diff --git a/.editorconfig b/.editorconfig index 47fde53b690b5b86037ede8cbf0337db8a472d7d..2b40ec32fac3e935b4f85e70bf339224d5e8f8b0 100644 --- a/.editorconfig +++ b/.editorconfig @@ -14,3 +14,9 @@ indent_style=space indent_size=2 tab_width=8 end_of_line=lf + +[*.sh] +indent_style=space +indent_size=2 +tab_width=8 +end_of_line=lf diff --git a/.github/ISSUE_TEMPLATE/release.md b/.github/ISSUE_TEMPLATE/release.md new file mode 100644 index 0000000000000000000000000000000000000000..6067dbf12fa70ab43a3065e59e7e68375b721049 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/release.md @@ -0,0 +1,9 @@ +--- +title: Release failure for {{ ref }} +--- + +Pipeline for release {{ ref }} failed. Please investigate. + +If the pipeline has failed before pushing to crates.io, delete the release tag +and fix the release as necessary, retagging after complete. If the pipeline has +failed after pushing to crates.io, create a new tag incrementing the version. diff --git a/.github/workflows/auto-label-issues.yml b/.github/workflows/auto-label-issues.yml new file mode 100644 index 0000000000000000000000000000000000000000..cd889b5941989a62e0784a73e974b25c166e6f4c --- /dev/null +++ b/.github/workflows/auto-label-issues.yml @@ -0,0 +1,17 @@ +# If the author of the issues is not a contributor to the project, label +# the issue with 'Z0-unconfirmed' + +name: Label New Issues +on: + issues: + types: [opened] + +jobs: + label-new-issues: + runs-on: ubuntu-latest + steps: + - name: Label drafts + uses: andymckay/labeler@master + if: github.event.issue.author_association == 'NONE' + with: + add-labels: 'Z0-unconfirmed' diff --git a/.github/workflows/auto-label-prs.yml b/.github/workflows/auto-label-prs.yml new file mode 100644 index 0000000000000000000000000000000000000000..f0b8e9b343e29ce7eb25bfb41a3f56277b4d7558 --- /dev/null +++ b/.github/workflows/auto-label-prs.yml @@ -0,0 +1,21 @@ +name: Label PRs +on: + pull_request: + types: [opened,ready_for_review] + +jobs: + label-new-prs: + runs-on: ubuntu-latest + steps: + - name: Label drafts + uses: andymckay/labeler@master + if: github.event.pull_request.draft == true + with: + add-labels: 'A3-inprogress' + remove-labels: 'A0-pleasereview' + - name: Label PRs + uses: andymckay/labeler@master + if: github.event.pull_request.draft == false && ! contains(github.event.pull_request.labels.*.name, 'A2-insubstantial') + with: + add-labels: 'A0-pleasereview' + remove-labels: 'A3-inprogress' diff --git a/.github/workflows/burnin-label-notification.yml b/.github/workflows/burnin-label-notification.yml new file mode 100644 index 0000000000000000000000000000000000000000..da422a659ee08600885c4241bbd39ddb5e62f25d --- /dev/null +++ b/.github/workflows/burnin-label-notification.yml @@ -0,0 +1,17 @@ +name: Notify devops when burn-in label applied +on: + pull_request: + types: [labeled] + +jobs: + notify-devops: + runs-on: ubuntu-latest + steps: + - name: Notify devops + if: github.event.label.name == 'A1-needsburnin' + uses: s3krit/matrix-message-action@v0.0.2 + with: + room_id: ${{ secrets.POLKADOT_DEVOPS_MATRIX_ROOM_ID }} + access_token: ${{ secrets.POLKADOT_DEVOPS_MATRIX_ACCESS_TOKEN }} + message: "@room Burn-in request received for [${{ github.event.pull_request.title }}](${{ github.event.pull_request.html_url }})" + server: "matrix.parity.io" diff --git a/.github/workflows/check-gitlab-pipeline.yml b/.github/workflows/check-gitlab-pipeline.yml new file mode 100644 index 0000000000000000000000000000000000000000..c87f17c2f732e447cacf297cfe41e7b266a4bc99 --- /dev/null +++ b/.github/workflows/check-gitlab-pipeline.yml @@ -0,0 +1,30 @@ +# A github action to track the status of the gitlab pipeline for tagged +# releases, and cancel the release/create a new issue if it fails + +name: Monitor gitlab pipeline status + +on: + push: + tags: + - v* + - ci-release-* + +jobs: + monitor: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Monitor pipeline + run: env; ./.maintain/github/check_gitlab_pipeline.sh + id: monitor_pipeline + env: + TAGGER: ${{ github.event.pusher.name }} + - name: Create Issue + if: failure() + uses: JasonEtco/create-an-issue@v2 + with: + filename: .github/ISSUE_TEMPLATE/release.md + assignees: ${{ github.event.pusher.name }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/polkadot-companion-labels.yml b/.github/workflows/polkadot-companion-labels.yml new file mode 100644 index 0000000000000000000000000000000000000000..27f743e1bd4529dc83ee7dfd5b96c6c5bb4ac3f8 --- /dev/null +++ b/.github/workflows/polkadot-companion-labels.yml @@ -0,0 +1,31 @@ +name: Check Polkadot Companion and Label + +on: + pull_request: + types: [opened, synchronize] + +jobs: + check_status: + runs-on: ubuntu-latest + steps: + - name: Monitor the status of the gitlab-check-companion-build job + uses: s3krit/await-status-action@v1.0.1 + id: 'check-companion-status' + with: + authToken: ${{ secrets.GITHUB_TOKEN }} + ref: ${{ github.event.pull_request.head.sha }} + contexts: 'continuous-integration/gitlab-check-polkadot-companion-build' + timeout: 1800 + notPresentTimeout: 3600 # It can take quite a while before the job starts... + failureStates: failure + interruptedStates: error # Error = job was probably cancelled. We don't want to label the PR in that case + - name: Label success + uses: andymckay/labeler@master + if: steps.check-companion-status.outputs.result == 'success' + with: + remove-labels: 'A7-needspolkadotpr' + - name: Label failure + uses: andymckay/labeler@master + if: steps.check-companion-status.outputs.result == 'failure' + with: + add-labels: 'A7-needspolkadotpr' diff --git a/.github/workflows/trigger-review-pipeline.yml b/.github/workflows/trigger-review-pipeline.yml new file mode 100644 index 0000000000000000000000000000000000000000..af54ec4358b438b7cd53513c33e661fef833aa94 --- /dev/null +++ b/.github/workflows/trigger-review-pipeline.yml @@ -0,0 +1,20 @@ +name: Trigger pipeline for review + +on: + pull_request: + types: [ready_for_review] + +jobs: + trigger: + runs-on: ubuntu-latest + + steps: + - name: Trigger pipeline + run: | + curl -X POST \ + -F token="$TOKEN" \ + -F ref="$REF" \ + https://gitlab.parity.io/api/v4/projects/145/trigger/pipeline + env: + REF: ${{ github.event.number }} + TOKEN: ${{ secrets.GITLAB_TRIGGER_TOKEN }} diff --git a/.gitignore b/.gitignore index 6398c09fe796278130978c2a8598ee9270399388..353d49df28f34b896567b0aa91bb08e056a5832c 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ rls*.log .local **/hfuzz_target/ **/hfuzz_workspace/ +.cargo/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1227153028e3e7a386794692e809c42d040d8e57..d3a7f36980063cb6719eee6494f909d360c42c5c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,7 +10,7 @@ # # my-example-job: # stage: test # One of the stages listed below this job (required) -# image: parity/tools:latest # Any docker image (required) +# image: paritytech/tools:latest # Any docker image (required) # allow_failure: true # Allow the pipeline to continue if this job fails (default: false) # dependencies: # - build-rust-doc-release # Any jobs that are required to run before this job (optional) @@ -22,6 +22,7 @@ # - ./.maintain/gitlab/my_amazing_script.sh stages: + - check - test - build - post-build-test @@ -29,19 +30,18 @@ stages: - kubernetes - flaming-fir -variables: +variables: &default-vars GIT_STRATEGY: fetch GIT_DEPTH: 100 - CARGO_HOME: "/ci-cache/${CI_PROJECT_NAME}/cargo/${CI_COMMIT_REF_NAME}/${CI_JOB_NAME}" - SCCACHE_DIR: "/ci-cache/${CI_PROJECT_NAME}/sccache" CARGO_INCREMENTAL: 0 - CI_SERVER_NAME: "GitLab CI" DOCKER_OS: "debian:stretch" ARCH: "x86_64" # FIXME set to release CARGO_UNLEASH_INSTALL_PARAMS: "--version 1.0.0-alpha.10" - CARGO_UNLEASH_PKG_DEF: "--skip node node-* pallet-template pallet-example pallet-example-* subkey chain-spec-builder sp-arithmetic-fuzzer" + CARGO_UNLEASH_PKG_DEF: "--skip node node-* pallet-template pallet-example pallet-example-* subkey chain-spec-builder" +default: + cache: {} .collect-artifacts: &collect-artifacts artifacts: @@ -56,31 +56,14 @@ variables: - kubernetes-parity-build environment: name: parity-build + interruptible: true .docker-env: &docker-env - image: parity/rust-builder:latest + image: paritytech/ci-linux:production before_script: - rustup show - cargo --version - sccache -s - # if there is no directory for this $CI_COMMIT_REF_NAME/$CI_JOB_NAME - # create such directory and - # copy recursively all the files from the newest dir which has $CI_JOB_NAME, if it exists - - | - if [[ ! -d $CARGO_HOME ]]; then - mkdir -p /ci-cache/${CI_PROJECT_NAME}/cargo/${CI_COMMIT_REF_NAME}; - FRESH_CACHE=$(find /ci-cache/${CI_PROJECT_NAME}/cargo -mindepth 2 -maxdepth 2 \ - -type d -name ${CI_JOB_NAME} -exec stat --printf="%Y\t%n\n" {} \; |sort -n -r |head -1 |cut -f2); - if [[ -d $FRESH_CACHE ]]; then - echo "____Using" "$FRESH_CACHE" "to prepopulate the cache____"; - cp -r "${FRESH_CACHE}" "${CARGO_HOME}"; - touch ${CARGO_HOME}/config; - else - echo "_____No such cargo dir, proceeding from scratch_____"; - fi - else - echo "____No need to prepopulate the cache____"; - fi only: - master - /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1 @@ -93,10 +76,9 @@ variables: - runner_system_failure - unknown_failure - api_failure - dependencies: [] interruptible: true tags: - - ci2 + - linux-docker .build-only: &build-only only: @@ -105,57 +87,64 @@ variables: - /^pre-v[0-9]+\.[0-9]+-[0-9a-f]+$/ - web +#### stage: .pre +skip-if-draft: + image: paritytech/tools:latest + <<: *kubernetes-build + stage: .pre + only: + - /^[0-9]+$/ # Pull requests + script: + - ./.maintain/gitlab/skip_if_draft.sh -#### stage: test +#### stage: check check-runtime: - stage: test - image: parity/tools:latest + stage: check + image: paritytech/tools:latest <<: *kubernetes-build only: - /^[0-9]+$/ variables: + <<: *default-vars GITLAB_API: "https://gitlab.parity.io/api/v4" GITHUB_API_PROJECT: "parity%2Finfrastructure%2Fgithub-api" script: - ./.maintain/gitlab/check_runtime.sh - interruptible: true allow_failure: true check-signed-tag: - stage: test - image: parity/tools:latest + stage: check + image: paritytech/tools:latest <<: *kubernetes-build only: - - tags + - /^ci-release-.*$/ - /^v[0-9]+\.[0-9]+\.[0-9]+.*$/ script: - ./.maintain/gitlab/check_signed.sh - allow_failure: false check-line-width: - stage: test - image: parity/tools:latest + stage: check + image: paritytech/tools:latest <<: *kubernetes-build only: - /^[0-9]+$/ script: - ./.maintain/gitlab/check_line_width.sh - interruptible: true allow_failure: true - - - -check-polkadot-companion-build: - stage: build - <<: *docker-env +test-dependency-rules: + stage: check + image: paritytech/tools:latest + <<: *kubernetes-build + except: + variables: + - $DEPLOY_TAG script: - - ./.maintain/gitlab/check_polkadot_companion_build.sh - interruptible: true - allow_failure: true + - .maintain/ensure-deps.sh +#### stage: test cargo-audit: stage: test @@ -169,6 +158,10 @@ cargo-audit: cargo-deny: stage: test <<: *docker-env + only: + - schedules + - tags + - web script: - cargo deny check --hide-inclusion-graph -c .maintain/deny.toml after_script: @@ -186,9 +179,10 @@ cargo-check-benches: <<: *docker-env script: - BUILD_DUMMY_WASM_BINARY=1 time cargo +nightly check --benches --all + - cargo run --release -p node-bench -- ::node::import::native::sr25519::transfer_keep_alive::paritydb::small + - cargo run --release -p node-bench -- ::trie::read::small - sccache -s - cargo-check-subkey: stage: test <<: *docker-env @@ -199,38 +193,21 @@ cargo-check-subkey: - BUILD_DUMMY_WASM_BINARY=1 time cargo check --release - sccache -s - test-linux-stable: &test-linux stage: test <<: *docker-env variables: + <<: *default-vars # Enable debug assertions since we are running optimized builds for testing # but still want to have debug assertions. - RUSTFLAGS: -Cdebug-assertions=y + RUSTFLAGS: "-Cdebug-assertions=y -Dwarnings" + RUST_BACKTRACE: 1 except: variables: - $DEPLOY_TAG script: - - WASM_BUILD_NO_COLOR=1 time cargo test --all --release --verbose --locked |& - tee output.log + - WASM_BUILD_NO_COLOR=1 time cargo test --all --release --verbose --locked - sccache -s - after_script: - - echo "___Collecting warnings for check_warnings job___" - - awk '/^warning:/,/^$/ { print }' output.log > ${CI_COMMIT_SHORT_SHA}_warnings.log - artifacts: - name: $CI_COMMIT_SHORT_SHA - expire_in: 3 days - paths: - - ${CI_COMMIT_SHORT_SHA}_warnings.log - -test-dependency-rules: - stage: test - <<: *docker-env - except: - variables: - - $DEPLOY_TAG - script: - - .maintain/ensure-deps.sh unleash-check: stage: test @@ -243,9 +220,11 @@ unleash-check: - cargo unleash check ${CARGO_UNLEASH_PKG_DEF} test-frame-staking: + # into one job stage: test <<: *docker-env variables: + <<: *default-vars # Enable debug assertions since we are running optimized builds for testing # but still want to have debug assertions. RUSTFLAGS: -Cdebug-assertions=y @@ -255,13 +234,15 @@ test-frame-staking: - $DEPLOY_TAG script: - cd frame/staking/ - - WASM_BUILD_NO_COLOR=1 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-frame-examples-compile-to-wasm: + # into one job stage: test <<: *docker-env variables: + <<: *default-vars # Enable debug assertions since we are running optimized builds for testing # but still want to have debug assertions. RUSTFLAGS: -Cdebug-assertions=y @@ -280,8 +261,9 @@ test-wasmtime: stage: test <<: *docker-env variables: + <<: *default-vars # Enable debug assertions since we are running optimized builds for testing - # but still want to have debug assertions. + # but still want to have debug assertions. RUSTFLAGS: -Cdebug-assertions=y RUST_BACKTRACE: 1 except: @@ -293,9 +275,11 @@ test-wasmtime: - sccache -s test-runtime-benchmarks: + # into one job stage: test <<: *docker-env variables: + <<: *default-vars # Enable debug assertions since we are running optimized builds for testing # but still want to have debug assertions. RUSTFLAGS: -Cdebug-assertions=y @@ -305,7 +289,7 @@ test-runtime-benchmarks: - $DEPLOY_TAG script: - cd bin/node/cli - - BUILD_DUMMY_WASM_BINARY=1 time cargo check --verbose --features runtime-benchmarks + - WASM_BUILD_NO_COLOR=1 time cargo test --workspace --release --verbose --features runtime-benchmarks - sccache -s test-linux-stable-int: @@ -318,7 +302,8 @@ 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.___" - - 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 + - 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 &> ${CI_COMMIT_SHORT_SHA}_int_failure.log - sccache -s @@ -331,7 +316,6 @@ test-linux-stable-int: paths: - ${CI_COMMIT_SHORT_SHA}_int_failure.log - check-web-wasm: stage: test <<: *docker-env @@ -343,19 +327,19 @@ check-web-wasm: - time cargo build --target=wasm32-unknown-unknown -p sp-io - time cargo build --target=wasm32-unknown-unknown -p sp-runtime - time cargo build --target=wasm32-unknown-unknown -p sp-std - - time cargo build --target=wasm32-unknown-unknown -p sc-client - time cargo build --target=wasm32-unknown-unknown -p sc-consensus-aura - time cargo build --target=wasm32-unknown-unknown -p sc-consensus-babe - time cargo build --target=wasm32-unknown-unknown -p sp-consensus - time cargo build --target=wasm32-unknown-unknown -p sc-telemetry # 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 +nightly build --manifest-path=bin/node/cli/Cargo.toml --no-default-features --features "browser" --target=wasm32-unknown-unknown -Z features=itarget + - time cargo +nightly build --manifest-path=bin/node/cli/Cargo.toml --no-default-features --features browser --target=wasm32-unknown-unknown -Z features=itarget - sccache -s test-full-crypto-feature: stage: test <<: *docker-env variables: + <<: *default-vars # Enable debug assertions since we are running optimized builds for testing # but still want to have debug assertions. RUSTFLAGS: -Cdebug-assertions=y @@ -370,14 +354,67 @@ test-full-crypto-feature: - time cargo +nightly build --verbose --no-default-features --features full_crypto - sccache -s +cargo-check-macos: + stage: test + # shell runner on mac ignores the image set in *docker-env + <<: *docker-env + script: + - BUILD_DUMMY_WASM_BINARY=1 time cargo check --release + - sccache -s + tags: + - osx + +test-prometheus-alerting-rules: + stage: test + image: paritytech/tools:latest + <<: *kubernetes-build + script: + - promtool check rules .maintain/monitoring/alerting-rules/alerting-rules.yaml + - cat .maintain/monitoring/alerting-rules/alerting-rules.yaml | promtool test rules .maintain/monitoring/alerting-rules/alerting-rule-tests.yaml #### stage: build +check-polkadot-companion-status: + stage: build + image: paritytech/tools:latest + <<: *kubernetes-build + only: + - /^[0-9]+$/ # PRs + script: + - ./.maintain/gitlab/check_polkadot_companion_status.sh + +check-polkadot-companion-build: + stage: build + <<: *docker-env + needs: + - job: test-linux-stable-int + artifacts: false + script: + - ./.maintain/gitlab/check_polkadot_companion_build.sh + allow_failure: true + +test-browser-node: + stage: build + <<: *docker-env + needs: + - job: check-web-wasm + artifacts: false + variables: + <<: *default-vars + CHROMEDRIVER_ARGS: "--log-level=INFO --whitelisted-ips=127.0.0.1" + CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER: "wasm-bindgen-test-runner" + WASM_BINDGEN_TEST_TIMEOUT: 120 + script: + - cargo +nightly test --target wasm32-unknown-unknown -p node-browser-testing -Z features=itarget + build-linux-substrate: &build-binary stage: build <<: *collect-artifacts <<: *docker-env <<: *build-only + needs: + - job: test-linux-stable + artifacts: false before_script: - mkdir -p ./artifacts/substrate/ except: @@ -391,8 +428,8 @@ build-linux-substrate: &build-binary echo "${CI_COMMIT_TAG}" | tee ./artifacts/substrate/VERSION; else ./artifacts/substrate/substrate --version | - sed -n -r 's/^substrate ([0-9.]+.*-[0-9a-f]{7,13})-.*$/\1/p' | - tee ./artifacts/substrate/VERSION; + sed -n -E 's/^substrate ([0-9.]+.*-[0-9a-f]{7,13})-.*$/\1/p' | + tee ./artifacts/substrate/VERSION; fi - sha256sum ./artifacts/substrate/substrate | tee ./artifacts/substrate/substrate.sha256 - printf '\n# building node-template\n\n' @@ -400,8 +437,12 @@ build-linux-substrate: &build-binary - cp -r .maintain/docker/substrate.Dockerfile ./artifacts/substrate/ - sccache -s -build-linux-subkey: + +build-linux-subkey: &build-subkey <<: *build-binary + needs: + - job: cargo-check-subkey + artifacts: false before_script: - mkdir -p ./artifacts/subkey script: @@ -411,12 +452,20 @@ build-linux-subkey: - mv ./target/release/subkey ./artifacts/subkey/. - echo -n "Subkey version = " - ./artifacts/subkey/subkey --version | - sed -n -r 's/^subkey ([0-9.]+.*)/\1/p' | + sed -n -E 's/^subkey ([0-9.]+.*)/\1/p' | tee ./artifacts/subkey/VERSION; - sha256sum ./artifacts/subkey/subkey | tee ./artifacts/subkey/subkey.sha256 - cp -r .maintain/docker/subkey.Dockerfile ./artifacts/subkey/ - sccache -s +build-macos-subkey: + <<: *build-subkey + only: + - master + - /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1 + tags: + - osx + build-rust-doc-release: stage: build <<: *docker-env @@ -430,44 +479,16 @@ 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 RUSTDOCFLAGS="--html-in-header $(pwd)/.maintain/rustdoc-header.html" time cargo +nightly doc --release --all --verbose + - BUILD_DUMMY_WASM_BINARY=1 RUSTDOCFLAGS="--html-in-header $(pwd)/.maintain/rustdoc-header.html" + time cargo +nightly doc --release --all --verbose - cp -R ./target/doc ./crate-docs - echo "" > ./crate-docs/index.html - sccache -s -check_warnings: - stage: build - <<: *docker-env - except: - variables: - - $DEPLOY_TAG - variables: - GIT_STRATEGY: none - needs: - - job: test-linux-stable - artifacts: true - script: - - if [ -s ${CI_COMMIT_SHORT_SHA}_warnings.log ]; then - cat ${CI_COMMIT_SHORT_SHA}_warnings.log; - exit 1; - else - echo "___No warnings___"; - fi - - -check-polkadot-companion-status: - stage: post-build-test - image: parity/tools:latest - <<: *kubernetes-build - only: - - /^[0-9]+$/ - script: - - ./.maintain/gitlab/check_polkadot_companion_status.sh - - +#### stage: post-build-test trigger-contracts-ci: - stage: publish + stage: post-build-test needs: - job: build-linux-substrate artifacts: false @@ -483,12 +504,19 @@ trigger-contracts-ci: #### stage: publish -.publish-docker-release: &publish-docker-release +.build-push-docker-image: &build-push-docker-image <<: *build-only <<: *kubernetes-build image: docker:stable services: - docker:dind + variables: &docker-build-vars + <<: *default-vars + DOCKER_HOST: tcp://localhost:2375 + DOCKER_DRIVER: overlay2 + GIT_STRATEGY: none + DOCKERFILE: $PRODUCT.Dockerfile + CONTAINER_IMAGE: parity/$PRODUCT before_script: - test "$Docker_Hub_User_Parity" -a "$Docker_Hub_Pass_Parity" || ( echo "no docker credentials provided"; exit 1 ) @@ -510,18 +538,15 @@ trigger-contracts-ci: publish-docker-substrate: stage: publish - <<: *publish-docker-release + <<: *build-push-docker-image # collect VERSION artifact here to pass it on to kubernetes <<: *collect-artifacts - dependencies: - - build-linux-substrate + needs: + - job: build-linux-substrate + artifacts: true variables: - DOCKER_HOST: tcp://localhost:2375 - DOCKER_DRIVER: overlay2 - GIT_STRATEGY: none + <<: *docker-build-vars PRODUCT: substrate - DOCKERFILE: $PRODUCT.Dockerfile - CONTAINER_IMAGE: parity/$PRODUCT after_script: - docker logout # only VERSION information is needed for the deployment @@ -529,16 +554,13 @@ publish-docker-substrate: publish-docker-subkey: stage: publish - <<: *publish-docker-release - dependencies: - - build-linux-subkey + <<: *build-push-docker-image + needs: + - job: build-linux-subkey + artifacts: true variables: - DOCKER_HOST: tcp://localhost:2375 - DOCKER_DRIVER: overlay2 - GIT_STRATEGY: none + <<: *docker-build-vars PRODUCT: subkey - DOCKERFILE: $PRODUCT.Dockerfile - CONTAINER_IMAGE: parity/$PRODUCT after_script: - docker logout @@ -546,10 +568,12 @@ publish-s3-release: stage: publish <<: *build-only <<: *kubernetes-build - dependencies: - - build-linux-substrate - - build-linux-subkey - image: parity/awscli:latest + needs: + - job: build-linux-substrate + artifacts: true + - job: build-linux-subkey + artifacts: true + image: paritytech/awscli:latest variables: GIT_STRATEGY: none BUCKET: "releases.parity.io" @@ -565,11 +589,11 @@ publish-s3-release: publish-s3-doc: stage: publish - image: parity/awscli:latest + image: paritytech/awscli:latest allow_failure: true - dependencies: - - build-rust-doc-release - cache: {} + needs: + - job: build-rust-doc-release + artifacts: true <<: *build-only <<: *kubernetes-build variables: @@ -587,74 +611,32 @@ publish-s3-doc: - aws s3 ls s3://${BUCKET}/${PREFIX}/ --human-readable --summarize - -publish-gh-doc: - stage: publish - image: parity/tools:latest - allow_failure: true - dependencies: - - build-rust-doc-release - cache: {} - <<: *build-only - <<: *kubernetes-build - variables: - GIT_STRATEGY: none - GITHUB_API: "https://api.github.com" - script: - - test -r ./crate-docs/index.html || ( - echo "./crate-docs/index.html not present, build:rust:doc:release job not complete"; - exit 1 - ) - - test "${GITHUB_USER}" -a "${GITHUB_EMAIL}" -a "${GITHUB_TOKEN}" || ( - echo "environment variables for github insufficient"; - exit 1 - ) - - | - cat > ${HOME}/.gitconfig <&1 | sed -r "s|(${GITHUB_USER}):[a-f0-9]+@|\1:REDACTED@|g" - after_script: - - rm -vrf ${HOME}/.gitconfig - publish-draft-release: stage: publish - image: parity/tools:latest + image: paritytech/tools:latest only: - - tags + - /^ci-release-.*$/ - /^v[0-9]+\.[0-9]+\.[0-9]+.*$/ script: - ./.maintain/gitlab/publish_draft_release.sh - interruptible: true allow_failure: true publish-to-crates-io: stage: publish <<: *docker-env only: - - tags - /^ci-release-.*$/ + - /^v[0-9]+\.[0-9]+\.[0-9]+.*$/ script: - cargo install cargo-unleash ${CARGO_UNLEASH_INSTALL_PARAMS} - cargo unleash em-dragons --no-check ${CARGO_UNLEASH_PKG_DEF} - interruptible: true allow_failure: true .deploy-template: &deploy stage: kubernetes when: manual retry: 1 - image: parity/kubetools:latest + image: paritytech/kubetools:latest <<: *build-only tags: # this is the runner that is used to deploy it @@ -668,18 +650,18 @@ publish-to-crates-io: - echo "Substrate version = ${DEPLOY_TAG}" # or use helm to render the template - helm template - --values ./.maintain/kubernetes/values.yaml - --set image.tag=${DEPLOY_TAG} - --set validator.keys=${VALIDATOR_KEYS} - ./.maintain/kubernetes | kubectl apply -f - --dry-run=false + --values ./.maintain/kubernetes/values.yaml + --set image.tag=${DEPLOY_TAG} + --set validator.keys=${VALIDATOR_KEYS} + ./.maintain/kubernetes | kubectl apply -f - --dry-run=false - echo "# substrate namespace ${KUBE_NAMESPACE}" - kubectl -n ${KUBE_NAMESPACE} get all - echo "# substrate's nodes' external ip addresses:" - kubectl get nodes -l node=substrate - -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{range @.status.addresses[?(@.type=="ExternalIP")]}{.address}{"\n"}{end}' + -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{range @.status.addresses[?(@.type=="ExternalIP")]}{.address}{"\n"}{end}' - echo "# substrate' nodes" - kubectl -n ${KUBE_NAMESPACE} get pods - -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.nodeName}{"\n"}{end}' + -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.nodeName}{"\n"}{end}' - echo "# wait for the rollout to complete" - kubectl -n ${KUBE_NAMESPACE} rollout status statefulset/substrate @@ -687,8 +669,9 @@ publish-to-crates-io: .deploy-cibuild: &deploy-cibuild <<: *deploy - dependencies: - - publish-docker-substrate + needs: + - job: publish-docker-substrate + artifacts: false .deploy-tag: &deploy-tag <<: *deploy @@ -719,14 +702,16 @@ 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 + needs: + # script will fail if there is no artifacts/substrate/VERSION + - job: publish-docker-substrate + artifacts: true image: parity/azure-ansible:v1 allow_failure: true when: manual + interruptible: true tags: - linux-docker @@ -734,15 +719,29 @@ validator 1 4: <<: *validator-deploy script: - ./.maintain/flamingfir-deploy.sh flamingfir-validator1 + validator 2 4: <<: *validator-deploy script: - ./.maintain/flamingfir-deploy.sh flamingfir-validator2 + validator 3 4: <<: *validator-deploy script: - ./.maintain/flamingfir-deploy.sh flamingfir-validator3 + validator 4 4: <<: *validator-deploy script: - ./.maintain/flamingfir-deploy.sh flamingfir-validator4 + +#### stage: .post + +check-labels: + stage: .post + image: paritytech/tools:latest + <<: *kubernetes-build + only: + - /^[0-9]+$/ + script: + - ./.maintain/gitlab/check_labels.sh diff --git a/.maintain/flamingfir-deploy.sh b/.maintain/flamingfir-deploy.sh index 596bb04ece091cd03f3c993d655f5d45770362ea..8f0fb3a2bc016067d0bf11ae993a3bfa1636280f 100755 --- a/.maintain/flamingfir-deploy.sh +++ b/.maintain/flamingfir-deploy.sh @@ -5,7 +5,7 @@ RETRY_ATTEMPT=0 SLEEP_TIME=15 TARGET_HOST="$1" COMMIT=$(cat artifacts/substrate/VERSION) -DOWNLOAD_URL="https://releases.parity.io/substrate/x86_64-debian:stretch/${COMMIT}/substrate" +DOWNLOAD_URL="https://releases.parity.io/substrate/x86_64-debian:stretch/${COMMIT}/substrate/substrate" POST_DATA='{"extra_vars":{"artifact_path":"'${DOWNLOAD_URL}'","target_host":"'${TARGET_HOST}'"}}' JOB_ID=$(wget -O - --header "Authorization: Bearer ${AWX_TOKEN}" --header "Content-type: application/json" --post-data "${POST_DATA}" https://ansible-awx.parity.io/api/v2/job_templates/32/launch/ | jq .job) diff --git a/.maintain/github/check_gitlab_pipeline.sh b/.maintain/github/check_gitlab_pipeline.sh new file mode 100755 index 0000000000000000000000000000000000000000..4e02dfdb2a428cda4a4a6dc224d69b383693e4ce --- /dev/null +++ b/.maintain/github/check_gitlab_pipeline.sh @@ -0,0 +1,37 @@ +#!/bin/bash +SUBSTRATE_API_BASEURL="https://gitlab.parity.io/api/v4/projects/145" + +TAG_NAME=$(echo "$GITHUB_REF" | sed -E 's_refs/tags/(.*)_\1_') +PIPELINE_ID=$(curl -s $SUBSTRATE_API_BASEURL/pipelines | jq -r "map(select(.ref==\"$TAG_NAME\")) | .[0] | .id") +if [ "$PIPELINE_ID" == "null" ]; then + echo "[!] Pipeline for $TAG_NAME not found. Exiting." + exit 1 +fi + +echo "[+] Pipeline path: https://gitlab.parity.io/parity/substrate/pipelines/$PIPELINE_ID" + +# 130 minute job max +for (( c=0; c < 180; c++ )); do + out=$(curl -s "$SUBSTRATE_API_BASEURL/pipelines/$PIPELINE_ID" | jq -r .status) + case $out in + "success") + echo "[+] Pipeline $PIPELINE_ID for $TAG_NAME succeeded!" + exit 0 + ;; + "failed") + echo "[!] Pipeline $PIPELINE_ID for $TAG_NAME failed. Cannot proceed. Check job output on gitlab!" + exit 1 + ;; + "cancelled") + echo "[!] Pipeline $PIPELINE_ID for $TAG_NAME was cancelled. Cannot proceed!" + exit 1 + ;; + "running") + echo "[-] Pipeline $PIPELINE_ID for $TAG_NAME still in progress..." + esac + sleep 60 +done +# If we reach here, we timed out after 30 minutes +echo "[!] Pipeline $PIPELINE_ID for $TAG_NAME timed out! Cannot proceed" +echo "::set-output name=pipeline_status::timedout" +exit 1 diff --git a/.maintain/gitlab/check_labels.sh b/.maintain/gitlab/check_labels.sh new file mode 100755 index 0000000000000000000000000000000000000000..5ab099b38291cc66b6f370430b8f06e6b2f5c24f --- /dev/null +++ b/.maintain/gitlab/check_labels.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +#shellcheck source=lib.sh +source "$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )/lib.sh" + +ensure_labels() { + for label in "$@"; do + if has_label 'paritytech/substrate' "$CI_COMMIT_BRANCH" "$label"; then + return 0 + fi + done + return 1 +} + +# Must have one of the following labels +releasenotes_labels=( + 'B0-silent' + 'B3-apinoteworthy' + 'B5-clientnoteworthy' + 'B7-runtimenoteworthy' +) + +criticality_labels=( + 'C1-low' + 'C3-medium' + 'C7-high' + 'C9-critical' +) + +echo "[+] Checking release notes (B) labels for $CI_COMMIT_BRANCH" +if ensure_labels "${releasenotes_labels[@]}"; then + echo "[+] Release notes label detected. All is well." +else + echo "[!] Release notes label not detected. Please add one of: ${releasenotes_labels[*]}" + exit 1 +fi + +echo "[+] Checking release criticality (C) labels for $CI_COMMIT_BRANCH" +if ensure_labels "${criticality_labels[@]}"; then + echo "[+] Release criticality label detected. All is well." +else + echo "[!] Release criticality label not detected. Please add one of: ${criticality_labels[*]}" + exit 1 +fi + +exit 0 diff --git a/.maintain/gitlab/check_line_width.sh b/.maintain/gitlab/check_line_width.sh index f382d630b183c6396115cc1e76e77dfab4c20047..611d3ae2681e2ef145753a0f774c5183fc9df7d9 100755 --- a/.maintain/gitlab/check_line_width.sh +++ b/.maintain/gitlab/check_line_width.sh @@ -2,47 +2,50 @@ # # check if line width of rust source files is not beyond x characters # +set -e +set -o pipefail +BASE_ORIGIN="origin" +BASE_BRANCH_NAME="master" +LINE_WIDTH="120" +GOOD_LINE_WIDTH="100" +BASE_BRANCH="${BASE_ORIGIN}/${BASE_BRANCH_NAME}" +git fetch ${BASE_ORIGIN} ${BASE_BRANCH_NAME} --depth 100 +BASE_HASH=$(git merge-base ${BASE_BRANCH} HEAD) -BASE_BRANCH="origin/master" -LINE_WIDTH="121" -GOOD_LINE_WIDTH="101" - - -git diff --name-only ${BASE_BRANCH}...${CI_COMMIT_SHA} \*.rs | ( while read file +git diff --name-only ${BASE_HASH} -- \*.rs | ( while read file do if [ ! -f ${file} ]; then echo "Skipping removed file." - elif git diff ${BASE_BRANCH}...${CI_COMMIT_SHA} ${file} | grep -q "^+.\{${LINE_WIDTH}\}" + elif git diff ${BASE_HASH} -- ${file} | grep -q "^+.\{$(( $LINE_WIDTH + 1 ))\}" then if [ -z "${FAIL}" ] then - echo "| warning!" - echo "| Lines should not be longer than 120 characters." + echo "| error!" + echo "| Lines must not be longer than ${LINE_WIDTH} characters." echo "| " echo "| see more https://wiki.parity.io/Substrate-Style-Guide" echo "|" FAIL="true" fi echo "| file: ${file}" - git diff ${BASE_BRANCH}...${CI_COMMIT_SHA} ${file} \ - | grep -n "^+.\{${LINE_WIDTH}\}" + git diff ${BASE_HASH} -- ${file} \ + | grep -n "^+.\{$(( $LINE_WIDTH + 1))\}" echo "|" else - if git diff ${BASE_BRANCH}...${CI_COMMIT_SHA} ${file} | grep -q "^+.\{${GOOD_LINE_WIDTH}\}" + if git diff ${BASE_HASH} -- ${file} | grep -q "^+.\{$(( $GOOD_LINE_WIDTH + 1 ))\}" then if [ -z "${FAIL}" ] then echo "| warning!" - echo "| Lines should be longer than 100 characters only in exceptional circumstances!" + echo "| Lines should be longer than ${GOOD_LINE_WIDTH} characters only in exceptional circumstances!" echo "| " echo "| see more https://wiki.parity.io/Substrate-Style-Guide" echo "|" fi echo "| file: ${file}" - git diff ${BASE_BRANCH}...${CI_COMMIT_SHA} ${file} \ - | grep -n "^+.\{${LINE_WIDTH}\}" + git diff ${BASE_HASH} -- ${file} | grep -n "^+.\{$(( $GOOD_LINE_WIDTH + 1 ))\}" echo "|" fi fi diff --git a/.maintain/gitlab/check_polkadot_companion_build.sh b/.maintain/gitlab/check_polkadot_companion_build.sh index eb4c6440f46c9fcafbd6a9ea9d78102518a4e619..7a1943e0bd4b0531d8bc8670669e89feadb76f4f 100755 --- a/.maintain/gitlab/check_polkadot_companion_build.sh +++ b/.maintain/gitlab/check_polkadot_companion_build.sh @@ -12,7 +12,7 @@ github_api_substrate_pull_url="https://api.github.com/repos/paritytech/substrate/pulls" # use github api v3 in order to access the data without authentication -github_header="Accept: application/vnd.github.v3+json" +github_header="Authorization: token ${GITHUB_PR_TOKEN}" boldprint () { printf "|\n| \033[1m${@}\033[0m\n|\n" ; } boldcat () { printf "|\n"; while read l; do printf "| \033[1m${l}\033[0m\n"; done; printf "|\n" ; } @@ -39,15 +39,24 @@ substrate's branch. if it can't find anything, it will uses master instead EOT +# Set the user name and email to make merging work +git config --global user.name 'CI system' +git config --global user.email '<>' SUBSTRATE_PATH=$(pwd) +# Merge master into our branch before building Polkadot to make sure we don't miss +# any commits that are required by Polkadot. +git merge origin/master + # Clone the current Polkadot master branch into ./polkadot. -git clone --depth 1 https://github.com/paritytech/polkadot.git +# NOTE: we need to pull enough commits to be able to find a common +# ancestor for successfully performing merges below. +git clone --depth 20 https://github.com/paritytech/polkadot.git cd polkadot -# either it's a pull request then check for a companion otherwise use +# either it's a pull request then check for a companion otherwise use # polkadot:master if expr match "${CI_COMMIT_REF_NAME}" '^[0-9]\+$' >/dev/null then @@ -76,17 +85,11 @@ then if [ "${pr_companion}" ] then boldprint "companion pr specified/detected: #${pr_companion}" - git fetch --depth 1 origin refs/pull/${pr_companion}/head:pr/${pr_companion} + git fetch origin refs/pull/${pr_companion}/head:pr/${pr_companion} git checkout pr/${pr_companion} + git merge origin/master else - pr_ref="$(grep -Po '"ref"\s*:\s*"\K(?!master)[^"]*' "${pr_data_file}")" - if git fetch --depth 1 origin "$pr_ref":branch/"$pr_ref" 2>/dev/null - then - boldprint "companion branch detected: $pr_ref" - git checkout branch/"$pr_ref" - else - boldprint "no companion branch found - building polkadot:master" - fi + boldprint "no companion branch found - building polkadot:master" fi rm -f "${pr_data_file}" else @@ -102,9 +105,5 @@ echo "paths = [ \"$SUBSTRATE_PATH\" ]" > .cargo/config mkdir -p target/debug/wbuild/.cargo cp .cargo/config target/debug/wbuild/.cargo/config -# package, others are updated along the way. -cargo update - # Test Polkadot pr or master branch with this Substrate commit. time cargo test --all --release --verbose - diff --git a/.maintain/gitlab/check_polkadot_companion_status.sh b/.maintain/gitlab/check_polkadot_companion_status.sh index b54f457dc56830ef1ad2892809025ff13cf4f38f..b781831055b6d500d133425fe7c0860a807938cb 100755 --- a/.maintain/gitlab/check_polkadot_companion_status.sh +++ b/.maintain/gitlab/check_polkadot_companion_status.sh @@ -7,7 +7,7 @@ github_api_substrate_pull_url="https://api.github.com/repos/paritytech/substrate/pulls" github_api_polkadot_pull_url="https://api.github.com/repos/paritytech/polkadot/pulls" # use github api v3 in order to access the data without authentication -github_header="Accept: application/vnd.github.v3+json" +github_header="Authorization: token ${GITHUB_PR_TOKEN}" boldprint () { printf "|\n| \033[1m${@}\033[0m\n|\n" ; } boldcat () { printf "|\n"; while read l; do printf "| \033[1m${l}\033[0m\n"; done; printf "|\n" ; } @@ -87,7 +87,8 @@ fi curl -H "${github_header}" -sS -o companion_pr_reviews.json \ ${github_api_polkadot_pull_url}/${pr_companion}/reviews -if [ "$(jq -r -e '.[].state' < companion_pr_reviews.json | uniq)" != "APPROVED" ] +if [ -n "$(jq -r -e '.[].state | select(. == "CHANGES_REQUESTED")' < companion_pr_reviews.json)" ] && \ + [ -z "$(jq -r -e '.[].state | select(. == "APPROVED")' < companion_pr_reviews.json)" ] then boldprint "polkadot pr #${pr_companion} not APPROVED" exit 1 diff --git a/.maintain/gitlab/check_runtime.sh b/.maintain/gitlab/check_runtime.sh index 5b7e25e3afc4eabef01d984047a98d675ab09757..6d009c5aafc6a8907fb9d8e598e8870854af8db7 100755 --- a/.maintain/gitlab/check_runtime.sh +++ b/.maintain/gitlab/check_runtime.sh @@ -67,7 +67,7 @@ sub_spec_version="$(git diff tags/release...${CI_COMMIT_SHA} ${VERSIONS_FILE} \ if [ "${add_spec_version}" != "${sub_spec_version}" ] then - github_label "B2-breaksapi" + github_label "D2-breaksapi" boldcat <<-EOT diff --git a/.maintain/gitlab/generate_changelog.sh b/.maintain/gitlab/generate_changelog.sh index ba2a507e4cac694f918aa2c88cf1585991faa373..b872d324438d64bd2b64cdf9745bf76a983675ed 100755 --- a/.maintain/gitlab/generate_changelog.sh +++ b/.maintain/gitlab/generate_changelog.sh @@ -19,18 +19,17 @@ while IFS= read -r line; do if has_label 'paritytech/substrate' "$pr_id" 'B0-silent'; then continue fi - if has_label 'paritytech/substrate' "$pr_id" 'B1-runtimenoteworthy'; then - runtime_changes="$runtime_changes + if has_label 'paritytech/substrate' "$pr_id" 'B3-apinoteworthy' ; then + api_changes="$api_changes $line" fi - if has_label 'paritytech/substrate' "$pr_id" 'B1-clientnoteworthy'; then + if has_label 'paritytech/substrate' "$pr_id" 'B5-clientnoteworthy'; then client_changes="$client_changes $line" fi - if has_label 'paritytech/substrate' "$pr_id" 'B1-apinoteworthy' ; then - api_changes="$api_changes + if has_label 'paritytech/substrate' "$pr_id" 'B7-runtimenoteworthy'; then + runtime_changes="$runtime_changes $line" - continue fi done <<< "$all_changes" diff --git a/.maintain/gitlab/lib.sh b/.maintain/gitlab/lib.sh index ecc9a5f54288cd4636a05cb7f2a2d0535e40ebe9..33477b52f5891a6855f15aec62cd3c41454dc85c 100755 --- a/.maintain/gitlab/lib.sh +++ b/.maintain/gitlab/lib.sh @@ -5,7 +5,7 @@ api_base="https://api.github.com/repos" # Function to take 2 git tags/commits and get any lines from commit messages # that contain something that looks like a PR reference: e.g., (#1234) sanitised_git_logs(){ - git --no-pager log --pretty=format:"%s" "$1..$2" | + git --no-pager log --pretty=format:"%s" "$1...$2" | # Only find messages referencing a PR grep -E '\(#[0-9]+\)' | # Strip any asterisks @@ -66,8 +66,12 @@ has_label(){ repo="$1" pr_id="$2" label="$3" - out=$(curl -H "Authorization: token $GITHUB_RELEASE_TOKEN" -s "$api_base/$repo/pulls/$pr_id") - [ -n "$(echo "$out" | jq ".labels | .[] | select(.name==\"$label\")")" ] + if [ -n "$GITHUB_RELEASE_TOKEN" ]; then + out=$(curl -H "Authorization: token $GITHUB_RELEASE_TOKEN" -s "$api_base/$repo/pulls/$pr_id") + else + out=$(curl -H "Authorization: token $GITHUB_PR_TOKEN" -s "$api_base/$repo/pulls/$pr_id") + fi + [ -n "$(echo "$out" | tr -d '\r\n' | jq ".labels | .[] | select(.name==\"$label\")")" ] } # Formats a message into a JSON string for posting to Matrix diff --git a/.maintain/gitlab/skip_if_draft.sh b/.maintain/gitlab/skip_if_draft.sh new file mode 100755 index 0000000000000000000000000000000000000000..cf6ea6a5b31155da9d6ac0c09079f4dffcec2dfa --- /dev/null +++ b/.maintain/gitlab/skip_if_draft.sh @@ -0,0 +1,14 @@ +#!/bin/sh +url="https://api.github.com/repos/paritytech/substrate/pulls/${CI_COMMIT_REF_NAME}" +echo "[+] API URL: $url" + +draft_state=$(curl -H "Authorization: token ${GITHUB_PR_TOKEN}" "$url" | jq -r .draft) +echo "[+] Draft state: $draft_state" + +if [ "$draft_state" = 'true' ]; then + echo "[!] PR is currently a draft, stopping pipeline" + exit 1 +else + echo "[+] PR is not a draft. Proceeding with CI pipeline" + exit 0 +fi diff --git a/.maintain/monitoring/alerting-rules/alerting-rule-tests.yaml b/.maintain/monitoring/alerting-rules/alerting-rule-tests.yaml new file mode 100644 index 0000000000000000000000000000000000000000..288750be3c108f3f9b820e038d81997626897806 --- /dev/null +++ b/.maintain/monitoring/alerting-rules/alerting-rule-tests.yaml @@ -0,0 +1,262 @@ +rule_files: + - /dev/stdin + +evaluation_interval: 1m + +tests: + - interval: 1m + input_series: + - series: 'polkadot_sub_libp2p_peers_count{ + job="polkadot", + pod="polkadot-abcdef01234-abcdef", + instance="polkadot-abcdef01234-abcdef", + }' + values: '3 2+0x4 1+0x9' # 3 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + + - series: 'polkadot_sub_txpool_validations_scheduled{ + job="polkadot", + pod="polkadot-abcdef01234-abcdef", + instance="polkadot-abcdef01234-abcdef", + }' + values: '11+1x10 22+2x30 10043x5' + + - series: 'polkadot_sub_txpool_validations_finished{ + job="polkadot", + pod="polkadot-abcdef01234-abcdef", + instance="polkadot-abcdef01234-abcdef", + }' + values: '0+1x42 42x5' + + - series: 'polkadot_block_height{ + status="best", job="polkadot", + pod="polkadot-abcdef01234-abcdef", + instance="polkadot-abcdef01234-abcdef", + }' + values: '1+1x3 4+0x13' # 1 2 3 4 4 4 4 4 4 4 4 4 ... + + - series: 'polkadot_block_height{ + status="finalized", + job="polkadot", + pod="polkadot-abcdef01234-abcdef", + instance="polkadot-abcdef01234-abcdef", + }' + values: '1+1x3 4+0x13' # 1 2 3 4 4 4 4 4 4 4 4 4 ... + + - series: 'polkadot_cpu_usage_percentage{ + job="polkadot", + pod="polkadot-abcdef01234-abcdef", + instance="polkadot-abcdef01234-abcdef", + }' + values: '0+20x5 100+0x5' # 0 20 40 60 80 100 100 100 100 100 100 + + alert_rule_test: + + ###################################################################### + # Resource usage + ###################################################################### + + - eval_time: 9m + alertname: HighCPUUsage + exp_alerts: + - eval_time: 10m + alertname: HighCPUUsage + exp_alerts: + - exp_labels: + severity: warning + pod: polkadot-abcdef01234-abcdef + instance: polkadot-abcdef01234-abcdef + job: polkadot + exp_annotations: + message: "The node polkadot-abcdef01234-abcdef has a CPU + usage higher than 100% for more than 5 minutes" + + ###################################################################### + # Block production + ###################################################################### + + - eval_time: 6m + alertname: LowNumberOfNewBlocks + exp_alerts: + - eval_time: 7m + alertname: LowNumberOfNewBlocks + exp_alerts: + - exp_labels: + severity: warning + pod: polkadot-abcdef01234-abcdef + instance: polkadot-abcdef01234-abcdef + job: polkadot + status: best + exp_annotations: + message: "Less than one new block per minute on instance + polkadot-abcdef01234-abcdef." + + - eval_time: 14m + alertname: LowNumberOfNewBlocks + exp_alerts: + - exp_labels: + severity: warning + pod: polkadot-abcdef01234-abcdef + instance: polkadot-abcdef01234-abcdef + job: polkadot + status: best + exp_annotations: + message: "Less than one new block per minute on instance + polkadot-abcdef01234-abcdef." + - exp_labels: + severity: critical + pod: polkadot-abcdef01234-abcdef + instance: polkadot-abcdef01234-abcdef + job: polkadot + status: best + exp_annotations: + message: "Less than one new block per minute on instance + polkadot-abcdef01234-abcdef." + + ###################################################################### + # Block finalization + ###################################################################### + + - eval_time: 6m + alertname: BlockFinalizationSlow + exp_alerts: + - eval_time: 7m + alertname: BlockFinalizationSlow + exp_alerts: + - exp_labels: + severity: warning + pod: polkadot-abcdef01234-abcdef + instance: polkadot-abcdef01234-abcdef + job: polkadot + status: finalized + exp_annotations: + message: "Finalized block on instance + polkadot-abcdef01234-abcdef increases by less than 1 per + minute." + + - eval_time: 14m + alertname: BlockFinalizationSlow + exp_alerts: + - exp_labels: + severity: warning + pod: polkadot-abcdef01234-abcdef + instance: polkadot-abcdef01234-abcdef + job: polkadot + status: finalized + exp_annotations: + message: "Finalized block on instance + polkadot-abcdef01234-abcdef increases by less than 1 per + minute." + - exp_labels: + severity: critical + pod: polkadot-abcdef01234-abcdef + instance: polkadot-abcdef01234-abcdef + job: polkadot + status: finalized + exp_annotations: + message: "Finalized block on instance + polkadot-abcdef01234-abcdef increases by less than 1 per + minute." + + ###################################################################### + # Transaction queue + ###################################################################### + + - eval_time: 11m + alertname: TransactionQueueSizeIncreasing + # Number of validations scheduled and finished both grow at a rate + # of 1 in the first 10 minutes, thereby the queue is not increasing + # in size, thus don't expect an alert. + exp_alerts: + - eval_time: 22m + alertname: TransactionQueueSizeIncreasing + # Number of validations scheduled is growing twice as fast as the + # number of validations finished after minute 10. Thus expect + # warning alert after 20 minutes. + exp_alerts: + - exp_labels: + severity: warning + pod: polkadot-abcdef01234-abcdef + instance: polkadot-abcdef01234-abcdef + job: polkadot + exp_annotations: + message: "The transaction pool size on node + polkadot-abcdef01234-abcdef has been monotonically + increasing for the last 10 minutes." + - eval_time: 43m + alertname: TransactionQueueSizeIncreasing + # Number of validations scheduled is growing twice as fast as the + # number of validations finished after minute 10. Thus expect + # both warning and critical alert after 40 minutes. + exp_alerts: + - exp_labels: + severity: warning + pod: polkadot-abcdef01234-abcdef + instance: polkadot-abcdef01234-abcdef + job: polkadot + exp_annotations: + message: "The transaction pool size on node + polkadot-abcdef01234-abcdef has been monotonically + increasing for the last 10 minutes." + - exp_labels: + severity: critical + pod: polkadot-abcdef01234-abcdef + instance: polkadot-abcdef01234-abcdef + job: polkadot + exp_annotations: + message: "The transaction pool size on node + polkadot-abcdef01234-abcdef has been monotonically + increasing for the last 30 minutes." + - eval_time: 49m + alertname: TransactionQueueSizeHigh + # After minute 43 the number of validations scheduled jumps up + # drastically while the number of validations finished stays the + # same. Thus expect an alert. + exp_alerts: + - exp_labels: + severity: critical + pod: polkadot-abcdef01234-abcdef + instance: polkadot-abcdef01234-abcdef + job: polkadot + exp_annotations: + message: "The transaction pool size on node + polkadot-abcdef01234-abcdef has been above 10_000 for the + last 5 minutes." + + ###################################################################### + # Networking + ###################################################################### + + - eval_time: 3m # Values: 3 2 2 + alertname: LowNumberOfPeers + exp_alerts: + - eval_time: 4m # Values: 2 2 2 + alertname: LowNumberOfPeers + exp_alerts: + - exp_labels: + severity: warning + pod: polkadot-abcdef01234-abcdef + instance: polkadot-abcdef01234-abcdef + job: polkadot + exp_annotations: + message: "The node polkadot-abcdef01234-abcdef has less + than 3 peers for more than 3 minutes" + + - eval_time: 16m # Values: 3 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 + alertname: LowNumberOfPeers + exp_alerts: + - exp_labels: + severity: warning + pod: polkadot-abcdef01234-abcdef + instance: polkadot-abcdef01234-abcdef + job: polkadot + exp_annotations: + message: "The node polkadot-abcdef01234-abcdef has less + than 3 peers for more than 3 minutes" + - exp_labels: + severity: critical + pod: polkadot-abcdef01234-abcdef + instance: polkadot-abcdef01234-abcdef + job: polkadot + exp_annotations: + message: "The node polkadot-abcdef01234-abcdef has less + than 3 peers for more than 15 minutes" diff --git a/.maintain/monitoring/alerting-rules/alerting-rules.yaml b/.maintain/monitoring/alerting-rules/alerting-rules.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2ed3889a2c2f94d80b79e9376201432d65cf89bc --- /dev/null +++ b/.maintain/monitoring/alerting-rules/alerting-rules.yaml @@ -0,0 +1,138 @@ +groups: +- name: polkadot.rules + rules: + + ############################################################################## + # Resource usage + ############################################################################## + + - alert: HighCPUUsage + expr: polkadot_cpu_usage_percentage >= 100 + for: 5m + labels: + severity: warning + annotations: + message: 'The node {{ $labels.instance }} has a CPU usage higher than 100% + for more than 5 minutes' + + ############################################################################## + # Block production + ############################################################################## + + - alert: LowNumberOfNewBlocks + annotations: + message: 'Less than one new block per minute on instance {{ + $labels.instance }}.' + expr: increase(polkadot_block_height{status="best"}[1m]) < 1 + for: 3m + labels: + severity: warning + - alert: LowNumberOfNewBlocks + annotations: + message: 'Less than one new block per minute on instance {{ + $labels.instance }}.' + expr: increase(polkadot_block_height{status="best"}[1m]) < 1 + for: 10m + labels: + severity: critical + + ############################################################################## + # Block finalization + ############################################################################## + + - alert: BlockFinalizationSlow + expr: increase(polkadot_block_height{status="finalized"}[1m]) < 1 + for: 3m + labels: + severity: warning + annotations: + message: 'Finalized block on instance {{ $labels.instance }} increases by + less than 1 per minute.' + - alert: BlockFinalizationSlow + expr: increase(polkadot_block_height{status="finalized"}[1m]) < 1 + for: 10m + labels: + severity: critical + annotations: + message: 'Finalized block on instance {{ $labels.instance }} increases by + less than 1 per minute.' + - alert: BlockFinalizationLaggingBehind + # Under the assumption of an average block production of 6 seconds, + # "best" and "finalized" being more than 10 blocks apart would imply + # more than a 1 minute delay between block production and finalization. + expr: '(polkadot_block_height_number{status="best"} - ignoring(status) + polkadot_block_height_number{status="finalized"}) > 10' + for: 8m + labels: + severity: critical + annotations: + message: "Block finalization on instance {{ $labels.instance }} is behind + block production by {{ $value }} for more than 8m" + + ############################################################################## + # Transaction queue + ############################################################################## + + - alert: TransactionQueueSizeIncreasing + expr: 'increase(polkadot_sub_txpool_validations_scheduled[5m]) - + increase(polkadot_sub_txpool_validations_finished[5m]) > 0' + for: 10m + labels: + severity: warning + annotations: + message: 'The transaction pool size on node {{ $labels.instance }} has + been monotonically increasing for the last 10 minutes.' + - alert: TransactionQueueSizeIncreasing + expr: 'increase(polkadot_sub_txpool_validations_scheduled[5m]) - + increase(polkadot_sub_txpool_validations_finished[5m]) > 0' + for: 30m + labels: + severity: critical + annotations: + message: 'The transaction pool size on node {{ $labels.instance }} has + been monotonically increasing for the last 30 minutes.' + - alert: TransactionQueueSizeHigh + expr: 'polkadot_sub_txpool_validations_scheduled - + polkadot_sub_txpool_validations_finished > 10000' + for: 5m + labels: + severity: critical + annotations: + message: 'The transaction pool size on node {{ $labels.instance }} has + been above 10_000 for the last 5 minutes.' + + ############################################################################## + # Networking + ############################################################################## + + - alert: LowNumberOfPeers + expr: polkadot_sub_libp2p_peers_count < 3 + for: 3m + labels: + severity: warning + annotations: + message: 'The node {{ $labels.instance }} has less than 3 peers for more + than 3 minutes' + - alert: LowNumberOfPeers + expr: polkadot_sub_libp2p_peers_count < 3 + for: 15m + labels: + severity: critical + annotations: + message: 'The node {{ $labels.instance }} has less than 3 peers for more + than 15 minutes' + + ############################################################################## + # Others + ############################################################################## + + - alert: AuthorityDiscoveryHighDiscoveryFailure + expr: 'polkadot_authority_discovery_handle_value_found_event_failure / + ignoring(name) + polkadot_authority_discovery_dht_event_received{name="value_found"} > 0.5' + for: 2h + labels: + severity: warning + annotations: + message: "Authority discovery on node {{ $labels.instance }} fails to + process more than 50 % of the values found on the DHT." diff --git a/.maintain/monitoring/grafana-dashboards/README_dashboard.md b/.maintain/monitoring/grafana-dashboards/README_dashboard.md new file mode 100644 index 0000000000000000000000000000000000000000..37bebc6f8eaae0e9430a612d7bc9676ac666e648 --- /dev/null +++ b/.maintain/monitoring/grafana-dashboards/README_dashboard.md @@ -0,0 +1,14 @@ +## Substrate Dashboard + +Shared templated Grafana dashboards. + +To import the dashboards follow the [Grafana +documentation](https://grafana.com/docs/grafana/latest/reference/export_import/). +You can see an example setup [here](../../../.maintain/sentry-node). + +#### Required labels on Prometheus metrics + +- `instance` referring to a single scrape target (see [Prometheus docs for + details](https://prometheus.io/docs/concepts/jobs_instances/)). + +- `network` referring to the Blockchain network e.g. Kusama. diff --git a/.maintain/monitoring/grafana-dashboards/substrate-dashboard.json b/.maintain/monitoring/grafana-dashboards/substrate-dashboard.json new file mode 100644 index 0000000000000000000000000000000000000000..629b22617b22a970eb1f439179f62711d1bac9b4 --- /dev/null +++ b/.maintain/monitoring/grafana-dashboards/substrate-dashboard.json @@ -0,0 +1,1650 @@ +{ + "annotations": { + "list": [ + { + "$$hashKey": "object:15", + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "iteration": 1586424254170, + "links": [ + { + "icon": "external link", + "tags": [], + "targetBlank": true, + "title": "With love from ColmenaLabs", + "tooltip": "", + "type": "link", + "url": "https://colmenalabs.org" + }, + { + "icon": "external link", + "tags": [], + "targetBlank": true, + "title": "Polkastats.io", + "tooltip": "", + "type": "link", + "url": "https://polkastats.io" + } + ], + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "description": "", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 0, + "y": 0 + }, + "hiddenSeries": false, + "id": 8, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate([[metric_namespace]]_block_height{status=\"finalized\",instance=\"[[instance]]\",network=\"[[network]]\"}[10m])/rate([[metric_namespace]]_block_height{status=\"finalized\",instance=\"[[instance]]\",network=\"[[network]]\"}[1m])", + "intervalFactor": 1, + "legendFormat": "rate[10m] / rate[1m]", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Relative Block Production Speed", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "description": "", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 6, + "y": 0 + }, + "hiddenSeries": false, + "id": 15, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "[[metric_namespace]]_sub_libp2p_peers_count{instance=\"[[instance]]\",network=\"[[network]]\"}", + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Peers count", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "cacheTimeout": null, + "dashLength": 10, + "dashes": false, + "datasource": null, + "description": "", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 12, + "y": 0 + }, + "hiddenSeries": false, + "id": 17, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pluginVersion": "6.4.1", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "scalar([[metric_namespace]]_block_height{status=\"best\",instance=\"[[instance]]\",network=\"[[network]]\"})-scalar([[metric_namespace]]_block_height{status=\"finalized\",instance=\"[[instance]]\",network=\"[[network]]\"})", + "intervalFactor": 2, + "legendFormat": "[[hostname]]", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Diff -> ( Best Block - Finalized )", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "cacheTimeout": null, + "dashLength": 10, + "dashes": false, + "datasource": null, + "description": "", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 18, + "y": 0 + }, + "hiddenSeries": false, + "id": 18, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate([[metric_namespace]]_block_height{status=\"finalized\",instance=\"[[instance]]\",network=\"[[network]]\"}[10m])*60", + "intervalFactor": 10, + "legendFormat": "{{instance}} Blocks / minute", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Block rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "description": "", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 0, + "y": 6 + }, + "hiddenSeries": false, + "id": 10, + "interval": "", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "increase([[metric_namespace]]_block_height{instance=\"[[instance]]\",network=\"[[network]]\",status=~\"finalized|sync_target\"}[1m])", + "intervalFactor": 5, + "legendFormat": "{{status}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Blocks Av per min", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "description": "", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 6, + "y": 6 + }, + "hiddenSeries": false, + "id": 14, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "[[metric_namespace]]_block_height{instance=\"[[instance]]\",network=\"[[network]]\",status=~\"finalized|sync_target\"}", + "legendFormat": "{{instance}} {{status}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Block Finalized", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "description": "", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 12, + "y": 6 + }, + "hiddenSeries": false, + "id": 13, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "[[metric_namespace]]_block_height{status=\"best\",instance=\"[[instance]]\",network=\"[[network]]\"}", + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Block height", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 18, + "y": 6 + }, + "hiddenSeries": false, + "id": 20, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "data": "", + "expr": "[[metric_namespace]]_ready_transactions_number{instance=\"[[instance]]\",network=\"[[network]]\"}", + "hide": false, + "legendFormat": "{{instance}}", + "refId": "A", + "target": "txcount", + "type": "timeseries" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "TXs Count", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 0, + "y": 12 + }, + "hiddenSeries": false, + "id": 23, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "[[metric_namespace]]_sync_extra_finality_proofs_active{instance=\"[[instance]]\",network=\"[[network]]\"}", + "legendFormat": "{{instance}} active", + "refId": "A" + }, + { + "expr": "[[metric_namespace]]_sync_extra_finality_proofs_failed{instance=\"[[instance]]\",network=\"[[network]]\"}", + "legendFormat": "{{instance}} failed", + "refId": "B" + }, + { + "expr": "[[metric_namespace]]_sync_extra_finality_proofs_importing{instance=\"[[instance]]\",network=\"[[network]]\"}", + "legendFormat": "{{instance}} importing", + "refId": "C" + }, + { + "expr": "[[metric_namespace]]_sync_extra_finality_proofs_pending{instance=\"[[instance]]\",network=\"[[network]]\"}", + "legendFormat": "{{instance}} pending", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Sync Proof", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 6, + "y": 12 + }, + "hiddenSeries": false, + "id": 22, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "[[metric_namespace]]_sync_extra_justifications_active{instance=\"[[instance]]\",network=\"[[network]]\"}", + "legendFormat": "{{instance}} active", + "refId": "A" + }, + { + "expr": "[[metric_namespace]]_sync_extra_justifications_failed{instance=\"[[instance]]\",network=\"[[network]]\"}", + "legendFormat": "{{instance}} failed", + "refId": "B" + }, + { + "expr": "[[metric_namespace]]_sync_extra_justifications_importing{instance=\"[[instance]]\",network=\"[[network]]\"}", + "legendFormat": "{{instance}} importing", + "refId": "C" + }, + { + "expr": "[[metric_namespace]]_sync_extra_justifications_pending{instance=\"[[instance]]\",network=\"[[network]]\"}", + "legendFormat": "{{instance}} pending", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Sync justifications", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "description": "", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 12, + "y": 12 + }, + "hiddenSeries": false, + "id": 24, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "[[metric_namespace]]_sub_libp2p_connections{instance=\"[[instance]]\",network=\"[[network]]\"}", + "hide": false, + "legendFormat": "{{instance}} connections", + "refId": "A" + }, + { + "expr": "[[metric_namespace]]_sub_libp2p_is_major_syncing{instance=\"[[instance]]\",network=\"[[network]]\"}", + "hide": false, + "legendFormat": "{{instance}} syncing", + "refId": "B" + }, + { + "expr": "[[metric_namespace]]_sub_libp2p_kbuckets_num_nodes{instance=\"[[instance]]\",network=\"[[network]]\"}", + "hide": false, + "legendFormat": "{{instance}} num_nodes", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "sub_libp2p", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "description": "", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 18, + "y": 12 + }, + "hiddenSeries": false, + "id": 26, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "[[metric_namespace]]_sub_libp2p_notifications_total{instance=\"[[instance]]\",network=\"[[network]]\",protocol=\"FRNK\",direction=\"in\"}", + "hide": false, + "legendFormat": "{{instance}} FRNK in", + "refId": "A" + }, + { + "expr": "[[metric_namespace]]_sub_libp2p_notifications_total{instance=\"[[instance]]\",network=\"[[network]]\",protocol=\"FRNK\",direction=\"out\"}", + "hide": false, + "legendFormat": "{{instance}} FRNK out", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "libp2p_notifications", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "description": "", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 0, + "y": 18 + }, + "hiddenSeries": false, + "id": 28, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "[[metric_namespace]]_cpu_usage_percentage{instance=\"[[instance]]\",network=\"[[network]]\"}", + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU usage %", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 6, + "y": 18 + }, + "hiddenSeries": false, + "id": 27, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "[[metric_namespace]]_memory_usage_bytes{instance=\"[[instance]]\",network=\"[[network]]\"}", + "legendFormat": "{{instance}} Mem bytes", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 2, + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "description": "", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 12, + "y": 18 + }, + "hiddenSeries": false, + "id": 25, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "[[metric_namespace]]_sub_libp2p_network_per_sec_bytes", + "hide": false, + "legendFormat": "{{instance}}", + "refId": "A" + }, + { + "expr": "[[metric_namespace]]_sub_libp2p_notifications_total", + "hide": true, + "legendFormat": "{{instance}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "libp2p_network_per_sec_bytes", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "cacheTimeout": null, + "dashLength": 10, + "dashes": false, + "datasource": null, + "description": "", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 18, + "y": 18 + }, + "hiddenSeries": false, + "id": 29, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pluginVersion": "6.5.2", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "[[metric_namespace]]_sub_libp2p_notifications_total{instance=\"[[instance]]\",network=\"[[network]]\",protocol=\"dot1\",direction=\"in\"}", + "hide": false, + "legendFormat": "{{instance}} dot1 in", + "refId": "B" + }, + { + "expr": "[[metric_namespace]]_sub_libp2p_notifications_total{instance=\"[[instance]]\",network=\"[[network]]\",protocol=\"dot2\",direction=\"in\"}", + "hide": false, + "legendFormat": "{{instance}} dot2 in", + "refId": "C" + }, + { + "expr": "[[metric_namespace]]_sub_libp2p_notifications_total{instance=\"[[instance]]\",network=\"[[network]]\",protocol=\"dot2\",direction=\"out\"}", + "hide": false, + "legendFormat": "{{instance}} dot2 out", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "libp2p_notifications", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": "5s", + "schemaVersion": 22, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "allValue": null, + "current": { + "selected": true, + "text": "substrate", + "value": "substrate" + }, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "metric_namespace", + "options": [ + { + "selected": true, + "text": "substrate", + "value": "substrate" + }, + { + "selected": false, + "text": "polkadot", + "value": "polkadot" + } + ], + "query": "substrate, polkadot", + "skipUrlSync": false, + "type": "custom" + }, + { + "allValue": null, + "current": { + "selected": true, + "text": "dev", + "value": "dev" + }, + "datasource": "Prometheus", + "definition": "label_values(network)", + "hide": 0, + "includeAll": false, + "index": -1, + "label": null, + "multi": false, + "name": "network", + "options": [], + "query": "label_values(network)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "selected": false, + "text": "validator-a:9615", + "value": "validator-a:9615" + }, + "datasource": "Prometheus", + "definition": "label_values(instance)", + "hide": 0, + "includeAll": false, + "index": -1, + "label": null, + "multi": false, + "name": "instance", + "options": [], + "query": "label_values(instance)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Substrate Dashboard", + "uid": "ColmenaLabs", + "variables": { + "list": [] + }, + "version": 2 +} diff --git a/.maintain/monitoring/grafana-dashboards/substrate-networking.json b/.maintain/monitoring/grafana-dashboards/substrate-networking.json new file mode 100644 index 0000000000000000000000000000000000000000..f18ca66c13a0774eca86ceef42795cf4b36a35d3 --- /dev/null +++ b/.maintain/monitoring/grafana-dashboards/substrate-networking.json @@ -0,0 +1,2722 @@ +{ + "__inputs": [ + { + "name": "VAR_METRIC_NAMESPACE", + "type": "constant", + "label": "Prefix of the metrics", + "value": "polkadot", + "description": "" + } + ], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "6.7.3" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "" + }, + { + "type": "panel", + "id": "heatmap", + "name": "Heatmap", + "version": "" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + } + ], + "annotations": { + "list": [ + { + "$$hashKey": "object:821", + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "limit": 100, + "name": "Annotations & Alerts", + "showIn": 0, + "type": "dashboard" + }, + { + "$$hashKey": "object:822", + "datasource": "$data_source", + "enable": true, + "expr": "count(count(${metric_namespace}_sub_libp2p_connections / max_over_time(${metric_namespace}_sub_libp2p_connections[1h]) < 0.1) >= count(${metric_namespace}_sub_libp2p_connections) / 10)", + "hide": false, + "iconColor": "#C4162A", + "limit": 100, + "name": "Connection losses events", + "showIn": 0, + "step": "5m", + "tags": [], + "titleFormat": "Network-wide connectivity loss", + "type": "tags" + } + ] + }, + "description": "Information related to the networking layer of Substrate", + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": null, + "iteration": 1590742405831, + "links": [], + "panels": [ + { + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 167, + "title": "Sync", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 24, + "x": 0, + "y": 1 + }, + "hiddenSeries": false, + "id": 101, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "v", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "1 - (${metric_namespace}_sub_libp2p_peerset_num_requested{instance=~\"${nodename}\"} - ${metric_namespace}_sub_libp2p_peers_count{instance=~\"${nodename}\"}) / ${metric_namespace}_sub_libp2p_peerset_num_requested{instance=~\"${nodename}\"}", + "interval": "", + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Number of peer slots filled", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1044", + "format": "percentunit", + "label": null, + "logBase": 1, + "max": "1.0", + "min": null, + "show": true + }, + { + "$$hashKey": "object:1045", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 6 + }, + "id": 29, + "panels": [], + "repeat": "request_protocol", + "title": "Requests (${request_protocol})", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 7 + }, + "hiddenSeries": false, + "id": 148, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(${metric_namespace}_sub_libp2p_requests_out_started_total{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[5m])", + "interval": "", + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests emitted per second", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 7 + }, + "hiddenSeries": false, + "id": 151, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(${metric_namespace}_sub_libp2p_requests_in_total_count{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[5m])", + "interval": "", + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests served per second", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 11 + }, + "hiddenSeries": false, + "id": 146, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(${metric_namespace}_sub_libp2p_requests_out_finished_bucket{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[5m])) by (instance, le)) > 0", + "instant": false, + "interval": "", + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Median request answer time", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1230", + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:1231", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 11 + }, + "hiddenSeries": false, + "id": 145, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(${metric_namespace}_sub_libp2p_requests_in_total_bucket{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[5m])) by (instance, le))", + "interval": "", + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Median request serving time", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 15 + }, + "hiddenSeries": false, + "id": 150, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(${metric_namespace}_sub_libp2p_requests_out_finished_bucket{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[5m])) by (instance, le)) > 0", + "instant": false, + "interval": "", + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "99th percentile request answer time", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 15 + }, + "hiddenSeries": false, + "id": 149, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(${metric_namespace}_sub_libp2p_requests_in_total_bucket{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[5m])) by (instance, le))", + "interval": "", + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "99th percentile request serving time", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 185 + }, + "id": 23, + "panels": [], + "repeat": "notif_protocol", + "title": "Notifications (${notif_protocol})", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 186 + }, + "hiddenSeries": false, + "id": 31, + "interval": "1m", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 2, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "v", + "seriesOverrides": [ + { + "$$hashKey": "object:850", + "alias": "/(in)/", + "color": "#73BF69" + }, + { + "$$hashKey": "object:851", + "alias": "/(out)/", + "color": "#F2495C" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg by (direction) (irate(${metric_namespace}_sub_libp2p_notifications_sizes_count{instance=~\"${nodename}\", protocol=\"${notif_protocol}\"}[$__interval]))", + "interval": "", + "legendFormat": "{{direction}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Average network notifications per second", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:874", + "format": "cps", + "label": "Notifs/sec", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:875", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 186 + }, + "hiddenSeries": false, + "id": 37, + "interval": "1m", + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 2, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "v", + "seriesOverrides": [ + { + "$$hashKey": "object:942", + "alias": "/(in)/", + "color": "#73BF69" + }, + { + "$$hashKey": "object:943", + "alias": "/(out)/", + "color": "#F2495C" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(irate(${metric_namespace}_sub_libp2p_notifications_sizes_sum{instance=~\"${nodename}\", protocol=\"${notif_protocol}\"}[$__interval])) by (direction)", + "instant": false, + "interval": "", + "legendFormat": "{{direction}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Average bandwidth used by notifications", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:966", + "format": "Bps", + "label": "Bandwidth", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:967", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 193 + }, + "hiddenSeries": false, + "id": 16, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "max(${metric_namespace}_sub_libp2p_out_events_notifications_sizes{instance=~\"${nodename}\", protocol=\"${notif_protocol}\", action=\"sent\"} - ignoring(action) ${metric_namespace}_sub_libp2p_out_events_notifications_sizes{instance=~\"${nodename}\", protocol=\"${notif_protocol}\", action=\"received\"}) by (instance) > 0", + "interval": "", + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Total sizes of notifications waiting to be delivered to the rest of Substrate", + "tooltip": { + "shared": false, + "sort": 1, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 1, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 193 + }, + "hiddenSeries": false, + "id": 21, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pluginVersion": "6.4.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(${metric_namespace}_sub_libp2p_notifications_sizes_sum{instance=~\"${nodename}\", protocol=\"${notif_protocol}\"}[5m])) by (direction, protocol) / sum(rate(${metric_namespace}_sub_libp2p_notifications_sizes_count{instance=~\"${nodename}\", protocol=\"${notif_protocol}\"}[5m])) by (direction, protocol)", + "format": "time_series", + "interval": "", + "legendFormat": "{{direction}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Average size of sent and received notifications in the past 5 minutes", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:2050", + "format": "bytes", + "label": "Max. notification size", + "logBase": 10, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:2051", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "description": "99.9% of the time, the output queue size for this protocol is below the given value", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 201 + }, + "hiddenSeries": false, + "id": 14, + "legend": { + "alignAsTable": false, + "avg": false, + "current": true, + "hideEmpty": false, + "hideZero": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "max", + "fill": 1, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(${metric_namespace}_sub_libp2p_notifications_queues_size_bucket{instance=~\"${nodename}\", protocol=\"${notif_protocol}\"}[2m])) by (le, instance))", + "hide": false, + "interval": "", + "legendFormat": "{{protocol}}", + "refId": "A" + }, + { + "expr": "max(histogram_quantile(0.99, sum(rate(${metric_namespace}_sub_libp2p_notifications_queues_size_bucket{instance=~\"${nodename}\", protocol=\"${notif_protocol}\"}[2m])) by (le, instance)))", + "interval": "", + "legendFormat": "max", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "99th percentile of queues sizes", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": "300", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 1, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 201 + }, + "hiddenSeries": false, + "id": 134, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pluginVersion": "6.4.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(1.0, sum(rate(${metric_namespace}_sub_libp2p_notifications_sizes_bucket{instance=~\"${nodename}\", protocol=\"${notif_protocol}\"}[5m])) by (direction, le))", + "format": "time_series", + "interval": "", + "legendFormat": "{{direction}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Maximum size of sent and received notifications in the past 5 minutes", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1524", + "format": "bytes", + "label": "Max. notification size", + "logBase": 10, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:1525", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 1853 + }, + "id": 27, + "panels": [], + "title": "Transport", + "type": "row" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 1854 + }, + "hiddenSeries": false, + "id": 19, + "interval": "1m", + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "maxPerRow": 2, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "v", + "seriesOverrides": [ + { + "alias": "established (in)", + "color": "#37872D" + }, + { + "alias": "established (out)", + "color": "#C4162A" + }, + { + "alias": "pending (out)", + "color": "#FF7383" + }, + { + "alias": "closed-recently", + "color": "#FADE2A", + "steppedLine": true + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(sum(${metric_namespace}_sub_libp2p_connections_opened_total{direction=\"in\", instance=~\"${nodename}\"}) by (instance) - sum(${metric_namespace}_sub_libp2p_connections_closed_total{direction=\"in\", instance=~\"${nodename}\"}) by (instance))", + "format": "time_series", + "hide": false, + "interval": "", + "legendFormat": "established (in)", + "refId": "A" + }, + { + "expr": "avg(sum(${metric_namespace}_sub_libp2p_connections_opened_total{direction=\"out\", instance=~\"${nodename}\"}) by (instance) - sum(${metric_namespace}_sub_libp2p_connections_closed_total{direction=\"out\", instance=~\"${nodename}\"}) by (instance))", + "hide": false, + "instant": false, + "interval": "", + "legendFormat": "established (out)", + "refId": "C" + }, + { + "expr": "avg(sum by (instance) (${metric_namespace}_sub_libp2p_pending_connections{instance=~\"${nodename}\"}))", + "hide": false, + "interval": "", + "legendFormat": "pending (out)", + "refId": "B" + }, + { + "expr": "avg(sum by(instance) (increase(${metric_namespace}_sub_libp2p_connections_closed_total{instance=~\"${nodename}\"}[$__interval])))", + "hide": false, + "interval": "", + "legendFormat": "closed-recently", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Average transport-level (TCP, QUIC, ...) connections per node", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Connections", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 1860 + }, + "hiddenSeries": false, + "id": 39, + "interval": "1m", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*/", + "color": "#FF780A" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(increase(${metric_namespace}_sub_libp2p_incoming_connections_handshake_errors_total{instance=~\"${nodename}\"}[$__interval])) by (reason)", + "interval": "", + "legendFormat": "{{reason}}", + "refId": "A" + }, + { + "expr": "avg(increase(${metric_namespace}_sub_libp2p_listeners_errors_total{instance=~\"${nodename}\"}[$__interval]))", + "interval": "", + "legendFormat": "pre-handshake", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Number of incoming connection errors, averaged by node", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Errors", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "cards": { + "cardPadding": null, + "cardRound": null + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateOranges", + "exponent": 0.5, + "max": 100, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "timeseries", + "datasource": "$data_source", + "description": "Each bucket represent a certain number of nodes using a certain bandwidth range.", + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 1860 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 4, + "legend": { + "show": false + }, + "reverseYBuckets": false, + "targets": [ + { + "expr": "${metric_namespace}_network_per_sec_bytes{instance=~\"${nodename}\"}", + "format": "time_series", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Heatmap of network bandwidth", + "tooltip": { + "show": true, + "showHistogram": false + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": "2.5m", + "yAxis": { + "decimals": null, + "format": "Bps", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 1866 + }, + "hiddenSeries": false, + "id": 81, + "interval": "1m", + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "v", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(increase(${metric_namespace}_sub_libp2p_pending_connections_errors_total{instance=~\"${nodename}\"}[$__interval])) by (reason)", + "interval": "", + "legendFormat": "{{reason}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Dialing attempt errors, averaged per node", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 1866 + }, + "hiddenSeries": false, + "id": 46, + "interval": "1m", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "maxPerRow": 2, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "v", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(increase(${metric_namespace}_sub_libp2p_connections_closed_total{instance=~\"${nodename}\"}[$__interval])) by (reason)", + "interval": "", + "legendFormat": "{{reason}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disconnects, averaged per node", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "short", + "label": "Disconnects", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 1873 + }, + "id": 52, + "panels": [], + "title": "GrandPa", + "type": "row" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 1874 + }, + "hiddenSeries": false, + "id": 54, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "v", + "seriesOverrides": [ + { + "alias": "/discard/", + "color": "#FA6400", + "zindex": -2 + }, + { + "alias": "/keep/", + "color": "#73BF69", + "zindex": 2 + }, + { + "alias": "/process_and_discard/", + "color": "#5794F2" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(increase(${metric_namespace}_finality_grandpa_communication_gossip_validator_messages{instance=~\"${nodename}\"}[$__interval])) by (action, message)", + "interval": "", + "legendFormat": "{{message}} => {{action}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "GrandPa messages received from the network, and action", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 1880 + }, + "id": 25, + "panels": [], + "repeat": null, + "title": "Kademlia", + "type": "row" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "description": "", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 1881 + }, + "hiddenSeries": false, + "id": 33, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*/", + "color": "#B877D9" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "${metric_namespace}_sub_libp2p_kbuckets_num_nodes{instance=~\"${nodename}\"}", + "format": "time_series", + "instant": true, + "interval": "", + "legendFormat": "Number nodes in all kbuckets", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Distribution over number of entries in k-buckets", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "max": 0, + "min": null, + "mode": "histogram", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 7, + "fillGradient": 7, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 1881 + }, + "hiddenSeries": false, + "id": 35, + "interval": "1m", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "60 * sum(irate(${metric_namespace}_sub_libp2p_random_kademalia_queries_total{instance=~\"${nodename}\"}[$__interval]))", + "interval": "", + "legendFormat": "Number of Kademlia random queries started per minute on all nodes", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Number of Kademlia discovery queries per minute on all nodes combined", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "cpm", + "label": "Queries per minute", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 1887 + }, + "hiddenSeries": false, + "id": 111, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "max", + "fillBelowTo": "min", + "lines": false + }, + { + "alias": "min", + "lines": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(${metric_namespace}_sub_libp2p_kademlia_records_count{instance=~\"${nodename}\"})", + "interval": "", + "legendFormat": "avg", + "refId": "A" + }, + { + "expr": "min(${metric_namespace}_sub_libp2p_kademlia_records_count{instance=~\"${nodename}\"})", + "interval": "", + "legendFormat": "min", + "refId": "B" + }, + { + "expr": "max(${metric_namespace}_sub_libp2p_kademlia_records_count{instance=~\"${nodename}\"})", + "interval": "", + "legendFormat": "max", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Number of Kademlia records (average/min/max per node)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 1887 + }, + "hiddenSeries": false, + "id": 112, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "max", + "fillBelowTo": "min", + "lines": false + }, + { + "alias": "min", + "lines": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(${metric_namespace}_sub_libp2p_kademlia_records_sizes_total{instance=~\"${nodename}\"})", + "interval": "", + "legendFormat": "avg", + "refId": "A" + }, + { + "expr": "min(${metric_namespace}_sub_libp2p_kademlia_records_sizes_total{instance=~\"${nodename}\"})", + "interval": "", + "legendFormat": "min", + "refId": "B" + }, + { + "expr": "max(${metric_namespace}_sub_libp2p_kademlia_records_sizes_total{instance=~\"${nodename}\"})", + "interval": "", + "legendFormat": "max", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Total size of Kademlia records (average/min/max per node)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 24, + "x": 0, + "y": 1891 + }, + "hiddenSeries": false, + "id": 68, + "interval": "1m", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "v", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(\n # The amount of inflight Kademlia queries per node.\r\n sum by (instance) (\r\n # The total amount of Kademlia GET_VALUE queries started.\r\n ${metric_namespace}_authority_discovery_authority_addresses_requested_total{instance=~\"${nodename}\"}\r\n \r\n # The total amount of Kademlia PUT_VALUE queries started.\r\n + ${metric_namespace}_authority_discovery_times_published_total{instance=~\"${nodename}\"}\r\n )\r\n - sum by (instance) (\r\n # The total amount of Kademlia queries (both GET_VALUE and PUT_VALUE) finished.\r\n ${metric_namespace}_authority_discovery_dht_event_received{instance=~\"${nodename}\"}\r\n )\n)", + "interval": "", + "legendFormat": "in-progress", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Authority discovery Kademlia queries in progress, averaged per node", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 24, + "x": 0, + "y": 1896 + }, + "hiddenSeries": false, + "id": 72, + "interval": "1m", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "v", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(sum without(instance) (delta(${metric_namespace}_authority_discovery_times_published_total{instance=~\"${nodename}\"}[$__interval])))", + "interval": "", + "legendFormat": "publications", + "refId": "A" + }, + { + "expr": "avg(sum without(instance) (delta(${metric_namespace}_authority_discovery_dht_event_received{instance=~\"${nodename}\", name=\"value_put\"}[$__interval])))", + "interval": "", + "legendFormat": "successes", + "refId": "B" + }, + { + "expr": "avg(sum without(instance) (delta(${metric_namespace}_authority_discovery_dht_event_received{instance=~\"${nodename}\", name=\"value_put_failed\"}[$__interval])))", + "interval": "", + "legendFormat": "failures", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Authority discovery publications, averaged per node", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": "1m", + "schemaVersion": 22, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "allValue": null, + "current": {}, + "datasource": "$data_source", + "definition": "${metric_namespace}_cpu_usage_percentage", + "hide": 0, + "includeAll": true, + "index": -1, + "label": "Instance name filter", + "multi": true, + "name": "nodename", + "options": [], + "query": "${metric_namespace}_cpu_usage_percentage", + "refresh": 1, + "regex": "/instance=\"(.*?)\"/", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "$data_source", + "definition": "${metric_namespace}_sub_libp2p_notifications_sizes_count", + "hide": 2, + "includeAll": true, + "index": -1, + "label": null, + "multi": false, + "name": "notif_protocol", + "options": [], + "query": "${metric_namespace}_sub_libp2p_notifications_sizes_count", + "refresh": 1, + "regex": "/protocol=\"(.*?)\"/", + "skipUrlSync": false, + "sort": 5, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "$data_source", + "definition": "${metric_namespace}_sub_libp2p_requests_out_started_total", + "hide": 2, + "includeAll": true, + "index": -1, + "label": null, + "multi": false, + "name": "request_protocol", + "options": [], + "query": "${metric_namespace}_sub_libp2p_requests_out_started_total", + "refresh": 1, + "regex": "/protocol=\"(.*?)\"/", + "skipUrlSync": false, + "sort": 5, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": false, + "tags": [], + "text": "prometheus.parity-mgmt", + "value": "prometheus.parity-mgmt" + }, + "hide": 0, + "includeAll": false, + "label": "Source of data", + "multi": false, + "name": "data_source", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": { + "value": "${VAR_METRIC_NAMESPACE}", + "text": "${VAR_METRIC_NAMESPACE}" + }, + "hide": 2, + "label": "Prefix of the metrics", + "name": "metric_namespace", + "options": [ + { + "value": "${VAR_METRIC_NAMESPACE}", + "text": "${VAR_METRIC_NAMESPACE}" + } + ], + "query": "${VAR_METRIC_NAMESPACE}", + "skipUrlSync": false, + "type": "constant" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Substrate Networking", + "uid": "vKVuiD9Zk", + "variables": { + "list": [] + }, + "version": 103 +} \ No newline at end of file diff --git a/.maintain/rename-crates-for-2.0.sh b/.maintain/rename-crates-for-2.0.sh index 5d873d26cdfca69db389ae569b6be534d142af1d..01d559448438b3cb857d1b46af2f8bc544232066 100755 --- a/.maintain/rename-crates-for-2.0.sh +++ b/.maintain/rename-crates-for-2.0.sh @@ -64,7 +64,7 @@ TO_RENAME=( "substrate-keyring sp-keyring" "substrate-offchain-primitives sp-offchain" "substrate-panic-handler sp-panic-handler" - "substrate-phragmen sp-phragmen" + "substrate-phragmen sp-npos-elections" "substrate-rpc-primitives sp-rpc" "substrate-runtime-interface sp-runtime-interface" "substrate-runtime-interface-proc-macro sp-runtime-interface-proc-macro" diff --git a/.maintain/sentry-node/docker-compose.yml b/.maintain/sentry-node/docker-compose.yml index db835b057969642c9da77a4bde57c3178745bbd3..2af9449853c771be95d34c8a25aef8adc867d72c 100644 --- a/.maintain/sentry-node/docker-compose.yml +++ b/.maintain/sentry-node/docker-compose.yml @@ -19,6 +19,9 @@ # - validator-a: localhost:9944 # - validator-b: localhost:9945 # - sentry-a: localhost:9946 +# - grafana: localhost:3001 +# - prometheus: localhost:9090 + version: "3.7" services: @@ -44,9 +47,9 @@ services: - "--validator" - "--alice" - "--sentry-nodes" - - "/dns4/sentry-a/tcp/30333/p2p/QmV7EhW6J6KgmNdr558RH1mPx2xGGznW7At4BhXzntRFsi" + - "/dns/sentry-a/tcp/30333/p2p/QmV7EhW6J6KgmNdr558RH1mPx2xGGznW7At4BhXzntRFsi" - "--reserved-nodes" - - "/dns4/sentry-a/tcp/30333/p2p/QmV7EhW6J6KgmNdr558RH1mPx2xGGznW7At4BhXzntRFsi" + - "/dns/sentry-a/tcp/30333/p2p/QmV7EhW6J6KgmNdr558RH1mPx2xGGznW7At4BhXzntRFsi" # Not only bind to localhost. - "--unsafe-ws-external" - "--unsafe-rpc-external" @@ -79,13 +82,12 @@ services: - "--chain=local" - "--port" - "30333" - - "--charlie" - - "--bootnodes" - - "/dns4/validator-a/tcp/30333/p2p/QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR" - - "--bootnodes" - - "/dns4/validator-b/tcp/30333/p2p/QmSVnNf9HwVMT1Y4cK1P6aoJcEZjmoTXpjKBmAABLMnZEk" + - "--sentry" + - "/dns/validator-a/tcp/30333/p2p/QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR" - "--reserved-nodes" - - "/dns4/validator-a/tcp/30333/p2p/QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR" + - "/dns/validator-a/tcp/30333/p2p/QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR" + - "--bootnodes" + - "/dns/validator-b/tcp/30333/p2p/QmSVnNf9HwVMT1Y4cK1P6aoJcEZjmoTXpjKBmAABLMnZEk" - "--no-telemetry" - "--rpc-cors" - "all" @@ -94,7 +96,7 @@ services: - "--unsafe-rpc-external" - "--log" - "sub-authority-discovery=trace" - - "--sentry" + - "--prometheus-external" validator-b: image: parity/substrate @@ -116,9 +118,9 @@ services: - "--validator" - "--bob" - "--bootnodes" - - "/dns4/validator-a/tcp/30333/p2p/QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR" + - "/dns/validator-a/tcp/30333/p2p/QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR" - "--bootnodes" - - "/dns4/sentry-a/tcp/30333/p2p/QmV7EhW6J6KgmNdr558RH1mPx2xGGznW7At4BhXzntRFsi" + - "/dns/sentry-a/tcp/30333/p2p/QmV7EhW6J6KgmNdr558RH1mPx2xGGznW7At4BhXzntRFsi" - "--no-telemetry" - "--rpc-cors" - "all" @@ -127,11 +129,37 @@ services: - "--unsafe-rpc-external" - "--log" - "sub-authority-discovery=trace" + - "--prometheus-external" + + prometheus: + image: prom/prometheus + networks: + - network-a + - internet + ports: + - "9090:9090" + links: + - validator-a:validator-a + - sentry-a:sentry-a + - validator-b:validator-b + volumes: + - ./prometheus/:/etc/prometheus/ + restart: always - ui: - image: polkadot-js/apps + grafana: + image: grafana/grafana + user: "104" + depends_on: + - prometheus + networks: + - network-a + - internet ports: - - "3000:80" + - 3001:3000 + volumes: + - ./grafana/provisioning/:/etc/grafana/provisioning + - ../monitoring/grafana-dashboards/:/etc/grafana/provisioning/dashboard-definitions + restart: always networks: network-a: diff --git a/.maintain/sentry-node/grafana/provisioning/dashboards/dashboards.yml b/.maintain/sentry-node/grafana/provisioning/dashboards/dashboards.yml new file mode 100644 index 0000000000000000000000000000000000000000..ad9164fd8ea01023a2b5736fdea9bfc0259f1eed --- /dev/null +++ b/.maintain/sentry-node/grafana/provisioning/dashboards/dashboards.yml @@ -0,0 +1,11 @@ +apiVersion: 1 + +providers: +- name: 'Prometheus' + orgId: 1 + folder: '' + type: file + disableDeletion: false + editable: false + options: + path: /etc/grafana/provisioning/dashboard-definitions diff --git a/.maintain/sentry-node/grafana/provisioning/datasources/datasource.yml b/.maintain/sentry-node/grafana/provisioning/datasources/datasource.yml new file mode 100644 index 0000000000000000000000000000000000000000..c02bb38b3d378112480b0772855e79b0f02cb02f --- /dev/null +++ b/.maintain/sentry-node/grafana/provisioning/datasources/datasource.yml @@ -0,0 +1,50 @@ +# config file version +apiVersion: 1 + +# list of datasources that should be deleted from the database +deleteDatasources: + - name: Prometheus + orgId: 1 + +# list of datasources to insert/update depending +# whats available in the database +datasources: + # name of the datasource. Required +- name: Prometheus + # datasource type. Required + type: prometheus + # access mode. direct or proxy. Required + access: proxy + # org id. will default to orgId 1 if not specified + orgId: 1 + # url + url: http://prometheus:9090 + # database password, if used + password: + # database user, if used + user: + # database name, if used + database: + # enable/disable basic auth + basicAuth: false + # basic auth username, if used + basicAuthUser: + # basic auth password, if used + basicAuthPassword: + # enable/disable with credentials headers + withCredentials: + # mark as default datasource. Max one per org + isDefault: true + # fields that will be converted to json and stored in json_data + jsonData: + graphiteVersion: "1.1" + tlsAuth: false + tlsAuthWithCACert: false + # json object of data that will be encrypted. + secureJsonData: + tlsCACert: "..." + tlsClientCert: "..." + tlsClientKey: "..." + version: 1 + # allow users to edit datasources from the UI. + editable: true diff --git a/.maintain/sentry-node/prometheus/prometheus.yml b/.maintain/sentry-node/prometheus/prometheus.yml new file mode 100644 index 0000000000000000000000000000000000000000..547d4bea57ae5c55f210743165b347dd732ec0de --- /dev/null +++ b/.maintain/sentry-node/prometheus/prometheus.yml @@ -0,0 +1,15 @@ +global: + scrape_interval: 15s + +scrape_configs: + - job_name: 'substrate-nodes' + static_configs: + - targets: ['validator-a:9615'] + labels: + network: dev + - targets: ['sentry-a:9615'] + labels: + network: dev + - targets: ['validator-b:9615'] + labels: + network: dev diff --git a/Cargo.lock b/Cargo.lock index 6038064ab0b44b05a917e72950700c33f8d9d56a..0b24f9ef5721892e2be3e1d5e5b7342660d2b169 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,6 +16,26 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" +[[package]] +name = "aead" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cf01b9b56e767bb57b94ebf91a58b338002963785cdd7013e21c0d4679471e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "aes" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54eb1d8fe354e5fc611daf4f2ea97dd45a765f4f1e4512306ec183ae2e8f20c9" +dependencies = [ + "aes-soft", + "aesni", + "block-cipher-trait", +] + [[package]] name = "aes-ctr" version = "0.3.0" @@ -28,6 +48,20 @@ dependencies = [ "stream-cipher", ] +[[package]] +name = "aes-gcm" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "834a6bda386024dbb7c8fc51322856c10ffe69559f972261c868485f5759c638" +dependencies = [ + "aead", + "aes", + "block-cipher-trait", + "ghash", + "subtle 2.2.2", + "zeroize", +] + [[package]] name = "aes-soft" version = "0.3.3" @@ -35,7 +69,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfd7e7ae3f9a1fb5c03b389fc6bb9a51400d0c13053f0dca698c832bfd893a0d" dependencies = [ "block-cipher-trait", - "byteorder 1.3.4", + "byteorder", "opaque-debug", ] @@ -59,6 +93,12 @@ dependencies = [ "const-random", ] +[[package]] +name = "ahash" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217" + [[package]] name = "aho-corasick" version = "0.7.10" @@ -70,12 +110,11 @@ dependencies = [ [[package]] name = "alga" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658f9468113d34781f6ca9d014d174c74b73de870f1e0e3ad32079bbab253b19" +checksum = "4f823d037a7ec6ea2197046bafd4ae150e6bc36f9ca347404f46a46823fa84f2" dependencies = [ "approx", - "libm", "num-complex", "num-traits 0.2.11", ] @@ -100,21 +139,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.26" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c" - -[[package]] -name = "app_dirs" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e73a24bad9bd6a94d6395382a6c69fe071708ae4409f763c5475e14ee896313d" -dependencies = [ - "ole32-sys", - "shell32-sys", - "winapi 0.2.8", - "xdg", -] +checksum = "d9a60d744a80c30fcb657dfe2c1b22bcb3e814c1a1e3674f32bf5820b570fbff" [[package]] name = "approx" @@ -133,9 +160,9 @@ checksum = "75153c95fdedd7db9732dfbfc3702324a1627eec91ba56e37cd0ac78314ab2ed" [[package]] name = "arc-swap" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7b8a9123b8027467bce0099fe556c628a53c8d83df0507084c31e9ba2e39aff" +checksum = "d663a8e9a99154b5fb793032533f6328da35e23aac63d5c152279aa8ba356825" [[package]] name = "arrayref" @@ -173,8 +200,8 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d0864d84b8e07b145449be9a8537db86bf9de5ce03b913214694643b4743502" dependencies = [ - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] @@ -198,50 +225,44 @@ checksum = "7deb0a829ca7bcfaf5da70b073a8d128619259a7be8216a355e23f00763059e5" [[package]] name = "async-std" -version = "1.5.0" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "538ecb01eb64eecd772087e5b6f7540cbc917f047727339a472dafed2185b267" +checksum = "00d68a33ebc8b57800847d00787307f84a562224a14db069b0acefe4c2abbf5d" dependencies = [ "async-task", - "broadcaster", - "crossbeam-channel", - "crossbeam-deque", "crossbeam-utils", + "futures-channel", "futures-core", "futures-io", - "futures-timer 2.0.2", + "futures-timer 3.0.2", "kv-log-macro", "log", "memchr", - "mio", - "mio-uds", "num_cpus", "once_cell", "pin-project-lite", "pin-utils", "slab", + "smol", + "wasm-bindgen-futures", ] [[package]] name = "async-task" -version = "1.3.1" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ac2c016b079e771204030951c366db398864f5026f84a44dafb0ff20f02085d" -dependencies = [ - "libc", - "winapi 0.3.8", -] +checksum = "c17772156ef2829aadc587461c7753af20b7e8db1529bc66855add962a3b35d3" [[package]] name = "async-tls" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce6977f57fa68da77ffe5542950d47e9c23d65f5bc7cb0a9f8700996913eec7" +checksum = "95fd83426b89b034bf4e9ceb9c533c2f2386b813fd3dcae0a425ec6f1837d78a" dependencies = [ - "futures 0.3.4", - "rustls 0.16.0", + "futures 0.3.5", + "rustls", "webpki", - "webpki-roots 0.17.0", + "webpki-roots 0.19.0", ] [[package]] @@ -269,9 +290,9 @@ checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" [[package]] name = "backtrace" -version = "0.3.45" +version = "0.3.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad235dabf00f36301792cfe82499880ba54c6486be094d1047b02bacb67c14e8" +checksum = "b1e692897359247cc6bb902933361652380af0f1b7651ae5c5013407f30e109e" dependencies = [ "backtrace-sys", "cfg-if", @@ -281,9 +302,9 @@ dependencies = [ [[package]] name = "backtrace-sys" -version = "0.1.34" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca797db0057bae1a7aa2eef3283a874695455cecf08a43bfb8507ee0ebc1ed69" +checksum = "7de8aba10a69c8e8d7622c5710229485ec32e9d55fdad160ea559c086fdcd118" dependencies = [ "cc", "libc", @@ -297,18 +318,15 @@ checksum = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" [[package]] name = "base64" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -dependencies = [ - "byteorder 1.3.4", -] +checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" [[package]] name = "base64" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" +checksum = "7d5ca2cd0adc3f48f9e9ea5a6bbdf9ccc0bfade884847e484d452414c7ccffb3" [[package]] name = "bincode" @@ -316,7 +334,7 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf" dependencies = [ - "byteorder 1.3.4", + "byteorder", "serde", ] @@ -337,7 +355,7 @@ dependencies = [ "log", "peeking_take_while", "proc-macro2", - "quote 1.0.3", + "quote 1.0.6", "regex", "rustc-hash", "shlex", @@ -399,6 +417,17 @@ dependencies = [ "constant_time_eq", ] +[[package]] +name = "blake2s_simd" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab9e07352b829279624ceb7c64adb4f585dacdb81d35cafae81139ccd617cf44" +dependencies = [ + "arrayref", + "arrayvec 0.5.1", + "constant_time_eq", +] + [[package]] name = "block-buffer" version = "0.7.3" @@ -407,7 +436,7 @@ checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" dependencies = [ "block-padding", "byte-tools", - "byteorder 1.3.4", + "byteorder", "generic-array", ] @@ -430,30 +459,29 @@ dependencies = [ ] [[package]] -name = "broadcaster" -version = "1.0.0" +name = "blocking" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c972e21e0d055a36cf73e4daae870941fe7a8abcd5ac3396aab9e4c126bd87" +checksum = "9d17efb70ce4421e351d61aafd90c16a20fb5bfe339fcdc32a86816280e62ce0" dependencies = [ "futures-channel", - "futures-core", - "futures-sink", "futures-util", - "parking_lot 0.10.0", - "slab", + "once_cell", + "parking", + "waker-fn", ] [[package]] name = "bs58" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b170cd256a3f9fa6b9edae3e44a7dfdfc77e8124dbc3e2612d75f9c3e2396dae" +checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb" [[package]] name = "bstr" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "502ae1441a0a5adb8fbd38a5955a6416b9493e92b465de5e4a9bde6a539c2c48" +checksum = "2889e6d50f394968c8bf4240dc3f2a7eb4680844d27308f798229ac9d4725f41" dependencies = [ "lazy_static", "memchr", @@ -488,12 +516,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" -[[package]] -name = "byteorder" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" - [[package]] name = "byteorder" version = "1.3.4" @@ -506,7 +528,7 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" dependencies = [ - "byteorder 1.3.4", + "byteorder", "either", "iovec", ] @@ -523,11 +545,17 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4964518bd3b4a8190e832886cdc0da9794f12e8e6c1613a9e90ff331c4c8724b" +[[package]] +name = "cache-padded" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24508e28c677875c380c20f4d28124fab6f8ed4ef929a1397d7b1a31e92f1005" + [[package]] name = "cargo_metadata" -version = "0.9.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46e3374c604fb39d1a2f35ed5e4a4e30e60d01fab49446e08f1b3e9a90aef202" +checksum = "b8de60b887edf6d74370fc8eb177040da4847d971d6234c7b13a6da324ef0caf" dependencies = [ "semver 0.9.0", "serde", @@ -569,21 +597,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] -name = "chacha20-poly1305-aead" -version = "0.1.2" +name = "chacha20" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77d2058ba29594f69c75e8a9018e0485e3914ca5084e3613cd64529042f5423b" +checksum = "f6a7ae4c498f8447d86baef0fa0831909333f558866fabcb21600625ac5a31c7" dependencies = [ - "constant_time_eq", + "stream-cipher", + "zeroize", +] + +[[package]] +name = "chacha20poly1305" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48901293601228db2131606f741db33561f7576b5d19c99cd66222380a7dc863" +dependencies = [ + "aead", + "chacha20", + "poly1305", + "stream-cipher", + "zeroize", ] [[package]] name = "chain-spec-builder" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "ansi_term 0.12.1", "node-cli", "rand 0.7.3", + "sc-chain-spec", "sc-keystore", "sp-core", "structopt", @@ -604,9 +647,9 @@ dependencies = [ [[package]] name = "clang-sys" -version = "0.29.2" +version = "0.29.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f92986241798376849e1a007827041fed9bb36195822c2049d18e174420e0534" +checksum = "fe6837df1d5cba2397b835c8530f51723267e16abbf83892e9e5af4f0e5dd10a" dependencies = [ "glob 0.3.0", "libc", @@ -655,6 +698,15 @@ dependencies = [ "cc", ] +[[package]] +name = "concurrent-queue" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83c06aff61f2d899eb87c379df3cbf7876f14471dcab474e0b6dc90ab96c080" +dependencies = [ + "cache-padded", +] + [[package]] name = "console_error_panic_hook" version = "0.1.6" @@ -719,37 +771,38 @@ checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" [[package]] name = "cranelift-bforest" -version = "0.59.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a9c21f8042b9857bda93f6c1910b9f9f24100187a3d3d52f214a34e3dc5818" +checksum = "d4425bb6c3f3d2f581c650f1a1fdd3196a975490149cf59bea9d34c3bea79eda" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.59.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7853f77a6e4a33c67a69c40f5e1bb982bd2dc5c4a22e17e67b65bbccf9b33b2e" +checksum = "d166b289fd30062ee6de86284750fc3fe5d037c6b864b3326ce153239b0626e1" dependencies = [ - "byteorder 1.3.4", + "byteorder", "cranelift-bforest", "cranelift-codegen-meta", "cranelift-codegen-shared", "cranelift-entity", "gimli", "log", + "regalloc", "serde", - "smallvec 1.2.0", + "smallvec 1.4.1", "target-lexicon", "thiserror", ] [[package]] name = "cranelift-codegen-meta" -version = "0.59.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084cd6d5fb0d1da28acd72c199471bfb09acc703ec8f3bf07b1699584272a3b9" +checksum = "02c9fb2306a36d41c5facd4bf3400bc6c157185c43a96eaaa503471c34c5144b" dependencies = [ "cranelift-codegen-shared", "cranelift-entity", @@ -757,36 +810,36 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.59.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "701b599783305a58c25027a4d73f2d6b599b2d8ef3f26677275f480b4d51e05d" +checksum = "44e0cfe9b1f97d9f836bca551618106c7d53b93b579029ecd38e73daa7eb689e" [[package]] name = "cranelift-entity" -version = "0.59.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b88e792b28e1ebbc0187b72ba5ba880dad083abe9231a99d19604d10c9e73f38" +checksum = "926a73c432e5ba9c891171ff50b75e7d992cd76cd271f0a0a0ba199138077472" dependencies = [ "serde", ] [[package]] name = "cranelift-frontend" -version = "0.59.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "518344698fa6c976d853319218415fdfb4f1bc6b42d0b2e2df652e55dff1f778" +checksum = "e45f82e3446dd1ebb8c2c2f6a6b0e6cd6cd52965c7e5f7b1b35e9a9ace31ccde" dependencies = [ "cranelift-codegen", "log", - "smallvec 1.2.0", + "smallvec 1.4.1", "target-lexicon", ] [[package]] name = "cranelift-native" -version = "0.59.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32daf082da21c0c05d93394ff4842c2ab7c4991b1f3186a1d952f8ac660edd0b" +checksum = "488b5d481bb0996a143e55a9d1739ef425efa20d4a5e5e98c859a8573c9ead9a" dependencies = [ "cranelift-codegen", "raw-cpuid", @@ -795,9 +848,9 @@ dependencies = [ [[package]] name = "cranelift-wasm" -version = "0.59.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2aa816f554a3ef739a5d17ca3081a1f8983f04c944ea8ff60fb8d9dd8cd2d7b" +checksum = "00aa8dde71fd9fdb1958e7b0ef8f524c1560e2c6165e4ea54bc302b40551c161" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -805,7 +858,7 @@ dependencies = [ "log", "serde", "thiserror", - "wasmparser", + "wasmparser 0.51.4", ] [[package]] @@ -828,7 +881,7 @@ dependencies = [ "clap", "criterion-plot 0.3.1", "csv", - "itertools", + "itertools 0.8.2", "lazy_static", "libc", "num-traits 0.2.11", @@ -855,7 +908,7 @@ dependencies = [ "clap", "criterion-plot 0.4.1", "csv", - "itertools", + "itertools 0.8.2", "lazy_static", "num-traits 0.2.11", "oorandom", @@ -875,9 +928,9 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76f9212ddf2f4a9eb2d401635190600656a1f88a932ef53d06e7fa4c7e02fb8e" dependencies = [ - "byteorder 1.3.4", + "byteorder", "cast", - "itertools", + "itertools 0.8.2", ] [[package]] @@ -887,17 +940,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a01e15e0ea58e8234f96146b1f91fa9d0e4dd7a38da93ff7a75d42c0b9d3a545" dependencies = [ "cast", - "itertools", -] - -[[package]] -name = "crossbeam-channel" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061" -dependencies = [ - "crossbeam-utils", - "maybe-uninit", + "itertools 0.8.2", ] [[package]] @@ -1000,8 +1043,8 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47c5e5ac752e18207b12e16b10631ae5f7f68f8805f335f9b817ead83d9ffce1" dependencies = [ - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] @@ -1014,23 +1057,13 @@ dependencies = [ "stream-cipher", ] -[[package]] -name = "cuckoofilter" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dd43f7cfaffe0a386636a10baea2ee05cc50df3b77bea4a456c9572a939bf1f" -dependencies = [ - "byteorder 0.5.3", - "rand 0.3.23", -] - [[package]] name = "curve25519-dalek" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26778518a7f6cffa1d25a44b602b62b979bd88adb9e99ffec546998cf3404839" dependencies = [ - "byteorder 1.3.4", + "byteorder", "digest", "rand_core 0.5.1", "subtle 2.2.2", @@ -1045,13 +1078,13 @@ checksum = "11c0346158a19b3627234e15596f5e465c360fcdb97d817bcb255e0510f5a788" [[package]] name = "derive_more" -version = "0.99.3" +version = "0.99.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a806e96c59a76a5ba6e18735b6cf833344671e61e7863f2edb5c518ea2cac95c" +checksum = "e2323f3f47db9a0e77ce7a300605d8d2098597fc451ed1a97bb1f6411bb550a7" dependencies = [ "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] @@ -1097,15 +1130,15 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4d33be9473d06f75f58220f71f7a9317aca647dc061dbd3c361b0bef505fbea" dependencies = [ - "byteorder 1.3.4", + "byteorder", "quick-error", ] [[package]] name = "doc-comment" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "807e5847c39ad6a11eac66de492ed1406f76a260eb8656e8740cad9eabc69c27" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "ed25519-dalek" @@ -1138,22 +1171,22 @@ dependencies = [ [[package]] name = "enumflags2" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33121c8782ba948ba332dab29311b026a8716dc65a1599e5b88f392d38496af8" +checksum = "a80e524ebf194285b57e5e7944018721c7fffc673253f5183f7accd88a2a3b0c" dependencies = [ "enumflags2_derive", ] [[package]] name = "enumflags2_derive" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecf634c5213044b8d54a46dd282cf5dd1f86bb5cb53e92c409cb4680a7fb9894" +checksum = "2ed9afacaea0301eefb738c9deea725e6d53938004597cdc518a8cf9a7aa2f03" dependencies = [ "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] @@ -1190,18 +1223,18 @@ checksum = "516aa8d7a71cb00a1c4146f0798549b93d083d4f189b3ced8f3de6b8f11ee6c4" [[package]] name = "erased-serde" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7d80305c9bd8cd78e3c753eb9fb110f83621e5211f1a3afffcc812b104daf9" +checksum = "d88b6d1705e16a4d62e05ea61cc0496c2bd190f4fa8e5c1f11ce747be6bcf3d1" dependencies = [ "serde", ] [[package]] name = "errno" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e" +checksum = "b480f641ccf0faf324e20c1d3e53d81b7484c698b42ea677f6907ae4db195371" dependencies = [ "errno-dragonfly", "libc", @@ -1220,22 +1253,22 @@ dependencies = [ [[package]] name = "ethbloom" -version = "0.9.0" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e7abcddbdd5db30aeed4deb586adc4824e6c247e2f7238d1187f752893f096b" +checksum = "71a6567e6fd35589fea0c63b94b4cf2e55573e413901bdbe60ab15cf0e25e5df" dependencies = [ "crunchy", "fixed-hash", "impl-rlp", "impl-serde 0.3.0", - "tiny-keccak 2.0.1", + "tiny-keccak 2.0.2", ] [[package]] name = "ethereum-types" -version = "0.9.0" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "964c23cdee0ca07d5be2a628b46d5c11a2134ce554a8c16d8dbc2db647e4fd4d" +checksum = "473aecff686bd8e7b9db0165cbbb53562376b39bf35b427f0c60446a9e1634b0" dependencies = [ "ethbloom", "fixed-hash", @@ -1297,16 +1330,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e43f2f1833d64e33f15592464d6fdd70f349dda7b1a53088eb83cd94014008c5" dependencies = [ - "futures 0.3.4", + "futures 0.3.5", ] [[package]] name = "faerie" -version = "0.14.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74b9ed6159e4a6212c61d9c6a86bee01876b192a64accecf58d5b5ae3b667b52" +checksum = "dfef65b0e94693295c5d2fe2506f0ee6f43465342d4b5331659936aee8b16084" dependencies = [ - "anyhow", "goblin", "indexmap", "log", @@ -1333,8 +1365,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "030a733c8287d6213886dd487564ff5c8f6aae10278b3588ed177f9d18f8d231" dependencies = [ "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", "synstructure", ] @@ -1350,6 +1382,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +[[package]] +name = "fastrand" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b90eb1dec02087df472ab9f0db65f27edaa654a746830042688bcc2eaf68090f" + [[package]] name = "fdlimit" version = "0.1.4" @@ -1371,11 +1409,12 @@ dependencies = [ [[package]] name = "finality-grandpa" -version = "0.11.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "024517816630be5204eba201e8d1d405042b1255a5e0e3f298b054fc24d59e1d" +checksum = "8feb87a63249689640ac9c011742c33139204e3c134293d3054022276869133b" dependencies = [ - "futures 0.3.4", + "either", + "futures 0.3.5", "futures-timer 2.0.2", "log", "num-traits 0.2.11", @@ -1390,7 +1429,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32529fc42e86ec06e5047092082aab9ad459b070c5d2a76b14f4f5ce70bf2e84" dependencies = [ - "byteorder 1.3.4", + "byteorder", "rand 0.7.3", "rustc-hex", "static_assertions", @@ -1404,9 +1443,9 @@ checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" [[package]] name = "flate2" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bd6d6f4752952feb71363cffc9ebac9411b75b87c6ab6058c40c8900cf43c0f" +checksum = "2cfff41391129e0a856d6d822600b8d71179d46879e310417eb9c762eb178b42" dependencies = [ "cfg-if", "crc32fast", @@ -1423,19 +1462,20 @@ checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" [[package]] name = "fork-tree" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "parity-scale-codec", ] [[package]] name = "frame-benchmarking" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-support", "frame-system", "linregress", "parity-scale-codec", + "paste", "sp-api", "sp-io", "sp-runtime", @@ -1445,12 +1485,12 @@ dependencies = [ [[package]] name = "frame-benchmarking-cli" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ + "Inflector", "frame-benchmarking", "parity-scale-codec", "sc-cli", - "sc-client", "sc-client-db", "sc-executor", "sc-service", @@ -1463,7 +1503,7 @@ dependencies = [ [[package]] name = "frame-executive" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-support", "frame-system", @@ -1477,12 +1517,13 @@ dependencies = [ "sp-io", "sp-runtime", "sp-std", + "sp-tracing", "sp-version", ] [[package]] name = "frame-metadata" -version = "11.0.0-alpha.5" +version = "11.0.0-rc4" dependencies = [ "parity-scale-codec", "serde", @@ -1492,7 +1533,7 @@ dependencies = [ [[package]] name = "frame-support" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "bitmask", "frame-metadata", @@ -1502,9 +1543,11 @@ dependencies = [ "log", "once_cell", "parity-scale-codec", + "parity-util-mem 0.7.0", "paste", "pretty_assertions", "serde", + "smallvec 1.4.1", "sp-arithmetic", "sp-core", "sp-inherents", @@ -1512,58 +1555,60 @@ dependencies = [ "sp-runtime", "sp-state-machine", "sp-std", - "tracing", + "sp-tracing", ] [[package]] name = "frame-support-procedural" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-support-procedural-tools", "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] name = "frame-support-procedural-tools" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-support-procedural-tools-derive", "proc-macro-crate", "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] name = "frame-support-procedural-tools-derive" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] name = "frame-support-test" -version = "2.0.0-dev" +version = "2.0.0-rc4" dependencies = [ "frame-support", "parity-scale-codec", "pretty_assertions", + "rustversion", "serde", "sp-core", "sp-inherents", "sp-io", "sp-runtime", "sp-state-machine", + "sp-std", "trybuild", ] [[package]] name = "frame-system" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "criterion 0.2.11", "frame-support", @@ -1579,9 +1624,24 @@ dependencies = [ "substrate-test-runtime-client", ] +[[package]] +name = "frame-system-benchmarking" +version = "2.0.0-rc4" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "frame-system-rpc-runtime-api" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "parity-scale-codec", "sp-api", @@ -1645,9 +1705,9 @@ checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" [[package]] name = "futures" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c329ae8753502fb44ae4fc2b622fa2a94652c41e795143765ba0927f92ab780" +checksum = "1e05b85ec287aac0dc34db7d4a569323df697f9c55b99b15d6b4ef8cde49f613" dependencies = [ "futures-channel", "futures-core", @@ -1660,9 +1720,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c77d04ce8edd9cb903932b608268b3fffec4163dc053b3b402bf47eac1f1a8" +checksum = "f366ad74c28cca6ba456d95e6422883cfb4b252a83bed929c83abfdbbf2967d5" dependencies = [ "futures-core", "futures-sink", @@ -1679,9 +1739,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a" +checksum = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399" [[package]] name = "futures-core-preview" @@ -1706,7 +1766,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdcef58a173af8148b182684c9f2d5250875adbcaff7b5794073894f9d8634a9" dependencies = [ "futures 0.1.29", - "futures 0.3.4", + "futures 0.3.5", "lazy_static", "log", "parking_lot 0.9.0", @@ -1717,9 +1777,9 @@ dependencies = [ [[package]] name = "futures-executor" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f674f3e1bcb15b37284a90cedf55afdba482ab061c407a9c0ebbd0f3109741ba" +checksum = "10d6bb888be1153d3abeb9006b11b02cf5e9b209fda28693c31ae1e4e012e314" dependencies = [ "futures-core", "futures-task", @@ -1729,33 +1789,36 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a638959aa96152c7a4cddf50fcb1e3fede0583b27157c26e67d6f99904090dc6" +checksum = "de27142b013a8e869c14957e6d2edeef89e97c289e69d042ee3a49acd8b51789" [[package]] name = "futures-macro" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a5081aa3de1f7542a794a397cde100ed903b0630152d0973479018fd85423a7" +checksum = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39" dependencies = [ "proc-macro-hack", "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] name = "futures-sink" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3466821b4bc114d95b087b850a724c6f83115e929bc88f1fa98a3304a944c8a6" +checksum = "3f2032893cb734c7a05d85ce0cc8b8c4075278e93b24b66f9de99d6eb0fa8acc" [[package]] name = "futures-task" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0a34e53cf6cdcd0178aa573aed466b646eb3db769570841fda0c7ede375a27" +checksum = "bdb66b5f09e22019b1ab0830f7785bcea8e7a42148683f99214f73f8ec21a626" +dependencies = [ + "once_cell", +] [[package]] name = "futures-timer" @@ -1775,9 +1838,9 @@ dependencies = [ [[package]] name = "futures-util" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22766cf25d64306bedf0384da004d05c9974ab104fcc4528f1236181c18004c5" +checksum = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6" dependencies = [ "futures 0.1.29", "futures-channel", @@ -1787,11 +1850,11 @@ dependencies = [ "futures-sink", "futures-task", "memchr", + "pin-project", "pin-utils", "proc-macro-hack", "proc-macro-nested", "slab", - "tokio-io", ] [[package]] @@ -1808,12 +1871,12 @@ dependencies = [ [[package]] name = "futures_codec" -version = "0.3.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0a73299e4718f5452e45980fc1d6957a070abe308d3700b63b8673f47e1c2b3" +checksum = "ce54d63f8b0c75023ed920d46fd71d0cbbb830b0ee012726b5b4f506fb6dea5b" dependencies = [ "bytes 0.5.4", - "futures 0.3.4", + "futures 0.3.5", "memchr", "pin-project", ] @@ -1867,6 +1930,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "ghash" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f0930ed19a7184089ea46d2fedead2f6dc2b674c5db4276b7da336c7cd83252" +dependencies = [ + "polyval", +] + [[package]] name = "gimli" version = "0.20.0" @@ -1874,10 +1946,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81dd6190aad0f05ddbbf3245c54ed14ca4aa6dd32f22312b70d8f168c3e3e633" dependencies = [ "arrayvec 0.5.1", - "byteorder 1.3.4", + "byteorder", "fallible-iterator", "indexmap", - "smallvec 1.2.0", + "smallvec 1.4.1", "stable_deref_trait", ] @@ -1895,9 +1967,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "globset" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" +checksum = "7ad1da430bd7281dde2576f44c84cc3f0f7b475e7202cd503042dff01a8c8120" dependencies = [ "aho-corasick", "bstr", @@ -1936,7 +2008,7 @@ version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" dependencies = [ - "byteorder 1.3.4", + "byteorder", "bytes 0.4.12", "fnv", "futures 0.1.29", @@ -1950,20 +2022,20 @@ dependencies = [ [[package]] name = "h2" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5c295d1c0c68e4e42003d75f908f5e16a1edd1cbe0b0d02e4dc2006a384f47" +checksum = "377038bf3c89d18d6ca1431e7a5027194fbd724ca10592b9487ede5e8e144f42" dependencies = [ "bytes 0.5.4", "fnv", "futures-core", "futures-sink", "futures-util", - "http 0.2.0", + "http 0.2.1", "indexmap", "log", "slab", - "tokio 0.2.13", + "tokio 0.2.18", "tokio-util", ] @@ -1988,10 +2060,20 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e6073d0ca812575946eb5f35ff68dbe519907b25c42530389ff946dc84c6ead" dependencies = [ - "ahash", + "ahash 0.2.18", "autocfg 0.1.7", ] +[[package]] +name = "hashbrown" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab9b7860757ce258c89fd48d28b68c41713e597a7b09e793f6c6a6e2ea37c827" +dependencies = [ + "ahash 0.3.8", + "autocfg 1.0.0", +] + [[package]] name = "heck" version = "0.3.1" @@ -2003,9 +2085,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.8" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1010591b26bbfe835e9faeabeb11866061cc7dcebffd56ad7d0942d0e61aefd8" +checksum = "725cf19794cf90aa94e65050cb4191ff5d8fa87a498383774c47b332e3af952e" dependencies = [ "libc", ] @@ -2058,9 +2140,9 @@ dependencies = [ [[package]] name = "honggfuzz" -version = "0.5.47" +version = "0.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3de2c3273ef7735df1c5a72128ca85b1d20105b9aac643cdfd7a6e581311150" +checksum = "832bac18a82ec7d6c21887daa8616b238fe90d5d5e762d0d4b9372cdaa9e097f" dependencies = [ "arbitrary", "lazy_static", @@ -2080,9 +2162,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b708cc7f06493459026f53b9a61a7a121a5d1ec6238dee58ea4941132b30156b" +checksum = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9" dependencies = [ "bytes 0.5.4", "fnv", @@ -2108,7 +2190,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" dependencies = [ "bytes 0.5.4", - "http 0.2.0", + "http 0.2.1", ] [[package]] @@ -2158,16 +2240,16 @@ dependencies = [ [[package]] name = "hyper" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7b15203263d1faa615f9337d79c1d37959439dc46c2b4faab33286fadc2a1c5" +checksum = "ed6081100e960d9d74734659ffc9cc91daf1c0fc7aceb8eaa94ee1a3f5046f2e" dependencies = [ "bytes 0.5.4", "futures-channel", "futures-core", "futures-util", - "h2 0.2.2", - "http 0.2.0", + "h2 0.2.4", + "http 0.2.1", "http-body 0.3.1", "httparse", "itoa", @@ -2175,7 +2257,7 @@ dependencies = [ "net2", "pin-project", "time", - "tokio 0.2.13", + "tokio 0.2.18", "tower-service", "want 0.3.0", ] @@ -2189,11 +2271,11 @@ dependencies = [ "bytes 0.5.4", "ct-logs", "futures-util", - "hyper 0.13.3", + "hyper 0.13.4", "log", - "rustls 0.17.0", + "rustls", "rustls-native-certs", - "tokio 0.2.13", + "tokio 0.2.18", "tokio-rustls", "webpki", ] @@ -2263,8 +2345,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef5550a42e3740a0e71f909d4c861056a284060af885ae7aa6242820f920d9d" dependencies = [ "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] @@ -2282,19 +2364,13 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f65877bf7d44897a473350b1046277941cee20b263397e90869c50b6e766088b" -[[package]] -name = "interleaved-ordered" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "141340095b15ed7491bd3d4ced9d20cebfb826174b6bb03386381f62b01e3d77" - [[package]] name = "intervalier" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14200459dc2319eb13708aed1c1efb8307e0e0e801e7282476939492e1492631" +checksum = "64fa110ec7b8f493f416eed552740d10e7030ad5f63b2308f82c9608ec2df275" dependencies = [ - "futures 0.3.4", + "futures 0.3.5", "futures-timer 2.0.2", ] @@ -2307,11 +2383,17 @@ dependencies = [ "libc", ] +[[package]] +name = "ip_network" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ee15951c035f79eddbef745611ec962f63f4558f1dadf98ab723cc603487c6f" + [[package]] name = "ipnet" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a859057dc563d1388c1e816f98a1892629075fc046ed06e845b883bb8b2916fb" +checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" [[package]] name = "itertools" @@ -2322,6 +2404,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "0.4.5" @@ -2339,18 +2430,18 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cb931d43e71f560c81badb0191596562bafad2be06a3f9025b845c847c60df5" +checksum = "6a27d435371a2fa5b6d2b028a74bbdb1234f308da363226a2854ca3ff8ba7055" dependencies = [ "wasm-bindgen", ] [[package]] name = "jsonrpc-client-transports" -version = "14.0.5" +version = "14.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a9ae166c4d1f702d297cd76d4b55758ace80272ffc6dbb139fdc1bf810de40b" +checksum = "ecbdaacc17243168d9d1fa6b2bd7556a27e1e60a621d8a2a6e590ae2b145d158" dependencies = [ "failure", "futures 0.1.29", @@ -2365,9 +2456,9 @@ dependencies = [ [[package]] name = "jsonrpc-core" -version = "14.0.5" +version = "14.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe3b688648f1ef5d5072229e2d672ecb92cbff7d1c79bcf3fd5898f3f3df0970" +checksum = "a0747307121ffb9703afd93afbd0fb4f854c38fb873f2c8b90e0e902f27c7b62" dependencies = [ "futures 0.1.29", "log", @@ -2378,57 +2469,72 @@ dependencies = [ [[package]] name = "jsonrpc-core-client" -version = "14.0.5" +version = "14.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080dc110be17701097df238fad3c816d4a478a1899dfbcf8ec8957dd40ec7304" +checksum = "34221123bc79b66279a3fde2d3363553835b43092d629b34f2e760c44dc94713" dependencies = [ "jsonrpc-client-transports", ] [[package]] name = "jsonrpc-derive" -version = "14.0.5" +version = "14.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8609af8f63b626e8e211f52441fcdb6ec54f1a446606b10d5c89ae9bf8a20058" +checksum = "0fadf6945e227246825a583514534d864554e9f23d80b3c77d034b10983db5ef" dependencies = [ "proc-macro-crate", "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] name = "jsonrpc-http-server" -version = "14.0.6" +version = "14.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "816d63997ea45d3634608edbef83ddb35e661f7c0b27b5b72f237e321f0e9807" +checksum = "0da906d682799df05754480dac1b9e70ec92e12c19ebafd2662a5ea1c9fd6522" dependencies = [ "hyper 0.12.35", "jsonrpc-core", "jsonrpc-server-utils", "log", "net2", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "unicase", ] +[[package]] +name = "jsonrpc-ipc-server" +version = "14.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dedccd693325d833963b549e959137f30a7a0ea650cde92feda81dc0c1393cb5" +dependencies = [ + "jsonrpc-core", + "jsonrpc-server-utils", + "log", + "parity-tokio-ipc", + "parking_lot 0.10.2", + "tokio-service", +] + [[package]] name = "jsonrpc-pubsub" -version = "14.0.6" +version = "14.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b31c9b90731276fdd24d896f31bb10aecf2e5151733364ae81123186643d939" +checksum = "2d44f5602a11d657946aac09357956d2841299ed422035edf140c552cb057986" dependencies = [ "jsonrpc-core", "log", - "parking_lot 0.10.0", + "parking_lot 0.10.2", + "rand 0.7.3", "serde", ] [[package]] name = "jsonrpc-server-utils" -version = "14.0.5" +version = "14.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b7635e618a0edbbe0d2a2bbbc69874277c49383fcf6c3c0414491cfb517d22" +checksum = "56cbfb462e7f902e21121d9f0d1c2b77b2c5b642e1a4e8f4ebfa2e15b94402bb" dependencies = [ "bytes 0.4.12", "globset", @@ -2442,14 +2548,14 @@ dependencies = [ [[package]] name = "jsonrpc-ws-server" -version = "14.0.6" +version = "14.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94e5773b2ae66e0e02c80775ce6bbba6f15d5bb47c14ec36a36fcf94f8df851" +checksum = "903d3109fe7c4acb932b567e1e607e0f524ed04741b09fb0e61841bc40a022fc" dependencies = [ "jsonrpc-core", "jsonrpc-server-utils", "log", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "slab", "ws", ] @@ -2492,56 +2598,76 @@ dependencies = [ [[package]] name = "kvdb" -version = "0.5.0" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e763b2a9b500ba47948061d1e8bc3b5f03a8a1f067dbcf822a4d2c84d2b54a3a" +dependencies = [ + "parity-util-mem 0.6.0", + "smallvec 1.4.1", +] + +[[package]] +name = "kvdb" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cad096c6849b2ef027fabe35c4aed356d0e3d3f586d0a8361e5e17f1e50a7ce5" +checksum = "0315ef2f688e33844400b31f11c263f2b3dc21d8b9355c6891c5f185fae43f9a" dependencies = [ - "parity-util-mem", - "smallvec 1.2.0", + "parity-util-mem 0.7.0", + "smallvec 1.4.1", ] [[package]] name = "kvdb-memorydb" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4aa954d12cfac958822dfd77aab34f3eec71f103b918c4ab79ab59a36ee594ea" +checksum = "73027d5e228de6f503b5b7335d530404fc26230a6ae3e09b33ec6e45408509a4" dependencies = [ - "kvdb", - "parity-util-mem", - "parking_lot 0.10.0", + "kvdb 0.6.0", + "parity-util-mem 0.6.0", + "parking_lot 0.10.2", ] [[package]] -name = "kvdb-rocksdb" +name = "kvdb-memorydb" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3f14c3a10c8894d26175e57e9e26032e6d6c49c30cbe2468c5bf5f6b64bb0be" +checksum = "73de822b260a3bdfb889dbbb65bb2d473eee2253973d6fa4a5d149a2a4a7c66e" +dependencies = [ + "kvdb 0.7.0", + "parity-util-mem 0.7.0", + "parking_lot 0.10.2", +] + +[[package]] +name = "kvdb-rocksdb" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c341ef15cfb1f923fa3b5138bfbd2d4813a2c1640b473727a53351c7f0b0fa2" dependencies = [ "fs-swap", - "interleaved-ordered", - "kvdb", + "kvdb 0.7.0", "log", "num_cpus", "owning_ref", - "parity-util-mem", - "parking_lot 0.10.0", + "parity-util-mem 0.7.0", + "parking_lot 0.10.2", "regex", "rocksdb", - "smallvec 1.2.0", + "smallvec 1.4.1", ] [[package]] name = "kvdb-web" -version = "0.5.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26f96eec962af83cdf7c83036b3dbb0ae6a1249ddab746820618e2567ca8ebcd" +checksum = "2701a1369d6ea4f1b9f606db46e5e2a4a8e47f22530a07823d653f85ab1f6c34" dependencies = [ - "futures 0.3.4", + "futures 0.3.5", "js-sys", - "kvdb", - "kvdb-memorydb", + "kvdb 0.7.0", + "kvdb-memorydb 0.7.0", "log", - "parity-util-mem", + "parity-util-mem 0.7.0", "send_wrapper 0.3.0", "wasm-bindgen", "web-sys", @@ -2567,9 +2693,9 @@ checksum = "3576a87f2ba00f6f106fdfcd16db1d698d648a26ad8e0573cad8537c3c362d2a" [[package]] name = "libc" -version = "0.2.67" +version = "0.2.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018" +checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49" [[package]] name = "libflate" @@ -2595,67 +2721,62 @@ dependencies = [ [[package]] name = "libm" -version = "0.1.4" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" +checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" [[package]] name = "libp2p" -version = "0.16.2" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bba17ee9cac4bb89de5812159877d9b4f0a993bf41697a5a875940cd1eb71f24" +checksum = "6d743d03fab397cde23925a17cb87b35b25994f44ab8c6a9e46a7e953ec739cd" dependencies = [ "bytes 0.5.4", - "futures 0.3.4", + "futures 0.3.5", "lazy_static", "libp2p-core", "libp2p-core-derive", - "libp2p-deflate", "libp2p-dns", - "libp2p-floodsub", - "libp2p-gossipsub", "libp2p-identify", "libp2p-kad", "libp2p-mdns", "libp2p-mplex", "libp2p-noise", "libp2p-ping", - "libp2p-plaintext", - "libp2p-pnet", "libp2p-secio", "libp2p-swarm", "libp2p-tcp", - "libp2p-uds", "libp2p-wasm-ext", "libp2p-websocket", "libp2p-yamux", + "multihash", "parity-multiaddr", - "parity-multihash", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "pin-project", - "smallvec 1.2.0", + "smallvec 1.4.1", "wasm-timer", ] [[package]] name = "libp2p-core" -version = "0.16.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b874594c4b29de1a29f27871feba8e6cd13aa54a8a1e8f8c7cf3dfac5ca287c" +checksum = "11ca8d5a64a5d19b45e00e8f24afda6b8e1b605fb25ad7bcf62a42ecf19d7ff3" dependencies = [ "asn1_der", "bs58", "ed25519-dalek", + "either", "fnv", - "futures 0.3.4", + "futures 0.3.5", "futures-timer 3.0.2", "lazy_static", "libsecp256k1", "log", + "multihash", "multistream-select", "parity-multiaddr", - "parity-multihash", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "pin-project", "prost", "prost-build", @@ -2663,176 +2784,123 @@ dependencies = [ "ring", "rw-stream-sink", "sha2", - "smallvec 1.2.0", + "smallvec 1.4.1", "thiserror", - "unsigned-varint", + "unsigned-varint 0.4.0", "void", "zeroize", ] [[package]] name = "libp2p-core-derive" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d472e9d522f588805c77801de10b957be84e10f019ca5f869fa1825b15ea9b" -dependencies = [ - "quote 1.0.3", - "syn 1.0.16", -] - -[[package]] -name = "libp2p-deflate" -version = "0.16.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e25004d4d9837b44b22c5f1a69be1724a5168fef6cff1716b5176a972c3aa62" +checksum = "4b2f4f7b4e596450a0b62a46669caaebab9686c68b3c386053182ab41d761f66" dependencies = [ - "flate2", - "futures 0.3.4", - "libp2p-core", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] name = "libp2p-dns" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b99e552f9939b606eb4b59f7f64d9b01e3f96752f47e350fc3c5fc646ed3f649" -dependencies = [ - "futures 0.3.4", - "libp2p-core", - "log", -] - -[[package]] -name = "libp2p-floodsub" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d3234f12e44f9a50351a9807b97fe7de11eb9ae4482370392ba10da6dc90722" -dependencies = [ - "cuckoofilter", - "fnv", - "futures 0.3.4", - "libp2p-core", - "libp2p-swarm", - "prost", - "prost-build", - "rand 0.7.3", - "smallvec 1.2.0", -] - -[[package]] -name = "libp2p-gossipsub" -version = "0.16.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d46cb3e0841bd951cbf4feae56cdc081e6347836a644fb260c3ec554149b4006" +checksum = "f751924b6b98e350005e0b87a822beb246792a3fb878c684e088f866158120ac" dependencies = [ - "base64 0.11.0", - "byteorder 1.3.4", - "bytes 0.5.4", - "fnv", - "futures 0.3.4", - "futures_codec", + "futures 0.3.5", "libp2p-core", - "libp2p-swarm", "log", - "lru", - "prost", - "prost-build", - "rand 0.7.3", - "sha2", - "smallvec 1.2.0", - "unsigned-varint", - "wasm-timer", ] [[package]] name = "libp2p-identify" -version = "0.16.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfeb935a9bd41263e4f3a24b988e9f4a044f3ae89ac284e83c17fe2f84e0d66b" +checksum = "912c00a7bf67e0e765daf0cc37e08f675ea26aba3d6d1fbfaee81f19a4c23049" dependencies = [ - "futures 0.3.4", + "futures 0.3.5", "libp2p-core", "libp2p-swarm", "log", "prost", "prost-build", - "smallvec 1.2.0", + "smallvec 1.4.1", "wasm-timer", ] [[package]] name = "libp2p-kad" -version = "0.16.2" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "464dc8412978d40f0286be72ed9ab5e0e1386a4a06e7f174526739b5c3c1f041" +checksum = "44ed3a4c8111c570ab2bffb30c6353178d7603ce3787e3c5f2493c8d3d16d1f0" dependencies = [ "arrayvec 0.5.1", "bytes 0.5.4", "either", "fnv", - "futures 0.3.4", + "futures 0.3.5", "futures_codec", "libp2p-core", "libp2p-swarm", "log", - "parity-multihash", + "multihash", "prost", "prost-build", "rand 0.7.3", "sha2", - "smallvec 1.2.0", + "smallvec 1.4.1", "uint", - "unsigned-varint", + "unsigned-varint 0.4.0", "void", "wasm-timer", ] [[package]] name = "libp2p-mdns" -version = "0.16.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881fcfb360c2822db9f0e6bb6f89529621556ed9a8b038313414eda5107334de" +checksum = "cd004c668160fd922f7268b2cd1e4550ff69165d9c744e9eb5770086eb753d02" dependencies = [ "async-std", "data-encoding", "dns-parser", "either", - "futures 0.3.4", + "futures 0.3.5", "lazy_static", "libp2p-core", "libp2p-swarm", "log", "net2", "rand 0.7.3", - "smallvec 1.2.0", + "smallvec 1.4.1", "void", "wasm-timer", ] [[package]] name = "libp2p-mplex" -version = "0.16.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8507b37ad0eed275efcde67a023c3d85af6c80768b193845b9288e848e1af95" +checksum = "14ae0ffacd30f073f96cd518b2c9cd2cb18ac27c3d136a4b23cf1af99f33e541" dependencies = [ "bytes 0.5.4", "fnv", - "futures 0.3.4", + "futures 0.3.5", "futures_codec", "libp2p-core", "log", - "parking_lot 0.10.0", - "unsigned-varint", + "parking_lot 0.10.2", + "unsigned-varint 0.4.0", ] [[package]] name = "libp2p-noise" -version = "0.16.2" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15a8a3d71f898beb6f854c8aae27aa1d198e0d1f2e49412261c2d90ef39675a" +checksum = "f6ad6b67d802de8b5ddc5e8b0ff55a0d0a6a737c2c5c174601dbb9d24e0ad5cb" dependencies = [ "curve25519-dalek", - "futures 0.3.4", + "futures 0.3.5", "lazy_static", "libp2p-core", "log", @@ -2848,11 +2916,11 @@ dependencies = [ [[package]] name = "libp2p-ping" -version = "0.16.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d22f2f228b3a828dca1cb8aa9fa331e0bc9c36510cb2c1916956e20dc85e8c" +checksum = "70130cf130e4ba6dc177366e72dd9f86f9e3588fa1a0c4145247e676f16affad" dependencies = [ - "futures 0.3.4", + "futures 0.3.5", "libp2p-core", "libp2p-swarm", "log", @@ -2861,47 +2929,15 @@ dependencies = [ "wasm-timer", ] -[[package]] -name = "libp2p-plaintext" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56126a204d7b3382bac163143ff4125a14570b3ba76ba979103d1ae1abed1923" -dependencies = [ - "bytes 0.5.4", - "futures 0.3.4", - "futures_codec", - "libp2p-core", - "log", - "prost", - "prost-build", - "rw-stream-sink", - "unsigned-varint", - "void", -] - -[[package]] -name = "libp2p-pnet" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b916938a8868f75180aeeffcc6a516a922d165e8fa2a90b57bad989d1ccbb57a" -dependencies = [ - "futures 0.3.4", - "log", - "pin-project", - "rand 0.7.3", - "salsa20", - "sha3", -] - [[package]] name = "libp2p-secio" -version = "0.16.1" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1219e9ecb4945d7331a05f5ffe96a1f6e28051bfa1223d4c60353c251de0354e" +checksum = "5ff43513c383f7cdab2736eb98465fc4c5dd5d1988df89749dc8a68950349d56" dependencies = [ "aes-ctr", "ctr", - "futures 0.3.4", + "futures 0.3.5", "hmac", "js-sys", "lazy_static", @@ -2925,52 +2961,42 @@ dependencies = [ [[package]] name = "libp2p-swarm" -version = "0.16.1" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "275471e7c0e88ae004660866cd54f603bd8bd1f4caef541a27f50dd8640c4d4c" +checksum = "3829b323fe096a9363362d0dbbfb3d73f12f1760a6a5c193a779994ab8cbc584" dependencies = [ - "futures 0.3.4", + "futures 0.3.5", "libp2p-core", "log", - "smallvec 1.2.0", + "rand 0.7.3", + "smallvec 1.4.1", "void", "wasm-timer", ] [[package]] name = "libp2p-tcp" -version = "0.16.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9e80ad4e3535345f3d666554ce347d3100453775611c05c60786bf9a1747a10" +checksum = "9b1fa2bbad054020cb875546a577a66a65a5bf42eff55ed5265f92ffee3cc052" dependencies = [ "async-std", - "futures 0.3.4", + "futures 0.3.5", "futures-timer 3.0.2", "get_if_addrs", "ipnet", "libp2p-core", "log", -] - -[[package]] -name = "libp2p-uds" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d329564a43da9d0e055a5b938633c4a8ceab1f59cec133fbc4647917c07341" -dependencies = [ - "async-std", - "futures 0.3.4", - "libp2p-core", - "log", + "socket2", ] [[package]] name = "libp2p-wasm-ext" -version = "0.16.2" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "923581c055bc4b8c5f42d4ce5ef43e52fe5216f1ea4bc26476cb8a966ce6220b" +checksum = "1e2b3f0281c184af2e3481ad2463682735d491b2ceb8f73fa99dcd5d41e7afbf" dependencies = [ - "futures 0.3.4", + "futures 0.3.5", "js-sys", "libp2p-core", "parity-send-wrapper", @@ -2980,18 +3006,17 @@ dependencies = [ [[package]] name = "libp2p-websocket" -version = "0.16.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5351ca9eea122081c1c0f9323164d2918cac29b5a6bfe5054d4ba8ec9447cf42" +checksum = "bd3a13025c0f621647ed2c5147615468e7b3cd1a5c7f26f2a6f6f8eafc9c1950" dependencies = [ "async-tls", - "bytes 0.5.4", "either", - "futures 0.3.4", + "futures 0.3.5", "libp2p-core", "log", "quicksink", - "rustls 0.16.0", + "rustls", "rw-stream-sink", "soketto", "url 2.1.1", @@ -3001,22 +3026,22 @@ dependencies = [ [[package]] name = "libp2p-yamux" -version = "0.16.2" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dac30de24ccde0e67f363d71a125c587bbe6589503f664947e9b084b68a34f1" +checksum = "46ae9bf2f7d8a4be9c7e9b61df9de9dc1bd66419d669098f22f81f8d9571029a" dependencies = [ - "futures 0.3.4", + "futures 0.3.5", "libp2p-core", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "thiserror", "yamux", ] [[package]] name = "librocksdb-sys" -version = "6.6.4" +version = "6.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3b727e2dd20ec2fb7ed93f23d9fd5328a0871185485ebdaff007b47d3e27e4" +checksum = "883213ae3d09bfc3d104aefe94b25ebb183b6f4d3a515b23b14817e1f4854005" dependencies = [ "bindgen", "cc", @@ -3089,9 +3114,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b" +checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" dependencies = [ "scopeguard", ] @@ -3111,7 +3136,16 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0609345ddee5badacf857d4f547e0e5a2e987db77085c24cd887f73573a04237" dependencies = [ - "hashbrown", + "hashbrown 0.6.3", +] + +[[package]] +name = "lru" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c456c123957de3a220cd03786e0d86aa542a88b46029973b542f426da6ef34" +dependencies = [ + "hashbrown 0.6.3", ] [[package]] @@ -3162,23 +3196,22 @@ dependencies = [ [[package]] name = "memoffset" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" +checksum = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8" dependencies = [ - "rustc_version", + "autocfg 1.0.0", ] [[package]] name = "memory-db" -version = "0.20.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58381b20ebe2c578e75dececd9da411414903415349548ccc46aac3209cdfbc" +checksum = "0777fbb396f666701d939e9b3876c18ada6b3581257d88631f2590bc366d8ebe" dependencies = [ - "ahash", "hash-db", - "hashbrown", - "parity-util-mem", + "hashbrown 0.8.0", + "parity-util-mem 0.7.0", ] [[package]] @@ -3193,7 +3226,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6feca46f4fa3443a01769d768727f10c10a20fdb65e52dc16a81f0c8269bb78" dependencies = [ - "byteorder 1.3.4", + "byteorder", "keccak", "rand_core 0.5.1", "zeroize", @@ -3221,7 +3254,7 @@ dependencies = [ "kernel32-sys", "libc", "log", - "miow", + "miow 0.2.1", "net2", "slab", "winapi 0.2.8", @@ -3239,6 +3272,18 @@ dependencies = [ "slab", ] +[[package]] +name = "mio-named-pipes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3" +dependencies = [ + "log", + "mio", + "miow 0.3.5", + "winapi 0.3.8", +] + [[package]] name = "mio-uds" version = "0.6.7" @@ -3262,30 +3307,55 @@ dependencies = [ "ws2_32-sys", ] +[[package]] +name = "miow" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07b88fb9795d4d36d62a012dfbf49a8f5cf12751f36d31a9dbe66d528e58979e" +dependencies = [ + "socket2", + "winapi 0.3.8", +] + [[package]] name = "more-asserts" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238" +[[package]] +name = "multihash" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae32179a9904ccc6e063de8beee7f5dd55fae85ecb851ca923d55722bc28cf5d" +dependencies = [ + "blake2b_simd", + "blake2s_simd", + "digest", + "sha-1", + "sha2", + "sha3", + "unsigned-varint 0.3.3", +] + [[package]] name = "multimap" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97fbd5d00e0e37bfb10f433af8f5aaf631e739368dc9fc28286ca81ca4948dc" +checksum = "d8883adfde9756c1d30b0f519c9b8c502a94b41ac62f696453c37c7fc0a958ce" [[package]] name = "multistream-select" -version = "0.7.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f938ffe420493e77c8b6cbcc3f282283f68fc889c5dcbc8e51668d5f3a01ad94" +checksum = "c9157e87afbc2ef0d84cc0345423d715f445edde00141c93721c162de35a05e5" dependencies = [ "bytes 0.5.4", - "futures 0.1.29", + "futures 0.3.5", "log", - "smallvec 1.2.0", - "tokio-io", - "unsigned-varint", + "pin-project", + "smallvec 1.4.1", + "unsigned-varint 0.4.0", ] [[package]] @@ -3332,7 +3402,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29449d242064c48d3057a194b049a2bdcccadda16faa18a91468677b44e8d422" dependencies = [ "bitflags", - "byteorder 1.3.4", + "byteorder", "enum-primitive-derive", "libc", "num-traits 0.2.11", @@ -3354,28 +3424,67 @@ dependencies = [ [[package]] name = "node-bench" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ + "derive_more", + "fs_extra", + "futures 0.3.5", + "hash-db", + "hex", + "kvdb 0.7.0", + "kvdb-rocksdb", + "lazy_static", "log", "node-primitives", + "node-runtime", "node-testing", + "parity-db", + "parity-util-mem 0.7.0", + "rand 0.7.3", + "sc-basic-authorship", "sc-cli", "sc-client-api", "serde", "serde_json", + "sp-consensus", + "sp-core", + "sp-finality-tracker", + "sp-inherents", "sp-runtime", + "sp-state-machine", + "sp-timestamp", + "sp-transaction-pool", + "sp-trie", "structopt", + "tempfile", +] + +[[package]] +name = "node-browser-testing" +version = "2.0.0-rc4" +dependencies = [ + "futures 0.3.5", + "futures-timer 3.0.2", + "jsonrpc-core", + "libp2p", + "node-cli", + "sc-rpc-api", + "serde", + "serde_json", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test", ] [[package]] name = "node-cli" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "assert_cmd", "frame-benchmarking-cli", "frame-support", "frame-system", - "futures 0.3.4", + "futures 0.3.5", "hex-literal", "jsonrpc-core", "log", @@ -3385,24 +3494,27 @@ dependencies = [ "node-primitives", "node-rpc", "node-runtime", - "node-transaction-factory", "pallet-authority-discovery", "pallet-balances", "pallet-contracts", + "pallet-grandpa", "pallet-im-online", "pallet-indices", "pallet-staking", "pallet-timestamp", "pallet-transaction-payment", "parity-scale-codec", + "parking_lot 0.10.2", + "platforms", "rand 0.7.3", + "regex", "sc-authority-discovery", "sc-basic-authorship", "sc-chain-spec", "sc-cli", - "sc-client", "sc-client-api", "sc-client-db", + "sc-consensus", "sc-consensus-babe", "sc-consensus-epochs", "sc-finality-grandpa", @@ -3434,14 +3546,13 @@ dependencies = [ "substrate-build-script-utils", "tempfile", "tracing", - "vergen", "wasm-bindgen", "wasm-bindgen-futures", ] [[package]] name = "node-executor" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "criterion 0.3.1", "frame-benchmarking", @@ -3475,7 +3586,7 @@ dependencies = [ [[package]] name = "node-inspect" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "derive_more", "log", @@ -3491,9 +3602,12 @@ dependencies = [ [[package]] name = "node-primitives" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ + "frame-system", + "parity-scale-codec", "pretty_assertions", + "sp-application-crypto", "sp-core", "sp-runtime", "sp-serializer", @@ -3501,19 +3615,23 @@ dependencies = [ [[package]] name = "node-rpc" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "jsonrpc-core", "node-primitives", "node-runtime", "pallet-contracts-rpc", "pallet-transaction-payment-rpc", - "sc-client", + "sc-client-api", "sc-consensus-babe", "sc-consensus-babe-rpc", "sc-consensus-epochs", + "sc-finality-grandpa", + "sc-finality-grandpa-rpc", "sc-keystore", + "sc-rpc-api", "sp-api", + "sp-block-builder", "sp-blockchain", "sp-consensus", "sp-consensus-babe", @@ -3524,7 +3642,7 @@ dependencies = [ [[package]] name = "node-rpc-client" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "env_logger 0.7.1", "futures 0.1.29", @@ -3537,13 +3655,15 @@ dependencies = [ [[package]] name = "node-runtime" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-benchmarking", "frame-executive", "frame-support", "frame-system", + "frame-system-benchmarking", "frame-system-rpc-runtime-api", + "hex-literal", "integer-sqrt", "node-primitives", "pallet-authority-discovery", @@ -3562,7 +3682,10 @@ dependencies = [ "pallet-im-online", "pallet-indices", "pallet-membership", + "pallet-multisig", "pallet-offences", + "pallet-offences-benchmarking", + "pallet-proxy", "pallet-randomness-collective-flip", "pallet-recovery", "pallet-scheduler", @@ -3595,20 +3718,22 @@ dependencies = [ "sp-std", "sp-transaction-pool", "sp-version", + "static_assertions", "substrate-wasm-builder-runner", ] [[package]] name = "node-template" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ - "futures 0.3.4", + "futures 0.3.5", "log", "node-template-runtime", + "parking_lot 0.10.2", "sc-basic-authorship", "sc-cli", - "sc-client", "sc-client-api", + "sc-consensus", "sc-consensus-aura", "sc-executor", "sc-finality-grandpa", @@ -3624,12 +3749,11 @@ dependencies = [ "sp-transaction-pool", "structopt", "substrate-build-script-utils", - "vergen", ] [[package]] name = "node-template-runtime" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-executive", "frame-support", @@ -3661,12 +3785,13 @@ dependencies = [ [[package]] name = "node-testing" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "criterion 0.3.1", "frame-support", "frame-system", "fs_extra", + "futures 0.3.5", "log", "node-executor", "node-primitives", @@ -3684,7 +3809,6 @@ dependencies = [ "parity-scale-codec", "sc-block-builder", "sc-cli", - "sc-client", "sc-client-api", "sc-client-db", "sc-executor", @@ -3705,25 +3829,6 @@ dependencies = [ "wabt", ] -[[package]] -name = "node-transaction-factory" -version = "0.8.0-alpha.5" -dependencies = [ - "log", - "parity-scale-codec", - "sc-block-builder", - "sc-cli", - "sc-client", - "sc-client-api", - "sc-service", - "sp-api", - "sp-block-builder", - "sp-blockchain", - "sp-consensus", - "sp-core", - "sp-runtime", -] - [[package]] name = "nodrop" version = "0.1.14" @@ -3788,9 +3893,9 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da4dc79f9e6c81bef96148c8f6b8e72ad4541caa4a24373e900a36da07de03a3" +checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" dependencies = [ "autocfg 1.0.0", "num-bigint", @@ -3814,6 +3919,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" dependencies = [ "autocfg 1.0.0", + "libm", ] [[package]] @@ -3828,26 +3934,11 @@ dependencies = [ [[package]] name = "object" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea44a4fd660ab0f38434934ca0212e90fbeaaee54126ef20a3451c30c95bafae" +checksum = "e5666bbb90bc4d1e5bdcb26c0afda1822d25928341e9384ab187a9b37ab69e36" dependencies = [ - "flate2", - "goblin", - "parity-wasm 0.41.0", - "scroll", "target-lexicon", - "uuid", -] - -[[package]] -name = "ole32-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" -dependencies = [ - "winapi 0.2.8", - "winapi-build", ] [[package]] @@ -3897,10 +3988,25 @@ dependencies = [ [[package]] name = "pallet-assets" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-atomic-swap" +version = "2.0.0-rc4" dependencies = [ "frame-support", "frame-system", + "pallet-balances", "parity-scale-codec", "serde", "sp-core", @@ -3911,7 +4017,7 @@ dependencies = [ [[package]] name = "pallet-aura" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-support", "frame-system", @@ -3919,7 +4025,7 @@ dependencies = [ "pallet-session", "pallet-timestamp", "parity-scale-codec", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "serde", "sp-application-crypto", "sp-consensus-aura", @@ -3933,7 +4039,7 @@ dependencies = [ [[package]] name = "pallet-authority-discovery" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-support", "frame-system", @@ -3951,7 +4057,7 @@ dependencies = [ [[package]] name = "pallet-authorship" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-support", "frame-system", @@ -3967,20 +4073,28 @@ dependencies = [ [[package]] name = "pallet-babe" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", + "pallet-authorship", + "pallet-balances", + "pallet-offences", "pallet-session", + "pallet-staking", + "pallet-staking-reward-curve", "pallet-timestamp", "parity-scale-codec", "serde", + "sp-application-crypto", "sp-consensus-babe", "sp-consensus-vrf", "sp-core", "sp-inherents", "sp-io", "sp-runtime", + "sp-session", "sp-staking", "sp-std", "sp-timestamp", @@ -3988,7 +4102,7 @@ dependencies = [ [[package]] name = "pallet-balances" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-benchmarking", "frame-support", @@ -4004,7 +4118,7 @@ dependencies = [ [[package]] name = "pallet-benchmark" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-benchmarking", "frame-support", @@ -4018,7 +4132,7 @@ dependencies = [ [[package]] name = "pallet-collective" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-benchmarking", "frame-support", @@ -4035,9 +4149,10 @@ dependencies = [ [[package]] name = "pallet-contracts" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "assert_matches", + "bitflags", "frame-support", "frame-system", "hex-literal", @@ -4047,6 +4162,7 @@ dependencies = [ "pallet-timestamp", "parity-scale-codec", "parity-wasm 0.41.0", + "pretty_assertions", "pwasm-utils", "serde", "sp-core", @@ -4060,7 +4176,7 @@ dependencies = [ [[package]] name = "pallet-contracts-primitives" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "parity-scale-codec", "sp-runtime", @@ -4069,7 +4185,7 @@ dependencies = [ [[package]] name = "pallet-contracts-rpc" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "jsonrpc-core", "jsonrpc-core-client", @@ -4088,7 +4204,7 @@ dependencies = [ [[package]] name = "pallet-contracts-rpc-runtime-api" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "pallet-contracts-primitives", "parity-scale-codec", @@ -4099,7 +4215,7 @@ dependencies = [ [[package]] name = "pallet-democracy" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-benchmarking", "frame-support", @@ -4114,11 +4230,12 @@ dependencies = [ "sp-runtime", "sp-std", "sp-storage", + "substrate-test-utils", ] [[package]] name = "pallet-elections" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-support", "frame-system", @@ -4134,18 +4251,18 @@ dependencies = [ [[package]] name = "pallet-elections-phragmen" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", "hex-literal", "pallet-balances", - "pallet-scheduler", "parity-scale-codec", "serde", "sp-core", "sp-io", - "sp-phragmen", + "sp-npos-elections", "sp-runtime", "sp-std", "substrate-test-utils", @@ -4153,7 +4270,7 @@ dependencies = [ [[package]] name = "pallet-evm" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "evm", "frame-support", @@ -4173,7 +4290,7 @@ dependencies = [ [[package]] name = "pallet-example" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-benchmarking", "frame-support", @@ -4189,7 +4306,7 @@ dependencies = [ [[package]] name = "pallet-example-offchain-worker" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-support", "frame-system", @@ -4204,7 +4321,7 @@ dependencies = [ [[package]] name = "pallet-finality-tracker" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-support", "frame-system", @@ -4221,7 +4338,7 @@ dependencies = [ [[package]] name = "pallet-generic-asset" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-support", "frame-system", @@ -4235,25 +4352,34 @@ dependencies = [ [[package]] name = "pallet-grandpa" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ + "finality-grandpa", "frame-support", "frame-system", + "pallet-balances", "pallet-finality-tracker", + "pallet-offences", "pallet-session", + "pallet-staking", + "pallet-staking-reward-curve", + "pallet-timestamp", "parity-scale-codec", "serde", + "sp-application-crypto", "sp-core", "sp-finality-grandpa", "sp-io", + "sp-keyring", "sp-runtime", + "sp-session", "sp-staking", "sp-std", ] [[package]] name = "pallet-identity" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "enumflags2", "frame-benchmarking", @@ -4269,27 +4395,74 @@ dependencies = [ ] [[package]] -name = "pallet-im-online" -version = "2.0.0-alpha.5" +name = "pallet-im-online" +version = "2.0.0-rc4" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-authorship", + "pallet-session", + "parity-scale-codec", + "serde", + "sp-application-crypto", + "sp-core", + "sp-io", + "sp-runtime", + "sp-staking", + "sp-std", +] + +[[package]] +name = "pallet-indices" +version = "2.0.0-rc4" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-balances", + "parity-scale-codec", + "serde", + "sp-core", + "sp-io", + "sp-keyring", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-membership" +version = "2.0.0-rc4" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-multisig" +version = "2.0.0-rc4" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "pallet-authorship", - "pallet-session", + "pallet-balances", "parity-scale-codec", "serde", - "sp-application-crypto", "sp-core", "sp-io", "sp-runtime", - "sp-staking", "sp-std", ] [[package]] -name = "pallet-indices" -version = "2.0.0-alpha.5" +name = "pallet-nicks" +version = "2.0.0-rc4" dependencies = [ "frame-support", "frame-system", @@ -4298,59 +4471,71 @@ dependencies = [ "serde", "sp-core", "sp-io", - "sp-keyring", "sp-runtime", "sp-std", ] [[package]] -name = "pallet-membership" -version = "2.0.0-alpha.5" +name = "pallet-offences" +version = "2.0.0-rc4" dependencies = [ "frame-support", "frame-system", + "pallet-balances", "parity-scale-codec", "serde", "sp-core", "sp-io", "sp-runtime", + "sp-staking", "sp-std", ] [[package]] -name = "pallet-nicks" -version = "2.0.0-alpha.5" +name = "pallet-offences-benchmarking" +version = "2.0.0-rc4" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", + "pallet-babe", "pallet-balances", + "pallet-grandpa", + "pallet-im-online", + "pallet-offences", + "pallet-session", + "pallet-staking", + "pallet-staking-reward-curve", + "pallet-timestamp", "parity-scale-codec", "serde", "sp-core", "sp-io", "sp-runtime", + "sp-staking", "sp-std", ] [[package]] -name = "pallet-offences" -version = "2.0.0-alpha.5" +name = "pallet-proxy" +version = "2.0.0-rc4" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", "pallet-balances", + "pallet-utility", "parity-scale-codec", "serde", "sp-core", "sp-io", "sp-runtime", - "sp-staking", "sp-std", ] [[package]] name = "pallet-randomness-collective-flip" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-support", "frame-system", @@ -4364,7 +4549,7 @@ dependencies = [ [[package]] name = "pallet-recovery" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "enumflags2", "frame-support", @@ -4380,7 +4565,7 @@ dependencies = [ [[package]] name = "pallet-scheduler" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-benchmarking", "frame-support", @@ -4391,11 +4576,12 @@ dependencies = [ "sp-io", "sp-runtime", "sp-std", + "substrate-test-utils", ] [[package]] name = "pallet-scored-pool" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-support", "frame-system", @@ -4410,7 +4596,7 @@ dependencies = [ [[package]] name = "pallet-session" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-support", "frame-system", @@ -4423,6 +4609,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", + "sp-session", "sp-staking", "sp-std", "sp-trie", @@ -4430,19 +4617,29 @@ dependencies = [ [[package]] name = "pallet-session-benchmarking" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-benchmarking", + "frame-support", "frame-system", + "pallet-balances", "pallet-session", "pallet-staking", + "pallet-staking-reward-curve", + "pallet-timestamp", + "parity-scale-codec", + "rand 0.7.3", + "serde", + "sp-core", + "sp-io", "sp-runtime", + "sp-session", "sp-std", ] [[package]] name = "pallet-society" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-support", "frame-system", @@ -4458,7 +4655,7 @@ dependencies = [ [[package]] name = "pallet-staking" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "env_logger 0.7.1", "frame-benchmarking", @@ -4467,19 +4664,17 @@ dependencies = [ "hex", "pallet-authorship", "pallet-balances", - "pallet-indices", "pallet-session", "pallet-staking-reward-curve", "pallet-timestamp", "parity-scale-codec", - "parking_lot 0.10.0", - "rand 0.7.3", + "parking_lot 0.10.2", "rand_chacha 0.2.2", "serde", "sp-application-crypto", "sp-core", "sp-io", - "sp-phragmen", + "sp-npos-elections", "sp-runtime", "sp-staking", "sp-std", @@ -4488,20 +4683,41 @@ dependencies = [ "substrate-test-utils", ] +[[package]] +name = "pallet-staking-fuzz" +version = "0.0.0" +dependencies = [ + "frame-support", + "frame-system", + "honggfuzz", + "pallet-balances", + "pallet-indices", + "pallet-session", + "pallet-staking", + "pallet-staking-reward-curve", + "pallet-timestamp", + "parity-scale-codec", + "sp-core", + "sp-io", + "sp-npos-elections", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-staking-reward-curve" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "proc-macro-crate", "proc-macro2", - "quote 1.0.3", + "quote 1.0.6", "sp-runtime", - "syn 1.0.16", + "syn 1.0.33", ] [[package]] name = "pallet-sudo" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-support", "frame-system", @@ -4515,7 +4731,7 @@ dependencies = [ [[package]] name = "pallet-template" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-support", "frame-system", @@ -4527,7 +4743,7 @@ dependencies = [ [[package]] name = "pallet-timestamp" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-benchmarking", "frame-support", @@ -4545,22 +4761,25 @@ dependencies = [ [[package]] name = "pallet-transaction-payment" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-support", "frame-system", "pallet-balances", "pallet-transaction-payment-rpc-runtime-api", "parity-scale-codec", + "serde", + "smallvec 1.4.1", "sp-core", "sp-io", "sp-runtime", "sp-std", + "sp-storage", ] [[package]] name = "pallet-transaction-payment-rpc" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "jsonrpc-core", "jsonrpc-core-client", @@ -4577,7 +4796,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc-runtime-api" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-support", "parity-scale-codec", @@ -4590,7 +4809,7 @@ dependencies = [ [[package]] name = "pallet-treasury" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-benchmarking", "frame-support", @@ -4602,11 +4821,12 @@ dependencies = [ "sp-io", "sp-runtime", "sp-std", + "sp-storage", ] [[package]] name = "pallet-utility" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-benchmarking", "frame-support", @@ -4622,7 +4842,7 @@ dependencies = [ [[package]] name = "pallet-vesting" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "enumflags2", "frame-benchmarking", @@ -4639,44 +4859,43 @@ dependencies = [ "sp-storage", ] +[[package]] +name = "parity-db" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00d595e372d119261593297debbe4193811a4dc811d2a1ccbb8caaa6666ad7ab" +dependencies = [ + "blake2-rfc", + "crc32fast", + "libc", + "log", + "memmap", + "parking_lot 0.10.2", +] + [[package]] name = "parity-multiaddr" -version = "0.7.3" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f77055f9e81921a8cc7bebeb6cded3d128931d51f1e3dd6251f0770a6d431477" +checksum = "cc20af3143a62c16e7c9e92ea5c6ae49f7d271d97d4d8fe73afc28f0514a3d0f" dependencies = [ "arrayref", "bs58", - "byteorder 1.3.4", + "byteorder", "data-encoding", - "parity-multihash", + "multihash", "percent-encoding 2.1.0", "serde", "static_assertions", - "unsigned-varint", + "unsigned-varint 0.4.0", "url 2.1.1", ] -[[package]] -name = "parity-multihash" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a1cd2ba02391b81367bec529fb209019d718684fdc8ad6a712c2b536e46f775" -dependencies = [ - "blake2", - "bytes 0.5.4", - "rand 0.7.3", - "sha-1", - "sha2", - "sha3", - "unsigned-varint", -] - [[package]] name = "parity-scale-codec" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "329c8f7f4244ddb5c37c103641027a76c530e65e8e4b8240b29f81ea40508b17" +checksum = "a74f02beb35d47e0706155c9eac554b50c671e0d868fe8296bcdf44a9a4847bf" dependencies = [ "arrayvec 0.5.1", "bitvec", @@ -4693,8 +4912,8 @@ checksum = "5a0ec292e92e8ec7c58e576adacc1e3f399c597c8f263c42f18420abe58e7245" dependencies = [ "proc-macro-crate", "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] @@ -4703,21 +4922,53 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa9777aa91b8ad9dd5aaa04a9b6bcb02c7f1deb952fca5a66034d5e63afc5c6f" +[[package]] +name = "parity-tokio-ipc" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e57fea504fea33f9fbb5f49f378359030e7e026a6ab849bb9e8f0787376f1bf" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.29", + "libc", + "log", + "mio-named-pipes", + "miow 0.3.5", + "rand 0.7.3", + "tokio 0.1.22", + "tokio-named-pipes", + "tokio-uds", + "winapi 0.3.8", +] + [[package]] name = "parity-util-mem" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e42755f26e5ea21a6a819d9e63cbd70713e9867a2b767ec2cc65ca7659532c5" +dependencies = [ + "cfg-if", + "impl-trait-for-tuples", + "parity-util-mem-derive", + "parking_lot 0.10.2", + "winapi 0.3.8", +] + +[[package]] +name = "parity-util-mem" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "297ff91fa36aec49ce183484b102f6b75b46776822bd81525bfc4cc9b0dd0f5c" dependencies = [ "cfg-if", "ethereum-types", - "hashbrown", + "hashbrown 0.8.0", "impl-trait-for-tuples", - "lru", + "lru 0.5.3", "parity-util-mem-derive", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "primitive-types", - "smallvec 1.2.0", + "smallvec 1.4.1", "winapi 0.3.8", ] @@ -4728,7 +4979,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f557c32c6d268a07c921471619c0295f5efad3a0e76d4f97a05c091a51d110b2" dependencies = [ "proc-macro2", - "syn 1.0.16", + "syn 1.0.33", "synstructure", ] @@ -4738,7 +4989,7 @@ version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16ad52817c4d343339b3bc2e26861bd21478eda0b7509acf83505727000512ac" dependencies = [ - "byteorder 1.3.4", + "byteorder", ] [[package]] @@ -4747,6 +4998,12 @@ version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddfc878dac00da22f8f61e7af3157988424567ab01d9920b962ef7dcbd7cd865" +[[package]] +name = "parking" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4029bc3504a62d92e42f30b9095fdef73b8a0b2a06aa41ce2935143b05a1a06" + [[package]] name = "parking_lot" version = "0.9.0" @@ -4760,12 +5017,12 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.10.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" +checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" dependencies = [ "lock_api", - "parking_lot_core 0.7.0", + "parking_lot_core 0.7.1", ] [[package]] @@ -4785,23 +5042,23 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" +checksum = "0e136c1904604defe99ce5fd71a28d473fa60a12255d511aa78a9ddf11237aeb" dependencies = [ "cfg-if", "cloudabi", "libc", "redox_syscall", - "smallvec 1.2.0", + "smallvec 1.4.1", "winapi 0.3.8", ] [[package]] name = "paste" -version = "0.1.7" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e1afe738d71b1ebab5f1207c055054015427dbfc7bbe9ee1266894156ec046" +checksum = "ab4fb1930692d1b6a9cfabdde3d06ea0a7d186518e2f4d67660d8970e2fa647a" dependencies = [ "paste-impl", "proc-macro-hack", @@ -4809,14 +5066,14 @@ dependencies = [ [[package]] name = "paste-impl" -version = "0.1.7" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d4dc4a7f6f743211c5aab239640a65091535d97d43d92a52bca435a640892bb" +checksum = "a62486e111e571b1e93b710b61e8f493c0013be39629b714cb166bdb06aa5a8a" dependencies = [ "proc-macro-hack", "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] @@ -4825,7 +5082,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" dependencies = [ - "byteorder 1.3.4", + "byteorder", "crypto-mac", ] @@ -4865,22 +5122,22 @@ dependencies = [ [[package]] name = "pin-project" -version = "0.4.8" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7804a463a8d9572f13453c516a5faea534a2403d7ced2f0c7e100eeff072772c" +checksum = "12e3a6cdbfe94a5e4572812a0201f8c0ed98c1c452c7b8563ce2276988ef9c17" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "0.4.8" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "385322a45f2ecf3410c68d2a549a4a2685e8051d0f278e39743ff4e451cb9b3f" +checksum = "6a0ffd45cf79d88737d7cc85bfd5d2894bee1139b356e616fe85dc389c61aaf7" dependencies = [ "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] @@ -4891,9 +5148,9 @@ checksum = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae" [[package]] name = "pin-utils" -version = "0.1.0-alpha.4" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" @@ -4907,6 +5164,12 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" +[[package]] +name = "platforms" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "feb3b2b1033b8a60b4da6ee470325f887758c95d5320f52f9ce0df055a55940e" + [[package]] name = "plotters" version = "0.2.12" @@ -4919,6 +5182,25 @@ dependencies = [ "web-sys", ] +[[package]] +name = "poly1305" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5829f50f48e9ddb79f3f7c3097029d0caee30f8286accb241416df603b080b8" +dependencies = [ + "universal-hash", +] + +[[package]] +name = "polyval" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ec3341498978de3bfd12d1b22f1af1de22818f5473a11e8a6ef997989e3a212" +dependencies = [ + "cfg-if", + "universal-hash", +] + [[package]] name = "ppv-lite86" version = "0.2.6" @@ -4987,52 +5269,47 @@ dependencies = [ [[package]] name = "proc-macro-error" -version = "0.4.11" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7959c6467d962050d639361f7703b2051c43036d03493c36f01d440fdd3138a" +checksum = "98e9e4b82e0ef281812565ea4751049f1bdcdfccda7d3f459f2e138a40c08678" dependencies = [ "proc-macro-error-attr", "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", "version_check", ] [[package]] name = "proc-macro-error-attr" -version = "0.4.11" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4002d9f55991d5e019fb940a90e1a95eb80c24e77cb2462dd4dc869604d543a" +checksum = "4f5444ead4e9935abd7f27dc51f7e852a0569ac888096d5ec2499470794e2e53" dependencies = [ "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", "syn-mid", "version_check", ] [[package]] name = "proc-macro-hack" -version = "0.5.11" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" -dependencies = [ - "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", -] +checksum = "0d659fe7c6d27f25e9d80a1a094c223f5246f6a6596453e09d7229bf42750b63" [[package]] name = "proc-macro-nested" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" +checksum = "8e946095f9d3ed29ec38de908c22f95d9ac008e424c7bcae54c75a79c527c694" [[package]] name = "proc-macro2" -version = "1.0.9" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" +checksum = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa" dependencies = [ "unicode-xid 0.2.0", ] @@ -5044,7 +5321,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe50036aa1b71e553a4a0c48ab7baabf8aa8c7a5a61aae06bf38c2eab7430475" dependencies = [ "bitflags", - "byteorder 1.3.4", + "byteorder", "chrono", "hex", "lazy_static", @@ -5084,7 +5361,7 @@ checksum = "02b10678c913ecbd69350e8535c3aef91a8676c0773fc1d7b95cdd196d7f2f26" dependencies = [ "bytes 0.5.4", "heck", - "itertools", + "itertools 0.8.2", "log", "multimap", "petgraph", @@ -5101,10 +5378,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "537aa19b95acde10a12fec4301466386f757403de4cd4e5b4fa78fb5ecb18f72" dependencies = [ "anyhow", - "itertools", + "itertools 0.8.2", "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] @@ -5119,9 +5396,9 @@ dependencies = [ [[package]] name = "protobuf" -version = "2.10.2" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37a5325d019a4d837d3abde0a836920f959e33d350f77b5f1e289e061e774942" +checksum = "8e86d370532557ae7573551a1ec8235a0f8d6cb276c7c9e6aa490b511c447485" [[package]] name = "pwasm-utils" @@ -5129,7 +5406,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f7a12f176deee919f4ba55326ee17491c8b707d0987aed822682c821b660192" dependencies = [ - "byteorder 1.3.4", + "byteorder", "log", "parity-wasm 0.41.0", ] @@ -5154,9 +5431,9 @@ dependencies = [ [[package]] name = "quicksink" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8461ef7445f61fd72d8dcd0629ce724b9131b3c2eb36e83a5d3d4161c127530" +checksum = "77de3c815e5a160b1539c6592796801df2043ae35e123b46d73380cfa57af858" dependencies = [ "futures-core", "futures-sink", @@ -5171,9 +5448,9 @@ checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" [[package]] name = "quote" -version = "1.0.3" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" +checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea" dependencies = [ "proc-macro2", ] @@ -5234,7 +5511,7 @@ dependencies = [ "rand_isaac", "rand_jitter", "rand_os", - "rand_pcg", + "rand_pcg 0.1.2", "rand_xorshift", "winapi 0.3.8", ] @@ -5250,6 +5527,7 @@ dependencies = [ "rand_chacha 0.2.2", "rand_core 0.5.1", "rand_hc 0.2.0", + "rand_pcg 0.2.1", ] [[package]] @@ -5359,6 +5637,15 @@ dependencies = [ "rand_core 0.4.2", ] +[[package]] +name = "rand_pcg" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +dependencies = [ + "rand_core 0.5.1", +] + [[package]] name = "rand_xorshift" version = "0.1.1" @@ -5374,7 +5661,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03b418169fb9c46533f326efd6eed2576699c44ca92d3052a066214a8d828929" dependencies = [ - "byteorder 1.3.4", + "byteorder", "rand_core 0.3.1", ] @@ -5445,11 +5732,42 @@ dependencies = [ "rust-argon2", ] +[[package]] +name = "ref-cast" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a214c7875e1b63fc1618db7c80efc0954f6156c9ff07699fd9039e255accdd1" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "602eb59cda66fcb9aec25841fb76bc01d2b34282dcdd705028da297db6f3eec8" +dependencies = [ + "proc-macro2", + "quote 1.0.6", + "syn 1.0.33", +] + +[[package]] +name = "regalloc" +version = "0.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b27b256b41986ac5141b37b8bbba85d314fbf546c182eb255af6720e07e4f804" +dependencies = [ + "log", + "rustc-hash", + "smallvec 1.4.1", +] + [[package]] name = "regex" -version = "1.3.4" +version = "1.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322cf97724bea3ee221b78fe25ac9c46114ebb51747ad5babd51a2fc6a8235a8" +checksum = "7f6946991529684867e47d86474e3a6d0c0ab9b82d5821e314b1ede31fa3a4b3" dependencies = [ "aho-corasick", "memchr", @@ -5463,14 +5781,14 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4" dependencies = [ - "byteorder 1.3.4", + "byteorder", ] [[package]] name = "regex-syntax" -version = "0.6.16" +version = "0.6.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1132f845907680735a84409c3bebc64d1364a5683ffbce899550cd09d5eaefc1" +checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae" [[package]] name = "region" @@ -5493,11 +5811,32 @@ dependencies = [ "winapi 0.3.8", ] +[[package]] +name = "rental" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8545debe98b2b139fb04cad8618b530e9b07c152d99a5de83c860b877d67847f" +dependencies = [ + "rental-impl", + "stable_deref_trait", +] + +[[package]] +name = "rental-impl" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "475e68978dc5b743f2f40d8e0a8fdc83f1c5e78cbf4b8fa5e74e73beebc340de" +dependencies = [ + "proc-macro2", + "quote 1.0.6", + "syn 1.0.33", +] + [[package]] name = "ring" -version = "0.16.11" +version = "0.16.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "741ba1704ae21999c00942f9f5944f801e977f54302af346b596287599ad1862" +checksum = "1ba5a8ec64ee89a76c98c549af81ff14813df09c3e6dc4766c3856da48597a0c" dependencies = [ "cc", "lazy_static", @@ -5516,18 +5855,18 @@ checksum = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac" [[package]] name = "rlp" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a44d5ae8afcb238af8b75640907edc6c931efcfab2c854e81ed35fa080f84cd" +checksum = "4a7d3f9bed94764eac15b8f14af59fac420c236adaff743b7bcc88e265cb4345" dependencies = [ "rustc-hex", ] [[package]] name = "rocksdb" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12069b106981c6103d3eab7dd1c86751482d0779a520b7c14954c8b586c1e643" +checksum = "61aa17a99a2413cd71c1106691bf59dad7de0cd5099127f90e9d99c429c40d4a" dependencies = [ "libc", "librocksdb-sys", @@ -5582,19 +5921,6 @@ dependencies = [ "semver 0.9.0", ] -[[package]] -name = "rustls" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b25a18b1bf7387f0145e7f8324e700805aade3842dd3db2e74e4cdeb4677c09e" -dependencies = [ - "base64 0.10.1", - "log", - "ring", - "sct", - "webpki", -] - [[package]] name = "rustls" version = "0.17.0" @@ -5615,7 +5941,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75ffeb84a6bd9d014713119542ce415db3a3e4748f0bfce1e1416cd224a23a5" dependencies = [ "openssl-probe", - "rustls 0.17.0", + "rustls", "schannel", "security-framework", ] @@ -5627,8 +5953,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3bba175698996010c4f6dce5e7f173b6eb781fce25d2cfc45e27091ce0b79f6" dependencies = [ "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] @@ -5637,16 +5963,16 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4da5fcb054c46f5a5dff833b129285a93d3f0179531735e6c866e8cc307d2020" dependencies = [ - "futures 0.3.4", + "futures 0.3.5", "pin-project", "static_assertions", ] [[package]] name = "ryu" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" +checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76" [[package]] name = "safe-mix" @@ -5657,26 +5983,6 @@ dependencies = [ "rustc_version", ] -[[package]] -name = "salsa20" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2324b0e8c3bb9a586a571fdb3136f70e7e2c748de00a78043f86e0cff91f91fe" -dependencies = [ - "byteorder 1.3.4", - "salsa20-core", - "stream-cipher", -] - -[[package]] -name = "salsa20-core" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fe6cc1b9f5a5867853ade63099de70f042f7679e408d1ffe52821c9248e6e69" -dependencies = [ - "stream-cipher", -] - [[package]] name = "same-file" version = "1.0.6" @@ -5688,12 +5994,12 @@ dependencies = [ [[package]] name = "sc-authority-discovery" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "bytes 0.5.4", "derive_more", "env_logger 0.7.1", - "futures 0.3.4", + "futures 0.3.5", "futures-timer 3.0.2", "libp2p", "log", @@ -5718,15 +6024,16 @@ dependencies = [ [[package]] name = "sc-basic-authorship" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ - "futures 0.3.4", + "futures 0.3.5", "futures-timer 3.0.2", "log", "parity-scale-codec", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "sc-block-builder", "sc-client-api", + "sc-proposer-metrics", "sc-telemetry", "sc-transaction-pool", "sp-api", @@ -5736,13 +6043,14 @@ dependencies = [ "sp-inherents", "sp-runtime", "sp-transaction-pool", + "substrate-prometheus-endpoint", "substrate-test-runtime-client", "tokio-executor 0.2.0-alpha.6", ] [[package]] name = "sc-block-builder" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "parity-scale-codec", "sc-client-api", @@ -5751,6 +6059,7 @@ dependencies = [ "sp-blockchain", "sp-consensus", "sp-core", + "sp-inherents", "sp-runtime", "sp-state-machine", "sp-trie", @@ -5759,7 +6068,7 @@ dependencies = [ [[package]] name = "sc-chain-spec" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "impl-trait-for-tuples", "sc-chain-spec-derive", @@ -5767,38 +6076,37 @@ dependencies = [ "sc-telemetry", "serde", "serde_json", + "sp-chain-spec", "sp-core", "sp-runtime", ] [[package]] name = "sc-chain-spec-derive" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "proc-macro-crate", "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] name = "sc-cli" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "ansi_term 0.12.1", - "app_dirs", "atty", "chrono", - "clap", "derive_more", "env_logger 0.7.1", "fdlimit", - "futures 0.3.4", + "futures 0.3.5", "lazy_static", "log", "names", "nix", - "parity-util-mem", + "parity-util-mem 0.7.0", "regex", "rpassword", "sc-client-api", @@ -5807,6 +6115,7 @@ dependencies = [ "sc-service", "sc-telemetry", "sc-tracing", + "serde", "serde_json", "sp-blockchain", "sp-core", @@ -5815,72 +6124,36 @@ dependencies = [ "sp-runtime", "sp-state-machine", "sp-utils", + "sp-version", "structopt", "substrate-prometheus-endpoint", "tempfile", "time", - "tokio 0.2.13", -] - -[[package]] -name = "sc-client" -version = "0.8.0-alpha.5" -dependencies = [ - "derive_more", - "env_logger 0.7.1", - "fnv", - "futures 0.3.4", - "hash-db", - "hex-literal", - "kvdb", - "kvdb-memorydb", - "log", - "parity-scale-codec", - "parking_lot 0.10.0", - "sc-block-builder", - "sc-client-api", - "sc-executor", - "sc-telemetry", - "sp-api", - "sp-blockchain", - "sp-consensus", - "sp-core", - "sp-externalities", - "sp-inherents", - "sp-keyring", - "sp-panic-handler", - "sp-runtime", - "sp-state-machine", - "sp-std", - "sp-trie", - "sp-utils", - "sp-version", - "substrate-prometheus-endpoint", - "substrate-test-runtime-client", - "tempfile", - "tracing", + "tokio 0.2.18", ] [[package]] name = "sc-client-api" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "derive_more", "fnv", - "futures 0.3.4", + "futures 0.3.5", "hash-db", "hex-literal", - "kvdb", + "kvdb 0.7.0", + "kvdb-memorydb 0.6.0", "lazy_static", "log", "parity-scale-codec", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "sc-executor", "sc-telemetry", "sp-api", "sp-blockchain", "sp-consensus", "sp-core", + "sp-database", "sp-externalities", "sp-inherents", "sp-keyring", @@ -5893,31 +6166,34 @@ dependencies = [ "sp-trie", "sp-utils", "sp-version", + "substrate-prometheus-endpoint", + "substrate-test-runtime", ] [[package]] name = "sc-client-db" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ + "blake2-rfc", "env_logger 0.7.1", "hash-db", - "kvdb", - "kvdb-memorydb", + "kvdb 0.7.0", + "kvdb-memorydb 0.7.0", "kvdb-rocksdb", "linked-hash-map", "log", + "parity-db", "parity-scale-codec", - "parity-util-mem", - "parking_lot 0.10.0", + "parity-util-mem 0.7.0", + "parking_lot 0.10.2", "quickcheck", - "rand 0.7.3", - "sc-client", "sc-client-api", "sc-executor", "sc-state-db", "sp-blockchain", "sp-consensus", "sp-core", + "sp-database", "sp-keyring", "sp-runtime", "sp-state-machine", @@ -5927,19 +6203,28 @@ dependencies = [ "tempfile", ] +[[package]] +name = "sc-consensus" +version = "0.8.0-rc4" +dependencies = [ + "sc-client-api", + "sp-blockchain", + "sp-consensus", + "sp-runtime", +] + [[package]] name = "sc-consensus-aura" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "derive_more", "env_logger 0.7.1", - "futures 0.3.4", + "futures 0.3.5", "futures-timer 3.0.2", "log", "parity-scale-codec", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "sc-block-builder", - "sc-client", "sc-client-api", "sc-consensus-slots", "sc-executor", @@ -5961,18 +6246,19 @@ dependencies = [ "sp-runtime", "sp-timestamp", "sp-version", + "substrate-prometheus-endpoint", "substrate-test-runtime-client", "tempfile", ] [[package]] name = "sc-consensus-babe" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "derive_more", "env_logger 0.7.1", "fork-tree", - "futures 0.3.4", + "futures 0.3.5", "futures-timer 3.0.2", "log", "merlin", @@ -5980,11 +6266,11 @@ dependencies = [ "num-rational", "num-traits 0.2.11", "parity-scale-codec", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "pdqselect", "rand 0.7.3", + "rand_chacha 0.2.2", "sc-block-builder", - "sc-client", "sc-client-api", "sc-consensus-epochs", "sc-consensus-slots", @@ -6011,23 +6297,27 @@ dependencies = [ "sp-runtime", "sp-timestamp", "sp-version", + "substrate-prometheus-endpoint", "substrate-test-runtime-client", "tempfile", ] [[package]] name = "sc-consensus-babe-rpc" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "derive_more", - "futures 0.3.4", + "futures 0.3.5", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", + "sc-consensus", "sc-consensus-babe", "sc-consensus-epochs", "sc-keystore", + "sc-rpc-api", "serde", + "serde_json", "sp-api", "sp-application-crypto", "sp-blockchain", @@ -6042,11 +6332,11 @@ dependencies = [ [[package]] name = "sc-consensus-epochs" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "fork-tree", "parity-scale-codec", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "sc-client-api", "sp-blockchain", "sp-runtime", @@ -6054,39 +6344,40 @@ dependencies = [ [[package]] name = "sc-consensus-manual-seal" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "assert_matches", "derive_more", "env_logger 0.7.1", - "futures 0.3.4", + "futures 0.3.5", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", "log", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "sc-basic-authorship", - "sc-client", "sc-client-api", "sc-transaction-pool", "serde", "sp-blockchain", "sp-consensus", + "sp-core", "sp-inherents", "sp-runtime", "sp-transaction-pool", + "substrate-prometheus-endpoint", "substrate-test-runtime-client", "substrate-test-runtime-transaction-pool", "tempfile", - "tokio 0.2.13", + "tokio 0.2.18", ] [[package]] name = "sc-consensus-pow" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "derive_more", - "futures 0.3.4", + "futures 0.3.5", "log", "parity-scale-codec", "sc-client-api", @@ -6099,22 +6390,25 @@ dependencies = [ "sp-inherents", "sp-runtime", "sp-timestamp", + "substrate-prometheus-endpoint", ] [[package]] name = "sc-consensus-slots" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ - "futures 0.3.4", + "futures 0.3.5", "futures-timer 3.0.2", "log", "parity-scale-codec", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "sc-client-api", "sc-telemetry", "sp-api", + "sp-application-crypto", "sp-blockchain", "sp-consensus", + "sp-consensus-slots", "sp-core", "sp-inherents", "sp-runtime", @@ -6124,7 +6418,7 @@ dependencies = [ [[package]] name = "sc-consensus-uncles" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "log", "sc-client-api", @@ -6137,7 +6431,7 @@ dependencies = [ [[package]] name = "sc-executor" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "assert_matches", "derive_more", @@ -6147,11 +6441,13 @@ dependencies = [ "log", "parity-scale-codec", "parity-wasm 0.41.0", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "sc-executor-common", "sc-executor-wasmi", "sc-executor-wasmtime", "sc-runtime-test", + "sc-tracing", + "sp-api", "sp-core", "sp-externalities", "sp-io", @@ -6160,22 +6456,25 @@ dependencies = [ "sp-runtime-interface", "sp-serializer", "sp-state-machine", + "sp-tracing", "sp-trie", "sp-version", "sp-wasm-interface", "substrate-test-runtime", "test-case", + "tracing", "wabt", "wasmi", ] [[package]] name = "sc-executor-common" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "derive_more", "log", "parity-scale-codec", + "parity-wasm 0.41.0", "sp-allocator", "sp-core", "sp-runtime-interface", @@ -6186,11 +6485,10 @@ dependencies = [ [[package]] name = "sc-executor-wasmi" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "log", "parity-scale-codec", - "parity-wasm 0.41.0", "sc-executor-common", "sp-allocator", "sp-core", @@ -6201,9 +6499,11 @@ dependencies = [ [[package]] name = "sc-executor-wasmtime" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "assert_matches", + "cranelift-codegen", + "cranelift-wasm", "log", "parity-scale-codec", "parity-wasm 0.41.0", @@ -6214,26 +6514,29 @@ dependencies = [ "sp-runtime-interface", "sp-wasm-interface", "substrate-wasmtime", + "substrate-wasmtime-runtime", + "wasmtime-environ", ] [[package]] name = "sc-finality-grandpa" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "assert_matches", + "derive_more", "env_logger 0.7.1", "finality-grandpa", "fork-tree", - "futures 0.3.4", + "futures 0.3.5", "futures-timer 3.0.2", "log", "parity-scale-codec", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "pin-project", "rand 0.7.3", "sc-block-builder", - "sc-client", "sc-client-api", + "sc-consensus", "sc-keystore", "sc-network", "sc-network-gossip", @@ -6241,6 +6544,7 @@ dependencies = [ "sc-telemetry", "serde_json", "sp-api", + "sp-application-crypto", "sp-arithmetic", "sp-blockchain", "sp-consensus", @@ -6256,32 +6560,51 @@ dependencies = [ "substrate-prometheus-endpoint", "substrate-test-runtime-client", "tempfile", - "tokio 0.2.13", + "tokio 0.2.18", +] + +[[package]] +name = "sc-finality-grandpa-rpc" +version = "0.8.0-rc4" +dependencies = [ + "derive_more", + "finality-grandpa", + "futures 0.3.5", + "jsonrpc-core", + "jsonrpc-core-client", + "jsonrpc-derive", + "log", + "sc-finality-grandpa", + "serde", + "serde_json", + "sp-core", ] [[package]] name = "sc-informant" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "ansi_term 0.12.1", - "futures 0.3.4", + "futures 0.3.5", "log", - "parity-util-mem", + "parity-util-mem 0.7.0", "sc-client-api", "sc-network", - "sc-service", "sp-blockchain", "sp-runtime", + "sp-transaction-pool", + "sp-utils", "wasm-timer", ] [[package]] name = "sc-keystore" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "derive_more", "hex", - "parking_lot 0.10.0", + "merlin", + "parking_lot 0.10.2", "rand 0.7.3", "serde_json", "sp-application-crypto", @@ -6290,13 +6613,32 @@ dependencies = [ "tempfile", ] +[[package]] +name = "sc-light" +version = "2.0.0-rc4" +dependencies = [ + "hash-db", + "lazy_static", + "parity-scale-codec", + "parking_lot 0.10.2", + "sc-client-api", + "sc-executor", + "sp-api", + "sp-blockchain", + "sp-core", + "sp-externalities", + "sp-runtime", + "sp-state-machine", +] + [[package]] name = "sc-network" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "assert_matches", "async-std", "bitflags", + "bs58", "bytes 0.5.4", "derive_more", "either", @@ -6304,25 +6646,25 @@ dependencies = [ "erased-serde", "fnv", "fork-tree", - "futures 0.3.4", + "futures 0.3.5", "futures-timer 3.0.2", "futures_codec", "hex", + "ip_network", "libp2p", "linked-hash-map", "linked_hash_set", "log", - "lru", + "lru 0.4.3", "nohash-hasher", "parity-scale-codec", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "pin-project", "prost", "prost-build", "quickcheck", "rand 0.7.3", "sc-block-builder", - "sc-client", "sc-client-api", "sc-peerset", "serde", @@ -6333,7 +6675,6 @@ dependencies = [ "sp-arithmetic", "sp-blockchain", "sp-consensus", - "sp-consensus-babe", "sp-core", "sp-keyring", "sp-runtime", @@ -6344,7 +6685,7 @@ dependencies = [ "substrate-test-runtime-client", "tempfile", "thiserror", - "unsigned-varint", + "unsigned-varint 0.4.0", "void", "wasm-timer", "zeroize", @@ -6352,35 +6693,38 @@ dependencies = [ [[package]] name = "sc-network-gossip" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ - "futures 0.3.4", + "async-std", + "futures 0.3.5", "futures-timer 3.0.2", "libp2p", "log", - "lru", + "lru 0.4.3", + "quickcheck", + "rand 0.7.3", "sc-network", "sp-runtime", - "sp-utils", "substrate-test-runtime-client", "wasm-timer", ] [[package]] name = "sc-network-test" -version = "0.8.0-dev" +version = "0.8.0-rc4" dependencies = [ "env_logger 0.7.1", - "futures 0.3.4", + "futures 0.3.5", "futures-timer 3.0.2", "libp2p", "log", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "rand 0.7.3", "sc-block-builder", - "sc-client", "sc-client-api", + "sc-consensus", "sc-network", + "sc-service", "sp-blockchain", "sp-consensus", "sp-consensus-babe", @@ -6393,20 +6737,20 @@ dependencies = [ [[package]] name = "sc-offchain" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "bytes 0.5.4", "env_logger 0.7.1", - "fdlimit", "fnv", - "futures 0.3.4", + "futures 0.3.5", "futures-timer 3.0.2", - "hyper 0.13.3", + "hyper 0.13.4", "hyper-rustls", + "lazy_static", "log", "num_cpus", "parity-scale-codec", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "rand 0.7.3", "sc-client-api", "sc-client-db", @@ -6421,14 +6765,14 @@ dependencies = [ "sp-utils", "substrate-test-runtime-client", "threadpool", - "tokio 0.2.13", + "tokio 0.2.18", ] [[package]] name = "sc-peerset" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ - "futures 0.3.4", + "futures 0.3.5", "libp2p", "log", "rand 0.7.3", @@ -6437,21 +6781,29 @@ dependencies = [ "wasm-timer", ] +[[package]] +name = "sc-proposer-metrics" +version = "0.8.0-rc4" +dependencies = [ + "log", + "substrate-prometheus-endpoint", +] + [[package]] name = "sc-rpc" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "assert_matches", "futures 0.1.29", - "futures 0.3.4", + "futures 0.3.5", "hash-db", "jsonrpc-core", "jsonrpc-pubsub", + "lazy_static", "log", "parity-scale-codec", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "sc-block-builder", - "sc-client", "sc-client-api", "sc-executor", "sc-keystore", @@ -6461,6 +6813,7 @@ dependencies = [ "serde_json", "sp-api", "sp-blockchain", + "sp-chain-spec", "sp-core", "sp-io", "sp-offchain", @@ -6477,19 +6830,20 @@ dependencies = [ [[package]] name = "sc-rpc-api" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "derive_more", - "futures 0.3.4", + "futures 0.3.5", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", "jsonrpc-pubsub", "log", "parity-scale-codec", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "serde", "serde_json", + "sp-chain-spec", "sp-core", "sp-rpc", "sp-runtime", @@ -6499,10 +6853,11 @@ dependencies = [ [[package]] name = "sc-rpc-server" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "jsonrpc-core", "jsonrpc-http-server", + "jsonrpc-ipc-server", "jsonrpc-pubsub", "jsonrpc-ws-server", "log", @@ -6513,7 +6868,7 @@ dependencies = [ [[package]] name = "sc-runtime-test" -version = "2.0.0-dev" +version = "2.0.0-rc4" dependencies = [ "sp-allocator", "sp-core", @@ -6526,29 +6881,34 @@ dependencies = [ [[package]] name = "sc-service" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "derive_more", + "directories", "exit-future", "futures 0.1.29", - "futures 0.3.4", - "futures-diagnose", + "futures 0.3.5", "futures-timer 3.0.2", + "hash-db", + "jsonrpc-pubsub", "lazy_static", "log", "netstat2", - "parity-multiaddr", "parity-scale-codec", - "parity-util-mem", - "parking_lot 0.10.0", + "parity-util-mem 0.7.0", + "parking_lot 0.10.2", + "pin-project", "procfs", + "rand 0.7.3", + "sc-block-builder", "sc-chain-spec", - "sc-client", "sc-client-api", "sc-client-db", "sc-executor", "sc-finality-grandpa", + "sc-informant", "sc-keystore", + "sc-light", "sc-network", "sc-offchain", "sc-rpc", @@ -6561,68 +6921,88 @@ dependencies = [ "slog", "sp-api", "sp-application-crypto", + "sp-block-builder", "sp-blockchain", "sp-consensus", "sp-consensus-babe", "sp-core", + "sp-externalities", "sp-finality-grandpa", "sp-io", "sp-runtime", "sp-session", + "sp-state-machine", "sp-transaction-pool", + "sp-trie", "sp-utils", + "sp-version", "substrate-prometheus-endpoint", "substrate-test-runtime-client", "sysinfo", - "target_info", + "tempfile", "tracing", "wasm-timer", ] [[package]] name = "sc-service-test" -version = "2.0.0-dev" +version = "2.0.0-rc4" dependencies = [ "env_logger 0.7.1", "fdlimit", "futures 0.1.29", - "futures 0.3.4", + "futures 0.3.5", + "hex-literal", "log", - "sc-client", + "parity-scale-codec", + "parking_lot 0.10.2", + "sc-block-builder", + "sc-client-api", + "sc-client-db", + "sc-executor", + "sc-light", "sc-network", "sc-service", + "sp-api", + "sp-blockchain", "sp-consensus", "sp-core", + "sp-externalities", + "sp-panic-handler", "sp-runtime", + "sp-state-machine", + "sp-storage", "sp-transaction-pool", + "sp-trie", + "substrate-test-runtime", + "substrate-test-runtime-client", "tempfile", "tokio 0.1.22", ] [[package]] name = "sc-state-db" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "env_logger 0.7.1", "log", "parity-scale-codec", - "parity-util-mem", + "parity-util-mem 0.7.0", "parity-util-mem-derive", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "sc-client-api", "sp-core", ] [[package]] name = "sc-telemetry" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ - "bytes 0.5.4", - "futures 0.3.4", + "futures 0.3.5", "futures-timer 3.0.2", "libp2p", "log", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "pin-project", "rand 0.7.3", "serde", @@ -6636,32 +7016,34 @@ dependencies = [ [[package]] name = "sc-tracing" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "erased-serde", "log", - "parking_lot 0.10.0", + "parking_lot 0.10.2", + "rustc-hash", "sc-telemetry", "serde", "serde_json", "slog", + "sp-tracing", "tracing", "tracing-core", ] [[package]] name = "sc-transaction-graph" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "assert_matches", "criterion 0.3.1", "derive_more", - "futures 0.3.4", + "futures 0.3.5", "linked-hash-map", "log", "parity-scale-codec", - "parity-util-mem", - "parking_lot 0.10.0", + "parity-util-mem 0.7.0", + "parking_lot 0.10.2", "serde", "sp-blockchain", "sp-core", @@ -6674,27 +7056,31 @@ dependencies = [ [[package]] name = "sc-transaction-pool" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "assert_matches", "derive_more", - "futures 0.3.4", + "futures 0.3.5", "futures-diagnose", "hex", "intervalier", "log", "parity-scale-codec", - "parity-util-mem", - "parking_lot 0.10.0", + "parity-util-mem 0.7.0", + "parking_lot 0.10.2", + "sc-block-builder", "sc-client-api", "sc-transaction-graph", "sp-api", "sp-blockchain", + "sp-consensus", "sp-core", "sp-keyring", "sp-runtime", + "sp-tracing", "sp-transaction-pool", "sp-utils", + "substrate-prometheus-endpoint", "substrate-test-runtime-client", "substrate-test-runtime-transaction-pool", "wasm-timer", @@ -6702,9 +7088,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507a9e6e8ffe0a4e0ebb9a10293e62fdf7657c06f1b8bb07a8fcf697d2abf295" +checksum = "039c25b130bd8c1321ee2d7de7fde2659fa9c2744e4bb29711cfc852ea53cd19" dependencies = [ "lazy_static", "winapi 0.3.8", @@ -6756,8 +7142,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8584eea9b9ff42825b46faf46a8c24d2cff13ec152fa2a50df788b87c07ee28" dependencies = [ "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] @@ -6770,23 +7156,33 @@ dependencies = [ "untrusted", ] +[[package]] +name = "secrecy" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9182278ed645df3477a9c27bfee0621c621aa16f6972635f7f795dae3d81070f" +dependencies = [ + "zeroize", +] + [[package]] name = "security-framework" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97bbedbe81904398b6ebb054b3e912f99d55807125790f3198ac990d98def5b0" +checksum = "572dfa3a0785509e7a44b5b4bebcf94d41ba34e9ed9eb9df722545c3b3c4144a" dependencies = [ "bitflags", "core-foundation", "core-foundation-sys", + "libc", "security-framework-sys", ] [[package]] name = "security-framework-sys" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06fd2f23e31ef68dd2328cc383bd493142e46107a3a0e24f7d734e3f3b80fe4c" +checksum = "8ddb15a5fec93b7021b8a9e96009c5d8d51c15673569f7c0f6b7204e5b7b404f" dependencies = [ "core-foundation-sys", "libc", @@ -6837,29 +7233,29 @@ checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" [[package]] name = "serde" -version = "1.0.105" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e707fbbf255b8fc8c3b99abb91e7257a622caeb20a9818cbadbeeede4e0932ff" +checksum = "5317f7588f0a5078ee60ef675ef96735a1442132dc645eb1d12c018620ed8cd3" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.105" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac5d00fc561ba2724df6758a17de23df5914f20e41cb00f94d5b7ae42fffaff8" +checksum = "2a0be94b04690fbaed37cddffc5c134bf537c8e3329d53e982fe04c374978f8e" dependencies = [ "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] name = "serde_json" -version = "1.0.48" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25" +checksum = "3433e879a558dde8b5e8feb2a04899cf34fdde1fafb894687e52105fc1162ac3" dependencies = [ "itoa", "ryu", @@ -6878,12 +7274,6 @@ dependencies = [ "opaque-debug", ] -[[package]] -name = "sha1" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" - [[package]] name = "sha2" version = "0.8.1" @@ -6909,16 +7299,6 @@ dependencies = [ "opaque-debug", ] -[[package]] -name = "shell32-sys" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ee04b46101f57121c9da2b151988283b6beb79b34f5bb29a58ee48cb695122c" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - [[package]] name = "shlex" version = "0.1.1" @@ -6981,8 +7361,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a945ec7f7ce853e89ffa36be1e27dce9a43e82ff9093bf3461c30d5da74ed11b" dependencies = [ "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] @@ -6996,19 +7376,40 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.2.0" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3757cb9d89161a2f24e1cf78efa0c1fcff485d18e3f55e0aa3480824ddaa0f3f" + +[[package]] +name = "smol" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" +checksum = "620cbb3c6e34da57d3a248cda0cd01cd5848164dc062e764e65d06fe3ea7aed5" +dependencies = [ + "async-task", + "blocking", + "concurrent-queue", + "fastrand", + "futures-io", + "futures-util", + "libc", + "once_cell", + "scoped-tls", + "slab", + "socket2", + "wepoll-sys-stjepang", + "winapi 0.3.8", +] [[package]] name = "snow" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb767eee7d257ba202f0b9b08673bc13b22281632ef45267b19f13100accd2f" +checksum = "ce0f91be479494dd92e69d9971bd23ed27037dd1c94fcf558f6c6e74e6afa654" dependencies = [ - "arrayref", - "blake2-rfc", - "chacha20-poly1305-aead", + "aes-gcm", + "blake2", + "chacha20poly1305", "rand 0.7.3", "rand_core 0.5.1", "ring", @@ -7018,29 +7419,37 @@ dependencies = [ "x25519-dalek", ] +[[package]] +name = "socket2" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "winapi 0.3.8", +] + [[package]] name = "soketto" -version = "0.3.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c9dab3f95c9ebdf3a88268c19af668f637a3c5039c2c56ff2d40b1b2d64a25b" +checksum = "85457366ae0c6ce56bf05a958aef14cd38513c236568618edbcd9a8c52cb80b0" dependencies = [ - "base64 0.11.0", + "base64 0.12.0", "bytes 0.5.4", "flate2", - "futures 0.3.4", - "http 0.2.0", + "futures 0.3.5", "httparse", "log", "rand 0.7.3", - "sha1", - "smallvec 1.2.0", - "static_assertions", - "thiserror", + "sha-1", ] [[package]] name = "sp-allocator" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "derive_more", "log", @@ -7051,7 +7460,7 @@ dependencies = [ [[package]] name = "sp-api" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "hash-db", "parity-scale-codec", @@ -7066,18 +7475,18 @@ dependencies = [ [[package]] name = "sp-api-proc-macro" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "blake2-rfc", "proc-macro-crate", "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] name = "sp-api-test" -version = "2.0.0-dev" +version = "2.0.0-rc4" dependencies = [ "criterion 0.3.1", "parity-scale-codec", @@ -7096,7 +7505,7 @@ dependencies = [ [[package]] name = "sp-application-crypto" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "parity-scale-codec", "serde", @@ -7107,7 +7516,7 @@ dependencies = [ [[package]] name = "sp-application-crypto-test" -version = "2.0.0-dev" +version = "2.0.0-rc4" dependencies = [ "sp-api", "sp-application-crypto", @@ -7118,7 +7527,7 @@ dependencies = [ [[package]] name = "sp-arithmetic" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "criterion 0.3.1", "integer-sqrt", @@ -7127,13 +7536,14 @@ dependencies = [ "primitive-types", "rand 0.7.3", "serde", + "serde_json", "sp-debug-derive", "sp-std", ] [[package]] name = "sp-arithmetic-fuzzer" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "honggfuzz", "num-bigint", @@ -7144,7 +7554,7 @@ dependencies = [ [[package]] name = "sp-authority-discovery" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "parity-scale-codec", "sp-api", @@ -7155,7 +7565,7 @@ dependencies = [ [[package]] name = "sp-authorship" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "parity-scale-codec", "sp-inherents", @@ -7165,7 +7575,7 @@ dependencies = [ [[package]] name = "sp-block-builder" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "parity-scale-codec", "sp-api", @@ -7176,31 +7586,39 @@ dependencies = [ [[package]] name = "sp-blockchain" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "derive_more", "log", - "lru", + "lru 0.4.3", "parity-scale-codec", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "sp-block-builder", "sp-consensus", + "sp-database", "sp-runtime", "sp-state-machine", ] +[[package]] +name = "sp-chain-spec" +version = "2.0.0-rc4" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "sp-consensus" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "derive_more", - "futures 0.3.4", - "futures-diagnose", + "futures 0.3.5", "futures-timer 3.0.2", "libp2p", "log", "parity-scale-codec", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "serde", "sp-core", "sp-inherents", @@ -7208,13 +7626,16 @@ dependencies = [ "sp-state-machine", "sp-std", "sp-test-primitives", + "sp-trie", "sp-utils", "sp-version", + "substrate-prometheus-endpoint", + "wasm-timer", ] [[package]] name = "sp-consensus-aura" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "parity-scale-codec", "sp-api", @@ -7227,13 +7648,16 @@ dependencies = [ [[package]] name = "sp-consensus-babe" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ + "merlin", "parity-scale-codec", "sp-api", "sp-application-crypto", "sp-consensus", + "sp-consensus-slots", "sp-consensus-vrf", + "sp-core", "sp-inherents", "sp-runtime", "sp-std", @@ -7242,7 +7666,7 @@ dependencies = [ [[package]] name = "sp-consensus-pow" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "parity-scale-codec", "sp-api", @@ -7251,9 +7675,17 @@ dependencies = [ "sp-std", ] +[[package]] +name = "sp-consensus-slots" +version = "0.8.0-rc4" +dependencies = [ + "parity-scale-codec", + "sp-runtime", +] + [[package]] name = "sp-consensus-vrf" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "parity-scale-codec", "schnorrkel", @@ -7264,14 +7696,15 @@ dependencies = [ [[package]] name = "sp-core" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "base58", "blake2-rfc", - "byteorder 1.3.4", + "byteorder", "criterion 0.2.11", + "derive_more", "ed25519-dalek", - "futures 0.3.4", + "futures 0.3.5", "hash-db", "hash256-std-hasher", "hex", @@ -7280,15 +7713,18 @@ dependencies = [ "lazy_static", "libsecp256k1", "log", + "merlin", "num-traits 0.2.11", "parity-scale-codec", - "parity-util-mem", - "parking_lot 0.10.0", + "parity-util-mem 0.7.0", + "parking_lot 0.10.2", "pretty_assertions", "primitive-types", "rand 0.7.3", + "rand_chacha 0.2.2", "regex", "schnorrkel", + "secrecy", "serde", "serde_json", "sha2", @@ -7300,45 +7736,57 @@ dependencies = [ "sp-storage", "substrate-bip39", "tiny-bip39", - "tiny-keccak 2.0.1", + "tiny-keccak 2.0.2", "twox-hash", "wasmi", "zeroize", ] +[[package]] +name = "sp-database" +version = "2.0.0-rc4" +dependencies = [ + "kvdb 0.7.0", + "parking_lot 0.10.2", +] + [[package]] name = "sp-debug-derive" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] name = "sp-externalities" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "environmental", + "parity-scale-codec", "sp-std", "sp-storage", ] [[package]] name = "sp-finality-grandpa" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ + "finality-grandpa", + "log", "parity-scale-codec", "serde", "sp-api", "sp-application-crypto", + "sp-core", "sp-runtime", "sp-std", ] [[package]] name = "sp-finality-tracker" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "parity-scale-codec", "sp-inherents", @@ -7347,35 +7795,38 @@ dependencies = [ [[package]] name = "sp-inherents" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "derive_more", "parity-scale-codec", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "sp-core", "sp-std", ] [[package]] name = "sp-io" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ + "futures 0.3.5", "hash-db", "libsecp256k1", "log", "parity-scale-codec", + "parking_lot 0.10.2", "sp-core", "sp-externalities", "sp-runtime-interface", "sp-state-machine", "sp-std", + "sp-tracing", "sp-trie", "sp-wasm-interface", ] [[package]] name = "sp-keyring" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "lazy_static", "sp-core", @@ -7384,48 +7835,61 @@ dependencies = [ ] [[package]] -name = "sp-offchain" -version = "2.0.0-alpha.5" +name = "sp-npos-elections" +version = "2.0.0-rc4" dependencies = [ - "sp-api", + "parity-scale-codec", + "rand 0.7.3", + "serde", + "sp-arithmetic", + "sp-npos-elections-compact", "sp-runtime", + "sp-std", + "substrate-test-utils", ] [[package]] -name = "sp-panic-handler" -version = "2.0.0-alpha.5" +name = "sp-npos-elections-compact" +version = "2.0.0-rc4" dependencies = [ - "backtrace", - "log", + "proc-macro-crate", + "proc-macro2", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] -name = "sp-phragmen" +name = "sp-npos-elections-fuzzer" version = "2.0.0-alpha.5" dependencies = [ - "parity-scale-codec", + "honggfuzz", "rand 0.7.3", - "serde", - "sp-phragmen", - "sp-phragmen-compact", + "sp-npos-elections", "sp-runtime", "sp-std", - "substrate-test-utils", ] [[package]] -name = "sp-phragmen-compact" -version = "2.0.0-dev" +name = "sp-offchain" +version = "2.0.0-rc4" dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "sp-api", + "sp-core", + "sp-runtime", + "sp-state-machine", +] + +[[package]] +name = "sp-panic-handler" +version = "2.0.0-rc4" +dependencies = [ + "backtrace", + "log", ] [[package]] name = "sp-rpc" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "serde", "serde_json", @@ -7434,13 +7898,14 @@ dependencies = [ [[package]] name = "sp-runtime" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ + "either", "hash256-std-hasher", "impl-trait-for-tuples", "log", "parity-scale-codec", - "parity-util-mem", + "parity-util-mem 0.7.0", "paste", "rand 0.7.3", "serde", @@ -7450,12 +7915,13 @@ dependencies = [ "sp-core", "sp-inherents", "sp-io", + "sp-state-machine", "sp-std", ] [[package]] name = "sp-runtime-interface" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "parity-scale-codec", "primitive-types", @@ -7467,6 +7933,7 @@ dependencies = [ "sp-runtime-interface-test-wasm", "sp-state-machine", "sp-std", + "sp-tracing", "sp-wasm-interface", "static_assertions", "trybuild", @@ -7474,31 +7941,33 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "Inflector", "proc-macro-crate", "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] name = "sp-runtime-interface-test" -version = "2.0.0-dev" +version = "2.0.0-rc4" dependencies = [ "sc-executor", + "sp-core", "sp-io", "sp-runtime", "sp-runtime-interface", "sp-runtime-interface-test-wasm", "sp-runtime-interface-test-wasm-deprecated", "sp-state-machine", + "tracing", ] [[package]] name = "sp-runtime-interface-test-wasm" -version = "2.0.0-dev" +version = "2.0.0-rc4" dependencies = [ "sp-core", "sp-io", @@ -7509,7 +7978,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-test-wasm-deprecated" -version = "2.0.0-dev" +version = "2.0.0-rc4" dependencies = [ "sp-core", "sp-io", @@ -7520,7 +7989,7 @@ dependencies = [ [[package]] name = "sp-sandbox" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "assert_matches", "parity-scale-codec", @@ -7534,7 +8003,7 @@ dependencies = [ [[package]] name = "sp-serializer" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "serde", "serde_json", @@ -7542,17 +8011,19 @@ dependencies = [ [[package]] name = "sp-session" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ + "parity-scale-codec", "sp-api", "sp-core", "sp-runtime", + "sp-staking", "sp-std", ] [[package]] name = "sp-staking" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "parity-scale-codec", "sp-runtime", @@ -7561,15 +8032,18 @@ dependencies = [ [[package]] name = "sp-state-machine" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "hash-db", "hex-literal", + "itertools 0.9.0", "log", "num-traits 0.2.11", "parity-scale-codec", - "parking_lot 0.10.0", + "parking_lot 0.10.2", + "pretty_assertions", "rand 0.7.3", + "smallvec 1.4.1", "sp-core", "sp-externalities", "sp-panic-handler", @@ -7581,13 +8055,14 @@ dependencies = [ [[package]] name = "sp-std" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" [[package]] name = "sp-storage" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "impl-serde 0.2.3", + "ref-cast", "serde", "sp-debug-derive", "sp-std", @@ -7595,10 +8070,10 @@ dependencies = [ [[package]] name = "sp-test-primitives" -version = "2.0.0-dev" +version = "2.0.0-rc4" dependencies = [ "parity-scale-codec", - "parity-util-mem", + "parity-util-mem 0.7.0", "serde", "sp-application-crypto", "sp-core", @@ -7607,7 +8082,7 @@ dependencies = [ [[package]] name = "sp-timestamp" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", @@ -7618,23 +8093,33 @@ dependencies = [ "wasm-timer", ] +[[package]] +name = "sp-tracing" +version = "2.0.0-rc4" +dependencies = [ + "log", + "rental", + "tracing", +] + [[package]] name = "sp-transaction-pool" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "derive_more", - "futures 0.3.4", + "futures 0.3.5", "log", "parity-scale-codec", "serde", "sp-api", + "sp-blockchain", "sp-runtime", "sp-utils", ] [[package]] name = "sp-trie" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "criterion 0.2.11", "hash-db", @@ -7652,17 +8137,18 @@ dependencies = [ [[package]] name = "sp-utils" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ - "futures 0.3.4", + "futures 0.3.5", "futures-core", + "futures-timer 3.0.2", "lazy_static", "prometheus", ] [[package]] name = "sp-version" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "impl-serde 0.2.3", "parity-scale-codec", @@ -7673,7 +8159,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", @@ -7743,9 +8229,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" -version = "0.3.11" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fe43617218c0805c6eb37160119dc3c548110a67786da7218d1c6555212f073" +checksum = "ff6da2e8d107dfd7b74df5ef4d205c6aebee0706c647f6bc6a2d5789905c00fb" dependencies = [ "clap", "lazy_static", @@ -7754,15 +8240,15 @@ dependencies = [ [[package]] name = "structopt-derive" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6e79c80e0f4efd86ca960218d4e056249be189ff1c42824dcd9a7f51a56f0bd" +checksum = "a489c87c08fbaf12e386665109dd13470dcc9c4583ea3e10dd2b4523e5ebd9ac" dependencies = [ "heck", "proc-macro-error", "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] @@ -7782,13 +8268,13 @@ checksum = "0054a7df764039a6cd8592b9de84be4bec368ff081d203a7d5371cbfa8e65c81" dependencies = [ "heck", "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] name = "subkey" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "clap", "derive_more", @@ -7797,12 +8283,13 @@ dependencies = [ "hex", "hex-literal", "hyper 0.12.35", - "itertools", + "itertools 0.8.2", "jsonrpc-core-client", "libp2p", "node-primitives", "node-runtime", "pallet-balances", + "pallet-grandpa", "pallet-transaction-payment", "parity-scale-codec", "rand 0.7.3", @@ -7829,14 +8316,14 @@ dependencies = [ [[package]] name = "substrate-browser-utils" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "chrono", "clear_on_drop", "console_error_panic_hook", "console_log", "futures 0.1.29", - "futures 0.3.4", + "futures 0.3.5", "futures-timer 3.0.2", "js-sys", "kvdb-web", @@ -7848,46 +8335,52 @@ dependencies = [ "sc-informant", "sc-network", "sc-service", + "sp-database", "wasm-bindgen", "wasm-bindgen-futures", ] [[package]] name = "substrate-build-script-utils" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" +dependencies = [ + "platforms", +] [[package]] name = "substrate-frame-rpc-support" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "frame-support", "frame-system", - "futures 0.3.4", + "futures 0.3.5", "jsonrpc-client-transports", "jsonrpc-core", "parity-scale-codec", "sc-rpc-api", "serde", "sp-storage", - "tokio 0.2.13", + "tokio 0.2.18", ] [[package]] name = "substrate-frame-rpc-system" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" dependencies = [ "env_logger 0.7.1", "frame-system-rpc-runtime-api", - "futures 0.3.4", + "futures 0.3.5", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", "log", "parity-scale-codec", - "sc-client", + "sc-client-api", + "sc-rpc-api", "sc-transaction-pool", "serde", "sp-api", + "sp-block-builder", "sp-blockchain", "sp-core", "sp-runtime", @@ -7897,28 +8390,34 @@ dependencies = [ [[package]] name = "substrate-prometheus-endpoint" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" dependencies = [ "async-std", "derive_more", "futures-util", - "hyper 0.13.3", + "hyper 0.13.4", "log", "prometheus", - "tokio 0.2.13", + "tokio 0.2.18", ] [[package]] name = "substrate-test-client" -version = "2.0.0-dev" +version = "2.0.0-rc4" dependencies = [ - "futures 0.3.4", + "futures 0.1.29", + "futures 0.3.5", "hash-db", + "hex", "parity-scale-codec", - "sc-client", "sc-client-api", "sc-client-db", + "sc-consensus", "sc-executor", + "sc-light", + "sc-service", + "serde", + "serde_json", "sp-blockchain", "sp-consensus", "sp-core", @@ -7929,7 +8428,7 @@ dependencies = [ [[package]] name = "substrate-test-runtime" -version = "2.0.0-dev" +version = "2.0.0-rc4" dependencies = [ "cfg-if", "frame-executive", @@ -7941,10 +8440,10 @@ dependencies = [ "pallet-babe", "pallet-timestamp", "parity-scale-codec", - "parity-util-mem", + "parity-util-mem 0.7.0", "sc-block-builder", - "sc-client", "sc-executor", + "sc-service", "serde", "sp-api", "sp-application-crypto", @@ -7952,6 +8451,7 @@ dependencies = [ "sp-consensus-aura", "sp-consensus-babe", "sp-core", + "sp-finality-grandpa", "sp-inherents", "sp-io", "sp-keyring", @@ -7971,15 +8471,18 @@ dependencies = [ [[package]] name = "substrate-test-runtime-client" -version = "2.0.0-dev" +version = "2.0.0-rc4" dependencies = [ - "futures 0.3.4", + "futures 0.3.5", "parity-scale-codec", "sc-block-builder", - "sc-client", "sc-client-api", + "sc-consensus", + "sc-light", + "sc-service", "sp-api", "sp-blockchain", + "sp-consensus", "sp-core", "sp-runtime", "substrate-test-client", @@ -7988,12 +8491,12 @@ dependencies = [ [[package]] name = "substrate-test-runtime-transaction-pool" -version = "2.0.0-dev" +version = "2.0.0-rc4" dependencies = [ "derive_more", - "futures 0.3.4", + "futures 0.3.5", "parity-scale-codec", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "sc-transaction-graph", "sp-blockchain", "sp-runtime", @@ -8003,17 +8506,17 @@ dependencies = [ [[package]] name = "substrate-test-utils" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" [[package]] name = "substrate-wasm-builder" -version = "1.0.9" +version = "1.0.11" dependencies = [ "atty", "build-helper", "cargo_metadata", "fs2", - "itertools", + "itertools 0.8.2", "tempfile", "toml", "walkdir", @@ -8022,13 +8525,13 @@ dependencies = [ [[package]] name = "substrate-wasm-builder-runner" -version = "1.0.5" +version = "1.0.6" [[package]] name = "substrate-wasmtime" -version = "0.13.0-threadsafe.1" +version = "0.16.0-threadsafe.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e512629525ecfe43bffe1f3d9e6bb0f08bf01155288ef27fcaae4ea086e4a9d" +checksum = "6bd62264edc1a5f3ef44d86fb0c11c9fb142894b9a2da034f34afae482080d7a" dependencies = [ "anyhow", "backtrace", @@ -8038,20 +8541,20 @@ dependencies = [ "region", "rustc-demangle", "substrate-wasmtime-jit", + "substrate-wasmtime-profiling", "substrate-wasmtime-runtime", "target-lexicon", - "wasmparser", + "wasmparser 0.52.2", "wasmtime-environ", - "wasmtime-profiling", "wat", "winapi 0.3.8", ] [[package]] name = "substrate-wasmtime-jit" -version = "0.13.0-threadsafe.1" +version = "0.16.0-threadsafe.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a20de5564886d2bcffdd351c9cd114ceb50758aa58eac3cedb14faabf7f93b91" +checksum = "4ce43c159d4f3ef6b19641e1ae045847fd202d8e2cc74df7ccb2b6475e069d4a" dependencies = [ "anyhow", "cfg-if", @@ -8060,23 +8563,44 @@ dependencies = [ "cranelift-frontend", "cranelift-native", "cranelift-wasm", + "gimli", + "log", "more-asserts", "region", + "substrate-wasmtime-profiling", "substrate-wasmtime-runtime", "target-lexicon", "thiserror", - "wasmparser", + "wasmparser 0.52.2", "wasmtime-debug", "wasmtime-environ", - "wasmtime-profiling", "winapi 0.3.8", ] +[[package]] +name = "substrate-wasmtime-profiling" +version = "0.16.0-threadsafe.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c77f0ce539b5a09a54dc80a1cf0c7cd7e694df11029354fe50a2d5fe889bdb97" +dependencies = [ + "anyhow", + "cfg-if", + "gimli", + "lazy_static", + "libc", + "object", + "scroll", + "serde", + "substrate-wasmtime-runtime", + "target-lexicon", + "wasmtime-environ", +] + [[package]] name = "substrate-wasmtime-runtime" -version = "0.13.0-threadsafe.1" +version = "0.16.0-threadsafe.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d08846f04293a7fc27eeb30f06262ca2e1b4ee20f5192cec1f3ce201e08ceb8" +checksum = "46516af0a64a7d9b652c5aa7436b6ce13edfa54435a66ef177fc02d2283e2dc2" dependencies = [ "backtrace", "cc", @@ -8089,7 +8613,6 @@ dependencies = [ "region", "thiserror", "wasmtime-environ", - "wasmtime-profiling", "winapi 0.3.8", ] @@ -8118,12 +8641,12 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.16" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859" +checksum = "e8d5d96e8cbb005d6959f119f773bfaebb5684296108fb32600c00cde305b2cd" dependencies = [ "proc-macro2", - "quote 1.0.3", + "quote 1.0.6", "unicode-xid 0.2.0", ] @@ -8134,8 +8657,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a" dependencies = [ "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] @@ -8154,16 +8677,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" dependencies = [ "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", "unicode-xid 0.2.0", ] [[package]] name = "sysinfo" -version = "0.12.0" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ccb41798287e8e299a701b5560d886d6ca2c3e7115e9ea2cb68c123aec339b7" +checksum = "5a0338198966bde7feb14b011a33d404a62a6e03b843352c71512a2a002634b7" dependencies = [ "cfg-if", "doc-comment", @@ -8186,12 +8709,6 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab0e7238dcc7b40a7be719a25365910f6807bd864f4cce6b2e6b873658e2b19d" -[[package]] -name = "target_info" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c63f48baada5c52e65a29eef93ab4f8982681b67f9e8d29c7b05abcfec2b9ffe" - [[package]] name = "tempfile" version = "3.1.0" @@ -8223,8 +8740,8 @@ checksum = "a605baa797821796a751f4a959e1206079b24a4b7e1ed302b7d785d81a9276c9" dependencies = [ "lazy_static", "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", "version_check", ] @@ -8239,22 +8756,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.11" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee14bf8e6767ab4c687c9e8bc003879e042a96fd67a3ba5934eadb6536bef4db" +checksum = "54b3d3d2ff68104100ab257bb6bb0cb26c901abe4bd4ba15961f3bf867924012" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.11" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7b51e1fbc44b5a0840be594fbc0f960be09050f2617e61e6aa43bef97cd3ef4" +checksum = "ca972988113b7715266f91250ddb98070d033c62a011fa0fcc57434a649310dd" dependencies = [ "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] @@ -8288,9 +8805,9 @@ dependencies = [ [[package]] name = "tiny-bip39" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6848cd8f566953ce1e8faeba12ee23cbdbb0437754792cd857d44628b5685e3" +checksum = "b0165e045cc2ae1660270ca65e1676dbaab60feb0f91b10f7d0665e9b47e31f2" dependencies = [ "failure", "hmac", @@ -8313,9 +8830,9 @@ dependencies = [ [[package]] name = "tiny-keccak" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2953ca5148619bc99695c1274cb54c5275bbb913c6adad87e72eaf8db9787f69" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" dependencies = [ "crunchy", ] @@ -8356,12 +8873,13 @@ dependencies = [ [[package]] name = "tokio" -version = "0.2.13" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa5e81d6bc4e67fe889d5783bd2a128ab2e0cfa487e0be16b6a8d177b101616" +checksum = "34ef16d072d2b6dc8b4a56c70f5c5ced1a37752116f8e7c1e80c659aa7cb6713" dependencies = [ "bytes 0.5.4", "fnv", + "futures-core", "iovec", "lazy_static", "libc", @@ -8458,8 +8976,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389" dependencies = [ "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", +] + +[[package]] +name = "tokio-named-pipes" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d282d483052288b2308ba5ee795f5673b159c9bdf63c385a05609da782a5eae" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.29", + "mio", + "mio-named-pipes", + "tokio 0.1.22", ] [[package]] @@ -8483,16 +9014,25 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4adb8b3e5f86b707f1b54e7c15b6de52617a823608ccda98a15d3a24222f265a" +checksum = "15cb62a0d2770787abc96e99c1cd98fcf17f94959f3af63ca85bdfb203f051b4" dependencies = [ "futures-core", - "rustls 0.17.0", - "tokio 0.2.13", + "rustls", + "tokio 0.2.18", "webpki", ] +[[package]] +name = "tokio-service" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162" +dependencies = [ + "futures 0.1.29", +] + [[package]] name = "tokio-sync" version = "0.1.8" @@ -8592,16 +9132,16 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930" +checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" dependencies = [ "bytes 0.5.4", "futures-core", "futures-sink", "log", "pin-project-lite", - "tokio 0.2.13", + "tokio 0.2.18", ] [[package]] @@ -8621,9 +9161,9 @@ checksum = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" [[package]] name = "tracing" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1721cc8cf7d770cc4257872507180f35a4797272f5962f24c806af9e7faf52ab" +checksum = "a7c6b59d116d218cb2d990eb06b77b64043e0268ef7323aae63d8b30ae462923" dependencies = [ "cfg-if", "tracing-attributes", @@ -8632,12 +9172,13 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbad39da2f9af1cae3016339ad7f2c7a9e870f12e8fd04c4fd7ef35b30c0d2b" +checksum = "99bbad0de3fd923c9c3232ead88510b783e5a4d16a6154adffa3d53308de984c" dependencies = [ - "quote 1.0.3", - "syn 1.0.16", + "proc-macro2", + "quote 1.0.6", + "syn 1.0.33", ] [[package]] @@ -8657,9 +9198,9 @@ checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41" [[package]] name = "trie-bench" -version = "0.21.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f105ed33e42b534284b691e804e909c42a8898afcf22896a32255c05a1a50488" +checksum = "24987a413863acfa081fb75051d0c2824cd4c450e2f0a7e03dca93ac989775fc" dependencies = [ "criterion 0.2.11", "hash-db", @@ -8673,15 +9214,15 @@ dependencies = [ [[package]] name = "trie-db" -version = "0.20.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de9222c50cc325855621271157c973da27a0dcd26fa06f8edf81020bd2333df0" +checksum = "39f1a9a9252d38c5337cf0c5392988821a5cf1b2103245016968f2ab41de9e38" dependencies = [ "hash-db", - "hashbrown", + "hashbrown 0.8.0", "log", "rustc-hex", - "smallvec 1.2.0", + "smallvec 1.4.1", ] [[package]] @@ -8711,9 +9252,9 @@ checksum = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" [[package]] name = "trybuild" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b4e093c5ed1a60b22557090120aa14f90ca801549c0949d775ea07c1407720" +checksum = "459186ab1afd6d93bd23c2269125f4f7694f8771fe0e64434b4bdc212b94034d" dependencies = [ "glob 0.3.0", "lazy_static", @@ -8730,7 +9271,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712d261e83e727c8e2dbb75dacac67c36e35db36a958ee504f2164fc052434e1" dependencies = [ "block-cipher-trait", - "byteorder 1.3.4", + "byteorder", "opaque-debug", ] @@ -8745,9 +9286,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.11.2" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" +checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" [[package]] name = "uint" @@ -8755,7 +9296,7 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e75a4cdd7b87b28840dba13c483b9a88ee6bbf16ba5c951ee1ecfcf723078e0d" dependencies = [ - "byteorder 1.3.4", + "byteorder", "crunchy", "rustc-hex", "static_assertions", @@ -8785,7 +9326,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" dependencies = [ - "smallvec 1.2.0", + "smallvec 1.4.1", ] [[package]] @@ -8812,11 +9353,27 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +[[package]] +name = "universal-hash" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0c900f2f9b4116803415878ff48b63da9edb268668e08cf9292d7503114a01" +dependencies = [ + "generic-array", + "subtle 2.2.2", +] + [[package]] name = "unsigned-varint" -version = "0.3.2" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f67332660eb59a6f1eb24ff1220c9e8d01738a8503c6002e30bcfe4bd9f2b4a9" + +[[package]] +name = "unsigned-varint" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38e01ad4b98f042e166c1bf9a13f9873a99d79eaa171ce7ca81e6dd0f895d8a" +checksum = "669d776983b692a906c881fcd0cfb34271a48e197e4d6cb8df32b05bfc3d3fa5" dependencies = [ "bytes 0.5.4", "futures-io", @@ -8852,12 +9409,6 @@ dependencies = [ "percent-encoding 2.1.0", ] -[[package]] -name = "uuid" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11" - [[package]] name = "vcpkg" version = "0.2.8" @@ -8870,16 +9421,6 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -[[package]] -name = "vergen" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ce50d8996df1f85af15f2cd8d33daae6e479575123ef4314a51a70a230739cb" -dependencies = [ - "bitflags", - "chrono", -] - [[package]] name = "version_check" version = "0.9.1" @@ -8906,9 +9447,9 @@ dependencies = [ [[package]] name = "wabt-sys" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af5d153dc96aad7dc13ab90835b892c69867948112d95299e522d370c4e13a08" +checksum = "23d7043ebb3e5d96fad7a8d3ca22ee9880748ff8c3e18092cfb2a49d3b8f9084" dependencies = [ "cc", "cmake", @@ -8924,6 +9465,12 @@ dependencies = [ "libc", ] +[[package]] +name = "waker-fn" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9571542c2ce85ce642e6b58b3364da2fb53526360dfb7c211add4f5c23105ff7" + [[package]] name = "walkdir" version = "2.3.1" @@ -8964,34 +9511,36 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasm-bindgen" -version = "0.2.59" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3557c397ab5a8e347d434782bcd31fc1483d927a6826804cec05cc792ee2519d" +checksum = "e3c7d40d09cdbf0f4895ae58cf57d92e1e57a9dd8ed2e8390514b54a47cc5551" dependencies = [ "cfg-if", + "serde", + "serde_json", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.59" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0da9c9a19850d3af6df1cb9574970b566d617ecfaf36eb0b706b6f3ef9bd2f8" +checksum = "c3972e137ebf830900db522d6c8fd74d1900dcfc733462e9a12e942b00b4ac94" dependencies = [ "bumpalo", "lazy_static", "log", "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "457414a91863c0ec00090dba537f88ab955d93ca6555862c29b6d860990b8a8a" +checksum = "7add542ea1ac7fdaa9dc25e031a6af33b7d63376292bd24140c637d00d1c312a" dependencies = [ "cfg-if", "js-sys", @@ -9001,32 +9550,56 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.59" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f6fde1d36e75a714b5fe0cffbb78978f222ea6baebb726af13c78869fdb4205" +checksum = "2cd85aa2c579e8892442954685f0d801f9129de24fa2136b2c6a539c76b65776" dependencies = [ - "quote 1.0.3", + "quote 1.0.6", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.59" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25bda4168030a6412ea8a047e27238cadf56f0e53516e1e83fec0a8b7c786f6d" +checksum = "8eb197bd3a47553334907ffd2f16507b4f4f01bbec3ac921a7719e0decdfe72a" dependencies = [ "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.59" +version = "0.2.62" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a91c2916119c17a8e316507afaaa2dd94b47646048014bbdf6bef098c1bb58ad" + +[[package]] +name = "wasm-bindgen-test" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "648da3460c6d2aa04b715a936329e2e311180efe650b2127d6267f4193ccac14" +dependencies = [ + "console_error_panic_hook", + "js-sys", + "scoped-tls", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test-macro", +] + +[[package]] +name = "wasm-bindgen-test-macro" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc9f36ad51f25b0219a3d4d13b90eb44cd075dff8b6280cca015775d7acaddd8" +checksum = "cf2f86cd78a2aa7b1fb4bb6ed854eccb7f9263089c79542dca1576a1518a8467" +dependencies = [ + "proc-macro2", + "quote 1.0.6", +] [[package]] name = "wasm-gc-api" @@ -9045,7 +9618,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "324c5e65a08699c9c4334ba136597ab22b85dccd4b65dd1e36ccf8f723a95b54" dependencies = [ - "futures 0.3.4", + "futures 0.3.5", "js-sys", "parking_lot 0.9.0", "pin-utils", @@ -9085,11 +9658,17 @@ version = "0.51.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aeb1956b19469d1c5e63e459d29e7b5aa0f558d9f16fcef09736f8a265e6c10a" +[[package]] +name = "wasmparser" +version = "0.52.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "733954023c0b39602439e60a65126fd31b003196d3a1e8e4531b055165a79b31" + [[package]] name = "wasmtime-debug" -version = "0.12.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d3d007436043bf55ec252d2f4dc1d35834157b5e2f148da839ca502e611cfe1" +checksum = "d39ba645aee700b29ff0093028b4123556dd142a74973f04ed6225eedb40e77d" dependencies = [ "anyhow", "faerie", @@ -9097,18 +9676,18 @@ dependencies = [ "more-asserts", "target-lexicon", "thiserror", - "wasmparser", + "wasmparser 0.51.4", "wasmtime-environ", ] [[package]] name = "wasmtime-environ" -version = "0.12.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80f3dea0e60c076dd0da27fa10c821323903c9554c617ed32eaab8e7a7e36c89" +checksum = "ed54fd9d64dfeeee7c285fd126174a6b5e6d4efc7e5a1566fdb635e60ff6a74e" dependencies = [ "anyhow", - "base64 0.11.0", + "base64 0.12.0", "bincode", "cranelift-codegen", "cranelift-entity", @@ -9125,50 +9704,34 @@ dependencies = [ "sha2", "thiserror", "toml", - "wasmparser", + "wasmparser 0.51.4", "winapi 0.3.8", "zstd", ] -[[package]] -name = "wasmtime-profiling" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "984d29c8add3381e60d649f4e3e2a501da900fc2d2586e139502eec32fe0ebc8" -dependencies = [ - "gimli", - "goblin", - "lazy_static", - "libc", - "object", - "scroll", - "serde", - "target-lexicon", -] - [[package]] name = "wast" -version = "10.0.0" +version = "13.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4efb62ecebf5cc9dbf2954309a20d816289c6550c0597a138b9e811cefc05007" +checksum = "5b20abd8b4a26f7e0d4dd5e357e90a3d555ec190e94472c9b2b27c5b9777f9ae" dependencies = [ "leb128", ] [[package]] name = "wat" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdea5e25273cc3a62f3ae3a1a4c7d7996625875b50c0b4475fee6698c2b069c" +checksum = "51a615830ee3e7200b505c441fec09aac2f114deae69df52f215cb828ba112c4" dependencies = [ "wast", ] [[package]] name = "web-sys" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "721c6263e2c66fd44501cc5efbfa2b7dfa775d13e4ea38c46299646ed1f9c70a" +checksum = "2d6f51648d8c56c366144378a33290049eafdd784071077f6fe37dae64c1c4cb" dependencies = [ "js-sys", "wasm-bindgen", @@ -9186,22 +9749,31 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a262ae37dd9d60f60dd473d1158f9fbebf110ba7b6a5051c8160460f6043718b" +checksum = "91cd5736df7f12a964a5067a12c62fa38e1bd8080aff1f80bc29be7c80d19ab4" dependencies = [ "webpki", ] [[package]] name = "webpki-roots" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91cd5736df7f12a964a5067a12c62fa38e1bd8080aff1f80bc29be7c80d19ab4" +checksum = "f8eff4b7516a57307f9349c64bf34caa34b940b66fed4b2fb3136cb7386e5739" dependencies = [ "webpki", ] +[[package]] +name = "wepoll-sys-stjepang" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fd319e971980166b53e17b1026812ad66c6b54063be879eb182342b55284694" +dependencies = [ + "cc", +] + [[package]] name = "which" version = "3.1.1" @@ -9241,9 +9813,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ccfbf554c6ad11084fb7517daca16cfdcaccbdadba4fc336f032a8b12c2ad80" +checksum = "fa515c5163a99cc82bab70fd3bfdd36d827be85de63737b40fcef2ce084a436e" dependencies = [ "winapi 0.3.8", ] @@ -9260,7 +9832,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c51a2c47b5798ccc774ffb93ff536aec7c4275d722fd9c740c83cdd1af1f2d94" dependencies = [ - "byteorder 1.3.4", + "byteorder", "bytes 0.4.12", "httparse", "log", @@ -9293,22 +9865,16 @@ dependencies = [ "zeroize", ] -[[package]] -name = "xdg" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57" - [[package]] name = "yamux" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84300bb493cc878f3638b981c62b4632ec1a5c52daaa3036651e8c106d3b55ea" +checksum = "cd37e58a1256a0b328ce9c67d8b62ecdd02f4803ba443df478835cb1a41a637c" dependencies = [ - "futures 0.3.4", + "futures 0.3.5", "log", "nohash-hasher", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "rand 0.7.3", "static_assertions", ] @@ -9329,8 +9895,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de251eec69fc7c1bc3923403d18ececb929380e016afe103da75f396704f8ca2" dependencies = [ "proc-macro2", - "quote 1.0.3", - "syn 1.0.16", + "quote 1.0.6", + "syn 1.0.33", "synstructure", ] diff --git a/Cargo.toml b/Cargo.toml index b5829073853dc21cdf305b39de6564421cb63505..ba146e55bca3fb5d5b0c2b0e5e1f5bbc37b1c4ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "bin/node-template/runtime", "bin/node-template/pallets/template", "bin/node/bench", + "bin/node/browser-testing", "bin/node/cli", "bin/node/executor", "bin/node/primitives", @@ -11,10 +12,8 @@ members = [ "bin/node/rpc", "bin/node/runtime", "bin/node/testing", - "bin/node/transaction-factory", "bin/utils/subkey", "bin/utils/chain-spec-builder", - "client", "client/api", "client/authority-discovery", "client/basic-authorship", @@ -25,6 +24,7 @@ members = [ "client/consensus/aura", "client/consensus/babe", "client/consensus/babe/rpc", + "client/consensus/common", "client/consensus/manual-seal", "client/consensus/pow", "client/consensus/uncles", @@ -38,6 +38,7 @@ members = [ "client/executor/runtime-test", "client/finality-grandpa", "client/informant", + "client/light", "client/tracing", "client/keystore", "client/network", @@ -45,6 +46,7 @@ members = [ "client/network-gossip", "client/offchain", "client/peerset", + "client/proposer-metrics", "client/rpc-servers", "client/rpc", "client/rpc-api", @@ -58,6 +60,7 @@ members = [ "utils/wasm-builder-runner", "frame/assets", "frame/aura", + "frame/atomic-swap", "frame/authority-discovery", "frame/authorship", "frame/babe", @@ -83,8 +86,10 @@ members = [ "frame/indices", "frame/membership", "frame/metadata", + "frame/multisig", "frame/nicks", "frame/offences", + "frame/proxy", "frame/randomness-collective-flip", "frame/recovery", "frame/scheduler", @@ -94,6 +99,7 @@ members = [ "frame/society", "frame/staking", "frame/staking/reward-curve", + "frame/staking/fuzzer", "frame/sudo", "frame/support", "frame/support/procedural", @@ -101,6 +107,7 @@ members = [ "frame/support/procedural/tools/derive", "frame/support/test", "frame/system", + "frame/system/benchmarking", "frame/system/rpc/runtime-api", "frame/timestamp", "frame/transaction-payment", @@ -122,6 +129,8 @@ members = [ "primitives/consensus/pow", "primitives/consensus/vrf", "primitives/core", + "primitives/chain-spec", + "primitives/database", "primitives/debug-derive", "primitives/storage", "primitives/externalities", @@ -131,8 +140,9 @@ members = [ "primitives/keyring", "primitives/offchain", "primitives/panic-handler", - "primitives/phragmen", - "primitives/phragmen/compact", + "primitives/npos-elections", + "primitives/npos-elections/fuzzer", + "primitives/npos-elections/compact", "primitives/rpc", "primitives/runtime-interface", "primitives/runtime-interface/proc-macro", @@ -156,6 +166,7 @@ members = [ "primitives/timestamp", "primitives/test-primitives", "primitives/transaction-pool", + "primitives/tracing", "primitives/trie", "primitives/utils", "primitives/wasm-interface", @@ -172,6 +183,74 @@ members = [ "utils/wasm-builder", ] +# The list of dependencies below (which can be both direct and indirect dependencies) are crates +# that are suspected to be CPU-intensive, and that are unlikely to require debugging (as some of +# their debug info might be missing) or to require to be frequently recompiled. We compile these +# dependencies with `opt-level=3` even in "dev" mode in order to make "dev" mode more usable. +# The majority of these crates are cryptographic libraries. +# +# Note that this does **not** affect crates that depend on Substrate. In other words, if you add +# a dependency on Substrate, you have to copy-paste this list in your own `Cargo.toml` (assuming +# that you want the same list). This list is only relevant when running `cargo build` from within +# the Substrate workspace. +# +# If you see an error mentioning "profile package spec ... did not match any packages", it +# probably concerns this list. +# +# This list is ordered alphabetically. +[profile.dev.package] +aes-ctr = { opt-level = 3 } +aes-soft = { opt-level = 3 } +aesni = { opt-level = 3 } +blake2 = { opt-level = 3 } +blake2-rfc = { opt-level = 3 } +blake2b_simd = { opt-level = 3 } +blake2s_simd = { opt-level = 3 } +chacha20poly1305 = { opt-level = 3 } +cranelift-codegen = { opt-level = 3 } +cranelift-wasm = { opt-level = 3 } +crc32fast = { opt-level = 3 } +crossbeam-deque = { opt-level = 3 } +crossbeam-queue = { opt-level = 3 } +crypto-mac = { opt-level = 3 } +ctr = { opt-level = 3 } +curve25519-dalek = { opt-level = 3 } +ed25519-dalek = { opt-level = 3 } +evm-core = { opt-level = 3 } +evm-runtime = { opt-level = 3 } +flate2 = { opt-level = 3 } +futures-channel = { opt-level = 3 } +hashbrown = { opt-level = 3 } +h2 = { opt-level = 3 } +hash-db = { opt-level = 3 } +hmac = { opt-level = 3 } +httparse = { opt-level = 3 } +integer-sqrt = { opt-level = 3 } +keccak = { opt-level = 3 } +libm = { opt-level = 3 } +librocksdb-sys = { opt-level = 3 } +libsecp256k1 = { opt-level = 3 } +libz-sys = { opt-level = 3 } +mio = { opt-level = 3 } +nalgebra = { opt-level = 3 } +num-bigint = { opt-level = 3 } +parking_lot = { opt-level = 3 } +parking_lot_core = { opt-level = 3 } +percent-encoding = { opt-level = 3 } +primitive-types = { opt-level = 3 } +ring = { opt-level = 3 } +rustls = { opt-level = 3 } +sha2 = { opt-level = 3 } +sha3 = { opt-level = 3 } +smallvec = { opt-level = 3 } +snow = { opt-level = 3 } +twox-hash = { opt-level = 3 } +uint = { opt-level = 3 } +wasmi = { opt-level = 3 } +x25519-dalek = { opt-level = 3 } +yamux = { opt-level = 3 } +zeroize = { opt-level = 3 } + [profile.release] # Substrate runtime requires unwinding. panic = "unwind" diff --git a/LICENSE-APACHE2 b/LICENSE-APACHE2 new file mode 100644 index 0000000000000000000000000000000000000000..fbb0616d18b261c461b5a004f6bba6dda702ec09 --- /dev/null +++ b/LICENSE-APACHE2 @@ -0,0 +1,211 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +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. + + NOTE + +Individual files contain the following tag instead of the full license +text. + + SPDX-License-Identifier: Apache-2.0 + +This enables machine processing of license information based on the SPDX +License Identifiers that are here available: http://spdx.org/licenses/ \ No newline at end of file diff --git a/LICENSE b/LICENSE-GPL3 similarity index 96% rename from LICENSE rename to LICENSE-GPL3 index 9cecc1d4669ee8af2ca727a5d8cde10cd8b2d7cc..2ba7526ee695722852efd2c162ea57f87e4fd54c 100644 --- a/LICENSE +++ b/LICENSE-GPL3 @@ -672,3 +672,29 @@ may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . + + "CLASSPATH" EXCEPTION TO THE GPL + + Linking this library statically or dynamically with other modules is making +a combined work based on this library. Thus, the terms and conditions of the +GNU General Public License cover the whole combination. + + As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent modules, +and to copy and distribute the resulting executable under terms of your +choice, provided that you also meet, for each linked independent module, +the terms and conditions of the license of that module. An independent +module is a module which is not derived from or based on this library. +If you modify this library, you may extend this exception to your version +of the library, but you are not obligated to do so. If you do not wish to +do so, delete this exception statement from your version. + + NOTE + + Individual files contain the following tag instead of the full license text. + + SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + + This enables machine processing of license information based on the SPDX +License Identifiers that are here available: http://spdx.org/licenses/ \ No newline at end of file diff --git a/Process.toml b/Process.toml new file mode 100644 index 0000000000000000000000000000000000000000..ecaf5c7120ff5cb1b5cc0f923b51e7fda4df9fca --- /dev/null +++ b/Process.toml @@ -0,0 +1,24 @@ +[Networking] +owner = "tomaka" +whitelist = [] +matrix_room_id = "!vUADSGcyXmxhKLeDsW:matrix.parity.io" + +[Client] +owner = "gnunicorn" +whitelist = [] +matrix_room_id = "!aenJixaHcSKbJOWxYk:matrix.parity.io" + +[Runtime] +owner = "gavofyork" +whitelist = [] +matrix_room_id = "!yBKstWVBkwzUkPslsp:matrix.parity.io" + +[Consensus] +owner = "andresilva" +whitelist = [] +matrix_room_id = "!XdNWDTfVNFVixljKZU:matrix.parity.io" + +[Smart Contracts] +owner = "pepyakin" +whitelist = [] +matrix_room_id = "!yBKstWVBkwzUkPslsp:matrix.parity.io" diff --git a/README.md b/README.md index cd00013d1ae8ad4fb86dee4044061f9b7b5e732b..5764722373d434289d2c0c29d42144869af87b11 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,17 @@ -# Substrate · [![GitHub license](https://img.shields.io/github/license/paritytech/substrate)](LICENSE) [![GitLab Status](https://gitlab.parity.io/parity/substrate/badges/master/pipeline.svg)](https://gitlab.parity.io/parity/substrate/pipelines) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](docs/CONTRIBUTING.adoc) +# Substrate · [![GitHub license](https://img.shields.io/badge/license-GPL3%2FApache2-blue)](LICENSE) [![GitLab Status](https://gitlab.parity.io/parity/substrate/badges/master/pipeline.svg)](https://gitlab.parity.io/parity/substrate/pipelines) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](docs/CONTRIBUTING.adoc) -Substrate is a next-generation framework for blockchain innovation. +

+ +

+ + +Substrate is a next-generation framework for blockchain innovation 🚀. ## Trying it out -Simply go to [substrate.dev](https://substrate.dev) and follow the [getting started](https://substrate.dev/docs/en/overview/getting-started/) instructions. +Simply go to [substrate.dev](https://substrate.dev) and follow the +[installation](https://substrate.dev/docs/en/knowledgebase/getting-started/) instructions. You can +also try out one of the [tutorials](https://substrate.dev/en/tutorials). ## Contributions & Code of Conduct @@ -16,4 +23,9 @@ The security policy and procedures can be found in [`docs/SECURITY.md`](docs/SEC ## License -Substrate is [GPL 3.0 licensed](LICENSE). +- Substrate Primitives (`sp-*`), Frame (`frame-*`) and the pallets (`pallets-*`), binaries (`/bin`) and all other utilities are licensed under [Apache 2.0](LICENSE-APACHE2). +- Substrate Client (`/client/*` / `sc-*`) is licensed under [GPL v3.0 with a classpath linking exception](LICENSE-GPL3). + +The reason for the split-licensing is to ensure that for the vast majority of teams using Substrate to create feature-chains, then all changes can be made entirely in Apache2-licensed code, allowing teams full freedom over what and how they release and giving licensing clarity to commercial teams. + +In the interests of the community, we require any deeper improvements made to Substrate's core logic (e.g. Substrate's internal consensus, crypto or database code) to be contributed back so everyone can benefit. diff --git a/bin/node-template/README.md b/bin/node-template/README.md index 4ae60478fc72b77f32664b4225c023c36ff5f1af..3317d04d549a19f7e495fb5c92af952d163465e6 100644 --- a/bin/node-template/README.md +++ b/bin/node-template/README.md @@ -1,54 +1,76 @@ +[![Substrate Playground](https://img.shields.io/badge/Playground-node_template-brightgreen?logo=Parity%20Substrate)](https://playground-staging.substrate.dev/?deploy=node-template) + # Substrate Node Template -A new FRAME-based Substrate node, ready for hacking. +A new FRAME-based Substrate node, ready for hacking :rocket: -## Build +## Local Development -Install Rust: +Follow these steps to prepare a local Substrate development environment :hammer_and_wrench: -```bash -curl https://sh.rustup.rs -sSf | sh -``` +### Simple Setup -Initialize your Wasm Build environment: +Install all the required dependencies with a single command (be patient, this can take up +to 30 minutes). ```bash -./scripts/init.sh +curl https://getsubstrate.io -sSf | bash -s -- --fast ``` -Build Wasm and native code: +### Manual Setup + +Find manual setup instructions at the [Substrate Developer Hub](https://substrate.dev/docs/en/knowledgebase/getting-started/#manual-installation). + +### Build + +Once the development environment is set up, build the node template. This command will build the +[Wasm](https://substrate.dev/docs/en/knowledgebase/advanced/executor#wasm-execution) and +[native](https://substrate.dev/docs/en/knowledgebase/advanced/executor#native-execution) code: ```bash cargo build --release ``` +## Playground [![Substrate Playground](https://img.shields.io/badge/Playground-node_template-brightgreen?logo=Parity%20Substrate)](https://playground-staging.substrate.dev/?deploy=node-template) + +[The Substrate Playground](https://playground-staging.substrate.dev/?deploy=node-template) is an +online development environment that supplies a pre-configured container with pre-compiled build +artifacts :cartwheeling: + ## Run -### Single node development chain +### Single Node Development Chain -Purge any existing developer chain state: +Purge any existing dev chain state: ```bash ./target/release/node-template purge-chain --dev ``` -Start a development chain with: +Start a dev chain: ```bash ./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`. +Or, start a dev chain with detailed logging: -### Multi-node local testnet +```bash +RUST_LOG=debug RUST_BACKTRACE=1 ./target/release/node-template -lruntime=debug --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. +### Multi-Node Local Testnet -Optionally, give each node a name and expose them so they are listed on the Polkadot [telemetry site](https://telemetry.polkadot.io/#/Local%20Testnet). +To see the multi-node consensus algorithm in action, run a local testnet with two validator nodes, +Alice and Bob, that have been [configured](/bin/node-template/node/src/chain_spec.rs) as the +initial authorities of the `local` testnet chain and endowed with testnet units. -You'll need two terminal windows open. +Note: this will require two terminal sessions (one for each node). -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: +Start Alice's node first. The command below uses the default TCP port (30333) and specifies +`/tmp/alice` as the chain database location. Alice's node ID will be +`12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp` (legacy representation: +`QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR`); this is determined by the `node-key`. ```bash cargo run -- \ @@ -56,21 +78,46 @@ cargo run -- \ --chain=local \ --alice \ --node-key 0000000000000000000000000000000000000000000000000000000000000001 \ - --telemetry-url ws://telemetry.polkadot.io:1024 \ + --telemetry-url 'ws://telemetry.polkadot.io:1024 0' \ --validator ``` -In the second terminal, we'll 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 another terminal, use the following command to start Bob's node on a different TCP port (30334) +and with a chain database location of `/tmp/bob`. The `--bootnodes` option will connect his node to +Alice's on TCP port 30333: ```bash cargo run -- \ --base-path /tmp/bob \ - --bootnodes /ip4/127.0.0.1/tcp/30333/p2p/QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR \ + --bootnodes /ip4/127.0.0.1/tcp/30333/p2p/12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp \ --chain=local \ --bob \ --port 30334 \ - --telemetry-url ws://telemetry.polkadot.io:1024 \ + --ws-port 9945 \ + --telemetry-url 'ws://telemetry.polkadot.io:1024 0' \ --validator ``` -Additional CLI usage options are available and may be shown by running `cargo run -- --help`. +Execute `cargo run -- --help` to learn more about the template node's CLI options. + +## Generate a Custom Node Template + +Generate a Substrate node template based on a particular commit by running the following commands: + +```bash +# Clone from the main Substrate repo +git clone https://github.com/paritytech/substrate.git +cd substrate + +# Switch to the branch or commit to base the template on +git checkout + +# Run the helper script to generate a node template. This script compiles Substrate, so it will take +# a while to complete. It expects a single parameter: the location for the script's output expressed +# as a relative path. +.maintain/node-template-release.sh ../node-template.tar.gz +``` + +Custom node templates are not supported. Please use a recently tagged version of the +[Substrate Developer Node Template](https://github.com/substrate-developer-hub/substrate-node-template) +in order to receive support. diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index b312d311118026092cc11b338b5c47dcf4428fc3..0533c5926b4b22c889850cc5106238df54f5033c 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -1,13 +1,17 @@ [package] name = "node-template" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Anonymous"] +description = "A new FRAME-based Substrate node, ready for hacking." edition = "2018" license = "Unlicense" build = "build.rs" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [[bin]] name = "node-template" @@ -15,30 +19,27 @@ name = "node-template" futures = "0.3.4" log = "0.4.8" structopt = "0.3.8" +parking_lot = "0.10.0" -sc-cli = { version = "0.8.0-alpha.5", path = "../../../client/cli" } -sp-core = { version = "2.0.0-alpha.5", path = "../../../primitives/core" } -sc-executor = { version = "0.8.0-alpha.5", path = "../../../client/executor" } -sc-service = { version = "0.8.0-alpha.5", path = "../../../client/service" } -sp-inherents = { version = "2.0.0-alpha.5", path = "../../../primitives/inherents" } -sc-transaction-pool = { version = "2.0.0-alpha.5", path = "../../../client/transaction-pool" } -sp-transaction-pool = { version = "2.0.0-alpha.5", path = "../../../primitives/transaction-pool" } -sc-network = { version = "0.8.0-alpha.5", path = "../../../client/network" } -sc-consensus-aura = { version = "0.8.0-alpha.5", path = "../../../client/consensus/aura" } -sp-consensus-aura = { version = "0.8.0-alpha.5", path = "../../../primitives/consensus/aura" } -sp-consensus = { version = "0.8.0-alpha.5", path = "../../../primitives/consensus/common" } -sc-finality-grandpa = { version = "0.8.0-alpha.5", path = "../../../client/finality-grandpa" } -sp-finality-grandpa = { version = "2.0.0-alpha.5", path = "../../../primitives/finality-grandpa" } -sc-client = { version = "0.8.0-alpha.5", path = "../../../client/" } -sc-client-api = { version = "2.0.0-alpha.5", path = "../../../client/api" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime" } -sc-basic-authorship = { path = "../../../client/basic-authorship", version = "0.8.0-alpha.5"} +sc-cli = { version = "0.8.0-rc4", path = "../../../client/cli", features = ["wasmtime"] } +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } +sc-executor = { version = "0.8.0-rc4", path = "../../../client/executor", features = ["wasmtime"] } +sc-service = { version = "0.8.0-rc4", path = "../../../client/service", features = ["wasmtime"] } +sp-inherents = { version = "2.0.0-rc4", path = "../../../primitives/inherents" } +sc-transaction-pool = { version = "2.0.0-rc4", path = "../../../client/transaction-pool" } +sp-transaction-pool = { version = "2.0.0-rc4", path = "../../../primitives/transaction-pool" } +sc-network = { version = "0.8.0-rc4", path = "../../../client/network" } +sc-consensus-aura = { version = "0.8.0-rc4", path = "../../../client/consensus/aura" } +sp-consensus-aura = { version = "0.8.0-rc4", path = "../../../primitives/consensus/aura" } +sp-consensus = { version = "0.8.0-rc4", path = "../../../primitives/consensus/common" } +sc-consensus = { version = "0.8.0-rc4", path = "../../../client/consensus/common" } +sc-finality-grandpa = { version = "0.8.0-rc4", path = "../../../client/finality-grandpa" } +sp-finality-grandpa = { version = "2.0.0-rc4", path = "../../../primitives/finality-grandpa" } +sc-client-api = { version = "2.0.0-rc4", path = "../../../client/api" } +sp-runtime = { version = "2.0.0-rc4", path = "../../../primitives/runtime" } +sc-basic-authorship = { path = "../../../client/basic-authorship", version = "0.8.0-rc4"} -node-template-runtime = { version = "2.0.0-alpha.5", path = "../runtime" } +node-template-runtime = { version = "2.0.0-rc4", path = "../runtime" } [build-dependencies] -vergen = "3.0.4" -build-script-utils = { version = "2.0.0-alpha.5", package = "substrate-build-script-utils", path = "../../../utils/build-script-utils" } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +substrate-build-script-utils = { version = "2.0.0-rc4", path = "../../../utils/build-script-utils" } diff --git a/bin/node-template/node/build.rs b/bin/node-template/node/build.rs index 222cbb409285b40e7204cd609d444854dd4082aa..e3bfe3116bf28dba1872f7d0b64c2ee0c9c71c3c 100644 --- a/bin/node-template/node/build.rs +++ b/bin/node-template/node/build.rs @@ -1,9 +1,7 @@ -use vergen::{ConstantsFlags, generate_cargo_keys}; - -const ERROR_MSG: &str = "Failed to generate metadata files"; +use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed}; fn main() { - generate_cargo_keys(ConstantsFlags::SHA_SHORT).expect(ERROR_MSG); + generate_cargo_keys(); - build_script_utils::rerun_if_git_head_changed(); + rerun_if_git_head_changed(); } diff --git a/bin/node-template/node/src/chain_spec.rs b/bin/node-template/node/src/chain_spec.rs index b57000fed7b642bd5d08503feb2e6dcd3b6f354d..fb53edd9a1a06b44fd2626feda427b79b0c08a5f 100644 --- a/bin/node-template/node/src/chain_spec.rs +++ b/bin/node-template/node/src/chain_spec.rs @@ -3,10 +3,10 @@ use node_template_runtime::{ AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, SudoConfig, SystemConfig, WASM_BINARY, Signature }; -use sp_consensus_aura::sr25519::{AuthorityId as AuraId}; -use sp_finality_grandpa::{AuthorityId as GrandpaId}; -use sc_service; +use sp_consensus_aura::sr25519::AuthorityId as AuraId; +use sp_finality_grandpa::AuthorityId as GrandpaId; use sp_runtime::traits::{Verify, IdentifyAccount}; +use sc_service::ChainType; // Note this is the URL for the telemetry server //const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; @@ -14,17 +14,6 @@ use sp_runtime::traits::{Verify, IdentifyAccount}; /// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. pub type ChainSpec = sc_service::GenericChainSpec; -/// The chain specification option. This is expected to come in from the CLI and -/// is little more than one of a number of alternatives which can easily be converted -/// from a string (`--chain=...`) into a `ChainSpec`. -#[derive(Clone, Debug)] -pub enum Alternative { - /// Whatever the current runtime is, with just Alice as an auth. - Development, - /// Whatever the current runtime is, with simple Alice/Bob auths. - LocalTestnet, -} - /// Helper function to generate a crypto pair from seed pub fn get_from_seed(seed: &str) -> ::Public { TPublic::Pair::from_string(&format!("//{}", seed), None) @@ -42,80 +31,72 @@ pub fn get_account_id_from_seed(seed: &str) -> AccountId where } /// Helper function to generate an authority key for Aura -pub fn get_authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) { +pub fn authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) { ( get_from_seed::(s), get_from_seed::(s), ) } -impl Alternative { - /// Get an actual chain config from one of the alternatives. - pub(crate) fn load(self) -> Result { - Ok(match self { - Alternative::Development => ChainSpec::from_genesis( - "Development", - "dev", - || testnet_genesis( - vec![ - 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"), - ], - true, - ), - vec![], - None, - None, - None, - None - ), - Alternative::LocalTestnet => ChainSpec::from_genesis( - "Local Testnet", - "local_testnet", - || testnet_genesis( - vec![ - get_authority_keys_from_seed("Alice"), - get_authority_keys_from_seed("Bob"), - ], - 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, - None, - None - ), - }) - } +pub fn development_config() -> ChainSpec { + ChainSpec::from_genesis( + "Development", + "dev", + ChainType::Development, + || testnet_genesis( + vec![ + 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"), + ], + true, + ), + vec![], + None, + None, + None, + None, + ) +} - pub(crate) fn from(s: &str) -> Option { - match s { - "dev" => Some(Alternative::Development), - "" | "local" => Some(Alternative::LocalTestnet), - _ => None, - } - } +pub fn local_testnet_config() -> ChainSpec { + ChainSpec::from_genesis( + "Local Testnet", + "local_testnet", + ChainType::Local, + || testnet_genesis( + vec![ + authority_keys_from_seed("Alice"), + authority_keys_from_seed("Bob"), + ], + 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, + None, + None, + ) } fn testnet_genesis(initial_authorities: Vec<(AuraId, GrandpaId)>, @@ -141,10 +122,3 @@ fn testnet_genesis(initial_authorities: Vec<(AuraId, GrandpaId)>, }), } } - -pub fn load_spec(id: &str) -> Result, String> { - Ok(match Alternative::from(id) { - Some(spec) => Box::new(spec.load()?), - None => Box::new(ChainSpec::from_json_file(std::path::PathBuf::from(id))?), - }) -} diff --git a/bin/node-template/node/src/command.rs b/bin/node-template/node/src/command.rs index 0f4c301dbff5b7defe0565bf71e85b21a6418867..3391ad2c8928969263cbdc6d15e7914338d648f9 100644 --- a/bin/node-template/node/src/command.rs +++ b/bin/node-template/node/src/command.rs @@ -1,49 +1,83 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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. +// 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. -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use sp_consensus_aura::sr25519::{AuthorityPair as AuraPair}; -use sc_cli::VersionInfo; -use crate::service; use crate::chain_spec; use crate::cli::Cli; +use crate::service; +use sc_cli::{SubstrateCli, RuntimeVersion, Role, ChainSpec}; -/// Parse and run command line arguments -pub fn run(version: VersionInfo) -> sc_cli::Result<()> { - let opt = sc_cli::from_args::(&version); +impl SubstrateCli for Cli { + fn impl_name() -> String { + "Substrate Node".into() + } + + fn impl_version() -> String { + env!("SUBSTRATE_CLI_IMPL_VERSION").into() + } + + fn description() -> String { + env!("CARGO_PKG_DESCRIPTION").into() + } + + fn author() -> String { + env!("CARGO_PKG_AUTHORS").into() + } - let mut config = sc_service::Configuration::from_version(&version); + fn support_url() -> String { + "support.anonymous.an".into() + } + + fn copyright_start_year() -> i32 { + 2017 + } + + fn load_spec(&self, id: &str) -> Result, String> { + Ok(match id { + "dev" => Box::new(chain_spec::development_config()), + "" | "local" => Box::new(chain_spec::local_testnet_config()), + path => Box::new(chain_spec::ChainSpec::from_json_file( + std::path::PathBuf::from(path), + )?), + }) + } + + fn native_runtime_version(_: &Box) -> &'static RuntimeVersion { + &node_template_runtime::VERSION + } +} + +/// Parse and run command line arguments +pub fn run() -> sc_cli::Result<()> { + let cli = Cli::from_args(); - match opt.subcommand { + match &cli.subcommand { Some(subcommand) => { - subcommand.init(&version)?; - subcommand.update_config(&mut config, chain_spec::load_spec, &version)?; - subcommand.run( - config, - |config: _| Ok(new_full_start!(config).0), - ) - }, + let runner = cli.create_runner(subcommand)?; + runner.run_subcommand(subcommand, |config| { + let (builder, _, _) = new_full_start!(config); + Ok(builder.to_chain_ops_parts()) + }) + } None => { - opt.run.init(&version)?; - opt.run.update_config(&mut config, chain_spec::load_spec, &version)?; - opt.run.run( - config, - service::new_light, - service::new_full, - &version, - ) - }, + let runner = cli.create_runner(&cli.run)?; + runner.run_node_until_exit(|config| match config.role { + Role::Light => service::new_light(config), + _ => service::new_full(config), + }) + } } } diff --git a/bin/node-template/node/src/lib.rs b/bin/node-template/node/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..38e43372ca3ff45d40015e83fc45a221f599f16d --- /dev/null +++ b/bin/node-template/node/src/lib.rs @@ -0,0 +1,2 @@ +pub mod chain_spec; +pub mod service; diff --git a/bin/node-template/node/src/main.rs b/bin/node-template/node/src/main.rs index 91b2c257e0cd733f7e87d00e02857101810a2fb0..369e6932a030811b542ae8de9f26e9324f22e069 100644 --- a/bin/node-template/node/src/main.rs +++ b/bin/node-template/node/src/main.rs @@ -8,16 +8,5 @@ mod cli; mod command; fn main() -> sc_cli::Result<()> { - let version = sc_cli::VersionInfo { - name: "Substrate Node", - commit: env!("VERGEN_SHA_SHORT"), - version: env!("CARGO_PKG_VERSION"), - executable_name: "node-template", - author: "Anonymous", - description: "Template Node", - support_url: "support.anonymous.an", - copyright_start_year: 2017, - }; - - command::run(version) + command::run() } diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index b8c1b32b56c385d52d649f375c570ce5a7870368..2d1cc878b41cb67c2701b2de28722150cfed7bdd 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -2,15 +2,20 @@ use std::sync::Arc; use std::time::Duration; -use sc_client::LongestChain; use sc_client_api::ExecutorProvider; +use sc_consensus::LongestChain; use node_template_runtime::{self, opaque::Block, RuntimeApi}; -use sc_service::{error::{Error as ServiceError}, AbstractService, Configuration, ServiceBuilder}; +use sc_service::{ + error::{Error as ServiceError}, Configuration, ServiceBuilder, ServiceComponents, + TaskManager, +}; use sp_inherents::InherentDataProviders; use sc_executor::native_executor_instance; pub use sc_executor::NativeExecutor; use sp_consensus_aura::sr25519::{AuthorityPair as AuraPair}; -use sc_finality_grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider, StorageAndProofProvider}; +use sc_finality_grandpa::{ + FinalityProofProvider as GrandpaFinalityProofProvider, StorageAndProofProvider, SharedVoterState, +}; // Our native executor instance. native_executor_instance!( @@ -26,37 +31,62 @@ native_executor_instance!( macro_rules! new_full_start { ($config:expr) => {{ use std::sync::Arc; + use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; + let mut import_setup = None; let inherent_data_providers = sp_inherents::InherentDataProviders::new(); let builder = sc_service::ServiceBuilder::new_full::< - node_template_runtime::opaque::Block, node_template_runtime::RuntimeApi, crate::service::Executor + node_template_runtime::opaque::Block, + node_template_runtime::RuntimeApi, + crate::service::Executor >($config)? .with_select_chain(|_config, backend| { - Ok(sc_client::LongestChain::new(backend.clone())) + Ok(sc_consensus::LongestChain::new(backend.clone())) })? - .with_transaction_pool(|config, client, _fetcher| { - let pool_api = sc_transaction_pool::FullChainApi::new(client.clone()); - Ok(sc_transaction_pool::BasicPool::new(config, std::sync::Arc::new(pool_api))) + .with_transaction_pool(|builder| { + let pool_api = sc_transaction_pool::FullChainApi::new( + builder.client().clone(), + None, + ); + Ok(sc_transaction_pool::BasicPool::new_full( + builder.config().transaction_pool.clone(), + std::sync::Arc::new(pool_api), + builder.prometheus_registry(), + builder.spawn_handle(), + builder.client().clone(), + )) })? - .with_import_queue(|_config, client, mut select_chain, _transaction_pool| { + .with_import_queue(| + _config, + client, + mut select_chain, + _transaction_pool, + spawn_task_handle, + registry, + | { let select_chain = select_chain.take() .ok_or_else(|| sc_service::Error::SelectChainRequired)?; - let (grandpa_block_import, grandpa_link) = - sc_finality_grandpa::block_import(client.clone(), &(client.clone() as Arc<_>), select_chain)?; + let (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import( + client.clone(), + &(client.clone() as Arc<_>), + select_chain, + )?; let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new( grandpa_block_import.clone(), client.clone(), ); - let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair>( + let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _>( sc_consensus_aura::slot_duration(&*client)?, aura_block_import, Some(Box::new(grandpa_block_import.clone())), None, client, inherent_data_providers.clone(), + spawn_task_handle, + registry, )?; import_setup = Some((grandpa_block_import, grandpa_link)); @@ -69,12 +99,10 @@ macro_rules! new_full_start { } /// Builds a new service for a full client. -pub fn new_full(config: Configuration) - -> Result -{ +pub fn new_full(config: Configuration) -> Result { let role = config.role.clone(); let force_authoring = config.force_authoring; - let name = config.name.clone(); + let name = config.network.node_name.clone(); let disable_grandpa = config.disable_grandpa; let (builder, mut import_setup, inherent_data_providers) = new_full_start!(config); @@ -83,20 +111,25 @@ pub fn new_full(config: Configuration) import_setup.take() .expect("Link Half and Block Import are present for Full Services or setup failed before. qed"); - let service = builder + let ServiceComponents { + client, transaction_pool, task_manager, keystore, network, select_chain, + prometheus_registry, telemetry_on_connect_sinks, .. + } = builder .with_finality_proof_provider(|client, backend| { // GenesisAuthoritySetProvider is implemented for StorageAndProofProvider let provider = client as Arc>; Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, provider)) as _) })? - .build()?; + .build_full()?; if role.is_authority() { - let proposer = - sc_basic_authorship::ProposerFactory::new(service.client(), service.transaction_pool()); + let proposer = sc_basic_authorship::ProposerFactory::new( + client.clone(), + transaction_pool, + prometheus_registry.as_ref(), + ); - let client = service.client(); - let select_chain = service.select_chain() + let select_chain = select_chain .ok_or(ServiceError::SelectChainRequired)?; let can_author_with = @@ -104,26 +137,26 @@ pub fn new_full(config: Configuration) let aura = sc_consensus_aura::start_aura::<_, _, _, _, _, AuraPair, _, _, _>( sc_consensus_aura::slot_duration(&*client)?, - client, + client.clone(), select_chain, block_import, proposer, - service.network(), + network.clone(), inherent_data_providers.clone(), force_authoring, - service.keystore(), + keystore.clone(), can_author_with, )?; // the AURA authoring task is considered essential, i.e. if it // fails we take down the service with it. - service.spawn_essential_task("aura", aura); + task_manager.spawn_essential_handle().spawn_blocking("aura", 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 role.is_authority() { - Some(service.keystore()) + Some(keystore.clone() as sp_core::traits::BareCryptoStorePtr) } else { None }; @@ -149,51 +182,65 @@ pub fn new_full(config: Configuration) let grandpa_config = sc_finality_grandpa::GrandpaParams { config: grandpa_config, link: grandpa_link, - network: service.network(), + network: network.clone(), inherent_data_providers: inherent_data_providers.clone(), - telemetry_on_connect: Some(service.telemetry_on_connect_stream()), + telemetry_on_connect: Some(telemetry_on_connect_sinks.on_connect_stream()), voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(), - prometheus_registry: service.prometheus_registry() + prometheus_registry: prometheus_registry.clone(), + shared_voter_state: SharedVoterState::empty(), }; // the GRANDPA voter task is considered infallible, i.e. // if it fails we take down the service with it. - service.spawn_essential_task( + task_manager.spawn_essential_handle().spawn_blocking( "grandpa-voter", sc_finality_grandpa::run_grandpa_voter(grandpa_config)? ); } else { sc_finality_grandpa::setup_disabled_grandpa( - service.client(), + client, &inherent_data_providers, - service.network(), + network.clone(), )?; } - Ok(service) + Ok(task_manager) } /// Builds a new service for a light client. -pub fn new_light(config: Configuration) - -> Result -{ +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, fetcher| { - let fetcher = fetcher + .with_transaction_pool(|builder| { + let fetcher = builder.fetcher() .ok_or_else(|| "Trying to start light transaction pool without active fetcher")?; - let pool_api = sc_transaction_pool::LightChainApi::new(client.clone(), fetcher.clone()); - let pool = sc_transaction_pool::BasicPool::with_revalidation_type( - config, Arc::new(pool_api), sc_transaction_pool::RevalidationType::Light, + let pool_api = sc_transaction_pool::LightChainApi::new( + builder.client().clone(), + fetcher.clone(), ); + let pool = Arc::new(sc_transaction_pool::BasicPool::new_light( + builder.config().transaction_pool.clone(), + Arc::new(pool_api), + builder.prometheus_registry(), + builder.spawn_handle(), + )); Ok(pool) })? - .with_import_queue_and_fprb(|_config, client, backend, fetcher, _select_chain, _tx_pool| { + .with_import_queue_and_fprb(| + _config, + client, + backend, + fetcher, + _select_chain, + _tx_pool, + spawn_task_handle, + prometheus_registry, + | { let fetch_checker = fetcher .map(|fetcher| fetcher.checker().clone()) .ok_or_else(|| "Trying to start light import queue without active fetch checker")?; @@ -207,13 +254,15 @@ pub fn new_light(config: Configuration) let finality_proof_request_builder = finality_proof_import.create_finality_proof_request_builder(); - let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair>( + let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _>( sc_consensus_aura::slot_duration(&*client)?, grandpa_block_import, None, Some(Box::new(finality_proof_import)), client, inherent_data_providers.clone(), + spawn_task_handle, + prometheus_registry, )?; Ok((import_queue, finality_proof_request_builder)) @@ -223,5 +272,6 @@ pub fn new_light(config: Configuration) let provider = client as Arc>; Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, provider)) as _) })? - .build() + .build_light() + .map(|ServiceComponents { task_manager, .. }| task_manager) } diff --git a/bin/node-template/pallets/template/Cargo.toml b/bin/node-template/pallets/template/Cargo.toml index 69fcd843526806c9fe9a0b6e684a292fcbfe778b..442fb7203098cde8c071e889b6628bfa11e3d175 100644 --- a/bin/node-template/pallets/template/Cargo.toml +++ b/bin/node-template/pallets/template/Cargo.toml @@ -2,37 +2,41 @@ authors = ['Anonymous'] edition = '2018' name = 'pallet-template' -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" license = "Unlicense" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet template" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } [dependencies.frame-support] default-features = false -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" path = "../../../../frame/support" [dependencies.frame-system] default-features = false -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" path = "../../../../frame/system" + [dev-dependencies.sp-core] default-features = false -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" path = "../../../../primitives/core" [dev-dependencies.sp-io] default-features = false -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" path = "../../../../primitives/io" [dev-dependencies.sp-runtime] default-features = false -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" path = "../../../../primitives/runtime" @@ -43,6 +47,3 @@ std = [ 'frame-support/std', 'frame-system/std' ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/bin/node-template/pallets/template/src/lib.rs b/bin/node-template/pallets/template/src/lib.rs index a0daecfb72c9a14ffa7e7819400f0345c542b5b8..93624170aadaefa007bb72b0befea7a2ee6aba92 100644 --- a/bin/node-template/pallets/template/src/lib.rs +++ b/bin/node-template/pallets/template/src/lib.rs @@ -9,8 +9,8 @@ /// For more guidance on Substrate FRAME, see the example pallet /// https://github.com/paritytech/substrate/blob/master/frame/example/src/lib.rs -use frame_support::{decl_module, decl_storage, decl_event, decl_error, dispatch}; -use frame_system::{self as system, ensure_signed}; +use frame_support::{decl_module, decl_storage, decl_event, decl_error, dispatch, traits::Get}; +use frame_system::ensure_signed; #[cfg(test)] mod mock; @@ -19,11 +19,11 @@ mod mock; mod tests; /// The pallet's configuration trait. -pub trait Trait: system::Trait { +pub trait Trait: frame_system::Trait { // Add other types and constants required to configure this pallet. /// The overarching event type. - type Event: From> + Into<::Event>; + type Event: From> + Into<::Event>; } // This pallet's storage items. @@ -41,7 +41,7 @@ decl_storage! { // The pallet's events decl_event!( - pub enum Event where AccountId = ::AccountId { + pub enum Event where AccountId = ::AccountId { /// Just a dummy event. /// Event `Something` is declared with a parameter of the type `u32` and `AccountId` /// To emit this event, we call the deposit function, from our runtime functions @@ -75,7 +75,7 @@ decl_module! { /// Just a dummy entry point. /// function that can be called by the external world as an extrinsics call /// takes a parameter of the type `AccountId`, stores it, and emits an event - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 10_000 + T::DbWeight::get().writes(1)] pub fn do_something(origin, something: u32) -> dispatch::DispatchResult { // Check it was signed and get the signer. See also: ensure_root and ensure_none let who = ensure_signed(origin)?; @@ -91,7 +91,7 @@ decl_module! { /// Another dummy entry point. /// takes no parameters, attempts to increment storage value, and possibly throws an error - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 10_000 + T::DbWeight::get().reads_writes(1,1)] pub fn cause_error(origin) -> dispatch::DispatchResult { // Check it was signed and get the signer. See also: ensure_root and ensure_none let _who = ensure_signed(origin)?; diff --git a/bin/node-template/pallets/template/src/mock.rs b/bin/node-template/pallets/template/src/mock.rs index a93ac0359e3a2f2b8f4e0e558a0b254e33eb1c7e..130a782bb7ba21f20d36e3a5c476da27842f2446 100644 --- a/bin/node-template/pallets/template/src/mock.rs +++ b/bin/node-template/pallets/template/src/mock.rs @@ -24,6 +24,7 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); } impl system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Call = (); type Index = u64; @@ -36,6 +37,10 @@ impl system::Trait for Test { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -43,6 +48,7 @@ impl system::Trait for Test { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } impl Trait for Test { type Event = (); diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index e8653e6df70e82e503a54e79c638e9a796e41913..ea44c805d0b1beee0691836ed5826de75bee7885 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -1,40 +1,43 @@ [package] name = "node-template-runtime" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Anonymous"] edition = "2018" license = "Unlicense" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } -aura = { version = "2.0.0-alpha.5", default-features = false, package = "pallet-aura", path = "../../../frame/aura" } -balances = { version = "2.0.0-alpha.5", default-features = false, package = "pallet-balances", path = "../../../frame/balances" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/support" } -grandpa = { version = "2.0.0-alpha.5", default-features = false, package = "pallet-grandpa", path = "../../../frame/grandpa" } -randomness-collective-flip = { version = "2.0.0-alpha.5", default-features = false, package = "pallet-randomness-collective-flip", path = "../../../frame/randomness-collective-flip" } -sudo = { version = "2.0.0-alpha.5", default-features = false, package = "pallet-sudo", path = "../../../frame/sudo" } -system = { version = "2.0.0-alpha.5", default-features = false, package = "frame-system", path = "../../../frame/system" } -timestamp = { version = "2.0.0-alpha.5", default-features = false, package = "pallet-timestamp", path = "../../../frame/timestamp" } -transaction-payment = { version = "2.0.0-alpha.5", default-features = false, package = "pallet-transaction-payment", path = "../../../frame/transaction-payment" } -frame-executive = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/executive" } +aura = { version = "2.0.0-rc4", default-features = false, package = "pallet-aura", path = "../../../frame/aura" } +balances = { version = "2.0.0-rc4", default-features = false, package = "pallet-balances", path = "../../../frame/balances" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/support" } +grandpa = { version = "2.0.0-rc4", default-features = false, package = "pallet-grandpa", path = "../../../frame/grandpa" } +randomness-collective-flip = { version = "2.0.0-rc4", default-features = false, package = "pallet-randomness-collective-flip", path = "../../../frame/randomness-collective-flip" } +sudo = { version = "2.0.0-rc4", default-features = false, package = "pallet-sudo", path = "../../../frame/sudo" } +system = { version = "2.0.0-rc4", default-features = false, package = "frame-system", path = "../../../frame/system" } +timestamp = { version = "2.0.0-rc4", default-features = false, package = "pallet-timestamp", path = "../../../frame/timestamp" } +transaction-payment = { version = "2.0.0-rc4", default-features = false, package = "pallet-transaction-payment", path = "../../../frame/transaction-payment" } +frame-executive = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/executive" } serde = { version = "1.0.101", optional = true, features = ["derive"] } -sp-api = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/api" } -sp-block-builder = { path = "../../../primitives/block-builder", default-features = false, version = "2.0.0-alpha.5"} -sp-consensus-aura = { version = "0.8.0-alpha.5", default-features = false, path = "../../../primitives/consensus/aura" } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/core" } -sp-inherents = { path = "../../../primitives/inherents", default-features = false, version = "2.0.0-alpha.5"} -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/io" } -sp-offchain = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/offchain" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/runtime" } -sp-session = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/session" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/std" } -sp-transaction-pool = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/transaction-pool" } -sp-version = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/version" } +sp-api = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/api" } +sp-block-builder = { path = "../../../primitives/block-builder", default-features = false, version = "2.0.0-rc4"} +sp-consensus-aura = { version = "0.8.0-rc4", default-features = false, path = "../../../primitives/consensus/aura" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/core" } +sp-inherents = { path = "../../../primitives/inherents", default-features = false, version = "2.0.0-rc4"} +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/io" } +sp-offchain = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/offchain" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/runtime" } +sp-session = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/session" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/std" } +sp-transaction-pool = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/transaction-pool" } +sp-version = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/version" } -template = { version = "2.0.0-alpha.5", default-features = false, path = "../pallets/template", package = "pallet-template" } +template = { version = "2.0.0-rc4", default-features = false, path = "../pallets/template", package = "pallet-template" } [build-dependencies] wasm-builder-runner = { version = "1.0.5", package = "substrate-wasm-builder-runner", path = "../../../utils/wasm-builder-runner" } @@ -68,6 +71,3 @@ std = [ "transaction-payment/std", "template/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/bin/node-template/runtime/build.rs b/bin/node-template/runtime/build.rs index 39f7f56feb0b1730d7f2c9a7daa898fe54bfd052..1f40a41ff8ee62a560785bc426c80787028a048f 100644 --- a/bin/node-template/runtime/build.rs +++ b/bin/node-template/runtime/build.rs @@ -3,7 +3,7 @@ use wasm_builder_runner::WasmBuilder; fn main() { WasmBuilder::new() .with_current_project() - .with_wasm_builder_from_crates("1.0.9") + .with_wasm_builder_from_crates("1.0.11") .export_heap_base() .import_memory() .build() diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 94f033fd8f58ee231f412e7a2cf6f7f53f77d49a..85010ba3941898e4957154d3c3cc433ed34898ce 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -9,17 +9,17 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); use sp_std::prelude::*; -use sp_core::OpaqueMetadata; +use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::{ ApplyExtrinsicResult, generic, create_runtime_str, impl_opaque_keys, MultiSignature, transaction_validity::{TransactionValidity, TransactionSource}, }; use sp_runtime::traits::{ - BlakeTwo256, Block as BlockT, IdentityLookup, Verify, ConvertInto, IdentifyAccount + BlakeTwo256, Block as BlockT, IdentityLookup, Verify, IdentifyAccount, NumberFor, Saturating, }; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; -use grandpa::AuthorityList as GrandpaAuthorityList; +use grandpa::{AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; use grandpa::fg_primitives; use sp_version::RuntimeVersion; #[cfg(feature = "std")] @@ -32,9 +32,12 @@ pub use timestamp::Call as TimestampCall; pub use balances::Call as BalancesCall; pub use sp_runtime::{Permill, Perbill}; pub use frame_support::{ - StorageValue, construct_runtime, parameter_types, - traits::Randomness, - weights::Weight, + construct_runtime, parameter_types, StorageValue, + traits::{KeyOwnerProofSystem, Randomness}, + weights::{ + Weight, IdentityFee, + constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, + }, }; /// Importing a template pallet @@ -98,6 +101,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_version: 1, impl_version: 1, apis: RUNTIME_API_VERSIONS, + transaction_version: 1, }; pub const MILLISECS_PER_BLOCK: u64 = 6000; @@ -119,14 +123,20 @@ pub fn native_version() -> NativeVersion { } parameter_types! { - pub const BlockHashCount: BlockNumber = 250; - pub const MaximumBlockWeight: Weight = 1_000_000_000; + pub const BlockHashCount: BlockNumber = 2400; + /// We allow for 2 seconds of compute with a 6 second average block time. + pub const MaximumBlockWeight: Weight = 2 * WEIGHT_PER_SECOND; pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); + /// Assume 10% of weight for average on_initialize calls. + pub MaximumExtrinsicWeight: Weight = AvailableBlockRatio::get() + .saturating_sub(Perbill::from_percent(10)) * MaximumBlockWeight::get(); pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; pub const Version: RuntimeVersion = VERSION; } impl system::Trait for Runtime { + /// The basic call filter to use in dispatchable. + type BaseCallFilter = (); /// The identifier used to distinguish between accounts. type AccountId = AccountId; /// The aggregated dispatch type that is available for extrinsics. @@ -151,6 +161,18 @@ impl system::Trait for Runtime { type BlockHashCount = BlockHashCount; /// Maximum weight of each block. type MaximumBlockWeight = MaximumBlockWeight; + /// The weight of database operations that the runtime can invoke. + type DbWeight = RocksDbWeight; + /// The weight of the overhead invoked on the block import process, independent of the + /// extrinsics included in that block. + type BlockExecutionWeight = BlockExecutionWeight; + /// The base weight of any extrinsic processed by the runtime, independent of the + /// logic of that extrinsic. (Signature verification, nonce increment, fee, etc...) + type ExtrinsicBaseWeight = ExtrinsicBaseWeight; + /// The maximum weight that a single extrinsic of `Normal` dispatch class can have, + /// idependent of the logic of that extrinsics. (Roughly max block weight - average on + /// initialize cost). + type MaximumExtrinsicWeight = MaximumExtrinsicWeight; /// 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. @@ -167,6 +189,8 @@ impl system::Trait for Runtime { type OnKilledAccount = (); /// The data to be stored in an account. type AccountData = balances::AccountData; + /// Weight information for the extrinsics of this pallet. + type SystemWeightInfo = (); } impl aura::Trait for Runtime { @@ -175,6 +199,19 @@ impl aura::Trait for Runtime { impl grandpa::Trait for Runtime { type Event = Event; + type Call = Call; + + type KeyOwnerProofSystem = (); + + type KeyOwnerProof = + >::Proof; + + type KeyOwnerIdentification = >::IdentificationTuple; + + type HandleEquivocation = (); } parameter_types! { @@ -186,6 +223,7 @@ impl timestamp::Trait for Runtime { type Moment = u64; type OnTimestampSet = Aura; type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); } parameter_types! { @@ -200,19 +238,18 @@ impl balances::Trait for Runtime { type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; + type WeightInfo = (); } 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 WeightToFee = IdentityFee; type FeeMultiplierUpdate = (); } @@ -235,7 +272,7 @@ construct_runtime!( System: system::{Module, Call, Config, Storage, Event}, RandomnessCollectiveFlip: randomness_collective_flip::{Module, Call, Storage}, Timestamp: timestamp::{Module, Call, Storage, Inherent}, - Aura: aura::{Module, Config, Inherent(Timestamp)}, + Aura: aura::{Module, Config, Inherent}, Grandpa: grandpa::{Module, Call, Storage, Config, Event}, Balances: balances::{Module, Call, Storage, Config, Event}, TransactionPayment: transaction_payment::{Module, Storage}, @@ -257,7 +294,8 @@ pub type SignedBlock = generic::SignedBlock; pub type BlockId = generic::BlockId; /// The SignedExtension to the basic transaction logic. pub type SignedExtra = ( - system::CheckVersion, + system::CheckSpecVersion, + system::CheckTxVersion, system::CheckGenesis, system::CheckEra, system::CheckNonce, @@ -349,7 +387,7 @@ impl_runtime_apis! { fn decode_session_keys( encoded: Vec, - ) -> Option, sp_core::crypto::KeyTypeId)>> { + ) -> Option, KeyTypeId)>> { opaque::SessionKeys::decode_into_raw_public_keys(&encoded) } } @@ -358,5 +396,25 @@ impl_runtime_apis! { fn grandpa_authorities() -> GrandpaAuthorityList { Grandpa::grandpa_authorities() } + + fn submit_report_equivocation_extrinsic( + _equivocation_proof: fg_primitives::EquivocationProof< + ::Hash, + NumberFor, + >, + _key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof, + ) -> Option<()> { + None + } + + fn generate_key_ownership_proof( + _set_id: fg_primitives::SetId, + _authority_id: GrandpaId, + ) -> Option { + // NOTE: this is the only implementation possible since we've + // defined our key owner proof type as a bottom type (i.e. a type + // with no values). + None + } } } diff --git a/bin/node/bench/Cargo.toml b/bin/node/bench/Cargo.toml index 22e7fe51d848e1f44ca0c34eddb57d39ca0d0c32..0778909fa93e59910a986e9b2592687dbda46139 100644 --- a/bin/node/bench/Cargo.toml +++ b/bin/node/bench/Cargo.toml @@ -1,20 +1,42 @@ [package] name = "node-bench" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] description = "Substrate node integration benchmarks." edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] log = "0.4.8" -node-primitives = { version = "2.0.0-alpha.5", path = "../primitives" } -node-testing = { version = "2.0.0-alpha.5", path = "../testing" } -sc-cli = { version = "0.8.0-alpha.5", path = "../../../client/cli" } -sc-client-api = { version = "2.0.0-alpha.5", path = "../../../client/api/" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime" } +node-primitives = { version = "2.0.0-rc4", path = "../primitives" } +node-testing = { version = "2.0.0-rc4", path = "../testing" } +node-runtime = { version = "2.0.0-rc4", path = "../runtime" } +sc-cli = { version = "0.8.0-rc4", path = "../../../client/cli" } +sc-client-api = { version = "2.0.0-rc4", path = "../../../client/api/" } +sp-runtime = { version = "2.0.0-rc4", path = "../../../primitives/runtime" } +sp-state-machine = { version = "0.8.0-rc4", path = "../../../primitives/state-machine" } serde = "1.0.101" serde_json = "1.0.41" -structopt = "0.3" \ No newline at end of file +structopt = "0.3" +derive_more = "0.99.2" +kvdb = "0.7" +kvdb-rocksdb = "0.9" +sp-trie = { version = "2.0.0-rc4", path = "../../../primitives/trie" } +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } +sp-consensus = { version = "0.8.0-rc4", path = "../../../primitives/consensus/common" } +sp-transaction-pool = { version = "2.0.0-rc4", path = "../../../primitives/transaction-pool" } +sc-basic-authorship = { version = "0.8.0-rc4", path = "../../../client/basic-authorship" } +sp-inherents = { version = "2.0.0-rc4", path = "../../../primitives/inherents" } +sp-finality-tracker = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/finality-tracker" } +sp-timestamp = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/timestamp" } +hash-db = "0.15.2" +tempfile = "3.1.0" +fs_extra = "1" +hex = "0.4.0" +rand = { version = "0.7.2", features = ["small_rng"] } +lazy_static = "1.4.0" +parity-util-mem = { version = "0.7.0", default-features = false, features = ["primitive-types"] } +parity-db = { version = "0.1.2" } +futures = "0.3.1" diff --git a/bin/node/bench/src/common.rs b/bin/node/bench/src/common.rs new file mode 100644 index 0000000000000000000000000000000000000000..2637d6e9bd04d809af5b374790adcc6e5207993f --- /dev/null +++ b/bin/node/bench/src/common.rs @@ -0,0 +1,48 @@ + +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#[derive(Clone, Copy, Debug, derive_more::Display)] +pub enum SizeType { + #[display(fmt = "empty")] + Empty, + #[display(fmt = "small")] + Small, + #[display(fmt = "medium")] + Medium, + #[display(fmt = "large")] + Large, + #[display(fmt = "full")] + Full, + #[display(fmt = "custom")] + Custom(usize), +} + +impl SizeType { + pub fn transactions(&self) -> Option { + match self { + SizeType::Empty => Some(0), + SizeType::Small => Some(10), + SizeType::Medium => Some(100), + SizeType::Large => Some(500), + SizeType::Full => None, + // Custom SizeType will use the `--transactions` input parameter + SizeType::Custom(val) => Some(*val), + } + } +} \ No newline at end of file diff --git a/bin/node/bench/src/construct.rs b/bin/node/bench/src/construct.rs new file mode 100644 index 0000000000000000000000000000000000000000..e23594dd4364a1de30d65096fe69ab1627599a36 --- /dev/null +++ b/bin/node/bench/src/construct.rs @@ -0,0 +1,296 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Block construction benchmark. +//! +//! This benchmark is expected to measure block construction. +//! We want to protect against cold-cache attacks, and so this +//! benchmark should not rely on any caching (except those entries that +//! DO NOT depend on user input). Thus transaction generation should be +//! based on randomized data. + +use std::{ + borrow::Cow, + collections::HashMap, + pin::Pin, + sync::Arc, +}; +use futures::Future; + +use node_primitives::Block; +use node_testing::bench::{BenchDb, Profile, BlockType, KeyTypes, DatabaseType}; +use sp_runtime::{ + generic::BlockId, + traits::NumberFor, + OpaqueExtrinsic, +}; +use sp_transaction_pool::{ + ImportNotificationStream, + PoolFuture, + PoolStatus, + TransactionFor, + TransactionSource, + TransactionStatusStreamFor, + TxHash, +}; +use sp_consensus::{Environment, Proposer, RecordProof}; + +use crate::{ + common::SizeType, + core::{self, Path, Mode}, +}; + +pub struct ConstructionBenchmarkDescription { + pub profile: Profile, + pub key_types: KeyTypes, + pub block_type: BlockType, + pub size: SizeType, + pub database_type: DatabaseType, +} + +pub struct ConstructionBenchmark { + profile: Profile, + database: BenchDb, + transactions: Transactions, +} + +impl core::BenchmarkDescription for ConstructionBenchmarkDescription { + fn path(&self) -> Path { + + let mut path = Path::new(&["node", "proposer"]); + + match self.profile { + Profile::Wasm => path.push("wasm"), + Profile::Native => path.push("native"), + } + + match self.key_types { + KeyTypes::Sr25519 => path.push("sr25519"), + KeyTypes::Ed25519 => path.push("ed25519"), + } + + match self.block_type { + BlockType::RandomTransfersKeepAlive => path.push("transfer"), + BlockType::RandomTransfersReaping => path.push("transfer_reaping"), + BlockType::Noop => path.push("noop"), + } + + match self.database_type { + DatabaseType::RocksDb => path.push("rocksdb"), + DatabaseType::ParityDb => path.push("paritydb"), + } + + path.push(&format!("{}", self.size)); + + path + } + + fn setup(self: Box) -> Box { + let mut extrinsics: Vec> = Vec::new(); + + let mut bench_db = BenchDb::with_key_types( + self.database_type, + 50_000, + self.key_types + ); + + let client = bench_db.client(); + + let content_type = self.block_type.to_content(self.size.transactions()); + for transaction in bench_db.block_content(content_type, &client) { + extrinsics.push(Arc::new(transaction.into())); + } + + Box::new(ConstructionBenchmark { + profile: self.profile, + database: bench_db, + transactions: Transactions(extrinsics), + }) + } + + fn name(&self) -> Cow<'static, str> { + format!( + "Block construction ({:?}/{}, {:?}, {:?} backend)", + self.block_type, + self.size, + self.profile, + self.database_type, + ).into() + } +} + +impl core::Benchmark for ConstructionBenchmark { + fn run(&mut self, mode: Mode) -> std::time::Duration { + let context = self.database.create_context(self.profile); + + let _ = context.client.runtime_version_at(&BlockId::Number(0)) + .expect("Failed to get runtime version") + .spec_version; + + if mode == Mode::Profile { + std::thread::park_timeout(std::time::Duration::from_secs(3)); + } + + let mut proposer_factory = sc_basic_authorship::ProposerFactory::new( + context.client.clone(), + self.transactions.clone().into(), + None, + ); + let inherent_data_providers = sp_inherents::InherentDataProviders::new(); + inherent_data_providers + .register_provider(sp_timestamp::InherentDataProvider) + .expect("Failed to register timestamp data provider"); + + let start = std::time::Instant::now(); + + let proposer = futures::executor::block_on(proposer_factory.init( + &context.client.header(&BlockId::number(0)) + .expect("Database error querying block #0") + .expect("Block #0 should exist"), + )).expect("Proposer initialization failed"); + + let _block = futures::executor::block_on( + proposer.propose( + inherent_data_providers.create_inherent_data().expect("Create inherent data failed"), + Default::default(), + std::time::Duration::from_secs(20), + RecordProof::Yes, + ), + ).map(|r| r.block).expect("Proposing failed"); + + let elapsed = start.elapsed(); + + if mode == Mode::Profile { + std::thread::park_timeout(std::time::Duration::from_secs(1)); + } + + elapsed + } +} + +#[derive(Clone, Debug)] +pub struct PoolTransaction { + data: OpaqueExtrinsic, + hash: node_primitives::Hash, +} + +impl From for PoolTransaction { + fn from(e: OpaqueExtrinsic) -> Self { + PoolTransaction { + data: e, + hash: node_primitives::Hash::zero(), + } + } +} + +impl sp_transaction_pool::InPoolTransaction for PoolTransaction { + type Transaction = OpaqueExtrinsic; + type Hash = node_primitives::Hash; + + fn data(&self) -> &Self::Transaction { + &self.data + } + + fn hash(&self) -> &Self::Hash { + &self.hash + } + + fn priority(&self) -> &u64 { unimplemented!() } + + fn longevity(&self) -> &u64 { unimplemented!() } + + fn requires(&self) -> &[Vec] { unimplemented!() } + + fn provides(&self) -> &[Vec] { unimplemented!() } + + fn is_propagable(&self) -> bool { unimplemented!() } +} + +#[derive(Clone, Debug)] +pub struct Transactions(Vec>); + +impl sp_transaction_pool::TransactionPool for Transactions { + type Block = Block; + type Hash = node_primitives::Hash; + type InPoolTransaction = PoolTransaction; + type Error = sp_transaction_pool::error::Error; + + /// Returns a future that imports a bunch of unverified transactions to the pool. + fn submit_at( + &self, + _at: &BlockId, + _source: TransactionSource, + _xts: Vec>, + ) -> PoolFuture>, Self::Error> { + unimplemented!() + } + + /// Returns a future that imports one unverified transaction to the pool. + fn submit_one( + &self, + _at: &BlockId, + _source: TransactionSource, + _xt: TransactionFor, + ) -> PoolFuture, Self::Error> { + unimplemented!() + } + + fn submit_and_watch( + &self, + _at: &BlockId, + _source: TransactionSource, + _xt: TransactionFor, + ) -> PoolFuture>, Self::Error> { + unimplemented!() + } + + fn ready_at(&self, _at: NumberFor) + -> Pin> + Send>> + Send>> + { + let iter: Box> + Send> = Box::new(self.0.clone().into_iter()); + Box::pin(futures::future::ready(iter)) + } + + fn ready(&self) -> Box> + Send> { + unimplemented!() + } + + fn remove_invalid(&self, _hashes: &[TxHash]) -> Vec> { + Default::default() + } + + fn status(&self) -> PoolStatus { + unimplemented!() + } + + fn import_notification_stream(&self) -> ImportNotificationStream> { + unimplemented!() + } + + fn on_broadcasted(&self, _propagations: HashMap, Vec>) { + unimplemented!() + } + + fn hash_of(&self, _xt: &TransactionFor) -> TxHash { + unimplemented!() + } + + fn ready_transaction(&self, _hash: &TxHash) -> Option> { + unimplemented!() + } +} \ No newline at end of file diff --git a/bin/node/bench/src/core.rs b/bin/node/bench/src/core.rs index a8164db75a53833855ad996cd1aceaa24e232123..c1b1711549be17daf43024caae16ee356d0c889c 100644 --- a/bin/node/bench/src/core.rs +++ b/bin/node/bench/src/core.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use std::{fmt, borrow::{Cow, ToOwned}}; use serde::Serialize; @@ -48,7 +50,7 @@ pub trait BenchmarkDescription { } pub trait Benchmark { - fn run(&mut self) -> std::time::Duration; + fn run(&mut self, mode: Mode) -> std::time::Duration; } #[derive(Debug, Clone, Serialize)] @@ -58,7 +60,7 @@ pub struct BenchmarkOutput { average: u64, } -struct NsFormatter(u64); +pub struct NsFormatter(pub u64); impl fmt::Display for NsFormatter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -68,27 +70,44 @@ impl fmt::Display for NsFormatter { return write!(f, "{} ns", v) } - if self.0 < 10_000 { + if self.0 < 100_000 { return write!(f, "{:.1} µs", v as f64 / 1000.0) } if self.0 < 1_000_000 { - return write!(f, "{:.1} ms", v as f64 / 1_000_000.0) + return write!(f, "{:.4} ms", v as f64 / 1_000_000.0) } if self.0 < 100_000_000 { - return write!(f, "{} ms", v as f64 / 1_000_000.0) + return write!(f, "{:.1} ms", v as f64 / 1_000_000.0) } - write!(f, "{:.2} s", v as f64 / 1_000_000_000.0) + write!(f, "{:.4} s", v as f64 / 1_000_000_000.0) } } +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum Mode { + Regular, + Profile, +} + +impl std::str::FromStr for Mode { + type Err = &'static str; + fn from_str(day: &str) -> Result { + match day { + "regular" => Ok(Mode::Regular), + "profile" => Ok(Mode::Profile), + _ => Err("Could not parse mode"), + } + } +} + impl fmt::Display for BenchmarkOutput { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, - "({}: avg {}, w_avg {})", + "{}: avg {}, w_avg {}", self.name, NsFormatter(self.raw_average), NsFormatter(self.average), @@ -96,13 +115,16 @@ impl fmt::Display for BenchmarkOutput { } } -pub fn run_benchmark(benchmark: Box) -> BenchmarkOutput { +pub fn run_benchmark( + benchmark: Box, + mode: Mode, +) -> BenchmarkOutput { let name = benchmark.name().to_owned(); let mut benchmark = benchmark.setup(); let mut durations: Vec = vec![]; for _ in 0..50 { - let duration = benchmark.run(); + let duration = benchmark.run(mode); durations.push(duration.as_nanos()); } @@ -119,10 +141,10 @@ pub fn run_benchmark(benchmark: Box) -> BenchmarkOutpu } macro_rules! matrix( - ( $var:ident in $over:expr => $tt:expr, $( $rest:tt )* ) => { + ( $var:tt in $over:expr => $tt:expr, $( $rest:tt )* ) => { { let mut res = Vec::>::new(); - for $var in $over.iter() { + for $var in $over { res.push(Box::new($tt)); } res.extend(matrix!( $($rest)* )); diff --git a/bin/node/bench/src/generator.rs b/bin/node/bench/src/generator.rs new file mode 100644 index 0000000000000000000000000000000000000000..759a4299c72758f540e92349de6a25591c506d39 --- /dev/null +++ b/bin/node/bench/src/generator.rs @@ -0,0 +1,66 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use std::{collections::HashMap, sync::Arc}; + +use kvdb::KeyValueDB; +use node_primitives::Hash; +use sp_trie::{trie_types::TrieDBMut, TrieMut}; + +use crate::simple_trie::SimpleTrie; + +/// Generate trie from given `key_values`. +/// +/// Will fill your database `db` with trie data from `key_values` and +/// return root. +pub fn generate_trie( + db: Arc, + key_values: impl IntoIterator, Vec)>, +) -> Hash { + let mut root = Hash::default(); + + let (db, overlay) = { + let mut overlay = HashMap::new(); + overlay.insert( + hex::decode("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").expect("null key is valid"), + Some(vec![0]), + ); + let mut trie = SimpleTrie { db, overlay: &mut overlay }; + { + let mut trie_db = TrieDBMut::new(&mut trie, &mut root); + + for (key, value) in key_values { + trie_db.insert(&key, &value).expect("trie insertion failed"); + } + + trie_db.commit(); + } + ( trie.db, overlay ) + }; + + let mut transaction = db.transaction(); + for (key, value) in overlay.into_iter() { + match value { + Some(value) => transaction.put(0, &key[..], &value[..]), + None => transaction.delete(0, &key[..]), + } + } + db.write(transaction).expect("Failed to write transaction"); + + root +} diff --git a/bin/node/bench/src/import.rs b/bin/node/bench/src/import.rs index 20181bf4c7f7de816226ab76701d2c9339d56fa8..e49a359fb6af16fc26a7f252ca759442c35bbe1a 100644 --- a/bin/node/bench/src/import.rs +++ b/bin/node/bench/src/import.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Block import benchmark. //! @@ -30,36 +32,30 @@ use std::borrow::Cow; -use node_testing::bench::{BenchDb, Profile, BlockType, KeyTypes}; +use node_testing::bench::{BenchDb, Profile, BlockType, KeyTypes, DatabaseType}; use node_primitives::Block; use sc_client_api::backend::Backend; use sp_runtime::generic::BlockId; +use sp_state_machine::InspectState; -use crate::core::{self, Path}; - -#[derive(Clone, Copy, Debug)] -pub enum SizeType { Small, Medium, Large } - -impl SizeType { - fn transactions(&self) -> usize { - match self { - SizeType::Small => 10, - SizeType::Medium => 100, - SizeType::Large => 500, - } - } -} +use crate::{ + common::SizeType, + core::{self, Path, Mode}, +}; pub struct ImportBenchmarkDescription { pub profile: Profile, pub key_types: KeyTypes, + pub block_type: BlockType, pub size: SizeType, + pub database_type: DatabaseType, } pub struct ImportBenchmark { profile: Profile, database: BenchDb, block: Block, + block_type: BlockType, } impl core::BenchmarkDescription for ImportBenchmarkDescription { @@ -77,46 +73,104 @@ impl core::BenchmarkDescription for ImportBenchmarkDescription { KeyTypes::Ed25519 => path.push("ed25519"), } - match self.size { - SizeType::Small => path.push("small"), - SizeType::Medium => path.push("medium"), - SizeType::Large => path.push("large"), + match self.block_type { + BlockType::RandomTransfersKeepAlive => path.push("transfer_keep_alive"), + BlockType::RandomTransfersReaping => path.push("transfer_reaping"), + BlockType::Noop => path.push("noop"), + } + + match self.database_type { + DatabaseType::RocksDb => path.push("rocksdb"), + DatabaseType::ParityDb => path.push("paritydb"), } + path.push(&format!("{}", self.size)); + path } fn setup(self: Box) -> Box { let profile = self.profile; - let mut bench_db = BenchDb::with_key_types(self.size.transactions(), self.key_types); - let block = bench_db.generate_block(BlockType::RandomTransfers(self.size.transactions())); + let mut bench_db = BenchDb::with_key_types( + self.database_type, + 50_000, + self.key_types + ); + let block = bench_db.generate_block(self.block_type.to_content(self.size.transactions())); Box::new(ImportBenchmark { database: bench_db, + block_type: self.block_type, block, profile, }) } fn name(&self) -> Cow<'static, str> { - match self.profile { - Profile::Wasm => "Import benchmark (random transfers, wasm)".into(), - Profile::Native => "Import benchmark (random transfers, native)".into(), - } + format!( + "Block import ({:?}/{}, {:?}, {:?} backend)", + self.block_type, + self.size, + self.profile, + self.database_type, + ).into() } } impl core::Benchmark for ImportBenchmark { - fn run(&mut self) -> std::time::Duration { + fn run(&mut self, mode: Mode) -> std::time::Duration { let mut context = self.database.create_context(self.profile); let _ = context.client.runtime_version_at(&BlockId::Number(0)) .expect("Failed to get runtime version") .spec_version; + if mode == Mode::Profile { + std::thread::park_timeout(std::time::Duration::from_secs(3)); + } + let start = std::time::Instant::now(); context.import_block(self.block.clone()); let elapsed = start.elapsed(); + // Sanity checks. + context.client.state_at(&BlockId::number(1)).expect("state_at failed for block#1") + .inspect_with(|| { + match self.block_type { + BlockType::RandomTransfersKeepAlive => { + // should be 5 per signed extrinsic + 1 per unsigned + // we have 1 unsigned and the rest are signed in the block + // those 5 events per signed are: + // - new account (RawEvent::NewAccount) as we always transfer fund to non-existant account + // - endowed (RawEvent::Endowed) for this new account + // - successful transfer (RawEvent::Transfer) for this transfer operation + // - deposit event for charging transaction fee + // - extrinsic success + assert_eq!( + node_runtime::System::events().len(), + (self.block.extrinsics.len() - 1) * 5 + 1, + ); + }, + BlockType::Noop => { + assert_eq!( + node_runtime::System::events().len(), + + // should be 2 per signed extrinsic + 1 per unsigned + // we have 1 unsigned and the rest are signed in the block + // those 2 events per signed are: + // - deposit event for charging transaction fee + // - extrinsic success + (self.block.extrinsics.len() - 1) * 2 + 1, + ); + }, + _ => {}, + } + } + ); + + if mode == Mode::Profile { + std::thread::park_timeout(std::time::Duration::from_secs(1)); + } + log::info!( target: "bench-logistics", "imported block with {} tx, took: {:#?}", @@ -133,4 +187,4 @@ impl core::Benchmark for ImportBenchmark { elapsed } -} \ No newline at end of file +} diff --git a/bin/node/bench/src/main.rs b/bin/node/bench/src/main.rs index 8f045465262856fcb907f9aa5dfee68f7f05fc88..11820247112f8c99891c54b7ea4cb60fcf22c87f 100644 --- a/bin/node/bench/src/main.rs +++ b/bin/node/bench/src/main.rs @@ -1,27 +1,44 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . +mod common; +mod construct; #[macro_use] mod core; mod import; +mod generator; +mod simple_trie; +mod state_sizes; +mod tempdb; +mod trie; -use crate::core::run_benchmark; -use import::{ImportBenchmarkDescription, SizeType}; -use node_testing::bench::{Profile, KeyTypes}; use structopt::StructOpt; +use node_testing::bench::{Profile, KeyTypes, BlockType, DatabaseType as BenchDataBaseType}; + +use crate::{ + common::SizeType, + core::{run_benchmark, Mode as BenchmarkMode}, + tempdb::DatabaseType, + import::ImportBenchmarkDescription, + trie::{TrieReadBenchmarkDescription, TrieWriteBenchmarkDescription, DatabaseSize}, + construct::ConstructionBenchmarkDescription, +}; + #[derive(Debug, StructOpt)] #[structopt(name = "node-bench", about = "Node integration benchmarks")] struct Opt { @@ -41,6 +58,19 @@ struct Opt { /// /// Run with `--list` for the hint of what to filter. filter: Option, + + /// Number of transactions for block import with `custom` size. + #[structopt(long)] + transactions: Option, + + /// Mode + /// + /// "regular" for regular benchmark + /// + /// "profile" mode adds pauses between measurable runs, + /// so that actual interval can be selected in the profiler of choice. + #[structopt(short, long, default_value = "regular")] + mode: BenchmarkMode, } fn main() { @@ -50,29 +80,85 @@ fn main() { sc_cli::init_logger(""); } + let mut import_benchmarks = Vec::new(); + + for profile in [Profile::Wasm, Profile::Native].iter() { + for size in [ + SizeType::Empty, + SizeType::Small, + SizeType::Medium, + SizeType::Large, + SizeType::Full, + SizeType::Custom(opt.transactions.unwrap_or(0)), + ].iter() { + for block_type in [ + BlockType::RandomTransfersKeepAlive, + BlockType::RandomTransfersReaping, + BlockType::Noop, + ].iter() { + for database_type in [BenchDataBaseType::RocksDb, BenchDataBaseType::ParityDb].iter() { + import_benchmarks.push((profile, size.clone(), block_type.clone(), database_type)); + } + } + } + } + let benchmarks = matrix!( - profile in [Profile::Wasm, Profile::Native] => + (profile, size, block_type, database_type) in import_benchmarks.into_iter() => ImportBenchmarkDescription { profile: *profile, key_types: KeyTypes::Sr25519, - size: SizeType::Medium, + size: size, + block_type: block_type, + database_type: *database_type, }, - ImportBenchmarkDescription { - profile: Profile::Native, - key_types: KeyTypes::Ed25519, + (size, db_type) in + [ + DatabaseSize::Empty, DatabaseSize::Smallest, DatabaseSize::Small, + DatabaseSize::Medium, DatabaseSize::Large, DatabaseSize::Huge, + ] + .iter().flat_map(|size| + [ + DatabaseType::RocksDb, DatabaseType::ParityDb + ] + .iter().map(move |db_type| (size, db_type))) + => TrieReadBenchmarkDescription { database_size: *size, database_type: *db_type }, + (size, db_type) in + [ + DatabaseSize::Empty, DatabaseSize::Smallest, DatabaseSize::Small, + DatabaseSize::Medium, DatabaseSize::Large, DatabaseSize::Huge, + ] + .iter().flat_map(|size| + [ + DatabaseType::RocksDb, DatabaseType::ParityDb + ] + .iter().map(move |db_type| (size, db_type))) + => TrieWriteBenchmarkDescription { database_size: *size, database_type: *db_type }, + ConstructionBenchmarkDescription { + profile: Profile::Wasm, + key_types: KeyTypes::Sr25519, + block_type: BlockType::RandomTransfersKeepAlive, size: SizeType::Medium, + database_type: BenchDataBaseType::RocksDb, + }, + ConstructionBenchmarkDescription { + profile: Profile::Wasm, + key_types: KeyTypes::Sr25519, + block_type: BlockType::RandomTransfersKeepAlive, + size: SizeType::Large, + database_type: BenchDataBaseType::RocksDb, }, - size in [SizeType::Small, SizeType::Large] => - ImportBenchmarkDescription { - profile: Profile::Native, - key_types: KeyTypes::Sr25519, - size: *size, - }, ); if opt.list { + println!("Available benchmarks:"); + if let Some(filter) = opt.filter.as_ref() { + println!("\t(filtered by \"{}\")", filter); + } for benchmark in benchmarks.iter() { - log::info!("{}: {}", benchmark.name(), benchmark.path().full()) + if opt.filter.as_ref().map(|f| benchmark.path().has(f)).unwrap_or(true) { + println!("{}: {}", benchmark.name(), benchmark.path().full()) + } } return; } @@ -81,15 +167,20 @@ fn main() { for benchmark in benchmarks { if opt.filter.as_ref().map(|f| benchmark.path().has(f)).unwrap_or(true) { log::info!("Starting {}", benchmark.name()); - let result = run_benchmark(benchmark); + let result = run_benchmark(benchmark, opt.mode); log::info!("{}", result); results.push(result); } } + if results.is_empty() { + eprintln!("No benchmark was found for query"); + std::process::exit(1); + } + if opt.json { let json_result: String = serde_json::to_string(&results).expect("Failed to construct json"); println!("{}", json_result); } -} \ No newline at end of file +} diff --git a/bin/node/bench/src/simple_trie.rs b/bin/node/bench/src/simple_trie.rs new file mode 100644 index 0000000000000000000000000000000000000000..3cfd7ddb300a9101b22d55a2d460526a283fa0e2 --- /dev/null +++ b/bin/node/bench/src/simple_trie.rs @@ -0,0 +1,70 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use std::{collections::HashMap, sync::Arc}; + +use kvdb::KeyValueDB; +use node_primitives::Hash; +use sp_trie::DBValue; +use hash_db::{HashDB, AsHashDB, Prefix, Hasher as _}; + +pub type Hasher = sp_core::Blake2Hasher; + +/// Immutable generated trie database with root. +pub struct SimpleTrie<'a> { + pub db: Arc, + pub overlay: &'a mut HashMap, Option>>, +} + +impl<'a> AsHashDB for SimpleTrie<'a> { + fn as_hash_db(&self) -> &dyn hash_db::HashDB { &*self } + + fn as_hash_db_mut<'b>(&'b mut self) -> &'b mut (dyn HashDB + 'b) { + &mut *self + } +} + +impl<'a> HashDB for SimpleTrie<'a> { + fn get(&self, key: &Hash, prefix: Prefix) -> Option { + let key = sp_trie::prefixed_key::(key, prefix); + if let Some(value) = self.overlay.get(&key) { + return value.clone(); + } + self.db.get(0, &key).expect("Database backend error") + } + + fn contains(&self, hash: &Hash, prefix: Prefix) -> bool { + self.get(hash, prefix).is_some() + } + + fn insert(&mut self, prefix: Prefix, value: &[u8]) -> Hash { + let key = Hasher::hash(value); + self.emplace(key, prefix, value.to_vec()); + key + } + + fn emplace(&mut self, key: Hash, prefix: Prefix, value: DBValue) { + let key = sp_trie::prefixed_key::(&key, prefix); + self.overlay.insert(key, Some(value)); + } + + fn remove(&mut self, key: &Hash, prefix: Prefix) { + let key = sp_trie::prefixed_key::(key, prefix); + self.overlay.insert(key, None); + } +} diff --git a/bin/node/bench/src/state_sizes.rs b/bin/node/bench/src/state_sizes.rs new file mode 100644 index 0000000000000000000000000000000000000000..d35989f61be3467960c0870fca1bd5969d571081 --- /dev/null +++ b/bin/node/bench/src/state_sizes.rs @@ -0,0 +1,4756 @@ +// Copyright 2015-2020 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity 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. + +// Parity 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 Parity. If not, see . + +/// Kusama value size distribution +pub const KUSAMA_STATE_DISTRIBUTION: &'static[(u32, u32)] = &[ + (32, 35), + (33, 20035), + (34, 5369), + (35, 184), + (36, 54599), + (37, 1515056), + (38, 885), + (39, 69965), + (41, 210754), + (42, 467), + (43, 3241), + (44, 32660), + (45, 231141), + (46, 220016), + (47, 248931), + (48, 157232), + (49, 143236), + (50, 2428), + (51, 1476159), + (52, 31), + (53, 112), + (54, 711), + (55, 1934), + (56, 39), + (57, 407), + (58, 6929), + (59, 6568), + (60, 26), + (61, 268673), + (62, 118137), + (63, 84640), + (64, 193232), + (65, 2584210), + (66, 1002), + (67, 2993), + (68, 4266), + (69, 5633381), + (70, 277369), + (71, 5106), + (72, 722), + (73, 1882), + (74, 8178), + (75, 4045), + (76, 1596), + (77, 5335), + (78, 14591), + (79, 9645), + (80, 44171), + (81, 13474), + (82, 51090), + (83, 2595), + (84, 6276), + (85, 382195), + (86, 1062), + (87, 3846), + (88, 5663), + (89, 3811), + (90, 1580), + (91, 5729), + (92, 19144), + (93, 197), + (94, 235), + (95, 545), + (96, 54914), + (97, 3858), + (98, 1610), + (99, 635), + (100, 2481), + (101, 6457), + (102, 3753951), + (103, 11821), + (104, 11114), + (105, 2601), + (106, 2518), + (107, 521925), + (108, 297), + (109, 411), + (110, 668), + (111, 4500), + (112, 704), + (113, 316), + (114, 59), + (115, 291), + (116, 1727), + (117, 6010), + (118, 51874), + (119, 13969), + (120, 9496), + (121, 274), + (122, 810), + (123, 643), + (124, 69), + (125, 41), + (126, 329), + (127, 175435), + (128, 2641), + (129, 2658), + (130, 415277), + (131, 2705), + (132, 2314), + (133, 4290), + (134, 693), + (135, 1957478), + (136, 1111), + (137, 1474503), + (138, 3656), + (139, 940), + (140, 1755692), + (141, 61), + (142, 4140), + (143, 47), + (144, 6725), + (145, 610), + (146, 250), + (147, 48), + (148, 28), + (149, 132), + (150, 123489), + (151, 7476), + (152, 55), + (153, 68), + (154, 170), + (155, 566), + (156, 8110), + (157, 1243), + (158, 1445), + (159, 2569), + (160, 1096), + (161, 865), + (162, 634), + (163, 372411), + (164, 685), + (165, 3481), + (166, 1467), + (167, 2146), + (168, 556539), + (169, 566), + (170, 5080), + (171, 202), + (172, 123), + (173, 100750), + (174, 667), + (175, 433), + (176, 737), + (177, 315), + (178, 317), + (179, 656), + (180, 2522), + (181, 315), + (182, 406), + (183, 4680), + (184, 4941), + (185, 828), + (186, 782), + (187, 565), + (188, 584), + (189, 376), + (190, 321), + (191, 418), + (192, 167), + (193, 362), + (194, 2198), + (195, 180), + (196, 787), + (197, 2680), + (198, 501), + (199, 843), + (200, 287), + (201, 608362), + (202, 1157), + (203, 959), + (204, 1683623), + (205, 440), + (206, 756), + (207, 812), + (208, 1147), + (209, 723), + (210, 856), + (211, 496), + (212, 916), + (213, 615), + (214, 488), + (215, 522), + (216, 8265), + (217, 32574), + (218, 417), + (219, 247), + (220, 579), + (221, 68), + (222, 126), + (223, 306), + (224, 310), + (225, 24), + (226, 37), + (227, 160), + (228, 11), + (229, 3288), + (230, 349), + (231, 23), + (232, 14), + (233, 45), + (234, 452840), + (235, 118), + (236, 741), + (237, 390), + (238, 517), + (239, 694), + (240, 765), + (241, 542), + (242, 417), + (243, 617), + (244, 1307), + (245, 583), + (246, 1640), + (247, 735), + (248, 478), + (249, 4312), + (250, 5426), + (251, 1067), + (252, 435), + (253, 202), + (254, 122), + (255, 486), + (256, 180), + (257, 279), + (258, 406), + (259, 160), + (260, 2759), + (261, 2600), + (262, 686), + (263, 95), + (264, 164), + (265, 150), + (266, 1013), + (267, 552618), + (268, 217), + (269, 188), + (270, 284), + (271, 416), + (272, 453), + (273, 95), + (274, 42), + (275, 68), + (276, 90), + (277, 123), + (278, 340), + (279, 98), + (280, 2795), + (281, 261), + (282, 7370), + (283, 5768), + (284, 3285), + (285, 461), + (286, 363), + (287, 456), + (288, 1475), + (289, 211), + (290, 153), + (291, 282), + (292, 241), + (293, 2924), + (294, 261), + (295, 1070), + (296, 1301), + (297, 688), + (298, 592), + (299, 95), + (300, 686447), + (301, 42), + (302, 385), + (303, 24), + (304, 931), + (305, 49), + (306, 23), + (307, 67), + (308, 32), + (309, 38), + (310, 2), + (311, 7), + (312, 198), + (313, 11), + (314, 38), + (315, 3704), + (316, 7406), + (317, 116), + (318, 229), + (319, 100), + (320, 437), + (321, 244), + (322, 285), + (323, 433), + (324, 382), + (325, 3171), + (326, 761), + (327, 324), + (328, 2264), + (329, 340), + (330, 353), + (331, 110), + (332, 403), + (333, 731366), + (334, 223), + (335, 350), + (336, 600), + (337, 219), + (338, 112), + (339, 10), + (340, 761), + (341, 35), + (342, 99), + (343, 83), + (344, 136), + (345, 7), + (346, 836), + (347, 11), + (348, 10832), + (349, 8931), + (350, 33), + (351, 64), + (352, 66), + (353, 54), + (354, 78), + (355, 198), + (356, 722), + (357, 2647), + (358, 64), + (359, 71), + (360, 2242), + (361, 1462), + (362, 505), + (363, 444), + (364, 597), + (365, 372), + (366, 664852), + (367, 464), + (368, 605), + (369, 123), + (370, 64), + (371, 117), + (372, 328), + (373, 123), + (374, 227), + (375, 151), + (376, 881), + (377, 111), + (378, 30), + (379, 73), + (380, 2126), + (381, 3662), + (382, 9107), + (383, 18), + (384, 294), + (385, 12), + (386, 262), + (387, 127), + (388, 269), + (389, 2566), + (390, 14), + (391, 17), + (392, 80), + (393, 67), + (394, 1470), + (395, 25), + (396, 220), + (397, 131), + (398, 225), + (399, 484755), + (400, 597), + (401, 300), + (402, 253), + (403, 359), + (404, 523), + (405, 311), + (406, 238), + (407, 999), + (408, 424), + (409, 165), + (410, 96), + (411, 248), + (412, 1771), + (413, 139), + (414, 7374), + (415, 11186), + (416, 1355), + (417, 1283666), + (418, 9), + (419, 116), + (420, 3897), + (421, 2554), + (422, 1), + (423, 1), + (424, 16878), + (425, 3198212), + (426, 335), + (427, 1676), + (428, 80), + (429, 19), + (430, 47), + (431, 495), + (432, 421946), + (433, 73), + (434, 95), + (435, 105), + (436, 184), + (437, 56903), + (438, 132), + (439, 87), + (440, 207411), + (441, 230), + (442, 372), + (443, 361), + (444, 387), + (445, 299), + (446, 175), + (447, 7487), + (448, 16346), + (449, 37), + (450, 98313), + (451, 307), + (452, 304), + (453, 2675), + (454, 229), + (455, 130), + (456, 134), + (457, 50), + (458, 238), + (459, 2), + (460, 2267), + (461, 7), + (462, 1), + (463, 8), + (464, 395), + (465, 1279781), + (466, 9), + (467, 12), + (468, 633), + (469, 37), + (470, 13), + (471, 54), + (472, 247), + (473, 82), + (474, 119), + (475, 114), + (476, 332), + (477, 79), + (478, 116), + (479, 128), + (480, 4206), + (481, 20732), + (482, 311), + (483, 343), + (484, 527), + (485, 2750), + (486, 76), + (487, 152), + (488, 510), + (489, 63), + (490, 257), + (491, 79), + (492, 825), + (493, 4198), + (494, 389), + (495, 72), + (496, 1547), + (497, 34), + (498, 631996), + (499, 5), + (500, 2334), + (501, 34), + (502, 7), + (503, 7), + (504, 7682), + (505, 6), + (506, 26), + (507, 22), + (508, 461), + (509, 95), + (510, 36), + (511, 46), + (512, 2741), + (513, 38455), + (514, 29678), + (515, 179), + (516, 1637), + (517, 2597), + (518, 166), + (519, 230), + (520, 2736), + (521, 187), + (522, 361), + (523, 310), + (524, 3327), + (525, 76), + (526, 8070), + (527, 35), + (528, 3310), + (529, 118), + (530, 167), + (531, 214180), + (532, 4597), + (533, 153), + (534, 126), + (535, 23), + (536, 13920), + (537, 10), + (538, 11), + (539, 50), + (540, 50739), + (541, 8), + (542, 347), + (543, 77), + (544, 451575), + (545, 16), + (546, 218814), + (547, 1859026), + (548, 303), + (549, 2511), + (550, 27), + (551, 28), + (552, 188), + (553, 46), + (554, 216), + (555, 63), + (556, 202), + (557, 192), + (558, 257), + (559, 170377), + (560, 902), + (561, 424), + (562, 186), + (563, 145), + (564, 342), + (565, 76), + (566, 41), + (567, 26), + (568, 136), + (569, 1336), + (570, 988), + (571, 131), + (572, 766), + (573, 95), + (574, 57), + (575, 16), + (576, 47), + (577, 63), + (578, 5), + (579, 140), + (580, 1263808), + (581, 2498), + (583, 2), + (584, 706), + (585, 49), + (586, 502), + (587, 16), + (588, 115), + (589, 25), + (590, 31), + (591, 34), + (592, 818), + (593, 60), + (594, 84), + (595, 116), + (596, 446), + (597, 111), + (598, 151), + (599, 153), + (600, 1408), + (601, 165), + (602, 575), + (603, 163), + (604, 309), + (605, 52), + (606, 40), + (607, 116), + (608, 749), + (609, 231), + (610, 171), + (611, 218), + (612, 1145), + (613, 2572), + (614, 27), + (615, 26), + (616, 2060), + (617, 173), + (618, 1094), + (619, 66), + (620, 14235), + (622, 294), + (623, 2), + (624, 79374), + (625, 1), + (626, 3), + (627, 7), + (628, 335), + (629, 27), + (630, 47), + (631, 113), + (632, 589), + (633, 56), + (634, 75), + (635, 85), + (636, 740), + (637, 118), + (638, 180), + (639, 149), + (640, 1169), + (641, 135), + (642, 169), + (643, 170), + (644, 1802), + (645, 2481), + (646, 28), + (647, 78), + (648, 5585), + (649, 173), + (650, 135), + (651, 177), + (652, 6553), + (653, 129), + (654, 55), + (655, 6), + (656, 13250), + (657, 5), + (658, 15), + (659, 3), + (660, 39892), + (661, 28), + (663, 1), + (664, 575061), + (665, 1), + (666, 5), + (667, 73), + (668, 39), + (669, 62), + (670, 50), + (671, 27), + (672, 33), + (673, 48), + (674, 44), + (675, 151), + (676, 70), + (677, 2540), + (678, 150), + (679, 109), + (680, 117), + (681, 95), + (682, 80), + (683, 44), + (684, 34), + (685, 31), + (686, 125), + (687, 146), + (688, 423), + (689, 142), + (690, 154), + (691, 135), + (692, 194), + (693, 48), + (694, 6), + (695, 141), + (696, 47), + (697, 9), + (699, 1), + (701, 1), + (702, 2), + (703, 81), + (704, 3), + (705, 4), + (706, 23), + (707, 131), + (708, 31), + (709, 2458), + (710, 346), + (711, 43), + (712, 46), + (713, 48), + (714, 85), + (715, 119), + (716, 89), + (717, 97), + (718, 95), + (719, 137), + (720, 437), + (721, 64), + (722, 28), + (723, 29), + (724, 121), + (725, 162), + (726, 241), + (727, 219), + (728, 143), + (729, 92), + (730, 100), + (731, 42), + (732, 38), + (733, 60), + (734, 2), + (735, 71), + (736, 12), + (737, 9), + (738, 7), + (739, 193), + (740, 2), + (741, 2404), + (742, 3), + (743, 11), + (744, 5), + (745, 5), + (746, 9), + (747, 16), + (748, 27), + (749, 32), + (750, 57), + (751, 54), + (752, 383), + (753, 61), + (754, 48), + (755, 84), + (756, 108), + (757, 134), + (758, 121), + (759, 160), + (760, 80), + (761, 68), + (762, 192), + (763, 107), + (764, 270), + (765, 58), + (766, 125), + (767, 151), + (768, 75), + (769, 94), + (770, 91), + (771, 187), + (772, 57), + (773, 2371), + (774, 8), + (775, 93), + (776, 107), + (777, 20), + (779, 1), + (780, 22), + (781, 1), + (783, 6), + (784, 318), + (785, 25), + (786, 31), + (787, 23), + (788, 28), + (789, 62), + (790, 53), + (791, 41), + (792, 68), + (793, 60), + (794, 88), + (795, 108), + (796, 63), + (797, 100), + (798, 68), + (799, 72), + (800, 83), + (801, 46), + (802, 36), + (803, 157), + (804, 139), + (805, 2439), + (806, 73), + (807, 81), + (808, 99), + (809, 66), + (810, 45), + (811, 98), + (812, 1), + (814, 31), + (815, 1), + (816, 312), + (818, 155), + (819, 2), + (820, 12), + (821, 27), + (822, 97), + (823, 23), + (824, 7), + (825, 15), + (826, 37), + (827, 39), + (828, 28), + (829, 33), + (830, 53), + (831, 101), + (832, 189), + (833, 94), + (834, 66), + (835, 173), + (836, 74), + (837, 2402), + (838, 64), + (839, 28), + (840, 20), + (841, 13), + (842, 32), + (843, 72), + (844, 68), + (845, 50), + (846, 41), + (847, 114), + (848, 345), + (849, 33), + (850, 17), + (851, 6), + (852, 61), + (853, 101), + (854, 123), + (855, 28), + (856, 3), + (857, 3), + (858, 30), + (859, 12), + (860, 28), + (861, 16), + (862, 20), + (863, 7), + (864, 23), + (865, 28), + (866, 40), + (867, 159), + (868, 40), + (869, 2361), + (870, 92), + (871, 88), + (872, 193), + (873, 61), + (874, 58), + (875, 67), + (876, 65), + (877, 46), + (878, 55), + (879, 30), + (880, 334), + (881, 74), + (882, 121), + (883, 107), + (884, 36), + (885, 66), + (886, 22), + (887, 25), + (888, 24), + (889, 10), + (890, 44), + (891, 5), + (892, 84), + (893, 4), + (894, 1), + (895, 7), + (896, 3), + (897, 8), + (898, 3), + (899, 126), + (900, 13), + (901, 2280), + (902, 74), + (903, 36), + (904, 46), + (905, 52), + (906, 24), + (907, 23), + (908, 43), + (909, 31), + (910, 66), + (911, 65), + (912, 376), + (913, 77), + (914, 85), + (915, 60), + (916, 29), + (917, 64), + (918, 48), + (919, 135), + (920, 21), + (921, 34), + (922, 26), + (923, 22), + (924, 52), + (925, 28), + (926, 142), + (927, 18), + (928, 14), + (929, 30), + (930, 56), + (931, 113), + (933, 2264), + (934, 14), + (935, 4), + (936, 10), + (937, 18), + (938, 2), + (939, 30), + (940, 9), + (941, 29), + (942, 10), + (943, 17), + (944, 296), + (945, 31), + (946, 40), + (947, 26), + (948, 70), + (949, 66), + (950, 44), + (951, 57), + (952, 55), + (953, 56), + (954, 51), + (955, 133), + (956, 39), + (957, 49), + (958, 45), + (959, 26), + (960, 30), + (961, 35), + (962, 40), + (963, 148), + (964, 34), + (965, 2264), + (966, 50), + (967, 21), + (968, 2), + (970, 24), + (972, 45), + (973, 8), + (974, 11), + (975, 20), + (976, 287), + (977, 20), + (978, 6), + (979, 9), + (980, 99), + (981, 32), + (982, 10), + (983, 13), + (984, 26), + (985, 30), + (986, 31), + (987, 38), + (988, 25), + (989, 32), + (990, 44), + (991, 125), + (992, 58), + (993, 44), + (994, 25), + (995, 140), + (996, 25), + (997, 2222), + (998, 16), + (999, 25), + (1000, 38), + (1001, 66), + (1002, 31), + (1003, 38), + (1004, 38), + (1005, 10), + (1006, 7), + (1008, 283), + (1009, 3), + (1010, 1), + (1011, 17), + (1012, 4), + (1013, 51), + (1014, 1), + (1015, 1), + (1016, 3), + (1017, 12), + (1018, 11), + (1019, 21), + (1020, 31), + (1021, 14), + (1022, 14), + (1023, 23), + (1024, 25), + (1025, 42), + (1026, 39), + (1027, 220), + (1028, 33), + (1029, 2206), + (1030, 24), + (1031, 64), + (1032, 36), + (1033, 61), + (1034, 123), + (1035, 32), + (1036, 20), + (1037, 15), + (1038, 11), + (1039, 33), + (1040, 311), + (1041, 58), + (1042, 80), + (1043, 29), + (1044, 10), + (1045, 48), + (1046, 18), + (1047, 22), + (1048, 3), + (1049, 17), + (1050, 1), + (1051, 2), + (1052, 5), + (1053, 4), + (1054, 4), + (1055, 1), + (1056, 4), + (1057, 15), + (1058, 11), + (1059, 135), + (1060, 59), + (1061, 2132), + (1062, 32), + (1063, 116), + (1064, 37), + (1065, 44), + (1066, 42), + (1067, 28), + (1068, 10), + (1069, 36), + (1070, 59), + (1071, 48), + (1072, 332), + (1073, 59), + (1074, 43), + (1075, 19), + (1076, 19), + (1077, 31), + (1078, 31), + (1079, 20), + (1080, 38), + (1081, 58), + (1082, 37), + (1083, 47), + (1084, 19), + (1085, 24), + (1086, 12), + (1087, 26), + (1088, 89), + (1089, 3), + (1091, 108), + (1093, 2112), + (1094, 13), + (1095, 4), + (1096, 4), + (1097, 17), + (1098, 7), + (1099, 105), + (1100, 12), + (1101, 10), + (1102, 17), + (1103, 19), + (1104, 329), + (1105, 28), + (1106, 58), + (1107, 21), + (1108, 22), + (1109, 63), + (1110, 29), + (1111, 53), + (1112, 84), + (1113, 28), + (1114, 30), + (1115, 22), + (1116, 40), + (1117, 16), + (1118, 20), + (1119, 75), + (1120, 43), + (1121, 49), + (1122, 25), + (1123, 118), + (1124, 8), + (1125, 2083), + (1126, 21), + (1127, 3), + (1128, 43), + (1129, 1), + (1130, 1), + (1132, 3), + (1133, 1), + (1134, 3), + (1135, 83), + (1136, 266), + (1137, 7), + (1138, 22), + (1139, 14), + (1140, 30), + (1141, 54), + (1142, 125), + (1143, 44), + (1144, 34), + (1145, 19), + (1146, 21), + (1147, 19), + (1148, 46), + (1149, 45), + (1150, 54), + (1151, 22), + (1152, 30), + (1153, 20), + (1154, 7), + (1155, 143), + (1156, 23), + (1157, 2078), + (1158, 30), + (1159, 23), + (1160, 12), + (1161, 18), + (1162, 6), + (1164, 5), + (1165, 1), + (1168, 254), + (1169, 1), + (1170, 3), + (1171, 95), + (1172, 37), + (1173, 23), + (1174, 7), + (1175, 11), + (1176, 5), + (1177, 14), + (1178, 15), + (1179, 19), + (1180, 10), + (1181, 28), + (1182, 87), + (1183, 35), + (1184, 30), + (1185, 30), + (1186, 38), + (1187, 148), + (1188, 49), + (1189, 2056), + (1190, 42), + (1191, 41), + (1192, 14), + (1193, 36), + (1194, 37), + (1195, 22), + (1196, 108), + (1197, 62), + (1198, 55), + (1199, 43), + (1200, 261), + (1201, 16), + (1202, 1), + (1203, 9), + (1204, 3), + (1205, 32), + (1207, 81), + (1208, 3), + (1210, 3), + (1212, 4), + (1213, 9), + (1214, 5), + (1215, 6), + (1216, 4), + (1217, 8), + (1218, 13), + (1219, 120), + (1220, 11), + (1221, 1989), + (1222, 11), + (1223, 20), + (1224, 15), + (1225, 21), + (1226, 23), + (1227, 50), + (1228, 37), + (1229, 51), + (1230, 37), + (1231, 21), + (1232, 256), + (1233, 26), + (1234, 25), + (1235, 21), + (1236, 79), + (1237, 50), + (1238, 21), + (1239, 2), + (1240, 6), + (1241, 8), + (1243, 95), + (1244, 1), + (1247, 1), + (1248, 1), + (1249, 1), + (1250, 96), + (1251, 112), + (1252, 43), + (1253, 1960), + (1254, 7), + (1255, 13), + (1256, 16), + (1257, 20), + (1258, 19), + (1259, 17), + (1260, 12), + (1261, 5), + (1262, 12), + (1263, 29), + (1264, 272), + (1265, 63), + (1266, 37), + (1267, 36), + (1268, 25), + (1269, 55), + (1270, 38), + (1271, 7), + (1272, 37), + (1273, 10), + (1274, 16), + (1275, 28), + (1276, 18), + (1277, 11), + (1278, 8), + (1279, 91), + (1280, 1), + (1282, 1), + (1283, 110), + (1284, 20), + (1285, 1923), + (1287, 3), + (1288, 1), + (1290, 23), + (1291, 4), + (1292, 4), + (1293, 12), + (1294, 19), + (1295, 8), + (1296, 248), + (1297, 21), + (1298, 12), + (1299, 31), + (1300, 10), + (1301, 60), + (1302, 1), + (1303, 8), + (1304, 99), + (1305, 29), + (1306, 29), + (1307, 28), + (1308, 33), + (1309, 19), + (1310, 8), + (1311, 1), + (1313, 11), + (1314, 12), + (1315, 236), + (1316, 18), + (1317, 1891), + (1318, 2), + (1322, 21), + (1324, 1), + (1326, 8), + (1327, 3), + (1328, 235), + (1329, 4), + (1330, 1), + (1331, 2), + (1332, 5), + (1333, 38), + (1334, 2), + (1335, 30), + (1336, 18), + (1337, 31), + (1338, 8), + (1339, 5), + (1340, 11), + (1341, 9), + (1342, 12), + (1343, 11), + (1344, 79), + (1345, 37), + (1346, 19), + (1347, 136), + (1348, 9), + (1349, 1861), + (1350, 8), + (1351, 112), + (1352, 10), + (1353, 3), + (1354, 16), + (1355, 4), + (1356, 12), + (1357, 18), + (1358, 67), + (1359, 6), + (1360, 229), + (1361, 1), + (1362, 1), + (1364, 1), + (1365, 27), + (1366, 6), + (1368, 14), + (1370, 8), + (1371, 29), + (1372, 3), + (1373, 21), + (1374, 8), + (1375, 6), + (1376, 3), + (1377, 9), + (1378, 9), + (1379, 120), + (1380, 5), + (1381, 1833), + (1382, 45), + (1383, 35), + (1384, 23), + (1385, 25), + (1386, 26), + (1387, 159), + (1388, 24), + (1389, 16), + (1390, 16), + (1391, 14), + (1392, 273), + (1393, 17), + (1394, 9), + (1395, 5), + (1396, 14), + (1397, 24), + (1398, 27), + (1400, 2), + (1404, 5), + (1405, 8), + (1406, 3), + (1407, 25), + (1408, 2), + (1409, 22), + (1410, 10), + (1411, 111), + (1412, 89), + (1413, 1793), + (1414, 4), + (1415, 9), + (1416, 16), + (1417, 13), + (1418, 13), + (1419, 13), + (1420, 15), + (1421, 19), + (1422, 26), + (1423, 110), + (1424, 229), + (1425, 11), + (1426, 10), + (1427, 7), + (1428, 7), + (1429, 28), + (1430, 12), + (1431, 11), + (1432, 14), + (1433, 2), + (1434, 2), + (1436, 1), + (1437, 1), + (1438, 13), + (1439, 1), + (1440, 1), + (1441, 1), + (1442, 2), + (1443, 132), + (1444, 5), + (1445, 1795), + (1448, 11), + (1449, 10), + (1450, 11), + (1451, 8), + (1452, 47), + (1453, 6), + (1454, 8), + (1455, 12), + (1456, 229), + (1457, 15), + (1458, 12), + (1459, 121), + (1460, 15), + (1461, 48), + (1462, 49), + (1463, 22), + (1464, 11), + (1465, 9), + (1466, 81), + (1467, 1), + (1468, 1), + (1469, 6), + (1470, 6), + (1471, 6), + (1472, 9), + (1473, 12), + (1474, 2), + (1475, 109), + (1476, 5), + (1477, 1721), + (1478, 1), + (1479, 28), + (1480, 7), + (1481, 23), + (1482, 2), + (1483, 12), + (1484, 5), + (1485, 3), + (1486, 2), + (1487, 4), + (1488, 219), + (1489, 7), + (1490, 8), + (1491, 10), + (1492, 16), + (1493, 32), + (1494, 25), + (1495, 96), + (1496, 13), + (1497, 15), + (1498, 16), + (1499, 12), + (1500, 14), + (1501, 19), + (1502, 7), + (1503, 11), + (1504, 3), + (1505, 8), + (1506, 41), + (1507, 108), + (1508, 25), + (1509, 1719), + (1510, 8), + (1511, 10), + (1514, 2), + (1515, 25), + (1516, 2), + (1517, 32), + (1518, 6), + (1519, 7), + (1520, 273), + (1521, 2), + (1522, 6), + (1523, 5), + (1524, 6), + (1525, 36), + (1526, 3), + (1527, 12), + (1528, 7), + (1529, 9), + (1530, 12), + (1531, 107), + (1532, 44), + (1533, 17), + (1534, 12), + (1535, 18), + (1536, 12), + (1537, 26), + (1538, 35), + (1539, 131), + (1540, 15), + (1541, 1693), + (1542, 11), + (1543, 7), + (1544, 2), + (1545, 6), + (1546, 14), + (1547, 6), + (1548, 2), + (1549, 24), + (1550, 2), + (1551, 33), + (1552, 206), + (1553, 18), + (1555, 1), + (1556, 7), + (1557, 38), + (1558, 6), + (1559, 3), + (1560, 21), + (1562, 2), + (1563, 5), + (1564, 7), + (1565, 5), + (1566, 6), + (1567, 110), + (1568, 9), + (1569, 16), + (1570, 13), + (1571, 109), + (1572, 6), + (1573, 1664), + (1574, 53), + (1575, 14), + (1576, 21), + (1577, 31), + (1578, 42), + (1579, 13), + (1580, 10), + (1581, 12), + (1582, 11), + (1583, 85), + (1584, 202), + (1585, 7), + (1586, 6), + (1587, 25), + (1588, 5), + (1589, 41), + (1590, 4), + (1591, 5), + (1593, 1), + (1595, 5), + (1596, 11), + (1598, 1), + (1599, 1), + (1600, 1), + (1601, 4), + (1602, 19), + (1603, 200), + (1604, 10), + (1605, 1640), + (1606, 15), + (1607, 14), + (1608, 7), + (1609, 12), + (1610, 5), + (1611, 2), + (1612, 3), + (1613, 7), + (1614, 37), + (1615, 4), + (1616, 203), + (1617, 13), + (1618, 3), + (1619, 12), + (1620, 38), + (1621, 22), + (1622, 12), + (1623, 43), + (1624, 19), + (1625, 35), + (1626, 15), + (1627, 26), + (1628, 43), + (1629, 2), + (1630, 10), + (1631, 1), + (1633, 1), + (1634, 1), + (1635, 110), + (1637, 1612), + (1638, 1), + (1639, 107), + (1640, 1), + (1641, 2), + (1643, 7), + (1644, 9), + (1645, 8), + (1646, 3), + (1647, 19), + (1648, 206), + (1649, 2), + (1650, 9), + (1651, 8), + (1652, 19), + (1653, 22), + (1654, 4), + (1655, 13), + (1656, 3), + (1657, 5), + (1658, 5), + (1659, 35), + (1660, 10), + (1661, 26), + (1662, 8), + (1663, 10), + (1664, 7), + (1665, 4), + (1666, 2), + (1667, 110), + (1668, 12), + (1669, 1594), + (1670, 1), + (1671, 2), + (1672, 15), + (1673, 4), + (1674, 2), + (1675, 303), + (1676, 12), + (1678, 1), + (1680, 194), + (1681, 1), + (1682, 40), + (1683, 2), + (1684, 2), + (1685, 19), + (1686, 16), + (1687, 2), + (1688, 6), + (1689, 9), + (1690, 18), + (1691, 15), + (1692, 5), + (1693, 7), + (1694, 6), + (1695, 32), + (1696, 4), + (1697, 34), + (1698, 1), + (1699, 117), + (1700, 5), + (1701, 1590), + (1702, 20), + (1703, 4), + (1704, 6), + (1705, 20), + (1707, 2), + (1710, 3), + (1711, 89), + (1712, 195), + (1713, 4), + (1714, 2), + (1715, 1), + (1716, 3), + (1717, 16), + (1718, 9), + (1719, 2), + (1720, 3), + (1723, 18), + (1724, 1), + (1725, 2), + (1726, 3), + (1727, 3), + (1728, 9), + (1729, 5), + (1730, 7), + (1731, 132), + (1732, 28), + (1733, 1585), + (1734, 5), + (1735, 3), + (1736, 5), + (1737, 27), + (1738, 4), + (1739, 19), + (1740, 15), + (1741, 4), + (1742, 15), + (1743, 9), + (1744, 183), + (1745, 12), + (1747, 119), + (1748, 1), + (1749, 15), + (1750, 5), + (1754, 1), + (1757, 2), + (1758, 8), + (1759, 7), + (1760, 7), + (1761, 2), + (1762, 13), + (1763, 113), + (1764, 8), + (1765, 1547), + (1766, 7), + (1767, 21), + (1768, 3), + (1769, 34), + (1770, 5), + (1772, 6), + (1773, 7), + (1774, 12), + (1775, 9), + (1776, 189), + (1777, 25), + (1778, 10), + (1779, 4), + (1780, 1), + (1781, 21), + (1782, 3), + (1783, 186), + (1784, 2), + (1787, 1), + (1788, 10), + (1789, 8), + (1790, 1), + (1791, 34), + (1792, 1), + (1793, 1), + (1794, 1), + (1795, 108), + (1796, 4), + (1797, 1519), + (1798, 9), + (1799, 9), + (1800, 3), + (1801, 6), + (1802, 4), + (1803, 35), + (1804, 15), + (1805, 30), + (1806, 5), + (1807, 7), + (1808, 192), + (1809, 8), + (1811, 4), + (1812, 24), + (1813, 36), + (1814, 4), + (1815, 14), + (1816, 2), + (1817, 2), + (1818, 4), + (1819, 72), + (1820, 3), + (1822, 1), + (1823, 4), + (1825, 1), + (1826, 5), + (1827, 104), + (1828, 1), + (1829, 1494), + (1830, 11), + (1831, 5), + (1832, 2), + (1833, 2), + (1834, 2), + (1835, 4), + (1836, 9), + (1837, 1), + (1838, 14), + (1839, 33), + (1840, 188), + (1841, 27), + (1842, 13), + (1843, 10), + (1844, 28), + (1845, 52), + (1846, 17), + (1847, 40), + (1848, 35), + (1849, 6), + (1850, 6), + (1851, 2), + (1853, 4), + (1854, 6), + (1855, 77), + (1856, 1), + (1859, 106), + (1860, 2), + (1861, 1466), + (1863, 2), + (1866, 1), + (1869, 1), + (1870, 2), + (1872, 179), + (1873, 1), + (1874, 9), + (1875, 29), + (1876, 15), + (1877, 43), + (1878, 2), + (1880, 8), + (1881, 13), + (1882, 18), + (1883, 12), + (1884, 14), + (1885, 18), + (1886, 16), + (1887, 6), + (1888, 2), + (1889, 3), + (1890, 9), + (1891, 196), + (1892, 13), + (1893, 1456), + (1894, 14), + (1895, 8), + (1896, 2), + (1898, 1), + (1899, 17), + (1900, 5), + (1901, 1), + (1904, 175), + (1905, 1), + (1906, 2), + (1907, 3), + (1908, 6), + (1909, 10), + (1910, 3), + (1911, 22), + (1912, 6), + (1913, 22), + (1914, 6), + (1915, 10), + (1916, 5), + (1917, 2), + (1918, 6), + (1919, 4), + (1920, 7), + (1921, 14), + (1922, 4), + (1923, 107), + (1924, 10), + (1925, 1434), + (1926, 7), + (1927, 76), + (1928, 4), + (1929, 7), + (1930, 10), + (1931, 14), + (1932, 6), + (1933, 15), + (1934, 4), + (1935, 2), + (1936, 182), + (1937, 2), + (1939, 11), + (1940, 1), + (1941, 4), + (1942, 2), + (1943, 9), + (1944, 1), + (1947, 24), + (1949, 22), + (1952, 15), + (1953, 14), + (1954, 5), + (1955, 111), + (1956, 11), + (1957, 1435), + (1958, 5), + (1959, 5), + (1960, 10), + (1961, 6), + (1962, 11), + (1963, 95), + (1964, 11), + (1965, 7), + (1966, 7), + (1967, 2), + (1968, 182), + (1969, 6), + (1970, 15), + (1972, 7), + (1973, 11), + (1974, 6), + (1975, 2), + (1976, 6), + (1977, 3), + (1978, 2), + (1983, 24), + (1985, 26), + (1986, 3), + (1987, 109), + (1988, 3), + (1989, 1421), + (1990, 1), + (1991, 3), + (1992, 8), + (1993, 4), + (1994, 6), + (1995, 5), + (1996, 13), + (1997, 6), + (1998, 10), + (1999, 92), + (2000, 181), + (2001, 5), + (2002, 5), + (2003, 1), + (2004, 1), + (2005, 14), + (2006, 12), + (2007, 10), + (2008, 7), + (2009, 9), + (2010, 6), + (2011, 8), + (2012, 13), + (2013, 2), + (2014, 2), + (2018, 1), + (2019, 128), + (2021, 1429), + (2022, 4), + (2026, 2), + (2027, 2), + (2030, 7), + (2032, 175), + (2033, 1), + (2035, 90), + (2036, 3), + (2037, 11), + (2038, 2), + (2039, 4), + (2040, 3), + (2041, 2), + (2042, 1), + (2043, 2), + (2044, 5), + (2045, 1), + (2046, 3), + (2047, 21), + (2048, 5), + (2050, 16), + (2051, 120), + (2053, 1403), + (2054, 4), + (2055, 29), + (2057, 26), + (2058, 3), + (2059, 4), + (2060, 4), + (2061, 7), + (2063, 1), + (2065, 170), + (2066, 3), + (2067, 2), + (2068, 7), + (2069, 13), + (2071, 77), + (2072, 1), + (2075, 4), + (2077, 1), + (2078, 2), + (2079, 5), + (2080, 4), + (2081, 3), + (2082, 3), + (2083, 2), + (2084, 293), + (2085, 6), + (2086, 1395), + (2087, 2), + (2089, 4), + (2090, 10), + (2091, 26), + (2092, 14), + (2093, 25), + (2097, 170), + (2099, 2), + (2100, 1), + (2101, 8), + (2102, 5), + (2104, 2), + (2105, 2), + (2107, 90), + (2108, 1), + (2110, 15), + (2112, 1), + (2113, 1), + (2114, 3), + (2115, 8), + (2116, 3), + (2117, 5), + (2118, 1380), + (2119, 4), + (2120, 1), + (2121, 3), + (2122, 1), + (2123, 6), + (2124, 24), + (2125, 1), + (2127, 33), + (2128, 4), + (2129, 197), + (2132, 1), + (2133, 3), + (2134, 8), + (2141, 1), + (2143, 95), + (2144, 6), + (2146, 1), + (2147, 1), + (2148, 3), + (2150, 1369), + (2152, 1), + (2153, 1), + (2155, 5), + (2156, 7), + (2157, 12), + (2158, 2), + (2159, 6), + (2160, 7), + (2161, 174), + (2162, 22), + (2163, 27), + (2164, 5), + (2165, 24), + (2166, 6), + (2169, 8), + (2170, 2), + (2171, 1), + (2172, 1), + (2174, 8), + (2175, 10), + (2176, 2), + (2177, 3), + (2179, 72), + (2180, 4), + (2181, 1), + (2182, 1366), + (2183, 2), + (2184, 5), + (2185, 4), + (2188, 3), + (2191, 1), + (2192, 2), + (2193, 169), + (2198, 7), + (2199, 27), + (2201, 28), + (2205, 2), + (2206, 2), + (2209, 9), + (2213, 8), + (2214, 1364), + (2215, 95), + (2216, 1), + (2217, 2), + (2218, 1), + (2219, 1), + (2220, 3), + (2221, 2), + (2222, 3), + (2223, 41), + (2225, 168), + (2228, 1), + (2229, 6), + (2230, 8), + (2231, 1), + (2232, 2), + (2233, 6), + (2234, 1), + (2235, 41), + (2236, 2), + (2237, 17), + (2240, 7), + (2242, 6), + (2244, 1), + (2246, 1350), + (2249, 2), + (2250, 4), + (2251, 89), + (2252, 1), + (2257, 167), + (2260, 4), + (2261, 3), + (2262, 6), + (2265, 1), + (2269, 2), + (2270, 4), + (2271, 32), + (2273, 21), + (2274, 1), + (2275, 3), + (2276, 1), + (2277, 2), + (2278, 1344), + (2279, 2), + (2280, 1), + (2281, 1), + (2284, 1), + (2287, 98), + (2288, 2), + (2289, 168), + (2292, 3), + (2293, 3), + (2294, 4), + (2298, 3), + (2303, 9), + (2307, 26), + (2308, 1), + (2309, 30), + (2310, 1344), + (2314, 1), + (2318, 1), + (2321, 164), + (2323, 1), + (2324, 82), + (2325, 1), + (2326, 5), + (2327, 1), + (2334, 6), + (2338, 1), + (2339, 1), + (2340, 1), + (2342, 1337), + (2343, 55), + (2344, 27), + (2345, 6), + (2346, 25), + (2347, 1), + (2348, 18), + (2350, 1), + (2351, 3), + (2352, 2), + (2353, 166), + (2358, 6), + (2360, 87), + (2361, 3), + (2362, 1), + (2373, 9), + (2374, 1330), + (2376, 1), + (2377, 1), + (2378, 11), + (2379, 4), + (2380, 28), + (2382, 29), + (2383, 2), + (2384, 8), + (2385, 169), + (2386, 4), + (2387, 9), + (2388, 8), + (2389, 4), + (2390, 15), + (2392, 1), + (2396, 117), + (2397, 4), + (2399, 1), + (2406, 1330), + (2410, 1), + (2414, 1), + (2415, 4), + (2416, 26), + (2417, 164), + (2418, 31), + (2421, 3), + (2422, 4), + (2424, 6), + (2425, 3), + (2426, 3), + (2427, 5), + (2428, 1), + (2429, 2), + (2432, 100), + (2433, 1), + (2435, 1), + (2436, 1), + (2438, 1328), + (2441, 10), + (2443, 11), + (2448, 2), + (2449, 163), + (2451, 1), + (2452, 27), + (2453, 8), + (2454, 24), + (2455, 1), + (2456, 2), + (2457, 2), + (2460, 4), + (2465, 5), + (2466, 3), + (2468, 95), + (2469, 6), + (2470, 1324), + (2471, 1), + (2472, 1), + (2476, 2), + (2477, 2), + (2478, 2), + (2479, 4), + (2481, 163), + (2484, 2), + (2485, 6), + (2486, 2), + (2488, 23), + (2489, 1), + (2490, 26), + (2491, 1), + (2493, 1), + (2494, 1), + (2495, 3), + (2496, 1), + (2500, 3), + (2502, 1327), + (2503, 1), + (2504, 93), + (2505, 2), + (2506, 1), + (2511, 4), + (2513, 166), + (2516, 3), + (2517, 5), + (2518, 8), + (2519, 2), + (2521, 1), + (2524, 27), + (2526, 20), + (2532, 1), + (2534, 1320), + (2535, 1), + (2540, 114), + (2541, 1), + (2543, 1), + (2545, 163), + (2550, 3), + (2555, 3), + (2557, 4), + (2558, 3), + (2559, 2), + (2560, 26), + (2561, 6), + (2562, 26), + (2564, 5), + (2565, 1), + (2566, 1325), + (2567, 5), + (2568, 9), + (2569, 10), + (2570, 2), + (2571, 1), + (2576, 97), + (2577, 165), + (2582, 3), + (2583, 5), + (2593, 2), + (2596, 42), + (2597, 1), + (2598, 1336), + (2602, 1), + (2609, 163), + (2612, 97), + (2613, 1), + (2614, 2), + (2619, 1), + (2621, 2), + (2624, 2), + (2628, 2), + (2630, 1684946), + (2632, 27), + (2633, 2), + (2634, 25), + (2635, 1), + (2637, 4), + (2639, 1), + (2640, 1), + (2641, 163), + (2644, 1), + (2645, 3), + (2646, 2), + (2648, 112), + (2649, 1), + (2653, 5), + (2659, 3), + (2660, 1), + (2661, 1), + (2662, 1315), + (2664, 1), + (2668, 30), + (2669, 1), + (2670, 26), + (2673, 163), + (2674, 2), + (2675, 1), + (2678, 7), + (2679, 1), + (2680, 1), + (2684, 90), + (2685, 1), + (2686, 1), + (2694, 1315), + (2699, 1), + (2701, 1), + (2704, 30), + (2705, 163), + (2706, 27), + (2710, 2), + (2712, 1), + (2720, 112), + (2721, 2), + (2723, 5), + (2726, 1316), + (2736, 1), + (2737, 165), + (2738, 2), + (2740, 25), + (2742, 33), + (2745, 1), + (2756, 97), + (2757, 1), + (2758, 1315), + (2769, 163), + (2774, 3), + (2776, 32), + (2778, 34), + (2781, 1), + (2782, 1), + (2784, 1), + (2790, 1313), + (2792, 94), + (2793, 12), + (2796, 1), + (2800, 1), + (2801, 163), + (2804, 2), + (2805, 6), + (2806, 2), + (2807, 2), + (2809, 1), + (2810, 1), + (2812, 23), + (2814, 33), + (2815, 3), + (2816, 1), + (2820, 2), + (2821, 1), + (2822, 1314), + (2824, 1), + (2828, 104), + (2829, 1), + (2833, 163), + (2837, 6), + (2838, 4), + (2839, 1), + (2848, 32), + (2849, 4), + (2850, 32), + (2852, 4), + (2853, 1), + (2854, 1312), + (2861, 1), + (2863, 52), + (2864, 111), + (2865, 164), + (2868, 2), + (2869, 15), + (2870, 2), + (2871, 1), + (2884, 30), + (2886, 1333), + (2890, 2), + (2891, 2), + (2892, 3), + (2893, 4), + (2894, 2), + (2897, 163), + (2899, 3), + (2900, 230), + (2901, 1), + (2902, 2), + (2908, 2), + (2911, 1), + (2918, 1312), + (2920, 42), + (2922, 25), + (2923, 1), + (2925, 1), + (2929, 165), + (2930, 2), + (2931, 5), + (2932, 4), + (2933, 8), + (2934, 2), + (2936, 110), + (2937, 1), + (2938, 1), + (2939, 1), + (2948, 1), + (2950, 1313), + (2956, 38), + (2958, 32), + (2961, 163), + (2964, 1), + (2966, 4), + (2967, 2), + (2969, 1), + (2971, 1), + (2972, 151), + (2973, 1), + (2975, 3), + (2976, 4), + (2977, 3), + (2978, 1), + (2979, 1), + (2980, 1), + (2982, 1312), + (2992, 28), + (2993, 163), + (2994, 29), + (2998, 2), + (3006, 1), + (3007, 2), + (3008, 188), + (3009, 2), + (3014, 1311), + (3015, 5), + (3016, 9), + (3017, 1), + (3020, 1), + (3025, 164), + (3028, 27), + (3030, 31), + (3044, 223), + (3045, 1), + (3046, 1311), + (3048, 1), + (3057, 163), + (3061, 2), + (3062, 4), + (3064, 41), + (3066, 35), + (3076, 2), + (3078, 1310), + (3080, 151), + (3081, 2), + (3089, 163), + (3094, 2), + (3100, 35), + (3101, 2), + (3102, 38), + (3104, 2), + (3110, 1310), + (3116, 106), + (3117, 2), + (3121, 163), + (3125, 5), + (3126, 2), + (3132, 2), + (3136, 36), + (3138, 39), + (3140, 2), + (3141, 1), + (3142, 1309), + (3143, 1), + (3144, 1), + (3152, 120), + (3153, 164), + (3155, 1), + (3157, 1), + (3158, 2), + (3163, 1), + (3164, 1), + (3172, 34), + (3174, 1343), + (3185, 163), + (3188, 136), + (3189, 1), + (3190, 2), + (3203, 1), + (3204, 1), + (3206, 1308), + (3208, 53), + (3210, 52), + (3217, 163), + (3220, 38), + (3221, 114), + (3222, 2), + (3224, 141), + (3225, 5), + (3230, 1), + (3236, 38), + (3238, 1308), + (3244, 35), + (3246, 46), + (3249, 163), + (3254, 2), + (3260, 105), + (3261, 4), + (3263, 1), + (3270, 1308), + (3280, 38), + (3281, 163), + (3282, 28), + (3286, 3), + (3292, 1), + (3296, 138), + (3297, 1), + (3301, 1), + (3302, 1308), + (3304, 1), + (3313, 163), + (3316, 33), + (3318, 34), + (3329, 1), + (3331, 1), + (3332, 120), + (3333, 1), + (3334, 1309), + (3345, 163), + (3350, 3), + (3352, 34), + (3354, 31), + (3357, 1), + (3366, 1307), + (3368, 230), + (3369, 6), + (3377, 163), + (3382, 2), + (3388, 37), + (3390, 45), + (3398, 1307), + (3404, 3128), + (3405, 2), + (3409, 163), + (3414, 2), + (3424, 40), + (3426, 23), + (3430, 1307), + (3440, 117), + (3441, 164), + (3446, 2), + (3460, 30), + (3462, 1344), + (3469, 1), + (3473, 163), + (3476, 116), + (3477, 1), + (3478, 3), + (3494, 1305), + (3496, 36), + (3498, 38), + (3501, 2), + (3504, 2), + (3505, 163), + (3510, 2), + (3512, 124), + (3513, 4), + (3515, 1), + (3525, 1), + (3526, 1305), + (3532, 27), + (3534, 33), + (3537, 165), + (3541, 2), + (3542, 2), + (3544, 2), + (3548, 119), + (3549, 1), + (3558, 1305), + (3568, 29), + (3569, 163), + (3570, 53), + (3574, 2), + (3581, 6), + (3584, 115), + (3585, 2), + (3590, 1306), + (3601, 163), + (3604, 39), + (3606, 45), + (3620, 107), + (3621, 1), + (3622, 1304), + (3633, 163), + (3634, 1), + (3637, 1), + (3638, 2), + (3640, 43), + (3642, 35), + (3654, 1305), + (3656, 126), + (3657, 2), + (3661, 1), + (3664, 1), + (3665, 163), + (3670, 3), + (3676, 32), + (3678, 48), + (3679, 1), + (3686, 1303), + (3692, 128), + (3693, 2), + (3697, 163), + (3702, 3), + (3712, 33), + (3714, 28), + (3718, 1302), + (3728, 137), + (3729, 165), + (3734, 2), + (3748, 54), + (3749, 1), + (3750, 1333), + (3758, 1), + (3761, 163), + (3764, 125), + (3765, 2), + (3766, 3), + (3782, 1301), + (3784, 32), + (3786, 50), + (3793, 163), + (3798, 2), + (3800, 123), + (3801, 3), + (3805, 1), + (3814, 1301), + (3820, 53), + (3822, 30), + (3825, 163), + (3830, 2), + (3833, 1), + (3836, 109), + (3837, 3), + (3846, 1301), + (3856, 35), + (3857, 163), + (3858, 54), + (3860, 20), + (3861, 51), + (3862, 2), + (3872, 124), + (3873, 2), + (3876, 17), + (3878, 1302), + (3882, 1), + (3889, 163), + (3892, 45), + (3894, 47), + (3901, 2), + (3903, 1), + (3904, 2), + (3908, 138), + (3909, 2), + (3910, 1300), + (3917, 2), + (3921, 163), + (3926, 2), + (3928, 38), + (3930, 37), + (3942, 1300), + (3944, 137), + (3945, 2), + (3953, 163), + (3958, 2), + (3964, 66), + (3966, 37), + (3971, 1), + (3974, 1300), + (3980, 166), + (3981, 1), + (3985, 163), + (3990, 2), + (4000, 35), + (4002, 54), + (4006, 1300), + (4016, 150), + (4017, 164), + (4021, 38), + (4022, 2), + (4024, 38), + (4036, 47), + (4038, 1347), + (4049, 163), + (4052, 134), + (4053, 10), + (4054, 2), + (4068, 1), + (4070, 1300), + (4072, 52), + (4074, 40), + (4075, 1), + (4081, 163), + (4085, 7), + (4086, 2), + (4088, 123), + (4089, 4), + (4100, 2), + (4102, 1300), + (4108, 38), + (4110, 43), + (4113, 163), + (4118, 2), + (4119, 2), + (4124, 159), + (4125, 3), + (4128, 1), + (4134, 1299), + (4141, 1), + (4144, 51), + (4145, 163), + (4146, 41), + (4150, 2), + (4152, 30), + (4160, 153), + (4161, 1), + (4164, 2), + (4166, 1299), + (4177, 163), + (4180, 225), + (4181, 596), + (4182, 50), + (4187, 1), + (4196, 373), + (4197, 3), + (4198, 1299), + (4209, 163), + (4214, 2), + (4216, 66), + (4217, 3), + (4218, 69), + (4221, 1), + (4230, 1299), + (4232, 158), + (4233, 2), + (4241, 163), + (4246, 2), + (4252, 45), + (4253, 1), + (4254, 48), + (4262, 1300), + (4267, 2), + (4268, 145), + (4269, 3), + (4270, 1), + (4271, 1), + (4273, 163), + (4278, 3), + (4288, 75), + (4290, 36), + (4294, 1298), + (4301, 1), + (4304, 173), + (4305, 166), + (4309, 2), + (4310, 2), + (4324, 52), + (4326, 1359), + (4337, 163), + (4340, 195), + (4341, 2), + (4342, 3), + (4358, 1297), + (4360, 76), + (4362, 56), + (4365, 2), + (4369, 163), + (4374, 2), + (4376, 171), + (4377, 1), + (4390, 1298), + (4396, 52), + (4398, 49), + (4401, 163), + (4406, 3), + (4407, 2), + (4412, 170), + (4413, 2), + (4421, 1), + (4422, 1296), + (4432, 57), + (4433, 163), + (4434, 51), + (4436, 1), + (4438, 2), + (4448, 481), + (4449, 2), + (4451, 1), + (4454, 1295), + (4463, 1), + (4465, 163), + (4468, 74), + (4470, 92), + (4484, 448), + (4485, 3), + (4486, 1295), + (4487, 1), + (4497, 163), + (4502, 2), + (4504, 52), + (4506, 65), + (4518, 1295), + (4519, 2), + (4520, 631), + (4521, 3), + (4529, 164), + (4530, 1), + (4532, 1), + (4533, 3), + (4534, 2), + (4540, 55), + (4542, 48), + (4550, 1294), + (4556, 2358), + (4557, 3), + (4561, 163), + (4562, 1), + (4566, 2), + (4576, 58), + (4578, 74), + (4582, 1294), + (4592, 193), + (4593, 167), + (4598, 2), + (4612, 66), + (4614, 1363), + (4621, 2), + (4625, 163), + (4628, 218), + (4629, 3), + (4630, 2), + (4635, 3), + (4640, 1), + (4645, 1), + (4646, 1295), + (4648, 57), + (4650, 90), + (4657, 163), + (4662, 3), + (4664, 194), + (4665, 1), + (4678, 1295), + (4684, 49), + (4685, 1), + (4686, 85), + (4689, 163), + (4694, 4), + (4700, 183), + (4701, 3), + (4710, 1291), + (4720, 61), + (4721, 163), + (4722, 75), + (4726, 3), + (4736, 175), + (4737, 4), + (4742, 1291), + (4753, 163), + (4756, 84), + (4758, 53), + (4772, 210), + (4773, 4), + (4774, 1291), + (4785, 163), + (4790, 2), + (4792, 54), + (4794, 66), + (4799, 2), + (4806, 1292), + (4808, 180), + (4809, 6), + (4817, 164), + (4820, 32), + (4821, 132), + (4822, 3), + (4824, 17), + (4828, 70), + (4830, 62), + (4836, 42), + (4838, 1290), + (4844, 199), + (4845, 3), + (4849, 163), + (4854, 2), + (4864, 104), + (4866, 98), + (4870, 1290), + (4873, 1), + (4880, 184), + (4881, 164), + (4886, 2), + (4900, 88), + (4902, 1387), + (4909, 1), + (4913, 163), + (4916, 187), + (4917, 6), + (4918, 2), + (4934, 1290), + (4936, 65), + (4938, 59), + (4945, 163), + (4948, 1), + (4950, 2), + (4952, 198), + (4953, 3), + (4966, 1290), + (4972, 64), + (4974, 108), + (4977, 163), + (4982, 2), + (4988, 199), + (4989, 8), + (4998, 1290), + (5008, 82), + (5009, 163), + (5010, 113), + (5012, 3), + (5013, 9), + (5014, 2), + (5017, 1), + (5024, 228), + (5025, 2), + (5028, 4), + (5030, 1290), + (5041, 162), + (5044, 96), + (5046, 71), + (5060, 275), + (5061, 6), + (5062, 1291), + (5064, 1), + (5070, 1), + (5073, 162), + (5078, 3), + (5080, 66), + (5082, 153), + (5094, 1289), + (5096, 272), + (5097, 10), + (5101, 2), + (5104, 2), + (5105, 162), + (5110, 2), + (5116, 87), + (5118, 80), + (5126, 1289), + (5132, 266), + (5133, 5), + (5135, 1), + (5137, 162), + (5140, 190), + (5141, 681), + (5142, 2), + (5152, 104), + (5154, 184), + (5156, 238), + (5158, 1289), + (5168, 257), + (5169, 165), + (5174, 2), + (5188, 99), + (5190, 1435), + (5201, 162), + (5204, 228), + (5205, 6), + (5206, 2), + (5221, 206), + (5222, 1289), + (5224, 312), + (5226, 110), + (5231, 1), + (5233, 162), + (5238, 2), + (5240, 266), + (5241, 7), + (5254, 1289), + (5260, 87), + (5262, 243), + (5265, 162), + (5270, 2), + (5274, 8), + (5276, 318), + (5277, 7), + (5286, 1289), + (5288, 86), + (5296, 88), + (5297, 162), + (5298, 123), + (5302, 3), + (5312, 351), + (5313, 1), + (5318, 1289), + (5329, 162), + (5332, 115), + (5334, 173), + (5339, 6), + (5344, 1), + (5348, 313), + (5349, 3), + (5350, 1289), + (5352, 24), + (5353, 14), + (5361, 162), + (5366, 3), + (5368, 157), + (5370, 107), + (5374, 1), + (5382, 1289), + (5384, 293), + (5385, 4), + (5388, 4), + (5393, 162), + (5396, 1), + (5398, 2), + (5404, 142), + (5406, 201), + (5407, 1), + (5414, 1289), + (5417, 3), + (5420, 285), + (5421, 5), + (5423, 1), + (5425, 162), + (5430, 2), + (5436, 1), + (5440, 142), + (5442, 210), + (5444, 1), + (5446, 1294), + (5456, 318), + (5457, 166), + (5462, 3), + (5476, 123), + (5478, 1608), + (5482, 2), + (5489, 162), + (5492, 329), + (5493, 2), + (5494, 2), + (5504, 1), + (5506, 1), + (5510, 1289), + (5511, 1), + (5512, 165), + (5514, 167), + (5521, 163), + (5522, 1), + (5526, 2), + (5528, 367), + (5529, 8), + (5542, 1289), + (5548, 192), + (5550, 291), + (5553, 162), + (5558, 2), + (5564, 399), + (5565, 13), + (5574, 1289), + (5584, 188), + (5585, 163), + (5586, 356), + (5590, 2), + (5592, 1), + (5599, 1), + (5600, 375), + (5601, 3), + (5606, 1290), + (5608, 1), + (5617, 162), + (5618, 1), + (5620, 261), + (5622, 667), + (5623, 1), + (5626, 1), + (5633, 1), + (5636, 406), + (5637, 4), + (5638, 1289), + (5639, 1), + (5649, 162), + (5654, 2), + (5656, 468), + (5658, 1159), + (5662, 1), + (5670, 1289), + (5671, 1), + (5672, 349), + (5673, 8), + (5675, 1), + (5681, 162), + (5686, 2), + (5692, 321), + (5694, 3067), + (5702, 1289), + (5706, 1), + (5708, 443), + (5709, 7), + (5713, 162), + (5718, 2), + (5728, 496), + (5730, 4577), + (5734, 1289), + (5744, 383), + (5745, 165), + (5750, 3), + (5756, 1), + (5758, 1), + (5764, 5847), + (5766, 8966), + (5775, 1), + (5777, 162), + (5780, 616), + (5781, 240), + (5782, 2), + (5784, 1), + (5788, 1), + (5796, 81), + (5798, 1289), + (5799, 1), + (5800, 5543), + (5802, 13287), + (5809, 162), + (5814, 2), + (5816, 409), + (5817, 3), + (5830, 1289), + (5833, 1), + (5836, 123), + (5838, 59), + (5841, 162), + (5846, 2), + (5852, 480), + (5853, 10), + (5862, 1289), + (5872, 191), + (5873, 162), + (5874, 38), + (5878, 2), + (5888, 616), + (5889, 12), + (5894, 1289), + (5905, 162), + (5908, 139), + (5910, 54), + (5922, 1), + (5924, 675), + (5925, 9), + (5926, 1289), + (5937, 162), + (5942, 2), + (5944, 153), + (5946, 48), + (5958, 1289), + (5960, 614), + (5961, 33), + (5969, 162), + (5974, 2), + (5980, 140), + (5982, 95), + (5990, 1289), + (5996, 628), + (5997, 10), + (6001, 162), + (6006, 2), + (6016, 155), + (6018, 67), + (6021, 42), + (6022, 1289), + (6024, 42), + (6032, 772), + (6033, 177), + (6038, 2), + (6049, 1), + (6052, 109), + (6054, 1340), + (6065, 162), + (6068, 749), + (6069, 11), + (6070, 2), + (6086, 1289), + (6088, 364), + (6090, 49), + (6096, 1), + (6097, 162), + (6102, 2), + (6104, 975), + (6105, 4), + (6106, 1), + (6118, 1289), + (6124, 273), + (6126, 58), + (6129, 162), + (6134, 2), + (6138, 1), + (6140, 1053), + (6141, 13), + (6150, 1289), + (6152, 1), + (6153, 2), + (6160, 372), + (6161, 162), + (6162, 70), + (6164, 1), + (6166, 2), + (6172, 1), + (6176, 1088), + (6177, 96), + (6178, 1), + (6182, 1290), + (6188, 4), + (6193, 162), + (6194, 1), + (6196, 346), + (6198, 101), + (6206, 1), + (6212, 1352), + (6213, 4), + (6214, 1290), + (6219, 2), + (6223, 1), + (6225, 162), + (6230, 1), + (6232, 321), + (6234, 170), + (6246, 1290), + (6248, 1755), + (6249, 4), + (6257, 162), + (6261, 4), + (6262, 1), + (6264, 4), + (6268, 616), + (6270, 141), + (6275, 1), + (6278, 1289), + (6280, 1), + (6281, 1), + (6284, 2516), + (6285, 73), + (6289, 162), + (6294, 1), + (6304, 409), + (6306, 163), + (6310, 1289), + (6314, 2), + (6320, 2276), + (6321, 210), + (6326, 1), + (6340, 445), + (6342, 1437), + (6353, 162), + (6356, 4090), + (6357, 55), + (6358, 1), + (6364, 1), + (6374, 1290), + (6376, 929), + (6378, 270), + (6385, 162), + (6390, 1), + (6392, 6135), + (6393, 16), + (6400, 1), + (6406, 1289), + (6412, 607), + (6414, 386), + (6417, 162), + (6420, 1), + (6421, 238), + (6422, 1), + (6424, 238), + (6428, 15189), + (6429, 227), + (6438, 1289), + (6443, 1), + (6448, 1211), + (6449, 162), + (6450, 1135), + (6453, 2), + (6454, 1), + (6464, 66588), + (6465, 77), + (6470, 1289), + (6474, 31), + (6481, 162), + (6484, 21001), + (6486, 9926), + (6488, 95), + (6498, 1), + (6500, 51017), + (6501, 2547), + (6502, 1289), + (6513, 162), + (6518, 1), + (6520, 11978), + (6522, 2546), + (6534, 1289), + (6536, 1), + (6537, 4), + (6539, 7), + (6545, 162), + (6546, 1), + (6550, 1), + (6553, 27), + (6566, 1289), + (6572, 1), + (6573, 2), + (6574, 1), + (6577, 163), + (6582, 2), + (6587, 1), + (6588, 17), + (6598, 1289), + (6600, 1), + (6603, 1), + (6605, 1), + (6606, 2), + (6608, 1), + (6609, 163), + (6610, 1), + (6614, 1), + (6623, 4), + (6630, 1289), + (6631, 1), + (6633, 1), + (6635, 1), + (6640, 1), + (6641, 162), + (6644, 1), + (6645, 2), + (6646, 2), + (6662, 1289), + (6666, 1), + (6670, 1), + (6673, 162), + (6678, 1), + (6679, 1), + (6680, 1), + (6681, 5), + (6686, 1), + (6694, 1289), + (6705, 162), + (6710, 1), + (6711, 1), + (6714, 1), + (6716, 1), + (6717, 10), + (6726, 1289), + (6734, 1), + (6737, 163), + (6738, 1), + (6740, 2), + (6742, 1), + (6752, 1), + (6753, 1), + (6757, 1), + (6758, 1289), + (6769, 162), + (6770, 1), + (6774, 1), + (6775, 1), + (6788, 1), + (6789, 3), + (6790, 1289), + (6797, 1), + (6801, 162), + (6802, 1), + (6803, 1), + (6806, 1), + (6818, 1), + (6819, 1), + (6822, 1289), + (6824, 1), + (6825, 5), + (6833, 162), + (6834, 1), + (6837, 1), + (6838, 1), + (6844, 2), + (6854, 1289), + (6860, 1), + (6861, 5), + (6865, 163), + (6869, 1), + (6870, 1), + (6872, 1), + (6875, 1), + (6881, 3), + (6886, 1289), + (6896, 1), + (6897, 166), + (6902, 1), + (6915, 1), + (6918, 1289), + (6929, 162), + (6932, 2), + (6933, 1), + (6934, 1), + (6947, 1), + (6950, 1290), + (6961, 162), + (6966, 1), + (6969, 2), + (6982, 1289), + (6993, 162), + (6998, 1), + (7004, 1), + (7005, 1), + (7014, 1289), + (7025, 162), + (7030, 1), + (7032, 1), + (7034, 1), + (7040, 1), + (7041, 1), + (7046, 1289), + (7057, 162), + (7058, 1), + (7059, 1), + (7062, 1), + (7070, 1), + (7076, 1), + (7077, 3), + (7078, 1289), + (7084, 1), + (7089, 162), + (7094, 1), + (7110, 1289), + (7112, 1), + (7113, 5), + (7121, 162), + (7124, 1), + (7126, 1), + (7133, 1), + (7142, 1289), + (7148, 1), + (7149, 12), + (7153, 162), + (7158, 1), + (7174, 1289), + (7184, 1), + (7185, 170), + (7190, 1), + (7206, 1289), + (7217, 162), + (7220, 1), + (7221, 82), + (7222, 1), + (7224, 81), + (7229, 1), + (7237, 1), + (7238, 1289), + (7242, 1), + (7243, 1), + (7248, 1), + (7249, 162), + (7254, 1), + (7256, 1), + (7257, 1), + (7266, 4), + (7270, 1289), + (7274, 13), + (7280, 20), + (7281, 162), + (7286, 1), + (7288, 12), + (7292, 1), + (7293, 5), + (7296, 1), + (7302, 1289), + (7308, 1), + (7313, 162), + (7315, 1), + (7318, 1), + (7328, 1), + (7329, 1), + (7334, 1290), + (7345, 162), + (7349, 1), + (7350, 1), + (7353, 1), + (7364, 1), + (7365, 1), + (7366, 1290), + (7377, 162), + (7382, 1), + (7392, 1), + (7398, 1289), + (7400, 1), + (7401, 4), + (7406, 1), + (7409, 162), + (7411, 1), + (7414, 1), + (7430, 1289), + (7431, 3), + (7436, 1), + (7437, 2), + (7441, 162), + (7445, 5), + (7446, 1), + (7448, 1), + (7460, 1), + (7462, 1289), + (7472, 1), + (7473, 166), + (7474, 1), + (7478, 1), + (7494, 1289), + (7505, 162), + (7508, 3), + (7509, 2), + (7510, 2), + (7525, 1), + (7526, 1289), + (7532, 1), + (7537, 162), + (7542, 1), + (7544, 1), + (7545, 9), + (7546, 1), + (7558, 1289), + (7569, 162), + (7574, 1), + (7580, 1), + (7581, 6), + (7590, 1289), + (7601, 162), + (7606, 1), + (7616, 1), + (7617, 6), + (7622, 1289), + (7623, 1), + (7625, 1), + (7633, 162), + (7638, 1), + (7652, 1), + (7653, 11), + (7654, 1289), + (7657, 1), + (7665, 162), + (7670, 1), + (7686, 1289), + (7688, 1), + (7689, 1), + (7697, 162), + (7702, 1), + (7708, 1), + (7715, 1), + (7717, 2), + (7718, 1289), + (7724, 1), + (7725, 3), + (7729, 162), + (7734, 1), + (7746, 1), + (7750, 1289), + (7760, 1), + (7761, 167), + (7766, 1), + (7782, 1289), + (7793, 162), + (7794, 1), + (7796, 1), + (7797, 1), + (7798, 1), + (7814, 1289), + (7820, 1), + (7825, 162), + (7826, 1), + (7830, 1), + (7832, 1), + (7833, 14), + (7842, 1), + (7846, 1289), + (7857, 162), + (7862, 1), + (7863, 1), + (7868, 1), + (7869, 4), + (7878, 1289), + (7885, 1), + (7889, 162), + (7894, 1), + (7904, 1), + (7905, 2), + (7910, 1289), + (7921, 162), + (7926, 1), + (7929, 1), + (7940, 1), + (7941, 2), + (7942, 1289), + (7953, 162), + (7958, 1), + (7963, 1), + (7973, 1), + (7974, 1289), + (7976, 1), + (7977, 16), + (7985, 162), + (7989, 1), + (7990, 1), + (7991, 1), + (7997, 1), + (8000, 1), + (8006, 1289), + (8012, 1), + (8013, 14), + (8017, 162), + (8022, 1), + (8038, 1289), + (8048, 1), + (8049, 185), + (8054, 2), + (8070, 1289), + (8081, 162), + (8084, 1), + (8085, 24), + (8086, 1), + (8102, 1289), + (8113, 162), + (8118, 1), + (8119, 1), + (8120, 1), + (8121, 1), + (8126, 1), + (8134, 1289), + (8140, 1), + (8145, 162), + (8150, 1), + (8157, 20), + (8166, 1289), + (8177, 162), + (8182, 1), + (8192, 1), + (8193, 1), + (8198, 1289), + (8209, 162), + (8214, 1), + (8228, 1), + (8229, 32), + (8230, 1290), + (8246, 1), + (8264, 1), + (8265, 27), + (8269, 1), + (8276, 1), + (8282, 1), + (8300, 1), + (8301, 133), + (8336, 2), + (8337, 60), + (8348, 3), + (8356, 1), + (8358, 1), + (8372, 1), + (8373, 196), + (8408, 1), + (8444, 1), + (8468, 1), + (8480, 1), + (8499, 1), + (8516, 1), + (8552, 1), + (8555, 1), + (8588, 1), + (8624, 1), + (8660, 3), + (8675, 1), + (8696, 1), + (8704, 1), + (8724, 1), + (8732, 1), + (8768, 1), + (8779, 1), + (8804, 1), + (8840, 1), + (8852, 2), + (8876, 1), + (8912, 1), + (8948, 1), + (8984, 1), + (9020, 1), + (9128, 1), + (9164, 1), + (9192, 1), + (9200, 2), + (9236, 1), + (9272, 1), + (9308, 1), + (9344, 1), + (9380, 1), + (9416, 1), + (9452, 1), + (9524, 1), + (9560, 1), + (9589, 1), + (9632, 1), + (9642, 1), + (9704, 1), + (9776, 1), + (9848, 1), + (9992, 1), + (10064, 1), + (10100, 1), + (10136, 1), + (10172, 1), + (10208, 1), + (10244, 1), + (10280, 1), + (10316, 1), + (10388, 1), + (10532, 1), + (10572, 1), + (10620, 1), + (10640, 1), + (10669, 1), + (10748, 1), + (10856, 1), + (10964, 1), + (11067, 1), + (11072, 1), + (11180, 1), + (11216, 1), + (11252, 1), + (11288, 1), + (11324, 1), + (11348, 2), + (11360, 1), + (11396, 1), + (11432, 1), + (11468, 1), + (11504, 1), + (11540, 1), + (11576, 1), + (11612, 1), + (11648, 1), + (11756, 1), + (11792, 1), + (11828, 1), + (11864, 1), + (11936, 1), + (12008, 1), + (12080, 1), + (12152, 1), + (12188, 1), + (12224, 1), + (12260, 1), + (12296, 1), + (12332, 1), + (12360, 1), + (12368, 1), + (12404, 1), + (12440, 1), + (12476, 1), + (12501, 2), + (12512, 1), + (12548, 1), + (12584, 1), + (12620, 1), + (12656, 1), + (12693, 1), + (12728, 1), + (12885, 1), + (13123, 1), + (13269, 1), + (13461, 1), + (13653, 1), + (13664, 1), + (13740, 1), + (13872, 1), + (13946, 1), + (14109, 1), + (14613, 2), + (14805, 2), + (14945, 1), + (14997, 1), + (15176, 1), + (15276, 1), + (15384, 1), + (15492, 1), + (15600, 1), + (15708, 1), + (15716, 1), + (15765, 1), + (15816, 1), + (15924, 1), + (16068, 1), + (16104, 1), + (16140, 1), + (16176, 1), + (16212, 1), + (16248, 1), + (16284, 1), + (16320, 1), + (16356, 1), + (16392, 1), + (16430, 1), + (16468, 1), + (16504, 1), + (16540, 1), + (16727, 2), + (16728, 1), + (16919, 2), + (16921, 1), + (16938, 1), + (17111, 6), + (17413, 1), + (17430, 1), + (17495, 1), + (17880, 1), + (18647, 2), + (18672, 1), + (19223, 38), + (19680, 1), + (20436, 1), + (21156, 1), + (21732, 1), + (22380, 1), + (22992, 1), + (23063, 17), + (23244, 1), + (23532, 1), + (23892, 1), + (24108, 1), + (24215, 1), + (24324, 1), + (24407, 2), + (24504, 1), + (24720, 1), + (24900, 1), + (24983, 205), + (25440, 1), + (25620, 1), + (26088, 1), + (26268, 1), + (26448, 1), + (26664, 1), + (26988, 1), + (27276, 1), + (27492, 1), + (27744, 1), + (28032, 1), + (28284, 1), + (28536, 1), + (28823, 42), + (28896, 1), + (29184, 1), + (29292, 1), + (29400, 1), + (29796, 1), + (29975, 4), + (30156, 1), + (30228, 1), + (30743, 238), + (30768, 1), + (31056, 1), + (31092, 1), + (31416, 1), + (32100, 1), + (32712, 1), + (33144, 1), + (33324, 1), + (33792, 1), + (34008, 1), + (34440, 1), + (34583, 81), + (34656, 1), + (34872, 1), + (34944, 1), + (35160, 1), + (35304, 1), + (35376, 1), + (35412, 1), + (35556, 1), + (35628, 1), + (35664, 1), + (35808, 1), + (36204, 1), + (36744, 1), + (37788, 1), + (39372, 1), + (40956, 1), + (41640, 1), + (41892, 1), + (42144, 1), + (42576, 1), + (42936, 1), + (43476, 1), + (45096, 1), + (47256, 1), + (47760, 1), + (47796, 1), + (47868, 1), + (48228, 1), + (48948, 1), + (49128, 1), + (49452, 1), + (49560, 1), + (49668, 1), + (49776, 1), + (50352, 1), + (50964, 1), + (52008, 1), + (53880, 1), + (55284, 1), + (55860, 1), + (56040, 1), + (56400, 1), + (56904, 1), + (57444, 1), + (59424, 1), + (60156, 1), + (60626, 1), + (60641, 1), + (61260, 1), + (62520, 1), + (64392, 1), + (65976, 1), + (67308, 1), + (68064, 1), + (68748, 1), + (69216, 1), + (69504, 1), + (69648, 1), + (69684, 1), + (69720, 1), + (69756, 1), + (69792, 1), + (69828, 1), + (70224, 1), + (70620, 1), + (71016, 1), + (71412, 1), + (71772, 1), + (71952, 1), + (72024, 1), + (72096, 1), + (72168, 1), + (72240, 1), + (72312, 1), + (72348, 1), + (72420, 1), + (72492, 1), + (72600, 1), + (72672, 1), + (72780, 1), + (72996, 1), + (73320, 1), + (73356, 1), + (73500, 1), + (73536, 1), + (73572, 1), + (73608, 1), + (73680, 1), + (73716, 1), + (73788, 1), + (73896, 1), + (74040, 1), + (74112, 1), + (74170, 1), + (74184, 1), + (74185, 1), + (74220, 1), + (74256, 1), + (74292, 1), + (74328, 1), + (74364, 1), + (74400, 1), + (74436, 1), + (74472, 1), + (74616, 1), + (74976, 1), + (75156, 1), + (75228, 1), + (75336, 1), + (75408, 1), + (75588, 1), + (75696, 1), + (75804, 1), + (75984, 1), + (76056, 1), + (76164, 1), + (76308, 1), + (76452, 1), + (76560, 1), + (76776, 1), + (76920, 1), + (77064, 1), + (77208, 1), + (77316, 1), + (77532, 1), + (77676, 1), + (77748, 1), + (77820, 1), + (77928, 1), + (78000, 1), + (78036, 1), + (78072, 1), + (78108, 1), + (78180, 1), + (78324, 1), + (78396, 1), + (78576, 1), + (78684, 1), + (78828, 1), + (78864, 1), + (78900, 1), + (78972, 1), + (79080, 1), + (79116, 1), + (79152, 1), + (79512, 1), + (79872, 1), + (80268, 1), + (80592, 1), + (80700, 1), + (80916, 1), + (81168, 1), + (81276, 1), + (81528, 1), + (81708, 1), + (81816, 1), + (81888, 1), + (82068, 1), + (82176, 1), + (82284, 1), + (82356, 1), + (82716, 1), + (83004, 1), + (83312, 1), + (83436, 1), + (83688, 1), + (83904, 1), + (84012, 1), + (84408, 1), + (84660, 1), + (85056, 1), + (85488, 1), + (85776, 1), + (85992, 1), + (86172, 1), + (86424, 1), + (86615, 1), + (86640, 1), + (86928, 1), + (87072, 1), + (87288, 1), + (87576, 1), + (87684, 1), + (87756, 1), + (87972, 1), + (88044, 1), + (88152, 1), + (88368, 1), + (88728, 1), + (88836, 1), + (88944, 1), + (89088, 1), + (89448, 1), + (89592, 1), + (89700, 1), + (89808, 1), + (89952, 1), + (90060, 1), + (90204, 1), + (90348, 1), + (90528, 1), + (90636, 1), + (90744, 1), + (90816, 1), + (91032, 1), + (91068, 1), + (91140, 1), + (91212, 1), + (91284, 1), + (91860, 1), + (92112, 1), + (92292, 1), + (92400, 1), + (92544, 1), + (92652, 1), + (92796, 1), + (92904, 1), + (92976, 1), + (93192, 1), + (93300, 1), + (93444, 1), + (93516, 1), + (93624, 1), + (93696, 1), + (93840, 1), + (93984, 1), + (94056, 1), + (94128, 1), + (94164, 1), + (94200, 1), + (94236, 1), + (94272, 1), + (94344, 1), + (94452, 1), + (94524, 1), + (94596, 1), + (94704, 1), + (94776, 1), + (94884, 1), + (94956, 1), + (95172, 1), + (95244, 1), + (95280, 1), + (95316, 1), + (95352, 1), + (95388, 1), + (95424, 1), + (95460, 1), + (95496, 1), + (95604, 1), + (95676, 1), + (95784, 1), + (95856, 1), + (95928, 1), + (96000, 1), + (96036, 1), + (96072, 1), + (96108, 1), + (96144, 1), + (96180, 1), + (96216, 1), + (96288, 1), + (96576, 1), + (98029, 1), + (98304, 1), + (98527, 1), + (98628, 1), + (99276, 1), + (99528, 1), + (99780, 1), + (99996, 1), + (100212, 1), + (100428, 1), + (100680, 1), + (100752, 1), + (100788, 1), + (100860, 1), + (100932, 1), + (101004, 1), + (101076, 1), + (101148, 1), + (101220, 1), + (101256, 1), + (101328, 1), + (101364, 1), + (101400, 1), + (101436, 1), + (101472, 1), + (101508, 1), + (101544, 1), + (101616, 1), + (101652, 1), + (101724, 1), + (101832, 1), + (101904, 1), + (101940, 1), + (101976, 1), + (102012, 1), + (102048, 1), + (102084, 1), + (102120, 1), + (102264, 1), + (102516, 1), + (102588, 1), + (102624, 1), + (102660, 1), + (102696, 1), + (102732, 1), + (102768, 1), + (102804, 1), + (102840, 1), + (102876, 1), + (102912, 1), + (102948, 1), + (102984, 1), + (103056, 1), + (103092, 1), + (103128, 1), + (103164, 1), + (103200, 1), + (103236, 1), + (103272, 1), + (103308, 1), + (103344, 1), + (103380, 1), + (103452, 1), + (103560, 1), + (103596, 1), + (103632, 1), + (103668, 1), + (103704, 1), + (103740, 1), + (103776, 1), + (103848, 1), + (103920, 1), + (103956, 1), + (104028, 1), + (104100, 1), + (104136, 1), + (104208, 1), + (104244, 1), + (104316, 1), + (104352, 1), + (104388, 1), + (104424, 1), + (104460, 1), + (104496, 1), + (104532, 1), + (104568, 1), + (104604, 1), + (104676, 1), + (104712, 1), + (104748, 1), + (104784, 1), + (104820, 1), + (104856, 1), + (104892, 1), + (104928, 1), + (104964, 1), + (105000, 1), + (105036, 1), + (105072, 1), + (105108, 1), + (105216, 1), + (105324, 1), + (105360, 1), + (105396, 1), + (105432, 1), + (105468, 1), + (105504, 1), + (105540, 1), + (105576, 1), + (105612, 1), + (105648, 1), + (105684, 1), + (105720, 1), + (105756, 1), + (105792, 1), + (105828, 1), + (105864, 1), + (105900, 1), + (105936, 1), + (110580, 1), + (115224, 1), + (118788, 1), + (121056, 1), + (121452, 1), + (121848, 1), + (122244, 1), + (122604, 1), + (122928, 1), + (123252, 1), + (123288, 1), + (123360, 1), + (123432, 1), + (123468, 1), + (123504, 1), + (123540, 1), + (123612, 1), + (123684, 1), + (123756, 1), + (123828, 1), + (123900, 1), + (123972, 1), + (124080, 1), + (124188, 1), + (124296, 1), + (124404, 1), + (124548, 1), + (124764, 1), + (124872, 1), + (124980, 1), + (125088, 1), + (125196, 1), + (125304, 1), + (125412, 1), + (125448, 1), + (125520, 1), + (125628, 1), + (125700, 1), + (125772, 1), + (125844, 1), + (125880, 1), + (125916, 1), + (125952, 1), + (125988, 1), + (126024, 1), + (126060, 1), + (126096, 1), + (126168, 1), + (126276, 1), + (126312, 1), + (126348, 1), + (126420, 1), + (126492, 1), + (126564, 1), + (126636, 1), + (126708, 1), + (126780, 1), + (126852, 1), + (126960, 1), + (127068, 1), + (127176, 1), + (127212, 1), + (127248, 1), + (127284, 1), + (127320, 1), + (127356, 1), + (127392, 1), + (127464, 1), + (127536, 1), + (127608, 1), + (127644, 1), + (127680, 1), + (127716, 1), + (127788, 1), + (127860, 1), + (127932, 1), + (128004, 1), + (128076, 1), + (128148, 1), + (128220, 1), + (128256, 1), + (128292, 1), + (128328, 1), + (128364, 1), + (128400, 1), + (128436, 1), + (128472, 1), + (128508, 1), + (128544, 1), + (128580, 1), + (128616, 1), + (128652, 1), + (128688, 1), + (128724, 1), + (128760, 1), + (128832, 1), + (128904, 1), + (128976, 1), + (129048, 1), + (129120, 1), + (129192, 1), + (129228, 1), + (129264, 1), + (129300, 1), + (129372, 1), + (129408, 1), + (129444, 1), + (129480, 1), + (129516, 1), + (129552, 1), + (129588, 1), + (129660, 1), + (129732, 1), + (129768, 1), + (129804, 1), + (129840, 1), + (129876, 1), + (129912, 1), + (129948, 1), + (129984, 1), + (130020, 1), + (130056, 1), + (130128, 1), + (130200, 1), + (130236, 1), + (130272, 1), + (130308, 1), + (130380, 1), + (130452, 1), + (130524, 1), + (130560, 1), + (130596, 1), + (130632, 1), + (130668, 1), + (130704, 1), + (130776, 1), + (130812, 1), + (130848, 1), + (130920, 1), + (130992, 1), + (131064, 1), + (131136, 1), + (131172, 1), + (131208, 1), + (131244, 1), + (131316, 1), + (131388, 1), + (131424, 1), + (131532, 1), + (131640, 1), + (131784, 1), + (131892, 1), + (131964, 1), + (132036, 1), + (132108, 1), + (132180, 1), + (132252, 1), + (132324, 1), + (132360, 1), + (132432, 1), + (132504, 1), + (132576, 1), + (132684, 1), + (132792, 1), + (132900, 1), + (132972, 1), + (133044, 1), + (133116, 1), + (133188, 1), + (133260, 1), + (133332, 1), + (133368, 1), + (133404, 1), + (133440, 1), + (133476, 1), + (133512, 1), + (133548, 1), + (133620, 1), + (133692, 1), + (133764, 1), + (133836, 1), + (133908, 1), + (133980, 1), + (134016, 1), + (134052, 1), + (134088, 1), + (134124, 1), + (134160, 1), + (134196, 1), + (134232, 1), + (134268, 1), + (134304, 1), + (134340, 1), + (134376, 1), + (134412, 1), + (134484, 1), + (134592, 1), + (134700, 1), + (134808, 1), + (134916, 1), + (134988, 1), + (135024, 1), + (135060, 1), + (135096, 1), + (135132, 1), + (135168, 1), + (135204, 1), + (135240, 1), + (135276, 1), + (135312, 1), + (135348, 1), + (135384, 1), + (135456, 1), + (135492, 1), + (135528, 1), + (135564, 1), + (135600, 1), + (135636, 1), + (135672, 1), + (135708, 1), + (135744, 1), + (135780, 1), + (135816, 1), + (135852, 1), + (135888, 1), + (135924, 1), + (135960, 1), + (135996, 1), + (136032, 1), + (136068, 1), + (136140, 1), + (136212, 1), + (136284, 1), + (136356, 1), + (136428, 1), + (136500, 1), + (136572, 1), + (136608, 1), + (136644, 1), + (136680, 1), + (136716, 1), + (136752, 1), + (136788, 1), + (136824, 1), + (136860, 1), + (136896, 1), + (136932, 1), + (136968, 1), + (137004, 1), + (137040, 1), + (137076, 1), + (137112, 1), + (137148, 1), + (137184, 1), + (137256, 1), + (137328, 1), + (137400, 1), + (137472, 1), + (137544, 1), + (137580, 1), + (137616, 1), + (137652, 1), + (137688, 1), + (137724, 1), + (137796, 1), + (137832, 1), + (137868, 1), + (137904, 1), + (137940, 1), + (137976, 1), + (138012, 1), + (138048, 1), + (138084, 1), + (138120, 1), + (138228, 1), + (138300, 1), + (138336, 1), + (138372, 1), + (138408, 1), + (138444, 1), + (138480, 1), + (138516, 1), + (138552, 1), + (138588, 1), + (138624, 1), + (138696, 1), + (138768, 1), + (138840, 1), + (138912, 1), + (138948, 1), + (138984, 1), + (139020, 1), + (139056, 1), + (139092, 1), + (139128, 1), + (139164, 1), + (139200, 1), + (139272, 1), + (139308, 1), + (139380, 1), + (139452, 1), + (139488, 1), + (139524, 1), + (139596, 1), + (139632, 1), + (139668, 1), + (139704, 1), + (139740, 1), + (139776, 1), + (139848, 1), + (139884, 1), + (139920, 1), + (139956, 1), + (139992, 1), + (140028, 1), + (140064, 1), + (140136, 1), + (140172, 1), + (140208, 1), + (140244, 1), + (140280, 1), + (140316, 1), + (140352, 1), + (140424, 1), + (140460, 1), + (140496, 1), + (140532, 1), + (140604, 1), + (140640, 1), + (140676, 1), + (140712, 1), + (140748, 1), + (140784, 1), + (140820, 1), + (140856, 1), + (140928, 1), + (141036, 1), + (141072, 1), + (141108, 1), + (141144, 1), + (141180, 1), + (141216, 1), + (141252, 1), + (141324, 1), + (141396, 1), + (141432, 1), + (141468, 1), + (141504, 1), + (141612, 1), + (142152, 1), + (142188, 1), + (142260, 1), + (142296, 1), + (142800, 1), + (143304, 1), + (143376, 1), + (143448, 1), + (143520, 1), + (143592, 1), + (143664, 1), + (143700, 1), + (143736, 1), + (143772, 1), + (143808, 1), + (143844, 1), + (143880, 1), + (143952, 1), + (144096, 1), + (144240, 1), + (144348, 1), + (144456, 1), + (144564, 1), + (144672, 1), + (144708, 1), + (144744, 1), + (144780, 1), + (144816, 1), + (144852, 1), + (144888, 1), + (144924, 1), + (144960, 1), + (144996, 1), + (145032, 1), + (145068, 1), + (145104, 1), + (145140, 1), + (145176, 1), + (145212, 1), + (145248, 1), + (145284, 1), + (145320, 1), + (145356, 1), + (145392, 1), + (145464, 1), + (145500, 1), + (145536, 1), + (145572, 1), + (145644, 1), + (145716, 1), + (145752, 1), + (145788, 1), + (145824, 1), + (145860, 1), + (145896, 1), + (145932, 1), + (145968, 1), + (146004, 1), + (146040, 1), + (146076, 1), + (146112, 1), + (146148, 1), + (146184, 1), + (146220, 1), + (146256, 1), + (146292, 1), + (146328, 1), + (146364, 1), + (146400, 1), + (146436, 1), + (146472, 1), + (146508, 1), + (146544, 1), + (146580, 1), + (146616, 1), + (146652, 1), + (146688, 1), + (146724, 1), + (146760, 1), + (146796, 1), + (146832, 1), + (146868, 1), + (146940, 1), + (146976, 1), + (147012, 1), + (147048, 1), + (147084, 1), + (147120, 1), + (147156, 1), + (147192, 1), + (147228, 1), + (147264, 1), + (147300, 1), + (147336, 1), + (147372, 1), + (147408, 1), + (147444, 1), + (147480, 1), + (147516, 1), + (147552, 1), + (147588, 1), + (147624, 1), + (147660, 1), + (147732, 1), + (147768, 1), + (147804, 1), + (147840, 1), + (147876, 1), + (147912, 1), + (147948, 1), + (147984, 1), + (148020, 1), + (148056, 1), + (148092, 1), + (148128, 1), + (148164, 1), + (148200, 1), + (148236, 1), + (148272, 1), + (1070556, 1), + (1079378, 1), + (1085421, 1), + (1086835, 1), + (1121118, 1), + (1121208, 1), + (1124515, 1), + (1128287, 1), + (1128379, 1), + (1153308, 1), + (1153342, 4), + (1153344, 5), + (1153398, 1), + (1153571, 1), + (1153663, 1), + (1153670, 1), + (1153672, 3), + (1153688, 3), + (1154504, 1), + (1154538, 5), + (1154540, 6), + (1154596, 1), + (1164963, 1), + (1165053, 1), + (1166494, 1), + (1166586, 1), + (1175528, 1), + (1175636, 1), + (1177016, 1), + (1193653, 1), + (1193743, 1), + (1205060, 1), + (1205152, 1), + (1323322, 1), + (1323414, 1), + (1336354, 1), + (1336444, 1), + (1348925, 1), + (1349015, 1), + (1353326, 1), + (1353418, 1), + (1426757, 1), + (1426845, 1), + (1426847, 1), + (1426937, 1), + (1476463, 1), + (1476553, 1), + (1516580, 1), + (1516670, 1), + (1605731, 1), + (1605821, 1), +]; \ No newline at end of file diff --git a/bin/node/bench/src/tempdb.rs b/bin/node/bench/src/tempdb.rs new file mode 100644 index 0000000000000000000000000000000000000000..770bafec6f38dc092ac3a905152e2c0861f54e5f --- /dev/null +++ b/bin/node/bench/src/tempdb.rs @@ -0,0 +1,137 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use std::{io, sync::Arc}; +use kvdb::{KeyValueDB, DBTransaction}; +use kvdb_rocksdb::{DatabaseConfig, Database}; + +#[derive(Debug, Clone, Copy, derive_more::Display)] +pub enum DatabaseType { + RocksDb, + ParityDb, +} + +pub struct TempDatabase(tempfile::TempDir); + +struct ParityDbWrapper(parity_db::Db); +parity_util_mem::malloc_size_of_is_0!(ParityDbWrapper); + +impl KeyValueDB for ParityDbWrapper { + /// Get a value by key. + fn get(&self, col: u32, key: &[u8]) -> io::Result>> { + Ok(self.0.get(col as u8, &key[key.len() - 32..]).expect("db error")) + } + + /// Get a value by partial key. Only works for flushed data. + fn get_by_prefix(&self, _col: u32, _prefix: &[u8]) -> Option> { + unimplemented!() + } + + /// Write a transaction of changes to the buffer. + fn write(&self, transaction: DBTransaction) -> io::Result<()> { + self.0.commit( + transaction.ops.iter().map(|op| match op { + kvdb::DBOp::Insert { col, key, value } => (*col as u8, &key[key.len() - 32..], Some(value.to_vec())), + kvdb::DBOp::Delete { col, key } => (*col as u8, &key[key.len() - 32..], None), + kvdb::DBOp::DeletePrefix { col: _, prefix: _ } => unimplemented!() + }) + ).expect("db error"); + Ok(()) + } + + /// Iterate over flushed data for a given column. + fn iter<'a>(&'a self, _col: u32) -> Box, Box<[u8]>)> + 'a> { + unimplemented!() + } + + /// Iterate over flushed data for a given column, starting from a given prefix. + fn iter_with_prefix<'a>( + &'a self, + _col: u32, + _prefix: &'a [u8], + ) -> Box, Box<[u8]>)> + 'a> { + unimplemented!() + } + + /// Attempt to replace this database with a new one located at the given path. + fn restore(&self, _new_db: &str) -> io::Result<()> { + unimplemented!() + } +} + +impl TempDatabase { + pub fn new() -> Self { + let dir = tempfile::tempdir().expect("temp dir creation failed"); + log::trace!( + target: "bench-logistics", + "Created temp db at {}", + dir.path().to_string_lossy(), + ); + + TempDatabase(dir) + } + + pub fn open(&mut self, db_type: DatabaseType) -> Arc { + match db_type { + DatabaseType::RocksDb => { + let db_cfg = DatabaseConfig::with_columns(1); + let db = Database::open(&db_cfg, &self.0.path().to_string_lossy()).expect("Database backend error"); + Arc::new(db) + }, + DatabaseType::ParityDb => { + Arc::new(ParityDbWrapper({ + let mut options = parity_db::Options::with_columns(self.0.path(), 1); + let mut column_options = &mut options.columns[0]; + column_options.ref_counted = true; + column_options.preimage = true; + column_options.uniform = true; + parity_db::Db::open(&options).expect("db open error") + })) + } + } + + } +} + +impl Clone for TempDatabase { + fn clone(&self) -> Self { + let new_dir = tempfile::tempdir().expect("temp dir creation failed"); + let self_dir = self.0.path(); + + log::trace!( + target: "bench-logistics", + "Cloning db ({}) to {}", + self_dir.to_string_lossy(), + new_dir.path().to_string_lossy(), + ); + let self_db_files = std::fs::read_dir(self_dir) + .expect("failed to list file in seed dir") + .map(|f_result| + f_result.expect("failed to read file in seed db") + .path() + .clone() + ).collect(); + fs_extra::copy_items( + &self_db_files, + new_dir.path(), + &fs_extra::dir::CopyOptions::new(), + ).expect("Copy of seed database is ok"); + + TempDatabase(new_dir) + } +} diff --git a/bin/node/bench/src/trie.rs b/bin/node/bench/src/trie.rs new file mode 100644 index 0000000000000000000000000000000000000000..886dc6011492f4564aa679f6f5f483025c057b58 --- /dev/null +++ b/bin/node/bench/src/trie.rs @@ -0,0 +1,377 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Trie benchmark (integrated). + +use std::{borrow::Cow, collections::HashMap, sync::Arc}; +use kvdb::KeyValueDB; +use lazy_static::lazy_static; +use rand::Rng; +use hash_db::Prefix; +use sp_state_machine::Backend as _; +use sp_trie::{trie_types::TrieDBMut, TrieMut as _}; + +use node_primitives::Hash; + +use crate::{ + core::{self, Mode, Path}, + generator::generate_trie, + simple_trie::SimpleTrie, + tempdb::{TempDatabase, DatabaseType}, +}; + +pub const SAMPLE_SIZE: usize = 100; +pub const TEST_WRITE_SIZE: usize = 128; + +pub type KeyValue = (Vec, Vec); +pub type KeyValues = Vec; + +#[derive(Clone, Copy, Debug, derive_more::Display)] +pub enum DatabaseSize { + #[display(fmt = "empty")] + Empty, + #[display(fmt = "smallest")] + Smallest, + #[display(fmt = "small")] + Small, + #[display(fmt = "medium")] + Medium, + #[display(fmt = "large")] + Large, + #[display(fmt = "huge")] + Huge, +} + +lazy_static! { + static ref KUSAMA_STATE_DISTRIBUTION: SizePool = + SizePool::from_histogram(crate::state_sizes::KUSAMA_STATE_DISTRIBUTION); +} + +impl DatabaseSize { + /// Should be multiple of SAMPLE_SIZE! + fn keys(&self) -> usize { + let val = match *self { + Self::Empty => 200, // still need some keys to query + Self::Smallest => 1_000, + Self::Small => 10_000, + Self::Medium => 100_000, + Self::Large => 200_000, + Self::Huge => 1_000_000, + }; + + assert_eq!(val % SAMPLE_SIZE, 0); + + val + } +} + +fn pretty_print(v: usize) -> String { + let mut print = String::new(); + for (idx, val) in v.to_string().chars().rev().enumerate() { + if idx != 0 && idx % 3 == 0 { + print.insert(0, ','); + } + print.insert(0, val); + } + print +} + +pub struct TrieReadBenchmarkDescription { + pub database_size: DatabaseSize, + pub database_type: DatabaseType, +} + +pub struct TrieReadBenchmark { + database: TempDatabase, + root: Hash, + warmup_keys: KeyValues, + query_keys: KeyValues, + database_type: DatabaseType, +} + +impl core::BenchmarkDescription for TrieReadBenchmarkDescription { + fn path(&self) -> Path { + let mut path = Path::new(&["trie", "read"]); + path.push(&format!("{}", self.database_size)); + path + } + + fn setup(self: Box) -> Box { + let mut database = TempDatabase::new(); + + let mut rng = rand::thread_rng(); + let warmup_prefix = KUSAMA_STATE_DISTRIBUTION.key(&mut rng); + + let mut key_values = KeyValues::new(); + let mut warmup_keys = KeyValues::new(); + let mut query_keys = KeyValues::new(); + let every_x_key = self.database_size.keys() / SAMPLE_SIZE; + for idx in 0..self.database_size.keys() { + let kv = ( + KUSAMA_STATE_DISTRIBUTION.key(&mut rng).to_vec(), + KUSAMA_STATE_DISTRIBUTION.value(&mut rng), + ); + if idx % every_x_key == 0 { + // warmup keys go to separate tree with high prob + let mut actual_warmup_key = warmup_prefix.clone(); + actual_warmup_key[16..].copy_from_slice(&kv.0[16..]); + warmup_keys.push((actual_warmup_key.clone(), kv.1.clone())); + key_values.push((actual_warmup_key.clone(), kv.1.clone())); + } else if idx % every_x_key == 1 { + query_keys.push(kv.clone()); + } + + key_values.push(kv) + } + + assert_eq!(warmup_keys.len(), SAMPLE_SIZE); + assert_eq!(query_keys.len(), SAMPLE_SIZE); + + let root = generate_trie( + database.open(self.database_type), + key_values, + ); + + Box::new(TrieReadBenchmark { + database, + root, + warmup_keys, + query_keys, + database_type: self.database_type, + }) + } + + fn name(&self) -> Cow<'static, str> { + format!( + "Trie read benchmark({} database ({} keys), db_type: {})", + self.database_size, + pretty_print(self.database_size.keys()), + self.database_type, + ).into() + } +} + +struct Storage(Arc); + +impl sp_state_machine::Storage for Storage { + fn get(&self, key: &Hash, prefix: Prefix) -> Result>, String> { + let key = sp_trie::prefixed_key::(key, prefix); + self.0.get(0, &key).map_err(|e| format!("Database backend error: {:?}", e)) + } +} + +impl core::Benchmark for TrieReadBenchmark { + fn run(&mut self, mode: Mode) -> std::time::Duration { + let mut db = self.database.clone(); + let storage: Arc> = + Arc::new(Storage(db.open(self.database_type))); + + let trie_backend = sp_state_machine::TrieBackend::new( + storage, + self.root, + ); + for (warmup_key, warmup_value) in self.warmup_keys.iter() { + let value = trie_backend.storage(&warmup_key[..]) + .expect("Failed to get key: db error") + .expect("Warmup key should exist"); + + // sanity for warmup keys + assert_eq!(&value, warmup_value); + } + + if mode == Mode::Profile { + std::thread::park_timeout(std::time::Duration::from_secs(3)); + } + + let started = std::time::Instant::now(); + for (key, _) in self.query_keys.iter() { + let _ = trie_backend.storage(&key[..]); + } + let elapsed = started.elapsed(); + + if mode == Mode::Profile { + std::thread::park_timeout(std::time::Duration::from_secs(1)); + } + + elapsed / (SAMPLE_SIZE as u32) + } +} + +pub struct TrieWriteBenchmarkDescription { + pub database_size: DatabaseSize, + pub database_type: DatabaseType, +} + + +impl core::BenchmarkDescription for TrieWriteBenchmarkDescription { + fn path(&self) -> Path { + let mut path = Path::new(&["trie", "write"]); + path.push(&format!("{}", self.database_size)); + path + } + + fn setup(self: Box) -> Box { + let mut database = TempDatabase::new(); + + let mut rng = rand::thread_rng(); + let warmup_prefix = KUSAMA_STATE_DISTRIBUTION.key(&mut rng); + + let mut key_values = KeyValues::new(); + let mut warmup_keys = KeyValues::new(); + let every_x_key = self.database_size.keys() / SAMPLE_SIZE; + for idx in 0..self.database_size.keys() { + let kv = ( + KUSAMA_STATE_DISTRIBUTION.key(&mut rng).to_vec(), + KUSAMA_STATE_DISTRIBUTION.value(&mut rng), + ); + if idx % every_x_key == 0 { + // warmup keys go to separate tree with high prob + let mut actual_warmup_key = warmup_prefix.clone(); + actual_warmup_key[16..].copy_from_slice(&kv.0[16..]); + warmup_keys.push((actual_warmup_key.clone(), kv.1.clone())); + key_values.push((actual_warmup_key.clone(), kv.1.clone())); + } + + key_values.push(kv) + } + + assert_eq!(warmup_keys.len(), SAMPLE_SIZE); + + let root = generate_trie( + database.open(self.database_type), + key_values, + ); + + Box::new(TrieWriteBenchmark { + database, + root, + warmup_keys, + database_type: self.database_type, + }) + } + + fn name(&self) -> Cow<'static, str> { + format!( + "Trie write benchmark({} database ({} keys), db_type = {})", + self.database_size, + pretty_print(self.database_size.keys()), + self.database_type, + ).into() + } +} + +struct TrieWriteBenchmark { + database: TempDatabase, + root: Hash, + warmup_keys: KeyValues, + database_type: DatabaseType, +} + +impl core::Benchmark for TrieWriteBenchmark { + fn run(&mut self, mode: Mode) -> std::time::Duration { + let mut rng = rand::thread_rng(); + let mut db = self.database.clone(); + let kvdb = db.open(self.database_type); + + let mut new_root = self.root.clone(); + + let mut overlay = HashMap::new(); + let mut trie = SimpleTrie { + db: kvdb.clone(), + overlay: &mut overlay, + }; + let mut trie_db_mut = TrieDBMut::from_existing(&mut trie, &mut new_root) + .expect("Failed to create TrieDBMut"); + + for (warmup_key, warmup_value) in self.warmup_keys.iter() { + let value = trie_db_mut.get(&warmup_key[..]) + .expect("Failed to get key: db error") + .expect("Warmup key should exist"); + + // sanity for warmup keys + assert_eq!(&value, warmup_value); + } + + let test_key = random_vec(&mut rng, 32); + let test_val = random_vec(&mut rng, TEST_WRITE_SIZE); + + if mode == Mode::Profile { + std::thread::park_timeout(std::time::Duration::from_secs(3)); + } + + let started = std::time::Instant::now(); + + trie_db_mut.insert(&test_key, &test_val).expect("Should be inserted ok"); + trie_db_mut.commit(); + drop(trie_db_mut); + + let mut transaction = kvdb.transaction(); + for (key, value) in overlay.into_iter() { + match value { + Some(value) => transaction.put(0, &key[..], &value[..]), + None => transaction.delete(0, &key[..]), + } + } + kvdb.write(transaction).expect("Failed to write transaction"); + + let elapsed = started.elapsed(); + + // sanity check + assert!(new_root != self.root); + + if mode == Mode::Profile { + std::thread::park_timeout(std::time::Duration::from_secs(1)); + } + + elapsed + } +} + +fn random_vec(rng: &mut R, len: usize) -> Vec { + let mut val = vec![0u8; len]; + rng.fill_bytes(&mut val[..]); + val +} + +struct SizePool { + distribution: std::collections::BTreeMap, + total: u32, +} + +impl SizePool { + fn from_histogram(h: &[(u32, u32)]) -> SizePool { + let mut distribution = std::collections::BTreeMap::default(); + let mut total = 0; + for (size, count) in h { + total += count; + distribution.insert(total, *size); + } + SizePool { distribution, total } + } + + fn value(&self, rng: &mut R) -> Vec { + let sr = (rng.next_u64() % self.total as u64) as u32; + let mut range = self.distribution.range((std::ops::Bound::Included(sr), std::ops::Bound::Unbounded)); + let size = *range.next().unwrap().1 as usize; + random_vec(rng, size) + } + + fn key(&self, rng: &mut R) -> Vec { + random_vec(rng, 32) + } +} diff --git a/bin/node/browser-testing/Cargo.toml b/bin/node/browser-testing/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..2e7ebe3be05f7cf99ceb0dcf0115c8bfcb751808 --- /dev/null +++ b/bin/node/browser-testing/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "node-browser-testing" +version = "2.0.0-rc4" +authors = ["Parity Technologies "] +description = "Tests for the in-browser light client." +edition = "2018" +license = "Apache-2.0" + +[dependencies] +futures-timer = "3.0.2" +libp2p = { version = "0.21.1", default-features = false } +jsonrpc-core = "14.2.0" +serde = "1.0.106" +serde_json = "1.0.48" +wasm-bindgen = { version = "=0.2.62", features = ["serde-serialize"] } +wasm-bindgen-futures = "0.4.10" +wasm-bindgen-test = "0.3.10" +futures = "0.3.4" + +node-cli = { path = "../cli", default-features = false, features = ["browser"] , version = "2.0.0-rc4"} +sc-rpc-api = { path = "../../../client/rpc-api" , version = "0.8.0-rc4"} diff --git a/bin/node/browser-testing/src/lib.rs b/bin/node/browser-testing/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..c943a383aefadf78fdf3af67458a0c488d55497b --- /dev/null +++ b/bin/node/browser-testing/src/lib.rs @@ -0,0 +1,70 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! # Running +//! Running this test can be done with +//! ```text +//! wasm-pack test --firefox --release --headless bin/node/browser-testing +//! ``` +//! or (without `wasm-pack`) +//! ```text +//! CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER=wasm-bindgen-test-runner WASM_BINDGEN_TEST_TIMEOUT=60 cargo test --target wasm32-unknown-unknown +//! ``` +//! For debug infomation, such as the informant, run without the `--headless` +//! flag and open a browser to the url that `wasm-pack test` outputs. +//! For more infomation see https://rustwasm.github.io/docs/wasm-pack/. + +use wasm_bindgen_test::{wasm_bindgen_test, wasm_bindgen_test_configure}; +use wasm_bindgen_futures::JsFuture; +use wasm_bindgen::JsValue; +use jsonrpc_core::types::{MethodCall, Success, Version, Params, Id}; +use serde::de::DeserializeOwned; + +wasm_bindgen_test_configure!(run_in_browser); + +fn rpc_call(method: &str) -> String { + serde_json::to_string(&MethodCall { + jsonrpc: Some(Version::V2), + method: method.into(), + params: Params::None, + id: Id::Num(1) + }).unwrap() +} + +fn deserialize_rpc_result(js_value: JsValue) -> T { + let string = js_value.as_string().unwrap(); + let value = serde_json::from_str::(&string).unwrap().result; + // We need to convert a `Value::Object` into a proper type. + let value_string = serde_json::to_string(&value).unwrap(); + serde_json::from_str(&value_string).unwrap() +} + +#[wasm_bindgen_test] +async fn runs() { + let mut client = node_cli::start_client(None, "info".into()) + .await + .unwrap(); + + // Check that the node handles rpc calls. + // TODO: Re-add the code that checks if the node is syncing. + let chain_name: String = deserialize_rpc_result( + JsFuture::from(client.rpc_send(&rpc_call("system_chain"))) + .await + .unwrap() + ); + assert_eq!(chain_name, "Development"); +} diff --git a/bin/node/browser-testing/webdriver.json b/bin/node/browser-testing/webdriver.json new file mode 100644 index 0000000000000000000000000000000000000000..417ac35a7bccd35a3c18135787c9c1506b48a21b --- /dev/null +++ b/bin/node/browser-testing/webdriver.json @@ -0,0 +1,7 @@ +{ + "goog:chromeOptions": { + "args": [ + "--whitelisted-ips=127.0.0.1" + ] + } +} diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index c477471166156e650c07cc5094774e2c7b22f824..6202c1af69e8d62ba82b4bb43b58b22e9698ea4c 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "node-cli" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] -description = "Substrate node implementation in Rust." +description = "Generic Substrate node implementation in Rust." build = "build.rs" edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" default-run = "substrate" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -15,6 +15,9 @@ repository = "https://github.com/paritytech/substrate/" # https://github.com/rustwasm/wasm-pack/issues/781 etc. wasm-opt = false +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [badges] travis-ci = { repository = "paritytech/substrate" } maintenance = { status = "actively-developed" } @@ -31,109 +34,108 @@ crate-type = ["cdylib", "rlib"] [dependencies] # third-party dependencies -codec = { package = "parity-scale-codec", version = "1.3.0" } +codec = { package = "parity-scale-codec", version = "1.3.1" } serde = { version = "1.0.102", features = ["derive"] } futures = { version = "0.3.1", features = ["compat"] } hex-literal = "0.2.1" -jsonrpc-core = "14.0.3" +jsonrpc-core = "14.2.0" log = "0.4.8" rand = "0.7.2" structopt = { version = "0.3.8", optional = true } tracing = "0.1.10" +parking_lot = "0.10.0" # primitives -sp-authority-discovery = { version = "2.0.0-alpha.5", path = "../../../primitives/authority-discovery" } -sp-consensus-babe = { version = "0.8.0-alpha.5", path = "../../../primitives/consensus/babe" } -grandpa-primitives = { version = "2.0.0-alpha.5", package = "sp-finality-grandpa", path = "../../../primitives/finality-grandpa" } -sp-core = { version = "2.0.0-alpha.5", path = "../../../primitives/core" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime" } -sp-timestamp = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/timestamp" } -sp-finality-tracker = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/finality-tracker" } -sp-inherents = { version = "2.0.0-alpha.5", path = "../../../primitives/inherents" } -sp-keyring = { version = "2.0.0-alpha.5", path = "../../../primitives/keyring" } -sp-io = { version = "2.0.0-alpha.5", path = "../../../primitives/io" } -sp-consensus = { version = "0.8.0-alpha.5", path = "../../../primitives/consensus/common" } +sp-authority-discovery = { version = "2.0.0-rc4", path = "../../../primitives/authority-discovery" } +sp-consensus-babe = { version = "0.8.0-rc4", path = "../../../primitives/consensus/babe" } +grandpa-primitives = { version = "2.0.0-rc4", package = "sp-finality-grandpa", path = "../../../primitives/finality-grandpa" } +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } +sp-runtime = { version = "2.0.0-rc4", path = "../../../primitives/runtime" } +sp-timestamp = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/timestamp" } +sp-finality-tracker = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/finality-tracker" } +sp-inherents = { version = "2.0.0-rc4", path = "../../../primitives/inherents" } +sp-keyring = { version = "2.0.0-rc4", path = "../../../primitives/keyring" } +sp-io = { version = "2.0.0-rc4", path = "../../../primitives/io" } +sp-consensus = { version = "0.8.0-rc4", path = "../../../primitives/consensus/common" } +sp-transaction-pool = { version = "2.0.0-rc4", path = "../../../primitives/transaction-pool" } # client dependencies -sc-client-api = { version = "2.0.0-alpha.5", path = "../../../client/api" } -sc-client = { version = "0.8.0-alpha.5", path = "../../../client/" } -sc-chain-spec = { version = "2.0.0-alpha.5", path = "../../../client/chain-spec" } -sc-transaction-pool = { version = "2.0.0-alpha.5", path = "../../../client/transaction-pool" } -sp-transaction-pool = { version = "2.0.0-alpha.5", path = "../../../primitives/transaction-pool" } -sc-network = { version = "0.8.0-alpha.5", path = "../../../client/network" } -sc-consensus-babe = { version = "0.8.0-alpha.5", path = "../../../client/consensus/babe" } -grandpa = { version = "0.8.0-alpha.5", package = "sc-finality-grandpa", path = "../../../client/finality-grandpa" } -sc-client-db = { version = "0.8.0-alpha.5", default-features = false, path = "../../../client/db" } -sc-offchain = { version = "2.0.0-alpha.5", path = "../../../client/offchain" } -sc-rpc = { version = "2.0.0-alpha.5", path = "../../../client/rpc" } -sc-basic-authorship = { version = "0.8.0-alpha.5", path = "../../../client/basic-authorship" } -sc-service = { version = "0.8.0-alpha.5", default-features = false, path = "../../../client/service" } -sc-tracing = { version = "2.0.0-alpha.5", path = "../../../client/tracing" } -sc-telemetry = { version = "2.0.0-alpha.5", path = "../../../client/telemetry" } -sc-authority-discovery = { version = "0.8.0-alpha.5", path = "../../../client/authority-discovery" } +sc-client-api = { version = "2.0.0-rc4", path = "../../../client/api" } +sc-chain-spec = { version = "2.0.0-rc4", path = "../../../client/chain-spec" } +sc-consensus = { version = "0.8.0-rc4", path = "../../../client/consensus/common" } +sc-transaction-pool = { version = "2.0.0-rc4", path = "../../../client/transaction-pool" } +sc-network = { version = "0.8.0-rc4", path = "../../../client/network" } +sc-consensus-babe = { version = "0.8.0-rc4", path = "../../../client/consensus/babe" } +grandpa = { version = "0.8.0-rc4", package = "sc-finality-grandpa", path = "../../../client/finality-grandpa" } +sc-client-db = { version = "0.8.0-rc4", default-features = false, path = "../../../client/db" } +sc-offchain = { version = "2.0.0-rc4", path = "../../../client/offchain" } +sc-rpc = { version = "2.0.0-rc4", path = "../../../client/rpc" } +sc-basic-authorship = { version = "0.8.0-rc4", path = "../../../client/basic-authorship" } +sc-service = { version = "0.8.0-rc4", default-features = false, path = "../../../client/service" } +sc-tracing = { version = "2.0.0-rc4", path = "../../../client/tracing" } +sc-telemetry = { version = "2.0.0-rc4", path = "../../../client/telemetry" } +sc-authority-discovery = { version = "0.8.0-rc4", path = "../../../client/authority-discovery" } # frame dependencies -pallet-indices = { version = "2.0.0-alpha.5", path = "../../../frame/indices" } -pallet-timestamp = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/timestamp" } -pallet-contracts = { version = "2.0.0-alpha.5", path = "../../../frame/contracts" } -frame-system = { version = "2.0.0-alpha.5", path = "../../../frame/system" } -pallet-balances = { version = "2.0.0-alpha.5", path = "../../../frame/balances" } -pallet-transaction-payment = { version = "2.0.0-alpha.5", path = "../../../frame/transaction-payment" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/support" } -pallet-im-online = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/im-online" } -pallet-authority-discovery = { version = "2.0.0-alpha.5", path = "../../../frame/authority-discovery" } -pallet-staking = { version = "2.0.0-alpha.5", path = "../../../frame/staking" } +pallet-indices = { version = "2.0.0-rc4", path = "../../../frame/indices" } +pallet-timestamp = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/timestamp" } +pallet-contracts = { version = "2.0.0-rc4", path = "../../../frame/contracts" } +frame-system = { version = "2.0.0-rc4", path = "../../../frame/system" } +pallet-balances = { version = "2.0.0-rc4", path = "../../../frame/balances" } +pallet-transaction-payment = { version = "2.0.0-rc4", path = "../../../frame/transaction-payment" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/support" } +pallet-im-online = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/im-online" } +pallet-authority-discovery = { version = "2.0.0-rc4", path = "../../../frame/authority-discovery" } +pallet-staking = { version = "2.0.0-rc4", path = "../../../frame/staking" } +pallet-grandpa = { version = "2.0.0-rc4", path = "../../../frame/grandpa" } # node-specific dependencies -node-runtime = { version = "2.0.0-alpha.5", path = "../runtime" } -node-rpc = { version = "2.0.0-alpha.5", path = "../rpc" } -node-primitives = { version = "2.0.0-alpha.5", path = "../primitives" } -node-executor = { version = "2.0.0-alpha.5", path = "../executor" } +node-runtime = { version = "2.0.0-rc4", path = "../runtime" } +node-rpc = { version = "2.0.0-rc4", path = "../rpc" } +node-primitives = { version = "2.0.0-rc4", path = "../primitives" } +node-executor = { version = "2.0.0-rc4", path = "../executor" } # CLI-specific dependencies -sc-cli = { version = "0.8.0-alpha.5", optional = true, path = "../../../client/cli" } -frame-benchmarking-cli = { version = "2.0.0-alpha.5", optional = true, path = "../../../utils/frame/benchmarking-cli" } -node-transaction-factory = { version = "0.8.0-alpha.5", optional = true, path = "../transaction-factory" } -node-inspect = { version = "0.8.0-alpha.5", optional = true, path = "../inspect" } +sc-cli = { version = "0.8.0-rc4", optional = true, path = "../../../client/cli" } +frame-benchmarking-cli = { version = "2.0.0-rc4", optional = true, path = "../../../utils/frame/benchmarking-cli" } +node-inspect = { version = "0.8.0-rc4", optional = true, path = "../inspect" } # WASM-specific dependencies wasm-bindgen = { version = "0.2.57", optional = true } wasm-bindgen-futures = { version = "0.4.7", optional = true } -browser-utils = { package = "substrate-browser-utils", path = "../../../utils/browser", optional = true, version = "0.8.0-alpha.5"} +browser-utils = { package = "substrate-browser-utils", path = "../../../utils/browser", optional = true, version = "0.8.0-rc4"} [target.'cfg(target_arch="x86_64")'.dependencies] -node-executor = { version = "2.0.0-alpha.4", path = "../executor", features = [ "wasmtime" ] } -sc-cli = { version = "0.8.0-alpha.4", optional = true, path = "../../../client/cli", features = [ "wasmtime" ] } -sc-service = { version = "0.8.0-alpha.4", default-features = false, path = "../../../client/service", features = [ "wasmtime" ] } +node-executor = { version = "2.0.0-rc4", path = "../executor", features = [ "wasmtime" ] } +sc-cli = { version = "0.8.0-rc4", optional = true, path = "../../../client/cli", features = [ "wasmtime" ] } +sc-service = { version = "0.8.0-rc4", default-features = false, path = "../../../client/service", features = [ "wasmtime" ] } [dev-dependencies] -sc-keystore = { version = "2.0.0-alpha.5", path = "../../../client/keystore" } -sc-consensus-babe = { version = "0.8.0-alpha.5", features = ["test-helpers"], path = "../../../client/consensus/babe" } -sc-consensus-epochs = { version = "0.8.0-alpha.5", path = "../../../client/consensus/epochs" } -sc-service-test = { version = "2.0.0-dev", path = "../../../client/service/test" } +sc-keystore = { version = "2.0.0-rc4", path = "../../../client/keystore" } +sc-consensus = { version = "0.8.0-rc4", path = "../../../client/consensus/common" } +sc-consensus-babe = { version = "0.8.0-rc4", features = ["test-helpers"], path = "../../../client/consensus/babe" } +sc-consensus-epochs = { version = "0.8.0-rc4", path = "../../../client/consensus/epochs" } +sc-service-test = { version = "2.0.0-rc4", path = "../../../client/service/test" } futures = "0.3.4" tempfile = "3.1.0" assert_cmd = "1.0" nix = "0.17" serde_json = "1.0" +regex = "1" +platforms = "0.2.1" [build-dependencies] -build-script-utils = { version = "2.0.0-alpha.5", package = "substrate-build-script-utils", path = "../../../utils/build-script-utils" } structopt = { version = "0.3.8", optional = true } -node-transaction-factory = { version = "0.8.0-alpha.5", optional = true, path = "../transaction-factory" } -node-inspect = { version = "0.8.0-alpha.5", optional = true, path = "../inspect" } -frame-benchmarking-cli = { version = "2.0.0-alpha.5", optional = true, path = "../../../utils/frame/benchmarking-cli" } +node-inspect = { version = "0.8.0-rc4", optional = true, path = "../inspect" } +frame-benchmarking-cli = { version = "2.0.0-rc4", optional = true, path = "../../../utils/frame/benchmarking-cli" } +substrate-build-script-utils = { version = "2.0.0-rc4", optional = true, path = "../../../utils/build-script-utils" } [build-dependencies.sc-cli] -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" package = "sc-cli" path = "../../../client/cli" optional = true -[build-dependencies.vergen] -version = "3.0.4" -optional = true - [features] default = [ "cli" ] browser = [ @@ -144,14 +146,13 @@ browser = [ cli = [ "node-executor/wasmi-errno", "node-inspect", - "node-transaction-factory", "sc-cli", "frame-benchmarking-cli", - "sc-service/rocksdb", + "sc-service/db", "structopt", - "vergen", + "substrate-build-script-utils", +] +runtime-benchmarks = [ + "node-runtime/runtime-benchmarks", + "frame-benchmarking-cli", ] -runtime-benchmarks = [ "node-runtime/runtime-benchmarks" ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/bin/node/cli/bin/main.rs b/bin/node/cli/bin/main.rs index 8c4412667baceec56904864413178cbc88001497..299b760c82e36b2b6540f6ae4efd8111cf430640 100644 --- a/bin/node/cli/bin/main.rs +++ b/bin/node/cli/bin/main.rs @@ -1,34 +1,25 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Substrate Node CLI #![warn(missing_docs)] fn main() -> sc_cli::Result<()> { - let version = sc_cli::VersionInfo { - name: "Substrate Node", - commit: env!("VERGEN_SHA_SHORT"), - version: env!("CARGO_PKG_VERSION"), - executable_name: "substrate", - author: "Parity Technologies ", - description: "Generic substrate node", - support_url: "https://github.com/paritytech/substrate/issues/new", - copyright_start_year: 2017, - }; - - node_cli::run(std::env::args(), version) + node_cli::run() } diff --git a/bin/node/cli/browser-demo/README.md b/bin/node/cli/browser-demo/README.md index 2ff1cc54f5dbe308a423c0bf90bccf49ecf4a1d0..08f1646f114a3104fa1cac14e83c03306860e7c9 100644 --- a/bin/node/cli/browser-demo/README.md +++ b/bin/node/cli/browser-demo/README.md @@ -1,9 +1,6 @@ # How to run this demo ```sh -cargo install wasm-pack # If necessary - -wasm-pack build --target web --out-dir ./browser-demo/pkg --no-typescript --release ./.. -- --no-default-features --features "browser" - -xdg-open index.html +cargo install wasm-bindgen-cli # If necessary +./build.sh ``` diff --git a/bin/node/cli/browser-demo/build.sh b/bin/node/cli/browser-demo/build.sh index 059ed9fe423b0ff030a1096b108b5d80efb3772d..be52b7a523f0177728181bfa18b8aef614185a26 100755 --- a/bin/node/cli/browser-demo/build.sh +++ b/bin/node/cli/browser-demo/build.sh @@ -1,3 +1,4 @@ #!/usr/bin/env sh -wasm-pack build --target web --out-dir ./browser-demo/pkg --no-typescript --release ./.. -- --no-default-features --features "browser" +cargo +nightly build --release -p node-cli --target wasm32-unknown-unknown --no-default-features --features browser -Z features=itarget +wasm-bindgen ../../../../target/wasm32-unknown-unknown/release/node_cli.wasm --out-dir pkg --target web python -m http.server 8000 diff --git a/bin/node/cli/build.rs b/bin/node/cli/build.rs index e824b59be64f3dedba3b738a6a3908b9e48b5091..a36f0d01a0a034a10686d3565e6abf538e6a5886 100644 --- a/bin/node/cli/build.rs +++ b/bin/node/cli/build.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . fn main() { #[cfg(feature = "cli")] @@ -24,14 +26,14 @@ mod cli { include!("src/cli.rs"); use std::{fs, env, path::Path}; - use sc_cli::{structopt::clap::Shell}; - use vergen::{ConstantsFlags, generate_cargo_keys}; + use sc_cli::structopt::clap::Shell; + use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed}; pub fn main() { build_shell_completion(); - generate_cargo_keys(ConstantsFlags::all()).expect("Failed to generate metadata files"); + generate_cargo_keys(); - build_script_utils::rerun_if_git_head_changed(); + rerun_if_git_head_changed(); } /// Build shell completion scripts for all known shells diff --git a/bin/node/cli/res/flaming-fir.json b/bin/node/cli/res/flaming-fir.json index 7ed98239b54b62c2a3c6309d96b13dedcdb1e65d..5f2eb265880efa1853e095486b3fe18d58fa233c 100644 --- a/bin/node/cli/res/flaming-fir.json +++ b/bin/node/cli/res/flaming-fir.json @@ -1,6 +1,7 @@ { "name": "Flaming Fir", - "id": "flamingfir6", + "id": "flamingfir7", + "chainType": "Live", "bootNodes": [ "/ip4/35.246.224.91/tcp/30333/p2p/QmaGKGpdm2iLiVCAnEcwrAhHxrcjMdGao4UubJxq7AF77n", "/ip4/35.246.224.91/tcp/30334/ws/p2p/QmaGKGpdm2iLiVCAnEcwrAhHxrcjMdGao4UubJxq7AF77n", @@ -13,128 +14,126 @@ ], "telemetryEndpoints": [ [ - "wss://telemetry.polkadot.io/submit/", + "/dns/telemetry.polkadot.io/tcp/443/x-parity-wss/%2Fsubmit%2F", 0 ] ], - "protocolId": "fir6", + "protocolId": "fir7", "properties": { "tokenDecimals": 15, "tokenSymbol": "FIR" }, "forkBlocks": null, - "badBlocks": [ - "0xf3b02820f81988282e1da41fd479ef2aa00d63d622863639ea15d48ab6533fdc" - ], + "badBlocks": null, "consensusEngine": null, "genesis": { "raw": { "top": { - "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da97f325c981c2b001f5fe8c51cc7b89e50ebb1f60feb7ab3fa3bc79d6ab71d45cb": "0x00000000030000c16ff28623000000000000000000000000000000000000000000000000000000c16ff286230000000000000000000000c16ff28623000000000000000000", - "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc47132bdc08fa57aeff963126d33d186054c4211cc8e3b7a46ed61365bcde8c5f5": "0x68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde780f0000c16ff286230f0000c16ff286230000", - "0x3a6772616e6470615f617574686f726974696573": "0x01103919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef01000000000000005633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce44001000000000000007932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f01000000000000009becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe96993320100000000000000", - "0x426e15054d267946093858132eb537f1ba7fb8745735dc3be2a2c61a72c39e78": "0x049ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809", - "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc413c312ec9dee1781c5bd27a5a5ba5b9718f39358b381bcd6783393fd2bee2090": "0xf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c26630f0000c16ff286230f0000c16ff286230000", - "0x5f3e4907f716ac89b6347d15ececedca42982b9d6c7acc99faa9094c912372c2b4def25cfda6ef3a000000007441588f5c9a91b3f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663": "0x0ff6ffc06ff286230ff6ffc06ff2862300", - "0x426e15054d267946093858132eb537f105fe52c2045750c3c492ccdcf62e2b9c": "0x9ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809", + "0x5f3e4907f716ac89b6347d15ececedca138e71612491192d68deab7e6f563fe1": "0x08000000", + "0x2b06af9719ac64d755623cda8ddd9b949f99a2ce711f3a31b2fc05604c93f179": "0x106e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f910600299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e", + "0x426e15054d267946093858132eb537f195999521c6c89cd80b677e53ce20f98c": "0x9ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809", + "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc40a81aa5d99517e5635e7865ccd909c4066bc1e5d275da50b72b15de072a2468a5ad414919ca9054d2695767cf650012f": "0xf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c26630f0000c16ff286230f0000c16ff286230000", "0x5f3e4907f716ac89b6347d15ececedca682db92dde20a10d96d00ff0e9e221c0b4def25cfda6ef3a00000000c90f9b6dd26886b468655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78": "0x00", - "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade987f325c981c2b001f5fe8c51cc7b89e50ebb1f60feb7ab3fa3bc79d6ab71d45cb": "0x00", - "0x26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac": "0x01000000", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b6579730a299be621974fd19374a88f1dddd8442b21db25d2c923907dda6af815b657fe": "0xf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", - "0x426e15054d267946093858132eb537f1a47a9ff5cd5bf4d848a80a0b1a947dc3": "0x00000000000000000000000000000000", + "0x5f3e4907f716ac89b6347d15ececedcaf7dad0317324aecae8744b87fc95f2f3": "0x00", + "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb354352b71083d945a9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12": "0x9becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe96993326e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f91066e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f91066e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106", + "0xcec5070d609dd3497f72bde07fc96ba0e0cdd062e6eaf24295ad4ccfc41d4609": "0x109c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d129becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe96993326e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f91066e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f91066e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c26633919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f437800299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f437800299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d655633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde787932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e", + "0xf2794c22e353e9a839f12faab03a911b7f17cdfbfa73331856cca0acddd7842e": "0x00000000", + "0xf2794c22e353e9a839f12faab03a911bbdcb0c5143a8617ed38ae3810dd45bc6": "0x00000000", + "0x426e15054d267946093858132eb537f105fe52c2045750c3c492ccdcf62e2b9c": "0x9ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809", "0xc2261276cc9d1f8598ea4b6a74b15c2f308ce9615de0775a82f8a94dc3d285a1": "0x01", - "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e16903e54094c2d5af8ae10b91e1288f4f59f2946d7738f2c509b7effd909e5e9ba0ad": "0x0001f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c26630168655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78", - "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade98711590f60a214f6f06502eb29dd14f55aa04e72e2fa12c098ba4fa5a00c57fa9": "0x00", - "0x5f3e4907f716ac89b6347d15ececedca682db92dde20a10d96d00ff0e9e221c0b4def25cfda6ef3a0000000054352b71083d945a9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12": "0x00", - "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e16903711590f60a214f6f06502eb29dd14f55aa04e72e2fa12c098ba4fa5a00c57fa9": "0x0001547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65019c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", - "0x26aa394eea5630e07c48ae0c9558cef78a42f33323cb5ced3b44dd825fda9fcc": "0x4545454545454545454545454545454545454545454545454545454545454545", - "0x34b9dcaacddd89d5a94929dccb713153d2d505c0e6f76fd7ce0796ebe187401c": "0x0000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000008700000000000000af00000000000000010000000000000001000000000000006400000000000000040000000000010010000000004000000020000000", - "0x2b06af9719ac64d755623cda8ddd9b949f99a2ce711f3a31b2fc05604c93f179": "0x1000299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e6e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106", - "0x26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7": "0x1c000000000000039ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e31809734747180900000000000000039c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12000000000000000368655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde780000000000000003547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d650000000000000003f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c266300000000000000036d6f646c70792f7472737279000000000000000000000000000000000000000000000000000003006d6f646c70792f7472737279000000000000000000000000000000000000000000407a10f35a0000000000000000000000", - "0x3a65787472696e7369635f696e646578": "0x00000000", - "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe70e54094c2d5af8ae10b91e1288f4f59f2946d7738f2c509b7effd909e5e9ba0ad": "0x9e42241d7cd91d001773b0b616d523dd80e13c6c2cab860b1234ef1b9ffc1526", - "0x426e15054d267946093858132eb537f1d0b4a3f7631f0c0e761898fe198211de": "0xe7030000", - "0x5f3e4907f716ac89b6347d15ececedca6a93112633bb3354e67952fcdd740cd5": "0xf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", - "0x5f3e4907f716ac89b6347d15ececedca42982b9d6c7acc99faa9094c912372c2b4def25cfda6ef3a0000000079091c57296b2634547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65": "0x0ff6ffc06ff286230ff6ffc06ff2862300", - "0x5f3e4907f716ac89b6347d15ececedca8bde0a0ea8864605e3b68ed9cb2da01bb4def25cfda6ef3a00000000c90f9b6dd26886b468655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78": "0x0ff6ffc06ff286230ff6ffc06ff2862300", - "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb39fe6329cc0b39e09343a73657373696f6e3a6b65797394f72a73893fbd00b11fcce65a014cc5b9ff5066ec15aa6be068b4cabfe67fdb": "0x3919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f437800299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f437800299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378", - "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da994f72a73893fbd00b11fcce65a014cc5b9ff5066ec15aa6be068b4cabfe67fdb": "0x00000000030000c16ff28623000000000000000000000000000000000000000000000000000000c16ff286230000000000000000000000c16ff28623000000000000000000", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b6579730cd914acf7b89329ae59e8f7e3b8f1ee7a4f5f68d4749cca82814f2f5b1d6bbb": "0x9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b65797346c8960f8387b17441ee2be48a0896e48d3580e922c6e1cd8f53a621370c1e49": "0x68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b65797365ab35e7816bae0042175c49c0d6da885e26780d56ff9c7f04727e757dddc666": "0x547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65", - "0xcec5070d609dd3497f72bde07fc96ba0e0cdd062e6eaf24295ad4ccfc41d4609": "0x10f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c26633919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f437800299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f437800299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d655633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde787932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d129becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe96993326e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f91066e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f91066e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106", - "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe707f325c981c2b001f5fe8c51cc7b89e50ebb1f60feb7ab3fa3bc79d6ab71d45cb": "0x781ead1e2fa9ccb74b44c19d29cb2a7a4b5be3972927ae98cd3877523976a276", - "0x3a636f6465": "0x0061736d0100000001a6033a60037f7f7f017f60027f7f017f60027f7f0060037f7f7f0060047f7f7f7f0060017f0060057f7f7f7f7f0060017f017e60037f7e7e0060017e017f60017e017e60027e7e0060017e0060047f7e7e7f017f60067f7e7e7f7f7f017f60057e7e7f7e7e0060047e7e7f7e017e60047e7e7f7e0060037f7e7f017f60027f7e017e60047f7e7e7e017f6000017e60037e7e7f0060047f7f7f7f017f6000017f60027f7e017f60017f017f60037e7e7f017e60037f7f7e017e60027f7f017e60000060037e7f7f017f60067f7f7f7f7f7f017f60057f7f7f7f7f017f60027f7e0060067f7f7f7f7f7f0060077f7e7e7e7e7e7e0060057f7f7e7e7f0060067f7f7f7e7e7f0060047f7f7f7f017e60077f7f7f7e7e7e7f0060037f7f7e0060077f7f7f7e7e7f7f0060077f7f7f7f7e7e7f0060047f7f7e7e0060077f7f7e7e7f7f7f0060057f7e7e7f7f0060057f7f7f7e7e0060077f7f7f7f7f7f7f0060067f7e7e7f7f7f0060027e7f0060067f7f7f7f7e7e0060087e7e7e7e7e7e7e7e017f60087f7f7f7f7f7e7e7f0060037f7e7f0060047f7e7e7f0060057f7e7e7e7e0060067f7e7e7e7e7f0002b00e2e03656e76066d656d6f727902001303656e76196578745f6c6f6767696e675f6c6f675f76657273696f6e5f31000803656e761e6578745f68617368696e675f74776f785f3132385f76657273696f6e5f31000903656e76196578745f73746f726167655f6765745f76657273696f6e5f31000a03656e76206578745f68617368696e675f626c616b65325f3235365f76657273696f6e5f31000903656e76196578745f73746f726167655f7365745f76657273696f6e5f31000b03656e761b6578745f73746f726167655f636c6561725f76657273696f6e5f31000c03656e761d6578745f68617368696e675f74776f785f36345f76657273696f6e5f31000903656e76206578745f68617368696e675f626c616b65325f3132385f76657273696f6e5f31000903656e761d6578745f6d6973635f7072696e745f757466385f76657273696f6e5f31000c03656e76206578745f73616e64626f785f6d656d6f72795f6e65775f76657273696f6e5f31000103656e76256578745f73616e64626f785f6d656d6f72795f74656172646f776e5f76657273696f6e5f31000503656e76216578745f73616e64626f785f696e7374616e74696174655f76657273696f6e5f31000d03656e761c6578745f73616e64626f785f696e766f6b655f76657273696f6e5f31000e03656e76276578745f73616e64626f785f696e7374616e63655f74656172646f776e5f76657273696f6e5f31000503656e76206578745f73746f726167655f6368696c645f726f6f745f76657273696f6e5f31000a03656e761f6578745f73746f726167655f6368696c645f7365745f76657273696f6e5f31000f03656e761f6578745f73746f726167655f6368696c645f6765745f76657273696f6e5f31001003656e76216578745f73746f726167655f6368696c645f636c6561725f76657273696f6e5f31001103656e76226578745f6d6973635f72756e74696d655f76657273696f6e5f76657273696f6e5f31000a03656e76226578745f73746f726167655f636c6561725f7072656669785f76657273696f6e5f31000c03656e76236578745f63727970746f5f737232353531395f7665726966795f76657273696f6e5f31001203656e76286578745f6f6666636861696e5f6c6f63616c5f73746f726167655f6765745f76657273696f6e5f31001303656e76346578745f6f6666636861696e5f6c6f63616c5f73746f726167655f636f6d706172655f616e645f7365745f76657273696f6e5f31001403656e76286578745f6f6666636861696e5f6c6f63616c5f73746f726167655f7365745f76657273696f6e5f31000803656e761e6578745f73746f726167655f6e6578745f6b65795f76657273696f6e5f31000a03656e761c6578745f6d6973635f7072696e745f6e756d5f76657273696f6e5f31000c03656e76236578745f63727970746f5f656432353531395f7665726966795f76657273696f6e5f31001203656e761a6578745f73746f726167655f726f6f745f76657273696f6e5f31001503656e76226578745f73746f726167655f6368616e6765735f726f6f745f76657273696f6e5f31000a03656e76286578745f73746f726167655f6368696c645f73746f726167655f6b696c6c5f76657273696f6e5f31001603656e76206578745f73616e64626f785f6d656d6f72795f6765745f76657273696f6e5f31001703656e76206578745f73616e64626f785f6d656d6f72795f7365745f76657273696f6e5f31001703656e761c6578745f6d6973635f7072696e745f6865785f76657273696f6e5f31000c03656e76236578745f6f6666636861696e5f69735f76616c696461746f725f76657273696f6e5f31001803656e76256578745f63727970746f5f656432353531395f67656e65726174655f76657273696f6e5f31001903656e76256578745f63727970746f5f737232353531395f67656e65726174655f76657273696f6e5f31001903656e762a6578745f747269655f626c616b65325f3235365f6f7264657265645f726f6f745f76657273696f6e5f31000903656e76296578745f6f6666636861696e5f7375626d69745f7472616e73616374696f6e5f76657273696f6e5f31000a03656e76246578745f6f6666636861696e5f6e6574776f726b5f73746174655f76657273696f6e5f31001503656e761e6578745f616c6c6f6361746f725f6d616c6c6f635f76657273696f6e5f31001a03656e761c6578745f616c6c6f6361746f725f667265655f76657273696f6e5f31000503656e761a6578745f73746f726167655f726561645f76657273696f6e5f31001b03656e76286578745f63727970746f5f737232353531395f7075626c69635f6b6579735f76657273696f6e5f31000703656e76216578745f63727970746f5f737232353531395f7369676e5f76657273696f6e5f31001c03656e76376578745f63727970746f5f736563703235366b315f65636473615f7265636f7665725f636f6d707265737365645f76657273696f6e5f31001d03c606c4061a1a050500001a1a1d1e1e1e030203001e060001010102011f0507201702020004010101020101010301010100042101010001010000010005030102020203020001010102202201020504230505050505020202030303020302020203030303050503020203030303040505050b08032405050505050205020202020203030203020125020302022302050202030226040b231e04040404040404040404040404040404040404040404040404040427020505011e0202030402020202020205030102050502020202020502020202020202020202022829022a02242b050303022c0405020303040202010404030203032d06040505030202040202020302060302051a030202020802050205020205020202020202030403060202020503010202020501020505050505050505050505050505050505050505050502020202020202020226020203021a0502020505050203030202030203030304050403050203030203050505050502020202020202020205020201020506010102000101011e02020202062e0202032f05020203020204020302020202030303020302301e06050402020131020205050505020202020104020201040202010517030505020202011a0202050202020203051e15020205021a32020602030505030505050202020202050202030202030202030303050505021a030203030505050205030203012c03030201051e02030505020505050202020202050505020202020102020202020102010402030305050203001a0202031a0205020525020205050205010201330202020317060302020305050202020305050205020505050502050506030301030202243401060402020202020302020202350205030103050505050502020202051a0202050205050505050202020202030502040204051d021d021d1d1d1d1d021d031d1d031d021d1d1d1d1d1d1d1d1d1d1d050303050502020205050203030302051e050202030202020202020502020202022c050502050202050501030306033602020203020106020203030505050206020201030204010301010202010101010101010102030103020201030103030302010103010503031a01020208010106010104030403040301060603030501010101000000003737383838390407017001950295020619037f01418080c0000b7f0041b4e2ca000b7f0041b4e2ca000b07e8051a195f5f696e6469726563745f66756e6374696f6e5f7461626c65010009686173685f7465737400350c436f72655f76657273696f6e00c90512436f72655f657865637574655f626c6f636b00cb0515436f72655f696e697469616c697a655f626c6f636b00cd05114d657461646174615f6d6574616461746100ce051c426c6f636b4275696c6465725f6170706c795f65787472696e73696300cf051b426c6f636b4275696c6465725f66696e616c697a655f626c6f636b00d00520426c6f636b4275696c6465725f696e686572656e745f65787472696e7369637300d1051c426c6f636b4275696c6465725f636865636b5f696e686572656e747300d30518426c6f636b4275696c6465725f72616e646f6d5f7365656400d5052b5461676765645472616e73616374696f6e51756575655f76616c69646174655f7472616e73616374696f6e00d605214f6666636861696e576f726b65724170695f6f6666636861696e5f776f726b657200d8051e4772616e6470614170695f6772616e6470615f617574686f72697469657300da0515426162654170695f636f6e66696775726174696f6e00db051b426162654170695f63757272656e745f65706f63685f737461727400dc0521417574686f72697479446973636f766572794170695f617574686f72697469657300dd051d4163636f756e744e6f6e63654170695f6163636f756e745f6e6f6e636500de0511436f6e7472616374734170695f63616c6c00df0518436f6e7472616374734170695f6765745f73746f7261676500e0051c436f6e7472616374734170695f72656e745f70726f6a656374696f6e00e105205472616e73616374696f6e5061796d656e744170695f71756572795f696e666f00e2052153657373696f6e4b6579735f67656e65726174655f73657373696f6e5f6b65797300e3051f53657373696f6e4b6579735f6465636f64655f73657373696f6e5f6b65797300e4050a5f5f646174615f656e6403010b5f5f686561705f626173650302098b04010041010b94024442564ed3064f505763d102af01c101c201c301c401c501c601c701c801c901ca01cb01cc01cd01ce01cf01d001d101d201d301d401d501d601d701d801d901da01db01dc01cb04cc02ef04ed04f003a703a803ac03ab06ad06ae069a0658c906ab03dd06b306e506c106bb06e5053f40416747595c5d5e5f606d6e6f70717674758f069004fd047e9901d506d206bf02a301bb02d606e001f501f301f201820281028002ff01fe01fd01fc01fb01fa01f901f801f8058d04ba02c002be02bd028c048b04d402ec04a7047a79d502980188068a067c7b7daa05a905b2058e068d06d60282058105d70284058c0587058805f605f405d802800687069f049e04d902a004a804b902b702da02bc02d302bc05ba05db02c805bb05ac05ab05dc02ad05b605d904d804dd02d903da03ec03fc04fb04de028b05c504c404df02c604e904f101f001e002f701a102ba04b904e102e504d803d703e202eb038605e3028905a201a101e402df01bd04bc04e502be04ea04b905b805e602c3059f019e01e702a001de01ad03dc03db03b40691048f048e04a104bb04fa05b105c204c104c004bf04ae05ca04c904c804c704f904f804fa04fe0483058d058e058f059005910587025354a505f604a605f704a705a805a405b005af05ff05fe05fd05fc05fb05f7058206810689068c068b06b806b206b706b506b606e306bf06c706e206e606e4060a83f75ec40606002000102e0b0600200010270b0600200010300b0600200010280b0a0020002001200210320b2801017f0240200210272203450d002003200020022001200120024b1b10e8061a200010280b20030b0600200010340b1c01017f0240200010272201450d0020014100200010e7061a0b20010bff0202017f037e230041206b220224002001ad42adfed5e4d485fda8d8007e42b9e0007c210302400240024002400240200141084b0d00200141014b0d0120010d02420021040c030b0240200141104b0d00200241106a2000290000200385420042adfed5e4d485fda8d800420010ed06200241186a29030020022903107c200120006a41786a2900008521040c040b200120006a41786a2900002105200321040340200029000020048542adfed5e4d485fda8d8007e42178942adfed5e4d485fda8d8007e2003852103200041086a2100200442cf829ebbefefde82147c2104200141786a220141084b0d000b200320058521040c030b0240200141034b0d00200120006a417e6a33000042108620003300008420038521040c030b200120006a417c6a35000042208620003500008420038521040c020b200031000021040b200420038521040b20022004420042adfed5e4d485fda8d800420010ed06200241086a290300210420022903002103200241206a2400200420037c42c300850b05001037000b24004100419ccaca00ad4280808080f0008441a3caca00ad4280808080a00484100000000b1100418080c0004111419480c0001039000b4701017f230041206b22032400200341146a4100360200200341c8e1ca00360210200342013702042003200136021c200320003602182003200341186a360200200320021043000b8b0301067f230041306b2202240020012802002103024002402001280204220441037422050d00410021060c010b200341046a2107410021060340200728020020066a2106200741086a2107200541786a22050d000b0b024002400240024002400240200141146a2802000d00200621070c010b024020040d0041bc80c00041004100103b000b024002402006410f4b0d00200341046a280200450d010b200620066a220720064f0d010b4101210541002107200241086a21060c010b2007417f4c0d01200241086a2106024020070d0041012105410021070c010b2007102d2205450d020b200241003602102002200736020c200220053602082002200241086a360214200241186a41106a200141106a290200370300200241186a41086a200141086a29020037030020022001290200370318200241146a41cc80c000200241186a103c0d0220002006290200370200200041086a200641086a280200360200200241306a24000f0b103d000b1036000b41e480c0004133200241186a419881c00041a881c000103e000b6c01017f230041306b2203240020032002360204200320013602002003411c6a41023602002003412c6a41013602002003420237020c2003419484c000360208200341013602242003200341206a360218200320033602282003200341046a360220200341086a20001043000bba06010a7f230041306b22032400200341246a2001360200200341033a002820034280808080800437030820032000360220410021042003410036021820034100360210024002400240024020022802082205450d0020022802002106200228020422072002410c6a2802002208200820074b1b2209450d01200241146a280200210a2002280210210b41012108200020062802002006280204200128020c1100000d03200541106a2102200641086a2100410121040240024003402003200241746a28020036020c20032002410c6a2d00003a00282003200241786a280200360208200241086a28020021084100210541002101024002400240200241046a2802000e03010002010b2008200a4f0d032008410374210c41002101200b200c6a220c2802044102470d01200c28020028020021080b410121010b2003200836021420032001360210200228020021080240024002402002417c6a2802000e03010002010b2008200a4f0d0420084103742101200b20016a22012802044102470d01200128020028020021080b410121050b2003200836021c200320053602180240200241706a2802002208200a4f0d00200b20084103746a2208280200200341086a20082802041101000d06200420094f0d05200041046a210120002802002105200241206a2102200041086a210041012108200441016a2104200328022020052001280200200328022428020c110000450d010c070b0b41948ac0002008200a103b000b41848ac0002008200a103b000b41848ac0002008200a103b000b2002280200210620022802042207200241146a2802002208200820074b1b220a450d002002280210210241012108200020062802002006280204200128020c1100000d02200641086a21004101210403402002280200200341086a200241046a2802001101000d022004200a4f0d01200041046a210120002802002105200241086a2102200041086a210041012108200441016a2104200328022020052001280200200328022428020c110000450d000c030b0b0240200720044d0d00410121082003280220200620044103746a22022802002002280204200328022428020c1100000d020b410021080c010b410121080b200341306a240020080b05001038000b7e01017f230041c0006b220524002005200136020c2005200036020820052003360214200520023602102005412c6a41023602002005413c6a41033602002005420237021c200541fca3c000360218200541043602342005200541306a3602282005200541106a3602382005200541086a360230200541186a20041043000bbc0101037f02400240024002402000280200220041046a2802002203200041086a28020022046b2002490d00200028020021030c010b200420026a22052004490d02200341017422042005200420054b1b22044100480d020240024020030d002004102d21030c010b200028020020032004103121030b2003450d0120002003360200200041046a2004360200200041086a28020021040b200041086a200420026a360200200320046a2001200210e8061a41000f0b1036000b1038000bc00401057f230041106b22022400200028020021000240024002400240024002402001418001490d002002410036020c2001418010490d012002410c6a210302402001418080044f0d0020022001413f71418001723a000e20022001410676413f71418001723a000d20022001410c76410f7141e001723a000c410321010c030b20022001413f71418001723a000f2002200141127641f001723a000c20022001410676413f71418001723a000e20022001410c76413f71418001723a000d410421010c020b0240024020002802082204200041046a280200460d00200028020021050c010b200441016a22052004490d05200441017422032005200320054b1b22034100480d050240024020040d002003102d21050c010b200028020020042003103121050b2005450d0420002005360200200041046a2003360200200028020821040b200520046a20013a00002000200028020841016a3602080c020b20022001413f71418001723a000d20022001410676411f7141c001723a000c2002410c6a2103410221010b02400240200041046a2802002205200041086a28020022046b2001490d00200028020021050c010b200420016a22062004490d03200541017422042006200420064b1b22044100480d030240024020050d002004102d21050c010b200028020020052004103121050b2005450d0220002005360200200041046a2004360200200041086a28020021040b200041086a200420016a360200200520046a2003200110e8061a0b200241106a240041000f0b1036000b1038000b6301017f230041206b2202240020022000280200360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a41cc80c000200241086a103c2101200241206a240020010b0300000b3401017f230041106b220224002002200136020c20022000360208200241a484c000360204200241c8e1ca0036020020021046000b0d0020003502004101200110450bd40203027f017e037f230041306b22032400412721040240024020004290ce005a0d00200021050c010b412721040340200341096a20046a2206417c6a200020004290ce0080220542f0b17f7e7ca7220741ffff037141e4006e220841017441e684c0006a2f00003b00002006417e6a2008419c7f6c20076a41ffff037141017441e684c0006a2f00003b00002004417c6a2104200042ffc1d72f5621062005210020060d000b0b02402005a7220641e3004c0d00200341096a2004417e6a22046a2005a7220741ffff037141e4006e2206419c7f6c20076a41ffff037141017441e684c0006a2f00003b00000b024002402006410a480d00200341096a2004417e6a22046a200641017441e684c0006a2f00003b00000c010b200341096a2004417f6a22046a200641306a3a00000b2002200141c8e1ca004100200341096a20046a412720046b10482104200341306a240020040b6f01017f230041c0006b220124002001200036020c200141346a4101360200200142013702242001419cdfca003602202001410536023c2001200141386a36023020012001410c6a360238200141106a200141206a103a4101419ccaca0041072001280210200128021810d40600000b0c004285f6f0e7a1e8c2a06a0b830601067f024002402001450d00412b418080c4002000280200220641017122011b2107200120056a21080c010b200541016a210820002802002106412d21070b0240024020064104710d00410021020c010b4100210902402003450d002003210a200221010340200920012d000041c00171418001466a2109200141016a2101200a417f6a220a0d000b0b200820036a20096b21080b410121010240024020002802084101460d00200020072002200310490d012000280218200420052000411c6a28020028020c11000021010c010b02402000410c6a280200220920084b0d00200020072002200310490d012000280218200420052000411c6a28020028020c1100000f0b0240024020064108710d0041002101200920086b22092108024002400240410120002d0020220a200a4103461b0e0402010001020b20094101762101200941016a41017621080c010b41002108200921010b200141016a210103402001417f6a2201450d0220002802182000280204200028021c280210110100450d000b41010f0b200028020421062000413036020420002d0020210b41012101200041013a0020200020072002200310490d0141002101200920086b220a2103024002400240410120002d0020220920094103461b0e0402010001020b200a4101762101200a41016a41017621030c010b41002103200a21010b200141016a2101024003402001417f6a2201450d0120002802182000280204200028021c280210110100450d000b41010f0b2000280204210a41012101200028021820042005200028021c28020c1100000d01200341016a2109200028021c210320002802182102024003402009417f6a2209450d01410121012002200a20032802101101000d030c000b0b2000200b3a00202000200636020441000f0b2000280204210a41012101200020072002200310490d00200028021820042005200028021c28020c1100000d00200841016a2109200028021c210320002802182100034002402009417f6a22090d0041000f0b410121012000200a2003280210110100450d000b0b20010b5401017f024002402001418080c400460d0041012104200028021820012000411c6a2802002802101101000d010b024020020d0041000f0b2000280218200220032000411c6a28020028020c11000021040b20040b6f01017f230041306b2202240020022001360204200220003602002002411c6a41023602002002412c6a41013602002002420237020c200241b086c000360208200241013602242002200241206a3602182002200241046a36022820022002360220200241086a41c086c0001043000b6f01017f230041306b2202240020022001360204200220003602002002411c6a41023602002002412c6a41013602002002420237020c2002419087c000360208200241013602242002200241206a3602182002200241046a36022820022002360220200241086a41a087c0001043000b9307010c7f200041106a28020021030240024002400240200041086a28020022044101460d0020034101460d012000280218200120022000411c6a28020028020c11000021030c030b20034101470d010b0240024020020d00410021020c010b200120026a2105200041146a28020041016a21064100210720012103200121080340200341016a210902400240024020032c0000220a417f4a0d000240024020092005470d004100210b200521030c010b20032d0001413f71210b200341026a220921030b200a411f71210c0240200a41ff0171220a41df014b0d00200b200c41067472210a0c020b0240024020032005470d004100210d2005210e0c010b20032d0000413f71210d200341016a2209210e0b200d200b41067472210b0240200a41f0014f0d00200b200c410c7472210a0c020b02400240200e2005470d004100210a200921030c010b200e41016a2103200e2d0000413f71210a0b200b410674200c411274418080f0007172200a72220a418080c400470d020c040b200a41ff0171210a0b200921030b02402006417f6a2206450d00200720086b20036a21072003210820052003470d010c020b0b200a418080c400460d00024002402007450d0020072002460d0041002103200720024f0d01200120076a2c00004140480d010b200121030b2007200220031b21022003200120031b21010b20044101460d002000280218200120022000411c6a28020028020c1100000f0b4100210902402002450d002002210a200121030340200920032d000041c00171418001466a2109200341016a2103200a417f6a220a0d000b0b0240200220096b200028020c2206490d002000280218200120022000411c6a28020028020c1100000f0b410021074100210902402002450d00410021092002210a200121030340200920032d000041c00171418001466a2109200341016a2103200a417f6a220a0d000b0b200920026b20066a2209210a024002400240410020002d0020220320034103461b0e0402010001020b20094101762107200941016a410176210a0c010b4100210a200921070b200741016a2103024003402003417f6a2203450d0120002802182000280204200028021c280210110100450d000b41010f0b2000280204210941012103200028021820012002200028021c28020c1100000d00200a41016a2103200028021c210a20002802182100034002402003417f6a22030d0041000f0b20002009200a280210110100450d000b41010f0b20030bd40801067f230041f0006b220424002004200336020c20042002360208410121052001210602402001418102490d00410020016b2107418002210803400240200820014f0d00200020086a2c000041bf7f4c0d0041002105200821060c020b2008417f6a21064100210520084101460d01200720086a21092006210820094101470d000b0b200420063602142004200036021020044100410520051b36021c200441c8e1ca0041d387c00020051b3602180240024002400240200220014b22080d00200320014b0d00200220034b0d01024002402002450d0020012002460d00200120024d0d01200020026a2c00004140480d010b200321020b200420023602202002450d0220022001460d02200141016a210903400240200220014f0d00200020026a2c000041404e0d040b2002417f6a210820024101460d0420092002462106200821022006450d000c040b0b20042002200320081b360228200441306a41146a4103360200200441c8006a41146a4104360200200441d4006a410436020020044203370234200441d887c0003602302004410136024c2004200441c8006a3602402004200441186a3602582004200441106a3602502004200441286a360248200441306a41f087c0001043000b200441e4006a4104360200200441c8006a41146a4104360200200441d4006a4101360200200441306a41146a4104360200200442043702342004418088c0003602302004410136024c2004200441c8006a3602402004200441186a3602602004200441106a36025820042004410c6a3602502004200441086a360248200441306a41a088c0001043000b200221080b024020082001460d00410121060240024002400240200020086a22092c00002202417f4a0d0041002105200020016a220621010240200941016a2006460d00200941026a210120092d0001413f7121050b2002411f712109200241ff017141df014b0d01200520094106747221010c020b2004200241ff0171360224200441286a21020c020b4100210020062107024020012006460d00200141016a210720012d0000413f7121000b200020054106747221010240200241ff017141f0014f0d0020012009410c747221010c010b41002102024020072006460d0020072d0000413f7121020b20014106742009411274418080f00071722002722201418080c400460d020b2004200136022441012106200441286a21022001418001490d00410221062001418010490d0041034104200141808004491b21060b200420083602282004200620086a36022c200441306a41146a4105360200200441ec006a4104360200200441e4006a4104360200200441c8006a41146a4106360200200441d4006a410736020020044205370234200441ec88c000360230200420023602582004410136024c2004200441c8006a3602402004200441186a3602682004200441106a3602602004200441246a3602502004200441206a360248200441306a419489c0001043000b41b088c000412b41dc88c0001039000b1000200120002802002000280204104c0b800101037f230041206b22022400024002402000280200200110520d002001411c6a2802002103200128021821042002411c6a4100360200200241c8e1ca003602182002420137020c200241fc89c00036020820042003200241086a103c450d010b200241206a240041010f0b2000280204200110522101200241206a240020010bff0301067f230041106b22022400410121030240200128021841272001411c6a2802002802101101000d002002200028020010512002410c6a2d00002104200241086a28020021052002280200210002400240024020022802042206418080c400460d000c010b03402000210341dc002107410121000240024020030e0404040100040b200441ff017121034104210441032100024002400240024020030e06070302010004070b4103210041f5002107410321040c030b4102210441fb0021070c020b4102410120051b2104418080c4002005410274411c7176410f7141307221072005417f6a410020051b21050c010b4100210441fd0021070b4101210320012802182007200128021c280210110100450d000c030b0b03402000210341dc00210741012100024002400240024020030e0405010300050b200441ff01712103410421044103210002400240024020030e06070201000405070b4102210441fb0021070c040b20062005410274411c7176410f712203413072200341d7006a2003410a491b21074102410120051b21042005417f6a410020051b21050c030b4100210441fd0021070c020b41002100200621070c010b4103210041f5002107410321040b4101210320012802182007200128021c2802101101000d020c000b0b20012802184127200128021c28021011010021030b200241106a240020030bab0903047f017e037f4102210202400240024002400240200141776a2203411e4d0d00200141dc00470d010c020b41f40021040240024020030e1f05010202000202020202020202020202020202020202020202030202020203050b41f20021040c040b41ee0021040c030b2001410a7621040240024002400240024002400240024002400240024002400240024002400240024020014180d807490d00411e21022004418007460d0120014180fe037141087621050c050b200441be8ac0006a2d00002202411e4b0d010b20024104742001410676410f717241b98bc0006a2d00002204418b014f0d0141032102200441037441d08fc0006a29030042012001413f71ad8683500d02200141017267410276410773ad4280808080d0008421060c100b41ac8fc0002002411f103b000b41bc8fc0002004418b01103b000b20014180fe03712104200141808004490d01200441087621050b200141808008490d0120014190fc476a4190fc0b490d0a200141e28b746a41e28d2c490d0a2001419fa8746a419f18490d0a200141dee2746a410e490d0a200141feffff0071419ef00a460d0a200141a9b2756a4129490d0a200141cb91756a410a4d0d0a410121020c0c0b2004410876210541c298c000210241002103200141ff017121070340200241026a2108200320022d000122046a2109024020022d000022022005460d00200220054b0d0820092103200821022008419499c000470d010c080b20092003490d02200941a5024b0d032003419499c0006a2102024003402004450d012004417f6a210420022d00002103200241016a210220032007470d000c0c0b0b20092103200821022008419499c000470d000c070b0b41849ec000210241002103200141ff017121070340200241026a2108200320022d000122046a2109024020022d000022022005460d00200220054b0d062009210320082102200841ca9ec000470d010c060b20092003490d03200941a6014b0d04200341ca9ec0006a2102024003402004450d012004417f6a210420022d00002103200241016a210220032007470d000c0b0b0b2009210320082102200841ca9ec000470d000c050b0b20032009104b000b200941a502104a000b20032009104b000b200941a601104a000b200141ffff0371210741f09fc00021044101210302400340200441016a21090240024020042d0000220241187441187522084100480d00200921040c010b20094188a3c000460d02200841ff007141087420042d0001722102200441026a21040b200720026b22074100480d032003410173210320044188a3c000470d000c030b0b41b088c000412b41f49dc0001039000b200141ffff0371210741b99bc0002104410121030340200441016a21090240024020042d0000220241187441187522084100480d00200921040c010b200941f39dc000460d03200841ff007141087420042d0001722102200441026a21040b200720026b22074100480d0120034101732103200441f39dc000470d000b0b4101210220034101710d020c010b41b088c000412b41f49dc0001039000b200141017267410276410773ad4280808080d000842106410321020c010b0b200121040b2000200436020420002002360200200041086a20063702000ba10201037f23004180016b2202240002400240024002400240200128020022034110710d0020034120710d012000ad41012001104521000c020b410021030340200220036a41ff006a2000410f712204413072200441d7006a2004410a491b3a00002003417f6a2103200041047622000d000b20034180016a22004181014f0d022001410141bc8ac0004102200220036a4180016a410020036b104821000c010b410021030340200220036a41ff006a2000410f712204413072200441376a2004410a491b3a00002003417f6a2103200041047622000d000b20034180016a22004181014f0d022001410141bc8ac0004102200220036a4180016a410020036b104821000b20024180016a240020000f0b2000418001104b000b2000418001104b000b1c00200128021841e0a3c000410b2001411c6a28020028020c1100000b1c00200128021841eba3c000410e2001411c6a28020028020c1100000b5b01017f230041306b220324002003200136020c20032000360208200341246a4101360200200342013702142003419cdfca003602102003410436022c2003200341286a3602202003200341086a360228200341106a20021043000b140020002802002001200028020428020c1101000b6901037f230041206b220224002001411c6a280200210320012802182104200241086a41106a2000280200220141106a290200370300200241086a41086a200141086a2902003703002002200129020037030820042003200241086a103c2101200241206a240020010b15002001200028020022002802002000280204104c0ba20401077f230041306b220324000240024020020d00410021040c010b200341286a210502400240024002400340024020002802082d0000450d00200028020041cea4c0004104200028020428020c1100000d050b2003410a3602282003428a808080103703202003200236021c200341003602182003200236021420032001360210200341086a410a20012002105a024002400240024020032802084101470d00200328020c210403402003200420032802186a41016a2204360218024002402004200328022422064f0d00200328021421070c010b200328021422072004490d00200641054f0d072003280210200420066b22086a22092005460d0420092005200610ea06450d040b200328021c22092004490d0220072009490d0220032006200341106a6a41176a2d0000200328021020046a200920046b105a2003280204210420032802004101460d000b0b2003200328021c3602180b200028020841003a0000200221040c010b200028020841013a0000200841016a21040b2000280204210920002802002106024020044520022004467222070d00200220044d0d03200120046a2c000041bf7f4c0d030b200620012004200928020c1100000d04024020070d00200220044d0d04200120046a2c000041bf7f4c0d040b200120046a2101200220046b22020d000b410021040c040b20064104104a000b2001200241002004104d000b2001200220042002104d000b410121040b200341306a240020040bf30201067f410021040240024020024103712205450d00410420056b2205450d0020032005200520034b1b210441002105200141ff01712106034020042005460d01200220056a2107200541016a210520072d000022072006470d000b410121032007200141ff01714641016a41017120056a417f6a21050c010b200141ff017121060240024020034108490d002004200341786a22084b0d00200641818284086c210502400340200220046a220741046a2802002005732209417f73200941fffdfb776a7120072802002005732207417f73200741fffdfb776a7172418081828478710d01200441086a220420084d0d000b0b200420034b0d010b200220046a2109200320046b210241002103410021050240034020022005460d01200920056a2107200541016a210520072d000022072006470d000b410121032007200141ff01714641016a41017120056a417f6a21050b200520046a21050c010b20042003104b000b20002005360204200020033602000bbb0302047f027e230041c0006b2205240041012106024020002d00040d0020002d000521070240200028020022082d00004104710d0041012106200828021841d5a4c00041d2a4c000200741ff017122071b4102410320071b2008411c6a28020028020c1100000d014101210620002802002208280218200120022008411c6a28020028020c1100000d01410121062000280200220828021841b9c3c80041022008411c6a28020028020c1100000d0120032000280200200428020c11010021060c010b0240200741ff01710d0041012106200828021841d7a4c00041032008411c6a28020028020c1100000d01200028020021080b41012106200541013a0017200541346a41dca4c000360200200520082902183703082005200541176a360210200829020821092008290210210a200520082d00203a00382005200a37032820052009370320200520082902003703182005200541086a360230200541086a2001200210590d00200541086a41b9c3c800410210590d002003200541186a200428020c1101000d00200528023041f4a4c0004102200528023428020c11000021060b200041013a0005200020063a0004200541c0006a240020000b8b0201027f230041106b220224002002410036020c02400240024002402001418001490d002001418010490d012002410c6a21032001418080044f0d0220022001413f71418001723a000e20022001410676413f71418001723a000d20022001410c76410f7141e001723a000c410321010c030b200220013a000c2002410c6a2103410121010c020b20022001413f71418001723a000d20022001410676411f7141c001723a000c2002410c6a2103410221010c010b20022001413f71418001723a000f2002200141127641f001723a000c20022001410676413f71418001723a000e20022001410c76413f71418001723a000d410421010b20002003200110592101200241106a240020010b6001017f230041206b2202240020022000360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a41f8a4c000200241086a103c2101200241206a240020010b0d0020002802002001200210590b0b0020002802002001105c0b6301017f230041206b2202240020022000280200360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a41f8a4c000200241086a103c2101200241206a240020010bd30202047f027e230041c0006b2203240041012104024020002d00080d00200028020421050240200028020022062d00004104710d0041012104200628021841d5a4c0004193a5c00020051b4102410120051b2006411c6a28020028020c1100000d0120012000280200200228020c11010021040c010b024020050d004101210420062802184194a5c00041022006411c6a28020028020c1100000d01200028020021060b41012104200341013a0017200341346a41dca4c000360200200320062902183703082003200341176a3602102006290208210720062902102108200320062d00203a00382003200837032820032007370320200320062902003703182003200341086a3602302001200341186a200228020c1101000d00200328023041f4a4c0004102200328023428020c11000021040b200020043a00082000200028020441016a360204200341c0006a240020000bd40202037f027e230041c0006b2203240041012104024020002d00040d0020002d000521040240200028020022052d00004104710d000240200441ff0171450d0041012104200528021841d5a4c00041022005411c6a28020028020c1100000d02200028020021050b20012005200228020c11010021040c010b0240200441ff01710d004101210420052802184197a5c00041012005411c6a28020028020c1100000d01200028020021050b41012104200341013a0017200341346a41dca4c000360200200320052902183703082003200341176a3602102005290208210620052902102107200320052d00203a00382003200737032820032006370320200320052902003703182003200341086a3602302001200341186a200228020c1101000d00200328023041f4a4c0004102200328023428020c11000021040b200041013a0005200020043a0004200341c0006a240020000b6401027f230041206b220224002001411c6a280200210320012802182101200241086a41106a200041106a290200370300200241086a41086a200041086a2902003703002002200029020037030820012003200241086a103c2100200241206a240020000b8709010d7f230041306b220324004101210402400240200228021841222002411c6a2802002802101101000d000240024020010d00410021050c010b200020016a210620002107410021054100210802400240034020072109200741016a210a02400240024020072c0000220b417f4a0d0002400240200a2006470d004100210c200621070c010b20072d0001413f71210c200741026a220a21070b200b411f71210d0240200b41ff0171220b41df014b0d00200c200d41067472210b0c020b0240024020072006470d004100210e2006210f0c010b20072d0000413f71210e200741016a220a210f0b200e200c41067472210c0240200b41f0014f0d00200c200d410c7472210b0c020b02400240200f2006470d004100210b200a21070c010b200f41016a2107200f2d0000413f71210b0b200c410674200d411274418080f0007172200b72220b418080c400470d020c050b200b41ff0171210b0b200a21070b2003200b105102400240024002402003280200220a0e0401020100010b200328020820032d000c6a4101460d010b2003200136021420032000360210200320053602182003200836021c20082005490d0302402005450d0020052001460d00200520014f0d04200020056a2c000041bf7f4c0d040b02402008450d0020082001460d00200820014f0d04200020086a2c000041bf7f4c0d040b2002280218200020056a200820056b200228021c28020c1100000d0120032d000c210d2003280208210f024002402003280204220e418080c400470d000340200a21054101210a41dc00210c0240024020050e0404040100040b200d41ff017121054103210a4104210d024002400240024020050e06070302010004070b4103210d41f500210c4103210a0c030b4102210d41fb00210c0c020b41024101200f1b210d418080c400200f410274411c7176410f71413072210c200f417f6a4100200f1b210f0c010b4100210d41fd00210c0b2002280218200c200228021c280210110100450d000c040b0b0340200a210c4101210a41dc0021050240024002400240200c0e0405010300050b200d41ff0171210c4103210a4104210d024002400240200c0e06070201000405070b4102210d41fb0021050c040b200e200f410274411c7176410f712205413072200541d7006a2005410a491b210541024101200f1b210d200f417f6a4100200f1b210f0c030b4100210d41fd0021050c020b4100210a200e21050c010b4103210d41f50021054103210a0b20022802182005200228021c2802101101000d030c000b0b410121050240200b418001490d0041022105200b418010490d0041034104200b41808004491b21050b200520086a21050b200820096b20076a210820062007470d010c030b0b410121040c030b20032003411c6a3602282003200341186a3602242003200341106a360220200341206a1065000b2005450d0020052001460d00200520014f0d02200020056a2c000041bf7f4c0d020b2002280218200020056a200120056b200228021c28020c1100000d0020022802184122200228021c28021011010021040b200341306a240020040f0b2000200120052001104d000b2601017f20002802002201280200200128020420002802042802002000280208280200104d000bee0704057f017e017f017e02400240024002402002450d00410020016b410020014103711b2103200241796a4100200241074b1b210441002105034002400240200120056a2d000022064118744118752207417f4a0d0042808080808020210802402006419182c0006a2d0000417e6a220941024d0d00428080808010210a0c070b0240024002400240024020090e03000102000b200541016a22062002490d024200210a0c090b4200210a200541016a220920024f0d08200120096a2d0000210902400240200641a07e6a2206410d4b0d000240024020060e0e0002020202020202020202020201000b200941e0017141a001460d02428080808010210a0c0c0b02402009411874411875417f4c0d00428080808010210a0c0c0b200941ff017141a001490d01428080808010210a0c0b0b02402007411f6a41ff0171410b4b0d0002402009411874411875417f4c0d00428080808010210a0c0c0b200941ff017141c001490d01428080808010210a0c0b0b0240200941ff017141bf014d0d00428080808010210a0c0b0b0240200741fe017141ee01460d00428080808010210a0c0b0b2009411874411875417f4c0d00428080808010210a0c0a0b42002108200541026a220620024f0d09200120066a2d000041c00171418001460d020c070b4200210a200541016a220920024f0d07200120096a2d0000210902400240200641907e6a220641044b0d000240024020060e050002020201000b200941f0006a41ff01714130490d02428080808010210a0c0b0b02402009411874411875417f4c0d00428080808010210a0c0b0b200941ff0171419001490d01428080808010210a0c0a0b0240200941ff017141bf014d0d00428080808010210a0c0a0b02402007410f6a41ff017141024d0d00428080808010210a0c0a0b2009411874411875417f4c0d00428080808010210a0c090b200541026a220620024f0d07200120066a2d000041c00171418001470d0642002108200541036a220620024f0d08200120066a2d000041c00171418001460d01428080808080e0002108428080808010210a0c080b428080808010210a200120066a2d000041c00171418001470d070b200641016a21050c010b0240200320056b4103710d000240200520044f0d000340200120056a220641046a280200200628020072418081828478710d01200541086a22052004490d000b0b200520024f0d010340200120056a2c00004100480d022002200541016a2205470d000c040b0b200541016a21050b20052002490d000b0b20002001360204200041086a2002360200200041003602000f0b428080808080c0002108428080808010210a0c010b420021080b2000200a2005ad84200884370204200041013602000b1c00200128021841a4dfca0041052001411c6a28020028020c1100000bf20301087f20002802042102024002400240024020002802004101470d002000410c6a28020022002001106920004103742200450d01200220006a2103200141086a2104034020022802002105200241046a28020022002001106902400240200141046a22062802002207200428020022086b2000490d00200128020021070c010b200820006a22092008490d05200741017422082009200820094b1b22084100480d050240024020070d002008102d21070c010b200128020020072008103121070b2007450d042001200736020020062008360200200428020021080b2004200820006a360200200720086a2005200010e8061a200241086a22022003470d000c020b0b200041086a28020022002001106920004103742200450d00200220006a2103200141086a2104034020022802002105200241046a28020022002001106902400240200141046a22062802002207200428020022086b2000490d00200128020021070c010b200820006a22092008490d04200741017422082009200820094b1b22084100480d040240024020070d002008102d21070c010b200128020020072008103121070b2007450d032001200736020020062008360200200428020021080b2004200820006a360200200720086a2005200010e8061a200241086a22022003470d000b0b0f0b1036000b1038000be20601037f02400240024002400240200041c000490d00200041808001490d012000418080808004490d0202400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d05200241017422042003200420034b1b22044100480d050240024020020d002004102d21030c010b200128020020022004103121030b2003450d0420012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41033a000002400240200141046a2802002203200428020022026b4104490d00200128020021030c010b200241046a22042002490d05200341017422022004200220044b1b22024100480d050240024020030d002002102d21030c010b200128020020032002103121030b2003450d0420012003360200200141046a2002360200200141086a28020021020b200141086a200241046a360200200320026a20003600000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d04200241017422042003200420034b1b22044100480d040240024020020d002004102d21030c010b200128020020022004103121030b2003450d0320012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a20004102743a00000f0b02400240200141046a2802002203200141086a28020022026b4102490d00200128020021030c010b200241026a22042002490d03200341017422022004200220044b1b22024100480d030240024020030d002002102d21030c010b200128020020032002103121030b2003450d0220012003360200200141046a2002360200200141086a28020021020b200141086a200241026a360200200320026a20004102744101723b00000f0b02400240200141046a2802002203200141086a28020022026b4104490d00200128020021030c010b200241046a22042002490d02200341017422022004200220044b1b22024100480d020240024020030d002002102d21030c010b200128020020032002103121030b2003450d0120012003360200200141046a2002360200200141086a28020021020b200141086a200241046a360200200320026a20004102744102723600000f0b1036000b1038000bdc0601087f20002802042102024002400240024020002802004101470d002000410c6a2802002200200110692000450d01200041186c2103200241146a2100200141086a2102200141046a21040340200041706a2802002105200041746a2802002206200110690240024020042802002207200228020022086b2006490d00200128020021070c010b200820066a22092008490d05200741017422082009200820094b1b22084100480d050240024020070d002008102d21070c010b200128020020072008103121070b2007450d042001200736020020042008360200200228020021080b2002200820066a360200200720086a2005200610e8061a2000417c6a280200210520002802002206200110690240024020042802002207200228020022086b2006490d00200128020021070c010b200820066a22092008490d05200741017422082009200820094b1b22084100480d050240024020070d002008102d21070c010b200128020020072008103121070b2007450d042001200736020020042008360200200228020021080b2002200820066a360200200720086a2005200610e8061a200041186a2100200341686a22030d000c020b0b200041086a2802002200200110692000450d00200041186c2103200241146a2100200141086a2102200141046a21040340200041706a2802002105200041746a2802002206200110690240024020042802002207200228020022086b2006490d00200128020021070c010b200820066a22092008490d04200741017422082009200820094b1b22084100480d040240024020070d002008102d21070c010b200128020020072008103121070b2007450d032001200736020020042008360200200228020021080b2002200820066a360200200720086a2005200610e8061a2000417c6a280200210520002802002206200110690240024020042802002207200228020022086b2006490d00200128020021070c010b200820066a22092008490d04200741017422082009200820094b1b22084100480d040240024020070d002008102d21070c010b200128020020072008103121070b2007450d032001200736020020042008360200200228020021080b2002200820066a360200200720086a2005200610e8061a200041186a2100200341686a22030d000b0b0f0b1036000b1038000bbb18010a7f230041106b220324002001200210690240024002402001450d00200141d8006c2104410021050340200020056a220641046a2802002107200641086a28020022082002106902400240200241046a2209280200220a200241086a2201280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d04200a410174220b200c200b200c4b1b220b4100480d0402400240200a0d00200b102d210a0c010b2002280200200a200b1031210a0b200a450d032002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a2007200810e8061a200641d4006a2d0000210a02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d0420084101742207200b2007200b4b1b22074100480d040240024020080d002007102d210b0c010b2002280200200820071031210b0b200b450d032002200b36020020092007360200200128020021080b2001200841016a360200200b20086a200a3a000002402006410c6a2d0000220841024b0d0002400240024020080e03000102000b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d072008410174220a200b200a200b4b1b220a4100480d070240024020080d00200a102d210b0c010b20022802002008200a1031210b0b200b450d062002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41003a0000200641146a2802002107200641186a280200220820021069024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d07200a410174220b200c200b200c4b1b220b4100480d0702400240200a0d00200b102d210a0c010b2002280200200a200b1031210a0b200a450d062002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a2007200810e8061a0c020b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d062008410174220a200b200a200b4b1b220a4100480d060240024020080d00200a102d210b0c010b20022802002008200a1031210b0b200b450d052002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41013a000002402006410d6a2d0000220841054b0d004100210a02400240024002400240024020080e06050001020304050b4101210a0c040b4102210a0c030b4103210a0c020b4104210a0c010b4105210a0b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d0720084101742207200b2007200b4b1b22074100480d070240024020080d002007102d210b0c010b2002280200200820071031210b0b200b450d062002200b36020020092007360200200128020021080b2001200841016a360200200b20086a200a3a00000b200641146a2802002107200641186a280200220820021069024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d06200a410174220b200c200b200c4b1b220b4100480d0602400240200a0d00200b102d210a0c010b2002280200200a200b1031210a0b200a450d052002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a2007200810e8061a200641206a2802002107200641246a280200220820021069024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d06200a410174220b200c200b200c4b1b220b4100480d0602400240200a0d00200b102d210a0c010b2002280200200a200b1031210a0b200a450d052002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a2007200810e8061a2006410e6a2d0000210a02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d0620084101742207200b2007200b4b1b22074100480d060240024020080d002007102d210b0c010b2002280200200820071031210b0b200b450d052002200b36020020092007360200200128020021080b2001200841016a360200200b20086a200a3a00000c010b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d052008410174220a200b200a200b4b1b220a4100480d050240024020080d00200a102d210b0c010b20022802002008200a1031210b0b200b450d042002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41023a000002402006410d6a2d0000220841054b0d004100210a02400240024002400240024020080e06050001020304050b4101210a0c040b4102210a0c030b4103210a0c020b4104210a0c010b4105210a0b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d0620084101742207200b2007200b4b1b22074100480d060240024020080d002007102d210b0c010b2002280200200820071031210b0b200b450d052002200b36020020092007360200200128020021080b2001200841016a360200200b20086a200a3a00000b200641146a2802002107200641186a280200220820021069024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d05200a410174220b200c200b200c4b1b220b4100480d0502400240200a0d00200b102d210a0c010b2002280200200a200b1031210a0b200a450d042002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a2007200810e8061a200641206a2802002107200641246a280200220820021069024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d05200a410174220b200c200b200c4b1b220b4100480d0502400240200a0d00200b102d210a0c010b2002280200200a200b1031210a0b200a450d042002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a2007200810e8061a2006412c6a2802002107200641306a280200220820021069024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d05200a410174220b200c200b200c4b1b220b4100480d0502400240200a0d00200b102d210a0c010b2002280200200a200b1031210a0b200a450d042002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a2007200810e8061a2006410e6a2d0000220841054b0d004100210a02400240024002400240024020080e06050001020304050b4101210a0c040b4102210a0c030b4103210a0c020b4104210a0c010b4105210a0b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d0520084101742207200b2007200b4b1b22074100480d050240024020080d002007102d210b0c010b2002280200200820071031210b0b200b450d042002200b36020020092007360200200128020021080b2001200841016a360200200b20086a200a3a00000b02400240200641346a2802004101470d00200641386a2802002107200641c0006a280200220820021069024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d06200a410174220b200c200b200c4b1b220b4100480d0602400240200a0d00200b102d210a0c010b2002280200200a200b1031210a0b200a450d052002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a2007200810e8061a0c010b2003200641386a2802002006413c6a28020028020c110200200328020021072003280208220820021069024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d05200a410174220b200c200b200c4b1b220b4100480d0502400240200a0d00200b102d210a0c010b2002280200200a200b1031210a0b200a450d042002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a2007200810e8061a2003280204450d002007102f0b200641c4006a200210682004200541d8006a2205470d000b0b200341106a24000f0b1036000b1038000bd205010b7f2001410c6a28020021022001280208210320012802042104200128020021050240024002400240024002400240024020012d001022060e03010002010b200420056b21070c020b200420056b2201200220036b6a220720014f0d010240024020052004460d00200541016a2108410021060c010b024020032002470d004101210941002104410021070c070b410221062003210120052108200341016a2103200121050b41002101410021074101210903402001410174210a200420086b210b034020052d00002105024020012007470d00200b2107024002400240200641ff01710e03010200010b200220036b21070c010b417f200b200220036b6a22072007200b491b21070b2001417f200741016a220c200c2007491b6a22072001490d06200a2007200a20074b1b22074100480d060240024020010d002007102d21090c010b200920012007103121090b2009450d050b200920016a20053a0000024002400240024002400240200641ff01710e03010300010b20022003460d010c040b024020082004460d00410021060c030b20022003470d030b200141016a21040c0a0b4101210620082004470d00200141016a21040c090b200141016a210120082105200841016a21080c020b200141016a210141022106200a41026a210a2003220541016a21030c000b0b0b200220036b21070b4101210902402007450d0020074100480d022007102d2209450d010b0240200641014d0d0041002104200921010c030b0240024020052004470d0041002104200921010c010b200921012005210a03402001200a2d00003a0000200141016a21012004200a41016a220a470d000b200420056b21040b200641024b0d0320060e03020302020b1036000b1038000b20032002460d002003210a03402001200a2d00003a0000200141016a21012002200a41016a220a470d000b2002200420036b6a21040b2000200436020820002007360204200020093602000bbc0101037f02400240024002402000280200220041046a2802002203200041086a28020022046b2002490d00200028020021030c010b200420026a22052004490d02200341017422042005200420054b1b22044100480d020240024020030d002004102d21030c010b200028020020032004103121030b2003450d0120002003360200200041046a2004360200200041086a28020021040b200041086a200420026a360200200320046a2001200210e8061a41000f0b1036000b1038000ba70301047f230041106b22022400200028020021002002410036020c02400240024002402001418001490d002001418010490d012001418080044f0d0220022001413f71418001723a000e20022001410676413f71418001723a000d20022001410c76410f7141e001723a000c410321010c030b200220013a000c410121010c020b20022001413f71418001723a000d20022001410676411f7141c001723a000c410221010c010b20022001413f71418001723a000f2002200141127641f001723a000c20022001410676413f71418001723a000e20022001410c76413f71418001723a000d410421010b0240024002400240200041046a2802002203200041086a28020022046b2001490d00200028020021030c010b200420016a22052004490d02200341017422042005200420054b1b22044100480d020240024020030d002004102d21030c010b200028020020032004103121030b2003450d0120002003360200200041046a2004360200200041086a28020021040b200041086a200420016a360200200320046a2002410c6a200110e8061a200241106a240041000f0b1036000b1038000b6301017f230041206b2202240020022000280200360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a419ca5c000200241086a103c2101200241206a240020010b040041010bb60101017f230041c0006b2202240020024100360210200242013703082002410836021c20022001410c6a3602202002200241206a3602182002200241086a3602242002413c6a41013602002002420137022c2002419cdfca003602282002200241186a360238200241246a419ca5c000200241286a103c1a20012d0000417f6a41ff0171200141046a290200200235021042208620023502088410000240200228020c450d002002280208102f0b200241c0006a24000bba0202037f017e230041106b2206240002400240024002400240200541206a2207417f4c0d002007450d01200710332208450d022007410f4d0d032001ad4220862000ad84100122012900002109200641086a2200200141086a290000370300200620093703002001102f200841086a2000290300370000200820062903003700002007411f4d0d042003ad4220862002ad841001220129000021092000200141086a290000370300200620093703002001102f200841186a200029030037000020082006290300370010200841206a2004200510e8061a20062007ad4220862008ad841002107302400240200628020022000d00410021070c010b410121072006280204450d002000102f0b2008102f200641106a240020070f0b103d000b41104100104a000b1036000b41102007104a000b41202007104a000baa0201067f230041206b22022400024002402001422088a722030d00410121040c010b2001a721040b200220033602142002200436021002402003450d0020042d0000210520022003417f6a3602142002200441016a360210200541014b0d0041002103024002400240024020050e020100010b200241086a200241106a10e60120022802080d0320022802142206200228020c2205490d032005417f4c0d010240024020050d00410121030c010b200510332203450d03200320022802102207200510e8061a2002200620056b3602142002200720056a3602100b2003450d032005ad220142208620018421010b20002001370204200020033602002004102f200241206a24000f0b103d000b1036000b41f4c8ca00412e200241186a418ccaca0041a4c9ca00103e000b040041000b02000b02000ba209010f7f23004190036b22042400024002400240200141046a28020022052f01062206410b490d00024020054190bdc600460d002001280208210720012802002108200441306a410041e00210e7061a200441286a22064100360200200441206a22094200370300200441186a220a4200370300200441106a220b4200370300200441086a220c420037030020044200370300419403102d220d0d021036000b4195b4ca00412d41f8b4ca001039000b200541086a220a200128020c220d41016a220b4105746a200a200d4105746a220a2006200d6b41057410e9061a200a41186a200241186a290000370000200a41106a200241106a290000370000200a41086a200241086a290000370000200a2002290000370000200541e8026a2202200b4102746a2002200d4102746a220220052f0106200d6b41027410e9061a20022003360200200520052f010641016a3b0106200441306a410b6a200141086a280000360000200041003a00002000200236023c200041106a200d3600002004200129000037003320002004290030370001200041086a200441376a2900003700000c010b200d41003b0106200d4100360200200d41086a200441306a41e00210e806210e200d4190036a2006280200360200200d4188036a2009290300370200200d4180036a200a290300370200200d41f8026a200b290300370200200d41f0026a200c290300370200200d20042903003702e802200441306a41086a220f200541d0016a290000370300200441306a41106a2210200541d8016a290000370300200441306a41186a2211200541e0016a290000370300200420052900c8013703302005280280032112200e200541e8016a20052f010641796a220641057410e8062109200d41e8026a20054184036a200641027410e806210e200541063b0106200d20063b0106200a2011290300370300200b2010290300370300200c200f2903003703002004200429033037030002400240200128020c220141074f0d00200541086a220a200141016a220b4105746a200a20014105746a2206200541066a220a2f010020016b41057410e9061a200641186a200241186a290000370000200641106a200241106a290000370000200641086a200241086a29000037000020062002290000370000200541e8026a220620014102746a21022006200b4102746a2106200121010c010b200d41066a210a20092001417a6a220c4105746a2009200141796a22014105746a220b200641ffff037120016b41057410e9061a200b41186a200241186a290000370000200b41106a200241106a290000370000200b41086a200241086a290000370000200b2002290000370000200e200c4102746a2106200e20014102746a21020b20062002200a2f010020016b41027410e9061a20022003360200200041013a00002000200236023c200041386a4100360200200041346a200d360200200041306a20123602002000412c6a2007360000200041286a2005360000200041246a200836000020002004290300370001200041096a200441086a290300370000200041116a200441106a290300370000200041196a200441186a290300370000200a200a2f010041016a3b01000b20044190036a24000be60b020f7f047e23004180046b220624000240024020012802002207417f6a2005470d000240024002400240200141046a28020022082f01062209410b490d002001280208210a200641c0006a410272410041be0310e7061a41c403102d220b450d05200b4100360200200b41046a200641c0006a41c00310e8061a200641c0006a41186a220c200841e0016a290000370300200641c0006a41106a220d200841d8016a290000370300200641c0006a41086a220e200841d0016a290000370300200620082900c801370340200828028003210f200b41086a200841e8016a20082f0106221041796a220541057410e8062111200b41e8026a20084184036a200541027410e8062112200b4194036a200841b0036a2010417a6a221341027410e8062114200841063b0106200b20053b010602402013450d00410021052014211003402010280200220920053b01042009200b360200201041046a21102013200541016a2205470d000b0b200641206a41186a200c2903002215370300200641206a41106a200d2903002216370300200641206a41086a200e2903002217370300200620062903402218370320200641186a2015370300200641106a2016370300200641086a201737030020062018370300200128020c22054107490d0120112005417a6a22014105746a2011200541796a22104105746a2209200b2f010620106b41057410e9061a200941186a200241186a290000370000200941106a200241106a290000370000200941086a200241086a290000370000200920022900003700002012200141027422096a201220104102746a2213200b2f010620106b41027410e9061a20132003360200200b200b2f010641016a22133b01062005410274220220146a416c6a201420096a2205201341ffff037120016b41027410e9061a200520043602002001200b2f010622134b0d022002200b6a41fc026a2105034020052802002209201041016a22103b01042009200b360200200541046a210520102013490d000c030b0b200841086a2205200128020c221341016a22104105746a200520134105746a2205200920136b41057410e9061a200541186a200241186a290000370000200541106a200241106a290000370000200541086a200241086a29000037000020052002290000370000200841e8026a22092010410274220b6a2009201341027422056a220920082f010620136b41027410e9061a20092003360200200820082f010641016a22093b0106200520084194036a22026a41086a2002200b6a220b200941ffff037120106b41027410e9061a200b20043602000240201020082f0106220b4b0d00200820056a4198036a210520132110034020052802002209201041016a22103b010420092008360200200541046a21052010200b490d000b0b200041003a0000200041046a2001290200370200200041106a20133602002000410c6a200141086a2802003602000c020b200841086a2210200541016a22094105746a201020054105746a221020082f010620056b41057410e9061a201041186a200241186a290000370000201041106a200241106a290000370000201041086a200241086a29000037000020102002290000370000200841e8026a2213200941027422016a2013200541027422106a221320082f010620056b41027410e9061a20132003360200200820082f010641016a22133b0106201020084194036a22026a41086a200220016a2201201341ffff037120096b41027410e9061a20012004360200200520082f010622134f0d00200820106a4198036a2110034020102802002209200541016a22053b010420092008360200201041046a211020132005470d000b0b20002006290300370001200041013a00002000412c6a200a360200200041286a2008360200200041246a2007360200200041386a2007360200200041346a200b360200200041306a200f360200200041096a200641086a290300370000200041116a200641106a290300370000200041196a200641186a2903003700000b20064180046a24000f0b41c2b4ca00413541f8b4ca001039000b1036000b130020004105360204200041b4b4c0003602000b3400200041b8c4c30036020420004100360200200041146a4101360200200041106a41dcd8c000360200200041086a42073702000b130020004101360204200041f4dac0003602000b3400200041d5a2ca0036020420004100360200200041146a4102360200200041106a41d0dec000360200200041086a42093702000b13002000410136020420004184e1c0003602000b2d01017f02404108102d22020d001036000b20004288808080800137020420002002360200200242dc0b3700000baa0501047f200028020021020240024002400240200141046a2802002203200141086a28020022046b4104490d00200128020021030c010b200441046a22052004490d02200341017422042005200420054b1b22044100480d020240024020030d002004102d21030c010b200128020020032004103121030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2205200441046a360200200320046a20023600004120102d2204450d0020042000290004370000200441186a2000411c6a290000370000200441106a200041146a290000370000200441086a2000410c6a29000037000002400240200141046a2802002202200528020022036b4120490d00200128020021020c010b200341206a22052003490d02200241017422032005200320054b1b22034100480d020240024020020d002003102d21020c010b200128020020022003103121020b2002450d0120012002360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200220036a220341186a200441186a290000370000200341106a200441106a290000370000200341086a200441086a290000370000200320042900003700002004102f02400240200141046a2802002203200528020022046b4120490d00200128020021030c010b200441206a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102d21030c010b200128020020032004103121030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a200441206a360200200320046a220141186a2000413c6a290000370000200141106a200041346a290000370000200141086a2000412c6a290000370000200120002900243700000f0b1036000b1038000bc50202057f037e2001280200210202404120102d2203450d0020032002290000370000200341186a2204200241186a290000370000200341106a2205200241106a290000370000200341086a2206200241086a2900003700004120102d2202450d0020022003290000370000200241186a2004290000370000200241106a2005290000370000200241086a20062900003700002003102f200128020421012002412041c00010312203450d0020032001290000370020200341386a200141186a290000370000200341306a200141106a290000370000200341286a200141086a2900003700002003ad4280808080800884100322022900002107200241086a2900002108200241106a2900002109200041186a200241186a290000370000200041106a2009370000200041086a2008370000200020073700002002102f2003102f0f0b1036000b8a0201037f230041206b2203240002400240200241286c4104722204417f4c0d002004102d2205450d0120034100360208200320043602042003200536020020022003106902402002450d002001200241286c6a21050340200320012802003602102003200341106a41041082014120102d2202450d032003422037021420032002360210200341106a200141046a2201412010820120032802142102200320032802102204200328021810820102402002450d002004102f0b2003200141206a2802003602102003200341106a4104108201200141246a22012005470d000b0b20002003290300370200200041086a200341086a280200360200200341206a24000f0b103d000b1036000bb50101037f0240024002400240200041046a2802002203200041086a28020022046b2002490d00200028020021030c010b200420026a22052004490d02200341017422042005200420054b1b22044100480d020240024020030d002004102d21030c010b200028020020032004103121030b2003450d0120002003360200200041046a2004360200200041086a28020021040b200041086a200420026a360200200320046a2001200210e8061a0f0b1036000b1038000bc703010a7f230041106b2203240002400240024020014105744104722204417f4c0d002004102d2205450d012003410036020820032004360204200320053602002001200310690240024020010d002003280208210620032802042107200328020021080c010b2001410574210920032802002108200328020421052003280208210403404120102d2201450d0320012000290000370000200141186a220a200041186a290000370000200141106a220b200041106a290000370000200141086a220c200041086a29000037000002400240200520046b4120490d00200441206a2106200521070c010b200441206a22062004490d05200541017422072006200720064b1b22074100480d050240024020050d002007102d21080c010b200820052007103121080b2008450d040b200041206a2100200820046a22042001290000370000200441186a200a290000370000200441106a200b290000370000200441086a200c2900003700002001102f2007210520062104200941606a22090d000b2003200736020420032006360208200320083602000b20022902002006ad4220862008ad84100402402007450d002008102f0b200341106a24000f0b103d000b1036000b1038000b9b0202067f017e230041106b2202240002404120102d2203450d0020032000290000370000200341186a2204200041186a290000370000200341106a2205200041106a290000370000200341086a2206200041086a2900003700004120102d2207450d0020072003290000370000200741186a2004290000370000200741106a2005290000370000200741086a20062900003700002003102f0240024020002d0020220341024d0d004280808080800421080c010b024002400240024020030e03000102000b410021030c020b410121030c010b410221030b200220033a000f2007412041c00010312207450d01200720033a00204280808080900421080b200129020020082007ad8410042007102f200241106a24000f0b1036000bef05010a7f230041106b22032400024002400240200241c4006c41046a2204417f4c0d000240024020040d00410121050c010b2004102d2205450d020b20034100360208200320043602042003200536020020022003106902402002450d002001200241c4006c6a2106200328020421042003280208210703402001280200210502400240200420076b4104490d00200328020021020c010b200741046a22022007490d05200441017422082002200820024b1b22084100480d050240024020040d002008102d21020c010b200328020020042008103121020b2002450d042003200836020420032002360200200821040b2003200741046a2208360208200220076a20053600004120102d2205450d03200541186a22092001411c6a290000370000200541106a220a200141146a290000370000200541086a220b2001410c6a2900003700002005200141046a29000037000002400240200420086b4120490d00200741246a21070c010b200841206a22072008490d052004410174220c2007200c20074b1b220c4100480d050240024020040d00200c102d21020c010b20022004200c103121020b2002450d042003200c36020420032002360200200c21040b20032007360208200220086a22082005290000370000200841086a200b290000370000200841106a200a290000370000200841186a20092900003700002005102f0240200420076b411f4b0d00200741206a22052007490d05200441017422082005200820054b1b22054100480d050240024020040d002005102d21020c010b200220042005103121020b2002450d042003200536020420032002360200200521040b200220076a220241086a2001412c6a290000370000200241106a200141346a290000370000200241186a2001413c6a2900003700002003200741206a22073602082002200141246a290000370000200141c4006a22012006470d000b0b20002003290300370200200041086a200341086a280200360200200341106a24000f0b103d000b1036000b1038000bf20503037f027e047f230041106b22022400200241003602082002420137030020002802102103024002404104102d2204450d0020024284808080c0003702042002200436020020042003360000200041146a280200210320044104410810312204450d002002428880808080013702042004200336000420022004360200200041086a290300210520002903002106024002404108200228020822076b4110490d00200741106a2103410821080c010b200741106a22032007490d024110200320034110491b22084100480d0220044108200810312204450d0120022008360204200220043602000b200420076a22072005370008200720063700002002200336020802400240200820036b4120490d00200341206a21070c010b200341206a22072003490d02200841017422092007200920074b1b22094100480d0220042008200910312204450d0120022009360204200220043602000b20022007360208200420036a22042000290024370000200441086a2000412c6a290000370000200441106a200041346a290000370000200441186a2000413c6a29000037000020002802182104200041206a2802002200200210690240024020000d002002280208210020022802042109200228020021080c010b2000410574210a4100200228020822006b210720022802042109034002400240200920076a4120490d00200228020021080c010b200041206a22032000490d04200941017422082003200820034b1b22034100480d040240024020090d002003102d21080c010b200228020020092003103121080b2008450d032002200336020420022008360200200321090b200820006a220341086a200441086a290000370000200341106a200441106a290000370000200341186a200441186a2900003700002002200041206a220036020820032004290000370000200741606a2107200441206a2104200a41606a220a0d000b0b20012902002000ad4220862008ad84100402402009450d002008102f0b200241106a24000f0b1036000b1038000b811505177f017e017f027e047f230041206b220224000240024020014115490d00024002402001410176220341ffffff3f712003470d0020034105742204417f4c0d0041012105024002402004450d002004102d2205450d01200441057621030b200041606a2106200041a07f6a210741002108410021094104210a4100210b2001210c034002400240200c220d417f6a220e0d004101210f4100210c0c010b0240024002400240024002402000200e4105746a200d410574221020006a41406a412010ea064100480d004102200d6b210e200720106a21044101210f03400240200e200f6a4101470d004100210c200d210f0c080b200f41016a210f200441206a2004412010ea062111200441606a21042011417f4a0d000b200d200f6b210e0c010b200720106a2104024003400240200e4101470d004100210e0c020b200e417f6a210e200441206a2004412010ea062111200441606a210420114100480d000b0b200d200e490d01200d20014b0d03200d200e6b220f4101762212450d00200620106a21042000200e4105746a21110340200241186a2210201141186a2213290000370300200241106a2214201141106a2215290000370300200241086a2216201141086a221729000037030020022011290000370300200441086a22182900002119200441106a221a290000211b200441186a220c290000211c201120042900003700002013201c3700002015201b37000020172019370000200c2010290300370000201a20142903003700002018201629030037000020042002290300370000200441606a2104201141206a21112012417f6a22120d000b0b0240200e0d00200e210c0c050b0240200f41094d0d00200e210c0c050b200d20014b0d01200d200e6b21122000200e4105746a21100340200d200e417f6a220c490d040240200d200c6b220f4102490d002000200e4105746a22042000200c4105746a220e412010ea06417f4a0d00200e2900002119200e2004290000370000200241186a2216200e41186a2211290000370300200241106a2217200e41106a2213290000370300200241086a2218200e41086a22142900003703002014200441086a2900003700002013200441106a2900003700002011200441186a29000037000020022019370300410121150240200f4103490d00200e41c0006a2002412010ea06417f4a0d00410221112010210402400340200441186a200441386a290000370000200441106a200441306a290000370000200441086a200441286a2900003700002004200441206a221329000037000020122011460d01200441c0006a21142011211520132104201141016a211120142002412010ea06417f4a0d020c000b0b201121150b200e20154105746a22042002290300370000200441186a2016290300370000200441106a2017290300370000200441086a20182903003700000b200c450d05201041606a2110201241016a2112200c210e200f410a4f0d050c000b0b200e200d104b000b200d200e417f6a220c490d010b200d2001104a000b200c200d104b000b0240200b2009470d0002400240200941016a22042009490d00200941017422112004201120044b1b220441ffffffff01712004470d002004410374220441004e0d010b1038000b0240024020090d002004102d210a0c010b200a200941037420041031210a0b200a450d02200441037621092008210b0b200a200b4103746a2204200f3602042004200c360200200841016a220b21080240200b4102490d00024003400240024002400240200a200b417f6a22084103746a2204280200450d00200b410374200a6a220f41746a280200220e200428020422114d0d000240200b41024b0d00200b21084102210b200c450d0b0c080b200a200b417d6a22164103746a28020422042011200e6a4d0d010240200b41034b0d00200b21084103210b200c450d0b0c080b200f41646a2802002004200e6a4d0d01200b21080c060b200b4103490d0120042802042111200a200b417d6a22164103746a28020421040b20042011490d010b200b417e6a21160b024002400240024002400240200b201641016a221d4b221e450d00200b20164b221f450d01200a20164103746a2217280204222020172802006a2204200a201d4103746a2218280200221a490d02200420014b0d032000201a4105746a22142018280204221541057422116a210f2004410574210e2004201a6b220d20156b220420154f0d042005200f2004410574221110e806221320116a21120240024020154101480d00200441014e0d010b200f2104201321110c060b2006200e6a210e200f21040340200e200441606a220f201241606a220d200d200f412010ea0641004822101b2211290000370000200e41186a201141186a290000370000200e41106a201141106a290000370000200e41086a201141086a2900003700002012200d20101b211202402014200f200420101b2204490d00201321110c070b200e41606a210e2013211120132012490d000c060b0b41c4c2ca00201d200b103b000b41c4c2ca002016200b103b000b201a2004104b000b20042001104a000b20052014201110e806221320116a21120240024020154101480d00200d20154a0d010b20142104201321110c010b2000200e6a2110201321112014210403402004200f2011200f2011412010ea06410048220d1b220e290000370000200441186a200e41186a290000370000200441106a200e41106a290000370000200441086a200e41086a2900003700002011201141206a200d1b2111200441206a2104200f41206a200f200d1b220f20104f0d01201220114b0d000b0b20042011201220116b41607110e8061a0240201f450d002017201a360200201741046a202020156a360200201e450d022018201841086a200b201d417f736a41037410e9061a2008210b200841014d0d030c010b0b419cc3ca002016200b103b000b41b8e3c300411d41f8b4ca001039000b200c450d030c000b0b1036000b103d000b02402009450d00200a102f0b2003450d012005102f0c010b20014102490d002001417f6a2111200141057420006a41206a2110410121120340024002400240024020112204417f6a221120014b0d00200120116b220e4102490d03200020044105746a2204200020114105746a220d412010ea06417f4a0d03200d2900002119200d2004290000370000200241186a2214200d41186a220f290000370300200241106a220b200d41106a2213290000370300200241086a2215200d41086a220a290000370300200a200441086a2900003700002013200441106a290000370000200f200441186a2900003700002002201937030041012104200e4103490d02200d41c0006a2002412010ea06417f4a0d0241002113201021040340200441406a220e200441606a220f290000370000200e41186a200f41186a290000370000200e41106a200f41106a290000370000200e41086a200f41086a29000037000020122013220e460d02200e417f6a211320042002412010ea06210f200441206a2104200f417f4a0d020c000b0b20112001104b000b4102200e6b21040b200d20044105746a22042002290300370000200441186a2014290300370000200441106a200b290300370000200441086a20152903003700000b201041606a21102012417f6a211220110d000b0b200241206a24000bf10101037f0240024002404101450d0041202102024002404120450d004120102d2203450d03200141106a21040c010b41204101742203411020031b2202102d2203450d02200141106a21040b20032001290000370000200341086a200141086a29000037000002400240200241f000714110460d00200221010c010b200241017422014120200141204b1b22014100480d03024002402002450d00200320022001103121030c010b2001102d21030b2003450d020b20032004290000370010200341186a200441086a2900003700002000412036020820002001360204200020033602000f0b103d000b1036000b1038000bd00201097f2001200210690240024002402001450d0020014105742103200241046a210403404120102d2201450d0220012000290000370000200141186a2205200041186a290000370000200141106a2206200041106a290000370000200141086a2207200041086a2900003700000240024020042802002208200241086a2209280200220a6b4120490d00200228020021080c010b200a41206a220b200a490d042008410174220a200b200a200b4b1b220a4100480d040240024020080d00200a102d21080c010b20022802002008200a103121080b2008450d03200220083602002004200a3602002009280200210a0b200041206a21002009200a41206a3602002008200a6a220a41186a2005290000370000200a41106a2006290000370000200a41086a2007290000370000200a20012900003700002001102f200341606a22030d000b0b0f0b1036000b1038000bce8b0106177f037e0b7f017e0a7f027e230041b0096b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e06000102030405000b200341f4056a4101360200200342013702e405200341b4d8c9003602e0052003410436029403200341fcdbc90036029003200320034190036a3602f005200341e0056a41e8d8c9001043000b200341c0006a41026a2204200241076a2d00003a000020034190086a41086a2205200241186a29020037030020034190086a410d6a22062002411d6a2900003700002003200241056a2f00003b01402003200241106a29020037039008200141046a28020022072001410c6a280200220841b0026c22096a210a200141086a280200210b2007210c024002402008450d00200241046a2d0000210d200241026a2f0100210e200241086a280200210f2002410c6a280200211020022d0001211120022d0000211220034190036a410272211320034190036a41106a211420034190036a4105722115200941d07d6a2102200341ce056a2116200341c0056a4103722117200341e0056a4104722118410021192007210c0340200c280200210820034190036a200c41046a220941ac0210e8061a200341e0056a200941ac0210e8061a02402008411b470d00200c41b0026a210c0c1e0b200341e0006a200341e0056a41ac0210e8061a200320083602e0052018200341e0006a41ac0210e8061a024002400240024020120e03000102000b4102210802400240024020110e03000102000b410021080c010b201720032f01403b00002016200329039008370100201741026a20042d00003a0000201641086a2005290300370100201641106a20034190086a41106a2f01003b01002003200d3a00c2052003200e3b01c005200320103601ca052003200f3601c605410121080b201320032903c005370000201341086a200341c0056a41086a290300370000201341106a200341c0056a41106a290300370000201341186a200341c0056a41186a290300370000200320083a009103200341003a0090030c020b41022108024002400240200d0e03000102000b410021080c010b200341b8086a41026a20042d00003a0000200341f8086a41086a2005290300370300200341f8086a410d6a2006290000370000200320032f01403b01b80820032003290390083703f808410121080b201520032f01b8083b0000201420032903f808370200201541026a200341b8086a41026a2d00003a0000201441086a200341f8086a41086a290300370200201441106a200341f8086a41106a290300370200200320083a0094032003201036029c032003200f36029803200341013a0090030c010b41022108024002400240200d0e03000102000b410021080c010b200341b8086a41026a20042d00003a0000200341f8086a41086a2005290300370300200341f8086a410d6a2006290000370000200320032f01403b01b80820032003290390083703f808410121080b201520032f01b8083b0000201420032903f808370200201441086a200341f8086a41086a290300370200201441106a200341f8086a41106a290300370200200341023a009003201541026a200341b8086a41026a2d00003a0000200320083a0094032003201036029c032003200f360298030b200341d8086a200341e0056a20034190036a108b0120032d00d8084104470d02201941016a2119200241d07d6a2102200c41b0026a220c200a470d000b200a210c0b200341e0056a20034190036a41ac0210e8061a0c1b0b200341e0056a41086a2019360200200341ec056a20032903d808370200200341f4056a200341d8086a41086a280200360200200341003a00e405200341013a00e00541c8e1ca004100200341e0056a108c01200041043a000002402002450d00200c41b0026a210c0340200c108d01200c41b0026a210c200241d07d6a22020d000b0b200b450d1b2007102f0c1b0b200141046a280200210a0240024020022d00000d0020022d00014101470d002002411a6a290100211a200241196a2d00002108200241186a2d00002114200241166a2f01002109200241156a2d00002119200241146a2d00002113200241126a2f01002115200241116a2d00002112200241106a2d000021182002410e6a2f0100210d2002410d6a2d0000210f2002410c6a2d000021102002410a6a2f01002107200241096a2d00002104200241086a2d00002105200241066a2f01002116200241056a2d00002111200241046a2d00002106200241026a2f01002102200141026a2f010021174112102d220c450d11200c41086a41002900ade440370000200c41002900a5e440370000200c411241301031220c450d11200c201a370028200c20083a0027200c20143a0026200c20093b0024200c20193a0023200c20133a0022200c20153b0020200c20123a001f200c20183a001e200c200d3b001c200c200f3a001b200c20103a001a200c20073b0018200c20043a0017200c20053a0016200c20163b0014200c20113a0013200c20063a0012200c20023b0010200c413041e00010312202450d11200220173b00302002ad4280808080a006841003220c290000211a200c41086a290000211b200c41106a290000211c200341c0056a41186a2208200c41186a290000370300200341c0056a41106a2214201c370300200341c0056a41086a2209201b3703002003201a3703c005200c102f2002102f200341093a0080062003410a3a0080062003410b3a008006200320032f01c0053b01e005200320032801c2053601e205200320032f01c6053b01e605200320092f01003b01e805200320032d00ca053a00ea052003410c3a008006200320032d00cb053a00eb052003410d3a008006200320032d00cc053a00ec052003410e3a008006200320032d00cd053a00ed052003410f3a008006200320032d00ce053a00ee05200341103a008006200320032d00cf053a00ef05200341113a008006200320142d00003a00f005200320032d00d1053a00f105200341123a008006200341133a008006200320032d00d2053a00f205200341143a008006200320032d00d3053a00f305200341153a008006200320032d00d4053a00f405200341163a008006200320032d00d5053a00f505200341173a008006200320032d00d6053a00f605200341183a008006200320032d00d7053a00f705200341193a008006200320082d00003a00f805200320032d00d9053a00f9052003411a3a0080062003411b3a008006200320032d00da053a00fa052003411c3a008006200320032d00db053a00fb052003411d3a008006200320032d00dc053a00fc052003411e3a008006200320032d00dd053a00fd052003411f3a008006200320032d00de053a00fe05200341203a008006200320032d00df053a00ff0520034190086a41186a220c20032903f80537030020034190086a41106a220220032903f00537030020034190086a41086a220820032903e805370300200320032903e00537039008200341e0006a41186a2214200c290300370300200341e0006a41106a220c2002290300370300200341e0006a41086a220220082903003703002003200329039008370360200341e0056a200a41b00210e8061a20034190036a410a6a200229030037010020034190036a41126a200c29030037010020034190036a411a6a201429030037010020034180023b01900320032003290360370192032000200341e0056a20034190036a108b010c010b200041023a0000200a108e010b200a102f410121084100210241012114410121090c180b200141086a280200210a200141046a28020021142001411c6a280200210c024020022d00000d0020022d00014101470d002001410c6a2802002108200141186a280200211d200141146a280200211e200141106a280200211f200141026a2f01002109200241196a2d00002119200241186a2d00002113200241166a2f01002115200241156a2d00002112200241146a2d00002118200241126a2f0100210d200241116a2d0000210f200241106a2d000021102002410e6a2f010021072002410d6a2d000021042002410c6a2d000021052002410a6a2f01002116200241096a2d00002111200241086a2d00002106200241066a2f01002117200241056a2d0000210b200241046a2d0000210e200241026a2f0100212020032002411a6a2901003703d008200320193a00cf08200320133a00ce08200320153b01cc08200320123a00cb08200320183a00ca082003200d3b01c8082003200f3a00c708200320103a00c608200320073b01c408200320043a00c308200320053a00c208200320163b01c008200320113a00bf08200320063a00be08200320173b01bc082003200b3a00bb082003200e3a00ba08200320203b01b8080240200941ffff03710d00410d210241aacdc7002108410021090c170b024020080d0041112102418da7c0002108410321090c170b0240200841e3004d0d004112210241fba6c0002108410421090c170b200320083602682003200a36026420032014360260200341e0056a41186a200341b8086a41186a290300370300200341e0056a41106a200341b8086a41106a290300370300200341e0056a41086a220a200341b8086a41086a290300370300200320032903b8083703e00520034190036a200341e0006a200341e0056a108f01410121022003280290034101460d0320034190036a41086a28020021212003280294032113200a20034190036a410c6a280200360200200320093b01ec05200320133602e405200341a5e4c0003602e005200341c0056a200341e0056a109001200341083a0080062003410b3a0080062003410c3a008006200320032f01c0053b01e005200320032801c2053601e205200320032d00c6053a00e605200320032800c7053600e705200320032d00cb053a00eb052003410d3a008006200320032d00cc053a00ec052003410e3a008006200320032d00cd053a00ed052003410f3a008006200320032d00ce053a00ee05200320032d00cf053a00ef05200341103a008006200341113a008006200320032d00d0053a00f005200341123a008006200320032d00d1053a00f105200341133a008006200320032d00d2053a00f205200341143a008006200320032d00d3053a00f305200341153a008006200320032d00d4053a00f405200341163a008006200320032d00d5053a00f505200341173a008006200320032d00d6053a00f605200320032d00d7053a00f705200341183a008006200341193a008006200320032d00d8053a00f8052003411a3a008006200320032d00d9053a00f9052003411b3a008006200320032d00da053a00fa052003411c3a008006200320032d00db053a00fb052003411d3a008006200320032d00dc053a00fc052003411e3a008006200320032d00dd053a00fd052003411f3a008006200320032d00de053a00fe05200341203a008006200320032d00df053a00ff0520034190086a41186a220220032903f80537030020034190086a41106a220a20032903f00537030020034190086a41086a220820032903e805370300200320032903e00537039008200341d8086a41186a2002290300370300200341d8086a41106a200a290300370300200341d8086a41086a200829030037030020032003290390083703d808200341003602e805200342013703e005200c200341e0056a10910120032802e405210a20033502e80542208620032802e0052208ad8410032202290018211a20022d0017211820022d0016210d20022f0014210f20022d0013211020022d0012210720022f0010210420022d000f210520022d000e211620022f000c211120022d000b210620022d000a211720022f0008210b20022d0007210e20022d0006212020022f0004212220022d0003212320022d0002212420022f000021252002102f0240200a450d002008102f0b2003201a3703d805200320183a00d7052003200d3a00d6052003200f3b01d405200320103a00d305200320073a00d205200320043b01d005200320053a00cf05200320163a00ce05200320113b01cc05200320063a00cb05200320173a00ca052003200b3b01c8052003200e3a00c705200320203a00c605200320223b01c405200320233a00c305200320243a00c205200320253b01c00520034190036a200341d8086a200341c0056a109201200341e0056a200328029003221420032802980310930120034190086a41086a22192003418c066a29020037030020034190086a41106a222620034194066a29020037030020034190086a41186a22272003419c066a29020037030020034190086a41206a200341a4066a280200360200200320034184066a29020037039008200341e0056a41086a290300211b200341e0056a41206a280200211520032903e005211c20032802fc05211220032802f405210a20032802f0052102024020032802f8052208450d00200341f8086a41206a20034190086a41206a280200360200200341f8086a41186a2027290300370300200341f8086a41106a2026290300370300200341f8086a41086a201929030037030020032003290390083703f8080b0240200328029403450d002014102f0b024002400240024020080d0041012102201f4101460d02200941ffff037141014b0d01200341e0056a200c41b00210e8061a2003419a036a200341e0086a290300370100200341a2036a200341e8086a290300370100200341aa036a200341f0086a29030037010020034180023b019003200320032903d808370192032000200341e0056a20034190036a108b01410021020c030b20034190036a41206a2015360200200341ac036a2012360200200341a4036a200a360200200341bc036a200341f8086a41086a290300370200200341c4036a20034188096a290300370200200341cc036a20034190096a290300370200200341d4036a200341f8086a41206a2802003602002003201c37039003200320083602a803200320023602a003200320032903f8083702b4032003201b370398030240201f4101460d00410b211441c8a6c00021194109211f0c160b410e211441baa6c0002119410a211f2002201e470d15200a201d470d150240024002400240201541014b0d004100210220150e020201020b2015210a4100210203402002200a410176221420026a2219200820194105746a200341b8086a412010ea0641004a1b2102200a20146b220a41014b0d000b0b200820024105746a200341b8086a412010ea06220a450d01200a411f7620026a21020b2009417f6a41ffff0371201541ffff03714b0d120c100b200941ffff0371201541ffff03714d0d0f410f211441afa7c00021194101211f0c150b200341106a2009ad42ffff038342004280a0e5b9c29101420010ed0620032003290310221c4280c0dfda8ee9067c221b3703602003200341106a41086a290300201b201c54ad7c221c3703682003200341b8086a3602402003200341b8086a36029008200320034190086a3602e8052003200341c0006a3602e4052003200341e0006a3602e00520034190036a200341b8086a200341e0056a109401024002402003280290034101470d0020032003290095033703e00520032003419c036a2800003600e70520032d00940321020c010b4104210220034190036a41086a2903004201520d0020034190036a41106a2903002128200328029008210a20034198066a20034190036a41186a29030037030020034190066a2028370300200341e0056a41086a41003a0000200341e9056a200a290000370000200341f1056a200a41086a290000370000200341f9056a200a41106a29000037000020034181066a200a41186a290000370000200341033a00e00541c8e1ca004100200341e0056a108c010b200320032903e0053703c005200320032800e7053600c7050240200241ff01714104470d0020034190036a41186a420037030020034190036a41106a2208420037030020034190036a41086a220242003703002003420037039003418de6c300ad4280808080e000841001220a29000021282002200a41086a2900003703002003202837039003200a102f419ce6c300ad4280808080e000841001220a2900002128200341e0056a41086a2214200a41086a290000370300200320283703e005200a102f200820032903e005222837030020034190086a41086a200229030037030020034190086a41106a202837030020034190086a41186a2014290300370300200320032903900337039008200341086a20034190086a4120109501200328020c210a2003280208210820034180e5c3004110109501200328020421142003280200210920032f01b808211920032d00ba08211520032d00bb08211220032f01bc08211f20032d00be08211e20032d00bf08211d20032f01c008212620032d00c208212720032d00c308212920032f01c408212a20032d00c608212b20032d00c708212c20032f01c808212d20032d00ca08212e20032d00cb08212f20032f01cc08213020032d00ce08213120032d00cf08213220032903d00821284120102d2202450d12200220032903b808370000200241186a200341b8086a41186a290300370000200241106a200341b8086a41106a290300370000200241086a200341b8086a41086a290300370000200341f4056a2014410020091b3602002003419c066a20283702002003419b066a20323a00002003419a066a20313a000020034198066a20303b010020034197066a202f3a000020034196066a202e3a000020034194066a202d3b010020034193066a202c3a000020034192066a202b3a000020034190066a202a3b01002003418f066a20293a00002003418e066a20273a00002003418c066a20263b01002003418b066a201d3a00002003418a066a201e3a000020034188066a201f3b010020034187066a20123a000020034186066a20153a00002003201c3703e8052003201b3703e0052003200a410020081b3602f005200320193b018406200341fc056a428180808010370200200320023602f8052003201a3703d805200320183a00d7052003200d3a00d6052003200f3b01d405200320103a00d305200320073a00d205200320043b01d005200320053a00cf05200320163a00ce05200320113b01cc05200320063a00cb05200320173a00ca052003200b3b01c8052003200e3a00c705200320203a00c605200320223b01c405200320233a00c305200320243a00c205200320253b01c00520034190036a200341d8086a200341c0056a1092012003280290032102200320032802980336026420032002360260200341e0056a200341e0006a1086010240200328029403450d002002102f0b024020032802fc05450d0020032802f805102f0b20034185066a20032903d808370000200341ed056a200341b8086a41086a290300370000200341f5056a200341b8086a41106a290300370000200341fd056a200341b8086a41186a2903003700002003418d066a200341d8086a41086a29030037000020034195066a200341d8086a41106a2903003700002003419d066a200341d8086a41186a290300370000200341023a00e40541012102200341013a00e005200320032903b8083700e50541c8e1ca004100200341e0056a108c010c100b200020023a0000200020032903c005370001200041086a20032800c705360000410121020c010b20004183023b0100200041086a4113360200200041046a41a7a6c000360200200041026a410b3a00000b02402021450d002013102f0b20020d140c150b200041023a00000c160b200141286a280200210c200141246a280200210a02400240024020022d00000d0020022d00014101470d00200141196a290000211a200141186a2d00002120200141176a2d0000211f200141156a2f0000211e200141146a2d0000211d200141136a2d00002122200141116a2f00002123200141106a2d000021242001410f6a2d000021252001410d6a2f000021212001410c6a2d000021262001410b6a2d00002127200141096a2f00002129200141086a2d0000212a200141076a2d0000212b200141056a2f0000212c200141046a2d0000212d200141036a2d0000212e2001412c6a2802002108200141386a2802002132200141346a2802002131200141306a2802002130200141226a2f0100211420012f0001212f200241196a2d00002109200241186a2d00002119200241166a2f01002113200241156a2d00002115200241146a2d00002112200241126a2f01002118200241116a2d0000210d200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021072002410c6a2d000021042002410a6a2f01002105200241096a2d00002116200241086a2d00002111200241066a2f01002106200241056a2d00002117200241046a2d0000210b200241026a2f0100210e20032002411a6a2901003703f008200320093a00ef08200320193a00ee08200320133b01ec08200320153a00eb08200320123a00ea08200320183b01e8082003200d3a00e7082003200f3a00e608200320103b01e408200320073a00e308200320043a00e208200320053b01e008200320163a00df08200320113a00de08200320063b01dc08200320173a00db082003200b3a00da082003200e3b01d8080240024002400240024002402014450d002008450d01200841e4004f0d02200320083602682003200c3602642003200a360260200341e0056a41186a200341d8086a41186a290300370300200341e0056a41106a200341d8086a41106a290300370300200341e0056a41086a220c200341d8086a41086a290300370300200320032903d8083703e00520034190036a200341e0006a200341e0056a108f012003280290034101460d0320034190036a41086a28020021192003280294032109200c20034190036a410c6a280200360200200320143b01ec05200320093602e405200341a5e4c0003602e005200341c0056a200341e0056a109001200341083a0080062003410b3a0080062003410c3a008006200320032f01c0053b01e005200320032801c2053601e205200320032d00c6053a00e605200320032800c7053600e705200320032d00cb053a00eb052003410d3a008006200320032d00cc053a00ec052003410e3a008006200320032d00cd053a00ed052003410f3a008006200320032d00ce053a00ee05200320032d00cf053a00ef05200341103a008006200341113a008006200320032d00d0053a00f005200341123a008006200320032d00d1053a00f105200341133a008006200320032d00d2053a00f205200341143a008006200320032d00d3053a00f305200341153a008006200320032d00d4053a00f405200341163a008006200320032d00d5053a00f505200341173a008006200320032d00d6053a00f605200320032d00d7053a00f705200341183a008006200341193a008006200320032d00d8053a00f8052003411a3a008006200320032d00d9053a00f9052003411b3a008006200320032d00da053a00fa052003411c3a008006200320032d00db053a00fb052003411d3a008006200320032d00dc053a00fc052003411e3a008006200320032d00dd053a00fd052003411f3a008006200320032d00de053a00fe05200320032d00df053a00ff05200341203a00800620034190086a41186a220220032903f80537030020034190086a41106a220a20032903f00537030020034190086a41086a220820032903e805370300200320032903e00537039008200341f8086a41186a2002290300370300200341f8086a41106a200a290300370300200341f8086a41086a200829030037030020032003290390083703f8082003201a3703d805200320203a00d7052003201f3a00d6052003201e3b01d4052003201d3a00d305200320223a00d205200320233b01d005200320243a00cf05200320253a00ce05200320213b01cc05200320263a00cb05200320273a00ca05200320293b01c8052003202a3a00c7052003202b3a00c6052003202c3b01c4052003202d3a00c3052003202e3a00c2052003202f3b01c00520034190036a200341f8086a200341c0056a109201200341e0056a200328029003221320032802980310930120082003418c066a290200370300200a20034194066a29020037030020022003419c066a29020037030020034190086a41206a2202200341a4066a280200360200200320034184066a29020037039008200c290300211b200341e0056a41206a280200211520032903e005211c20032802fc05210820032802f405211220032802f005210a024020032802f805220c450d00200341e0006a41206a2002280200360200200341e0006a41186a20034190086a41186a290300370300200341e0006a41106a20034190086a41106a290300370300200341e0006a41086a20034190086a41086a29030037030020032003290390083703600b0240200328029403450d002013102f0b200c0d04201441014b0d0520004183023b0100200041086a4111360200200041046a419ea7c000360200200041026a41023a00000c0f0b20004183023b0100200041086a410d360200200041046a41aacdc700360200200041026a41003a00000c060b20004183023b0100200041086a4111360200200041046a418da7c000360200200041026a41033a00000c050b20004183023b0100200041086a4112360200200041046a41fba6c000360200200041026a41043a00000c040b200020034190036a410472220c290200370200200041086a200c41086a2802003602000c0d0b20034190036a41206a200341e0006a41206a28020036020020034190036a41186a200341e0006a41186a29030037030020034190036a41106a200341e0006a41106a29030037030020034190036a41086a200341e0006a41086a290300370300200320032903603703900302400240024002400240024020304101470d00200a2031470d0120122032470d01201520144f0d0c201541014b0d034100210220150e020204020b20004183023b0100200041086a410b360200200041046a41c8a6c000360200200041026a41093a00000c0e0b20004183023b0100200041086a410e360200200041046a41baa6c000360200200041026a410a3a00000c0d0b200341e0056a41186a200341d8086a41186a290300370300200341e0056a41106a200341d8086a41106a290300370300200341e0056a41086a200341d8086a41086a290300370300200320032903d8083703e00541002114200341e0056a210a0c020b2015210a4100210203402002200a410176221420026a2213200c20134105746a200341d8086a412010ea0641004a1b2102200a20146b220a41014b0d000b0b0240200c20024105746a200341d8086a412010ea0622140d0020004183023b0100200041086a410f360200200041046a41afa7c000360200200041026a41013a00000c0b0b200341e0056a41186a200341d8086a41186a290300370300200341e0056a41106a200341d8086a41106a290300370300200341e0056a41086a200341d8086a41086a290300370300200320032903d8083703e005200341e0056a210a20152014411f7620026a2214490d080b024020152008470d00200841016a22022008490d14200841017422132002201320024b1b220241ffffff3f712002470d14200241057422024100480d140240024020080d002002102d210c0c010b200c200841057420021031210c0b200c450d12200241057621080b200c20144105746a220241206a2002201520146b41057410e9061a200241186a200a41186a290000370000200241106a200a41106a290000370000200241086a200a41086a2900003700002002200a290000370000200341e0056a41206a201541016a360200200341fc056a2008360200200341f4056a20323602002003418c066a20034190036a41086a29030037020020034194066a20034190036a41106a2903003702002003419c066a20034190036a41186a290300370200200341a4066a20034190036a41206a2802003602002003201b3703e8052003201c3703e0052003200c3602f805200320313602f0052003200329039003370284062003201a3703d805200320203a00d7052003201f3a00d6052003201e3b01d4052003201d3a00d305200320223a00d205200320233b01d005200320243a00cf05200320253a00ce05200320213b01cc05200320263a00cb05200320273a00ca05200320293b01c8052003202a3a00c7052003202b3a00c6052003202c3b01c4052003202d3a00c3052003202e3a00c2052003202f3b01c00520034190086a200341f8086a200341c0056a109201200328029008210220032003280298083602bc08200320023602b808200341e0056a200341b8086a1086010240200328029408450d002002102f0b02402008450d00200c102f0b20034185066a20032903f808370000200341ed056a200341d8086a41086a290300370000200341f5056a200341d8086a41106a290300370000200341fd056a200341d8086a41186a2903003700002003418d066a200341f8086a41086a29030037000020034195066a200341f8086a41106a2903003700002003419d066a200341f8086a41186a290300370000200341033a00e405200341013a00e005200320032903d8083700e505200341ac066a2032360200200341a8066a203136020041c8e1ca004100200341e0056a108c010c080b20304101460d02200341306a2014ad42004280a0e5b9c29101420010ed0620032003290330221c4280c0dfda8ee9067c221b370390082003200341306a41086a290300201b201c54ad7c221c370398082003200341d8086a3602402003200341d8086a3602b8082003200341b8086a3602e8052003200341c0006a3602e405200320034190086a3602e00520034190036a200341d8086a200341e0056a109401024002402003280290034101470d0020032003290095033703e00520032003419c036a2800003600e70520032d009403210c0c010b4104210c20034190036a41086a2903004201520d0020034190036a41106a290300212820032802b808210220034198066a20034190036a41186a29030037030020034190066a2028370300200341e0056a41086a41003a0000200341e9056a2002290000370000200341f1056a200241086a290000370000200341f9056a200241106a29000037000020034181066a200241186a290000370000200341033a00e00541c8e1ca004100200341e0056a108c010b200320032903e0053703c005200320032800e7053600c7050240200c41ff01714104470d0020034190036a41186a420037030020034190036a41106a220a420037030020034190036a41086a220c42003703002003420037039003418de6c300ad4280808080e00084100122022900002128200c200241086a29000037030020032028370390032002102f419ce6c300ad4280808080e00084100122022900002128200341e0056a41086a2208200241086a290000370300200320283703e0052002102f200a20032903e005222837030020034190086a41086a200c29030037030020034190086a41106a202837030020034190086a41186a2008290300370300200320032903900337039008200341286a20034190086a4120109501200328022c21022003280228210a200341206a4180e5c3004110109501200328022421082003280220211420032f01d808211320032d00da08211520032d00db08211220032f01dc08211820032d00de08210d20032d00df08210f20032f01e008211020032d00e208210720032d00e308210420032f01e408210520032d00e608211620032d00e708211120032f01e808210620032d00ea08211720032d00eb08210b20032f01ec08210e20032d00ee08213020032d00ef08213120032903f00821284120102d220c450d11200c20032903d808370000200c41186a200341d8086a41186a290300370000200c41106a200341d8086a41106a290300370000200c41086a200341d8086a41086a290300370000200341f4056a2008410020141b3602002003419c066a20283702002003419b066a20313a00002003419a066a20303a000020034198066a200e3b010020034197066a200b3a000020034196066a20173a000020034194066a20063b010020034193066a20113a000020034192066a20163a000020034190066a20053b01002003418f066a20043a00002003418e066a20073a00002003418c066a20103b01002003418b066a200f3a00002003418a066a200d3a000020034188066a20183b010020034187066a20123a000020034186066a20153a00002003201c3703e8052003201b3703e005200320024100200a1b3602f005200320133b018406200341fc056a4281808080103702002003200c3602f8052003201a3703d805200320203a00d7052003201f3a00d6052003201e3b01d4052003201d3a00d305200320223a00d205200320233b01d005200320243a00cf05200320253a00ce05200320213b01cc05200320263a00cb05200320273a00ca05200320293b01c8052003202a3a00c7052003202b3a00c6052003202c3b01c4052003202d3a00c3052003202e3a00c2052003202f3b01c00520034190036a200341f8086a200341c0056a109201200328029003210c2003200328029803360294082003200c36029008200341e0056a20034190086a1086010240200328029403450d00200c102f0b024020032802fc05450d0020032802f805102f0b20034185066a20032903f808370000200341ed056a200341d8086a41086a290300370000200341f5056a200341d8086a41106a290300370000200341fd056a200341d8086a41186a2903003700002003418d066a200341f8086a41086a29030037000020034195066a200341f8086a41106a2903003700002003419d066a200341f8086a41186a290300370000200341023a00e405200341013a00e005200320032903d8083700e50541c8e1ca004100200341e0056a108c010c080b2000200c3a0000200020032903c005370001200041086a20032800c7053600000c090b200041023a00000b4100211441012102200c450d0a200a102f0c0a0b20004183023b0100200041086a4113360200200041046a41a7a6c000360200200041026a410b3a00000c060b2001412c6a2802002108200141286a280200210c200141246a280200210a200141346a2802002119200141306a2802002109200141226a2f01002114200341c0006a41186a200141196a290000370300200341c0006a41106a200141116a290000370300200341c0006a41086a200141096a2900003703002003200129000137034002400240024020022d00000d0020022d00014101470d00200241196a2d00002113200241186a2d00002115200241166a2f01002112200241156a2d00002118200241146a2d0000210d200241126a2f0100210f200241116a2d00002110200241106a2d000021072002410e6a2f010021042002410d6a2d000021052002410c6a2d000021162002410a6a2f01002111200241096a2d00002106200241086a2d00002117200241066a2f0100210b200241056a2d0000210e200241046a2d00002120200241026a2f0100211f20032002411a6a2901003703d008200320133a00cf08200320153a00ce08200320123b01cc08200320183a00cb082003200d3a00ca082003200f3b01c808200320103a00c708200320073a00c608200320043b01c408200320053a00c308200320163a00c208200320113b01c008200320063a00bf08200320173a00be082003200b3b01bc082003200e3a00bb08200320203a00ba082003201f3b01b8080240024002400240201441ffff0371450d002008450d01200841e4004f0d02200320083602682003200c3602642003200a360260200341e0056a41186a200341b8086a41186a290300370300200341e0056a41106a200341b8086a41106a290300370300200341e0056a41086a220c200341b8086a41086a290300370300200320032903b8083703e00520034190036a200341e0006a200341e0056a108f012003280290034101470d03200020034190036a410472220c290200370200200041086a200c41086a2802003602000c060b20004183023b0100200041086a410d360200200041046a41aacdc700360200200041026a41003a00000c040b20004183023b0100200041086a4111360200200041046a418da7c000360200200041026a41033a00000c030b20004183023b0100200041086a4112360200200041046a41fba6c000360200200041026a41043a00000c020b20034190036a41086a28020021152003280294032113200c20034190036a410c6a280200360200200320143b01ec05200320133602e405200341a5e4c0003602e005200341c0056a200341e0056a109001200341083a0080062003410b3a0080062003410c3a008006200320032f01c0053b01e005200320032801c2053601e205200320032d00c6053a00e605200320032800c7053600e705200320032d00cb053a00eb052003410d3a008006200320032d00cc053a00ec052003410e3a008006200320032d00cd053a00ed052003410f3a008006200320032d00ce053a00ee05200320032d00cf053a00ef05200341103a008006200341113a008006200320032d00d0053a00f005200341123a008006200320032d00d1053a00f105200341133a008006200320032d00d2053a00f205200341143a008006200320032d00d3053a00f305200341153a008006200320032d00d4053a00f405200341163a008006200320032d00d5053a00f505200341173a008006200320032d00d6053a00f605200320032d00d7053a00f705200341183a008006200341193a008006200320032d00d8053a00f8052003411a3a008006200320032d00d9053a00f9052003411b3a008006200320032d00da053a00fa052003411c3a008006200320032d00db053a00fb052003411d3a008006200320032d00dc053a00fc052003411e3a008006200320032d00dd053a00fd052003411f3a008006200320032d00de053a00fe05200320032d00df053a00ff05200341203a00800620034190086a41186a220220032903f80537030020034190086a41106a220a20032903f00537030020034190086a41086a220820032903e805370300200320032903e00537039008200341d8086a41186a2002290300370300200341d8086a41106a200a290300370300200341d8086a41086a200829030037030020032003290390083703d8082003200341c0006a41186a2903003703d8052003200341c0006a41106a2903003703d0052003200341c0006a41086a2903003703c805200320032903403703c005200341a0096a200341d8086a200341c0056a109201200341e0056a20032802a009221420032802a80910930120082003418c066a290200370300200a20034194066a29020037030020022003419c066a29020037030020034190086a41206a2212200341a4066a280200360200200320034184066a2902003703900802400240024020032802f8052202450d00200c290300211a200341e0056a41206a280200211820032903e005211b20032802fc05210a20032802f405210820032802f005210c200341e0006a41206a2012280200360200200341e0006a41186a221220034190086a41186a290300370300200341e0006a41106a220d20034190086a41106a290300370300200341e0006a41086a220f20034190086a41086a2903003703002003200329039008370360024020032802a409450d002014102f0b200341f8086a41086a200f290300221c370300200341f8086a41106a200d2903002228370300200341f8086a41186a20122903002233370300200341f8086a41206a2214200341e0006a41206a28020036020020034190036a41206a2018360200200341ac036a200a360200200341a4036a20083602002003200329036022343703f8082003201b37039003200320023602a8032003201a370398032003200c3602a003200341cc036a2033370200200341c4036a2028370200200341bc036a201c370200200341d4036a2014280200360200200320343702b403410e211441baa6c0002112410a21180240200c2009470d0020082019470d00200341b4036a220c200341b8086a412010ea06450d03410821184188d9c9002112410821140b20004183023b0100200041086a2014360200200041046a2012360200200041026a20183a0000200a450d012002102f0c010b024020032802a409450d002014102f0b200041086a4108360200200041046a4184f5c000360200200041026a41073a000020004183023b01000b2015450d032013102f0c030b2003201b3703f8082003201a370380090240201b201a84500d002003200c36029008200341e0006a200c200341f8086a20034190086a10960120032903604201520d002003290368211a20034198066a200341e0006a41106a29030037030020034190066a201a370300200341e0056a41086a41003a0000200341e9056a200c290000370000200341f1056a200c41086a290000370000200341f9056a200c41106a29000037000020034181066a200c41186a290000370000200341033a00e00541c8e1ca004100200341e0056a108c010b200341c0056a41186a200341c0006a41186a290300370300200341c0056a41106a200341c0006a41106a290300370300200341c0056a41086a200341c0006a41086a290300370300200320032903403703c005200341e0056a200341d8086a200341c0056a10920120033502e80542208620032802e005220cad841005024020032802e405450d00200c102f0b20034185066a20032903d808370000200341ed056a200341b8086a41086a290300370000200341f5056a200341b8086a41106a290300370000200341fd056a200341b8086a41186a2903003700002003418d066a200341d8086a41086a29030037000020034195066a200341d8086a41106a2903003700002003419d066a200341d8086a41186a290300370000200341053a00e405200341013a00e005200320032903b8083700e505200341ac066a2019360200200341a8066a200936020041c8e1ca004100200341e0056a108c01200041043a0000024020032802ac03450d0020032802a803102f0b2015450d022013102f0c020b200041023a00000b200c450d00200a102f0b410021094101210241012108410121140c150b200020034190036a410472220a290200370200200041086a200a41086a280200360200200c108e01200c102f4100210841012114410121090c140b20004183023b0100200041086a4111360200200041046a419ea7c000360200200041026a41023a00000c020b419ae3c300411e41f8b4ca001039000b200041043a000020190d020c030b2008450d00200c102f0b2019450d010b2009102f0b41002114410121020b41012108410121090c0c0b200341e0056a200c41b00210e8061a200341ea006a200341d8086a41086a290300370100200341f2006a200341e8086a290300370100200341fa006a200341f0086a29030037010020034180023b0160200320032903d808370162200341c0006a200341e0056a200341e0006a108b01200329039003211b200320034190036a41086a290300221c370398082003201b370390080240201b201c84500d002003200341b4036a22023602c005200341e0006a200220034190086a200341c0056a10960120032903604201520d002003290368211b20034198066a200341e0006a41106a29030037030020034190066a201b370300200341e0056a41086a41003a0000200341e9056a2002290000370000200341f1056a200241086a290000370000200341f9056a200241106a29000037000020034181066a200241186a290000370000200341033a00e00541c8e1ca004100200341e0056a108c010b2003201a3703d805200320183a00d7052003200d3a00d6052003200f3b01d405200320103a00d305200320073a00d205200320043b01d005200320053a00cf05200320163a00ce05200320113b01cc05200320063a00cb05200320173a00ca052003200b3b01c8052003200e3a00c705200320203a00c605200320223b01c405200320233a00c305200320243a00c205200320253b01c005200341e0056a200341d8086a200341c0056a10920120033502e80542208620032802e0052202ad841005024020032802e405450d002002102f0b20034185066a20032903d808370000200341ed056a200341b8086a41086a290300370000200341f5056a200341b8086a41106a290300370000200341fd056a200341b8086a41186a2903003700002003418d066a200341d8086a41086a29030037000020034195066a200341d8086a41106a2903003700002003419d066a200341d8086a41186a290300370000200341043a00e405200341013a00e005200320032903b8083700e505200341ac066a201d360200200341a8066a201e360200200341b0066a2003290340370300200341b8066a200341c0006a41086a2802003602004100210241c8e1ca004100200341e0056a108c0120032802ac03450d0020032802a803102f0b200041043a000002402021450d002013102f0b2002450d07200c108e010c070b200341e0056a41186a200341b8086a41186a290300370300200341e0056a41106a200341b8086a41106a290300370300200341e0056a41086a200341b8086a41086a290300370300200320032903b8083703e00520152002490d01024020152012470d00201241016a220a2012490d0320124101742214200a2014200a4b1b220a41ffffff3f71200a470d03200a410574220a4100480d030240024020120d00200a102d21080c010b20082012410574200a103121080b2008450d01200320083602a8032003200a4105763602ac030b200820024105746a220a41206a200a201520026b41057410e9061a200a41186a200341e0056a41186a290300370000200a41106a200341e0056a41106a290300370000200a41086a200341e0056a41086a290300370000200a20032903e0053700002003201541016a3602b003200341e0056a20034190036a41c80010e8061a2003201a3703d805200320183a00d7052003200d3a00d6052003200f3b01d405200320103a00d305200320073a00d205200320043b01d005200320053a00cf05200320163a00ce05200320113b01cc05200320063a00cb05200320173a00ca052003200b3b01c8052003200e3a00c705200320203a00c605200320223b01c405200320233a00c305200320243a00c205200320253b01c005200341e0006a200341d8086a200341c0056a1092012003280260210220032003280268360294082003200236029008200341e0056a20034190086a10860102402003280264450d002002102f0b0240200341fc056a280200450d0020032802f805102f0b20034185066a20032903d808370000200341ed056a200341b8086a41086a290300370000200341f5056a200341b8086a41106a290300370000200341fd056a200341b8086a41186a2903003700002003418d066a200341d8086a41086a29030037000020034195066a200341d8086a41106a2903003700002003419d066a200341d8086a41186a290300370000200341033a00e405200341013a00e005200320032903b8083700e505200341ac066a201d360200200341a8066a201e36020041c8e1ca004100200341e0056a108c01200041043a00000c040b1036000b419ae3c300411e41f8b4ca001039000b1038000b20004183023b0100200041086a2014360200200041046a2019360200200041026a201f3a00002012450d002008102f0b2021450d002013102f0b200c108e010b200c102f410021084101210241012114410121090c020b20004183023b0100200041086a2002360200200041046a2008360200200041026a20093a00000b200c108e01200c102f41002108410121020240200a0d0041012114410121090c010b2014102f41012114410121090b4101210a0c020b0240200a200c460d000340200c108d01200a200c41b0026a220c470d000b0b0240200b450d002007102f0b200341013a00e405200341013a00e00541c8e1ca004100200341e0056a108c01200041043a00000b4100210a410121024101210841012114410121090b024020012d0000417f6a220c41044b0d0002400240024002400240200c0e050001020304000b200a450d0402402001410c6a2802002202450d00200141046a280200210c200241b0026c21020340200c108d01200c41b0026a210c200241d07d6a22020d000b0b200141086a280200450d042001280204102f0c040b2002450d03200141046a220c280200108e01200c280200102f0c030b2008450d020240200141086a280200450d00200141046a280200102f0b2001411c6a220c280200108e01200c280200102f0c020b2014450d01200141286a280200450d01200141246a280200102f0c010b2009450d00200141286a280200450d00200141246a280200102f0b200341b0096a24000bb3b10309057f017e137f047e017f047e057f077e087f230041b00b6b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802000e1b020301040506070b0c0d0e0f1011121314151617010101181a1900020b200341f0056a41086a2204200141146a290200370300200341f0056a41106a22052001411c6a290200370300200341f0056a41186a2206200141246a290200370300200341f0056a41206a22072001412c6a28020036020020032001410c6a2902003703f0052002411a6a2901002108200241196a2d00002109200241186a2d0000210a200241166a2f0100210b200241156a2d0000210c200241146a2d0000210d200241126a2f0100210e200241116a2d0000210f200241106a2d000021102002410e6a2f010021112002410d6a2d000021122002410c6a2d000021132002410a6a2f01002114200241096a2d00002115200241086a2d00002116200241066a2f01002117200241056a2d00002118200241046a2d00002119200241026a2f0100211a20022d0001211b20022d000021020240024002400240200141086a2802000e0400010203000b20034180096a41146a41013602002003420137028409200341b4d8c90036028009200341043602fc06200341fcdbc9003602f8062003200341f8066a3602900920034180096a41e8d8c9001043000b2003200837038804200320093a0087042003200a3a0086042003200b3b0184042003200c3a0083042003200d3a0082042003200e3b0180042003200f3a00ff03200320103a00fe03200320113b01fc03200320123a00fb03200320133a00fa03200320143b01f803200320153a00f703200320163a00f603200320173b01f403200320183a00f303200320193a00f2032003201a3b01f003410121040240201b41ff01714101470d00200241ff01710d0020034188026a41186a200341f0036a41186a290300220837030020034188026a41106a200341f0036a41106a290300221c37030020034188026a41086a200341f0036a41086a290300221d370300200320032903f003221e3703880220034180096a41186a200837030020034180096a41106a201c37030020034180096a41086a201d3703002003201e37038009200020034180096a10ae014101211b0c5a0b200041023a00004101211b410121050c700b200341f8076a41206a2007280200360200200341f8076a41186a2006290300370300200341f8076a41106a2005290300370300200341f8076a41086a2004290300370300200320032903f0053703f807200241ff01710d1b201b41ff01714101470d1b20034180096a41206a200341f8076a41206a28020036020020034180096a41186a200341f8076a41186a29030037030020034180096a41106a200341f8076a41106a29030037030020034180096a41086a200341f8076a41086a290300370300200320032903f80737038009200341f8066a20034180096a10bb01200341f0036a41086a220220034181076a290000370300200341f0036a41106a221b20034189076a290000370300200341f0036a41186a220420034191076a290000370300200320032900f9063703f00320032d00f8064101460d08200341f0046a41186a2004290300370300200341f0046a41106a201b290300370300200341f0046a41086a2002290300370300200320032903f0033703f0042000200341f0046a10ae014101211b0c580b200141c8006a290300211e200141c0006a290300211f200141386a290300211c200141306a290300211d200141d0006a2802002120200341f8076a41206a2007280200360200200341f8076a41186a2006290300370300200341f8076a41106a2005290300370300200341f8076a41086a2004290300370300200320032903f0053703f807200241ff01710d1b201b41ff01714101470d1b200320083703e802200320093a00e7022003200a3a00e6022003200b3b01e4022003200c3a00e3022003200d3a00e2022003200e3b01e0022003200f3a00df02200320103a00de02200320113b01dc02200320123a00db02200320133a00da02200320143b01d802200320153a00d702200320163a00d602200320173b01d402200320183a00d302200320193a00d2022003201a3b01d002201d42808084fea6dee111544100201c501b0d1c20034180096a41206a200341f8076a41206a28020036020020034180096a41186a200341f8076a41186a29030037030020034180096a41106a200341f8076a41106a29030037030020034180096a41086a200341f8076a41086a290300370300200320032903f80737038009200341f8066a20034180096a10bb0120034188026a41086a220220034181076a29000037030020034188026a41106a220420034189076a29000037030020034188026a41186a220520034191076a290000370300200320032900f906370388024101211b20032d00f8064101460d08200341f0046a41186a2005290300370300200341f0046a41106a2004290300370300200341f0046a41086a200229030037030020032003290388023703f00441adc5c300ad4280808080f00084220810012202290008212120022d0007210420022d0006210520022f0004210620022d0003210720022d0002210920022f0000210a2002102f2008100122022900002108200341a8026a41086a200241086a290000370300200320083703a8022002102f4120102d2202450d63200220032903f004370000200241186a200341f0046a41186a290300370000200241106a200341f0046a41106a290300370000200241086a200341f0046a41086a2903003700002002ad42808080808004841003221b2900002108201b41086a2900002122201b41106a2900002123200341f0036a41186a220b201b41186a290000370300200341f0036a41106a220c2023370300200341f0036a41086a220d2022370300200320083703f003201b102f2002102f41c000102d2202450d63200220043a0007200220053a0006200220063b0004200220073a0003200220093a00022002200a3b000020022021370008200220032903a802370010200241186a200341a8026a41086a290300370000200220032903f003370020200241286a200d290300370000200241306a200c290300370000200241386a200b290300370000200341d8016a200241c00041c8e1ca004100410010b50120032802d80121042002102f4101211b20044101460d1d20034180096a200341d0026a200341f0046a201d201c410110f20220032003290081093703f003200320034180096a41086a2800003600f703024020032d00800922024104470d0041adc5c300ad4280808080f000842208100122022900002121200341a8026a41086a200241086a290000370300200320213703a8022002102f2008100122022d000f210420022d000e210520022f000c210620022d000b210720022d000a210920022f0008210a20022d0007210b20022d0006210c20022f0004210d20022d0003210e20022d0002210f20022f000021102002102f4120102d2202450d64200220032903f004370000200241186a200341f0046a41186a290300370000200241106a200341f0046a41106a290300370000200241086a200341f0046a41086a2903003700002002ad42808080808004841003221b2900002108201b41086a2900002121201b41106a290000212220034188026a41186a2211201b41186a29000037030020034188026a41106a2212202237030020034188026a41086a221320213703002003200837038802201b102f2002102f41c000102d2202450d64200220032903a802370000200241086a200341a8026a41086a2903003700002002200b3a00172002200c3a00162002200d3b00142002200e3a00132002200f3a0012200220103b0010200220043a001f200220053a001e200220063b001c200220073a001b200220093a001a2002200a3b00182002200329038802370020200241286a2013290300370000200241306a2012290300370000200241386a2011290300370000200341d0016a200241c00041c8e1ca004100410010b50120032802d001211b2002102f0240201b4101460d0041adc5c300ad4280808080f00084220810012202290000212120034188026a41086a200241086a29000037030020032021370388022002102f2008100122022900002108200341b8026a41086a200241086a290000370300200320083703b8022002102f4120102d2202450d65200220032903f004370000200241186a200341f0046a41186a290300370000200241106a200341f0046a41106a290300370000200241086a200341f0046a41086a2903003700002002ad42808080808004841003221b2900002108201b41086a2900002121201b41106a2900002122200341f0036a41186a2204201b41186a290000370300200341f0036a41106a22052022370300200341f0036a41086a2021370300200320083703f003201b102f2002102f41c000102d2202450d652002200329038802370000200241086a20034188026a41086a290300370000200220032903b802370010200241186a200341b8026a41086a290300370000200220032903f003370020200241286a200341f0036a41086a290300370000200241306a2005290300370000200241386a20042903003700004110102d221b450d65201b201d370000201b201c370008201b411041201031221b450d65201b201f370010201b41186a201e370000201b412041c0001031221b450d65201b20203600202002ad4280808080800884201bad4280808080c004841004201b102f2002102f20034180096a41186a200341f0046a41186a29030037030020034180096a41106a200341f0046a41106a29030037030020034180096a41086a200341f0046a41086a290300370300200320032903f00437038009200341f8066a20034180096a10ae01200041043a00004101211b0c590b20034188096a4117360200200341e6b4c60036028409200341013a00820920034183363b01800941a8c3c100413720034180096a41e0c3c10041f0c3c100103e000b200020023a0000200020032903f003370001200041086a20032800f7033600004101211b0c570b000b200141106a29030021082001410c6a280200211520022d0001210420022d0000211b0240024002400240024002400240024002400240200141086a2802002205417f6a0e0a00010203040506070809000b02402004201b41ff01714100477241ff01710d00200041043a00004101211b0c750b200041023a00004101211b0c740b2008a721020240201b41ff01710d004101211b200441ff01714101470d00200041043a00002002450d740c730b200041023a00004101211b20020d720c730b02402004201b41ff01714100477241ff01710d004108102d2202450d692002200837000041bfa9c400ad4280808080a001842002ad428080808080018410042002102f200041043a00004101211b0c730b200041023a00004101211b0c720b2008a72102024002402004201b41ff01714100477241ff01710d0020034180096a2008428080808070832015ad84221c10121073200328028009221b450d6f2003280284092104200320034188096a2802003602f4052003201b3602f005200341106a200341f0056a10e60120032802100d6e20032802f405220920032802142206490d6e2006417f4c0d240240024020060d00410121070c010b200610332207450d6a200720032802f005220a200610e8061a2003200920066b3602f4052003200a20066a3602f0050b2007450d6e200341086a200341f0056a10e6012006ad221d422086201d84221da7210620032802080d6c20032802f405220a200328020c2209490d6c2009417f4c0d240240024020090d004101210b0c010b20091033220b450d6a200b20032802f005220c200910e8061a2003200a20096b220a3602f4052003200c20096a3602f0050b200b450d6c2009ad221e422086201e84a721090240024002400240200a4104490d00200320032802f005220c41046a3602f0052003200a417c6a220d3602f405200d4104490d012003200c41086a3602f005200c28000421162003200a41786a220d3602f405200d4104490d032003200a41746a3602f4052003200c410c6a3602f005200c28000821172003200341f0056a10e6012003280200450d020c6f0b02402009450d00200b102f0b20060d700c710b02402009450d00200b102f0b20060d6f0c700b2003280204221420032802f405410c6e220a200a20144b1b2213ad420c7e221e422088a70d25201ea7220a417f4c0d2502400240200a0d004104210f0c010b200a102d220f450d6b200a410c6e21130b024002402014450d004100210e4100210d4100210c0340200341f8076a200341f0056a10f30220032d00f8074101460d0220032802f40522104104490d02200c41016a210a20032900f907211e20032802f0052211280000211220032010417c6a3602f4052003201141046a3602f0050240200c2013470d00200e200a200e200a4b1bad420c7e221f422088a70d58201fa722104100480d5802400240200c0d002010102d210f0c010b200f200d20101031210f0b200f450d6e2010410c6e21130b200f200d6a220c201e370200200c41086a2012360200200e41026a210e200d410c6a210d200a210c2014200a470d000b0b200f450d6d201d422088a7210c02402004450d00201b102f0b410f211b41f1e4c30021044100210a200c4104470d6c2007418ca9c300460d03200728000041eede91ab06460d030c6c0b2013450d6c200f102f0c6c0b02402009450d00200b102f0b2006450d6e0c6d0b200041023a00000c6f0b411f211b0240201641e7014f0d0041d2e4c30021044101210a0c690b0240201641e701470d0020170d004194e4c30021044103210a0c690b41c9a9c400ad4280808080d00084201c1004200341f0036a41186a4200370300200341f0036a41106a220a4200370300200341f0036a41086a221b4200370300200342003703f003418de6c300ad4280808080e0008410012204290000211c200341b8026a41086a220c200441086a2900003703002003201c3703b8022004102f201b200c290300370300200320032903b8023703f00341f883c400ad4280808080f0018410012204290000211c200341a8026a41086a220c200441086a2900003703002003201c3703a8022004102f200a20032903a802221c37030020034188026a41086a201b29030037030020034188026a41106a201c37030020034188026a41186a200c290300370300200320032903f00337038802200341013a00800920034188026aad428080808080048420034180096aad428080808010841004200341003a008009200341023a00840941c8e1ca00410020034180096a108c0102402006450d002007102f0b02402009450d00200b102f0b02402013450d00200f102f0b200041043a00000c6e0b2008a7210202402004201b41ff01714100477241ff01710d0041c9a9c400ad4280808080d000842008428080808070832015ad841004200341f0036a41186a4200370300200341f0036a41106a22054200370300200341f0036a41086a221b4200370300200342003703f003418de6c300ad4280808080e00084100122042900002108200341b8026a41086a2206200441086a290000370300200320083703b8022004102f201b2006290300370300200320032903b8023703f00341f883c400ad4280808080f00184100122042900002108200341a8026a41086a2206200441086a290000370300200320083703a8022004102f200520032903a802220837030020034188026a41086a201b29030037030020034188026a41106a200837030020034188026a41186a2006290300370300200320032903f003370388024101211b200341013a00800920034188026aad428080808080048420034180096aad428080808010841004200341003a008009200341023a00840941c8e1ca00410020034180096a108c01200041043a000020020d700c710b200041023a00004101211b20020d6f0c700b2004201b41ff01714100477241ff01710d212008422088a721042008a721070240024020154101460d0041cea9c400ad4280808080d0018410050c010b4104102d2202450d662002200736000020024104410810312202450d662002200436000441cea9c400ad4280808080d001842002ad428080808080018410042002102f0b4200211c200341f0036a41186a4200370300200341f0036a41106a22064200370300200341f0036a41086a22024200370300200342003703f003418de6c300ad4280808080e000841001221b290000211d2002201b41086a2900003703002003201d3703f003201b102f41bae6c300ad4280808080e000841001221b290000211d200341a8026a41086a2209201b41086a2900003703002003201d3703a802201b102f200620032903a802221d37030020034188026a41086a200229030037030020034188026a41106a201d37030020034188026a41186a2009290300370300200320032903f0033703880220034180096a20034188026a10f4020240024020032802800922060d0041002102410421064100211b0c010b200329028409221c422088a7211b201ca721020b200341f8076a41026a200341f0056a41026a2d00003a0000200341f0046a41086a20034180096a41086a290200370300200341f0046a41106a20034180096a41106a280200360200200320032f00f0053b01f80720032003290280093703f00402400240201b2002460d00201c422088211d0c010b02402002201ca7470d00200241016a221b2002490d5120024101742209201b2009201b4b1bad42247e221d422088a70d51201da7221b4100480d510240024020020d00201b102d21060c010b2006200241246c201b103121060b2006450d67201c42808080807083201b41246ead84211c0b201c422088221da7211b0b2006201b41246c6a220241043a00002002200436020c2002200736020820022015360204200220032f01f8073b0001200241036a200341fa076a2d00003a0000200220032903f004370210200241186a200341f0046a41086a290300370200200241206a200341f0046a41106a280200360200200341f0036a41186a4200370300200341f0036a41106a22044200370300200341f0036a41086a22024200370300200342003703f003418de6c300ad4280808080e000841001221b290000211e200341b8026a41086a2207201b41086a2900003703002003201e3703b802201b102f20022007290300370300200320032903b8023703f00341bae6c300ad4280808080e000841001221b290000211e200341a8026a41086a2207201b41086a2900003703002003201e3703a802201b102f200420032903a802221e37030020034188026a41086a200229030037030020034188026a41106a201e37030020034188026a41186a2007290300370300200320032903f00337038802200341203602fc07200320034188026a3602f8072006201da7220241016a221b200341f8076a10f5020240201b2002490d00200241246c41246a211b2006210203400240024020022d0000220441044b0d0002400240024020040e050400010204040b2002410c6a280200450d03200241086a280200102f0c030b2002410c6a280200450d02200241086a280200102f0c020b2002410c6a280200450d01200241086a280200102f0c010b200241086a280200450d00200241046a280200102f0b200241246a2102201b415c6a221b0d000b0b0240201ca7450d002006102f0b200041043a00004101211741002116410121180c6d0b2008422088a7210b2008a7210c024002402004201b41ff01714100477241ff01710d000240200b41186c2202450d00201520026a210620034180096aad42808080801084211d20034188026aad4280808080800484211e200341f0036a41106a2104201521020340200241086a221b350200422086200235020084200241146a3502004220862002410c6a3502008410040240201b2802004105470d0002402002280200221b41c9a9c400460d00201b41c9a9c400410510ea060d010b200341f0036a41186a2209420037030020044200370300200341f0036a41086a221b4200370300200342003703f003418de6c300ad4280808080e0008410012207290000211c200341b8026a41086a220a200741086a2900003703002003201c3703b8022007102f201b200a290300370300200320032903b8023703f00341f883c400ad4280808080f0018410012207290000211c200341a8026a41086a220a200741086a2900003703002003201c3703a8022007102f200420032903a802370000200441086a200a29030037000020034188026a41086a201b29030037030020034188026a41106a200429030037030020034188026a41186a2009290300370300200320032903f00337038802200341013a008009201e201d10040b200241186a22022006470d000b0b200041043a0000200b450d01200b41186c21002015210203400240200241046a280200450d002002280200102f0b0240200241106a280200450d002002410c6a280200102f0b200241186a2102200041686a22000d000c020b0b200041023a0000200b450d00200b41186c21002015210203400240200241046a280200450d002002280200102f0b0240200241106a280200450d002002410c6a280200102f0b200241186a2102200041686a22000d000b0b41012118410021160240200c450d002015102f0b410021170c6c0b2008422088a721062008a72107024002402004201b41ff01714100477241ff01710d0002402006410c6c2202450d00201520026a211b201521020340200241086a35020042208620023502008410052002410c6a2202201b470d000b0b200041043a00002006450d012006410c6c21002015210203400240200241046a280200450d002002280200102f0b2002410c6a2102200041746a22000d000c020b0b200041023a00002006450d002006410c6c21002015210203400240200241046a280200450d002002280200102f0b2002410c6a2102200041746a22000d000b0b410121174100211602402007450d002015102f0b410021180c6b0b2008a72102024002402004201b41ff01714100477241ff01710d002008428080808070832015ad841013200041043a00000c010b200041023a00000b4101211b20020d6b0c6c0b02400240201b41ff01710d00200441ff01714101470d002002411a6a2901002108200241196a2d00002104200241186a2d00002105200241166a2f01002106200241156a2d00002107200241146a2d00002109200241126a2f0100210a200241116a2d0000210b200241106a2d0000210c2002410e6a2f0100210d2002410d6a2d0000210e2002410c6a2d0000210f2002410a6a2f01002110200241096a2d00002111200241086a2d00002112200241066a2f01002113200241056a2d00002114200241046a2d00002115200241026a2f01002116418de6c300ad4280808080e0008410012202290000211c200341b8026a41086a200241086a2900003703002003201c3703b8022002102f41f0e8c600ad4280808080f0008410012202290000211c200341a8026a41086a200241086a2900003703002003201c3703a8022002102f4120102d2202450d6320022008370018200220043a0017200220053a0016200220063b0014200220073a0013200220093a00122002200a3b00102002200b3a000f2002200c3a000e2002200d3b000c2002200e3a000b2002200f3a000a200220103b0008200220113a0007200220123a0006200220133b0004200220143a0003200220153a0002200220163b00002002ad42808080808004841003221b290000211c201b41086a290000211d201b41106a290000211e200341f0036a41186a2217201b41186a290000370300200341f0036a41106a2218201e370300200341f0036a41086a201d3703002003201c3703f003201b102f2002102f41c000102d2202450d63200220032903b802370000200241086a200341b8026a41086a290300370000200220032903a802370010200241186a200341a8026a41086a290300370000200220032903f003370020200241286a200341f0036a41086a290300370000200241306a2018290300370000200241386a201729030037000020034180096a200210f6022003290380094201510d012002102f4200211c4200211d4200211e4200211f420021214200212242002123420021240c600b200041023a00004101211b0c6c0b20034190096a290300211d200341a0096a290300212420034198096a290300212320034180096a41306a290300212220034180096a41286a2903002121200341c0096a290300211f20034180096a41386a290300211e200329038809211c20032d00cc09211b2002102f201b450d5e410f210241d5e3c300211b410621040c5f0b200341b8096a2001413c6a280200360200200341b0096a200141346a290200370300200341a8096a2001412c6a29020037030020034180096a41206a200141246a29020037030020034180096a41186a2001411c6a29020037030020034180096a41106a200141146a29020037030020034180096a41086a2001410c6a2902003703002003200129020437038009200341f8076a41206a200241206a290200370300200341f8076a41186a200241186a290200370300200341f8076a41106a200241106a290200370300200341f8076a41086a200241086a290200370300200320022902003703f807200020034180096a200341f8076a108a014100211b410121050c5c0b20022d00000d1c20022d000141ff01714102470d1c200141086a2903002108200341f0036a41186a22054200370300200341f0036a41106a22024200370300200341f0036a41086a221b4200370300200342003703f00341d5a2ca00ad4280808080900184221c10012204290000211d2004290008211e2004102f201b201e3703002003201d3703f00341dea2ca00ad428080808090018410012206290000211d200341a8026a41086a2204200641086a2900003703002003201d3703a8022006102f200220032903a802221d37030020034188026a41086a2207201b29030037030020034188026a41106a2209201d37030020034188026a41186a220a2004290300370300200320032903f00337038802200341386a20034188026a412041c8e1ca004100410010b50120032802384101460d1d2005420037030020024200370300201b4200370300200342003703f003201c10012206290000211c2006290008211d2006102f201b201d3703002003201c3703f00341ecb0c000ad42808080803084221c10012206290000211d2004200641086a2900003703002003201d3703a8022006102f200220032903a802370000200241086a20042903003700002007201b29030037030020092002290300370300200a2005290300370300200320032903f00337038802200341286a20034188026a10e301024002402003290330500d002003280228450d00200341f0036a41186a22054200370300200341f0036a41106a22064200370300200341f0036a41086a221b4200370300200342003703f00341d5a2ca00ad428080808090018410012204290000211d2004290008211e2004102f201b201e3703002003201d3703f00341ecb0c000ad4280808080308410012204290000211d200341a8026a41086a2207200441086a2900003703002003201d3703a8022004102f200220032903a802370000200241086a200729030037000020034188026a41086a201b29030037030020034188026a41106a200629030037030020034188026a41186a2005290300370300200320032903f00337038802200341186a20034188026a10e301200329032042dc0b7c42dc0b20032802181b2008560d010b200341f0036a41186a22044200370300200341f0036a41106a22054200370300200341f0036a41086a221b4200370300200342003703f00341d5a2ca00ad4280808080900184221d10012206290000211e2006290008211f2006102f201b201f3703002003201e3703f003201c10012207290000211c200341a8026a41086a2206200741086a2900003703002003201c3703a8022007102f200220032903a802370000200241086a2209200629030037000020034188026a41086a220a201b29030037030020034188026a41106a220b200529030037030020034188026a41186a220c2004290300370300200320032903f00337038802200320083703800920034188026aad4280808080800484220820034180096aad221c428080808080018410042004420037030020054200370300201b4200370300200342003703f003201d10012207290000211d2007290008211e2007102f201b201e3703002003201d3703f00341dea2ca00ad428080808090018410012207290000211d2006200741086a2900003703002003201d3703a8022007102f200220032903a80237000020092006290300370000200a201b290300370300200b2005290300370300200c2004290300370300200320032903f0033703880241012104200341013a0080092008201c428080808010841004200041043a00004101211b410121050c6b0b41e5e4c00041ce0041f8b4ca001039000b2001410c6a2802002107200141086a280200210c2001280204210a024002400240024020022d00000d0020022d000141ff01714102470d002007410a4b0d02200341f0036a41186a22044200370300200341f0036a41106a22124200370300200341f0036a41086a22024200370300200342003703f003419487ca00ad4280808080a00184221d1001221b2900002108201b290008211c201b102f2002201c370300200320083703f003419e87ca00ad4280808080c00184221e1001221b2900082108201b290000211c201b102f20034188026a41106a221b201c37030020034188026a41186a2205200837030020034188026a41086a22062002290300370300200320032903f0033703880220034188026a10f702220941ff01714102460d032009410171450d0320004183083b0100200041086a4110360200200041046a41a087c700360200200041026a41013a00000c010b200041023a00000b2007450d5b0c5a0b20004183083b0100200041086a410d360200200041046a419387c700360200200041026a41023a00000c590b200442003703002012420037030020024200370300200342003703f003201d1001220929000021082009290008211c2009102f2002201c370300200320083703f003201e1001220929000821082009290000211c2009102f201b201c3703002005200837030020062002290300370300200320032903f00337038802200341013a00800920034188026aad4280808080800484221e20034180096aad428080808010841004200442003703002012420037030020024200370300200342003703f003418de6c300ad4280808080e000841001220429000021082002200441086a290000370300200320083703f0032004102f419ce6c300ad4280808080e00084100122042900002108200341a8026a41086a2209200441086a290000370300200320083703a8022004102f201220032903a802220837030020062002290300370300201b200837030020052009290300370300200320032903f00337038802200341c8006a20034188026a412010950120032802482104200328024c2105200341b8026a10f802024020032802c002221b20032802bc022211470d00201b41016a2202201b490d49201b41017422062002200620024b1bad42c4007e2208422088a70d492008a722024100480d4902400240201b0d002002102d21060c010b20032802b802201b41c4006c2002103121060b2006450d5f200320063602b8022003200241c4006e22113602bc020b20032802b802220d201b41c4006c22096a220241003a0000200220032f00f8073b000120022005410020041b3602042002200329028009370208200241036a200341f8076a41026a2d00003a0000200241106a20034180096a41086a2225290200370200200241186a20034180096a41106a2226290200370200200241206a20034180096a41186a290200370200200241286a20034180096a41206a290200370200200241306a20034180096a41286a290200370200200241386a20034180096a41306a290200370200200241c0006a20034180096a41386a2802003602002003201b41016a220f3602c002200a200741f0006c22026a2127024020070d00200a21050c550b200a41f4006a2106200941c4006a2118200241907f6a2109418de6c300ad4280808080e00084211d200a210503402005280204210e2005280200210420034180096a200541086a41e80010e8061a200541f0006a2105200e450d55200341f8076a20034180096a41e80010e8061a2003200e3602840920032004360280092025200341f8076a41e80010e8061a200341f0036a41186a22134200370300200341f0036a41106a22144200370300200341f0036a41086a22104200370300200342003703f003201d1001220229000021082010200241086a290000370300200320083703f0032002102f419ce6c300ad4280808080e00084100122022900002108200341a8026a41086a221b200241086a290000370300200320083703a8022002102f201220032903a802370000201241086a201b29030037000020034188026a41086a2215201029030037030020034188026a41106a2216201429030037030020034188026a41186a22172013290300370300200320032903f00337038802200341c0006a20034188026a4120109501200328024021022003280244210b200341f8066a20034180096a10f902410c211b024020040d00418787c70021044103211a0c550b02402004200b410020021b22024d0d0041fb86c70021044104211a0c550b200341f0056a2004417f6a10fa020240200341f0056a2026412010ea06450d004112211b41b087c70021044100211a0c550b0240200441002002417b6a221b201b20024b1b4f0d004108211b41df86c70021044106211a0c550b02400240200d200d200f41c4006c22196a460d00200d41016a21022018211b034002402002417f6a2d00004101470d004101210b200341f8066a2002460d032002200341f8066a412010ea06450d030b200241c4006a2102201b41bc7f6a221b0d000b0b4100210b0b200341f0056a200410fa02200341f0056a200341f8066a412010ea0621024114211b41e786c70021044105211a200b0d542002450d54200341e0016a41086a221a200341f0046a41086a221b290200370300200341e0016a41106a2220200341f0046a41106a22042f01003b0100200320032902f0043703e001200341f8066a20034180096a10f902200341d0036a41186a220b4200370300200341d0036a41106a22284200370300200341d0036a41086a22294200370300200342003703d003201742003703002016420037030020154200370300200342003703880241c800102d2202450d5f200341f0036a10fb02200241186a2013290300370200200241106a2014290300370200200241086a2010290300370200200220032903f003370200200241023602202002410136024420022003290388023700242002412c6a2015290300370000200241346a20162903003700002002413c6a2017290300370000200320023602f00520034282808080203702f405200341f0056a10fc02200341f0056a41186a200b290300370300200341f0056a41106a220b2028290300370300200341f0056a41086a22102029290300370300200320032903d0033703f005200341f0056a10fd02201b200341f8066a41086a2903003703002004200341f8066a41106a290300370300200341f0046a41186a2213200341f8066a41186a2903003703002010201a290300370300200b20202f01003b0100200320032903f8063703f004200320032903e0013703f0050240200f2011470d0020112011470d00201141016a22022011490d4a201141017422142002201420024b1bad42c4007e2208422088a70d4a2008a722024100480d4a0240024020110d002002102d210d0c010b200d201141c4006c20021031210d0b200d450d602003200d3602b8022003200241c4006e22113602bc020b200d20196a220241013a0000200241096a201b290300370000200220032903f004370001201329030021082004290300211c200241003a0021200241116a201c370000200241196a2008370000200220032903f005370030200241c0006a200b2f01003b0000200241386a20102903003700002003200f41016a220f3602c0020240200328028c092202450d00200241246c211b200e210203400240024020022d0000220441044b0d0002400240024020040e050400010204040b2002410c6a280200450d03200241086a280200102f0c030b2002410c6a280200450d02200241086a280200102f0c020b2002410c6a280200450d01200241086a280200102f0c010b200241086a280200450d00200241046a280200102f0b200241246a2102201b415c6a221b0d000b0b0240200328028809450d00200e102f0b201841c4006a2118200941907f6a2109200641f0006a210620052027470d000c560b0b200141156a29000021082001410d6a290000211c2002411a6a290100211f200241196a2d00002104200241186a2d00002105200241166a2f01002106200241156a2d00002107200241146a2d00002109200241126a2f0100210a200241116a2d0000210b200241106a2d0000210c2002410e6a2f0100210d2002410d6a2d0000210e2002410c6a2d0000210f2002410a6a2f01002110200241096a2d00002111200241086a2d00002112200241066a2f01002113200241056a2d00002114200241046a2d00002115200241026a2f01002116200141286a28020021182001411d6a290000211d200141056a290000221e421888a7211720022d0001211b20022d000021020240024002400240024020012d00040e050001020304000b20034180096a41146a41013602002003420137028409200341b4d8c90036028009200341043602fc06200341fcdbc9003602f8062003200341f8066a3602900920034180096a41e8d8c9001043000b200241ff01710d1f201b41ff01714101470d1f2003201f37039007200320043a008f07200320053a008e07200320063b018c07200320073a008b07200320093a008a072003200a3b0188072003200b3a0087072003200c3a0086072003200d3b0184072003200e3a0083072003200f3a008207200320103b018007200320113a00ff06200320123a00fe06200320133b01fc06200320143a00fb06200320153a00fa06200320163b01f806200341f0036a201710fe0220034180096a20032802f003220420032802f803220b10ff02200341f8076a41086a220220034180096a41106a290300370300200341f8076a41106a221b20034180096a41186a290300370300200341f8076a41186a2205200341a0096a29030037030020032003290388093703f80702402003290380094201510d00200341f0056a41086a200341f8066a41086a290300370300200341f0056a41106a200341f8066a41106a290300370300200341f0056a41186a200341f8066a41186a290300370300200320032903f8063703f005200342003703f8042003428080e983b1de163703f0042003200341f8066a3602e0012003200341f8066a3602d0022003200341d0026a360288092003200341e0016a360284092003200341f0046a36028009200341f8076a200341f8066a20034180096a109401024020032802f8074101470d0020034184086a280200210520034180086a280200210620032d00ff07210720032d00fe07210920032d00fd07210a20032d00fc0721020c540b410421020240200341f8076a41086a2903004201510d000c540b200341f8076a41106a290300210820032802d002211b200341b8096a200341f8076a41186a290300370300200341b0096a200837030020034180096a41086a41003a000020034189096a201b29000037000020034191096a201b41086a29000037000020034199096a201b41106a290000370000200341a1096a201b41186a290000370000200341033a00800941c8e1ca00410020034180096a108c010c530b200341f0056a41186a2005290300370300200341f0056a41106a201b290300370300200341f0056a41086a2002290300370300200320032903f8073703f0054105210a4183d9c900210641022109410321024100211b410521050c530b200341f0056a41106a20083703002003201e3703f0052003201d370388062003201c3703f805200241ff01710d1f201b41ff01714101470d1f2003201f37039008200320043a008f08200320053a008e08200320063b018c08200320073a008b08200320093a008a082003200a3b0188082003200b3a0087082003200c3a0086082003200d3b0184082003200e3a0083082003200f3a008208200320103b018008200320113a00ff07200320123a00fe07200320133b01fc07200320143a00fb07200320153a00fa07200320163b01f807200341f8076a200341f0056a412010ea06450d21200341f0046a201810fe0220034180096a20032802f004221b20032802f804220a10ff02410321024105210402402003290380094201510d00410021054190d9c9002106410b21070c510b200341b0096a2903002108200341a8096a290300211c20034190096a2205290300211e20034180096a41206a290300211d200329038809211f200520034198096a2903003703002003201d370398092003201f370380092003201e3703880920034180096a200341f8076a412010ea060d20200341f8066a200341f8076a200341f0056a201c2008410110bc01200341f8066a41086a290300211e0240024020032802f8064101460d0042002008200341f8066a41106a2903007d201c201e54ad7d221d201c201e7d221e201c56201d200856201d2008511b22021b21084200201e20021b211c200341f0056a41106a290300211f20032903f805212120032903f0052122200329038806211d4201211e0c010b20032802fc06220241187621092002411076210520024108762104201e422088a72107201ea72106200241ff01714104470d514200211e0b200341b0096a2008370300200341a8096a201c370300200341a0096a201d3703002003201e3703800920034198096a201f3703002003202237038809200320213703900902400240201e4201510d00200aad422086201bad8410050c010b4110102d2202450d6020024110412010312202450d60200220034188096a220b290000370000200241186a200b41186a290000370000200241106a200b41106a290000370000200241086a200b41086a2900003700002002412041c00010312202450d602002201c370020200241286a2008370000200aad422086201bad842002ad428080808080068410042002102f0b410421020c500b200241ff01710d22201b41ff01714101470d222003201f37039007200320043a008f07200320053a008e07200320063b018c07200320073a008b07200320093a008a072003200a3b0188072003200b3a0087072003200c3a0086072003200d3b0184072003200e3a0083072003200f3a008207200320103b018007200320113a00ff06200320123a00fe06200320133b01fc06200320143a00fb06200320153a00fa06200320163b01f806200341f0036a201710fe0220034180096a20032802f003221b20032802f803220410ff024103210202402003290380094201510d00410021044190d9c9002105410b21060c4f0b200341b0096a290300211e200341a8096a290300211f20034180096a41106a290300210820034180096a41206a290300211c200329038809211d200341f0056a41106a20034198096a2903003703002003201c370388062003201d3703f005200320083703f805200341f0056a200341f8066a412010ea060d212003201f3703f0042003201e3703f8040240201f201e84500d002003200341f8066a3602d002200341f8076a200341f8066a200341f0046a200341d0026a10960120032903f8074201520d002003290380082108200341b8096a200341f8076a41106a290300370300200341b0096a200837030020034180096a41086a41003a000020034189096a20032903f80637000020034191096a200341f8066a41086a29030037000020034199096a200341f8066a41106a290300370000200341a1096a20034190076a290300370000200341033a00800941c8e1ca00410020034180096a108c010b2004ad422086201bad841005410421020c4e0b0240201b200241ff01714100477241ff01710d00200341f0046a201810fe0220034180096a20032802f004220420032802f804220710ff02200341b0096a2102200341a8096a211b20034198096a2105200341a0096a210602402003290380094201520d002002290300211f201b290300212120034180096a41106a2903002122200629030021232003290388092124200341f0056a41106a20052903003703002003202337038806200320243703f005200320223703f805200320213703f8062003201f370380072021201f84500d002003200341f0056a3602f003200341f8076a200341f0056a200341f8066a200341f0036a10960120032903f8074201520d00200329038008211f200341b8096a200341f8076a41106a290300370300200341b0096a201f37030020034180096a41086a41003a000020034189096a20032903f00537000020034191096a200341f0056a41086a29030037000020034199096a200341f0056a41106a290300370000200341a1096a20034188066a290300370000200341033a00800941c8e1ca00410020034180096a108c010b20024200370300201b42003703002006201d370300200520083703002003201e3703880920034201370380092003201c370390094110102d2202450d5e20024110412010312202450d5e200220034188096a221b290000370000200241186a201b41186a290000370000200241106a201b41106a290000370000200241086a201b41086a2900003700002002412041c00010312202450d5e20024200370020200241286a42003700002007ad4220862004ad842002ad428080808080068410042002102f024020032802f404450d002004102f0b2003418d096a201c37000020034180096a41286a20183602002003419d096a201d37000020034195096a20083700002003201e37008509200341003a008409200341023a00800941c8e1ca00410020034180096a108c01200041043a00004101211b0c520b200041023a00004101211b0c510b200341e0016a41086a221b200141146a290200370300200341e0016a41106a22042001411c6a290200370300200341e0016a41186a2205200141246a290200370300200341e0016a41206a22062001412c6a28020036020020032001410c6a2902003703e001200141c8006a290300211f200141c0006a290300211e200141386a2903002108200141306a290300211c2002411a6a290100211d200241196a2d00002109200241186a2d0000210a200241166a2f0100210b200241156a2d0000210c200241146a2d0000210d200241126a2f0100210e200241116a2d0000210f200241106a2d000021102002410e6a2f010021112002410d6a2d000021122002410c6a2d000021132002410a6a2f01002114200241096a2d00002115200241086a2d00002116200241066a2f01002117200241056a2d00002118200241046a2d00002119200241026a2f0100211a20022d0001210720022d0000210202400240024002400240200141086a2802000e050001020304000b20034180096a41146a41013602002003420137028409200341b4d8c90036028009200341043602fc06200341fcdbc9003602f8062003200341f8066a3602900920034180096a41e8d8c9001043000b200341f8076a41206a2006280200360200200341f8076a41186a2005290300370300200341f8076a41106a2004290300370300200341f8076a41086a201b290300370300200320032903e0013703f807200241ff01710d24200741ff01714101470d242003201d37038805200320093a0087052003200a3a0086052003200b3b0184052003200c3a0083052003200d3a0082052003200e3b0180052003200f3a00ff04200320103a00fe04200320113b01fc04200320123a00fb04200320133a00fa04200320143b01f804200320153a00f704200320163a00f604200320173b01f404200320183a00f304200320193a00f2042003201a3b01f00420034180096a41206a200341f8076a41206a28020036020020034180096a41186a200341f8076a41186a29030037030020034180096a41106a200341f8076a41106a29030037030020034180096a41086a2202200341f8076a41086a290300370300200320032903f80737038009200341f0056a20034180096a10bb0120034188026a41086a221b200341f9056a29000037030020034188026a41106a220420034181066a29000037030020034188026a41186a220520034189066a290000370300200320032900f1053703880220032d00f0054101460d03200341f8066a41186a2005290300370300200341f8066a41106a2004290300370300200341f8066a41086a201b29030037030020032003290388023703f8064101211b20034180096a200341f0046a200341f8066a201c2008410110f20220032003290081093703f003200320022800003600f703024020032d00800922024104470d00200041043a00000c540b200020023a0000200020032903f003370001200041086a20032800f7033600000c530b200341d0026a41206a2006280200360200200341d0026a41186a2005290300370300200341d0026a41106a2004290300370300200341d0026a41086a201b290300370300200320032903e0013703d0022007200241ff01714100477241ff01710d2420034180096a41206a200341d0026a41206a28020036020020034180096a41186a200341d0026a41186a29030037030020034180096a41106a200341d0026a41106a29030037030020034180096a41086a200341d0026a41086a290300370300200320032903d00237038009200341f8076a20034180096a10bb0120034188026a41086a220220034181086a29000037030020034188026a41106a220420034189086a29000037030020034188026a41186a220520034191086a290000370300200320032900f907370388024101211b20032d00f8074101460d03200341d0036a41186a2005290300370300200341d0036a41106a2004290300370300200341d0036a41086a200229030037030020032003290388023703d00320034200201f201e201c7c221d428080e983b1de16544100201f20087c201d201e54ad7c501b22041b221f3703c00220034200201e20041b221e3703b8022003200341d0036a3602cc02418de6c300ad4280808080e0008410012202290000211d200341a8026a41086a200241086a2900003703002003201d3703a8022002102f41f0e8c600ad4280808080f00084100122022d000f210520022d000e210620022f000c210720022d000b210920022d000a210a20022f0008210b20022d0007210c20022d0006210d20022f0004210e20022d0003210f20022d0002211020022f000021112002102f4120102d2202450d5e200220032903d003370000200241186a200341d0036a41186a290300370000200241106a200341d0036a41106a290300370000200241086a200341d0036a41086a2903003700002002ad42808080808004841003221b290000211d201b41086a2900002121201b41106a2900002122200341f0036a41186a2212201b41186a290000370300200341f0036a41106a22132022370300200341f0036a41086a221420213703002003201d3703f003201b102f2002102f41c000102d2202450d5e4200200820041b21084200201c20041b211c200220032903a802370000200241086a200341a8026a41086a2903003700002002200c3a00172002200d3a00162002200e3b00142002200f3a0013200220103a0012200220113b0010200220053a001f200220063a001e200220073b001c200220093a001b2002200a3a001a2002200b3b0018200220032903f003370020200241286a2014290300370000200241306a2013290300370000200241386a2012290300370000200341f8066a200210f60220032903f806212442002122200342003703f806200341c0076a280200210520032d00c40721060240024020244201510d00200341f0046a41306a4200370300200341f0046a41286a4200370300200341f0046a41206a420037030020034188056a420037030020034180056a4200370300200341f8046a4200370300200342003703f00442002123420021214200211d4200212a0c010b200341f8066a41386a290300212b200341f8066a41306a290300212c200341f8066a41206a2903002123200341f8066a41186a2903002122200341f8066a41c0006a290300212a200329038807211d2003290380072121200341f0046a41206a200341f8066a41286a290300370300200341f0046a41286a202c370300200341f0046a41306a202b37030020034180056a20223703002003202337038805200320213703f0042003201d3703f8040b201d20237c212b202120227c222c2021542207ad212d201c2021562008201d562008201d51221b1b0d25201c2021542008201d54201b1b450d4d200341f0036a41186a220b4200370300200341f0036a41106a22044200370300200341f0036a41086a221b4200370300200342003703f00341e7a2ca00ad4280808080800184221e10012209290000211f2009290008212e2009102f201b202e3703002003201f3703f00341ecb5c600ad4280808080d00184221f1001220a290000212e200341a8026a41086a2209200a41086a2900003703002003202e3703a802200a102f200420032903a802222e37030020034188026a41086a220c201b29030037030020034188026a41106a220d202e37030020034188026a41186a220e2009290300370300200320032903f0033703880220034198016a20034188026a4120109c0120034198016a41106a290300212e20032903a001212f200328029801210a200b420037030020044200370300201b4200370300200342003703f003201e1001220b290000211e200b2900082130200b102f201b20303703002003201e3703f003201f1001220b290000211e2009200b41086a2900003703002003201e3703a802200b102f200420032903a802221e370300200c201b290300370300200d201e370300200e2009290300370300200320032903f0033703880220034200202e4200200a1b221e2021201c54ad2008201d7d7c7c202f4200200a1b221f2021201c7d222e54ad7d2221201f202e7d222e201f562021201e562021201e511b221b1b3703880920034200202e201b1b3703800920034180096a211b20034188026a21040c4c0b200141e0006a290300211d200141d8006a2903002121200141d0006a2802002109200341f8076a41206a2006280200360200200341f8076a41186a2005290300370300200341f8076a41106a2004290300370300200341f8076a41086a201b290300370300200320032903e0013703f8072007200241ff01714100477241ff01710d2520034180096a41206a2202200341f8076a41206a28020036020020034180096a41186a2204200341f8076a41186a29030037030020034180096a41106a2205200341f8076a41106a29030037030020034180096a41086a200341f8076a41086a290300370300200320032903f80737038009200341f0056a20034180096a10bb014101211b20032d00f0054101460d02200341f0056a41086a2d0000211b200341f9056a22062f00002107200341fb056a2d0000210a200341fc056a2d0000210b200341fd056a2f0000210c200341ff056a2d0000210d200341f0056a41106a2d0000210e20034181066a220f2f0000211020034183066a2d0000211120034184066a2d0000211220034185066a2f0000211320034187066a2d00002114200341f0056a41186a2d0000211520032f00f105211620032d00f305211720032d00f405211820032f00f505211920032d00f705211a200320034189066a222029000037038805200320153a008705200320143a008605200320133b018405200320123a008305200320113a008205200320103b0180052003200e3a00ff042003200d3a00fe042003200c3b01fc042003200b3a00fb042003200a3a00fa04200320073b01f8042003201b3a00f7042003201a3a00f604200320193b01f404200320183a00f304200320173a00f204200320163b01f0042004201f3703002005201e3703002002200936020020032008370388092003201c37038009200341f0056a20034180096a10bb0120034188026a41086a200629000037030020034188026a41106a200f29000037030020034188026a41186a2020290000370300200320032900f1053703880220032d00f0054101460d01200341f8066a41186a20034188026a41186a290300370300200341f8066a41106a20034188026a41106a290300370300200341f8066a41086a20034188026a41086a29030037030020032003290388023703f8064101211b20034180096a200341f0046a200341f8066a2021201d410110f20220032003290081093703f003200320034180096a41086a2800003600f703024020032d00800922024104470d00200041043a00000c520b200020023a0000200020032903f003370001200041086a20032800f7033600000c510b200341f8076a41206a2006280200360200200341f8076a41186a2005290300370300200341f8076a41106a2004290300370300200341f8076a41086a201b290300370300200320032903e0013703f807200241ff01710d25200741ff01714101470d252003201d37038805200320093a0087052003200a3a0086052003200b3b0184052003200c3a0083052003200d3a0082052003200e3b0180052003200f3a00ff04200320103a00fe04200320113b01fc04200320123a00fb04200320133a00fa04200320143b01f804200320153a00f704200320163a00f604200320173b01f404200320183a00f304200320193a00f2042003201a3b01f00420034180096a41206a200341f8076a41206a28020036020020034180096a41186a200341f8076a41186a29030037030020034180096a41106a200341f8076a41106a29030037030020034180096a41086a2202200341f8076a41086a290300370300200320032903f80737038009200341f0056a20034180096a10bb0120034188026a41086a221b200341f9056a29000037030020034188026a41106a220420034181066a29000037030020034188026a41186a220520034189066a290000370300200320032900f1053703880220032d00f0054101460d00200341f8066a41186a2005290300370300200341f8066a41106a2004290300370300200341f8066a41086a201b29030037030020032003290388023703f80620034180096a200341f0046a200341f8066a201c2008410010f20220032003290081093703f003200320022800003600f70320032d00800922024104470d02200041043a00004101211b0c500b4101211b0b2000201b3a00000c4e0b200020023a0000200020032903f003370001200041086a20032800f7033600004101211b0c4d0b20034180096a41306a200141386a29030037030020034180096a41286a200141306a29030037030020034180096a41206a200141286a29030037030020034180096a41186a200141206a29030037030020034180096a41106a200141186a29030037030020034180096a41086a200141106a2903003703002003200141086a29030037038009200341f8076a41206a200241206a290200370300200341f8076a41186a200241186a290200370300200341f8076a41106a200241106a290200370300200341f8076a41086a200241086a290200370300200320022902003703f807200020034180096a200341f8076a108003410021064101211b41012104410121050c640b200141086a28020021292001280204212820034180096a2001410c6a41840110e8061a2002411a6a2901002108200241196a2d00002104200241186a2d00002105200241166a2f01002106200241156a2d00002107200241146a2d00002109200241126a2f0100210a200241116a2d0000210b200241106a2d0000210c2002410e6a2f0100210d2002410d6a2d0000210e2002410c6a2d0000210f2002410a6a2f01002110200241096a2d00002111200241086a2d00002112200241066a2f01002113200241056a2d00002114200241046a2d00002115200241026a2f0100211620022d0001211b20022d0000210202402028450d00200341d0026a20034180096a41046a41800110e8061a024002400240200241ff01710d00201b41ff01714101460d010b200041023a000020290d010c470b200320083703e803200320043a00e703200320053a00e603200320063b01e403200320073a00e303200320093a00e2032003200a3b01e0032003200b3a00df032003200c3a00de032003200d3b01dc032003200e3a00db032003200f3a00da03200320103b01d803200320113a00d703200320123a00d603200320133b01d403200320143a00d303200320153a00d203200320163b01d003200341f0036a200341d0026a41800110e8061a20034188066a20032903e803370300200341f0056a41106a20032903e003370300200341f0056a41086a20032903d803370300200320032903d0033703f005200341f8076a200341f0056a1081030240024020032802a4084102460d00200341f8066a41086a200341b5086a290000370300200341f8066a41106a200341bd086a290000370300200341f8066a41176a2202200341c4086a290000370000200320032900ad083703f806200341ac086a2d0000211b0240200328029c08450d00200328029808102f0b200341f0046a41176a22042002290000370000200341f0046a41106a2202200341f8066a41106a290300370300200341e9016a20034180076a290300370000200341f1016a2002290300370000200341f8016a20042900003700002003201b3a00e001200320032903f8063700e101200341f0046a200341f0036a41800110e8061a20034188026a200341e0016a108203200341f8076a200328028802221b20032802900210830320032d00f8072102200341f8066a200341f8076a41017241800110e8061a0240024020024101460d00200341003a00f0050c010b200341013a00f005200341f0056a410172200341f8066a41800110e8061a0b0240200328028c02450d00201b102f0b200341f0046a41206a2127200341b0056a2125200341d0056a212620034191066a2131200341b1066a2132200341d1066a2133200341f0056a41017221344170210503404100211b41c8e1ca0021040240024002400240200541c0aac3006a280000220241e6e485f3064a22090d00200241e2c289ab06460d01200241e1ea91cb06470d034120211b202621040c030b200241e9dabdf306460d01200241e7e485f306470d024120211b200341f0046a21040c020b4120211b202721040c010b4120211b202521040b2003201b36028008200320043602fc07200320023602f807200341f8066a200341f8076a108403200341f8076a20032802f806220720032802800710ad0220032802fc0621060240024020032d00f8074101470d00200329009108210820032d009008210a20032d008f08210b20032f008d08210c20032d008c08210d20032d008b08210e20032f008908210f20032d008808211020032d008708211120032f008508211220032d008408211320032d008308211420032f008108211520032d008008211620032d00ff07211720032f00fd07211820032d00fc07211920032d00fb07211a20032f00f907212002402006450d002007102f0b20032008370390082003200a3a008f082003200b3a008e082003200c3b018c082003200d3a008b082003200e3a008a082003200f3b018808200320103a008708200320113a008608200320123b018408200320133a008308200320143a008208200320153b018008200320163a00ff07200320173a00fe07200320183b01fc07200320193a00fb072003201a3a00fa07200320203b01f807200341f8076a200341e0016a412010ea06450d014102210241b7eac300211b410d21040c040b2006450d002007102f0b0240024020032d00f0054101470d004100210641c8e1ca002107024002400240024020090d00200241e2c289ab06460d01200241e1ea91cb06470d0341202106203321070c030b200241e9dabdf306460d01200241e7e485f306470d0241202106203421070c020b41202106203121070c010b41202106203221070b0240201b2006470d0020042007460d0220042007201b10ea06450d020b2003200636028008200320073602fc07200320023602f807200341f8066a200341f8076a10840320033502800742208620032802f8062206ad84100520032802fc06450d002006102f0b2003201b36028008200320043602fc07200320023602f807200341f8066a200341f8076a10840320032802f806211b20033502800721084120102d2202450d5d200220032903e001370000200241186a200341e0016a41186a290300370000200241106a200341e0016a41106a290300370000200241086a200341e0016a41086a2903003700002008422086201bad842002ad428080808080048410042002102f20032802fc06450d00201b102f0b200541046a22050d000b200341f8076a200341e0016a108203200335028008210820032802f807211b4120102d2202450d5b200220032903f004370000200241186a200341f0046a41186a290300370000200241106a200341f0046a41106a290300370000200241086a200341f0046a41086a2903003700002002412041c00010312202450d5b2002200329039005370020200241386a200341f0046a41386a290300370000200241306a200341f0046a41306a290300370000200241286a200341f0046a41286a290300370000200241c00041800110312202450d5b200220032903b005370040200241d8006a200341f0046a41d8006a290300370000200241d0006a200341f0046a41d0006a290300370000200241c8006a200341f0046a41c8006a290300370000200220032903d005370060200241e8006a200341f0046a41e8006a290300370000200241f0006a200341f0046a41f0006a290300370000200241f8006a200341f0046a41f8006a2903003700002008422086201bad842002ad428080808080108410042002102f024020032802fc07450d00201b102f0b024020032d00f0050d00200341d0036a10d0020b200041043a000020290d020c480b4101210241c4eac300211b411721040b200041086a2004360200200041046a201b360200200041026a20023a000020004183123b01002029450d460b2028102f0c450b200241ff01710d21201b41ff01714101470d21200320113a00d702200320123a00d602200320133b01d402200320143a00d302200320153a00d202200320163b01d0022003200b3a00df022003200c3a00de022003200d3b01dc022003200e3a00db022003200f3a00da02200320103b01d802200320043a00e702200320053a00e602200320063b01e402200320073a00e302200320093a00e2022003200a3b01e002200320083703e80220034188066a2008370300200341f0056a41106a20032903e002370300200341f0056a41086a20032903d802370300200320032903d0023703f005200341f8076a200341f0056a1081030240024020032802a4084102460d00200341f8066a41086a200341b5086a290000370300200341f8066a41106a200341bd086a290000370300200341f8066a41176a2202200341c4086a290000370000200320032900ad083703f806200341ac086a2d0000211b0240200328029c08450d00200328029808102f0b200341f0046a41176a22042002290000370000200341f0046a41106a2202200341f8066a41106a290300370300200341f9036a20034180076a29030037000020034181046a200229030037000020034188046a20042900003700002003201b3a00f003200320032903f8063700f103200341e0016a200341f0036a108203200341f8076a20032802e001220220032802e8012204108303024020032d00f807221b450d002004ad4220862002ad8410050b20032d00f9072104200341f8066a200341f8076a41027241ff0010e8061a200341f8076a200341f8066a41ff0010e8061a0240201b4101470d00200341f0046a200341f8076a41ff0010e8061a024020032802e401450d002002102f0b200320043a00f005200341f0056a410172200341f0046a41ff0010e8061a20034180086a4120360200200341e7e485f3063602f8072003200341f0056a3602fc07200341f8066a200341f8076a10840320033502800742208620032802f8062202ad841005024020032802fc06450d002002102f0b200341e2c289ab063602f80720034120360280082003200341f0056a41206a3602fc07200341f8066a200341f8076a10840320033502800742208620032802f8062202ad841005024020032802fc06450d002002102f0b20034120360280082003200341b0066a3602fc07200341e9dabdf3063602f807200341f8066a200341f8076a10840320033502800742208620032802f8062202ad841005024020032802fc06450d002002102f0b20034120360280082003200341d0066a3602fc07200341e1ea91cb063602f807200341f8066a200341f8076a10840320033502800742208620032802f8062202ad841005024020032802fc06450d002002102f0b200341d0026a10ca02200041043a00000c470b024020032802e401450d002002102f0b4106210241b1eac300211b410321040c010b4117210241c4eac300211b410121040b20004183123b0100200041086a2002360200200041046a201b360200200041026a20043a00000c440b20034180096a41306a200141386a29030037030020034180096a41286a200141306a29030037030020034180096a41206a200141286a29030037030020034180096a41186a200141206a29030037030020034180096a41106a200141186a29030037030020034180096a41086a200141106a2903003703002003200141086a29030037038009200341f8076a41206a200241206a290200370300200341f8076a41186a200241186a290200370300200341f8076a41106a200241106a290200370300200341f8076a41086a200241086a290200370300200320022902003703f807200020034180096a200341f8076a10c302410021094101211b410121044101210541012106410121070c640b200341a8096a2001412c6a29020037030020034180096a41206a200141246a29020037030020034180096a41186a2001411c6a29020037030020034180096a41106a200141146a29020037030020034180096a41086a2001410c6a2902003703002003200129020437038009200341f8076a41206a200241206a290200370300200341f8076a41186a200241186a290200370300200341f8076a41106a200241106a290200370300200341f8076a41086a200241086a290200370300200320022902003703f807200020034180096a200341f8076a1085034100210a4101211b41012104410121054101210641012107410121090c640b200341a8096a2001412c6a29020037030020034180096a41206a200141246a29020037030020034180096a41186a2001411c6a29020037030020034180096a41106a200141146a29020037030020034180096a41086a2001410c6a2902003703002003200129020437038009200341f8076a41206a200241206a290200370300200341f8076a41186a200241186a290200370300200341f8076a41106a200241106a290200370300200341f8076a41086a200241086a290200370300200320022902003703f807200020034180096a200341f8076a1086034100210b4101211b41012104410121054101210641012107410121094101210a0c640b200341f8076a41206a200141286a290300370300200341f8076a41186a200141206a290300370300200341f8076a41106a200141186a290300370300200341f8076a41086a200141106a2903003703002003200141086a2903003703f80720034180096a41206a200241206a29020037030020034180096a41186a200241186a29020037030020034180096a41106a200241106a29020037030020034180096a41086a200241086a29020037030020032002290200370380092000200341f8076a20034180096a1087034100210c4101211b41012104410121054101210641012107410121094101210a4101210b0c640b200341cc026a41026a2207200141076a2d00003a0000200341f8076a41086a22092001411c6a290200370300200341f8076a41106a220a200141246a290200370300200341f8076a41186a2001412c6a29020037030020034198086a200141346a290200370300200341a0086a2001413c6a290200370300200341a8086a200141c4006a2d00003a0000200320012f00053b01cc022003200141146a2902003703f807200141086a28020021042001410c6a2802002105200141106a280200210620022f0001200241036a2d000041107472210c2002410c6a280200210d200241086a280200210e200241046a280200210f20022d0000211b02400240024002400240024002400240024020012d0004220b0e080001020304050607000b20034180096a41146a41013602002003420137028409200341b4d8c90036028009200341043602fc06200341fcdbc9003602f8062003200341f8066a3602900920034180096a41e8d8c9001043000b20034187066a20092903003700002003418f066a200a2d00003a0000200320032f01cc023b01f005200320063600fb05200320053600f705200320043600f305200320032903f8073700ff05200320072d00003a00f20502400240201b417f6a220241024b0d00024020020e03000102000b200e410174200d4d0d00200f41ff0171450d010b200c201b4100477241ff01710d070b200341f0036a41186a4200370300200341f0036a41106a22064200370300200341f0036a41086a22024200370300200342003703f00341eba1c600ad4280808080b002841001221b29000021082002201b41086a290000370300200320083703f003201b102f41ebdec700ad4280808080f000841001221b2900002108200341a8026a41086a2207201b41086a290000370300200320083703a802201b102f200620032903a802220837030020034188026a41086a200229030037030020034188026a41106a200837030020034188026a41186a2007290300370300200320032903f0033703880220034180096a20034188026a412010aa02024020032802800922090d0041012109200341013602f8064100210c4100210d0c410b200320093602f806200328028409210c2003290284092208a7210d024002402008422088a7220a41014b0d0041002102200a0e024201420b200a211b4100210203402002201b410176220620026a2207200920074105746a200341f0056a412010ea0641004a1b2102201b20066b221b41014b0d000b0b0240200920024105746a200341f0056a412010ea06221b450d0020034180096a41186a200341f0056a41186a29030037030020034180096a41106a200341f0056a41106a29030037030020034180096a41086a200341f0056a41086a290300370300200320032903f00537038009201b411f7620026a2206200a4b0d2520034180096a211b0c420b200041831c3b0100200041086a410d360200200041046a41f2b6c400360200200041026a41003a0000200c450d422009102f0c420b200341e7026a2009290300370000200341ef026a200a2d00003a0000200320032f01cc023b01d002200320063600db02200320053600d702200320043600d302200320032903f8073700df02200320072d00003a00d20202400240201b417f6a220241024b0d00024020020e03000102000b200e410174200d4d0d00200f41ff0171450d010b200c201b4100477241ff01710d250b200341f0036a41186a4200370300200341f0036a41106a22064200370300200341f0036a41086a22024200370300200342003703f00341eba1c600ad4280808080b002841001221b29000021082002201b41086a290000370300200320083703f003201b102f41ebdec700ad4280808080f000841001221b2900002108200341a8026a41086a2207201b41086a290000370300200320083703a802201b102f200620032903a802220837030020034188026a41086a200229030037030020034188026a41106a200837030020034188026a41186a2007290300370300200320032903f0033703880220034180096a20034188026a412010aa022003280280092202410120021b2109024002400240200329028409420020021b2208422088a7220a41014b0d0041002102200a0e020201020b200a211b4100210203402002201b410176220620026a2207200920074105746a200341d0026a412010ea0641004a1b2102201b20066b221b41014b0d000b0b200920024105746a200341d0026a412010ea060d002002200a4f0d26200920024105746a221b201b41206a2002417f73200a6a41057410e9061a20034180096a41186a2207420037030020034180096a41106a2206420037030020034180096a41086a221b4200370300200342003703800941eba1c600ad4280808080b00284221c10012202290000211d200341b8026a41086a220c200241086a2900003703002003201d3703b8022002102f201b200c290300370300200320032903b8023703800941ebdec700ad4280808080f0008410012202290000211d200341a8026a41086a220c200241086a2900003703002003201d3703a8022002102f200620032903a802221d370300200341f8066a41086a201b290300370300200341f8066a41106a201d370300200341f8066a41186a200c29030037030020032003290380093703f80620034120360284092003200341f8066a360280092009200a417f6a220220034180096a10aa012007200341d0026a41186a2903003703002006200341d0026a41106a290300370300201b200341d0026a41086a290300370300200320032903d0023703800920034180096a41012009200210880320034188026a41186a2207420037030020034188026a41106a220c420037030020034188026a41086a221b42003703002003420037038802201c10012206290000211c2006290008211d2006102f201b201d3703002003201c3703880241fbd4c700ad4280808080d0008410012206290008211c2006290000211d2006102f200341f0046a41106a201d370300200341f0046a41186a201c370300200341f0046a41086a201b29030037030020032003290388023703f00420034180096a200341f0046a412010ad0220032d0080092106200720034199096a290000370300200c20034191096a290000370300201b20034189096a290000370300200320032900810937038802024020064101470d00200341d0036a41186a2007290300221c370300200341d0036a41106a200c290300221d370300200341d0036a41086a201b290300221e3703002003200329038802221f3703d003200341f0056a41186a201c370300200341f0056a41106a201d370300200341f0056a41086a201e3703002003201f3703f0050240024002400240200a417f6a220641014b0d004100211b20060e020201020b4100211b0340201b20024101762206201b6a2207200920074105746a200341f0056a412010ea0641004a1b211b200220066b220241014b0d000b0b2009201b4105746a200341f0056a412010ea06450d010b200341f0046a41186a4200370300200341f0046a41106a22074200370300200341f0046a41086a221b4200370300200342003703f00441eba1c600ad4280808080b0028410012206290000211c20034188026a41086a2202200641086a2900003703002003201c370388022006102f201b200229030037030020032003290388023703f00441fbd4c700ad4280808080d0008410012206290000211c2002200641086a2900003703002003201c370388022006102f2007200329038802221c370300200341f0036a41086a201b290300370300200341f0036a41106a201c370300200341f0036a41186a2002290300370300200320032903f0043703f003200341f0036aad428080808080048410050c010b20034199096a20034188066a29030037000020034191096a20034180066a29030037000020034189096a200341f8056a290300370000200320032903f00537008109200341013a00800920034180096a1089030b2003418a023b01800941c8e1ca00410020034180096a108c0102402008a7450d002009102f0b200041043a00000c420b200041831c3b0100200041086a4109360200200041046a41d1d5c700360200200041026a41013a00002008a7450d412009102f0c410b200341f7016a2009290300370000200341ff016a200a2d00003a0000200320032f01cc023b01e001200320063600eb01200320053600e701200320043600e301200320032903f8073700ef01200320072d00003a00e201200341d0026a41186a200341a1086a290000370300200341d0026a41106a20034199086a290000370300200341d0026a41086a20034191086a29000037030020032003290089083703d00202400240201b417f6a220241024b0d00024020020e03000102000b200e410174200d4d0d00200f41ff0171450d010b200c201b4100477241ff01710d260b200341e0016a200341d0026a412010ea06450d26200341f0036a41186a4200370300200341f0036a41106a22064200370300200341f0036a41086a22024200370300200342003703f00341eba1c600ad4280808080b002841001221b29000021082002201b41086a290000370300200320083703f003201b102f41ebdec700ad4280808080f000841001221b2900002108200341a8026a41086a2207201b41086a290000370300200320083703a802201b102f200620032903a802220837030020034188026a41086a200229030037030020034188026a41106a200837030020034188026a41186a2007290300370300200320032903f0033703880220034180096a20034188026a412010aa024101210c2003280280092202410120021b21094109210d41d1d5c700210e02400240200329028409420020021b2208422088a7220a41014b0d0041002102200a0e023e013e0b200a211b4100210203402002201b410176220620026a2207200920074105746a200341e0016a412010ea0641004a1b2102201b20066b221b41014b0d000b0b200920024105746a220f200341e0016a412010ea060d3c0240200a41014b0d004100211b200a0e023e3c3e0b200a21064100211b0340201b20064101762207201b6a220c2009200c4105746a200341d0026a412010ea0641004a1b211b200620076b220641014b0d000c3c0b0b024002400240201b417f6a220241024b0d00024020020e03000102000b200e410174200d4d0d00200f41ff0171450d010b200c201b4100477241ff01710d010b20042006108701200341f0036a41186a4200370300200341f0036a41106a22074200370300200341f0036a41086a221b4200370300200342003703f00341eba1c600ad4280808080b00284220810012202290000211c201b200241086a2900003703002003201c3703f0032002102f41ebdec700ad4280808080f0008410012202290000211c200341a8026a41086a2209200241086a2900003703002003201c3703a8022002102f200720032903a802221c37030020034188026a41086a2202201b29030037030020034188026a41106a221b201c37030020034188026a41186a22072009290300370300200320032903f0033703880220034180096a20034188026a412010aa02200420062003280280092209410120091b220a200329028409420020091b221c422088a7108a0320074200370300201b420037030020024200370300200342003703880220081001220929000021082009290008211d2009102f2002201d370300200320083703880241fbd4c700ad4280808080d000841001220929000821082009290000211d2009102f200341f0046a41106a201d370300200341f0046a41186a2008370300200341f0046a41086a200229030037030020032003290388023703f00420034180096a200341f0046a412010ad0220032d0080092109200720034199096a290000370300201b20034191096a290000370300200220034189096a290000370300200320032900810937038802024020094101470d00200341d0036a41186a20072903002208370300200341d0036a41106a201b290300221d370300200341d0036a41086a2002290300221e3703002003200329038802221f3703d003200341f0056a41186a2008370300200341f0056a41106a201d370300200341f0056a41086a201e3703002003201f3703f0050240024002400240200641014b0d004100210220060e020201020b2006211b4100210203402002201b410176220720026a2209200420094105746a200341f0056a412010ea0641004a1b2102201b20076b221b41014b0d000b0b200420024105746a200341f0056a412010ea06450d010b200341f0046a41186a4200370300200341f0046a41106a22094200370300200341f0046a41086a221b4200370300200342003703f00441eba1c600ad4280808080b0028410012207290000210820034188026a41086a2202200741086a29000037030020032008370388022007102f201b200229030037030020032003290388023703f00441fbd4c700ad4280808080d000841001220729000021082002200741086a29000037030020032008370388022007102f20092003290388022208370300200341f0036a41086a201b290300370300200341f0036a41106a2008370300200341f0036a41186a2002290300370300200320032903f0043703f003200341f0036aad428080808080048410050c010b20034199096a20034188066a29030037000020034191096a20034180066a29030037000020034189096a200341f8056a290300370000200320032903f00537008109200341013a00800920034180096a1089030b0240201ca7450d00200a102f0b200341f0046a41186a4200370300200341f0046a41106a22094200370300200341f0046a41086a221b4200370300200342003703f00441eba1c600ad4280808080b0028410012207290000210820034188026a41086a2202200741086a29000037030020032008370388022007102f201b200229030037030020032003290388023703f00441ebdec700ad4280808080f000841001220729000021082002200741086a29000037030020032008370388022007102f20092003290388022208370300200341f0036a41086a201b290300370300200341f0036a41106a2008370300200341f0036a41186a2002290300370300200320032903f0043703f00320034120360284092003200341f0036a360280092004200620034180096a10aa0102402005450d002004102f0b2003418a063b01800941c8e1ca00410020034180096a108c01200041043a00000c430b200041023a00002005450d422004102f0c420b200241106a2902002108200241186a2f010021102002411a6a290100211c200341e7026a2009290300370000200341ef026a200a2d00003a0000200320072d00003a00d202200320032f01cc023b01d002200320063600db02200320053600d702200320043600d302200320032903f8073700df022003201c37038805200320103b018605200320083701fe042003200c4108763b01f0042003200d3a00fa042003200d4110763b01fc042003200d4108763a00fb042003200e3a00f6042003200e4110763b01f8042003200e4108763a00f7042003200f3a00f2042003200f4110763b01f4042003200f4108763a00f304200c41ff01714101470d25201b0d25200341f8066a41186a200341f0046a41186a290300370300200341f8066a41106a200341f0046a41106a290300370300200341f8066a41086a200341f0046a41086a290300370300200320032903f0043703f806200341f8066a200341d0026a412010ea06450d37200341f0036a41186a4200370300200341f0036a41106a22064200370300200341f0036a41086a22024200370300200342003703f00341eba1c600ad4280808080b002841001221b29000021082002201b41086a290000370300200320083703f003201b102f41ebdec700ad4280808080f000841001221b2900002108200341a8026a41086a2207201b41086a290000370300200320083703a802201b102f200620032903a802220837030020034188026a41086a200229030037030020034188026a41106a200837030020034188026a41186a2007290300370300200320032903f0033703880220034180096a20034188026a412010aa024101210a2003280280092202410120021b21094109210d41d1d5c700210e02400240200329028409420020021b2208422088a7220c41014b0d0041002102200c0e023701370b200c211b4100210203402002201b410176220620026a2207200920074105746a200341f8066a412010ea0641004a1b2102201b20066b221b41014b0d000b0b200920024105746a220f200341f8066a412010ea060d350240200c41014b0d004100211b200c0e023735370b200c21064100211b0340201b20064101762207201b6a220a2009200a4105746a200341d0026a412010ea0641004a1b211b200620076b220641014b0d000c350b0b20034187066a20092903003700002003418f066a200a2d00003a0000200320032f01cc023b01f005200320063600fb05200320053600f705200320043600f305200320032903f8073700ff05200320072d00003a00f20502400240201b417f6a220241024b0d00024020020e03000102000b200e410174200d4d0d00200f41ff0171450d010b200c201b4100477241ff01710d260b200341f0036a41186a4200370300200341f0036a41106a22064200370300200341f0036a41086a22024200370300200342003703f00341eba1c600ad4280808080b002841001221b29000021082002201b41086a290000370300200320083703f003201b102f41ebdec700ad4280808080f000841001221b2900002108200341a8026a41086a2207201b41086a290000370300200320083703a802201b102f200620032903a802220837030020034188026a41086a200229030037030020034188026a41106a200837030020034188026a41186a2007290300370300200320032903f0033703880220034180096a20034188026a412010aa022003280280092202410120021b2109024002400240200329028409420020021b2208422088a7220241014b0d004100211b20020e020201020b4100211b0340201b20024101762206201b6a2207200920074105746a200341f0056a412010ea0641004a1b211b200220066b220241014b0d000b0b2009201b4105746a200341f0056a412010ea060d0002402008a7450d002009102f0b200341f0046a41186a4200370300200341f0046a41106a22074200370300200341f0046a41086a221b4200370300200342003703f00441eba1c600ad4280808080b0028410012206290000210820034188026a41086a2202200641086a29000037030020032008370388022006102f201b200229030037030020032003290388023703f00441fbd4c700ad4280808080d000841001220629000021082002200641086a29000037030020032008370388022006102f20072003290388022208370300200341f0036a41086a201b290300370300200341f0036a41106a2008370300200341f0036a41186a2002290300370300200320032903f0043703f0034120102d2202450d55200220032903f005370000200241186a200341f0056a41186a221b290300370000200241106a200341f0056a41106a2206290300370000200241086a200341f0056a41086a2207290300370000200341f0036aad42808080808004842002ad428080808080048410042002102f20034199096a201b29030037000020034191096a200629030037000020034189096a2007290300370000200320032903f00537008109200341013a00800920034180096a108903200041043a00000c3e0b200041831c3b0100200041086a4109360200200041046a41d1d5c700360200200041026a41013a00002008a7450d3d2009102f0c3d0b024002400240201b417f6a220241024b0d00024020020e03000102000b200e410174200d4d0d00200f41ff0171450d010b200c201b4100477241ff01710d010b200341f0046a41186a4200370300200341f0046a41106a22054200370300200341f0046a41086a221b4200370300200342003703f00441eba1c600ad4280808080b0028410012204290000210820034188026a41086a2202200441086a29000037030020032008370388022004102f201b200229030037030020032003290388023703f00441fbd4c700ad4280808080d000841001220429000021082002200441086a29000037030020032008370388022004102f20052003290388022208370300200341f0036a41086a201b290300370300200341f0036a41106a2008370300200341f0036a41186a2002290300370300200320032903f0043703f003200341f0036aad42808080808004841005200341003a00800920034180096a108903200041043a00000c400b200041023a00000c3f0b200041023a00000c3b0b20022d00000d2320022d000141ff01714102470d2320012802042105200341f0036a41186a22064200370300200341f0036a41106a22044200370300200341f0036a41086a22024200370300200342003703f00341d5a2ca00ad42808080809001841001221b2900002108201b290008211c201b102f2002201c370300200320083703f00341a2c9c300ad4280808080e000841001221b2900082108201b290000211c201b102f20034188026a41106a2207201c37030020034188026a41186a2209200837030020034188026a41086a220a2002290300370300200320032903f00337038802200341b8016a20034188026a412041c8e1ca004100410010b5014101211b20032802b8014101460d24200642003703002004420037030020024200370300200342003703f003418de6c300ad4280808080e000841001221b29000021082002201b41086a290000370300200320083703f003201b102f419ce6c300ad4280808080e000841001221b2900002108200341a8026a41086a2206201b41086a290000370300200320083703a802201b102f200420032903a8022208370300200a20022903003703002007200837030020092006290300370300200320032903f00337038802200341b0016a20034188026a4120109501024020032802b401410020032802b0011b2005490d00200341f0036a41186a4200370300200341f0036a41106a4200370300200341f0036a41086a22024200370300200342003703f00341d5a2ca00ad42808080809001841001221b2900002108201b290008211c201b102f2002201c370300200320083703f00341a2c9c300ad4280808080e000841001221b2900082108201b290000211c201b102f20034188026a41106a201c37030020034188026a41186a200837030020034188026a41086a2002290300370300200320032903f00337038802200320053602800920034188026aad428080808080048420034180096aad4280808080c000841004200041043a00004101211b0c460b200041831e3b0100200041086a4107360200200041046a41f5e1c3003602004101211b200041026a41013a00000c450b200141086a280200210420012802042105024020022d00000d004101211b20022d000141ff01714101470d00200041043a00004100210e2004450d2f0c2e0b200041023a00004100210e4101211b20040d2d0c2e0b20034180096a41386a200141c0006a29030037030020034180096a41306a200141386a29030037030020034180096a41286a200141306a29030037030020034180096a41206a200141286a29030037030020034180096a41186a200141206a29030037030020034180096a41106a200141186a29030037030020034180096a41086a200141106a2903003703002003200141086a29030037038009200341f8076a41206a200241206a290200370300200341f8076a41186a200241186a290200370300200341f8076a41106a200241106a290200370300200341f8076a41086a200241086a290200370300200320022902003703f807200020034180096a200341f8076a108b034100210f4101211b41012104410121054101210641012107410121094101210a4101210b4101210c4101210d4101210e0c630b20034180096a200141086a41880110e8061a200341f8076a41206a200241206a290200370300200341f8076a41186a200241186a290200370300200341f8076a41106a200241106a290200370300200341f8076a41086a200241086a290200370300200320022902003703f807200020034180096a200341f8076a109c02410021104101211b41012104410121054101210641012107410121094101210a4101210b4101210c4101210d4101210e4101210f0c630b200341d0026a41086a2205200141146a290200370300200341d0026a41106a22062001411c6a290200370300200341d0026a41186a2207200141246a29020037030020032001410c6a2902003703d0022002411a6a2901002108200241196a2d00002109200241186a2d0000210a200241166a2f0100210b200241156a2d0000210c200241146a2d0000210d200241126a2f0100210e200241116a2d0000210f200241106a2d000021102002410e6a2f010021112002410d6a2d000021122002410c6a2d000021132002410a6a2f01002114200241096a2d00002115200241086a2d00002116200241066a2f01002117200241056a2d00002118200241046a2d00002119200241026a2f0100211a200141086a280200211b20022d0001210420022d00002102024002400240024020012802040e0400010203000b20034180096a41146a41013602002003420137028409200341b4d8c90036028009200341043602fc06200341fcdbc9003602f8062003200341f8066a3602900920034180096a41e8d8c9001043000b02400240200241ff01710d00200441ff01714101470d002003200837038806200320093a0087062003200a3a0086062003200b3b0184062003200c3a0083062003200d3a0082062003200e3b0180062003200f3a00ff05200320103a00fe05200320113b01fc05200320123a00fb05200320133a00fa05200320143b01f805200320153a00f705200320163a00f605200320173b01f405200320183a00f305200320193a00f2052003201a3b01f005200341f0036a41186a22064200370300200341f0036a41106a22044200370300200341f0036a41086a22024200370300200342003703f00341a4e3c400ad4280808080c000841001220529000021082002200541086a290000370300200320083703f0032005102f4180e4c400ad42808080803084100122052900002108200341a8026a41086a2207200541086a290000370300200320083703a8022005102f200420032903a802220837030020034188026a41086a200229030037030020034188026a41106a200837030020034188026a41186a2007290300370300200320032903f0033703880220034180096a20034188026a412010ad0220032d0080092105200620034199096a290000370300200420034191096a290000370300200220034189096a29000037030020032003290081093703f0030240024020054101460d00200341f8076a41186a4200370300200341f8076a41106a4200370300200341f8076a41086a4200370300200342003703f8070c010b200341f8076a41186a2006290300370300200341f8076a41106a2004290300370300200341f8076a41086a2002290300370300200320032903f0033703f8070b200341f0056a200341f8076a412010ea060d0120034180096a201b41b00210e8061a200341003b01f807200341f8066a20034180096a200341f8076a108b0141012102024020032d00f8064104460d0020034180096a41086a200341f8066a41086a280200360200200320032903f8063703800920034180096a108c03410021020b200320023a0082092003410e3b01800941c8e1ca00410020034180096a108c01200041043a00000c2c0b200041023a00000c2a0b20004183263b0100200041086a410b360200200041046a4199b3c400360200200041026a41003a00000c290b200341f8066a41186a2007290300370300200341f8066a41106a2006290300370300200341f8066a41086a2005290300370300200320032903d0023703f806200241ff01710d22200441ff01714101470d222003200837038806200320093a0087062003200a3a0086062003200b3b0184062003200c3a0083062003200d3a0082062003200e3b0180062003200f3a00ff05200320103a00fe05200320113b01fc05200320123a00fb05200320133a00fa05200320143b01f805200320153a00f705200320163a00f605200320173b01f405200320183a00f305200320193a00f2052003201a3b01f005200341f0036a41186a22064200370300200341f0036a41106a22044200370300200341f0036a41086a22024200370300200342003703f00341a4e3c400ad4280808080c000841001220529000021082002200541086a290000370300200320083703f0032005102f4180e4c400ad42808080803084100122052900002108200341a8026a41086a2207200541086a290000370300200320083703a8022005102f200420032903a802220837030020034188026a41086a200229030037030020034188026a41106a200837030020034188026a41186a2007290300370300200320032903f0033703880220034180096a20034188026a412010ad0220032d0080092105200620034199096a290000370300200420034191096a290000370300200220034189096a29000037030020032003290081093703f0030240024020054101460d00200341f8076a41186a4200370300200341f8076a41106a4200370300200341f8076a41086a4200370300200342003703f8070c010b200341f8076a41186a2006290300370300200341f8076a41106a2004290300370300200341f8076a41086a2002290300370300200320032903f0033703f8070b200341f0056a200341f8076a412010ea060d232003418c096a200341f8066a41086a29030037020020034194096a200341f8066a41106a2903003702002003419c096a200341f8066a41186a2903003702002003201b36028009200320032903f80637028409200341f8076a20034180096a10bb0120034188026a41086a2202200341f8076a41096a29000037030020034188026a41106a221b200341f8076a41116a29000037030020034188026a41186a2205200341f8076a41196a290000370300200320032900f90737038802024020032d00f8074101460d00200341f0046a41186a2005290300370300200341f0046a41106a201b290300370300200341f0046a41086a200229030037030020032003290388023703f00442002108200341f0036a41186a22074200370300200341f0036a41106a22094200370300200341f0036a41086a22064200370300200342003703f00341a4e3c400ad4280808080c00084221c1001220a290000211d2006200a41086a2900003703002003201d3703f003200a102f4180e4c400ad42808080803084221d1001220a290000211e200341a8026a41086a220b200a41086a2900003703002003201e3703a802200a102f200420032903a802370000200441086a200b29030037000020022006290300370300201b200929030037030020052007290300370300200320032903f0033703880220034180096a20034188026a412010ad0220032d008009211b200720034180096a41196a290000370300200920034180096a41116a290000370300200620034180096a41096a29000037030020032003290081093703f0034100210241002104410021054100210641002107410021094100210a4100210b4100210c4100210d4100210e4100210f4100211041002111410021124100211341002114410021150240201b4101470d00200329038804210820032d008704210220032d008604210420032f018404210520032d008304210620032d008204210720032f018004210920032d00ff03210a20032d00fe03210b20032f01fc03210c20032d00fb03210d20032d00fa03210e20032f01f803210f20032d00f703211020032d00f603211120032f01f403211220032d00f303211320032d00f203211420032f01f00321150b2003419a096a200837010020034199096a20023a000020034180096a41186a221b20043a000020034196096a20053b010020034195096a20063a000020034194096a20073a000020034192096a20093b010020034191096a200a3a000020034180096a41106a2204200b3a00002003418e096a200c3b01002003418d096a200d3a00002003418c096a200e3a00002003418a096a200f3b010020034189096a20103a000020034180096a41086a220520113a0000200320123b018609200320133a008509200320143a008409200320153b0182092003418e023b01800941c8e1ca00410020034180096a108c01201b200341f0046a41186a2903003703002004200341f0046a41106a2903003703002005200341f0046a41086a290300370300200320032903f00437038009201c1001220229000021082002290008211c2002102f201d10012202290000211d2002290008211e2002102f2003201e370388042003201d370380042003201c3703f803200320083703f0034120102d2202450d4f2002200329038009370000200241186a201b290300370000200241106a2004290300370000200241086a2005290300370000200341f0036aad42808080808004842002ad428080808080048410042002102f200041043a00000c2b0b200041013a00000c2a0b2001412c6a2802002120200341f8066a41186a2007290300370300200341f8066a41106a2006290300370300200341f8066a41086a2005290300370300200320032903d0023703f806024002400240200241ff01710d00200441ff01714101470d002003200837038806200320093a0087062003200a3a0086062003200b3b0184062003200c3a0083062003200d3a0082062003200e3b0180062003200f3a00ff05200320103a00fe05200320113b01fc05200320123a00fb05200320133a00fa05200320143b01f805200320153a00f705200320163a00f605200320173b01f405200320183a00f305200320193a00f2052003201a3b01f005200341f0036a41186a22064200370300200341f0036a41106a22044200370300200341f0036a41086a22024200370300200342003703f00341a4e3c400ad4280808080c000841001220529000021082002200541086a290000370300200320083703f0032005102f4180e4c400ad42808080803084100122052900002108200341a8026a41086a2207200541086a290000370300200320083703a8022005102f200420032903a802220837030020034188026a41086a200229030037030020034188026a41106a200837030020034188026a41186a2007290300370300200320032903f0033703880220034180096a20034188026a412010ad0220032d0080092105200620034199096a290000370300200420034191096a290000370300200220034189096a29000037030020032003290081093703f0030240024020054101460d00200341f8076a41186a4200370300200341f8076a41106a4200370300200341f8076a41086a4200370300200342003703f8070c010b200341f8076a41186a2006290300370300200341f8076a41106a2004290300370300200341f8076a41086a2002290300370300200320032903f0033703f8070b200341f0056a200341f8076a412010ea060d0120034180096a410c6a200341f8066a41086a29030037020020034180096a41146a200341f8066a41106a2903003702002003419c096a200341f8066a41186a2903003702002003201b36028009200320032903f80637028409200341f8076a20034180096a10bb014101210220032d00f8074101460d02200341f8076a41086a2d0000211b20034181086a2f0000210420034183086a2d00002105200341f8076a410c6a2d0000210620034185086a2f0000210720034187086a2d00002109200341f8076a41106a2d0000210a20034189086a2f0000210b2003418b086a2d0000210c200341f8076a41146a2d0000210d2003418d086a2f0000210e2003418f086a2d0000210f200341f8076a41186a2d0000211020032f00f907211120032d00fb07211220032d00fc07211320032f00fd07211420032d00ff072115200320034191086a29000037038804200320103a0087042003200f3a0086042003200e3b0184042003200d3a0083042003200c3a0082042003200b3b0180042003200a3a00ff03200320093a00fe03200320073b01fc03200320063a00fb03200320053a00fa03200320043b01f8032003201b3a00f703200320153a00f603200320143b01f403200320133a00f303200320123a00f203200320113b01f00320034180096a202041b00210e8061a20034182086a20032903f8033701002003418a086a20032903800437010020034192086a20032903880437010020034180023b01f807200320032903f0033701fa07200341f0046a20034180096a200341f8076a108b01024020032d00f0044104460d0020034180096a41086a200341f0046a41086a280200360200200320032903f0043703800920034180096a108c03410021020b200320023a0082092003418e043b01800941c8e1ca00410020034180096a108c01200041043a00002020102f0c2c0b200041023a00000c280b20004183263b0100200041086a410b360200200041046a4199b3c400360200200041026a41003a00000c270b200041013a00000c260b2001411c6a280200210b200141186a280200210d200141146a280200210c2001410c6a280200210e200141086a280200211002400240024020022d00000d0020022d000141ff01714102470d00200141246a280200210f200141106a2802002107200341f0036a41186a22054200370300200341f0036a41106a22064200370300200341f0036a41086a221b4200370300200342003703f003419c9eca00ad4280808080f00084100122022900002108201b200241086a290000370300200320083703f0032002102f41a39eca00ad4280808080c001841001220229000821082002290000211c2002102f20034188026a41106a201c37030020034188026a41186a200837030020034188026a41086a201b290300370300200320032903f00337038802200341c8016a20034188026a412010950120032802cc01210420032802c801210941d39bca00ad4280808080800184100122022900002108200341a8026a41086a220a200241086a290000370300200320083703a8022002102f41db9bca00ad4280808080a0028410012202290008210820022d0007211120022d0006211220022f0004211320022d0003211420022d0002211520022f000021162002102f20032004410020091b22173602800920034180096aad22214280808080c00084221c10032202290000211d200241086a290000211e200241106a290000211f2005200241186a2900003703002006201f370300201b201e3703002003201d3703f0032002102f41c000102d2202450d4f200220032903a802370000200241086a200a290300370000200220113a0017200220123a0016200220133b0014200220143a0013200220153a0012200220163b001020022008370018200220032903f003370020200241286a201b290300370000200241306a2006290300370000200241386a20052903003700002003200f36028009201c100322042900002108200441086a290000211c200441106a290000211d2005200441186a2900003703002006201d370300201b201c370300200320083703f0032004102f200241c00041800110312202450d4f200220032903f003370040200241d8006a200341f0036a41186a2204290300370000200241d0006a200341f0036a41106a2205290300370000200241c8006a200341f0036a41086a221b290300370000200341c0016a200241e00041c8e1ca004100410010b50120032802c00121062002102f2004420037030020054200370300201b4200370300200342003703f00341d39bca00ad4280808080800184100122022900002108201b200241086a290000370300200320083703f0032002102f419087ca00ad4280808080c000841001220229000821082002290000211c2002102f20034188026a41106a201c37030020034188026a41186a200837030020034188026a41086a201b290300370300200320032903f0033703880220034180096a20034188026a108d032003280280092202410120021b2111200329028409420020021b210802402006410146221b0d002011200f4105746a4100200f2008422088a7491b22020d030b20004183283b0100200041026a201b3a0000200041086a4113410a201b1b360200200041046a41d0e0c30041e3e0c300201b1b3602002008a7450d012011102f0c010b200041023a00000b0240200e450d002010102f0b200b450d25200b410c6c2100200c210203400240200241046a280200450d002002280200102f0b2002410c6a2102200041746a22000d000c260b0b200241086a290000211c200241106a290000211d2002290000211e20034188026a41186a200241186a290000221f37030020034188026a41106a201d37030020034188026a41086a201c3703002003201e370388022003418d096a201c37000020034195096a201d3700002003419d096a201f370000200341003a0084092003410f3a0080092003201e3700850941c8e1ca00410020034180096a108c0120034100360288092003420137038009200720034180096a106902400240200328028409221b20032802880922026b2007490d00200328028009211b0c010b200220076a22042002490d37201b41017422052004200520044b1b22044100480d3702400240201b0d002004102d211b0c010b200328028009201b20041031211b0b201b450d4d20032004360284092003201b360280090b2003200220076a36028809201b20026a2010200710e8061a200b20034180096a1069200b450d22200c200b410c6c6a210a200c211b0340201b2802002107201b41086a280200220220034180096a106902400240200328028409220620032802880922046b2002490d0020032802800921050c010b200420026a22052004490d38200641017422092005200920054b1b22094100480d380240024020060d002009102d21050c010b20032802800920062009103121050b2005450d4e20032009360284092003200536028009200921060b2003200420026a220936028809200520046a2007200210e8061a201b410c6a221b200a470d000c240b0b20034180096a200141086a41a80210e8061a200341f8076a41206a200241206a290200370300200341f8076a41186a200241186a290200370300200341f8076a41106a200241106a290200370300200341f8076a41086a200241086a290200370300200320022902003703f807200020034180096a200341f8076a10b201410021134101211b41012104410121054101210641012107410121094101210a4101210b4101210c4101210d4101210e4101210f410121104101211141012112410121000c630b20034180096a200141046a41c40010e8061a200341f8076a41206a200241206a290200370300200341f8076a41186a200241186a290200370300200341f8076a41106a200241106a290200370300200341f8076a41086a200241086a290200370300200320022902003703f807200020034180096a200341f8076a108e03410021144101211b41012104410121054101210641012107410121094101210a4101210b4101210c4101210d4101210e4101210f41012110410121114101211241012113410121000c630b20034180096a200141086a41c80010e8061a200341f8076a41206a200241206a290200370300200341f8076a41186a200241186a290200370300200341f8076a41106a200241106a290200370300200341f8076a41086a200241086a290200370300200320022902003703f807200020034180096a200341f8076a108f03410021004101211b41012104410121054101210641012107410121094101210a4101210b4101210c4101210d4101210e4101210f410121104101211141012112410121130c610b200041023a0000410121044101211b410121050c530b200041023a00004101211b0c3b0b20004183363b0100200041086a4109360200200041046a41e1f0c000360200200041026a41023a00004101211b0c3a0b20004183363b0100200041086a4117360200200041046a41e6b4c600360200200041026a41013a00000c390b103d000b200041023a00004101211b0c4d0b200041023a00004101211b0c360b41b5e4c000413041f8b4ca001039000b200041023a00004101211b0c340b200041023a00004101211b0c330b410121054188d9c9002106410821070c2f0b200041830a3b0100200041086a410b360200200041046a41f8d8c900360200200041026a41033a00004101211b0c310b410121044188d9c9002105410821060c2c0b200041023a00004101211b0c2f0b200041023a00004101211b0c2e0b200041023a00004101211b0c2d0b200341f0036a41186a220b4200370300200341f0036a41106a22044200370300200341f0036a41086a221b4200370300200342003703f00341e7a2ca00ad4280808080800184221e10012209290000211f2009290008212e2009102f201b202e3703002003201f3703f00341ecb5c600ad4280808080d00184221f1001220a290000212e200341a8026a41086a2209200a41086a2900003703002003202e3703a802200a102f200420032903a802222e37030020034188026a41086a220c201b29030037030020034188026a41106a220d202e37030020034188026a41186a220e2009290300370300200320032903f0033703880220034180016a20034188026a4120109c0120034180016a41106a290300212e200329038801212f200328028001210a200b420037030020044200370300201b4200370300200342003703f003201e1001220b290000211e200b2900082130200b102f201b20303703002003201e3703f003201f1001220b290000211e2009200b41086a2900003703002003201e3703a802200b102f200420032903a802221e370300200c201b290300370300200d201e370300200e2009290300370300200320032903f003370388022003427f202e4200200a1b221e2008201d7d201c202154ad7d7c202f4200200a1b221f201c20217d7c2221201f54221bad7c221f201b201f201e54201f201e511b221b1b370388092003427f2021201b1b3703800920034180096a211b20034188026a21040c260b200041023a00004101211b0c2b0b200041023a00004101211b0c2a0b200041023a00000c220b419ae3c300411e41f8b4ca001039000b200041023a00000c1c0b41b8e3c300411d41f8b4ca001039000b200041023a00000c1a0b200041043a00000c190b200041023a00000c180b200041023a00000c170b200041023a00004101211b0c210b200041831e3b0100200041086a410e360200200041046a41e7e1c300360200200041026a41003a00000c200b200041023a00000c070b20004183263b0100200041086a410b360200200041046a4199b3c400360200200041026a41003a00000c060b2003280288092109200328028409210620032802800921050b41d39bca00ad428080808080018410012202290000211c200341a8026a41086a221b200241086a2900003703002003201c3703a8022002102f41db9bca00ad4280808080a0028410012202290008211c20022d0007211220022d0006211320022f0004211420022d0003211520022d0002211620022f000021182002102f200320173602800920214280808080c00084221d10032202290000211e200241086a290000211f200241106a2900002121200341f0036a41186a2204200241186a290000370300200341f0036a41106a22072021370300200341f0036a41086a220a201f3703002003201e3703f0032002102f41c000102d2202450d28200220032903a802370000200241086a201b290300370000200220123a0017200220133a0016200220143b0014200220153a0013200220163a0012200220183b00102002201c370018200220032903f003370020200241286a200a290300370000200241306a2007290300370000200241386a20042903003700002003200f36028009201d1003221b290000211c201b41086a290000211d201b41106a290000211e2004201b41186a2900003703002007201e370300200a201d3703002003201c3703f003201b102f200241c00041800110312202450d28200220032903f003370040200241d8006a20034188046a290300370000200241d0006a20034180046a290300370000200241c8006a200341f8036a290300370000200341e0003602840920032002360280092005200920034180096a109d022002102f02402006450d002005102f0b02402008a7450d002011102f0b200041043a00000240200e450d002010102f0b200b450d00200b410c6c2100200c210203400240200241046a280200450d002002280200102f0b2002410c6a2102200041746a22000d000b0b410021124101211b0240200d450d00200c102f0b41012104410121054101210641012107410121094101210a4101210b4101210c4101210d4101210e4101210f41012110410121110c3e0b2020108e012020102f0c020b201b108e010b201b102f0b41002111410121044101211b410121054101210641012107410121094101210a4101210b4101210c4101210d4101210e4101210f410121100c390b2005102f0b41012104410121054101210641012107410121094101210a4101210b4101210c4101210d0c340b2009201b4105746a200341d0026a412010ea060d01410d210d41f2b6c400210e4100210a0b200041831c3b0100200041086a200d360200200041046a200e360200200041026a200a3a00002008a7450d082009102f0c080b20034188026a41186a2206200341d0026a41186a29030037030020034188026a41106a2207200341d0026a41106a29030037030020034188026a41086a221b200341d0026a41086a290300370300200320032903d002370388022002200c4f0d01200f200329038802370000200f41186a2006290300370000200f41106a2007290300370000200f41086a201b2903003700002009200c108701200341f0046a41186a22074200370300200341f0046a41106a22064200370300200341f0046a41086a22024200370300200342003703f00441eba1c600ad4280808080b00284221c1001220a290000211d201b200a41086a2900003703002003201d37038802200a102f2002201b29030037030020032003290388023703f00441ebdec700ad4280808080f000841001220a290000211d201b200a41086a2900003703002003201d37038802200a102f2006200329038802221d370300200341f0036a41086a220e2002290300370300200341f0036a41106a220f201d370300200341f0036a41186a2210201b290300370300200320032903f0043703f00320034120360284092003200341f0036a360280092009200c20034180096a10aa0120034180096a41186a200341f8066a41186a29030037030020034180096a41106a200341f8066a41106a29030037030020034180096a41086a200341f8066a41086a290300370300200320032903f806370380094101210d20034180096a41012009200c108803200742003703002006420037030020024200370300200342003703f004201c1001220a290000211c201b200a41086a2900003703002003201c37038802200a102f2002201b29030037030020032003290388023703f00441fbd4c700ad4280808080d000841001220a290000211c201b200a41086a2900003703002003201c37038802200a102f2006200329038802221c370300200e2002290300370300200f201c3703002010201b290300370300200320032903f0043703f00320034180096a200341f0036a412010ad0220032d008009211b200720034180096a41196a290000370300200620034180096a41116a290000370300200220034180096a41096a29000037030020032003290081093703f00402400240201b4101460d004100210d200341003a00f0050c010b200341f0056a41096a200341f8046a290300370000200341f0056a41116a20034180056a290300370000200341f0056a41196a20034188056a290300370000200341013a00f005200320032903f0043700f1050b20034199096a20034190076a29030037000020034191096a20034188076a29030037000020034189096a20034180076a290300370000200320032903f80637008109200341013a0080090240200d450d00200341f0056a41017220034180096a410172412010ea060d00200341f0046a41186a220a4200370300200341f0046a41106a220c4200370300200341f0046a41086a221b4200370300200342003703f00441eba1c600ad4280808080b0028410012207290000211c20034188026a41086a2202200741086a2900003703002003201c370388022007102f201b200229030037030020032003290388023703f00441fbd4c700ad4280808080d0008410012207290000211c2002200741086a2900003703002003201c370388022007102f2006200329038802370000200641086a2002290300370000200341f0036a41086a201b290300370300200341f0036a41106a200c290300370300200341f0036a41186a200a290300370300200320032903f0043703f0034120102d2202450d1f200220032903d002370000200241186a200341d0026a41186a221b290300370000200241106a200341d0026a41106a2206290300370000200241086a200341d0026a41086a2207290300370000200341f0036aad42808080808004842002ad428080808080048410042002102f20034199096a201b29030037000020034191096a200629030037000020034189096a2007290300370000200320032903d00237008109200341013a00800920034180096a1089030b2008a7450d002009102f0b2003418a083b01800941c8e1ca00410020034180096a108c01200041043a00000c060b419cc3ca002002200c103b000b2009201b4105746a200341d0026a412010ea060d01410d210d41f2b6c400210e4100210c0b200041831c3b0100200041086a200d360200200041046a200e360200200041026a200c3a00002008a7450d032009102f0c030b200341f0036a41186a2207200341d0026a41186a290300370300200341f0036a41106a220c200341d0026a41106a290300370300200341f0036a41086a220d200341d0026a41086a290300370300200320032903d0023703f00302402002200a4f0d00200f20032903f003370000200f41186a2007290300370000200f41106a200c290300370000200f41086a200d2903003700002009200a10870120034188026a41186a420037030020034188026a41106a420037030020034188026a41086a22024200370300200342003703880241eba1c600ad4280808080b00284221c1001221b290000211d201b290008211e201b102f2002201e3703002003201d3703880241ebdec700ad4280808080f000841001221b290008211d201b290000211e201b102f200341f0046a41106a2206201e370300200341f0046a41186a220e201d370300200341f0046a41086a221b200229030037030020032003290388023703f00420034120360284092003200341f0046a360280092009200a20034180096a10aa0120034180096a41186a200341e0016a41186a29030037030020034180096a41106a200341e0016a41106a29030037030020034180096a41086a200341e0016a41086a290300370300200320032903e0013703800920034180096a41012009200a108803200e420037030020064200370300201b4200370300200342003703f004201c1001220f290000211c2002200f41086a2900003703002003201c37038802200f102f201b200229030037030020032003290388023703f00441fbd4c700ad4280808080d000841001220f290000211c2002200f41086a2900003703002003201c37038802200f102f2006200329038802221c370300200d201b290300370300200c201c37030020072002290300370300200320032903f0043703f00320034180096a200341f0036a412010ad0220032d0080092102200e20034199096a290000370300200620034191096a290000370300201b20034189096a29000037030020032003290081093703f004024020024101470d00200341f8066a41186a200341f0046a41186a290300221c370300200341f8066a41106a200341f0046a41106a290300221d370300200341f8066a41086a200341f0046a41086a290300221e370300200320032903f004221f3703f806200341f0056a41186a201c370300200341f0056a41106a201d370300200341f0056a41086a201e3703002003201f3703f005410021020240200a4101460d004100210203402002200a410176221b20026a2206200920064105746a200341f0056a412010ea0641004a1b2102200a201b6b220a41014b0d000b0b0240200920024105746a200341f0056a412010ea06450d00200341d0036a41186a4200370300200341d0036a41106a22064200370300200341d0036a41086a22024200370300200342003703d00341eba1c600ad4280808080b002841001221b290000211c200341b8026a41086a2207201b41086a2900003703002003201c3703b802201b102f20022007290300370300200320032903b8023703d00341fbd4c700ad4280808080d000841001221b290000211c200341a8026a41086a2207201b41086a2900003703002003201c3703a802201b102f200620032903a802221c37030020034180096a41086a200229030037030020034180096a41106a201c37030020034180096a41186a2007290300370300200320032903d0033703800920034180096aad428080808080048410050c010b20034199096a20034188066a29030037000020034191096a20034180066a29030037000020034189096a200341f8056a290300370000200320032903f00537008109200341013a00800920034180096a1089030b2003418a043b01800941c8e1ca00410020034180096a108c0102402008a7450d002009102f0b200041043a00000c030b419cc3ca002002200a103b000b20034180096a41186a200341f0056a41186a29030037030020034180096a41106a200341f0056a41106a29030037030020034180096a41086a200341f0056a41086a290300370300200320032903f005370380094100210a20034180096a211b410021060b0240200a200d470d00200c200a470d00200c41016a2202200c490d02200c41017422072002200720024b1b220241ffffff3f712002470d02200241057422024100480d0202400240200c0d002002102d21090c010b2009200c4105742002103121090b2009450d18200320093602f8062002410576210c0b200920064105746a220241206a2002200a20066b41057410e9061a200241186a201b41186a290000370000200241106a201b41106a290000370000200241086a201b41086a2900003700002002201b290000370000200341f0046a41186a4200370300200341f0046a41106a22074200370300200341f0046a41086a221b4200370300200342003703f00441eba1c600ad4280808080b0028410012206290000210820034188026a41086a2202200641086a29000037030020032008370388022006102f201b200229030037030020032003290388023703f00441ebdec700ad4280808080f000841001220629000021082002200641086a29000037030020032008370388022006102f20072003290388022208370300200341f0036a41086a201b290300370300200341f0036a41106a2008370300200341f0036a41186a2002290300370300200320032903f0043703f00320034120360284092003200341f0036a3602800920032802f806200a41016a220220034180096a10aa0120034180096a41186a200341f0056a41186a29030037030020034180096a41106a200341f0056a41106a29030037030020034180096a41086a200341f0056a41086a290300370300200320032903f0053703800941c8e1ca00410020032802f806221b20021088032003410a3b01800941c8e1ca00410020034180096a108c010240200c450d00201b102f0b200041043a00000b200b4104470d0220050d010c020b1038000b2004102f0b4100210d410121044101211b410121054101210641012107410121094101210a4101210b4101210c0c250b41002107410121044101211b41012105410121060c1f0b2004ad4280808080800484201bad4280808080800284100420032903c002211f20032903b802211e0b202b202d7c2121200341f0046a41106a211b024002400240201e202256201f202356201f20235122041b0d00201e202254201f20235420041b450d02200341f0036a41186a220c4200370300200341f0036a41106a22094200370300200341f0036a41086a22044200370300200342003703f00341e7a2ca00ad4280808080800184222b1001220a290000212d200a290008212e200a102f2004202e3703002003202d3703f00341ecb5c600ad4280808080d00184222d1001220b290000212e200341a8026a41086a220a200b41086a2900003703002003202e3703a802200b102f200920032903a802222e37030020034188026a41086a220d200429030037030020034188026a41106a220e202e37030020034188026a41186a220f200a290300370300200320032903f00337038802200341e8006a20034188026a4120109c01200341e8006a41106a290300212e2003290370212f2003280268210b200c42003703002009420037030020044200370300200342003703f003202b1001220c290000212b200c2900082130200c102f200420303703002003202b3703f003202d1001220c290000212b200a200c41086a2900003703002003202b3703a802200c102f200920032903a802222b370300200d2004290300370300200e202b370300200f200a290300370300200320032903f0033703880220034200202e4200200b1b222b2022201e54ad201f20237d7c7c202f4200200b1b22232022201e7d222d54ad7d22222023202d7d222d2023562022202b562022202b511b22041b3703880920034200202d20041b3703800920034180096a210420034188026a21090c010b200341f0036a41186a220c4200370300200341f0036a41106a22094200370300200341f0036a41086a22044200370300200342003703f00341e7a2ca00ad4280808080800184222b1001220a290000212d200a290008212e200a102f2004202e3703002003202d3703f00341ecb5c600ad4280808080d00184222d1001220b290000212e200341a8026a41086a220a200b41086a2900003703002003202e3703a802200b102f200920032903a802222e37030020034188026a41086a220d200429030037030020034188026a41106a220e202e37030020034188026a41186a220f200a290300370300200320032903f00337038802200341d0006a20034188026a4120109c01200341d0006a41106a290300212e2003290358212f2003280250210b200c42003703002009420037030020044200370300200342003703f003202b1001220c290000212b200c2900082130200c102f200420303703002003202b3703f003202d1001220c290000212b200a200c41086a2900003703002003202b3703a802200c102f200920032903a802222b370300200d2004290300370300200e202b370300200f200a290300370300200320032903f003370388022003427f202e4200200b1b222b201f20237d201e202254ad7d7c202f4200200b1b2223201e20227d7c222d2023542204ad7c222220042022202b542022202b511b22041b370388092003427f202d20041b3703800920034180096a210420034188026a21090b2009ad42808080808004842004ad428080808080028410040b2021201d5121092021201d54210a2003201c3703f0042003201f370388052003201e37038005200320083703f80420032802cc022104200341f0036a41186a201b41086a290300221d370300200341f0036a41206a220b201b41106a29030037030020034198046a220c201b41186a290300370300200341a0046a220d201b41206a290300370300200320083703f8032003201c3703f0032003201b29030022223703800402400240427f201c20227c22222022201c54221b2008201d7c201bad7c221d200854201d2008511b221b1b2222428080e983b1de16544100427f201d201b1b2223501b0d00200341f0036a41106a2903002122200d2903002123200c290300212b200b290300212d20032903f803212e20032903f003212f4201211d20032903880421300c010b4200211d02402022202384500d0020222023109a01200341b8096a2023370300200341b0096a202237030020034180096a41086a41013a000020034189096a200429000037000020034191096a200441086a29000037000020034199096a200441106a290000370000200341a1096a200441186a290000370000200341033a00800941c8e1ca00410020034180096a108c010b0b2007200a20091b211b200341a0076a202d370300200341a8076a202b37030020034188076a202e370300200341b0076a202337030020034190076a202237030020032030370398072003202a3703b8072003202f37038007200320064100202442015122071b3a00c40720032005410020071b3602c0072003201d4201512205ad3703f8060240024020050d002002ad428080808080088410050c010b200341c00036028409200320023602800920034180076a20034180096a1090030b427f2021201b1b2121427f202c201b1b21222002102f201d420152210202400240024020244201510d0020020d004103211b200341f8076a21020c010b20244201522002410173720d014104211b200341f0056a21020b200241046a201b3a0000200241056a20032903d003370000200241003a00002002410d6a200341d8036a290300370000200241156a200341e0036a2903003700002002411d6a200341e8036a29030037000041c8e1ca0041002002108c010b0240202220218450450d00200341b8096a2008370300200341b0096a201c37030020034180096a41086a41003a000020034189096a200429000037000020034191096a200441086a29000037000020034199096a200441106a290000370000200341a1096a200441186a290000370000200341033a00800941c8e1ca00410020034180096a108c010b200341c8096a201f370300200341c0096a201e370300200341b8096a2008370300200341b0096a201c37030020034180096a41086a41033a000020034189096a20032903d00337000020034191096a200341d0036a41086a29030037000020034199096a200341e0036a290300370000200341a1096a200341e8036a290300370000200341033a00800941c8e1ca00410020034180096a108c01200041043a00004101211b0c040b024020032802f403450d00201b102f0b024020024104470d0020034188096a20173602004101211b200341013a008409200341023a00800941c8e1ca00410020034180096a108c01200041043a00000c040b200041053a0001200020023a0000200041086a2006360200200041046a2005360200200041026a20043a00004101211b0c030b024020032802f404450d00201b102f0b0240200241ff01714104470d00200341a8096a20183602002003418d096a200341f8056a29030037000020034195096a20034180066a2903003700002003419d096a20034188066a290300370000200341003a008409200341023a008009200320032903f0053700850941c8e1ca00410020034180096a108c01200041043a00004101211b0c030b200020043a0001200020023a0000200041086a2007360200200041046a2006360200200041036a20093a0000200041026a20053a00004101211b0c020b4100211b200241ff01714104470d00200341b0096a4200370300200341a8096a428080e983b1de1637030020034180096a41106a200341f0056a41086a29030037030020034180096a41186a200341f0056a41106a29030037030020034180096a41206a200341f0056a41186a2903003703002003420137038009200320032903f005370388094110102d2202450d0d20024110412010312202450d0d200220034180096a41086a221b290000370000200241186a201b41186a290000370000200241106a201b41106a290000370000200241086a201b41086a2900003700002002412041c00010312202450d0d2002428080e983b1de16370020200241286a4200370000200bad4220862004ad842002ad428080808080068410042002102f410421024101211b0b024020032802f403450d002004102f0b0240201b450d00200341a8096a20173602002003418d096a20034180076a29030037000020034195096a20034188076a2903003700002003419d096a20034190076a290300370000200341003a008409200341023a008009200320032903f8063700850941c8e1ca00410020034180096a108c01200041043a00004101211b0c010b2000200a3a0001200020023a0000200041086a2005360000200041046a2006360000200041036a20073a0000200041026a20093a00004101211b0b41012104410121050c160b200041086a201b360200200041046a2004360200200041026a201a3a000020004183083b01000240200328028c092202450d00200241246c2100200e210203400240024020022d0000221b41044b0d00024002400240201b0e050400010204040b2002410c6a280200450d03200241086a280200102f0c030b2002410c6a280200450d02200241086a280200102f0c020b2002410c6a280200450d01200241086a280200102f0c010b200241086a280200450d00200241046a280200102f0b200241246a21022000415c6a22000d000b0b0240200328028809450d00200e102f0b024020272005460d00034020061097010240200641046a280200450d002006280200102f0b200641f0006a2106200941907f6a22090d000b0b0240200c450d00200a102f0b20110d020c030b20272005460d00200a200741f0006c6a21040340200541046a221b109701200541f0006a21020240200541086a280200450d00201b280200102f0b2002210520042002470d000b0b0240200c450d00200a102f0b200341f0036a41186a4200370300200341f0036a41106a4200370300200341f0036a41086a22024200370300200342003703f003419487ca00ad4280808080a001841001221b2900002108201b290008211c201b102f2002201c370300200320083703f003418691c700ad4280808080e000841001221b2900082108201b290000211c201b102f20034188026a41106a201c37030020034188026a41186a200837030020034188026a41086a2002290300370300200320032903f0033703880220034180096a200d200f109103201e2003350288094220862003280280092202ad8410040240200328028409450d002002102f0b200041043a00002011450d010b200d102f0b410021054101211b0c020b200741f0006c2100200a41046a2102034020021097010240200241046a280200450d002002280200102f0b200241f0006a2102200041907f6a22000d000b0b410021054101211b200c450d00200a102f0b410121040c0e0b201e201c84202184202384201f201d8420228420248484500d014113210241e4e3c300211b410521040b200041033b0100200041086a2002360200200041046a201b360200200041026a20043a00004101211b0c0b0b418de6c300ad4280808080e00084100122022d000f211720022d000e211820022f000c211920022d000b211a20022d000a212020022f0008212820022d0007212920022d0006212720022f0004212520022d0003212620022d0002213120022f000021322002102f41f0e8c600ad4280808080f0008410012202290008211c20022d0007213320022d0006213420022f0004213520022d0003213620022d0002213720022f000021382002102f4120102d2202450d0020022008370018200220043a0017200220053a0016200220063b0014200220073a0013200220093a00122002200a3b00102002200b3a000f2002200c3a000e2002200d3b000c2002200e3a000b2002200f3a000a200220103b0008200220113a0007200220123a0006200220133b0004200220143a0003200220153a0002200220163b00002002ad42808080808004841003221b2900002108201b41086a290000211d201b41106a290000211e20034188026a41186a2204201b41186a29000037030020034188026a41106a2205201e37030020034188026a41086a2206201d3703002003200837038802201b102f2002102f41c000102d2202450d00200220173a000f200220183a000e200220193b000c2002201a3a000b200220203a000a200220283b0008200220293a0007200220273a0006200220253b0004200220263a0003200220313a0002200220323b0000200220333a0017200220343a0016200220353b0014200220363a0013200220373a0012200220383b00102002201c370018200241386a2004290300370000200241306a2005290300370000200241286a200629030037000020022003290388023700202002ad428080808080088410052002102f200041043a00004101211b0c0a0b1036000b200041033b0100200041086a201b360200200041046a2004360200200041026a200a3a000002402006450d002007102f0b02402009450d00200b102f0b2013450d05200f102f0c050b2009450d00200b102f0b2006450d010b2007102f0b2004450d00201b102f0b200041033b0100200041086a411d360200200041046a41f7e3c300360200200041026a41043a00000b4101211602402002450d002015102f0b41012117410121180b4101211b4100210402402005417e6a220241074b0d00410121054101210641012107410121094101210a4101210b4101210c4101210d4101210e4101210f410121104101211141012112410121134101210041012114024002400240024002400240024020020e080618040318020100060b41000d082008a70d070c080b2018450d0502402008422088a72202450d002002410c6c21002015210203400240200241046a280200450d002002280200102f0b2002410c6a2102200041746a22000d000b0b2008a7450d050c030b2017450d0402402008422088a72202450d00200241186c21002015210203400240200241046a280200450d002002280200102f0b0240200241106a280200450d002002410c6a280200102f0b200241186a2102200041686a22000d000b0b2008a7450d040c020b41000d052008a70d040c050b20162008a745720d020b2015102f410121050c040b41000d022008a70d010c020b410121050c020b2015102f0b41002104410121050b410121060b410121070b410121090b4101210a0b4101210b0b4101210c0b4101210d0b4101210e0b4101210f0b410121100b410121110b410121120b41012113410121000b410121140b02402001280200220241194b0d0002400240024002400240024002400240024002400240024002400240024002400240024020020e1a111012120f12120e0d0c0b0a0908120706050403121212020100110b2014450d1120012d0004417f6a220241024b0d110240024020020e03001301000b200141286a22012802001092032001280200102f0c120b2001410c6a280200450d11200141086a280200102f0c110b2000450d10200141086a2d00004108470d10200141346a280200450d10200141306a280200102f0c100b2013450d0f200141086a1093030c0f0b2012450d0e02402001410c6a280200450d00200141086a280200102f0b02402001411c6a2802002200450d00200141146a28020021022000410c6c210003400240200241046a280200450d002002280200102f0b2002410c6a2102200041746a22000d000b0b200141186a280200450d0e2001280214102f0c0e0b2011450d0d02402001280204220241024b0d00024020020e030f000f0f0b200141086a22012802001092032001280200102f0c0e0b2001412c6a22012802001092032001280200102f0c0d0b2010450d0c200141086a2d0000417e6a220241024b0d0c02400240024020020e03000102000b200141106a280200450d0e2001410c6a280200102f0c0e0b200141346a280200450d0d200141306a280200102f0c0d0b200141306a280200450d0c2001412c6a280200102f0c0c0b200f450d0b200141086a2d0000417c6a220241024b0d0b0240024020020e03000d01000b200141306a280200450d0c2001412c6a280200102f0c0c0b200141306a280200450d0b2001412c6a280200102f0c0b0b200e450d0a200141086a280200450d0a2001280204102f0c0a0b200d450d0920012d00044104470d092001410c6a280200450d09200141086a280200102f0c090b200c450d08200141086a2802004101470d08200141106a280200450d082001410c6a280200102f0c080b200b450d0720012d0004417f6a220241024b0d0702400240024020020e03000102000b2001412c6a280200450d09200141286a280200102f0c090b200141086a22012802001092032001280200102f0c080b2001410c6a22012802001092032001280200102f0c070b200a450d0620012d0004417f6a220241024b0d0602400240024020020e03000102000b2001412c6a280200450d08200141286a280200102f0c080b200141086a22012802001092032001280200102f0c070b2001410c6a22012802001092032001280200102f0c060b2009450d05200141086a2d0000416d6a220241014b0d050240024020020e020001000b200141106a280200450d062001410c6a280200102f0c060b200141106a280200450d052001410c6a280200102f0c050b2007450d0420012802042202450d04200141086a280200450d042002102f0c040b2006450d03200141086a1094030c030b2005450d0202402001410c6a2802002202450d00200241f0006c2100200128020441046a2102034020021097010240200241046a280200450d002002280200102f0b200241f0006a2102200041907f6a22000d000b0b200141086a280200450d022001280204102f0c020b201b450d01200141046a1095030c010b2004450d00200141086a1096030b200341b00b6a24000bd12e05087f037e047f017e037f23004180046b22032400200341186a4180e5c3004110109501200328021c2104200328021821054101210641002107410021080240024002400240024002402001450d00200141057422074100480d022007102d2206450d012001410574220941606a410576210a2006210720002108034020072008290000370000200741086a200841086a290000370000200741106a200841106a290000370000200741186a200841186a290000370000200741206a2107200841206a2108200941606a22090d000b200a41016a2108200121070b200341a4016a200436020020032005453602a001200341206a200241800110e8061a200341b0016a2008360200200341ac016a2007360200200320063602a801200341d0026a41186a22064200370300200341d0026a41106a22024200370300200341d0026a41086a22074200370300200342003703d002418de6c300ad4280808080e00084220b10012209290000210c200341c8036a41086a2208200941086a2900003703002003200c3703c8032009102f20072008290300370300200320032903c8033703d00241d882c400ad4280808080a00184220d10012204290000210c200341e0036a41086a2209200441086a2900003703002003200c3703e0032004102f200220032903e003220c370300200341f0026a41086a22042007290300370300200341f0026a41106a200c370300200341f0026a41186a22052009290300370300200320032903d0023703f002200341106a200341f0026a412010950102400240024002400240024002402003280214410020032802101b220e41016a220f200e490d0020064200370300200341d0026a41106a220a420037030020074200370300200342003703d002200b10012210290000210c2008201041086a2900003703002003200c3703c8032010102f20072008290300370300200320032903c8033703d002200d10012210290000210c2009201041086a2900003703002003200c3703e0032010102f200220032903e003370000200241086a2210200929030037000020042007290300370300200341f0026a41106a2211200a29030037030020052006290300370300200320032903d0023703f0022003200f3602b801200341f0026aad4280808080800484220c200341b8016aad4280808080c000841004200341b8016a200341206a41980110e8061a20064200370300200a420037030020074200370300200342003703d002200b1001220f290000210b2008200f41086a2900003703002003200b3703c803200f102f20072008290300370300200320032903c8033703d00241baebc300ad4280808080e0008410012208290000210b2009200841086a2900003703002003200b3703e0032008102f200220032903e00337000020102009290300370000200420072903003703002011200a29030037030020052006290300370300200320032903d0023703f002200341c8036a200c100210730240024020032802c803450d0020034190036a41086a200341c8036a41086a280200360200200320032903c803370390030c010b200341003602e803200342083703e0034104102d2207450d08200342043702d402200320073602d0024100200341d0026a106920034198036a20032802d802360200200320032903d00237039003200341e0036a10f4030b200341a0036a41086a20034190036a41086a280200220736020020032003290390033703a003024002402007450d00200341d0026a20032802a0032007410110c40220032802d0024101470d0120032802a403450d0c20032802a003102f0c0c0b4101200341a0036a10690240024020032802b8024101460d000240024020032802a40320032802a8032207460d0020032802a00321080c010b200741016a22082007490d0c200741017422092008200920084b1b22094100480d0c0240024020070d002009102d21080c010b20032802a00320072009103121080b2008450d0b200320093602a403200320083602a00320032802a80321070b2003200741016a3602a803200820076a41003a000020032802bc0221090240024020032802a403220820032802a80322076b4104490d0020032802a00321080c010b200741046a22062007490d0c200841017422072006200720064b1b22074100480d0c0240024020080d002007102d21080c010b20032802a00320082007103121080b2008450d0b200320073602a403200320083602a00320032802a80321070b2003200741046a3602a803200820076a20093600000c010b0240024020032802a40320032802a8032207460d0020032802a00321080c010b200741016a22082007490d0b200741017422092008200920084b1b22094100480d0b0240024020070d002009102d21080c010b20032802a00320072009103121080b2008450d0a200320093602a403200320083602a00320032802a80321070b2003200741016a3602a803200820076a41013a00000b200341b8016a200341a0036a10ef0220032802c00220032802c802200341a0036a1089010c060b20032802d40221060240200341dc026a2802002207200341d0026a41086a2802002208460d0020032802a803200720086b6a220941046a2204417f4c0d0a0240024020040d00410121050c010b2004102d2205450d090b200320043602b403200320053602b003200320093602b8032003200341b0036a3602d0022006200341d0026a200710c50220092007490d0220032802b80322062009490d0320032802a80322062008490d0420032802b003210420032802a00321052003200920076b22093602c0032003200620086b22063602c40320092006470d05200420076a200520086a200910e8061a0240024020032802b8024101460d000240024020032802b40320032802b8032207460d0020032802b00321080c010b200741016a22082007490d0c200741017422092008200920084b1b22094100480d0c0240024020070d002009102d21080c010b20032802b00320072009103121080b2008450d0b200320093602b403200320083602b00320032802b80321070b2003200741016a3602b803200820076a41003a000020032802bc0221090240024020032802b403220820032802b80322076b4104490d0020032802b00321080c010b200741046a22062007490d0c200841017422072006200720064b1b22074100480d0c0240024020080d002007102d21080c010b20032802b00320082007103121080b2008450d0b200320073602b403200320083602b00320032802b80321070b2003200741046a3602b803200820076a20093600000c010b0240024020032802b40320032802b8032207460d0020032802b00321080c010b200741016a22082007490d0b200741017422092008200920084b1b22094100480d0b0240024020070d002009102d21080c010b20032802b00320072009103121080b2008450d0a200320093602b403200320083602b00320032802b80321070b2003200741016a3602b803200820076a41013a00000b200341b8016a200341b0036a10ef0220032802c00220032802c802200341b0036a10890120032802b803210820032802b403210920032802b003210720032802a403450d0720032802a003102f0c070b2003200341a0036a3602d0022006200341d0026a200810c5020240024020032802b8024101460d000240024020032802a40320032802a8032207460d0020032802a00321080c010b200741016a22082007490d0b200741017422092008200920084b1b22094100480d0b0240024020070d002009102d21080c010b20032802a00320072009103121080b2008450d0a200320093602a403200320083602a00320032802a80321070b2003200741016a3602a803200820076a41003a000020032802bc0221090240024020032802a403220820032802a80322076b4104490d0020032802a00321080c010b200741046a22062007490d0b200841017422072006200720064b1b22074100480d0b0240024020080d002007102d21080c010b20032802a00320082007103121080b2008450d0a200320073602a403200320083602a00320032802a80321070b2003200741046a3602a803200820076a20093600000c010b0240024020032802a40320032802a8032207460d0020032802a00321080c010b200741016a22082007490d0a200741017422092008200920084b1b22094100480d0a0240024020070d002009102d21080c010b20032802a00320072009103121080b2008450d09200320093602a403200320083602a00320032802a80321070b2003200741016a3602a803200820076a41013a00000b200341b8016a200341a0036a10ef0220032802c00220032802c802200341a0036a1089010c050b200341206a1088040c0a0b20072009104b000b20092006104a000b20082006104b000b200341e0036a41146a4109360200200341ec036a410a360200200341c8036a41146a41033602002003200341c0036a3602f8032003200341c4036a3602fc03200341d0026a41146a4100360200200342033702cc03200341b4e0ca003602c8032003410a3602e403200341c8e1ca003602e002200342013702d40220034188e1ca003602d0022003200341e0036a3602d8032003200341d0026a3602f0032003200341fc036a3602e8032003200341f8036a3602e003200341c8036a41c8e1ca001043000b20032802a803210820032802a403210920032802a00321070b2007450d03200c2008ad4220862007ad84100402402009450d002007102f0b200341b8016a108804200341d0026a41186a22044200370300200341d0026a41106a22054200370300200341d0026a41086a22064200370300200342003703d002418de6c300ad4280808080e00084221210012207290000210b200341c8036a41086a2209200741086a2900003703002003200b3703c8032007102f20062009290300370300200320032903c8033703d002419ce6c300ad4280808080e0008410012207290000210b200341e0036a41086a220a200741086a2900003703002003200b3703e0032007102f200220032903e003370000200241086a200a290300370000200341f0026a41086a22132006290300370300200341f0026a41106a2005290300370300200341f0026a41186a2004290300370300200320032903d0023703f002200341086a200341f0026a41201095012001450d04200328020c410020032802081b2114200141057421020340201210012207290000210b2009200741086a2900003703002003200b3703c8032007102f41c0ebc300ad4280808080b0018410012207290000210b200a200741086a2900003703002003200b3703e0032007102f4120102d2207450d0120072000290000370000200741186a200041186a290000370000200741106a200041106a290000370000200741086a200041086a2900003700002007ad428080808080048410032208290000210b200841086a290000210c200841106a290000210d2004200841186a2900003703002005200d3703002006200c3703002003200b3703d0022008102f2007102f41c000102d2207450d01200720032903c803370000200720032903e003370010200720032903d002370020200741086a2009290300370000200741186a200a290300370000200741286a2006290300370000200741306a2005290300370000200741386a2004290300370000200341f0026a2007ad4280808080800884220b100210730240024020032802f002450d00200341b0036a41086a2013280200360200200320032903f0023703b0030c010b4104102d2208450d02200342043702bc01200320083602b8014100200341b8016a1069200341b0036a41086a20032802c001360200200320032903b8013703b0030b2009200341b0036a41086a2802002208360200200320032903b0033703c8030240024002400240024002400240024002400240024002402008450d00200341b8016a20032802c8032008410110c40220032802b8014101460d0420032802bc01211020032802c401220820032802c0012201460d0320032802d003200820016b6a220f41046a2211417f4c0d0f20110d01410121150c020b4101200341c8036a10690240024020032802cc03220120032802d00322086b4104490d0020032802c80321010c010b200841046a220f2008490d0e20014101742208200f2008200f4b1b22084100480d0e0240024020010d002008102d21010c010b20032802c80320012008103121010b2001450d0d200320083602cc03200320013602c80320032802d00321080b2003200841046a3602d003200120086a20143600000240024020032802cc03220120032802d00322086b4104490d0020032802c80321010c010b200841046a220f2008490d0e20014101742208200f2008200f4b1b22084100480d0e0240024020010d002008102d21010c010b20032802c80320012008103121010b2001450d0d200320083602cc03200320013602c80320032802d00321080b2003200841046a3602d003200120086a200e3600000c080b2011102d2215450d0b0b200320113602d402200320153602d0022003200f3602d8022003200341d0026a3602b8012010200341b8016a200810c502200f2008490d0220032802d8022210200f490d0320032802d00322102001490d0420032802d002211120032802c80321152003200f20086b220f3602f8032003201020016b22103602fc03200f2010470d05201120086a201520016a200f10e8061a0240024020032802d402220120032802d80222086b4104490d0020032802d00221010c010b200841046a220f2008490d0c20014101742208200f2008200f4b1b22084100480d0c0240024020010d002008102d21010c010b20032802d00220012008103121010b2001450d0b200320083602d402200320013602d00220032802d80221080b2003200841046a3602d802200120086a20143600000240024020032802d402220120032802d80222086b4104490d0020032802d00221010c010b200841046a220f2008490d0c20014101742208200f2008200f4b1b22084100480d0c0240024020010d002008102d21010c010b20032802d00220012008103121010b2001450d0b200320083602d402200320013602d00220032802d80221080b2003200841046a3602d802200120086a200e36000020032802d802210120032802d402210f20032802d002210820032802cc03450d0720032802c803102f0c070b2003200341c8036a3602b8012010200341b8016a200110c5020240024020032802cc03220120032802d00322086b4104490d0020032802c80321010c010b200841046a220f2008490d0b20014101742208200f2008200f4b1b22084100480d0b0240024020010d002008102d21010c010b20032802c80320012008103121010b2001450d0a200320083602cc03200320013602c80320032802d00321080b2003200841046a3602d003200120086a20143600000240024020032802cc03220120032802d00322086b4104490d0020032802c80321010c010b200841046a220f2008490d0b20014101742208200f2008200f4b1b22084100480d0b0240024020010d002008102d21010c010b20032802c80320012008103121010b2001450d0a200320083602cc03200320013602c80320032802d00321080b2003200841046a3602d003200120086a200e3600000c050b20032802cc03450d0620032802c803102f0c060b2008200f104b000b200f2010104a000b20012010104b000b200341e0036a41146a4109360200200341ec036a410a360200200341f0026a41146a41033602002003200341f8036a360290032003200341fc036a3602a003200341b8016a41146a4100360200200342033702f402200341b4e0ca003602f0022003410a3602e403200341c8e1ca003602c801200342013702bc0120034188e1ca003602b8012003200341e0036a360280032003200341b8016a3602f0032003200341a0036a3602e803200320034190036a3602e003200341f0026a41c8e1ca001043000b20032802d003210120032802cc03210f20032802c80321080b2008450d00200b2001ad4220862008ad8410040240200f450d002008102f0b200041206a21002007102f200241606a22020d010c060b0b2007102f0c040b1036000b1038000b103d000b200341b8016a1088040b20034180046a24000b8d1201027f02402000280200220141194b0d0002400240024002400240024002400240024002400240024002400240024002400240024020010e1a0001121202121203040506070809120a0b0c0d0e1212120f1011000b200041086a280200417e6a220141074b0d1102400240024002400240024020010e080017010217030405000b200041106a280200450d162000410c6a280200102f0f0b200041106a280200450d152000410c6a280200102f0f0b200041106a280200450d142000410c6a280200102f0f0b0240200041146a2802002202450d002000410c6a2802002101200241186c210203400240200141046a280200450d002001280200102f0b0240200141106a280200450d002001410c6a280200102f0b200141186a2101200241686a22020d000b0b200041106a280200450d13200028020c102f0f0b0240200041146a2802002202450d002000410c6a28020021012002410c6c210203400240200141046a280200450d002001280200102f0b2001410c6a2101200241746a22020d000b0b200041106a280200450d12200028020c102f0f0b200041106a280200450d112000410c6a280200102f0f0b024020002d0004220141044b0d00024002400240024020010e051500010203150b0240200041106a2802002202450d00200041086a2802002101200241b0026c210203402001108d01200141b0026a2101200241d07d6a22020d000b0b2000410c6a280200450d142000280208102f0f0b200041086a2201280200108d012001280200102f0f0b02402000410c6a280200450d00200041086a280200102f0b200041206a2201280200108d012001280200102f0f0b2000412c6a280200450d11200041286a280200102f0f0b2000412c6a280200450d10200041286a280200102f0f0b02402000410c6a2802002201450d00200141f0006c2102200028020441046a2101034020011097010240200141046a280200450d002001280200102f0b200141f0006a2101200241907f6a22020d000b0b200041086a280200450d0f2000280204102f0f0b200041086a2d0000417a6a2201410b4b0d0e024002400240024020010e0c001212121212120112120203000b200041106a280200450d112000410c6a280200102f0f0b200041106a280200450d102000410c6a280200102f0f0b200041146a280200450d0f200041106a280200102f0f0b200041146a280200450d0e200041106a280200102f0f0b20002802042201450d0d200041086a280200450d0d2001102f0f0b200041086a2d0000416d6a220141014b0d0c0240024020010e020001000b200041106a280200450d0d2000410c6a280200102f0f0b200041106a280200450d0c2000410c6a280200102f0f0b20002d0004417f6a220141024b0d0b02400240024020010e03000102000b2000412c6a280200450d0d200041286a280200102f0f0b200041086a2201280200108d012001280200102f0f0b2000410c6a2201280200108d012001280200102f0f0b20002d0004417f6a220141024b0d0a02400240024020010e03000102000b2000412c6a280200450d0c200041286a280200102f0f0b200041086a2201280200108d012001280200102f0f0b2000410c6a2201280200108d012001280200102f0f0b200041086a2802004101470d09200041106a280200450d092000410c6a280200102f0f0b20002d00044104470d082000410c6a280200450d08200041086a280200102f0f0b200041086a280200450d072000280204102f0f0b200041086a2d0000417c6a220141024b0d060240024020010e03000801000b200041306a280200450d072000412c6a280200102f0f0b200041306a280200450d062000412c6a280200102f0f0b200041086a2d0000417e6a220141024b0d0502400240024020010e03000102000b200041106a280200450d072000410c6a280200102f0c070b200041346a280200450d06200041306a280200102f0f0b200041306a280200450d052000412c6a280200102f0f0b02402000280204220141024b0d00024020010e03060006060b200041086a2201280200108d012001280200102f0f0b2000412c6a2201280200108d012001280200102f0f0b02402000410c6a280200450d00200041086a280200102f0b02402000411c6a2802002202450d00200041146a28020021012002410c6c210203400240200141046a280200450d002001280200102f0b2001410c6a2101200241746a22020d000b0b200041186a280200450d032000280214102f0f0b200041086a2d0000417e6a220141014b0d020240024020010e020001000b0240200041146a2802002202450d002000410c6a2802002201200241c8006c6a21020340024020012d00004101470d00200141086a280200450d00200141046a280200102f0b0240200141246a2d00004101470d002001412c6a280200450d00200141286a280200102f0b200141c8006a22012002470d000b0b0240200041106a280200450d00200028020c102f0b0240200041186a2d00004101470d00200041206a280200450d002000411c6a280200102f0b02402000413c6a2d00004101470d00200041c4006a280200450d00200041c0006a280200102f0b0240200041e0006a2d00004101470d00200041e8006a280200450d00200041e4006a280200102f0b024020004184016a2d00004101470d002000418c016a280200450d0020004188016a280200102f0b0240200041a8016a2d00004101470d00200041b0016a280200450d00200041ac016a280200102f0b0240200041cc016a2d00004101470d00200041d4016a280200450d00200041d0016a280200102f0b200041f0016a2d00004101470d03200041f8016a280200450d03200041f4016a280200102f0f0b0240200041146a2802002201450d00200141c4006c21022000410c6a28020041286a210103400240200141786a2d00004101470d002001280200450d002001417c6a280200102f0b200141c4006a2101200241bc7f6a22020d000b0b200041106a280200450d02200028020c102f0f0b200041086a2d00004108470d01200041346a280200450d01200041306a280200102f0f0b20002d0004417f6a220141024b0d000240024020010e03000201000b200041286a2201280200108d012001280200102f0f0b2000410c6a280200450d00200041086a280200102f0f0b0b8d1201027f02402000280200220141194b0d0002400240024002400240024002400240024002400240024002400240024002400240024020010e1a0001121202121203040506070809120a0b0c0d0e1212120f1011000b200041086a280200417e6a220141074b0d1102400240024002400240024020010e080017010217030405000b200041106a280200450d162000410c6a280200102f0f0b200041106a280200450d152000410c6a280200102f0f0b200041106a280200450d142000410c6a280200102f0f0b0240200041146a2802002202450d002000410c6a2802002101200241186c210203400240200141046a280200450d002001280200102f0b0240200141106a280200450d002001410c6a280200102f0b200141186a2101200241686a22020d000b0b200041106a280200450d13200028020c102f0f0b0240200041146a2802002202450d002000410c6a28020021012002410c6c210203400240200141046a280200450d002001280200102f0b2001410c6a2101200241746a22020d000b0b200041106a280200450d12200028020c102f0f0b200041106a280200450d112000410c6a280200102f0f0b024020002d0004220141044b0d00024002400240024020010e051500010203150b0240200041106a2802002202450d00200041086a2802002101200241b0026c210203402001108d01200141b0026a2101200241d07d6a22020d000b0b2000410c6a280200450d142000280208102f0f0b200041086a2201280200108e012001280200102f0f0b02402000410c6a280200450d00200041086a280200102f0b200041206a2201280200108e012001280200102f0f0b2000412c6a280200450d11200041286a280200102f0f0b2000412c6a280200450d10200041286a280200102f0f0b02402000410c6a2802002201450d00200141f0006c2102200028020441046a2101034020011097010240200141046a280200450d002001280200102f0b200141f0006a2101200241907f6a22020d000b0b200041086a280200450d0f2000280204102f0f0b200041086a2d0000417a6a2201410b4b0d0e024002400240024020010e0c001212121212120112120203000b200041106a280200450d112000410c6a280200102f0f0b200041106a280200450d102000410c6a280200102f0f0b200041146a280200450d0f200041106a280200102f0f0b200041146a280200450d0e200041106a280200102f0f0b20002802042201450d0d200041086a280200450d0d2001102f0f0b200041086a2d0000416d6a220141014b0d0c0240024020010e020001000b200041106a280200450d0d2000410c6a280200102f0f0b200041106a280200450d0c2000410c6a280200102f0f0b20002d0004417f6a220141024b0d0b02400240024020010e03000102000b2000412c6a280200450d0d200041286a280200102f0f0b200041086a2201280200108e012001280200102f0f0b2000410c6a2201280200108e012001280200102f0f0b20002d0004417f6a220141024b0d0a02400240024020010e03000102000b2000412c6a280200450d0c200041286a280200102f0f0b200041086a2201280200108e012001280200102f0f0b2000410c6a2201280200108e012001280200102f0f0b200041086a2802004101470d09200041106a280200450d092000410c6a280200102f0f0b20002d00044104470d082000410c6a280200450d08200041086a280200102f0f0b200041086a280200450d072000280204102f0f0b200041086a2d0000417c6a220141024b0d060240024020010e03000801000b200041306a280200450d072000412c6a280200102f0f0b200041306a280200450d062000412c6a280200102f0f0b200041086a2d0000417e6a220141024b0d0502400240024020010e03000102000b200041106a280200450d072000410c6a280200102f0c070b200041346a280200450d06200041306a280200102f0f0b200041306a280200450d052000412c6a280200102f0f0b02402000280204220141024b0d00024020010e03060006060b200041086a2201280200108e012001280200102f0f0b2000412c6a2201280200108e012001280200102f0f0b02402000410c6a280200450d00200041086a280200102f0b02402000411c6a2802002202450d00200041146a28020021012002410c6c210203400240200141046a280200450d002001280200102f0b2001410c6a2101200241746a22020d000b0b200041186a280200450d032000280214102f0f0b200041086a2d0000417e6a220141014b0d020240024020010e020001000b0240200041146a2802002202450d002000410c6a2802002201200241c8006c6a21020340024020012d00004101470d00200141086a280200450d00200141046a280200102f0b0240200141246a2d00004101470d002001412c6a280200450d00200141286a280200102f0b200141c8006a22012002470d000b0b0240200041106a280200450d00200028020c102f0b0240200041186a2d00004101470d00200041206a280200450d002000411c6a280200102f0b02402000413c6a2d00004101470d00200041c4006a280200450d00200041c0006a280200102f0b0240200041e0006a2d00004101470d00200041e8006a280200450d00200041e4006a280200102f0b024020004184016a2d00004101470d002000418c016a280200450d0020004188016a280200102f0b0240200041a8016a2d00004101470d00200041b0016a280200450d00200041ac016a280200102f0b0240200041cc016a2d00004101470d00200041d4016a280200450d00200041d0016a280200102f0b200041f0016a2d00004101470d03200041f8016a280200450d03200041f4016a280200102f0f0b0240200041146a2802002201450d00200141c4006c21022000410c6a28020041286a210103400240200141786a2d00004101470d002001280200450d002001417c6a280200102f0b200141c4006a2101200241bc7f6a22020d000b0b200041106a280200450d02200028020c102f0f0b200041086a2d00004108470d01200041346a280200450d01200041306a280200102f0f0b20002d0004417f6a220141024b0d000240024020010e03000201000b200041286a2201280200108e012001280200102f0f0b2000410c6a280200450d00200041086a280200102f0f0b0bd204010c7f230041206b220324002001280204210420012802002105024002400240024002400240200128020822060d00410021070c010b20064105742108200220056b2109410021014100210a410021072005210b02400340200520016a210c0240200a450d00200a200c412010ea064100480d004115210c41e6a6c000210d4105210e0c020b0240200c2002412010ea06220a41004a0d004113210c41d3a6c000210d4106210e20092001460d02200a450d02200741016a21070b200b210a200b41206a210b2008200141206a2201460d020c000b0b2000200e3a000620004183023b0104200041013602002000410c6a200c360200200041086a200d3602002004450d012005102f0c010b200341186a200241186a290000370300200341106a200241106a290000370300200341086a200241086a2900003703002003200229000037030020062007490d01024020062004470d00200441016a22012004490d042004410174220b2001200b20014b1b220141ffffff3f712001470d04200141057422014100480d040240024020040d002001102d21050c010b200520044105742001103121050b2005450d03200141057621040b200520074105746a220141206a2001200620076b41057410e9061a200141186a200341186a290300370000200141106a200341106a290300370000200141086a200341086a290300370000200120032903003700002000410c6a200641016a360200200041086a200436020020002005360204200041003602000b200341206a24000f0b419ae3c300411e41f8b4ca001039000b1036000b1038000bfd0402087f037e230041106b22022400024002400240200141086a28020022034105744116722204417f4c0d002004102d2205450d01200520012802002206290000370000200541086a200641086a290000370000200241103602082002200436020420022005360200200141046a28020021052003200210690240024020030d0020022802042107200228020821060c010b20034105742108200228020021092002280204210420022802082103034002400240200420036b4120490d00200341206a2106200421070c010b200341206a22062003490d05200441017422072006200720064b1b22074100480d050240024020040d002007102d21090c010b200920042007103121090b2009450d040b200920036a22032005290000370000200341186a200541186a290000370000200341106a200541106a290000370000200341086a200541086a2900003700002007210420062103200541206a2105200841606a22080d000b2002200736020420022006360208200220093602000b20012f010c210402400240200720066b4102490d00200641026a2105200228020021030c010b200641026a22052006490d03200741017422032005200320054b1b22094100480d030240024020070d002009102d21030c010b200228020020072009103121030b2003450d022002200936020420022003360200200921070b200320066a20043b00002005ad4220862003ad8410032205290000210a200541086a290000210b200541106a290000210c200041186a200541186a290000370000200041106a200c370000200041086a200b3700002000200a3700002005102f02402007450d002003102f0b200241106a24000f0b103d000b1036000b1038000bdf800304057f017e067f017e230041206b2202240002400240024002400240024002400240024020002802002203411a4b0d0002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020030e1b000102030405060708090a0b0c0d0e0f101112131415161718191a000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d1d200341017422052004200520044b1b22054100480d1d0240024020030d002005102d21040c010b200128020020032005103121040b2004450d1c20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a00002000280208417f6a220341094b0d1a024002400240024002400240024002400240024020030e0a00010203040506070809000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d26200341017422052004200520044b1b22054100480d260240024020030d002005102d21040c010b200128020020032005103121040b2004450d2520012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200028020c210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d26200341017422002005200020054b1b22004100480d260240024020030d002000102d21030c010b200128020020032000103121030b2003450d2520012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c230b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d25200341017422052004200520044b1b22054100480d250240024020030d002005102d21040c010b200128020020032005103121040b2004450d2420012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a0000200028020c2106200041146a28020022002001106902400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d25200441017422032005200320054b1b22034100480d250240024020040d002003102d21040c010b200128020020042003103121040b2004450d2420012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010e8061a0c220b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d24200341017422052004200520044b1b22054100480d240240024020030d002005102d21040c010b200128020020032005103121040b2004450d2320012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a00002000290310210702400240200141046a2802002203200528020022006b4108490d00200128020021030c010b200041086a22042000490d24200341017422002004200020044b1b22004100480d240240024020030d002000102d21030c010b200128020020032000103121030b2003450d2320012003360200200141046a2000360200200141086a28020021000b200141086a200041086a360200200320006a20073700000c210b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d23200341017422052004200520044b1b22054100480d230240024020030d002005102d21040c010b200128020020032005103121040b2004450d2220012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a0000200028020c2106200041146a28020022002001106902400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d23200441017422032005200320054b1b22034100480d230240024020040d002003102d21040c010b200128020020042003103121040b2004450d2220012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010e8061a0c200b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d22200341017422052004200520044b1b22054100480d220240024020030d002005102d21040c010b200128020020032005103121040b2004450d2120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a0000200028020c2106200041146a28020022002001106902400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d22200441017422032005200320054b1b22034100480d220240024020040d002003102d21040c010b200128020020042003103121040b2004450d2120012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010e8061a0c1f0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d21200341017422052004200520044b1b22054100480d210240024020030d002005102d21040c010b200128020020032005103121040b2004450d2020012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41053a0000200141046a28020021042005280200210302402000410c6a2802004101460d000240024020042003460d00200128020021000c010b200341016a22002003490d22200341017422042000200420004b1b22044100480d220240024020030d002004102d21000c010b200128020020032004103121000b2000450d2120012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41003a00000c1f0b0240024020042003460d00200128020021040c010b200341016a22042003490d21200341017422052004200520044b1b22054100480d210240024020030d002005102d21040c010b200128020020032005103121040b2004450d2020012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a0000200041106a280200210602400240200141046a2802002204200528020022036b4104490d00200128020021040c010b200341046a22052003490d21200441017422032005200320054b1b22034100480d210240024020040d002003102d21040c010b200128020020042003103121040b2004450d2020012004360200200141046a2003360200200141086a28020021030b200141086a2205200341046a360200200420036a2006360000200041146a280200210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d21200341017422002005200020054b1b22004100480d210240024020030d002000102d21030c010b200128020020032000103121030b2003450d2020012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c1e0b02400240200141046a280200200141086a2802002203460d00200128020021050c010b200341016a22042003490d20200341017422052004200520044b1b22044100480d200240024020030d002004102d21050c010b200128020020032004103121050b2005450d1f20012005360200200141046a2004360200200141086a28020021030b200141086a2204200341016a360200200520036a41063a0000200028020c2103200041146a2802002200200110692000450d1d2003200041186c6a2108200141046a2106034020032802002109200341086a280200220020011069024002402006280200220a200428020022056b2000490d002001280200210a0c010b200520006a220b2005490d21200a4101742205200b2005200b4b1b22054100480d2102400240200a0d002005102d210a0c010b2001280200200a20051031210a0b200a450d202001200a36020020062005360200200428020021050b2004200520006a360200200a20056a2009200010e8061a2003410c6a2802002109200341146a280200220020011069024002402006280200220a200428020022056b2000490d002001280200210a0c010b200520006a220b2005490d21200a4101742205200b2005200b4b1b22054100480d2102400240200a0d002005102d210a0c010b2001280200200a20051031210a0b200a450d202001200a36020020062005360200200428020021050b2004200520006a360200200a20056a2009200010e8061a200341186a22032008470d000c1e0b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d1f200341017422052004200520044b1b22054100480d1f0240024020030d002005102d21040c010b200128020020032005103121040b2004450d1e20012004360200200141046a2005360200200141086a28020021030b200141086a2206200341016a360200200420036a41073a0000200028020c2104200041146a2802002200200110692000450d1c20042000410c6c6a2108200141046a210903402004280200210a200441086a2802002200200110690240024020092802002205200628020022036b2000490d00200128020021050c010b200320006a220b2003490d2020054101742203200b2003200b4b1b22034100480d200240024020050d002003102d21050c010b200128020020052003103121050b2005450d1f2001200536020020092003360200200628020021030b2006200320006a360200200520036a200a200010e8061a2004410c6a22042008470d000c1d0b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d1e200341017422052004200520044b1b22054100480d1e0240024020030d002005102d21040c010b200128020020032005103121040b2004450d1d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41083a0000200028020c2106200041146a28020022002001106902400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d1e200441017422032005200320054b1b22034100480d1e0240024020040d002003102d21040c010b200128020020042003103121040b2004450d1d20012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010e8061a0c1b0b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d1d200041017422042003200420034b1b22044100480d1d0240024020000d002004102d21030c010b200128020020002004103121030b2003450d1c20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41093a00000c1a0b02400240200141046a2206280200200141086a22032802002204460d00200128020021050c010b200441016a22052004490d1c2004410174220a2005200a20054b1b220a4100480d1c0240024020040d00200a102d21050c010b20012802002004200a103121050b2005450d1b20012005360200200141046a200a360200200141086a28020021040b2003200441016a360200200520046a41013a0000200041046a22082d0000417f6a220441044b0d190240024002400240024020040e050001020304000b02400240200628020020032802002203460d00200128020021040c010b200341016a22042003490d20200341017422052004200520044b1b22054100480d200240024020030d002005102d21040c010b200128020020032005103121040b2004450d1f20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a000020002802082103200041106a2802002200200110692000450d1d200041b0026c2100034020032001109101200341b0026a2103200041d07d6a22000d000c1e0b0b02400240200628020020032802002204460d00200128020021050c010b200441016a22052004490d1f2004410174220a2005200a20054b1b220a4100480d1f0240024020040d00200a102d21050c010b20012802002004200a103121050b2005450d1e20012005360200200141046a200a360200200141086a28020021040b2003200441016a360200200520046a41013a000020082f010221050240024020062802002204200328020022036b4102490d00200128020021040c010b200341026a22062003490d1f200441017422032006200320064b1b22034100480d1f0240024020040d002003102d21040c010b200128020020042003103121040b2004450d1e20012004360200200141046a2003360200200141086a28020021030b200141086a200341026a360200200420036a20053b0000200028020820011091010c1c0b02400240200628020020032802002204460d00200128020021050c010b200441016a22052004490d1e2004410174220a2005200a20054b1b220a4100480d1e0240024020040d00200a102d21050c010b20012802002004200a103121050b2005450d1d20012005360200200141046a200a360200200141086a28020021040b2003200441016a360200200520046a41023a000020082f0102210a0240024020062802002205200328020022046b4102490d00200128020021050c010b200441026a22092004490d1e200541017422042009200420094b1b22044100480d1e0240024020050d002004102d21050c010b200128020020052004103121050b2005450d1d20012005360200200141046a2004360200200141086a28020021040b200141086a2208200441026a360200200520046a200a3b000020002802082104200041106a28020022052001106902402005450d0020054105742109200141046a210c0340024002402006280200220a200328020022056b4120490d002001280200210a0c010b200541206a220b2005490d20200a4101742205200b2005200b4b1b22054100480d2002400240200a0d002005102d210a0c010b2001280200200a20051031210a0b200a450d1f2001200a360200200c2005360200200828020021050b2003200541206a360200200a20056a220541186a200441186a290000370000200541106a200441106a290000370000200541086a200441086a29000037000020052004290000370000200441206a2104200941606a22090d000b0b20062802002105200328020021040240024020002802144101460d000240024020052004460d00200128020021050c010b200441016a22052004490d20200441017422062005200620054b1b22064100480d200240024020040d002006102d21050c010b200128020020042006103121050b2005450d1f20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a41003a00000c010b0240024020052004460d00200128020021050c010b200441016a22052004490d1f2004410174220a2005200a20054b1b220a4100480d1f0240024020040d00200a102d21050c010b20012802002004200a103121050b2005450d1e20012005360200200141046a200a360200200141086a28020021040b2003200441016a360200200520046a41013a0000200041186a280200210a0240024020062802002205200328020022046b4104490d00200128020021050c010b200441046a22092004490d1f200541017422042009200420094b1b22044100480d1f0240024020050d002004102d21050c010b200128020020052004103121050b2005450d1e20012005360200200141046a2004360200200141086a28020021040b2003200441046a360200200520046a200a3600002000411c6a280200210a0240024020062802002205200328020022046b4104490d00200128020021050c010b200441046a22062004490d1f200541017422042006200420064b1b22044100480d1f0240024020050d002004102d21050c010b200128020020052004103121050b2005450d1e20012005360200200141046a2004360200200141086a28020021040b2003200441046a360200200520046a200a3600000b200028022020011091010c1b0b02400240200628020020032802002204460d00200128020021050c010b200441016a22052004490d1d2004410174220a2005200a20054b1b220a4100480d1d0240024020040d00200a102d21050c010b20012802002004200a103121050b2005450d1c20012005360200200141046a200a360200200141086a28020021040b2003200441016a360200200520046a41033a000020082f0122210a0240024020062802002205200328020022046b4102490d00200128020021050c010b200441026a22092004490d1d200541017422042009200420094b1b22044100480d1d0240024020050d002004102d21050c010b200128020020052004103121050b2005450d1c20012005360200200141046a2004360200200141086a28020021040b200141086a220c200441026a360200200520046a200a3b000020002802282104200041306a28020022052001106902402005450d0020054105742109200141046a210d0340024002402006280200220a200328020022056b4120490d002001280200210a0c010b200541206a220b2005490d1f200a4101742205200b2005200b4b1b22054100480d1f02400240200a0d002005102d210a0c010b2001280200200a20051031210a0b200a450d1e2001200a360200200d2005360200200c28020021050b2003200541206a360200200a20056a220541186a200441186a290000370000200541106a200441106a290000370000200541086a200441086a29000037000020052004290000370000200441206a2104200941606a22090d000b0b20062802002105200328020021040240024020002802344101460d000240024020052004460d00200128020021000c010b200441016a22002004490d1f200441017422052000200520004b1b22054100480d1f0240024020040d002005102d21000c010b200128020020042005103121000b2000450d1e20012000360200200141046a2005360200200141086a28020021040b2003200441016a360200200020046a41003a00000c010b0240024020052004460d00200128020021050c010b200441016a22052004490d1e2004410174220a2005200a20054b1b220a4100480d1e0240024020040d00200a102d21050c010b20012802002004200a103121050b2005450d1d20012005360200200141046a200a360200200141086a28020021040b2003200441016a360200200520046a41013a0000200041386a280200210a0240024020062802002205200328020022046b4104490d00200128020021050c010b200441046a22092004490d1e200541017422042009200420094b1b22044100480d1e0240024020050d002004102d21050c010b200128020020052004103121050b2005450d1d20012005360200200141046a2004360200200141086a28020021040b2003200441046a360200200520046a200a3600002000413c6a28020021050240024020062802002204200328020022006b4104490d00200128020021040c010b200041046a220a2000490d1e20044101742200200a2000200a4b1b22004100480d1e0240024020040d002000102d21040c010b200128020020042000103121040b2004450d1d20012004360200200141046a2000360200200141086a28020021000b2003200041046a360200200420006a20053600000b0240024020062802002204200328020022006b4120490d00200128020021040c010b200041206a22052000490d1d200441017422002005200020054b1b22004100480d1d0240024020040d002000102d21040c010b200128020020042000103121040b2004450d1c20012004360200200141046a2000360200200141086a28020021000b2003200041206a360200200420006a220041186a200841196a290000370000200041106a200841116a290000370000200041086a200841096a290000370000200020082900013700000c1a0b02400240200628020020032802002204460d00200128020021050c010b200441016a22052004490d1c2004410174220a2005200a20054b1b220a4100480d1c0240024020040d00200a102d21050c010b20012802002004200a103121050b2005450d1b20012005360200200141046a200a360200200141086a28020021040b2003200441016a360200200520046a41043a000020082f0122210a0240024020062802002205200328020022046b4102490d00200128020021050c010b200441026a22092004490d1c200541017422042009200420094b1b22044100480d1c0240024020050d002004102d21050c010b200128020020052004103121050b2005450d1b20012005360200200141046a2004360200200141086a28020021040b200141086a220c200441026a360200200520046a200a3b000020002802282104200041306a28020022052001106902402005450d0020054105742109200141046a210d0340024002402006280200220a200328020022056b4120490d002001280200210a0c010b200541206a220b2005490d1e200a4101742205200b2005200b4b1b22054100480d1e02400240200a0d002005102d210a0c010b2001280200200a20051031210a0b200a450d1d2001200a360200200d2005360200200c28020021050b2003200541206a360200200a20056a220541186a200441186a290000370000200541106a200441106a290000370000200541086a200441086a29000037000020052004290000370000200441206a2104200941606a22090d000b0b2000280234210a0240024020062802002205200328020022046b4104490d00200128020021050c010b200441046a22092004490d1c200541017422042009200420094b1b22044100480d1c0240024020050d002004102d21050c010b200128020020052004103121050b2005450d1b20012005360200200141046a2004360200200141086a28020021040b2003200441046a360200200520046a200a360000200041386a28020021050240024020062802002204200328020022006b4104490d00200128020021040c010b200041046a220a2000490d1c20044101742200200a2000200a4b1b22004100480d1c0240024020040d002000102d21040c010b200128020020042000103121040b2004450d1b20012004360200200141046a2000360200200141086a28020021000b2003200041046a360200200420006a20053600000240024020062802002204200328020022006b4120490d00200128020021040c010b200041206a22052000490d1c200441017422002005200020054b1b22004100480d1c0240024020040d002000102d21040c010b200128020020042000103121040b2004450d1b20012004360200200141046a2000360200200141086a28020021000b2003200041206a360200200420006a220041186a200841196a290000370000200041106a200841116a290000370000200041086a200841096a290000370000200020082900013700000c190b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d1b200041017422042003200420034b1b22044100480d1b0240024020000d002004102d21030c010b200128020020002004103121030b2003450d1a20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41023a0000200110e8020c180b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d1a200341017422052004200520044b1b22054100480d1a0240024020030d002005102d21040c010b200128020020032005103121040b2004450d1920012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d1a200341017422052004200520044b1b22054100480d1a0240024020030d002005102d21040c010b200128020020032005103121040b2004450d1920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041086a200110e9020c170b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d19200341017422052004200520044b1b22054100480d190240024020030d002005102d21040c010b200128020020032005103121040b2004450d1820012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d19200341017422052004200520044b1b22054100480d190240024020030d002005102d21040c010b200128020020032005103121040b2004450d1820012004360200200141046a2005360200200141086a28020021030b200141086a2206200341016a360200200420036a41003a00002000280204210c2000410c6a2802002200200110692000450d16200c200041f0006c6a210d200141046a210b03404120102d2200450d182000200c290010370000200041186a2205200c41286a290000370000200041106a220a200c41206a290000370000200041086a2209200c41186a29000037000002400240200b2802002204200628020022036b4120490d00200128020021040c010b200341206a22082003490d1a200441017422032008200320084b1b22034100480d1a0240024020040d002003102d21040c010b200128020020042003103121040b2004450d1920012004360200200b2003360200200628020021030b2006200341206a360200200420036a220341186a2005290000370000200341106a200a290000370000200341086a2009290000370000200320002900003700002000102f200c20011095024120102d2200450d182000200c290030370000200041186a2205200c41c8006a290000370000200041106a220a200c41c0006a290000370000200041086a2209200c41386a29000037000002400240200b2802002204200628020022036b4120490d00200128020021040c010b200341206a22082003490d1a200441017422032008200320084b1b22034100480d1a0240024020040d002003102d21040c010b200128020020042003103121040b2004450d1920012004360200200b2003360200200628020021030b2006200341206a360200200420036a220341186a2005290000370000200341106a200a290000370000200341086a2009290000370000200320002900003700002000102f4120102d2200450d182000200c290050370000200041186a2205200c41e8006a290000370000200041106a220a200c41e0006a290000370000200041086a2209200c41d8006a29000037000002400240200b2802002204200628020022036b4120490d00200128020021040c010b200341206a22082003490d1a200441017422032008200320084b1b22034100480d1a0240024020040d002003102d21040c010b200128020020042003103121040b2004450d1920012004360200200b2003360200200628020021030b2006200341206a360200200420036a220341186a2005290000370000200341106a200a290000370000200341086a2009290000370000200320002900003700002000102f200c2802042104200c28020c22002001106902402000450d00200041246c210903402002200410ea022002280200210a02400240200b2802002205200628020022006b20022802082203490d00200128020021050c010b200020036a22082000490d1c200541017422002008200020084b1b22004100480d1c0240024020050d002000102d21050c010b200128020020052000103121050b2005450d1b20012005360200200b2000360200200628020021000b2006200020036a360200200520006a200a200310e8061a02402002280204450d00200a102f0b200441246a21042009415c6a22090d000b0b200c41f0006a220c200d470d000c170b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d18200341017422052004200520044b1b22054100480d180240024020030d002005102d21040c010b200128020020032005103121040b2004450d1720012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41053a0000200041046a22032d0000417f6a220441034b0d1502400240024002400240024020040e0400010203000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d1d200341017422052004200520044b1b22054100480d1d0240024020030d002005102d21040c010b200128020020032005103121040b2004450d1c20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200028020821030c040b02400240200141046a280200200141086a2802002204460d00200128020021050c010b200441016a22052004490d1c200441017422062005200620054b1b22064100480d1c0240024020040d002006102d21050c010b200128020020042006103121050b2005450d1b20012005360200200141046a2006360200200141086a28020021040b200141086a2206200441016a360200200520046a41013a000002400240200141046a2802002205200628020022046b4120490d00200128020021050c010b200441206a22062004490d1c200541017422042006200420064b1b22044100480d1c0240024020050d002004102d21050c010b200128020020052004103121050b2005450d1b20012005360200200141046a2004360200200141086a28020021040b200141086a200441206a360200200520046a220441186a200341196a290000370000200441106a200341116a290000370000200441086a200341096a290000370000200420032900013700000c020b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d1b200341017422052004200520044b1b22054100480d1b0240024020030d002005102d21040c010b200128020020032005103121040b2004450d1a20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a0000200028020821030c020b02400240200141046a280200200141086a2802002204460d00200128020021050c010b200441016a22052004490d1a200441017422062005200620054b1b22064100480d1a0240024020040d002006102d21050c010b200128020020042006103121050b2005450d1920012005360200200141046a2006360200200141086a28020021040b200141086a2206200441016a360200200520046a41033a000002400240200141046a2802002205200628020022046b4120490d00200128020021050c010b200441206a22062004490d1a200541017422042006200420064b1b22044100480d1a0240024020050d002004102d21050c010b200128020020052004103121050b2005450d1920012005360200200141046a2004360200200141086a28020021040b200141086a200441206a360200200520046a220441186a200341196a290000370000200441106a200341116a290000370000200441086a200341096a290000370000200420032900013700000b200028022821030b200220033602002002210502400240200141046a2802002204200141086a28020022006b4104490d00200128020021040c010b200041046a22032000490d18200441017422002003200020034b1b22004100480d180240024020040d002000102d21040c010b200128020020042000103121040b2004450d1720012004360200200141046a2000360200200141086a2802002100200528020021030b200141086a200041046a360200200420006a20033600000c150b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d17200341017422052004200520044b1b22054100480d170240024020030d002005102d21040c010b200128020020032005103121040b2004450d1620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41063a00002000280208417f6a220341034b0d140240024002400240024020030e0400010203000b02400240200141046a280200200141086a2802002204460d00200128020021050c010b200441016a22032004490d1b200441017422052003200520034b1b22034100480d1b0240024020040d002003102d21050c010b200128020020042003103121050b2005450d1a20012005360200200141046a2003360200200141086a28020021040b200041306a2103200141086a200441016a360200200520046a41003a00002000410c6a200110eb02200241106a21000c030b02400240200141046a280200200141086a2802002204460d00200128020021050c010b200441016a22032004490d1a200441017422052003200520034b1b22034100480d1a0240024020040d002003102d21050c010b200128020020042003103121050b2005450d1920012005360200200141046a2003360200200141086a28020021040b200041c0006a2103200141086a200441016a360200200520046a41013a00002000410c6a200110eb022002200041306a360214200241146a200110c202200241186a21000c020b02400240200141046a280200200141086a2802002204460d00200128020021050c010b200441016a22032004490d19200441017422052003200520034b1b22034100480d190240024020040d002003102d21050c010b200128020020042003103121050b2005450d1820012005360200200141046a2003360200200141086a28020021040b200041d8006a2103200141086a200441016a360200200520046a41023a00002000410c6a200110eb02200041306a200110eb022002411c6a21000c010b02400240200141046a280200200141086a2802002204460d00200128020021050c010b200441016a22032004490d18200441017422052003200520034b1b22034100480d180240024020040d002003102d21050c010b200128020020042003103121050b2005450d1720012005360200200141046a2003360200200141086a28020021040b200041306a2103200141086a200441016a360200200520046a41033a00002000410c6a200110eb02200221000b200020033602002000200110c2020c140b02400240200141046a2205280200200141086a22032802002204460d00200128020021060c010b200441016a22062004490d162004410174220a2006200a20064b1b220a4100480d160240024020040d00200a102d21060c010b20012802002004200a103121060b2006450d1520012006360200200141046a200a360200200141086a28020021040b2003200441016a360200200620046a41073a0000200041086a22062d0000417f6a220441144b0d1302400240024002400240024002400240024002400240024002400240024002400240024002400240024020040e15000102030405060708090a0b0c0d0e0f1011121314000b02400240200528020020032802002204460d002001280200210a0c010b200441016a220a2004490d2a20044101742209200a2009200a4b1b22094100480d2a0240024020040d002009102d210a0c010b2001280200200420091031210a0b200a450d292001200a360200200141046a2009360200200141086a28020021040b200141086a200441016a360200200a20046a41003a00002000410c6a200110eb022002200041306a3602002002200110c20220062d0001220041024b0d2702400240024020000e03000102000b02400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d2e200041017422052004200520044b1b22054100480d2e0240024020000d002005102d21040c010b200128020020002005103121040b2004450d2b20012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41003a00000c290b02400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d2d200041017422052004200520044b1b22054100480d2d0240024020000d002005102d21040c010b200128020020002005103121040b2004450d2c20012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41013a00000c280b02400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d2c200041017422052004200520044b1b22054100480d2c0240024020000d002005102d21040c010b200128020020002005103121040b2004450d2b20012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41023a00000c270b02400240200528020020032802002203460d00200128020021040c010b200341016a22042003490d2b200341017422052004200520044b1b22054100480d2b0240024020030d002005102d21040c010b200128020020032005103121040b2004450d2a20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00002002200041106a3602002002200110c2020c260b02400240200528020020032802002203460d00200128020021040c010b200341016a22042003490d2a200341017422052004200520044b1b22054100480d2a0240024020030d002005102d21040c010b200128020020032005103121040b2004450d2920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a00002002200041106a3602002002200110c2020c250b02400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d29200041017422052004200520044b1b22054100480d290240024020000d002005102d21040c010b200128020020002005103121040b2004450d2820012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41033a00000c240b02400240200528020020032802002203460d00200128020021040c010b200341016a22042003490d28200341017422052004200520044b1b22054100480d280240024020030d002005102d21040c010b200128020020032005103121040b2004450d2720012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41043a00002000410c6a20011095020c230b02400240200528020020032802002203460d00200128020021040c010b200341016a22042003490d27200341017422052004200520044b1b22054100480d270240024020030d002005102d21040c010b200128020020032005103121040b2004450d2620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41053a0000200028020c2103200041146a2802002200200110692000450d22200041246c210003402003200110eb02200341246a21032000415c6a22000d000c230b0b02400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d26200041017422052004200520044b1b22054100480d260240024020000d002005102d21040c010b200128020020002005103121040b2004450d2520012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41063a00000c210b02400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d252000410174220a2004200a20044b1b220a4100480d250240024020000d00200a102d21040c010b20012802002000200a103121040b2004450d2420012004360200200141046a200a360200200141086a28020021000b2003200041016a360200200420006a41073a000020062d0001220041024b0d2002400240024020000e03000102000b02400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d27200041017422052004200520044b1b22054100480d270240024020000d002005102d21040c010b200128020020002005103121040b2004450d2620012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41003a00000c220b02400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d26200041017422052004200520044b1b22054100480d260240024020000d002005102d21040c010b200128020020002005103121040b2004450d2520012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41013a00000c210b02400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d25200041017422052004200520044b1b22054100480d250240024020000d002005102d21040c010b200128020020002005103121040b2004450d2420012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41023a00000c200b02400240200528020020032802002203460d00200128020021040c010b200341016a22042003490d24200341017422052004200520044b1b22054100480d240240024020030d002005102d21040c010b200128020020032005103121040b2004450d2320012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41083a00002000410c6a200110eb020c1f0b02400240200528020020032802002203460d00200128020021040c010b200341016a22042003490d23200341017422052004200520044b1b22054100480d230240024020030d002005102d21040c010b200128020020032005103121040b2004450d2220012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41093a00002000410c6a20011095020c1e0b02400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d22200041017422052004200520044b1b22054100480d220240024020000d002005102d21040c010b200128020020002005103121040b2004450d2120012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a410a3a00000c1d0b02400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d21200041017422052004200520044b1b22054100480d210240024020000d002005102d21040c010b200128020020002005103121040b2004450d2020012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a410b3a00000c1c0b02400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d202004410174220a2006200a20064b1b220a4100480d200240024020040d00200a102d21060c010b20012802002004200a103121060b2006450d1f20012006360200200141046a200a360200200141086a28020021040b200141086a220b200441016a360200200620046a410c3a0000200028020c2104200041146a2802002200200110692000450d1b2000410574210a200141046a210803400240024020052802002206200328020022006b4120490d00200128020021060c010b200041206a22092000490d21200641017422002009200020094b1b22004100480d210240024020060d002000102d21060c010b200128020020062000103121060b2006450d202001200636020020082000360200200b28020021000b2003200041206a360200200620006a220041186a200441186a290000370000200041106a200441106a290000370000200041086a200441086a29000037000020002004290000370000200441206a2104200a41606a220a0d000c1c0b0b02400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d1f2000410174220a2004200a20044b1b220a4100480d1f0240024020000d00200a102d21040c010b20012802002000200a103121040b2004450d1e20012004360200200141046a200a360200200141086a28020021000b2003200041016a360200200420006a410d3a00000240024020052802002204200328020022006b4120490d00200128020021040c010b200041206a22052000490d1f200441017422002005200020054b1b22004100480d1f0240024020040d002000102d21040c010b200128020020042000103121040b2004450d1e20012004360200200141046a2000360200200141086a28020021000b2003200041206a360200200420006a220041186a200641196a290000370000200041106a200641116a290000370000200041086a200641096a290000370000200020062900013700000c1a0b02400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d1e200041017422052004200520044b1b22054100480d1e0240024020000d002005102d21040c010b200128020020002005103121040b2004450d1d20012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a410e3a00000c190b02400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d1d2004410174220a2006200a20064b1b220a4100480d1d0240024020040d00200a102d21060c010b20012802002004200a103121060b2006450d1c20012006360200200141046a200a360200200141086a28020021040b2003200441016a360200200620046a410f3a0000200028020c21060240024020052802002205200328020022046b4104490d00200128020021050c010b200441046a220a2004490d1d20054101742204200a2004200a4b1b22044100480d1d0240024020050d002004102d21050c010b200128020020052004103121050b2005450d1c20012005360200200141046a2004360200200141086a28020021040b200141086a220a200441046a360200200520046a200636000020002802102106200041186a28020022042001106902400240200141046a2802002205200a28020022006b20044102742204490d00200128020021050c010b200020046a220a2000490d1d20054101742200200a2000200a4b1b22004100480d1d0240024020050d002000102d21050c010b200128020020052000103121050b2005450d1c20012005360200200141046a2000360200200141086a28020021000b2003200020046a360200200520006a2006200410e8061a0c180b02400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d1c2004410174220a2006200a20064b1b220a4100480d1c0240024020040d00200a102d21060c010b20012802002004200a103121060b2006450d1b20012006360200200141046a200a360200200141086a28020021040b2003200441016a360200200620046a41103a0000200028020c210a0240024020052802002206200328020022046b4104490d00200128020021060c010b200441046a22092004490d1c200641017422042009200420094b1b22044100480d1c0240024020060d002004102d21060c010b200128020020062004103121060b2006450d1b20012006360200200141046a2004360200200141086a28020021040b200141086a220b200441046a360200200620046a200a36000020002802102104200041186a2802002200200110692000450d172004200041246c6a2108200141046a210c03400240024020052802002206200328020022006b4120490d00200128020021060c010b200041206a220a2000490d1d20064101742200200a2000200a4b1b22004100480d1d0240024020060d002000102d21060c010b200128020020062000103121060b2006450d1c20012006360200200c2000360200200b28020021000b2003200041206a360200200620006a220041186a200441186a290000370000200041106a200441106a290000370000200041086a200441086a29000037000020002004290000370000200441206a280200210a0240024020052802002206200328020022006b4104490d00200128020021060c010b200041046a22092000490d1d200641017422002009200020094b1b22004100480d1d0240024020060d002000102d21060c010b200128020020062000103121060b2006450d1c20012006360200200c2000360200200b28020021000b2003200041046a360200200620006a200a3600002008200441246a2204470d000c180b0b02400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d1b2004410174220a2006200a20064b1b220a4100480d1b0240024020040d00200a102d21060c010b20012802002004200a103121060b2006450d1a20012006360200200141046a200a360200200141086a28020021040b2003200441016a360200200620046a41113a0000200028020c21060240024020052802002204200328020022006b4104490d00200128020021040c010b200041046a22052000490d1b200441017422002005200020054b1b22004100480d1b0240024020040d002000102d21040c010b200128020020042000103121040b2004450d1a20012004360200200141046a2000360200200141086a28020021000b2003200041046a360200200420006a20063600000c160b02400240200528020020032802002203460d00200128020021040c010b200341016a22042003490d1a200341017422052004200520044b1b22054100480d1a0240024020030d002005102d21040c010b200128020020032005103121040b2004450d1920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41123a00002002200041106a3602002002200110c2020c150b02400240200528020020032802002203460d00200128020021040c010b200341016a22042003490d19200341017422052004200520044b1b22054100480d190240024020030d002005102d21040c010b200128020020032005103121040b2004450d1820012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41133a00002000410c6a20011095020c140b02400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d182000410174220a2004200a20044b1b220a4100480d180240024020000d00200a102d21040c010b20012802002000200a103121040b2004450d1720012004360200200141046a200a360200200141086a28020021000b2003200041016a360200200420006a41143a00000240024020052802002204200328020022006b4120490d00200128020021040c010b200041206a22052000490d18200441017422002005200020054b1b22004100480d180240024020040d002000102d21040c010b200128020020042000103121040b2004450d1720012004360200200141046a2000360200200141086a28020021000b2003200041206a360200200420006a220041186a200641196a290000370000200041106a200641116a290000370000200041086a200641096a290000370000200020062900013700000c130b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d17200341017422052004200520044b1b22054100480d170240024020030d002005102d21040c010b200128020020032005103121040b2004450d1620012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41083a000002402000280204450d0002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d18200341017422052004200520044b1b22054100480d180240024020030d002005102d21040c010b200128020020032005103121040b2004450d1720012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d18200441017422032005200320054b1b22034100480d180240024020040d002003102d21040c010b200128020020042003103121040b2004450d1720012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041106a220441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002003200429000037000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d18200441017422032005200320054b1b22034100480d180240024020040d002003102d21040c010b200128020020042003103121040b2004450d1720012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041306a220441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002003200429000037000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d18200441017422032005200320054b1b22034100480d180240024020040d002003102d21040c010b200128020020042003103121040b2004450d1720012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041d0006a220441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002003200429000037000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d18200441017422032005200320054b1b22034100480d180240024020040d002003102d21040c010b200128020020042003103121040b2004450d1720012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041f0006a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200028020421062000410c6a28020022002001106902400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d18200441017422032005200320054b1b22034100480d180240024020040d002003102d21040c010b200128020020042003103121040b2004450d1720012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010e8061a0c130b02400240200141046a28020020052802002200460d00200128020021030c010b200041016a22032000490d17200041017422042003200420034b1b22044100480d170240024020000d002004102d21030c010b200128020020002004103121030b2003450d1620012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41013a00000c120b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d16200341017422052004200520044b1b22054100480d160240024020030d002005102d21040c010b200128020020032005103121040b2004450d1520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41093a0000200041086a200110c1020c110b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d15200341017422052004200520044b1b22054100480d150240024020030d002005102d21040c010b200128020020032005103121040b2004450d1420012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410a3a0000200041046a200110ec020c100b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d14200341017422052004200520044b1b22054100480d140240024020030d002005102d21040c010b200128020020032005103121040b2004450d1320012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410b3a0000200041046a200110ec020c0f0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d13200341017422052004200520044b1b22054100480d130240024020030d002005102d21040c010b200128020020032005103121040b2004450d1220012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410c3a00002000280208417f6a220341054b0d0e02400240024002400240024020030e06000102030405000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d18200341017422052004200520044b1b22054100480d180240024020030d002005102d21040c010b200128020020032005103121040b2004450d1720012004360200200141046a2005360200200141086a28020021030b200141086a2206200341016a360200200420036a41003a0000200028020c2103200041146a28020022042001106902402004450d002004410574210a200141046a210903400240024020092802002205200628020022046b4120490d00200128020021050c010b200441206a220b2004490d1a20054101742204200b2004200b4b1b22044100480d1a0240024020050d002004102d21050c010b200128020020052004103121050b2005450d192001200536020020092004360200200628020021040b2006200441206a360200200520046a220441186a200341186a290000370000200441106a200341106a290000370000200441086a200341086a29000037000020042003290000370000200341206a2103200a41606a220a0d000b0b2002200041186a3602002002200110c2020c130b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d17200041017422042003200420034b1b22044100480d170240024020000d002004102d21030c010b200128020020002004103121030b2003450d1620012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41013a00000c120b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d16200341017422052004200520044b1b22054100480d160240024020030d002005102d21040c010b200128020020032005103121040b2004450d1520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a00002000410c6a200110eb020c110b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d15200041017422042003200420034b1b22044100480d150240024020000d002004102d21030c010b200128020020002004103121030b2003450d1420012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41033a00000c100b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d14200041017422042003200420034b1b22044100480d140240024020000d002004102d21030c010b200128020020002004103121030b2003450d1320012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41043a00000c0f0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d13200341017422052004200520044b1b22054100480d130240024020030d002005102d21040c010b200128020020032005103121040b2004450d1220012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41053a00002000410c6a200110eb020c0e0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d12200341017422052004200520044b1b22054100480d120240024020030d002005102d21040c010b200128020020032005103121040b2004450d1120012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410d3a0000200041046a22032d0000417f6a220441064b0d0d024002400240024002400240024020040e0700010203040506000b02400240200141046a280200200141086a2802002200460d00200128020021040c010b200041016a22042000490d18200041017422052004200520044b1b22054100480d180240024020000d002005102d21040c010b200128020020002005103121040b2004450d1720012004360200200141046a2005360200200141086a28020021000b200141086a2205200041016a360200200420006a41003a000002400240200141046a2802002204200528020022006b4120490d00200128020021040c010b200041206a22052000490d18200441017422002005200020054b1b22004100480d180240024020040d002000102d21040c010b200128020020042000103121040b2004450d1720012004360200200141046a2000360200200141086a28020021000b200141086a200041206a360200200420006a220041186a200341196a290000370000200041106a200341116a290000370000200041086a200341096a290000370000200020032900013700000c130b02400240200141046a280200200141086a2802002200460d00200128020021040c010b200041016a22042000490d17200041017422052004200520044b1b22054100480d170240024020000d002005102d21040c010b200128020020002005103121040b2004450d1620012004360200200141046a2005360200200141086a28020021000b200141086a2205200041016a360200200420006a41013a000002400240200141046a2802002204200528020022006b4120490d00200128020021040c010b200041206a22052000490d17200441017422002005200020054b1b22004100480d170240024020040d002000102d21040c010b200128020020042000103121040b2004450d1620012004360200200141046a2000360200200141086a28020021000b200141086a200041206a360200200420006a220041186a200341196a290000370000200041106a200341116a290000370000200041086a200341096a290000370000200020032900013700000c120b02400240200141046a280200200141086a2802002200460d00200128020021040c010b200041016a22042000490d16200041017422052004200520044b1b22054100480d160240024020000d002005102d21040c010b200128020020002005103121040b2004450d1520012004360200200141046a2005360200200141086a28020021000b200141086a2205200041016a360200200420006a41023a000002400240200141046a2802002204200528020022006b4120490d00200128020021040c010b200041206a22052000490d16200441017422002005200020054b1b22004100480d160240024020040d002000102d21040c010b200128020020042000103121040b2004450d1520012004360200200141046a2000360200200141086a28020021000b200141086a2205200041206a360200200420006a220041186a200341196a290000370000200041106a200341116a290000370000200041086a200341096a2900003700002000200329000137000002400240200141046a2802002204200528020022006b4120490d00200128020021040c010b200041206a22052000490d16200441017422002005200020054b1b22004100480d160240024020040d002000102d21040c010b200128020020042000103121040b2004450d1520012004360200200141046a2000360200200141086a28020021000b200141086a200041206a360200200420006a220041186a200341216a220341186a290000370000200041106a200341106a290000370000200041086a200341086a290000370000200020032900003700000c110b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d15200341017422052004200520044b1b22054100480d150240024020030d002005102d21040c010b200128020020032005103121040b2004450d1420012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a000020002802082103200041106a2802002200200110692000450d1020004105742106200141046a210a034002400240200a2802002204200528020022006b4120490d00200128020021040c010b200041206a22092000490d16200441017422002009200020094b1b22004100480d160240024020040d002000102d21040c010b200128020020042000103121040b2004450d1520012004360200200a2000360200200528020021000b2005200041206a360200200420006a220041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a29000037000020002003290000370000200341206a2103200641606a22060d000c110b0b02400240200141046a280200200141086a2802002200460d00200128020021040c010b200041016a22042000490d14200041017422052004200520044b1b22054100480d140240024020000d002005102d21040c010b200128020020002005103121040b2004450d1320012004360200200141046a2005360200200141086a28020021000b200141086a2205200041016a360200200420006a41043a000002400240200141046a2802002204200528020022006b4120490d00200128020021040c010b200041206a22052000490d14200441017422002005200020054b1b22004100480d140240024020040d002000102d21040c010b200128020020042000103121040b2004450d1320012004360200200141046a2000360200200141086a28020021000b200141086a200041206a360200200420006a220041186a200341196a290000370000200041106a200341116a290000370000200041086a200341096a290000370000200020032900013700000c0f0b02400240200141046a280200200141086a2802002200460d00200128020021040c010b200041016a22042000490d13200041017422052004200520044b1b22054100480d130240024020000d002005102d21040c010b200128020020002005103121040b2004450d1220012004360200200141046a2005360200200141086a28020021000b200141086a2205200041016a360200200420006a41053a000002400240200141046a2802002204200528020022006b4120490d00200128020021040c010b200041206a22052000490d13200441017422002005200020054b1b22004100480d130240024020040d002000102d21040c010b200128020020042000103121040b2004450d1220012004360200200141046a2000360200200141086a28020021000b200141086a200041206a360200200420006a220041186a200341196a290000370000200041106a200341116a290000370000200041086a200341096a290000370000200020032900013700000c0e0b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d12200041017422042003200420034b1b22044100480d120240024020000d002004102d21030c010b200128020020002004103121030b2003450d1120012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41063a00000c0d0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d11200341017422052004200520044b1b22054100480d110240024020030d002005102d21040c010b200128020020032005103121040b2004450d1020012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410e3a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d11200341017422052004200520044b1b22054100480d110240024020030d002005102d21040c010b200128020020032005103121040b2004450d1020012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041046a20011095020c0c0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d10200341017422052004200520044b1b22054100480d100240024020030d002005102d21040c010b200128020020032005103121040b2004450d0f20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410f3a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d10200341017422052004200520044b1b22054100480d100240024020030d002005102d21040c010b200128020020032005103121040b2004450d0f20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200028020421062000410c6a28020022002001106902400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d10200441017422032005200320054b1b22034100480d100240024020040d002003102d21040c010b200128020020042003103121040b2004450d0f20012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010e8061a0c0b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0f200341017422052004200520044b1b22054100480d0f0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0e20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41103a0000200041086a22032d0000417f6a220441074b0d0a0240024002400240024002400240024020040e080001020304050607000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d18200341017422052004200520044b1b22054100480d180240024020030d002005102d21040c010b200128020020032005103121040b2004450d1720012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a00002002200041306a3602002002200110c2022000410c6a200110eb020c110b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d17200341017422052004200520044b1b22054100480d170240024020030d002005102d21040c010b200128020020032005103121040b2004450d1620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00002000410c6a20011095020c100b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d16200341017422052004200520044b1b22054100480d160240024020030d002005102d21040c010b200128020020032005103121040b2004450d1520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a00002000410c6a20011095020c0f0b02400240200141046a280200200141086a2802002204460d00200128020021050c010b200441016a22052004490d15200441017422062005200620054b1b22064100480d150240024020040d002006102d21050c010b200128020020042006103121050b2005450d1420012005360200200141046a2006360200200141086a28020021040b200141086a2206200441016a360200200520046a41033a0000200028022c210a200041346a28020022002001106902400240200141046a2802002205200628020022046b2000490d00200128020021050c010b200420006a22062004490d15200541017422042006200420064b1b22044100480d150240024020050d002004102d21050c010b200128020020052004103121050b2005450d1420012005360200200141046a2004360200200141086a28020021040b200141086a2206200420006a360200200520046a200a200010e8061a02400240200141046a2802002204200628020022006b4120490d00200128020021040c010b200041206a22052000490d15200441017422002005200020054b1b22004100480d150240024020040d002000102d21040c010b200128020020042000103121040b2004450d1420012004360200200141046a2000360200200141086a28020021000b200141086a200041206a360200200420006a220041186a200341196a290000370000200041106a200341116a290000370000200041086a200341096a290000370000200020032900013700000c0e0b02400240200141046a280200200141086a2802002200460d00200128020021040c010b200041016a22042000490d14200041017422052004200520044b1b22054100480d140240024020000d002005102d21040c010b200128020020002005103121040b2004450d1320012004360200200141046a2005360200200141086a28020021000b200141086a2205200041016a360200200420006a41043a00004120102d2200450d1220002003290001370000200041186a200341196a290000370000200041106a200341116a290000370000200041086a200341096a29000037000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d14200441017422032005200320054b1b22034100480d140240024020040d002003102d21040c010b200128020020042003103121040b2004450d1320012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220341186a200041186a290000370000200341106a200041106a290000370000200341086a200041086a290000370000200320002900003700002000102f0c0d0b02400240200141046a280200200141086a2802002204460d00200128020021050c010b200441016a22052004490d13200441017422062005200620054b1b22064100480d130240024020040d002006102d21050c010b200128020020042006103121050b2005450d1220012005360200200141046a2006360200200141086a28020021040b200141086a220a200441016a360200200520046a41053a0000200028022c2109200041346a28020022042001106902400240200141046a2802002206200a28020022056b2004490d00200128020021060c010b200520046a220a2005490d1320064101742205200a2005200a4b1b22054100480d130240024020060d002005102d21060c010b200128020020062005103121060b2006450d1220012006360200200141046a2005360200200141086a28020021050b200141086a220a200520046a360200200620056a2009200410e8061a02400240200141046a2802002205200a28020022046b4120490d00200128020021050c010b200441206a22062004490d13200541017422042006200420064b1b22044100480d130240024020050d002004102d21050c010b200128020020052004103121050b2005450d1220012005360200200141046a2004360200200141086a28020021040b200141086a2206200441206a360200200520046a220441186a200341196a290000370000200441106a200341116a290000370000200441086a200341096a29000037000020042003290001370000200041c0006a29030021072000290338210e02400240200141046a2802002203200628020022006b4110490d00200128020021030c010b200041106a22042000490d13200341017422002004200020044b1b22004100480d130240024020030d002000102d21030c010b200128020020032000103121030b2003450d1220012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a220020073700082000200e3700000c0c0b02400240200141046a280200200141086a2802002204460d00200128020021050c010b200441016a22052004490d12200441017422062005200620054b1b22064100480d120240024020040d002006102d21050c010b200128020020042006103121050b2005450d1120012005360200200141046a2006360200200141086a28020021040b200141086a2206200441016a360200200520046a41063a00004120102d2204450d1020042003290001370000200441186a200341196a290000370000200441106a200341116a290000370000200441086a200341096a29000037000002400240200141046a2802002205200628020022036b4120490d00200128020021050c010b200341206a22062003490d12200541017422032006200320064b1b22034100480d120240024020050d002003102d21050c010b200128020020052003103121050b2005450d1120012005360200200141046a2003360200200141086a28020021030b200141086a2206200341206a360200200520036a220341186a200441186a290000370000200341106a200441106a290000370000200341086a200441086a290000370000200320042900003700002004102f200041386a29030021072000290330210e02400240200141046a2802002203200628020022006b4110490d00200128020021030c010b200041106a22042000490d12200341017422002004200020044b1b22004100480d120240024020030d002000102d21030c010b200128020020032000103121030b2003450d1120012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a220020073700082000200e3700000c0b0b02400240200141046a280200200141086a2802002200460d00200128020021040c010b200041016a22042000490d11200041017422052004200520044b1b22054100480d110240024020000d002005102d21040c010b200128020020002005103121040b2004450d1020012004360200200141046a2005360200200141086a28020021000b200141086a2205200041016a360200200420006a41073a00004120102d2200450d0f20002003290001370000200041186a200341196a290000370000200041106a200341116a290000370000200041086a200341096a29000037000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d11200441017422032005200320054b1b22034100480d110240024020040d002003102d21040c010b200128020020042003103121040b2004450d1020012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220341186a200041186a290000370000200341106a200041106a290000370000200341086a200041086a290000370000200320002900003700002000102f0c0a0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d10200341017422052004200520044b1b22054100480d100240024020030d002005102d21040c010b200128020020032005103121040b2004450d0f20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41113a0000200041086a22032d0000417f6a220441044b0d090240024002400240024020040e050001020304000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d14200341017422052004200520044b1b22054100480d140240024020030d002005102d21040c010b200128020020032005103121040b2004450d1320012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041106a200110f6010c0d0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d13200341017422052004200520044b1b22054100480d130240024020030d002005102d21040c010b200128020020032005103121040b2004450d1220012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a0000200041186a200110e902200028020c2106200041146a28020022002001106902400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d13200441017422032005200320054b1b22034100480d130240024020040d002003102d21040c010b200128020020042003103121040b2004450d1220012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010e8061a0c0c0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d12200341017422052004200520044b1b22054100480d120240024020030d002005102d21040c010b200128020020032005103121040b2004450d1120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a00002000410c6a200110eb022002200041c0006a3602002002200110c202200041d0006a200110e90220002802302106200041386a28020022002001106902400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d12200441017422032005200320054b1b22034100480d120240024020040d002003102d21040c010b200128020020042003103121040b2004450d1120012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010e8061a0c0b0b02400240200141046a280200200141086a2802002204460d00200128020021050c010b200441016a22052004490d11200441017422062005200620054b1b22064100480d110240024020040d002006102d21050c010b200128020020042006103121050b2005450d1020012005360200200141046a2006360200200141086a28020021040b200141086a2206200441016a360200200520046a41033a00002002200041386a3602002002200110c202200041c8006a200110e9024120102d2204450d0f20042003290001370000200441186a200341196a290000370000200441106a200341116a290000370000200441086a200341096a29000037000002400240200141046a2802002205200628020022036b4120490d00200128020021050c010b200341206a22062003490d11200541017422032006200320064b1b22034100480d110240024020050d002003102d21050c010b200128020020052003103121050b2005450d1020012005360200200141046a2003360200200141086a28020021030b200141086a2206200341206a360200200520036a220341186a200441186a290000370000200341106a200441106a290000370000200341086a200441086a290000370000200320042900003700002004102f200028022c2105200041346a28020022002001106902400240200141046a2802002204200628020022036b2000490d00200128020021040c010b200320006a22062003490d11200441017422032006200320064b1b22034100480d110240024020040d002003102d21040c010b200128020020042003103121040b2004450d1020012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2005200010e8061a0c0a0b02400240200141046a280200200141086a2802002200460d00200128020021040c010b200041016a22042000490d10200041017422052004200520044b1b22054100480d100240024020000d002005102d21040c010b200128020020002005103121040b2004450d0f20012004360200200141046a2005360200200141086a28020021000b200141086a2205200041016a360200200420006a41043a000002400240200141046a2802002204200528020022006b4120490d00200128020021040c010b200041206a22052000490d10200441017422002005200020054b1b22004100480d100240024020040d002000102d21040c010b200128020020042000103121040b2004450d0f20012004360200200141046a2000360200200141086a28020021000b200141086a2205200041206a360200200420006a220041186a200341196a290000370000200041106a200341116a290000370000200041086a200341096a29000037000020002003290001370000024020032d00214101460d0002400240200141046a28020020052802002200460d00200128020021030c010b200041016a22032000490d11200041017422042003200420034b1b22044100480d110240024020000d002004102d21030c010b200128020020002004103121030b2003450d1020012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41003a00000c0a0b02400240200141046a28020020052802002200460d00200128020021040c010b200041016a22042000490d10200041017422052004200520044b1b22054100480d100240024020000d002005102d21040c010b200128020020002005103121040b2004450d0f20012004360200200141046a2005360200200141086a28020021000b200141086a2205200041016a360200200420006a41013a000002400240200141046a2802002204200528020022006b4120490d00200128020021040c010b200041206a22052000490d10200441017422002005200020054b1b22004100480d100240024020040d002000102d21040c010b200128020020042000103121040b2004450d0f20012004360200200141046a2000360200200141086a28020021000b200141086a200041206a360200200420006a220041186a200341226a220341186a290000370000200041106a200341106a290000370000200041086a200341086a290000370000200020032900003700000c090b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0f200341017422052004200520044b1b22054100480d0f0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0e20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41123a00002000280204417f6a220341024b0d0802400240024020030e03000102000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d11200341017422052004200520044b1b22054100480d110240024020030d002005102d21040c010b200128020020032005103121040b2004450d1020012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200028020820011091010c0a0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d10200341017422052004200520044b1b22054100480d100240024020030d002005102d21040c010b200128020020032005103121040b2004450d0f20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a0000200041086a200110eb020c090b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0f200341017422052004200520044b1b22054100480d0f0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0e20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a0000200041086a200110eb02200028022c20011091010c080b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0e200341017422052004200520044b1b22054100480d0e0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41133a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d0e200341017422052004200520044b1b22054100480d0e0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a00002000280204210602400240200141046a2802002204200528020022036b4104490d00200128020021040c010b200341046a22052003490d0e200441017422032005200320054b1b22034100480d0e0240024020040d002003102d21040c010b200128020020042003103121040b2004450d0d20012004360200200141046a2003360200200141086a28020021030b200141086a220a200341046a360200200420036a2006360000200041086a2802002106200041106a28020022032001106902400240200141046a2802002205200a28020022046b2003490d00200128020021050c010b200420036a220a2004490d0e20054101742204200a2004200a4b1b22044100480d0e0240024020050d002004102d21050c010b200128020020052004103121050b2005450d0d20012005360200200141046a2004360200200141086a28020021040b200141086a220a200420036a360200200520046a2006200310e8061a200041146a28020021052000411c6a28020022032001106902402003450d0020052003410c6c6a210c200141046a210b034020052802002109200541086a28020022032001106902400240200b2802002206200a28020022046b2003490d00200128020021060c010b200420036a22082004490d10200641017422042008200420084b1b22044100480d100240024020060d002004102d21060c010b200128020020062004103121060b2006450d0f20012006360200200b2004360200200a28020021040b200a200420036a360200200620046a2009200310e8061a2005410c6a2205200c470d000b0b200041206a280200210502400240200141046a2802002204200a28020022036b4104490d00200128020021040c010b200341046a22062003490d0e200441017422032006200320064b1b22034100480d0e0240024020040d002003102d21040c010b200128020020042003103121040b2004450d0d20012004360200200141046a2003360200200141086a28020021030b200141086a2206200341046a360200200420036a2005360000200041246a280200210502400240200141046a2802002204200628020022036b4104490d00200128020021040c010b200341046a22062003490d0e200441017422032006200320064b1b22034100480d0e0240024020040d002003102d21040c010b200128020020042003103121040b2004450d0d20012004360200200141046a2003360200200141086a28020021030b200141086a2206200341046a360200200420036a200536000002400240200141046a2802002204200628020022036b41c000490d00200128020021040c010b200341c0006a22052003490d0e200441017422032005200320054b1b22034100480d0e0240024020040d002003102d21040c010b200128020020042003103121040b2004450d0d20012004360200200141046a2003360200200141086a28020021030b200141086a200341c0006a360200200420036a220341386a200041286a220041386a290000370000200341306a200041306a290000370000200341286a200041286a290000370000200341206a200041206a290000370000200341186a200041186a290000370000200341106a200041106a290000370000200341086a200041086a290000370000200320002900003700000c070b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d0d200041017422042003200420034b1b22044100480d0d0240024020000d002004102d21030c010b200128020020002004103121030b2003450d0c20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41143a0000200110e8020c060b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d0c200041017422042003200420034b1b22044100480d0c0240024020000d002004102d21030c010b200128020020002004103121030b2003450d0b20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41153a0000200110e8020c050b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d0b200041017422042003200420034b1b22044100480d0b0240024020000d002004102d21030c010b200128020020002004103121030b2003450d0a20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41163a0000200110e8020c040b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0a200341017422052004200520044b1b22054100480d0a0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41173a0000200041086a22042d0000417f6a2203410a4b0d030240024002400240024002400240024002400240024020030e0b000102030405060708090a000b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d14200041017422052003200520034b1b22054100480d140240024020000d002005102d21030c010b200128020020002005103121030b2003450d1320012003360200200141046a2005360200200141086a28020021000b200141086a2205200041016a360200200320006a41003a000002400240200141046a2802002203200528020022006b4120490d00200128020021030c010b200041206a22052000490d14200341017422002005200020054b1b22004100480d140240024020030d002000102d21030c010b200128020020032000103121030b2003450d1320012003360200200141046a2000360200200141086a28020021000b200141086a200041206a360200200320006a220041186a200441196a290000370000200041106a200441116a290000370000200041086a200441096a290000370000200020042900013700000c0d0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d13200341017422052004200520044b1b22054100480d130240024020030d002005102d21040c010b200128020020032005103121040b2004450d1220012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00002000410c6a200110a6010c0c0b02400240200141046a280200200141086a2802002203460d00200128020021050c010b200341016a22042003490d12200341017422052004200520044b1b22044100480d120240024020030d002004102d21050c010b200128020020032004103121050b2005450d1120012005360200200141046a2004360200200141086a28020021030b200141086a2204200341016a360200200520036a41023a0000200028020c2103200041146a2802002200200110692000450d0b2003200041c4006c6a2108200141046a210503400240024020052802002206200428020022006b4120490d00200128020021060c010b200041206a220a2000490d1320064101742200200a2000200a4b1b22004100480d130240024020060d002000102d21060c010b200128020020062000103121060b2006450d122001200636020020052000360200200428020021000b2004200041206a360200200620006a220041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a290000370000200020032900003700002002200341206a220910a7012002280200210a0240024020052802002206200428020022006b20022802082203490d00200128020021060c010b200020036a220b2000490d1320064101742200200b2000200b4b1b22004100480d130240024020060d002000102d21060c010b200128020020062000103121060b2006450d122001200636020020052000360200200428020021000b2004200020036a360200200620006a200a200310e8061a02402002280204450d00200a102f0b2008200941246a2203470d000c0c0b0b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d11200041017422042003200420034b1b22044100480d110240024020000d002004102d21030c010b200128020020002004103121030b2003450d1020012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41033a00000c0a0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d10200341017422052004200520044b1b22054100480d100240024020030d002005102d21040c010b200128020020032005103121040b2004450d0f20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41043a00002000410c6a20011095022002200041106a3602002002200110c2020c090b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0f200341017422052004200520044b1b22054100480d0f0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0e20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41053a0000200028020c210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d0f200341017422002005200020054b1b22004100480d0f0240024020030d002000102d21030c010b200128020020032000103121030b2003450d0e20012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c080b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0e200341017422052004200520044b1b22054100480d0e0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41063a00002000410c6a20011095022002200041106a3602002002200110c2020c070b02400240200141046a280200200141086a2802002203460d00200128020021050c010b200341016a22052003490d0d200341017422062005200620054b1b22064100480d0d0240024020030d002006102d21050c010b200128020020032006103121050b2005450d0c20012005360200200141046a2006360200200141086a28020021030b200141086a2206200341016a360200200520036a41073a00002000412c6a200110950202400240200141046a2802002203200628020022006b4120490d00200128020021030c010b200041206a22052000490d0d200341017422002005200020054b1b22004100480d0d0240024020030d002000102d21030c010b200128020020032000103121030b2003450d0c20012003360200200141046a2000360200200141086a28020021000b200141086a200041206a360200200320006a220041186a200441196a290000370000200041106a200441116a290000370000200041086a200441096a290000370000200020042900013700000c060b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0c200341017422052004200520044b1b22054100480d0c0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41083a00002000410c6a20011095022000290310210702400240200141046a2802002203200528020022006b4108490d00200128020021030c010b200041086a22042000490d0c200341017422002004200020044b1b22004100480d0c0240024020030d002000102d21030c010b200128020020032000103121030b2003450d0b20012003360200200141046a2000360200200141086a28020021000b200141086a200041086a360200200320006a20073700000c050b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0b200341017422052004200520044b1b22054100480d0b0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0a20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41093a00002000410c6a2001109502200041106a200110eb02200041386a200110a5010c040b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0a200341017422052004200520044b1b22054100480d0a0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410a3a00002000410c6a200110eb020c030b02400240200141046a2206280200200141086a22032802002204460d00200128020021050c010b200441016a22052004490d092004410174220a2005200a20054b1b220a4100480d090240024020040d00200a102d21050c010b20012802002004200a103121050b2005450d0820012005360200200141046a200a360200200141086a28020021040b2003200441016a360200200520046a41183a0000200041086a22042d0000417f6a2205410b4b0d0202400240024002400240024002400240024002400240024020050e0c000102030405060708090a0b000b02400240200628020020032802002204460d00200128020021050c010b200441016a22052004490d142004410174220a2005200a20054b1b220a4100480d140240024020040d00200a102d21050c010b20012802002004200a103121050b2005450d1320012005360200200141046a200a360200200141086a28020021040b2003200441016a360200200520046a41003a0000200041186a29030021072000290310210e0240024020062802002204200328020022006b4110490d00200128020021040c010b200041106a22052000490d14200441017422002005200020054b1b22004100480d140240024020040d002000102d21040c010b200128020020042000103121040b2004450d1320012004360200200141046a2000360200200141086a28020021000b2003200041106a360200200420006a220020073700082000200e3700000c0d0b02400240200628020020032802002204460d00200128020021050c010b200441016a22052004490d132004410174220a2005200a20054b1b220a4100480d130240024020040d00200a102d21050c010b20012802002004200a103121050b2005450d1220012005360200200141046a200a360200200141086a28020021040b2003200441016a360200200520046a41013a0000200028020c21050240024020062802002204200328020022006b4104490d00200128020021040c010b200041046a22062000490d13200441017422002006200020064b1b22004100480d130240024020040d002000102d21040c010b200128020020042000103121040b2004450d1220012004360200200141046a2000360200200141086a28020021000b2003200041046a360200200420006a20053600000c0c0b02400240200628020020032802002205460d002001280200210a0c010b200541016a220a2005490d1220054101742209200a2009200a4b1b22094100480d120240024020050d002009102d210a0c010b2001280200200520091031210a0b200a450d112001200a360200200141046a2009360200200141086a28020021050b2003200541016a360200200a20056a41023a0000024002402006280200220a200328020022056b4120490d002001280200210a0c010b200541206a22092005490d12200a41017422052009200520094b1b22054100480d1202400240200a0d002005102d210a0c010b2001280200200a20051031210a0b200a450d112001200a360200200141046a2005360200200141086a28020021050b2003200541206a360200200a20056a220541186a200441196a290000370000200541106a200441116a290000370000200541086a200441096a29000037000020052004290001370000200041386a29030021072000290330210e0240024020062802002205200328020022046b4110490d00200128020021050c010b200441106a220a2004490d1220054101742204200a2004200a4b1b22044100480d120240024020050d002004102d21050c010b200128020020052004103121050b2005450d1120012005360200200141046a2004360200200141086a28020021040b2003200441106a360200200520046a220420073700082004200e370000200041c8006a29030021072000290340210e0240024020062802002204200328020022006b4110490d00200128020021040c010b200041106a22052000490d12200441017422002005200020054b1b22004100480d120240024020040d002000102d21040c010b200128020020042000103121040b2004450d1120012004360200200141046a2000360200200141086a28020021000b2003200041106a360200200420006a220020073700082000200e3700000c0b0b02400240200628020020032802002204460d00200128020021050c010b200441016a22052004490d132004410174220a2005200a20054b1b220a4100480d130240024020040d00200a102d21050c010b20012802002004200a103121050b2005450d1220012005360200200141046a200a360200200141086a28020021040b2003200441016a360200200520046a41033a0000200028020c21050240024020062802002204200328020022006b4104490d00200128020021040c010b200041046a22062000490d13200441017422002006200020064b1b22004100480d130240024020040d002000102d21040c010b200128020020042000103121040b2004450d1220012004360200200141046a2000360200200141086a28020021000b2003200041046a360200200420006a20053600000c0a0b02400240200628020020032802002205460d00200128020021060c010b200541016a22062005490d122005410174220a2006200a20064b1b220a4100480d120240024020050d00200a102d21060c010b20012802002005200a103121060b2006450d1120012006360200200141046a200a360200200141086a28020021050b200141086a220a200541016a360200200620056a41043a00002000410c6a200110eb0220042d0001210502400240200141046a280200200a2802002200460d00200128020021040c010b200041016a22042000490d12200041017422062004200620044b1b22064100480d120240024020000d002006102d21040c010b200128020020002006103121040b2004450d1120012004360200200141046a2006360200200141086a28020021000b2003200041016a360200200420006a20053a00000c090b02400240200628020020032802002200460d00200128020021050c010b200041016a22052000490d112000410174220a2005200a20054b1b220a4100480d110240024020000d00200a102d21050c010b20012802002000200a103121050b2005450d1020012005360200200141046a200a360200200141086a28020021000b2003200041016a360200200520006a41053a000020042d0001210502400240200628020020032802002200460d00200128020021040c010b200041016a22042000490d11200041017422062004200620044b1b22064100480d110240024020000d002006102d21040c010b200128020020002006103121040b2004450d1020012004360200200141046a2006360200200141086a28020021000b2003200041016a360200200420006a20053a00000c080b02400240200628020020032802002200460d00200128020021040c010b200041016a22042000490d10200041017422052004200520044b1b22054100480d100240024020000d002005102d21040c010b200128020020002005103121040b2004450d0f20012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41063a00000c070b02400240200628020020032802002205460d002001280200210a0c010b200541016a220a2005490d0f20054101742209200a2009200a4b1b22094100480d0f0240024020050d002009102d210a0c010b2001280200200520091031210a0b200a450d0e2001200a360200200141046a2009360200200141086a28020021050b2003200541016a360200200a20056a41073a0000024002402006280200220a200328020022056b4120490d002001280200210a0c010b200541206a22092005490d0f200a41017422052009200520094b1b22054100480d0f02400240200a0d002005102d210a0c010b2001280200200a20051031210a0b200a450d0e2001200a360200200141046a2005360200200141086a28020021050b2003200541206a360200200a20056a220541186a200441196a290000370000200541106a200441116a290000370000200541086a200441096a29000037000020052004290001370000200028022c210a0240024020062802002205200328020022046b4104490d00200128020021050c010b200441046a22062004490d0f200541017422042006200420064b1b22044100480d0f0240024020050d002004102d21050c010b200128020020052004103121050b2005450d0e20012005360200200141046a2004360200200141086a28020021040b200141086a2206200441046a360200200520046a200a3600002000280230210a200041386a28020022002001106902400240200141046a2802002205200628020022046b2000490d00200128020021050c010b200420006a22062004490d0f200541017422042006200420064b1b22044100480d0f0240024020050d002004102d21050c010b200128020020052004103121050b2005450d0e20012005360200200141046a2004360200200141086a28020021040b2003200420006a360200200520046a200a200010e8061a0c060b02400240200628020020032802002200460d00200128020021040c010b200041016a22042000490d0e200041017422052004200520044b1b22054100480d0e0240024020000d002005102d21040c010b200128020020002005103121040b2004450d0d20012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41083a00000c050b02400240200628020020032802002200460d00200128020021050c010b200041016a22052000490d0d2000410174220a2005200a20054b1b220a4100480d0d0240024020000d00200a102d21050c010b20012802002000200a103121050b2005450d0c20012005360200200141046a200a360200200141086a28020021000b2003200041016a360200200520006a41093a00000240024020062802002205200328020022006b4120490d00200128020021050c010b200041206a220a2000490d0d20054101742200200a2000200a4b1b22004100480d0d0240024020050d002000102d21050c010b200128020020052000103121050b2005450d0c20012005360200200141046a2000360200200141086a28020021000b2003200041206a360200200520006a220041186a200441196a290000370000200041106a200441116a290000370000200041086a200441096a2900003700002000200429000137000020042d0021210502400240200628020020032802002200460d00200128020021040c010b200041016a22042000490d0d200041017422062004200620044b1b22064100480d0d0240024020000d002006102d21040c010b200128020020002006103121040b2004450d0c20012004360200200141046a2006360200200141086a28020021000b2003200041016a360200200420006a20053a00000c040b02400240200628020020032802002200460d00200128020021050c010b200041016a22052000490d0c2000410174220a2005200a20054b1b220a4100480d0c0240024020000d00200a102d21050c010b20012802002000200a103121050b2005450d0b20012005360200200141046a200a360200200141086a28020021000b2003200041016a360200200520006a410a3a00000240024020062802002205200328020022006b4120490d00200128020021050c010b200041206a220a2000490d0c20054101742200200a2000200a4b1b22004100480d0c0240024020050d002000102d21050c010b200128020020052000103121050b2005450d0b20012005360200200141046a2000360200200141086a28020021000b2003200041206a360200200520006a220041186a200441196a290000370000200041106a200441116a290000370000200041086a200441096a2900003700002000200429000137000020042d0021220041024b0d0302400240024020000e03000102000b02400240200628020020032802002200460d00200128020021040c010b200041016a22042000490d0e200041017422052004200520044b1b22054100480d0e0240024020000d002005102d21040c010b200128020020002005103121040b2004450d0d20012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41003a00000c050b02400240200628020020032802002200460d00200128020021040c010b200041016a22042000490d0d200041017422052004200520044b1b22054100480d0d0240024020000d002005102d21040c010b200128020020002005103121040b2004450d0c20012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41013a00000c040b02400240200628020020032802002200460d00200128020021040c010b200041016a22042000490d0c200041017422052004200520044b1b22054100480d0c0240024020000d002005102d21040c010b200128020020002005103121040b2004450d0b20012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41023a00000c030b02400240200628020020032802002204460d00200128020021050c010b200441016a22052004490d0b2004410174220a2005200a20054b1b220a4100480d0b0240024020040d00200a102d21050c010b20012802002004200a103121050b2005450d0a20012005360200200141046a200a360200200141086a28020021040b2003200441016a360200200520046a410b3a0000200028020c21050240024020062802002204200328020022006b4104490d00200128020021040c010b200041046a22062000490d0b200441017422002006200020064b1b22004100480d0b0240024020040d002000102d21040c010b200128020020042000103121040b2004450d0a20012004360200200141046a2000360200200141086a28020021000b2003200041046a360200200420006a20053600000c020b02400240200141046a220a280200200141086a22042802002203460d00200128020021050c010b200341016a22052003490d0a200341017422062005200620054b1b22064100480d0a0240024020030d002006102d21050c010b200128020020032006103121050b2005450d0920012005360200200141046a2006360200200141086a28020021030b2004200341016a360200200520036a41193a0000200041046a22092d0000417f6a220341084b0d0102400240024002400240024002400240024020030e09000102030405060708000b02400240200a28020020042802002203460d00200128020021050c010b200341016a22052003490d12200341017422062005200620054b1b22064100480d120240024020030d002006102d21050c010b200128020020032006103121050b2005450d1120012005360200200141046a2006360200200141086a28020021030b2004200341016a360200200520036a41003a000002400240200a2802002205200428020022036b4120490d00200128020021040c010b200341206a22042003490d12200541017422032004200320044b1b22034100480d120240024020050d002003102d21040c010b200128020020052003103121040b2004450d1120012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220341186a200941196a290000370000200341106a200941116a290000370000200341086a200941096a29000037000020032009290001370000200028022820011091010c090b02400240200a28020020042802002200460d00200128020021030c010b200041016a22032000490d11200041017422052003200520034b1b22054100480d110240024020000d002005102d21030c010b200128020020002005103121030b2003450d1020012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41013a000002400240200a2802002203200428020022006b4120490d00200128020021030c010b200041206a22052000490d11200341017422002005200020054b1b22004100480d110240024020030d002000102d21030c010b200128020020032000103121030b2003450d1020012003360200200141046a2000360200200141086a28020021000b2004200041206a360200200320006a220041186a200941196a290000370000200041106a200941116a290000370000200041086a200941096a2900003700002000200929000137000002400240200a2802002203200428020022006b4120490d00200128020021030c010b200041206a22052000490d11200341017422002005200020054b1b22004100480d110240024020030d002000102d21030c010b200128020020032000103121030b2003450d1020012003360200200141046a2000360200200141086a28020021000b2004200041206a360200200320006a220041186a200941216a220341186a290000370000200041106a200341106a290000370000200041086a200341086a290000370000200020032900003700000c080b02400240200a28020020042802002203460d00200128020021050c010b200341016a22052003490d10200341017422062005200620054b1b22064100480d100240024020030d002006102d21050c010b200128020020032006103121050b2005450d0f20012005360200200141046a2006360200200141086a28020021030b200141086a220c200341016a360200200520036a41023a000020002802082103200041106a28020022052001106902402005450d002005410574210b200141046a210d034002400240200a2802002206200428020022056b4120490d00200128020021060c010b200541206a22082005490d12200641017422052008200520084b1b22054100480d120240024020060d002005102d21060c010b200128020020062005103121060b2006450d1120012006360200200d2005360200200c28020021050b2004200541206a360200200620056a220541186a200341186a290000370000200541106a200341106a290000370000200541086a200341086a29000037000020052003290000370000200341206a2103200b41606a220b0d000b0b20092f0102210602400240200a2802002205200428020022036b4102490d00200128020021050c010b200341026a22092003490d10200541017422032009200320094b1b22034100480d100240024020050d002003102d21050c010b200128020020052003103121050b2005450d0f20012005360200200141046a2003360200200141086a28020021030b2004200341026a360200200520036a20063b00002000280214210502400240200a2802002203200428020022006b4104490d00200128020021030c010b200041046a22062000490d10200341017422002006200020064b1b22004100480d100240024020030d002000102d21030c010b200128020020032000103121030b2003450d0f20012003360200200141046a2000360200200141086a28020021000b2004200041046a360200200320006a20053600000c070b02400240200a28020020042802002200460d00200128020021030c010b200041016a22032000490d0f200041017422052003200520034b1b22054100480d0f0240024020000d002005102d21030c010b200128020020002005103121030b2003450d0e20012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41033a000002400240200a2802002203200428020022006b4120490d00200128020021030c010b200041206a22052000490d0f200341017422002005200020054b1b22004100480d0f0240024020030d002000102d21030c010b200128020020032000103121030b2003450d0e20012003360200200141046a2000360200200141086a28020021000b2004200041206a360200200320006a220041186a200941196a290000370000200041106a200941116a290000370000200041086a200941096a290000370000200020092900013700000c060b02400240200a28020020042802002200460d00200128020021030c010b200041016a22032000490d0e200041017422052003200520034b1b22054100480d0e0240024020000d002005102d21030c010b200128020020002005103121030b2003450d0d20012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41043a000002400240200a2802002203200428020022006b4120490d00200128020021030c010b200041206a22052000490d0e200341017422002005200020054b1b22004100480d0e0240024020030d002000102d21030c010b200128020020032000103121030b2003450d0d20012003360200200141046a2000360200200141086a28020021000b2004200041206a360200200320006a220041186a200941196a290000370000200041106a200941116a290000370000200041086a200941096a2900003700002000200929000137000002400240200a2802002203200428020022006b4120490d00200128020021030c010b200041206a22052000490d0e200341017422002005200020054b1b22004100480d0e0240024020030d002000102d21030c010b200128020020032000103121030b2003450d0d20012003360200200141046a2000360200200141086a28020021000b2004200041206a360200200320006a220041186a200941216a220341186a290000370000200041106a200341106a290000370000200041086a200341086a290000370000200020032900003700000c050b02400240200a28020020042802002200460d00200128020021030c010b200041016a22032000490d0d200041017422052003200520034b1b22054100480d0d0240024020000d002005102d21030c010b200128020020002005103121030b2003450d0c20012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41053a000002400240200a2802002203200428020022006b4120490d00200128020021030c010b200041206a22052000490d0d200341017422002005200020054b1b22004100480d0d0240024020030d002000102d21030c010b200128020020032000103121030b2003450d0c20012003360200200141046a2000360200200141086a28020021000b2004200041206a360200200320006a220041186a200941196a290000370000200041106a200941116a290000370000200041086a200941096a290000370000200020092900013700000c040b02400240200a28020020042802002200460d00200128020021030c010b200041016a22032000490d0c200041017422052003200520034b1b22054100480d0c0240024020000d002005102d21030c010b200128020020002005103121030b2003450d0b20012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41063a000002400240200a2802002203200428020022006b4120490d00200128020021030c010b200041206a22052000490d0c200341017422002005200020054b1b22004100480d0c0240024020030d002000102d21030c010b200128020020032000103121030b2003450d0b20012003360200200141046a2000360200200141086a28020021000b2004200041206a360200200320006a220041186a200941196a290000370000200041106a200941116a290000370000200041086a200941096a290000370000200020092900013700000c030b02400240200a28020020042802002200460d00200128020021030c010b200041016a22032000490d0b200041017422052003200520034b1b22054100480d0b0240024020000d002005102d21030c010b200128020020002005103121030b2003450d0a20012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41073a00000c020b02400240200a28020020042802002200460d00200128020021030c010b200041016a22032000490d0a200041017422052003200520034b1b22054100480d0a0240024020000d002005102d21030c010b200128020020002005103121030b2003450d0920012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41083a000002400240200a2802002203200428020022006b4120490d00200128020021030c010b200041206a22052000490d0a200341017422002005200020054b1b22004100480d0a0240024020030d002000102d21030c010b200128020020032000103121030b2003450d0920012003360200200141046a2000360200200141086a28020021000b2004200041206a360200200320006a220041186a200941196a290000370000200041106a200941116a290000370000200041086a200941096a290000370000200020092900013700000c010b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d09200341017422052004200520044b1b22054100480d090240024020030d002005102d21040c010b200128020020032005103121040b2004450d0820012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a411a3a00002000280208417f6a220341024b0d0002400240024020030e03000102000b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d0b200041017422042003200420034b1b22044100480d0b0240024020000d002004102d21030c010b200128020020002004103121030b2003450d0a20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41003a00000c020b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0a200341017422052004200520044b1b22054100480d0a0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00002000410c6a200110eb020c010b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d09200341017422052004200520044b1b22054100480d090240024020030d002005102d21040c010b200128020020032005103121040b2004450d0820012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a00002000410c6a200110eb02200041386a29030021072000290330210e02400240200141046a2802002204200528020022036b4110490d00200128020021040c010b200341106a22052003490d09200441017422032005200320054b1b22034100480d090240024020040d002003102d21040c010b200128020020042003103121040b2004450d0820012004360200200141046a2003360200200141086a28020021030b200141086a2205200341106a360200200420036a220320073700082003200e370000200041c8006a2903002107200041c0006a290300210e02400240200141046a2802002204200528020022036b4110490d00200128020021040c010b200341106a22052003490d09200441017422032005200320054b1b22034100480d090240024020040d002003102d21040c010b200128020020042003103121040b2004450d0820012004360200200141046a2003360200200141086a28020021030b200141086a2205200341106a360200200420036a220320073700082003200e370000200041d0006a280200210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d09200341017422002005200020054b1b22004100480d090240024020030d002000102d21030c010b200128020020032000103121030b2003450d0820012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000b200241206a24000f0b1036000b1038000b1036000b1038000b1036000b1038000b1036000b1038000bb40703027f017e047f230041d0006b2203240041b8c4c300ad4280808080f00084100122042900002105200341086a200441086a290000370300200320053703002004102f41b4d9c000ad4280808080900184100122042900002105200341286a41086a200441086a290000370300200320053703282004102f024002404120102d2204450d0020042001290000370000200441186a200141186a290000370000200441106a200141106a290000370000200441086a200141086a29000037000020032004ad4280808080800484100622012900003703202001102f200341c4006a200441206a360200200341003a0048200320043602402003200341206a41086a36023c2003200341206a360238200341106a200341386a106c2004102f02400240024002402003280218220641206a2207417f4c0d0020032802102108024002402007450d002007102d2204450d062007410f4d0d01200721090c050b411021094110102d21040c030b200741017422014110200141104b1b220941004e0d010c050b103d000b200420072009103121040b2004450d010b20042003290300370000200441086a200341086a2903003700000240024020094170714110460d00200921010c010b200941017422014120200141204b1b22014100480d0220042009200110312204450d010b20042003290328370010200441186a200341286a41086a29030037000002400240200141606a2006490d00200121090c010b2006415f4b0d02200141017422092007200920074b1b22094100480d0220042001200910312204450d010b200441206a2008200610e8061a02402003280214450d002008102f0b4120102d2201450d0020012002290000370000200141186a200241186a290000370000200141106a200241106a290000370000200141086a200241086a2900003700002001ad4280808080800484100722022900002105200341286a41086a200241086a290000370300200320053703282002102f200341c4006a200141206a360200200341003a0048200320013602402003200341286a41106a36023c2003200341286a3602382003200341386a106c2001102f2003280200210602400240200920076b20032802082201490d00200120076a2102200921080c010b200720016a22022007490d02200941017422082002200820024b1b22084100480d0220042009200810312204450d010b200420076a2006200110e8061a02402003280204450d002006102f0b200020023602082000200836020420002004360200200341d0006a24000f0b1036000b1038000b850604067f027e027f057e23004190016b220324002003200236020420032001360200200341086a2002ad4220862001ad84100210730240024020032802082202450d00200328020c21042003200341106a280200220136023c200320023602380240024020014104490d002003200241046a36023820032001417c6a220536023c20054104490d00200228000021062003200241086a3602382003200141786a220536023c20054110490d00200228000421072003200141686a220836023c2003200241186a360238200241106a29000021092002290008210a41002101200341003a0088010240034020082001460d01200341e8006a20016a200220016a220541186a2d00003a00002003200541196a3602382003200141016a22053a0088012005210120054120470d000b200341c8006a41086a2201200341e8006a41086a290300370300200341c8006a41106a220b200341e8006a41106a290300370300200341c8006a41186a220c200341e8006a41186a290300370300200320032903683703482003200820056b36023c200341e8006a200341386a10980320032802682205450d01200341186a41086a2001290300220d370300200341186a41106a200b290300220e370300200341186a41186a200c290300220f370300200320032903482210370318200329026c2111200020093703082000200a3703002000201137021c200020053602182000200736021420002006360210200041246a20103702002000412c6a200d370200200041346a200e3702002000413c6a200f3702000c020b2003410036023c200141ff0171450d00200341003a0088010b20034100360250200342013703482003410b36021c200320033602182003200341c8006a360244200341fc006a41013602002003420137026c200341b885c7003602682003200341186a360278200341c4006a41d8dbc100200341e8006a103c1a200335025042208620033502488410080240200328024c450d002003280248102f0b200041003602180b2004450d012002102f0c010b200041003602180b20034190016a24000b830f08047f017e017f027e027f097e017f017e230041f0026b22032400200228020821042002280204210520022802002106418de6c300ad4280808080e00084100122022900002107200341386a41086a200241086a290000370300200320073703382002102f41f0e8c600ad4280808080f00084100122022900002107200341f0006a41086a200241086a290000370300200320073703702002102f0240024002404120102d2202450d0020022001290000370000200241186a200141186a290000370000200241106a200141106a290000370000200241086a200141086a2900003700002002ad4280808080800484100322082900002107200841086a2900002109200841106a290000210a200341f0016a41186a220b200841186a290000370300200341f0016a41106a220c200a370300200341f0016a41086a2009370300200320073703f0012008102f2002102f41c000102d2202450d002002200329033837000020022003290370370010200220032903f001370020200241086a200341386a41086a290300370000200241186a200341f0006a41086a290300370000200241286a200341f0016a41086a290300370000200241306a200c290300370000200241386a200b290300370000200341f0006a200210f6022003290370210d4200210e20034200370370200341b8016a280200210820032d00bc01210b02400240200d4201510d00200341306a4200370300200341286a4200370300200341206a4200370300200341186a4200370300200341106a4200370300200341086a4200370300200342003703004200210f4200210942002107420021100c010b200341f0006a41386a290300210a200341f0006a41306a2903002111200341f0006a41206a290300210f200341f0006a41186a290300210e200341f0006a41c0006a2903002110200329038001210720032903782109200341206a200341f0006a41286a290300370300200341286a2011370300200341306a200a370300200341106a200e3703002003200f37031820032009370300200320073703080b02402009200629030022117d22122009562007200641086a29030022137d2009201154ad7d220a200756200a2007511b450d0041838c0c21084198b5c60021014280808080b00221070c020b200320123703002003200a3703080240200e20117c2214200e542206200f20137c2006ad7c2215200f542015200f511b450d0041838c0821084191ccc70021014280808080800121070c020b200341186a20153703002003201437031002402011201384500d00200341f0016a2005280200108d0220032903900220125620034198026a2903002211200a562011200a511b450d0041838c04210841abb5c60021014280808080d00221070c020b2004280200210c200341386a41186a200341106a220641086a2903002211370300200341386a41206a2204200641106a290300370300200341e0006a2205200641186a290300370300200341e8006a2216200641206a290300370300200320062903002213370348200320123703382003200a370340427f2009200e7c220e200e20095422062007200f7c2006ad7c220920075420092007511b22061b427f200920061b84210e02400240427f201220137c220720072012542206200a20117c2006ad7c2207200a542007200a511b22061b2209428080e983b1de16544100427f200720061b2207501b0d00200341386a41106a2903002107201629030021092005290300210f20042903002111200329034021132003290338211542012114200329035021170c010b4200211402402009200784500d0020092007109a01200341a8026a2007370300200341a0026a2009370300200341f0016a41086a41013a0000200341f9016a200c29000037000020034181026a200c41086a29000037000020034189026a200c41106a29000037000020034191026a200c41186a290000370000200341033a00f00141c8e1ca004100200341f0016a108c010b0b200e50210c20034198016a2011370300200341a0016a200f37030020034180016a2013370300200341a8016a200937030020034188016a20073703002003201737039001200320103703b00120032015370378410021062003200b4100200d42015122041b3a00bc0120032008410020041b3602b801200320144201512208ad3703700240024020080d002002ad42808080808008841005410121060c010b200341c0003602f401200320023602f001200341f8006a200341f0016a1090030b200cad21072002102f024002400240200d4201510d0020060d0041032108200341f0016a21020c010b200d4201522006410173720d0141042108200341f0006a21020b200241046a20083a0000200241003a0000200241056a20012900003700002002410d6a200141086a290000370000200241156a200141106a2900003700002002411d6a200141186a29000037000041c8e1ca0041002002108c010b200041186a200a370300200041106a2012370300200041086a2007370300410021020c020b1036000b2002102f20002008360204200041086a2007200141ff0171ad842001ad22074280fe0383842007428080fcff0f8384370200410121020b20002002360200200341f0026a24000b8e0201037f230041d0006b220324002003200236020420032001360200200341086a2002ad4220862001ad841002107302400240200328020822040d00410021010c010b200328020c210502400240200341106a2802004104490d0020042800002102410121010c010b4100210120034100360220200342013703182003410b36022c200320033602282003200341186a360234200341cc006a41013602002003420137023c200341b885c7003602382003200341286a360248200341346a41d8dbc100200341386a103c1a200335022042208620033502188410080240200328021c450d002003280218102f0b0b2005450d002004102f0b2000200236020420002001360200200341d0006a24000bd00d08027f017e017f027e027f0b7e037f037e230041f0026b2204240020032802002105418de6c300ad4280808080e00084100122032900002106200441386a41086a200341086a290000370300200420063703382003102f41f0e8c600ad4280808080f00084100122032900002106200441f0006a41086a200341086a290000370300200420063703702003102f02404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100322072900002106200741086a2900002108200741106a2900002109200441f0016a41186a220a200741186a290000370300200441f0016a41106a220b2009370300200441f0016a41086a2008370300200420063703f0012007102f2003102f41c000102d2203450d002003200429033837000020032004290370370010200320042903f001370020200341086a200441386a41086a290300370000200341186a200441f0006a41086a290300370000200341286a200441f0016a41086a290300370000200341306a200b290300370000200341386a200a290300370000200441f0006a200310f6022004290370210c4200210820044200370370200441b8016a280200210720042d00bc01210a02400240200c4201510d00200441306a4200370300200441286a4200370300200441206a4200370300200441186a4200370300200441106a4200370300200441086a420037030020044200370300420021094200210d420021064200210e0c010b200441f0006a41386a290300210f200441f0006a41306a2903002110200441f0006a41206a2903002109200441f0006a41186a2903002108200441f0006a41c0006a290300210e20042903800121062004290378210d200441206a200441f0006a41286a290300370300200441286a2010370300200441306a200f370300200441106a2008370300200420093703182004200d370300200420063703080b200441186a2009200241086a2903002211200920082002290300221256200920115620092011511b22021b22137d20082012200820021b221054ad7d22143703002004200820107d22153703102004427f200620137c200d20107c2216200d542202ad7c220f2002200f200654200f2006511b22021b220f3703082004427f201620021b2216370300200441386a41186a2014370300200441386a41206a2217200441206a290300370300200441386a41286a2218200441286a290300370300200441386a41306a2219200441306a2903003703002004200f370340200420163703382004201537034820122010542102427f200d20087c22082008200d54220b200620097c200bad7c220820065420082006511b220b1b427f2008200b1b84210d02400240427f201620157c22062006201654220b200f20147c200bad7c2206200f542006200f511b220b1b2208428080e983b1de16544100427f2006200b1b2209501b0d00200441c8006a29030021082019290300210920182903002114201729030021152004290340211a2004290338211b420121062004290350211c0c010b4200210602402008200984500d0020082009109a01200441a8026a2009370300200441a0026a2008370300200441f0016a41086a41013a0000200441f9016a200529000037000020044181026a200541086a29000037000020044189026a200541106a29000037000020044191026a200541186a290000370000200441033a00f00141c8e1ca004100200441f0016a108c010b0b201120137d21112002ad2113200d50210220044198016a2015370300200441a0016a201437030020044180016a201a370300200441a8016a200937030020044188016a20083703002004201c370390012004200e3703b0012004201b3703782004200a4100200c42015122051b3a00bc0120042007410020051b3602b801200420064201512207ad3703700240024020070d002003ad428080808080088410050c010b200441c0003602f401200420033602f001200441f8006a200441f0016a1090030b201120137d21082002ad2109201220107d210d2003102f20064201522103024002400240200c4201510d0020030d0041032107200441f0016a21030c010b200c4201522003410173720d0141042107200441f0006a21030b200341046a20073a0000200341003a0000200341056a20012900003700002003410d6a200141086a290000370000200341156a200141106a2900003700002003411d6a200141186a29000037000041c8e1ca0041002003108c010b2000200d3703182000201637030820002009370300200041206a2008370300200041106a200f370300200441f0026a24000f0b1036000bb10101027f024020002802082201450d0020002802002100200141246c210103400240024020002d0000220241044b0d0002400240024020020e050400010204040b2000410c6a280200450d03200041086a280200102f0c030b2000410c6a280200450d02200041086a280200102f0c020b2000410c6a280200450d01200041086a280200102f0c010b200041086a280200450d00200041046a280200102f0b200041246a21002001415c6a22010d000b0b0b13002000410c360204200041b4e5c0003602000b1f0002402000280200450d00200041086a280200450d002000280204102f0b0bdd0908017f017e047f017e017f017e037f017e230041a0016b22022400200241386a20002001109b01200241386a41106a29030021012002290340210002400240024020022903382203a7450d00200241f0006a41186a22044200370300200241f0006a41106a22054200370300200241f0006a41086a220642003703002002420037037041e7a2ca00ad4280808080800184220310012207290000210820024190016a41086a2209200741086a29000037030020022008370390012007102f20062009290300370300200220022903900137037041ecb5c600ad4280808080d00184220810012207290000210a2009200741086a2900003703002002200a370390012007102f2005200229039001220a370300200241d0006a41086a220b2006290300370300200241d0006a41106a220c200a370300200241d0006a41186a220d200929030037030020022002290370370350200241206a200241d0006a4120109c01200241206a41106a290300210a2002290328210e200228022021072004420037030020054200370300200642003703002002420037037020031001220429000021032009200441086a29000037030020022003370390012004102f20062009290300370300200220022903900137037020081001220429000021032009200441086a29000037030020022003370390012004102f20052002290390012203370300200b2006290300370300200c2003370300200d20092903003703002002200229037037035020024200200a420020071b220320017d200e420020071b2201200054ad7d2208200120007d2200200156200820035620082003511b22091b37037820024200200020091b370370200241f0006a2109200241d0006a21060c010b2003500d01200241f0006a41186a22044200370300200241f0006a41106a22054200370300200241f0006a41086a220642003703002002420037037041e7a2ca00ad4280808080800184220310012207290000210820024190016a41086a2209200741086a29000037030020022008370390012007102f20062009290300370300200220022903900137037041ecb5c600ad4280808080d00184220810012207290000210a2009200741086a2900003703002002200a370390012007102f2005200229039001220a370300200241d0006a41086a220b2006290300370300200241d0006a41106a220c200a370300200241d0006a41186a220d200929030037030020022002290370370350200241086a200241d0006a4120109c01200241086a41106a290300210a2002290310210e200228020821072004420037030020054200370300200642003703002002420037037020031001220429000021032009200441086a29000037030020022003370390012004102f20062009290300370300200220022903900137037020081001220429000021032009200441086a29000037030020022003370390012004102f20052002290390012203370300200b2006290300370300200c2003370300200d20092903003703002002200229037037035020024200200a420020071b220320017d200e420020071b2201200054ad7d2208200120007d2200200156200820035620082003511b22091b37037820024200200020091b370370200241f0006a2109200241d0006a21060b2006ad42808080808004842009ad428080808080028410040b200241a0016a24000bd70408027f017e037f017e017f027e037f017e230041f0006b2203240020012002844200522204ad2105024020040d00200341c0006a41186a22064200370300200341c0006a41106a22074200370300200341c0006a41086a220842003703002003420037034041e7a2ca00ad428080808080018422091001220a290000210b200341e0006a41086a2204200a41086a2900003703002003200b370360200a102f200820042903003703002003200329036037034041ecb5c600ad4280808080d00184220b1001220a290000210c2004200a41086a2900003703002003200c370360200a102f20072003290360220c370300200341206a41086a220d2008290300370300200341206a41106a220e200c370300200341206a41186a220f200429030037030020032003290340370320200341086a200341206a4120109c01200341086a41106a290300210c200329031021102003280208210a2006420037030020074200370300200842003703002003420037034020091001220629000021092004200641086a290000370300200320093703602006102f2008200429030037030020032003290360370340200b1001220629000021092004200641086a290000370300200320093703602006102f200720032903602209370300200d2008290300370300200e2009370300200f2004290300370300200320032903403703202003200c4200200a1b370348200320104200200a1b370340200341206aad4280808080800484200341c0006aad428080808080028410040b2000200137030820002005370300200041106a2002370300200341f0006a24000ba70202017f037e230041d0006b220324002003200236020420032001360200200341086a2002ad4220862001ad841002107302400240200328020822010d00420021040c010b200328020c210202400240200341086a41086a2802004110490d00200141086a290000210520012900002106420121040c010b20034100360220200342013703182003410b36022c200320033602282003200341186a360234200341cc006a41013602002003420137023c200341b885c7003602382003200341286a360248200341346a41d8dbc100200341386a103c1a200335022042208620033502188410080240200328021c450d002003280218102f0b420021040b2002450d002001102f0b2000200637030820002004370300200041106a2005370300200341d0006a24000bde1006037f037e057f027e037f017e230041b0016b220724002004a721080240024002400240024020014201510d0041012109024020084101460d00427f200320067c200220057c220a2002542208ad7c220b2008200b200354200b2003511b22081b210b427f200a20081b210a4200210c4100210d0c030b02402002200556200320065620032006511b0d00200620037d2005200254ad7d210b200520027d210a4201210c0c020b200320067d2002200554ad7d210b200220057d210a4200210c0c010b4101210d024020084101470d00427f200320067c200220057c22012002542208ad7c22022008200220035420022003511b22081b210b427f200120081b210a410021094201210c0c030b200741306a200420052006420120022003109d01200741c0006a290300210b2007290338210a2007290330210c0c030b410021094101210d0b2001500d0020074180016a41186a220e420037030020074180016a41106a220f420037030020074180016a41086a22104200370300200742003703800141e7a2ca00ad42808080808001842201100122112900002112200741a0016a41086a2208201141086a290000370300200720123703a0012011102f20102008290300370300200720072903a0013703800141ecb5c600ad4280808080d0018422121001221129000021132008201141086a290000370300200720133703a0012011102f200f20072903a0012213370300200741e0006a41086a22142010290300370300200741e0006a41106a22152013370300200741e0006a41186a221620082903003703002007200729038001370360200741c8006a200741e0006a4120109c01200741c8006a41106a29030021132007290350211720072802482111200e4200370300200f420037030020104200370300200742003703800120011001220e29000021012008200e41086a290000370300200720013703a001200e102f20102008290300370300200720072903a0013703800120121001220e29000021012008200e41086a290000370300200720013703a001200e102f200f20072903a00122013703002014201029030037030020152001370300201620082903003703002007200729038001370360200742002013420020111b220120037d2017420020111b2203200254ad7d2212200320027d2202200356201220015620122001511b22081b3703880120074200200220081b37038001200741e0006aad428080808080048420074180016aad428080808080028410040b02402004500d002009450d0120074180016a41186a220f420037030020074180016a41106a2209420037030020074180016a41086a22104200370300200742003703800141e7a2ca00ad428080808080018422031001220d2900002102200741a0016a41086a2208200d41086a290000370300200720023703a001200d102f20102008290300370300200720072903a0013703800141ecb5c600ad4280808080d0018422021001220d29000021042008200d41086a290000370300200720043703a001200d102f200920072903a0012204370300200741e0006a41086a22112010290300370300200741e0006a41106a220e2004370300200741e0006a41186a221420082903003703002007200729038001370360200741186a200741e0006a4120109c01200741186a41106a2903002104200729032021012007280218210d200f42003703002009420037030020104200370300200742003703800120031001220f29000021032008200f41086a290000370300200720033703a001200f102f20102008290300370300200720072903a0013703800120021001220f29000021032008200f41086a290000370300200720033703a001200f102f200920072903a001220337030020112010290300370300200e20033703002014200829030037030020072007290380013703602007420020044200200d1b220320067d20014200200d1b2202200554ad7d2204200220057d2205200256200420035620042003511b22081b3703880120074200200520081b37038001200741e0006aad428080808080048420074180016aad428080808080028410040c010b200d450d0020074180016a41186a220f420037030020074180016a41106a2209420037030020074180016a41086a22104200370300200742003703800141e7a2ca00ad428080808080018422031001220d2900002102200741a0016a41086a2208200d41086a290000370300200720023703a001200d102f20102008290300370300200720072903a0013703800141ecb5c600ad4280808080d0018422021001220d29000021042008200d41086a290000370300200720043703a001200d102f200920072903a0012204370300200741e0006a41086a22112010290300370300200741e0006a41106a220e2004370300200741e0006a41186a2214200829030037030020072007290380013703602007200741e0006a4120109c01200741106a2903002104200729030821012007280200210d200f42003703002009420037030020104200370300200742003703800120031001220f29000021032008200f41086a290000370300200720033703a001200f102f20102008290300370300200720072903a0013703800120021001220f29000021032008200f41086a290000370300200720033703a001200f102f200920072903a001220337030020112010290300370300200e20033703002014200829030037030020072007290380013703602007427f20044200200d1b220320067c20014200200d1b220220057c22052002542208ad7c22022008200220035420022003511b22081b370388012007427f200520081b37038001200741e0006aad428080808080048420074180016aad428080808080028410040b2000200a3703082000200c370300200041106a200b370300200741b0016a24000b130020004103360204200041acfdc0003602000b3400200041adc5c30036020420004100360200200041146a4101360200200041106a418888c100360200200041086a42073702000b130020004101360204200041b089c1003602000b13002000410b360204200041dc8ac1003602000b3400200041a4e3c40036020420004100360200200041146a4104360200200041106a4188bac100360200200041086a42043702000b6001027f230041106b2202240002404114102d22030d001036000b200342003700082003420037000020024294808080800237020420022003360200410020021069200041086a200228020836020020002002290300370200200241106a24000b880301027f024020002802082201450d0020002802002202200141c8006c6a21010340024020022d00004101470d00200241086a280200450d00200241046a280200102f0b0240200241246a2d00004101470d002002412c6a280200450d00200241286a280200102f0b200241c8006a22022001470d000b0b0240200041046a280200450d002000280200102f0b024020002d000c4101470d00200041146a280200450d00200041106a280200102f0b024020002d00304101470d00200041386a280200450d00200041346a280200102f0b024020002d00544101470d00200041dc006a280200450d00200041d8006a280200102f0b024020002d00784101470d0020004180016a280200450d00200041fc006a280200102f0b024020002d009c014101470d00200041a4016a280200450d00200041a0016a280200102f0b024020002d00c0014101470d00200041c8016a280200450d00200041c4016a280200102f0b024020002d00e4014101470d00200041ec016a280200450d00200041e8016a280200102f0b0bc70a02037f027e0240024002402000280200220241064b0d00024002400240024002400240024020020e0700010203040506000b02400240200141046a280200200141086a2802002200460d00200128020021020c010b200041016a22022000490d09200041017422032002200320024b1b22034100480d090240024020000d002003102d21020c010b200128020020002003103121020b2002450d0820012002360200200141046a2003360200200141086a28020021000b200141086a200041016a360200200220006a41003a00000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d08200241017422042003200420034b1b22044100480d080240024020020d002004102d21030c010b200128020020022004103121030b2003450d0720012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41013a0000200041106a29030021052000290308210602400240200141046a2802002202200428020022006b4110490d00200128020021020c010b200041106a22032000490d08200241017422002003200020034b1b22004100480d080240024020020d002000102d21020c010b200128020020022000103121020b2002450d0720012002360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200220006a22012005370008200120063700000f0b02400240200141046a280200200141086a2802002200460d00200128020021020c010b200041016a22022000490d07200041017422032002200320024b1b22034100480d070240024020000d002003102d21020c010b200128020020002003103121020b2002450d0620012002360200200141046a2003360200200141086a28020021000b200141086a200041016a360200200220006a41023a00000f0b02400240200141046a280200200141086a2802002200460d00200128020021020c010b200041016a22022000490d06200041017422032002200320024b1b22034100480d060240024020000d002003102d21020c010b200128020020002003103121020b2002450d0520012002360200200141046a2003360200200141086a28020021000b200141086a200041016a360200200220006a41033a00000f0b02400240200141046a280200200141086a2802002200460d00200128020021020c010b200041016a22022000490d05200041017422032002200320024b1b22034100480d050240024020000d002003102d21020c010b200128020020002003103121020b2002450d0420012002360200200141046a2003360200200141086a28020021000b200141086a200041016a360200200220006a41043a00000f0b02400240200141046a280200200141086a2802002200460d00200128020021020c010b200041016a22022000490d04200041017422032002200320024b1b22034100480d040240024020000d002003102d21020c010b200128020020002003103121020b2002450d0320012002360200200141046a2003360200200141086a28020021000b200141086a200041016a360200200220006a41053a00000f0b02400240200141046a280200200141086a2802002200460d00200128020021020c010b200041016a22022000490d03200041017422032002200320024b1b22034100480d030240024020000d002003102d21020c010b200128020020002003103121020b2002450d0220012002360200200141046a2003360200200141086a28020021000b200141086a200041016a360200200220006a41063a00000b0f0b1036000b1038000be212010a7f230041106b220224002000280200210320002802082204200110690240024002402004450d002003200441c8006c6a2105200141086a2104200141046a210603402002200310a701200228020021070240024020062802002208200428020022096b2002280208220a490d00200128020021080c010b2009200a6a220b2009490d0420084101742209200b2009200b4b1b22094100480d040240024020080d002009102d21080c010b200128020020082009103121080b2008450d032001200836020020062009360200200428020021090b20042009200a6a360200200820096a2007200a10e8061a02402002280204450d002007102f0b2002200341246a220710a701200228020021080240024020062802002203200428020022096b2002280208220a490d00200128020021030c010b2009200a6a220b2009490d0420034101742209200b2009200b4b1b22094100480d040240024020030d002009102d21030c010b200128020020032009103121030b2003450d032001200336020020062009360200200428020021090b20042009200a6a360200200320096a2008200a10e8061a02402002280204450d002008102f0b200741246a22032005470d000b0b20022000410c6a10a7012002280200210302400240200141046a280200220a200141086a28020022046b20022802082209490d002001280200210a0c010b200420096a22062004490d02200a41017422042006200420064b1b22044100480d0202400240200a0d002004102d210a0c010b2001280200200a20041031210a0b200a450d012001200a360200200141046a2004360200200141086a28020021040b200141086a2206200420096a360200200a20046a2003200910e8061a02402002280204450d002003102f0b2002200041306a10a7012002280200210302400240200141046a280200220a200628020022046b20022802082209490d002001280200210a0c010b200420096a22062004490d02200a41017422042006200420064b1b22044100480d0202400240200a0d002004102d210a0c010b2001280200200a20041031210a0b200a450d012001200a360200200141046a2004360200200141086a28020021040b200141086a2206200420096a360200200a20046a2003200910e8061a02402002280204450d002003102f0b2002200041d4006a10a7012002280200210302400240200141046a280200220a200628020022046b20022802082209490d002001280200210a0c010b200420096a22062004490d02200a41017422042006200420064b1b22044100480d0202400240200a0d002004102d210a0c010b2001280200200a20041031210a0b200a450d012001200a360200200141046a2004360200200141086a28020021040b200141086a2206200420096a360200200a20046a2003200910e8061a02402002280204450d002003102f0b2002200041f8006a10a7012002280200210302400240200141046a280200220a200628020022046b20022802082209490d002001280200210a0c010b200420096a22062004490d02200a41017422042006200420064b1b22044100480d0202400240200a0d002004102d210a0c010b2001280200200a20041031210a0b200a450d012001200a360200200141046a2004360200200141086a28020021040b200141086a2206200420096a360200200a20046a2003200910e8061a02402002280204450d002003102f0b20022000419c016a10a7012002280200210302400240200141046a280200220a200628020022046b20022802082209490d002001280200210a0c010b200420096a22062004490d02200a41017422042006200420064b1b22044100480d0202400240200a0d002004102d210a0c010b2001280200200a20041031210a0b200a450d012001200a360200200141046a2004360200200141086a28020021040b200141086a2206200420096a360200200a20046a2003200910e8061a02402002280204450d002003102f0b200141046a2802002109200628020021040240024020002d0088024101460d000240024020092004460d00200128020021090c010b200441016a22092004490d042004410174220a2009200a20094b1b220a4100480d040240024020040d00200a102d21090c010b20012802002004200a103121090b2009450d0320012009360200200141046a200a360200200141086a28020021040b200141086a200441016a360200200920046a41003a00000c010b0240024020092004460d00200128020021090c010b200441016a22092004490d032004410174220a2009200a20094b1b220a4100480d030240024020040d00200a102d21090c010b20012802002004200a103121090b2009450d0220012009360200200141046a200a360200200141086a28020021040b200141086a220a200441016a360200200920046a41013a000002400240200141046a2802002209200a28020022046b4114490d00200128020021090c010b200441146a220a2004490d0320094101742204200a2004200a4b1b22044100480d030240024020090d002004102d21090c010b200128020020092004103121090b2009450d0220012009360200200141046a2004360200200141086a28020021040b200141086a200441146a360200200920046a220441106a20004199026a280000360000200441086a20004191026a290000370000200420004189026a2900003700000b2002200041c0016a10a7012002280200210302400240200141046a280200220a200141086a28020022046b20022802082209490d002001280200210a0c010b200420096a22062004490d02200a41017422042006200420064b1b22044100480d0202400240200a0d002004102d210a0c010b2001280200200a20041031210a0b200a450d012001200a360200200141046a2004360200200141086a28020021040b200141086a2206200420096a360200200a20046a2003200910e8061a02402002280204450d002003102f0b2002200041e4016a10a7012002280200210302400240200141046a280200220a200628020022046b20022802082209490d002001280200210a0c010b200420096a22062004490d02200a41017422042006200420064b1b22044100480d0202400240200a0d002004102d210a0c010b2001280200200a20041031210a0b200a450d012001200a360200200141046a2004360200200141086a28020021040b200141086a200420096a360200200a20046a2003200910e8061a02402002280204450d002003102f0b200241106a24000f0b1036000b1038000bce0201047f230041106b2202240002400240024002400240024002400240024020012d00000e06010203040500010b200241003a000a20024181ca003b01082002200141216a3602042002200141016a3602000c050b410110332201450d062000428180808010370204200020013602000c050b2001410c6a2802002203412020034120491b220441016a2203102d2205450d0520052003200310e706220541016a200141046a280200200410e8061a2000200336020820002003360204200020053602000c040b200241003a000a20024181c4003b01082002200141216a3602042002200141016a3602000c020b200241003a000a20024181c6003b01082002200141216a3602042002200141016a3602000c010b200241003a000a20024181c8003b01082002200141216a3602042002200141016a3602000b2000200210b0060b200241106a24000f0b1036000bec12010b7f23004180016b22022400200241003a004002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802002203280204220420044100472205490d00200241c0006a20032802002206200510e8061a2003200420056b3602042003200620056a360200024020040d00410021062002410d6a2107200241106a2108200241246a21090c140b2002410d6a2107200241106a2108200241246a210920022d0040220a41254b0d0141002106200a0e261301010101010101010101010101010101010101010101010101010101010101010102030405130b200041063a00000c130b0240200a417f6a220441ff01714121490d00200041063a00000c130b024020040d00410121034100210441002105410121060c120b0240200410332203450d002003200128020022012802002001280204220a2004200a2004491b220510e806210b200128020422062005490d052001200620056b3602042001200128020020056a360200410121060240200a20044f0d00200b20056a22014100200b20046a20016b10e7061a0b200421050c120b1036000b200241003a00784100210402400340200241003a004020012802002205280204220320034100472206490d01200241c0006a2005280200220a200610e8061a2005200320066b3602042005200a20066a360200024002402003450d0020022d004021030c010b41002103200241003a00400b200241d8006a20046a20033a00002002200441016a22043a007820044120470d000b200241d6006a20022d005a3a0000200241c8006a200241ef006a290000370300200241d0006a200241f7006a2d00003a0000200220022f01583b0154200220022900673703404100210120022800632104200228005f2105200228005b21030c100b41012101200441ff01710d040c0e0b200241003a00784100210402400340200241003a004020012802002205280204220320034100472206490d01200241c0006a2005280200220a200610e8061a2005200320066b3602042005200a20066a360200024002402003450d0020022d004021030c010b41002103200241003a00400b200241d8006a20046a20033a00002002200441016a22043a007820044120470d000b200241d6006a20022d005a3a0000200241c8006a200241ef006a290000370300200241d0006a200241f7006a2d00003a0000200220022f01583b0154200220022900673703404100210120022800632104200228005f2105200228005b21030c0d0b41012101200441ff01710d040c0b0b200241003a00784100210402400340200241003a004020012802002205280204220320034100472206490d01200241c0006a2005280200220a200610e8061a2005200320066b3602042005200a20066a360200024002402003450d0020022d004021030c010b41002103200241003a00400b200241d8006a20046a20033a00002002200441016a22043a007820044120470d000b200241d6006a20022d005a3a0000200241c8006a200241ef006a290000370300200241d0006a200241f7006a2d00003a0000200220022f01583b0154200220022900673703404100210120022800632104200228005f2105200228005b21030c0a0b41012101200441ff01710d040c080b200241003a00784100210402400340200241003a004020012802002205280204220320034100472206490d01200241c0006a2005280200220a200610e8061a2005200320066b3602042005200a20066a360200024002402003450d0020022d004021030c010b41002103200241003a00400b200241d8006a20046a20033a00002002200441016a22043a007820044120470d000b200241d6006a20022d005a3a0000200241c8006a200241ef006a290000370300200241d0006a200241f7006a2d00003a0000200220022f01583b0154200220022900673703404100210120022800632104200228005f2105200228005b21030c070b41012101200441ff01710d040c050b20052006104b000b200241003a00780c090b200241003a00780c060b200241003a00780c030b200241003a00780b0b2002413c6a41026a2206200241d4006a41026a2d00003a0000200241286a41086a220a200241c0006a41086a290300370300200241286a41106a220b200241c0006a41106a2d00003a0000200220022f01543b013c20022002290340370328024020010d00200241246a41026a20062d00003a0000200241106a41086a200a290300370300200241106a41106a200b2d00003a0000200220022f013c3b012420022002290328370310410521060c070b200041063a00000c070b0b2002413c6a41026a2206200241d4006a41026a2d00003a0000200241286a41086a220a200241c0006a41086a290300370300200241286a41106a220b200241c0006a41106a2d00003a0000200220022f01543b013c20022002290340370328024020010d00200241246a41026a20062d00003a0000200241106a41086a200a290300370300200241106a41106a200b2d00003a0000200220022f013c3b012420022002290328370310410421060c050b200041063a00000c050b0b2002413c6a41026a2206200241d4006a41026a2d00003a0000200241286a41086a220a200241c0006a41086a290300370300200241286a41106a220b200241c0006a41106a2d00003a0000200220022f01543b013c20022002290340370328024020010d00200241246a41026a20062d00003a0000200241106a41086a200a290300370300200241106a41106a200b2d00003a0000200220022f013c3b012420022002290328370310410321060c030b200041063a00000c030b0b410221062002413c6a41026a220a200241d4006a41026a2d00003a0000200241286a41086a220b200241c0006a41086a290300370300200241286a41106a220c200241c0006a41106a2d00003a0000200220022f01543b013c20022002290340370328024020010d00200241246a41026a200a2d00003a0000200241106a41086a200b290300370300200241106a41106a200c2d00003a0000200220022f013c3b0124200220022903283703100c010b200041063a00000c010b200020063a0000200020092f00003b00012000410c6a2004360000200041086a2005360000200041046a2003360000200041106a2008290000370000200041216a20072f00003b0000200041036a200941026a2d00003a0000200041186a200841086a290000370000200041206a200841106a2d00003a0000200041236a200741026a2d00003a00000b20024180016a24000b8111010a7f23004180016b2202240002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a22063602042001200441016a2207360200200541254b0d014100210820050e261301010101010101010101010101010101010101010101010101010101010101010102030405130b200041063a00000c130b02402005417f6a41ff01714121490d00200041063a00000c130b02402005417f6a22090d0020012006360204200120073602004101210a410021094100210b410121080c120b0240024020091033220a450d0020012802042009490d01200a2001280200200910e8061a200128020422052009490d062001200520096b3602042001200128020020096a360200410121082009210b0c130b1036000b200041063a0000200a102f0c120b41002105200241003a00782003417f6a210a2003417e6a210302400340200a2005460d01200241d8006a20056a200420056a220941016a2d00003a0000200120033602042001200941026a3602002002200541016a22093a00782003417f6a21032009210520094120470d000b200241d6006a20022d005a3a0000200241c8006a200241ef006a290000370300200241d0006a200241f7006a2d00003a0000200220022f01583b0154200220022900673703404100210120022800632109200228005f210b200228005b210a0c100b41012101200541ff01710d040c0e0b41002105200241003a00782003417f6a210a2003417e6a210302400340200a2005460d01200241d8006a20056a200420056a220941016a2d00003a0000200120033602042001200941026a3602002002200541016a22093a00782003417f6a21032009210520094120470d000b200241d6006a20022d005a3a0000200241c8006a200241ef006a290000370300200241d0006a200241f7006a2d00003a0000200220022f01583b0154200220022900673703404100210120022800632109200228005f210b200228005b210a0c0d0b41012101200541ff01710d040c0b0b41002105200241003a00782003417f6a210a2003417e6a210302400340200a2005460d01200241d8006a20056a200420056a220941016a2d00003a0000200120033602042001200941026a3602002002200541016a22093a00782003417f6a21032009210520094120470d000b200241d6006a20022d005a3a0000200241c8006a200241ef006a290000370300200241d0006a200241f7006a2d00003a0000200220022f01583b0154200220022900673703404100210120022800632109200228005f210b200228005b210a0c0a0b41012101200541ff01710d040c080b41002105200241003a00782003417f6a210a2003417e6a210302400340200a2005460d01200241d8006a20056a200420056a220941016a2d00003a0000200120033602042001200941026a3602002002200541016a22093a00782003417f6a21032009210520094120470d000b200241d6006a20022d005a3a0000200241c8006a200241ef006a290000370300200241d0006a200241f7006a2d00003a0000200220022f01583b0154200220022900673703404100210120022800632109200228005f210b200228005b210a0c070b41012101200541ff01710d040c050b20092005104b000b200241003a00780c090b200241003a00780c060b200241003a00780c030b200241003a00780b0b2002413c6a41026a2205200241d4006a41026a2d00003a0000200241286a41086a2204200241c0006a41086a290300370300200241286a41106a2203200241c0006a41106a2d00003a0000200220022f01543b013c20022002290340370328024020010d00200241246a41026a20052d00003a0000200241106a41086a2004290300370300200241106a41106a20032d00003a0000200220022f013c3b012420022002290328370310410521080c070b200041063a00000c070b0b2002413c6a41026a2205200241d4006a41026a2d00003a0000200241286a41086a2204200241c0006a41086a290300370300200241286a41106a2203200241c0006a41106a2d00003a0000200220022f01543b013c20022002290340370328024020010d00200241246a41026a20052d00003a0000200241106a41086a2004290300370300200241106a41106a20032d00003a0000200220022f013c3b012420022002290328370310410421080c050b200041063a00000c050b0b2002413c6a41026a2205200241d4006a41026a2d00003a0000200241286a41086a2204200241c0006a41086a290300370300200241286a41106a2203200241c0006a41106a2d00003a0000200220022f01543b013c20022002290340370328024020010d00200241246a41026a20052d00003a0000200241106a41086a2004290300370300200241106a41106a20032d00003a0000200220022f013c3b012420022002290328370310410321080c030b200041063a00000c030b0b410221082002413c6a41026a2205200241d4006a41026a2d00003a0000200241286a41086a2204200241c0006a41086a290300370300200241286a41106a2203200241c0006a41106a2d00003a0000200220022f01543b013c20022002290340370328024020010d00200241246a41026a20052d00003a0000200241106a41086a2004290300370300200241106a41106a20032d00003a0000200220022f013c3b0124200220022903283703100c010b200041063a00000c010b200020083a0000200020022f01243b00012000410c6a2009360000200041086a200b360000200041046a200a360000200041106a2002290310370000200041216a20022f000d3b0000200041036a200241246a41026a2d00003a0000200041186a200241106a41086a290300370000200041206a200241106a41106a2d00003a0000200041236a2002410d6a41026a2d00003a00000b20024180016a24000b830301067f230041106b2203240002400240024020014105744104722204417f4c0d002004102d2205450d012003410036020820032004360204200320053602002001200310690240024020010d002003280208210520032802042106200328020021070c010b20014105742108200328020021072003280204210420032802082101034002400240200420016b4120490d00200141206a2105200421060c010b200141206a22052001490d05200441017422062005200620054b1b22064100480d050240024020040d002006102d21070c010b200720042006103121070b2007450d040b200720016a22012000290000370000200141186a200041186a290000370000200141106a200041106a290000370000200141086a200041086a2900003700002006210420052101200041206a2100200841606a22080d000b2003200636020420032005360208200320073602000b20022902002005ad4220862007ad84100402402006450d002007102f0b200341106a24000f0b103d000b1036000b1038000b830402067f027e230041106b22032400024002400240200141306c4104722204417f4c0d002004102d2205450d012003410036020820032004360204200320053602002001200310690240024020010d002003280208210120032802042106200328020021050c010b2000200141306c6a2107200328020021052003280204210620032802082101034002400240200620016b4120490d00200141206a2104200621080c010b200141206a22042001490d05200641017422082004200820044b1b22084100480d050240024020060d002008102d21050c010b200520062008103121050b2005450d040b200520016a22012000290000370000200141186a200041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200041286a2903002109200041206a290300210a02400240200820046b4110490d00200441106a2101200821060c010b200441106a22012004490d05200841017422062001200620014b1b22064100480d050240024020080d002006102d21050c010b200520082006103121050b2005450d040b200520046a220420093700082004200a3700002007200041306a2200470d000b2003200636020420032001360208200320053602000b20022902002001ad4220862005ad84100402402006450d002005102f0b200341106a24000f0b103d000b1036000b1038000be10302087f027e230041106b22022400200241003602082002420137030020002802102103200041186a2802002204200210690240024002402004450d00200320044105746a21050340200328020021060240024020022802042207200228020822046b4104490d00200228020021070c010b200441046a22082004490d04200741017422092008200920084b1b22084100480d040240024020070d002008102d21070c010b200228020020072008103121070b2007450d0320022008360204200220073602000b2002200441046a360208200720046a2006360000200341086a200210a5012005200341206a2203470d000b0b200041086a290300210a2000290300210b0240024020022802042207200228020822036b4110490d00200341106a2104200228020021070c010b200341106a22042003490d02200741017422062004200620044b1b22064100480d020240024020070d002006102d21070c010b200228020020072006103121070b2007450d0120022006360204200220073602000b200720036a2203200a3700082003200b370000200220043602082000411c6a200210a601200228020421032001290200200235020842208620022802002204ad84100402402003450d002004102f0b200241106a24000f0b1036000b1038000b830301067f230041106b2203240002400240024020014105744104722204417f4c0d002004102d2205450d012003410036020820032004360204200320053602002001200310690240024020010d002003280208210520032802042106200328020021070c010b20014105742108200328020021072003280204210420032802082101034002400240200420016b4120490d00200141206a2105200421060c010b200141206a22052001490d05200441017422062005200620054b1b22064100480d050240024020040d002006102d21070c010b200720042006103121070b2007450d040b200720016a22012000290000370000200141186a200041186a290000370000200141106a200041106a290000370000200141086a200041086a2900003700002006210420052101200041206a2100200841606a22080d000b2003200636020420032005360208200320073602000b20022902002005ad4220862007ad84100402402006450d002007102f0b200341106a24000f0b103d000b1036000b1038000bf90e09017f017e017f017e017f017e037f027e037f23004190026b2202240041adc5c300ad4280808080f000842203100122042900002105200241e8006a41086a200441086a290000370300200220053703682004102f2003100122042900002103200241c8006a41086a200441086a290000370300200220033703482004102f024002404120102d2204450d0020042001290000370000200441186a200141186a290000370000200441106a200141106a290000370000200441086a200141086a2900003700002004ad4280808080800484100322062900002103200641086a2900002105200641106a2900002107200241f8006a41186a2208200641186a290000370300200241f8006a41106a22092007370300200241f8006a41086a2005370300200220033703782006102f2004102f41c000102d2204450d00200420022903683700002004200229034837001020042002290378370020200441086a200241e8006a41086a220a290300370000200441186a200241c8006a41086a290300370000200441286a200241f8006a41086a290300370000200441306a2009290300370000200441386a2008290300370000200241c0003602fc01200220043602f801200241e8006a2004ad42808080808008841002107302400240200228026822060d00420021030c010b200228026c2109024002400240200a28020022084110490d0020084170714110460d002008417c714120470d010b20024100360250200242013703482002410b360284022002200241f8016a360280022002200241c8006a36028c022002418c016a41013602002002420137027c200241b885c700360278200220024180026a360288012002418c026a41d8dbc100200241f8006a103c1a200235025042208620023502488410080240200228024c450d002002280248102f0b420021030c010b200641086a290000210b20062900002107200641186a290000210c2006290010210520062800202108420121030b2009450d002006102f0b2004102f0240024002402003500d00200241f8006a41186a4200370300200241f8006a41106a220a4200370300200241f8006a41086a2204420037030020024200370378418de6c300ad4280808080e000841001220629000021032004200641086a290000370300200220033703782006102f419ce6c300ad4280808080e00084100122062900002103200241e8006a41086a2209200641086a290000370300200220033703682006102f200a20022903682203370300200241c8006a41086a220a2004290300370300200241c8006a41106a2003370300200241c8006a41186a200929030037030020022002290378370348200241306a200241c8006a4120109501200241106a200c420041002002280234410020022802301b220420086b2206200620044b1bad2203420010ed06200241206a200342002005420010ed062002420042002005420010ed062002290308200229031884420052200241206a41086a2903002203200229030020022903107c7c2205200354720d0142002007200229032022037d220c200c200756200b20057d2007200354ad7d2203200b562003200b511b22041b22054200200320041b220384500d01200242f6cacda397cddbb320370340200241c0006a200120052003410610b001200241b0016a2003370300200241a8016a2005370300200241f8006a41086a41003a000020024181016a200129000037000020024189016a200141086a29000037000020024191016a200141106a29000037000020024199016a200141186a290000370000200241143a0078200241f8006a21040c020b2000411b3b0001200041086a410a360200200041046a41eaf0c000360200410321040c030b200242f6cacda397cddbb320370338200241386a200110b10141adc5c300ad4280808080f0008422031001220429000021052009200441086a290000370300200220053703682004102f2003100122042900002103200a200441086a290000370300200220033703482004102f4120102d2204450d0120042001290000370000200441186a200141186a2209290000370000200441106a200141106a220a290000370000200441086a200141086a220d2900003700002004ad4280808080800484100322062900002103200641086a2900002105200641106a2900002107200241f8006a41186a220e200641186a290000370300200241f8006a41106a220f2007370300200241f8006a41086a22082005370300200220033703782006102f2004102f41c000102d2204450d01200420022903683700002004200229034837001020042002290378370020200441086a200241e8006a41086a290300370000200441186a200241c8006a41086a290300370000200441286a2008290300370000200441306a200f290300370000200441386a200e2903003700002004ad428080808080088410052004102f200841013a000020024181016a200129000037000020024189016a200d29000037000020024191016a200a29000037000020024199016a2009290000370000200241143a0078200241f8006a21040b41c8e1ca0041002004108c01410421040c010b1036000b200020043a000020024190026a24000bbd0101047f230041106b2202240020002802042103200028020021004101210420012802184199a5c00041012001411c6a28020028020c1100002105200241003a0005200220053a00042002200136020002402003450d0003402002200036020c20022002410c6a4190ebc30010621a200041016a21002003417f6a22030d000b20022d000421050b0240200541ff01710d00200228020022002802184198a5c00041012000411c6a28020028020c11000021040b200241106a240020040bfe0e03037f017e0e7f230022052106200541e0016b416071220524000240024002402002200384500d00200441ff01712207450d002000290000210841002109024020074101460d004102410120044101711b21090b20052002370300200520093a00182005200837031020052003370308200541c0016a200110ff0420052802c001210a20052802c401210b02400240024020052802c801220c450d00200a200c41057422046a210d200441606a210e200541a0016a411072210f200541a0016a4119722110200a21040340200541e8006a41106a2211200441106a290300370300200541e8006a41086a2212200441086a29030037030020052004290300370368200441186a2d000021072005200441196a28000036023820052004411c6a28000036003b20074103460d0120102005280238360000201041036a200528003b360000200520112903003703b001200520122903003703a801200520052903683703a001200520073a00b80102400240200f2000460d00200f2900002000290000510d00200520052903b801220237039801200520052903b00137039001200520052903a80137038801200520052903a001370380010c010b200541033a00d80120052005290318220237039801200520052903103703900120052005290308370388012005200529030037038001200520052903d001370310200520052903c801370308200520052903c001370300200520052903d80122033703182003a721090b2002a7220741ff01714103470d02200e41606a210e200441206a2204200d470d000b0b41082111410021100240200b450d00200a102f0b410021130c010b200541d0006a41106a2210200529039001370300200541d0006a41086a22122005290388013703002005200528009c0136004320052005280099013602402005200529038001370350200520052802403602482005200528004336004b4120102d2211450d0220112005290350370300201120073a0018201120052802483600192011411c6a200528004b360000201141106a2010290300370300201141086a201229030037030002400240200e0d0041012110410121130c010b200441206a2112200c410574200a6a41606a211420054180016a4119722115200541a0016a411072210c200541a0016a411972210e41012110410121130340201221040340200541e8006a41106a2212200441106a290300370300200541e8006a41086a220f200441086a29030037030020052004290300370368200441186a2d000021072005200441196a28000036023820052004411c6a28000036003b20074103460d02200e2005280238360000200e41036a200528003b360000200520122903003703b0012005200f2903003703a801200520052903683703a001200520073a00b80102400240200c2000460d00200c2900002000290000510d00200520052903b801220237039801200520052903b00137039001200520052903a80137038801200520052903a001370380010c010b200541033a00d80120052005290318220237039801200520052903103703900120052005290308370388012005200529030037038001200520052903d001370310200520052903c801370308200520052903c001370300200520052903d80122033703182003a721090b02402002a7220741ff01714103470d00200441206a2204200d470d010c030b0b200541d0006a41106a2212200529039001370300200541d0006a41086a220f200529038801370300200520152800003602402005201541036a2800003600432005200529038001370350200520052802403602482005200528004336004b200541c0016a41086a2216200f290300370300200541c0016a41106a220f2012290300370300200520052903503703c001200520052802483602a0012005200528004b3600a301024020132010470d00201041016a22122010490d06201041017422132012201320124b1b221241ffffff3f712012470d06201241057422124100480d060240024020100d002012102d21110c010b201120104105742012103121110b2011450d05201241057621130b200441206a211220162903002102200f290300210320052903c0012108201120104105746a220f20073a0018200f2008370300200f41106a2003370300200f41086a2002370300200f20052802a001360019200f411c6a20052800a301360000201041016a211020142004470d000b0b200b450d00200a102f0b0240200941ff01714103460d00200541c0016a41186a22072005290318370300200541c0016a41106a22002005290310370300200541c0016a41086a220e2005290308370300200520052903003703c001024020102013470d00201041016a22042010490d04201041017422122004201220044b1b220441ffffff3f712004470d04200441057422044100480d040240024020100d002004102d21110c010b201120104105742004103121110b2011450d03200441057621130b201120104105746a220420052903c001370300200441186a2007290300370300200441106a2000290300370300200441086a200e290300370300201041016a21100b2001201120101080052013450d002011102f0b200624000f0b1036000b1038000ba60304107f027e017f017e230041306b220224002002200110ff042002280200210302400240200228020822040d00410021040c010b200041706a210541002106200321074100210802400240034002400240024020052007460d00200741106a22092900002000290000510d0020060d01410021060c020b200641016a21060c010b200820066b220a20044f0d02200241106a41186a220b200720064105746b220a41186a220c290300370300200241106a41106a220d200a41106a220e290300370300200241106a41086a220f200a41086a22102903003703002002200a290300370310200741086a2211290300211220092903002113200741186a22142903002115200a2007290300370300200c2015370300200e2013370300201020123703002014200b2903003703002009200d2903003703002011200f290300370300200720022903103703000b200741206a21072004200841016a2208460d020c000b0b4188bbca00200a2004103b000b2006417f6a20044f0d002002200420066b22043602080b20012003200410800502402002280204450d002003102f0b200241306a24000be7d70106037f017e147f057e067f037e230041b0116b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e0c000102030405060708090a0b000b200341840f6a4101360200200342013702f40e200341b4d8c9003602f00e200341043602ec09200341fcdbc9003602e8092003200341e8096a3602800f200341f00e6a41e8d8c9001043000b200241036a2d0000210420022f00012105200141196a2900002106200141186a2d00002107200141176a2d00002108200141156a2f00002109200141146a2d0000210a200141136a2d0000210b200141116a2f0000210c200141106a2d0000210d2001410f6a2d0000210e2001410d6a2f0000210f2001410c6a2d000021102001410b6a2d00002111200141096a2f00002112200141086a2d00002113200141076a2d00002114200141056a2f00002115200141046a2d00002116200141036a2d0000211720012f0001211802400240024020022d00002219417f6a221a41024b0d000240201a0e03000102000b200241086a2802004101742002410c6a2802004d0d00200241046a28020041ff0171450d010b200520044110747220194100477241ff01710d010b41a4e3c400ad4280808080c0008410012202290000211b2002290008211c2002102f4188bec100ad4280808080a0018410012202290000211d2002290008211e2002102f2003201e3703a8032003201d3703a0032003201c370398032003201b37039003200341f00e6a20034190036a10b301024020032802f00e221a0d004200211b4108211a410021020c1d0b20032902f40e221b422088221ca72202201ba7460d1c201ca721040c200b200041023a00004101211a0c200b200341286a200141046a41a00210e8061a024002400240024020022d00000d0020022d00014101470d00200241196a2d0000211a200241186a2d00002104200241166a2f01002107200241156a2d00002108200241146a2d00002109200241126a2f0100210a200241116a2d0000210b200241106a2d0000210c2002410e6a2f0100210d2002410d6a2d0000210e2002410c6a2d0000210f2002410a6a2f01002110200241096a2d00002111200241086a2d00002112200241066a2f01002113200241056a2d00002114200241046a2d00002115200241026a2f0100211620032002411a6a2901003703d0052003201a3a00cf05200320043a00ce05200320073b01cc05200320083a00cb05200320093a00ca052003200a3b01c8052003200b3a00c7052003200c3a00c6052003200d3b01c4052003200e3a00c3052003200f3a00c205200320103b01c005200320113a00bf05200320123a00be05200320133b01bc05200320143a00bb05200320153a00ba05200320163b01b80502402003280230220241e4004b0d0020032002ad42004280c0c6c9faeb38420010ed0641a4e3c400ad4280808080c0008410012202290000211b200341a80c6a41086a200241086a2900003703002003201b3703a80c2002102f41e8bcc100ad4280808080a0018410012202290000211b200341d00e6a41086a200241086a2900003703002003201b3703d00e2002102f200341086a290300211f4120102d2202450d262003290300211e200220032903b805370000200241186a200341b8056a41186a290300370000200241106a200341b8056a41106a290300370000200241086a200341b8056a41086a2903003700002002ad42808080808004841003221a290000211b201a41086a2900002106201a41106a290000211c20034190036a41186a2204201a41186a29000037030020034190036a41106a2207201c37030020034190036a41086a20063703002003201b37039003201a102f2002102f41c000102d221a450d26201a20032903a80c370000201a41086a200341a80c6a41086a290300370000201a20032903d00e370010201a41186a200341d00e6a41086a290300370000201a200329039003370020201a41286a20034190036a41086a290300370000201a41306a2007290300370000201a41386a2004290300370000200341f00e6a201a10b401200341f00e6a41086a290300211b20032903f00e210620032802800f210220032802840f210420032802880f210920034190036a200341f00e6a411c6a220741880210e8061a200341f0026a41086a22082003419d116a220a290000370300200341f0026a41106a200341a5116a220b290000370300200341f0026a41176a220c200341ac116a220d28000036000020032003290095113703f00220032d009411220e4102460d03200341c80c6a20034190036a41880210e8061a200341c8026a41176a220f200c280000360000200341c8026a41106a220c200341f0026a41106a290300370300200341c8026a41086a22102008290300370300200320032903f0023703c802201a102f200341f00e6a41186a2009360200200341840f6a20043602002003201b3703f80e200320063703f00e200320023602800f2007200341c80c6a41880210e806211220034194116a200e3a000020034195116a20032903c802370000200a2010290300370000200b200c290300370000200d200f28000036000002402009450d004100211a410021040340024002400240200241086a2208280200417f6a220741054b0d00024020070e06000101010100000b201a0d014100211a0c020b201a41016a211a0c010b2004201a6b220720094f0d12200341c0076a41186a220a2002201a4105746b220741186a220b290300370300200341c0076a41106a220c200741106a220d290300370300200341c0076a41086a220e200741086a220f290300370300200320072903003703c0072008290300211b200241106a22102903002106200241186a2211290300211c20072002290300370300200b201c370300200d2006370300200f201b3703002011200a2903003703002010200c2903003703002008200e290300370300200220032903c0073703000b200241206a21022009200441016a2204470d000b201a417f6a20094f0d0020032009201a6b3602880f0b201210a4012012200341286a41a00210e8061a200341e8096a200341f00e6a41c00210e8061a200341f0096a290300210620032903e809211d0c040b20004183303b0100200041086a410d360200200041046a418bf4c000360200200041026a410b3a00000c010b200041023a00000b200341286a10a4010c1b0b201a102f200341800a6a41003602004200211d200342003703f009200342003703e809200342083703f809200341e8096a411c6a200341286a41a00210e8061a420021060b2003201e4280809aa6eaafe3017c221b3703e8092003201f201b201e54ad7c221c3703f009201b201d56201c200656201c20065122021b0d170c180b2001410c6a2802002104200141086a2802002114200141046a28020021092002411a6a290100211b200241196a2d00002107200241186a2d00002108200241166a2f0100210a200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002115200241086a2d00002116200241066a2f01002117200241056a2d00002118200241046a2d00002105200241026a2f010021194101211a024020022d00000d0020022d0001410147211a0b2003201b3703a803200320073a00a703200320083a00a6032003200a3b01a4032003200b3a00a3032003200c3a00a2032003200d3b01a0032003200e3a009f032003200f3a009e03200320103b019c03200320113a009b03200320123a009a03200320133b019803200320153a009703200320163a009603200320173b019403200320183a009303200320053a009203200320193b019003024002400240201a0d00200341b8056a41186a220720034190036a41186a290300370300200341b8056a41106a220820034190036a41106a290300370300200341b8056a41086a220a20034190036a41086a221a29030037030020032003290390033703b80541a4e3c400ad4280808080c0008410012202290000211b201a200241086a2900003703002003201b370390032002102f41e8bcc100ad4280808080a0018410012202290008211b20022d0007210b20022d0006210c20022f0004210d20022d0003210e20022d0002210f20022f000021102002102f4120102d221a450d23201a20032903b805370000201a41186a2007290300370000201a41106a2008290300370000201a41086a200a290300370000201aad428080808080048410032202290018210620022d0017210720022d0016210820022f0014210a20022d0013211120022d0012211220022f0010211320022d000f211520022d000e211620022f000c211720022d000b211820022d000a210520022f0008211920022d0007212020022d0006212120022f0004212220022d0003212320022d0002212420022f000021252002102f201a102f41c000102d2202450d23200220032903900337000020022006370038200220073a0037200220083a00362002200a3b0034200220113a0033200220123a0032200220133b0030200220153a002f200220163a002e200220173b002c200220183a002b200220053a002a200220193b0028200220203a0027200220213a0026200220223b0024200220233a0023200220243a0022200220253b00202002201b3700182002200b3a00172002200c3a00162002200d3b00142002200e3a00132002200f3a0012200220103b0010200241086a20034190036a41086a290300370000200341206a200241c00041c8e1ca004100410010b5012003280220211a2002102f201a4101470d01200441e4004d0d0220004183303b0100200041086a4112360200200041046a418cf5c000360200200041026a41003a00000c180b200041023a00000c170b20004183303b0100200041086a4108360200200041046a4184f5c000360200200041026a41013a00000c160b41a4e3c400ad4280808080c0008410012202290000211b20034190036a41086a200241086a2900003703002003201b370390032002102f41d8bdc100ad4280808080e0008410012202290008211b20022d0007210720022d0006210820022f0004210a20022d0003210b20022d0002210c20022f0000210d2002102f4120102d221a450d20201a20032903b805370000201a41186a200341b8056a41186a290300370000201a41106a200341b8056a41106a290300370000201a41086a200341b8056a41086a290300370000201aad428080808080048410032202290018210620022d0017210e20022d0016210f20022f0014211020022d0013211120022d0012211220022f0010211320022d000f211520022d000e211620022f000c211720022d000b211820022d000a210520022f0008211920022d0007212020022d0006212120022f0004212220022d0003212320022d0002212420022f000021252002102f201a102f41c000102d2202450d20200341106a2004ad4200428080d287e2bc2d420010ed062002200329039003370000200220063700382002200e3a00372002200f3a0036200220103b0034200220113a0033200220123a0032200220133b0030200220153a002f200220163a002e200220173b002c200220183a002b200220053a002a200220193b0028200220203a0027200220213a0026200220223b0024200220233a0023200220243a0022200220253b00202002201b370018200220073a0017200220083a00162002200a3b00142002200b3a00132002200c3a00122002200d3b0010200241086a20034190036a41086a290300370000200341f00e6a200210b601200341f00e6a41086a290300211b20032902840f210620032903f00e211c20032802800f211a2002102f20064200201a1b2126201a4101201a1b21200240201c4200201a1b220620032903102227542207201b4200201a1b221b200341106a41086a290300222854201b20285122021b450d0020032028201b7d2027200654ad7d221c3703302003202720067d221d3703282003200341b8056a3602c0074104211a0240201d201c84500d002003200341b8056a3602c80c2003200341c80c6a3602f80e2003200341c0076a3602f40e2003200341286a3602f00e200341e8096a200341b8056a200341f00e6a109401024020032802e8094101470d00200320032900ed093703f00e2003200341f4096a2800003600f70e20032d00ec09211a0c010b4104211a200341e8096a41086a2903004201520d00200341e8096a41106a290300211c20032802c80c2108200341a80f6a200341e8096a41186a290300370300200341a00f6a201c370300200341f00e6a41086a41003a0000200341f90e6a2008290000370000200341810f6a200841086a290000370000200341890f6a200841106a290000370000200341910f6a200841186a290000370000200341033a00f00e41c8e1ca004100200341f00e6a108c010b200320032903f00e37039003200320032800f70e36009703201a41ff01714104460d002000201a3a00002000200329039003370001200041086a2003280097033600002026a7450d162020102f0c160b02402006202758201b20285820021b0d002003201b20287d2007ad7d221b3703302003200620277d22063703282006201b84500d002003200341b8056a3602c80c200341e8096a200341b8056a200341286a200341c80c6a10960120032903e8094201520d0020032903f009211b200341a80f6a200341e8096a41106a290300370300200341a00f6a201b370300200341f00e6a41086a41003a0000200341f90e6a20032903b805370000200341810f6a200341b8056a41086a290300370000200341890f6a200341b8056a41106a290300370000200341910f6a200341d0056a290300370000200341033a00f00e41c8e1ca004100200341f00e6a108c010b02402026422088a72202450d002002410574211a202021020340200210b701200241206a2102201a41606a221a0d000b0b4100211302400240200441c4006c22020d0041012119410021210c010b200241c4006d221a41ffffff3f71201a470d1b201a410574221a4100480d1b201a102d2219450d21201a41057621210b0240200920026a22222009460d00200441c4006c2118200341f00e6a41206a2105200341f00e6a41216a2107200341e8096a411f6a211541a4e3c400ad4280808080c00084211e41a9f6c000ad4280808080f00084211f4100210b201921044100211302400340200341c0076a41186a221a2009200b6a220241186a290200370300200341c0076a41106a2208200241106a290200370300200341c0076a41086a220a200241086a290200370300200341e8096a41086a220f200241296a290000370300200341e8096a41106a2210200241316a290000370300200341e8096a41186a2211200241396a2900003703002015200241c0006a280000360000200320022902003703c0072003200241216a2900003703e809200241206a2d000022124106460d01200341c80c6a41186a220c201a290300370300200341c80c6a41106a220d2008290300370300200341c80c6a41086a220e200a290300370300200320032903c0073703c80c200341f00e6a41186a2208200341b8056a41186a290300370300200341f00e6a41106a220a200341b8056a41106a290300370300200341f00e6a41086a2216200341b8056a41086a290300370300200320032903b8053703f00e200320123a00900f200720032903e809370000200741086a200f290300370000200741106a2010290300370000200741186a20112903003700002007411f6a2015280000360000201e10012202290000211b200341c8026a41086a2212200241086a2900003703002003201b3703c8022002102f201f10012202290000211b20034190036a41086a2217200241086a2900003703002003201b370390032002102f4120102d2202450d23200220032903c80c370000200241186a200c290300370000200241106a200d290300370000200241086a200e2903003700002002ad42808080808004841003221a290000211b201a41086a2900002106201a41106a290000211c200341286a41186a220f201a41186a290000370300200341286a41106a2210201c370300200341286a41086a221120063703002003201b370328201a102f2002102f41c000102d2202450d23200220032903c802370000200220032903900337001020022003290328370020200241086a2012290300370000200241186a2017290300370000200241286a2011290300370000200241306a2010290300370000200241386a200f2903003700004120102d221a450d23201a20032903f00e370000201a41186a2008290300370000201a41106a200a290300370000201a41086a2016290300370000200341286a200510a7012003280228211202400240200328023022080d00200841206a210a0c010b200841206a220a2008490d1e200a41c000200a41c0004b1b22164100480d1e201a412020161031221a450d240b201a41206a2012200810e8061a0240200328022c450d002012102f0b2002ad4280808080800884200aad422086201aad841004201a102f2002102f024020032d00900f4101470d0020032802980f450d0020032802940f102f0b2011200e290300221b3703002010200d2903002206370300200f200c290300221c370300200320032903c80c221d370328200441186a201c370000200441106a2006370000200441086a201b3700002004201d370000201341016a2113200441206a21042018200b41c4006a220b470d000c020b0b200241c4006a2022460d00200241e4006a21022018200b6b41bc7f6a211a0340024020022d00004101470d00200241086a280200450d00200241046a280200102f0b200241c4006a2102201a41bc7f6a221a0d000b0b02402014450d002009102f0b0240024002402013450d00200341f00e6a41186a2013360200200341840f6a2021360200200320273703f00e200320193602800f200320283703f80e41a4e3c400ad4280808080c0008410012202290000211b20034190036a41086a200241086a2900003703002003201b370390032002102f41d8bdc100ad4280808080e0008410012202290008211b20022d0007210420022d0006210720022f0004210820022d0003210920022d0002210a20022f0000210b2002102f4120102d221a450d23201a20032903b805370000201a41186a200341b8056a41186a290300370000201a41106a200341b8056a41106a290300370000201a41086a200341b8056a41086a290300370000201aad428080808080048410032202290018210620022d0017210c20022d0016210d20022f0014210e20022d0013210f20022d0012211020022f0010211120022d000f211220022d000e211320022f000c211420022d000b211520022d000a211620022f0008211720022d0007211820022d0006210520022f0004212220022d0003212320022d0002212420022f000021252002102f201a102f41c000102d2202450d232002200329039003370000200220063700382002200c3a00372002200d3a00362002200e3b00342002200f3a0033200220103a0032200220113b0030200220123a002f200220133a002e200220143b002c200220153a002b200220163a002a200220173b0028200220183a0027200220053a0026200220223b0024200220233a0023200220243a0022200220253b00202002201b370018200220043a0017200220073a0016200220083b0014200220093a00132002200a3a00122002200b3b0010200241086a20034190036a41086a290300370000200341c0003602ec09200320023602e809200341f00e6a200341e8096a10b8012002102f20210d010c020b41a4e3c400ad4280808080c0008410012202290000211b20034190036a41086a200241086a2900003703002003201b370390032002102f41d8bdc100ad4280808080e0008410012202290008211b20022d0007210420022d0006210720022f0004210820022d0003210920022d0002210a20022f0000210b2002102f4120102d221a450d22201a20032903b805370000201a41186a200341b8056a41186a290300370000201a41106a200341b8056a41106a290300370000201a41086a200341b8056a41086a290300370000201aad428080808080048410032202290018210620022d0017210c20022d0016210d20022f0014210e20022d0013210f20022d0012211020022f0010211120022d000f211220022d000e211320022f000c211420022d000b211520022d000a211620022f0008211720022d0007211820022d0006210520022f0004212220022d0003212320022d0002212420022f000021252002102f201a102f41c000102d2202450d222002200329039003370000200220063700382002200c3a00372002200d3a00362002200e3b00342002200f3a0033200220103a0032200220113b0030200220123a002f200220133a002e200220143b002c200220153a002b200220163a002a200220173b0028200220183a0027200220053a0026200220223b0024200220233a0023200220243a0022200220253b00202002201b370018200220043a0017200220073a0016200220083b0014200220093a00132002200a3a00122002200b3b0010200241086a20034190036a41086a2903003700002002ad428080808080088410052002102f2021450d010b2019102f0b02402026a7450d002020102f0b200041043a0000410021004101211a0c1f0b2002411a6a290100211b200241196a2d00002104200241186a2d00002107200241166a2f01002108200241156a2d00002109200241146a2d0000210a200241126a2f0100210b200241116a2d0000210c200241106a2d0000210d2002410e6a2f0100210e2002410d6a2d0000210f2002410c6a2d000021102002410a6a2f01002111200241096a2d00002112200241086a2d00002113200241066a2f01002114200241056a2d00002115200241046a2d00002116200241026a2f010021174101211a024020022d00000d0020022d0001410147211a0b2003201b3703a803200320043a00a703200320073a00a603200320083b01a403200320093a00a3032003200a3a00a2032003200b3b01a0032003200c3a009f032003200d3a009e032003200e3b019c032003200f3a009b03200320103a009a03200320113b019803200320123a009703200320133a009603200320143b019403200320153a009303200320163a009203200320173b0190030240201a0d00200341c8026a41186a220420034190036a41186a290300370300200341c8026a41106a220720034190036a41106a290300370300200341c8026a41086a220820034190036a41086a221a29030037030020032003290390033703c802200341f00e6a200341c8026a10b901200341f00e6a41086a290300211e200341f00e6a41186a2802002125200341840f6a280200210920032903f00e211f20032802800f212441a4e3c400ad4280808080c0008410012202290000211b201a200241086a2900003703002003201b370390032002102f41e8bcc100ad4280808080a0018410012202290008211b20022d0007210a20022d0006210b20022f0004210c20022d0003210d20022d0002210e20022f0000210f2002102f4120102d221a450d20201a20032903c802370000201a41186a2004290300370000201a41106a2007290300370000201a41086a2008290300370000201aad428080808080048410032202290018210620022d0017210420022d0016210720022f0014210820022d0013211020022d0012211120022f0010211220022d000f211320022d000e211420022f000c211520022d000b211620022d000a211720022f0008211820022d0007210520022d0006211920022f0004212020022d0003212120022d0002212220022f000021232002102f201a102f41c000102d2202450d20200220032903900337000020022006370038200220043a0037200220073a0036200220083b0034200220103a0033200220113a0032200220123b0030200220133a002f200220143a002e200220153b002c200220163a002b200220173a002a200220183b0028200220053a0027200220193a0026200220203b0024200220213a0023200220223a0022200220233b00202002201b3700182002200a3a00172002200b3a00162002200c3b00142002200d3a00132002200e3a00122002200f3b0010200241086a20034190036a41086a290300370000200341f00e6a200210b401024020032d009411220d410246221a0d002002ad428080808080088410050b200341f00e6a41086a290300211d20032903f00e211c20032802880f210420032802840f210820032802800f2107200341286a200341f00e6a411c6a41880210e8061a200341c8096a41176a220a200341f00e6a41bc026a280000360000200341c8096a41106a220b200341f00e6a41b5026a290000370300200341c8096a41086a220c200341f00e6a41ad026a29000037030020032003290095113703c80920034190036a200341286a41880210e8061a200341f0026a41176a220e200a280000360000200341f0026a41106a220a200b290300370300200341f0026a41086a200c290300370300200320032903c8093703f0020240201a0d00200341c0076a20034190036a41880210e8061a20034198056a41176a221a200e28000036000020034198056a41106a220b200a29030037030020034198056a41086a220a200341f0026a41086a290300370300200320032903f002370398052002102f200341b8056a200341c0076a41880210e8061a200341c80c6a200341b8056a41880210e8061a200341d00e6a41176a2202201a280000360000200341d00e6a41106a221a200b290300370300200341d00e6a41086a220b200a290300370300200341800a6a2004360200200341fc096a200836020020032003290398053703d00e2003201d3703f0092003201c3703e809200320073602f809200341e8096a411c6a200341c80c6a41880210e806210a2003418c0c6a200d3a00002003418d0c6a20032903d00e370000200341e8096a41ad026a200b290300370000200341e8096a41b5026a201a290300370000200341e8096a41bc026a2002280000360000024002402004410574221a0d004200211b420021060c010b200741106a21024200211b420021060340200241086a2903004200200241786a29030042015122041b20067c2002290300420020041b2206201b7c221b200654ad7c2106200241206a2102201a41606a221a0d000b0b201d201e7c201c201f7c221d201c54ad7c20067c2106201d201b7c221b201d54ad211c02402008450d002007102f0b2006201c7c2106200a10a40102402025450d002025410574211a202421020340200210b701200241206a2102201a41606a221a0d000b0b2003201b370328200320063703300240201b200684500d002003200341c8026a3602c80c200341e8096a200341c8026a200341286a200341c80c6a10960120032903e8094201520d0020032903f009211c200341a80f6a200341e8096a41106a290300370300200341a00f6a201c370300200341f00e6a41086a41003a0000200341f90e6a20032903c802370000200341810f6a200341c8026a41086a290300370000200341890f6a200341c8026a41106a290300370000200341910f6a200341e0026a290300370000200341033a00f00e41c8e1ca004100200341f00e6a108c010b200341a80f6a2006370300200341a00f6a201b3703004101211a200341f00e6a41086a41013a0000200341f90e6a20032903c802370000200341890f6a200341d8026a290300370000200341910f6a200341e0026a290300370000200341c8026a41086a290300211b200341113a00f00e200341f00e6a41116a201b37000041c8e1ca004100200341f00e6a108c0102402009450d002024102f0b200041043a00000c1f0b2002102f200041086a4108360200200041046a41fcf4c000360200200041026a41023a000020004183303b01002009450d142024102f0c140b200041023a00004101211a0c1d0b20022d00000d0820022d00014101470d08200141106a290300211e200141086a290300211f200141046a280200211a200241196a2d00002104200241186a2d00002107200241166a2f01002108200241156a2d00002109200241146a2d0000210a200241126a2f0100210b200241116a2d0000210c200241106a2d0000210d2002410e6a2f0100210e2002410d6a2d0000210f2002410c6a2d000021102002410a6a2f01002111200241096a2d00002112200241086a2d00002113200241066a2f01002114200241056a2d00002115200241046a2d00002116200241026a2f0100211720032002411a6a2901003703e00c200320043a00df0c200320073a00de0c200320083b01dc0c200320093a00db0c2003200a3a00da0c2003200b3b01d80c2003200c3a00d70c2003200d3a00d60c2003200e3b01d40c2003200f3a00d30c200320103a00d20c200320113b01d00c200320123a00cf0c200320133a00ce0c200320143b01cc0c200320153a00cb0c200320163a00ca0c200320173b01c80c41a4e3c400ad4280808080c0008410012202290000211b200229000821062002102f4188bec100ad4280808080a0018410012202290000211c2002290008211d2002102f2003201d3703800a2003201c3703f809200320063703f0092003201b3703e809200341f00e6a200341e8096a10b30120032802f00e2202410820021b210402400240201a20032902f40e420020021b221b422088a74f0d002004201a4106746a2202450d0020022903004201520d002004201a4106746a2208290308201f56200841106a2903002206201e562006201e511b450d0120004183303b0100200041086a410a360200200041046a41e8f4c000360200200041026a41043a00000c130b20004183303b0100200041086a410a360200200041046a41f2f4c000360200200041026a41033a00000c120b41a4e3c400ad4280808080c00084100122022900002106200341a80c6a41086a200241086a290000370300200320063703a80c2002102f41e8bcc100ad4280808080a00184100122022900002106200341d00e6a41086a200241086a290000370300200320063703d00e2002102f4120102d2202450d1e200220032903c80c370000200241186a200341c80c6a41186a290300370000200241106a200341c80c6a41106a290300370000200241086a200341c80c6a41086a2903003700002002ad4280808080800484100322072900002106200741086a290000211c200741106a290000211d20034190036a41186a2209200741186a29000037030020034190036a41106a220a201d37030020034190036a41086a220b201c37030020032006370390032007102f2002102f41c000102d2202450d1e200220032903a80c370000200241086a200341a80c6a41086a290300370000200220032903d00e370010200241186a200341d00e6a41086a2903003700002002200329039003370020200241286a200b290300370000200241306a200a290300370000200241386a2009290300370000200341f00e6a200210b401200341f00e6a41086a290300210620032903f00e211c20032802800f210a20032802840f210c20032802880f210b20034190036a200341f00e6a411c6a41880210e8061a200341f0026a41086a200341f00e6a41ad026a290000370300200341f0026a41106a200341f00e6a41b5026a290000370300200341f0026a41176a2207200341f00e6a41bc026a28000036000020032003290095113703f00202400240024002400240024020032d00941122094102460d00200341c0076a20034190036a41880210e8061a20034198056a41176a220d200728000036000020034198056a41106a2207200341f0026a41106a29030037030020034198056a41086a220e200341f0026a41086a290300370300200320032903f002370398052002102f200341b8056a200341c0076a41880210e8061a200341286a200341b8056a41880210e8061a200341c8026a41176a2202200d280000360000200341c8026a41106a220d2007290300370300200341c8026a41086a2207200e290300370300200341800a6a200b360200200341fc096a200c36020020032003290398053703c802200320063703f0092003201c3703e8092003200a3602f809200341e8096a411c6a200341286a41880210e806210e2003418c0c6a20093a00002003418d0c6a20032903c802370000200341e8096a41ad026a2007290300370000200341e8096a41b5026a200d290300370000200341e8096a41bc026a2002280000360000200841086a220d41086a2903002106200d290300211c41002102200b41014b0d01200b0e020302030b2002102f200041086a410a360200200041046a41def4c000360200200041026a41053a000020004183303b01000c160b200b2107034020022007410176220820026a2209200a20094105746a280200201a4b1b2102200720086b220741014b0d000b0b200a20024105746a22082802002207201a460d01200b20022007201a496a2202490d0c0b0240200b200c470d00200c41016a2207200c490d1b200c41017422082007200820074b1b220741ffffff3f712007470d1b200741057422074100480d1b02400240200c0d002007102d210a0c010b200a200c41057420071031210a0b200a450d212003200a3602f80920032007410576220c3602fc090b200a20024105746a220741206a2007200b20026b41057410e9061a200741186a2006370300200741106a201c370300200742013703082007201a3602002003200b41016a3602800a0c010b200b20024d0d0b0240200a20024105746a2202280208417f6a220741054b0d00024020070e06000101010100000b20004183303b0100200041086a410f360200200041046a41cff4c000360200200041026a41063a00000c120b200241086a42013703002008201a360200200241186a2006370300200241106a201c3703000b200d29030021062003200d41086a290300221c3703c807200320063703c0072003200341c80c6a3602c8024104210202402006201c84500d002003200341c80c6a3602b8052003200341b8056a3602f80e2003200341c8026a3602f40e2003200341c0076a3602f00e200341286a200341c80c6a200341f00e6a109401024020032802284101470d002003200329002d3703f00e2003200341346a2800003600f70e20032d002c21020c010b41042102200341286a41086a2903004201520d00200341286a41106a290300210620032802b8052107200341a80f6a200341286a41186a290300370300200341a00f6a2006370300200341f00e6a41086a41003a0000200341f90e6a2007290000370000200341810f6a200741086a290000370000200341890f6a200741106a290000370000200341910f6a200741186a290000370000200341033a00f00e41c8e1ca004100200341f00e6a108c010b200320032903f00e37039003200320032800f70e360097030240200241ff01714104470d00200341f00e6a200341e8096a41c00210e8061a41a4e3c400ad4280808080c0008410012202290000210620034190036a41086a200241086a29000037030020032006370390032002102f41e8bcc100ad4280808080a0018410012202290008210620022d0007210820022d0006210920022f0004210a20022d0003210b20022d0002210c20022f0000210d2002102f4120102d2207450d1f200720032903c80c370000200741186a200341c80c6a41186a290300370000200741106a200341c80c6a41106a290300370000200741086a200341c80c6a41086a2903003700002007ad428080808080048410032202290018211c20022d0017210e20022d0016210f20022f0014211020022d0013211120022d0012211220022f0010211320022d000f211420022d000e211520022f000c211620022d000b211720022d000a211820022f0008210520022d0007211920022d0006212020022f0004212120022d0003212220022d0002212320022f000021242002102f2007102f41c000102d2202450d1f20022003290390033700002002201c3700382002200e3a00372002200f3a0036200220103b0034200220113a0033200220123a0032200220133b0030200220143a002f200220153a002e200220163b002c200220173a002b200220183a002a200220053b0028200220193a0027200220203a0026200220213b0024200220223a0023200220233a0022200220243b002020022006370018200220083a0017200220093a00162002200a3b00142002200b3a00132002200c3a00122002200d3b0010200241086a20034190036a41086a290300370000200341c00036022c20032002360228200341f00e6a200341286a10ac012002102f0240200341840f6a280200450d0020032802800f102f0b2003418c0f6a10a401200341f00e6a41086a41033a0000200341f90e6a20032903c80c370000200341890f6a200341d80c6a290300370000200341910f6a200341e00c6a2903003700002003419c0f6a201a360200200341c80c6a41086a2903002106200341113a00f00e200341f00e6a41116a200637000041c8e1ca004100200341f00e6a108c010240201ba7450d002004102f0b200041043a00004101211a0c1d0b200020023a00002000200329039003370001200041086a2003280097033600000c100b0240024002400240024020022d00000d0020022d00014101470d00200141046a2802002109200241196a2d0000211a200241186a2d00002104200241166a2f01002107200241156a2d00002108200241146a2d0000210a200241126a2f0100210b200241116a2d0000210c200241106a2d0000210d2002410e6a2f0100210e2002410d6a2d0000210f2002410c6a2d000021102002410a6a2f01002111200241096a2d00002112200241086a2d00002113200241066a2f01002114200241056a2d00002115200241046a2d00002116200241026a2f0100211720032002411a6a2901003703e00c2003201a3a00df0c200320043a00de0c200320073b01dc0c200320083a00db0c2003200a3a00da0c2003200b3b01d80c2003200c3a00d70c2003200d3a00d60c2003200e3b01d40c2003200f3a00d30c200320103a00d20c200320113b01d00c200320123a00cf0c200320133a00ce0c200320143b01cc0c200320153a00cb0c200320163a00ca0c200320173b01c80c41a4e3c400ad4280808080c0008410012202290000211b200341a80c6a41086a200241086a2900003703002003201b3703a80c2002102f41e8bcc100ad4280808080a0018410012202290000211b200341d00e6a41086a200241086a2900003703002003201b3703d00e2002102f4120102d2202450d22200220032903c80c370000200241186a200341c80c6a41186a290300370000200241106a200341c80c6a41106a290300370000200241086a200341c80c6a41086a2903003700002002ad42808080808004841003221a290000211b201a41086a2900002106201a41106a290000211c20034190036a41186a2204201a41186a29000037030020034190036a41106a2207201c37030020034190036a41086a20063703002003201b37039003201a102f2002102f41c000102d2202450d22200220032903a80c3700004108210c200241086a200341a80c6a41086a290300370000200220032903d00e370010200241186a200341d00e6a41086a2903003700002002200329039003370020200241286a20034190036a41086a290300370000200241306a2007290300370000200241386a2004290300370000200341f00e6a200210b401200341f00e6a41086a290300211b20032903f00e210620032802800f210820032802840f210b20032802880f210a20034190036a200341f00e6a411c6a41880210e8061a200341f0026a41086a221a200341f00e6a41ad026a290000370300200341f0026a41106a200341f00e6a41b5026a290000370300200341f0026a41176a2204200341f00e6a41bc026a28000036000020032003290095113703f002024020032d00941122074102460d00200341c0076a20034190036a41880210e8061a20034198056a41176a220d200428000036000020034198056a41106a2204200341f0026a41106a29030037030020034198056a41086a220e201a290300370300200320032903f002370398052002102f200341b8056a200341c0076a41880210e8061a200341286a200341b8056a41880210e8061a200341c8026a41176a2202200d280000360000200341c8026a41106a221a2004290300370300200341c8026a41086a2204200e290300370300200341800a6a200a360200200341fc096a200b36020020032003290398053703c8022003201b3703f009200320063703e809200320083602f809200341e8096a411c6a200341286a41880210e806210f2003418c0c6a20073a00002003418d0c6a20032903c802370000200341e8096a41ad026a2004290300370000200341e8096a41b5026a201a290300370000200341e8096a41bc026a20022800003600004101210d4184f5c000210e41002102200a41014b0d02200a0e020403040b2002102f200041086a410a360200200041046a41def4c000360200200041026a41053a000020004183303b01004101211a0c200b200041023a00004101211a0c1f0b200a211a03402002201a410176220420026a2207200820074105746a28020020094b1b2102201a20046b221a41014b0d000b0b200820024105746a2802002009470d00200a20024d0d0c200820024105746a221a41186a290300211b201a41106a2903002106201a290308211c201a201a41206a2002417f73200a6a41057410e9061a2003200a417f6a3602800a201c4201510d01410e210c41c1f4c000210e4107210d0b20004183303b0100200041086a200c360200200041046a200e360200200041026a200d3a00000240200b450d002008102f0b200f10a4014101211a0c1c0b200320063703c0072003201b3703c80702402006201b84500d002003200341c80c6a3602b805200341286a200341c80c6a200341c0076a200341b8056a10960120032903284201520d002003290330211b200341a80f6a200341286a41106a290300370300200341a00f6a201b370300200341f00e6a41086a41003a0000200341f90e6a20032903c80c370000200341810f6a200341c80c6a41086a290300370000200341890f6a200341c80c6a41106a290300370000200341910f6a200341e00c6a290300370000200341033a00f00e41c8e1ca004100200341f00e6a108c010b200341f00e6a200341e8096a41c00210e8061a41a4e3c400ad4280808080c0008410012202290000211b20034190036a41086a200241086a2900003703002003201b370390032002102f41e8bcc100ad4280808080a0018410012202290008211b20022d0007210420022d0006210720022f0004210820022d0003210a20022d0002210b20022f0000210c2002102f4120102d221a450d1d201a20032903c80c370000201a41186a200341c80c6a41186a290300370000201a41106a200341c80c6a41106a290300370000201a41086a200341c80c6a41086a290300370000201aad428080808080048410032202290018210620022d0017210d20022d0016210e20022f0014210f20022d0013211020022d0012211120022f0010211220022d000f211320022d000e211420022f000c211520022d000b211620022d000a211720022f0008211820022d0007210520022d0006211920022f0004212020022d0003212120022d0002212220022f000021232002102f201a102f41c000102d2202450d1d2002200329039003370000200220063700382002200d3a00372002200e3a00362002200f3b0034200220103a0033200220113a0032200220123b0030200220133a002f200220143a002e200220153b002c200220163a002b200220173a002a200220183b0028200220053a0027200220193a0026200220203b0024200220213a0023200220223a0022200220233b00202002201b370018200220043a0017200220073a0016200220083b00142002200a3a00132002200b3a00122002200c3b0010200241086a20034190036a41086a290300370000200341c00036022c20032002360228200341f00e6a200341286a10ac012002102f0240200341840f6a280200450d0020032802800f102f0b2003418c0f6a10a401200341f00e6a41086a41043a0000200341f90e6a20032903c80c370000200341890f6a200341d80c6a290300370000200341910f6a200341e00c6a2903003700002003419c0f6a2009360200200341c80c6a41086a290300211b200341113a00f00e200341f00e6a41116a201b37000041c8e1ca004100200341f00e6a108c01200041043a00004101211a0c1b0b4101211a20022d00014101470d0420022d000041ff01710d04200141106a2903002128200141086a2903002127200141046a280200211a20032002411a6a2901003703880f2003200241026a2901003703f00e20032002410a6a2901003703f80e2003200241126a2901003703800f41a4e3c400ad4280808080c00084221b1001220229000021062002290008211c2002102f4188bec100ad4280808080a00184221d10012202290000211e2002290008211f2002102f2003201f3703a8032003201e3703a0032003201c370398032003200637039003200341e8096a20034190036a10b30120032802e8092204410820041b2102410321070240201a20032902ec09420020041b221e422088a722044f0d002002201a4106746a2208450d0020082903004201520d0002402002201a4106746a220841206a221a200341f00e6a460d00201a200341f00e6a412010ea060d010b200841086a221a2027370300201a2028370308410421070b201b1001221a290000211b201a2900082106201a102f201d1001221a290000211c201a290008211d201a102f2003201d3703a8032003201c3703a00320032006370398032003201b370390030240024020020d0020034190036aad428080808080048410050c010b200341e8096a2002200410ba0120034190036aad428080808080048420033502f00942208620032802e809221aad841004024020032802ec09450d00201a102f0b201ea7450d002002102f0b20004198123b0001200020073a0000200041086a410c360200200041046a41a5f4c0003602004101211a0c1a0b200141246a280200211a200341286a41186a200141196a290000370300200341286a41106a200141116a290000370300200341286a41086a200141096a29000037030020032001290001370328024020022d00000d0020022d00014101470d00200241196a2d00002104200241186a2d00002107200241166a2f01002108200241156a2d00002109200241146a2d0000210a200241126a2f0100210b200241116a2d0000210c200241106a2d0000210d2002410e6a2f0100210e2002410d6a2d0000210f2002410c6a2d000021102002410a6a2f01002111200241096a2d00002112200241086a2d00002113200241066a2f01002114200241056a2d00002115200241046a2d00002116200241026a2f0100211720032002411a6a2901003703880f200320043a00870f200320073a00860f200320083b01840f200320093a00830f2003200a3a00820f2003200b3b01800f2003200c3a00ff0e2003200d3a00fe0e2003200e3b01fc0e2003200f3a00fb0e200320103a00fa0e200320113b01f80e200320123a00f70e200320133a00f60e200320143b01f40e200320153a00f30e200320163a00f20e200320173b01f00e200341e8096a41186a2208200341286a41186a290300370300200341e8096a41106a2209200341286a41106a290300370300200341e8096a41086a220a200341286a41086a290300370300200320032903283703e80941a4e3c400ad4280808080c00084221b1001220229000021062002290008211c2002102f4188bec100ad4280808080a00184221d10012202290000211e2002290008211f2002102f2003201f3703a8032003201e3703a0032003201c370398032003200637039003200341c80c6a20034190036a10b30120032802c80c2204410820041b2102410321070240201a20032902cc0c420020041b221e422088a722044f0d002002201a4106746a220b450d00200b2903004201520d0020092f01002109200a2f0100210a20032d00ff09210b20032d00fe09210c20032f01fc09210d20032d00fb09210e20032d00fa09210f20032d00f709211020032d00f609211120032f01f409211220032d00f309211320032d00f209211420032d00ef09211520032d00ee09211620032f01ec09211720032d00eb09211820032d00ea09210520032f01e80921192003200829030022063703a8032003200b3a00a7032003200c3a00a6032003200d3b01a4032003200e3a00a3032003200f3a00a203200320093b01a003200320103a009f03200320113a009e03200320123b019c03200320133a009b03200320143a009a032003200a3b019803200320153a009703200320163a009603200320173b019403200320183a009303200320053a009203200320193b0190030240200341f00e6a2002201a4106746a220841206a221a460d00201a200341f00e6a412010ea060d010b201a20153a0007201a20163a0006201a20173b0104201a20183a0003201a20053a0002201a20193b01002008200a3b0128201a20103a000f201a20113a000e201a20123b010c201a20133a000b201a20143a000a200820093b0130201a200b3a0017201a200c3a0016201a200d3b0114201a200e3a0013201a200f3a001220082006370338410421070b201b1001221a290000211b201a2900082106201a102f201d1001221a290000211c201a290008211d201a102f2003201d3703a8032003201c3703a00320032006370398032003201b370390030240024020020d0020034190036aad428080808080048410050c010b200341c80c6a2002200410ba0120034190036aad428080808080048420033502d00c42208620032802c80c221aad841004024020032802cc0c450d00201a102f0b201ea7450d002002102f0b20004198123b0001200020073a0000200041086a410c360200200041046a41a5f4c0003602004101211a0c1a0b200041023a00004101211a0c190b4101211a024020022d00014101470d0020022d000041ff01710d00200141086a2903002128200141046a280200211a20032002411a6a2901003703880f2003200241026a2901003703f00e20032002410a6a2901003703f80e2003200241126a2901003703800f41a4e3c400ad4280808080c00084221b1001220229000021062002290008211c2002102f4188bec100ad4280808080a00184221d10012202290000211e2002290008211f2002102f2003201f3703a8032003201e3703a0032003201c370398032003200637039003200341e8096a20034190036a10b30120032802e8092204410820041b2102410321070240201a20032902ec09420020041b221e422088a722044f0d002002201a4106746a2208450d0020082903004201520d0002402002201a4106746a220841206a221a200341f00e6a460d00201a200341f00e6a412010ea060d010b20082028370318410421070b201b1001221a290000211b201a2900082106201a102f201d1001221a290000211c201a290008211d201a102f2003201d3703a8032003201c3703a00320032006370398032003201b370390030240024020020d0020034190036aad428080808080048410050c010b200341e8096a2002200410ba0120034190036aad428080808080048420033502f00942208620032802e809221aad841004024020032802ec09450d00201a102f0b201ea7450d002002102f0b20004198123b0001200020073a0000200041086a410c360200200041046a41a5f4c0003602004101211a0c190b200041023a00000c180b200141c0006a2903002106200141386a290300211c200141306a290300211b200141046a280200211a200341286a41206a200141286a280200360200200341286a41186a200141206a290200370300200341286a41106a200141186a290200370300200341286a41086a200141106a2902003703002003200141086a29020037032820022d00000d0720022d00014101470d07200241196a2d00002104200241186a2d00002107200241166a2f01002108200241156a2d00002109200241146a2d0000210a200241126a2f0100210b200241116a2d0000210c200241106a2d0000210d2002410e6a2f0100210e2002410d6a2d0000210f2002410c6a2d000021102002410a6a2f01002111200241096a2d00002112200241086a2d00002113200241066a2f01002114200241056a2d00002115200241046a2d00002116200241026a2f0100211720032002411a6a2901003703e002200320043a00df02200320073a00de02200320083b01dc02200320093a00db022003200a3a00da022003200b3b01d8022003200c3a00d7022003200d3a00d6022003200e3b01d4022003200f3a00d302200320103a00d202200320113b01d002200320123a00cf02200320133a00ce02200320143b01cc02200320153a00cb02200320163a00ca02200320173b01c802200341f00e6a41206a200341286a41206a280200360200200341f00e6a41186a200341286a41186a290300370300200341f00e6a41106a200341286a41106a290300370300200341f00e6a41086a200341286a41086a290300370300200320032903283703f00e200341e8096a200341f00e6a10bb0102400240024002400240024002400240024020032d00e8094101460d00200341e8096a41086a2d00002102200341f1096a2f00002104200341f3096a2d00002107200341f4096a2d00002108200341f5096a2f00002109200341f7096a2d0000210a200341e8096a41106a2d0000210b200341f9096a2f0000210c200341fb096a2d0000210d200341fc096a2d0000210e200341fd096a2f0000210f200341ff096a2d00002110200341e8096a41186a2d0000211120032f00e909211220032d00eb09211320032d00ec09211420032f00ed09211520032d00ef0921162003200341810a6a2900003703e00c200320113a00df0c200320103a00de0c2003200f3b01dc0c2003200e3a00db0c2003200d3a00da0c2003200c3b01d80c2003200b3a00d70c2003200a3a00d60c200320093b01d40c200320083a00d30c200320073a00d20c200320043b01d00c200320023a00cf0c200320163a00ce0c200320153b01cc0c200320143a00cb0c200320133a00ca0c200320123b01c80c201b4201510d0141a4e3c400ad4280808080c0008410012202290000211d2002290008211e2002102f4188bec100ad4280808080a0018410012202290000211f200229000821282002102f200320283702800a2003201f3702f8092003201e3702f0092003201d3702e809200341f00e6a200341e8096a10b30120032802f00e2202410820021b2104201a20032902f40e420020021b221d422088a74f0d032004201a4106746a2202450d0320022903004201520d0302402004201a4106746a41206a2202200341c8026a460d002002200341c8026a412010ea060d040b0240201da7450d002004102f0b41a4e3c400ad4280808080c0008410012202290000211d200341a80c6a41086a200241086a2900003703002003201d3703a80c2002102f41e8bcc100ad4280808080a0018410012202290000211d200341d00e6a41086a200241086a2900003703002003201d3703d00e2002102f4120102d2202450d22200220032903c80c370000200241186a200341c80c6a41186a290300370000200241106a200341c80c6a41106a290300370000200241086a200341c80c6a41086a2903003700002002ad428080808080048410032204290000211d200441086a290000211e200441106a290000211f20034190036a41186a2207200441186a29000037030020034190036a41106a2208201f37030020034190036a41086a201e3703002003201d370390032004102f2002102f41c000102d2202450d22200220032903a80c370000200241086a200341a80c6a41086a290300370000200220032903d00e370010200241186a200341d00e6a41086a2903003700002002200329039003370020200241286a20034190036a41086a290300370000200241306a2008290300370000200241386a2007290300370000200341f00e6a200210b401200341f00e6a41086a290300211d20032903f00e211e20032802800f210920032802840f210b20032802880f210a20034190036a2003418c0f6a41880210e8061a200341f0026a41086a22042003419d116a290000370300200341f0026a41106a200341a5116a290000370300200341f0026a41176a2207200341ac116a28000036000020032003290095113703f00220032d009411220c4102460d02200341c0076a20034190036a41880210e8061a20034198056a41176a2208200728000036000020034198056a41106a2207200341f0026a41106a29030037030020034198056a41086a220d2004290300370300200320032903f002370398052002102f200341b8056a200341c0076a41880210e8061a200341e8096a200341b8056a41880210e8061a200341c8096a41176a2008280000360000200341c8096a41106a2007290300370300200341c8096a41086a200d29030037030020032003290398053703c80941002102200a41014b0d04200a0e020605060b200041013a00004101211a0c1f0b20004183303b0100200041086a4110360200200041046a41b1f4c000360200200041026a41083a00004101211a0c1e0b2002102f200041086a410d360200200041046a4198f4c000360200200041026a410a3a000020004183303b01004101211a0c1d0b20004183303b0100200041086a410c360200200041046a41a5f4c000360200200041026a41093a0000201da7450d122004102f4101211a0c1c0b200a2104034020022004410176220720026a2208200920084105746a280200201a4b1b2102200420076b220441014b0d000b0b200920024105746a22042802002207201a460d01200a20022007201a496a2202490d0b0b0240200a200b470d00200b41016a2204200b490d16200b41017422072004200720044b1b220441ffffff3f712004470d16200441057422044100480d1602400240200b0d002004102d21090c010b2009200b4105742004103121090b2009450d1c2004410576210b0b200920024105746a220441206a2004200a20026b41057410e9061a200441186a2006370300200441106a201c3703002004201b3703082004201a360200200a41016a210a0c010b200a20024d0d0a200920024105746a220241086a2107024020022903084201520d00200341f00e6a200341c80c6a200341c8026a200241106a290300200241186a290300410010bc010b2007201b3703002004201a360200200241186a2006370300200241106a201c3703000b200341f00e6a41186a200a360200200341840f6a200b3602002003201e3703f00e200320093602800f2003201d3703f80e2003418c0f6a200341e8096a41880210e806210720034194116a200c3a000020034195116a20032903c8093700002003419d116a200341c8096a41086a290300370000200341a5116a200341c8096a41106a290300370000200341ac116a200341df096a28000036000041a4e3c400ad4280808080c0008410012202290000211b20034190036a41086a200241086a2900003703002003201b370390032002102f41e8bcc100ad4280808080a0018410012202290008211b20022d0007210820022d0006210920022f0004210a20022d0003210b20022d0002210c20022f0000210d2002102f4120102d2204450d19200420032903c80c370000200441186a200341c80c6a41186a290300370000200441106a200341c80c6a41106a290300370000200441086a200341c80c6a41086a2903003700002004ad428080808080048410032202290018210620022d0017210e20022d0016210f20022f0014211020022d0013211120022d0012211220022f0010211320022d000f211420022d000e211520022f000c211620022d000b211720022d000a211820022f0008210520022d0007211920022d0006212020022f0004212120022d0003212220022d0002212320022f000021242002102f2004102f41c000102d2202450d192002200329039003370000200220063700382002200e3a00372002200f3a0036200220103b0034200220113a0033200220123a0032200220133b0030200220143a002f200220153a002e200220163b002c200220173a002b200220183a002a200220053b0028200220193a0027200220203a0026200220213b0024200220223a0023200220233a0022200220243b00202002201b370018200220083a0017200220093a00162002200a3b00142002200b3a00132002200c3a00122002200d3b0010200241086a20034190036a41086a290300370000200341c0003602c407200320023602c007200341f00e6a200341c0076a10ac012002102f024020032802840f450d0020032802800f102f0b200710a401200341f00e6a41086a41053a0000200341f90e6a20032903c80c370000200341890f6a200341d80c6a290300370000200341910f6a200341e00c6a2903003700002003419c0f6a201a360200200341c80c6a41086a290300211b200341113a00f00e200341f00e6a41116a201b37000041c8e1ca004100200341f00e6a108c01200041043a00004101211a0c170b200341e8026a200141246a280200360200200341e0026a2001411c6a290200370300200341c8026a41106a200141146a290200370300200341d0026a2001410c6a2902003703002003200141046a2902003703c802200241036a2d0000210420022f000121070240024020022d00002208417f6a221a41024b0d000240201a0e03000102000b200241086a2802004101742002410c6a2802004d0d00200241046a28020041ff0171450d010b200720044110747220084100477241ff01710d0a0b200341f00e6a41206a200341c8026a41206a280200360200200341f00e6a41186a2204200341c8026a41186a290300370300200341f00e6a41106a200341c8026a41106a290300370300200341f00e6a41086a2207200341c8026a41086a290300370300200320032903c8023703f00e200341e8096a200341f00e6a10bb0120034190036a41086a2202200341f1096a29000037030020034190036a41106a2208200341f9096a29000037030020034190036a41186a2209200341810a6a290000370300200320032900e909370390034101211a02400240024020032d00e8094101460d00200341c8096a41186a2009290300370300200341c8096a41106a2008290300370300200341c8096a41086a200229030037030020032003290390033703c809200341f00e6a200341c8096a10b9012007290300211e20042802002125200341840f6a280200210820032903f00e211f20032802800f212441a4e3c400ad4280808080c000841001221a290000211b2002201a41086a2900003703002003201b37039003201a102f41e8bcc100ad4280808080a0018410012202290008211b20022d0007210420022d0006210720022f0004210920022d0003210a20022d0002210b20022f0000210c2002102f4120102d221a450d1b201a20032903c809370000201a41186a200341c8096a41186a290300370000201a41106a200341c8096a41106a290300370000201a41086a200341c8096a41086a290300370000201aad428080808080048410032202290018210620022d0017210d20022d0016210e20022f0014210f20022d0013211020022d0012211120022f0010211220022d000f211320022d000e211420022f000c211520022d000b211620022d000a211720022f0008211820022d0007210520022d0006211920022f0004212020022d0003212120022d0002212220022f000021232002102f201a102f41c000102d2202450d1b2002200329039003370000200220063700382002200d3a00372002200e3a00362002200f3b0034200220103a0033200220113a0032200220123b0030200220133a002f200220143a002e200220153b002c200220163a002b200220173a002a200220183b0028200220053a0027200220193a0026200220203b0024200220213a0023200220223a0022200220233b00202002201b370018200220043a0017200220073a0016200220093b00142002200a3a00132002200b3a00122002200c3b0010200241086a20034190036a41086a290300370000200341f00e6a200210b401024020032d009411220d410246221a0d002002ad428080808080088410050b200341f00e6a41086a290300211d20032903f00e211c20032802880f210420032802840f210920032802800f2107200341286a200341f00e6a411c6a41880210e8061a200341d00e6a41176a220a200341f00e6a41bc026a280000360000200341d00e6a41106a220b200341f00e6a41b5026a290000370300200341d00e6a41086a220c200341f00e6a41ad026a29000037030020032003290095113703d00e20034190036a200341286a41880210e8061a200341f0026a41176a220e200a280000360000200341f0026a41106a220a200b290300370300200341f0026a41086a220b200c290300370300200320032903d00e3703f0020240201a0d00200341c0076a20034190036a41880210e8061a20034198056a41176a221a200e28000036000020034198056a41106a220c200a29030037030020034198056a41086a220a200b290300370300200320032903f002370398052002102f200341b8056a200341c0076a41880210e8061a200341c80c6a200341b8056a41880210e8061a200341a80c6a41176a2202201a280000360000200341a80c6a41106a221a200c290300370300200341a80c6a41086a220b200a290300370300200341800a6a2004360200200341fc096a200936020020032003290398053703a80c2003201d3703f0092003201c3703e809200320073602f809200341e8096a411c6a200341c80c6a41880210e806210a2003418c0c6a200d3a00002003418d0c6a20032903a80c370000200341e8096a41ad026a200b290300370000200341e8096a41b5026a201a290300370000200341e8096a41bc026a2002280000360000024002402004410574221a0d004200211b420021060c010b200741106a21024200211b420021060340200241086a2903004200200241786a29030042015122041b20067c2002290300420020041b2206201b7c221b200654ad7c2106200241206a2102201a41606a221a0d000b0b201d201e7c201c201f7c221d201c54ad7c20067c2106201d201b7c221b201d54ad211c02402009450d002007102f0b2006201c7c2106200a10a40102402025450d002025410574211a202421020340200210b701200241206a2102201a41606a221a0d000b0b2003201b37032820032006370330201b20068450450d024200211c4200211d0c030b2002102f200041086a4108360200200041046a41fcf4c000360200200041026a41023a000020004183303b01002008450d0f2024102f4101211a0c190b200041013a00000c180b2003200341c8096a3602c80c200341e8096a200341c8096a200341286a200341c80c6a10bd01200341880a6a290300211d20032903800a211c20032903e8094201520d0020032903f009211e200341a80f6a200341e8096a41106a290300370300200341a00f6a201e370300200341f00e6a41086a41003a0000200341f90e6a20032903c809370000200341810f6a200341c8096a41086a290300370000200341890f6a200341c8096a41106a290300370000200341910f6a200341e0096a290300370000200341033a00f00e41c8e1ca004100200341f00e6a108c010b201c201d10be01200341a80f6a2006370300200341a00f6a201b370300200341f00e6a41086a41023a0000200341f90e6a20032903c809370000200341890f6a200341d8096a290300370000200341910f6a200341e0096a290300370000200341c8096a41086a290300211b200341113a00f00e200341f00e6a41116a201b37000041c8e1ca004100200341f00e6a108c0102402008450d002024102f0b200041043a00004101211a0c160b200041023a00000c150b4188bbca0020072009103b000b200041023a00004101211a0c130b419ae3c300411e41f8b4ca001039000b41c4c2ca002002200b103b000b41b8e3c300411d41f8b4ca001039000b200041023a00004101211a0c0f0b419ae3c300411e41f8b4ca001039000b41c4c2ca002002200a103b000b200041023a00004101211a0c0c0b0240200c450d00200a102f0b200e10a4010b201ba7450d002004102f4101211a0c0a0b4101211a0c090b02402004450d00200441c4006c2100200941286a210203400240200241786a2d00004101470d002002280200450d002002417c6a280200102f0b200241c4006a2102200041bc7f6a22000d000b0b410021004101211a2014450d092009102f0c090b2003201c20067d201b201d54ad7d221e3703c8072003201b201d7d221f3703c0072003200341b8056a3602c8094104211a0240201f201e84500d002003200341b8056a3602c8022003200341c8026a3602f80e2003200341c8096a3602f40e2003200341c0076a3602f00e200341c80c6a200341b8056a200341f00e6a109401024020032802c80c4101470d00200320032900cd0c3703f00e2003200341d40c6a2800003600f70e20032d00cc0c211a0c010b4104211a200341c80c6a41086a2903004201520d00200341c80c6a41106a290300211e20032802c8022104200341a80f6a200341c80c6a41186a290300370300200341a00f6a201e370300200341f00e6a41086a41003a0000200341f90e6a2004290000370000200341810f6a200441086a290000370000200341890f6a200441106a290000370000200341910f6a200441186a290000370000200341033a00f00e41c8e1ca004100200341f00e6a108c010b200320032903f00e37039003200320032800f70e36009703201a41ff01714104460d002000201a3a00002000200329039003370001200041086a2003280097033600000240200341fc096a280200450d0020032802f809102f0b200341840a6a10a4010c010b0240201d201b582006201c5820021b0d0020032006201c7d201d201b54ad7d22063703c8072003201d201b7d221b3703c007201b200684500d002003200341b8056a36029003200341c80c6a200341b8056a200341c0076a20034190036a10960120032903c80c4201520d0020032903d00c211b200341a80f6a200341c80c6a41106a290300370300200341a00f6a201b370300200341f00e6a41086a41003a0000200341f90e6a20032903b805370000200341810f6a200341b8056a41086a290300370000200341890f6a200341b8056a41106a290300370000200341910f6a200341d0056a290300370000200341033a00f00e41c8e1ca004100200341f00e6a108c010b200341f00e6a200341e8096a41c00210e8061a41a4e3c400ad4280808080c0008410012202290000211b20034190036a41086a200241086a2900003703002003201b370390032002102f41e8bcc100ad4280808080a0018410012202290008211b20022d0007210420022d0006210720022f0004210820022d0003210920022d0002210a20022f0000210b2002102f4120102d221a450d08201a20032903b805370000201a41186a200341b8056a41186a290300370000201a41106a200341b8056a41106a290300370000201a41086a200341b8056a41086a290300370000201aad428080808080048410032202290018210620022d0017210c20022d0016210d20022f0014210e20022d0013210f20022d0012211020022f0010211120022d000f211220022d000e211320022f000c211420022d000b211520022d000a211620022f0008211720022d0007211820022d0006210520022f0004211920022d0003212020022d0002212120022f000021222002102f201a102f41c000102d2202450d082002200329039003370000200220063700382002200c3a00372002200d3a00362002200e3b00342002200f3a0033200220103a0032200220113b0030200220123a002f200220133a002e200220143b002c200220153a002b200220163a002a200220173b0028200220183a0027200220053a0026200220193b0024200220203a0023200220213a0022200220223b00202002201b370018200220043a0017200220073a0016200220083b0014200220093a00132002200a3a00122002200b3b0010200241086a20034190036a41086a290300370000200341c0003602cc0c200320023602c80c200341f00e6a200341c80c6a10ac012002102f0240200341840f6a280200450d0020032802800f102f0b2003418c0f6a10a401200341f00e6a41086a41003a0000200341f90e6a20032903b805370000200341890f6a200341c8056a290300370000200341910f6a200341d0056a290300370000200341b8056a41086a290300211b200341113a00f00e200341f00e6a41116a201b37000041c8e1ca004100200341f00e6a108c01200041043a00000b410121004100211a0c060b2002201ba7470d02200241016a22042002490d00200241017422052004200520044b1b220441ffffff1f712004470d002004410674220441004e0d010b1038000b0240024020020d002004102d211a0c010b201a200241067420041031211a0b201a450d04201b428080808070832004410676ad84211b0b201b422088a7220421020b201a20024106746a2202420037030820024201370300200241106a4200370300200241186a4200370300200241386a2006370300200241376a20073a0000200241366a20083a0000200241346a20093b0100200241336a200a3a0000200241326a200b3a0000200241306a200c3b01002002412f6a200d3a00002002412e6a200e3a00002002412c6a200f3b01002002412b6a20103a00002002412a6a20113a0000200241286a20123b0100200241276a20133a0000200241266a20143a0000200241246a20153b0100200241236a20163a0000200241226a20173a0000200241206a20183b010041a4e3c400ad4280808080c000841001220229000021062002290008211c2002102f4188bec100ad4280808080a0018410012202290000211d2002290008211e2002102f2003201e3703a8032003201d3703a0032003201c37039803200320063703900302400240201a0d0020034190036aad428080808080048410050c010b201ba72102200341f00e6a201a200441016a10ba0120034190036aad428080808080048420033502f80e42208620032802f00e2207ad841004024020032802f40e450d002007102f0b2002450d00201a102f0b200341fc0e6a2004360200200341f80e6a41063a0000200341113a00f00e41c8e1ca004100200341f00e6a108c01200041043a00004101211a0b410121000b20012d0000417e6a220241014b0d0320020e020201020b1036000b2000450d0102402001410c6a2802002202450d00200241c4006c2100200141046a28020041286a210203400240200241786a2d00004101470d002002280200450d002002417c6a280200102f0b200241c4006a2102200041bc7f6a22000d000b0b200141086a280200450d012001280204102f0c010b201a450d00200141046a10a4010b200341b0116a24000bee09040a7f017e047f037e230041f0016b220224002002412036020c20022001360208200241106a2001ad42808080808004841002107302400240024002400240024020022802102203450d00200228021421042002200241186a280200360224200220033602202002200241206a10e60120022802000d0320022802042205200228022422064106762201200120054b1b22074106742201417f4c0d010240024020070d00410821080c010b2001102d2208450d030b02402005450d004100210903400240024002402006450d0020022006417f6a220a36022420022002280220220b41016a360220200b2d0000220141014b0d004200210c024002400240024020010e020100010b41002101200241003a00e8012006417f6a210a0340200a2001460d02200241c8016a20016a200b20016a220d41016a2d00003a00002002200d41026a3602202002200141016a220d3a00e801200d2101200d4120470d000b200241a8016a41086a220e200241c8016a41086a290300370300200241a8016a41106a220f200241c8016a41106a290300370300200241a8016a41186a2210200241c8016a41186a290300370300200220022903c8013703a8012002200d417f7320066a220136022420014110490d022002200b200d6a220141116a220b36022020022006200d6b220a416f6a220d360224200d4108490d02200141096a2900002111200141016a29000021122002200a41676a220a3602242002200141196a360220200b29000022134280025a0d02200241e8006a41086a200e290300220c370300200241c8006a41186a2010290300370300200241c8006a41106a200f290300370300200241c8006a41086a200c370300200220022903a801220c3703682002200c3703484201210c0b200941016a210d200241286a41186a220b200241c8006a41186a290300370300200241286a41106a2206200241c8006a41106a290300370300200241286a41086a220e200241c8006a41086a2903003703002002200229034837032820072009470d04024020094101742201200d2001200d4b1b220141ffffff1f712001470d002001410674220141004e0d040b1038000b20024100360224200141ff0171450d00200241003a00e8010b200241e8006a41086a20024188016a41086a290300370300200241e8006a41106a20024188016a41106a2903003703000b2007450d072008102f0c070b0240024020090d002001102d21080c010b200820094106742001103121080b2008450d05200141067621070b200820094106746a220120123703082001200c370300200141106a2011370300200141186a2013370300200141206a2002290328370300200141286a200e290300370300200141306a2006290300370300200141386a200b290300370300200a2106200d2109200d2005470d000b0b2008450d032000200736020420002008360200200041086a20053602000c040b200041003602000c040b103d000b1036000b200241003602b001200242013703a8012002410b36028c012002200241086a360288012002200241a8016a360268200241dc016a4101360200200242013702cc01200241b885c7003602c801200220024188016a3602d801200241e8006a41d8dbc100200241c8016a103c1a20023502b00142208620023502a801841008024020022802ac01450d0020022802a801102f0b200041003602000b2004450d002003102f0b200241f0016a24000bfe46070b7f017e017f017e017f027e3a7f230041f0076b22022400200241c00036021420022001360210200241186a2001ad42808080808008841002107302400240024002400240024020022802182203450d0041082104200228021c21052002200241186a41086a280200360294022002200336029002200220024190026a36028804200241086a20024188046a10eb04024020022802080d000240200228020c22064180012006418001491b2207450d002007410574102d2204450d030b0240024002402006450d00200241d0076a2108411021094100210a0340200241003602c807200241c8076a200228029002220b2002280294022201410420014104491b220c10e8061a20022001200c6b360294022002200b200c6a360290020240200141034b0d00200241c8076a200c6a41004104200c6b10e7061a0b20023502c807210d200241003a00c807024020022802940222012001410047220c490d00200241c8076a200228029002220b200c10e8061a20022001200c6b220e360294022002200b200c6a220c3602900202400240024020010d004200210f0c010b20022d00c807220141064b0d024200210f02400240024002400240024020010e0707000102030405070b200241c8076a200e4110200e4110491b22016a41004100411020016b220b2001410f4b1b10e7062110200241c8076a200c200110e8061a2002200e20016b360294022002200c20016a360290020240200e410f4b0d0020104100200b10e7061a0b2008290300211120022903c80721124201210f0c060b4202210f0c040b4203210f0c030b4204210f0c020b4205210f0c010b4206210f0b0b0240200a2007470d0020074101742201200741016a220c2001200c4b1b220141ffffff3f712001470d09200141057422014100480d090240024020070d002001102d21040c010b200420074105742001103121040b2004450d08200141057621070b200420096a2201201137030820012012370300200141786a200f370300200141706a200d370300200941206a21092006200a41016a220a470d010c030b0b20070d020c030b2004450d020b200241d0076a22094200370300200242003703c807200241c8076a200228029002220a2002280294022201411020014110491b220c10e8061a20022001200c6b360294022002200a200c6a3602900202402001410f4b0d00200241c8076a200c6a41004110200c6b10e7061a0b2009290300211220022903c8072111200220024188046a10eb04024020022802000d000240024020022802042213413820134138491b22140d004104210e0c010b201441c8006c102d220e450d050b024002402013450d00200241a0076a410c6a210a200241a0076a41017221084100210b41002109410021010340200241a0076a20024188046a10a8010240024020022d00a00722104106460d0020024198066a41026a2215200841026a2d00003a000020024188076a41086a2216200a41086a29020037030020024188076a41106a2217200a41106a290200370300200220082f00003b0198062002200a2902003703880720022802a407211820022802a8072119200241c8076a20024188046a10a80120022d00c8074106470d0120104101470d002019450d002018102f0b02402001450d00200e20096a210c200e21010340024020012d00004101470d00200141086a280200450d00200141046a280200102f0b0240200141246a2d00004101470d002001412c6a280200450d00200141286a280200102f0b200c200141c8006a2201470d000b0b20140d030c040b200141016a210c200241f8056a41026a221a20152d00003a0000200241f0066a41086a22152016290300370300200241f0066a41106a22162017290300370300200241c8066a41086a2217200241c8076a41086a290300370300200241c8066a41106a221b200241c8076a41106a290300370300200241c8066a41186a221c200241c8076a41186a290300370300200241c8066a41206a221d200241c8076a41206a280200360200200220022f0198063b01f80520022002290388073703f006200220022903c8073703c806024020012014470d00200b200c200b200c4b1bad42c8007e220f422088a70d09200fa722144100480d090240024020010d002014102d210e0c010b200e200920141031210e0b200e450d08201441c8006e21140b200e20096a220120103a0000200141086a2019360200200141046a2018360200200141036a201a2d00003a0000200141016a20022f01f8053b00002001410c6a20022903f006370200200141146a20152903003702002001411c6a2016290300370200200141346a201b2903003702002001412c6a20172903003702002001413c6a201c290300370200200141246a20022903c806370200200141c4006a201d280200360200200b41026a210b200941c8006a2109200c21012013200c470d000b0b200e450d01200241c8076a20024188046a10a8010240024002400240024020022d00c807220c4106460d0020024194066a41026a20022d00cb073a0000200241f8056a41086a200241dc076a2201290200370300200241f8056a41106a200241e4076a220b290200370300200220022f00c9073b0194062002200241d4076a22082902003703f805200241c8076a41086a2210280200210920022802cc07210a200241c8076a20024188046a10a80120022d00c80722194106460d01200241b4066a41026a20022d00cb073a000020024198066a41086a200129020037030020024198066a41106a200b290200370300200220022f00c9073b01b40620022008290200370398062010280200210b20022802cc072108200241c8076a20024188046a10a80120022d00c80722104106460d02200241b8066a41026a20022d00cb073a0000200241f0066a41086a200241dc076a2201290200370300200241f0066a41106a200241e4076a2216290200370300200220022f00c9073b01b8062002200241d4076a22172902003703f006200241c8076a41086a221a280200211820022802cc072115200241c8076a20024188046a10a80120022d00c807221b4106460d03200241bc066a41026a20022d00cb073a000020024188076a41086a200129020037030020024188076a41106a2016290200370300200220022f00c9073b01bc062002201729020037038807201a280200211620022802cc072117200241c8076a20024188046a10a80120022d00c807221a4106470d040240201b4101470d002016450d002017102f0b024020104101470d002018450d002015102f0b024020194101470d00200b450d002008102f0b0240200c4101470d002009450d00200a102f0b02402013450d00200e201341c8006c6a210c200e21010340024020012d00004101470d00200141086a280200450d00200141046a280200102f0b0240200141246a2d00004101470d002001412c6a280200450d00200141286a280200102f0b200141c8006a2201200c470d000b0b20140d050c060b02402013450d00200e201341c8006c6a210c200e21010340024020012d00004101470d00200141086a280200450d00200141046a280200102f0b0240200141246a2d00004101470d002001412c6a280200450d00200141286a280200102f0b200141c8006a2201200c470d000b0b20140d040c050b0240200c4101470d002009450d00200a102f0b02402013450d00200e201341c8006c6a210c200e21010340024020012d00004101470d00200141086a280200450d00200141046a280200102f0b0240200141246a2d00004101470d002001412c6a280200450d00200141286a280200102f0b200141c8006a2201200c470d000b0b20140d030c040b024020194101470d00200b450d002008102f0b0240200c4101470d002009450d00200a102f0b02402013450d00200e201341c8006c6a210c200e21010340024020012d00004101470d00200141086a280200450d00200141046a280200102f0b0240200141246a2d00004101470d002001412c6a280200450d00200141286a280200102f0b200141c8006a2201200c470d000b0b20140d020c030b024020104101470d002018450d002015102f0b024020194101470d00200b450d002008102f0b0240200c4101470d002009450d00200a102f0b02402013450d00200e201341c8006c6a210c200e21010340024020012d00004101470d00200141086a280200450d00200141046a280200102f0b0240200141246a2d00004101470d002001412c6a280200450d00200141286a280200102f0b200141c8006a2201200c470d000b0b20140d010c020b200241c2066a20022d00cb073a0000200241c8066a41086a200241dc076a290200370300200241d8066a200241e4076a290200370300200220022f00c9073b01c0062002200241d4076a2902003703c806200241c8076a41086a280200211d20022802cc07211e200241003a00c8070240024020022802940222012001410047221c490d00200241c8076a200228029002221f201c10e8061a20022001201c6b2220360294022002201f201c6a221c360290020240024020010d00410021010c010b20022d00c807222141014b0d0141002101024020210e020100010b200241003a00c807202020204100472201490d01200241c8076a201c200110e8061a2002202020016b2221360294022002201c20016a221c36029002024002402020450d0020022d00c807211f0c010b4100211f200241003a00c8070b200241003a00c807202120214100472201490d01200241c8076a201c200110e8061a2002202120016b2220360294022002201c20016a221c36029002024002402021450d0020022d00c80721220c010b41002122200241003a00c8070b200241003a00c807202020204100472201490d01200241c8076a201c200110e8061a2002202020016b2221360294022002201c20016a221c36029002024002402020450d0020022d00c80721230c010b41002123200241003a00c8070b200241003a00c807202120214100472201490d01200241c8076a201c200110e8061a2002202120016b2220360294022002201c20016a221c36029002024002402021450d0020022d00c80721240c010b41002124200241003a00c8070b200241003a00c807202020204100472201490d01200241c8076a201c200110e8061a2002202020016b2221360294022002201c20016a221c36029002024002402020450d0020022d00c80721250c010b41002125200241003a00c8070b200241003a00c807202120214100472201490d01200241c8076a201c200110e8061a2002202120016b2220360294022002201c20016a221c36029002024002402021450d0020022d00c80721260c010b41002126200241003a00c8070b200241003a00c807202020204100472201490d01200241c8076a201c200110e8061a2002202020016b2221360294022002201c20016a221c36029002024002402020450d0020022d00c80721270c010b41002127200241003a00c8070b200241003a00c807202120214100472201490d01200241c8076a201c200110e8061a2002202120016b2220360294022002201c20016a221c36029002024002402021450d0020022d00c80721280c010b41002128200241003a00c8070b200241003a00c807202020204100472201490d01200241c8076a201c200110e8061a2002202020016b2221360294022002201c20016a221c36029002024002402020450d0020022d00c80721290c010b41002129200241003a00c8070b200241003a00c807202120214100472201490d01200241c8076a201c200110e8061a2002202120016b2220360294022002201c20016a221c36029002024002402021450d0020022d00c807212a0c010b4100212a200241003a00c8070b200241003a00c807202020204100472201490d01200241c8076a201c200110e8061a2002202020016b2221360294022002201c20016a221c36029002024002402020450d0020022d00c807212b0c010b4100212b200241003a00c8070b200241003a00c807202120214100472201490d01200241c8076a201c200110e8061a2002202120016b2220360294022002201c20016a221c36029002024002402021450d0020022d00c807212c0c010b4100212c200241003a00c8070b200241003a00c807202020204100472201490d01200241c8076a201c200110e8061a2002202020016b2221360294022002201c20016a221c36029002024002402020450d0020022d00c807212d0c010b4100212d200241003a00c8070b200241003a00c807202120214100472201490d01200241c8076a201c200110e8061a2002202120016b2220360294022002201c20016a221c36029002024002402021450d0020022d00c807212e0c010b4100212e200241003a00c8070b200241003a00c807202020204100472201490d01200241c8076a201c200110e8061a2002202020016b2221360294022002201c20016a221c36029002024002402020450d0020022d00c807212f0c010b4100212f200241003a00c8070b200241003a00c807202120214100472201490d01200241c8076a201c200110e8061a2002202120016b2220360294022002201c20016a221c36029002024002402021450d0020022d00c80721300c010b41002130200241003a00c8070b200241003a00c807202020204100472201490d01200241c8076a201c200110e8061a2002202020016b2221360294022002201c20016a221c36029002024002402020450d0020022d00c80721310c010b41002131200241003a00c8070b200241003a00c807202120214100472201490d01200241c8076a201c200110e8061a2002202120016b2220360294022002201c20016a221c36029002024002402021450d0020022d00c80721320c010b41002132200241003a00c8070b200241003a00c807202020204100472201490d01200241c8076a201c200110e8061a2002202020016b2221360294022002201c20016a221c36029002024002402020450d0020022d00c80721330c010b41002133200241003a00c8070b200241003a00c807202120214100472201490d01200241c8076a201c200110e8061a2002202120016b360294022002201c20016a36029002024002402021450d0020022d00c80721340c010b41002134200241003a00c8070b410121010b200241c8076a20024188046a10a80120022d00c807221c4106460d01200241c4066a41026a223520022d00cb073a0000200241a0076a41086a2236200241dc076a290200370300200241a0076a41106a2237200241e4076a290200370300200220022f00c9073b01c4062002200241d4076a2902003703a007200241c8076a41086a2238280200212020022802cc072121200241c8076a20024188046a10a80120022d00c8074106470d090240201c4101470d002020450d002021102f0b0240201a4101470d00201d450d00201e102f0b0240201b4101470d002016450d002017102f0b024020104101470d002018450d002015102f0b024020194101470d00200b450d002008102f0b0240200c4101470d002009450d00200a102f0b02402013450d00200e201341c8006c6a210c200e21010340024020012d00004101470d00200141086a280200450d00200141046a280200102f0b0240200141246a2d00004101470d002001412c6a280200450d00200141286a280200102f0b200141c8006a2201200c470d000b0b20140d020c030b0240201a4101470d00201d450d00201e102f0b0240201b4101470d002016450d002017102f0b024020104101470d002018450d002015102f0b024020194101470d00200b450d002008102f0b0240200c4101470d002009450d00200a102f0b02402013450d00200e201341c8006c6a210c200e21010340024020012d00004101470d00200141086a280200450d00200141046a280200102f0b0240200141246a2d00004101470d002001412c6a280200450d00200141286a280200102f0b200141c8006a2201200c470d000b0b20140d010c020b0240201a4101470d00201d450d00201e102f0b0240201b4101470d002016450d002017102f0b024020104101470d002018450d002015102f0b024020194101470d00200b450d002008102f0b0240200c4101470d002009450d00200a102f0b02402013450d00200e201341c8006c6a210c200e21010340024020012d00004101470d00200141086a280200450d00200141046a280200102f0b0240200141246a2d00004101470d002001412c6a280200450d00200141286a280200102f0b200141c8006a2201200c470d000b0b2014450d010b200e102f0b2007450d010b2004102f0b200241003602a807200242013703a0072002410b3602cc062002200241106a3602c8062002200241a0076a36029004200241dc076a4101360200200242013702cc07200241b885c7003602c8072002200241c8066a3602d80720024190046a41d8dbc100200241c8076a103c1a20023502a80742208620023502a007841008024020022802a407450d0020022802a007102f0b410221010c040b200041023a00a4020c040b1036000b1038000b20024190046a41206a2239200241c8076a41206a28020036020020024190046a41186a223a200241c8076a41186a29030037030020024190046a41106a223b200241c8076a41106a29030037030020024190046a41086a223c2038290300370300200241f2056a41026a223820024194066a41026a2d00003a0000200241d8056a41086a223d200241f8056a41086a290300370300200241d8056a41106a223e200241f8056a41106a290300370300200220022903c80737039004200220022f0194063b01f205200220022903f8053703d805200241d4056a41026a223f200241b4066a41026a2d00003a0000200220022f01b4063b01d405200241b8056a41106a224020024198066a41106a290300370300200241b8056a41086a224120024198066a41086a29030037030020022002290398063703b805200241b4056a41026a2242200241b8066a41026a2d00003a0000200220022f01b8063b01b40520024198056a41106a2243200241f0066a41106a29030037030020024198056a41086a2244200241f0066a41086a290300370300200220022903f0063703980520024194056a41026a2245200241bc066a41026a2d00003a0000200220022f01bc063b019405200241f8046a41106a224620024188076a41106a290300370300200241f8046a41086a224720024188076a41086a29030037030020022002290388073703f804200241f4046a41026a2248200241c0066a41026a2d00003a0000200220022f01c0063b01f404200241d8046a41106a2249200241c8066a41106a290300370300200241d8046a41086a224a200241c8066a41086a290300370300200220022903c8063703d804200241d4046a41026a224b20352d00003a0000200220022f01c4063b01d404200241b8046a41106a22352037290300370300200241b8046a41086a22372036290300370300200220022903a0073703b8042002418c046a41026a2236200241f5056a41026a2d00003a0000200220022f00f5053b018c0420024184046a41026a224c20382d00003a0000200220022f01f2053b018404200241e8036a41106a2238203e290300370300200241e8036a41086a223e203d290300370300200220022903d8053703e803200241e4036a41026a223d203f2d00003a0000200220022f01d4053b01e403200241c8036a41106a223f2040290300370300200241c8036a41086a22402041290300370300200220022903b8053703c803200241c4036a41026a224120422d00003a0000200220022f01b4053b01c403200241a8036a41106a22422043290300370300200241a8036a41086a2243204429030037030020022002290398053703a803200241a4036a41026a224420452d00003a0000200220022f0194053b01a40320024188036a41106a2245204629030037030020024188036a41086a22462047290300370300200220022903f8043703880320024184036a41026a224720482d00003a0000200220022f01f4043b018403200241e8026a41106a22482049290300370300200241e8026a41086a2249204a290300370300200220022903d8043703e802200241e4026a41026a224a204b2d00003a0000200220022f01d4043b01e402200241c8026a41106a224b2035290300370300200241c8026a41086a22352037290300370300200220022903b8043703c802200241a0026a41206a22372039280200360200200241a0026a41186a2239203a290300370300200241a0026a41106a223a203b290300370300200241a0026a41086a223b203c29030037030020022002290390043703a0022002419c026a41026a223c20362d00003a0000200220022f018c043b019c022002418c026a41026a2236204c2d00003a0000200220022f0184043b018c02200241f0016a41106a224c2038290300370300200241f0016a41086a2238203e290300370300200220022903e8033703f001200241ec016a41026a223e203d2d00003a0000200220022f01e4033b01ec01200241d0016a41106a223d203f290300370300200241d0016a41086a223f2040290300370300200220022903c8033703d001200241cc016a41026a224020412d00003a0000200220022f01c4033b01cc01200241b0016a41106a22412042290300370300200241b0016a41086a22422043290300370300200220022903a8033703b001200241ac016a41026a224320442d00003a0000200220022f01a4033b01ac0120024190016a41106a2244204529030037030020024190016a41086a224520462903003703002002200229038803370390012002418c016a41026a224620472d00003a0000200220022f0184033b018c01200241f0006a41106a22472048290300370300200241f0006a41086a22482049290300370300200220022903e802370370200241ec006a41026a2249204a2d00003a0000200220022f01e4023b016c200241d0006a41106a224a204b290300370300200241d0006a41086a224b2035290300370300200220022903c802370350200241286a41206a22352037280200360200200241286a41186a22372039290300370300200241286a41106a2239203a290300370300200241286a41086a223a203b290300370300200220022903a002370328200241c8076a41026a223b203c2d00003a0000200220022f019c023b01c80720002012370308200020113703002000200c3a002820002013360224200020143602202000200e36021c200020063602182000200736021420002004360210200020093602302000200a36022c200020022f018c023b00292000412b6a20362d00003a0000200020022903f0013702342000413c6a2038290300370200200041c4006a204c290300370200200020193a004c200041cf006a203e2d00003a0000200020022f01ec013b004d2000200b36025420002008360250200041e8006a203d290300370200200041e0006a203f290300370200200020022903d001370258200020103a0070200041f3006a20402d00003a0000200020022f01cc013b007120002018360278200020153602742000418c016a204129030037020020004184016a2042290300370200200020022903b00137027c2000201b3a00940120004197016a20432d00003a0000200020022f01ac013b0095012000201636029c012000201736029801200041b0016a2044290300370200200041a8016a204529030037020020002002290390013702a0012000201a3a00b801200041bb016a20462d00003a0000200020022f018c013b00b9012000201d3602c0012000201e3602bc01200041d4016a2047290300370200200041cc016a2048290300370200200020022903703702c4012000201c3a00dc01200041df016a20492d00003a0000200020022f016c3b00dd01200020203602e401200020213602e001200041f8016a204a290300370200200041f0016a204b290300370200200020022903503702e801200041a0026a203528020036020020004198026a203729030037020020004190026a203929030037020020004188026a203a2903003702002000200229032837028002200041b8026a20343a0000200041b7026a20333a0000200041b6026a20323a0000200041b5026a20313a0000200041b4026a20303a0000200041b3026a202f3a0000200041b2026a202e3a0000200041b1026a202d3a0000200041b0026a202c3a0000200041af026a202b3a0000200041ae026a202a3a0000200041ad026a20293a0000200041ac026a20283a0000200041ab026a20273a0000200041aa026a20263a0000200041a9026a20253a0000200041a8026a20243a0000200041a7026a20233a0000200041a6026a20223a00002000201f3a00a502200041bb026a203b2d00003a0000200041b9026a20022f01c8073b00000b200020013a00a4022005450d002003102f0b200241f0076a24000b9d0102017f017e230041106b2206240002402002ad4220862001ad842004ad4220862003ad84200510292207422088a72204450d002007a722052d0000220341014b0d00410021010240024020030e020100010b2004417f6a4104490d0120052800012102410121010b2005102f2000200236020420002001360200200641106a24000f0b41f4c8ca00412e200641086a418ccaca0041a4c9ca00103e000bf80202037f037e230041e0006b22022400200241c00036020c20022001360208200241106a2001ad4280808080800884100210730240024020022802102201450d00200228021421032002200241106a41086a2802002204360224200220013602200240024020044110490d002002200441706a3602242002200141106a360220200141086a290000210520012900002106200241c8006a200241206a10980320022802482204450d00200229024c2107200020053703082000200637030020002007370214200020043602100c010b20024100360230200242013703282002410b36023c2002200241086a3602382002200241286a360244200241dc006a41013602002002420137024c200241b885c7003602482002200241386a360258200241c4006a41d8dbc100200241c8006a103c1a200235023042208620023502288410080240200228022c450d002002280228102f0b200041003602100b2003450d012001102f0c010b200041003602100b200241e0006a24000bbc0303027f037e027f230041c0006b2201240041a4e3c400ad4280808080c00084100122022900002103200141086a200241086a290000370300200120033703002002102f41a9f6c000ad4280808080f00084100122022900002103200141106a41086a200241086a290000370300200120033703102002102f02404120102d2202450d0020022000290000370000200241186a200041186a290000370000200241106a200041106a290000370000200241086a200041086a2900003700002002ad4280808080800484100322002900002103200041086a2900002104200041106a2900002105200141206a41186a2206200041186a290000370300200141206a41106a22072005370300200141206a41086a2004370300200120033703202000102f2002102f41c000102d2202450d00200220012903003700002002200129031037001020022001290320370020200241086a200141086a290300370000200241186a200141106a41086a290300370000200241286a200141206a41086a290300370000200241306a2007290300370000200241386a20062903003700002002ad428080808080088410052002102f200141c0006a24000f0b1036000ba90301077f230041106b22022400024002400240200041186a28020022034105744114722204417f4c0d002004102d2205450d01200520002903003700002005200041086a290300370008200241103602082002200436020420022005360200200028021021002003200210690240024020030d002002280208210420022802042106200228020021070c010b20034105742108200228020021072002280204210320022802082105034002400240200320056b4120490d00200541206a2104200321060c010b200541206a22042005490d05200341017422062004200620044b1b22064100480d050240024020030d002006102d21070c010b200720032006103121070b2007450d040b200720056a22052000290000370000200541186a200041186a290000370000200541106a200041106a290000370000200541086a200041086a2900003700002006210320042105200041206a2100200841606a22080d000b2002200636020420022004360208200220073602000b20012902002004ad4220862007ad84100402402006450d002007102f0b200241106a24000f0b103d000b1036000b1038000ba40503027f037e047f230041d0006b2202240041a4e3c400ad4280808080c00084100122032900002104200241106a41086a200341086a290000370300200220043703102003102f41d8bdc100ad4280808080e00084100122032900002104200241206a41086a200341086a290000370300200220043703202003102f02404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100322012900002104200141086a2900002105200141106a2900002106200241306a41186a2207200141186a290000370300200241306a41106a22082006370300200241306a41086a2005370300200220043703302001102f2003102f41c000102d2203450d00200320022903103700002003200229032037001020032002290330370020200341086a200241106a41086a2209290300370000200341186a200241206a41086a220a290300370000200341286a200241306a41086a2201290300370000200341306a2008290300370000200341386a2007290300370000200241306a200310b601024020022802402207450d002003ad428080808080088410050b200a20012903002204370300200241086a200241306a411c6a280200220836020020022002290330220537032020022002290244220637030020012004370300200920083602002002200537033020022006370310024002402007450d002000200229033037030020002007360210200041146a2002290310370200200041086a200241306a41086a2903003703002000411c6a200241106a41086a2802003602000c010b200042003703082000420037030020004201370310200041186a41003602000b2003102f200241d0006a24000f0b1036000b9a0202037f017e230041206b220324000240024020024106744104722204417f4c0d002004102d2205450d0120034100360208200320043602042003200536020020022003106902402002450d002002410674210203400240024020012903004201510d00200341003a00102003200341106a41011082010c010b200341013a00102003200341106a41011082012003200141206a4120108201200141086a29030021062003200141106a290300370318200320063703102003200341106a41101082012003200141186a2903003703102003200341106a41081082010b200141c0006a2101200241406a22020d000b0b20002003290300370200200041086a200341086a280200360200200341206a24000f0b103d000b1036000b850501067f230041c0016b22022400200241ce006a2203200141036a2d00003a0000200241306a41086a2204200141106a290200370300200241306a41106a2205200141186a290200370300200241306a41186a2206200141206a280200360200200220012f00013b014c2002200141086a290200370330200141046a280200210702400240024020012d00004101470d0020024188016a200710fe02200241d0006a200228028801220120022802900110ff0220024198016a41086a200241e7006a29000037030020024198016a41106a200241ef006a29000037030020024198016a41186a200241f7006a2d00003a0000200220022f01583b01b8012002200241da006a2d00003a00ba012002200229005f37039801024020022903504201520d00200241db006a2800002107200241086a41086a20024198016a41086a290300370300200241086a41106a20024198016a41106a290300370300200241086a41186a20024198016a41186a2d00003a0000200220022d00ba013a002a200220022f01b8013b01282002200229039801370308200228028c01450d022001102f0c020b0240200228028c01450d002001102f0b410121010c020b200241086a41086a2004290300370300200241086a41106a2005290300370300200241086a41186a20062d00003a0000200220022f014c3b012820022002290330370308200220032d00003a002a0b200041036a20022d002a3a0000200020022f01283b0001200041046a2007360000200041086a2002290308370000200041106a200241086a41086a290300370000200041186a200241086a41106a290300370000200041206a200241086a41186a2d00003a0000410021010b200020013a0000200241c0016a24000b96220c027f017e027f017e027f047e027f057e017f017e027f047e230041f0086b220624002006200437031020062003370308200620053a001f024002400240024002400240024002402003200484500d0020012002460d0220012002412010ea06450d02418de6c300ad4280808080e00084100122052900002103200641f0056a41086a200541086a290000370300200620033703f0052005102f41f0e8c600ad4280808080f00084100122052900002103200641f0066a41086a200541086a290000370300200620033703f0062005102f4120102d22050d010c070b20004100360200200041106a4200370300200041086a42003703000c050b20052002290000370000200541186a200241186a290000370000200541106a200241106a290000370000200541086a200241086a2900003700002005ad4280808080800484100322072900002103200741086a2900002104200741106a2900002108200641f0076a41186a2209200741186a290000370300200641f0076a41106a220a2008370300200641f0076a41086a2004370300200620033703f0072007102f2005102f41c000102d2205450d05200520062903f005370000200520062903f006370010200520062903f007370020200541086a200641f0056a41086a290300370000200541186a200641f0066a41086a290300370000200541286a200641f0076a41086a290300370000200541306a200a290300370000200541386a2009290300370000200641a0016a200510f60220062903a001210b42002104200642003703a001200641e8016a280200210c20062d00ec01210d02400240200b4201510d00200641f0016a41386a4200370300200641f0016a41306a4200370300200641f0016a41286a4200370300200641f0016a41206a420037030020064188026a420037030020064180026a4200370300200641f0016a41086a4200370300200642003703f00142002103420021084200210e0c010b200641a0016a41386a290300210f200641a0016a41306a2903002110200641a0016a41206a290300210e200641a0016a41186a2903002108200641a0016a41c0006a290300211120062903b001210320062903a8012104200641f0016a41206a200641a0016a41286a290300370300200641f0016a41286a2010370300200641f0016a41306a200f37030020064180026a20083703002006200e37038802200620113703a802200620043703f001200620033703f8010b200641f0016a41106a21090240427f200420087c2208200820045422072003200e7c2007ad7c220420035420042003511b22071b427f200420071b844200520d00200641f0056a41206a200941206a290300370300200641f0056a41186a200941186a290300370300200641f0056a41106a200941106a290300370300200641f0056a41086a200941086a290300370300200620092903003703f00541dbb4c600ad4280808080b00184210341838c1c21010c040b418de6c300ad4280808080e00084100122072900002103200641b8056a41086a200741086a290000370300200620033703b8052007102f41f0e8c600ad4280808080f00084100122072900002103200641b0046a41086a200741086a290000370300200620033703b0042007102f4120102d2207450d0520072001290000370000200741186a200141186a290000370000200741106a200141106a290000370000200741086a200141086a2900003700002007ad42808080808004841003220a2900002103200a41086a2900002104200a41106a2900002108200641f0076a41186a2212200a41186a290000370300200641f0076a41106a22132008370300200641f0076a41086a2004370300200620033703f007200a102f2007102f41c000102d2207450d05200720062903b805370000200720062903b004370010200720062903f007370020200741086a200641b8056a41086a290300370000200741186a200641b0046a41086a290300370000200741286a200641f0076a41086a290300370000200741306a2013290300370000200741386a2012290300370000200641b0046a200710f60220062903b004211142002103200642003703b004200641f8046a280200211220062d00fc0421130240024020114201510d0020064180056a41306a420037030020064180056a41286a420037030020064180056a41206a420037030020064198056a420037030020064190056a420037030020064180056a41086a42003703002006420037038005420021044200210e42002108420021140c010b200641b0046a41386a290300210f200641b0046a41306a2903002110200641b0046a41206a2903002104200641b0046a41186a2903002103200641b0046a41c0006a290300211420062903c004210820062903b804210e20064180056a41206a200641b0046a41286a29030037030020064180056a41286a201037030020064180056a41306a200f37030020064190056a200337030020062004370398052006200e3703800520062008370388050b200641086a41086a2903002210200420032006290308221556200420105620042010511b220a1b211620152003200a1b210f0240024020062d001f4101470d002009210a2006290380022217200f7c2218201754221920064188026a290300221a20167c2019ad7c2217201a542017201a511b450d010c030b200641f0016a210a20062903f0012217200f7c22182017542219200641f0016a41086a290300221a20167c2019ad7c2217201a542017201a511b0d020b200a2018370300200a201737030820064180056a41186a200420167d2003200f54ad7d37030020062003200f7d37039005200641b8056a41186a20064190056a220a41086a2903002217370300200641b8056a41206a2219200a41106a290300370300200641e0056a221b200a41186a290300370300200641e8056a221c200a41206a2903003703002006200a29030022183703c8052006200e3703b805200620083703c005427f200e20037c22032003200e54220a200820047c200aad7c220320085420032008511b220a1b427f2003200a1b84211a02400240427f200e20187c22032003200e54220a200820177c200aad7c220320085420032008511b220a1b2204428080e983b1de16544100427f2003200a1b2203501b0d00200641b8056a41106a2903002103201c2903002104201b29030021172019290300211820062903c005211d20062903b805211e4201211f20062903d00521200c010b4200211f02402004200384500d0020042003109a01200641a8086a2003370300200641a0086a2004370300200641f0076a41086a41013a0000200641f9076a200129000037000020064181086a200141086a29000037000020064189086a200141106a29000037000020064191086a200141186a290000370000200641033a00f00741c8e1ca004100200641f0076a108c010b0b2015200f542119201a50211b200641d8046a2018370300200641e0046a2017370300200641c0046a201d370300200641e8046a2004370300200641c8046a2003370300200620203703d004200620143703f0042006201e3703b8044100210a2006201341002011420151221c1b3a00fc04200620124100201c1b3602f8042006201f4201512212ad3703b0040240024020120d002007ad428080808080088410054101210a0c010b200641c0003602f407200620073602f007200641b8046a200641f0076a1090030b201020167d21032019ad2104201bad21162007102f02400240024020114201510d00200a0d004103210a200641f0066a21070c010b2011420152200a410173720d014104210a200641f0056a21070b200741046a200a3a0000200741003a0000200741056a20012900003700002007410d6a200141086a290000370000200741156a200141106a2900003700002007411d6a200141186a29000037000041c8e1ca0041002007108c010b200320047d21102015200f7d2103410021072016500d02200641a8086a2008370300200641a0086a200e37030041002107200641f0076a41086a41003a0000200641f9076a200129000037000020064181086a200141086a29000037000020064189086a200141106a29000037000020064191086a200141186a290000370000200641033a00f00741c8e1ca004100200641f0076a108c010c020b02402005450d00200641f0076a2001108d0220064188086a290300210b200629038008210820004100360200200041106a42002004200b7d2003200854ad7d220b200320087d2208200356200b200456200b2004511b22011b370300200041086a4200200820011b3703000c040b200620033703f005200620043703f805200620013602b003200641f0066a2001200641f0056a200641b0036a10960120064190076a29030021032006290388072104024020062903f0064201520d0020062903f8062108200641a8086a200641f0066a41106a290300370300200641a0086a2008370300200641f0076a41086a41003a0000200641f9076a200129000037000020064181086a200141086a29000037000020064189086a200141106a29000037000020064191086a200141186a290000370000200641033a00f00741c8e1ca004100200641f0076a108c010b200041106a2003370300200041086a2004370300200041003602000c030b2007102f4191ccc700ad4280808080800184210342002110410121070b200641f0016a41086a290300210420062903f001210820062903a802210e200641f0056a41206a220a200941206a290300370300200641f0056a41186a2212200941186a290300370300200641f0056a41106a2213200941106a290300370300200641f0056a41086a2219200941086a290300370300200620092903003703f00541838c08210120070d00200641f0066a41186a2019290300220f370300200641f0066a41206a201329030037030020064198076a22072012290300370300200641a0076a2209200a290300370300200620062903f005221137038007200620083703f006200620043703f80602400240427f200820117c2211201120085422012004200f7c2001ad7c220820045420082004511b22011b2204428080e983b1de16544100427f200820011b2208501b0d0020064180076a2903002104200929030021082007290300210f20064190076a290300211120062903f806211520062903f00621164201211720062903880721140c010b4200211702402004200884500d0020042008109a01200641a8086a2008370300200641a0086a2004370300200641f0076a41086a41013a0000200641f9076a200229000037000020064181086a200241086a29000037000020064189086a200241106a29000037000020064191086a200241186a290000370000200641033a00f00741c8e1ca004100200641f0076a108c010b0b200641c8016a2011370300200641d0016a200f370300200641b0016a2015370300200641d8016a2008370300200641b8016a2004370300200620143703c0012006200e3703e001200620163703a801410021012006200d4100200b42015122071b3a00ec012006200c410020071b3602e801200620174201512207ad3703a0010240024020070d002005ad42808080808008841005410121010c010b200641c0003602f407200620053602f007200641a8016a200641f0076a1090030b2005102f024002400240200b4201510d0020010d0041032105200641b0036a21010c010b200b4201522001410173720d0141042105200641b0026a21010b200141046a20053a0000200141003a0000200141056a20022900003700002001410d6a200241086a290000370000200141156a200241106a2900003700002001411d6a200241186a29000037000041c8e1ca0041002001108c010b200041106a2010370300200041086a2003370300200041003602000c010b2005102f200041086a200337020020002001360204200041013602000b200641f0086a24000f0b1036000ba80d08027f017e017f027e027f097e037f067e230041f0026b2204240020032802002105418de6c300ad4280808080e00084100122032900002106200441386a41086a200341086a290000370300200420063703382003102f41f0e8c600ad4280808080f00084100122032900002106200441f0006a41086a200341086a290000370300200420063703702003102f02404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100322072900002106200741086a2900002108200741106a2900002109200441f0016a41186a220a200741186a290000370300200441f0016a41106a220b2009370300200441f0016a41086a2008370300200420063703f0012007102f2003102f41c000102d2203450d002003200429033837000020032004290370370010200320042903f001370020200341086a200441386a41086a290300370000200341186a200441f0006a41086a290300370000200341286a200441f0016a41086a290300370000200341306a200b290300370000200341386a200a290300370000200441f0006a200310f6022004290370210c4200210920044200370370200441b8016a280200210720042d00bc01210a02400240200c4201510d00200441306a4200370300200441286a4200370300200441206a4200370300200441186a4200370300200441106a4200370300200441086a4200370300200442003703004200210d42002108420021064200210e0c010b200441f0006a41386a290300210f200441f0006a41306a2903002110200441f0006a41206a290300210d200441f0006a41186a2903002109200441f0006a41c0006a290300210e200429038001210620042903782108200441206a200441f0006a41286a290300370300200441286a2010370300200441306a200f370300200441106a20093703002004200d37031820042008370300200420063703080b200441186a200d200241086a2903002210200d20092002290300221156200d201056200d2010511b22021b22127d20092011200920021b220f54ad7d221337030020042009200f7d2214370310200441386a41186a2013370300200441386a41206a2215200441206a290300370300200441386a41286a2216200441286a290300370300200441386a41306a2217200441306a2903003703002004201437034820042008370338200420063703402011200f542102427f200820097c22092009200854220b2006200d7c200bad7c220920065420092006511b220b1b427f2009200b1b84211802400240427f200820147c22092009200854220b200620137c200bad7c220920065420092006511b220b1b220d428080e983b1de16544100427f2009200b1b2213501b0d00200441c8006a290300210d2017290300211320162903002114201529030021192004290340211a2004290338211b420121092004290350211c0c010b420021090240200d201384500d00200d2013109a01200441a8026a2013370300200441a0026a200d370300200441f0016a41086a41013a0000200441f9016a200529000037000020044181026a200541086a29000037000020044189026a200541106a29000037000020044191026a200541186a290000370000200441033a00f00141c8e1ca004100200441f0016a108c010b0b201020127d21102002ad211d201850210220044198016a2019370300200441a0016a201437030020044180016a201a370300200441a8016a201337030020044188016a200d3703002004201c370390012004200e3703b0012004201b3703782004200a4100200c42015122051b3a00bc0120042007410020051b3602b801200420094201512207ad3703700240024020070d002003ad428080808080088410050c010b200441c0003602f401200420033602f001200441f8006a200441f0016a1090030b2010201d7d210d2002ad21102011200f7d21112003102f20094201522103024002400240200c4201510d0020030d0041032107200441f0016a21030c010b200c4201522003410173720d0141042107200441f0006a21030b200341046a20073a0000200341003a0000200341056a20012900003700002003410d6a200141086a290000370000200341156a200141106a2900003700002003411d6a200141186a29000037000041c8e1ca0041002003108c010b2000200f3703182000200837030820002010370300200041306a200d370300200041286a2011370300200041206a2012370300200041106a2006370300200441f0026a24000f0b1036000be20508017f017e047f017e017f017e037f017e230041e0016b22022400200241186a20002001109b01200241186a41106a2903002101200229032021000240024020022903182203a7450d00200241e0006a41f4c7c40010b402200241e0006a2000200110b502200241f8006a2001370300200241e0006a41106a2000370300200241e8006a41063a00002002410c3a006041c8e1ca004100200241e0006a108c010c010b2003500d00200241e0006a41186a22044200370300200241e0006a41106a22054200370300200241e0006a41086a220642003703002002420037036041e7a2ca00ad42808080808001842203100122072900002108200241d0006a41086a2209200741086a290000370300200220083703502007102f200620092903003703002002200229035037036041ecb5c600ad4280808080d00184220810012207290000210a2009200741086a2900003703002002200a3703502007102f20052002290350220a370300200241306a41086a220b2006290300370300200241306a41106a220c200a370300200241306a41186a220d2009290300370300200220022903603703302002200241306a4120109c01200241106a290300210a2002290308210e200228020021072004420037030020054200370300200642003703002002420037036020031001220429000021032009200441086a290000370300200220033703502004102f200620092903003703002002200229035037036020081001220429000021032009200441086a290000370300200220033703502004102f200520022903502203370300200b2006290300370300200c2003370300200d20092903003703002002200229036037033020024200200a420020071b220320017d200e420020071b2201200054ad7d2208200120007d2200200156200820035620082003511b22091b37036820024200200020091b370360200241306aad4280808080800484200241e0006aad428080808080028410040b200241e0016a24000bb33103077f037e017f230041d0006b220624000240024002402002410c6a280200200241106a28020010092207417f460d00410c102d22080d010c020b10c001000b20082007360208200842818080801037020002400240024002404101450d002008410141016a3602004101417e460d00200841014102723602004104102d2209450d04200920083602002008280208210a4103102d220b450d04200b41026a41002d00d2bc4a3a0000200b41002f00d0bc4a3b00004106102d220c450d04200c41046a41002f009593463b0000200c410028009193463600004120102d2207450d042007200a36021c2007410136021820074286808080e0003702102007200c36020c20074283808080303702042007200b36020020082008280200417f6a220b3602000240200b0d002008280208100a20082008280204417f6a220b360204200b0d002008102f0b4103102d220b450d04200b41026a41002d00d2bc4a3a0000200b41002f00d0bc4a3b00004103102d220c450d04200c41026a41002d00d5bc4a3a0000200c41002f00d3bc4a3b00002007412041c00010312207450d042007410c36023c2007410036023820074283808080303702302007200c36022c20074283808080303702242007200b3602204103102d220b450d04200b41026a41002d00d2bc4a3a0000200b41002f00d0bc4a3b0000410f102d220c450d04200c41076a41002900b0944a370000200c41002900a9944a370000200741c00041800110312207450d042007410d36025c200741003602582007428f808080f0013702502007200c36024c20074283808080303702442007200b3602404103102d220b450d04200b41026a41002d00d2bc4a3a0000200b41002f00d0bc4a3b0000410f102d220c450d04200c41076a41002900bf944a370000200c41002900b8944a3700002007410e36027c200741003602782007428f808080f0013702702007200c36026c20074283808080303702642007200b3602604103102d220b450d04200b41026a41002d00d2bc4a3a0000200b41002f00d0bc4a3b00004108102d220c450d04200c42e5f0d1fbb5ac98b6ec00370000200741800141800210312207450d042007410f36029c012007410036029801200742888080808001370290012007200c36028c012007428380808030370284012007200b360280014103102d220b450d04200b41026a41002d00d2bc4a3a0000200b41002f00d0bc4a3b0000410f102d220c450d04200c41076a41002900d6944a370000200c41002900cf944a370000200741103602bc01200741003602b8012007428f808080f0013702b0012007200c3602ac0120074283808080303702a4012007200b3602a0014103102d220b450d04200b41026a41002d00d2bc4a3a0000200b41002f00d0bc4a3b0000410a102d220c450d04200c41086a41002f00e6944a3b0000200c41002900de944a370000200741113602dc01200741003602d8012007428a808080a0013702d0012007200c3602cc0120074283808080303702c4012007200b3602c0014103102d220b450d04200b41026a41002d00d2bc4a3a0000200b41002f00d0bc4a3b0000410a102d220c450d04200c41086a41002f00f0944a3b0000200c41002900e8944a370000200741123602fc01200741003602f8012007428a808080a0013702f0012007200c3602ec0120074283808080303702e4012007200b3602e0014103102d220b450d04200b41026a41002d00d2bc4a3a0000200b41002f00d0bc4a3b0000410b102d220c450d04200c41076a41002800f9944a360000200c41002900f2944a370000200741800241800410312207450d042007411336029c0220074100360298022007428b808080b001370290022007200c36028c022007428380808030370284022007200b360280024103102d220b450d04200b41026a41002d00d2bc4a3a0000200b41002f00d0bc4a3b0000410d102d220c450d04200c41056a4100290082954a370000200c41002900fd944a370000200741143602bc02200741003602b8022007428d808080d0013702b0022007200c3602ac0220074283808080303702a4022007200b3602a0024103102d220b450d04200b41026a41002d00d2bc4a3a0000200b41002f00d0bc4a3b0000410c102d220c450d04200c41086a4100280092954a360000200c410029008a954a370000200741153602dc02200741003602d8022007428c808080c0013702d0022007200c3602cc0220074283808080303702c4022007200b3602c0024103102d220b450d04200b41026a41002d00d2bc4a3a0000200b41002f00d0bc4a3b0000410b102d220c450d04200c41076a410028009d954a360000200c4100290096954a370000200741163602fc02200741003602f8022007428b808080b0013702f0022007200c3602ec0220074283808080303702e4022007200b3602e0024103102d220c450d04200c41026a41002d00d2bc4a3a0000200c41002f00d0bc4a3b00004115102d220b450d04200b410d6a41002900ae954a370000200b41086a41002900a9954a370000200b41002900a1954a3700002007411736029c03200741003602980320074295808080d002370290032007200b36028c032007428380808030370284032007200c360280034103102d220b450d04200b41026a41002d00d2bc4a3a0000200b41002f00d0bc4a3b0000410a102d220c450d04200c41086a41002f00be954a3b0000200c41002900b6954a370000200741183602bc03200741003602b8032007428a808080a0013702b0032007200c3602ac0320074283808080303702a4032007200b3602a0034103102d220b450d04200b41026a41002d00d2bc4a3a0000200b41002f00d0bc4a3b00004107102d220c450d04200c41036a41002800c3954a360000200c41002800c0954a360000200741193602dc03200741003602d80320074287808080f0003702d0032007200c3602cc0320074283808080303702c4032007200b3602c0034103102d220c450d04200c41026a41002d00d2bc4a3a0000200c41002f00d0bc4a3b00004113102d220b450d04200b410f6a41002800d6954a360000200b41086a41002900cf954a370000200b41002900c7954a3700002007411a3602fc03200741003602f80320074293808080b0023702f0032007200b3602ec0320074283808080303702e4032007200c3602e0034103102d220c450d04200c41026a41002d00d2bc4a3a0000200c41002f00d0bc4a3b00004115102d220b450d04200b410d6a41002900e7954a370000200b41086a41002900e2954a370000200b41002900da954a37000020074180044180081031220a450d04200a411b36029c04200a410036029804200a4295808080d00237029004200a200b36028c04200a42838080803037028404200a200c360280044103102d220b450d04200b41026a41002d00d2bc4a3a0000200b41002f00d0bc4a3b00004111102d2207450d04200741106a41002d00ff954a3a0000200741086a41002900f7954a370000200741002900ef954a370000200a411c3602bc04200a41003602b804200a429180808090023702b004200a20073602ac04200a4283808080303702a404200a200b3602a0044103102d2207450d04200741026a41002d00d2bc4a3a0000200741002f00d0bc4a3b0000410e102d220b450d04200b41066a4100290086964a370000200b4100290080964a370000200a411d3602dc04200a41003602d804200a428e808080e0013702d004200a200b3602cc04200a4283808080303702c404200a20073602c0044103102d2207450d04200741026a41002d00d2bc4a3a0000200741002f00d0bc4a3b00004110102d220b450d04200b41086a4100290096964a370000200b410029008e964a370000200a411e3602fc04200a41003602f804200a429080808080023702f004200a200b3602ec04200a4283808080303702e404200a20073602e0044103102d2207450d04200741026a41002d00d2bc4a3a0000200741002f00d0bc4a3b00004110102d220b450d04200b41086a41002900a6964a370000200b410029009e964a370000200a411f36029c05200a410036029805200a4290808080800237029005200a200b36028c05200a42838080803037028405200a2007360280054103102d220b450d04200b41026a41002d00d2bc4a3a0000200b41002f00d0bc4a3b00004111102d2207450d04200741106a41002d00be964a3a0000200741086a41002900b6964a370000200741002900ae964a370000200a41203602bc05200a41003602b805200a429180808090023702b005200a20073602ac05200a4283808080303702a405200a200b3602a0054103102d220b450d04200b41026a41002d00d2bc4a3a0000200b41002f00d0bc4a3b00004111102d2207450d04200741106a41002d00cf964a3a0000200741086a41002900c7964a370000200741002900bf964a370000200a41213602dc05200a41003602d805200a429180808090023702d005200a20073602cc05200a4283808080303702c405200a200b3602c0054103102d220b450d04200b41026a41002d00d2bc4a3a0000200b41002f00d0bc4a3b00004116102d2207450d042007410e6a41002900de964a370000200741086a41002900d8964a370000200741002900d0964a370000200a41223602fc05200a41003602f805200a4296808080e0023702f005200a20073602ec05200a4283808080303702e405200a200b3602e0054103102d220b450d04200b41026a41002d00d2bc4a3a0000200b41002f00d0bc4a3b00004112102d2207450d04200741106a41002f00f6964a3b0000200741086a41002900ee964a370000200741002900e6964a370000200a412336029c06200a410036029806200a4292808080a00237029006200a200736028c06200a42838080803037028406200a200b360280064103102d2207450d04200741026a41002d00d2bc4a3a0000200741002f00d0bc4a3b0000410b102d220b450d04200b41076a41002800ff964a360000200b41002900f8964a370000200a41243602bc06200a41003602b806200a428b808080b0013702b006200a200b3602ac06200a4283808080303702a406200a20073602a0064103102d2207450d04200741026a41002d00d2bc4a3a0000200741002f00d0bc4a3b00004110102d220b450d04200b41086a410029008b974a370000200b4100290083974a370000200a41253602dc06200a41003602d806200a429080808080023702d006200a200b3602cc06200a4283808080303702c406200a20073602c0064103102d220b450d04200b41026a41002d00d2bc4a3a0000200b41002f00d0bc4a3b00004117102d2207450d042007410f6a41002900a2974a370000200741086a410029009b974a37000020074100290093974a370000200a41263602fc06200a41003602f806200a4297808080f0023702f006200a20073602ec06200a4283808080303702e406200a200b3602e006200641086a410c6a200441086a2802003602002006200336020820064100360224200620053602202006200836021c2006200429020037020c20062001280200360218200241146a350200210d2002411c6a350200210e418407102d2207450d04200642840737024420062007360240411c200641c0006a1069200a4180076a2105200a2108034020082802002104200841086a2802002207200641c0006a1069024002402006280244220c2006280248220b6b2007490d002006280240210c0c010b200b20076a2201200b490d03200c41017422032001200320014b1b22014100480d0302400240200c0d002001102d210c0c010b2006280240200c20011031210c0b200c450d06200620013602442006200c3602400b2006200b20076a360248200c200b6a2004200710e8061a2008410c6a2802002103200841146a280200220c200641c0006a1069024002402006280244220b200628024822016b200c490d00200628024021070c010b2001200c6a22072001490d03200b41017422042007200420074b1b22044100480d0302400240200b0d002004102d21070c010b2006280240200b2004103121070b2007450d0620062004360244200620073602402004210b0b20062001200c6a2204360248200720016a2003200c10e8061a02400240200841186a2802004101460d0002400240200b2004460d00200b210c0c010b200b41016a220c200b490d05200b4101742201200c2001200c4b1b220c4100480d0502400240200b0d00200c102d21070c010b2007200b200c103121070b2007450d082006200c360244200620073602400b2006200441016a220b360248200720046a41013a000020062008411c6a2802002204360238200641386a21010c010b02400240200b2004460d00200b210c0c010b200b41016a220c200b490d04200b4101742201200c2001200c4b1b220c4100480d0402400240200b0d00200c102d21070c010b2007200b200c103121070b2007450d072006200c360244200620073602400b2006200441016a220b360248200720046a41023a000020062008411c6a2802002204360238200641386a21010b0240200c200b6b41034b0d00200b41046a2204200b490d03200c41017422032004200320044b1b22044100480d0302400240200c0d002004102d21070c010b2007200c2004103121070b2007450d062006200436024420062007360240200128020021040b2006200b41046a3602482007200b6a2004360000200841206a22082005470d000b2006280244210402400240024002400240024002404127200e422086200d84200635024842208620062802402205ad84200641086a100b220341036a220741024b0d004100210c20070e03010002010b4104102d220c450d0a410021070340200920076a280200220828020041016a220b41014d0d072008200b360200200c20076a2008360200200741046a22074104470d000b02402004450d002005102f0b2002350204210d2002350200210e4104102d2208450d0a20064204370244200620083602404100200641c0006a10692006350248210f200628024421022006280240210b410a10332208450d0a2003200d422086200e84200f422086200bad842008410a200641086a100c41036a221041034b0d024101210120100e0404020203040b4102210c0b41012101024020040d000c080b2005102f0c070b41d5cfca00412841f8b4ca001039000b2006410936023c410121012006200841016a36023820082d0000221041014b0d01410421040240024020100e020100010b200641c0006a200641386a10dd01200628024022044104460d02200628024421050b410021010b2008102f2002450d03200b102f0c030b2008102f024020020d000c030b200b102f0c020b00000b1038000b2003100d200c210803402008280200220b200b280200417f6a36020002402008280200220b2802000d00200b280208100a2008280200220b200b280204417f6a3602042008280200220b2802040d00200b102f0b200841046a21082007417c6a22070d000b200c102f4102210c0b200641146a290200210d200641106a2802002108200628021c2107200628020c210b02400240024002400240024002400240024020062802244101460d0020010d04200441044b0d0320040e050203030301020b2006412c6a2802002104200641286a280200220c0d0541002101200041003a0004200041186a200d3e0200200041146a2008360200200041106a200b3602002000410c6a4128360200200041086a41c3f5c600360200410121030c060b2000200b36020420004100360200200041106a41003a00002000410c6a4100360200200041086a20083602000c030b2000200b36020420004100360200200041106a20053a00002000410c6a200d3e0200200041086a20083602000c020b200041003a000420004101360200200041186a200d3e0200200041146a2008360200200041106a200b3602002000410c6a4111360200200041086a41ebf5c6003602000c010b200041003a0004200da721040240200c0d00200041fcf5c60036020820004101360200200041186a2004360200200041146a2008360200200041106a200b3602002000410c6a41103602000c010b2000418cf6c60036020820004101360200200041186a2004360200200041146a2008360200200041106a200b3602002000410c6a41213602000b20072007280200417f6a220836020020080d022007280208100a20072007280204417f6a220836020420080d022007102f0c020b200641306a28020021012000200c36020441002103200041106a41003a00002000410c6a2001360200200041086a2004360200410121012008450d00200b102f0b2000200336020020072007280200417f6a2208360200024020080d002007280208100a20072007280204417f6a220836020420080d002007102f0b200c452001720d002004450d00200c102f0b4100210803400240200a20086a220741046a280200450d002007280200102f0b0240200741106a280200450d002007410c6a280200102f0b200841206a2208418007470d000b200a102f200928020022072007280200417f6a3602000240200928020022072802000d002007280208100a200928020022072007280204417f6a360204200928020022072802040d002007102f0b2009102f200641d0006a24000f0b1036000b120041c3c4c10041fc0041f8b4ca001039000b7201027f230041106b22042400024002402003450d002002280200450d010b4182bfc60041f40341f8c2c6001055000b2001280210210320012802182105200228020421022004410036020020042002360204200041054104200520032001411c6a200410f5041b360200200441106a24000bf80e03077f017e017f230041b00c6b2204240002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d0220034103460d0320022802300d0320022802042105200241246a2802002106200241346a280200210302400240200241146a2802002207450d004105210220012802002802182802402802b4012003490d010b200441186a4200370300200441106a4200370300200441086a42003703002004420037030020012802182108200128021021092004428180808080043703b00141052102200820092001411c6a220a200441b0016a10f5040d00024002402001280214280208200520044120101e41026a220841024b0d0020080e03020001020b41d5cfca0041284180d0ca001039000b0240024020070d004100210a0c010b2001280210210820012802182109200441013602b001200420033602b40120092008200a200441b0016a10f5040d012003417f4c0d060240024020030d004101210a02402001280214280208200641014100101e41026a220341024b0d004200210b20030e03040002040b41d5cfca0041284180d0ca001039000b20031033220a450d090240024020012802142802082006200a2003101e41026a220841024b0d002003ad210b20080e03010002010b41d5cfca0041284180d0ca001039000b200a102f0c020b200b422086200b84210b0b20012802002102200441206a41186a2203200441186a290300370300200441206a41106a2201200441106a290300370300200441206a41086a2208200441086a290300370300200420042903003703202002280218210502400240200a450d0020052802402802b401200b422088a74f0d0041ec90c7002102200ba7450d01200a102f0c010b200441c0006a41186a2003290300370300200441c0006a41106a2001290300370300200441c0006a41086a20082903003703002004200429032037034020052802180d072005417f36021820044198016a200541e8006a29000037030020044190016a200541e0006a29000037030020044188016a200541d8006a2900003703002004200529005037038001024002402005411c6a220c28020022094190bdc600460d00200541206a28020021060c010b41002106200441d0096a410041e00210e7061a200441b0016a410041a00810e7061a41880b102d2209450d09200941003b010620094100360200200941086a200441d0096a41e00210e8061a200941e8026a200441b0016a41a00810e8061a200541206a41003602002005200936021c0b024003400240024020092f010622070d00410021070c010b20074105742102200941086a21034100210103402002450d01024020044180016a2003412010ea0622080d00410121020c040b200241606a2102200141016a2101200341206a21032008417f4a0d000b2001417f6a21070b02402006450d002006417f6a2106200920074102746a41880b6a28020021090c010b0b200441e0006a41186a20044180016a41186a290300370300200441e0006a41106a20044180016a41106a290300370300200441e0006a41086a20044180016a41086a29030037030020042004290380013703604100210620072101410021020b0240024020020d00200441ec096a200441e0006a41086a290300370200200441d0096a41246a200441e0006a41106a290300370200200441fc096a200441e0006a41186a290300370200200420013602dc092004200c3602d809200420093602d409200420063602d009200420042903603702e4092004200541246a3602e009200441d0016a20042903a001370300200441d8016a200441a0016a41086a290300370300200441e4016a4200370200200442003703c801200442003703b00120044190bdc6003602e001200441003a00ec01200441ed016a200429008001370000200441f5016a20044180016a41086a290000370000200441fd016a20044180016a41106a29000037000020044185026a20044180016a41186a290000370000200441003a008d02200441d0096a200441b0016a10970221020c010b200441c8016a4200370300200441c4016a4190bdc600360200200441003602d001200441003602c001200442003703b80120044190bdc6003602b401200441003602b0012009200141e0006c6a41e8026a2102200441b0016a1090020b200441b0016a41186a200441c0006a41186a290300370300200441b0016a41106a200441c0006a41106a290300370300200441b0016a41086a200441c0006a41086a290300370300200420042903403703b0012004200b370284012004200a36028001200441d0096a200241306a200441b0016a20044180016a109802024020042802d009450d0020042802d4092202450d00200441d8096a280200450d002002102f0b2005200528021841016a360218410021020b4105410420021b21020b20002002360200200441b00c6a24000f0b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b103d000b41c3c5ca004110200441b0016a41dc90c70041e4c5ca00103e000b1036000be60201027f230041306b2204240002402003450d0020022802000d0020022802042105200441186a4200370300200441106a4200370300200441086a420037030020044200370300200128021821022001280210210320044281808080800437032002400240200220032001411c6a200441206a10f5040d00024002402001280214280208200520044120101e41026a220241024b0d0020020e03020001020b41d5cfca0041284180d0ca001039000b200441206a2001280200280218220241186a200241d0006a2002410c6a4100200228020c1b200410f604024002402004280220450d00200141046a21020240200141086a280200450d002002280200102f0b20022004290320370200200241086a200441206a41086a280200360200410021010c010b2001410c6a4100360200410121010b20004100360200200020013602040c010b200041053602000b200441306a24000f0b4182bfc60041f40341f8c2c6001055000b800d04037f017e077f047e230041a0016b22042400024002400240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802204101470d0220034103460d0320022802300d0320034104460d0420022802400d0420034105460d0520022802500d0520034106460d0620022802600d0620022802042105200241146a2802002106200241286a2903002107200241346a2802002108200241c4006a2802002109200241d4006a280200210a200241e4006a280200210b2001280210210220012802182103200441013602482004200636024c200320022001411c6a220c200441c8006a10f5040d092006417f4c0d070240024002400240024020060d004101210d02402001280214280208200541014100101e41026a220241024b0d00200141146a210520020e030f00020f0b41d5cfca0041284180d0ca001039000b20061033220d450d01024020012802142802082005200d2006101e41026a220241024b0d00200141146a210520020e030d00010d0b41d5cfca0041284180d0ca001039000b41002102200441003a0068024002400240034020062002460d01200441c8006a20026a200d20026a2d00003a00002004200241016a22033a00682003210220034120470d000b200441f0006a41186a2202200441c8006a41186a290300370300200441f0006a41106a2203200441c8006a41106a290300370300200441f0006a41086a220e200441c8006a41086a2903003703002004200429034837037002402006450d00200d102f0b200441086a41086a200e290300370300200441086a41106a2003290300370300200441086a41186a2002290300370300200420042903703703082001280210210220012802182103200441013602482004200936024c20032002200c200441c8006a10f5040d0f2009417f4c0d0d20090d022005280200280208200841014100101e41026a220241024b0d0120020e030f010f0f0b0240200241ff0171450d00200441003a00680b2006450d0e200d102f0c0e0b41d5cfca0041284180d0ca001039000b200910332202450d0002402005280200280208200820022009101e41026a220341024b0d0020030e03030002030b41d5cfca0041284180d0ca001039000b1036000b2009410f4d0d00200241086a290000210f200229000021102002102f2001280210210220012802182103200441013602482004200b36024c20032002200c200441c8006a10f5040d0a200141046a2203200b10f203024002402001280214280208200a20012802042001410c6a280200101e41026a220241024b0d0020020e030c00010c0b41d5cfca0041284180d0ca001039000b200128020c21052001410036020c200141086a28020021062001280204210d20014201370204200128021822022903082211211202400240024002402007500d002007211220112007540d010b2002201120127d37030820022903102107200441f0006a41186a200241186a29030037030020042012370378200420123703702004200737038001200128020041186a2802002109200441c8006a41186a200441086a41186a290300370300200441c8006a41106a200441086a41106a290300370300200441c8006a41086a200441086a41086a29030037030020042004290308370348200420053602980120042006360294012004200d36029001200441286a2009200441c8006a2010200f200441f0006a20044190016a1086024101210c0240024020042802284101460d00200441286a410472210d200441286a41106a2d00002105200441346a2802002109200441306a28020021064100210c0c010b200441286a41106a210d200441286a41186a28020021092004413c6a2802002106410021050b200d280200210d2002200429037820022903087c370308200141086a2802002102200c450d012002450d002003280200102f0b2003200d3602004180022105410021090c010b02402002450d002003280200102f0b2003200d3602000b2001200936020c200141086a200636020020004100360200200020053602040c0b0b2002102f0c090b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b103d000b200d102f0b200041053602000b200441a0016a24000bb60f04037f017e077f047e230041b0016b2204240002400240024002400240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802204101470d0220034103460d0320022802300d0320034104460d0420022802400d0420034105460d0520022802500d0520034106460d0620022802600d0620022802042105200241146a2802002106200241286a2903002107200241346a2802002108200241c4006a2802002109200241d4006a280200210a200241e4006a280200210b2001280210210220012802182103200441013602782004200636027c200320022001411c6a220c200441f8006a10f5040d0b2006417f4c0d070240024020060d004101210d02402001280214280208200541014100101e41026a220241024b0d00200141146a210520020e030e00020e0b41d5cfca0041284180d0ca001039000b20061033220d450d09024020012802142802082005200d2006101e41026a220241024b0d00200141146a210520020e030c00010c0b41d5cfca0041284180d0ca001039000b41002102200441003a009801024002400240034020062002460d01200441f8006a20026a200d20026a2d00003a00002004200241016a22033a0098012003210220034120470d000b200441d8006a41186a2202200441f8006a41186a290300370300200441d8006a41106a2203200441f8006a41106a290300370300200441d8006a41086a220e200441f8006a41086a2903003703002004200429037837035802402006450d00200d102f0b200441086a200e290300370300200441106a2003290300370300200441186a2002290300370300200420042903583703002001280210210220012802182103200441013602782004200936027c20032002200c200441f8006a10f5040d0e2009417f4c0d0a20090d022005280200280208200841014100101e41026a220241024b0d0120020e030e010e0e0b0240200241ff0171450d00200441003a0098010b2006450d0d200d102f0c0d0b41d5cfca0041284180d0ca001039000b200910332202450d080240024002402005280200280208200820022009101e41026a220341024b0d0020030e03020001020b41d5cfca0041284180d0ca001039000b2009410f4d0d00200241086a290000210f200229000021102002102f2001280210210220012802182103200441013602782004200b36027c20032002200c200441f8006a10f5040d0c200141046a220d200b10f203024002402001280214280208200a20012802042001410c6a280200101e41026a220241024b0d0020020e030e00010e0b41d5cfca0041284180d0ca001039000b2001410c6a2202280200210520024100360200200141086a28020021032001280204210620014201370204200128021822022903082211211202400240024002402007500d002007211220112007540d010b2002201120127d37030820022903102107200441d8006a41186a200241186a290300370300200420123703602004201237035820042007370368200128020041186a2802002109200420053602282004200336022420042006360220200441f8006a20092010200f200441d8006a2004200441206a109e02410121050240024020042802784101460d00200441206a41086a200441f8006a41186a290300370300200441206a41106a20044198016a2802003602002004200441f8006a41106a290300370320200441a8016a2d00002108200441a0016a280200210c2004419c016a280200210920044184016a280200210a200441f8006a41086a280200210341002105200428027c21060c010b200441f8006a41186a280200210a2004418c016a280200210320044188016a2802002106410021080b2002200429036020022903087c370308200441c0006a41086a2202200441206a41086a290300370300200441c0006a41106a220b200441206a41106a280200360200200420042903203703402005450d01200141086a280200450d00200d280200102f0b200120063602042001410c6a4100360200200141086a200336020041800221020c010b200441f8006a41106a200b280200360200200441f8006a41086a2002290300370300200420042903403703780240200141086a280200450d00200d280200102f0b200120093602044100210d2001410c6a4100360200200141086a200c360200200841ff017122020d000240200c411f4b0d00200c410174220d4120200d41204b1b220d4100480d0c02400240200c0d00200d102d21090c010b2009200c200d103121090b2009450d0b20012009360204200141086a200d3602002001410c6a280200210d0b2001410c6a200d41206a3602002009200d6a2201200a36000820012003360004200120063600002001200429037837000c200141146a20044180016a2903003700002001411c6a20044188016a2802003600000b20004100360200200020023602040c0d0b2002102f0c0b0b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b103d000b1036000b1038000b200d102f0b200041053602000b200441b0016a24000b830301047f230041106b22042400024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200241146a2802002102200128021021032001280218210620044103360200200420023602040240200620032001411c6a2207200410f5040d0020012802102103200128021821062004410136020020042002360204200620032007200410f5040d00200141046a200210f203024002402001280214280208200520012802042001410c6a280200101e41026a220241024b0d0020020e03020001020b41d5cfca0041284180d0ca001039000b200128020c21022001410036020c200141086a280200210320012802042106200142013702040240200128021c450d00200141206a2802002207450d00200141246a280200450d002007102f0b2001410136021c200141286a2002360200200141246a2003360200200141206a20063602000b20004105360200200441106a24000f0b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000bec0101037f410021042001410c6a4100360200200128020021050240024002400240200141086a28020022064120490d00200128020421060c010b200641017422044120200441204b1b22044100480d020240024020060d002004102d21060c010b200128020420062004103121060b2006450d0120012006360204200141086a20043602002001410c6a28020021040b2001410c6a200441206a360200200620046a220141186a200541386a290000370000200141106a200541306a290000370000200141086a200541286a29000037000020012005290020370000200041043602000f0b1036000b1038000bf20101037f410021042001410c6a4100360200200128020028021821050240024002400240200141086a28020022064120490d00200128020421060c010b200641017422044120200441204b1b22044100480d020240024020060d002004102d21060c010b200128020420062004103121060b2006450d0120012006360204200141086a20043602002001410c6a28020021040b2001410c6a200441206a360200200620046a220141186a200541e8006a290000370000200141106a200541e0006a290000370000200141086a200541d8006a29000037000020012005290050370000200041043602000f0b1036000b1038000bd10102027f027e410021042001410c6a41003602002001280218220541186a2903002106200529031021070240024002400240200141086a28020022054110490d00200128020421050c010b200541017422044110200441104b1b22044100480d020240024020050d002004102d21050c010b200128020420052004103121050b2005450d0120012005360204200141086a20043602002001410c6a28020021040b2001410c6a200441106a360200200520046a2201200637000820012007370000200041043602000f0b1036000b1038000bbe0103017f017e017f410021042001410c6a4100360200200128021829030821050240024002400240200141086a28020022064108490d00200128020421060c010b200641017422044108200441084b1b22044100480d020240024020060d002004102d21060c010b200128020420062004103121060b2006450d0120012006360204200141086a20043602002001410c6a28020021040b2001410c6a200441086a360200200620046a2005370000200041043602000f0b1036000b1038000bc704020b7f027e230041206b220424002001410c6a41003602000240024002402001280200280218220528021841016a220641004c0d00200541d0006a2107200520063602182005411c6a2108200541206a28020021090240024002400340024002402008280200220a2f0106220b0d004100210c0c010b200b4105742108200a41086a210d417f210c0340024020080d00200b210c0c020b200c41016a210c2007200d412010ea06220e450d03200841606a2108200d41206a210d200e417f4a0d000b0b2009450d022009417f6a2109200a200c4102746a41880b6a21080c000b0b200a200c41e0006c6a220841c5036a310000200841e8026a290300220f200f50220d1ba7450d004200200841f8026a290300200d1b210f4200200841f0026a290300200d1b21100c010b200441086a200541286a28020020072005412c6a28020028021c110300200441106a290300210f20052802182106200429030821100b20052006417f6a36021802400240200141086a280200220d2001410c6a28020022086b4110490d002001280204210d0c010b200841106a220c2008490d03200d4101742208200c2008200c4b1b22084100480d0302400240200d0d002008102d210d0c010b2001280204200d20081031210d0b200d450d022001200d360204200141086a20083602002001410c6a28020021080b2001410c6a200841106a360200200d20086a2208200f3700082008201037000020004104360200200441206a24000f0b41c6c4ca004118200441186a41cc90c70041f0c4ca00103e000b1036000b1038000bd10102027f027e410021042001410c6a41003602002001280200220541086a2903002106200529030021070240024002400240200141086a28020022054110490d00200128020421050c010b200541017422044110200441104b1b22044100480d020240024020050d002004102d21050c010b200128020420052004103121050b2005450d0120012005360204200141086a20043602002001410c6a28020021040b2001410c6a200441106a360200200520046a2201200637000820012007370000200041043602000f0b1036000b1038000bfd0401057f230041206b22042400024002400240024002402003450d0020022802000d0020034101460d0120022802100d01410521050240200241146a2802002203200128021022062802744b0d0020022802042107200128021821022004410136020020042003360204200220062001411c6a200410f5040d002003417f4c0d0302400240024020030d004101210602402001280214280208200741014100101e41026a220241024b0d0020020e03040002040b41d5cfca0041284180d0ca001039000b200310332206450d0602402001280214280208200720062003101e41026a220241024b0d0020020e03020001020b41d5cfca0041284180d0ca001039000b2001410c6a2205410036020020042006200310ac044120102d2202450d0520022004290300370000200241186a200441186a290300370000200241106a200441106a290300370000200241086a200441086a29030037000002400240200141086a2802002207200528020022056b4120490d00200128020421070c010b200541206a22082005490d07200741017422052008200520084b1b22054100480d070240024020070d002005102d21070c010b200128020420072005103121070b2007450d0620012007360204200141086a20053602002001410c6a28020021050b2001410c6a200541206a360200200720056a220141186a200241186a290000370000200141106a200241106a290000370000200141086a200241086a290000370000200120022900003700002002102f410421052003450d010b2006102f0b20002005360200200441206a24000f0b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b103d000b1036000b1038000bbe0103017f017e017f410021042001410c6a4100360200200128020029031021050240024002400240200141086a28020022064108490d00200128020421060c010b200641017422044108200441084b1b22044100480d020240024020060d002004102d21060c010b200128020420062004103121060b2006450d0120012006360204200141086a20043602002001410c6a28020021040b2001410c6a200441086a360200200620046a2005370000200041043602000f0b1036000b1038000bd90102027f027e410021042001410c6a4100360200200128020028021828024022054188016a290300210620052903800121070240024002400240200141086a28020022054110490d00200128020421050c010b200541017422044110200441104b1b22044100480d020240024020050d002004102d21050c010b200128020420052004103121050b2005450d0120012005360204200141086a20043602002001410c6a28020021040b2001410c6a200441106a360200200520046a2201200637000820012007370000200041043602000f0b1036000b1038000bd90102027f027e410021042001410c6a4100360200200128020028021828024022054198016a290300210620052903900121070240024002400240200141086a28020022054110490d00200128020421050c010b200541017422044110200441104b1b22044100480d020240024020050d002004102d21050c010b200128020420052004103121050b2005450d0120012005360204200141086a20043602002001410c6a28020021040b2001410c6a200441106a360200200520046a2201200637000820012007370000200041043602000f0b1036000b1038000bb70803047f047e017f230041f0096b22042400024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200241146a28020021022001280210210320012802182106200441013602b807200420023602bc07024002400240200620032001411c6a2207200441b8076a10f5040d002002417f4c0d0502400240024020020d004101210302402001280214280208200541014100101e41026a220641024b0d0020060e03040002040b41d5cfca0041284180d0ca001039000b200210332203450d0802402001280214280208200520032002101e41026a220641024b0d0020060e03020001020b41d5cfca0041284180d0ca001039000b2004200236022c20042003360228200441b8076a200441286a10b302024020042802b8072206411b460d0020044188056a200441b8076a41047241ac0210e8061a02402002450d002003102f0b200441d8026a20044188056a41ac0210e8061a20042006360228200441286a410472200441d8026a41ac0210e8061a200441003602c007200442013703b807200441286a200441b8076a10910120042802c0072103024020042802bc07450d0020042802b807102f0b02400240200128021822022903102208200241186a29030022098450450d00420021080c010b200441186a2003ad42004280c8afa025420010ed06200441086a2004290318220a4280a094a58d1d7c220b200441186a41086a290300200b200a54ad7c2008200910ee062004290308427f200441086a41086a290300501b21080b20012802102103200441043602b807200420083703c007200220032007200441b8076a10f504450d03200441286a108e01410521020c040b2002450d010b2003102f0b410521020c010b2001280200210220044188056a200441286a41b00210e8061a200441e0026a22032002280218220241d8006a290000370300200441e8026a2206200241e0006a290000370300200441f0026a2205200241e8006a290000370300200420022900503703d802200441bf076a20044188056a41b00210e8061a02402002413c6a2802002201200241386a280200470d00200141016a22072001490d062001410174220c2007200c20074b1bad42d8027e2208422088a70d062008a722074100480d060240024020010d002007102d21010c010b2002280234200141d8026c2007103121010b2001450d0520022001360234200241386a200741d8026e360200200228023c21010b2002280234200141d8026c6a220141013a0000200120042903d802370001200141096a2003290300370000200141116a2006290300370000200141196a2005290300370000200141216a200441b8076a41b70210e8061a2002200228023c41016a36023c410421020b20002002360200200441f0096a24000f0b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b103d000b1036000b1038000b8016040c7f027e047f017e230041a0036b22042400024002400240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d0220034103460d0320022802300d0320034104460d0420022802400d0420034105460d0520022802500d0520034106460d0620022802600d0620034107460d0720022802700d0720022802042105200241146a2802002106200241246a2802002107200241346a2802002108200241c4006a2802002109200241d4006a280200210a200241e4006a280200210b200241f4006a280200210c2001280210210220012802182103200441013602a801200420063602ac01024002400240024002400240024002400240200320022001411c6a220d200441a8016a10f5040d002006417f4c0d1102400240024020060d004101210e02402001280214280208200541014100101e41026a220241024b0d00200141146a210520020e03040002040b41d5cfca0041284180d0ca001039000b20061033220e450d14024020012802142802082005200e2006101e41026a220241024b0d00200141146a210520020e03020001020b41d5cfca0041284180d0ca001039000b41002102200441003a00c8010240034020062002460d01200441a8016a20026a200e20026a2d00003a00002004200241016a22033a00c8012003210220034120470d000b20044180036a41086a2202200441a8016a41086a29030037030020044180036a41106a2203200441a8016a41106a29030037030020044180036a41186a220f200441a8016a41186a290300370300200420042903a8013703800302402006450d00200e102f0b200441086a41086a2002290300370300200441086a41106a2003290300370300200441086a41186a200f29030037030020042004290380033703082001280210210220012802182103200441013602a801200420083602ac0120032002200d200441a8016a10f5040d072008417f4c0d1320080d04410121062005280200280208200741014100101e41026a220241024b0d0320020e03070305070b0240200241ff0171450d00200441003a00c8010b2006450d010b200e102f0b200441c8006a41186a20044180036a41186a290300370300200441c8006a41106a20044180036a41106a290300370300200441c8006a41086a20044180036a41086a2903003703002004200429038003370348410521020c070b41d5cfca0041284180d0ca001039000b200810332206450d0f02402005280200280208200720062008101e41026a220241024b0d0020020e03020001020b41d5cfca0041284180d0ca001039000b41002102200441003a00c8010240034020082002460d01200441a8016a20026a200620026a2d00003a00002004200241016a22033a00c8012003210220034120470d000b20044180036a41086a2202200441a8016a41086a29030037030020044180036a41106a2203200441a8016a41106a29030037030020044180036a41186a220e200441a8016a41186a290300370300200420042903a8013703800302402008450d002006102f0b200441286a41086a2002290300370300200441286a41106a2003290300370300200441286a41186a200e29030037030020042004290380033703282001280210210320012802182106200441013602a8012004200a3602ac014105210220062003200d200441a8016a10f5040d05200a417f4c0d0e200a0d042005280200280208200941014100101e41026a220341024b0d0320030e03050305050b0240200241ff0171450d00200441003a00c8010b2008450d010b2006102f0b410521020c020b41d5cfca0041284180d0ca001039000b200a10332203450d0a024002400240200528020028020820092003200a101e41026a220641024b0d0020060e03010002010b41d5cfca0041284180d0ca001039000b2003102f0c010b0240200a410f4b0d002003102f0c010b200341086a2900002110200329000021112003102f02400240200c0d004101210e41002106410021080c010b20044180036a41186a210320044180036a41106a210720044180036a41086a210a410021124100210241002106410021084101210e03402003420037030020074200370300200a42003703002004420037038003200128021821092001280210210f2004428180808080043703a801024002402009200f200d200441a8016a10f5040d00024002402005280200280208200b20026a220920044180036a4120101e41026a220f41024b0d00200f0e03020001020b41d5cfca0041284180d0ca001039000b200441a8016a41186a22132003290300370300200441a8016a41106a22142007290300370300200441a8016a41086a2215200a29030037030020042004290380033703a801024020062008470d002012200641016a2208201220084b1b220841ffffff3f712008470d10200841057422084100480d100240024020060d002008102d210e0c010b200e200220081031210e0b200e450d0f200841057621080b200e20026a220f20042903a801370000200f41186a2013290300370000200f41106a2014290300370000200f41086a2015290300370000200941206a20094f0d010b410521022008450d03200e102f0c030b201241026a2112200241206a2102200c200641016a2206470d000b0b20012802002802182103200441e8006a41086a200441086a41086a290300370300200441e8006a41106a2201200441086a41106a290300370300200441e8006a41186a2205200441086a41186a29030037030020044188016a41086a200341d8006a29000037030020044188016a41106a220d200341e0006a29000037030020044188016a41186a2207200341e8006a29000037030020042004290308370368200420032900503703880120044180036a41186a220a200441286a41186a29030037030020044180036a41106a2209200441286a41106a29030037030020044180036a41086a200441286a41086a290300370300200420042903283703800302402003413c6a2802002202200341386a280200470d00200241016a220c2002490d0c2002410174220b200c200b200c4b1bad42d8027e2216422088a70d0c2016a7220c4100480d0c0240024020020d00200c102d21020c010b2003280234200241d8026c200c103121020b2002450d0b20032002360234200341386a200c41d8026e360200200328023c21020b2003280234200241d8026c6a220241023a0000200220042903880137000120022004290368370021200241096a20044188016a41086a290300370000200241116a200d290300370000200241196a2007290300370000200241296a200441e8006a41086a290300370000200241316a2001290300370000200241396a20052903003700002002200e360064200220083600682002200636006c20022011370370200241f8006a20103703002002200429038003370041200241c9006a20044180036a41086a290300370000200241d1006a2009290300370000200241d9006a200a290300370000200220042f00483b0061200241e3006a200441c8006a41026a2d00003a000020024180016a200441a8016a41d80110e8061a2003200328023c41016a36023c410421020b20002002360200200441a0036a24000f0b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b103d000b1036000b1038000b16002000410036020020002001410c6a2802003602040ba50201067f230041106b220424000240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d024105210302402001410c6a2802002205200241146a2802002206490d00200520066b200241246a2802002205470d00200228020421072001280204210820012802182102200128021021092004410236020020042005360204200220092001411c6a200410f5040d000240024020012802142802082007200820066a2005101f41026a220241024b0d0020020e03020001020b41d5cfca00412841e4d0ca001039000b410421030b20002003360200200441106a24000f0b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000bee0101047f230041106b22042400024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200241146a280200210220012802102106200128021821072004410136020020042002360204410521030240200720062001411c6a200410f5040d00200141046a200210f203024002402001280214280208200520012802042001410c6a280200101e41026a220141024b0d0020010e03020001020b41d5cfca0041284180d0ca001039000b410421030b20002003360200200441106a24000f0b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000bef0903077f017e027f230041d0026b220424000240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d0220034103460d0320022802300d03200241246a2802002105200241346a2802002106024002400240200241146a2802002203450d00200228020421072001280210210820012802182109200441013602082004200336020c41052102200920082001411c6a200441086a10f5040d0b2003417f4c0d07200310332208450d08024002402001280214280208200720082003101e41026a220941024b0d0020090e03010003010b41d5cfca0041284180d0ca001039000b2008102f0c0b0b41012107410021094100210a0c010b200420033602dc01200420083602d801200441086a200441d8016a109803200429020c210b200428020821072008102f2007450d09200ba7210a2001280210280264200b422088a72209490d080b20072009410041202009676b10e003024020094102490d00200721022009210303402002200241206a2208412010ea06450d09200821022003417f6a220341024f0d000b0b2001280210210220012802182103200441013602082004200636020c200320022001411c6a2208200441086a10f5040d072006417f4c0d040240024020060d004101210c02402001280214280208200541014100101e41026a220241024b0d0020020e030a00020a0b41d5cfca0041284180d0ca001039000b20061033220c450d060240024020012802142802082005200c2006101e41026a220241024b0d0020020e03010002010b41d5cfca0041284180d0ca001039000b200c102f0c080b2001280210210220012802182103200441086a41086a20063602002004200936020c200441053602080240200320022008200441086a10f504450d002006450d08200c102f0c080b200441a8026a41086a2001280200280218220341d8006a290000370300200441b8026a2208200341e0006a290000370300200441c0026a2201200341e8006a290000370300200420032900503703a80202402003413c6a2802002202200341386a280200470d00200241016a22052002490d072002410174220d2005200d20054b1bad42d8027e220b422088a70d07200ba722054100480d070240024020020d002005102d21020c010b2003280234200241d8026c2005103121020b2002450d0620032002360234200341386a200541d8026e360200200328023c21020b2003280234200241d8026c6a220241003a0000200220042f00cd023b0001200241073a00102002200936000c2002200a36000820022007360004200220042903a802370011200241036a200441cd026a41026a2d00003a0000200241196a200441b0026a290300370000200241216a2008290300370000200241296a20012903003700002002200c360034200220063600382002200636003c200220042f00a5023b0031200241336a200441a5026a41026a2d00003a0000200241c0006a200441d8016a41c80010e8061a20024188016a200441086a41d00110e8061a2003200328023c41016a36023c410421020c080b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b103d000b1036000b1038000b41052102200a450d002007102f0b20002002360200200441d0026a24000bfe0903047f027e037f230041d00b6b22042400024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200241146a280200210220012802102106200128021821072004410136025020042002360254410521030240200720062001411c6a200441d0006a10f5040d002002417f4c0d03024020020d0002402001280214280208200541014100101e41026a220241024b0d0020020e03020002020b41d5cfca0041284180d0ca001039000b200210332206450d050240024002402001280214280208200520062002101e41026a220741024b0d0020070e03010002010b41d5cfca0041284180d0ca001039000b2006102f0c010b02402002410f4b0d002006102f0c010b200641086a2900002108200629000021092006102f2001280200280218220a2802180d04200a417f360218200441386a200a41e8006a290000370300200441306a200a41e0006a290000370300200441206a41086a200a41d8006a2900003703002004200a29005037032002400240200a411c6a220b28020022074190bdc600460d00200a41206a280200210c0c010b4100210c200441f0086a410041e00210e7061a200441d0006a410041a00810e7061a41880b102d2207450d06200741003b010620074100360200200741086a200441f0086a41e00210e8061a200741e8026a200441d0006a41a00810e8061a200a41206a4100360200200a200736021c0b024003400240024020072f010622050d00410021050c010b20054105742102200741086a21014100210303402002450d010240200441206a2001412010ea0622060d00410121020c040b200241606a2102200341016a2103200141206a21012006417f4a0d000b2003417f6a21050b0240200c450d00200c417f6a210c200720054102746a41880b6a28020021070c010b0b200441186a200441206a41186a290300370300200441106a200441206a41106a290300370300200441086a200441206a41086a290300370300200420042903203703004100210c20052103410021020b0240024020020d002004418c096a200441086a290300370200200441f0086a41246a200441106a2903003702002004419c096a200441186a290300370200200420033602fc082004200b3602f808200420073602f4082004200c3602f00820042004290300370284092004200a41246a36028009200441f0006a2004290340370300200441f8006a200441c0006a41086a29030037030020044184016a4200370200200442003703682004420037035020044190bdc60036028001200441003a008c012004418d016a200429002037000020044195016a200441206a41086a2900003700002004419d016a200441206a41106a290000370000200441a5016a200441206a41186a290000370000200441003a00ad01200441f0086a200441d0006a10970221020c010b200441e8006a4200370300200441e4006a4190bdc60036020020044100360270200441003602602004420037035820044190bdc600360254200441003602502007200341e0006c6a41e8026a2102200441d0006a1090020b200241286a2008370300200241206a200937030020024201370318200a200a28021841016a360218410421030b20002003360200200441d00b6a24000f0b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b103d000b41c3c5ca004110200441d0006a41dc90c70041e4c5ca00103e000b1036000b9f0203037f027e027f230041206b220424002001410c6a22054100360200200441086a2001280200280218220641186a200641d0006a10f704200441086a41106a290300210720042802082106200429031021080240024002400240200141086a2802002209200528020022056b4110490d00200128020421090c010b200541106a220a2005490d0220094101742205200a2005200a4b1b22054100480d020240024020090d002005102d21090c010b200128020420092005103121090b2009450d0120012009360204200141086a20053602002001410c6a28020021050b2001410c6a200541106a360200200920056a22012007427f20061b37000820012008427f20061b37000020004104360200200441206a24000f0b1036000b1038000bdb0201047f230041106b220424000240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200241146a280200210220012802102106200128021821072004410136020020042002360204410521030240200720062001411c6a200410f5040d002002417f4c0d0302400240024020020d004101210602402001280214280208200541014100101e41026a220141024b0d0020010e03040002040b41d5cfca0041284180d0ca001039000b0240200210332206450d0002402001280214280208200520062002101e41026a220141024b0d0020010e03030002030b41d5cfca0041284180d0ca001039000b1036000b2004200620021066024020042802000d00200429020410080b410421032002450d010b2006102f0b20002003360200200441106a24000f0b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000b103d000bba0101037f410021042001410c6a4100360200200128020028021c21050240024002400240200141086a28020022064104490d00200128020421060c010b200641017422044104200441044b1b22044100480d020240024020060d002004102d21060c010b200128020420062004103121060b2006450d0120012006360204200141086a20043602002001410c6a28020021040b2001410c6a200441046a360200200620046a2005360000200041043602000f0b1036000b1038000bab0302037f017e230041106b22042400024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200241146a28020021022001280210210320012802182106200441013602002004200236020402400240200620032001411c6a200410f5040d00200141046a2203200210f203024002402001280214280208200520012802042001410c6a280200101e41026a220241024b0d0020020e03020001020b41d5cfca0041284180d0ca001039000b200135020c21072001410036020c200141086a220628020021052001280204210220014201370204200420074220862002ad8410021073200628020021060240024020042802000d0002402006450d002003280200102f0b2001410036020c20012002360204200141086a2005360200410121010c010b02402006450d002003280200102f0b20032004290300370200200341086a200441086a280200360200410021012005450d002002102f0b20004100360200200020013602040c010b200041053602000b200441106a24000f0b4182bfc60041f40341f8c2c6001055000b4182bfc60041f40341f8c2c6001055000baa05020a7f017e230041c0006b220424002004200136020c2004200041c8e1ca0020011b3602082004200441086a10e60102400240024002400240024020042802000d0020042802042205200428020c4104762201200120054b1b22064104742201417f4c0d030240024020060d00410821070c010b2001102d2207450d050b024002402005450d00200441206a4104722108410021094100210a410021000340200441206a200441086a10dd01200441306a41086a220b200841086a280200360200200420082902003703302004280220220c4104460d02200041016a2101200441106a41086a220d200b28020036020020042004290330370310024020002006470d0020092001200920014b1b220b41ffffffff0071200b470d09200b410474220b4100480d090240024020000d00200b102d21070c010b2007200a200b103121070b2007450d08200b41047621060b2007200a6a2200200c360200200041046a20042903103702002000410c6a200d280200360200200941026a2109200a41106a210a2001210020052001470d000b0b2007450d01200441206a2002200720052003110400200428022021004101102d2201450d0520044281808080103702342004200136023020004105470d02200141013a00004201210e0c030b2006450d002007102f0b41a4dcc10041f000200441206a41f0dbc1004194ddc100103e000b200141003a000020014101410210312101024020004104470d002001450d03200141003a00012004428280808020370234200420013602304202210e0c010b2001450d02200141013a0001200442828080802037023420042001360230200441206a200441306a10e7012004350238210e200428023021010b2001ad422086200e84210e02402006450d002007102f0b200441c0006a2400200e0f0b103d000b1036000b1038000bd90202047f017e02400240024002400240024020012802042202450d00200128020022032d0000210420012002417f6a22053602042001200341016a360200200441034b0d0520040e0401020304010b200041043602000f0b024020054104490d00200041003602002003280001210420012002417b6a3602042001200341056a360200200020043602040f0b200041043602000f0b024020054108490d0020004101360200200329000121062001200241776a3602042001200341096a360200200041086a20063703000f0b200041043602000f0b024020054104490d00200041023602002003280001210420012002417b6a3602042001200341056a360200200020043602040f0b200041043602000f0b024020054108490d0020004103360200200329000121062001200241776a3602042001200341096a360200200041086a20063703000f0b200041043602000f0b200041043602000b130020004103360204200041c0c5c1003602000b13002000410c360204200041e8c7c1003602000b6301017f230041206b2202240020022000280200360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a41d8dbc100200241086a103c2101200241206a240020010b4d01017f230041206b22002400200041146a410136020020004201370204200041b4d8c9003602002000410436021c200041fcdbc9003602182000200041186a360210200041e8d8c9001043000bac0503047f017e017f230041e0006b220224000240024020012802004111460d00200041003a0000200041306a41013a0000200041286a4200370300200041206a4280808080c000370300200041186a4204370300200041106a427f370300200041086a42003703000c010b024002400240024002400240200141086a2d00000e06050402010004050b200141c8006a21030c020b200141d0006a21030c010b200141186a21030b200241306a41186a4200370300200241306a41106a22044200370300200241306a41086a220142003703002002420037033041aa97ca00ad42808080808001841001220529000021062001200541086a290000370300200220063703302005102f41b297ca00ad4280808080800184100122052900002106200241d0006a41086a2207200541086a290000370300200220063703502005102f200420022903502206370300200241106a41086a2001290300370300200241106a41106a2006370300200241106a41186a2007290300370300200220022903303703102002200241106a10e301024020032903004280ade20420022903087d4280ade20420022802001b560d00200041003a0000200041306a41013a0000200041286a4200370300200041206a4280808080c000370300200041186a4204370300200041106a427f370300200041086a42003703000c030b200041800c3b0001200041013a0000200041036a41003a00000c020b200041003a0000200041306a41013a0000200041286a4200370300200041206a4280808080c000370300200041186a4204370300200041106a427f370300200041086a42003703000c010b200241c4006a410136020020024201370234200241b4d8c9003602302002410436021420024180dcc1003602102002200241106a360240200241306a41e8d8c9001043000b200241e0006a24000b980204017f017e017f017e230041d0006b220224002002412036020420022001360200200241086a2001ad42808080808004841002107302400240200228020822010d00420021030c010b200228020c210402400240200241086a41086a2802004108490d0020012900002105420121030c010b20024100360220200242013703182002410b36022c200220023602282002200241186a360234200241cc006a41013602002002420137023c200241b885c7003602382002200241286a360248200241346a41d8dbc100200241386a103c1a200235022042208620023502188410080240200228021c450d002002280218102f0b420021030b2004450d002001102f0b2000200537030820002003370300200241d0006a24000b820303037f017e017f02402001450d00034020002802e40121002001417f6a22010d000b0b02402002450d0041002103034002400240200320002f01064f0d0041002104200021010c010b41002104034002400240024020004190bdc600460d00200028020022010d0141002103410021010c020b41edb3ca00412841f8b4ca001039000b200441016a210420002f010421030b2000102f20012100200320012f01064f0d000b0b200341016a210520012003410c6c6a220041e4006a2902002106200041e0006a28020021070240024020040d0020012100200521030c010b200120054102746a41e4016a2802002100410021032004417f6a2201450d00034020002802e40121002001417f6a22010d000b0b2007450d012002417f6a210202402006a7450d002007102f0b20020d000b0b0240024020004190bdc600460d00200028020021012000102f2001450d00034020014190bdc600460d02200128020021002001102f2000210120000d000b0b0f0b41edb3ca00412841f8b4ca001039000bf00401077f20022003106902402001450d00034020002802940321002001417f6a22010d000b0b0240024002402002450d00200341046a210441002105034002400240200520002f0106490d0041002106024003400240200028020022010d0041002107410021010c020b200641016a210620002f0104210720012100200720012f01064f0d000b0b200741016a2105024020060d00200121000c020b200120054102746a4194036a2802002100410021052006417f6a2206450d01034020002802940321002006417f6a22060d000c020b0b2000210120052107200541016a21050b0240024020042802002208200341086a220628020022096b4120490d00200328020021080c010b200941206a220a2009490d0420084101742209200a2009200a4b1b22094100480d040240024020080d002009102d21080c010b200328020020082009103121080b2008450d032003200836020020042009360200200628020021090b2006200941206a360200200820096a220941186a200120074105746a41086a220841186a290000370000200941106a200841106a290000370000200941086a200841086a29000037000020092008290000370000200120074102746a41e8026a28020021090240024020042802002207200628020022016b4104490d00200328020021070c010b200141046a22082001490d04200741017422012008200120084b1b22014100480d040240024020070d002001102d21070c010b200328020020072001103121070b2007450d032003200736020020042001360200200628020021010b2006200141046a360200200720016a20093600002002417f6a22020d000b0b0f0b1036000b1038000bcf0201067f0240024020012802042202450d00200128020022032d0000210420012002417f6a2205360204410121062001200341016a3602000240200441037122074103460d0002400240024020070e03000102000b20044102762107410021060c040b41012106024020050d000c040b20032d0001210520012002417e6a3602042001200341026a3602002005410874200472220141ffff0371418002490d03200141fcff03714102762107410021060c030b20054103490d01200341036a2d0000210620032f0001210720012002417c6a3602042001200341046a3602002007200641107472410874200472220141808004492106200141027621070c020b0240200441034d0d000c020b20054104490d012003280001210720012002417b6a3602042001200341056a36020020074180808080044921060c010b410121060b20002007360204200020063602000bba0a02037f017e02400240024002400240024020002802000e0400010203000b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d05200241017422042003200420034b1b22044100480d050240024020020d002004102d21030c010b200128020020022004103121030b2003450d0420012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41003a00002000280204210302400240200141046a2802002202200428020022006b4104490d00200128020021020c010b200041046a22042000490d05200241017422002004200020044b1b22004100480d050240024020020d002000102d21020c010b200128020020022000103121020b2002450d0420012002360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200220006a20033600000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d04200241017422042003200420034b1b22044100480d040240024020020d002004102d21030c010b200128020020022004103121030b2003450d0320012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41013a00002000290308210502400240200141046a2802002202200428020022006b4108490d00200128020021020c010b200041086a22032000490d04200241017422002003200020034b1b22004100480d040240024020020d002000102d21020c010b200128020020022000103121020b2002450d0320012002360200200141046a2000360200200141086a28020021000b200141086a200041086a360200200220006a20053700000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d03200241017422042003200420034b1b22044100480d030240024020020d002004102d21030c010b200128020020022004103121030b2003450d0220012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41023a00002000280204210302400240200141046a2802002202200428020022006b4104490d00200128020021020c010b200041046a22042000490d03200241017422002004200020044b1b22004100480d030240024020020d002000102d21020c010b200128020020022000103121020b2002450d0220012002360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200220006a20033600000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d02200241017422042003200420034b1b22044100480d020240024020020d002004102d21030c010b200128020020022004103121030b2003450d0120012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41033a00002000290308210502400240200141046a2802002202200428020022006b4108490d00200128020021020c010b200041086a22032000490d02200241017422002003200020034b1b22004100480d020240024020020d002000102d21020c010b200128020020022000103121020b2002450d0120012002360200200141046a2000360200200141086a28020021000b200141086a200041086a360200200220006a20053700000f0b1036000b1038000bec0f05027f037e0d7f017e017f23004190016b2202240041aa97ca00ad4280808080800184100122032900002104200241106a41086a200341086a290000370300200220043703102003102f41cbcec100ad4280808080e00184100122032900002104200241206a41086a200341086a290000370300200220043703202003102f0240024002400240024002404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100322012900002104200141086a2900002105200141106a2900002106200241e8006a41186a2207200141186a290000370300200241e8006a41106a22082006370300200241e8006a41086a2005370300200220043703682001102f2003102f41c000102d2203450d00200320022903103700002003200229032037001020032002290368370020200341086a200241106a41086a2201290300370000200341186a200241206a41086a290300370000200341286a200241e8006a41086a290300370000200341306a2008290300370000200341386a2007290300370000200241c00036023420022003360230200241106a2003ad4280808080800884100210730240200228021022090d00410221010c060b2002280214210a20022001280200220736024c200220093602482007450d0320092d0000210120022007417f6a36024c2002200941016a360248200141014b0d03024002400240024020010e020001000b200241086a200241c8006a10e60120022802080d06200228024c220b200228020c2207490d062007417f4c0d040240024020070d00410121080c010b200710332208450d04200820022802482201200710e8061a2002200b20076b220b36024c2002200120076a3602480b2008450d06024002400240024002400240200b4104490d002002280248220c280000210d2002200b417c6a220e36024c2002200c41046a36024841002101200241003a008801417b210f02400340200e2001460d01200241e8006a20016a200c20016a221041046a2d00003a00002002200b200f6a36024c2002201041056a3602482002200141016a22113a008801200f417f6a210f2011210120114120470d000b2002200228006b360023200220022802683602202002200228022036025020022002280023360053200b20116b2201417c6a4110490d06200241f7006a2900002105200229006f2104200228007f210f200228008301211020022d008701210e2002200c20116a221241146a221336024820022001416c6a220c36024c200c4104490d042012410c6a2900002114201241046a29000021062013280000210c2002200141686a36024c2002201241186a2213360248200b41686a2011460d0520132d000021132002200141676a221536024c2002201241196a360248201341014b0d054100210b20130e020302030b0240200141ff0171450d00200241003a0088010b2007450d0c0c0b0b2007450d0b2008102f0c0b0b20154104490d02201241196a28000021112002200141636a36024c20022012411d6a3602484101210b0b2002200228005336006320022002280250360260200220022802603602382002200228006336003b200220022800593602402002200241dc006a28000036004341002101200721120c040b2007450d082008102f0c080b2007450d072008102f0c070b20070d050c060b41002101200241003a0088012007417f6a210d2007417e6a21070340200d2001460d02200241e8006a20016a200920016a220841016a2d00003a00002002200841026a3602482002200141016a22083a0088012002200736024c2007417f6a21072008210120084120470d000b2002200228006b3600232002200228026836022020022002280023360053200220022802203602502002200228025036026020022002280053360063200241f7006a2900002114200229006f2106200228007f2108200228008301211220022d008701210720022002280063360043200220022802603602402002200241dc006a28000036003b20022002280059360238410121010b2002200228004336005320022002280240360250200220022802383602602002200228003b3600630c050b200141ff0171450d03200241003a0088010c030b1036000b103d000b2008102f0b20024100360228200242013703202002410b3602542002200241306a3602502002200241206a360260200241fc006a41013602002002420137026c200241b885c7003602682002200241d0006a360278200241e0006a41d8dbc100200241e8006a103c1a2002350228422086200235022084100802402002280224450d002002280220102f0b410221010b200a450d002009102f0b200220022802503602682002200228005336006b20022002280260360220200220022800633600230240024020014102470d00200041023a00000c010b200020013a000020002002280268360001200041106a2014370000200041086a2006370000200041c3006a20053700002000413b6a2004370000200041046a200228006b360000200041306a20113600002000412c6a200b360000200041286a200c360000200041246a200d360000200041206a20073600002000411c6a2012360000200041186a2008360000200041346a2002280220360000200041376a2002280023360000200041cb006a200f360000200041cf006a2010360000200041d3006a200e3a00000b2003102f20024190016a24000b840603027f037e047f230041c0006b2202240041aa97ca00ad4280808080800184100122032900002104200241086a200341086a290000370300200220043703002003102f41cbcec100ad4280808080e00184100122032900002104200241106a41086a200341086a290000370300200220043703102003102f02404120102d2203450d0020032000290000370000200341186a200041186a290000370000200341106a200041106a290000370000200341086a200041086a2900003700002003ad4280808080800484100322002900002104200041086a2900002105200041106a2900002106200241206a41186a2207200041186a290000370300200241206a41106a22082006370300200241206a41086a2005370300200220043703202000102f2003102f41c000102d2203450d00200320022903003700002003200229031037001020032002290320370020200341086a200241086a290300370000200341186a200241106a41086a290300370000200341286a200241206a41086a290300370000200341306a2008290300370000200341386a2007290300370000200241003602282002420137032020012d000021074101102d21000240024020074101460d002000450d02200041003a0000200242818080801037022420022000360220200141086a200241206a10ea01200235022842208621042002280224452101200228022021000c010b2000450d01200041013a00002002428180808010370224200220003602204120102d2207450d0120072001290001370000200741186a2208200141196a290000370000200741106a2209200141116a290000370000200741086a220a200141096a29000037000020004101412110312200450d0120002007290000370001200041096a200a290000370000200041116a2009290000370000200041196a2008290000370000200242a18080809004370224200220003602202007102f410021014280808080900421040b2003ad428080808080088420042000ad841004024020010d002000102f0b2003102f200241c0006a24000f0b1036000bda0b02057f027e20002802102102200041186a2802002203200110690240024002400240200141046a2802002204200141086a28020022056b2003490d00200128020021040c010b200520036a22062005490d02200441017422052006200520064b1b22054100480d020240024020040d002005102d21040c010b200128020020042005103121040b2004450d0120012004360200200141046a2005360200200141086a28020021050b200141086a2206200520036a360200200420056a2002200310e8061a200028021c210402400240200141046a2802002205200628020022036b4104490d00200128020021050c010b200341046a22022003490d02200541017422032002200320024b1b22034100480d020240024020050d002003102d21050c010b200128020020052003103121050b2005450d0120012005360200200141046a2003360200200141086a28020021030b200141086a2202200341046a360200200520036a20043600004120102d2203450d002003200029002c370000200341186a200041c4006a290000370000200341106a2000413c6a290000370000200341086a200041346a29000037000002400240200141046a2802002204200228020022056b4120490d00200128020021040c010b200541206a22022005490d02200441017422052002200520024b1b22054100480d020240024020040d002005102d21040c010b200128020020042005103121040b2004450d0120012004360200200141046a2005360200200141086a28020021050b200141086a2202200541206a360200200420056a220541186a200341186a290000370000200541106a200341106a290000370000200541086a200341086a290000370000200520032900003700002003102f200041086a29030021072000290300210802400240200141046a2802002205200228020022036b4110490d00200128020021050c010b200341106a22042003490d02200541017422032004200320044b1b22034100480d020240024020050d002003102d21050c010b200128020020052003103121050b2005450d0120012005360200200141046a2003360200200141086a28020021030b200141086a2204200341106a360200200520036a22032007370008200320083700002000280220210202400240200141046a2802002205200428020022036b4104490d00200128020021050c010b200341046a22042003490d02200541017422032004200320044b1b22034100480d020240024020050d002003102d21050c010b200128020020052003103121050b2005450d0120012005360200200141046a2003360200200141086a28020021030b200141086a2204200341046a360200200520036a2002360000024020002802244101460d0002400240200141046a28020020042802002200460d00200128020021030c010b200041016a22032000490d03200041017422052003200520034b1b22054100480d030240024020000d002005102d21030c010b200128020020002005103121030b2003450d0220012003360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200320006a41003a00000f0b02400240200141046a28020020042802002203460d00200128020021050c010b200341016a22052003490d02200341017422042005200420054b1b22044100480d020240024020030d002004102d21050c010b200128020020032004103121050b2005450d0120012005360200200141046a2004360200200141086a28020021030b200141086a2204200341016a360200200520036a41013a00002000280228210502400240200141046a2802002203200428020022006b4104490d00200128020021030c010b200041046a22042000490d02200341017422002004200020044b1b22004100480d020240024020030d002000102d21030c010b200128020020032000103121030b2003450d0120012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20053600000f0b1036000b1038000ba00603027f037e057f230041c0006b2202240041aa97ca00ad4280808080800184100122032900002104200241086a200341086a290000370300200220043703002003102f41cbcec100ad4280808080e00184100122032900002104200241106a41086a200341086a290000370300200220043703102003102f02404120102d2203450d0020032000290000370000200341186a200041186a290000370000200341106a200041106a290000370000200341086a200041086a2900003700002003ad4280808080800484100322002900002104200041086a2900002105200041106a2900002106200241206a41186a2207200041186a290000370300200241206a41106a22082006370300200241206a41086a2005370300200220043703202000102f2003102f41c000102d2203450d00200320022903003700002003200229031037001020032002290320370020200341086a200241086a290300370000200341186a200241106a41086a290300370000200341286a200241206a41086a290300370000200341306a2008290300370000200341386a2007290300370000200241003602282002420137032020012d000021084101102d21000240024020084101460d002000450d02200041003a0000200242818080801037022420022000360220200141086a200241206a10ea01200235022842208621042002280224452107200228022021000c010b2000450d01200041013a00002002428180808010370224200220003602204120102d2207450d0120072001290001370000200741186a2209200141196a290000370000200741106a220a200141116a290000370000200741086a220b200141096a29000037000020004101412110312200450d0120002007290000370001200041096a200b290000370000200041116a200a290000370000200041196a2009290000370000200242a18080809004370224200220003602202007102f410021074280808080900421040b2003ad428080808080088420042000ad841004024020070d002000102f0b2003102f024020080d002001411c6a280200450d00200141186a280200102f0b200241c0006a24000f0b1036000bbc0303027f037e027f230041c0006b2201240041aa97ca00ad4280808080800184100122022900002103200141086a200241086a290000370300200120033703002002102f41cbcec100ad4280808080e00184100122022900002103200141106a41086a200241086a290000370300200120033703102002102f02404120102d2202450d0020022000290000370000200241186a200041186a290000370000200241106a200041106a290000370000200241086a200041086a2900003700002002ad4280808080800484100322002900002103200041086a2900002104200041106a2900002105200141206a41186a2206200041186a290000370300200141206a41106a22072005370300200141206a41086a2004370300200120033703202000102f2002102f41c000102d2202450d00200220012903003700002002200129031037001020022001290320370020200241086a200141086a290300370000200241186a200141106a41086a290300370000200241286a200141206a41086a290300370000200241306a2007290300370000200241386a20062903003700002002ad428080808080088410052002102f200141c0006a24000f0b1036000bab0502077f047e230041b0036b22032400200341186a200141186a290000370300200341106a200141106a290000370300200341086a200141086a29000037030020032001290000370300024002400240200028020022044190bdc600460d00200028020421050c010b41002105200341d0006a410041e00210e7061a200341c8006a22014100360200200341c0006a22064200370300200341206a41186a4200370300200341206a41106a4200370300200341206a41086a420037030020034200370320419403102d2204450d01200441003b010620044100360200200441086a200341d0006a41e00210e8061a20044190036a200128020036020020044188036a200629030037020020044180036a200341386a290300370200200441f8026a200341306a290300370200200441f0026a200341206a41086a290300370200200420032903203702e80220004100360204200020043602000b0240024003400240024020042f010622070d00410021080c010b20074105742101200441086a2106417f21080340024020010d00200721080c020b200841016a210820032006412010ea062209450d03200141606a2101200641206a21062009417f4a0d000b0b02402005450d002005417f6a2105200420084102746a4194036a28020021040c010b0b200341206a41186a200341186a290300220a370300200341206a41106a200341106a290300220b370300200341206a41086a200341086a290300220c37030020032003290300220d370320200341ec006a200c370200200341f4006a200b370200200341fc006a200a3702002003200836025c20032004360254200341003602502003200d370264200320003602582003200041086a360260200341d0006a200210ee011a0c010b200420084102746a41e8026a20023602000b200341b0036a24000f0b1036000beb0701087f23004190046b2202240020002802102203200328020041016a360200200241086a2203200041086a29020037030020022000290200370300200241306a41186a2000412c6a290000370300200241306a41106a200041246a290000370300200241306a41086a2000411c6a29000037030020022000290014370330200241d0006a2002200241306a2001107702400240024020022d00504101470d002003200241d9006a290000370300200241106a200241e1006a290000370300200241186a200241e9006a29000037030020022002290051370300200241d0006a412c6a280200210120024188016a280200210420024184016a280200210320024180016a2802002105200228028c012106200241f8006a28020022002802002207450d0120002f01042108200241f4006a2802002109200241d0006a410172210003402002200841ffff037136022c20022001360228200220073602242002200941016a360220200241306a41186a200241186a2201290300370300200241306a41106a200241106a2207290300370300200241306a41086a200241086a220829030037030020022002290300370330200241d0006a200241206a200241306a200520032004107820022d00504101470d032008200041086a2900003703002007200041106a2900003703002001200041186a29000037030020022000290000370300200228027c2101200228028801210420022802840121032002280280012105200228027822082802002207450d0220082f01042108200228027421090c000b0b200241d0006a41086a280200200241d0006a41106a2802004102746a41e8026a21060c010b200241d0006a410272410041be0310e7061a02400240024041c403102d2200450d0020004100360200200041046a200241d0006a41c00310e8061a200020012802002207360294032001200036020020012001280204220841016a360204200741003b010420072000360200200241d0006a41186a200241186a290300370300200241d0006a41106a200241106a290300370300200241d0006a41086a200241086a2903003703002002200229030037035020082004470d0120002f01062201410a4b0d02200020014105746a220441206a200241d0006a41186a290300370000200441186a200241d0006a41106a290300370000200441106a200241d0006a41086a290300370000200441086a2002290350370000200020014102746a41e8026a20053602002000200141016a22014102746a4194036a2003360200200020013b0106200320013b0104200320003602000c030b1036000b4196b3ca00413041f8b4ca001039000b41c6b3ca00412741f8b4ca001039000b20024190046a240020060bfc0707047f017e017f017e017f017e047f230041e0006b22022400200241306a41186a22034200370300200241306a41106a22044200370300200241306a41086a220542003703002002420037033041aa97ca00ad42808080808001842206100122072900002108200241d0006a41086a2209200741086a290000370300200220083703502007102f200520092903003703002002200229035037033041c997ca00ad4280808080e00184220810012207290000210a2009200741086a2900003703002002200a3703502007102f20042002290350220a370300200241106a41086a220b2005290300370300200241106a41106a220c200a370300200241106a41186a220d2009290300370300200220022903303703102002200241106a10e3012002280200210e2002290308210a2003420037030020044200370300200542003703002002420037033020061001220729000021062009200741086a290000370300200220063703502007102f200520092903003703002002200229035037033020081001220729000021062009200741086a290000370300200220063703502007102f200420022903502206370300200b2005290300370300200c2006370300200d2009290300370300200220022903303703102002200a42017c4201200e1b2206370330200241106aad4280808080800484200241306aad4280808080800184100402404120102d2209450d0020092001290000370000200941186a200141186a290000370000200941106a200141106a290000370000200941086a200141086a2900003700002009412041c00010312205450d00200520063700202005ad4280808080800584100322092900002106200941086a2900002108200941106a290000210a200241306a41186a200941186a290000370300200241306a41106a200a370300200241306a41086a2008370300200220063703302009102f4137102d2209450d00200942bac6a1cbc68dd9aff300370000200942f4dec98bf6ac999de400370008200941e5cc85ab073600102009413a3a0016200941ece8013b001420092002290330370017200920022f01383b001f2009200228013a360021200920022f013e3b0025200920022d00403a0027200920022d00413a0028200920022d00423a0029200920022d00433a002a200920022d00443a002b200920022d00453a002c200920022d00463a002d200920022d00473a002e200920022d00483a002f200920022d00493a0030200920022d004a3a0031200920022d004b3a0032200920022d004c3a0033200920022d004d3a0034200920022d004e3a0035200920022d004f3a0036200041ccddc10041a4ddc1006b410f6a36020820004137360204200020093602002005102f200241e0006a24000f0b1036000b130020004105360204200041acddc1003602000b3400200041aa97ca0036020420004100360200200041146a4107360200200041106a41b4efc100360200200041086a42083702000b3301017f02404110102d22020d001036000b2002420037000820024201370000200042908080808002370204200020023602000b2201017f230041106b22022400200241003602002000200210f401200241106a24000bff0201067f230041106b220224000240024002400240024002400240200128020022030d00410121040c010b0240200141086a28020041056a2204417f4c0d0020040d0120024100360208200242013703000c020b103d000b2004102d2205450d04200241003602082002200436020420022005360200024020030d00200541003a0000200241013602080c030b20040d010b4101102d2205450d0320024101360204200220053602000b200541013a000020024101360208200141086a2802002204200210690240024020022802042201200228020822056b2004490d00200228020021010c010b200520046a22062005490d02200141017422072006200720064b1b22064100480d020240024020010d002006102d21010c010b200228020020012006103121010b2001450d0320022006360204200220013602000b2002200520046a360208200120056a2003200410e8061a0b20002002290300370200200041086a200241086a280200360200200241106a24000f0b1038000b1036000bcc0101017f23004190016b22022400200241003a0078200242808084808002370368200242e4003703582002420137035020024201370348200242af0137034020024287013703382002420137033020024201370328200242013703202002420137031820024201370310200242013703082002420137030020024280808080c00037036020024280808180800437037020024100360288012002420137038001200220024180016a10f601200041086a200228028801360200200020022903800137020020024190016a24000bf41802047f017e200028026021020240024002400240200141046a2802002203200141086a28020022046b4104490d00200128020021030c010b200441046a22052004490d02200341017422042005200420054b1b22044100480d020240024020030d002004102d21030c010b200128020020032004103121030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2205200441046a360200200320046a20023600002000290300210602400240200141046a2802002203200528020022046b4108490d00200128020021030c010b200441086a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102d21030c010b200128020020032004103121030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290308210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102d21030c010b200128020020032004103121030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290310210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102d21030c010b200128020020032004103121030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290318210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102d21030c010b200128020020032004103121030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290320210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102d21030c010b200128020020032004103121030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290328210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102d21030c010b200128020020032004103121030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290330210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102d21030c010b200128020020032004103121030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290338210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102d21030c010b200128020020032004103121030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290340210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102d21030c010b200128020020032004103121030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290348210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102d21030c010b200128020020032004103121030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290350210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102d21030c010b200128020020032004103121030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290358210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102d21030c010b200128020020032004103121030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000280264210502400240200141046a2802002203200228020022046b4104490d00200128020021030c010b200441046a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102d21030c010b200128020020032004103121030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441046a360200200320046a20053600002000280268210502400240200141046a2802002203200228020022046b4104490d00200128020021030c010b200441046a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102d21030c010b200128020020032004103121030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441046a360200200320046a2005360000200028026c210502400240200141046a2802002203200228020022046b4104490d00200128020021030c010b200441046a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102d21030c010b200128020020032004103121030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441046a360200200320046a20053600002000280270210502400240200141046a2802002203200228020022046b4104490d00200128020021030c010b200441046a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102d21030c010b200128020020032004103121030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441046a360200200320046a200536000020002d0078210502400240200141046a28020020022802002204460d00200128020021030c010b200441016a22032004490d02200441017422022003200220034b1b22024100480d020240024020040d002002102d21030c010b200128020020042002103121030b2003450d0120012003360200200141046a2002360200200141086a28020021040b200141086a2202200441016a360200200320046a20053a00002000280274210302400240200141046a2802002204200228020022006b4104490d00200128020021040c010b200041046a22022000490d02200441017422002002200020024b1b22004100480d020240024020040d002000102d21040c010b200128020020042000103121040b2004450d0120012004360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200420006a20033600000f0b1036000b1038000b13002000410e360204200041bcf8c1003602000b2f01017f02404108102d22020d001036000b2000428880808080013702042000200236020020024280ade2043700000b2e01017f02404104102d22020d001036000b20004284808080c000370204200020023602002002418080013600000b2c01017f02404104102d22020d001036000b20004284808080c00037020420002002360200200241203600000b2d01017f02404108102d22020d001036000b20004288808080800137020420002002360200200242e8073700000b3801017f02404110102d22020d001036000b2002420037000820024280a094a58d1d370000200042908080808002370204200020023602000b3701017f02404110102d22020d001036000b2002420037000820024280c8afa025370000200042908080808002370204200020023602000b3a01017f02404110102d22020d001036000b20024200370008200242808086bdbacdd21a370000200042908080808002370204200020023602000b3b01017f02404110102d22020d001036000b200242003700082002428080a8ec85afd1b101370000200042908080808002370204200020023602000b3901017f02404110102d22020d001036000b200242003700082002428080e983b1de16370000200042908080808002370204200020023602000b2c01017f02404104102d22020d001036000b20004284808080c00037020420002002360200200241083600000b2c01017f02404104102d22020d001036000b20004284808080c00037020420002002360200200241023600000bd91f05047f027e097f017e157f230041d00d6b22072400200741186a41186a200141186a290000370300200741186a41106a200141106a290000370300200741186a41086a200141086a29000037030020072001290000370318200741386a41186a200241186a290000370300200741386a41106a200241106a290000370300200741386a41086a200241086a2900003703002007200229000037033820062802002108200628020421092006280208210a200741a0066a200741186a20051084020240024020072802a0064101470d00200020072902a40637020420004101360200200041186a4100360200200041106a42013702002000410c6a200741a0066a410c6a2802003602002009450d012008102f0c010b200741d0066a2903002105200741c8066a290300210b200741d8006a41186a200741c0066a290300370300200741d8006a41106a200741a0066a41186a2201290300370300200741d8006a41086a200741a0066a41106a2202290300370300200720072903a8063703582001420037030020024200370300200741a0066a41086a22014200370300200742003703a00641aa97ca00ad428080808080018410012206290000210c2001200641086a2900003703002007200c3703a0062006102f41ba97ca00ad4280808080f0018410012206290000210c200741f8096a41086a220d200641086a2900003703002007200c3703f8092006102f200220072903f809220c370300200741c8036a41086a2001290300370300200741c8036a41106a200c370300200741c8036a41186a200d290300370300200720072903a0063703c803200741a0066a200741c8036a10850220072d0098072102200741c8036a200741a0066a41f80010e8061a2007200741a0066a41fc006a2800003600fb0920072007280099073602f8090240024020024102470d002007428080818080043703e8012007428080848080023703e001200742e4003703d001200742013703c801200742013703c001200742af013703b80120074287013703b001200742013703a801200742013703a00120074201370398012007420137039001200742013703880120074201370380012007420137037820074280808080c0003703d801410021020c010b200741f8006a200741c8036a41f80010e8061a200741f8006a41fc006a20072800fb09360000200720072802f8093600f1010b20074190026a420037030020074180026a4200370300200741a0026a4200370300200720023a00f0012007428080e983b1de16370388022007428080e983b1de163703f80120074280a094a58d1d37039802200742a08080808080103703a8022007200741f8006a3602b0022007200741f8006a3602b402200741f8096a41186a220e200741186a41186a290300370300200741f8096a41106a220f200741186a41106a290300370300200741f8096a41086a2210200741186a41086a290300370300200720072903183703f809200741a0066a41186a220d4200370300200741a0066a41106a22014200370300200741a0066a41086a22024200370300200742003703a00641d5a2ca00ad428080808090018410012206290000210c2002200641086a2900003703002007200c3703a0062006102f41ecb0c000ad4280808080308410012211290000210c200741f8086a41086a2206201141086a2900003703002007200c3703f8082011102f200120072903f808220c370300200741c8036a41086a22122002290300370300200741c8036a41106a2213200c370300200741c8036a41186a22142006290300370300200720072903a0063703c803200741086a200741c8036a10e3012007290310210c20072802082115200d42003703002001420037030020024200370300200742003703a006418de6c300ad4280808080e000841001221129000021162002201141086a290000370300200720163703a0062011102f419ce6c300ad4280808080e000841001221129000021162006201141086a290000370300200720163703f8082011102f200120072903f8082216370300201220022903003703002013201637030020142006290300370300200720072903a0063703c8032007200741c8036a4120109501200741f0026a4200370300200741e4026a418886c700360200200741e0026a41c8e1ca00360200200741d4026a4190bdc60036020020074190036a201029030037030020074198036a200f290300370300200741a0036a200e290300370300200741b8026a41206a42003703002007428080808080013703e802200742003703c002200720072903f80937038803200741003602d00220072802002106200728020421112007200741b4026a360280032007200741b0026a3602fc022007200741f8006a3602f80220072011410020061b360284032007200c420020151b3703b802200d200741386a41186a2903003703002001200741386a41106a2903003703002002200741386a41086a290300370300200720072903383703a0062007200a3602d003200720093602cc03200720083602c803200741a8036a200741b8026a200741a0066a20032004200741d8006a200741c8036a10860241012117024020072802a8030d00200741a8036a41106a2d00000d00200741a0066a41086a200741d8026a290300370300200741c8036a41086a200741ac066a280200360200200720072903d0023703a006200720072902a4063703c803200741c80d6a200741c8036a108702410021170b200741186a200729035820072903602007290368200741d8006a41186a290300200b200510880220072802ec02221820072802f402220241d8026c6a210820072802f002211920182101024002402002450d00200741c10a6a2111200741e1066a210a200741f8096a410172211a200741f8086a41076a211b200741810a6a2109200741f8086a410272210e200741a10a6a210f200741a0066a41106a211c200741c8066a211d20074184076a2114200741c1066a210d200741a0066a410172211320182101034020012d00002106200741c8036a200141016a41d70210e8061a0240024002400240024020064103460d00200720063a00a0062013200741c8036a41d70210e8062102024002400240024020060e03000102000b20072802a806211220072802ac06210620072802a4062102201b201c41f80010e8061a2007410d3a00f809201a200741f8086a41ff0010e8061a20022006200741f8096a108c014101210641002110024020120d00410021120c030b2002102f410021120c020b200741980d6a41186a2206200241186a2210290000370300200741980d6a41106a2212200241106a2215290000370300200741980d6a41086a221e200241086a221f290000370300200720022900003703980d200741f8096a201d41b00210e8061a200e2002290000370000200e41086a201f290000370000200e41106a2015290000370000200e41186a201029000037000020074180023b01f808200741e80c6a200741f8096a200741f8086a108b0120072d00e80c2102200920072903980d370000200941086a201e290300370000200941106a2012290300370000200941186a2006290300370000200741063a00800a2007410d3a00f809200720024104463a00a10a4100211041c8e1ca004100200741f8096a108c0141012112410021060c010b200741a80c6a41186a2206200241186a2210290000370300200741a80c6a41106a2212200241106a2215290000370300200741a80c6a41086a221e200241086a221f290000370300200720022900003703a80c200741c80c6a41186a2220200d41186a2221290000370300200741c80c6a41106a2222200d41106a2223290000370300200741c80c6a41086a2224200d41086a22252900003703002007200d2900003703c80c200741e80c6a41186a2226200a41186a2227290000370300200741e80c6a41106a2228200a41106a2229290000370300200741e80c6a41086a222a200a41086a222b2900003703002007200a2900003703e80c200741a0066a41f8006a29030021052007290390072103200741980d6a41186a2010290000370300200741980d6a41106a2015290000370300200741980d6a41086a201f290000370300200720022900003703980d200741f8086a41186a2021290000370300200741f8086a41106a2023290000370300200741f8086a41086a20252900003703002007200d2900003703f808200741f8096a41186a2027290000370300200741f8096a41106a2029290000370300200741f8096a41086a202b2900003703002007200a2900003703f809200741b80d6a41086a201441086a280200360200200720142902003703b80d200741880d6a200741980d6a200741f8086a200741f8096a20032005200741b80d6a10890220072d00880d2102200920072903a80c370000200941086a201e290300370000200941106a2012290300370000200941186a2006290300370000200f20072903c80c370000200f41086a2024290300370000200f41106a2022290300370000200f41186a2020290300370000200741033a00800a2007410d3a00f809200741f8096a41f8006a2005370300201141186a2026290300370000201141106a2028290300370000201141086a202a290300370000201120072903e80c370000200720033703e80a200720024104463a00e10a41c8e1ca004100200741f8096a108c014101211041012112410121060b20072d00a006220241014b0d0120020e020302030b200141d8026a21010c050b201020072802880745720d02200728028407102f0c020b2006450d01201d108e010c010b2012450d00024020072802a806450d0020072802a406102f0b20072d00b0064107470d0020072802d806450d0020072802d406102f0b200141d8026a22012008470d000c020b0b20082001460d0003402001220241d8026a21010240024020022d0000220641014b0d000240024020060e020001000b0240200241086a280200450d00200241046a280200102f0b200241106a2d00004107470d02200241386a280200450d02200241346a280200102f0c020b200241286a108d010c010b200241e8006a280200450d00200241e4006a280200102f0b20082001470d000b0b02402019450d002018102f0b200020072903a803370200200041186a200741a8036a41186a280200360200200041106a200741a8036a41106a290300370200200041086a200741a8036a41086a290300370200024020072802c4022202450d00200741b8026a41106a280200450d002002102f0b2017450d00200741b8026a411c6a280200210220072802dc0221080240024020072802d80222060d00200221010c010b2006210920022101034020012802880b21012009417f6a22090d000b0340200220022f01064102746a41880b6a28020021022006417f6a22060d000b0b200741a0066a411c6a20022f0106360200200741b8066a4100360200200741b4066a2002360200200720083602c006200741003602b006200742003703a806200720013602a406200741003602a006200741a0066a108a020b200741d00d6a24000bd90706017f017e037f017e017f037e230041a0026b2203240042002104200341a0016a41186a4200370300200341a0016a41106a22054200370300200341a0016a41086a22064200370300200342003703a00141aa97ca00ad42808080808001841001220729000021082006200741086a290000370300200320083703a0012007102f41d9cec100ad4280808080800184100122072900002108200341d8006a41086a2209200741086a290000370300200320083703582007102f200520032903582208370300200341f0006a41086a2006290300370300200341f0006a41106a2008370300200341f0006a41186a2009290300370300200320032903a001370370200341386a200341f0006a4120109c0102400240024020032903404201200328023822061b2208200341386a41106a290300420020061b220a8450450d004200210b4200210c0c010b200341186a200a42002002420010ed06200341286a200842002002420010ed06200341086a420042002008420010ed0602402003290320200329031084420052200341286a41086a290300220b200329031820032903087c7c220c200b54724101460d002003290328210b0c010b200041003a0004200041013602002000410c6a4127360200200041086a41e085c7003602000c010b41002106200341003a006b200341083a006a200320013602542003200b3703582003200c370360024002400240200b200c8450450d004200210c0c010b2003200136026c2003200341ec006a3602b0012003200341ea006a3602ac012003200341d4006a3602a8012003200341eb006a3602a4012003200341d8006a3602a001200341f0006a2001200341a0016a10a50441012106024020032802704101470d00200341f8006a29030021044200210c200328027421070c020b20034198016a290300210c20034190016a29030021040240200341f0006a41086a2903004201510d00410021060c010b200341f0006a41106a290300210b200328026c2107200341d8016a200341f0006a41186a290300370300200341d0016a200b37030041002106200341a0016a41086a41003a0000200341a9016a2007290000370000200341b1016a200741086a290000370000200341b9016a200741106a290000370000200341c1016a200741186a290000370000200341033a00a00141c8e1ca004100200341a0016a108c010b0b024020060d0020004100360200200041306a200c370300200041286a2004370300200041206a200a370300200041186a2008370300200041106a2002370300200041086a20023703000c010b2000200736020420004101360200200041086a20043702000b200341a0026a24000bf00201047f230041c0016b220224002002412036020420022001360200200241086a2001ad4280808080800484100210730240024020022802082201450d00200228020c21032002200241106a28020036029c012002200136029801200241186a20024198016a1091020240024020022d00900122044102470d00200241003602a801200242013703a0012002410b3602b401200220023602b0012002200241a0016a3602bc012002412c6a41013602002002420137021c200241b885c7003602182002200241b0016a360228200241bc016a41d8dbc100200241186a103c1a20023502a80142208620023502a00184100820022802a401450d0120022802a001102f0c010b2000200241186a41f80010e80621052002200241186a41fc006a2800003600a30120022002280091013602a001200541fc006a20022800a301360000200520022802a0013600790b200020043a00782003450d012001102f0c010b200041023a00780b200241c0016a24000bed3207037f017e017f017e057f047e057f23002207210820074180106b4160712207240020072004370360200720033703582007200536026c0240024002402001280230200128024022092802b001460d002005420020052903082203200941386a2903007d2204200420035622091b3703082009450d01200041003a0004200041013602002000410c6a4123360200200041086a41c891c700360200200041106a2006290200370200200041186a200641086a280200360200200824000f0b200041003a0004200041013602002000410c6a4129360200200041086a419f91c700360200200041106a2006290200370200200041186a200641086a2802003602000c010b20074180056a200210e801024002400240024020072d008005417f6a41ff01714102490d0020074180056a41106a290300210a20074180056a41086a220b290300210c200741a4056a280200210d200741a8056a280200210e42002103200741a00d6a41186a4200370300200741a00d6a41106a220f4200370300200741a00d6a41086a22054200370300200742003703a00d418de6c300ad4280808080e000841001220929000021042005200941086a290000370300200720043703a00d2009102f419ce6c300ad4280808080e00084100122092900002104200741d8026a41086a2210200941086a290000370300200720043703d8022009102f200f20072903d8022204370300200741e8016a41086a2005290300370300200741e8016a41106a220f2004370300200741e8016a41186a22112010290300370300200720072903a00d3703e801200741d0006a200741e8016a412010950141002007280254410020072802501b2209200e6b220e200e20094b1b220e450d02200741a00d6a2002108d0242002103200741c0006a20072903a00d221220052903002213428080a8ec85afd1b101420010ee064200200dad2204200729034022147d221520152004564200200741c0006a41086a2903002004201454ad7c7d22044200522004501b22051b22144200200420051b220484500d02420121032012428080d287e2bc2d5441002013501b0d02200741306a200ead42002014200410ed06200741206a2007290330200741306a41086a290300428080e983b1de16420010ed06024002402012428080aef89dc3527c2203200c200c200356200a20132003201254ad7c427f7c220356200a2003511b22051b22042007290320220c2004200c542003200a20051b2204200741206a41086a290300220a542004200a511b22051b22032004200a20051b220484500d00200741a00d6a2002108d0220072903c00d220c4200201220037d220a200a201256201320047d2012200354ad7d221220135620122013511b220e1b221458200741c80d6a290300220a42002012200e1b221258200a201251220e1bad2113200c201456200a201256200e1b0d032005450d010c030b4201211320050d020b200720033703d802200720043703e002420321030c020b200741f0006a20074180056a41d80010e8061a0c020b200741e8026a2004370300200720033703e002200720133703d802420221030b200741a00d6a200b41d00010e8061a200f20102903003703002011200741d8026a41106a290300370300200720033703e801200720072903d8023703f001200741f0006a2002200741a00d6a2009200741e8016a109f020b024002400240024002400240024002400240024002400240024020072d007022094103714103460d00024020090e03000100000b200741c8016a41186a220b200141e8006a290000370300200741c8016a41106a220e200141e0006a290000370300200741c8016a41086a220f200141d8006a290000370300200720012900503703c801200741f0006a41206a28020021054100211141002110024020090d002005417f4c0d02200741f0006a411c6a280200210d200741f0006a41186a28020021090240024020050d00410121100c010b2005102d2210450d090b20102009200510e8061a200d450d002009102f0b200741a4026a410036020020074194026a41ec91c700360200200741e8016a41206a4200370300200741e8016a411c6a4190bdc600360200200741e8016a41146a2005360200200741e8016a41106a2005360200200741e8016a41d8006a200241086a290000370300200741e8016a41e0006a200241106a290000370300200741e8016a41e8006a200241186a290000370300200720013602f001200741e8016a41286a200141186a22163602002007420837029c022007410036028002200720103602f401200720022900003703b802200720012802483602b002200720012903403703a8022007200128023041016a36029802200129030021032007200128024c3602b402200720033703e801200741d8026a41206a200f290300370300200741d8026a41286a200e29030037030020074188036a200b290300370300200741d8026a41146a200641086a280200360200200720023602e002200720072903c8013703f002200720062902003702e4022007200741ec006a3602dc022007200741d8006a3602d802024020072903582203200741d8006a41086a290300220484500d0020074180056a200728026c4100200741f0026a200220032004200741e8016a10a305024020072d0080054104460d0020072f00e502200741e7026a2d000041107472210e200741d8026a41106a290300210320072d00e402210f200729028405210420072802800521060c0e0b200728028002211120072802e00221020b201141016a220d41004c0d02200741d8026a41186a2117200741e4026a21182007200d36028002200741e8016a41206a280200210f20074184026a2219210602400240024002400340024002402006280200220e2f010622110d00410021090c010b20114105742106200e41c5036a2110200e41086a2105417f21090340024020060d00201121090c020b20022005412010ea06220b450d03200641606a2106201041e0006a2110200941016a2109200541206a2105200b417f4a0d000b0b200f450d02200f417f6a210f200e20094102746a41880b6a21060c000b0b0240024020102d00000d002010415f6a2d0000210520074180056a41186a2209201041606a220641186a29000037030020074180056a41106a2210200641106a29000037030020074180056a41086a220b200641086a29000037030020072006290000370380054102210620054101470d01200741a00d6a41186a2009290300370300200741a00d6a41106a2010290300370300200741a00d6a41086a200b29030037030020072007290380053703a00d410121060c010b2010415f6a2d00002106200741a00d6a41186a201041606a220541186a290000370300200741a00d6a41106a200541106a290000370300200741a00d6a41086a200541086a290000370300200720052900003703a00d0b200641ff01714102470d010b20074190036a200728029002200220072802940228021011030020072d0090032106200728028002210d0c010b20074199036a200741a80d6a290300370000200741a1036a200741b00d6a290300370000200741a9036a200741b80d6a290300370000200720063a009003200720072903a00d370091030b2007200d417f6a36028002410121110240200641ff01714101470d00200741b8036a41186a200741a9036a290000370300200741b8036a41106a200741a1036a290000370300200741b8036a41086a20074199036a29000037030020072007290091033703b80320074180056a200741b8036a20072802b00228020010920202402007280280054101470d0020072f00e502200741e7026a2d000041107472210e2007290284052104200741d8026a41106a290300210320072d00e402210f410021060c0e0b200741a00d6a41186a220520074180056a410472220641186a2802002209360200200741d8036a41106a200641086a290200370300200741d8036a41186a200641106a290200370300200741f8036a2009360200200741043602dc03200741fb8bca003602d803200720062902003703e00320072802ac0221062005201741186a2900002203370300200741a00d6a41106a201741106a2900002204370300200741a00d6a41086a2205201741086a2900002212370300200741a8056a2012370300200741b0056a2004370300200741b8056a20033703002007201729000022033703a00d200720033703a00520072802d802220941086a29030021032007200741e8016a360298052009290300210420072903e801211220072802b4022109200720033703880520072004370380052007200936029c0520072012370390052005201841086a280200360200200720182902003703a00d200741e0046a2006200741d8036a20074180056a200741a00d6a20072802dc0228020010bf0120072f00f104200741f3046a2d000041107472210e200741e0046a41106a2d0000210f200741e0046a41086a290300211220072802e4042111024020072802e0044101470d00200741f4046a290200210320122104201121060c0d0b20072802800241016a221a41004c0d0420072802e00221022007201a360280022007280288022117201921060240024002400340024002402006280200220d2f010622180d00410021090c010b20184105742106200d41c5036a2110200d41086a2105417f21090340024020060d00201821090c020b20022005412010ea06220b450d03200641606a2106201041e0006a2110200941016a2109200541206a2105200b417f4a0d000b0b2017450d022017417f6a2117200d20094102746a41880b6a21060c000b0b2010310000201041a37f6a290300220320035022061ba7450d004200201041ab7f6a220541086a29030020061b21034200200529030020061b21040c010b200741106a200728029002200220072802940228021c110300200741186a290300210320072903102104200728028002211a0b2007201a417f6a221036028002200420072802a80222062903800154200320064188016a29030022045420032004511b0d050c060b420021124100210f0240200741e8026a280200450d0020072802e402102f0b0c060b200041003a0004200041013602002000410c6a4119360200200041086a418b93c700360200200041106a2006290200370200200041186a200641086a28020036020020090d0c2007418c016a280200450d0c20074188016a280200102f200824000f0b103d000b41c6c4ca00411820074180056a41cc90c70041f0c4ca00103e000b41c6c4ca00411820074180056a41cc90c70041f0c4ca00103e000b20072802f0012206450d030240024020072802e0022205200641d0006a2209460d0020092005412010ea06450d00034020062802082206450d022005200641d0006a2209460d0120092005412010ea060d000b0b2011410876210e41d492c700ad4280808080f00684210441002106201221032011210f0c070b20100d042007417f36028002200741003a00bc04200742003702b404200741013a009d0420074190bdc6003602b004200741e0046a41186a200541186a290000370300200741e0046a41106a200541106a290000370300200741e0046a41086a200541086a290000370300200720052900003703e00402400240200728028402220b4190bdc600460d0020072802880221020c010b200741a00d6a410041e00210e7061a20074180056a410041a00810e7061a41880b102d220b450d0341002102200b41003b0106200b4100360200200b41086a200741a00d6a41e00210e8061a200b41e8026a20074180056a41a00810e8061a20074100360288022007200b360284020b02400240034002400240200b2f0106220d0d00410021090c010b200d4105742106200b41086a2105417f21090340024020060d00200d21090c020b200941016a2109200741e0046a2005412010ea062210450d03200641606a2106200541206a21052010417f4a0d000b0b02402002450d002002417f6a2102200b20094102746a41880b6a280200210b0c010b0b200741c0046a41186a200741e0046a41186a2903002203370300200741c0046a41106a200741e0046a41106a2903002204370300200741c0046a41086a200741e0046a41086a290300220a370300200720072903e00422133703c004200741bc0d6a200a370200200741a00d6a41246a2004370200200741cc0d6a20033702002007200741e8016a41246a3602b00d200720093602ac0d200720193602a80d2007200b3602a40d200741003602a00d200720133702b40d20074180056a41186a42003703002007420037038005200741b8056a20072903b804370300200741b0056a20072903b004370300200741a8056a20072903a804370300200741a0056a20072903a004370300200741d8056a200729039804370300200741d0056a200729039004370300200741c8056a200729038804370300200741c0056a200729038004370300200741a00d6a20074180056a1097021a420221040c010b200b200941e0006c6a22064190036a20072903a80437030020064188036a20072903a004370300200641c0036a200729039804370000200641b8036a200729039004370000200641b0036a200729038804370000200641a8036a20072903800437000020064180036a4200370300200641e8026a2205290300210420054200370300200641a0036a2205280200210b200520072903b80437030020064198036a22062903002103200620072903b0043703002003a721062003422088a721050b024020044202510d000240024020050d00200621090c010b2005211020062109034020092802ec0321092010417f6a22100d000b0340200620062f01064102746a41ec036a28020021062005417f6a22050d000b0b2007419c056a20062f010636020020074198056a410036020020074194056a20063602002007200b3602a005200741003602900520074200370388052007200936028405200741003602800520074180056a1090020b200720072802800241016a360280020b200741f0036a280200450d00200741ec036a280200102f0b20072802a402210520072802a002210d200728029c022102200728028c02211720072802880221102007280284022106024020072802f4012209450d0020072802f801450d002009102f0b02400240200f41ff01710d00200720173602880520072010360284052007200636028005201620074180056a10a40502400240200141386a28020022062001413c6a28020022076b200541d8026c220941d8026d2205490d00200128023421060c010b200720056a22102007490d06200641017422072010200720104b1bad42d8027e2203422088a70d062003a722074100480d060240024020060d002007102d21060c010b2001280234200641d8026c2007103121060b2006450d0320012006360234200141386a200741d8026e3602002001413c6a28020021070b2006200741d8026c6a2002200910e8061a2001413c6a2207200728020020056a3602000240200d450d002002102f0b2000200e3b001120002011360204200041136a200e4110763a0000200041106a41003a0000200041086a20123702000c010b2000200e3b001120002011360204200041136a200e4110763a0000200041106a200f3a0000200041086a201237020002402005450d00200541d8026c210141002105034002400240200220056a22092d0000220b41014b0d0002400240200b0e020001000b0240200941086a280200450d00200941046a280200102f0b200941106a2d00004107470d02200941386a280200450d02200941346a280200102f0c020b200941286a108d010c010b200941e8006a280200450d00200941e4006a280200102f0b2001200541d8026a2205470d000b0b0240200d450d002002102f0b0240024020100d00200621050c010b2010210920062105034020052802880b21052009417f6a22090d000b0340200620062f01064102746a41880b6a28020021062010417f6a22100d000b0b2007419c056a20062f010636020020074198056a410036020020074194056a2006360200200720173602a005200741003602900520074200370388052007200536028405200741003602800520074180056a108a020b20004100360200200824000f0b1036000b419092c700413241c492c7001055000b41c3c5ca00411020074180056a41dc90c70041e4c5ca00103e000b1038000b200741f0036a280200450d00200741ec036a280200102f0b2000200e3b00112000200636020420004101360200200041136a200e4110763a0000200041146a2003370000200041106a200f3a0000200041086a2004370200024020072802f4012206450d0020072802f801450d002006102f0b200741e8016a411c6a2802002106200728028c0221100240024020072802880222050d00200621090c010b2005210020062109034020092802880b21092000417f6a22000d000b0340200620062f01064102746a41880b6a28020021062005417f6a22050d000b0b20074180056a411c6a20062f01063602004100210520074198056a410036020020074194056a2006360200200720103602a005200741003602900520074200370388052007200936028405200741003602800520074180056a108a02024020072802a4022206450d00200728029c022100200641d8026c2110034002400240200020056a22062d0000220941014b0d000240024020090e020001000b0240200641086a280200450d00200641046a280200102f0b200641106a2d00004107470d02200641386a280200450d02200641346a280200102f0c020b200641286a108d010c010b200641e8006a280200450d00200641e4006a280200102f0b2010200541d8026a2205470d000b0b20072802a002450d00200728029c02102f200824000f0b200824000bce3d0f067f027e047f067e047f027e067f027e027f087e017f027e0b7f027e0b7f230041f0046b22022400200128020821032001280200210402400240200128020422050d00200421010c010b2005210620042101034020012802880b21012006417f6a22060d000b0340200420042f01064102746a41880b6a28020021042005417f6a22050d000b0b2002419c016a20042f01063602004100210720024198016a410036020020024194016a2004360200200220033602a001200241003602900142002108200242003703880120022001360284012002410036028001024002402003450d0020022003417f6a3602a0010240024020012f0106450d004100210620012104410021050c010b4100210641002105034002400240024020014190bdc600460d00200128020022040d012005ad2109410021040c020b41edb3ca00412841f8b4ca001039000b200641016a210620013301044220862005ad8421090b2001102f2009a72105200421012009422088a7220720042f01064f0d000b0b200241d0046a41186a220a200420074105746a220141206a290000370300200241d0046a41106a220b200141186a290000370300200241d0046a41086a220c200141106a2900003703002002200141086a2900003703d0042004200741e0006c6a220141a4036a2d0000210d200141a0036a280200210320014198036a290300210e20014190036a290300210f20014188036a290300211020014180036a2903002111200141f8026a2903002112200141f0026a2903002113200141e8026a2903002109200241e8036a41186a2214200141bd036a290000370300200241e8036a41106a2215200141b5036a290000370300200241e8036a41086a2216200141ad036a2900003703002002200141a5036a2900003703e803200741016a2107200141c5036a2d0000211702402006450d00200420074102746a41880b6a2802002104410021072006417f6a2201450d00034020042802880b21042001417f6a22010d000b0b200241c8026a41186a200a290300370300200241c8026a41106a200b290300370300200241c8026a41086a200c290300370300200241c8036a41086a2016290300370300200241c8036a41106a2015290300370300200241c8036a41186a2014290300370300200220022903d0043703c802200220022903e8033703c8032002200736028c01200220053602880120022004360284012002410036028001024020094202520d00420021080c010b200241d0046aad42808080808004842118200241c8036aad428080808080048421192002419c046a211a200241e8036a412c6a211b200241e8036a41106a211c200241e8036a41086a211d200241c8026a412c6a211e200241c8026a41106a211f4200210842002120420021210340200241c8016a41186a2201200241c8026a41186a2222290300370300200241c8016a41106a2204201f290300370300200241c8016a41086a2205200241c8026a41086a2223290300370300200241a8016a41086a2206200241c8036a41086a220b290300370300200241a8016a41106a2207200241c8036a41106a220c290300370300200241a8016a41186a220a200241c8036a41186a2214290300370300200220022903c8023703c801200220022903c8033703a801200241e8016a41186a2001290300370300200241e8016a41106a2004290300370300200241e8016a41086a2005290300370300200220022903c8013703e80120024188026a41186a2204200a29030037030020024188026a41106a2205200729030037030020024188026a41086a22072006290300370300200220022903a801370388020240024002402017ad42ff0183200920095022011b4201520d00200241e8036a200241e8016a108d02200241e8036a41186a22062903002124201d290300210920022903f803212520022903e8032126200241e8006a200241e8016a4200201320011b4200201220011b108e02200241e8006a41106a29030021132002290370212720022903682128200241e8036a200241e8016a108d0220062903002129201d290300211220022903f803212a20022903e803212b200241d0006a202120082020202820272013109d01200241d0006a41106a29030021202002290358210820022903502121427f202620257c221320132026542201200920247c2001ad7c221320095420132009511b22011b427f201320011b84500d00427f202b202a7c22092009202b542201201220297c2001ad7c220920125420092012511b22011b427f200920011b84500d010b0240024002400240024002400240024002400240200d41ff0171220a41014622010d00201741ff01710d0020032011a772450d010b200241e8036a200241e8016a10e8010240024020022d00e8032215417f6a220641014b0d004102212c024020060e020002000b20150d0b200228028404450d0b200228028004102f0c0b0b200241a8026a41086a201a41086a290200370300200241a8026a41106a201a41106a290200370300200241a8026a41186a201a41186a2902003703002002201a2902003703a802201c290300212d20022903f003212e20022802bc04212f2002280298042130200228029404212c2002280290042131200228028c0421322002280288042133200228028404213420022802800421350b410221360240202c4102460d002033417f4c0d020240024020330d00410121370c010b2033102d2237450d040b20372035203310e8061a200241e8036a41186a200241a8026a41186a290300370300201c200241a8026a41106a290300370300201d200241a8026a41086a290300370300200220022903a8023703e803202c41014621362033213820332139202e213a202d213b2032213c2031213d2030213e0b2014200241e8036a41186a2206290300370300200c201c290300370300200b201d290300370300200241a8036a41086a223f2007290300370300200241a8036a41106a22402005290300370300200241a8036a41186a22412004290300370300200220022903e8033703c80320022002290388023703a803201741ff0171450d040c030b200ea7210102400240200e422088a722050d00200121040c010b2005210620012104034020042802ec0321042006417f6a22060d000b0340200120012f01064102746a41ec036a28020021012005417f6a22050d000b0b20022003360288042002410036028004200241003602f803200242003703f003200220043602ec03200241003602e803200220013602fc03200220012f010636028404200241e8036a1090020c090b103d000b1036000b20364102460d010240203941164d0d002039ad4220862037ad84203941696aad422086203741176aad844101101d024020010d00200241e8016a10ec012038450d042037102f0c040b20024198036a200241e8016a10ef0120064200370300201c420037030041082142200241e8036a41086a22014200370300200242003703e803418de6c300ad4280808080e000841001221729000021092001201741086a290000370300200220093703e8032017102f419ce6c300ad4280808080e00084100122172900002109200241c0046a41086a2215201741086a290000370300200220093703c0042017102f201c20022903c004370000201c41086a2015290300370000200241d0046a41086a2001290300370300200241d0046a41106a201c290300370300200241d0046a41186a2006290300370300200220022903e8033703d004200241c8006a200241d0046a4120109501200228024c210120022802482117201f41086a20024198036a41086a280200360200201f200229039803370200201e20022903a803370100201e41086a200241a8036a41086a290300370100201e41106a2040290300370100201e41186a2041290300370100427f212b2002427f3703d0022002427f3703c802200241083602e40241002136200241003602ec0220022001410020171b22433602e802024020380d00427f21240c060b2037102f427f212b427f21240c050b41172039104b000b20364102470d020b2001450d0020024198036a200241e8016a10ef0120064200370300201c420037030041082142200241e8036a41086a22014200370300200242003703e803418de6c300ad4280808080e000841001221729000021092001201741086a290000370300200220093703e8032017102f419ce6c300ad4280808080e00084100122172900002109200241c0046a41086a2215201741086a290000370300200220093703c0042017102f201c20022903c004370000201c41086a2015290300370000200241d0046a41086a2001290300370300200241d0046a41106a201c290300370300200241d0046a41186a2006290300370300200220022903e8033703d004200241c0006a200241d0046a41201095012002280244210120022802402117201f41086a20024198036a41086a280200360200201f200229039803370200201e20022903a803370100201e41086a200241a8036a41086a290300370100201e41106a2040290300370100201e41186a2041290300370100427f212b2002427f3703d0022002427f3703c802200241083602e40241002136200241003602ec0220022001410020171b22433602e802427f21240c020b202c4102460d02024020340d00410021340c030b2035102f0c020b201e20022903c803370200201e41086a200b290300370200201e41106a200c290300370200201e41186a20142903003702002002203a3703c8022002203e3602f002200220363602ec022002203d3602e8022002203c3602e402200220393602e002200220383602dc02200220373602d8022002203b3703d002203d2143203a212b203b2124203c21420b024020114201520d00200220103703c8022002200f3703d0022010212b200f21240b0240200a450d00201e200229038802370000201e41186a2004290300370000201e41106a2005290300370000201e41086a20072903003700000b02402003450d0020064200370300201c4200370300201d4200370300200242003703e803418de6c300ad4280808080e00084100122012900002109201d200141086a290000370300200220093703e8032001102f419ce6c300ad4280808080e00084100122012900002109200241c0046a41086a2204200141086a290000370300200220093703c0042001102f201c20022903c004370000201c41086a2004290300370000200241d0046a41086a201d290300370300200241d0046a41106a201c290300370300200241d0046a41186a2006290300370300200220022903e8033703d004200241386a200241d0046a412010950141012136200241013602ec022002200228023c410020022802381b3602f0020b200ea7210102400240200e422088a722050d00200121040c010b2005210620012104034020042802ec0321042006417f6a22060d000b0340200120012f01064102746a41ec036a28020021012005417f6a22050d000b0b20012f01062105200220033602880420022005360284042002410036028004200220013602fc03200241003602f803200242003703f003200220043602ec03200241003602e80302402003450d0020022003417f6a221636028804410021150240024020042f0106450d004100210620042101410021050c010b4100210641002105034002400240024020044190bdc600460d00200428020022010d012005ad2109410021010c020b41edb3ca00412841f8b4ca001039000b200641016a210620043301044220862005ad8421090b2004102f2009a72105200121042009422088a7221520012f01064f0d000b0b200241d0046a41186a2203200120154105746a220441206a290000370300200241d0046a41106a2217200441186a290000370300200241d0046a41086a220a200441106a2900003703002002200441086a2900003703d004201541016a210720012015410c6c6a220441f0026a280200210d200441ec026a2802002144200441e8026a280200211502402006450d00200120074102746a41ec036a2802002101410021072006417f6a2204450d00034020012802ec0321012004417f6a22040d000b0b20142003290300370300200c2017290300370300200b200a290300370300200220022903d0043703c803200220073602f403200220053602f003200220013602ec03200241003602e80320022802e002224541696aad42208620022802d802220441176aad84210e2045ad4220862004ad8421110240024003402041201429030022093703002040200c2903002212370300203f200b2903002213370300200220022903c80322263703a80320142009370300200c2012370300200b2013370300200220263703c803204541164d0d0120191003220441086a2900002109200441106a2900002112200429000021132003200441186a29000037030020172012370300200a2009370300200220133703d0042004102f200241c0046a2011200e4101201810101073024020022802c0042204450d00204220022802c8046b214220022802c404450d002004102f0b024002402015450d0020191003220441086a2900002109200441106a2900002112200429000021132003200441186a29000037030020172012370300200a2009370300200220133703d0042004102f2011200e41012018200dad4220862015ad84100f2042200d6a21422044450d012015102f0c010b20191003220441086a2900002109200441106a2900002112200429000021132003200441186a29000037030020172012370300200a2009370300200220133703d0042004102f2011200e4101201810110b2016450d0220022016417f6a2216360288044100210602400240200720012f01064f0d00200121040c010b41002106034002400240024020014190bdc600460d00200128020022040d012005ad2109410021040c020b41edb3ca00412841f8b4ca001039000b200641016a210620013301044220862005ad8421090b2001102f2009a72105200421012009422088a7220720042f01064f0d000b0b2003200420074105746a220141206a2900003703002017200141186a290000370300200a200141106a2900003703002002200141086a2900003703d004200741016a214620042007410c6c6a220141f0026a280200210d200141ec026a2802002144200141e8026a28020021150240024020060d0020042101204621070c010b200420464102746a41ec036a2802002101410021072006417f6a2204450d00034020012802ec0321012004417f6a22040d000b0b20142003290300370300200c2017290300370300200b200a290300370300200220022903d0043703c803200220073602f403200220053602f003200220013602ec03200241003602e8030c000b0b41172045104b000b200220423602e4020b200241e8036a109002200241d0046a41186a2201200241a8026a41186a290300370300200241d0046a41106a2204200241a8026a41106a290300370300200241d0046a41086a2205200241a8026a41086a290300370300200220022903a8023703d00402400240202c4102460d00201b20022903d004370200201b41086a2005290300370200201b41106a2004290300370200201b41186a20012903003702002002202e3703e80320022030360290042002202c36028c0420022031360288042002203236028404200220343602fc03200220353602f8032002202f3602b4042002202d3703f0032002203336028004410121010240203320022802e002470d000240024020022802d80222042035460d0020352004203310ea060d0220322042470d020c010b20322042470d010b201b201e412010ea060d00202e202b85202d202485844200520d0020312043470d000240202c2036470d0041002101202c4101470d01203020022802f002460d010b410121010b02402034450d002035102f0b20014102460d002001450d010b201d200241c8026a41d00010e8061a200241003a00e803200241e8016a200241e8036a10eb010c020b20022802dc02450d0120022802d802102f0c010b200ea7210102400240200e422088a722050d00200121040c010b2005210620012104034020042802ec0321042006417f6a22060d000b0340200120012f01064102746a41ec036a28020021012005417f6a22050d000b0b20022003360288042002410036028004200241003602f803200242003703f003200220043602ec03200241003602e803200220013602fc03200220012f010636028404200241e8036a1090020b20022802a0012201450d0220022001417f6a3602a0012002280288012105200228028001210602400240200228028c01220720022802840122042f01064f0d00200421010c010b034002400240024020044190bdc600460d00200428020022010d012005ad2109410021010c020b41edb3ca00412841f8b4ca001039000b200641016a210620043301044220862005ad8421090b2004102f2009a72105200121042009422088a7220720012f01064f0d000b0b200241d0046a41186a220a200120074105746a220441206a290000370300200241d0046a41106a2215200441186a290000370300200241d0046a41086a2216200441106a2900003703002002200441086a2900003703d0042001200741e0006c6a220441a4036a2d0000210d200441a0036a280200210320044198036a290300210e20044190036a290300210f20044188036a290300211020044180036a2903002111200441f8026a2903002112200441f0026a2903002113200441e8026a2903002109200241e8036a41186a2242200441bd036a290000370300201c200441b5036a290000370300201d200441ad036a2900003703002002200441a5036a2900003703e803200741016a2107200441c5036a2d0000211702402006450d00200120074102746a41880b6a2802002101410021072006417f6a2204450d00034020012802880b21012004417f6a22040d000b0b2022200a290300370300201f201529030037030020232016290300370300200b201d290300370300200c201c29030037030020142042290300370300200220022903d0043703c802200220022903e8033703c8032002200736028c0120022005360288012002200136028401200241003602800120094202520d000c020b0b42002120420021210b20024180016a108a02024002402021500d00200241e8036a41186a22034200370300200241e8036a41106a22044200370300200241e8036a41086a22014200370300200242003703e80341e7a2ca00ad4280808080800184220910012206290000210e200241c8026a41086a2205200641086a2900003703002002200e3703c8022006102f20012005290300370300200220022903c8023703e80341ecb5c600ad4280808080d00184220e100122072900002111200241c0046a41086a2206200741086a290000370300200220113703c0042007102f200420022903c0042211370300200241d0046a41086a22172001290300370300200241d0046a41106a220a2011370300200241d0046a41186a220b2006290300370300200220022903e8033703d004200241206a200241d0046a4120109c01200241206a41106a29030021112002290328211920022802202107200342003703002004420037030020014200370300200242003703e80320091001220329000021092005200341086a290000370300200220093703c8022003102f20012005290300370300200220022903c8023703e803200e1001220529000021092006200541086a290000370300200220093703c0042005102f200420022903c004220937030020172001290300370300200a2009370300200b2006290300370300200220022903e8033703d004200242002011420020071b220920207d2019420020071b220e200854ad7d2211200e20087d2219200e56201120095620112009511b22011b3703f00320024200201920011b3703e803200241e8036a2101200241d0046a21040c010b02402008202084500d0041ac86c700413341f8b4ca001039000b200241e8036a41186a22034200370300200241e8036a41106a22044200370300200241e8036a41086a22014200370300200242003703e80341e7a2ca00ad4280808080800184220910012206290000210e200241c8026a41086a2205200641086a2900003703002002200e3703c8022006102f20012005290300370300200220022903c8023703e80341ecb5c600ad4280808080d00184220e100122072900002111200241c0046a41086a2206200741086a290000370300200220113703c0042007102f200420022903c0042211370300200241d0046a41086a22172001290300370300200241d0046a41106a220a2011370300200241d0046a41186a220b2006290300370300200220022903e8033703d004200241086a200241d0046a4120109c01200241086a41106a29030021112002290310211920022802082107200342003703002004420037030020014200370300200242003703e80320091001220329000021092005200341086a290000370300200220093703c8022003102f20012005290300370300200220022903c8023703e803200e1001220529000021092006200541086a290000370300200220093703c0042005102f200420022903c004220937030020172001290300370300200a2009370300200b2006290300370300200220022903e8033703d00420022011420020071b3703f00320022019420020071b3703e803200241e8036a2101200241d0046a21040b2004ad42808080808004842001ad42808080808002841004200241f0046a24000bc50b04067f017e047f037e23004180026b22072400200741186a200242002003200410ed06200741f0006a41186a22084200370300200741f0006a41106a22094200370300200741f0006a41086a220a42003703002007420037037041aa97ca00ad428080808080018422031001220b2900002104200741f0016a41086a220c200b41086a290000370300200720043703f001200b102f200a200c290300370300200720072903f00137037041b297ca00ad428080808080018422041001220b290000210d200c200b41086a2900003703002007200d3703f001200b102f200920072903f001220d370300200741c0006a41086a220e200a290300370300200741c0006a41106a220f200d370300200741c0006a41186a2210200c29030037030020072007290370370340200741286a200741c0006a10e3012007290330210d200728022821112008420037030020094200370300200a42003703002007420037037020031001220b2900002103200c200b41086a290000370300200720033703f001200b102f200a200c290300370300200720072903f00137037020041001220b2900002103200c200b41086a290000370300200720033703f001200b102f200920072903f0012203370300200e200a290300370300200f20033703002010200c290300370300200720072903703703402007200120027d200d420020111b7c370370200741c0006aad22034280808080800484200741f0006aad2204428080808080018410042007200729031822023703f0012007200741186a41086a29030022013703f80102400240024020022001844200510d002007200036023c200741c0006a2000200741f0016a2007413c6a108f020240024020072903404201510d00200741e8006a2903002102200741e0006a290300210120072903484201520d01200741c0006a41106a290300210d200741a8016a200741c0006a41186a290300370300200741a0016a200d370300200741f0006a41086a41003a0000200741f9006a200029000037000020074181016a200041086a29000037000020074189016a200041106a29000037000020074191016a200041186a290000370000200741033a007041c8e1ca004100200741f0006a108c010c010b200741d0006a2903002102200729034821010b2005200154220c200620025420062002511b0d01200620027d200cad7d2106200520017d21050b20052006109a010c010b200741f0006a41186a22004200370300200741f0006a41106a22094200370300200741f0006a41086a220a42003703002007420037037041e7a2ca00ad4280808080800184220d1001220b2900002112200741f0016a41086a220c200b41086a290000370300200720123703f001200b102f200a200c290300370300200720072903f00137037041ecb5c600ad4280808080d0018422121001220b2900002113200c200b41086a290000370300200720133703f001200b102f200920072903f0012213370300200741c0006a41086a2208200a290300370300200741c0006a41106a220e2013370300200741c0006a41186a220f200c290300370300200720072903703703402007200741c0006a4120109c01200741106a2903002113200729030821142007280200210b2000420037030020094200370300200a420037030020074200370370200d10012200290000210d200c200041086a2900003703002007200d3703f0012000102f200a200c290300370300200720072903f001370370201210012200290000210d200c200041086a2900003703002007200d3703f0012000102f200920072903f001220d3703002008200a290300370300200e200d370300200f200c290300370300200720072903703703402007427f20134200200b1b220d200220067d2001200554ad7d7c20144200200b1b2206200120057d7c2205200654220cad7c2206200c2006200d542006200d511b220c1b3703782007427f2005200c1b370370200342808080808004842004428080808080028410040b20074180026a24000bc72b040e7f017e057f067e230041a0046b22072400200741a0036a200110e801410221080240024020072d00a00322094102470d00410121094102210a0c010b200741f0026a41086a200741a9036a290000370300200741f0026a41106a200741b1036a290000370300200741f0026a41186a200741b9036a290000370300200741f0026a41206a200741c1036a29000037030020074197036a220b200741c8036a280000360000200741c8026a41086a220a200741d8036a290300370300200741c8026a41106a220c200741e0036a290300370300200741c8026a41186a220d200741e8036a290300370300200741c8026a41206a220e200741f0036a290300370300200720072900a1033703f0022007200741d0036a2903003703c802024020090d00200741cc036a2802002108200741a0026a41206a200b280000360200200741a0026a41186a2007418f036a290000370300200741a0026a41106a20074187036a290000370300200741a0026a41086a200741ff026a290000370300200741f8016a41086a200a290300370300200741f8016a41106a200c290300370300200741f8016a41186a200d290300370300200741f8016a41206a200e290300370300200720072900f7023703a002200720072903c8023703f8010b4102210a4101210920084102460d00200741c6036a200741a0026a41206a280200360100200741be036a200741a0026a41186a290300370100200741b6036a200741a0026a41106a290300370100200741ae036a200741a0026a41086a290300370100200741f0026a41086a200741f8016a41086a290300370300200741f0026a41106a200741f8016a41106a290300370300200741f0026a41186a200741f8016a41186a290300370300200741f0026a41206a200741f8016a41206a290300370300200720072903a0023701a603200720072903f8013703f002410021092008210a0b200741c8016a41086a200741a0036a41086a2208290100370300200741c8016a41106a200741a0036a41106a220b290100370300200741c8016a41186a200741a0036a41186a220c290100370300200741c8016a41206a200741a0036a41206a290100370300200741c8016a41286a200741a0036a41286a2f01003b0100200741a0016a41086a220d200741f0026a41086a220e290300370300200741a0016a41106a220f200741f0026a41106a2210290300370300200741a0016a41186a2211200741f0026a41186a2212290300370300200741a0016a41206a2213200741f0026a41206a290300370300200720072901a0033703c801200720072903f0023703a00102400240024002400240024002400240024020090d00200741d0006a41286a221420072903a001370300200741d0006a41206a200741ee016a280100360200200741d0006a41186a200741e6016a290100370300200741d0006a41106a200741de016a290100370300200741d0006a41086a200741d6016a29010037030020074180016a200d29030037030020074188016a200f29030037030020074190016a201129030037030020074198016a2013290300370300200720072901ce013703502007200a360274200c4200370300200b420037030020084200370300200742003703a003418de6c300ad4280808080e000841001220929000021152008200941086a290000370300200720153703a0032009102f419ce6c300ad4280808080e00084100122092900002115200741f8016a41086a220a200941086a290000370300200720153703f8012009102f200b20072903f8012215370300200e2008290300370300201020153703002012200a290300370300200720072903a0033703f002200741c8006a200741f0026a4120109501200728024c410020072802481b210c024020072802744101470d002014280200200c470d0020004183243b0100200041086a4115360200200041046a419bcdc100360200200041026a41053a00000c070b200741a0036a200210e8010240024020072d00a00322084102460d00200741f0026a41086a220d200741aa036a290100370300200741f0026a410e6a220e200741b0036a290100370100200720072901a2033703f002200741bc036a2802002109200741b8036a280200210a20080d012009450d00200a102f0b20004183243b0100200041086a411a360200200041046a41c0cdc100360200200041026a41033a00000c070b20072d00a1032108200741c8016a410e6a220f200e290100370100200741c8016a41086a220e200d290300370300200741d1026a200e290300370000200741d7026a200f290100370000200720083a00c802200720072903f0023700c902200720093600e3022007200a3600df022007200741a0036a41206a2d00003a00e702200641086a280200211120072802742116200728027821172007200628020022123602f80120072012201141057422096a3602fc012007200741d0006a360280020240024002402011450d00200741f8016a41086a210d2012210803402007200841206a220a3602f801200741a0036a200d2008108b0220072802a00322080d02200a2108200941606a22090d000b0b4104210f41002110410021140c010b200741f0026a41086a220a200741a0036a410c6a280200360200200720072902a4033703f0024110102d220f450d02200f2008360200200f20072903f002370204200f410c6a200a280200360200200a200741f8016a41086a280200360200200720072903f80122153703f00202402015a7220920072802f402220d470d0041012110410121140c010b200741a0036a4104722113200d41606a21184101211041012114034020092108024003402007200841206a22093602f002200741a0036a200a2008108b0220072802a003220e0d0120092108200d2009470d000c030b0b200741c8016a41086a201341086a28020022193602002007201329020022153703c801200741a0036a41086a221a2019360200200720153703a003024020142010470d00201041016a22142010490d05201041017422192014201920144b1b221441ffffffff00712014470d05201441047422144100480d050240024020100d002014102d210f0c010b200f201041047420141031210f0b200f450d04201441047621140b200f20104104746a2219200e360200201920072903a0033702042019410c6a201a280200360200201041016a211020182008470d000b0b02400240200741d0006a41186a350200422086200735026084100e2215422088a7220e0d00410121130c010b2015a721130b200741a0036a41186a200341186a290000370300200741a0036a41106a200341106a290000370300200741a0036a41086a200341086a290000370300200720032900003703a003200741003602f802200742013703f0022013200e200741f0026a108c020240024020072802f402220d20072802f802220a6b4120490d00200a41206a210820072802f00221090c010b200a41206a2208200a490d03200d41017422092008200920084b1b22194100480d0302400240200d0d002019102d21090c010b20072802f002200d2019103121090b2009450d02200720193602f402200720093602f0022019210d0b200720083602f8022009200a6a220a20072903a003370000200a41086a200741a0036a41086a290300370000200a41106a200741a0036a41106a290300370000200a41186a200741a0036a41186a2903003700002008ad4220862009ad84100322082900002115200841086a290000211b200841106a290000211c200741c8016a41186a200841186a290000370300200741c8016a41106a201c370300200741c8016a41086a201b370300200720153703c8012008102f0240200d450d002009102f0b0240200e450d002013102f0b0240200741c8016a200741c8026a412010ea060d00200c201720111b210e4101201620111b2111200741d0006a41106a210d4100210902402010450d002010410474210a200f410c6a2108410021090340200828020020096a2109200841106a2108200a41706a220a0d000b0b2007200728026c20096b36026c200110ec01200741a0036a41106a220a2005370300200741d0036a200e360200200741cc036a2011360200200741c8036a200c360200200741c4036a200728026c360200200741a0036a41186a220c200d290300370300200741a0036a41206a200d41086a280200360200200741d4036a2003290000370200200741dc036a200341086a290000370200200741e4036a200341106a290000370200200741ec036a200341186a290000370200200720043703a803200741003a00a0032002200741a0036a10eb01200741a0036a2001108d02200741a0036a41086a2209290300211520072903a003211b200741306a200142004200108e02200741306a41106a290300211d2007290338211c2007290330211e200c4200370300200a420037030020094200370300200742003703a00341e7a2ca00ad4280808080800184221f100122012900002104200741f8016a41086a2208200141086a290000370300200720043703f8012001102f20092008290300370300200720072903f8013703a00341ecb5c600ad4280808080d0018422201001220129000021042008200141086a290000370300200720043703f8012001102f200b20072903f801370000200b41086a22012008290300370000200741f0026a41086a220d2009290300370300200741f0026a41106a220e200a290300370300200741f0026a41186a2211200c290300370300200720072903a0033703f002200741186a200741f0026a4120109c01200741186a41106a2903004200200728021822131b21042007290320420020131b210502400240201e4200520d00200c4200370300200a420037030020094200370300200742003703a003201f10012213290000211f2008201341086a2900003703002007201f3703f8012013102f20092008290300370300200720072903f8013703a003202010012213290000211f2008201341086a2900003703002007201f3703f8012013102f200b20072903f80137000020012008290300370000200d2009290300370300200e200a2903003703002011200c290300370300200720072903a0033703f0022007427f2004201d7c2005201c7c221c2005542208ad7c22052008200520045420052004511b22081b3703a8032007427f201c20081b3703a003200741a0036a21080c010b200c4200370300200a420037030020094200370300200742003703a003201f10012213290000211f2008201341086a2900003703002007201f3703f8012013102f20092008290300370300200720072903f8013703a003202010012213290000211f2008201341086a2900003703002007201f3703f8012013102f200b20072903f80137000020012008290300370000200d2009290300370300200e200a2903003703002011200c290300370300200720072903a0033703f002200742002004201d7d2005201c54ad7d221d2005201c7d221c200556201d200456201d2004511b22081b3703a80320074200201c20081b3703a003200741a0036a21080b200741f0026aad4280808080800484221c2008ad428080808080028410042007201b3703f801200720153703800202400240201b20158450450d0042002105420021150c010b200720023602a001200741f0026a2002200741f8016a200741a0016a108f02024020072903f0024201510d0020074198036a290300211520074190036a290300210520072903f8024201520d01200741f0026a41106a2903002104200741d8036a200741f0026a41186a290300370300200741d0036a2004370300200741a0036a41086a41003a0000200741a9036a2002290000370000200741b1036a200241086a290000370000200741b9036a200241106a290000370000200741c1036a200241186a290000370000200741033a00a00341c8e1ca004100200741a0036a108c010c010b20074180036a290300211520072903f80221050b200741a0036a41186a22014200370300200741a0036a41106a220a4200370300200741a0036a41086a22094200370300200742003703a00341e7a2ca00ad428080808080018422041001220c290000211b200741f8016a41086a2208200c41086a2900003703002007201b3703f801200c102f20092008290300370300200720072903f8013703a00341ecb5c600ad4280808080d00184221b1001220c290000211d2008200c41086a2900003703002007201d3703f801200c102f200b20072903f801370000200b41086a220e2008290300370000200741f0026a41086a22112009290300370300200741f0026a41106a2213200a290300370300200741f0026a41186a22032001290300370300200720072903a0033703f0022007200741f0026a4120109c01200741106a290300211d2007290308211f2007280200210c20014200370300200a420037030020094200370300200742003703a00320041001220d29000021042008200d41086a290000370300200720043703f801200d102f20092008290300370300200720072903f8013703a003201b1001220d29000021042008200d41086a290000370300200720043703f801200d102f200b20072903f801370000200e2008290300370000201120092903003703002013200a29030037030020032001290300370300200720072903a0033703f0022007427f201d4200200c1b220420157c201f4200200c1b221520057c221b2015542208ad7c22052008200520045420052004511b22081b3703a8032007427f201b20081b3703a003201c200741a0036aad42808080808002841004200041043a000002402010450d0020104104742108200f41046a210003400240200041046a280200450d002000280200102f0b200041106a2100200841706a22080d000b0b02402014450d00200f102f0b200641046a280200450d092012102f0c090b200f20104104746a210c024020100d00200f21080c050b200741a0036aad4280808080800484211c200f210803400240200828020022090d00200841106a21080c060b2007280268220b41164d0d04200841046a280200210a20072802602101200841086a280200210d2008410c6a35020021042009ad4280808080800484100322092900002105200941086a2900002115200941106a290000211b200741a0036a41186a200941186a290000370300200741a0036a41106a201b370300200741a0036a41086a2015370300200720053703a0032009102f200bad4220862001ad84200b41696aad422086200141176aad844101201c2004422086200aad84100f0240200d450d00200a102f0b200841106a2208200c470d000c060b0b20004183243b0100200041086a4115360200200041046a41dacdc100360200200041026a41023a00000c060b1036000b1038000b4117200b104b000b200c2008460d000340200841106a21090240200841086a280200450d00200841046a280200102f0b20092108200c2009470d000b0b02402014450d00200f102f0b20004183243b0100200041086a4110360200200041046a41b0cdc100360200200041026a41043a00000b200741e4006a280200450d002007280260102f0b200641046a280200450d002006280200102f0b200741a0046a24000bd20403067f017e037f230041306b22012400024020002802202202450d00034020002002417f6a360220200028020821032000280200210402400240200028020c2205200028020422062f01064f0d00200621020c010b034002400240024020064190bdc600460d00200628020022020d012003ad2107410021020c020b41edb3ca00412841f8b4ca001039000b200441016a210420063301044220862003ad8421070b2006102f2007a72103200221062007422088a7220520022f01064f0d000b0b200541016a21082002200541e0006c6a220941a0036a280200210a2009419c036a280200210520094198036a2802002106200941e8026a290300210702402004450d00200220084102746a41880b6a2802002102410021082004417f6a2204450d00034020022802880b21022004417f6a22040d000b0b2000200836020c20002003360208200020023602042000410036020020074202510d010240024020050d00200621020c010b2005210320062102034020022802ec0321022003417f6a22030d000b0340200620062f01064102746a41ec036a28020021062005417f6a22050d000b0b2001200a3602282001410036022020014100360218200142003703102001200236020c200141003602082001200636021c200120062f0106360224200141086a109002200028022022020d000b0b02400240200028020422064190bdc600460d00200628020021022006102f2002450d00034020024190bdc600460d02200228020021062002102f2006210220060d000b0b200141306a24000f0b41edb3ca00412841f8b4ca001039000bad0302047f047e230041d0006b22032400024002402001280200220441186a280200220541164d0d00200428021021062002ad42808080808004842207100322042900002108200441086a2900002109200441106a290000210a200341106a41186a200441186a290000370300200341106a41106a200a370300200341106a41086a2009370300200320083703102004102f20032005ad4220862006ad84200541696aad422086200641176aad844101200341106aad428080808080048410101073024002402003280200450d0020012802002204280218220541164d0d032004280210210620071003220441086a2900002108200441106a29000021092004290000210a200341306a41186a200441186a290000370300200341306a41106a2009370300200341306a41086a20083703002003200a3703302004102f2005ad4220862006ad84200541696aad422086200641176aad844101200341306aad4280808080800484101120002002360200200020032903003702042000410c6a200341086a2802003602000c010b200041003602000b200341d0006a24000f0b41172005104b000b41172005104b000ba40301057f230041106b22032400024002400240200141046a2204417f4c0d000240024020040d00410121050c010b2004102d2205450d020b2003410036020820032004360204200320053602002001200310690240024020032802042206200328020822056b2001490d00200328020021040c010b200520016a22042005490d03200641017422072004200720044b1b22074100480d030240024020060d002007102d21040c010b200328020020062007103121040b2004450d022003200736020420032004360200200721060b200420056a2000200110e8061a02400240200241046a2802002207200241086a28020022006b200520016a2201490d00200228020021050c010b200020016a22052000490d03200741017422002005200020054b1b22004100480d030240024020070d002000102d21050c010b200228020020072000103121050b2005450d0220022005360200200241046a2000360200200241086a28020021000b200241086a200020016a360200200520006a2004200110e8061a02402006450d002004102f0b200341106a24000f0b103d000b1036000b1038000bfd0403027f037e027f230041e0016b22022400418de6c300ad4280808080e00084100122032900002104200241086a200341086a290000370300200220043703002003102f41f0e8c600ad4280808080f0008410012203290000210420024198016a41086a200341086a29000037030020022004370398012003102f02404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100322012900002104200141086a2900002105200141106a2900002106200241c8006a41186a2207200141186a290000370300200241c8006a41106a22082006370300200241c8006a41086a2005370300200220043703482001102f2003102f41c000102d2203450d0020032002290300370000200320022903980137001020032002290348370020200341086a200241086a290300370000200341186a20024198016a41086a290300370000200341286a200241c8006a41086a2201290300370000200341306a2008290300370000200341386a2007290300370000200241c8006a200310f6022002290348210420024198016a200141c80010e8061a0240024020044201510d002002410041c50010e7061a0c010b200220024198016a41c80010e8061a0b2003102f200041386a200241386a290300370300200041306a200241306a290300370300200041286a200241286a290300370300200041206a200241206a290300370300200041186a200241186a290300370300200041106a200241106a290300370300200041086a200241086a29030037030020002002290300370300200241e0016a24000f0b1036000bdb130a027f017e017f027e027f067e037f037e027f067e230041e0046b22042400418de6c300ad4280808080e00084100122052900002106200441a8016a41086a200541086a290000370300200420063703a8012005102f41f0e8c600ad4280808080f00084100122052900002106200441206a41086a200541086a290000370300200420063703202005102f0240024002404120102d2205450d0020052001290000370000200541186a200141186a290000370000200541106a200141106a290000370000200541086a200141086a2900003700002005ad4280808080800484100322072900002106200741086a2900002108200741106a2900002109200441e0036a41186a220a200741186a290000370300200441e0036a41106a220b2009370300200441e0036a41086a2008370300200420063703e0032007102f2005102f41c000102d2205450d00200520042903a80137000020052004290320370010200520042903e003370020200541086a200441a8016a41086a290300370000200541186a200441206a41086a290300370000200541286a200441e0036a41086a290300370000200541306a200b290300370000200541386a200a290300370000200441206a200510f6022004290320210c4200210920044200370320200441e8006a280200210a20042d006c210b02400240200c4201510d00200441f0006a41306a4200370300200441f0006a41286a4200370300200441f0006a41206a420037030020044188016a420037030020044180016a4200370300200441f0006a41086a4200370300200442003703704200210d42002108420021064200210e0c010b200441206a41386a290300210f200441206a41306a2903002110200441206a41206a290300210d200441206a41186a2903002109200441206a41c0006a290300210e2004290330210620042903282108200441f0006a41206a200441206a41286a290300370300200441f0006a41286a2010370300200441f0006a41306a200f37030020044180016a20093703002004200d3703880120042008370370200420063703780b427f2006200d7c200820097c22102008542207ad7c220f2007200f200654200f2006511b22071b210f427f201020071b21100240200920027c221142ffffe883b1de1656200d20037c2011200954ad7c22094200522009501b0d002010200f84500d020b2004200237037020042003370378200441a8016a41186a200441f0006a41186a2903002209370300200441a8016a41206a2212200441f0006a41206a290300370300200441a8016a41286a2213200441f0006a41286a290300370300200441a8016a41306a2214200441f0006a41306a290300370300200420033703b001200420023703a8012004200429038001220d3703b8012008200256200620035620062003511b2107200320067d2002200854ad7d2111200620037d2008200254ad7d2115200220087d2116200820027d21172010200f8450211802400240427f2002200d7c220620062002542219200320097c2019ad7c220620035420062003511b22191b2208428080e983b1de16544100427f200620191b2206501b0d00200441b8016a2903002108201429030021092013290300211a2012290300211b20042903b001211c20042903a801211d4201211e20042903c001211f0c010b4200211e02402008200684500d0020082006109a0120044198046a200637030020044190046a2008370300200441e0036a41086a41013a0000200441e9036a2001290000370000200441f1036a200141086a290000370000200441f9036a200141106a29000037000020044181046a200141186a290000370000200441033a00e00341c8e1ca004100200441e0036a108c010b0b2015201120071b210d2017201620071b210f2007ad21102018ad2106200441c8006a201b370300200441d0006a201a370300200441306a201c370300200441d8006a2009370300200441386a20083703002004201f3703402004200e3703602004201d370328410021072004200b4100200c42015122181b3a006c2004200a410020181b3602682004201e420151220aad3703200240200a0d002005ad428080808080088410050c030b200441c0003602e403200420053602e003200441286a200441e0036a109003410121070c020b1036000b420221060b2005102f0240024020064202520d004200210642002108420021090c010b024002400240200c4201510d00200741ff0171450d0041032107200441e0026a21050c010b200c4201520d01200741ff01710d0141042107200441e0016a21050b200541046a20073a0000200541003a0000200541056a20012900003700002005410d6a200141086a290000370000200541156a200141106a2900003700002005411d6a200141186a29000037000041c8e1ca0041002005108c010b02402006427f7c220c4201560d004200210642002108420021090240200ca70e020002000b20044198046a200337030020044190046a2002370300200441e0036a41086a41003a0000200441e9036a2001290000370000200441f1036a200141086a290000370000200441f9036a200141106a29000037000020044181046a200141186a290000370000200441033a00e00341c8e1ca004100200441e0036a108c010b200441e0036a41186a220b4200370300200441e0036a41106a22074200370300200441e0036a41086a22014200370300200442003703e00341e7a2ca00ad428080808080018422021001220a2900002103200441e0016a41086a2205200a41086a290000370300200420033703e001200a102f20012005290300370300200420042903e0013703e00341ecb5c600ad4280808080d0018422031001220a29000021062005200a41086a290000370300200420063703e001200a102f200720042903e0012206370300200441e0026a41086a22182001290300370300200441e0026a41106a22192006370300200441e0026a41186a22122005290300370300200420042903e0033703e002200441086a200441e0026a4120109c01200441086a41106a2903002106200429031021082004280208210a200b42003703002007420037030020014200370300200442003703e00320021001220b29000021022005200b41086a290000370300200420023703e001200b102f20012005290300370300200420042903e0013703e00320031001220b29000021022005200b41086a290000370300200420023703e001200b102f200720042903e0012202370300201820012903003703002019200237030020122005290300370300200420042903e0033703e002200420064200200a1b3703e803200420084200200a1b3703e003200441e0026aad4280808080800484200441e0036aad4280808080800284100420102106200f2108200d21090b2000200837030820002006370300200041106a2009370300200441e0046a24000bd61208027f017e017f027e027f0b7e067f027e230041a0036b2204240020032802002105418de6c300ad4280808080e00084100122032900002106200441d8006a41086a200341086a290000370300200420063703582003102f41f0e8c600ad4280808080f0008410012203290000210620044190016a41086a200341086a29000037030020042006370390012003102f02404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100322072900002106200741086a2900002108200741106a2900002109200441a0026a41186a220a200741186a290000370300200441a0026a41106a220b2009370300200441a0026a41086a2008370300200420063703a0022007102f2003102f41c000102d2203450d00200320042903583700002003200429039001370010200320042903a002370020200341086a200441d8006a41086a290300370000200341186a20044190016a41086a290300370000200341286a200441a0026a41086a290300370000200341306a200b290300370000200341386a200a29030037000020044190016a200310f602200429039001210c420021092004420037039001200441d8016a280200210a20042d00dc01210b02400240200c4201510d00200441206a41306a4200370300200441206a41286a4200370300200441206a41206a4200370300200441386a4200370300200441306a4200370300200441206a41086a4200370300200442003703204200210d42002108420021064200210e0c010b20044190016a41386a290300210f20044190016a41306a290300211020044190016a41206a290300210d20044190016a41186a290300210920044190016a41c0006a290300210e20042903a00121062004290398012108200441206a41206a20044190016a41286a290300370300200441206a41286a2010370300200441206a41306a200f370300200441306a20093703002004200d37033820042008370320200420063703280b427f2006200d7c200820097c220d2008542207ad7c22092007200920065420092006511b22071b210f427f200d20071b21104200211102400240024002402002290300221242ffffe883b1de1656200241086a290300220d420052200d501b0d0042002113420021144200211542002116420021092010200f84500d010b4200211342002006200d7c200820127c22112008542207ad7c22082007200820065420082006511b22071b21094200201120071b210620074101470d0120064280807c832116200642ff0183211120064280fe03832114420021150b2003102f20002014201184201684370308200041106a2015201384200984370300420121060c010b200441a0026a41186a22174200370300200441a0026a41106a22184200370300200441a0026a41086a22024200370300200442003703a00241e7a2ca00ad4280808080800184221310012219290000211420044190026a41086a2207201941086a29000037030020042014370390022019102f2002200729030037030020042004290390023703a00241ecb5c600ad4280808080d0018422141001221929000021152007201941086a29000037030020042015370390022019102f20182004290390022215370300200441d8006a41086a221a2002290300370300200441d8006a41106a221b2015370300200441d8006a41186a22192007290300370300200420042903a002370358200441086a200441d8006a4120109c01200441086a41106a2903002115200429031021162004280208211c201742003703002018420037030020024200370300200442003703a00220131001221729000021132007201741086a29000037030020042013370390022017102f2002200729030037030020042004290390023703a00220141001221729000021132007201741086a29000037030020042013370390022017102f20182004290390022213370300201a2002290300370300201b201337030020192007290300370300200420042903a002370358200420154200201c1b3703a802200420164200201c1b3703a002200441d8006aad4280808080800484200441a0026aad4280808080800284100420042009370328200420063703202019200441306a220741086a2903002213370300200441d8006a41206a2202200741106a29030037030020044180016a2218200741186a29030037030020044188016a2219200741206a290300370300200420093703602004200637035820042007290300221437036802400240427f200620147c221420142006542207200920137c2007ad7c220620095420062009511b22071b2209428080e983b1de16544100427f200620071b2206501b0d00201b290300210620192903002109201829030021132002290300211420042903602115200429035821164201211d2004290370211e0c010b4200211d02402009200684500d0020092006109a01200441d8026a2006370300200441d0026a2009370300200441a0026a41086a41013a0000200441a9026a2005290000370000200441b1026a200541086a290000370000200441b9026a200541106a290000370000200441c1026a200541186a290000370000200441033a00a00241c8e1ca004100200441a0026a108c010b0b200441b8016a2014370300200441c0016a2013370300200441a0016a2015370300200441c8016a2009370300200441a8016a20063703002004201e3703b0012004200e3703d0012004201637039801410021072004200b4100200c42015122021b3a00dc012004200a410020021b3602d8012004201d4201512202ad370390010240024020020d002003ad42808080808008841005410121070c010b200441c0003602a402200420033602a00220044198016a200441a0026a1090030b2003102f2010200f8450ad2106024002400240200c4201510d0020070d0041032107200441a0026a21030c010b200c4201522007410173720d014104210720044190016a21030b200341046a20073a0000200341003a0000200341056a20012900003700002003410d6a200141086a290000370000200341156a200141106a2900003700002003411d6a200141186a29000037000041c8e1ca0041002003108c010b20002006370308200041286a200d370300200041206a2012370300200041186a2008370300200041106a2011370300420021060b20002006370300200441a0036a24000f0b1036000ba60303057f017e027f024020002802202201450d00034020002001417f6a360220200028020821022000280200210302400240200028020c2204200028020422052f01064f0d00200521010c010b034002400240024020054190bdc600460d00200528020022010d012002ad2106410021010c020b41edb3ca00412841f8b4ca001039000b200341016a210320053301044220862002ad8421060b2005102f2006a72102200121052006422088a7220420012f01064f0d000b0b200441016a210720012004410c6c6a220541ec026a2802002108200541e8026a280200210402402003450d00200120074102746a41ec036a2802002101410021072003417f6a2205450d00034020012802ec0321012005417f6a22050d000b0b2000200736020c20002002360208200020013602042000410036020002402004450d002008450d002004102f0b200028022022010d000b0b02400240200028020422054190bdc600460d00200528020021012005102f2001450d00034020014190bdc600460d02200128020021052001102f2005210120050d000b0b0f0b41edb3ca00412841f8b4ca001039000b9e0703057f0c7e067f230041106b21020240200128020422034104490d0020012802002204280000210520012003417c6a22063602042001200441046a36020020064108490d00200429000421072001200341746a220636020420012004410c6a36020020064108490d00200429000c210820012003416c6a22063602042001200441146a36020020064108490d00200429001421092001200341646a220636020420012004411c6a36020020064108490d00200429001c210a20012003415c6a22063602042001200441246a36020020064108490d002004290024210b2001200341546a220636020420012004412c6a36020020064108490d00200429002c210c20012003414c6a22063602042001200441346a36020020064108490d002004290034210d2001200341446a220636020420012004413c6a36020020064108490d00200429003c210e2001200341bc7f6a22063602042001200441c4006a36020020064108490d002004290044210f2001200341b47f6a22063602042001200441cc006a36020020064108490d00200429004c21102001200341ac7f6a22063602042001200441d4006a36020020064108490d00200429005421112001200341a47f6a22063602042001200441dc006a36020020064108490d00200429005c211220012003419c7f6a22063602042001200441e4006a36020020064104490d00200428006421132001200341987f6a22063602042001200441e8006a36020020064104490d00200428006821142001200341947f6a22063602042001200441ec006a36020020064104490d00200428006c21152001200341907f6a22063602042001200441f0006a36020020064104490d002004280070211620012003418c7f6a22063602042001200441f4006a22043602002006450d0020042d0000210620012003418b7f6a22173602042001200441016a360200200641014b0d00410021180240024020060e020100010b410121180b20174104490d00200428000121062001200341877f6a3602042001200441056a360200200020183a007820002006360274200020163602702000201536026c2000201436026820002013360264200020053602602000201237035820002011370350200020103703482000200f3703402000200e3703382000200d3703302000200c3703282000200b3703202000200a370318200020093703102000200837030820002007370300200041fc006a2002410c6a280000360000200020022800093600790f0b200041023a00780bc31606027f017e017f027e097f017e230041b0016b2203240041aa97ca00ad4280808080800184100122042900002105200341e8006a41086a200441086a290000370300200320053703682004102f41e4f4c100ad4280808080b00184100122042900002105200341c8006a41086a200441086a290000370300200320053703482004102f0240024002400240024002404120102d2204450d0020042001290000370000200441186a200141186a290000370000200441106a200141106a290000370000200441086a200141086a2900003700002004ad4280808080800484100322062900002105200641086a2900002107200641106a2900002108200341f8006a41186a2209200641186a290000370300200341f8006a41106a220a2008370300200341f8006a41086a2007370300200320053703782006102f2004102f41c000102d2204450d00200420032903683700002004200329034837001020042003290378370020200441086a200341e8006a41086a290300370000200441186a200341c8006a41086a290300370000200441286a200341f8006a41086a290300370000200441306a200a290300370000200441386a2009290300370000200341c00036029c012003200436029801200341286a2004ad428080808080088410021073024002402003280228220b0d004102210a0c010b200328022c210c2003200341286a41086a2802003602a4012003200b3602a001200341206a200341a0016a10e6010240024020032802200d0020032802242106200341186a200341a0016a10e60120032802180d00200328021c2109200341106a200341a0016a10e60120032802100d0020032802a401220a450d002003280214210d2003200a417f6a3602a401200320032802a001220a41016a3602a001200a2d0000220e41014b0d004100210a02400240200e0e020100010b4101210a0b200341086a200341a0016a10e60120032802080d0020032802a401220f200328020c2210490d002010417f4c0d040240024020100d004101210e0c010b20101033220e450d04200e20032802a0012211201010e8061a2003200f20106b3602a4012003201120106a3602a0010b200e450d002010ad22054220862005842105200341e8006a41026a200341f8006a41026a2d00003a0000200320032f00783b01680c010b20034100360250200342013703482003410b36026c200320034198016a3602682003200341c8006a3602ac012003418c016a41013602002003420137027c200341b885c7003602782003200341e8006a36028801200341ac016a41d8dbc100200341f8006a103c1a200335025042208620033502488410080240200328024c450d002003280248102f0b4102210a0b200c450d00200b102f0b200341f8006a41026a200341e8006a41026a2d00003a0000200320032f01683b017802400240200a4102470d004101210b41848ec2002106411121090c010b200341c8006a41026a200341f8006a41026a2d00003a0000200320032f01783b01484100210b0b2004102f200341c4006a41026a2204200341c8006a41026a2d00003a0000200320032f01483b014402400240200b0d00200341386a220b2005370300200341c3006a20042d00003a00002003200a3a00402003200e3602342003200d3602302003200936022c200320032f01443b004120032006360228200341286a41086a2109200228026020064b0d010c060b2000200636020420004101360200200041086a20093602000c060b41aa97ca00ad4280808080800184100122042900002107200341e8006a41086a200441086a290000370300200320073703682004102f41c0f4c100ad4280808080c00184100122042900002107200341c8006a41086a200441086a290000370300200320073703482004102f4120102d2204450d0020042001290000370000200441186a200141186a290000370000200441106a200141106a290000370000200441086a200141086a2900003700002004ad4280808080800484100322062900002107200641086a2900002108200641106a2900002112200341f8006a41186a220a200641186a290000370300200341f8006a41106a220d2012370300200341f8006a41086a220c2008370300200320073703782006102f2004102f41c000102d2204450d002005a72110200420032903683700002004200329034837001020042003290378370020200441086a200341e8006a41086a290300370000200441186a200341c8006a41086a290300370000200441286a200c290300370000200441306a200d290300370000200441386a200a290300370000200341f8006a200441c000109302200329027c2105200328027821062004102f02400240024002402006450d00200341f8006a20062005422088a720021094022005a7210220032802784101460d03200341c8006a41186a220d200341f8006a410472220441186a280200360200200341c8006a41106a220c200441106a290200370300200341c8006a41086a220a200441086a2902003703002003200429020037034802402010450d00200e102f0b200341286a41186a200d280200360200200341286a41106a200c290300370300200341286a41086a200a2903003703002003200329034837032841aa97ca00ad4280808080800184100122042900002105200341e8006a41086a200441086a290000370300200320053703682004102f41e4f4c100ad4280808080b00184100122042900002105200a200441086a290000370300200320053703482004102f4120102d2204450d0420042001290000370000200441186a200141186a290000370000200441106a200141106a290000370000200441086a200141086a2900003700002004ad4280808080800484100322012900002105200141086a2900002107200141106a2900002108200341f8006a41186a220a200141186a290000370300200341f8006a41106a220e2008370300200341f8006a41086a220d2007370300200320053703782001102f2004102f41c000102d2204450d04200420032903683700002004200329034837001020042003290378370020200441086a200341e8006a41086a290300370000200441186a200341c8006a41086a290300370000200441286a200d290300370000200441306a200e290300370000200441386a200a290300370000200341003602800120034201370378200341286a200341f8006a109502200341286a410472200341f8006a1095022009200341f8006a10950220032d0040210e200328027c2003280280012201460d012003280278210a0c020b200041958ec20036020420004101360200200041086a411a3602000c060b200141016a220a2001490d042001410174220d200a200d200a4b1b220d4100480d040240024020010d00200d102d210a0c010b20032802782001200d1031210a0b200a450d022003200d36027c2003200a3602780b2003200141016a36028001200a20016a200e3a00002003280234210c2003413c6a280200220a200341f8006a106902400240200328027c220d200328028001220e6b200a490d00200328027821010c010b200e200a6a2201200e490d04200d41017422102001201020014b1b22104100480d0402400240200d0d002010102d21010c010b2003280278200d2010103121010b2001450d022003201036027c200320013602782010210d0b2001200e6a200c200a10e8061a2004ad4280808080800884200e200a6aad4220862001ad8410040240200d450d002001102f0b2004102f2002450d052006102f0c050b2000200329027c370204200041013602002002450d032006102f0c030b1036000b103d000b1038000b2010450d01200e102f0c010b20002003290328370204200041003602002000411c6a200341c0006a280200360200200041146a200b2903003702002000410c6a20092903003702000b200341b0016a24000b980302057f017e230041e0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad8410021073024002400240024020032802102201450d00200328021421022003200341186a280200360224200320013602202003200341206a10e6010240024020032802000d002003280224220420032802042205490d002005417f4c0d040240024020050d00410121060c010b200510332206450d06200620032802202207200510e8061a2003200420056b3602242003200720056a3602200b2006450d0020002005ad2208422086200884370204200020063602000c010b20034100360230200342013703282003410b36023c2003200341086a3602382003200341286a360244200341dc006a41013602002003420137024c200341b885c7003602482003200341386a360258200341c4006a41d8dbc100200341c8006a103c1a200335023042208620033502288410080240200328022c450d002003280228102f0b200041003602000b2002450d012001102f0c010b200041003602000b200341e0006a24000f0b103d000b1036000bf79c0106167f017e047f017e037f027e230041e0046b22042400200441003602b002200420023602ac02200420013602a80202400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020024104490d00200441043602b00220012800004180c2cdeb06460d01410121010c030b200441013a0068200441e4036a4101360200200442013702d403200441b4afca003602d0032004412836029402200420044190026a3602e0032004200441e8006a3602900220044180016a200441d0036a103a0c010b0240024002400240024002402002417c714104460d00200241074d0d02200441083602b0020240200128000422054101460d00410221010c080b200441d0036a200441a8026a10cc0420042802d0034101470d014104210641002107410021080c040b200441013a0068200441e4036a4101360200200442013702d403200441b4afca003602d0032004412836029402200420044190026a3602e0032004200441e8006a3602900220044180016a200441d0036a103a0c050b200441d0036a410572210941042106412c210a4100210541002107410021084100210b034020044190026a41026a2201200941026a2d00003a0000200420092f00003b019002200428028004210c20042802fc03210d20042802f803210e20042802f403210f20042802f003211020042802ec03211120042802e803211220042802e403211320042802e003211420042802dc03211520042802d8032116024020042d00d4032217417e6a41ff0171410c4f0d0041002118024002400240024002400240024002400240024002400240024020170e100c0c000102030405060708090a0b0c0c0c0b410121180c0b0b410221180c0a0b410321180c090b410421180c080b410521180c070b410621180c060b410721180c050b410821180c040b410921180c030b410a21180c020b410b21180c010b410c21180b0240200b41ff0171221920184d0d00411321010c040b41002118024002400240024002400240024002400240024002400240024020170e100c0c000102030405060708090a0b0c0c0c0b410121180c0b0b410221180c0a0b410321180c090b410421180c080b410521180c070b410621180c060b410721180c050b410821180c040b410921180c030b410a21180c020b410b21180c010b410c21180b024020192018470d00411421010c040b4100210b02400240024002400240024002400240024002400240024020170e100c0c000102030405060708090a0b0c0c0c0b4101210b0c0b0b4102210b0c0a0b4103210b0c090b4104210b0c080b4105210b0c070b4106210b0c060b4107210b0c050b4108210b0c040b4109210b0c030b410a210b0c020b410b210b0c010b410c210b0b20044180016a41026a221820012d00003a0000200420042f0190023b018001024020072008470d00200741016a22012007490d0920052001200520014b1bad42307e221a422088a70d09201aa722014100480d090240024020070d002001102d21060c010b2006200a41546a2001103121060b2006450d0a200141306e21080b2006200a6a220141546a20173a00002001200c3602002001417c6a200d360200200141786a200e360200200141746a200f360200200141706a20103602002001416c6a2011360200200141686a2012360200200141646a2013360200200141606a20143602002001415c6a2015360200200141586a2016360200200141556a220120042f0180013b0000200141026a20182d00003a0000200541026a2105200a41306a210a200741016a2107200441d0036a200441a8026a10cc0420042802d0034101460d030c000b0b41082002104a000b024002402017410e4b0d00024002400240024002400240024002400240024002400240024020170e0f0001020304050607080e090e0a0b0c000b2015450d0d2016102f0c0d0b02402015450d002016102f0b2012450d0c2013102f0c0c0b02402014450d002014410474210a2016211703400240201741046a280200450d002017280200102f0b201741106a2117200a41706a220a0d000b0b2015450d0b2016102f0c0b0b02402014450d00201441286c210a2016211703400240201741046a280200450d002017280200102f0b0240201741106a280200450d002017410c6a280200102f0b201741286a2117200a41586a220a0d000b0b2015450d0a2016102f0c0a0b2015450d092016102f0c090b2015450d082016102f0c080b2015450d072016102f0c070b02402014450d00201620144104746a211220162114034002402014280208220a450d0020142802002117200a410474210a0340024020172d00004109470d000240201741046a2209280200220528020441ffffffff0371450d002005280200102f200928020021050b2005102f0b201741106a2117200a41706a220a0d000b0b201441106a21170240201441046a280200450d002014280200102f0b2017211420172012470d000b0b2015450d062016102f0c060b02402014450d00201441146c210a2016211703400240201741046a280200450d002017280200102f0b201741146a2117200a416c6a220a0d000b0b2015450d052016102f0c050b02402014450d0020162014411c6c6a2112201621140340024020142802042217450d0002402014410c6a280200220a450d00200a410474210a0340024020172d00004109470d000240201741046a2209280200220528020441ffffffff0371450d002005280200102f200928020021050b2005102f0b201741106a2117200a41706a220a0d000b0b201441086a280200450d002014280204102f0b2014411c6a21170240201441146a280200450d002014280210102f0b2017211420172012470d000b0b2015450d042016102f0c040b02402014450d002016201441186c6a21122016211403400240201441046a280200450d002014280200102f0b0240201441146a280200220a450d00201428020c2117200a410474210a0340024020172d00004109470d000240201741046a2209280200220528020441ffffffff0371450d002005280200102f200928020021050b2005102f0b201741106a2117200a41706a220a0d000b0b201441186a21170240201441106a280200450d00201428020c102f0b2017211420172012470d000b0b2015450d032016102f0c030b02402014450d0020162014411c6c6a2112201621140340024020142802042217450d0002402014410c6a280200220a450d00200a410474210a0340024020172d00004109470d000240201741046a2209280200220528020441ffffffff0371450d002005280200102f200928020021050b2005102f0b201741106a2117200a41706a220a0d000b0b201441086a280200450d002014280204102f0b2014411c6a21170240201441146a280200450d002014280210102f0b2017211420172012470d000b0b2015450d022016102f0c020b02402016450d002015450d002016102f0b02402012450d0002402010450d002010410c6c210a201221170340024020172802002205450d00201741046a280200450d002005102f0b2017410c6a2117200a41746a220a0d000b0b2011450d002012102f0b200e450d010240200c450d00200e200c4104746a2115200e211603402016220941106a2116024020092802042217450d0002402009410c6a280200220a450d00200a410c6c210a0340024020172802002205450d00201741046a280200450d002005102f0b2017410c6a2117200a41746a220a0d000b0b200941086a280200450d002009280204102f0b20162015470d000b0b200d450d01200e102f0c010b02402015450d002016102f0b02402012450d002011450d002012102f0b200e450d00200f102f0b0c010b024020042d00d4030d002006200741306c6a21172006210102400340024020172001470d00410021090c020b20012d0000210b200141306a220a2101200b410c470d000b200a415c6a28020021090b2006200741306c6a210a2006210b02400340410021010240200a200b470d004100210b0c020b200b2d00002117200b41306a2205210b20174104470d000b200441e0006a200541546a10d6032004280264210b0b02402009200b470d004101210541e100210b41f3da0121174100210a0c050b2006200710cd044101210a411a2101024020080d000c050b2006102f0c040b20042802d403220141107621172001410876210b200441d0036a41106a2802002109200441dc036a2802002116200441d0036a41086a28020021050b2006200710cd044101210a02402008450d002006102f0b20092108201621060c020b200428028001210520042802840121062004280288012108410521010b410021174104410010cd044101210a4100210b0b2017411074200b41ff017141087472200141ff01717221170240200a450d002006210b0c110b20042802b0022002470d0f200441d0026a2007360200200441cc026a2008360200200420063602c802200420053602c402200420173602c002200441d0036a200441c0026a10ce04024020042802d0032201450d00024020042802d403450d002001102f0b2006200710cd0441b689ca002101411321022008450d122006102f0c120b2006200741306c6a210b20062101024003400240200b2001470d00410021010c020b20012d00002102200141306a220a210120024102470d000b200441d8006a200a41546a10d60320042802582101200428025c21020b2002410020011b2112200141c8e1ca0020011b210e2006200741306c6a210b20062101024003400240200b2001470d00410021010c020b20012d00002102200141306a220a210120024108470d000b200441d0006a200a41546a10d60320042802502101200428025421020b2002410020011b2111200141c8e1ca0020011b21162006200741306c6a210b20062101024003400240200b2001470d00410021010c020b20012d00002102200141306a220a210120024104470d000b200441c8006a200a41546a10d60320042802482101200428024c21020b2002410020011b2115200141c8e1ca0020011b21142006200741306c6a210a2006210102400340410021020240200a2001470d00410021010c020b20012d0000210b200141306a22092101200b4103470d000b200441c0006a200941546a10d603200428024021012004280244210b0b0240200b410020011b220b450d00200b41286c210b200141c8e1ca0020011b41186a2101410021020340200220012d0000456a2102200141286a2101200b41586a220b0d000b0b024020110d00411e2101200041858cca003602040c0f0b2016201141146c6a21114100210c4100211002400240034041a38cca00210b41382101201641086a280200417c6a220941024b0d012016280200210a02400240024020090e03000401000b41012110200a41fb8bca00460d01200a28000041e3c2b1e306460d010c030b4101210c200a41ff8bca00460d00200a41ff8bca00410610ea060d020b02402016410c6a280200450d0041132101200041a18dca003602040c120b0240201641106a280200220120026b220a20014d0d00412a2101200041b48dca003602040c120b41fb8cca00210b412621012015200a4d0d012014200a4102746a220a450d0141db8cca00210b412021012012200a280200220a4d0d01200e200a4104746a220a450d0141de8dca00210b411f2101200a2802080d01200a2d000d220a41077141044b0d010240200a0e050002020200000b201641146a22162011470d000b200c2010714101710d01411c411e200c41017122021b2101200041fd8dca0041858cca0020021b3602040c100b2000200b3602040c0f0b2006200741306c6a210b2006210102400340200b2001460d0120012d00002102200141306a220a210120024106470d000b200441386a200a41546a10d603200428023c0d030b2006200741306c6a210b200328027021092006210102400340200b2001460d0120012d00002102200141306a220a210120024105470d000b200441306a200a41546a220110d6030240200428023441014d0d0041182101200041e889ca003602040c100b200441286a200110d603200428022c450d0020042802282201450d00200128020020094d0d0041222101200041808aca003602040c0f0b2006200741306c6a210b2006210102400340200b2001460d0120012d00002102200141306a220a210120024107470d000b200441206a200a41546a10d6032004280220220120042802244104746a210b03402001200b460d012001450d012001410c6a2102200141106a210120022d0000410271450d000b413221012000418c8bca003602040c0f0b2006200741306c6a210b2006210102400340200b2001460d0120012d00002102200141306a220a21012002410c470d000b200a415c6a2802002201450d00200a41546a280200220a200141186c6a21090340200a220241186a210a2002280208410374210120022802002102024003402001450d01200141786a210120022d0004210b200241086a2102200b410271450d000b41312101200041db8aca003602040c110b200a2009470d000b0b2006200741306c6a210b2006210102400340200b2001460d0120012d00002102200141306a220a210120024102470d000b200441186a200a41546a10d603200428021c2201450d002004280218220220014104746a211503402002450d01200241106a2116200420022d000d220b3a00d0032002280200220120022802086a2109410021024100200441d0036a200b4104461b210a024003400240024002400240200241ff01710e03000102000b20012009460d01410021022001210b200141016a21010c020b20012009460d03410121022001210b200141016a21010c010b200a450d0241022102200a210b4100210a0b200b2d0000410271450d000b41392101200041a28aca003602040c110b2016210220162015470d000b0b2006200741306c6a210b20062101024003400240200b2001470d00410021010c020b20012d00002102200141306a220a210120024102470d000b200441106a200a41546a10d60320042802102101200428021421020b2002410020011b210e200141c8e1ca0020011b21112006200741306c6a210b20062101024003400240200b2001470d00410021010c020b20012d00002102200141306a220a210120024103470d000b200441086a200a41546a10d60320042802082101200428020c210b0b200141c8e1ca0020011b2202200b410020011b41286c6a210a41002114034002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402002200a460d00412d210141d494c600210b20022802084103470d2702402002280200220941d0bcca00460d00200941d0bcca00410310ea060d280b200241286a21154115210941cd93c60021164114210141c094c600210b0240024020022d00180e0401290028010b412f2101418195c600210b20022802144106470d280240200228020c2209419193c600460d002009419193c600410610ea060d290b2014450d02411f2101200041b095c6003602040c290b41362109419793c6002116200e200228021c22014d0d26201120014104746a2212450d2620022802142109200228020c2102024020032d00780d002009410b470d0041382101418894c600210b200241f896ca00460d28410b2109200241f896ca00410b10ea06450d280c0e0b4100211602402009417d6a220141124d0d004100210b0c100b4100210b0240024002400240024002400240024002400240024002400240024020010e13001d1d1d1d041d071b0b0a1d011d1d1d1d1d0c000b4126210141e293c600210b200241d3bcca00460d34200241d3bcca00410310ea06450d3441d3bcca002002410310ea060d1b4101102d220c450d28200c41003a000020122d000c41e000460d010c190b200241a994ca00460d0141a994ca002002410f10ea06450d01200241b894ca00460d0341b894ca002002410f10ea06450d030240200241cf94ca00460d0041cf94ca002002410f10ea060d1b0b4107102d2209450d2720094100360003200941013a0002200941003b000020122d000c41e000460d060c170b20122802084101470d17024020122802002210200c460d0041002102034020024101460d01200c20026a2109201020026a2116200241016a210220162d000020092d0000470d190c000b0b20122d000d4104470d17200c102f201521020c240b4104102d2209450d252009410036000020122d000c41e000470d1420122802084104470d140240201228020022162009460d0041002101034020014104460d01200920016a2102201620016a210b200141016a2101200b2d000020022d0000470d160c000b0b20122d000d4104470d142009102f201521020c230b200241c794ca00460d01200229000042e5f0d1fbb5ac98b6ec00510d010c170b4101102d2209450d23200941003a000020122d000c41e000470d1120122802084101470d11201228020022162009460d1041002101034020014101460d11200920016a2102201620016a210b200141016a2101200b2d000020022d0000470d120c000b0b4107102d2209450d2220094100360003200941013a0002200941003b000020122d000c41e000470d0e20122802084107470d0e201228020022162009460d0d41002101034020014107460d0e200920016a2102201620016a210b200141016a2101200b2d000020022d0000470d0f0c000b0b200241de94ca00460d0141de94ca002002410a10ea06450d010240200241e894ca00460d0041e894ca002002410a10ea060d060b4126210941e293c600211620122d000c41e000470d2c20122802080d2c2015210220122d000d4104460d1f0c2c0b20122802084107470d10201228020022162009460d0a41002101034020014107460d0b200920016a2102201620016a210b200141016a2101200b2d000020022d0000470d110c000b0b4102102d2209450d1f200941003b000020122d000c41e000470d0820122802084102470d080240201228020022162009460d0041002101034020014102460d01200920016a2102201620016a210b200141016a2101200b2d000020022d0000470d0a0c000b0b20122d000d4104470d082009102f201521020c1d0b0240200241fd94ca00460d004100211641fd94ca002002410d10ea060d120b4126210941e293c600211620122d000c41e000470d2920122802080d292015210220122d000d4104460d1c0c290b02402002418a95ca00460d0041002116418a95ca002002410c10ea060d110b4126210941e293c600211620122d000c41e000470d2820122802080d282015210220122d000d4104460d1b0c280b0240200241a195ca00460d004100211641a195ca002002411510ea060d120b4126210941e293c600211620122d000c41e000470d2720122802080d272015210220122d000d4104460d1a0c270b0240200241b695ca00460d0041b695ca002002410a10ea060d260b4102102d2209450d1b200941003b000020122d000c41e000470d0320122802084102470d030240201228020022162009460d0041002101034020014102460d01200920016a2102201620016a210b200141016a2101200b2d000020022d0000470d050c000b0b20122d000d4104470d032009102f201521020c190b024020140d004100211b4100211c0c020b024020142802040d00200041cf95c600360204413221010c280b02402014280200221b201441086a280200221c4d0d002000418196c60036020441c90021010c280b201c200328026c4d0d01200041ca96c60036020441c10021010c270b2002411c6a2114201521020c170b200441d0036a41086a2202420037030020044190bdc6003602d40320042003290308221aa7417f201a428080808010541b3602e00320042003290310221aa7417f201a428080808010541b3602d003200441d0036a4104722201410d10cf042001410c10cf042001410710cf042001410f10cf04200441e8006a41106a20042802e003360200200441e8006a41086a2002290300370300200420042903d003370368200441d0036a41106a220b2007360200200441d0036a410c6a2008360200200420063602d803200420053602d403200420173602d00320044180016a200441d0036a10d0044101102d2201450d18200141003a0000200420042f01d00322073b01c002200b41e0083b01002002428180808010370300200420013602d403200441013602d003200420073b01e20320044180016a200441d0036a10d10421174103102d2202450d18200241026a41002d00d2bc4a3a0000200241002f00d0bc4a3b00004103102d2207450d18200741026a41002d00d5bc4a3a0000200741002f00d3bc4a3b0000200441c0026a41026a200441d0036a41026a220a2d000022063a0000200420042f00d00322083b01c00220044194016a280200210b20044180016a41106a2802002101200a20063a0000200420083b01d0030240200b2001470d00200141016a220b2001490d182001410174220a200b200a200b4b1bad42287e221a422088a70d18201aa7220b4100480d180240024020010d00200b102d21010c010b200428028c01200141286c200b103121010b2001450d192004200136028c012004200b41286e36029001200428029401210b0b200428028c01200b41286c6a220141003a00182001200736020c200142838080803037020420012002360200200141106a428380808030370200200141196a20042f01d0033b00002001411b6a200441d2036a2d00003a00002001411c6a2017360200200420042802940141016a36029401200441d0036a20044180016a418c0110e8061a20044190026a200441d0036a10d20420044190026a41106a280200220841306c2101200428029802220a41546a210202400340410021072001450d01200141506a21012002412c6a210b200241306a22172102200b2d00004103470d000b201741086a2802002201450d00200141286c2102201728020041186a2101410021070340200720012d0000456a2107200141286a2101200241586a22020d000b0b200841306c2101200a41546a21022007417f6a210b02400340410021072001450d01200141506a21012002412c6a2117200241306a2206210220172d00004103470d000b200641086a2802002201450d00200141286c2102200628020041186a2101410021070340200720012d0000456a2107200141286a2101200241586a22020d000b0b200841306c2101200a415c6a21020240034041002105024020010d00410021010c020b200141506a2101200241246a2117200241306a2206210220172d00004104470d000b200628020021010b02400240024002402008450d00200120076a2113200a200841306c6a210c200441e8006a41047221194100211d4100211803400240200a2d000041786a220141044b0d0002400240024002400240024020010e050301020600030b200a28020c2201450d05200a2802042217200141186c6a211e201821010340200121180240201722072802144104742202450d00200728020c21010340024020012d0000410b470d00200141046a22172802002206200b490d002017200641016a3602000b200141106a2101200241706a22020d000b0b200442003703e00320044280808080c0003703d803200442043703d0034110102d2201450d2420042802d8032102200420013602d003200441013602d403200120024104746a22014200370200200141056a4200370000200420042802d80341016a3602d80302402007280214220e450d0041002115200e210103400240024002400240201520014f0d00411021080240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200728020c221020154104746a2d000022120eac010001020202020202020202020202020303030404050506060707080809090a0a0b0b0c0d0d0e0e0f0f1010111213131414151516161717181819191a1a1b1b1c1c1d1d1e1e1f1f2020212122222323242425252627272828292a2a2b2b2c2d2d2e2e2f2f303031313232333434353536363737383839393a3a3b3b3c3c3d3d3e3e3f3f40404141424243434444454546464747484a4a4a4a49494a4a4a4a4a4a4a4a4a4a4a4a4a4a4b4b4b4b000b411121080c4a0b411221080c490b410a21080c480b410821080c470b410821080c460b410421080c450b410421080c440b410421080c430b410421080c420b410421080c410b410421080c400b410421080c3f0b410521080c3e0b410521080c3d0b410521080c3c0b410521080c3b0b410521080c3a0b411321080c390b411421080c380b410621080c370b410721080c360b410b21080c350b410b21080c340b410b21080c330b410b21080c320b410b21080c310b410b21080c300b410b21080c2f0b410b21080c2e0b410b21080c2d0b410b21080c2c0b410b21080c2b0b410c21080c2a0b410c21080c290b410c21080c280b410c21080c270b410c21080c260b410c21080c250b410021080c240b410021080c230b410121080c220b410221080c210b410321080c200b410321080c1f0b410021080c1e0b410021080c1d0b410021080c1c0b410021080c1b0b410021080c1a0b410021080c190b410121080c180b410221080c170b410321080c160b410321080c150b410021080c140b410021080c130b410021080c120b410021080c110b410d21080c100b410d21080c0f0b410d21080c0e0b410d21080c0d0b410d21080c0c0b410d21080c0b0b410d21080c0a0b410d21080c090b410d21080c080b410d21080c070b410d21080c060b410d21080c050b410d21080c040b410d21080c030b410e21080c020b410e21080c010b410f21080b201541016a21142004280270210520192101024002400240034002400240200128020022062f010622010d00410021010c010b200641086a2116410021170340200120172202460d01200241016a211702404100417f4101201620026a2d0000220920084b1b20092008461b41016a0e03000401000b0b2017417f6a21010b2005450d022005417f6a2105200620014102746a41ec006a21010c000b0b200620024103746a220241186a2101200241146a2802000e04000d0100000b200441e8006a21010b20012802002102024002400240024002400240024002402012417e6a220141084b0d00024020010e09020403000506060708020b200441d0036a201510d304450d0b0c130b20042802d8032201417f6a221720014f0d12201720014b0d1220042802d00320174104746a2217280208220120026a22022001490d12201741086a20023602000c0a0b20042802d8032201417f6a221720014f0d11201720014b0d1120042802d00320174104746a2217280208220120026a22022001490d11201741086a200236020020042802d8032201417f6a221720014f0d11201720014b0d1120042802d003220220174104746a280204211702400240200120042802d403460d00200121060c010b200141016a22062001490d30200141017422082006200820064b1b220641ffffffff00712006470d30200641047422064100480d3020022001410474200610312202450d31200420023602d003200420064104763602d40320042802d80321060b200220064104746a220241003a000c2002201736020420022001360200200220042f00c0023b000d200241086a41003602002002410f6a200441c2026a2d00003a0000200420042802d80341016a3602d8030c090b20042802d8032201417f6a221720014f0d10201720014b0d1020042802d00320174104746a2217280208220120026a22022001490d10201741086a200236020020042802d803220221010240200220042802d403470d00200241016a22012002490d2f200241017422172001201720014b1b220141ffffffff00712001470d2f200141047422014100480d2f0240024020020d002001102d21170c010b20042802d00320024104742001103121170b2017450d30200420173602d003200420014104763602d40320042802d80321010b20042802d00320014104746a220141003a000c2001201436020420012002360200200120042f00c0023b000d200141086a41003602002001410f6a200441c2026a2d00003a0000200420042802d80341016a3602d8030c080b20042802d8032201417f6a221720014f0d0f201720014b0d0f20042802d00320174104746a2217280208220120026a22022001490d0f201741086a200236020020042802d803220221010240200220042802d403470d00200241016a22012002490d2e200241017422172001201720014b1b220141ffffffff00712001470d2e200141047422014100480d2e0240024020020d002001102d21170c010b20042802d00320024104742001103121170b2017450d2f200420173602d003200420014104763602d40320042802d80321010b20042802d00320014104746a220141013a000c2001201436020420012002360200200120042f00c0023b000d200141086a41003602002001410f6a200441c2026a2d00003a0000200420042802d80341016a3602d8030c070b200441d0036a201510d3040d0e20042802d8032202450d0e20042002417f6a22013602d80320042802d003221720014104746a22062d000c4102460d0e2001450d062002417e6a220220014f0d0e201720024104746a22172006280200220220172802002217201720024b1b360200200220014f0d06200441d0036a201510d3040d0e0c060b20042802d8032201417f6a221720014f0d0d201720014b0d0d20042802d00320174104746a2217280208220120026a22022001490d0d201020154104746a41046a2802002106201741086a200236020020042802d8032201417f6a220220014b0d0d200220066b220120024b0d0d200441d0036a201510d3040d0d20042802d803220220014d0d0d20042802d003221720014104746a2d000c0d05200241047420176a41706a2202200120022802002202200220014b1b3602000c050b20042802d8032201417f6a221720014f0d0c201720014b0d0c20042802d00320174104746a2217280208220120026a22022001490d0c201741086a200236020020042802d8032201417f6a220820014b0d0c201020154104746a41046a280200220128020421022001280200211220012802082101200441003a00c0020240200820016b220120084d0d00200441013a00c0020c0d0b4104102d2206450d2b20062001360200024020020d0041012117410121160c040b200820122802006b220520084b0d024102211720024102742110410121164104210141022102034002402017417f6a22092016470d00200941016a22162009490d2c20022016200220164b1b220941ffffffff03712009470d2c200941027422094100480d2c0240024020020d002009102d21060c010b200620012009103121060b2006450d2d200941027621160b200620016a200536020020102001460d04201220016a2105201741016a2117200241026a2102200141046a2101200820052802006b220520084d0d000b200441013a00c0020c0b0b20042802d8032201417f6a221720014f0d0b201720014b0d0b20042802d00320174104746a2217280208220120026a22022001490d0b201741086a2002360200200441d0036a201510d3040d0b20042802d8032201450d0b20042802d00322022d000c0d03200141047420026a41706a41003602000c030b41d8bcca0020152001103b000b41012116200441013a00c0020c080b20042d00c0020d072006450d082017ad4220862016ad84211a410121090240200441d0036a201510d3040d0041002109201a422088a72201450d0020014102742117200621010340024020042802d8032208200128020022024b0d00410121090c020b024020042802d003220520024104746a2d000c0d00200841047420056a41706a2208200220082802002208200820024b1b3602000b200141046a21012017417c6a22170d000b0b0240201aa7450d002006102f0b20090d080b2014200e460d0120072802142101201421150c000b0b20042802dc0320042802e4032201410041202001676b10d40420042903e003211f20042802dc032120024020042802d403450d0020042802d003102f0b024020200d004101211d0c070b02400240024020072802142202201f422088a722084101746a220141ffffffff00712001470d0020014104742217417f4c0d000240024020170d00410821060c010b2017102d2206450d2820174104762101200728021421020b20074100360214200728020c21212007200636020c200741106a2209280200212220092001360200202120024104746a2106202020084103746a210f41022116024020020d0020202110202121010c020b41002101202021104100210820212102034020022d00002105200441d0036a41026a220e200241036a22152d00003a00002004200241016a22142f00003b01d003200241046a2800002112200241086a290000211a200441c0026a41026a221720152d00003a0000200420142f00003b01c0020240200541ac01470d00200241106a21010c040b200441a8026a41026a20172d000022153a0000200420042f01c00222143b01a802201720153a0000200420143b01c0020240024020164102470d0002402010200f470d0041002116200f21100c020b20102902002223422088a7210d2023a7211141012116201041086a21100b20164101470d0020082011470d00024020012009280200470d00200141016a22162001490d29200141017422152016201520164b1b221641ffffffff00712016470d29201641047422164100480d290240024020010d002016102d21010c010b200728020c20014104742016103121010b2001450d2a2007200136020c20092016410476360200200728021421010b200728020c20014104746a220120042f00d0033b00012001412d3a00002001200d360204200141036a200e2d00003a00002007200728021441016a2201360214024020012009280200470d00200141016a22162001490d29200141017422152016201520164b1b221641ffffffff00712016470d29201641047422164100480d290240024020010d002016102d21010c010b200728020c20014104742016103121010b2001450d2a2007200136020c20092016410476360200200728021421010b200728020c20014104746a2201200b3602042001410b3a00002007200728021441016a220136021441022116200821110b200441fc006a41026a221520172d00003a0000200420042f01c0023b017c024020012009280200470d00200141016a22172001490d28200141017422142017201420174b1b221741ffffffff00712017470d28201741047422174100480d280240024020010d002017102d21010c010b200728020c20014104742017103121010b2001450d292007200136020c20092017410476360200200728021421010b200841016a2108200728020c20014104746a220120042f017c3b0001200120053a00002001201a37030820012012360204200141036a20152d00003a00002007200728021441016a2201360214200241106a22022006470d000b200621010c010b103d000b200441c0026a41026a200441d0036a41026a2d00003a0000200420042f01d0033b01c0020b024020062001460d000340200141106a2102024020012d00004109470d000240200141046a2217280200220128020441ffffffff0371450d002001280200102f201728020021010b2001102f0b2002210120062002470d000b0b201fa7210102402022450d002021102f0b2010200f47201620164102461b210202402001450d002020102f0b024020024101470d004101211d0c070b200741186a2117024002402004280278450d0020072802142202450d00200728020c210120024104742102410021070340024020012d0000412c470d002001410b3a0000200141046a2013360200200741016a21070b200141106a2101200241706a22020d000b4101210120070d010b201821010b2017201e470d000b200121180c050b200a2802042201200b490d04200a200141016a3602040c040b200a28020c2201450d03200a28020422172001411c6c6a2106034020172201411c6a2117024020012802182202450d0020012802102101200241027421020340024020012802002207200b490d002001200741016a3602000b200141046a21012002417c6a22020d000b0b20172006460d040c000b0b200a28020c2201450d02200141146c2102200a28020441106a2101034002402001417c6a2802000d0020012802002207200b490d002001200741016a3602000b200141146a21012002416c6a22020d000c030b0b2016450d002006102f0b024020042802d403450d0020042802d003102f0b024020042802e003450d0020042802dc03102f0b4101211d0b200a41306a220a200c470d000b41012109201d4101710d0220184101710d0120042802a0022105200428029802210a0b2004419c026a280200211420042802940221162004280290022115410021090c020b200441d0036a41106a20044190026a41106a280200360200200441d0036a41086a20044190026a41086a29030037030020042004290390023703d003200441c0026a200441d0036a10d0044110102d2202450d1a200241063a00004101102d2201450d1a200141003a00004101102d2217450d1a201720012d00003a00002001102f4110102d2207450d1a200741063a000041f000102d2201450d1a200141063a00602001412c3b01502001200b3602442001410b3a0040200141d8003a0030200120042802783602242001412d3a0020200141003602142001410f3a0010200141003602042001410f3a0000024020072d00004109470d0002402007280204220b28020441ffffffff0371450d00200b280200102f2007280204210b0b200b102f0b2007102f024020022d00004109470d0002402002280204220728020441ffffffff0371450d002007280200102f200228020421070b2007102f0b2002102f200441f4036a4287808080f000370200200441f0036a2001360200200441ec036a4100360200200441d0036a410c6a4281808080800c370200200441d8036a4101360200200441003602fc03200442043702e403200420173602d403200441013602d003200441c0026a200441d0036a10d504200441d0036a200441c0026a418c0110e8061a200441a8026a200441d0036a10d204200441a8026a410c6a2802002114200441b8026a280200210520042802a802211520042802ac02211620042802b002210a410021090c010b2004419c026a2802002114200428029802220a20042802a002220510cd04411a211641be8bca0021152014450d00200a102f0b200441f4006a2802002117200428026c21010240200441f0006a2802002202450d00200221070340200128026c21012007417f6a22070d000b03402002417f6a22020d000b0b02402017450d0041002107034002400240200720012f01064f0d004100210b200121020c010b4100210b034002400240024020014190bdc600460d00200128020022020d0141002107410021020c020b41edb3ca00412841f8b4ca001039000b200b41016a210b20012f010421070b2001102f20022101200720022f01064f0d000b0b200741016a2106200220074103746a41146a280200210802400240200b0d0020022101200621070c010b200220064102746a41ec006a280200210141002107200b417f6a2202450d000340200128026c21012002417f6a22020d000b0b20084103460d012017417f6a22170d000b0b02400240024020014190bdc600460d00200128020021022001102f2002450d00034020024190bdc600460d02200228020021012002102f2001210220010d000b0b0240024020090d00200441c0026a41106a2005360200200441c0026a410c6a20143602002004200a3602c802200420163602c402200420153602c002200441d0036a200441c0026a200328026810d60420042802d0034101470d010240200441d0036a41086a280200450d0020042802d403102f0b200041d88bca0036020420004101360200200041086a41233602000c2d0b2000201536020420004101360200200041086a20163602000c2c0b200441e4036a2802002102200441d0036a41106a2802002114200441d0036a410c6a2802002115200441d8036a280200210b20042802d403210720032802602112200441003602b002200442013703a8024104102d2201450d1a200441043602ac02200420042802b002221741046a3602b002200420013602a802200120176a20073600000240024020042802ac02220720042802b00222016b4104490d0020042802a80221070c010b200141046a22172001490d1a200741017422012017200120174b1b22014100480d1a0240024020070d002001102d21070c010b20042802a80220072001103121070b2007450d1b200420013602ac02200420073602a80220042802b00221010b2004200141046a3602b002200720016a200b3600002015200241306c6a2116024020020d00201521010c020b200441d0036a4101722102200441d0036a41276a210b200441d0036a41206a2117200441d0036a41186a210a200441d0036a41086a2106201521010240034020012d00002107200b200141286a2900003700002017200141216a290000370300200a200141196a290000370300200441d0036a41106a2208200141116a2900003703002006200141096a2900003703002004200141016a2900003703d003024020074110470d00200141306a21010c040b200441c0026a41276a2205200b290000370000200441c0026a41206a22092017290300370300200441c0026a41186a200a290300221a370300200441c0026a41106a20082903002223370300200441c0026a41086a2006290300221f370300200420042903d00322243703c00220022024370000200241086a201f370000200241106a2023370000200241186a201a370000200241206a2009290300370000200241276a2005290000370000200420073a00d00320044180016a200441d0036a200441a8026a10d70420042d0080012207411f470d01200141306a22012016470d000b201621010c020b200428028401210b2004280288012102200141306a2201201620016b41306d10cd0402402014450d002015102f0b024020042802ac02450d0020042802a802102f0b024020074105470d002002450d00200b102f0b200041998eca0036020420004101360200200041086a41253602000c2b0b41edb3ca00412841f8b4ca001039000b2001201620016b41306d10cd0402402014450d002015102f0b20042802a802210120042902ac02211a2000411c6a41003a0000200041146a201a370200200041106a20013602002000410c6a201c360200200041086a201b360200200020123602042000411d6a20042f0090023b0000200041003602002000411f6a20044192026a2d00003a00000c290b2009102f0c210b2009102f0c200b20122d000d22014104460d05200141fb01710d052009102f201521020c130b20122d000d22014104460d00200141fb01710d002009102f201521020c120b2009102f0c1d0b20122d000d22014104460d00200141fb01710d002009102f201521020c100b2009102f0c1b0b2009102f0c1a0b2009102f0c190b200c102f0c1a0b02400240200241f294ca00460d0041f294ca002002410b10ea060d010b4126210941e293c600211620122d000c41e000470d1920122802080d192015210220122d000d4104460d0c0c190b02402002419695ca00460d0041012116419695ca002002410b10ea060d010b4126210941e293c600211620122d000c41e000470d1820122802080d182015210220122d000d4104460d0b0c180b2009411546210b0b0240200941796a2201410c4b0d000240024020010e0d00020202020202020202020201000b0240200241c095ca00460d0041c095ca002002410710ea060d020b4126210941e293c600211620122d000c41e000470d1820122802080d182015210220122d000d4104460d0b0c180b200241c795ca00460d0241c795ca002002411310ea06450d020b200b450d020b0240200241da95ca00460d004100210141da95ca002002411510ea060d030b4126210941e293c600211620122d000c41e000470d1520122802080d152015210220122d000d4104460d080c150b4126210941e293c600211620122d000c41e000470d1420122802080d142015210220122d000d4104460d070c140b41002101200941726a220b41084b0d0002400240024002400240024002400240024002400240200b0e09010b03000a0b0b0b08010b200241ef95ca00460d0141ef95ca002002411110ea06450d01200241ae96ca00460d0641ae96ca002002411110ea06450d060240200241bf96ca00460d0041bf96ca002002411110ea060d0b0b4104102d2209450d122009410036000020122d000c41e000460d080c1b0b02402002418096ca00460d00418096ca002002410e10ea060d0a0b4108102d2209450d112009420037000020122d000c41e000460d020c190b4102102d2209450d10200941003b000020122d000c41e000470d1720122802084102470d170240201228020022162009460d0041002101034020014102460d01200920016a2102201620016a210b200141016a2101200b2d000020022d0000470d190c000b0b20122d000d4104470d172009102f201521020c0e0b2002418e96ca00460d01418e96ca002002411010ea06450d0102402002419e96ca00460d0041012101419e96ca002002411010ea060d080b4103102d2209450d0f200941003a0002200941003b000020122d000c41e000460d020c150b20122802084108470d160240201228020022162009460d0041002101034020014108460d01200920016a2102201620016a210b200141016a2101200b2d000020022d0000470d180c000b0b20122d000d4104470d162009102f201521020c0c0b4126210941e293c600211620122d000c41e000470d1820122802080d1820122d000d22014104460d1820152102200141fb0171450d0b0c180b20122802084103470d120240201228020022162009460d0041002101034020014103460d01200920016a2102201620016a210b200141016a2101200b2d000020022d0000470d140c000b0b20122d000d4104470d122009102f201521020c0a0b4102102d2209450d0b200941003b000020122d000c41e000470d1020122802084102470d100240201228020022162009460d0041002101034020014102460d01200920016a2102201620016a210b200141016a2101200b2d000020022d0000470d120c000b0b20122d000d4104470d102009102f201521020c090b0240200241d096ca00460d0041d096ca002002411610ea060d030b4102102d2209450d0a200941003b000020122d000c41e000460d030c0e0b20122802084104470d120240201228020022162009460d0041002101034020014104460d01200920016a2102201620016a210b200141016a2101200b2d000020022d0000470d140c000b0b20122d000d4104470d122009102f201521020c070b200241e696ca00460d0241e696ca002002411210ea06450d020b02402016450d00200241f896ca00460d0341f896ca002002410b10ea06450d030b02402001450d002002418397ca00460d04418397ca002002411010ea06450d040b4126210141e293c600210b20094117470d1302402002419397ca00460d00419397ca002002411710ea060d140b4102102d2216450d07201641003b000020122d000c41e000460d040c0a0b20122802084102470d0a0240201228020022162009460d0041002101034020014102460d01200920016a2102201620016a210b200141016a2101200b2d000020022d0000470d0c0c000b0b20122d000d4104470d0a2009102f201521020c040b4126210941e293c600211620122d000c41e000470d1020122802080d102015210220122d000d4104460d030c100b4102102d2209450d04200941003b000020122d000c41e000470d0620122802084102470d060240201228020022162009460d0041002101034020014102460d01200920016a2102201620016a210b200141016a2101200b2d000020022d0000470d080c000b0b20122d000d4104470d062009102f201521020c020b4126210941e293c600211620122d000c41e000470d0e20122802080d0e2015210220122d000d4104460d010c0e0b20122802084102470d0502402012280200220c2016460d0041002102034020024102460d01201620026a210b200c20026a2109200241016a210220092d0000200b2d0000470d070c000b0b20122d000d22024104460d05200241fb01710d052016102f201521020c000b0b1038000b1036000b200041c989ca00360204411f21010c0b0b2009102f0c070b2016102f200041e293c6003602040c090b2009102f0c050b2009102f0c040b2009102f0c030b2009102f0c020b2009102f0c010b2009102f0b41262101200041e293c6003602040c020b20092101200020163602040c010b2000200b3602040b20004101360200200041086a200136020002402007450d002006200741306c6a21092006210a0340200a221741306a210a0240024020172d00002201410e4b0d00024002400240024002400240024002400240024002400240024020010e0f0001020304050607080e090e0a0b0c000b201741086a280200450d0d201741046a280200102f0c0d0b0240201741086a280200450d00201741046a280200102f0b201741146a280200450d0c201741106a280200102f0c0c0b02402017410c6a2802002202450d00201741046a28020021012002410474210203400240200141046a280200450d002001280200102f0b200141106a2101200241706a22020d000b0b201741086a280200450d0b2017280204102f0c0b0b02402017410c6a2802002202450d00201741046a2802002101200241286c210203400240200141046a280200450d002001280200102f0b0240200141106a280200450d002001410c6a280200102f0b200141286a2101200241586a22020d000b0b201741086a280200450d0a2017280204102f0c0a0b201741086a280200450d09201741046a280200102f0c090b201741086a280200450d08201741046a280200102f0c080b201741086a280200450d07201741046a280200102f0c070b02402017410c6a2802002201450d00201741046a280200220b20014104746a210503400240200b2802082202450d00200b2802002101200241047421020340024020012d00004109470d000240200141046a2200280200220728020441ffffffff0371450d002007280200102f200028020021070b2007102f0b200141106a2101200241706a22020d000b0b200b41106a21010240200b41046a280200450d00200b280200102f0b2001210b20012005470d000b0b201741086a280200450d062017280204102f0c060b02402017410c6a2802002202450d00201741046a2802002101200241146c210203400240200141046a280200450d002001280200102f0b200141146a21012002416c6a22020d000b0b201741086a280200450d052017280204102f0c050b02402017410c6a2802002201450d00201741046a280200220b2001411c6c6a210503400240200b2802042201450d000240200b410c6a2802002202450d00200241047421020340024020012d00004109470d000240200141046a2200280200220728020441ffffffff0371450d002007280200102f200028020021070b2007102f0b200141106a2101200241706a22020d000b0b200b41086a280200450d00200b280204102f0b200b411c6a21010240200b41146a280200450d00200b280210102f0b2001210b20012005470d000b0b201741086a280200450d042017280204102f0c040b02402017410c6a2802002201450d00201741046a280200220b200141186c6a210503400240200b41046a280200450d00200b280200102f0b0240200b41146a2802002202450d00200b28020c2101200241047421020340024020012d00004109470d000240200141046a2200280200220728020441ffffffff0371450d002007280200102f200028020021070b2007102f0b200141106a2101200241706a22020d000b0b200b41186a21010240200b41106a280200450d00200b28020c102f0b2001210b20012005470d000b0b201741086a280200450d032017280204102f0c030b02402017410c6a2802002201450d00201741046a280200220b2001411c6c6a210503400240200b2802042201450d000240200b410c6a2802002202450d00200241047421020340024020012d00004109470d000240200141046a2200280200220728020441ffffffff0371450d002007280200102f200028020021070b2007102f0b200141106a2101200241706a22020d000b0b200b41086a280200450d00200b280204102f0b200b411c6a21010240200b41146a280200450d00200b280210102f0b2001210b20012005470d000b0b201741086a280200450d022017280204102f0c020b0240201741046a2802002201450d00201741086a280200450d002001102f0b0240201741146a2802002201450d0002402017411c6a2802002202450d002002410c6c21020340024020012802002207450d00200141046a280200450d002007102f0b2001410c6a2101200241746a22020d000b0b201741186a280200450d002017280214102f0b201741246a280200220b450d0102402017412c6a2802002201450d00200b20014104746a21050340200b220041106a210b024020002802042201450d0002402000410c6a2802002202450d002002410c6c21020340024020012802002207450d00200141046a280200450d002007102f0b2001410c6a2101200241746a22020d000b0b200041086a280200450d002000280204102f0b200b2005470d000b0b201741286a280200450d012017280224102f0c010b0240201741086a280200450d00201741046a280200102f0b0240201741146a2802002201450d00201741186a280200450d002001102f0b201741246a280200450d00201741206a280200102f0b200a2009470d000b0b2008450d032006102f0c030b200441003a0068200441e4036a4101360200200442013702d403200441b4afca003602d0032004412836029402200420044190026a3602e0032004200441e8006a3602900220044180016a200441d0036a103a2004280280012105200428028401210b2006200710cd04410521172008450d002006102f0b41a089ca00210141162102200b450d00201741ff01714105470d002005102f0b2000200136020420004101360200200041086a20023602000b200441e0046a24000bee0601037f024002400240024002402000280200220241c000490d00200241808001490d012002418080808004490d0202400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d05200241017422042003200420034b1b22044100480d050240024020020d002004102d21030c010b200128020020022004103121030b2003450d0420012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41033a00002000280200210302400240200141046a2802002202200428020022006b4104490d00200128020021020c010b200041046a22042000490d05200241017422002004200020044b1b22004100480d050240024020020d002000102d21020c010b200128020020022000103121020b2002450d0420012002360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200220006a20033600000f0b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d04200041017422042003200420034b1b22044100480d040240024020000d002004102d21030c010b200128020020002004103121030b2003450d0320012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a20024102743a00000f0b02400240200141046a2802002203200141086a28020022006b4102490d00200128020021030c010b200041026a22042000490d03200341017422002004200020044b1b22004100480d030240024020030d002000102d21030c010b200128020020032000103121030b2003450d0220012003360200200141046a2000360200200141086a28020021000b200141086a200041026a360200200320006a20024102744101723b00000f0b02400240200141046a2802002203200141086a28020022006b4104490d00200128020021030c010b200041046a22042000490d02200341017422002004200020044b1b22004100480d020240024020030d002000102d21030c010b200128020020032000103121030b2003450d0120012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20024102744102723600000f0b1036000b1038000b960f03087f017e017f230041106b2202240020024100360208200242013703000240024002402001280200220341044b0d000240024002400240024020030e050001020304000b4101102d2203450d05200242818080801037020420022003360200200341013a0000200128020421032001410c6a28020022042002106902402004450d002003200441286c6a210503400240024020022802042206200228020822076b4120490d00200228020021040c010b200741206a22042007490d09200641017422082004200820044b1b22084100480d090240024020060d002008102d21040c010b200228020020062008103121040b2004450d082002200836020420022004360200200821060b200420076a220841186a200341186a290000370000200841106a200341106a290000370000200841086a200341086a2900003700002002200741206a220936020820082003290000370000200341206a290300210a0240200620096b41074b0d00200941086a22082009490d092006410174220b2008200b20084b1b22084100480d090240024020060d002008102d21040c010b200420062008103121040b2004450d0820022008360204200220043602000b2002200741286a360208200420096a200a3700002005200341286a2203470d000b0b200141106a28020021060240024020022802042204200228020822036b4104490d00200228020021040c010b200341046a22072003490d07200441017422082007200820074b1b22074100480d070240024020040d002007102d21040c010b200228020020042007103121040b2004450d0620022007360204200220043602000b2002200341046a360208200420036a20063600000c040b4101102d2203450d04200242818080801037020420022003360200200341023a0000200128020421060240024020022802042204200228020822036b4104490d00200228020021040c010b200341046a22072003490d06200441017422082007200820074b1b22074100480d060240024020040d002007102d21040c010b200228020020042007103121040b2004450d0520022007360204200220043602000b2002200341046a360208200420036a200636000020012802082103200141106a28020022042002106902402004450d002003200441286c6a210503400240024020022802042207200228020822086b4120490d00200841206a2104200228020021060c010b200841206a22042008490d08200741017422062004200620044b1b22094100480d080240024020070d002009102d21060c010b200228020020072009103121060b2006450d072002200936020420022006360200200921070b200620086a220841186a200341186a290000370000200841106a200341106a290000370000200841086a200341086a2900003700002002200436020820082003290000370000200341206a290300210a0240200720046b41074b0d00200441086a22082004490d08200741017422092008200920084b1b22084100480d080240024020070d002008102d21060c010b200620072008103121060b2006450d0720022008360204200220063602000b2002200441086a360208200620046a200a3700002005200341286a2203470d000b0b200141146a28020021060240024020022802042204200228020822036b4104490d00200228020021040c010b200341046a22072003490d06200441017422082007200820074b1b22074100480d060240024020040d002007102d21040c010b200228020020042007103121040b2004450d0520022007360204200220043602000b2002200341046a360208200420036a20063600000c030b4101102d2203450d03200242818080801037020420022003360200200341033a0000200141086a290300210a0240024020022802042206200228020822036b4108490d00200341086a2104200228020021060c010b200341086a22042003490d05200641017422072004200720044b1b22074100480d050240024020060d002007102d21060c010b200228020020062007103121060b2006450d0420022007360204200220063602000b20022004360208200620036a200a3700000c020b4101102d2203450d02200242818080801037020420022003360200200341043a0000200128020421060240024020022802042204200228020822036b4104490d00200228020021040c010b200341046a22072003490d04200441017422082007200820074b1b22074100480d040240024020040d002007102d21040c010b200228020020042007103121040b2004450d0320022007360204200220043602000b2002200341046a360208200420036a20063600000c010b4101102d2203450d01200242818080801037020420022003360200200341053a0000200128020421070240024020022802042206200228020822036b4104490d00200341046a2104200228020021060c010b200341046a22042003490d03200641017422082004200820044b1b22084100480d030240024020060d002008102d21060c010b200228020020062008103121060b2006450d0220022008360204200220063602000b20022004360208200620036a20073600000b20002002290300370200200041086a200241086a280200360200200241106a24000f0b1036000b1038000bd01a01197f230041d0116b2202240020002802102203200328020041016a360200200028020c2104200028020821052000280200210620002802042103200241206a41186a22072000412c6a290000370300200241206a41106a2208200041246a290000370300200241206a41086a22092000411c6a29000037030020022000290014370320200241a0026a200141e00010e8061a024002400240024002400240024020032f01062201410b490d000240024020034190bdc600460d00200241b0036a410041e00210e7061a20024198066a410041a00810e7061a41880b102d220a0d010c080b4195b4ca00412d41f8b4ca001039000b200a41003b0106200a4100360200200a41086a200241b0036a41e00210e8062101200a41e8026a20024198066a41a00810e8062107200220032f00c8013b01ac032002200341ca016a2d00003a00ae03200220032900db01370398032002200341e0016a29000037009d03200341cb016a280000210b200341cf016a280000210c200341d3016a280000210d200341d7016a280000210e20024198066a200341a8076a41e00010e8061a2001200341e8016a20032f010641796a220041057410e8062101200720034188086a200041e0006c10e8062107200341063b0106200a20003b0106200220022f01ac033b019403200220022d00ae033a0096032002200229039803370380032002200229009d0337008503200241b0036a20024198066a41e00010e8061a0240024020044107490d00200441057420016a41c07e6a2001200441796a22084105746a2201200041ffff037120086b41057410e9061a200141186a200241206a41186a290300370000200141106a200241206a41106a290300370000200141086a200241206a41086a29030037000020012002290320370000200441e0006c20076a220041c07b6a200041e07a6a220f200a41066a22002f010020086b41e0006c10e9061a200f200241a0026a41e00010e8061a0c010b200341066a2100200341086a20044105746a220141206a200120032f010620046b41057410e9061a200141186a200241206a41186a290300370000200141106a200241206a41106a290300370000200141086a200241206a41086a29030037000020012002290320370000200341e8026a200441e0006c6a220f41e0006a200f20032f010620046b41e0006c10e9061a200f200241a0026a41e00010e8061a0b20024188026a41026a220420022d0096033a0000200020002f010041016a3b0100200220022f0194033b01880220022002290380033703800120022002290085033700850120024190016a200241b0036a41e00010e8061a2002411c6a41026a221020042d00003a0000200220022f0188023b011c2002200229038001370308200220022900850137000d200241206a20024190016a41e00010e8061a0240200328020022070d00410021030c030b20032f0104211120024198066a41027221124100210303402002419c026a41026a221320102d00003a0000200220022f011c3b019c0220022002290308370388022002200229000d37008d02200241a0026a200241206a41e00010e8061a20062003470d02201141ffff0371210802400240024020072f01062203410b490d002012410041b20b10e7061a41b80b102d2201450d0a20014100360200200141046a20024198066a41b40b10e8061a200220072f00c8013b01ac032002200741ca016a2d00003a00ae03200220072900db01370398032002200741e0016a29000037009d03200741cb016a2800002114200741cf016a2800002115200741d3016a2800002116200741d7016a280000211720024198066a200741a8076a41e00010e8061a200141086a200741e8016a20072f0106220041796a220341057410e8062118200141e8026a20074188086a200341e0006c10e8062119200141880b6a200741a40b6a2000417a6a220941027410e806211a200741063b0106200120033b010602402009450d0041002103201a210003402000280200220420033b010420042001360200200041046a21002009200341016a2203470d000b0b200241b0036a20024198066a41e00010e8061a200220022d00ae0322033a009603200220022f01ac0322003b0194032002200229009d033700850320022002290398033703800320024194066a41026a220920033a0000200220003b01940620022002290380033703800120022002290085033700850120024198066a200241b0036a41e00010e8061a201141ffff037122004107490d0120182008417a6a22044105746a2018200841796a22034105746a220020012f010620036b41057410e9061a200041186a200229008d023700002000200e36000f2000200d36000b2000200c3600072000200b360003200041026a20132d00003a0000200020022f019c023b00002000200229038802370013200841e0006c20196a220041c07b6a200041e07a6a220020012f010620036b41e0006c10e9061a2000200241a0026a41e00010e8061a200120012f010641016a22003b01062008410274220b201a6a416c6a201a20044102746a2211200041ffff0371220820046b41027410e9061a2011200a36020020082004490d022001200b6a41f00a6a2100034020002802002204200341016a22033b010420042001360200200041046a210020032008490d000c030b0b200741086a2200200841016a22044105746a200020084105746a2200200320086b220141057410e9061a2000200e36000f2000200d36000b2000200c3600072000200b360003200041026a2002419c026a41026a2d00003a0000200020022f019c023b00002000200229038802370013200041186a200229008d023700002007200841e0006c6a220041c8036a200041e8026a2200200141e0006c10e9061a2000200241a0026a41e00010e8061a2007200341016a22033b01062008410274200741880b6a22006a41086a200020044102746a2200200341ffff037120046b41027410e9061a2000200a360200201141ffff037120072f010622034f0d06200a20043b0104200a2007360200200420034f0d062003417f6a210120072004417f6a22034102746a41900b6a2100034020002802002204200341026a3b010420042007360200200041046a21002001200341016a2203470d000c070b0b200741086a2203200841016a22044105746a200320084105746a220320072f0106221120086b221a41057410e9061a2003200e36000f2003200d36000b2003200c3600072003200b360003200341026a20132d00003a0000200320022f019c023b00002003200229038802370013200341186a200229008d02370000200741e8026a200841e0006c6a220341e0006a2003201a41e0006c10e9061a2003200241a0026a41e00010e8061a2007201141016a22033b01062008410274221a200741880b6a22116a41086a201120044102746a2211200341ffff037120046b41027410e9061a2011200a360200200020072f010622044f0d002007201a6a418c0b6a2103034020032802002200200841016a22083b010420002007360200200341046a210320042008470d000b0b200641016a210320024184026a41026a220020092d00003a0000200220022f0194063b01840220022002290380013703f00120022002290085013700f50120024190016a20024198066a41e00010e8061a201020002d00003a0000200220022f0184023b011c200220022903f001370308200220022900f50137000d200241206a20024190016a41e00010e8061a0240200728020022000d002014210b2017210e2016210d2015210c2001210a0c040b20072f010421112014210b2017210e2016210d2015210c200021072001210a200321060c000b0b200320044105746a220041286a200041086a2206200120046b41057410e9061a200041206a2007290300370000200041186a2008290300370000200041106a2009290300370000200620022903203700002003200441e0006c6a220041c8036a200041e8026a220f20032f010620046b41e0006c10e9061a200f200241a0026a41e00010e8061a200320032f010641016a3b01060c020b41c2b4ca00413541f8b4ca001039000b20024198066a410272410041b20b10e7061a41b80b102d2200450d0320004100360200200041046a20024198066a41b40b10e8061a2000200528020022043602880b2005200036020020052005280204220141016a360204200441003b010420042000360200200241a0026a41026a2002411c6a41026a2d00003a0000200220022f011c3b01a002200220022903083703b0032002200229000d3700b50320024198066a200241206a41e00010e8061a20012003470d0120002f01062204410a4b0d02200020044105746a2203410a6a200241a0026a41026a2d00003a0000200341086a20022f01a0023b0000200341176a200e360000200341136a200d3600002003410f6a200c3600002003410b6a200b3600002003411b6a20022903b003370000200341206a20022900b5033700002000200441e0006c6a41e8026a20024198066a41e00010e8061a2000200441016a22034102746a41880b6a200a360200200020033b0106200a20033b0104200a20003602000b200241d0116a2400200f0f0b4196b3ca00413041f8b4ca001039000b41c6b3ca00412741f8b4ca001039000b1036000b802003077f037e147f23004180076b22042400200441e0006a41186a200241186a290000370300200441e0006a41106a200241106a290000370300200441e0006a41086a200241086a2900003703002004200229000037036002400240024002400240200128020022054190bdc600460d00200128020421060c010b41002106200441e8026a410041e00210e7061a200441c0016a410041840110e7061a41ec03102d2205450d01200541003b010620054100360200200541086a200441e8026a41e00210e8061a200541e8026a200441c0016a41840110e8061a20014100360204200120053602000b02400240024002400240024003400240024020052f010622070d00410021080c010b20074105742102200541086a2109417f21080340024020020d00200721080c020b200841016a2108200441e0006a2009412010ea06220a450d03200241606a2102200941206a2109200a417f4a0d000b0b02402006450d002006417f6a2106200520084102746a41ec036a28020021050c010b0b200441086a41186a2206200441e0006a41186a2202290300370300200441086a41106a200441e0006a41106a2209290300220b370300200441086a41086a200441e0006a41086a220a290300220c37030020042004290360220d3703082001200128020841016a3602082009200b370300200a200c370300200220062903003703002004200d370360200441d8026a41086a2207200341086a280200360200200420032902003703d802024020052f01062203410b490d0020054190bdc600460d02200441e8026a410041e00210e7061a200441c0016a410041840110e7061a41ec03102d220e450d07200e41003b0106200e4100360200200e41086a200441e8026a41e00210e8062109200e41e8026a200441c0016a41840110e806210a200441e8026a41086a2206200541b8036a280200360200200420052900db013703a8012004200541e0016a2900003700ad01200420052902b0033703e802200420052f00c8013b01bc012004200541ca016a2d00003a00be01200541cb016a280000210f200541cf016a2800002110200541d3016a2800002111200541d7016a28000021122009200541e8016a20052f010641796a220241057410e8062109200a200541bc036a2002410c6c10e806210a200541063b0106200e20023b0106200420042f01bc013b01a401200420042d00be013a00a601200420042903a8013703c001200420042900ad013700c501200441286a41086a2006280200360200200420042903e8023703280240024020084107490d00200841057420096a41c07e6a2009200841796a22064105746a2209200241ffff037120066b41057410e9061a200941186a200441e0006a41186a290300370000200941106a200441e0006a41106a290300370000200941086a200441e0006a41086a290300370000200920042903603700002008410c6c200a6a220241b87f6a200241ac7f6a2209200e41066a22022f010020066b410c6c10e9061a200941086a200441d8026a41086a280200360200200920042903d8023702000c010b200541086a20084105746a220941206a2009200541066a22022f010020086b41057410e9061a200941186a200441e0006a41186a290300370000200941106a200441e0006a41106a290300370000200941086a200441e0006a41086a29030037000020092004290360370000200541e8026a2008410c6c6a2209410c6a200920022f010020086b410c6c10e9061a200941086a200441d8026a41086a280200360200200920042903d8023702000b200220022f010041016a3b010020044198016a41026a220220042d00a6013a0000200441c8026a41086a2213200441286a41086a280200360200200420042f01a4013b019801200420042903c001370350200420042900c501370055200420042903283703c8022004413c6a41026a221420022d00003a0000200420042f0198013b013c2004200429005537002d20042004290350370328200441c0006a41086a22152013280200360200200420042903c8023703400240200528020022060d00410021160c050b20052f01042103200441e8026a410272211741002116034020044194016a41026a221820142d00003a0000200420042f013c3b019401200420042903283703602004200429002d37006520044198016a41086a22192015280200360200200420042903403703980141000d04200341ffff0371210502400240024020062f01062202410b490d002017410041960410e7061a419c04102d220a450d0b200a4100360200200a41046a200441e8026a41980410e8061a200420062f00c8013b01bc012004200641ca016a2d00003a00be012004200641db016a2900003703a8012004200641e0016a2900003700ad01200641cb016a280000211a200641cf016a280000211b200641d3016a280000211c200641d7016a280000211d200441e8026a41086a221e200641b8036a2802003602002004200641b0036a2902003703e802200a41086a200641e8016a20062f0106220941796a220241057410e806211f200a41e8026a200641bc036a2002410c6c10e8062120200a41ec036a20064188046a2009417a6a220741027410e8062121200641063b0106200a20023b010602402007450d00410021022021210903402009280200220820023b01042008200a360200200941046a21092007200241016a2202470d000b0b200441d8026a41086a2202201e280200360200200420042d00be0122093a00a601200420042f01bc0122083b01a401200420042903a8013703c001200420042900ad013700c501200420042903e8023703d802200441c4026a41026a220720093a0000200420083b01c402200420042903c0013703e802200420042900c5013700ed0220132002280200360200200420042903d8023703c802200341ffff037122094107490d01201f2005417a6a22084105746a201f200541796a22024105746a2209200a2f010620026b41057410e9061a200941186a20042900653700002009201236000f2009201136000b200920103600072009200f360003200941026a20182d00003a0000200920042f0194013b0000200920042903603700132005410c6c20206a220941b87f6a200941ac7f6a2209200a2f0106220320026b410c6c10e9061a200941086a20192802003602002009200429039801370200200a200341016a22093b01062005410274220f20216a416c6a202120084102746a2203200941ffff0371220520086b41027410e9061a2003200e36020020052008490d02200a200f6a41d4036a2109034020092802002208200241016a22023b01042008200a360200200941046a210920022005490d000c030b0b200641086a2209200541016a22084105746a200920054105746a2209200220056b41057410e9061a200941186a20042900653700002009201236000f2009201136000b200920103600072009200f360003200941026a20044194016a41026a2d00003a0000200920042f0194013b00002009200429036037001320062005410c6c6a220241f4026a200241e8026a220920062f0106220a20056b410c6c10e9061a200241f0026a20044198016a41086a28020036020020092004290398013702002006200a41016a22023b01062005410274200641ec036a22096a41086a200920084102746a2209200241ffff0371220a20086b41027410e9061a2009200e360200200341ffff0371200a4f0d0820062008417f6a22024102746a41f0036a2109034020092802002208200241016a22023b010420082006360200200941046a21092002200a490d000c090b0b200641086a2202200541016a22034105746a200220054105746a220220062f010620056b41057410e9061a200241186a20042900653700002002201236000f2002201136000b200220103600072002200f360003200241026a20182d00003a0000200220042f0194013b000020022004290360370013200641e8026a2005410c6c6a2202410c6a200220062f0106220820056b410c6c10e9061a200241086a201928020036020020022004290398013702002006200841016a22023b01062005410274220f200641ec036a22086a41086a200820034102746a2221200241ffff0371220820036b41027410e9061a2021200e360200200920084f0d002006200f6a41f0036a2102034020022802002209200541016a22053b010420092006360200200241046a210220082005470d000b0b201641016a211620044190016a41026a220220072d00003a000020044180016a41086a22092013280200360200200420042f01c40222083b019001200420042903e802370350200420042900ed02370055200420042903c80237038001201420022d00003a0000200420083b013c2004200429005537002d200420042903503703282015200928020036020020042004290380013703400240200628020022020d00201a210f201d2112201c2111201b2110200a210e0c060b20062f01042103201a210f201d2112201c2111201b211020022106200a210e0c000b0b200520084105746a220641286a200641086a2201200320086b41057410e9061a200641206a2002290300370000200641186a2009290300370000200641106a200a2903003700002001200429036037000020052008410c6c6a220241f4026a200241e8026a220920052f010620086b410c6c10e9061a200241f0026a2007280200360200200920042903d802370200200520052f010641016a3b01060c040b200441e8026a41086a220220052008410c6c6a220941f0026a22082802003602002004200941e8026a22092902003703e802200920032902003702002008200341086a280200360200200441c0016a41086a20022802002202360200200420042903e802220b3703c0012000410c6a20023602002000200b370204200041013602000c040b4195b4ca00412d41f8b4ca001039000b41c2b4ca00413541f8b4ca001039000b200441e8026a410272410041960410e7061a419c04102d2202450d0220024100360200200241046a200441e8026a41980410e8061a2002200128020022093602ec032001200236020020012001280204220841016a360204200941003b010420092002360200200441e0006a41026a2004413c6a41026a2d00003a0000200420042f013c3b0160200420042903283703e8022004200429002d3700ed02200441c0016a41086a200441c0006a41086a280200360200200420042903403703c00120082016470d0320022f01062208410a4b0d04200220084105746a2209410a6a200441e0006a41026a2d00003a0000200941086a20042f01603b0000200941176a2012360000200941136a20113600002009410f6a20103600002009410b6a200f3600002009411b6a20042903e802370000200941206a20042900ed0237000020022008410c6c6a220941f0026a200441c0016a41086a280200360200200941e8026a20042903c0013702002002200841016a22094102746a41ec036a200e360200200220093b0106200e20093b0104200e20023602000b200041003602000b20044180076a24000f0b1036000b4196b3ca00413041f8b4ca001039000b41c6b3ca00412741f8b4ca001039000bbd2504077f037e1d7f027e230041f00a6b22042400200441c0016a41186a200241186a290000370300200441c0016a41106a200241106a290000370300200441c0016a41086a200241086a290000370300200420022900003703c00102400240024002400240200128020022054190bdc600460d00200128020421060c010b41002106200441f8046a410041e00210e7061a20044190026a410041e00210e7061a41c805102d2205450d01200541003b010620054100360200200541086a200441f8046a41e00210e8061a200541e8026a20044190026a41e00210e8061a20014100360204200120053602000b02400240024002400240024003400240024020052f010622070d00410021080c010b20074105742102200541086a2109417f21080340024020020d00200721080c020b200841016a2108200441c0016a2009412010ea06220a450d03200241606a2102200941206a2109200a417f4a0d000b0b02402006450d002006417f6a2106200520084102746a41c8056a28020021050c010b0b200441186a2206200441c0016a41186a2202290300370300200441106a200441c0016a41106a2209290300220b370300200441086a200441c0016a41086a220a290300220c370300200420042903c001220d3703002001200128020841016a36020820044188016a41106a2207200b37030020044188016a41086a220e200c37030020044188016a41186a220f20062903003703002004200d370388012002200341186a2903003703002009200341106a290300370300200a200341086a290300370300200420032903003703c001024020052f01062203410b490d0020054190bdc600460d02200441f8046a410041e00210e7061a20044190026a410041e00210e7061a41c805102d2210450d07201041003b010620104100360200201041086a200441f8046a41e00210e8062109201041e8026a20044190026a41e00210e806210a200441f8046a41086a2206200541b0046a290300370300200441f8046a41106a2207200541b8046a290300370300200441f8046a41186a2203200541c0046a290300370300200420052900db013703f8012004200541e0016a2900003700fd01200420052903a8043703f804200420052f00c8013b018c022004200541ca016a2d00003a008e02200541cb016a2800002111200541cf016a2800002112200541d3016a2800002113200541d7016a28000021142009200541e8016a20052f010641796a2202410574220e10e8062109200a200541c8046a200e10e806210a200541063b0106201020023b0106200420042f018c023b01f401200420042d008e023a00f601200420042903f8013703e001200420042900fd013700e50120044190026a41186a200329030037030020044190026a41106a200729030037030020044190026a41086a2006290300370300200420042903f804370390020240024020084107490d002009200841057441c07e6a22066a2009200841796a220841057422076a2209200241ffff037120086b41057410e9061a200941186a20044188016a41186a290300370000200941106a20044188016a41106a290300370000200941086a20044188016a41086a2903003700002009200429038801370000200a20066a200a20076a2209201041066a22022f010020086b41057410e9061a200941186a200441c0016a41186a290300370300200941106a200441c0016a41106a290300370300200941086a200441c0016a41086a290300370300200920042903c0013703000c010b200541066a2102200541086a22092008410574220a41206a22066a2009200a6a220920052f010620086b41057410e9061a200941186a20044188016a41186a290300370000200941106a20044188016a41106a290300370000200941086a20044188016a41086a2903003700002009200429038801370000200541e8026a220920066a2009200a6a220920052f010620086b41057410e9061a200941186a200441c0016a41186a290300370300200941106a200441c0016a41106a290300370300200941086a200441c0016a41086a290300370300200920042903c0013703000b200220022f010041016a3b0100200441a8016a41026a220220042d00f6013a0000200441d8006a41086a220920044190026a41086a2215290300370300200441d8006a41106a220820044190026a41106a2216290300370300200441d8006a41186a220a20044190026a41186a2217290300370300200420042f01f4013b01a801200420042903e001370378200420042900e50137007d2004200429039002370358200441346a41026a221820022d00003a0000200420042f01a8013b01342004200429007d37002520042004290378370320200441386a41186a2219200a290300370300200441386a41106a221a2008290300370300200441386a41086a221b2009290300370300200420042903583703380240200528020022060d004100211c0c050b20052f0104211d200441f8046a410272211e4100211c0340200441bc016a41026a221f20182d00003a0000200420042f01343b01bc01200420042903203703782004200429002537007d200441c0016a41186a22202019290300370300200441c0016a41106a2221201a290300370300200441c0016a41086a2222201b290300370300200420042903383703c00141000d04201d41ffff0371210502400240024020062f01062202410b490d00201e410041f20510e7061a41f805102d220a450d0b200a4100360200200a41046a200441f8046a41f40510e8061a200420062f00c8013b018c022004200641ca016a2d00003a008e02200420062900db013703f8012004200641e0016a2900003700fd01200641cb016a2800002123200641cf016a2800002124200641d3016a2800002125200641d7016a2800002126200441f8046a41186a2203200641c0046a290300370300200441f8046a41106a220e200641b8046a290300370300200441f8046a41086a220f200641b0046a290300370300200420062903a8043703f804200a41086a200641e8016a20062f0106220241796a2209410574220810e8062127200a41e8026a200641c8046a200810e8062128200a41c8056a200641e4056a2002417a6a220741027410e8062129200641063b0106200a20093b010602402007450d00410021022029210903402009280200220820023b01042008200a360200200941046a21092007200241016a2202470d000b0b201720032903003703002016200e2903003703002015200f290300370300200420042903f80437039002200420042f018c023b01f401200420042d008e023a00f601200420042903f8013703e001200420042900fd013700e501200441f4046a41026a220720042d00f6013a0000200420042f01f4013b01f404200420042903e001370358200420042900e50137005d20032017290300370300200e2016290300370300200f201529030037030020042004290390023703f804201d41ffff037122094107490d0120272005417a6a2208410574221d6a2027200541796a2202410574222a6a2209200a2f010620026b41057410e9061a200941186a200429007d3700002009201436000f2009201336000b2009201236000720092011360003200941026a201f2d00003a0000200920042f01bc013b0000200920042903783700132028201d6a2028202a6a2209200a2f0106221d20026b41057410e9061a200941186a2020290300370300200941106a2021290300370300200941086a2022290300370300200920042903c001370300200a201d41016a22093b01062005410274221120296a416c6a202920084102746a221d200941ffff0371220520086b41027410e9061a201d201036020020052008490d02200a20116a41b0056a2109034020092802002208200241016a22023b01042008200a360200200941046a210920022005490d000c030b0b200641086a2209200541016a2208410574220a6a2009200541057422076a2209200220056b410574220310e9061a2009201436000f2009201336000b2009201236000720092011360003200941026a200441bc016a41026a2d00003a0000200920042f01bc013b000020092004290378370013200941186a200429007d370000200641e8026a2209200a6a200920076a2209200310e9061a200941186a200441c0016a41186a290300370300200941106a200441c0016a41106a290300370300200941086a200441c0016a41086a290300370300200920042903c0013703002006200241016a22023b01062005410274200641c8056a22096a41086a200920084102746a2209200241ffff037120086b41027410e9061a20092010360200201d41ffff037120062f010622024f0d08201020083b010420102006360200200820024f0d082002417f6a210a20062008417f6a22024102746a41d0056a2109034020092802002208200241026a3b010420082006360200200941046a2109200a200241016a2202470d000c090b0b200641086a2202200541016a2208410574221d6a2002200541057422296a220220062f0106222720056b410574222810e9061a2002201436000f2002201336000b2002201236000720022011360003200241026a201f2d00003a0000200220042f01bc013b000020022004290378370013200241186a200429007d370000200641e8026a2202201d6a200220296a2202202810e9061a200241186a2020290300370300200241106a2021290300370300200241086a2022290300370300200220042903c0013703002006202741016a22023b010620054102742229200641c8056a221d6a41086a201d20084102746a221d200241ffff037120086b41027410e9061a201d2010360200200920062f010622084f0d00200620296a41cc056a2102034020022802002209200541016a22053b010420092006360200200241046a210220082005470d000b0b201c41016a211c200441b8016a41026a220220072d00003a000020044188016a41086a2209200f29030037030020044188016a41106a2208200e29030037030020044188016a41186a22052003290300370300200420042f01f4043b01b801200420042903583703a8012004200429005d3700ad01200420042903f80437038801201820022d00003a0000200420042f01b8013b0134200420042900ad01370025200420042903a80137032020192005290300370300201a2008290300370300201b200929030037030020042004290388013703380240200628020022020d0020232111202621142025211320242112200a21100c060b20062f0104211d2023211120262114202521132024211220022106200a21100c000b0b200541086a22062008410574220141206a221d6a200620016a2206200320086b41057410e9061a200641186a200f290300370000200641106a2007290300370000200641086a200e2903003700002006200429038801370000200541e8026a2206201d6a200620016a220620052f010620086b41057410e9061a200641186a2002290300370300200641106a2009290300370300200641086a200a290300370300200620042903c001370300200520052f010641016a3b01060c040b200520084105746a22024180036a2209290300210b2003290300210c2003290308210d2003290310212b2009200341186a290300370300200241f8026a2209290300212c2009202b370300200241f0026a2209290300212b2009200d370300200241e8026a2202290300210d2002200c370300200041186a200b3703002000202c3703102000202b3703082000200d3703000c040b4195b4ca00412d41f8b4ca001039000b41c2b4ca00413541f8b4ca001039000b200441f8046a410272410041f20510e7061a41f805102d2209450d0220094100360200200941046a200441f8046a41f40510e8061a2009200128020022023602c8052001200936020020012001280204220841016a360204200241003b010420022009360200200441c0016a41026a200441346a41026a2d00003a0000200420042f01343b01c00120042004290320370390022004200429002537009502200441f8046a41186a200441386a41186a290300370300200441f8046a41106a200441386a41106a290300370300200441f8046a41086a200441386a41086a290300370300200420042903383703f8042008201c470d0320092f01062208410a4b0d04200920084105746a2202410a6a200441c0016a41026a2d00003a0000200241086a20042f01c0013b0000200241176a2014360000200241136a20133600002002410f6a20123600002002410b6a20113600002002411b6a200429039002370000200241206a200429009502370000200241e8026a20042903f804370300200241f0026a200441f8046a41086a290300370300200241f8026a20044188056a29030037030020024180036a20044190056a2903003703002009200841016a22024102746a41c8056a2010360200200920023b0106201020023b0104201020093602000b200041003602100b200441f00a6a24000f0b1036000b4196b3ca00413041f8b4ca001039000b41c6b3ca00412741f8b4ca001039000b8e0c01087f230041c0046b22032400200341206a41186a200141186a290000370300200341206a41106a200141106a290000370300200341206a41086a200141086a2900003703002003200129000037032002400240024002400240200028020022044190bdc600460d00200028020421050c010b4100210520034180016a410041e00210e7061a200341f8006a22014100360200200341f0006a22064200370300200341d0006a41186a4200370300200341d0006a41106a4200370300200341d0006a41086a420037030020034200370350419403102d2204450d01200441003b010620044100360200200441086a20034180016a41e00210e8061a20044190036a200128020036020020044188036a200629030037020020044180036a200341e8006a290300370200200441f8026a200341e0006a290300370200200441f0026a200341d0006a41086a290300370200200420032903503702e80220004100360204200020043602000b02400240024003400240024020042f010622070d00410021080c010b20074105742101200441086a2106417f21080340024020010d00200721080c020b200841016a2108200341206a2006412010ea062209450d03200141606a2101200641206a21062009417f4a0d000b0b02402005450d002005417f6a2105200420084102746a4194036a28020021040c010b0b200341186a2201200341206a41186a2205290300370300200341106a2206200341206a41106a2207290300370300200341086a2209200341206a41086a220a290300370300200320032903203703002000200028020841016a3602082003200836024c200320003602482003200436024420034100360240200341d0006a41186a2001290300370300200341d0006a41106a2006290300370300200341d0006a41086a20092903003703002003200329030037035020034180016a200341c0006a200341d0006a2002107720032d0080014101470d02200a20034189016a290000370300200720034191016a290000370300200520034199016a2900003703002003200329008101370320200341ac016a2802002106200341b8016a2802002109200341b4016a2802002108200341b0016a2802002104200341a8016a28020022012802002205450d0120012f01042107200341a4016a280200210020034180016a410172210103402003200741ffff037136024c20032006360248200320053602442003200041016a360240200341d0006a41186a200341206a41186a2206290300370300200341d0006a41106a200341206a41106a2205290300370300200341d0006a41086a200341206a41086a22072903003703002003200329032037035020034180016a200341c0006a200341d0006a200420082009107820032d0080014101470d032007200141086a2900003703002005200141106a2900003703002006200141186a2900003703002003200129000037032020032802ac01210620032802b801210920032802b401210820032802b001210420032802a80122072802002205450d0220072f0104210720032802a40121000c000b0b200420084102746a41e8026a20023602000c010b20034180016a410272410041be0310e7061a41c403102d2201450d0120014100360200200141046a20034180016a41c00310e8061a200120062802002205360294032006200136020020062006280204220741016a360204200541003b01042005200136020020034180016a41186a200341206a41186a29030037030020034180016a41106a200341206a41106a29030037030020034180016a41086a200341206a41086a290300370300200320032903203703800120072009470d0220012f01062206410a4b0d03200120064105746a220941206a20034180016a41186a290300370000200941186a20034180016a41106a290300370000200941106a20034180016a41086a290300370000200941086a200329038001370000200120064102746a41e8026a20043602002001200641016a22064102746a4194036a2008360200200120063b0106200820063b0104200820013602000b200341c0046a24000f0b1036000b4196b3ca00413041f8b4ca001039000b41c6b3ca00412741f8b4ca001039000bed1307027f017e057f027e017f017e0a7f230041b0036b2202240020002802102203200328020041016a36020020002902142104200028020c2105200028020821062000280200210320002802042100200241f0016a41086a2207200141086a280200360200200220012902003703f001024002400240024002400240024020002f01062201410b490d000240024020004190bdc600460d00200241d0026a410272410041da0010e7061a200241386a410041840110e7061a41e401102d22080d010c080b4195b4ca00412d41f8b4ca001039000b20084100360200200841046a200241d0026a41dc0010e8061a200841e0006a200241386a41840110e8062107200241386a41086a2209200041b0016a280200360200200220002902a8013703382000413c6a330000210a2000413e6a310000210b20002d003f210c2000350038210d200841086a200041c0006a20002f010641796a220141037410e806210e2007200041b4016a2001410c6c10e8062107200041063b0106200820013b0106200241d0026a41086a2009280200360200200220022903383703d002200d200a200b4210868442208684210a0240024020054107490d002005410374200e6a41506a200e200541796a22094103746a220e200141ffff037120096b41037410e9061a200e20043700002005410c6c20076a220541b87f6a200541ac7f6a2205200841066a22012f010020096b410c6c10e9061a200541086a200241f0016a41086a280200360200200520022903f0013702000c010b200041086a20054103746a220741086a2007200041066a22012f010020056b41037410e9061a20072004370000200041e0006a2005410c6c6a2207410c6a200720012f010020056b410c6c10e9061a200741086a200241f0016a41086a280200360200200720022903f0013702000b200120012f010041016a3b0100200241286a41086a220f200241d0026a41086a22102802002205360200200241086a221120053602002002200c3a0017200220022903d00222043703282002200a3e02102002200a4230883c00162002200a4220883d011420022004370300200229031021040240200028020022090d00410021120c030b20002f01042113200241d0026a4102722114410021000340200220093602242002200341016a2212360220200f20112802003602002002200229030037032820032000470d02201341ffff0371210702400240024020092f01062203410b490d002014410041da0010e7061a200241f0016a200241d0026a41dc0010e8061a200241386a410041b40110e7061a419402102d2201450d0a20014100360200200141046a200241f0016a41dc0010e8061a200141e0006a200241386a41b40110e8062100200941386a290000210a200241386a41086a220e200941b0016a2802003602002002200941a8016a290200370338200141086a200941c0006a20092f0106220541796a220341037410e80621152000200941b4016a2003410c6c10e8062116200141e4016a20094180026a2005417a6a220c41027410e8062117200941063b0106200120033b01060240200c450d00410021032017210003402000280200220520033b010420052001360200200041046a2100200c200341016a2203470d000b0b2010200e280200220336020020022002290338220b3703d002200e20033602002002200b370338201341ffff037122004107490d0120152007417a6a22004103746a2015200741796a22034103746a220520012f010620036b41037410e9061a200520043700002007410c6c20166a220541b87f6a200541ac7f6a220520012f0106220c20036b410c6c10e9061a200541086a200f280200360200200520022903283702002001200c41016a22053b01062007410274221320176a416c6a201720004102746a220c200541ffff0371220720006b41027410e9061a200c200836020020072000490d02200120136a41cc016a2100034020002802002205200341016a22033b010420052001360200200041046a210020032007490d000c030b0b200941086a2205200741016a22004103746a200520074103746a2205200320076b220141037410e9061a2005200437000020092007410c6c6a220541ec006a200541e0006a220c2001410c6c10e9061a200541e8006a200241286a41086a280200360200200c20022903283702002009200341016a22033b01062007410274200941e4016a22056a41086a200520004102746a2205200341ffff0371220120006b41027410e9061a20052008360200201341ffff037120014f0d0620092000417f6a22034102746a41e8016a2100034020002802002205200341016a22033b010420052009360200200041046a210020032001490d000c070b0b200941086a2203200741016a220c4103746a200320074103746a220320092f0106220520076b221341037410e9061a20032004370000200941e0006a2007410c6c6a2203410c6a20032013410c6c10e9061a200341086a200f280200360200200320022903283702002009200541016a22033b010620074102742217200941e4016a22056a41086a2005200c4102746a2213200341ffff03712205200c6b41027410e9061a20132008360200200020054f0d00200920176a41e8016a2103034020032802002200200741016a22073b010420002009360200200341046a210320052007470d000b0b200241106a41086a200e280200220336020020112003360200200220022903382204370310200220043703000240200928020022030d0020012108200a21040c040b20092f0104211320032109200a21042001210820122100201221030c000b0b200020054103746a220341106a200341086a2203200120056b41037410e9061a2003200437000020002005410c6c6a220341ec006a200341e0006a220120002f010620056b410c6c10e9061a200341e8006a2007280200360200200120022903f001370200200020002f010641016a3b01060c020b41c2b4ca00413541f8b4ca001039000b200241d0026a410272410041da0010e7061a200241f0016a200241d0026a41dc0010e8061a200241386a410041b40110e7061a419402102d2203450d0320034100360200200341046a200241f0016a41dc0010e8061a200341e0006a200241386a41b40110e80621052003200628020022003602e4012006200336020020062006280204220141016a360204200041003b010420002003360200200241386a41086a200241086a2802003602002002200229030037033820012012470d0120032f01062200410a4b0d0220052000410c6c6a22052002290338370200200320004103746a41086a2004370000200541086a200241386a41086a2802003602002003200041016a22004102746a41e4016a2008360200200320003b0106200820003b0104200820033602000b200241b0036a24000f0b4196b3ca00413041f8b4ca001039000b41c6b3ca00412741f8b4ca001039000b1036000be66d05027f067e147f0c7e157f230041d00d6b22032400024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e06000102030407000b200341f4066a4101360200200342013702e406200341b4d8c9003602e0062003410436028c04200341fcdbc90036028804200320034188046a3602f006200341e0066a41e8d8c9001043000b200141e8006a280200210420034188046a200141086a41e00010e8061a200341d00a6a20014184016a280200360200200341c80a6a200141fc006a290200370300200341b80a6a41086a200141f4006a2902003703002003200141ec006a2902003703b80a0240024020022d000120022d0000410047720d0041aa97ca00ad42808080808001842205100122022900002106200229000821072002102f41ba97ca00ad4280808080f0018422081001220229000021092002290008210a2002102f2003200a3703f001200320093703e801200320073703e001200320063703d801200341e0066a200341d8016a108502410020032802c00720032d00d8074102461b2004490d0120004183243b0100200041086a4116360200200041046a4184cec100360200200041026a41003a00000c100b200041023a00000c0f0b200341ec066a2004360200200341e0066a41086a41053a00002003410d3a00e00641c8e1ca004100200341e0066a108c01200341e0066a20034188046a41e00010e8061a200341cc076a200341b80a6a41086a290300370200200341d4076a200341c80a6a290300370200200341dc076a200341d00a6a280200360200200320043602c007200320032903b80a3702c4072005100122022900002106200229000821072002102f20081001220229000021092002290008210a2002102f2003200a3703f001200320093703e801200320073703e001200320063703d801200341003602c009200342013703b809200341e0066a200341b8096a10f60120032802bc092102200341d8016aad428080808080048420033502c00942208620032802b8092204ad84100402402002450d002004102f0b200041043a00000c0e0b200141086a280200210b200141046a280200210c02400240024020022d00000d0020022d00014101470d002001410c6a280200210d200141106a2903002106200241196a2d00002104200241186a2d0000210e200241166a2f0100210f200241156a2d00002110200241146a2d00002111200241126a2f01002112200241116a2d00002113200241106a2d000021142002410e6a2f010021152002410d6a2d000021162002410c6a2d000021172002410a6a2f01002118200241096a2d00002119200241086a2d0000211a200241066a2f0100211b200241056a2d0000211c200241046a2d0000211d200241026a2f0100211e20032002411a6a2901003703d00a200320043a00cf0a2003200e3a00ce0a2003200f3b01cc0a200320103a00cb0a200320113a00ca0a200320123b01c80a200320133a00c70a200320143a00c60a200320153b01c40a200320163a00c30a200320173a00c20a200320183b01c00a200320193a00bf0a2003201a3a00be0a2003201b3b01bc0a2003201c3a00bb0a2003201d3a00ba0a2003201e3b01b80a200341e0066a200341b80a6a200610840220032802e0064101470d02200020032902e406370200200041086a200341ec066a2802003602000c010b200041023a00000b4100210e410121040240200b450d00200c102f0b410121000c100b20034190076a290300210a20034188076a290300210541202104200341e0066a41206a2903002108200341f8066a290300211f4110210e200341e0066a41106a290300210620032903e806212041aa97ca00ad4280808080800184100122022900002107200229000821092002102f41ba97ca00ad4280808080f00184100122022900002121200229000821222002102f200320223703f001200320213703e801200320093703e001200320073703d801200341e0066a200341d8016a10850220032903e006210720032903e806212120032903f006212220032903f8062123200329038007212420032903880721252003290390072126200329039807212720032903a007212820032903a807212920032903b007212a20032903b807210920032802c007211220032802c407210f20032802c807211020032802cc07211320032802d007211120032802d407211420032d00d80721022003200341e0066a41fc006a2800003600bb09200320032800d9073602b8090240024020024102470d0042012107200342013703d804200342013703d004200342af013703c80420034287013703c004200342013703b804200342013703b004200342013703a804200342013703a00420034201370398042003420137039004200342013703880441002102200341003602e8044180800121114180800421104104210f42e40021090c010b20034188046a41fc006a20032800bb09360000200320123602e8042003202a3703d804200320293703d004200320283703c804200320273703c004200320263703b804200320253703b004200320243703a804200320233703a004200320223703980420032021370390042003200737038804200320032802b809360081052013210e201421040b200320074200200dad2221420010ed06200320023a008005200320043602fc04200320113602f8042003200e3602f404200320103602f0042003200f3602ec04200320093703e00442002006427f200329030020032903084200521b7d2207200720065622021b210602400240024002402002450d00412c210241af8ec20021040c010b200341e0066a200c200d20034188046a10940220032802e0064101470d01200341e8066a280200210220032802e40621040b0240200b450d00200c102f0b200341b80a6a20202006201f20082005200a108802200041086a2002360200200041046a2004360200200041003a00000c010b200341d8016a41186a2204200341e0066a410472220241186a280200360200200341d8016a41106a220e200241106a290200370300200341d8016a41086a2211200241086a290200370300200320022902003703d801200341e80c6a41026a22122021422086200cad841003220241026a2d00003a00002002280003210f2002280007211020022f0000211320034198036a410d6a2214200241186a29000037000020034198036a41086a2215200241136a290000370300200320133b01e80c2003200229000b370398032002102f200341e0066a41186a2004280200360200200341e0066a41106a200e290300370300200341e0066a41086a2011290300370300200320032903d8013703e006200341980d6a41026a220e20122d00003a0000200341b8096a41086a22112015290300370300200341b8096a410d6a22122014290000370000200320032f01e80c3b01980d20032003290398033703b80941aa97ca00ad4280808080800184100122022d000f211320022d000e211420022f000c211520022d000b211620022d000a211720022f0008211820022d0007211920022d0006211a20022f0004211b20022d0003211c20022d0002211d20022f0000211e2002102f41e4f4c100ad4280808080b0018410012202290008210720022d0007212b20022d0006212c20022f0004212d20022d0003212e20022d0002212f20022f000021302002102f4120102d2204450d04200420032f01980d3b0000200420103600072004200f360003200420032903b80937000b200441026a200e2d00003a0000200441136a2011290300370000200441186a20122900003700002004ad428080808080048410032202290018210920022d0017210e20022d0016211120022f0014211220022d0013213120022d0012213220022f0010213320022d000f213420022d000e213520022f000c213620022d000b213720022d000a213820022f0008213920022d0007213a20022d0006213b20022f0004213c20022d0003213d20022d0002213e20022f0000213f2002102f2004102f41c000102d2202450d04200220093700382002200e3a0037200220113a0036200220123b0034200220313a0033200220323a0032200220333b0030200220343a002f200220353a002e200220363b002c200220373a002b200220383a002a200220393b00282002203a3a00272002203b3a00262002203c3b00242002203d3a00232002203e3a00222002203f3b0020200220073700182002202b3a00172002202c3a00162002202d3b00142002202e3a00132002202f3a0012200220303b0010200220133a000f200220143a000e200220153b000c200220163a000b200220173a000a200220183b0008200220193a00072002201a3a00062002201b3b00042002201c3a00032002201d3a00022002201e3b0000200341003602c009200342013703b809200341e0066a200341b8096a109502200341e0066a410472200341b8096a109502200341e8066a200341b8096a10950220032d00f80621110240024020032802bc0920032802c0092204460d0020032802b809210e0c010b200441016a220e2004490d0420044101742212200e2012200e4b1b22124100480d040240024020040d002012102d210e0c010b20032802b809200420121031210e0b200e450d05200320123602bc092003200e3602b8090b2003200441016a3602c009200e20046a20113a000020032802ec062113200341f4066a280200220e200341b8096a10690240024020032802bc09221220032802c00922116b200e490d0020032802b80921040c010b2011200e6a22042011490d04201241017422142004201420044b1b22144100480d040240024020120d002014102d21040c010b20032802b80920122014103121040b2004450d05200320143602bc09200320043602b809201421120b200420116a2013200e10e8061a2002ad42808080808008842011200e6aad4220862004ad84100402402012450d002004102f0b2002102f0240200341f0066a280200450d002013102f0b200341b8096a41026a220e200341e80c6a41026a2d00003a0000200341e0066a41086a221120034198036a41086a290300370300200341e0066a410d6a221220034198036a410d6a290000370000200320032f01e80c3b01b80920032003290398033703e00641aa97ca00ad4280808080800184100122022d000f211320022d000e211420022f000c211520022d000b211620022d000a211720022f0008211820022d0007211920022d0006211a20022f0004211b20022d0003211c20022d0002211d20022f0000211e2002102f41c0f4c100ad4280808080c0018410012202290008210720022d0007212b20022d0006212c20022f0004212d20022d0003212e20022d0002212f20022f000021302002102f4120102d2204450d04200420032f01b8093b0000200420103600072004200f360003200420032903e00637000b200441026a200e2d00003a0000200441136a2011290300370000200441186a20122900003700002004ad428080808080048410032202290018210920022d0017210e20022d0016211120022f0014211220022d0013213120022d0012213220022f0010213320022d000f213420022d000e213520022f000c213620022d000b213720022d000a213820022f0008213920022d0007213a20022d0006213b20022f0004213c20022d0003213d20022d0002213e20022f0000213f2002102f2004102f41c000102d2202450d04200220093700382002200e3a0037200220113a0036200220123b0034200220313a0033200220323a0032200220333b0030200220343a002f200220353a002e200220363b002c200220373a002b200220383a002a200220393b00282002203a3a00272002203b3a00262002203c3b00242002203d3a00232002203e3a00222002203f3b0020200220073700182002202b3a00172002202c3a00162002202d3b00142002202e3a00132002202f3a0012200220303b0010200220133a000f200220143a000e200220153b000c200220163a000b200220173a000a200220183b0008200220193a00072002201a3a00062002201b3b00042002201c3a00032002201d3a00022002201e3b0000200341c0003602e406200320023602e006200c200d200341e0066a109d022002102f0240200b450d00200c102f0b200341980d6a41026a200341e80c6a41026a2d000022023a0000200341b8096a41086a220420034198036a41086a290300370300200341b8096a410d6a220e20034198036a410d6a290000370000200320032f01e80c220b3b01980d20032003290398033703b809200341e0066a41086a41043a0000200341e9066a200b3b0000200341eb066a20023a0000200341f0066a2010360200200341ec066a200f3602002003410d3a00e006200341f4066a20032903b809370200200341fc066a200429030037020020034181076a200e29000037000041c8e1ca004100200341e0066a108c01200341b80a6a20202006201f20082005200a108802200041043a00000b4100210e41012104410121000c0f0b200141c0006a2903002106200141386a2903002107200141c8006a2903002109200341a8046a200141246a28020036020020034188046a41186a2001411c6a29020037030020034188046a41106a200141146a29020037030020034188046a41086a2001410c6a2902003703002003200141046a290200370388042001412c6a2802002104200141286a280200210e0240024020022d00000d0020022d00014101470d002002411a6a290100210a200241196a2d0000210b200241186a2d0000210c200241166a2f0100210f200241156a2d00002110200241146a2d00002111200241126a2f01002112200241116a2d00002113200241106a2d000021142002410e6a2f010021152002410d6a2d000021162002410c6a2d000021172002410a6a2f01002118200241096a2d00002119200241086a2d0000211a200241066a2f0100211b200241056a2d0000211c200241046a2d0000211d200241026a2f01002102200141306a280200211e200341e0066a41206a20034188046a41206a280200360200200341e0066a41186a220d20034188046a41186a290300370300200341e0066a41106a222b20034188046a41106a290300370300200341e0066a41086a222c20034188046a41086a29030037030020032003290388043703e006200341b80a6a200341e0066a10bb0120032d00b80a4101470d01200041013a00002004450d0d0c0c0b200041023a000020040d0b0c0c0b200341b80a6a41086a2d0000212d200341c10a6a2f0000212e200341c30a6a2d0000212f200341c40a6a2d00002130200341c50a6a2f00002131200341c70a6a2d00002132200341b80a6a41106a2d00002133200341c90a6a2f00002134200341cb0a6a2d00002135200341cc0a6a2d00002136200341cd0a6a2f00002137200341cf0a6a2d00002138200341b80a6a41186a2d0000213920032f00b90a213a20032d00bb0a213b20032d00bc0a213c20032f00bd0a213d20032d00bf0a213e2003200341d10a6a2900003703f001200320393a00ef01200320383a00ee01200320373b01ec01200320363a00eb01200320353a00ea01200320343b01e801200320333a00e701200320323a00e601200320313b01e401200320303a00e3012003202f3a00e2012003202e3b01e0012003202d3a00df012003203e3a00de012003203d3b01dc012003203c3a00db012003203b3a00da012003203a3b01d8012003200a3703d00a2003200b3a00cf0a2003200c3a00ce0a2003200f3b01cc0a200320103a00cb0a200320113a00ca0a200320123b01c80a200320133a00c70a200320143a00c60a200320153b01c40a200320163a00c30a200320173a00c20a200320183b01c00a200320193a00bf0a2003201a3a00be0a2003201b3b01bc0a2003201c3a00bb0a2003201d3a00ba0a200320023b01b80a200d20032903f001370300202b20032903e801370300202c20032903e001370300200320032903d8013703e0062003201e3602a0032003200436029c032003200e36029803200341b8096a200341b80a6a200341e0066a20072006200920034198036a10830202400240024020032802b8094101460d00200341c0096a280200450d0120032802bc09102f0c010b20032d00bc0922024104470d010b200041043a00000c0c0b200341cc096a2802002104200341b8096a41106a280200210f200341c4096a280200210e200341b8096a41086a280200210b200020032f00bd0920032d00bf0941107472220c3b0001200020023a0000200041036a200c4110763a0000200041086a200e360000200041046a200b3600002004450d0b200f102f0c0b0b200141386a2903002107200141306a2903002109200141c0006a2903002106200341f8006a41186a200141196a290000370300200341f8006a41106a200141116a290000370300200341f8006a41086a200141096a29000037030020032001290001370378200141286a2802002104200141246a280200210e20022d00000d0320022d00014101470d03200241196a2d0000210b200241186a2d0000210c200241166a2f0100210f200241156a2d00002110200241146a2d00002111200241126a2f01002112200241116a2d00002113200241106a2d000021142002410e6a2f010021152002410d6a2d000021162002410c6a2d000021172002410a6a2f01002118200241096a2d00002119200241086a2d0000211a200241066a2f0100211b200241056a2d0000211c200241046a2d0000211d200241026a2f0100211e2001412c6a280200210d20032002411a6a2901003703b0012003200b3a00af012003200c3a00ae012003200f3b01ac01200320103a00ab01200320113a00aa01200320123b01a801200320133a00a701200320143a00a601200320153b01a401200320163a00a301200320173a00a201200320183b01a001200320193a009f012003201a3a009e012003201b3b019c012003201c3a009b012003201d3a009a012003201e3b019801200341e0066a20034198016a2006108402024020032802e0064101470d0020032d00e706411074210220032f00e506210b20032802ec06212d20032802e806212b20032d00e406211b02402004450d00200e102f0b200b200272210d4100212e410121020c070b20034190076a290300210a20034188076a29030021054120210b200341b8016a41186a200341e0066a41206a2903003703004110210c200341b8016a41106a200341e0066a41186a290300370300200341c0016a200341e0066a41106a290300370300200320032903e8063703b80141aa97ca00ad4280808080800184100122022900002106200229000821082002102f41ba97ca00ad4280808080f0018410012202290000211f200229000821202002102f200320203703f0012003201f3703e801200320083703e001200320063703d801200341e0066a200341d8016a10850220032903e006210820032903e806211f20032903f006212020032903f8062121200329038007212220032903880721232003290390072124200329039807212520032903a007212620032903a807212720032903b007212820032903b807210620032802c007211220032802c407210f20032802c807211020032802cc07211320032802d007211120032802d407211420032d00d80721022003200341e0066a41fc006a2800003600bb09200320032800d9073602b8090240024020024102470d00200342013703a802200342013703a002200342af013703980220034287013703900220034201370388022003420137038002200342013703f801200342013703f001200342013703e801200342013703e001200342013703d80141002102200341003602b8024180800121114180800421104104210f42e40021060c010b200341d8016a41fc006a20032800bb09360000200320123602b802200320283703a802200320273703a0022003202637039802200320253703900220032024370388022003202337038002200320223703f801200320213703f001200320203703e8012003201f3703e001200320083703d801200320032802b8093600d1022013210c2014210b0b200341f0026a4200370300200341e0026a420037030020034180036a4200370300200320023a00d0022003200b3602cc02200320113602c8022003200c3602c402200320103602c0022003200f3602bc02200320063703b0022003428080e983b1de163703e8022003428080e983b1de163703d80220034280a094a58d1d3703f802200342a0808080808010370388032003200341d8016a360290032003200341d8016a36029403200341b80a6a41186a221020034198016a41186a290300370300200341b80a6a41106a221120034198016a41106a290300370300200341b80a6a41086a221220034198016a41086a29030037030020032003290398013703b80a200341e0066a41186a22134200370300200341e0066a41106a220b4200370300200341e0066a41086a22024200370300200342003703e00641d5a2ca00ad42808080809001841001220c29000021062002200c41086a290000370300200320063703e006200c102f41ecb0c000ad428080808030841001220f2900002106200341b8096a41086a220c200f41086a290000370300200320063703b809200f102f200b20032903b809220637030020034188046a41086a2214200229030037030020034188046a41106a2215200637030020034188046a41186a2216200c290300370300200320032903e00637038804200341186a20034188046a10e301200329032021062003280218211720134200370300200b420037030020024200370300200342003703e006418de6c300ad4280808080e000841001220f29000021082002200f41086a290000370300200320083703e006200f102f419ce6c300ad4280808080e000841001220f2900002108200c200f41086a290000370300200320083703b809200f102f200b20032903b809220837030020142002290300370300201520083703002016200c290300370300200320032903e00637038804200341106a20034188046a4120109501200341d0036a420037030020034198036a412c6a418886c70036020020034198036a41286a41c8e1ca00360200200341b4036a4190bdc600360200200341f0036a2012290300370300200341f8036a201129030037030020034180046a201029030037030020034198036a41206a42003703002003428080808080013703c803200342003703a003200320032903b80a3703e8034100212f200341003602b0032003280210210c2003280214210f200320034194036a3602e003200320034190036a3602dc032003200341d8016a3602d8032003200f4100200c1b3602e40320032006420020171b370398032003200d360290042003200436028c042003200e36028804200341e0066a20034198036a20092007200341b8016a200341f8006a20034188046a109e02410121300240024020032802e0064101470d0020032f00e50620032d00e70641107472210d200b28020022314108762133200341f4066a280200212e200341ec066a280200212d2002280200212b20032d00e406211b4101212f410121300c010b20034190076a2802002231410876213320032f00850720034187076a2d000041107472210d200341e0066a412c6a280200212d200341e0066a41286a280200212b20034184076a2d0000211b0240203141ff0171450d000c010b200341e0066a41086a200341b8036a29030037030020034188046a41086a200341ec066a280200360200200320032903b0033703e006200320032902e40637038804200341c80d6a20034188046a1087024100212f41002131410021300b20034198016a20032903b80120032903c00120032903c801200341b8016a41186a2903002005200a10880220032802cc03222c20032802d403220241d8026c6a210b20032802d0032132202c21042002450d04200341810b6a210f200341a1076a210c200341b80a6a410172211c200341b8096a41076a211d200341c10a6a2110200341b8096a4102722111200341e0066a41106a211e20034188076a211a200341c4076a211620034181076a2112200341e0066a4101722115202c2102034020022d0000210420034188046a200241016a41d70210e8061a0240024002400240024020044103460d00200320043a00e006201520034188046a41d70210e806210e024002400240024020040e03000102000b20032802e806211420032802ec06210e20032802e4062104201d201e41f80010e8061a2003410d3a00b80a201c200341b8096a41ff0010e8061a2004200e200341b80a6a108c014101210e41002113024020140d00410021140c030b2004102f410021140c020b200341980d6a41186a2204200e41186a2213290000370300200341980d6a41106a2214200e41106a2217290000370300200341980d6a41086a2218200e41086a22192900003703002003200e2900003703980d200341b80a6a201a41b00210e8061a2011200e290000370000201141086a2019290000370000201141106a2017290000370000201141186a201329000037000020034180023b01b809200341e80c6a200341b80a6a200341b8096a108b0120032d00e80c210e201020032903980d370000201041086a2018290300370000201041106a2014290300370000201041186a2004290300370000200341063a00c00a2003410d3a00b80a2003200e4104463a00e10a4100211341c8e1ca004100200341b80a6a108c01410121144100210e0c010b20032900e106210920032900e906210a20032900f106210520032900f9062108200329008107211f200329008907212020032900910721212003290099072122200341e80c6a41186a2204200c41186a2213290000370300200341e80c6a41106a2214200c41106a2217290000370300200341e80c6a41086a2218200c41086a22192900003703002003200c2900003703e80c200341e0066a41f8006a290300210620032903d0072107200341980d6a41186a200e41186a290000370300200341980d6a41106a200e41106a290000370300200341980d6a41086a200e41086a2900003703002003200e2900003703980d200341b8096a41186a201241186a290000370300200341b8096a41106a201241106a290000370300200341b8096a41086a201241086a290000370300200320122900003703b809200341b80a6a41186a2013290000370300200341b80a6a41106a2017290000370300200341b80a6a41086a20192900003703002003200c2900003703b80a200341b80d6a41086a201641086a280200360200200320162902003703b80d200341880d6a200341980d6a200341b8096a200341b80a6a20072006200341b80d6a10890220032d00880d210e200f41186a2004290300370000200f41106a2014290300370000200f41086a2018290300370000200f20032903e80c370000200320223700f90a200320213700f10a200320203700e90a2003201f3700e10a200320083700d90a200320053700d10a2003200a3700c90a200320093700c10a200341033a00c00a2003410d3a00b80a200341b80a6a41f8006a2006370300200320073703a80b2003200e4104463a00a10b41c8e1ca004100200341b80a6a108c0141012113410121144101210e0b20032d00e006220441014b0d0120040e020302030b200241d8026a21040c090b201320032802c80745720d0220032802c407102f0c020b200e450d01201a108e010c010b2014450d00024020032802e806450d0020032802e406102f0b20032d00f0064107470d00200328029807450d00200328029407102f0b200241d8026a2202200b470d000c060b0b1038000b1036000b200141216a2d00002111200341e80c6a41186a200141196a290000370300200341e80c6a41106a200141116a290000370300200341e80c6a41086a200141096a290000370300200320012900013703e80c200341980d6a41186a22042001413a6a290000370300200341980d6a41106a220e200141326a290000370300200341980d6a41086a220b2001412a6a2900003703002003200141226a2900003703980d2002411a6a2901002106200241196a2d0000210c200241186a2d0000210f200241166a2f010021100240024020022d0000450d002003200637029c012003200c3a009b012003200f3a009a01200320103b019801200341d8016a41186a2004290300370300200341d8016a41106a200e290300370300200341d8016a41086a200b290300370300200320032903980d3703d8010c010b200241156a2d00002112200241146a2d00002113200241126a2f01002114200241116a2d00002115200241106a2d000021162002410e6a2f010021172002410d6a2d000021182002410c6a2d000021192002410a6a2f0100211a200241096a2d0000211b200241086a2d0000211c200241066a2f0100211d200241056a2d0000211e200241046a2d0000210d200241026a2f0100212b20022d000121022003200637039801200341d8016a41186a2004290300370300200341d8016a41106a200e290300370300200341d8016a41086a200b290300370300200320032903980d3703d8010240024020114101710d0041022104200241ff01714101470d020c010b200241ff01714102470d014100210420032903f001210620032f01ec01211020032f01e801211420032f01e401211720032f01e001211a20032f01dc01211d20032f01d801212b20032d00ef01210c20032d00ee01210f20032d00eb01211220032d00ea01211320032d00e701211520032d00e601211620032d00e301211820032d00e201211920032d00df01211b20032d00de01211c20032d00db01211e20032d00da01210d0b200320063703b0032003200c3a00af032003200f3a00ae03200320103b01ac03200320123a00ab03200320133a00aa03200320143b01a803200320153a00a703200320163a00a603200320173b01a403200320183a00a303200320193a00a2032003201a3b01a0032003201b3a009f032003201c3a009e032003201d3b019c032003201e3a009b032003200d3a009a032003202b3b01980320034188046a200341e80c6a10e8010240024020032d008804417f6a41ff01714102490d00200341d8016a41086a200341bc046a290200370300200341d8016a41106a200341c4046a290200370300200341d8016a41186a200341cc046a290200370300200341d8016a41206a200341d4046a290200370300200341d8016a41286a200341dc046a2802003602002003200341b4046a2902003703d80120034188046a41106a290300210720034188046a41086a290300210a200341ac046a280200211120034188046a41206a2802002113200341a4046a280200210c20034188046a41186a280200211220034188046a41286a280200210b200341e0066a41186a4200370300200341e0066a41106a220f4200370300200341e0066a41086a22024200370300200342003703e006418de6c300ad4280808080e000841001220e29000021062002200e41086a290000370300200320063703e006200e102f419ce6c300ad4280808080e000841001220e2900002106200341b8096a41086a2210200e41086a290000370300200320063703b809200e102f200f20032903b8092206370300200341b80a6a41086a2002290300370300200341b80a6a41106a2006370300200341b80a6a41186a2010290300370300200320032903e0063703b80a200341f0006a200341b80a6a4120109501024002400240410041002003280274410020032802701b220e20046b22042004200e4b1b2204200b6b220f200f20044b1b2204450d00200341e0066a200341e80c6a108d02200341e0006a20032903e006220920022903002205428080a8ec85afd1b101420010ee0642002011ad2206200329036022087d221f201f2006564200200341e0006a41086a2903002006200854ad7c7d22064200522006501b22021b22084200200620021b220684500d004201211f2009428080d287e2bc2d5441002005501b0d02200341d0006a2004ad42002008200610ed06200341c0006a2003290350200341d0006a41086a290300428080e983b1de16420010ed06024002402009428080aef89dc3527c2206200a200a200656200720052006200954ad7c427f7c22065620072006511b22021b22082003290340221f2008201f542006200720021b2208200341c0006a41086a290300221f542008201f511b22021b22062008201f20021b220884500d00200341e0066a200341e80c6a108d0220032903800722204200200920067d221f201f200956200520087d2009200654ad7d220920055620092005511b22041b22215820034188076a29030022054200200920041b220958200520095122041bad211f2020202156200520095620041b0d032002450d010c030b4201211f20020d020b200320063703b801200320083703c0010b200c450d022012102f0c020b200341c8016a2008370300200320063703c0012003201f3703b8014202211f0b200341b80a6a41186a2013360200200341cc0a6a200c360200200341e40a6a200341d8016a41086a290300370200200341ec0a6a200341d8016a41106a290300370200200341f40a6a200341d8016a41186a290300370200200341fc0a6a200341f8016a290300370200200341840b6a20034180026a280200360200200320073703c00a2003200a3703b80a2003200b3602d80a200320113602d40a200320123602c80a200320032903d8013702dc0a200341b8096a41106a200341b8016a41086a290300370300200341b8096a41186a200341b8016a41106a2903003703002003201f3703b809200320032903b8013703c009200341e0066a200341e80c6a200341b80a6a200e200341b8096a109f02024020032d00e0060d00200341fc066a280200450d00200341f8066a280200102f0b200342003703c00a200342808086bdbacdd21a3703b80a200320034198036a3602d80120034188046a20034198036a200341b80a6a200341d8016a10a002410121042003280288044101460d01200341b0046a290300210720034188046a41206a2903002109024020034188046a41086a220c2903004201520d0020034188046a41106a290300210620034198076a20034188046a41186a29030037030020034190076a2006370300200341e0066a41086a41003a0000200341e9066a200329039803370000200341f1066a20034198036a41086a290300370000200341f9066a20034198036a41106a29030037000020034181076a20034198036a41186a290300370000200341033a00e00641c8e1ca004100200341e0066a108c010b200341e0066a41186a22104200370300200341e0066a41106a22044200370300200341e0066a41086a22024200370300200342003703e00641e7a2ca00ad428080808080018422061001220b290000210a200341b80a6a41086a220e200b41086a2900003703002003200a3703b80a200b102f2002200e290300370300200320032903b80a3703e00641ecb5c600ad4280808080d00184220a1001220f2900002105200341b8096a41086a220b200f41086a290000370300200320053703b809200f102f200420032903b8092205370300200c200229030037030020034188046a41106a2211200537030020034188046a41186a2212200b290300370300200320032903e00637038804200341286a20034188046a4120109c01200341286a41106a2903002105200329033021082003280228210f201042003703002004420037030020024200370300200342003703e0062006100122102900002106200e201041086a290000370300200320063703b80a2010102f2002200e290300370300200320032903b80a3703e006200a1001220e2900002106200b200e41086a290000370300200320063703b809200e102f200420032903b8092206370300200c2002290300370300201120063703002012200b290300370300200320032903e006370388042003427f20054200200f1b220620077c20084200200f1b220720097c22092007542202ad7c22072002200720065420072006511b22021b3703e8062003427f200920021b3703e00620034188046aad4280808080800484200341e0066aad428080808080028410040b200041043a00000c0a0b200328028c042102200041046a20034190046a29030037020020002002360200410121000c0a0b20004183243b0100200041086a4115360200200041046a41efcdc10036020041012104200041026a41013a0000410121000c090b200041023a00002004450d04200e102f0c040b200b2004460d0003402004220241d8026a21040240024020022d0000220e41014b0d0002400240200e0e020001000b0240200241086a280200450d00200241046a280200102f0b200241106a2d00004107470d02200241386a280200450d02200241346a280200102f0c020b200241286a108d010c010b200241e8006a280200450d00200241e4006a280200102f0b200b2004470d000b0b02402032450d00202c102f0b024020032802a4032202450d00200341a8036a280200450d002002102f0b02402030450d0020034198036a411c6a280200210220032802bc03210c0240024020032802b803220e0d00200221040c010b200e210b20022104034020042802880b2104200b417f6a220b0d000b0340200220022f01064102746a41880b6a2802002102200e417f6a220e0d000b0b200341e0066a411c6a20022f0106360200200341f8066a4100360200200341f4066a20023602002003200c36028007200341003602f006200342003703e806200320043602e406200341003602e006200341e0066a108a020b0240202f450d002033410874203141ff01717221020c010b202b450d01200d410874201b41ff017172102f0c010b201b41ff01714104460d002000200d3b00012000201b3a0000200041036a200d4110763a0000200041086a202d360200200041046a202b360200202e450d012002102f0c010b200041043a00000b41002100410121040c030b200e102f0b41012100410021040c010b41012104410121000b4101210e0b024020012d0000417e6a220241024b0d00024002400240024020020e03000102000b200e450d03200141086a280200450d03200141046a280200102f0c030b20040d010c020b2000450d01200141286a280200450d01200141246a280200102f0c010b2001412c6a280200450d00200141286a280200102f0b200341d00d6a24000b8f0201057f230041106b22032400024002400240200141046a2204417f4c0d000240024020040d00410121050c010b2004102d2205450d020b2003410036020820032004360204200320053602002001200310690240024020032802042206200328020822056b2001490d00200328020021040c010b200520016a22042005490d03200641017422072004200720044b1b22074100480d030240024020060d002007102d21040c010b200328020020062007103121040b2004450d022003200736020420032004360200200721060b200420056a2000200110e8061a2002290200200520016aad4220862004ad84100402402006450d002004102f0b200341106a24000f0b103d000b1036000b1038000bde2e05027f027e097f037e027f230041f00d6b2207240002400240024002400240024002400240024002402001280230200128024022082802b001460d002004420020042903082209200841c0006a2903007d220a200a20095622081b37030820080d02200741106a41186a200141e8006a290000370300200741106a41106a200141e0006a290000370300200741106a41086a200141d8006a29000037030020072001290050370310200741900b6a41186a20063502084220862006350200841003220841186a290000370300200741900b6a41106a200841106a290000370300200741900b6a41086a200841086a290000370300200720082900003703900b2008102f4120102d22080d010c090b200041003a0004200041013602002000410c6a4129360200200041086a41f594c700360200200041106a2006290200370200200041186a200641086a2802003602000c070b20082005290000370000200841186a200541186a290000370000200841106a200541106a290000370000200841086a200541086a2900003700002008412041c00010312208450d07200820072903900b370020200841386a200741900b6a41186a290300370000200841306a200741900b6a41106a290300370000200841286a200741900b6a41086a290300370000200841c00041800110312208450d0720082007290310370040200841d8006a200741106a41186a290300370000200841d0006a200741106a41106a290300370000200841c8006a200741106a41086a290300370000200741f0026a41186a220b2008ad4280808080800c841003220c41186a290000370300200741f0026a41106a220d200c41106a290000370300200741f0026a41086a220e200c41086a2900003703002007200c2900003703f002200c102f200741306a41186a220c200b290300370300200741306a41106a220b200d290300370300200741306a41086a220d200e290300370300200720072903f0023703302008102f200741f0006a41d8006a200d290300370300200741d0016a200b290300370300200741d8016a200c2903003703004100210e200741ac016a41003602002007419c016a41ec91c70036020020074190016a42003703002007418c016a220f4190bdc60036020020072001360278200741f0006a41286a200141186a2210360200200720072903303703c001200742083702a40120074100360288012007410036027c200720012802483602b801200720012903403703b0012007200128023041016a3602a001200129030021092007200128024c3602bc0120072009370370200741f4016a41026a2208200641036a2d00003a0000200720062f00013b01f40120062d0000211120062902042109200741a8026a41186a200541186a290000370300200741a8026a41106a200541106a290000370300200741a8026a41086a200541086a290000370300200720052900003703a80220074101360288012010200741306a10a70521062007200728028801417f6a220c36028801024020060d00200c0d032007417f36028801200741f8016a41186a200741306a41186a290300370300200741f8016a41106a200741306a41106a290300370300200741f8016a41086a200741306a41086a290300370300200720072903303703f80102400240200728028c01220e4190bdc600460d0020072802900121120c010b41002112200741900b6a410041e00210e7061a200741f0026a410041a00810e7061a41880b102d220e450d09200e41003b0106200e4100360200200e41086a200741900b6a41e00210e8061a200e41e8026a200741f0026a41a00810e8061a20074100360290012007200e36028c010b0240034002400240200e2f010622130d004100210b0c010b20134105742106200e41e8026a210c200e41086a2108417f210b0340024020060d002013210b0c020b200741f8016a2008412010ea06220d450d03200641606a2106200c41e0006a210c200b41016a210b200841206a2108200d417f4a0d000b0b02402012450d002012417f6a2112200e200b4102746a41880b6a280200210e0c010b0b200741d0026a41186a200741f8016a41186a290300220a370300200741d0026a41106a200741f8016a41106a2903002214370300200741d0026a41086a200741f8016a41086a2903002215370300200720072903f80122163703d002200741ac0b6a2015370200200741900b6a41246a2014370200200741bc0b6a200a3702002007200741f0006a41246a3602a00b2007200b36029c0b2007200f3602980b2007200e3602940b200741003602900b200720163702a40b200741a4036a4200370200200741003a00ac03200742003703f002200741003a00cd0320074190bdc6003602a0032007420037038803200741900b6a200741f0026a109702210c0b200741c0026a290300210a200c4201370318200c41013a003c200c41286a427f370300200c41206a427f370300200c413d6a20072903a802370000200c41c5006a200741a8026a41086a290300370000200c41cd006a200741b8026a290300370000200c41d5006a200a370000200720072802880141016a36028801200741f0026a20044101200741106a200741306a20022003200741f0006a10a305024020072d00f002220e4104460d00200741f0016a41026a20072d00f3023a0000200741ec016a41026a200741f4016a41026a2d00003a0000200720072f00f1023b01f001200720072f01f4013b01ec012009422088a72105200741f0026a41086a280200210120072802f40221122009a721040c070b200741f0026a200520072802b801280200109202024020072802f0024101470d00200741ec016a41026a200741f4016a41026a2d00003a0000200720072f01f4013b01ec012009422088a72105200741f8026a280200210120072802f40221122009a721044100210e0c070b200741900b6a41186a200741f0026a410472220641186a2802002208360200200741f8016a41106a200641086a290200370300200741f8016a41186a200641106a29020037030020074198026a2008360200200741063602fc01200741ff8bca003602f801200720062902003703800220072802b40121062007200741f0006a360288032007290370210a20072802bc01210820074198036a200741106a41086a290300370300200741a0036a200741106a41106a290300370300200741a8036a200741106a41186a290300370300200720033703f802200720023703f0022007200836028c032007200a370380032007200729031037039003200720113a00d002200720093702d402200720072f01f4013b00d1022007200741f4016a41026a2d00003a00d302200741900b6a2006200741f8016a200741f0026a200741d0026a200410bf01200741900b6a410572210620072d00940b2111024020072802900b4101470d00200741f0016a41026a200641026a2d00003a0000200741ec016a41026a200741a30b6a2d00003a0000200720072f00a10b3b01ec01200720062f00003b01f001200741a40b6a2902002202422088a72105200741900b6a41086a28020021122007419c0b6a28020021012002a721042011210e200741900b6a41106a2d000021110c060b200741a4026a41026a200641026a2d00003a0000200741a0026a41026a200741a30b6a2d00003a0000200720072f00a10b3b01a002200720062f00003b01a40220072802880141016a221741004c0d02200741900b6a41086a28020021042007419c0b6a2802002105200741900b6a41106a2d0000211820072017360288012007280290012112024002400240034002400240200f280200220e2f010622130d004100210c0c010b20134105742106200e41c5036a210b200e41086a2108417f210c0340024020060d002013210c0c020b200741306a2008412010ea06220d450d03200641606a2106200b41e0006a210b200c41016a210c200841206a2108200d417f4a0d000b0b2012450d022012417f6a2112200e200c4102746a41880b6a210f0c000b0b200b310000200b41a37f6a290300220220025022061ba7450d004200200b41ab7f6a220841086a29030020061b21024200200829030020061b21030c010b2007200728029801200741306a200728029c0128021c110300200741086a29030021022007290300210320072802880121170b20072017417f6a36028801200320072802b00122062903800154200220064188016a29030022035420022003511b450d04200741ec016a41026a200741a4026a41026a2d00003a0000200720072f01a4023b01ec01411e210141c895c70021124100210e0c050b200741ec016a41026a20082d00003a0000200720072f01f4013b01ec012009422088a721052009a72104412a2101419e95c70021120c050b200041003a0004200041013602002000410c6a412a360200200041086a41e695c700360200200041106a2006290200370200200041186a200641086a2802003602000c050b41c6c4ca004118200741f0026a41cc90c70041f0c4ca00103e000b41c3c5ca004110200741f0026a41dc90c70041e4c5ca00103e000b200741d0026a41086a2208200741106a41086a290300370300200741d0026a41106a220c200741106a41106a290300370300200741d0026a41186a220b200741106a41186a290300370300200741a8026a41086a220d200741306a41086a290300370300200741a8026a41106a220e200741306a41106a290300370300200741a8026a41186a2212200741306a41186a290300370300200720072903103703d002200720072903303703a8020240024020072802ac01220620072802a801470d00200641016a22132006490d012006410174220f2013200f20134b1bad42d8027e2202422088a70d012002a722134100480d010240024020060d002013102d21060c010b20072802a401200641d8026c2013103121060b2006450d05200720063602a4012007201341d8026e3602a80120072802ac0121060b20072802a401200641d8026c6a220641003a0000200620072f00cd023b0001200641013a00102006410036000c20064201370004200620072903d002370011200620072903a802370031200641036a200741cd026a41026a2d00003a0000200641196a2008290300370000200641216a200c290300370000200641296a200b290300370000200641396a200d290300370000200641c1006a200e290300370000200641c9006a201229030037000020064180016a200741bf0b6a290000370000200641f9006a200741b80b6a290000370000200641f1006a200741b00b6a290000370000200641e9006a200741900b6a41186a290000370000200641e1006a200741900b6a41106a290000370000200641d9006a200741900b6a41086a290000370000200620072900900b37005120064188016a200741f0026a41d00110e8061a200741f0016a41026a2206200741a4026a41026a2d00003a0000200741ec016a41026a220c200741a0026a41026a2d00003a0000200720072802ac0141016a22083602ac01200720072f01a4023b01f001200720072f01a0023b01ec010240200741f8016a41186a280200450d002007418c026a280200102f20072802ac0121080b200741ec006a41026a20062d00003a0000200741e8006a41026a200c2d00003a0000200720072f01f0013b016c200720072f01ec013b016820072802a801211220072802a401210e2007280294012113200728029001210b200728028c0121060240200728027c220c450d0020074180016a280200450d00200c102f0b200741900b6a41026a220c200741ec006a41026a2d00003a0000200741f0006a41026a220d200741e8006a41026a2d00003a0000200720072f016c3b01900b200720072f01683b017002400240201841ff01710d00200720133602f8022007200b3602f402200720063602f0022010200741f0026a10a40502400240200141386a280200220b2001413c6a28020022066b200841d8026c220d41d8026d220c490d00200128023421080c010b2006200c6a22082006490d03200b41017422062008200620084b1bad42d8027e2202422088a70d032002a722064100480d0302400240200b0d002006102d21080c010b2001280234200b41d8026c2006103121080b2008450d0720012008360234200141386a200641d8026e3602002001413c6a28020021060b2008200641d8026c6a200e200d10e8061a2001413c6a22062006280200200c6a36020002402012450d00200e102f0b200741e4006a41026a200741900b6a41026a2d00003a0000200741e0006a41026a200741f0006a41026a2d00003a0000200720072f01900b3b0164200720072f01703b01600c010b200741e4006a41026a200c2d00003a0000200741e0006a41026a200d2d00003a0000200720072f01900b3b0164200720072f01703b016002402008450d00200841d8026c210141002108034002400240200e20086a220c2d0000220d41014b0d0002400240200d0e020001000b0240200c41086a280200450d00200c41046a280200102f0b200c41106a2d00004107470d02200c41386a280200450d02200c41346a280200102f0c020b200c41286a108d010c010b200c41e8006a280200450d00200c41e4006a280200102f0b2001200841d8026a2208470d000b0b02402012450d00200e102f0b02400240200b0d00200621080c010b200b210c20062108034020082802880b2108200c417f6a220c0d000b0340200620062f01064102746a41880b6a2802002106200b417f6a220b0d000b0b2007418c036a20062f010636020020074188036a410036020020074184036a200636020020072013360290032007410036028003200742003703f802200720083602f402200741003602f002200741f0026a108a020b200741d4006a41026a2206200741e4006a41026a2d00003a0000200741d0006a41026a2208200741e0006a41026a2d00003a0000200720072f0164220c3b015c200720072f0160220b3b01582007200c3b01542007200b3b0150200041246a20113a00002000411c6a200741c8006a290300370000200041146a200741c0006a2903003700002000410c6a200741386a29030037000020002007290330370004200041306a20183a00002000412c6a2005360200200041286a2004360200200020072f01543b0025200041276a20062d00003a0000200020072f01503b0031200041336a20082d00003a0000200041003602000c030b1038000b20074190026a280200450d002007418c026a280200102f0b200741e4006a41026a200741f0016a41026a2d00003a0000200741e0006a41026a200741ec016a41026a2d00003a0000200720072f01f0013b0164200720072f01ec013b01600240200728027c2206450d0020074180016a280200450d002006102f0b2005ad2102200728029401210d200728028c0121060240024020072802900122080d002006210c0c010b2008210b2006210c0340200c2802880b210c200b417f6a220b0d000b0340200620062f01064102746a41880b6a28020021062008417f6a22080d000b0b200242208621022004ad21032007418c036a20062f01063602004100210820074188036a410036020020074184036a20063602002007200d360290032007410036028003200742003703f8022007200c3602f402200741003602f002200741f0026a108a02024020072802ac012206450d0020072802a401210b200641d8026c210d034002400240200b20086a22062d0000220c41014b0d0002400240200c0e020001000b0240200641086a280200450d00200641046a280200102f0b200641106a2d00004107470d02200641386a280200450d02200641346a280200102f0c020b200641286a108d010c010b200641e8006a280200450d00200641e4006a280200102f0b200d200841d8026a2208470d000b0b20022003842102024020072802a801450d0020072802a401102f0b200741dc006a41026a200741e4006a41026a2d000022063a0000200741d8006a41026a2208200741e0006a41026a2d00003a0000200720072f0164220c3b015c200720072f01603b01582000200e3a00042000200c3b0005200041076a20063a0000200041106a20113a00002000410c6a2001360200200041086a2012360200200041146a200237020020004101360200200020072f01583b0011200041136a20082d00003a00000b200741f00d6a24000f0b1036000be50f03017f037e087f230041b0026b22052400024002400240024002400240024002400240024020042802000e0401020300010b200441106a290300210620042903082107200541286a2003360200200541186a20022903103703002005412c6a2002290224370200200541206a200241186a290300370300200541346a200229022c3702002005413c6a200241346a290200370200200541c4006a2002413c6a290200370200200541cc006a200241c4006a290200370200200541106a200241086a29030020067d20022903002208200754ad7d37030041002102200541003a00002005200820077d3703082001200510e901200541003a00af01200541083a007720052006370368200520073703602005200136025c02400240200720068450450d0042002107420021060c010b200520013602a8012005200541a8016a3602c0012005200541f7006a3602bc012005200541dc006a3602b8012005200541af016a3602b4012005200541e0006a3602b001200541f8006a2001200541b0016a10a50441012102024020052802784101470d004200210620052903800121070c010b200541a0016a290300210620054198016a2903002107410021022005290380014201520d00200541f8006a41106a290300210820052802a8012101200541e8016a200541f8006a41186a290300370300200541e0016a200837030041002102200541b0016a41086a41003a0000200541b9016a2001290000370000200541c1016a200141086a290000370000200541c9016a200141106a290000370000200541d1016a200141186a290000370000200541033a00b00141c8e1ca004100200541b0016a108c010b024020020d0020072006109a010b2000200541d80010e8061a0c080b200541b7016a200241d00010e8061a200041003a0000200041016a200541b0016a41d70010e8061a0c070b200110ec01200241186a280200220341164d0d022003ad42208620022802102204ad84200341696aad422086200441176aad844101101d200541b0016a41086a41023a0000200541d9016a41003a0000200541b9016a2001290000370000200541c1016a200141086a290000370000200541c9016a200141106a290000370000200541d1016a200141186a2900003700002005410d3a00b00141c8e1ca004100200541b0016a108c01200041023a00000c010b024020042903084201520d00200441106a2903002107200441186a290300210641002104200541003a005c200541083a00af01200520063703800120052007370378200520013602a80102400240200720068450450d0042002107420021060c010b200520013602602005200541e0006a3602c0012005200541af016a3602bc012005200541a8016a3602b8012005200541dc006a3602b4012005200541f8006a3602b00120052001200541b0016a10a50441012104024020052802004101470d0042002106200529030821070c010b200541286a2903002106200541206a29030021074100210420052903084201520d00200541106a290300210820052802602103200541e8016a200541186a290300370300200541e0016a200837030041002104200541b0016a41086a41003a0000200541b9016a2003290000370000200541c1016a200341086a290000370000200541c9016a200341106a290000370000200541d1016a200341186a290000370000200541033a00b00141c8e1ca004100200541b0016a108c010b20040d0020072006109a010b02400240200241186a2802002209ad42208620022802102204ad842207100e2206422088a7220a0d004101210b0c010b2006a7210b0b200541b0016a41186a200241c4006a290000370300200541c0016a2002413c6a290000370300200541b8016a200241346a2900003703002005200229002c3703b0012005410036020820054201370300200b200a2005108c02024002402005280204220c2005280208220d6b4120490d00200d41206a21032005280200210e0c010b200d41206a2203200d490d04200c410174220e2003200e20034b1b220f4100480d0402400240200c0d00200f102d210e0c010b2005280200200c200f1031210e0b200e450d032005200f3602042005200e360200200f210c0b20052003360208200e200d6a220d20052903b001370000200d41086a200541b0016a41086a290300370000200d41106a200541b0016a41106a290300370000200d41186a200541b0016a41186a290300370000200541f8006a41186a220d2003ad422086200ead841003220341186a290000370300200541f8006a41106a220f200341106a290000370300200541f8006a41086a2210200341086a290000370300200520032900003703782003102f0240200c450d00200e102f0b200541196a200d290300370000200541116a200f290300370000200541096a201029030037000020052005290378370001200541013a00002001200510e901200941164d0d042007200941696aad422086200441176aad844101101d200541b0016a41086a41023a0000200541d9016a41013a0000200541b0016a41096a2001290000370000200541b0016a41116a200141086a290000370000200541b0016a41196a200141106a290000370000200541d1016a200141186a2900003700002005410d3a00b00141c8e1ca004100200541b0016a108c012000200541d80010e8061a200a450d00200b102f0b200241146a280200450d042004102f0c040b41172003104b000b1036000b1038000b41172009104b000b200541b0026a24000bd70d08027f017e017f027e027f057e027f067e230041f0026b2204240020032802002105418de6c300ad4280808080e00084100122032900002106200441386a41086a200341086a290000370300200420063703382003102f41f0e8c600ad4280808080f00084100122032900002106200441f0006a41086a200341086a290000370300200420063703702003102f0240024002404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100322072900002106200741086a2900002108200741106a2900002109200441f0016a41186a220a200741186a290000370300200441f0016a41106a220b2009370300200441f0016a41086a2008370300200420063703f0012007102f2003102f41c000102d2203450d002003200429033837000020032004290370370010200320042903f001370020200341086a200441386a41086a290300370000200341186a200441f0006a41086a290300370000200341286a200441f0016a41086a290300370000200341306a200b290300370000200341386a200a290300370000200441f0006a200310f6022004290370210c4200210920044200370370200441b8016a280200210a20042d00bc01210b02400240200c4201510d00200441306a4200370300200441286a4200370300200441206a4200370300200441186a4200370300200441106a4200370300200441086a4200370300200442003703004200210d42002108420021064200210e0c010b200441f0006a41386a290300210f200441f0006a41306a2903002110200441f0006a41206a290300210d200441f0006a41186a2903002109200441f0006a41c0006a290300210e200429038001210620042903782108200441206a200441f0006a41286a290300370300200441286a2010370300200441306a200f370300200441106a20093703002004200d37031820042008370300200420063703080b0240427f200820097c2209200920085422072006200d7c2007ad7c220920065420092006511b22071b427f200920071b8450450d0041dbb4c600ad4280808080b00184210641838c1c21010c020b024020082002290300220d7c220920085422072006200241086a290300220f7c2007ad7c220820065420082006511b450d004191ccc700ad4280808080800184210641838c0821010c020b2004200937030020042008370308200441386a41186a200441106a220741086a2903002206370300200441386a41206a2202200741106a290300370300200441e0006a2211200741186a290300370300200441e8006a2212200741206a290300370300200420083703402004200937033820042007290300221037034802400240427f200920107c221020102009542207200820067c2007ad7c220620085420062008511b22071b2210428080e983b1de16544100427f200620071b2206501b0d00200441386a41106a2903002106201229030021102011290300211320022903002114200429034021152004290338211642012117200429035021180c010b4200211702402010200684500d0020102006109a01200441a8026a2006370300200441a0026a2010370300200441f0016a41086a41013a0000200441f9016a200529000037000020044181026a200541086a29000037000020044189026a200541106a29000037000020044191026a200541186a290000370000200441033a00f00141c8e1ca004100200441f0016a108c010b0b20044198016a2014370300200441a0016a201337030020044180016a2015370300200441a8016a201037030020044188016a200637030020042018370390012004200e3703b00120042016370378410021072004200b4100200c42015122021b3a00bc012004200a410020021b3602b801200420174201512202ad3703700240024020020d002003ad42808080808008841005410121070c010b200441c0003602f401200420033602f001200441f8006a200441f0016a1090030b2003102f024002400240200c4201510d0020070d0041032107200441f0016a21030c010b200c4201522007410173720d0141042107200441f0006a21030b200341046a20073a0000200341003a0000200341056a20012900003700002003410d6a200141086a290000370000200341156a200141106a2900003700002003411d6a200141186a29000037000041c8e1ca0041002003108c010b200041286a200f370300200041206a200d370300200041186a2008370300200041106a2009370300200041086a4200370300410021030c020b1036000b2003102f200041086a200637020020002001360204410121030b20002003360200200441f0026a24000b130020004106360204200041dc8ec2003602000ba60303057f017e027f024020002802202201450d00034020002001417f6a360220200028020821022000280200210302400240200028020c2204200028020422052f01064f0d00200521010c010b034002400240024020054190bdc600460d00200528020022010d012002ad2106410021010c020b41edb3ca00412841f8b4ca001039000b200341016a210320053301044220862002ad8421060b2005102f2006a72102200121052006422088a7220420012f01064f0d000b0b200441016a2107200120044105746a220541fc026a2802002108200541f8026a280200210402402003450d00200120074102746a41c8056a2802002101410021072003417f6a2205450d00034020012802c80521012005417f6a22050d000b0b2000200736020c2000200236020820002001360204200041003602002004450d0102402008450d002004102f0b200028022022010d000b0b02400240200028020422054190bdc600460d00200528020021012005102f2001450d00034020014190bdc600460d02200128020021052001102f2005210120050d000b0b0f0b41edb3ca00412841f8b4ca001039000bc40201027f02402001450d00034020002802940321002001417f6a22010d000b0b02402002450d0041002103034002400240200320002f0106490d0041002104034002400240024020004190bdc600460d00200028020022010d0141002103410021010c020b41edb3ca00412841f8b4ca001039000b200441016a210420002f010421030b2000102f20012100200320012f01064f0d000b200341016a2103024020040d00200121000c020b200120034102746a4194036a2802002100410021032004417f6a2201450d01034020002802940321002001417f6a22010d000c020b0b200341016a21030b2002417f6a22020d000b0b0240024020004190bdc600460d00200028020021012000102f2001450d00034020014190bdc600460d02200128020021002001102f2000210120000d000b0b0f0b41edb3ca00412841f8b4ca001039000bfd0505047f017e017f017e0a7f230041e0016b22022400200241c0006a41186a22034200370300200241c0006a41106a22044200370300200241c0006a41086a2205420037030020024200370340419298ca00ad42808080809001842206100122072900002108200241e0006a41086a2209200741086a290000370300200220083703602007102f200520092903003703002002200229036037034041bfa8c200ad4280808080c001841001220729000021082009200741086a290000370300200220083703602007102f200420022903602208370300200241206a41086a220a2005290300370300200241206a41106a220b2008370300200241206a41186a220c200929030037030020022002290340370320200241e0006a200241206a10a502410321070240024020022d008001220d4103470d00200041086a410b360200200041046a41c193c2003602002000418a2a3b00010c010b200241206aad428080808080048422081005200241086a220e2009290300370300200241106a220f200241e0006a41106a2210290300370300200241186a2211200241e0006a41186a2212290300370300200220022903603703002003420037030020044200370300200542003703002002420037034020061001220729000021062009200741086a290000370300200220063703602007102f200520092903003703002002200229036037034041a898ca00ad4280808080d002841001220729000021062009200741086a290000370300200220063703602007102f20042002290360370000200441086a2009290300370000200a2005290300370300200b2004290300370300200c200329030037030020022002290340370320200241013a00602008200241e0006aad428080808010841004200941023a0000200241063a006041c8e1ca004100200241e0006a108c01201220112903003703002010200f2903003703002009200e29030037030020022002290300370360200141809c316a200241e0006a200d4180de3410a602410421070b200020073a0000200241e0016a24000bfe0301057f230041f0006b220224002002412036020c20022001360208200241106a2001ad4280808080800484100210730240024020022802102203450d00200241186a28020021042002280214210541002101200241003a0068024002400240034020042001460d01200241c8006a20016a200320016a2d00003a00002002200141016a22063a00682006210120064120470d000b200241286a41186a200241c8006a41186a290300370300200241286a41106a200241c8006a41106a290300370300200241286a41086a200241c8006a41086a2903003703002002200229034837032820042006460d01200320066a2d0000220141034f0d0120002002290328370000200041186a200241286a41186a290300370000200041106a200241286a41106a290300370000200041086a200241286a41086a2903003700000c020b200141ff0171450d00200241003a00680b20024100360230200242013703282002410b3602242002200241086a3602202002200241286a36026c200241dc006a41013602002002420137024c200241b885c7003602482002200241206a360258200241ec006a41d8dbc100200241c8006a103c1a200235023042208620023502288410080240200228022c450d002002280228102f0b410321010b200020013a00202005450d012003102f0c010b200041033a00200b200241f0006a24000b800a07047f017e017f017e027f017e057f230041d0016b22042400200441c8006a41186a22054200370300200441c8006a41106a22064200370300200441c8006a41086a2207420037030020044200370348419298ca00ad4280808080900184220810012209290000210a200441286a41086a220b200941086a2900003703002004200a3703282009102f2007200b29030037030020042004290328370348418398ca00ad4280808080f00184220a1001220c290000210d200441386a41086a2209200c41086a2900003703002004200d370338200c102f20062004290338220d370300200441086a41086a220c2007290300370300200441086a41106a220e200d370300200441086a41186a220f2009290300370300200420042903483703082004200441086a4120109501200428020421102004280200211120054200370300200642003703002007420037030020044200370348200810012212290000210d200b201241086a2900003703002004200d3703282012102f2007200b29030037030020042004290328370348200a10012212290000210a2009201241086a2900003703002004200a3703382012102f20062004290338220a370300200c2007290300370300200e200a370300200f20092903003703002004200429034837030820042010410020111b221241016a360248200441086aad4280808080800484200441c8006aad4280808080c000841004200f200141186a290000370300200e200141106a290000370300200c200141086a290000370300200420012900003703082008100122012900002108200b200141086a290000370300200420083703282001102f41ce97c200ad42808080808002841001220129000021082009200141086a290000370300200420083703382001102f200420123602cc01200441cc016aad4280808080c00084100322012900002108200141086a290000210a200141106a290000210d2005200141186a2900003703002006200d3703002007200a370300200420083703482001102f024041c000102d2201450d00200120042903283700002001200429033837001020012004290348370020200141086a200b290300370000200141186a2009290300370000200141286a2007290300370000200141306a2006290300370000200141386a20052903003700004104102d2207450d00200720003600004120102d2206450d0020062004290308370000200641186a2209200441086a41186a290300370000200641106a2205200441086a41106a290300370000200641086a220c200441086a41086a2903003700004124210b20074104412410312207450d00200720062900003700042007411c6a2009290000370000200741146a20052900003700002007410c6a200c2900003700002006102f02400240200241ff0171220641024d0d00412421060c010b024002400240024020060e03000102000b410021060c020b410121060c010b410221060b200420063a004841c800210b2007412441c80010312207450d01200720063a0024412521060b0240200b20066b41034b0d002007200b200b4101742209200641046a2205200920054b1b10312207450d010b200720066a20033600002001ad4280808080800884200641046aad4220862007ad8410042007102f2001102f200441d4006a2012360200200441d1006a20023a0000200441d0006a41033a0000200441063a004841c8e1ca004100200441c8006a108c01200441d0016a24000f0b1036000bb01f06057f017e017f017e137f097e230022022103200241e0036b4160712202240020024180016a41186a420037030020024180016a41106a2204420037030020024180016a41086a220542003703002002420037038001419298ca00ad4280808080900184100122062900002107200241a0036a41086a2208200641086a290000370300200220073703a0032006102f20052008290300370300200220022903a0033703800141aba8c200ad4280808080b00184100122062900002107200241d8006a41086a2208200641086a290000370300200220073703582006102f200420022903582207370300200241386a41086a2005290300370300200241386a41106a2007370300200241386a41186a2008290300370300200220022903800137033820024120360284022002200241386a3602800220024188026a200241386aad42808080808004842209100210730240024002400240024002400240200228028802220a0d004100210b0c010b200228028c02210c200220024188026a41086a28020036029c022002200a36029802200241306a20024198026a10e6010240024020022802300d002002280234220d200228029c02220e41c4006e22052005200d4b1b220fad42c4007e2207422088a70d042007a72205417f4c0d040240024020050d004104210b0c010b2005102d220b450d07200541c4006e210f0b02400240200d450d0041002110034002400240200e41044f0d00410121050c010b2002200e417c6a220836029c022002200228029802221141046a360298022011280000211241002105200241003a00a0010240024002400240034020082005460d0120024180016a20056a201120056a220641046a2d00003a00002002200641056a360298022002200541016a22063a00a0012006210520064120470d000b200241c0036a41086a221320024180016a41086a2214290300370300200241c0036a41106a221520024180016a41106a2216290300370300200241c0036a41186a221720024180016a41186a221829030037030020022002290380013703c0032002200820066b36029c0241002105200241003a00a001201120066a21192006200e6b41046a210e0340200e20056a450d0220024180016a20056a201920056a221141046a2d00003a00002002201141056a360298022002200541016a22113a00a0012008417f6a21082011210520114120470d000b200241d8006a41086a22052014290300370300200241d8006a41106a22112016290300370300200241d8006a41186a22192018290300370300200241a0036a41086a221a2013290300370300200241a0036a41106a221b2015290300370300200241a0036a41186a221c201729030037030020022002290380013703582002200820066b220e36029c02200220022903c0033703a0032018201c2903003703002016201b2903003703002014201a290300370300200220022903a00337038001201720192903003703002015201129030037030020132005290300370300200220022903583703c003410021052012211a0c040b2002410036029c02200541ff0171450d020c010b2002410036029c02200541ff0171450d010b200241003a00a0010b4100210e410121050b20024180036a41086a220820024180016a41086a29030037030020024180036a41106a221120024180016a41106a29030037030020024180036a41186a221920024180016a41186a290300370300200241e0026a41086a2212200241c0036a41086a290300370300200241e0026a41106a2213200241c0036a41106a290300370300200241e0026a41186a2214200241c0036a41186a290300370300200220022903800137038003200220022903c0033703e00220050d02201041016a2106200241c0026a41186a22152019290300370300200241c0026a41106a22192011290300370300200241c0026a41086a22112008290300370300200241a0026a41086a22082012290300370300200241a0026a41106a22122013290300370300200241a0026a41186a2213201429030037030020022002290380033703c002200220022903e0023703a0020240200f2010470d00201041017422052006200520064b1bad42c4007e2207422088a70d072007a722054100480d070240024020100d002005102d210b0c010b200b201041c4006c20051031210b0b200b450d0a200541c4006e210f0b200b201041c4006c6a2205201a360200200520022903c0023702042005410c6a2011290300370200200541146a20192903003702002005411c6a2015290300370200200520022903a0023702242005412c6a2008290300370200200541346a20122903003702002005413c6a2013290300370200200621102006200d470d000b0b200dad422086200fad842107200b450d010c020b0240200f450d00200b102f0b0b4100210b20024100360260200242013703582002410b3602c403200220024180026a3602c0032002200241d8006a3602a00320024194016a41013602002002420137028401200241b885c700360280012002200241c0036a36029001200241a0036a41d8dbc10020024180016a103c1a20023502604220862002350258841008200228025c450d002002280258102f0b200c450d00200a102f0b200b4104200b1b2112024020074200200b1b221d422088a7220b450d0020024180016a201228020010a8020240024020022802900122050d004200211e420021070c010b200241206a20022903800120024180016a41086a29030020024198016a350200420010ed06200241206a41086a29030021072002290320211e200228029401450d002005102f0b0240200b4101470d002002201e3703800141002111200241003602900120022007370388010c040b201241c4006a210e200b41c4006c41bc7f6a2119410021112012211041012106034020024180016a200e220828020010a8020240024020022802900122050d004200211f420021200c010b200241106a20022903800120024180016a41086a290300200235029801420010ed06200241106a41086a29030021202002290310211f200228029401450d002005102f0b200841c4006a210e20072020201e201f56200720205620072020511b22051b2107201e201f20051b211e2010200820051b21102011200620051b2111200641016a2106201941bc7f6a22190d000b2002201e370380012002201136029001200220073703880120100d030b20004183143b0100200041086a410b360200200041046a41c193c200360200200041026a41153a00000240201da7450d002012102f0b200324000f0b1038000b103d000b2011200b4f0d012012201141c4006c6a220541186a220829020021202012200b417f6a221141c4006c6a220641c0006a2802002110200641206a290200211e200641286a290200211f200641306a2902002121200641386a29020021222006290200212320062902082107200629021021242008200641186a290200370200200529021021252005202437021020052902082124200520073702082005290200210720052023370200200541386a2022370200200541306a2021370200200541286a201f370200200541206a2206280200210b2006201e370200200541c0006a20103602002002202537039001200220243703880120022007370380012002202037039801200241c0036a41186a200228029c01360200200241c0036a41106a200229029401370300200241c0036a41086a200229028c0137030020022002290284013703c00320024180016a41186a2208420037030020024180016a41106a2210420037030020024180016a41086a220542003703002002420037038001419298ca00ad4280808080900184100122062900002120200241a0036a41086a220e200641086a290000370300200220203703a0032006102f2005200e290300370300200220022903a0033703800141aba8c200ad4280808080b00184100122062900002120200241d8006a41086a220e200641086a290000370300200220203703582006102f20042002290358370000200441086a200e290300370000200241386a41086a2005290300370300200241386a41106a2010290300370300200241386a41186a2008290300370300200220022903800137033820024180016a2012201110850120092002350288014220862002280280012205ad8410040240200228028401450d002005102f0b2007a7210e0240201da7450d002012102f0b419298ca00ad4280808080900184100122052900002107200241a0036a41086a2206200541086a290000370300200220073703a0032005102f41b6a8c200ad4280808080900184100122052900002107200241d8006a41086a2208200541086a290000370300200220073703582005102f2002200e3602800320024180036aad4280808080c00084100322052900002107200541086a2900002120200541106a290000211e20024180016a41186a2211200541186a29000037030020024180016a41106a2210201e37030020024180016a41086a2219202037030020022007370380012005102f41c000102d2205450d00200520022903a003370000200520022903583700102005200229038001370020200541086a2006290300370000200541186a2008290300370000200541286a2019290300370000200541306a2010290300370000200541386a201129030037000020024180016a200510b60102402002280290012210450d002005ad428080808080088410050b20024188016a290300210720024198016a2802002119200229038001212020022802940121122005102f02402010450d0002402019410574450d002020200784500d0020024189016a210620194105742108200241b8016a2111201021050340200220203703a003200220073703a8032002200536028003200241d8006a2005200241a0036a20024180036a109601024020022903584201520d002002290360211e200541186a290000211f200541106a290000211d200541086a2900002109200529000021212011200241d8006a41106a29030037030020062021370000200641086a2009370000200641106a201d370000200641186a201f370000200241003a008801200241033a0080012002201e3703b00141c8e1ca00410020024180016a108c010b200541206a2105200841606a22080d000b0b200241a8016a2007370300200241a0016a202037030020024180016a41186a2205201936020020024194016a201236020020024180016a41106a220620103602002002418c016a200e36020020024180016a41086a220841013a0000200241063a00800141c8e1ca00410020024180016a108c012005200241c0036a41186a2802003602002006200241c0036a41106a2903003703002008200241c0036a41086a290300370300200220022903c003370380012002200b36029c01200141809c316a20024180016a41004180de3410a6020b200041043a0000200324000f0b1036000b419cc3ca002011200b103b000bf70305027f017e027f027e027f230041d0006b22022400419298ca00ad4280808080900184100122032900002104200241086a41086a2205200341086a290000370300200220043703082003102f41b6a8c200ad4280808080900184100122032900002104200241386a41086a2206200341086a290000370300200220043703382003102f2002200136024c200241cc006aad4280808080c00084100322032900002104200341086a2900002107200341106a2900002108200241186a41186a2209200341186a290000370300200241186a41106a220a2008370300200241186a41086a22012007370300200220043703182003102f024041c000102d2203450d00200320022903083700002003200229033837001020032002290318370020200341086a2005290300370000200341186a2006290300370000200341286a2001290300370000200341306a200a290300370000200341386a2009290300370000200241186a200310b601200620012903003703002005200241186a411c6a280200360200200220022903183703382002200229022c370308024020022802282205450d002000200229033837030020002002290308370214200041086a200241386a41086a2903003703002000411c6a200241086a41086a2802003602000b200020053602102003102f200241d0006a24000f0b1036000baf0305027f017e027f027e027f230041d0006b22022400419298ca00ad4280808080900184100122032900002104200241086a41086a2205200341086a290000370300200220043703082003102f41a2a8c200ad4280808080900184100122032900002104200241186a41086a2206200341086a290000370300200220043703182003102f2002200136024c200241cc006aad4280808080c00084100322032900002104200341086a2900002107200341106a2900002108200241286a41186a2201200341186a290000370300200241286a41106a22092008370300200241286a41086a220a2007370300200220043703282003102f024041c000102d2203450d00200320022903083700002003200229031837001020032002290328370020200341086a2005290300370000200341186a2006290300370000200341286a200a290300370000200341306a2009290300370000200341386a2001290300370000200241286a200341c00010aa020240024020022802282201450d002000200229022c370204200020013602000c010b20004100360208200042013702000b2003102f200241d0006a24000f0b1036000bbf0201017f230041e0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100210730240024020032802102201450d00200328021421022003200341106a41086a28020036022420032001360220200341c8006a200341206a109803024002402003280248450d0020002003290348370200200041086a200341c8006a41086a2802003602000c010b20034100360230200342013703282003410b36023c2003200341086a3602382003200341286a360244200341dc006a41013602002003420137024c200341b885c7003602482003200341386a360258200341c4006a41d8dbc100200341c8006a103c1a200335023042208620033502288410080240200328022c450d002003280228102f0b200041003602000b2002450d012001102f0c010b200041003602000b200341e0006a24000bac0603027f037e037f230041f0006b22022400200241086a2001410c6a290200370300200241106a200141146a290200370300200241186a2001411c6a2902003703002002200129020437030020012802002103419298ca00ad4280808080900184100122012900002104200241206a41086a200141086a290000370300200220043703202001102f41de97c200ad4280808080e00084100122012900002104200241306a41086a200141086a290000370300200220043703302001102f02404104102d2201450d002001200336000020014104412410312201450d00200120022903003700042001411c6a200241186a290300370000200141146a200241106a2903003700002001410c6a200241086a2903003700002001ad4280808080c00484100322032900002104200341086a2900002105200341106a2900002106200241c0006a41186a2207200341186a290000370300200241c0006a41106a22082006370300200241c0006a41086a22092005370300200220043703402003102f2001102f41c000102d2201450d00200120022903203700002001200229033037001020012002290340370020200141086a200241206a41086a290300370000200141186a200241306a41086a290300370000200141286a2009290300370000200141306a2008290300370000200141386a2007290300370000200241c00036026420022001360260200241306a2001ad42808080808008841002107302400240200228023022030d0041002103410021070c010b2002280234210902400240200241386a280200450d0020032d0000220741ff0071220841064b0d00200741077621070c010b20024100360208200242013703002002410b3602242002200241e0006a3602202002200236026c200241d4006a410136020020024201370244200241b885c7003602402002200241206a360250200241ec006a41d8dbc100200241c0006a103c1a2002350208422086200235020084100802402002280204450d002002280200102f0b410221070b02402009450d002003102f0b4100200820074102461b2103200741017121070b2001102f200020033a0001200020073a0000200241f0006a24000f0b1036000ba40e08017f047e0c7f017e027f027e037f057e23004190046b2205240002400240024020040d00420021064200210742002108420021090c010b419298ca00ad42808080809001841001220a290000210620054190036a41086a220b200a41086a2900003703002005200637039003200a102f41f992c200ad42808080809002841001220a2900002106200541a0036a41086a220c200a41086a290000370300200520063703a003200a102f200541a8026a41086a220a200b290300370300200541a8026a41186a220b200c29030037030020052005290390033703a802200520052903a0033703b802200541e0016a200541a8026a108801200541a8026a20052802e001220c20052802e80110ad02024020052802e401450d00200c102f0b20054190016a41086a200a290300220637030020054190016a41106a200541a8026a41106a290300220737030020054190016a41186a200b290300220837030020054190016a41206a200541a8026a41206a220d2d0000220a3a0000200520052903a802220937039001200541b8016a41206a200a3a0000200541b8016a41186a2008370300200541b8016a41106a2007370300200541b8016a41086a2006370300200520093703b801200541e0016a200541b8016a10ae024200210842002109420021064200210720052d00a0024107460d002004417f6a210e200541a8026a41c0006a210f200541a8026a41186a211042002106420021074200210842002109034020102007370300200520063703b802200520083703a802200520093703b002200d200541e0016a41c10010e806210a02400240200f2002460d00200f2002412010ea060d010b200541b0036a41186a220c200a41186a2211290200370300200541b0036a41106a2212200a41106a2213290200370300200541b0036a41086a2214200a41086a22152902003703002005200a2902003703b003419298ca00ad428080808090018410012204290000211620054190036a41086a2217200441086a29000037030020052016370390032004102f41de97c200ad4280808080e00084100122042900002116200541a0036a41086a2218200441086a290000370300200520163703a0032004102f4104102d2204450d032004200136000020044104412410312204450d03200420052903b0033700042004411c6a200c290300370000200441146a20122903003700002004410c6a20142903003700002004ad4280808080c004841003220b2900002116200b41086a2900002119200b41106a290000211a200541d0036a41186a221b200b41186a290000370300200541d0036a41106a221c201a370300200541d0036a41086a221d2019370300200520163703d003200b102f2004102f41c000102d2204450d032004200529039003370000200420052903a003370010200420052903d003370020200441086a2017290300370000200441186a2018290300370000200441286a201d290300370000200441306a201c290300370000200441386a201b29030037000020054188016a200441c00041c8e1ca004100410010b501200528028801210b2004102f200b4101460d0020052d0088032104200c201129000037030020122013290000370300201420152900003703002005200a2900003703b003200541d0036a200541b0036a108d02427f201d2903002216201b2903007c20052903d003221920052903e0037c221a201954220aad7c2219200a201920165420192016511b220a1b2119427f201a200a1b211602400240200420032004200341ff0171491b220441ff0171450d00200541c8006a201942002004ad42ff0183221a420010ed06200541d8006a20164200201a420010ed06201b200c290300370300201c2012290300370300201d2014290300370300200520052903b0033703d003200541e8006a2001200541d0036a2004200e10ac02200541386a420042002016420010ed06427f200541d8006a41086a290300221a200529034820052903387c7c221e2005290350200529034084420052201e201a547222041b211e427f200529035820041b211a200541e8006a41186a290300211f200541e8006a41086a290300212020052903782121200529036821220c010b200541086a20162019420a420010ee06201b200c290300370300201c2012290300370300201d2014290300370300200520052903b0033703d003200541186a2001200541d0036a4100200e10ac02200541186a41186a290300211f200541186a41086a290300212020052903282121200529031821222005290308221a2116200541086a41086a290300221e21190b201920077c201620067c2207201654ad7c201f7c200720217c2206200754ad7c2107201e20097c201a20087c2209201a54ad7c20207c200920227c2208200954ad7c21090b200541e0016a200541b8016a10ae0220052d00a0024107470d000b0b2000200637031020002008370300200041186a20073703002000200937030820054190046a24000f0b1036000bd50302047f047e230041f0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100210730240024020032802102204450d00200341186a28020021052003280214210641002101200341003a006802400240034020052001460d01200341c8006a20016a200420016a2d00003a00002003200141016a22023a00682002210120024120470d000b200341206a41186a200341c8006a41186a2903002207370300200341206a41106a200341c8006a41106a2903002208370300200341206a41086a200341c8006a41086a290300220937030020032003290348220a370320200041196a2007370000200041116a2008370000200041096a20093700002000200a370001410121010c010b0240200141ff0171450d00200341003a00680b4100210120034100360228200342013703202003410b3602442003200341086a3602402003200341206a36026c200341dc006a41013602002003420137024c200341b885c7003602482003200341c0006a360258200341ec006a41d8dbc100200341c8006a103c1a200335022842208620033502208410082003280224450d002003280220102f0b200020013a00002006450d012004102f0c010b200041003a00000b200341f0006a24000b800803037f047e067f230022022103200241c0036b41607122022400200141186a22042900002105200420022903b80237000020012900102106200120022903b00237001020012900082107200120022903a802370008200241003a00a00220012900002108200120022903a002370000200220053703b801200220063703b001200220073703a801200220083703a001200141206a2d00002104200241a0026a41176a22092005370000200241a0026a41106a220a20022900b101370300200241a0026a41086a220b20022900a901370300200220022900a1013703a0020240024002402008a741ff01714101470d00200241106a41176a2009290000370000200241106a41106a200a290300370300200241106a41086a200b290300370300200220022903a002370310200220043a002f20024190026a200241106a10b602200241a0026a200228029002220420022802980210cb0220022d00c1024102470d02200241003602a0032002420137039803200241306a41146a41293602002002413c6a410b360200200241093602ac032002419298ca003602a8032002410b3602342002410b3602b4032002418a93c2003602b003200220024190026a3602402002200241b0036a3602382002200241a8036a360230200220024198036a3602bc03200241d8006a41146a41033602002002420337025c200241b48fc4003602582002200241306a360268200241bc036a41d8dbc100200241d8006a103c1a20023502a0034220862002350298038410080240200228029c03450d00200228029803102f0b200041073a0040200228029402450d01200228029002102f200324000f0b200041073a00400b200324000f0b200241a0016a200241a0026a41e30010e8061a0240200228029402450d002004102f0b200241306a41206a2204200241a0026a41206a2d00003a0000200241306a41186a2209200241a0026a41186a220a290300370300200241306a41106a220b200241a0026a41106a220c290300370300200241306a41086a220d200241a0026a41086a220e290300370300200220022903a002370330200241d8006a200241c1016a41c20010e8061a200141206a200241d8006a41c1006a2d00003a0000200141186a20024191016a290000370000200141106a20024189016a290000370000200141086a20024181016a29000037000020012002290079370000200a200241106a41186a290300370300200c200241106a41106a290300370300200e200241106a41086a290300370300200220022903103703a002200241c8026a200d290300370300200241d0026a200b290300370300200241d8026a2009290300370300200241e0026a20042d00003a0000200220022903303703c0022000200241a0026a41c10010e8061a200324000bd61007017f017e017f017e027f037e087f230041f0006b22012400419298ca00ad42808080809001842202100122032900002104200141106a41086a2205200341086a290000370300200120043703102003102f41ce97c200ad4280808080800284100122032900002104200141206a41086a2206200341086a290000370300200120043703202003102f20012000360250200141d0006aad22044280808080c00084100322032900002107200341086a2900002108200341106a2900002109200141306a41186a220a200341186a290000370300200141306a41106a220b2009370300200141306a41086a220c2008370300200120073703302003102f024041c000102d2203450d00200320012903103700002003200129032037001020032001290330370020200341086a2005290300370000200341186a2006290300370000200341286a200c290300370000200341306a200b290300370000200341386a200a2903003700002003ad428080808080088410052003102f200a4200370300200b4200370300200c42003703002001420037033020021001220329000021022005200341086a290000370300200120023703102003102f200c200529030037030020012001290310370330419b98ca00ad4280808080d0018422021001220329000021072006200341086a290000370300200120073703202003102f200b20012903202207370300200141d0006a41086a200c290300370300200141d0006a41106a2007370300200141d0006a41186a200629030037030020012001290330370350200141086a200141d0006a41201095010240200128020c410020012802081b22032000470d00200141306a41186a22054200370300200141306a41106a22064200370300200141306a41086a2203420037030020014200370330419298ca00ad42808080809001841001220c2900002107200141106a41086a220a200c41086a29000037030020012007370310200c102f2003200a29030037030020012001290310370330418398ca00ad4280808080f001841001220c2900002107200141206a41086a220a200c41086a29000037030020012007370320200c102f200b2001290320370000200b41086a200a290300370000200141d0006a41086a2003290300370300200141d0006a41106a2006290300370300200141d0006a41186a2005290300370300200120012903303703502001200141d0006a41201095012001280200210c20012802042105200041016a220310b0022106200320054100200c1b22054f0d0020060d000340200341016a220310b002210c200320054f0d01200c450d000b0b200141306a41186a22054200370300200141306a41106a22064200370300200141306a41086a220c420037030020014200370330419298ca00ad428080808090018422071001220d2900002108200141106a41086a220a200d41086a29000037030020012008370310200d102f200c200a2903003703002001200129031037033020021001220e2900002102200141206a41086a220d200e41086a29000037030020012002370320200e102f200b2001290320370000200b41086a200d290300370000200141d0006a41086a200c290300370300200141d0006a41106a2006290300370300200141d0006a41186a2005290300370300200120012903303703502001200336023020044280808080800484200141306aad4280808080c0008410042007100122032900002102200a200341086a290000370300200120023703102003102f41a2a8c200ad4280808080900184100122032900002102200d200341086a290000370300200120023703202003102f2001200036025020044280808080c00084100322032900002104200341086a2900002102200341106a29000021072005200341186a29000037030020062007370300200c2002370300200120043703302003102f41c000102d2203450d00200320012903103700002003200129032037001020032001290330370020200341086a200a290300370000200341186a200d290300370000200341286a200c290300370000200341306a2006290300370000200341386a20052903003700002003ad428080808080088410052003102f200141d0006a200010a9022001280254210f20012802502110024020012802582203450d002003410574210b419298ca00ad428080808090018421082010210c0340200141d0006a41186a2205200c41186a290000370300200141d0006a41106a2206200c41106a290000370300200141d0006a41086a220a200c41086a2900003703002001200c2900003703502008100122032900002104200141106a41086a220d200341086a290000370300200120043703102003102f41de97c200ad4280808080e00084100122032900002104200141206a41086a220e200341086a290000370300200120043703202003102f4104102d2203450d022003200036000020034104412410312203450d02200320012903503700042003411c6a2005290300370000200341146a20062903003700002003410c6a200a2903003700002003ad4280808080c00484100322052900002104200541086a2900002102200541106a2900002107200141306a41186a2206200541186a290000370300200141306a41106a220a2007370300200141306a41086a22112002370300200120043703302005102f2003102f41c000102d2203450d02200c41206a210c200320012903103700002003200129032037001020032001290330370020200341086a200d290300370000200341186a200e290300370000200341286a2011290300370000200341306a200a290300370000200341386a20062903003700002003ad428080808080088410052003102f200b41606a220b0d000b0b0240200f450d002010102f0b200141f0006a24000f0b1036000b8e0305027f017e027f027e027f230041d0006b22012400419298ca00ad4280808080900184100122022900002103200141086a41086a2204200241086a290000370300200120033703082002102f41ce97c200ad4280808080800284100122022900002103200141186a41086a2205200241086a290000370300200120033703182002102f2001200036024c200141cc006aad4280808080c00084100322022900002103200241086a2900002106200241106a2900002107200141286a41186a2200200241186a290000370300200141286a41106a22082007370300200141286a41086a22092006370300200120033703282002102f024041c000102d22020d001036000b200220012903083700002002200129031837001020022001290328370020200241086a2004290300370000200241186a2005290300370000200241286a2009290300370000200241306a2008290300370000200241386a20002903003700002001200241c00041c8e1ca004100410010b501200128020021002002102f200141d0006a240020004101460be21407027f017e017f027e057f037e037f230041b0086b22032400419298ca00ad4280808080900184100122042900002105200341d8006a41086a200441086a290000370300200320053703582004102f4199a8c200ad428080808090018410012204290000210520034190036a41086a200441086a29000037030020032005370390032004102f0240024002404120102d2204450d0020042001290000370000200441186a200141186a290000370000200441106a200141106a290000370000200441086a200141086a2900003700002004ad4280808080800484100322062900002105200641086a2900002107200641106a2900002108200341c0056a41186a2209200641186a290000370300200341c0056a41106a220a2008370300200341c0056a41086a2007370300200320053703c0052006102f2004102f41c000102d2204450d00200420032903583700002004200329039003370010200420032903c005370020200441086a200341d8006a41086a290300370000200441186a20034190036a41086a220b290300370000200441286a200341c0056a41086a220c290300370000200441306a200a290300370000200441386a2009290300370000200341c0056a200410b202024020032802d0052206450d002004ad428080808080088410050b200b200341e4056a290200220837030020034190036a41106a200341ec056a220d290200220e37030020034190036a41186a200341f4056a290200220f3703002003200341dc056a290200221037039003200c2903002105200341c0056a41186a2209280200210a20032903c005210720032802d405210b2009200f370300200341c0056a41106a2211200e370300200c2008370300200320103703c00502402006450d00200341186a41186a220c2009290300370300200341186a41106a22092011290300370300200341186a41086a2211200341c0056a41086a290300370300200320032903c0053703182004102f200341386a41186a200c290300370300200341386a41106a2009290300370300200341386a41086a2011290300370300200320032903183703382003200a36028c032003200636028803200341d8006a20034188036a10b30202402003280258411b460d0020034190036a200341d8006a41b00210e8061a200320073703a008200320053703a80802402007200584500d002003200341386a3602f407200341f8076a200341386a200341a0086a200341f4076a10960120032903f8074201520d002003290380082108200341f8056a200341f8076a41106a290300370300200341f0056a2008370300200341c0056a41086a41003a0000200341c9056a2003290338370000200341d1056a200341386a41086a290300370000200341d9056a200341386a41106a290300370000200341e1056a200341d0006a290300370000200341033a00c00541c8e1ca004100200341c0056a108c010b200341c0056a41086a2204410c3a0000200341e9056a2003290338370000200341c9056a220c2001290000370000200341d1056a200141086a290000370000200341d9056a200141106a290000370000200341e1056a200141186a290000370000200341f1056a200341386a41086a290300370000200341f9056a200341386a41106a29030037000020034181066a200341386a41186a290300370000200341063a00c00520034198066a200537030020034190066a200737030041c8e1ca004100200341c0056a108c01200341c0056a20034190036a41b00210e8061a200341003b01f807200341a0086a200341c0056a200341f8076a108b0120032d00a0082101200341c0056a410c6a2002360200200c20014104463a0000200441073a0000200341063a00c00541c8e1ca004100200341c0056a108c01200041043a00000c030b200320073703f8072003200537038008024002400240024020072005844200520d00200342003703a808200342003703a0080c010b2003200341386a3602a00820034190036a200341386a200341f8076a200341a0086a10bd01200341b0036a290300210520032903a803210702402003290390034201520d002003290398032108200341f8056a20034190036a41106a290300370300200341f0056a2008370300200341c0056a41086a41003a0000200341c9056a2003290338370000200341d1056a200341386a41086a290300370000200341d9056a200341386a41106a290300370000200341e1056a200341d0006a290300370000200341033a00c00541c8e1ca004100200341c0056a108c010b200320073703a008200320053703a80820072005844200520d010b200341c0056a41186a22114200370300200341c0056a41106a22094200370300200341c0056a41086a220c4200370300200342003703c00541e7a2ca00ad428080808080018422051001220a2900002107200341f8076a41086a2204200a41086a290000370300200320073703f807200a102f200c2004290300370300200320032903f8073703c00541ecb5c600ad4280808080d0018422071001220a29000021082004200a41086a290000370300200320083703f807200a102f200920032903f807220837030020034190036a41086a220d200c29030037030020034190036a41106a2212200837030020034190036a41186a22132004290300370300200320032903c00537039003200320034190036a4120109c01200341106a29030021082003290308210e2003280200210a2011420037030020094200370300200c4200370300200342003703c00520051001221129000021052004201141086a290000370300200320053703f8072011102f200c2004290300370300200320032903f8073703c00520071001221129000021052004201141086a290000370300200320053703f8072011102f200920032903f8072205370300200d200c2903003703002012200537030020132004290300370300200320032903c00537039003200320084200200a1b3703c8052003200e4200200a1b3703c00520034190036aad4280808080800484200341c0056aad428080808080028410040c010b200341c0056a41f4c7c40010b402200341c0056a2007200510b502200341d8056a2005370300200341d0056a2007370300200341c8056a41063a00002003410c3a00c00541c8e1ca004100200341c0056a108c010b200341c0056a41086a410d3a0000200341c9056a2001290000370000200341ec056a2002360200200341d1056a200141086a290000370000200341d9056a200141106a290000370000200341e1056a200141186a290000370000200341063a00c00541c8e1ca004100200341c0056a108c01200041086a410f360200200041046a41cc93c200360200200041026a41143a000020004183143b01000c020b2004102f200341c0056a41086a410e3a0000200d2002360200200341c9056a2001290000370000200341d1056a200141086a290000370000200341d9056a200141106a290000370000200341e1056a200141186a290000370000200341063a00c00541c8e1ca004100200341c0056a108c01200041086a410f360200200041046a41ec93c200360200200041026a41123a000020004183143b01000c020b1036000b200b450d002006102f0b200341b0086a24000b890702097f027e230041a0016b22022400200241c00036021420022001360210200241186a2001ad428080808080088410021073024002400240024002400240024020022802182203450d00200228021c21042002200241206a28020036024c20022003360248200241086a200241c8006a10e60120022802080d04200228024c2205200228020c2206490d042006417f4c0d010240024020060d00410121070c010b200610332207450d03200720022802482201200610e8061a2002200520066b220536024c2002200120066a3602480b2007450d0441002101200241003a009801417f2108024002400240034020052001460d01200241f8006a20016a200228024822092d00003a00002002200520086a36024c2002200941016a3602482002200141016a220a3a0098012008417f6a2108200a2101200a4120470d000b200241d8006a41186a200241f8006a41186a290300370300200241d8006a41106a200241f8006a41106a290300370300200241d8006a41086a200241f8006a41086a290300370300200220022903783703582005200a6b22014110490d012002200941116a3602482002200141706a220836024c200841044f0d0220060d060c070b0240200141ff0171450d00200241003a0098010b2006450d060c050b20060d040c050b200941096a290000210b2009290001210c200241286a41086a2208200241d8006a41086a290300370300200241286a41106a220a200241d8006a41106a290300370300200241286a41186a2205200241d8006a41186a290300370300200220022903583703282002200941156a36024820022001416c6a36024c2007450d04200928001121012000200c37030020002006360214200020073602102000200b370308200041186a20063602002000411c6a20022903283702002000413c6a2001360200200041246a20082903003702002000412c6a200a290300370200200041346a20052903003702000c050b200041003602100c050b103d000b1036000b2007102f0b20024100360260200242013703582002410b36022c2002200241106a3602282002200241d8006a3602542002418c016a41013602002002420137027c200241b885c7003602782002200241286a36028801200241d4006a41d8dbc100200241f8006a103c1a200235026042208620023502588410080240200228025c450d002002280258102f0b200041003602100b2004450d002003102f0b200241a0016a24000bb2c40209087f027e067f027e027f067e0a7f017e1c7f230041c0116b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a22063602042001200441016a3602002005411a4b0d3d200141046a210720050e1b0102030405060708090a0b0c0d0e0f101112131415161718192324010b2000411b3602000c540b2006450d5120042d0001210520012003417e6a22083602042001200441026a360200200541094b0d51410a2109024002400240024002400240024002400240024020050e0a00010203040506070809000b20084104490d5a2004280002210620012003417a6a3602042001200441066a360200410121090c080b2002200110e60120022802000d59200728020020022802042204490d592004417f4c0d2b0240024020040d00410121060c010b200410332206450d2120072802002004490d5920062001280200200410e8061a200128020422032004490d2d2001200320046b3602042001200128020020046a3602000b2006450d592004ad220a422086200a84210a410221090c070b20084108490d582004290002210a2001200341766a36020420012004410a6a360200410321090c060b200241086a200110e60120022802080d572007280200200228020c2204490d572004417f4c0d290240024020040d00410121060c010b200410332206450d1f20072802002004490d5720062001280200200410e8061a200128020422032004490d2c2001200320046b3602042001200128020020046a3602000b2006450d572004ad220a422086200a84210a410421090c050b200241106a200110e60120022802100d56200728020020022802142204490d562004417f4c0d280240024020040d00410121060c010b200410332206450d1e20072802002004490d5620062001280200200410e8061a200128020422032004490d2c2001200320046b3602042001200128020020046a3602000b2006450d562004ad220a422086200a84210a410521090c040b2008450d5520042d0002210520012003417d6a22073602042001200441036a360200200541014b0d554106210941002106024020050e020400040b20074104490d552004350003210a2001200341796a22053602042001200441076a36020020054104490d552004350007210b2001200341756a36020420012004410b6a360200200b422086200a84210a410121060c030b200241286a200110e60120022802280d54200228022c220c200728020041186e22042004200c4b1b220dad42187e220a422088a70d26200aa72204417f4c0d260240024020040d00410421060c010b2004102d2206450d1c200441186e210d0b0240200c450d004100210e41002104410021080340200241206a200110e60102400240024020022802200d00200728020020022802242203490d002003417f4c0d2b02400240024020030d004101210f0c010b20031033220f450d2220072802002003490d01200f2001280200200310e8061a200128020422052003490d312001200520036b3602042001200128020020036a3602000b200241186a200110e601024020022802180d002007280200200228021c2205490d002005417f4c0d2d02400240024020050d00410121100c010b200510332210450d2420072802002005490d0120102001280200200510e8061a200128020422092005490d342001200920056b3602042001200128020020056a3602000b200841016a21092008200d470d05200e2009200e20094b1bad42187e220a422088a70d5d200aa7220d41004e0d040c5d0b2010102f0b2003450d010b200f102f0b02402008450d002006210103400240200141046a280200450d002001280200102f0b0240200141106a280200450d002001410c6a280200102f0b200141186a2101200441686a22040d000b0b200d450d580c570b0240024020080d00200d102d21060c010b20062004200d103121060b2006450d1e200d41186e210d0b200620046a2208200f360200200841106a2005ad220a422086200a843702002008410c6a2010360200200841046a2003ad220a422086200a84370200200e41026a210e200441186a210420092108200c2009470d000b0b2006450d54200cad422086200dad84210a410721090c020b200241386a200110e60120022802380d53200228023c22102007280200410c6e2204200420104b1b220fad420c7e220a422088a70d25200aa72204417f4c0d250240024020040d00410421060c010b2004102d2206450d1b2004410c6e210f0b0240024002402010450d004100210841002103410021090340200241306a200110e60120022802300d03200728020020022802342204490d032004417f4c0d290240024020040d004101210e0c010b20041033220e450d1f20072802002004490d03200e2001280200200410e8061a200128020422052004490d302001200520046b3602042001200128020020046a3602000b200941016a210502402009200f470d0020082005200820054b1bad420c7e220a422088a70d59200aa7220f4100480d590240024020090d00200f102d21060c010b20062003200f103121060b2006450d1f200f410c6e210f0b200620036a2209200e360200200941046a2004ad220a422086200a84370200200841026a21082003410c6a21032005210920102005470d000b0b2006450d552010ad422086200fad84210a410821090c030b200e102f0b02402009450d002006210103400240200141046a280200450d002001280200102f0b2001410c6a2101200341746a22030d000b0b200f0d520c530b200241c0006a200110e60120022802400d52200728020020022802442204490d522004417f4c0d240240024020040d00410121060c010b200410332206450d1a20072802002004490d5220062001280200200410e8061a200128020422032004490d2c2001200320046b3602042001200128020020046a3602000b2006450d522004ad220a422086200a84210a410921090b20004100360200200041106a200a3702002000410c6a2006360200200041086a2009360200200041186a200241900f6a41980210e8061a0c530b2006450d4e20042d0001210520012003417e6a22063602042001200441026a360200200541044b0d4e02400240024002400240024002400240024020050e050001020304000b200241900f6a200110970320022802900f2204450d5620022902940f220a422088a72110200aa7210341012111410021050c040b20064102490d5520042f0002210520012003417c6a3602042001200441046a360200200241e00c6a200110b30220022802e00c411b460d55200241900f6a200241e00c6a41b00210e8061a41b002102d2204450d1e2004200241900f6a41b00210e8061a20024191096a33000020024193096a31000042108684210a200229008909210b200228028409211020022d008809210d410221110c030b20064102490d5420042f0002210520012003417c6a3602042001200441046a360200200241900f6a200110980320022802900f2204450d5420022802940f21030240024020072802002206450d00200241980f6a2802002110200128020022092d0000210720012006417f6a22083602042001200941016a3602000240024002400240200741014b0d0020070e020201020b200241023602900f0c040b024020084104490d002009280001210820012006417b6a22073602042001200941056a36020020074104490d00200928000521072001200641776a3602042001200941096a360200200241980f6a2007360200200220083602940f4101210d0c020b200241023602900f0c030b4100210d0b2002200d3602900f200241990f6a330000210a2002419b0f6a310000211220022900910f210b200241e00c6a200110b30220022802e00c411b460d07200241900f6a200241e00c6a41b00210e8061a41b002102d2201450d1f200a201242108684210a2001200241900f6a41b00210e8061a410321110c040b200241023602900f0b2003450d540c530b20064102490d5320042f0002210820012003417c6a3602042001200441046a360200200241900f6a200110980320022802900f2206450d5320022802940f2109024020072802002204450d00200241980f6a2802002107200128020022052d0000210320012004417f6a22103602042001200541016a360200200341014b0d004100210e0240024020030e020100010b20104104490d012005280001210f20012004417b6a22033602042001200541056a36020020034104490d012005280005210c2001200441776a22103602042001200541096a3602004101210e0b41002103200241003a00b00f2010417f6a2104024003402004417f460d01200241900f6a20036a200128020022052d00003a0000200120043602042001200541016a3602002002200341016a22053a00b00f2004417f6a21042005210320054120470d000b200241c00c6a41106a200241a70f6a290000370300200241c00c6a41086a2002419f0f6a2900002212370300200220022900970f22133703c00c20022f01900f20022d00920f4110747222144108762105200241d10c6a330000200241d30c6a31000042108684210a200241af0f6a2d0000211520022800930f210420022802c40c211020022802d40c210120022900c90c210b2013a721032012a7210d410421110c030b0240200341ff0171450d00200241003a00b00f0b2009450d542006102f0c540b2009450d532006102f0c530b20064102490d5220042f0002210820012003417c6a3602042001200441046a360200200241900f6a200110980320022802900f2206450d5220022802940f2109200728020022034104490d02200241980f6a280200210720012802002210280000210e20012003417c6a22043602042001201041046a36020020044104490d022010280004210f2001200341786a220d3602042001201041086a36020041002104200241003a00b00f200341776a21030340200d2004460d02200241900f6a20046a201020046a220541086a2d00003a0000200120033602042001200541096a3602002002200441016a22053a00b00f2003417f6a21032005210420054120470d000b20024180096a41106a200241a70f6a29000037030020024198096a200241af0f6a2d00003a000020024180096a41086a2002419f0f6a290000221237030020022f01900f20022d00920f411074722214410876210520022900970f2213422088a7211020024191096a290000220a423888a72115200a421888a7210120022800930f2104200229008909210b2013a721032012a7210d410521110b200020143a0005200020113a0004200041013602002000411d6a200a3d0000200041156a200b3700002000413c6a200c360200200041386a200f360200200041346a200e360200200041306a20073602002000412c6a2009360200200041286a2006360200200041266a20083b0100200041246a20153a0000200041206a2001360200200041146a200d3a0000200041106a20103602002000410c6a2003360200200041086a2004360200200041066a20053b01002000411f6a200a4210883c0000200041c0006a20024190066a41f00110e8061a0c550b0240200441ff0171450d00200241003a00b00f0b2009450d502006102f0c500b2009450d4f2006102f0c4f0b20030d4d0c4e0b02402006450d0020012003417e6a3602042001200441026a3602000b2000411b3602000c510b02402006450d0020042d0001210520012003417e6a3602042001200441026a36020020050d00200241c8006a20011099032002290348a70d002002290350210a20004103360200200041086a200a370300200041106a200241900f6a41a00210e8061a0c510b2000411b3602000c500b02402006450d0020042d0001210520012003417e6a3602042001200441026a36020020050d00200241e00c6a2001109a0320022802e00c2201450d00200041086a20022902e40c3702002000200136020420004104360200200041106a200241900f6a41a00210e8061a0c500b2000411b3602000c4f0b02402006450d0020042d0001210520012003417e6a22063602042001200441026a360200200541034b0d0002400240024002400240024020050e0400010203000b20064104490d052004280002210520012003417a6a3602042001200441066a36020020024180086a41086a20024190066a41086a29030037030020024180086a41106a20024190066a41106a2f01003b0100200220022903900637038008410121064100210141002109410021080c030b41002105200241003a00800d2003417e6a2109417d21060240034020092005460d01200241e00c6a20056a200420056a220741026a2d00003a00002001200320066a3602042001200741036a3602002002200541016a22073a00800d2006417f6a21062007210520074120470d000b20024190066a410f6a200241e00c6a410f6a29000037000020024190066a41176a200241e00c6a41176a29000037000020024190066a411f6a200241e00c6a411f6a2d00003a0000200220022d00e20c22093a009206200220022f01e00c22083b019006200220022800e30c220536009306200220022900e70c37009706200320076b2203417e6a4104490d0541022106200420076a220741026a280000210e200241800c6a41106a20024190066a410772220441106a290000370300200241800c6a41086a200441086a290000370300200241800c6a41186a200441186a2d00003a000020012003417a6a3602042001200741066a36020020024180086a41086a200241800c6a410f6a29000037030020024180086a41106a200241800c6a41176a2f00003b010020022004290000220a3703800c200220022900870c370380082008200941107472220741ffffff0771220141107621042001410876210320022f01840c20022d00860c41107472210820022d00830c2109200aa721010c030b200541ff0171450d04200241003a00800d0c040b20064104490d032004280002210520012003417a6a3602042001200441066a36020020024180086a41086a200241a00c6a41086a29030037030020024180086a41106a200241a00c6a41106a2f01003b0100200220022903a00c37038008410321064100210141002104410021080c010b41002105200241003a00800d2003417e6a2109417d2106034020092005460d02200241e00c6a20056a200420056a220741026a2d00003a00002001200320066a3602042001200741036a3602002002200541016a22073a00800d2006417f6a21062007210520074120470d000b20024198096a200241ff0c6a2d00003a000020024180096a41106a200241e00c6a41176a29000037030020024180096a41086a200241e00c6a410f6a290000220b37030041042106200320076b2203417e6a4104490d0220022d00e20c210920022f01e00c210820022800e30c210520022900e70c210a2002290089092112200420076a220441026a280000210e200241c00c6a41116a20024180096a41116a29000037000020012003417a6a3602042001200441066a360200200220123700c90c20024180086a41086a200241c00c6a410f6a29000037030020024180086a41106a200241c00c6a41176a2f00003b01002002200ba73a00c80c2002200a3703c00c200220022900c70c370380082008200941107472220741ffffff07712201411076210420014108762103200a422088a72108200a421888a72109200aa721010b200241800a6a41106a20024180086a41106a2f0100220f3b0100200241800a6a41086a20024180086a41086a290300220a3703002002200229038008220b3703800a2000410e6a20014110763a00002000410c6a20013b01002000410f6a2008410874200941ff017172360000200041086a2005360200200020043a0007200020033a0006200020073a0005200020063a0004200041053602002000200b3700132000411b6a200a370000200041236a200f3b0000200041286a200e360200200041003a00272000412c6a200241900f6a41840210e8061a0c500b200541ff0171450d00200241003a00800d0b2000411b3602000c4e0b02402006450d0020042d0001210520012003417e6a3602042001200441026a360200200541034b0d00024002400240024020050e0400010203000b200241e00c6a2001109b0320022d00e00c4102460d03200241f40c6a290200210a200241ec0c6a290200210b200241fc0c6a2902002112200241e80c6a280200210420022802e40c210320022802e00c2105200241d8006a2001109c0320022802580d03200241e8006a290300211341012101200229036021160c4b0b200241e00c6a2001109b0320022d00e00c4102460d02200241f40c6a290200210a200241ec0c6a290200210b200241fc0c6a2902002112200241e80c6a280200210420022802e40c210320022802e00c210520024188016a2001109c03200229038801a70d0220024188016a41106a29030021132002290390012116200241f0006a2001109c032002290370a70d02200241f0006a41106a290300211720022903782118410221010c4a0b200241e00c6a2001109b0320022d00e00c4102460d01200241f40c6a290200210a200241ec0c6a290200210b200241fc0c6a2902002112200241e00c6a41086a2206280200210420022802e40c210320022802e00c2105200241e00c6a2001109b0320022d00e00c4102460d0120024190066a41206a2207200241e00c6a41206a28020036020020024190066a41186a2209200241e00c6a41186a29030037030020024190066a41106a2208200241e00c6a41106a29030037030020024190066a41086a2006290300370300200220022903e00c37039006200241a0016a2001109c0320022903a001a70d01200241a0016a41106a290300211920022903a801211a200929030021172008290300211820024198066a29030021132007350200211b2002290390062116410321010c490b200241e00c6a2001109b0320022d00e00c4102460d00200241f40c6a290200210a200241ec0c6a290200210b200241fc0c6a2902002112200241e80c6a280200210420022802e40c210320022802e00c2105200241b8016a2001109c0320022802b8010d00200241c8016a29030021134104210120022903c00121160c480b2000411b3602000c4d0b2006450d4020042d0001210520012003417e6a221c3602042001200441026a360200200541144b0d4041042110420021134100211d4100210d0240024002400240024002400240024002400240024002400240024002400240024002400240024020050e1500010259030405060708090a0b0c0d0e0f10111213000b200241e00c6a2001109b0320022d00e00c4102460d53200241fc0c6a2902002116200241f40c6a290200211b200241ec0c6a290200211a20022902e40c211920022802e00c2106200241d0016a2001109c0320022903d001a70d5320072802002204450d53200241e0016a290300210b20022903d801210a200128020022032d0000210e20012004417f6a360204410121102001200341016a360200200e41024b0d53201b4238882016420886842112201b4220882016422086842113201ba7220d418080807871211d2019422088a721082016422088a72115201a422088a721142019a72109201aa7210f0c580b200241e8016a2001109c0320022903e801a70d5220022903f001220a422088a72108200241f8016a290300220b422088a72114200aa72109200ba7210f410221100c560b20024180026a2001109c03200229038002a70d51200229038802220a422088a7210820024190026a290300220b422088a72114200aa72109200ba7210f410321104100210d0c560b20024198026a200110e6012002280298020d50200228029c02210641052110420021124100211d4100210d420021130c520b200241a0026a200110e60120022802a0020d4f20022802a4022208200728020041246e2204200420084b1b2209ad42247e220a422088a70d2b200aa72204417f4c0d2b0240024020040d00410421060c010b2004102d2206450d21200441246e21090b024002402008450d004122210541002107410021040340200241e00c6a2001109b0320022d00e00c220e4102460d02200441016a210320022d00e30c210f20022f00e10c211020022f01820d210d20022d00810d210c20022d00800d211120022802fc0c211520022802f80c211420022802f40c211d20022802f00c211c20022802ec0c211e20022f01ea0c211f20022d00e90c212020022d00e80c212120022802e40c2122024020042009470d0020072003200720034b1bad42247e220a422088a70d5e200aa722094100480d5e0240024020040d002009102d21060c010b20062005415e6a2009103121060b2006450d24200941246e21090b200620056a2204200d3b00002004415f6a220d2010200f41107472220f3b00002004417f6a200c3a00002004417e6a20113a00002004417a6a2015360000200441766a2014360000200441726a201d3600002004416e6a201c3600002004416a6a201e360000200441686a201f3b0000200441676a20203a0000200441666a20213a0000200441626a20223600002004415e6a200e3a0000200d41026a200f4110763a0000200741026a2107200541246a21052003210420082003470d000b0b2006450d50410621100c530b2009450d4f2006102f0c4f0b410721104100210d0c530b201c450d4d20042d0002210e20012003417d6a3602042001200441036a360200200e41034f0d4d41082110420021124100211d4100210d42002113410021144100210f410021080c520b200241e00c6a2001109b0320022d00e00c4102460d4c20024198096a200241fc0c6a28020036020020024190096a200241f40c6a290200220a370300200aa7220d418080807871211d2002290294092213421888211220022902e40c220a422088a72108200241ec0c6a290200220b422088a72114200241800d6a280200211520022802e00c2106200aa72109200ba7210f410921100c510b200241a8026a200110e60120022802a8020d4b20022802ac022106410a21100c4c0b410b21104100210d0c4f0b410c21104100210d0c4e0b200241e00c6a200110980320022802e00c2206450d4820022902e40c220a422088a72108200aa72109410d21100c4b0b41002105200241003a00800d2003417e6a21072003417d6a21030240034020072005460d01200241e00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00800d2003417f6a21032006210520064120470d000b200241980c6a2201200241ff0c6a2d00003a0000200241800c6a41106a200241f70c6a290000220a37030020022f01e00c20022d00e20c41107472220e411076210c200e4108762111200aa7220d418080807871211d20023502940c2001310000422086842213421888211220022900e70c220a422088a72108200241ef0c6a290000220b422088a7211420022800e30c2106200aa72109200ba7210f410e21100c4d0b200541ff0171450d47200241003a00800d0c470b410f21104100210d0c4b0b201c4104490d452004280002210620012003417a6a3602042001200441066a360200200241b0026a200110e60120022802b0020d45200728020020022802b40222034102742204490d452004417f4c0d210240024020040d00410121090c010b200410332209450d1720072802002004490d4520092001280200200410e8061a200128020422052004490d2a2001200520046b3602042001200128020020046a3602000b2009450d454100211d024002402004450d0020094103710d46200341ffffffff0371220f0d012009102f0b410421094100210f0b41000d452009450d4541102110420021124100210d42002113200f21080c4a0b201c4104490d442004280002210620012003417a6a3602042001200441066a360200200241b8026a200110e60120022802b8020d4420022802bc02220f200728020041246e22042004200f4b1b2208ad42247e220a422088a70d20200aa72204417f4c0d200240024020040d00410421090c010b2004102d2209450d16200441246e21080b0240200f450d00200241e00c6a410772211120024191096a21154100210d0340200241003a00800d200d220c41016a210d2007280200210e417f210341002104024002400240024002400340200e2004460d01200241e00c6a20046a200128020022102d00003a00002001200e20036a3602042001201041016a3602002002200441016a22053a00800d2003417f6a21032005210420054120470d000b20024180096a41086a201141086a29000037030020024180096a41106a201141106a29000037030020024180096a41186a201141186a2d00003a00002002201129000037038009200e20056b22044104490d0120022d00e20c210320022f01e00c210520022800e30c210e201028000121142001201041056a36020020012004417c6a3602042015290000210a200229008909210b200229038009211220022d00880921102008200c470d04200c4101742204200d2004200d4b1bad42247e2213422088a70d562013a722044100480d56200c0d022004102d21090c030b200441ff0171450d00200241003a00800d0b2008450d490c480b2009200c41246c2004103121090b2009450d18200441246e21080b2009200c41246c6a2204200520034110747222034180feff0771410876410874200341ff0171723b01002004200b37021020042014360220200420103a000f200420123700072004200e360003200441026a20034110763a0000200441186a200a370200200d200f470d000b0b2009450d4420022903c80c2213421888211220022802c40c220d418080807871211d411121100c490b201c4104490d432004280002210620012003417a6a3602042001200441066a360200411221100c440b200241c0026a2001109c0320022903c002a70d4220022903c802220a422088a72108200241d0026a290300220b422088a72114200aa72109200ba7210f411321100c460b200241d8026a200110e60120022802d8020d4120022802dc022106411421100c420b41002105200241003a00800d2003417e6a21072003417d6a21030240034020072005460d01200241e00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00800d2003417f6a21032006210520064120470d000b200241b80c6a2201200241ff0c6a2d00003a0000200241a00c6a41106a200241f70c6a290000220a37030020022f01e00c20022d00e20c41107472220e411076210c200e4108762111200aa7220d418080807871211d20023502b40c2001310000422086842213421888211220022900e70c220a422088a72108200241ef0c6a290000220b422088a7211420022800e30c2106200aa72109200ba7210f411521100c460b200541ff0171450d40200241003a00800d0c400b2006450d2620042d0001210520012003417e6a3602042001200441026a360200200541014b0d26410021040240024020050e020001000b200241e00c6a200110ee0220022d00e00c4101460d2720024190066a200241e00c6a41017241800110e8061a200241e0026a200110e60120022802e0020d27200728020020022802e4022203490d272003417f4c0d1c0240024020030d00410121040c010b200310332204450d1220072802002003490d2720042001280200200310e8061a200128020422052003490d262001200520036b3602042001200128020020036a3602000b2004450d272003ad220a422086200a84210a20024180096a20024190066a41800110e8061a0b20024180086a20024180096a41800110e8061a200041086a200a3702002000200436020420004108360200200041106a20024180086a41800110e8061a20004190016a200241900f6a41a00110e8061a0c4b0b02402006450d0020042d0001210520012003417e6a221f3602042001200441026a360200200541164b0d00410e21110240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020050e17000102030405060708090a0b0c540d0e0f101112131415000b41002105200241003a00800d2003417e6a21072003417d6a21030240034020072005460d01200241e00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00800d2003417f6a21032006210520064120470d000b20024180096a41086a200241ef0c6a290000220b37030020024198096a2204200241ff0c6a2d00003a000020024180096a41106a200241f70c6a290000221237030020022800e30c210920022900e70c211320022f01e00c210320022d00e20c21052004310000210a200228028c09210e20022f018a09210f20022d00890921102002350294092116200241e8026a2001109c0320022903e802a70d172016200a42208684210a2012a72115200ba72114200241e8026a41106a290300211220022903f002210b2003200541107472220641ffffff07712201410876210d2001411076211d2013422088a7211e2013a7211c410121110c540b200541ff0171450d16200241003a00800d0c160b20024180036a200110e6012002280280030d1520022802840321094100211e410221110c520b20024188036a200110e6012002280288030d1420072802002204450d14200228028c032109200128020022052d0000210320012004417f6a3602042001200541016a360200200341ff0071220d41064b0d14200341077621064100211e410321110c510b20024190036a200110e6012002280290030d1320072802002204450d132002280294032109200128020022052d0000210320012004417f6a3602042001200541016a360200200341ff0071220d41064b0d13200341077621064100211e410421110c500b201f4104490d122004280002210920012003417a6a3602042001200441066a3602004100211e410521110c4f0b41002105200241003a00800d2003417e6a21072003417d6a21030240034020072005460d01200241e00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00800d2003417f6a21032006210520064120470d000b20024198096a2201200241ff0c6a2d00003a000020024180096a41106a200241f70c6a290000220b37030020024180096a41086a200241ef0c6a290000221237030020022f01e00c20022d00e20c411074722206411076211d2006410876210d200235029409200131000042208684210a20022900e70c2213422088a7211e20022800e30c2109200228028c09210e20022f018a09210f20022d00890921102013a7211c200ba721152012a72114410621110c4f0b200541ff0171450d11200241003a00800d0c110b41002105200241003a00800d2003417e6a21072003417d6a21030240034020072005460d01200241e00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00800d2003417f6a21032006210520064120470d000b20024198096a2201200241ff0c6a2d00003a000020024180096a41106a200241f70c6a290000220b37030020024180096a41086a200241ef0c6a290000221237030020022f01e00c20022d00e20c411074722206411076211d2006410876210d200235029409200131000042208684210a20022900e70c2213422088a7211e20022800e30c2109200228028c09210e20022f018a09210f20022d00890921102013a7211c200ba721152012a72114410721110c4e0b200541ff0171450d10200241003a00800d0c100b41002105200241003a00800d2003417e6a21072003417d6a21030240034020072005460d01200241e00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00800d2003417f6a21032006210520064120470d000b20024198096a2201200241ff0c6a2d00003a000020024180096a41106a200241f70c6a290000220b3703004108211120024180096a41086a200241ef0c6a290000221237030020022f01e00c20022d00e20c411074722206411076211d2006410876210d200235029409200131000042208684210a20022900e70c2213422088a7211e20022800e30c2109200228028c09210e20022f018a09210f20022d00890921102013a7211c200ba721152012a721140c4d0b200541ff0171450d0f200241003a00800d0c0f0b41002105200241003a00800d2003417e6a2109417d21060240034020092005460d01200241e00c6a20056a200420056a220741026a2d00003a00002001200320066a3602042001200741036a3602002002200541016a22073a00800d2006417f6a21062007210520074120470d000b20024180096a41086a200241ef0c6a2900002212370300200320076b2203417e6a4104490d0f20022d00e20c210620022f01e00c2108200241f70c6a2900002113200241ff0c6a2d0000210e20022800e30c210920022900e70c2116200420076a220441026a280000210c20012003417a6a22053602042001200441066a220736020020054104490d0f20082006411074722206411076211d2006410876210d2007350000210b2001200341766a36020420012004410a6a3602002002200e3a009806200231009806210a2002201337039006200235029406200a42208684210a2016422088a7211e2012422088a7210e2012421088a7210f2012420888a721102016a7211c2013a721152012a7211442002112410921110c4c0b200541ff0171450d0e200241003a00800d0c0e0b41002105200241003a00800d2003417e6a21072003417d6a21030240034020072005460d01200241e00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00800d2003417f6a21032006210520064120470d000b20024190066a41086a2201200241ff0c6a2d00003a000020024180096a41086a200241ef0c6a290000220b3703002002200241f70c6a29000022123703900620022f01e00c20022d00e20c411074722206411076211d2006410876210d200235029406200131000042208684210a20022900e70c2213422088a7211e200b422088a7210e200b421088a7210f200b420888a7211020022800e30c21092013a7211c2012a72115200ba72114410a21110c4b0b200541ff0171450d0d200241003a00800d0c0d0b20024198036a200110e6012002280298030d0c200228029c0321094100211e410b21110c490b201f4104490d0b2004280002210920012003417a6a3602042001200441066a3602004100211e410c21110c480b41002105200241003a00800d2003417e6a21072003417d6a21030240034020072005460d01200241e00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00800d2003417f6a21032006210520064120470d000b20024198096a200241ff0c6a2d00003a000020024180096a41106a200241f70c6a29000037030020024180096a41086a200241ef0c6a290000220a370300200220022f01e00c22013b019006200220022800e30c220936009306200220022900e70c370097062002200a3c009f062002200120022d00e20c411074722206411076221d3a009206200229008909220b42388820024191096a290000220a42088684a721152006410876210d200a421888210a200b421888a7210e200b420888a7210f2002290097062212422088a7211e20022d009f062114200ba721102012a7211c410d21110c480b200541ff0171450d0a200241003a00800d0c0a0b41002105200241003a00800d2003417e6a21072003417d6a21030240034020072005460d01200241e00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00800d2003417f6a21032006210520064120470d000b200241a8066a2201200241ff0c6a2d00003a000020024190066a41106a200241f70c6a290000220b370300410f211120024190066a41086a2204200241e00c6a410f6a29000037030020022f01e00c20022d00e20c411074722206411076211d2006410876210d20023502a406200131000042208684210a20022900e70c2212422088a7211e20022800e30c210920042d00002114200228029c06210e20022f019a06210f20022d00990621102012a7211c200ba721150c470b200541ff0171450d09200241003a00800d0c090b41002105200241003a00800d2003417e6a21092003417d6a21060240034020092005460d01200241e00c6a20056a200420056a220741026a2d00003a0000200120063602042001200741036a3602002002200541016a22073a00800d2006417f6a21062007210520074120470d000b20024190066a410f6a200241e00c6a410f6a29000037000020024190066a41176a200241e00c6a41176a29000037000020024190066a411f6a200241e00c6a411f6a2d00003a0000200220022d00e20c22053a009206200220022f01e00c220e3b019006200220022800e30c220936009306200220022900e70c370097062003417e6a2007460d09200420076a220441026a2d00002108200120063602042001200441036a360200200841074f0d09200241800c6a41186a220420024190066a410772220141186a2d00003a000041102111200241800c6a41106a200141106a290000220b370300200241800c6a41086a200141086a29000022123703002002200129000022133703800c200e200541107472220641ffffff07712201411076211d2001410876210d20023502940c200431000042208684210a200ba721152012a7211420022802840c211e20022d00890c211020022f018a0c210f200228028c0c210e2013a7211c0c460b200541ff0171450d08200241003a00800d0c080b411121110c440b411221110c430b200241a0036a200110e60120022802a0030d05200728020020022802a4032204490d052004417f4c0d200240024020040d00410121090c010b200410332209450d1620072802002004490d0520092001280200200410e8061a200128020422032004490d2d2001200320046b3602042001200128020020046a3602000b2009450d052004ad220a422086200a84220a422088a7211e200aa7211c411321114100211d0c420b200241a8036a200110e60120022802a8030d04200728020020022802ac032204490d042004417f4c0d1f0240024020040d00410121090c010b200410332209450d1520072802002004490d0420092001280200200410e8061a200128020422032004490d2d2001200320046b3602042001200128020020046a3602000b2009450d042004ad220a422086200a84220a422088a7211e200aa7211c411421114100211d0c410b41002105200241003a00800d2003417e6a21072003417d6a21030240034020072005460d01200241e00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00800d2003417f6a21032006210520064120470d000b200241b80c6a2201200241ff0c6a2d00003a0000200241a00c6a41106a200241f70c6a290000220b370300200241a00c6a41086a2204200241ef0c6a29000037030020022f01e00c20022d00e20c411074722206411076211d2006410876210d20023502b40c200131000042208684210a20022900e70c2212422088a7211e20022800e30c210920042d0000211420022802ac0c210e20022f01aa0c210f20022d00a90c21102012a7211c200ba72115411521110c410b200541ff0171450d03200241003a00800d0c030b41002105200241003a00800d2003417e6a21072003417d6a21030240034020072005460d01200241e00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00800d2003417f6a21032006210520064120470d000b200241d80c6a2201200241ff0c6a2d00003a0000200241c00c6a41106a200241f70c6a290000220b370300200241c00c6a41086a2204200241ef0c6a29000037030020022f01e00c20022d00e20c411074722206411076211d2006410876210d20023502d40c200131000042208684210a20022900e70c2212422088a7211e20022800e30c210920042d0000211420022802cc0c210e20022f01ca0c210f20022d00c90c21102012a7211c200ba72115411621110c400b200541ff0171450d02200241003a00800d0c020b41002105200241003a00800d2003417e6a21072003417d6a21030240034020072005460d01200241e00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00800d2003417f6a21032006210520064120470d000b20024198096a200241ff0c6a2d00003a00004117211120024180096a41106a200241e00c6a41176a29000037030020024180096a41086a200241ef0c6a2900002212370300200229008909220b42388820024191096a290000220a42088684a7211520022f01e00c20022d00e20c411074722206411076211d2006410876210d200a421888210a20022900e70c2213422088a7211e200b421888a7210e200b420888a7210f20022800e30c21092013a7211c2012a72114200ba721100c3f0b200541ff0171450d01200241003a00800d0c010b2009102f0b2000411b3602000c4a0b200241e00c6a2001109d03024020022d00e00c4106460d0020024190066a41286a200241e00c6a41286a290300220a37030020024190066a41206a200241e00c6a41206a290300220b37030020024190066a41186a200241e00c6a41186a290300221237030020024190066a41106a200241e00c6a41106a290300221337030020024190066a41086a200241e00c6a41086a2903002216370300200220022903e00c221b370390062000410a3602002000201b3702042000410c6a2016370200200041146a20133702002000411c6a2012370200200041246a200b3702002000412c6a200a370200200041346a200241900f6a41fc0110e8061a0c4a0b2000411b3602000c490b200241e00c6a2001109d03024020022d00e00c4106460d0020024190066a41286a200241e00c6a41286a290300220a37030020024190066a41206a200241e00c6a41206a290300220b37030020024190066a41186a200241e00c6a41186a290300221237030020024190066a41106a200241e00c6a41106a290300221337030020024190066a41086a200241e00c6a41086a2903002216370300200220022903e00c221b370390062000410b3602002000201b3702042000410c6a2016370200200041146a20133702002000411c6a2012370200200041246a200b3702002000412c6a200a370200200041346a200241900f6a41fc0110e8061a0c490b2000411b3602000c480b2006450d3820042d0001210520012003417e6a360204410221032001200441026a360200200541054b0d3802400240024002400240024020050e06000501020304000b200241e00c6a200110980320022802e00c2204450d3d200241e80c6a280200210720022802e40c2106200241b0036a2001109c03024020022903b003a70d00200241c0036a290300211220022903b803210b410121030c050b2006450d3d2004102f0c3d0b200241e00c6a2001109b0320022d00e00c4102460d3c200241f40c6a2902002112200241ec0c6a290200210b200241fc0c6a290200210a200241e80c6a280200210720022802e40c210620022802e00c2104410321030c030b410421030c020b410521030c010b200241e00c6a2001109b0320022d00e00c4102460d39200241f40c6a2902002112200241ec0c6a290200210b200241fc0c6a290200210a200241e80c6a280200210720022802e40c210620022802e00c2104410621030b2000410c360200200041206a2012370200200041186a200b370200200041286a200a370200200041146a2007360200200041106a20063602002000410c6a2004360200200041086a2003360200200041306a200241900f6a41800210e8061a0c470b02402006450d0020042d0001210520012003417e6a3602042001200441026a360200200541064b0d004107210802400240024002400240024020050e070001020304053d000b41002105200241003a00800d2003417e6a21072003417d6a21030240034020072005460d01200241e00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00800d2003417f6a21032006210520064120470d000b20024198096a200241ff0c6a2d00003a000020024180096a41106a200241f70c6a29000037030020024188096a200241ef0c6a290000220a370300200220022d00e20c22013a009206200220022f01e00c22043b019006200220022800e30c220936009306200220022900e70c370097062002200a3c009f062004200141107472210720024191096a2900002112200229008909210b20022d009f06210f200229009706210a410121080c3d0b200541ff0171450d05200241003a00800d0c050b41002105200241003a00800d2003417e6a21072003417d6a21030240034020072005460d01200241e00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00800d2003417f6a21032006210520064120470d000b20024198066a2201200241ef0c6a29000037030020024190066a41106a200241f70c6a290000370300200241a8066a200241ff0c6a2d00003a000020022f01e00c20022d00e20c41107472210720022800e30c210920022900e70c210a200241a1066a290000211220012d0000210f200229009906210b410221080c3c0b200541ff0171450d04200241003a00800d0c040b41002105200241003a00800d410220036b21092003417d6a2106024002400340200920056a450d01200241e00c6a20056a200420056a220741026a2d00003a0000200120063602042001200741036a3602002002200541016a22073a00800d2006417f6a21062007210520074120470d000b200241a80c6a200241ef0c6a290000370300200241a00c6a41106a200241f70c6a290000370300200241b80c6a200241ff0c6a2d00003a0000200220022900e70c3703a00c20022800e30c210920022f01e00c210e20022d00e20c210f41002105200241003a00800d200420076a2108200720036b41026a2103200e200f4110747221070340200320056a450d02200241e00c6a20056a200820056a220441026a2d00003a0000200120063602042001200441036a3602002002200541016a22043a00800d2006417f6a21062004210520044120470d000b200241800c6a41086a2201200241ef0c6a290000370300200241800c6a41106a2204200241e00c6a41176a290000370300200241800c6a41186a2203200241e00c6a411f6a2d00003a0000200220022900e70c3703800c2002200936009306200220073b019006200220074110763a00920620022800e30c210e20022f01e00c210520022d00e20c210620024190066a411f6a200241a00c6a41186a2d00003a000020024190066a41176a200241a00c6a41106a2903003700002002200241a00c6a41086a29030037009f06200220022903a00c370097062005200641107472210620024190066a41186a290300211220032d0000211e2004280200211d2001280200211520022903a006210b20022802940c211c200228028c0c211420022802840c211120022f01820c210c20022d00810c210d20022d00800c211020022d009f06210f200229009706210a410321080c3c0b200541ff0171450d04200241003a00800d0c040b200541ff0171450d03200241003a00800d0c030b200241e00c6a200110980320022802e00c2209450d0220022f00910920024193096a2d000041107472210620022902e40c210a20024189096a2900002112200229008109210b41042108410021070c390b41002105200241003a00800d2003417e6a21072003417d6a21030240034020072005460d01200241e00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00800d2003417f6a21032006210520064120470d000b200241c80c6a2201200241ef0c6a290000370300200241c00c6a41106a200241f70c6a290000370300200241d80c6a200241ff0c6a2d00003a000020022f01e00c20022d00e20c41107472210720022800e30c210920022900e70c210a200241d10c6a290000211220012d0000210f20022900c90c210b410521080c390b200541ff0171450d01200241003a00800d0c010b41002105200241003a00800d2003417e6a21072003417d6a21030240034020072005460d01200241e00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00800d2003417f6a21032006210520064120470d000b20024198096a200241ff0c6a2d00003a000020024180096a41106a200241f70c6a29000037030020024188096a200241ef0c6a290000221337030020022f01e00c20022d00e20c41107472210720022800e30c210920022900e70c210a20024191096a2900002112200229008909210b2013a7210f410621080c380b200541ff0171450d00200241003a00800d0b2000411b3602000c460b02402006450d0020042d0001210520012003417e6a3602042001200441026a36020020050d00200241c8036a200110e60120022802c8030d0020022802cc0321012000410e36020020002001360204200041086a200241900f6a41a80210e8061a0c460b2000411b3602000c450b02402006450d0020042d0001210520012003417e6a3602042001200441026a36020020050d00200241d0036a200110e60120022802d0030d00200728020020022802d4032204490d002004417f4c0d1502400240024020040d00410121030c010b200410332203450d0c20072802002004490d0120032001280200200410e8061a200128020422052004490d252001200520046b3602042001200128020020046a3602000b2003450d01200020033602042000410f360200200041086a2004ad220a422086200a84370200200041106a200241900f6a41a00210e8061a0c460b2003102f0b2000411b3602000c440b2006450d3120042d0001210520012003417e6a3602042001200441026a360200200541074b0d3102400240024002400240024002400240024020050e080001020304050607000b200241d8036a2001109c0320022903d803a70d39200241e8036a290300210a20022903e003210b200241e00c6a2001109b0320022d00e00c4102460d3920024198096a200241fc0c6a28020036020020024190096a200241f40c6a29020037030020024188096a200241ec0c6a29020022123703002002200b3703800a2002200a3703880a20022902e40c2213422088a72105200241800d6a280200210420022802e00c210320024191096a290000210a20022f019a09210620022d0099092107200229008909210b2013a721092012a721084101210e0c3a0b200241f0036a200110e60120022802f0030d3820022802f4032103200241800a6a41106a200241e00c6a41106a290300370300200241800a6a41086a200241e00c6a41086a290300370300200220022903e00c3703800a410021054102210e0c390b200241f8036a200110e60120022802f8030d3720022802fc032103200241c90c6a290000210a20022900c10c210b20022f01d20c210620022d00d10c2107410021054103210e0c380b20024180046a200110e6012002280280040d3620072802002002280284042209490d362009417f4c0d1802400240024020090d00410121040c010b200910332204450d0f20072802002009490d0120042001280200200910e8061a200128020422032009490d292001200320096b3602042001200128020020096a3602000b2004450d3741002105200241003a00800d2007280200417f6a2103024003402003417f460d01200241e00c6a20056a200128020022062d00003a0000200120033602042001200641016a3602002002200541016a22063a00800d2003417f6a21032006210520064120470d000b20024198096a200241ff0c6a2d00003a000020024180096a41106a200241f70c6a29000037030020024180096a41086a200241ef0c6a290000220a370300200220022f01e00c22013b019006200220022800e30c220336009306200220022900e70c370097062002200a3c009f062002200120022d00e20c411074722201411076220f3a00920620024191096a290000210a200229008909210b20022d009f0621082002290097062112200220093602840a200220093602800a200141087621102012422088a721052012a721094104210e0c390b0240200541ff0171450d00200241003a00800d0b2009450d370b2004102f0c360b41002105200241003a00800d2003417e6a21072003417d6a21030240034020072005460d01200241e00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00800d2003417f6a21032006210520064120470d000b20024190066a41086a2201200241ef0c6a29000037030020024190066a41106a200241f70c6a290000370300200241a8066a200241ff0c6a2d00003a0000200220022900e70c22123703900620022800e30c210320022f01e00c210420022d00e20c2105200241a1066a290000210a20012d00002108200229009906210b200241800a6a41106a20024180086a41106a290000370300200241800a6a41086a20024180086a41086a29000037030020022002290080083703800a20042005411074722201411076210f200141087621102012422088a721052012a721094105210e0c370b200541ff0171450d35200241003a00800d0c350b20024188046a200110e6012002280288040d342007280200200228028c042208490d342008417f4c0d160240024020080d00410121040c010b200810332204450d0c20072802002008490d3420042001280200200810e8061a200128020422032008490d272001200320086b3602042001200128020020086a3602000b2004450d3441002103200241003a00800d20072802002107417f21050240034020072003460d01200241e00c6a20036a200128020022092d00003a00002001200720056a3602042001200941016a3602002002200341016a22063a00800d2005417f6a21052006210320064120470d000b20024190066a410f6a200241e00c6a410f6a29000037000020024190066a41176a200241e00c6a41176a29000037000020024190066a411f6a200241e00c6a411f6a2d00003a0000200220022d00e20c22053a009206200220022f01e00c220e3b019006200220022800e30c220336009306200220022900e70c37009706200720066b22064110490d03200941096a290000210a2009290001210b2001200641706a3602042001200941116a360200200241800c6a41186a20024190066a410772220141186a2d00003a0000200241800c6a41106a200141106a290000370300200241800c6a41086a200141086a2900002212370300200241800a6a41106a200a3703002002200129000022133703800c200220083602840a200220083602800a2002200b3703880a200e200541107472220141ffffff07712205411076210f200541087621102012a72108200241800c6a41116a290000210a20022802840c210520022900890c210b2013a721094106210e0c360b0240200341ff0171450d00200241003a00800d0b2008450d340c330b41002105200241003a00800d2003417e6a2109417d21060240034020092005460d01200241e00c6a20056a200420056a220741026a2d00003a00002001200320066a3602042001200741036a3602002002200541016a22073a00800d2006417f6a21062007210520074120470d000b200241c00c6a41086a2205200241ef0c6a290000370300200241c00c6a41106a2206200241f70c6a290000370300200241c00c6a41186a2209200241ff0c6a2d00003a0000200220022900e70c3703c00c200320076b2208417e6a4110490d3420022d00e20c210e20022f01e00c210f20022800e30c2103200420076a220441026a290000210a2004410a6a290000210b20012008416e6a3602042001200441126a360200200241a00c6a41186a20092d00003a0000200241a00c6a41106a2006290300370300200241a00c6a41086a200529030022123703002002200b3703880a2002200a3703800a200f200e41107472220141ffffff07712204411076210f2004410876211020022903c00c2213422088a72105200241b10c6a290000210a20022900a90c210b2013a721092012a721084107210e410021060c350b200541ff0171450d33200241003a00800d0c330b41002105200241003a00800d2003417e6a21072003417d6a21030240034020072005460d01200241e00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00800d2003417f6a21032006210520064120470d000b20024198096a200241ff0c6a2d00003a000020024180096a41106a200241f70c6a2900003703004108210e20024180096a41086a200241ef0c6a2900002212370300200241800a6a41086a20024190066a41086a290000370300200241800a6a41106a20024190066a41106a29000037030020022002290090063703800a20022f01e00c20022d00e20c411074722201411076210f2001410876211020022900e70c2213422088a7210520022800e30c210320024191096a290000210a200229008909210b2013a721092012a721080c340b200541ff0171450d32200241003a00800d0c320b20080d300c310b2006450d2d20042d0001210520012003417e6a3602042001200441026a360200200541044b0d2d02400240024002400240024020050e050001020304000b200241e00c6a200110910220022d00d80d4102460d32200241d80b6a41086a200241e00c6a41186a2d00003a000020024180086a41086a2002418c0d6a29020037030020024190086a200241940d6a29020037030020024180086a41186a2002419c0d6a280200360200200220022903f00c3703d80b200220022902840d3703800820022903e80c210a20022903e00c211220022d00f90c210620022f01fa0c210e20022802fc0c210420022802800d210520022902c40d220b42ffffffff0f832113200b428080808070832116200241d80d6a290300211b20022903d00d211a20022802cc0d210320022802c00d210720022802bc0d210820022f01ba0d210f20022d00b90d211020022d00b80d210d20022903b00d211920022903a80d211820022903a00d210b4101210c0c330b20024198046a2001109903200229039804a70d3120022903a004210a20024190046a200110e6012002280290040d3120072802002002280294042204490d312004417f4c0d160240024020040d00410121090c010b200410332209450d0c20072802002004490d2920092001280200200410e8061a200128020422032004490d282001200320046b3602042001200128020020046a3602000b2009450d312004ad220b422086200b842112200241d80b6a41086a20024190066a41086a2d00003a000020024180086a41086a200241e00c6a41086a29020037030020024180086a41106a200241e00c6a41106a29020037030020024180086a41186a200241e00c6a41186a28020036020020022002290390063703d80b200220022902e00c370380084102210c42002113420021160c320b200241e00c6a2001109b0320022d00e00c4102460d3020024198066a200241ec0c6a29020037030020024190066a41106a200241f40c6a290200370300200241a8066a200241fc0c6a280200360200200220022902e40c37039006200241800d6a280200210420022802e00c2109200241c0046a2001109c0320022903c004a70d30200241c0046a41106a290300210a20022903c8042112200241b0046a200110990320022903b004a70d3020022903b804210b200241a8046a200110e60120022802a8040d30200728020020022802ac042203490d302003417f4c0d150240024020030d00410121050c010b200310332205450d0b20072802002003490d0320052001280200200310e8061a200128020422062003490d292001200620036b3602042001200128020020036a3602000b2005450d3020024180096a41186a20024190066a41186a280200220136020020024194086a200a370200200241d80b6a41086a20013a00002002201237028c0820022003ad220a422086200a84370380082002200241a0066a2903003703d80b20024190066a41086a290300210a200229039006211220022d00c80c210d20022d00c90c211020022f01ca0c210f20022802d00c210720022802cc0c210820022d009909210620022f019a09210e4103210c4200211341002111420021160c310b200241f0046a2001109c0320022903f004a70d2f20024180056a290300210a20022903f804210b200241e0046a200110990320022903e004a70d2f20022903e804211241002103200241003a00800d2007280200417f6a2104024002400240024003402004417f460d01200241e00c6a20036a200128020022052d00003a0000200120043602042001200541016a3602002002200341016a22053a00800d2004417f6a21042005210320054120470d000b200241880c6a200241ef0c6a290000370300200241800c6a41106a200241f70c6a290000370300200241980c6a200241ff0c6a2d00003a0000200220022900e70c3703800c20022800e30c210920022f01e00c210320022d00e20c2106200241d8046a200110e60120022802d8040d33200728020020022802dc042205490d332005417f4c0d1820050d014101210441010d020c330b200341ff0171450d32200241003a00800d0c320b200510332204450d0b20072802002005490d0120042001280200200510e8062107200128020422082005490d2a2001200820056b3602042001200128020020056a3602002007450d310b2002418c086a200a370200200241d80b6a41086a200241980c6a2d00003a00002002200b37028408200220123702940820022005360280082002200241900c6a2903003703d80b200320064110747222014180feff07714108762111200241800c6a41086a290300210a20022903800c21124104210c42002113420021160c310b2004102f0c2f0b41002105200241003a00800d2003417e6a21092003417d6a21060240024002400240034020092005460d01200241e00c6a20056a200420056a220741026a2d00003a0000200120063602042001200741036a3602002002200541016a22073a00800d2006417f6a21062007210520074120470d000b200241a80c6a200241ef0c6a290000370300200241a00c6a41106a200241f70c6a290000370300200241b80c6a200241ff0c6a2d00003a0000200220022900e70c3703a00c2003417e6a2007460d3220022d00e20c210f20022f01e00c211020022800e30c2109200420076a220841026a2d00002104200120063602042001200841036a360200200441014b0d324100210620040e020201020b200541ff0171450d31200241003a00800d0c310b41002104200241003a00800d200720036b41036a2106200320076b417c6a21030340200620046a450d02200241e00c6a20046a200820046a220541036a2d00003a0000200120033602042001200541046a3602002002200441016a22053a00800d2003417f6a21032005210420054120470d000b20024180096a41186a200241ff0c6a2d00003a000020024180096a41106a200241f70c6a29000037030020024188096a200241ef0c6a290000220a370300200241850c6a20022800e30c22014110763a0000200220013b00830c200220022d00e20c22043a00820c200220022f01e00c22033b01800c20024191096a2900002113200229008909210b200220022900e70c3700c10c200220014118763a00c00c2003200441107472210e200aa7210d4101210620022802c00c21050b200241af066a2203200241b80c6a2d00003a0000200220022802c40c360280082002200241c00c6a41086a2d00003a00840820022010200f4110747222013b0190062002200936009306200220022903a00c37009706200220014110763a0092062002200241a00c6a41086a29030037009f062002200241a00c6a41106a2903003700a70620022801820c2104200229009f06210a2002290097062112200241d80b6a41086a20032d00003a0000200220022900a7063703d80b2002418e086a20133701002002200b370186082002200d3a00850820014180feff077141087621114105210c42002113420021160c300b200441ff0171450d2e200241003a00800d0c2e0b2005102f0c2d0b200241e00c6a2001109e03024020022802e00c4104460d0020024190066a41286a200241e00c6a41286a280200220136020020024190066a41206a200241e00c6a41206a290300220a37030020024190066a41186a200241e00c6a41186a290300220b37030020024190066a41106a200241e00c6a41106a290300221237030020024190066a41086a200241e00c6a41086a2903002213370300200220022903e00c22163703900620004112360200200020163702042000410c6a2013370200200041146a20123702002000411c6a200b370200200041246a200a3702002000412c6a2001360200200041306a200241900f6a41800210e8061a0c420b2000411b3602000c410b02402006450d0020042d0001210520012003417e6a22063602042001200441026a36020020050d0020064104490d002004280002210520012003417a6a3602042001200441066a36020020024198056a200110e6012002280298050d002007280200200228029c052204490d002004417f4c0d11024002400240024002400240024020040d004101210e0c010b20041033220e450d0c20072802002004490d01200e2001280200200410e8061a200128020422032004490d2c2001200320046b3602042001200128020020046a3602000b200e450d052004ad220a422086200a84210b20024190056a200110e601024002402002280290050d00200228029405220c2007280200410c6e22042004200c4b1b220dad420c7e220a422088a70d18200aa72204417f4c0d180240024020040d004104210f0c010b2004102d220f450d0e2004410c6e210d0b024002400240200c450d00410021084100210341002109034020024188056a200110e6012002280288050d032007280200200228028c052204490d032004417f4c0d1c0240024020040d00410121100c010b200410332210450d1220072802002004490d0320102001280200200410e8061a200128020422062004490d332001200620046b3602042001200128020020046a3602000b200941016a210602402009200d470d0020082006200820064b1bad420c7e220a422088a70d4c200aa7220d4100480d4c0240024020090d00200d102d210f0c010b200f2003200d1031210f0b200f450d12200d410c6e210d0b200f20036a22092010360200200941046a2004ad220a422086200a84370200200841026a21082003410c6a210320062109200c2006470d000b0b200ba72103200f450d03200728020022064104490d0520012802002209280000211020012006417c6a22043602042001200941046a36020020044104490d06200b422088a72111200928000421152001200641786a22083602042001200941086a36020041002104200241003a00a00d200641776a2106034020082004460d08200241e00c6a20046a200920046a220741086a2d00003a0000200120063602042001200741096a3602002002200441016a22073a00a00d2006417f6a210620072104200741c000470d000b200e450d09200241e00c6a41386a290300210a200241e00c6a41086a290300210b20022903900d211220022903e00c2113200228028c0d210120022902840d211620022802800d210420022802fc0c210620022f01fa0c210720022d00f80c210920022903f00c211b200020022d00f90c3a00412000200536020420004113360200200041e0006a200a370200200041d8006a2012370200200041306a200b370200200041286a2013370200200041d4006a2001360200200041cc006a2016370200200041c8006a2004360200200041c4006a2006360200200041c2006a20073b0100200041c0006a20093a0000200041386a201b370200200041246a2015360200200041206a20103602002000411c6a200c360200200041186a200d360200200041146a200f360200200041106a20113602002000410c6a2003360200200041086a200e360200200041e8006a200241900f6a41c80110e8061a0c4a0b2010102f0b02402009450d00200f210103400240200141046a280200450d002001280200102f0b2001410c6a2101200341746a22030d000b0b200d450d00200f102f0b200ba721030b2003450d050b200e102f0c040b02402003450d00200e102f0b0240200c450d00200c410c6c2104200f210103400240200141046a280200450d002001280200102f0b2001410c6a2101200441746a22040d000b0b200d0d020c030b02402003450d00200e102f0b0240200c450d00200c410c6c2104200f210103400240200141046a280200450d002001280200102f0b2001410c6a2101200441746a22040d000b0b200d0d010c020b0240200441ff0171450d00200241003a00a00d0b02402003450d00200e102f0b0240200c450d00200c410c6c2104200f210103400240200141046a280200450d002001280200102f0b2001410c6a2101200441746a22040d000b0b200d450d010b200f102f0b2000411b3602000c400b02402006450d0020012003417e6a3602042001200441026a3602000b2000411b3602000c3f0b02402006450d0020012003417e6a3602042001200441026a3602000b2000411b3602000c3e0b02402006450d0020012003417e6a3602042001200441026a3602000b2000411b3602000c3d0b2006450d2620042d0001210520012003417e6a22233602042001200441026a3602002005410a4b0d26410421244200211802400240024002400240024002400240024002400240024020050e0b0001020b03040506070809000b41002105200241003a00b00f2003417e6a21072003417d6a21030240034020072005460d01200241900f6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00b00f2003417f6a21032006210520064120470d000b200241800c6a41086a2002419f0f6a290000220b370300200241800c6a41106a200241a70f6a2900002213370300200241980c6a2201200241af0f6a2d00003a0000200220022900970f22123703800c20022800930f210620022f01900f210420022d00920f21032001310000210a200228028c0c211420023502940c2116200241f00b6a41086a200241800a6a41086a290000370300200220022900800a3703f00b200241d80b6a41106a200241e00c6a41106a290000370300200241d80b6a41086a200241e00c6a41086a290000370300200220022900e00c3703d80b200241c00b6a41106a20024190066a41106a290000370300200241c00b6a41086a20024190066a41086a29000037030020022002290090063703c00b200241a80b6a41106a20024180096a41106a290000370300200241a80b6a41086a20024180096a41086a29000037030020022002290080093703a80b200241900b6a41106a20024180086a41106a290000370300200241900b6a41086a20024180086a41086a29000037030020022002290080083703900b2004200341107472210e2016200a42208684210a2012422088a72108200b4280feffff0f83420888a721252012a721092013a72111200ba7210d410121244100211d0c0b0b200541ff0171450d31200241003a00b00f0c310b200241a0056a200110e60120022802a0050d3020022802a4052208200728020041c8006e2204200420084b1b2209ad42c8007e220a422088a70d16200aa72204417f4c0d160240024020040d00410421060c010b2004102d2206450d0c200441c8006e21090b02402008450d00200241e00c6a410c6a210e4100210f41002105410021040340200241e00c6a200110a9010240024020022d00e00c22104106460d0020024180096a41086a2211200e41086a29020037030020024180096a41106a2215200e41106a2902003703002002200e2902003703800920022802e80c210d20022802e40c210c20022f01e20c211420022d00e10c211d200241900f6a200110a90120022d00900f4106470d0120104101470d00200d450d00200c102f0b02402004450d00200620056a2104200621010340024020012d00004101470d00200141086a280200450d00200141046a280200102f0b0240200141246a2d00004101470d002001412c6a280200450d00200141286a280200102f0b2004200141c8006a2201470d000b0b2009450d330c320b200441016a210320024180086a41106a221c201529030037030020024180086a41086a2215201129030037030020024190066a41086a2211200241900f6a41086a29030037030020024190066a41106a221e200241900f6a41106a29030037030020024190066a41186a221f200241900f6a41186a29030037030020024190066a41206a2220200241900f6a41206a280200360200200220022903800937038008200220022903900f37039006024020042009470d00200f2003200f20034b1bad42c8007e220a422088a70d48200aa722094100480d480240024020040d002009102d21060c010b200620052009103121060b2006450d0e200941c8006e21090b200620056a220420103a0000200441086a200d360200200441046a200c360200200441026a20143b0000200441016a201d3a00002004410c6a200229038008370200200441146a20152903003702002004411c6a201c290300370200200441246a2002290390063702002004412c6a2011290300370200200441346a201e2903003702002004413c6a201f290300370200200441c4006a2020280200360200200f41026a210f200541c8006a21052003210420082003470d000b0b2006450d30200241900f6a200110a90102400240024002400240024002400240024020022d00900f220d4106460d00200241b00f6a280200210c200241a80f6a290300210b200241a40f6a220428020021102002419c0f6a2203290200210a200241900f6a41086a2205280200211120022802940f211420022f00910f210e20022d00930f210f200241900f6a200110a90120022d00900f221d4106460d01200241800a6a41086a200241ac0f6a221f290200370300200220042902003703800a200329020021122005280200211c20022802940f211520023100930f211820023100920f211720023100910f2126200241900f6a200110a90120022d00900f221e4106460d0220024180086a41086a200241a40f6a220429020037030020024180086a41106a201f29020037030020022002419c0f6a220329020037038008200241900f6a41086a2205280200211f20022802940f212020022d00930f212720022d00920f212820022d00910f2122200241900f6a200110a90120022d00900f22214106460d0320024180096a41086a200429020037030020024180096a41106a200241ac0f6a220429020037030020022003290200370380092005280200212920022802940f212a20022f01920f212b20022d00910f212c200241900f6a200110a90120022d00900f222d4106460d0620024190066a41086a200241a40f6a290200370300200241a0066a200429020037030020022002419c0f6a29020037039006200241900f6a41086a280200212e20022802940f212f20072802002204450d0720022d00930f213020022d00920f213120022d00910f2132200128020022032d0000210520012004417f6a22073602042001200341016a360200200541014b0d07420021134100212441002123420021164100213320050e020504050b02402008450d002006200841c8006c6a2104200621010340024020012d00004101470d00200141086a280200450d00200141046a280200102f0b0240200141246a2d00004101470d002001412c6a280200450d00200141286a280200102f0b200141c8006a22012004470d000b0b20090d370c380b0240200d4101470d002011450d002014102f0b02402008450d002006200841c8006c6a2104200621010340024020012d00004101470d00200141086a280200450d00200141046a280200102f0b0240200141246a2d00004101470d002001412c6a280200450d00200141286a280200102f0b200141c8006a22012004470d000b0b20090d360c370b0240201d4101470d00201c450d002015102f0b0240200d4101470d002011450d002014102f0b02402008450d002006200841c8006c6a2104200621010340024020012d00004101470d00200141086a280200450d00200141046a280200102f0b0240200141246a2d00004101470d002001412c6a280200450d00200141286a280200102f0b200141c8006a22012004470d000b0b20090d350c360b0240201e4101470d00201f450d002020102f0b0240201d4101470d00201c450d002015102f0b0240200d4101470d002011450d002014102f0b02402008450d002006200841c8006c6a2104200621010340024020012d00004101470d00200141086a280200450d00200141046a280200102f0b0240200141246a2d00004101470d002001412c6a280200450d00200141286a280200102f0b200141c8006a22012004470d000b0b20090d340c350b2007450d0220032d0001212420012004417e6a22053602042001200341026a3602002005450d0220032d0002210720012004417d6a22053602042001200341036a3602002005450d0220032d0003213420012004417c6a22053602042001200341046a3602002005450d0220032d0004213320012004417b6a22053602042001200341056a3602002005450d0220032d0005213520012004417a6a22053602042001200341066a3602002005450d0220032d000621362001200441796a22053602042001200341076a3602002005450d0220032d000721372001200441786a22053602042001200341086a3602002005450d0220032d000821382001200441776a22053602042001200341096a3602002005450d0220032d000921392001200441766a220536020420012003410a6a3602002005450d0220032d000a213a2001200441756a220536020420012003410b6a3602002005450d0220032d000b213b2001200441746a220536020420012003410c6a3602002005450d0220032d000c213c2001200441736a220536020420012003410d6a3602002005450d0220032d000d213d2001200441726a220536020420012003410e6a3602002005450d0220032d000e21252001200441716a220536020420012003410f6a3602002005450d0220032d000f213e2001200441706a22053602042001200341106a3602002005450d0220032d0010213f20012004416f6a22053602042001200341116a3602002005450d0220032d0011214020012004416e6a22053602042001200341126a3602002005450d0220032d0012214120012004416d6a22053602042001200341136a3602002005450d0220032d0013214220012004416c6a22053602042001200341146a3602002005450d022003310014211320012004416b6a3602042001200341156a3602002002203341187420344110747220074108747222232024723602900f2002203cad423886203bad42ff018342308684203aad42ff0183422886842039ad42ff0183422086842038ad42ff01834218868422162037ad42ff0183421086842036ad42ff0183420886842035ad42ff0183843702940f201642188820134238862042ad42ff0183423086842041ad42ff0183422886842040ad42ff018342208684203fad42ff018342188684203ead42ff0183421086842025ad42ff018342088684203dad42ff01838422164228868421132016421888211620022800930f2134410121330b200241900f6a200110a90120022d00900f22354106460d02200241e00c6a41086a2204200241a40f6a2203290200370300200241e00c6a41106a2205200241ac0f6a220729020037030020022002419c0f6a2902003703e00c200241900f6a41086a223b280200213620022802940f213720022d00930f213a20022d00920f213920022d00910f2138200241900f6a200110a90120022d00900f4106470d0b024020354101470d002036450d002037102f0b0240202d4101470d00202e450d00202f102f0b024020214101470d002029450d00202a102f0b0240201e4101470d00201f450d002020102f0b0240201d4101470d00201c450d002015102f0b0240200d4101470d002011450d002014102f0b02402008450d002006200841c8006c6a2104200621010340024020012d00004101470d00200141086a280200450d00200141046a280200102f0b0240200141246a2d00004101470d002001412c6a280200450d00200141286a280200102f0b200141c8006a22012004470d000b0b20090d320c330b024020214101470d002029450d00202a102f0b0240201e4101470d00201f450d002020102f0b0240201d4101470d00201c450d002015102f0b0240200d4101470d002011450d002014102f0b02402008450d002006200841c8006c6a2104200621010340024020012d00004101470d00200141086a280200450d00200141046a280200102f0b0240200141246a2d00004101470d002001412c6a280200450d00200141286a280200102f0b200141c8006a22012004470d000b0b20090d310c320b0240202d4101470d00202e450d00202f102f0b024020214101470d002029450d00202a102f0b0240201e4101470d00201f450d002020102f0b0240201d4101470d00201c450d002015102f0b0240200d4101470d002011450d002014102f0b02402008450d002006200841c8006c6a2104200621010340024020012d00004101470d00200141086a280200450d00200141046a280200102f0b0240200141246a2d00004101470d002001412c6a280200450d00200141286a280200102f0b200141c8006a22012004470d000b0b20090d300c310b0240202d4101470d00202e450d00202f102f0b024020214101470d002029450d00202a102f0b0240201e4101470d00201f450d002020102f0b0240201d4101470d00201c450d002015102f0b0240200d4101470d002011450d002014102f0b02402008450d002006200841c8006c6a2104200621010340024020012d00004101470d00200141086a280200450d00200141046a280200102f0b0240200141246a2d00004101470d002001412c6a280200450d00200141286a280200102f0b200141c8006a22012004470d000b0b20090d2f0c300b200241a8056a200110e60120022802a8050d2f20022802ac05220e200728020041c4006e22042004200e4b1b2210ad42c4007e220a422088a70d15200aa72204417f4c0d150240024020040d00410421060c010b2004102d2206450d0b200441c4006e21100b0240200e450d00200241900f6a410772210d20024191096a210c41002109410021080340200241003a00b00f2008220f41016a21082007280200417f6a2104410021030240024002400240024003402004417f460d01200241900f6a20036a200128020022052d00003a0000200120043602042001200541016a3602002002200341016a22053a00b00f2004417f6a21042005210320054120470d000b20024180096a41086a200d41086a29000037030020024180096a41106a200d41106a29000037030020024180096a41186a200d41186a2d00003a00002002200d2900003703800920022800930f210520022f01900f210320022d00920f2111200241900f6a200110a90120022d00900f22154106460d0120022d00930f211420022f00910f211d200c290000210a200229008909210b20022f01b20f211c20022d00b10f211e20022d00b00f211f20022802ac0f212020022802a80f212120022802a40f212220022802a00f2128200228029c0f212720022f019a0f212920022d00990f212a20022d00980f212d20022802940f212c20022d008809212b20022903800921122010200f470d04200f41017422042008200420084b1bad42c4007e2213422088a70d4b2013a722044100480d4b200f0d022004102d21060c030b200341ff0171450d00200241003a00b00f0b0240200f450d00200641286a210103400240200141786a2d00004101470d002001280200450d002001417c6a280200102f0b200141c4006a2101200941bc7f6a22090d000b0b20100d330c340b2006200f41c4006c2004103121060b2006450d0d200441c4006e21100b2006200f41c4006c6a2204201d201441107472220f3b00212004200320114110747222034180feff0771410876410874200341ff0171723b01002004200b3702102004201c3b00422004201e3a00412004201f3a00402004202036003c2004202136003820042022360034200420283600302004202736002c200420293b002a2004202a3a00292004202d3a00282004202c360024200420153a00202004202b3a000f2004201237000720042005360003200441236a200f4110763a0000200441026a20034110763a0000200441186a200a370200200941c4006a21092008200e470d000b0b2006450d2f200241f00b6a41086a200241c00c6a41086a290300370300200241d80b6a41086a200241e00c6a41086a290200370300200241d80b6a41106a200241e00c6a41106a290200370300200241c00b6a41086a20024190066a41086a290300370300200241c00b6a41106a20024190066a41106a290300370300200241a80b6a41106a20024180086a41106a290200370300200241a80b6a41086a20024180086a41086a290200370300200220022903c00c3703f00b200220022902e00c3703d80b20022002290390063703c00b20022002290280083703a80b200241900b6a41106a200241800a6a41106a290300370300200241900b6a41086a200241800a6a41086a290300370300200220022903800a3703900b200ead4220862010ad84220a422088a72108200aa72109410321244100210e4100211d0c080b200241c8056a200110e60120022802c8050d2e20022802cc052106200241b0056a2001109c0320022903b005a70d2e200241b0056a41106a290300210a20022903b805210b200241f00b6a41086a20024180086a41086a290300370300200241d80b6a41086a200241900f6a41086a290200370300200241d80b6a41106a200241900f6a41106a290200370300200241c00b6a41086a200241e00c6a41086a290300370300200241c00b6a41106a200241e00c6a41106a290300370300200241a80b6a41106a20024190066a41106a290200370300200241a80b6a41086a20024190066a41086a29020037030020022002290380083703f00b200220022902900f3703d80b200220022903e00c3703c00b20022002290290063703a80b200241900b6a41106a20024180096a41106a290300370300200241900b6a41086a20024180096a41086a29030037030020022002290380093703900b200b422088a72108200a422088a72114200a4280feffff0f83420888a72125200ba72109200aa7210d410521244100211d0c070b20234104490d2d2004280002210620012003417a6a360204410621242001200441066a360200200241f00b6a41086a20024180086a41086a290300370300200241d80b6a41086a200241900f6a41086a290200370300200241d80b6a41106a200241900f6a41106a290200370300200241c00b6a41086a200241e00c6a41086a290300370300200241c00b6a41106a200241e00c6a41106a29030037030020022002290380083703f00b200220022902900f3703d80b200220022903e00c3703c00b200241a80b6a41106a20024190066a41106a290200370300200241a80b6a41086a20024190066a41086a290200370300200241900b6a41086a20024180096a41086a290300370300200241900b6a41106a20024180096a41106a29030037030020022002290290063703a80b20022002290380093703900b41002108410021254100210d4100211d0c060b200241e8056a200110e60120022802e8050d2c20022802ec052106200241d0056a2001109c0320022903d005a70d2c200241d0056a41106a290300210a20022903d805210b200241f00b6a41086a20024180086a41086a290300370300200241d80b6a41086a200241900f6a41086a290200370300200241d80b6a41106a200241900f6a41106a290200370300200241c00b6a41086a200241e00c6a41086a290300370300200241c00b6a41106a200241e00c6a41106a290300370300200241a80b6a41106a20024190066a41106a290200370300200241a80b6a41086a20024190066a41086a29020037030020022002290380083703f00b200220022902900f3703d80b200220022903e00c3703c00b20022002290290063703a80b200241900b6a41106a20024180096a41106a290300370300200241900b6a41086a20024180096a41086a29030037030020022002290380093703900b200b422088a72108200a422088a72114200a4280feffff0f83420888a72125200ba72109200aa7210d410721244100211d0c050b200241f0056a200110e60120022802f0050d2b20022802f405211041002103200241003a00b00f2007280200417f6a2104024003402004417f460d01200241900f6a20036a200128020022052d00003a0000200120043602042001200541016a3602002002200341016a22053a00b00f2004417f6a21042005210320054120470d000b20024190066a410f6a2201200241900f6a410f6a29000037000020024190066a411f6a2204200241900f6a411f6a2d00003a0000200220022d00920f22033a009206200220022f01900f22053b019006200220022800930f220636009306200220022900970f370097062002200241a70f6a2900003700a7062001350000210b2004310000210a4108212420022800a706211120022800a3062114200229009706211220023500ab062113200241f00b6a41086a200241800c6a41086a290300370300200220022903800c3703f00b200241d80b6a41106a200241e00c6a41106a290200370300200241d80b6a41086a200241e00c6a41086a290200370300200220022902e00c3703d80b200241c00b6a41106a20024180096a41106a290300370300200241c00b6a41086a20024180096a41086a29030037030020022002290380093703c00b200241a80b6a41106a20024180086a41106a290200370300200241a80b6a41086a20024180086a41086a29020037030020022002290280083703a80b200241900b6a41106a200241800a6a41106a290300370300200241900b6a41086a200241800a6a41086a290300370300200220022903800a3703900b2005200341107472210e2013200a42208684210a200b420888a721252012422088a72108200ba7210d2012a721094100211d0c050b200341ff0171450d2b200241003a00b00f0c2b0b200241f8056a200110e60120022802f8050d2a200728020022044108490d2a20022802fc05210620012802002203290000210a2001200441786a3602042001200341086a360200200a4280025a0d2a200241f00b6a41086a20024180086a41086a290300370300200241d80b6a41086a200241900f6a41086a290200370300200241d80b6a41106a200241900f6a41106a290200370300200241c00b6a41086a200241e00c6a41086a290300370300200241c00b6a41106a200241e00c6a41106a290300370300200241a80b6a41106a20024190066a41106a290200370300200241a80b6a41086a20024190066a41086a29020037030020022002290380083703f00b200220022902900f3703d80b200220022903e00c3703c00b20022002290290063703a80b200241900b6a41106a20024180096a41106a290300370300200241900b6a41086a20024180096a41086a29030037030020022002290380093703900b200a422088a72108200aa72109410921244100211d0c030b20024180066a200110e6012002280280060d292002280284062106200241900f6a2001109b0320022d00900f4102460d29200241800a6a41086a200241900f6a41086a290300370300200220022903900f3703800a20072802002203450d29200241ac0f6a2902002113200241a40f6a290200210a200241a00f6a2802002111200128020022052d0000210420012003417f6a22073602042001200541016a360200200441064b0d29420021124100211c4100210c0240024002400240024002400240024020040e0707000501020304070b20074110490d30200541096a29000021122005290001210b20012003416f6a3602042001200541116a360200200b422088a7211c200ba721154101210c0c060b4103210c0c040b4104210c0c030b4105210c0c020b4106210c0c010b4102210c0b0b200241c00c6a41086a200241800a6a41086a2903002216370300200241f00b6a41086a200241a00c6a41086a290300370300200241d80b6a41086a200241e00c6a41086a290200370300200241d80b6a41106a200241e00c6a41106a290200370300200241c00b6a41086a20024190066a41086a290300370300200241c00b6a41106a20024190066a41106a290300370300200220022903800a221b3703c00c200220022903a00c3703f00b200220022902e00c3703d80b20022002290390063703c00b20022802cc0c2114200241a80b6a41106a20024180096a41106a290200370300200241a80b6a41086a20024180096a41086a290200370300200241900b6a41106a20024180086a41106a290300370300200241900b6a41086a20024180086a41086a29030037030020022002290280093703a80b20022002290380083703900b2013422088210b201b422088a7210820164280feffff0f83420888a72125201ba721092013a721102016a7210d410a21244100211d420021180c020b200241900f6a2001109b0320022d00900f4102460d2820024198096a200241ac0f6a28020036020020024180096a41106a200241a40f6a290200221337030020024180096a41086a2002419c0f6a290200220b370300200241f00b6a41086a200241c00c6a41086a290300370300200220022902940f221237038009200220022903c00c3703f00b200241b00f6a280200211020022802900f2106200229029409210a200228028c092114200241d80b6a41106a200241e00c6a41106a290200370300200241d80b6a41086a200241e00c6a41086a290200370300200220022902e00c3703d80b200241c00b6a41106a20024190066a41106a290300370300200241c00b6a41086a20024190066a41086a29030037030020022002290390063703c00b200241a80b6a41106a20024180086a41106a290200370300200241a80b6a41086a20024180086a41086a29020037030020022002290280083703a80b200241900b6a41106a200241800a6a41106a290300370300200241900b6a41086a200241800a6a41086a290300370300200220022903800a3703900b2012422088a72108200b4280feffff0f83420888a721252012a721092013a72111200ba7210d410b21244100210e4100211d0c010b200e200f411074722125200241f00b6a41086a200241800a6a41086a290300370300200241d80b6a41086a20024180086a41086a290300370300200241d80b6a41106a20024180086a41106a290300370300200241c00b6a41106a20024180096a41106a290300370300200241c00b6a41086a20024180096a41086a290300370300200220022903800a3703f00b20022002290380083703d80b20022002290380093703c00b200729020021192003290200211a200241900f6a41106a280200213d203b290300211b20022802940f213c20022802900f213b200241a80b6a41106a20024190066a41106a290300370300200241a80b6a41086a20024190066a41086a290300370300200241900b6a41086a2004290300370300200241900b6a41106a200529030037030020022002290390063703a80b200220022903e00c3703900b201842108620174208868420268421182023202472210f410221240b200241800b6a41086a2201200241f00b6a41086a290300370300200241e80a6a41086a2204200241d80b6a41086a290300370300200241e80a6a41106a2203200241d80b6a41106a290300370300200241d00a6a41086a2205200241c00b6a41086a290300370300200241d00a6a41106a2207200241c00b6a41106a290300370300200241b80a6a41106a2223200241a80b6a41106a290300370300200241b80a6a41086a223e200241a80b6a41086a290300370300200220022903f00b3703800b200220022903d80b3703e80a200220022903c00b3703d00a200220022903a80b3703b80a200241a00a6a41106a223f200241900b6a41106a290300370300200241a00a6a41086a2240200241900b6a41086a290300370300200220022903900b3703a00a2000410b6a200e4110763a00002000200e3b0009200041186a2025410874ad200dad42ff0183843e0200200041106a2008ad4220862009ad84370200200041c8006a2012370200200041c4006a201c360200200041c0006a2015360200200041386a2018422886201dad42ff018342208684200cad84370200200041306a200b3702002000412c6a2010360200200041246a200a370200200041206a20113602002000411c6a20143602002000410c6a2006360200200041086a20243a000020004117360200200041e8006a201f360200200041e4006a2020360200200020273a0063200020283a0062200020223a0061200041e0006a201e3a0000200041d0006a20022903800b370200200041d8006a2001290300370200200041fc006a2003290300370200200041f4006a2004290300370200200041ec006a20022903e80a3702002000418c016a202936020020004188016a202a3602002000202b3b0086012000202c3a00850120004184016a20213a0000200041a0016a200729030037020020004198016a200529030037020020004190016a20022903d00a370200200041b0016a202e360200200041ac016a202f360200200020303a00ab01200020313a00aa01200020323a00a901200041a8016a202d3a0000200041c4016a2023290300370200200041bc016a203e290300370200200041b4016a20022903b80a370200200041d4016a2036360200200041d0016a20373602002000203a3a00cf01200020393a00ce01200020383a00cd01200041cc016a20353a0000200041e8016a203f290300370200200041e0016a2040290300370200200041d8016a20022903a00a37020020004197026a200f4110763a00002000200f3b009502200041a4026a20163700002000419c026a20133700002000418c026a201937020020004184026a201a37020020004198026a203436000020004194026a20333a000020004180026a203d360200200041f8016a201b370200200041f4016a203c360200200041f0016a203b3602000c3c0b2006450d0820042d0001210520012003417e6a221d3602042001200441026a3602002005410b4b0d084107210f024002400240024002400240024020050e0c0001020304050d0608090a0b000b201d4110490d0e2004410a6a290000210a2004290002210b20012003416e6a3602042001200441126a3602004101210f420021120c0c0b201d4104490d0d2004280002210820012003417a6a3602042001200441066a3602004102210f0c0b0b41002105200241003a00800d2003417e6a2109417d21060240034020092005460d01200241e00c6a20056a200420056a220741026a2d00003a00002001200320066a3602042001200741036a3602002002200541016a22073a00800d2006417f6a21062007210520074120470d000b20024180096a41086a200241ef0c6a290000220a37030020024190066a41086a200241ff0c6a2d00003a00002002200241f70c6a29000037039006200320076b2203417e6a4110490d0d20022d00e20c210620022f01e00c210920022800e30c210820022900e70c210b200420076a2204410e6a280000210d200441066a2900002112200441026a280000211020012003416e6a22053602042001200441126a220736020020054110490d0d200920064110747222064110762114200641087621152004411a6a290000211b2007290000211620012003415e6a3602042001200441226a360200200229039006211320022d009806210c4103210f410021110c0b0b200541ff0171450d0c200241003a00800d0c0c0b4104210f201d4104490d0b2004280002210820012003417a6a3602042001200441066a3602000c090b200241e00c6a2001109b0320022d00e00c4102460d0a20072802002203450d0a200241ec0c6a290200210a200241800d6a280200210e200241fe0c6a2f01002111200241fd0c6a2d00002109200241fc0c6a2d0000210c200241f40c6a290200211320022902e40c210b20022802e00c2108200128020022052d0000210420012003417f6a3602042001200541016a360200200441014b0d0a410021060240024020040e020100010b410121060b200228029c06210d200229029406211220022802900621104105210f0c080b201d450d0920042d0002210520012003417d6a3602042001200441036a360200200541014b0d094200210b4106210f410021064200210a20050e020706070b41002105200241003a00800d2003417e6a2108417d2106024002400240034020082005460d01200241e00c6a20056a200420056a220941026a2d00003a00002001200320066a3602042001200941036a3602002002200541016a22093a00800d2006417f6a21062009210520094120470d000b200241880c6a200241ef0c6a290000370300200241800c6a41106a200241f70c6a290000370300200241980c6a200241ff0c6a2d00003a0000200220022900e70c3703800c200320096b2203417e6a4104490d0b20022d00e20c210520022f01e00c210620022800e30c2108200420096a220441026a280000210e20012003417a6a3602042001200441066a36020020024188066a200110e6012002280288060d0b2007280200200228028c062204490d0b2004417f4c0d0e20040d01410121100c020b200541ff0171450d0a200241003a00800d0c0a0b200410332210450d0120072802002004490d0820102001280200200410e8061a200128020422032004490d232001200320046b3602042001200128020020046a3602000b2010450d082004ad220a422086200a84211220024190066a41186a200241800c6a41186a2d0000220c3a00002006200541107472220641ffffff0771220141107621144108210f20014108762115200241800c6a41106a2903002113200241800c6a41086a290300210a20022903800c210b0c060b1036000b4109210f0c040b41002105200241003a00800d2003417e6a21092003417d6a2106024002400240034020092005460d01200241e00c6a20056a200420056a220741026a2d00003a0000200120063602042001200741036a3602002002200541016a22073a00800d2006417f6a21062007210520074120470d000b200241a80c6a200241ef0c6a290000370300200241a00c6a41106a200241f70c6a290000370300200241b80c6a200241ff0c6a2d00003a0000200220022900e70c3703a00c2003417e6a2007460d0820022d00e20c210520022f01e00c210920022800e30c2108200420076a220341026a2d00002104200120063602042001200341036a360200200441014b0d08200920054110747221064100210920040e020201020b200541ff0171450d07200241003a00800d0c070b410121090b200220063b0190062002200836009306200220064110763a009206200641ffffff07712201411076211420014108762115200241a00c6a41086a290300210a200241a00c6a41106a2903002113200241b80c6a2d0000210c20022903a00c210b410a210f0c030b41002105200241003a00800d2003417e6a21092003417d6a21060240034020092005460d01200241e00c6a20056a200420056a220741026a2d00003a0000200120063602042001200741036a3602002002200541016a22073a00800d2006417f6a21062007210520074120470d000b20024198096a200241ff0c6a2d00003a000020024180096a41106a200241f70c6a29000037030020024180096a41086a200241ef0c6a290000220a3703002003417e6a2007460d0520022d00e20c210320022f01e00c210520022800e30c210820022900e70c210b20024191096a29000021122002290089092113200420076a220441026a2d00002109200120063602042001200441036a360200200941034f0d052005200341107472220641087621152002200aa73a00c80c200220133700c90c20134238882012420886842113200641107621142012423888a7210c20022903c80c210a410b210f410021110c030b200541ff0171450d04200241003a00800d0c040b201d4104490d032004280002210820012003417a6a3602042001200441066a3602004200210b410c210f410021144200210a0c010b4200210b410121064200210a0b200020113b012a200020093a0029200020143a000b200020153a000a200020063a000920004118360200200041c8006a201b370200200041c0006a2016370200200041186a200a370200200041106a200b3702002000413c6a200d360200200041346a2012370200200041306a20103602002000412c6a200e360200200041286a200c3a0000200041206a20133702002000410c6a2008360200200041086a200f3a0000200041d0006a200241900f6a41e00110e8061a0c340b2010102f0b2000411b3602000c320b200241e00c6a2001109f03024020022d00e00c410a460d0020024190066a200241e00c6a41c40010e8061a20004119360200200041046a20024190066a41c40010e8061a200041c8006a200241900f6a41e80110e8061a0c320b2000411b3602000c310b02402006450d0020042d0001210520012003417e6a3602042001200441026a360200200541024b0d004101210402400240024020050e03020001020b200241e00c6a2001109b034102210420022d00e00c4102460d02200241f40c6a2902002112200241ec0c6a290200210b200241fc0c6a290200210a200241e80c6a280200210320022802e40c210620022802e00c21090c010b200241e00c6a2001109b0320022d00e00c4102460d01200728020022054110490d01200241f40c6a2902002112200241ec0c6a290200210b200241fc0c6a290200210a200241e00c6a41086a280200210320022802e40c210620022802e00c21092001280200220441086a2900002116200429000021132001200441106a3602002001200541706a220736020420074110490d01200441186a290000211a2004290010211b2001200541606a22073602042001200441206a36020020074104490d012004280020210820012005415c6a3602042001200441246a360200410321040b2000411a360200200041c8006a201a370200200041c0006a201b370200200041386a2016370200200041306a2013370200200041206a2012370200200041186a200b370200200041d0006a2008360200200041286a200a370200200041146a2003360200200041106a20063602002000410c6a2009360200200041086a2004360200200041d8006a200241900f6a41d80110e8061a0c310b2000411b3602000c300b103d000b20042003104b000b20042003104b000b20042003104b000b20032005104b000b20052009104b000b20042005104b000b20042003104b000b20042005104b000b20032005104b000b2004102f0b2000411b3602000c240b20042003104b000b20042003104b000b20042005104b000b20092003104b000b20082003104b000b20042003104b000b2009102f0c080b20032006104b000b20052008104b000b20042003104b000b20042006104b000b20042003104b000b2000411b3602000c170b2006102f0b2000411b3602000c150b2000411b3602000c140b200241c00b6a41086a2215200241d80b6a41086a2d00003a0000200241800a6a41086a221420024180086a41086a290300370300200241800a6a41106a221d20024180086a41106a290300370300200241800a6a41186a221c20024180086a41186a280200360200200220022903d80b3703c00b20022002290380083703800a200041186a200a370200200041106a20123702002000410c6a2009360200200020113b000a200020013a0009200041086a200c3a000020004111360200200041306a20053602002000412c6a20043602002000412a6a200e3b0100200020063a0029200041206a20022903c00b370200200041286a20152d00003a0000200041346a20022903800a3702002000413c6a2014290300370200200041c4006a201d290300370200200041cc006a201c28020036020020004188016a201b37020020004180016a201a370200200041fc006a2003360200200041f4006a2016201384370200200041f0006a2007360200200041ec006a2008360200200041ea006a200f3b0100200020103a0069200041e8006a200d3a0000200041e0006a2019370200200041d8006a2018370200200041d0006a200b37020020004190016a200241900f6a41a00110e8061a0c130b2004102f0b2000411b3602000c110b200241d80b6a41106a220d200241800a6a41106a290300370300200241d80b6a41086a220c200241800a6a41086a290300370300200220022903800a3703d80b200041216a200a370000200041196a200b3700002000412c6a20043602002000412a6a20063b0100200020073a0029200041186a20083a0000200041106a2005ad4220862009ad843702002000410c6a20033602002000200f3a000b200020103a000a200020013a0009200041086a200e3a000020004110360200200041306a20022903d80b370200200041386a200c290300370200200041c0006a200d290300370200200041c8006a200241900f6a41e80110e8061a0c100b200020063b0025200020073b00052000200b370015200041003b0046200041003a00452000200d3a002d200020083a00042000410d360200200041276a20064110763a0000200041076a20074110763a00002000411d6a2012370000200041c4006a201e3a0000200041c0006a201c3600002000413c6a201d360000200041386a2014360000200041346a2015360000200041306a20113600002000412e6a200c3b00002000412c6a20103a0000200041286a200e360000200041146a200f3a00002000410c6a200a370000200041086a2009360000200041c8006a200241900f6a41e80110e8061a0c0f0b2000411b3602000c0e0b200041003b012a200020083a0029200020103a00192000201d3a000b2000200d3a000a200020063a000920004109360200200041286a200a4220883c0000200041246a200a3e0200200041386a2012370200200041306a200b3702002000412c6a200c360200200041206a20153602002000411c6a200e3602002000411a6a200f3b0100200041186a20143a00002000410c6a2009360200200041086a20113a0000200041106a201ead422086201cad84370200200041c0006a200241900f6a41f00110e8061a0c0d0b2009102f0b2000411b3602000c0b0b4100211d420021124100210d420021134100210c0b410021144100210f41002108410021090c020b420021124100211d4100210d420021134100210f0c010b420021124100210d420021130b2000200c3a000b200020113a000a2000200e3a000920004107360200200041386a200b370200200041306a200a3702002000412c6a20153602002000410c6a2006360200200041086a20103a0000200041246a2012421886201342ffffff078384370200200041206a201d200d41ffffff077172360200200041186a2014ad422086200fad84370200200041106a2008ad4220862009ad84370200200041c0006a200241900f6a41f00110e8061a0c060b20004106360200200041e0006a2019370200200041d8006a201a370200200041c8006a2017370200200041c0006a2018370200200041386a2013370200200041306a2016370200200041206a200a370200200041186a200b370200200041d0006a201b370200200041286a2012370200200041146a2004360200200041106a20033602002000410c6a2005360200200041086a2001360200200041e8006a200241900f6a41c80110e8061a0c050b2004102f0b2000411b3602000c030b2006102f0b2000411b3602000c010b1038000b200241c0116a24000bce0201057f230041d0006b22022400024002404104102d2203450d00200341edde91e306360000410c210420034104410c10312205450d0020052001290000370004200241003a004820052106410021030340200241003a0008200241086a20062004410047220110e8061a024020040d00200241003a00080b20042001490d02200241286a20036a20022d00083a00002002200341016a22033a0048200420016b2104200620016a210620034120470d000b200241086a41186a2204200241286a41186a290300370300200241086a41106a2203200241286a41106a290300370300200241086a41086a2201200241286a41086a290300370300200220022903283703082005102f200041186a2004290300370000200041106a2003290300370000200041086a200129030037000020002002290308370000200241d0006a24000f0b1036000b20012004104b000bbf0908017f037e037f017e017f017e047f037e230041e0016b22032400200320023703582003200137035002400240200120028450450d0042002104420021050c010b2003200036021c200341206a2000200341d0006a2003411c6a108f02024020032903204201510d00200341c8006a2903002105200341c0006a290300210420032903284201520d01200341206a41106a290300210620034198016a200341206a41186a29030037030020034190016a2006370300200341e0006a41086a41003a0000200341e9006a2000290000370000200341f1006a200041086a290000370000200341f9006a200041106a29000037000020034181016a200041186a290000370000200341033a006041c8e1ca004100200341e0006a108c010c010b200341306a2903002105200329032821040b200341e0006a41186a22074200370300200341e0006a41106a22084200370300200341e0006a41086a220942003703002003420037036041e7a2ca00ad4280808080800184220a1001220b2900002106200341d0006a41086a2200200b41086a29000037030020032006370350200b102f200920002903003703002003200329035037036041ecb5c600ad4280808080d00184220c1001220b29000021062000200b41086a29000037030020032006370350200b102f200820032903502206370300200341206a41086a220d2009290300370300200341206a41106a220e2006370300200341206a41186a220f2000290300370300200320032903603703202003200341206a4120109c01200220057d2001200454ad7d200520027d2004200154ad7d200420015820052002582005200251220b1b22101b2111200120047d200420017d20101b2112200341106a2903004200200328020022101b21062003290308420020101b21130240024020042001562005200256200b1b0d0020074200370300200842003703002009420037030020034200370360200a1001220b29000021012000200b41086a29000037030020032001370350200b102f2009200029030037030020032003290350370360200c1001220b29000021012000200b41086a29000037030020032001370350200b102f20082003290350370000200841086a2000290300370000200d2009290300370300200e2008290300370300200f20072903003703002003200329036037032020034200200620117d2013201254ad7d2201201320127d2202201356200120065620012006511b22001b37036820034200200220001b370360200341e0006a21000c010b20074200370300200842003703002009420037030020034200370360200a1001220b29000021012000200b41086a29000037030020032001370350200b102f2009200029030037030020032003290350370360200c1001220b29000021012000200b41086a29000037030020032001370350200b102f20082003290350370000200841086a2000290300370000200d2009290300370300200e2008290300370300200f2007290300370300200320032903603703202003427f200620117c201320127c22022013542200ad7c22012000200120065420012006511b22001b3703682003427f200220001b370360200341e0006a21000b200341206aad42808080808004842000ad42808080808002841004200341e0016a24000bbe0303027f037e027f230041c0006b22022400419298ca00ad4280808080900184100122032900002104200241086a200341086a290000370300200220043703002003102f418a93c200ad4280808080b00184100122032900002104200241106a41086a200341086a290000370300200220043703102003102f02404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100322012900002104200141086a2900002105200141106a2900002106200241206a41186a2207200141186a290000370300200241206a41106a22082006370300200241206a41086a2005370300200220043703202001102f2003102f41c000102d2203450d00200320022903003700002003200229031037001020032002290320370020200042c0808080800837020420002003360200200341086a200241086a290300370000200341186a200241106a41086a290300370000200341286a200241206a41086a290300370000200341306a2008290300370000200341386a2007290300370000200241c0006a24000f0b1036000b130020004117360204200041cca8c2003602000bf50905027f017e027f027e057f230041b0016b22022400419298ca00ad4280808080900184100122032900002104200241c0006a41086a2205200341086a290000370300200220043703402003102f41ce97c200ad4280808080800284100122032900002104200241e8006a41086a2206200341086a290000370300200220043703682003102f20022001360208200241086aad4280808080c00084100322032900002104200341086a2900002107200341106a290000210820024188016a41186a2201200341186a29000037030020024188016a41106a2209200837030020024188016a41086a220a200737030020022004370388012003102f024041c000102d220b450d00200b2002290340370000200b2002290368370010200b200229038801370020200b41086a2005290300370000200b41186a2006290300370000200b41286a200a290300370000200b41306a2009290300370000200b41386a2001290300370000200241c00036022c2002200b360228200241306a200bad42808080808008841002107302400240200228023022050d00410321030c010b2002280234210a02400240200241386a280200220c4104490d002005280000210941002103200241003a00a801200c417c6a21060240034020062003460d0120024188016a20036a200520036a41046a2d00003a00002002200341016a22013a00a8012001210320014120470d000b200241e8006a41186a20024188016a41186a290300370300200241e8006a41106a20024188016a41106a290300370300200241e8006a41086a20024188016a41086a2903003703002002200229038801370368200c417c6a2001460d01200520016a220641046a2d0000220341034f0d01200c20016b417b6a4104490d01200241c0006a41086a200241e8006a41086a2903002204370300200241c0006a41106a200241e8006a41106a2903002207370300200241c0006a41186a200241e8006a41186a29030022083703002002413c6a41026a220c200241e4006a41026a220d2d00003a0000200241086a41086a2004370300200241086a41106a2007370300200241086a41186a2008370300200220022903682204370340200220022f00643b013c20022004370308200641056a2800002101200d200c2d00003a0000200220022f013c3b01640c020b200341ff0171450d00200241003a00a8010b20024100360270200242013703682002410b3602442002200241286a3602402002200241e8006a3602082002419c016a41013602002002420137028c01200241b885c700360288012002200241c0006a36029801200241086a41d8dbc10020024188016a103c1a200235027042208620023502688410080240200228026c450d002002280268102f0b410321030b200a450d002005102f0b20024188016a41086a2205200241086a41086a29030037030020024188016a41106a2206200241086a41106a29030037030020024188016a41186a220a200241086a41186a290300370300200241e8006a41026a220c200241e4006a41026a2d00003a00002002200229030837038801200220022f01643b0168024020034103460d0020002001360204200020093602002000200229038801370208200020022f01683b0029200041106a2005290300370200200041186a2006290300370200200041206a200a2903003702002000412b6a200c2d00003a00000b200020033a0028200b102f200241b0016a24000f0b1036000b34002000419298ca0036020420004100360200200041146a4111360200200041106a4190efc200360200200041086a42093702000ba80101057f230041206b22022400200241186a22034200370300200241106a22044200370300200241086a220542003703002002420037030002404120102d2206450d0020062002290300370000200641186a2003290300370000200641106a2004290300370000200641086a20052903003700002006412041c00010312206450d00200042c0808080900437020420002006360200200641003a0020200241206a24000f0b1036000b4d01027f230041106b2202240002404104102d22030d001036000b2002420437020420022003360200410020021069200041086a200228020836020020002002290300370200200241106a24000b130020004107360204200041a490c3003602000b2e01017f02404104102d22020d001036000b20004284808080c00037020420002002360200200241809c313600000b2e01017f02404104102d22020d001036000b20004284808080c0003702042000200236020020024180a3053600000b3a01017f02404110102d22020d001036000b20024200370008200242808084fea6dee111370000200042908080808002370204200020023602000b2e01017f02404104102d22020d001036000b20004284808080c0003702042000200236020020024180de343600000bde4201057f230041106b2202240002400240024020002d0000417f6a220341164b0d000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020030e17000102030405060708090a0b0c0d0e0f10111213141516000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d19200341017422052004200520044b1b22054100480d190240024020030d002005102d21040c010b200128020020032005103121040b2004450d1820012004360200200141046a2005360200200141086a28020021030b200141086a2206200341016a360200200420036a41003a00004120102d2203450d1720032000290001370000200341186a200041196a290000370000200341106a200041116a290000370000200341086a200041096a29000037000002400240200141046a2802002205200628020022046b4120490d00200128020021050c010b200441206a22062004490d19200541017422042006200420064b1b22044100480d190240024020050d002004102d21050c010b200128020020052004103121050b2005450d1820012005360200200141046a2004360200200141086a28020021040b200141086a200441206a360200200520046a220441186a200341186a290000370000200441106a200341106a290000370000200441086a200341086a290000370000200420032900003700002003102f2002200041286a360208200241086a200110c2020c160b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d18200341017422052004200520044b1b22054100480d180240024020030d002005102d21040c010b200128020020032005103121040b2004450d1720012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a0000200041046a20011095020c150b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d17200341017422052004200520044b1b22054100480d170240024020030d002005102d21040c010b200128020020032005103121040b2004450d1620012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a0000200041046a200110950220002d00012104200041026a2d0000210602400240200141046a28020020052802002200460d00200128020021030c010b200041016a22032000490d17200041017422052003200520034b1b22054100480d170240024020000d002005102d21030c010b200128020020002005103121030b2003450d1620012003360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200320006a20044100474107742006723a00000c140b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d16200341017422052004200520044b1b22054100480d160240024020030d002005102d21040c010b200128020020032005103121040b2004450d1520012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a0000200041046a200110950220002d00012104200041026a2d0000210602400240200141046a28020020052802002200460d00200128020021030c010b200041016a22032000490d16200041017422052003200520034b1b22054100480d160240024020000d002005102d21030c010b200128020020002005103121030b2003450d1520012003360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200320006a20044100474107742006723a00000c130b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d15200341017422052004200520044b1b22054100480d150240024020030d002005102d21040c010b200128020020032005103121040b2004450d1420012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a00002000280204210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d15200341017422002005200020054b1b22004100480d150240024020030d002000102d21030c010b200128020020032000103121030b2003450d1420012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c120b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d14200341017422052004200520044b1b22054100480d140240024020030d002005102d21040c010b200128020020032005103121040b2004450d1320012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41053a00004120102d2203450d1220032000290001370000200341186a200041196a290000370000200341106a200041116a290000370000200341086a200041096a29000037000002400240200141046a2802002204200528020022006b4120490d00200128020021040c010b200041206a22052000490d14200441017422002005200020054b1b22004100480d140240024020040d002000102d21040c010b200128020020042000103121040b2004450d1320012004360200200141046a2000360200200141086a28020021000b200141086a200041206a360200200420006a220141186a200341186a290000370000200141106a200341106a290000370000200141086a200341086a290000370000200120032900003700002003102f0c110b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d13200341017422052004200520044b1b22054100480d130240024020030d002005102d21040c010b200128020020032005103121040b2004450d1220012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41063a00004120102d2203450d1120032000290001370000200341186a200041196a290000370000200341106a200041116a290000370000200341086a200041096a29000037000002400240200141046a2802002204200528020022006b4120490d00200128020021040c010b200041206a22052000490d13200441017422002005200020054b1b22004100480d130240024020040d002000102d21040c010b200128020020042000103121040b2004450d1220012004360200200141046a2000360200200141086a28020021000b200141086a200041206a360200200420006a220141186a200341186a290000370000200141106a200341106a290000370000200141086a200341086a290000370000200120032900003700002003102f0c100b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d12200341017422052004200520044b1b22054100480d120240024020030d002005102d21040c010b200128020020032005103121040b2004450d1120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41073a00004120102d2203450d1020032000290001370000200341186a200041196a290000370000200341106a200041116a290000370000200341086a200041096a29000037000002400240200141046a2802002204200528020022006b4120490d00200128020021040c010b200041206a22052000490d12200441017422002005200020054b1b22004100480d120240024020040d002000102d21040c010b200128020020042000103121040b2004450d1120012004360200200141046a2000360200200141086a28020021000b200141086a200041206a360200200420006a220141186a200341186a290000370000200141106a200341106a290000370000200141086a200341086a290000370000200120032900003700002003102f0c0f0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d11200341017422052004200520044b1b22054100480d110240024020030d002005102d21040c010b200128020020032005103121040b2004450d1020012004360200200141046a2005360200200141086a28020021030b200141086a2206200341016a360200200420036a41083a00004120102d2203450d0f20032000290001370000200341186a200041196a290000370000200341106a200041116a290000370000200341086a200041096a29000037000002400240200141046a2802002205200628020022046b4120490d00200128020021050c010b200441206a22062004490d11200541017422042006200420064b1b22044100480d110240024020050d002004102d21050c010b200128020020052004103121050b2005450d1020012005360200200141046a2004360200200141086a28020021040b200141086a2206200441206a360200200520046a220441186a200341186a290000370000200441106a200341106a290000370000200441086a200341086a290000370000200420032900003700002003102f2000280224210502400240200141046a2802002204200628020022036b4104490d00200128020021040c010b200341046a22062003490d11200441017422032006200320064b1b22034100480d110240024020040d002003102d21040c010b200128020020042003103121040b2004450d1020012004360200200141046a2003360200200141086a28020021030b200141086a2206200341046a360200200420036a20053600002000280228210402400240200141046a2802002203200628020022006b4104490d00200128020021030c010b200041046a22052000490d11200341017422002005200020054b1b22004100480d110240024020030d002000102d21030c010b200128020020032000103121030b2003450d1020012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c0e0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d10200341017422052004200520044b1b22054100480d100240024020030d002005102d21040c010b200128020020032005103121040b2004450d0f20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41093a00004120102d2203450d0e20032000290001370000200341186a200041196a290000370000200341106a200041116a290000370000200341086a200041096a29000037000002400240200141046a2802002204200528020022006b4120490d00200128020021040c010b200041206a22052000490d10200441017422002005200020054b1b22004100480d100240024020040d002000102d21040c010b200128020020042000103121040b2004450d0f20012004360200200141046a2000360200200141086a28020021000b200141086a200041206a360200200420006a220141186a200341186a290000370000200141106a200341106a290000370000200141086a200341086a290000370000200120032900003700002003102f0c0d0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0f200341017422052004200520044b1b22054100480d0f0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0e20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410a3a0000200041046a20011095020c0c0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0e200341017422052004200520044b1b22054100480d0e0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410b3a00002000280204210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d0e200341017422002005200020054b1b22004100480d0e0240024020030d002000102d21030c010b200128020020032000103121030b2003450d0d20012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c0b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0d200341017422052004200520044b1b22054100480d0d0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0c20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410c3a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d0d200441017422032005200320054b1b22034100480d0d0240024020040d002003102d21040c010b200128020020042003103121040b2004450d0c20012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041196a290000370000200141106a200041116a290000370000200141086a200041096a290000370000200120002900013700000c0a0b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d0c200041017422042003200420034b1b22044100480d0c0240024020000d002004102d21030c010b200128020020002004103121030b2003450d0b20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a410d3a00000c090b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0b200341017422052004200520044b1b22054100480d0b0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0a20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410e3a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d0b200441017422032005200320054b1b22034100480d0b0240024020040d002003102d21040c010b200128020020042003103121040b2004450d0a20012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041196a290000370000200141106a200041116a290000370000200141086a200041096a290000370000200120002900013700000c080b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0a200341017422052004200520044b1b22054100480d0a0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0920012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410f3a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d0a200441017422032005200320054b1b22034100480d0a0240024020040d002003102d21040c010b200128020020042003103121040b2004450d0920012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220341186a200041196a290000370000200341106a200041116a290000370000200341086a200041096a2900003700002003200029000137000020002d0021220041064b0d070240024002400240024002400240024020000e0700010203040506000b410021040c060b410121040c050b410221040c040b410321040c030b410421040c020b410521040c010b410621040b200220043a000f02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d0a200041017422052003200520034b1b22054100480d0a0240024020000d002005102d21030c010b200128020020002005103121030b2003450d0920012003360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200320006a20043a00000c070b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d09200041017422042003200420034b1b22044100480d090240024020000d002004102d21030c010b200128020020002004103121030b2003450d0820012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41103a00000c060b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d08200041017422042003200420034b1b22044100480d080240024020000d002004102d21030c010b200128020020002004103121030b2003450d0720012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41113a00000c050b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d07200341017422052004200520044b1b22054100480d070240024020030d002005102d21040c010b200128020020032005103121040b2004450d0620012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41123a0000200028020421062000410c6a28020022002001106902400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d07200441017422032005200320054b1b22034100480d070240024020040d002003102d21040c010b200128020020042003103121040b2004450d0620012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010e8061a0c040b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d06200341017422052004200520044b1b22054100480d060240024020030d002005102d21040c010b200128020020032005103121040b2004450d0520012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41133a0000200028020421062000410c6a28020022002001106902400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d06200441017422032005200320054b1b22034100480d060240024020040d002003102d21040c010b200128020020042003103121040b2004450d0520012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010e8061a0c030b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d05200341017422052004200520044b1b22054100480d050240024020030d002005102d21040c010b200128020020032005103121040b2004450d0420012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41143a00004120102d2203450d0320032000290001370000200341186a200041196a290000370000200341106a200041116a290000370000200341086a200041096a29000037000002400240200141046a2802002204200528020022006b4120490d00200128020021040c010b200041206a22052000490d05200441017422002005200020054b1b22004100480d050240024020040d002000102d21040c010b200128020020042000103121040b2004450d0420012004360200200141046a2000360200200141086a28020021000b200141086a200041206a360200200420006a220141186a200341186a290000370000200141106a200341106a290000370000200141086a200341086a290000370000200120032900003700002003102f0c020b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d04200341017422052004200520044b1b22054100480d040240024020030d002005102d21040c010b200128020020032005103121040b2004450d0320012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41153a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d04200441017422032005200320054b1b22034100480d040240024020040d002003102d21040c010b200128020020042003103121040b2004450d0320012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041196a290000370000200141106a200041116a290000370000200141086a200041096a290000370000200120002900013700000c010b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d03200341017422052004200520044b1b22054100480d030240024020030d002005102d21040c010b200128020020032005103121040b2004450d0220012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41163a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d03200441017422032005200320054b1b22034100480d030240024020040d002003102d21040c010b200128020020042003103121040b2004450d0220012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041196a290000370000200141106a200041116a290000370000200141086a200041096a290000370000200120002900013700000b200241106a24000f0b1036000b1038000bea0903017f027e057f230041e0006b220224000240024002400240024002400240024020002802002200290300220342c000544100200041086a29030022045022051b0d0020034280800154410020051b0d01200342808080800454410020051b0d02411020047920037942c0007c20044200521ba741037622066b41044f0d0341d6bcc600413641f8b4ca001039000b02400240200141046a280200200141086a2802002200460d00200128020021050c010b200041016a22052000490d06200041017422062005200620054b1b22064100480d060240024020000d002006102d21050c010b200128020020002006103121050b2005450d0520012005360200200141046a2006360200200141086a28020021000b200141086a200041016a360200200520006a2003a74102743a00000c030b02400240200141046a2802002205200141086a28020022006b4102490d00200128020021050c010b200041026a22062000490d05200541017422002006200020064b1b22004100480d050240024020050d002000102d21050c010b200128020020052000103121050b2005450d0420012005360200200141046a2000360200200141086a28020021000b200141086a200041026a360200200520006a2003a74102744101723b00000c020b02400240200141046a2802002205200141086a28020022006b4104490d00200128020021050c010b200041046a22062000490d04200541017422002006200020064b1b22004100480d040240024020050d002000102d21050c010b200128020020052000103121050b2005450d0320012005360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200520006a2003a74102744102723600000c010b02400240200141046a280200200141086a2802002205460d00200128020021070c010b200541016a22082005490d03200541017422072008200720084b1b22084100480d030240024020050d002008102d21070c010b200128020020052008103121070b2007450d0220012007360200200141046a2008360200200141086a28020021050b200141086a2208200541016a360200200720056a413320064102746b3a0000200029030021032002200041086a290300220437030820022003370300200641706a2105200141046a2107034002400240200728020020082802002200460d00200128020021060c010b200041016a22062000490d04200041017422092006200920064b1b22094100480d040240024020000d002009102d21060c010b200128020020002009103121060b2006450d032001200636020020072009360200200828020021000b2008200041016a360200200620006a2003a73a00002003420888200442388684210320044208882104200541016a22002005492106200021052006450d000b2002200337030020022004370308200320048450450d030b200241e0006a24000f0b1036000b1038000b200241286a41146a4109360200200241346a412a360200200241106a41146a410336020020022002360240200241e0bdc600360244200241c8006a41146a410036020020024203370214200241b4e0ca003602102002412a36022c200241c8e1ca003602582002420137024c20024198bdc6003602482002200241286a3602202002200241c8006a3602382002200241c4006a3602302002200241c0006a360228200241106a41e8d8c9001043000ba7ed0205027f037e127f057e287f230022032104200341a0076b41607122032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e18000102030405060708090a0b0c0d0e0f1011121314151617000b200341b4036a4101360200200342013702a403200341b4d8c9003602a003200341043602a406200341fcdbc9003602a0062003200341a0066a3602b003200341a0036a41e8d8c9001043000b200141306a2903002105200141286a2903002106200341c0026a41186a200141196a290000370300200341c0026a41106a200141116a290000370300200341c0026a41086a200141096a290000370300200320012900013703c0022002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a024020022d0000450d00200320073702a403200320083a00a303200320093a00a2032003200a3b01a0030c420b200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241086a2d00002115200241066a2f01002116200241056a2d00002117200241046a2d00002118200241026a2f0100211920022d00012102200320073703a003200241ff01714101470d412003200737039005200320083a008f05200320093a008e052003200a3b018c052003200b3a008b052003200c3a008a052003200d3b0188052003200e3a0087052003200f3a008605200320103b018405200320113a008305200320123a008205200320133b018005200320143a00ff04200320153a00fe04200320163b01fc04200320173a00fb04200320183a00fa04200320193b01f804200642808084fea6dee1115441002005501b0d172003200537038002200320063703f8012003200341f8046a3602d0012003200341f8046a3602d8042003200341d8046a3602a8032003200341d0016a3602a4032003200341f8016a3602a003200341a0066a200341f8046a200341a0036a1094010240024020032802a0064101470d00200320032900a5063703a0032003200341ac066a2800003600a70320032d00a40621020c010b41042102200341a0066a41086a2903004201520d00200341a0066a41106a290300210720032802d8042108200341d8036a200341a0066a41186a290300370300200341d0036a2007370300200341a0036a41086a41003a0000200341a9036a2008290000370000200341b1036a200841086a290000370000200341b9036a200841106a290000370000200341c1036a200841186a290000370000200341033a00a00341c8e1ca004100200341a0036a108c010b200320032903a0033703c005200320032800a7033600c7050240200241ff01714104470d00419298ca00ad4280808080900184220710012202290000211a2002290008211b2002102f41f497ca00ad4280808080f00184221c10012202290000211d2002290008211e2002102f2003201e3703c8012003201d3703c0012003201b3703b8012003201a3703b001200341086a200341b0016a4120109501200328020c210820032802082109200710012202290000211a2002290008211b2002102f201c10012202290000211c2002290008211d2002102f2003201d3703c8012003201c3703c0012003201b3703b8012003201a3703b00120032008410020091b220a41016a3602a003200341b0016aad4280808080800484221a200341a0036aad4280808080c00084221b10042003200341f8046a3602a0062007100122022d000f210820022d000e210920022f000c210b20022d000b210c20022d000a210d20022f0008210e20022d0007210f20022d0006211020022f0004211120022d0003211220022d0002211320022f000021142002102f41b6a8c200ad428080808090018410012202290008210720022d0007211520022d0006211620022f0004211720022d0003211820022d0002211920022f0000211f2002102f2003200a3602a003201b10032202290018211b20022d0017212020022d0016212120022f0014212220022d0013212320022d0012212420022f0010212520022d000f212620022d000e212720022f000c212820022d000b212920022d000a212a20022f0008212b20022d0007212c20022d0006212d20022f0004212e20022d0003212f20022d0002213020022f000021312002102f41c000102d2202450d412002201b370038200220203a0037200220213a0036200220223b0034200220233a0033200220243a0032200220253b0030200220263a002f200220273a002e200220283b002c200220293a002b2002202a3a002a2002202b3b00282002202c3a00272002202d3a00262002202e3b00242002202f3a0023200220303a0022200220313b002020022007370018200220153a0017200220163a0016200220173b0014200220183a0013200220193a00122002201f3b0010200220083a000f200220093a000e2002200b3b000c2002200c3a000b2002200d3a000a2002200e3b00082002200f3a0007200220103a0006200220113b0004200220123a0003200220133a0002200220143b00004118102d2208450d4120082006370000200820053700082003429880808080023702a403200320083602a0034101200341a0036a106920032802a006210820032802a00321090240024020032802a403220c20032802a803220b6b411f4d0d00200c210d0c010b200b41206a220d200b490d3a200c410174220e200d200e200d4b1b220d4100480d3a02400240200c0d00200d102d21090c010b2009200c200d103121090b2009450d420b2009200b6a220c41086a200841086a290000370000200c41106a200841106a290000370000200c41186a200841186a2900003700002003200b41206a220b3602a803200c20082900003700002002ad4280808080800884200bad4220862009ad8410040240200d450d002009102f0b2002102f200341ac066a200341c0026a41086a290300370200200341b4066a200341c0026a41106a290300370200200341bc066a200341c0026a41186a290300370200200341cc066a200341f8046a41086a290300370200200341d4066a200341f8046a41106a290300370200200341dc066a200341f8046a41186a2903003702002003200a3602a006200320032903c0023702a406200320032903f8043702c4062003200341a0066a36029007419298ca00ad42808080809001841001220229000021072002290008211b2002102f41aba8c200ad4280808080b0018410012202290000211c2002290008211d2002102f2003201d3703c8012003201c3703c0012003201b3703b801200320073703b001200341f8016a201a100210730240024020032802f801450d0020034190016a41086a200341f8016a41086a280200360200200320032903f801370390010c010b4104102d2202450d42200342043702a403200320023602a0034100200341a0036a106920034198016a20032802a803360200200320032903a003370390010b200341d0016a41086a20034190016a41086a280200220236020020032003290390013703d001024002402002450d00200341a0036a20032802d00122082002410110c40220032802a0034101470d0120032802d401450d412008102f0c410b4101200341d0016a1069200328029007200341d0016a107f0c3e0b20032802a403210b0240200341ac036a2802002208200341a0036a41086a2802002209460d002002200820096b6a220241046a220c417f4c0d3902400240200c0d004101210d0c010b200c102d220d450d430b2003200c3602dc042003200d3602d804200320023602e0042003200341d8046a3602a003200b200341a0036a200810c50220022008490d1a20032802e004220b2002490d1b20032802d801220b2009490d1c20032802d804210c20032802d001210d2003200220086b2202360280062003200b20096b220b360290062002200b470d1d200c20086a200d20096a200210e8061a200328029007200341d8046a107f20032802e004210820032802dc04210920032802d804210220032802d401450d3f20032802d001102f0c3f0b2003200341d0016a3602a003200b200341a0036a200910c502200328029007200341d0016a107f0c3d0b200020023a0000200020032903c005370001200041086a20032800c705360000410121080c420b2002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a024020022d0000450d00200320073702a403200320083a00a303200320093a00a2032003200a3b01a0030c3b0b200141046a280200210b200241156a2d0000210c200241146a2d0000210d200241126a2f0100210e200241116a2d0000210f200241106a2d000021102002410e6a2f010021112002410d6a2d000021122002410c6a2d000021132002410a6a2f01002114200241096a2d00002115200241086a2d00002116200241066a2f01002117200241056a2d00002118200241046a2d00002119200241026a2f0100211f20022d00012102200320073703a003200241ff01714101470d3a2003200737039005200320083a008f05200320093a008e052003200a3b018c052003200c3a008b052003200d3a008a052003200e3b0188052003200f3a008705200320103a008605200320113b018405200320123a008305200320133a008205200320143b018005200320153a00ff04200320163a00fe04200320173b01fc04200320183a00fb04200320193a00fa042003201f3b01f804200341a0036a200b10a802024002400240024020032802b0032208450d00200341bc036a280200210c200341b8036a280200210a20032802b403210220032903a00321072003200341a8036a29030022053703c802200320073703c0022003200341f8046a3602d8044104210902402007200584500d002003200341f8046a3602f8012003200341f8016a3602a8032003200341d8046a3602a4032003200341c0026a3602a003200341a0066a200341f8046a200341a0036a109401024020032802a0064101470d00200320032900a5063703a0032003200341ac066a2800003600a70320032d00a40621090c010b41042109200341a0066a41086a2903004201520d00200341a0066a41106a290300210620032802f801210d200341d8036a200341a0066a41186a290300370300200341d0036a2006370300200341a0036a41086a41003a0000200341a9036a200d290000370000200341b1036a200d41086a290000370000200341b9036a200d41106a290000370000200341c1036a200d41186a290000370000200341033a00a00341c8e1ca004100200341a0036a108c010b200320032903a0033703c005200320032800a7033600c705200941ff01714104470d03200341b0016a41186a2209200341f8046a41186a290300370300200341b0016a41106a220d200341f8046a41106a290300370300200341b0016a41086a220e200341f8046a41086a290300370300200320032903f8043703b001200a2002460d012002210f200a21020c020b20004183143b0100200041086a410f360200200041046a41b1d5c700360200200041026a41013a00000c3c0b200241016a220f2002490d3920024101742210200f2010200f4b1b220f41ffffff3f71200f470d39200f410574220f4100480d390240024020020d00200f102d21080c010b20082002410574200f103121080b2008450d41200f410576210f0b200820024105746a220220032903b001370000200241186a2009290300370000200241106a200d290300370000200241086a200e290300370000200341a0036a41186a200a41016a360200200341b4036a200f360200200320053703a803200320073703a0032003200c3602bc03200320083602b003419298ca00ad4280808080900184100122022d000f210820022d000e210920022f000c210a20022d000b210c20022d000a210d20022f0008210e20022d0007210f20022d0006211020022f0004211120022d0003211220022d0002211320022f000021142002102f41b6a8c200ad428080808090018410012202290008210720022d0007211520022d0006211620022f0004211720022d0003211820022d0002211920022f0000211f2002102f2003200b3602a006200341a0066aad4280808080c0008410032202290018210520022d0017210b20022d0016212020022f0014212120022d0013212220022d0012212320022f0010212420022d000f212520022d000e212620022f000c212720022d000b212820022d000a212920022f0008212a20022d0007212b20022d0006212c20022f0004212d20022d0003212e20022d0002212f20022f000021302002102f41c000102d2202450d40200220053700382002200b3a0037200220203a0036200220213b0034200220223a0033200220233a0032200220243b0030200220253a002f200220263a002e200220273b002c200220283a002b200220293a002a2002202a3b00282002202b3a00272002202c3a00262002202d3b00242002202e3a00232002202f3a0022200220303b002020022007370018200220153a0017200220163a0016200220173b0014200220183a0013200220193a00122002201f3b0010200220083a000f200220093a000e2002200a3b000c2002200c3a000b2002200d3a000a2002200e3b00082002200f3a0007200220103a0006200220113b0004200220123a0003200220133a0002200220143b0000200341c0003602a406200320023602a006200341a0036a200341a0066a10b8012002102f024020032802b403450d0020032802b003102f0b200041043a0000410121080c420b200020093a0000200020032903c005370001200041086a20032800c7053600002002450d392008102f410121080c410b024020022d00000d004101210820022d000141ff01714101470d00200141026a2d00002109200141046a280200210a20012d0001210b2002411a6a2901002107200241196a2d0000210c200241186a2d0000210d200241166a2f0100210e200241156a2d0000210f200241146a2d00002110200241126a2f01002111200241116a2d00002112200241106a2d000021132002410e6a2f010021142002410d6a2d000021152002410c6a2d000021162002410a6a2f01002117200241086a2d00002118200241066a2f01002119200241056a2d0000211f200241046a2d00002120200241026a2f010021212003200241096a2d00003a00b701200320183a00b601200320193b01b4012003201f3a00b301200320203a00b201200320213b01b001200320123a00bf01200320133a00be01200320143b01bc01200320153a00bb01200320163a00ba01200320173b01b8012003200c3a00c7012003200d3a00c6012003200e3b01c4012003200f3a00c301200320103a00c201200320113b01c001200320073703c801200341b8036a2007370300200341b0036a20032903c001370300200341a8036a20032903b801370300200320032903b0013703a0032000200341a0036a200a200b41ff0171410047200910c6020c410b200041023a0000410121080c400b200241196a2d00002109200241186a2d0000210a200241166a2f0100210b2002411a6a2901002107024020022d0000450d00200320073702a403200320093a00a3032003200a3a00a2032003200b3b01a0030c370b200241156a3100002105200241146a3100002106200241126a330100211a200241116a2d0000210c200241106a2d0000210d2002410e6a2f0100210e2002410d6a2d0000210f2002410c6a2d000021102002410a6a2f01002111200241096a2d00002112200241086a2d00002113200241066a2f01002114200241056a2d00002115200241046a2d00002116200241026a2f01002117200141026a2d00002118200141046a280200211920022d0001210220012d0001211f200320073703a003200241ff01714101470d36419298ca00ad4280808080900184100122022d000f212020022d000e212120022f000c212220022d000b212320022d000a212420022f0008212520022d0007212620022d0006212720022f0004212820022d0003212920022d0002212a20022f0000212b2002102f41d49ac800ad4280808080d0008410012202290008211b20022d0007212c20022d0006212d20022f0004212e20022d0003212f20022d0002213020022f000021312002102f4120102d2208450d3d2008200e3b000c200820113b0008200820143b0004200820173b0000200820073700182008200c3a000f2008200f3a000b200820123a0007200820153a00032008410e6a200d3a00002008410a6a20103a0000200841066a20133a0000200841026a20163a000020082009ad42ff0183423886200aad42ff018342308684200bad42ffff038342208684200542188684200642108684201a843700102008ad428080808080048410032202290018210720022d0017210920022d0016210a20022f0014210b20022d0013210c20022d0012210d20022f0010210e20022d000f210f20022d000e211020022f000c211120022d000b211220022d000a211320022f0008211420022d0007211520022d0006211620022f0004211720022d0003213220022d0002213320022f000021342002102f2008102f41c000102d2202450d3d20022007370038200220093a00372002200a3a00362002200b3b00342002200c3a00332002200d3a00322002200e3b00302002200f3a002f200220103a002e200220113b002c200220123a002b200220133a002a200220143b0028200220153a0027200220163a0026200220173b0024200220323a0023200220333a0022200220343b00202002201b3700182002202c3a00172002202d3a00162002202e3b00142002202f3a0013200220303a0012200220313b0010200220203a000f200220213a000e200220223b000c200220233a000b200220243a000a200220253b0008200220263a0007200220273a0006200220283b0004200220293a00032002202a3a00022002202b3b0000200341a0036a200210c7020240024020032d00a00322094102460d00200341b8036a2d0000210a200341b7036a2d0000210b200341b5036a2f0000210c200341b4036a2d0000210d200341b3036a2d0000210e200341b1036a2f0000210f200341b0036a2d00002110200341af036a2d00002111200341ad036a2f00002112200341ac036a2d00002113200341ab036a2d00002114200341a9036a2f00002115200341a8036a2d0000211620032d00a703211720032f00a503212020032d00a403212120032d00a30321222003200341b9036a29000022073703c8012003200a3a00c7012003200b3a00c6012003200c3b01c4012003200d3a00c3012003200e3a00c2012003200f3b01c001200320103a00bf01200320113a00be01200320123b01bc01200320133a00bb01200320143a00ba01200320153b01b801200320163a00b701200320173a00b601200320203b01b401200320213a00b301200320223a00b201200320032f00a10322233b01b0012002102f4101210820094101470d01200320073703b8032003200a3a00b7032003200b3a00b6032003200c3b01b4032003200d3a00b3032003200e3a00b2032003200f3b01b003200320103a00af03200320113a00ae03200320123b01ac03200320133a00ab03200320143a00aa03200320153b01a803200320163a00a703200320173a00a603200320203b01a403200320213a00a303200320223a00a203200320233a00a003200320234108763a00a1032000200341a0036a2019201f41ff0171410047201810c6020c410b2002102f0b20004183143b0100200041086a4108360200200041046a419795c200360200200041026a41023a0000410121080c3f0b0240024020022d0000417f6a220841024b0d00200141046a2802002109024020080e03000102000b200241046a2d00000d00200241086a28020041036c2002410c6a2802004101744f0d010b200041023a0000410121080c3f0b200341f8046a200910b80220032d00a0054103460d18200341a0036a410a6a200341f8046a41086a290300370100200341a0036a41126a200341f8046a41106a290300370100200341a0036a411a6a200341f8046a41186a290300370100200341a0036a41226a200341f8046a41206a290300370100200341a0036a412a6a200341f8046a41286a280200360100200320032903f8043701a203200341a0066a41086a200341a0036a41086a220a290100370300200341a0066a41106a200341a0036a41106a220b290100370300200341a0066a41186a200341a0036a41186a220c290100370300200341a0066a41206a200341a0036a41206a290100370300200341a0066a41266a200341a0036a41266a290100370100200320032901a0033703a006200341c0026a41286a200341a0066a412a6a280100360200200341c0026a41206a2202200341a0066a41226a290100370300200341c0026a41186a2208200341a0066a411a6a290100370300200341c0026a41106a220d200341a0066a41126a290100370300200341c0026a41086a220e200341a0066a410a6a290100370300200320032901a2063703c002200341b0016a41186a2002290300370300200341b0016a41106a2008290300370300200341b0016a41086a200d2903003703002003200e2903003703b001200c2002290300370300200b2008290300370300200a200d2903003703002003200e2903003703a003419298ca00ad4280808080900184100122022d000f210d20022d000e210e20022f000c210f20022d000b211020022d000a211120022f0008211220022d0007211320022d0006211420022f0004211520022d0003211620022d0002211720022f000021182002102f41fc80c300ad4280808080d0018410012202290008210720022d0007211920022d0006211f20022f0004212020022d0003212120022d0002212220022f000021232002102f4120102d2208450d3c200820032903a003370000200841186a200c290300370000200841106a200b290300370000200841086a200a2903003700002008ad428080808080048410032202290018210520022d0017210a20022d0016210b20022f0014210c20022d0013212420022d0012212520022f0010212620022d000f212720022d000e212820022f000c212920022d000b212a20022d000a212b20022f0008212c20022d0007212d20022d0006212e20022f0004212f20022d0003213020022d0002213120022f000021322002102f2008102f41c000102d2202450d3c200220053700382002200a3a00372002200b3a00362002200c3b0034200220243a0033200220253a0032200220263b0030200220273a002f200220283a002e200220293b002c2002202a3a002b2002202b3a002a2002202c3b00282002202d3a00272002202e3a00262002202f3b0024200220303a0023200220313a0022200220323b002020022007370018200220193a00172002201f3a0016200220203b0014200220213a0013200220223a0012200220233b00102002200d3a000f2002200e3a000e2002200f3b000c200220103a000b200220113a000a200220123b0008200220133a0007200220143a0006200220153b0004200220163a0003200220173a0002200220183b0000200341106a200241c00041c8e1ca004100410010b5012003280210210a2002102f41012108200a4101460d12200341a0036a41186a220a200341b0016a41186a290300370300200341a0036a41106a220b200341b0016a41106a290300370300200341a0036a41086a220c200341b0016a41086a290300370300200320032903b0013703a003419298ca00ad4280808080900184100122022d000f210d20022d000e210e20022f000c210f20022d000b211020022d000a211120022f0008211220022d0007211320022d0006211420022f0004211520022d0003211620022d0002211720022f000021182002102f41fc80c300ad4280808080d0018410012202290008210720022d0007211920022d0006211f20022f0004212020022d0003212120022d0002212220022f000021232002102f4120102d2208450d3c200820032903a003370000200841186a200a290300370000200841106a200b290300370000200841086a200c2903003700002008ad428080808080048410032202290018210520022d0017210a20022d0016210b20022f0014210c20022d0013212420022d0012212520022f0010212620022d000f212720022d000e212820022f000c212920022d000b212a20022d000a212b20022f0008212c20022d0007212d20022d0006212e20022f0004212f20022d0003213020022d0002213120022f000021322002102f2008102f41c000102d2202450d3c200220053700382002200a3a00372002200b3a00362002200c3b0034200220243a0033200220253a0032200220263b0030200220273a002f200220283a002e200220293b002c2002202a3a002b2002202b3a002a2002202c3b00282002202d3a00272002202e3a00262002202f3b0024200220303a0023200220313a0022200220323b002020022007370018200220193a00172002201f3a0016200220203b0014200220213a0013200220223a0012200220233b00102002200d3a000f2002200e3a000e2002200f3b000c200220103a000b200220113a000a200220123b0008200220133a0007200220143a0006200220153b0004200220163a0003200220173a0002200220183b000041012108200341013a00a0032002ad4280808080800884200341a0036aad4280808080108410042002102f200910af02200041043a00000c3e0b20034190056a200141196a29000037030020034188056a200141116a29000037030020034180056a200141096a290000370300200320012900013703f8040240024020022d0000417f6a220841024b0d00024020080e03000102000b200241086a2802004101742002410c6a280200490d00200241046a28020041ff0171450d010b200041023a0000410121080c3e0b419298ca00ad4280808080900184221b100122022900002107200229000821052002102f41bfa8c200ad4280808080c001841001220229000021062002290008211a2002102f2003201a3703c801200320063703c001200320053703b801200320073703b001200341206a200341b0016a412041c8e1ca004100410010b50102400240024020032802204101460d00200341a0036a41186a2209200341f8046a41186a290300370300200341a0036a41106a220a200341f8046a41106a290300370300200341a0036a41086a220b200341f8046a41086a290300370300200320032903f8043703a003201b100122022d000f210c20022d000e210d20022f000c210e20022d000b210f20022d000a211020022f0008211120022d0007211220022d0006211320022f0004211420022d0003211520022d0002211620022f000021172002102f41b080c300ad428080808090018410012202290008210720022d0007211820022d0006211920022f0004211f20022d0003212020022d0002212120022f000021222002102f4120102d2208450d3e200820032903a003370000200841186a2009290300370000200841106a200a290300370000200841086a200b2903003700002008ad428080808080048410032202290018210520022d0017210920022d0016210a20022f0014210b20022d0013212320022d0012212420022f0010212520022d000f212620022d000e212720022f000c212820022d000b212920022d000a212a20022f0008212b20022d0007212c20022d0006212d20022f0004212e20022d0003212f20022d0002213020022f000021312002102f2008102f41c000102d2202450d3e20022005370038200220093a00372002200a3a00362002200b3b0034200220233a0033200220243a0032200220253b0030200220263a002f200220273a002e200220283b002c200220293a002b2002202a3a002a2002202b3b00282002202c3a00272002202d3a00262002202e3b00242002202f3a0023200220303a0022200220313b002020022007370018200220183a0017200220193a00162002201f3b0014200220203a0013200220213a0012200220223b00102002200c3a000f2002200d3a000e2002200e3b000c2002200f3a000b200220103a000a200220113b0008200220123a0007200220133a0006200220143b0004200220153a0003200220163a0002200220173b0000200341a0066a200210c80220032802a40622090d012002102f0c020b20004183143b0100200041086a4111360200200041046a41c0d5c700360200200041026a41053a0000410121080c3f0b20032903a806210720032802a006210a2002102f200341a0036a41186a4200370300200341a0036a41106a220b4200370300200341a0036a41086a22024200370300200342003703a003418de6c300ad4280808080e000841001220829000021052002200841086a290000370300200320053703a0032008102f419ce6c300ad4280808080e00084100122082900002105200341d8046a41086a220c200841086a290000370300200320053703d8042008102f200b20032903d8042205370300200341a0066a41086a2002290300370300200341a0066a41106a2005370300200341a0066a41186a200c290300370300200320032903a0033703a006200341186a200341a0066a41201095010240200328021c410020032802181b200a4f0d0020004183143b0100200041086a4113360200200041046a41ed94c200360200200041026a41063a00002007a7450d372009102f410121080c3f0b2007a7450d002009102f0b200341a0036a41186a200341f8046a41186a290300370300200341a0036a41106a200341f8046a41106a290300370300200341a0036a41086a200341f8046a41086a290300370300200320032903f8043703a003200341003a00c003419298ca00ad4280808080900184100122022900002107200229000821052002102f41bfa8c200ad4280808080c001841001220229000021062002290008211a2002102f2003201a3703c801200320063703c001200320053703b801200320073703b001200341203602a4062003200341b0016a3602a006200341a0036a200341a0066a108401200041043a0000410121080c3d0b200341b8066a200141196a290000370300200341b0066a200141116a290000370300200341a0066a41086a200141096a290000370300200320012900013703a0060240024020022d0000417f6a220841024b0d00024020080e03000102000b200241046a2d00000d00200241086a2802004102742002410c6a28020041036c4f0d010b200041023a0000410121080c3d0b200341a0036a41186a200341a0066a41186a290300370300200341a0036a41106a200341a0066a41106a290300370300200341a0036a41086a200341a0066a41086a290300370300200320032903a0063703a003200341023a00c003419298ca00ad4280808080900184100122022900002107200229000821052002102f41bfa8c200ad4280808080c001841001220229000021062002290008211a2002102f2003201a3703c801200320063703c001200320053703b801200320073703b001200341203602fc042003200341b0016a3602f804200341a0036a200341f8046a108401200041043a0000410121080c3c0b200341b8066a200141196a290000370300200341b0066a200141116a290000370300200341a8066a200141096a290000370300200320012900013703a0060240024020022d0000417f6a220841024b0d00024020080e03000102000b200241086a2802002002410c6a280200490d00200241046a28020041ff0171450d010b200041023a0000410121080c3c0b200341a0036a41186a200341a0066a41186a290300370300200341a0036a41106a200341a0066a41106a290300370300200341a0036a41086a200341a0066a41086a290300370300200320032903a0063703a00341012108200341013a00c003419298ca00ad4280808080900184100122022900002107200229000821052002102f41bfa8c200ad4280808080c001841001220229000021062002290008211a2002102f2003201a3703c801200320063703c001200320053703b801200320073703b001200341203602fc042003200341b0016a3602f804200341a0036a200341f8046a108401200041043a00000c3b0b200141286a280200210b200141246a280200210a200341d8026a200141196a290000370300200341d0026a200141116a290000370300200341c0026a41086a200141096a290000370300200320012900013703c002410121080240024020022d0000417e6a220941014b0d00024020090e020002000b200241046a2d00000d00200241086a28020041036c2002410c6a2802004101744f0d010b200041023a00000c3b0b419298ca00ad4280808080900184100122022900002107200229000821052002102f41bfa8c200ad4280808080c001841001220229000021062002290008211a2002102f2003201a3703c801200320063703c001200320053703b801200320073703b001200341a0036a200341b0016a10a502024002400240024020032d00c00322024103460d0020032f01a003210820032901a203210720032901aa03210520032801b203210920032f01b603210c200320032903b803370390052003200c3b018e052003200936018a052003200537018205200320073701fa04200320083a00f804200320084108763a00f90420020d014111210341dc94c2002102410721080c020b20004183143b0100200041086a410f360200200041046a41b1d5c70036020041012108200041026a41013a00000c3d0b200341c0026a200341f8046a412010ea06450d01410b210341d194c2002102410821080b20004183143b0100200041086a2003360200200041046a2002360200200041026a20083a0000410121080c3b0b419298ca00ad4280808080900184100122082900002107200829000821052008102f41bfa8c200ad4280808080c001841001220829000021062008290008211a2008102f2003201a3703c801200320063703c001200320053703b801200320073703b001200341b0016aad42808080808004841005200341a0036a41186a220d4200370300200341a0036a41106a22094200370300200341a0036a41086a22084200370300200342003703a003418de6c300ad4280808080e000841001220c29000021072008200c41086a290000370300200320073703a003200c102f419ce6c300ad4280808080e000841001220c2900002107200341d8046a41086a220e200c41086a290000370300200320073703d804200c102f200920032903d8042207370300200341a0066a41086a2008290300370300200341a0066a41106a2007370300200341a0066a41186a200e290300370300200320032903a0033703a006200341286a200341a0066a4120109501200328022c210c2003280228210e200d200341c0026a41186a2903003703002009200341c0026a41106a2903003703002008200341c0026a41086a290300370300200320032903c0023703a003200c4100200e1b200a4180a305200a4180a3054b1b6a200341a0036a2002200b10a602200041043a0000410121080c3a0b200341d8026a200141196a290000370300200341c0026a41106a200141116a290000370300200341c0026a41086a200141096a290000370300200320012900013703c00220022d00004102470d14200241236a2d00002109200241216a2f0000210a2002411f6a2d0000210b2002411d6a2f0000210c2002410f6a2d0000210d2002410d6a2f0000210e2002410b6a2d0000210f200241096a2f00002110200241076a2d00002111200241056a2f00002112200241246a3502002105200241206a3100002106200241116a2900002107200241106a2d000021132002410c6a2d00002114200241086a2d00002115200241046a2d000021082003200241196a2800003602a803200320073703a00320084101470d142003200e200d4110747222023b018005200341f8046a410a6a20024110763a000020032007a722023b01840520034186056a20024110763a0000200320032902a40337038805200320133a008305200320143a00ff04200320153a00fb04200320074218883c00870520032010200f4110747222023b01fc04200320024110763a00fe042003201220114110747222023b01f804200320024110763a00fa0420032006421886200c200b41107472ad42ffffff078384200a200941107472ad42ffffff07834220868420054238868437039005419298ca00ad4280808080900184100122022900002107200229000821052002102f41bfa8c200ad4280808080c001841001220229000021062002290008211a2002102f2003201a3703c801200320063703c001200320053703b801200320073703b001200341a0036a200341b0016a10a5020240024020032d00c0034103460d0020032903a003210720032903a803210520032903b0032106200320032903b8033703b803200320063703b003200320053703a803200320073703a003200341c0026a200341a0036a412010ea06450d0120004183143b0100200041086a410f360200200041046a41b1d5c700360200200041026a41013a0000410121080c3b0b20004183143b0100200041086a410a360200200041046a41c794c200360200200041026a41093a0000410121080c3a0b419298ca00ad4280808080900184100122022d000f210920022d000e210a20022f000c210b20022d000b210c20022d000a210d20022f0008210e20022d0007210f20022d0006211020022f0004211120022d0003211220022d0002211320022f000021142002102f41b080c300ad428080808090018410012202290008210720022d0007211520022d0006211620022f0004211720022d0003211820022d0002211920022f0000211f2002102f4120102d2208450d37200820032903c002370000200841186a200341c0026a41186a290300370000200841106a200341c0026a41106a290300370000200841086a200341c0026a41086a2903003700002008ad428080808080048410032202290018210520022d0017212020022d0016212120022f0014212220022d0013212320022d0012212420022f0010212520022d000f212620022d000e212720022f000c212820022d000b212920022d000a212a20022f0008212b20022d0007212c20022d0006212d20022f0004212e20022d0003212f20022d0002213020022f000021312002102f2008102f41c000102d2202450d3720022005370038200220203a0037200220213a0036200220223b0034200220233a0033200220243a0032200220253b0030200220263a002f200220273a002e200220283b002c200220293a002b2002202a3a002a2002202b3b00282002202c3a00272002202d3a00262002202e3b00242002202f3a0023200220303a0022200220313b002020022007370018200220153a0017200220163a0016200220173b0014200220183a0013200220193a00122002201f3b0010200220093a000f2002200a3a000e2002200b3b000c2002200c3a000b2002200d3a000a2002200e3b00082002200f3a0007200220103a0006200220113b0004200220123a0003200220133a0002200220143b0000200341a0036a200210c80220032903a803210720032802a803211120032802a40321102002102f41002109024020100d0041012110410021114100210b0c2d0b2007a7210b024002402007422088a7220c41014b0d0041002102200c0e022e012e0b200c210841002102034020022008410176220920026a220a2010200a4105746a200341f8046a412010ea0641004a1b2102200820096b220841014b0d000b0b0240201020024105746a200341f8046a412010ea062208450d00200341a0036a41186a200341f8046a41186a290300370300200341a0036a41106a200341f8046a41106a290300370300200341a0036a41086a200341f8046a41086a290300370300200320032903f8043703a0032008411f7620026a220a200c4b0d16200341a0036a2108200c21090c2e0b20004183143b0100200041086a410d360200200041046a41ba94c200360200200041026a410a3a00002011450d312010102f410121080c390b024020022d000120022d0000410047720d00200141046a28020010af02200041043a0000410121080c390b200041023a0000410121080c380b024020022d000120022d0000410047720d00200141046a280200210c200341a0036a41186a220f4200370300200341a0036a41106a220e4200370300200341a0036a41086a220d4200370300200342003703a003419298ca00ad4280808080900184100122022900002107200d200241086a290000370300200320073703a0032002102f418ca8c200ad4280808080d00184100122022900002107200341d8046a41086a2208200241086a290000370300200320073703d8042002102f200e20032903d8042207370300200341a0066a41086a200d290300370300200341a0066a41106a2007370300200341a0066a41186a2008290300370300200320032903a0033703a006200341a0036a200341a0066a10c90220032802a0032202410420021b211920032902a403420020021b221b422088a7220b450d294100210820192102410021090340024002400240200241246a280200200c460d0020080d01410021080c020b200841016a21080c010b200920086b220a200b4f0d17200341a0036a41206a22102002200841586c6a220a41206a2211290200370300200f200a41186a2212290200370300200e200a41106a2213290200370300200d200a41086a22142902003703002003200a2902003703a003200241206a22152902002107200241186a22162902002105200241106a22172902002106200241086a2218290200211a200a20022902003702002014201a370200201320063702002012200537020020112007370200201520102903003702002016200f2903003702002017200e2903003702002018200d290300370200200220032903a0033702000b200241286a2102200b200941016a2209460d290c000b0b200041023a0000410121080c370b200341f8016a41186a200141196a290000370300200341f8016a41106a200141116a290000370300200341f8016a41086a200141096a290000370300200320012900013703f801200241196a2d00002108200241186a2d00002109200241166a2f0100210a2002411a6a2901002107024020022d0000450d00200320073702a403200320083a00a303200320093a00a2032003200a3b01a0030c260b200241026a2f0100210b200241046a2d0000210c200241056a2d0000210d200241066a2f0100210e200241086a2d0000210f200241096a2d000021102002410a6a2f010021112002410c6a2d000021122002410d6a2d000021132002410e6a2f01002114200241106a2d00002115200241116a2d00002116200241126a3301002105200241146a3100002106200241156a310000211a20022d00012102200320073703a003200241ff01714101470d25200341be016a20153a0000200341ba016a20123a0000200320143b01bc01200320113b01b8012003200f3a00b6012003200e3b01b4012003200c3a00b2012003200b3b01b001200320073703c801200320163a00bf01200320133a00bb01200320103a00b7012003200d3a00b30120032008ad42ff01834238862009ad42ff018342308684200aad42ffff038342208684201a421886842006421086842005843703c001419298ca00ad4280808080900184100122022d000f210920022d000e210a20022f000c210b20022d000b210c20022d000a210d20022f0008210e20022d0007210f20022d0006211020022f0004211120022d0003211220022d0002211320022f000021142002102f41d49ac800ad4280808080d0008410012202290008210720022d0007211520022d0006211620022f0004211720022d0003211820022d0002211920022f0000211f2002102f4120102d2208450d34200820032903f801370000200841186a200341f8016a41186a290300370000200841106a200341f8016a41106a290300370000200841086a200341f8016a41086a2903003700002008ad428080808080048410032202290018210520022d0017212020022d0016212120022f0014212220022d0013212320022d0012212420022f0010212520022d000f212620022d000e212720022f000c212820022d000b212920022d000a212a20022f0008212b20022d0007212c20022d0006212d20022f0004212e20022d0003212f20022d0002213020022f000021312002102f2008102f41c000102d2202450d3420022005370038200220203a0037200220213a0036200220223b0034200220233a0033200220243a0032200220253b0030200220263a002f200220273a002e200220283b002c200220293a002b2002202a3a002a2002202b3b00282002202c3a00272002202d3a00262002202e3b00242002202f3a0023200220303a0022200220313b002020022007370018200220153a0017200220163a0016200220173b0014200220183a0013200220193a00122002201f3b0010200220093a000f2002200a3a000e2002200b3b000c2002200c3a000b2002200d3a000a2002200e3b00082002200f3a0007200220103a0006200220113b0004200220123a0003200220133a0002200220143b0000200341a0036a200210c7020240024020032d00a00322084102470d00200341023a00c0020c010b200341b9036a2900002107200320032900a1033700c102200320083a00c002200320073e00d902200320074230883c00df02200320074220883d00dd022003200341a9036a2900003700c9022003200341b1036a2900003700d1022007423888a721080b200341f8046a41186a200341b0016a41186a290300370300200341f8046a41106a200341b0016a41106a290300370300200341f8046a41086a200341b0016a41086a290300370300200320032903b0013703f804200341a0036a41186a20032903d802370300200341a0036a41206a20083a0000200341023a00a006200320032903d0023703b003200320032903c8023703a803200320032903c00222073703a003200320032903b8063703d802200320032903b0063703d002200320032903a8063703c802200320032903a0063703c002024002400240024002402007a7410371417f6a220841014b0d0020080e020102010b200341a0036a410172200341f8046a412010ea060d02200320032903f8043700c102200341013a00c00220032003418f056a2900003700d802200320034188056a2903003700d102200320034180056a2903003700c90220032d0097052109200320032903d8023703b803200320032903d0023703b003200320032903c8023703a803200320032903c00222073703a003024002402007a7220841ff01714102470d002002ad428080808080088410050c010b200320083a00e0054101102d220a450d39200a20083a0000200a4101412110312208450d39200820032900a103370001200820093a0020200841186a20032900b803370000200841116a20032900b103370000200841096a20032900a9033700002002ad42808080808008842008ad428080808090048410042008102f0b2002102f200041043a0000410121080c3a0b2002102f4185ccc7002103410c2102410b21080c020b2002102f41a793c200210341072102411821080c010b2002102f419e93c200210341092102411921080b20004183143b0100200041086a2002360200200041046a2003360200200041026a20083a0000410121080c360b2002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241086a2d00002115200241066a2f01002116200241056a2d00002117200241046a2d00002118200241026a2f010021190240024020022d0000450d00200320073702a403200320083a00a303200320093a00a2032003200a3b01a003410121020c010b20022d00012102200320073703a003200241ff017141014721020b200320073703c801200320083a00c701200320093a00c6012003200a3b01c4012003200b3a00c3012003200c3a00c2012003200d3b01c0012003200e3a00bf012003200f3a00be01200320103b01bc01200320113a00bb01200320123a00ba01200320133b01b801200320143a00b701200320153a00b601200320163b01b401200320173a00b301200320183a00b201200320193b01b001024020020d00200341a0066a41186a2209200341b0016a41186a290300370300200341a0066a41106a220a200341b0016a41106a290300370300200341a0066a41086a220b200341b0016a41086a290300370300200320032903b0013703a006419298ca00ad4280808080900184100122022d000f210c20022d000e210d20022f000c210e20022d000b210f20022d000a211020022f0008211120022d0007211220022d0006211320022f0004211420022d0003211520022d0002211620022f000021172002102f41d49ac800ad4280808080d0008410012202290008210720022d0007211820022d0006211920022f0004211f20022d0003212020022d0002212120022f000021222002102f4120102d2208450d34200820032903a006370000200841186a2009290300370000200841106a200a290300370000200841086a200b2903003700002008ad428080808080048410032202290018210520022d0017210920022d0016210a20022f0014210b20022d0013212320022d0012212420022f0010212520022d000f212620022d000e212720022f000c212820022d000b212920022d000a212a20022f0008212b20022d0007212c20022d0006212d20022f0004212e20022d0003212f20022d0002213020022f000021312002102f2008102f41c000102d2202450d3420022005370038200220093a00372002200a3a00362002200b3b0034200220233a0033200220243a0032200220253b0030200220263a002f200220273a002e200220283b002c200220293a002b2002202a3a002a2002202b3b00282002202c3a00272002202d3a00262002202e3b00242002202f3a0023200220303a0022200220313b002020022007370018200220183a0017200220193a00162002201f3b0014200220203a0013200220213a0012200220223b00102002200c3a000f2002200d3a000e2002200e3b000c2002200f3a000b200220103a000a200220113b0008200220123a0007200220133a0006200220143b0004200220153a0003200220163a0002200220173b0000200341a0036a200210c702024020032d00a0034102460d00200341a0066a10ca020b2002ad428080808080088410052002102f200041043a0000410121080c360b200041023a0000410121080c350b200341f8016a41186a200141196a290000370300200341f8016a41106a200141116a290000370300200341f8016a41086a200141096a290000370300200320012900013703f801200241196a2d00002108200241186a2d00002109200241166a2f0100210a2002411a6a2901002107024020022d0000450d00200320073702a403200320083a00a303200320093a00a2032003200a3b01a0030c230b200241026a2f0100210b200241046a2d0000210c200241056a2d0000210d200241066a2f0100210e200241086a2d0000210f200241096a2d000021102002410a6a2f010021112002410c6a2d000021122002410d6a2d000021132002410e6a2f01002114200241106a2d00002115200241116a2d00002116200241126a3301002105200241146a3100002106200241156a310000211a20022d00012102200320073703a003200241ff01714101470d22200341be016a20153a0000200341ba016a20123a0000200320143b01bc01200320113b01b8012003200f3a00b6012003200e3b01b4012003200c3a00b2012003200b3b01b001200320073703c801200320163a00bf01200320133a00bb01200320103a00b7012003200d3a00b30120032008ad42ff01834238862009ad42ff018342308684200aad42ffff038342208684201a421886842006421086842005843703c001419298ca00ad4280808080900184100122022d000f210920022d000e210a20022f000c210b20022d000b210c20022d000a210d20022f0008210e20022d0007210f20022d0006211020022f0004211120022d0003211220022d0002211320022f000021142002102f41d49ac800ad4280808080d0008410012202290008210720022d0007211520022d0006211620022f0004211720022d0003211820022d0002211920022f0000211f2002102f4120102d2208450d32200820032903f801370000200841186a200341f8016a41186a290300370000200841106a200341f8016a41106a290300370000200841086a200341f8016a41086a2903003700002008ad428080808080048410032202290018210520022d0017212020022d0016212120022f0014212220022d0013212320022d0012212420022f0010212520022d000f212620022d000e212720022f000c212820022d000b212920022d000a212a20022f0008212b20022d0007212c20022d0006212d20022f0004212e20022d0003212f20022d0002213020022f000021312002102f2008102f41c000102d2202450d3220022005370038200220203a0037200220213a0036200220223b0034200220233a0033200220243a0032200220253b0030200220263a002f200220273a002e200220283b002c200220293a002b2002202a3a002a2002202b3b00282002202c3a00272002202d3a00262002202e3b00242002202f3a0023200220303a0022200220313b002020022007370018200220153a0017200220163a0016200220173b0014200220183a0013200220193a00122002201f3b0010200220093a000f2002200a3a000e2002200b3b000c2002200c3a000b2002200d3a000a2002200e3b00082002200f3a0007200220103a0006200220113b0004200220123a0003200220133a0002200220143b0000200341a0036a200210c7020240024020032d00a00322084102470d00200341023a00c0020c010b200341b9036a2900002107200320032900a1033700c102200320083a00c002200320073e00d902200320074230883c00df02200320074220883d00dd022003200341a9036a2900003700c9022003200341b1036a2900003700d1022007423888a721080b200341f8046a41186a200341b0016a41186a290300370300200341f8046a41106a200341b0016a41106a290300370300200341f8046a41086a200341b0016a41086a290300370300200320032903b0013703f804200341a0036a41186a20032903d802370300200341a0036a41206a20083a0000200341023a00a006200320032903d0023703b003200320032903c8023703a803200320032903c00222073703a003200320032903b8063703d802200320032903b0063703d002200320032903a8063703c802200320032903a0063703c0020240024002402007a741ff01714101470d00200341a0036a410172200341f8046a412010ea060d01200320032903f8043700c102200341003a00c00220032003418f056a2900003700d802200320034188056a2903003700d102200320034180056a2903003700c90220032d0097052109200320032903d8023703b803200320032903d0023703b003200320032903c8023703a803200320032903c00222073703a003024002402007a7220841ff01714102470d002002ad428080808080088410050c010b200320083a00e0054101102d220a450d36200a20083a0000200a4101412110312208450d36200820032900a103370001200820093a0020200841186a20032900b803370000200841116a20032900b103370000200841096a20032900a9033700002002ad42808080808008842008ad428080808090048410042008102f0b2002102f200041043a0000410121080c370b2002102f419593c200210341092102411a21080c010b2002102f41b094c2002103410a2102410c21080b20004183143b0100200041086a2002360200200041046a2003360200200041026a20083a0000410121080c340b200141216a2d0000210b20034190016a41186a200141196a29000037030020034190016a41106a200141116a29000037030020034190016a41086a200141096a29000037030020032001290001370390012002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a024020022d0000450d00200320073702a403200320083a00a303200320093a00a2032003200a3b01a0030c210b200241156a2d0000210c200241146a2d0000210d200241126a2f0100210e200241116a2d0000210f200241106a2d000021102002410e6a2f010021112002410d6a2d000021122002410c6a2d000021132002410a6a2f01002114200241096a2d00002115200241086a2d00002116200241066a2f01002117200241056a2d00002118200241046a2d00002119200241026a2f0100211f20022d00012102200320073703a003200241ff01714101470d20200320073703e801200320083a00e701200320093a00e6012003200a3b01e4012003200c3a00e3012003200d3a00e2012003200e3b01e0012003200f3a00df01200320103a00de01200320113b01dc01200320123a00db01200320133a00da01200320143b01d801200320153a00d701200320163a00d601200320173b01d401200320183a00d301200320193a00d2012003201f3b01d001419298ca00ad4280808080900184100122022900002107200341a0066a41086a200241086a290000370300200320073703a0062002102f418a93c200ad4280808080b00184100122022900002107200341a0036a41086a200241086a290000370300200320073703a0032002102f4120102d2202450d31200220032903d001370000200241186a200341d0016a41186a290300370000200241106a200341d0016a41106a290300370000200241086a200341d0016a41086a2903003700002002ad4280808080800484100322082900002107200841086a2900002105200841106a2900002106200341b0016a41186a2209200841186a290000370300200341b0016a41106a220a2006370300200341b0016a41086a2005370300200320073703b0012008102f2002102f41c000102d2202450d31200220032903a006370000200241086a200341a0066a41086a290300370000200220032903a003370010200241186a200341a0036a41086a290300370000200220032903b001370020200241286a200341b0016a41086a290300370000200241306a200a290300370000200241386a2009290300370000200341a0066a200241c00010cb02024020032d00c10622084102470d002003200341d0016a36029007419298ca00ad4280808080900184100122082900002107200341e0056a41086a2209200841086a290000370300200320073703e0052008102f41f992c200ad4280808080900284100122082900002107200341f0056a41086a220a200841086a290000370300200320073703f0052008102f200341c0056a41086a2009290300370300200341d8056a200a290300370300200320032903e0053703c005200320032903f0053703d005200341a0036a200341c0056a108801200341f8016a20032802a003220820032802a80310ad02024020032802a403450d002008102f0b200341d0056a2108024020032d00f8010d00419298ca00ad4280808080900184100122092900002107200341e0056a41086a220a200941086a290000370300200320073703e0052009102f41f992c200ad4280808080900284100122092900002107200341f0056a41086a220c200941086a290000370300200320073703f0052009102f200341c0056a41086a200a290300370300200820032903f005370000200841086a200c290300370000200320032903e0053703c005200341a0036a200341c0056a10880120032802a003210920033502a80321074120102d2208450d33200820032903d001370000200841186a200341d0016a41186a290300370000200841106a200341d0016a41106a290300370000200841086a200341d0016a41086a29030037000020074220862009ad842008ad428080808080048410042008102f20032802a403450d202009102f0c200b200341d8046a41186a20034191026a290000370300200341d8046a41106a20034189026a290000370300200341d8046a41086a200341f8016a41096a290000370300200320032900f9013703d804200341b0016a200341d8046a10b602200341a0036a20032802b001220a20032802b801220c10cb02024020032d00c1034102470d00200341003602c802200342013703c002200341c0056a41146a4129360200200341cc056a410b360200200341093602e4052003419298ca003602e0052003410b3602c4052003410b3602f4052003418a93c2003602f0052003200341b0016a3602d0052003200341f0056a3602c8052003200341e0056a3602c0052003200341c0026a36028006200341f8046a41146a4103360200200342033702fc04200341cc90c4003602f8042003200341c0056a3602880520034180066a41d8dbc100200341f8046a103c1a20033502c80242208620033502c002841008024020032802c402450d0020032802c002102f0b2003280290072109419298ca00ad42808080809001841001220a2900002107200341e0056a41086a220c200a41086a290000370300200320073703e005200a102f41f992c200ad42808080809002841001220a2900002107200341f0056a41086a220d200a41086a290000370300200320073703f005200a102f200341c0056a41086a200c290300370300200820032903f005370000200841086a200d290300370000200320032903e0053703c005200341f8046a200341c0056a10880120032802f804210a20033502800521074120102d2208450d3320082009290000370000200841186a200941186a290000370000200841106a200941106a290000370000200841086a200941086a2900003700002007422086200aad842008ad428080808080048410042008102f024020032802fc04450d00200a102f0b20032802b401450d2020032802b001102f0c200b200341f8046a200341c1036a41c20010e8061a20032d0099052109200341c0026a41206a200341a0036a41206a2d00003a0000200341c0026a41186a200341a0036a41186a290300370300200341c0026a41106a200341a0036a41106a290300370300200341c0026a41086a200341a0036a41086a290300370300200341e8026a2003419a056a410020094101461b360200200320032903a0033703c002200320034190076a3602e402200341003602c805200342013703c0054120102d2209450d32200920032903c002370000200941086a200341c0026a41086a290300370000200941106a200341c0026a41106a290300370000200941186a200341c0026a41186a290300370000200342a080808080043702c405200320093602c005024020032d00e002220d41064b0d0002400240024002400240024002400240200d0e0700010203040506000b200341003a00e0050c060b200341013a00e0050c050b200341023a00e0050c040b200341033a00e0050c030b200341043a00e0050c020b200341053a00e0050c010b200341063a00e0050b2009412041c00010312209450d33200920032d00e0053a0020200320093602c005200342c080808090043702c4050b200341e4026a200341c0056a10cd0220032802c4052109200cad422086200aad8420033502c80542208620032802c005220aad84100402402009450d00200a102f0b024020032802b401450d0020032802b001102f0b2003280290072109419298ca00ad42808080809001841001220a2900002107200341e0056a41086a220c200a41086a290000370300200320073703e005200a102f41f992c200ad42808080809002841001220a2900002107200341f0056a41086a220d200a41086a290000370300200320073703f005200a102f200341c0056a41086a200c290300370300200820032903f005370000200841086a200d290300370000200320032903e0053703c005200341a0036a200341c0056a10880120032802a003210a20033502a80321074120102d2208450d3220082009290000370000200841186a200941186a290000370000200841106a200941106a290000370000200841086a200941086a2900003700002007422086200aad842008ad428080808080048410042008102f024020032802a403450d00200a102f0b200341c0026a41086a200341d8046a41086a290300370300200341c0026a41106a200341d8046a41106a290300370300200341c0026a41186a200341d8046a41186a290300370300200320032903d8043703c00241012109410021080c200b200341f8046a41186a200341da066a290100370300200341f8046a41106a200341d2066a290100370300200341f8046a41086a200341ca066a290100370300200341c0026a41086a200341eb066a290000370300200341c0026a41106a200341f3066a290000370300200341c0026a41186a200341fb066a290000370300200320032901c2063703f8042003200341e3066a2900003703c002200341e2066a2d000021090c1f0b2002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a024020022d0000450d00200320073702a403200320083a00a303200320093a00a2032003200a3b01a0030c1d0b200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241086a2d00002115200241066a2f01002116200241056a2d00002117200241046a2d00002118200241026a2f0100211920022d00012102200320073703a003200241ff01714101470d1c200320073703e801200320083a00e701200320093a00e6012003200a3b01e4012003200b3a00e3012003200c3a00e2012003200d3b01e0012003200e3a00df012003200f3a00de01200320103b01dc01200320113a00db01200320123a00da01200320133b01d801200320143a00d701200320153a00d601200320163b01d401200320173a00d301200320183a00d201200320193b01d001419298ca00ad4280808080900184100122022900002107200341a0066a41086a200241086a290000370300200320073703a0062002102f418a93c200ad4280808080b00184100122022900002107200341a0036a41086a200241086a290000370300200320073703a0032002102f4120102d2208450d30200820032903d001370000200841186a200341d0016a41186a290300370000200841106a200341d0016a41106a290300370000200841086a200341d0016a41086a2903003700002008ad42808080808004841003220229001821072002290010210520022d000f210920022d000b210a20022d0007210b20022d0003210c20022f0000210d200241026a2d0000210e20022f0004210f200241066a2d0000211020022f000821112002410a6a2d0000211220022f000c21132002410e6a2d000021142002102f2008102f41c000102d2202450d302002201320144110747222083b002c2002201120124110747222113b00282002200f201041107472220f3b00242002200d200e41107472220d3b0020200220032903a006370000200220032903a0033700102002200737003820022005370030200220093a002f2002200a3a002b2002200b3a00272002200c3a00232002412e6a20084110763a00002002412a6a20114110763a0000200241266a200f4110763a0000200241226a200d4110763a0000200241086a200341a0066a41086a220a290300370000200241186a200341a0036a41086a220b290300370000200341c0006a200241c00041c8e1ca004100410010b501200328024021092002102f41012108024020094101470d00419298ca00ad4280808080900184100122022900002107200a200241086a290000370300200320073703a0062002102f418a93c200ad4280808080b00184100122022900002107200b200241086a290000370300200320073703a0032002102f4120102d2209450d31200920032903d001370000200941186a200341d0016a41186a290300370000200941106a200341d0016a41106a290300370000200941086a200341d0016a41086a2903003700002009ad42808080808004841003220229001821072002290010210520022d000f210a20022d000b210b20022d0007210c20022d0003210d20022f0000210e200241026a2d0000210f20022f00042110200241066a2d0000211120022f000821122002410a6a2d0000211320022f000c21142002410e6a2d000021152002102f2009102f41c000102d2202450d312002201420154110747222093b002c2002201220134110747222123b00282002201020114110747222103b00242002200e200f41107472220e3b0020200220032903a006370000200220032903a00337001020022007370038200220053700302002200a3a002f2002200b3a002b2002200c3a00272002200d3a00232002412e6a20094110763a00002002412a6a20124110763a0000200241266a20104110763a0000200241226a200e4110763a0000200241086a200341a0066a41086a290300370000200241186a200341a0036a41086a290300370000200341a0036a200241c00010cb02024020032d00c10322094102460d002002ad428080808080088410050b200341d8046a41186a220b200341a0036a41186a290300370300200341d8046a41106a220c200341a0036a41106a290300370300200341d8046a41086a220d200341a0036a41086a290300370300200320032903a0033703d80420032d00c003210a200341f8016a200341a0036a41226a41c10010e8061a200341b0016a41086a200d290300370300200341b0016a41106a200c290300370300200341b0016a41186a200b290300370300200320032903d8043703b001200341c0026a200341f8016a41c10010e8061a20094102460d1b200320093a00f804200341f8046a410172200341c0026a41c10010e806210d2003419a056a210b0240024020032d009905220c4101460d0020034100360280060c010b20034180066a200b10b6020b02400240024020094101460d0020034100360290060c010b20034190066a200d10b6022003280290060d010b0240200c4101460d00419298ca00ad4280808080900184100122092900002107200341e0056a41086a220b200941086a290000370300200320073703e0052009102f41f992c200ad4280808080900284100122092900002107200341f0056a41086a220c200941086a290000370300200320073703f0052009102f200341c0056a41086a200b290300370300200341d8056a200c290300370300200320032903e0053703c005200320032903f0053703d005200341a0036a200341c0056a10880120033502a80342208620032802a0032209ad84100520032802a403450d1b2009102f0c1b0b419298ca00ad4280808080900184100122092900002107200341e0056a41086a220c200941086a290000370300200320073703e0052009102f41f992c200ad4280808080900284100122092900002107200341f0056a41086a220d200941086a290000370300200320073703f0052009102f200341c0056a41086a200c290300370300200341c0056a41186a200d290300370300200320032903e0053703c005200320032903f0053703d005200341a0036a200341c0056a10880120032802a003210c20033502a80321074120102d2209450d322009200b290000370000200941186a200b41186a290000370000200941106a200b41106a290000370000200941086a200b41086a2900003700002007422086200cad842009ad428080808080048410042009102f20032802a403450d1a200c102f0c1a0b200341f0056a41086a20034190066a41086a280200220b360200200320032903900622073703f005200341a0066a2007a7220c200b10cb02024020032d00c1064102470d0020034100360298012003420137039001200341c0056a41146a4129360200200341cc056a410b36020020034109360294072003419298ca00360290072003410b3602c4052003410b3602e4052003418a93c2003602e0052003200341f0056a3602d0052003200341e0056a3602c805200320034190076a3602c005200320034190016a36029c07200341a0036a41146a4103360200200342033702a4032003419090c4003602a0032003200341c0056a3602b0032003419c076a41d8dbc100200341a0036a103c1a200335029801422086200335029001841008200328029401450d19200328029001102f0c190b200341a0036a200341a0066a41c20010e8061a20034182046a20034199056a220941206a2d00003a0000200341fa036a200941186a290000370100200341f2036a200941106a290000370100200341ea036a200941086a290000370100200341a0036a41c2006a2009290000370100200341003602c805200342013703c0054120102d2209450d31200920032903a003370000200941086a200341a0036a41086a290300370000200941106a200341a0036a41106a290300370000200941186a200341a0036a41186a290300370000200342a080808080043702c405200320093602c005024020032d00c003220d41064b0d0002400240024002400240024002400240200d0e0700010203040506000b4100210d0c060b4101210d0c050b4102210d0c040b4103210d0c030b4104210d0c020b4105210d0c010b4106210d0b2003200d3a00e0052009412041c00010312209450d322009200d3a0020200342c080808090043702c405200320093602c0050b200341c1036a200341c0056a10ce0220032802c4052109200bad422086200cad8420033502c80542208620032802c005220bad8410042009450d18200b102f0c180b20004183143b0100200041086a410c360200200041046a41a494c200360200200041026a410d3a00000c320b024020022d000120022d0000410047720d00419298ca00ad4280808080900184100122022900002107200229000821052002102f41aba8c200ad4280808080b001841001220229000021062002290008211a2002102f2003201a3703c801200320063703c001200320053703b801200320073703b001200341b0016aad42808080808004841005200041043a0000410121080c320b200041023a0000410121080c310b2001410c6a2802002121200141086a280200210c200141046a280200210b2002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a200241156a2d0000210d200241146a2d0000210e200241126a2f0100210f200241116a2d00002110200241106a2d000021112002410e6a2f010021122002410d6a2d000021132002410c6a2d000021142002410a6a2f01002115200241096a2d00002116200241086a2d00002117200241066a2f01002118200241056a2d00002119200241046a2d0000211f200241026a2f010021200240024020022d0000450d00200320073702a403200320083a00a303200320093a00a2032003200a3b01a003410121020c010b20022d00012102200320073703a003200241ff017141014721020b200320073703c801200320083a00c701200320093a00c6012003200a3b01c4012003200d3a00c3012003200e3a00c2012003200f3b01c001200320103a00bf01200320113a00be01200320123b01bc01200320133a00bb01200320143a00ba01200320153b01b801200320163a00b701200320173a00b601200320183b01b401200320193a00b3012003201f3a00b201200320203b01b00102400240024020020d00200341c0026a41186a200341b0016a41186a290300370300200341c0026a41106a200341b0016a41106a290300370300200341c0026a41086a200341b0016a41086a290300370300200320032903b0013703c0022021ad221a422086200bad84100322022900002107200241086a2900002105200241106a2900002106200341f8046a41186a2209200241186a290000370300200341f8046a41106a220a2006370300200341f8046a41086a220d2005370300200320073703f8042002102f419298ca00ad4280808080900184100122022d000f210e20022d000e210f20022f000c211020022d000b211120022d000a211220022f0008211320022d0007211420022d0006211520022f0004211620022d0003211720022d0002211820022f000021192002102f4199a8c200ad428080808090018410012202290008210720022d0007211f20022d0006212020022f0004212220022d0003212320022d0002212420022f000021252002102f4120102d2208450d31200820032903f804370000200841186a2009290300370000200841106a200a290300370000200841086a200d2903003700002008ad428080808080048410032202290018210520022d0017210920022d0016210a20022f0014210d20022d0013212620022d0012212720022f0010212820022d000f212920022d000e212a20022f000c212b20022d000b212c20022d000a212d20022f0008212e20022d0007212f20022d0006213020022f0004213120022d0003213220022d0002213320022f000021342002102f2008102f41c000102d2202450d3120022005370038200220093a00372002200a3a00362002200d3b0034200220263a0033200220273a0032200220283b0030200220293a002f2002202a3a002e2002202b3b002c2002202c3a002b2002202d3a002a2002202e3b00282002202f3a0027200220303a0026200220313b0024200220323a0023200220333a0022200220343b0020200220073700182002201f3a0017200220203a0016200220223b0014200220233a0013200220243a0012200220253b00102002200e3a000f2002200f3a000e200220103b000c200220113a000b200220123a000a200220133b0008200220143a0007200220153a0006200220163b0004200220173a0003200220183a0002200220193b0000200341e0006a200241c00041c8e1ca004100410010b501200328026021082002102f20084101460d11200341d0006a201a42004280a094a58d1d420010ed062003200341d8006a2903002207370380022003200329035022053703f8012003200341c0026a3602d001410421022021450d022003200341c0026a3602d8042003200341d8046a3602a8032003200341d0016a3602a4032003200341f8016a3602a003200341a0066a200341c0026a200341a0036a10940120032802a0064101470d01200320032900a5063703a0032003200341ac066a2800003600a70320032d00a40621020c020b200041023a00000c160b41042102200341a0066a41086a2903004201520d00200341a0066a41106a290300210620032802d8042108200341d8036a200341a0066a41186a290300370300200341d0036a2006370300200341a0036a41086a41003a0000200341a9036a2008290000370000200341b1036a200841086a290000370000200341b9036a200841106a290000370000200341c1036a200841186a290000370000200341033a00a00341c8e1ca004100200341a0036a108c010b200320032903a0033703c005200320032800a7033600c7050240200241ff01714104470d00200341a0036a41186a22094200370300200341a0036a41106a220a4200370300200341a0036a41086a22024200370300200342003703a003418de6c300ad4280808080e000841001220829000021062002200841086a290000370300200320063703a0032008102f419ce6c300ad4280808080e00084100122082900002106200341d8046a41086a220d200841086a290000370300200320063703d8042008102f200a20032903d8042206370300200341a0066a41086a22082002290300370300200341a0066a41106a220a2006370300200341a0066a41186a220e200d290300370300200320032903a0033703a006200341c8006a200341a0066a4120109501200328024c210d2003280248210f200e200341f8046a41186a2210290300370300200a200341f8046a41106a220e2903003703002008200341f8046a41086a220a290300370300200320032903f8043703a00620092021360200200341b4036a200c360200200341c4036a200341c0026a41086a2209290300370200200341cc036a200341c0026a41106a220c290300370200200341d4036a200341c0026a41186a2211290300370200200320073703a803200320053703a0032003200b3602b003200320032903c0023702bc03410021082003200d4100200f1b3602dc03200341a0066a200341a0036a10cf02200341f8036a2007370300200341f0036a20053703002002410b3a0000200341a9036a20032903f804370000200341b1036a200a290300370000200341b9036a200e290300370000200341c1036a2010290300370000200341c9036a20032903c002370000200341d1036a2009290300370000200341d9036a200c290300370000200341e1036a2011290300370000200341063a00a00341c8e1ca004100200341a0036a108c01200041043a00000c310b200020023a0000200020032903c005370001200041086a20032800c7053600000c140b2001410c6a2802002123200141086a2802002122200141046a28020021212002411a6a2901002107200241196a2d0000210a200241186a2d0000210b200241166a2f0100210c200241156a2d0000210d200241146a2d0000210e200241126a2f0100210f200241116a2d00002110200241106a2d000021112002410e6a2f010021122002410d6a2d000021132002410c6a2d000021142002410a6a2f01002115200241096a2d00002116200241086a2d00002117200241066a2f01002118200241056a2d00002119200241046a2d0000211f200241026a2f010021200240024020022d0000450d00200320073702a4032003200a3a00a3032003200b3a00a2032003200c3b01a003410121020c010b20022d00012102200320073703a003200241ff017141014721020b200320073703c8012003200a3a00c7012003200b3a00c6012003200c3b01c4012003200d3a00c3012003200e3a00c2012003200f3b01c001200320103a00bf01200320113a00be01200320123b01bc01200320133a00bb01200320143a00ba01200320153b01b801200320163a00b701200320173a00b601200320183b01b401200320193a00b3012003201f3a00b201200320203b01b0010240024020020d002023ad4220862021ad84100322022900002105200241086a2900002106200241106a290000211a200341f8046a41186a2209200241186a290000370300200341f8046a41106a2224201a370300200341f8046a41086a22252006370300200320053703f8042002102f419298ca00ad4280808080900184100122022d000f212620022d000e212720022f000c212820022d000b212920022d000a212a20022f0008212b20022d0007212c20022d0006212d20022f0004212e20022d0003212f20022d0002213020022f000021312002102f4199a8c200ad428080808090018410012202290008210520022d0007213220022d0006213320022f0004213420022d0003213520022d0002213620022f000021372002102f4120102d2208450d2f200820032903f804370000200841186a2009290300370000200841106a2024290300370000200841086a20252903003700002008ad428080808080048410032202290018210620022d0017210920022d0016212420022f0014212520022d0013213820022d0012213920022f0010213a20022d000f213b20022d000e213c20022f000c213d20022d000b213e20022d000a213f20022f0008214020022d0007214120022d0006214220022f0004214320022d0003214420022d0002214520022f000021462002102f2008102f41c000102d2202450d2f20022006370038200220093a0037200220243a0036200220253b0034200220383a0033200220393a00322002203a3b00302002203b3a002f2002203c3a002e2002203d3b002c2002203e3a002b2002203f3a002a200220403b0028200220413a0027200220423a0026200220433b0024200220443a0023200220453a0022200220463b002020022005370018200220323a0017200220333a0016200220343b0014200220353a0013200220363a0012200220373b0010200220263a000f200220273a000e200220283b000c200220293a000b2002202a3a000a2002202b3b00082002202c3a00072002202d3a00062002202e3b00042002202f3a0003200220303a0002200220313b0000200341f0006a200241c00041c8e1ca004100410010b501200328027021082002102f20084101460d10200341a0036a41186a4200370300200341a0036a41106a22244200370300200341a0036a41086a22024200370300200342003703a003419298ca00ad42808080809001841001220829000021052002200841086a290000370300200320053703a0032008102f418ca8c200ad4280808080d00184100122082900002105200341d8046a41086a2209200841086a290000370300200320053703d8042008102f202420032903d8042205370300200341a0066a41086a2002290300370300200341a0066a41106a2005370300200341a0066a41186a2009290300370300200320032903a0033703a006200341a0036a200341a0066a10c90220032802a0032202410420021b222520032902a403420020021b2205422088a741286c6a210920252102034020022009460d020240200341f8046a200241046a2208460d00200841246a21022008200341f8046a412010ea060d010b0b200341a0036a41186a22024200370300200341a0036a41106a22264200370300200341a0036a41086a22084200370300200342003703a003418de6c300ad4280808080e000841001220929000021062008200941086a290000370300200320063703a0032009102f419ce6c300ad4280808080e00084100122092900002106200341d8046a41086a2227200941086a290000370300200320063703d8042009102f202420032903d804370000202441086a2027290300370000200341a0066a41086a22092008290300370300200341a0066a41106a22242026290300370300200341a0066a41186a22262002290300370300200320032903a0033703a006200341e8006a200341a0066a4120109501200328026c2127200328026821282026200341f8046a41186a22292903003703002024200341f8046a41106a22262903003703002009200341f8046a41086a2224290300370300200320032903f8043703a006200341d4036a22092007370200200341d3036a222a200a3a0000200341d2036a200b3a0000200341d0036a222b200c3b0100200341cf036a222c200d3a0000200341ce036a200e3a0000200341cc036a222d200f3b0100200341cb036a222e20103a0000200341ca036a20113a0000200341c8036a20123b0100200341c7036a20133a0000200341c6036a20143a0000200341c4036a20153b0100200341c3036a20163a0000200341c2036a20173a0000200341a0036a41206a20183b0100200341bf036a20193a0000200341be036a201f3a000020022023360200200341b4036a2022360200200320203b01bc03200320213602b003200342003703a803200342003703a0034100210220032027410020281b3602dc03200341a0066a200341a0036a10cf02200341f8036a4200370300200341f0036a42003703002008410b3a0000200341a9036a20032903f804370000200341b1036a2024290300370000200341b9036a2026290300370000200341c1036a2029290300370000200341e1036a2007370000200341e0036a200a3a0000200341df036a200b3a0000200341dd036a200c3b0000200341dc036a200d3a0000200341db036a200e3a0000200341d9036a200f3b0000200341d8036a20103a0000200341d7036a20113a0000200341d5036a20123b0000200920133a0000202a20143a0000200341d1036a20153b0000202b20163a0000202c20173a0000200341cd036a20183b0000202d20193a0000202e201f3a0000200341c9036a20203b0000200341063a00a00341c8e1ca004100200341a0036a108c0102402005a7450d002025102f0b200041043a0000410121080c320b200041023a00000c130b20004183143b0100200041086a410b360200200041046a418894c200360200200041026a410f3a00002005a7450d122025102f0c120b200341c0056a41186a200141196a290000370300200341c0056a41106a200141116a290000370300200341c0056a41086a200141096a290000370300200320012900013703c0052002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241086a2d00002115200241066a2f01002116200241056a2d00002117200241046a2d00002118200241026a2f010021190240024020022d0000450d00200320073702a403200320083a00a303200320093a00a2032003200a3b01a003410121020c010b20022d00012102200320073703a003200241ff017141014721020b200320073703c801200320083a00c701200320093a00c6012003200a3b01c4012003200b3a00c3012003200c3a00c2012003200d3b01c0012003200e3a00bf012003200f3a00be01200320103b01bc01200320113a00bb01200320123a00ba01200320133b01b801200320143a00b701200320153a00b601200320163b01b401200320173a00b301200320183a00b201200320193b01b00102400240024020020d00200341f8016a41186a200341b0016a41186a290300370300200341f8016a41106a200341b0016a41106a290300370300200341f8016a41086a200341b0016a41086a290300370300200320032903b0013703f801419298ca00ad4280808080900184100122022d000f210920022d000e210a20022f000c210b20022d000b210c20022d000a210d20022f0008210e20022d0007210f20022d0006211020022f0004211120022d0003211220022d0002211320022f000021142002102f4199a8c200ad428080808090018410012202290008210720022d0007211520022d0006211620022f0004211720022d0003211820022d0002211920022f0000211f2002102f4120102d2208450d2f200820032903c005370000200841186a200341c0056a41186a290300370000200841106a200341c0056a41106a290300370000200841086a200341c0056a41086a2903003700002008ad428080808080048410032202290018210520022d0017212020022d0016212120022f0014212220022d0013212320022d0012212420022f0010212520022d000f212620022d000e212720022f000c212820022d000b212920022d000a212a20022f0008212b20022d0007212c20022d0006212d20022f0004212e20022d0003212f20022d0002213020022f000021312002102f2008102f41c000102d2202450d2f20022005370038200220203a0037200220213a0036200220223b0034200220233a0033200220243a0032200220253b0030200220263a002f200220273a002e200220283b002c200220293a002b2002202a3a002a2002202b3b00282002202c3a00272002202d3a00262002202e3b00242002202f3a0023200220303a0022200220313b002020022007370018200220153a0017200220163a0016200220173b0014200220183a0013200220193a00122002201f3b0010200220093a000f2002200a3a000e2002200b3b000c2002200c3a000b2002200d3a000a2002200e3b00082002200f3a0007200220103a0006200220113b0004200220123a0003200220133a0002200220143b0000200341a0036a200210b202200341a0066a41086a2208200341a0036a41206a290300370300200341a0066a41106a2209200341c8036a290300370300200341a0066a41186a220a200341d0036a290300370300200341a0066a41206a220b200341d8036a2802003602002003200341a0036a41186a2903003703a006024020032802b003220c450d00200341a0036a41086a2903002105200341dc036a280200210d20032903a003210620032802b403210e200341f8046a41206a200b280200360200200341f8046a41186a200a290300370300200341f8046a41106a2009290300370300200341f8046a41086a2008290300370300200320032903a0063703f8042002102f200341c0026a41186a20034194056a290200370300200341c0026a41106a2003418c056a290200370300200341c0026a41086a20034184056a290200370300200320032902fc043703c0020240200e450d00200c102f0b200341a0036a41186a220b4200370300200341a0036a41106a22084200370300200341a0036a41086a22024200370300200342003703a003418de6c300ad4280808080e000841001220929000021072002200941086a290000370300200320073703a0032009102f419ce6c300ad4280808080e00084100122092900002107200341d8046a41086a220a200941086a290000370300200320073703d8042009102f200820032903d8042207370300200341a0066a41086a22092002290300370300200341a0066a41106a220c2007370300200341a0066a41186a220e200a290300370300200320032903a0033703a006200341f8006a200341a0066a4120109501200328027c410020032802781b200d4180de344100200341f8016a200341c0026a412010ea061b6a41809c316a490d02200b42003703002008420037030020024200370300200342003703a003419298ca00ad42808080809001841001220d29000021072002200d41086a290000370300200320073703a003200d102f418ca8c200ad4280808080d001841001220d2900002107200a200d41086a290000370300200320073703d804200d102f200820032903d804370000200841086a200a29030037000020092002290300370300200c2008290300370300200e200b290300370300200320032903a0033703a006200341a0036a200341a0066a10c90220032802a0032202410420021b220a20032902a403420020021b2207422088a741286c6a2109200a2102034020022009460d040240200341c0056a200241046a2208460d00200841246a21022008200341c0056a412010ea060d010b0b20004183143b0100200041086a4108360200200041046a41fb93c200360200200041026a41113a00002007a7450d2a200a102f410121080c320b2002102f200041086a410f360200200041046a41ec93c200360200200041026a41123a000020004183143b0100410121080c310b200041023a0000410121080c300b20004183143b0100200041086a4105360200200041046a418394c200360200200041026a41103a0000410121080c2f0b200341a0036a200341c0026a200341f8016a20062005410010bc01419298ca00ad4280808080900184100122022d000f210920022d000e210b20022f000c210c20022d000b210d20022d000a210e20022f0008210f20022d0007211020022d0006211120022f0004211220022d0003211320022d0002211420022f000021152002102f4199a8c200ad428080808090018410012202290008211a20022d0007211620022d0006211720022f0004211820022d0003211920022d0002211f20022f000021202002102f4120102d2208450d2c200820032903c005370000200841186a200341c0056a41186a2221290300370000200841106a200341c0056a41106a2222290300370000200841086a200341c0056a41086a22232903003700002008ad428080808080048410032202290018211b20022d0017212420022d0016212520022f0014212620022d0013212720022d0012212820022f0010212920022d000f212a20022d000e212b20022f000c212c20022d000b212d20022d000a212e20022f0008212f20022d0007213020022d0006213120022f0004213220022d0003213320022d0002213420022f000021352002102f2008102f41c000102d2202450d2c2002201b370038200220243a0037200220253a0036200220263b0034200220273a0033200220283a0032200220293b00302002202a3a002f2002202b3a002e2002202c3b002c2002202d3a002b2002202e3a002a2002202f3b0028200220303a0027200220313a0026200220323b0024200220333a0023200220343a0022200220353b00202002201a370018200220163a0017200220173a0016200220183b0014200220193a00132002201f3a0012200220203b0010200220093a000f2002200b3a000e2002200c3b000c2002200d3a000b2002200e3a000a2002200f3b0008200220103a0007200220113a0006200220123b0004200220133a0003200220143a0002200220153b00002002ad428080808080088410052002102f200341a0036a41086a410f3a0000200341a9036a20032903c005370000200341b1036a2023290300370000200341b9036a2022290300370000200341c1036a2021290300370000200341c9036a20032903c002370000200341d1036a200341c0026a41086a290300370000200341d9036a200341c0026a41106a290300370000200341e1036a200341c0026a41186a290300370000200341063a00a00320034190046a200637030020034198046a200537030020034181046a200341f8016a41186a290300370000200341f9036a200341f8016a41106a290300370000200341f1036a200341f8016a41086a290300370000200341e9036a20032903f80137000041c8e1ca004100200341a0036a108c0102402007a7450d00200a102f0b200041043a0000410121080c2e0b200341f8046a41186a200141196a29000037030020034188056a200141116a29000037030020034180056a200141096a290000370300200320012900013703f8042002411a6a2901002107024020022d0000450d00200241196a2d00002108200241186a2d00002109200241166a2f01002102200320073702a403200320083a00a303200320093a00a203200320023b01a0030c100b20022d00012102200320073703a003200241ff01714101470d0f419298ca00ad4280808080900184100122022900002107200341a0066a41086a200241086a290000370300200320073703a0062002102f41f9b5c600ad4280808080d00084100122022900002107200341a0036a41086a200241086a290000370300200320073703a0032002102f4120102d2202450d2b200220032903f804370000200241186a200341f8046a41186a290300370000200241106a200341f8046a41106a290300370000200241086a200341f8046a41086a2903003700002002ad4280808080800484100322082900002107200841086a2900002105200841106a2900002106200341b0016a41186a2209200841186a290000370300200341b0016a41106a220a2006370300200341b0016a41086a2005370300200320073703b0012008102f2002102f41c000102d2202450d2b200220032903a006370000200241086a200341a0066a41086a220b290300370000200220032903a003370010200241186a200341a0036a41086a2208290300370000200220032903b001370020200241286a200341b0016a41086a290300370000200241306a200a290300370000200241386a200929030037000020034188016a200241c000109501200328028c01210a20032802880121092002102f2009450d0d200341a0036a41186a4200370300200341a0036a41106a2209420037030020084200370300200342003703a003418de6c300ad4280808080e000841001220229000021072008200241086a290000370300200320073703a0032002102f419ce6c300ad4280808080e00084100122022900002107200341d8046a41086a220c200241086a290000370300200320073703d8042002102f200920032903d8042207370300200b2008290300370300200341a0066a41106a2007370300200341a0066a41186a200c290300370300200320032903a0033703a00620034180016a200341a0066a41201095010240200a20032802840141002003280280011b4b0d00200342e4cab5fbb6ccdcb0e3003703c002200341c0026a200341f8046a10b101419298ca00ad4280808080900184100122022d000f210920022d000e210a20022f000c210b20022d000b210c20022d000a210d20022f0008210e20022d0007210f20022d0006211020022f0004211120022d0003211220022d0002211320022f000021142002102f41f9b5c600ad4280808080d0008410012202290008210720022d0007211520022d0006211620022f0004211720022d0003211820022d0002211920022f0000211f2002102f4120102d2208450d2c200820032903f804370000200841186a200341f8046a41186a2220290300370000200841106a200341f8046a41106a2221290300370000200841086a200341f8046a41086a22222903003700002008ad428080808080048410032202290018210520022d0017212320022d0016212420022f0014212520022d0013212620022d0012212720022f0010212820022d000f212920022d000e212a20022f000c212b20022d000b212c20022d000a212d20022f0008212e20022d0007212f20022d0006213020022f0004213120022d0003213220022d0002213320022f000021342002102f2008102f41c000102d2202450d2c20022005370038200220233a0037200220243a0036200220253b0034200220263a0033200220273a0032200220283b0030200220293a002f2002202a3a002e2002202b3b002c2002202c3a002b2002202d3a002a2002202e3b00282002202f3a0027200220303a0026200220313b0024200220323a0023200220333a0022200220343b002020022007370018200220153a0017200220163a0016200220173b0014200220183a0013200220193a00122002201f3b0010200220093a000f2002200a3a000e2002200b3b000c2002200c3a000b2002200d3a000a2002200e3b00082002200f3a0007200220103a0006200220113b0004200220123a0003200220133a0002200220143b00002002ad428080808080088410052002102f200341a0036a41086a41103a0000200341a9036a20032903f804370000200341b1036a2022290300370000200341b9036a2021290300370000200341c1036a2020290300370000200341063a00a00341c8e1ca004100200341a0036a108c01200041043a0000410121080c2e0b20004183143b0100200041086a410a360200200041046a41ae93c200360200200041026a41173a0000410121080c2d0b2002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a024020022d0000450d00200320073702a403200320083a00a303200320093a00a2032003200a3b01a0030c0e0b2001410f6a2d0000210f2001410d6a2f000021102001410b6a2d00002111200141096a2f00002112200141076a2d00002113200141056a2f00002114200141036a2d0000211520012f00012116200141196a2900002106200141116a2900002105200141106a2d0000210b2001410c6a2d0000210c200141086a2d0000210d200141046a2d0000210e200241156a2d00002117200241146a2d00002118200241126a2f01002119200241116a2d0000211f200241106a2d000021202002410e6a2f010021212002410d6a2d000021222002410c6a2d000021232002410a6a2f01002124200241096a2d00002125200241086a2d00002126200241066a2f01002127200241056a2d00002128200241046a2d00002129200241026a2f0100212a20022d00012102200320073703a003200241ff01714101470d0d200320073703b806200320083a00b706200320093a00b6062003200a3b01b406200320173a00b306200320183a00b206200320193b01b0062003201f3a00af06200320203a00ae06200320213b01ac06200320223a00ab06200320233a00aa06200320243b01a806200320253a00a706200320263a00a606200320273b01a406200320283a00a306200320293a00a2062003202a3b01a006419298ca00ad4280808080900184100122022d000f210920022d000e210a20022f000c211720022d000b211820022d000a211920022f0008211f20022d0007212020022d0006212120022f0004212220022d0003212320022d0002212420022f000021252002102f41d49ac800ad4280808080d0008410012202290008210720022d0007212620022d0006212720022f0004212820022d0003212920022d0002212a20022f0000212b2002102f4120102d2208450d2a200820032903a006370000200841186a200341a0066a41186a290300370000200841106a200341a0066a41106a290300370000200841086a200341a0066a41086a2903003700002008ad428080808080048410032202290018211a20022d0017212c20022d0016212d20022f0014212e20022d0013212f20022d0012213020022f0010213120022d000f213220022d000e213320022f000c213420022d000b213520022d000a213620022f0008213720022d0007213820022d0006213920022f0004213a20022d0003213b20022d0002213c20022f0000213d2002102f2008102f41c000102d2202450d2a2002201a3700382002202c3a00372002202d3a00362002202e3b00342002202f3a0033200220303a0032200220313b0030200220323a002f200220333a002e200220343b002c200220353a002b200220363a002a200220373b0028200220383a0027200220393a00262002203a3b00242002203b3a00232002203c3a00222002203d3b002020022007370018200220263a0017200220273a0016200220283b0014200220293a00132002202a3a00122002202b3b0010200220093a000f2002200a3a000e200220173b000c200220183a000b200220193a000a2002201f3b0008200220203a0007200220213a0006200220223b0004200220233a0003200220243a0002200220253b0000200341a0036a200210c70220032d00a003211720032010200f4110747222083b01bc01200341be016a20084110763a00002003201220114110747222093b01b801200341ba016a20094110763a000020032014201341107472220a3b01b401200341b6016a200a4110763a0000200320063702c801200320053702c0012003200b3a00bf012003200c3a00bb012003200d3a00b7012003200e3a00b30120032016201541107472220f3b01b0012003200f4110763a00b2010240024020174102460d00200f418080fc07714110762110200a418080fc077141107621112009418080fc077141107621122008418080fc077141107621132005421088a721142005421888a721152005422088a721162005423088a721172005423888a721182005a721190c010b200341a0066a10d00220032902c801210620032d00c701211820032d00c601211720032f01c401211620032d00c301211520032d00c201211420032f01c001211920032d00bf01210b20032d00be01211320032f01bc01210820032d00bb01210c20032d00ba01211220032f01b801210920032d00b701210d20032d00b601211120032f01b401210a20032d00b301210e20032d00b201211020032f01b001210f0b200341003a00e0054101102d2203450d2a200341003a000020034101412110312203450d2a20032006370019200320183a0018200320173a0017200320163b0015200320153a0014200320143a0013200320193b00112003200b3a0010200320133a000f200320083b000d2003200c3a000c200320123a000b200320093b00092003200d3a0008200320113a00072003200a3b00052003200e3a0004200320103a00032003200f3b00012002ad42808080808008842003ad428080808090048410042003102f2002102f200041043a0000410121080c2c0b20004183143b0100200041086a410f360200200041046a418095c200360200200041026a41043a00000c2b0b20004183143b0100200041086a4108360200200041046a419f95c200360200200041026a41003a0000410121080c2a0b20082002104b000b2002200b104a000b2009200b104b000b200341c0056a41146a4109360200200341cc056a410a360200200341f8016a41146a4103360200200320034180066a3602e005200320034190066a3602f005200341a0036a41146a4100360200200342033702fc01200341b4e0ca003602f8012003410a3602c405200341c8e1ca003602b003200342013702a40320034188e1ca003602a0032003200341c0056a360288022003200341a0036a3602d0052003200341f0056a3602c8052003200341e0056a3602c005200341f8016a41c8e1ca001043000b200041086a4108360200200041046a418f95c200360200200041026a41033a000020004183143b0100410121080c250b200041023a0000410121080c240b419ae3c300411e41f8b4ca001039000b4188bbca00200a200b103b000b20004183143b0100200041086a4111360200200041046a419394c200360200200041026a410e3a00000c050b20004183143b0100200041086a4111360200200041046a419394c200360200200041026a410e3a00000c030b20004183143b0100200041086a4109360200200041046a41b893c200360200200041026a41163a0000410121080c1f0b200041023a0000410121080c1e0b200041023a0000410121080c1d0b41002102410121082022450d1d2021102f0c1d0b4101210241002108200c450d1c200b102f0c1c0b024020032802f405450d0020032802f005102f0b4101210c0c010b4100210c0b0240024020032802800622090d004100210b0c010b200341f0056a41086a20034180066a41086a280200220d360200200320032903800622073703f005200341a0066a2007a7220e200d10cb020240024020032d00c1064102470d0020034100360298012003420137039001200341c0056a41146a4129360200200341cc056a410b36020020034109360294072003419298ca00360290072003410b3602c4052003410b3602e4052003418a93c2003602e0052003200341f0056a3602d0052003200341e0056a3602c805200320034190076a3602c005200320034190016a36029c07200341a0036a41146a4103360200200342033702a403200341b48fc4003602a0032003200341c0056a3602b0032003419c076a41d8dbc100200341a0036a103c1a200335029801422086200335029001841008200328029401450d01200328029001102f0c010b200341a0036a200341a0066a41e30010e8061a200341e1036a200341f8046a41206a2d00003a0000200341d9036a200341f8046a41186a290300370000200341d1036a200341f8046a41106a290300370000200341c9036a200341f8046a41086a290300370000200320032903f8043700c103200341003602c805200342013703c0054120102d220b450d18200b20032903a003370000200b41086a200341a0036a41086a290300370000200b41106a200341a0036a41106a290300370000200b41186a200341a0036a41186a290300370000200342a080808080043702c4052003200b3602c005024020032d00c003220f41064b0d0002400240024002400240024002400240200f0e0700010203040506000b200341003a00e0050c060b200341013a00e0050c050b200341023a00e0050c040b200341033a00e0050c030b200341043a00e0050c020b200341053a00e0050c010b200341063a00e0050b200b412041c0001031220b450d19200b20032d00e0053a00202003200b3602c005200342c080808090043702c4050b200341c1036a200341c0056a10ce0220032802c405210b200dad422086200ead8420033502c80542208620032802c005220dad841004200b450d00200d102f0b024020032802f405450d0020032802f005102f0b4101210b0b0240200c200328029006220d45720d00200328029406450d00200d102f0b0240200b200945720d00200328028406450d002009102f0b200a41ff01714107470d010b4100210a0b2002102f200341a0036a41186a4200370300200341a0036a41106a220b4200370300200341a0036a41086a22024200370300200342003703a003418de6c300ad4280808080e000841001220929000021072002200941086a290000370300200320073703a0032009102f419ce6c300ad4280808080e00084100122092900002107200341d8046a41086a220c200941086a290000370300200320073703d8042009102f200b20032903d8042207370300200341a0066a41086a2002290300370300200341a0066a41106a2007370300200341a0066a41186a200c290300370300200320032903a0033703a006200341386a200341a0066a4120109501200328023c210b2003280238210c419298ca00ad4280808080900184100122022d000f210d20022d000e210e20022f000c210f20022d000b211020022d000a211120022f0008211220022d0007211320022d0006211420022f0004211520022d0003211620022d0002211720022f000021182002102f41f9b5c600ad4280808080d0008410012202290008210720022d0007211920022d0006211f20022f0004212020022d0003212120022d0002212220022f000021232002102f4120102d2209450d14200920032903d001370000200941186a200341d0016a41186a290300370000200941106a200341d0016a41106a290300370000200941086a200341d0016a41086a2903003700002009ad428080808080048410032202290018210520022d0017212420022d0016212520022f0014212620022d0013212720022d0012212820022f0010212920022d000f212a20022d000e212b20022f000c212c20022d000b212d20022d000a212e20022f0008212f20022d0007213020022d0006213120022f0004213220022d0003213320022d0002213420022f000021352002102f2009102f41c000102d2202450d1420022005370038200220243a0037200220253a0036200220263b0034200220273a0033200220283a0032200220293b00302002202a3a002f2002202b3a002e2002202c3b002c2002202d3a002b2002202e3a002a2002202f3b0028200220303a0027200220313a0026200220323b0024200220333a0023200220343a0022200220353b002020022007370018200220193a00172002201f3a0016200220203b0014200220213a0013200220223a0012200220233b00102002200d3a000f2002200e3a000e2002200f3b000c200220103a000b200220113a000a200220123b0008200220133a0007200220143a0006200220153b0004200220163a0003200220173a0002200220183b00002003200a41187441187541027441d897ca006a2802004180de346c200b4100200c1b6a3602a0032002ad4280808080800884200341a0036aad4280808080c0008410042002102f200342e4cab5fbb6ccdcb0e3003703f001200341f0016a200341d0016a427f427f410210b001200341a0036a41086a41093a0000200341a0036a41096a20032903d001370000200341b1036a200341d0016a41086a290300370000200341b9036a200341e0016a290300370000200341c1036a200341e8016a290300370000200341063a00a00341c8e1ca004100200341a0036a108c01200041043a00000c160b200041023a0000410121080c150b41002109410021080b200341a9036a20032903f804370000200341c9036a20093a0000200341ca036a20032903c002370100200341b1036a200341f8046a41086a290300370000200341b9036a200341f8046a41106a290300370000200341c1036a200341f8046a41186a290300370000200341d2036a200341c0026a41086a290300370100200341da036a200341c0026a41106a290300370100200341e2036a200341c0026a41186a290300370100200320083a00a8032003200b3a00a403200320034190016a3602a003200341003602a806200342013703a0064120102d2208450d112008200329039001370000200841086a20034190016a41086a290300370000200841106a20034190016a41106a290300370000200841186a20034190016a41186a290300370000200342a080808080043702a406200320083602a0060240200b41064b0d0002400240024002400240024002400240200b0e0700010203040506000b200341003a00e0050c060b200341013a00e0050c050b200341023a00e0050c040b200341033a00e0050c030b200341043a00e0050c020b200341053a00e0050c010b200341063a00e0050b2008412041c00010312208450d12200820032d00e0053a0020200320083602a006200342c080808090043702a4060b200341a0036a41086a200341a0066a10ce0220032802a40621082002ad428080808080088420033502a80642208620032802a0062209ad84100402402008450d002009102f0b2002102f200342e4cab5fbb6ccdcb0e3003703900620034190066a200341d0016a10d202419298ca00ad4280808080900184100122022d000f210920022d000e210a20022f000c210b20022d000b210c20022d000a210d20022f0008210e20022d0007210f20022d0006211020022f0004211120022d0003211220022d0002211320022f000021142002102f41f9b5c600ad4280808080d0008410012202290008210720022d0007211520022d0006211620022f0004211720022d0003211820022d0002211920022f0000211f2002102f4120102d2208450d11200820032903d001370000200841186a200341d0016a41186a2220290300370000200841106a200341d0016a41106a2221290300370000200841086a200341d0016a41086a22222903003700002008ad428080808080048410032202290018210520022d0017212320022d0016212420022f0014212520022d0013212620022d0012212720022f0010212820022d000f212920022d000e212a20022f000c212b20022d000b212c20022d000a212d20022f0008212e20022d0007212f20022d0006213020022f0004213120022d0003213220022d0002213320022f000021342002102f2008102f41c000102d2202450d1120022005370038200220233a0037200220243a0036200220253b0034200220263a0033200220273a0032200220283b0030200220293a002f2002202a3a002e2002202b3b002c2002202c3a002b2002202d3a002a2002202e3b00282002202f3a0027200220303a0026200220313b0024200220323a0023200220333a0022200220343b002020022007370018200220153a0017200220163a0016200220173b0014200220183a0013200220193a00122002201f3b0010200220093a000f2002200a3a000e2002200b3b000c2002200c3a000b2002200d3a000a2002200e3b00082002200f3a0007200220103a0006200220113b0004200220123a0003200220133a0002200220143b00002002ad428080808080088410052002102f200341a0036a41086a41083a0000200341a9036a20032903d001370000200341b1036a2022290300370000200341b9036a2021290300370000200341c1036a2020290300370000200341c9036a200329039001370000200341d1036a20034190016a41086a290300370000200341d9036a20034190016a41106a290300370000200341e1036a20034190016a41186a290300370000200341063a00a00341c8e1ca004100200341a0036a108c01200041043a0000410121080c130b200041023a0000410121080c120b200041023a0000410121080c110b200041023a0000410121080c100b2008417f6a200b4f0d00200b20086b2202200b490d01201b42ffffffff0f83211b0b20004183143b0100200041086a410f360200200041046a41b1d5c70036020041012108200041026a41013a0000201ba7450d0e2019102f0c0e0b419298ca00ad4280808080900184100122082900002107200829000821052008102f418ca8c200ad4280808080d001841001220829000021062008290008211a2008102f2003201a3703c801200320063703c001200320053703b801200320073703b001200341a0036a20192002108101200341b0016aad428080808080048420033502a80342208620032802a0032202ad841004024020032802a403450d002002102f0b0240201ba7450d002019102f0b200041043a0000410121080c0d0b200341a0036a41186a200341f8046a41186a290300370300200341a0036a41106a200341f8046a41106a290300370300200341a0036a41086a200341f8046a41086a290300370300200320032903f8043703a003200341a0036a21084100210a0b02402009200b470d0020112009470d00201141016a22022011490d022011410174220b2002200b20024b1b220241ffffff3f712002470d02200241057422024100480d020240024020110d002002102d21100c010b201020114105742002103121100b2010450d0a200241057621110b2010200a4105746a220241206a20022009200a6b41057410e9061a200241186a200841186a290000370000200241106a200841106a290000370000200241086a200841086a29000037000020022008290000370000200341a0036a41186a4200370300200341a0036a41106a220a4200370300200341a0036a41086a22024200370300200342003703a003418de6c300ad4280808080e000841001220829000021072002200841086a290000370300200320073703a0032008102f419ce6c300ad4280808080e00084100122082900002107200341d8046a41086a220b200841086a290000370300200320073703d8042008102f200a20032903d8042207370300200341a0066a41086a2002290300370300200341a0066a41106a2007370300200341a0066a41186a200b290300370300200320032903a0033703a006200341306a200341a0066a41201095012003280230210a2003280234210b419298ca00ad4280808080900184100122022d000f210c20022d000e210d20022f000c210f20022d000b211220022d000a211320022f0008211420022d0007211520022d0006211620022f0004211720022d0003211820022d0002211920022f0000211f2002102f41b080c300ad428080808090018410012202290008210720022d0007212020022d0006212120022f0004212220022d0003212320022d0002212420022f000021252002102f4120102d2208450d09200820032903c002370000200841186a200341c0026a41186a290300370000200841106a200341c0026a41106a290300370000200841086a200341c0026a41086a2903003700002008ad428080808080048410032202290018210520022d0017212620022d0016212720022f0014212820022d0013212920022d0012212a20022f0010212b20022d000f212c20022d000e212d20022f000c212e20022d000b212f20022d000a213020022f0008213120022d0007213220022d0006213320022f0004213420022d0003213520022d0002213620022f000021372002102f2008102f41c000102d220e450d09200e2005370038200e20263a0037200e20273a0036200e20283b0034200e20293a0033200e202a3a0032200e202b3b0030200e202c3a002f200e202d3a002e200e202e3b002c200e202f3a002b200e20303a002a200e20313b0028200e20323a0027200e20333a0026200e20343b0024200e20353a0023200e20363a0022200e20373b0020200e2007370018200e20203a0017200e20213a0016200e20223b0014200e20233a0013200e20243a0012200e20253b0010200e200c3a000f200e200d3a000e200e200f3b000c200e20123a000b200e20133a000a200e20143b0008200e20153a0007200e20163a0006200e20173b0004200e20183a0003200e20193a0002200e201f3b0000200941016a2202410574220d41047241046a2208417f4c0d002008102d2209450d092009200b41809c316a41809c31200a1b2212360000200341043602a803200320083602a403200320093602a0032002200341a0036a10690240024020020d0020032802a803210820032802a403210b20032802a003210c0c010b410020032802a80322086b210a20032802a003210c20032802a4032109201021020340024002402009200a6a411f4d0d002009210b0c010b200841206a220b2008490d042009410174220f200b200f200b4b1b220b4100480d040240024020090d00200b102d210c0c010b200c2009200b1031210c0b200c450d0c0b200c20086a22092002290000370000200941186a200241186a290000370000200941106a200241106a290000370000200941086a200241086a290000370000200a41606a210a200841206a2108200b2109200241206a2102200d41606a220d0d000b2003200b3602a403200320083602a8032003200c3602a0030b200ead42808080808008842008ad422086200cad8410040240200b450d00200c102f0b200e102f02402011450d002010102f0b200341a0036a41086a410a3a0000200341a9036a20032903f804370000200341c9036a20032903c002370000200341b1036a200341f8046a41086a290300370000200341b9036a200341f8046a41106a290300370000200341c1036a200341f8046a41186a290300370000200341d1036a200341c0026a41086a290300370000200341d9036a200341c0026a41106a290300370000200341e1036a200341c0026a41186a290300370000200341063a00a003200341ec036a201236020041c8e1ca004100200341a0036a108c01419298ca00ad4280808080900184100122022900002107200229000821052002102f41bfa8c200ad4280808080c001841001220229000021062002290008211a2002102f2003201a3703c801200320063703c001200320053703b801200320073703b001200341b0016aad42808080808004841005200041043a0000410121080c0b0b103d000b1038000b200041023a0000410121080c080b410121080c070b200041023a0000410121080c060b20032802d801210820032802d401210920032802d00121020b2002450d00201a2008ad4220862002ad8410042009450d012002102f0c010b419298ca00ad42808080809001841001220229000021072002290008211b2002102f41aba8c200ad4280808080b0018410012202290000211c2002290008211d2002102f2003201d3703c8012003201c3703c0012003201b3703b801200320073703b0014108102d2202450d01200342083702a403200320023602a0034101200341a0036a1069200328029007200341a0036a107f20032802a4032102201a20033502a80342208620032802a0032208ad8410042002450d002008102f0b200341b8036a2005370300200341b0036a2006370300200341ac036a200a360200200341a8036a41003a0000200341063a00a00341c8e1ca004100200341a0036a108c01200041043a0000410121080c020b1036000b200041023a0000410121080b410121020b024020012d0000416d6a220341014b0d000240024020030e020100010b2002450d01200141086a280200450d01200141046a280200102f0c010b2008450d00200141086a280200450d00200141046a280200102f200424000f0b200424000bd60201027f024002402002450d002002417f6a21040240024020012d0000220241037122054103460d0002400240024020050e03000102000b200241027621020c030b2004450d0320012d0001410874200272220241ffff0371418002490d03200241fcff037141027621020c020b20044103490d0220012f0001200141036a2d000041107472410874200272220241808004490d02200241027621020c010b200241034b0d0120044104490d0120012800012202418080808004490d010b200220036a22012002490d0141012103410121050240200241c000490d0041022105200241808001490d00410441052002418080808004491b21050b0240200141c000490d0041022103200141808001490d00410441052001418080808004491b21030b20002001360204200041003602002000410c6a2003360200200041086a20053602000f0b200041013602000f0b200041013602000b9f0301027f230041e0006b22032400200341003a00050240024002400240200041c000490d00200041808001490d012000418080808004490d0241052104200341053a0005200341033a0000200320003600010c030b41012104200341013a0005200320004102743a00000c020b41022104200341023a0005200320004102744101723b01000c010b41042104200341043a0005200320004102744102723602000b024002402001280200220028020822012002490d0020002802002100200320023602082003200436020c20042002470d0120002003200210e8061a200341e0006a24000f0b20022001104a000b200341286a41146a4109360200200341346a410a360200200341106a41146a41033602002003200341086a36024020032003410c6a360244200341c8006a41146a410036020020034203370214200341b4e0ca003602102003410a36022c200341c8e1ca003602582003420137024c20034188e1ca003602482003200341286a3602202003200341c8006a3602382003200341c4006a3602302003200341c0006a360228200341106a41c8e1ca001043000b881a07027f017e017f027e037f017e027f23004190016b220524000240024002400240024002400240200210b002450d00419298ca00ad4280808080900184100122062900002107200541d8006a41086a200641086a290000370300200520073703582006102f41de97c200ad4280808080e00084100122062900002107200541f0006a41086a200641086a290000370300200520073703702006102f4104102d2206450d042006200236000020064104412410312206450d04200620012900003700042006411c6a200141186a290000370000200641146a200141106a2900003700002006410c6a200141086a2900003700002006ad4280808080c00484100322082900002107200841086a2900002109200841106a290000210a200541106a41186a220b200841186a290000370300200541106a41106a220c200a370300200541106a41086a220d2009370300200520073703102008102f2006102f41c000102d2206450d04200620052903583700002006200529037037001020062005290310370020200641086a200541d8006a41086a290300370000200641186a200541f0006a41086a290300370000200641286a200d290300370000200641306a200c290300370000200641386a200b2903003700002005200641c00041c8e1ca004100410010b501200528020021082006102f20084101460d032005200136020c419298ca00ad4280808080900184100122062900002107200541d8006a41086a2208200641086a290000370300200520073703582006102f41a2a8c200ad4280808080900184100122062900002107200541f0006a41086a220b200641086a290000370300200520073703702006102f20052002360240200541c0006aad220e4280808080c00084100322062900002107200641086a2900002109200641106a290000210a200541106a41186a220c200641186a290000370300200541106a41106a220d200a370300200541106a41086a220f2009370300200520073703102006102f41c000102d2206450d04200620052903583700002006200529037037001020062005290310370020200641086a2008290300370000200641186a200b290300370000200641286a200f290300370000200641306a200d290300370000200641386a200c290300370000200541f0006a2006ad42808080808008842207100210732005280270220b450d01200541f8006a28020021082005280274210c0c020b2000418a263b0001200041086a4111360200200041046a41db93c200360200410321060c050b4104102d2208450d0220054204370214200520083602104100200541106a1069200528021821082005280214210c2005280210210b0b200520083602382005200c3602342005200b3602300240024002400240024002400240024002402008450d00200541106a200b2008410110c40220052802104101470d01200c450d08200b102f0c080b4101200541306a1069200528020c210c024002402005280234220b2005280238220d6b4120490d00200528023021080c010b200d41206a2208200d490d0b200b410174220d2008200d20084b1b220f4100480d0b02400240200b0d00200f102d21080c010b2005280230200b200f103121080b2008450d0a2005200f360234200520083602302005280238210d200f210b0b2008200d6a220f41086a200c41086a290000370000200f41106a200c41106a290000370000200f41186a200c41186a2900003700002005200d41206a220d360238200f200c2900003700000c010b2005280214210d02402005411c6a280200220b200541186a280200220c460d002008200b200c6b6a220841046a220f417f4c0d0202400240200f0d00410121100c010b200f102d2210450d0a0b2005200f36024420052010360240200520083602482005200541c0006a360210200d200541106a200b10c5022008200b490d032005280248220d2008490d042005280238220d200c490d052005280240210f2005280230211020052008200b6b22083602502005200d200c6b220d3602542008200d470d06200f200b6a2010200c6a200810e8061a200528020c210c024002402005280244220b2005280248220d6b4120490d00200528024021080c010b200d41206a2208200d490d0b200b410174220d2008200d20084b1b220f4100480d0b02400240200b0d00200f102d21080c010b2005280240200b200f103121080b2008450d0a2005200f360244200520083602402005280248210d200f210b0b2008200d6a220f41086a200c41086a290000370000200f41106a200c41106a290000370000200f41186a200c41186a2900003700002005200d41206a220d360248200f200c2900003700002005280234450d012005280230102f0c010b2005200541306a360210200d200541106a200c10c502200528020c210c024002402005280234220b2005280238220d6b4120490d00200528023021080c010b200d41206a2208200d490d0a200b410174220d2008200d20084b1b220f4100480d0a02400240200b0d00200f102d21080c010b2005280230200b200f103121080b2008450d092005200f360234200520083602302005280238210d200f210b0b2008200d6a220f41086a200c41086a290000370000200f41106a200c41106a290000370000200f41186a200c41186a2900003700002005200d41206a220d360238200f200c2900003700000b2008450d052007200dad4220862008ad8410040240200b450d002008102f0b2006102f0c060b103d000b200b2008104b000b2008200d104a000b200c200d104b000b200541f0006a41146a4109360200200541fc006a410a360200200541d8006a41146a41033602002005200541d0006a360288012005200541d4006a36028c01200541106a41146a41003602002005420337025c200541b4e0ca003602582005410a360274200541c8e1ca003602202005420137021420054188e1ca003602102005200541f0006a3602682005200541106a3602800120052005418c016a360278200520054188016a360270200541d8006a41c8e1ca001043000b2006102f419298ca00ad4280808080900184100122062900002107200541d8006a41086a2208200641086a290000370300200520073703582006102f41a2a8c200ad4280808080900184100122062900002107200541f0006a41086a220b200641086a290000370300200520073703702006102f20052002360240200e4280808080c00084100322062900002107200641086a2900002109200641106a290000210a200541106a41186a220c200641186a290000370300200541106a41106a220d200a370300200541106a41086a220f2009370300200520073703102006102f41c000102d2206450d01200620052903583700002006200529037037001020062005290310370020200641086a2008290300370000200641186a200b290300370000200641286a200f290300370000200641306a200d290300370000200641386a200c2903003700004108102d2208450d0120054208370214200520083602104101200541106a1069200528020c2108024002402005280214220f2005280218220c6b4120490d002005280210210b0c010b200c41206a220b200c490d03200f410174220d200b200d200b4b1b220d4100480d0302400240200f0d00200d102d210b0c010b2005280210200f200d1031210b0b200b450d022005200d3602142005200b360210200d210f0b200b200c6a220d41086a200841086a290000370000200d41106a200841106a290000370000200d41186a200841186a2900003700002005200c41206a220c360218200d20082900003700002006ad4280808080800884200cad422086200bad8410040240200f450d00200b102f0b2006102f0b419298ca00ad4280808080900184100122062900002107200541d8006a41086a200641086a290000370300200520073703582006102f41de97c200ad4280808080e00084100122062900002107200541f0006a41086a200641086a290000370300200520073703702006102f4104102d2206450d002006200236000020064104412410312206450d00200620012900003700042006411c6a200141186a290000370000200641146a200141106a2900003700002006410c6a200141086a2900003700002006ad4280808080c00484100322012900002107200141086a2900002109200141106a290000210a200541106a41186a2202200141186a290000370300200541106a41106a2208200a370300200541106a41086a220b2009370300200520073703102001102f2006102f41c000102d2206450d00200620052903583700002006200529037037001020062005290310370020200641086a200541d8006a41086a290300370000200641186a200541f0006a41086a290300370000200641286a200b290300370000200641306a2008290300370000200641386a20022903003700004101102d2201450d00200141807f410020031b2004723a00002006ad42808080808008842001ad4280808080108410042001102f2006102f410421060c020b1036000b1038000b200020063a000020054190016a24000bad0602067f047e23004190016b22022400200241c00036020c20022001360208200241106a2001ad4280808080800884100210730240024020022802102203450d002002280214210402400240200241186a2802002201450d0020032d0000220541014b0d002001417f6a2106024002400240024020050e020001000b41002101200241003a008801200341016a21070240034020062001460d01200241e8006a20016a200720016a2d00003a00002002200141016a22053a0088012005210120054120470d000b200241c8006a41186a200241e8006a41186a2903002208370300200241206a41086a200241e8006a41086a290300370300200241206a41106a200241e8006a41106a290300370300200241206a41186a200837030020022002290368370320410021010c020b200141ff0171450d03200241003a0088010c030b41002101200241003a008801200341016a2107034020062001460d02200241e8006a20016a200720016a2d00003a00002002200141016a22053a0088012005210120054120470d000b200241c8006a41186a200241e8006a41186a2903002208370300200241206a41086a200241e8006a41086a290300370300200241206a41106a200241e8006a41106a290300370300200241206a41186a200837030020022002290368370320410121010b200241e8006a41186a200241206a41186a2903002208370300200241e8006a41106a200241206a41106a2903002209370300200241e8006a41086a200241206a41086a290300220a37030020022002290320220b370368200041196a2008370000200041116a2009370000200041096a200a3700002000200b3700010c020b200141ff0171450d00200241003a0088010b20024100360250200242013703482002410b3602242002200241086a3602202002200241c8006a360244200241fc006a41013602002002420137026c200241b885c7003602682002200241206a360278200241c4006a41d8dbc100200241e8006a103c1a200235025042208620023502488410080240200228024c450d002002280248102f0b410221010b200020013a00002004450d012003102f0c010b200041023a00000b20024190016a24000bde0201047f230041e0006b22022400200241c00036020c20022001360208200241106a2001ad4280808080800884100210730240024020022802102201450d00200228021421032002200241186a2802002204360224200220013602200240024020044104490d0020022004417c6a3602242002200141046a36022020012800002104200241c8006a200241206a10980320022802482205450d002000200229024c37020820002005360204200020043602000c010b20024100360230200242013703282002410b36023c2002200241086a3602382002200241286a360244200241dc006a41013602002002420137024c200241b885c7003602482002200241386a360258200241c4006a41d8dbc100200241c8006a103c1a200235023042208620023502288410080240200228022c450d002002280228102f0b200041003602040b2003450d012001102f0c010b200041003602040b200241e0006a24000bdc0703067f017e0a7f230041a0016b220224002002412036021420022001360210200241186a2001ad428080808080048410021073024002400240024002400240024020022802182203450d00200228021c21042002200241206a28020036022c20022003360228200241086a200241286a10e60120022802080d04200228020c2205200228022c220641286e2201200120054b1b2207ad42287e2208422088a70d012008a72201417f4c0d010240024020010d00410421090c010b2001102d2209450d03200141286e21070b02402005450d004100210a0340024002400240024020064104490d00200a41016a210b20022006417c6a220c36022c20022002280228220d41046a360228200d280000210e41002101200241003a00980102400340200c2001460d01200241f8006a20016a200d20016a220f41046a2d00003a00002002200f41056a3602282002200141016a220f3a009801200f2101200f4120470d000b200241d8006a41086a220c200241f8006a41086a290300370300200241d8006a41106a2210200241f8006a41106a290300370300200241d8006a41186a2211200241f8006a41186a2903003703002002200229037837035820022006200f6b2206417c6a220136022c20014104490d01200241386a41086a2212200c290300370300200241386a41106a220c2010290300370300200241386a41186a22102011290300370300200220022903583703382002200641786a220636022c2002200d200f6a220141086a360228200141046a280000210f2007200a470d04200a4101742201200b2001200b4b1bad42287e2208422088a70d0a2008a722014100480d0a200a0d022001102d21090c030b2002410036022c200141ff0171450d00200241003a0098010b2007450d092009102f0c090b2009200a41286c2001103121090b2009450d05200141286e21070b2009200a41286c6a2201200e360200200120022903383702042001410c6a2012290300370200200141146a200c2903003702002001411c6a20102903003702002001200f360224200b210a200b2005470d000b0b2009450d042000200736020420002009360200200041086a20053602000c050b200041003602000c050b103d000b1036000b1038000b20024100360260200242013703582002410b36023c2002200241106a3602382002200241d8006a3602342002418c016a41013602002002420137027c200241b885c7003602782002200241386a36028801200241346a41d8dbc100200241f8006a103c1a200235026042208620023502588410080240200228025c450d002002280258102f0b200041003602000b2004450d002003102f0b200241a0016a24000bcb0503027f037e027f230041f0016b22012400418de6c300ad4280808080e00084100122022900002103200141086a41086a200241086a290000370300200120033703082002102f41f0e8c600ad4280808080f00084100122022900002103200141a8016a41086a200241086a290000370300200120033703a8012002102f02404120102d2202450d0020022000290000370000200241186a200041186a290000370000200241106a200041106a290000370000200241086a200041086a2900003700002002ad4280808080800484100322002900002103200041086a2900002104200041106a2900002105200141d0006a41186a2206200041186a290000370300200141d0006a41106a22072005370300200141d0006a41086a2004370300200120033703502000102f2002102f41c000102d2202450d0020022001290308370000200220012903a80137001020022001290350370020200241086a200141086a41086a290300370000200241186a200141a8016a41086a290300370000200241286a200141d0006a41086a2200290300370000200241306a2007290300370000200241386a2006290300370000200141d0006a200210f60220012903502103200141a8016a200041c40010e8061a200141a4016a41026a22062001419f016a2d00003a0000200120012f009d013b01a4010240024020034201510d0041002100200141086a410041c40010e7061a0c010b20012d009c012100200141086a200141a8016a41c40010e8061a200141046a41026a20062d00003a0000200120012f01a4013b01040b200141d8006a200141086a41c40010e80621062001419f016a200141066a2d00003a000020014201370350200141002000411874220041808080786a2207200720004b1b4118763a009c01200120012f01043b009d01200141c0003602ac01200120023602a8012006200141a8016a1090032002102f200141f0016a24000f0b1036000bec0d03077f017e067f230041c0026b220324002003200236020420032001360200200341086a2002ad4220862001ad84100210730240024020032802082204450d00200341106a2802002105200328020c210641002101200341003a00b8022005417e6a21070240024002400240024002400240034020052001460d0120034198026a20016a200420016a2d00003a00002003200141016a22023a00b8022007417f6a21072002210120024120470d000b200341f8016a41186a20034198026a41186a290300370300200341f8016a41106a20034198026a41106a290300370300200341f8016a41086a20034198026a41086a29030037030020032003290398023703f80120052002460d04200420026a22082d0000220941074f0d04200341f8006a41186a200341f8016a41186a290300370300200341f8006a41106a200341f8016a41106a290300370300200341f8006a41086a200341f8016a41086a290300370300200320032903f8013703782005417f6a2002460d04200841016a2d0000220141014b0d04200520026b210220010e020201020b200141ff0171450d03200341003a00b8020c030b41002101200341003a00b8022002417e6a21050240034020052001460d0120034198026a20016a200820016a41026a2d00003a00002003200141016a22023a00b8022002210120024120470d000b200341d8016a41086a20034198026a41086a290300220a370300200341b8016a41186a20034198026a41186a290300370300200341b8016a41106a20034198026a41106a290300370300200341b8016a41086a200a3703002003200329039802220a3703d8012003200a3703b801200720026b2107200820026a41026a2105410121010c020b200141ff0171450d02200341003a00b8020c020b200841026a21052002417e6a2107410021010b20034198016a41186a200341b8016a41186a29030037030020034198016a41106a200341b8016a41106a29030037030020034198016a41086a200341b8016a41086a290300370300200320032903b801370398012007450d0020052d0000220241014b0d004100210802400240024020020e020100010b41002102200341003a00b802200541016a21082007417f6a2105034020052002460d0220034198026a20026a200820026a2d00003a00002003200241016a22073a00b8022007210220074120470d000b200341d8016a41086a20034198026a41086a290300220a370300200341b8016a41186a20034198026a41186a290300370300200341b8016a41106a20034198026a41106a290300370300200341b8016a41086a200a3703002003200329039802220a3703d8012003200a3703b801410121080b200341186a41186a2202200341b8016a41186a290300370300200341186a41106a2207200341b8016a41106a290300370300200341186a41086a2205200341b8016a41086a290300370300200341386a41086a220b20034198016a41086a290300370300200341386a41106a220c20034198016a41106a290300370300200341386a41186a220d20034198016a41186a290300370300200320032903b8013703182003200329039801370338200341d8006a41186a220e200341f8006a41186a290300370300200341d8006a41106a220f200341f8006a41106a290300370300200341d8006a41086a2210200341f8006a41086a2903003703002003200329037837035820014102460d0220002003290358370000200020093a0020200041186a200e290300370000200041106a200f290300370000200041086a201029030037000020034198026a41086a2209200b29030037030020034198026a41106a220b200c29030037030020034198026a41186a220c200d2903003703002003200329033837039802200341f8016a41186a220d2002290300370300200341f8016a41106a22022007290300370300200341f8016a41086a22072005290300370300200320032903183703f8012000413a6a200c290300370000200041326a200b2903003700002000412a6a20092903003700002000200329039802370022200041c2006a20083a0000200041c3006a20032903f801370000200041cb006a2007290300370000200041d3006a2002290300370000200041db006a200d2903003700000c030b200241ff0171450d00200341003a00b8020b410221010b2003410036028002200342013703f8012003410b3602dc01200320033602d8012003200341f8016a3602b801200341ac026a41013602002003420137029c02200341b885c700360298022003200341d8016a3602a802200341b8016a41d8dbc10020034198026a103c1a20033502800242208620033502f80184100820032802fc01450d0020032802f801102f0b200020013a00212006450d012004102f0c010b200041023a00210b200341c0026a24000bbd0101047f230041106b2202240020002802082103200028020021004101210420012802184199a5c00041012001411c6a28020028020c1100002105200241003a0005200220053a00042002200136020002402003450d0003402002200036020c20022002410c6a4190ebc30010621a200041016a21002003417f6a22030d000b20022d000421050b0240200541ff01710d00200228020022002802184198a5c00041012000411c6a28020028020c11000021040b200241106a240020040bc80801047f0240024002400240200028020022020d0002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d04200341017422022004200220044b1b22024100480d040240024020030d002002102d21040c010b200128020020032002103121040b2004450d0320012004360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200420036a41003a00000c010b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d03200341017422052004200520044b1b22054100480d030240024020030d002005102d21040c010b200128020020032005103121040b2004450d0220012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a00002002280200210302400240200141046a2802002202200528020022046b4120490d00200128020021020c010b200441206a22052004490d03200241017422042005200420054b1b22044100480d030240024020020d002004102d21020c010b200128020020022004103121020b2002450d0220012002360200200141046a2004360200200141086a28020021040b200141086a200441206a360200200220046a220441186a200341186a290000370000200441106a200341106a290000370000200441086a200341086a290000370000200420032900003700000b200141046a2802002104200141086a28020021030240200028020422000d000240024020042003460d00200128020021000c010b200341016a22002003490d03200341017422042000200420004b1b22044100480d030240024020030d002004102d21000c010b200128020020032004103121000b2000450d0220012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41003a00000f0b0240024020042003460d00200128020021040c010b200341016a22042003490d02200341017422022004200220044b1b22024100480d020240024020030d002002102d21040c010b200128020020032002103121040b2004450d0120012004360200200141046a2002360200200141086a28020021030b200141086a2202200341016a360200200420036a41013a000002400240200141046a2802002204200228020022036b4120490d00200128020021040c010b200341206a22022003490d02200441017422032002200320024b1b22034100480d020240024020040d002003102d21040c010b200128020020042003103121040b2004450d0120012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000f0b1036000b1038000bbe0801037f200141046a2802002102200141086a2802002103024002400240024020002d00004101460d000240024020022003460d00200128020021020c010b200341016a22022003490d04200341017422042002200420024b1b22044100480d040240024020030d002004102d21020c010b200128020020032004103121020b2002450d0320012002360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200220036a41003a00000c010b0240024020022003460d00200128020021020c010b200341016a22022003490d03200341017422042002200420024b1b22044100480d030240024020030d002004102d21020c010b200128020020032004103121020b2002450d0220012002360200200141046a2004360200200141086a28020021030b200141086a2204200341016a360200200220036a41013a000002400240200141046a2802002202200428020022036b4120490d00200128020021020c010b200341206a22042003490d03200241017422032004200320044b1b22034100480d030240024020020d002003102d21020c010b200128020020022003103121020b2002450d0220012002360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200220036a220341186a200041196a290000370000200341106a200041116a290000370000200341086a200041096a290000370000200320002900013700000b200141046a2802002102200141086a2802002103024020002d00214101460d000240024020022003460d00200128020021000c010b200341016a22002003490d03200341017422022000200220004b1b22024100480d030240024020030d002002102d21000c010b200128020020032002103121000b2000450d0220012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41003a00000f0b0240024020022003460d00200128020021020c010b200341016a22022003490d02200341017422042002200420024b1b22044100480d020240024020030d002004102d21020c010b200128020020032004103121020b2002450d0120012002360200200141046a2004360200200141086a28020021030b200141086a2204200341016a360200200220036a41013a000002400240200141046a2802002202200428020022036b4120490d00200128020021020c010b200341206a22042003490d02200241017422032004200320044b1b22034100480d020240024020020d002003102d21020c010b200128020020022003103121020b2002450d0120012002360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200220036a220141186a2000413a6a290000370000200141106a200041326a290000370000200141086a2000412a6a2900003700002001200041226a2900003700000f0b1036000b1038000bfb0903047f037e037f230041e0006b22022400200241186a2203200041186a290000370300200241106a2204200041106a290000370300200241086a2205200041086a29000037030020022000290000370300419298ca00ad4280808080900184100122002900002106200241206a41086a200041086a290000370300200220063703202000102f4199a8c200ad4280808080900184100122002900002106200241306a41086a200041086a290000370300200220063703302000102f0240024002404120102d2200450d0020002002290300370000200041186a2003290300370000200041106a2004290300370000200041086a20052903003700002000ad4280808080800484100322032900002106200341086a2900002107200341106a2900002108200241c0006a41186a200341186a290000370300200241c0006a41106a2008370300200241c0006a41086a2007370300200220063703402003102f2000102f41c000102d2203450d00200320022903203700002003200229033037001020032002290340370020200341086a200241206a41086a290300370000200341186a200241306a41086a290300370000200341286a200241c0006a41086a290300370000200341306a200241d0006a290300370000200341386a200241c0006a41186a290300370000200141186a280200220941186a2200417f4c0d010240024020000d00410121040c010b2000102d2204450d010b2002410036024820022000360244200220043602402001280210210a2009200241c0006a106902400240200228024422052002280248220b6b2009490d00200228024021000c010b200b20096a2200200b490d03200541017422042000200420004b1b22044100480d030240024020050d002004102d21000c010b200228024020052004103121000b2000450d012002200436024420022000360240200421050b2002200b20096a22043602482000200b6a200a200910e8061a02400240200520046b411f4d0d00200521090c010b200441206a22092004490d032005410174220b2009200b20094b1b22094100480d030240024020050d002009102d21000c010b200020052009103121000b2000450d0120022009360244200220003602400b200020046a220541186a200141346a290000370000200541106a2001412c6a290000370000200541086a200141246a2900003700002002200441206a220b3602482005200129001c370000200141086a290300210620012903002107024002402009200b6b410f4d0d00200921050c010b200b41106a2205200b490d032009410174220a2005200a20054b1b22054100480d030240024020090d002005102d21000c010b200020092005103121000b2000450d0120022005360244200220003602400b2000200b6a22092006370008200920073700002002200441306a2209360248200128023c210b02400240200520096b4104490d00200441346a21040c010b200941046a22042009490d032005410174220a2004200a20044b1b220a4100480d030240024020050d00200a102d21000c010b20002005200a103121000b2000450d012002200a360244200220003602400b20022004360248200020096a200b360000200228024421002003ad4280808080800884200235024842208620022802402204ad84100402402000450d002004102f0b2003102f0240200141146a280200450d002001280210102f0b200241e0006a24000f0b1036000b103d000b1038000bcb0503027f037e027f230041f0016b22012400418de6c300ad4280808080e00084100122022900002103200141086a41086a200241086a290000370300200120033703082002102f41f0e8c600ad4280808080f00084100122022900002103200141a8016a41086a200241086a290000370300200120033703a8012002102f02404120102d2202450d0020022000290000370000200241186a200041186a290000370000200241106a200041106a290000370000200241086a200041086a2900003700002002ad4280808080800484100322002900002103200041086a2900002104200041106a2900002105200141d0006a41186a2206200041186a290000370300200141d0006a41106a22072005370300200141d0006a41086a2004370300200120033703502000102f2002102f41c000102d2202450d0020022001290308370000200220012903a80137001020022001290350370020200241086a200141086a41086a290300370000200241186a200141a8016a41086a290300370000200241286a200141d0006a41086a2200290300370000200241306a2007290300370000200241386a2006290300370000200141d0006a200210f60220012903502103200141a8016a200041c40010e8061a200141a4016a41026a22062001419f016a2d00003a0000200120012f009d013b01a4010240024020034201510d0041002100200141086a410041c40010e7061a0c010b20012d009c012100200141086a200141a8016a41c40010e8061a200141046a41026a20062d00003a0000200120012f01a4013b01040b200141d8006a200141086a41c40010e80621062001419f016a200141066a2d00003a0000200142013703502001417f2000411874220041808080086a220720072000491b4118763a009c01200120012f01043b009d01200141c0003602ac01200120023602a8012006200141a8016a1090032002102f200141f0016a24000f0b1036000bb60201037f23004180016b220224002000280200210002400240024002400240200128020022034110710d002000280200210420034120710d012004ad41012001104521000c020b20002802002104410021000340200220006a41ff006a2004410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d022001410141bc8ac0004102200220006a4180016a410020006b104821000c010b410021000340200220006a41ff006a2004410f712203413072200341376a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d022001410141bc8ac0004102200220006a4180016a410020006b104821000b20024180016a240020000f0b2004418001104b000b2004418001104b000bca0d030e7f047e037f230022022103200241a0016b416071220224002002427f3703082002427f37030041012104200241013a00182002200029000037031020024180016a200110ff042002280280012105200228028401210602400240024002402002280288012207450d002005200741057422086a2109200841606a210a200241e0006a41106a210b200241e0006a41196a210c41012104200521080340200241c0006a41106a220d200841106a290300370300200241c0006a41086a220e200841086a29030037030020022008290300370340200841186a2d0000210f2002200841196a28000036022820022008411c6a28000036002b200f4103460d01200b200d290300370300200241e0006a41086a200e290300370300200c2002280228360000200c41036a200228002b360000200220022903403703602002200f3a0078024002400240200b2000460d00200b2900002000290000510d002002200c2800003602582002200c41036a28000036005b200241e8006a2903002110200229036021110c010b2002200229039001370310200229030821122002200229038801370308200229030021132002200229038001370300200241033a00980120022903182110200220022903980122113703182011a721042010a7220d41ff01714103460d01200241e8006a2903002210201220022903602211201356201020125620102012511b220b1b211020112013200b1b2111200f4102200f200d41ff0171461b210f0b200229037021122002200228005b36003320022002280258360230200220022802303602382002200228003336003b4120102d220d450d04200d2011370300200d200f3a0018200d2012370310200d2002280238360019200d2010370308200d411c6a200228003b36000002400240200a0d004101210c410121140c010b200841206a2115200741057420056a41606a2116200241e0006a41106a210b200241e0006a41196a210a4101210c410121140340201521080340200241c0006a41106a220e200841106a290300370300200241c0006a41086a2207200841086a29030037030020022008290300370340200841186a2d0000210f2002200841196a28000036022820022008411c6a28000036002b200f4103460d02200b200e290300370300200241e0006a41086a220e2007290300370300200a2002280228360000200a41036a2207200228002b360000200220022903403703602002200f3a007802400240200b2000460d00200b2900002000290000510d002002200a2800003602582002200728000036005b200e2903002110200229036021110c010b2002200229039001370310200229030821122002200229038801370308200229030021132002200229038001370300200241033a00980120022903182110200220022903980122113703182011a7210402402010a741ff017122074103460d00200e2903002210201220022903602211201356201020125620102012511b220e1b211020112013200e1b2111200f4102200f2007461b210f0c010b200841206a22082009470d010c030b0b200229037021122002200228005b36003320022002280258360230200220022802303602382002200228003336003b2002200228003b36008301200220022802383602800102402014200c470d00200c41016a220e200c490d08200c4101742207200e2007200e4b1b220e41ffffff3f71200e470d08200e410574220e4100480d0802400240200c0d00200e102d210d0c010b200d200c410574200e1031210d0b200d450d07200e41057621140b200841206a2115200d200c4105746a220e200f3a0018200e2010370308200e2011370300200e2012370310200e200228028001360019200e411c6a200228008301360000200c41016a210c20162008470d000b0b2006450d032005102f0c030b200a41606a210a200841206a22082009470d000b0b4108210d4100210c02402006450d002005102f0b410021140b0240200441ff01714103460d0020024180016a41186a220f200229031837030020024180016a41106a2200200229031037030020024180016a41086a220b200229030837030020022002290300370380010240200c2014470d00200c41016a2208200c490d03200c410174220a2008200a20084b1b220841ffffff3f712008470d03200841057422084100480d0302400240200c0d002008102d210d0c010b200d200c41057420081031210d0b200d450d02200841057621140b200d200c4105746a2208200229038001370300200841186a200f290300370300200841106a2000290300370300200841086a200b290300370300200c41016a210c0b2001200d200c10800502402014450d00200d102f0b200324000f0b1036000b1038000b13002000411b360204200041849bc3003602000b130020004105360204200041c0e6c3003602000b130020004106360204200041f0a7c0003602000b130020004102360204200041ccd9c9003602000b13002000410536020420004180b6c6003602000b130020004103360204200041c0cbc8003602000b130020004101360204200041d09eca003602000b130020004111360204200041e497c2003602000b130020004107360204200041fcd5c7003602000b130020004105360204200041d889c7003602000b130020004106360204200041bcd2c4003602000b130020004103360204200041e898ca003602000b13002000410b360204200041d4c8c4003602000b130020004108360204200041e4cec1003602000b130020004103360204200041b8b3c4003602000b130020004103360204200041ccc5c3003602000b130020004101360204200041889cca003602000b130020004107360204200041b0f6c0003602000b13002000410f36020420004180b8c4003602000b130020004106360204200041c4cec7003602000b13002000410236020420004194f1c0003602000bf70101077f230041106b220124002001410036020820014201370300200110e80220012802042102200128020021030240024002400240200041046a2802002204200041086a28020022056b20012802082206490d00200028020021040c010b200520066a22072005490d02200441017422052007200520074b1b22054100480d020240024020040d002005102d21040c010b200028020020042005103121040b2004450d0120002004360200200041046a2005360200200041086a28020021050b200041086a200520066a360200200420056a2003200610e8061a02402002450d002003102f0b200141106a24000f0b1036000b1038000b990903017f017e057f230041e0006b22022400024002400240024002400240024002402000290300220342c000540d00200342808001540d012003428080808004540d024108200379a741037622046b41044f0d0341d6bcc600413641f8b4ca001039000b02400240200141046a280200200141086a2802002200460d00200128020021050c010b200041016a22052000490d06200041017422042005200420054b1b22044100480d060240024020000d002004102d21050c010b200128020020002004103121050b2005450d0520012005360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200520006a2003a74102743a00000c030b02400240200141046a2802002205200141086a28020022006b4102490d00200128020021050c010b200041026a22042000490d05200541017422002004200020044b1b22004100480d050240024020050d002000102d21050c010b200128020020052000103121050b2005450d0420012005360200200141046a2000360200200141086a28020021000b200141086a200041026a360200200520006a2003a74102744101723b00000c020b02400240200141046a2802002205200141086a28020022006b4104490d00200128020021050c010b200041046a22042000490d04200541017422002004200020044b1b22004100480d040240024020050d002000102d21050c010b200128020020052000103121050b2005450d0320012005360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200520006a2003a74102744102723600000c010b02400240200141046a280200200141086a2802002205460d00200128020021060c010b200541016a22072005490d03200541017422062007200620074b1b22074100480d030240024020050d002007102d21060c010b200128020020052007103121060b2006450d0220012006360200200141046a2007360200200141086a28020021050b200141086a2207200541016a360200200620056a411320044102746b3a0000200220002903002203370308200441786a2105200141046a2106034002400240200628020020072802002200460d00200128020021040c010b200041016a22042000490d04200041017422082004200820044b1b22084100480d040240024020000d002008102d21040c010b200128020020002008103121040b2004450d032001200436020020062008360200200728020021000b2007200041016a360200200420006a2003a73a000020034208882103200541016a22002005492104200021052004450d000b20022003370308200350450d030b200241e0006a24000f0b1036000b1038000b200241286a41146a4109360200200241346a412b360200200241106a41146a41033602002002200241086a36024020024190bdc600360244200241c8006a41146a410036020020024203370214200241b4e0ca003602102002412b36022c200241c8e1ca003602582002420137024c20024198bdc6003602482002200241286a3602202002200241c8006a3602382002200241c4006a3602302002200241c0006a360228200241106a41e8d8c9001043000b9b1301067f230041106b2202240002400240024002400240024002400240024020012d00000e06010402030500010b20024100360208200242013703004101102d2203450d06200242818080801037020420022003360200200341003a0000200141046a28020021042001410c6a2802002201200210690240024020022802042205200228020822036b2001490d00200228020021050c010b200320016a22062003490d08200541017422072006200720064b1b22064100480d080240024020050d002006102d21050c010b200228020020052006103121050b2005450d0720022006360204200220053602000b2002200320016a360208200520036a2004200110e8061a0c050b20024100360208200242013703004101102d2203450d05200242818080801037020420022003360200200341023a00004120102d2203450d0520032001290001370000200341186a200141196a290000370000200341106a200141116a290000370000200341086a200141096a2900003700000240024020022802042204200228020822016b4120490d00200141206a2105200228020021040c010b200141206a22052001490d07200441017422062005200620054b1b22064100480d070240024020040d002006102d21040c010b200228020020042006103121040b2004450d0620022006360204200220043602000b200420016a220141086a200341086a290000370000200141106a200341106a290000370000200141186a200341186a29000037000020022005360208200120032900003700002003102f0c040b20024100360208200242013703004101102d2203450d04200242818080801037020420022003360200200341043a00000240024020022802042205200228020822036b4104490d00200228020021050c010b200341046a22042003490d06200541017422062004200620044b1b22044100480d060240024020050d002004102d21050c010b200228020020052004103121050b2005450d0520022004360204200220053602000b2002200341046a360208200520036a200128000136000020012802082104200141106a2802002201200210690240024020022802042205200228020822036b2001490d00200228020021050c010b200320016a22062003490d06200541017422072006200720064b1b22064100480d060240024020050d002006102d21050c010b200228020020052006103121050b2005450d0520022006360204200220053602000b2002200320016a360208200520036a2004200110e8061a0c030b20024100360208200242013703004101102d2203450d03200242818080801037020420022003360200200341053a00000240024020022802042205200228020822036b4104490d00200228020021050c010b200341046a22042003490d05200541017422062004200620044b1b22044100480d050240024020050d002004102d21050c010b200228020020052004103121050b2005450d0420022004360204200220053602000b2002200341046a360208200520036a200128000136000020012802082104200141106a2802002201200210690240024020022802042205200228020822036b2001490d00200228020021050c010b200320016a22062003490d05200541017422072006200720064b1b22064100480d050240024020050d002006102d21050c010b200228020020052006103121050b2005450d0420022006360204200220053602000b2002200320016a360208200520036a2004200110e8061a0c020b20024100360208200242013703004101102d2203450d02200242818080801037020420022003360200200341063a00000240024020022802042205200228020822036b4104490d00200228020021050c010b200341046a22042003490d04200541017422062004200620044b1b22044100480d040240024020050d002004102d21050c010b200228020020052004103121050b2005450d0320022004360204200220053602000b2002200341046a360208200520036a200128000136000020012802082104200141106a2802002201200210690240024020022802042205200228020822036b2001490d00200228020021050c010b200320016a22062003490d04200541017422072006200720064b1b22064100480d040240024020050d002006102d21050c010b200228020020052006103121050b2005450d0320022006360204200220053602000b2002200320016a360208200520036a2004200110e8061a0c010b20024100360208200242013703004101102d2203450d01200242818080801037020420022003360200200341073a000002400240200228020420022802082203460d00200228020021050c010b200341016a22052003490d03200341017422042005200420054b1b22044100480d030240024020030d002004102d21050c010b200228020020032004103121050b2005450d0220022004360204200220053602000b2002200341016a360208200520036a41003a00002002280204210520022802082103024020012802044101460d000240024020052003460d00200228020021010c010b200341016a22012003490d04200341017422052001200520014b1b22054100480d040240024020030d002005102d21010c010b200228020020032005103121010b2001450d0320022005360204200220013602000b2002200341016a360208200120036a41003a00000c010b0240024020052003460d00200228020021050c010b200341016a22052003490d03200341017422042005200420054b1b22044100480d030240024020030d002004102d21050c010b200228020020032004103121050b2005450d0220022004360204200220053602000b2002200341016a360208200520036a41013a0000200141086a28020021060240024020022802042204200228020822036b4104490d00200341046a2105200228020021040c010b200341046a22052003490d03200441017422072005200720054b1b22074100480d030240024020040d002007102d21040c010b200228020020042007103121040b2004450d0220022007360204200220043602000b20022005360208200420036a20063600002001410c6a28020021050240024020022802042203200228020822016b4104490d00200228020021030c010b200141046a22042001490d03200341017422062004200620044b1b22044100480d030240024020030d002004102d21030c010b200228020020032004103121030b2003450d0220022004360204200220033602000b2002200141046a360208200320016a20053600000b200020022201290200370200200041086a200141086a280200360200200241106a24000f0b1036000b1038000bc80901037f024002400240024002400240024020002d00004101470d00200041046a280200220241ffff034b0d01200241ef014b0d04200141046a280200200141086a2802002200460d02200128020021030c030b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d06200241017422042003200420034b1b22044100480d060240024020020d002004102d21030c010b200128020020022004103121030b2003450d0520012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41ff013a000002400240200141046a2802002203200428020022026b4120490d00200128020021030c010b200241206a22042002490d06200341017422022004200220044b1b22024100480d060240024020030d002002102d21030c010b200128020020032002103121030b2003450d0520012003360200200141046a2002360200200141086a28020021020b200141086a200241206a360200200320026a220141186a200041196a290000370000200141106a200041116a290000370000200141086a200041096a290000370000200120002900013700000f0b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d05200041017422042003200420034b1b22044100480d050240024020000d002004102d21030c010b200128020020002004103121030b2003450d0420012003360200200141046a2004360200200141086a28020021000b200141086a2204200041016a360200200320006a41fd013a000002400240200141046a2802002203200428020022006b4104490d00200128020021030c010b200041046a22042000490d05200341017422002004200020044b1b22004100480d050240024020030d002000102d21030c010b200128020020032000103121030b2003450d0420012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20023600000f0b200041016a22032000490d03200041017422042003200420034b1b22044100480d030240024020000d002004102d21030c010b200128020020002004103121030b2003450d0220012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a20023a00000f0b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d02200041017422042003200420034b1b22044100480d020240024020000d002004102d21030c010b200128020020002004103121030b2003450d0120012003360200200141046a2004360200200141086a28020021000b200141086a2204200041016a360200200320006a41fc013a000002400240200141046a2802002203200428020022006b4102490d00200128020021030c010b200041026a22042000490d02200341017422002004200020044b1b22004100480d020240024020030d002000102d21030c010b200128020020032000103121030b2003450d0120012003360200200141046a2000360200200141086a28020021000b200141086a200041026a360200200320006a20023b00000f0b1036000b1038000bff1201077f02400240024020002d0000417f6a220241044b0d000240024002400240024020020e050001020304000b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d07200241017422042003200420034b1b22044100480d070240024020020d002004102d21030c010b200128020020022004103121030b2003450d0620012003360200200141046a2004360200200141086a28020021020b200141086a2205200241016a360200200320026a41003a0000200028022421022000412c6a28020022032001106902402003450d0020034105742106200141046a210703400240024020072802002204200528020022036b4120490d00200128020021040c010b200341206a22082003490d09200441017422032008200320084b1b22034100480d090240024020040d002003102d21040c010b200128020020042003103121040b2004450d082001200436020020072003360200200528020021030b2005200341206a360200200420036a220341186a200241186a290000370000200341106a200241106a290000370000200341086a200241086a29000037000020032002290000370000200241206a2102200641606a22060d000b0b024020002d00014101460d0002400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d08200241017422042003200420034b1b22044100480d080240024020020d002004102d21030c010b200128020020022004103121030b2003450d0720012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a41003a00000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d07200241017422042003200420034b1b22044100480d070240024020020d002004102d21030c010b200128020020022004103121030b2003450d0620012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41013a000002400240200141046a2802002203200428020022026b4120490d00200128020021030c010b200241206a22042002490d07200341017422022004200220044b1b22024100480d070240024020030d002002102d21030c010b200128020020032002103121030b2003450d0620012003360200200141046a2002360200200141086a28020021020b200141086a200241206a360200200320026a220241186a200041026a220341186a290000370000200241106a200341106a290000370000200241086a200341086a290000370000200220032900003700000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d06200241017422042003200420034b1b22044100480d060240024020020d002004102d21030c010b200128020020022004103121030b2003450d0520012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a41013a0000200028020420011091010f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d05200241017422042003200420034b1b22044100480d050240024020020d002004102d21030c010b200128020020022004103121030b2003450d0420012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a41023a0000200041046a2001109502200028020820011091010f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d04200241017422042003200420034b1b22044100480d040240024020020d002004102d21030c010b200128020020022004103121030b2003450d0320012003360200200141046a2004360200200141086a28020021020b200141086a2205200241016a360200200320026a41033a00004120102d2202450d0220022000290001370000200241186a200041196a290000370000200241106a200041116a290000370000200241086a200041096a29000037000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d04200441017422032005200320054b1b22034100480d040240024020040d002003102d21040c010b200128020020042003103121040b2004450d0320012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200241186a290000370000200341106a200241106a290000370000200341086a200241086a290000370000200320022900003700002002102f200041246a200110950220002d0021210402400240200141046a28020020052802002202460d00200128020021030c010b200241016a22032002490d04200241017422052003200520034b1b22054100480d040240024020020d002005102d21030c010b200128020020022005103121030b2003450d0320012003360200200141046a2005360200200141086a28020021020b200141086a200241016a360200200320026a20043a00000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d03200241017422042003200420034b1b22044100480d030240024020020d002004102d21030c010b200128020020022004103121030b2003450d0220012003360200200141046a2004360200200141086a28020021020b200141086a2205200241016a360200200320026a41043a00004120102d2202450d0120022000290001370000200241186a200041196a290000370000200241106a200041116a290000370000200241086a200041096a29000037000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d03200441017422032005200320054b1b22034100480d030240024020040d002003102d21040c010b200128020020042003103121040b2004450d0220012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220341186a200241186a290000370000200341106a200241106a290000370000200341086a200241086a290000370000200320022900003700002002102f200041246a20011095020b0f0b1036000b1038000bcc0301037f02404120102d2202450d0020022001290000370000200241186a200141186a290000370000200241106a200141106a290000370000200241086a200141086a2900003700004110102d2203450d00200341e7e485f30636020c200342a08080808004370204200320023602004120102d2202450d0020022001290020370000200241186a200141386a290000370000200241106a200141306a290000370000200241086a200141286a29000037000020034110412010312204450d00200441e2c289ab0636021c200442a08080808004370214200420023602104120102d2203450d0020032001290040370000200341186a200141d8006a290000370000200341106a200141d0006a290000370000200341086a200141c8006a2900003700002004412041c00010312202450d00200241e9dabdf30636022c200242a08080808004370224200220033602204120102d2203450d0020032001290060370000200341186a200141f8006a290000370000200341106a200141f0006a290000370000200341086a200141e8006a29000037000020004284808080c00037020420002002360200200241e1ea91cb0636023c200242a08080808004370234200220033602300f0b1036000ba60901077f230041d0026b2202240041002103200241003a002820012802042104417f210502400240024002400240034020042003460d01200241086a20036a200128020022062d00003a00002001200420056a3602042001200641016a3602002002200341016a22073a00282005417f6a21052007210320074120470d000b20024188016a41086a200241086a41086a29030037030020024188016a41106a200241086a41106a29030037030020024188016a41186a200241086a41186a290300370300200220022903083703880141002108200241003a0028200420076b2107200420056a2103034020072008460d02200241086a20086a200620086a220541016a2d00003a0000200120033602042001200541026a3602002002200841016a22053a00282003417f6a21032005210820054120470d000b200241a8016a41086a200241086a41086a290300370300200241a8016a41106a200241086a41106a290300370300200241a8016a41186a200241086a41186a290300370300200220022903083703a80141002107200241003a0028200620056a210803402003417f460d03200241086a20076a200820076a220541016a2d00003a0000200120033602042001200541026a3602002002200741016a22053a00282003417f6a21032005210720054120470d000b200241c8016a41086a200241086a41086a290300370300200241c8016a41106a200241086a41106a290300370300200241c8016a41186a200241086a41186a290300370300200220022903083703c80141002107200241003a00c802200820056a41016a210503402003417f460d04200241a8026a20076a20052d00003a0000200120033602042001200541016a22053602002002200741016a22083a00c8022003417f6a21032008210720084120470d000b200241e8016a41086a2201200241a8026a41086a290300370300200241e8016a41106a2203200241a8026a41106a290300370300200241e8016a41186a2205200241a8026a41186a290300370300200241086a41086a20024188016a41086a290300370300200241086a41106a20024188016a41106a290300370300200241086a41186a20024188016a41186a290300370300200220022903a8023703e8012002200229038801370308200241c0006a200241a8016a41186a290300370300200241386a200241a8016a41106a290300370300200241306a200241a8016a41086a290300370300200220022903a801370328200241e0006a200241c8016a41186a290300370300200241d8006a200241c8016a41106a290300370300200241d0006a200241c8016a41086a290300370300200220022903c80137034820024180016a2005290300370300200241f8006a2003290300370300200241f0006a2001290300370300200220022903e801370368200041016a200241086a41800110e8061a200041003a00000c040b0240200341ff0171450d00200241003a00280b200041013a00000c030b0240200841ff0171450d00200241003a00280b200041013a00000c020b0240200741ff0171450d00200241003a00280b200041013a00000c010b0240200741ff0171450d00200241003a00c8020b200041013a00000b200241d0026a24000bb1bb0303077f027e027f230041106b220224000240024002400240024002400240024002400240024020002d0000220341144b0d0002400240024002400240024002400240024002400240024002400240024002400240024002400240024020030e15000102030405060708090a0b0c0d0e0f1011121314000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d17200341017422052004200520044b1b22054100480d170240024020030d002005102d21040c010b200128020020032005103121040b2004450d1620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a000020002d0004220341044b0d140240024002400240024020030e050001020304000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d1b200341017422052004200520044b1b22054100480d1b0240024020030d002005102d21040c010b200128020020032005103121040b2004450d1a20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a00002000280208210602400240200141046a2802002204200528020022036b4104490d00200128020021040c010b200341046a22052003490d1b200441017422032005200320054b1b22034100480d1b0240024020040d002003102d21040c010b200128020020042003103121040b2004450d1a20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341046a360200200420036a20063600002000410c6a2d0000210602400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d1b200341017422052004200520044b1b22054100480d1b0240024020030d002005102d21040c010b200128020020032005103121040b2004450d1a20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a20063a00002000410d6a2d0000210402400240200141046a28020020052802002200460d00200128020021030c010b200041016a22032000490d1b200041017422052003200520034b1b22054100480d1b0240024020000d002005102d21030c010b200128020020002005103121030b2003450d1a20012003360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200320006a20043a00000c180b02400240200141046a280200200141086a2802002203460d00200128020021050c010b200341016a22042003490d1a200341017422052004200520044b1b22044100480d1a0240024020030d002004102d21050c010b200128020020032004103121050b2005450d1920012005360200200141046a2004360200200141086a28020021030b41012104200141086a2206200341016a360200200520036a41013a0000024002400240024020002d00080e0400030102000b410021040c020b410221040c010b200241033a000002400240200141046a28020020062802002203460d00200128020021040c010b200341016a22042003490d1b200341017422052004200520044b1b22054100480d1b0240024020030d002005102d21040c010b200128020020032005103121040b2004450d1a20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a0000200220002d000922063a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d1b200341017422052004200520044b1b22054100480d1b0240024020030d002005102d21040c010b200128020020032005103121040b2004450d1a20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a20063a000020002d000a21040b200220043a000002400240200141046a280200200141086a2802002203460d00200128020021050c010b200341016a22052003490d1a200341017422062005200620054b1b22064100480d1a0240024020030d002006102d21050c010b200128020020032006103121050b2005450d1920012005360200200141046a2006360200200141086a28020021030b200141086a2206200341016a360200200520036a20043a00002000280214210502400240200141046a2802002204200628020022036b4104490d00200128020021040c010b200341046a22062003490d1a200441017422032006200320064b1b22034100480d1a0240024020040d002003102d21040c010b200128020020042003103121040b2004450d1920012004360200200141046a2003360200200141086a28020021030b200141086a2206200341046a360200200420036a2005360000200041186a2d0000210502400240200141046a28020020062802002203460d00200128020021040c010b200341016a22042003490d1a200341017422062004200620044b1b22064100480d1a0240024020030d002006102d21040c010b200128020020032006103121040b2004450d1920012004360200200141046a2006360200200141086a28020021030b200141086a2206200341016a360200200420036a20053a0000200041196a2d0000210402400240200141046a28020020062802002200460d00200128020021030c010b200041016a22032000490d1a200041017422052003200520034b1b22054100480d1a0240024020000d002005102d21030c010b200128020020002005103121030b2003450d1920012003360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200320006a20043a00000c170b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d19200041017422042003200420034b1b22044100480d190240024020000d002004102d21030c010b200128020020002004103121030b2003450d1820012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41023a00000c160b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d18200341017422052004200520044b1b22054100480d180240024020030d002005102d21040c010b200128020020032005103121040b2004450d1720012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d18200441017422032005200320054b1b22034100480d180240024020040d002003102d21040c010b200128020020042003103121040b2004450d1720012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041056a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c150b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d17200341017422052004200520044b1b22054100480d170240024020030d002005102d21040c010b200128020020032005103121040b2004450d1620012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d17200441017422032005200320054b1b22034100480d170240024020040d002003102d21040c010b200128020020042003103121040b2004450d1620012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041056a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c140b02400240200141046a2205280200200141086a22032802002204460d00200128020021060c010b200441016a22062004490d16200441017422072006200720064b1b22074100480d160240024020040d002007102d21060c010b200128020020042007103121060b2006450d1520012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41013a000020002d0004220441054b0d1302400240024002400240024020040e06000102030405000b02400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d1b200441017422072006200720064b1b22074100480d1b0240024020040d002007102d21060c010b200128020020042007103121060b2006450d1a20012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41003a0000200028020821070240024020052802002206200328020022046b4104490d00200128020021060c010b200441046a22082004490d1b200641017422042008200420084b1b22044100480d1b0240024020060d002004102d21060c010b200128020020062004103121060b2006450d1a20012006360200200141046a2004360200200141086a28020021040b2003200441046a360200200620046a20073600000240024002400240024020002d000c0e0400010203000b410021040c030b410121040c020b410221040c010b200241033a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d1c200441017422072006200720064b1b22074100480d1c0240024020040d002007102d21060c010b200128020020042007103121060b2006450d1b20012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41033a0000200220002d000d22073a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d1c200441017422082006200820064b1b22084100480d1c0240024020040d002008102d21060c010b200128020020042008103121060b2006450d1b20012006360200200141046a2008360200200141086a28020021040b2003200441016a360200200620046a20073a000020002d000e21040b200220043a000002400240200528020020032802002200460d00200128020021050c010b200041016a22052000490d1b200041017422062005200620054b1b22064100480d1b0240024020000d002006102d21050c010b200128020020002006103121050b2005450d1a20012005360200200141046a2006360200200141086a28020021000b2003200041016a360200200520006a20043a00000c180b02400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d1a200041017422052004200520044b1b22054100480d1a0240024020000d002005102d21040c010b200128020020002005103121040b2004450d1920012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41013a00000c170b02400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d19200441017422072006200720064b1b22074100480d190240024020040d002007102d21060c010b200128020020042007103121060b2006450d1820012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41023a00000240024020052802002206200328020022046b4120490d00200128020021060c010b200441206a22072004490d19200641017422042007200420074b1b22044100480d190240024020060d002004102d21060c010b200128020020062004103121060b2006450d1820012006360200200141046a2004360200200141086a28020021040b2003200441206a360200200620046a220441186a200041056a220641186a290000370000200441106a200641106a290000370000200441086a200641086a290000370000200420062900003700000240024020052802002205200328020022046b4120490d00200128020021050c010b200441206a22062004490d19200541017422042006200420064b1b22044100480d190240024020050d002004102d21050c010b200128020020052004103121050b2005450d1820012005360200200141046a2004360200200141086a28020021040b2003200441206a360200200520046a220141186a200041256a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c160b02400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d18200441017422072006200720064b1b22074100480d180240024020040d002007102d21060c010b200128020020042007103121060b2006450d1720012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41033a00000240024020052802002206200328020022046b4120490d00200128020021060c010b200441206a22072004490d18200641017422042007200420074b1b22044100480d180240024020060d002004102d21060c010b200128020020062004103121060b2006450d1720012006360200200141046a2004360200200141086a28020021040b2003200441206a360200200620046a220441186a200041056a220641186a290000370000200441106a200641106a290000370000200441086a200641086a29000037000020042006290000370000200028024821070240024020052802002206200328020022046b4104490d00200128020021060c010b200441046a22082004490d18200641017422042008200420084b1b22044100480d180240024020060d002004102d21060c010b200128020020062004103121060b2006450d1720012006360200200141046a2004360200200141086a28020021040b2003200441046a360200200620046a2007360000200041cc006a28020021070240024020052802002206200328020022046b4104490d00200128020021060c010b200441046a22082004490d18200641017422042008200420084b1b22044100480d180240024020060d002004102d21060c010b200128020020062004103121060b2006450d1720012006360200200141046a2004360200200141086a28020021040b2003200441046a360200200620046a20073600000240024020052802002205200328020022046b4120490d00200128020021050c010b200441206a22062004490d18200541017422042006200420064b1b22044100480d180240024020050d002004102d21050c010b200128020020052004103121050b2005450d1720012005360200200141046a2004360200200141086a28020021040b2003200441206a360200200520046a220141186a200041256a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c150b02400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d17200441017422072006200720064b1b22074100480d170240024020040d002007102d21060c010b200128020020042007103121060b2006450d1620012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41043a00000240024020052802002206200328020022046b4120490d00200128020021060c010b200441206a22072004490d17200641017422042007200420074b1b22044100480d170240024020060d002004102d21060c010b200128020020062004103121060b2006450d1620012006360200200141046a2004360200200141086a28020021040b2003200441206a360200200620046a220441186a200041056a220641186a290000370000200441106a200641106a290000370000200441086a200641086a29000037000020042006290000370000200028024821070240024020052802002206200328020022046b4104490d00200128020021060c010b200441046a22082004490d17200641017422042008200420084b1b22044100480d170240024020060d002004102d21060c010b200128020020062004103121060b2006450d1620012006360200200141046a2004360200200141086a28020021040b2003200441046a360200200620046a2007360000200041cc006a28020021070240024020052802002206200328020022046b4104490d00200128020021060c010b200441046a22082004490d17200641017422042008200420084b1b22044100480d170240024020060d002004102d21060c010b200128020020062004103121060b2006450d1620012006360200200141046a2004360200200141086a28020021040b2003200441046a360200200620046a20073600000240024020052802002206200328020022046b4120490d00200128020021060c010b200441206a22072004490d17200641017422042007200420074b1b22044100480d170240024020060d002004102d21060c010b200128020020062004103121060b2006450d1620012006360200200141046a2004360200200141086a28020021040b2003200441206a360200200620046a220441186a200041256a220641186a290000370000200441106a200641106a290000370000200441086a200641086a290000370000200420062900003700002005280200210620032802002104024020002d00504104460d000240024020062004460d00200128020021070c010b200441016a22062004490d18200441017422072006200720064b1b22064100480d180240024020040d002006102d21070c010b200128020020042006103121070b2007450d1720012007360200200141046a2006360200200141086a28020021040b410121062003200441016a360200200720046a41013a0000024002400240024020002d00500e0400030102000b410021060c020b410221060c010b200241033a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d19200441017422072006200720064b1b22074100480d190240024020040d002007102d21060c010b200128020020042007103121060b2006450d1820012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41033a0000200220002d005122073a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d19200441017422082006200820064b1b22084100480d190240024020040d002008102d21060c010b200128020020042008103121060b2006450d1820012006360200200141046a2008360200200141086a28020021040b2003200441016a360200200620046a20073a000020002d005221060b200220063a000002400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d18200041017422052004200520044b1b22054100480d180240024020000d002005102d21040c010b200128020020002005103121040b2004450d1720012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a20063a00000c150b0240024020062004460d00200128020021000c010b200441016a22002004490d17200441017422052000200520004b1b22054100480d170240024020040d002005102d21000c010b200128020020042005103121000b2000450d1620012000360200200141046a2005360200200141086a28020021040b2003200441016a360200200020046a41003a00000c140b02400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d16200441017422072006200720064b1b22074100480d160240024020040d002007102d21060c010b200128020020042007103121060b2006450d1520012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41053a00000240024020052802002206200328020022046b4120490d00200128020021060c010b200441206a22072004490d16200641017422042007200420074b1b22044100480d160240024020060d002004102d21060c010b200128020020062004103121060b2006450d1520012006360200200141046a2004360200200141086a28020021040b2003200441206a360200200620046a220441186a200041056a220641186a290000370000200441106a200641106a290000370000200441086a200641086a29000037000020042006290000370000200028024821070240024020052802002206200328020022046b4104490d00200128020021060c010b200441046a22082004490d16200641017422042008200420084b1b22044100480d160240024020060d002004102d21060c010b200128020020062004103121060b2006450d1520012006360200200141046a2004360200200141086a28020021040b2003200441046a360200200620046a2007360000200041cc006a28020021070240024020052802002206200328020022046b4104490d00200128020021060c010b200441046a22082004490d16200641017422042008200420084b1b22044100480d160240024020060d002004102d21060c010b200128020020062004103121060b2006450d1520012006360200200141046a2004360200200141086a28020021040b2003200441046a360200200620046a20073600000240024020052802002205200328020022046b4120490d00200128020021050c010b200441206a22062004490d16200541017422042006200420064b1b22044100480d160240024020050d002004102d21050c010b200128020020052004103121050b2005450d1520012005360200200141046a2004360200200141086a28020021040b2003200441206a360200200520046a220141186a200041256a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c130b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d15200341017422052004200520044b1b22054100480d150240024020030d002005102d21040c010b200128020020032005103121040b2004450d1420012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a0000024020002d00044101460d0002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d16200341017422052004200520044b1b22054100480d160240024020030d002005102d21040c010b200128020020032005103121040b2004450d1520012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d16200441017422032005200320054b1b22034100480d160240024020040d002003102d21040c010b200128020020042003103121040b2004450d1520012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041056a220441186a290000370000200341106a200441106a290000370000200341086a200441086a290000370000200320042900003700002000280228210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d16200341017422002005200020054b1b22004100480d160240024020030d002000102d21030c010b200128020020032000103121030b2003450d1520012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c130b02400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d15200341017422052004200520044b1b22054100480d150240024020030d002005102d21040c010b200128020020032005103121040b2004450d1420012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a00002000280208210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d15200341017422002005200020054b1b22004100480d150240024020030d002000102d21030c010b200128020020032000103121030b2003450d1420012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c120b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d14200341017422052004200520044b1b22054100480d140240024020030d002005102d21040c010b200128020020032005103121040b2004450d1320012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41033a000020002d0008220341044b0d1102400240024002400240024020030e050001020304000b200241003a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d19200341017422052004200520044b1b22054100480d190240024020030d002005102d21040c010b200128020020032005103121040b2004450d1820012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d19200441017422032005200320054b1b22034100480d190240024020040d002003102d21040c010b200128020020042003103121040b2004450d1820012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200029033021092002200041386a290300370308200220093703000c040b200241013a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d18200341017422052004200520044b1b22054100480d180240024020030d002005102d21040c010b200128020020032005103121040b2004450d1720012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d18200441017422032005200320054b1b22034100480d180240024020040d002003102d21040c010b200128020020042003103121040b2004450d1720012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200029033021092002200041386a290300370308200220093703000c030b200241023a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d17200341017422052004200520044b1b22054100480d170240024020030d002005102d21040c010b200128020020032005103121040b2004450d1620012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d17200441017422032005200320054b1b22034100480d170240024020040d002003102d21040c010b200128020020042003103121040b2004450d1620012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002003200429000037000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d17200441017422032005200320054b1b22034100480d170240024020040d002003102d21040c010b200128020020042003103121040b2004450d1620012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220341186a200041296a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200029035021092002200041d8006a290300370308200220093703000c020b200241033a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d16200341017422052004200520044b1b22054100480d160240024020030d002005102d21040c010b200128020020032005103121040b2004450d1520012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d16200441017422032005200320054b1b22034100480d160240024020040d002003102d21040c010b200128020020042003103121040b2004450d1520012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200041386a29030021092000290330210a02400240200141046a2802002204200528020022036b4110490d00200128020021040c010b200341106a22052003490d16200441017422032005200320054b1b22034100480d160240024020040d002003102d21040c010b200128020020042003103121040b2004450d1520012004360200200141046a2003360200200141086a28020021030b200141086a200341106a360200200420036a220320093700082003200a370000200029034021092002200041c8006a290300370308200220093703000c010b200141086a2802002103200241043a0000024002402003200141046a280200460d00200128020021040c010b200341016a22042003490d15200341017422052004200520044b1b22054100480d150240024020030d002005102d21040c010b200128020020032005103121040b2004450d1420012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d15200441017422032005200320054b1b22034100480d150240024020040d002003102d21040c010b200128020020042003103121040b2004450d1420012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200029033021092002200041386a290300370308200220093703000b2002210302400240200141046a2802002204200141086a28020022006b4110490d00200128020021040c010b200041106a22052000490d14200441017422002005200020054b1b22004100480d140240024020040d002000102d21040c010b200128020020042000103121040b2004450d1320012004360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200420006a220041086a200341086a290000370000200020032900003700000c110b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d13200341017422052004200520044b1b22054100480d130240024020030d002005102d21040c010b200128020020032005103121040b2004450d1220012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41043a000020002d0008220341024b0d1002400240024020030e03000102000b200241003a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d15200341017422052004200520044b1b22054100480d150240024020030d002005102d21040c010b200128020020032005103121040b2004450d1420012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d15200441017422032005200320054b1b22034100480d150240024020040d002003102d21040c010b200128020020042003103121040b2004450d1420012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200041386a29030021092000290330210a02400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d15200341017422002004200020044b1b22004100480d150240024020030d002000102d21030c010b200128020020032000103121030b2003450d1420012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a220020093700082000200a3700000c120b200241013a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d14200341017422052004200520044b1b22054100480d140240024020030d002005102d21040c010b200128020020032005103121040b2004450d1320012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d14200441017422032005200320054b1b22034100480d140240024020040d002003102d21040c010b200128020020042003103121040b2004450d1320012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200041386a29030021092000290330210a02400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d14200341017422002004200020044b1b22004100480d140240024020030d002000102d21030c010b200128020020032000103121030b2003450d1320012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a220020093700082000200a3700000c110b200241023a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d13200341017422052004200520044b1b22054100480d130240024020030d002005102d21040c010b200128020020032005103121040b2004450d1220012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a0000200028020c210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d14200341017422002005200020054b1b22004100480d140240024020030d002000102d21030c010b200128020020032000103121030b2003450d1520012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c100b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d13200341017422052004200520044b1b22054100480d130240024020030d002005102d21040c010b200128020020032005103121040b2004450d1420012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41053a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d13200341017422052004200520044b1b22054100480d130240024020030d002005102d21040c010b200128020020032005103121040b2004450d1420012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a00002000280204210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d13200341017422002005200020054b1b22004100480d130240024020030d002000102d21030c010b200128020020032000103121030b2003450d1420012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c0f0b02400240200141046a2205280200200141086a22032802002204460d00200128020021060c010b200441016a22062004490d12200441017422072006200720064b1b22074100480d120240024020040d002007102d21060c010b200128020020042007103121060b2006450d1320012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41063a000020002d0008220441104b0d0e0240024002400240024002400240024002400240024002400240024002400240024020040e11000102030405060708090a0b0c0d0e0f10000b200241003a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d22200441017422072006200720064b1b22074100480d220240024020040d002007102d21060c010b200128020020042007103121060b2006450d2320012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41003a0000200028020c21070240024020052802002206200328020022046b4104490d00200128020021060c010b200441046a22082004490d22200641017422042008200420084b1b22044100480d220240024020060d002004102d21060c010b200128020020062004103121060b2006450d2320012006360200200141046a2004360200200141086a28020021040b2003200441046a360200200620046a2007360000200041186a29030021092000290310210a0240024020052802002204200328020022006b4110490d00200128020021040c010b200041106a22052000490d22200441017422002005200020054b1b22004100480d220240024020040d002000102d21040c010b200128020020042000103121040b2004450d2320012004360200200141046a2000360200200141086a28020021000b2003200041106a360200200420006a220020093700082000200a3700000c1e0b200241013a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d21200441017422072006200720064b1b22074100480d210240024020040d002007102d21060c010b200128020020042007103121060b2006450d2220012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41013a0000200028020c21070240024020052802002206200328020022046b4104490d00200128020021060c010b200441046a22082004490d21200641017422042008200420084b1b22044100480d210240024020060d002004102d21060c010b200128020020062004103121060b2006450d2220012006360200200141046a2004360200200141086a28020021040b2003200441046a360200200620046a2007360000200041286a29030021092000290320210a0240024020052802002206200328020022046b4110490d00200128020021060c010b200441106a22072004490d21200641017422042007200420074b1b22044100480d210240024020060d002004102d21060c010b200128020020062004103121060b2006450d2220012006360200200141046a2004360200200141086a28020021040b200141086a220b200441106a360200200620046a220420093700082004200a37000020002802102104200041186a2802002200200110692000450d1d20004105742107200141046a210c03400240024020052802002206200328020022006b4120490d00200128020021060c010b200041206a22082000490d22200641017422002008200020084b1b22004100480d220240024020060d002000102d21060c010b200128020020062000103121060b2006450d2320012006360200200c2000360200200b28020021000b2003200041206a360200200620006a220041186a200441186a290000370000200041106a200441106a290000370000200041086a200441086a29000037000020002004290000370000200441206a2104200741606a22070d000c1e0b0b200241023a000002400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d20200041017422052004200520044b1b22054100480d200240024020000d002005102d21040c010b200128020020002005103121040b2004450d2120012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41023a00000c1c0b200241033a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d1f200441017422072006200720064b1b22074100480d1f0240024020040d002007102d21060c010b200128020020042007103121060b2006450d2020012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41033a0000200028020c21070240024020052802002206200328020022046b4104490d00200128020021060c010b200441046a22082004490d1f200641017422042008200420084b1b22044100480d1f0240024020060d002004102d21060c010b200128020020062004103121060b2006450d2020012006360200200141046a2004360200200141086a28020021040b2003200441046a360200200620046a200736000020002d0009220041024b0d1b02400240024020000e03000102000b200241003a000002400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d21200041017422052004200520044b1b22054100480d210240024020000d002005102d21040c010b200128020020002005103121040b2004450d2220012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41003a00000c1d0b200241013a000002400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d20200041017422052004200520044b1b22054100480d200240024020000d002005102d21040c010b200128020020002005103121040b2004450d2120012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41013a00000c1c0b200241023a000002400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d1f200041017422052004200520044b1b22054100480d1f0240024020000d002005102d21040c010b200128020020002005103121040b2004450d2020012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41023a00000c1b0b200241043a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d1e200441017422072006200720064b1b22074100480d1e0240024020040d002007102d21060c010b200128020020042007103121060b2006450d1f20012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41043a0000200028020c21060240024020052802002204200328020022006b4104490d00200128020021040c010b200041046a22052000490d1e200441017422002005200020054b1b22004100480d1e0240024020040d002000102d21040c010b200128020020042000103121040b2004450d1f20012004360200200141046a2000360200200141086a28020021000b2003200041046a360200200420006a20063600000c1a0b200241053a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d1d200441017422072006200720064b1b22074100480d1d0240024020040d002007102d21060c010b200128020020042007103121060b2006450d1e20012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41053a0000200028020c21060240024020052802002204200328020022006b4104490d00200128020021040c010b200041046a22052000490d1d200441017422002005200020054b1b22004100480d1d0240024020040d002000102d21040c010b200128020020042000103121040b2004450d1e20012004360200200141046a2000360200200141086a28020021000b2003200041046a360200200420006a20063600000c190b200241063a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d1c200441017422072006200720064b1b22074100480d1c0240024020040d002007102d21060c010b200128020020042007103121060b2006450d1d20012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41063a0000200028020c21060240024020052802002204200328020022006b4104490d00200128020021040c010b200041046a22052000490d1c200441017422002005200020054b1b22004100480d1c0240024020040d002000102d21040c010b200128020020042000103121040b2004450d1d20012004360200200141046a2000360200200141086a28020021000b2003200041046a360200200420006a20063600000c180b200241073a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d1b200441017422072006200720064b1b22074100480d1b0240024020040d002007102d21060c010b200128020020042007103121060b2006450d1c20012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41073a0000200028020c21070240024020052802002206200328020022046b4104490d00200128020021060c010b200441046a22082004490d1b200641017422042008200420084b1b22044100480d1b0240024020060d002004102d21060c010b200128020020062004103121060b2006450d1c20012006360200200141046a2004360200200141086a28020021040b2003200441046a360200200620046a2007360000200220002d000922063a000002400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d1b200041017422052004200520044b1b22054100480d1b0240024020000d002005102d21040c010b200128020020002005103121040b2004450d1c20012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a20063a00000c170b200241083a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d1a200441017422072006200720064b1b22074100480d1a0240024020040d002007102d21060c010b200128020020042007103121060b2006450d1b20012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41083a00000240024020052802002206200328020022046b4120490d00200128020021060c010b200441206a22072004490d1a200641017422042007200420074b1b22044100480d1a0240024020060d002004102d21060c010b200128020020062004103121060b2006450d1b20012006360200200141046a2004360200200141086a28020021040b2003200441206a360200200620046a220441186a200041096a220641186a290000370000200441106a200641106a290000370000200441086a200641086a290000370000200420062900003700000240024020052802002205200328020022046b4120490d00200128020021050c010b200441206a22062004490d1a200541017422042006200420064b1b22044100480d1a0240024020050d002004102d21050c010b200128020020052004103121050b2005450d1b20012005360200200141046a2004360200200141086a28020021040b2003200441206a360200200520046a220141186a200041296a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c160b200241093a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d19200441017422072006200720064b1b22074100480d190240024020040d002007102d21060c010b200128020020042007103121060b2006450d1a20012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41093a00000240024020052802002205200328020022046b4120490d00200128020021050c010b200441206a22062004490d19200541017422042006200420064b1b22044100480d190240024020050d002004102d21050c010b200128020020052004103121050b2005450d1a20012005360200200141046a2004360200200141086a28020021040b2003200441206a360200200520046a220141186a200041096a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c150b2002410a3a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d18200441017422072006200720064b1b22074100480d180240024020040d002007102d21060c010b200128020020042007103121060b2006450d1920012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a410a3a00000240024020052802002206200328020022046b4120490d00200128020021060c010b200441206a22072004490d18200641017422042007200420074b1b22044100480d180240024020060d002004102d21060c010b200128020020062004103121060b2006450d1920012006360200200141046a2004360200200141086a28020021040b2003200441206a360200200620046a220441186a200041096a220641186a290000370000200441106a200641106a290000370000200441086a200641086a290000370000200420062900003700004120102d2204450d18200441186a200041c1006a290000370000200441106a200041396a290000370000200441086a200041316a2900003700002004200041296a2900003700000240024020052802002207200328020022066b4120490d00200128020021070c010b200641206a22082006490d18200741017422062008200620084b1b22064100480d180240024020070d002006102d21070c010b200128020020072006103121070b2007450d1920012007360200200141046a2006360200200141086a28020021060b2003200641206a360200200720066a220641186a200441186a290000370000200641106a200441106a290000370000200641086a200441086a290000370000200620042900003700002004102f200028024c21060240024020052802002204200328020022006b4104490d00200128020021040c010b200041046a22052000490d18200441017422002005200020054b1b22004100480d180240024020040d002000102d21040c010b200128020020042000103121040b2004450d1920012004360200200141046a2000360200200141086a28020021000b2003200041046a360200200420006a20063600000c140b2002410b3a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d17200441017422072006200720064b1b22074100480d170240024020040d002007102d21060c010b200128020020042007103121060b2006450d1820012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a410b3a00004120102d2204450d17200441186a200041216a290000370000200441106a200041196a290000370000200441086a200041116a2900003700002004200041096a2900003700000240024020052802002207200328020022066b4120490d00200128020021070c010b200641206a22082006490d17200741017422062008200620084b1b22064100480d170240024020070d002006102d21070c010b200128020020072006103121070b2007450d1820012007360200200141046a2006360200200141086a28020021060b2003200641206a360200200720066a220641186a200441186a290000370000200641106a200441106a290000370000200641086a200441086a290000370000200620042900003700002004102f0240024020052802002206200328020022046b4120490d00200128020021060c010b200441206a22072004490d17200641017422042007200420074b1b22044100480d170240024020060d002004102d21060c010b200128020020062004103121060b2006450d1820012006360200200141046a2004360200200141086a28020021040b2003200441206a360200200620046a220441186a200041296a220641186a290000370000200441106a200641106a290000370000200441086a200641086a29000037000020042006290000370000200041d8006a29030021092000290350210a0240024020052802002204200328020022006b4110490d00200128020021040c010b200041106a22052000490d17200441017422002005200020054b1b22004100480d170240024020040d002000102d21040c010b200128020020042000103121040b2004450d1820012004360200200141046a2000360200200141086a28020021000b2003200041106a360200200420006a220020093700082000200a3700000c130b2002410c3a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d16200441017422072006200720064b1b22074100480d160240024020040d002007102d21060c010b200128020020042007103121060b2006450d1720012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a410c3a00004120102d2204450d16200441186a200041216a290000370000200441106a200041196a290000370000200441086a200041116a2900003700002004200041096a2900003700000240024020052802002207200328020022066b4120490d00200128020021070c010b200641206a22082006490d16200741017422062008200620084b1b22064100480d160240024020070d002006102d21070c010b200128020020072006103121070b2007450d1720012007360200200141046a2006360200200141086a28020021060b2003200641206a360200200720066a220641186a200441186a290000370000200641106a200441106a290000370000200641086a200441086a290000370000200620042900003700002004102f0240024020052802002206200328020022046b4120490d00200128020021060c010b200441206a22072004490d16200641017422042007200420074b1b22044100480d160240024020060d002004102d21060c010b200128020020062004103121060b2006450d1720012006360200200141046a2004360200200141086a28020021040b2003200441206a360200200620046a220441186a200041296a220641186a290000370000200441106a200641106a290000370000200441086a200641086a29000037000020042006290000370000200041d8006a29030021092000290350210a0240024020052802002204200328020022006b4110490d00200128020021040c010b200041106a22052000490d16200441017422002005200020054b1b22004100480d160240024020040d002000102d21040c010b200128020020042000103121040b2004450d1720012004360200200141046a2000360200200141086a28020021000b2003200041106a360200200420006a220020093700082000200a3700000c120b2002410d3a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d15200441017422072006200720064b1b22074100480d150240024020040d002007102d21060c010b200128020020042007103121060b2006450d1620012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a410d3a00004120102d2204450d15200441186a200041216a290000370000200441106a200041196a290000370000200441086a200041116a2900003700002004200041096a2900003700000240024020052802002207200328020022066b4120490d00200128020021070c010b200641206a22082006490d15200741017422062008200620084b1b22064100480d150240024020070d002006102d21070c010b200128020020072006103121070b2007450d1620012007360200200141046a2006360200200141086a28020021060b2003200641206a360200200720066a220641186a200441186a290000370000200641106a200441106a290000370000200641086a200441086a290000370000200620042900003700002004102f200028022c21060240024020052802002204200328020022006b4104490d00200128020021040c010b200041046a22052000490d15200441017422002005200020054b1b22004100480d150240024020040d002000102d21040c010b200128020020042000103121040b2004450d1620012004360200200141046a2000360200200141086a28020021000b2003200041046a360200200420006a20063600000c110b2002410e3a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d14200441017422072006200720064b1b22074100480d140240024020040d002007102d21060c010b200128020020042007103121060b2006450d1520012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a410e3a00004120102d2204450d14200441186a200041216a290000370000200441106a200041196a290000370000200441086a200041116a2900003700002004200041096a2900003700000240024020052802002207200328020022066b4120490d00200128020021070c010b200641206a22082006490d14200741017422062008200620084b1b22064100480d140240024020070d002006102d21070c010b200128020020072006103121070b2007450d1520012007360200200141046a2006360200200141086a28020021060b2003200641206a360200200720066a220641186a200441186a290000370000200641106a200441106a290000370000200641086a200441086a290000370000200620042900003700002004102f200028022c21060240024020052802002204200328020022006b4104490d00200128020021040c010b200041046a22052000490d14200441017422002005200020054b1b22004100480d140240024020040d002000102d21040c010b200128020020042000103121040b2004450d1520012004360200200141046a2000360200200141086a28020021000b2003200041046a360200200420006a20063600000c100b2002410f3a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d13200441017422072006200720064b1b22074100480d130240024020040d002007102d21060c010b200128020020042007103121060b2006450d1420012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a410f3a00004120102d2204450d13200441186a200041216a290000370000200441106a200041196a290000370000200441086a200041116a2900003700002004200041096a2900003700000240024020052802002207200328020022066b4120490d00200128020021070c010b200641206a22082006490d13200741017422062008200620084b1b22064100480d130240024020070d002006102d21070c010b200128020020072006103121070b2007450d1420012007360200200141046a2006360200200141086a28020021060b2003200641206a360200200720066a220641186a200441186a290000370000200641106a200441106a290000370000200641086a200441086a290000370000200620042900003700002004102f0240024020052802002206200328020022046b4120490d00200128020021060c010b200441206a22072004490d13200641017422042007200420074b1b22044100480d130240024020060d002004102d21060c010b200128020020062004103121060b2006450d1420012006360200200141046a2004360200200141086a28020021040b2003200441206a360200200620046a220441186a200041296a220641186a290000370000200441106a200641106a290000370000200441086a200641086a29000037000020042006290000370000200041f8006a29030021092000290370210a0240024020052802002206200328020022046b4110490d00200128020021060c010b200441106a22072004490d13200641017422042007200420074b1b22044100480d130240024020060d002004102d21060c010b200128020020062004103121060b2006450d1420012006360200200141046a2004360200200141086a28020021040b2003200441106a360200200620046a220420093700082004200a3700000240024020052802002205200328020022046b4120490d00200128020021050c010b200441206a22062004490d13200541017422042006200420064b1b22044100480d130240024020050d002004102d21050c010b200128020020052004103121050b2005450d1420012005360200200141046a2004360200200141086a28020021040b2003200441206a360200200520046a220141186a200041c9006a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c0f0b200241103a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d12200441017422072006200720064b1b22074100480d120240024020040d002007102d21060c010b200128020020042007103121060b2006450d1320012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41103a00000240024020052802002205200328020022046b4120490d00200128020021050c010b200441206a22062004490d12200541017422042006200420064b1b22044100480d120240024020050d002004102d21050c010b200128020020052004103121050b2005450d1320012005360200200141046a2004360200200141086a28020021040b2003200441206a360200200520046a220141186a200041096a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c0e0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d11200341017422052004200520044b1b22054100480d110240024020030d002005102d21040c010b200128020020032005103121040b2004450d1220012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41073a0000200041046a200110f0020c0d0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d10200341017422052004200520044b1b22054100480d100240024020030d002005102d21040c010b200128020020032005103121040b2004450d1120012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41083a0000200041046a200110f0020c0c0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0f200341017422052004200520044b1b22054100480d0f0240024020030d002005102d21040c010b200128020020032005103121040b2004450d1020012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41093a000020002d0004220341044b0d0b0240024002400240024020030e050001020304000b200241003a000002400240200141046a280200200141086a2802002203460d00200128020021050c010b200341016a22042003490d13200341017422052004200520044b1b22044100480d130240024020030d002004102d21050c010b200128020020032004103121050b2005450d1420012005360200200141046a2004360200200141086a28020021030b200141086a2204200341016a360200200520036a41003a000020002802082103200041106a2802002200200110692000450d0f2003200041306c6a2108200141046a210503400240024020052802002206200428020022006b4120490d00200128020021060c010b200041206a22072000490d14200641017422002007200020074b1b22004100480d140240024020060d002000102d21060c010b200128020020062000103121060b2006450d152001200636020020052000360200200428020021000b2004200041206a360200200620006a220041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a29000037000020002003290000370000200341286a2903002109200341206a290300210a0240024020052802002206200428020022006b4110490d00200128020021060c010b200041106a22072000490d14200641017422002007200020074b1b22004100480d140240024020060d002000102d21060c010b200128020020062000103121060b2006450d152001200636020020052000360200200428020021000b2004200041106a360200200620006a220020093700082000200a3700002008200341306a2203470d000c100b0b200241013a000002400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d12200041017422042003200420034b1b22044100480d120240024020000d002004102d21030c010b200128020020002004103121030b2003450d1320012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41013a00000c0e0b200241023a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d11200341017422052004200520044b1b22054100480d110240024020030d002005102d21040c010b200128020020032005103121040b2004450d1220012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d11200441017422032005200320054b1b22034100480d110240024020040d002003102d21040c010b200128020020042003103121040b2004450d1220012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041056a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c0d0b200241033a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d10200341017422052004200520044b1b22054100480d100240024020030d002005102d21040c010b200128020020032005103121040b2004450d1120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d10200441017422032005200320054b1b22034100480d100240024020040d002003102d21040c010b200128020020042003103121040b2004450d1120012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041056a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c0c0b200141086a2802002103200241043a0000024002402003200141046a280200460d00200128020021040c010b200341016a22042003490d0f200341017422052004200520044b1b22054100480d0f0240024020030d002005102d21040c010b200128020020032005103121040b2004450d1020012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d0f200441017422032005200320054b1b22034100480d0f0240024020040d002003102d21040c010b200128020020042003103121040b2004450d1020012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041056a220441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002003200429000037000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d0f200441017422032005200320054b1b22034100480d0f0240024020040d002003102d21040c010b200128020020042003103121040b2004450d1020012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041256a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200220002d004522043a000002400240200141046a28020020052802002200460d00200128020021030c010b200041016a22032000490d11200041017422052003200520034b1b22054100480d110240024020000d002005102d21030c010b200128020020002005103121030b2003450d1020012003360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200320006a20043a00000c0b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d10200341017422052004200520044b1b22054100480d100240024020030d002005102d21040c010b200128020020032005103121040b2004450d1120012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410a3a000020002d0001220041054b0d0a024002400240024002400240024020000e06000102030405000b410021030c050b410121030c040b410221030c030b410321030c020b410421030c010b410521030b200220033a000002400240200141046a280200200141086a2802002200460d00200128020021040c010b200041016a22042000490d10200041017422052004200520044b1b22054100480d100240024020000d002005102d21040c010b200128020020002005103121040b2004450d1120012004360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200420006a20033a00000c0a0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0f200341017422052004200520044b1b22054100480d0f0240024020030d002005102d21040c010b200128020020032005103121040b2004450d1020012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410b3a00002000280204220341024b0d0902400240024020030e03000102000b200241003a000002400240200141046a280200200141086a2802002203460d00200128020021050c010b200341016a22042003490d11200341017422052004200520044b1b22044100480d110240024020030d002004102d21050c010b200128020020032004103121050b2005450d1220012005360200200141046a2004360200200141086a28020021030b200141086a2204200341016a360200200520036a41003a000020002802082103200041106a2802002200200110692000450d0b2003200041286c6a2108200141046a210503400240024020052802002206200428020022006b4120490d00200128020021060c010b200041206a22072000490d12200641017422002007200020074b1b22004100480d120240024020060d002000102d21060c010b200128020020062000103121060b2006450d132001200636020020052000360200200428020021000b2004200041206a360200200620006a220041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a29000037000020002003290000370000200341206a29030021090240024020052802002206200428020022006b4108490d00200128020021060c010b200041086a22072000490d12200641017422002007200020074b1b22004100480d120240024020060d002000102d21060c010b200128020020062000103121060b2006450d132001200636020020052000360200200428020021000b2004200041086a360200200620006a20093700002008200341286a2203470d000c0c0b0b200241013a000002400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d10200041017422042003200420034b1b22044100480d100240024020000d002004102d21030c010b200128020020002004103121030b2003450d1120012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41013a00000c0a0b200241023a000002400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d0f200041017422042003200420034b1b22044100480d0f0240024020000d002004102d21030c010b200128020020002004103121030b2003450d1020012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41023a00000c090b02400240200141046a2205280200200141086a22032802002204460d00200128020021060c010b200441016a22062004490d0e200441017422072006200720064b1b22074100480d0e0240024020040d002007102d21060c010b200128020020042007103121060b2006450d0f20012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a410c3a000020002d00082204410a4b0d080240024002400240024002400240024002400240024020040e0b000102030405060708090a000b200241003a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d18200441017422072006200720064b1b22074100480d180240024020040d002007102d21060c010b200128020020042007103121060b2006450d1920012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41003a0000200028020c21060240024020052802002204200328020022006b4104490d00200128020021040c010b200041046a22052000490d18200441017422002005200020054b1b22004100480d180240024020040d002000102d21040c010b200128020020042000103121040b2004450d1920012004360200200141046a2000360200200141086a28020021000b2003200041046a360200200420006a20063600000c120b200241013a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d17200441017422072006200720064b1b22074100480d170240024020040d002007102d21060c010b200128020020042007103121060b2006450d1820012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41013a0000200041186a29030021092000290310210a0240024020052802002204200328020022006b4110490d00200128020021040c010b200041106a22052000490d17200441017422002005200020054b1b22004100480d170240024020040d002000102d21040c010b200128020020042000103121040b2004450d1820012004360200200141046a2000360200200141086a28020021000b2003200041106a360200200420006a220020093700082000200a3700000c110b200241023a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d16200441017422072006200720064b1b22074100480d160240024020040d002007102d21060c010b200128020020042007103121060b2006450d1720012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41023a0000200028022c21070240024020052802002206200328020022046b4104490d00200128020021060c010b200441046a22082004490d16200641017422042008200420084b1b22044100480d160240024020060d002004102d21060c010b200128020020062004103121060b2006450d1720012006360200200141046a2004360200200141086a28020021040b2003200441046a360200200620046a2007360000200041386a29030021092000290330210a0240024020052802002206200328020022046b4110490d00200128020021060c010b200441106a22072004490d16200641017422042007200420074b1b22044100480d160240024020060d002004102d21060c010b200128020020062004103121060b2006450d1720012006360200200141046a2004360200200141086a28020021040b2003200441106a360200200620046a220420093700082004200a3700000240024020052802002205200328020022046b4120490d00200128020021050c010b200441206a22062004490d16200541017422042006200420064b1b22044100480d160240024020050d002004102d21050c010b200128020020052004103121050b2005450d1720012005360200200141046a2004360200200141086a28020021040b2003200441206a360200200520046a220141186a200041096a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c100b200241033a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d15200441017422072006200720064b1b22074100480d150240024020040d002007102d21060c010b200128020020042007103121060b2006450d1620012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41033a0000200028020c21070240024020052802002206200328020022046b4104490d00200128020021060c010b200441046a22082004490d15200641017422042008200420084b1b22044100480d150240024020060d002004102d21060c010b200128020020062004103121060b2006450d1620012006360200200141046a2004360200200141086a28020021040b2003200441046a360200200620046a2007360000200041186a29030021092000290310210a0240024020052802002204200328020022006b4110490d00200128020021040c010b200041106a22052000490d15200441017422002005200020054b1b22004100480d150240024020040d002000102d21040c010b200128020020042000103121040b2004450d1620012004360200200141046a2000360200200141086a28020021000b2003200041106a360200200420006a220020093700082000200a3700000c0f0b200241043a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d14200441017422072006200720064b1b22074100480d140240024020040d002007102d21060c010b200128020020042007103121060b2006450d1520012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41043a0000200041186a29030021092000290310210a0240024020052802002204200328020022006b4110490d00200128020021040c010b200041106a22052000490d14200441017422002005200020054b1b22004100480d140240024020040d002000102d21040c010b200128020020042000103121040b2004450d1520012004360200200141046a2000360200200141086a28020021000b2003200041106a360200200420006a220020093700082000200a3700000c0e0b200241053a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d13200441017422072006200720064b1b22074100480d130240024020040d002007102d21060c010b200128020020042007103121060b2006450d1420012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41053a0000200041186a29030021092000290310210a0240024020052802002204200328020022006b4110490d00200128020021040c010b200041106a22052000490d13200441017422002005200020054b1b22004100480d130240024020040d002000102d21040c010b200128020020042000103121040b2004450d1420012004360200200141046a2000360200200141086a28020021000b2003200041106a360200200420006a220020093700082000200a3700000c0d0b200241063a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d12200441017422072006200720064b1b22074100480d120240024020040d002007102d21060c010b200128020020042007103121060b2006450d1320012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41063a0000200041186a29030021092000290310210a0240024020052802002204200328020022006b4110490d00200128020021040c010b200041106a22052000490d12200441017422002005200020054b1b22004100480d120240024020040d002000102d21040c010b200128020020042000103121040b2004450d1320012004360200200141046a2000360200200141086a28020021000b2003200041106a360200200420006a220020093700082000200a3700000c0c0b200241073a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d11200441017422072006200720064b1b22074100480d110240024020040d002007102d21060c010b200128020020042007103121060b2006450d1220012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41073a00004120102d2204450d11200441186a200041216a290000370000200441106a200041196a290000370000200441086a200041116a2900003700002004200041096a2900003700000240024020052802002205200328020022006b4120490d00200128020021050c010b200041206a22062000490d11200541017422002006200020064b1b22004100480d110240024020050d002000102d21050c010b200128020020052000103121050b2005450d1220012005360200200141046a2000360200200141086a28020021000b2003200041206a360200200520006a220041186a200441186a290000370000200041106a200441106a290000370000200041086a200441086a290000370000200020042900003700002004102f0c0b0b200241083a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d10200441017422072006200720064b1b22074100480d100240024020040d002007102d21060c010b200128020020042007103121060b2006450d1120012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41083a00004120102d2204450d10200441186a200041216a290000370000200441106a200041196a290000370000200441086a200041116a2900003700002004200041096a2900003700000240024020052802002205200328020022006b4120490d00200128020021050c010b200041206a22062000490d10200541017422002006200020064b1b22004100480d100240024020050d002000102d21050c010b200128020020052000103121050b2005450d1120012005360200200141046a2000360200200141086a28020021000b2003200041206a360200200520006a220041186a200441186a290000370000200041106a200441106a290000370000200041086a200441086a290000370000200020042900003700002004102f0c0a0b200241093a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d0f200441017422072006200720064b1b22074100480d0f0240024020040d002007102d21060c010b200128020020042007103121060b2006450d1020012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41093a00004120102d2204450d0f200441186a200041216a290000370000200441106a200041196a290000370000200441086a200041116a2900003700002004200041096a2900003700000240024020052802002207200328020022066b4120490d00200128020021070c010b200641206a22082006490d0f200741017422062008200620084b1b22064100480d0f0240024020070d002006102d21070c010b200128020020072006103121070b2007450d1020012007360200200141046a2006360200200141086a28020021060b2003200641206a360200200720066a220641186a200441186a290000370000200641106a200441106a290000370000200641086a200441086a290000370000200620042900003700002004102f0240024020052802002206200328020022046b4120490d00200128020021060c010b200441206a22072004490d0f200641017422042007200420074b1b22044100480d0f0240024020060d002004102d21060c010b200128020020062004103121060b2006450d1020012006360200200141046a2004360200200141086a28020021040b2003200441206a360200200620046a220441186a200041296a220641186a290000370000200441106a200641106a290000370000200441086a200641086a29000037000020042006290000370000200041d8006a29030021092000290350210a0240024020052802002204200328020022006b4110490d00200128020021040c010b200041106a22052000490d0f200441017422002005200020054b1b22004100480d0f0240024020040d002000102d21040c010b200128020020042000103121040b2004450d1020012004360200200141046a2000360200200141086a28020021000b2003200041106a360200200420006a220020093700082000200a3700000c090b2002410a3a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d0e200441017422072006200720064b1b22074100480d0e0240024020040d002007102d21060c010b200128020020042007103121060b2006450d0f20012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a410a3a00004120102d2204450d0e200441186a200041216a290000370000200441106a200041196a290000370000200441086a200041116a2900003700002004200041096a2900003700000240024020052802002205200328020022006b4120490d00200128020021050c010b200041206a22062000490d0e200541017422002006200020064b1b22004100480d0e0240024020050d002000102d21050c010b200128020020052000103121050b2005450d0f20012005360200200141046a2000360200200141086a28020021000b2003200041206a360200200520006a220041186a200441186a290000370000200041106a200441106a290000370000200041086a200441086a290000370000200020042900003700002004102f0c080b02400240200141046a2205280200200141086a22032802002204460d00200128020021060c010b200441016a22062004490d0d200441017422072006200720064b1b22074100480d0d0240024020040d002007102d21060c010b200128020020042007103121060b2006450d0e20012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a410d3a00000240024002400240024002400240024020002d00080e080001020304050607000b200241003a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d14200441017422072006200720064b1b22074100480d140240024020040d002007102d21060c010b200128020020042007103121060b2006450d1520012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41003a00000240024020052802002206200328020022046b4120490d00200128020021060c010b200441206a22072004490d14200641017422042007200420074b1b22044100480d140240024020060d002004102d21060c010b200128020020062004103121060b2006450d1520012006360200200141046a2004360200200141086a28020021040b2003200441206a360200200620046a220441186a200041096a220641186a290000370000200441106a200641106a290000370000200441086a200641086a290000370000200420062900003700000240024020052802002206200328020022046b4120490d00200128020021060c010b200441206a22072004490d14200641017422042007200420074b1b22044100480d140240024020060d002004102d21060c010b200128020020062004103121060b2006450d1520012006360200200141046a2004360200200141086a28020021040b2003200441206a360200200620046a220441186a200041296a220641186a290000370000200441106a200641106a290000370000200441086a200641086a29000037000020042006290000370000200041d8006a29030021092000290350210a0240024020052802002204200328020022006b4110490d00200128020021040c010b200041106a22052000490d14200441017422002005200020054b1b22004100480d140240024020040d002000102d21040c010b200128020020042000103121040b2004450d1520012004360200200141046a2000360200200141086a28020021000b2003200041106a360200200420006a220020093700082000200a3700000c0e0b200241013a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d13200441017422072006200720064b1b22074100480d130240024020040d002007102d21060c010b200128020020042007103121060b2006450d1420012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41013a00000240024020052802002206200328020022046b4120490d00200128020021060c010b200441206a22072004490d13200641017422042007200420074b1b22044100480d130240024020060d002004102d21060c010b200128020020062004103121060b2006450d1420012006360200200141046a2004360200200141086a28020021040b2003200441206a360200200620046a220441186a200041096a220641186a290000370000200441106a200641106a290000370000200441086a200641086a290000370000200420062900003700000240024020052802002205200328020022046b4120490d00200128020021050c010b200441206a22062004490d13200541017422042006200420064b1b22044100480d130240024020050d002004102d21050c010b200128020020052004103121050b2005450d1420012005360200200141046a2004360200200141086a28020021040b2003200441206a360200200520046a220141186a200041296a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c0d0b200241023a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d12200441017422072006200720064b1b22074100480d120240024020040d002007102d21060c010b200128020020042007103121060b2006450d1320012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41023a00000240024020052802002206200328020022046b4120490d00200128020021060c010b200441206a22072004490d12200641017422042007200420074b1b22044100480d120240024020060d002004102d21060c010b200128020020062004103121060b2006450d1320012006360200200141046a2004360200200141086a28020021040b2003200441206a360200200620046a220441186a200041096a220641186a290000370000200441106a200641106a290000370000200441086a200641086a29000037000020042006290000370000200220002d002922063a000002400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d12200041017422052004200520044b1b22054100480d120240024020000d002005102d21040c010b200128020020002005103121040b2004450d1320012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a20063a00000c0c0b200241033a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d11200441017422072006200720064b1b22074100480d110240024020040d002007102d21060c010b200128020020042007103121060b2006450d1220012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41033a00000240024020052802002206200328020022046b4120490d00200128020021060c010b200441206a22072004490d11200641017422042007200420074b1b22044100480d110240024020060d002004102d21060c010b200128020020062004103121060b2006450d1220012006360200200141046a2004360200200141086a28020021040b2003200441206a360200200620046a220441186a200041096a220641186a290000370000200441106a200641106a290000370000200441086a200641086a290000370000200420062900003700000240024020052802002206200328020022046b4120490d00200128020021060c010b200441206a22072004490d11200641017422042007200420074b1b22044100480d110240024020060d002004102d21060c010b200128020020062004103121060b2006450d1220012006360200200141046a2004360200200141086a28020021040b2003200441206a360200200620046a220441186a200041296a220641186a290000370000200441106a200641106a290000370000200441086a200641086a290000370000200420062900003700004120102d2204450d11200441186a200041e1006a290000370000200441106a200041d9006a290000370000200441086a200041d1006a2900003700002004200041c9006a2900003700000240024020052802002207200328020022066b4120490d00200128020021070c010b200641206a22082006490d11200741017422062008200620084b1b22064100480d110240024020070d002006102d21070c010b200128020020072006103121070b2007450d1220012007360200200141046a2006360200200141086a28020021060b2003200641206a360200200720066a220641186a200441186a290000370000200641106a200441106a290000370000200641086a200441086a290000370000200620042900003700002004102f200041f8006a29030021092000290370210a0240024020052802002206200328020022046b4110490d00200128020021060c010b200441106a22072004490d11200641017422042007200420074b1b22044100480d110240024020060d002004102d21060c010b200128020020062004103121060b2006450d1220012006360200200141046a2004360200200141086a28020021040b2003200441106a360200200620046a220420093700082004200a370000200220002d006922063a000002400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d11200041017422052004200520044b1b22054100480d110240024020000d002005102d21040c010b200128020020002005103121040b2004450d1220012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a20063a00000c0b0b200241043a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d10200441017422072006200720064b1b22074100480d100240024020040d002007102d21060c010b200128020020042007103121060b2006450d1120012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41043a00004120102d2204450d10200441186a200041216a290000370000200441106a200041196a290000370000200441086a200041116a2900003700002004200041096a2900003700000240024020052802002205200328020022006b4120490d00200128020021050c010b200041206a22062000490d10200541017422002006200020064b1b22004100480d100240024020050d002000102d21050c010b200128020020052000103121050b2005450d1120012005360200200141046a2000360200200141086a28020021000b2003200041206a360200200520006a220041186a200441186a290000370000200041106a200441106a290000370000200041086a200441086a290000370000200020042900003700002004102f0c0a0b200241053a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d0f200441017422072006200720064b1b22074100480d0f0240024020040d002007102d21060c010b200128020020042007103121060b2006450d1020012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41053a0000200028020c21060240024020052802002204200328020022006b4104490d00200128020021040c010b200041046a22052000490d0f200441017422002005200020054b1b22004100480d0f0240024020040d002000102d21040c010b200128020020042000103121040b2004450d1020012004360200200141046a2000360200200141086a28020021000b2003200041046a360200200420006a20063600000c090b200241063a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d0e200441017422072006200720064b1b22074100480d0e0240024020040d002007102d21060c010b200128020020042007103121060b2006450d0f20012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41063a00000240024020052802002206200328020022046b4120490d00200128020021060c010b200441206a22072004490d0e200641017422042007200420074b1b22044100480d0e0240024020060d002004102d21060c010b200128020020062004103121060b2006450d0f20012006360200200141046a2004360200200141086a28020021040b2003200441206a360200200620046a220441186a200041096a220641186a290000370000200441106a200641106a290000370000200441086a200641086a29000037000020042006290000370000200220002d002922063a000002400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d0e200041017422052004200520044b1b22054100480d0e0240024020000d002005102d21040c010b200128020020002005103121040b2004450d0f20012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a20063a00000c080b200241073a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d0d200441017422072006200720064b1b22074100480d0d0240024020040d002007102d21060c010b200128020020042007103121060b2006450d0e20012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41073a00000240024020052802002205200328020022046b4120490d00200128020021050c010b200441206a22062004490d0d200541017422042006200420064b1b22044100480d0d0240024020050d002004102d21050c010b200128020020052004103121050b2005450d0e20012005360200200141046a2004360200200141086a28020021040b200141086a2206200441206a360200200520046a220441186a200041096a220541186a290000370000200441106a200541106a290000370000200441086a200541086a29000037000020042005290000370000200028022c2107200041346a28020022002001106902400240200141046a2802002205200628020022046b2000490d00200128020021050c010b200420006a22062004490d0d200541017422042006200420064b1b22044100480d0d0240024020050d002004102d21050c010b200128020020052004103121050b2005450d0e20012005360200200141046a2004360200200141086a28020021040b2003200420006a360200200520046a2007200010e8061a0c070b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0c200341017422052004200520044b1b22054100480d0c0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410e3a000020002d0001220341024b0d0602400240024020030e03000102000b200241003a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0e200341017422052004200520044b1b22054100480d0e0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0f20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200220002d000222043a000002400240200141046a28020020052802002200460d00200128020021030c010b200041016a22032000490d0e200041017422052003200520034b1b22054100480d0e0240024020000d002005102d21030c010b200128020020002005103121030b2003450d0f20012003360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200320006a20043a00000c080b200241013a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0d200341017422052004200520044b1b22054100480d0d0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0e20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d0d200441017422032005200320054b1b22034100480d0d0240024020040d002003102d21040c010b200128020020042003103121040b2004450d0e20012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041026a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c070b200241023a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0c200341017422052004200520044b1b22054100480d0c0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a0000200220002d000222043a000002400240200141046a28020020052802002200460d00200128020021030c010b200041016a22032000490d0c200041017422052003200520034b1b22054100480d0c0240024020000d002005102d21030c010b200128020020002005103121030b2003450d0d20012003360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200320006a20043a00000c060b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0b200341017422052004200520044b1b22054100480d0b0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0c20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410f3a000020002d0004220341024b0d0502400240024020030e03000102000b200241003a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0f200341017422052004200520044b1b22054100480d0f0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0e20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d0f200441017422032005200320054b1b22034100480d0f0240024020040d002003102d21040c010b200128020020042003103121040b2004450d1020012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041056a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c070b200241013a000002400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d0e200041017422042003200420034b1b22044100480d0e0240024020000d002004102d21030c010b200128020020002004103121030b2003450d0f20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41013a00000c060b200241023a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0d200341017422052004200520044b1b22054100480d0d0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0e20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a00002000280208210b200041106a2802002200200110692000450d05200b200041d0006c6a210c200141046a210703400240024020072802002203200528020022006b4120490d00200128020021030c010b200041206a22042000490d0e200341017422002004200020044b1b22004100480d0e0240024020030d002000102d21030c010b200128020020032000103121030b2003450d0f2001200336020020072000360200200528020021000b2005200041206a360200200320006a220041186a200b41186a290000370000200041106a200b41106a290000370000200041086a200b41086a2900003700002000200b2900003700002002200b41206a3602002002200110c2022002200b41306a3602002002200110c202200b2802402100200b28024822032001106902402003450d00200341306c210603400240024020072802002204200528020022036b4120490d00200128020021040c010b200341206a22082003490d10200441017422032008200320084b1b22034100480d100240024020040d002003102d21040c010b200128020020042003103121040b2004450d112001200436020020072003360200200528020021030b2005200341206a360200200420036a220341186a200041286a290000370000200341106a200041206a290000370000200341086a200041186a2900003700002003200041106a290000370000200220003602002002200110c202200041306a2100200641506a22060d000b0b200c200b41d0006a220b470d000c060b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0c200341017422052004200520044b1b22054100480d0c0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41103a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d0c200341017422052004200520044b1b22054100480d0c0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a000002400240200141046a2802002204200528020022036b4110490d00200128020021040c010b200341106a22052003490d0c200441017422032005200320054b1b22034100480d0c0240024020040d002003102d21040c010b200128020020042003103121040b2004450d0d20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341106a360200200420036a220341086a200041106a220441086a29000037000020032004290000370000200028020421062000410c6a28020022002001106902400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d0c200441017422032005200320054b1b22034100480d0c0240024020040d002003102d21040c010b200128020020042003103121040b2004450d0d20012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010e8061a0c040b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0b200341017422052004200520044b1b22054100480d0b0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0c20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41113a000020002d0008220341064b0d03024002400240024002400240024020030e0700010203040506000b200241003a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d11200341017422052004200520044b1b22054100480d110240024020030d002005102d21040c010b200128020020032005103121040b2004450d1220012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d11200441017422032005200320054b1b22034100480d110240024020040d002003102d21040c010b200128020020042003103121040b2004450d1220012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041096a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c090b200241013a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d10200341017422052004200520044b1b22054100480d100240024020030d002005102d21040c010b200128020020032005103121040b2004450d1120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d10200441017422032005200320054b1b22034100480d100240024020040d002003102d21040c010b200128020020042003103121040b2004450d1120012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200041386a29030021092000290330210a02400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d10200341017422002004200020044b1b22004100480d100240024020030d002000102d21030c010b200128020020032000103121030b2003450d1120012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a220020093700082000200a3700000c080b200241023a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0f200341017422052004200520044b1b22054100480d0f0240024020030d002005102d21040c010b200128020020032005103121040b2004450d1020012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d0f200441017422032005200320054b1b22034100480d0f0240024020040d002003102d21040c010b200128020020042003103121040b2004450d1020012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200041386a29030021092000290330210a02400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d0f200341017422002004200020044b1b22004100480d0f0240024020030d002000102d21030c010b200128020020032000103121030b2003450d1020012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a220020093700082000200a3700000c070b200241033a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0e200341017422052004200520044b1b22054100480d0e0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0f20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d0e200441017422032005200320054b1b22034100480d0e0240024020040d002003102d21040c010b200128020020042003103121040b2004450d0f20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200028022c210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d0e200341017422002005200020054b1b22004100480d0e0240024020030d002000102d21030c010b200128020020032000103121030b2003450d0f20012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c060b200141086a2802002103200241043a0000024002402003200141046a280200460d00200128020021040c010b200341016a22042003490d0d200341017422052004200520044b1b22054100480d0d0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0e20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d0d200441017422032005200320054b1b22034100480d0d0240024020040d002003102d21040c010b200128020020042003103121040b2004450d0e20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200028022c210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d0d200341017422002005200020054b1b22004100480d0d0240024020030d002000102d21030c010b200128020020032000103121030b2003450d0e20012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c050b200241053a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0c200341017422052004200520044b1b22054100480d0c0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41053a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d0c200441017422032005200320054b1b22034100480d0c0240024020040d002003102d21040c010b200128020020042003103121040b2004450d0d20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200028022c210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d0c200341017422002005200020054b1b22004100480d0c0240024020030d002000102d21030c010b200128020020032000103121030b2003450d0d20012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c040b200241063a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0b200341017422052004200520044b1b22054100480d0b0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0c20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41063a0000200028020c210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d0b200341017422002005200020054b1b22004100480d0b0240024020030d002000102d21030c010b200128020020032000103121030b2003450d0c20012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c030b02400240200141046a2205280200200141086a22032802002204460d00200128020021060c010b200441016a22062004490d0a200441017422072006200720064b1b22074100480d0a0240024020040d002007102d21060c010b200128020020042007103121060b2006450d0b20012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41123a000020002d00082204410e4b0d0202400240024002400240024002400240024002400240024002400240024020040e0f000102030405060708090a0b0c0d0e000b200241003a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d18200441017422072006200720064b1b22074100480d180240024020040d002007102d21060c010b200128020020042007103121060b2006450d1920012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41003a00000240024020052802002205200328020022046b4120490d00200128020021050c010b200441206a22062004490d18200541017422042006200420064b1b22044100480d180240024020050d002004102d21050c010b200128020020052004103121050b2005450d1920012005360200200141046a2004360200200141086a28020021040b2003200441206a360200200520046a220141186a200041096a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c100b200241013a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d17200441017422072006200720064b1b22074100480d170240024020040d002007102d21060c010b200128020020042007103121060b2006450d1820012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41013a00000240024020052802002206200328020022046b4120490d00200128020021060c010b200441206a22072004490d17200641017422042007200420074b1b22044100480d170240024020060d002004102d21060c010b200128020020062004103121060b2006450d1820012006360200200141046a2004360200200141086a28020021040b2003200441206a360200200620046a220441186a200041096a220641186a290000370000200441106a200641106a290000370000200441086a200641086a29000037000020042006290000370000200041386a29030021092000290330210a0240024020052802002204200328020022006b4110490d00200128020021040c010b200041106a22052000490d17200441017422002005200020054b1b22004100480d170240024020040d002000102d21040c010b200128020020042000103121040b2004450d1820012004360200200141046a2000360200200141086a28020021000b2003200041106a360200200420006a220020093700082000200a3700000c0f0b200241023a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d16200441017422072006200720064b1b22074100480d160240024020040d002007102d21060c010b200128020020042007103121060b2006450d1720012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41023a00000240024020052802002206200328020022046b4120490d00200128020021060c010b200441206a22072004490d16200641017422042007200420074b1b22044100480d160240024020060d002004102d21060c010b200128020020062004103121060b2006450d1720012006360200200141046a2004360200200141086a28020021040b2003200441206a360200200620046a220441186a200041096a220641186a290000370000200441106a200641106a290000370000200441086a200641086a29000037000020042006290000370000200041d8006a29030021092000290350210a0240024020052802002206200328020022046b4110490d00200128020021060c010b200441106a22072004490d16200641017422042007200420074b1b22044100480d160240024020060d002004102d21060c010b200128020020062004103121060b2006450d1720012006360200200141046a2004360200200141086a28020021040b2003200441106a360200200620046a220420093700082004200a3700000240024020052802002205200328020022046b4120490d00200128020021050c010b200441206a22062004490d16200541017422042006200420064b1b22044100480d160240024020050d002004102d21050c010b200128020020052004103121050b2005450d1720012005360200200141046a2004360200200141086a28020021040b2003200441206a360200200520046a220141186a200041296a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c0e0b200241033a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d15200441017422072006200720064b1b22074100480d150240024020040d002007102d21060c010b200128020020042007103121060b2006450d1620012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41033a00000240024020052802002205200328020022046b4120490d00200128020021050c010b200441206a22062004490d15200541017422042006200420064b1b22044100480d150240024020050d002004102d21050c010b200128020020052004103121050b2005450d1620012005360200200141046a2004360200200141086a28020021040b2003200441206a360200200520046a220141186a200041096a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c0d0b200241043a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d14200441017422072006200720064b1b22074100480d140240024020040d002007102d21060c010b200128020020042007103121060b2006450d1520012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41043a00000240024020052802002205200328020022046b4120490d00200128020021050c010b200441206a22062004490d14200541017422042006200420064b1b22044100480d140240024020050d002004102d21050c010b200128020020052004103121050b2005450d1520012005360200200141046a2004360200200141086a28020021040b2003200441206a360200200520046a220141186a200041096a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c0c0b200241053a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d13200441017422072006200720064b1b22074100480d130240024020040d002007102d21060c010b200128020020042007103121060b2006450d1420012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41053a00000240024020052802002205200328020022046b4120490d00200128020021050c010b200441206a22062004490d13200541017422042006200420064b1b22044100480d130240024020050d002004102d21050c010b200128020020052004103121050b2005450d1420012005360200200141046a2004360200200141086a28020021040b2003200441206a360200200520046a220141186a200041096a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c0b0b200241063a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d12200441017422072006200720064b1b22074100480d120240024020040d002007102d21060c010b200128020020042007103121060b2006450d1320012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41063a00000240024020052802002206200328020022046b4120490d00200128020021060c010b200441206a22072004490d12200641017422042007200420074b1b22044100480d120240024020060d002004102d21060c010b200128020020062004103121060b2006450d1320012006360200200141046a2004360200200141086a28020021040b200141086a220b200441206a360200200620046a220441186a200041096a220641186a290000370000200441106a200641106a290000370000200441086a200641086a29000037000020042006290000370000200028022c2104200041346a2802002200200110692000450d0a20004105742107200141046a210c03400240024020052802002206200328020022006b4120490d00200128020021060c010b200041206a22082000490d13200641017422002008200020084b1b22004100480d130240024020060d002000102d21060c010b200128020020062000103121060b2006450d1420012006360200200c2000360200200b28020021000b2003200041206a360200200620006a220041186a200441186a290000370000200041106a200441106a290000370000200041086a200441086a29000037000020002004290000370000200441206a2104200741606a22070d000c0b0b0b200241073a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d11200441017422072006200720064b1b22074100480d110240024020040d002007102d21060c010b200128020020042007103121060b2006450d1220012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41073a00000240024020052802002206200328020022046b4120490d00200128020021060c010b200441206a22072004490d11200641017422042007200420074b1b22044100480d110240024020060d002004102d21060c010b200128020020062004103121060b2006450d1220012006360200200141046a2004360200200141086a28020021040b2003200441206a360200200620046a220441186a200041096a220641186a290000370000200441106a200641106a290000370000200441086a200641086a29000037000020042006290000370000200220002d002922063a000002400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d11200041017422052004200520044b1b22054100480d110240024020000d002005102d21040c010b200128020020002005103121040b2004450d1220012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a20063a00000c090b200241083a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d10200441017422072006200720064b1b22074100480d100240024020040d002007102d21060c010b200128020020042007103121060b2006450d1120012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41083a00000240024020052802002205200328020022046b4120490d00200128020021050c010b200441206a22062004490d10200541017422042006200420064b1b22044100480d100240024020050d002004102d21050c010b200128020020052004103121050b2005450d1120012005360200200141046a2004360200200141086a28020021040b2003200441206a360200200520046a220141186a200041096a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c080b200241093a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d0f200441017422072006200720064b1b22074100480d0f0240024020040d002007102d21060c010b200128020020042007103121060b2006450d1020012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a41093a00000240024020052802002205200328020022046b4120490d00200128020021050c010b200441206a22062004490d0f200541017422042006200420064b1b22044100480d0f0240024020050d002004102d21050c010b200128020020052004103121050b2005450d1020012005360200200141046a2004360200200141086a28020021040b2003200441206a360200200520046a220141186a200041096a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c070b2002410a3a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d0e200441017422072006200720064b1b22074100480d0e0240024020040d002007102d21060c010b200128020020042007103121060b2006450d0f20012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a410a3a00000240024020052802002205200328020022046b4120490d00200128020021050c010b200441206a22062004490d0e200541017422042006200420064b1b22044100480d0e0240024020050d002004102d21050c010b200128020020052004103121050b2005450d0f20012005360200200141046a2004360200200141086a28020021040b2003200441206a360200200520046a220141186a200041096a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c060b2002410b3a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d0d200441017422072006200720064b1b22074100480d0d0240024020040d002007102d21060c010b200128020020042007103121060b2006450d0e20012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a410b3a00000240024020052802002206200328020022046b4120490d00200128020021060c010b200441206a22072004490d0d200641017422042007200420074b1b22044100480d0d0240024020060d002004102d21060c010b200128020020062004103121060b2006450d0e20012006360200200141046a2004360200200141086a28020021040b2003200441206a360200200620046a220441186a200041096a220641186a290000370000200441106a200641106a290000370000200441086a200641086a290000370000200420062900003700000240024020052802002206200328020022046b4120490d00200128020021060c010b200441206a22072004490d0d200641017422042007200420074b1b22044100480d0d0240024020060d002004102d21060c010b200128020020062004103121060b2006450d0e20012006360200200141046a2004360200200141086a28020021040b2003200441206a360200200620046a220441186a200041296a220641186a290000370000200441106a200641106a290000370000200441086a200641086a29000037000020042006290000370000200220002d004922063a000002400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d0d200041017422052004200520044b1b22054100480d0d0240024020000d002005102d21040c010b200128020020002005103121040b2004450d0e20012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a20063a00000c050b2002410c3a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d0c200441017422072006200720064b1b22074100480d0c0240024020040d002007102d21060c010b200128020020042007103121060b2006450d0d20012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a410c3a00000240024020052802002206200328020022046b4120490d00200128020021060c010b200441206a22072004490d0c200641017422042007200420074b1b22044100480d0c0240024020060d002004102d21060c010b200128020020062004103121060b2006450d0d20012006360200200141046a2004360200200141086a28020021040b2003200441206a360200200620046a220441186a200041096a220641186a290000370000200441106a200641106a290000370000200441086a200641086a29000037000020042006290000370000200220002d002922063a000002400240200528020020032802002200460d00200128020021040c010b200041016a22042000490d0c200041017422052004200520044b1b22054100480d0c0240024020000d002005102d21040c010b200128020020002005103121040b2004450d0d20012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a20063a00000c040b2002410d3a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d0b200441017422072006200720064b1b22074100480d0b0240024020040d002007102d21060c010b200128020020042007103121060b2006450d0c20012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a410d3a0000200028020c21060240024020052802002204200328020022006b4104490d00200128020021040c010b200041046a22052000490d0b200441017422002005200020054b1b22004100480d0b0240024020040d002000102d21040c010b200128020020042000103121040b2004450d0c20012004360200200141046a2000360200200141086a28020021000b2003200041046a360200200420006a20063600000c030b2002410e3a000002400240200528020020032802002204460d00200128020021060c010b200441016a22062004490d0a200441017422072006200720064b1b22074100480d0a0240024020040d002007102d21060c010b200128020020042007103121060b2006450d0b20012006360200200141046a2007360200200141086a28020021040b2003200441016a360200200620046a410e3a00000240024020052802002205200328020022046b4120490d00200128020021050c010b200441206a22062004490d0a200541017422042006200420064b1b22044100480d0a0240024020050d002004102d21050c010b200128020020052004103121050b2005450d0b20012005360200200141046a2004360200200141086a28020021040b2003200441206a360200200520046a220141186a200041096a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c020b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d09200341017422052004200520044b1b22054100480d090240024020030d002005102d21040c010b200128020020032005103121040b2004450d0a20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41133a000020002d0001220341054b0d01024002400240024002400240024020030e06000102030405000b200241003a000002400240200141046a280200200141086a2802002204460d00200128020021050c010b200441016a22032004490d0f200441017422052003200520034b1b22034100480d0f0240024020040d002003102d21050c010b200128020020042003103121050b2005450d1020012005360200200141046a2003360200200141086a28020021040b200041026a2103200141086a200441016a360200200520046a41003a00000c050b200241013a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0e200341017422052004200520044b1b22054100480d0e0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0f20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a000002400240200141046a2802002203200528020022046b4120490d00200128020021050c010b200441206a22052004490d0e200341017422042005200420054b1b22044100480d0e0240024020030d002004102d21050c010b200128020020032004103121050b2005450d0f20012005360200200141046a2004360200200141086a28020021040b200041226a2103200141086a200441206a360200200520046a220441186a200041026a220041186a290000370000200441106a200041106a290000370000200441086a200041086a290000370000200420002900003700000c040b200141086a2802002103200141046a2802002104200241023a00000240024020042003460d00200128020021040c010b200341016a22042003490d0d200341017422052004200520044b1b22054100480d0d0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0e20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d0d200441017422032005200320054b1b22034100480d0d0240024020040d002003102d21040c010b200128020020042003103121040b2004450d0e20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041026a220441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002003200429000037000002400240200141046a2802002203200528020022046b4120490d00200128020021050c010b200441206a22052004490d10200341017422042005200420054b1b22044100480d100240024020030d002004102d21050c010b200128020020032004103121050b2005450d0e20012005360200200141046a2004360200200141086a28020021040b200041c2006a2103200141086a200441206a360200200520046a220441186a200041226a220041186a290000370000200441106a200041106a290000370000200441086a200041086a290000370000200420002900003700000c030b200241033a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0f200341017422052004200520044b1b22054100480d0f0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0e20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a000002400240200141046a2802002203200528020022046b4120490d00200128020021050c010b200441206a22052004490d0f200341017422042005200420054b1b22044100480d0f0240024020030d002004102d21050c010b200128020020032004103121050b2005450d0e20012005360200200141046a2004360200200141086a28020021040b200041226a2103200141086a200441206a360200200520046a220441186a200041026a220041186a290000370000200441106a200041106a290000370000200441086a200041086a290000370000200420002900003700000c020b200141086a2802002103200241043a0000024002402003200141046a280200460d00200128020021040c010b200341016a22042003490d0e200341017422052004200520044b1b22054100480d0e0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a000002400240200141046a2802002203200528020022046b4120490d00200128020021050c010b200441206a22052004490d0e200341017422042005200420054b1b22044100480d0e0240024020030d002004102d21050c010b200128020020032004103121050b2005450d0d20012005360200200141046a2004360200200141086a28020021040b200041226a2103200141086a200441206a360200200520046a220441186a200041026a220041186a290000370000200441106a200041106a290000370000200441086a200041086a290000370000200420002900003700000c010b200241053a000002400240200141046a280200200141086a2802002204460d00200128020021050c010b200441016a22032004490d0d200441017422052003200520034b1b22034100480d0d0240024020040d002003102d21050c010b200128020020042003103121050b2005450d0c20012005360200200141046a2003360200200141086a28020021040b200041026a2103200141086a200441016a360200200520046a41053a00000b02400240200141046a2802002204200141086a28020022006b4120490d00200128020021040c010b200041206a22052000490d0c200441017422002005200020054b1b22004100480d0c0240024020040d002000102d21040c010b200128020020042000103121040b2004450d0b20012004360200200141046a2000360200200141086a28020021000b200141086a200041206a360200200420006a220041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a290000370000200020032900003700000c010b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0b200341017422052004200520044b1b22054100480d0b0240024020030d002005102d21040c010b200128020020032005103121040b2004450d0a20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41143a0000200041096a2103024020002d00084101460d0002400240200141046a28020020052802002204460d00200128020021050c010b200441016a22052004490d0c200441017422062005200620054b1b22064100480d0c0240024020040d002006102d21050c010b200128020020042006103121050b2005450d0b20012005360200200141046a2006360200200141086a28020021040b200141086a2206200441016a360200200520046a41003a000002400240200141046a2802002205200628020022046b4120490d00200128020021050c010b200441206a22062004490d0c200541017422042006200420064b1b22044100480d0c0240024020050d002004102d21050c010b200128020020052004103121050b2005450d0b20012005360200200141046a2004360200200141086a28020021040b200141086a2206200441206a360200200520046a220441186a200341186a290000370000200441106a200341106a290000370000200441086a200341086a29000037000020042003290000370000200041386a29030021092000290330210a02400240200141046a2802002203200628020022006b4110490d00200128020021030c010b200041106a22042000490d0c200341017422002004200020044b1b22004100480d0c0240024020030d002000102d21030c010b200128020020032000103121030b2003450d0b20012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a220020093700082000200a3700000c010b02400240200141046a28020020052802002200460d00200128020021040c010b200041016a22042000490d0b200041017422052004200520044b1b22054100480d0b0240024020000d002005102d21040c010b200128020020002005103121040b2004450d0a20012004360200200141046a2005360200200141086a28020021000b200141086a2205200041016a360200200420006a41013a000002400240200141046a2802002204200528020022006b4120490d00200128020021040c010b200041206a22052000490d0b200441017422002005200020054b1b22004100480d0b0240024020040d002000102d21040c010b200128020020042000103121040b2004450d0a20012004360200200141046a2000360200200141086a28020021000b200141086a200041206a360200200420006a220041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a290000370000200020032900003700000b200241106a24000f0b1036000b1038000b1038000b1036000b1038000b1036000b1038000b1036000b1036000b1038000bcf2701057f02400240024020002d0000220241064b0d00024002400240024002400240024020020e0700010203040506000b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d09200241017422042003200420034b1b22044100480d090240024020020d002004102d21030c010b200128020020022004103121030b2003450d0820012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41003a000002400240200141046a2802002203200428020022026b4120490d00200128020021030c010b200241206a22042002490d09200341017422022004200220044b1b22024100480d090240024020030d002002102d21030c010b200128020020032002103121030b2003450d0820012003360200200141046a2002360200200141086a28020021020b200141086a2204200241206a360200200320026a220241186a200041196a290000370000200241106a200041116a290000370000200241086a200041096a290000370000200220002900013700002000280244210502400240200141046a2802002203200428020022026b4104490d00200128020021030c010b200241046a22042002490d09200341017422022004200220044b1b22024100480d090240024020030d002002102d21030c010b200128020020032002103121030b2003450d0820012003360200200141046a2002360200200141086a28020021020b200141086a2206200241046a360200200320026a20053600004120102d2202450d07200241186a200041396a290000370000200241106a200041316a290000370000200241086a200041296a2900003700002002200041216a29000037000002400240200141046a2802002204200628020022036b4120490d00200128020021040c010b200341206a22052003490d09200441017422032005200320054b1b22034100480d090240024020040d002003102d21040c010b200128020020042003103121040b2004450d0820012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200241186a290000370000200341106a200241106a290000370000200341086a200241086a290000370000200320022900003700002002102f2000280248210302400240200141046a2802002202200528020022006b4104490d00200128020021020c010b200041046a22042000490d09200241017422002004200020044b1b22004100480d090240024020020d002000102d21020c010b200128020020022000103121020b2002450d0820012002360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200220006a20033600000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d08200241017422042003200420034b1b22044100480d080240024020020d002004102d21030c010b200128020020022004103121030b2003450d0720012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41013a000002400240200141046a2802002203200428020022026b4120490d00200128020021030c010b200241206a22042002490d08200341017422022004200220044b1b22024100480d080240024020030d002002102d21030c010b200128020020032002103121030b2003450d0720012003360200200141046a2002360200200141086a28020021020b200141086a2205200241206a360200200320026a220241186a200041196a290000370000200241106a200041116a290000370000200241086a200041096a290000370000200220002900013700004120102d2202450d06200241186a200041396a290000370000200241106a200041316a290000370000200241086a200041296a2900003700002002200041216a29000037000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d08200441017422032005200320054b1b22034100480d080240024020040d002003102d21040c010b200128020020042003103121040b2004450d0720012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200241186a290000370000200341106a200241106a290000370000200341086a200241086a290000370000200320022900003700002002102f20002d0041210402400240200141046a28020020052802002202460d00200128020021030c010b200241016a22032002490d08200241017422052003200520034b1b22054100480d080240024020020d002005102d21030c010b200128020020022005103121030b2003450d0720012003360200200141046a2005360200200141086a28020021020b200141086a2205200241016a360200200320026a20043a00002000280244210402400240200141046a2802002203200528020022026b4104490d00200128020021030c010b200241046a22052002490d08200341017422022005200220054b1b22024100480d080240024020030d002002102d21030c010b200128020020032002103121030b2003450d0720012003360200200141046a2002360200200141086a28020021020b200141086a2205200241046a360200200320026a20043600002000280248210302400240200141046a2802002202200528020022006b4104490d00200128020021020c010b200041046a22042000490d08200241017422002004200020044b1b22004100480d080240024020020d002000102d21020c010b200128020020022000103121020b2002450d0720012002360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200220006a20033600000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d07200241017422042003200420034b1b22044100480d070240024020020d002004102d21030c010b200128020020022004103121030b2003450d0620012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41023a00004120102d2202450d0520022000290001370000200241186a200041196a290000370000200241106a200041116a290000370000200241086a200041096a29000037000002400240200141046a2802002203200428020022006b4120490d00200128020021030c010b200041206a22042000490d07200341017422002004200020044b1b22004100480d070240024020030d002000102d21030c010b200128020020032000103121030b2003450d0620012003360200200141046a2000360200200141086a28020021000b200141086a200041206a360200200320006a220141186a200241186a290000370000200141106a200241106a290000370000200141086a200241086a290000370000200120022900003700002002102f0f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d06200241017422042003200420034b1b22044100480d060240024020020d002004102d21030c010b200128020020022004103121030b2003450d0520012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41033a00004120102d2202450d0420022000290001370000200241186a200041196a290000370000200241106a200041116a290000370000200241086a200041096a29000037000002400240200141046a2802002203200428020022006b4120490d00200128020021030c010b200041206a22042000490d06200341017422002004200020044b1b22004100480d060240024020030d002000102d21030c010b200128020020032000103121030b2003450d0520012003360200200141046a2000360200200141086a28020021000b200141086a200041206a360200200320006a220141186a200241186a290000370000200141106a200241106a290000370000200141086a200241086a290000370000200120022900003700002002102f0f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d05200241017422042003200420034b1b22044100480d050240024020020d002004102d21030c010b200128020020022004103121030b2003450d0420012003360200200141046a2004360200200141086a28020021020b200141086a2205200241016a360200200320026a41043a00004120102d2202450d0320022000290001370000200241186a200041196a290000370000200241106a200041116a290000370000200241086a200041096a29000037000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d05200441017422032005200320054b1b22034100480d050240024020040d002003102d21040c010b200128020020042003103121040b2004450d0420012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200241186a290000370000200341106a200241106a290000370000200341086a200241086a290000370000200320022900003700002002102f20002d0021210302400240200141046a28020020052802002200460d00200128020021020c010b200041016a22022000490d05200041017422042002200420024b1b22044100480d050240024020000d002004102d21020c010b200128020020002004103121020b2002450d0420012002360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200220006a20033a00000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d04200241017422042003200420034b1b22044100480d040240024020020d002004102d21030c010b200128020020022004103121030b2003450d0320012003360200200141046a2004360200200141086a28020021020b200141086a2205200241016a360200200320026a41053a00004120102d2202450d0220022000290001370000200241186a200041196a290000370000200241106a200041116a290000370000200241086a200041096a29000037000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d04200441017422032005200320054b1b22034100480d040240024020040d002003102d21040c010b200128020020042003103121040b2004450d0320012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200241186a290000370000200341106a200241106a290000370000200341086a200241086a290000370000200320022900003700002002102f20002d0021210302400240200141046a28020020052802002200460d00200128020021020c010b200041016a22022000490d04200041017422042002200420024b1b22044100480d040240024020000d002004102d21020c010b200128020020002004103121020b2002450d0320012002360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200220006a20033a00000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d03200241017422042003200420034b1b22044100480d030240024020020d002004102d21030c010b200128020020022004103121030b2003450d0220012003360200200141046a2004360200200141086a28020021020b200141086a2205200241016a360200200320026a41063a00004120102d2202450d0120022000290001370000200241186a200041196a290000370000200241106a200041116a290000370000200241086a200041096a29000037000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d03200441017422032005200320054b1b22034100480d030240024020040d002003102d21040c010b200128020020042003103121040b2004450d0220012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200241186a290000370000200341106a200241106a290000370000200341086a200241086a290000370000200320022900003700002002102f2000280224210402400240200141046a2802002203200528020022026b4104490d00200128020021030c010b200241046a22052002490d03200341017422022005200220054b1b22024100480d030240024020030d002002102d21030c010b200128020020032002103121030b2003450d0220012003360200200141046a2002360200200141086a28020021020b200141086a2205200241046a360200200320026a20043600002000280228210302400240200141046a2802002202200528020022006b4104490d00200128020021020c010b200041046a22042000490d03200241017422002004200020044b1b22004100480d030240024020020d002000102d21020c010b200128020020022000103121020b2002450d0220012002360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200220006a20033600000b0f0b1036000b1038000b881901057f230041206b22022400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802000e1b010214030405060708090a0b0c0d0e0f1011121314141415161700010b4190ce0021030240200141086a2802002201417f6a4102490d0002400240024020010e0400010102000b2002411c6a41013602002002420137020c200241b4d8c90036020820024104360204200241fcdbc90036020020022002360218200241086a41e8d8c90010430b000b41c0843d21030b20004180023b0104200020033602000c170b024002400240024002400240024002400240024002400240200141086a2802000e0b000102030405060708090a000b2002411c6a41013602002002420137020c200241b4d8c90036020820024104360204200241fcdbc90036020020022002360218200241086a41e8d8c9001043000b200041013a000420002001410c6a2802003602000c090b200041003a000420004190ce003602000c080b200041013a000420004190ce003602000c070b200041013a0004200041c09a0c3602000c060b200041013a0004200041c09a0c3602000c050b200041013a0004200041a09c013602000c040b200041013a000420004190ce003602000c030b200041013a000420004190ce003602000c020b200041013a000420004190ce003602000c010b200041013a0004200041a8c3013602000b200041013a00050c160b0240024002400240024002400240024020012d00040e06000102030405000b2002411c6a41013602002002420137020c200241b4d8c90036020820024104360204200241fcdbc90036020020022002360218200241086a41e8d8c9001043000b200141086a28020021044190ce0021030240200141106a280200220541b0026c2206450d00200421010340200241086a200110f102200141b0026a2101200228020820036a2103200641d07d6a22060d000b0b200541b0026c21010340024020010d00410121010c070b200141d07d6a2101200241086a200410f102200441b0026a210420022d000c0d000c050b0b200241086a200141086a280200220110f10220022802082103200241086a200110f10220034190ce006a210320022d000c21010c040b200241086a200141206a280200220310f102200141106a280200210120022802082104200241086a200310f102200420014190ce006c6a4190ce006a210320022d000c21010c030b200141306a2802004190ce006c4190ce006a21030c010b200141306a2802004190ce006c4190ce006a21030b410021010b200041013a0005200020013a0004200020033602000c150b20004181023b010420004190ce003602000c140b20004181023b010420004190ce003602000c130b20004180023b010420004190ce003602000c120b4100210341c0843d2104024002400240200141086a2802000e050002010202000b2002411c6a41013602002002420137020c200241b4d8c90036020820024104360204200241fcdbc90036020020022002360218200241086a41e8d8c9001043000b4101210341d0860321040b200041013a0005200020033a0004200020043602000c110b4100210441a0c21e210302400240024002400240024002400240200141086a2d00000e1600070701010202070702030303030603040707070506000b2002411c6a41013602002002420137020c200241b4d8c90036020820024104360204200241fcdbc90036020020022002360218200241086a41e8d8c9001043000b4180b51821030c050b41b0e32d21030c040b41882721030c030b41c0843d21030c020b410121040c010b4190ce0021030b200041013a0005200020043a0004200020033602000c100b20004180023b0104200041f093093602000c0f0b4100210441c096b1022103024002400240024002400240024002400240200141086a2d00000e18000808010102080808030304040707070505060707060607000b2002411c6a41013602002002420137020c200241b4d8c90036020820024104360204200241fcdbc90036020020022002360218200241086a41e8d8c9001043000b41c09a0c21030c060b4101210441a0c21e21030c050b41c09a0c21030c040b410121044190ce0021030c030b41a0c21e21030c020b4190ce0021030c010b41a08d0621030b200041013a0005200020043a0004200020033602000c0e0b41a08d062103024002400240024020012d00040e06000303010202000b2002411c6a41013602002002420137020c200241b4d8c90036020820024104360204200241fcdbc90036020020022002360218200241086a41e8d8c9001043000b41c096b10221030c010b41c09a0c21030b20004181023b0104200020033602000c0d0b41a08d062103024002400240024020012d00040e06000303010202000b2002411c6a41013602002002420137020c200241b4d8c90036020820024104360204200241fcdbc90036020020022002360218200241086a41e8d8c9001043000b41c096b10221030c010b41c09a0c21030b20004181023b0104200020033602000c0c0b4100210441a08d062103024002400240024002400240200141086a2802000e0700050102030404000b2002411c6a41013602002002420137020c200241b4d8c90036020820024104360204200241fcdbc90036020020022002360218200241086a41e8d8c9001043000b4190ce0021030c030b41c0843d21030c020b41a0c21e21030c010b41012104418089fa0021030b200041013a0005200020043a0004200020033602000c0b0b20004180023b0104200041d086033602000c0a0b20004180023b010420004190ce003602000c090b20004180023b010420004190ce003602000c080b4100210441a0c21e2103024002400240024002400240200141086a2d00000e09000501010204030404000b2002411c6a41013602002002420137020c200241b4d8c90036020820024104360204200241fcdbc90036020020022002360218200241086a41e8d8c9001043000b410121040b41a08d0621030c020b41f0930921030c010b41d0860321030b200041013a0005200020043a0004200020033602000c070b20004180023b010420004190ce003602000c060b0240024002400240024020012802040e0400010203000b2002411c6a41013602002002420137020c200241b4d8c90036020820024104360204200241fcdbc90036020020022002360218200241086a41e8d8c9001043000b200241086a200141086a280200220110f10220022802082103200241086a200110f102200020022d000c3a0004200020034190ce006a3602000c020b200041003a000420004190ce003602000c010b200241086a2001412c6a280200220110f10220022802082103200241086a200110f102200020022d000c3a0004200020034190ce006a3602000b200041013a00050c050b20004180023b010420004190ce003602000c040b10e101000b4190ce0021030240024002400240200141086a2d00000e0c000301010101010101010102000b2002411c6a41013602002002420137020c200241b4d8c90036020820024104360204200241fcdbc90036020020022002360218200241086a41e8d8c9001043000b41d0860321030c010b41a08d0621030b20004180023b0104200020033602000c020b41d086032103024002400240024002400240024002400240200141086a2d00000e0d00080108010203040705060807000b2002411c6a41013602002002420137020c200241b4d8c90036020820024104360204200241fcdbc90036020020022002360218200241086a41e8d8c9001043000b41a09c0121030c060b41b0ea0121030c050b41a09c0121030c040b41b0ea0121030c030b41a09c0121030c020b41b0ea0121030c010b4190ce0021030b20004180023b0104200020033602000c010b0240024002400240024002400240024002400240024020012d00040e0a00010203040506070809000b2002411c6a41013602002002420137020c200241b4d8c90036020820024104360204200241fcdbc90036020020022002360218200241086a41e8d8c9001043000b200241086a200141286a280200220110f10220022802082103200241086a200110f102200020022d000c3a0004200020034190ce006a3602000c080b200041003a000420004190ce003602000c070b200041003a0004200041a08d063602000c060b200041003a0004200041a08d063602000c050b200041003a0004200041a08d063602000c040b200041003a0004200041a08d063602000c030b200041003a0004200041b0ea013602000c020b200041003a0004200041b0ea013602000c010b200041003a000420004190ce003602000b200041013a00050b200241206a24000b87260b017f017e027f017e027f047e017f097e017f027e037f23004180086b22062400200620043703102006200337030820062001360204200620053a001f02400240024002400240024020012002460d002003200484500d0020012002412010ea06450d00418de6c300ad4280808080e0008410012201290000210320064180056a41086a200141086a29000037030020062003370380052001102f41f0e8c600ad4280808080f0008410012201290000210320064180066a41086a200141086a29000037030020062003370380062001102f4120102d2201450d0120012002290000370000200141186a200241186a290000370000200141106a200241106a290000370000200141086a200241086a2900003700002001ad4280808080800484100322052900002103200541086a2900002104200541106a290000210720064180076a41186a2208200541186a29000037030020064180076a41106a2209200737030020064180076a41086a200437030020062003370380072005102f2001102f41c000102d2201450d01200120062903800537000020012006290380063700102001200629038007370020200141086a20064180056a41086a290300370000200141186a20064180066a41086a290300370000200141286a20064180076a41086a290300370000200141306a2009290300370000200141386a2008290300370000200641206a200110f602200629032021074200210a20064200370320200641e8006a280200210b20062d006c210c0240024020074201510d00200641f0006a41386a4200370300200641f0006a41306a4200370300200641f0006a41286a4200370300200641f0006a41206a420037030020064188016a420037030020064180016a4200370300200641f0006a41086a4200370300200642003703704200210d4200210e4200210f0c010b200641206a41386a2903002103200641206a41306a2903002104200641206a41206a290300210d200641206a41186a290300210a200641206a41c0006a29030021102006290330210f2006290328210e200641f0006a41206a200641206a41286a290300370300200641f0006a41286a2004370300200641f0006a41306a200337030020064180016a200a3703002006200d37038801200620103703a8012006200e3703702006200f3703780b20062802042108418de6c300ad4280808080e0008410012205290000210320064180046a41086a200541086a29000037030020062003370380042005102f41f0e8c600ad4280808080f00084100122052900002103200641c8046a41086a200541086a290000370300200620033703c8042005102f4120102d2205450d0120052008290000370000200541186a200841186a290000370000200541106a200841106a290000370000200541086a200841086a2900003700002005ad4280808080800484100322092900002103200941086a2900002104200941106a290000211020064180076a41186a2211200941186a29000037030020064180076a41106a201037030020064180076a41086a200437030020062003370380072009102f2005102f41c000102d2205450d012005200629038004370000200520062903c8043700102005200629038007370020200541086a20064180046a41086a290300370000200541186a200641c8046a41086a290300370000200541286a20064180076a41086a290300370000200541306a20064180076a41106a290300370000200541386a2011290300370000200641b0036a200510f60220062903b003211242002113200642003703b003200641f8036a280200210920062d00fc0321110240024020124201510d0020064190046a41306a420037030020064190046a41286a420037030020064190046a41206a4200370300200641a8046a420037030020064190046a41106a420037030020064190046a41086a42003703002006420037039004420021144200210442002103420021150c010b200641b0036a41386a2903002110200641b0036a41306a2903002116200641b0036a41206a2903002114200641b0036a41186a2903002113200641b0036a41c0006a290300211520062903c003210320062903b803210420064190046a41206a200641b0036a41286a29030037030020064190046a41286a201637030020064190046a41306a201037030020064190046a41106a2013370300200620143703a804200620043703900420062003370398040b02402004200629030822167d22172004562003200641086a41086a29030022187d2004201654ad7d221020035620102003511b450d004198b5c600ad21034280808080b002210441838c0c21090c040b2006201737039004200620103703980402402006290370221920167c221a201954221b200641f0006a41086a290300221c20187c201bad7c2219201c542019201c511b450d004191ccc700ad210342808080808001210441838c0821090c040b2006201a37037020064188016a290300211c200620193703780240427f201a2006290380017c221d201d201a54221b2019201c7c201bad7c221c201954201c2019511b221b1b428080e983b1de16544100427f201c201b1b501b450d004186b5c600ad21034280808080a002210441838c1021090c040b02402016201884500d0020064180076a2006280204108d0220062903a007201756200641a8076a290300221620105620162010511b450d0041abb5c600ad21034280808080d002210441838c0421090c040b0240024020062d001f4101460d002017428080e983b1de165441002010501b450d0141fdb4c600ad21030c040b2006280204211e418de6c300ad4280808080e000841001221b290000211620064180046a41086a201b41086a2900003703002006201637038004201b102f41f0e8c600ad4280808080f000841001221b2900002116200641c8046a41086a201b41086a290000370300200620163703c804201b102f4120102d221b450d02201b201e290000370000201b41186a201e41186a290000370000201b41106a201e41106a290000370000201b41086a201e41086a290000370000201bad42808080808004841003221e2900002116201e41086a2900002119201e41106a290000211820064180076a41186a221f201e41186a29000037030020064180076a41106a2220201837030020064180076a41086a20193703002006201637038007201e102f201b102f41c000102d221b450d02201b200629038004370000201b20062903c804370010201b200629038007370020201b41086a20064180046a41086a290300370000201b41186a200641c8046a41086a290300370000201b41286a20064180076a41086a290300370000201b41306a2020290300370000201b41386a201f29030037000020064180076a201b10f60220062d00cc07211e2006290380072116201b102f201e450d0020164201520d002017428080e983b1de165441002010501b450d0041fdb4c600ad21030c030b200641c8046a41186a200641a0046a221b41086a2903002216370300200641c8046a41206a221e201b41106a290300370300200641f0046a221f201b41186a290300370300200641f8046a2220201b41206a2903003703002006201b29030022193703d804200620173703c804200620103703d004427f200420137c22132013200454221b200320147c201bad7c220420035420042003511b221b1b427f2004201b1b84211302400240427f201720197c22032003201754221b201020167c201bad7c220320105420032010511b221b1b2204428080e983b1de16544100427f2003201b1b2203501b0d00200641c8046a41106a290300210320202903002104201f2903002116201e290300211920062903d004211820062903c80421144201211c20062903e004211a0c010b4200211c02402004200384500d0020042003109a01200641b8076a2003370300200641b0076a200437030020064180076a41086a41013a000020064189076a200829000037000020064191076a200841086a29000037000020064199076a200841106a290000370000200641a1076a200841186a290000370000200641033a00800741c8e1ca00410020064180076a108c010b0b201350211e200641d8036a2019370300200641e0036a2016370300200641c0036a2018370300200641e8036a2004370300200641c8036a20033703002006201a3703d003200620153703f003200620143703b8034100211b2006201141002012420151221f1b3a00fc03200620094100201f1b3602f8032006201c4201512209ad3703b0030240024020090d002005ad428080808080088410054101211b0c010b200641c000360284072006200536028007200641b8036a20064180076a1090030b201ead21032005102f02400240024020124201510d00201b0d004103210920064180066a21050c010b2012420152201b410173720d014104210920064180056a21050b200541046a20093a0000200541003a0000200541056a20082900003700002005410d6a200841086a290000370000200541156a200841106a2900003700002005411d6a200841186a29000037000041c8e1ca0041002005108c010b41002111410421092003500d04200641b8076a2010370300200641b0076a20173703004100211120064180076a41086a41003a000020064189076a200829000037000020064191076a200841086a29000037000020064199076a200841106a290000370000200641a1076a200841186a290000370000200641033a00800741c8e1ca00410020064180076a108c010c040b200041043a00000c040b1036000b42808080809001210441838c1421090b2005102f20094108762111200320048421030b20064180056a41086a2208200641f0006a41106a220541086a29030037030020064180056a41106a221b200541106a29030037030020064180056a41186a221e200541186a29030037030020064180056a41206a221f200541206a29030037030020062005290300370380050240200941ff01714104470d00200641f0006a41086a29030021032006290370210420062903a801211620064180066a41186a2008290300221237030020064180066a41206a201b290300370300200641a8066a2208201e290300370300200641b0066a2209201f290300370300200620062903800522133703900620062004370380062006200337038806427f200e200a7c22102010200e542205200f200d7c2005ad7c2210200f542010200f511b22051b427f201020051b84210a02400240427f200420137c220f200f2004542205200320127c2005ad7c220f200354200f2003511b22051b2210428080e983b1de16544100427f200f20051b220f501b0d0020064190066a290300210f200929030021102008290300210e200641a0066a29030021122006290388062113200629038006210d4201211920062903980621170c010b4200211902402010200f84500d002010200f109a01200641b8076a200f370300200641b0076a201037030020064180076a41086a41013a000020064189076a200229000037000020064191076a200241086a29000037000020064199076a200241106a290000370000200641a1076a200241186a290000370000200641033a00800741c8e1ca00410020064180076a108c010b0b200a502108200641c8006a2012370300200641d0006a200e370300200641306a2013370300200641d8006a2010370300200641386a200f37030020062017370340200620163703602006200d370328410021052006200c4100200742015122091b3a006c2006200b410020091b360268200620194201512209ad3703200240024020090d002001ad42808080808008841005410121050c010b200641c000360284072006200136028007200641286a20064180076a1090030b2008ad210f2001102f02400240024020074201510d0020050d0041032105200641b0026a21010c010b20074201522005410173720d0141042105200641b0016a21010b200141046a20053a0000200141003a0000200141056a20022900003700002001410d6a200241086a290000370000200141156a200241106a2900003700002001411d6a200241186a29000037000041c8e1ca0041002001108c010b0240200f500d00200641b8076a2003370300200641b0076a200437030020064180076a41086a41003a000020064189076a200229000037000020064191076a200241086a29000037000020064199076a200241106a290000370000200641a1076a200241186a290000370000200641033a00800741c8e1ca00410020064180076a108c010b2006280204210120062903082103200641d8076a200641086a41086a290300370300200641d0076a200337030020064180076a41086a41023a000020064189076a200129000037000020064191076a200141086a29000037000020064199076a200141106a290000370000200641a1076a200141186a290000370000200641a9076a2002290000370000200641b1076a200241086a290000370000200641b9076a200241106a290000370000200641c1076a200241186a290000370000200641033a00800741c8e1ca00410020064180076a108c01200041043a00000c010b2001102f200041036a41003a0000200020113b0001200041046a2003370000200020093a00000b20064180086a24000bf00204027f017e017f077e0240024020012802042202450d0020012802002203310000210420012002417f6a22053602042001200341016a3602002005450d012003310001210620012002417e6a22053602042001200341026a3602002005450d012003310002210720012002417d6a22053602042001200341036a3602002005450d012003310003210820012002417c6a22053602042001200341046a3602002005450d012003310004210920012002417b6a22053602042001200341056a3602002005450d012003310005210a20012002417a6a22053602042001200341066a3602002005450d012003310006210b2001200241796a22053602042001200341076a3602002005450d01200041003a00002003310007210c2001200241786a3602042001200341086a3602002000200c423886200b42308684200a422886842009422086842008421886842007421086842006420886842004843700010f0b200041013a00000f0b200041013a00000bb20201037f230041e0006b220224002002412036020c20022001360208200241106a2001ad4280808080800484100210730240024020022802102201450d00200228021421032002200241186a28020036022420022001360220200241c8006a200241206a10f5030240024020022802482204450d002000200229024c370204200020043602000c010b20024100360230200242013703282002410b36023c2002200241086a3602382002200241286a360244200241dc006a41013602002002420137024c200241b885c7003602482002200241386a360258200241c4006a41d8dbc100200241c8006a103c1a200235023042208620023502288410080240200228022c450d002002280228102f0b200041003602000b2003450d012001102f0c010b200041003602000b200241e0006a24000b850301087f230041206b22032400024002400240200141246c41046a2204417f4c0d000240024020040d00410121050c010b2004102d2205450d020b2003410036020820032004360204200320053602002001200310690240024020010d002003280208210420032802042106200328020021050c010b200141246c210720032802042106200328020821010340200341106a200010ea022003280210210802400240200620016b20032802182209490d00200120096a2104200328020021050c010b200120096a22042001490d05200641017422052004200520044b1b220a4100480d050240024020060d00200a102d21050c010b20032802002006200a103121050b2005450d042003200a36020420032005360200200a21060b20032004360208200520016a2008200910e8061a02402003280214450d002008102f0b200041246a2100200421012007415c6a22070d000b0b20022902002004ad4220862005ad84100402402006450d002005102f0b200341206a24000f0b103d000b1036000b1038000be40603047f017e0f7f230041c0016b22022400200241c00036020c20022001360208200241106a2001ad4280808080800884100210730240024020022802102201450d00200228021421032002200241186a28020022043602642002200136026002400240024020044104490d0020022004417c6a22053602642002200141046a3602602005450d002001280000210520022004417b6a3602642002200141056a36026020012d00042104200241f8006a200241e0006a1085054201210620022903784201520d010b20024100360228200242013703202002410b36026c2002200241086a3602682002200241206a3602742002418c016a41013602002002420137027c200241b885c7003602782002200241e8006a36028801200241f4006a41d8dbc100200241f8006a103c1a2002350228422086200235022084100802402002280224450d002002280220102f0b420021060c010b200241206a41386a2207200241f8006a41c0006a290300370300200241206a41306a2208200241f8006a41386a2209290300370300200241206a41286a220a200241f8006a41306a220b290300370300200241206a41206a220c200241f8006a41286a220d290300370300200241206a41186a220e200241f8006a41206a220f290300370300200241206a41106a2210200241f8006a41186a2211290300370300200241206a41086a2212200241f8006a41106a2213290300370300200241f4006a41026a2214200241e8006a41026a22152d00003a00002002200229038001370320200220022f00683b017420092007290300370300200b2008290300370300200d200a290300370300200f200c2903003703002011200e29030037030020132010290300370300200241f8006a41086a2207201229030037030020022002290320370378201520142d00003a0000200220022f01743b0168200020043a004c200041c8006a2005360200200041c0006a2009290300370300200041386a200b290300370300200041306a200d290300370300200041286a200f290300370300200041206a2011290300370300200041186a2013290300370300200041106a200729030037030020002002290378370308200020022f01683b004d200041cf006a20152d00003a00000b200020063703002003450d012001102f0c010b200042003703000b200241c0016a24000b940201047f230041d0006b220124002001412036020420012000360200200141086a2000ad42808080808004841002107302400240200128020822020d00410221000c010b200128020c210302400240200141106a280200450d0020022d0000220441014b0d0041002100024020040e020200020b410121000c010b20014100360220200142013703182001410b36022c200120013602282001200141186a360234200141cc006a41013602002001420137023c200141b885c7003602382001200141286a360248200141346a41d8dbc100200141386a103c1a200135022042208620013502188410080240200128021c450d002001280218102f0b410221000b2003450d002002102f0b200141d0006a240020000bea1504047f017e127f027e23004190036b22012400200141e8026a41186a4200370300200141e8026a41106a22024200370300200141e8026a41086a22034200370300200142003703e802419487ca00ad4280808080a001841001220429000021052003200441086a290000370300200120053703e8022004102f418691c700ad4280808080e00084100122042900002105200141c8026a41086a2206200441086a290000370300200120053703c8022004102f200220012903c8022205370300200141106a41086a2003290300370300200141106a41106a2005370300200141106a41186a2006290300370300200120012903e802370310200141203602342001200141106a360230200141386a200141106aad42808080808004841002107302400240200128023822070d00410021080c010b200128023c21092001200141386a41086a28020036025c20012007360258200141086a200141d8006a10e60102400240024002400240024002402001280208450d0041002103200141003602480c010b200128020c220a200128025c220b41c4006e22032003200a4b1b220cad42c4007e2205422088a70d012005a72203417f4c0d010240024020030d00410421080c010b2003102d2208450d03200341c4006e210c0b024002400240200a450d00200141e8026a410772210d4100210e0340200b450d022001200b417f6a220f36025c20012001280258220641016a36025820062d0000220341014b0d0202400240024020030e020001000b200f4104490d04200141a4026a41026a200141a8026a41026a2d00003a000020014188026a41086a200141c8026a41086a29020037030020014188026a41106a200141c8026a41106a29020037030020014188026a41186a200141c8026a41186a2d00003a0000200141e8016a41086a200141e8026a41086a290100370300200141e8016a41106a200141e8026a41106a290100370300200141e8016a41186a200141e8026a41186a290100370300200120012f00a8023b01a402200120012902c80237038802200120012901e8023703e8012001200b417b6a221036025c2001200641056a36025820062800012111200120012f01c4023b01e601410021020c010b41002102200141003a008803200b417e6a2104024002400240024002400340200f20022203460d01200141e8026a20036a200620036a220241016a2d00003a00002001200241026a3602582001200341016a22023a0088032001200436025c2004417f6a210420024120470d000b200141c4026a41026a221220012d00ea023a0000200141a8026a41086a2213200d41086a290000370300200141a8026a41106a2214200d41106a290000370300200141a8026a41186a2215200d41186a2d00003a0000200120012f01e8023b01c4022001200d2900003703a80241002110200f2002460d0220012800eb0221162001200436025c2001200620026a220f41026a360258200f41016a2d0000220241014d0d0120042110410221020c050b0240200341ff0171450d00200141003a0088030b41002110410221020c040b024020020e020200020b41002102200141003a008803200b20036b417c6a21030240034020042002460d01200141e8026a20026a200f20026a220641026a2d00003a00002001200641036a3602582001200241016a22063a0088032001200336025c2003417f6a21032006210220064120470d000b200141c8026a41186a200141e8026a41186a290300370300200141c8026a41106a200141e8026a41106a290300370300200141c8026a41086a200141e8026a41086a290300370300200120012903e8023703c802200420066b2110410121170c030b0240200241ff0171450d00200141003a0088030b410021100b410221020c020b41002117200421100b200141e8016a41186a200141c8026a41186a290300370300200141e8016a41106a200141c8026a41106a290300370300200141e8016a41086a200141c8026a41086a290300370300200141a4026a41026a20122d00003a000020014188026a41086a201329030037030020014188026a41106a201429030037030020014188026a41186a20152d00003a0000200120012903c8023703e801200120012f01c4023b01a402200120012903a8023703880241012102201621110b200141e2016a41026a2203200141a4026a41026a2d00003a0000200141c8016a41086a220620014188026a41086a290300370300200141c8016a41106a220f20014188026a41106a290300370300200141c8016a41186a220b20014188026a41186a2d00003a0000200141a8016a41086a2212200141e8016a41086a290300370300200141a8016a41106a2213200141e8016a41106a290300370300200141a8016a41186a2214200141e8016a41186a290300370300200120012f01a4023b01e20120012001290388023703c801200120012903e8013703a801200120012f01e6013b01a60120024102460d03200e41016a2104200141a2016a41026a221520032d00003a000020014188016a41086a2216200629030037030020014188016a41106a2206200f29030037030020014188016a41186a220f200b2d00003a0000200141e8006a41086a220b2012290300370300200141e8006a41106a22122013290300370300200141e8006a41186a22132014290300370300200120012f01e2013b01a201200120012903c80137038801200120012903a801370368200120012f01a6013b01660240200c200e470d00200e41017422032004200320044b1bad42c4007e2205422088a70d082005a722034100480d0802400240200e0d002003102d21080c010b2008200e41c4006c2003103121080b2008450d07200341c4006e210c0b2008200e41c4006c6a220320023a000020032011360004200341036a20152d00003a0000200320012f01a2013b0001200f2d0000210220062903002105201629030021182001290388012119200320173a002120032019370008200341106a2018370000200341186a2005370000200341206a20023a00002003413a6a2013290300370000200341326a20122903003700002003412a6a200b29030037000020032001290368370022200320012f01663b00422010210b2004210e2004200a470d000b0b200141d0006a200a3602002001200c36024c2001200836024820080d06200821030c020b200141e2016a41026a200141a4026a41026a2d00003a0000200141c8016a41086a20014188026a41086a290300370300200141c8016a41106a20014188026a41106a290300370300200141c8016a41186a20014188026a41186a2d00003a0000200141a8016a41086a200141e8016a41086a290300370300200141a8016a41106a200141e8016a41106a290300370300200141a8016a41186a200141e8016a41186a290300370300200120012f01a4023b01e20120012001290388023703c801200120012903e8013703a801200120012f01e6013b01a6010b4100210320014100360248200c450d002008102f0b200141003602d002200142013703c8022001410b3602ec012001200141306a3602e8012001200141c8026a3602a801200141fc026a4101360200200142013702ec02200141b885c7003602e8022001200141e8016a3602f802200141a8016a41d8dbc100200141e8026a103c1a20013502d00242208620013502c802841008024020012802cc02450d0020012802c802102f0b200321080c040b103d000b1036000b1038000b200129024c21050b2009450d002007102f0b024002402008450d0020002005370204200020083602000c010b20004100360208200042043702000b20014190036a24000bc90802097f037e230041206b220224002002410036020820024201370300024002404120102d2203450d0020032001290010370000200341186a2204200141286a290000370000200341106a2205200141206a290000370000200341086a2206200141186a2900003700004120102d2207450d00200242a080808080043702042002200736020020072003290000370000200741086a2006290000370000200741106a2005290000370000200741186a20042900003700002003102f200120021095024120102d2203450d0020032001290030370000200341186a200141c8006a290000370000200341106a200141c0006a290000370000200341086a200141386a2900003700000240024020022802042205200228020822066b4120490d00200641206a2107200228020021040c010b200641206a22072006490d02200541017422042007200420074b1b22084100480d020240024020050d002008102d21040c010b200228020020052008103121040b2004450d012002200836020420022004360200200821050b200420066a220641086a200341086a290000370000200641106a200341106a290000370000200641186a200341186a29000037000020022007360208200620032900003700002003102f4120102d2203450d0020032001290050370000200341186a200141e8006a290000370000200341106a200141e0006a290000370000200341086a200141d8006a2900003700000240200520076b411f4b0d00200741206a22062007490d02200541017422082006200820064b1b22064100480d020240024020050d002006102d21040c010b200420052006103121040b2004450d0120022006360204200220043602000b200420076a220441086a200341086a290000370000200441106a200341106a290000370000200441186a200341186a2900003700002002200741206a360208200420032900003700002003102f200128020421042001410c6a2802002201200210690240024020010d002002280208210320022802042106200228020021070c010b200141246c210920022802042106200228020821010340200241106a200410ea022002280210210802400240200620016b20022802182205490d00200120056a2103200228020021070c010b200120056a22032001490d04200641017422072003200720034b1b220a4100480d040240024020060d00200a102d21070c010b20022802002006200a103121070b2007450d032002200a36020420022007360200200a21060b20022003360208200720016a2008200510e8061a02402002280214450d002008102f0b200441246a2104200321012009415c6a22090d000b0b2003ad4220862007ad8410032201290000210b200141086a290000210c200141106a290000210d200041186a200141186a290000370000200041106a200d370000200041086a200c3700002000200b3700002001102f02402006450d002007102f0b200241206a24000f0b1036000b1038000ba30405027f017e027f027e027f230041e0006b22022400418de6c300ad4280808080e00084100122032900002104200241286a41086a2205200341086a290000370300200220043703282003102f4193e6c300ad4280808080900184100122032900002104200241086a2206200341086a290000370300200220043703002003102f2002200136025c200241dc006aad4280808080c00084100322032900002104200341086a2900002107200341106a2900002108200241386a41186a2201200341186a290000370300200241386a41106a22092008370300200241386a41086a220a2007370300200220043703382003102f024041c000102d2203450d00200320022903283700002003200229030037001020032002290338370020200341086a2005290300370000200341186a2006290300370000200341286a200a290300370000200341306a2009290300370000200341386a20012903003700002002200341c00010ad02200a200241096a2900003703002009200241116a2900003703002001200241196a290000370300200220022900013703380240024020022d00004101460d0020004200370000200041186a4200370000200041106a4200370000200041086a42003700000c010b20002002290338370000200041186a200241386a41186a290300370000200041106a200241386a41106a290300370000200041086a200241386a41086a2903003700000b2003102f200241e0006a24000f0b1036000b890f05017f017e047f017e067f230041e0016b2201240042002102200141d0006a41186a22034200370300200141d0006a41106a22044200370300200141d0006a41086a2205420037030020014200370350419487ca00ad4280808080a00184100122062900002107200141c0006a41086a2208200641086a290000370300200120073703402006102f200520082903003703002001200129034037035041da85c700ad4280808080e000841001220629000021072008200641086a290000370300200120073703402006102f200420012903402207370300200141206a41086a22062005290300370300200141206a41106a2007370300200141206a41186a200829030037030020012001290350370320200141f0006a200141206a412010ad0220012d00702108200320014189016a290000370300200420014181016a2900003703002005200141f9006a290000370300200120012900713703500240024020084101470d0020002001290350370000200041186a2003290300370000200041106a2004290300370000200041086a20052903003700000c010b200141f0006a41186a4200370300200141f0006a41106a22094200370300200141f0006a41086a2208420037030020014200370370418de6c300ad4280808080e000841001220a29000021072008200a41086a29000037030020012007370370200a102f41bae6c300ad4280808080e000841001220a29000021072006200a41086a29000037030020012007370320200a102f20092001290320220737030020052008290300370300200420073703002003200629030037030020012001290370370350200141f0006a200141d0006a10f402024002402001280270220a0d004104210a410021050c010b20012902742202422088a721050b02400240200541246c2205450d002005415c6a2108200a210503400240024020052d00004101460d002008450d030c010b200541016a2800002103200541086a28020021062001200541106a280200360254200120063602500240200341c28289aa04460d0020080d010c030b200141f0006a200141d0006a10920520012d007022054102460d02200141d4016a28020021092001280274210b200141f0006a41186a4200370300200141f0006a41106a22064200370300200141f0006a41086a2208420037030020014200370370419c9eca00ad4280808080f000841001220329000021072008200341086a290000370300200120073703702003102f41a5c6c800ad4280808080a00184100122032900002107200141206a41086a220c200341086a290000370300200120073703202003102f200620012903202207370300200141d0006a41086a2008290300370300200141d0006a41106a2007370300200141d0006a41186a200c29030037030020012001290370370350200141f0006a200141d0006a412010aa0220012802702208410120081b2106410021030240200b200920054101711b22052001290274420020081b2207422088a74f0d00200620054105746a2205450d00200141186a200541186a290000370300200141106a200541106a290000370300200141086a200541086a29000037030020012005290000370300410121030b02402007a7450d002006102f0b2003450d02200141f0006a41186a2208200141186a290300370300200141f0006a41106a2203200141106a290300370300200141f0006a41086a2206200141086a29030037030020012001290300370370200141d0006a41186a220c4200370300200141d0006a41106a220d4200370300200141d0006a41086a2209420037030020014200370350419487ca00ad4280808080a001841001220b2900002107200141c0006a41086a2205200b41086a29000037030020012007370340200b102f200920052903003703002001200129034037035041da85c700ad4280808080e000841001220b29000021072005200b41086a29000037030020012007370340200b102f20042001290340370000200441086a2005290300370000200141206a41086a2009290300370300200141206a41106a200d290300370300200141206a41186a200c2903003703002001200129035037032002404120102d2205450d0020052001290370370000200541186a2008290300370000200541106a2003290300370000200541086a2006290300370000200141206aad42808080808004842005ad428080808080048410042005102f200041186a2008290300370000200041106a2003290300370000200041086a2006290300370000200020012903703700000c040b1036000b200541246a21052008415c6a21080c000b0b20004200370000200041186a4200370000200041106a4200370000200041086a42003700000b02402002422088a72205450d00200541246c2108200a210503400240024020052d0000220341044b0d0002400240024020030e050400010204040b2005410c6a280200450d03200541086a280200102f0c030b2005410c6a280200450d02200541086a280200102f0c020b2005410c6a280200450d01200541086a280200102f0c010b200541086a280200450d00200541046a280200102f0b200541246a21052008415c6a22080d000b0b2002a7450d00200a102f0b200141e0016a24000b9e0d08047f017e017f017e057f017e0b7f017e230041c0036b22012400200141e0006a41186a22024200370300200141e0006a41106a22034200370300200141e0006a41086a220442003703002001420037036041eba1ca00ad4280808080f0008422051001220629000021072004200641086a290000370300200120073703602006102f41adcac800ad4280808080900184100122062900002107200141106a41086a2208200641086a290000370300200120073703102006102f200320012903102207370300200141306a41086a22062004290300370300200141306a41106a2007370300200141306a41186a200829030037030020012001290360370330200141e0006a200141306a10fd03024002400240024020012903604202510d00200328020021092000280208210a2000280204210b2000280200210c20051001220029000021072008200041086a290000370300200120073703102000102f41e5cac800ad42808080808002841001220029000021072006200041086a290000370300200120073703302000102f200120093602002001ad4280808080c00084100322002900002107200041086a2900002105200041106a290000210d2002200041186a2900003703002003200d37030020042005370300200120073703602000102f41c000102d220e450d01200e2001290310370000200e2001290330370010200e2001290360370020200e41086a200141106a41086a290300370000200e41186a200141306a41086a290300370000200e41286a200141e0006a41086a290300370000200e41306a200141f0006a290300370000200e41386a200141e0006a41186a290300370000200141e0006a200e109f050240024020012802642208450d00200141086a200129036837030020012008360204200128026021040c010b200141086a42003703004190bdc600210820014190bdc600360204410021040b200120043602000240200a450d00200c200a41246c6a210f200141f4006a21102001410c6a211120014104722112200141d8006a2113200141306a41206a2114200c210a0340200a2802202115200141106a41186a2216200a41186a290000370300200141106a41106a2217200a41106a290000370300200141106a41086a2218200a41086a2900003703002001200a2900003703100240024020084190bdc600460d00200128020821020c010b200141e0006a410041e00210e7061a2013410036020020144200370300200141306a41186a22044200370300200141306a41106a22004200370300200141306a41086a2203420037030020014200370330419403102d2208450d0441002102200841003b010620084100360200200841086a200141e0006a41e00210e8061a20084190036a201328020036020020084188036a201429030037020020084180036a2004290300370200200841f8026a2000290300370200200841f0026a2003290300370200200820012903303702e80220014100360208200120083602040b200a41246a210a0240024003400240024020082f010622090d00410021030c010b20094105742104200841086a2100417f21030340024020040d00200921030c020b200341016a2103200141106a2000412010ea062206450d03200441606a2104200041206a21002006417f4a0d000b0b02402002450d002002417f6a2102200820034102746a4194036a28020021080c010b0b200141306a41186a20162903002207370300200141306a41106a20172903002205370300200141306a41086a2018290300220d37030020012001290310221937033020102019370200201041086a200d370200201041106a2005370200201041186a2007370200200120113602702001200336026c200120123602682001200836026420014100360260200141e0006a410010ee0121040c010b200820034102746a41e8026a21040b2004200428020020156a3602002001200128020020156a2204360200200a200f460d01200128020421080c000b0b0240200b450d00200c102f200128020021040b20012802042200450d022001410c6a2802002103200141086a280200210620014100360268200142013703604104102d2208450d012008200436000020014284808080c00037026420012008360260200020062003200141e0006a10e50120012802642104200ead4280808080800884200135026842208620012802602208ad84100402402004450d002008102f0b20002006200310a302200e102f0c030b200041046a280200450d022000280200102f0c020b1036000b200ead42808080808008841005200e102f0b200141c0036a24000bc30704057f017e057f027e23004180016b22012400200141c8006a41186a22024200370300200141c8006a41106a22034200370300200141c8006a41086a2204420037030020014200370348419c9eca00ad4280808080f000841001220529000021062004200541086a290000370300200120063703482005102f41a39eca00ad4280808080c00184100122072900002106200141e8006a41086a2205200741086a290000370300200120063703682007102f200320012903682206370300200141286a41086a22072004290300370300200141286a41106a22082006370300200141286a41186a2209200529030037030020012001290348370328200141106a200141286a41201095012001280214210a2001280210210b2009200041186a2900003703002008200041106a2900003703002007200041086a2900003703002001200029000037032841d39bca00ad4280808080800184100122002900002106200141186a41086a2207200041086a290000370300200120063703182000102f4194c9c300ad4280808080e001841001220029000021062005200041086a290000370300200120063703682000102f2001200a4100200b1b36027c200141fc006aad4280808080c00084100322002900002106200041086a290000210c200041106a290000210d2002200041186a2900003703002003200d3703002004200c370300200120063703482000102f024041c000102d2200450d00200020012903183700002000200129036837001020002001290348370020200041086a2007290300370000200041186a2005290300370000200041286a2004290300370000200041306a2003290300370000200041386a20022903003700004120102d2204450d0020042001290328370000200441186a200141286a41186a290300370000200441106a200141286a41106a290300370000200441086a200141286a41086a2903003700002004ad4280808080800484100322032900002106200341086a290000210c200341106a290000210d200141c8006a41186a2205200341186a290000370300200141c8006a41106a2202200d370300200141c8006a41086a2207200c370300200120063703482003102f2004102f200041c00041800110312200450d0020002001290348370040200041d8006a2005290300370000200041d0006a2002290300370000200041c8006a2007290300370000200141086a200041e0001095012001200128020c41016a410120012802081b3602482000ad4280808080800c84200141c8006aad4280808080c0008410042000102f20014180016a24000f0b1036000bed0403027f017e047f230041e0006b22022400419bd9c900ad4280808080f00084100122032900002104200241086a41086a200341086a290000370300200220043703082003102f41c1d9c900ad4280808080800184100122032900002104200241186a41086a200341086a290000370300200220043703182003102f20022001360234200241346aad4280808080c00084100722032900002104200241386a41086a200341086a290000370300200220043703382003102f200241d4006a200241386a360200200241003a00582002200241c8006a36024c2002200241346a3602502002200241386a360248200241286a200241c8006a106c0240024002400240024002402002280230220541206a2201417f4c0d0020022802282106024002402001450d002001102d2203450d062001410f4d0d01200121070c050b411021074110102d21030c030b200141017422084110200841104b1b220741004e0d010c050b103d000b200320012007103121030b2003450d010b20032002290308370000200341086a200241086a41086a2903003700000240024020074170714110460d00200721080c010b200741017422084120200841204b1b22084100480d0220032007200810312203450d010b20032002290318370010200341186a200241186a41086a29030037000002400240200841606a2005490d00200821070c010b2005415f4b0d02200841017422072001200720014b1b22074100480d0220032008200710312203450d010b200341206a2006200510e8061a2000200136020820002007360204200020033602000240200228022c450d002006102f0b200241e0006a24000f0b1036000b1038000bbb0402097f057e230041f0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100210730240024020032802102204450d00200341186a28020021052003280214210641002101200341003a0068024002400240034020052001460d01200341c8006a20016a200420016a2d00003a00002003200141016a22023a00682002210120024120470d000b200341286a41186a2201200341c8006a41186a2207290300370300200341286a41106a2208200341c8006a41106a2209290300370300200341286a41086a220a200341c8006a41086a220b29030037030020032003290348370328200520026b410f4d0d01200b200a290300220c37030020092008290300220d37030020072001290300220e37030020032003290328220f370348200420026a22012900002110200041306a200141086a290000370300200041286a2010370300200041206a200e370300200041186a200d370300200041106a200c3703002000200f3703084201210c0c020b200141ff0171450d00200341003a00680b20034100360230200342013703282003410b3602242003200341086a3602202003200341286a36026c200341dc006a41013602002003420137024c200341b885c7003602482003200341206a360258200341ec006a41d8dbc100200341c8006a103c1a200335023042208620033502288410080240200328022c450d002003280228102f0b4200210c0b2000200c3703002006450d012004102f0c010b200042003703000b200341f0006a24000bd6d8020b017f027e137f017e017f017e127f057e017f037e147f23004190096b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e16000102030405061d1c1614131211100f0e0d0c0b0a09000b200341c4076a4101360200200342013702b407200341b4d8c9003602b007200341043602dc06200341fcdbc9003602d8062003200341d8066a3602c007200341b0076a41e8d8c9001043000b200141306a2903002104200141286a290300210520012d00012106200341f8066a200141246a280200360200200341d8066a41186a2001411c6a290200370300200341d8066a41106a200141146a290200370300200341d8066a41086a2001410c6a2902003703002003200141046a2902003703d80620022d00000d0620022d00014101470d06200241196a2d00002107200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241086a2d00002114200241066a2f01002115200241056a2d00002116200241046a2d00002117200241026a2f0100211820032002411a6a29010037039806200320073a009706200320083a009606200320093b0194062003200a3a0093062003200b3a0092062003200c3b0190062003200d3a008f062003200e3a008e062003200f3b018c06200320103a008b06200320113a008a06200320123b018806200320133a008706200320143a008606200320153b018406200320163a008306200320173a008206200320183b01800641eba1ca00ad4280808080f00084100122022d000f210820022d000e210920022f000c210a20022d000b210b20022d000a210c20022f0008210d20022d0007210e20022d0006210f20022f0004211020022d0003211120022d0002211220022f000021132002102f41a1cac800ad4280808080e0008410012202290008211920022d0007211420022d0006211520022f0004211620022d0003211720022d0002211820022f0000211a2002102f4120102d2207450d232007200329038006370000200741186a20034180066a41186a290300370000200741106a20034180066a41106a290300370000200741086a20034180066a41086a2903003700002007ad428080808080048410032202290018211b20022d0017211c20022d0016211d20022f0014211e20022d0013211f20022d0012212020022f0010212120022d000f212220022d000e212320022f000c212420022d000b212520022d000a212620022f0008212720022d0007212820022d0006212920022f0004212a20022d0003212b20022d0002212c20022f0000212d2002102f2007102f41c000102d2202450d232002201b3700382002201c3a00372002201d3a00362002201e3b00342002201f3a0033200220203a0032200220213b0030200220223a002f200220233a002e200220243b002c200220253a002b200220263a002a200220273b0028200220283a0027200220293a00262002202a3b00242002202b3a00232002202c3a00222002202d3b002020022019370018200220143a0017200220153a0016200220163b0014200220173a0013200220183a00122002201a3b0010200220083a000f200220093a000e2002200a3b000c2002200b3a000b2002200c3a000a2002200d3b00082002200e3a00072002200f3a0006200220103b0004200220113a0003200220123a0002200220133b0000200341106a200241c00041c8e1ca004100410010b501200328021021082002102f41012107024020084101470d0020004183103b0100200041086a410d360200200041046a41c9c7c800360200200041026a41023a0000410121080c2b0b200341b0076a41206a200341d8066a41206a280200360200200341b0076a41186a200341d8066a41186a290300370300200341b0076a41106a200341d8066a41106a290300370300200341b0076a41086a200341d8066a41086a290300370300200320032903d8063703b007200341e8036a200341b0076a10bb01200341b8086a41086a2202200341f1036a290000370300200341b8086a41106a2207200341f9036a290000370300200341b8086a41186a220820034181046a290000370300200320032900e9033703b80820032d00e8034101460d13200341a8066a41186a2008290300370300200341a8066a41106a2007290300370300200341a8066a41086a2002290300370300200320032903b8083703a80641eba1ca00ad4280808080f0008410012202290000211920034180056a41086a200241086a29000037030020032019370380052002102f41a7cac800ad4280808080e00084100122022900002119200341a8056a41086a200241086a290000370300200320193703a8052002102f4120102d2207450d23200720032903a806370000200741186a200341a8066a41186a290300370000200741106a200341a8066a41106a290300370000200741086a200341a8066a41086a2903003700002007ad428080808080048410032202290018211920022d0017210820022d0016210920022f0014210a20022d0013210b20022d0012210c20022f0010210d20022d000f210e20022d000e210f20022f000c211020022d000b211120022d000a211220022f0008211320022d0007211420022d0006211520022f0004211620022d0003211720022d0002211820022f0000211a2002102f2007102f41c000102d2202450d232002200329038005370000200220032903a80537001020022019370038200220083a0037200220093a00362002200a3b00342002200b3a00332002200c3a00322002200d3b00302002200e3a002f2002200f3a002e200220103b002c200220113a002b200220123a002a200220133b0028200220143a0027200220153a0026200220163b0024200220173a0023200220183a00222002201a3b0020200241086a20034180056a41086a290300370000200241186a200341a8056a41086a290300370000200341086a200241c00041c8e1ca004100410010b501200328020821082002102f41012107024020084101470d00410d210241bcc7c8002106410321080c2a0b02402005428080e983b1de165441002004501b450d00411121024180c7c8002106410721080c2a0b41eba1ca00ad4280808080f00084100122022900002119200341d8036a41086a200241086a290000370300200320193703d8032002102f41a1cac800ad4280808080e0008410012202290000211920034180056a41086a200241086a29000037030020032019370380052002102f4120102d2202450d232002200329038006370000200241186a20034180066a41186a290300370000200241106a20034180066a41106a290300370000200241086a20034180066a41086a2903003700002002ad4280808080800484100322072900002119200741086a290000211b200741106a290000212e200341a8056a41186a2208200741186a290000370300200341a8056a41106a2209202e370300200341a8056a41086a201b370300200320193703a8052007102f2002102f41c000102d2202450d23200220032903d803370000200241086a200341d8036a41086a2903003700002002200329038005370010200241186a20034180056a41086a290300370000200220032903a805370020200241286a200341a8056a41086a290300370000200241306a2009290300370000200241386a20082903003700004120102d2207450d23200720032903a806370000200741186a200341a8066a41186a290300370000200741106a200341a8066a41106a290300370000200741086a200341a8066a41086a2903003700002002ad42808080808008842007ad428080808080048410042007102f2002102f41eba1ca00ad4280808080f00084100122022d000f210820022d000e210920022f000c210a20022d000b210b20022d000a210c20022f0008210d20022d0007210e20022d0006210f20022f0004211020022d0003211120022d0002211220022f000021132002102f41c8abc900ad4280808080d0008410012202290008211920022d0007211420022d0006211520022f0004211620022d0003211720022d0002211820022f0000211a2002102f4120102d2207450d232007200329038006370000200741186a20034180066a41186a290300370000200741106a20034180066a41106a290300370000200741086a20034180066a41086a2903003700002007ad428080808080048410032202290018211b20022d0017211c20022d0016211d20022f0014211e20022d0013211f20022d0012212020022f0010212120022d000f212220022d000e212320022f000c212420022d000b212520022d000a212620022f0008212720022d0007212820022d0006212920022f0004212a20022d0003212b20022d0002212c20022f0000212d2002102f2007102f41c000102d2202450d232002201b3700382002201c3a00372002201d3a00362002201e3b00342002201f3a0033200220203a0032200220213b0030200220223a002f200220233a002e200220243b002c200220253a002b200220263a002a200220273b0028200220283a0027200220293a00262002202a3b00242002202b3a00232002202c3a00222002202d3b002020022019370018200220143a0017200220153a0016200220163b0014200220173a0013200220183a00122002201a3b0010200220083a000f200220093a000e2002200a3b000c2002200b3a000b2002200c3a000a2002200d3b00082002200e3a00072002200f3a0006200220103b0004200220113a0003200220123a0002200220133b000002400240200641037122074103470d004101210742002119410121060c010b024002400240024020070e03000102000b410021060c020b410121060c010b410221060b200320063a00d8034101102d2207450d24200720063a00004100210642808080801021190b2002ad428080808080088420192007ad841004024020060d002007102f0b2002102f20034180066a10d002200341b0076a20034180066a108d02200341b0076a41086a290300211920032903b007211b200341e8036a41186a220720034180066a41186a290300370300200341e8036a41106a220620034180066a41106a290300370300200341e8036a41086a220820034180066a41086a29030037030020032003290380063703e80341eba1ca00ad4280808080f0008410012202290000212e2002290008212f2002102f41d2a0ca00ad4280808080a00184100122022900002130200229000821312002102f200320313703d008200320303703c8082003202f3703c0082003202e3703b8082003200341b8086a4120109501200341b0076a41186a20192004201b200554201920045420192004511b22021b2204370300200341d8076a4100360200200341ec076a2008290300370200200341f4076a2006290300370200200341fc076a20072903003702002003201b200520021b22053703c007200320043703b807200320053703b007200342083703d007200320032903e8033702e407200320032903003702dc07200341a8066a200341b0076a10b6030240200341d4076a280200450d0020032802d007102f0b200041043a00000c280b4101210720022d00014101470d0420022d000041ff01710d04200141106a2903002104200141086a290300210520032002411a6a2901003703c0052003200241026a2901003703a80520032002410a6a2901003703b0052003200241126a2901003703b805200341b0076a200341a8056a10b50341012107024020032d00b0074101470d00200341d8066a41176a2208200341c9076a290000370000200341d8066a41106a2209200341b0076a41126a290100370300200341e8036a41086a2202200341b0076a410a6a290100370300200341e8036a41106a22062009290300370300200341e8036a41176a22092008290000370000200320032901b2073703e803200320032d00b1073a00a806200341a8066a41186a2009290000370000200341b9066a2006290300370000200341b1066a2002290300370000200320032903e8033700a906200341b0076a200341a8066a108103024020032802dc074102460d00200341b8086a41086a2209200341dc076a220841086a290100370300200341b8086a41106a220a200841106a290100370300200341b8086a41186a220b200841186a290100370300200341b8086a41206a220c200841206a290100370300200341b8086a41286a220d200841286a280100360200200320082901003703b808200341b0076a41086a220e290300211b200341b0076a41186a290300213120032903b007211920032903c007213020032802d007210f20032802d807211020032802d4072108200220092903003703002006200a290300370300200341e8036a41186a2209200b290300370300200341e8036a41206a220a200c290300370300200341e8036a41286a220b200d280200360200200341fc066a2008360200200341d8066a41286a2010360200200341d8066a41186a2031370300200320032903b8083703e8032003200f3602f806200320303703e806200320193703d8062003201b3703e006200341ac076a200b280200360200200341a4076a200a2903003702002003419c076a200929030037020020034194076a20062903003702002003418c076a2002290300370200200320032903e80337028407200341b0076a200341a8056a108d02024020032903b007222e20197d2232202e56200e290300222f201b7d202e201954ad7d222e202f56202e202f511b0d0020032030200520322032200556202e200456202e2004511b22021b22057c222f3703e806200341f0066a20312004202e20021b22047c202f203054ad7c3703002003200520197c22193703d80620032004201b7c2019200554ad7c3703e006200341a8066a200341d8066a10b60320032802fc0621080b02402008450d0020032802f806102f0b200041043a0000410121080c2b0b200041086a410d360200200041046a41dec7c800360200200041026a41003a000020004183103b0100410121080c2a0b200041086a4108360200200041046a41d6c7c800360200200041026a41013a000020004183103b0100410121080c290b200141106a2903002105200141086a29030021192002411a6a2901002104200241196a2d00002106200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241086a2d00002114200241066a2f01002115200241056a2d00002116200241046a2d00002117200241026a2f0100211841012107024020022d00000d0020022d000141014721070b200320043703d008200320063a00cf08200320083a00ce08200320093b01cc082003200a3a00cb082003200b3a00ca082003200c3b01c8082003200d3a00c7082003200e3a00c6082003200f3b01c408200320103a00c308200320113a00c208200320123b01c008200320133a00bf08200320143a00be08200320153b01bc08200320163a00bb08200320173a00ba08200320183b01b80802400240024002400240024020070d00200341a8066a41186a200341b8086a41186a2207290300370300200341a8066a41106a200341b8086a41106a2206290300370300200341a8066a41086a200341b8086a41086a2208290300370300200320032903b8083703a806200341b0076a200341a8066a108103024020032802dc074102460d002008200341dc076a220241086a2901003703002006200241106a2901003703002007200241186a290100370300200341b8086a41206a220b200241206a290100370300200341b8086a41286a220c200241286a280100360200200320022901003703b808200341b0076a41086a290300212e200341b0076a41186a290300210420032903b007212f20032903c007211b20032802d007210a20032802d807210920032802d4072102200341e8036a41086a220d2008290300370300200341e8036a41106a22082006290300370300200341e8036a41186a22062007290300370300200341e8036a41206a2207200b290300370300200341e8036a41286a220b200c280200360200200341fc066a2002360200200341d8066a41286a2009360200200341d8066a41186a2004370300200320032903b8083703e8032003200a3602f8062003201b3703e8062003202f3703d8062003202e3703e006200341ac076a200b280200360200200341a4076a20072903003702002003419c076a200629030037020020034194076a20082903003702002003418c076a200d290300370200200320032903e803370284072009411f4b0d02201b2019201b201954200420055420042005511b22071b22192004200520071b220584500d06200341d8066a41186a4200200420057d201b201954ad7d222e201b20197d222f428080e983b1de16544100202e501b22071b37030020034200202f20071b3703e80641eba1ca00ad4280808080f0008410012206290000212e2006290008212f2006102f41d2a0ca00ad4280808080a00184100122062900002130200629000821312006102f200320313703c005200320303703b8052003202f3703b0052003202e3703a805200341186a200341a8056a4120109501200328021c21062003280218210820092002470d0520032802fc062002460d0320032802f806210a0c040b200041086a410d360200200041046a41dec7c800360200200041026a41003a000020004183103b01000c2c0b200041023a00000c2b0b20004183103b0100200041086a410c360200200041046a41f4c6c800360200200041026a41083a00002002450d2a200a102f0c2a0b200241016a22092002490d252002410174220a2009200a20094b1bad42187e222e422088a70d25202ea722094100480d250240024020020d002009102d210a0c010b20032802f806200241186c20091031210a0b200a450d242003200a3602f8062003200941186e3602fc060b20032802800721090b200a200941186c6a22022004200520071b3703082002201b201920071b3703002002200641a0056a41a00520081b360210200320032802800741016a36028007200341a8066a200341d8066a10b60320032802fc0621020b02402002450d0020032802f806102f0b200041043a00000c260b024002400240024020022d00000d0020022d00014101470d00200241196a2d00002107200241186a2d00002106200241166a2f01002108200241156a2d00002109200241146a2d0000210a200241126a2f0100210b200241116a2d0000210c200241106a2d0000210d2002410e6a2f0100210e2002410d6a2d0000210f2002410c6a2d000021102002410a6a2f01002111200241096a2d00002112200241086a2d00002113200241066a2f01002114200241056a2d00002115200241046a2d00002116200241026a2f0100211720032002411a6a2901003703c006200320073a00bf06200320063a00be06200320083b01bc06200320093a00bb062003200a3a00ba062003200b3b01b8062003200c3a00b7062003200d3a00b6062003200e3b01b4062003200f3a00b306200320103a00b206200320113b01b006200320123a00af06200320133a00ae06200320143b01ac06200320153a00ab06200320163a00aa06200320173b01a806200341b0076a200341a8066a108103024020032802dc074102460d00200341b8086a41086a2207200341dc076a220241086a290100370300200341b8086a41106a2206200241106a290100370300200341b8086a41186a2209200241186a290100370300200341b8086a41206a2208200241206a290100370300200341b8086a41286a220c200241286a280100360200200320022901003703b808200341b0076a41086a2903002104200341b0076a41186a290300212e20032903b007210520032903c007212f20032802d007210b20032802d807210a20032802d407210d200341e8036a41086a22022007290300370300200341e8036a41106a220e2006290300370300200341e8036a41186a220f2009290300370300200341e8036a41206a22102008290300370300200341e8036a41286a2208200c280200360200200341fc066a200d360200200341d8066a41286a200a360200200341d8066a41186a202e370300200320032903b8083703e8032003200b3602f8062003202f3703e806200320053703d806200320043703e006200341ac076a2008280200360200200341a4076a221120102903003702002003419c076a2210200f29030037020020034194076a220f200e2903003702002003418c076a220c2002290300370200200320032903e8033702840741eba1ca00ad4280808080f000841001220229000021192002290008211b2002102f41d2a0ca00ad4280808080a00184100122022900002130200229000821312002102f200320313703c005200320303703b8052003201b3703b005200320193703a805200341206a200341a8056a412010950120032802204101470d04200328022421082007200f29020037030020062010290200370300200920112902003703002003200329028c073703b80820034188076a280200210f20032802840721100240200a450d00200b200a41186c6a2109200a41186c41686a2107200b21020340200241086a290300211b200229030021192008200241106a2802002206490d0442002004201b7d2005201954ad7d221b200520197d2219200556201b200456201b2004511b22061b21044200201920061b2105200741686a2107200241186a22022009470d000b0b4108210e4100210a0240200d450d00200b102f0b410021060c030b200041086a410d360200200041046a41dec7c800360200200041026a41003a000020004183103b01000c290b200041023a00000c280b4118102d220e450d22200e2019370300200e2006360210200e201b3703080240024020070d004101210a410121060c010b200241186a2111200a41186c200b6a41686a21134101210a4101210603402011210202400340200241086a290300211b200229030021192008200241106a2802002207490d0142002004201b7d2005201954ad7d221b200520197d2219200556201b200456201b2004511b22071b21044200201920071b2105200241186a22022009470d000c030b0b02402006200a470d00200a41016a2206200a490d26200a41017422112006201120064b1bad42187e2230422088a70d262030a722064100480d2602400240200a0d002006102d210e0c010b200e200a41186c20061031210e0b200e450d25200641186e21060b200241186a2111200e200a41186c6a2212201b3703082012201937030020122007360210200a41016a210a20132002470d000b0b200d450d00200b102f0b200c20032903b808370200200341d8066a41186a202e370300200c41086a200341b8086a41086a290300370200200c41106a200341b8086a41106a290300370200200c41186a200341b8086a41186a2903003702002003202f3703e806200320053703d8062003200f3602880720032010360284072003200a36028007200320063602fc062003200e3602f806200320043703e0060b02400240200a0d00202f202e84500d010b200341a8066a200341d8066a10b6030c250b200341c8076a200341a4076a290200370300200341c0076a2003419c076a290200370300200341b0076a41086a20034194076a2902003703002003200329028c073703b007200341e8036a200341b0076a108306200320032900e9033703b8082003200341e8036a41086a2800003600bf08024020032d00e80322024104470d00200342f3e885db96cddbb3203703800620034180066a200341b0076a10b1010c250b200020023a0000200020032903b808370001200041086a20032800bf0836000020032802fc06450d2520032802f806102f0c250b200141046a280200211a2002411a6a2901002104200241196a2d00002106200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241086a2d00002114200241066a2f01002115200241056a2d00002116200241046a2d00002117200241026a2f0100211841012107024020022d00000d0020022d000141014721070b200320043703c005200320063a00bf05200320083a00be05200320093b01bc052003200a3a00bb052003200b3a00ba052003200c3b01b8052003200d3a00b7052003200e3a00b6052003200f3b01b405200320103a00b305200320113a00b205200320123b01b005200320133a00af05200320143a00ae05200320153b01ac05200320163a00ab05200320173a00aa05200320183b01a80502400240024020070d00200341d8056a41186a200341a8056a41186a290300370300200341d8056a41106a200341a8056a41106a290300370300200341d8056a41086a200341a8056a41086a290300370300200320032903a8053703d805200341b0076a200341d8056a108103024020032802dc074102460d00200341b8086a41086a200341dc076a220241086a2901002204370300200341b8086a41106a200241106a2901002205370300200341b8086a41186a200241186a2901002219370300200341b8086a41206a200241206a290100221b370300200341e8036a41106a22072005370300200341e8036a41186a22062019370300200341e8036a41206a2208201b370300200341e8036a41286a2209200241286a280100360200200341e8036a41086a220a20043703002003200229010022043703b808200341b0076a41086a2903002105200341b0076a41186a290300211920032903b007211b20032903c007212e20032903d007212f200341d8066a41286a20032802d807360200200341d8066a41186a201937030020034194076a20072903003702002003419c076a2006290300370200200341a4076a2008290300370200200341ac076a2009280200360200200320043703e8032003202f3703f8062003202e3703e806200320053703e0062003201b3703d806200320032903e803370284072003200a29030037028c072003418c076a220610e90541eba1ca00ad4280808080f00084100122022d000f210820022d000e210920022f000c210a20022d000b210b20022d000a210c20022f0008210d20022d0007210e20022d0006210f20022f0004211020022d0003211120022d0002211220022f000021132002102f41a5c6c800ad4280808080a0018410012202290008210420022d0007211420022d0006211520022f0004211620022d0003211720022d0002211820022f0000211c2002102f4120102d2207450d2320072006290000370000200741186a200641186a290000370000200741106a200641106a290000370000200741086a200641086a2900003700002007ad428080808080048410032202290018210520022d0017211d20022d0016211e20022f0014211f20022d0013212020022d0012212120022f0010212220022d000f212320022d000e212420022f000c212520022d000b212620022d000a212720022f0008212820022d0007212920022d0006212a20022f0004212b20022d0003212c20022d0002212d20022f000021332002102f2007102f41c000102d2202450d23200220053700382002201d3a00372002201e3a00362002201f3b0034200220203a0033200220213a0032200220223b0030200220233a002f200220243a002e200220253b002c200220263a002b200220273a002a200220283b0028200220293a00272002202a3a00262002202b3b00242002202c3a00232002202d3a0022200220333b002020022004370018200220143a0017200220153a0016200220163b0014200220173a0013200220183a00122002201c3b0010200220083a000f200220093a000e2002200a3b000c2002200b3a000b2002200c3a000a2002200d3b00082002200e3a00072002200f3a0006200220103b0004200220113a0003200220123a0002200220133b0000200341e8036a200241c000109b0420032d00ec0322074102470d032003200636028c0941eba1ca00ad4280808080f00084100122072900002104200341e0046a41086a2208200741086a290000370300200320043703e0042007102f4195c6c800ad428080808080028410012207290000210420034180066a41086a2209200741086a29000037030020032004370380062007102f200341b8086a41086a2008290300370300200341d0086a2009290300370300200320032903e0043703b80820032003290380063703c808200341b0076a200341b8086a108801200341a8066a20032802b007220720032802b80710ad02024020032802b407450d002007102f0b200341c8086a210720032d00a8060d0241eba1ca00ad4280808080f00084100122082900002104200341e0046a41086a2209200841086a290000370300200320043703e0042008102f4195c6c800ad428080808080028410012208290000210420034180066a41086a220a200841086a29000037030020032004370380062008102f200341b8086a41086a20092903003703002007200329038006370000200741086a200a290300370000200320032903e0043703b808200341b0076a200341b8086a10880120032802b007210820033502b80721044120102d2207450d2320072006290000370000200741186a200641186a290000370000200741106a200641106a290000370000200741086a200641086a29000037000020044220862008ad842007ad428080808080048410042007102f20032802b407450d252008102f0c250b200041086a410d360200200041046a41dec7c800360200200041026a41003a000020004183103b01000c270b200041023a00000c260b200341c0056a200341c1066a290000370300200341b8056a200341b9066a290000370300200341a8056a41086a200341b1066a290000370300200320032900a9063703a805200341c0046a200341a8056a109a04200341b0076a20032802c004220620032802c8042208109b04024020032d00b4074102470d002003410036028805200342013703800520034180066a41146a41293602002003418c066a410b360200200341073602dc03200341eba1ca003602d8032003410b360284062003410a3602e404200341a5c6c8003602e0042003200341c0046a360290062003200341e0046a360288062003200341d8036a36028006200320034180056a36028009200341b8086a41146a4103360200200342033702bc08200341cc90c4003602b808200320034180066a3602c80820034180096a41d8dbc100200341b8086a103c1a2003350288054220862003350280058410080240200328028405450d00200328028005102f0b200328028c09210641eba1ca00ad4280808080f00084100122082900002104200341e0046a41086a2209200841086a290000370300200320043703e0042008102f4195c6c800ad428080808080028410012208290000210420034180066a41086a220a200841086a29000037030020032004370380062008102f200341b8086a41086a20092903003703002007200329038006370000200741086a200a290300370000200320032903e0043703b80820034180066a200341b8086a108801200328028006210820033502880621044120102d2207450d2120072006290000370000200741186a200641186a290000370000200741106a200641106a290000370000200741086a200641086a29000037000020044220862008ad842007ad428080808080048410042007102f0240200328028406450d002008102f0b20032802c404450d2320032802c004102f0c230b20032802b0072109200341b8086a200341b0076a41047241c20010e8061a20034180056a41086a200341da086a410020032d00d9084101461b360200200320093602800520032003418c096a360284052003410036028806200342013703800620034180056a20034180066a10950220034180056a41047220034180066a10cd0220032802840621092008ad4220862006ad842003350288064220862003280280062206ad84100402402009450d002006102f0b024020032802c404450d0020032802c004102f0b200328028c09210641eba1ca00ad4280808080f00084100122082900002104200341e0046a41086a2209200841086a290000370300200320043703e0042008102f4195c6c800ad428080808080028410012208290000210420034180066a41086a220a200841086a29000037030020032004370380062008102f200341b8086a41086a20092903003703002007200329038006370000200741086a200a290300370000200320032903e0043703b808200341b0076a200341b8086a10880120032802b007210820033502b80721044120102d2207450d2020072006290000370000200741186a200641186a290000370000200741106a200641106a290000370000200741086a200641086a29000037000020044220862008ad842007ad428080808080048410042007102f024020032802b407450d002008102f0b20034180066a41086a200341a8056a41086a29030037030020034180066a41106a200341a8056a41106a29030037030020034180066a41186a200341a8056a41186a290300370300200320032903a8053703800641012106410021070c230b200341b8086a41186a20034185046a290000370300200341b8086a41106a200341fd036a290000370300200341b8086a41086a200341f5036a29000037030020034180066a41086a20034196046a29010037030020034180066a41106a2003419e046a29010037030020034180066a41186a200341a6046a290100370300200320032900ed033703b80820032003418e046a290100370380062003418d046a2d000021060c220b2001410c6a280200211d200141086a2802002109200141046a28020021062002411a6a2901002104200241196a2d00002108200241186a2d0000210a200241166a2f0100210b200241156a2d0000210c200241146a2d0000210d200241126a2f0100210e200241116a2d0000210f200241106a2d000021102002410e6a2f010021112002410d6a2d000021122002410c6a2d000021132002410a6a2f01002114200241096a2d00002115200241086a2d00002116200241066a2f01002117200241056a2d00002118200241046a2d0000211a200241026a2f0100211c41012107024020022d00000d0020022d000141014721070b200320043703d008200320083a00cf082003200a3a00ce082003200b3b01cc082003200c3a00cb082003200d3a00ca082003200e3b01c8082003200f3a00c708200320103a00c608200320113b01c408200320123a00c308200320133a00c208200320143b01c008200320153a00bf08200320163a00be08200320173b01bc08200320183a00bb082003201a3a00ba082003201c3b01b808024020070d0020034180056a41186a200341b8086a41186a220729030037030020034180056a41106a200341b8086a41106a220829030037030020034180056a41086a200341b8086a41086a220a290300370300200320032903b80837038005200341b0076a20034180056a10810320032802dc074102460d18200a200341dc076a220241086a2901003703002008200241106a2901003703002007200241186a290100370300200341b8086a41206a220c200241206a290100370300200341b8086a41286a220d200241286a280100360200200320022901003703b808200341b0076a41086a2903002104200341b0076a41186a290300210520032903b007211920032903c007211b20032802d007210b20032802d807210e20032802d4072102200341d8066a41086a220f200a290300370300200341d8066a41106a220a2008290300370300200341d8066a41186a22082007290300370300200341d8066a41206a2207200c290300370300200341d8066a41286a220c200d280200360200200341e8036a41246a2002360200200341e8036a41286a200e360200200341e8036a41186a2005370300200320032903b8083703d8062003200b360288042003201b3703f803200320193703e803200320043703f003200341bc046a200c280200360200200341b4046a2007290300370200200341ac046a2008290300370200200341a4046a200a2903003702002003200f29030037029c04200320032903d80637029404201d450d19201d41246c2208450d1b200341d8066a41086a2202200641096a290000370300200341d8066a41106a2207200641116a290000370300200341d8066a41186a220a200641196a290000370300200341f7066a220b200641206a280000360000200320062900013703d80620062d0000220c4102460d1b200341b0076a41096a2002290300370000200341b0076a41116a2007290300370000200341b0076a41196a200a290300370000200341b0076a41206a200b2800003600002003200c3a00b007200320032903d8063700b107200341b8086a200341b0076a10bb01200341a8066a41086a200341b8086a41096a290000370300200341a8066a41106a200341b8086a41116a290000370300200341a8066a41186a200341b8086a41196a290000370300200320032900b9083703a80641012107024020032d00b8084101470d0020034180066a41086a200341a8056a41086a29030037030020034180066a41106a200341a8056a41106a29030037030020034180066a41186a200341a8056a41186a290300370300200320032903a805370380060c1d0b200341d8056a41086a2207200341a8066a41086a290300370300200341d8056a41106a220a200341a8066a41106a290300370300200341d8056a41186a220b200341a8066a41186a290300370300200320032903a806220437038006200320043703d8054120102d2202450d1f200220032903d805370000200241186a200b290300370000200241106a200a290300370000200241086a2007290300370000024002400240200620086a200641246a460d00200341d8066a41086a22072006412d6a290000370300200341d8066a41106a2208200641356a290000370300200341d8066a41186a220a2006413d6a290000370300200341f7066a220b200641c4006a280000360000200320062900253703d80620062d0024220c4102460d00200341b0076a41096a2007290300370000200341b0076a41116a2008290300370000200341b0076a41196a200a290300370000200341b0076a41206a200b2800003600002003200c3a00b007200320032903d8063700b107200341b8086a200341b0076a10bb01200341a8066a41086a200341b8086a41096a290000370300200341a8066a41106a200341b8086a41116a290000370300200341a8066a41186a200341b8086a41196a290000370300200320032900b9083703a80620032d00b8084101470d0220034180066a41086a200341a8056a41086a29030037030020034180066a41106a200341a8056a41106a29030037030020034180066a41186a200341a8056a41186a290300370300200320032903a80537038006410121070c010b410021070b410121084101210a0c1e0b200641c8006a210b20034180066a41086a221e200341a8066a41086a22182903002204370300200341d8056a41186a2211200341a8066a41186a221a290300370300200341d8056a41106a2212200341a8066a41106a221c290300370300200341d8056a41086a22132004370300200320032903a806220437038006200320043703d805201d41246c41b87f6a2110200341b8086a410172210d200341b0076a410172210c200341d8066a411f6a21174102210f4120210e410221084101210a0340200341b0076a41186a22142011290300370300200341b0076a41106a22152012290300370300200341b0076a41086a22162013290300370300200320032903d8053703b00702402008417f6a200a470d00200f2008200f20084b1b220741ffffff3f712007470d22200741057422074100480d222002200e200710312202450d212007410576210a0b2002200e6a220720032903b007370000200741186a2014290300370000200741106a2015290300370000200741086a20162903003700004100210720084110460d1e2010450d1e200341d8066a41086a2214200b41096a290000370300200341d8066a41106a2215200b41116a290000370300200341d8066a41186a2216200b41196a2900003703002017200b41206a2800003600002003200b2900013703d806200b2d0000221d4102460d1e200c20032903d806370000200c41086a2014290300370000200c41106a2015290300370000200c41186a2016290300370000200c411f6a20172800003600002003201d3a00b007200341b8086a200341b0076a10bb012018200d41086a290000370300201c200d41106a290000370300201a200d41186a2900003703002003200d2900003703a806024020032d00b8084101470d0020034180066a41086a200341a8056a41086a29030037030020034180066a41106a200341a8056a41106a29030037030020034180066a41186a200341a8056a41186a290300370300200320032903a80537038006410121070c1f0b200b41246a210b201e201829030022043703002011201a2903003703002012201c29030037030020132004370300200320032903a806220437038006200320043703d805200f41026a210f200e41206a210e200841016a21082010415c6a21100c000b0b200041023a00000c190b200041023a0000410121080c240b200041023a00000c210b200341d8066a41186a200141196a290000370300200341e8066a200141116a290000370300200341d8066a41086a200141096a290000370300200320012900013703d806200341b0076a200341d8066a108d020240427f20032903b007220420032903c0077c220520052004542202200341b0076a41086a22072903002204200341b0076a41186a2903007c2002ad7c220520045420052004511b22021b427f200520021b844200520d00200341b0076a200341d8066a108306200320032900b1073703b808200320072800003600bf08024020032d00b00722024104470d00200342f3e885db96cddbb3203703e803200341e8036a200341d8066a10b101200041043a00000c220b200020023a0000200020032903b808370001200041086a20032800bf083600000c210b20004183103b0100200041086a410c360200200041046a41dbc6c800360200200041026a410a3a00000c200b024020022d000120022d0000410047720d00200141046a280200210841eba1ca00ad4280808080f00084222e100122022900002104200229000821052002102f41d2a0ca00ad4280808080a001841001220229000021192002290008211b2002102f2003201b3701c005200320193701b805200320053701b005200320043701a805200341d0036a200341a8056a412010950141012107024020032802d0034101470d0020032802d4032106202e100122022900002104200229000821052002102f41a3a0ca00ad4280808080c00184221910012202290000211b2002290008212e2002102f2003202e3701c0052003201b3701b805200320053701b005200320043701a805200341c8036a200341a8056a412010950102404100200620032802cc0341d40020032802c8031b6b2202200220064b1b22024100200620086b2209200920064b1b22064f0d000340200210ee052006200241016a2202470d000b0b41eba1ca00ad4280808080f00084100122022900002104200229000821052002102f20191001220229000021192002290008211b2002102f2003201b3701c005200320193701b805200320053701b005200320043701a805200320083602b007200341a8056aad4280808080800484200341b0076aad4280808080c0008410040b200041043a0000410121080c220b200041023a00000c1f0b41012107024020022d00014101470d0020022d000041ff01710d00200141106a290300211b200141086a290300212e20032002411a6a2901003703c0062003200241026a2901003703a80620032002410a6a2901003703b0062003200241126a2901003703b806200341b0076a200341a8066a108103024020032802dc074102460d00200341b8086a41086a2207200341dc076a220241086a290100370300200341b8086a41106a2206200241106a290100370300200341b8086a41186a2208200241186a290100370300200341b8086a41206a220a200241206a290100370300200341b8086a41286a220b200241286a280100360200200320022901003703b808200341b0076a41186a290300212f200341b0076a41086a290300213420032903c007213020032903b007213520032802d807210220032802d407210c20032802d0072109200341e8036a41086a220d2007290300370300200341e8036a41106a22072006290300370300200341e8036a41186a22062008290300370300200341e8036a41206a2208200a290300370300200341e8036a41286a220a200b280200360200200320032903b8083703e80302402002450d00200341d8066a41286a200a280200360200200341d8066a41206a2008290300370300200341d8066a41186a2006290300370300200341d8066a41106a2007290300370300200341d8066a41086a200d290300370300200320032903e8033703d80642002131420021320240034002402002417f6a220720024d0d00410021070c020b024020072002490d00200221070c020b02402009200741186c6a22060d00200221070c020b02402006290300220420317c2205202e58200641086a290300223620327c2005200454ad7c2219201b582019201b5122081b0d0020062004202e20317d22057d37030020062036201b20327d202e203154ad7d22197d2004200554ad7d3703082019202f7c200520307c2230200554ad7c212f200221070c020b2036202f7c200420307c2230200454ad7c212f2007210220052131201921322005202e542019201b5420081b0d000b0b200341b0076a41186a202f370300200341b0076a41286a2007360200200341d4076a2202200c360200200341e4076a200341e0066a290300370200200341ec076a200341e8066a290300370200200341f4076a200341d8066a41186a290300370200200341fc076a200341f8066a29030037020020034184086a200341d8066a41286a280200360200200320303703c007200320353703b007200320093602d007200320032903d8063702dc07200320343703b807200341a8066a200341b0076a10b60302402002280200450d0020032802d007102f0b200041043a00000c210b20004183103b0100200041086a410d360200200041046a41e7c6c800360200200041026a41093a0000200c450d202009102f0c200b200041086a410d360200200041046a41dec7c800360200200041026a41003a000020004183103b01000c1f0b200041023a0000410121080c200b02400240024002400240024020022d00000d0020022d00014101470d002002411a6a2901002104200241196a2d0000210a200241186a2d0000210b200241166a2f0100210c200241156a2d0000210d200241146a2d0000210e200241126a2f0100210f200241116a2d00002110200241106a2d000021112002410e6a2f010021122002410d6a2d000021132002410c6a2d000021142002410a6a2f01002115200241096a2d00002116200241086a2d00002117200241066a2f01002118200241056a2d0000211a200241046a2d0000211c200241026a2f0100211d200341b0036a200141046a28020022061084060240024020032802b003450d00200341c0036a290300212f20032903b803212e41eba1ca00ad4280808080f00084100122022900002105200341d8036a41086a200241086a290000370300200320053703d8032002102f41a7cac800ad4280808080e0008410012202290000210520034180056a41086a200241086a29000037030020032005370380052002102f4120102d2202450d20200220043700182002200a3a00172002200b3a00162002200c3b00142002200d3a00132002200e3a00122002200f3b0010200220103a000f200220113a000e200220123b000c200220133a000b200220143a000a200220153b0008200220163a0007200220173a0006200220183b00042002201a3a00032002201c3a00022002201d3b00002002ad4280808080800484100322072900002105200741086a2900002119200741106a290000211b200341a8056a41186a2208200741186a290000370300200341a8056a41106a2209201b370300200341a8056a41086a2019370300200320053703a8052007102f2002102f41c000102d2202450d20200220032903d803370000200241086a200341d8036a41086a2903003700002002200329038005370010200241186a20034180056a41086a2207290300370000200220032903a805370020200241286a200341a8056a41086a221e290300370000200241306a2009290300370000200241386a2008290300370000200341b0076a200210a005201e200341b0076a41086a2903003703002009200341b0076a41106a2903003703002008200341b0076a41186a290300370300200341a8056a41206a2209200341b0076a41206a290300370300200341a8056a41286a221f200341b0076a41286a2802003602002007200341b0076a41386a29030037030020034180056a41106a200341b0076a41c0006a29030037030020034180056a41186a200341b0076a41c8006a29030037030020034180056a41206a2220200341b0076a41d0006a290300370300200320032903b0073703a805200320032903e00737038005024020032802dc0722084102460d00200341a8066a41286a2221201f280200360200200341a8066a41206a221f2009290300370300200341a8066a41186a2209200341a8056a41186a290300370300200341a8066a41106a2222200341a8056a41106a290300370300200341a8066a41086a2223201e29030037030020034180066a41086a221e200729030037030020034180066a41106a220720034180056a41106a29030037030020034180066a41186a222420034180056a41186a29030037030020034180066a41206a22252020290300370300200320032903a8053703a8062003200329038005370380062002102f200341e8036a410e6a2023290300370100200341e8036a41166a2022290300370100200341e8036a411e6a2009290300370100200341e8036a41266a201f290300370100200341e8036a412e6a2021280200360100200320032903a8063701ee03200341b8086a41086a200341e8036a41086a290100370300200341b8086a41106a200341e8036a41106a290100370300200341b8086a41186a200341e8036a41186a290100370300200341b8086a41206a200341e8036a41206a290100370300200341b8086a41286a200341e8036a41286a290100370300200341b8086a41306a200341e8036a41306a2f01003b0100200320032901e8033703b808200341d8056a41206a22022025290300370300200341d8056a41186a22092024290300370300200341d8056a41106a221f2007290300370300200341d8056a41086a2207201e29030037030020032003290380063703d805200341d8066a41286a200341b8086a412e6a280100360200200341d8066a41206a200341b8086a41266a290100370300200341d8066a41186a200341b8086a411e6a290100370300200341d8066a41106a200341b8086a41166a290100370300200341d8066a41086a200341b8086a410e6a290100370300200320032901be083703d8062003200836028407200341d8066a41d0006a2002290300370300200341d8066a41c8006a200929030037030020034198076a201f290300370300200341d8066a41386a2007290300370300200341d8066a41306a220220032903d805370300200620022802004d410220081b22024102460d022002410171450d0220004183103b0100200041086a4112360200200041046a41c9c6c800360200200041026a410b3a0000200341fc066a280200450d2620032802f806102f0c260b2002102f200041086a410d360200200041046a41dec7c800360200200041026a41003a000020004183103b01000c250b20004183103b0100200041086a4112360200200041046a41c9c6c800360200200041026a410b3a00000c240b2003200636028807200341013602840741eba1ca00ad4280808080f00084100122022d000f210820022d000e210920022f000c211e20022d000b211f20022d000a212020022f0008212120022d0007212220022d0006212320022f0004212420022d0003212520022d0002212620022f000021272002102f41a7cac800ad4280808080e0008410012202290008210520022d0007212820022d0006212920022f0004212a20022d0003212b20022d0002212c20022f0000212d2002102f4120102d2202450d1e200220043700182002200a3a00172002200b3a00162002200c3b00142002200d3a00132002200e3a00122002200f3b0010200220103a000f200220113a000e200220123b000c200220133a000b200220143a000a200220153b0008200220163a0007200220173a0006200220183b00042002201a3a00032002201c3a00022002201d3b00002002ad428080808080048410032207290018211920072d0017213320072d0016213720072f0014213820072d0013213920072d0012213a20072f0010213b20072d000f213c20072d000e213d20072f000c213e20072d000b213f20072d000a214020072f0008214120072d0007214220072d0006214320072f0004214420072d0003214520072d0002214620072f000021472007102f2002102f41c000102d2202450d1e20022019370038200220333a0037200220373a0036200220383b0034200220393a00332002203a3a00322002203b3b00302002203c3a002f2002203d3a002e2002203e3b002c2002203f3a002b200220403a002a200220413b0028200220423a0027200220433a0026200220443b0024200220453a0023200220463a0022200220473b002020022005370018200220283a0017200220293a00162002202a3b00142002202b3a00132002202c3a00122002202d3b0010200220083a000f200220093a000e2002201e3b000c2002201f3a000b200220203a000a200220213b0008200220223a0007200220233a0006200220243b0004200220253a0003200220263a0002200220273b0000200341c0003602b407200320023602b007200341d8066a200341b0076a10f3052002102f200341a8066a2006108506200341b0076a20062003418c076a220910f205200341a8036a20032802b007220820032802b80710c10320032802a803210220032802ac032107024020032802b407450d002008102f0b200341e8036a2006200910f005200341b0076a20032802e803220620032802f00310bc030240024020032802d00722230d004200211b41082123410021244200210542002130420021190c010b200341b8076a2903002105200341c8076a290300211920032903b007211b20032903c007213020032802d40721240b024020032802ec03450d002006102f0b20034198036a201b4201201b42015620054200522005501b22061b221b2005420020061b2205428094ebdc03420010ee0620034188036a201b200520032903980322314201203142015620034198036a41086a29030022314200522031501b22061b22322031420020061b223610ee06200329038803223142808080801054410020034188036a41086a290300501b450d01200341f8026a201b2030201b203054200520195420052019511b22061b2005201920061b2032203610ee0620032903f8022205428080808010544100200341f8026a41086a290300501b450d022031a7450d032007410020021b2122200542ffffffff0f83428094ebdc037e203142ffffffff0f83802105200341a8066a4104722102200341a8066a41086a280200211f024002400340410021214100210602402002280200221e2f01062220450d0020204105742102201e41086a2107417f21060340024020020d00202021060c020b200641016a210620092007412010ea062208450d03200241606a2102200741206a21072008417f4a0d000b0b201f450d02201f417f6a211f201e20064102746a4194036a21020c000b0b201e20064102746a41e8026a28020021210b200341d0026a202e202f428094ebdc03420010ee06200341c0026a20032903d0022219200341d0026a41086a290300221b4280ec94a37c427f10ed0620032802a80621022003418094ebdc033602b4072003200542ffffffff0f834100418094ebdc0320226b22072007418094ebdc034b1bad7e428094ebdc0380a722073602b007200341b0076a2007418094ebdc034b4102746a28020021072003418094ebdc033602b4072003417f202220076a220720072022491b22073602b007200341b0076a2007418094ebdc034b4102746a35020021052003418094ebdc033602b4072003200520024101200241014b1b2202202120022021491b2002418094ebdc036e22074101200741014b1b22076ead428094ebdc037e200220076ead8042ffffffff0f837e428094ebdc0380a722023602b007200341b0026a2019201b200341b0076a2002418094ebdc034b4102746a3502002205420010ed06200341e0026a200920032903b00222192005202e20032903c0027c7e22052005428094ebdc038022054280ec94a37c7e7c4280cab5ee01562005a76aad7c2205200341b0026a41086a2903002005201954ad7c108606200341e0026a41106a290300210520032903e8022119024020032903e002221ba74101470d00200320043702d0082003200a3a00cf082003200b3a00ce082003200c3b01cc082003200d3a00cb082003200e3a00ca082003200f3b01c808200320103a00c708200320113a00c608200320123b01c408200320133a00c308200320143a00c208200320153b01c008200320163a00bf08200320173a00be08200320183b01bc082003201a3a00bb082003201c3a00ba082003201d3b01b808200341e8076a2005370300200341e0076a2019370300200341d1076a2004370000200341b0076a41206a200a3a0000200341cf076a200b3a0000200341cd076a200c3b0000200341cc076a200d3a0000200341cb076a200e3a0000200341c9076a200f3b0000200341b0076a41186a220820103a0000200341c7076a20113a0000200341c5076a20123b0000200341c4076a20133a0000200341c3076a20143a0000200341c1076a20153b0000200341b0076a41106a220620163a0000200341bf076a20173a0000200341bd076a20183b0000200341bc076a201a3a0000200341bb076a201c3a0000200341b9076a201d3b0000200341b0076a41086a220741003a0000200341043a00b00741c8e1ca004100200341b0076a108c01200842003703002006420037030020074200370300200342003703b00741e7a2ca00ad4280808080800184220410012209290000211b200341b8086a41086a2202200941086a2900003703002003201b3703b8082009102f20072002290300370300200320032903b8083703b00741ecb5c600ad4280808080d00184221b10012209290000212e2002200941086a2900003703002003202e3703b8082009102f200620032903b808222e370300200341e8036a41086a220a2007290300370300200341e8036a41106a220b202e370300200341e8036a41186a220c2002290300370300200320032903b0073703e80320034180026a200341e8036a4120109c0120034180026a41106a290300212e200329038802212f2003280280022109200842003703002006420037030020074200370300200342003703b00720041001220829000021042002200841086a290000370300200320043703b8082008102f20072002290300370300200320032903b8083703b007201b1001220829000021042002200841086a290000370300200320043703b8082008102f200620032903b8082204370300200a2007290300370300200b2004370300200c2002290300370300200320032903b0073703e8032003427f202e420020091b220420057c202f420020091b220520197c22192005542202ad7c22052002200520045420052004511b22021b3703b8072003427f201920021b3703b007200341b0076a2102200341e8036a21070c050b201b4201520d05200341b0076a41186a22094200370300200341b0076a41106a22064200370300200341b0076a41086a22074200370300200342003703b00741e7a2ca00ad4280808080800184220410012208290000211b200341b8086a41086a2202200841086a2900003703002003201b3703b8082008102f20072002290300370300200320032903b8083703b00741ecb5c600ad4280808080d00184221b10012208290000212e2002200841086a2900003703002003202e3703b8082008102f200620032903b808222e370300200341e8036a41086a220a2007290300370300200341e8036a41106a220b202e370300200341e8036a41186a220c2002290300370300200320032903b0073703e80320034198026a200341e8036a4120109c0120034198026a41106a290300212e20032903a002212f2003280298022108200942003703002006420037030020074200370300200342003703b00720041001220929000021042002200941086a290000370300200320043703b8082009102f20072002290300370300200320032903b8083703b007201b1001220929000021042002200941086a290000370300200320043703b8082009102f200620032903b8082204370300200a2007290300370300200b2004370300200c2002290300370300200320032903b0073703e8032003427f202e420020081b220420057c202f420020081b220520197c22192005542202ad7c22052002200520045420052004511b22021b3703b8072003427f201920021b3703b007200341b0076a2102200341e8036a21070c040b200041023a00000c220b200341113602b40720034198b4c0003602b0074186b3c00041e000200341b0076a419cb2c00041e8b3c000103e000b200341113602b40720034198b4c0003602b0074186b3c00041e000200341b0076a419cb2c00041f8b3c000103e000b4180b2c00041194188b4c0001039000b2007ad42808080808004842002ad428080808080028410040b200041043a000002402024450d002023102f0b20032802ac0620032802b006200341b4066a28020010a302200341fc066a280200450d1d20032802f806102f0c1d0b2001410c6a2802002106200141086a2802002108024002400240024002400240024020022d00000d0020022d00014101470d0002400240200141106a280200220941104b0d002002411a6a2901002119200241196a2d00002113200241186a2d00002114200241166a2f01002115200241156a2d00002116200241146a2d00002117200241126a2f01002118200241116a2d0000211a200241106a2d0000211c2002410e6a2f0100211d2002410d6a2d0000211e2002410c6a2d0000211f2002410a6a2f01002120200241096a2d00002121200241086a2d00002122200241066a2f01002123200241056a2d00002124200241046a2d00002125200241026a2f01002126200341e8016a200141046a280200220d10840620032802e8010d0120004183103b0100200041086a4112360200200041046a41c9c6c800360200200041026a410b3a00000c070b20004183103b0100200041086a411a360200200041046a41afc6c800360200200041026a410c3a00000c060b200341e8016a41106a290300212f20032903f001212e41eba1ca00ad4280808080f00084100122022900002104200341d8036a41086a200241086a290000370300200320043703d8032002102f41a7cac800ad4280808080e0008410012202290000210420034180056a41086a200241086a29000037030020032004370380052002102f4120102d2202450d1e20022019370018200220133a0017200220143a0016200220153b0014200220163a0013200220173a0012200220183b00102002201a3a000f2002201c3a000e2002201d3b000c2002201e3a000b2002201f3a000a200220203b0008200220213a0007200220223a0006200220233b0004200220243a0003200220253a0002200220263b00002002ad4280808080800484100322072900002104200741086a2900002105200741106a290000211b200341a8056a41186a220a200741186a290000370300200341a8056a41106a220b201b370300200341a8056a41086a2005370300200320043703a8052007102f2002102f41c000102d2202450d1e200220032903d803370000200241086a200341d8036a41086a2903003700002002200329038005370010200241186a20034180056a41086a2207290300370000200220032903a805370020200241286a200341a8056a41086a220c290300370000200241306a200b290300370000200241386a200a290300370000200341b0076a200210a005200c200341b0076a41086a290300370300200b200341b0076a41106a290300370300200a200341b0076a41186a290300370300200341a8056a41206a220b200341b0076a41206a290300370300200341a8056a41286a220e200341b0076a41286a2802003602002007200341b0076a41386a29030037030020034180056a41106a200341b0076a41c0006a29030037030020034180056a41186a200341b0076a41c8006a29030037030020034180056a41206a220f200341b0076a41d0006a290300370300200320032903b0073703a805200320032903e007370380050240024020032802dc07220a4102460d00200341a8066a41286a2210200e280200360200200341a8066a41206a220e200b290300370300200341a8066a41186a220b200341a8056a41186a290300370300200341a8066a41106a2211200341a8056a41106a290300370300200341a8066a41086a2212200c29030037030020034180066a41086a220c200729030037030020034180066a41106a220720034180056a41106a29030037030020034180066a41186a222720034180056a41186a29030037030020034180066a41206a2228200f290300370300200320032903a8053703a8062003200329038005370380062002102f200341e8036a410e6a2012290300370100200341e8036a41166a2011290300370100200341e8036a411e6a200b290300370100200341e8036a41266a200e290300370100200341e8036a412e6a2010280200360100200320032903a8063701ee03200341b8086a41086a200341e8036a41086a290100370300200341b8086a41106a200341e8036a41106a290100370300200341b8086a41186a200341e8036a41186a290100370300200341b8086a41206a200341e8036a41206a290100370300200341b8086a41286a200341e8036a41286a290100370300200341b8086a41306a200341e8036a41306a2f01003b0100200320032901e8033703b808200341d8056a41206a22022028290300370300200341d8056a41186a220b2027290300370300200341d8056a41106a220e2007290300370300200341d8056a41086a2207200c29030037030020032003290380063703d805200341d8066a41286a200341b8086a412e6a280100360200200341d8066a41206a200341b8086a41266a290100370300200341d8066a41186a200341b8086a411e6a290100370300200341d8066a41106a200341b8086a41166a290100370300200341d8066a41086a200341b8086a410e6a290100370300200320032901be083703d8062003200a36028407200341d8066a41d0006a2002290300370300200341d8066a41c8006a200b29030037030020034198076a200e290300370300200341d8066a41386a2007290300370300200341d8066a41306a220220032903d805370300200d20022802004d4102200a1b22024102460d012002410171450d0120004183103b0100200041086a4112360200200041046a41c9c6c800360200200041026a410b3a0000200341fc066a280200450d0720032802f806102f0c070b2002102f200041086a410d360200200041046a41dec7c800360200200041026a41003a000020004183103b01000c060b2003200d36028807200341013602840741eba1ca00ad4280808080f00084100122022d000f210a20022d000e210b20022f000c210c20022d000b210e20022d000a210f20022f0008211020022d0007211120022d0006211220022f0004212720022d0003212820022d0002212920022f0000212a2002102f41a7cac800ad4280808080e0008410012202290008210420022d0007212b20022d0006212c20022f0004212d20022d0003213320022d0002213720022f000021382002102f4120102d2202450d1e20022019370018200220133a0017200220143a0016200220153b0014200220163a0013200220173a0012200220183b00102002201a3a000f2002201c3a000e2002201d3b000c2002201e3a000b2002201f3a000a200220203b0008200220213a0007200220223a0006200220233b0004200220243a0003200220253a0002200220263b00002002ad428080808080048410032207290018210520072d0017213920072d0016213a20072f0014213b20072d0013213c20072d0012213d20072f0010213e20072d000f213f20072d000e214020072f000c214120072d000b214220072d000a214320072f0008214420072d0007214520072d0006214620072f0004214720072d0003214820072d0002214920072f0000214a2007102f2002102f41c000102d2202450d1e20022005370038200220393a00372002203a3a00362002203b3b00342002203c3a00332002203d3a00322002203e3b00302002203f3a002f200220403a002e200220413b002c200220423a002b200220433a002a200220443b0028200220453a0027200220463a0026200220473b0024200220483a0023200220493a00222002204a3b0020200220043700182002202b3a00172002202c3a00162002202d3b0014200220333a0013200220373a0012200220383b00102002200a3a000f2002200b3a000e2002200c3b000c2002200e3a000b2002200f3a000a200220103b0008200220113a0007200220123a0006200220273b0004200220283a0003200220293a00022002202a3b0000200341c0003602b407200320023602b007200341d8066a200341b0076a10f3052002102f200341a8066a200d1085060240200941246c22020d00410021290c050b200820026a2211415c6a212a200341a8066a410472212c2003418c076a210f20082107410021290340200721020340200241206a2802002107200341e8036a41186a200241186a290000370300200341e8036a41106a200241106a290000370300200341e8036a41086a200241086a290000370300200320022900003703e803200341b0076a200d200341e8036a10f205200341e0016a20032802b007220920032802b80710c10320032802e001210b20032802e4012110024020032802b407450d002009102f0b200341b8086a200d200341e8036a10f105200341b0076a20032802b808220a20032802c00810bc030240024020032802d007220c0d00420021054100210e4108210c41002109420021040c010b200341b0076a41086a290300210420032903b007210520032802d407210e20032802d80721090b024020032802bc08450d00200a102f0b02400240200920074d0d00200c200741306c6a2207450d000240200f200741106a2209460d002009200f412010ea060d020b200341d0016a20054201200542015620044200522004501b22091b22052004420020091b2204428094ebdc03420010ee06200341c0016a2005200420032903d001221b4201201b420156200341d0016a41086a290300221b420052201b501b22091b2231201b420020091b223210ee0620032903c001221b428080808010544100200341c0016a41086a290300501b450d05200341b0016a20052007290300223020052030542004200741086a29030022305420042030511b22071b2004203020071b2031203210ee0620032903b0012204428080808010544100200341b0016a41086a290300501b450d06201ba7450d0720104100200b1b212b200442ffffffff0f83428094ebdc037e201b42ffffffff0f8380210420032802b0062112202c2107024002400340410021284100210a0240200728020022102f01062227450d0020274105742107201041086a2109417f210a0340024020070d002027210a0c020b200a41016a210a200341e8036a2009412010ea06220b450d03200741606a2107200941206a2109200b417f4a0d000b0b2012450d022012417f6a21122010200a4102746a4194036a21070c000b0b2010200a4102746a41e8026a28020021280b20032802a80621072003418094ebdc033602b407200320074101200741014b1b2207202820072028491b2007418094ebdc036e22094101200941014b1b22096ead428094ebdc037e200720096ead8042ffffffff0f834100418094ebdc03202b6b22072007418094ebdc034b1bad7e428094ebdc0380a722073602b007200341b0076a2007418094ebdc034b4102746a35020021052003418094ebdc033602b40720032005200442ffffffff0f837e428094ebdc0380a722073602b007200341b0076a2007418094ebdc034b4102746a28020021072003418094ebdc033602b4072003417f202920076a220720072029491b22073602b007200341b0076a2007418094ebdc034b4102746a28020021290b0240200e450d00200c102f0b200241246a2107202a2002460d070c020b200241246a21020240200e450d00200c102f0b20112002460d060c000b0b0b200041023a00000c040b200341113602b40720034198b4c0003602b0074186b3c00041e000200341b0076a419cb2c00041e8b3c000103e000b200341113602b40720034198b4c0003602b0074186b3c00041e000200341b0076a419cb2c00041f8b3c000103e000b4180b2c00041194188b4c0001039000b02402006450d002008102f0b20034188016a202e202f428094ebdc03420010ee06200341f8006a200329038801220420034188016a41086a29030022054280ec94a37c427f10ed06200341e8006a200420052029ad221b420010ed0620034198016a2003418c076a20032903682204201b202e20032903787c7e22052005428094ebdc038022054280ec94a37c7e7c4280cab5ee01562005a76aad7c2205200341e8006a41086a2903002005200454ad7c10860620034198016a41106a290300210420032903a0012105024002400240200329039801221ba74101470d00200320193702d008200320133a00cf08200320143a00ce08200320153b01cc08200320163a00cb08200320173a00ca08200320183b01c8082003201a3a00c7082003201c3a00c6082003201d3b01c4082003201e3a00c3082003201f3a00c208200320203b01c008200320213a00bf08200320223a00be08200320233b01bc08200320243a00bb08200320253a00ba08200320263b01b808200341e8076a2004370300200341e0076a2005370300200341d1076a2019370000200341b0076a41206a20133a0000200341cf076a20143a0000200341cd076a20153b0000200341cc076a20163a0000200341cb076a20173a0000200341c9076a20183b0000200341b0076a41186a2208201a3a0000200341c7076a201c3a0000200341c5076a201d3b0000200341c4076a201e3a0000200341c3076a201f3a0000200341c1076a20203b0000200341b0076a41106a220620213a0000200341bf076a20223a0000200341bd076a20233b0000200341bc076a20243a0000200341bb076a20253a0000200341b9076a20263b0000200341b0076a41086a220741003a0000200341043a00b00741c8e1ca004100200341b0076a108c01200842003703002006420037030020074200370300200342003703b00741e7a2ca00ad4280808080800184221910012209290000211b200341b8086a41086a2202200941086a2900003703002003201b3703b8082009102f20072002290300370300200320032903b8083703b00741ecb5c600ad4280808080d00184221b10012209290000212e2002200941086a2900003703002003202e3703b8082009102f200620032903b808222e370300200341e8036a41086a220a2007290300370300200341e8036a41106a220b202e370300200341e8036a41186a220c2002290300370300200320032903b0073703e803200341386a200341e8036a4120109c01200341386a41106a290300212e2003290340212f20032802382109200842003703002006420037030020074200370300200342003703b00720191001220829000021192002200841086a290000370300200320193703b8082008102f20072002290300370300200320032903b8083703b007201b1001220829000021192002200841086a290000370300200320193703b8082008102f200620032903b8082219370300200a2007290300370300200b2019370300200c2002290300370300200320032903b0073703e8032003427f202e420020091b221920047c202f420020091b220420057c22052004542202ad7c22042002200420195420042019511b22021b3703b8072003427f200520021b3703b007200341b0076a2102200341e8036a21070c010b201b4201520d01200341b0076a41186a22094200370300200341b0076a41106a22064200370300200341b0076a41086a22074200370300200342003703b00741e7a2ca00ad4280808080800184221910012208290000211b200341b8086a41086a2202200841086a2900003703002003201b3703b8082008102f20072002290300370300200320032903b8083703b00741ecb5c600ad4280808080d00184221b10012208290000212e2002200841086a2900003703002003202e3703b8082008102f200620032903b808222e370300200341e8036a41086a220a2007290300370300200341e8036a41106a220b202e370300200341e8036a41186a220c2002290300370300200320032903b0073703e803200341d0006a200341e8036a4120109c01200341d0006a41106a290300212e2003290358212f20032802502108200942003703002006420037030020074200370300200342003703b00720191001220929000021192002200941086a290000370300200320193703b8082009102f20072002290300370300200320032903b8083703b007201b1001220929000021192002200941086a290000370300200320193703b8082009102f200620032903b8082219370300200a2007290300370300200b2019370300200c2002290300370300200320032903b0073703e8032003427f202e420020081b221920047c202f420020081b220420057c22052004542202ad7c22042002200420195420042019511b22021b3703b8072003427f200520021b3703b007200341b0076a2102200341e8036a21070b2007ad42808080808004842002ad428080808080028410040b200041043a000020032802ac06200341b0066a280200200341b4066a28020010a3020240200341fc066a280200450d0020032802f806102f0b41002100410121070c010b41002100410121072006450d002008102f0b41012108410121060c1f0b200241036a2d0000210820022f00012109200141106a28020021072001410c6a2802002113200141086a2802002110200141046a2802002114024002400240024020022d0000220a417f6a220641024b0d00024020060e03000102000b200241046a2d00000d00200241086a2802004102742002410c6a28020041036c4f0d010b410021062009200841107472200a4100477241ff01710d010b20102007410041202007676b10e40341eba1ca00ad4280808080f00084100122022d000f210620022d000e210820022f000c210920022d000b210a20022d000a210b20022f0008210c20022d0007210d20022d0006210e20022f0004210f20022d0003211120022d0002211220022f000021152002102f41e0cfc800ad428080808080028410012202290008210420022d0007211620022d0006211720022f0004211820022d0003211a20022d0002211c20022f0000211d2002102f200320143602b007200341b0076aad22194280808080c0008410032202290018210520022d0017211e20022d0016211f20022f0014212020022d0013212120022d0012212220022f0010212320022d000f212420022d000e212520022f000c212620022d000b212720022d000a212820022f0008212920022d0007212a20022d0006212b20022f0004212c20022d0003212d20022d0002213320022f000021372002102f41c000102d2202450d18200220053700382002201e3a00372002201f3a0036200220203b0034200220213a0033200220223a0032200220233b0030200220243a002f200220253a002e200220263b002c200220273a002b200220283a002a200220293b00282002202a3a00272002202b3a00262002202c3b00242002202d3a0023200220333a0022200220373b002020022004370018200220163a0017200220173a0016200220183b00142002201a3a00132002201c3a00122002201d3b0010200220063a000f200220083a000e200220093b000c2002200a3a000b2002200b3a000a2002200c3b00082002200d3a00072002200e3a00062002200f3b0004200220113a0003200220123a0002200220153b0000200341b0076a2002109a0520032902b407210420032802b00721062002102f2004420020061b21042006410820061b2111024020074102742212450d0041002107417f210a41002108410021060340024002400240201020076a280200220920064f0d00410e210241a2c7c8002107410521060c010b200820096a22022004422088a7220b490d01411121024191c7c8002107410621060b20004183103b0100200041086a2002360200200041046a2007360200200041026a20063a000002402013450d002010102f0b02402004422088a72200450d00201141306a2102200041d8006c210003400240200241746a280200450d00200241706a280200102f0b02402002280200450d002002417c6a280200102f0b200241d8006a2102200041a87f6a22000d000b0b41002106410121072004a7450d042011102f0c040b2011200241d8006c6a220228022c210e2002280220210f200241306a280200210c200241246a280200210d2002200241d8006a200a200b6a20096b41d8006c10e9061a0240200d450d00200f102f0b0240200c450d00200e102f0b200641016a210620044280808080707c2104200a41016a210a2008417f6a21082012200741046a2207470d000b0b02402013450d002010102f0b41eba1ca00ad4280808080f00084100122022d000f210720022d000e210620022f000c210820022d000b210920022d000a210a20022f0008210b20022d0007210c20022d0006210d20022f0004210e20022d0003210f20022d0002211020022f000021122002102f41e0cfc800ad428080808080028410012202290008210520022d0007211320022d0006211520022f0004211620022d0003211720022d0002211820022f0000211a2002102f200320143602b00720194280808080c0008410032202290018211920022d0017211420022d0016211c20022f0014211d20022d0013211e20022d0012211f20022f0010212020022d000f212120022d000e212220022f000c212320022d000b212420022d000a212520022f0008212620022d0007212720022d0006212820022f0004212920022d0003212a20022d0002212b20022f0000212c2002102f41c000102d2202450d1820022019370038200220143a00372002201c3a00362002201d3b00342002201e3a00332002201f3a0032200220203b0030200220213a002f200220223a002e200220233b002c200220243a002b200220253a002a200220263b0028200220273a0027200220283a0026200220293b00242002202a3a00232002202b3a00222002202c3b002020022005370018200220133a0017200220153a0016200220163b0014200220173a0013200220183a00122002201a3b0010200220073a000f200220063a000e200220083b000c200220093a000b2002200a3a000a2002200b3b00082002200c3a00072002200d3a00062002200e3b00042002200f3a0003200220103a0002200220123b0000200341b0076a20112004422088a7220710f9052002ad428080808080088420033502b80742208620032802b0072206ad841004024020032802b407450d002006102f0b2002102f02402007450d00200741d8006c2107201141306a210203400240200241746a280200450d00200241706a280200102f0b02402002280200450d002002417c6a280200102f0b200241d8006a2102200741a87f6a22070d000b0b02402004a7450d002011102f0b200041043a000041002106410121070c010b200041023a0000410121072013450d002010102f0b41012108410121000c1e0b024020022d000120022d0000410047720d0041eba1ca00ad4280808080f00084100122022900002104200229000821052002102f41f1a0ca00ad42808080808001841001220229000021192002290008211b2002102f2003201b3703c005200320193703b805200320053703b005200320043703a805200341033a00d803410121074101102d2202450d16200220032d00d8033a0000200341a8056aad42808080808004842002ad4280808080108410042002102f200041043a0000410121080c1d0b200041023a00000c1a0b200341c8076a200141196a290000370300200341c0076a200141116a290000370300200341b0076a41086a200141096a290000370300200320012900013703b007024020022d000120022d0000410047720d00200341d8066a200341b0076a108306200320032900d9063703b8082003200341d8066a41086a2800003600bf08024020032d00d80622024104470d00200342f3e885db96cddbb3203703e803200341e8036a200341b0076a10b101200041043a00000c1b0b200020023a0000200020032903b808370001200041086a20032800bf083600000c1a0b200041023a00000c190b41002108200141086a2802002106200141046a2802002109024020022d000120022d0000410047720d002001410c6a280200210741eba1ca00ad4280808080f00084100122022900002104200229000821052002102f41c4aac900ad4280808080d001841001220229000021192002290008211b2002102f2003201b3703c005200320193703b805200320053703b005200320043703a805200341203602b4072003200341a8056a3602b00720092007200341b0076a10aa0102402006450d002009102f0b200041043a0000410121070c1b0b200041023a0000410121072006450d1a2009102f0c1a0b024020022d000120022d0000410047720d0041eba1ca00ad4280808080f00084100122022900002104200229000821052002102f41f1a0ca00ad42808080808001841001220229000021192002290008211b2002102f2003201b3703c005200320193703b805200320053703b005200320043703a80541012107200341013a00d8034101102d2202450d13200220032d00d8033a0000200341a8056aad42808080808004842002ad4280808080108410042002102f200041043a0000410121080c1a0b200041023a00000c170b024020022d000120022d0000410047720d0041eba1ca00ad4280808080f00084100122022900002104200229000821052002102f41f1a0ca00ad42808080808001841001220229000021192002290008211b2002102f2003201b3703c005200320193703b805200320053703b005200320043703a805200341023a00d803410121074101102d2202450d12200220032d00d8033a0000200341a8056aad42808080808004842002ad4280808080108410042002102f200041043a0000410121080c190b200041023a00000c160b024020022d000120022d0000410047720d00200141046a280200210741eba1ca00ad4280808080f00084100122022900002104200229000821052002102f41afa0ca00ad4280808080e001841001220229000021192002290008211b2002102f2003201b3703c005200320193703b805200320053703b005200320043703a805200320073602b007200341a8056aad4280808080800484200341b0076aad4280808080c000841004200041043a00000c160b200041023a00000c150b410121070c010b200341a0066a200141246a28020036020020034180066a41186a2001411c6a29020037030020034180066a41106a200141146a29020037030020034180066a41086a2001410c6a2902003703002003200141046a2902003703800620022d00000d0220022d00014101470d02200241196a2d00002107200241186a2d00002106200241166a2f01002108200241156a2d00002109200241146a2d0000210a200241126a2f0100210b200241116a2d0000210c200241106a2d0000210d2002410e6a2f0100210e2002410d6a2d0000210f2002410c6a2d000021102002410a6a2f01002111200241096a2d00002112200241086a2d00002113200241066a2f01002114200241056a2d00002115200241046a2d00002116200241026a2f0100211720032002411a6a2901003703d804200320073a00d704200320063a00d604200320083b01d404200320093a00d3042003200a3a00d2042003200b3b01d0042003200c3a00cf042003200d3a00ce042003200e3b01cc042003200f3a00cb04200320103a00ca04200320113b01c804200320123a00c704200320133a00c604200320143b01c404200320153a00c304200320163a00c204200320173b01c004200341b0076a200341c0046a10b50320032d00b0074101470d03200341d8066a41176a2202200341b0076a41196a290000370000200341d8066a41106a2206200341c2076a290100370300200341e8036a41086a2207200341ba076a290100370300200341e8036a41106a22082006290300370300200341e8036a41176a22092002290000370000200320032901b2073703e803200320032d00b1073a00e004200341e0046a41186a2009290000370000200341e0046a41116a2008290300370000200341e0046a41096a2007290300370000200320032903e8033700e104200341b0076a41206a20034180066a41206a280200360200200341b0076a41186a20034180066a41186a290300370300200341b0076a41106a20034180066a41106a290300370300200341b0076a41086a20034180066a41086a29030037030020032003290380063703b007200341d8066a200341b0076a10bb014101210720032d00d8064101460d00200341d8066a41086a2d00002107200341d8066a41096a2f00002108200341e3066a2d00002109200341e4066a2d0000210a200341e5066a2f0000210b200341e7066a2d0000210c20062d00002106200341d8066a41116a2f0000210d200341eb066a2d0000210e200341ec066a2d0000210f200341ed066a2f0000211020022d00002102200341d8066a41186a2d0000211120032f00d906211220032d00db06211320032d00dc06211420032f00dd06211520032d00df0621162003200341d8066a41196a2900003703f005200320113a00ef05200320023a00ee05200320103b01ec052003200f3a00eb052003200e3a00ea052003200d3b01e805200320063a00e7052003200c3a00e6052003200b3b01e4052003200a3a00e305200320093a00e205200320083b01e005200320073a00df05200320163a00de05200320153b01dc05200320143a00db05200320133a00da05200320123b01d80541eba1ca00ad4280808080f00084100122022900002104200341d8036a41086a200241086a290000370300200320043703d8032002102f41a7cac800ad4280808080e0008410012202290000210420034180056a41086a200241086a29000037030020032004370380052002102f4120102d2202450d0e200220032903d805370000200241186a200341d8056a41186a290300370000200241106a200341d8056a41106a290300370000200241086a200341d8056a41086a2903003700002002ad4280808080800484100322072900002104200741086a2900002105200741106a2900002119200341a8056a41186a2206200741186a290000370300200341a8056a41106a22082019370300200341a8056a41086a22092005370300200320043703a8052007102f2002102f41c000102d2202450d0e200220032903d803370000200241086a200341d8036a41086a2903003700002002200329038005370010200241186a20034180056a41086a290300370000200220032903a805370020200241286a2009290300370000200241306a2008290300370000200241386a2006290300370000200341306a200241c00041c8e1ca004100410010b501200328023021062002102f4101210720064101470d0120004183103b0100200041086a410d360200200041046a41bcc7c800360200200041026a41033a0000410121080c150b200020073a0000410121080c140b200341d8056a200341e0046a412010ea06450d0241eba1ca00ad4280808080f00084100122022d000f210620022d000e210820022f000c210920022d000b210a20022d000a210b20022f0008210c20022d0007210d20022d0006210e20022f0004210f20022d0003211020022d0002211120022f000021122002102f41a1cac800ad4280808080e0008410012202290008210420022d0007211320022d0006211420022f0004211520022d0003211620022d0002211720022f000021182002102f4120102d2207450d0c200720032903c004370000200741186a200341c0046a41186a290300370000200741106a200341c0046a41106a290300370000200741086a200341c0046a41086a2903003700002007ad428080808080048410032202290018210520022d0017211a20022d0016211c20022f0014211d20022d0013211e20022d0012211f20022f0010212020022d000f212120022d000e212220022f000c212320022d000b212420022d000a212520022f0008212620022d0007212720022d0006212820022f0004212920022d0003212a20022d0002212b20022f0000212c2002102f2007102f41c000102d2202450d0c200220053700382002201a3a00372002201c3a00362002201d3b00342002201e3a00332002201f3a0032200220203b0030200220213a002f200220223a002e200220233b002c200220243a002b200220253a002a200220263b0028200220273a0027200220283a0026200220293b00242002202a3a00232002202b3a00222002202c3b002020022004370018200220133a0017200220143a0016200220153b0014200220163a0013200220173a0012200220183b0010200220063a000f200220083a000e200220093b000c2002200a3a000b2002200b3a000a2002200c3b00082002200d3a00072002200e3a00062002200f3b0004200220103a0003200220113a0002200220123b00004120102d2207450d0c200720032903d805370000200741186a200341d8056a41186a290300370000200741106a200341d8056a41106a290300370000200741086a200341d8056a41086a2903003700002002ad42808080808008842007ad428080808080048410042007102f2002102f41eba1ca00ad4280808080f0008410012202290000210420034180056a41086a200241086a29000037030020032004370380052002102f41a7cac800ad4280808080e00084100122022900002104200341a8056a41086a200241086a290000370300200320043703a8052002102f4120102d2202450d0c200220032903e004370000200241186a200341e0046a41186a290300370000200241106a200341e0046a41106a290300370000200241086a200341e0046a41086a2903003700002002ad4280808080800484100322072900002104200741086a2900002105200741106a2900002119200341b8086a41186a200741186a290000370300200341b8086a41106a2019370300200341b8086a41086a2005370300200320043703b8082007102f2002102f41c000102d2202450d0c2002200329038005370000200241086a20034180056a41086a2209290300370000200220032903a805370010200241186a200341a8056a41086a220a290300370000200220032903b808370020200241286a200341b8086a41086a2207290300370000200241306a200341b8086a41106a2206290300370000200241386a200341b8086a41186a2208290300370000200341b0076a200210a005024020032802dc072212410246220b0d002002ad428080808080088410050b200341d8066a41286a220c200341b0076a41286a280200360200200341d8066a41206a220d200341b0076a41206a2213290300370300200341d8066a41186a220e200341b0076a41186a290300370300200341d8066a41106a220f200341b0076a41106a290300370300200341d8066a41086a2210200341b0076a41086a2903003703002007200341b0076a41386a2903003703002006200341f0076a22142903003703002008200341f8076a2215290300370300200341b8086a41206a221120034180086a2216290300370300200320032903b0073703d806200320032903e0073703b808200a2010290300370300200341a8056a41106a200f290300370300200341a8056a41186a200e290300370300200341a8056a41206a220a200d290300370300200341a8056a41286a200c2802003602002009200729030037030020034180056a41106a200629030037030020034180056a41186a200829030037030020034180056a41206a22072011290300370300200320032903d8063703a805200320032903b808370380050240200b0d00200341e8036a41286a2206200341a8056a41286a280200360200200341e8036a41206a2208200a290300370300200341e8036a41186a2209200341a8056a41186a290300370300200341e8036a41106a220a200341a8056a41106a290300370300200341e8036a41086a220b200341a8056a41086a220c290300370300200341a8066a41086a220d20034180056a41086a220e290300370300200341a8066a41106a220f20034180056a41106a290300370300200341a8066a41186a221020034180056a41186a290300370300200341a8066a41206a22112007290300370300200320032903a8053703e80320032003290380053703a8062002102f200341b0076a41286a200628020036020020132008290300370300200341b0076a41186a2009290300370300200341b0076a41106a200a290300370300200341b0076a41086a200b290300370300200341e0076a20032903a806370300200341e8076a200d2903003703002014200f2903003703002015201029030037030020162011290300370300200320032903e8033703b007200320123602dc0741eba1ca00ad4280808080f00084100122022900002104200e200241086a29000037030020032004370380052002102f41a7cac800ad4280808080e00084100122022900002104200c200241086a290000370300200320043703a8052002102f4120102d2202450d0d200220032903d805370000200241186a200341d8056a41186a290300370000200241106a200341d8056a41106a290300370000200241086a200341d8056a41086a2903003700002002ad4280808080800484100322072900002104200741086a2900002105200741106a2900002119200341b8086a41186a200741186a290000370300200341b8086a41106a2019370300200341b8086a41086a2005370300200320043703b8082007102f2002102f41c000102d2202450d0d2002200329038005370000200241086a20034180056a41086a290300370000200220032903a805370010200241186a200341a8056a41086a290300370000200220032903b808370020200241286a200341b8086a41086a290300370000200241306a200341c8086a290300370000200241386a200341b8086a41186a290300370000200341c0003602dc06200320023602d806200341b0076a200341d8066a10c4032002102f200341d4076a280200450d0320032802d007102f0c030b2002102f0c020b200041023a00000c100b200041086a4108360200200041046a41d6c7c80036020041012107200041026a41013a000020004183103b0100410121080c110b200041043a00000c0e0b20012d0001210620032002411a6a2901003703c0052003200241026a2901003703a80520032002410a6a2901003703b0052003200241126a2901003703b80541012107024020022d00014101470d0020022d000041ff01710d00200341e8036a41186a200341a8056a41186a290300370300200341e8036a41106a200341a8056a41106a290300370300200341e8036a41086a200341a8056a41086a290300370300200320032903a8053703e803200341b0076a200341e8036a108103024020032802dc074102460d00200341b8086a41106a200341dc076a220241106a2901002204370300200341b8086a41186a200241186a2901002205370300200341d8066a41086a200241086a290100370300200341d8066a41106a2004370300200341d8066a41186a2005370300200341d8066a41206a2208200241206a290100370300200341d8066a41286a200241286a280100360200200320022901003703d80620032802d407210920032802d007213741eba1ca00ad4280808080f00084100122022d000f210a20022d000e210b20022f000c210c20022d000b210d20022d000a210e20022f0008210f20022d0007211020022d0006211120022f0004211220022d0003211320022d0002211420022f000021152002102f41c8abc900ad4280808080d0008410012202290008210420022d0007211620022d0006211720022f0004211820022d0003211a20022d0002211c20022f0000211d2002102f4120102d2207450d0a200720032903e006370000200741186a2008290300370000200741106a200341d8066a41186a290300370000200741086a200341d8066a41106a2903003700002007ad428080808080048410032202290018210520022d0017210820022d0016211e20022f0014211f20022d0013212020022d0012212120022f0010212220022d000f212320022d000e212420022f000c212520022d000b212620022d000a212720022f0008212820022d0007212920022d0006212a20022f0004212b20022d0003212c20022d0002212d20022f000021332002102f2007102f41c000102d2202450d0a20022005370038200220083a00372002201e3a00362002201f3b0034200220203a0033200220213a0032200220223b0030200220233a002f200220243a002e200220253b002c200220263a002b200220273a002a200220283b0028200220293a00272002202a3a00262002202b3b00242002202c3a00232002202d3a0022200220333b002020022004370018200220163a0017200220173a0016200220183b00142002201a3a00132002201c3a00122002201d3b00102002200a3a000f2002200b3a000e2002200c3b000c2002200d3a000b2002200e3a000a2002200f3b0008200220103a0007200220113a0006200220123b0004200220133a0003200220143a0002200220153b000002400240200641037122074103470d004101210742002104410121060c010b024002400240024020070e03000102000b410021060c020b410121060c010b410221060b200320063a00d8034101102d2207450d0b200720063a00004100210642808080801021040b2002ad428080808080088420042007ad841004024020060d002007102f0b2002102f02402009450d002037102f0b200041043a00000c0f0b200041086a410d360200200041046a41dec7c800360200200041026a41003a000020004183103b01000c0e0b200041023a0000410121080c0f0b41012107024020022d00014101470d0020022d000041ff01710d0020032002411a6a2901003703c0062003200241026a2901003703a80620032002410a6a2901003703b0062003200241126a2901003703b806200341b0076a200341a8066a108103024020032802dc074102460d00200341b8086a41086a2206200341dc076a220241086a290100370300200341b8086a41106a2208200241106a290100370300200341b8086a41186a2209200241186a290100370300200341b8086a41206a220a200241206a290100370300200341b8086a41286a220b200241286a280100360200200320022901003703b808200341b0076a41086a2903002104200341b0076a41186a290300210520032903b007211920032903c007211b20032802d007210720032802d807210c20032802d4072102200341e8036a41086a220d2006290300370300200341e8036a41106a22062008290300370300200341e8036a41186a22082009290300370300200341e8036a41206a2209200a290300370300200341e8036a41286a220a200b280200360200200341fc066a2002360200200341d8066a41286a200c360200200341d8066a41186a2005370300200320032903b8083703e803200320073602f8062003201b3703e806200320193703d806200320043703e006200341ac076a200a280200360200200341a4076a20092903003702002003419c076a200829030037020020034194076a20062903003702002003200d29030037028c07200320032903e803370284072003418c076a220610e805200610e90502402002450d002007102f0b200041043a00000c0e0b200041086a410d360200200041046a41dec7c800360200200041026a41003a000020004183103b01000c0d0b200041023a0000410121080c0e0b200041086a410d360200200041046a41dec7c800360200200041026a41003a000020004183103b01000c010b20004183103b0100200041086a410c360200200041046a41b0c7c800360200200041026a41043a00002002450d00200b102f0b41012108410021072009450d0b2006102f0c0b0b410021070b4100210a4101210202402009450d002006102f0b410021080c010b2009450d002006102f0b0240024002402007450d00200a450d012002102f0c010b20020d010b41012108200041013a00000240200328028c04450d00200328028804102f0b410021070c080b41eba1ca00ad4280808080f000842204100122072900002105200729000821192007102f41d2a0ca00ad4280808080a0018410012207290000211b2007290008212e2007102f2003202e3703c0052003201b3703b805200320193703b005200320053703a805200341286a200341a8056a4120109501200320083602e0052003200a3602dc05200320023602d805200341003a00e8052003200328022c410020032802281b3602e4052003419c046a220610e8052004100122022d000f210820022d000e210920022f000c210b20022d000b210c20022d000a210d20022f0008210e20022d0007210f20022d0006211020022f0004211120022d0003211220022d0002211320022f000021142002102f418bc6c800ad4280808080a0018410012202290008210420022d0007211520022d0006211620022f0004211720022d0003211820022d0002211a20022f0000211c2002102f4120102d2207450d0020072006290000370000200741186a200641186a290000370000200741106a200641106a290000370000200741086a200641086a2900003700002007ad428080808080048410032202290018210520022d0017211d20022d0016211e20022f0014211f20022d0013212020022d0012212120022f0010212220022d000f212320022d000e212420022f000c212520022d000b212620022d000a212720022f0008212820022d0007212920022d0006212a20022f0004212b20022d0003212c20022d0002212d20022f000021332002102f2007102f41c000102d220a450d00200a2005370038200a201d3a0037200a201e3a0036200a201f3b0034200a20203a0033200a20213a0032200a20223b0030200a20233a002f200a20243a002e200a20253b002c200a20263a002b200a20273a002a200a20283b0028200a20293a0027200a202a3a0026200a202b3b0024200a202c3a0023200a202d3a0022200a20333b0020200a2004370018200a20153a0017200a20163a0016200a20173b0014200a20183a0013200a201a3a0012200a201c3b0010200a20083a000f200a20093a000e200a200b3b000c200a200c3a000b200a200d3a000a200a200e3b0008200a200f3a0007200a20103a0006200a20113b0004200a20123a0003200a20133a0002200a20143b0000200341d8066a200a41c0001098040240024020032d00e8064102460d00200341b8086a41086a200341f5066a290000370300200341b8086a41106a200341fd066a290000370300200341b8086a41186a20034185076a29000037030020034180066a41086a20034196076a29010037030020034180066a41106a2003419e076a29010037030020034180066a41186a200341a6076a2901003703002003200341ed066a2900003703b80820032003418e076a290100370380062003418d076a2d0000210220032d00ec06210720032802dc06450d0120032802d806102f0c010b200320063602b40841eba1ca00ad4280808080f00084100122022900002104200341e0046a41086a2207200241086a290000370300200320043703e0042002102f41fbc5c800ad428080808080028410012202290000210420034180066a41086a2208200241086a29000037030020032004370380062002102f200341b8086a41086a2007290300370300200341d0086a2008290300370300200320032903e0043703b80820032003290380063703c808200341b0076a200341b8086a108801200341a8066a20032802b007220220032802b80710ad02024020032802b407450d002002102f0b200341c8086a210d0240024020032d00a8060d0041eba1ca00ad4280808080f00084100122022900002104200341e0046a41086a2207200241086a290000370300200320043703e0042002102f41fbc5c800ad428080808080028410012202290000210420034180066a41086a2208200241086a29000037030020032004370380062002102f200341b8086a41086a2007290300370300200d200329038006370000200d41086a2008290300370000200320032903e0043703b808200341b0076a200341b8086a10880120032802b007210720033502b80721044120102d2202450d0320022006290000370000200241186a200641186a290000370000200241106a200641106a290000370000200241086a200641086a29000037000020044220862007ad842002ad428080808080048410042002102f024020032802b407450d002007102f0b410021020c010b200341a8056a41186a200341c1066a290000370300200341a8056a41106a200341b9066a290000370300200341a8056a41086a200341b1066a290000370300200320032900a9063703a805200341c0046a200341a8056a109704200341b0076a20032802c004220e20032802c804220f109804024020032d00c0074102470d00200341003602e804200342013703e00420034180066a41146a41293602002003418c066a410b3602002003410736028409200341eba1ca00360280092003410b360284062003410a3602dc032003418bc6c8003602d8032003200341c0046a360290062003200341d8036a36028806200320034180096a360280062003200341e0046a36028c09200341b8086a41146a4103360200200342033702bc08200341cc90c4003602b808200320034180066a3602c8082003418c096a41d8dbc100200341b8086a103c1a20033502e80442208620033502e004841008024020032802e404450d0020032802e004102f0b20032802b408210741eba1ca00ad4280808080f00084100122022900002104200341e0046a41086a2206200241086a290000370300200320043703e0042002102f41fbc5c800ad428080808080028410012202290000210420034180066a41086a2208200241086a29000037030020032004370380062002102f200341b8086a41086a2006290300370300200d200329038006370000200d41086a2008290300370000200320032903e0043703b80820034180066a200341b8086a108801200328028006210620033502880621044120102d2202450d0320022007290000370000200241186a200741186a290000370000200241106a200741106a290000370000200241086a200741086a29000037000020044220862006ad842002ad428080808080048410042002102f0240200328028406450d002006102f0b024020032802c404450d0020032802c004102f0b410021020c010b200341b8086a200341b0076a41146a41c20010e8061a20032d00d908210220034180066a41106a200341b0076a41106a28020036020020034180066a41086a200341b0076a41086a290300220437030020034180066a41186a200341da086a410020024101461b360200200320032903b0072205370380062003200341b4086a36029406200341003602e804200342013703e0042004a72202200341e0046a10692005a721100240024020020d0020032802e404210820032802e80421070c010b2002410574210b410020032802e80422076b210920032802e404210820102102034002400240200820096a4120490d0020032802e00421060c010b200741206a22062007490d062008410174220c2006200c20064b1b220c4100480d060240024020080d00200c102d21060c010b20032802e0042008200c103121060b2006450d052003200c3602e404200320063602e004200c21080b200620076a220641086a200241086a290000370000200641106a200241106a290000370000200641186a200241186a2900003700002003200741206a22073602e80420062002290000370000200941606a2109200241206a2102200b41606a220b0d000b0b200328028c06210902400240200820076b4104490d0020032802e00421020c010b200741046a22022007490d04200841017422062002200620024b1b22064100480d040240024020080d002006102d21020c010b20032802e00420082006103121020b2002450d03200320063602e404200320023602e004200621080b2003200741046a22063602e804200220076a2009360000200320032d00900622093a00d803024020082006470d00200841016a22092008490d042008410174220b2009200b20094b1b22094100480d040240024020080d002009102d21020c010b200220082009103121020b2002450d03200320093602e404200320023602e00420032d00d80321090b2003200741056a3602e804200220066a20093a000020034180066a41146a200341e0046a10cd0220032802e4042102200fad422086200ead8420033502e80442208620032802e0042207ad84100402402002450d002007102f0b0240200328028406450d002010102f0b024020032802c404450d0020032802c004102f0b20032802b408210741eba1ca00ad4280808080f00084100122022900002104200341e0046a41086a2206200241086a290000370300200320043703e0042002102f41fbc5c800ad428080808080028410012202290000210420034180066a41086a2208200241086a29000037030020032004370380062002102f200341b8086a41086a2006290300370300200d200329038006370000200d41086a2008290300370000200320032903e0043703b808200341b0076a200341b8086a10880120032802b007210620033502b80721044120102d2202450d0220022007290000370000200241186a200741186a290000370000200241106a200741106a290000370000200241086a200741086a29000037000020044220862006ad842002ad428080808080048410042002102f024020032802b407450d002006102f0b20034180066a41086a200341a8056a41086a29030037030020034180066a41106a200341a8056a41106a29030037030020034180066a41186a200341a8056a41186a290300370300200320032903a80537038006410121020b410021070b200341d5076a20023a0000200341d6076a200329038006370100200341bd076a200341b8086a41086a290300370000200341c5076a200341b8086a41106a290300370000200341cd076a200341b8086a41186a290300370000200341de076a20034180066a41086a290300370100200341e6076a20034180066a41106a290300370100200341ee076a20034180066a41186a290300370100200320073a00b407200320032903b8083700b5072003200341d8056a3602b007200341003602e006200342013703d80620032802d805210220032802e0052207200341d8066a10690240024020070d0020032802dc06210820032802e00621070c010b2007410574210b410020032802e00622076b210920032802dc062108034002400240200820096a4120490d0020032802d80621060c010b200741206a22062007490d042008410174220c2006200c20064b1b220c4100480d040240024020080d00200c102d21060c010b20032802d8062008200c103121060b2006450d032003200c3602dc06200320063602d806200c21080b200620076a220641086a200241086a290000370000200641106a200241106a290000370000200641186a200241186a2900003700002003200741206a22073602e00620062002290000370000200941606a2109200241206a2102200b41606a220b0d000b0b20032802e405210902400240200820076b4104490d0020032802d80621020c010b200741046a22022007490d02200841017422062002200620024b1b22064100480d020240024020080d002006102d21020c010b20032802d80620082006103121020b2002450d01200320063602dc06200320023602d806200621080b2003200741046a22063602e006200220076a2009360000200320032d00e80522093a00d803024020082006470d00200841016a22092008490d022008410174220b2009200b20094b1b22094100480d020240024020080d002009102d21020c010b200220082009103121020b2002450d01200320093602dc06200320023602d80620032d00d80321090b2003200741056a3602e006200220066a20093a0000200341b0076a410472200341d8066a10ce0220032802dc062102200aad428080808080088420033502e00642208620032802d8062207ad84100402402002450d002007102f0b200a102f024020032802dc05450d0020032802d805102f0b0240200328028c04450d00200328028804102f0b200041043a000041012108410021070c070b1036000b1038000b41002106410021070b200341d5076a20063a0000200341d6076a200329038006370100200341bd076a200341b8086a41086a290300370000200341c5076a200341b8086a41106a290300370000200341cd076a200341b8086a41186a290300370000200341de076a20034180066a41086a290300370100200341e6076a20034180066a41106a290300370100200341ee076a20034180066a41186a290300370100200320073a00b4072003201a3602b007200320032903b8083700b507200341003602f003200342013703e803200341b0076a200341e8036a109502200341b0076a410472200341e8036a10ce0220032802ec0321072002ad428080808080088420033502f00342208620032802e8032206ad84100402402007450d002006102f0b2002102f024020032802fc06450d0020032802f806102f0b200041043a00000c010b024020032802fc06450d0020032802f806102f0b200041043a00000b41012107410121080c010b20004183103b0100200041086a2002360200200041046a2006360200200041026a20083a0000410121080b41012106410121000b024020012d0000417a6a2202410b4b0d00024002400240024020020e0c000404040404040104040203000b2007450d03200141086a280200450d03200141046a280200102f0c030b2008450d02200141086a280200450d02200141046a280200102f0c020b2006450d012001410c6a280200450d01200141086a280200102f0c010b2000450d002001410c6a280200450d00200141086a280200102f0b20034190096a24000bb60603027f037e057f230041b0016b2202240041eba1ca00ad4280808080f00084100122032900002104200241d8006a41086a200341086a290000370300200220043703582003102f41a7cac800ad4280808080e0008410012203290000210420024180016a41086a200341086a29000037030020022004370380012003102f02404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100322012900002104200141086a2900002105200141106a2900002106200241186a2207200141186a290000370300200241106a22082006370300200241086a2005370300200220043703002001102f2003102f41c000102d2203450d0020032002290358370000200320022903800137001020032002290300370020200341086a200241d8006a41086a2201290300370000200341186a20024180016a41086a2209290300370000200341286a200241086a220a290300370000200341306a2008290300370000200341386a20072903003700002002200310a0052009200a29030037030020024180016a41106a200829030037030020024180016a41186a200729030037030020024180016a41206a2208200241206a29030037030020024180016a41286a220a200241286a2802003602002001200241386a290300370300200241d8006a41106a200241c0006a290300370300200241d8006a41186a200241c8006a290300370300200241d8006a41206a220b200241d0006a2903003703002002200229030037038001200220022903303703580240200228022c22074102460d00200020022903800137030020002002290358370330200041286a200a280200360200200041206a2008290300370300200041186a20024180016a41186a290300370300200041106a20024180016a41106a290300370300200041086a2009290300370300200041386a2001290300370300200041c0006a200241d8006a41106a290300370300200041c8006a200241d8006a41186a290300370300200041d0006a200b2903003703000b2000200736022c2003102f200241b0016a24000f0b1036000b980605027f017e057f027e027f230041c0006b22022400419c9eca00ad4280808080f00084100122032900002104200241206a41086a200341086a290000370300200220043703202003102f4186ebc300ad4280808080800184100122032900002104200241086a200341086a290000370300200220043703002003102f200241306a41e7eac300410d109c040240024002400240024002402002280238220541206a2206417f4c0d0020022802302107024002402006450d002006102d2203450d062006410f4d0d01200621080c050b411021084110102d21030c030b200641017422094110200941104b1b220841004e0d010c050b103d000b200320062008103121030b2003450d010b20032002290320370000200341086a200241206a41086a2903003700000240024020084170714110460d00200821090c010b200841017422094120200941204b1b22094100480d0220032008200910312203450d010b20032002290300370010200341186a200241086a29030037000002400240200941606a2005490d00200921080c010b2005415f4b0d02200941017422082006200820064b1b22084100480d0220032009200810312203450d010b200341206a2007200510e8061a02402002280234450d002007102f0b4120102d2209450d0020092001290000370000200941186a200141186a290000370000200941106a200141106a290000370000200941086a200141086a2900003700002009ad4280808080800484100322012900002104200141086a290000210a200141106a290000210b200241186a2207200141186a290000370300200241106a220c200b370300200241086a220d200a370300200220043703002001102f2009102f200541c0006a210902400240200820066b411f4d0d00200821010c010b200841017422012009200120094b1b22014100480d0220032008200110312203450d010b200320066a22062002290300370000200641186a2007290300370000200641106a200c290300370000200641086a200d290300370000200020093602082000200136020420002003360200200241c0006a24000f0b1036000b1038000bd60201027f230041c0026b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100210730240024020032802102201450d00200328021421042003200341186a2802003602ac02200320013602a802200341a0016a200341a8026a10ee02410121020240024020032d00a0014101470d004100210220034100360228200342013703202003410b3602b4022003200341086a3602b0022003200341206a3602bc02200341b4016a4101360200200342013702a401200341b885c7003602a0012003200341b0026a3602b001200341bc026a41d8dbc100200341a0016a103c1a200335022842208620033502208410082003280224450d012003280220102f0c010b200341206a200341a0016a41017241800110e8061a200041016a200341206a41800110e8061a0b200020023a00002004450d012001102f0c010b200041003a00000b200341c0026a24000ba70804027f017e087f027e230041c0006b22022400419c9eca00ad4280808080f00084100122032900002104200241206a41086a200341086a290000370300200220043703202003102f41ac9fc400ad4280808080800184100122032900002104200241086a200341086a290000370300200220043703002003102f200241306a41e7eac300410d109c040240024002400240024002402002280238220541206a2206417f4c0d002002280230210702400240024002402006450d002006102d2203450d082006410f4d0d01200621080c030b411021084110102d21030c010b200641017422094110200941104b1b22084100480d07200320062008103121030b2003450d050b20032002290320370000200341086a200241206a41086a2903003700000240024020084170714110460d00200821090c010b200841017422094120200941204b1b22094100480d0620032008200910312203450d050b20032002290300370010200341186a200241086a29030037000002400240200941606a2005490d002009210a0c010b2005415f4b0d06200941017422082006200820064b1b220a4100480d0620032009200a10312203450d050b200341206a2007200510e8061a02402002280234450d002007102f0b200141086a280200220941046a2208417f4c0d002008450d012008102d2207450d04200241003602082002200736020020022008360204200841034b0d032008410174220b4104200b41044b1b220b4100480d0520072008200b103121070c020b103d000b200241003602082002410136020020022008360204200841017422084104200841044b1b220b102d21070b2007450d012002200b360204200220073602000b20024104360208200720012800003600002001280204210b2009200210690240024020022802042201200228020822076b2009490d00200228020021080c010b200720096a22082007490d022001410174220c2008200c20084b1b220c4100480d020240024020010d00200c102d21080c010b20022802002001200c103121080b2008450d012002200c36020420022008360200200c21010b200820076a200b200910e8061a200720096aad4220862008ad84100322092900002104200941086a290000210d200941106a290000210e200241186a200941186a290000370300200241106a200e370300200241086a200d370300200220043703002009102f02402001450d002008102f0b200541c0006a210902400240200a20066b411f4d0d00200a21080c010b200a41017422082009200820094b1b22084100480d022003200a200810312203450d010b200320066a22062002290300370000200641186a200241186a290300370000200641106a200241106a290300370000200641086a200241086a290300370000200020093602082000200836020420002003360200200241c0006a24000f0b1036000b1038000b806a06077f017e027f017e0d7f027e230041a0046b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e06000102030405000b200341e4016a4101360200200342013702d401200341b4d8c9003602d001200341043602ac01200341fcdbc9003602a8012003200341a8016a3602e001200341d0016a41e8d8c9001043000b2001412c6a2802002104200141286a2802002105200141246a280200210620012d0001210720034188016a41186a2001411a6a29000037030020034188016a41106a200141126a29000037030020034188016a41086a2001410a6a2900003703002003200141026a290000370388010240024020022d000120022d0000410047720d0020062004108701200341d0016a41186a4200370300200341d0016a41106a22024200370300200341d0016a41086a22084200370300200342003703d00141f2cbc700ad4280808080b0028410012209290000210a2008200941086a2900003703002003200a3703d0012009102f41ebdec700ad4280808080f0008410012209290000210a200341c8006a41086a220b200941086a2900003703002003200a3703482009102f20022003290348220a370300200341a8016a41086a2008290300370300200341a8016a41106a200a370300200341a8016a41186a200b290300370300200320032903d0013703a801200341d0016a200341a8016a412010aa02200341d0016a2006200420032802d0012208410120081b220920032902d401420020081b220a422088a71097052002280200210220032802d401210820032802d001210b20032802dc01220c200341e4016a2802002006200410980502402002450d00200c102f0b02402008450d00200b102f0b20034180046a41186a220220034188016a41186a29030037030020034180046a41106a220420034188016a41106a29030037030020034180046a41086a220820034188016a41086a29030037030020032003290388013703800402400240200741ff01710d00200341a8016a41186a4200370300200341a8016a41106a22074200370300200341a8016a41086a22024200370300200342003703a80141f2cbc700ad4280808080b0028410012204290000210d200341e8006a41086a2208200441086a2900003703002003200d3703682004102f20022008290300370300200320032903683703a80141fbd4c700ad4280808080d0008410012204290000210d200341f8006a41086a2208200441086a2900003703002003200d3703782004102f20072003290378220d370300200341286a41086a2002290300370300200341286a41106a200d370300200341286a41186a2008290300370300200320032903a801370328200341286aad428080808080048410050c010b200341a8016a41186a2002290300370300200341a8016a41106a2004290300370300200341a8016a41086a200829030037030020032003290380043703a801200341c8006a41186a4200370300200341c8006a41106a22084200370300200341c8006a41086a220442003703002003420037034841f2cbc700ad4280808080b0028410012207290000210d200341286a41086a2202200741086a2900003703002003200d3703282007102f200420022903003703002003200329032837034841fbd4c700ad4280808080d0008410012207290000210d2002200741086a2900003703002003200d3703282007102f20082003290328220d370300200341d0016a41086a2004290300370300200341d0016a41106a200d370300200341d0016a41186a2002290300370300200320032903483703d0014120102d2202450d07200220032903a801370000200241186a200341a8016a41186a290300370000200241106a200341a8016a41106a290300370000200241086a200341a8016a41086a290300370000200341d0016aad42808080808004842002ad428080808080048410042002102f0b0240200aa7450d002009102f0b02402005450d002006102f0b200041043a00000c010b200041023a00002005450d002006102f0b41012104410021050c110b200141046a280200210720032002411a6a2901003703c0012003200241026a2901003703a80120032002410a6a2901003703b0012003200241126a2901003703b8010240024020022d00014101470d0020022d000041ff01710d0020034188016a41186a200341a8016a41186a220429030037030020034188016a41106a200341a8016a41106a220529030037030020034188016a41086a200341a8016a41086a2208290300370300200320032903a80137038801200341d0016a41186a4200370300200341d0016a41106a22094200370300200341d0016a41086a22024200370300200342003703d00141f2cbc700ad4280808080b0028410012206290000210a2002200641086a2900003703002003200a3703d0012006102f41ebdec700ad4280808080f0008410012206290000210a200341c8006a41086a220b200641086a2900003703002003200a3703482006102f20092003290348220a370300200820022903003703002005200a3703002004200b290300370300200320032903d0013703a801200341d0016a200341a8016a412010aa0220032902d401420020032802d00122021b220a422088a741057421062002410120021b2208210202400340024020060d00410021050c020b4101210520034188016a2002460d01200641606a2106200220034188016a412010ea062104200241206a210220040d000b0b0240200aa7450d002008102f0b2005450d0141002104200341003602d801200342013703d0012007200341d0016a10910120032802d401210620034180046a41186a220820033502d80142208620032802d0012205ad841003220241186a29000037030020034180046a41106a2209200241106a29000037030020034180046a41086a220b200241086a29000037030020032002290000370380042002102f02402006450d002005102f0b200341d0016a200741b00210e8061a200341a8016a410d6a20034188016a41086a290300370000200341a8016a41156a20034188016a41106a290300370000200341a8016a411d6a20034188016a41186a29030037000041012105200341013a00ac0120032003290388013700ad01200341013a00a801200341c8006a200341d0016a200341a8016a108b0120032d00482102200341d0016a410d6a200b290300370000200341d0016a41156a2009290300370000200341d0016a411d6a2008290300370000200341f5016a20024104463a0000200341053a00d401200341073a00d00120032003290380043700d50141c8e1ca004100200341d0016a108c01200041043a00002007102f0c120b200041023a00000c100b20004183163b0100200041086a4109360200200041046a41d1d5c700360200200041026a41003a00000c0f0b200141086a2802002107200141046a280200210e2002411a6a290100210a200241196a2d00002104200241186a2d00002105200241166a2f01002108200241156a2d00002109200241146a2d0000210b200241126a2f0100210c200241116a2d0000210f200241106a2d000021102002410e6a2f010021112002410d6a2d000021122002410c6a2d000021132002410a6a2f01002114200241096a2d00002115200241086a2d00002116200241066a2f01002117200241056a2d00002118200241046a2d00002119200241026a2f0100211a41012106024020022d00000d0020022d000141014721060b2003200a370340200320043a003f200320053a003e200320083b013c200320093a003b2003200b3a003a2003200c3b01382003200f3a0037200320103a0036200320113b0134200320123a0033200320133a0032200320143b0130200320153a002f200320163a002e200320173b012c200320183a002b200320193a002a2003201a3b01280240024002400240024020060d0020034188016a41186a200341286a41186a29030037030020034188016a41106a200341286a41106a29030037030020034188016a41086a200341286a41086a2903003703002003200329032837038801200341d0016a41186a4200370300200341d0016a41106a22084200370300200341d0016a41086a22024200370300200342003703d00141f2cbc700ad4280808080b0028410012206290000210a2002200641086a2900003703002003200a3703d0012006102f41ebdec700ad4280808080f0008410012206290000210a200341c8006a41086a2204200641086a2900003703002003200a3703482006102f20082003290348220a370300200341a8016a41086a2002290300370300200341a8016a41106a200a370300200341a8016a41186a2004290300370300200320032903d0013703a801200341d0016a200341a8016a412010aa0220032902d401420020032802d00122021b220a422088a741057421062002410120021b2209210202400340024020060d00410021050c020b4101210520034188016a2002460d01200641606a2106200220034188016a412010ea062104200241206a210220040d000b0b0240200aa7450d002009102f0b2005450d08200341003602d801200342013703d0012007200341d0016a10910120032802d401210620034180046a41186a220420033502d80142208620032802d001220bad841003220241186a29000037030020034180046a41106a2205200241106a29000037030020034180046a41086a2209200241086a29000037030020032002290000370380042002102f02402006450d00200b102f0b200341d0016a41186a2004290300370300200341d0016a41106a2005290300370300200341d0016a41086a200929030037030020032003290380043703d00141f2cbc700ad4280808080b0028410012202290000210a200341e8006a41086a200241086a2900003703002003200a3703682002102f41f0abc800ad4280808080a0018410012202290000210a200341f8006a41086a200241086a2900003703002003200a3703782002102f4120102d2202450d07200220032903d001370000200241186a200341d0016a41186a290300370000200241106a200341d0016a41106a290300370000200241086a200341d0016a41086a2903003700002002ad428080808080048410032206290000210a200641086a290000210d200641106a290000211b200341c8006a41186a2204200641186a290000370300200341c8006a41106a2205201b370300200341c8006a41086a2209200d3703002003200a3703482006102f2002102f41c000102d2202450d0720022003290368370000200241086a200341e8006a41086a29030037000020022003290378370010200241186a200341f8006a41086a29030037000020022003290348370020200241286a2009290300370000200241306a2005290300370000200241386a2004290300370000200341186a200241c00041c8e1ca004100410010b501200328021821062002102f20064101460d09200e4102490d034200210d200341c8006a41186a220f4200370300200341c8006a41106a22064200370300200341c8006a41086a220242003703002003420037034841f2cbc700ad4280808080b00284220a10012205290000211b200341e8006a41086a2204200541086a2900003703002003201b3703682005102f20022004290300370300200320032903683703484188a3ca00ad4280808080d00184221b10012209290000211c200341f8006a41086a2205200941086a2900003703002003201c3703782009102f20062003290378221c370300200341a8016a41086a22092002290300370300200341a8016a41106a220b201c370300200341a8016a41186a220c2005290300370300200320032903483703a801200341106a200341a8016a41201095012003280214211120032802102112200f4200370300200642003703002002420037030020034200370348200a10012210290000211c2004201041086a2900003703002003201c3703682010102f2002200429030037030020032003290368370348201b10012210290000211c2005201041086a2900003703002003201c3703782010102f20062003290378221c37030020092002290300370300200b201c370300200c2005290300370300200320032903483703a801200341086a200341a8016a412010950120032802082110200328020c2113200f4200370300200642003703002002420037030020034200370348200a1001220f290000211c2004200f41086a2900003703002003201c370368200f102f2002200429030037030020032003290368370348201b10012204290000211b2005200441086a2900003703002003201b3703782004102f20062003290378221b37030020092002290300370300200b201b370300200c2005290300370300200320032903483703a801410121062003201341016a410120101b3602d001200341a8016aad4280808080800484200341d0016aad4280808080c000841004200341d0016a41186a220f4200370300200341d0016a41106a22104200370300200341d0016a41086a22044200370300200342003703d001200a10012205290000210a2004200541086a2900003703002003200a3703d0012005102f41e2dec700ad428080808090018410012205290000210a2002200541086a2900003703002003200a3703482005102f20082003290348370000200841086a200229030037000020092004290300370300200b2010290300370300200c200f290300370300200320032903d0013703a801200341d0016a200341a8016a412010aa0220032802d00122050d0141002102410021040c020b200041023a00000c100b20032902d401220d422088a72104200da72102200521060b200c20034180046a41186a290300370300200b20034180046a41106a290300370300200920034180046a41086a29030037030020032003290380043703a8010240024020042002460d002002210c0c010b02402002200da7220c470d00200241016a22042002490d0b200241017422052004200520044b1b220441ffffff3f712004470d0b200441057422044100480d0b0240024020020d002004102d21060c010b200620024105742004103121060b2006450d06200d42808080807083210d2004410576210c0b200d422088a721040b200620044105746a220220032903a801370000200241186a200341a8016a41186a2209290300370000200241106a200341a8016a41106a2205290300370000200241086a200341a8016a41086a2202290300370000200942003703002005420037030020024200370300200342003703a80141f2cbc700ad4280808080b0028410012209290000210a200341e8006a41086a220b200941086a2900003703002003200a3703682009102f2002200b290300370300200320032903683703a80141e2dec700ad428080808090018410012209290000210a200341f8006a41086a220b200941086a2900003703002003200a3703782009102f20052003290378220a370300200341c8006a41086a2002290300370300200341c8006a41106a200a370300200341c8006a41186a200b290300370300200320032903a8013703480240024020060d00200341c8006aad428080808080048410050c010b200341203602d4012003200341c8006a3602d0012006200441016a200341d0016a108301200c450d002006102f0b200341d0016a200741b00210e8061a200341a8016a41186a220620034180046a41186a290300370300200341a8016a41106a220420034180046a41106a290300370300200341a8016a41086a220520034180046a41086a29030037030020032003290380043703a80141f2cbc700ad4280808080b0028410012202290000210a200341e8006a41086a200241086a2900003703002003200a3703682002102f41f0abc800ad4280808080a0018410012202290000210a200341f8006a41086a200241086a2900003703002003200a3703782002102f4120102d2202450d04200220032903a801370000200241186a2006290300370000200241106a2004290300370000200241086a20052903003700002002ad428080808080048410032206290000210a200641086a290000210d200641106a290000211b200341c8006a41186a200641186a290000370300200341c8006a41106a201b370300200341c8006a41086a200d3703002003200a3703482006102f2002102f41c000102d2202450d0420022003290368370000200241086a200341e8006a41086a29030037000020022003290378370010200241186a200341f8006a41086a29030037000020022003290348370020200241286a200341c8006a41086a2206290300370000200241306a200341c8006a41106a290300370000200241386a200341c8006a41186a290300370000200341003602b001200342013703a801200341d0016a200341a8016a10910120032802ac0121042002ad428080808080088420033502b00142208620032802a8012205ad84100402402004450d002005102f0b2002102f200341d0016a108e01200341d0016a41186a22054200370300200341d0016a41106a22094200370300200341d0016a41086a22024200370300200342003703d001418de6c300ad4280808080e0008410012204290000210a2002200441086a2900003703002003200a3703d0012004102f419ce6c300ad4280808080e0008410012204290000210a2006200441086a2900003703002003200a3703482004102f20082003290348370000200841086a2006290300370000200341a8016a41086a2002290300370300200341a8016a41106a2009290300370300200341a8016a41186a2005290300370300200320032903d0013703a8012003200341a8016a412010950120032802042102200328020021044120102d2206450d042006200329038801370000200641186a20034188016a41186a290300370000200641106a20034188016a41106a290300370000200641086a20034188016a41086a290300370000200341ec016a4100360200200341dc016a428180808010370200200320024180e5086a4180e50820041b3602f001200342013702e401200320063602d8012003200e3602d40120032011410020121b22053602d001200341a8016a41186a220420034180046a41186a290300370300200341a8016a41106a220820034180046a41106a290300370300200341a8016a41086a220920034180046a41086a29030037030020032003290380043703a80141f2cbc700ad4280808080b0028410012202290000210a200341e8006a41086a200241086a2900003703002003200a3703682002102f41f2dec700ad4280808080e0008410012202290000210a200341f8006a41086a200241086a2900003703002003200a3703782002102f4120102d2202450d04200220032903a801370000200241186a2004290300370000200241106a2008290300370000200241086a20092903003700002002ad428080808080048410032204290000210a200441086a290000210d200441106a290000211b200341c8006a41186a200441186a290000370300200341c8006a41106a201b370300200341c8006a41086a200d3703002003200a3703482004102f2002102f41c000102d2202450d0420022003290368370000200241086a200341e8006a41086a29030037000020022003290378370010200241186a200341f8006a41086a29030037000020022003290348370020200241286a200341c8006a41086a290300370000200241306a200341c8006a41106a290300370000200241386a200341c8006a41186a290300370000200341c0003602ac01200320023602a801200341d0016a200341a8016a10bd052002102f2006102f200341dd016a20034188016a41086a290300370000200341e5016a20034188016a41106a290300370000200341ed016a20034188016a41186a290300370000200341f5016a200329038004370000200341fd016a20034180046a41086a29030037000020034185026a20034180046a41106a2903003700002003418d026a20034180046a41186a2903003700002003419c026a200e36020020034198026a2005360200200341003a00d401200341073a00d00120032003290388013700d501200341d0016a21020c010b200341d0016a41186a22044200370300200341d0016a41106a22054200370300200341d0016a41086a22024200370300200342003703d00141f2cbc700ad4280808080b0028410012206290000210a2002200641086a2900003703002003200a3703d0012006102f41ebdec700ad4280808080f0008410012206290000210a200341c8006a41086a2209200641086a2900003703002003200a3703482006102f20082003290348370000200841086a2009290300370000200341a8016a41086a2002290300370300200341a8016a41106a2005290300370300200341a8016a41186a2004290300370300200320032903d0013703a801200341286a200341a8016a412010aa0202400240200328022822060d00410021020c010b200329022c220a422088a72102200aa7450d002006102f0b200341d0016a200741b00210e8061a200341b4016a2002360200200341a8016a41086a4101360200200341003a00ac01200341013a00a801200341c8006a200341d0016a200341a8016a108b0120032d00482102200341dd016a20034180046a41086a290300370000200341e5016a20034190046a290300370000200341ed016a20034198046a290300370000200341043a00d401200341f5016a20024104463a0000200341073a00d00120032003290380043700d501200341d0016a21020b4100210641c8e1ca0041002002108c01200041043a00002007102f0c0d0b200141216a2d0000210e200141246a280200211a20034188016a41186a200141196a29000037030020034188016a41106a200141116a29000037030020034188016a41086a200141096a29000037030020032001290001370388012002411a6a290100210a200241196a2d00002104200241186a2d00002105200241166a2f01002107200241156a2d00002108200241146a2d00002109200241126a2f0100210b200241116a2d0000210c200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241086a2d00002115200241066a2f01002116200241056a2d00002117200241046a2d00002118200241026a2f0100211941012106024020022d00000d0020022d000141014721060b2003200a3701e801200320043a00e701200320053a00e601200320073b01e401200320083a00e301200320093a00e2012003200b3b01e0012003200c3a00df012003200f3a00de01200320103b01dc01200320113a00db01200320123a00da01200320133b01d801200320143a00d701200320153a00d601200320163b01d401200320173a00d301200320183a00d201200320193b01d00120060d0420034180046a41186a200341d0016a41186a220629010037030020034180046a41106a200341d0016a41106a220729010037030020034180046a41086a200341d0016a41086a2202290100370300200320032901d00137038004200642003703002007420037030020024200370300200342003703d00141f2cbc700ad4280808080b0028410012206290000210a2002200641086a2900003703002003200a3703d0012006102f41ebdec700ad4280808080f0008410012206290000210a200341c8006a41086a2204200641086a2900003703002003200a3703482006102f20072003290348220a370300200341a8016a41086a2002290300370300200341a8016a41106a200a370300200341a8016a41186a2004290300370300200320032903d0013703a801200341d0016a200341a8016a412010aa0220032902d401420020032802d00122021b220a422088a741057421062002410120021b2208210202400340024020060d00410021050c020b4101210520034180046a2002460d01200641606a2106200220034180046a412010ea062104200241206a210220040d000b0b0240200aa7450d002008102f0b024002402005450d00200341d0016a20034188016a10c605024020032802d8012209450d00200341e8016a280200210b200341e4016a280200211020032802dc01210c20032802d001201a460d02410a210241a7d5c7002106410321040c0c0b20004183163b0100200041086a410f360200200041046a41b1d5c700360200200041026a41023a00000c0c0b20004183163b0100200041086a4109360200200041046a41d1d5c700360200200041026a41003a00000c0b0b200341f0016a2802002114200341ec016a280200210f20032802d40121134100210641002104410021120240200341e0016a2802002211450d002011410574210541002104200921020240034020034180046a2002460d012004200220034180046a412010ea0622084100476a21042008450d01200241206a2102200541606a22050d000b410021120c010b410121120b410021020240200f450d00200f410574210541002106201021020240034020034180046a2002460d012006200220034180046a412010ea0622084100476a21062008450d01200241206a2102200541606a22050d000b410021020c010b410121020b024002400240200e41ff01710d002002450d010c0b0b20120d0a200341286a41186a220820034180046a41186a290300370300200341286a41106a221220034180046a41106a290300370300200341286a41086a221520034180046a41086a2903003703002003200329038004370328024002402011200c460d00200c21052011210c0c010b200c41016a2204200c490d09200c41017422052004200520044b1b220441ffffff3f712004470d09200441057422044100480d0902400240200c0d002004102d21090c010b2009200c4105742004103121090b2009450d04200441057621050b2009200c4105746a22042003290328370000200441186a2008290300370000200441106a2012290300370000200441086a2015290300370000201141016a21112002450d01200f20064d0d072010200f417f6a220f4105746a2202290000210a2002290008210d2002290010211b201020064105746a220641186a200241186a2900003700002006201b3700102006200d3700082006200a3700000c010b200341c8006a41186a220620034180046a41186a290300370300200341c8006a41106a220520034180046a41106a290300370300200341c8006a41086a220820034180046a41086a290300370300200320032903800437034802400240200f200b460d00200b2115200f210b0c010b200b41016a2202200b490d08200b41017422152002201520024b1b220241ffffff3f712002470d08200241057422024100480d0802400240200b0d002002102d21100c010b2010200b4105742002103121100b2010450d03200241057621150b2010200b4105746a22022003290348370000200241186a2006290300370000200241106a2005290300370000200241086a2008290300370000200f41016a210f02402012450d00201120044d0d0920092011417f6a22114105746a2202290000210a2002290008210d2002290010211b200920044105746a220641186a200241186a2900003700002006201b3700102006200d3700082006200a3700000b200c21052015210b0b200341f5016a200329038801370000200341dd016a20034180046a41086a290300370000200341e5016a20034180046a41106a290300370000200341ed016a20034180046a41186a290300370000200341fd016a20034188016a41086a29030037000020034185026a20034188016a41106a2903003700002003418d026a20034188016a41186a290300370000200341013a00d401200341073a00d00120032003290380043700d5012003419c026a200f36020020034198026a201136020020034195026a200e3a00004100210241c8e1ca004100200341d0016a108c01200341d0016a41186a22084200370300200341d0016a41106a220c4200370300200341d0016a41086a22064200370300200342003703d00141f2cbc700ad4280808080b0028410012204290000210a2006200441086a2900003703002003200a3703d0012004102f41ebdec700ad4280808080f0008410012204290000210a200341c8006a41086a2212200441086a2900003703002003200a3703482004102f20072003290348370000200741086a2012290300370000200341a8016a41086a2006290300370300200341a8016a41106a200c290300370300200341a8016a41186a2008290300370300200320032903d0013703a801200341286a200341a8016a412010aa02024020032802282206450d00200329022c220a422088a72102200aa7450d002006102f0b02400240201120134f22060d0041002002200f6b2204200420024b1b2013490d00200341ec016a200f360200200341d0016a41186a200b360200200341d0016a41106a2011360200200341dc016a2005360200200320143602f001200320103602e401200320093602d801200320133602d4012003201a3602d00141f2cbc700ad4280808080b0028410012202290000210a200341e8006a41086a200241086a2900003703002003200a3703682002102f41f2dec700ad4280808080e0008410012202290000210a200341f8006a41086a200241086a2900003703002003200a3703782002102f4120102d2202450d032002200329038801370000200241186a20034188016a41186a290300370000200241106a20034188016a41106a290300370000200241086a20034188016a41086a2903003700002002ad428080808080048410032206290000210a200641086a290000210d200641106a290000211b200341a8016a41186a200641186a290000370300200341a8016a41106a201b370300200341a8016a41086a200d3703002003200a3703a8012006102f2002102f41c000102d2202450d0320022003290368370000200241086a200341e8006a41086a29030037000020022003290378370010200241186a200341f8006a41086a290300370000200220032903a801370020200241286a200341a8016a41086a290300370000200241306a200341b8016a290300370000200241386a200341a8016a41186a290300370000200341c0003602ac01200320023602a801200341d0016a200341a8016a10bd052002102f02402005450d002009102f0b200b450d012010102f0c010b200341ec016a200f360200200341d0016a41186a200b360200200341d0016a41106a2011360200200341dc016a2005360200200320143602f001200320103602e401200320093602d8012003201a3602d001200320133602d401200341a8016a41186a20034188016a41186a290300370300200341a8016a41106a20034188016a41106a290300370300200341a8016a41086a20034188016a41086a29030037030020032003290388013703a80120062002200341d0016a200341a8016a10c7050b200041043a00000c0a0b200141246a280200210620034198046a200141196a29000037030020034190046a200141116a29000037030020034188046a200141096a2900003703002003200129000137038004024002400240024020022d00000d0020022d00014101470d00200341d0016a20034180046a10c605024020032802d8012207450d00200341d0016a41186a22022802002109200341e4016a280200210f20032802dc01210b20032802d0012006460d02410a210241a7d5c7002106410321040c030b20004183163b0100200041086a410f360200200041046a41b1d5c700360200200041026a41023a00000c0d0b200041023a00000c0c0b200341d0016a41206a2802002111200341ec016a2802002112200341d0016a41106a220c280200211020032802d401211320024200370300200c420037030041082102200341d0016a41086a22044200370300200342003703d001418de6c300ad4280808080e0008410012205290000210a2004200541086a2900003703002003200a3703d0012005102f419ce6c300ad4280808080e0008410012205290000210a200341c8006a41086a2208200541086a2900003703002003200a3703482005102f200c2003290348220a370300200341a8016a41086a2004290300370300200341a8016a41106a200a370300200341a8016a41186a2008290300370300200320032903d0013703a801200341206a200341a8016a41201095012003280224410020032802201b20114f0d014180d5c7002106410621040b20004183163b0100200041086a2002360200200041046a2006360200200041026a20043a00000240200b450d002007102f0b2009450d0a200f102f0c0a0b200341a8016a41186a22084200370300200341a8016a41106a22044200370300200341a8016a41086a22024200370300200342003703a80141f2cbc700ad4280808080b0028410012205290000210a200341e8006a41086a2214200541086a2900003703002003200a3703682005102f20022014290300370300200320032903683703a80141fbd4c700ad4280808080d0008410012205290000210a200341f8006a41086a2214200541086a2900003703002003200a3703782005102f20042003290378220a370300200341c8006a41086a2002290300370300200341c8006a41106a200a370300200341c8006a41186a2014290300370300200320032903a801370348200341d0016a200341c8006a412010ad0220032d00d00121052008200341e9016a2900003703002004200341e1016a2900003703002002200341d9016a290000370300200320032900d1013703a8010240024020054101460d00410021080c010b200341286a41186a2008290300220a370300200341286a41106a2004290300220d370300200341286a41086a2002290300221b370300200320032903a801221c370328200341d0016a41186a200a370300200341d0016a41106a200d370300200341d0016a41086a201b3703002003201c3703d00120104105742104200721020340024020040d00410021080c020b41012108200341d0016a2002460d01200441606a21042002200341d0016a412010ea062105200241206a210220050d000b0b200341d0016a41186a22054200370300200341d0016a41106a22144200370300200341d0016a41086a22024200370300200342003703d00141f2cbc700ad4280808080b0028410012204290000210a2002200441086a2900003703002003200a3703d0012004102f41ebdec700ad4280808080f0008410012204290000210a200341c8006a41086a2215200441086a2900003703002003200a3703482004102f200c2003290348370000200c41086a2015290300370000200341a8016a41086a2002290300370300200341a8016a41106a2014290300370300200341a8016a41186a2005290300370300200320032903d0013703a80120034188016a200341a8016a412010aa020240024020032802880122040d00410021020c010b200329028c01220a422088a72102200aa7450d002004102f0b200341dd016a20034180046a41086a2204290300370000200341e5016a20034180046a41106a2205290300370000200341ed016a20034180046a41186a220c290300370000200341fc016a41002002201220106a6b221420081b20126a360200200341f8016a2014410020081b20106a2208360200200341063a00d401200341073a00d00120032003290380043700d50141c8e1ca004100200341d0016a108c01200341ec016a2012360200200341d0016a41186a2009360200200341d0016a41106a2010360200200341dc016a200b360200200320113602f0012003200f3602e401200320073602d801200320063602d001200320133602d401200341a8016a41186a200c290300370300200341a8016a41106a2005290300370300200341a8016a41086a200429030037030020032003290380043703a801200820134f2002200341d0016a200341a8016a10c705200041043a00000c090b1036000b20004183163b0100200041086a4109360200200041046a41d1d5c700360200200041026a41003a00000c080b20004183163b0100200041086a4111360200200041046a41c0d5c700360200200041026a41013a00000c070b200041023a00000c050b419cc3ca002006200f103b000b1038000b419cc3ca0020042011103b000b410d2102419ad5c7002106410421040b20004183163b0100200041086a2002360200200041046a2006360200200041026a20043a00000240200c450d002009102f0b200b450d002010102f0b41012105410121040c030b2007108e012007102f410021060b41012105410121040c020b2007108e012007102f41002104410121050b410121060b024020012d0000417f6a220241024b0d0002400240024020020e03000102000b2005450d02200141286a280200450d02200141246a280200102f0c020b2004450d01200141046a2802002202108e012002102f0c010b2006450d00200141086a2802002202108e012002102f0b200341a0046a24000b8e6906097f017e017f017e0c7f027e230041a0046b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e06000102030405000b200341e4016a4101360200200342013702d401200341b4d8c9003602d001200341043602ac01200341fcdbc9003602a8012003200341a8016a3602e001200341d0016a41e8d8c9001043000b2001412c6a2802002104200141286a2802002105200141246a280200210620012d0001210720034188016a41186a22082001411a6a29000037030020034188016a41106a2209200141126a29000037030020034188016a41086a220a2001410a6a2900003703002003200141026a290000370388010240024020022d000120022d0000410047720d0020062004108701200341d0016a41186a4200370300200341d0016a41106a220b4200370300200341d0016a41086a22024200370300200342003703d00141dfcbc700ad4280808080b00284220c1001220d290000210e2002200d41086a2900003703002003200e3703d001200d102f41ebdec700ad4280808080f000841001220d290000210e200341c8006a41086a220f200d41086a2900003703002003200e370348200d102f200b2003290348220e370300200341a8016a41086a2002290300370300200341a8016a41106a200e370300200341a8016a41186a200f290300370300200320032903d0013703a801200341d0016a200341a8016a412010aa022006200420032802d0012202410120021b220d20032902d401420020021b220e422088a7108a0320034180046a41186a200829030037030020034180046a41106a200929030037030020034180046a41086a200a29030037030020032003290388013703800402400240200741ff01710d00200341a8016a41186a4200370300200341a8016a41106a22074200370300200341a8016a41086a22024200370300200342003703a801200c10012204290000210c200341e8006a41086a2208200441086a2900003703002003200c3703682004102f20022008290300370300200320032903683703a80141fbd4c700ad4280808080d0008410012204290000210c200341f8006a41086a2208200441086a2900003703002003200c3703782004102f20072003290378220c370300200341286a41086a2002290300370300200341286a41106a200c370300200341286a41186a2008290300370300200320032903a801370328200341286aad428080808080048410050c010b200341a8016a41186a220820034180046a41186a290300370300200341a8016a41106a220920034180046a41106a290300370300200341a8016a41086a220a20034180046a41086a29030037030020032003290380043703a801200341c8006a41186a4200370300200341c8006a41106a220b4200370300200341c8006a41086a2204420037030020034200370348200c10012207290000210c200341286a41086a2202200741086a2900003703002003200c3703282007102f200420022903003703002003200329032837034841fbd4c700ad4280808080d0008410012207290000210c2002200741086a2900003703002003200c3703282007102f200b2003290328220c370300200341d0016a41086a2004290300370300200341d0016a41106a200c370300200341d0016a41186a2002290300370300200320032903483703d0014120102d2202450d07200220032903a801370000200241186a2008290300370000200241106a2009290300370000200241086a200a290300370000200341d0016aad42808080808004842002ad428080808080048410042002102f0b0240200ea7450d00200d102f0b02402005450d002006102f0b200041043a00000c010b200041023a00002005450d002006102f0b41012105410021040c110b200141046a280200210720032002411a6a2901003703c0012003200241026a2901003703a80120032002410a6a2901003703b0012003200241126a2901003703b8010240024020022d00014101470d0020022d000041ff01710d0020034188016a41186a200341a8016a41186a220529030037030020034188016a41106a200341a8016a41106a220429030037030020034188016a41086a200341a8016a41086a2208290300370300200320032903a80137038801200341d0016a41186a4200370300200341d0016a41106a22094200370300200341d0016a41086a22024200370300200342003703d00141dfcbc700ad4280808080b0028410012206290000210c2002200641086a2900003703002003200c3703d0012006102f41ebdec700ad4280808080f0008410012206290000210c200341c8006a41086a220a200641086a2900003703002003200c3703482006102f20092003290348220c370300200820022903003703002004200c3703002005200a290300370300200320032903d0013703a801200341d0016a200341a8016a412010aa0220032902d401420020032802d00122021b220c422088a741057421062002410120021b2208210202400340024020060d00410021040c020b4101210420034188016a2002460d01200641606a2106200220034188016a412010ea062105200241206a210220050d000b0b0240200ca7450d002008102f0b2004450d0141002105200341003602d801200342013703d0012007200341d0016a10910120032802d401210620034180046a41186a220820033502d80142208620032802d0012204ad841003220241186a29000037030020034180046a41106a2209200241106a29000037030020034180046a41086a220a200241086a29000037030020032002290000370380042002102f02402006450d002004102f0b200341d0016a200741b00210e8061a200341a8016a410d6a20034188016a41086a290300370000200341a8016a41156a20034188016a41106a290300370000200341a8016a411d6a20034188016a41186a29030037000041012104200341013a00ac0120032003290388013700ad01200341023a00a801200341c8006a200341d0016a200341a8016a108b0120032d00482102200341d0016a410d6a200a290300370000200341d0016a41156a2009290300370000200341d0016a411d6a2008290300370000200341f5016a20024104463a0000200341053a00d401200341083a00d00120032003290380043700d50141c8e1ca004100200341d0016a108c01200041043a00002007102f0c120b200041023a00000c100b20004183183b0100200041086a4109360200200041046a41d1d5c700360200200041026a41003a00000c0f0b200141086a2802002107200141046a28020021102002411a6a290100210c200241196a2d00002105200241186a2d00002104200241166a2f01002108200241156a2d00002109200241146a2d0000210a200241126a2f0100210d200241116a2d0000210b200241106a2d0000210f2002410e6a2f010021112002410d6a2d000021122002410c6a2d000021132002410a6a2f01002114200241096a2d00002115200241086a2d00002116200241066a2f01002117200241056a2d00002118200241046a2d00002119200241026a2f0100211a41012106024020022d00000d0020022d000141014721060b2003200c370340200320053a003f200320043a003e200320083b013c200320093a003b2003200a3a003a2003200d3b01382003200b3a00372003200f3a0036200320113b0134200320123a0033200320133a0032200320143b0130200320153a002f200320163a002e200320173b012c200320183a002b200320193a002a2003201a3b01280240024002400240024020060d0020034188016a41186a200341286a41186a29030037030020034188016a41106a200341286a41106a29030037030020034188016a41086a200341286a41086a2903003703002003200329032837038801200341d0016a41186a4200370300200341d0016a41106a22084200370300200341d0016a41086a22024200370300200342003703d00141dfcbc700ad4280808080b0028410012206290000210c2002200641086a2900003703002003200c3703d0012006102f41ebdec700ad4280808080f0008410012206290000210c200341c8006a41086a2205200641086a2900003703002003200c3703482006102f20082003290348220c370300200341a8016a41086a2002290300370300200341a8016a41106a200c370300200341a8016a41186a2005290300370300200320032903d0013703a801200341d0016a200341a8016a412010aa0220032902d401420020032802d00122021b220c422088a741057421062002410120021b2209210202400340024020060d00410021040c020b4101210420034188016a2002460d01200641606a2106200220034188016a412010ea062105200241206a210220050d000b0b0240200ca7450d002009102f0b2004450d08200341003602d801200342013703d0012007200341d0016a10910120032802d401210620034180046a41186a220520033502d80142208620032802d001220aad841003220241186a29000037030020034180046a41106a2204200241106a29000037030020034180046a41086a2209200241086a29000037030020032002290000370380042002102f02402006450d00200a102f0b200341d0016a41186a2005290300370300200341d0016a41106a2004290300370300200341d0016a41086a200929030037030020032003290380043703d00141dfcbc700ad4280808080b0028410012202290000210c200341e8006a41086a200241086a2900003703002003200c3703682002102f41f0abc800ad4280808080a0018410012202290000210c200341f8006a41086a200241086a2900003703002003200c3703782002102f4120102d2202450d07200220032903d001370000200241186a200341d0016a41186a290300370000200241106a200341d0016a41106a290300370000200241086a200341d0016a41086a2903003700002002ad428080808080048410032206290000210c200641086a290000210e200641106a290000211b200341c8006a41186a2205200641186a290000370300200341c8006a41106a2204201b370300200341c8006a41086a2209200e3703002003200c3703482006102f2002102f41c000102d2202450d0720022003290368370000200241086a200341e8006a41086a29030037000020022003290378370010200241186a200341f8006a41086a29030037000020022003290348370020200241286a2009290300370000200241306a2004290300370000200241386a2005290300370000200341186a200241c00041c8e1ca004100410010b501200328021821062002102f20064101460d0920104102490d034200210e200341c8006a41186a220b4200370300200341c8006a41106a22064200370300200341c8006a41086a220242003703002003420037034841dfcbc700ad4280808080b00284220c10012204290000211b200341e8006a41086a2205200441086a2900003703002003201b3703682004102f20022005290300370300200320032903683703484188a3ca00ad4280808080d00184221b10012209290000211c200341f8006a41086a2204200941086a2900003703002003201c3703782009102f20062003290378221c370300200341a8016a41086a22092002290300370300200341a8016a41106a220a201c370300200341a8016a41186a220d2004290300370300200320032903483703a801200341106a200341a8016a41201095012003280214211120032802102112200b4200370300200642003703002002420037030020034200370348200c1001220f290000211c2005200f41086a2900003703002003201c370368200f102f2002200529030037030020032003290368370348201b1001220f290000211c2004200f41086a2900003703002003201c370378200f102f20062003290378221c37030020092002290300370300200a201c370300200d2004290300370300200320032903483703a801200341086a200341a8016a41201095012003280208210f200328020c2113200b4200370300200642003703002002420037030020034200370348200c1001220b290000211c2005200b41086a2900003703002003201c370368200b102f2002200529030037030020032003290368370348201b10012205290000211b2004200541086a2900003703002003201b3703782005102f20062003290378221b37030020092002290300370300200a201b370300200d2004290300370300200320032903483703a801410121062003201341016a4101200f1b3602d001200341a8016aad4280808080800484200341d0016aad4280808080c000841004200341d0016a41186a220b4200370300200341d0016a41106a220f4200370300200341d0016a41086a22054200370300200342003703d001200c10012204290000210c2005200441086a2900003703002003200c3703d0012004102f41e2dec700ad428080808090018410012204290000210c2002200441086a2900003703002003200c3703482004102f20082003290348370000200841086a200229030037000020092005290300370300200a200f290300370300200d200b290300370300200320032903d0013703a801200341d0016a200341a8016a412010aa0220032802d00122040d0141002102410021050c020b200041023a00000c100b20032902d401220e422088a72105200ea72102200421060b200d20034180046a41186a290300370300200a20034180046a41106a290300370300200920034180046a41086a29030037030020032003290380043703a8010240024020052002460d002002210d0c010b02402002200ea7220d470d00200241016a22052002490d0b200241017422042005200420054b1b220541ffffff3f712005470d0b200541057422054100480d0b0240024020020d002005102d21060c010b200620024105742005103121060b2006450d06200e42808080807083210e2005410576210d0b200e422088a721050b200620054105746a220220032903a801370000200241186a200341a8016a41186a2209290300370000200241106a200341a8016a41106a2204290300370000200241086a200341a8016a41086a2202290300370000200942003703002004420037030020024200370300200342003703a80141dfcbc700ad4280808080b0028410012209290000210c200341e8006a41086a220a200941086a2900003703002003200c3703682009102f2002200a290300370300200320032903683703a80141e2dec700ad428080808090018410012209290000210c200341f8006a41086a220a200941086a2900003703002003200c3703782009102f20042003290378220c370300200341c8006a41086a2002290300370300200341c8006a41106a200c370300200341c8006a41186a200a290300370300200320032903a8013703480240024020060d00200341c8006aad428080808080048410050c010b200341203602d4012003200341c8006a3602d0012006200541016a200341d0016a108301200d450d002006102f0b200341d0016a200741b00210e8061a200341a8016a41186a220620034180046a41186a290300370300200341a8016a41106a220520034180046a41106a290300370300200341a8016a41086a220420034180046a41086a29030037030020032003290380043703a80141dfcbc700ad4280808080b0028410012202290000210c200341e8006a41086a200241086a2900003703002003200c3703682002102f41f0abc800ad4280808080a0018410012202290000210c200341f8006a41086a200241086a2900003703002003200c3703782002102f4120102d2202450d04200220032903a801370000200241186a2006290300370000200241106a2005290300370000200241086a20042903003700002002ad428080808080048410032206290000210c200641086a290000210e200641106a290000211b200341c8006a41186a200641186a290000370300200341c8006a41106a201b370300200341c8006a41086a200e3703002003200c3703482006102f2002102f41c000102d2202450d0420022003290368370000200241086a200341e8006a41086a29030037000020022003290378370010200241186a200341f8006a41086a29030037000020022003290348370020200241286a200341c8006a41086a2206290300370000200241306a200341c8006a41106a290300370000200241386a200341c8006a41186a290300370000200341003602b001200342013703a801200341d0016a200341a8016a10910120032802ac0121052002ad428080808080088420033502b00142208620032802a8012204ad84100402402005450d002004102f0b2002102f200341d0016a108e01200341d0016a41186a22044200370300200341d0016a41106a22094200370300200341d0016a41086a22024200370300200342003703d001418de6c300ad4280808080e0008410012205290000210c2002200541086a2900003703002003200c3703d0012005102f419ce6c300ad4280808080e0008410012205290000210c2006200541086a2900003703002003200c3703482005102f20082003290348370000200841086a2006290300370000200341a8016a41086a2002290300370300200341a8016a41106a2009290300370300200341a8016a41186a2004290300370300200320032903d0013703a8012003200341a8016a412010950120032802042102200328020021054120102d2206450d042006200329038801370000200641186a20034188016a41186a290300370000200641106a20034188016a41106a290300370000200641086a20034188016a41086a290300370000200341ec016a4100360200200341dc016a428180808010370200200320024180e5086a4180e50820051b3602f001200342013702e401200320063602d801200320103602d40120032011410020121b22043602d001200341a8016a41186a220520034180046a41186a290300370300200341a8016a41106a220820034180046a41106a290300370300200341a8016a41086a220920034180046a41086a29030037030020032003290380043703a80141dfcbc700ad4280808080b0028410012202290000210c200341e8006a41086a200241086a2900003703002003200c3703682002102f41f2dec700ad4280808080e0008410012202290000210c200341f8006a41086a200241086a2900003703002003200c3703782002102f4120102d2202450d04200220032903a801370000200241186a2005290300370000200241106a2008290300370000200241086a20092903003700002002ad428080808080048410032205290000210c200541086a290000210e200541106a290000211b200341c8006a41186a200541186a290000370300200341c8006a41106a201b370300200341c8006a41086a200e3703002003200c3703482005102f2002102f41c000102d2202450d0420022003290368370000200241086a200341e8006a41086a29030037000020022003290378370010200241186a200341f8006a41086a29030037000020022003290348370020200241286a200341c8006a41086a290300370000200241306a200341c8006a41106a290300370000200241386a200341c8006a41186a290300370000200341c0003602ac01200320023602a801200341d0016a200341a8016a10bd052002102f2006102f200341dd016a20034188016a41086a290300370000200341e5016a20034188016a41106a290300370000200341ed016a20034188016a41186a290300370000200341f5016a200329038004370000200341fd016a20034180046a41086a29030037000020034185026a20034180046a41106a2903003700002003418d026a20034180046a41186a2903003700002003419c026a201036020020034198026a2004360200200341003a00d401200341083a00d00120032003290388013700d501200341d0016a21020c010b200341d0016a41186a22054200370300200341d0016a41106a22044200370300200341d0016a41086a22024200370300200342003703d00141dfcbc700ad4280808080b0028410012206290000210c2002200641086a2900003703002003200c3703d0012006102f41ebdec700ad4280808080f0008410012206290000210c200341c8006a41086a2209200641086a2900003703002003200c3703482006102f20082003290348370000200841086a2009290300370000200341a8016a41086a2002290300370300200341a8016a41106a2004290300370300200341a8016a41186a2005290300370300200320032903d0013703a801200341286a200341a8016a412010aa0202400240200328022822060d00410021020c010b200329022c220c422088a72102200ca7450d002006102f0b200341d0016a200741b00210e8061a200341b4016a2002360200200341a8016a41086a4101360200200341003a00ac01200341023a00a801200341c8006a200341d0016a200341a8016a108b0120032d00482102200341dd016a20034180046a41086a290300370000200341e5016a20034190046a290300370000200341ed016a20034198046a290300370000200341043a00d401200341f5016a20024104463a0000200341083a00d00120032003290380043700d501200341d0016a21020b4100210641c8e1ca0041002002108c01200041043a00002007102f0c0d0b200141216a2d00002110200141246a280200211a20034188016a41186a200141196a29000037030020034188016a41106a200141116a29000037030020034188016a41086a200141096a29000037030020032001290001370388012002411a6a290100210c200241196a2d00002105200241186a2d00002104200241166a2f01002107200241156a2d00002108200241146a2d00002109200241126a2f0100210a200241116a2d0000210d200241106a2d0000210b2002410e6a2f0100210f2002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241086a2d00002115200241066a2f01002116200241056a2d00002117200241046a2d00002118200241026a2f0100211941012106024020022d00000d0020022d000141014721060b2003200c3701e801200320053a00e701200320043a00e601200320073b01e401200320083a00e301200320093a00e2012003200a3b01e0012003200d3a00df012003200b3a00de012003200f3b01dc01200320113a00db01200320123a00da01200320133b01d801200320143a00d701200320153a00d601200320163b01d401200320173a00d301200320183a00d201200320193b01d00120060d0420034180046a41186a200341d0016a41186a220629010037030020034180046a41106a200341d0016a41106a220729010037030020034180046a41086a200341d0016a41086a2202290100370300200320032901d00137038004200642003703002007420037030020024200370300200342003703d00141dfcbc700ad4280808080b0028410012206290000210c2002200641086a2900003703002003200c3703d0012006102f41ebdec700ad4280808080f0008410012206290000210c200341c8006a41086a2205200641086a2900003703002003200c3703482006102f20072003290348220c370300200341a8016a41086a2002290300370300200341a8016a41106a200c370300200341a8016a41186a2005290300370300200320032903d0013703a801200341d0016a200341a8016a412010aa0220032902d401420020032802d00122021b220c422088a741057421062002410120021b2208210202400340024020060d00410021040c020b4101210420034180046a2002460d01200641606a2106200220034180046a412010ea062105200241206a210220050d000b0b0240200ca7450d002008102f0b024002402004450d00200341d0016a20034188016a10c405024020032802d8012209450d00200341e8016a280200210a200341e4016a280200210f20032802dc01210d20032802d001201a460d02410a210241a7d5c7002106410321050c0c0b20004183183b0100200041086a410f360200200041046a41b1d5c700360200200041026a41023a00000c0c0b20004183183b0100200041086a4109360200200041046a41d1d5c700360200200041026a41003a00000c0b0b200341f0016a2802002114200341ec016a280200210b20032802d40121134100210641002105410021120240200341e0016a2802002211450d002011410574210441002105200921020240034020034180046a2002460d012005200220034180046a412010ea0622084100476a21052008450d01200241206a2102200441606a22040d000b410021120c010b410121120b410021020240200b450d00200b410574210441002106200f21020240034020034180046a2002460d012006200220034180046a412010ea0622084100476a21062008450d01200241206a2102200441606a22040d000b410021020c010b410121020b024002400240201041ff01710d002002450d010c0b0b20120d0a200341286a41186a220820034180046a41186a290300370300200341286a41106a221220034180046a41106a290300370300200341286a41086a221520034180046a41086a2903003703002003200329038004370328024002402011200d460d00200d21042011210d0c010b200d41016a2205200d490d09200d41017422042005200420054b1b220541ffffff3f712005470d09200541057422054100480d0902400240200d0d002005102d21090c010b2009200d4105742005103121090b2009450d04200541057621040b2009200d4105746a22052003290328370000200541186a2008290300370000200541106a2012290300370000200541086a2015290300370000201141016a21112002450d01200b20064d0d07200f200b417f6a220b4105746a2202290000210c2002290008210e2002290010211b200f20064105746a220641186a200241186a2900003700002006201b3700102006200e3700082006200c3700000c010b200341c8006a41186a220620034180046a41186a290300370300200341c8006a41106a220420034180046a41106a290300370300200341c8006a41086a220820034180046a41086a290300370300200320032903800437034802400240200b200a460d00200a2115200b210a0c010b200a41016a2202200a490d08200a41017422152002201520024b1b220241ffffff3f712002470d08200241057422024100480d0802400240200a0d002002102d210f0c010b200f200a41057420021031210f0b200f450d03200241057621150b200f200a4105746a22022003290348370000200241186a2006290300370000200241106a2004290300370000200241086a2008290300370000200b41016a210b02402012450d00201120054d0d0920092011417f6a22114105746a2202290000210c2002290008210e2002290010211b200920054105746a220641186a200241186a2900003700002006201b3700102006200e3700082006200c3700000b200d21042015210a0b200341f5016a200329038801370000200341e5016a20034180046a41106a290300370000200341ed016a20034180046a41186a29030037000020034185026a20034188016a41106a2903003700002003418d026a20034188016a41186a290300370000200341083a00d001200341dd016a20034180046a41086a290300370000200341fd016a20034188016a41086a290300370000200341013a00d40120032003290380043700d5012003419c026a200b36020020034198026a201136020020034195026a20103a00004100210241c8e1ca004100200341d0016a108c01200341d0016a41186a22084200370300200341d0016a41106a220d4200370300200341d0016a41086a22064200370300200342003703d00141dfcbc700ad4280808080b0028410012205290000210c2006200541086a2900003703002003200c3703d0012005102f41ebdec700ad4280808080f0008410012205290000210c200341c8006a41086a2212200541086a2900003703002003200c3703482005102f20072003290348370000200741086a2012290300370000200341a8016a41086a2006290300370300200341a8016a41106a200d290300370300200341a8016a41186a2008290300370300200320032903d0013703a801200341286a200341a8016a412010aa02024020032802282206450d00200329022c220c422088a72102200ca7450d002006102f0b02400240201120134f22060d0041002002200b6b2205200520024b1b2013490d00200341ec016a200b360200200341d0016a41186a200a360200200341d0016a41106a2011360200200341dc016a2004360200200320143602f0012003200f3602e401200320093602d801200320133602d4012003201a3602d00141dfcbc700ad4280808080b0028410012202290000210c200341e8006a41086a200241086a2900003703002003200c3703682002102f41f2dec700ad4280808080e0008410012202290000210c200341f8006a41086a200241086a2900003703002003200c3703782002102f4120102d2202450d032002200329038801370000200241186a20034188016a41186a290300370000200241106a20034188016a41106a290300370000200241086a20034188016a41086a2903003700002002ad428080808080048410032206290000210c200641086a290000210e200641106a290000211b200341a8016a41186a200641186a290000370300200341a8016a41106a201b370300200341a8016a41086a200e3703002003200c3703a8012006102f2002102f41c000102d2202450d0320022003290368370000200241086a200341e8006a41086a29030037000020022003290378370010200241186a200341f8006a41086a290300370000200220032903a801370020200241286a200341a8016a41086a290300370000200241306a200341b8016a290300370000200241386a200341a8016a41186a290300370000200341c0003602ac01200320023602a801200341d0016a200341a8016a10bd052002102f02402004450d002009102f0b200a450d01200f102f0c010b200341ec016a200b360200200341d0016a41186a200a360200200341d0016a41106a2011360200200341dc016a2004360200200320143602f0012003200f3602e401200320093602d8012003201a3602d001200320133602d401200341a8016a41186a20034188016a41186a290300370300200341a8016a41106a20034188016a41106a290300370300200341a8016a41086a20034188016a41086a29030037030020032003290388013703a80120062002200341d0016a200341a8016a10c5050b200041043a00000c0a0b200141246a280200210620034198046a200141196a29000037030020034190046a200141116a29000037030020034188046a200141096a2900003703002003200129000137038004024002400240024020022d00000d0020022d00014101470d00200341d0016a20034180046a10c405024020032802d8012207450d00200341d0016a41186a22022802002109200341e4016a280200210b20032802dc01210a20032802d0012006460d02410a210241a7d5c7002106410321050c030b20004183183b0100200041086a410f360200200041046a41b1d5c700360200200041026a41023a00000c0d0b200041023a00000c0c0b200341d0016a41206a2802002111200341ec016a2802002112200341d0016a41106a220d280200210f20032802d401211320024200370300200d420037030041082102200341d0016a41086a22054200370300200342003703d001418de6c300ad4280808080e0008410012204290000210c2005200441086a2900003703002003200c3703d0012004102f419ce6c300ad4280808080e0008410012204290000210c200341c8006a41086a2208200441086a2900003703002003200c3703482004102f200d2003290348220c370300200341a8016a41086a2005290300370300200341a8016a41106a200c370300200341a8016a41186a2008290300370300200320032903d0013703a801200341206a200341a8016a41201095012003280224410020032802201b20114f0d014180d5c7002106410621050b20004183183b0100200041086a2002360200200041046a2006360200200041026a20053a00000240200a450d002007102f0b2009450d0a200b102f0c0a0b200341a8016a41186a22084200370300200341a8016a41106a22054200370300200341a8016a41086a22024200370300200342003703a80141dfcbc700ad4280808080b0028410012204290000210c200341e8006a41086a2214200441086a2900003703002003200c3703682004102f20022014290300370300200320032903683703a80141fbd4c700ad4280808080d0008410012204290000210c200341f8006a41086a2214200441086a2900003703002003200c3703782004102f20052003290378220c370300200341c8006a41086a2002290300370300200341c8006a41106a200c370300200341c8006a41186a2014290300370300200320032903a801370348200341d0016a200341c8006a412010ad0220032d00d00121042008200341e9016a2900003703002005200341e1016a2900003703002002200341d9016a290000370300200320032900d1013703a8010240024020044101460d00410021080c010b200341286a41186a2008290300220c370300200341286a41106a2005290300220e370300200341286a41086a2002290300221b370300200320032903a801221c370328200341d0016a41186a200c370300200341d0016a41106a200e370300200341d0016a41086a201b3703002003201c3703d001200f4105742105200721020340024020050d00410021080c020b41012108200341d0016a2002460d01200541606a21052002200341d0016a412010ea062104200241206a210220040d000b0b200341d0016a41186a22044200370300200341d0016a41106a22144200370300200341d0016a41086a22024200370300200342003703d00141dfcbc700ad4280808080b0028410012205290000210c2002200541086a2900003703002003200c3703d0012005102f41ebdec700ad4280808080f0008410012205290000210c200341c8006a41086a2215200541086a2900003703002003200c3703482005102f200d2003290348370000200d41086a2015290300370000200341a8016a41086a2002290300370300200341a8016a41106a2014290300370300200341a8016a41186a2004290300370300200320032903d0013703a80120034188016a200341a8016a412010aa020240024020032802880122050d00410021020c010b200329028c01220c422088a72102200ca7450d002005102f0b200341e5016a20034180046a41106a2205290300370000200341ed016a20034180046a41186a2204290300370000200341083a00d001200341dd016a20034180046a41086a220d290300370000200341fc016a410020022012200f6a6b221420081b20126a360200200341f8016a2014410020081b200f6a2208360200200341063a00d40120032003290380043700d50141c8e1ca004100200341d0016a108c01200341ec016a2012360200200341d0016a41186a2009360200200341d0016a41106a200f360200200341dc016a200a360200200320113602f0012003200b3602e401200320073602d801200320063602d001200320133602d401200341a8016a41186a2004290300370300200341a8016a41106a2005290300370300200341a8016a41086a200d29030037030020032003290380043703a801200820134f2002200341d0016a200341a8016a10c505200041043a00000c090b1036000b20004183183b0100200041086a4109360200200041046a41d1d5c700360200200041026a41003a00000c080b20004183183b0100200041086a4111360200200041046a41c0d5c700360200200041026a41013a00000c070b200041023a00000c050b419cc3ca002006200b103b000b1038000b419cc3ca0020052011103b000b410d2102419ad5c7002106410421050b20004183183b0100200041086a2002360200200041046a2006360200200041026a20053a00000240200d450d002009102f0b200a450d00200f102f0b41012104410121050c030b2007108e012007102f410021060b41012104410121050c020b2007108e012007102f41002105410121040b410121060b024020012d0000417f6a220241024b0d0002400240024020020e03000102000b2004450d02200141286a280200450d02200141246a280200102f0c020b2005450d01200141046a2802002202108e012002102f0c010b2006450d00200141086a2802002202108e012002102f0b200341a0046a24000bef7405037f027e127f037e047f23004190046b220324000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802000e0700010203040506000b200341e4016a4101360200200342013702d401200341b4d8c9003602d00120034104360244200341fcdbc9003602402003200341c0006a3602e001200341d0016a41e8d8c9001043000b200141086a2802002104200128020421050240024020022d00000d0020022d00014101470d00200141186a2903002106200141106a29030021072001410c6a2802002108200241196a2d00002101200241186a2d00002109200241166a2f0100210a200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241086a2d00002115200241066a2f01002116200241056a2d00002117200241046a2d00002118200241026a2f0100211920032002411a6a290100370330200320013a002f200320093a002e2003200a3b012c2003200b3a002b2003200c3a002a2003200d3b01282003200e3a00272003200f3a0026200320103b0124200320113a0023200320123a0022200320133b0120200320143a001f200320153a001e200320163b011c200320173a001b200320183a001a200320193b011820034190016a41186a420037030020034190016a41106a2201420037030020034190016a41086a22024200370300200342003703900141bd98ca00ad428080808080028410012209290000211a200341c0006a41086a220a200941086a2900003703002003201a3703402009102f2002200a2903003703002003200329034037039001418c91c700ad4280808080a0018410012209290000211a200341d0016a41086a220b200941086a2900003703002003201a3703d0012009102f200120032903d001221a370300200341b0016a41086a2002290300370300200341b0016a41106a201a370300200341b0016a41186a200b29030037030020032003290390013703b001200341c0006a200341b0016aad4280808080800484221a10021073024002400240024020032802402202450d00200328024421092003200a2802003602d401200320023602d001200341106a200341d0016a10e6012003280210450d014100210d0c020b200342003702d401200341013602d001200341d0016a10f103210d0c020b2003280214210d0b2009450d002002102f0b20034190016a41186a220b420037030020034190016a41106a220c420037030020034190016a41086a22024200370300200342003703900141bd98ca00ad428080808080028410012209290000211b200341c0006a41086a220a200941086a2900003703002003201b3703402009102f2002200a290300370300200320032903403703900141ebdec700ad4280808080f0008410012209290000211b200341d0016a41086a220a200941086a2900003703002003201b3703d0012009102f200120032903d001370000200141086a200a290300370000200341b0016a41086a2002290300370300200341b0016a41106a200c290300370300200341b0016a41186a200b29030037030020032003290390013703b001200341d0016a201a100210734100210241002101024020032802d0012209450d0020032802d401210b2003200a28020036024420032009360240200341086a200341c0006a10e601024002402003280208450d00410021010c010b200328020c21010b200b450d002009102f0b410c21092001200d6a22010d0141f388c70021010c170b200041023a00000c170b0240200820014d0d0041e088c7002101410221020c160b0240200841104d0d004114210941cc88c7002101410321020c160b024020080d004107210941ec88c7002101410121020c160b02402007428180e983b1de165441002006501b450d00410a210941c288c7002101410421020c160b0240200341186a10b3050d00200342003703b8032003428080e983b1de163703b0032003200341186a360280032003200341186a3602d8022003200341d8026a3602d801200320034180036a3602d4012003200341b0036a3602d001200341c0006a200341186a200341d0016a109401024020032802404101470d0020032d00444104460d01410f210941b388c7002101410521020c170b200341c0006a41086a2903004201520d00200341c0006a41106a290300211a20032802d802210120034188026a200341c0006a41186a29030037030020034180026a201a370300200341d0016a41086a41003a0000200341d9016a2001290000370000200341e1016a200141086a290000370000200341e9016a200141106a290000370000200341f1016a200141186a290000370000200341033a00d00141c8e1ca004100200341d0016a108c010b200341d0016a200341186a108d02200342f0d0c9abc6add9b1f400370338200341386a200341186a427f20032903d001221a20032903e0017c221b201b201a542201200341d0016a41086a2202290300221a200341d0016a41186a2903007c2001ad7c221b201a54201b201a511b22011b221a2007201a200754427f201b20011b221a200654201a2006511b22011b221b201a200620011b221a411e10b00141bd98ca00ad4280808080800284100122012900002106200341c0006a41086a200141086a290000370300200320063703402001102f41ce89c700ad4280808080f000841001220129000021062002200141086a290000370300200320063703d0012001102f4120102d2201450d0f20012003290318370000200141186a200341186a41186a290300370000200141106a200341186a41106a290300370000200141086a200341186a41086a2903003700002001ad4280808080800484100322022900002106200241086a2900002107200241106a290000211c20034190016a41186a200241186a29000037030020034190016a41106a2209201c37030020034190016a41086a200737030020032006370390012002102f2001102f41c000102d2201450d0f20012003290340370000200141086a200341c0006a41086a2202290300370000200120032903d001370010200141186a200341d0016a41086a220a2903003700002001200329039001370020200141286a20034190016a41086a220b290300370000200141306a2009290300370000200141386a20034190016a41186a22092903003700002003201a3703d8012003201b3703d0012001ad4280808080800884200341d0016aad428080808080028410042001102f41bd98ca00ad428080808080028410012201290000211a2002200141086a2900003703002003201a3703402001102f41ae85c700ad4280808080f0008410012201290000211a200a200141086a2900003703002003201a3703d0012001102f4120102d2201450d0f20012003290318370000200141186a200341186a41186a290300370000200141106a200341186a41106a290300370000200141086a200341186a41086a2903003700002001ad428080808080048410032202290000211a200241086a290000211b200241106a29000021062009200241186a29000037030020034190016a41106a22092006370300200b201b3703002003201a370390012002102f2001102f41c000102d220a450d0f200a2003290340370000200a41086a200341c0006a41086a290300370000200a20032903d001370010200a41186a200341d0016a41086a290300370000200a200329039001370020200a41286a20034190016a41086a2202290300370000200a41306a2009290300370000200a41386a20034190016a41186a290300370000200341c0006a200a41c0001095040240024020032d004c22014102460d00200341b0036a41086a200341d5006a290000370300200341b0036a41106a200341dd006a290000370300200341b0036a41186a200341e5006a290000370300200341b0016a41086a200341f6006a290100370300200341b0016a41106a200341fe006a290100370300200341b0016a41186a20034186016a2901003703002003200341cd006a2900003703b0032003200341ee006a2901003703b001200341ed006a2d000021022003280244450d012003280240102f0c010b2003200341186a3602d40241bd98ca00ad428080808080028410012201290000211a2002200141086a2900003703002003201a370390012001102f41a185c700ad4280808080d0018410012201290000211a200341b0016a41086a2209200141086a2900003703002003201a3703b0012001102f200341b0036a41086a2002290300370300200341b0036a41186a200929030037030020032003290390013703b003200320032903b0013703c003200341d0016a200341b0036a108801200341d8026a20032802d001220120032802d80110ad02024020032802d401450d002001102f0b200341c0036a21100240024020032d00d8020d0041bd98ca00ad428080808080028410012201290000211a20034190016a41086a2202200141086a2900003703002003201a370390012001102f41a185c700ad4280808080d0018410012201290000211a200341b0016a41086a2209200141086a2900003703002003201a3703b0012001102f200341b0036a41086a2002290300370300201020032903b001370000201041086a200929030037000020032003290390013703b003200341d0016a200341b0036a10880120032802d001210220033502d801211a4120102d2201450d1220012003290318370000200141186a200341186a41186a290300370000200141106a200341186a41106a290300370000200141086a200341186a41086a290300370000201a4220862002ad842001ad428080808080048410042001102f024020032802d401450d002002102f0b410021020c010b20034198036a200341f1026a29000037030020034180036a41106a200341e9026a29000037030020034180036a41086a200341e1026a290000370300200320032900d90237038003200341a0036a20034180036a109404200341d0016a20032802a003221120032802a8032212109504024020032d00dc014102470d0020034100360298012003420137039001200341b0016a41146a4129360200200341b0016a410c6a410b360200200341103602fc03200341bd98ca003602f8032003410b3602b4012003410736028404200341ae85c700360280042003200341a0036a3602c001200320034180046a3602b8012003200341f8036a3602b001200320034190016a36028c04200341b0036a41146a4103360200200342033702b403200341cc90c4003602b0032003200341b0016a3602c0032003418c046a41d8dbc100200341b0036a103c1a2003350298014220862003350290018410080240200328029401450d00200328029001102f0b20032802d402210241bd98ca00ad428080808080028410012201290000211a20034190016a41086a2209200141086a2900003703002003201a370390012001102f41a185c700ad4280808080d0018410012201290000211a200341b0016a41086a220b200141086a2900003703002003201a3703b0012001102f200341b0036a41086a2009290300370300201020032903b001370000201041086a200b29030037000020032003290390013703b003200341b0016a200341b0036a10880120032802b001210920033502b801211a4120102d2201450d1220012002290000370000200141186a200241186a290000370000200141106a200241106a290000370000200141086a200241086a290000370000201a4220862009ad842001ad428080808080048410042001102f024020032802b401450d002009102f0b024020032802a403450d0020032802a003102f0b410021020c010b200341b0036a200341d0016a410c6a41c20010e8061a20032d00d1032102200341b0016a41086a200341d0016a41086a2802002201360200200341b0016a41106a200341d2036a410020024101461b360200200320032903d001221a3703b0012003200341d4026a3602bc012001410574220e4104722202417f4c0d082002102d2209450d11201aa72113200341003602980120032002360294012003200936029001200120034190016a106902402001450d00410020032802980122026b210b200328029001210d2003280294012109201321010340024002402009200b6a411f4d0d002009210c0c010b200241206a220c2002490d162009410174220f200c200f200c4b1b220c4100480d160240024020090d00200c102d210d0c010b200d2009200c1031210d0b200d450d140b200d20026a22092001290000370000200941186a200141186a290000370000200941106a200141106a290000370000200941086a200141086a290000370000200b41606a210b200241206a2102200c2109200141206a2101200e41606a220e0d000b2003200c3602940120032002360298012003200d360290010b200341b0016a410c6a20034190016a10cd0220032802940121012012ad4220862011ad842003350298014220862003280290012202ad84100402402001450d002002102f0b024020032802b401450d002013102f0b024020032802a403450d0020032802a003102f0b20032802d402210241bd98ca00ad428080808080028410012201290000211a20034190016a41086a2209200141086a2900003703002003201a370390012001102f41a185c700ad4280808080d0018410012201290000211a200341b0016a41086a220b200141086a2900003703002003201a3703b0012001102f200341b0036a41086a2009290300370300201020032903b001370000201041086a200b29030037000020032003290390013703b003200341d0016a200341b0036a10880120032802d001210920033502d801211a4120102d2201450d1120012002290000370000200141186a200241186a290000370000200141106a200241106a290000370000200141086a200241086a290000370000201a4220862009ad842001ad428080808080048410042001102f024020032802d401450d002009102f0b200341b0016a41086a20034180036a41086a290300370300200341b0016a41106a20034180036a41106a290300370300200341b0016a41186a20034180036a41186a29030037030020032003290380033703b001410121020b410021010b200341dd016a20032903b003370000200341fd016a20023a0000200341fe016a20032903b001370100200341e5016a200341b0036a41086a290300370000200341ed016a200341b0036a41106a290300370000200341f5016a200341b0036a41186a29030037000020034186026a200341b0016a41086a2903003701002003418e026a200341b0016a41106a29030037010020034196026a200341b0016a41186a290300370100200320013a00dc01200320083602d801200320043602d401200320053602d001200341c0003602442003200a360240200341d0016a200341c0006a10ef03200a102f02402004450d002005102f0b200041043a00000c170b20032002411a6a2901003703c8012003200241026a2901003703b00120032002410a6a2901003703b8012003200241126a2901003703c00120022d00014101470d0420022d000041ff01710d04200341d0016a41186a200341b0016a41186a290300370300200341d0016a41106a200341b0016a41106a290300370300200341d0016a41086a200341b0016a41086a290300370300200320032903b0013703d0010240200341d0016a10b305450d00200341d0016a410110b405200041043a00000c140b200041831a3b0100200041086a410b360200200041046a41a888c700360200200041026a41063a00000c130b200341d0036a200141246a280200360200200341b0036a41186a2001411c6a290200370300200341b0036a41106a200141146a290200370300200341b0036a41086a2001410c6a290200370300200320012902043703b00320022d00000d0520022d00014101470d05200241196a2d00002104200241186a2d00002105200241166a2f01002109200241156a2d0000210a200241146a2d00002108200241126a2f0100210b200241116a2d0000210c200241106a2d0000210d2002410e6a2f0100210e2002410d6a2d0000210f2002410c6a2d000021102002410a6a2f01002111200241096a2d00002112200241086a2d00002113200241066a2f01002114200241056a2d00002115200241046a2d00002116200241026a2f0100211720032002411a6a29010037039803200320043a009703200320053a009603200320093b0194032003200a3a009303200320083a0092032003200b3b0190032003200c3a008f032003200d3a008e032003200e3b018c032003200f3a008b03200320103a008a03200320113b018803200320123a008703200320133a008603200320143b018403200320153a008303200320163a008203200320173b018003200341d0016a41206a200341b0036a41206a280200360200200341d0016a41186a200341b0036a41186a290300370300200341d0016a41106a200341b0036a41106a290300370300200341d0016a41086a200341b0036a41086a290300370300200320032903b0033703d001200341c0006a200341d0016a10bb0120034190016a41086a2202200341c9006a29000037030020034190016a41106a2204200341d1006a29000037030020034190016a41186a2205200341d9006a290000370300200320032900413703900120032d00404101460d06200341d8026a41186a2005290300370300200341d8026a41106a2004290300370300200341d8026a41086a200229030037030020032003290390013703d80220034180036a200341d8026a412010ea06450d070240024020034180036a10b305450d0002400240200341d8026a10b305450d0041bd98ca00ad428080808080028410012202290000211a200341c0006a41086a200241086a2900003703002003201a3703402002102f41ae85c700ad4280808080f0008410012202290000211a200341d0016a41086a200241086a2900003703002003201a3703d0012002102f4120102d2202450d11200220032903d802370000200241186a200341d8026a41186a290300370000200241106a200341d8026a41106a290300370000200241086a200341d8026a41086a2903003700002002ad428080808080048410032204290000211a200441086a290000211b200441106a2900002106200341b0016a41186a2205200441186a290000370300200341b0016a41106a22092006370300200341b0016a41086a201b3703002003201a3703b0012004102f2002102f41c000102d2202450d1120022003290340370000200241086a200341c0006a41086a220e290300370000200220032903d001370010200241186a200341d0016a41086a220b290300370000200220032903b001370020200241286a200341b0016a41086a220d290300370000200241306a2009290300370000200241386a2005290300370000200341d0016a200241c00010aa022002102f20032802d0012202410120021b220f20032902d401420020021b221b422088a74105746a2110200341d0016a41106a2108200f2105034020052010460d020240200510e1040d00200541206a2112200341d0016a41186a220c420037030020084200370300200b4200370300200342003703d00141bd98ca00ad4280808080800284220610012202290000211a200b200241086a2900003703002003201a3703d0012002102f419691c700ad428080808090018410012202290000211a200d200241086a2900003703002003201a3703b0012002102f200820032903b001370000200841086a2213200d290300370000200e200b290300370300200341c0006a41106a22142008290300370300200341c0006a41186a2215200c290300370300200320032903d001370340200341d0016a200341c0006a10e40420032902d401420020032802d00122021b221a422088a741306c2104410021092002410820021b22112102024003402004450d01024020052002460d0020022005412010ea06210a200941016a2109200441506a2104200241306a2102200a0d010b0b201aa7450d012011102f0c010b0240201aa7450d002011102f0b200c420037030020084200370300200b4200370300200342003703d001200610012202290000211a200b200241086a2900003703002003201a3703d0012002102f418c91c700ad4280808080a0018410012202290000211a200d200241086a2900003703002003201a3703b0012002102f200820032903b0013700002013200d290300370000200e200b290300370300201420082903003703002015200c290300370300200320032903d001370340200341d0016a200341c0006a412010aa0220032802d0012204410120041b210c4100210202400240024020032902d401420020041b221a422088a7220441014b0d0020040e020201020b034020022004410176220920026a220a200c200a4105746a2005412010ea0641004a1b2102200420096b220441014b0d000b0b200c20024105746a2005412010ea064521020b0240201aa7450d00200c102f0b201221052002450d010b0b201ba7450d00200f102f0b200342003703b8012003428080e983b1de163703b001200320034180036a36029001200341c0006a20034180036a200341b0016a20034190016a10bd01200341e0006a290300211a2003290358211b024020032903404201520d002003290348210620034188026a200341c0006a41106a29030037030020034180026a2006370300200341d0016a41086a41003a0000200341d9016a200329038003370000200341e1016a20034180036a41086a290300370000200341e9016a20034180036a41106a290300370000200341f1016a20034198036a290300370000200341033a00d00141c8e1ca004100200341d0016a108c010b201b201a109a014100210220034180036a21040c140b0240201ba7450d00200f102f0b200341d0016a200341d8026a20034180036a428080e983b1de164200410010bc01200341c0006a41086a2204200341dc016a280200360200200320032902d4013703404101210220032802d0014101460d01200341d8026a21040c130b200041831a3b0100200041086a410b360200200041046a41a888c700360200200041026a41063a00000c130b20002003290340370200200041086a20042802003602000c120b024020022d00000d0020022d00014101470d00200241196a2d00002104200241186a2d00002105200241166a2f01002109200241156a2d0000210a200241146a2d00002108200241126a2f0100210b200241116a2d0000210c200241106a2d0000210d2002410e6a2f0100210e2002410d6a2d0000210f2002410c6a2d000021102002410a6a2f01002111200241096a2d00002112200241086a2d00002113200241066a2f01002114200241056a2d00002115200241046a2d00002116200241026a2f0100211720032002411a6a2901003703c803200320043a00c703200320053a00c603200320093b01c4032003200a3a00c303200320083a00c2032003200b3b01c0032003200c3a00bf032003200d3a00be032003200e3b01bc032003200f3a00bb03200320103a00ba03200320113b01b803200320123a00b703200320133a00b603200320143b01b403200320153a00b303200320163a00b203200320173b01b003200341d0016a41186a4200370300200341d0016a41106a22084200370300200341d0016a41086a22024200370300200342003703d00141bd98ca00ad428080808080028410012204290000211a2002200441086a2900003703002003201a3703d0012004102f418c91c700ad4280808080a0018410012204290000211a200341b0016a41086a2205200441086a2900003703002003201a3703b0012004102f200820032903b001221a370300200341c0006a41086a2002290300370300200341c0006a41106a201a370300200341c0006a41186a2005290300370300200320032903d001370340200341d0016a200341c0006a412010aa0220032802d0012202410120021b210a4100210b024020032902d401420020021b221a422088a7220441014b0d00410021024100210c20040e020d0c0d0b41002102034020022004410176220520026a2209200a20094105746a200341b0036a412010ea0641004a1b2102200420056b220441014b0d000c0c0b0b200041023a00000c110b20022d00000d0620022d00014101470d06200241196a2d00002104200241186a2d00002105200241166a2f01002109200241156a2d0000210a200241146a2d00002108200241126a2f0100210b200241116a2d0000210c200241106a2d0000210d2002410e6a2f0100210e2002410d6a2d0000210f2002410c6a2d000021102002410a6a2f01002111200241096a2d00002112200241086a2d00002113200241066a2f01002114200241056a2d00002115200241046a2d00002116200241026a2f0100211720032002411a6a2901003703c803200320043a00c703200320053a00c603200320093b01c4032003200a3a00c303200320083a00c2032003200b3b01c0032003200c3a00bf032003200d3a00be032003200e3b01bc032003200f3a00bb03200320103a00ba03200320113b01b803200320123a00b703200320133a00b603200320143b01b403200320153a00b303200320163a00b203200320173b01b00320034180036a200341b0036a10b5050240024020032d008003450d00200341d0016a41186a4200370300200341d0016a41106a220a4200370300200341d0016a41086a22024200370300200342003703d00141bd98ca00ad428080808080028410012204290000211a2002200441086a2900003703002003201a3703d0012004102f419691c700ad428080808090018410012204290000211a200341b0016a41086a2205200441086a2900003703002003201a3703b0012004102f200a20032903b001221a370300200341c0006a41086a2002290300370300200341c0006a41106a201a370300200341c0006a41186a2005290300370300200320032903d001370340200341d0016a200341c0006a10e40420032902d401420020032802d00122021b221a422088a7220b41306c2104410021052002410820021b22082102024003402004450d03200341b0036a2002460d01200541016a2105200441506a21042002200341b0036a412010ea062109200241306a210220090d000b20094541016a41017120056a417f6a21050b2008200541306c6a2202200241306a2005417f73200b6a41306c10e9061a200342003703e00220034280809aa6eaafe3013703d8022003200341b0036a36028003200341c0006a200341b0036a200341d8026a20034180036a109601024020032903404201520d002003290348211b20034188026a200341c0006a41106a290300370300200341d0016a41306a201b370300200341d0016a41086a41003a0000200341d9016a20032903b003370000200341e1016a200341b0036a41086a290300370000200341e9016a200341b0036a41106a290300370000200341f1016a200341c8036a290300370000200341033a00d00141c8e1ca004100200341d0016a108c010b200341b0016a41186a4200370300200341b0016a41106a22054200370300200341b0016a41086a22024200370300200342003703b00141bd98ca00ad428080808080028410012204290000211b200341c0006a41086a2209200441086a2900003703002003201b3703402004102f20022009290300370300200320032903403703b001419691c700ad428080808090018410012204290000211b200341d0016a41086a2209200441086a2900003703002003201b3703d0012004102f200520032903d001221b37030020034190016a41086a200229030037030020034190016a41106a201b37030020034190016a41186a2009290300370300200320032903b00137039001200341203602d401200320034190016a3602d0012008200b417f6a200341d0016a10ab010240201aa7450d002008102f0b200041043a00000c120b200342003703e00220034280809aa6eaafe3013703d8022003200341b0036a3602b001200341c0006a200341b0036a200341d8026a200341b0016a109601024020032903404201520d002003290348211a20034188026a200341c0006a41106a29030037030020034180026a201a370300200341d0016a41086a41003a0000200341d9016a20032903b003370000200341e1016a200341b0036a41086a290300370000200341e9016a200341b0036a41106a290300370000200341f1016a200341c8036a290300370000200341033a00d00141c8e1ca004100200341d0016a108c010b200341dd016a200341b8036a290300370000200341e5016a200341c0036a290300370000200341ed016a200341c8036a290300370000200341033a00d401200341093a00d001200320032903b0033700d50141c8e1ca004100200341d0016a108c01200041043a00000c110b200341d0016a41186a22054200370300200341d0016a41106a22094200370300200341d0016a41086a22024200370300200342003703d00141bd98ca00ad428080808080028410012204290000211b2002200441086a2900003703002003201b3703d0012004102f418c91c700ad4280808080a0018410012204290000211b200341b0016a41086a220b200441086a2900003703002003201b3703b0012004102f200a20032903b001370000200a41086a200b290300370000200341c0006a41086a2002290300370300200341c0006a41106a2009290300370300200341c0006a41186a2005290300370300200320032903d001370340200341d0016a200341c0006a412010aa0220032802d0012202410120021b210a02400240024020032902d401420020021b221b422088a7220b41014b0d0041002102200b0e020201020b200b210441002102034020022004410176220520026a2209200a20094105746a200341b0036a412010ea0641004a1b2102200420056b220441014b0d000b0b200a20024105746a200341b0036a412010ea060d002002200b4f0d08200a20024105746a2204200441206a2002417f73200b6a41057410e9061a200342003703e00220034280809aa6eaafe3013703d8022003200341b0036a36028003200341c0006a200341b0036a200341d8026a20034180036a109601024020032903404201520d002003290348210620034188026a200341c0006a41106a29030037030020034180026a2006370300200341d0016a41086a41003a0000200341d9016a20032903b003370000200341e1016a200341b0036a41086a290300370000200341e9016a200341b0036a41106a290300370000200341f1016a200341c8036a290300370000200341033a00d00141c8e1ca004100200341d0016a108c010b200341b0016a41186a4200370300200341b0016a41106a22054200370300200341b0016a41086a22024200370300200342003703b00141bd98ca00ad4280808080800284100122042900002106200341c0006a41086a2209200441086a290000370300200320063703402004102f20022009290300370300200320032903403703b001418c91c700ad4280808080a00184100122042900002106200341d0016a41086a2209200441086a290000370300200320063703d0012004102f200520032903d001220637030020034190016a41086a200229030037030020034190016a41106a200637030020034190016a41186a2009290300370300200320032903b00137039001200341203602d401200320034190016a3602d001200a200b417f6a200341d0016a10aa010240201ba7450d00200a102f0b200041043a0000201aa7450d112008102f0c110b200041831a3b0100200041086a410d360200200041046a41cc87c700360200200041026a410c3a00000240201ba7450d00200a102f0b201aa7450d102008102f0c100b200341b0036a41206a2204200141246a280200360200200341b0036a41186a22052001411c6a290200370300200341b0036a41106a2209200141146a290200370300200341b0036a41086a220a2001410c6a290200370300200320012902043703b00320022d000120022d0000410047720d07200341d0016a41206a2004280200360200200341d0016a41186a2005290300370300200341d0016a41106a2009290300370300200341d0016a41086a200a290300370300200320032903b0033703d001200341c0006a200341d0016a10bb01200341b0016a41086a200341c9006a290000370300200341b0016a41106a200341d1006a290000370300200341b0016a41186a200341d9006a290000370300200320032900413703b001024020032d00404101460d00200341d8026a41186a200341b0016a41186a290300370300200341d8026a41106a200341b0016a41106a290300370300200341d8026a41086a200341b0016a41086a290300370300200320032903b0013703d802200341b0016a200341d8026a10b505024020032d00b0014101470d00200020032902b401370200200041086a200341bc016a2802003602000c110b20032d00b1012102200342003703880320034280809aa6eaafe301370380032003200341d8026a36029001200341c0006a200341d8026a20034180036a20034190016a10bd01200341e0006a290300211a2003290358211b024020032903404201520d002003290348210620034188026a200341c0006a41106a29030037030020034180026a2006370300200341d0016a41086a41003a0000200341d9016a20032903d802370000200341e1016a200341d8026a41086a290300370000200341e9016a200341d8026a41106a290300370000200341f1016a200341f0026a290300370000200341033a00d00141c8e1ca004100200341d0016a108c010b201b201a109a01200341dd016a200341e0026a290300370000200341e5016a200341e8026a290300370000200341ed016a200341f0026a290300370000200341023a00d401200341093a00d001200320032903d8023700d50141c8e1ca004100200341d0016a108c010240200241ff01710d0010b6040b200041043a00000c100b200041013a00000c0f0b200041023a00000c0e0b103d000b200041023a00000c0c0b200041013a00000c0b0b200041831a3b0100200041086a410a360200200041046a419e88c700360200200041026a41073a00000c0a0b200041023a00000c090b41b8e3c300411d41f8b4ca001039000b200041023a00000c070b0240200a20024105746a200341b0036a412010ea0622040d004101210b2002210c0c010b2004411f7620026a210c0b0240201aa7450d00200a102f0b0240200b450d004113210a418b88c7002102410821040c040b410c210a0240200341b0036a10e104450d0041ff87c7002102410921040c040b200341d0016a41186a22054200370300200341d0016a41106a22094200370300200341d0016a41086a22024200370300200342003703d00141bd98ca00ad428080808080028410012204290000211a2002200441086a2900003703002003201a3703d0012004102f419691c700ad428080808090018410012204290000211a200341b0016a41086a220b200441086a2900003703002003201a3703b0012004102f200820032903b001370000200841086a200b290300370000200341c0006a41086a2002290300370300200341c0006a41106a2009290300370300200341c0006a41186a2005290300370300200320032903d001370340200341d0016a200341c0006a10e40420032902d401420020032802d00122021b221a422088a741306c2104410021052002410820021b220b2102024003402004450d010240200341b0036a2002460d00200541016a2105200441506a21042002200341b0036a412010ea062109200241306a210220090d010b0b41f387c7002102410a2104201aa7450d04200b102f0c040b0240201aa7450d00200b102f0b200342003703e00220034280809aa6eaafe3013703d8022003200341b0036a3602b0012003200341b0036a36028003200320034180036a3602d8012003200341b0016a3602d4012003200341d8026a3602d001200341c0006a200341b0036a200341d0016a1094010240024020032802404101470d0020032d00444104460d01411a210a41d987c7002102410b21040c050b200341c0006a41086a2903004201520d00200341c0006a41106a290300211a200328028003210220034188026a200341c0006a41186a29030037030020034180026a201a370300200341d0016a41086a41003a0000200341d9016a2002290000370000200341e1016a200241086a290000370000200341e9016a200241106a290000370000200341f1016a200241186a290000370000200341033a00d00141c8e1ca004100200341d0016a108c010b20032903c803211b20032d00c703210920032d00c603210a20032f01c403210b20032d00c303210d20032d00c203210e20032f01c003210f20032d00bf03211020032d00be03211120032f01bc03211220032d00bb03211320032d00ba03211420032f01b803211520032d00b703211620032d00b603211720032f01b403211820032d00b303211920032d00b203211d20032f01b003211e4200211a200341d0016a41186a22054200370300200341d0016a41106a221f4200370300200341d0016a41086a22024200370300200342003703d00141bd98ca00ad42808080808002841001220429000021062002200441086a290000370300200320063703d0012004102f418c91c700ad4280808080a00184100122042900002106200341b0016a41086a2220200441086a290000370300200320063703b0012004102f200820032903b001370000200841086a2020290300370000200341c0006a41086a2002290300370300200341c0006a41106a201f290300370300200341c0006a41186a2005290300370300200320032903d001370340200341d0016a200341c0006a412010aa020240024020032802d00122040d004100210241012104410021050c010b20032902d401221a422088a72105201aa721020b2005200c490d01024020052002470d002002201aa7470d00200241016a22082002490d032002410174221f2008201f20084b1b220841ffffff3f712008470d03200841057422084100480d030240024020020d002008102d21040c010b200420024105742008103121040b2004450d012008410576ad211a0b2004200c4105746a220241206a20022005200c6b41057410e9061a2002201b370018200220093a00172002200a3a00162002200b3b00142002200d3a00132002200e3a00122002200f3b0010200220103a000f200220113a000e200220123b000c200220133a000b200220143a000a200220153b0008200220163a0007200220173a0006200220183b0004200220193a00032002201d3a00022002201e3b0000200341b0016a41186a4200370300200341b0016a41106a220a4200370300200341b0016a41086a22024200370300200342003703b00141bd98ca00ad428080808080028410012209290000211b200341c0006a41086a2208200941086a2900003703002003201b3703402009102f20022008290300370300200320032903403703b001418c91c700ad4280808080a0018410012209290000211b200341d0016a41086a2208200941086a2900003703002003201b3703d0012009102f200a20032903d001221b37030020034190016a41086a200229030037030020034190016a41106a201b37030020034190016a41186a2008290300370300200320032903b001370390010240024020040d0020034190016aad428080808080048410050c010b200341203602d401200320034190016a3602d0012004200541016a200341d0016a10aa01201aa7450d002004102f0b200041043a00000c050b1036000b419ae3c300411e41f8b4ca001039000b1038000b200041831a3b0100200041086a200a360200200041046a2002360200200041026a20043a00000c010b2004410010b405200341dd016a200341d8026a41086a290300370000200341e5016a200341d8026a41106a290300370000200341ed016a200341d8026a41186a290300370000200341f5016a200329038003370000200341fd016a20034180036a41086a29030037000020034185026a20034180036a41106a2903003700002003418d026a20034180036a41186a29030037000020034195026a20023a0000200341043a00d401200341093a00d001200320032903d8023700d50141c8e1ca004100200341d0016a108c01200041043a00000b20012802004101470d02200141086a280200450d022001280204102f0c020b200041831a3b0100200041086a2009360200200041046a2001360200200041026a20023a00000b2004450d002005102f0b20034190046a24000bb512080a7f027e047f017e047f027e027f057e23002204210520044180016b416071220424000240024002400240024002400240200141ffffff3f712001470d0020014105742206417f4c0d00024020060d00200020014105746a210741012108200121090c030b2006102d2208450d05200020014105746a21072006410576220920014f0d02200941017422062001200620014b1b220641ffffff3f712006470d01200641057422064100480d010240024020090d002006102d21080c010b200820094105742006103121080b2008450d05200641057621090c030b103d000b1038000b20010d00410021060c010b200720006b210a410021060340200820066a2207200020066a220b290000370000200741186a200b41186a290000370000200741106a200b41106a290000370000200741086a200b41086a290000370000200a200641206a2206470d000b200020014105746a20006b41606a41057641016a21060b20042006360208200420093602042004200836020020082006410041202006676b10e003200441206a41186a220a4200370300200441206a41106a220c4200370300200441206a41086a220d42003703002004420037032041dfcbc700ad4280808080b00284220e10012206290000210f200d200641086a2900003703002004200f3703202006102f41e2dec700ad428080808090018410012206290000210f200441c8006a41086a2200200641086a2900003703002004200f3703482006102f200c2004290348220f370300200441e0006a41086a2210200d290300370300200441e0006a41106a2211200f370300200441e0006a41186a2212200029030037030020042004290320370360200441206a200441e0006a412010aa0220042802202206410120061b21132004290224420020061b2214422088a72206450d0120064105742115200441e0006a410c722116200441206a410c6a2101200441206a4114722117200441206a4108722118201321070340200a200741186a290000370300200c200741106a290000370300200d200741086a29000037030020042007290000370320200e10012206290000210f200441106a41086a2208200641086a2900003703002004200f3703102006102f41f2dec700ad4280808080e0008410012206290000210f2000200641086a2900003703002004200f3703482006102f4120102d2206450d0120062004290320370000200641186a200a290300370000200641106a200c290300370000200641086a200d2903003700002006ad42808080808004841003220b290000210f200b41086a2900002119200b41106a290000211a2012200b41186a2900003703002011201a370300201020193703002004200f370360200b102f2006102f41c000102d2206450d01200620042903103700002006200429034837001020062004290360370020200641086a2008290300370000200641186a2000290300370000200641286a2010290300370000200641306a2011290300370000200641386a2012290300370000200441206a200610a1052000200141086a290200370300200441c8006a41106a2209200141106a280200360200200420012902003703482004280240211b02402004280228220b450d002004290320210f20162004290348370200201641086a2000290300370200201641106a20092802003602002004200f370360201b211c0b2004200b360268200441003602282004290378211a20042004290338221d3703782004290370211e20042004290330221f370370200429036021202004200429032022193703602004290368210f2004200429032822213703682021a7210b02400240200fa722090d002021210f201f211e201d211a0c010b200420203703202004200f3703282004201e3703302004201a37033820042009201ea74105746a360254200420093602502004200f422088a736024c2004200936024820042004360258200441106a200441c8006a10f803201841086a2008280200360200201820042903103702002004201e422088a72209201a422088a74105746a360254200420093602502004201aa736024c2004200936024820042004360258200441106a200441c8006a10f803201741086a2008280200360200201720042903103702002004290328210f200429032021192004290338211a2004290330211e0240200b450d00201da7210802402021422088a7450d00200b102f0b2008450d00201f422088a7102f0b200420193703602004200f3703682004201e3703702004201a370378200fa7210b201b211c0b2004200f3703282004201e370330200a201a370300200420193703202004201c360240200fa7210802400240200b0d002006ad428080808080088410050c010b200441c00036024c20042006360248200441206a200441c8006a10b7050b02402008450d00201aa7210b0240200f422088a7450d002008102f0b200b450d00201e422088a7102f0b200741206a21072006102f201541606a22150d000c020b0b1036000b02402014a7450d002013102f0b200441e0006a41186a220a4200370300200441e0006a41106a22074200370300200441e0006a41086a220642003703002004420037036041dfcbc700ad4280808080b00284220f100122002900002119200441106a41086a220b200041086a290000370300200420193703102000102f2006200b2903003703002004200429031037036041ebdec700ad4280808080f00084100122082900002119200441c8006a41086a2200200841086a290000370300200420193703482008102f200720042903482219370300200441206a41086a22012006290300370300200441206a41106a22092019370300200441206a41186a221c200029030037030020042004290360370320200441203602642004200441206a36026020022003200441e0006a10ad01200a4200370300200742003703002006420037030020044200370360200f10012208290000210f200b200841086a2900003703002004200f3703102008102f2006200b2903003703002004200429031037036041fbd4c700ad4280808080d000841001220b290000210f2000200b41086a2900003703002004200f370348200b102f20072004290348220f370300200120062903003703002009200f370300201c200029030037030020042004290360370320200441206aad4280808080800484100502402004280204450d002004280200102f0b200524000bec0502057f017e23004190016b2201240020002d00002102200141186a2203200041196a290000370300200141106a2204200041116a290000370300200141086a2205200041096a2900003703002001200029000137030002400240024020020d00200141f0006a41186a4200370300200141f0006a41106a22034200370300200141f0006a41086a220042003703002001420037037041dfcbc700ad4280808080b002841001220229000021062000200241086a290000370300200120063703702002102f41fbd4c700ad4280808080d00084100122022900002106200141206a41086a2204200241086a290000370300200120063703202002102f200320012903202206370300200141c0006a41086a2000290300370300200141c0006a41106a2006370300200141c0006a41186a200429030037030020012001290370370340200141c0006aad428080808080048410050c010b200141206a41186a2003290300370300200141206a41106a2004290300370300200141206a41086a200529030037030020012001290300370320200141f0006a41186a4200370300200141f0006a41106a22034200370300200141f0006a41086a220042003703002001420037037041dfcbc700ad4280808080b002841001220229000021062000200241086a290000370300200120063703702002102f41fbd4c700ad4280808080d00084100122022900002106200141e0006a41086a2204200241086a290000370300200120063703602002102f200320012903602206370300200141c0006a41086a2000290300370300200141c0006a41106a2006370300200141c0006a41186a2004290300370300200120012903703703404120102d2200450d0120002001290320370000200041186a200141206a41186a290300370000200041106a200141206a41106a290300370000200041086a200141206a41086a290300370000200141c0006aad42808080808004842000ad428080808080048410042000102f0b20014190016a24000f0b1036000b8d0901177f230041206b220424002002410020031b21052000410020011b2106200241206a200220031b2107200041206a200020011b2108200020014105746a2109200220034105746a210a4100210b4100210c4101210d4100210e4100210f4101211002400340200b4101742111200b41057421120240024003402011211320122114200b2115200c2116200d2117200721032005210202400340024020020d00410021052006450d020c040b02402006450d000240024020022006460d0020022006412010ea0622180d010b2003200341206a2003200a4622021b210741002008200820094622141b21064100200320021b21052015210b2016210c2017210d2008200841206a20141b21080c070b02402018417f4c0d00200221050c050b200441186a2218200241186a290000370300200441106a2219200241106a290000370300200441086a221a200241086a29000037030020042002290000370300024020152016470d00201541016a22022015490d0820132002201320024b1b220241ffffff3f712002470d08200241057422024100480d080240024020150d002002102d21170c010b201720142002103121170b2017450d06200241057621160b201720146a22022004290300370000200241186a2018290300370000200241106a2019290300370000200241086a201a290300370000410020032003200a4622181b2102201341026a2113201441206a2114201541016a21152003200341206a20181b21030c010b0b200441186a2203200541186a290000370300200441106a2215200541106a290000370300200441086a2206200541086a290000370300200420052900003703000240200b200c470d00200b41016a2202200b490d06200b41017422142002201420024b1b220241ffffff3f712002470d06200241057422024100480d0602400240200b0d002002102d210d0c010b200d200b41057420021031210d0b200d450d042002410576210c0b200d200b4105746a22022004290300370000200241186a2003290300370000200241106a2015290300370000200241086a200629030037000041002106410020072007200a4622021b2105201141026a2111201241206a2112200b41016a210b2007200741206a20021b21070c010b0b201720152000200110880302402016450d002017102f0b0240200f450d002010102f0b200441206a24000f0b200441186a2214200641186a290000370300200441106a2213200641106a290000370300200441086a2218200641086a290000370300200420062900003703000240200e200f470d00200e41016a2202200e490d03200e41017422062002200620024b1b220241ffffff3f712002470d03200241057422024100480d0302400240200e0d002002102d21100c010b2010200e4105742002103121100b2010450d012002410576210f0b2010200e4105746a22022004290300370000200241186a2014290300370000200241106a2013290300370000200241086a201829030037000041002008200820094622021b2106200e41016a210e2015210b2016210c2017210d2008200841206a20021b2108200321070c010b0b1036000b1038000be2a50107017f027e137f017e057f057e087f23004180096b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e09000102030405090a0f000b20034184076a4101360200200342013702f406200341b4d8c9003602f006200341043602b405200341fcdbc9003602b0052003200341b0056a36028007200341f0066a41e8d8c9001043000b200141306a2903002104200141286a2903002105200341d0056a200141246a280200360200200341b0056a41186a2001411c6a290200370300200341b0056a41106a200141146a290200370300200341b0056a41086a2001410c6a2902003703002003200141046a2902003703b00520022d00000d0420022d00014101470d04200241196a2d00002106200241186a2d00002107200241166a2f01002108200241156a2d00002109200241146a2d0000210a200241126a2f0100210b200241116a2d0000210c200241106a2d0000210d2002410e6a2f0100210e2002410d6a2d0000210f2002410c6a2d000021102002410a6a2f01002111200241096a2d00002112200241086a2d00002113200241066a2f01002114200241056a2d00002115200241046a2d00002116200241026a2f0100211720032002411a6a2901003703a003200320063a009f03200320073a009e03200320083b019c03200320093a009b032003200a3a009a032003200b3b0198032003200c3a0097032003200d3a0096032003200e3b0194032003200f3a009303200320103a009203200320113b019003200320123a008f03200320133a008e03200320143b018c03200320153a008b03200320163a008a03200320173b018803200341f0066a41206a200341b0056a41206a280200360200200341f0066a41186a200341b0056a41186a290300370300200341f0066a41106a200341b0056a41106a290300370300200341f0066a41086a200341b0056a41086a290300370300200320032903b0053703f00620034180086a200341f0066a10bb0120032d0080084101460d0c20034180086a41086a2d0000210c20034189086a2f0000210d2003418b086a2d0000210e2003418c086a2d0000210f2003418d086a2f000021102003418f086a2d0000211120034180086a41106a2d0000211220034191086a2f0000211320034193086a2d0000211420034194086a2d0000211520034195086a2f0000211620034197086a2d0000211720034180086a41186a2d0000211820034199086a290000211920032f008108211a20032d008308211b20032d008408211c20032f008508211d20032d008708211e200341286a2005200442c0843d420010ee06200341186a2003290328221f200341286a41086a290300222042c0fb42427f10ed06200341086a201f202042d08603420010ed062003200341086a41086a29030020032903082220200520032903187c221f42d086037e201f421480221f42c0fb427e7c42a0c21e56201fa76aad7c221f202054ad7c22204200201f428080e983b1de165620204200522020501b22021b22203703b0022003201f428080e983b1de1620021b22213703a802200320034188036a3602c006200320034188036a3602c8012003200341c8016a3602f8062003200341c0066a3602f4062003200341a8026a3602f00620034180086a20034188036a200341f0066a109401024002402003280280084101470d0020032d0084084104460d0120004183223b0100200041086a411c360200200041046a41d8c7c400360200200041026a41003a0000410121060c180b20034180086a41086a2903004201520d0020034180086a41106a290300211f20032802c8012102200341a8076a20034180086a41186a290300370300200341a0076a201f370300200341f0066a41086a41003a0000200341f9066a200229000037000020034181076a200241086a29000037000020034189076a200241106a29000037000020034191076a200241186a290000370000200341033a00f00641c8e1ca004100200341f0066a108c010b20034198046a41186a220a420037030020034198046a41106a2207420037030020034198046a41086a2202420037030020034200370398044180a3ca00ad4280808080800184221f100122062900002122200341e8036a41086a2208200641086a290000370300200320223703e8032006102f20022008290300370300200320032903e803370398044188a3ca00ad4280808080d001842222100122062900002123200341c0066a41086a2209200641086a290000370300200320233703c0062006102f200720032903c0062223370300200341c8046a41086a220b2002290300370300200341c8046a41106a22242023370300200341c8046a41186a2225200929030037030020032003290398043703c8042003200341c8046a41201095012003280204212620032802002127200a420037030020074200370300200242003703002003420037039804201f1001220629000021232008200641086a290000370300200320233703e8032006102f20022008290300370300200320032903e8033703980420221001220629000021222009200641086a290000370300200320223703c0062006102f200720032903c0062222370300200b2002290300370300202420223703002025200929030037030020032003290398043703c80420032026410020271b220b41016a3602f006200341c8046aad4280808080800484200341f0066aad4280808080c000841004200341f0066a41186a20034188036a41186a290300370300200341f0066a41106a20034188036a41106a290300370300200341f0066a41086a20034188036a41086a29030037030020032003290388033703f006201f10012206290000211f2008200641086a2900003703002003201f3703e8032006102f41e2dec700ad428080808090018410012206290000211f2009200641086a2900003703002003201f3703c0062006102f2003200b3602800820034180086aad4280808080c0008410032206290000211f200641086a2900002122200641106a2900002123200a200641186a29000037030020072023370300200220223703002003201f370398042006102f41c000102d2206450d0e200620032903e803370000200641086a2008290300370000200620032903c006370010200641186a20092903003700002006200329039804370020200641286a2002290300370000200641306a2007290300370000200641386a200a2903003700004120102d2202450d0e200220032903f006370000200241186a200341f0066a41186a290300370000200241106a200341f0066a41106a290300370000200241086a200341f0066a41086a2903003700002002412041c00010312202450d0e20022005370020200241286a2004370000200241c00041800110312202450d0e2002202137005020022019370048200220183a0047200220173a0046200220163b0044200220153a0043200220143a0042200220133b0040200220123a003f200220113a003e200220103b003c2002200f3a003b2002200e3a003a2002200d3b00382002200c3a00372002201e3a00362002201d3b00342002201c3a00332002201b3a00322002201a3b0030200241d8006a20203700002006ad42808080808008842002ad4280808080800c8410042002102f2006102f200341f8066a41003a00002003410c3a00f006200341f0066a410c6a200b36020041c8e1ca004100200341f0066a108c01200041043a0000410121060c160b41012106024020022d00004101470d00200241086a2802004102490d00200241046a28020041ff01710d00200141046a28020021074180a3ca00ad4280808080800184100122022900002105200341e8036a41086a2208200241086a290000370300200320053703e8032002102f41e2dec700ad4280808080900184100122022900002105200341c0066a41086a2209200241086a290000370300200320053703c0062002102f200320073602f006200341f0066aad4280808080c00084100322022900002105200241086a2900002104200241106a290000211f200341c8046a41186a220a200241186a290000370300200341c8046a41106a220b201f370300200341c8046a41086a220c2004370300200320053703c8042002102f41c000102d2202450d0e200220032903e803370000200241086a2008290300370000200220032903c006370010200241186a2009290300370000200220032903c804370020200241286a200c290300370000200241306a200b290300370000200241386a200a290300370000200341f0066a200210aa04024020032903f00642015222080d002002ad428080808080088410050b20034188036a200341f0066a41086a41e00010e8061a200341f0066a20034188036a41e00010e8061a024020080d00200341a8026a200341f0066a41e00010e8061a2002102f200341b0056a41066a200341a8026a41e00010e8061a20034180086a200341b0056a41e60010e8061a200341c8016a20034180086a41066a41e00010e8061a20032903d80121052003200341c8016a41186a290300220437038808200320053703800802400240200520048450450d004200211f420021200c010b2003200341c8016a41206a220236028803200341b0056a200220034180086a20034188036a10bd01200341b0056a41206a290300212020032903c805211f20032903b0054201520d0020032903b8052119200341a8076a200341b0056a41106a290300370300200341a0076a2019370300200341f0066a41086a41003a0000200341f9066a200229000037000020034181076a200241086a29000037000020034189076a200241106a29000037000020034191076a200241186a290000370000200341033a00f00641c8e1ca004100200341f0066a108c010b201f2020109a01200341f0066a41186a200437030020034180076a2005370300200341f8066a41033a00002003410c3a00f006200341f0066a410c6a200736020041c8e1ca004100200341f0066a108c01200041043a00000c170b2002102f200041086a4114360200200041046a41c4c7c40036020041012106200041026a41013a000020004183223b01000c160b200041023a00000c150b4101210620022d00004101470d09200241086a2802004104490d09200241046a28020041ff01710d09200141046a28020021094180a3ca00ad4280808080800184100122022900002105200341e8036a41086a2206200241086a290000370300200320053703e8032002102f41e2dec700ad4280808080900184100122022900002105200341c0066a41086a2207200241086a290000370300200320053703c0062002102f200320093602f006200341f0066aad4280808080c00084100322022900002105200241086a2900002104200241106a290000211f20034198046a41186a2208200241186a29000037030020034198046a41106a220a201f37030020034198046a41086a220b200437030020032005370398042002102f41c000102d2202450d0c200220032903e803370000200241086a2006290300370000200220032903c006370010200241186a20072903003700002002200329039804370020200241286a200b290300370000200241306a200a290300370000200241386a2008290300370000200341386a200241c00041c8e1ca004100410010b501200328023821072002102f41012106024020074101470d0020034198046a41186a220d420037030020034198046a41106a2202420037030020034198046a41086a2207420037030020034200370398044180a3ca00ad4280808080800184221f100122082900002105200341e8036a41086a220a200841086a290000370300200320053703e8032008102f2007200a290300370300200320032903e803370398044195a3ca00ad42808080809001842220100122082900002105200341c0066a41086a220b200841086a290000370300200320053703c0062008102f200220032903c0062205370300200341c8046a41086a220e2007290300370300200341c8046a41106a220f2005370300200341c8046a41186a2210200b29030037030020032003290398043703c804200341f0066a200341c8046a10fe0320032802f006220c4104200c1b2108024020032902f4064200200c1b22054220882204a7220c2005a7470d00200c41016a2211200c490d122004a722134101742212201120112012491b221141ffffffff03712011470d12201141027422114100480d1202400240200c0d002011102d21080c010b200820134102742011103121080b2008450d0e20054220882204a7210c2011410276ad21050b2008200c4102746a2009360200200d420037030020024200370300200742003703002003420037039804201f10012209290000211f200a200941086a2900003703002003201f3703e8032009102f2007200a290300370300200320032903e80337039804202010012209290000211f200b200941086a2900003703002003201f3703c0062009102f200220032903c006370000200241086a200b290300370000200e2007290300370300200f20022903003703002010200d29030037030020032003290398043703c8040240024020080d00200341c8046aad428080808080048410050c010b200341203602f4062003200341c8046a3602f00620082004a741016a200341f0066a10a3042005a7450d002008102f0b200041043a00000c150b20004183223b0100200041086a4114360200200041046a41c4c7c400360200200041026a41013a00000c140b2001412c6a2802002108200141286a2802002106200141246a2802002107200341c0066a41186a200141196a290000370300200341c0066a41106a200141116a290000370300200341c0066a41086a200141096a290000370300200320012900013703c006024002400240024020022d00000d0020022d00014101470d00200241196a2d00002109200241186a2d0000210a200241166a2f0100210b200241156a2d0000210c200241146a2d0000210d200241126a2f0100210e200241116a2d0000210f200241106a2d000021102002410e6a2f010021112002410d6a2d000021122002410c6a2d000021132002410a6a2f01002114200241096a2d00002115200241086a2d00002116200241066a2f01002117200241056a2d00002118200241046a2d0000211a200241026a2f0100211b20032002411a6a2901003703e001200320093a00df012003200a3a00de012003200b3b01dc012003200c3a00db012003200d3a00da012003200e3b01d8012003200f3a00d701200320103a00d601200320113b01d401200320123a00d301200320133a00d201200320143b01d001200320153a00cf01200320163a00ce01200320173b01cc01200320183a00cb012003201a3a00ca012003201b3b01c8012008418080014b0d012008ad22204220862007ad84100322022900002105200241086a2900002104200241106a290000211f200341a8026a41186a200241186a290000370300200341a8026a41106a201f370300200341a8026a41086a2004370300200320053703a8022002102f200341f0066a200341a8026a10de04200341d8006a20032802f006220920032802f80641c8e1ca004100410010b50120032802582102024020032802f406450d002009102f0b20024101460d022003200341c0066a3602f4062003200341a8026a3602f00620034180086a200341f0066a108001200341f0066a20034180086a10df04200341d0006a20032802f006220920032802f80641c8e1ca004100410010b50120032802502102024020032802f406450d002009102f0b20024101470d0320004183223b0100200041086a410c360200200041046a41acc7c400360200200041026a41033a000020060d180c190b200041023a000020060d170c180b20004183223b0100200041086a410c360200200041046a41b8c7c400360200200041026a41023a000020060d160c170b20004183223b0100200041086a410c360200200041046a41acc7c400360200200041026a41033a000020060d150c160b200341c0006a202042004280a094a58d1d420010ed06200320032903402204428080e983b1de167c2205370388032003200341c0006a41086a2903002005200454ad7c2204370390032003200341c8016a3602e8032003200341c8016a36029804200320034198046a3602f8062003200341e8036a3602f406200320034188036a3602f006200341b0056a200341c8016a200341f0066a1094010240024020032802b0054101470d00200320032900b5053703f0062003200341bc056a2800003600f70620032d00b40521020c010b41042102200341b0056a41086a2903004201520d00200341b0056a41106a290300211f2003280298042109200341a8076a200341b0056a41186a290300370300200341a0076a201f370300200341f0066a41086a41003a0000200341f9066a200929000037000020034181076a200941086a29000037000020034189076a200941106a29000037000020034191076a200941186a290000370000200341033a00f00641c8e1ca004100200341f0066a108c010b200320032903f0063703c804200320032800f7063600cf04200241ff01714104470d07200341f0066a200341a8026a10de0420032802f0062102200320032802f8063602b405200320023602b00520072008200341b0056a109d02024020032802f406450d002002102f0b200341c8046a41086a200341a8026a41086a2202290300370300200341c8046a41106a200341a8026a41106a2208290300370300200341c8046a41186a200341a8026a41186a220929030037030020034198046a41086a200341c0066a41086a220a29030037030020034198046a41106a200341c0066a41106a220b29030037030020034198046a41186a200341c0066a41186a220c290300370300200320032903a8023703c804200320032903c0063703980420034188036a41186a200341c8016a41186a220d29030037030020034188036a41106a200341c8016a41106a220e29030037030020034188036a41086a200341c8016a41086a220f290300370300200320032903c80137038803200341a0076a200437030020034198076a2005370300200341b8076a4100360200200342013703f006200341f0066a41106a200f290300370300200341f0066a41186a200e29030037030020034190076a200d290300370300200342083703b007200341003602a807200320032903c8013703f806200341c4076a2002290300370200200341cc076a2008290300370200200341d4076a2009290300370200200320032903a8023702bc07200341f4076a200c290300370200200341ec076a200b290300370200200341e4076a200a290300370200200320032903c0063702dc07200341b0056a20034180086a10df0420032802b0052102200320032802b8053602ec03200320023602e803200341f0066a200341e8036a10da04024020032802b405450d002002102f0b200341f0066a41086a41073a0000200341f9066a20032903800837000020034181076a20034180086a41086a29030037000020034189076a20034180086a41106a29030037000020034191076a20034180086a41186a2903003700002003410c3a00f00641c8e1ca004100200341f0066a108c01200041043a00002006450d150c140b200341a8016a41186a200141196a290000370300200341a8016a41106a200141116a290000370300200341a8016a41086a200141096a290000370300200320012900013703a8012002411a6a2901002105200241196a2d00002107200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241086a2d00002114200241066a2f01002115200241056a2d00002116200241046a2d00002117200241026a2f0100211841012106024020022d00000d0020022d000141014721060b200320053703e004200320073a00df04200320083a00de04200320093b01dc042003200a3a00db042003200b3a00da042003200c3b01d8042003200d3a00d7042003200e3a00d6042003200f3b01d404200320103a00d304200320113a00d204200320123b01d004200320133a00cf04200320143a00ce04200320153b01cc04200320163a00cb04200320173a00ca04200320183b01c8040240024020060d00200341f8046a41186a200341c8046a41186a2202290300370300200341f8046a41106a200341c8046a41106a2206290300370300200341f8046a41086a200341c8046a41086a2207290300370300200320032903c8043703f804200341a0056a200341a8016a10df04200341f0066a20032802a005220a20032802a80510e0042007200341f0066a41106a2903003703002006200341f0066a41186a2903003703002002200341f0066a41206a290300370300200341c8046a41206a220b200341f0066a41286a290300370300200341c8046a41286a220c200341a0076a290300370300200320032903f8063703c804200341a8076a280200210d200341ac076a280200210e200341b0076a2802002109200341f0066a41c4006a2802002108200341b8076a280200210f20032903f006210520034188036a200341bc076a41c40010e8061a024020054202510d0020034198046a41286a200c29030037030020034198046a41206a200b29030037030020034198046a41186a200229030037030020034198046a41106a200629030037030020034198046a41086a2007290300370300200320032903c80437039804200341a8026a20034188036a41c40010e8061a024020032802a405450d00200a102f0b200341e8036a41086a220220034198046a41086a290300370300200341e8036a41106a220620034198046a41106a290300370300200341e8036a41186a220720034198046a41186a290300370300200341e8036a41206a220a20034198046a41206a290300370300200341e8036a41286a220b20034198046a41286a29030037030020032003290398043703e803200341c8016a200341a8026a41c40010e8061a200341c0066a41086a220c2002290300370300200341c0066a41106a22022006290300370300200341c0066a41186a22062007290300370300200341c0066a41206a2207200a290300370300200341c0066a41286a220a200b290300370300200320032903e8033703c00620034180086a200341c8016a41c40010e8061a200341f8056a200f360200200341b0056a41c4006a2008360200200341ec056a200e360200200341b0056a41106a220b200c290300370300200341b0056a41186a220c2002290300370300200341b0056a41206a22022006290300370300200341b0056a41286a220e2007290300370300200341e0056a220f200a290300370300200320093602f0052003200d3602e805200320032903c0063703b805200320053703b005200341fc056a20034180086a41c40010e8061a20034188036a41186a2206200229030037030020034188036a41106a2202200c29030037030020034188036a41086a2207200b290300370300200320032903b8053703880320054201520d02200f2903002104200e290300211f200341f0066a410e6a2007290300370100200341f0066a41166a2002290300370100200341f0066a411e6a2006290300220537010020034180086a411e6a220a200537010020032003290388033701f60620034180086a41086a200341f0066a41086a29010037030020034180086a41106a200341f0066a41106a29010037030020034180086a41186a200341f0066a41186a290100370300200320032901f006370380082006200a290100370300200220034180086a41166a290100370300200720034180086a410e6a29010037030020032003290186083703880320034188036a200341f8046a412010ea060d04200341f0066a200341fc056a10de0420033502f80642208620032802f0062202ad841005024020032802f406450d002002102f0b200341f0066a200341a8016a10df0420033502f80642208620032802f0062202ad841005024020032802f406450d002002102f0b2003201f3703a802200320043703b0020240201f200484500d002003200341f8046a3602c80120034180086a200341f8046a200341a8026a200341c8016a1096012003290380084201520d002003290388082105200341a8076a20034180086a41106a290300370300200341a0076a2005370300200341f0066a41086a41003a0000200341f9066a20032903f80437000020034181076a200341f8046a41086a29030037000020034189076a200341f8046a41106a29030037000020034191076a20034190056a290300370000200341033a00f00641c8e1ca004100200341f0066a108c010b200341f0066a41086a410a3a0000200341f9066a20032903a80137000020034181076a200341a8016a41086a29030037000020034189076a200341b8016a29030037000020034191076a200341c0016a2903003700002003410c3a00f00641c8e1ca004100200341f0066a108c0102402008450d002009102f0b200041043a0000410121060c150b024020032802a405450d00200a102f0b200041086a410a360200200041046a41a2c7c400360200200041026a41043a000020004183223b0100410121060c140b200041023a0000410121060c130b200041086a4109360200200041046a4199c7c400360200200041026a41053a000020004183223b01000c020b200041023a00000c100b20004183223b0100200041086a4109360200200041046a4199c7c400360200200041026a41053a00000b2008450d0e2009102f410121060c0f0b200141386a2903002105200141306a29030021042001412c6a2802002108200141286a2802002106200141246a2802002107200341c0026a200141196a290000370300200341b8026a200141116a290000370300200341b0026a200141096a290000370300200320012900013703a80220032002411a6a2901003703b0042003200241026a2901003703980420032002410a6a2901003703a0042003200241126a2901003703a8040240024020022d00014101470d0020022d000041ff01710d0020034188036a41186a20034198046a41186a29030037030020034188036a41106a20034198046a41106a29030037030020034188036a41086a20034198046a41086a29030037030020032003290398043703880320034188036a10e104450d012008ad4220862007ad8410032202290000211f200241086a2900002120200241106a290000211920034180086a41186a200241186a29000037030020034180086a41106a201937030020034180086a41086a20203703002003201f370380082002102f200341f0066a20034180086a10de04200341e0006a20032802f006220920032802f80641c8e1ca004100410010b50120032802602102024020032802f406450d002009102f0b20024101460d032003200341a8026a3602f406200320034180086a3602f006200341b0056a200341f0066a108001200341f0066a20034180086a10de0420032802f0062102200320032802f8063602cc01200320023602c80120072008200341c8016a109d02024020032802f406450d002002102f0b200341c8046a41186a200341b0056a41186a290300221f370300200341c8046a41106a200341b0056a41106a2903002220370300200341c8046a41086a200341b0056a41086a2903002219370300200320032903b00522213703c804200341f0066a41086a41073a0000200341f9066a202137000020034181076a201937000020034189076a202037000020034191076a201f3700002003410c3a00f00641c8e1ca004100200341f0066a108c014130102d2202450d08200220043703202002200329038803370000200241286a2005370300200241186a20034188036a41186a290300370000200241106a20034188036a41106a290300370000200241086a20034188036a41086a290300370000200341b4076a428180808010370200200341c4076a20034180086a41086a290300370200200341cc076a20034180086a41106a290300370200200341d4076a20034180086a41186a290300370200200320023602b007200341003602a807200342003703f00620032003290380083702bc07200341e4076a200341a8026a41086a290300370200200341ec076a200341a8026a41106a290300370200200341f4076a200341a8026a41186a290300370200200320032903a8023702dc07200341c8016a200341b0056a10df0420032802c8012108200320032802d0013602c406200320083602c006200341f0066a200341c0066a10da04024020032802cc01450d002008102f0b2002102f200041043a00002006450d0e0c0d0b200041023a000020060d0c0c0d0b200041023a000020060d0b0c0c0b200141306a2903002105200141286a2903002104200341a8016a41186a200141196a290000370300200341a8016a41106a200141116a290000370300200341a8016a41086a200141096a290000370300200320012900013703a801024020022d00000d0020022d00014101470d00200241196a2d00002106200241186a2d00002107200241166a2f01002108200241156a2d00002109200241146a2d0000210a200241126a2f0100210b200241116a2d0000210c200241106a2d0000210d2002410e6a2f0100210e2002410d6a2d0000210f2002410c6a2d000021102002410a6a2f01002111200241096a2d00002112200241086a2d00002113200241066a2f01002114200241056a2d00002115200241046a2d00002116200241026a2f0100211720032002411a6a29010037039005200320063a008f05200320073a008e05200320083b018c05200320093a008b052003200a3a008a052003200b3b0188052003200c3a0087052003200d3a0086052003200e3b0184052003200f3a008305200320103a008205200320113b018005200320123a00ff04200320133a00fe04200320143b01fc04200320153a00fb04200320163a00fa04200320173b01f80402400240024002400240024002400240200341f8046a10e104450d0020034180086a41186a200341a8016a41186a29030037030020034180086a41106a200341a8016a41106a29030037030020034180086a41086a200341a8016a41086a290300370300200320032903a80137038008200341a0056a20034180086a10e204200341f0066a20032802a005220220032802a80510e004200341c8046a41086a2206200341f0066a41106a290300370300200341c8046a41106a2207200341f0066a41186a290300370300200341c8046a41186a2208200341f0066a41206a290300370300200341c8046a41206a220a200341f0066a41286a290300370300200341c8046a41286a220b200341a0076a290300370300200320032903f8063703c804200341a8076a2802002126200341ac076a2802002125200341b0076a2802002109200341f0066a41c4006a280200211e200341b8076a280200210e20032903f006212120034188036a200341bc076a41c40010e8061a024020214202510d0020034198046a41286a200b29030037030020034198046a41206a200a29030037030020034198046a41186a200829030037030020034198046a41106a200729030037030020034198046a41086a2006290300370300200320032903c80437039804200341a8026a20034188036a41c40010e8061a024020032802a405450d002002102f0b200341e8036a41086a220220034198046a41086a290300370300200341e8036a41106a220620034198046a41106a290300370300200341e8036a41186a220720034198046a41186a290300370300200341e8036a41206a220820034198046a41206a290300370300200341e8036a41286a220a20034198046a41286a29030037030020032003290398043703e803200341c8016a200341a8026a41c40010e8061a200341c0066a41086a2002290300370300200341c0066a41106a2006290300370300200341c0066a41186a2007290300370300200341c0066a41206a2008290300370300200341c0066a41286a200a290300370300200320032903e8033703c006200341b0056a200341c8016a41c40010e8061a200320093602980520034188036a41186a200341f8046a41186a29030037030020034188036a41106a200341f8046a41106a29030037030020034188036a41086a200341f8046a41086a290300370300200320032903f8043703880341002102200e41014b0d020240200e0e020004000b200341f0066a41186a20034188036a41186a290300370300200341f0066a41106a20034188036a41106a290300370300200341f0066a41086a20034188036a41086a29030037030020032003290388033703f00641002107200341f0066a21060c040b024020032802a405450d002002102f0b200041086a410a360200200041046a41a2c7c400360200200041026a41043a000020004183223b0100410121060c160b200041023a0000410121060c150b200e210603402006410176220720026a220820022009200841306c6a20034188036a412010ea064101481b2102200620076b220641014b0d000b0b2009200241306c6a220620034188036a412010ea062207450d01200341f0066a41186a20034188036a41186a290300370300200341f0066a41106a20034188036a41106a290300370300200341f0066a41086a20034188036a41086a29030037030020032003290388033703f006200341f0066a2106200e2007411f7620026a2207490d040b0240200e201e470d00201e41016a2202201e490d0f201e41017422082002200820024b1bad42307e221f422088a70d0f201fa722024100480d0f02400240201e0d002002102d21090c010b2009201e41306c2002103121090b2009450d0b2003200936029805200241306e211e0b2009200741306c6a220241306a2002200e20076b41306c10e9061a200241286a200537030020022004370320200241186a200641186a290300370300200241106a200641106a290300370300200241086a200641086a29030037030020022006290300370300200e41016a210e0c010b200341c8046a41186a220720034188036a41186a290300370300200341c8046a41106a220820034188036a41106a290300370300200341c8046a41086a220a20034188036a41086a29030037030020032003290388033703c804200e20024d0d01200620032903c804370300200a290300211f20082903002120200729030021192009200241306c6a22022004370320200641186a2019370300200641106a2020370300200641086a201f370300200241286a20053703000b200341f0066a10e30420032802f0062124200328029805210f02400240200e0d00410021090c010b202420032802f80622024105746a210a2024410020021b2106202441206a202420021b21024100210d4100210b0340200b220c41016a210b200f200c41306c6a2109024002400340024020060d00410021060c020b20062009412010ea06220741004a0d01410020022002200a4622081b21062002200241206a20081b2208210220074100480d000b024002400240200d0d004100210d0c010b200c200d6b2202200e4f0d0120034180086a41286a2207200f200241306c6a220241286a220c29030037030020034180086a41206a2210200241206a221129030037030020034180086a41186a2212200241186a221329030037030020034180086a41106a2214200241106a221529030037030020034180086a41086a2216200241086a22172903003703002003200229030037038008200941086a22182903002105200941106a221a2903002104200941186a221b290300211f200941206a221c290300212020092903002119200c200941286a221d290300370300201120203703002013201f370300201520043703002017200537030020022019370300201d2007290300370300201c2010290300370300201b2012290300370300201a20142903003703002018201629030037030020092003290380083703000b200821020c020b4188bbca002002200e103b000b200d41016a210d0b200b200e470d000b200e200d4100200d417f6a200e491b6b21090b024020032802f406450d002024102f0b20034180086a41186a420037030020034180086a41106a2207420037030020034180086a41086a22024200370300200342003703800841bd98ca00ad42808080808002841001220629000021052002200641086a29000037030020032005370380082006102f41ebdec700ad4280808080f00084100122062900002105200341a8026a41086a2208200641086a290000370300200320053703a8022006102f200720032903a8022205370300200341f0066a41086a2002290300370300200341f0066a41106a2005370300200341f0066a41186a200829030037030020032003290380083703f00620034180086a200341f0066a10e4044100210602400240200329028408420020032802800822021b2205422088a7220741306c22080d004101210a4100210c0c010b200841306d220841ffffff3f712008470d0d200841057422084100480d0d2008102d220a450d092008410576210c0b2005a7210d2002410820021b210b02402007450d00200741306c210841012107200a2102200b21060340200641086a2900002105200641106a29000021042006290000211f200241186a200641186a290000370000200241106a2004370000200241086a20053700002002201f370000200741016a2107200241206a2102200641306a2106200841506a22080d000b200741017621060b0240200d450d00200b102f0b0240200c450d00200a102f0b02400240200920064f0d00202621020c010b4101210220264101460d00200341f0066a41186a4200370300200341f0066a41106a22084200370300200341f0066a41086a22064200370300200342003703f006418de6c300ad4280808080e000841001220729000021052006200741086a290000370300200320053703f0062007102f419ce6c300ad4280808080e00084100122072900002105200341a8026a41086a220a200741086a290000370300200320053703a8022007102f200820032903a802220537030020034180086a41086a200629030037030020034180086a41106a200537030020034180086a41186a200a290300370300200320032903f00637038008200341e8006a20034180086a412010950120032802682107200328026c210820034198046a41186a200341a8016a41186a290300220537030020034198046a41106a200341a8016a41106a290300220437030020034198046a41086a200341a8016a41086a290300221f370300200320032903a801222037039804200641083a0000200341f9066a202037000020034181076a201f37000020034189076a200437000020034191076a20053700002003410c3a00f00641c8e1ca004100200341f0066a108c0120084180e1016a4180e10120071b21250b200341f0066a41106a200341c8066a290300370300200341f0066a41186a200341c0066a41106a290300370300200341f0066a41206a200341c0066a41186a290300370300200341f0066a41286a200341c0066a41206a290300370300200341a0076a200341c0066a41286a290300370300200341b8076a2009360200200341f0066a41c4006a201e360200200341ac076a2025360200200320213703f006200320032903c0063703f8062003200f3602b007200320023602a807200341bc076a200341b0056a41c40010e8061a20034180086a200341a8016a10df042003280280082102200320032802880836028c032003200236028803200341f0066a20034188036a10da040240200328028408450d002002102f0b0240201e450d00200f102f0b200041043a0000410121060c100b419cc3ca002002200e103b000b419ae3c300411e41f8b4ca001039000b200041023a0000410121060c0d0b20004183223b0100200041086a410c360200200041046a41acc7c400360200200041026a41033a000020060d090c0a0b200020023a0000200020032903c804370001200041086a20032800cf0436000020060d0c0c0d0b200041023a00000c0a0b41012106200041013a00000c090b20034190056a200141196a29000037030020034188056a200141116a29000037030020034180056a200141096a290000370300200320012900013703f804024002400240024020022d00000d0020022d00014101470d0020034188036a41186a200341f8046a41186a29030037030020034188036a41106a200341f8046a41106a29030037030020034188036a41086a200341f8046a41086a290300370300200320032903f80437038803200341a8016a20034188036a10e204200341f0066a20032802a801220920032802b00110e004200341c8046a41086a220a200341f0066a41106a290300370300200341c8046a41106a220b200341f0066a41186a290300370300200341c8046a41186a220c200341f0066a41206a290300370300200341c8046a41206a220d200341f0066a41286a290300370300200341c8046a41286a220e200341a0076a290300370300200320032903f8063703c804200341a8076a2802002102200341ac076a2802002107200341b0076a2802002108200341f0066a41c4006a2802002106200341b8076a280200210f20032903f006210520034188036a200341bc076a41c40010e8061a024020054202510d0020034198046a41286a200e29030037030020034198046a41206a200d29030037030020034198046a41186a200c29030037030020034198046a41106a200b29030037030020034198046a41086a200a290300370300200320032903c80437039804200341a8026a20034188036a41c40010e8061a024020032802ac01450d002009102f0b200341e8036a41086a220920034198046a41086a290300370300200341e8036a41106a220a20034198046a41106a290300370300200341e8036a41186a220b20034198046a41186a290300370300200341e8036a41206a220c20034198046a41206a290300370300200341e8036a41286a220d20034198046a41286a29030037030020032003290398043703e803200341c8016a200341a8026a41c40010e8061a200341c0066a41086a220e2009290300370300200341c0066a41106a2209200a290300370300200341c0066a41186a220a200b290300370300200341c0066a41206a220b200c290300370300200341c0066a41286a220c200d290300370300200320032903e8033703c00620034180086a200341c8016a41c40010e8061a200341f8056a200f360200200341b0056a41c4006a2006360200200341ec056a2007360200200341b0056a41106a200e290300370300200341b0056a41186a2009290300370300200341b0056a41206a200a290300370300200341b0056a41286a200b290300370300200341e0056a200c290300370300200320053703b005200320083602f005200320032903c0063703b805200320023602e805200341fc056a20034180086a41c40010e8061a20024101460d024190c7c4002102410621070c030b024020032802ac01450d002009102f0b200041086a410a360200200041046a41a2c7c400360200200041026a41043a000020004183223b0100410121060c0c0b200041023a0000410121060c0b0b200341f0066a41186a4200370300200341f0066a41106a220a4200370300200341f0066a41086a22024200370300200342003703f006418de6c300ad4280808080e000841001220929000021052002200941086a290000370300200320053703f0062009102f419ce6c300ad4280808080e00084100122092900002105200341a8026a41086a220b200941086a290000370300200320053703a8022009102f200a20032903a802220537030020034180086a41086a200229030037030020034180086a41106a200537030020034180086a41186a200b290300370300200320032903f00637038008200341a0016a20034180086a412010950120032802a401410020032802a0011b20074f0d014187c7c4002102410721070b20004183223b0100200041086a4109360200200041046a2002360200200041026a20073a00002006450d082008102f410121060c090b200341f0066a200341fc056a10de0420033502f80642208620032802f0062202ad841005024020032802f406450d002002102f0b200341f0066a41186a200341f8046a41186a290300370300200341f0066a41106a200341f8046a41106a290300370300200341f0066a41086a200341f8046a41086a290300370300200320032903f8043703f00620034180086a200341f0066a10e2042003350288084220862003280280082202ad8410050240200328028408450d002002102f0b200341f0066a200341b0056a41900110e8061a200341b8076a280200211d200341b4076a280200212820032802b007211820034188036a10e304200328028803211e02400240201d0d004100211d0c010b201e20032802900322024105746a210a201e410020021b2106201e41206a201e20021b21024100210d4100210b0340200b220c41016a210b2018200c41306c6a2109024002400340024020060d00410021060c020b20062009412010ea06220741004a0d01410020022002200a4622081b21062002200241206a20081b2208210220074100480d000b024002400240200d0d004100210d0c010b200c200d6b2202201d4f0d0120034180086a41286a22072018200241306c6a220241286a220c29030037030020034180086a41206a220e200241206a220f29030037030020034180086a41186a2210200241186a221129030037030020034180086a41106a2212200241106a221329030037030020034180086a41086a2214200241086a22152903003703002003200229030037038008200941086a22162903002105200941106a22172903002104200941186a221a290300211f200941206a221b290300212020092903002119200c200941286a221c290300370300200f20203703002011201f370300201320043703002015200537030020022019370300201c2007290300370300201b200e290300370300201a2010290300370300201720122903003703002016201429030037030020092003290380083703000b200821020c020b4188bbca002002201d103b000b200d41016a210d0b200b201d470d000b200d450d00201d201d200d6b2202201d2002491b211d0b0240200328028c03450d00201e102f0b201d4115490d020240201d4101762229ad42307e2205422088a70d002005a72202417f4c0d004108212502402002450d002002102d2225450d02200241306e21290b201841506a212a201841907f6a212b4104211041002126410021164100210e201d2115034020152108410021154101210902402008417f6a2227450d000240024002400240024002402018202741306c6a220241206a290300200841306c220720186a41406a2206290300220454200241286a290300221f200641086a290300220554201f2005511b0d002008417e6a210b202b20076a2102410021154100210603400240200b2006470d00200821090c080b2004200229030022205a21072005200241086a290300221f5121092005201f5a210a200241506a2102200641016a210620202104201f21052007200a20091b0d000b200641016a21092006417f7320086a21070c010b202b200841066c410374220b6a21022027210702400340024020074101470d00410021070c020b2004200229030022205421062005200241086a290300221f5121092005201f54210a200241506a21022007417f6a210720202104201f21052006200a20091b0d000b0b20082007490d012008201d4b0d03200820076b2209410176220a450d00202a200b6a21022018200741306c6a2106034020034180086a41286a220b200641286a220c29030037030020034180086a41206a220d200641206a220f29030037030020034180086a41186a2211200641186a221229030037030020034180086a41106a2213200641106a221429030037030020034180086a41086a2215200641086a22172903003703002003200629030037038008200241086a221a2903002105200241106a221b2903002104200241186a221c290300211f200241206a221e2903002120200241286a2224290300211920062002290300370300200c2019370300200f20203703002012201f37030020142004370300201720053703002024200b290300370300201e200d290300370300201c2011290300370300201b2013290300370300201a20152903003703002002200329038008370300200241506a2102200641306a2106200a417f6a220a0d000b0b024020070d00200721150c050b0240200941094d0d00200721150c050b2008201d4b0d012018200741306c6a210c034020082007417f6a2215490d040240200820156b22094102490d002018200741306c6a220241206a220a2903002018201541306c6a220641206a220b290300221f5a200241286a220d2903002204200641286a220f29030022055a20042005511b0d00200629030021042006200229030037030020034180086a41186a2211200641186a221229030037030020034180086a41106a2213200641106a221429030037030020034180086a41086a2217200641086a221a290300370300201a200241086a2903003703002014200241106a2903003703002012200241186a290300370300200b200a290300370300200f200d2903003703002003200437038008024020094103490d002027210a200c210b20064180016a290300201f5a20064188016a290300220420055a20042005511b0d0002400340200b220241286a200241d8006a290300370300200241206a200241d0006a290300370300200241186a200241c8006a290300370300200241106a200241c0006a290300370300200241086a200241386a2903003703002002200241306a220b2903003703002007200a417f6a220a460d0120024180016a290300201f5a20024188016a290300220420055a20042005511b450d000b0b200241306a21020b2002201f3703202002200329038008370300200241286a2005370300200241186a2011290300370300200241106a2013290300370300200241086a20172903003703000b2015450d05200c41506a210c201521072009410a4f0d050c000b0b20072008104b000b20082007417f6a2215490d010b2008201d104a000b20152008104b000b0240200e2026470d00202641016a22022026490d07202641017422062002200620024b1b220241ffffffff01712002470d07200241037422024100480d070240024020260d002002102d21100c010b201020264103742002103121100b2010450d03200241037621262016210e0b2010200e4103746a2202200936020420022015360200201641016a220e21160240200e4102490d000240034002400240024002402010200e417f6a22164103746a2202280200450d00200e41037420106a220841746a2802002207200228020422064d0d000240200e41024b0d00200e21164102210e2015450d0b0c080b2010200e417d6a22114103746a2802042202200620076a4d0d010240200e41034b0d00200e21164103210e2015450d0b0c080b200841646a280200200220076a4d0d01200e21160c060b200e4103490d01200228020421062010200e417d6a22114103746a28020421020b20022006490d010b200e417e6a21110b024002400240024002400240200e201141016a22174b221a450d00200e20114b221b450d01201020114103746a2212280204221c20122802006a2202201020174103746a22132802002214490d022002201d4b0d032018201441306c6a220d2013280204220f41306c22066a2108200241306c2107200220146b220a200f6b2202200f4f0d0420252008200241306c220610e806220a20066a210902400240200f4101480d00200241014e0d010b20082102200a21060c060b202a20076a21072008210203402007200241506a220b200941506a220c200941706a2206290300200241706a220829030054200641086a2903002205200841086a29030022045420052004511b22081b2206290300370300200741086a200641086a290300370300200741106a200641106a290300370300200741186a200641186a290300370300200741206a200641206a290300370300200741286a200641286a2903003703002009200c20081b21090240200d200b200220081b2202490d00200a21060c070b200741506a2107200a2106200a2009490d000c060b0b41c4c2ca002017200e103b000b41c4c2ca002011200e103b000b20142002104b000b2002201d104a000b2025200d200610e806220c20066a210902400240200f4101480d00200a200f4a0d010b200d2102200c21060c010b201820076a210b200c2106200d21020340200220082006200841206a290300200641206a29030054200841286a2903002205200641286a29030022045420052004511b220a1b2207290300370300200241086a200741086a290300370300200241106a200741106a290300370300200241186a200741186a290300370300200241206a200741206a290300370300200241286a200741286a2903003703002006200641306a200a1b2106200241306a2102200841306a2008200a1b2208200b4f0d01200920064b0d000b0b20022006200920066b220720074130706b10e8061a0240201b450d0020122014360200201241046a201c200f6a360200201a450d022013201341086a200e2017417f736a41037410e9061a2016210e201641014d0d030c010b0b419cc3ca002011200e103b000b41b8e3c300411d41f8b4ca001039000b2015450d030c000b0b103d000b1036000b02402026450d002010102f0b2029450d012025102f0c010b201d4102490d00201d417f6a21072018201d41306c6a21094100210a0340024002400240201d20072202417f6a2207490d00201d20076b22084102490d022018200241306c6a220241206a220b2903002018200741306c6a220641206a220c290300221f5a200241286a220d2903002204200641286a220e29030022055a20042005511b0d02200629030021042006200229030037030020034180086a41186a220f200641186a221029030037030020034180086a41106a2211200641106a221229030037030020034180086a41086a2213200641086a22142903003703002014200241086a2903003703002012200241106a2903003703002010200241186a290300370300200c200b290300370300200e200d290300370300200320043703800820084103490d01200a21082009210b20064180016a290300201f5a20064188016a290300220420055a20042005511b0d010340200b220241506a22062002290300370300200641286a200241286a290300370300200641206a200241206a290300370300200641186a200241186a290300370300200641106a200241106a290300370300200641086a200241086a2903003703002008417f6a2208450d02200241306a210b200241d0006a290300201f5a200241d8006a290300220420055a20042005511b0d020c000b0b2007201d104b000b2002201f3703202002200329038008370300200241286a2005370300200241186a200f290300370300200241106a2011290300370300200241086a20132903003703000b200a41016a210a200941506a210920070d000b0b200341c8016a41f4c7c40010b40220034180086a200341c8016a108d020240201d201d41017622024d0d0020034188086a29030022052018200241306c6a220241286a29030022042002290320221f200329038008222056200420055620042005511b22021b21042020201f20021b2105024020032903f0064201520d00200341a8026a41186a200341f0066a41206a290300370300200341a8026a41106a200341f0066a41186a290300370300200341b0026a200341f0066a41106a290300370300200320032903f8063703a802200341f0066a41286a290300211f2003200341f0066a41306a29030022203703c8062003201f3703c0060240201f202084500d002003200341a8026a3602c80420034188036a200341a8026a200341c0066a200341c8046a1096012003290388034201520d00200329039003211f200341b8086a20034188036a41106a290300370300200341b0086a201f37030020034180086a41086a41003a000020034189086a20032903a80237000020034191086a200341a8026a41086a29030037000020034199086a200341a8026a41106a290300370000200341a1086a200341c0026a290300370000200341033a00800841c8e1ca00410020034180086a108c010b200341a8026a200341dc076a412010ea06450d0020034190016a2005200442e400420010ee0620034180016a200329039001221f20034190016a41086a2903002220429c7f427f10ed06200341f0006a201f20204214420010ed0620034180086a200341c8016a200341a8026a2003290370222020052003290380017ca741ff0071220241146c200241056e2202419c7f6c6a41fcff037141324b20026aad7c221f200341f0006a41086a290300201f202054ad7c2220410110f202200420207d2005201f54ad7d21042005201f7d21050b4101210620034180086a200341c8016a200341dc076a20052004410110f20202402028450d002018102f0b200041043a00000c050b41c4c2ca002002201d103b000b1038000b2007102f0b41002107410121060c040b410121060b410121070c020b2007102f0b41012107410021060b024020012d0000417c6a220241024b0d000240024020020e03010200010b2007450d01200141286a280200450d01200141246a280200102f0c010b2006450d00200141286a280200450d00200141246a280200102f0b20034180096a24000b8b0101017f41f2cbca00ad4280808080d001841008024002400240024020002d00000e0400010203000b200041046a29020010080f0b41e4cbca00ad4280808080e0018410080f0b41dacbca00ad4280808080a0018410080f0b20003100011019200041026a31000010190240200041046a2802002201450d00200041086a3502004220862001ad8410080b0b9c06010d7f23004180016b220224002002412036020c20022001360208200241106a2001ad42808080808004841002107302400240024002400240024020022802102203450d00200228021421042002200241186a280200360224200220033602202002200241206a10e60120022802000d0320022802042205200228022422014105762206200620054b1b22074105742206417f4c0d010240024020070d00410121080c010b2006102d2208450d030b02402005450d004100210903402001210a200241003a00782009220b41016a2109410021010240024002400340200a2001460d01200241d8006a20016a200228022022062d00003a00002002200641016a3602202002200141016a22063a00782006210120064120470d000b200241386a41186a220c200241d8006a41186a290300370300200241386a41106a220d200241d8006a41106a290300370300200241386a41086a220e200241d8006a41086a290300370300200220022903583703382007200b470d020240200b41017422012009200120094b1b220141ffffff3f712001470d002001410574220141004e0d020b1038000b200241003602240240200141ff0171450d00200241003a00780b2007450d072008102f0c070b02400240200b0d002001102d21080c010b2008200b4105742001103121080b2008450d05200141057621070b200a20066b21012008200b4105746a220b2002290338370000200b41186a200c290300370000200b41106a200d290300370000200b41086a200e29030037000020092005470d000b2002200a20066b3602240b2008450d032000200736020420002008360200200041086a20053602000c040b200041003602000c040b103d000b1036000b20024100360240200242013703382002410b36022c2002200241086a3602282002200241386a360234200241ec006a41013602002002420137025c200241b885c7003602582002200241286a360268200241346a41d8dbc100200241d8006a103c1a200235024042208620023502388410080240200228023c450d002002280238102f0b200041003602000b2004450d002003102f0b20024180016a24000ba07f05037f037e167f027e037f230041b0046b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e0a0001020304050a0b0c0d000b2003419c016a41013602002003420137028c01200341b4d8c90036028801200341043602ec03200341fcdbc9003602e8032003200341e8036a3602980120034188016a41e8d8c9001043000b200141246a2802002104200341e0006a200141196a290000370300200341d8006a200141116a290000370300200341d0006a200141096a2900003703002003200129000137034820032002411a6a2901003703a0012003200241026a2901003703880120032002410a6a290100370390012003200241126a2901003703980102400240024020022d00014101470d0020022d000041ff01710d00200341e8006a41186a20034188016a41186a290300370300200341e8006a41106a20034188016a41106a290300370300200341e8006a41086a20034188016a41086a290300370300200320032903880137036820034188016a200341e8006a10bf0520032d0088014101470d01200341ff036a2202200341a1016a290000370000200341e8036a41106a220520034188016a41126a290100370300200341d1036a20034188016a410a6a290100370000200341d9036a2005290300370000200341c8036a41186a2002290000370000200320032d0089013a00c8032003200329018a013700c903200341c8036a200341c8006a412010ea060d0220034188016a200441b00210e8061a200341e8036a410a6a200341d0006a290300370100200341e8036a41126a200341d8006a29030037010020034182046a200341e0006a29030037010020034180023b01e803200320032903483701ea03200020034188016a200341e8036a108b010c240b200041023a00002004108e010c230b20004183343b0100200041086a410a360200200041046a41b7cdc700360200200041026a41003a00002004108e010c220b20004183343b0100200041086a410a360200200041046a41b7cdc700360200200041026a41003a00002004108e010c210b200341c8036a41186a200141196a290000370300200341c8036a41106a200141116a290000370300200341c8036a41086a200141096a290000370300200320012900013703c803200341e8036a41186a200141396a290000370300200341e8036a41106a200141316a290000370300200341e8036a41086a200141296a2900003703002003200141216a2900003703e80320022d000120022d0000410047720d0341e796c800ad4280808080800184100122022900002106200341b8036a41086a200241086a290000370300200320063703b8032002102f41d49ac800ad4280808080d00084100122022900002106200341c8006a41086a200241086a290000370300200320063703482002102f4120102d2202450d19200220032903e803370000200241186a200341e8036a41186a290300370000200241106a200341e8036a41106a290300370000200241086a200341e8036a41086a2903003700002002ad4280808080800484100322042900002106200441086a2900002107200441106a290000210820034188016a41186a2205200441186a29000037030020034188016a41106a2209200837030020034188016a41086a220a200737030020032006370388012004102f2002102f41c000102d2202450d19200220032903b803370000200241086a200341b8036a41086a29030037000020022003290348370010200241186a200341c8006a41086a2903003700002002200329038801370020200241286a200a290300370000200241306a2009290300370000200241386a20052903003700004120102d2204450d19200420032903c803370000200441186a200341c8036a41186a2205290300370000200441106a200341c8036a41106a2209290300370000200441086a200341c8036a41086a220a2903003700002002ad42808080808008842004ad428080808080048410042004102f2002102f20034192016a200a2903003701002003419a016a2009290300370100200341a2016a2005290300370100200341aa016a20032903e803370100200341b2016a200341e8036a41086a290300370100200341ba016a200341e8036a41106a290300370100200341c2016a200341e8036a41186a29030037010020034193083b018801200320032903c80337018a0141c8e1ca00410020034188016a108c01200041043a0000410121040c1e0b200141086a2802002109200141046a280200210a02400240024002400240024020022d00000d0020022d00014101470d002001410c6a280200210b200141106a280200210c200141026a2f0100210d200241196a2d00002104200241186a2d00002105200241166a2f0100210e200241156a2d0000210f200241146a2d00002110200241126a2f01002111200241116a2d00002112200241106a2d000021132002410e6a2f010021142002410d6a2d000021152002410c6a2d000021162002410a6a2f01002117200241096a2d00002118200241086a2d00002119200241066a2f0100211a200241056a2d0000211b200241046a2d0000211c200241026a2f0100211d20032002411a6a2901003703e003200320043a00df03200320053a00de032003200e3b01dc032003200f3a00db03200320103a00da03200320113b01d803200320123a00d703200320133a00d603200320143b01d403200320153a00d303200320163a00d203200320173b01d003200320183a00cf03200320193a00ce032003201a3b01cc032003201b3a00cb032003201c3a00ca032003201d3b01c80341e796c800ad4280808080800184100122022900002106200341e8036a41086a200241086a290000370300200320063703e8032002102f41f898c800ad4280808080b0018410012202290000210620034188016a41086a200241086a29000037030020032006370388012002102f4120102d2204450d1e200420032903c803370000200441186a200341c8036a41186a290300370000200441106a200341c8036a41106a290300370000200441086a200341c8036a41086a2903003700002004ad428080808080048410032202290018210620022d0017210520022d0016210e20022f0014210f20022d0013211020022d0012211120022f0010211220022d000f211320022d000e211420022f000c211520022d000b211620022d000a211720022f0008211820022d0007211920022d0006211a20022f0004211b20022d0003211c20022d0002211d20022f0000211e2002102f2004102f41c000102d2202450d1e200220032903e803370000200220032903880137001020022006370038200220053a00372002200e3a00362002200f3b0034200220103a0033200220113a0032200220123b0030200220133a002f200220143a002e200220153b002c200220163a002b200220173a002a200220183b0028200220193a00272002201a3a00262002201b3b00242002201c3a00232002201d3a00222002201e3b0020200241086a200341e8036a41086a290300370000200241186a20034188016a41086a290300370000200341186a200241c00041c8e1ca004100410010b501200328021821042002102f20044101460d01200d450d02200b450d03200b200d490d04200b41094b0d11200b41016a2104200a210203402004417f6a22044102490d062002200241206a2205412010ea06210e20052102200e4100480d000b20004183343b0100200041086a4109360200200041046a4187cdc700360200200041026a41043a00000c240b200041023a00000c230b20004183343b0100200041086a4112360200200041046a41e7ccc700360200200041026a41063a00000c220b20004183343b0100200041086a410d360200200041046a41aacdc700360200200041026a41013a00000c210b20004183343b0100200041086a4110360200200041046a419acdc700360200200041026a41023a00000c200b20004183343b0100200041086a4110360200200041046a419acdc700360200200041026a41023a00000c1f0b200341086a200bad42004280c0f4c198af0b420010ed062003200329030822074280808d93f5d7f1007c22063703682003200341086a41086a2903002006200754ad7c22073703702003200341c8036a360298042003200341c8036a3602482003200341c8006a36029001200320034198046a36028c012003200341e8006a36028801200341e8036a200341c8036a20034188016a1094010240024020032802e8034101470d00200320032900ed03370388012003200341f4036a28000036008f0120032d00ec0321020c010b41042102200341e8036a41086a2903004201520d00200341e8036a41106a290300210820032802482104200341c0016a200341e8036a41186a290300370300200341b8016a200837030020034188016a41086a41003a000020034191016a200429000037000020034199016a200441086a290000370000200341a1016a200441106a290000370000200341a9016a200441186a290000370000200341033a00880141c8e1ca00410020034188016a108c010b20032003290388013703b8032003200328008f013600bf030240200241ff01714104470d0041e796c800ad4280808080800184100122022900002108200341b8036a41086a200241086a290000370300200320083703b8032002102f41f898c800ad4280808080b00184100122022900002108200341c8006a41086a200241086a290000370300200320083703482002102f4120102d2202450d19200220032903c803370000200241186a200341c8036a41186a290300370000200241106a200341c8036a41106a290300370000200241086a200341c8036a41086a2903003700002002ad4280808080800484100322042900002108200441086a290000211f200441106a290000212020034188016a41186a2205200441186a29000037030020034188016a41106a220e202037030020034188016a41086a201f37030020032008370388012004102f2002102f41c000102d2214450d19201420032903b803370000201441086a200341b8036a41086a29030037000020142003290348370010201441186a200341c8006a41086a2903003700002014200329038801370020201441286a20034188016a41086a290300370000201441306a200e290300370000201441386a2005290300370000200341003602900120034201370388014104102d2202450d1920034284808080c00037028c0120032002360288012002200c36000020024104411410312202450d19200220063700042002410c6a200737000020034294808080c00237028c012003200236028801200b20034188016a1069200b4105742112410020032802900122116b2113200328028c0121104100210e410021020340201120026a210f02400240201320106a200e6a4120490d0020032802880121040c010b200f41206a2204200f490d1d201041017422052004200520044b1b22054100480d1d0240024020100d002005102d21040c010b20032802880120102005103121040b2004450d1b2003200536028c012003200436028801200521100b200420116a20026a220441086a200a20026a220541086a290000370000200441106a200541106a290000370000200441186a200541186a2900003700002003200f41206a3602900120042005290000370000200e41606a210e2012200241206a2202470d000b201120026a210502400240201020116b20026b4102490d0020032802880121040c010b200541026a22042005490d1c2010410174220e2004200e20044b1b220e4100480d1c0240024020100d00200e102d21040c010b2003280288012010200e103121040b2004450d1a2003200e36028c012003200436028801200e21100b200420116a20026a200d3b00002014ad4280808080800884200541026aad4220862004ad84100402402010450d002004102f0b2014102f02402009450d00200a102f0b20034192016a200341d0036a2903003701002003419a016a200341d8036a290300370100200341a2016a200341e0036a290300370100200341133b018801200320032903c80337018a014100210541c8e1ca00410020034188016a108c01200041043a0000410121040c210b200020023a0000200020032903b803370001200041086a20032800bf033600000c1e0b200341e8006a41186a200141196a290000370300200341e8006a41106a200141116a290000370300200341e8006a41086a200141096a2900003703002003200129000137036820022d00000d0b20022d00014101470d0b200241196a2d00002104200241186a2d00002105200241166a2f01002109200241156a2d0000210a200241146a2d0000210e200241126a2f0100210f200241116a2d00002110200241106a2d000021112002410e6a2f010021122002410d6a2d000021132002410c6a2d000021142002410a6a2f01002115200241096a2d00002116200241086a2d00002117200241066a2f01002118200241056a2d00002119200241046a2d0000211a200241026a2f0100211b20032002411a6a2901003703e003200320043a00df03200320053a00de03200320093b01dc032003200a3a00db032003200e3a00da032003200f3b01d803200320103a00d703200320113a00d603200320123b01d403200320133a00d303200320143a00d203200320153b01d003200320163a00cf03200320173a00ce03200320183b01cc03200320193a00cb032003201a3a00ca032003201b3b01c80341e796c800ad4280808080800184100122022900002106200341b8036a41086a200241086a290000370300200320063703b8032002102f41f898c800ad4280808080b00184100122022900002106200341c8006a41086a200241086a290000370300200320063703482002102f4120102d2202450d1720022003290368370000200241186a200341e8006a41186a290300370000200241106a200341e8006a41106a290300370000200241086a200341e8006a41086a2903003700002002ad4280808080800484100322042900002106200441086a2900002107200441106a290000210820034188016a41186a2205200441186a29000037030020034188016a41106a2209200837030020034188016a41086a200737030020032006370388012004102f2002102f41c000102d2202450d17200220032903b803370000200241086a200341b8036a41086a29030037000020022003290348370010200241186a200341c8006a41086a2903003700002002200329038801370020200241286a20034188016a41086a290300370000200241306a2009290300370000200241386a2005290300370000200341306a200241c00041c8e1ca004100410010b501200328023021052002102f4101210420054101470d09200341c8006a200341e8006a10c0054120102d2202450d17200220032903c803370000200241186a200341c8036a41186a290300370000200241106a200341c8036a41106a290300370000200241086a200341c8036a41086a29030037000020032002ad428080808080048410062204290000370390042004102f20034194016a200241206a360200200341003a0098012003200236029001200320034190046a41086a220f36028c01200320034190046a36028801200341e8036a20034188016a106c2002102f20032802e803210a02400240200328024c2205200328025022046b20032802f0032209490d00200328024821020c010b200420096a22022004490d1a2005410174220e2002200e20024b1b220e4100480d1a0240024020050d00200e102d21020c010b20032802482005200e103121020b2002450d182003200e36024c20032002360248200e21050b2003200420096a220e360250200220046a200a200910e8061a024020032802ec03450d00200a102f0b200341286a2002200e41c8e1ca004100410010b5012003280228210902402005450d002002102f0b4101210420094101460d0c2003420037035020034280808d93f5d7f1003703482003200341c8036a360290042003200341c8036a36029804200320034198046a36029001200320034190046a36028c012003200341c8006a36028801200341e8036a200341c8036a20034188016a1094010240024020032802e8034101470d00200320032900ed03370388012003200341f4036a28000036008f0120032d00ec0321020c010b41042102200341e8036a41086a2903004201520d00200341e8036a41106a29030021062003280298042104200341c0016a200341e8036a41186a290300370300200341b8016a200637030020034188016a41086a41003a000020034191016a200429000037000020034199016a200441086a290000370000200341a1016a200441106a290000370000200341a9016a200441186a290000370000200341033a00880141c8e1ca00410020034188016a108c010b20032003290388013703b8032003200328008f013600bf030240200241ff01714104470d0020034188016a41186a420037030020034188016a41106a2205420037030020034188016a41086a220242003703002003420037038801418de6c300ad4280808080e000841001220429000021062002200441086a29000037030020032006370388012004102f419ce6c300ad4280808080e00084100122042900002106200341c8006a41086a2209200441086a290000370300200320063703482004102f200520032903482206370300200341e8036a41086a2002290300370300200341e8036a41106a2006370300200341e8036a41186a200929030037030020032003290388013703e803200341206a200341e8036a41201095012003280224210220032802202104200341a4016a4100360200200342003703900120034280808d93f5d7f100370388012003420137029c0120032002410020041b36029801200341b8036a200341e8006a10c0054120102d2202450d18200220032903c803370000200241186a200341c8036a41186a290300370000200241106a200341c8036a41106a290300370000200241086a200341c8036a41086a29030037000020032002ad428080808080048410062204290000370390042004102f200341f4036a200241206a360200200341003a00f803200320023602f0032003200f3602ec03200320034190046a3602e803200341c8006a200341e8036a106c2002102f2003280248210a0240024020032802bc03220520032802c00322046b20032802502209490d0020032802b80321020c010b200420096a22022004490d1b2005410174220e2002200e20024b1b220e4100480d1b0240024020050d00200e102d21020c010b20032802b8032005200e103121020b2002450d192003200e3602bc03200320023602b803200e21050b2003200420096a220e3602c003200220046a200a200910e8061a0240200328024c450d00200a102f0b2003200e3602ec03200320023602e80320034188016a200341e8036a10be0502402005450d002002102f0b200341aa016a20032903c80337010020034192016a200341e8006a41086a2903003701002003419a016a200341e8006a41106a290300370100200341a2016a200341e8006a41186a290300370100200341b2016a200341c8036a41086a290300370100200341ba016a200341c8036a41106a290300370100200341c2016a200341c8036a41186a29030037010020034193023b0188012003200329036837018a0141c8e1ca00410020034188016a108c01200041043a0000410121040c1d0b200020023a0000200020032903b803370001200041086a20032800bf03360000410121040c1c0b200341e8006a41186a200141196a290000370300200341e8006a41106a200141116a290000370300200341e8006a41086a200141096a29000037030020032001290001370368200341c8036a41186a200141396a290000370300200341c8036a41106a200141316a290000370300200341c8036a41086a200141296a2900003703002003200141216a2900003703c8032002411a6a2901002106200241196a2d00002105200241186a2d00002109200241166a2f0100210a200241156a2d0000210e200241146a2d0000210f200241126a2f01002110200241116a2d00002111200241106a2d000021122002410e6a2f010021132002410d6a2d000021142002410c6a2d000021152002410a6a2f01002116200241096a2d00002117200241086a2d00002118200241066a2f01002119200241056a2d0000211a200241046a2d0000211b200241026a2f0100211c41012104024020022d00000d0020022d000141014721040b200320063703a001200320053a009f01200320093a009e012003200a3b019c012003200e3a009b012003200f3a009a01200320103b019801200320113a009701200320123a009601200320133b019401200320143a009301200320153a009201200320163b019001200320173a008f01200320183a008e01200320193b018c012003201a3a008b012003201b3a008a012003201c3b01880102400240024020040d00200341e8036a41186a20034188016a41186a290300370300200341e8036a41106a20034188016a41106a290300370300200341e8036a41086a20034188016a41086a29030037030020032003290388013703e80320034188016a200341e8006a10c1050240200328029c01220a450d00200341a4016a2204280200210220032802a001210f20034188016a200341e8006a200341c8036a10c205200328029c01220e450d0520034190016a290300210620042802002111200329038801210720032802a0012110200328029801211341c6ccc7002112200241014b0d0241002104410921054109210920020e021703170b20004183343b0100200041086a410e360200200041046a41f9ccc700360200200041026a41053a0000410121040c1e0b200041023a0000410121040c1d0b41002104034020042002410176220520046a2209200a20094105746a200341e8036a412010ea0641004a1b2104200220056b220241014b0d000b0b4109210541092109200a20044105746a200341e8036a412010ea060d13201141014b0d034100210220110e020212020b200041023a00000c190b20004183343b0100200041086a410a360200200041046a41cfccc700360200200041026a41083a00000c170b20034188016a41186a200341e8036a41186a29030037030020034188016a41106a200341e8036a41106a29030037030020034188016a41086a200341e8036a41086a290300370300200320032903e803370388014100210520034188016a21040c120b2011210441002102034020022004410176220520026a2209200e20094105746a200341e8036a412010ea0641004a1b2102200420056b220441014b0d000c0f0b0b200341e8006a41186a200141196a290000370300200341e8006a41106a200141116a290000370300200341e8006a41086a200141096a2900003703002003200129000137036820022d00000d0720022d00014101470d07200241196a2d00002104200241186a2d00002105200241166a2f01002109200241156a2d0000210a200241146a2d0000210e200241126a2f0100210f200241116a2d00002110200241106a2d000021112002410e6a2f010021122002410d6a2d000021132002410c6a2d000021142002410a6a2f01002115200241096a2d00002116200241086a2d00002117200241066a2f01002118200241056a2d00002119200241046a2d0000211a200241026a2f0100211b20032002411a6a2901003703e003200320043a00df03200320053a00de03200320093b01dc032003200a3a00db032003200e3a00da032003200f3b01d803200320103a00d703200320113a00d603200320123b01d403200320133a00d303200320143a00d203200320153b01d003200320163a00cf03200320173a00ce03200320183b01cc03200320193a00cb032003201a3a00ca032003201b3b01c80320034188016a200341e8006a10c105024002400240200328029c012205450d0020034188016a41206a280200212120032802a0012109200328029801210e20034188016a200341e8006a200341c8036a10c205200328029c01220a450d01200341a4016a280200212220032802a001210f200328029801211041e796c800ad4280808080800184100122022900002106200341e8036a41086a200241086a290000370300200320063703e8032002102f41d49ac800ad4280808080d0008410012202290000210620034188016a41086a200241086a29000037030020032006370388012002102f4120102d2204450d14200420032903c803370000200441186a200341c8036a41186a290300370000200441106a200341c8036a41106a290300370000200441086a200341c8036a41086a2903003700002004ad428080808080048410032202290018210620022d0017211120022d0016211220022f0014211320022d0013211420022d0012211520022f0010211620022d000f211720022d000e211820022f000c211920022d000b211a20022d000a211b20022f0008211c20022d0007211d20022d0006211e20022f0004210d20022d0003210b20022d0002210c20022f000021232002102f2004102f41c000102d2202450d14200220032903e803370000200220032903880137001020022006370038200220113a0037200220123a0036200220133b0034200220143a0033200220153a0032200220163b0030200220173a002f200220183a002e200220193b002c2002201a3a002b2002201b3a002a2002201c3b00282002201d3a00272002201e3a00262002200d3b00242002200b3a00232002200c3a0022200220233b0020200241086a200341e8036a41086a2212290300370000200241186a20034188016a41086a2204290300370000200341c0006a200241c00041c8e1ca004100410010b501200328024021112002102f20114101470d02410c21024185ccc7002104410f210e0c0e0b20004183343b0100200041086a410e360200200041046a41f9ccc700360200200041026a41053a0000410121040c180b20004183343b0100200041086a410a360200200041046a41cfccc700360200200041026a41083a00000c0d0b20034188016a41186a420037030020034188016a41106a22114200370300200442003703002003420037038801418de6c300ad4280808080e000841001220229000021062004200241086a29000037030020032006370388012002102f419ce6c300ad4280808080e00084100122022900002106200341c8006a41086a2213200241086a290000370300200320063703482002102f20112003290348220637030020122004290300370300200341e8036a41106a2006370300200341e8036a41186a201329030037030020032003290388013703e803200341386a200341e8036a412010950102402010200e6a220220104f0d004191ccc7002104410e210e410821020c0c0b02402002200328023c410020032802381b4d0d00410b210241bbccc7002104410a210e0c0c0b02402022202141ffff03714f0d004109210241a4ccc7002104410c210e0c0c0b41e796c800ad4280808080800184100122022900002106200341b8036a41086a200241086a290000370300200320063703b8032002102f41d49ac800ad4280808080d00084100122022900002106200341c8006a41086a200241086a290000370300200320063703482002102f4120102d2202450d11200220032903c803370000200241186a200341c8036a41186a290300370000200241106a200341c8036a41106a290300370000200241086a200341c8036a41086a2903003700002002ad4280808080800484100322042900002106200441086a2900002107200441106a290000210820034188016a41186a220e200441186a29000037030020034188016a41106a2210200837030020034188016a41086a200737030020032006370388012004102f2002102f41c000102d2202450d11200220032903b803370000200241086a200341b8036a41086a29030037000020022003290348370010200241186a200341c8006a41086a2903003700002002200329038801370020200241286a20034188016a41086a290300370000200241306a2010290300370000200241386a200e2903003700004120102d2204450d1120042003290368370000200441186a200341e8006a41186a220e290300370000200441106a200341e8006a41106a2210290300370000200441086a200341e8006a41086a22112903003700002002ad42808080808008842004ad428080808080048410042004102f2002102f200341c8036a10d00220034192016a20112903003701002003419a016a2010290300370100200341a2016a200e290300370100200341aa016a20032903c803370100200341b2016a200341c8036a41086a290300370100200341ba016a200341c8036a41106a290300370100200341c2016a200341c8036a41186a29030037010020034193083b0188012003200329036837018a0141c8e1ca00410020034188016a108c010240200f450d00200a102f0b02402009450d002005102f0b200041043a0000410121040c160b200341c8036a41186a200141196a290000370300200341c8036a41106a200141116a290000370300200341c8036a41086a200141096a290000370300200320012900013703c8032002411a6a2901002106200241196a2d00002105200241186a2d00002109200241166a2f0100210a200241156a2d0000210e200241146a2d0000210f200241126a2f01002110200241116a2d00002111200241106a2d000021122002410e6a2f010021132002410d6a2d000021142002410c6a2d000021152002410a6a2f01002116200241096a2d00002117200241086a2d00002118200241066a2f01002119200241056a2d0000211a200241046a2d0000211b200241026a2f0100211c41012104024020022d00000d0020022d000141014721040b200320063703a001200320053a009f01200320093a009e012003200a3b019c012003200e3a009b012003200f3a009a01200320103b019801200320113a009701200320123a009601200320133b019401200320143a009301200320153a009201200320163b019001200320173a008f01200320183a008e01200320193b018c012003201a3a008b012003201b3a008a012003201c3b018801024020040d00200341e8036a41186a20034188016a41186a290300370300200341e8036a41106a20034188016a41106a290300370300200341e8036a41086a20034188016a41086a29030037030020032003290388013703e803200341c8006a200341e8036a10c0054120102d2202450d11200220032903c803370000200241186a200341c8036a41186a290300370000200241106a200341c8036a41106a290300370000200241086a200341c8036a41086a29030037000020032002ad428080808080048410062204290000370390042004102f20034194016a200241206a360200200341003a0098012003200236029001200320034190046a41086a36028c01200320034190046a36028801200341e8006a20034188016a106c2002102f2003280268210a02400240200328024c2205200328025022046b20032802702209490d00200328024821020c010b200420096a22022004490d142005410174220e2002200e20024b1b220e4100480d140240024020050d00200e102d21020c010b20032802482005200e103121020b2002450d122003200e36024c20032002360248200e21050b2003200420096a220e360250200220046a200a200910e8061a0240200328026c450d00200a102f0b20034188016a2002200e109e050240200328029c012204450d00200ead4220862002ad84100520034188016a41086a2903002106200329038801210720032903a001210802402005450d002002102f0b20034188016a200341c8036a200341e8036a20072006410010bc0120034192016a200341e8036a41086a2903003701002003419a016a200341e8036a41106a290300370100200341a2016a200341e8036a41186a290300370100200341aa016a20032903c803370100200341b2016a200341c8036a41086a290300370100200341ba016a200341c8036a41106a290300370100200341c2016a200341c8036a41186a29030037010020034193063b018801200320032903e80337018a0141c8e1ca00410020034188016a108c0102402008a7450d002004102f0b200041043a0000410121040c170b02402005450d002002102f0b20004183343b0100200041086a410a360200200041046a41cfccc700360200200041026a41083a0000410121040c160b200041023a0000410121040c150b20022d00000d0720022d00014101470d07200241196a2d00002104200241186a2d00002105200241166a2f01002109200241156a2d0000210a200241146a2d0000210e200241126a2f0100210f200241116a2d00002110200241106a2d000021112002410e6a2f010021122002410d6a2d000021132002410c6a2d000021142002410a6a2f01002115200241096a2d00002116200241086a2d00002117200241066a2f01002118200241056a2d00002119200241046a2d0000211a200241026a2f0100211b20032002411a6a2901003703e003200320043a00df03200320053a00de03200320093b01dc032003200a3a00db032003200e3a00da032003200f3b01d803200320103a00d703200320113a00d603200320123b01d403200320133a00d303200320143a00d203200320153b01d003200320163a00cf03200320173a00ce03200320183b01cc03200320193a00cb032003201a3a00ca032003201b3b01c80320034188016a200341c8036a10c0052003280290012202417f4c0d0620032802880121040240024020020d00410121050c010b2002102d2205450d100b20052004200210e8062104200341fc006a20034190016a22092802002205360200200320023602702003200236026c200320043602682003200329038801220637027420034188016a2005ad422086200642ffffffff0f8384101810730240024002402003280288012202450d00200328028c012104024002402009280200220520032802702209490d002003280268220a2002460d01200a2002200910ea06450d010b2004450d012002102f0c010b200341f4006a2109200320053602a0042003200436029c04200320023602980420034188016a20022005109e050240200328029c01220a0d00200341003602c003200342013703b803200341d4006a412c360200200320093602a8042003412c36024c2003200341ac046a3602502003200341a8046a360248200320034198046a3602ac042003200341b8036a36029004200341fc036a4102360200200342023702ec03200341a8dcc9003602e8032003200341c8006a3602f80320034190046a41d8dbc100200341e8036a103c1a20033502c00342208620033502b80384100820032802bc03450d0020032802b803102f0b200341e8036a41086a220220034198046a41086a28020036020020032003290398043703e8030240200341f8006a280200450d002003280274102f0b200920032903e803370200200941086a2002280200360200200a0d010b41e796c800ad4280808080800184100122022900002106200341b8036a41086a200241086a290000370300200320063703b8032002102f41f898c800ad4280808080b00184100122022900002106200341c8006a41086a200241086a290000370300200320063703482002102f4120102d2202450d11200220032903c803370000200241186a200341c8036a41186a290300370000200241106a200341c8036a41106a290300370000200241086a200341c8036a41086a2903003700002002ad4280808080800484100322042900002106200441086a2900002107200441106a290000210820034188016a41186a2205200441186a29000037030020034188016a41106a2209200837030020034188016a41086a200737030020032006370388012004102f2002102f41c000102d2202450d11200220032903b803370000200241086a200341b8036a41086a29030037000020022003290348370010200241186a200341c8006a41086a2903003700002002200329038801370020200241286a20034188016a41086a220a290300370000200241306a2009290300370000200241386a200529030037000020034188016a2002109b050240200328029c012204450d002002ad428080808080088410050b200a2903002106200329038801210720032802a00121052002102f024020040d00410e210241f9ccc7002104410521050c020b200320073703482003200637035002402007200684500d002003200341c8036a3602b803200341e8036a200341c8036a200341c8006a200341b8036a10960120032903e8034201520d0020032903f0032106200341c0016a200341e8036a41106a290300370300200341b8016a200637030020034188016a41086a41003a000020034191016a20032903c80337000020034199016a200341c8036a41086a290300370000200341a1016a200341c8036a41106a290300370000200341a9016a200341e0036a290300370000200341033a00880141c8e1ca00410020034188016a108c010b20034192016a200341d0036a2903003701002003419a016a200341d8036a290300370100200341a2016a200341e0036a290300370100200341930a3b018801200320032903c80337018a0141c8e1ca00410020034188016a108c0102402005450d002004102f0b0240200328026c450d002003280268102f0b0240200341f8006a280200450d002003280274102f0b200041043a0000410121040c160b410b21024199ccc7002104410d210520032802a001450d00200a102f0b20004183343b0100200041086a2002360200200041046a2004360200200041026a20053a00000240200328026c450d002003280268102f0b200341f8006a280200450d132003280274102f410121040c140b20034180016a200141196a290000370300200341f8006a200141116a290000370300200341f0006a200141096a290000370300200320012900013703684101210420022d00014101470d0720022d000041ff01710d0720032002411a6a2901003703e0032003200241026a2901003703c80320032002410a6a2901003703d0032003200241126a2901003703d803200341e8036a200341c8036a10bf05200341a1016a20034180016a29030037000020034199016a200341f8006a29030037000020034191016a200341f0006a2903003700002003200329036837008901200341013a008801024020032d00e8034101470d00200341e8036a41017220034188016a410172412010ea060d0041e796c800ad4280808080800184100122022900002106200341b8036a41086a200241086a290000370300200320063703b8032002102f41d49ac800ad4280808080d00084100122022900002106200341c8006a41086a200241086a290000370300200320063703482002102f4120102d2202450d0f200220032903c803370000200241186a200341c8036a41186a290300370000200241106a200341c8036a41106a290300370000200241086a200341c8036a41086a2903003700002002ad4280808080800484100322042900002106200441086a2900002107200441106a290000210820034188016a41186a2205200441186a29000037030020034188016a41106a2209200837030020034188016a41086a200737030020032006370388012004102f2002102f41c000102d2202450d0f200220032903b803370000200241086a200341b8036a41086a29030037000020022003290348370010200241186a200341c8006a41086a2903003700002002200329038801370020200241286a20034188016a41086a290300370000200241306a2009290300370000200241386a20052903003700002002ad428080808080088410052002102f200341c8036a10ca02200041043a0000410121040c140b20004183343b0100200041086a410a360200200041046a41b7cdc700360200200041026a41003a0000410121040c130b20004183343b0100200041086a410e360200200041046a41f9ccc700360200200041026a41053a00000c120b20004183343b0100200041086a410a360200200041046a4190cdc700360200200041026a41033a00000c120b200041023a0000410121040c100b20004183343b0100200041086a410e360200200041046a41d9ccc700360200200041026a41073a00000c0f0b200041023a0000410121040c0e0b103d000b200041023a0000410121040c0c0b200041023a00000c0b0b20004183343b0100200041086a2002360200200041046a2004360200200041026a200e3a0000200f450d00200a102f0b2009450d082005102f410121040c090b200e20024105746a200341e8036a412010ea0622050d01410e210941adccc7002112410b21050b20004183343b0100200041086a2009360200200041046a2012360200200041026a20053a00002010450d05200e102f0c050b20034188016a41186a200341e8036a41186a29030037030020034188016a41106a200341e8036a41106a29030037030020034188016a41086a200341e8036a41086a290300370300200320032903e8033703880120034188016a210420112005411f7620026a2205490d020b024020112010470d00201041016a22022010490d03201041017422092002200920024b1b220241ffffff3f712002470d03200241057422024100480d030240024020100d002002102d210e0c010b200e201041057420021031210e0b200e450d01200241057621100b200e20054105746a220241206a2002201120056b41057410e9061a200241186a200441186a290000370000200241106a200441106a290000370000200241086a200441086a29000037000020022004290000370000200341a4016a201141016a36020020034188016a41186a2010360200200320063703900120032007370388012003200e36029c01200320133602980120034198046a200341e8006a10c0054120102d2202450d00200220032903c803370000200241186a200341c8036a41186a290300370000200241106a200341c8036a41106a290300370000200241086a200341c8036a41086a29030037000020032002ad428080808080048410062204290000370390042004102f200341d4006a200241206a360200200341003a005820032002360250200320034190046a41086a36024c200320034190046a360248200341b8036a200341c8006a106c2002102f20032802b803211102400240200328029c04220520032802a00422046b20032802c0032209490d0020032802980421020c010b200420096a22022004490d03200541017422122002201220024b1b22124100480d030240024020050d002012102d21020c010b20032802980420052012103121020b2002450d012003201236029c042003200236029804201221050b2003200420096a22123602a004200220046a2011200910e8061a024020032802bc03450d002011102f0b2003201236024c2003200236024820034188016a200341c8006a10be0502402005450d002002102f0b02402010450d00200e102f0b200341aa016a20032903c80337010020034192016a200341e8006a41086a2903003701002003419a016a200341e8006a41106a290300370100200341a2016a200341e8006a41186a290300370100200341b2016a200341c8036a41086a290300370100200341ba016a200341c8036a41106a290300370100200341c2016a200341c8036a41186a29030037010020034193043b0188012003200329036837018a01200341e2016a200341e8036a41186a290300370100200341da016a200341e8036a41106a290300370100200341d2016a200341e8036a41086a290300370100200341ca016a20032903e80337010041c8e1ca00410020034188016a108c010240200f450d00200a102f0b200041043a0000410121040c050b1036000b419ae3c300411e41f8b4ca001039000b1038000b200f450d00200a102f410121040c010b410121040b410121050c020b41002105410121042009450d01200a102f0c010b2004102f41012105410021040b024020012d0000417f6a220241024b0d000240024020020e03010200010b2005450d01200141086a280200450d01200141046a280200102f0c010b2004450d00200141246a2802002202108e012002102f0b200341b0046a24000bcb8a0208017f037e137f037e037f017e107f067e230041a0046b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e0d000102030405060708090a0b0c000b200341b4036a4101360200200342013702a403200341b4d8c9003602a003200341043602d401200341fcdbc9003602d0012003200341d0016a3602b003200341a0036a41e8d8c9001043000b200141106a2903002104200141086a29030021052002411a6a2901002106200241196a2d00002107200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241086a2d00002114200241066a2f01002115200241056a2d00002116200241046a2d00002117200241026a2f0100211841012119024020022d00000d0020022d000141014721190b200320063703b803200320073a00b703200320083a00b603200320093b01b4032003200a3a00b3032003200b3a00b2032003200c3b01b0032003200d3a00af032003200e3a00ae032003200f3b01ac03200320103a00ab03200320113a00aa03200320123b01a803200320133a00a703200320143a00a603200320153b01a403200320163a00a303200320173a00a203200320183b01a00320190d0b200341a8016a41186a2219200341a0036a41186a290300370300200341a8016a41106a2207200341a0036a41106a290300370300200341a8016a41086a2208200341a0036a41086a2209290300370300200320032903a0033703a80141c6b5c400ad4280808080f0008410012202290000210620034188016a41086a200241086a29000037030020032006370388012002102f419cccc500ad4280808080b002841001220229000021062009200241086a290000370300200320063703a0032002102f4120102d2202450d23200220032903a801370000200241186a2019290300370000200241106a2007290300370000200241086a20082903003700002002ad4280808080800484100322192900002106201941086a290000211a201941106a290000211b200341f8026a41186a201941186a290000370300200341f8026a41106a201b370300200341f8026a41086a201a370300200320063703f8022019102f2002102f41c000102d2202450d232002200329038801370000200241086a20034188016a41086a290300370000200220032903a003370010200241186a200341a0036a41086a290300370000200220032903f802370020200241286a200341f8026a41086a290300370000200241306a20034188036a290300370000200241386a200341f8026a41186a290300370000200341106a200241c00041c8e1ca004100410010b501200328021021192002102f20194101460d1c41c6b5c400ad4280808080f00084100122022900002106200341e8006a41086a200241086a290000370300200320063703682002102f41dfdbc400ad4280808080800284100122022900002106200341f8006a41086a200241086a290000370300200320063703782002102f4120102d2202450d23200220032903a801370000200241186a200341a8016a41186a290300370000200241106a200341a8016a41106a290300370000200241086a200341a8016a41086a2903003700002002ad4280808080800484100322192900002106201941086a290000211a201941106a290000211b20034188016a41186a2207201941186a29000037030020034188016a41106a2208201b37030020034188016a41086a2209201a37030020032006370388012019102f2002102f41c000102d2202450d2320022003290368370000200241086a200341e8006a41086a29030037000020022003290378370010200241186a200341f8006a41086a2903003700002002200329038801370020200241286a2009290300370000200241306a2008290300370000200241386a2007290300370000200341086a200241c00041c8e1ca004100410010b501200328020821192002102f0240024020194101460d00200341a0036a41186a4200370300200341a0036a41106a22084200370300200341a0036a41086a22024200370300200342003703a00341c6b5c400ad4280808080f000841001221929000021062002201941086a290000370300200320063703a0032019102f41b4dac400ad4280808080c0008410012219290000210620034188016a41086a2207201941086a29000037030020032006370388012019102f20082003290388012206370300200341f8026a41086a2002290300370300200341f8026a41106a2006370300200341f8026a41186a2007290300370300200320032903a0033703f802200341a0036a200341f8026a10ad0420032802a0032202410820021b220920032902a403420020021b2206422088a741e8006c6a210720092102034020022007460d020240200341a8016a200241c8006a2219460d00201941206a21022019200341a8016a412010ea060d010b0b20004183323b0100200041086a410a360200200041046a4189b6c400360200200041026a410c3a00000c2b0b20004183323b0100200041086a4109360200200041046a41e9b6c400360200200041026a41033a00000c2b0b200341a0036a41186a22074200370300200341a0036a41106a220a4200370300200341a0036a41086a22024200370300200342003703a00341c6b5c400ad4280808080f0008410012219290000211a2002201941086a2900003703002003201a3703a0032019102f418c91c700ad4280808080a0018410012219290000211a20034188016a41086a220b201941086a2900003703002003201a370388012019102f2008200329038801370000200841086a200b290300370000200341f8026a41086a2002290300370300200341f8026a41106a200a290300370300200341f8026a41186a2007290300370300200320032903a0033703f802200341a0036a200341f8026a10ad0420032802a0032202410820021b220b20032902a403420020021b221a422088a741e8006c6a2107200b21020240034020022007460d010240200341a8016a200241c8006a2219460d00201941206a21022019200341a8016a412010ea060d010b0b20004183323b0100200041086a4110360200200041046a41f9b5c400360200200041026a410d3a00000c290b200341a0036a41186a22074200370300200341a0036a41106a220a4200370300200341a0036a41086a22024200370300200342003703a00341c6b5c400ad4280808080f0008410012219290000211b2002201941086a2900003703002003201b3703a0032019102f41ebdec700ad4280808080f0008410012219290000211b20034188016a41086a220c201941086a2900003703002003201b370388012019102f2008200329038801370000200841086a200c290300370000200341f8026a41086a2002290300370300200341f8026a41106a200a290300370300200341f8026a41186a2007290300370300200320032903a0033703f802200341a0036a200341f8026a412010aa0220032802a0032202410120021b210a0240024002400240024020032902a403420020021b221b422088a7221941014b0d004100210220190e020201020b41002102034020022019410176220720026a2208200a20084105746a200341a8016a412010ea0641004a1b2102201920076b221941014b0d000b0b200a20024105746a200341a8016a412010ea06450d010b200342003703800320034280809aa6eaafe3013703f8022003200341a8016a360288012003200341a8016a3602c0022003200341c0026a3602a803200320034188016a3602a4032003200341f8026a3602a003200341d0016a200341a8016a200341a0036a1094010240024020032802d0014101470d00200341dc016a2802002119200341d8016a280200210720032d00d701210820032d00d601210c20032d00d501210d20032d00d40121020c010b410421020240200341d0016a41086a2903004201520d00200341d0016a41106a290300211c20032802c0022119200341d8036a200341d0016a41186a290300370300200341d0036a201c370300200341a0036a41086a41003a0000200341a9036a2019290000370000200341b1036a201941086a290000370000200341b9036a201941106a290000370000200341c1036a201941186a290000370000200341033a00a00341c8e1ca004100200341a0036a108c010b0b200241ff01714104470d01200320063702d401200320093602d001200341a0036a41106a4200370300200341a0036a41086a22024280809aa6eaafe301370300200341003a00a003200341d0016a200341a8016a20052004200341a0036a10e604200341d8036a2004370300200341d0036a2005370300200241013a0000200341a9036a20032903a801370000200341b1036a200341a8016a41086a290300370000200341b9036a200341a8016a41106a290300370000200341c1036a200341c0016a290300370000200341123a00a00341c8e1ca004100200341a0036a108c01200041043a00000240201ba7450d00200a102f0b201aa7450d2c200b102f0c2c0b20004183323b0100200041086a410d360200200041046a41f2b6c400360200200041026a41023a00000c280b2000200d3a0001200020023a0000200041086a2019360000200041046a2007360000200041036a20083a0000200041026a200c3a00000c270b200141046a2802002118200241026a2f01002119200241046a2d00002107200241056a2d00002108200241066a2f01002109200241086a2d0000210a200241096a2d0000210b2002410a6a2f0100210c2002410c6a2d0000210d2002410d6a2d0000210e2002410e6a2f0100210f200241106a2d00002110200241116a2d00002111200241126a2f01002112200241146a2d00002113200241156a2d00002114200241166a2f01002115200241186a2d00002116200241196a2d0000211720022d0000211d20022d0001211e20032002411a6a29010022063703b803200320173a00b703200320163a00b603200320153b01b403200320143a00b303200320133a00b203200320123b01b003200320113a00af03200320103a00ae032003200f3b01ac032003200e3a00ab032003200d3a00aa032003200c3b01a8032003200b3a00a7032003200a3a00a603200320093b01a403200320083a00a303200320073a00a203200320193b01a0030240201d410047201e410147720d00200320183602a002200341a0036a41186a4200370300200341a0036a41106a221e4200370300200341a0036a41086a22024200370300200342003703a00341c6b5c400ad4280808080f0008422041001221d29000021052002201d41086a290000370300200320053703a003201d102f41b4dac400ad4280808080c0008422051001221d290000211a20034188016a41086a221f201d41086a2900003703002003201a37038801201d102f201e200329038801221a370300200341f8026a41086a2002290300370300200341f8026a41106a201a370300200341f8026a41186a201f290300370300200320032903a0033703f802200341a0036a200341f8026a10ad0420032802a003210220032902a403211a200341c4016a2006370200200341c3016a20173a0000200341a8016a411a6a20163a0000200341a8016a41186a20153b0100200341bf016a20143a0000200341a8016a41166a20133a0000200341a8016a41146a20123b0100200341bb016a20113a0000200341a8016a41126a20103a0000200341a8016a41106a200f3b0100200341b7016a200e3a0000200341a8016a410e6a200d3a0000200341a8016a410c6a200c3b0100200341b3016a200b3a0000200341a8016a410a6a200a3a0000200341a8016a41086a20093b0100200320083a00af01200320073a00ae01200320193b01ac012002410820021b21192003200341a0026a3602a8014103210802402018201a420020021b2206422088a722094f0d0002402019201841e8006c6a220241c8006a220a200341a8016a4104722207460d00200a2007412010ea060d010b20022d0000210820032002280001360288012003200241046a28000036008b01200241106a290300211a200241086a290300211b200341d0016a200241186a41d00010e8061a2002200241e8006a2018417f7320096a41e8006c10e9061a0240024020084101470d00200341a0036a41086a200341d0016a41086a2d00003a000020032003280288013602c0022003200328008b013600c302200320032903d0013703a00341c6b5c400ad4280808080f0008410012202290000211c200341e8006a41086a200241086a2900003703002003201c3703682002102f41d8cdc500ad428080808080018410012202290000211c200341f8006a41086a200241086a2900003703002003201c3703782002102f4120102d2202450d262002201b370007200220032802c002360000200220032903a0033700172002410f6a201a370000200241036a20032800c3023600002002411f6a200341a0036a41086a2d00003a00002002ad428080808080048410032208290000211a200841086a290000211b200841106a290000211c200341f8026a41186a2209200841186a290000370300200341f8026a41106a220a201c370300200341f8026a41086a220b201b3703002003201a3703f8022008102f2002102f41c000102d2202450d2620022003290368370000200241086a200341e8006a41086a29030037000020022003290378370010200241186a200341f8006a41086a290300370000200220032903f802370020200241286a200b290300370000200241306a200a290300370000200241386a20092903003700002002ad428080808080088410052002102f0c010b2003201b3703c0022003201a3703c802201b201a84500d00200320073602b002200341f8026a2007200341c0026a200341b0026a10960120032903f8024201520d00200329038003211a200341d8036a200341f8026a41106a290300370300200341d0036a201a370300200341a0036a41086a41003a0000200341a9036a2007290000370000200341b1036a200741086a290000370000200341b9036a200741106a290000370000200341c1036a200741186a290000370000200341033a00a00341c8e1ca004100200341a0036a108c010b20064280808080707c210641042108200341a0036a41086a41043a0000200341a9036a2007290000370000200341b1036a200741086a290000370000200341b9036a200741106a290000370000200341c1036a200741186a290000370000200341123a00a00341c8e1ca004100200341a0036a108c010b200341f8026a41186a4200370300200341f8026a41106a22094200370300200341f8026a41086a22024200370300200342003703f8022004100122072900002104200341e8006a41086a220a200741086a290000370300200320043703682007102f2002200a290300370300200320032903683703f8022005100122072900002104200341f8006a41086a220a200741086a290000370300200320043703782007102f20092003290378220437030020034188016a41086a200229030037030020034188016a41106a200437030020034188016a41186a200a290300370300200320032903f802370388010240024020190d0020034188016aad428080808080048410050c010b200341a0036a20192006422088a710b10420034188016aad428080808080048420033502a80342208620032802a0032202ad841004024020032802a403450d002002102f0b2006a7450d002019102f0b200041193b0001200020083a0000200041086a410b360200200041046a41ffb6c4003602000c2a0b200041023a00000c290b200141c0006a290300211a200141386a290300211b200141306a2903002104200141286a2903002105200341a8016a41186a200141196a290000370300200341a8016a41106a200141116a290000370300200341a8016a41086a200141096a290000370300200320012900013703a8012002411a6a2901002106200241196a2d00002107200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241086a2d00002114200241066a2f01002115200241056a2d00002116200241046a2d00002117200241026a2f0100211841012119024020022d00000d0020022d000141014721190b200320063703b803200320073a00b703200320083a00b603200320093b01b4032003200a3a00b3032003200b3a00b2032003200c3b01b0032003200d3a00af032003200e3a00ae032003200f3b01ac03200320103a00ab03200320113a00aa03200320123b01a803200320133a00a703200320143a00a603200320153b01a403200320163a00a303200320173a00a203200320183b01a00320190d0a200341d0016a41186a200341a0036a41186a2207290300370300200341d0016a41106a200341a0036a41106a2208290300370300200341d0016a41086a200341a0036a41086a2209290300370300200320032903a0033703d00141c6b5c400ad4280808080f00084100122022d000f210a20022d000e210b20022f000c210c20022d000b210d20022d000a210e20022f0008210f20022d0007211020022d0006211120022f0004211220022d0003211320022d0002211420022f000021152002102f419cccc500ad4280808080b00284100122022900002106200341f8026a41086a200241086a290000370300200320063703f8022002102f4120102d2202450d21200220032903a801370000200241186a200341a8016a41186a290300370000200241106a200341a8016a41106a290300370000200241086a200341a8016a41086a2903003700002002ad4280808080800484100322192900002106201941086a290000211c201941106a29000021202007201941186a290000370300200820203703002009201c370300200320063703a0032019102f2002102f41c000102d2202450d21200220103a0007200220113a0006200220123b0004200220133a0003200220143a0002200220153b00002002200a3a000f2002200b3a000e2002200c3b000c2002200d3a000b2002200e3a000a2002200f3b0008200220032903f802370010200241186a200341f8026a41086a290300370000200220032903a003370020200241286a200341a0036a41086a2207290300370000200241306a200341b0036a290300370000200241386a200341a0036a41186a290300370000200341286a200241c00041c8e1ca004100410010b501200328022821192002102f20194101460d0b41c6b5c400ad4280808080f0008410012202290000210620034188016a41086a200241086a29000037030020032006370388012002102f41dfdbc400ad42808080808002841001220229000021062007200241086a290000370300200320063703a0032002102f4120102d2202450d21200220032903a801370000200241186a200341a8016a41186a290300370000200241106a200341a8016a41106a290300370000200241086a200341a8016a41086a2903003700002002ad4280808080800484100322192900002106201941086a290000211c201941106a2900002120200341f8026a41186a2207201941186a290000370300200341f8026a41106a22082020370300200341f8026a41086a2209201c370300200320063703f8022019102f2002102f41c000102d2202450d212002200329038801370000200241086a20034188016a41086a290300370000200220032903a003370010200241186a200341a0036a41086a290300370000200220032903f802370020200241286a2009290300370000200241306a2008290300370000200241386a2007290300370000200341206a200241c00041c8e1ca004100410010b501200328022021192002102f0240024020194101460d00200341a0036a41186a4200370300200341a0036a41106a22084200370300200341a0036a41086a22024200370300200342003703a00341c6b5c400ad4280808080f000841001221929000021062002201941086a290000370300200320063703a0032019102f41b4dac400ad4280808080c0008410012219290000210620034188016a41086a2207201941086a29000037030020032006370388012019102f20082003290388012206370300200341f8026a41086a2002290300370300200341f8026a41106a2006370300200341f8026a41186a2007290300370300200320032903a0033703f802200341a0036a200341f8026a10ad0420032802a0032202410820021b220920032902a403420020021b2206422088a741e8006c6a210720092102034020022007460d020240200341a8016a200241c8006a2219460d00201941206a21022019200341a8016a412010ea060d010b0b20004183323b0100200041086a410a360200200041046a4189b6c400360200200041026a410c3a00000c260b20004183323b0100200041086a4109360200200041046a41e9b6c400360200200041026a41033a00000c290b200341a0036a41186a22074200370300200341a0036a41106a220a4200370300200341a0036a41086a22024200370300200342003703a00341c6b5c400ad4280808080f0008410012219290000211c2002201941086a2900003703002003201c3703a0032019102f418c91c700ad4280808080a0018410012219290000211c20034188016a41086a220b201941086a2900003703002003201c370388012019102f2008200329038801370000200841086a200b290300370000200341f8026a41086a2002290300370300200341f8026a41106a200a290300370300200341f8026a41186a2007290300370300200320032903a0033703f802200341a0036a200341f8026a10ad0420032802a0032202410820021b220c20032902a403420020021b221c422088a741e8006c6a2107200c21020240034020022007460d010240200341a8016a200241c8006a2219460d00201941206a21022019200341a8016a412010ea060d010b0b20004183323b0100200041086a4110360200200041046a41f9b5c400360200200041026a410d3a00000c240b200341a0036a41186a22074200370300200341a0036a41106a220a4200370300200341a0036a41086a22024200370300200342003703a00341c6b5c400ad4280808080f000841001221929000021202002201941086a290000370300200320203703a0032019102f41ebdec700ad4280808080f0008410012219290000212020034188016a41086a220b201941086a29000037030020032020370388012019102f2008200329038801370000200841086a200b290300370000200341f8026a41086a2002290300370300200341f8026a41106a200a290300370300200341f8026a41186a2007290300370300200320032903a0033703f802200341a0036a200341f8026a412010aa024101210820032802a0032202410120021b210a4109210d41d1d5c700210e024020032902a403420020021b2220422088a7220b41014b0d0041002102200b0e022321230b200b211941002102034020022019410176220720026a2208200a20084105746a200341a8016a412010ea0641004a1b2102201920076b221941014b0d000c210b0b200141046a280200210720032002411a6a2901003703b8032003200241026a2901003703a00320032002410a6a2901003703a8032003200241126a2901003703b00320022d000041004720022d0001410147720d0b200341d0016a41186a2219200341a0036a41186a290300370300200341d0016a41106a2208200341a0036a41106a290300370300200341d0016a41086a2209200341a0036a41086a290300370300200320032903a0033703d00141c6b5c400ad4280808080f00084100122022900002106200341e8006a41086a200241086a290000370300200320063703682002102f41d8cdc500ad4280808080800184100122022900002106200341f8006a41086a200241086a290000370300200320063703782002102f4120102d2202450d20200220032903d001370000200241186a2019290300370000200241106a2008290300370000200241086a20092903003700002002ad4280808080800484100322192900002106201941086a2900002104201941106a2900002105200341f8026a41186a201941186a290000370300200341f8026a41106a2005370300200341f8026a41086a2004370300200320063703f8022019102f2002102f41c000102d2202450d2020022003290368370000200241086a200341e8006a41086a29030037000020022003290378370010200241186a200341f8006a41086a290300370000200220032903f802370020200241286a200341f8026a41086a2208290300370000200241306a200341f8026a41106a2209290300370000200241386a200341f8026a41186a220a290300370000200210dd0421192002102f0240201941ff01710d00200341a0036a41186a4200370300200341a0036a41106a220b4200370300200341a0036a41086a22024200370300200342003703a00341c6b5c400ad4280808080f0008422041001221929000021062002201941086a290000370300200320063703a0032019102f41b4dac400ad4280808080c00084220510012219290000210620034188016a41086a220c201941086a29000037030020032006370388012019102f200b20032903880122063703002008200229030037030020092006370300200a200c290300370300200320032903a0033703f802200341a0036a200341f8026a10ad0420032802a0032219410820191b210202400240200720032902a403420020191b2206422088a72208490d00410b210841ffb6c40021094103210a0c010b02402002200741e8006c6a22192d00000d004192a5c6002109410b21084100210a0c010b0240200341d0016a201941016a2219460d002019200341d0016a412010ea06450d004180a5c6002109411221084100210a0c010b41c6b5c400ad4280808080f0008410012219290000211a200341e8006a41086a201941086a2900003703002003201a3703682019102f41d8cdc500ad428080808080018410012219290000211a200341f8006a41086a201941086a2900003703002003201a3703782019102f4120102d2219450d22201920032903d001370000201941186a200341d0016a41186a290300370000201941106a200341d0016a41106a290300370000201941086a200341d0016a41086a2903003700002019ad428080808080048410032209290000211a200941086a290000211b200941106a290000211c200341f8026a41186a220a200941186a290000370300200341f8026a41106a220b201c370300200341f8026a41086a201b3703002003201a3703f8022009102f2019102f41c000102d2219450d2220192003290368370000201941086a200341e8006a41086a29030037000020192003290378370010201941186a200341f8006a41086a290300370000201920032903f802370020201941286a200341f8026a41086a290300370000201941306a200b290300370000201941386a200a2903003700002019ad428080808080088410052019102f200341a0036a2002200741e8006c6a221941e80010e8061a2019201941e8006a20082007417f736a41e8006c10e9061a20034188016a41186a20034180046a290300221a37030020034188016a41106a200341f8036a290300221b37030020034188016a41086a200341f0036a290300221c370300200320032903e803222037038801200341a0036a41086a41053a0000200341a9036a2020370000200341b1036a201c370000200341b9036a201b370000200341c1036a201a370000200341123a00a00341c8e1ca004100200341a0036a108c0120064280808080707c21064104210a0b200341f8026a41186a4200370300200341f8026a41106a220b4200370300200341f8026a41086a22194200370300200342003703f8022004100122072900002104200341e8006a41086a220c200741086a290000370300200320043703682007102f2019200c290300370300200320032903683703f8022005100122072900002104200341f8006a41086a220c200741086a290000370300200320043703782007102f200b2003290378220437030020034188016a41086a201929030037030020034188016a41106a200437030020034188016a41186a200c290300370300200320032903f802370388010240024020020d0020034188016aad428080808080048410050c010b200341a0036a20022006422088a710b10420034188016aad428080808080048420033502a80342208620032802a0032219ad841004024020032802a403450d002019102f0b2006a7450d002002102f0b200041193b00012000200a3a0000200041086a2008360200200041046a20093602000c280b20004183323b0100200041086a410b360200200041046a419eb6c400360200200041026a41093a00000c270b20012d0001211d200341f0016a200141246a280200360200200341d0016a41186a2001411c6a290200370300200341d0016a41106a200141146a290200370300200341d0016a41086a2001410c6a2902003703002003200141046a2902003703d0012002411a6a2901002106200241196a2d00002107200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241086a2d00002114200241066a2f01002115200241056a2d00002116200241046a2d00002117200241026a2f0100211841012119024020022d00000d0020022d000141014721190b2003200637039003200320073a008f03200320083a008e03200320093b018c032003200a3a008b032003200b3a008a032003200c3b0188032003200d3a0087032003200e3a0086032003200f3b018403200320103a008303200320113a008203200320123b018003200320133a00ff02200320143a00fe02200320153b01fc02200320163a00fb02200320173a00fa02200320183b01f80220190d0b200341c0026a41186a200341f8026a41186a2207290300370300200341c0026a41106a200341f8026a41106a2209290300370300200341c0026a41086a200341f8026a41086a220a290300370300200320032903f8023703c002200341a0036a41206a200341d0016a41206a280200360200200341a0036a41186a220b200341d0016a41186a290300370300200341a0036a41106a2208200341d0016a41106a290300370300200341a0036a41086a2202200341d0016a41086a290300370300200320032903d0013703a003200341f8026a200341a0036a10bb0120034188016a41086a221920034181036a29000037030020034188016a41106a220c20034189036a29000037030020034188016a41186a220d20034191036a290000370300200320032900f90237038801024002400240024002400240024020032d00f8024101460d00200341a8016a41186a200d290300370300200341a8016a41106a200c290300370300200341a8016a41086a201929030037030020032003290388013703a801200b42003703002008420037030020024200370300200342003703a00341c6b5c400ad4280808080f000841001220b29000021062002200b41086a290000370300200320063703a003200b102f418c91c700ad4280808080a001841001220b29000021062019200b41086a2900003703002003200637038801200b102f20082003290388012206370300200a20022903003703002009200637030020072019290300370300200320032903a0033703f802200341a0036a200341f8026a10ad0420032802a0032202410820021b220a20032902a403420020021b2206422088a741e8006c6a2107200a2102034020022007460d040240200341a8016a200241c8006a2219460d00201941206a21022019200341a8016a412010ea060d010b0b200341a0036a41186a22074200370300200341a0036a41106a22094200370300200341a0036a41086a22024200370300200342003703a00341c6b5c400ad4280808080f000841001221929000021042002201941086a290000370300200320043703a0032019102f41ebdec700ad4280808080f0008410012219290000210420034188016a41086a220b201941086a29000037030020032004370388012019102f2008200329038801370000200841086a200b290300370000200341f8026a41086a2002290300370300200341f8026a41106a2009290300370300200341f8026a41186a2007290300370300200320032903a0033703f802200341a0036a200341f8026a412010aa0220032802a0032202410120021b210920032902a403420020021b2204422088a7220241014b0d014100211920020e020402040b200041013a00000c2c0b41002119034020192002410176220720196a2208200920084105746a200341c0026a412010ea0641004a1b2119200220076b220241014b0d000b0b200920194105746a200341c0026a412010ea060d01201d41ff01710d02200341013a00f802200341a0036a200341a8016a200341c0026a10b20420033502a803210520032802a00321194101102d2202450d23200241013a000020054220862019ad842002ad4280808080108410042002102f20032802a403450d032019102f0c030b20004183323b0100200041086a410c360200200041046a41edb5c400360200200041026a410e3a00000c200b20004183323b0100200041086a4109360200200041046a41d1d5c700360200200041026a41013a00002004a7450d1f2009102f0c1f0b200341023a00f802200341a0036a200341a8016a200341c0026a10b20420033502a803210520032802a00321194101102d2202450d20200241023a000020054220862019ad842002ad4280808080108410042002102f20032802a403450d002019102f0b200341a0036a41086a410b3a0000200341a9036a20032903a801370000200341b1036a200341a8016a41086a290300370000200341b9036a200341a8016a41106a290300370000200341c1036a200341a8016a41186a290300370000200341c9036a20032903c002370000200341d1036a200341c0026a41086a290300370000200341d9036a200341c0026a41106a290300370000200341e1036a200341c0026a41186a290300370000200341123a00a003200341e9036a201d3a000041c8e1ca004100200341a0036a108c0102402004a7450d002009102f0b02402006a7450d00200a102f0b200041043a00000c260b20012d0001210a20032002411a6a2901003703a0012003200241026a2901003703880120032002410a6a290100370390012003200241126a2901003703980120022d00014101470d0b20022d000041ff01710d0b200341d0016a41186a20034188016a41186a290300370300200341d0016a41106a20034188016a41106a290300370300200341d0016a41086a20034188016a41086a220229030037030020032003290388013703d001200341a0036a41186a4200370300200341a0036a41106a22084200370300200341a0036a41086a22194200370300200342003703a00341c6b5c400ad4280808080f000841001220729000021062019200741086a290000370300200320063703a0032007102f41ebdec700ad4280808080f000841001220729000021062002200741086a29000037030020032006370388012007102f20082003290388012206370300200341f8026a41086a2019290300370300200341f8026a41106a2006370300200341f8026a41186a2002290300370300200320032903a0033703f802200341a0036a200341f8026a412010aa0220032802a0032202410120021b21090240024002400240024020032902a403420020021b2206422088a7220241014b0d004100211920020e020201020b41002119034020192002410176220720196a2208200920084105746a200341d0016a412010ea0641004a1b2119200220076b220241014b0d000b0b200920194105746a200341d0016a412010ea060d00200a41ff01710d01200341013a00f802200341a0036a200341d0016a10b30420033502a803210420032802a00321194101102d2202450d21200241013a000020044220862019ad842002ad4280808080108410042002102f20032802a403450d022019102f0c020b20004183323b0100200041086a4109360200200041046a41d1d5c700360200200041026a41013a00002006a7450d272009102f0c270b200341023a00f802200341a0036a200341d0016a10b30420033502a803210420032802a00321194101102d2202450d1f200241023a000020044220862019ad842002ad4280808080108410042002102f20032802a403450d002019102f0b200341a0036a41086a410c3a0000200341a9036a20032903d001370000200341b1036a200341d0016a41086a290300370000200341b9036a200341e0016a290300370000200341c1036a200341e8016a290300370000200341c9036a200a3a0000200341123a00a00341c8e1ca004100200341a0036a108c0102402006a7450d002009102f0b200041043a00000c250b20022d00000d0b20022d00014101470d0b200241196a2d00002119200241186a2d00002107200241166a2f01002108200241156a2d00002109200241146a2d0000210a200241126a2f0100210b200241116a2d0000210c200241106a2d0000210d2002410e6a2f0100210e2002410d6a2d0000210f2002410c6a2d000021102002410a6a2f01002111200241096a2d00002112200241086a2d00002113200241066a2f01002114200241056a2d00002115200241046a2d00002116200241026a2f0100211720032002411a6a2901003703e801200320193a00e701200320073a00e601200320083b01e401200320093a00e3012003200a3a00e2012003200b3b01e0012003200c3a00df012003200d3a00de012003200e3b01dc012003200f3a00db01200320103a00da01200320113b01d801200320123a00d701200320133a00d601200320143b01d401200320153a00d301200320163a00d201200320173b01d001200341a0036a41186a4200370300200341a0036a41106a220a4200370300200341a0036a41086a22024200370300200342003703a00341c6b5c400ad4280808080f000841001221929000021062002201941086a290000370300200320063703a0032019102f41ebdec700ad4280808080f0008410012219290000210620034188016a41086a2207201941086a29000037030020032006370388012019102f200a2003290388012206370300200341f8026a41086a2002290300370300200341f8026a41106a2006370300200341f8026a41186a2007290300370300200320032903a0033703f802200341a0036a200341f8026a412010aa0220032802a0032202410120021b2109024002400240024020032902a403420020021b2206422088a7220241014b0d004100211920020e020201020b41002119034020192002410176220720196a2208200920084105746a200341d0016a412010ea0641004a1b2119200220076b220241014b0d000b0b200920194105746a200341d0016a412010ea060d0041c6b5c400ad4280808080f0008410012202290000210420034188016a41086a200241086a29000037030020032004370388012002102f41f6dbc400ad4280808080f00084100122022900002104200341a0036a41086a200241086a290000370300200320043703a0032002102f4120102d2202450d1f200220032903d001370000200241186a200341d0016a41186a290300370000200241106a200341d0016a41106a290300370000200241086a200341d0016a41086a2903003700002002ad4280808080800484100322192900002104201941086a2900002105201941106a290000211a200341f8026a41186a2207201941186a290000370300200341f8026a41106a2208201a370300200341f8026a41086a2005370300200320043703f8022019102f2002102f41c000102d2202450d1f2002200329038801370000200241086a20034188016a41086a290300370000200220032903a003370010200241186a200341a0036a41086a290300370000200220032903f802370020200241286a200341f8026a41086a290300370000200241306a2008290300370000200241386a2007290300370000200341a0036a200210b70420032902a403210420032802a00321192002102f2004420020191b210402402019410820191b2202450d002004422088a7220d450d00200341a0036a41186a22084200370300200341a0036a41106a220b4200370300200341a0036a41086a22194200370300200342003703a003418de6c300ad4280808080e000841001220729000021052019200741086a290000370300200320053703a0032007102f419ce6c300ad4280808080e0008410012207290000210520034188016a41086a220c200741086a29000037030020032005370388012007102f200a200329038801370000200a41086a200c290300370000200341f8026a41086a22072019290300370300200341f8026a41106a200b290300370300200341f8026a41186a2008290300370300200320032903a0033703f802200341306a200341f8026a412010950120022802002003280234410020032802301b4d0d020b20004183323b0100200041086a4108360200200041046a41d5b6c400360200200041026a41053a000002402004a7450d002002102f0b2006a7450d262009102f0c260b20004183323b0100200041086a4109360200200041046a41d1d5c700360200200041026a41013a00000c1b0b200341a0036a10e803200341f8026a200341a0036a200341d0016a2002290308200241106a290300410110f2020240024020032d00f80222194104460d002007280200210720032802fc02210820032d00fb02210a20032d00fa02210b200020032d00f9023a0001200020193a0000200041086a2007360200200041046a2008360200200041036a200a3a0000200041026a200b3a00000c010b2002200241186a200d417f6a220741186c10e906210802402007450d0041c6b5c400ad4280808080f00084100122022d000f210a20022d000e210b20022f000c210c20022d000b210d20022d000a210e20022f0008210f20022d0007211020022d0006211120022f0004211220022d0003211320022d0002211420022f000021152002102f41f6dbc400ad4280808080f00084100122022900002105200341f8026a41086a200241086a290000370300200320053703f8022002102f4120102d2202450d1f200220032903d001370000200241186a200341d0016a41186a290300370000200241106a200341d0016a41106a290300370000200241086a200341d0016a41086a2903003700002002ad4280808080800484100322192900002105201941086a290000211a201941106a290000211b200341a0036a41186a2216201941186a290000370300200341a0036a41106a2217201b370300200341a0036a41086a201a370300200320053703a0032019102f2002102f41c000102d2202450d1f200220103a0007200220113a0006200220123b0004200220133a0003200220143a0002200220153b00002002200a3a000f2002200b3a000e2002200c3b000c2002200d3a000b2002200e3a000a2002200f3b0008200220032903f802370010200241186a200341f8026a41086a290300370000200220032903a003370020200241286a200341a0036a41086a290300370000200241306a2017290300370000200241386a2016290300370000200341c0003602a403200320023602a00320082007200341a0036a10b8042002102f02402004a7450d002008102f0b200041043a00000c1c0b41c6b5c400ad4280808080f00084100122192900002105200341e8006a41086a201941086a290000370300200320053703682019102f41f6dbc400ad4280808080f00084100122192900002105200341f8006a41086a201941086a290000370300200320053703782019102f4120102d2219450d1e201920032903d001370000201941186a200341d0016a41186a290300370000201941106a200341d0016a41106a290300370000201941086a200341d0016a41086a2903003700002019ad4280808080800484100322072900002105200741086a290000211a200741106a290000211b20034188016a41186a2208200741186a29000037030020034188016a41106a220a201b37030020034188016a41086a201a37030020032005370388012007102f2019102f41c000102d2219450d1e200442ffffffff0f83210420192003290368370000201941086a200341e8006a41086a29030037000020192003290378370010201941186a200341f8006a41086a2903003700002019200329038801370020201941286a20034188016a41086a290300370000201941306a200a290300370000201941386a20082903003700002019ad428080808080088410052019102f200041043a00000b2004a7450d1a2002102f0c1a0b200141246a2802002109200341e8016a200141196a290000370300200341e0016a200141116a290000370300200341d8016a200141096a290000370300200320012900013703d0012001412c6a2802002119200141286a28020021080240024020022d0000417f6a220741024b0d00200141306a3502002104024020070e03000102000b200241086a2802004101742002410c6a2802004d0d00200241046a28020041ff0171450d010b200041023a00000c190b20034188016a41186a420037030020034188016a41106a2202420037030020034188016a41086a22014200370300200342003703880141c6b5c400ad4280808080f00084100122072900002106200341e8006a41086a220a200741086a290000370300200320063703682007102f2001200a2903003703002003200329036837038801419ab6c400ad4280808080c00084100122072900002106200341f8006a41086a220a200741086a290000370300200320063703782007102f200220032903782206370300200341f8026a41086a2001290300370300200341f8026a41106a2006370300200341f8026a41186a200a29030037030020032003290388013703f802200341386a200341f8026a412041c8e1ca004100410010b50120032802384101460d0b20094102490d0c20034188016a41186a2207420037030020034188016a41106a220a420037030020034188016a41086a22014200370300200342003703880141c6b5c400ad4280808080f0008422051001220b2900002106200341e8006a41086a220c200b41086a29000037030020032006370368200b102f2001200c290300370300200320032903683703880141cdb5c400ad4280808080a001841001220b2900002106200341f8006a41086a220d200b41086a29000037030020032006370378200b102f20022003290378370000200241086a220b200d290300370000200341f8026a41086a220e2001290300370300200341f8026a41106a220f200a290300370300200341f8026a41186a2210200729030037030020032003290388013703f802200320093602a003200341f8026aad42808080808004842206200341a0036aad4280808080c000841004200341a0036a200341d0016a10e70420032d00a00322094104470d0d20074200370300200a42003703002001420037030020034200370388012005100122092900002105200c200941086a290000370300200320053703682009102f2001200c2903003703002003200329036837038801419ab6c400ad4280808080c00084100122092900002105200d200941086a290000370300200320053703782009102f20022003290378370000200b200d290300370000200e2001290300370300200f200a2903003703002010200729030037030020032003290388013703f8024120102d2201450d1c200120032903d001370000200141186a200341d0016a41186a220d290300370000200141106a200341d0016a41106a220e290300370000200141086a200341d0016a41086a220f29030037000020062001ad428080808080048410042001102f20034188016a41186a2209420037030020034188016a41106a220a420037030020034188016a41086a22074200370300200342003703880141c6b5c400ad4280808080f00084220510012201290000211a200341e8006a41086a220b200141086a2900003703002003201a3703682001102f2007200b29030037030020032003290368370388014193b6c400ad4280808080f0008410012201290000211a200341f8006a41086a220c200141086a2900003703002003201a3703782001102f20022003290378370000200241086a2210200c290300370000200341f8026a41086a22112007290300370300200341f8026a41106a2212200a290300370300200341f8026a41186a2213200929030037030020032003290388013703f8024120102d2201450d1c200120032903d001370000200141186a200d290300370000200141106a200e290300370000200141086a200f29030037000020062001ad428080808080048410042001102f200341a0036a41186a20044220862008ad841003220141186a290000370300200341a0036a41106a200141106a290000370300200341a0036a41086a200141086a290000370300200320012900003703a0032001102f20094200370300200a42003703002007420037030020034200370388012005100122012900002104200b200141086a290000370300200320043703682001102f2007200b290300370300200320032903683703880141c4cbc500ad4280808080d00084100122012900002104200c200141086a290000370300200320043703782001102f200220032903783700002010200c290300370000201120072903003703002012200a2903003703002013200929030037030020032003290388013703f8024120102d2202450d1c200220032903a003370000200241186a200341a0036a41186a290300370000200241106a200341a0036a41106a290300370000200241086a200341a0036a41086a220129030037000020062002ad428080808080048410042002102f200141003a0000200341a9036a20032903d001370000200341b1036a200341d0016a41086a290300370000200341b9036a200341d0016a41106a290300370000200341c1036a200341d0016a41186a290300370000200341123a00a00341c8e1ca004100200341a0036a108c01200041043a00002019450d242008102f0c240b200241026a2f01002119200241046a2d00002107200241056a2d00002108200241066a2f01002109200241086a2d0000210a200241096a2d0000210b2002410a6a2f0100210c2002410c6a2d0000210d2002410d6a2d0000210e2002410e6a2f0100210f200241106a2d00002110200241116a2d00002111200241126a2f01002112200241146a2d00002113200241156a2d00002114200241166a2f01002115200241186a2d00002116200241196a2d0000211720022d0000211d20022d0001211820032002411a6a29010022063703b803200320173a00b703200320163a00b603200320153b01b403200320143a00b303200320133a00b203200320123b01b003200320113a00af03200320103a00ae032003200f3b01ac032003200e3a00ab032003200d3a00aa032003200c3b01a8032003200b3a00a7032003200a3a00a603200320093b01a403200320083a00a303200320073a00a203200320193b01a00320184101470d0d201d41ff01710d0d20034188016a41186a221e420037030020034188016a41106a2218420037030020034188016a41086a22024200370300200342003703880141c6b5c400ad4280808080f000841001221d2900002104200341e8006a41086a221f201d41086a29000037030020032004370368201d102f2002201f29030037030020032003290368370388014193b6c400ad4280808080f000841001221d2900002104200341f8006a41086a221f201d41086a29000037030020032004370378201d102f201820032903782204370300200341f8026a41086a2002290300370300200341f8026a41106a2004370300200341f8026a41186a201f29030037030020032003290388013703f802200341a0036a200341f8026a412010ad0220032d00a003211f201e200341a0036a41196a2900003703002018200341a0036a41116a2900003703002002200341a0036a41096a290000370300200320032900a103370388014101211d02400240201f4101460d004100211d200341003a00d0010c010b200341d0016a41096a2002290300370000200341d0016a41116a2018290300370000200341d0016a41196a201e290300370000200341013a00d00120032003290388013700d1010b200341b9036a2006370000200341b8036a20173a0000200341b7036a20163a0000200341b5036a20153b0000200341b4036a20143a0000200341b3036a20133a0000200341b1036a20123b000041102102200341a0036a41106a20113a0000200341af036a20103a0000200341ad036a200f3b0000200341ac036a200e3a0000200341ab036a200d3a0000200341a9036a200c3b0000200341a8036a200b3a00002003200a3a00a703200320093b00a503200320083a00a403200320073a00a303200320193b00a103200341013a00a003201d450d15200341d0016a410172200341a0036a410172412010ea060d1520034188016a41186a221d420037030020034188016a41106a221e420037030020034188016a41086a22024200370300200342003703880141c6b5c400ad4280808080f000841001221f2900002104200341e8006a41086a2221201f41086a29000037030020032004370368201f102f200220212903003703002003200329036837038801419ab6c400ad4280808080c000841001221f2900002104200341f8006a41086a2221201f41086a29000037030020032004370378201f102f20182003290378370000201841086a2021290300370000200341f8026a41086a2002290300370300200341f8026a41106a201e290300370300200341f8026a41186a201d29030037030020032003290388013703f802200341a0036a200341f8026a412010ad0220032d00a0032121201d200341a0036a41196a290000370300201e200341a0036a41116a2900003703002002200341a0036a41096a290000370300200320032900a103370388014101211f0240024020214101460d004100211f200341003a00d0010c010b200341d0016a41096a2002290300370000200341d0016a41116a201e290300370000200341d0016a41196a201d290300370000200341013a00d00120032003290388013700d1010b200341b9036a2006370000200341b8036a20173a0000200341b7036a20163a0000200341b5036a20153b0000200341b4036a20143a0000200341b3036a20133a000041112102200341a0036a41116a20123b0000200341b0036a20113a0000200341af036a20103a0000200341ad036a200f3b0000200341ac036a200e3a0000200341ab036a200d3a0000200341a9036a200c3b0000200341a8036a200b3a00002003200a3a00a703200320093b00a503200320083a00a403200320073a00a303200320193b00a103200341013a00a00302400240201f450d00200341d0016a410172200341a0036a410172412010ea06450d010b4107211941dcb5c40021070c170b20034188016a41186a221d420037030020034188016a41106a221e420037030020034188016a41086a22024200370300200342003703880141c6b5c400ad4280808080f000842204100122212900002105200341e8006a41086a221f202141086a290000370300200320053703682021102f2002201f290300370300200320032903683703880141ebdec700ad4280808080f00084100122222900002105200341f8006a41086a2221202241086a290000370300200320053703782022102f20182003290378370000201841086a22222021290300370000200341f8026a41086a22232002290300370300200341f8026a41106a2224201e290300370300200341f8026a41186a2225201d29030037030020032003290388013703f802200341f8026aad428080808080048422051005201d4200370300201e4200370300200242003703002003420037038801200410012226290000211a201f202641086a2900003703002003201a3703682026102f2002201f2903003703002003200329036837038801419ab6c400ad4280808080c0008410012226290000211a2021202641086a2900003703002003201a3703782026102f2018200329037837000020222021290300370000202320022903003703002024201e2903003703002025201d29030037030020032003290388013703f80220051005201d4200370300201e4200370300200242003703002003420037038801200410012226290000211a201f202641086a2900003703002003201a3703682026102f2002201f29030037030020032003290368370388014193b6c400ad4280808080f0008410012226290000211a2021202641086a2900003703002003201a3703782026102f2018200329037837000020222021290300370000202320022903003703002024201e2903003703002025201d29030037030020032003290388013703f80220051005201d4200370300201e4200370300200242003703002003420037038801200410012226290000211a201f202641086a2900003703002003201a3703682026102f2002201f290300370300200320032903683703880141c4cbc500ad4280808080d0008410012226290000211a2021202641086a2900003703002003201a3703782026102f2018200329037837000020222021290300370000202320022903003703002024201e2903003703002025201d29030037030020032003290388013703f80220051005201d4200370300201e4200370300200242003703002003420037038801200410012226290000211a201f202641086a2900003703002003201a3703682026102f2002201f2903003703002003200329036837038801418c91c700ad4280808080a0018410012226290000211a2021202641086a2900003703002003201a3703782026102f2018200329037837000020222021290300370000202320022903003703002024201e2903003703002025201d29030037030020032003290388013703f80220051005201d4200370300201e42003703002002420037030020034200370388012004100122262900002104201f202641086a290000370300200320043703682026102f2002201f2903003703002003200329036837038801419cccc500ad4280808080b002841001221f29000021042021201f41086a29000037030020032004370378201f102f2018200329037837000020222021290300370000202320022903003703002024201e2903003703002025201d29030037030020032003290388013703f80220051013200341c1036a2006370000200341a0036a41206a20173a0000200341bf036a20163a0000200341bd036a20153b0000200341bc036a20143a0000200341bb036a20133a0000200341b9036a20123b0000200341a0036a41186a20113a0000200341b7036a20103a0000200341b5036a200f3b0000200341b4036a200e3a0000200341b3036a200d3a0000200341b1036a200c3b0000200341a0036a41106a200b3a0000200341af036a200a3a0000200341ad036a20093b0000200341ac036a20083a0000200341ab036a20073a0000200341a9036a20193b0000200341a0036a41086a410e3a0000200341123a00a00341c8e1ca004100200341a0036a108c01200041043a00000c220b200141216a2d00002107200341a8016a41186a200141196a290000370300200341a8016a41106a200141116a290000370300200341a8016a41086a200141096a290000370300200320012900013703a801200341a0036a41206a200241206a290200370300200341a0036a41186a200241186a290200370300200341a0036a41106a200241106a290200370300200341a0036a41086a200241086a290200370300200320022902003703a003200341d0016a200341a0036a10e80420032d00d0014101460d0d41c6b5c400ad4280808080f00084100122022900002106200341a0026a41086a200241086a290000370300200320063703a0022002102f41dfdbc400ad4280808080800284100122022900002106200341b0026a41086a200241086a290000370300200320063703b0022002102f4120102d2219450d1a201920032903a801370000201941186a200341a8016a41186a290300370000201941106a200341a8016a41106a290300370000201941086a200341a8016a41086a2903003700002019ad428080808080048410032202290018210620022d0017210820022d0016210920022f0014210a20022d0013210b20022d0012210c20022f0010210d20022d000f210e20022d000e210f20022f000c211020022d000b211120022d000a211220022f0008211320022d0007211420022d0006211520022f0004211620022d0003211720022d0002211820022f0000211d2002102f2019102f41c000102d2202450d1a200220032903a002370000200220032903b00237001020022006370038200220083a0037200220093a00362002200a3b00342002200b3a00332002200c3a00322002200d3b00302002200e3a002f2002200f3a002e200220103b002c200220113a002b200220123a002a200220133b0028200220143a0027200220153a0026200220163b0024200220173a0023200220183a00222002201d3b0020200241086a200341a0026a41086a290300370000200241186a200341b0026a41086a290300370000200341c0006a200241c00041c8e1ca004100410010b501200328024021192002102f20194101470d0e024002400240200741ff01710d0041c6b5c400ad4280808080f00084100122022d000f210820022d000e210920022f000c210a20022d000b210b20022d000a210c20022f0008210d20022d0007210e20022d0006210f20022f0004211020022d0003211120022d0002211220022f000021132002102f41f6dbc400ad4280808080f00084100122022900002106200341f8026a41086a200241086a290000370300200320063703f8022002102f4120102d2202450d1d200220032903a801370000200241186a200341a8016a41186a290300370000200241106a200341a8016a41106a290300370000200241086a200341a8016a41086a2903003700002002ad4280808080800484100322192900002106201941086a2900002104201941106a2900002105200341a0036a41186a2214201941186a290000370300200341a0036a41106a22152005370300200341a0036a41086a2004370300200320063703a0032019102f2002102f41c000102d2202450d1d2002200e3a00072002200f3a0006200220103b0004200220113a0003200220123a0002200220133b0000200220083a000f200220093a000e2002200a3b000c2002200b3a000b2002200c3a000a2002200d3b0008200220032903f802370010200241186a200341f8026a41086a2208290300370000200220032903a003370020200241286a200341a0036a41086a2219290300370000200241306a2015290300370000200241386a20142903003700002002ad428080808080088410052002102f41c6b5c400ad4280808080f0008410012202290000210620034188016a41086a200241086a29000037030020032006370388012002102f41efdbc400ad4280808080f000841001220229000021062019200241086a290000370300200320063703a0032002102f4120102d2202450d1d200220032903a801370000200241186a200341a8016a41186a290300370000200241106a200341a8016a41106a290300370000200241086a200341a8016a41086a2903003700002002ad4280808080800484100322192900002106201941086a2900002104201941106a2900002105200341f8026a41186a2209201941186a290000370300200341f8026a41106a220a200537030020082004370300200320063703f8022019102f2002102f41c000102d2202450d1d2002200329038801370000200241086a20034188016a41086a2208290300370000200220032903a003370010200241186a200341a0036a41086a290300370000200220032903f802370020200241286a200341f8026a41086a290300370000200241306a200a290300370000200241386a20092903003700002002ad428080808080088410052002102f41c6b5c400ad4280808080f00084100122022900002106200341e8006a41086a200241086a290000370300200320063703682002102f41d8cdc500ad4280808080800184100122022900002106200341f8006a41086a200241086a290000370300200320063703782002102f4120102d2202450d1d200220032903a801370000200241186a200341a8016a41186a290300370000200241106a200341a8016a41106a290300370000200241086a200341a8016a41086a2903003700002002ad4280808080800484100322192900002106201941086a2900002104201941106a290000210520034188016a41186a2209201941186a29000037030020034188016a41106a220a20053703002008200437030020032006370388012019102f2002102f41c000102d2202450d1d20022003290368370000200241086a200341e8006a41086a29030037000020022003290378370010200241186a200341f8006a41086a2903003700002002200329038801370020200241286a20034188016a41086a290300370000200241306a200a290300370000200241386a2009290300370000200210dd0441ff017122194102470d012002102f0c020b200341a0036a200341a8016a10e70420032d00a00322024104460d01200341a0036a41086a280200211920032802a403210720032d00a303210820032d00a2032109200020032d00a1033a0001200020023a0000200041086a2019360200200041046a2007360200200041036a20083a0000200041026a20093a00000c230b2002ad428080808080088410052002102f20190d00200341a0036a41186a220f4200370300200341a0036a41106a220d4200370300200341a0036a41086a220c4200370300200342003703a00341c6b5c400ad4280808080f000842204100122022900002106200c200241086a290000370300200320063703a0032002102f41b4dac400ad4280808080c00084220510012202290000210620034188016a41086a2219200241086a29000037030020032006370388012002102f200d2003290388012206370300200341f8026a41086a220e200c290300370300200341f8026a41106a2006370300200341f8026a41186a2019290300370300200320032903a0033703f802200341a0036a200341f8026a10ad0420032802a0032202410820021b2109024020032902a403420020021b2206422088a72210450d00201041037441786a41037641016a210a2009417f73200341a8016a6a210b4100210241002119024003400240200920026a22082d0000450d00200b2002460d02200841016a200341a8016a412010ea06450d020b200241e8006a2102200a201941016a2219470d000c020b0b200341a0036a200841e80010e8061a2008200841e8006a201041e8006c20026b41987f6a10e9061a200341e8016a20034180046a290300221a370300200341e0016a200341f8036a290300221b370300200341d0016a41086a200341f0036a290300221c370300200320032903e80322203703d001200341a0036a41086a41053a0000200341a9036a2020370000200341b1036a201c370000200341b9036a201b370000200341c1036a201a370000200341123a00a00341c8e1ca004100200341a0036a108c0120064280808080707c21060b200341d0016a41186a4200370300200341d0016a41106a22084200370300200341d0016a41086a22024200370300200342003703d0012004100122192900002104200e201941086a290000370300200320043703f8022019102f2002200e290300370300200320032903f8023703d0012005100122192900002104200341c0026a41086a220a201941086a290000370300200320043703c0022019102f200820032903c0022204370300200c2002290300370300200d2004370300200f200a290300370300200320032903d0013703a003024020090d00200341a0036aad428080808080048410050c010b200341d0016a20092006422088a710b104200341a0036aad428080808080048420033502d80142208620032802d0012202ad841004024020032802d401450d002002102f0b2006a7450d002009102f0b41c6b5c400ad4280808080f00084100122022900002106200341f8026a41086a200241086a290000370300200320063703f8022002102f41dfdbc400ad4280808080800284100122022900002106200341c0026a41086a200241086a290000370300200320063703c0022002102f4120102d2202450d1a200220032903a801370000200241186a200341a8016a41186a2208290300370000200241106a200341a8016a41106a2209290300370000200241086a200341a8016a41086a2903003700002002ad4280808080800484100322192900002106201941086a2900002104201941106a2900002105200341a0036a41186a220a201941186a290000370300200341a0036a41106a220b2005370300200341a0036a41086a2004370300200320063703a0032019102f2002102f41c000102d2202450d1a200220032903f802370000200241086a200341f8026a41086a290300370000200220032903c002370010200241186a200341c0026a41086a290300370000200220032903a003370020200241286a200341a0036a41086a2219290300370000200241306a200b290300370000200241386a200a2903003700002002ad428080808080088410052002102f201941073a0000200341a9036a20032903a801370000200341b1036a200341a8016a41086a290300370000200341b9036a2009290300370000200341c1036a2008290300370000200341c9036a20073a0000200341123a00a00341c8e1ca004100200341a0036a108c01200041043a00000c210b200141216a2d00002108200341a8016a41186a200141196a290000370300200341a8016a41106a200141116a290000370300200341a8016a41086a200141096a290000370300200320012900013703a801200341a0036a41206a200241206a290200370300200341a0036a41186a200241186a290200370300200341a0036a41106a200241106a290200370300200341a0036a41086a200241086a290200370300200320022902003703a003200341d0016a200341a0036a10e80420032d00d0014101460d0e41c6b5c400ad4280808080f00084100122022d000f210720022d000e210920022f000c210a20022d000b210b20022d000a210c20022f0008210d20022d0007210e20022d0006210f20022f0004211020022d0003211120022d0002211220022f000021132002102f419cccc500ad4280808080b0028410012202290008210620022d0007211420022d0006211520022f0004211620022d0003211720022d0002211820022f0000211d2002102f4120102d2219450d19201920032903a801370000201941186a200341a8016a41186a290300370000201941106a200341a8016a41106a290300370000201941086a200341a8016a41086a2903003700002019ad428080808080048410032202290018210420022d0017211e20022d0016211f20022f0014212120022d0013212220022d0012212320022f0010212420022d000f212520022d000e212620022f000c212720022d000b212820022d000a212920022f0008212a20022d0007212b20022d0006212c20022f0004212d20022d0003212e20022d0002212f20022f000021302002102f2019102f41c000102d2202450d19200220043700382002201e3a00372002201f3a0036200220213b0034200220223a0033200220233a0032200220243b0030200220253a002f200220263a002e200220273b002c200220283a002b200220293a002a2002202a3b00282002202b3a00272002202c3a00262002202d3b00242002202e3a00232002202f3a0022200220303b002020022006370018200220143a0017200220153a0016200220163b0014200220173a0013200220183a00122002201d3b0010200220073a000f200220093a000e2002200a3b000c2002200b3a000b2002200c3a000a2002200d3b00082002200e3a00072002200f3a0006200220103b0004200220113a0003200220123a0002200220133b0000200341c0003602a402200320023602a002200341f8026a2002ad4280808080800884100210730240024020032802f80222070d00410221190c010b20032802fc02210f2003200341f8026a41086a28020022193602b402200320073602b00202400240024020194110490d002003201941706a3602b4022003200741106a3602b002200741086a290000210620072900002104200341a0036a200341b0026a10c30420032d00a00322194102470d010b200341003602d801200342013703d0012003410b36028c012003200341a0026a360288012003200341d0016a360278200341b4036a4101360200200342013702a403200341b885c7003602a003200320034188016a3602b003200341f8006a41d8dbc100200341a0036a103c1a20033502d80142208620033502d001841008024020032802d401450d0020032802d001102f0b410221190c010b200341d0016a41086a200341c0036a290300370300200320032800a40336008b01200320032800a103360288012003200341b8036a2903003703d0012004423888200642088684a721092004423088200642108684a7210a2004422088a7210b2004421888a7210c2004421088a7210d200341b0036a290300211a200341a0036a41086a2903002105200341d0036a290300211b200341c8036a290300211c2004a7210e0b200f450d002007102f0b200341f8026a41086a2207200341d0016a41086a29030037030020032003280288013602a0032003200328008b013600a303200320032903d0013703f8020240024020194102470d000c010b200341c0026a41086a2007290300370300200320032800a3033600e302200320032802a0033602e002200320032903f8023703c0022009ad423886200aad42ff018342308684200bad42ffff038342208684200cad42ff018342188684200dad42ff018342108684200ead42ffff03838421040b2002102f02400240024020194102460d00200341a0026a41086a2202200341c0026a41086a290300370300200320032802e0023602e802200320032800e3023600eb02200320032903c0023703a0020240024020084103710e03030100030b41c6b5c400ad4280808080f00084100122022900002120200229000821312002102f41e4d8c400ad42808080803084100122022900002132200229000821332002102f200320333701b803200320323701b003200320313701a803200320203701a003200341d0006a200341a0036a4120109c0120032903584200200328025022021b22312004542207200341e0006a290300420020021b222020065420202006511b0d13200341a0036a200341a8016a10e704200341a0036a41086a2102024020032d00a00322084104470d0041c6b5c400ad4280808080f000842232100122082900002133200829000821342008102f41e4d8c400ad42808080803084100122082900002135200829000821362008102f200320363701b803200320353701b003200320343701a803200320333701a0032003202020067d2007ad7d3703d8012003203120047d3703d001200341a0036aad4280808080800484200341d0016aad42808080808002841004200341a0036a41186a220a4200370300200341a0036a41106a2207420037030020024200370300200342003703a003418de6c300ad4280808080e000841001220829000021202002200841086a290000370300200320203703a0032008102f419ce6c300ad4280808080e0008410012209290000212020034188016a41086a2208200941086a29000037030020032020370388012009102f20072003290388012220370300200341f8026a41086a220b2002290300370300200341f8026a41106a220c2020370300200341f8026a41186a220d2008290300370300200320032903a0033703f802200341c8006a200341f8026a4120109501200328024c210e2003280248210f200a42003703002007420037030020024200370300200342003703a00320321001220929000021202002200941086a290000370300200320203703a0032009102f41ebdec700ad4280808080f000841001220929000021202008200941086a29000037030020032020370388012009102f20072003290388012220370300200b2002290300370300200c2020370300200d2008290300370300200320032903a0033703f802200341a0036a200341f8026a412010aa0220032902a403420020032802a00322021b2220422088a741f4036a2207450d15200341e4003a00a103200341e40041d0860320076e22076b3a00a003200e4100200f1b2108200341a0036a200741ff017141e4004b6a2d00004180fe126c210702402020a7450d002002410120021b102f0b200720086a2107200341b0026a41086a2202200341a0026a41086a290300370300200320032802e8023602f002200320032800eb023600f302200320032903a0023703b0020240024020194101470d00200341af036a201a370000200341bf036a20022d00003a0000200320053700a703200320032800f3023600a303200320032802f0023602a003200320032903b0023700b70341c6b5c400ad4280808080f00084100122022900002105200341e8006a41086a200241086a290000370300200320053703682002102f41d8cdc500ad4280808080800184100122022900002105200341f8006a41086a200241086a290000370300200320053703782002102f4120102d2202450d20200220032903a003370000200241186a200341a0036a41186a290300370000200241106a200341a0036a41106a290300370000200241086a200341a0036a41086a2903003700002002ad4280808080800484100322192900002105201941086a290000211a201941106a290000212020034188016a41186a2208201941186a29000037030020034188016a41106a2209202037030020034188016a41086a220a201a37030020032005370388012019102f2002102f41c000102d2202450d2020022003290368370000200241086a200341e8006a41086a29030037000020022003290378370010200241186a200341f8006a41086a2903003700002002200329038801370020200241286a200a290300370000200241306a2009290300370000200241386a20082903003700000240200210dd0441ff017122194102470d002002102f0c020b2002ad428080808080088410052002102f20190d01200341a0036a20072004201c2004201c5422022006201b542006201b511b22191b2006201b20191b10b00442002006201b7d2002ad7d22052004201c7d221a200456200520065620052006511b22021b21064200201a20021b21040c010b200320053703f8022003201a370380032005201a84500d002003200341a8016a36028801200341d0016a200341a8016a200341f8026a20034188016a10960120032903d0014201520d0020032903d8012105200341d8036a200341d0016a41106a290300370300200341d0036a2005370300200341a0036a41086a41003a0000200341a9036a20032903a801370000200341b1036a200341a8016a41086a290300370000200341b9036a200341a8016a41106a290300370000200341c1036a200341c0016a290300370000200341033a00a00341c8e1ca004100200341a0036a108c010b200341a8016a20072004200610b0040c040b2002280200210220032802a403211920032d00a303210720032d00a2032109200020032d00a1033a0001200020083a0000200041086a2002360200200041046a2019360200200041036a20073a0000200041026a20093a00000c240b02402019410171450d00200341d0016a41086a2219200341a0026a41086a2d00003a0000200320032802e8023602b002200320032800eb023600b302200320032903a0023703d00141c6b5c400ad4280808080f0008410012202290000210620034188016a41086a200241086a29000037030020032006370388012002102f41d8cdc500ad4280808080800184100122022900002106200341a0036a41086a200241086a290000370300200320063703a0032002102f4120102d2202450d1d20022005370007200220032802b002360000200220032903d0013700172002410f6a201a370000200241036a20032800b3023600002002411f6a20192d00003a00002002ad4280808080800484100322192900002106201941086a2900002104201941106a2900002105200341f8026a41186a2207201941186a290000370300200341f8026a41106a22082005370300200341f8026a41086a2004370300200320063703f8022019102f2002102f41c000102d2202450d1d2002200329038801370000200241086a20034188016a41086a290300370000200220032903a003370010200241186a200341a0036a41086a290300370000200220032903f802370020200241286a200341f8026a41086a290300370000200241306a2008290300370000200241386a20072903003700004101102d2219450d1d201941013a00002002ad42808080808008842019ad4280808080108410042019102f2002102f0c030b200341a0036a41bcd9c40010b402200341d0016a200341a8016a200341a0036a2005201a410010bc010c020b20004183323b0100200041086a410c360200200041046a41ddb6c400360200200041026a41043a00000c220b200341a0036a41186a220a4200370300200341a0036a41106a22084200370300200341a0036a41086a22074200370300200342003703a00341c6b5c400ad4280808080f000841001220929000021202007200941086a290000370300200320203703a0032009102f41b4dac400ad4280808080c0008410012209290000212020034188016a41086a220b200941086a29000037030020032020370388012009102f20082003290388012220370300200341f8026a41086a2007290300370300200341f8026a41106a2020370300200341f8026a41186a200b290300370300200320032903a0033703f802200341a0036a200341f8026a10ad04200320032902a403420020032802a00322091b3702d40120032009410820091b3602d0012008201a37030020072005370300200341d0036a201b370300200341c8036a201c370300200a20032903a002370300200341c0036a2002290300370300200320193a00a003200320032802e8023600a103200320032800eb023600a403200341d0016a200341a8016a20042006200341a0036a10e6040b200341a0036a41186a2207200341a8016a41186a290300370300200341a0036a41106a2208200341a8016a41106a290300370300200341a0036a41086a2209200341a8016a41086a290300370300200320032903a8013703a00341c6b5c400ad4280808080f00084100122022d000f210a20022d000e210b20022f000c210c20022d000b210d20022d000a210e20022f0008210f20022d0007211020022d0006211120022f0004211220022d0003211320022d0002211420022f000021152002102f419cccc500ad4280808080b0028410012202290008210620022d0007211620022d0006211720022f0004211820022d0003211d20022d0002211e20022f0000211f2002102f4120102d2219450d19201920032903a003370000201941186a2007290300370000201941106a2008290300370000201941086a20092903003700002019ad428080808080048410032202290018210420022d0017210720022d0016210820022f0014210920022d0013212120022d0012212220022f0010212320022d000f212420022d000e212520022f000c212620022d000b212720022d000a212820022f0008212920022d0007212a20022d0006212b20022f0004212c20022d0003212d20022d0002212e20022f0000212f2002102f2019102f41c000102d2202450d1920022004370038200220073a0037200220083a0036200220093b0034200220213a0033200220223a0032200220233b0030200220243a002f200220253a002e200220263b002c200220273a002b200220283a002a200220293b00282002202a3a00272002202b3a00262002202c3b00242002202d3a00232002202e3a00222002202f3b002020022006370018200220163a0017200220173a0016200220183b00142002201d3a00132002201e3a00122002201f3b00102002200a3a000f2002200b3a000e2002200c3b000c2002200d3a000b2002200e3a000a2002200f3b0008200220103a0007200220113a0006200220123b0004200220133a0003200220143a0002200220153b00002002ad428080808080088410052002102f200041043a00000c200b20022d000120022d0000410047720d100240200141046a28020022024102490d0020034188016a41186a420037030020034188016a41106a2208420037030020034188016a41086a22194200370300200342003703880141c6b5c400ad4280808080f00084100122072900002106200341e8006a41086a2209200741086a290000370300200320063703682007102f20192009290300370300200320032903683703880141cdb5c400ad4280808080a00184100122072900002106200341f8006a41086a2209200741086a290000370300200320063703782007102f200820032903782206370300200341f8026a41086a2019290300370300200341f8026a41106a2006370300200341f8026a41186a200929030037030020032003290388013703f802200320023602a003200341f8026aad4280808080800484200341a0036aad4280808080c000841004200341ac036a2002360200200341a0036a41086a410d3a0000200341123a00a00341c8e1ca004100200341a0036a108c01200041043a00000c200b20004183323b0100200041086a410a360200200041046a41cdb5c400360200200041026a410f3a00000c1f0b200041023a00000c1e0b200041023a00000c1d0b20004183323b0100200041086a4109360200200041046a41e9b6c400360200200041026a41033a00000c1c0b200041023a00000c1b0b200041023a00000c1a0b200041023a00000c190b200041023a00000c180b20004183323b0100200041086a410e360200200041046a41c7b6c400360200200041026a41063a00000c0c0b20004183323b0100200041086a410a360200200041046a41cdb5c400360200200041026a410f3a00000c0b0b200341a0036a41086a280200210220032802a403210120032d00a303210720032d00a203210a200020032d00a1033a0001200020093a0000200041086a2002360200200041046a2001360200200041036a20073a0000200041026a200a3a00000c0a0b200041023a00000c140b200041023a00000c130b20004183323b0100200041086a410c360200200041046a41ddb6c400360200200041026a41043a00000c120b200041023a00000c110b20004183323b0100200041086a410f360200200041046a41b8b6c400360200200041026a41073a00000c100b4180d9c4004119419cd9c4001039000b200041023a00000c0e0b20004183323b0100200041086a4109360200200041046a41e9b6c400360200200041026a41033a00000c0d0b410a211941e3b5c40021070b20004183323b0100200041086a2019360200200041046a2007360200200041026a20023a00000c0b0b2019450d0b2008102f0c0b0b2006a7450d092009102f0c090b2006a7450d08200a102f0c080b0240200a20024105746a200341a8016a412010ea060d00410d210d41f2b6c400210e410221080c020b4101210802400240200b41014b0d0041002102200b0e020301030b4100210203402002200b410176221920026a2207200a20074105746a200341d0016a412010ea0641004a1b2102200b20196b220b41014b0d000b0b200a20024105746a200341d0016a412010ea060d0141c6b5c400ad4280808080f00084100122022900002131200341a0026a41086a200241086a290000370300200320313703a0022002102f41d8cdc500ad4280808080800184100122022900002131200341b0026a41086a200241086a290000370300200320313703b0022002102f4120102d2219450d00201920032903d001370000201941186a200341d0016a41186a290300370000201941106a200341d0016a41106a290300370000201941086a200341d0016a41086a2903003700002019ad428080808080048410032202290018213120022d0017210720022d0016210820022f0014210b20022d0013210d20022d0012210e20022f0010210f20022d000f211020022d000e211120022f000c211220022d000b211320022d000a211420022f0008211520022d0007211620022d0006211720022f0004211820022d0003211d20022d0002211e20022f0000211f2002102f2019102f41c000102d2202450d00200220032903a002370000200220032903b00237001020022031370038200220073a0037200220083a00362002200b3b00342002200d3a00332002200e3a00322002200f3b0030200220103a002f200220113a002e200220123b002c200220133a002b200220143a002a200220153b0028200220163a0027200220173a0026200220183b00242002201d3a00232002201e3a00222002201f3b002041082108200241086a200341a0026a41086a290300370000200241186a200341b0026a41086a290300370000200341186a200241c00041c8e1ca004100410010b501200328021821192002102f024020194101470d00410f210d41a9b6c400210e0c020b41c6b5c400ad4280808080f00084100122022900002131200341e8006a41086a200241086a290000370300200320313703682002102f41d8cdc500ad4280808080800184100122022900002131200341f8006a41086a200241086a290000370300200320313703782002102f4120102d2202450d00200220032903d001370000200241186a200341d0016a41186a290300370000200241106a200341d0016a41106a290300370000200241086a200341d0016a41086a2903003700002002ad4280808080800484100322192900002131201941086a2900002132201941106a290000213320034188016a41186a2207201941186a29000037030020034188016a41106a2208203337030020034188016a41086a203237030020032031370388012019102f2002102f41c000102d2202450d0020022003290368370000200241086a200341e8006a41086a29030037000020022003290378370010200241186a200341f8006a41086a2903003700002002200329038801370020200241286a20034188016a41086a290300370000200241306a2008290300370000200241386a20072903003700004101102d2219450d00201941003a00002002ad42808080808008842019ad4280808080108410042019102f2002102f200320063702fc02200320093602f802200341a0036a41306a201a370300200341b9036a2202200341d0016a41186a2219290300370000200341b1036a2207200341d0016a41106a2208290300370000200341a9036a2209200341d0016a41086a220b2903003700002003201b3703c803200320032903d0013700a103200341013a00a003200341f8026a200341a8016a20052004200341a0036a10e604200341f8036a2004370300200341f0036a2005370300200341a0036a41086a41023a0000200920032903a8013700002007200341a8016a41086a2903003700002002200341a8016a41106a290300370000200341c1036a200341a8016a41186a290300370000200341c9036a20032903d001370000200341d1036a200b290300370000200341d9036a2008290300370000200341e1036a2019290300370000200341123a00a00341c8e1ca004100200341a0036a108c01200041043a000002402020a7450d00200a102f0b201ca7450d07200c102f0c070b1036000b20004183323b0100200041086a200d360200200041046a200e360200200041026a20083a00002020a7450d00200a102f0b201ca7450d00200c102f0b2006a7450d032009102f0c030b201ba7450d00200a102f0b201aa7450d00200b102f0b2006a7450d002009102f0b20012d00004108470d002001412c6a280200450d00200141286a280200102f0b200341a0046a24000bfd0102027f027e2000280240210202404104102d2203450d002003200236000020002d0044210220034104410810312203450d00200320023a0004200041086a29030021042000290300210520034108411510312203450d00200320053700052003410d6a2004370000200041186a29030021042000290310210520034115412a10312203450d00200320053700152003411d6a2004370000200041286a2903002104200029032021052003412a41d40010312203450d00200320053700252003412d6a2004370000200320002903303700352003413d6a200041386a29030037000020012902002003ad4280808080d0088410042003102f0f0b1036000b830301037f230041206b2203240002400240200241c4006c41046a2204417f4c0d000240024020040d00410121050c010b2004102d2205450d020b20034100360208200320043602042003200536020020022003106902402002450d00200241c4006c210203400240024020012d00004101460d00200341003a00102003200341106a41011082012003200141046a2802003602102003200341106a41041082010c010b200341013a00102003200341106a41011082014120102d2204450d042003422037021420032004360210200341106a200141016a412010820120032802142104200320032802102205200328021810820102402004450d002005102f0b0240200141216a2d00004101460d00200341003a00102003200341106a41011082010c010b200341013a00102003200341106a41011082012003200141226a41201082010b200141c4006a2101200241bc7f6a22020d000b0b20002003290300370200200041086a200341086a280200360200200341206a24000f0b103d000b1036000bc00801027f02402000280200220141194b0d0002400240024002400240024002400240024002400240024002400240024002400240024020010e1a0001121202121203040506070809120a0b0c0d0e1212120f1011000b200041086a1096030f0b200041046a1095030f0b02402000410c6a2802002201450d00200141f0006c2102200028020441046a2101034020011097010240200141046a280200450d002001280200102f0b200141f0006a2101200241907f6a22020d000b0b200041086a280200450d0f2000280204102f0f0b200041086a1094030f0b20002802042201450d0d200041086a280200450d0d2001102f0f0b200041086a2d0000416d6a220141014b0d0c0240024020010e020001000b200041106a280200450d0d2000410c6a280200102f0f0b200041106a280200450d0c2000410c6a280200102f0f0b20002d0004417f6a220141024b0d0b02400240024020010e03000102000b2000412c6a280200450d0d200041286a280200102f0f0b200041086a22012802001092032001280200102f0f0b2000410c6a22012802001092032001280200102f0f0b20002d0004417f6a220141024b0d0a02400240024020010e03000102000b2000412c6a280200450d0c200041286a280200102f0f0b200041086a22012802001092032001280200102f0f0b2000410c6a22012802001092032001280200102f0f0b200041086a2802004101470d09200041106a280200450d092000410c6a280200102f0f0b20002d00044104470d082000410c6a280200450d08200041086a280200102f0f0b200041086a280200450d072000280204102f0f0b200041086a2d0000417c6a220141024b0d060240024020010e03000801000b200041306a280200450d072000412c6a280200102f0f0b200041306a280200450d062000412c6a280200102f0f0b200041086a2d0000417e6a220141024b0d0502400240024020010e03000102000b200041106a280200450d072000410c6a280200102f0c070b200041346a280200450d06200041306a280200102f0f0b200041306a280200450d052000412c6a280200102f0f0b02402000280204220141024b0d00024020010e03060006060b200041086a22012802001092032001280200102f0f0b2000412c6a22012802001092032001280200102f0f0b02402000410c6a280200450d00200041086a280200102f0b02402000411c6a2802002202450d00200041146a28020021012002410c6c210203400240200141046a280200450d002001280200102f0b2001410c6a2101200241746a22020d000b0b200041186a280200450d032000280214102f0f0b200041086a1093030f0b200041086a2d00004108470d01200041346a280200450d01200041306a280200102f0f0b20002d0004417f6a220141024b0d000240024020010e03000201000b200041286a22012802001092032001280200102f0f0b2000410c6a280200450d00200041086a280200102f0f0b0bb20401027f024020002d0000417e6a220141014b0d000240024020010e020001000b02402000410c6a2802002202450d00200041046a2802002201200241c8006c6a21020340024020012d00004101470d00200141086a280200450d00200141046a280200102f0b0240200141246a2d00004101470d002001412c6a280200450d00200141286a280200102f0b200141c8006a22012002470d000b0b0240200041086a280200450d002000280204102f0b0240200041106a2d00004101470d00200041186a280200450d00200041146a280200102f0b0240200041346a2d00004101470d002000413c6a280200450d00200041386a280200102f0b0240200041d8006a2d00004101470d00200041e0006a280200450d00200041dc006a280200102f0b0240200041fc006a2d00004101470d0020004184016a280200450d0020004180016a280200102f0b0240200041a0016a2d00004101470d00200041a8016a280200450d00200041a4016a280200102f0b0240200041c4016a2d00004101470d00200041cc016a280200450d00200041c8016a280200102f0b200041e8016a2d00004101470d01200041f0016a280200450d01200041ec016a280200102f0c010b02402000410c6a2802002201450d00200141c4006c2102200041046a28020041286a210103400240200141786a2d00004101470d002001280200450d002001417c6a280200102f0b200141c4006a2101200241bc7f6a22020d000b0b200041086a280200450d002000280204102f0f0b0b8c0101017f024020002d0000417a6a2201410b4b0d00024002400240024020010e0c000404040404040104040203000b200041086a280200450d03200041046a280200102f0c030b200041086a280200450d02200041046a280200102f0f0b2000410c6a280200450d01200041086a280200102f0f0b2000410c6a280200450d00200041086a280200102f0f0b0bea0101027f0240024020002d0000220141044b0d00024002400240024020010e050500010203050b02402000410c6a2802002202450d00200041046a2802002101200241b0026c210203402001108d01200141b0026a2101200241d07d6a22020d000b0b200041086a280200450d042000280204102f0f0b200041046a22012802001092032001280200102f0f0b0240200041086a280200450d00200041046a280200102f0b2000411c6a22012802001092032001280200102f0f0b200041286a280200450d01200041246a280200102f0c010b200041286a280200450d00200041246a280200102f0f0b0bcc0201027f02402000280200417e6a220141074b0d0002400240024002400240024020010e080006010206030405000b200041086a280200450d052000280204102f0f0b200041086a280200450d042000280204102f0f0b200041086a280200450d032000280204102f0c030b02402000410c6a2802002202450d0020002802042101200241186c210203400240200141046a280200450d002001280200102f0b0240200141106a280200450d002001410c6a280200102f0b200141186a2101200241686a22020d000b0b200041086a280200450d022000280204102f0f0b02402000410c6a2802002202450d00200028020421012002410c6c210203400240200141046a280200450d002001280200102f0b2001410c6a2101200241746a22020d000b0b200041086a280200450d012000280204102f0f0b200041086a280200450d002000280204102f0f0b0bb80303047f017e047f230041f0046b22022400200241086a200110e601024002400240024002402002280208450d00200041003602000c010b200228020c2203200128020441b0026e2204200420034b1b2205ad42b0027e2206422088a70d012006a72204417f4c0d010240024020040d00410821070c010b2004102d2207450d03200441b0026e21050b024002402003450d004100210841002104410021090340200241c0026a200110b30220022802c002411b460d02200941016a210a200241106a200241c0026a41b00210e8061a024020092005470d002008200a2008200a4b1bad42b0027e2206422088a70d072006a722054100480d070240024020090d002005102d21070c010b200720042005103121070b2007450d06200541b0026e21050b200720046a200241106a41b00210e8061a200841026a2108200441b0026a2104200a21092003200a470d000b0b2000200536020420002007360200200041086a20033602000c010b2000410036020002402009450d002007210a0340200a108d01200a41b0026a210a200441d07d6a22040d000b0b2005450d002007102f0b200241f0046a24000f0b103d000b1036000b1038000bb004010a7f230041d0006b220224002002200110e60102400240024002402002280200450d00200041003602000c010b2002280204220320012802044105762204200420034b1b22054105742204417f4c0d010240024020050d00410121060c010b2004102d2206450d030b02402003450d00410021070340200241003a00482007220841016a21072001280204417f6a21044100210902400240024003402004417f460d01200241286a20096a2001280200220a2d00003a0000200120043602042001200a41016a3602002002200941016a220a3a00482004417f6a2104200a2109200a4120470d000b200241086a41186a2209200241286a41186a290300370300200241086a41106a220a200241286a41106a290300370300200241086a41086a220b200241286a41086a2903003703002002200229032837030820052008470d020240200841017422042007200420074b1b220441ffffff3f712004470d002004410574220441004e0d020b1038000b0240200941ff0171450d00200241003a00480b200041003602002005450d042006102f0c040b0240024020080d002004102d21060c010b200620084105742004103121060b2006450d05200441057621050b200620084105746a22042002290308370000200441186a2009290300370000200441106a200a290300370000200441086a200b29030037000020072003470d000b0b2000200536020420002006360200200041086a20033602000b200241d0006a24000f0b103d000b1036000bb50404057f017e017f017e0240024020012802042202450d00200128020022032d0000210420012002417f6a22053602042001200341016a3602000240200441037122064103460d00024002400240024020060e03000102000b2004410276ad21070c020b41012106024020050d000c050b20032d0001210520012002417e6a3602042001200341026a3602002005410874200472220141ffff0371418002490d04200141fcff0371410276ad21070c010b410121060240200541034f0d000c040b200341036a2d0000210520032f0001210820012002417c6a3602042001200341046a3602002008200541107472410874200472220141808004490d032001410276ad21070b410021060c020b02402004410276220841044b0d000240024020080e050002020201000b20054104490d022003350001210720012002417b6a3602042001200341056a36020020074280808080045421060c030b20054108490d01200329000121072001200241776a3602042001200341096a3602002007428080808080808080015421060c020b200841046a220541084b0d002002417e6a2102200341026a2103410021044200210741012106034002402002417f470d000c030b2003417f6a310000210920012002360204200120033602002002417f6a2102200341016a210320092004410374413871ad862007842107200441016a220441ff01712005490d000b2007427f412820084103746b413871ad885821060c010b410121060b2000200737030820002006ad3703000bce0303047f017e047f230041f0016b22022400200241086a200110e601024002400240024002402002280208450d00200041003602000c010b200228020c2203200128020441f0006e2204200420034b1b2205ad42f0007e2206422088a70d012006a72204417f4c0d010240024020040d00410421070c010b2004102d2207450d03200441f0006e21050b024002402003450d00410021084100210441002109034020024180016a200110f603200228028401450d02200941016a210a200241106a20024180016a41f00010e8061a024020092005470d002008200a2008200a4b1bad42f0007e2206422088a70d072006a722054100480d070240024020090d002005102d21070c010b200720042005103121070b2007450d06200541f0006e21050b200720046a200241106a41f00010e8061a200841026a2108200441f0006a2104200a21092003200a470d000b0b2000200536020420002007360200200041086a20033602000c010b2000410036020002402009450d00200741046a210a0340200a1097010240200a41046a280200450d00200a280200102f0b200a41f0006a210a200441907f6a22040d000b0b2005450d002007102f0b200241f0016a24000f0b103d000b1036000b1038000bf30601067f230041f0006b2102024002400240024002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a2206360204410121072001200441016a360200200541f001490d06200541847e6a220541034b0d0120050e0402030405020b200041023a00000f0b200041023a00000f0b20064102490d0420042f0001210520012003417d6a3602042001200441036a3602000240200541ef014d0d00410121070c040b200041023a00000f0b20064104490d042004280001210520012003417b6a3602042001200441056a36020041012107200541ffff034b0d02200041023a00000f0b024020064104490d00200041023a000020012003417b6a3602042001200441056a3602000f0b200041023a00000f0b41002105200241003a00682003417f6a21062003417e6a210302400240034020062005460d01200241c8006a20056a200420056a220741016a2d00003a0000200120033602042001200741026a3602002002200541016a22073a00682003417f6a21032007210520074120470d000b200241c6006a20022d004a3a0000200241306a200241d7006a290000370300200241386a200241df006a290000370300200241c0006a200241e7006a2d00003a0000200220022f01483b01442002200229004f370328200228004b2105410021010c010b0240200541ff0171450d00200241003a00680b410121010b200241246a41026a2203200241c4006a41026a2d00003a0000200241086a41086a2207200241286a41086a290300370300200241086a41106a2204200241286a41106a290300370300200241086a41186a2206200241286a41186a2d00003a0000200220022f01443b01242002200229032837030820010d03200241286a41026a20032d00003a0000200241c8006a41086a2007290300370300200241c8006a41106a2004290300370300200241c8006a41186a20062d00003a0000200220022f01243b012820022002290308370348410021070b200020073a0000200020022f01283b0001200041046a2005360200200041086a2002290348370200200041036a2002412a6a2d00003a0000200041106a200241c8006a41086a290300370200200041186a200241c8006a41106a290300370200200041206a200241c8006a41186a2802003602000f0b200041023a00000f0b200041023a00000f0b200041023a00000bde0506067f017e017f017e017f017e230041206b220224000240024020012802042203450d00200128020022042d0000210520012003417f6a22063602042001200441016a360200024002400240200541037122074103460d0002400240024020070e03000102000b2005410276ad21080c040b410121072006450d0220042d0001210620012003417e6a3602042001200441026a3602002006410874200572220141ffff0371418002490d02200141fcff0371410276ad21080c030b4101210720064103490d01200441036a2d0000210620042f0001210920012003417c6a3602042001200441046a3602002009200641107472410874200572220141808004490d012001410276ad21080c020b024020054102762209410c4b0d0002400240024020090e0d00030303010303030303030302000b20064104490d052004350001210820012003417b6a3602042001200441056a36020020084280808080045421074200210a0c060b20064108490d04200429000121082001200341776a3602042001200441096a3602002008428080808080808080015421074200210a0c050b20064110490d03200441096a290000210a2004290001210820012003416f6a3602042001200441116a360200200a428080808080808080015421070c040b200941046a220641104b0d022003417e6a2103200441026a21044100210541012107200241186a210b420021084200210a03402003417f460d01200241106a2004417f6a3100004200200541037441f8007110eb0620012003360204200120043602002003417f6a2103200441016a2104200b290300200a84210a20022903102008842108200541016a220541ff01712006490d000b2002427f427f41e80020094103746b41f8007110ec062008200229030058200a200241086a290300220c58200a200c511b21070c030b0c020b4200210a410021070c010b410121070b20002008370308200041106a200a37030020002007ad370300200241206a24000bd10f02097f047e230041d0056b220224000240024002400240024002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a3602042001200441016a360200200541044b0d0620050e050102030405010b200041063a00000c090b200241a0036a2001109803024020022802a0032206450d0020022802a4032107024020012802042203450d00200241a8036a2802002108200128020022042d0000210520012003417f6a3602042001200441016a360200200541014b0d004100210902400240024020050e020100010b41002105200241003a00c0032003417f6a210a2003417e6a21030340200a2005460d02200241a0036a20056a200420056a220941016a2d00003a0000200120033602042001200941026a3602002002200541016a22093a00c0032003417f6a21032009210520094120470d000b200241f0006a41186a200241a0036a41186a290300370300200241f0006a41106a200241a0036a41106a290300370300200241f0006a41086a200241a0036a41086a290300370300200220022903a003370370410121090b200241206a41186a200241f0006a41186a290300220b370300200241206a41106a200241f0006a41106a290300220c370300200241206a41086a200241f0006a41086a290300220d37030020022002290370220e370320200020093a0001200041013a0000200041026a200e3700002000410a6a200d370000200041126a200c3700002000411a6a200b3700002000412c6a2008360100200041286a2007360100200041246a20063601000c0b0b200541ff0171450d00200241003a00c0030b200041063a00002007450d092006102f0c090b200041063a00000c080b200241f0006a200110b302024002402002280270411b460d00200241a0036a200241f0006a41b00210e8061a41b002102d22010d010c080b200041063a00000c080b2001200241a0036a41b00210e8062101200041023a0000200020022f00503b0001200041036a200241d0006a41026a2d00003a0000200041046a2001360200200041086a2002290220370200200041106a200241206a41086a290200370200200041186a200241206a41106a290200370200200041206a200241206a41186a290200370200200041286a200241206a41206a2902003702000c070b200241086a200110e601024020022802080d00200228020c2105200241f0006a200110b3022002280270411b460d00200241a0036a200241f0006a41b00210e8061a41b002102d2201450d062001200241a0036a41b00210e8062101200041033a0000200020022f00503b0001200041036a200241d2006a2d00003a0000200041086a2001360200200041046a20053602002000410c6a2002290220370200200041146a200241206a41086a2902003702002000411c6a200241306a290200370200200041246a200241386a2902003702002000412c6a200241c0006a2802003602000c070b200041063a00000c060b41002105200241003a00c0032003417f6a210a2003417e6a210302400240024002400340200a2005460d01200241a0036a20056a200420056a220941016a2d00003a0000200120033602042001200941026a3602002002200541016a22093a00c0032003417f6a21032009210520094120470d000b200241206a41086a200241a0036a41086a290300370300200241206a41106a200241a0036a41106a290300370300200241206a41186a200241a0036a41186a290300370300200220022903a003370320200241106a200110e60120022802100d0120012802042203450d0120022802142104200128020022092d0000210520012003417f6a3602042001200941016a360200200541014b0d014100210120050e020302030b200541ff0171450d00200241003a00c0030b200041063a00000c070b410121010b200241d0006a41186a200241206a41186a290300220b370300200241d0006a41106a200241206a41106a290300220c370300200241d0006a41086a200241206a41086a290300220d37030020022002290320220e370350200041043a00002000200e370001200041096a200d370000200041116a200c370000200041196a200b370000200041246a2004360200200041216a20013a00000c050b41002105200241003a00c0032003417f6a210a2003417e6a210302400340200a2005460d01200241a0036a20056a200420056a220941016a2d00003a0000200120033602042001200941026a3602002002200541016a22093a00c0032003417f6a21032009210520094120470d000b200241206a41086a2205200241a0036a41086a290300370300200241206a41106a2203200241a0036a41106a290300370300200241206a41186a2209200241a0036a41186a290300370300200220022903a003370320200241186a200110e6012002280218450d020c030b200541ff0171450d02200241003a00c0030c020b200041063a00000c030b200228021c2101200241d0006a41186a2009290300220b370300200241d0006a41106a2003290300220c370300200241d0006a41086a2005290300220d37030020022002290320220e370350200041053a00002000200e370001200041096a200d370000200041116a200c370000200041196a200b370000200041216a20022f004d3b0000200041236a200241cf006a2d00003a0000200041246a20013602000c020b200041063a00000c010b1036000b200241d0056a24000bfa0602047f047e230041b0056b22022400024002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a3602042001200441016a360200200541024b0d0320050e03010204010b200041043602000c050b200241d0006a200110b302024002402002280250411b460d0020024180036a200241d0006a41b00210e8061a41b002102d22010d010c050b200041043602000c050b2000200120024180036a41b00210e80636020420004101360200200041086a2002290228370200200041106a200241286a41086a290200370200200041186a200241286a41106a290200370200200041206a200241286a41186a290200370200200041286a200241286a41206a2802003602000c040b20024180036a2001109b03024020022d0080034102460d00200241d0006a41206a20024180036a41206a2802002201360200200241d0006a41186a20024180036a41186a2903002206370300200241d0006a41106a20024180036a41106a2903002207370300200241d0006a41086a20024180036a41086a29030022083703002002200229038003220937035020004102360200200020093702042000410c6a2008370200200041146a20073702002000411c6a2006370200200041246a20013602000c040b200041043602000c030b200041043602000c020b20024180036a2001109b03024020022d0080034102470d00200041043602000c020b200241286a41206a20024180036a41206a280200360200200241286a41186a20024180036a41186a290300370300200241286a41106a20024180036a41106a290300370300200241286a41086a20024180036a41086a2903003703002002200229038003370328200241d0006a200110b30202402002280250411b460d0020024180036a200241d0006a41b00210e8061a41b002102d2201450d01200120024180036a41b00210e8062101200241206a200241286a41206a2802002205360200200241186a200241286a41186a2903002206370300200241106a200241286a41106a2903002207370300200241086a200241286a41086a290300220837030020022002290328220937030020004103360200200020093702042000410c6a2008370200200041146a20073702002000411c6a2006370200200041246a2005360200200041286a20013602000c020b200041043602000c010b1036000b200241b0056a24000b8d1e03077f047e017f230041e0056b2202240002400240024002400240024002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a3602042001200441016a360200200541084b0d0a20050e09010203040506070809010b2000410a3a00000c0a0b41002105200241003a00d0032003417f6a21062003417e6a2107024002400240034020062005460d01200241b0036a20056a200420056a220841016a2d00003a0000200120073602042001200841026a3602002002200541016a22083a00d0032007417f6a21072008210520084120470d000b200241c0006a41086a200241b0036a41086a290300370300200241c0006a41106a200241b0036a41106a290300370300200241c0006a41186a200241b0036a41186a290300370300200220022903b00337034020024180016a200110b302200228028001411b460d01200241b0036a20024180016a41b00210e8061a41b002102d22010d021036000b200541ff0171450d00200241003a00d0030b2000410a3a00000c0a0b2001200241b0036a41b00210e8062101200241206a41186a200241c0006a41186a2903002209370300200241206a41106a200241c0006a41106a290300220a370300200241206a41086a200241c0006a41086a290300220b37030020022002290340220c370320200041013a00002000200c370001200041096a200b370000200041116a200a370000200041196a2009370000200041216a20022f001d3b0000200041236a2002411f6a2d00003a0000200041246a2001360200200041286a2002290200370200200041306a200241086a290200370200200041386a200241106a290200370200200041c0006a200241186a2802003602000c090b41002105200241003a00d003410120036b21062003417e6a21070240024002400340200620056a450d01200241b0036a20056a200420056a220841016a2d00003a0000200120073602042001200841026a3602002002200541016a22083a00d0032007417f6a21072008210520084120470d000b20024180016a41086a200241b0036a41086a29030037030020024180016a41106a200241b0036a41106a29030037030020024180016a41186a200241b0036a41186a290300370300200220022903b0033703800141002105200241003a00d003200420086a2106200820036b41016a21080340200820056a450d02200241b0036a20056a200620056a220441016a2d00003a0000200120073602042001200441026a3602002002200541016a22043a00d0032007417f6a21072004210520044120470d000b200241206a41086a2201200241b0036a41086a290300370300200241206a41106a2204200241b0036a41106a290300370300200241206a41186a2205200241b0036a41186a290300370300200241c0006a41086a220720024180016a41086a290300370300200241c0006a41106a220820024180016a41106a290300370300200241c0006a41186a220320024180016a41186a290300370300200220022903b0033703202002200229038001370340200041023a000020002002290340370001200041096a2007290300370000200041116a2008290300370000200041196a2003290300370000200041216a2002290320370000200041296a2001290300370000200041316a2004290300370000200041396a2005290300370000200041c1006a20022f00003b0000200041c3006a200241026a2d00003a00000c0b0b200541ff0171450d01200241003a00d0030c010b200541ff0171450d00200241003a00d0030b2000410a3a00000c080b20024180016a20011098030240024002402002280280012204450d002002280284012105200128020422074102490d0120024188016a2802002106200128020022082f0000210d20012007417e6a22033602042001200841026a36020020034104490d022008280002210320012007417a6a3602042001200841066a360200200041106a20033602002000410c6a2006360200200041086a2005360200200041046a2004360200200041026a200d3b0100200041033a0000200041146a20022902b0033702002000411c6a200241b0036a41086a290200370200200041246a200241b0036a41106a2902003702002000412c6a200241c8036a290200370200200041346a200241d0036a2902003702002000413c6a200241d8036a2902003702000c0a0b2000410a3a00000c090b2000410a3a00002005450d082004102f0c080b2000410a3a00002005450d072004102f0c070b41002105200241003a00a0012003417f6a21062003417e6a21070240034020062005460d0120024180016a20056a200420056a220841016a2d00003a0000200120073602042001200841026a3602002002200541016a22083a00a0012007417f6a21072008210520084120470d000b200241c0006a41086a20024180016a41086a2903002209370300200241c0006a41106a20024180016a41106a290300220a370300200241c0006a41186a20024180016a41186a290300220b3703002002200229038001220c370340200041043a00002000200c370001200041096a2009370000200041116a200a370000200041196a200b370000200041216a20022900b003370000200041296a200241b0036a41086a290000370000200041316a200241b0036a41106a290000370000200041396a200241b0036a41186a290000370000200041c0006a200241cf036a2800003600000c070b0240200541ff0171450d00200241003a00a0010b2000410a3a00000c060b41002105200241003a00d003410120036b21062003417e6a21070240024002400340200620056a450d01200241b0036a20056a200420056a220841016a2d00003a0000200120073602042001200841026a3602002002200541016a22083a00d0032007417f6a21072008210520084120470d000b20024180016a41086a200241b0036a41086a29030037030020024180016a41106a200241b0036a41106a29030037030020024180016a41186a200241b0036a41186a290300370300200220022903b0033703800141002105200241003a00d003200420086a2106200820036b41016a21080340200820056a450d02200241b0036a20056a200620056a220441016a2d00003a0000200120073602042001200441026a3602002002200541016a22043a00d0032007417f6a21072004210520044120470d000b200241206a41086a2201200241b0036a41086a290300370300200241206a41106a2204200241b0036a41106a290300370300200241206a41186a2205200241b0036a41186a290300370300200241c0006a41086a220720024180016a41086a290300370300200241c0006a41106a220820024180016a41106a290300370300200241c0006a41186a220320024180016a41186a290300370300200220022903b0033703202002200229038001370340200041053a000020002002290340370001200041096a2007290300370000200041116a2008290300370000200041196a2003290300370000200041216a2002290320370000200041296a2001290300370000200041316a2004290300370000200041396a2005290300370000200041c1006a20022f00003b0000200041c3006a200241026a2d00003a00000c080b200541ff0171450d01200241003a00d0030c010b200541ff0171450d00200241003a00d0030b2000410a3a00000c050b41002105200241003a00a0012003417f6a21062003417e6a21070240034020062005460d0120024180016a20056a200420056a220841016a2d00003a0000200120073602042001200841026a3602002002200541016a22083a00a0012007417f6a21072008210520084120470d000b200241c0006a41086a20024180016a41086a2903002209370300200241c0006a41106a20024180016a41106a290300220a370300200241c0006a41186a20024180016a41186a290300220b3703002002200229038001220c370340200041063a00002000200c370001200041096a2009370000200041116a200a370000200041196a200b370000200041216a20022900b003370000200041296a200241b0036a41086a290000370000200041316a200241b0036a41106a290000370000200041396a200241b0036a41186a290000370000200041c0006a200241cf036a2800003600000c050b0240200541ff0171450d00200241003a00a0010b2000410a3a00000c040b41002105200241003a00a0012003417f6a21062003417e6a21070240034020062005460d0120024180016a20056a200420056a220841016a2d00003a0000200120073602042001200841026a3602002002200541016a22083a00a0012007417f6a21072008210520084120470d000b200241c0006a41086a20024180016a41086a2903002209370300200241c0006a41106a20024180016a41106a290300220a370300200241c0006a41186a20024180016a41186a290300220b3703002002200229038001220c370340200041073a00002000200c370001200041096a2009370000200041116a200a370000200041196a200b370000200041216a20022900b003370000200041296a200241b0036a41086a290000370000200041316a200241b0036a41106a290000370000200041396a200241b0036a41186a290000370000200041c0006a200241cf036a2800003600000c040b0240200541ff0171450d00200241003a00a0010b2000410a3a00000c030b200041083a00000c020b41002105200241003a00a0012003417f6a21062003417e6a21070240034020062005460d0120024180016a20056a200420056a220841016a2d00003a0000200120073602042001200841026a3602002002200541016a22083a00a0012007417f6a21072008210520084120470d000b200241c0006a41086a20024180016a41086a2903002209370300200241c0006a41106a20024180016a41106a290300220a370300200241c0006a41186a20024180016a41186a290300220b3703002002200229038001220c370340200041093a00002000200c370001200041096a2009370000200041116a200a370000200041196a200b370000200041216a20022900b003370000200041296a200241b0036a41086a290000370000200041316a200241b0036a41106a290000370000200041396a200241b0036a41186a290000370000200041c0006a200241cf036a2800003600000c020b0240200541ff0171450d00200241003a00a0010b2000410a3a00000c010b2000410a3a00000b200241e0056a24000b892f010e7f230041d0006b22012400024002404108102d2202450d002002410c3602042002418aa9c4003602004108102d2203450d00200320022902003702002002102f4108102d2202450d002002410c36020420024196a9c40036020020034108411010312203450d00200320022902003702082002102f4108102d2202450d0020024108360204200241a2a9c40036020020034110412010312204450d00200420022902003702102002102f4108102d2202450d002002410a360204200241aaa9c400360200200420022902003702182002102f4108102d2203450d002003410b360204200341b4a9c4003602002004412041c00010312202450d00200220032902003702202003102f4108102d2203450d0020034118360204200341f2b3c600360200200220032902003702282003102f4108102d2203450d002003411236020420034189cdc100360200200220032902003702302003102f41d400102d2205450d0041002106024020022802002203450d002005200228020436020820052003360204200541003602000240200228020822030d00410121060c010b2005200228020c360214200520033602102005410036020c0240200228021022030d00410221060c010b200520022802143602202005200336021c200541003602180240200228021822030d00410321060c010b2005200228021c36022c20052003360228200541003602240240200228022022030d00410421060c010b2005200228022436023820052003360234200541003602300240200228022822030d00410521060c010b2005200228022c360244200520033602402005410036023c0240200228023022030d00410621060c010b200520022802343602502005200336024c20054100360248410721060b2002102f20014100360228200142013703204104102d2202450d0020014284808080c00037022420012002360220200241edcad18b0636000002400240200128022420012802282202460d00200128022021030c010b200241016a22032002490d02200241017422042003200420034b1b22044100480d020240024020020d002004102d21030c010b200128022020022004103121030b2003450d0120012004360224200120033602200b2001200241016a360228200320026a410b3a0000411c200141206a106941e8acc300210703402007280204210820072802082204200141206a10690240024020012802242202200128022822096b2004490d00200128022021030c010b200920046a22032009490d032002410174220a2003200a20034b1b220a4100480d030240024020020d00200a102d21030c010b20012802202002200a103121030b2003450d022001200a36022420012003360220200a21020b2001200920046a220a360228200320096a2008200410e8061a02400240200728020c4102470d0002402002200a470d00200241016a22042002490d05200241017422092004200920044b1b22044100480d050240024020020d002004102d21030c010b200320022004103121030b2003450d0420012004360224200120033602200b2001200a41016a3602282003200a6a41003a00000c010b02402002200a470d00200241016a22042002490d04200241017422092004200920044b1b22044100480d040240024020020d002004102d21030c010b200320022004103121030b2003450d0320012004360224200120033602200b2001200a41016a3602282003200a6a41013a00000240200728020c4101470d002007280214210920072802182202200141206a10690240024020012802242204200128022822036b2002490d00200128022021040c010b200320026a220a2003490d0520044101742208200a2008200a4b1b220a4100480d050240024020040d00200a102d21040c010b20012802202004200a103121040b2004450d042001200a360224200120043602200b2001200320026a360228200420036a2009200210e8061a200728022021020240200728021c4101470d0020022007280228200141206a106b0c020b2002200741246a280200200141206a106b0c010b200141306a20072802101105002001280234210920012802382202200141206a10690240024020012802242204200128022822036b2002490d00200128022021040c010b200320026a220a2003490d0420044101742208200a2008200a4b1b220a4100480d040240024020040d00200a102d21040c010b20012802202004200a103121040b2004450d032001200a360224200120043602200b2001200320026a360228200420036a2009200210e8061a200128024021040240200128023c4101460d0020042001280244200141206a106b0c010b200420012802482202200141206a106b02402002450d00200241d8006c21094100210303400240200420036a220241346a280200450d002002413c6a280200450d00200241386a280200102f0b0240200241c4006a280200450d00200241cc006a280200450d00200241c8006a280200102f0b2009200341d8006a2203470d000b0b2001280244450d002004102f0b200128022421032001280228210202400240200728022c4102470d000240024020032002460d00200128022021030c010b200241016a22032002490d05200241017422042003200420034b1b22044100480d050240024020020d002004102d21030c010b200128022020022004103121030b2003450d0420012004360224200120033602200b2001200241016a360228200320026a41003a00000c010b0240024020032002460d00200128022021030c010b200241016a22032002490d04200241017422042003200420034b1b22044100480d040240024020020d002004102d21030c010b200128022020022004103121030b2003450d0320012004360224200120033602200b2001200241016a360228200320026a41013a00000240200728022c4101470d002007280230210320072802382202200141206a10692002450d012002412c6c210a2003411c6a21020340200241686a28020021082002416c6a2802002203200141206a10690240024020012802242209200128022822046b2003490d00200128022021090c010b200420036a220b2004490d062009410174220c200b200c200b4b1b220b4100480d060240024020090d00200b102d21090c010b20012802202009200b103121090b2009450d052001200b360224200120093602200b2001200420036a360228200920046a2008200310e8061a200241706a200141206a106a2002200141206a10682002412c6a2102200a41546a220a0d000c020b0b200141186a200728023011050020012802182103200128021c2202200141206a10692002450d002002412c6c210a2003411c6a21020340200241686a28020021082002416c6a2802002203200141206a10690240024020012802242209200128022822046b2003490d00200128022021090c010b200420036a220b2004490d052009410174220c200b200c200b4b1b220b4100480d050240024020090d00200b102d21090c010b20012802202009200b103121090b2009450d042001200b360224200120093602200b2001200420036a360228200920046a2008200310e8061a200241706a200141206a106a2002200141206a10682002412c6a2102200a41546a220a0d000b0b200128022421032001280228210202400240200728023c4102470d000240024020032002460d00200128022021030c010b200241016a22032002490d05200241017422042003200420034b1b22044100480d050240024020020d002004102d21030c010b200128022020022004103121030b2003450d0420012004360224200120033602200b2001200241016a360228200320026a41003a00000c010b0240024020032002460d00200128022021030c010b200241016a22032002490d04200241017422042003200420034b1b22044100480d040240024020020d002004102d21030c010b200128022020022004103121030b2003450d0320012004360224200120033602200b2001200241016a360228200320026a41013a00000240200728023c4101470d002007280240210320072802482202200141206a10692002450d012002412c6c210a2003411c6a21020340200241686a28020021082002416c6a2802002203200141206a10690240024020012802242209200128022822046b2003490d00200128022021090c010b200420036a220b2004490d062009410174220c200b200c200b4b1b220b4100480d060240024020090d00200b102d21090c010b20012802202009200b103121090b2009450d052001200b360224200120093602200b2001200420036a360228200920046a2008200310e8061a200241706a200141206a10682002200141206a10682002412c6a2102200a41546a220a0d000c020b0b200141106a20072802401105002001280210210320012802142202200141206a10692002450d002002412c6c210a2003411c6a21020340200241686a28020021082002416c6a2802002203200141206a10690240024020012802242209200128022822046b2003490d00200128022021090c010b200420036a220b2004490d052009410174220c200b200c200b4b1b220b4100480d050240024020090d00200b102d21090c010b20012802202009200b103121090b2009450d042001200b360224200120093602200b2001200420036a360228200920046a2008200310e8061a200241706a200141206a10682002200141206a10682002412c6a2102200a41546a220a0d000b0b02400240200728024c4101470d002007280250210c20072802582202200141206a10692002450d01200241386c210d410021090340200c20096a220241046a2802002108200241086a2802002203200141206a1069024002402001280224220a200128022822046b2003490d002001280220210a0c010b200420036a220b2004490d06200a410174220e200b200e200b4b1b220b4100480d0602400240200a0d00200b102d210a0c010b2001280220200a200b1031210a0b200a450d052001200b3602242001200a3602200b2001200420036a360228200a20046a2008200310e8061a200241106a2802002108200241146a2802002203200141206a1069024002402001280224220a200128022822046b2003490d002001280220210a0c010b200420036a220b2004490d06200a410174220e200b200e200b4b1b220b4100480d0602400240200a0d00200b102d210a0c010b2001280220200a200b1031210a0b200a450d052001200b3602242001200a3602200b2001200420036a360228200a20046a2008200310e8061a02400240200241186a2802004101470d002002411c6a2802002108200241246a2802002203200141206a1069024002402001280224220a200128022822046b2003490d002001280220210a0c010b200420036a220b2004490d08200a410174220e200b200e200b4b1b220b4100480d0802400240200a0d00200b102d210a0c010b2001280220200a200b1031210a0b200a450d072001200b3602242001200a3602200b2001200420036a360228200a20046a2008200310e8061a0c010b200141306a2002411c6a280200200241206a28020028020c1102002001280230210820012802382203200141206a1069024002402001280224220a200128022822046b2003490d002001280220210a0c010b200420036a220b2004490d07200a410174220e200b200e200b4b1b220b4100480d0702400240200a0d00200b102d210a0c010b2001280220200a200b1031210a0b200a450d062001200b3602242001200a3602200b2001200420036a360228200a20046a2008200310e8061a2001280234450d002008102f0b200241286a200141206a1068200d200941386a2209470d000c020b0b200141086a20072802501105002001280208210c200128020c2202200141206a10692002450d00200241386c210d410021090340200c20096a220241046a2802002108200241086a2802002203200141206a1069024002402001280224220a200128022822046b2003490d002001280220210a0c010b200420036a220b2004490d05200a410174220e200b200e200b4b1b220b4100480d0502400240200a0d00200b102d210a0c010b2001280220200a200b1031210a0b200a450d042001200b3602242001200a3602200b2001200420036a360228200a20046a2008200310e8061a200241106a2802002108200241146a2802002203200141206a1069024002402001280224220a200128022822046b2003490d002001280220210a0c010b200420036a220b2004490d05200a410174220e200b200e200b4b1b220b4100480d0502400240200a0d00200b102d210a0c010b2001280220200a200b1031210a0b200a450d042001200b3602242001200a3602200b2001200420036a360228200a20046a2008200310e8061a02400240200241186a2802004101470d002002411c6a2802002108200241246a2802002203200141206a1069024002402001280224220a200128022822046b2003490d002001280220210a0c010b200420036a220b2004490d07200a410174220e200b200e200b4b1b220b4100480d0702400240200a0d00200b102d210a0c010b2001280220200a200b1031210a0b200a450d062001200b3602242001200a3602200b2001200420036a360228200a20046a2008200310e8061a0c010b200141306a2002411c6a280200200241206a28020028020c1102002001280230210820012802382203200141206a1069024002402001280224220a200128022822046b2003490d002001280220210a0c010b200420036a220b2004490d06200a410174220e200b200e200b4b1b220b4100480d0602400240200a0d00200b102d210a0c010b2001280220200a200b1031210a0b200a450d052001200b3602242001200a3602200b2001200420036a360228200a20046a2008200310e8061a2001280234450d002008102f0b200241286a200141206a1068200d200941386a2209470d000b0b02400240200728025c4101470d002007280260210320072802682202200141206a10692002450d012002411c6c210a2003410c6a21020340200241786a28020021082002417c6a2802002203200141206a10690240024020012802242209200128022822046b2003490d00200128022021090c010b200420036a220b2004490d062009410174220c200b200c200b4b1b220b4100480d060240024020090d00200b102d21090c010b20012802202009200b103121090b2009450d052001200b360224200120093602200b2001200420036a360228200920046a2008200310e8061a2002200141206a10682002411c6a2102200a41646a220a0d000c020b0b200120072802601105002001280200210320012802042202200141206a10692002450d002002411c6c210a2003410c6a21020340200241786a28020021082002417c6a2802002203200141206a10690240024020012802242209200128022822046b2003490d00200128022021090c010b200420036a220b2004490d052009410174220c200b200c200b4b1b220b4100480d050240024020090d00200b102d21090c010b20012802202009200b103121090b2009450d042001200b360224200120093602200b2001200420036a360228200920046a2008200310e8061a2002200141206a10682002411c6a2102200a41646a220a0d000b0b200741ec006a220741b8c4c300470d000b02400240200128022420012802282202460d00200128022021030c010b200241016a22032002490d02200241017422042003200420034b1b22044100480d020240024020020d002004102d21030c010b200128022020022004103121030b2003450d0120012004360224200120033602200b2001200241016a360228200320026a41043a00002006200141206a106902402006450d002006410c6c210a200541086a210303402003417c6a280200210820032802002202200141206a10690240024020012802242209200128022822046b2002490d00200128022021090c010b200420026a22072004490d042009410174220b2007200b20074b1b22074100480d040240024020090d002007102d21090c010b200128022020092007103121090b2009450d0320012007360224200120093602200b2001200420026a360228200920046a2008200210e8061a2003410c6a2103200a41746a220a0d000b0b20002001290320370200200041086a200141206a41086a2802003602002005102f200141d0006a24000f0b1036000b1038000ba00b01057f230041106b22022400200141046a2802002103200141086a2802002104024002400240024020002d00004101460d000240024020032004460d00200128020021050c010b200441016a22032004490d04200441017422052003200520034b1b22034100480d040240024020040d002003102d21050c010b200128020020042003103121050b2005450d0320012005360200200141046a2003360200200141086a28020021040b200141086a2206200441016a36020041002103200520046a41003a000002400240024002400240024002400240024020002d00010e080700010203040506070b200241013a000f410121030c070b410221030c050b410321030c040b410421030c030b410521030c020b410621030c010b200241073a000f02400240200141046a28020020062802002204460d00200128020021030c010b200441016a22032004490d06200441017422052003200520034b1b22054100480d060240024020040d002005102d21030c010b200128020020042005103121030b2003450d0520012003360200200141046a2005360200200141086a28020021040b200141086a200441016a360200200320046a41073a000020002d000221030b200220033a000f0b02400240200141046a280200200141086a2802002204460d00200128020021000c010b200441016a22002004490d04200441017422052000200520004b1b22054100480d040240024020040d002005102d21000c010b200128020020042005103121000b2000450d0320012000360200200141046a2005360200200141086a28020021040b200141086a200441016a360200200020046a20033a00000c010b0240024020032004460d00200128020021030c010b200441016a22032004490d03200441017422052003200520034b1b22054100480d030240024020040d002005102d21030c010b200128020020042005103121030b2003450d0220012003360200200141046a2005360200200141086a28020021040b200141086a200441016a360200200320046a41013a000020002d0001220441024b0d0002400240024020040e03000102000b02400240200141046a280200200141086a2802002204460d00200128020021000c010b200441016a22002004490d05200441017422032000200320004b1b22034100480d050240024020040d002003102d21000c010b200128020020042003103121000b2000450d0420012000360200200141046a2003360200200141086a28020021040b200141086a200441016a360200200020046a41003a00000c020b02400240200141046a280200200141086a2802002204460d00200128020021000c010b200441016a22002004490d04200441017422032000200320004b1b22034100480d040240024020040d002003102d21000c010b200128020020042003103121000b2000450d0320012000360200200141046a2003360200200141086a28020021040b200141086a200441016a360200200020046a41013a00000c010b02400240200141046a280200200141086a2802002204460d00200128020021030c010b200441016a22032004490d03200441017422052003200520034b1b22054100480d030240024020040d002005102d21030c010b200128020020042005103121030b2003450d0220012003360200200141046a2005360200200141086a28020021040b200141086a2205200441016a360200200320046a41023a000020002d0002210302400240200141046a28020020052802002204460d00200128020021000c010b200441016a22002004490d03200441017422052000200520004b1b22054100480d030240024020040d002005102d21000c010b200128020020042005103121000b2000450d0220012000360200200141046a2005360200200141086a28020021040b200141086a200441016a360200200020046a20033a00000b200241106a24000f0b1036000b1038000beb0f03057f017e077f230041e0006b2202240020012802202103200241306a41186a4200370300200241306a41106a22044200370300200241306a41086a2205420037030020024200370330419c9eca00ad4280808080f000841001220629000021072005200641086a290000370300200220073703302006102f41a5c6c800ad4280808080a00184100122062900002107200241d0006a41086a2208200641086a290000370300200220073703502006102f200420022903502207370300200241106a41086a2005290300370300200241106a41106a2007370300200241106a41186a200829030037030020022002290330370310200241306a200241106a412010aa0220022802302205410120051b2106024002400240024002400240024002400240024020032002290234420020051b2207422088a7490d002007a7450d012006102f0c010b2003200620034105746a10a303210302402007a7450d002006102f0b20030d010b200241306a41186a22054200370300200241306a41106a22064200370300200241306a41086a2203420037030020024200370330419c9eca00ad4280808080f000841001220829000021072003200841086a290000370300200220073703302008102f41a39eca00ad4280808080c00184100122082900002107200241d0006a41086a2209200841086a290000370300200220073703502008102f20042002290350370000200441086a22082009290300370000200241106a41086a220a2003290300370300200241106a41106a220b2006290300370300200241106a41186a220c200529030037030020022002290330370310200241086a200241106a4120109501200128021c200228020c410020022802081b220d470d012005420037030020064200370300200342003703002002420037033041d39bca00ad42808080808001841001220e29000021072003200e41086a29000037030020022007370330200e102f419087ca00ad4280808080c000841001220e29000021072009200e41086a29000037030020022007370350200e102f2004200229035037000020082009290300370000200a2003290300370300200b2006290300370300200c200529030037030020022002290330370310200241306a200241106a108d0320022802302204410120041b210c200128022022052002290234420020041b2207422088a74f0d03200c20054105746a220e450d032002410036023820024201370330200128020021034104102d22040d020c070b20004180063b0001200041013a0000200041036a41003a00000c050b20004180063b0001200041013a0000200041036a41003a00000c040b20024284808080c0003702342002200436023020042003360000200128020421082001410c6a2802002204200241306a10690240024020022802342206200228023822036b2004490d00200228023021060c010b200320046a22092003490d032006410174220a2009200a20094b1b22094100480d030240024020060d002009102d21060c010b200228023020062009103121060b2006450d0520022009360234200220063602300b2002200320046a360238200620036a2008200410e8061a200141106a2802002103200141186a2802002204200241306a10690240024020040d002002280234210620022802382109200d21080c010b20032004410c6c6a210b03402003280200210a200341086a2802002204200241306a10690240024020022802342206200228023822056b2004490d00200228023021080c010b200520046a22082005490d05200641017422092008200920084b1b22094100480d050240024020060d002009102d21080c010b200228023020062009103121080b2008450d072002200936023420022008360230200921060b2002200520046a2209360238200820056a200a200410e8061a2003410c6a2203200b470d000b20012802202105200128021c21080b02400240200620096b4104490d00200941046a2103200228023021040c010b200941046a22032009490d03200641017422042003200420034b1b220a4100480d030240024020060d00200a102d21040c010b20022802302006200a103121040b2004450d052002200a36023420022004360230200a21060b20022003360238200420096a200836000002400240200620036b41034d0d00200621080c010b200341046a22082003490d03200641017422092008200920084b1b22084100480d030240024020060d002008102d21040c010b200420062008103121040b2004450d0520022008360234200220043602300b200420036a2005360000200141246a200341046aad4220862004ad84200e1014210302402008450d002004102f0b20034101460d010b20004180083b0001200041013a0000200041036a41003a00002007a7450d02200c102f0c020b410c102d2203450d024104102d2204450d022004200d36000020044104412410312204450d022004200e2900003700042004411c6a200e41186a290000370000200441146a200e41106a2900003700002004410c6a200e41086a290000370000200041306a41013a0000200041286a428180808010370200200041246a2003360200200041206a4100360200200041186a4204370300200041106a42e400370300200041086a427f370300200342a4808080c00437020420032004360200200041316a2002280030360000200041346a200241336a280000360000200041003a00002007a7450d01200c102f0c010b1038000b200241e0006a24000f0b1036000b870b04057f017e047f037e230041f0006b22022400200241386a41186a22034200370300200241386a41106a22044200370300200241386a41086a2205420037030020024200370338419c9eca00ad4280808080f000841001220629000021072005200641086a290000370300200220073703382006102f41a39eca00ad4280808080c00184100122062900002107200241d8006a41086a2208200641086a290000370300200220073703582006102f200420022903582207370300200241186a41086a22092005290300370300200241186a41106a2007370300200241186a41186a200829030037030020022002290338370318200241106a200241186a41201095012002280214210a2002280210210b41d39bca00ad42808080808001841001220629000021072009200641086a290000370300200220073703182006102f41db9bca00ad4280808080a002841001220629000021072008200641086a290000370300200220073703582006102f2002200a4100200b1b220a36026c200241ec006aad220c4280808080c00084100322062900002107200641086a290000210d200641106a290000210e2003200641186a2900003703002004200e3703002005200d370300200220073703382006102f024041c000102d2206450d00200620022903183700002006200229035837001020062002290338370020200641086a2009290300370000200641186a2008290300370000200641286a2005290300370000200641306a2004290300370000200641386a200329030037000020022000360218200241186aad4280808080c00084100322082900002107200841086a290000210d200841106a290000210e2003200841186a2900003703002004200e3703002005200d370300200220073703382008102f200641c00041800110312206450d0020062002290338370040200641d8006a200241386a41186a2204290300370000200641d0006a200241386a41106a2208290300370000200641c8006a200241386a41086a2203290300370000200241086a200641e00041c8e1ca004100410010b501200228020821052006102f41012106024020054101460d0041d39bca00ad4280808080800184100122062900002107200241d8006a41086a200641086a290000370300200220073703582006102f4194c9c300ad4280808080e00184100122062900002107200241186a41086a200641086a290000370300200220073703182006102f2002200a36026c200c4280808080c00084100322062900002107200641086a290000210d200641106a290000210e2004200641186a2900003703002008200e3703002003200d370300200220073703382006102f41c000102d2206450d01200620022903583700002006200229031837001020062002290338370020200641086a200241d8006a41086a290300370000200641186a200241186a41086a290300370000200641286a200241386a41086a2208290300370000200641306a200241386a41106a2203290300370000200641386a200241386a41186a22092903003700004120102d2205450d0120052001290000370000200541186a200141186a290000370000200541106a200141106a290000370000200541086a200141086a2900003700002005ad4280808080800484100322042900002107200441086a290000210d200441106a290000210e2009200441186a2900003703002003200e3703002008200d370300200220073703382004102f2005102f200641c00041800110312206450d0120062002290338370040200641d8006a200241d0006a290300370000200641d0006a200241c8006a290300370000200641c8006a200241c0006a2903003700002002200641e00010950120022802042105200228020021042006102f200541004720044100477121060b200241f0006a240020060f0b1036000bfb20030b7f047e097f230041c0066b2202240002400240024020012802082203200128020c2204460d002001200341206a220536020820012802102106200241f8026a41186a200341186a290000370300200241f8026a41106a200341106a290000370300200241f8026a41086a200341086a290000370300200220032900003703f802200128021421074100210802400240024002402001411c6a280200220941014b0d0020090e020201020b2009210a0340200a410176220b20086a220c20082007200c4105746a200241f8026a412010ea064101481b2108200a200b6b220a41014b0d000b0b200720084105746a200241f8026a412010ea060d002006210c0c010b2001200641016a220c3602104108210820052004460d020240200941014d0d0003402001200541206a2203360208200241f8026a41186a200541186a290000370300200241f8026a41106a200541106a290000370300200241f8026a41086a200541086a290000370300200220052900003703f802410021082009210a0340200a410176220520086a220b20082007200b4105746a200241f8026a412010ea064101481b2108200a20056b220a41014b0d000b200720084105746a200241f8026a412010ea06450d022001200c41016a220c3602102003210520032004460d030c000b0b0240024020090e020100010b03402001200541206a2208360208200241f8026a41186a200541186a290000370300200241f8026a41106a200541106a290000370300200241f8026a41086a200541086a290000370300200220052900003703f80202402007200241f8026a412010ea060d00410021080c030b2001200c41016a220c3602102008210520042008460d030c000b0b2001200436020820012006200420036b41406a4105766a41026a3602100c020b0240024002400240024002400240200920084d0d00200241186a200720084105746a220841186a290000220d370300200241106a200841106a290000220e370300200241086a200841086a290000220f3703002002200829000022103703002001200c41016a360210200141206a2802002108200141246a280200210a200241206a41186a200d370300200241206a41106a200e370300200241206a41086a200f370300200220103703202002200a36024c200220083602482002200c360244200241f8026a41186a4200370300200241f8026a41106a22054200370300200241f8026a41086a22084200370300200242003703f802419c9eca00ad4280808080f000841001220a290000210d2008200a41086a2900003703002002200d3703f802200a102f41a5c6c800ad4280808080a001841001220a290000210d200241b8026a41086a220b200a41086a2900003703002002200d3703b802200a102f200520022903b802220d370300200241d0006a41086a2008290300370300200241d0006a41106a200d370300200241d0006a41186a200b290300370300200220022903f802370350200241f8026a200241d0006a412010aa0220022802f8022208410120081b210a02400240200c20022902fc02420020081b220d422088a7490d00200da7450d01200a102f2002280244210c0c010b200c200a200c4105746a10a30321050240200da7450d00200a102f0b410221082002280244210c20050d0a0b200228024c210620022802482111411b102d2208450d06200841176a41002800bacf43360000200841106a41002900b3cf43370000200841086a41002900abcf43370000200841002900a3cf433700004104102d220a450d06200a200c3600002008411b413610312209450d062009200a28000036001b200a102f200241b8026a41002009ad4280808080f00384220d10151073024002400240024020022802b8022208450d00200241c0026a280200220a4104490d00200a417c714104460d0041000d0020082800002011470d002008280004220a41036a20064b0d010b4104102d2208450d092008201136000020084104410810312208450d0920082006360004200241d0006a41086a200241b8026a41086a280200360200200220022903b802370350200241f8026a200241d0006a10f40120022802fc02210a4100200d20023502800342208620022802f802220bad842008ad4280808080800184101621050240200a450d00200b102f0b02402002280250220a450d002002280254450d00200a102f0b2008102f4104210820054101460d022006210a0c010b024020022802bc02450d002008102f0b410121080b2009102f200a210c0c0a0b200241f8026a10a503024020022802f8022212450d002002418c036a280200211320024188036a280200211420024184036a280200211520024180036a280200211620022802fc0221172002410036028003200242013703f8024104102d2208450d0720024284808080c0003702fc02200220083602f802200820063600002016200241f8026a10690240024020022802fc02220a20022802800322086b2016490d0020022802f802210a0c010b200820166a22052008490d05200a410174220b2005200b20054b1b22054100480d0502400240200a0d002005102d210a0c010b20022802f802200a20051031210a0b200a450d08200220053602fc022002200a3602f8020b2002200820166a36028003200a20086a2012201610e8061a2013200241f8026a10692013450d0220152013410c6c6a21032015210a0340200a2802002101200a41086a2802002208200241f8026a10690240024020022802fc02220b20022802800322056b2008490d0020022802f80221070c010b200520086a22072005490d06200b41017422042007200420074b1b22044100480d0602400240200b0d002004102d21070c010b20022802f802200b2004103121070b2007450d09200220043602fc02200220073602f8022004210b0b2002200520086a220436028003200720056a2001200810e8061a200a410c6a220a2003470d000c040b0b41012108410521060c050b41c4c2ca0020082009103b000b20022802fc02210b20022802800321040b02400240200b20046b4104490d0020022802f80221080c010b200441046a22082004490d01200b410174220a2008200a20084b1b220a4100480d0102400240200b0d00200a102d21080c010b20022802f802200b200a103121080b2008450d042002200a3602fc02200220083602f802200a210b0b2002200441046a220a36028003200820046a20113600004103210502400240200b200a6b41034d0d00200b21070c010b200a41046a2207200a490d01200b41017422012007200120074b1b22074100480d0102400240200b0d002007102d21080c010b2008200b2007103121080b2008450d04200220073602fc02200220083602f8020b2008200a6a200c360000200241f8026a41e9dabdf306200241206a2008200441086a10a6034101210a024020022d00f8024101470d00200241f6026a20022d00fb023a0000200241b8026a41086a2002418c036a290200370300200241c8026a20024194036a290200370300200241d0026a2002419c036a290200370300200241d8026a200241a4036a290200370300200241e0026a200241ac036a290200370300200241e5026a200241b1036a290000370000200220022f00f9023b01f402200220024184036a2902003703b802200241f8026a41086a280200210b4100210a20022802fc0221050b200241b4026a41026a2201200241f4026a41026a2d00003a0000200241f8016a41086a200241b8026a41086a290300370300200241f8016a41106a2204200241b8026a41106a290300370300200241f8016a41186a2203200241b8026a41186a290300370300200241f8016a41206a2218200241b8026a41206a290300370300200241f8016a41286a2219200241b8026a41286a290300370300200241f8016a41306a200241b8026a41306a290300370300200220022f01f4023b01b402200220022903b8023703f8010240200a0d00200241f4016a41026a20012d00003a0000200241f8026a41086a200241f8016a41086a290300370300200241f8026a41106a2004290300370300200241f8026a41186a2003290300370300200241f8026a41206a2018290300370300200241f8026a41286a2019290300370300200241f8026a412d6a200241f8016a412d6a290000370000200220022f01b4023b01f401200220022903f8013703f80202402007450d002008102f0b200220022f01f4013b01b8022002200241f6016a2d00003a00ba02410021080c030b02402007450d002008102f0b02402017450d002012102f0b02402013450d002013410c6c210a2015210803400240200841046a280200450d002008280200102f0b2008410c6a2108200a41746a220a0d000b0b410121082014450d012015102f0c010b1038000b200b2112200521060b200241b8016a41086a220a200241f8026a41086a290300370300200241b8016a41106a2207200241f8026a41106a290300370300200241b8016a41186a2201200241f8026a41186a290300370300200241b8016a41206a2204200241f8026a41206a290300370300200241b8016a41286a2203200241f8026a41286a290300370300200241b8016a412d6a2218200241f8026a412d6a290000370000200220022d00ba023a00f201200220022f01b8023b01f001200220022903f8023703b80102400240024020080d00200241d0006a41186a2013360200200241d0006a41146a2014360200200241d0006a41106a2015360200200241d0006a410c6a2016360200200241d0006a41086a2017360200200241f6006a20022d00f2013a0000200241fb006a200b360000200241f7006a2005360000200241ff006a20022903b80137000020024187016a200a2903003700002002418f016a200729030037000020024197016a20012903003700002002419f016a2004290300370000200241a7016a2003290300370000200241ac016a20182900003700002002200c3602702002201136026c2002201236025420022006360250200220022f01f0013b0174024041002802a4e24a4103490d00200241b8026a411c6a412d360200200241b8026a41146a412e360200200241b8026a410c6a412e3602002002412e3602bc022002200241d0006a3602d0022002200241c8006a3602c8022002200241cc006a3602c0022002200241c4006a3602b80241002802b0e24a210841002802ace24a210a41002802a8e24a2105200241b8036a41da03360200200241b0036a42c580808010370300200241ac036a4188ccc300360200200241a4036a4210370200200241a0036a41f8cbc30036020020024198036a420437030020024188036a4204370300200241f8026a41086a4108360200200241f8026a411c6a200241b8026a360200200241c0cfc30036028403200241f0cbc3003602fc02200241033602f802200a41cca5c000200541024622051b200241f8026a200841e4a5c00020051b2802101102000b2002411336029004200242023703e00320024194046a200241d0006a41e40010e8061a2002200241f8026a3602f801200241b8026a200241f8016a10a90320022802b80220022802bc0220022802c00210aa03210a20024190046a108e014107210841062106200a0d010c020b4107210820064107460d010b4104102d2208450d012008201136000020084104410810312208450d01200841003600044100200d2008ad428080808080018410172008102f200621080b2009102f2012210c0c030b1036000b410821080b0b2000200c36020420002008360200200241c0066a24000ba70603017f017e0e7f230041306b220124000240024010262202422088a722030d00410121040c010b2002a721040b20012003360224200120043602200240024002400240024002402003450d0020042d0000210520012003417f6a3602242001200441016a360220200541014b0d00024020050e020002000b200141186a200141206a10e60120012802180d0020012802242205200128021c2206490d002006417f4c0d030240024020060d00410121070c010b200610332207450d05200720012802202208200610e8061a2001200520066b3602242001200820066a3602200b2007450d00200141106a200141206a10e601024020012802100d00200128021422092001280224410c6e2205200520094b1b220aad420c7e2202422088a70d042002a72205417f4c0d040240024020050d004104210b0c010b2005102d220b450d062005410c6e210a0b024002402009450d004100210c410021084100210d0340200141086a200141206a10e60120012802080d022001280224220e200128020c2205490d022005417f4c0d070240024020050d004101210f0c010b20051033220f450d09200f20012802202210200510e8061a2001200e20056b3602242001201020056a3602200b200d41016a210e0240200d200a470d00200c200e200c200e4b1bad420c7e2202422088a70d0a2002a7220a4100480d0a02400240200d0d00200a102d210b0c010b200b2008200a1031210b0b200b450d09200a410c6e210a0b200b20086a220d200f360200200d41046a2005ad2202422086200284370200200c41026a210c2008410c6a2108200e210d2009200e470d000b0b200b450d012007450d020c040b0240200d450d00200b210503400240200541046a280200450d002005280200102f0b2005410c6a2105200841746a22080d000b0b200a450d00200b102f0b2006450d002007102f0b41f4c8ca00412e200141286a418ccaca0041a4c9ca00103e000b410021070b2000200636020420002007360200200041146a2009360200200041106a200a3602002000410c6a200b360200200041086a200636020002402003450d002004102f0b200141306a24000f0b103d000b1036000b1038000b970403017f017e017f23004190016b22052400200520013602040240200541046a20022004ad4220862003ad84102b2206422088a72201450d002006a722072d0000220341014b0d004100210202400240024020030e020100010b41002102200541003a008801200741016a21042001417f6a2101034020012002460d02200541c8006a20026a200420026a2d00003a00002005200241016a22033a00880120032102200341c000470d000b200541086a41386a200541c8006a41386a290300370300200541086a41306a200541c8006a41306a290300370300200541086a41286a200541c8006a41286a290300370300200541086a41206a200541c8006a41206a290300370300200541086a41186a200541c8006a41186a290300370300200541086a41106a200541c8006a41106a290300370300200541086a41086a200541c8006a41086a29030037030020052005290348370308410121020b200020023a000020002005290308370001200041096a200541106a290300370000200041116a200541186a290300370000200041196a200541206a290300370000200041216a200541286a290300370000200041296a200541306a290300370000200041316a200541386a290300370000200041396a200541c0006a2903003700002007102f20054190016a24000f0b200241ff0171450d00200541003a0088010b41f4c8ca00412e200541c8006a418ccaca0041a4c9ca00103e000bec0603067f017e097f23004190016b2202240002400240024002402000410c6a2802002203417f4c0d0020002802042104200028020021050240024020030d00410121060c010b2003102d2206450d040b20062004200310e8062107200041186a2802002204ad420c7e2208422088a70d002008a72209417f4c0d002000280210210a02400240024020090d00200a2004410c6c6a210b4104210c200421060c010b2009102d220c450d05200a2004410c6c6a210b2009410c6e220620044f0d0002402006410174220d2004200d20044b1b220e410c6c22044100480d00024002402009410b4b0d002004102d210c0c010b200c2006410c6c20041031210c0b200c0d020c060b1038000b2004450d022006210e0b410021064100210f0340200a20066a220941086a2802002204417f4c0d01200928020021100240024020040d00410121110c010b2004102d2211450d050b200c20066a220d20112010200410e806360200200d41086a2004360200200d41046a20043602002006410c6a2106200f41016a210f2009410c6a200b470d000b200e21060c020b103d000b4100210f0b200241286a200f360200200241106a41146a2006360200200241206a200c360200200241106a410c6a2003360200200241186a22042003360200200241106a412c6a2000412c6a290200370200200241106a41346a200041346a290200370200200241106a413c6a2000413c6a290200370200200241106a41c4006a200041c4006a290200370200200241106a41cc006a200041cc006a290200370200200241106a41d4006a200041d4006a290200370200200241106a41dc006a200041dc006a29020037020020022007360214200220053602102002200029021c37022c200220002902243702342002410c6a412f360200200241043602042002418cc9c3003602002001411c6a28020021062002200241106a36020820012802182109200241f8006a41146a41023602002002420237027c20024194d0c300360278200220023602880120092006200241f8006a103c210902402004280200450d002002280214102f0b024020022802282206450d00200228022021042006410c6c210603400240200441046a280200450d002004280200102f0b2004410c6a2104200641746a22060d000b0b02402002280224450d002002280220102f0b20024190016a240020090f0b1036000baf0201037f23004180016b2202240002400240024002400240200128020022034110710d002000280200210420034120710d012004ad41012001104521000c020b20002802002104410021000340200220006a41ff006a2004410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d022001410141bc8ac0004102200220006a4180016a410020006b104821000c010b410021000340200220006a41ff006a2004410f712203413072200341376a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d022001410141bc8ac0004102200220006a4180016a410020006b104821000b20024180016a240020000f0b2004418001104b000b2004418001104b000b8d1203067f027e067f230041206b2202240002400240024041ca03102d2203450d00200242ca03370204200220033602002002410210f20302400240200128020022012903684202520d0002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d05200341017422052004200520044b1b22054100480d050240024020030d002005102d21040c010b200228020020032005103121040b2004450d0320022005360204200220043602000b200420036a41043a00002002200228020841016a3602080c010b02400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d04200341017422052004200520044b1b22054100480d040240024020030d002005102d21040c010b200228020020032005103121040b2004450d0220022005360204200220043602000b200420036a4184013a00002002200228020841016a3602082001200210eb02024020012d0024220341024b0d000240024002400240024020030e03000102000b410021060c020b410121060c010b41022106200241023a001041c10021040c010b200220063a001041c00021040b02400240200228020420022802082203460d00200228020021050c010b200341016a22052003490d05200341017422072005200720054b1b22074100480d050240024020030d002007102d21050c010b200228020020032007103121050b2005450d0320022007360204200220053602000b2002200341016a360208200520036a20063a00000240024020022802042205200228020822036b2004490d00200228020021050c010b200320046a22062003490d05200541017422072006200720064b1b22064100480d050240024020050d002006102d21050c010b200228020020052006103121050b2005450d0320022006360204200220053602000b2002200320046a360208200520036a200141256a200410e8061a0b0240024020012903684201520d00200141f8006a29030020012903702208420c882209420120094201561b8021090240024020022802042204200228020822036b4102490d00200228020021040c010b200341026a22052003490d06200441017422062005200620054b1b22054100480d060240024020040d002005102d21040c010b200228020020042005103121040b2004450d0420022005360204200220043602000b2002200341026a360208200420036a2009a741047420087aa7417f6a22034101200341014b1b2203410f2003410f491b723b00000c010b02400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d05200341017422052004200520044b1b22054100480d050240024020030d002005102d21040c010b200228020020032005103121040b2004450d0320022005360204200220043602000b2002200341016a360208200420036a41003a00000b20014190016a2002109502200220014180016a360210200241106a200210c2020b20014198016a2002109101200228020821014104102d2203450d0020024204370214200220033602102001417e6a200241106a10692002280208220341014d0d01200228021821052002280214210a2002280210210620024100360208200228020021010240024002400240024002402003417e6a2207450d004102210b2005450d04200120062d00003a00004101210c2002200228020841016a36020820054101460d04200620056a210d200120062d00013a00012002200228020841016a3602084102210b200641026a21042005417e6a220e0d014100210e0c020b0240024002402002280204220320054f0d00200341017422042005200420054b1b22044100480d0a0240024020030d002004102d21010c010b200120032004103121010b2001450d0820022004360204200220013602002002280208210b0c010b4100210b2005450d010b2001200b6a220320062d00003a0000024020054101470d00200b41016a210b0c010b2005417f6a2104200641016a2101200341016a21030340200320012d00003a0000200341016a2103200141016a21012004417f6a22040d000b200b20056a210b0b2002200b3602084102210b0c020b024002402002280204220120036b200e490d00200228020021010c010b2003200e6a220b2003490d0720014101742203200b2003200b4b1b22034100480d070240024020010d002003102d21010c010b200228020020012003103121010b2001450d0520022003360204200220013602000b200120056a200141026a200710e9061a0240200520022802082201460d00200520016b210b2005417e6a2103200228020020016a210c410021010340024020032001470d002005210b0c040b200c20016a20042d00003a00002002200228020841016a360208200441016a2104200b200141016a2201470d000b200d20046b220e0d004100210e4101210c2005210b0c010b200e4100480d062005210b200e102d220c450d040b0240200d2004460d00200c20042d00003a00004101210f02400240200441016a2201200d470d00200c41016a21050c010b200c41016a21032006200520046b6a21040340200320012d00003a0000200341016a2103200d200141016a2201470d000b2004450d01200c20046a21052004210f0b02400240200228020422012007200b6a22036b200f490d00200228020021010c010b2003200f6a22042003490d07200141017422032004200320044b1b22034100480d070240024020010d002003102d21010c010b200228020020012003103121010b2001450d0520022003360204200220013602000b2001200b200f6a220d6a2001200b6a200710e9061a0240200d20022802082201460d00200228020020016a2103200b200f6a20016b2104200c2101034020052001460d01200320012d00003a00002002200228020841016a360208200141016a2101200341016a21032004417f6a22040d000b0b200d210b0b200e450d00200c102f0b2007450d010b0240200b20022802082201460d002002280200220320016a2003200b6a200710e9061a0b2002200720016a3602080b0240200a450d002006102f0b20002002290300370200200041086a200241086a280200360200200241206a24000f0b1036000b41a6b5ca00411c41f8b4ca001039000b1038000b810103017f017e027f230041106b220324000240024002402002ad4220862000ad8410252204428080808010540d00410121022004a722052d0000220641014b0d0020060e020102010b41f4c8ca00412e200341086a418ccaca0041a4c9ca00103e000b410021020b2005102f02402001450d002000102f0b200341106a240020020bef0401017f230041306b220224000240024002400240024002400240024020002802000e0701020304050600010b2001411c6a2802002100200128021821012002412c6a4100360200200241c8e1ca003602282002420137021c200241f8ccc30036021820012000200241186a103c21010c060b2002200041046a36020c2002410a3602142001411c6a280200210020022002410c6a360210200128021821012002412c6a41013602002002420137021c20024180cdc3003602182002200241106a36022820012000200241186a103c21010c050b2002200041046a36020c2002410a3602142001411c6a280200210020022002410c6a360210200128021821012002412c6a41013602002002420237021c20024188cdc3003602182002200241106a36022820012000200241186a103c21010c040b2002200028020436020c200241013602142001411c6a280200210020022002410c6a360210200128021821012002412c6a41013602002002420237021c20024198cdc3003602182002200241106a36022820012000200241186a103c21010c030b2001411c6a2802002100200128021821012002412c6a4100360200200241c8e1ca003602282002420137021c200241a8cdc30036021820012000200241186a103c21010c020b2001411c6a2802002100200128021821012002412c6a4100360200200241c8e1ca003602282002420137021c200241b0cdc30036021820012000200241186a103c21010c010b2001411c6a2802002100200128021821012002412c6a4100360200200241c8e1ca003602282002420137021c200241b8cdc30036021820012000200241186a103c21010b200241306a240020010b980201027f230041206b220224002002200128021841c8e1ca0041002001411c6a28020028020c1100003a00102002200136020841012101200241013a00112002410036020c200220003602182002200041246a36021c200241086a200241186a41a4d0c30010612002411c6a41b4d0c30010611a20022d0010210002400240200228020c22030d00200021010c010b0240200041ff01710d00024020034101470d0020022d001141ff0171450d00200228020822002d00004104710d004101210120002802184196a5c00041012000411c6a28020028020c1100000d010b2002280208220128021841e4d3ca0041012001411c6a28020028020c11000021010b200220013a00100b200241206a2400200141ff01714100470b1c00200128021841ffcbca00410f2001411c6a28020028020c1100000b88810109057f017e017f017e077f017e207f057e057f23004180066b2200240020004180056a41186a2201420037030020004180056a41106a220242003703004108210320004180056a41086a220442003703002000420037038005419c9eca00ad4280808080f0008422051001220629000021072004200641086a29000037030020002007370380052006102f41a39eca00ad4280808080c00184100122062900002107200041e0036a41086a2208200641086a290000370300200020073703e0032006102f200220002903e0032207370300200041b0046a41086a22092004290300370300200041b0046a41106a220a2007370300200041b0046a41186a220b200829030037030020002000290380053703b004200041286a200041b0046a4120109501200028022c210c2000280228210d200142003703002002420037030020044200370300200042003703800541d39bca00ad42808080808001841001220629000021072004200641086a29000037030020002007370380052006102f419087ca00ad4280808080c000841001220629000021072008200641086a290000370300200020073703e0032006102f200220002903e003220737030020092004290300370300200a2007370300200b200829030037030020002000290380053703b00420004180056a200041b0046a108d03200028028005210e200029028405210f200142003703002002420037030020044200370300200042003703800520051001220629000021052004200641086a29000037030020002005370380052006102f41a5c6c800ad4280808080a001841001220629000021052008200641086a290000370300200020053703e0032006102f200220002903e003220537030020092004290300370300200a2005370300200b200829030037030020002000290380053703b00420004180056a200041b0046a412010aa022000280280052206410120061b2110200029028405420020061b2205a721110240024002400240024002400240024002402005422088a72206450d002010200641057422126a2113200041c4036a211420004180056a41206a2115200041f8026a4104722116200041d0026a410472211741022106410021180340200041e0016a41186a201020186a221941186a221a290000370300200041e0016a41106a201941106a221b290000370300200041e0016a41086a201941086a221c290000370300200020192900003703e00120172019290000370000201741086a201c290000370000201741106a201b290000370000201741186a201a29000037000020002006417e6a221b3602d0024100211a0240201b201710a3030d00200041f8026a41206a200041d0026a41206a280200360200200041f8026a41186a200041d0026a41186a290300370300200041f8026a41106a200041d0026a41106a290300370300200041f8026a41086a200041d0026a41086a290300370300200020002903d0023703f80220004190026a41186a221a201641186a221b29000037030020004190026a41106a221c201641106a221d29000037030020004190026a41086a221e201641086a221f29000037030020002016290000370390022001201b2900003703002002201d2900003703002004201f2900003703002000201629000037038005200041a0036a20004180056a10af03200041b0026a41186a221b201a290300370300200041b0026a41106a221d201c290300370300200041b0026a41086a221c201e29030037030020002000290390023703b00220002802c003221a450d00201520002903a003370300201541186a200041a0036a41186a290300370300201541106a200041a0036a41106a290300370300201541086a200041a0036a41086a2903003703002001201b2903003703002002201d2903003703002004201c29030037030020004180026a41086a221b201441086a280200360200200020002903b002370380052000201429020037038002200041b0046a41386a221c20004180056a41386a290300370300200041b0046a41306a221d20004180056a41306a290300370300200041b0046a41286a221e20004180056a41286a290300370300200041b0046a41206a221f2015290300370300200b2001290300370300200a20022903003703002009200429030037030020002000290380053703b004200041e0036a41386a201c290300370300200041e0036a41306a201d290300370300200041e0036a41286a201e290300370300200041e0036a41206a201f290300370300200041e0036a41186a200b290300370300200041e0036a41106a200a29030037030020082009290300370300200020002903b0043703e003200041d0036a41086a201b28020036020020002000290380023703d0030b200041a0016a41086a2008290300370300200041a0016a41106a200041e0036a41106a290300370300200041a0016a41186a200041e0036a41186a290300370300200041a0016a41206a200041e0036a41206a290300370300200041a0016a41286a200041e0036a41286a290300370300200041a0016a41306a200041e0036a41306a290300370300200041a0016a41386a200041e0036a41386a29030037030020004190016a41086a200041d0036a41086a280200360200200020002903e0033703a001200020002903d00337039001201a0d02200641016a21062012201841206a2218470d000b0b410021202000410036029801200042083703900102402011450d002010102f0b4100211a0c010b200041c0006a41386a2217200041a0016a41386a290300370300200041c0006a41306a2216200041a0016a41306a290300370300200041c0006a41286a2204200041a0016a41286a290300370300200041c0006a41206a221b200041a0016a41206a290300370300200041c0006a41186a221c200041a0016a41186a290300370300200041c0006a41106a2208200041a0016a41106a290300370300200041c0006a41086a2201200041a0016a41086a29030037030020004180016a41086a221d20004190016a41086a280200360200200020002903a001370340200020002903900137038001200041306a41086a221e201d280200360200200020002903800137033020004180056a41086a221d200129030037030020004180056a41106a2201200829030037030020004180056a41186a2208201c29030037030020004180056a41206a221c201b29030037030020004180056a41286a221b200429030037030020004180056a41306a2204201629030037030020004180056a41386a221620172903003703002000200029034037038005200041b0046a41086a2217201e280200360200200020002903303703b00441d000102d2203450d0120032000290380053703002003201a360240200320002903b004370244200341386a2016290300370300200341306a2004290300370300200341286a201b290300370300200341206a201c290300370300200341186a2008290300370300200341106a2001290300370300200341086a201d290300370300200341cc006a201728020036020002400240201241606a2018470d004101211a410121200c010b201941206a2117201220186b41606a211b200041c4036a211e200041f8026a4104722116200041d0026a410472211902400340200041e0016a41186a201741186a2218290000370300200041e0016a41106a201741106a221a290000370300200041e0016a41086a201741086a2204290000370300200020172900003703e00120172900002105201941186a201829000037000020192005370000201941086a2004290000370000201941106a201a29000037000020002006417f6a221a3602d002410021180240201a201910a3030d00200041f8026a41206a200041d0026a41206a280200360200200041f8026a41186a200041d0026a41186a290300370300200041f8026a41106a200041d0026a41106a290300370300200041f8026a41086a200041d0026a41086a290300370300200020002903d0023703f80220004190026a41186a2218201641186a220429000037030020004190026a41106a2208201641106a221c29000037030020004190026a41086a2201201641086a2212290000370300200020162900003703900220004180056a41186a221a200429000037030020004180056a41106a2204201c29000037030020004180056a41086a221c20122900003703002000201629000037038005200041a0036a20004180056a10af03200041b0026a41186a22122018290300370300200041b0026a41106a221d2008290300370300200041b0026a41086a2208200129030037030020002000290390023703b00220002802c0032218450d00201520002903a003370300201541186a200041a0036a41186a290300370300201541106a200041a0036a41106a290300370300201541086a200041a0036a41086a290300370300201a20122903003703002004201d290300370300201c200829030037030020004180026a41086a2208201e41086a280200360200200020002903b002370380052000201e29020037038002200041b0046a41386a220120004180056a41386a290300370300200041b0046a41306a221220004180056a41306a290300370300200041b0046a41286a221d20004180056a41286a290300370300200041b0046a41206a221f20004180056a41206a290300370300200041b0046a41186a2209201a290300370300200041b0046a41106a221a2004290300370300200041b0046a41086a2204201c29030037030020002000290380053703b004200041e0036a41386a2001290300370300200041e0036a41306a2012290300370300200041e0036a41286a201d290300370300200041e0036a41206a201f290300370300200041e0036a41186a2009290300370300200041e0036a41106a201a290300370300200041e0036a41086a2004290300370300200020002903b0043703e003200041d0036a41086a200828020036020020002000290380023703d0030b200041a0016a41086a200041e0036a41086a290300370300200041a0016a41106a200041e0036a41106a290300370300200041a0016a41186a200041e0036a41186a290300370300200041a0016a41206a200041e0036a41206a290300370300200041a0016a41286a200041e0036a41286a290300370300200041a0016a41306a200041e0036a41306a290300370300200041a0016a41386a200041e0036a41386a29030037030020004190016a41086a200041d0036a41086a280200360200200020002903e0033703a001200020002903d0033703900120180d01201741206a21174101211a200641016a2106201b41606a221b0d000b410121200c010b200041c0006a41386a2221200041a0016a41386a2212290300370300200041c0006a41306a2222200041a0016a41306a221d290300370300200041c0006a41286a2223200041a0016a41286a221e290300370300200041c0006a41206a2224200041a0016a41206a221f290300370300200041c0006a41186a2225200041a0016a41186a2209290300370300200041c0006a41106a2226200041a0016a41106a220a290300370300200041c0006a41086a2227200041a0016a41086a220b29030037030020004180016a41086a222820004190016a41086a2214280200360200200020002903a001370340200020002903900137038001200041306a41086a222920282802003602002000200029038001370330201741206a2117200041c4036a212a200041f8026a4104722116200041d0026a41047221194101211a41012120034020004180056a41086a221c202729030037030020004180056a41106a2208202629030037030020004180056a41186a2201202529030037030020004180056a41206a222b202429030037030020004180056a41286a222c202329030037030020004180056a41306a222d202229030037030020004180056a41386a222e20212903003703002000200029034037038005200041b0046a41086a222f2029280200360200200020002903303703b00402402020201a470d00201a41016a2204201a490d09201a410174221b2004201b20044b1bad42d0007e2205422088a70d092005a722044100480d0902400240201a0d002004102d21030c010b2003201a41d0006c2004103121030b2003450d04200441d0006e21200b2003201a41d0006c6a22042000290380053703002008290300210520012903002107202b2903002130202c2903002131202d2903002132202e2903002133201c290300213420042018360240200441086a2034370300200441386a2033370300200441306a2032370300200441286a2031370300200441206a2030370300200441186a2007370300200441106a2005370300200420002903b004370244200441cc006a202f280200360200201a41016a211a20172013460d010340200041e0016a41186a201741186a2218290000370300200041e0016a41106a201741106a2204290000370300200041e0016a41086a201741086a221b290000370300200020172900003703e001200020063602d002201b29000021052004290000210720172900002130201941186a2018290000370000201941106a2007370000201941086a2005370000201920303700004100211802402006201910a3030d00200041f8026a41206a200041d0026a41206a280200360200200041f8026a41186a200041d0026a41186a290300370300200041f8026a41106a200041d0026a41106a290300370300200041f8026a41086a200041d0026a41086a290300370300200020002903d0023703f80220004190026a41186a2218201641186a220429000037030020004190026a41106a221b201641106a223529000037030020004190026a41086a2236201641086a223729000037030020002016290000370390022001200429000037030020082035290000370300201c20372900003703002000201629000037038005200041a0036a20004180056a10af03200041b0026a41186a22042018290300370300200041b0026a41106a2235201b290300370300200041b0026a41086a221b203629030037030020002000290390023703b00220002802c0032218450d00201520002903a003370300201541186a200041a0036a41186a290300370300201541106a200041a0036a41106a290300370300201541086a200041a0036a41086a2903003703002001200429030037030020082035290300370300201c201b29030037030020004180026a41086a2204202a41086a280200360200200020002903b002370380052000202a29020037038002200041b0046a41386a221b202e290300370300200041b0046a41306a2235202d290300370300200041b0046a41286a2236202c290300370300200041b0046a41206a2237202b290300370300200041b0046a41186a22382001290300370300200041b0046a41106a22392008290300370300202f201c29030037030020002000290380053703b004200041e0036a41386a201b290300370300200041e0036a41306a2035290300370300200041e0036a41286a2036290300370300200041e0036a41206a2037290300370300200041e0036a41186a2038290300370300200041e0036a41106a2039290300370300200041e0036a41086a202f290300370300200020002903b0043703e003200041d0036a41086a200428020036020020002000290380023703d0030b200b200041e0036a41086a290300370300200a200041e0036a41106a2903003703002009200041e0036a41186a290300370300201f200041e0036a41206a290300370300201e200041e0036a41286a290300370300201d200041e0036a41306a2903003703002012200041e0036a41386a2903003703002014200041d0036a41086a280200360200200020002903e0033703a001200020002903d00337039001024020180d00200641016a21062013201741206a2217470d010c030b0b202120122903003703002022201d2903003703002023201e2903003703002024201f290300370300202520092903003703002026200a2903003703002027200b29030037030020282014280200360200200020002903a001370340200020002903900137038001202920282802003602002000200029038001370330201741206a2117200641016a21060c000b0b02402011450d002010102f0b2000201a36029801200020203602940120002003360290010b20004180056a41186a2219420037030020004180056a41106a2218420037030020004180056a41086a221742003703002000420037038005419c9eca00ad4280808080f0008422051001220629000021072017200641086a29000037030020002007370380052006102f41a39eca00ad4280808080c001842207100122062900002130200041e0036a41086a2216200641086a290000370300200020303703e0032006102f200220002903e003370000200241086a22042016290300370000200041b0046a41086a22152017290300370300200041b0046a41106a221b2018290300370300200041b0046a41186a221c201929030037030020002000290380053703b004200041206a200041b0046a4120109501200028022421082000280220210141d39bca00ad428080808080018422301001220629000021312015200641086a290000370300200020313703b0042006102f41db9bca00ad4280808080a002841001220629000021312016200641086a290000370300200020313703e0032006102f20002008410020011b3602a001200041a0016aad4280808080c000842231100322062900002132200641086a2900002133200641106a29000021342019200641186a290000370300201820343703002017203337030020002032370380052006102f41c000102d2206450d00200620002903b004370000200620002903e0033700102006200029038005370020200641086a2015290300370000200641186a2016290300370000200641286a2017290300370000200641306a2018290300370000200641386a20192903003700002006ad428080808080088410132006102f201942003703002018420037030020174200370300200042003703800520051001220629000021052017200641086a29000037030020002005370380052006102f20071001220629000021052016200641086a290000370300200020053703e0032006102f200220002903e0033700002004201629030037000020152017290300370300201b2018290300370300201c201929030037030020002000290380053703b004200041186a200041b0046a4120109501200028021c21022000280218210420301001220629000021052016200641086a290000370300200020053703e0032006102f4194c9c300ad4280808080e001841001220629000021052015200641086a290000370300200020053703b0042006102f20002002410020041b3602a0012031100322062900002105200641086a2900002107200641106a29000021302019200641186a290000370300201820303703002017200737030020002005370380052006102f41c000102d2206450d00200f4200200e1b2132200620002903e003370000200620002903b0043700102006200029038005370020200641086a200041e0036a41086a290300370000200641186a200041b0046a41086a290300370000200641286a20004180056a41086a2217290300370000200641306a20004180056a41106a290300370000200641386a20004180056a41186a2903003700002006ad428080808080088410132006102f02400240024002400240024002400240201a450d0020004180056a20004190016a10b003200041bb046a201728020036000020002000290380053700b3042000418c056a200041b7046a290000370000200041023a0084052000410f3a008005200020002900b0043700850541c8e1ca00410020004180056a108c01200041f8026a41106a20004190016a41086a28020036020020002032422088a7222b3602fc022000200c4100200d1b22043602f802200020002903900137038003200041d0036a200041f8026a41086a10b00320002802d803210220002802d403210d20002802d003210c4104102d2239450d082039200436000020004284808080c0003702a401200020393602a00141ed9bca00ad4280808080800184100122062900002105200041e0036a41086a200641086a290000370300200020053703e0032006102f41f59bca00ad4280808080a00284100122062900002105200041b0046a41086a200641086a290000370300200020053703b0042006102f4110102d2206450d0841002116200641086a41002902b8f646370000200641002902b0f6463700002006ad4280808080800284100322172900002105201741086a2900002107201741106a290000213020004190026a41186a2219201741186a29000037030020004190026a41106a203037030020004190026a41086a200737030020002005370390022017102f2006102f41c000102d2206450d08200620002903e003370000200620002903b0043700102006200029039002370020200641086a200041e0036a41086a290300370000200641186a200041b0046a41086a290300370000200641286a20004190026a41086a290300370000200641306a200041a0026a290300370000200641386a201929030037000020004180056a200641c000109302200029028405210520002802800521172006102f20002005420020171b22074220883e02b40420002017410120171b221b3602b004200041106a200041b0046a10e60120002802142115024020002802100d00201520002802b404220641246e2217201720154b1b221aad42247e2205422088a70d0a2005a72217417f4c0d0a0240024020170d00410421160c010b2017102d2216450d0a201741246e211a0b2015450d004100211c034002400240024020064104490d00201c41016a210820002006417c6a22193602b404200020002802b004221841046a3602b0042018280000210141002106200041003a00a0050240034020192006460d0120004180056a20066a201820066a221741046a2d00003a00002000201741056a3602b0042000200641016a22173a00a0052017210620174120470d000b200041b0026a41086a221820004180056a41086a290300370300200041b0026a41106a221020004180056a41106a290300370300200041b0026a41186a221220004180056a41186a29030037030020002000290380053703b0022000201920176b22063602b404201a201c470d03201c41017422172008201720084b1bad42247e2205422088a70d132005a7221741004e0d020c130b200041003602b404200641ff0171450d00200041003a00a0050b0240201a450d002016102f0b410021160c030b02400240201c0d002017102d21160c010b2016201c41246c2017103121160b2016450d0b201741246e211a0b2016201c41246c6a22172001360200201720002903b0023702042017410c6a2018290300370200201741146a20102903003702002017411c6a20122903003702002008211c20082015470d000b0b20004180056a200041a0016a10b103200041b0046a200028028005221720002802880510aa0220002802b004210620002902b40421050240200028028405450d002017102f0b2005420020061b210502402007a7450d00201b102f0b201a410020161b21112016410420161b211b2006410120061b212a2005a721202002450d012015410020161b21082005422088a72109200c200241d0006c6a213520004180056a41306a210320004180056a41206a2113200041e0036a41306a2136200041e0036a41206a2137200041e0036a41c4006a212f41002138200c2102034020004180056a41386a22172002220641386a2903003703002003200641306a29030037030020004180056a41286a2219200641286a2903003703002013200641206a29030037030020004180056a41186a2201200641186a29030037030020004180056a41106a2210200641106a29030037030020004180056a41086a2212200641086a29030037030020004180026a41086a2218200641cc006a28020036020020002006290300370380052000200641c4006a29020037038002200641d0006a2102200641c0006a2802002206450d03200041c0006a41386a22162017290300370300200041c0006a41306a22172003290300370300200041c0006a41286a221a2019290300370300200041c0006a41206a22192013290300370300200041c0006a41186a22152001290300370300200041c0006a41106a221c2010290300370300200041c0006a41086a221d201229030037030020004180016a41086a221e20182802003602002000200029038005370340200020002903800237038001200041e0036a41386a201629030037030020362017290300370300200041e0036a41286a201a29030037030020372019290300370300200041e0036a41186a22162015290300370300200041e0036a41106a221a201c290300370300200041e0036a41086a221c201d290300370300200020002903403703e003200020063602a004202f200029038001370200202f41086a201e2802003602004104102d2215450d09201520043600004118102d2206450d09200641086a41002902b8f646370000200042988080808002370284052000200636028005200641002902b0f646370000410420004180056a106902400240200028028405221720002802880522196b4104490d0020002802800521060c010b201941046a22062019490d0f201741017422182006201820064b1b22184100480d0f0240024020170d002018102d21060c010b20002802800520172018103121060b2006450d0a20002018360284052000200636028005201821170b2000201941046a221836028805200620196a20152800003600000240201720186b411f4b0d00201841206a221d2018490d0f2017410174221e201d201e201d4b1b221d4100480d0f0240024020170d00201d102d21060c010b20062017201d103121060b2006450d0a2000201d3602840520002006360280050b200620186a220641086a201c290300370000200641106a201a290300370000200641186a20162903003700002000201941246a36028805200620002903e003370000200020373602b004200041b0046a20004180056a10c202200020363602b004200041b0046a20004180056a10c20220002802a004210620002802a804221720004180056a106902402017450d00201741306c2118034002400240200028028405221920002802880522176b4120490d0020002802800521190c010b201741206a22162017490d112019410174221a2016201a20164b1b22164100480d110240024020190d002016102d21190c010b20002802800520192016103121190b2019450d0c200020163602840520002019360280050b201920176a221941086a200641186a290000370000201941106a200641206a290000370000201941186a200641286a2900003700002000201741206a360288052019200641106a290000370000200020063602b004200041b0046a20004180056a10c202200641306a2106201841506a22180d000b0b2000280284052117200041a0016a41186a220a2000350288054220862000280280052219ad841003220641186a290000370300200041a0016a41106a220b200641106a290000370300200041a0016a41086a2214200641086a290000370300200020062900003703a0012006102f02402017450d002019102f0b2015102f41ed9bca00ad4280808080800184220f100122062900002105200041d0026a41086a2219200641086a290000370300200020053703d0022006102f4194bbc600ad4280808080f000842231100122062900002105200041a0036a41086a2218200641086a290000370300200020053703a0032006102f4120102d2206450d09200620002903a001370000200641186a200a290300370000200641106a200b290300370000200641086a20142903003700002006ad4280808080800484100322172900002105201741086a2900002107201741106a2900002130200041b0046a41186a221d201741186a290000370300200041b0046a41106a221e2030370300200041b0046a41086a221f2007370300200020053703b0042017102f2006102f41c000102d2206450d09200620002903d002370000200620002903a003370010200620002903b004370020200641086a2019290300370000200641186a2018290300370000200641286a201f290300370000200641306a201e290300370000200641386a201d290300370000200041086a200641c00041c8e1ca004100410010b501200028020821172006102f024002400240024020174101460d00200041b0046a200041e0036a41d00010e8061a20004180056a200041b0046a41d00010e8061a200041003602d805200042013703d005200f1001220629000021052019200641086a290000370300200020053703d0022006102f20311001220629000021052018200641086a290000370300200020053703a0032006102f4120102d2206450d0d200620002903a001370000200641186a200a290300370000200641106a200b290300370000200641086a20142903003700002006ad4280808080800484100322172900002105201741086a2900002107201741106a2900002130201d201741186a290000370300201e2030370300201f2007370300200020053703b0042017102f2006102f41c000102d221c450d0d201c20002903d002370000201c20002903a003370010201c20002903b004370020201c41086a2019290300370000201c41186a2018290300370000201c41286a201f290300370000201c41306a201e290300370000201c41386a201d290300370000200041003602b804200042013703b0044120102d2206450d0d200042a080808080043702b404200020063602b0042006200029038005370000200641086a2012290300370000200641106a2010290300370000200641186a2001290300370000200020133602a003200041a0036a200041b0046a10c202200020033602a003200041a0036a200041b0046a10c20220002802c005210620002802c8052217200041b0046a106902402017450d00201741306c211803400240024020002802b404221920002802b80422176b4120490d0020002802b00421190c010b201741206a22162017490d152019410174221a2016201a20164b1b22164100480d150240024020190d002016102d21190c010b20002802b00420192016103121190b2019450d10200020163602b404200020193602b0040b201920176a221941086a200641186a290000370000201941106a200641206a290000370000201941186a200641286a2900003700002000201741206a3602b8042019200641106a290000370000200020063602a003200041a0036a200041b0046a10c202200641306a2106201841506a22180d000b0b20002802d005210620002802d8052217200041b0046a10690240024020170d0020002802b804211720002802b404211a20002802b00421180c010b20174105742115410020002802b80422176b211620002802b404211a034002400240201a20166a4120490d0020002802b00421180c010b201741206a22192017490d15201a41017422182019201820194b1b22194100480d1502400240201a0d002019102d21180c010b20002802b004201a2019103121180b2018450d10200020193602b404200020183602b0042019211a0b201820176a221941086a200641086a290000370000201941106a200641106a290000370000201941186a200641186a2900003700002000201741206a22173602b80420192006290000370000201641606a2116200641206a2106201541606a22150d000b0b201cad42808080808008842017ad4220862018ad8410040240201a450d002018102f0b201c102f024020002802c405450d0020002802c005102f0b024020002802d405450d0020002802d005102f0b2001200a2903003703002010200b29030037030020122014290300370300200020002903a00137038005410021060240200841014b0d00024020080e020003000b200041e0016a41186a2001290300370300200041e0016a41106a2010290300370300200041e0016a41086a201229030037030020002000290380053703e001410021060c030b20082117034020062017410176221920066a2218201b201841246c6a28020020044b1b2106201720196b221741014b0d000c020b0b20002802a404450d0220002802a004102f0c020b0240201b200641246c6a28020022172004460d00200620172004496a21060b200041e0016a41186a2001290300370300200041e0016a41106a2010290300370300200041e0016a41086a201229030037030020002000290380053703e001200820064f0d00419ae3c300411e41f8b4ca001039000b024020082011470d00200841016a22172008490d10200841017422192017201920174b1bad42247e2205422088a70d102005a722174100480d100240024020080d002017102d211b0c010b201b200841246c20171031211b0b201b450d0b201741246e21110b201b200641246c6a221741246a2017200820066b41246c10e9061a201720043602002017411c6a200041e0016a41186a290300370200201741146a200041e0016a41106a2903003702002017410c6a200041e0016a41086a290300370200201720002903e001370204201d2001290300370300201e2010290300370300201f201229030037030020002000290380053703b004024020092020470d00200941016a22062009490d10200941017422172006201720064b1b220641ffffff3f712006470d10200641057422064100480d100240024020090d002006102d212a0c010b202a200941057420061031212a0b202a450d0b200641057621200b200841016a2108202a20094105746a220620002903b004370000200641186a201d290300370000200641106a201e290300370000200641086a201f29030037000041012138200941016a21090b20022035470d000b203521020c020b200041013a0084052000410f3a00800541c8e1ca00410020004180056a108c012020450d0b2003102f0c0b0b200d450d01200c102f0c010b024020352002460d000340200241d0006a21060240200241c4006a280200450d00200241c0006a280200102f0b2006210220352006470d000b0b0240200d450d00200c102f0b2038410171450d0002402009450d0020094105742117202a2106034020004180056a200610b20320002802c00522190d03200641206a2106201741606a22170d000b0b410821124100211d4100211e0c020b2039102f02402020450d00202a102f0b2011450d02201b102f0c020b200041e0036a41386a221220004180056a41386a2218290300370300200041e0036a41306a221d20004180056a41306a221a290300370300200041e0036a41286a221e20004180056a41286a2215290300370300200041e0036a41206a221f20004180056a41206a2202290300370300200041e0036a41186a220a20004180056a41186a221c290300370300200041e0036a41106a220b20004180056a41106a2201290300370300200041e0036a41086a221420004180056a41086a2210290300370300200041a0036a41086a220320004180056a41cc006a290200370300200041a0036a41106a221320004180056a41d4006a290200370300200041a0036a41186a223520004180056a41dc006a28020036020020002000290380053703e0032000200041c4056a22162902003703a003200041c0006a41086a22362014290300370300200041c0006a41106a2214200b290300370300200041c0006a41186a220b200a290300370300200041c0006a41206a220a201f290300370300200041c0006a41286a221f201e290300370300200041c0006a41306a221e201d290300370300200041c0006a41386a221d2012290300370300200041a0016a41086a22122003290300370300200041a0016a41106a22032013290300370300200041a0016a41186a22132035280200360200200020002903e003370340200020002903a0033703a0012010203629030037030020012014290300370300201c200b2903003703002002200a2903003703002015201f290300370300201a201e2903003703002018201d2903003703002000200029034037038005200041b0046a41086a221d2012290300370300200041b0046a41106a221e2003290300370300200041b0046a41186a221f2013280200360200200020002903a0013703b00441e000102d2212450d03201220002903800537030020122019360240201220002903b004370244201241386a2018290300370300201241306a201a290300370300201241286a2015290300370300201241206a2002290300370300201241186a201c290300370300201241106a2001290300370300201241086a2010290300370300201241cc006a201d290300370200201241d4006a201e290300370200201241dc006a201f280200360200024020174120470d004101211d4101211e0c010b200641206a211c202a20094105746a221941606a21134101211d4101211e0340201c21060240034020004180056a200610b20320002802c00522170d012019200641206a2206470d000c030b0b200041e0036a41386a221820004180056a41386a2201290300370300200041e0036a41306a221c20004180056a41306a2210290300370300200041e0036a41286a223520004180056a41286a221f290300370300200041e0036a41206a223620004180056a41206a220a290300370300200041e0036a41186a221a20004180056a41186a220b290300370300200041e0036a41106a221520004180056a41106a2214290300370300200041e0036a41086a220220004180056a41086a2203290300370300200041a0036a41086a2237201641086a290200370300200041a0036a41106a222f201641106a290200370300200041a0036a41186a2238201641186a28020036020020002000290380053703e003200020162902003703a003200041b0046a41086a220c2002290300370300200041b0046a41106a220d2015290300370300200041b0046a41186a222c201a290300370300200041b0046a41206a222d2036290300370300200041b0046a41286a22362035290300370300200041b0046a41306a2235201c290300370300200041b0046a41386a221c2018290300370300200041a0016a41086a22182037290300370300200041a0016a41106a2237202f290300370300200041a0016a41186a222f2038280200360200200020002903e0033703b004200020002903a0033703a0012003200c2903003703002014200d290300370300200b202c290300370300200a202d290300370300201f2036290300370300201020352903003703002001201c290300370300200020002903b004370380052002201829030037030020152037290300370300201a202f280200360200200020002903a0013703e0030240201e201d470d00201d41016a2218201d490d0a201d410174221c2018201c20184b1bad42e0007e2205422088a70d0a2005a722184100480d0a02400240201d0d002018102d21120c010b2012201d41e0006c2018103121120b2012450d05201841e0006e211e0b200641206a211c2012201d41e0006c6a2218200029038005370300201841106a2014290300370300201841086a20032903003703002010290300210520012903002107201f2903002130200a290300210f200b2903002131201841c0006a2017360200201841186a2031370300201841206a200f370300201841286a2030370300201841386a2007370300201841306a2005370300201841c4006a20002903e003370200201841cc006a2002290300370200201841d4006a2015290300370200201841dc006a201a280200360200201d41016a211d20132006470d000b0b200041a0056a20083602002000419c056a201136020020004190056a2009ad4220862020ad843703002000201b360298052000202a36028c0520004284808080c000370284052000203936028005200841246c41046a2206417f4c0d030240024020060d00410121170c010b2006102d2217450d030b200041003602b804200020063602b404200020173602b0042008200041b0046a10690240024020080d0020002802b804211920002802b404211620002802b00421180c010b201b200841246c6a2110410020002802b80422196b211a20002802b4042116201b2106034020062802002117024002402016201a6a4104490d0020002802b00421180c010b201941046a22182019490d0a201641017422152018201520184b1b22154100480d0a0240024020160d002015102d21180c010b20002802b00420162015103121180b2018450d05200020153602b404200020183602b004201521160b2000201941046a22153602b804201820196a20173600004120102d2217450d04201741186a22022006411c6a290000370000201741106a221c200641146a290000370000201741086a22082006410c6a2900003700002017200641046a29000037000002402016201a6a417c6a411f4b0d00201541206a22012015490d0a201641017422152001201520014b1b22154100480d0a0240024020160d002015102d21180c010b201820162015103121180b2018450d05200020153602b404200020183602b004201521160b201820196a2215410c6a2008290000370000201541146a201c2900003700002015411c6a20022900003700002000201941246a22193602b804201541046a20172900003700002017102f201a415c6a211a200641246a22062010470d000b0b41ed9bca00ad4280808080800184100122062900002105200041e0036a41086a200641086a290000370300200020053703e0032006102f41f59bca00ad4280808080a00284100122062900002105200041b0046a41086a200641086a290000370300200020053703b0042006102f4110102d2206450d02200641086a41002902b8f646370000200641002902b0f6463700002006ad4280808080800284100322172900002105201741086a2900002107201741106a290000213020004190026a41186a221a201741186a29000037030020004190026a41106a203037030020004190026a41086a200737030020002005370390022017102f2006102f41c000102d2206450d02200620002903e003370000200620002903b0043700102006200029039002370020200641086a200041e0036a41086a290300370000200641186a200041b0046a41086a290300370000200641286a20004190026a41086a290300370000200641306a200041a0026a290300370000200641386a201a290300370000200041c0003602b404200020063602b00420182019200041b0046a109d022006102f02402016450d002018102f0b200041b0046a20004180056a10b10320002802b0042106200020002802b8043602e403200020063602e003202a2009200041e0036a108301024020002802b404450d002006102f0b2039102f02402020450d00202a102f0b02402011450d00201b102f0b20120d010b2000280280032119024020004188036a2802002206450d00200641d0006c2117201941c0006a210603400240200641046a280200450d002006280200102f0b200641d0006a2106201741b07f6a22170d000b0b024020004184036a280200450d002019102f0b4183d1ca00ad4280808080c00184100841f4d0ca00ad4280808080f0018410080c050b4104102d2206450d002006200436000020004188056a4284808080c0003703004100211920004198056a41002902b8f646370300200041103a00800520004180056a41106a41002902b0f646370300200020063602840541c8e1ca00410020004180056a108c010240202b410a6e417f73201d6a2217201d4b0d002000418094ebdc03360284052000202b4101202b41014b1b2206201741036c221720062017491b2006418094ebdc036e22174101201741014b1b22176ead428094ebdc037e200620176ead8042ffffffff0f834280bbb0217e428094ebdc0380a722063602800520004180056a2006418094ebdc034b4102746a28020021190b201d450d02201d41ffffffff0371201d470d05201d41027422064100480d052006102d2218450d0020064102762116201d211720182106034020062019360200200641046a21062017417f6a22170d000b2012201d2018201d200410b30302402016450d002018102f0b201d450d03201d41e0006c2117201241d4006a210603400240200641706a280200450d002006416c6a280200102f0b02402006280200450d002006417c6a280200102f0b200641e0006a2106201741a07f6a22170d000c040b0b1036000b103d000b2012410041044100200410b3030b0240201e450d002012102f0b2000280280032119024020004188036a2802002206450d00200641d0006c2117201941c0006a210603400240200641046a280200450d002006280200102f0b200641d0006a2106201741b07f6a22170d000b0b20004184036a280200450d002019102f0b02402032a7450d00200e4101200e1b102f0b20004180066a24000f0b1038000be70703047f017e037f23004180016b22022400200241286a41186a4200370300200241286a41106a22034200370300200241286a41086a220442003703002002420037032841eba1ca00ad4280808080f000841001220529000021062004200541086a290000370300200220063703282005102f41adcac800ad4280808080900184100122052900002106200241086a41086a2207200541086a290000370300200220063703082005102f200320022903082206370300200241d8006a41086a2004290300370300200241d8006a41106a2006370300200241d8006a41186a200729030037030020022002290328370358200241286a200241d8006a10fd03024002400240024020022903284202520d00200041003602200c010b200241086a200328020010bd034120102d2204450d0120042001290000370000200441186a200141186a290000370000200441106a200141106a290000370000200441086a200141086a29000037000020022004ad4280808080800484100622012900003703782001102f200241346a200441206a360200200241003a0038200220043602302002200241f8006a41086a36022c2002200241f8006a360228200241d8006a200241286a106c2004102f2002280258210702400240200228020c2205200228021022016b20022802602203490d00200228020821040c010b200120036a22042001490d03200541017422082004200820044b1b22084100480d030240024020050d002008102d21040c010b200228020820052008103121040b2004450d022002200836020c20022004360208200821050b2002200120036a2208360210200420016a2007200310e8061a0240200228025c450d002007102f0b200241286a2004200810bc03200241d8006a41186a2207200241286a41186a290300370300200241d8006a41106a2208200241286a41106a290300370300200241d8006a41086a2209200241286a41086a29030037030020022002290328370358200241d4006a28020021030240024020022802482201450d00200241086a41086a2009290300370300200241086a41106a2008290300370300200241086a41186a200729030037030020022002290358370308200229024c21060c010b42002106200241086a41186a4200370300200241086a41106a4200370300200241086a41086a420037030020024200370308410821010b02402005450d002004102f0b2000200229030837030020002006370224200020013602202000412c6a2003360200200041186a200241086a41186a290300370300200041106a200241086a41106a290300370300200041086a200241086a41086a2903003703000b20024180016a24000f0b1036000b1038000be50607027f017e0b7f027e017f017e037f230041206b2202240002400240024020012802082203ad42d0007e2204422088a70d002004a72205417f4c0d0020012802002106024002400240024020050d002006200341d0006c6a210741082108200321090c010b2005102d2208450d052006200341d0006c6a21070240200541d0006e22012003490d00200121090c010b2001410174220a2003200a20034b1b220941d0006c220a4100480d0402400240200541cf004b0d00200a102d21080c010b2008200141d0006c200a103121080b2008450d050c010b20030d00410021030c010b200341047441706a410476210b2008210c0340200241186a220d200641186a290300370300200241106a220e200641106a290300370300200241086a220f200641086a29030037030020022006290300370300200641c8006a2802002203ad42307e2204422088a70d022004a72201417f4c0d02200641386a2903002104200641306a2903002110200641286a2903002111200641c0006a2802002112200629032021130240024002400240024020010d002012200341306c6a211441082115200321050c010b2001102d2215450d082012200341306c6a2114200141306e220520034f0d002005410174220a2003200a20034b1b221641306c22034100480d07024002402001412f4b0d002003102d21150c010b2015200541306c2003103121150b20150d010c080b2003450d01200521160b410021014100210a0340201520016a2205201220016a22032903003703002005200341086a290300370308200541106a200341106a290300370300200541186a200341186a290300370300200541206a200341206a290300370300200541286a200341286a290300370300200141306a2101200a41016a210a200341306a2014470d000b201621050c010b4100210a0b200c2013370320200c2002290300370300200c41386a2004370300200c41306a2010370300200c41286a2011370300200c41c8006a200a360200200c41c4006a2005360200200c41c0006a2015360200200c41186a200d290300370300200c41106a200e290300370300200c41086a200f290300370300200c41d0006a210c200641d0006a22062007470d000b200b41016a21030b200020033602082000200936020420002008360200200241206a24000f0b103d000b1038000b1036000bc20605027f017e017f027e047f230041c0006b2202240041ed9bca00ad4280808080800184100122032900002104200241086a200341086a290000370300200220043703002003102f4198f1c600ad4280808080e00284100122032900002104200241106a41086a200341086a290000370300200220043703102003102f02400240024002404110102d2203450d00200341086a41002902b8f646370000200341002902b0f6463700002003ad4280808080800284100322052900002104200541086a2900002106200541106a2900002107200241206a41186a2208200541186a290000370300200241206a41106a2007370300200241206a41086a2006370300200220043703202005102f2003102f41c000102d2203450d00200320022903003700002003200229031037001020032002290320370020200341086a200241086a290300370000200341186a200241106a41086a290300370000200341286a200241206a41086a290300370000200341306a200241306a290300370000200341386a20082903003700002001280208220541046a2208417f4c0d01200128020021090240024020080d00410121010c010b2008102d2201450d010b2002410036022820022008360224200220013602202005200241206a1069024002402002280224220a200228022822016b2005490d00200228022021080c010b200120056a22082001490d03200a410174220b2008200b20084b1b220b4100480d0302400240200a0d00200b102d21080c010b2002280220200a200b103121080b2008450d012002200b36022420022008360220200b210a0b200820016a2009200510e8061a200120056aad4220862008ad84100322052900002104200541086a2900002106200541106a2900002107200241206a41186a200541186a290000370300200241206a41106a2007370300200241206a41086a2006370300200220043703202005102f0240200a450d002008102f0b200341c000418001103122030d030b1036000b103d000b1038000b20032002290320370040200341d8006a200241386a290300370000200341d0006a200241306a290300370000200341c8006a200241286a29030037000020004280818080800c37020420002003360200200241c0006a24000bab0f03027f037e0f7f230041d0026b2202240041ed9bca00ad4280808080800184100122032900002104200241e8006a41086a200341086a290000370300200220043703682003102f4194bbc600ad4280808080f00084100122032900002104200241b0016a41086a200341086a290000370300200220043703b0012003102f02400240024002404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100322012900002104200141086a2900002105200141106a2900002106200241f0016a41186a2207200141186a290000370300200241f0016a41106a22082006370300200241f0016a41086a2005370300200220043703f0012001102f2003102f41c000102d2209450d0020092002290368370000200920022903b001370010200920022903f001370020200941086a200241e8006a41086a290300370000200941186a200241b0016a41086a220a290300370000200941286a200241f0016a41086a220b290300370000200941306a2008290300370000200941386a2007290300370000200241c00036024420022009360240200241c8006a2009ad4280808080800884100210730240200228024822070d00410021030c040b200228024c210c2002200241c8006a41086a28020022083602ac01200220073602a80141002103200241003a002002400240034020082003460d01200220036a200720036a22012d00003a00002002200141016a3602a8012002200341016a22013a00202001210320014120470d000b200241b0026a41086a220d200241086a220e290300370300200241b0026a41106a220f200241106a2210290300370300200241b0026a41186a2211200241186a2212290300370300200220022903003703b0022002200820016b3602ac012002200241a8016a108a0520022802202203450d01200241f0016a41186a22082011290300370300200241f0016a41106a2211200f290300370300200241f0016a41086a220f200d290300370300200241f0016a41286a220d200e290300370300200241f0016a41306a220e2010290300370300200241f0016a41386a22102012290300370300200220022903b0023703f0012002200229030037039002200241246a2802002101200241286a22122903002104200241b0016a41086a200f290300370300200241b0016a41106a2011290300370300200241b0016a41186a2008290300370300200241b0016a41206a2208200229039002370300200241b0016a41286a220f200d290300370300200241b0016a41306a220d200e290300370300200241b0016a41386a220e2010290300370300200220022903f0013703b001200241f0016a200241a8016a10980320022802f0010d032001450d012003102f0c010b200241003602ac01200341ff0171450d00200241003a00200b41002103200241003602b801200242013703b0012002410b36026c2002200241c0006a3602682002200241b0016a36020020024184026a4101360200200242013702f401200241b885c7003602f0012002200241e8006a36028002200241d8dbc100200241f0016a103c1a20023502b80142208620023502b001841008024020022802b401450d0020022802b001102f0b0c020b1036000b200241d8006a41086a2210200241f0016a41086a280200360200200241e8006a41086a2211200241b0016a41086a290300370300200241e8006a41106a2213200241b0016a41106a290300370300200241e8006a41186a2214200241b0016a41186a290300370300200241e8006a41206a22152008290300370300200241e8006a41286a2208200f290300370300200241e8006a41306a220f200d290300370300200241e8006a41386a220d200e290300370300200220022903f001370358200220022903b001370368200241386a200d290300370300200241306a200f29030037030020122008290300370300200241206a2015290300370300200241186a2014290300370300200241106a2013290300370300200241086a2011290300370300200241b0026a41086a201028020036020020022002290368370300200220022903583703b0020b200c450d002007102f0b200b200241086a290300370300200241f0016a41106a2207200241106a290300370300200241f0016a41186a2208200241186a290300370300200241f0016a41206a220b200241206a290300370300200241f0016a41286a200241286a290300370300200241f0016a41306a200241306a290300370300200241f0016a41386a200241386a290300370300200220022903003703f001200a200241b0026a41086a280200360200200220022903b0023703b00102402003450d00200020022903f00137030020002001360244200041c8006a2004370200200041386a200241f0016a41386a290300370300200041306a200241f0016a41306a290300370300200041286a200241f0016a41286a290300370300200041206a200b290300370300200041186a2008290300370300200041106a2007290300370300200041086a200241f0016a41086a290300370300200041d8006a200241b0016a41086a280200360200200041d0006a20022903b0013702000b200020033602402009102f200241d0026a24000bc94312047f017e017f017e077f027e047f017e087f027e027f027e017f017e057f017e027f027e230041d0036b22052400200541f8026a41186a22064200370300200541f8026a41106a22074200370300200541f8026a41086a22084200370300200542003703f80241eba1ca00ad4280808080f0008422091001220a290000210b200541d8026a41086a220c200a41086a2900003703002005200b3703d802200a102f2008200c290300370300200520052903d8023703f80241f9a0ca00ad4280808080b002841001220a290000210b200541e8026a41086a220c200a41086a2900003703002005200b3703e802200a102f200720052903e802220b370300200541a8036a41086a220d2008290300370300200541a8036a41106a220e200b370300200541a8036a41186a220f200c290300370300200520052903f8023703a803200541203602ec022005200541a8036a3602e802200541d8016a200541a8036aad4280808080800484220b100210730240024020052802d801220a0d004100210c0c010b20052802dc01211002400240200541d8016a41086a2802004104490d00200a28000021114101210c0c010b4100210c2005410036028002200542013703f8012005410b3602dc022005200541e8026a3602d8022005200541f8016a3602a8022005418c036a4101360200200542013702fc02200541b885c7003602f8022005200541d8026a36028803200541a8026a41d8dbc100200541f8026a103c1a20053502800242208620053502f801841008024020052802fc01450d0020052802f801102f0b0b2010450d00200a102f0b200642003703002007420037030020084200370300200542003703f80220091001220a29000021092008200a41086a290000370300200520093703f802200a102f41adcac800ad42808080809001841001220a2900002109200541f8016a41086a2206200a41086a290000370300200520093703f801200a102f200720052903f8012209370300200d2008290300370300200e2009370300200f2006290300370300200520052903f8023703a803200541f8026a200541a8036a10fd03024020052903f8024202510d002007280200211241eba1ca00ad4280808080f00084100122082900002109200541f8016a41086a220a200841086a290000370300200520093703f8012008102f41dca0ca00ad4280808080d00284100122082900002109200541a8036a41086a2206200841086a290000370300200520093703a8032008102f200520123602d801200541d8016aad4280808080c00084100322082900002109200841086a2900002113200841106a2900002114200541f8026a41186a220d200841186a290000370300200541f8026a41106a220e2014370300200541f8026a41086a220f2013370300200520093703f8022008102f02400240024041c000102d2208450d00200820052903f801370000200820052903a803370010200820052903f802370020200841086a200a290300370000200841186a2006290300370000200841286a200f290300370000200841306a200e290300370000200841386a200d290300370000200541d0016a200841c00010950120052802d401210620052802d001210a2008102f02400240200a0d0041aacfc800ad4280808080e0068410084100201241e07a6a2208200820124b1b2115201221160c010b4100201241e07a6a2208200820124b1b21150240200620044b0d00201221160c010b200541f8026a41186a22064200370300200541f8026a41106a220d4200370300200541f8026a41086a22084200370300200542003703f80241eba1ca00ad4280808080f000841001220a2900002109200541d8026a41086a220e200a41086a290000370300200520093703d802200a102f2008200e290300370300200520052903d8023703f802418ca1ca00ad4280808080a001841001220a2900002109200541e8026a41086a220e200a41086a290000370300200520093703e802200a102f200720052903e802370000200741086a200e290300370000200541a8036a41086a2008290300370300200541a8036a41106a200d290300370300200541a8036a41186a2006290300370300200520052903f8023703a803200541f8026a200541a8036a109d0520052802f8022208410420081b220d20052902fc02420020081b2209422088a741037422086a210a03402008450d04200841786a2108200a417c6a2106200a41786a210a200628020020044b0d000b200d20086a28020021162009a7450d00200d102f0b200541f8026a41186a22174200370300200541f8026a41106a22184200370300200541f8026a41086a22104200370300200542003703f80241eba1ca00ad4280808080f000842219100122082900002109200541d8026a41086a221a200841086a290000370300200520093703d8022008102f2010201a290300370300200520052903d8023703f8024196a1ca00ad4280808080e002842209100122082900002113200541e8026a41086a221b200841086a290000370300200520133703e8022008102f200720052903e802370000200741086a221c201b290300370000200541a8036a41086a221d2010290300370300200541a8036a41106a221e2018290300370300200541a8036a41186a221f2017290300370300200520052903f8023703a803200541c8016a200541a8036a412010950120052802cc01210a20052802c8012106201742003703002018420037030020104200370300200542003703f8022019100122082900002113201a200841086a290000370300200520133703d8022008102f2010201a290300370300200520052903d8023703f8022009100122082900002109201b200841086a290000370300200520093703e8022008102f200720052903e802370000201c201b290300370000201d2010290300370300201e2018290300370300201f2017290300370300200520052903f8023703a8032005200a201220064101461b3602f802200b200541f8026aad22094280808080c00084100420032001200120034b1b2220450d0320114100200c1b2121200541a8026aad4280808080c000842122200942808080808002842123201241016a21242000210f410021250340201742003703002018420037030020104200370300200542003703f8022019100122082900002109201a200841086a290000370300200520093703d8022008102f2010201a290300370300200520052903d8023703f80241c4aac900ad4280808080d00184100122082900002109201b200841086a290000370300200520093703e8022008102f200720052903e802370000201c201b290300370000201d2010290300370300201e2018290300370300201f2017290300370300200520052903f8023703a803200541f8026a200541a8036a412010aa0220052902fc02420020052802f80222081b2209422088a7410574210a2025220641016a2125200220064102746a210e2000200641e0006c6a210c2008410120081b220d2108024003400240200a0d00410021040c020b41012104200f2008460d012008200c412010ea062106200a41606a210a200841206a210820060d000b0b02402009a7450d00200d102f0b024020040d00200e2802002108200542003703a0022005420037039802200541b8016a200c2903202209200c41286a290300428094ebdc03420010ee0620054198016a200c290330220b200c41386a290300428094ebdc03420010ee06200541a8016a20052903b8012214200541b8016a41086a29030022264280ec94a37c427f10ed06200541e8006a201420262008ad2213420010ed0620054188016a200529039801221420054198016a41086a29030022264280ec94a37c427f10ed06200541f8006a201420262013420010ed06200542003703b002200542003703a802200b2005290388017c20137e2214428094ebdc0380210b02400240024020052903684200200920052903a8017c20137e22092009428094ebdc038022094280ec94a37c7e7c4280cab5ee01562009a76a220aad7d85200541e8006a41086a2903004200200a410047ad7d8584500d0020052903782126200541f8006a41086a2903002127200541d8016a2016200c10e60520052802d801210a200520052802e00122063602ec022005200a3602e802200541f8016a2006ad422086200aad84100210730240024020052802f80122060d00420021090c010b20052802fc01210402400240200528028002220d4104490d00200d417c6a410f4d0d0020062800002128420121090c010b200541003602b003200542013703a8032005410b3602dc022005200541e8026a3602d8022005200541a8036a3602cc032005410136028c03200542013702fc02200541b885c7003602f8022005200541d8026a36028803200541cc036a41d8dbc100200541f8026a103c1a20053502b00342208620053502a803841008024020052802ac03450d0020052802a803102f0b420021090b2004450d002006102f0b024020052802dc01450d00200a102f0b20082028410020094200521b22034d0d03200541f8026a2016200c10e605200535028003212920052802f80221064110102d220a450d05200a2008360000200a4110412010312208450d05200820262014200b4280ec94a37c7e7c4280cab5ee0156200ba76aad7c22093700042008410c6a20272009202654ad7c220b37000020294220862006ad842008ad4280808080c0028410042008102f024020052802fc02450d002006102f0b200541f8016a200c10eb05200528028402450d01200541d8016a41106a200541f8016a41106a290300370300200541d8016a41086a200541f8016a41086a290300370300200520052903f8013703d8010c020b200542003703e002200542003703d802200542003703f002200542003703e802200541f8016a200c10eb0502400240200528028402450d00200541d8016a41106a200541f8016a41106a290300370300200541d8016a41086a200541f8016a41086a290300370300200520052903f8013703d8010c010b200542003703b80320054280808080c0003703b003200520153602ac03200541003602a803200c200541a8036a10ec05200541d8016a41106a20052903b803370300200541d8016a41086a20052903b003370300200520052903a8033703d8010b201020052903d801370200201041086a200541d8016a41086a290300370200201041106a200541d8016a41106a290300370200200541003a00a4032005200c3602fc02200520153602f802200520213602a0032005200541e8026a36029c032005200541d8026a36029803200541a8036a200541f8026a201610b703024020052802b0034102460d0020052802a803220d200528028003470d00410021080240202420052802840322064d0d000240200528029403220a200528029003470d00200a41016a2208200a490d08200a41017422042008200420084b1b220841ffffffff03712008470d08200841027422084100480d0802400240200a0d002008102d21040c010b200528028c03200a4102742008103121040b2004450d072005200436028c0320052008410276360290030b200528028c03220841046a2008200a41027410e9061a2008202420066b3602002005202436028403410121082005200a41016a360294032005200d41016a220d360280030b200520083a00a403200c10e805200c10e9050240200c10a20441ff0171220a4102460d00200a410171450d0010f5050b2008450d00200528028403210e0240024002402005280294032201450d00200528028c03210a2001410274210441002106200e210802400340200820154d0d01200641016a21062008200a2802006b2108200a41046a210a2004417c6a22040d000c020b0b200120064f0d010b2005200e2015200e20154b1b360284030c010b2005200e2015200e20154b1b36028403200520063602940341000d00200d20016b200d20066b4f0d00410020016b21080340201d200c41086a290200370300201e200c41106a290200370300201f200c41186a2902003703002005200c2902003703a8032005200d20086a3602c803200541a8036a10ed052006200841016a22086a0d000b0b200c201010ec050b200528029003450d02200528028c03102f0c020b200542003703b80320054280808080c0003703b003200520153602ac03200541003602a803200c200541a8036a10ec05200541d8016a41106a20052903b803370300200541d8016a41086a20052903b003370300200520052903a8033703d8010b201020052903d801370200201041086a222a200541d8016a41086a222b290300370200201041106a222c200541d8016a41106a222d290300370200200541003a00a4032005200c3602fc02200520153602f802200520213602a0032005200541a8026a36029c03200520054198026a36029803200541e0006a200541f8026a20162009200b10b803200528028003210e02400240024020052802604101470d002005280264220a200e460d010b20052d00a40321080c010b02400240202420052802840322084d0d0002402005280294032206200528029003470d00200641016a22042006490d072006410174220d2004200d20044b1b220441ffffffff03712004470d07200441027422044100480d070240024020060d002004102d210d0c010b200528028c03200641027420041031210d0b200d450d062005200d36028c0320052004410276360290030b200528028c03220441046a2004200641027410e9061a2004202420086b3602002005202436028403410121082005200641016a360294032005200a41016a220a360280030c010b20052d00a40321080b200520083a00a403200c10e805200c10e9050240200c10a20441ff017122064102460d002006410171450d0010f5050b200a210e0b0240200841ff0171450d00200528028403210120052802f802210d0240024002402005280294032211450d00200528028c03210a201141027421044100210620012108024003402008200d4d0d01200641016a21062008200a2802006b2108200a41046a210a2004417c6a22040d000c020b0b201120064f0d010b20052001200d2001200d4b1b360284030c010b20052001200d2001200d4b1b36028403200520063602940341000d00200e20116b200e20066b4f0d00410020116b210a20052802fc0221080340201f200841186a290000370300201e200841106a290000370300201d200841086a290000370300200520082900003703a8032005200e200a6a3602c803200541a8036a10ed052006200a41016a220a6a0d000b0b20052802fc02201010ec050b0240200528029003450d00200528028c03102f0b42002109200542003703e002200542003703d8020240024002400240200c41c8006a220a28020022080d00410821110c010b2008ad42307e2209422088a70d062009a722084100480d062008102d2211450d05200841306ead2109200a28020022080d010b42002114420021260c010b200c41c0006a2802002201200841306c6a212e2003ad21290340200542003703f002200542003703e802200541386a20012903002226200141086a290300428094ebdc03420010ee06200541286a2005290338220b200541386a41086a29030022144280ec94a37c427f10ed06200541186a200b20142029420010ed06200541086a200b20142013420010ed06200541f8026a2016200141106a220d10e705200541c8006a20052802f802220a200528028003109c014200200541086a41086a29030020052903082214202620052903287c222620137e220b200b428094ebdc0380220b4280ec94a37c7e7c4280cab5ee0156200ba76aad7c220b201454ad7c2214200541186a41086a29030020052903182227202620297e22262026428094ebdc038022264280ec94a37c7e7c4280cab5ee01562026a76aad7c2226202754ad7c7d200b202654ad7d2227200b20267d2226200b56202720145620272014511b22081b21144200202620081b210b200541c8006a41106a29030021262005290350212720052802482108024020052802fc02450d00200a102f0b200541a8036a2016200d10e70520052802a803210a20053502b003212f20052027420020081b2227200b7c220b3703f80220052026420020081b20147c200b202754ad7c221437038003202f422086200aad8420231004024020052802ac03450d00200a102f0b200541f8016a200d10eb0502400240200528028402450d00202d200541f8016a41106a290300370300202b200541f8016a41086a290300370300200520052903f8013703d8010c010b200542003703b80320054280808080c0003703b003200520153602ac03200541003602a803200d200541a8036a10ec05202d20052903b803370300202b20052903b003370300200520052903a8033703d8010b201020052903d801370200202a202b290300370200202c202d290300370200200541003a00a4032005200d3602fc02200520153602f802200520213602a0032005200541e8026a36029c032005200541d8026a360298032005200541f8026a2016200b201410b803200528028003210302400240024020052802004101470d00200528020422062003470d00202420052802840322084d0d010240200528029403220a200528029003470d00200a41016a2204200a490d09200a410174220e2004200e20044b1b220441ffffffff03712004470d09200441027422044100480d0902400240200a0d002004102d210e0c010b200528028c03200a41027420041031210e0b200e450d082005200e36028c0320052004410276360290030b200528028c03220441046a2004200a41027410e9061a2004202420086b3602002005202436028403410121082005200a41016a360294032005200641016a220336028003200541013a00a4030c020b20052d00a40321080c010b200520052d00a40322083a00a403200621030b0240200841ff0171450d00200528028403213020052802f802210e0240024002402005280294032231450d00200528028c03210a203141027421044100210620302108024003402008200e4d0d01200641016a21062008200a2802006b2108200a41046a210a2004417c6a22040d000c020b0b203120064f0d010b20052030200e2030200e4b1b360284030c010b20052030200e2030200e4b1b36028403200520063602940341000d00200320316b200320066b4f0d00410020316b210a20052802fc0221080340201f200841186a290000370300201e200841106a290000370300201d200841086a290000370300200520082900003703a80320052003200a6a3602c803200541a8036a10ed052006200a41016a220a6a0d000b0b20052802fc02201010ec050b0240200528029003450d00200528028c03102f0b200d41086a290000210b200d29000021142017200d41186a2900003703002018200d41106a2900003703002010200b370300200520143703f802201b290300210b20052903e80221140240024020094220882226a722082009a7460d002008210a0c010b200841016a22062008490d062026a7220a4101742204200620062004491bad42307e2209422088a70d062009a722064100480d060240024020080d002006102d21110c010b2011200841306c2006103121110b2011450d05200641306ead21090b20102903002126201829030021272017290300212f20052903f80221322011200a41306c6a2208201437032020082032370300200841286a200b370300200841186a202f370300200841106a2027370300200841086a2026370300200942ffffffff0f83200a41016aad422086842109200141306a2201202e470d000b201a290300212620052903d80221140b20054198026a41086a29030021272005290398022113202b200c41086a290300370300202d200c41106a290300370300200541d8016a41186a2208200c41186a2903003703002005200c2903003703d8012011450d00200541a8026a41086a290300212920052903a802212f200541f8016a41186a22012008290300370300200541f8016a41106a2203202d290300370300200541f8016a41086a2230202b290300370300200520052903d8013703f8010240024002400240200c280258220841ffffff3f712008470d0020084105742204417f4c0d00200c280250210c024020040d00200c20046a21064101210d2008210e0c020b2004102d220d450d06200c20046a21062004410576220e20084f0d01200e410174220a2008200a20084b1b220841ffffff3f712008470d07200841057422084100480d0702400240200e0d002008102d210d0c010b200d200e41057420081031210d0b200d450d062008410576210e0c020b103d000b20080d004100210c0c010b200d2108200c210a03402008200a290000370000200841186a200a41186a290000370000200841106a200a41106a290000370000200841086a200a41086a290000370000200841206a21082006200a41206a220a470d000b200c20046a200c6b41606a41057641016a210c0b201f2001290300370300201e2003290300370300201d2030290300370300200520052903f8013703a803201910012208290000210b201a200841086a2900003703002005200b3703d8022008102f41e0cfc800ad428080808080028410012208290000210b201b200841086a2900003703002005200b3703e8022008102f200520123602a80220221003220841086a290000210b200841106a2900002132200829000021332017200841186a290000370300201820323703002010200b370300200520333703f8022008102f41c000102d2206450d02200620052903d802370000200620052903e802370010200620052903f80237002041082104200641086a200541d8026a41086a290300370000200641186a200541e8026a41086a290300370000200641286a200541f8026a41086a290300370000200641306a2018290300370000200641386a2017290300370000200541f8026a2006109a050240024020052802f80222010d004100210a4200210b410021080c010b20052902fc02220b422088a7210a200ba72108200121040b2017201f2903003703002018201e2903003703002010201d290300370300200520052903a8033703f8020240200a2008470d000240200a200ba7470d00200a41016a2208200a490d05200a41017422012008200120084b1bad42d8007e2232422088a70d052032a722084100480d0502400240200a0d002008102d21040c010b2004200a41d8006c2008103121040b2004450d04200b42808080807083200841d8006ead84210b0b200b422088a7210a0b2004200a41d8006c22016a2208201320147c2214370310200820293703082008202f3703002008200d36022c20082011360220200841186a202720267c2014201354ad7c370300200841346a200c360200200841306a200e360200200841246a2009370200200820052903f802370338200841c0006a2010290300370300200841c8006a2018290300370300200841d0006a20172903003703000240024020040d002006ad428080808080088410050c010b200541f8026a2004200a41016a220810f9052006ad428080808080088420053502800342208620052802f802220aad841004024020052802fc02450d00200a102f0b200ba7210c02402008450d00200441306a2108200141d8006a210a03400240200841746a280200450d00200841706a280200102f0b02402008280200450d002008417c6a280200102f0b200841d8006a2108200a41a87f6a220a0d000b0b200c450d002004102f0b2006102f0b200f41e0006a210f20252020490d000c040b0b1036000b1038000b2009a7450d00200d102f0b200541d0036a24000bfb1808017f047e017f057e047f057e057f047e230041c0056b22052400200541c0046a200010b50302400240024020052d00c0044101470d00200541086a41186a200541d9046a290000370300200541186a200541d1046a290000370300200541086a41086a200541c9046a290000370300200520052900c104370308200541c0046a200541086a10810320052802ec044102460d00200541286a200541c0046a41d80010e8061a200541286a41086a290300210620052903282107024002402005290338220820012008200154200541286a41186a290300220920025420092002511b220a1b220b20092002200a1b220c8450450d002007210d2006210e0c010b200541c0006a220a2009200c7d2008200b54ad7d220f37030020052008200b7d220d37033802400240200d428080e983b1de1656200f420052200f501b450d00200b2108200c21090c010b200a420037030020054200370338200f20027c200d20017c2201200d54ad7c21020b20054200200620097d2007200854ad7d220b200720087d220f200756200b200656200b2006511b220a1b220e37033020054200200f200a1b220d370328200220097d2001200854ad7d2102200120087d21010b02400240200541d0006a28020022100d004100210a410021100c010b2005280248210a201041186c21114100211003400240200a2903002208200120012008562002200a41086a221229030022095620022009511b22131b220b2009200220131b220c84500d00200a2008200b7d220d370300200a2009200c7d2008200b54ad7d220f37030802400240200d428080e983b1de1656200f420052200f501b450d002001210f200b2108200c21090c010b200a4200370308200a42003703002002200f7c2001200d7c220f200154ad7c21020b200541286a41086a221342002013290300220120097d2005290328220b200854ad7d220c200b20087d220d200b56200c200156200c2001511b22131b220e37030020054200200d20131b220d370328200220097d200f200854ad7d2102200f20087d210120122903002109200a29030021080b024020082009844200520d00200a41186a210a201041016a2110201141686a22110d010b0b2005280250220a2010490d020b200541003602500240200a20106b220a450d0002402010450d00200528024822132013201041186c6a200a41186c10e9061a0b2005200a3602500b024042002007200d7d220820082007562006200e7d2007200d54ad7d220820065620082006511b220a1b220242002008200a1b220184500d00418de6c300ad4280808080e000841001220a290000210820054188026a41086a200a41086a2900003703002005200837038802200a102f41f0e8c600ad4280808080f000841001220a290000210820054180016a41086a200a41086a2900003703002005200837038001200a102f4120102d220a450d03200a2000290000370000200a41186a200041186a290000370000200a41106a200041106a290000370000200a41086a200041086a290000370000200aad4280808080800484100322102900002108201041086a2900002109201041106a290000210b200541c0046a41186a2213201041186a290000370300200541c0046a41106a2211200b370300200541c0046a41086a2009370300200520083703c0042010102f200a102f41c000102d220a450d03200a200529038802370000200a200529038001370010200a20052903c004370020200a41086a20054188026a41086a290300370000200a41186a20054180016a41086a290300370000200a41286a200541c0046a41086a290300370000200a41306a2011290300370000200a41386a201329030037000020054180016a200a10f602200529038001210e4200210b2005420037038001200541c8016a280200211320052d00cc01211102400240200e4201510d00200541d0016a41306a4200370300200541d0016a41286a4200370300200541d0016a41206a4200370300200541e8016a4200370300200541e0016a4200370300200541d0016a41086a4200370300200542003703d0014200210c4200210942002108420021140c010b20054180016a41386a290300210f20054180016a41306a290300210d20054180016a41206a290300210c20054180016a41186a290300210b20054180016a41c0006a290300211420052903900121082005290388012109200541d0016a41206a20054180016a41286a290300370300200541d0016a41286a200d370300200541d0016a41306a200f370300200541e0016a200b3703002005200c3703e801200520093703d001200520083703d8010b20052009200220092009200256200820015620082001511b22101b220d7d22063703d001200520082001200820101b22157d2009200d54ad7d220f3703d8012008200c7c2009200b7c22162009542212ad7c2109200541d0016a41106a2110024002402002200d7d2207200120157d2002200d54ad7d22178450450d004200210b4200211720022115200121180c010b200541e8016a200c2017200c200b200756200c201756200c2017511b22191b22187d200b2007200b20191b220c54ad7d3703002005200b200c7d3703e001201720187d2007200c54ad7d2117201820157c200c200d7c2215200c54ad7c21182007200c7d210b0b200920085121192009200854211a20054188026a41186a201041086a290300220837030020054188026a41206a221b201041106a290300370300200541b0026a221c201041186a290300370300200541b8026a221d201041206a29030037030020052010290300220c3703980220052006370388022005200f3703900202400240427f2006200c7c220c200c2006542210200f20087c2010ad7c2208200f542008200f511b22101b220c428080e983b1de16544100427f200820101b220d501b0d0020054198026a290300210c201d290300210d201c2903002107201b290300211e200529039002211f20052903880221204201210820052903a00221210c010b420021080240200c200d84500d00200c200d109a01200541f8046a200d370300200541f0046a200c370300200541c0046a41086a41013a0000200541c9046a2000290000370000200541d1046a200041086a290000370000200541d9046a200041106a290000370000200541e1046a200041186a290000370000200541033a00c00441c8e1ca004100200541c0046a108c010b0b2012201a20191b2110200541a8016a201e370300200541b0016a200737030020054190016a201f370300200541b8016a200d37030020054198016a200c370300200520213703a001200520143703c0012005202037038801200520114100200e42015122121b3a00cc0120052013410020121b3602c801200520084201512213ad370380010240024020130d00200aad428080808080088410050c010b200541c0003602c4042005200a3602c00420054188016a200541c0046a1090030b427f200920101b2109427f201620101b210c200a102f2008420152210a024002400240200e4201510d00200a0d0041032110200541c0036a210a0c010b200e420152200a410173720d0141042110200541c0026a210a0b200a41046a20103a0000200a41003a0000200a41056a2000290000370000200a410d6a200041086a290000370000200a41156a200041106a290000370000200a411d6a200041186a29000037000041c8e1ca004100200a108c010b0240200c2009844200520d00200541f8046a200f370300200541f0046a2006370300200541c0046a41086a41003a0000200541c9046a2000290000370000200541d1046a200041086a290000370000200541d9046a200041106a290000370000200541e1046a200041186a290000370000200541033a00c00441c8e1ca004100200541c0046a108c010b2004427f2004290300220820157c22092009200854220a200441086a2210290300220820187c200aad7c220920085420092008511b220a1b3703002010427f2009200a1b3703000240200b201784500d002003420020032903002208200b7d22092009200856200341086a220a290300220920177d2008200b54ad7d220820095620082009511b22101b370300200a4200200820101b3703000b200541086a200541286a10b603200541f8046a2001370300200541f0046a2002370300200541c0046a41086a41013a0000200541c9046a2000290000370000200541d1046a200041086a290000370000200541d9046a200041106a290000370000200541e1046a200041186a290000370000200541043a00c00441c8e1ca004100200541c0046a108c010b200541cc006a280200450d002005280248102f0b200541c0056a24000f0b41a6b5ca00411c41f8b4ca001039000b1036000bdb0403027f037e027f230041e0006b2202240041eba1ca00ad4280808080f00084100122032900002104200241306a41086a200341086a290000370300200220043703302003102f41a1cac800ad4280808080e00084100122032900002104200241086a41086a200341086a290000370300200220043703082003102f02404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100322012900002104200141086a2900002105200141106a2900002106200241c0006a41186a2207200141186a290000370300200241c0006a41106a22082006370300200241c0006a41086a2005370300200220043703402001102f2003102f41c000102d2203450d00200320022903303700002003200229030837001020032002290340370020200341086a200241306a41086a290300370000200341186a200241086a41086a290300370000200341286a200241c0006a41086a2201290300370000200341306a2008290300370000200341386a2007290300370000200241086a200341c00010ad022001200241086a41096a2900003703002008200241086a41116a2900003703002007200241086a41196a290000370300200220022900093703400240024020022d00084101460d00200041003a00000c010b200041013a000020002002290340370001200041096a2001290300370000200041116a200241d0006a290300370000200041196a200241d8006a2903003700000b2003102f200241e0006a24000f0b1036000bf90303027f037e027f230041d0006b22022400200242f3e885db96cddbb320370308200241086a200141346a2001290300200141086a290300411f10b00141eba1ca00ad4280808080f00084100122032900002104200241106a41086a200341086a290000370300200220043703102003102f41a7cac800ad4280808080e00084100122032900002104200241206a41086a200341086a290000370300200220043703202003102f02404120102d2203450d0020032000290000370000200341186a200041186a290000370000200341106a200041106a290000370000200341086a200041086a2900003700002003ad4280808080800484100322002900002104200041086a2900002105200041106a2900002106200241306a41186a2207200041186a290000370300200241306a41106a22082006370300200241306a41086a2005370300200220043703302000102f2003102f41c000102d2203450d00200320022903103700002003200229032037001020032002290330370020200341086a200241106a41086a290300370000200341186a200241206a41086a290300370000200341286a200241306a41086a290300370000200341306a2008290300370000200341386a2007290300370000200241c000360234200220033602302001200241306a10f3052003102f200241d0006a24000f0b1036000bbd0101057f2001280208210302402001410c6a280200220420024b0d002000410036020820002004ad4220862003ad843702000f0b024002402001411c6a2802002205450d00200141146a2802002101200541027421062003417f6a2103034002402004200128020022076b220520024b0d00200420024b0d030b200141046a21012003417f6a2103200521042006417c6a22060d000b0b200041023602080f0b2000200736020c2000410136020820002005ad4220862003ad843702000ba51308037f017e017f027e017f017e017f037e230041c0026b22052400200541c0016a2001200210b70302400240024002400240024020052802c8014102460d0020052802c0012106200541c0016a41086a2001280204220741086a290000370300200541c0016a41106a200741106a290000370300200541c0016a41186a200741186a290000370300200520063602e001200520072900003703c00141eba1ca00ad4280808080f00084100122072900002108200541e8016a41086a200741086a290000370300200520083703e8012007102f41b6cbc800ad4280808080900184100122072900002108200541f8016a41086a200741086a290000370300200520083703f8012007102f4104102d2207450d0420074104412010312207450d04200720052903c001370000200741186a200541c0016a41186a290300370000200741106a200541c0016a41106a290300370000200741086a200541c0016a41086a2903003700002007412041c00010312209450d04200920063600202009ad4280808080c00484100322072900002108200741086a290000210a200741106a290000210b20054188026a41186a200741186a29000037030020054188026a41106a200b37030020054188026a41086a200a37030020052008370388022007102f2009102f41c000102d2207450d04200720052903e801370000200720052903f8013700102007200529038802370020200741086a200541e8016a41086a220c290300370000200741186a200541f8016a41086a290300370000200741286a20054188026a41086a290300370000200741306a20054188026a41106a290300370000200741386a20054188026a41186a290300370000200541c0003602ac02200520073602a802200541e8016a2007ad4280808080800884100210730240024020052802e80122090d004200210d0c010b20052802ec01210e024002400240200c280200220c4110490d00200c4170714110470d010b2005410036028002200542013703f8012005410b3602b4022005200541a8026a3602b0022005200541f8016a3602bc022005419c026a41013602002005420137028c02200541b885c700360288022005200541b0026a36029802200541bc026a41d8dbc10020054188026a103c1a20053502800242208620053502f801841008024020052802fc01450d0020052802f801102f0b4200210d0c010b200941186a290000210a200941086a290000210f200929001021082009290000210b4201210d0b200e450d002009102f0b2007102f200a4200200d42005222071b210a2008420020071b2108200b420020071b220d200354200f420020071b220b200454200b2004511b0d01200d200385200b2004858450450d03200541b0016a20032004428094ebdc03420010ee06200541a0016a20052903b001220b200541b0016a41086a290300220d4280ec94a37c427f10ed0620054190016a200b200d2001350228220f420010ed0620054180016a4200200529039001220d200f20052903a00120037c7e220b200b428094ebdc0380220b4280ec94a37c7e7c4280cab5ee0156200ba76aad7c220b20087d220f200f200b5620054190016a41086a290300200b200d54ad7c220d200a7d200b200854ad7d220b200d56200b200d511b22071b220d4200200b20071b428094ebdc03420010ee06200541f0006a200529038001220b20054180016a41086a290300220f4280ec94a37c427f10ed06200541e0006a200b200f4280cab5ee01420010ed06200541e0006a41086a2903002005290360220f200d20052903707c220b4280cab5ee017e428094ebdc03824280cab5ee0156200b420188a76aad7c220b200f54ad7c210d410021070c020b410021070c040b200541c0006a20032004428094ebdc03420010ee06200541d0006a20032004428094ebdc03420010ef06200541306a2005290340200541c0006a41086a2903002001350228220f420010ed06200541206a420020052903302210200f20052903507e220f200f428094ebdc0380220f4280ec94a37c7e7c4280cab5ee0156200fa76aad7c220f20087d22112011200f56200541306a41086a290300200f201054ad7c2210200a7d200f200854ad7d220f201056200f2010511b22071b22104200200f20071b428094ebdc03420010ee06200541106a2005290320220f200541206a41086a29030022114280ec94a37c427f10ed062005200f20114280cab5ee01420010ed06200128022422072003200d7d220f20072903007c2211370300200741086a22072004200b7d2003200d54ad7d20072903007c2011200f54ad7c370300200141106a2207200728020022072002200720024b1b360200200541086a2903002005290300220d201020052903107c220b4280cab5ee017e428094ebdc03824280cab5ee0156200b420188a76aad7c220b200d54ad7c210d410121070b02400240200b200d84500d00200128022022072007290300220f200b7c2210370300200741086a22072007290300200d7c2010200f54ad7c370300200a200d7c2008200b7c220b200854ad7c210a200b21080c010b2007450d010b200141013a002c41eba1ca00ad4280808080f0008410012207290000210b200541e8016a41086a200741086a2900003703002005200b3703e8012007102f41b6cbc800ad428080808090018410012207290000210b200541f8016a41086a200741086a2900003703002005200b3703f8012007102f4104102d2207450d0120074104412010312207450d01200720052903c001370000200741186a200541c0016a41186a290300370000200741106a200541c0016a41106a290300370000200741086a200541c0016a41086a2903003700002007412041c00010312201450d01200120063600202001ad4280808080c0048410032207290000210b200741086a290000210d200741106a290000210f20054188026a41186a200741186a29000037030020054188026a41106a200f37030020054188026a41086a200d3703002005200b370388022007102f2001102f41c000102d2207450d01200720052903e801370000200720052903f8013700102007200529038802370020200741086a200541e8016a41086a290300370000200741186a200541f8016a41086a290300370000200741286a20054188026a41086a290300370000200741306a20054188026a41106a290300370000200741386a20054188026a41186a2903003700004110102d2201450d01200120033700002001200437000820014110412010312201450d0120012008370010200141186a200a3700002007ad42808080808008842001ad428080808080048410042001102f2007102f0b410121070c010b1036000b2000200636020420002007360200200541c0026a24000bd58e010e047f017e017f027e017f027e017f027e097f027e037f037e0c7f057e230041d0036b22012400200141f8006a200010ba03200141d0026a41186a4200370300200141d0026a41106a22024200370300200141d0026a41086a22034200370300200142003703d002418de6c300ad4280808080e000841001220429000021052003200441086a290000370300200120053703d0022004102f41f883c400ad4280808080f0018410012204290000210520014188016a41086a2206200441086a29000037030020012005370388012004102f20022001290388012205370300200141e0016a41086a2003290300370300200141e0016a41106a2005370300200141e0016a41186a2006290300370300200120012903d0023703e0010240024002400240024002400240200141e0016a10f702220341ff01714102460d00200141e0016aad22074280808080800484220810052003410171450d00200141f0026a41186a4200370300200141f0026a41106a22094200370300200141f0026a41086a22034200370300200142003703f00241eba1ca00ad4280808080f000841001220429000021052003200441086a290000370300200120053703f0022004102f41aca1ca00ad4280808080e0018410012204290000210520014190036a41086a2206200441086a29000037030020012005370390032004102f20092001290390032205370300200141d0026a41086a2003290300370300200141d0026a41106a2005370300200141d0026a41186a2006290300370300200120012903f0023703d002200141203602c4012001200141d0026a3602c001200141f0026a200141d0026aad220a4280808080800484220b1002107341022104024020012802f0022206450d0020012802f402210c024002402003280200450d0020062d0000220341014b0d0041002104024020030e020200020b410121040c010b200141003602980320014201370390032001410b36029c012001200141c0016a36029801200120014190036a3602a001200141f4016a4101360200200142013702e401200141b885c7003602e001200120014198016a3602f001200141a0016a41d8dbc100200141e0016a103c1a2001350298034220862001350290038410080240200128029403450d00200128029003102f0b410221040b200c450d002006102f0b0240024020044102460d0020044101710d010b42002105200141f0026a41186a22044200370300200141f0026a41106a22064200370300200141f0026a41086a22034200370300200142003703f00241eba1ca00ad4280808080f00084220d1001220c290000210e2003200c41086a2900003703002001200e3703f002200c102f41f2a1ca00ad4280808080a001841001220f290000210e20014190036a41086a220c200f41086a2900003703002001200e37039003200f102f2009200129039003370000200941086a2210200c290300370000200141d0026a41086a22112003290300370300200141d0026a41106a22122006290300370300200141d0026a41186a22132004290300370300200120012903f0023703d002200b1005200442003703002006420037030020034200370300200142003703f002200d1001220f290000210e2003200f41086a2900003703002001200e3703f002200f102f41baa1ca00ad4280808080b003841001220f290000210e200c200f41086a2900003703002001200e37039003200f102f20092001290390033700002010200c290300370000201120032903003703002012200629030037030020132004290300370300200120012903f0023703d002200141f0006a200141d0026a41201095012001280274211420012802702115200442003703002006420037030020034200370300200142003703f002200d1001220f290000210e2003200f41086a2900003703002001200e3703f002200f102f41d2a0ca00ad4280808080a001841001220f290000210e200c200f41086a2900003703002001200e37039003200f102f20092001290390033700002010200c290300370000201120032903003703002012200629030037030020132004290300370300200120012903f0023703d002200141e8006a200141d0026a4120109501200128026c211620012802682117200442003703002006420037030020034200370300200142003703f002200d1001220f290000210e2003200f41086a2900003703002001200e3703f002200f102f4180b1c000ad4280808080f001841001220f290000210e200c200f41086a2900003703002001200e37039003200f102f20092001290390033700002010200c290300370000201120032903003703002012200629030037030020132004290300370300200120012903f0023703d002200141d8006a200141d0026a10e3012001290360210e20012903582118200d1001220f2900002119200141c0016a41086a221a200f41086a290000370300200120193703c001200f102f41dca0ca00ad4280808080d002841001220f290000211920014188016a41086a221b200f41086a2900003703002001201937038801200f102f20012016410020171b221c3602e00120074280808080c0008422191003220f290000211d200f41086a290000211e200f41106a290000211f200141a0016a41186a2216200f41186a290000370300200141a0016a41106a2217201f370300200141a0016a41086a2220201e3703002001201d3703a001200f102f41c000102d220f450d02200f20012903c001370000200f41086a201a290300370000200f200129038801370010200f41186a201b290300370000200f20012903a001370020200f41286a2020290300370000200f41306a2017290300370000200f41386a201629030037000020012014410020151b3602e001200fad428080808080088420191004200f102f2001200e42002018a71b3703e801200142013703e0012001201c3602f001200442003703002006420037030020034200370300200142003703f002200d1001220f290000210e2003200f41086a2900003703002001200e3703f002200f102f41adcac800ad42808080809001841001220f290000210e200c200f41086a2900003703002001200e37039003200f102f20092001290390033700002010200c290300370000201120032903003703002012200629030037030020132004290300370300200120012903f0023703d00220014120360294032001200141d0026a36029003200141e0016a20014190036a10bb03200442003703002006420037030020034200370300200142003703f002200d1001220f290000210d2003200f41086a2900003703002001200d3703f002200f102f41f2b0c000ad4280808080e001841001220f290000210d200c200f41086a2900003703002001200d37039003200f102f20092001290390033700002010200c290300370000201120032903003703002012200629030037030020132004290300370300200120012903f0023703d002200141e0016a200141d0026a412010aa0220012802e0012203410120031b21210240024020012902e401420020031b221f422088a722220d004200210e0c010b2022410574212320014188016a41086a2106200141e0016a41246a212420014190036a41246a2125420021054200210e20212104034041eba1ca00ad4280808080f00084221810012203290000210d200141c0016a41086a2212200341086a2900003703002001200d3703c0012003102f4198b1c000ad4280808080f0008410012203290000210d2006200341086a2900003703002001200d370388012003102f4120102d2203450d0420032004290000370000200341186a200441186a220c290000370000200341106a200441106a220f290000370000200341086a200441086a22102900003700002003ad428080808080048410032211290000210d201141086a2900002119201141106a290000211d200141a0016a41186a2213201141186a290000370300200141a0016a41106a2214201d370300200141a0016a41086a221520193703002001200d3703a0012011102f2003102f41c000102d2203450d04200320012903c001370000200341086a20122903003700002003200129038801370010200341186a2006290300370000200320012903a001370020200341286a2015290300370000200341306a2014290300370000200341386a2013290300370000200141e0016a200341c00010bc03200141f0026a41086a2217200141e0016a41086a2226290300370300200141f0026a41106a221a200141e0016a41106a2227290300370300200141f0026a41186a221b200141e0016a41186a2228290300370300200141d0026a41086a2211202441086a280200360200200120012903e0013703f002200120242902003703d002024002402001280280022216450d00202520012903d00237020020014190036a41186a201b29030037030020014190036a41106a201a29030037030020014190036a41086a2017290300370300202541086a2011280200360200200120012903f00237039003200120163602b0030c010b20014190036a41186a420037030020014190036a41106a420037030020014190036a41086a42003703002001420037039003200141003602b803200142083703b0030b2003102f20014190036a41086a22292903002119200129039003210d200141d0026a201c10bd034120102d2203450d0420032004290000370000200341186a200c290000370000200341106a200f290000370000200341086a201029000037000020012003ad428080808080048410062211290000370388012011102f200141003a00f0012001200341206a3602ec01200120033602e801200120063602e401200120014188016a3602e001200141f0026a200141e0016a106c2003102f20012802f002212a0240024020012802d402221620012802d80222116b20012802f8022220490d0020012802d00221030c010b201120206a22032011490d072016410174222b2003202b20034b1b222b4100480d070240024020160d00202b102d21030c010b20012802d0022016202b103121030b2003450d052001202b3602d402200120033602d002202b21160b2001201120206a222b3602d802200320116a202a202010e8061a024020012802f402450d00202a102f0b2001202b3602e401200120033602e00120014190036a200141e0016a10be0302402016450d002003102f0b201b20014190036a41186a290300370300201a20014190036a41106a2903003703002017202929030037030020012001290390033703f00220012802bc03211620012802b403212020012802b0032111024020012802b803220341c100490d0020112003410041202003676b10bf0341c00021030b2028201b2903003703002027201a29030037030020262017290300370300200120012903f0023703e0012001201636028c02200120033602880220012020360284022001201136028002200141a0016a201c10c0034120102d2203450d0420032004290000370000200341186a200c290000370000200341106a200f290000370000200341086a201029000037000020012003ad428080808080048410062211290000370388012011102f200141003a00e0022001200341206a3602dc02200120033602d802200120063602d402200120014188016a3602d002200141c0016a200141d0026a106c2003102f20012802c001211a0240024020012802a401221620012802a80122116b20012802c8012217490d0020012802a00121030c010b201120176a22032011490d072016410174221b2003201b20034b1b221b4100480d070240024020160d00201b102d21030c010b20012802a0012016201b103121030b2003450d052001201b3602a401200120033602a001201b21160b2001201120176a221b3602a801200320116a201a201710e8061a024020012802c401450d00201a102f0b2001201b3602d402200120033602d002200141e0016a200141d0026a10be0302402016450d002003102f0b0240200128028402450d00200128028002102f0b20181001220329000021182012200341086a290000370300200120183703c0012003102f41a5c6c800ad4280808080a001841001220329000021182006200341086a29000037030020012018370388012003102f4120102d2203450d0420032004290000370000200341186a200c290000370000200341106a200f290000370000200341086a20102900003700002003ad4280808080800484100322112900002118201141086a290000211d201141106a290000211e2013201141186a2900003703002014201e3703002015201d370300200120183703a0012011102f2003102f41c000102d2203450d04200320012903c001370000200341086a20122903003700002003200129038801370010200341186a2006290300370000200320012903a001370020200341286a2015290300370000200341306a2014290300370000200341386a2013290300370000200141d0006a200341c00010c10320012802542113200128025021142003102f200141c0016a201c10c2034120102d2203450d0420032004290000370000200341186a200c290000370000200341106a200f290000370000200341086a201029000037000020012003ad42808080808004841006220c29000037038801200c102f200141003a00f0012001200341206a3602ec01200120033602e801200120063602e401200120014188016a3602e001200141d0026a200141e0016a106c2003102f20012802d00221120240024020012802c401220f20012802c801220c6b20012802d8022211490d0020012802c00121030c010b200c20116a2203200c490d07200f41017422102003201020034b1b22104100480d0702400240200f0d002010102d21030c010b20012802c001200f2010103121030b2003450d05200120103602c401200120033602c0012010210f0b2013410020141b21102001200c20116a22133602c8012003200c6a2012201110e8061a024020012802d402450d002012102f0b200d20057c2105200141003a00e5010240024002400240201041c000490d00201041808001490d012010418080808004490d02200141053a00e501200141033a00e001200120103600e1014280808080d00021180c030b200141013a00e501200120104102743a00e00142808080801021180c020b200141023a00e501200120104102744101723b01e00142808080802021180c010b200141043a00e501200120104102744102723602e0014280808080c00021180b2005200d54210c2013ad4220862003ad8420182007841004024020012d00e501450d00200141003a00e5010b2019200e7c210d200cad210e0240200f450d002003102f0b200441206a2104200d200e7c210e202341606a22230d000b0b41eba1ca00ad4280808080f00084220d100122032900002118200141c0016a41086a2204200341086a290000370300200120183703c0012003102f41f5cac800ad4280808080e0018410012203290000211820014188016a41086a2206200341086a29000037030020012018370388012003102f2001201c3602e00120074280808080c00084100322032900002118200341086a2900002119200341106a290000211d200141a0016a41186a220c200341186a290000370300200141a0016a41106a220f201d370300200141a0016a41086a22102019370300200120183703a0012003102f41c000102d2203450d02200320012903c001370000200341086a20042903003700002003200129038801370010200341186a2006290300370000200320012903a001370020200341286a2010290300370000200341306a200f290300370000200341386a200c2903003700002001200e3703e801200120053703e0012003ad42808080808008842007428080808080028410042003102f200141f0026a41186a22064200370300200141f0026a41106a220c4200370300200141f0026a41086a22034200370300200142003703f002200d1001220429000021052003200441086a290000370300200120053703f0022004102f41d5a1ca00ad4280808080e0028410012204290000210520014190036a41086a220f200441086a29000037030020012005370390032004102f2009200129039003370000200941086a200f290300370000200141d0026a41086a2003290300370300200141d0026a41106a200c290300370300200141d0026a41186a2006290300370300200120012903f0023703d002200141203602a4012001200141d0026a3602a001200141f0026a200b100210730240024020012802f00222030d004100210f0c010b20012802f40221062001200141f8026a28020022043602c401200120033602c0010240024020044104490d0020012004417c6a3602c4012001200341046a3602c00120032800002111200141c8006a200141c0016a10e60120012802480d0020012802c401220c200128024c22104102742204490d002004417f4c0d060240024020040d004101210f0c010b20041033220f450d06200f20012802c0012212200410e8061a2001200c20046b3602c4012001201220046a3602c0010b200f450d000240024002402004450d00200f4103710d02201041ffffffff037122040d01200f102f0b410021044104210f0b41000d01200f450d012004ad220542208620058421050c020b200f102f0b4100210f200141003602980320014201370390032001410b36029c012001200141a0016a36029801200120014190036a36028801200141f4016a4101360200200142013702e401200141b885c7003602e001200120014198016a3602f00120014188016a41d8dbc100200141e0016a103c1a2001350298034220862001350290038410080240200128029403450d00200128029003102f0b0b2006450d002003102f0b4190bdc600210420014190bdc6003602f002200142003702f402200f4104200f1b211b4100210c41002110024020054200200f1b222c422088a72203202241ffffff3f712206200620034b1b2206450d0020212103201b2104034020014190036a41186a200341186a290000220537030020014190036a41106a200341106a290000220d37030020014190036a41086a200341086a290000220e370300200120032900002218370390032004280200210c200141e0016a41186a2005370300200141e0016a41106a200d370300200141e0016a41086a200e370300200120183703e001200141f0026a200141e0016a200c10ed01200341206a2103200441046a21042006417f6a22060d000b20012802f802210c20012802f402211020012802f00221040b41eba1ca00ad4280808080f00084100122032900002105200141c0016a41086a2206200341086a290000370300200120053703c0012003102f41e5cac800ad428080808080028410012203290000210520014188016a41086a2212200341086a29000037030020012005370388012003102f2001201c3602e00120074280808080c00084100322032900002105200341086a290000210d200341106a290000210e200141a0016a41186a2213200341186a290000370300200141a0016a41106a2214200e370300200141a0016a41086a2215200d370300200120053703a0012003102f41c000102d2203450d02200320012903c001370000200341086a20062903003700002003200129038801370010200341186a2012290300370000200320012903a001370020200341286a2015290300370000200341306a2014290300370000200341386a2013290300370000200141003602e801200142013703e0014104102d2206450d02200620114100200f1b36000020014284808080c0003702e401200120063602e00120042010200c200141e0016a10e50120012802e40121062003ad428080808080088420013502e80142208620012802e001220fad84100402402006450d00200f102f0b2003102f20042010200c10a302200141e0016a41186a4200370300200141e0016a41106a22064200370300200141e0016a41086a22034200370300200142003703e00141eba1ca00ad4280808080f000841001220429000021052003200441086a290000370300200120053703e0012004102f41a7cac800ad4280808080e0008410012204290000210520014188016a41086a220c200441086a29000037030020012005370388012004102f20062001290388012205370300200141c0016a41086a22042003290300370300200141c0016a41106a22032005370300200141c0016a41186a2206200c290300370300200120012903e0013703c0014120102d2210450d02201020012903c001370000201041186a2006290300370000201041106a2003290300370000201041086a2004290300370000200141e0016a2010ad42808080808004841018107302400240024020012802e001220f0d0041002103410021140c010b20014194026a21134100211441202112024003400240024020012902e4012205422088a722114120490d00200141c0016a200f460d01200141c0016a200f412010ea06450d010b2005a7450d02200f102f0c020b200120113602c4032001200f3602c00320014188016a200542808080807083200fad84220d10021073024002402001280288012206450d00200128028c0121152001200128029001220c3602c402200120063602c00241002103200141003a00800202400240024002400340200c2003460d01200141e0016a20036a200620036a22042d00003a00002001200441016a3602c0022001200341016a22043a0080022004210320044120470d000b200141a0016a41086a2216200141e0016a41086a290300370300200141a0016a41106a2217200141e0016a41106a290300370300200141a0016a41186a221a200141e0016a41186a290300370300200120012903e0013703a0012001200c20046b3602c402200141306a200141c0026a109c032001290330a70d02200141306a41106a290300212d2001290338212e200141186a200141c0026a109c032001290318a7450d010c020b200141003602c402200341ff0171450d01200141003a0080020c010b200141186a41106a290300212f20012903202130200141e0016a200141c0026a10c30320012802e0012203450d00200141f0026a41086a2016290300370300200141f0026a41106a2017290300370300200141f0026a41186a201a290300370300200120012903a001220e370390032001200e3703f00220012902e401210e20302118202f2119202e211d202d211e0c010b200141003602980320014201370390032001410b36029c012001200141c0036a36029801200120014190036a3602f002200141013602f401200142013702e401200141b885c7003602e001200120014198016a3602f001200141f0026a41d8dbc100200141e0016a103c1a2001350298034220862001350290038410080240200128029403450d00200128029003102f0b410021030b02402015450d002006102f0b2003450d00201320012903f002370200200141e0016a41186a2019370300201341186a200141f0026a41186a290300370200201341106a200141f0026a41106a290300370200201341086a200141f0026a41086a290300370200200120183703f0012001201d3703e0012001410036028c022001200e3702840220012003360280022001201e3703e80120012011360294032001200f36029003200141e0016a20014190036a10c403200128028402450d01200128028002102f0c010b200d1005201441016a21140b02402012450d002010102f0b200141e0016a200d101810732005a72112200f211020012802e001220f0d000b0b201441004721032012450d010b2010102f0b02402003450d0041d0fcc000ad4280808080e0068410084186fdc000ad4280808080b0048410082014ad10190b200141f0026a41186a22044200370300200141f0026a41106a22064200370300200141f0026a41086a22034200370300200142003703f00241eba1ca00ad4280808080f0008422051001220c290000210d2003200c41086a2900003703002001200d3703f002200c102f4198b1c000ad4280808080f000841001220f290000210d20014190036a41086a220c200f41086a2900003703002001200d37039003200f102f2009200129039003370000200941086a2212200c290300370000200141d0026a41086a220f2003290300370300200141d0026a41106a22102006290300370300200141d0026a41186a22112004290300370300200120012903f0023703d002200b1013200442003703002006420037030020034200370300200142003703f002200510012213290000210d2003201341086a2900003703002001200d3703f0022013102f418fb1c000ad428080808090018410012213290000210d200c201341086a2900003703002001200d370390032013102f20092001290390033700002012200c290300370000200f20032903003703002010200629030037030020112004290300370300200120012903f0023703d002200b1005200442003703002006420037030020034200370300200142003703f002200510012213290000210d2003201341086a2900003703002001200d3703f0022013102f41f2b0c000ad4280808080e0018410012213290000210d200c201341086a2900003703002001200d370390032013102f20092001290390033700002012200c290300370000200f20032903003703002010200629030037030020112004290300370300200120012903f0023703d002200b1005200442003703002006420037030020034200370300200142003703f002200510012213290000210d2003201341086a2900003703002001200d3703f0022013102f4180b1c000ad4280808080f0018410012213290000210d200c201341086a2900003703002001200d370390032013102f20092001290390033700002012200c290300370000200f20032903003703002010200629030037030020112004290300370300200120012903f0023703d002200b1005200442003703002006420037030020034200370300200142003703f002200510012213290000210d2003201341086a2900003703002001200d3703f0022013102f41baa1ca00ad4280808080b0038410012213290000210d200c201341086a2900003703002001200d370390032013102f20092001290390033700002012200c290300370000200f20032903003703002010200629030037030020112004290300370300200120012903f0023703d002200b1005200442003703002006420037030020034200370300200142003703f002200510012213290000210d2003201341086a2900003703002001200d3703f0022013102f41d5a1ca00ad4280808080e0028410012213290000210d200c201341086a2900003703002001200d370390032013102f20092001290390033700002012200c290300370000200f20032903003703002010200629030037030020112004290300370300200120012903f0023703d002200b1005200141a0016a41186a4200370300200141a0016a41106a22064200370300200141a0016a41086a22034200370300200142003703a00120051001220429000021052003200441086a290000370300200120053703a0012004102f41aca1ca00ad4280808080e0018410012204290000210520014188016a41086a220c200441086a29000037030020012005370388012004102f20062001290388012205370300200f2003290300370300201020053703002011200c290300370300200120012903a0013703d0024101102d2203450d02200341013a0000200a42808080808004842003ad4280808080108410042003102f0240202ca7450d00201b102f0b201fa7450d002021102f0b200141c0016a41186a4200370300200141c0016a41106a22064200370300200141c0016a41086a22034200370300200142003703c00141e7a2ca00ad42808080808001841001220429000021052003200441086a290000370300200120053703c0012004102f41aca1ca00ad4280808080e0018410012204290000210520014190036a41086a220c200441086a29000037030020012005370390032004102f20062001290390032205370300200141a0016a41086a2003290300370300200141a0016a41106a2005370300200141a0016a41186a200c290300370300200120012903c0013703a001200141203602d4022001200141a0016a3602d002200141f0026a200141a0016aad42808080808004841002107341022103024020012802f0022204450d0020012802f402210602400240200141f0026a41086a280200450d0020042d0000220c41014b0d00410021030240200c0e020200020b410121030c010b200141003602980320014201370390032001410b36029c012001200141d0026a36029801200120014190036a3602c001200141f4016a4101360200200142013702e401200141b885c7003602e001200120014198016a3602f001200141c0016a41d8dbc100200141e0016a103c1a2001350298034220862001350290038410080240200128029403450d00200128029003102f0b410221030b2006450d002004102f0b0240024020034102460d0020034101710d010b41b1dac000ad4280808080d003841008200141a0016a41186a22064200370300200141a0016a41106a22294200370300200141a0016a41086a22044200370300200142003703a00141e7a2ca00ad42808080808001841001220329000021052004200341086a290000370300200120053703a0012003102f41cedac000ad4280808080b0018410012203290000210520014190036a41086a220c200341086a29000037030020012005370390032003102f2006200c29030022053703002029200129039003220d370300200141c0016a41186a220c2005370300200141c0016a41106a220f200d370300200141c0016a41086a22102004290300370300200120012903a0013703c0014120102d2203450d02200320012903a001370000200341186a2006290300370000200341106a2029290300370000200341086a2004290300370000200141f0026a41086a22042010290300370300200141f0026a41106a2206200f290300370300200141f0026a41186a220f200c290300370300200120012903c0013703f002200141bc026a41026a220c200141e0016a41026a2d00003a0000200120012f00e0013b01bc02200142a0808080800437029403200120033602900320014190036a41146a200429030037020020014190036a411c6a2006290300370200200141b4036a200f290300370200200141013a00bc03200120012903f00237029c03200141bf036a200c2d00003a0000200120012f01bc023b00bd03200141e0016a20014190036a10c503024020012802e001450d0020074280808080c00084211e200141e0016a41186a211c20014198026a212720014188026a2128200141e3016a211a0340200141d0026a41086a200141e0016a41086a290300220d370300200120012903e00122053703d002201c290300210720012903f001210b200141c0026a41086a200da72206360200200120053703c002200641206a2204417f4c0d05024002400240024002400240024002402004450d00200410332203450d0c2004410f4d0d0141e7a2ca00ad42808080808001841001220c290000210d200141c0016a41086a2213200c41086a2900003703002001200d3703c001200c102f200341086a2013290300370000200320012903c0013700002004411f4d0d0241f9b5c600ad4280808080d0008422191001220c290000210d20014188016a41086a2214200c41086a2900003703002001200d37038801200c102f200341186a20142903003700002003200129038801370010200341206a2005a7200610e8061a200120033602c003200120043602c403200141a0016a2004ad4220862003ad84100210730240024020012802a00122160d004100211b0c010b20012802a4012126200120012802a80136028c012001201636028801200141106a20014188016a10e6010240024020012802100d0020012802142215200128028c014105762204200420154b1b22104105742204417f4c0d100240024020100d004108211b0c010b2004102d221b450d100b024002402015450d0041002112410021114100210f0340200141e0016a20014188016a10f30220012d00e0014101460d02200128028c0122064110490d0220012900e10121052001200128028801220441106a360288012001200641706a220c36028c01200c4104490d02200441086a290000210d2004290000210e20012006416c6a220c36028c012001200441146a36028801200c450d02200f41016a210c20042800102117200141c8036a41026a200141c0016a41026a2d0000222a3a0000200141cc036a41026a2224202a3a000020012006416b6a36028c012001200441156a36028801200120012f00c00122063b01c803200120063b01cc0320042d001421060240200f2010470d002012200c2012200c4b1b220441ffffff3f712004470d15200441057422044100480d1502400240200f0d002004102d211b0c010b201b201120041031211b0b201b450d13200441057621100b201b20116a2204411c6a20063a00002004200d3703082004200e370300200441146a2005370200200441106a20173602002004411d6a20012f01cc033b00002004411f6a20242d00003a0000201241026a2112201141206a2111200c210f2015200c470d000b0b201b450d010c020b2010450d00201b102f0b200141003602c801200142013703c0012001410b36029c012001200141c0036a360298012001200141c0016a3602c803200141013602f401200142013702e401200141b885c7003602e001200120014198016a3602f001200141c8036a41d8dbc100200141e0016a103c1a20013502c80142208620013502c001841008024020012802c401450d0020012802c001102f0b4100211b20232110202021150b02402026450d002016102f0b20102123201521200b2003102f0240201b0d004200211d4200210e420021194200210d0c080b20204105742103410021110240024020200d004108212a410021240c010b2003410575220441ffffff3f712004470d0f20034100480d0f2003102d222a450d0d200341057621240b0240201b20036a2217201b460d0041002111202a2103201b21040340200441086a2903002105200441146a290200210d200441106a280200210f2004290300210e4100211002402004411c6a2d000022064101460d004102410120064101711b21100b0240200f417f460d0020012802c802221541206a220c417f4c0d10200c450d0620012802c0022116200c10332206450d0f200c410f4d0d07419298ca00ad42808080809001841001221229000021182013201241086a290000370300200120183703c0012012102f200641086a2013290300370000200620012903c001370000200c411f4d0d0820191001221229000021182014201241086a29000037030020012018370388012012102f200641186a20142903003700002006200129038801370010200641206a2016201510e8061a2001200f3602e001200cad4220862006ad84201e10042006102f0b200120012800e0013602c0012001201a2800003600c301200341186a20103a0000200320053703082003200e370300200341106a200d370300200341196a20012802c0013600002003411c6a20012800c301360000200341206a2103201141016a2111200441206a22042017470d000b0b02402023450d00201b102f0b024020110d004200211d4200210e420021194200210d0c070b20114105742104420021194200210d4200211d4200210e202a210303400240200341186a2d0000220641024b0d00024002400240024020060e03020100020b200e200341086a2903002205201d2003290300221856200e200556200e2005511b22061b210e201d201820061b211d0c020b200e200341086a2903002205201d2003290300221856200e200556200e2005511b22061b210e201d201820061b211d0c020b200341086a2903002105200329030021180b200d20052019201856200d200556200d2005511b22061b210d2019201820061b21190b200341206a2103200441606a2204450d070c000b0b41104100104a000b41102004104a000b41202004104a000b41104100104a000b4110200c104a000b4120200c104a000b20012802c802210320012802c0022104200120113602e801200120243602e4012001202a3602e00120042003200141e0016a10c6030b20012802c802210320012802c00221042027200d3703002028200e370300201c420037030020012019370390022001201d37038002200142003703f001200120073703e8012001200b3703e00120042003200141e0016a10c703024020012802c402450d0020012802c002102f0b200141e0016a20014190036a10c50320012802e0010d000b0b0240200128029403450d00200128029003102f0b200141a0016a41186a22064200370300200141a0016a41106a220c4200370300200141a0016a41086a22044200370300200142003703a00141e7a2ca00ad42808080808001841001220329000021052004200341086a290000370300200120053703a0012003102f41d9dac000ad4280808080f0018410012203290000210520014190036a41086a220f200341086a29000037030020012005370390032003102f202941086a200f2903003700002029200129039003370000200141c0016a41186a220f2006290300370300200141c0016a41106a2210200c290300370300200141c0016a41086a22112004290300370300200120012903a0013703c0014120102d2203450d02200320012903a001370000200341186a2006290300370000200341106a200c290300370000200341086a2004290300370000200141d0026a41086a22042011290300370300200141d0026a41106a22062010290300370300200141d0026a41186a220c200f290300370300200120012903c0013703d002200141c0016a41026a220f200141e0016a41026a2d00003a0000200120012f00e0013b01c001200142a08080808004370294032001200336029003200141a4036a2004290300370200200141ac036a2006290300370200200141b4036a200c290300370200200141013a00bc03200120012903d00237029c03200141bf036a200f2d00003a0000200120012f01c0013b00bd03200141e0016a20014190036a10c503024020012802e0012204450d0020014180026a210320014188026a2106200141e0016a41186a210c0340200c290300210520012903f001210d20012802e401210f200141e0016a200420012802e801221010c8030240024020012903e0014201510d004200210e200141f0026a41186a4200370300200141f0026a41106a4200370300200141f0026a41086a4200370300200142003703f002420021180c010b200141f0026a41086a200641086a290300370300200141f0026a41106a200641106a290300370300200141f0026a41186a200641186a290300370300200120062903003703f002200141e0016a41106a290300211820012903e801210e0b200c2005370300200320012903f002370300200341086a200141f0026a41086a290300370300200341106a200141f0026a41106a290300370300200341186a200141f0026a41186a2903003703002001200d3703f001200120183703e8012001200e3703e00120042010200141e0016a10c7030240200f450d002004102f0b200141e0016a20014190036a10c50320012802e00122040d000b0b0240200128029403450d00200128029003102f0b200141a0016a41186a22064200370300200141a0016a41106a220c4200370300200141a0016a41086a22044200370300200142003703a00141e7a2ca00ad42808080808001841001220329000021052004200341086a290000370300200120053703a0012003102f41adc5c300ad4280808080f0008410012203290000210520014190036a41086a220f200341086a29000037030020012005370390032003102f202941086a200f2903003700002029200129039003370000200141c0016a41186a220f2006290300370300200141c0016a41106a2210200c290300370300200141c0016a41086a22112004290300370300200120012903a0013703c0014120102d2203450d02200320012903a001370000200341186a2006290300370000200341106a200c290300370000200341086a2004290300370000200141d0026a41086a22042011290300370300200141d0026a41106a22062010290300370300200141d0026a41186a220c200f290300370300200120012903c0013703d002200141a0016a41026a220f200141e0016a41026a2d00003a0000200120012f00e0013b01a001200142a08080808004370294032001200336029003200141a4036a200429030037020020014190036a411c6a200629030037020020014190036a41246a200c290300370200200141013a00bc03200120012903d00237029c03200141bf036a200f2d00003a0000200120012f01a0013b00bd03200141e0016a20014190036a10c903024020012802e001220c450d00200141e0016a41086a211320014188026a2116200141e0016a41186a2117200141a0026a212a20014190026a2123200141e3016a212020014198026a211c0240024003402016290300211920172903002105200129038002211d20012903f001210d200128029002211a20012802e401211b200141e0016a200c20012802e801220f10c8030240024020012903e0014201510d004200211e200141f0026a41186a4200370300200141f0026a41106a4200370300200141f0026a41086a4200370300200142003703f00242002107420021184200210e0c010b200141f0026a41186a201341186a290300370300200141f0026a41106a201341106a290300370300200141f0026a41086a201341086a290300370300200120132903003703f002202a29030021072023290300210e200129039802211e20012903880221180b200f41206a2203417f4c0d0702402003450d00200310332204450d072003410f4d0d0241e7a2ca00ad428080808080018410012210290000210b200141c0016a41086a2206201041086a2900003703002001200b3703c0012010102f200441086a2006290300370000200420012903c0013700002003411f4d0d0341f9b5c600ad4280808080d0008410012210290000210b20014188016a41086a2211201041086a2900003703002001200b370388012010102f200441186a20112903003700002004200129038801370010200441206a200c200f10e8061a200141e0016a2004200310ca032004102f02400240024020012802e00122100d0041002104410821100c010b20012802e4012204211520012802e80122122004470d010b200441016a22122004490d0a200441017422142012201420124b1b221241ffffff3f712012470d0a201241057422124100480d0a0240024020040d002012102d21100c010b201020044105742012103121100b2010450d0820124105762115200421120b201020124105746a220441013a0018200420053703082004200d370300200442f6cacda397cddbb320370310200420012800e0013600192004411c6a2020280000360000200310332204450d0741adc5c300ad4280808080f00084220b10012214290000210a2006201441086a2900003703002001200a3703c0012014102f200441086a2006290300370000200420012903c001370000200b10012206290000210b2011200641086a2900003703002001200b370388012006102f200441186a20112903003700002004200129038801370010200441206a200c200f10e8061a4124102d2206450d072006201d3700102006200d3700002006201a360020200641186a2019370000200620053700082003ad4220862004ad842006ad4280808080c0048410042006102f2004102f2001201241016a3602e801200120153602e401200120103602e001200c200f200141e0016a10c603201c20073703002016200e20052018200d56200e200556200e2005511b22031b3703002017200141f0026a41186a290300370300200141e0016a41106a200141f0026a41106a2903003703002013200141f0026a41086a2903003703002001201e3703900220012018200d20031b37038002200120012903f0023703e001200c200f200141e0016a10c7030240201b450d00200c102f0b200141e0016a20014190036a10c90320012802e001220c0d010c040b0b41104100104a000b41102003104a000b41202003104a000b0240200128029403450d00200128029003102f0b200141a0016a41186a22064200370300200141a0016a41106a220c4200370300200141a0016a41086a22044200370300200142003703a00141e7a2ca00ad42808080808001841001220329000021052004200341086a290000370300200120053703a0012003102f41f0e8c600ad4280808080f0008410012203290000210520014190036a41086a220f200341086a29000037030020012005370390032003102f202941086a200f2903003700002029200129039003370000200141c0016a41186a220f2006290300370300200141c0016a41106a2210200c290300370300200141c0016a41086a22112004290300370300200120012903a0013703c0014120102d2203450d02200320012903a001370000200341186a2006290300370000200341106a200c290300370000200341086a2004290300370000200141f0026a41086a22042011290300370300200141f0026a41106a22062010290300370300200141f0026a41186a220c200f290300370300200120012903c0013703f002200141d0026a41026a220f200141e0016a41026a2d00003a0000200120012f00e0013b01d002200142a08080808004370294032001200336029003200141a4036a2004290300370200200141ac036a2006290300370200200141b4036a200c290300370200200141013a00bc03200120012903f00237029c03200141bf036a200f2d00003a0000200120012f01d0023b00bd03200141e0016a20014190036a10cb03024020012802e001220c450d00200141a8026a211a20014198026a211b20014188026a2120200141e0016a41186a211c41e7eac300ad4280808080d00184210a0340201a2903002105201b290300210d2020290300210e201c290300211820012903a0022119200129039002211d200129038002211e20012903f001210720012802e4012112200141086a418de6c300410641e8dac000410c200c20012802e801220310cc03200128020c211320012802082114419298ca00410941d49ac8004105200c200310722110200a10062204290000210b2004102f4108102d2204450d042004200b37000020044108411510312206450d042006410d6a41002900ecea43370000200641002900e7ea433700080240024020030d00411521040c010b200341156a22042003490d072004412a2004412a4b1b220f4100480d0720064115200f10312206450d050b200641156a200c200310e8061a419c9eca0041074186ebc3004108200620041072211541eba1ca00410741a1cac8004106200c200310722116200341206a220f417f4c0d05200f450d07200f10332204450d04200f410f4d0d08418de6c300ad4280808080e0008410012211290000210b200141c0016a41086a2217201141086a2900003703002001200b3703c0012011102f200441086a2017290300370000200420012903c001370000200f411f4d0d0941f0e8c600ad4280808080f0008410012211290000210b20014188016a41086a2217201141086a2900003703002001200b370388012011102f200441186a20172903003700002004200129038801370010200441206a200c200310e8061a4105102d2203450d0420034102410120101b201020151b20166a3a000420032013410020141b36000020034105411510312203450d04200320073700052003410d6a201837000020034115412a10312203450d042003201e3700152003411d6a200e3700002003412a41d40010312203450d04200320193700352003201d3700252003413d6a20053700002003412d6a200d370000200fad4220862004ad842003ad4280808080d0088410042003102f2004102f2006102f02402012450d00200c102f0b200141e0016a20014190036a10cb0320012802e001220c0d000b0b0240200128029403450d00200128029003102f0b200141e7a2ca00410841f2a1ca00410a41c8e1ca00410010cc03200141d0026a41186a22064200370300200141d0026a41106a220c4200370300200141d0026a41086a22034200370300200142003703d00241e7a2ca00ad42808080808001841001220429000021052003200441086a290000370300200120053703d0022004102f41aca1ca00ad4280808080e0018410012204290000210520014188016a41086a220f200441086a29000037030020012005370388012004102f2002200129038801370000200241086a200f290300370000200141e0016a41086a2003290300370300200141e0016a41106a200c290300370300200141e0016a41186a2006290300370300200120012903d0023703e0014101102d2203450d02200341013a000020082003ad4280808080108410042003102f0b10cd030b2000280200200041106a200041d0006a200141f8006a410110ce03200028020010cf0310cd0310cd032001280278210c02402001280280012203450d00200341246c2104200c210303400240024020032d0000220641044b0d0002400240024020060e050400010204040b2003410c6a280200450d03200341086a280200102f0c030b2003410c6a280200450d02200341086a280200102f0c020b2003410c6a280200450d01200341086a280200102f0c010b200341086a280200450d00200341046a280200102f0b200341246a21032004415c6a22040d000b0b0240200128027c450d00200c102f0b200141d0036a24000f0b1036000b103d000b1038000b41104100104a000b4110200f104a000b4120200f104a000bf103030d7f017e017f230041306b2202240041042103200241086a200141046a10d60302400240024002400240200228020c41246c22040d0041002105410021060c010b200228020821014100210541002106410421030340024020012d00004101470d00200141106a2802002207417f4c0d03200141036a2d00002108200141016a2f00002109200141086a280200210a200141046a2d0000210b0240024020070d004101210c0c010b2007102d220c450d050b200c200a200710e806210c200241206a41086a220d200241106a41086a29020037030020022002290210370320024020052006470d00200641016a220a2006490d062006410174220e200a200e200a4b1bad42247e220f422088a70d06200fa7220a4100480d060240024020060d00200a102d21030c010b2003200641246c200a103121030b2003450d05200a41246e21060b2003200541246c6a220a2007360210200a200736020c200a200c360208200a201041807e71200b722210360204200a200920084110747222073b0001200a41013a0000200a41036a20074110763a0000200a2002290320370214200a411c6a200d290300370200200541016a21050b200141246a21012004415c6a22040d000b0b200020053602082000200636020420002003360200200241306a24000f0b103d000b1036000b1038000b9a0102027f017e2000280210210202404104102d2203450d002003200236000020002903002104200341044108103121030240024020044201510d002003450d02200341003a00044280808080d00021040c010b2003450d01200341013a00042000290308210420034108411010312203450d01200320043700054280808080d00121040b200129020020042003ad8410042003102f0f0b1036000b870301017f230041f0006b220324002003200236020420032001360200200341086a2002ad4220862001ad84100210730240024020032802082201450d00200328020c21022003200341086a41086a28020036024c20032001360248200341186a200341c8006a108a05024002402003280238450d0020002003290318370300200041286a200341186a41286a290300370300200041206a200341186a41206a290300370300200041186a200341186a41186a290300370300200041106a200341186a41106a290300370300200041086a200341186a41086a2903003703000c010b20034100360258200342013703502003410b360264200320033602602003200341d0006a36026c2003412c6a41013602002003420137021c200341b885c7003602182003200341e0006a360228200341ec006a41d8dbc100200341186a103c1a2003350258422086200335025084100802402003280254450d002003280250102f0b200041003602200b2002450d012001102f0c010b200041003602200b200341f0006a24000bd10403027f017e047f230041d0006b2202240041eba1ca00ad4280808080f00084100122032900002104200241086a200341086a290000370300200220043703002003102f41b6cac800ad4280808080b00184100122032900002104200241106a41086a200341086a290000370300200220043703102003102f2002200136022c20022002412c6aad4280808080c00084100622032900003703302003102f200241c4006a200241306a360200200241003a00482002200241306a41086a36023c20022002412c6a3602402002200241306a360238200241206a200241386a106c0240024002400240024002402002280228220541206a2201417f4c0d0020022802202106024002402001450d002001102d2203450d062001410f4d0d01200121070c050b411021074110102d21030c030b200141017422084110200841104b1b220741004e0d010c050b103d000b200320012007103121030b2003450d010b20032002290300370000200341086a200241086a2903003700000240024020074170714110460d00200721080c010b200741017422084120200841204b1b22084100480d0220032007200810312203450d010b20032002290310370010200341186a200241106a41086a29030037000002400240200841606a2005490d00200821070c010b2005415f4b0d02200841017422072001200720014b1b22074100480d0220032008200710312203450d010b200341206a2006200510e8061a20002001360208200020073602042000200336020002402002280224450d002006102f0b200241d0006a24000f0b1036000b1038000b8e0301067f230041106b2202240020024100360208200242013703002002200036020c2002410c6a200210c2022002200041106a36020c2002410c6a200210c20220002802202103200041286a2802002200200210690240024002402000450d00200041306c210403400240024020022802042205200228020822006b4120490d00200041206a2106200228020021050c010b200041206a22062000490d04200541017422072006200720064b1b22074100480d040240024020050d002007102d21050c010b200228020020052007103121050b2005450d0320022007360204200220053602000b200520006a220041086a200341186a290000370000200041106a200341206a290000370000200041186a200341286a290000370000200220063602082000200341106a2900003700002002200336020c2002410c6a200210c202200341306a2103200441506a22040d000b0b200228020421032001290200200235020842208620022802002200ad84100402402003450d002000102f0b200241106a24000f0b1036000b1038000be22c080a7f017e017f047e147f017e017f017e230041d0026b220424000240024020014115490d0041012105410121060240024002400340200121072000210820052006714101732109024002400240024002400240034002400240024002402003450d00024020054101710d002000200110dd032003417f6a21030b2001410276220a41036c210b200a410174210c4100210d024020014132490d00410241012000200a41306c6a220d290300220e200d41506a220f290300221056200d41086a2903002211200f41086a29030022125620112012511b220f1b200f200d41306a29030022132010200e200f1b221056200d41386a290300220e20122011200f1b221156200e2011511b22141b2013201020141b2000200a200a417f6a2215200f1b221641306c6a220d29030056200e201120141b2211200d41086a29030022125620112012511b22176a2000200c41306c6a220d290300220e200d41506a2218290300221056200d41086a2903002211201841086a29030022125620112012511b22186a2000200c410172221941306c6a220d29030022132010200e20181b221056200d41086a290300220e2012201120181b221156200e2011511b221a6a20132010201a1b2000200c200c417f6a221b20181b221c41306c6a220d29030056200e2011201a1b2211200d41086a29030022125620112012511b221d6a2000200b41306c6a220d290300220e200d41506a221e290300221056200d41086a2903002211201e41086a29030022125620112012511b221e6a200d41306a29030022132010200e201e1b221056200d41386a290300220e20122011201e1b221156200e2011511b221f6a20132010201f1b2000200b200b417f6a2220201e1b222141306c6a220d29030056200e2011201f1b2211200d41086a29030022125620112012511b22066a210d2021200b41016a2020200b201e1b201f1b20061b210b201c2019201b200c20181b201a1b201d1b210c2016200a41016a2015200a200f1b20141b20171b210a0b200d2000200c41306c6a220f290300220e2000200a41306c6a2218290300221056200f41086a2903002211201841086a29030022125620112012511b220f6a2000200b41306c6a220d29030022132010200e200f1b221056200d41086a290300220e20122011200f1b221156200e2011511b220d6a211820132010200d1b2000200c200a200f1b222141306c6a221e29030058200e2011200d1b2211201e41086a29030022125820112012511b450d01200b200a200c200f1b200d1b21210c020b2000200110de030c0f0b201841016a2218410c490d0002402001410176220b450d002000200141306c6a41506a210a2000210c0340200441a0026a41286a220f200c41286a220d290300370300200441a0026a41206a2218200c41206a221e290300370300200441a0026a41186a2214200c41186a221a290300370300200441a0026a41106a221f200c41106a2215290300370300200441a0026a41086a2216200c41086a22172903003703002004200c2903003703a002200a41086a22192903002111200a41106a221b2903002112200a41186a221c290300210e200a41206a221d2903002110200a41286a22202903002113200c200a290300370300200d2013370300201e2010370300201a200e37030020152012370300201720113703002020200f290300370300201d2018290300370300201c2014290300370300201b201f29030037030020192016290300370300200a20042903a002370300200c41306a210c200a41506a210a200b417f6a220b0d000b0b20012021417f736a21214101210a0c010b201845210a0b0240200a452009724101710d002000200110df030d0d0b2002450d02202120014f0d01024020022903002000202141306c6a220a29030056200241086a2903002211200a41086a220c29030022125620112012511b450d0020002108200121070c040b200441a0026a41286a221a200041286a2218290300370300200441a0026a41206a221f200041206a221e290300370300200441a0026a41186a2215200041186a2214290300370300200441a0026a41106a2216200041106a220b290300370300200441a0026a41086a2217200041086a220f290300370300200420002903003703a002200c2903002111200a41106a220d2903002112200a41186a2219290300210e200a41206a221b2903002110200a41286a221c29030021132000200a29030037030020182013370300201e20103703002014200e370300200b2012370300200f2011370300201c201a290300370300201b201f29030037030020192015290300370300200d2016290300370300200c2017290300370300200a20042903a002370300200f29030021112000290300210e200441186a221c2018290300370300200441106a221d201e290300370300200441086a222020142903003703002004200b290300370300200041506a2119200041306a211b4100210c2001210b03400240200c200b417f6a220f4f0d00201b200c41306c6a210a0340200e200a290300582011200a41086a29030022125820112012511b450d01200a41306a210a200f200c41016a220c470d000b200f210c0b2019200b41306c6a210a02400340200c200b417f6a220b4f0d01200a2903002112200a41086a210f200a41506a220d210a200e2012562011200f29030022125620112012511b0d000b201a201b200c41306c6a220a41286a220f290300370300201f200a41206a22212903003703002015200a41186a22062903003703002016200a41106a22222903003703002017200a41086a22232903003703002004200a2903003703a002200d41386a22242903002112200d41c0006a22252903002110200d41c8006a22262903002113200d41d0006a22272903002128200d41d8006a2229290300212a200a200d41306a220d290300370300200f202a370300202120283703002006201337030020222010370300202320123703002029201a2903003703002027201f290300370300202620152903003703002025201629030037030020242017290300370300200d20042903a002370300200c41016a210c0c010b0b2000200e370300200020113703082000200429030037031020142020290300370300201e201d2903003703002018201c29030037030002402001200c41016a220a490d002000200a41306c6a21002001200a6b220141154f0d010c0c0b0b200a2001104b000b41d4bbca0020212001103b000b2007450d010b202120074f0d01200441a0026a41286a2217200841286a2222290300370300200441a0026a41206a2219200841206a2223290300370300200441a0026a41186a221b200841186a2224290300370300200441a0026a41106a221c200841106a2225290300370300200441a0026a41086a221d200841086a2226290300370300200420082903003703a0022008202141306c6a220a41086a220c2903002111200a41106a220b2903002112200a41186a220f290300210e200a41206a220d2903002110200a41286a220029030021132008200a29030037030020222013370300202320103703002024200e370300202520123703002026201137030020002017290300370300200d2019290300370300200f201b290300370300200b201c290300370300200c201d290300370300200a20042903a0023703002026290300211120082903002112200441186a22272022290300370300200441106a22292023290300370300200441086a2205202429030037030020042025290300370300200841306a2101410021212007417f6a220f450d022001210a0340200a290300201256200a41086a290300220e201156200e2011511b450d03200a41306a210a200f202141016a2221470d000b200f21210c020b4188bbca0041004100103b000b4198bbca0020212007103b000b2008200741306c6a210a200f210b02400340200a2100200b220c20214d22060d01200c417f6a210b200041506a220a290300201258200a41086a290300220e201158200e2011511b0d000b0b0240200c2021490d00200f200c490d0241800121154100210d4100211a4100210f4100211441800121162001202141306c6a220921010340200020016b220a41306e210c0240200a41afe0004b22200d00200c41807f6a200c201a200d492014200f49220b7222181b210a02402018450d002016200a200b1b2116200a2015200b1b21150c010b200a200a41017622166b21150b02402014200f470d00024020160d00200441206a220f21140c010b4100210c200441206a2214210f2001210a0340200f200c3a0000200f410041014102200a2903002210201285200a41086a290300220e20118584501b2010201254200e201154200e2011511b1b41027441b8e0c3006a2802006a210f200a41306a210a2016200c41016a220c470d000b0b0240201a200d470d00024020150d00200441a0016a220d211a0c010b200041506a210a4100210c200441a0016a221a210d0340200d200c3a0000200d410041014102200a2903002210201285200a41086a290300220e20118584501b2010201254200e201154200e2011511b1b41027441c4e0c3006a2802006a210d200a41506a210a2015200c41016a220c470d000b0b0240200d201a6b220a200f20146b220c200c200a4b1b221f450d002017200120142d000041306c6a220a41286a2903003703002019200a41206a290300370300201b200a41186a290300370300201c200a41106a290300370300201d200a41086a2903003703002004200a2903003703a002200120142d000041306c6a220a2000201a2d0000417f7341306c6a220c290300370300200a41286a200c41286a290300370300200a41206a200c41206a290300370300200a41186a200c41186a290300370300200a41106a200c41106a290300370300200a41086a200c41086a2903003703000240201f4101460d004100210b03402000201a200b6a22182d0000417f7341306c6a220a20012014200b6a41016a221e2d000041306c6a220c290300370300200a41286a200c41286a290300370300200a41206a200c41206a290300370300200a41186a200c41186a290300370300200a41106a200c41106a290300370300200a41086a200c41086a2903003703002001201e2d000041306c6a220a2000201841016a2d0000417f7341306c6a220c290300370300200a41286a200c41286a290300370300200a41206a200c41206a290300370300200a41186a200c41186a290300370300200a41106a200c41106a290300370300200a41086a200c41086a290300370300200b41026a210a200b41016a220c210b200a201f490d000b201a200c6a211a2014200c6a21140b2000201a2d0000417f7341306c6a220a20042903a002370300200a41286a2017290300370300200a41206a2019290300370300200a41186a201b290300370300200a41106a201c290300370300200a41086a201d290300370300201a41016a211a201441016a21140b2001201641306c6a20012014200f461b21012000410020156b41306c6a2000201a200d461b210020200d000b024002402014200f4f0d002000210a034020172001200f417f6a220f2d000041306c6a220c41286a220b2903003703002019200c41206a220d290300370300201b200c41186a2200290300370300201c200c41106a2218290300370300201d200c41086a221e2903003703002004200c2903003703a002200a41506a220a41086a221a290300210e200a41106a221f2903002110200a41186a22152903002113200a41206a22162903002128200a41286a2220290300212a200c200a290300370300200b202a370300200d20283703002000201337030020182010370300201e200e37030020202017290300370300201620192903003703002015201b290300370300201f201c290300370300201a201d290300370300200a20042903a0023703002014200f490d000c020b0b2001210a201a200d4f0d000340200d417f6a220d2d0000210c2017200a41286a220b2903003703002019200a41206a220f290300370300201b200a41186a2201290300370300201c200a41106a2218290300370300201d200a41086a221e2903003703002004200a2903003703a0022000200c417f7341306c6a220c41086a2214290300210e200c41106a221f2903002110200c41186a22152903002113200c41206a22162903002128200c41286a2220290300212a200a200c290300370300200b202a370300200f20283703002001201337030020182010370300201e200e37030020202017290300370300201620192903003703002015201b290300370300201f201c2903003703002014201d290300370300200c20042903a002370300200a41306a210a201a200d490d000b0b2008201137030820082012370300200820042903003703102024200529030037030020232029290300370300202220272903003703002007200a20096b41306e20216a22014d0d032017202229030037030020192023290300370300201b2024290300370300201c2025290300370300201d2026290300370300200420082903003703a0022008200141306c6a220a41086a220c2903002111200a41106a220b2903002112200a41186a220f290300210e200a41206a220d2903002110200a41286a220029030021132008200a29030037030020222013370300202320103703002024200e370300202520123703002026201137030020002017290300370300200d2019290300370300200f201b290300370300200b201c290300370300200c201d290300370300200a20042903a002370300200720016b220c450d04200c20012001200c4b1b210b2007410376210f200a41306a2100024002402001200c417f6a220c490d002000200c200a200310bf03200821000c010b200820012002200310bf03200a2102200c21010b200b200f4f2105200141154f0d010c050b0b2021200c104b000b200c200f104a000b4198bbca0020012007103b000b41a8bbca00411c41c4bbca001039000b20014102490d00200041a07f6a210d410021184101210c0340200c41016a210f02402000200c41306c6a220b290300220e200b41506a220a29030058200b41086a221e2903002211200a41086a221429030022125820112012511b0d00200441186a221a200b41286a221f290300370300200441106a2215200b41206a2216290300370300200441086a2217200b41186a22192903003703002004200b290310370300200b200a290300370300201e2014290300370300200b41106a200a41106a2903003703002019200a41186a2903003703002016200a41206a290300370300201f200a41286a2903003703002000200c417f6a221e41306c6a211402400240201e0d004100211e0c010b2018210c200d210a200e200b41a07f6a220b290300582011200b41086a29030022125820112012511b0d00024002400340200a4188016a200a41d8006a290300370300200a4180016a200a41d0006a290300370300200a41f8006a200a41c8006a290300370300200a41f0006a200a41c0006a290300370300200a41e8006a200a41386a290300370300200a41e0006a200a41306a290300370300200c4101460d01200a2903002112200a41086a210b200c417f6a210c200a41506a210a200e2012562011200b29030022125620112012511b0d000c020b0b4100210c0b2000200c41306c6a2114200c211e0b2014200e370300201420113703082000201e41306c6a220a41286a201a290300370300200a41206a2015290300370300200a41186a2017290300370300200a20042903003703100b201841016a2118200d41306a210d200f210c200f2001470d000b0b200441d0026a24000bd10403027f017e047f230041d0006b2202240041eba1ca00ad4280808080f00084100122032900002104200241086a200341086a290000370300200220043703002003102f41c1cac800ad4280808080a00284100122032900002104200241106a41086a200341086a290000370300200220043703102003102f2002200136022c20022002412c6aad4280808080c00084100622032900003703302003102f200241c4006a200241306a360200200241003a00482002200241306a41086a36023c20022002412c6a3602402002200241306a360238200241206a200241386a106c0240024002400240024002402002280228220541206a2201417f4c0d0020022802202106024002402001450d002001102d2203450d062001410f4d0d01200121070c050b411021074110102d21030c030b200141017422084110200841104b1b220741004e0d010c050b103d000b200320012007103121030b2003450d010b20032002290300370000200341086a200241086a2903003700000240024020074170714110460d00200721080c010b200741017422084120200841204b1b22084100480d0220032007200810312203450d010b20032002290310370010200341186a200241106a41086a29030037000002400240200841606a2005490d00200821070c010b2005415f4b0d02200841017422072001200720014b1b22074100480d0220032008200710312203450d010b200341206a2006200510e8061a20002001360208200020073602042000200336020002402002280224450d002006102f0b200241d0006a24000f0b1036000b1038000bab0201037f230041e0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad841002107302400240200328021022010d00410021020c010b200328021421042003200341186a280200360224200320013602202003200341206a10e6010240024020032802000d0020032802042105410121020c010b4100210220034100360230200342013703282003410b36023c2003200341086a3602382003200341286a360244200341dc006a41013602002003420137024c200341b885c7003602482003200341386a360258200341c4006a41d8dbc100200341c8006a103c1a200335023042208620033502288410080240200328022c450d002003280228102f0b0b2004450d002001102f0b2000200536020420002002360200200341e0006a24000bd10403027f017e047f230041d0006b2202240041eba1ca00ad4280808080f00084100122032900002104200241086a200341086a290000370300200220043703002003102f41d3cac800ad4280808080a00284100122032900002104200241106a41086a200341086a290000370300200220043703102003102f2002200136022c20022002412c6aad4280808080c00084100622032900003703302003102f200241c4006a200241306a360200200241003a00482002200241306a41086a36023c20022002412c6a3602402002200241306a360238200241206a200241386a106c0240024002400240024002402002280228220541206a2201417f4c0d0020022802202106024002402001450d002001102d2203450d062001410f4d0d01200121070c050b411021074110102d21030c030b200141017422084110200841104b1b220741004e0d010c050b103d000b200320012007103121030b2003450d010b20032002290300370000200341086a200241086a2903003700000240024020074170714110460d00200721080c010b200741017422084120200841204b1b22084100480d0220032007200810312203450d010b20032002290310370010200341186a200241106a41086a29030037000002400240200841606a2005490d00200821070c010b2005415f4b0d02200841017422072001200720014b1b22074100480d0220032008200710312203450d010b200341206a2006200510e8061a20002001360208200020073602042000200336020002402002280224450d002006102f0b200241d0006a24000f0b1036000b1038000bb60306047f017e057f017e017f017e230041306b22022400200241286a200110e601024002400240024002402002280228450d00200041003602000c010b200228022c2203200128020441186e2204200420034b1b2205ad42187e2206422088a70d012006a72204417f4c0d010240024020040d00410821070c010b2004102d2207450d03200441186e21050b024002402003450d00200241106a41106a2108410021094100210a4100210b0340200241106a2001109c032002290310a70d02200829030021062002290318210c200241086a200110e60120022802080d02200b41016a2104200228020c210d0240200b2005470d0020092004200920044b1bad42187e220e422088a70d07200ea722054100480d0702400240200b0d002005102d21070c010b2007200a2005103121070b2007450d06200541186e21050b2007200a6a220b2006370308200b200c370300200b41106a200d360200200941026a2109200a41186a210a2004210b20032004470d000b0b2000200536020420002007360200200041086a20033602000c010b200041003602002005450d002007102f0b200241306a24000f0b103d000b1036000b1038000bc60501067f230041106b220224002002410036020820024201370300024002404120102d2203450d00200242a080808080043702042002200336020020032000290034370000200341086a2000413c6a290000370000200341106a200041c4006a290000370000200341186a200041cc006a2900003700002002200036020c2002410c6a200210c2022002200041106a36020c2002410c6a200210c20220002802202103200041286a28020022042002106902402004450d002003200441186c6a210403402002200336020c2002410c6a200210c202200341106a20021095022004200341186a2203470d000b0b02400240200028022c4101460d00024002402002280204220420022802082205460d00200228020021030c010b200541016a22032005490d04200541017422042003200420034b1b22044100480d040240024020050d002004102d21030c010b200228020020052004103121030b2003450d0320022004360204200220033602000b2002200541016a2200360208200320056a41003a00000c010b024002402002280204220420022802082205460d00200228020021030c010b200541016a22032005490d03200541017422042003200420034b1b22044100480d030240024020050d002004102d21030c010b200228020020052004103121030b2003450d0220022004360204200220033602000b2002200541016a2206360208200320056a41013a00002000280230210702400240200420066b4104490d00200541056a21000c010b200641046a22002006490d03200441017422052000200520004b1b22054100480d030240024020040d002005102d21030c010b200320042005103121030b2003450d022002200536020420022003360200200521040b20022000360208200320066a20073600000b20012902002000ad4220862003ad84100402402004450d002003102f0b200241106a24000f0b1036000b1038000bdc0304057f017e027f027e230041306b22022400200241206a2001350208422086200135020084101810730240024020022802202203450d002001410c6a2104200141046a2105200241186a21060240024003400240024020022902242207422088a722084120490d0020042003460d0120042003412010ea06450d010b2007a7450d042003102f0c040b02402008417f4c0d002008102d2209450d0220092003200810e806210902402005280200450d002001280200102f0b200120083602082001200936020020052008360200200241086a20032008109c0102402002290308a7450d002006290300210a2002290310210b024020012d002c450d002007428080808070832003ad8410050b20012802082208411f4d0d04200841606a2208417f4c0d01200128020021010240024020080d00410121050c010b2008102d2205450d040b2005200141206a200810e8062101200041186a200a370300200041106a200b370300200041086a200836020020002008360204200020013602002007a7450d062003102f0c060b02402007a7450d002003102f0b200241206a200135020842208620013502008410181073200228022022030d010c040b0b103d000b1036000b41202008104b000b200041003602000b200241306a24000bdc0203047f017e017f230041106b2203240002400240024002400240200141206a2204417f4c0d002004450d01200410332205450d022004410f4d0d0341e7a2ca00ad4280808080800184100122062900002107200341086a2208200641086a290000370300200320073703002006102f200541086a2008290300370000200520032903003700002004411f4d0d0441f9b5c600ad4280808080d000841001220629000021072008200641086a290000370300200320073703002006102f200541186a200829030037000020052003290300370010200541206a2000200110e8061a2003200228020022082002280208109d042004ad4220862005ad84200335020842208620032802002204ad84100402402003280204450d002004102f0b2005102f0240200241046a280200450d002008102f0b200341106a24000f0b103d000b41104100104a000b1036000b41102004104a000b41202004104a000bcb0304047f017e017f017e230041106b2203240002400240024002400240200141206a2204417f4c0d002004450d01200410332205450d022004410f4d0d0341e7a2ca00ad4280808080800184100122062900002107200341086a2208200641086a290000370300200320073703002006102f200541086a2008290300370000200520032903003700002004411f4d0d0441f0e8c600ad4280808080f000841001220629000021072008200641086a290000370300200320073703002006102f200541186a200829030037000020052003290300370010200541206a2000200110e8061a200241086a2903002107200229030021094110102d2208450d022008200937000020082007370008200241186a29030021072002290310210920084110412010312208450d0220082009370010200841186a2007370000200241286a2903002107200229032021092008412041c00010312208450d0220082009370020200841286a200737000020082002290330370030200841386a200241386a2903003700002004ad4220862005ad842008ad428080808080088410042008102f2005102f200341106a24000f0b103d000b41104100104a000b1036000b41102004104a000b41202004104a000b960203047f017e017f230041106b2203240002400240024002400240200241206a2204417f4c0d002004450d01200410332205450d022004410f4d0d0341e7a2ca00ad4280808080800184100122062900002107200341086a2208200641086a290000370300200320073703002006102f200541086a2008290300370000200520032903003700002004411f4d0d0441f0e8c600ad4280808080f000841001220629000021072008200641086a290000370300200320073703002006102f200541186a200829030037000020052003290300370010200541206a2001200210e8061a2000200520041089042005102f200341106a24000f0b103d000b41104100104a000b1036000b41102004104a000b41202004104a000bed0507047f017e027f017e017f057e017f230041d0006b22022400200241386a2001350208422086200135020084101810730240024020022802382203450d002001410c6a2104200141046a210502400240034002400240200229023c2206422088a722074120490d0020042003460d0120042003412010ea06450d010b2006a7450d042003102f0c040b02402007417f4c0d002007102d2208450d0220082003200710e806210802402005280200450d002001280200102f0b2001200736020820012008360200200520073602002002200736020420022003360200200241086a2006428080808070832003ad84220910021073024020022802082207450d00200228020c21080240024002402002280210220a4110490d00200a4170714110460d00200a417c714120470d010b20024100360220200242013703182002410b36022c200220023602282002200241186a3602342002410136024c2002420137023c200241b885c7003602382002200241286a360248200241346a41d8dbc100200241386a103c1a200235022042208620023502188410080240200228021c450d002002280218102f0b4200210b0c010b200741086a290000210c2007290000210d200741186a290000210e2007290010210f200728002021104201210b0b02402008450d002007102f0b200b500d00024020012d002c450d00200910050b20012802082207411f4d0d04200741606a2207417f4c0d01200128020021010240024020070d00410121050c010b2007102d2205450d040b2005200141206a200710e8062101200041286a200e370200200041206a200f370200200041186a200c370200200041106a200d370200200041306a2010360200200041086a200736020020002007360204200020013602002006a7450d062003102f0c060b02402006a7450d002003102f0b200241386a200135020842208620013502008410181073200228023822030d010c040b0b103d000b1036000b41202007104b000b200041003602000b200241d0006a24000bcd0604097f017e027f057e230041e0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100210730240024020032802102204450d00200328021421052003200341186a280200360224200320043602202003200341206a10e6010240024002400240024020032802000d002003280204220620032802244105762201200120064b1b22074105742201417f4c0d040240024020070d00410821080c010b2001102d2208450d030b024002402006450d00410021094100210a410021010340200341c0006a200341206a10f3020240024020032d00404101460d004103210b200328022422024110490d012003290041210c2003200241706a220d36022420032003280220220e41106a360220200d450d01200e41086a290000210f200e290000211020032002416f6a3602242003200e41116a3602204103210b200e2d0010220241034f0d01200320032800403602282003200341c0006a41036a28000036002b200c211120102112200f21132002210b0c010b4103210b0b200320032802283602382003200328002b36003b200b4103460d02200141016a21022003200328003b36005b20032003280238360258024020012007470d0020092002200920024b1b220741ffffff3f712007470d07200741057422074100480d070240024020010d002007102d21080c010b2008200a2007103121080b2008450d06200741057621070b2008200a6a220141186a200b3a00002001201337030820012012370300200141106a2011370300200141196a20032802583600002001411c6a200328005b360000200941026a2109200a41206a210a2002210120062002470d000b0b2008450d012000200736020420002008360200200041086a20063602000c020b2007450d002008102f0b20034100360230200342013703282003410b36023c2003200341086a3602382003200341286a360258200341d4006a410136020020034201370244200341b885c7003602402003200341386a360250200341d8006a41d8dbc100200341c0006a103c1a200335023042208620033502288410080240200328022c450d002003280228102f0b200041003602000b2005450d042004102f0c040b1036000b1038000b103d000b200041003602000b200341e0006a24000be00503047f017e027f230041d0016b2202240020022001350208422086200135020084101810730240024020022802002203450d002001410c6a2104200141046a21050240024003400240024020022902042206422088a722074120490d0020042003460d0120042003412010ea06450d010b2006a7450d042003102f0c040b02402007417f4c0d002007102d2208450d0220082003200710e806210802402005280200450d002001280200102f0b200120073602082001200836020020052007360200200220032007108904024020022903004201520d00200241c8006a41386a200241c0006a290300370300200241c8006a41306a200241386a290300370300200241c8006a41286a200241306a290300370300200241c8006a41206a200241286a290300370300200241c8006a41186a200241206a290300370300200241c8006a41106a200241186a290300370300200241d0006a200241106a29030037030020022002290308370348024020012d002c450d002006428080808070832003ad8410050b20012802082207411f4d0d04200741606a2207417f4c0d01200128020021010240024020070d00410121050c010b2007102d2205450d040b2005200141206a200710e8062101200041086a20073602002000200736020420002001360200200241c8016a20024180016a290300370200200241c0016a200241f8006a290300370200200241b8016a200241f0006a290300370200200241b0016a200241e8006a290300370200200241a8016a200241e0006a290300370200200241a0016a200241d8006a2903003702002002418c016a410c6a200241c8006a41086a29030037020020022002290348370290012000410c6a2002418c016a41c40010e8061a2006a7450d062003102f0c060b02402006a7450d002003102f0b2002200135020842208620013502008410181073200228020022030d010c040b0b103d000b1036000b41202007104b000b200041003602000b200241d0016a24000bc20202037f017e230041206b2207240002400240024002400240200641206a2208417f4c0d002008450d01200810332209450d022008410f4d0d032002ad4220862001ad8410012202290000210a200741106a41086a2201200241086a2900003703002007200a3703102002102f200941086a2001290300370000200920072903103700002008411f4d0d042004ad4220862003ad8410012202290000210a2001200241086a2900003703002007200a3703102002102f200941186a200129030037000020092007290310370010200941206a2005200610e8061a200741086a20092008109501200728020c21010240200728020822064101470d002008ad4220862009ad8410050b2009102f2000200136020420002006360200200741206a24000f0b103d000b41104100104a000b1036000b41102008104a000b41202008104a000b9e0407047f017e017f017e017f017e057f230041e0006b22002400200041306a41186a22014200370300200041306a41106a22024200370300200041306a41086a2203420037030020004200370330418de6c300ad4280808080e000842204100122052900002106200041d0006a41086a2207200541086a290000370300200020063703502005102f200320072903003703002000200029035037033041d480c400ad4280808080b0028422061001220529000021082007200541086a290000370300200020083703502005102f200220002903502208370300200041106a41086a22092003290300370300200041106a41106a220a2008370300200041106a41186a220b200729030037030020002000290330370310200041086a200041106a4120109501200028020c210c2000280208210d2001420037030020024200370300200342003703002000420037033020041001220529000021042007200541086a290000370300200020043703502005102f200320072903003703002000200029035037033020061001220529000021042007200541086a290000370300200020043703502005102f20022000290350220437030020092003290300370300200a2004370300200b2007290300370300200020002903303703102000200c4100200d1b2207418094ebdc032007418094ebdc03491b360230200041106aad4280808080800484200041306aad4280808080c000841004200041e0006a24000ba91109017f017e037f017e017f017e047f017e017f230041e0006b22052400200541003602204180e5c300ad4280808080800284200541206aad4280808080c0008422061004200541206a41186a22074200370300200541206a41106a22084200370300200541206a41086a2209420037030020054200370320418de6c300ad4280808080e00084220a1001220b290000210c200541c0006a41086a220d200b41086a2900003703002005200c370340200b102f2009200d29030037030020052005290340370320419ce6c300ad4280808080e000841001220e290000210c200541d0006a41086a220b200e41086a2900003703002005200c370350200e102f20082005290350220c370300200541086a220e2009290300370300200541106a220f200c370300200541186a2210200b29030037030020052005290320370300200520003602202005ad22114280808080800484220c2006100420074200370300200842003703002009420037030020054200370320200a100122122900002106200d201241086a290000370300200520063703402012102f2009200d2903003703002005200529034037032041bae6c300ad4280808080e00084100122122900002106200b201241086a290000370300200520063703502012102f200820052903502206370300200e2009290300370300200f20063703002010200b29030037030020052005290320370300200520053602202005412036022420032802002003280208200541206a10f50220074200370300200842003703002009420037030020054200370320200a100122032900002106200d200341086a290000370300200520063703402003102f2009200d2903003703002005200529034037032041a2e6c300ad4280808080a00184100122032900002106200b200341086a290000370300200520063703502003102f200820052903502206370300200e2009290300370300200f20063703002010200b2903003703002005200529032037030002404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a290000370000200c2003ad428080808080048410042003102f200a10012203290000210a200d200341086a2900003703002005200a3703402003102f4193e6c300ad42808080809001841001220d290000210a200b200d41086a2900003703002005200a370350200d102f20052000417f6a36020020114280808080c000841003220d290000210a200d41086a2900002106200d41106a29000021112007200d41186a29000037030020082011370300200920063703002005200a370320200d102f41c000102d2209450d00200920052903403700002009200529035037001020092005290320370020200941086a200541c0006a41086a2203290300370000200941186a200541d0006a41086a2207290300370000200941286a200541206a41086a220b290300370000200941306a200541206a41106a2200290300370000200941386a200541206a41186a220e2903003700004120102d220d450d00200d2001290000370000200d41186a200141186a290000370000200d41106a200141106a290000370000200d41086a200141086a2900003700002009ad4280808080800884200dad42808080808004841004200d102f2009102f200e420037030020004200370300200b420037030020054200370320418de6c300ad4280808080e0008410012209290000210a2003200941086a2900003703002005200a3703402009102f200b20032903003703002005200529034037032041ace6c300ad4280808080e0018410012209290000210a2007200941086a2900003703002005200a3703502009102f20082005290350370000200841086a2007290300370000200541086a200b290300370300200541106a2000290300370300200541186a200e290300370300200520052903203703004120102d2209450d0020092002290000370000200941186a200241186a290000370000200941106a200241106a290000370000200941086a200241086a290000370000200c2009ad428080808080048410042009102f02402004450d00200541206a41186a22014200370300200541206a41106a220d4200370300200541206a41086a2209420037030020054200370320418de6c300ad4280808080e00084220a100122032900002106200541c0006a41086a220b200341086a290000370300200520063703402003102f2009200b2903003703002005200529034037032041baebc300ad4280808080e00084100122022900002106200541d0006a41086a2203200241086a290000370300200520063703502002102f20082005290350370000200841086a22022003290300370000200541086a22072009290300370300200541106a2200200d290300370300200541186a220e200129030037030020052005290320370300200c100520014200370300200d42003703002009420037030020054200370320200a1001220f2900002106200b200f41086a29000037030020052006370340200f102f2009200b2903003703002005200529034037032041d882c400ad4280808080a001841001220f29000021062003200f41086a29000037030020052006370350200f102f2008200529035037000020022003290300370000200720092903003703002000200d290300370300200e200129030037030020052005290320370300200c100520014200370300200d42003703002009420037030020054200370320200a1001220f290000210a200b200f41086a2900003703002005200a370340200f102f2009200b2903003703002005200529034037032041c0ebc300ad4280808080b001841001220b290000210a2003200b41086a2900003703002005200a370350200b102f2008200529035037000020022003290300370000200720092903003703002000200d290300370300200e200129030037030020052005290320370300200c10130b200541e0006a24000f0b1036000b90a2010c017f017e017f047e037f027e0e7f067e117f027e027f047e230041f00a6b22012400200141003602d803200142013703d00302400240024002400240024020004180ee05700d0041c6b5c400ad4280808080f000842202100122032900002104200329000821052003102f41ebdec700ad4280808080f00084100122032900002106200329000821072003102f200120073702a807200120063702a00720012005370298072001200437029007200141d8046a20014190076a412010aa0220012902dc04420020012802d80422031b21042003410120031b2103024020012802d403450d0020012802d003102f0b200120043702d403200120033602d0032001200141d0036a3602dc032002100122032900002102200329000821042003102f41e4d8c400ad42808080803084100122032900002105200329000821062003102f200120063702a807200120053702a00720012004370298072001200237029007200141b8036a20014190076a4120109c01200141b8036a41106a290300210220012903c003210420012802b8032103200141e0036a41e7d8c400411010ac04200141003a00f8042002420020031b21062004420020031b2107200141e0036a21084120210341002109024002400240024002400340200141003a00900720014190076a20082003410047220a10e8061a024020030d00200141003a0090070b2003200a490d01200141d8046a20096a20012d0090073a00002001200941016a22093a00f8042003200a6b21032008200a6a210820094120470d000b20012903d804210420012903e004210520012903e804210b20012903f004210c4100210d200141d8046a410041800210e7061a4200210220014188076a420037030020014180076a4200370300200141f8066a200c370300200141f0066a200b370300200141e8066a2005370300200120043703e006200141c0003602d8064108210e024020012802dc0341086a2802000d00410021090c050b41c6b5c400ad4280808080f00084100122032900002104200329000821052003102f418c91c700ad4280808080a0018410012203290000210b2003290008210c2003102f2001200c3702a8072001200b3702a0072001200537029807200120043702900720014180096a20014190076a10ad040240024020012802800922030d00410021090c010b20014190076aad428080808080048410052001290284092202422088a721092003210e0b024020012802dc03220341046a280200220a200328020822086b20094f0d00200820096a22092008490d08200a41017422082009200820094b1b220941ffffff3f712009470d08200941057422094100480d0802400240200a0d002009102d210a0c010b2003280200200a41057420091031210a0b200a450d072003200a360200200341046a20094105763602000b418de6c300ad4280808080e00084100122032900002104200329000821052003102f419ce6c300ad4280808080e0008410012203290000210b2003290008210c2003102f2001200c3702a8072001200b3702a00720012005370298072001200437029007200141b0036a20014190076a412010950120012802dc0341086a28020041f4036a2203450d0120012802b403210920012802b003210a200141e4003a009107200141e40041d0860320036e22036b3a0090074100210f200120014190076a200341ff017141e4004b6a2d00004180fe126c20094100200a1b6a36028404200141003602900420014201370388042001410036029404200142003703a0042001420037039804200142003703e80a200142003703e00a200141d0046a20014184046a360200200141cc046a200141e00a6a360200200141a8046a41206a20014194046a360200200141c4046a20014198046a360200200141c0046a20014188046a360200200141bc046a200141d8046a3602002001200e2002422088a7220341e8006c220a6a3602b4042001200e3602b00420012002a722103602ac042001200e3602a8042001200141dc036a3602b8040240024002402003450d0020014190076a4101722111200141b8046a2112200e210303402001200341e8006a22083602b00420032d0000210920014180096a200341016a41e70010e8061a20094102460d01200120093a009007201120014180096a41e70010e8061a200141a00a6a201220014190076a10ae0420012903a00a4201510d0220082103200a41987f6a220a0d000b0b4108211102402010450d00200e102f0b410021100c010b200141e8096a41306a200141a00a6a41386a2903002202370300200141e8096a41286a200141a00a6a41306a2903002204370300200141e8096a41206a200141a00a6a41286a2903002205370300200141c8086a41086a2211200141a00a6a41106a290300370300200141c8086a41106a2212200141a00a6a41186a290300370300200141c8086a41186a2208200141a00a6a41206a290300370300200141c8086a41206a220a2005370300200141c8086a41286a22092004370300200141c8086a41306a22032002370300200120012903a80a3703c80820014190086a41306a220e200329030037030020014190086a41286a2203200929030037030020014190086a41206a2209200a29030037030020014190086a41186a220a200829030037030020014190086a41106a2208201229030037030020014190086a41086a22122011290300370300200120012903c808370390084138102d2211450d072011200129039008370300201141306a200e290300370300201141286a2003290300370300201141206a2009290300370300201141186a200a290300370300201141106a2008290300370300201141086a20122903003703002012200141a8046a41086a29030022023703002003200141a8046a41286a2802003602002009200141a8046a41206a290300370300200a200141a8046a41186a2903003703002008200141a8046a41106a290300370300200120012903a80437039008024002402002a72209200128029c082208470d004101210f410121100c010b200841987f6a2113200141a00a6a41086a211420014190076a410172211220014190086a41106a210e4101210f4101211003402009210303402001200341e8006a220a3602980820032d0000210920014180096a200341016a41e70010e8061a20094102460d02200120093a009007201220014180096a41e70010e8061a200141a00a6a200e20014190076a10ae04024020012903a00a4201510d00200a21032008200a470d010c030b0b200141e8096a41306a201441306a2903002202370300200141e8096a41286a201441286a2903002204370300200141e8096a41206a201441206a2903002205370300200141c8086a41086a2209201441086a290300370300200141c8086a41106a220a201441106a290300370300200141c8086a41186a2215201441186a290300370300200141c8086a41206a22162005370300200141c8086a41286a22172004370300200141c8086a41306a22182002370300200120142903003703c80820014190076a41306a2219201829030037030020014190076a41286a2218201729030037030020014190076a41206a2217201629030037030020014190076a41186a2216201529030037030020014190076a41106a2215200a29030037030020014190076a41086a221a2009290300370300200120012903c8083703900702402010200f470d00200f41016a2209200f490d0b200f410174220a2009200a20094b1bad42387e2202422088a70d0b2002a722094100480d0b02400240200f0d002009102d21110c010b2011200f41386c2009103121110b2011450d0a200941386e21100b200341e8006a21092011200f41386c6a220a200129039007370300200a41306a2019290300370300200a41286a2018290300370300200a41206a2017290300370300200a41186a2016290300370300200a41106a2015290300370300200a41086a201a290300370300200f41016a210f20132003470d000b0b200128029408450d00200128029008102f0b41c6b5c400ad4280808080f00084100122032900002102200329000821042003102f41d7b5c400ad4280808080d000841001220329000021052003290008210b2003102f2001200b3702a807200120053702a0072001200437029807200120023702900720014190076aad4280808080800484220b1013024020012903980420014198046a41086a29030084500d00024002402001280290042203450d002001280288042109200141d8046a2003417f6a10af04220a2003490d0141acd9c400200a2003103b000b20014180096a10e80320014190076a41bcd9c40010b402200141a00a6a20014180096a20014190076a200129039804200141a0046a290300410110f2020c010b2009200a4105746a200128028404200129039804200141a0046a29030010b0040b024020012903e00a2202200141e00a6a41086a290300220484500d0020014180096a41bcd9c40010b40220014190076a10e803200141a00a6a20014180096a20014190076a20012903e00a200141e80a6a290300410110f2024200200620047d2007200254ad7d2204200720027d2202200756200420065620042006511b22031b21064200200220031b21070b410021090240200f450d00200f41386c2109201141046a2108200141d8046a200128029404417f6a10af04210e2011210303402008210a2009450d0402402003290328200341306a29030084500d00200941486a2109200a41386a210820032802002112200341386a21032012200e4d0d010b0b20014180096a41186a200a41186a29000037030020014180096a41106a200a41106a29000037030020014180096a41086a200a41086a2900003703002001200a290000370380094100210a410021144101210e0240200f41386c2212450d00201241386d220341ffffff3f712003470d09200341057422034100480d092003102d220e450d08200341057621140b41002108200e210303402011200a6a220941046a29020021022009410c6a2902002104200941146a2902002105200341186a2009411c6a290200370000200341106a2005370000200341086a200437000020032002370000200341206a2103200841016a21082012200a41386a220a470d000b02402010450d002011102f0b20012802dc032203280200200328020810870120012802dc03220328020821092003280200210a41c6b5c400ad4280808080f000842202100122032900002104200329000821052003102f41ebdec700ad4280808080f0008410012203290000210c2003290008211b2003102f2001201b3702a8072001200c3702a00720012005370298072001200437029007200120014190076a3602a00a200141203602a40a200a2009200141a00a6a10ad012002100122032900002102200329000821042003102f419ab6c400ad4280808080c000841001220329000021052003290008210c2003102f2001200c3702a807200120053702a007200120043702980720012002370290074120102d2203450d072003200129038009370000200341186a20014180096a41186a2209290300370000200341106a20014180096a41106a220a290300370000200341086a20014180096a41086a2212290300370000200b2003ad428080808080048410042003102f20014190076a41086a41063a000020014199076a200129038009370000200141a1076a2012290300370000200141a9076a200a290300370000200141b1076a2009290300370000200141c4076a2008360200200141c0076a2014360200200141bc076a200e360200200141123a00900741c8e1ca00410020014190076a108c01410121090b20014180096a41bcd9c40010b40220014190076a20014180096a108d0220014198076a2903002102200129039007210441c6b5c400ad4280808080f000841001220329000021052003290008210c2003102f41e4d8c400ad4280808080308410012203290000211b2003290008211c2003102f2001201c3702a8072001201b3702a0072001200c37029807200120053702900720014200200420077d22052005200456200220067d2004200754ad7d220420025620042002511b22031b4201884200200420031b2202423f8684220442808094f6c2d7e8d800200442808094f6c2d7e8d80054410020024201882202501b22031b220420077c22073703800920012002420020031b20067c2007200454ad7c220637038809200b20014180096aad4280808080800284100420090d032010450d032011102f0c030b200a2003104b000b4180d9c4004119419cd9c4001039000b41cbd9c40041d70041a4dac4001055000b0240200128028c04450d00200128028804102f0b20012802dc0341086a28020021090b41c6b5c400ad4280808080f00084221b100122032900002102200329000821042003102f41cdb5c400ad4280808080a001841001220329000021052003290008210b2003102f2001200b3702a807200120053702a00720012004370298072001200237029007200141a8036a20014190076a41201095014108211002400240410020012802ac03410020012802a8031b220320096b2209200920034b1b2203410a2003410a491b22090d00410021140c010b201b100122032900002102200329000821042003102f41b4dac400ad4280808080c000841001220329000021052003290008210b2003102f2001200b3702a807200120053702a0072001200437029807200120023702900720014180096a20014190076a10ad04024020012802800922190d00410021140c010b024002400240200129028409221d422088a722110d00201da72103410821104100210d410021140c010b0240024020110d0041002114410821104100210d0c010b20112009200920114b1b210e201941286a2103410021184100210d4100211441082110420021024200210441002112410021094100210a024002400340024002402012200e4f0d00024002400240200341106a2903002205200341186a290300220b84500d00200220057c220c2007562004200b7c200c200254ad7c220420065620042006511b450d01200c21020c030b201841ff01710d0220014180096a41186a2208200341386a29000037030020014180096a41106a220f200341306a29000037030020014180096a41086a2213200341286a2900003703002001200341206a2900003703800902400240200341586a2d00004101470d002001200341596a221541036a28000036009307200341086a2903002105200341606a2216290000210b201641086a290000210c201528000021152003290300211c200141a8046a41086a200341706a221641086a2d00003a00002001201536029007200120162900003703a804410121150c010b200341606a2215290300210b201541086a290300210c410021150b20014190086a41186a2216200829030037030020014190086a41106a2217200f29030037030020014190086a41086a220f2013290300370300200141e00a6a41086a2213200141a8046a41086a29030037030020012001290380093703900820012001280290073602a00a20012001280093073600a30a200120012903a8043703e00a0240200d2014470d00200d41016a2208200d490d0e200d41017422142008201420084b1bad42e8007e221e422088a70d0e201ea722084100480d0e02400240200d0d002008102d21100c010b2010200d41e8006c2008103121100b2010450d0d200841e8006e21140b2010200d41e8006c6a220820153a0000200841106a200c370300200841086a200b370300200820012802a00a360001200841046a20012800a30a3600002013290300210b20012903e00a210c200841c0006a420037030020084200370338200841306a2005370300200841286a201c370300200841186a200c370300200841206a200b3703002008200129039008370348200841d0006a200f290300370300200841d8006a2017290300370300200841e0006a2016290300370300410121180c010b20014180096a41186a2208200341386a29000037030020014180096a41106a220f200341306a29000037030020014180096a41086a2213200341286a2900003703002001200341206a2900003703800902400240200341586a2d00004101470d002001200341596a221541036a28000036009307200341086a2903002102200341606a2216290000211c201641086a290000211e201528000021152003290300211f200141a8046a41086a200341706a221641086a2d00003a00002001201536029007200120162900003703a804410121150c010b200341606a2215290300211c201541086a290300211e410021150b200141a00a6a41186a22162008290300370300200141a00a6a41106a2217200f290300370300200141a00a6a41086a220f201329030037030020014190086a41086a2213200141a8046a41086a29030037030020012001290380093703a00a20012001280290073602e80920012001280093073600eb09200120012903a804370390080240200d2014470d00200d41016a2208200d490d0d200d41017422142008201420084b1bad42e8007e2220422088a70d0d2020a722084100480d0d02400240200d0d002008102d21100c010b2010200d41e8006c2008103121100b2010450d0c200841e8006e21140b2010200d41e8006c6a220820153a0000200841106a201e370300200841086a201c370300200820012802e809360001200841046a20012800eb093600002013290300211c200129039008211e200841c0006a200b37030020082005370338200841306a2002370300200841286a201f370300200841186a201e370300200841206a201c370300200820012903a00a370348200841d0006a200f290300370300200841d8006a2017290300370300200841e0006a2016290300370300200c21020b200941016a2109201241016a2112200d41016a210d0c010b024020090d00410021090c010b200a20096b220820114f0d0220014190076a2003200941987f6c6a41586a220841e80010e8061a2008200341586a220f41e80010e9061a200f20014190076a41e80010e8061a0b200341e8006a21032011200a41016a220a460d020c000b0b4188bbca0020082011103b000b02402009417f6a20114f0d00201d42ffffffff0f83201120096bad42208684211d0b2012450d0041c6b5c400ad4280808080f00084100122032900002102200329000821042003102f41b4dac400ad4280808080c00084100122032900002105200329000821062003102f200120063702a807200120053702a0072001200437029807200120023702900720014180096a2019201d422088a710b10420014190076aad42808080808004842001350288094220862001280280092209ad841004201da721030240200128028409450d002009102f0b20030d020c030b201da721030b2003450d010b2019102f0b201b100122032900002102200329000821042003102f418c91c700ad4280808080a00184100122032900002105200329000821062003102f200120063702a807200120053702a0072001200437029807200120023702900720014180096a2010200d10b10420014190076aad42808080808004842001350288094220862001280280092203ad8410040240200128028409450d002003102f0b41002103024020012802dc03221141086a2802002209410276220a450d0041002103200a2009460d004100210a0340200a41026a21032009200a41046a411e71762208450d012003210a20082009470d000b0b410021120340024020124101742212410172220aad220220027e2202422088a70d002012200a2002a720092003411f71764b1b21120b02402003450d0041002003417e6a220a200a20034b1b21030c010b0b02402012450d0002400240200d41e8006c220e450d00201041c8006a210f4100210d0c010b2012417f6a210a03402009450d07200141d8046a2009417f6a10af04220320094f0d08200a450d02200a417f6a210a20012802dc0328020821090c000b0b03402009450d062011280200210a200141d8046a2009417f6a10af04220320094f0d07200d41016a210d200a20034105746a2111200e2108200f2109034020014190076a2009201110b2042001350298072102200128029007210a4101102d2203450d04200341003a00002002422086200aad842003ad4280808080108410042003102f0240200128029407450d00200a102f0b200941e8006a2109200841987f6a22080d000b200d2012460d0120012802dc03221128020821090c000b0b2014450d002010102f0b0240024002400240024002400240024020004180a70c70220d0d00024020012802d8030d0041c6b5c400ad4280808080f00084100122032900002102200329000821042003102f41ebdec700ad4280808080f00084100122032900002105200329000821062003102f200120063702a807200120053702a00720012004370298072001200237029007200141d8046a20014190076a412010aa0220012902dc04420020012802d80422031b21022003410120031b2103024020012802d403450d0020012802d003102f0b200120033602d003200120023702d4032002428080808010540d010b41c6b5c400ad4280808080f00084100122032900002102200329000821042003102f41e4dac400ad4280808080800184100122032900002105200329000821062003102f200120063702a807200120053702a00720012004370298072001200237029007200141d8046a20014190076a412010ad02024020012d00d8044101470d00200141e1046a2800002103200141e5046a2800002109200141e9046a280000210a200141ed046a2800002108200141f1046a280000211120012800d904211220012800dd04210e2001200141f5046a2800003602f404200120113602f004200120083602ec042001200a3602e804200120093602e404200120033602e0042001200e3602dc04200120123602d8040240024020012802d8032209450d0020012802d0032103200941057421094100211141002112034020014190076a200310b304200128029007220820012802980710b40441ff0171210a0240200128029407450d002008102f0b024002400240200a417e6a220a41014b0d00200a0e020102010b201141016a21110c010b201241016a21120b200341206a2103200941606a22090d000b201220114a0d010b200141d8046a10b50441c6b5c400ad4280808080f00084100122032900002102200329000821042003102f41ebdec700ad4280808080f00084100122032900002105200329000821062003102f200120063702a807200120053702a0072001200437029807200120023702900720014180096a20014190076a412010aa02200129028409420020012802800922031b21022003410120031b2103024020012802d403450d0020012802d003102f0b200120023702d403200120033602d0030b41c6b5c400ad4280808080f00084100122032900002102200329000821042003102f41ecdac400ad4280808080d00184100122032900002105200329000821062003102f200120063702a807200120053702a0072001200437029807200120023702900720014190076aad428080808080048410130b024020012802d80341024d0d0020014180096a41f9dac400411110ac04200141003a00f80420014180096a210841202103410021090340200141003a00900720014190076a20082003410047220a10e8061a024020030d00200141003a0090070b2003200a490d03200141d8046a20096a20012d0090073a00002001200941016a22093a00f8042003200a6b21032008200a6a210820094120470d000b20012903d804210220012903e004210420012903e804210520012903f0042106200141d8046a410041800210e7061a20014188076a420037030020014180076a4200370300200141f8066a2006370300200141f0066a2005370300200141e8066a2004370300200120023703e006200141c0003602d80620012802d8032203417f6a2209450d032003450d04024002402003417e6a2209450d0020012802d003210a200141d8046a2003417d6a10af0422082009490d0141acd9c40020082009103b000b41b8dac400411c418cdbc4001055000b41c6b5c400ad4280808080f00084100122032900002102200329000821042003102f41e4dac400ad4280808080800184100122032900002105200329000821062003102f200120063702a807200120053702a007200120043702980720012002370290074120102d2203450d092003200a41206a20084105746a2209290000370000200341186a200941186a220a290000370000200341106a200941106a2208290000370000200341086a200941086a221129000037000020014190076aad42808080808004842003ad428080808080048410042003102f20014190076a41086a410a3a000020014199076a2009290000370000200141a1076a2011290000370000200141a9076a2008290000370000200141b1076a200a290000370000200141123a00900741c8e1ca00410020014190076a108c010c010b41c6b5c400ad4280808080f00084100122032900002102200329000821042003102f41e4dac400ad4280808080800184100122032900002105200329000821062003102f200120063702a807200120053702a0072001200437029807200120023702900720014190076aad428080808080048410050b024020012802d403450d0020012802d003102f0b20014190076a41186a2208420037030020014190076a41106a2203420037030020014190076a41086a220942003703002001420037039007418de6c300ad4280808080e000841001220a29000021022009200a41086a2900003703002001200237039007200a102f41a2e6c300ad4280808080a001841001220a2900002102200141d8046a41086a2211200a41086a290000370300200120023703d804200a102f200320012903d804220237030020014180096a41086a200929030037030020014180096a41106a200237030020014180096a41186a2011290300370300200120012903900737038009200141d8046a20014180096a412010ad0220012d00d804210a2008200141f1046a2900003703002003200141e9046a2900003703002009200141e1046a290000370300200120012900d9043703900702400240200a4101460d00200141a00a6a41186a4200370300200141a00a6a41106a4200370300200141a00a6a41086a4200370300200142003703a00a0c010b200141a00a6a41186a2008290300370300200141a00a6a41106a2003290300370300200141a00a6a41086a200929030037030020012001290390073703a00a0b20014190076a41186a2208420037030020014190076a41106a2211420037030020014190076a41086a22094200370300200142003703900741dcbec600ad42808080808003841001220a29000021022009200a41086a2900003703002001200237039007200a102f41f4bec600ad4280808080e001841001220a2900002102200141d8046a41086a2212200a41086a290000370300200120023703d804200a102f200320012903d804370000200341086a201229030037000020014180096a41086a200929030037030020014180096a41106a201129030037030020014180096a41186a2008290300370300200120012903900737038009200141e8096a20014180096a412010aa02024002400240024020012802e80922030d002008200141a00a6a41186a2903003703002011200141a00a6a41106a2903003703002009200141a00a6a41086a290300370300200120012903a00a37039007410121034100210920014190076a210a410021120c010b20012902ec092202a7210802402002422088a7221141d100490d00200141d8046a41186a220a200141a00a6a41186a290300370300200141d8046a41106a2212200141a00a6a41106a290300370300200141d8046a41086a220e200141a00a6a41086a290300370300200120012903a00a3703d8042000417f6a41d10070220920114f0d07200320094105746a220920012903d804370000200941186a200a290300370000200941106a2012290300370000200941086a200e290300370000200821090c030b200141e8096a41086a280200211220012802ec09210920014190076a41186a200141a00a6a41186a29030037030020014190076a41106a200141a00a6a41106a29030037030020014190076a41086a200141a00a6a41086a290300370300200120012903a00a37039007024020112008460d0020014190076a210a20082109201121120c020b20014190076a210a20092011470d010b200941016a22082009490d0a200941017422112008201120084b1b220841ffffff3f712008470d0a200841057422084100480d0a0240024020090d002008102d21030c010b200320094105742008103121030b2003450d09200841057621090b200320124105746a2208200a290000370000200841186a200a41186a290000370000200841106a200a41106a290000370000200841086a200a41086a290000370000201241016a21110b200141d8046a41186a4200370300200141d8046a41106a22124200370300200141d8046a41086a220a4200370300200142003703d80441dcbec600ad4280808080800384100122082900002102200a200841086a290000370300200120023703d8042008102f41f4bec600ad4280808080e0018410012208290000210220014180096a41086a220e200841086a29000037030020012002370380092008102f2012200129038009220237030020014190076a41086a200a29030037030020014190076a41106a200237030020014190076a41186a200e290300370300200120012903d804370390070240024020030d0020014190076aad428080808080048410050c010b200141203602dc04200120014190076a3602d80420032011200141d8046a1083012009450d002003102f0b0240200d0d0010b6040b0240200041809c3170450d00200141a00a6a21210c070b20014180096a41186a420037030020014180096a41106a220a420037030020014180096a41086a220342003703002001420037038009419298ca00ad4280808080900184100122092900002102200141a8046a41086a2208200941086a290000370300200120023703a8042009102f20032008290300370300200120012903a8043703800941a898ca00ad4280808080d0028410012209290000210220014190086a41086a2208200941086a29000037030020012002370390082009102f200a2001290390082202370300200141a00a6a41086a2003290300370300200141a00a6a41106a2002370300200141a00a6a41186a200829030037030020012001290380093703a00a02400240200141a00a6a10f702220341ff01714102460d00200141a00a6aad4280808080800484100520034101710d010b200141d8046a200010a40220012d00d8044104460d0520014190076a200010a7020c060b200141d8046a200010a70220012d00d8044104460d0420014190076a200010a4020c050b200a2003104b000b41014100104b000b20094100104a000b419cc3ca0020092011103b000b200141043a0090070b200141a00a6a21210b20014180096a41186a2217420037030020014180096a41106a2222420037030020014180096a41086a220f42003703002001420037038009419298ca00ad42808080809001842202100122092900002104200141a8046a41086a2203200941086a290000370300200120043703a8042009102f200f2003290300370300200120012903a80437038009419b98ca00ad4280808080d001841001220a290000210420014190086a41086a2209200a41086a2900003703002001200437039008200a102f20222001290390082204370300200141a00a6a41086a2208200f290300370300200141a00a6a41106a22112004370300200141a00a6a41186a2212200929030037030020012001290380093703a00a200141a0036a2021412010950120012802a403210d20012802a003210e2017420037030020224200370300200f4200370300200142003703800920021001220a29000021022003200a41086a290000370300200120023703a804200a102f200f2003290300370300200120012903a80437038009418398ca00ad4280808080f001841001220329000021022009200341086a29000037030020012002370390082003102f202220012903900822023703002008200f290300370300201120023703002012200929030037030020012001290380093703a00a20014198036a2021412010950141002123024002400240200d4100200e1b2203200128029c0341002001280298031b220a4f0d00200141d8046a410472210920014181056a21120340200141d8046a200310b802024020012d00800522114103460d0020014190076a41086a200941086a290200220237030020014190076a41106a200941106a290200220437030020014190076a41186a200941186a290200220537030020014190076a41206a200941206a280200220836020020014190086a41026a220d201241026a2d00003a000020012009290200220637039007200120122f00003b01900820012802d804210e200141d8046a41086a22102002370300200141d8046a41106a22142004370300200141d8046a41186a22132005370300200141d8046a41206a22152008360200200120063703d804200141c8086a41026a2216200d2d00003a0000200120012f0190083b01c808410321080240200e2000470d0020014180096a41206a20152802003602002017201329030037030020222014290300370300200f2010290300370300200141a8046a41026a20162d00003a0000200120012903d80437038009200120012f01c8083b01a80420032118201121080b20084103470d030b200a200341016a2203470d000b0b41042124410021090c010b200141a00a6a41206a20014180096a41206a2802002209360200200141a00a6a41186a20014180096a41186a2903002202370300200141a00a6a41106a20014180096a41106a2903002204370300200141a00a6a41086a20014180096a41086a2903002205370300200141e0036a41026a2211200141a8046a41026a2d00003a0000200141e8096a41086a22122005370300200141e8096a41106a220d2004370300200141e8096a41186a220e2002370300200141e8096a41206a220f2009360200200120012903800922023703a00a200120012f01a8043b01e003200120023703e809200141e00a6a41026a221020112d00003a0000200120012f01e0033b01e00a4130102d2224450d01410121092024200036020420242018360200202420012903e809370208202420083a002c202420012f01e00a3b002d202441106a2012290300370200202441186a200d290300370200202441206a200e290300370200202441286a200f2802003602002024412f6a20102d00003a000041012123200341016a2203200a4f0d00200141d8046a410472210920014181056a211202400340200141d8046a200310b802024020012d00800522114103460d0020014190076a41086a200941086a290200220237030020014190076a41106a200941106a290200220437030020014190076a41186a200941186a290200220537030020014190076a41206a200941206a280200220836020020014190086a41026a220d201241026a2d00003a000020012009290200220637039007200120122f00003b01900820012802d804210e200141d8046a41086a220f2002370300200141d8046a41106a22102004370300200141d8046a41186a22142005370300200141d8046a41206a22132008360200200120063703d804200141c8086a41026a2215200d2d00003a0000200120012f0190083b01c808410321080240200e2000470d0020014180096a41206a201328020036020020014180096a41186a201429030037030020014180096a41106a201029030037030020014180096a41086a200f290300370300200141a8046a41026a20152d00003a0000200120012903d80437038009200120012f01c8083b01a80420032116201121080b20084103470d020b200a200341016a2203470d000b41012109410121230c010b200141a00a6a41206a222520014180096a41206a22182802002209360200200141a00a6a41186a222620014180096a41186a22192903002202370300200141a00a6a41106a222720014180096a41106a221a2903002204370300200141a00a6a41086a222820014180096a41086a22292903002205370300200141e0036a41026a222a200141a8046a41026a222b2d00003a0000200141e8096a41086a222c2005370300200141e8096a41106a222d2004370300200141e8096a41186a222e2002370300200141e8096a41206a222f2009360200200120012903800922023703a00a200120012f01a8043b01e003200120023703e809200141e00a6a41026a2230202a2d00003a0000200120012f01e0033b01e00a200341016a2103200141d8046a410472211120014181056a210d41012109410121230340200141d8046a41086a2210202c290300370300200141d8046a41106a2214202d290300370300200141d8046a41186a2213202e290300370300200141d8046a41206a2215202f28020036020020014190076a41026a220e20302d00003a0000200120012903e8093703d804200120012f01e00a3b019007024020232009470d00200941016a22122009490d042009410174220f2012200f20124b1bad42307e2202422088a70d042002a722124100480d040240024020090d002012102d21240c010b2024200941306c2012103121240b2024450d03201241306e21230b2024200941306c6a22122000360204201220163602002015280200210f20132903002102201429030021042010290300210520012903d80421062012412c6a20083a0000201241086a2006370200201241106a2005370200201241186a2004370200201241206a2002370200201241286a200f3602002012412d6a20012f0190073b00002012412f6a200e2d00003a0000200941016a21092003200a4f0d0102400340200141d8046a200310b802024020012d00800522124103460d0020014190076a41086a201141086a290200220237030020014190076a41106a201141106a290200220437030020014190076a41186a201141186a290200220537030020014190076a41206a201141206a280200220836020020014190086a41026a220e200d41026a2d00003a0000200120112902002206370390072001200d2f00003b01900820012802d804210f20102002370300201420043703002013200537030020152008360200200120063703d804200141c8086a41026a2217200e2d00003a0000200120012f0190083b01c808410321080240200f2000470d002018201528020036020020192013290300370300201a201429030037030020292010290300370300202b20172d00003a0000200120012903d80437038009200120012f01c8083b01a80420032116201221080b20084103470d020b200a200341016a2203470d000c030b0b2025201828020022123602002026201929030022023703002027201a2903002204370300202820292903002205370300202a202b2d00003a0000202c2005370300202d2004370300202e2002370300202f2012360200200120012903800922023703a00a200120012f01a8043b01e003200120023703e8092030202a2d00003a0000200120012f01e0033b01e00a200341016a21030c000b0b2009450d022024200941306c6a2131200141d8046aad4280808080800484213220014180096aad4280808080c000842133200141d8046a4104722103200141a00a6a41106a212c200141d8046a41186a21112024212a0340202a41086a2802002126202a28020021082011202a41246a290200370300200141d8046a41106a2213202a411c6a290200370300200141d8046a41086a2212202a41146a2902003703002001202a410c6a2902003703d804202a412c6a2d000022164103460d03200141c8086a41186a20112903002202370300200141c8086a41106a20132903002204370300200141c8086a41086a20122903002205370300200120012903d80422063703c808200141e8096a41186a22282002370300200141e8096a41106a22342004370300200141e8096a41086a22352005370300200120063703e80920014190076a200810a902200128029007210f0240024020012802980722090d00420021074200210b4200210c4200211b4200211c4200211e0c010b2009410574210d4200211c200f21094200211e4200210c4200211b420021074200210b0340200141d8046a2009108d02201129030021052012290300210220012903e804210620012903d804210420032009290000370000200341086a200941086a290000370000200341106a200941106a290000370000200341186a200941186a290000370000200120083602d804427f200220057c200420067c2205200454220aad7c2204200a200420025420042002511b220a1b2104427f2005200a1b210220014190036a200141d8046a10ab0220012d009003410171210a0240024020012d009103220e450d00200141f0026a20044200200ead2205420010ed0620014180036a200242002005420010ed06200141e0026a420042002002420010ed06427f20014180036a41086a290300220520012903f00220012903e0027c7c220620012903f80220012903e80284420052200620055472220e1b2105427f200129038003200e1b21060c010b200141d0026a20022004420a420010ee0620012903d00222062102200141d0026a41086a290300220521040b200941206a210942002005200a1b201b7c42002006200a1b221b200c7c220c201b54ad7c211b20054200200a1b200b7c20064200200a1b220520077c2207200554ad7c210b2004201e7c2002201c7c221c200254ad7c211e200d41606a220d0d000b0b0240200128029407450d00200f102f0b20014190076a200810a90220012802900721150240024020012802980722090d004200210242002106420021044200211f420021054200211d0c010b2009410574210d42002105201521094200211d420021044200211f4200210242002106034020032009290000370000200341086a200941086a220a290000370000200341106a200941106a220e290000370000200341186a200941186a220f290000370000200120083602d804200141c8026a200141d8046a10ab0220012d00c802211020012d00c90221142011200f2900003703002013200e2900003703002012200a290000370300200120092900003703d804200141a8026a2008200141d8046a2014411010ac02200141a8026a41186a290300201d7c20012903b802221d20057c2205201d54ad7c211d4200200141a8026a41086a29030022202010410171220a1b201f7c420020012903a8022236200a1b221f20047c2204201f54ad7c211f20204200200a1b20067c20364200200a1b220620027c2202200654ad7c2106200941206a2109200d41606a220d0d000b0b0240200128029407450d002015102f0b200141a00a6a41186a222f4200370300202c4200370300200141a00a6a41086a222d4200370300200142003703a00a41e7a2ca00ad4280808080800184100122092900002120202d200941086a290000370300200120203703a00a2009102f41ecb5c600ad4280808080d00184100122092900002120200141a8046a41086a222e200941086a290000370300200120203703a8042009102f202c20012903a804370300202c41086a2227202e29030037030020014190086a41086a2210202d29030037030020014190086a41106a2214202c29030037030020014190086a41186a2215202f290300370300200120012903a00a3703900820014190026a20014190086a4120109c0120014190026a41106a2903002136200128029002210a2001290398022137201f201b7c21382004200c7c2220200454ad21392006200b7c2106200220077c221f200254ad21074100210902402005201c7c220b420288201d201e7c200b200554ad7c220c423e86842202200c420288220484500d002002200b852004200c8584500d0041002109034020014180026a200b200c200941046a41fe007110ec06200941026a2109200129038002220220014180026a41086a290300220484500d012002200b852004200c85844200520d000b0b202a41306a212a20364200200a1b211b20374200200a1b211c203820397c211d200620077c211e42002106420021040340200141e0016a20044201862006423f888422044200200642018622064201842202420010ed06200141f0016a200242002002420010ed060240200420012903e801220584200584420052200141f0016a41086a290300220520012903e001220720077c7c2207200554720d0020012903f0012105200141d0016a200b200c200941ff007110ec0620042004200520012903d001562007200141d0016a41086a29030022055620072005511b220a1b210420062002200a1b21060b02402009450d0041002009417e6a220a200a20094b1b21090c010b0b410021090240201c420288201b423e86842202201b420288220584500d002002201c852005201b8584500d00410021090340200141c0016a201c201b200941046a41fe007110ec06200941026a210920012903c0012202200141c0016a41086a290300220584500d012002201c852005201b85844200520d000b0b42002105420021020340200141a0016a20024201862005423f888422024200200542018622054201842207420010ed06200141b0016a200742002007420010ed060240200220012903a801220b84200b84420052200141b0016a41086a290300220b20012903a001220c200c7c7c220c200b54720d0020012903b001210b20014190016a201c201b200941ff007110ec0620022002200b20012903900156200c20014190016a41086a290300220b56200c200b511b220a1b210220052007200a1b21050b02402009450d0041002009417e6a220a200a20094b1b21090c010b0b02400240024002400240200620048450450d004100210f0c010b02400240024020160e03010200010b201f202056201e201d56201e201d511b210f0c020b0340200141c0006a2020201d2006200410ee062005220b2002220c844200510d04200141c0006a41086a290300210220012903402105200141306a201f201e200b200c10ee064101210f20052001290330221b542002200141306a41086a290300220754200220075122091b0d020240201b200554200720025420091b450d004100210f0c030b200141206a200520022006200410ed06200141106a201b2007200b200c10ed060240201f200129031022027d2207201e200141106a41086a2903007d201f200254ad7d220284500d00201d200141206a41086a2903007d211b202020012903202205542109202020057d21052006211f2004211e2007210620022104200b2120200c211d2005201b2009ad7d220284500d030c010b0b4100210f0c010b0340200421072006210b20052002844200510d02200141f0006a201f201e200b200710ee0620014180016a2020201d2005200210ee064101210f200129038001220c2001290370221b5420014180016a41086a2903002204200141f0006a41086a290300220654200420065122091b0d010240201b200c54200620045420091b450d004100210f0c020b200141e0006a200c20042005200210ed06200141d0006a201b2006200b200710ed060240201f200129035022047d220c201e200141d0006a41086a2903007d201f200454ad7d22048450450d004100210f0c020b201d200141e0006a41086a2903007d211b202020012903602206542109202020067d21062005211f2002211e200c210520042102200b21202007211d2006201b2009ad7d2204844200520d000b0b200141d8046a200810a90220012802d804213020012802dc04212520012802e0042209450d022030200941057422196a212b203021090240034020014180096a41186a220a200941186a221629000037030020014180096a41106a220d200941106a221729000037030020014180096a41086a220e200941086a2218290000370300200120092900003703800920092900002102200341186a221a201629000037000020032002370000200341086a22162018290000370000200341106a22182017290000370000200120083602d804200141086a200141d8046a10ab022010200e2903003703002014200d2903003703002015200a2903003703002001200129038009370390080240200f20012d000841017145734101470d0020012d00092129200941206a21090c020b200941206a2109201941606a22190d000c040b0b034020014190076a41186a2015290300220237030020014190076a41106a2014290300220437030020014190076a41086a201029030022053703002001200129039008220637039007201120023703002013200437030020122005370300200120063703d804419298ca00ad4280808080900184100122172900002102202e201741086a290000370300200120023703a8042017102f41f9b5c600ad4280808080d000841001221729000021022010201741086a29000037030020012002370390082017102f4120102d2217450d05201720012903d804370000201741186a2011290300370000201741106a2013290300370000201741086a20122903003700002017ad4280808080800484100322192900002102201941086a2900002104201941106a2900002105200a201941186a290000370300200d2005370300200e200437030020012002370380092019102f2017102f41c000102d2217450d05201720012903a80437000020172001290390083700102017200129038009370020201741086a202e290300370000201741186a2010290300370000201741286a200e290300370000201741306a200d290300370000201741386a200a2903003700002001202941187441187541027441d897ca006a2802004180de346c20006a360280092017ad4280808080800884203310042017102f200142e4cab5fbb6ccdcb0e3003703e003200141e0036a200141d8046a10d2022009202b460d0302400340200a200941186a2217290000370300200d200941106a2219290000370300200e200941086a22292900003703002001200929000037038009200120083602d804202929000021022019290000210420092900002105201a20172900003700002018200437000020162002370000200320053700002001200141d8046a10ab022010200e2903003703002014200d2903003703002015200a290300370300200120012903800937039008200f20012d000041017145730d01202b200941206a2209470d000c050b0b20012d00012129200941206a21090c000b0b4180b2c000411941a0b1c0001039000b4180b2c000411941a0b1c0001039000b02402025450d002030102f0b200810af0202400240200f0d00200120083602e404200141053a00e004200141063a00d80441c8e1ca004100200141d8046a108c010c010b200120083602e404200141043a00e004200141063a00d80441c8e1ca004100200141d8046a108c0102400240024002402026450d0020014190076a41186a2216202829030037030020014190076a41106a2217203429030037030020014190076a41086a22182035290300370300200120012903e80937039007202f4200370300202c4200370300202d4200370300200142003703a00a419298ca00ad42808080809001842204100122092900002102202d200941086a290000370300200120023703a00a2009102f418ca8c200ad4280808080d001842205100122092900002102202e200941086a290000370300200120023703a8042009102f202c20012903a8043703002027202e2903003703002010202d2903003703002014202c2903003703002015202f290300370300200120012903a00a37039008202620006a2114200141d8046a20014190086a10c902024020012802d804220f0d004104210f41002119420021020c030b20012902dc042202a721194100210902402002422088a7221541014b0d0020150e020302030b2015210a03402009200a410176220d20096a220e2014200f200e41286c6a280200491b2109200a200d6b220a41014b0d000c020b0b201120282903003703002013203429030037030020122035290300370300200120012903e8093703d80420014190076a200141d8046a200810b1020c030b02402014200f200941286c6a280200220a460d0020092014200a4b6a21090b20112016290300370300201320172903003703002012201829030037030020012001290390073703d804200920154d0d01419ae3c300411e41f8b4ca001039000b20112016290300370300201320172903003703002012201829030037030020012001290390073703d80441002115410021090b024020152019470d0020152002a7470d00201541016a220a2015490d042015410174220d200a200d200a4b1bad42287e2202422088a70d042002a7220a4100480d040240024020150d00200a102d210f0c010b200f201541286c200a1031210f0b200f450d03200a41286ead21020b200f200941286c6a220a41286a200a201520096b41286c10e9061a200a2014360200200a20012903d804370204200a410c6a2012290300370200200a41146a2013290300370200200a411c6a2011290300370200200a2008360224202f4200370300202c4200370300202d4200370300200142003703a00a2004100122092900002104200141e00a6a41086a220a200941086a290000370300200120043703e00a2009102f202141086a200a290300370000202120012903e00a37000020051001220929000021042010200941086a29000037030020012004370390082009102f202c200129039008370000202720102903003700002012202d2903003703002013202c2903003703002011202f290300370300200120012903a00a3703d8040240200f0d00203210050c010b2002a7210920014180096a200f201541016a1081012032200135028809422086200128028009220aad8410040240200128028409450d00200a102f0b2009450d00200f102f0b202a2031470d000c030b0b1036000b1038000b02402023450d002024102f0b200141a00a6a41186a4200370300200141a00a6a41106a220a4200370300200141a00a6a41086a22034200370300200142003703a00a419298ca00ad42808080809001841001220929000021022003200941086a290000370300200120023703a00a2009102f418ca8c200ad4280808080d00184100122092900002102200141a8046a41086a2208200941086a290000370300200120023703a8042009102f200a20012903a804220237030020014190086a41086a200329030037030020014190086a41106a200237030020014190086a41186a2008290300370300200120012903a00a37039008200141d8046a20014190086a10c90220012802d8042203410420031b210e0240024020012902dc04420020031b2206422088a7220f450d00200e200f41286c6a210841002109200141d8046a41186a2111200141d8046a41106a2112200141d8046a41086a210d200e210302400340024020032802002000460d0020090d020c030b200341246a280200210a200341046a29000021022003410c6a2900002104200341146a290000210520112003411c6a29000037030020122005370300200d2004370300200120023703d80420014190076a200141d8046a200a10b102200941016a21092008200341286a2203470d000b0b2009200f4b0d0120014180096a41186a2208420037030020014180096a41106a2211420037030020014180096a41086a220342003703002001420037038009419298ca00ad42808080809001841001220a2900002102200141a8046a41086a2212200a41086a290000370300200120023703a804200a102f20032012290300370300200120012903a80437038009418ca8c200ad4280808080d001841001220a290000210220014190086a41086a2212200a41086a2900003703002001200237039008200a102f2022200129039008370000202241086a2012290300370000200141a00a6a41086a2003290300370300200141a00a6a41106a2011290300370300200141a00a6a41186a200829030037030020012001290380093703a00a200141d8046a200e200941286c6a200f20096b1081012021ad428080808080048420013502e00442208620012802d8042203ad84100420012802dc04450d002003102f0b02402006a7450d00200e102f0b200010fa03200141f00a6a24000f0b2009200f104b000b41b8dac400411c41d4dac4001055000b41acd9c40020032009103b000bca1e05057f027e047f0c7e017f230041c00b6b22042400200441a8066a200141c80310e8061a200441a0036a200441a8066a10d10341012105024002400240024002400240024002400240024020042d00a0034101460d00200441206a200441a0036a41086a41800310e8061a024020032802002206450d00200341086a280200210720032802042108200441186a4180e5c300411010950141002105200441a8066a200428021c410020042802181b10d20320042802a8062101200420042802b0063602a403200420013602a00320062007200441a0036a109d02024020042802ac06450d002001102f0b2008450d002006102f0b200441f0096a200441206a41d0006a10f102200441a8066a200441206a41800310e8061a20042903f00921090240024020042903c806220a4202520d00200420093703a0030240200441a0036a200210d303220141ff017141024622020d002002450d080b4100210b20042802f8064113470d0a200441a0036a200441fc066a10a20320042d00a0034101460d01200441cc036a2802002107200441c8036a280200210c200441c4036a2802002108200441bc036a280200210d200441b8036a280200210e0240200441c0036a2802002201450d002001410c6c2102200e210103400240200141046a280200450d002001280200102f0b2001410c6a2101200241746a22020d000b0b0240200d450d00200e102f0b02402007450d002007410c6c21022008210103400240200141046a280200450d002001280200102f0b2001410c6a2101200241746a22020d000b0b200c450d0a2008102f0c0a0b200441900b6a41186a200441a8066a41186a290300370300200441900b6a41106a200441a8066a41106a290300370300200441900b6a41086a200441a8066a41086a290300370300200420042903a8063703900b200441e8066a290300210f200441e0066a2903002110200441f0066a280200210820042903d0062111200441a0036a41186a4200370300200441a0036a41106a220c4200370300200441a0036a41086a22014200370300200442003703a003418de6c300ad4280808080e000842212100122072900002113200441b00b6a41086a220e200741086a290000370300200420133703b00b2007102f2001200e290300370300200420042903b00b3703a003419ce6c300ad4280808080e00084100122072900002113200441a80a6a41086a220b200741086a290000370300200420133703a80a2007102f200c20042903a80a2213370300200441c80a6a41086a2001290300370300200441c80a6a41106a2013370300200441c80a6a41186a200b290300370300200420042903a0033703c80a200441106a200441c80a6a41201095010240200a4201520d0020114200510d030b201210012201290000210a200e200141086a2900003703002004200a3703b00b2001102f41f0e8c600ad4280808080f0008410012201290000210a200b200141086a2900003703002004200a3703a80a2001102f4120102d2201450d03200120042903900b370000200141186a200441900b6a41186a290300370000200141106a200441900b6a41106a290300370000200141086a200441900b6a41086a2903003700002001ad428080808080048410032207290000210a200741086a2900002112200741106a2900002113200441a0036a41186a220e200741186a290000370300200441a0036a41106a220b2013370300200441a0036a41086a220c20123703002004200a3703a0032007102f2001102f41c000102d2201450d03200120042903b00b370000200120042903a80a370010200120042903a003370020200141086a200441b00b6a41086a290300370000200141186a200441a80a6a41086a290300370000200141286a200c290300370000200141306a200b290300370000200141386a200e290300370000200441a0036a200110f6020240024020042903a0034201510d004200210a41002107420021124200211342002111420021144200211542002116420021174100210e0c010b200441b0036a2903002117200441c0036a2903002115200441b8036a2903002114200441a0036a41306a2903002111200441a0036a41286a2903002113200441e0036a2903002112200441a0036a41386a290300210a200441e8036a280200210720042903a803211620042802ec03210e0b2001102f024020072008470d00418de6c300ad4280808080e00084100122012900002118200441a80a6a41086a200141086a290000370300200420183703a80a2001102f41f0e8c600ad4280808080f00084100122012900002118200441a0036a41086a200141086a290000370300200420183703a0032001102f4120102d2201450d04200120042903900b370000200141186a200441900b6a41186a290300370000200141106a200441900b6a41106a290300370000200141086a200441900b6a41086a2903003700002001ad4280808080800484100322072900002118200741086a2900002119200741106a290000211a200441c80a6a41186a220b200741186a290000370300200441c80a6a41106a220c201a370300200441c80a6a41086a2019370300200420183703c80a2007102f2001102f41c000102d2201450d04200120042903a80a370000200141086a200441a80a6a41086a290300370000200120042903a003370010200141186a200441a0036a41086a290300370000200120042903c80a370020200141286a200441c80a6a41086a290300370000200141306a200c290300370000200141386a200b2903003700004104102d2207450d042007200841016a36000020074104410810312207450d042007200e3a000420074108411510312207450d04200720163700052007410d6a201737000020074115412a10312207450d04200720143700152007411d6a20153700002007412a41d40010312207450d042007200a370035200720133700252007413d6a20123700002007412d6a20113700002001ad42808080808008842007ad4280808080d0088410042007102f2001102f200420093703a0030240200441a0036a200210d303220141ff01714102470d00200420093703c80a200441a0036a2010200f200441900b6a200441c80a6a200210d403024020042d00a0034101460d00200441cc036a2802002107200441c8036a280200210b200441c4036a2802002108200441bc036a280200210c200441b8036a280200210e0240200441c0036a2802002201450d002001410c6c2102200e210103400240200141046a280200450d002001280200102f0b2001410c6a2101200241746a22020d000b0b0240200c450d00200e102f0b02402007450d002007410c6c21022008210103400240200141046a280200450d002001280200102f0b2001410c6a2101200241746a22020d000b0b200b450d072008102f0c070b20042d00a10322014102460d0620042f01a20321020c070b20014180feff077141087621020c060b41034102200720084b1b2102410021010c050b20042d00a10322014102460d0820042f01a20341087420017221010c050b200020042f00a1033b0001200041013a0000200041036a20042d00a3033a000020032802002106410021000c050b41d0caca00411941eccaca001039000b1036000b200441a0036a200441a8066a41d0006a10e201024020042d00a0034101460d00200441cc036a2802002107200441c8036a280200210b200441c4036a2802002108200441bc036a280200210c200441b8036a280200210e0240200441c0036a2802002201450d002001410c6c2102200e210103400240200141046a280200450d002001280200102f0b2001410c6a2101200241746a22020d000b0b0240200c450d00200e102f0b02402007450d002007410c6c21022008210103400240200141046a280200450d002001280200102f0b2001410c6a2101200241746a22020d000b0b200b450d042008102f0c040b20042d00a10322014102460d0320042f01a20321020b2002410874200141ff01717221010b200441f8066a108e01200420042900980a3703880a20042004419f0a6a28000036008f0a200041036a20014110763a0000200020013b0001200041013a000020054521000b20000d022006450d02200341046a280200450d022006102f0c020b200441f00a6a41186a200441900b6a41186a290300370300200441f00a6a41106a200441900b6a41106a290300370300200441f00a6a41086a200441900b6a41086a290300370300200420042903900b3703f00a4101210b0b200441a80a6a41186a2208200441f00a6a41186a2201290300370300200441a80a6a41106a220e200441f00a6a41106a2202290300370300200441a80a6a41086a220c200441f00a6a41086a2207290300370300200420042903f00a3703a80a200441a0036a200441f8066a41b00210e8061a200441900b6a41186a220d2008290300370300200441900b6a41106a221b200e290300370300200441900b6a41086a2208200c290300370300200420042903a80a3703900b4102210e0240200b450d002001200d2903003703002002201b29030037030020072008290300370300200420042903900b3703f00a4101210e0b200441d20a6a2007290300370100200441da0a6a2002290300370100200441e20a6a20012903003701002004200e3a00c90a200420042903f00a3701ca0a41002101200441003a00c80a200441900b6a200441a0036a200441c80a6a108b01200420042900910b3703a003200420082800003600a703024020042d00900b220741044622080d00200420042800a7033600cf0a200420042903a0033703c80a0b200420042800cf0a36009f0a200420042903c80a3703980a2004200428009f0a36008f0a200420042903980a3703880a200441f8096a41086a2202200428008f0a360000200420042903880a3700f909200420073a00f8092009210a024020080d00200441f8096a108c03200228020021074101210120042903f809210a0b200441bc066a2009370200200441a8066a41106a2007360200200441a8066a41086a200a370300200441c4066a20042902a003370200200441cc066a200441a0036a41086a280200360200200420013a00ac06200420042f00c80a3b00ad06200441003a00a8062004200441ca0a6a2d00003a00af0641c8e1ca004100200441a8066a108c01200441086a4180e5c30041101095012004200428020c41016a410120042802081b3602a8064180e5c300ad4280808080800284200441a8066aad4280808080c0008410042000410c6a2002280200360200200041046a20042903f809370200200041003a00002006450d002005450d00200341046a280200450d002006102f0b200441c00b6a24000be22007017f027e027f017e057f037e037f23004190116b2202240042022103024002400240024002400240024002400240200129036822044202520d00200241186a20014198016a41b00210e8061a0c010b20024196036a200141246a41c20010e8061a200241d8036a41086a220520014188016a290300370300200241d8036a41106a220620014190016a290300370300200220014180016a2903003703d803200141f8006a29030021032001290370210720024190046a41206a200141206a28020036020020024190046a41186a200141186a29020037030020024190046a41106a200141106a29020037030020024190046a41086a200141086a2902003703002002200129020037039004200241c80a6a20024190046a10bb0120024190086a41086a2208200241d10a6a29000037030020024190086a41106a2209200241d90a6a29000037030020024190086a41186a220a200241e10a6a290000370300200220022900c90a3703900820022d00c80a4101460d02200241f0036a41186a200a290300370300200241f0036a41106a2009290300370300200241f0036a41086a200829030037030020022002290390083703f003200241800d6a20014198016a41b00210e8061a200241b00f6a41106a2006290300370300200241b00f6a41086a2005290300370300200220022903d8033703b00f41002105200241e8106a410010fa02200241a8106a41086a200241f3106a290000370300200241a8106a41106a200241fb106a290000370300200241bd106a200241e8106a41186a2201290000370000200220022900eb103703a81020022f01e810210b20022d00ea10210c20014200370300200241e8106a41106a22094200370300200241e8106a41086a22014200370300200242003703e810418de6c300ad4280808080e0008410012206290000210d200241c8106a41086a2208200641086a2900003703002002200d3703c8102006102f20012008290300370300200220022903c8103703e810419ce6c300ad4280808080e0008410012206290000210d20024188106a41086a220a200641086a2900003703002002200d370388102006102f2009200229038810220d37030020082001290300370300200241c8106a41106a200d370300200241c8106a41186a200a290300370300200220022903e8103703c810200241106a200241c8106a4120109501024020044201520d0020074200510d052002280214410020022802101b2101417f21052001ad220d20032003200d541b220d200d20037d2007827d220d42ffffffff0f560d00200da721050b418de6c300ad4280808080e0008410012201290000210d200241c8106a41086a2206200141086a2900003703002002200d3703c8102001102f4193e6c300ad428080808090018410012201290000210d20024188106a41086a2208200141086a2900003703002002200d370388102001102f2002200536028c112002418c116aad4280808080c0008410032201290000210d200141086a290000210e200141106a290000210f200241e8106a41186a2209200141186a290000370300200241e8106a41106a220a200f370300200241e8106a41086a2210200e3703002002200d3703e8102001102f41c000102d2201450d05200120022903c8103700002001200229038810370010200120022903e810370020200141086a2006290300370000200141186a2008290300370000200141286a2010290300370000200141306a200a290300370000200141386a2009290300370000200241086a200141c00041c8e1ca004100410010b501200228020821082001102f41012101024020084101470d00200241e8106a200510fa0220024188106a41086a200241f3106a29000037030020024188106a41106a200241fb106a29000037030020024188106a41156a20024180116a290000370000200241c8106a41086a200241a8106a41086a290300370300200241c8106a41106a200241a8106a41106a290300370300200241c8106a41156a200241a8106a41156a290000370000200220022900eb1037038810200220022903a8103703c81020022f01e81020022d00ea10411074722106410021010b200241e80f6a41086a2205200241c8106a41086a290300370300200241e80f6a41106a2208200241c8106a41106a290300370300200241e80f6a41156a2209200241c8106a41156a290000370000200241c80f6a41086a220a20024188106a41086a290300370300200241c80f6a41106a221020024188106a41106a290300370300200241c80f6a41156a221120024188106a41156a290000370000200220022903c8103703e80f20022002290388103703c80f20010d01200241d8076a41156a22012009290000370000200241d8076a41106a22092008290300370300200241d8076a41086a22082005290300370300200241b8076a41086a2205200a290300370300200241b8076a41106a220a2010290300370300200241b8076a41156a22102011290000370000200220022903e80f3703d807200220022903c80f3703b807200241f8076a41106a2211200241b00f6a41106a290300370300200241f8076a41086a2212200241b00f6a41086a290300370300200220022903b00f3703f807200241c80a6a41046a200241800d6a41b00210e8061a20024190086a200241c80a6a41b40210e8061a20024190046a20024190086a41046a41b00210e8061a200241f6066a200b200c41107472220b4110763a0000200241f4066a200b3b0100200241d0066a2003370300200241c8066a2007370300200241d8066a220b20022903f807370300200241e0066a2012290300370300200241e8066a220c2011290300370300200241f7066a20022903d807370000200241ff066a200829030037000020024187076a20092903003700002002418c076a2001290000370000200220043703c006200241e7013602f00620024196076a20064110763a000020024194076a20063b010020024197076a20022903b8073700002002419f076a2005290300370000200241a7076a200a290300370000200241ac076a20102900003700004104102d2201450d05200242043702cc0a200220013602c80a20024190046a200241c80a6a1091010240024020022903c0064201520d0020022903d00620022903c8062203420c882204420120044201561b8021040240024020022802cc0a220520022802d00a22016b4102490d0020022802c80a21050c010b200141026a22062001490d09200541017422012006200120064b1b22014100480d090240024020050d002001102d21050c010b20022802c80a20052001103121050b2005450d08200220013602cc0a200220053602c80a20022802d00a21010b2002200141026a3602d00a200520016a2004a741047420037aa7417f6a22014101200141014b1b2201410f2001410f491b723b00000c010b0240024020022802cc0a20022802d00a2201460d0020022802c80a21050c010b200141016a22052001490d08200141017422062005200620054b1b22064100480d080240024020010d002006102d21050c010b20022802c80a20012006103121050b2005450d07200220063602cc0a200220053602c80a20022802d00a21010b2002200141016a3602d00a200520016a41003a00000b200c200241c80a6a1095022002200b3602900820024190086a200241c80a6a10c20220022802f00621060240024020022802cc0a220520022802d00a22016b4104490d0020022802c80a21050c010b200141046a22082001490d07200541017422012008200120084b1b22014100480d070240024020050d002001102d21050c010b20022802c80a20052001103121050b2005450d06200220013602cc0a200220053602c80a20022802d00a21010b2002200141046a3602d00a200520016a20063600004120102d2201450d052001200241f4066a290200370000200141186a2002418c076a290200370000200141106a20024184076a290200370000200141086a200241fc066a2902003700000240024020022802cc0a220620022802d00a22056b4120490d0020022802c80a21060c010b200541206a22082005490d07200641017422052008200520084b1b22054100480d070240024020060d002005102d21060c010b20022802c80a20062005103121060b2006450d06200220053602cc0a200220063602c80a20022802d00a21050b200620056a220641086a200141086a290000370000200641106a200141106a290000370000200641186a200141186a2900003700002002200541206a3602d00a200620012900003700002001102f4120102d2201450d05200120024194076a290200370000200141186a200241ac076a290200370000200141106a200241a4076a290200370000200141086a2002419c076a2902003700000240024020022802cc0a220620022802d00a22056b4120490d0020022802c80a21060c010b200541206a22082005490d07200641017422052008200520084b1b22054100480d070240024020060d002005102d21060c010b20022802c80a20062005103121060b2006450d06200220053602cc0a200220063602c80a20022802d00a21050b200620056a220641086a200141086a290000370000200641106a200141106a290000370000200641186a200141186a2900003700002002200541206a3602d00a200620012900003700002001102f20022802cc0a210620022802c80a21010240024020022802d00a22054180024b0d0020024196036a20012005200241f0036a10e90321050c010b2005ad4220862001ad84100322052900002103200541086a2900002104200541106a2900002107200241c80a6a41186a200541186a290000370300200241c80a6a41106a2007370300200241c80a6a41086a2004370300200220033703c80a2005102f20024196036a200241c80a6a4120200241f0036a10e90321050b02402006450d002001102f0b2005450d03200241f0026a41086a200241f0036a41086a290300370300200241f0026a41106a200241f0036a41106a290300370300200241f0026a41186a200241f0036a41186a290300370300200241c8026a41086a200241d0066a290300370300200241c8026a41106a200241d8066a290300370300200241c8026a41186a200241e0066a290300370300200241e8026a200241e8066a290300370300200220022903f0033703f0022002200241c8066a2903003703c80220022903c0062103200241186a20024190046a41b00210e8061a0b200041086a20022903f002370300200041286a2003370300200041306a20022903c802370300200041206a200241f0026a41186a290300370300200041186a200241f0026a41106a290300370300200041106a200241f0026a41086a290300370300200041386a200241c8026a41086a290300370300200041c0006a200241c8026a41106a290300370300200041c8006a200241c8026a41186a290300370300200041d0006a200241c8026a41206a290300370300200041d8006a200241186a41b00210e8061a200041003a000020024190116a24000f0b200241800d6a108e01200041036a41003a0000200041800a3b0001200041013a00000c050b200041013b0001200041013a0000200041036a41003a000020014198016a108e010c040b20004180083b0001200041013a0000200041036a41003a000020024190046a108e010c030b41d0caca00411941eccaca001039000b1036000b1038000b20024190116a24000bd10403027f017e047f230041d0006b22022400418de6c300ad4280808080e00084100122032900002104200241086a200341086a290000370300200220043703002003102f41a881c400ad4280808080d00184100122032900002104200241106a41086a200341086a290000370300200220043703102003102f2002200136022c20022002412c6aad4280808080c00084100622032900003703302003102f200241c4006a200241306a360200200241003a00482002200241306a41086a36023c20022002412c6a3602402002200241306a360238200241206a200241386a106c0240024002400240024002402002280228220541206a2201417f4c0d0020022802202106024002402001450d002001102d2203450d062001410f4d0d01200121070c050b411021074110102d21030c030b200141017422084110200841104b1b220741004e0d010c050b103d000b200320012007103121030b2003450d010b20032002290300370000200341086a200241086a2903003700000240024020074170714110460d00200721080c010b200741017422084120200841204b1b22084100480d0220032007200810312203450d010b20032002290310370010200341186a200241106a41086a29030037000002400240200841606a2005490d00200821070c010b2005415f4b0d02200841017422072001200720014b1b22074100480d0220032008200710312203450d010b200341206a2006200510e8061a20002001360208200020073602042000200336020002402002280224450d002006102f0b200241d0006a24000f0b1036000b1038000bdf0808017f017e027f017e017f017e067f017e230041e0006b2202240020002902002103200241306a41186a22044200370300200241306a41106a22054200370300200241306a41086a2200420037030020024200370330418de6c300ad4280808080e0008422061001220729000021082000200741086a290000370300200220083703302007102f41f880c400ad4280808080800284100122072900002108200241d0006a41086a2209200741086a290000370300200220083703502007102f200520022903502208370300200241106a41086a220a2000290300370300200241106a41106a220b2008370300200241106a41186a220c200929030037030020022002290330370310200241086a200241106a41201095014100210741800c210d0240417f200228020c410020022802081b220e20016a22012001200e491b220e42808080c0f588fe064280808080f28ba80920034280808080f01f835022011b22082008428094ebdc038022084280ec94a37c7e7c4280cab5ee01562008a76a4b0d002004420037030020054200370300200042003703002002420037033020061001220729000021082000200741086a290000370300200220083703302007102f41d480c400ad4280808080b0028422061001220729000021082009200741086a290000370300200220083703502007102f200520022903502208370300200a2000290300370300200b2008370300200c2009290300370300200220022903303703102002200241106a412010950141002107417f2002280204410020022802001b22054180afd0e502418094ebdc0320011b22002003a7220920002009491b6a220920092005491b220920004b0d00200241306a41186a22014200370300200241306a41106a22074200370300200241306a41086a2205420037030020024200370330418de6c300ad4280808080e0008422031001220d2900002108200241d0006a41086a2200200d41086a29000037030020022008370350200d102f200520002903003703002002200229035037033041f880c400ad42808080808002841001220d29000021082000200d41086a29000037030020022008370350200d102f200720022903502208370300200241106a41086a22042005290300370300200241106a41106a220a2008370300200241106a41186a220b2000290300370300200220022903303703102002200e360230200241106aad42808080808004842208200241306aad4280808080c00084220f10042001420037030020074200370300200542003703002002420037033020031001220d29000021032000200d41086a29000037030020022003370350200d102f200520002903003703002002200229035037033020061001220d29000021032000200d41086a29000037030020022003370350200d102f20072002290350220337030020042005290300370300200a2003370300200b200029030037030020022002290330370310200220093602302008200f1004410221074100210d0b200241e0006a2400200d2007720b851006017f047e027f017e037f017e230041f0026b2206240020064190016a200520042902002207a72007422888a72001200210f00402400240200629039001220720064190016a41086a290300220884500d00200641003a00ab01200620083703e802200620073703e002200620033602a4012006410141112001200284501b3a00aa01200620033602ac012006200641ac016a3602f0012006200641aa016a3602ec012006200641a4016a3602e8012006200641ab016a3602e4012006200641e0026a3602e001200641b0016a2003200641e0016a10a504024020062802b0014101470d00200041036a41003a000020004180023b0001200041013a00000c020b200641d8016a2903002101200641d0016a29030021020240200641b0016a41086a2903004201520d00200641b0016a41106a290300210920062802ac01210320064198026a200641b0016a41186a29030037030020064190026a2009370300200641e0016a41086a41003a0000200641e9016a2003290000370000200641f1016a200341086a290000370000200641f9016a200341106a29000037000020064181026a200341186a290000370000200641033a00e00141c8e1ca004100200641e0016a108c010b200641f8006a20022001109b01200641f8006a41106a29030021012006290380012102024020062903782209a7450d00200641c0006a200242004204420010ed06200641306a420042002002420010ed06200641d0006a2006290340200641c0006a41086a2903002209200142028620062903307c7c220a4205420010ee0642b3e6cc99b3e6cc99332006290350200142ffffffffffffffff3f83200152200629033842005272200a2009547222031b220920022002200956200142b3e6cc99b3e6cc9933200641d0006a41086a29030020031b22095620012009511b22031b220a2009200120031b220910be01200641e0006a2002200a7d200120097d2002200a54ad7d109b01200641e0006a41106a290300210220062903682101024020062903602209a7450d00200641e0016a10fb02200641e0016a2001200210b5020c020b2009500d01200641e0016a41186a220b4200370300200641e0016a41106a22044200370300200641e0016a41086a22054200370300200642003703e00141e7a2ca00ad428080808080018422091001220c290000210a200641e0026a41086a2203200c41086a2900003703002006200a3703e002200c102f20052003290300370300200620062903e0023703e00141ecb5c600ad4280808080d00184220a1001220c290000210d2003200c41086a2900003703002006200d3703e002200c102f200420062903e002220d370300200641b0016a41086a220e2005290300370300200641b0016a41106a220f200d370300200641b0016a41186a22102003290300370300200620062903e0013703b001200641186a200641b0016a4120109c01200641186a41106a290300210d200629032021112006280218210c200b42003703002004420037030020054200370300200642003703e00120091001220b29000021092003200b41086a290000370300200620093703e002200b102f20052003290300370300200620062903e0023703e001200a1001220b29000021092003200b41086a290000370300200620093703e002200b102f200420062903e0022209370300200e2005290300370300200f200937030020102003290300370300200620062903e0013703b00120064200200d4200200c1b220920027d20114200200c1b2202200154ad7d220a200220017d2201200256200a200956200a2009511b22031b3703e80120064200200120031b3703e001200641b0016aad4280808080800484200641e0016aad428080808080028410040c010b2009500d00200641e0016a41186a220b4200370300200641e0016a41106a22044200370300200641e0016a41086a22054200370300200642003703e00141e7a2ca00ad428080808080018422091001220c290000210a200641e0026a41086a2203200c41086a2900003703002006200a3703e002200c102f20052003290300370300200620062903e0023703e00141ecb5c600ad4280808080d00184220a1001220c290000210d2003200c41086a2900003703002006200d3703e002200c102f200420062903e002220d370300200641b0016a41086a220e2005290300370300200641b0016a41106a220f200d370300200641b0016a41186a22102003290300370300200620062903e0013703b0012006200641b0016a4120109c01200641106a290300210d200629030821112006280200210c200b42003703002004420037030020054200370300200642003703e00120091001220b29000021092003200b41086a290000370300200620093703e002200b102f20052003290300370300200620062903e0023703e001200a1001220b29000021092003200b41086a290000370300200620093703e002200b102f200420062903e0022209370300200e2005290300370300200f200937030020102003290300370300200620062903e0013703b00120064200200d4200200c1b220920017d20114200200c1b2201200254ad7d220a200120027d2202200156200a200956200a2009511b22031b3703e80120064200200220031b3703e001200641b0016aad4280808080800484200641e0016aad428080808080028410040b200041003a0000200041306a41013a0000200041286a4200370300200041206a4280808080c000370300200041186a4204370300200041106a427f370300200041086a2007427f2008501b3703000b200641f0026a24000bec0101027f20014180feff07714108762102024002402001410171450d00411f210341b6cfca00210102400240200241ff01710e03000103000b41c100210341f5ceca0021010c020b41c100210341b4ceca0021010c010b411f21034195ceca0021010240024002400240024002400240200241ff01710e080006010203040507000b4120210341f5cdca0021010c060b412721034195cdca0021010c050b4117210341feccca0021010c040b41dfccca0021010c030b4126210341b9ccca0021010c020b412b2103418eccca0021010c010b4139210341bccdca0021010b20002003360204200020013602000b160020002001280208360204200020012802003602000b13002000410136020420004190d2c3003602000b3400200041d39bca0036020420004100360200200041146a4104360200200041106a41c0d3c300360200200041086a42083702000b130020004101360204200041a4dcc3003602000b130020004102360204200041ecddc3003602000b2d01017f02404104102d22020d001036000b20004284808080c00037020420002002360200200241e8073600000b2d01017f02404104102d22020d001036000b20004284808080c00037020420002002360200200241e5003600000b88090b107f017e017f017e017f017e017f017e017f017e017f230041306b2202240002400240024020014108490d00200141017641feffffff07712203417f6a220420014f0d022001410d74200173220541117620057322054105742005732206417f2001417f6a677622077122054100200120052001491b6b220520014f0d01200241286a22082000200441306c6a220441286a2209290300370300200241206a220a200441206a220b290300370300200241186a220c200441186a220d290300370300200241106a220e200441106a220f290300370300200241086a2210200441086a2211290300370300200220042903003703002000200541306c6a22052903002112200541086a22132903002114200541106a22152903002116200541186a22172903002118200541206a2219290300211a2009200541286a221b290300370300200b201a370300200d2018370300200f20163703002011201437030020042012370300201b20082903003703002019200a2903003703002017200c2903003703002015200e2903003703002013201029030037030020052002290300370300024020032001490d00200321040c030b2006410d7420067322044111762004732204410574200473220620077122044100200120042001491b6b220520014f0d01200241286a22082000200341306c6a220441286a2209290300370300200241206a220a200441206a220b290300370300200241186a220c200441186a220d290300370300200241106a220e200441106a220f290300370300200241086a2210200441086a2211290300370300200220042903003703002000200541306c6a22052903002112200541086a22132903002114200541106a22152903002116200541186a22172903002118200541206a2219290300211a2009200541286a221b290300370300200b201a370300200d2018370300200f20163703002011201437030020042012370300201b20082903003703002019200a2903003703002017200c2903003703002015200e29030037030020132010290300370300200520022903003703002003410172220420014f0d022006410d742006732205411176200573220541057420057320077122054100200120052001491b6b220520014f0d01200241286a22032000200441306c6a220141286a2204290300370300200241206a2206200141206a2207290300370300200241186a2208200141186a2209290300370300200241106a220a200141106a220b290300370300200241086a220c200141086a220d290300370300200220012903003703002000200541306c6a22002903002112200041086a22052903002114200041106a220e2903002116200041186a220f2903002118200041206a2210290300211a2004200041286a22112903003703002007201a37030020092018370300200b2016370300200d2014370300200120123703002011200329030037030020102006290300370300200f2008290300370300200e200a2903003703002005200c290300370300200020022903003703000b200241306a24000f0b4198bbca0020052001103b000b4188bbca0020042001103b000bf20907077f027e0b7f017e017f027e017f230041306b22022400024020014101762203450d0003402003417f6a2203210402400240024003402004410174220541017221060240200541026a220520014f0d00200620014f0d02200520062000200641306c6a22072903002000200541306c6a220829030056200741086a2903002209200841086a290300220a562009200a511b1b21060b200620014f0d03200420014f0d022000200441306c6a22042903002000200641306c6a220529030056200441086a22072903002209200541086a2208290300220a562009200a511b450d03200241286a220b200441286a220c290300370300200241206a220d200441206a220e290300370300200241186a220f200441186a2210290300370300200241106a2211200441106a2212290300370300200241086a221320072903003703002002200429030037030020082903002109200541106a2214290300210a200541186a22152903002116200541206a2217290300211820052903002119200c200541286a221a290300370300200e2018370300201020163703002012200a3703002007200937030020042019370300201a200b2903003703002017200d2903003703002015200f290300370300201420112903003703002008201329030037030020052002290300370300200621040c000b0b41b0bcca0020062001103b000b41c0bcca0020042001103b000b20030d000b0b0240024020014102490d002001210703402007417f6a220720014f0d02200241286a220b200041286a2205290300370300200241206a220c200041206a2206290300370300200241186a220d200041186a2208290300370300200241106a220e200041106a2210290300370300200241086a220f200041086a2211290300370300200220002903003703002000200741306c6a22042903002109200441086a290300210a200441106a2903002116200441186a2903002118200441206a29030021192005200441286a2903003703002006201937030020082018370300201020163703002011200a3703002000200937030041002105024002400240034020042002290300370300200441286a200b290300370300200441206a200c290300370300200441186a200d290300370300200441106a200e290300370300200441086a200f2903003703002005410174220441017221060240200441026a220420074f0d00200620074f0d02200420062000200641306c6a22082903002000200441306c6a221029030056200841086a2903002209201041086a290300220a562009200a511b1b21060b200620074f0d03200520074f0d022000200541306c6a22052903002000200641306c6a220429030056200541086a22082903002209200441086a2210290300220a562009200a511b450d03200b200541286a2211290300370300200c200541206a2212290300370300200d200541186a2213290300370300200e200541106a2214290300370300200f20082903003703002002200529030037030020102903002109200441106a290300210a200441186a2903002116200441206a2903002118200429030021192011200441286a29030037030020122018370300201320163703002014200a3703002008200937030020052019370300200621050c000b0b41b0bcca0020062007103b000b41c0bcca0020052007103b000b200741014b0d000b0b200241306a24000f0b4198bbca0020072001103b000bb80c050a7f017e017f037e0f7f230041306b22022400200041c07e6a21032001417f6a2104200041306a2105410021062001413249210741012108024003400240024020082001490d00410021090c010b410121092000200841306c220a6a220b290300220c200b41506a220d29030056200b41086a290300220e200d41086a290300220f56200e200f511b0d002005200a6a210903404101210b20042008460d03200841016a210820092903002210200c58210b200941086a290300220f200e51210d200f200e58210a200941306a21092010210c200f210e200b200a200d1b0d000b200820014921090b2008200146210b20070d0120082001460d010240024002400240024002402008417f6a220b20014f0d002009450d012000200b41306c6a2209290300210e20092000200841306c22116a220b290300370300200241286a220a200941286a2212290300370300200241206a2213200941206a2214290300370300200241186a2215200941186a2216290300370300200241106a2217200941106a2218290300370300200241086a2219200941086a220d290300370300200d200b41086a221a2903003703002018200b41106a221b2903003703002016200b41186a221c2903003703002014200b41206a221d2903003703002012200b41286a221e2903003703002002200e370300200b2002290300370300201e200a290300370300201d2013290300370300201c2015290300370300201b2017290300370300201a201929030037030020084102490d052009290300220c20002008417e6a221341306c6a220a29030058200d290300220e200a41086a221f290300220f58200e200f511b0d052009200a290300370300200d201f2903003703002009290310210f2018200a41106a2903003703002015201229030037030020172014290300370300201920162903003703002016200a41186a2903003703002014200a41206a2903003703002012200a41286a2903003703002002200f370300024020130d00410021130c050b200c20002008417d6a220d41306c6a220929030058200e200941086a290300220f58200e200f511b0d04200320116a2109034020094188016a200941d8006a29030037030020094180016a200941d0006a290300370300200941f8006a200941c8006a290300370300200941f0006a200941c0006a290300370300200941e8006a200941386a290300370300200941e0006a200941306a290300370300200d450d032009290300210f200941086a210a200941506a2109200d417f6a210d200c200f56200e200a290300220f56200e200f511b0d000b200d41016a21130c030b4188bbca00200b2001103b000b4198bbca0020082001103b000b410021130b2000201341306c6a210a0b200a200c370300200a200e3703082000201341306c6a22092002290300370310200941286a2015290300370300200941206a2017290300370300200941186a20192903003703000b200641016a21060240200120086b22144102490d00200b290330200b290300220c58200b41386a290300220f201a290300220e58200f200e511b0d00200b200b41306a2212290300370300201a201241086a290300370300200b290310210f201b201241106a2903003703002015201e2903003703002017201d2903003703002019201c290300370300201c201241186a290300370300201d201241206a290300370300201e201241286a2903003703002002200f3703004101211a024020144103490d00200b290360200c58200b41e8006a290300220f200e58200f200e511b0d00200b41e0006a21094103210a4102210d0340200d221a41306c200b6a221241506a220d2009290300370300200d41286a200941286a290300370300200d41206a200941206a290300370300200d41186a200941186a290300370300200d41106a200941106a290300370300200d41086a200941086a290300370300200a20144f0d01200a41306c2109200a210d200a41016a210a200b20096a2209290300200c56200941086a290300220f200e56200f200e511b0d000b0b2012200c3703002012200e370308200b201a41306c6a22092002290300370310200941286a2015290300370300200941206a2017290300370300200941186a20192903003703000b20064105470d000b4100210b0b200241306a2400200b0be52003167f037e067f230041c0026b220424000240024020014115490d0041012105410121060240024002400340200121072000210820052006714101732109024002400240024002400240034002400240024002402003450d00024020054101710d002000200110e1032003417f6a21030b2001410276220a41036c210b200a410174210c4100210d024020014132490d00200a200a417f6a220d2000200a4105746a2000200d4105746a412010ea06220e410048220f1b2210200a41016a2211200d200a200f1b220a200020114105746a2000200a4105746a412010ea0641004822111b220a2000200a4105746a200020104105746a412010ea0622104100481b210a200c200c417f6a220d2000200c4105746a2000200d4105746a412010ea06221241004822131b2214200c4101722215200d200c20131b220c200020154105746a2000200c4105746a412010ea0622134100481b220c2000200c4105746a200020144105746a412010ea0622144100481b210c200b200b417f6a220d2000200b4105746a2000200d4105746a412010ea06221541004822161b2217200b41016a2218200d200b20161b220b200020184105746a2000200b4105746a412010ea06220d4100481b220b2000200b4105746a200020174105746a412010ea0622164100481b210b41024101200f1b200e411f7620111b2010411f766a2012411f766a2013411f766a2014411f766a2015411f766a200d411f766a2016411f766a210d0b2000200c4105746a2000200a4105746a412010ea06220f411f76200d6a2000200b4105746a2000200a200c200f410048220f1b220e4105746a412010ea062210411f766a210d2000200b200e20104100481b220b4105746a2000200c200a200f1b22194105746a412010ea06417f4c0d01200b21190c020b2000200110e2030c0f0b200d41016a220d410c490d0002402001410176220b450d00200020014105746a41606a210a2000210c0340200441206a41186a220d200c41186a220f290000370300200441206a41106a220e200c41106a2210290000370300200441206a41086a2211200c41086a22122900003703002004200c290000370320200a41086a2213290000211a200a41106a2214290000211b200a41186a2215290000211c200c200a290000370000200f201c3700002010201b3700002012201a3700002015200d2903003700002014200e29030037000020132011290300370000200a2004290320370000200a41606a210a200c41206a210c200b417f6a220b0d000b0b20012019417f736a21194101210a0c010b200d45210a0b0240200a452009724101710d002000200110e3030d0d0b2002450d02201920014f0d0102402002200020194105746a220a412010ea0641004e0d0020002108200121070c040b200441206a41186a2212200041186a220e290000370300200441206a41106a2213200041106a2210290000370300200441206a41086a2214200041086a221129000037030020042000290000370320200a41086a220c290000211a200a41106a220b290000211b200a41186a220d290000211c2000200a290000370000200e201c3700002010201b3700002011201a370000200d2012290300370000200b2013290300370000200c2014290300370000200a2004290320370000200441c0016a41186a2217200e290000370300200441c0016a41106a22182010290000370300200441c0016a41086a22192011290000370300200420002900003703c001200041606a2115200041206a21164100210c2001210b03400240200c200b417f6a220d4f0d002016200c4105746a210a0340200441c0016a200a412010ea06417f4c0d01200a41206a210a200d200c41016a220c470d000b200d210c0b2015200b4105746a210a02400340200c200b417f6a220b4f0d01200441c0016a200a412010ea06210d200a41606a220f210a200d4100480d000b20122016200c4105746a220a41186a220d2900003703002013200a41106a221d2900003703002014200a41086a22062900003703002004200a290000370320200f41286a221e290000211a200f41306a221f290000211b200f41386a2220290000211c200a200f41206a220f290000370000200d201c370000201d201b3700002006201a37000020202012290300370000201f2013290300370000201e2014290300370000200f2004290320370000200c41016a210c0c010b0b200020042903c001370000200e2017290300370000201020182903003700002011201929030037000002402001200c41016a220a490d002000200a4105746a21002001200a6b220141154f0d010c0c0b0b200a2001104b000b41d4bbca0020192001103b000b2007450d010b201920074f0d01200441206a41186a2216200841186a221e290000370300200441206a41106a2217200841106a221f290000370300200441206a41086a2218200841086a222029000037030020042008290000370320200820194105746a220a41086a220c290000211a200a41106a220b290000211b200a41186a220d290000211c2008200a290000370000201e201c370000201f201b3700002020201a370000200d2016290300370000200b2017290300370000200c2018290300370000200a2004290320370000200441186a2205201e290000370300200441106a2209201f290000370300200441086a2221202029000037030020042008290000370300200841206a21014100211d2007417f6a220d450d022001210a0340200a2004412010ea0641004e0d03200a41206a210a200d201d41016a221d470d000b200d211d0c020b4188bbca0041004100103b000b4198bbca0020192007103b000b200820074105746a210c200d210b02400340200c2100200b220a201d4d22060d01200a417f6a210b200041606a220c2004412010ea06417f4a0d000b0b0240200a201d490d00200d200a490d0241800121144100210f410021124100210d4100211141800121152001201d4105746a2222210103400240200020016b220a419fc0004b22190d00200a410576220a41807f6a200a2012200f492011200d49220c72220b1b210a0240200b450d002015200a200c1b2115200a2014200c1b21140c010b200a200a41017622156b21140b02402011200d470d00024020150d00200441c0006a220d21110c010b4100210a200441c0006a2211210d2001210c0340200d200a3a0000200d200c2004412010ea06417f73411f766a210d200c41206a210c2015200a41016a220a470d000b0b02402012200f470d00024020140d00200441c0016a220f21120c010b200041606a210a4100210c200441c0016a2212210f0340200f200c3a0000200f200a2004412010ea06411f766a210f200a41606a210a2014200c41016a220c470d000b0b0240200f20126b220a200d20116b220c200c200a4b1b2213450d002016200120112d00004105746a220a41186a2900003703002017200a41106a2900003703002018200a41086a2900003703002004200a290000370320200120112d00004105746a220a200020122d0000417f734105746a220c290000370000200a41186a200c41186a290000370000200a41106a200c41106a290000370000200a41086a200c41086a290000370000024020134101460d004100210a034020002012200a6a220e2d0000417f734105746a220c20012011200a6a41016a22102d00004105746a220b290000370000200c41186a200b41186a290000370000200c41106a200b41106a290000370000200c41086a200b41086a290000370000200120102d00004105746a220c2000200e41016a2d0000417f734105746a220b290000370000200c41186a200b41186a290000370000200c41106a200b41106a290000370000200c41086a200b41086a290000370000200a41026a210c200a41016a220b210a200c2013490d000b2012200b6a21122011200b6a21110b200020122d0000417f734105746a220a2004290320370000200a41186a2016290300370000200a41106a2017290300370000200a41086a2018290300370000201241016a2112201141016a21110b200020144105746b20002012200f461b2100200120154105746a20012011200d461b210120190d000b024002402011200d4f0d002000210a034020162001200d417f6a220d2d00004105746a220c41186a220b2900003703002017200c41106a220f2900003703002018200c41086a22002900003703002004200c290000370320200a41606a220a41086a220e290000211a200a41106a2210290000211b200a41186a2212290000211c200c200a290000370000200b201c370000200f201b3700002000201a3700002012201629030037000020102017290300370000200e2018290300370000200a20042903203700002011200d490d000c020b0b2001210a2012200f4f0d000340200f417f6a220f2d0000210c2016200a41186a220b2900003703002017200a41106a220d2900003703002018200a41086a22012900003703002004200a2900003703202000200c417f734105746a220c41086a220e290000211a200c41106a2210290000211b200c41186a2211290000211c200a200c290000370000200b201c370000200d201b3700002001201a3700002011201629030037000020102017290300370000200e2018290300370000200c2004290320370000200a41206a210a2012200f490d000b0b20082004290300370000201e2005290300370000201f2009290300370000202020212903003700002007200a20226b410576201d6a22014d0d032016201e2900003703002017201f2900003703002018202029000037030020042008290000370320200820014105746a220a41086a220c290000211a200a41106a220b290000211b200a41186a220d290000211c2008200a290000370000201e201c370000201f201b3700002020201a370000200d2016290300370000200b2017290300370000200c2018290300370000200a2004290320370000200720016b220c450d04200c20012001200c4b1b210b2007410376210d200a41206a2100024002402001200c417f6a220c490d002000200c200a200310e003200821000c010b200820012002200310e003200a2102200c21010b200b200d4f2105200141154f0d010c050b0b201d200a104b000b200a200d104a000b4198bbca0020012007103b000b41a8bbca00411c41c4bbca001039000b20014102490d00200041606a210f4101210b0340200b410574210a200b417f6a210c200b41016a210b02402000200a6a220a2000200c4105746a220d412010ea06417f4a0d00200441c0016a41186a220e200a41186a2210290000370300200441c0016a41106a2211200a41106a2212290000370300200441c0016a41086a2213200a41086a22142900003703002004200a2900003703c001200a200d2900003700002014200d41086a2900003700002012200d41106a2900003700002010200d41186a2900003700004100210d0240200c450d00200f210a03400240200441c0016a200a412010ea064100480d00200c210d0c020b200a41206a200a290000370000200a41386a200a41186a290000370000200a41306a200a41106a290000370000200a41286a200a41086a290000370000200a41606a210a200c417f6a220c0d000b0b2000200d4105746a220a20042903c001370000200a41186a200e290300370000200a41106a2011290300370000200a41086a20132903003700000b200f41206a210f200b2001470d000b0b200441c0026a24000beb050a067f017e017f017e017f017e017f017e017f017e230041206b2202240002400240024020014108490d00200141017641feffffff07712203417f6a220420014f0d022001410d74200173220541117620057322054105742005732206417f2001417f6a677622077122054100200120052001491b6b220520014f0d01200020044105746a22042900002108200020054105746a220541086a2209290000210a200541106a220b290000210c200541186a220d290000210e20042005290000370000200441186a220f2900002110200f200e370000200441106a220f290000210e200f200c370000200441086a2204290000210c2004200a370000200d2010370000200b200e3700002009200c37000020052008370000024020032001490d00200321040c030b2006410d7420067322054111762005732205410574200573220620077122054100200120052001491b6b220520014f0d01200020034105746a22042900002108200020054105746a220541086a2209290000210a200541106a220b290000210c200541186a220d290000210e20042005290000370000200441186a220f2900002110200f200e370000200441106a220f290000210e200f200c370000200441086a2204290000210c2004200a370000200d2010370000200b200e3700002009200c370000200520083700002003410172220420014f0d022006410d742006732205411176200573220541057420057320077122054100200120052001491b6b220520014f0d01200020044105746a22012900002108200020054105746a220041086a2205290000210a200041106a2204290000210c200041186a2203290000210e20012000290000370000200141186a220629000021102006200e370000200141106a2206290000210e2006200c370000200141086a2201290000210c2001200a370000200320103700002004200e3700002005200c370000200020083700000b200241206a24000f0b4198bbca0020052001103b000b4188bbca0020042001103b000be90609067f017e017f017e017f027e017f017e027f230041206b22022400024020014101762203450d0003402003417f6a2203210402400240024003402004410174220541017221060240200541026a220520014f0d00200620014f0d0220052006200020064105746a200020054105746a412010ea064100481b21060b200620014f0d03200420014f0d02200020044105746a2204200020064105746a2205412010ea0641004e0d03200541086a22072900002108200541106a2209290000210a200541186a220b290000210c2004290000210d20042005290000370000200441186a220e290000210f200e200c370000200441106a220e290000210c200e200a370000200441086a2204290000210a20042008370000200b200f3700002009200c3700002007200a3700002005200d370000200621040c000b0b41b0bcca0020062001103b000b41c0bcca0020042001103b000b20030d000b0b0240024020014102490d002001210703402007417f6a220720014f0d02200241186a2209200041186a2204290000370300200241106a220b200041106a2205290000370300200241086a220e200041086a2203290000370300200020074105746a220641086a2900002108200641106a290000210a200641186a290000210c2000290000210d200020062900003700002004200c3700002005200a370000200320083700002002200d37030041002105024002400240034020062002290300370000200641186a2009290300370000200641106a200b290300370000200641086a200e2903003700002005410174220641017221040240200641026a220620074f0d00200420074f0d0220062004200020044105746a200020064105746a412010ea064100481b21040b200420074f0d03200520074f0d02200020054105746a2205200020044105746a2206412010ea0641004e0d032009200541186a2203290000370300200b200541106a2210290000370300200e200541086a2211290000370300200641086a2900002108200641106a290000210a200641186a290000210c2005290000210d200520062900003700002003200c3700002010200a370000201120083700002002200d370300200421050c000b0b41b0bcca0020042007103b000b41c0bcca0020052007103b000b200741014b0d000b0b200241206a24000f0b4198bbca0020072001103b000bdb08030a7f017e0a7f230041c0006b22022400200041a07f6a21032001417f6a2104200141324921054101210641002107024003400240024020062001490d00410021080c010b41012108200020064105746a2209200941606a412010ea064100480d0003404101210a20042006460d03200641016a2106200941206a220a2009412010ea062108200a21092008417f4a0d000b200620014921080b2006200146210a20050d0120062001460d0102400240024002402006417f6a220920014f0d002008450d0120002006410574220b6a220a290000210c200a200020094105746a22092900003700002009200c370000200a41086a220d290000210c200d200941086a220e290000370000200e200c370000200a41106a220f290000210c200f200941106a22102900003700002010200c370000200a41186a2211290000210c2011200941186a22122900003700002012200c37000020064102490d03200920002006417e6a22084105746a2213412010ea06417f4a0d032009290000210c20092013290000370000200241206a41186a22142012290000370300200241206a41106a22152010290000370300200241206a41086a2216200e290000370300200e201341086a2900003700002010201341106a2900003700002012201341186a2900003700002002200c3703204100210e2008450d022003200b6a210903400240200241206a2009412010ea064100480d002008210e0c040b200941206a2009290000370000200941386a200941186a290000370000200941306a200941106a290000370000200941286a200941086a290000370000200941606a21092008417f6a22080d000c030b0b4188bbca0020092001103b000b4198bbca0020062001103b000b2000200e4105746a22092002290320370000200941186a2014290300370000200941106a2015290300370000200941086a20162903003700000b200741016a21070240200120066b22104102490d00200a41206a2209200a412010ea06417f4a0d00200a290000210c200a2009290000370000200241206a41186a22122011290000370300200241206a41106a2213200f290000370300200241206a41086a220b200d290000370300200d200941086a290000370000200f200941106a2900003700002011200941186a2900003700002002200c3703204101210d024020104103490d00200a41c0006a200241206a412010ea06417f4a0d00410321084102210e0340200a200e4105746a220941606a220d2009290000370000200d41186a200941186a290000370000200d41106a200941106a290000370000200d41086a200941086a290000370000024020082010490d00200e210d0c020b20084105742109200e210d2008210e200841016a2108200a20096a200241206a412010ea064100480d000b0b200a200d4105746a22092002290320370000200941186a2012290300370000200941106a2013290300370000200941086a200b2903003700000b20074105470d000b4100210a0b200241c0006a2400200a0bc21301147f23004180026b220424000240024020014115490d0041012105410121060240024002400340200121072000210820052006714101732109024002400240024002400240034002400240024002402003450d00024020054101710d002000200110e5032003417f6a21030b2001410276220a41036c210b200a410174210c4100210d024020014132490d00200b200b417f6a220e2000200b4102746a280200220f2000200e4102746a280200221049220d1b2211200b41016a2212200e200b200d1b200020124102746a280200220b2010200f200d1b220e4922101b200b200e20101b200020114102746a2802004922131b210b200c200c417f6a220e2000200c4102746a28020022112000200e4102746a280200221249220f1b2214200c4101722215200e200c200f1b200020154102746a280200220c20122011200f1b220e4922111b200c200e20111b200020144102746a2802004922141b210c200a200a417f6a22122000200a4102746a2802002215200020124102746a280200220649220e1b2216200a41016a22172012200a200e1b200020174102746a280200220a20062015200e1b22154922121b200a201520121b200020164102746a2802004922151b210a41024101200e1b200e20121b20156a200f6a20116a20146a200d6a20106a20136a210d0b200d2000200c4102746a280200220f2000200a4102746a280200221049220e6a2000200b4102746a280200220d2010200f200e1b22114922106a210f200d201120101b2000200c200a200e1b220d4102746a280200490d01200b200a200c200e1b20101b210d0c020b2000200110e6030c0f0b200f41016a220f410c490d0002402001410176220b450d00200020014102746a417c6a210a2000210c0340200c280200210e200c200a280200360200200a200e360200200c41046a210c200a417c6a210a200b417f6a220b0d000b0b2001200d417f736a210d4101210a0c010b200f45210a0b0240200a452009724101710d002000200110e7030d0d0b2002450d02200d20014f0d01024020022802002000200d4102746a220a280200220c4f0d0020002108200121070c040b2000280200210b2000200c360200200a200b3602002000417c6a2110200041046a21112000280200210d4100210c2001210b03400240200c200b417f6a220e4f0d002011200c4102746a210a0340200d200a280200490d01200a41046a210a200e200c41016a220c470d000b200e210c0b2010200b4102746a210a02400340200c200b417f6a220b4f0d01200a280200210e200a417c6a220f210a200d200e490d000b2011200c4102746a220a2802002112200a200e360200200f41046a2012360200200c41016a210c0c010b0b2000200d36020002402001200c41016a220a490d002000200a4102746a21002001200a6b220141154f0d010c0c0b0b200a2001104b000b41d4bbca00200d2001103b000b2007450d010b200d20074f0d012008280200210a20082008200d4102746a220c280200360200200c200a360200200841046a210f20082802002111410021142007417f6a220d450d02200f210a0340200a28020020114f0d03200a41046a210a200d201441016a2214470d000b200d21140c020b4188bbca0041004100103b000b4198bbca00200d2007103b000b200820074102746a210c200d210b02400340200c210e200b220a20144d22060d01200a417f6a210b200e417c6a220c28020020114f0d000b0b0240200a2014490d00200d200a490d0241800121054100210b410021014100210c410021104180012109200f20144102746a2216210d03400240200e200d6b220a4183084b22130d00200a410276220a41807f6a200a2001200b492010200c49220f7222001b210a02402000450d002009200a200f1b2109200a2005200f1b21050c010b200a200a41017622096b21050b02402010200c470d00024020090d002004220c21100c010b4100210a20042210210c200d210f0340200c200a3a0000200c200f28020020114f6a210c200f41046a210f2009200a41016a220a470d000b0b02402001200b470d00024020050d0020044180016a220b21010c010b200e417c6a210a4100210f20044180016a2201210b0340200b200f3a0000200b200a2802002011496a210b200a417c6a210a2005200f41016a220f470d000b0b0240200b20016b220a200c20106b220f200f200a4b1b2212450d00200d20102d00004102746a220a2802002115200a200e20012d0000417f734102746a280200360200024020124101460d004100210a0340200e2001200a6a220f2d0000417f734102746a200d2010200a6a41016a22002d00004102746a280200360200200d20002d00004102746a200e200f41016a2d0000417f734102746a280200360200200a41026a210f200a41016a2200210a200f2012490d000b200120006a2101201020006a21100b200e20012d0000417f734102746a2015360200200141016a2101201041016a21100b200e20054102746b200e2001200b461b210e200d20094102746a200d2010200c461b210d20130d000b024002402010200c4f0d00200e210a0340200d200c417f6a220c2d00004102746a220b280200210e200b200a417c6a220a280200360200200a200e3602002010200c490d000c020b0b200d210a2001200b4f0d000340200a280200210c200a200e200b417f6a220b2d0000417f734102746a220d280200360200200d200c360200200a41046a210a2001200b490d000b0b200820113602002007200a20166b41027620146a22014d0d032008200820014102746a220a280200360200200a2011360200200720016b220c450d04200c20012001200c4b1b210b2007410376210e200a41046a2100024002402001200c417f6a220c490d002000200c200a200310e403200821000c010b200820012002200310e403200a2102200c21010b200b200e4f2105200141154f0d010c050b0b2014200a104b000b200a200d104a000b4198bbca0020012007103b000b41a8bbca00411c41c4bbca001039000b20014102490d00200041746a210e4102210d4101210a0340200a41016a210c02402000200a4102746a2210280200220b2000200a417f6a22114102746a220f28020022124f0d002010201236020002402011450d00200b2000200a417e6a22104102746a221128020022124f0d00200f2012360200024020100d002011210f0c010b0240200b2000200a417d6a220a4102746a220f2802002210490d002011210f0c010b20112010360200200a450d00200d210f200e210a02400340200b200a28020022104f0d01200a41046a2010360200200a417c6a210a200f41016a2210200f4921112010210f2011450d000b0b200a41046a210f0b200f200b3602000b200d417f6a210d200e41046a210e200c210a200c2001470d000b0b20044180026a24000bf30201067f02400240024020014108490d00200141017641feffffff07712202417f6a220320014f0d022001410d74200173220441117620047322044105742004732205417f2001417f6a677622067122044100200120042001491b6b220420014f0d01200020034102746a220328020021072003200020044102746a220428020036020020042007360200024020022001490d00200221030c030b2005410d7420057322044111762004732204410574200473220520067122044100200120042001491b6b220420014f0d01200020024102746a220328020021072003200020044102746a2204280200360200200420073602002002410172220320014f0d022005410d742005732204411176200473220441057420047320067122044100200120042001491b6b220420014f0d01200020034102746a220128020021022001200020044102746a2200280200360200200020023602000b0f0b4198bbca0020042001103b000b4188bbca0020032001103b000bc70301067f024020014101762202450d0003402002417f6a2202210302400240024003402003410174220441017221050240200441026a220420014f0d00200520014f0d0220042005200020054102746a280200200020044102746a280200491b21050b200520014f0d03200320014f0d02200020034102746a22032802002204200020054102746a220628020022074f0d032003200736020020062004360200200521030c000b0b41b0bcca0020052001103b000b41c0bcca0020032001103b000b20020d000b0b0240024020014102490d002001210403402004417f6a220420014f0d02200028020021052000200020044102746a2203280200360200200320053602004100210302400240024003402003410174220641017221050240200641026a220620044f0d00200520044f0d0220062005200020054102746a280200200020064102746a280200491b21050b200520044f0d03200320044f0d02200020034102746a22032802002206200020054102746a220728020022024f0d032003200236020020072006360200200521030c000b0b41b0bcca0020052004103b000b41c0bcca0020032004103b000b200441014b0d000b0b0f0b4198bbca0020042001103b000b8a05010f7f2001417d6a2102200041086a21032000416c6a21042001417f6a2105200041046a2106410021072001413249210841012109024003400240024020092001490d004100210a0c010b4101210a20002009410274220b6a220c280200220d200c417c6a280200490d002006200b6a210a03404101210c20052009460d03200941016a2109200a280200220c200d4f210b200a41046a210a200c210d200b0d000b2009200149210a0b2009200146210c20080d0120092001460d0102400240024002402009417f6a220d20014f0d00200a450d012000200d4102746a220c280200210b200c20002009410274220e6a220a280200220d360200200a200b360200024020094102490d00200d20002009417e6a220b4102746a220f28020022104f0d00200c201036020002400240200b0d00200f210c0c010b0240200d20002009417d6a220b4102746a220c2802002210490d00200f210c0c010b200f2010360200200b450d00200d200a41706a280200220f4f0d002004200e6a2110024003402010220c41086a200f360200200b417f6a220b450d01200c417c6a2110200d200c280200220f490d000b0b200c41046a210c0b200c200d3602000b200741016a2107200120096b220b4102490d03200a280204220f200a280200220c4f0d03200a41046a210d200a200f360200200b4103490d02200a280208220f200c4f0d02200d200f3602000240200b41044f0d00200a41086a210d0c030b200220096b210a2003200e6a210d0340200d41046a220b280200220e200c4f0d03200d200e360200200b210d200a417f6a220a0d000b200b210d0c020b4188bbca00200d2001103b000b4198bbca0020092001103b000b200d200c3602000b20074105470d000b4100210c0b200c0bef0201067f230041d0006b2201240002400240410b102d2202450d00200241edde91e3063600002002410b411610312203450d00200342f0f2bd99f7edd8b4e500370004200341002800c4d94436000c2003410f6a41002800c7d944360000200141003a00484113210220032104410021050340200141003a0008200141086a20042002410047220610e8061a024020020d00200141003a00080b20022006490d02200141286a20056a20012d00083a00002001200541016a22053a0048200220066b2102200420066a210420054120470d000b200141086a41186a2202200141286a41186a290300370300200141086a41106a2205200141286a41106a290300370300200141086a41086a2206200141286a41086a290300370300200120012903283703082003102f200041186a2002290300370000200041106a2005290300370000200041086a200629030037000020002001290308370000200141d0006a24000f0b1036000b20062002104b000bc90402017f037e23004190016b22042400024002400240024020002d00000e03000102000b200441206a41186a200341186a290000370300200441206a41106a200341106a290000370300200441206a41086a200341086a29000037030020042003290000370320200041016a2002ad4220862001ad84200441206a101a41014621000c020b200441206a41186a200341186a290000370300200441206a41106a200341106a290000370300200441206a41086a200341086a29000037030020042003290000370320200041016a2002ad4220862001ad84200441206a101441014621000c010b2002ad4220862001ad84100322012900002105200141086a2900002106200141106a2900002107200441186a200141186a290000370300200441106a2007370300200441086a2006370300200420053703002001102f41012101200441206a200041016a200410ea034100210020042d00200d00200441c8006a41206a200441c1006a2d00003a0000200441c8006a41186a200441396a290000370300200441c8006a41106a200441316a290000370300200441c8006a41086a200441296a29000037030020042004290021370348200441c8006aad4280808080900484100322002900002105200041086a2900002106200041106a2900002107200441f0006a41186a200041186a290000370300200441f0006a41106a2007370300200441f0006a41086a2006370300200420053703702000102f0240200441f0006a2003460d00200441f0006a2003412010ea064521010b200121000b20044190016a240020000bcf0303017f017e037f230041d0006b22032400024020012002102c2204422088a72201450d002004a722052d0000220241014b0d002001417f6a210602400240024020020e020001000b41002101200341003a0049200541016a21070240034020062001460d01200341286a20016a200720016a2d00003a00002003200141016a22023a00492002210120024121470d000b200341106a200341316a290000370300200341186a200341396a290000370300200341206a200341c1006a2900003703002003200329002937030820032d0028210241002106200341086a21010c020b200141ff0171450d02200341003a00490c020b2006450d0120052d0001220241034f0d01200341086a41186a200341286a41186a290000370300200341086a41106a200341286a41106a290000370300200341086a41086a200341286a41086a2900003703002003200329002837030841012106200341086a21010b200020023a0001200020063a0000200041026a20012900003700002000410a6a200141086a290000370000200041126a200141106a2900003700002000411a6a200141186a2900003700002005102f200341d0006a24000f0b41f4c8ca00412e200341286a418ccaca0041a4c9ca00103e000b130020004102360204200041f0e0c3003602000b130020004102360204200041fce1c3003602000b910302087f017e230041106b2202240002400240024020012802042203450d00200128020022042d0000210520012003417f6a22063602042001200441016a3602002006450d0020042d0001210720012003417e6a22063602042001200441026a3602002006450d0020042d0002210820012003417d6a22063602042001200441036a36020020060d010b200041003602040c010b20042d0003210620012003417c6a3602042001200441046a360200200241086a200110e60102400240024020022802080d002001280204200228020c2204490d002004417f4c0d01024002400240024020040d00410121030c010b200410332203450d0120012802042004490d0220032001280200200410e8061a200128020422092004490d052001200920046b3602042001200128020020046a3602000b2003450d0220002004ad220a422086200a8437020820002003360204200020074108742005722008411074722006411874723602000c050b1036000b2003102f0b200041003602040c020b103d000b20042009104b000b200241106a24000bc80504047f017e087f037e230041f0006b220224002002200110e60102400240024002402002280200450d00200041003602000c010b20022802042203200128020441286e2204200420034b1b2205ad42287e2206422088a70d012006a72204417f4c0d010240024020040d00410821070c010b2004102d2207450d03200441286e21050b02402003450d00410021080340200241003a00682008220941016a21082001280204210a417f210b4100210402400240024002400340200a2004460d01200241c8006a20046a2001280200220c2d00003a00002001200a200b6a3602042001200c41016a3602002002200441016a220d3a0068200b417f6a210b200d2104200d4120470d000b200241286a41186a2204200241c8006a41186a290300370300200241286a41106a220b200241c8006a41106a290300370300200241286a41086a220e200241c8006a41086a29030037030020022002290348370328200a200d6b220d4108490d01200c29000121062001200c41096a3602002001200d41786a360204200241086a41086a220d200e290300370300200241086a41106a220a200b290300370300200241086a41186a220b20042903003703002002200229032837030820052009470d030240200941017422042008200420084b1bad42287e220f422088a70d00200fa7220441004e0d030b1038000b200441ff0171450d00200241003a00680b200041003602002005450d042007102f0c040b0240024020090d002004102d21070c010b2007200941286c2004103121070b2007450d05200441286e21050b2007200941286c6a22042002290308370300200d290300210f200a2903002110200b290300211120042006370320200441186a2011370300200441106a2010370300200441086a200f37030020082003470d000b0b2000200536020420002007360200200041086a20033602000b200241f0006a24000f0b103d000b1036000b8e0301087f230041106b22022400024002400240200028020822034105744104722204417f4c0d00200028020021052004102d2206450d0120024100360208200220043602042002200636020020032002106902402003450d0020034105742107200228020021082002280204210420022802082103034002400240200420036b4120490d00200341206a2106200421090c010b200341206a22062003490d05200441017422092006200920064b1b22094100480d050240024020040d002009102d21080c010b200820042009103121080b2008450d040b200820036a22032005290000370000200341186a200541186a290000370000200341106a200541106a290000370000200341086a200541086a2900003700002009210420062103200541206a2105200741606a22070d000b2002200936020420022006360208200220083602000b2000410c6a200210ce02200228020421052001290200200235020842208620022802002203ad84100402402005450d002003102f0b200241106a24000f0b103d000b1036000b1038000bc20101047f230041106b22022400200028020022002802082103200028020021004101210420012802184199a5c00041012001411c6a28020028020c1100002105200241003a0005200220053a00042002200136020002402003450d0003402002200036020c20022002410c6a4190ebc30010621a200041016a21002003417f6a22030d000b20022d000421050b0240200541ff01710d00200228020022002802184198a5c00041012000411c6a28020028020c11000021040b200241106a240020040bd90201077f0240024002400240024002402000280208220141ffffff3f712001470d0020014105742202417f4c0d0020002802002103024020020d00200320014105746a210041012104200121050c040b2002102d2204450d01200320014105746a21002002410576220520014f0d03200541017422022001200220014b1b220241ffffff3f712002470d02200241057422024100480d020240024020050d002002102d21040c010b200420054105742002103121040b2004450d01200241057621050c040b103d000b1036000b1038000b20010d00410021020c010b200020036b2106410021020340200420026a2200200320026a2207290000370000200041186a200741186a290000370000200041106a200741106a290000370000200041086a200741086a2900003700002006200241206a2202470d000b200320014105746a20036b41057521020b02402005450d002004102f0b20020b8c0201067f0240200041086a220228020022032001490d00200220013602000f0b0240024002400240200041046a280200220420036b200120036b2205490d0020002802002104200321000c010b200320056a22062003490d02200441017422072006200720064b1b22064100480d020240024020040d002006102d21040c010b200028020020042006103121040b2004450d0120002004360200200041046a2006360200200041086a28020021000b200420006a210602400240024020054102490d00200641002003417f73220320016a10e7061a2004200020016a20036a22006a21060c010b2005450d010b200641003a0000200041016a21000b200220003602000f0b1036000b1038000bf80204017f017e067f037e0240024002400240024020012802082202ad42287e2203422088a70d002003a72204417f4c0d0020012802002105024020040d002005200241286c6a210641082107200221010c020b024002402004102d2207450d002005200241286c6a2106200441286e220120024f0d03200141017422082002200820024b1b220941286c22024100480d0102400240200441274b0d002002102d21070c010b2007200141286c2002103121070b20070d040b1036000b1038000b103d000b2002450d01200121090b200620056b210841002104410021060340200520046a22022903002103200241086a290300210a200241106a290300210b200241186a290300210c200720046a220141206a200241206a290300370300200141186a200c370300200141106a200b370300200141086a200a37030020012003370300200641016a21062008200441286a2204470d000b200921010c010b410021060b2000200636020820002001360204200020073602000bbb0301037f024020002802082201450d002000280200220020014198016c6a21020340024020002d0000417a6a2201410c4b0d00024002400240024002400240024020010e0d00070701070207030704050706000b200041086a2d00004101470d06200041146a280200450d06200041106a280200102f0c060b200041046a2d00000d052000410c6a280200450d05200041086a280200102f0c050b200041046a2802000d042000410c6a280200450d04200041086a280200102f0c040b200041086a2d00004107470d03200041306a280200450d032000412c6a280200102f0c030b200041046a2d00004102490d020240200041106a2802002201450d00200141d0006c2103200041086a28020041c0006a210103400240200141046a280200450d002001280200102f0b200141d0006a2101200341b07f6a22030d000b0b2000410c6a280200450d022000280208102f0c020b200041086a280200450d01200041046a280200102f0c010b200041086a2d00004106470d00200041306a280200450d002000412c6a280200102f0b20004198016a210102402000418c016a280200450d00200028028801102f0b2001210020012002470d000b0b0bbd0c05047f017e0b7f027e027f230041e0006b22022400200241086a200110e601024002402002280208450d00200041003602000c010b02400240024002400240200228020c2203200128020441246e2204200420034b1b2205ad42247e2206422088a70d002006a72204417f4c0d000240024020040d00410421070c010b2004102d2207450d02200441246e21050b024020030d00410021040c050b2002412d6a2108200241cb006a220941056a210a4100210b4100210c03402001280204220d450d042001280200220e2d000021042001200d417f6a220f3602042001200e41016a360200200441074b0d040240024002400240024002400240024002400240024020040e08000f010f03040205000b2002200110e60120022802000d0e200128020420022802042204490d0e2004417f4c0d0b0240024020040d00410121100c010b200410332210450d0d20012802042004490d0820102001280200200410e8061a2001280204220d2004490d0e2001200d20046b3602042001200128020020046a3602000b2010450d0e2004ad22064220862006842106200241206a41086a200241386a41086a29020037030020022002290238370320201041807e71210f410521110c050b41002104200241003a0058200d417e6a210d02400340200f2004460d01200241386a20046a200e20046a221041016a2d00003a00002001200d3602042001201041026a3602002002200441016a22103a0058200d417f6a210d2010210420104120470d000b200220092900003703202002200a2900003700252002280047210e200229003f210620022f0138210420022d003a210d200228003b2110200841026a200241356a41026a2d00003a0000200820022f00353b0000201041807e71210f2004200d41107472210d410021110c060b200441ff0171450d0d200241003a00580c0d0b200241386a200110ed03200228023c450d0c20022f013820022d003a41107472210d2002280244210e200229023c210620022d003b2110410121114100210f0c040b200241386a200110ed03200228023c450d0b20022f013820022d003a41107472210d2002280244210e200229023c210620022d003b2110410221114100210f0c030b200241386a200110ed03200228023c450d0a20022f013820022d003a41107472210d2002280244210e200229023c210620022d003b2110410321114100210f0c020b200f450d09200e2d000121042001200d417e6a22103602042001200e41026a36020020040d092010450d09200e2d000221042001200d417d6a220f3602042001200e41036a360200200441014b0d09410021100240024020040e020100010b200f4104490d0a200e35000321062001200d41796a22043602042001200e41076a36020020044104490d0a200e35000721122001200d41756a3602042001200e410b6a36020020124220862006842113410121100b200241206a41086a200241386a41086a29020037030020022002290238370320410421114100210f201321060b0b200241106a41086a2214200241206a41086a29030037030020022002290320370310200c2005470d020240200541016a22042005490d00200541017422152004201520044b1bad42247e2212422088a70d002012a7220441004e0d020b1038000b2010102f0c060b0240024020050d002004102d21070c010b2007200541246c2004103121070b2007450d03200441246e21050b2007200c41246c6a2204200e360210200420063702082004200f201041ff0171723602042004200d3b0001200420113a0000200441036a200d4110763a0000200420022903103702142004411c6a2014290300370200200b41246a210b200c41016a2204210c20042003460d050c000b0b103d000b1036000b2004200d104b000b200041003602000240200c450d002007210103400240024020012d0000220441044b0d0002400240024020040e050400010204040b2001410c6a280200450d03200141086a280200102f0c030b2001410c6a280200450d02200141086a280200102f0c020b2001410c6a280200450d01200141086a280200102f0c010b200141086a280200450d00200141046a280200102f0b200141246a2101200b415c6a220b0d000b0b2005450d012007102f0c010b2000200536020420002007360200200041086a20043602000b200241e0006a24000ba00a03077f037e057f230041d0026b2202240041002103200241003a00c8022001280204417f6a210402400240024002400240024003402004417f460d01200241a8026a20036a200128020022052d00003a0000200120043602042001200541016a3602002002200341016a22053a00c8022004417f6a21042005210320054120470d000b200241e8006a41086a200241a8026a41086a290300370300200241e8006a41106a200241a8026a41106a290300370300200241e8006a41186a200241a8026a41186a290300370300200220022903a8023703682002200110e60120022802000d022002280204210641002104200241003a00c80220012802042107417f2103034020072004460d02200241a8026a20046a200128020022082d00003a00002001200720036a3602042001200841016a3602002002200441016a22053a00c8022003417f6a21032005210420054120470d000b200241a8016a41086a200241a8026a41086a2903002209370300200241a8016a41106a200241a8026a41106a290300220a370300200241a8016a41186a200241a8026a41186a290300220b37030020024188016a41086a200937030020024188016a41106a200a37030020024188016a41186a200b370300200220022903a80222093703a801200220093703880141002104200241003a00c802200720056b210c200720036a21030340200c2004460d04200241a8026a20046a200820046a220541016a2d00003a0000200120033602042001200541026a3602002002200441016a22053a00c8022003417f6a21032005210420054120470d000b200241e8016a41086a200241a8026a41086a2903002209370300200241e8016a41106a200241a8026a41106a290300220a370300200241e8016a41186a200241a8026a41186a290300220b370300200241c8016a41086a22042009370300200241c8016a41106a2203200a370300200241c8016a41186a2205200b370300200220022903a80222093703e801200220093703c801200241a8026a200110f50320022802a8022201450d04200241c8006a41086a2208200241e8006a41086a290300370300200241c8006a41106a2207200241e8006a41106a290300370300200241c8006a41186a220c200241e8006a41186a290300370300200241286a41086a220d20024188016a41086a290300370300200241286a41106a220e20024188016a41106a290300370300200241286a41186a220f20024188016a41186a29030037030020022002290368370348200220022903880137032820022902ac022109200241086a41186a22102005290300370300200241086a41106a22052003290300370300200241086a41086a22032004290300370300200220022903c801370308200020093702082000200136020420002006360200200041106a2002290348370200200041186a2008290300370200200041206a2007290300370200200041286a200c290300370200200041306a2002290328370200200041386a200d290300370200200041c0006a200e290300370200200041c8006a200f290300370200200041e8006a2010290300370200200041e0006a2005290300370200200041d8006a2003290300370200200041d0006a20022903083702000c050b0240200341ff0171450d00200241003a00c8020b200041003602040c040b0240200441ff0171450d00200241003a00c8020b200041003602040c030b200041003602040c020b0240200441ff0171450d00200241003a00c8020b200041003602040c010b200041003602040b200241d0026a24000be00504047f017e087f057e230041f0006b220224002002200110e60102400240024002402002280200450d00200041003602000c010b20022802042203200128020441306e2204200420034b1b2205ad42307e2206422088a70d012006a72204417f4c0d010240024020040d00410821070c010b2004102d2207450d03200441306e21050b02402003450d00410021080340200241003a00682008220941016a21082001280204210a417f210b4100210402400240024002400340200a2004460d01200241c8006a20046a2001280200220c2d00003a00002001200a200b6a3602042001200c41016a3602002002200441016a220d3a0068200b417f6a210b200d2104200d4120470d000b200241286a41186a2204200241c8006a41186a290300370300200241286a41106a220b200241c8006a41106a290300370300200241286a41086a220e200241c8006a41086a29030037030020022002290348370328200a200d6b220d4110490d01200c41096a2900002106200c290001210f2001200d41706a3602042001200c41116a360200200241086a41086a220d200e290300370300200241086a41106a220a200b290300370300200241086a41186a220b20042903003703002002200229032837030820052009470d030240200941017422042008200420084b1bad42307e2210422088a70d002010a7220441004e0d030b1038000b200441ff0171450d00200241003a00680b200041003602002005450d042007102f0c040b0240024020090d002004102d21070c010b2007200941306c2004103121070b2007450d05200441306e21050b200d2903002110200a2903002111200b2903002112200229030821132007200941306c6a2204200f37032020042013370300200441286a2006370300200441186a2012370300200441106a2011370300200441086a201037030020082003470d000b0b2000200536020420002007360200200041086a20033602000b200241f0006a24000f0b103d000b1036000ba908040c7f017e057f037e23004180016b2202240002400240024002400240200141086a220328020022042001410c6a2802002205460d002001280210220628020021072006280208220841014b210903402003200441206a220a360200200241e0006a41186a200441186a290000370300200241e0006a41106a200441106a290000370300200241e0006a41086a200441086a29000037030020022004290000370360410021040240024020090d0020080e020401040b2008210b03402004200b410176220c20046a220d2007200d4105746a200241e0006a412010ea0641004a1b2104200b200c6b220b41014b0d000b0b200720044105746a200241e0006a412010ea060d02200a2104200a2005470d000b0b20004100360208200042013702002001280204450d012001280200102f0c010b200241c0006a41086a2204200241e0006a41086a290300370300200241c0006a41106a220b200241e0006a41106a290300370300200241c0006a41186a220c200241e0006a41186a29030037030020022002290360220e3703002002200e3703404120102d220f450d01200f2002290340370000200f41186a200c290300370000200f41106a200b290300370000200f41086a2004290300370000200128020421102001280200211102400240200a2005470d0041012112410121130c010b41012112410121130340200628020821032006280200210702400340200241e0006a41186a2208200a41186a290000370300200241e0006a41106a2209200a41106a290000370300200241e0006a41086a2201200a41086a2900003703002002200a290000370360200a41206a210a4100210402400240200341014b0d0020030e020301030b2003210b03402004200b410176220c20046a220d2007200d4105746a200241e0006a412010ea0641004a1b2104200b200c6b220b41014b0d000b0b200720044105746a200241e0006a412010ea060d01200a2005470d000c030b0b200241c0006a41086a2001290300220e370300200241c0006a41106a20092903002214370300200241c0006a41186a20082903002215370300200220022903602216370340200241186a220b2015370300200241106a220c2014370300200241086a220d200e37030020022016370300024020132012470d00201241016a22042012490d05201241017422072004200720044b1b220441ffffff3f712004470d05200441057422044100480d050240024020120d002004102d210f0c010b200f201241057420041031210f0b200f450d04200441057621130b200f20124105746a22042002290300370000200441186a200b290300370000200441106a200c290300370000200441086a200d290300370000201241016a2112200a2005470d000b0b02402010450d002011102f0b20002012360208200020133602042000200f3602000b20024180016a24000f0b1036000b1038000bd70704067f017e097f027e230041f0006b22032400200341206a2001200228020c2204110200024002400240024002402003280220450d00200341c8006a41106a200341206a41106a290300370300200341c8006a41086a200341206a41086a290300370300200341c8006a41186a200341206a41186a290300370300200341c8006a41206a200341206a41206a280200360200200341086a200341d4006a290200370300200341106a200341dc006a290200370300200341186a200341e4006a290200370300200320032903203703482003200329024c370300200341c8006a200120022802102205110200417f2003280248220641016a220720072006491b2208ad42287e2209422088a70d022009a72206417f4c0d024108210a02402006450d002006102d220a450d04200641286e21080b200a2003290300370300200a4201370320200a41186a200341186a220b290300370300200a41106a200341106a220c290300370300200a41086a200341086a290300370300200341206a200120041102000240024020032802200d004101210d0c010b200341c8006a410472210641c800210e4101210d0340200341c8006a41206a200341206a41206a280200360200200341c8006a41186a220f200341206a41186a290300370300200341c8006a41106a2210200341206a41106a290300370300200341c8006a41086a2211200341206a41086a29030037030020032003290320370348200341086a2207200641086a290200370300200c200641106a290200370300200b200641186a29020037030020032006290200370300200f200b2903003703002010200c29030037030020112007290300370300200320032903003703480240200d2008470d00200341206a200120051102002008417f2003280220220741016a221220122007491b6a22072008490d07200841017422122007201220074b1bad42287e2209422088a70d072009a722074100480d070240024020080d002007102d210a0c010b200a200841286c20071031210a0b200a450d06200741286e21080b200a200e6a221241606a220720032903483703002011290300210920102903002113200f290300211420124201370300200741186a2014370300200741106a2013370300200741086a2009370300200341206a20012004110200200e41286a210e200d41016a210d20032802200d000b0b2001200228020011050002402002280204450d002001102f0b2000200d360208200020083602042000200a3602000c010b2000410036020820004208370200200120022802001105002002280204450d002001102f0b200341f0006a24000f0b103d000b1036000b1038000bb8cc010d057f017e027f017e027f017e067f047e017f017e037f047e0b7f230041b00a6b2201240010fb030240024002400240024002400240024020004101460d00200141c0066a41186a22024200370300200141c0066a41106a22034200370300200141c0066a41086a22044200370300200142003703c00641aa87ca00ad4280808080c000841001220529000021062004200541086a290000370300200120063703c0062005102f41ce87ca00ad4280808080b00184100122052900002106200141d8036a41086a2207200541086a290000370300200120063703d8032005102f200320012903d8032206370300200141b8056a41086a22082004290300370300200141b8056a41106a2006370300200141b8056a41186a2007290300370300200120012903c0063703b805200141b8036a200141b8056a10e301420020012903c003420020012802b8031b220610fc037d220920092006561b42c801540d00200141e0086a41186a220a4200370300200141e0086a41106a220b4200370300200141e0086a41086a22074200370300200142003703e008419c9eca00ad4280808080f00084220c1001220d290000210620014198046a41086a2205200d41086a2900003703002001200637039804200d102f2007200529030037030020012001290398043703e00841a39eca00ad4280808080c001841001220d29000021062005200d41086a2900003703002001200637039804200d102f200b2001290398042206370300200141e0076a41086a220e2007290300370300200141e0076a41106a220f2006370300200141e0076a41186a22102005290300370300200120012903e0083703e007200141b0036a200141e0076a412010950120012802b403211120012802b0032112200a4200370300200b420037030020074200370300200142003703e008200c1001220d29000021062005200d41086a2900003703002001200637039804200d102f2007200529030037030020012001290398043703e00841af9eca00ad4280808080d001841001220d29000021062005200d41086a2900003703002001200637039804200d102f200b2001290398042206370300200e2007290300370300200f200637030020102005290300370300200120012903e0083703e007200141e0076a10f702210a10ae03200242003703002003420037030020044200370300200142003703c00641eba1ca00ad4280808080f0008422091001220529000021062004200541086a290000370300200120063703c0062005102f41adcac800ad42808080809001841001220529000021062008200541086a290000370300200120063703b8052005102f200320012903b8052206370300200141e8036a41086a2004290300370300200141e8036a41106a2006370300200141e8036a41186a2008290300370300200120012903c0063703e803410021082011410020121b210d200141e0086a200141e8036a10fd03024002400240024020012903e00822064202510d00200b280200210220012903e8082113200910012204290000210920014188046a41086a2205200441086a29000037030020012009370388042004102f41dca0ca00ad4280808080d00284100122042900002109200141d8036a41086a2207200441086a290000370300200120093703d8032004102f2001200241016a3602e008200141e0086aad22144280808080c00084100322042900002109200441086a2900002115200441106a2900002116200141c0066a41186a220e200441186a290000370300200141c0066a41106a220f2016370300200141c0066a41086a22102015370300200120093703c0062004102f41c000102d2204450d052004200129038804370000200441086a2005290300370000200420012903d803370010200441186a2007290300370000200420012903c006370020200441286a2010290300370000200441306a200f290300370000200441386a200e290300370000200141a8036a200441c00010950120012802ac03210720012802a80321052004102f20054101470d0020064201520d002007200d41016a470d00200141b8056a41186a220f4200370300200141b8056a41106a22074200370300200141b8056a41086a22054200370300200142003703b80541d5a2ca00ad42808080809001841001220429000021062005200441086a290000370300200120063703b8052004102f41ecb0c000ad4280808080308410012204290000210620014188046a41086a220e200441086a29000037030020012006370388042004102f2007200129038804220637030020014198046a41086a2211200529030037030020014198046a41106a2212200637030020014198046a41186a2217200e290300370300200120012903b8053703980420014198036a20014198046a10e30120012903a0032118200128029803211941eba1ca00ad4280808080f000841001220429000021062005200441086a290000370300200120063703b8052004102f41f5cac800ad4280808080e00184100122042900002106200e200441086a29000037030020012006370388042004102f200120023602e00820144280808080c00084100322042900002106200441086a2900002109200441106a2900002115200141e0066a41186a2210200441186a290000370300200141e0066a41106a221a2015370300200141e0066a41086a221b2009370300200120063703e0062004102f41c000102d2204450d05200420012903b8053700002004200129038804370010200420012903e006370020200441086a2005290300370000200441186a200e290300370000200441286a201b290300370000200441306a201a290300370000200441386a201029030037000020014180036a200441c000109c0120014180036a41106a2903002115200129038803211620012802800321102004102f200f42003703002007420037030020054200370300200142003703b80541e7a2ca00ad42808080808001841001220429000021062005200441086a290000370300200120063703b8052004102f41ecb5c600ad4280808080d00184100122042900002106200e200441086a29000037030020012006370388042004102f2007200129038804370000200741086a200e29030037000020112005290300370300201220072903003703002017200f290300370300200120012903b80537039804200141e8026a20014198046a4120109c01200141d8026a20012903f002420020012802e80222041b2209200141e8026a41106a290300420020041b2206428094ebdc03420010ee06200141c8026a20012903d802221c200141d8026a41086a290300221d4280ec94a37c427f10ed0620062015420020101b22152016420020101b2216200956201520065620152006511b22041b21062009201620041b211620012903c80220097c211e2018420020191b20137d2209428086ebc7f5002009428086ebc7f500541b421f8042ffffffff0f83428094ebdc037e429880b5e5038021134100210541d87d2104024002400340200141b8026a201c201d200441e8acc3006a3502002209420010ed062005201620012903b80222152009201e7e22092009428094ebdc038022094280ec94a37c7e7c4280cab5ee01562009a76aad7c22095a2006200141b8026a41086a2903002009201554ad7c22155a200620155122071b6a21052016200954200620155420071b0d01200441086a22040d000b200141a8026a201c201d42e8aafa0b420010ed06200141b0026a29030020012903a8022209201e42e8aafa0b7e22062006428094ebdc038022064280ec94a37c7e7c4280cab5ee01562006a76aad7c2206200954ad7c21090c010b02402005417f6a220420054d0d00200141a8016a201c201d42c0f0f50b420010ed06200141b0016a29030020012903a8012209201e42c0f0f50b7e201e42288022064280ec94a37c7e7c4280cab5ee01562006a76aad7c2206200954ad7c21090c010b200441244b0d0220014198026a201c201d2004410374220741c0aac3006a280200220ead2209420010ed06200141f8016a201620012903980222152009201e7e22092009428094ebdc038022094280ec94a37c7e7c4280cab5ee01562009a76aad7c22092016200956200620014198026a41086a2903002009201554ad7c22155620062015511b22041b22182009201620041b22097d221f2006201520041b2015200620041b7d2018200954ad7d41002005410374220f41c0aac3006a2802002205200e6b220e200e20054b1b22054101200541014b1bad2215420010ee06200141e8016a20012903f8012206200141f8016a41086a29030022092015420010ed0620014188026a201c201d200741c4aac3006a2802002205ad2218420010ed06200141b8016a20094200200f41c4aac3006a28020022072005200720054b220e1b20052007200e1b6bad2216420010ed06200141d8016a200642002016420010ed06200141c8016a420042002006420010ed06427f20014188026a41086a29030020012903880222092018201e7e22062006428094ebdc038022064280ec94a37c7e7c4280cab5ee01562006a76aad7c2206200954ad7c2209427f427f200141d8016a41086a290300221e20012903b80120012903c8017c7c221c20012903c00120012903d00184420052201c201e5472220e1b221c427f20012903d801200e1b221e201f20012903e8017d20167e2015807c2215201e54220ead7c2216200e2016201c542015201e5a1b220e1b221e7c2006427f2015200e1b22157c221c200654220ead7c2216200e201620095420162009511b220e1b42002009201e7d2006201554ad7d2216200620157d2215200656201620095620162009511b220f1b2004200720054d7322041b2109427f201c200e1b42002015200f1b20041b21060b20014198016a20062009428094ebdc03420010ee0620014188016a200129039801220920014198016a41086a29030022154280ec94a37c427f10ed0641eba1ca00ad4280808080f00084100122042900002116200141b8056a41086a2205200441086a290000370300200120163703b8052004102f4197cfc800ad4280808080b0028410012204290000211620014188046a41086a2207200441086a29000037030020012016370388042004102f200120023602e00820144280808080c00084100322042900002116200441086a290000211e200441106a290000211c200141e0066a41186a2202200441186a290000370300200141e0066a41106a220e201c370300200141e0066a41086a220f201e370300200120163703e0062004102f200129038801211641c000102d2204450d05200141f8006a200920152013420010ed06200420012903b8053700002004200129038804370010200420012903e006370020200441086a2005290300370000200441186a2007290300370000200441286a200f290300370000200441306a200e290300370000200441386a20022903003700002001200129037822092013200620167c7e22062006428094ebdc038022064280ec94a37c7e7c4280cab5ee01562006a76aad7c22063703e0082001200141f8006a41086a2903002006200954ad7c3703e8082004ad42808080808008842014428080808080028410042004102f0b200141e0086a41186a22024200370300200141e0086a41106a220e4200370300200141e0086a41086a22054200370300200142003703e008200c10012207290000210620014198046a41086a2204200741086a29000037030020012006370398042007102f2005200429030037030020012001290398043703e00841b0ebc300ad4280808080a001841001220729000021062004200741086a29000037030020012006370398042007102f200b200129039804370000200b41086a2004290300370000200141e0076a41086a2005290300370300200141e0076a41106a200e290300370300200141e0076a41186a2002290300370300200120012903e0083703e0072001412036028c042001200141e0076a36028804200141e0066a200141e0076aad42808080808004842216100210730240024020012802e00622020d000c010b20012802e406210e2001200141e0066a41086a2802003602ec03200120023602e803200141f0006a200141e8036a10e6010240024020012802700d002001280274221020012802ec03220741a0016e2204200420104b1b2211ad42a0017e2206422088a70d082006a72204417f4c0d080240024020040d00410121080c010b2004102d2208450d08200441a0016e21110b02402010450d00200141e0086a41206a2117200141b8056a41017221194100210f0340200141003a00d805200f41016a2112410021040240024002400240024002400340200141003a00d80320072004460d01200141b8056a20046a20012802e80322052d00003a00002001200541016a3602e8032001200441016a22053a00d8052005210420054120470d000b200141c0066a41086a2204200141b8056a41086a290300370300200141c0066a41106a221a200141b8056a41106a290300370300200141c0066a41186a221b200141b8056a41186a290300370300200120012903b8053703c0062001200720056b3602ec03200141b8056a200141e8036a10ee0220012d00b8054101460d01200141e0086a41186a201b290300370300200141e0086a41106a201a290300370300200141e0086a41086a2004290300370300200120012903c0063703e0082017201941800110e8061a20014198046a200141e0086a41a00110e8061a2011200f470d04200f41017422042012200420124b1bad42a0017e2206422088a70d132006a722044100480d13200f0d022004102d21080c030b200141003602ec03200441ff0171450d00200141003a00d8050b20110d030c060b2008200f41a0016c2004103121080b2008450d0b200441a0016e21110b2008200f41a0016c6a20014198046a41a00110e8061a20122010460d0220012802ec0321072012210f0c010b0b2008102f0c010b2010ad4220862011ad84210620080d010b41002108200141003602a00420014201370398042001410b3602bc05200120014188046a3602b805200120014198046a3602c006200141f4086a4101360200200142013702e408200141b885c7003602e0082001200141b8056a3602f008200141c0066a41d8dbc100200141e0086a103c1a20013502a004422086200135029804841008200128029c04450d00200128029804102f0b200e450d002002102f0b41002107410021204101212102402006420020081b221c422088a7221a41a0016c220e450d00200e41a0016e2220410574102d2221450d050b200a200a41ff01714102477121222008410120081b21230240201a450d00201a41a0016c2108410021072021210420232105034020042005290000370000200441186a200541186a290000370000200441106a200541106a290000370000200441086a200541086a290000370000200741016a2107200441206a2104200541a0016a2105200841e07e6a22080d000b0b200141e0086a41186a22024200370300200141e0086a41106a22084200370300200141e0086a41086a22054200370300200142003703e008419c9eca00ad4280808080f0008422061001220a290000210920014198046a41086a2204200a41086a2900003703002001200937039804200a102f2005200429030037030020012001290398043703e00841a5c6c800ad4280808080a001841001220a29000021092004200a41086a2900003703002001200937039804200a102f200b200129039804370000200b41086a220a2004290300370000200141e0076a41086a220f2005290300370300200141e0076a41106a22102008290300370300200141e0076a41186a22112002290300370300200120012903e0083703e007200141203602e4082001200141e0076a3602e00820212007200141e0086a10aa0102402022450d00200242003703002008420037030020054200370300200142003703e00820061001220729000021092004200741086a29000037030020012009370398042007102f2005200429030037030020012001290398043703e00841bc9eca00ad4280808080a002841001220729000021092004200741086a29000037030020012009370398042007102f200b200129039804370000200a2004290300370000200f20052903003703002010200829030037030020112002290300370300200120012903e0083703e007200141e0086a200141e0076a10fe0320012802e0082207450d002016100520012802e408450d002007102f0b200242003703002008420037030020054200370300200142003703e00820061001220729000021062004200741086a29000037030020012006370398042007102f2005200429030037030020012001290398043703e00841a39eca00ad4280808080c001841001220729000021062004200741086a29000037030020012006370398042007102f200b200129039804370000200a2004290300370000200f20052903003703002010200829030037030020112002290300370300200120012903e0083703e0072001200d41016a221b3602e0082016200141e0086aad220c4280808080c0008422061004200141b8056a41186a4200370300200141b8056a41106a22054200370300200141b8056a41086a22074200370300200142003703b80541eba1ca00ad4280808080f0008422091001220229000021152007200241086a290000370300200120153703b8052002102f41adcac800ad428080808090018410012202290000211520014188046a41086a220a200241086a29000037030020012015370388042002102f200520012903880422153703002004200729030037030020014198046a41106a201537030020014198046a41186a200a290300370300200120012903b80537039804200141e0086a20014198046a10fd032008280200210720012903e00821152009100122042900002109200a200441086a29000037030020012009370388042004102f41dca0ca00ad4280808080d00284100122042900002109200141d8036a41086a200441086a290000370300200120093703d8032004102f20014100200741016a20154202511b3602e0082006100322042900002106200441086a2900002109200441106a2900002115200141c0066a41186a200441186a290000370300200141c0066a41106a2015370300200141c0066a41086a2009370300200120063703c0062004102f41c000102d2204450d042004200129038804370000200441086a20014188046a41086a2207290300370000200420012903d803370010200441186a200141d8036a41086a290300370000200420012903c006370020200441286a200141c0066a41086a290300370000200441306a200141c0066a41106a290300370000200441386a200141c0066a41186a290300370000200141e8006a200441c000109501200128026c2102200128026821082004102f024020084101470d0002402002201b460d002002201b4f0d0141ebc7c800ad428080808080068410080b201b10ff030b200141b8056a41186a22024200370300200141b8056a41106a220a4200370300200141b8056a41086a22044200370300200142003703b80541eba1ca00ad4280808080f0008422091001220829000021062007200841086a29000037030020012006370388042008102f2004200729030037030020012001290388043703b80541d2a0ca00ad4280808080a001841001220829000021062007200841086a29000037030020012006370388042008102f2005200129038804370000200541086a200729030037000020014198046a41086a200429030037030020014198046a41106a200a29030037030020014198046a41186a2002290300370300200120012903b80537039804200141e0006a20014198046a4120109501200d41026a2107024020012802604101460d00200141c8036a20071080040c030b20012802642108200910012204290000210620014188046a41086a2202200441086a29000037030020012006370388042004102f41dca0ca00ad4280808080d00284100122042900002106200141d8036a41086a220d200441086a290000370300200120063703d8032004102f200120083602e008200c4280808080c00084100322042900002106200441086a2900002109200441106a2900002115200141c0066a41186a2208200441186a290000370300200141c0066a41106a220a2015370300200141c0066a41086a220f2009370300200120063703c0062004102f41c000102d2204450d042004200129038804370000200441086a2002290300370000200420012903d803370010200441186a200d290300370000200420012903c006370020200441286a200f290300370000200441306a200a290300370000200441386a2008290300370000200141d8006a200441c000109501200128025c210f200128025821082004102f024020080d0041aacfc800ad4280808080e0068410084100210f0b200141b8056a41186a220d4200370300200141b8056a41106a220a4200370300200141b8056a41086a22084200370300200142003703b80541eba1ca00ad4280808080f0008410012202290000210620014188046a41086a2204200241086a29000037030020012006370388042002102f2008200429030037030020012001290388043703b80541f1a0ca00ad42808080808001841001220229000021062004200241086a29000037030020012006370388042002102f2005200129038804370000200541086a200429030037000020014198046a41086a200829030037030020014198046a41106a200a29030037030020014198046a41186a200d290300370300200120012903b80537039804410020014198046a1081042204200441ff01714104461b41ff0171220441034b0d0102400240024020040e0401000402010b200141b8056a41186a220d4200370300200141b8056a41106a220a4200370300200141b8056a41086a22084200370300200142003703b80541eba1ca00ad4280808080f0008410012202290000210620014188046a41086a2204200241086a29000037030020012006370388042002102f2008200429030037030020012001290388043703b80541f1a0ca00ad42808080808001841001220229000021062004200241086a29000037030020012006370388042002102f2005200129038804370000200541086a200429030037000020014198046a41086a200829030037030020014198046a41106a200a29030037030020014198046a41186a200d290300370300200120012903b8053703980420014198046aad428080808080048410050c010b2007200f6b220420074b0d0220044106490d020b200141c8036a20071080040c020b41f0bdc60020044125103b000b200141003602c8030b2023200e6a21240240024020012802c80322250d00200141e0086a41186a4200370300200141e0086a41106a22074200370300200141e0086a41086a22044200370300200142003703e008419c9eca00ad4280808080f000841001220529000021062004200541086a290000370300200120063703e0082005102f41a5c6c800ad4280808080a00184100122052900002106200141b8056a41086a2208200541086a290000370300200120063703b8052005102f200720012903b805220637030020014198046a41086a200429030037030020014198046a41106a200637030020014198046a41186a2008290300370300200120012903e00837039804200141e0086a20014198046a412010aa0220012902e408420020012802e00822041b21062004410120041b2125410021260c010b4101212620012902cc0321060b200120263a00a00a200120243602dc03200120233602d8032001200141d8036a36028c042001200141a00a6a3602880441002117024002402006422088a7220441057422050d0041012111410021270c010b2005410575ad42a0017e2209422088a70d062009a722054100480d062005102d2211450d02200541a0016e21270b2006a7212802402004450d002004410574220741606a410576212920014198046a4101722110200141e0086a41206a2112200141e0066a41e0006a212a200141e0066a41c0006a2119200141e0066a41206a211720112108202521040340200441086a2900002106200441106a290000210920042900002115200141c0066a41186a2202200441186a290000370300200141c0066a41106a220d2009370300200141c0066a41086a220a2006370300200120153703c006200141e8036a200141c0066a10820320014198046a20012802e803220f20012802f00310830320012d009804210e200141b8056a201041800110e8061a410021050240200e4101470d00200141e0076a200141b8056a41800110e8061a410121050b024020012802ec03450d00200f102f0b0240024020050d00200141e0066a410041800110e7061a0c010b200141e0066a200141e0076a41800110e8061a0b02402001280288042d00000d00200128028c04220e2802002205200e280204460d00200e200541a0016a36020002400240200141e0066a200541206a220e460d00200e200141e0066a412010ea060d010b02402017200541c0006a220e460d00200e2017412010ea060d010b02402019200541e0006a220e460d00200e2019412010ea060d010b202a20054180016a2205460d012005202a412010ea06450d010b20012802880441013a00000b200441206a2104200141e0086a41186a2002290300370300200141e0086a41106a200d290300370300200141e0086a41086a200a290300370300200120012903c0063703e0082012200141e0066a41800110e8061a2008200141e0086a41a00110e80641a0016a2108200741606a22070d000b202941016a21170b02402028450d002025102f0b2017ad42a0017e2206422088a70d022006a72204417f4c0d0220012d00a00a21250240024002400240024020040d002011201741a0016c6a210e4101210f201721190c010b2004102d220f450d052011201741a0016c6a210e200441a0016e221920174f0d00201941017422052017200520174b1b221041a0016c22054100480d09024002402004419f014b0d002005102d210f0c010b200f201941a0016c20051031210f0b200f450d050c010b2017450d01201921100b200141e0086a4180016a2105200141e0086a41e0006a2107200141e0086a41c0006a2108200141e0086a41206a21024100210d4100210a0340200141e0086a41186a2011200d6a220441186a290000370300200141e0086a41106a200441106a290000370300200141e0086a41086a200441086a290000370300200120042900003703e008200241186a200441386a290000370000200241106a200441306a290000370000200241086a200441286a2900003700002002200441206a2900003700002008200441c0006a290000370000200841086a200441c8006a290000370000200841106a200441d0006a290000370000200841186a200441d8006a2900003700002007200441e0006a290000370000200741086a200441e8006a290000370000200741106a200441f0006a290000370000200741186a200441f8006a290000370000200520044180016a290000370000200541086a20044188016a290000370000200541106a20044190016a290000370000200541186a20044198016a290000370000200f200d6a200141e0086a41a00110e8061a200d41a0016a210d200a41016a210a200441a0016a200e470d000b201021190c010b4100210a0b200141e0086a41186a22084200370300200141e0086a41106a22024200370300200141e0086a41086a22054200370300200142003703e008419c9eca00ad4280808080f0008410012207290000210620014198046a41086a2204200741086a29000037030020012006370398042007102f2005200429030037030020012001290398043703e00841b0ebc300ad4280808080a001841001220729000021062004200741086a29000037030020012006370398042007102f200b200129039804370000200b41086a2004290300370000200141e0076a41086a2005290300370300200141e0076a41106a2002290300370300200141e0076a41186a2008290300370300200120012903e0083703e007200a41a0016c4104722204417f4c0d022004102d2205450d01200141003602e808200120043602e408200120053602e008200a200141e0086a106902400240200a0d0020012802e808210420012802e408210820012802e00821050c010b200f200a41a0016c6a2112410020012802e808220a6b210220012802e4082108410021070340200a20076a210d02400240200820026a4120490d0020012802e00821050c010b200d41206a2204200d490d08200841017422052004200520044b1b22044100480d080240024020080d002004102d21050c010b20012802e00820082004103121050b2005450d04200120043602e408200120053602e008200421080b2005200a6a20076a220e41086a200f20076a220441086a290000370000200e41106a200441106a290000370000200e41186a200441186a2900003700002001200d41206a22103602e808200e200429000037000002400240200820026a41606a411f4d0d002008210e0c010b201041206a220e2010490d0820084101742210200e2010200e4b1b220e4100480d080240024020080d00200e102d21050c010b20052008200e103121050b2005450d042001200e3602e408200120053602e0080b2005200a6a20076a220841286a200441286a290000370000200841306a200441306a290000370000200841386a200441386a2900003700002001200d41c0006a22103602e808200841206a200441206a29000037000002400240200e20026a41406a411f4d0d00200e21080c010b201041206a22082010490d08200e41017422102008201020084b1b22084100480d0802400240200e0d002008102d21050c010b2005200e2008103121050b2005450d04200120083602e408200120053602e0080b2005200a6a20076a220e41c8006a200441c8006a290000370000200e41d0006a200441d0006a290000370000200e41d8006a200441d8006a2900003700002001200d41e0006a22103602e808200e41c0006a200441c0006a29000037000002400240200820026a41a07f6a411f4d0d002008210e0c010b201041206a220e2010490d0820084101742210200e2010200e4b1b220e4100480d080240024020080d00200e102d21050c010b20052008200e103121050b2005450d042001200e3602e408200120053602e0080b2005200a6a20076a220841e8006a200441e8006a290000370000200841f0006a200441f0006a290000370000200841f8006a200441f8006a2900003700002001200d4180016a22103602e808200841e0006a200441e0006a29000037000002400240200e20026a41807f6a411f4d0d00200e21080c010b201041206a22082010490d08200e41017422102008201020084b1b22084100480d0802400240200e0d002008102d21050c010b2005200e2008103121050b2005450d04200120083602e408200120053602e0080b2005200a6a20076a220e4188016a20044188016a290000370000200e4190016a20044190016a290000370000200e4198016a20044198016a2900003700002001200d41a0016a3602e808200e4180016a20044180016a290000370000200241e07e6a2102200741a0016a2107200441a0016a2012470d000b200a20076a21040b20162004ad4220862005ad84100402402008450d002005102f0b02402019450d00200f102f0b200141e0086a41186a22084200370300200141e0086a41106a22024200370300200141e0086a41086a22054200370300200142003703e008419c9eca00ad4280808080f0008410012207290000210620014198046a41086a2204200741086a29000037030020012006370398042007102f2005200429030037030020012001290398043703e00841af9eca00ad4280808080d001841001220729000021062004200741086a29000037030020012006370398042007102f200b200129039804370000200b41086a2004290300370000200141e0076a41086a2005290300370300200141e0076a41106a2002290300370300200141e0076a41186a2008290300370300200120012903e0083703e007200120253a00e0082016200c4280808080108410042001201b3602e408200141053a00e00841c8e1ca004100200141e0086a108c014108102d2207450d0120072024360204200720233602000240024020220d00200141e0086a41186a220d4200370300200141e0086a41106a22084200370300200141e0086a41086a22044200370300200142003703e00841b89bca00ad4280808080f00184100122022900002106200141b8056a41086a2205200241086a290000370300200120063703b8052002102f20042005290300370300200120012903b8053703e00841ac9bca00ad4280808080c001841001220229000021062005200241086a290000370300200120063703b8052002102f200820012903b805220637030020014198046a41086a220a200429030037030020014198046a41106a220e200637030020014198046a41186a220f2005290300370300200120012903e00837039804200141c8006a20014198046a10e3012001290350210620012802482110200d42003703002008420037030020044200370300200142003703e008419c9eca00ad4280808080f000841001220229000021092004200241086a290000370300200120093703e0082002102f41a39eca00ad4280808080c001841001220229000021092005200241086a290000370300200120093703b8052002102f200820012903b8052209370300200a2004290300370300200e2009370300200f2005290300370300200120012903e00837039804200141c0006a20014198046a41201095012006420020101b2001280244410020012802401b1082042007102f0c010b024002400240201a450d002007202341a0016a360200200141003a008009202341206a2105410021040340200141003a00d803200141e0086a20046a200520046a2d00003a00002001200441016a22043a00800920044120470d000b20014198046a41086a2204200141e0086a41086a29030037030020014198046a41106a2205200141e0086a41106a29030037030020014198046a41186a2208200141e0086a41186a290300370300200120012903e008370398042023450d00200141b8056a41186a2008290300370300200141b8056a41106a2005290300370300200141b8056a41086a200429030037030020012001290398043703b805200728020420072802006b41a0016e41016a220241286c2204417f4c0d062004102d220d450d05200d20012903b805370300200d4201370320200d41186a200141b8056a41186a290300370300200d41106a200141b8056a41106a290300370300200d41086a200141b8056a41086a2903003703000240200728020022042007280204470d00410121080c020b2007200441a0016a360200200141003a008009200441206a2105410021040340200141003a00d803200141e0086a20046a200520046a2d00003a00002001200441016a22043a00800920044120470d000b200141c0066a41186a220b200141e0086a41186a2219290300220637030020014198046a41086a220a200141e0086a41086a221a29030037030020014198046a41106a220e200141e0086a41106a221b29030037030020014198046a41186a220f2006370300200120012903e00837039804410121080340200141b8056a41186a200f2903002206370300200141b8056a41106a200e2903002209370300200141b8056a41086a200a2903002215370300200120012903980422163703b805200141e8036a41186a22052006370300200141e8036a41106a22102009370300200141e8036a41086a22122015370300200120163703e803024020022008470d00200728020420072802006b41a0016e20026a41016a22042002490d0b200241017422252004202520044b1bad42287e2206422088a70d0b2006a722044100480d0b0240024020020d002004102d210d0c010b200d200241286c20041031210d0b200d450d07200441286e21020b200d200841286c6a220420012903e80337030020122903002106201029030021092005290300211520044201370320200441186a2015370300200441106a2009370300200441086a2006370300200841016a2108200728020022052007280204460d022007200541a0016a36020041002104200141003a008009200541206a21050340200141003a00d803200141e0086a20046a200520046a2d00003a00002001200441016a22043a00800920044120470d000b200b20192903002206370300200a201a290300370300200e201b290300370300200f2006370300200120012903e008370398040c000b0b2007102f4108210d41002108410021020c010b2007102f0b200141e0086a41186a4200370300200141e0086a41106a220a4200370300200141e0086a41086a22054200370300200142003703e00841b89bca00ad4280808080f00184100122072900002106200141b8056a41086a2204200741086a290000370300200120063703b8052007102f20052004290300370300200120012903b8053703e00841ddc3c600ad4280808080f000841001220729000021062004200741086a290000370300200120063703b8052007102f200a20012903b805220637030020014198046a41086a200529030037030020014198046a41106a200637030020014198046a41186a2004290300370300200120012903e00837039804200141e0086a20014198046a1083040240024020012802e0084101460d00200120083602e808200120023602e4082001200d3602e00820014198046a200141e0086a41004100200110840420014198046aad428080808080048421060c010b20014198046aad42808080808004842206100520012902e4082109200120083602e808200120023602e4082001200d3602e00820014198046a200141e0086a2009a741012009422088a71084040b200141e0086a41186a22084200370300200141e0086a41106a22074200370300200141e0086a41086a22054200370300200142003703e00841b89bca00ad4280808080f001842209100122022900002115200141b8056a41086a2204200241086a290000370300200120153703b8052002102f20052004290300370300200120012903b8053703e00841ac9bca00ad4280808080c0018422151001220229000021162004200241086a290000370300200120163703b8052002102f200a20012903b805370000200a41086a2210200429030037000020014198046a41086a2202200529030037030020014198046a41106a220d200729030037030020014198046a41186a220e2008290300370300200120012903e00837039804200141306a20014198046a10e3012001280230211220012903382116200842003703002007420037030020054200370300200142003703e00820091001220f29000021092004200f41086a290000370300200120093703b805200f102f20052004290300370300200120012903b8053703e00820151001220f29000021092004200f41086a290000370300200120093703b805200f102f200a20012903b8053700002010200429030037000020022005290300370300200d2007290300370300200e2008290300370300200120012903e008370398042001201642017c420120121b22093703e0082006200c42808080808001841004200842003703002007420037030020054200370300200142003703e008419c9eca00ad4280808080f000841001220829000021062005200841086a290000370300200120063703e0082008102f41a39eca00ad4280808080c001841001220829000021062004200841086a290000370300200120063703b8052008102f200720012903b805220637030020022005290300370300200d2006370300200e2004290300370300200120012903e00837039804200141286a20014198046a41201095012009200128022c410020012802281b1082040b4108102d2204450d0120042024360204200420233602004108102d2205450d0120052011201741a0016c6a222a36020420052011360200200141800a6a200441e4c3c60010f903200141900a6a200541e4c3c60010f90320012802880a210820012802840a211020012802800a210f200141a00a6a41086a200141900a6a41086a280200360200200120012903900a3703a00a200141e0086a41186a22074200370300200141e0086a41106a220b4200370300200141e0086a41086a22054200370300200142003703e00841aa87ca00ad4280808080c00084220610012202290000210920014188046a41086a2204200241086a29000037030020012009370388042002102f2005200429030037030020012001290388043703e00841ae87ca00ad4280808080a0018422151001220229000021092004200241086a29000037030020012009370388042002102f200b2001290388042209370300200141c0066a41086a22022005290300370300200141c0066a41106a220d2009370300200141c0066a41186a220a2004290300370300200120012903e0083703c006200141186a200141c0066a10e3012001290320420020012802181b221642017c22092016540d0320074200370300200b420037030020054200370300200142003703e00820061001220e29000021162004200e41086a2900003703002001201637038804200e102f2005200429030037030020012001290388043703e00820151001220e29000021152004200e41086a2900003703002001201537038804200e102f200b200129038804370000200b41086a2212200429030037000020022005290300370300200d200b290300370300200a2007290300370300200120012903e0083703c006200120093703e008200141c0066aad4280808080800484221e200c4280808080800184100420074200370300200b420037030020054200370300200142003703e00820061001220e29000021062004200e41086a2900003703002001200637038804200e102f2005200429030037030020012001290388043703e00841b887ca00ad4280808080b001841001220e29000021062004200e41086a2900003703002001200637038804200e102f200b2001290388043700002012200429030037000020022005290300370300200d200b290300370300200a2007290300370300200120012903e0083703c006200841286c4104722204417f4c0d022004102d2205450d01200141003602e808200120043602e408200120053602e0082008200141e0086a10690240024020080d0020012802e808210420012802e408210820012802e00821070c010b200f200841286c6a210a20012802e408210820012802e8082104200f2105034002400240200820046b4120490d0020012802e00821070c010b200441206a22072004490d08200841017422022007200220074b1b22024100480d080240024020080d002002102d21070c010b20012802e00820082002103121070b2007450d04200120023602e408200120073602e008200221080b200720046a220241186a200541186a290000370000200241106a200541106a290000370000200241086a200541086a2900003700002001200441206a220d3602e80820022005290000370000200541206a2903002106024002402008200d6b4108490d00200441286a21040c010b200d41086a2204200d490d08200841017422022004200220044b1b22024100480d080240024020080d002002102d21070c010b200720082002103121070b2007450d04200120023602e408200120073602e008200221080b200120043602e8082007200d6a2006370000200a200541286a2205470d000b0b201e2004ad4220862007ad84100402402008450d002007102f0b02402010450d00200f102f0b200942017c22062009540d04200141c0066a41186a22074200370300200141c0066a41106a22084200370300200141c0066a41086a22044200370300200142003703c00641aa87ca00ad4280808080c0008410012202290000210920014188046a41086a2205200241086a29000037030020012009370388042002102f2004200529030037030020012001290388043703c00641e387ca00ad4280808080e001841001220229000021092005200241086a29000037030020012009370388042002102f2003200129038804370000200341086a2005290300370000200141e8036a41086a2004290300370300200141e8036a41106a2008290300370300200141e8036a41186a2007290300370300200120012903c0063703e803200141e0086a200141e8036a10850420012d00e00821052007200141f9086a2900003703002008200141f1086a2900003703002004200141e9086a290000370300200120012900e1083703c0060240024020054101460d0020014198046a41186a420037030020014198046a41106a420037030020014198046a41086a420037030020014200370398040c010b20014198046a41186a200729030037030020014198046a41106a200829030037030020014198046a41086a2004290300370300200120012903c006370398040b200141c0066a41186a22074200370300200141c0066a41106a22084200370300200141c0066a41086a22054200370300200142003703c00641aa87ca00ad4280808080c00084220910012202290000211520014188046a41086a2204200241086a29000037030020012015370388042002102f2005200429030037030020012001290388043703c00641f187ca00ad4280808080c0018422151001220229000021162004200241086a29000037030020012016370388042002102f2003200129038804370000200341086a220d2004290300370000200141e8036a41086a220a2005290300370300200141e8036a41106a220e2008290300370300200141e8036a41186a220f2007290300370300200120012903c0063703e803200141106a200141e8036a41201095012001280214211020012802102112200742003703002008420037030020054200370300200142003703c00620091001220229000021092004200241086a29000037030020012009370388042002102f2005200429030037030020012001290388043703c00620151001220229000021092004200241086a29000037030020012009370388042002102f2003200129038804370000200d2004290300370000200a2005290300370300200e2008290300370300200f2007290300370300200120012903c0063703e803200141003602e008200141e8036aad4280808080800484221d200c4280808080c000841004200141b8056a41186a20014198046a41186a290300370300200141b8056a41106a20014198046a41106a290300370300200141b8056a41086a20014198046a41086a29030037030020012001290398043703b805417f2010410020121b221041016a220420042010491b410d744128722219417f4c0d022019102d2212450d01201220012903b80537000020122006370020201241186a200141b8056a41186a290300370000201241106a200141b8056a41106a290300370000201241086a200141b8056a41086a290300370000200141ac0a6aad4280808080c000842116412821174100210541002104024002400340024002400240024002402007200d460d0020040d010b034020042108200520104f0d0241aa87ca00ad4280808080c00084100122042900002106200141d8036a41086a2207200441086a290000370300200120063703d8032004102f41fd87ca00ad428080808090028410012204290000210620014188046a41086a2202200441086a29000037030020012006370388042004102f200120053602ac0a20161003220441086a2900002106200441106a290000210920042900002115200141c0066a41186a220d200441186a290000370300200141c0066a41106a220a2009370300200141c0066a41086a220e2006370300200120153703c0062004102f41c000102d2204450d09200420012903d803370000200441086a20072903003700002004200129038804370010200441186a2002290300370000200420012903c006370020200441286a200e290300370000200441306a200a290300370000200441386a200d290300370000200141c0066a200441c000108604024020012802c0062207450d002004ad428080808080088410050b20012902c40621062004102f2007410120071b2204450d022006420020071b2206422088a7210702402008450d00200f450d002008102f0b200541016a21052006a7210f2007450d000b200420074105746a210d200421070b200141e8036a41186a200741186a2208290000370300200141e8036a41106a200741106a2202290000370300200141e8036a41086a200741086a220a290000370300200120072900003703e803200a29000021062002290000210920072900002115200141e0086a41186a22022008290000370300200141e0086a41106a22082009370300200141e0086a41086a220a2006370300200120153703e008200141c0066a41186a220e2002290300370300200141c0066a41106a221a2008290300370300200141c0066a41086a221b200a290300370300200120012903e0083703c006201920176b411f4d0d01201921020c020b02402008450d00200f450d002008102f0b2017ad4220862012ad84100322042900002106200441086a2900002109200441106a2900002115200141e0076a41186a200441186a290000370300200141e0076a41106a2015370300200141e0076a41086a2009370300200120063703e0072004102f02402019450d002012102f0b200141c0066a41186a22084200370300200141c0066a41106a22024200370300200141c0066a41086a22054200370300200142003703c00641aa87ca00ad4280808080c00084220610012207290000210920014188046a41086a2204200741086a29000037030020012009370388042007102f2005200429030037030020012001290388043703c00641e387ca00ad4280808080e001841001220729000021092004200741086a29000037030020012009370388042007102f2003200129038804370000200341086a2004290300370000200141e8036a41086a2005290300370300200141e8036a41106a2002290300370300200141e8036a41186a2008290300370300200120012903c0063703e8034120102d2204450d06200420012903e007370000200441186a200141e0076a41186a290300370000200441106a200141e0076a41106a290300370000200441086a200141e0076a41086a290300370000201d2004ad428080808080048410042004102f200141e0066a41186a20014198046a41186a220d2903002209370300200141e0066a41106a20014198046a41106a220a2903002215370300200141e0066a41086a20014198046a41086a220e29030022163703002001200129039804221d3703e006200d2009370300200a2015370300200e20163703002001201d37039804200141e0086a41186a22084200370300200141e0086a41106a22024200370300200141e0086a41086a22074200370300200142003703e008200610012205290000210620014188046a41086a2204200541086a29000037030020012006370388042005102f2007200429030037030020012001290388043703e00841d987ca00ad4280808080a001841001220529000021062004200541086a29000037030020012006370388042005102f200b200129038804370000200b41086a22172004290300370000200141c0066a41086a220f2007290300370300200141c0066a41106a22102002290300370300200141c0066a41186a22122008290300370300200120012903e0083703c0064120102d2205450d062005200129039804370000200541186a200d290300370000200541106a200a290300370000200541086a200e290300370000201e2005ad428080808080048410042005102f200842003703002002420037030020074200370300200142003703e00841aa87ca00ad4280808080c000841001220529000021062004200541086a29000037030020012006370388042005102f2007200429030037030020012001290388043703e00841e387ca00ad4280808080e001841001220529000021062004200541086a29000037030020012006370388042005102f200b20012903880437000020172004290300370000200f20072903003703002010200229030037030020122008290300370300200120012903e0083703c006200141e0086a200141c0066a10850420012d00e00821042012200141f9086a2900003703002010200141f1086a290000370300200f200141e9086a290000370300200120012900e1083703c00620044101460d03200141d0056a4200370300200141c8056a4200370300200141c0056a4200370300200142003703b8050c040b201741206a22082017490d09201941017422022008200220084b1b22024100480d090240024020190d002002102d21120c010b201220192002103121120b2012450d050b200741206a2107201220176a220820012903c006370000200841186a200e290300370000200841106a201a290300370000200841086a201b290300370000201741206a2117200221190c000b0b200141b8056a41186a200141c0066a41186a290300370300200141b8056a41106a200141c0066a41106a290300370300200141b8056a41086a200141c0066a41086a290300370300200120012903c0063703b8050b20014198046a41086a2204200141a00a6a41086a28020036020020014198046a41246a200141b8056a41186a29030037020020014198046a411c6a200141b8056a41106a29030037020020014198046a41146a200141b8056a41086a290300370200200120012903a00a220637039804200120012903b8053702a4042001418c096a200141c0046a280200360200200141e0086a41246a200141b8046a290300370200200141e0086a411c6a20014198046a41186a290300370200200141e0086a41146a20014198046a41106a290300370200200141ec086a2004290300370200200120063702e408200141003602e008200141e0086a1087044108102d2207450d0120072024360204200720233602004108102d2225450d012025202a3602042025201136020020014198046a41186a420037030020014198046a41106a2228420037030020014198046a41086a220542003703002001420037039804418de6c300ad4280808080e000841001220429000021062005200441086a29000037030020012006370398042004102f419ce6c300ad4280808080e0008410012208290000210620014188046a41086a2204200841086a29000037030020012006370388042008102f20282001290388042206370300200141e0086a41086a2005290300370300200141e0086a41106a2006370300200141e0086a41186a200429030037030020012001290398043703e008200141086a200141e0086a412010950120012802082102200128020c210d200141c0066a41186a220a4200370300200141c0066a41106a220e4200370300200141c0066a41086a22054200370300200142003703c00641d39bca00ad42808080808001841001220829000021062004200841086a29000037030020012006370388042008102f2005200429030037030020012001290388043703c00641bdc5c300ad4280808080e00184100122042900002106200141d8036a41086a2208200441086a290000370300200120063703d8032004102f200320012903d803370000200341086a2008290300370000200141b8056a41086a2005290300370300200141b8056a41106a200e290300370300200141b8056a41186a200a290300370300200120012903c0063703b8052001200d41e4006a41e40020021b3602e008200141b8056aad4280808080800484221e200c4280808080c00084100402400240200728020022042007280204460d002007200441a0016a360200200141003a008009200441e0006a2105410021040340200141003a00d803200141e0086a20046a200520046a2d00003a00002001200441016a22043a00800920044120470d000b200141e0076a41086a2204200141e0086a41086a290300370300200141e0076a41106a2205200141e0086a41106a290300370300200141e0076a41186a2202200141e0086a41186a290300370300200120012903e008220637039804200120063703e00741012108200728020420072802006b41a0016e41016a220d410574102d220f450d03200f20012903e007370000200f41186a2002290300370000200f41106a2005290300370000200f41086a20042903003700000240200728020022042007280204460d002007200441a0016a360200200141003a008009200441e0006a2105410021040340200141003a00d803200141e0086a20046a200520046a2d00003a00002001200441016a22043a00800920044120470d000b200141c0066a41186a220b200141e0086a41186a2217290300220637030020014198046a41086a2202200141e0086a41086a221929030037030020014198046a41106a220a200141e0086a41106a221a29030037030020014198046a41186a220e2006370300200120012903e00837039804410121080340200141b8056a41186a200e2903002206370300200141b8056a41106a200a2903002209370300200141b8056a41086a20022903002215370300200120012903980422163703b805200141e8036a41186a22052006370300200141e8036a41106a22102009370300200141e8036a41086a22122015370300200120163703e8030240200d2008470d00200728020420072802006b41a0016e200d6a41016a2204200d490d0a200d410174221b2004201b20044b1b220441ffffff3f712004470d0a200441057422044100480d0a02400240200d0d002004102d210f0c010b200f200d41057420041031210f0b200f450d062004410576210d0b200f20084105746a220420012903e803370000200441186a2005290300370000200441106a2010290300370000200441086a2012290300370000200841016a2108200728020022052007280204460d012007200541a0016a36020041002104200141003a008009200541e0006a21050340200141003a00d803200141e0086a20046a200520046a2d00003a00002001200441016a22043a00800920044120470d000b200b2017290300220637030020022019290300370300200a201a290300370300200e2006370300200120012903e008370398040c000b0b2007102f0c010b2007102f4100210d4101210f410021080b200141c0066a41186a22074200370300200141c0066a41106a22024200370300200141c0066a41086a22044200370300200142003703c00641d39bca00ad428080808080018410012205290000210620014188046a41086a220a200541086a29000037030020012006370388042005102f2004200a29030037030020012001290388043703c006419087ca00ad4280808080c00084100122052900002106200141d8036a41086a220a200541086a290000370300200120063703d8032005102f200320012903d803370000200341086a200a290300370000200141b8056a41086a2004290300370300200141b8056a41106a2002290300370300200141b8056a41186a2007290300370300200120012903c0063703b8052008410574220e4104722204417f4c0d022004102d2205450d01200141003602e808200120043602e408200120053602e0082008200141e0086a10690240024020080d0020012802e808210520012802e408210220012802e008210a0c010b410020012802e80822056b210820012802e008210a20012802e4082107200f2104034002400240200720086a411f4d0d00200721020c010b200541206a22022005490d08200741017422102002201020024b1b22024100480d080240024020070d002002102d210a0c010b200a200720021031210a0b200a450d040b200a20056a22072004290000370000200741186a200441186a290000370000200741106a200441106a290000370000200741086a200441086a290000370000200841606a2108200541206a210520022107200441206a2104200e41606a220e0d000b200120023602e408200120053602e8082001200a3602e0080b201e2005ad422086200aad84100402402002450d00200a102f0b0240200d450d00200f102f0b2025102f4108102d2207450d0120072024360204200720233602004108102d221b450d01201b202a360204201b2011360200024002402022450d0002400240200728020022042007280204460d002007200441a0016a360200200141003a00800920044180016a2105410021040340200141003a00d803200141e0086a20046a200520046a2d00003a00002001200441016a22043a00800920044120470d000b200141e0076a41086a2204200141e0086a41086a290300370300200141e0076a41106a2205200141e0086a41106a290300370300200141e0076a41186a2202200141e0086a41186a290300370300200120012903e008220637039804200120063703e00741012108200728020420072802006b41a0016e41016a220d410574102d220f450d05200f20012903e007370000200f41186a2002290300370000200f41106a2005290300370000200f41086a20042903003700000240200728020022042007280204460d002007200441a0016a360200200141003a00800920044180016a2105410021040340200141003a00d803200141e0086a20046a200520046a2d00003a00002001200441016a22043a00800920044120470d000b200141c0066a41186a2203200141e0086a41186a220b290300220637030020014198046a41086a2202200141e0086a41086a221729030037030020014198046a41106a220a200141e0086a41106a221929030037030020014198046a41186a220e2006370300200120012903e00837039804410121080340200141b8056a41186a200e2903002206370300200141b8056a41106a200a2903002209370300200141b8056a41086a20022903002215370300200120012903980422163703b805200141e8036a41186a22052006370300200141e8036a41106a22102009370300200141e8036a41086a22122015370300200120163703e8030240200d2008470d00200728020420072802006b41a0016e200d6a41016a2204200d490d0c200d410174221a2004201a20044b1b220441ffffff3f712004470d0c200441057422044100480d0c02400240200d0d002004102d210f0c010b200f200d41057420041031210f0b200f450d082004410576210d0b200f20084105746a220420012903e803370000200441186a2005290300370000200441106a2010290300370000200441086a2012290300370000200841016a2108200728020022052007280204460d012007200541a0016a36020041002104200141003a00800920054180016a21050340200141003a00d803200141e0086a20046a200520046a2d00003a00002001200441016a22043a00800920044120470d000b2003200b290300220637030020022017290300370300200a2019290300370300200e2006370300200120012903e008370398040c000b0b2007102f0c010b2007102f4101210f410021084100210d0b20014198046a41186a2207420037030020014198046a41106a2202420037030020014198046a41086a22044200370300200142003703980441fe86ca00ad4280808080a002841001220529000021062004200541086a29000037030020012006370398042005102f419087ca00ad4280808080c0008410012205290000210620014188046a41086a220a200541086a29000037030020012006370388042005102f2028200129038804370000202841086a200a290300370000200141e0086a41086a2004290300370300200141e0086a41106a2002290300370300200141e0086a41186a200729030037030020012001290398043703e0082008410574220e4104722204417f4c0d042004102d2205450d03200141003602a0042001200436029c042001200536029804200820014198046a10690240024020080d0020012802a0042105200128029c042102200128029804210a0c010b410020012802a00422056b2108200128029804210a200128029c042107200f2104034002400240200720086a411f4d0d00200721020c010b200541206a22022005490d0a200741017422102002201020024b1b22024100480d0a0240024020070d002002102d210a0c010b200a200720021031210a0b200a450d060b200a20056a22072004290000370000200741186a200441186a290000370000200741106a200441106a290000370000200741086a200441086a290000370000200841606a2108200541206a210520022107200441206a2104200e41606a220e0d000b2001200236029c04200120053602a0042001200a360298040b200c42808080808004842005ad422086200aad84100402402002450d00200a102f0b0240200d450d00200f102f0b201b102f0c010b201b102f2007102f0b02402027450d002011102f0b0240202620012802c803220445720d0020012802cc03450d002004102f0b02402020450d002021102f0b201ca7450d002023102f0b2001419bd9c900410741f3dcc900410b41c8e1ca00410010cc03024020012802004101470d0020012802042217450d0020014198046aad4280808080c00084211541002103419bd9c900ad4280808080f0008421164100211203402001201236029804200141e0086a41186a220220151003220441186a290000370300200141e0086a41106a2210200441106a290000370300200141e0086a41086a220d200441086a290000370300200120042900003703e0082004102f41c00010332204450d02201610012205290000210620014188046a41086a2207200541086a29000037030020012006370388042005102f200441086a2007290300370000200420012903880437000041fedcc900ad4280808080f00084100122052900002106200141d8036a41086a2207200541086a290000370300200120063703d8032005102f200441186a2007290300370000200420012903d803370010200441386a2002290300370000200441306a2010290300370000200441286a200d290300370000200420012903e00837002020014198046a200441c00010aa0202402001280298042211450d002004ad428080808080088410050b20012802a0042105200128029c04210b2004102f2011450d0102402005450d002005410574210820032105201121040340200141b8056a41186a2207200441186a290000370300200141b8056a41106a220a200441106a290000370300200141b8056a41086a220e200441086a290000370300200120042900003703b80520014198046a41186a420037030020014198046a41106a420037030020014198046a41086a420037030020014200370398040240200141b8056a20014198046a412010ea06450d00200141e0086a200141b8056a108d02427f20012903e008220620012903f0087c22092009200654220f200d290300220620022903007c200fad7c220920065420092006511b220f1b427f2009200f1b84500d00200220072903003703002010200a290300370300200d200e290300370300200120012903b8053703e00820014198046a200510fe0220013502a0042106200128029804210a4110102d2207450d0520074110412010312207450d05200720012903e008370000200741186a2002290300370000200741106a2010290300370000200741086a200d2903003700002007412041c00010312207450d0520074200370020200741286a42003700002006422086200aad842007ad428080808080068410042007102f200128029c04450d00200a102f0b200441206a2104200541016a2105200841606a22080d000b0b0240200b450d002011102f0b200341c0006a2103201241016a22122017470d000b0b02400240200041044b0d0020014198046aad428080808080048421060c010b200141e0076a10f8024100210520012802e007210241002107024020012802e807220a450d002000417b6a210d200a41c4006c2108410021072002210402400340024020042d00004101460d00200441046a280200200d4f0d020b200441c4006a2104200741016a2107200841bc7f6a22080d000b0b200a2007490d070b200141003602e807200a20076b210e2002200741c4006c220d6a210402400340200d2005460d01200220056a2108200541c4006a220a210520082d00004102470d000b2002200a6a21040b2002200741c4006c6a21080240034020082004460d0120042d00002105200441c4006a210420054102470d000b0b0240200e450d0002402007450d0020022002200741c4006c6a200e41c4006c10e9061a0b2001200e3602e8070b20012802e4072107200141b8056a41186a4200370300200141b8056a41106a22084200370300200141b8056a41086a22044200370300200142003703b805419487ca00ad4280808080a0018410012205290000210620014188046a41086a220d200541086a29000037030020012006370388042005102f2004200d29030037030020012001290388043703b805418691c700ad4280808080e00084100122052900002106200141d8036a41086a220d200541086a290000370300200120063703d8032005102f200820012903d803220637030020014198046a41086a200429030037030020014198046a41106a200637030020014198046a41186a200d290300370300200120012903b80537039804200141e0086a2002200e10910320014198046aad4280808080800484220620013502e80842208620012802e0082204ad841004024020012802e408450d002004102f0b2007450d002002102f0b200141b8056a41186a4200370300200141b8056a41106a22074200370300200141b8056a41086a22044200370300200142003703b805419487ca00ad4280808080a0018410012205290000210920014188046a41086a2208200541086a29000037030020012009370388042005102f2004200829030037030020012001290388043703b805419e87ca00ad4280808080c00184100122052900002109200141d8036a41086a2202200541086a290000370300200120093703d8032005102f200720012903d803220937030020014198046a41086a2205200429030037030020014198046a41106a2207200937030020014198046a41186a22082002290300370300200120012903b80537039804200141003a00d8032006200141d8036aad42808080801084100420014198046a10fb02200141c0066a41186a22022008290300370300200141c0066a41106a220d2007290300370300200141c0066a41086a220a200529030037030020012001290398043703c0064124102d22040d060b1036000b103d000b419ef4c90041c90041e8f4c9001055000b419ef4c90041c90041f8f4c9001055000b1038000b41a6b5ca00411c41f8b4ca001039000b200420012903c00637000020044114360220200441186a2002290300370000200441106a200d290300370000200441086a200a29030037000020014281808080103702e408200120043602e008200141e0086a10fc02200141e0086a41186a2008290300370300200141e0086a41106a2007290300370300200141e0086a41086a200529030037030020012001290398043703e008200141e0086a10fd0210fb03200141b00a6a24000ba71b0c017f017e037f017e037f017e017f017e047f017e017f027e230041f0036b2200240042002101200041a0036a41186a4200370300200041a0036a41106a22024200370300200041a0036a41086a22034200370300200042003703a00341aa87ca00ad4280808080c00084100122042900002105200041e0026a41086a2206200441086a290000370300200020053703e0022004102f20032006290300370300200020002903e0023703a00341db98ca00ad4280808080b001841001220429000021052006200441086a290000370300200020053703e0022004102f200220002903e0022205370300200041d0036a41086a2003290300370300200041d0036a41106a2005370300200041d0036a41186a2006290300370300200020002903a0033703d003200041d8016a200041d0036a10f3040240024020002d00d8014102470d00200041d8016a41186a4200370300200041d8016a41106a22044200370300200041d8016a41086a22064200370300200042003703d801418de6c300ad4280808080e000841001220329000021052006200341086a290000370300200020053703d8012003102f41bae6c300ad4280808080e00084100122032900002105200041106a41086a2207200341086a290000370300200020053703102003102f200420002903102205370300200041f8006a41086a2006290300370300200041f8006a41106a2005370300200041f8006a41186a2007290300370300200020002903d801370378200041d8016a200041f8006a10f4020240024020002802d80122080d0041042108410021060c010b20002902dc012201422088a721060b02400240200641246c2203450d002008210602400340024020062d00004101470d00200641016a2800002104200641086a28020021072000200641106a28020036027c20002007360278200441c28289aa04470d00200041d8016a200041f8006a10920520002d00d80122074102470d020b200641246a21062003415c6a2203450d020c000b0b200020002800dc0136006b200020002800d901360268200041e0016a2903002105200041106a200041e8016a41d80010e8061a200041c0026a29030021090c010b410221070b02402001422088a72206450d00200641246c21032008210603400240024020062d0000220441044b0d0002400240024020040e050400010204040b2006410c6a280200450d03200641086a280200102f0c030b2006410c6a280200450d02200641086a280200102f0c020b2006410c6a280200450d01200641086a280200102f0c010b200641086a280200450d00200641046a280200102f0b200641246a21062003415c6a22030d000b0b02402001a7450d002008102f0b200020002802683602d0012000200028006b3600d301200041f8006a200041106a41d80010e8061a0240024020074102470d0041002103200041d0036a21080c010b200020002802d0013602d802200020002800d3013600db02200020053703d002200041d8016a200041f8006a41d80010e8061a200020093703c802200041a0036a41186a22044200370300200041a0036a41106a22084200370300200041a0036a41086a22034200370300200042003703a00341aa87ca00ad4280808080c0008422011001220a2900002109200041e0026a41086a2206200a41086a290000370300200020093703e002200a102f20032006290300370300200020002903e0023703a00341c387ca00ad4280808080b00184220b1001220a29000021092006200a41086a290000370300200020093703e002200a102f200220002903e002370000200241086a220c2006290300370000200041d0036a41086a220a2003290300370300200041d0036a41106a220d2008290300370300200041d0036a41186a220e2004290300370300200020002903a0033703d0032000200041d0036a10e301024002402000280200450d002000290308500d00200041d0036aad42808080808004842109200041d0036a21080c010b200041d0026a200041c8026a20074101461b2903002109200442003703002008420037030020034200370300200042003703a00320011001220f29000021102006200f41086a290000370300200020103703e002200f102f20032006290300370300200020002903e0023703a003200b1001220f290000210b2006200f41086a2900003703002000200b3703e002200f102f200220002903e002370000200c2006290300370000200a2003290300370300200d2008290300370300200e2004290300370300200020002903a0033703d003200020093703a003200041d0036aad42808080808004842209200041a0036aad42808080808001841004200442003703002008420037030020034200370300200042003703a00320011001220f290000210b2006200f41086a2900003703002000200b3703e002200f102f20032006290300370300200020002903e0023703a00341b887ca00ad4280808080b001841001220f290000210b2006200f41086a2900003703002000200b3703e002200f102f200220002903e002370000200c2006290300370000200a2003290300370300200d2008290300370300200e2004290300370300200020002903a0033703d003200041a0036a200041d0036a10990520002902a403210b20002802a003210f200442003703002008420037030020034200370300200042003703a00320011001221129000021012006201141086a290000370300200020013703e0022011102f20032006290300370300200020002903e0023703a00341d987ca00ad4280808080a001841001221129000021012006201141086a290000370300200020013703e0022011102f200220002903e002370000200c2006290300370000200a2003290300370300200d2008290300370300200e2004290300370300200020002903a0033703d003200041a0036a200041d0036a10850420002d00a0032106200e200041b9036a290000370300200d200041b1036a290000370300200a200041a9036a290000370300200020002900a1033703d003200f4108200f1b21030240024020064101460d0020004198036a420037030020004190036a420037030020004188036a420037030020004200370380030c010b20004180036a41186a200041d0036a41186a29030037030020004180036a41106a200041d0036a41106a29030037030020004180036a41086a200041d0036a41086a290300370300200020002903d003370380030b200041e0026a41086a20004180036a41086a2903002201370300200041e0026a41106a20004180036a41106a2903002210370300200041e0026a41186a20004180036a41186a2903002212370300200020002903800322133703e002200041a0036a41086a200b4200200f1b370300200041a0036a41106a2013370300200041a0036a41186a2001370300200041c0036a2010370300200041c8036a2012370300200020033602a403200041003602a003200041a0036a108704200041d0036a21080b200041d0026a200041c8026a20074101461b2903002101200041a0036a41186a220a4200370300200041a0036a41106a220d4200370300200041a0036a41086a22034200370300200042003703a00341aa87ca00ad4280808080c0008410012204290000210b200041e0026a41086a2206200441086a2900003703002000200b3703e0022004102f20032006290300370300200020002903e0023703a00341ce87ca00ad4280808080b0018410012204290000210b2006200441086a2900003703002000200b3703e0022004102f200220002903e002370000200241086a2006290300370000200041d0036a41086a2003290300370300200041d0036a41106a200d290300370300200041d0036a41186a200a290300370300200020002903a0033703d003200020013703a0032009200041a0036aad428080808080018410044100210320070d0020004180036a41086a200041d8016a41086a29030037030020004180036a41106a200041d8016a41106a2d00003a0000200020002800db02360073200020002802d802360270200020002903d80137038003410121030b200041d8016a41086a20004180036a41086a290300370300200041d8016a41106a20004180036a41106a2d00003a0000200020002802703602782000200028007336007b20002000290380033703d801200041a0036a41186a220a4200370300200041a0036a41106a220d4200370300200041a0036a41086a22044200370300200042003703a00341aa87ca00ad4280808080c00084100122072900002101200041e0026a41086a2206200741086a290000370300200020013703e0022007102f20042006290300370300200020002903e0023703a00341db98ca00ad4280808080b001841001220729000021012006200741086a290000370300200020013703e0022007102f200220002903e002370000200241086a2006290300370000200041d0036a41086a2004290300370300200041d0036a41106a200d290300370300200041d0036a41186a200a290300370300200020002903a0033703d0034121410120031b102d2206450d010240024020030d00200641003a000042808080801021010c010b200641013a00002006200028027836000120062005370008200620002903d801370010200641046a200028007b360000200641186a200041e0016a290300370000200641206a200041e8016a2d00003a00004280808080900421010b2008ad428080808080048420012006ad8410042006102f0b200041f0036a24000f0b1036000b940405047f017e017f017e057f230041f0006b22002400200041c0006a41186a22014200370300200041c0006a41106a22024200370300200041c0006a41086a220342003703002000420037034041aa87ca00ad4280808080c000842204100122052900002106200041e0006a41086a2207200541086a290000370300200020063703602005102f200320072903003703002000200029036037034041ae87ca00ad4280808080a001841001220529000021062007200541086a290000370300200020063703602005102f200220002903602206370300200041206a41086a22082003290300370300200041206a41106a22092006370300200041206a41186a220a200729030037030020002000290340370320200041106a200041206a10e3012000280210210b200029031821062001420037030020024200370300200342003703002000420037034020041001220529000021042007200541086a290000370300200020043703602005102f200320072903003703002000200029036037034041c387ca00ad4280808080b001841001220529000021042007200541086a290000370300200020043703602005102f2002200029036022043703002008200329030037030020092004370300200a2007290300370300200020002903403703202000200041206a10e3012000280200210720002903082104200041f0006a24002004420020071b200642c8017e4200200b1b7c0bd60202057f027e230041d0006b220224002002412036020420022001360200200241086a2001ad4280808080800484100210730240024020022802082201450d00200228020c210302400240200241106a28020022044104490d0020044104460d0020012d0004220541014b0d0020012800002106420021070240024020050e020100010b2004417b6a4108490d0120012900052108420121070b20002008370308200041106a20063602000c010b20024100360220200242013703182002410b36022c200220023602282002200241186a360234200241cc006a41013602002002420137023c200241b885c7003602382002200241286a360248200241346a41d8dbc100200241386a103c1a200235022042208620023502188410080240200228021c450d002002280218102f0b420221070b200020073703002003450d012001102f0c010b200042023703000b200241d0006a24000bd80301077f230041e0006b220224002002412036020c20022001360208200241106a2001ad428080808080048410021073024002400240024020022802102201450d00200228021421032002200241186a280200360224200220013602202002200241206a10e6010240024020022802000d0020022802242204200228020422054102742206490d002006417f4c0d040240024020060d00410121070c010b200610332207450d06200720022802202208200610e8061a2002200420066b3602242002200820066a3602200b2007450d000240024002402006450d0020074103710d02200541ffffffff037122060d012007102f0b41042107410021060b41000d012007450d012000200636020420002007360200200041086a20063602000c020b2007102f0b20024100360230200242013703282002410b36023c2002200241086a3602382002200241286a360244200241dc006a41013602002002420137024c200241b885c7003602482002200241386a360258200241c4006a41d8dbc100200241c8006a103c1a200235023042208620023502288410080240200228022c450d002002280228102f0b200041003602000b2003450d012001102f0c010b200041003602000b200241e0006a24000f0b103d000b1036000bf93819047f017e017f017e027f017e057f027e017f017e017f027e037f027e047f017e047f017e017f017e087f037e037f017e017f230041e0036b22012400200141e0026a41186a22024200370300200141e0026a41106a22034200370300200141e0026a41086a22044200370300200142003703e00241eba1ca00ad4280808080f000842205100122062900002107200141a0026a41086a2208200641086a290000370300200120073703a0022006102f20042008290300370300200120012903a0023703e00241adcac800ad4280808080900184220710012209290000210a200141d0006a41086a2206200941086a2900003703002001200a3703502009102f20032001290350220a370300200141a8016a41086a220b2004290300370300200141a8016a41106a220c200a370300200141a8016a41186a220d2006290300370300200120012903e0023703a801200141e0026a200141a8016a10fd032003280200210e20012903e002210a200242003703002003420037030020044200370300200142003703e00220051001220929000021052008200941086a290000370300200120053703a0022009102f20042008290300370300200120012903a0023703e00220071001220829000021052006200841086a290000370300200120053703502008102f200320012903502205370300200b2004290300370300200c2005370300200d2006290300370300200120012903e0023703a80102404104102d2204450d0020044100200e41016a200a4202511b220f36000020044104410810312204450d00200441003a0004200141a8016aad2210428080808080048422112004ad4280808080d0008410042004102f200141e0026a41186a22064200370300200141e0026a41106a22094200370300200141e0026a41086a22044200370300200142003703e00241eba1ca00ad4280808080f00084100122082900002105200141a0026a41086a2202200841086a290000370300200120053703a0022008102f20042002290300370300200120012903a0023703e002418ca1ca00ad4280808080a00184100122082900002105200141d0006a41086a2202200841086a290000370300200120053703502008102f20032001290350370000200341086a2002290300370000200141a8016a41086a2004290300370300200141a8016a41106a2009290300370300200141a8016a41186a2006290300370300200120012903e0023703a801200141e0026a200141a8016a109d0520012802e0022204410420041b2112024002400240024020012902e402420020041b22054220882207a722042005a7470d00200441016a22082004490d012007a722094101742206200820082006491b220841ffffffff01712008470d01200841037422084100480d010240024020040d002008102d21120c010b201220094103742008103121120b2012450d042005422088a721042008410376ad21050b201220044103746a220820003602042008200f360200200542ffffffff0f832113200441016a211402400240200f41a1054f0d0020132014ad4220868421130c010b2014450d00200f41e07a6a2108200441ffffffff017141016a21064100210e2012210402400340200428020020084f0d01200441086a21042006200e41016a220e470d000b0b2014200e490d030240200e450d00200e410374210d200141e0026aad4280808080c0008421052012210b0340200b280200210c41eba1ca00ad4280808080f00084220710012204290000210a20014180026a41086a2208200441086a2900003703002001200a370380022004102f4183cbc800ad4280808080b0028410012204290000210a20014190026a41086a2206200441086a2900003703002001200a370390022004102f2001200c3602e00220051003220441086a290000210a200441106a290000211520042900002116200141a0026a41186a2209200441186a290000370300200141a0026a41106a22002015370300200141a0026a41086a2202200a370300200120163703a0022004102f41c000102d2204450d0620042001290380023700002004200129039002370010200420012903a002370020200441086a2008290300370000200441186a2006290300370000200441286a2002290300370000200441306a2000290300370000200441386a20092903003700002004ad428080808080088410132004102f20071001220429000021072008200441086a29000037030020012007370380022004102f4196cbc800ad4280808080b002841001220429000021072006200441086a29000037030020012007370390022004102f2001200c3602e00220051003220441086a2900002107200441106a290000210a200429000021152009200441186a2900003703002000200a37030020022007370300200120153703a0022004102f41c000102d2204450d06200b41086a210b20042001290380023700002004200129039002370010200420012903a002370020200441086a2008290300370000200441186a2006290300370000200441286a2002290300370000200441306a2000290300370000200441386a20092903003700002004ad428080808080088410132004102f200d41786a220d0d000b0b2014200e6b2217450d000240200e450d0020122012200e4103746a201741037410e9061a0b20122802042118200141a0026a41186a22194200370300200141a0026a41106a220c4200370300200141a0026a41086a220d4200370300200142003703a002419c9eca00ad4280808080f00084221a10012204290000210520014180026a41086a2214200441086a29000037030020012005370380022004102f200d201429030037030020012001290380023703a00241919eca00ad4280808080b00184221b10012204290000210520014190026a41086a221c200441086a29000037030020012005370390022004102f200c2001290390022205370300200141e0026a41086a221d200d290300370300200141e0026a41106a221e2005370300200141e0026a41186a221f201c290300370300200120012903a0023703e002200141a8016a200141e0026a1083044101210620012902ac0121200240024020012802a80122044101460d00200441014621060c010b2020422088a722212018201820214b1b220e2020a72208490d000240200e20084d0d00200141e0026aad4280808080c000842115419c9eca00ad4280808080f0008421160340201610012204290000210520014180026a41086a2206200441086a29000037030020012005370380022004102f41f8dec700ad4280808080a0028410012204290000210520014190026a41086a2209200441086a29000037030020012005370390022004102f200120083602e00220151003220441086a2900002105200441106a29000021072004290000210a200141a0026a41186a2200200441186a290000370300200141a0026a41106a22022007370300200141a0026a41086a220b20053703002001200a3703a0022004102f41c000102d2204450d0720042001290380023700002004200129039002370010200420012903a002370020200441086a2006290300370000200441186a2009290300370000200441286a200b290300370000200441306a2002290300370000200441386a20002903003700002004ad428080808080088410052004102f200e200841016a2208470d000b0b20182021492106202042808080807083200ead8421200b20132017ad42208684211320194200370300200c4200370300200d4200370300200142003703a002201a1001220429000021052014200441086a29000037030020012005370380022004102f200d201429030037030020012001290380023703a002201b100122042900002105201c200441086a29000037030020012005370390022004102f200c200129039002370000200c41086a201c290300370000201d200d290300370300201e200c290300370300201f2019290300370300200120012903a0023703e002024020060d00200141e0026aad428080808080048410050c010b4108102d2204450d04200420203e0000200420204220883e0004200141e0026aad42808080808004842004ad428080808080018410042004102f0b200141e0026a41186a22064200370300200141e0026a41106a22094200370300200141e0026a41086a22044200370300200142003703e00241eba1ca00ad4280808080f00084100122082900002105200141a0026a41086a2200200841086a290000370300200120053703a0022008102f20042000290300370300200120012903a0023703e002418ca1ca00ad4280808080a00184100122082900002105200141d0006a41086a2200200841086a290000370300200120053703502008102f20032001290350370000200341086a2000290300370000200141a8016a41086a2004290300370300200141a8016a41106a2009290300370300200141a8016a41186a2006290300370300200120012903e0023703a8010240024020120d00201110050c010b2013422088a722044103744104722208417f4c0d022008102d2206450d04200141003602e802200120083602e402200120063602e0022004200141e0026a10690240024020040d0020012802e802210420012802e402210620012802e00221080c010b201220044103746a2114410020012802e80222026b210920012802e4022106410021040340200220046a2100201220046a220b280200210c02400240200620096a4104490d0020012802e00221080c010b200041046a22082000490d042006410174220d2008200d20084b1b220d4100480d040240024020060d00200d102d21080c010b20012802e0022006200d103121080b2008450d072001200d3602e402200120083602e002200d21060b2001200041046a220d3602e802200820026a20046a200c360000200b41046a280200210c0240200620096a417c6a41034b0d00200d41046a220e200d490d042006410174220d200e200d200e4b1b220d4100480d040240024020060d00200d102d21080c010b20082006200d103121080b2008450d072001200d3602e402200120083602e002200d21060b2001200041086a3602e802200820026a20046a41046a200c360000200941786a2109200441086a2104200b41086a2014470d000b200220046a21040b2013a7210920112004ad4220862008ad84100402402006450d002008102f0b2009450d002012102f0b200141e0026a41186a22224200370300200141e0026a41106a22234200370300200141e0026a41086a22244200370300200142003703e00241eba1ca00ad4280808080f000842225100122042900002105200141a0026a41086a2226200441086a290000370300200120053703a0022004102f20242026290300370300200120012903a0023703e0024196a1ca00ad4280808080e002842227100122042900002105200141d0006a41086a2228200441086a290000370300200120053703502004102f20032001290350370000200341086a22292028290300370000200141a8016a41086a222a2024290300370300200141a8016a41106a222b2023290300370300200141a8016a41186a222c2022290300370300200120012903e0023703a801200141c8006a200141a8016a4120109501200128024c212d02402001280248222e4101470d000240202d4100200f41d87e6a22042004200f4b1b222f4f0d00200141a0026aad42808080808002842130200141e0026aad4280808080800484213120104280808080c000842132200141a0026a41106a2112200141a8016a41386a2133200141a8016a41246a2100202d2134034041eba1ca00ad4280808080f00084100122042900002105200141a0026a41086a2214200441086a290000370300200120053703a0022004102f41e0cfc800ad4280808080800284100122042900002105200141d0006a41086a220f200441086a290000370300200120053703502004102f200120343602a80120321003220441086a2900002105200441106a29000021072004290000210a200141e0026a41186a220b200441186a290000370300200141e0026a41106a220d2007370300200141e0026a41086a220e20053703002001200a3703e0022004102f41c000102d2204450d06200420012903a00237000020042001290350370010200420012903e002370020200441086a2014290300370000200441186a200f290300370000200441286a200e290300370000200441306a200d290300370000200441386a200b290300370000200141e0026a2004109a050240024020012802e0022235450d002004ad4280808080800884100520012902e40221360c010b42002136410821350b2004102f20352036422088a7220441d8006c6a210c2035210902402004450d000340200141a8016a41186a2204200941186a290300370300200141a8016a41106a2208200941106a290300370300200141a8016a41086a2206200941086a2903003703002009280220210220092903002105200141e0026a41206a221c200941c4006a290200370300200141e0026a41286a2217200941cc006a290200370300200141e0026a41306a2219200941d4006a280200360200200e2009412c6a290200370300200d200941346a290200370300200b2009413c6a290200370300200120053703a8012001200941246a2902003703e002200941d8006a21092002450d0120014188016a41186a2218200429030037030020014188016a41106a221d200829030037030020014188016a41086a221e2006290300370300200f200e290300370300200141d0006a41106a221f200d290300370300200141d0006a41186a2221200b290300370300200141d0006a41206a2237201c290300370300200141d0006a41286a221c2017290300370300200141d0006a41306a22172019280200360200200120012903a80137038801200120012903e002370350200420182903003703002008201d2903003703002006201e29030037030020002001290350370200200041086a200f290300370200200041106a201f290300370200200041186a2021290300370200200041206a2037290300370200200041286a201c290300370200200041306a201728020036020020012001290388013703a801200120023602c801200142003703c802200142003703c002200120042903003703d802200120082903003703d002203320012903a8012006290300200141d0026a200141c0026a10b403024020012802d0012204450d00200441306c21082002210403402004200441206a290300200441286a290300200141d0026a200141c0026a10b403200441306a2104200841506a22080d000b0b200141c0026a41086a290300211020012903c002212020012802d401211c024002400240024020012903d0022207200141d0026a41086a290300220584500d0020012802dc012204450d00200141386a202020072020200754201020055420102005511b22081b221a2010200520081b221b2004ad420010ee0620044105742108200141386a41086a290300210a20012903382116201a2105201b2107201c2104034020042016200520052016562007200a562007200a511b22061b2215200a200720061b221310b502200720137d2005201554ad7d2107200520157d2105200441206a2104200841606a22080d000b427f2020201a7d220a20057c22052005200a5422042010201b7d2020201a54ad7d220520077c2004ad7c220720055420072005511b22041b2205427f200720041b2207844200520d01200141a0026a41186a220442003703002012420037030020144200370300200142003703a00241e7a2ca00ad4280808080800184220510012206290000210720014180026a41086a2208200641086a29000037030020012007370380022006102f2014200829030037030020012001290380023703a00241ecb5c600ad4280808080d00184220710012217290000210a20014190026a41086a2206201741086a2900003703002001200a370390022017102f2012200129039002370000201241086a22182006290300370000200e2014290300370300200d2012290300370300200b2004290300370300200120012903a0023703e002200141206a200141e0026a4120109c01200141206a41106a290300210a2001290328211520012802202117200442003703002012420037030020144200370300200142003703a00220051001221929000021052008201941086a29000037030020012005370380022019102f2014200829030037030020012001290380023703a00220071001220829000021052006200841086a29000037030020012005370390022008102f201220012903900237000020182006290300370000200e2014290300370300200d2012290300370300200b2004290300370300200120012903a0023703e0022001200a420020171b3703a80220012015420020171b3703a0022031203010040c030b20202010844200520d01200141a0026a41186a220442003703002012420037030020144200370300200142003703a00241e7a2ca00ad4280808080800184220510012206290000210720014180026a41086a2208200641086a29000037030020012007370380022006102f2014200829030037030020012001290380023703a00241ecb5c600ad4280808080d00184220710012217290000210a20014190026a41086a2206201741086a2900003703002001200a370390022017102f2012200129039002370000201241086a22182006290300370000200e2014290300370300200d2012290300370300200b2004290300370300200120012903a0023703e002200141086a200141e0026a4120109c01200141086a41106a290300210a2001290310211520012802082117200442003703002012420037030020144200370300200142003703a00220051001221929000021052008201941086a29000037030020012005370380022019102f2014200829030037030020012001290380023703a00220071001220829000021052006200841086a29000037030020012005370390022008102f201220012903900237000020182006290300370000200e2014290300370300200d2012290300370300200b2004290300370300200120012903a0023703e0022001200a420020171b3703a80220012015420020171b3703a0022031203010040c020b200141e0026a41f4c7c40010b402200141e0026a2005200710b502200b2007370300200120053703f002200141063a00e8022001410c3a00e00241c8e1ca004100200141e0026a108c010c010b200141e0026a41f4c7c40010b402200141e0026a2020201010b502200b2010370300200120203703f002200141063a00e8022001410c3a00e00241c8e1ca004100200141e0026a108c010b024020012802cc01450d002002102f0b024020012802d801450d00201c102f0b2009200c470d000b200c21090b2036a721080240200c2009460d0003400240200941246a280200450d00200941206a280200102f0b200941d8006a21040240200941306a280200450d002009412c6a280200102f0b20042109200c2004470d000b0b203441016a213402402008450d002035102f0b2034202f470d000b0b202d202f202d202f4b1b212d0b202242003703002023420037030020244200370300200142003703e00220251001220429000021052026200441086a290000370300200120053703a0022004102f20242026290300370300200120012903a0023703e00220271001220429000021052028200441086a290000370300200120053703502004102f2003200129035037000020292028290300370000202a2024290300370300202b2023290300370300202c2022290300370300200120012903e0023703a80102400240202e0d00201110050c010b2001202d3602e0022011200141e0026aad4280808080c0008410040b200141e0036a24000f0b1038000b103d000b41a6b5ca00411c41f8b4ca001039000b1036000bf68b010a047f017e017f017e017f017e077f047e167f067e230041f0086b22022400200241f0046a41186a22034200370300200241f0046a41106a22044200370300200241f0046a41086a22054200370300200242003703f00441eba1ca00ad4280808080f000842206100122072900002108200241d0086a41086a2209200741086a290000370300200220083703d0082007102f20052009290300370300200220022903d0083703f00441d2a0ca00ad4280808080a00184220810012207290000210a200241b8036a41086a220b200741086a2900003703002002200a3703b8032007102f200420022903b803220a37030020024180046a41086a220c200529030037030020024180046a41106a220d200a37030020024180046a41186a220e200b290300370300200220022903f00437038004200241b8026a20024180046a412010950120022802b802210f20022802bc022110200342003703002004420037030020054200370300200242003703f004200610012207290000210a2009200741086a2900003703002002200a3703d0082007102f20052009290300370300200220022903d0083703f0042008100122072900002108200b200741086a290000370300200220083703b8032007102f200420022903b8032208370300200c2005290300370300200d2008370300200e200b290300370300200220022903f004370380042002201041016a4100200f1b22113602f00420024180046aad22124280808080800484200241f0046aad22134280808080c0008422081004200610012207290000210a2009200741086a2900003703002002200a3703d0082007102f41dca0ca00ad4280808080d0028410012207290000210a200b200741086a2900003703002002200a3703b8032007102f200220113602800420124280808080c0008410032207290000210a200741086a2900002114200741106a29000021152003200741186a29000037030020042015370300200520143703002002200a3703f0042007102f024002400240024041c000102d2207450d00200720022903d008370000200720022903b803370010200720022903f004370020200741086a2009290300370000200741186a200b290300370000200741286a2005290300370000200741306a2004290300370000200741386a2003290300370000200220013602f0042007ad4280808080800884200810042007102f200342003703002004420037030020054200370300200242003703f00420061001220729000021062009200741086a290000370300200220063703d0082007102f20052009290300370300200220022903d0083703f00441a3a0ca00ad4280808080c00184100122072900002106200b200741086a290000370300200220063703b8032007102f200420022903b803370000200441086a200b290300370000200c2005290300370300200d2004290300370300200e2003290300370300200220022903f00437038004200241b0026a20024180046a41201095010240201120022802b40241016a41d50020022802b0021b6b220520114b0d00200510ee050b200242003702c40220024190bdc6003602c00241eba1ca00ad4280808080f00084100122052900002106200241b8036a41086a2207200541086a290000370300200220063703b8032005102f4195c6c800ad428080808080028410012205290000210620024180046a41086a2209200541086a29000037030020022006370380042005102f200241f0046a41086a22052007290300370300200241f0046a41186a220b2009290300370300200220022903b8033703f00420022002290380043703800520024180046a200241f0046a108801200241f0046a200228028004220920022802880410ad02200241f0046a41106a21160240200228028404450d002009102f0b20024190036a41086a2005290300220637030020024190036a41106a2016290300220837030020024190036a41186a200b290300220a37030020024190036a41206a200241f0046a41206a2d000022053a0000200220022903f004221437039003200241b8036a41206a20053a0000200241b8036a41186a200a370300200241b8036a41106a200837030020072006370300200220143703b803200241f0046a200241b8036a109904410121170240024002400240024002400240024020022802f0044101460d0041042118410021194100211a4100211b0c010b200241f0046a410272211c200241f0046a410172211d200241f0046a410472211e200241a8046a211f4100210d4100211a410121174100211b410421180340200241d0026a41086a201e41086a2902002206370300200241d0026a41106a201e41106a2902002208370300200241d0026a41186a201e41186a290200220a3703002002201e29020022143703d0022002280294052120200241f0026a41186a2221200a370300200241f0026a41106a22222008370300200241f0026a41086a22232006370300200220143703f002200241f0046a41186a2201200a370300200241f0046a41106a220f2008370300200241f0046a41086a22102006370300200220143703f0044120102d2205450d08200520022903f002370000200541186a2021290300370000200541106a2022290300370000200541086a2023290300370000200241e0036a41086a20102903002206370300200241e0036a41106a200f2903002208370300200241e0036a41186a2001290300220a370300200220022903f00422143703e0032001200a370300200f200837030020102006370300200220143703f0040240200d201b470d00200d41016a2207200d490d0c200d41017422092007200920074b1bad422c7e2206422088a70d0c2006a722074100480d0c02400240200d0d002007102d21180c010b2018200d412c6c2007103121180b2018450d092007412c6e211b0b2018200d412c6c6a220720022903f00437020020102903002106200f29030021082001290300210a200742818080801037022420072005360220200741186a200a370200200741106a2008370200200741086a2006370200200241d0086a41186a22242021290300370300200241d0086a41106a22252022290300370300200241d0086a41086a22262023290300370300200220022903f0023703d0080240024020022802c00222034190bdc600460d0020022802c402210c0c010b200241f0046a410041e00210e7061a201f410036020020024180046a41206a2205420037030020024180046a41186a2207420037030020024180046a41106a2209420037030020024180046a41086a220b42003703002002420037038004419403102d2203450d094100210c200341003b010620034100360200200341086a200241f0046a41e00210e8061a20034190036a201f28020036020020034188036a200529030037020020034180036a2007290300370200200341f8026a2009290300370200200341f0026a200b29030037020020032002290380043702e802200241003602c402200220033602c0020b200d41016a211902400240024003400240024020032f0106220e0d00410021090c010b200e4105742105200341086a2107417f21090340024020050d00200e21090c020b200941016a2109200241d0086a2007412010ea06220b450d03200541606a2105200741206a2107200b417f4a0d000b0b0240200c450d00200c417f6a210c200320094102746a4194036a28020021030c010b0b200241b0046a41186a22052024290300370300200241b0046a41106a22072025290300370300200241b0046a41086a220b2026290300370300200220022903d0083703b004200220022802c80241016a3602c802200220093602dc08200220033602d408200241003602d0082002200241c0026a3602d80820024180046a41186a2226200529030037030020024180046a41106a2227200729030037030020024180046a41086a2228200b290300370300200220022903b00437038004200241f0046a200241d0086a20024180046a2020107720022d00f0044101470d02200241d0046a41186a2209201d41186a2229290000370300200241d0046a41106a220b201d41106a222a290000370300200241d0046a41086a2203201d41086a222b2900003703002002201d2900003703d004200228029c05210520022802a805210c20022802a405210720022802a005210e20022802980522242802002220450d0120242f01042124034020022802940521252002202441ffff03713602dc08200220053602d808200220203602d4082002202541016a3602d008202620092903003703002027200b29030037030020282003290300370300200220022903d00437038004200241f0046a200241d0086a20024180046a200e2007200c107820022d00f0044101470d0320092029290000370300200b202a2900003703002003202b2900003703002002201d2900003703d004200228029c05210520022802a805210c20022802a405210720022802a005210e20022802980522242802002220450d0220242f010421240c000b0b200320094102746a41e8026a20203602000c010b201c410041be0310e7061a41c403102d2220450d0920204100360200202041046a200241f0046a41c00310e8061a202020052802002224360294032005202036020020052005280204222541016a360204202441003b010420242020360200200241b0086a41186a22242009290300370300200241b0086a41106a2226200b290300370300200241b0086a41086a220b2003290300370300200220022903d0043703b0082025200c470d0420202f01062205410a4b0d03202020054105746a220941206a2024290300370000200941186a2026290300370000200941106a200b290300370000200941086a20022903b008370000202020054102746a41e8026a200e3602002020200541016a22054102746a4194036a2007360200202020053b0106200720053b0104200720203602000b20012021290300370300200f202229030037030020102023290300370300200220022903f0023703f0040240200d201a470d00200d41016a2205200d490d0c200d41017422072005200720054b1b220541ffffff3f712005470d0c200541057422054100480d0c02400240200d0d002005102d21170c010b2017200d4105742005103121170b2017450d092005410576211a0b2017200d4105746a220520022903f004370000200541186a2001290300370000200541106a200f290300370000200541086a2010290300370000200241f0046a200241b8036a1099042019210d20022802f0044101460d000b0b41eba1ca00ad4280808080f00084100122052900002106200241b8036a41086a2207200541086a290000370300200220063703b8032005102f41fbc5c800ad428080808080028410012205290000210620024180046a41086a2209200541086a29000037030020022006370380042005102f200241f0046a41086a220520072903003703002016200229038004370000201641086a2009290300370000200220022903b8033703f00420024180046a200241f0046a108801200241f0046a200228028004220920022802880410ad020240200228028404450d002009102f0b20024190036a41086a2005290300220637030020024190036a41106a200241f0046a41106a2227290300220837030020024190036a41186a200241f0046a41186a2228290300220a37030020024190036a41206a200241f0046a41206a22252d000022053a0000200220022903f004221437039003200241b8036a41206a20053a0000200241b8036a41186a200a370300200241b8036a41106a200837030020072006370300200220143703b803200241f0046a200241b8036a1096040240024020022d00a0054102470d00201921200c010b20192120034020024180046a41286a200241f0046a41286a28020036020020024180046a41206a202529030037030020024180046a41186a2226202829030037030020024180046a41106a221f202729030037030020024180046a41086a221d200241f0046a41086a290300370300200220022903f004370380042025280200212402402002290294052214422088a72222450d00200228029c05212341002103202421074100210c0240034041eba1ca00ad4280808080f00084100122052900002106200241d0046a41086a220b200541086a290000370300200220063703d0042005102f41a9cbc800ad4280808080d00184100122052900002106200241f0026a41086a220d200541086a290000370300200220063703f0022005102f4120102d2205450d0b20052007290000370000200541186a200741186a2210290000370000200541106a200741106a221e290000370000200541086a200741086a22212900003700002005ad4280808080800484100322092900002106200941086a2900002108200941106a290000210a200241b0086a41186a220e200941186a290000370300200241b0086a41106a2201200a370300200241b0086a41086a220f2008370300200220063703b0082009102f2005102f41c000102d2205450d0b200520022903d004370000200520022903f002370010200520022903b008370020200541086a200b290300370000200541186a200d290300370000200541286a200f290300370000200541306a2001290300370000200541386a200e290300370000200241d0086a2005109c0502400240024002400240024020022802dc0822090d002005102f0c010b20022802d808210d20022903e00821062005102f02402006a7450d002009102f0b200d20234b0d010b20030d01410021030c020b200341016a21030c010b200c20036b220520224f0d01200241d0046a41186a2209200720034105746b220541186a220d290000370300200241d0046a41106a220e200541106a2201290000370300200b200541086a220f290000370300200220052900003703d00420212900002106201e29000021082010290000210a20052007290000370000200d200a37000020012008370000200f200637000020102009290300370000201e200e2903003700002021200b290300370000200720022903d0043700000b200741206a21072022200c41016a220c460d020c010b0b4188bbca0020052022103b000b2003417f6a20224f0d00201442ffffffff0f83202220036bad4220868421140b200241b0046a41186a22052026290300370300200241b0046a41106a2207201f290300370300200241b0046a41086a2209201d29030037030020022002290380043703b0042024450d01200241b0086a41186a220b2005290300370300200241b0086a41106a22032007290300370300200241b0086a41086a22072009290300370300200220022903b0043703b00802402020201b470d00202041016a22052020490d0c202041017422092005200920054b1bad422c7e2206422088a70d0c2006a722054100480d0c0240024020200d002005102d21180c010b20182020412c6c2005103121180b2018450d092005412c6e211b0b20182020412c6c6a220520022903b0083702002007290300210620032903002108200b290300210a2005201437022420052024360220200541186a200a370200200541106a2008370200200541086a2006370200202041016a2120200241f0046a200241b8036a10960420022d00a0054102470d000b0b200241f0046a41186a22074200370300200241f0046a41106a22094200370300200241f0046a41086a22054200370300200242003703f00441eba1ca00ad4280808080f000842206100122032900002108200241d0086a41086a220b200341086a290000370300200220083703d0082003102f2005200b290300370300200220022903d0083703f00441afa0ca00ad4280808080e001841001220c2900002108200241b8036a41086a2203200c41086a290000370300200220083703b803200c102f200420022903b803370000200441086a220d200329030037000020024180046a41086a220e200529030037030020024180046a41106a2201200929030037030020024180046a41186a220f2007290300370300200220022903f00437038004200241a8026a20024180046a412010950120022802ac02211620022802a802211c200742003703002009420037030020054200370300200242003703f00420061001220c2900002106200b200c41086a290000370300200220063703d008200c102f2005200b290300370300200220022903d0083703f00441bda0ca00ad4280808080d002841001220b29000021062003200b41086a290000370300200220063703b803200b102f200420022903b803370000200d2003290300370000200e200529030037030020012009290300370300200f2007290300370300200220022903f00437038004200241a0026a20024180046a412010950120022802a402210720022802a0022109200242003702e40320024190bdc6003602e003202020196a222aad42e0007e2206422088a70d042006a72205417f4c0d04410821104108212902402005450d002005102d2229450d07200541e0006e212a0b4100210f4100212b02402019410574220b450d00200b410575ad42d8007e2206422088a70d0a2006a722054100480d0a2005102d2210450d07200541d8006e212b0b2007410420091b222241014b212302402019450d00200b41606a2119200241a0056a210720024198056a21212010210341002109201721050340200241b8036a41186a220c200541186a220d290000370300200241b8036a41106a220e200541106a2201290000370300200241b8036a41086a220f200541086a221e290000370300200220052900003703b80320024180046a41186a200d29000037030020024180046a41106a200129000037030020024180046a41086a201e2900003703002002200529000037038004200241e0036a20024180046a2009109a02200241f0046a41086a4200370300200241f0046a41106a4200370300200241f0046a41186a4200370300200241f0046a41206a420037030020214200370300200741186a200c290300370000200741106a200e290300370000200741086a200f290300370000200720022903b803370000200242003703f0042003200241f0046a41d00010e806220341d0006a41003a0000200341d8006a2103200541206a2105200941016a2109200b41606a220b0d000b201941057641016a210f0b2022410120231b21050240201a450d002017102f0b024002400240200f2005490d000240202a2020412c6c2205412c6d22074f0d00202a41017422092007200920074b1bad42e0007e2206422088a70d0d2006a722074100480d0d02400240202a0d002007102d21290c010b2029202a41e0006c2007103121290b2029450d0a200741e0006e212a0b201820056a211f024020200d00410021262018211a0c060b200241b0086a41106a21012018210520292124410021260340200241b0046a41186a2209200541186a290200370300200241b0046a41106a220b200541106a290200370300200241b0046a41086a2203200541086a290200370300200220052902003703b0042005412c6a211a20052802202225450d06200541286a2802002107200541246a280200211d20024180046a41186a2204200929030037030020024180046a41106a2227200b29030037030020024180046a41086a22282003290300370300200220022903b0043703800420024190026a20024180046a10ef052007ad42c8007e2206422088a70d082006a72205417f4c0d0820024190026a41086a2903002115200229039002212c0240024020050d00410821222007211e0c010b2005102d2222450d0b200541c8006e211e0b0240024020070d00410021210c010b202520074105746a2119410021212025210e0340200e41086a2900002106200e41106a2900002108200e290000210a200241f0046a41186a2223200e41186a290000370300200241f0046a41106a22202008370300200241f0046a41086a221720063703002002200a3703f004200e41206a210e200241e0036a210520022802e403210c02400240034002400240200528020022032f0106220d0d00410021090c010b200d4105742105200341086a2107417f21090340024020050d00200d21090c020b200941016a2109200241f0046a2007412010ea06220b450d03200541606a2105200741206a2107200b417f4a0d000b0b200c450d02200c417f6a210c200320094102746a4194036a21050c000b0b200f200320094102746a41e8026a220528020022074d0d052010200741d8006c6a22072903202106200741286a2903002108200241b0086a41186a2209420037030020014200370300200241b0086a41086a22074200370300200242003703b00841e7a2ca00ad42808080808001841001220b290000210a2007200b41086a2900003703002002200a3703b008200b102f41ecb5c600ad4280808080d001841001220b290000210a200241f0026a41086a2203200b41086a2900003703002002200a3703f002200b102f200120022903f002370000200141086a2003290300370000200241d0046a41086a2007290300370300200241d0046a41106a2001290300370300200241d0046a41186a2009290300370300200220022903b0083703d004200241f8016a200241d0046a4120109c01200241e8016a200229038002200241f8016a41106a290300427f420010ee06200f2005280200220b4d0d06200241d8016a202c201520022903e801420020022802f80122031b220a4201200a420156200241e8016a41086a290300420020031b220a420052200a501b22031b200a420020031b10ee062010200b41d8006c6a220b41286a427f2008200620022903d8017c220a2006542203ad7c221420032014200854200a20065a1b22031b370300200b427f200a20031b370320200920232903003703002001202029030037030020072017290300370300200220022903f0043703b0082005280200210b024002402021201e460d00202121050c010b201e41016a2205201e490d11201e41017422032005200320054b1bad42c8007e2206422088a70d112006a722034100480d1102400240201e0d002003102d21220c010b2022201e41c8006c2003103121220b2022450d0e201e2105200341c8006e211e0b2022200541c8006c6a220542003703002005200b360220200541186a4200370300200541106a4200370300200541086a4200370300200520022903b0083702242005412c6a2007290300370200200541346a20012903003702002005413c6a2009290300370200202141016a21210b200e2019470d000b0b0240201d450d002025102f0b200241d0086a41186a22092004290300370300200241d0086a41106a220b2027290300370300200241d0086a41086a2203202829030037030020022002290380043703d008200241b0086a41186a220c420037030020014200370300200241b0086a41086a22054200370300200242003703b00841e7a2ca00ad42808080808001841001220729000021062005200741086a290000370300200220063703b0082007102f41ecb5c600ad4280808080d00184100122072900002106200241f0026a41086a220d200741086a290000370300200220063703f0022007102f200120022903f002370000200141086a200d290300370000200241d0046a41086a2005290300370300200241d0046a41106a2001290300370300200241d0046a41186a200c290300370300200220022903b0083703d004200241c0016a200241d0046a4120109c01200241b0016a20022903c801200241c0016a41106a290300427f420010ee06200241a0016a202c201520022903b001420020022802c00122051b220642012006420156200241b0016a41086a290300420020051b22064200522006501b22051b2006420020051b10ee0620244200370308202420022903a00137030020244200370310202441186a4200370300202441286a420037030020244201370320202420213602382024201e36023420242022360230202420022903d00837023c202441c4006a2003290300370200202441cc006a200b290300370200202441d4006a2009290300370200202641016a2126202441e0006a2124201a2105201a201f470d000c070b0b0240202b450d002010102f0b0240202a450d002029102f0b20022802e00320022802e40320022802e80310a30202402020450d002020412c6c2107201841206a210503400240200541046a280200450d002005280200102f0b2005412c6a2105200741546a22070d000b0b410021250240201b450d002018102f0b0c0a0b41c4c2ca002007200f103b000b419cc3ca00200b200f103b000b41c6b3ca00412741f8b4ca001039000b4196b3ca00413041f8b4ca001039000b201f201a460d000340201a412c6a21050240201a41246a280200450d00201a41206a280200102f0b2005211a201f2005470d000b0b20164100201c1b21170240201b450d002018102f0b2017ad42307e2206422088a70d002006a72205417f4c0d000240024020050d0041082123201721180c010b2005102d2223450d03200541306e21180b2017412c6c2205417f4c0d000240024020050d004104211b0c010b2005102d221b450d030b410021190240200f2017200f2017491b22160d002018211d4100211f0c020b201041a87f6a2104200f41d8006c21252029202641e0006c6a2120200241f0046a41186a2127200241f0046a41106a2122200241f0046a41086a21284100211f4100211a03400240200f450d00202521072010210503400240200541d0006a2d00000d0002400240200541206a2903002208200541286a290300220a8450450d0042002106427f2108427f210a0c010b427f210620024190016a427f427f2008200a10ee0620024190016a41086a290300210a20022903900121080b200520083703002005200a370308200541106a2006370300200541186a20063703000b200541d8006a2105200741a87f6a22070d000b0b2029210b02402026450d00024003400240200b2802382205450d00200541c8006c2109200b28023041206a21050340200f200528020022074d0d0302402010200741d8006c6a22072d00500d0020072903202206200741286a290300220884500d00200241f0046a200b290310200b41186a290300200b290300200b41086a29030020062008109405200720072903002206427f2006427f20022903f80420022802f00441014622031b220a7c22082008200654220c200741086a220d2903002206427f202229030020031b22147c200cad7c220820065420082006511b22031b200a20148450220c1b370300200d2006427f200820031b200c1b3703000b200541c8006a2105200941b87f6a22090d000b0b200b41e0006a220b2020460d020c000b0b419cc3ca002007200f103b000b201a41016a211a2025210520042107201021090340024020050d002018211d0c040b200541a87f6a2105200741d8006a2107200941d0006a210b200941d8006a22032109200b2d00000d000b02402005450d00200741086a2903002106200741186a2903002108200741106a290300210a200729030021144100210903400240200320096a220b41d0006a2d00000d00200b41086a2903002215200620142006200a2008200b290300222c2015200b41106a290300222d200b41186a290300222e10950541ff0171410146220c1b2106202c2014200c1b2114202e2008200c1b2108202d200a200c1b210a200b2007200c1b21070b2005200941d8006a2209470d000b20070d002018211d0c030b200741013a005002402026450d002007410c6a211e200741306a2121202921090340200941e0006a212402402009280238220b450d0020092802302105200b41c8006c210b034002400240201e2005460d00200541246a2021412010ea060d010b200941186a22032903002114200741086a220c29030021062009290310210a2007290300210820072903102115200541186a200741186a220d290300370300200541106a2015370300200520064200200620147d2008200a54ad7d22152008200a7d222c200856201520065620152006511b220e1b200a2014845022011b370308200520084200202c200e1b20011b370300200c2903002106200d29030021082007290300210a20092007290310370320200941286a20083703002009200a370310200320063703000b200541c8006a2105200b41b87f6a220b0d000b0b2024210920242020470d000b0b2027200741c8006a2900003703002022200741c0006a2900003703002028200741386a290000370300200220072900303703f004200741286a29030021062007290320210802400240201f2018460d002018211d0c010b201841016a22052018490d07201841017422072005200720054b1bad42307e220a422088a70d07200aa722054100480d070240024020180d002005102d21230c010b2023201841306c2005103121230b2023450d042018211f200541306e221d21180b2028290300210a202229030021142027290300211520022903f004212c2023201f41306c6a220520083703202005202c370300200541286a2006370300200541186a2015370300200541106a2014370300200541086a200a370300201f41016a211f201a20164f0d020c000b0b103d000b02402026450d002029202641e0006c6a2125201f41306c212020024180046a41186a212420024180046a41106a211820024180046a41086a211a410021192029211e03402024201e41d4006a2900003703002018201e41cc006a290000370300201a201e41c4006a2900003703002002201e29003c370380040240201e2802382205450d00201e280230220e200541c8006c6a2121201e41106a2122410021014104210f4100210d0340200e220c41246a2109200c41c8006a210e4100210b2020210720232105024003402007450d01024020092005460d0020052009412010ea062103200b41016a210b200741506a2107200541306a210520030d010b0b418094ebdc03210502402022200c1096050d0041002105200c290310201e29032085200c41186a290300201e41286a29030085844200520d00200241f0046a428094ebdc034200200c290300200c41086a2903002022290300202241086a290300109405427f20022903f80420022802f00441014622051b2206a7417f2006428080808010544100427f200241f0046a41106a29030020051b501b1b21050b200220053602f0042002418094ebdc033602f404200241f0046a2005418094ebdc034b4102746a2802002107200241f0046a41186a2209200c413c6a290000370300200241f0046a41106a220b200c41346a290000370300200241f0046a41086a2203200c412c6a2900003703002002200c2900243703f00402400240200d2001460d00200d21050c010b200141016a22052001490d092001410174220c2005200c20054b1bad42247e2206422088a70d092006a7220c4100480d090240024020010d00200c102d210f0c010b200f200141246c200c1031210f0b200f450d0620012105200c41246e21010b200f200541246c6a220520022903f00437020020032903002106200b29030021082009290300210a20052007360220200541186a200a370200200541106a2008370200200541086a2006370200200d41016a210d0b200e2021470d000b024002400240200d450d0002400240200d41246c22090d00410021050c010b200f41206a2107410021050340417f200520072802006a220b200b2005491b2105200741246a21072009415c6a22090d000b0b02404100418094ebdc0320056b22052005418094ebdc034b1b220c200d6e2205418094ebdc032005418094ebdc03491b2203450d00200f41206a2105410021070340200d2007460d032002417f2005280200220920036a220b200b2009491b22093602f0042002418094ebdc033602f4042005200241f0046a2009418094ebdc034b4102746a280200360200200541246a2105200d200741016a2207470d000b0b0240200c2003200d6c6b2203450d00410021050340200d2005200d7022074d0d042002417f200f200741246c6a2207280220220941016a220b200b2009491b22093602f0042002418094ebdc033602f4042007200241f0046a2009418094ebdc034b4102746a280200360220200541016a22052003490d000b0b200241f0046a41186a22072024290300370300200241f0046a41106a22092018290300370300200241f0046a41086a220b201a29030037030020022002290380043703f004024020192017470d00201741016a22052017490d0a201741017422032005200320054b1bad422c7e2206422088a70d0a2006a722054100480d0a0240024020170d002005102d211b0c010b201b2017412c6c20051031211b0b201b450d07201721192005412c6e21170b201b2019412c6c6a220520022903f004370200200b2903002106200929030021082007290300210a2005200d360228200520013602242005200f360220200541186a200a370200200541106a2008370200200541086a2006370200201941016a21190c030b2001450d02200f102f0c020b41c4c2ca002007200d103b000b41c4c2ca002007200d103b000b201e41e0006a221e2025470d000b0b0240202b450d002010102f0b02402026450d00202641e0006c2107202941306a210503400240200541046a280200450d002005280200102f0b200541e0006a2105200741a07f6a22070d000b0b0240202a450d002029102f0b20022802e00320022802e40320022802e80310a302024020230d00410021250c030b02400240201f41306c22050d004200212f410121250c010b200541306d220541ffffff3f712005470d04200541057422054100480d042005102d2225450d012005410576ad212f0b02400240201f0d00410021240c010b201f41306c21094100212420252105202321070340200741086a2900002106200741106a29000021082007290000210a200541186a200741186a290000370000200541106a2008370000200541086a20063700002005200a370000202441016a2124200541206a2105200741306a2107200941506a22090d000b0b0240201d450d002023102f0b200242003702d40820024190bdc6003602d00802402024450d002024410574210720252105034020024180046a41186a200541186a29000037030020024180046a41106a200541106a29000037030020024180046a41086a200541086a2900003703002002200529000037038004200242003703f804200242003703f00420024100360288052002420837038005200241b8036a200241d0086a20024180046a200241f0046a109902024020022802c8032209450d0020022802cc03450d002009102f0b200541206a2105200741606a22070d000b0b02402019412c6c2205450d00201b20056a2123200241b0086a41106a210141e7a2ca00ad42808080808001842115201b211003400240201028022841246c2205450d002010280220222120056a2122034020024180016a201010ef0520024180016a41086a2903002108200229038001210a200241b0086a41186a221e420037030020014200370300200241b0086a41086a220f4200370300200242003703b0082015100122052900002106200f200541086a290000370300200220063703b0082005102f41ecb5c600ad4280808080d00184100122052900002106200241f0026a41086a2207200541086a290000370300200220063703f0022005102f200120022903f002370000200141086a2007290300370000200241d0046a41086a200f290300370300200241d0046a41106a2001290300370300200241d0046a41186a201e290300370300200220022903b0083703d004200241e8006a200241d0046a4120109c01200241d8006a2002290370200241e8006a41106a290300427f420010ee06200241c8006a200a200820022903584200200228026822051b220642012006420156200241d8006a41086a290300420020051b22064200522006501b22051b2006420020051b10ee06200241386a20022903482206428094ebdc03802208420020212203350220220a420010ed06200241386a41086a29030020022903382214200a200620084280ec94a37c7e7c7e22062006428094ebdc038022064280ec94a37c7e7c4280cab5ee01562006a76aad7c2206201454ad7c2108200341246a2121200241d0086a210520022802d408210d024002400340024002402005280200220c2f0106220e0d00410021090c010b200e4105742105200c41086a2107417f21090340024020050d00200e21090c020b200941016a210920032007412010ea06220b450d03200541606a2105200741206a2107200b417f4a0d000b0b200d450d02200d417f6a210d200c20094102746a41c8056a21050c000b0b201e201041186a2900003703002001201041106a290000370300200f201041086a290000370300200220102900003703b008200c20094105746a220741f8026a210b024020074180036a22092802002205200741fc026a280200470d00200541016a22032005490d092005410174220c2003200c20034b1bad42307e220a422088a70d09200aa722034100480d090240024020050d002003102d21050c010b200b280200200541306c2003103121050b2005450d06200b2005360200200b41046a200341306e360200200928020021050b200b280200200541306c6a220520022903b00837030020052006370320200541186a201e290300370300200541106a2001290300370300200541086a200f290300370300200541286a20083703002009200928020041016a360200200741e8026a2205427f2005290300220a20067c22062006200a542207200541086a2205290300220620087c2007ad7c220820065420082006511b22071b3703002005427f200820071b3703000b20212022470d000b0b2010412c6a22102023470d000b0b20022802d808210c20022802d00821070240024020022802d40822090d00200721050c010b2009210b20072105034020052802c8052105200b417f6a220b0d000b0340200720072f01064102746a41c8056a28020021072009417f6a22090d000b0b200241d4036a20072f010636020041002103200241b8036a41186a4100360200200241cc036a20073602002002200c3602d803200241003602c80342002130200242003703c003200220053602bc03200241003602b803024002400240200c450d002002200c417f6a3602d8030240024020052f0106450d004100210b20052107410021090c010b4100210b41002109034002400240024020054190bdc600460d00200528020022070d012009ad2106410021070c020b41edb3ca00412841f8b4ca001039000b200b41016a210b20053301044220862009ad8421060b2005102f2006a72109200721052006422088a7220320072f01064f0d000b0b200241b0086a41186a220c200720034105746a220541206a290000370300200241b0086a41106a220e200541186a290000370300200241b0086a41086a2201200541106a2900003703002002200541086a2900003703b008200341016a210320054180036a280200210d200541fc026a280200211a200541f8026a28020021180240200b450d00200720034102746a41c8056a280200210741002103200b417f6a2205450d00034020072802c80521072005417f6a22050d000b0b200241f0046a41186a200c290300370300200241f0046a41106a200e290300370300200241f0046a41086a2001290300370300200220022903b0083703f004200220033602c403200220093602c003200220073602bc03200241003602b80320180d01420021300b420021310c010b200241b0086a41106a210742002130420021310340200241e0036a41186a200241f0046a41186a221e2903002206370300200241e0036a41106a200241f0046a41106a22212903002208370300200241e0036a41086a200241f0046a41086a2222290300220a370300200220022903f00422143703e003200241b0046a41186a2006370300200241b0046a41106a2008370300200241b0046a41086a200a370300200220143703b00402400240200d41306c220d0d004100210b4200212d4200212c410021204108212342002108420021060c010b4200212d410821234100210b4200212c410021204200210842002106201821050340200541286a2903002114200541206a2903002115200241d0086a41186a220e200541186a290300370300200241d0086a41106a2201200541106a290300370300200241d0086a41086a220f200541086a290300370300200220052903003703d008200241b0086a41186a220c420037030020074200370300200241b0086a41086a22094200370300200242003703b00841e7a2ca00ad428080808080018410012203290000210a2009200341086a2900003703002002200a3703b0082003102f41ecb5c600ad4280808080d0018410012203290000210a200241f0026a41086a2210200341086a2900003703002002200a3703f0022003102f200720022903f002370000200741086a2010290300370000200241d0046a41086a2009290300370300200241d0046a41106a2007290300370300200241d0046a41186a200c290300370300200220022903b0083703d004200241206a200241d0046a4120109c01200241106a2002290328200241206a41106a290300427f420010ee06200220022903104200200228022022031b220a4201200a420156200241106a41086a290300420020031b220a420052200a501b22031b200a420020031b2015201410ed06201e200e290300370300202120012903003703002022200f290300370300200220022903d0083703f004200241086a290300210a2002290300211402400240200241f0046a200241b0046a412010ea06450d00200c201e2903003703002007202129030037030020092022290300370300200220022903f0043703b0080240200b2020470d00200b41016a2203200b490d0a200b410174220e2003200e20034b1bad42307e2215422088a70d0a2015a722034100480d0a02400240200b0d002003102d21230c010b2023200b41306c2003103121230b2023450d07200341306e21200b2023200b41306c6a2203200a37030820032014370300200320022903b008370310200341186a2009290300370300200341206a2007290300370300200341286a200c290300370300200b41016a210b0c010b427f202c200a7c202d20147c222e202d542209ad7c221520092015202c542015202c511b22091b212c427f202e20091b212d0b200541306a2105427f2006200a7c200820147c220a2008542209ad7c22082009200820065420082006511b22091b2106427f200a20091b2108200d41506a220d0d000b0b0240201a450d002018102f0b20024180046a41186a2209202c3703002002202d370390042002200b3602a804200220203602a404200220233602a00420022008370380042002200637038804200241f0046a2011200241b0046a10f00520022802f0042105200220022802f8043602d408200220053602d008203120067c2106203020087c2208203054220bad210a20024180046a200241d0086a10be03024020022802f404450d002005102f0b2006200a7c2106200241d0086a41186a22032009290300370300200241d0086a41106a220c20024180046a41106a290300370300200241d0086a41086a220d20024180046a41086a29030037030020022002290380043703d00820022802ac04210e20022802a404210120022802a0042109024020022802a804220541c100490d0020092005410041202005676b10bf0341c00021050b2006203151210f20062031542110201e20032903003703002021200c2903003703002022200d290300370300200220022903d0083703f0042002200e36029c05200220053602980520022001360294052002200936029005200241b0086a2011200241b0046a10f10520022802b0082105200220022802b8083602d404200220053602d004200241f0046a200241d0046a10be03024020022802b408450d002005102f0b200b2010200f1b21050240200228029405450d00200228029005102f0b427f200620051b2131427f200820051b213020022802d8032205450d0120022005417f6a3602d80320022802c003210b20022802b80321030240024020022802c403220c20022802bc0322092f01064f0d00200921050c010b034002400240024020094190bdc600460d00200928020022050d01200bad2106410021050c020b41edb3ca00412841f8b4ca001039000b200341016a21032009330104422086200bad8421060b2009102f2006a7210b200521092006422088a7220c20052f01064f0d000b0b200241b0086a41186a220e2005200c4105746a220941206a2900003703002007200941186a290000370300200241b0086a41086a2201200941106a2900003703002002200941086a2900003703b008200c41016a210c20094180036a280200210d200941fc026a280200211a200941f8026a280200211802402003450d002005200c4102746a41c8056a28020021054100210c2003417f6a2209450d00034020052802c80521052009417f6a22090d000b0b201e200e2903003703002021200729030037030020222001290300370300200220022903b0083703f0042002200c3602c4032002200b3602c003200220053602bc03200241003602b80320180d000b0b200241b8036a10a20241eba1ca00ad4280808080f00084100122052900002106200241d0086a41086a2207200541086a290000370300200220063703d0082005102f41f5cac800ad4280808080e00184100122052900002106200241b8036a41086a2209200541086a290000370300200220063703b8032005102f200220113602800420124280808080c00084100322052900002106200541086a2900002108200541106a290000210a200241f0046a41186a200541186a290000370300200241f0046a41106a220b200a370300200241f0046a41086a22032008370300200220063703f0042005102f41c000102d2205450d002024ad210a200520022903d008370000200520022903b803370010200520022903f004370020200541086a2007290300370000200541186a2009290300370000200541286a2003290300370000200541306a200b290300370000200541386a200241f0046a41186a290300370000200220313703f804200220303703f0042005ad42808080808008842013428080808080028410042005102f200241003602b8032024450d01202520244105746a210f2025210103402001220341206a2101200241c0026a210520022802c402210d024002400340024002402005280200220c2f0106220e0d00410021090c010b200e4105742105200c41086a2107417f21090340024020050d00200e21090c020b200941016a210920032007412010ea06220b450d03200541606a2105200741206a2107200b417f4a0d000b0b0240200d0d00200241b8036a21090c030b200d417f6a210d200c20094102746a4194036a21050c000b0b200c20094102746a41e8026a21090b200241f0046a2011200310f20520023502f804210620022802f0042105200241003a00850402400240024002402009280200220741c000490d00200741808001490d012007418080808004490d02200241033a008004200241053a00850420022009280200360081044280808080d00021080c030b200241013a008504200220074102743a00800442808080801021080c020b200241023a008504200220074102744101723b01800442808080802021080c010b200241043a00850420022007410274410272360280044280808080c00021080b20064220862005ad8420082012841004024020022d008504450d00200241003a0085040b024020022802f404450d002005102f0b2001200f470d000c020b0b1036000b200a422086210602402019450d002019412c6c2107201b41206a210503400240200541046a280200450d002005280200102f0b2005412c6a2105200741546a22070d000b0b202f20068421062017450d00201b102f0b20022802c802210320022802c0022105024020022802c4022207450d00034020052802940321052007417f6a22070d000b0b02402003450d0041002109034002400240200920052f0106490d004100210b034002400240024020054190bdc600460d00200528020022070d0141002109410021070c020b41edb3ca00412841f8b4ca001039000b200b41016a210b20052f010421090b2005102f20072105200920072f01064f0d000b200941016a21090240200b0d00200721050c020b200720094102746a4194036a280200210541002109200b417f6a2207450d01034020052802940321052007417f6a22070d000c020b0b200941016a21090b2003417f6a22030d000b0b0240024020054190bdc600460d00200528020021072005102f2007450d00034020074190bdc600460d02200728020021052007102f2005210720050d000b0b2000200637020420002025360200200241f0086a24000f0b41edb3ca00412841f8b4ca001039000b1038000b800201037f230041d0006b220124002001412036020420012000360200200141086a2000ad42808080808004841002107302400240200128020822020d00410421000c010b200128020c210302400240200141106a280200450d0020022d000022004104490d010b20014100360220200142013703182001410b36022c200120013602282001200141186a360234200141cc006a41013602002001420137023c200141b885c7003602382001200141286a360248200141346a41d8dbc100200141386a103c1a200135022042208620013502188410080240200128021c450d002001280218102f0b410421000b2003450d002002102f0b200141d0006a240020000b910305027f017e027f017e037f230041d0006b2202240041b89bca00ad4280808080f00184100122032900002104200241086a41086a2205200341086a290000370300200220043703082003102f41c79bca00ad4280808080c00184100122032900002104200241186a41086a2206200341086a290000370300200220043703182003102f20022000370348200241c8006aad4280808080800184100322032900002100200341086a2900002104200341106a2900002107200241286a41186a2208200341186a290000370300200241286a41106a22092007370300200241286a41086a220a2004370300200220003703282003102f024041c000102d22030d001036000b200320022903083700002003200229031837001020032002290328370020200341086a2005290300370000200341186a2006290300370000200341286a200a290300370000200341306a2009290300370000200341386a2008290300370000200220013602282003ad4280808080800884200241286aad4280808080c0008410042003102f200241d0006a24000bbc0201047f230041d0006b220224002002412036020420022001360200200241086a2001ad4280808080800484100210730240024020022802082201450d00200241106a2802002103200228020c2104200241003602380240024020034104490d0020012800002105200241003602382003417c714104460d00200041086a200128000436020020002005360204410121030c010b20024100360220200242013703182002410b36022c200220023602282002200241186a360234200241cc006a41013602002002420137023c200241b885c7003602382002200241286a360248200241346a41d8dbc100200241386a103c1a200235022042208620023502188410080240200228021c450d002002280218102f0b410021030b200020033602002004450d012001102f0c010b200041003602000b200241d0006a24000be11205057f017e037f027e047f230041f0006b22052400200541c0006a41186a22064200370300200541c0006a41106a22074200370300200541c0006a41086a220842003703002005420037034041b89bca00ad4280808080f0018410012209290000210a200541e0006a41086a220b200941086a2900003703002005200a3703602009102f2008200b2903003703002005200529036037034041cabec600ad4280808080d0018410012209290000210a200b200941086a2900003703002005200a3703602009102f20072005290360220a370300200541206a41086a22092008290300370300200541206a41106a220c200a370300200541206a41186a220d200b29030037030020052005290340370320200541186a200541206a412041c8e1ca004100410010b501024002400240024002400240024020052802184101470d00410d210b4191b4c6002108410221070c010b20064200370300200742003703002008420037030020054200370340418de6c300ad4280808080e0008410012206290000210a2008200641086a2900003703002005200a3703402006102f419ce6c300ad4280808080e0008410012206290000210a200b200641086a2900003703002005200a3703602006102f20072005290360220a37030020092008290300370300200c200a370300200d200b29030037030020052005290340370320200541106a200541206a41201095012005280214410020052802101b2109024020034101460d00200541206a210d0c030b200541c0006a41186a22064200370300200541c0006a41106a220c4200370300200541c0006a41086a220842003703002005420037034041b89bca00ad4280808080f00184220e1001220d290000210a200541e0006a41086a220b200d41086a2900003703002005200a370360200d102f2008200b2903003703002005200529036037034041f8c5c600ad4280808080a00184220f1001220d290000210a200b200d41086a2900003703002005200a370360200d102f20072005290360370000200741086a220d200b290300370000200541206a41086a22102008290300370300200541206a41106a2211200c290300370300200541206a41186a2212200629030037030020052005290340370320200541086a200541206a41201095012005280208450d01200528020c20094d0d014107210b418ab4c6002108410321070b20004183203b0100200041086a200b360200200041046a2008360200200041026a20073a0000200141046a280200450d022001280200102f0c020b20064200370300200c42003703002008420037030020054200370340200e10012213290000210a200b201341086a2900003703002005200a3703602013102f2008200b29030037030020052005290360370340200f10012213290000210a200b201341086a2900003703002005200a3703602013102f20072005290360370000200d200b290300370000201020082903003703002011200c29030037030020122006290300370300200520052903403703202005200920024101746a360240200541206aad4280808080800484200541c0006aad4280808080c000841004200541206a210d0b20012802082108200128020421102001280200210c200541c0006a41186a22114200370300200541c0006a41106a22124200370300200541c0006a41086a220142003703002005420037034041b89bca00ad4280808080f0018410012206290000210a200541e0006a41086a220b200641086a2900003703002005200a3703602006102f2001200b2903003703002005200529036037034041cabec600ad4280808080d0018410012206290000210a200b200641086a2900003703002005200a3703602006102f20072005290360370000200741086a200b290300370000200541206a41086a2001290300370300200541206a41106a2012290300370300200541206a41186a20112903003703002005200529034037032020054100360248200542013703404104102d220b450d0120054284808080c0003702442005200b360240200b2009360000200b410441081031220b450d01200542888080808001370244200b20023600042005200b3602402008200541c0006a106902402008450d00200c200841286c6a21062005280244210920052802482108200c210b034002400240200920086b4120490d00200841206a2107200528024021010c010b200841206a22072008490d05200941017422012007200120074b1b22024100480d050240024020090d002002102d21010c010b200528024020092002103121010b2001450d042005200236024420052001360240200221090b200120086a220841186a200b41186a290000370000200841106a200b41106a290000370000200841086a200b41086a290000370000200520073602482008200b290000370000200b41206a290300210a02400240200920076b4108490d00200741086a21080c010b200741086a22082007490d05200941017422022008200220084b1b22024100480d050240024020090d002002102d21010c010b200120092002103121010b2001450d042005200236024420052001360240200221090b20052008360248200120076a200a3700002006200b41286a220b470d000b0b200528024421072005280248210b0240024020034101460d00024002402007200b460d00200528024021080c010b200b41016a2208200b490d05200b41017422072008200720084b1b22074100480d0502400240200b0d002007102d21080c010b2005280240200b2007103121080b2008450d0420052007360244200520083602400b2005200b41016a22013602482008200b6a41003a00000c010b024002402007200b460d00200528024021080c010b200b41016a2208200b490d04200b41017422072008200720084b1b22074100480d0402400240200b0d002007102d21080c010b2005280240200b2007103121080b2008450d0320052007360244200520083602400b2005200b41016a22093602482008200b6a41013a00000240200720096b41034b0d00200941046a22012009490d04200741017422022001200220014b1b22014100480d040240024020070d002001102d21080c010b200820072001103121080b2008450d032005200136024420052008360240200121070b2005200b41056a2201360248200820096a20043600000b200dad42808080808004842001ad4220862008ad84100402402007450d002008102f0b02402010450d00200c102f0b200041043a00000b200541f0006a24000f0b1036000b1038000bd60302057f047e230041f0006b220224002002412036020c20022001360208200241106a2001ad4280808080800484100210730240024020022802102203450d00200241186a28020021042002280214210541002101200241003a006802400240034020042001460d01200241c8006a20016a200320016a2d00003a00002002200141016a22063a00682006210120064120470d000b200241206a41186a200241c8006a41186a2903002207370300200241206a41106a200241c8006a41106a2903002208370300200241206a41086a200241c8006a41086a290300220937030020022002290348220a370320200041196a2007370000200041116a2008370000200041096a20093700002000200a370001410121010c010b0240200141ff0171450d00200241003a00680b4100210120024100360228200242013703202002410b3602442002200241086a3602402002200241206a36026c200241dc006a41013602002002420137024c200241b885c7003602482002200241c0006a360258200241ec006a41d8dbc100200241c8006a103c1a200235022842208620023502208410082002280224450d002002280220102f0b200020013a00002005450d012003102f0c010b200041003a00000b200241f0006a24000b9b06010c7f23004180016b220324002003200236020c20032001360208200341106a2002ad4220862001ad841002107302400240024002400240024020032802102204450d00200328021421052003200341186a280200360224200320043602202003200341206a10e60120032802000d0320032802042206200328022422014105762202200220064b1b22074105742202417f4c0d010240024020070d00410121080c010b2002102d2208450d030b02402006450d004100210903402001210a200341003a00782009220b41016a2109410021010240024002400340200a2001460d01200341d8006a20016a200328022022022d00003a00002003200241016a3602202003200141016a22023a00782002210120024120470d000b200341386a41186a220c200341d8006a41186a290300370300200341386a41106a220d200341d8006a41106a290300370300200341386a41086a220e200341d8006a41086a290300370300200320032903583703382007200b470d020240200b41017422012009200120094b1b220141ffffff3f712001470d002001410574220141004e0d020b1038000b200341003602240240200141ff0171450d00200341003a00780b2007450d072008102f0c070b02400240200b0d002001102d21080c010b2008200b4105742001103121080b2008450d05200141057621070b200a20026b21012008200b4105746a220b2003290338370000200b41186a200c290300370000200b41106a200d290300370000200b41086a200e29030037000020092006470d000b2003200a20026b3602240b2008450d032000200736020420002008360200200041086a20063602000c040b200041003602000c040b103d000b1036000b20034100360240200342013703382003410b36022c2003200341086a3602282003200341386a360234200341ec006a41013602002003420137025c200341b885c7003602582003200341286a360268200341346a41d8dbc100200341d8006a103c1a200335024042208620033502388410080240200328023c450d002003280238102f0b200041003602000b2005450d002004102f0b20034180016a24000ba207020a7f017e230041e0006b220124002001410036024020014201370338200028020021024101102d2103024002400240024020024101460d002003450d02200142818080801037023c20012003360238200341013a0000200028020421042000410c6a2802002203200141386a10690240024020030d0020012802402105200128023c21060c010b2004200341286c6a2107200128023c21062001280240210520042103034002400240200620056b4120490d00200541206a2108200128023821090c010b200541206a22082005490d06200641017422092008200920084b1b220a4100480d060240024020060d00200a102d21090c010b20012802382006200a103121090b2009450d052001200a36023c20012009360238200a21060b200920056a220541186a200341186a290000370000200541106a200341106a290000370000200541086a200341086a2900003700002001200836024020052003290000370000200341206a290300210b02400240200620086b4108490d00200841086a21050c010b200841086a22052008490d062006410174220a2005200a20054b1b220a4100480d060240024020060d00200a102d21090c010b20092006200a103121090b2009450d052001200a36023c20012009360238200a21060b20012005360240200920086a200b3700002007200341286a2203470d000b0b02400240200620056b4120490d00200128023821030c010b200541206a22032005490d04200641017422082003200820034b1b22084100480d040240024020060d002008102d21030c010b200128023820062008103121030b2003450d032001200836023c200120033602380b200320056a220341086a200041106a220841086a290000370000200341106a200841106a290000370000200341186a200841186a2900003700002001200541206a360240200320082900003700000c010b2003450d01200142818080801037023c20012003360238200341023a00002000280204210420034101410510312203450d0120014285808080d00037023c20012003360238200320043600010b200141246a200141386a41086a2802003600002001200129033837001c200141c4006a200141206a290000370000200141cc006a2001290208370200200141d4006a200141086a41086a290200370200200141c28289aa04360039200141023a00382001200129001937003d200141386a108a04024020020d00200041086a280200450d002004102f0b200141e0006a24000f0b1036000b1038000b880301027f024020002d0000417a6a2201410c4b0d00024002400240024002400240024020010e0d00070701070207030704050706000b200041086a2d00004101470d06200041146a280200450d06200041106a280200102f0c060b200041046a2d00000d052000410c6a280200450d05200041086a280200102f0c050b200041046a2802000d042000410c6a280200450d04200041086a280200102f0c040b200041086a2d00004107470d03200041306a280200450d032000412c6a280200102f0c030b200041046a2d00004102490d020240200041106a2802002201450d00200141d0006c2102200041086a28020041c0006a210103400240200141046a280200450d002001280200102f0b200141d0006a2101200241b07f6a22020d000b0b2000410c6a280200450d022000280208102f0c020b200041086a280200450d01200041046a280200102f0c010b200041086a2d00004106470d00200041306a280200450d002000412c6a280200102f0b02402000418c016a280200450d00200028028801102f0b0bbe0402017f097e230041c0016b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100210730240024020032802102201450d00200328021421022003200341106a41086a2802003602ac01200320013602a801200341e0006a200341a8016a108505420121040240024020032903604201520d0020034100360228200342013703202003410b3602b4012003200341086a3602b0012003200341206a3602bc01200341f4006a410136020020034201370264200341b885c7003602602003200341b0016a360270200341bc016a41d8dbc100200341e0006a103c1a2003350228422086200335022084100802402003280224450d002003280220102f0b420021040c010b200341206a41386a200341e0006a41c0006a2903002205370300200341206a41306a200341e0006a41386a2903002206370300200341206a41286a200341e0006a41306a2903002207370300200341206a41206a200341e0006a41286a2903002208370300200341206a41186a200341e0006a41206a2903002209370300200341206a41106a200341e0006a41186a290300220a370300200341206a41086a200341e0006a41106a290300220b37030020032003290368220c370320200041c0006a2005370300200041386a2006370300200041306a2007370300200041286a2008370300200041206a2009370300200041186a200a370300200041106a200b3703002000200c3703080b200020043703002002450d012001102f0c010b200042003703000b200341c0016a24000b910805017f017e047f017e027f230041e0006b2201240042002102200141386a41186a22034200370300200141386a41106a22044200370300200141386a41086a2205420037030020014200370338418de6c300ad4280808080e000841001220629000021072005200641086a290000370300200120073703382006102f41bae6c300ad4280808080e00084100122062900002107200141286a41086a2208200641086a290000370300200120073703282006102f200420012903282207370300200141086a41086a2005290300370300200141086a41106a2007370300200141086a41186a200829030037030020012001290338370308200141386a200141086a10f40202400240200128023822080d004104210841002106410021090c010b200129023c2202422088a721062002a721090b200141386a41206a200041206a2802003602002003200041186a2902003703002004200041106a2902003703002005200041086a2902003703002001200029020037033802400240024020062009470d00024020062002a7470d00200641016a22002006490d03200641017422052000200520004b1bad42247e2207422088a70d032007a722004100480d030240024020060d002000102d21080c010b2008200641246c2000103121080b2008450d02200242808080807083200041246ead8421020b2002422088a721060b2008200641246c22096a22002001290338370200200041206a200141386a41206a280200360200200041186a200141386a41186a2204290300370200200041106a200141386a41106a2205290300370200200041086a200141386a41086a220029030037020020044200370300200542003703002000420037030020014200370338418de6c300ad4280808080e000841001220429000021072000200441086a290000370300200120073703382004102f41bae6c300ad4280808080e00084100122042900002107200141286a41086a2203200441086a290000370300200120073703282004102f200520012903282207370300200141086a41086a2000290300370300200141086a41106a2007370300200141086a41186a2003290300370300200120012903383703082001412036023c2001200141086a3602382008200641016a2200200141386a10f502024020002006490d00200941246a21002008210603400240024020062d0000220541044b0d0002400240024020050e050400010204040b2006410c6a280200450d03200641086a280200102f0c030b2006410c6a280200450d02200641086a280200102f0c020b2006410c6a280200450d01200641086a280200102f0c010b200641086a280200450d00200641046a280200102f0b200641246a21062000415c6a22000d000b0b02402002a7450d002008102f0b200141e0006a24000f0b1036000b1038000b13002000410a360204200041ccebc3003602000b34002000418de6c30036020420004100360200200041146a410e360200200041106a41acf6c300360200200041086a42063702000b2c01017f02404104102d22020d001036000b20004284808080c00037020420002002360200200241003600000b6301027f230041206b22022400200241003602082002420837030002404104102d22030d001036000b20024204370214200220033602104100200241106a1069200041086a200228021836020020002002290310370200200210f403200241206a24000bda0101057f230041206b22022400200241186a22034200370300200241106a22044200370300200241086a220542003703002002420037030002404120102d2206450d0020062002290300370000200641186a2003290300370000200641106a2004290300370000200641086a20052903003700004120102d2203450d0020032006290000370000200341186a200641186a290000370000200341106a200641106a290000370000200341086a200641086a2900003700002006102f200042a0808080800437020420002003360200200241206a24000f0b1036000b2b01017f02404101102d22020d001036000b200042818080801037020420002002360200200241003a00000bae0101017f02404104102d2202450d002002410036000020024104410810312202450d00200241003a000420024108411510312202450d00200242003700052002410d6a420037000020024115412a10312202450d00200242003700152002411d6a42003700002002412a41d40010312202450d002002420037003520024200370025200042d4808080d008370204200020023602002002413d6a42003700002002412d6a42003700000f0b1036000b8c1e0a047f017e017f017e047f017e017f017e067f017e230041e0016b2201240020014198016a41186a2202420037030020014198016a41106a2203420037030020014198016a41086a220442003703002001420037039801418de6c300ad4280808080e000842205100122062900002107200141c8006a41086a2208200641086a290000370300200120073703482006102f20042008290300370300200120012903483703980141bc80c400ad4280808080e00184100122092900002107200141b8016a41086a2206200941086a290000370300200120073703b8012009102f200320012903b8012207370300200141f8006a41086a22092004290300370300200141f8006a41106a220a2007370300200141f8006a41186a220b20062903003703002001200129039801370378200141f8006aad220c428080808080048422071005200242003703002003420037030020044200370300200142003703980120051001220d290000210e2008200d41086a2900003703002001200e370348200d102f20042008290300370300200120012903483703980141d480c400ad4280808080b002841001220d290000210e2006200d41086a2900003703002001200e3703b801200d102f200320012903b801220e37030020092004290300370300200a200e370300200b2006290300370300200120012903980137037820071005200242003703002003420037030020044200370300200142003703980120051001220d290000210e2008200d41086a2900003703002001200e370348200d102f20042008290300370300200120012903483703980141f880c400ad42808080808002841001220d290000210e2006200d41086a2900003703002001200e3703b801200d102f200320012903b801220e37030020092004290300370300200a200e370300200b2006290300370300200120012903980137037820071005200242003703002003420037030020044200370300200142003703980120051001220d290000210e2008200d41086a2900003703002001200e370348200d102f200420082903003703002001200129034837039801419ce6c300ad4280808080e000841001220d290000210e2006200d41086a2900003703002001200e3703b801200d102f200320012903b801220e37030020092004290300370300200a200e370300200b200629030037030020012001290398013703782001200141f8006a41201095012001280204210f0240200128020022104101470d00200710050b200242003703002003420037030020044200370300200142003703980120051001220d29000021052008200d41086a29000037030020012005370348200d102f20042008290300370300200120012903483703980141a2e6c300ad4280808080a001841001220829000021052006200841086a290000370300200120053703b8012008102f200320012903b801370000200341086a200629030037000020092004290300370300200a2003290300370300200b20022903003703002001200129039801370378200141b8016a200141f8006a412010ad02024002400240024020012d00b80122040d00200141b0016a200141d1016a290000370300200141a8016a200141c9016a290000370300200141a0016a200141c1016a290000370300200120012900b901370398010c010b2007100520014198016a41186a2208200141d1016a29000037030020014198016a41106a2206200141c9016a29000037030020014198016a41086a2202200141c1016a290000370300200120012900b9013703980120044101460d010b200141206a4200370300200141186a4200370300200141106a4200370300200142003703080c010b200141086a41186a2008290300370300200141086a41106a2006290300370300200141086a41086a200229030037030020012001290398013703080b20014198016a41186a2208420037030020014198016a41106a2206420037030020014198016a41086a220442003703002001420037039801418de6c300ad4280808080e00084220e100122092900002105200141c8006a41086a2202200941086a290000370300200120053703482009102f20042002290300370300200120012903483703980141bae6c300ad4280808080e000841001220a2900002105200141b8016a41086a2209200a41086a290000370300200120053703b801200a102f200320012903b801370000200341086a22112009290300370000200141f8006a41086a22122004290300370300200141f8006a41106a22132006290300370300200141f8006a41186a221420082903003703002001200129039801370378200141b8016a200141f8006a10f4020240024020012802b801220a0d004104210a420021050c010b2007100520012902bc0121050b200f410020101b210b2008420037030020064200370300200442003703002001420037039801200e1001220d290000210e2002200d41086a2900003703002001200e370348200d102f20042002290300370300200120012903483703980141ace6c300ad4280808080e0018410012202290000210e2009200241086a2900003703002001200e3703b8012002102f200320012903b801370000201120092903003700002012200429030037030020132006290300370300201420082903003703002001200129039801370378200141b8016a200141f8006a412010ad02024002400240024020012d00b80122030d00200141b0016a200141d1016a290000370300200141a8016a200141c9016a290000370300200141a0016a200141c1016a290000370300200120012900b901370398010c010b2007100520014198016a41186a2204200141d1016a29000037030020014198016a41106a2208200141c9016a29000037030020014198016a41086a2206200141c1016a290000370300200120012900b9013703980120034101460d010b200141c0006a4200370300200141386a4200370300200141306a4200370300200142003703280c010b200141286a41186a2004290300370300200141286a41106a2008290300370300200141286a41086a200629030037030020012001290398013703280b02400240200b41fb01490d00200b41857e6a2204450d00418de6c300ad4280808080e00084100122032900002107200141c8006a41086a2208200341086a290000370300200120073703482003102f4193e6c300ad4280808080900184100122032900002107200141b8016a41086a2206200341086a290000370300200120073703b8012003102f20012004360278200c4280808080c00084100322032900002107200341086a290000210e200341106a290000210c20014198016a41186a2204200341186a29000037030020014198016a41106a2202200c37030020014198016a41086a2209200e37030020012007370398012003102f41c000102d2203450d0120032001290348370000200320012903b8013700102003200129039801370020200341086a2008290300370000200341186a2006290300370000200341286a2009290300370000200341306a2002290300370000200341386a20042903003700002003ad428080808080088410052003102f0b410121020240101b2207422088a72206450d002007a721020b41002103200141003a00d8012002210402400240024002400240034020062003460d01200141b8016a20036a20042d00003a00002001200341016a22083a00d801200441016a21042008210320084120470d000b200141c8006a41086a200141b8016a41086a290300370300200141c8006a41106a200141b8016a41106a290300370300200141c8006a41186a200141b8016a41186a290300370300200120012903b80137034802402006450d002002102f0b4120102d2203450d0520032001290308370000200341186a2208200141086a41186a290300370000200341106a2206200141086a41106a290300370000200341086a2202200141086a41086a2903003700004120102d2204450d0520042003290000370000200441186a2008290000370000200441106a2006290000370000200441086a20022900003700002003102f200141e8006a2004ad4280808080800484101c10732004102f20012802682208450d04200141f0006a2802002106200128026c210941002103200141003a00d801034020062003460d02200141b8016a20036a200820036a2d00003a00002001200341016a22043a00d8012004210320044120470d000b200141f8006a41086a200141b8016a41086a22042903002207370300200141f8006a41106a200141b8016a41106a2206290300220e370300200141f8006a41186a200141b8016a41186a2202290300220c370300200120012903b8012215370378200420073703002006200e3703002002200c370300200120153703b80120014198016a41026a220d200141f5006a41026a2d00003a0000200120012f00753b01980120054220882207a722032005a7470d030240200341016a220f2003490d002007a74101742210200f200f2010491bad42247e2207422088a70d002007a7220f41004e0d030b1038000b0240200341ff0171450d00200141003a00d8010b41a18ec400412c200141b8016a41a0ebc30041d08ec400103e000b0240200341ff0171450d00200141003a00d8010b41a18ec400412c200141b8016a41a0ebc30041e08ec400103e000b0240024020030d00200f102d210a0c010b200a200341246c200f1031210a0b200a450d0220054220882207a72103200f41246ead21050b200a200341246c6a220341003a0000200320012903b801370001200341096a2004290300370000200341116a2006290300370000200341196a2002290300370000200320012f0198013b0021200341236a200d2d00003a00002007422086200542ffffffff0f83844280808080107c21052009450d002008102f0b200020012903083700102000200b36020020002001290348370030200041286a200141086a41186a290300370000200041206a200141086a41106a290300370000200041186a200141086a41086a290300370000200041386a200141c8006a41086a290300370000200041c0006a200141c8006a41106a290300370000200041c8006a200141c8006a41186a290300370000200041086a20053702002000200a360204200041e8006a200141286a41186a290300370000200041e0006a200141286a41106a290300370000200041d8006a200141286a41086a29030037000020002001290328370050200141e0016a24000f0b1036000bbc0703037f047e037f23002202210320024180036b41607122022400200141186a22042900002105200420022903f80137000020012900102106200120022903f00137001020012900082107200120022903e801370008200241003a00e00120012900002108200120022903e0013700002002200537039801200220063703900120022007370388012002200837038001200141206a2d00002104200241e0016a41176a22092005370000200241e0016a41106a220a200229009101370300200241e0016a41086a220b20022900890137030020022002290081013703e0010240024002402008a741ff01714101470d00200241186a41176a2009290000370000200241186a41106a200a290300370300200241186a41086a200b290300370300200220022903e001370318200220043a0037200241d0016a200241186a109404200241e0016a20022802d001220420022802d80110950420022d00ec014102470d02200241003602c802200242013703c002200241d0026a41146a4129360200200241dc026a410b360200200241103602ec02200241bd98ca003602e8022002410b3602d402200241073602f402200241ae85c7003602f0022002200241d0016a3602e0022002200241f0026a3602d8022002200241e8026a3602d0022002200241c0026a3602fc02200241386a41146a41033602002002420337023c200241b48fc4003602382002200241d0026a360248200241fc026a41d8dbc100200241386a103c1a20023502c80242208620023502c002841008024020022802c402450d0020022802c002102f0b2000410036022020022802d401450d0120022802d001102f200324000f0b200041003602200b200324000f0b20024180016a200241e0016a41d00010e8061a024020022802d401450d002004102f0b200241d0026a41086a220420024180016a41086a28020036020020022002290380013703d002200241386a2002418c016a41c20010e8061a200141206a200241f9006a2d00003a0000200141186a200241f1006a290000370000200141106a200241e9006a290000370000200141086a200241e1006a29000037000020012002290059370000200241e0016a41186a200241186a41186a2903002205370300200241e0016a41106a200241186a41106a2903002208370300200241e0016a41086a200241186a41086a2903002206370300200020022903182207370200200041086a2006370200200041106a2008370200200041186a2005370200200220073703e001200041206a20022903d002370200200041286a2004280200360200200324000bbe0303027f037e027f230041c0006b2202240041bd98ca00ad4280808080800284100122032900002104200241086a200341086a290000370300200220043703002003102f41ae85c700ad4280808080f00084100122032900002104200241106a41086a200341086a290000370300200220043703102003102f02404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100322012900002104200141086a2900002105200141106a2900002106200241206a41186a2207200141186a290000370300200241206a41106a22082006370300200241206a41086a2005370300200220043703202001102f2003102f41c000102d2203450d00200320022903003700002003200229031037001020032002290320370020200042c0808080800837020420002003360200200341086a200241086a290300370000200341186a200241106a41086a290300370000200341286a200241206a41086a290300370000200341306a2008290300370000200341386a2007290300370000200241c0006a24000f0b1036000be60b030a7f017e027f230041a0026b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100210730240024020032802102204450d00200328021421052003200341106a41086a28020036026420032004360260200341e8006a200341e0006a10980302400240024020032802682206450d00200328026c2107024020032802642201450d00200341e8006a41086a280200210820032001417f6a220936026420032003280260220a41016a220b360260200a2d0000220141014b0d004100210c02400240024002400240024020010e020100010b41002101200341003a009802034020092001460d02200341f8016a20016a200a20016a220241016a2d00003a00002003200241026a3602602003200141016a22023a0098022002210120024120470d000b200341b8016a41086a200341f8016a41086a290300220d37030020034198016a41186a200341f8016a41186a29030037030020034198016a41106a200341f8016a41106a29030037030020034198016a41086a200d3703002003200920026b2209360264200320032903f801220d3703b8012003200d370398014101210c200a20026a41016a210b0b200341f8006a41186a20034198016a41186a290300370300200341f8006a41106a20034198016a41106a290300370300200341f8006a41086a20034198016a41086a29030037030020032003290398013703782009450d0420032009417f6a22093602642003200b41016a360260200b2d0000220141014b0d044100210220010e020201020b20034100360264200141ff0171450d03200341003a0098020c030b41002101200341003a009802034020092001460d02200341f8016a20016a200b20016a220241016a2d00003a00002003200241026a3602602003200141016a22023a0098022002210120024120470d000b200341b8016a41086a200341f8016a41086a290300220d37030020034198016a41186a200341f8016a41186a29030037030020034198016a41106a200341f8016a41106a29030037030020034198016a41086a200d3703002003200920026b360264200320032903f801220d3703b8012003200d37039801410121020b200341206a41186a220120034198016a41186a290300370300200341206a41106a220920034198016a41106a290300370300200341206a41086a220a20034198016a41086a290300370300200341c0006a41086a220b200341f8006a41086a290300370300200341c0006a41106a220e200341f8006a41106a290300370300200341c0006a41186a220f200341f8006a41186a290300370300200320032903980137032020032003290378370340200c4102460d03200020083602082000200736020420002006360200200341f8016a41086a2206200b290300370300200341f8016a41106a220b200e290300370300200341f8016a41186a2207200f290300370300200341d8016a41086a2208200a290300370300200341d8016a41106a220a2009290300370300200341d8016a41186a22092001290300370300200320032903403703f801200320032903203703d801200320032f011e3b01b801200041256a20072903003700002000411d6a200b290300370000200041156a2006290300370000200020032903f80137000d2000412d6a20023a00002000412e6a20032903d801370000200041366a20082903003700002000413e6a200a290300370000200041c6006a2009290300370000200041ce006a20032f01b8013b00000c040b20034100360264200141ff0171450d00200341003a0098020b2007450d002006102f0b4102210c0b200341003602e001200342013703d8012003410b3602bc012003200341086a3602b8012003200341d8016a360298012003418c026a4101360200200342013702fc01200341b885c7003602f8012003200341b8016a3602880220034198016a41d8dbc100200341f8016a103c1a20033502e00142208620033502d80184100820032802dc01450d0020032802d801102f0b2000200c3a000c2005450d012004102f0c010b200041023a000c0b200341a0026a24000be30703037f047e037f230022022103200241a0036b41607122022400200141186a220429000021052004200229039802370000200129001021062001200229039002370010200129000821072001200229038802370008200241003a0080022001290000210820012002290380023700002002200537039801200220063703900120022007370388012002200837038001200141206a2d0000210420024180026a41176a2209200537000020024180026a41106a220a20022900910137030020024180026a41086a220b2002290089013703002002200229008101370380020240024002402008a741ff01714101470d00200241186a41176a2009290000370000200241186a41106a200a290300370300200241186a41086a200b2903003703002002200229038002370318200220043a0037200241f0016a200241186a10970420024180026a20022802f001220420022802f80110980420022d0090024102470d02200241003602e802200242013703e002200241f0026a41146a4129360200200241fc026a410b3602002002410736028c03200241eba1ca00360288032002410b3602f4022002410a360294032002418bc6c800360290032002200241f0016a36028003200220024190036a3602f802200220024188036a3602f0022002200241e0026a36029c03200241386a41146a41033602002002420337023c200241b48fc4003602382002200241f0026a3602482002419c036a41d8dbc100200241386a103c1a20023502e80242208620023502e002841008024020022802e402450d0020022802e002102f0b200041023a003020022802f401450d0120022802f001102f200324000f0b200041023a00300b200324000f0b20024180016a20024180026a41d80010e8061a024020022802f401450d002004102f0b200241f0026a41106a220420024180016a41106a280200360200200241f0026a41086a220920024180016a41086a29030037030020022002290380013703f002200241386a20024194016a41c20010e8061a200141206a200241f9006a2d00003a0000200141186a200241f1006a290000370000200141106a200241e9006a290000370000200141086a200241e1006a2900003700002001200229005937000020024180026a41186a200241186a41186a290300220537030020024180026a41106a200241186a41106a290300220837030020024180026a41086a200241186a41086a2903002206370300200020022903182207370200200041086a2006370200200041106a2008370200200041186a20053702002002200737038002200041206a20022903f002370200200041286a2009290300370200200041306a2004280200360200200324000bbe0303027f037e027f230041c0006b2202240041eba1ca00ad4280808080f00084100122032900002104200241086a200341086a290000370300200220043703002003102f418bc6c800ad4280808080a00184100122032900002104200241106a41086a200341086a290000370300200220043703102003102f02404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100322012900002104200141086a2900002105200141106a2900002106200241206a41186a2207200141186a290000370300200241206a41106a22082006370300200241206a41086a2005370300200220043703202001102f2003102f41c000102d2203450d00200320022903003700002003200229031037001020032002290320370020200042c0808080800837020420002003360200200341086a200241086a290300370000200341186a200241106a41086a290300370000200341286a200241206a41086a290300370000200341306a2008290300370000200341386a2007290300370000200241c0006a24000f0b1036000b840e030c7f017e037f230041a0026b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100210730240024020032802102201450d00200328021421042003200341106a41086a28020036026c20032001360268200341f8016a200341e8006a10980302400240024020032802f8012205450d0020032802fc0121060240024002400240200328026c22074104490d00200341f8016a41086a280200210820032007417c6a220236026c20032003280268220941046a220a3602682002450d002009280000210b20032007417b6a220c36026c2003200a41016a360268200a2d0000220d41014b0d0041002102200d0e020201020b20060d020c030b410121020b200341f4006a41026a200341d8016a41026a2d00003a0000200320032f00d8013b01740240200c450d0020032007417a6a220c36026c2003200a41026a220d360268200a2d0001220a41014b0d004100210e024002400240024002400240200a0e020100010b4100210a200341003a0098022007417a6a210e4179210c0340200e200a460d02200341f8016a200a6a2009200a6a220d41066a2d00003a000020032007200c6a36026c2003200d41076a3602682003200a41016a220d3a009802200c417f6a210c200d210a200d4120470d000b200341b8016a41086a200341f8016a41086a290300220f37030020034198016a41186a200341f8016a41186a29030037030020034198016a41106a200341f8016a41106a29030037030020034198016a41086a200f370300200320032903f801220f3703b8012003200f370398012007200d6b417a6a210c2009200d6a41066a210d4101210e0b200341f8006a41186a20034198016a41186a290300370300200341f8006a41106a20034198016a41106a290300370300200341f8006a41086a20034198016a41086a2903003703002003200329039801370378200c450d042003200c417f6a36026c2003200d41016a360268200d2d0000220a41014b0d0441002107200a0e020201020b200a41ff0171450d03200341003a0098020c030b4100210a200341003a009802200c417f6a2109200c417e6a210703402009200a460d02200341f8016a200a6a200d200a6a220c41016a2d00003a00002003200c41026a3602682003200a41016a220c3a0098022003200736026c2007417f6a2107200c210a200c4120470d000b200341b8016a41086a200341f8016a41086a290300220f37030020034198016a41186a200341f8016a41186a29030037030020034198016a41106a200341f8016a41106a29030037030020034198016a41086a200f370300200320032903f801220f3703b8012003200f37039801410121070b200341206a41186a220a20034198016a41186a290300370300200341206a41106a220c20034198016a41106a290300370300200341206a41086a220d20034198016a41086a290300370300200341c0006a41086a2209200341f8006a41086a290300370300200341c0006a41106a2210200341f8006a41106a290300370300200341c0006a41186a2211200341f8006a41186a290300370300200320032903980137032020032003290378370340200341e4006a41026a2212200341f4006a41026a2d00003a0000200320032f01743b016420024102460d042000200b36020c200020083602082000200636020420002005360200200341b8016a41026a220520122d00003a0000200341f8016a41086a22062009290300370300200341f8016a41106a22092010290300370300200341f8016a41186a22082011290300370300200341d8016a41086a220b200d290300370300200341d8016a41106a220d200c290300370300200341d8016a41186a220c200a290300370300200320032f01643b01b801200320032903403703f801200320032903203703d801200320032f011e3b019801200041136a20052d00003a0000200020032f01b8013b0011200041146a200e3a0000200041156a20032903f8013700002000411d6a2006290300370000200041256a20092903003700002000412d6a2008290300370000200041356a20073a0000200041366a20032903d8013700002000413e6a200b290300370000200041c6006a200d290300370000200041ce006a200c290300370000200041d6006a20032f0198013b00000c050b200a41ff0171450d00200341003a0098020b2006450d010b2005102f0b410221020b200341003602e001200342013703d8012003410b3602bc012003200341086a3602b8012003200341d8016a360298012003418c026a4101360200200342013702fc01200341b885c7003602f8012003200341b8016a3602880220034198016a41d8dbc100200341f8016a103c1a20033502e00142208620033502d80184100820032802dc01450d0020032802d801102f0b200020023a00102004450d012001102f0c010b200041023a00100b200341a0026a24000bad0603037f047e037f230022022103200241a0026b41607122022400200141186a220429000021052004200229039801370000200129001021062001200229039001370010200129000821072001200229038801370008200241003a00800120012900002108200120022903800137000020022005370338200220063703302002200737032820022008370320200141206a2d0000210420024180016a41176a2209200537000020024180016a41106a220a200229003137030020024180016a41086a220b200229002937030020022002290021370380010240024002402008a741ff01714101470d00200241176a2009290000370000200241106a200a290300370300200241086a200b2903003703002002200229038001370300200220043a001f200241f0006a2002109a0420024180016a200228027022042002280278109b0420022d0084014102470d02200241003602e801200242013703e001200241f0016a41146a4129360200200241fc016a410b3602002002410736028c02200241eba1ca00360288022002410b3602f4012002410a36029402200241a5c6c800360290022002200241f0006a36028002200220024190026a3602f801200220024188026a3602f0012002200241e0016a36029c02200241206a41146a410336020020024203370224200241b48fc4003602202002200241f0016a3602302002419c026a41d8dbc100200241206a103c1a20023502e80142208620023502e001841008024020022802e401450d0020022802e001102f0b200041003602002002280274450d012002280270102f200324000f0b200041003602000b200324000f0b20024180016a4104722109200228028001210a02402002280274450d002004102f0b200241206a200941c20010e8061a200141206a200241e1006a2d00003a0000200141186a200241d9006a290000370000200141106a200241d1006a290000370000200141086a200241c9006a29000037000020012002290041370000200020022903003700042000410c6a200241086a290300370000200041146a200241106a2903003700002000411c6a200241186a29030037000020004101360200200041246a200a360200200324000bbe0303027f037e027f230041c0006b2202240041eba1ca00ad4280808080f00084100122032900002104200241086a200341086a290000370300200220043703002003102f41a5c6c800ad4280808080a00184100122032900002104200241106a41086a200341086a290000370300200220043703102003102f02404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100322012900002104200141086a2900002105200141106a2900002106200241206a41186a2207200141186a290000370300200241206a41106a22082006370300200241206a41086a2005370300200220043703202001102f2003102f41c000102d2203450d00200320022903003700002003200229031037001020032002290320370020200042c0808080800837020420002003360200200341086a200241086a290300370000200341186a200241106a41086a290300370000200341286a200241206a41086a290300370000200341306a2008290300370000200341386a2007290300370000200241c0006a24000f0b1036000bbd0b03097f017e027f23004190026b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100210730240024020032802102204450d00200328021421052003200341186a280200360264200320043602602003200341e0006a10e6014102210602400240024020032802000d0020032802642201450d002003280204210720032001417f6a220836026420032003280260220941016a220a36026020092d0000220141014b0d004100210b02400240024002400240024020010e020100010b41002101200341003a008802034020082001460d02200341e8016a20016a200920016a220241016a2d00003a00002003200241026a3602602003200141016a22023a0088022002210120024120470d000b200341a8016a41086a200341e8016a41086a290300220c37030020034188016a41186a200341e8016a41186a29030037030020034188016a41106a200341e8016a41106a29030037030020034188016a41086a200c3703002003200820026b2208360264200320032903e801220c3703a8012003200c370388014101210b200920026a41016a210a0b200341e8006a41186a20034188016a41186a290300370300200341e8006a41106a20034188016a41106a290300370300200341e8006a41086a20034188016a41086a29030037030020032003290388013703682008450d0420032008417f6a22083602642003200a41016a360260200a2d0000220141014b0d044100210220010e020201020b20034100360264200141ff0171450d03200341003a0088020c030b41002101200341003a008802034020082001460d02200341e8016a20016a200a20016a220241016a2d00003a00002003200241026a3602602003200141016a22023a0088022002210120024120470d000b200341a8016a41086a200341e8016a41086a290300220c37030020034188016a41186a200341e8016a41186a29030037030020034188016a41106a200341e8016a41106a29030037030020034188016a41086a200c3703002003200820026b360264200320032903e801220c3703a8012003200c37038801410121020b200341206a41186a220120034188016a41186a290300370300200341206a41106a220620034188016a41106a290300370300200341206a41086a220820034188016a41086a290300370300200341c0006a41086a2209200341e8006a41086a290300370300200341c0006a41106a220a200341e8006a41106a290300370300200341c0006a41186a220d200341e8006a41186a290300370300200320032903880137032020032003290368370340200b4102470d02200b21060c010b20034100360264200141ff0171450d00200341003a0088020b200341003602d001200342013703c8012003410b3602ac012003200341086a3602a8012003200341c8016a36028801200341fc016a4101360200200342013702ec01200341b885c7003602e8012003200341a8016a3602f80120034188016a41d8dbc100200341e8016a103c1a20033502d00142208620033502c80184100820032802cc01450d0120032802c801102f0c010b200341e8016a41186a220e200d290300370300200341e8016a41106a220d200a290300370300200341e8016a41086a220a2009290300370300200341c8016a41086a22092008290300370300200341c8016a41106a22082006290300370300200341c8016a41186a22062001290300370300200320032903403703e801200320032903203703c801200320032f011e3b01a80120002007360200200020032903e8013700052000410d6a200a290300370000200041156a200d2903003700002000411d6a200e290300370000200041256a20023a0000200041266a20032903c8013700002000412e6a2009290300370000200041366a20082903003700002000413e6a2006290300370000200041c6006a20032f01a8013b0000200b21060b200020063a00042005450d012004102f0c010b200041023a00040b20034190026a24000bd20201057f230041206b22032400024002400240200241046a2204417f4c0d000240024020040d00410121050c010b2004102d2205450d020b200341003602102003200436020c200320053602082002200341086a106902400240200328020c2206200328021022056b2002490d00200328020821040c010b200520026a22042005490d03200641017422072004200720044b1b22074100480d030240024020060d002007102d21040c010b200328020820062007103121040b2004450d022003200736020c20032004360208200721060b200420056a2001200210e8061a2003200520026a2202ad4220862004ad84100622052900003703002005102f200341146a200420026a360200200341003a0018200320043602102003200341086a36020c200320033602082000200341086a106c02402006450d002004102f0b200341206a24000f0b103d000b1036000b1038000bde0102037f017e230041206b220324000240024020024105744104722204417f4c0d002004102d2205450d0120034100360208200320043602042003200536020020022003106902402002450d002002410574210203402003200141106a4108108201200129030021062003200141086a290300370318200320063703102003200341106a41101082012003200141186a2d00003a00102003200341106a4101108201200141206a2101200241606a22020d000b0b20002003290300370200200041086a200341086a280200360200200341206a24000f0b103d000b1036000b1300200041023602042000418491c4003602000b34002000419c9eca0036020420004100360200200041146a4107360200200041106a41b898c400360200200041086a42073702000b130020004101360204200041c0a5c4003602000bfa0101057f230041106b22022400024002404111102d2203450d002002421137020420022003360200410d200210690240024020022802042204200228020822036b410d490d002003410d6a2105200228020021040c010b2003410d6a22052003490d02200441017422062005200620054b1b22064100480d020240024020040d002006102d21040c010b200228020020042006103121040b2004450d0120022006360204200220043602000b20022005360208200420036a220341002900e7ea43370000200341056a41002900ecea4337000020002002290300370200200041086a2002280208360200200241106a24000f0b1036000b1038000ba30f07047f017e047f017e037f027e017f230041f0006b22012400200141c0006a41186a4200370300200141c0006a41106a22024200370300200141c0006a41086a2203420037030020014200370340419c9eca00ad4280808080f000841001220429000021052003200441086a290000370300200120053703402004102f41a5c6c800ad4280808080a00184100122042900002105200141306a41086a2206200441086a290000370300200120053703302004102f200220012903302205370300200141106a41086a2003290300370300200141106a41106a2005370300200141106a41186a200629030037030020012001290340370310200141c0006a200141106a412010aa0220012802402203410120031b21074102210802400240024002402001290244420020031b2205422088a72203450d002003410574210241002104200721030240034020002003460d01200420032000412010ea0622064100476a21042006450d01200341206a2103200241606a22020d000c020b0b200141c0006a41186a4200370300200141c0006a41106a22094200370300200141c0006a41086a2200420037030020014200370340419c9eca00ad4280808080f0008410012202290000210a200141306a41086a2203200241086a2900003703002001200a3703302002102f200020032903003703002001200129033037034041bc9eca00ad4280808080a0028410012202290000210a2003200241086a2900003703002001200a3703302002102f20092001290330220a370300200141106a41086a2000290300370300200141106a41106a200a370300200141106a41186a200329030037030020012001290340370310200141c0006a200141106a10fe0320012802402200410420001b210b4100210302400240024002402001290244420020001b220a422088a7220c41014b0d00200c0e020201020b200c2100034020032000410176220220036a22062004200b20064102746a280200491b2103200020026b220041014b0d000b0b4100210802402004200b20034102746a2802002200470d00410021060c020b2003200420004b6a21030b200141c0006a41186a22084200370300200141c0006a41106a220d4200370300200141c0006a41086a2202420037030020014200370340419c9eca00ad4280808080f0008410012206290000210e200141306a41086a2200200641086a2900003703002001200e3703302006102f200220002903003703002001200129033037034041a5c6c800ad4280808080a0018410012206290000210e2000200641086a2900003703002001200e3703302006102f20092001290330370000200941086a2000290300370000200141106a41086a2002290300370300200141106a41106a200d290300370300200141106a41186a200829030037030020012001290340370310200141306a200141106aad428080808080048410021073024002400240024020012802302202450d00200128023421062001200028020036024420012002360240200141086a200141c0006a10e6012001280208450d01410021000c020b2001420037024420014101360240200141c0006a10f10321000c020b200128020c21000b2006450d002002102f0b20002000418094ebdc036e22024180ec94a37c6c6aad4280fd87d1007e220f428094ebdc0380210e2003200c4b0d020240200c200aa7470d00200c41016a2200200c490d05200c4101742206200020002006491b220041ffffffff03712000470d05200041027422004100480d0502400240200c0d002000102d210b0c010b200b200c41027420001031210b0b200b450d042000410276ad210a0b200b20034102746a220041046a2000200c20036b41027410e9061a20002004360200200a42ffffffff0f83210a41012106200c41016a220c20024180fd87d1006c200ea76a200f200e4280ec94a37c7e7c4280cab5ee01566a4b21080b200141c0006a41186a220d4200370300200141c0006a41106a22104200370300200141c0006a41086a2200420037030020014200370340419c9eca00ad4280808080f0008410012202290000210e200141306a41086a2203200241086a2900003703002001200e3703302002102f200020032903003703002001200129033037034041bc9eca00ad4280808080a0028410012202290000210e2003200241086a2900003703002001200e3703302002102f20092001290330370000200941086a2003290300370000200141106a41086a2000290300370300200141106a41106a2010290300370300200141106a41186a200d2903003703002001200129034037031002400240200b0d00200141106aad428080808080048410050c010b200141203602442001200141106a360240200b200c200141c0006a10a304200aa7450d00200b102f0b2006450d00200141106a41086a2004ad37030020014102360210200141c0006a200141106a1096022001413b6a200141c0006a41086a28020036000020012001290340370033200141cc006a200141376a290000370000200141c6a4b9da04360041200141023a004020012001290030370045200141c0006a108a042001410136024020012004360244200141c0006a1087040b02402005a7450d002007102f0b200141f0006a240020080f0b419ae3c300411e41f8b4ca001039000b1036000b1038000b940201057f230041106b220324000240024002402001410274220441046a2205417f4c0d000240024020050d00410121060c010b2005102d2206450d020b2003410036020820032005360204200320063602002001200310690240024020032802042206200328020822016b2004490d00200328020021050c010b200120046a22052001490d03200641017422072005200720054b1b22074100480d030240024020060d002007102d21050c010b200328020020062007103121050b2005450d022003200736020420032005360200200721060b200520016a2000200410e8061a2002290200200120046aad4220862005ad84100402402006450d002005102f0b200341106a24000f0b103d000b1036000b1038000bb50f04047f017e037f047e230041f0056b22022400200241286a200110e6010240024002400240024020022802280d0020012802042203450d02200128020022042d0000210520012003417f6a3602042001200441016a360200024002400240200541ff00714104470d0020054118744118754100480d01420221060c020b200042033703680c060b20024180046a2001109b0320022d0080044102460d04200241d8036a41206a20024180046a41206a280200360200200241d8036a41186a20024180046a41186a290300370300200241d8036a41106a20024180046a41106a290300370300200241d8036a41086a20024180046a41086a29030037030020022002290380043703d80320012802042205450d04200128020022042d0000210320012005417f6a3602042001200441016a360200200341024b0d04024002400240024002400240024020030e03000102000b41002103200241003a00e0012005417f6a2107417e21080240034020072003460d01200241a0016a20036a200420036a220941016a2d00003a00002001200520086a3602042001200941026a3602002002200341016a22093a00e0012008417f6a210820092103200941c000470d000b200241b0056a41386a200241a0016a41386a290300220a370300200241b0056a41306a200241a0016a41306a2903002206370300200241b0056a41286a200241a0016a41286a290300220b370300200241b0056a41206a200241a0016a41206a290300220c370300200241b0056a41186a200241a0016a41186a290300220d370300200241e8046a41086a200241a0016a41086a290300370300200241e8046a41106a200241a0016a41106a290300370300200241e8046a41186a200d370300200241e8046a41206a200c370300200241e8046a41286a200b370300200241e8046a41306a2006370300200241e8046a41386a200a370300200220022903a0013703e8042009417f7320056a2105200420096a41016a2104410021030c030b200341ff0171450d0a200241003a00e0010c0a0b41002103200241003a00e0012005417f6a2107417e21080240034020072003460d01200241a0016a20036a200420036a220941016a2d00003a00002001200520086a3602042001200941026a3602002002200341016a22093a00e0012008417f6a210820092103200941c000470d000b200241b0056a41386a200241a0016a41386a290300220a370300200241b0056a41306a200241a0016a41306a2903002206370300200241b0056a41286a200241a0016a41286a290300220b370300200241b0056a41206a200241a0016a41206a290300220c370300200241b0056a41186a200241a0016a41186a290300220d370300200241e8046a41086a200241a0016a41086a290300370300200241e8046a41106a200241a0016a41106a290300370300200241e8046a41186a200d370300200241e8046a41206a200c370300200241e8046a41286a200b370300200241e8046a41306a2006370300200241e8046a41386a200a370300200220022903a0013703e8042009417f7320056a210541012103200420096a41016a21040c020b200341ff0171450d09200241003a00e0010c090b41002103200241003a00e1012005417f6a2107417e2108034020072003460d02200241a0016a20036a200420036a220941016a2d00003a00002001200520086a3602042001200941026a3602002002200341016a22093a00e1012008417f6a210820092103200941c100470d000b200241e8046a200241a0016a41c10010e8061a2009417f7320056a2105200420096a41016a2104410221030b200241a7046a200241e8046a41c10010e8061a2005450d072004310000210b20012005417f6a22083602042001200441016a360200200b50450d01420021060c020b200341ff0171450d06200241003a00e1010c060b2008450d052004310001210c20012005417e6a3602042001200441026a3602004202200b420f8386220a4204540d0542012106200c420886200b84420488200a420c88220b4201200b4201561b7e220b200a5a0d050b200241206a200110e60120022802200d0420022802242105200241086a2001109c032002290308a70d04200241086a41106a290300210d2002290310210c200241f8006a41206a200241d8036a41206a280200360200200241f8006a41186a200241d8036a41186a290300370300200241f8006a41106a200241d8036a41106a290300370300200241f8006a41086a200241d8036a41086a290300370300200220022903d803370378200241376a200241a7046a41c10010e8061a200220022f01d6033b01340b200241a0016a200110b30220022802a001411b460d0120002002290378370300200020033a0024200041206a200241f8006a41206a280200360200200041186a200241f8006a41186a290300370300200041106a200241f8006a41106a290300370300200041086a200241f8006a41086a290300370300200041256a200241376a41c10010e8061a200020022f01343b016620004188016a200d37030020004180016a200c37030020004190016a2005360200200041f8006a200b3703002000200a3703702000200637036820004198016a200241a0016a41b00210e8061a0c040b200042033703680c030b200042033703680c020b200042033703680c010b200042033703680b200241f0056a24000ba71006067f017e017f027e027f0c7e230041f0026b2203240020022802102104200228020c2105200228020821062002280204210720022802002108418de6c300ad4280808080e00084100122022900002109200341386a41086a200241086a290000370300200320093703382002102f41f0e8c600ad4280808080f00084100122022900002109200341f0006a41086a200241086a290000370300200320093703702002102f0240024002404120102d2202450d0020022001290000370000200241186a200141186a290000370000200241106a200141106a290000370000200241086a200141086a2900003700002002ad42808080808004841003220a2900002109200a41086a290000210b200a41106a290000210c200341f0016a41186a220d200a41186a290000370300200341f0016a41106a220e200c370300200341f0016a41086a200b370300200320093703f001200a102f2002102f41c000102d2202450d002002200329033837000020022003290370370010200220032903f001370020200241086a200341386a41086a290300370000200241186a200341f0006a41086a290300370000200241286a200341f0016a41086a290300370000200241306a200e290300370000200241386a200d290300370000200341f0006a200210f6022003290370210f4200211020034200370370200341b8016a280200210d20032d00bc01210e02400240200f4201510d00200341306a4200370300200341286a4200370300200341206a4200370300200341186a4200370300200341106a4200370300200341086a420037030020034200370300420021114200210b42002109420021120c010b200341f0006a41386a290300210c200341f0006a41306a2903002113200341f0006a41206a2903002111200341f0006a41186a2903002110200341f0006a41c0006a290300211220032903800121092003290378210b200341206a200341f0006a41286a290300370300200341286a2013370300200341306a200c370300200341106a2010370300200320113703182003200b370300200320093703080b0240200b200829030022147d2213200b562009200841086a29030022157d200b201454ad7d220c200956200c2009511b450d004198b5c600ad4280808080b00284210941838c0c21010c020b0240200b20107c2216428080e983b1de16544100200920117c22172016201054ad7c501b0d00201320107c221042ffffe883b1de1656200c20117c2010201354ad7c22104200522010501b0d0020072d00004101460d0041fdb4c600ad4280808080900184210941838c1421010c020b02400240201420158450450d0042002110420021110c010b20052d0000210a200341f0016a2006280200108d0202400240200a4101470d00200341a8026a290300211020032903a00221110c010b20034198026a29030021102003290390022111200a410171450d002010200341a8026a2903002214201120032903a002221556201020145620102014511b220a1b211020112015200a1b21110b024020112013562010200c562010200c511b450d0041abb5c600ad4280808080d00284210941838c0421010c030b200841086a2903002111200829030021100b200320133703002003200c37030820042802002108200341386a41186a200341106a220a41086a2903002214370300200341386a41206a2204200a41106a290300370300200341e0006a2207200a41186a290300370300200341e8006a2205200a41206a2903003703002003200c370340200320133703382003200a2903002215370348427f20162016200b54220a2017200aad7c220b200954200b2009511b220a1b427f200b200a1b84211602400240427f201320157c22092009201354220a200c20147c200aad7c2209200c542009200c511b220a1b220b428080e983b1de16544100427f2009200a1b2209501b0d00200341386a41106a29030021092005290300210b20072903002114200429030021152003290340211720032903382118420121192003290350211a0c010b420021190240200b200984500d00200b2009109a01200341a8026a2009370300200341a0026a200b370300200341f0016a41086a41013a0000200341f9016a200829000037000020034181026a200841086a29000037000020034189026a200841106a29000037000020034191026a200841186a290000370000200341033a00f00141c8e1ca004100200341f0016a108c010b0b201650210820034198016a2015370300200341a0016a201437030020034180016a2017370300200341a8016a200b37030020034188016a20093703002003201a37039001200320123703b001200320183703784100210a2003200e4100200f42015122041b3a00bc012003200d410020041b3602b80120032019420151220dad37037002400240200d0d002002ad428080808080088410054101210a0c010b200341c0003602f401200320023602f001200341f8006a200341f0016a1090030b2008ad21092002102f024002400240200f4201510d00200a0d004103210a200341f0016a21020c010b200f420152200a410173720d014104210a200341f0006a21020b200241046a200a3a0000200241003a0000200241056a20012900003700002002410d6a200141086a290000370000200241156a200141106a2900003700002002411d6a200141186a29000037000041c8e1ca0041002002108c010b200041286a2011370300200041206a2010370300200041186a200c370300200041106a2013370300200041086a2009370300410021020c020b1036000b2002102f200041086a200937020020002001360204410121020b20002002360200200341f0026a24000bfe0507017f017e027f017e017f017e057f230041e0006b2203240020012902002104200341306a41186a22054200370300200341306a41106a22064200370300200341306a41086a2201420037030020034200370330418de6c300ad4280808080e0008422071001220829000021092001200841086a290000370300200320093703302008102f41f880c400ad4280808080800284100122082900002109200341d0006a41086a220a200841086a290000370300200320093703502008102f200620032903502209370300200341106a41086a220b2001290300370300200341106a41106a220c2009370300200341106a41186a220d200a29030037030020032003290330370310200341086a200341106a4120109501024002400240417f200328020c410020032802081b220820026a220220022008491b4280808080f28ba80942808080c0f588fe062004422088a7220e41ff017122081b22092009428094ebdc038022094280ec94a37c7e7c4280cab5ee01562009a76a4b0d002005420037030020064200370300200142003703002003420037033020071001220229000021092001200241086a290000370300200320093703302002102f41d480c400ad4280808080b00284100122022900002109200a200241086a290000370300200320093703502002102f200620032903502209370300200b2001290300370300200c2009370300200d200a290300370300200320032903303703102003200341106a4120109501417f2003280204410020032802001b2206418094ebdc034180afd0e50220081b22012004a7220820012008491b6a220820082006491b20014b0d01200041003a0000200041306a41013a0000200041286a4200370200200041206a4280808080c000370300200041186a4204370300200041106a427f370300200041086a427f200442ffffffff0f83200e41ff01714101461b3703000c020b200041800c3b0001200041013a0000200041036a41003a00000c010b200041800c3b0001200041013a0000200041036a41003a00000b200341e0006a24000b130020004107360204200041dca9c4003602000b13002000410436020420004184b1c4003602000bed2b0c027f047e047f017e047f017e017f027e087f017e047f017e230041c0046b220124000240024020004180e101700d00200141d8026a41f4c7c40010b402200141c0036a200141d8026a108d0220014200200141c0036a41086a2202290300220320012903c0032204428080e983b1de1654ad7d2205200442808097fccea1697c22062004562005200356200442ffffe883b1de16561b22071b22043703880120014200200620071b220337038001200141c0036a41186a22082004370300200141c0036a41106a22092003370300200241013a00002001410c3a00c00341c8e1ca004100200141c0036a108c01200141003a009701200142003703a0012001420037039801200842003703002009420037030020024200370300200142003703c0034180a3ca00ad42808080808001842206100122072900002104200141a8016a41086a220a200741086a290000370300200120043703a8012007102f2002200a290300370300200120012903a8013703c0034195a3ca00ad4280808080900184220b100122072900002104200a200741086a290000370300200120043703a8012007102f200920012903a8012204370300200141d8026a41086a220c2002290300370300200141d8026a41106a220d2004370300200141d8026a41186a220e200a290300370300200120012903c0033703d802200141c0036a200141d8026a10fe0320012802c0032207410420071b210f024020012902c403420020071b2210422088a72211450d00200141c0036aad4280808080c000842112200141d8026aad4280808080c000842113200141c9036a2114200141d8026a41c0006a2115200141f8026a2116200f21174100211841002119024003402017280200211a2006100122072900002104200141b8026a41086a221b200741086a290000370300200120043703b8022007102f41e2dec700ad4280808080900184221c100122072900002104200141c8026a41086a221d200741086a290000370300200120043703c8022007102f2001201a3602d80220131003220741086a2900002104200741106a29000021032007290000210520014188026a41186a221e200741186a29000037030020014188026a41106a221f200337030020014188026a41086a2220200437030020012005370388022007102f41c000102d2207450d04200720012903b802370000200720012903c8023700102007200129038802370020200741086a201b290300370000200741186a201d290300370000200741286a2020290300370000200741306a201f290300370000200741386a201e290300370000200141c0036a200710aa0420012903c0032104200141d8026a200241e00010e8061a024002400240024020044201520d00200141a8016a200141d8026a41e00010e8061a2007102f200141d8026a200141a8016a41e00010e8061a0240200129038001220520012903d802222154220720014180016a41086a2903002204200c29030022035420042003511b0d002001200520217d370380012001200420037d2007ad7d370388012006100122072900002104201b200741086a290000370300200120043703b8022007102f201c100122072900002104201d200741086a290000370300200120043703c8022007102f2001201a3602c00320121003220741086a2900002104200741106a290000210320072900002105201e200741186a290000370300201f20033703002020200437030020012005370388022007102f41c000102d2207450d09200720012903b802370000200720012903c8023700102007200129038802370020200741086a201b290300370000200741186a201d290300370000200741286a2020290300370000200741306a201f290300370000200741386a201e2903003700002007ad428080808080088410052007102f20012903e80221042001200e29030022033703d002200120043703c80202402004200384500d00200120163602b80220014188026a2016200141c8026a200141b8026a1096012001290388024201520d002001290390022104200141c0036a41386a201f29030037030020142016290000370000201441086a201641086a290000370000201441106a201641106a290000370000201441186a201641186a290000370000200120043703f003200141003a00c803200141033a00c00341c8e1ca004100200141c0036a108c010b20012903d80221042001200c29030022033703d002200120043703c80202400240200420038450450d004200211c4200212142002105420021030c010b200120153602b80220014188026a2015200141c8026a200141b8026a108f02024002402001290388024201510d0020014188026a41286a290300210320012903a80221052001290390024201520d012001290398022104200141c0036a41386a201e29030037030020142015290000370000201441086a201541086a290000370000201441106a201541106a290000370000201441186a201541186a290000370000200120043703f003200141003a00c803200141033a00c00341c8e1ca004100200141c0036a108c010c010b201f290300210320012903900221050b200c290300212120012903d802211c0b20014198016a41086a2207427f2007290300220420037c200129039801220320057c22052003542207ad7c22032007200320045420032004511b22071b3703002001427f200520071b37039801200141c0036a41386a202137030020142015290000370000201441086a201541086a290000370000201441106a201541106a290000370000201441186a201541186a2900003700002001201c3703f003200141023a00c8032001410c3a00c0032001201a3602ec0341c8e1ca004100200141c0036a108c01201841016a21180c030b200141013a00970120180d01410021180c020b2007102f201841016a21180c010b201920186b220720114f0d01201720184102746b2207280200211f200720172802003602002017201f3602000b201741046a21172011201941016a2219460d020c010b0b4188bbca0020072011103b000b2018417f6a20114f0d00201042ffffffff0f832110201120186b21110b200842003703002009420037030020024200370300200142003703c0032006100122072900002104200a200741086a290000370300200120043703a8012007102f2002200a290300370300200120012903a8013703c003200b100122072900002104200a200741086a290000370300200120043703a8012007102f200920012903a801370000200941086a200a290300370000200c2002290300370300200d2009290300370300200e2008290300370300200120012903c0033703d80202400240200f0d00200141d8026aad428080808080048410050c010b200141203602c4032001200141d8026a3602c003200f2011200141c0036a10a3042010a7450d00200f102f0b024020012d0097010d004200211c200141f0006a200129038001220420014180016a41086a2207290300220342c0843d420010ee06200141e0006a20012903702205200141f0006a41086a290300220642c0fb42427f10ed06200141d0006a2005200642a0c21e420010ed06200720032003200141d0006a41086a29030020012903502205200420012903607c220642a0c21e7e2006420188220642c0fb427e7c42a0c21e562006a76aad7c2206200554ad7c22052006200456200520035620052003511b22171b22057d20042004200620171b220354ad7d3703002001200420037d3703800102400240200320058450450d00420021130c010b20014188026a41186a221b420037030020014188026a41106a2217420037030020014188026a41086a22074200370300200142003703880241e7a2ca00ad428080808080018422041001221e2900002106200141b8026a41086a221f201e41086a290000370300200120063703b802201e102f2007201f290300370300200120012903b8023703880241ecb5c600ad4280808080d0018422061001221a290000211c200141c8026a41086a221e201a41086a2900003703002001201c3703c802201a102f201720012903c802221c370300200141c0036a41086a221d2007290300370300200141c0036a41106a2220201c370300200141c0036a41186a2218201e29030037030020012001290388023703c003200141386a200141c0036a4120109c01200141386a41106a290300211c200129034021132001280238211a201b42003703002017420037030020074200370300200142003703880220041001221b2900002104201f201b41086a290000370300200120043703b802201b102f2007201f290300370300200120012903b8023703880220061001221f2900002104201e201f41086a290000370300200120043703c802201f102f201720012903c8022204370300201d2007290300370300202020043703002018201e29030037030020012001290388023703c00320014200201c4200201a1b220420057d20134200201a1b2206200354ad7d221c200620037d2213200656201c200456201c2004511b22071b3703e00220014200201320071b3703d802200141c0036aad4280808080800484200141d8026aad428080808080028410042004200520071b21132006200320071b211c0b20014198016a41086a2207427f2007290300220420137c2001290398012206201c7c221c2006542207ad7c22062007200620045420062004511b22071b3703002001427f201c20071b37039801200141d8036a2005370300200141d0036a2003370300200141c0036a41086a41043a00002001410c3a00c00341c8e1ca004100200141c0036a108c010b200141a8016a41f4c7c40010b402200141a0016a2903002103200129039801210441002107200141003a00bf03200141023a00be03200120033703900220012004370388022001200141a8016a3602b80202400240200420038450450d0042002105420021060c010b2001200141a8016a3602c8022001200141c8026a3602d0032001200141be036a3602cc032001200141b8026a3602c8032001200141bf036a3602c403200120014188026a3602c003200141d8026a200141a8016a200141c0036a10a50441012107024020012802d8024101470d004200210620012903e00221050c010b20014180036a2903002106200141f8026a29030021054100210720012903e0024201520d00200141d8026a41106a290300211c20012802c8022117200141f8036a200141d8026a41186a290300370300200141f0036a201c37030041002107200141c0036a41086a41003a0000200141c9036a2017290000370000200141d1036a201741086a290000370000200141d9036a201741106a290000370000200141e1036a201741186a290000370000200141033a00c00341c8e1ca004100200141c0036a108c010b0240024020070d0020014188026a41186a221a420037030020014188026a41106a2207420037030020014188026a41086a22174200370300200142003703880241e7a2ca00ad428080808080018422121001221e290000211c200141b8026a41086a221f201e41086a2900003703002001201c3703b802201e102f2017201f290300370300200120012903b8023703880241ecb5c600ad4280808080d0018422101001221b290000211c200141c8026a41086a221e201b41086a2900003703002001201c3703c802201b102f200720012903c802221c370300200141c0036a41086a221b2017290300370300200141c0036a41106a221d201c370300200141c0036a41186a2220201e29030037030020012001290388023703c003200141086a200141c0036a4120109c01200320067d2004200554ad7d200620037d2005200454ad7d20052004582006200358200620035122181b22191b210b200420057d200520047d20191b2121200141086a41106a2903004200200128020822191b211c2001290310420020191b2113024002402005200456200620035620181b0d00201a4200370300200742003703002017420037030020014200370388022012100122182900002104201f201841086a290000370300200120043703b8022018102f2017201f290300370300200120012903b8023703880220101001221f2900002104201e201f41086a290000370300200120043703c802201f102f200720012903c802370000200741086a201e290300370000201b2017290300370300201d20072903003703002020201a29030037030020012001290388023703c0032001427f201c200b7c201320217c22032013542207ad7c220420072004201c542004201c511b22071b3703e0022001427f200320071b3703d802200141d8026a21070c010b201a4200370300200742003703002017420037030020014200370388022012100122182900002104201f201841086a290000370300200120043703b8022018102f2017201f290300370300200120012903b8023703880220101001221f2900002104201e201f41086a290000370300200120043703c802201f102f200720012903c802370000200741086a201e290300370000201b2017290300370300201d20072903003703002020201a29030037030020012001290388023703c00320014200201c200b7d2013202154ad7d2204201320217d22032013562004201c562004201c511b22071b3703e00220014200200320071b3703d802200141d8026a21070b200141c0036aad42808080808004842007ad428080808080028410040c010b419ad8c400ad4280808080a009841008200141c0036a41186a221a4200370300200141c0036a41106a221f4200370300200141c0036a41086a22174200370300200142003703c00341e7a2ca00ad428080808080018422051001221e290000210620014188026a41086a2207201e41086a2900003703002001200637038802201e102f2017200729030037030020012001290388023703c00341ecb5c600ad4280808080d0018422061001221e290000211c2007201e41086a2900003703002001201c37038802201e102f201f200129038802221c370300200141d8026a41086a221b2017290300370300200141d8026a41106a221d201c370300200141d8026a41186a22202007290300370300200120012903c0033703d802200141206a200141d8026a4120109c01200141206a41106a290300211c200129032821132001280220211e201a4200370300201f420037030020174200370300200142003703c00320051001221a29000021052007201a41086a2900003703002001200537038802201a102f2017200729030037030020012001290388023703c00320061001221a29000021052007201a41086a2900003703002001200537038802201a102f201f2001290388022205370300201b2017290300370300201d200537030020202007290300370300200120012903c0033703d8022001427f201c4200201e1b220520037c20134200201e1b220320047c22062003542207ad7c22042007200420055420042005511b22071b3703c8032001427f200620071b3703c003200141d8026aad4280808080800484200141c0036aad428080808080028410040b2001290380012104200141d8036a20014180016a41086a290300370300200141d0036a2004370300200141c0036a41086a41053a00002001410c3a00c00341c8e1ca004100200141c0036a108c010b200010ab04200141c0046a24000f0b1036000be90804077f027e077f027e230041e0016b22022400200241c00036020420022001360200200241086a2001ad4280808080800884100210730240024020022802082203450d00200241106a2802002104200228020c210541002101200241003a00d801200441706a21060240024002400240034020042001460d01200241b8016a20016a200320016a2d00003a00002002200141016a22073a00d8012006417f6a21062007210120074120470d000b200241d8006a41086a200241b8016a41086a290300370300200241d8006a41106a200241b8016a41106a290300370300200241d8006a41186a200241b8016a41186a290300370300200220022903b801370358200420076b22084110490d02200320076a22042900002109200441086a290000210a41002101200241003a00d801200841706a2108034020082001460d02200241b8016a20016a200420016a41106a2d00003a00002002200141016a22073a00d8012007210120074120470d000b200241f8006a41086a220b200241b8016a41086a2201290300370300200241f8006a41106a220c200241b8016a41106a2208290300370300200241f8006a41186a220d200241b8016a41186a220e290300370300200220022903b801370378200620076b410f4d0d02200241386a41086a2206200241d8006a41086a290300370300200241386a41106a220f200241d8006a41106a290300370300200241386a41186a2210200241d8006a41186a290300370300200241186a41086a2211200b290300370300200241186a41106a220b200c290300370300200241186a41186a220c200d2903003703002002200229035837033820022002290378370318200420076a220741106a2900002112200741186a2900002113200120062903003703002008200f290300370300200e201029030037030020024198016a41086a2207201129030037030020024198016a41106a2206200b29030037030020024198016a41186a2204200c290300370300200220022903383703b8012002200229031837039801200041206a2013370300200041186a2012370300200041106a200a37030020002009370308200041286a20022903b801370300200041306a2001290300370300200041386a2008290300370300200041c0006a200e290300370300200041c8006a200229039801370300200041d0006a2007290300370300200041d8006a2006290300370300200041e0006a2004290300370300420121090c030b200141ff0171450d01200241003a00d8010c010b200141ff0171450d00200241003a00d8010b200241003602a00120024201370398012002410b36027c20022002360278200220024198016a360258200241cc016a4101360200200242013702bc01200241b885c7003602b8012002200241f8006a3602c801200241d8006a41d8dbc100200241b8016a103c1a20023502a0014220862002350298018410080240200228029c01450d00200228029801102f0b420021090b200020093703002005450d012003102f0c010b200042003703000b200241e0016a24000bb5670a047f017e017f027e077f017e037f017e017f027e230041f0026b22012400200141d0006a41186a4200370300200141d0006a41106a22024200370300200141d0006a41086a220342003703002001420037035041b89bca00ad4280808080f00184100122042900002105200141f0016a41086a2206200441086a290000370300200120053703f0012004102f20032006290300370300200120012903f00137035041cabec600ad4280808080d001841001220429000021052006200441086a290000370300200120053703f0012004102f200220012903f0012205370300200141d0026a41086a2003290300370300200141d0026a41106a2005370300200141d0026a41186a2006290300370300200120012903503703d002200141203602d4012001200141d0026a3602d001200141f0016a200141d0026aad220742808080808004842208100210730240024020012802f0012203450d0020012802f40121092001200628020022063602dc01200120033602d8010240024020064104490d002001200341046a3602d80120012006417c6a22043602dc0120044104490d002003280000210a2001200641786a3602dc012001200341086a3602d8012003280004210b200141d0006a200141d8016a10ee032001280250220c450d002001290254210541002106200141003a00e00102400240024020012802dc01220d450d002001200d417f6a220e3602dc01200120012802d801220f41016a3602d801200f2d00004101460d010b0c010b200e4104490d002001200d417b6a3602dc012001200f41056a3602d801200f2800012104410121060b200120043602c802200120053702bc022001200c3602b8022001200b3602b4022001200a3602b0020c010b200141003602980220014201370390022001410b3602e4012001200141d0016a3602e001200120014190026a3602ec01200141e4006a410136020020014201370254200141b885c7003602502001200141e0016a360260200141ec016a41d8dbc100200141d0006a103c1a2001350298024220862001350290028410080240200128029402450d00200128029002102f0b410221060b200120063602c4022009450d012003102f0c010b41022106200141023602c4020b200141d0006a41106a2203200141b0026a41106a2209280200360200200141d0006a41086a220a200141b0026a41086a220b290300370300200120012903b002370350024002400240024002400240024002400240024020064102460d0020014190026a41106a2003280200220336020020014190026a41086a200a29030022103703002001200129035022053703900220092003360200200b2010370300200141c8026a2004360200200120053703b002200120063602c40202402005a722032000470d000240024020064101460d0020012802b4022106200141d0006a200141b0026a41086a10f303200141e0026a2006360200200141d0026a410c6a200141d0006a41086a2206280200360200200141003602d002200120012903503702d402200141d0006a200141d0026a109602200141fb016a2006280200360000200120012903503700f301200141d0006a410c6a200141f7016a290000370000200141c6a4b9da04360051200141023a0050200120012900f001370055200141d0006a108a04200141d0026a41086a280200450d0120012802d402102f0c010b20012802b4022106200141d0006a200141b0026a41086a10f303200141e4026a2006360200200141d0026a41086a2001290350370300200141e0026a200141d0006a41086a2206280200360200200120043602d402200141013602d002200141d0006a200141d0026a109602200141fb016a2006280200360000200120012903503700f301200141d0006a410c6a200141f7016a290000370000200141c6a4b9da04360051200141023a0050200120012900f001370055200141d0006a108a04200141d0026a410c6a280200450d0020012802d802102f0b20012802b00221030b024020012802b40220036a2000470d00200141c0026a28020041286c4105722206417f4c0d022006102d2203450d06200141003602582001200636025420012003360250200141013a00e001200341013a00002001410136025820012802b802210620012802c0022203200141d0006a10690240024020030d00200128025821032001280254210a200128025021090c010b2006200341286c6a210c2001280254210a20012802582103034002400240200a20036b4120490d00200341206a2104200128025021090c010b200341206a22042003490d0d200a41017422092004200920044b1b220b4100480d0d02400240200a0d00200b102d21090c010b2001280250200a200b103121090b2009450d092001200b36025420012009360250200b210a0b200920036a220341186a200641186a290000370000200341106a200641106a290000370000200341086a200641086a2900003700002001200436025820032006290000370000200641206a290300210502400240200a20046b4108490d00200441086a21030c010b200441086a22032004490d0d200a410174220b2003200b20034b1b220b4100480d0d02400240200a0d00200b102d21090c010b2009200a200b103121090b2009450d092001200b36025420012009360250200b210a0b20012003360258200920046a2005370000200c200641286a2206470d000b0b200141b8026a210441c7b4c600ad4280808080c002842003ad4220862009ad8410040240200a450d002009102f0b200141d0006a41086a22062004290000370300200141d0006a41106a2209200441086a280000360200200141003602542001410b3a005041c8e1ca004100200141d0006a108c01200141d0006a41186a220a420037030020094200370300200642003703002001420037035041b89bca00ad4280808080f00184100122042900002105200141f0016a41086a2203200441086a290000370300200120053703f0012004102f20062003290300370300200120012903f00137035041cabec600ad4280808080d001841001220429000021052003200441086a290000370300200120053703f0012004102f200220012903f001370000200241086a2003290300370000200141d0026a41086a2006290300370300200141d0026a41106a2009290300370300200141d0026a41186a200a290300370300200120012903503703d002200810050c010b200141bc026a280200450d0020012802b802102f0b200141d0006a41186a22094200370300200141d0006a41106a220a4200370300200141d0006a41086a220342003703002001420037035041b89bca00ad4280808080f00184100122042900002105200141f0016a41086a2206200441086a290000370300200120053703f0012004102f20032006290300370300200120012903f00137035041d7bec600ad4280808080d000841001220429000021052006200441086a290000370300200120053703f0012004102f200220012903f001370000200241086a2006290300370000200141d0026a41086a2003290300370300200141d0026a41106a200a290300370300200141d0026a41186a2009290300370300200120012903503703d002200141203602f4012001200141d0026a3602f00120014190026a2008100210732001280290022206450d0320014190026a41086a2802002104200128029402210941002103200141003a00e0010240024002402004450d0020062d0000220a41034b0d00024002400240200a0e0405000102050b2004417f6a4108490d0220062900012105410121030c040b410221030c020b2004417f6a4108490d0020062900012105410321030c020b200141003602b802200142013703b0022001410b3602e4012001200141f0016a3602e0012001200141b0026a3602d801200141e4006a410136020020014201370254200141b885c7003602502001200141e0016a360260200141d8016a41d8dbc100200141d0006a103c1a20013502b80242208620013502b002841008024020012802b402450d0020012802b002102f0b410421030b0b02402009450d002006102f0b2003417f6a220641024b0d0320060e03020301020b103d000b2005422088a7210602402005a722032000470d00200141043602d002200120063602d402200141d0006a200141d0026a109602200141fb016a200141d8006a280200360000200120012903503700f301200141dc006a200141f7016a290000370000200141c6a4b9da04360051200141023a0050200120012900f001370055200141d0006a108a040b200620036a2000470d01200141003602b002200141d0006a41186a22094200370300200141d0006a41106a220a4200370300200141d0006a41086a220342003703002001420037035041b89bca00ad4280808080f00184100122042900002105200141f0016a41086a2206200441086a290000370300200120053703f0012004102f20032006290300370300200120012903f00137035041d7bec600ad4280808080d000841001220429000021052006200441086a290000370300200120053703f0012004102f200220012903f001370000200241086a2006290300370000200141d0026a41086a2003290300370300200141d0026a41106a200a290300370300200141d0026a41186a2009290300370300200120012903503703d002200141d0006a200141b0026a10f2042008200135025842208620012802502206ad84100402402001280254450d002006102f0b200141023602542001410b3a005041c8e1ca004100200141d0006a108c010c010b2005422088a7210602402005a722032000470d00200141033602d002200120063602d402200141d0006a200141d0026a109602200141fb016a200141d8006a280200360000200120012903503700f301200141dc006a200141f7016a290000370000200141c6a4b9da04360051200141023a0050200120012900f001370055200141d0006a108a040b200620036a2000470d00200141023602b002200141d0006a41186a22094200370300200141d0006a41106a220a4200370300200141d0006a41086a220342003703002001420037035041b89bca00ad4280808080f00184100122042900002105200141f0016a41086a2206200441086a290000370300200120053703f0012004102f20032006290300370300200120012903f00137035041d7bec600ad4280808080d000841001220429000021052006200441086a290000370300200120053703f0012004102f200220012903f001370000200241086a2006290300370000200141d0026a41086a2003290300370300200141d0026a41106a200a290300370300200141d0026a41186a2009290300370300200120012903503703d002200141d0006a200141b0026a10f2042008200135025842208620012802502206ad84100402402001280254450d002006102f0b200141013602542001410b3a005041c8e1ca004100200141d0006a108c010b200141d0006a41186a22044200370300200141d0006a41106a220d4200370300200141d0006a41086a220342003703002001420037035041d5a2ca00ad42808080809001842205100122092900002108200141b0026a41086a2206200941086a290000370300200120083703b0022009102f20032006290300370300200120012903b00237035041a2c9c300ad4280808080e000841001220929000021082006200941086a290000370300200120083703b0022009102f200d20012903b0022208370300200141d0026a41086a220a2003290300370300200141d0026a41106a220b2008370300200141d0026a41186a220c2006290300370300200120012903503703d002200141c8006a200141d0026a4120109501200128024c210f0240200128024822024101470d002007428080808080048410050b20044200370300200d4200370300200342003703002001420037035020051001220929000021052006200941086a290000370300200120053703b0022009102f20032006290300370300200120012903b00237035041db98ca00ad4280808080b001841001220929000021052006200941086a290000370300200120053703b0022009102f200d20012903b002370000200d41086a2006290300370000200a2003290300370300200b200d290300370300200c2004290300370300200120012903503703d00202400240200141d0026a10f702220641ff01714102460d0020064101710d010b4104102d220a450d01200a4100360200200141d0006a41186a22044200370300200141d0006a41106a22094200370300200141d0006a41086a220342003703002001420037035041d5a2ca00ad428080808090018422051001220b2900002108200141b0026a41086a2206200b41086a290000370300200120083703b002200b102f20032006290300370300200120012903b00237035041f4c8c300ad4280808080b001841001220b29000021082006200b41086a290000370300200120083703b002200b102f200d20012903b002370000200d41086a220b2006290300370000200141d0026a41086a220c2003290300370300200141d0026a41106a22002009290300370300200141d0026a41186a220e2004290300370300200120012903503703d002200141203602542001200141d0026a360250200a4101200141d0006a10a304200a102f4104102d220a450d01200a41003602002004420037030020094200370300200342003703002001420037035020051001221129000021082006201141086a290000370300200120083703b0022011102f20032006290300370300200120012903b00237035041a8c9c300ad4280808080c001841001221129000021082006201141086a290000370300200120083703b0022011102f200d20012903b002370000200b2006290300370000200c200329030037030020002009290300370300200e2004290300370300200120012903503703d002200141203602542001200141d0026a360250200a4101200141d0006a10a304200a102f2004420037030020094200370300200342003703002001420037035020051001220a29000021082006200a41086a290000370300200120083703b002200a102f20032006290300370300200120012903b00237035041b4c9c300ad4280808080e000841001220a29000021082006200a41086a290000370300200120083703b002200a102f200d20012903b002370000200b2006290300370000200c200329030037030020002009290300370300200e2004290300370300200120012903503703d00220014100360250200742808080808004842208200141d0006aad4280808080c0008410042004420037030020094200370300200342003703002001420037035020051001220a29000021052006200a41086a290000370300200120053703b002200a102f20032006290300370300200120012903b00237035041db98ca00ad4280808080b001841001220a29000021052006200a41086a290000370300200120053703b002200a102f200d20012903b002370000200b2006290300370000200c200329030037030020002009290300370300200e2004290300370300200120012903503703d002200141013a00e0012008200141e0016aad4280808080108410040b200141d0006a41186a22044200370300200141d0006a41106a22124200370300200141d0006a41086a220642003703002001420037035041d5a2ca00ad428080808090018422051001220329000021082006200341086a290000370300200120083703502003102f41f4c8c300ad4280808080b00184100122092900002108200141b0026a41086a2203200941086a290000370300200120083703b0022009102f201220012903b0022208370300200141d0026a41086a220a2006290300370300200141d0026a41106a220b2008370300200141d0026a41186a220c2003290300370300200120012903503703d002200141d0006a200141d0026a10fe03024002402001280250220e0d004104210e41002111420021100c010b20012902542210422088a721110b2004420037030020124200370300200642003703002001420037035020051001220929000021052003200941086a290000370300200120053703b0022009102f20062003290300370300200120012903b00237035041a8c9c300ad4280808080c001841001220929000021052003200941086a290000370300200120053703b0022009102f200d20012903b002370000200d41086a2003290300370000200a2006290300370300200b2012290300370300200c2004290300370300200120012903503703d002200141d0006a200141d0026a10fe03024002402001280250220a450d002001200a3602900220012902542208422088a721040c010b4104210a200141043602900241002104420021080b0240024002400240024020020d002011417f6a220620114f0d01200620114b0d01200e20064102746a280200210f0b201141002011419c7f6a22062006201141016a4b1b2213490d012013450d03200e20134102746a21002004ad2105200e210203402002280200210b024002400240024002402005a7220c41014b0d0041002106200c0e020201020b41002106200c2103034020062003410176220420066a2209200b200a20094102746a280200491b2106200320046b220341014b0d000b0b200b200a200641027422036a2802002204460d022006200b20044b6a21060c010b410021060b2001200636025041f0c9c300412e200141d0006a41a0cac30041b0cac300103e000b20052006ad580d03200a20036a2203200341046a2006417f73200c6a41027410e9061a200842ffffffff0f83200c417f6a2204ad422086842108200241046a22022000460d042005427f7c2105200128029002210a0c000b0b41bac9c300412641e0c9c3001055000b41a6b5ca00411c41f8b4ca001039000b41b8e3c300411d41f8b4ca001039000b201042ffffffff0f8321050240201120136b2206450d0002402013450d00200e200e20134102746a200641027410e9061a2008422088a721040b20052006ad4220868421050b200128029002210b41002106024002400240024002400240200441014b0d0020040e020201020b20042103034020062003410176220920066a220a200f200b200a4102746a280200491b2106200320096b220341014b0d000b0b0240200f200b20064102746a2802002203460d002006200f20034b6a21060b20042006490d010b20042008a7470d02200441016a22032004490d07200441017422092003200920034b1b220341ffffffff03712003470d072003410274220341004e0d010c070b419ae3c300411e41f8b4ca001039000b0240024020040d002003102d210b0c010b200b200441027420031031210b0b200b450d012001200b360290022003410276ad21080b200b20064102746a220341046a2003200420066b41027410e9061a2003200f360200024020054220882210a722092005a7470d00200941016a22062009490d052010a7220a4101742203200620062003491b220641ffffffff03712006470d05200641027422064100480d050240024020090d002006102d210e0c010b200e200a41027420061031210e0b200e450d012005422088a721092006410276ad21050b200e20094102746a200f3602000240200441016a22040d0041c0cac30041c30041f8b4ca001039000b2004200441017622064d0d01200128029002220320064102746a280200210c024020044101710d0020042006417f6a22064d0d03200320064102746a280200200c6a410176210c0b200141d0006a41186a220a4200370300200141d0006a41106a220b4200370300200141d0006a41086a220342003703002001420037035041d5a2ca00ad42808080809001842210100122022900002114200141b0026a41086a2206200241086a290000370300200120143703b0022002102f20032006290300370300200120012903b00237035041f4c8c300ad4280808080b001841001220229000021142006200241086a290000370300200120143703b0022002102f200d20012903b002370000200d41086a22002006290300370000200141d0026a41086a220f2003290300370300200141d0026a41106a2211200b290300370300200141d0026a41186a2213200a290300370300200120012903503703d002200141203602542001200141d0026a360250200e200941016a2215200141d0006a10a30402402005a7450d00200e102f0b2001280290022102200a4200370300200b4200370300200342003703002001420037035020101001220929000021052006200941086a290000370300200120053703b0022009102f20032006290300370300200120012903b00237035041a8c9c300ad4280808080c001841001220929000021052006200941086a290000370300200120053703b0022009102f200d20012903b00237000020002006290300370000200f20032903003703002011200b2903003703002013200a290300370300200120012903503703d002200141203602542001200141d0026a36025020022004200141d0006a10a30402402008a7450d002002102f0b200141d0006a41186a22094200370300200141d0006a41106a22044200370300200141d0006a41086a220642003703002001420037035041d5a2ca00ad42808080809001841001220a2900002105200141b0026a41086a2203200a41086a290000370300200120053703b002200a102f20062003290300370300200120012903b00237035041b4c9c300ad4280808080e000841001220a29000021052003200a41086a290000370300200120053703b002200a102f200d20012903b002370000200d41086a2003290300370000200141d0026a41086a220a2006290300370300200141d0026a41106a220b2004290300370300200141d0026a41186a22022009290300370300200120012903503703d0022001200c36025020074280808080800484200141d0006aad22084280808080c0008410040240201541e500470d0020094200370300200442003703002006420037030020014200370350418de6c300ad4280808080e000841001220c29000021052006200c41086a29000037030020012005370350200c102f419ce6c300ad4280808080e000841001220c29000021052003200c41086a290000370300200120053703b002200c102f201220012903b002370000201241086a2003290300370000200a2006290300370300200b200429030037030020022009290300370300200120012903503703d002200141c0006a200141d0026a41201095010b2009420037030020044200370300200642003703002001420037035041eba1ca00ad4280808080f0008422101001220929000021052006200941086a290000370300200120053703502009102f41adcac800ad221442808080809001841001220929000021052003200941086a290000370300200120053703b0022009102f200420012903b0022205370300200a2006290300370300200b200537030020022003290300370300200120012903503703d002200141d0006a200141d0026a10fd0302402001290350427f7c4202540d0020042903002105200141d0006a41186a22094200370300200141d0006a41106a22034200370300200141d0006a41086a220642003703002001420037035041d5a2ca00ad42808080809001841001220429000021162006200441086a290000370300200120163703502004102f41ecb0c000ad42808080803084100122042900002116200141b0026a41086a220a200441086a290000370300200120163703b0022004102f200320012903b0022216370300200141d0026a41086a220b2006290300370300200141d0026a41106a220c2016370300200141d0026a41186a2202200a290300370300200120012903503703d002200141306a200141d0026a10e3012001290338211620012802302104200120053703c00220012016420020041b3703b802200142013703b0022009420037030020034200370300200642003703002001420037035020101001220429000021052006200441086a290000370300200120053703502004102f2014428080808090018410012204290000210520014190026a41086a2209200441086a29000037030020012005370390022004102f20032001290390022205370300200b2006290300370300200c200537030020022009290300370300200120012903503703d002200141203602542001200141d0026a360250200141b0026a200141d0006a10bb030b200141d0006a41186a220b4200370300200141d0006a41106a22094200370300200141d0006a41086a220642003703002001420037035041e7a2ca00ad4280808080800184100122042900002105200141b0026a41086a2203200441086a290000370300200120053703b0022004102f20062003290300370300200120012903b00237035041efa2ca00ad42808080809002841001220429000021052003200441086a290000370300200120053703b0022004102f200920012903b0022205370300200141d0026a41086a22042006290300370300200141d0026a41106a2005370300200141d0026a41186a2003290300370300200120012903503703d002200141206a200141d0026a10e301200129032821102001280220210c200141f0016a41186a4200370300200141f0016a41106a22024200370300200141f0016a41086a22034200370300200142003703f001418de6c300ad4280808080e000841001220a29000021052003200a41086a290000370300200120053703f001200a102f41d480c400ad4280808080b002841001220a29000021052004200a41086a290000370300200120053703d002200a102f200220012903d00222053703002006200329030037030020092005370300200b2004290300370300200120012903f001370350200141186a200141d0006a4120109501200141086a200128021c410020012802181b22064180e59af70020064180e59af7004b22031b4180e59af700200620031b6bad220542002005420010ed06200542a8c30180211420104200200c1b210542092001290308221042808090bbbad6adf00d7f20012903102010423f87521b211002400240200641ffe49af7004b0d0042ffffffffffffffffff00428080808080808080807f2005201420107d22147d22104200531b20102005427f5522062014427f554720062010427f5547711b22054280ec94a37c20054280ec94a37c551b21050c010b42ffffffffffffffffff00428080808080808080807f2005201420107c22147c22104200531b20102005427f5522062014427f554620062010427f5547711b21050b200141d0006a41186a220a4200370300200141d0006a41106a22044200370300200141d0006a41086a220342003703002001420037035041e7a2ca00ad42808080808001841001220b2900002110200141b0026a41086a2206200b41086a290000370300200120103703b002200b102f20032006290300370300200120012903b00237035041efa2ca00ad42808080809002841001220b29000021102006200b41086a290000370300200120103703b002200b102f200920012903b002370000200941086a2006290300370000200141d0026a41086a22092003290300370300200141d0026a41106a220b2004290300370300200141d0026a41186a220c200a290300370300200120012903503703d00220012005370350200742808080808004842205200842808080808001841004200a4200370300200442003703002003420037030020014200370350419487ca00ad4280808080a0018422101001220229000021142006200241086a290000370300200120143703b0022002102f20032006290300370300200120012903b00237035041da85c700ad4280808080e000841001220229000021142006200241086a290000370300200120143703b0022002102f200420012903b002221437030020092003290300370300200b2014370300200c2006290300370300200120012903503703d00220051005200a420037030020044200370300200342003703002001420037035020101001220229000021102006200241086a290000370300200120103703b0022002102f20032006290300370300200120012903b002370350419e87ca00ad4280808080c001841001220229000021102006200241086a290000370300200120103703b0022002102f200420012903b002221037030020092003290300370300200b2010370300200c2006290300370300200120012903503703d00220051005200a420037030020044200370300200342003703002001420037035041d5a2ca00ad42808080809001841001220a29000021102003200a41086a29000037030020012010370350200a102f41dea2ca00ad42808080809001841001220a29000021102006200a41086a290000370300200120103703b002200a102f200420012903b002221037030020092003290300370300200b2010370300200c2006290300370300200120012903503703d002200141d0026a10f702220641ff01714102460d03200510052006410171450d03200141d0006a41186a4200370300200141d0006a41106a22094200370300200141d0006a41086a220342003703002001420037035041aa87ca00ad4280808080c00084100122042900002105200141f0016a41086a2206200441086a290000370300200120053703f0012004102f20032006290300370300200120012903f00137035041db98ca00ad4280808080b001841001220429000021052006200441086a290000370300200120053703f0012004102f200920012903f0012205370300200141d0026a41086a2003290300370300200141d0026a41106a2005370300200141d0026a41186a2006290300370300200120012903503703d002200141d0006a200141d0026a10f304024020012d005022064102460d0020074280808080800484100520014190026a41086a200141d9006a29000037030020014190026a41106a200141e1006a29000037030020014190026a41186a200141e9006a29000037030020012001290051370390020240200641037122064103460d0020060e03010001010b200141b0026a41186a20014190026a41186a290300370300200141b0026a41106a20014190026a41106a290300370300200141b0026a41086a20014190026a41086a29030037030020012001290390023703b002200141d0006a41186a220b4200370300200141d0006a41106a220c4200370300200141d0006a41086a220442003703002001420037035041aa87ca00ad4280808080c000842205100122062900002110200141f0016a41086a2203200641086a290000370300200120103703f0012006102f20042003290300370300200120012903f00137035041f187ca00ad4280808080c001841001220629000021102003200641086a290000370300200120103703f0012006102f200920012903f001370000200941086a2003290300370000200141d0026a41086a220a2004290300370300200141d0026a41106a200c290300370300200141d0026a41186a200b290300370300200120012903503703d0022001200141d0026a41201095012001280204210b2001280200210c20051001220629000021052004200641086a290000370300200120053703502006102f41fd87ca00ad4280808080900284100122062900002105200a200641086a290000370300200120053703d0022006102f2001200b4100200c1b220c3602e001200141e0016aad22104280808080c00084100322062900002105200641086a2900002114200641106a2900002116200141f0016a41186a220b200641186a290000370300200141f0016a41106a2202201637030020032014370300200120053703f0012006102f41c000102d2206450d0120062001290350370000200620012903d002370010200620012903f001370020200641086a2004290300370000200641186a200a290300370000200641286a2003290300370000200641306a2002290300370000200641386a200b290300370000200141d0006a200641c00010860420012902542105200128025021032006102f2003410120031b2104024002402005420020031b22054220882214a72203418002490d004120102d2203450d03200320012903b002370000200341186a200141b0026a41186a290300370000200341106a200141b0026a41106a290300370000200341086a200141b0026a41086a29030037000041aa87ca00ad4280808080c000842214100122062900002116200141d0006a41086a220b200641086a290000370300200120163703502006102f41fd87ca00ad4280808080900284100122062900002116200141d0026a41086a2202200641086a290000370300200120163703d0022006102f2001200c41016a220c3602e00120104280808080c00084100322062900002110200641086a2900002116200641106a2900002117200141f0016a41186a2200200641186a290000370300200141f0016a41106a220d2017370300200141f0016a41086a220a2016370300200120103703f0012006102f41c000102d2206450d0320062001290350370000200620012903d002370010200620012903f001370020200641086a200b290300370000200641186a2002290300370000200641286a200a290300370000200641306a200d290300370000200641386a2000290300370000200141c0003602542001200636025020034101200141d0006a10f4042006102f2003102f200141d0006a41186a22034200370300200141d0006a41106a22004200370300200b4200370300200142003703502014100122062900002110200a200641086a290000370300200120103703f0012006102f200b200a290300370300200120012903f00137035041f187ca00ad4280808080c00184100122062900002110200a200641086a290000370300200120103703f0012006102f200920012903f001370000200941086a200a2903003700002002200b290300370300200141d0026a41106a2000290300370300200141d0026a41186a2003290300370300200120012903503703d0022001200c3602502007428080808080048420084280808080c0008410040c010b200141d0006a41186a220a200141b0026a41186a290300370300200141d0006a41106a220b200141b0026a41106a290300370300200141d0006a41086a2209200141b0026a41086a290300370300200120012903b002370350024020032005a7470d00200341016a22062003490d072014a722004101742202200620062002491b220641ffffff3f712006470d07200641057422064100480d070240024020030d002006102d21040c010b200420004105742006103121040b2004450d032005422088a721032006410576ad21050b200420034105746a22062001290350370000200641186a200a290300370000200641106a200b290300370000200641086a200929030037000041aa87ca00ad4280808080c000841001220629000021082009200641086a290000370300200120083703502006102f41fd87ca00ad4280808080900284100122062900002108200141d0026a41086a200641086a290000370300200120083703d0022006102f2001200c3602e00120104280808080c00084100322062900002108200641086a2900002107200641106a2900002110200141f0016a41186a200641186a290000370300200141f0016a41106a2010370300200141f0016a41086a2007370300200120083703f0012006102f41c000102d2206450d0220062001290350370000200620012903d002370010200620012903f001370020200641086a200141d0006a41086a290300370000200641186a200141d0026a41086a290300370000200641286a200141f0016a41086a290300370000200641306a20014180026a290300370000200641386a200141f0016a41186a290300370000200141c000360254200120063602502004200341016a200141d0006a10f4042006102f200542ffffffff0f8321050b2005a7450d002004102f0b200141f0026a24000f0b1036000b41c4c2ca0020062004103b000b41c4c2ca0020062004103b000b41fca5c000412b41f8b4ca001039000b1038000bb61b06057f017e077f017e287f027e230041a00d6b22032400200341106a41186a22044200370300200341106a41106a22054200370300200341106a41086a2206420037030020034200370310418de6c300ad4280808080e000841001220729000021082006200741086a290000370300200320083703102007102f419ce6c300ad4280808080e00084100122092900002108200341900d6a41086a2207200941086a290000370300200320083703900d2009102f200520032903900d2208370300200341f00c6a41086a220a2006290300370300200341f00c6a41106a220b2008370300200341f00c6a41186a220c2007290300370300200320032903103703f00c200341086a200341f00c6a4120109501200328020c210d2003280208210e2004420037030020054200370300200642003703002003420037031041dcbec600ad42808080808003841001220929000021082006200941086a290000370300200320083703102009102f41f4bec600ad4280808080e001841001220929000021082007200941086a290000370300200320083703900d2009102f200520032903900d2208370300200a2006290300370300200b2008370300200c2007290300370300200320032903103703f00c200341106a200341f00c6a412010aa0220032802102206410120061b210f024002402003290214420020061b2210422088a722050d0020004200370000200041186a4200370000200041106a4200370000200041086a42003700000c010b200341106a410041e00c10e7061a200d417f6a41d100704130200e1b2106200241056a2111200f41206a2112200f20054105746a21134100210d4100211441002115410021164100211741002118410021194100211a4100211b4100211c4100211d4100211e4100211f410021204100212141002122410021234100212441002125410021264100212741002128410021294100212a4100212b4100212c4100212d4100212e4100212f410021304100213141002132200f21054100213341d10021340240034020332109024002402006450d00200641016a210603400240024020052013460d0020052107200541206a21050c010b20122105200f21070b2006417f6a22060d000b20070d010c030b024020052013460d0020052107200541206a21050c010b20122105200f21070b02400240024002402011417f4c0d00024002402011450d002011102d2206450d03200341003602980d200320113602940d0c010b200341003602980d200320113602940d200341013602900d4101102d2206450d02200341013602940d0b200320063602900d200341013602980d200620093a00002002200341900d6a10690240024020032802940d220e20032802980d22046b2002490d0020032802900d21060c010b200420026a22062004490d03200e41017422332006203320064b1b22334100480d0302400240200e0d002033102d21060c010b20032802900d200e2033103121060b2006450d02200320333602940d200320063602900d2033210e0b2003200420026a22333602980d200620046a2001200210e8061a4120102d2204450d0120042007290000370000200441186a2235200741186a290000370000200441106a2236200741106a290000370000200441086a2237200741086a29000037000002400240200e20336b411f4d0d00200e21380c010b203341206a22072033490d03200e41017422382007203820074b1b22384100480d0302400240200e0d002038102d21060c010b2006200e2038103121060b2006450d02200320383602940d200320063602900d0b200620336a220741086a2037290000370000200741106a2036290000370000200741186a20352900003700002003203341206a220e3602980d200720042900003700002004102f200ead4220862006ad84100322072900002108200741086a2900002139200741106a290000213a200c200741186a290000370300200b203a370300200a2039370300200320083703f00c2007102f02402038450d002006102f0b2034417f6a2134200941016a2133200341106a20094103704105746a220620032903f00c370000200641186a200c290300370000200641106a200b290300370000200641086a200a2903003700004100210703402009200941036e2204417d6c6a4102470d04200341106a20076a220641df006a2d0000220d2006411f6a2d0000220e71200d200e722006413f6a2d000071722132200641de006a2d0000220d2006411e6a2d0000220e71200d200e722006413e6a2d000071722131200641dd006a2d0000220d2006411d6a2d0000220e71200d200e722006413d6a2d000071722130200641dc006a2d0000220d2006411c6a2d0000220e71200d200e722006413c6a2d00007172212f200641db006a2d0000220d2006411b6a2d0000220e71200d200e722006413b6a2d00007172212e200641da006a2d0000220d2006411a6a2d0000220e71200d200e722006413a6a2d00007172212d200641d9006a2d0000220d200641196a2d0000220e71200d200e72200641396a2d00007172212c200641d8006a2d0000220d200641186a2d0000220e71200d200e72200641386a2d00007172212b200641d7006a2d0000220d200641176a2d0000220e71200d200e72200641376a2d00007172212a200641d6006a2d0000220d200641166a2d0000220e71200d200e72200641366a2d000071722129200641d5006a2d0000220d200641156a2d0000220e71200d200e72200641356a2d000071722128200641d4006a2d0000220d200641146a2d0000220e71200d200e72200641346a2d000071722127200641d3006a2d0000220d200641136a2d0000220e71200d200e72200641336a2d000071722126200641d2006a2d0000220d200641126a2d0000220e71200d200e72200641326a2d000071722125200641d1006a2d0000220d200641116a2d0000220e71200d200e72200641316a2d000071722124200641d0006a2d0000220d200641106a2d0000220e71200d200e72200641306a2d000071722123200641cf006a2d0000220d2006410f6a2d0000220e71200d200e722006412f6a2d000071722122200641ce006a2d0000220d2006410e6a2d0000220e71200d200e722006412e6a2d000071722121200641cd006a2d0000220d2006410d6a2d0000220e71200d200e722006412d6a2d000071722120200641cc006a2d0000220d2006410c6a2d0000220e71200d200e722006412c6a2d00007172211f200641cb006a2d0000220d2006410b6a2d0000220e71200d200e722006412b6a2d00007172211e200641ca006a2d0000220d2006410a6a2d0000220e71200d200e722006412a6a2d00007172211d200641c9006a2d0000220d200641096a2d0000220e71200d200e72200641296a2d00007172211c200641c8006a2d0000220d200641086a2d0000220e71200d200e72200641286a2d00007172211b200641c7006a2d0000220d200641076a2d0000220e71200d200e72200641276a2d00007172211a200641c6006a2d0000220d200641066a2d0000220e71200d200e72200641266a2d000071722119200641c5006a2d0000220d200641056a2d0000220e71200d200e72200641256a2d000071722118200641c4006a2d0000220d200641046a2d0000220e71200d200e72200641246a2d000071722117200641c3006a2d0000220d200641036a2d0000220e71200d200e72200641236a2d000071722116200641c2006a2d0000220d200641026a2d0000220e71200d200e72200641226a2d000071722115200641c1006a2d0000220d200641016a2d0000220e71200d200e72200641216a2d000071722114200641c0006a2d0000220d20062d0000220e71200d200e72200641206a2d00007172210d200741800c460d04200341106a20072004410574200941096e41e0006c6b6a6a220641ff006a20323a0000200641fe006a20313a0000200641fd006a20303a0000200641fc006a202f3a0000200641fb006a202e3a0000200641fa006a202d3a0000200641f9006a202c3a0000200641f8006a202b3a0000200641f7006a202a3a0000200641f6006a20293a0000200641f5006a20283a0000200641f4006a20273a0000200641f3006a20263a0000200641f2006a20253a0000200641f1006a20243a0000200641f0006a20233a0000200641ef006a20223a0000200641ee006a20213a0000200641ed006a20203a0000200641ec006a201f3a0000200641eb006a201e3a0000200641ea006a201d3a0000200641e9006a201c3a0000200641e8006a201b3a0000200641e7006a201a3a0000200641e6006a20193a0000200641e5006a20183a0000200641e4006a20173a0000200641e3006a20163a0000200641e2006a20153a0000200641e1006a20143a0000200641e0006a200d3a000020042109200741e0006a220741e00c470d000c040b0b103d000b1036000b1038000b4100210620340d000b0b200020323a001f200020313a001e200020303a001d2000202f3a001c2000202e3a001b2000202d3a001a2000202c3a00192000202b3a00182000202a3a0017200020293a0016200020283a0015200020273a0014200020263a0013200020253a0012200020243a0011200020233a0010200020223a000f200020213a000e200020203a000d2000201f3a000c2000201e3a000b2000201d3a000a2000201c3a00092000201b3a00082000201a3a0007200020193a0006200020183a0005200020173a0004200020163a0003200020153a0002200020143a00012000200d3a00000b02402010a7450d00200f102f0b200341a00d6a24000bc10e04067f017e107f047e23004190036b220224002002412036021420022001360210200241186a2001ad428080808080048410021073024002400240024020022802182203450d00200228021c21042002200241206a28020036022c20022003360228200241086a200241286a10e60120022802080d010240200228020c2205200228022c220641e8006e2201200120054b1b2207ad42e8007e2208422088a70d002008a72201417f4c0d00024002400240024020010d00410821090c010b2001102d2209450d01200141e8006e21070b02402005450d00200241d8026a410172210a4100210b0340200241003a00f802200b41016a210c410021010240024002400240034020062001460d01200241d8026a20016a2002280228220d2d00003a00002002200d41016a3602282002200141016a220d3a00f802200d2101200d4120470d000b20024180026a41086a2201200241d8026a41086a220e29030037030020024180026a41106a220f200241d8026a41106a221029030037030020024180026a41186a2211200241d8026a41186a2212290300370300200220022903d8023703800220022006200d6b36022c200241d8026a200241286a10c30420022d00d802220d4102470d010c020b2002410036022c200141ff0171450d01200241003a00f8024102210d0c020b200241a0026a412f6a2206200a412f6a290000370000200241a0026a41286a2213200a41286a290000370300200241a0026a41206a2214200a41206a290000370300200241a0026a41186a2215200a41186a290000370300200241a0026a41106a2216200a41106a290000370300200241a0026a41086a2217200a41086a2900003703002002200a2900003703a002200228022c22184110490d00200241e0016a41086a2001290300370300200241e0016a41106a200f290300370300200241e0016a41186a2011290300370300200e20172903003703002010201629030037030020122015290300370300200241d8026a41206a2014290300370300200241d8026a41286a2013290300370300200241d8026a412f6a200629000037000020022002290380023703e001200220022903a0023703d8022002201841706a36022c20022002280228220141106a360228200141086a29000021192001290000211a0c010b4102210d0b200241a8016a412f6a2201200241d8026a412f6a290000370000200241a8016a41286a2206200241d8026a41286a290300370300200241a8016a41206a220e200241d8026a41206a290300370300200241a8016a41186a220f200241d8026a41186a290300370300200241a8016a41106a2210200241d8026a41106a290300370300200241a8016a41086a2211200241d8026a41086a29030037030020024188016a41086a2212200241e0016a41086a29030037030020024188016a41106a2213200241e0016a41106a29030037030020024188016a41186a2214200241e0016a41186a290300370300200220022903d8023703a801200220022903e001370388010240200d4102460d00200241d0006a412f6a22152001290000370000200241d0006a41286a22162006290300370300200241d0006a41206a2206200e290300370300200241d0006a41186a220e200f290300370300200241d0006a41106a220f2010290300370300200241d0006a41086a22102011290300370300200241306a41086a22112012290300370300200241306a41106a22122013290300370300200241306a41186a22132014290300370300200220022903a801370350200220022903880137033002402007200b470d00200b4101742201200c2001200c4b1bad42e8007e2208422088a70d052008a722014100480d0502400240200b0d002001102d21090c010b2009200b41e8006c2001103121090b2009450d04200141e8006e21070b2009200b41e8006c6a2201200d3a0000200141196a200e290300370000200141116a200f290300370000200141096a201029030037000020012002290350370001201529000021082016290300211b2006290300211c200141c0006a2019370000200141386a201a370000200141216a201c370000200141296a201b370000200141306a2008370000200141c8006a2002290330370000200141d0006a2011290300370000200141d8006a2012290300370000200141e0006a2013290300370000200c2005460d02200228022c2106200c210b0c010b0b2007450d052009102f0c050b2009450d042000200736020420002009360200200041086a20053602000c050b1036000b1038000b103d000b200041003602000c020b200241003602a802200242013703a0022002410b3602ac012002200241106a3602a8012002200241a0026a360250200241ec026a4101360200200242013702dc02200241b885c7003602d8022002200241a8016a3602e802200241d0006a41d8dbc100200241d8026a103c1a20023502a80242208620023502a002841008024020022802a402450d0020022802a002102f0b200041003602000b2004450d002003102f0b20024190036a24000bae1e04017f067e0f7f037e230041d0026b22032400200241c0006a2903002104200241306a2903002105200241286a2903002106200241106a2903002107200241086a29030021082002290338210920022d0000210a200341186a200241e0006a290000370300200341106a200241d8006a290000370300200341086a200241d0006a29000037030020032002290048370300200341206a41086a200241206a290300370300200320022800013602304104210b2003200241046a2800003600332003200241186a29030037032020012802002802002202280200210c0240024002402002280208220d0d004103210e200c21020c010b200d410574210f200c210202400340200341a8016a20032002221010b20420032802a801220220032802b00110b40441ff0171210e024020032802ac01450d002002102f0b0240200e4103470d00201041206a2102200f41606a220f450d020c010b0b201041206a21020c020b201041206a21024103210e0b0b4101211102400240024002400240024002400240200e41ff0171417e6a220f41014b0d00410021124100211341002114200f0e020102010b410021110b4108102d220b450d03200b2010360204200b200e3a0000200c200d4105746a210f4101211241012113034002400240200f2002470d004103210e0c010b200341a8016a2003200210b20420032802a801221020032802b00110b40441ff0171210e024020032802ac01450d002010102f0b200241206a2102200e4103460d01200241606a21100b024002400240200e41ff0171220c4102470d00201141016a21110c010b200c4103460d010b024020132012470d00201241016a220c2012490d0820124101742213200c2013200c4b1b220c41ffffffff0171200c470d08200c410374220c4100480d080240024020120d00200c102d210b0c010b200b2012410374200c1031210b0b200b450d06200c41037621130b200b20124103746a220c2010360204200c200e3a0000201241016a21120c010b0b02402012450d0020012802042012417f6a10af04220220124f0d05200b20024103746a2d000022024103470d020b201121140b410121024100210c0c010b410241012002410246220c1b2102201121140b200320023a00372001280208210f200341c0026a200128020c360200200341bc026a200341c8026a3602002003200b20124103746a22023602b4022003200b3602b002200320133602ac022003200b3602a8022003200341376a3602b8022003200341b8026a220e3602a80102400340200b2002460d012003200b41086a3602b002200b280200220241ff01714103460d010240200e2002200b28020410dc0422020d0020032802b402210220032802b002210b0c010b0b20034180016a41086a220b200241086a29000037030020034180016a41106a2213200241106a29000037030020034180016a41186a2211200241186a2900003703002003200229000037038001200f41046a21120340200341a8016a41186a220d2011290300370300200341a8016a41106a22152013290300370300200341a8016a41086a2216200b29030037030020032003290380013703a80102400240200f41086a221728020022022012280200460d00200f28020021100c010b200241016a22102002490d05200241017422182010201820104b1b221041ffffff3f712010470d05201041057422184100480d050240024020020d002018102d21100c010b200f28020020024105742018103121100b2010450d03200f2010360200201220184105763602000b201020024105746a221020032903a801370000201041186a200d290300370000201041106a2015290300370000201041086a20162903003700002017200241016a3602002003200e3602a801034020032802b002220220032802b402460d022003200241086a3602b0022002280200221041ff01714103460d02200e2010200228020410dc042202450d000b200b200241086a2900003703002013200241106a2900003703002011200241186a29000037030020032002290000370380010c000b0b024020032802ac02450d0020032802a802102f0b02400240200c0d00200341f0006a41086a200341206a41086a290300370300200320032802303602382003200328003336003b2003200329032037037041c6b5c400ad4280808080f00084100122022900002119200341a8026a41086a200241086a290000370300200320193703a8022002102f419cccc500ad4280808080b0028410012202290000211920034180016a41086a200241086a29000037030020032019370380012002102f4120102d2202450d0220022003290300370000200241186a200341186a290300370000200241106a200341106a290300370000200241086a200341086a2903003700002002ad42808080808004841003220e2900002119200e41086a290000211a200e41106a290000211b200341a8016a41186a2210200e41186a290000370300200341a8016a41106a220f201b370300200341a8016a41086a201a370300200320193703a801200e102f2002102f41c000102d2202450d02200220032903a8023700002002200329038001370010200220032903a801370020200241086a200341a8026a41086a290300370000200241186a20034180016a41086a290300370000200241286a200341a8016a41086a290300370000200241306a200f290300370000200241386a20102903003700004110102d220e450d02200e2009370000200e2004370008200e411041201031210e02400240200a41ff01714101460d00200e450d04200e41003a0010200320073703b001200320083703a801200341a8016a210f41112110412021120c010b200e450d03200e41013a001041c0002112200e412041c0001031220e450d03200e2008370018200e2003280238360011200e2003290370370028200e41206a2007370000200e41146a200328003b360000200e41306a200341f8006a2d00003a0000200320053703b001200320063703a801200341a8016a210f413121100b0240201220106b410f470d00200e20122012410174220b201041106a220c200b200c4b1b1031220e450d030b200e20106a2212200f290000370000201241086a200f41086a2900003700002002ad4280808080800884201041106aad422086200ead841004200e102f2002102f200341a8016a41086a41083a0000200341b1016a2003290300370000200341b9016a200341086a290300370000200341c1016a200341106a290300370000200341c9016a200341186a290300370000200341123a00a80141c8e1ca004100200341a8016a108c01200042003703000c010b20012802102202200228020020146a360200200128021422022002290300221920097c221a370300200241086a2202200229030020047c201a201954ad7c37030020012802002802002102200341a8016a41186a2210200341186a290300370300200341a8016a41106a220f200341106a290300370300200341a8016a41086a2212200341086a290300370300200320032903003703a80102402002280208220e200241046a280200470d00200e41016a220b200e490d04200e410174220c200b200c200b4b1b220b41ffffff3f71200b470d04200b410574220b4100480d0402400240200e0d00200b102d210e0c010b2002280200200e410574200b1031210e0b200e450d022002200e360200200241046a200b4105763602002002280208210e0b2002280200200e4105746a220e20032903a801370000200e41186a2010290300370000200e41106a200f290300370000200e41086a20122903003700002002200228020841016a360208200320032802303602482003200328003336004b200341386a41086a200341206a41086a29030037030020032003290320370338200128021828020021100240024002400240200a41ff01714101470d002003418f016a20073700002003419f016a200341386a41086a2d00003a000020032008370087012003200328004b360083012003200328024836028001200320032903383700970141c6b5c400ad4280808080f00084100122022900002107200341f0006a41086a200241086a290000370300200320073703702002102f41d8cdc500ad4280808080800184100122022900002107200341a8026a41086a200241086a290000370300200320073703a8022002102f4120102d2202450d052002200329038001370000200241186a20034180016a41186a290300370000200241106a20034180016a41106a290300370000200241086a20034180016a41086a2903003700002002ad42808080808004841003220e2900002107200e41086a2900002108200e41106a2900002119200341a8016a41186a220f200e41186a290000370300200341a8016a41106a22122019370300200341a8016a41086a2008370300200320073703a801200e102f2002102f41c000102d2202450d0520022003290370370000200220032903a802370010200220032903a801370020200241086a200341f0006a41086a290300370000200241186a200341a8026a41086a290300370000200241286a200341a8016a41086a290300370000200241306a2012290300370000200241386a200f290300370000200210dd0441ff0171220e4102470d022002102f0c010b200320083703a802200320073703b0022008200784500d002003200336027020034180016a2003200341a8026a200341f0006a1096012003290380014201520d002003290388012107200341e0016a20034180016a41106a290300370300200341d8016a2007370300200341a8016a41086a41003a0000200341b1016a2003290300370000200341b9016a200341086a290300370000200341c1016a200341106a290300370000200341c9016a200341186a290300370000200341033a00a80141c8e1ca004100200341a8016a108c010b20092107200421080c010b2002ad428080808080088410052002102f2009210720042108200e0d0020034180016a20102009200620092006542202200420055420042005511b220e1b20042005200e1b10b0044200200420057d2002ad7d2207200920067d2205200956200720045620072004511b22021b21084200200520021b21070b200320102007200810b004200041386a2004370300200041306a20093703002000410c6a2003290300370200200041146a200341086a2903003702002000411c6a200341106a290300370200200041246a200341186a29030037020020004201370300200020012802102802003602080b200341d0026a24000f0b1036000b41acd9c40020022012103b000b1038000b992209027f017e027f017e2f7f017e1e7f077e017f0240200028028002220241c000490d00200041a0026a22032903002204a7210520004198026a22062903002207a721082004422088a721092007422088a7210a41e5f0c18b06210b41eec8819903210c41b2da88cb07210d41f4ca81d906210e410a21022006280200220f21102000419c026a28020022112112200328020022132114200041a4026a28020022152116200f211720112118201321192015211a200f211b2011211c2013211d2015211e20004194026a280200221f210320004190026a280200222021062000418c026a2802002221212220002802880222232124201f2125202021262021212720232128201f21292020212a2021212b2023212c201f212d2020212e2021212f20232130200041b0026a2903002204422088a7223121322004a722332134200041ac026a2802002235ad422086200041a8026a2802002236ad84223742037c2204422088a7223821392004a7223a213b2031213c2033213d203742027c2204422088a7223e213f2004a7224021412031214220332143203742017c2204422088a7224421452004a722462147203121482033214941f4ca81d906214a41b2da88cb07214b41eec8819903214c41e5f0c18b06214d41f4ca81d906214e41b2da88cb07214f41eec8819903215041e5f0c18b06215141f4ca81d906215241e5f0c18b06215341eec8819903215441b2da88cb0721550340200c20226a220cad422086200b20246a220bad842039ad422086203bad84852204a74110772239201b6a221bad2004422088a7411077223b201c6a221cad422086842022ad4220862024ad84852204a7410c772222200b6a2224ad2004422088a7410c77220b200c6a220cad422086842039ad203bad42208684852204a7410877223b201b6a221bad2004422088a74108772239201c6a221cad422086842022ad200bad42208684852204a74107772222200d20066a220bad200e20036a220dad422086842034ad2032ad42208684852207a7411077220e201d6a221dad2007422088a74110772232201e6a221ead422086842006ad2003ad42208684852207422088a7410c772203200d6a22066a2234ad4220862007a7410c77220d200b6a220bad2006ad42208684200ead2032ad42208684852207a74108772206201d6a221dad2007422088a74108772232201e6a221ead42208684200dad2003ad42208684852207422088a74107772203200b6a220bad842039ad2006ad42208684852256a74110772206201b6a221bad2056422088a74110772239201c6a221cad422086842022ad4220862003ad84852256a7410c772203200b6a220dad2056422088a7410c77222220346a220ead422086842006ad2039ad42208684852256a74108772239201b6a221bad2056422088a74108772234201c6a221cad422086842003ad2022ad42208684852256a741077721032004422088a7410777220620246a2222ad2007a74107772224200c6a220cad42208684203bad4220862032ad84852204a74110772232201d6a221dad2004422088a7411077223b201e6a221ead422086842006ad2024ad42208684852204a7410c77220620226a220bad2004422088a7410c772222200c6a220cad422086842032ad203bad42208684852204a74108772232201d6a221dad2004422088a7410877223b201e6a221ead422086842006ad2022ad42208684852204a74107772122204c20276a2206ad422086204d20286a2224ad84203fad4220862041ad84852207a7411077223f20176a2217ad2007422088a7411077224120186a2218ad422086842027ad4220862028ad84852207a7410c77222720246a2224ad2007422088a7410c77222820066a2206ad42208684203fad2041ad42208684852207a7410877224120176a2217ad2007422088a7410877223f20186a2218ad422086842027ad2028ad42208684852207a74107772227204b20266a2228ad204a20256a224aad42208684203dad203cad42208684852257a7411077223c20196a2219ad2057422088a7411077223d201a6a221aad422086842026ad2025ad42208684852257422088a7410c772225204a6a22266a224aad4220862057a7410c77224b20286a2228ad2026ad42208684203cad203dad42208684852257a7410877222620196a2219ad2057422088a7410877223c201a6a221aad42208684204bad2025ad42208684852257422088a7410777222520286a2228ad84203fad2026ad42208684852258a7411077222620176a2217ad2058422088a7411077223d20186a2218ad422086842027ad4220862025ad84852258a7410c77222520286a224bad2058422088a7410c772227204a6a224aad422086842026ad203dad42208684852258a7410877223f20176a2217ad2058422088a7410877223d20186a2218ad422086842025ad2027ad42208684852258a741077721252007422088a7410777222620246a2224ad2057a7410777222720066a2206ad422086842041ad422086203cad84852207a7411077222820196a2219ad2007422088a7411077223c201a6a221aad422086842026ad2027ad42208684852207a7410c77222620246a224dad2007422088a7410c77222420066a224cad422086842028ad203cad42208684852207a7410877223c20196a2219ad2007422088a74108772241201a6a221aad422086842026ad2024ad42208684852207a741077721272050202b6a2206ad4220862051202c6a2224ad842045ad4220862047ad84852257a7411077222620106a2228ad2057422088a7411077221020126a2212ad42208684202bad422086202cad84852257a7410c77222b20246a2224ad2057422088a7410c77222c20066a2206ad422086842026ad2010ad42208684852257a7410877222620286a2228ad2057422088a7410877221020126a2212ad42208684202bad202cad42208684852257a7410777222b204f202a6a222cad204e20296a2245ad422086842043ad2042ad42208684852259a7411077224220146a2214ad2059422088a7411077224320166a2216ad42208684202aad2029ad42208684852259422088a7410c77222920456a222a6a2245ad4220862059a7410c772247202c6a222cad202aad422086842042ad2043ad42208684852259a7410877222a20146a2214ad2059422088a7410877224220166a2216ad422086842047ad2029ad42208684852259422088a74107772229202c6a222cad842010ad202aad4220868485225aa7411077222a20286a2228ad205a422088a7411077221020126a2212ad42208684202bad4220862029ad8485225aa7410c772229202c6a224fad205a422088a7410c77222b20456a224ead42208684202aad2010ad4220868485225aa7410877224520286a2210ad205a422088a7410877224320126a2212ad422086842029ad202bad4220868485225aa741077721292057422088a7410777222820246a2224ad2059a7410777222a20066a2206ad422086842026ad4220862042ad84852257a7411077222620146a222bad2057422088a7411077222c20166a2216ad422086842028ad202aad42208684852257a7410c77222820246a2251ad2057422088a7410c77222420066a2250ad422086842026ad202cad42208684852257a74108772242202b6a2214ad2057422088a7410877224720166a2216ad422086842028ad2024ad42208684852257a7410777212b205320306a2206ad2054202f6a2224ad422086842035ad4220862036ad84852259a7411077222620086a2228ad2059422088a7411077222a200a6a222cad42208684202fad4220862030ad84852259a7410c77222f20066a2206ad2059422088a7410c77223020246a2224ad422086842026ad202aad42208684852259a7410877222620286a2228ad2059422088a7410877222a202c6a222cad42208684202fad2030ad42208684852259a7410777222f2052202d6a2230ad4220862055202e6a2208ad842049ad2048ad4220868485225ba7411077220a20056a2205ad205b422088a7411077223520096a2209ad42208684202ead202dad4220868485225b422088a7410c77222d20306a222e6a2230ad422086205ba7410c77223620086a2208ad202ead42208684200aad2035ad4220868485225ba7410877222e20056a2205ad205b422088a7410877224820096a2209ad422086842036ad202dad4220868485225b422088a7410777222d20086a2208ad84202aad202ead4220868485225ca7411077222a20286a2228ad205c422088a7411077222e202c6a222cad42208684202fad422086202dad8485225ca7410c77222d20086a2255ad205c422088a7410c77222f20306a2252ad42208684202aad202ead4220868485225ca7410877223520286a2208ad205c422088a74108772249202c6a220aad42208684202dad202fad4220868485225ca7410777212d2059422088a7410777222820066a2206ad205ba7410777222a20246a2224ad422086842026ad4220862048ad84852259a7411077222620056a222cad2059422088a7411077222e20096a222fad422086842028ad202aad42208684852259a7410c77222820066a2253ad2059422088a7410c77220620246a2254ad422086842026ad202ead42208684852259a74108772248202c6a2205ad2059422088a74108772236202f6a2209ad422086842028ad2006ad42208684852259a7410777212f2056422088a741077721242004422088a741077721062058422088a741077721282007422088a74107772126205a422088a7410777212c2057422088a7410777212a205c422088a741077721302059422088a7410777212e2002417f6a22020d000b41002102200041003602800220002802a802215d2000203742047c22043e02a8022000203220316a3602fc012000203420336a3602f8012000203920386a3602f4012000203b203a6a3602f0012000201e20156a3602ec012000201d20136a3602e8012000201c20116a3602e4012000201b200f6a3602e00120002003201f6a3602dc012000200620206a3602d8012000202220216a3602d4012000202420236a3602d0012000200e41f4ca81d9066a3602cc012000200d41b2da88cb076a3602c8012000200c41eec88199036a3602c4012000200b41e5f0c18b066a3602c0012000203c20316a3602bc012000203d20336a3602b8012000203f203e6a3602b4012000204120406a3602b0012000201a20156a3602ac012000201920136a3602a8012000201820116a3602a40120002017200f6a3602a00120002025201f6a36029c012000202620206a360298012000202720216a360294012000202820236a360290012000204a41f4ca81d9066a36028c012000204b41b2da88cb076a360288012000204c41eec88199036a360284012000204d41e5f0c18b066a360280012000204220316a36027c2000204320336a3602782000204520446a3602742000204720466a3602702000201620156a36026c2000201420136a3602682000201220116a36026420002010200f6a36026020002029201f6a36025c2000202a20206a3602582000202b20216a3602542000202c20236a3602502000204e41f4ca81d9066a36024c2000204f41b2da88cb076a3602482000205041eec88199036a3602442000205141e5f0c18b066a3602402000200920156a36022c2000200520136a3602282000200a20116a36022420002008200f6a3602202000202d201f6a36021c2000202e20206a3602182000202f20216a3602142000203020236a3602102000205241f4ca81d9066a36020c2000205541b2da88cb076a3602082000205441eec88199036a3602042000205341e5f0c18b066a36020020002802ac022103200020044220883e02ac02200020002802b40220486a36023c200020002802b00220496a3602382000200320356a3602342000205d20366a3602300b200020024102746a28020021032000200241016a360280020240200141016a220620014f0d004180dcc400413941bcdcc4001039000b20032006700bcc0703027f037e077f230041c0006b2204240002402002200384500d0041c6b5c400ad4280808080f00084100122052900002106200441086a200541086a290000370300200420063703002005102f41f6dbc400ad4280808080f00084100122052900002106200441106a41086a200541086a290000370300200420063703102005102f0240024002400240024002404120102d2205450d0020052000290000370000200541186a200041186a290000370000200541106a200041106a290000370000200541086a200041086a2900003700002005ad4280808080800484100322002900002106200041086a2900002107200041106a2900002108200441206a41186a2209200041186a290000370300200441206a41106a220a2008370300200441206a41086a2007370300200420063703202000102f2005102f41c000102d220b450d00200b2004290300370000200b2004290310370010200b2004290320370020200b41086a200441086a290300370000200b41186a200441106a41086a290300370000200b41286a200441206a41086a290300370000200b41306a200a290300370000200b41386a2009290300370000200441206a200b10b704024002400240024002402004280220220c0d004100210d20044100360210410021054108210c4100210e0c010b20042004280224220e36021020042902242206a7210f410021050240024002402006422088a7220d41014b0d00200d0e020201020b200d2100034020052000410176220920056a220a200c200a41186c6a28020020014b1b2105200020096b220041014b0d000b0b200c200541186c6a28020022002001460d03200520002001496a2205200d4b0d060b200d200f470d01200e200d470d010b200e41016a2200200e490d05200e41017422092000200920004b1bad42187e2206422088a70d052006a722004100480d0502400240200e0d002000102d210c0c010b200c200e41186c20001031210c0b200c450d032004200041186e3602100b200c200541186c6a220041186a2000200d20056b41186c10e9061a200041106a20033703002000200237030820002001360200200c450d06200d41016a210d2004280210210f0c010b2005200d4f0d04200c200541186c6a22052005290308220620027c2202370308200541106a2205200529030020037c2002200654ad7c3703000b200441c0003602242004200b360220200c200d200441206a10b804200f450d05200c102f0c050b1036000b419ae3c300411e41f8b4ca001039000b1038000b419cc3ca002005200d103b000b200bad428080808080088410050b200b102f0b200441c0006a24000be90202047f017e230041206b2203240002400240200241e8006c4104722204417f4c0d002004102d2205450d0120034100360208200320043602042003200536020020022003106902402002450d00200241e8006c21064100210403402003200120046a220241c8006a41201082010240024020022d00004101460d00200341003a00102003200341106a4101108201200241086a29030021072003200241106a29030037031820032007370310200341106a21050c010b200341013a00102003200341106a41011082012003200241016a4120108201200241286a29030021072003200241306a29030037031820032007370310200341106a21050b200320054110108201200241386a29030021072003200241c0006a290300370318200320073703102003200341106a41101082012006200441e8006a2204470d000b0b20002003290300370200200041086a200341086a280200360200200341206a24000f0b103d000b1036000b9c0703027f017e057f230041d0006b2203240041c6b5c400ad4280808080f00084100122042900002105200341086a200441086a290000370300200320053703002004102f41d7b5c400ad4280808080d00084100122042900002105200341106a41086a200441086a290000370300200320053703102004102f024002404120102d2204450d0020042001290000370000200441186a200141186a290000370000200441106a200141106a290000370000200441086a200141086a29000037000020032004ad4280808080800484100622012900003703302001102f200341c4006a200441206a360200200341003a0048200320043602402003200341306a41086a220636023c2003200341306a360238200341206a200341386a106c2004102f02400240024002402003280228220741206a2208417f4c0d0020032802202109024002402008450d002008102d2204450d062008410f4d0d012008210a0c050b4110210a4110102d21040c030b200841017422014110200141104b1b220a41004e0d010c050b103d000b20042008200a103121040b2004450d010b20042003290300370000200441086a200341086a29030037000002400240200a4170714110460d00200a21010c010b200a41017422014120200141204b1b22014100480d022004200a200110312204450d010b20042003290310370010200441186a200341106a41086a29030037000002400240200141606a2007490d002001210a0c010b2007415f4b0d022001410174220a2008200a20084b1b220a4100480d0220042001200a10312204450d010b200441206a2009200710e8061a02402003280224450d002009102f0b4120102d2201450d0020012002290000370000200141186a200241186a290000370000200141106a200241106a290000370000200141086a200241086a29000037000020032001ad4280808080800484100622022900003703302002102f200341c4006a200141206a360200200341003a0048200320013602402003200636023c2003200341306a360238200341106a200341386a106c2001102f2003280210210702400240200a20086b20032802182201490d00200120086a2102200a21090c010b200820016a22022008490d02200a41017422092002200920024b1b22094100480d022004200a200910312204450d010b200420086a2007200110e8061a02402003280214450d002007102f0b200020023602082000200936020420002004360200200341d0006a24000f0b1036000b1038000b8b0503027f017e047f230041d0006b2202240041c6b5c400ad4280808080f00084100122032900002104200241086a200341086a290000370300200220043703002003102f41ecdac400ad4280808080d00184100122032900002104200241106a41086a200341086a290000370300200220043703102003102f024002404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad4280808080800484100622012900003703302001102f200241c4006a200341206a360200200241003a0048200220033602402002200241306a41086a36023c2002200241306a360238200241206a200241386a106c2003102f02400240024002402002280228220541206a2201417f4c0d0020022802202106024002402001450d002001102d2203450d062001410f4d0d01200121070c050b411021074110102d21030c030b200141017422084110200841104b1b220741004e0d010c050b103d000b200320012007103121030b2003450d010b20032002290300370000200341086a200241086a2903003700000240024020074170714110460d00200721080c010b200741017422084120200841204b1b22084100480d0220032007200810312203450d010b20032002290310370010200341186a200241106a41086a29030037000002400240200841606a2005490d00200821070c010b2005415f4b0d02200841017422072001200720014b1b22074100480d0220032008200710312203450d010b200341206a2006200510e8061a20002001360208200020073602042000200336020002402002280224450d002006102f0b200241d0006a24000f0b1036000b1038000b9a0203017f017e017f230041d0006b220224002002200136020420022000360200200241086a2001ad4220862000ad8422031002107302400240200228020822010d00410321000c010b200228020c210402400240200241106a280200450d0020012d000022004103490d010b20024100360220200242013703182002410b36022c200220023602282002200241186a360234200241cc006a41013602002002420137023c200241b885c7003602382002200241286a360248200241346a41d8dbc100200241386a103c1a200235022042208620023502188410080240200228021c450d002002280218102f0b02402004450d002001102f0b410321000c010b02402004450d002001102f0b200310050b200241d0006a240020000b8a1604057f017e057f027e23004180026b22012400200141d0006a41186a22024200370300200141d0006a41106a22034200370300200141d0006a41086a220442003703002001420037035041c6b5c400ad4280808080f00084100122052900002106200141f0006a41086a2207200541086a290000370300200120063703702005102f2004200729030037030020012001290370370350419ab6c400ad4280808080c0008410012205290000210620014180016a41086a2207200541086a29000037030020012006370380012005102f20032001290380012206370300200141306a41086a2004290300370300200141306a41106a2006370300200141306a41186a20072903003703002001200129035037033020014180016a200141306a412010ad0220012d0080012107200220014180016a41196a290000370300200320014180016a41116a290000370300200420014180016a41096a2900003703002001200129008101370350410121050240024020074101460d0041002105200141003a00080c010b200141086a41096a2004290300370000200141086a41116a2003290300370000200141086a41196a2002290300370000200141013a0008200120012903503700090b20014199016a200041186a29000037000020014191016a200041106a29000037000020014189016a200041086a2900003700002001200029000037008101200141013a00800102400240024002402005450d00200141086a41017220014180016a410172412010ea06450d010b200141d0006a41186a22054200370300200141d0006a41106a22024200370300200141d0006a41086a220442003703002001420037035041c6b5c400ad4280808080f00084100122072900002106200141f0006a41086a2208200741086a290000370300200120063703702007102f20042008290300370300200120012903703703504193b6c400ad4280808080f0008410012207290000210620014180016a41086a2208200741086a29000037030020012006370380012007102f2003200129038001370000200341086a2008290300370000200141306a41086a2004290300370300200141306a41106a2002290300370300200141306a41186a20052903003703002001200129035037033020014180016a200141306a412010ad0220012d0080012108200520014180016a41196a290000370300200220014180016a41116a290000370300200420014180016a41096a2900003703002001200129008101370350410121070240024020084101460d0041002107200141003a00080c010b200141086a41096a2004290300370000200141086a41116a2002290300370000200141086a41196a2005290300370000200141013a0008200120012903503700090b20014199016a200041186a29000037000020014191016a200041106a29000037000020014189016a200041086a2900003700002001200029000037008101200141013a00800102402007450d00200141086a41017220014180016a410172412010ea06450d010b20014180016a41186a420037030020014180016a41106a2202420037030020014180016a41086a22044200370300200142003703800141c6b5c400ad4280808080f000841001220529000021062004200541086a29000037030020012006370380012005102f41ebdec700ad4280808080f00084100122052900002106200141d0006a41086a2207200541086a290000370300200120063703502005102f200220012903502206370300200141086a41086a2004290300370300200141086a41106a2006370300200141086a41186a2007290300370300200120012903800137030820014180016a200141086a412010aa022001280280012204410120041b21080240024002400240200129028401420020041b2206422088a7220941014b0d004100210420090e020201020b2009210541002104034020042005410176220220046a2207200820074105746a2000412010ea0641004a1b2104200520026b220541014b0d000b0b200820044105746a2000412010ea06450d010b2006a7450d012008102f0c010b200420094f0d01200820044105746a2205200541206a2004417f7320096a41057410e9061a200141d0006a41186a220a4200370300200141d0006a41106a220b4200370300200141d0006a41086a220442003703002001420037035041c6b5c400ad4280808080f00084220c10012205290000210d200141f0006a41086a2202200541086a2900003703002001200d3703702005102f200420022903003703002001200129037037035041ebdec700ad4280808080f0008410012205290000210d20014180016a41086a2207200541086a2900003703002001200d370380012005102f2003200129038001370000200341086a2007290300370000200141306a41086a2004290300370300200141306a41106a200b290300370300200141306a41186a200a2903003703002001200129035037033020014120360284012001200141306a3602800120082009417f6a20014180016a10aa0102402006a7450d002008102f0b200c1001220429000021062002200441086a290000370300200120063703702004102f41dfdbc400ad42808080808002841001220429000021062007200441086a29000037030020012006370380012004102f4120102d2204450d0220042000290000370000200441186a200041186a290000370000200441106a200041106a290000370000200441086a200041086a2900003700002004ad4280808080800484100322052900002106200541086a290000210c200541106a290000210d200141d0006a41186a2207200541186a290000370300200141d0006a41106a2208200d370300200141d0006a41086a2202200c370300200120063703502005102f2004102f41c000102d2204450d0220042001290370370000200420012903800137001020042001290350370020200441086a200141f0006a41086a290300370000200441186a20014180016a41086a290300370000200441286a2002290300370000200441306a2008290300370000200441386a2007290300370000200141013a0080012004ad428080808080088420014180016aad4280808080108410042004102f41c6b5c400ad4280808080f000841001220429000021062002200441086a290000370300200120063703502004102f41efdbc400ad4280808080f00084100122042900002106200141086a41086a200441086a290000370300200120063703082004102f4120102d2204450d0220042000290000370000200441186a200041186a2207290000370000200441106a200041106a2208290000370000200441086a200041086a22032900003700002004ad4280808080800484100322052900002106200541086a290000210c200541106a290000210d20014180016a41186a2209200541186a29000037030020014180016a41106a220a200d37030020014180016a41086a2202200c37030020012006370380012005102f2004102f41c000102d2204450d0220042001290350370000200420012903083700102004200129038001370020200441086a200141d0006a41086a290300370000200441186a200141086a41086a290300370000200441286a2002290300370000200441306a200a290300370000200441386a20092903003700002004ad428080808080088410052004102f200241093a000020014180016a41096a200029000037000020014191016a200329000037000020014199016a2008290000370000200141a1016a2007290000370000200141123a00800141c8e1ca00410020014180016a108c010b20014180026a24000f0b41b8e3c300411d41f8b4ca001039000b1036000bcab4010d017f017e037f017e0a7f027e027f017e027f017e147f027e0d7f230041b0056b2200240042002101200041b0036a41186a4200370300200041b0036a41106a22024200370300200041b0036a41086a22034200370300200042003703b00341bd98ca00ad42808080808002841001220429000021052003200441086a290000370300200020053703b0032004102f418c91c700ad4280808080a00184100122042900002105200041d0026a41086a2206200441086a290000370300200020053703d0022004102f200220002903d0022205370300200041f8026a41086a2003290300370300200041f8026a41106a2005370300200041f8026a41186a2006290300370300200020002903b0033703f802200041b0036a200041f8026a412010aa020240024020002802b00322070d0041012107410021080c010b20002902b4032201422088a721080b0240024002400240200841ffffff3f712008470d0020084105742203417f4c0d00024002400240024020030d00200720084105746a2104410121092008210a0c010b2003102d2209450d04200720084105746a21042003410576220a20084f0d00200a41017422032008200320084b1b220341ffffff3f712003470d06200341057422034100480d0602400240200a0d002003102d21090c010b2009200a4105742003103121090b2009450d042003410576210a0c010b20080d004100210b0c010b200420076b210c410021030340200920036a2204200720036a2206290000370000200441186a200641186a290000370000200441106a200641106a290000370000200441086a200641086a290000370000200c200341206a2203470d000b200720084105746a20076b41606a41057641016a210b0b200041b0036a41186a22064200370300200041b0036a41106a220c4200370300200041b0036a41086a22034200370300200042003703b00341bd98ca00ad42808080808002841001220429000021052003200441086a290000370300200020053703b0032004102f41ebdec700ad4280808080f00084100122042900002105200041d0026a41086a2208200441086a290000370300200020053703d0022004102f200220002903d002370000200241086a2008290300370000200041f8026a41086a2003290300370300200041f8026a41106a200c290300370300200041f8026a41186a2006290300370300200020002903b0033703f802200041b0036a200041f8026a10e404410021060240024020002902b403420020002802b00322031b2205422088a7220441306c220c0d00410121084100210d0c010b200c41306d220c41ffffff3f71200c470d04200c410574220c4100480d04200c102d2208450d02200c410576210d0b2005a7210e2003410820031b210f02402004450d00200441306c210c4100210620082103200f21040340200441086a2900002105200441106a290000211020042900002111200341186a200441186a290000370000200341106a2010370000200341086a200537000020032011370000200641016a2106200341206a2103200441306a2104200c41506a220c0d000b0b0240200e450d00200f102f0b02402001a722032001422088a7220f6b20064f0d00200f20066a2204200f490d042003410174220c2004200c20044b1b220441ffffff3f712004470d04200441057422044100480d040240024020030d002004102d21070c010b200720034105742004103121070b2007450d022001422088a7210f2004410576ad21010b2007200f4105746a2008200641057410e8061a0240200d450d002008102f0b200041b0036a41186a220c4200370300200041b0036a41106a22084200370300200041b0036a41086a22034200370300200042003703b00341bd98ca00ad42808080808002841001220429000021052003200441086a290000370300200020053703b0032004102f419691c700ad4280808080900184100122042900002105200041d0026a41086a220d200441086a290000370300200020053703d0022004102f200220002903d002370000200241086a200d290300370000200041f8026a41086a2003290300370300200041f8026a41106a2008290300370300200041f8026a41186a200c290300370300200020002903b0033703f802200041b0036a200041f8026a10e404410021080240024020002902b403420020002802b00322031b2205422088a7220441306c220c0d00410121024100210e0c010b200c41306d220c41ffffff3f71200c470d04200c410574220c4100480d04200c102d2202450d02200c410576210e0b2005a721122003410820031b210d02402004450d00200441306c210c4100210820022103200d21040340200441086a2900002105200441106a290000211020042900002111200341186a200441186a290000370000200341106a2010370000200341086a200537000020032011370000200841016a2108200341206a2103200441306a2104200c41506a220c0d000b0b200f20066a211302402012450d00200d102f0b024002402001a7220320136b2008490d00200142ffffffff0f8321140c010b201320086a22042013490d04200341017422062004200620044b1b220441ffffff3f712004470d04200441057422044100480d040240024020030d002004102d21070c010b200720034105742004103121070b2007450d022004410576ad21140b200720134105746a2002200841057410e8061a0240200e450d002002102f0b41bd98ca00ad4280808080800284100122032900002105200041f8026a41086a2206200341086a290000370300200020053703f8022003102f41a185c700ad4280808080d00184100122032900002105200041d0026a41086a2204200341086a290000370300200020053703d0022003102f200041b0036a41086a22032006290300370300200041b0036a41186a22062004290300370300200020002903f8023703b003200020002903d0023703c003200041f8026a200041b0036a108801200041b0036a20002802f802220c20002802800310ad02024020002802fc02450d00200c102f0b200041a8026a41086a20032903002205370300200041a8026a41106a200041b0036a41106a220c2903002210370300200041a8026a41186a20062903002211370300200041a8026a41206a200041b0036a41206a2d000022033a0000200020002903b00322013703a802200041d0026a41206a20033a0000200041d0026a41186a2011370300200041d0026a41106a201037030020042005370300200020013703d002200041b0036a200041d0026a1093040240024020002802d0032206450d00200041f8026a41186a2203200041b0036a41186a290300370300200041f8026a41106a200c290300370300200041f8026a41086a2204200041b0036a41086a290300370300200020002903b0033703f80220002902d4032105412c102d2215450d03201520002903f8023702002015200537022420152006360220201541186a2003290300370200201541106a200041f8026a41106a2206290300370200201541086a2004290300370200200041f8026a41206a200041d0026a41206a2d00003a00002003200041d0026a41186a2903003703002006200041d0026a41106a2903003703002004200041d0026a41086a290300370300200020002903d0023703f802200041b0036a200041f8026a109304024020002802d00322020d004101210c410121160c020b41022106412c21044101210c410121160340200041b0046a41186a200041b0036a41186a2903002205370300200041b0046a41106a200041b0036a41106a2903002210370300200041b0046a41086a200041b0036a41086a2903002211370300200020002903b00322013703b00420002902d4032117200041d0046a41186a220f2005370300200041d0046a41106a220d2010370300200041d0046a41086a220e2011370300200020013703d0040240200c2016470d00200c41016a2203200c490d0720062003200620034b1bad422c7e2205422088a70d072005a722034100480d0702400240200c0d002003102d21150c010b201520042003103121150b2015450d052003412c6e21160b201520046a220320002903d004370200200341186a200f290300370200200341106a200d290300370200200341086a200e290300370200200341246a2017370200200341206a2002360200200641026a21062004412c6a2104200c41016a210c200041b0036a200041f8026a10930420002802d00322020d000c020b0b410421154100210c410021160b200042003702f40420004190bdc6003602f004200c201320086a22046a2218ad42e0007e2205422088a70d002005a72203417f4c0d00410821134108211902402003450d002003102d2219450d02200341e0006e21180b4100210e4100211a024020044105742208450d002008410575ad42d8007e2205422088a70d042005a722034100480d042003102d2213450d02200341d8006e211a0b02402004450d00200841606a211b200041e0036a2104200041d8036a211c2013210241002106200721030340200041a8026a41186a220f200341186a220d290000370300200041a8026a41106a220e200341106a2212290000370300200041a8026a41086a221d200341086a221e290000370300200020032900003703a802200041f8026a41186a200d290000370300200041f8026a41106a2012290000370300200041f8026a41086a201e290000370300200020032900003703f802200041f0046a200041f8026a2006109a02200041b0036a41086a4200370300200041b0036a41106a4200370300200041b0036a41186a4200370300200041b0036a41206a4200370300201c4200370300200441186a200f290300370000200441106a200e290300370000200441086a201d290300370000200420002903a802370000200042003703b0032002200041b0036a41d00010e806220241d0006a41003a0000200241d8006a2102200341206a2103200641016a2106200841606a22080d000b201b41057641016a210e0b02402014500d002007102f0b02402018200c412c6c2203412c6d22044f0d00201841017422062004200620044b1bad42e0007e2205422088a70d042005a722044100480d040240024020180d002004102d21190c010b2019201841e0006c2004103121190b2019450d02200441e0006e21180b201520036a211f024002400240200c0d0041002120201521210c010b200041d0046a41106a211d20152103201921224100212002400340200041b0046a41186a2206200341186a290200370300200041b0046a41106a220c200341106a290200370300200041b0046a41086a2208200341086a290200370300200020032902003703b0042003412c6a212120032802202223450d02200341286a2802002104200341246a2802002124200041a8026a41186a22252006290300370300200041a8026a41106a2226200c290300370300200041a8026a41086a22272008290300370300200020002903b0043703a80220004198026a200041a8026a1093052004ad42c8007e2205422088a70d042005a72203417f4c0d0420004198026a41086a290300211720002903980221140240024020030d0041082107200421120c010b2003102d2207450d06200341c8006e21120b02400240024020040d004100211e0c010b202320044105746a21284100211e2023210d0340200d41086a2900002105200d41106a2900002110200d2900002111200041b0036a41186a221c200d41186a290000370300200041b0036a41106a221b2010370300200041b0036a41086a22292005370300200020113703b003200d41206a210d200041f0046a210320002802f404210202400240034002400240200328020022082f0106220f0d00410021060c010b200f4105742103200841086a2104417f21060340024020030d00200f21060c020b200641016a2106200041b0036a2004412010ea06220c450d03200341606a2103200441206a2104200c417f4a0d000b0b2002450d022002417f6a2102200820064102746a4194036a21030c000b0b200e200820064102746a41e8026a220328020022044d0d032013200441d8006c6a22042903202105200441286a2903002110200041d0046a41186a220c4200370300201d4200370300200041d0046a41086a22044200370300200042003703d00441e7a2ca00ad42808080808001841001220629000021112004200641086a290000370300200020113703d0042006102f41ecb5c600ad4280808080d00184100122062900002111200041a0056a41086a2208200641086a290000370300200020113703a0052006102f201d20002903a005370000201d41086a2008290300370000200041f8026a41086a2004290300370300200041f8026a41106a201d290300370300200041f8026a41186a200c290300370300200020002903d0043703f80220004180026a200041f8026a4120109c01200041f0016a20002903880220004180026a41106a290300427f420010ee06200e200328020022044d0d05200041e0016a2014201720002903f001420020002802800222061b221142012011420156200041f0016a41086a290300420020061b22114200522011501b22061b2011420020061b10ee062013200441d8006c6a220441286a427f2010200520002903e0017c22112005542206ad7c220120062001201054201120055a1b22061b3703002004427f201120061b370320200041d0026a41186a2204201c290300370300200041d0026a41106a2206201b290300370300200041d0026a41086a220c2029290300370300200020002903b0033703d0022003280200210802400240201e2012460d00201e21030c010b201241016a22032012490d0c201241017422022003200220034b1bad42c8007e2205422088a70d0c2005a722024100480d0c0240024020120d002002102d21070c010b2007201241c8006c2002103121070b2007450d0a20122103200241c8006e21120b2007200341c8006c6a2203420037030020032008360220200341186a4200370300200341106a4200370300200341086a4200370300200320002903d0023702242003412c6a200c290300370200200341346a20062903003702002003413c6a2004290300370200201e41016a211e0b200d2028470d000b0b02402024450d002023102f0b20004180056a41186a2206202529030037030020004180056a41106a220c202629030037030020004180056a41086a22082027290300370300200020002903a80237038005200041d0046a41186a22024200370300201d4200370300200041d0046a41086a22034200370300200042003703d00441e7a2ca00ad42808080808001841001220429000021052003200441086a290000370300200020053703d0042004102f41ecb5c600ad4280808080d00184100122042900002105200041a0056a41086a220f200441086a290000370300200020053703a0052004102f201d20002903a005370000201d41086a200f290300370000200041f8026a41086a2003290300370300200041f8026a41106a201d290300370300200041f8026a41186a2002290300370300200020002903d0043703f802200041c8016a200041f8026a4120109c01200041b8016a20002903d001200041c8016a41106a290300427f420010ee06200041a8016a2014201720002903b801420020002802c80122031b220542012005420156200041b8016a41086a290300420020031b22054200522005501b22031b2005420020031b10ee0620224200370308202220002903a80137030020224200370310202241186a4200370300202241286a4200370300202242013703202022201e3602382022201236023420222007360230202220002903800537023c202241c4006a2008290300370200202241cc006a200c290300370200202241d4006a2006290300370200202041016a2120202241e0006a2122202121032021201f470d010c040b0b41c4c2ca002004200e103b000b419cc3ca002004200e103b000b201f2021460d0003402021412c6a21030240202141246a280200450d00202141206a280200102f0b20032121201f2003470d000b0b02402016450d002015102f0b41c007102d221c450d0141f006102d222a450d01410021244114212502400240200e4114200e4114491b22260d004114212b410021150c010b201341a87f6a2123200e41d8006c21212019202041e0006c6a211b41142128200041b0036a41186a211f200041b0036a41106a2107200041b0036a41086a2116410021154100212203400240200e450d00202121042013210303400240200341d0006a2d00000d0002400240200341206a2903002210200341286a29030022118450450d0042002105427f2110427f21110c010b427f210520004198016a427f427f2010201110ee0620004198016a41086a290300211120002903980121100b2003201037030020032011370308200341106a2005370300200341186a20053703000b200341d8006a2103200441a87f6a22040d000b0b2019210c02402020450d00024003400240200c2802382203450d00200341c8006c2106200c28023041206a21030340200e200328020022044d0d0302402013200441d8006c6a22042d00500d0020042903202205200441286a290300221084500d00200041b0036a200c290310200c41186a290300200c290300200c41086a29030020052010109405200420042903002205427f2005427f20002903b80320002802b00341014622081b22117c221020102005542202200441086a220f2903002205427f200729030020081b22017c2002ad7c221020055420102005511b22081b20112001845022021b370300200f2005427f201020081b20021b3703000b200341c8006a2103200641b87f6a22060d000b0b200c41e0006a220c201b460d020c000b0b419cc3ca002004200e103b000b202241016a21222021210320232104201321060340024020030d002028212b0c030b200341a87f6a2103200441d8006a2104200641d0006a210c200641d8006a22082106200c2d00000d000b02402003450d00200441086a2903002105200441186a2903002110200441106a2903002111200429030021014100210603400240200820066a220c41d0006a2d00000d00200c41086a290300221720052001200520112010200c29030022142017200c41106a290300222c200c41186a290300222d10950541ff017141014622021b21052014200120021b2101202d201020021b2110202c201120021b2111200c200420021b21040b2003200641d8006a2206470d000b20040d002028212b0c020b200441013a005002402020450d002004410c6a211d200441306a211e201921060340200641e0006a212902402006280238220c450d0020062802302103200c41c8006c210c034002400240201d2003460d00200341246a201e412010ea060d010b200641186a22082903002101200441086a22022903002105200629031021112004290300211020042903102117200341186a200441186a220f290300370300200341106a2017370300200320054200200520017d2010201154ad7d2217201020117d2214201056201720055620172005511b220d1b20112001845022121b3703082003201042002014200d1b20121b37030020022903002105200f29030021102004290300211120062004290310370320200641286a201037030020062011370310200820053703000b200341c8006a2103200c41b87f6a220c0d000b0b202921062029201b470d000b0b201f200441c8006a2900003703002007200441c0006a2900003703002016200441386a290000370300200020042900303703b003200441286a2903002105200429032021100240024020152028460d002028212b0c010b202841016a22032028490d06202841017422042003200420034b1bad42307e2211422088a70d062011a722034100480d060240024020280d002003102d211c0c010b201c202841306c20031031211c0b201c450d0420282115200341306e222b21280b2016290300211120072903002101201f290300211720002903b0032114201c201541306c6a2203201037032020032014370300200341286a2005370300200341186a2017370300200341106a2001370300200341086a2011370300201541016a211520222026490d000b0b02402020450d002019202041e0006c6a2121201541306c211b41142125200041f8026a41186a2129200041f8026a41106a2128200041f8026a41086a2122410021242019211d03402029201d41d4006a2900003703002028201d41cc006a2900003703002022201d41c4006a2900003703002000201d29003c3703f8020240201d2802382203450d00201d280230220d200341c8006c6a211e201d41106a21074100210e410421124100210f0340200d220241246a2106200241c8006a210d4100210c201b2104201c2103024003402004450d01024020062003460d0020032006412010ea062108200c41016a210c200441506a2104200341306a210320080d010b0b418094ebdc0321030240200720021096050d00410021032002290310201d29032085200241186a290300201d41286a29030085844200520d00200041b0036a428094ebdc0342002002290300200241086a2903002007290300200741086a290300109405427f20002903b80320002802b00341014622031b2205a7417f2005428080808010544100427f200041b0036a41106a29030020031b501b1b21030b200020033602b0032000418094ebdc033602b403200041b0036a2003418094ebdc034b4102746a2802002104200041b0036a41186a22062002413c6a290000370300200041b0036a41106a220c200241346a290000370300200041b0036a41086a22082002412c6a290000370300200020022900243703b00302400240200f200e460d00200f21030c010b200e41016a2203200e490d09200e41017422022003200220034b1bad42247e2205422088a70d092005a722024100480d0902400240200e0d002002102d21120c010b2012200e41246c2002103121120b2012450d07200e2103200241246e210e0b2012200341246c6a220320002903b00337020020082903002105200c29030021102006290300211120032004360220200341186a2011370200200341106a2010370200200341086a2005370200200f41016a210f0b200d201e470d000b024002400240200f450d0002400240200f41246c22060d00410021030c010b201241206a2104410021030340417f200320042802006a220c200c2003491b2103200441246a21042006415c6a22060d000b0b02404100418094ebdc0320036b22032003418094ebdc034b1b2202200f6e2203418094ebdc032003418094ebdc03491b2208450d00201241206a2103410021040340200f2004460d032000417f2003280200220620086a220c200c2006491b22063602b0032000418094ebdc033602b4032003200041b0036a2006418094ebdc034b4102746a280200360200200341246a2103200f200441016a2204470d000b0b024020022008200f6c6b2208450d00410021030340200f2003200f7022044d0d042000417f2012200441246c6a2204280220220641016a220c200c2006491b22063602b0032000418094ebdc033602b4032004200041b0036a2006418094ebdc034b4102746a280200360220200341016a22032008490d000b0b200041b0036a41186a22042029290300370300200041b0036a41106a22062028290300370300200041b0036a41086a220c2022290300370300200020002903f8023703b003024020242025470d00202541016a22032025490d0a202541017422082003200820034b1bad422c7e2205422088a70d0a2005a722034100480d0a0240024020250d002003102d212a0c010b202a2025412c6c20031031212a0b202a450d08202521242003412c6e21250b202a2024412c6c6a220320002903b003370200200c290300210520062903002110200429030021112003200f3602282003200e36022420032012360220200341186a2011370200200341106a2010370200200341086a2005370200202441016a21240c030b200e450d022012102f0c020b41c4c2ca002004200f103b000b41c4c2ca002004200f103b000b201d41e0006a221d2021470d000b0b0240201a450d002013102f0b02402020450d00202041e0006c2104201941306a210303400240200341046a280200450d002003280200102f0b200341e0006a2103200441a07f6a22040d000b0b02402018450d002019102f0b20002802f00420002802f40420002802f80410a30202400240201c0d0041012112200041013a00b403200041093a00b00341c8e1ca004100200041b0036a108c01200041f8026a210c0c010b42002105200041b0036a41186a4200370300200041b0036a41106a222e42003703004108210c200041b0036a41086a22044200370300200042003703b00341bd98ca00ad4280808080800284100122062900002110200041d0026a41086a2203200641086a290000370300200020103703d0022006102f20042003290300370300200020002903d0023703b00341ebdec700ad4280808080f000841001220629000021102003200641086a290000370300200020103703d0022006102f202e20002903d0022210370300200041f8026a41086a2004290300370300200041f8026a41106a2010370300200041f8026a41186a2003290300370300200020002903b0033703f802200041b0036a200041f8026a10e404024020002802b0032203450d00200041f8026aad4280808080800484100520002902b40321052003210c0b41002127024002402005422088a7220341306c22040d004101212f410021300c010b200441306d220441ffffff3f712004470d05200441057422044100480d052004102d222f450d03200441057621300b2005a7210802402003450d00200341306c210641002127202f2103200c21040340200441086a2900002105200441106a290000211020042900002111200341186a200441186a290000370000200341106a2010370000200341086a200537000020032011370000202741016a2127200341206a2103200441306a2104200641506a22060d000b0b02402008450d00200c102f0b42002105200041b0036a41186a22084200370300200041b0036a41106a220242003703004108210c200041b0036a41086a22044200370300200042003703b00341bd98ca00ad4280808080800284100122062900002110200041d0026a41086a2203200641086a290000370300200020103703d0022006102f20042003290300370300200020002903d0023703b003419691c700ad42808080809001841001220629000021102003200641086a290000370300200020103703d0022006102f202e20002903d002370000202e41086a2003290300370000200041f8026a41086a2004290300370300200041f8026a41106a2002290300370300200041f8026a41186a2008290300370300200020002903b0033703f802200041b0036a200041f8026a10e404024020002802b0032203450d00200041f8026aad4280808080800484100520002902b40321052003210c0b41002119024002402005422088a7220341306c22040d0041012131410021320c010b200441306d220441ffffff3f712004470d05200441057422044100480d052004102d2231450d03200441057621320b2005a7210802402003450d00200341306c21064100211920312103200c21040340200441086a2900002105200441106a290000211020042900002111200341186a200441186a290000370000200341106a2010370000200341086a200537000020032011370000201941016a2119200341206a2103200441306a2104200641506a22060d000b0b02402008450d00200c102f0b024002400240201541306c2204450d00201c21030340200341286a2903002105200341206a2903002110200041d0046a41186a200341186a290200370300200041d0046a41106a200341106a290200370300200041d0046a41086a200341086a290200370300200020032902003703d00420102005844200520d02200341306a2103200441506a22040d000b0b410121294100211b0240202b450d00201c102f0b410021280c010b200041a8026a41086a2206200041d0046a41086a290300370300200041a8026a41106a220c200041d0046a41106a290300370300200041a8026a41186a2208200041d0046a41186a290300370300200020002903d004220537038005200020053703a8024120102d2229450d03202920002903a802370000202941186a2008290300370000202941106a200c290300370000202941086a20062903003700000240024020044130470d004101211b410121280c010b200341306a2106201c201541306c6a220841506a21024101211b4101212803402006210302400340200341286a2903002105200341206a2903002110200041d0046a41186a2204200341186a290200370300200041d0046a41106a2206200341106a290200370300200041d0046a41086a220c200341086a290200370300200020032902003703d00420102005844200520d012008200341306a2203470d000c030b0b200041f8026a41086a200c2903002205370300200041f8026a41106a20062903002210370300200041f8026a41186a20042903002211370300200020002903d00422013703f80220004180056a41186a220c201137030020004180056a41106a220f201037030020004180056a41086a220d2005370300200020013703800502402028201b470d00201b41016a2204201b490d08201b41017422062004200620044b1b220441ffffff3f712004470d08200441057422044100480d0802400240201b0d002004102d21290c010b2029201b4105742004103121290b2029450d06200441057621280b200341306a21062029201b4105746a2204200029038005370000200441186a200c290300370000200441106a200f290300370000200441086a200d290300370000201b41016a211b20022003470d000b0b202b450d00201c102f0b200042003702ac0220004190bdc6003602a8020240201b450d00201b4105742104202921030340200041f8026a41186a200341186a290000370300200041f8026a41106a200341106a290000370300200041f8026a41086a200341086a290000370300200020032900003703f802200042003703b803200042003703b003200041003602c803200042083703c003200041d0026a200041a8026a200041f8026a200041b0036a109902024020002802e0022206450d0020002802e402450d002006102f0b200341206a2103200441606a22040d000b0b02402024412c6c2203450d00202a20036a2107200041d0046a41106a211341e7a2ca00ad4280808080800184212c202a210e03400240200e28022841246c2203450d00200e280220221220036a211d034020004188016a200e10930520004188016a41086a29030021102000290388012111200041d0046a41186a2206420037030020134200370300200041d0046a41086a22034200370300200042003703d004202c1001220429000021052003200441086a290000370300200020053703d0042004102f41ecb5c600ad4280808080d00184100122042900002105200041a0056a41086a220c200441086a290000370300200020053703a0052004102f201320002903a005370000201341086a200c290300370000200041f8026a41086a2003290300370300200041f8026a41106a2013290300370300200041f8026a41186a2006290300370300200020002903d0043703f802200041f0006a200041f8026a4120109c01200041e0006a2000290378200041f0006a41106a290300427f420010ee06200041d0006a2011201020002903604200200028027022031b220542012005420156200041e0006a41086a290300420020031b22054200522005501b22031b2005420020031b10ee06200041c0006a20002903502205428094ebdc038022104200201222083502202211420010ed06200041c0006a41086a290300200029034022012011200520104280ec94a37c7e7c7e22052005428094ebdc038022054280ec94a37c7e7c4280cab5ee01562005a76aad7c2205200154ad7c2110200841246a2112200041a8026a210320002802ac02210f02400240034002400240200328020022022f0106220d0d00410021060c010b200d4105742103200241086a2104417f21060340024020030d00200d21060c020b200641016a210620082004412010ea06220c450d03200341606a2103200441206a2104200c417f4a0d000b0b200f450d02200f417f6a210f200220064102746a41c8056a21030c000b0b200041d0026a41186a2208200e41186a290000370300200041d0026a41106a220f200e41106a290000370300200041d0026a41086a220d200e41086a2900003703002000200e2900003703d002200220064105746a220441f8026a210c024020044180036a22062802002203200441fc026a280200470d00200341016a22022003490d0a2003410174221e2002201e20024b1bad42307e2211422088a70d0a2011a722024100480d0a0240024020030d002002102d21030c010b200c280200200341306c2002103121030b2003450d08200c2003360200200c41046a200241306e360200200628020021030b200d2903002111200f29030021012008290300211720002903d0022114200c280200200341306c6a2203200537032020032014370300200341286a2010370300200341186a2017370300200341106a2001370300200341086a20113703002006200628020041016a360200200441e8026a2203427f2003290300221120057c220520052011542204200341086a2203290300220520107c2004ad7c221020055420102005511b22041b3703002003427f201020041b3703000b2012201d470d000b0b200e412c6a220e2007470d000b0b41082133200041f0046a41086a200041a8026a41086a280200360200200020002903a8023703f00402400240201b0d0041002134410021260c010b201b4105742204410575ad42307e2205422088a70d052005a722034100480d052003102d2233450d03202920046a2107200341306e2134200041d0046a41106a21134100212641e7a2ca00ad428080808080018421012033210d2029210e0340200e41086a2900002105200e41106a2900002110200e2900002111200041b0036a41186a2212200e41186a290000370300200041b0036a41106a221d2010370300200041b0036a41086a221e2005370300200020113703b003200e41206a210e200041f0046a210320002802f40421020240034002400240200328020022082f0106220f0d00410021060c010b200f4105742103200841086a2104417f21060340024020030d00200f21060c020b200641016a2106200041b0036a2004412010ea06220c450d03200341606a2103200441206a2104200c417f4a0d000b0b02402002450d002002417f6a2102200820064102746a41c8056a21030c010b0b419bbbc60041da0041f8bbc6001055000b200041d0026a41186a220c2012290300370300200041d0026a41106a2202201d290300370300200041d0026a41086a220f201e290300370300200020002903b0033703d002200820064105746a220341f0026a2903002110200341e8026a2903002111200041d0046a41186a2206420037030020134200370300200041d0046a41086a22034200370300200042003703d00420011001220429000021052003200441086a290000370300200020053703d0042004102f41ecb5c600ad4280808080d00184100122042900002105200041a0056a41086a2208200441086a290000370300200020053703a0052004102f201320002903a005370000201341086a2008290300370000200041f8026a41086a2003290300370300200041f8026a41106a2013290300370300200041f8026a41186a2006290300370300200020002903d0043703f802200041286a200041f8026a4120109c01200041186a2000290330200041286a41106a290300427f420010ee06200041086a20002903184200200028022822031b220542012005420156200041186a41086a290300420020031b22054200522005501b22031b2005420020031b2011201010ed06200d41186a200c290300370300200d41106a2002290300370300200d41086a200f290300370300200d20002903d002370300200d41286a200041086a41086a290300370300200d2000290308370320202641016a2126200d41306a210d200e2007470d000b0b02402028450d002029102f0b410021230240024002402026410d2026410d491b22350d0041082112410021180c010b203541306c2203102d2212450d04024020030d00203521180c010b2033203541306c6a21064100212320122103203321040340200441086a2903002105200441106a2903002110200441186a290300211120042903002101200341286a200441286a290300370300200341206a200441206a290300370300200341186a2011370300200341106a2010370300200341086a200537030020032001370300200341306a2103202341016a21232006200441306a2204470d000b200041b0046a41186a201241186a290000370300200041b0046a41106a201241106a290000370300200041b0046a41086a201241086a290000370300200020122900003703b004024020234115490d0020234101762236ad42307e2205422088a70d042005a72203417f4c0d044108213702402003450d002003102d2237450d06200341306e21360b201241506a2138201241f07e6a21394104211e4100213a410021214100211320232122034020222102410021224101210802402002417f6a2206450d000240024002400240024002402012200641306c6a200241306c220f20126a41a07f6a412010ea064100480d002002417e6a210c2039200f6a2103410021224100210403400240200c2004470d00200221080c080b200441016a2104200341306a2003412010ea062106200341506a21032006417f4a0d000b200441016a21082004417f7320026a21060c010b2039200f6a210302400340024020064101470d00410021060c020b2006417f6a2106200341306a2003412010ea062104200341506a210320044100480d000b0b20022006490d01200220234b0d03200220066b2208410176220c450d002038200f6a21032012200641306c6a21040340200041b0036a41286a220f200441286a220d290300370300200041b0036a41206a220e200441206a221d290300370300200041b0036a41186a2207200441186a221b290300370300200041b0036a41106a2229200441106a2228290300370300200041b0036a41086a2222200441086a2215290300370300200020042903003703b003200341086a22202903002105200341106a221f2903002110200341186a22162903002111200341206a22182903002101200341286a221a290300211720042003290300370300200d2017370300201d2001370300201b20113703002028201037030020152005370300201a200f2903003703002018200e29030037030020162007290300370300201f202929030037030020202022290300370300200320002903b003370300200341506a2103200441306a2104200c417f6a220c0d000b0b024020060d00200621220c050b0240200841094d0d00200621220c050b200220234b0d01200220066b210c2012200641306c6a210f034020022006417f6a2222490d040240200220226b22084102490d002012200641306c6a22032012202241306c6a2206412010ea06417f4a0d002006290300210520062003290300370300200041b0036a41286a2207200641286a2204290300370300200041b0036a41206a221b200641206a220d290300370300200041b0036a41186a2229200641186a220e290300370300200041b0036a41106a2228200641106a221d290300370300200041b0036a41086a2215200641086a22202903003703002020200341086a290300370300201d200341106a290300370300200e200341186a290300370300200d200341206a2903003703002004200341286a290300370300200020053703b0034101211d024020084103490d00200641e0006a200041b0036a412010ea06417f4a0d0041022104200f210302400340200341286a200341d8006a290300370300200341206a200341d0006a290300370300200341186a200341c8006a290300370300200341106a200341c0006a290300370300200341086a200341386a2903003703002003200341306a220d290300370300200c2004460d01200341e0006a210e2004211d200d2103200441016a2104200e200041b0036a412010ea06417f4a0d020c000b0b2004211d0b2006201d41306c6a220320002903b003370300200341286a2007290300370300200341206a201b290300370300200341186a2029290300370300200341106a2028290300370300200341086a20152903003703000b2022450d05200f41506a210f200c41016a210c202221062008410a4f0d050c000b0b20062002104b000b20022006417f6a2222490d010b20022023104a000b20222002104b000b02402013203a470d00203a41016a2203203a490d09203a41017422042003200420034b1b220341ffffffff01712003470d09200341037422034100480d0902400240203a0d002003102d211e0c010b201e203a41037420031031211e0b201e450d072003410376213a202121130b201e20134103746a2203200836020420032022360200202141016a221321210240024020134102490d00024003400240024002400240201e2013417f6a22214103746a2203280200450d002013410374201e6a220c41746a2802002206200328020422044d0d000240201341024b0d0020132121410221132022450d080c090b201e2013417d6a22074103746a2802042203200420066a4d0d010240201341034b0d0020132121410321132022450d080c090b200c41646a280200200320066a4d0d01201321210c060b20134103490d0120032802042104201e2013417d6a22074103746a28020421030b20032004490d010b2013417e6a21070b0240024002400240024002402013200741016a22154b2220450d00201320074b221f450d01201e20074103746a221b2802042216201b2802006a2203201e20154103746a22292802002228490d02200320234b0d032012202841306c6a220e2029280204221d41306c22046a210c200341306c2106200320286b2202201d6b2203201d4f0d042037200c200341306c220410e806220d20046a210802400240201d4101480d00200341014e0d010b200c2103200d21060c060b203820066a2104200c210303402004200341506a220c200841506a22022002200c412010ea06410048220f1b2206290300370300200441286a200641286a290300370300200441206a200641206a290300370300200441186a200641186a290300370300200441106a200641106a290300370300200441086a200641086a29030037030020082002200f1b21080240200e200c2003200f1b2203490d00200d21060c070b200441506a2104200d2106200d2008490d000c060b0b41c4c2ca0020152013103b000b41c4c2ca0020072013103b000b20282003104b000b20032023104a000b2037200e200410e806220d20046a210802400240201d4101480d002002201d4a0d010b200e2103200d21060c010b201220066a210f200d2106200e210303402003200c2006200c2006412010ea0641004822021b2204290300370300200341286a200441286a290300370300200341206a200441206a290300370300200341186a200441186a290300370300200341106a200441106a290300370300200341086a200441086a2903003703002006200641306a20021b2106200341306a2103200c41306a200c20021b220c200f4f0d01200820064b0d000b0b20032006200820066b220420044130706b10e8061a0240201f450d00201b2028360200201b41046a2016201d6a3602002020450d022029202941086a20132015417f736a41037410e9061a20212113202141014d0d030c010b0b419cc3ca0020072013103b000b41b8e3c300411d41f8b4ca001039000b20220d010b0b0240203a450d00201e102f0b4101211b41002129200041b0046a211e02402036450d002037102f0b203521180c020b41002129200041b0046a211e024020234102490d002023417f6a2104202341306c20126a41506a21084101210603400240024002400240202320042203417f6a2204490d00202320046b22024102490d032012200341306c6a22032012200441306c6a220c412010ea06417f4a0d03200c2903002105200c2003290300370300200041b0036a41286a2213200c41286a220f290300370300200041b0036a41206a221d200c41206a220d290300370300200041b0036a41186a2207200c41186a220e290300370300200041b0036a41106a221b200c41106a2228290300370300200041b0036a41086a2222200c41086a22212903003703002021200341086a2903003703002028200341106a290300370300200e200341186a290300370300200d200341206a290300370300200f200341286a290300370300200020053703b0034101210320024103490d02200c41e0006a200041b0036a412010ea06417f4a0d0241002102200821030340200341286a200341d8006a290300370300200341206a200341d0006a290300370300200341186a200341c8006a290300370300200341106a200341c0006a290300370300200341086a200341386a2903003703002003200341306a220d29030037030020062002220f460d02200f417f6a2102200341e0006a210e200d2103200e200041b0036a412010ea06417f4a0d020c000b0b20042023104b000b4102200f6b21030b200c200341306c6a220320002903b003370300200341286a2013290300370300200341206a201d290300370300200341186a2007290300370300200341106a201b290300370300200341086a20222903003703000b200841506a21082006417f6a210620040d000b0b4101211b203521180c010b41012129200041b0046a211e4100211b0b024002402012202341306c6a221620126b22030d004100211a410121150c010b200341306e221a41057422034100480d052003102d2215450d030b0240024020122016470d00410021060c010b2012202341306c6a210c410021062015210320122104034020032004290000370000200341186a200441186a290000370000200341106a200441106a290000370000200341086a200441086a290000370000200641016a2106200341206a2103200c200441306a2204470d000b0b024002402033202641306c6a2033203541306c6a6b22030d0041082108410021370c010b20034100480d052003102d2208450d03200341306e21370b024002402026410d4b0d00410121134100210f20082120410021260c010b203541306c202641306c22036b210c200320336a41506a21034100210f200821040340200341086a2903002105200341106a2903002110200341186a290300211120032903002101200441286a200341286a290300370300200441206a200341206a290300370300200441186a2011370300200441106a2010370300200441086a200537030020042001370300200441306a2104200341506a2103200f41016a210f200c41306a220c0d000b200f41ffffff3f71200f470d05200f41057422034100480d052003102d2213450d0320034105762126200821202008200f41306c6a21080b0240024020202008470d004100210c0c010b4100210c2013210320202104034020032004290000370000200341186a200441186a290000370000200341106a200441106a290000370000200341086a200441086a290000370000200c41016a210c200341206a21032008200441306a2204470d000b0b200041b0036a20152006202f2027109705200041c4036a280200220241ffffff3f712002470d012002410574221d417f4c0d01200041c0036a280200212720002802bc03210d20002802b403213a20002802b00321380240024002400240201d0d00200d20024105746a21084101210e200221070c010b201d102d220e450d05200d20024105746a2108201d410576220720024f0d00200741017422032002200320024b1b220341ffffff3f712003470d07200341057422034100480d070240024020070d002003102d210e0c010b200e200741057420031031210e0b200e450d05200341057621070c010b20020d00410021030c010b200e2103200d2104034020032004290000370000200341186a200441186a290000370000200341106a200441106a290000370000200341086a200441086a290000370000200341206a21032008200441206a2204470d000b200d20024105746a200d6b41606a41057641016a21030b200e20032015200610980502402007450d00200e102f0b200041a8026a41186a2203201e41186a290000370300200041a8026a41106a2204201e41106a290000370300200041a8026a41086a2206201e41086a2900003703002000201e2900003703a80202400240201b0d00200041d0046a41186a4200370300200041d0046a41106a22064200370300200041d0046a41086a22034200370300200042003703d00441f2cbc700ad4280808080b002841001220429000021052003200441086a290000370300200020053703d0042004102f41fbd4c700ad4280808080d00084100122042900002105200041a0056a41086a220e200441086a290000370300200020053703a0052004102f200620002903a0052205370300200041d0026a41086a2003290300370300200041d0026a41106a2005370300200041d0026a41186a200e290300370300200020002903d0043703d002200041d0026aad428080808080048410050c010b200041b0036a41186a2003290300370300200041b0036a41106a2004290300370300200041b0036a41086a2006290300370300200020002903a8023703b003200041f8026a41186a4200370300200041f8026a41106a22064200370300200041f8026a41086a22034200370300200042003703f80241f2cbc700ad4280808080b002841001220429000021052003200441086a290000370300200020053703f8022004102f41fbd4c700ad4280808080d00084100122042900002105200041d0026a41086a220e200441086a290000370300200020053703d0022004102f200620002903d002220537030020004180056a41086a200329030037030020004180056a41106a200537030020004180056a41186a200e290300370300200020002903f802370380054120102d2203450d03200320002903b003370000200341186a200041b0036a41186a290300370000200341106a200041b0036a41106a290300370000200341086a200041b0036a41086a29030037000020004180056aad42808080808004842003ad428080808080048410042003102f0b0240024002400240201d0d004101210e200221210c010b201d102d220e450d05201d410576222120024f0d00202141017422032002200320024b1b220341ffffff3f712003470d07200341057422034100480d070240024020210d002003102d210e0c010b200e202141057420031031210e0b200e450d05200341057621210c010b20020d00410021030c010b2008200d6b2108410021030340200e20036a2204200d20036a2206290000370000200441186a200641186a290000370000200441106a200641106a290000370000200441086a200641086a2900003700002008200341206a2203470d000b200d20024105746a200d6b41606a41057641016a21030b200041b0036a2013200c20312019109705200041c4036a2802002106200041c0036a280200210820002802bc032104024020002802b403450d0020002802b003102f0b02400240202120036b200641057422064105752202490d00200320026a211f0c010b200320026a221f2003490d0520214101742202201f2002201f4b1b220241ffffff3f712002470d05200241057422024100480d050240024020210d002002102d210e0c010b200e202141057420021031210e0b200e450d03200241057621210b200e20034105746a2004200610e8061a02402008450d002004102f0b0240200b450d002009200b4105746a211d200041b9036a211e02402029450d00200c410574211b200041e8036a21292009210c0340200c41086a2900002105200c41106a2900002110200c2900002111200041d0026a41186a2208200c41186a290000370300200041d0026a41106a22022010370300200041d0026a41086a22072005370300200020113703d002200c41206a210c201b2104201321030240024003402004450d01200041d0026a2003460d02200441606a21042003200041d0026a412010ea062106200341206a210320060d000c020b0b200042003703b00220004280809aa6eaafe3013703a8022000200041d0026a36028005200041f8026a200041d0026a200041a8026a20004180056a10bd01200041f8026a41206a29030021052000290390032110024020002903f8024201520d0020002903800321112029200041f8026a41106a290300370300201e20002903d002370000201e41086a2007290300370000201e41106a2002290300370000201e41186a2008290300370000200020113703e003200041003a00b803200041033a00b00341c8e1ca004100200041b0036a108c010b20102005109a010b200c201d470d000c020b0b200c410574212820234101462122200041e8036a2119200921020340200241086a2900002105200241106a290000211020022900002111200041d0026a41186a2207200241186a290000370300200041d0026a41106a221b2010370300200041d0026a41086a22292005370300200020113703d00241002104024020220d0041002104202321060340200041b0036a41186a20122006410176220c20046a220841306c6a220341186a290000370300200041b0036a41106a200341106a290000370300200041b0036a41086a200341086a290000370300200020032900003703b00320082004200041b0036a200041d0026a412010ea064101481b21042006200c6b220641014b0d000b0b200241206a2102200041b0036a41186a2012200441306c6a220341186a290000370300200041b0036a41106a200341106a290000370300200041b0036a41086a200341086a290000370300200020032900003703b00320282104201321030240200041b0036a200041d0026a412010ea06450d00024003402004450d01200041d0026a2003460d02200441606a21042003200041d0026a412010ea062106200341206a210320060d000c020b0b200042003703b00220004280809aa6eaafe3013703a8022000200041d0026a36028005200041f8026a200041d0026a200041a8026a20004180056a10bd01200041f8026a41206a29030021052000290390032110024020002903f8024201520d0020002903800321112019200041f8026a41106a290300370300201e20002903d002370000201e41086a2029290300370000201e41106a201b290300370000201e41186a2007290300370000200020113703e003200041003a00b803200041033a00b00341c8e1ca004100200041b0036a108c010b20102005109a010b2002201d470d000b0b0240200a450d002009102f0b0240201f450d00201f4105742104200041b9036a2106200041e8036a211d200e21030340200341086a2900002105200341106a290000211020032900002111200041d0026a41186a220c200341186a290000370300200041d0026a41106a22082010370300200041d0026a41086a22022005370300200020113703d002200042003703b00220004280809aa6eaafe3013703a8022000200041d0026a36028005200041f8026a200041d0026a200041a8026a20004180056a10bd01200041f8026a41206a29030021052000290390032110024020002903f8024201520d002000290380032111201d200041f8026a41106a290300370300200620002903d002370000200641086a2002290300370000200641106a2008290300370000200641186a200c290300370000200020113703e003200041003a00b803200041033a00b00341c8e1ca004100200041b0036a108c010b200341206a210320102005109a01200441606a22040d000b0b02402021450d00200e102f0b200041b0036a41186a22064200370300200041b0036a41106a220c4200370300200041b0036a41086a22044200370300200042003703b00341bd98ca00ad42808080808002842205100122082900002110200041d0026a41086a2203200841086a290000370300200020103703d0022008102f20042003290300370300200020002903d0023703b00341ebdec700ad4280808080f000841001220829000021102003200841086a290000370300200020103703d0022008102f202e20002903d002370000202e41086a22022003290300370000200041f8026a41086a220e2004290300370300200041f8026a41106a221d200c290300370300200041f8026a41186a221e2006290300370300200020002903b0033703f802200041203602b4032000200041f8026a3602b00320122023200041b0036a10ab0120064200370300200c420037030020044200370300200042003703b00320051001220829000021052003200841086a290000370300200020053703d0022008102f20042003290300370300200020002903d0023703b003419691c700ad42808080809001841001220829000021052003200841086a290000370300200020053703d0022008102f202e20002903d00237000020022003290300370000200e2004290300370300201d200c290300370300201e2006290300370300200020002903b0033703f802200041203602b4032000200041f8026a3602b0032020200f200041b0036a10ab012023ad42307e2205422088a70d012005a72203417f4c0d010240024020030d00410821022023210e0c010b2003102d2202450d03200341306e220e20234f0d00200e41017422032023200320234b1bad42307e2205422088a70d052005a722034100480d0502400240200e0d002003102d21020c010b2002200e41306c2003103121020b2002450d03200341306e210e0b0240024020162012470d00410021060c010b2012202341306c6a210c4100210620022103201221040340200441086a2903002105200441106a2903002110200441186a290300211120042903002101200341286a200441286a290300370300200341206a200441206a290300370300200341186a2011370300200341106a2010370300200341086a200537030020032001370300200341306a2103200641016a2106200c200441306a2204470d000b0b2006ad42307e2205422088a70d012005a72203417f4c0d010240024020030d002002200641306c6a21084108210f0c010b2003102d220f450d032002200641306c6a21080240200341306e22032006490d00200321060c010b200341017422042006200420064b1bad42307e2205422088a70d052005a722044100480d050240024020030d002004102d210f0c010b200f200341306c20041031210f0b200f450d03200441306e21060b4100210c024020082002460d004100210c200f2103200221040340200441086a2903002105200441106a2903002110200441186a290300211120042903002101200341286a200441286a290300370300200341206a200441206a290300370300200341186a2011370300200341106a2010370300200341086a200537030020032001370300200341306a2103200c41016a210c2008200441306a2204470d000b0b200041c0036a200c360200200041bc036a2006360200200041b8036a200f360200200041003a00b403200041093a00b003200020002f00f8023b00b5032000200041fa026a2d00003a00b70341c8e1ca004100200041b0036a108c010240200e450d002002102f0b02402027450d00200d102f0b0240203a450d002038102f0b02402026450d002013102f0b02402037450d002020102f0b0240201a450d002015102f0b02402018450d002012102f0b02402034450d002033102f0b20002802f804210820002802f00421030240024020002802f40422060d00200321040c010b2006210c20032104034020042802c8052104200c417f6a220c0d000b0340200320032f01064102746a41c8056a28020021032006417f6a22060d000b0b200041cc036a20032f0106360200200041c8036a4100360200200041c4036a2003360200200020083602d003200041003602c003200042003703b803200020043602b403200041003602b003200041b0036a10a20202402032450d002031102f0b02402030450d00202f102f0b02402024450d002024412c6c2104202a41206a210303400240200341046a280200450d002003280200102f0b2003412c6a2103200441546a22040d000b0b41002112200041f8026a210c2025450d00202a102f0b200041b0036a41186a22084200370300200041b0036a41106a22064200370300200041b0036a41086a22044200370300200042003703b00341bd98ca00ad42808080808002842205100122022900002110200041d0026a41086a2203200241086a290000370300200020103703d0022002102f20042003290300370300200020002903d0023703b003418c91c700ad4280808080a001841001220229000021102003200241086a290000370300200020103703d0022002102f200620002903d0022210370300200041f8026a41086a22022004290300370300200041f8026a41106a220f2010370300200041f8026a41186a220d2003290300370300200020002903b0033703f802200cad42808080808004841005200842003703002006420037030020044200370300200042003703b00320051001220e29000021102003200e41086a290000370300200020103703d002200e102f20042003290300370300200020002903d0023703b00341cd98ca00ad4280808080e0018422101001220e29000021112003200e41086a290000370300200020113703d002200e102f200620002903d002221137030020022004290300370300200f2011370300200d2003290300370300200020002903b0033703f8022000200c41201095012000280200210e20002802042113200842003703002006420037030020044200370300200042003703b00320051001220c29000021052003200c41086a290000370300200020053703d002200c102f20042003290300370300200020002903d0023703b00320101001220c29000021052003200c41086a290000370300200020053703d002200c102f200620002903d002220537030020022004290300370300200f2005370300200d2003290300370300200020002903b0033703f8022000201341016a4101200e1b3602b003200041f8026aad4280808080800484200041b0036aad4280808080c00084100402400240201c0d00200a450d042012410173450d010c040b2012450d030240202b450d00201c102f0b02402024450d002024412c6c2104202a41206a210303400240200341046a280200450d002003280200102f0b2003412c6a2103200441546a22040d000b0b02402025450d00202a102f0b200a450d030b2009102f0c020b103d000b1036000b200041b0056a24000f0b1038000bae0504067f017e067f027e230041e0006b22022400200241c00036020c20022001360208200241106a2001ad4280808080800884100210730240024002400240024020022802102203450d00200228021421042002200241186a280200360224200220033602202002200241206a10e6010240024020022802000d00200228020422052002280224220641186e2201200120054b1b2207ad42187e2208422088a70d042008a72201417f4c0d040240024020010d00410821090c010b2001102d2209450d06200141186e21070b024002402005450d004100210a4100210b4100210c034020064104490d0220022006417c6a220636022420022002280220220141046a36022020064110490d02200c41016a210d2001280000210e2002200641706a22063602242002200141146a3602202001410c6a29000021082001290004210f0240200c2007470d00200a200d200a200d4b1bad42187e2210422088a70d0a2010a722014100480d0a02400240200c0d002001102d21090c010b2009200b2001103121090b2009450d09200141186e21070b2009200b6a2201200e360200200141106a2008370300200141086a200f370300200a41026a210a200b41186a210b200d210c2005200d470d000b0b2009450d012000200736020420002009360200200041086a20053602000c020b2007450d002009102f0b20024100360230200242013703282002410b36023c2002200241086a3602382002200241286a360244200241dc006a41013602002002420137024c200241b885c7003602482002200241386a360258200241c4006a41d8dbc100200241c8006a103c1a200235023042208620023502288410080240200228022c450d002002280228102f0b200041003602000b2004450d012003102f0c010b200041003602000b200241e0006a24000f0b103d000b1036000b1038000bed0302067f027e230041106b22032400024002400240200141186c4104722204417f4c0d002004102d2205450d0120034100360208200320043602042003200536020020012003106902400240200141186c22010d002003280208210120032802042105200328020021040c010b200020016a2106200328020421052003280208210103402000280200210702400240200520016b4104490d00200328020021040c010b200141046a22042001490d05200541017422082004200820044b1b22084100480d050240024020050d002008102d21040c010b200328020020052008103121040b2004450d042003200836020420032004360200200821050b2003200141046a2208360208200420016a2007360000200041106a2903002109200041086a290300210a02400240200520086b4110490d00200141146a21010c010b200841106a22012008490d05200541017422072001200720014b1b22074100480d050240024020050d002007102d21040c010b200420052007103121040b2004450d042003200736020420032004360200200721050b200420086a220820093700082008200a37000020032001360208200041186a22002006470d000b0b20022902002001ad4220862004ad84100402402005450d002004102f0b200341106a24000f0b103d000b1036000b1038000b130020004103360204200041ccdcc4003602000b3400200041a4e3c40036020420004100360200200041146a4101360200200041106a41a8e3c400360200200041086a42043702000b910101057f230041206b22022400200241186a22034200370300200241106a22044200370300200241086a220542003703002002420037030002404120102d22060d001036000b20062002290300370000200042a0808080800437020420002006360200200641186a2003290300370000200641106a2004290300370000200641086a2005290300370000200241206a24000b13002000410c360204200041c0e4c4003602000b3400200041c6b5c40036020420004100360200200041146a4110360200200041106a41bcc0c500360200200041086a42073702000b130020004106360204200041f4d5c5003602000b2e01017f02404104102d22020d001036000b20004284808080c0003702042000200236020020024180ee053600000b3b01017f02404110102d22020d001036000b20024200370008200242808094f6c2d7e8d800370000200042908080808002370204200020023602000b2c01017f02404104102d22020d001036000b20004284808080c000370204200020023602002002410a3600000b3901017f02404110102d22020d001036000b200242003700082002428080d287e2bc2d370000200042908080808002370204200020023602000bcc0502077f067e230041f0006b2102024002400240024020012802042203450d00200128020022042d0000210520012003417f6a22063602042001200441016a360200200541014b0d0320050e020102010b200041023a00000f0b024020064110490d00200041003a000020002002280028360001200041086a2004290001370300200041186a2002290348370300200041106a200441096a29000037030020012003416f6a3602042001200441116a360200200041046a2002412b6a280000360000200041206a200241c8006a41086a290300370300200041286a200241c8006a41106a290300370300200041306a200241c8006a41186a2903003703000f0b200041023a00000f0b41002105200241003a00682003417f6a2107417e210602400240034020072005460d01200241c8006a20056a200420056a220841016a2d00003a00002001200320066a3602042001200841026a3602002002200541016a22083a00682006417f6a21062008210520084120470d000b200241286a41186a2205200241c8006a41186a290300370300200241286a41106a2206200241c8006a41106a290300370300200241286a41086a2207200241c8006a41086a290300370300200220022903483703282008417f7320036a4110490d01200241086a41086a20072903002209370300200241086a41106a2006290300220a370300200241086a41186a2005290300220b370300200420086a220541016a290000210c200541096a290000210d2001200320086b416f6a3602042001200541116a36020020022002290328220e370308200041013a00002000200e370001200041096a2009370000200041116a200a370000200041196a200b370000200041306a200d370300200041286a200c370300200041216a2002280001360000200041246a200241046a2800003600000f0b200541ff0171450d00200241003a00680b200041023a00000f0b200041023a00000b130020004108360204200041c4dec5003602000b340020004180a3ca0036020420004100360200200041146a4105360200200041106a4190ffc500360200200041086a42083702000b130020004108360204200041c088c6003602000b2b01017f02404101102d22020d001036000b200042818080801037020420002002360200200241143a00000b2e01017f02404104102d22020d001036000b20004284808080c0003702042000200236020020024180e1013600000b2e01017f02404104102d22020d001036000b20004284808080c00037020420002002360200200241a0c21e3600000b2e01017f02404104102d22020d001036000b20004284808080c00037020420002002360200200241d086033600000bd30101017f230041106b22022400024002400240024020002d00000e03010200010b2002200128021841c7afca00410b2001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c020b2002200128021841d2afca00410c2001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c010b2002200128021841deafca00410d2001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040b200241106a240020000ba3cb01040a7f027e0d7f027e2300418081046b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402001280204220320012802082204460d00200441016a22052004490d0720032005490d06200128020020046a2d00002104200120053602082004410c4b0d0220040e0d010319181716151409100f0e08010b200241013a0030200241ec006a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241306a360218200241e880046a200241d8006a103a20022802e88004210420022802ec8004210120004101360200200041003a00042001450d312004102f0c310b200241d8006a2001109d0641012106200228025c210720022802584101460d08200241d8006a41004180800110e7061a41002108410021052007450d2341012106410021084100210341002109024003402001280204220a200128020822056b200720096b220441808001200441808001491b2204490d01200520046a220b2005490d05200a200b490d04200241d8006a200128020020056a200410e8061a2001200b36020802400240200820036b2004490d00200420036a21050c010b200320046a22052003490d272008410174220b2005200b20054b1b220b4100480d270240024020080d00200b102d21060c010b20062008200b103121060b2006450d30200b21080b200620036a200241d8006a200410e8061a200521032007200420096a22094b0d000c250b0b200241013a00d88004200241fc80046a4101360200200242013702ec8004200241b4afca003602e880042002412836021c2002200241186a3602f880042002200241d880046a360218200241306a200241e880046a103a2002290330210c2002280238210441052107024020080d000c2d0b2006102f0c2c0b200041123a000420004101360200200041056a20043a00000c2f0b200241d8006a200110a306024020022802584101470d00200228025c22044108762105200241d8006a41086a290300220c422088210d200241e8006a28020021030c210b200241ec006a280200210a200241e8006a2802002101200241e4006a2802002103200241e0006a280200210b200228025c2108410021044100210502400240024002400240034002402004411f4d0d00410f21040c030b20032001460d012001417f460d052003200141016a2207490d04200820016a2d0000220941ff00712004411f71742005722105200441076a2104200721012009418001710d000b024020044120490d00410d21042009410f4b0d020b200241003602382002420437033020050d02410421010c230b200241013a0030200241ec006a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241306a360218200241206a200241d8006a103a410521040b200241e880046a41086a200241206a41086a280200220336020020022002290320220c3703e88004200c422088a72107200ca721090c220b410120036b21064100210e0240034002400240024002400240024002400240024020032007460d00200741016a22012007490d0120032001490d020240200820076a2d0000220f41e000460d00411821100c2b0b200e41016a210e200741026a21014100210441002109024002400240034002402004411f4d0d00410f21104100210f0c2e0b200620016a4102460d012001450d0720032001490d0b200820016a417f6a2d0000220741ff00712004411f71742009722109200141016a2101200441076a21042007418001710d000b024020044120490d002007410f4d0d00410d21104100210f0c2d0b2001417f6a2104410021114101211220090d01410021130c020b200241013a00482002410136026c2002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241c8006a360218200241e880046a200241d8006a103a20022802e88004210920022802ec8004210720022802f080042101410521104100210f0c2b0b410021144100210741002113034020032004460d28200120076a220f450d062003200f490d070240200820046a2c0000220f41004e0d00411921100c2b0b41062110200f41c00071450d29200f41807f72220f41ff017141fc01490d29200741016a2110024020072013470d0020142010201420104b1b22134100480d320240024020070d002013102d21120c010b201220072013103121120b2012450d3b0b200441016a2104201220076a200f417f733a0000201441026a21142010210720092010470d000b0b20124110764110742215201241087641ff0171410874221672201241ff017122127221144100210103404100210f02402011411f4d0d00410f21100c270b0240024020032004460d002004417f460d092003200441016a22074f0d01200441016a2003104a000b200241013a00d880042002410136026c2002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241d880046a360218200241e880046a200241d8006a103a20022802e88004210920022802ec8004210720022d00f08004210120022d00f18004210320022f01f280042104410521100c270b200820046a2d0000221041ff00712011411f71742001722101201141076a2111200721042010418001710d000b20114120490d082010410f4d0d08410d21100c250b200241013a00d880042002410136026c2002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241d880046a360218200241e880046a200241d8006a103a20022802e88004210920022802ec8004210720022d00f08004210120022d00f18004210320022f01f280042104410521100c290b417f2001104b000b20012003104a000b417f2001104b000b417f200f104b000b200f2003104a000b417f200441016a104b000b20012003104a000b0240200141014d0d004104211041be8eca002109412421070c1c0b024002400240024020010e020100010b0240024020032007460d00200741016a22012007490d0420032001490d06200820076a2c0000220f41004e0d01411921100c210b200241013a00d880042002410136026c2002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241d880046a360218200241e880046a200241d8006a103a20022802e88004210920022802ec8004210720022d00f08004210120022d00f18004210320022f01f280042104410521100c1f0b41062110200f41c00071450d1d200f41807f72220f41ff017141fb014d0d1d200f417f732111200121070c010b410421110b0240200228023822042002280234470d00200441016a22012004490d282004410174220f2001200f20014b1b220141ffffffff00712001470d28200141047422014100480d280240024020040d002001102d210f0c010b2002280230200441047420011031210f0b200f450d312002200f360230200220014104763602340b2002280230220120044104746a220f20174180807c71201141ff01714108747241e00072221736020c200f2009360208200f2013360204200f20162012722015723602002002200441016a360238200e2005460d230c010b0b417f200741016a104b000b200741016a2003104a000b200141016a2003104a000b417f200141016a104b000b200b200a104a000b2005200b104b000b20052003104a000b417f2005104b000b200241d8006a200110a306024020022802584101470d00200041013602002000200241d8006a41047222012902003702042000410c6a200141086a2902003702000c2a0b200241ec006a2802002106200241e8006a2802002104200241e4006a2802002105200241e0006a280200210b200228025c2108410021034100210102400240034002402003411f4d0d00410f21040c070b20052004460d052004417f460d012005200441016a2209490d02200820046a2d0000220741ff00712003411f71742001722101200341076a2103200921042007418001710d000b20034120490d06410d21042007410f4d0d060c050b417f200441016a104b000b200441016a2005104a000b200241d8006a200110a306024020022802584101470d00200041013602002000200241d8006a41047222012902003702042000410c6a200141086a2902003702000c290b200241ec006a2802002106200241e8006a2802002104200241e4006a2802002105200241e0006a280200210b200228025c2108410021034100210102400240034002402003411f4d0d00410f21040c0c0b20052004460d0a2004417f460d012005200441016a2209490d02200820046a2d0000220741ff00712003411f71742001722101200341076a2103200921042007418001710d000b20034120490d0b410d21042007410f4d0d0b0c0a0b417f200441016a104b000b200441016a2005104a000b20074108762101200241e8006a2802002104200241d8006a41086a290300210c0c230b200241013a0030200241ec006a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241306a360218200241e880046a200241d8006a103a410521040b2000200436020420004101360200200041086a20022903e88004370200200041106a200241e880046a41086a280200360200200b450d252008102f0c250b200620094621040240200b450d002008102f0b02402004450d00410b21030c200b20024103410220041b3a00d88004200241ec006a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241d880046a360218200241306a200241d8006a103a200241f380046a200241386a280200360000200220022903303700eb8004200041053a0004200020022900e880043700052000410c6a200241ef80046a290000370000200041013602000c240b200241d8006a200110a3060240024020022802584101470d00200228025c22014108762109200241d8006a41086a290300220c422088210d200241e8006a28020021080c010b200241c0006a200241ec006a280200360200200241386a200241e4006a2902003703002002200229025c370330410021014100210502400240024002400240024002400240034002402001411f4d0d00410f21060c030b20022802382207200228023c2204460d01200441016a22032004490d0620072003490d05200228023020046a2d000021042002200336023c200441ff00712001411f71742005722105200141076a21012004418001710d000b024020014120490d00410d21062004410f4b0d020b200241003602502002420437034820050d02410421010c030b200241013a00d88004200241ec006a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241d880046a360218200241206a200241d8006a103a410521060b200241e880046a41086a200241206a41086a280200220836020020022002290320220c3703e88004200c422088a7210a200ca7210f410021090c040b410021060340200641016a21064100210141002107024002400240024002400240024002400240024002400240034002402001411f4d0d00410f21060c030b20022802382209200228023c2204460d01200441016a22032004490d0420092003490d06200228023020046a2d000021042002200336023c200441ff00712001411f71742007722107200141076a21012004418001710d000b20014120490d022004410f4d0d02410d21060c010b200241013a00202002410136026c2002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241206a360218200241e880046a200241d8006a103a200241d880046a41086a200241e880046a41086a280200360200200220022903e88004220c3703d88004200ca7210f410521060b20022802e08004210820022802dc8004210a410021090c080b200241d8006a200241306a109506024020022802584101470d00200228025c22064108762109200228026821082002280264210a2002280260210f0c080b200228026421142002280260210e200228025c21124100210441002108034002402004411f4d0d00410f21060c080b20022802382209200228023c2203460d05200341016a22012003490d0220092001490d042002280230220b20036a2d000021032002200136023c200341ff00712004411f71742008722108200441076a21042003418001710d000b20044120490d052003410f4d0d05410d21060c060b417f2003104b000b417f2001104b000b20032009104a000b20012009104a000b200241013a00d880042002410136026c2002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241d880046a360218200241e880046a200241d8006a103a20022802e88004210f20022802ec8004210a20022802f080042108410521060c010b41002111200241d8006a41004180800410e7061a024020080d00410121104100210f0c030b4100211141012110410021034100210a0240024002400340200920016b2008200a6b220441808004200441808004491b2204490d01200120046a220f2001490d022009200f490d03200241d8006a200b20016a200410e8061a2002200f36023c02400240201120036b2004490d00200420036a210f0c010b200320046a220f2003490d2620114101742201200f2001200f4b1b22014100480d260240024020110d002001102d21100c010b201020112001103121100b2010450d2f200121110b201020036a200241d8006a200410e8061a20082004200a6a220a4d0d06200228023c2101200228023821092002280230210b200f21030c000b0b200241013a0020200241013602fc8004200242013702ec8004200241b4afca003602e880042002412836021c2002200241186a3602f880042002200241206a360218200241d880046a200241e880046a103a20022802d88004210f20022802dc8004210a20022802e080042108410521062011450d022010102f0c020b2001200f104b000b200f2009104a000b02402014450d0020144104742104201221010340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102f200528020021030b2003102f0b200141106a2101200441706a22040d000b0b41002109200e450d002012102f0b20022802482111024020022802502201450d0020112001411c6c6a210b201121070340024020072802042201450d0002402007410c6a2802002204450d00200441047421040340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102f200528020021030b2003102f0b200141106a2101200441706a22040d000b0b200741086a280200450d002007280204102f0b2007411c6a21010240200741146a280200450d002007280210102f0b200121072001200b470d000b0b200228024c450d052011102f0c050b024020022802502203200228024c470d00200341016a22012003490d1f200341017422042001200420014b1bad421c7e220c422088a70d1f200ca722014100480d1f0240024020030d002001102d21040c010b20022802482003411c6c2001103121040b2004450d282002200436024820022001411c6e36024c0b200228024822012003411c6c6a2204200741087622093b00012004201036021020042012360204200420073a0000200441036a20094110763a0000200441186a200f360200200441146a20113602002004410c6a2014360200200441086a200e3602002002200341016a36025020062005470d000b0b200228023c2002280240462104200229024c220c422088210d02402002280234450d002002280230102f0b20014108762105200da72103200ca7210b2004450d032005410874200141ff01717221012003ad422086200bad84210c410d21030c230b20032007104a000b417f2003104b000b2009410874200641ff0171722101200aad220d422086200fad84210c2002280234450d012002280230102f0c010b2005410874200141ff017172210620024103410220041b3a00d88004200241d8006a41146a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241d880046a360218200241e880046a200241d8006a103a20022903e88004210c20022802f08004210802402003450d0020062003411c6c6a2109200621070340024020072802042201450d0002402007410c6a2802002204450d00200441047421040340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102f200528020021030b2003102f0b200141106a2101200441706a22040d000b0b200741086a280200450d002007280204102f0b2007411c6a21010240200741146a280200450d002007280210102f0b2001210720012009470d000b0b200c422088210d4105210141002109200b450d002006102f0b20004101360200200041106a2008360200200041086a200d422086200c42ffffffff0f838437020020002009410874200141ff0171723602040c230b200241d8006a200110a3060240024020022802584101470d00200228025c220b4108762104200241d8006a41086a290300220c422088210d200241e8006a28020021060c010b200241ec006a2802002111200241e8006a2802002101200241e4006a2802002105200241e0006a280200210a200228025c2108410021044100210702400240024002400240024002400240024002400240024002400240034002402004411f4d0d00410f210b0c030b20052001460d012001417f460d062005200141016a2203490d05200820016a2d0000220941ff00712004411f71742007722107200441076a2104200321012009418001710d000b024020044120490d00410d210b2009410f4b0d020b200241003602502002420437034820070d02410421010c030b200241013a00d88004200241ec006a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241d880046a360218200241e880046a200241d8006a103a4105210b0b200241306a41086a200241e880046a41086a2802002206360200200220022903e88004220c370330200c422088a7210f200ca721110c0a0b200241e1006a21134100210e0340200e41016a210e4100210141002109024002400240024002400240024002400240024002400240024002400240024002400240034002402001411f4d0d00410f210b0c030b20052003460d012003417f460d052005200341016a2204490d0c200820036a2d0000220b41ff00712001411f71742009722109200141076a210120042103200b418001710d000b024020014120490d00200b410f4d0d00410d210b0c020b4100210f200241d8006a41004180800110e7061a20090d024101211020042103410021124100210b0c030b200241013a00e880042002410136026c2002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241e880046a360218200241206a200241d8006a103a4105210b200228022021110b200228022821062002280224210f0c190b410021124101211041002106410021140340200520046b200920146b220141808001200141808001491b2201490d18200420016a22032004490d0320052003490d04200241d8006a200820046a200110e8061a02400240201220066b2001490d00200120066a210b0c010b200620016a220b2006490d3420124101742204200b2004200b4b1b22044100480d340240024020120d002004102d21100c010b201020122004103121100b2010450d3d200421120b201020066a200241d8006a200110e8061a20032104200b21062009200120146a22144b0d000b0b2002200b3602402002410036023c2002200b3602382002201236023420022010360230410021014100210602400240024002400240034002402001411f4d0d00410f210b0c030b200b200f460d01200f417f460d09200b200f41016a2209490d0e2010200f6a2d000021042002200936023c200441ff00712001411f71742006722106200141076a21012009210f2004418001710d000b024020014120490d002004410f4d0d00410d210b0c020b4100210f200241003602e08004200242043703d8800420060d024104211841002119410021150c030b200241013a00202002410136026c2002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241206a360218200241e880046a200241d8006a103a20022802e88004211120022802ec8004210f20022802f0800421064105210b0b200220063602e080042002200f3602dc8004200220113602d880040c180b4100211941042118410021150340201921162015221a41016a211541002101410021100240024002400240034002402001411f4d0d00410f21040c030b20022802382214200228023c2204460d01200441016a22092004490d0c20142009490d112002280230221220046a2d0000210b2002200936023c200b41ff00712001411f71742010722110200141076a2101200b418001710d000b024020014120490d00200b410f4d0d00410d21040c020b20142009460d06200441026a21042009417f460d0c20142004490d0d201220096a2c000021012002200436023c0240200141004e0d00411921040c130b41062104200141c00071450d11200141807f72220141ff017141fb014d0d11201a2016460d0220162119201a21160c030b200241013a00e880042002410136026c2002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241e880046a360218200241206a200241d8006a103a41052104200228022021110b200228022821062002280224210f410021010c100b201641016a22042016490d35201641017422092004200920044b1b220441ffffffff01712004470d35200441037422044100480d350240024020160d002004102d21180c010b201820164103742004103121180b2018450d3e200220183602d88004200441037621190b201820164103746a2204201741807e712001417f7341ff01717222173a00042004201036020020152006470d000b200220193602dc8004200220153602e080040b201820154103746a210b201821010340200b2001460d0f200f20012802006a2204200f492109200141086a21012004210f20090d0e0c000b0b200241013a00202002410136026c2002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241206a360218200241e880046a200241d8006a103a20022802e88004211120022802ec8004210f20022802f080042106410521040c0b0b417f200341016a104b000b20042003104b000b20032005104a000b417f200f41016a104b000b417f2009104b000b417f2004104b000b20042014104a000b200341016a2005104a000b200f41016a200b104a000b20092014104a000b0b200220163602dc80042002201a3602e08004200141ff0171410874200472210b2016450d090c080b20022802f08004210620022802ec8004210f411c210b0c060b4101210b4100210441082110410021090340200241d8006a200241306a109606024020022802584101470d00200228026821062002280264210f20022802602111200228025c210b0c060b200241e880046a41026a2201201341026a2d00003a0000200220132f00003b01e88004200228026421142002290368210c0240024020022d006022064106470d00200b417f6a210b0c010b2006417e6a41034f0d00200b41016a220f200b4f2112200f210b20120d004115210f418e88ca0021114104210b024020064109460d000c070b0240201428020441ffffffff0371450d002014280200102f0b2014102f0c060b200241d8006a41026a220f20012d00003a0000200220022f01e880043b01580240024020092004460d00200421120c010b200441016a22012004490d25200441017422092001200920014b1b220141ffffffff00712001470d25200141047422014100480d250240024020040d002001102d21100c010b201020044104742001103121100b2010450d2e200421092001410476221221040b201020094104746a220120063a00002001200c37030820012014360204200120022f01583b0001200141036a200f2d00003a0000200941016a2109200b0d000b20022802402101200228023c210402402002280234450d002002280230102f0b024002400240024020042001470d002002280250220b200228024c470d03200b41016a2201200b490d27200b41017422042001200420014b1bad42187e220c422088a70d27200ca722014100480d27200b0d012001102d21040c020b20024103410220042001461b3a00d880042002410136026c2002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241d880046a360218200241e880046a200241d8006a103a20022802e88004211120022802ec8004210f20022802f08004210602402009450d0020094104742104201021010340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102f200528020021030b2003102f0b200141106a2101200441706a22040d000b0b02402012450d002010102f0b4105210b2019450d0c2018102f0c0c0b2002280248200b41186c2001103121040b2004450d2d200220043602482002200141186e36024c0b20022802482201200b41186c6a2204201036020c200420153602082004201936020420042018360200200441146a2009360200200441106a20123602002002200b41016a360250200e2007470d000b0b20032011462104200229024c220c422088210d0240200a450d002008102f0b200da72103200ca7210a2004450d092003ad422086200aad84210c410c21030c280b200141016a2005104a000b417f200141016a104b000b02402009450d0020094104742103201021010340024020012d00004109470d000240200141046a2207280200220528020441ffffffff0371450d002005280200102f200728020021050b2005102f0b200141106a2101200341706a22030d000b0b2004450d002010102f20190d010c020b2019450d010b2018102f0b2002280234450d012002280230102f0c010b200241013a0020200241013602fc8004200242013702ec8004200241b4afca003602e880042002412836021c2002200241186a3602f880042002200241206a360218200241d880046a200241e880046a103a20022802d88004211120022802dc8004210f20022802e0800421064105210b2012450d002010102f0b20022802482110024020022802502201450d002010200141186c6a21092010210703400240200741046a280200450d002007280200102f0b0240200741146a2802002204450d00200728020c2101200441047421040340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102f200528020021030b2003102f0b200141106a2101200441706a22040d000b0b200741186a21010240200741106a280200450d00200728020c102f0b2001210720012009470d000b0b200228024c450d002010102f0b200b4108762104200fad220d4220862011ad84210c200a450d012008102f0c010b20024103410220041b3a0030200241d8006a41146a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241306a360218200241e880046a200241d8006a103a20022903e88004210c20022802f08004210602402003450d002001200341186c6a21082001210903400240200941046a280200450d002009280200102f0b0240200941146a2802002203450d00200928020c2104200341047421030340024020042d00004109470d000240200441046a2207280200220528020441ffffffff0371450d002005280200102f200728020021050b2005102f0b200441106a2104200341706a22030d000b0b200941186a21040240200941106a280200450d00200928020c102f0b2004210920042008470d000b0b200c422088210d4105210b41002104200a450d002001102f0b20004101360200200041106a2006360200200041086a200d422086200c42ffffffff0f838437020020002004410874200b41ff0171723602040c220b200241d8006a200110a3060240024020022802584101470d00200228025c22014108762109200241d8006a41086a290300220c422088210d200241e8006a28020021080c010b200241f880046a200241ec006a280200360200200241f080046a200241e4006a2902003703002002200229025c3703e880044100210141002105024002400240024002400240024002400240024002400240034002402001411f4d0d00410f21060c030b20022802f08004220720022802f480042204460d01200441016a22032004490d0820072003490d0a20022802e8800420046a2d00002104200220033602f48004200441ff00712001411f71742005722105200141076a21012004418001710d000b024020014120490d00410d21062004410f4b0d020b200241003602e08004200242043703d8800420050d02410421040c030b200241013a0048200241ec006a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241c8006a360218200241306a200241d8006a103a200241d880046a41086a200241306a41086a280200360200200220022903303703d88004410521060b200241206a41086a200241d880046a41086a2802002208360200200220022903d88004220c370320200c422088a7210a200ca7210f410021090c040b4100210b0340200b41016a210b410021094100210141002107034002402001411f4d0d00410f21060c050b20022802f08004220820022802f480042204460d03200441016a22032004490d0720082003490d0920022802e8800420046a2d00002104200220033602f48004200441ff00712001411f71742007722107200141076a21012004418001710d000b024020014120490d002004410f4d0d00410d21060c040b200241d8006a200241e880046a109506024020022802584101470d00200228025c22064108762109200228026821082002280264210a2002280260210f0c040b2002280264211120022802602114200228025c2110200241d8006a200241e880046a109706024020022802584101470d00200228025c2106200228026821082002280264210a2002280260210f02402011450d0020114104742104201021010340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102f200528020021030b2003102f0b200141106a2101200441706a22040d000b0b200641087621092014450d042010102f0c040b410021092002280260210a200228025c2106024002402002280264220141027422030d00410421084100210f0c010b2003410275220441ffffffff03712004470d2120034100480d212003102d2208450d2a2003410276210f0b02402001450d002003417c6a21092008210120062104034020012004280200360200200141046a2101200441046a21042003417c6a22030d000b200941027641016a21090b0240200a450d002006102f0b024020022802e08004220320022802dc8004470d00200341016a22012003490d21200341017422042001200420014b1bad421c7e220c422088a70d21200ca722014100480d210240024020030d002001102d21040c010b20022802d880042003411c6c2001103121040b2004450d2a200220043602d8800420022001411c6e3602dc80040b20022802d8800422042003411c6c6a2201200741087622063b00012001200836021020012010360204200120073a0000200141036a20064110763a0000200141186a2009360200200141146a200f3602002001410c6a2011360200200141086a20143602002002200341016a3602e08004200b2005470d000b0b20022802f4800420022802f8800446210120022902dc8004220c422088210d024020022802ec8004450d0020022802e88004102f0b20044108762105200da72103200ca7210b2001450d072005410874200441ff01717221012003ad422086200bad84210c410a21030c250b200241013a00482002410136026c2002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241c8006a360218200241306a200241d8006a103a2002280230210f2002280234210a20022802382108410521060b20022802d880042111024020022802e080042201450d0020112001411c6c6a210b201121070340024020072802042201450d0002402007410c6a2802002204450d00200441047421040340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102f200528020021030b2003102f0b200141106a2101200441706a22040d000b0b200741086a280200450d002007280204102f0b2007411c6a21010240200741146a280200450d002007280210102f0b200121072001200b470d000b0b20022802dc8004450d002011102f0b2009410874200641ff0171722101200aad220d422086200fad84210c20022802ec8004450d0520022802e88004102f0c050b417f2003104b000b417f2003104b000b20032007104a000b20032008104a000b2005410874200441ff017172210620024103410220011b3a00d88004200241d8006a41146a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241d880046a360218200241306a200241d8006a103a2002290330210c2002280238210802402003450d0020062003411c6c6a2109200621070340024020072802042201450d0002402007410c6a2802002204450d00200441047421040340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102f200528020021030b2003102f0b200141106a2101200441706a22040d000b0b200741086a280200450d002007280204102f0b2007411c6a21010240200741146a280200450d002007280210102f0b2001210720012009470d000b0b200c422088210d4105210141002109200b450d002006102f0b20004101360200200041106a2008360200200041086a200d422086200c42ffffffff0f838437020020002009410874200141ff0171723602040c210b200241013a0030200241ec006a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241306a360218200241e880046a200241d8006a103a410521040b2000200436020420004101360200200041086a20022903e88004370200200041106a200241e880046a41086a280200360200200b450d1f2008102f0c1f0b200620094621040240200b450d002008102f0b02402004450d00410921030c1a0b20024103410220041b3a00d88004200241ec006a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241d880046a360218200241306a200241d8006a103a200241f380046a200241386a280200360000200220022903303700eb8004200041053a0004200020022900e880043700052000410c6a200241ef80046a290000370000200041013602000c1e0b200241d8006a200110a3060240024020022802584101470d00200228025c22034108762104200241d8006a41086a290300220c422088210d200241e8006a28020021050c010b200241f880046a200241ec006a280200360200200241f080046a200241e4006a2902003703002002200229025c3703e8800441002101410021050240024002400240024002400240024002400240024002400240024002400240024002400240034002402001411f4d0d00410f21030c120b20022802f08004220720022802f480042204460d10200441016a22032004490d0120072003490d0820022802e8800420046a2d00002104200220033602f48004200441ff00712001411f71742005722105200141076a21012004418001710d000b024020014120490d002004410f4d0d00410d21030c110b20024100360250200242043703484104210102402005450d00410021114100210f410021120340200241d8006a200241e880046a109906024020022802584101470d0020022002290264220c3703d8800420022802602108200228025c2103200ca721090c110b20022802602110200228025c211402400240024002400240024020022802f08004220320022802f480042207460d00200741016a22042007490d0920032004490d0a2002280264210e20022802e88004220920076a2d0000210a200220043602f480040240200a41034d0d00410a21040c160b200a0e0401020304010b200241013a00202002410136026c2002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241206a360218200241306a200241d8006a103a0c120b4100210a4100210841002107034002402008411f4d0d00410f21040c150b20032004460d132004417f460d0a2003200441016a2206490d0f200920046a2d0000210b200220063602f48004200b41ff00712008411f71742007722107200841076a210820062104200b418001710d000b4100210a20084120490d03200b410f4d0d03410d21040c130b410021084100210703402008411f4b0d100240024020032004460d002004417f460d0c2003200441016a22064f0d01200441016a2003104a000b200241013a00202002410136026c2002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241206a360218200241306a200241d8006a103a0c120b200920046a2d0000210b200220063602f48004200b41ff00712008411f71742007722107200841076a210820062104200b418001710d000b4101210a20084120490d02200b410f4d0d020c0e0b410021084100210703402008411f4b0d0f0240024020032004460d002004417f460d0c2003200441016a22064f0d01200441016a2003104a000b200241013a00202002410136026c2002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241206a360218200241306a200241d8006a103a0c110b200920046a2d0000210b200220063602f48004200b41ff00712008411f71742007722107200841076a210820062104200b418001710d000b4102210a20084120490d01200b410f4b0d0d0c010b410021084100210703402008411f4b0d0e0240024020032004460d002004417f460d0c2003200441016a22064f0d01200441016a2003104a000b200241013a00202002410136026c2002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241206a360218200241306a200241d8006a103a0c100b200920046a2d0000210b200220063602f48004200b41ff00712008411f71742007722107200841076a210820062104200b418001710d000b4103210a20084120490d00200b410f4b0d0c0b200220073602e080042002200a3602dc800420022902dc8004210c02400240200f2011460d00201121030c010b201141016a22042011490d28201141017422032004200320044b1bad42147e220d422088a70d28200da722044100480d280240024020110d002004102d21010c010b2001201141146c2004103121010b2001450d31200220013602482011210f200441146e220321110b2001200f41146c6a2204200c37020c2004200e3602082004201036020420042014360200200f41016a210f201241016a22122005470d000b2002200336024c2002200f3602500b20022802f4800420022802f88004462104200229024c220c422088210d024020022802ec8004450d0020022802e88004102f0b200da72103200ca721072004450d112003ad4220862007ad84210c410821030c2c0b417f2003104b000b417f2004104b000b20042003104a000b417f200441016a104b000b417f200441016a104b000b417f200441016a104b000b417f200441016a104b000b20032007104a000b200441016a2003104a000b410d21044100210a0c030b410f21044100210a0c020b200228023021082002290234210c410521044100210a0c010b200241013a00202002410136026c2002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241206a360218200241306a200241d8006a103a200228023021082002290234210c410521040b200a41087420047221032002200c3703d88004200ca721092010450d002014102f0b2002200f3602502002201136024c20022802dc800421050240200f450d00200f41146c21072001210403400240200441046a280200450d002004280200102f0b200441146a21042007416c6a22070d000b0b2011450d032001102f0c030b200241013a0048200241ec006a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241c8006a360218200241306a200241d8006a103a200228023021012002280234210420022802382105410521030b200220043602dc8004200220013602d88004200220053602e0800420022903d88004220c422088a72109200ca721080c010b20024103410220041b3a00d88004200241d8006a41146a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241d880046a360218200241306a200241d8006a103a2002290330210c2002280238210502402003450d00200341146c21032001210403400240200441046a280200450d002004280200102f0b200441146a21042003416c6a22030d000b0b200c422088210d41052103410021042007450d012001102f0c010b200341087621042009ad220d4220862008ad84210c20022802ec8004450d0020022802e88004102f0b20004101360200200041106a2005360200200041086a200d422086200c42ffffffff0f838437020020002004410874200341ff0171723602040c1d0b200241d8006a200110a3060240024020022802584101470d00200228025c22094108762104200241d8006a41086a290300220c422088210d200241e8006a28020021080c010b200241c0006a200241ec006a280200360200200241386a200241e4006a2902003703002002200229025c3703304100210141002107024002400240024002400240024002400240024002400240024002400240024002400240034002402001411f4d0d00410f21090c030b20022802382205200228023c2204460d01200441016a22032004490d0520052003490d0c2002280230220920046a2d000021042002200336023c200441ff00712001411f71742007722107200141076a21012004418001710d000b024020014120490d002004410f4d0d00410d21090c020b200241003602502002420437034820070d02410421010c030b200241013a0048200241ec006a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241c8006a360218200241e880046a200241d8006a103a20022802e88004210120022802ec8004210420022802f080042108410521090b200220043602dc8004200220013602d88004200220083602e0800420022903d88004220c422088a7210a200ca721060c0f0b2007417f6a2111410421014104211241042107410421144100210b4100210f034020052003460d05200341016a22082003490d0320052008490d04200920036a2c000021042002200836023c20044100480d0602400240024002400240200441c00071450d00200441807f72220441ff017141fb014d0d00024020052008460d00200341026a21062008417f460d0d20052006490d0e200920086a2d000021032002200636023c200341014b0d024100210520030e020504050b2002200b36024c2002200f360250200241013a0020200241ec006a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241206a360218200241d880046a200241d8006a103a20022802d88004210620022802dc8004210a20022802e080042108410521010c020b2002200b36024c2002200f360250410621010c0e0b2002200b36024c2002200f360250410c21010b200241f880046a2008360200200241f480046a200a360200200241f080046a2006360200200220033a00ed8004200220013a00ec80040c0e0b41800221050b200241d8006a200241306a1095062002280264210a20022802602106200228025c2109024020022802584101470d002002200b36024c2002200f360250200241e8006a28020021080c0e0b02400240200f200b460d00200b2108200f210b0c010b200b41016a2201200b490d22200b41017422032001200320014b1b220141ffffffff00712001470d22200141047422034100480d2202400240200b0d002003102d21010c010b2014200b4104742003103121010b2001450d2b20022001360248200341047621082001211220012107200121140b2014200b4104746a220320104180807c712004417f7341ff017172200572221036020c2003200a3602082003200636020420032009360200200b41016a210f02402011450d002011417f6a2111200228023c210320022802382105200228023021092008210b0c010b0b2002200836024c2002200f3602500b200228023c2002280240462104200229024c220c422088210d02402002280234450d002002280230102f0b200da72103200ca721062004450d0c2003ad4220862006ad84210c410721030c260b417f2003104b000b417f2008104b000b20082005104a000b2002200b36024c2002200f360250200241013a0020200241ec006a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241206a360218200241d880046a200241d8006a103a20022802d88004210620022802dc8004210a20022802e080042108410521010c050b2002200b36024c2002200f360250411921010c030b417f2006104b000b20062005104a000b20032005104a000b0b200241f880046a2008360200200241f480046a200a360200200241f080046a2006360200200220043a00ed8004200220013a00ec80040b200241013a00e8800420022802ec800421090b0240200f450d002007200f4104746a210f0340024020072802082204450d0020072802002101200441047421040340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102f200528020021030b2003102f0b200141106a2101200441706a22040d000b0b200741106a21010240200741046a280200450d002007280200102f0b200121072001200f470d000b0b200b450d012012102f0c010b20024103410220041b3a00d88004200241ec006a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241d880046a360218200241e880046a200241d8006a103a20022903e88004210c20022802f08004210802402003450d00200120034104746a210b200121090340024020092802082203450d0020092802002104200341047421030340024020042d00004109470d000240200441046a2207280200220528020441ffffffff0371450d002005280200102f200728020021050b2005102f0b200441106a2104200341706a22030d000b0b200941106a21040240200941046a280200450d002009280200102f0b200421092004200b470d000b0b200c422088210d41052109410021042006450d012001102f0c010b20094108762104200aad220d4220862006ad84210c2002280234450d002002280230102f0b20004101360200200041106a2008360200200041086a200d422086200c42ffffffff0f838437020020002004410874200941ff0171723602040c1c0b200241d8006a200110a3060240024020022802584101470d00200228025c22034108762105200241d8006a41086a290300220c422088210d200241e8006a28020021040c010b200241f880046a200241ec006a280200360200200241f080046a200241e4006a290200220c3703002002200229025c220d3703e88004200da72108200ca721054100210420022802f4800421014100210302400240024002400240024003402004411f4b0d020240024020052001460d002001417f460d032005200141016a22074f0d01200141016a2005104a000b200220053602f48004200241013a0048200241ec006a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241c8006a360218200241306a200241d8006a103a200228023021012002280234210320022802382104410521080c050b200820016a2d0000220941ff00712004411f71742003722103200441076a2104200721012009418001710d000b200220073602f48004024020044120490d002009410f4d0d00410d21080c030b200241003602382002420437033041042101024002402003450d0041002105410021090340200241d8006a200241e880046a109c0620022f005d20022d005f4110747221072002280264210b2002280260210620022d005c210820022802584101460d020240024020092005460d002005210a200921040c010b200541016a22042005490d1a2005410174220a2004200a20044b1bad420c7e220c422088a70d1a200ca7220a4100480d1a0240024020050d00200a102d21010c010b20012005410c6c200a103121010b2001450d232002200136023020052104200a410c6e220a21050b20012004410c6c6a220420073b000120042006360204200420083a0000200441036a20074110763a0000200441086a200b3602002003200941016a2209470d000b2002200a360234200220093602380b20022802f4800420022802f880044621042002290234210c024020022802ec8004450d0020022802e88004102f0b200ca721072004450d06200c422088a7ad4220862007ad84210c410621030c1e0b2002200536023420022009360238200241e8006a28020021042005450d042001102f0c040b417f200141016a104b000b200220013602f48004410f21080b0b200220033602dc8004200220013602d88004200220043602e0800420022903d88004220c422088a7210b200ca72106410021070b200741ffffff07712205410874200841ff0171722103200bad220d4220862006ad84210c20022802ec8004450d0120022802e88004102f0c010b20024103410220041b3a00d88004200241ec006a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241d880046a360218200241306a200241d8006a103a2002290330220c422088210d2002280238210441052103410021052007450d002001102f0b20004101360200200041106a2004360200200041086a200d422086200c42ffffffff0f838437020020002005410874200341ff0171723602040c1b0b200241d8006a200110a3060240024020022802584101470d00200228025c22034108762105200241d8006a41086a290300220c422088210d200241e8006a28020021040c010b200241f880046a200241ec006a280200360200200241f080046a200241e4006a290200220c3703002002200229025c220d3703e88004200da72108200ca721034100210420022802f480042101410021070240024002400240024002400240024002400240024003402004411f4b0d010240024020032001460d002001417f460d0a2003200141016a22054f0d01200141016a2003104a000b200220033602f48004200241013a0048200241ec006a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241c8006a360218200241306a200241d8006a103a2002280230210b2002280234210620022802382104410521080c040b200820016a2d0000220941ff00712004411f71742007722107200441076a2104200521012009418001710d000b200220053602f48004024020044120490d002009410f4d0d00410d21080c020b4100210a200241003602e08004200242043703d8800420070d03410421014100210b0c060b200220013602f48004410f21080b0b200220043602e08004200220063602dc80042002200b3602d88004410021030c010b410421014101210a41002109024002400240034020032005460d01200541016a22042005490d0820032004490d09200820056a2c00002103200220043602f480040240200341004e0d00411921080c030b410721080240200341c000710d000c030b200341807f7222034170470d03200241d8006a200241e880046a109c0620022f005d20022d005f41107472210320022d005c2108024020022802584101470d0020034180feff0771410876210520022802682104200228026421062002280260210b0c040b200228026421052002280260210602400240200a417f6a22042009460d002009210b200421090c010b200941016a22042009490d1b2009410174220b2004200b20044b1bad420c7e220c422088a70d1b200ca722044100480d1b0240024020090d002004102d21010c010b20012009410c6c2004103121010b2001450d24200220013602d880042004410c6e210b0b20012009410c6c6a220420033b00012004200536020820042006360204200420083a0000200441036a20034110763a00002007200a460d05200a41016a210a20022802f48004210520022802f08004210320022802e880042108200b21090c000b0b200241013a00482002410136026c2002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241c8006a360218200241306a200241d8006a103a2002280230210b2002280234210620022802382104410521080b0b200220093602dc80042002200a417f6a3602e080042005410874200341ff01717221032009450d002001102f0b200341ffffff07712205410874200841ff01717221032006ad220d422086200bad84210c20022802ec8004450d0620022802e88004102f0c060b2002200b3602dc80042002200a3602e080040b20022802f4800420022802f88004462104024020022802ec8004450d0020022802e88004102f0b2004450d03200aad422086200bad84210c410521030c1a0b417f200141016a104b000b417f2004104b000b20042003104a000b20024103410220041b3a00d88004200241ec006a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241d880046a360218200241306a200241d8006a103a2002290330220c422088210d200228023821044105210341002105200b450d002001102f0b20004101360200200041106a2004360200200041086a200d422086200c42ffffffff0f838437020020002005410874200341ff0171723602040c1a0b200241d8006a200110a3060240024020022802584101470d00200228025c22034108762105200241d8006a41086a290300220c422088210d200241e8006a28020021040c010b200241ec006a280200210f200241e8006a2802002101200241e4006a2802002103200241e0006a280200210a200228025c210841002104410021070240024002400240024002400240024002400240024002400240034002402004411f4d0d00410f21030c030b20032001460d012001417f460d0a2003200141016a2205490d0c200820016a2d0000220941ff00712004411f71742007722107200441076a2104200521012009418001710d000b024020044120490d002009410f4d0d00410d21030c020b41002111200241003602382002420437033020070d0241042101410021090c030b200241013a0030200241ec006a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241306a360218200241e880046a200241d8006a103a20022802e88004210520022802ec8004210720022802f080042104410521030b200220043602e08004200220073602dc8004200220053602d880040c060b4104210141002109410021110340200921102011221441016a211120052104410021094100210b03402009411f4b0d030240024020032004460d002004417f460d0b2003200441016a22054f0d01200441016a2003104a000b2002201036023420022014360238200241013a00d88004200241ec006a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241d880046a360218200241e880046a200241d8006a103a20022802e88004210520022802ec8004210720022802f080042104410521030c070b200820046a2d0000220641ff00712009411f7174200b72210b200941076a2109200521042006418001710d000b024020094120490d002006410f4b0d040b0240024020142010460d0020102109201421100c010b201041016a22042010490d1a201041017422092004200920044b1b220441ffffffff03712004470d1a200441027422044100480d1a0240024020100d002004102d21010c010b200120104102742004103121010b2001450d2320022001360230200441027621090b200120104102746a200b36020020112007470d000b20022009360234200220113602380b2005200f4621040240200a450d002008102f0b2004450d082011ad4220862009ad84210c410421030c1e0b2002201036023420022014360238410f21030c010b2002201036023420022014360238410d21030b0b2010450d002001102f0b2007ad220d4220862005ad84210c41002105200a450d042008102f0c040b417f200141016a104b000b417f200441016a104b000b200141016a2003104a000b20024103410220041b3a0030200241ec006a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241306a360218200241e880046a200241d8006a103a20022903e88004220c422088210d20022802f08004210441052103410021052009450d002001102f0b20004101360200200041106a2004360200200041086a200d422086200c42ffffffff0f838437020020002005410874200341ff0171723602040c190b200241d8006a200110a3060240024020022802584101470d00200228025c22044108762105200241d8006a41086a290300220c422088210d200241e8006a28020021030c010b200241f880046a200241ec006a280200360200200241f080046a200241e4006a2902003703002002200229025c3703e8800441002101410021050240024002400240024002400240024002400240024002400240034002402001411f4d0d00410f21040c030b20022802f08004220720022802f480042204460d01200441016a22032004490d0620072003490d0520022802e8800420046a2d00002104200220033602f48004200441ff00712001411f71742005722105200141076a21012004418001710d000b024020014120490d002004410f4d0d00410d21040c020b200241003602e08004200242043703d8800420050d02410421010c030b200241013a0048200241ec006a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241c8006a360218200241306a200241d8006a103a200228023021012002280234210520022802382103410521040b200220053602dc8004200220013602d88004200220033602e0800420022903d88004220c422088a72107200ca721090c0a0b20022802dc8004210a20022802e080042106410021130340200241d8006a200241e880046a1099062002280264210720022802602110200228025c2112024020022802584101470d002002280268210320102109201221040c090b200241d8006a200241e880046a1099062002280264211720022802602114200228025c210e024020022802584101470d00200228026821032014210920172107200e21040c080b02400240024002400240024002400240024002400240024002400240024002400240024002400240024020022802f08004220320022802f480042209460d00200941016a22012009490d0520032001490d0620022802e88004220f20096a2d00002104200220013602f48004410021110240200441034d0d004109210b410021030c1c0b20040e0401020304010b200241013a00482002410136026c2002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241c8006a360218200241306a200241d8006a103a200228023021092002290234210d4105210b41002111410021030c1a0b41002111410021044100210b034002402004411f4d0d00410f210b0c190b0240024020032001460d002001417f460d082003200141016a22084f0d01200141016a2003104a000b200241013a00482002410136026c2002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241c8006a360218200241306a200241d8006a103a200228023021092002290234210d4105210b410021110c1a0b200f20016a2d00002109200220083602f48004200941ff00712004411f7174200b72210b200441076a2104200821012009418001710d000b4100211120044120490d112009410f4d0d11410d210b0c170b0240024020032001460d00200941026a21042001417f460d0720032004490d08200f20016a2c00002101200220043602f4800402402001417f4a0d00411921030c100b200141c00071450d0e200141807f7222014170470d0e200241d8006a200241e880046a109c062002290360210c200228025c210b20022802584101470d01200228026821040c100b200241013a00482002410136026c2002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241c8006a360218200241306a200241d8006a103a2002290330210c20022802382104410521030c0e0b410121110c110b200241d8006a200241e880046a109c062002290360210c200228025c210b024020022802584101460d00410221110c110b20022002280268360260200b4180808078712111200b4180807c712103200b41087621040c0e0b0240024020032001460d00200941026a21082001417f460d0720032008490d08200f20016a2c00002104200220083602f480040240200441004e0d004119210b410021030c190b200441c000710d010c0b0b200241013a00482002410136026c2002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241c8006a360218200241306a200241d8006a103a4105210b2002290234210d20022802302109410021030c170b200441807f72220441ff017141fb014d0d090240024020032008460d00200941036a21012008417f460d0920032001490d0a200f20086a2d00002108200220013602f48004410021030240200841014d0d00410c210b41002111200821040c190b2004417f7321094103211120080e021101110b200241013a00482002410136026c2002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241c8006a360218200241306a200241d8006a103a200228023021092002290234210d4105210b410021030c170b410121030c0f0b417f2001104b000b20012003104a000b417f200141016a104b000b417f2004104b000b20042003104a000b417f2008104b000b20082003104a000b417f2001104b000b20012003104a000b4106210b410021030c0c0b410721030b200141ff0171410874200372210b0b20022004360260200b4180808078712111200b4180807c712103200b41087621040b2002200c370358200229025c210d200ca721090c080b0b024002402006200a460d00200a21080c010b200a41016a2201200a490d19200a41017422042001200420014b1bad42287e220d422088a70d19200da722014100480d1902400240200a0d002001102d21040c010b20022802d88004200a41286c2001103121040b2004450d22200220043602d88004200a2106200141286e2208210a0b20022802d880042201200641286c6a2204200e36020c200420073602082004201036020420042012360200200441206a200c3702002004411c6a200b3602002004411a6a20033a0000200441196a20093a0000200441186a20113a0000200441146a2017360200200441106a2014360200200641016a2106201341016a22132005470d000b200220083602dc8004200220063602e080040b20022802f4800420022802f8800446210420022902dc8004220c422088210d024020022802ec8004450d0020022802e88004102f0b200da72105200ca721072004450d072005ad4220862007ad84210c410321030c1d0b20032007104a000b417f2003104b000b0b41002103410021040b200b41ff0171200441ff0171410874722003418080fc0771722011722104200d422088a72103200da721072014450d00200e102f0b2010450d002012102f0b2002200a3602dc8004200220063602e0800420022802d88004210802402006450d00200641286c21052008210103400240200141046a280200450d002001280200102f0b0240200141106a280200450d002001410c6a280200102f0b200141286a2101200541586a22050d000b0b200a450d012008102f0c010b20024103410220041b3a00d88004200241ec006a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241d880046a360218200241306a200241d8006a103a2002290330210c2002280238210302402005450d00200541286c21052001210403400240200441046a280200450d002004280200102f0b0240200441106a280200450d002004410c6a280200102f0b200441286a2104200541586a22050d000b0b200c422088210d41052104410021052007450d012001102f0c010b200441087621052007ad220d4220862009ad84210c20022802ec8004450d0020022802e88004102f0b20004101360200200041106a2003360200200041086a200d422086200c42ffffffff0f838437020020002005410874200441ff0171723602040c180b0c010b0b2013450d042014102f0c040b200241013a00d880042002410136026c2002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241d880046a360218200241e880046a200241d8006a103a20022802e88004210920022802ec8004210720022802f080042101410521100c010b0b2013450d002012102f0b20014110762104200141087621030b200341ff0171410874200141ff017172210320044110742106200f41ff0171410874210a20022802302105024020022802382201450d00200141047421042005210103400240200141046a280200450d002001280200102f0b200141106a2101200441706a22040d000b0b20032006722103200a20107221042002280234450d012005102f0c010b2007200a4621042002290234220c422088210d0240200b450d002008102f0b200da72105200ca7210702402004450d002005ad4220862007ad84210c410221030c0b0b20024103410220041b3a0030200241ec006a41013602002002420137025c200241b4afca003602582002412836021c2002200241186a3602682002200241306a360218200241e880046a200241d8006a103a20022903e88004210c20022802f08004210302402005450d00200541047421052001210403400240200441046a280200450d002004280200102f0b200441106a2104200541706a22050d000b0b200c422088210d41052104410021052007450d012001102f0c010b200441087621052007ad220d4220862009ad84210c200b450d002008102f0b20004101360200200041106a2003360200200041086a200d422086200c42ffffffff0f838437020020002005410874200441ff0171723602040c0d0b200241003602e08004200220053602dc8004200220063602d88004200241d8006a200241d880046a109d064101210f200228025c2107024020022802584101460d00024020070d004100210b41002103410021090c080b200241d8006a410041800810e7061a4101210f41002109410021044100210b0240034020022802dc8004221120022802e0800422036b2007200b6b22014180082001418008491b2201490d01200320016a220a2003490d042011200a490d05200241d8006a20022802d8800420036a200110e8061a2002200a3602e0800402400240200920046b2001490d00200120046a21030c010b200420016a22032004490d042009410174220a2003200a20034b1b220a4100480d040240024020090d00200a102d210f0c010b200f2009200a1031210f0b200f450d0d200a21090b200f20046a200241d8006a200110e8061a2003210420072001200b6a220b4d0d060c000b0b200241013a0048200241fc80046a4101360200200242013702ec8004200241b4afca003602e880042002412836021c2002200241186a3602f880042002200241c8006a360218200241306a200241e880046a103a2002290330220c422088a7210320022802382104200ca721054105210741002101024020090d00200521090c060b200f102f200521090c050b20074108762101200241d8006a41086a290300220c422088a72103200241e8006a2802002104200ca721090c040b1038000b2003200a104b000b200a2011104a000b200241d8006a200f2003106620022802584101470d0141082107024020090d000c010b200f102f0b2003ad4220862009ad84210c2008450d032006102f0c030b200f410876210b0b200520022802e080042207490d03200520076b2201417f4c0d040240024020010d00410121040c010b2001102d2204450d032004200620076a200110e8061a0b2003ad422086210c2009ad210d2001ad221b422086211c02402008450d002006102f0b200c200d84210c201c201b84210d200b410874200f41ff0171722101410121030b200020033a000420004100360200200041056a20022f00153b0000200041186a200d370200200041146a20043602002000410c6a200c370200200041086a2001360200200041206a2002290200370200200041076a200241176a2d00003a0000200041286a200241086a290200370200200041306a200241106a2802003602000c040b20004101360200200041106a2004360200200041086a200c37020020002001410874200741ff0171723602040c030b1036000b20072005104b000b103d000b2002418081046a24000ba80e01077f02402001450d002000200141306c6a210203402000220341306a21000240024020032d00002201410e4b0d00024002400240024002400240024002400240024002400240024020010e0f0001020304050607080e090e0a0b0c000b200341086a280200450d0d200341046a280200102f0c0d0b0240200341086a280200450d00200341046a280200102f0b200341146a280200450d0c200341106a280200102f0c0c0b02402003410c6a2802002204450d00200341046a28020021012004410474210403400240200141046a280200450d002001280200102f0b200141106a2101200441706a22040d000b0b200341086a280200450d0b2003280204102f0c0b0b02402003410c6a2802002204450d00200341046a2802002101200441286c210403400240200141046a280200450d002001280200102f0b0240200141106a280200450d002001410c6a280200102f0b200141286a2101200441586a22040d000b0b200341086a280200450d0a2003280204102f0c0a0b200341086a280200450d09200341046a280200102f0c090b200341086a280200450d08200341046a280200102f0c080b200341086a280200450d07200341046a280200102f0c070b02402003410c6a2802002201450d00200341046a280200220520014104746a21060340024020052802082204450d0020052802002101200441047421040340024020012d00004109470d000240200141046a2207280200220828020441ffffffff0371450d002008280200102f200728020021080b2008102f0b200141106a2101200441706a22040d000b0b200541106a21010240200541046a280200450d002005280200102f0b2001210520012006470d000b0b200341086a280200450d062003280204102f0c060b02402003410c6a2802002204450d00200341046a2802002101200441146c210403400240200141046a280200450d002001280200102f0b200141146a21012004416c6a22040d000b0b200341086a280200450d052003280204102f0c050b02402003410c6a2802002201450d00200341046a28020022052001411c6c6a21060340024020052802042201450d0002402005410c6a2802002204450d00200441047421040340024020012d00004109470d000240200141046a2207280200220828020441ffffffff0371450d002008280200102f200728020021080b2008102f0b200141106a2101200441706a22040d000b0b200541086a280200450d002005280204102f0b2005411c6a21010240200541146a280200450d002005280210102f0b2001210520012006470d000b0b200341086a280200450d042003280204102f0c040b02402003410c6a2802002201450d00200341046a2802002205200141186c6a210603400240200541046a280200450d002005280200102f0b0240200541146a2802002204450d00200528020c2101200441047421040340024020012d00004109470d000240200141046a2207280200220828020441ffffffff0371450d002008280200102f200728020021080b2008102f0b200141106a2101200441706a22040d000b0b200541186a21010240200541106a280200450d00200528020c102f0b2001210520012006470d000b0b200341086a280200450d032003280204102f0c030b02402003410c6a2802002201450d00200341046a28020022052001411c6c6a21060340024020052802042201450d0002402005410c6a2802002204450d00200441047421040340024020012d00004109470d000240200141046a2207280200220828020441ffffffff0371450d002008280200102f200728020021080b2008102f0b200141106a2101200441706a22040d000b0b200541086a280200450d002005280204102f0b2005411c6a21010240200541146a280200450d002005280210102f0b2001210520012006470d000b0b200341086a280200450d022003280204102f0c020b0240200341046a2802002201450d00200341086a280200450d002001102f0b0240200341146a2802002201450d0002402003411c6a2802002204450d002004410c6c21040340024020012802002208450d00200141046a280200450d002008102f0b2001410c6a2101200441746a22040d000b0b200341186a280200450d002003280214102f0b200341246a2802002205450d0102402003412c6a2802002201450d00200520014104746a210603402005220741106a2105024020072802042201450d0002402007410c6a2802002204450d002004410c6c21040340024020012802002208450d00200141046a280200450d002008102f0b2001410c6a2101200441746a22040d000b0b200741086a280200450d002007280204102f0b20052006470d000b0b200341286a280200450d012003280224102f0c010b0240200341086a280200450d00200341046a280200102f0b0240200341146a2802002201450d00200341186a280200450d002001102f0b200341246a280200450d00200341206a280200102f0b20002002470d000b0b0b994d021b7f027e230041e0026b22022400200128020841546a2103200141106a28020041306c210402400240024002400240024002400240024002400240024003402004450d01200441506a21042003412c6a2105200341306a2206210320052d00004102470d000b200241e8006a200610d60341042107200228026c2208450d01200841047422044100480d0b200228026821032004102d2207450d052008410474210641002109200721040340200341086a2802002205417f4c0d042003410c6a2d0000210a2003280200210b0240024020050d004101210c0c010b2005102d220c450d070b200c200b200510e806210b2004410d6a2003410d6a2d00003a00002004410c6a200a3a0000200441086a2005360200200441046a20053602002004200b360200200441106a2104200941016a2109200341106a2103200641706a22060d000b20070d020b410421070b41002109410021080b200128021041306c2104200128020841546a2103024003404100210b41c8e1ca002106024020040d00410021040c020b200441506a21042003412c6a2105200341306a220a210320052d00004103470d000b200241e0006a200a10d6034100210420022802602203450d0020022802642104200321060b024020040d004101210d4100210e410021034100210f410421104100210a41002111410121124100210541002113410421144100210641002115410421160c020b200441286c210c2006411c6a2104410421104100210b4100210e4101210d410021034100210f4100210a41002111410121124100210541002113410421144100210641002115410421160340024002400240024002402004417c6a2d00000e0401020300010b2004417e6a22172d000021182004417d6a22192d0000211a0240200a2011470d00200a41016a221b200a490d0e200a410174221c201b201c201b4b1b221120116a221b2011490d0e201b4100480d0e02400240200a0d00201b102d21120c010b2012201c201b103121120b2012450d08201b41017621110b2012200a4101746a221b20184101713a0001201b201a3a000020172d0000211720192d000021180240200b200e470d00200b41016a221b200b490d0e200b410174221a201b201a201b4b1b221920196a221b2019490d0e201b4100480d0e02400240200b0d00201b102d210d0c010b200d201a201b1031210d0b200d450d08201b410176210e0b200a41016a210a200d200b4101746a221b20174101713a0001201b20183a0000200b41016a210b0c030b2004280200211b02402003200f470d00200341016a220f2003490d0d20034101742217200f2017200f4b1b220f41ffffffff0371200f470d0d200f410274220f4100480d0d0240024020030d00200f102d21100c010b20102003410274200f103121100b2010450d07200f410276210f0b201020034102746a201b360200200341016a21030c020b200241b8016a41086a221b200441086a280200360200200220042902003703b801024020052013470d00200541016a22132005490d0c200541017422172013201720134b1bad420c7e221d422088a70d0c201da722134100480d0c0240024020050d002013102d21140c010b20142005410c6c2013103121140b2014450d062013410c6e21130b20142005410c6c6a221720022903b801370200201741086a201b280200360200200541016a21050c010b200241b8016a41086a221b200441086a280200360200200220042902003703b801024020062015470d00200641016a22172006490d0b200641017422182017201820174b1bad420c7e221d422088a70d0b201da722174100480d0b0240024020060d002017102d21160c010b20162006410c6c2017103121160b2016450d052017410c6e21150b20162006410c6c6a221720022903b801370200201741086a201b280200360200200641016a21060b200441286a2104200c41586a220c450d020c000b0b103d000b2001280210221941306c21172001280208210c410021040240034020172004460d01200c20046a211b200441306a22182104201b2d00004104470d000b200241d8006a200c20186a41546a10d603200228025c2204450d002002280258210c200441027421172003410174211b200341027421040340200c280200211802402003200f470d00200341016a220f2003490d09201b200f201b200f4b1b220f41ffffffff0371200f470d09200f410274220f4100480d090240024020030d00200f102d21100c010b20102004200f103121100b2010450d03200f410276210f0b200c41046a210c201020046a2018360200201b41026a211b200441046a2104200341016a21032017417c6a22170d000b2001280208210c200128021021190b200c201941306c6a2117200c21040240034020172004460d0120042d0000211b200441306a22182104201b4105470d000b200241d0006a201841546a10d6032002280254410c6c2218450d00200228025021042005410174211b2005410c6c210c0340200441086a2117024002400240200441046a2802004101470d002002201728020022193602a0022004280200221a20194b0d010b200241003602700c010b200241023602cc01200242023702bc01200241e4d7ca003602b801200241013602d402200241013602cc022002201a3602b0022002200241c8026a3602c8012002200241b0026a3602d0022002200241a0026a3602c802200241f0006a200241b8016a103a2002280270450d00200241f0006a21040c070b2004290200211d200241b8016a41086a221920172802003602002002201d3703b801024020052013470d00200541016a22132005490d09201b2013201b20134b1bad420c7e221d422088a70d09201da722134100480d090240024020050d002013102d21140c010b2014200c2013103121140b2014450d032013410c6e21130b2004410c6a21042014200c6a221720022903b801370200201741086a2019280200360200201b41026a211b200c410c6a210c200541016a2105201841746a22180d000b2001280208210c200128021021190b200c201941306c6a2117200c21040240034020172004460d0120042d0000211b200441306a22182104201b4106470d000b200241c8006a201841546a10d603200228024c221b450d0020022802482104201b410c6c21172006410174211b2006410c6c210c0340200241b8016a200410a906024020022802b801450d00200241b8016a21040c070b2004290200211d200241b8016a41086a2218200441086a2802003602002002201d3703b801024020062015470d00200641016a22152006490d09201b2015201b20154b1bad420c7e221d422088a70d09201da722154100480d090240024020060d002015102d21160c010b2016200c2015103121160b2016450d032015410c6e21150b2004410c6a21042016200c6a221920022903b801370200201941086a2018280200360200201b41026a211b200c410c6a210c200641016a2106201741746a22170d000b2001280208210c200128021021190b200c201941306c6a2117200c21040240034020172004460d0120042d0000211b200441306a22182104201b4107470d000b200241c0006a201841546a10d6032002280244221b450d0020022802402204201b4104746a211a200a410174210c200241b8016a41047221190340200241b8016a2004200d200b10aa0602400240024020022d00b8014101460d00200220022d00b901221b3a00a0020240201b2004410c6a2d00002217470d00200241003602700c030b200241023602cc01200242023702bc01200241f8d8ca003602b801200241303602d402200241303602cc02200220173a00b0022002200241c8026a3602c8012002200241a0026a3602d0022002200241b0026a3602c802200241f0006a200241b8016a103a0c010b200241f0006a41086a201941086a280200360200200220192902003703700b02402002280270450d00200241f0006a21040c080b2004410c6a2d0000211b0b2004410d6a2d000021170240200a2011470d00200a41016a2218200a490d09200c2018200c20184b1b221120116a22182011490d0920184100480d0902400240200a0d002018102d21120c010b2012200c2018103121120b2012450d03201841017621110b2012200c6a2218201b3a0000201841016a20174101713a0000200c41026a210c200a41016a210a200441106a2204201a470d000b2001280208210c200128021021190b200241a8016a2003360200200241a4016a200f3602002002419c016a200936020020024198016a200836020020024190016a200a3602002002418c016a201136020020024184016a200536020020024180016a2013360200200220103602a001200220073602940120022012360288012002201436027c200220063602782002201536027420022016360270200c201941306c6a2105200c210402400340024020052004470d004100210a0c020b20042d00002103200441306a2206210420034104470d000b200241386a200641546a10d603200228023c210a0b2002200a3602ac01200c201941306c6a2105200c210402400340024020052004470d00410021040c020b20042d00002103200441306a220621042003410c470d000b2006415c6a28020021040b200220043602b001200a2004470d0102400240024002400240024002400240200a450d00200c201941306c6a2105200c2104034020052004460d0320042d00002103200441306a2206210420034104470d000b200c201941306c6a210a200c21040340200a2004460d0220042d00002103200441306a220521042003410c470d000b200241306a200641546a10d60320022802342204450d002002280230220c20044102746a211b2005415c6a2110200541546a2114200241f1016a21184100210b03402002200b3602b4012010280200210420142802002105200242013702bc01200241fc8fca003602b801200241013602b402200241013602cc012002200241b0026a3602c8012002200241b4016a3602b002200241c8026a200241b8016a103a20022802c802210320022902cc02211d024002402004200b4d0d000240201da7450d002003102f0b2002200c28020022043602a002024002400240200228029c0120044d0d0002400240024002402005200b41186c6a22032802142213450d0020022802940120044104746a22052d000d210f20052802002117200328020c2104200328020021162005280208221221060240024020032802082209450d002009410374210a20122103201621050340200320052802006a22062003490d02200541086a210520062103200a41786a220a0d000b0b4108102d2203450d132003200fad42ff0183422886370200200241b0026a41026a2205200241c8026a41026a2d00003a0000200220022f00c8023b01b0022002200f3a00f0012002418080013602ec0120024281808080103702e401200220033602e001200242808080808080103703d801200242013703d001200220063602cc01200220093602c801200220163602c401200220123602c001200220173602bc012002200241f0006a3602b801201820022f01b0023b0000201841026a20052d00003a000020134104742105410021030340200220033602f801200220043602fc0120024180026a200241b8016a200410ac060240200228028002450d00200241a0026a41086a20024180026a41086a28020036020020022002290380023703a002200241033602c402200242033702b402200241c488ca003602b002200241313602dc02200241013602d402200241323602cc022002200241c8026a3602c0022002200241a0026a3602d8022002200241f8016a3602d0022002200241fc016a3602c80220024190026a200241b0026a103a024020022802a402450d0020022802a002102f0b20022802900222060d050b200441106a2104200341016a2103200541706a22050d000b20022802e8010d04024020022802d401450d0020022802d001102f0b20022802e401450d0920022802e001102f0c090b4120102d2206450d12200641186a41002900d4df4a370000200641106a41002900ccdf4a370000200641086a41002900c4df4a370000200641002900bcdf4a3700000c010b4120102d2206450d11200641186a41002900bb884a370000200641106a41002900b3884a370000200641086a41002900ab884a370000200641002900a3884a3700000b41202104412021030c030b200229029402211d024020022802d401450d0020022802d001102f0b201d422088211e024020022802e401450d0020022802e001102f0b201ea72103201da721040c030b41dc88ca00413041f8b4ca001039000b200241013602cc01200242023702bc0120024184dcca003602b801200241013602b4022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a103a20022902cc02221d422088a7210320022802c8022106201da721040b2006450d020b200220063602b00220022003ad4220862004ad843702b4022002200241b0026a36029002200241023602cc01200242023702bc012002418490ca003602b801200241333602d402200241013602cc022002200241c8026a3602c801200220024190026a3602d0022002200241b4016a3602c802200241a0026a200241b8016a103a024020022802b402450d0020022802b002102f0b20022802a0022204450d0120022902a402211d200020043602002000201d3702040c0e0b200020033602002000201d3702040c0d0b200b41016a210b200c41046a220c201b470d000b2001280208210c200128021021190b200c201941306c6a2105200c21040240034020052004460d0120042d00002103200441306a2206210420034109470d000b2002200641546a2802002204360290020240024020022802a80120044d0d00200220022802a00120044102746a28020022043602a002200228029c0120044b0d01200241cc016a4101360200200242023702bc0120024184dcca003602b801200241013602b4022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a103a0c0c0b200241cc016a4101360200200242023702bc01200241e0dbca003602b801200241013602b4022002200241b0026a3602c801200220024190026a3602b002200241c8026a200241b8016a103a0c0b0b20022802940120044104746a220431000d4220862004350208844280808080c000520d070b200c201941306c6a210303402003200c460d04200c2d00002104200c41306a2205210c20044108470d000b200241286a200541546a221410d6030240200228022c2203450d00200341ffffffff01712003470d0e2003410374220a4100480d0e20022802282104200a102d220c450d082004200341146c6a21062003410274417c6a210b200c2103034020042802002105200341046a200441086a28020036020020032005360200200341086a2103200441146a22042006470d000b200a4103762110200b41027641016a21040c030b4104210c41002110410021040c020b41a48fca0041c80041ec8fca001055000b41f48eca00411e41948fca001055000b200c2004200241b8016a410041202004676b10a406024020044103742204450d00200c20046a210641012105200c2104200c21030340024002402005450d00200620046b41037620054d0d03200420054103746a21040c010b20062004460d020b200220033602a0020240200341046a2802002205200441046a280200470d002003280200220a2004280200220b460d04200a200b200510ea06450d040b200441086a210441002105200341086a22032006470d000b0b200241206a201410d603024020022802242204450d00200441146c2103200228022041106a2104024003400240024002400240024002402004417c6a2802000e0400030201000b20022004280200220536029002024020022802a80120054d0d00200220022802a00120054102746a28020022053602a002200228029c0120054b0d04200241013602cc01200242023702bc0120024184dcca003602b801200241013602b4022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a103a0c070b200241cc016a4101360200200242023702bc01200241e0dbca003602b801200241013602b4022002200241b0026a3602c801200220024190026a3602b002200241c8026a200241b8016a103a0c060b2002200428020022053602a0020240024020022802900120054d0d0020022802880120054101746a2d0001450d05200241cc016a4101360200200242023702bc01200241c4dcca003602b801200241013602b4022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a103a0c010b200241cc016a4101360200200242023702bc01200241a4dcca003602b801200241013602b4022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a103a0b20022802c8022104200020022902cc02370204200020043602000c090b2002200428020022053602a002200228027820054b0d02200241013602cc01200242023702bc0120024190dbca003602b801200241013602b4022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a103a20022802c8022205450d02200020022902cc02370204200020053602000c080b2002200428020022053602a00220022802840120054b0d01200241cc016a4101360200200242023702bc01200241c0dbca003602b801200241013602b4022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a103a20022802c8022104200020022902cc02370204200020043602000c070b201d428080808080608320022802940120054104746a220535020884200531000d42208684211d0b200441146a21042003416c6a22030d000c020b0b20022802c8022104200020022902cc02370204200020043602000c030b2010450d00200c102f0b2001280210220b41306c21042001280208220c41546a2103024003402004450d01200441506a21042003412c6a2105200341306a2206210320052d00004103470d000b200241186a200610d603200228021c2204450d0020022802182105200441286c210641002104034002400240024002400240200520046a220341186a2d00000e0401000302010b200341206a2802004101470d032003411c6a280200210a2002200341246a280200220336029002200a20034d0d03200241023602cc01200242023702bc01200241e4d7ca003602b801200241013602d402200241013602cc022002200a3602a0022002200241c8026a3602c8012002200241a0026a3602d002200220024190026a3602c802200241b0026a200241b8016a103a20022802b0022203450d03200020022902b402370204200020033602000c0c0b20022003411c6a28020022033602a002200228029c0120034b0d02200241cc016a4101360200200242023702bc0120024184dcca003602b801200241013602b4022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a103a20022802c8022104200020022902cc02370204200020043602000c0b0b2003411a6a2d0000450d012003410c6a2802002104200341146a2802002103200241b8016a41146a4101360200200220033602b402200220043602b002200241043602a402200242013702bc01200241cc90ca003602b8012002200241b0026a3602a0022002200241a0026a3602c801200241c8026a200241b8016a103a200041086a200241c8026a41086a280200360200200020022903c8023702000c0a0b200241b8016a2003411c6a10a90620022802b801450d00200020022903b801370200200041086a200241b8016a41086a2802003602000c090b2006200441286a2204470d000b0b02400240024002400240200228028401220441014b0d002002280278220441014b0d01200b41306c2104200c41546a2103024003402004450d01200441506a21042003412c6a2105200341306a2206210320052d0000410d470d000b200241106a200610d603200228021022042002280214411c6c6a210502400240034020042005460d032002200428020022033602a0020240200228027820034b0d00200241013602cc01200242023702bc0120024190dbca003602b801200241013602b4022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a103a20022802c80222030d070b200441046a2204280200450d01200241b8016a200420022802880120022802900110aa0620022d00b8014101460d02200441186a210420022d00b901450d000b4120102d2204450d0b200441186a41002900a5914a370000200441106a410029009d914a370000200441086a4100290095914a3700002004410029008d914a370000200042a08080808004370204200020043602000c0e0b4129102d2204450d0a200441286a41002d008c914a3a0000200441206a4100290084914a370000200441186a41002900fc904a370000200441106a41002900f4904a370000200441086a41002900ec904a370000200441002900e4904a370000200042a98080809005370204200020043602000c0d0b200020022902bc01370200200041086a200241c4016a2802003602000c0c0b200b41306c2104200c41546a2103024003402004450d01200441506a21042003412c6a2105200341306a2206210320052d0000410a470d000b200241086a200610d603200228020c2204450d002002280208220a2004411c6c6a210b02400240024002400340200a450d052002200a28020022043602a00220022802840120044d0d09200a280204450d01200241b8016a200a41046a20022802880120022802900110aa0620022d00b8014101460d0220022d00b9010d032002200a10af060240024020022802042204450d00200228020021032004410274210520022802a8012106034020022003280200220436029002200620044d0d07200220022802a00120044102746a28020022043602a002200228029c0120044d0d02201d428080808080608320022802940120044104746a220435020884200431000d42208684211d200341046a21032005417c6a22050d000b0b200a411c6a220a200b460d060c010b0b200241013602cc01200242023702bc0120024184dcca003602b801200241013602b4022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a103a0c090b412a102d2204450d0c200441286a41002f00d5914a3b0000200441206a41002900cd914a370000200441186a41002900c5914a370000200441106a41002900bd914a370000200441086a41002900b5914a370000200441002900ad914a370000200042aa808080a005370204200020043602000c0f0b200020022902bc01370200200041086a200241c4016a2802003602000c0e0b4120102d2204450d0a200441186a41002900a5914a370000200441106a410029009d914a370000200441086a4100290095914a3700002004410029008d914a370000200042a08080808004370204200020043602000c0d0b200241cc016a4101360200200242023702bc01200241e0dbca003602b801200241013602b4022002200241b0026a3602c801200220024190026a3602b002200241c8026a200241b8016a103a0c050b2000410036020002402002280274450d002002280270102f0b0240200228028001450d00200228027c102f0b0240200228028c01450d00200228028801102f0b0240200228029c012203450d0020022802940121042003410474210303400240200441046a280200450d002004280200102f0b200441106a2104200341706a22030d000b0b0240200228029801450d00200228029401102f0b024020022802a401450d0020022802a001102f0b200e450d0d200d102f0c0d0b200241cc016a4101360200200242013702bc01200241d490ca003602b801200241013602b402200220043602a0022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a103a200041086a200241c8026a41086a280200360200200020022903c8023702000c0a0b200241cc016a4101360200200242013702bc01200241dc90ca003602b801200241013602b402200220043602a0022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a103a200041086a200241c8026a41086a280200360200200020022903c8023702000c090b200020022902cc02370204200020033602000c080b200241cc016a4101360200200242023702bc01200241c0dbca003602b801200241013602b4022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a103a20022802c8022104200020022902cc02370204200020043602000c070b20022802c8022104200020022902cc02370204200020043602000c060b200241cc016a4101360200200242013702bc01200241c490ca003602b801200241343602b4022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a103a200041086a200241c8026a41086a280200360200200020022903c8023702000b2010450d04200c102f0c040b412d102d2204450d00200441256a41002900b9904a370000200441206a41002900b4904a370000200441186a41002900ac904a370000200441106a41002900a4904a370000200441086a410029009c904a37000020044100290094904a370000200042ad808080d005370204200020043602000c030b1036000b200241cc016a4102360200200241d4026a4101360200200242023702bc01200241e48eca003602b801200241013602cc022002200241c8026a3602c8012002200241b0016a3602d0022002200241ac016a3602c802200241b0026a200241b8016a103a200041086a200241b0026a41086a280200360200200020022903b0023702000c010b20022802c8022104200020022902cc02370204200020043602000b02402002280274450d002002280270102f0b0240200228028001450d00200228027c102f0b0240200228028c01450d00200228028801102f0b0240200228029c012203450d0020022802940121042003410474210303400240200441046a280200450d002004280200102f0b200441106a2104200341706a22030d000b0b0240200228029801450d00200228029401102f0b024020022802a401450d0020022802a001102f0b200e450d01200d102f0c010b20002004290200370200200041086a200441086a2802003602000240200e450d00200d102f0b02402015450d002016102f0b02402013450d002014102f0b02402011450d002012102f0b02402009450d00200941047421032007210403400240200441046a280200450d002004280200102f0b200441106a2104200341706a22030d000b0b02402008450d002007102f0b200f450d002010102f0b200241e0026a24000f0b1038000b971401187f23004190026b2202240002400240024002400240200028020022034190bdc600460d00200028020421040c010b41002104200241286a410041d80010e7061a2002410f6a220542003700002002420037010a41ec00102d2203450d0120034100360200200320022902083702042003410b6a2005290000370000200341136a200241276a41d90010e8061a20004100360204200020033602000b200141ff017121060240024002400240034041002105024020032f01062207450d0041002105410c21080340024020072005470d00200721050c020b200320056a2109200841086a2108200541016a210502404100417f4101200941086a2d0000220920064b1b20092006461b41016a0e03000401000b0b2005417f6a21050b02402004450d002004417f6a2104200320054102746a41ec006a28020021030c010b0b2000200028020841016a360208024002400240200341066a22082f01002204410b490d0020034190bdc600460d04200241286a410041d80010e7061a200241003a001941ec00102d220a450d07200a4100360200200a410036000f200a4200370007200a20022f01183b0005200a41136a200241276a41d90010e8061a2003410e6a2d0000210b2003280248210c2003280244210d200a41086a2003410f6a20032f010641796a220410e8062106200a41146a200341cc006a200441037410e8062107200341063b0106200a20043b010620054107490d0120062005417a6a22086a2006200541796a22056a2206200441ffff037120056b10e9061a200620013a0000200720084103746a200720054103746a2204200a41066a22082f010020056b41037410e9061a200441013602000c020b200341086a2208200541016a22066a200820056a2208200420056b10e9061a200820013a0000200341146a220820064103746a200820054103746a220820032f010620056b41037410e9061a20084101360200200320032f010641016a3b01060c050b200341086a2204200541016a22066a200420056a220420082f010020056b10e9061a200420013a0000200341146a220420064103746a200420054103746a220420082f010020056b41037410e9061a200441013602000b200820082f010041016a3b01000240200328020022070d004100210e0c030b200341046a2103200241276a41016a210f200241a8016a2110200241a0016a211120024198016a211220024190016a211320024180016a41086a21144100210e034020032f0100210602400240024020072f01062203410b490d00200f410041d80010e7061a200241003a0019200220022f01183b0108200241b7016a200241276a41d90010e8061a20104200370300201142003703002012420037030020134200370300201442003703002002420037038001419c01102d2208450d08200841003602002008410036000f20084200370007200820022f01083b0005200841136a200241b7016a41d90010e8061a20084194016a20102903003702002008418c016a201129030037020020084184016a2012290300370200200841fc006a2013290300370200200841f4006a2014290300370200200820022903800137026c200741c8006a2802002115200741c4006a28020021162007410e6a2d00002117200841086a2007410f6a20072f0106220541796a220310e8062118200841146a200741cc006a200341037410e8062119200841ec006a20074188016a2005417a6a220941027410e8062101200741063b0106200820033b010602402009450d00410021032001210503402005280200220420033b010420042008360200200541046a21052009200341016a2203470d000b0b20064107490d0120182006417a6a22056a2018200641796a22036a220420082f010620036b10e9061a2004200b3a0000201920054103746a201920034103746a220420082f010620036b41037410e9061a2004200d3602002004200c360204200820082f010641016a22043b01062006410274220b20016a416c6a200120054102746a2209200441ffff0371220620056b41027410e9061a2009200a36020020062005490d022008200b6a41d4006a2105034020052802002204200341016a22033b010420042008360200200541046a210520032006490d000c030b0b200741086a2208200641016a22056a200820066a2208200320066b220410e9061a2008200b3a0000200741146a220820054103746a200820064103746a2208200441037410e9061a2008200d3602002008200c3602042007200341016a22033b01062006410274200741ec006a22086a41086a200820054102746a2208200341ffff0371220420056b41027410e9061a2008200a360200200620044f0d0620072005417f6a22034102746a41f0006a2105034020052802002208200341016a22033b010420082007360200200541046a210520032004490d000c070b0b200741086a2205200641016a22036a200520066a220520072f0106220420066b220910e9061a2005200b3a0000200741146a220520034103746a200520064103746a2205200941037410e9061a2005200d3602002005200c3602042007200441016a22053b010620064102742201200741ec006a22046a41086a200420034102746a2209200541ffff0371220420036b41027410e9061a2009200a360200200620044f0d00200720016a41f0006a2103034020032802002205200641016a22063b010420052007360200200341046a210320042006470d000b0b200e41016a210e0240200728020022050d002008210a2015210c2016210d2017210b0c040b200741046a2103200521072017210b2016210d2015210c2008210a0c000b0b200320086a42013702000c020b4195b4ca00412d41f8b4ca001039000b200241276a41016a410041d80010e7061a2002410f6a220342003700002002420037010a200220022902083703182002200329000037001f200241b7016a200241276a41d90010e8061a200241a8016a22054200370300200241a0016a2208420037030020024198016a2204420037030020024190016a2206420037030020024188016a220742003703002002420037038001419c01102d2203450d0120034100360200200320022903183702042003410b6a200229001f370000200341136a200241b7016a41d90010e8061a20034194016a20052903003702002003418c016a200829030037020020034184016a2004290300370200200341fc006a2006290300370200200341f4006a2007290300370200200320022903800137026c20032000280200220536026c2000200336020020002000280204220841016a360204200541003b0104200520033602002008200e470d0220032f01062205410a4b0d03200320054103746a220841186a200c360200200841146a200d360200200320056a41086a200b3a00002003200541016a22054102746a41ec006a200a360200200320053b0106200a20053b0104200a20033602000b20024190026a24000f0b1036000b4196b3ca00413041f8b4ca001039000b41c6b3ca00412741f8b4ca001039000bb02711067f017e017f017e017f017e027f017e017f017e017f017e017f017e157f067e027f2001410c6a28020021022001280208210302400240200141106a28020022040d0041002105410021064100210742002108410421094200210a4104210b4200210c4104210d41002101410021044104210e4200210f4104211042002111410421124200211341042114420021150c010b410021074100210641002105410021164100211741002118410021194100211a4100211b4100211c4100210102400340201d21142001211e024020032004417f6a220441306c6a22012d000022124110470d002014211d201e21010c020b200128002c211f200128002821202001280024212120012800202122200128001c2123200128001821242001280014212520012800102126200129000821082001280004210e4101210102400240024002400240024002402012417e6a2210410b4b2227450d00410121280c010b200e211d41012128410121294101212a4101210d410121094101210b0240024002400240024002400240024002400240024002400240024002400240024020100e0c000102030405061607150809000b0240201c0d00201e21012014211d200e211c2008212b0c160b0240202b422088a72201450d002001410474211d201c210103400240200141046a280200450d002001280200102f0b200141106a2101201d41706a221d0d000b0b4100210b41012101202ba7450d0f201c102f0c0f0b0240201b0d00201e21012014211d200e211b2008210f0c150b0240200f422088a72201450d00200141286c211d201b210103400240200141046a280200450d002001280200102f0b0240200141106a280200450d002001410c6a280200102f0b200141286a2101201d41586a221d0d000b0b4100210941012101200fa7450d0d201b102f0c0d0b201a450d0b202ca7450d0b201a102f0c0b0b2019450d09202da7450d092019102f0c090b2018450d072011a7450d072018102f0c070b024020170d00201e21012014211d200e21172008210c0c110b0240200c422088a72201450d00201720014104746a21292017210d03400240200d280208221d450d00200d2802002101201d410474211d0340024020012d00004109470d000240200141046a220b280200220928020441ffffffff0371450d002009280200102f200b28020021090b2009102f0b200141106a2101201d41706a221d0d000b0b200d41106a21010240200d41046a280200450d00200d280200102f0b2001210d20012029470d000b0b4101212841002101200ca7450d052017102f0c050b024020160d00201e21012014211d200e21162008210a0c100b0240200a422088a72201450d00200141146c211d2016210103400240200141046a280200450d002001280200102f0b200141146a2101201d416c6a221d0d000b0b4100212841012101200aa7450d032016102f0c030b02402007450d000240202e422088a72201450d0020072001411c6c6a21292007210d03400240200d2802042201450d000240200d410c6a280200221d450d00201d410474211d0340024020012d00004109470d000240200141046a220b280200220928020441ffffffff0371450d002009280200102f200b28020021090b2009102f0b200141106a2101201d41706a221d0d000b0b200d41086a280200450d00200d280204102f0b200d411c6a21010240200d41146a280200450d00200d280210102f0b2001210d20012029470d000b0b202ea7450d002007102f0b4100212941012101200e21072008212e410121280c0a0b02402006450d000240202f422088a72201450d002006200141186c6a21292006210d03400240200d41046a280200450d00200d280200102f0b0240200d41146a280200221d450d00200d28020c2101201d410474211d0340024020012d00004109470d000240200141046a220b280200220928020441ffffffff0371450d002009280200102f200b28020021090b2009102f0b200141106a2101201d41706a221d0d000b0b200d41186a21010240200d41106a280200450d00200d28020c102f0b2001210d20012029470d000b0b202fa7450d002006102f0b4100212a41012101200e21062008212f41012128410121290c0a0b02402005450d0002402030422088a72201450d0020052001411c6c6a21292005210d03400240200d2802042201450d000240200d410c6a280200221d450d00201d410474211d0340024020012d00004109470d000240200141046a220b280200220928020441ffffffff0371450d002009280200102f200b28020021090b2009102f0b200141106a2101201d41706a221d0d000b0b200d41086a280200450d00200d280204102f0b200d411c6a21010240200d41146a280200450d00200d280210102f0b2001210d20012029470d000b0b2030a7450d002005102f0b4100210d41012101200e21052008213041012128410121294101212a0c0a0b2008210a200e21160c060b2008210c200e21170c050b201e21012014211d200e2118200821110c090b201e21012014211d200e21192008212d0c080b201e21012014211d200e211a2008212c0c070b2008210f200e211b41012128410121294101212a4101210d4101210b0c050b2008212b200e211c41012128410121294101212a4101210d410121090c040b410121290b4101212a0b4101210d0b410121094101210b0b2008422088a721312008a7213202400240024020270d00024002400240024002400240024002400240024020100e0c000102030405060a070a0809000b200b450d0b02402031450d002031410474211d200e210103400240200141046a280200450d002001280200102f0b200141106a2101201d41706a221d0d000b0b2032450d0b0c0a0b2009450d0a02402031450d00203141286c211d200e210103400240200141046a280200450d002001280200102f0b0240200141106a280200450d002001410c6a280200102f0b200141286a2101201d41586a221d0d000b0b20320d090c0a0b41000d0920320d080c090b41000d0820320d070c080b41000d0720320d060c070b2001450d0602402031450d00200e20314104746a2110200e210d03400240200d280208221d450d00200d2802002101201d410474211d0340024020012d00004109470d000240200141046a220b280200220928020441ffffffff0371450d002009280200102f200b28020021090b2009102f0b200141106a2101201d41706a221d0d000b0b200d41106a21010240200d41046a280200450d00200d280200102f0b2001210d20012010470d000b0b20320d050c060b2028450d0502402031450d00203141146c211d200e210103400240200141046a280200450d002001280200102f0b200141146a2101201d416c6a221d0d000b0b20320d040c050b2029450d0402402031450d00200e2031411c6c6a2110200e210d03400240200d2802042201450d000240200d410c6a280200221d450d00201d410474211d0340024020012d00004109470d000240200141046a220b280200220928020441ffffffff0371450d002009280200102f200b28020021090b2009102f0b200141106a2101201d41706a221d0d000b0b200d41086a280200450d00200d280204102f0b200d411c6a21010240200d41146a280200450d00200d280210102f0b2001210d20012010470d000b0b20320d030c040b202a450d0302402031450d00200e203141186c6a2110200e210d03400240200d41046a280200450d00200d280200102f0b0240200d41146a280200221d450d00200d28020c2101201d410474211d0340024020012d00004109470d000240200141046a220b280200220928020441ffffffff0371450d002009280200102f200b28020021090b2009102f0b200141106a2101201d41706a221d0d000b0b200d41186a21010240200d41106a280200450d00200d28020c102f0b2001210d20012010470d000b0b20320d020c030b200d450d0202402031450d00200e2031411c6c6a2110200e210d03400240200d2802042201450d000240200d410c6a280200221d450d00201d410474211d0340024020012d00004109470d000240200141046a220b280200220928020441ffffffff0371450d002009280200102f200b28020021090b2009102f0b200141106a2101201d41706a221d0d000b0b200d41086a280200450d00200d280204102f0b200d411c6a21010240200d41146a280200450d00200d280210102f0b2001210d20012010470d000b0b20320d010c020b02402012410e4b0d00201e21012014211d0240024002400240024002400240024002400240024020120e0f0001020304040405060e070e08090a000b20320d0b0c0c0b02402032450d00200e102f0b2025450d0b2026102f0c0b0b02402031450d002031410474211d200e210103400240200141046a280200450d002001280200102f0b200141106a2101201d41706a221d0d000b0b20320d090c0a0b2031450d00203141286c211d200e210103400240200141046a280200450d002001280200102f0b0240200141106a280200450d002001410c6a280200102f0b200141286a2101201d41586a221d0d000b0b20320d070c080b02402031450d00200e20314104746a2110200e210d03400240200d280208221d450d00200d2802002101201d410474211d0340024020012d00004109470d000240200141046a220b280200220928020441ffffffff0371450d002009280200102f200b28020021090b2009102f0b200141106a2101201d41706a221d0d000b0b200d41106a21010240200d41046a280200450d00200d280200102f0b2001210d20012010470d000b0b20320d060c070b02402031450d00203141146c211d200e210103400240200141046a280200450d002001280200102f0b200141146a2101201d416c6a221d0d000b0b20320d050c060b02402031450d00200e2031411c6c6a2110200e210d03400240200d2802042201450d000240200d410c6a280200221d450d00201d410474211d0340024020012d00004109470d000240200141046a220b280200220928020441ffffffff0371450d002009280200102f200b28020021090b2009102f0b200141106a2101201d41706a221d0d000b0b200d41086a280200450d00200d280204102f0b200d411c6a21010240200d41146a280200450d00200d280210102f0b2001210d20012010470d000b0b20320d040c050b02402031450d00200e203141186c6a2110200e210d03400240200d41046a280200450d00200d280200102f0b0240200d41146a280200221d450d00200d28020c2101201d410474211d0340024020012d00004109470d000240200141046a220b280200220928020441ffffffff0371450d002009280200102f200b28020021090b2009102f0b200141106a2101201d41706a221d0d000b0b200d41186a21010240200d41106a280200450d00200d28020c102f0b2001210d20012010470d000b0b20320d030c040b02402031450d00200e2031411c6c6a2110200e210d03400240200d2802042201450d000240200d410c6a280200221d450d00201d410474211d0340024020012d00004109470d000240200141046a220b280200220928020441ffffffff0371450d002009280200102f200b28020021090b2009102f0b200141106a2101201d41706a221d0d000b0b200d41086a280200450d00200d280204102f0b200d411c6a21010240200d41146a280200450d00200d280210102f0b2001210d20012010470d000b0b20320d020c030b0240200e450d002032450d00200e102f0b02402025450d0002402023450d002023410c6c211d202521010340024020012802002209450d00200141046a280200450d002009102f0b2001410c6a2101201d41746a221d0d000b0b2024450d002025102f0b2021450d020240201f450d002021201f4104746a210e2021210d0340200d220b41106a210d0240200b2802042201450d000240200b410c6a280200221d450d00201d410c6c211d0340024020012802002209450d00200141046a280200450d002009102f0b2001410c6a2101201d41746a221d0d000b0b200b41086a280200450d00200b280204102f0b200d200e470d000b0b2020450d022021102f0c020b02402032450d00200e102f0b02402025450d002024450d002025102f0b2021450d012022102f0c010b200e102f0b201e21012014211d0b20040d000b410021040b200a420020161b2115200c420020171b21082011420020181b2113202d420020191b210a202c4200201a1b2111200f4200201b1b210c202b4200201c1b210f2016410420161b21142017410420171b21092018410420181b21122019410420191b210b201a4104201a1b2110201b4104201b1b210d201c4104201c1b210e0b4104410010cd0420004188016a200436020020004184016a20023602002000200336028001200041f8006a2030420020051b22303e020020002005410420051b360274200041ec006a202f420020061b222f3e020020002006410420061b360268200041e0006a202e420020071b222e3e020020002007410420071b36025c200041d8006a201d36020020002001360254200041d0006a20154220883e0200200041cc006a20153e020020002014360248200041c4006a20084220883e0200200041c0006a20083e02002000200936023c200041386a20134220883e0200200041346a20133e0200200020123602302000412c6a200a4220883e0200200041286a200a3e02002000200b360224200041206a20114220883e02002000411c6a20113e020020002010360218200041146a200c4220883e0200200041106a200c3e02002000200d36020c2000200f4220883e02082000200f3e02042000200e360200200041fc006a20304220883e0200200041f0006a202f4220883e0200200041e4006a202e4220883e02000bbb05010e7f230041106b22022400024002400240024020012802004101470d00200141106a2d000021032001410c6a2802002104200141086a280200210520012f0112210620012d0011210720012802042108200241086a200010d60302400240200228020c2209450d0020022802082101200941047441706a410476210a0240200741ff0171220b4104460d004100210c200341ff0171210d0340200c2109024020012d000c200d470d0020012802082004470d0002402001280200220c2008460d002004450d002004210e2008210f0340200c2d0000200f2d0000470d02200c41016a210c200f41016a210f200e417f6a220e0d000b0b20012d000d220c200b470d00200c4104470d040b200141106a2101200941016a210c2009200a470d000c020b0b4100210c200341ff0171210d0340200c2109024020012d000c200d470d0020012802082004470d0002402001280200220c2008460d002004450d002004210e2008210f0340200c2d0000200f2d0000470d02200c41016a210c200f41016a210f200e417f6a220e0d000b0b20012d000d4104460d030b200141106a2101200941016a210c2009200a470d000b0b024020002802082201200041046a280200470d00200141016a22092001490d042001410174220c2009200c20094b1b220941ffffffff00712009470d04200941047422094100480d040240024020010d002009102d21010c010b200028020020014104742009103121010b2001450d0320002001360200200041046a2009410476360200200028020821010b200028020020014104746a220120063b010e200120073a000d200120033a000c2001200436020820012005360204200120083602002000200028020841016a3602082002200010d6032002280204417f6a21090c040b2005450d032008102f0c030b200128020421090c020b1036000b1038000b200241106a240020090bec2103137f017e1a7f230041306b220224002002410436020020012802042103200128020021044101210502400240024002400240200128020822060d0041002107410121080c010b4130102d2207450d012007200636000c200720033600082007200436000420022007360200200741023a000041002108410121070b200141106a2802002109200128020c210a02400240200141146a280200220b0d002007210c0c010b2007410174220c200741016a220d200c200d4b1b220c41306c210d0240024020070d00200d102d210d0c010b2002280200200741306c200d1031210d0b200d450d012002200d360200200d200741306c6a220d41033a0000200d20022f002d3b0001200d200b36000c200d2009360008200d200a360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a290200370200200741016a2107410021050b2001411c6a280200210e2001280218210f4100211002400240200141206a28020022110d00410021120c010b02402007200c470d0041000d0341000d03200c410174220d200c41016a2213200d20134b1bad42307ea7220d4100480d0302400240200c0d00200d102d210c0c010b2002280200200c41306c200d1031210c0b200c450d022002200c360200200d41306e210c0b2002280200200741306c6a220d41043a0000200d20022f002d3b0001200d201136000c200d200e360008200d200f360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a29020037020041012112200741016a21070b200141286a28020021132001280224211402402001412c6a2802002211450d0002402007200c470d0041000d03200c410174220d200c41016a2210200d20104b1bad42307e2215422088a70d032015a7220d4100480d0302400240200c0d00200d102d210c0c010b2002280200200c41306c200d1031210c0b200c450d022002200c360200200d41306e210c0b2002280200200741306c6a220d41053a0000200d20022f002d3b0001200d201136000c200d2013360008200d2014360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a29020037020041012110200741016a21070b200141346a28020021162001280230211702400240200141386a28020022110d00410021180c010b02402007200c470d0041000d03200c410174220d200c41016a2219200d20194b1bad42307e2215422088a70d032015a7220d4100480d0302400240200c0d00200d102d210c0c010b2002280200200c41306c200d1031210c0b200c450d022002200c360200200d41306e210c0b2002280200200741306c6a220d41063a0000200d20022f002d3b0001200d201136000c200d2016360008200d2017360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a29020037020041012118200741016a21070b200141c0006a280200211a200128023c211b4101211902400240200141c4006a280200221c0d004101211d0c010b02402007200c470d0041000d03200c410174220d200c41016a2211200d20114b1bad42307e2215422088a70d032015a7220d4100480d0302400240200c0d00200d102d210c0c010b2002280200200c41306c200d1031210c0b200c450d022002200c360200200d41306e210c0b2002280200200741306c6a220d41073a0000200d20022f002d3b0001200d201c36000c200d201a360008200d201b360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a290200370200200741016a21074100211d0b200141cc006a280200211e2001280248211f0240200141d0006a2802002220450d0002402007200c470d0041000d03200c410174220d200c41016a2211200d20114b1bad42307e2215422088a70d032015a7220d4100480d0302400240200c0d00200d102d210c0c010b2002280200200c41306c200d1031210c0b200c450d022002200c360200200d41306e210c0b2002280200200741306c6a220d41083a0000200d20022f002d3b0001200d202036000c200d201e360008200d201f360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a200241046a41086a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a290200370200200741016a2107410021190b41012121024020012802544101470d00200141d8006a280200211102402007200c470d0041000d03200c410174220d200c41016a2222200d20224b1bad42307e2215422088a70d032015a7220d4100480d0302400240200c0d00200d102d210c0c010b2002280200200c41306c200d1031210c0b200c450d022002200c360200200d41306e210c0b2002280200200741306c6a220d41093a0000200d20022f002d3b0001200d2011360204200d2002290204370208200d41036a2002412f6a2d00003a0000200d41106a2002410c6a290200370200200d41186a200241046a41106a290200370200200d41206a200241046a41186a290200370200200d41286a200241046a41206a290200370200200741016a21070b200141e0006a2802002123200128025c21220240200141e4006a2802002224450d0002402007200c470d0041000d03200c410174220d200c41016a2211200d20114b1bad42307e2215422088a70d032015a7220d4100480d0302400240200c0d00200d102d210c0c010b2002280200200c41306c200d1031210c0b200c450d022002200c360200200d41306e210c0b2002280200200741306c6a220d410a3a0000200d20022f002d3b0001200d202436000c200d2023360008200d2022360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a290200370200200741016a2107410021210b200141ec006a2802002125200128026821264101211102400240200141f0006a28020022270d00410121280c010b02402007200c470d0041000d03200c410174220d200c41016a2229200d20294b1bad42307e2215422088a70d032015a7220d4100480d0302400240200c0d00200d102d210c0c010b2002280200200c41306c200d1031210c0b200c450d022002200c360200200d41306e210c0b2002280200200741306c6a220d410c3a0000200d20022f002d3b0001200d202736000c200d2025360008200d2026360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a290200370200200741016a2107410021280b200141f8006a280200212a200128027421290240200141fc006a280200222b450d0002402007200c470d0041000d03200c410174220d200c41016a2211200d20114b1bad42307e2215422088a70d032015a7220d4100480d0302400240200c0d00200d102d210c0c010b2002280200200c41306c200d1031210c0b200c450d022002200c360200200d41306e210c0b2002280200200741306c6a220d410d3a0000200d20022f002d3b0001200d202b36000c200d202a360008200d2029360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a290200370200200741016a2107410021110b20014184016a280200212c200128028001210d02400240200c20076b20014188016a28020041306c222d41306d222e490d00200228020021010c010b2007202e6a22012007490d02200c410174222f2001202f20014b1bad42307e2215422088a70d022015a7222f4100480d0202400240200c0d00202f102d21010c010b2002280200200c41306c202f103121010b2001450d0120022001360200202f41306e210c0b2001200741306c6a200d202d10e8061a0240202c450d00200d102f0b418006102d220d450d002000200136020820004280c2cdeb16370200200041106a2007202e6a3602002000410c6a200c360200200d102f2011450d020240202b450d002029202b411c6c6a2111202921000340024020002802042201450d0002402000410c6a2802002207450d00200741047421070340024020012d00004109470d000240200141046a220d280200220c28020441ffffffff0371450d00200c280200102f200d280200210c0b200c102f0b200141106a2101200741706a22070d000b0b200041086a280200450d002000280204102f0b2000411c6a21010240200041146a280200450d002000280210102f0b2001210020012011470d000b0b202a450d022029102f0c020b1036000b1038000b02402028450d0002402027450d002026202741186c6a21112026210003400240200041046a280200450d002000280200102f0b0240200041146a2802002207450d00200028020c2101200741047421070340024020012d00004109470d000240200141046a220d280200220c28020441ffffffff0371450d00200c280200102f200d280200210c0b200c102f0b200141106a2101200741706a22070d000b0b200041186a21010240200041106a280200450d00200028020c102f0b2001210020012011470d000b0b2025450d002026102f0b02402021450d0002402024450d0020222024411c6c6a2111202221000340024020002802042201450d0002402000410c6a2802002207450d00200741047421070340024020012d00004109470d000240200141046a220d280200220c28020441ffffffff0371450d00200c280200102f200d280200210c0b200c102f0b200141106a2101200741706a22070d000b0b200041086a280200450d002000280204102f0b2000411c6a21010240200041146a280200450d002000280210102f0b2001210020012011470d000b0b2023450d002022102f0b02402019450d0002402020450d00202041146c2107201f210103400240200141046a280200450d002001280200102f0b200141146a21012007416c6a22070d000b0b201e450d00201f102f0b0240201d450d000240201c450d00201b201c4104746a2111201b21000340024020002802082207450d0020002802002101200741047421070340024020012d00004109470d000240200141046a220d280200220c28020441ffffffff0371450d00200c280200102f200d280200210c0b200c102f0b200141106a2101200741706a22070d000b0b200041106a21010240200041046a280200450d002000280200102f0b2001210020012011470d000b0b201a450d00201b102f0b02402016410047201841017371450d002017102f0b02402013410047201041017371450d002014102f0b0240200e410047201241017371450d00200f102f0b02402005450d000240200b450d00200b41286c2107200a210103400240200141046a280200450d002001280200102f0b0240200141106a280200450d002001410c6a280200102f0b200141286a2101200741586a22070d000b0b2009450d00200a102f0b02402008450d0002402006450d00200641047421072004210103400240200141046a280200450d002001280200102f0b200141106a2101200741706a22070d000b0b2003450d002004102f0b200241306a24000bf70203037f017e017f410121020240200041086a2802002203417f6a220420034f0d00200420034b0d00200028020020044104746a220329020421052003200141016aad3702042005a721042005422088a721030240024002400240200041086a28020022024101460d002002450d0120002802002002417e6a4104746a22022802042004470d002002200228020820036a360208410021020c040b410021022003450d030240200041146a2802002202200041106a280200470d00200241016a22012002490d03200241017422062001200620014b1b220141ffffffff01712001470d03200141037422014100480d030240024020020d002001102d21020c010b200028020c20024103742001103121020b2002450d022000200236020c200041106a2001410376360200200028021421020b200028020c20024103746a22022003360204200220043602002000200028021441016a36021441000f0b41c5bdca00413f4184beca001055000b1036000b1038000b20020b911302147f027e23004180026b220424000240024020014115490d0041012105410121060240024002400340200121072000210820052006714101732109024002400240024002400240034002400240024002402003450d00024020054101710d002000200110a5062003417f6a21030b2001410276220a41036c210b200a410174210c4100210d024020014132490d00200b200b417f6a220d2000200b4103746a280200220e2000200d4103746a280200220f4922101b2211200b41016a2212200d200b20101b200020124103746a280200220b200f200e20101b220d49220f1b200b200d200f1b200020114103746a2802004922131b210b200c200c417f6a220d2000200c4103746a28020022112000200d4103746a280200221249220e1b2214200c4101722206200d200c200e1b200020064103746a280200220c20122011200e1b220d4922111b200c200d20111b200020144103746a2802004922141b210c200a200a417f6a22122000200a4103746a2802002206200020124103746a280200221549220d1b2216200a41016a22172012200a200d1b200020174103746a280200220a20152006200d1b22064922121b200a200620121b200020164103746a2802004922061b210a41024101200d1b200d20121b20066a200e6a20116a20146a20106a200f6a20136a210d0b200d2000200c4103746a280200220e2000200a4103746a280200220f4922106a2000200b4103746a280200220d200f200e20101b221149220f6a210e200d2011200f1b2000200c200a20101b220d4103746a280200490d01200b200a200c20101b200f1b210d0c020b2000200110c5060c0f0b200e41016a220e410c490d0002402001410176220b450d00200020014103746a41786a210a2000210c0340200c2902002118200c200a290200370200200a2018370200200c41086a210c200a41786a210a200b417f6a220b0d000b0b2001200d417f736a210d4101210a0c010b200e45210a0b0240200a452009724101710d002000200110c6060d0d0b2002450d02200d20014f0d01024020022802002000200d4103746a220a2802004f0d0020002108200121070c040b200029020021182000200a290200370200200a2018370200200041786a210f200041086a211120002902002218a721104100210c2001210b03400240200c200b417f6a220d4f0d002011200c4103746a210a0340200a28020020104b0d01200a41086a210a200d200c41016a220c470d000b200d210c0b200f200b4103746a210a02400340200c200b417f6a220b4f0d01200a280200210d200a41786a220e210a200d20104b0d000b2011200c4103746a220a2902002119200a200e41086a220d290200370200200d2019370200200c41016a210c0c010b0b2000201837020002402001200c41016a220a490d002000200a4103746a21002001200a6b220141154f0d010c0c0b0b200a2001104b000b41d4bbca00200d2001103b000b2007450d010b200d20074f0d012008290200211820082008200d4103746a220a290200370200200a2018370200200841086a210e20082902002219a72111410021142007417f6a2210450d02200e210a0340200a28020020114f0d03200a41086a210a2010201441016a2214470d000b201021140c020b4188bbca0041004100103b000b4198bbca00200d2007103b000b200820074103746a210c2010210b02400340200c210d200b220a20144d22060d01200a417f6a210b200d41786a220c28020020114f0d000b0b0240200a2014490d002010200a490d0241800121054100210b410021014100210c4100210f4180012109200e20144103746a2215211003400240200d20106b220a4187104b22130d00200a410376220a41807f6a200a2001200b49200f200c49220e7222001b210a02402000450d002009200a200e1b2109200a2005200e1b21050c010b200a200a41017622096b21050b0240200f200c470d00024020090d002004220c210f0c010b4100210a2004220f210c2010210e0340200c200a3a0000200c200e28020020114f6a210c200e41086a210e2009200a41016a220a470d000b0b02402001200b470d00024020050d0020044180016a220b21010c010b200d41786a210a4100210e20044180016a2201210b0340200b200e3a0000200b200a2802002011496a210b200a41786a210a2005200e41016a220e470d000b0b0240200b20016b220a200c200f6b220e200e200a4b1b2212450d002010200f2d00004103746a220a2902002118200a200d20012d0000417f734103746a290200370200024020124101460d004100210a0340200d2001200a6a220e2d0000417f734103746a2010200f200a6a41016a22002d00004103746a290200370200201020002d00004103746a200d200e41016a2d0000417f734103746a290200370200200a41026a210e200a41016a2200210a200e2012490d000b200120006a2101200f20006a210f0b200d20012d0000417f734103746a2018370200200141016a2101200f41016a210f0b200d20054103746b200d2001200b461b210d201020094103746a2010200f200c461b211020130d000b02400240200f200c4f0d00200d210a03402010200c417f6a220c2d00004103746a220b2902002118200b200a41786a220a290200370200200a2018370200200f200c490d000c020b0b2010210a2001200b4f0d000340200a2902002118200a200d200b417f6a220b2d0000417f734103746a220c290200370200200c2018370200200a41086a210a2001200b490d000b0b200820193702002007200a20156b41037620146a22014d0d032008200820014103746a220a290200370200200a2019370200200720016b220c450d04200c20012001200c4b1b210b2007410376210d200a41086a2100024002402001200c417f6a220c490d002000200c200a200310d404200821000c010b200820012002200310d404200a2102200c21010b200b200d4f2105200141154f0d010c050b0b2014200a104b000b200a2010104a000b4198bbca0020012007103b000b41a8bbca00411c41c4bbca001039000b20014102490d00200041786a21104100210e4101210b0340200b410374210c200b417f6a210a200b41016a210b02402000200c6a220d2802002000200a4103746a220f2802004f0d00200d2902002118200d200f2902003702000240200a450d00200e210c2010210a200d41706a2802002018a7220d4d0d00024002400340200a41086a200a290200370200200c4101460d01200c417f6a210c200a41786a220a280200200d4b0d000c020b0b4100210c0b2000200c4103746a210f0b200f20183702000b200e41016a210e201041086a2110200b2001470d000b0b20044180026a24000bd60402097f017e230041306b22022400200241106a2203200141246a290200370300200241086a22042001411c6a29020037030020022001290214370300200241186a41106a2205200141106a280200360200200241186a41086a2206200141086a290200370300200220012902003703182000200241186a10d1042107024002400240200041206a28020022082000411c6a280200470d00200841016a22092008490d022008410174220a2009200a20094b1b220941ffffffff03712009470d02200941027422094100480d020240024020080d002009102d21080c010b200028021820084102742009103121080b2008450d01200020083602182000411c6a2009410276360200200028022021080b200028021820084102746a20073602002000200028022041016a3602202005200329030037030020062004290300370300200220022903003703180240200041f0006a22032802002208200041ec006a280200470d00200841016a22042008490d02200841017422052004200520044b1bad42187e220b422088a70d02200ba722044100480d020240024020080d002004102d21080c010b2000280268200841186c2004103121080b2008450d0120002008360268200041ec006a200441186e360200200041f0006a28020021080b2000280268200841186c6a22082002290318370200200841106a200241186a41106a290300370200200841086a200241186a41086a29030037020020032003280200220841016a360200024020012d002c450d0020004101360254200041d8006a20083602000b200241306a24000f0b1036000b1038000b927a05077f017e217f037e147f23002203210420034180096b416071220324000240024002404110102d2205450d00200541063a00004120102d2206450d00200641063a001020064100360204200620032f00f0053b00012006412d3a0000200641036a200341f2056a2d00003a0000024020052d00004109470d0002402005280204220728020441ffffffff0371450d002007280200102f200528020421070b2007102f0b2005102f200141106a28020041306c2105200128020841546a210702400340024020050d004110102d2207450d0320074180023b010c200742828080802037020420072006360200200720032f01d0033b010e0240200128021022052001410c6a280200470d00200541016a22082005490d06200541017422092008200920084b1bad42307e220a422088a70d06200aa722084100480d060240024020050d002008102d21050c010b2001280208200541306c2008103121050b2005450d04200120053602082001410c6a200841306e360200200128021021050b2001280208200541306c6a220520032f00e0043b0001200541073a0000200542818080801037000820052007360004200520032902f005370210200541036a200341e2046a2d00003a0000200541186a200341f8056a290200370200200541206a20034180066a290200370200200541286a200341f0056a41186a2902003702002001200128021041016a220b3602104100210c0c020b200541506a21052007412c6a2108200741306a2209210720082d00004107470d000b200320032f01d0033b01f0050240200941086a22072802002205200941046a280200470d00200541016a22082005490d042005410174220d2008200d20084b1b220841ffffffff00712008470d04200841047422084100480d040240024020050d002008102d21050c010b200928020020054104742008103121050b2005450d0220092005360200200941046a2008410476360200200941086a28020021050b200928020020054104746a22054180023b010c200542828080802037020420052006360200200520032f01f0053b010e2007200728020041016a360200200341c8006a200910d603200328024c417f6a210c2001280210210b0b200b41306c21052001280208220e41546a210702400340410021082005450d01200541506a21052007412c6a2109200741306a2206210720092d00004103470d000b200641086a2802002205450d00200541286c2107200628020041186a2105410021080340200820052d0000456a2108200541286a2105200741586a22070d000b0b200b41306c2105200e41546a210702400340410021092005450d01200541506a21052007412c6a2106200741306a220d210720062d00004103470d000b200d41086a2802002205450d00200541286c2107200d28020041186a2105410021090340200920052d0000456a2109200541286a2105200741586a22070d000b0b200b41306c2105200e415c6a2107024003404100210f024020050d00410021050c020b200541506a2105200741246a2106200741306a220d210720062d00004104470d000b200d28020021050b200341003602e0040240024002400240200520096a220e0d0041042110410021110c010b0240024002402008450d00200342003703f005410021050c010b200341f0056a4100200110c80620032802f405210520032802f0054101470d00200341f8056a290300210a024020032802e0042207450d0020032802e404450d002007102f0b2003200a3702e404200320053602e00441002111410421104100210f0c010b4104102d2210450d042010200536020002400240200e4102490d000240024020084102490d00200342003703f0054100210d0c010b200341f0056a4101200110c80620032802f405210d20032802f0054101470d00200341f8056a290300210a024020032802e004450d0020032802e404450d0020032802e004102f0b2003200a3702e4042003200d3602e0040c010b410221064104210741012109410121110340200941016a2105024020092011470d0020062005200620054b1b220b41ffffffff0371200b470d0a200b410274220b4100480d0a20102007200b10312210450d08200b41027621110b201020076a200d360200024002402005200e4f0d000240200820054d0d00200342003703f0054100210d0c020b200341f0056a2005200110c80620032802f405210d20032802f0054101470d0120032903f805210a024020032802e004450d0020032802e404450d0020032802e004102f0b200941016a210f2003200a3702e4042003200d3602e0040c040b200941016a210f0c030b200641026a2106200741046a2107200521090c000b0b4101210f410121110b20032802e00421050b2005450d0020032902e404210a02402011450d002010102f0b2000200536020420004101360200200041086a200a3702000c010b20012802102205450d0120012802082212200541306c6a2113200341e0046a41146a2114200341e0076a211520034194066a2116200341a4066a2117200341b4066a2118200341c4066a2119200341d4066a211a200341e4066a211b200341f4066a211c20034184076a211d20034194076a211e200341a4076a211f200341b4076a2120200341c4076a2121200341d4076a212202400340024020122d0000410c470d00201228020c2205450d002012280204220d200541186c6a212303400240200d41146a220e2802002205450d00200d410c6a212441002109034002400240024002400240200920054f0d00410121052024280200200941047422256a22072d0000410b470d042003200741046a22073602c00220072802002207200f4f0d01201020074102746a2802002208450d042003200c3602d407200341133a00d007200341d7003a00c007200320083602b4072003412d3a00b0072003200c3602a407200341123a00a00720032007360294072003410b3a009007200341063a008007200341003a00f00620034184083b01e006200341373a00d006200320023602c4062003412d3a00c0062003200c3602b406200341123a00b0062003200c3602a406200341133a00a006200341d6003a00900620032008360284062003412d3a0080062003200c3602f405200341123a00f005200e280200222620094d0d02200e2009360200200d28020c2105200320153602f804200320243602f0042003200520256a220b41106a22063602e8042003200941016a22273602e0042003202620276b22283602e40420032005202741047422296a222a3602ec042003200341f0056a3602f404200621050240200b2d0000220841ac01460d004100210502400340200b20056a21070240200841ff01714109470d000240200741046a280200220828020441ffffffff0371450d002008280200102f0b2008102f0b2005450d012003200741206a3602e804200541106a2105200741106a2d0000220841ac01470d000b200b20056a41106a21050c010b200741106a21050b02402005202a460d0003402003200541106a22073602e80420052d0000220841ac01460d01024020084109470d000240200541046a280200220528020441ffffffff0371450d002005280200102f0b2005102f0b2007210520062007470d000b0b02400240024002402028450d0002402027200d2802142205470d00200341f0056a21052015210b0c030b2025200541047422056b2108200d28020c20056a2107200341f0056a21052015210603400240024020052006470d00410021050c010b2003200541106a3602f4040b200341d0036a200510b90620032d00d00341ac01460d04200720032903d003370300200741086a200341d0036a41086a290300370300200d200d28021441016a3602142008450d02200741106a2107200841706a210820032802f804210620032802f40421050c000b0b2024201410be060c020b20032802f804210b20032802f40421050b0240200b20056b2207450d000240024020032802f004220641046a222a280200222520266b20074104762208490d00200628020021070c010b202620086a22072026490d12202541017422262007202620074b1b220741ffffffff00712007470d12200741047422264100480d120240024020250d002026102d21070c010b200628020020254104742026103121070b2007450d1020062007360200202a20264104763602000b2007202720086a22254104746a200720296a202841047410e9061a200320253602e004202520062802082207460d00200920086a410474200741047422076b2108200628020020076a21070340024002402005200b470d00410021050c010b2003200541106a3602f4040b200341d0036a200510b90620032d00d00341ac01460d02200720032903d003370300200741086a200341d0036a41086a2903003703002006200628020841016a3602082008450d01200741106a2107200841706a210820032802f804210b20032802f40421050c000b0b200341003602d803200342083703d003200341d0036a201410be0620032802d003222820032802d8032207410474220b6a210620032802d40321292028210502402007450d000240024020032802f004222541046a222a280200220520032802e404222720032802e00422076a22266b200b4104752208490d00202528020021050c010b202620086a222b2026490d1220054101742226202b2026202b4b1b222641ffffffff00712026470d12202641047422264100480d120240024020050d002026102d21050c010b202528020020054104742026103121050b2005450d1020252005360200202a20264104763602000b2005200720086a220841047422266a200520074104746a202741047410e9061a200320083602e00420282105200820252802082207460d002025280200220520266a212a200520074104746a21082028210703400240200b0d00200621050c020b200341d0036a41026a2205200741036a2d00003a0000200320072f00013b01d003024020072d0000222741ac01470d00200741106a21050c020b200741046a2802002126200741086a290300210a200820273a0000200841086a200a370300200841046a202636020020032f01d0032127200841036a20052d00003a0000200841016a20273b00002025202528020841016a360208200b41706a210b200741106a22052107200841106a2208202a470d000b0b024020062005460d000340200541106a2107024020052d00004109470d000240200541046a2208280200220528020441ffffffff0371450d002005280200102f200828020021050b2005102f0b2007210520062007470d000b0b2029450d002028102f0b20032802e804220520032802ec042206460d0303402003200541106a22073602e8040240024020052d000022084109460d00200841ac01470d01200641706a2005460d06200541106a210503402003200541106a22073602e80420052d0000220841ac01460d07024020084109470d000240200541046a280200220528020441ffffffff0371450d002005280200102f0b2005102f0b2007210520062007470d000c070b0b0240200541046a280200220528020441ffffffff0371450d002005280200102f0b2005102f0b2007210520062007470d000c040b0b4194beca0020092005103b000b2003410136028406200342013702f405200341a4beca003602f005200341353602d4032003200341d0036a360280062003200341c0026a3602d003200341e0046a200341f0056a103a20032802e00422050d080c040b41a6b5ca00411c41f8b4ca001039000b024020032802e4042205450d00024020032802e004220620032802f004220b41086a22082802002207460d00200b280200220b20074104746a200b20064104746a200541047410e9061a0b2008200520076a3602000b024020032d00f0054109470d00024020032802f405220528020441ffffffff0371450d002005280200102f20032802f40521050b2005102f0b024020032d0080064109470d000240200341f0056a41146a280200220528020441ffffffff0371450d002005280200102f20032802840621050b2005102f0b024020032d0090064109470d0002402016280200220528020441ffffffff0371450d002005280200102f20032802940621050b2005102f0b024020032d00a0064109470d0002402017280200220528020441ffffffff0371450d002005280200102f20032802a40621050b2005102f0b024020032d00b0064109470d0002402018280200220528020441ffffffff0371450d002005280200102f20032802b40621050b2005102f0b024020032d00c0064109470d0002402019280200220528020441ffffffff0371450d002005280200102f20032802c40621050b2005102f0b024020032d00d0064109470d000240201a280200220528020441ffffffff0371450d002005280200102f20032802d40621050b2005102f0b024020032d00e0064109470d000240201b280200220528020441ffffffff0371450d002005280200102f20032802e40621050b2005102f0b024020032d00f0064109470d000240201c280200220528020441ffffffff0371450d002005280200102f20032802f40621050b2005102f0b024020032d0080074109470d000240201d280200220528020441ffffffff0371450d002005280200102f20032802840721050b2005102f0b024020032d0090074109470d000240201e280200220528020441ffffffff0371450d002005280200102f20032802940721050b2005102f0b024020032d00a0074109470d000240201f280200220528020441ffffffff0371450d002005280200102f20032802a40721050b2005102f0b024020032d00b0074109470d0002402020280200220528020441ffffffff0371450d002005280200102f20032802b40721050b2005102f0b024020032d00c0074109470d0002402021280200220528020441ffffffff0371450d002005280200102f20032802c40721050b2005102f0b024020032d00d0074109470d0002402022280200220528020441ffffffff0371450d002005280200102f20032802d40721050b2005102f0b410f21050b200520096a2209200e2802002205490d000b0b200d41186a220d2023470d000b0b201241306a22122013470d000c030b0b20032902e404210a2000200536020420004101360200200041086a200a3702002011450d002010102f0b2001280208200128021010cd042001410c6a280200450d022001280208102f0c020b200341d0006a41106a200141106a280200221e360200200341d0006a41086a200141086a290200220a37030020032001290200370350201e41306c2108200aa721094100210d4100210502400340024020082005470d000c020b200920056a2107200541306a2206210520072d00004108470d000b200341c0006a200920066a41546a10d6032003280240210d200328024421050b4100210b20054100200d1b2124201e41306c2106200d41c8e1ca00200d1b21054100210702400340024020062007470d000c020b200920076a2108200741306a220d210720082d0000410a470d000b200341386a2009200d6a41546a10d6032003280238210b200328023c21070b4100210e20074100200b1b2125201e41306c210d200b41c8e1ca00200b1b210641002107024003400240200d2007470d000c020b200920076a2108200741306a220b210720082d00004109470d000b2009200b6a41546a28020021074101210e0b2003420037026c20034190bdc600360268200341003602782003410036027420062025411c6c6a21292005202441146c6a210d200341e0046a410272221941266a2121201941206a2122201941186a2123201941106a2112201941086a2101200341e0046a41286a21134104212b41002115410021144100211b4100211a0240024002400240410041ff01710e03000102000b410021080c020b410221080c010b410121080b034002400240024002400240024002400240024002400240024002400240024002400240024002400240024020080e03000104040b0240201b41ff01710e03020300020b02400240024020032802782208450d0020182008460d002003200841046a3602780c010b034020292006460d15200341206a200610af0620032802202208450d022006411c6a21062003280224210b200320083602782008200b4102746a2118200b450d000b2003200841046a3602782008450d140b200e211620072117200828020021070c050b2006411c6a21060c120b4100211641002117200e0d030c050b02400340200d2005460d012005410c6a2108200541146a220b210520082802000d000b200b2105200e211620072117200b417c6a28020021070c030b024002400240024020032802782208450d0020182008460d002003200841046a3602780c010b034020292006460d03200341186a200610af0620032802182208450d022006411c6a2106200328021c210b200320083602782008200b4102746a2118200b450d000b2003200841046a3602782008450d020b4102211b200e211620072117200828020021070c040b2006411c6a21060b4102211b0c100b0340200d2005460d102005410c6a2108200541146a220b210520082802000d000b200b2105200e211620072117200b417c6a28020021070c010b024002400240201b41ff01710e03010200010b024002402003280278220b450d002018200b460d002003200b41046a3602780c010b034020292006460d05200341306a200610af0620032802302208450d052006411c6a21062008210b20032802342224450d000b2003200841046a3602782008450d05200820244102746a21182008210b0b200e211620072117200b28020021070c020b02400340200d2005460d012005410c6a2108200541146a220b210520082802000d000b200b2105200e211620072117200b417c6a28020021070c020b0240024020032802782208450d0020182008460d002003200841046a3602780c010b034020292006460d05200341286a200610af0620032802282208450d052006411c6a2106200328022c210b20032008360278200b450d000b2003200841046a3602782008450d042008200b4102746a21180b4102211b200e211620072117200828020021070c010b03402005200d460d032005410c6a2108200541146a220b210520082802000d000b200b2105200e211620072117200b417c6a28020021070b2003200736027c0240024002402007200f4f0d00201020074102746a2802002208450d0720142015460d012015211c201421150c020b2003410136028406200342023702f405200341a8b0ca003602f005200341013602d4032003200341d0036a360280062003200341fc006a3602d003200341e0046a200341f0056a103a20032902e404220a422088a7210520032802e0042128200aa7211d0c0b0b201541016a220b2015490d132015410174220e200b200e200b4b1b220b41ffffffff0371200b470d13200b410274220b4100480d130240024020150d00200b102d212b0c010b202b2015410274200b1031212b0b202b450d11200b410276211c0b202b20154102746a2007360200200341f0056a200328027c2226200341d0006a10c40620032802f805211d20032802f4052128024020032802f00522154101460d0020282802082207417f4c0d0c20282d000c210e0240024020070d004101210b0c010b202828020021242007102d220b450d12200b2024200710e8061a0b2003200e3a008c01200320073602880120032007360284012003200b3602800120282d000d21072003200836029c012003200328027c360298012003410036029001200320073a008d0102400240200328026822074190bdc600460d00200328026c21270c010b202142003701002022420037010020234200370100201242003701002001420037010020194200370100200341f0056a410041e00210e7061a419403102d2207450d124100212720074100360200200720032903e0043702042007410c6a200341e0046a41086a290300370200200741146a200341e0046a41106a2903003702002007411c6a200341e0046a41186a290300370200200741246a200341e0046a41206a2903003702002007412c6a2013290300370200200741346a200341f0056a41e00210e8061a2003410036026c200320073602680b201441016a211403400240024020072f0106222a0d004100210b0c010b200741146a2108202a410274210e200741086a2124417f210b03400240200e0d00202a210b0c020b20242802002125200841206a2108200b41016a210b200e417c6a210e202441046a21240240417f2025202647202520264b1b41016a0e03020001020b0b2008290200210a2008200329038001370200200841186a200329039801370200200841106a2207290200212c2007200329039001370200200841086a200329038801370200202c42ffffffff0f83420285500d06200a42808080807083500d06200aa7102f0c060b02402027450d002027417f6a21272007200b4102746a4194036a28020021070c010b0b2003200328027041016a360270200329039801210a200329039001212c200329038801212d200329038001212e0240024020072f01062208410b490d0020074190bdc600460d01202142003701002022420037010020234200370100201242003701002001420037010020194200370100200341f0056a410041e00210e7061a419403102d2208450d1320084100360200200820032903e0043702042008410c6a200341e0046a41086a222f290300370200200841146a200341e0046a41106a22302903003702002008411c6a200341e0046a41186a2231290300370200200841246a200341e0046a41206a22322903003702002008412c6a2013290300370200200841346a200341f0056a41e00210e8062124200341f0056a41086a222a200741fc016a290200370300200341f0056a41106a221f20074184026a290200370300200341f0056a41186a22202007418c026a290200370300200320072902f4013703f00520072802202133200841086a200741246a20072f010641796a220e41027410e8062125202420074194026a200e41057410e8062124200741063b01062008200e3b0106203120202903003703002030201f290300370300202f202a290300370300200320032903f0053703e00402400240200b4107490d002025200b417a6a22344102746a2025200b41796a22274102746a220b200e41ffff037120276b41027410e9061a200b2026360200202420344105746a202420274105746a220b200841066a220e2f010020276b41057410e9061a200b41186a200a370200200b202c370210200b202d370208200b202e3702000c010b200741086a220e200b41016a22244102746a200e200b4102746a2225200741066a220e2f0100200b6b41027410e9061a20252026360200200741346a222520244105746a2025200b4105746a2224200e2f0100200b6b41057410e9061a202441186a200a3702002024202c3702102024202d3702082024202e3702000b200e200e2f010041016a3b0100200341d0036a41186a22352031290300220a370300200341d0036a41106a22362030290300222c370300200341d0036a41086a2237202f290300222d370300200341b0016a41186a2238200a370300200341b0016a41106a2239202c370300200341b0016a41086a223a202d370300200320032903e004220a3703d0032003200a3703b0010240200728020022250d004100213b2008210b0c060b20072f010421264100213b2008213c0340200341c0026a41186a223d2038290300370300200341c0026a41106a223e2039290300370300200341c0026a41086a223f203a290300370300200320032903b0013703c002202641ffff0371212402400240024020252f01062207410b490d002021420037010020224200370100202342003701002012420037010020014200370100201942003701002037202f2903003703002036203029030037030020352031290300370300200341d0036a41206a22072032290300370300200341d0036a41286a22082013290300370300200320032903e0043703d003200341f0056a410041900310e7061a41c403102d220b450d17200b4100360200200b20032903d003370204200b410c6a2037290300370200200b41146a2036290300370200200b411c6a2035290300370200200b41246a2007290300370200200b412c6a2008290300370200200b41346a200341f0056a41900310e8062108202541206a280200214020202025418c026a290200370300201f20254184026a290200370300202a202541fc016a2902003703002003202541f4016a2902003703f005200b41086a202541246a20252f0106220e41796a220741027410e8062141200820254194026a200741057410e8062142200b4194036a202541b0036a200e417a6a222741027410e8062134202541063b0106200b20073b010602402027450d00410021072034210803402008280200220e20073b0104200e200b360200200841046a21082027200741016a2207470d000b0b20312020290300220a3703002030201f290300222c370300202f202a290300222d370300200320032903f005222e3703e0042020200a370300201f202c370300202a202d3703002003202e3703f005202641ffff037122084107490d0120412024417a6a220e41027422276a2041202441796a22074102746a2208200b2f010620076b41027410e9061a200820333602002042200e4105746a204220074105746a2208200b2f010620076b41057410e9061a200841186a203d290300370200200841106a203e290300370200200841086a203f290300370200200820032903c002370200200b200b2f010641016a22083b01062024410274222620346a416c6a203420276a2227200841ffff03712224200e6b41027410e9061a2027203c3602002024200e490d02200b20266a41fc026a210803402008280200220e200741016a22073b0104200e200b360200200841046a210820072024490d000c030b0b202541086a2208202441016a220b410274220e6a2008202441027422276a2208200720246b222641027410e9061a20082033360200202541346a2208200b4105746a200820244105746a2208202641057410e9061a200841186a203d290300370200200841106a203e290300370200200841086a203f290300370200200820032903c0023702002025200741016a22073b0106202720254194036a22086a41086a2008200e6a2208200741ffff0371220e200b6b41027410e9061a2008203c3602002024200e4f0d092025200b417f6a22074102746a4198036a210803402008280200220b200741016a22073b0104200b2025360200200841046a21082007200e490d000c0a0b0b202541086a2207202441016a2227410274220e6a2007202441027422266a220720252f0106223420246b224141027410e9061a20072033360200202541346a220720274105746a200720244105746a2207204141057410e9061a200741186a203d290300370200200741106a203e290300370200200741086a203f290300370200200720032903c0023702002025203441016a22073b0106202620254194036a22346a41086a2034200e6a2234200741ffff0371220e20276b41027410e9061a2034203c3602002008200e4f0d00202520266a4198036a2107034020072802002208202441016a22243b010420082025360200200741046a2107200e2024470d000b0b203b41016a213b203820202903003703002039201f290300370300203a202a290300370300200320032903f0053703b0010240202528020022070d00204021330c070b20252f010421262007212520402133200b213c0c000b0b200741086a220e200b41016a22244102746a200e200b4102746a220e2008200b6b41027410e9061a200e2026360200200741346a220820244105746a2008200b4105746a220820072f0106200b6b41057410e9061a200841186a200a3702002008202c3702102008202d3702082008202e370200200720072f010641016a3b01060c050b4195b4ca00412d41f8b4ca001039000b20032802fc052105201c21150c090b2003200b3602780b2003280260220d41306c21052003280258220b41546a210720032802682127200328026c21262003280270213802400340410021082005450d01200541506a21052007412c6a2109200741306a2206210720092d00004103470d000b200641086a2802002205450d00200541286c2107200628020041186a2105410021080340200820052d0000456a2108200541286a2105200741586a22070d000b0b200d41306c2105200b415c6a2107024003402005450d01200541506a2105200741246a2109200741306a2206210720092d00004104470d000b200628020021050c090b410021050c080b2021420037010020224200370100202342003701002012420037010020014200370100201942003701002037202f2903003703002036203029030037030020352031290300370300200341d0036a41206a22082032290300370300200341d0036a41286a220e2013290300370300200320032903e0043703d003200341f0056a410041900310e7061a41c403102d2207450d0d20074100360200200720032903d0033702042007410c6a2037290300370200200741146a20362903003702002007411c6a2035290300370200200741246a20082903003702002007412c6a200e290300370200200741346a200341f0056a41900310e806210e200720032802682208360294032003200328026c222441016a36026c200841003b0104200320073602682008200736020020202038290300370300201f2039290300370300202a203a290300370300200320032903b0013703f0052024203b470d0220072f01062208410a4b0d03200e20084105746a220e20032903f005370200200e41086a202a290300370200200e41106a201f290300370200200e41186a2020290300370200200720084102746a41086a20333602002007200841016a22084102746a4194036a200b360200200720083b0106200b20083b0104200b20073602000b02402015450d00201d450d002028102f0b201c21150b2016210e20172107201a41ff01710e03020309020b4196b3ca00413041f8b4ca001039000b41c6b3ca00412741f8b4ca001039000b410021080c070b410221080c060b2003280268200328026c200328027010bc0602402015450d00202b102f0b2009201e10cd040240200341dc006a280200450d002009102f0b2000202836020420004101360200200041086a2005ad422086201dad843702002011450d072010102f200424000f0b200341f0056a41106a220f200341d0006a41106a280200360200200341f0056a41086a200341d0006a41086a290300370300200320032903503703f005200341b0016a200341f0056a10d0042014450d01202b20144102746a2129200520086a2128200341f0056a41e0016a2114200341f0056a41d0016a2116200341f0056a41c0016a2117200341f0056a41b0016a2118200341f0056a41a0016a2119200341f0056a4190016a211a200341f0056a4180016a211b200341f0056a41f0006a211c200341f0056a41e0006a211d200341f0056a41d0006a211e200341f0056a41c0006a211f200341f0056a41306a2120200341f0056a41206a2121200341e7046a2122200341a4066a2123200341b4066a2112200341c4066a2101200341d4066a2113200341e4066a2134200341f4066a212f20034184076a213020034194076a2131200341a4076a2135200341b4076a2136200341c4076a2137200341d4076a2133202b212503402025220541046a21252005280200210d202721072026210603400240024020072f0106220e0d00410021080c010b200e4102742124417f210841002109410021050340024020242005470d00200e21080c020b200720056a210b200941206a2109200841016a2108200541046a21050240417f200b41086a280200220b200d47200b200d4b1b41016a0e03020001020b0b200720096a220e412c6a2802002107200e41306a28020021052003200c3602d407200341133a00d007200341d7003a00c007200320053602b4072003412d3a00b0072003200c3602a407200341123a00a00720032007360294072003410b3a009007200341063a008007200341003a00f00620034184083b01e006200341373a00d006200320023602c4062003412d3a00c0062003200c3602b406200341123a00b0062003200c3602a406200341133a00a006200341d6003a00900620032005360284062003412d3a0080062003200c3602f405200341123a00f005200e411c6a2224280200220d41106a220541ffffffff00712005470d0320054104742207417f4c0d030240024020070d00410821060c010b2007102d2206450d09200741047621052024280200210d0b02400240200d0d00410021080c010b41002109410021070340024020072005470d00200541016a22082005490d0d2005410174220b2008200b20084b1b220841ffffffff00712008470d0d200841047422084100480d0d0240024020050d002008102d21060c010b200620054104742008103121060b2006450d0b200841047621050b200620096a2208410f3a0000200841046a2007360200200841016a20032f01d0033b0000200841036a200341d0036a41026a2d00003a0000200941106a2109200741016a22082107200d2008470d000b0b0240200520086b410e4b0d002008410f6a22072008490d0b200541017422092007200920074b1b220741ffffffff00712007470d0b200741047422074100480d0b0240024020050d002007102d21060c010b200620054104742007103121060b2006450d09200741047621050b200341e0046a200341f0056a10bd06200620084104746a220720032903e004370300200741086a200341e0046a41086a2209290300370300200341e0046a200f10bd06200741186a2009290300370300200720032903e004370310200341e0046a202110bd06200741286a2009290300370300200741206a20032903e004370300200341e0046a202010bd06200741386a2009290300370300200741306a20032903e004370300200341e0046a201f10bd06200741c8006a2009290300370300200741c0006a20032903e004370300200341e0046a201e10bd06200741d8006a2009290300370300200741d0006a20032903e004370300200341e0046a201d10bd06200741e8006a2009290300370300200741e0006a20032903e004370300200341e0046a201c10bd06200741f8006a2009290300370300200741f0006a20032903e004370300200341e0046a201b10bd0620074188016a200929030037030020074180016a20032903e004370300200341e0046a201a10bd0620074198016a200929030037030020074190016a20032903e004370300200341e0046a201910bd06200741a8016a2009290300370300200741a0016a20032903e004370300200341e0046a201810bd06200741b8016a2009290300370300200741b0016a20032903e004370300200341e0046a201710bd06200741c8016a2009290300370300200741c0016a20032903e004370300200341e0046a201610bd06200741d8016a2009290300370300200741d0016a20032903e004370300200341e0046a201410bd06200741e8016a2009290300370300200741e0016a20032903e004370300024002402008410f6a22072005460d002005210b200721050c010b200541016a22072005490d0b200541017422092007200920074b1b220741ffffffff00712007470d0b200741047422074100480d0b0240024020050d002007102d21060c010b200620054104742007103121060b2006450d092007410476210b0b200620054104746a220541063a0000200520032900e004370001200541086a2022290000370000200341e0046a200341b0016a418c0110e8061a4110102d2207450d08200741063a0000200341d0036a200341e0046a418c0110e8061a20242802002205417f4c0d030240024020050d004101210d41014101200510e8061a2005ad212c410021050c010b200e41146a28020021092005102d220d450d09200d2009200510e80621092005102d220d450d09200d2009200510e8061a2009102f2005ad212c0b200341e0046a200341d0036a418c0110e8061a200e41216a310000212d200341d0036a200341e0046a418c0110e8061a200341e0046a200341d0036a418c0110e8061a200341c0026a200341e0046a418c0110e8061a4110102d2209450d08200841106a2108202a41807e71212a200a428080808080804083220a202c84202d422886844280808080800c84212c200941063a00002009102f200341d0036a200341c0026a418c0110e8061a200341e0046a200341d0036a418c0110e8061a024020072d00004109470d0002402007280204220928020441ffffffff0371450d002009280200102f200728020421090b2009102f0b2007102f200341c0026a200341e0046a418c0110e8061a200341e0046a200341c0026a418c0110e8061a2003202a3602fc03200320083602f8032003200b3602f403200320063602f003200341003602ec03200342043702e4032003202c3702dc03200320053602d8032003200d3602d403200341013602d003200341e0046a200341d0036a10d504200341b0016a200341e0046a418c0110e8061a200e41286a2028360200200e41246a4101360200024020032d00f0054109470d00024020032802f405220528020441ffffffff0371450d002005280200102f20032802f40521050b2005102f0b024020032d0080064109470d000240200341f0056a41146a280200220528020441ffffffff0371450d002005280200102f20032802840621050b2005102f0b024020032d0090064109470d000240200341f0056a41246a280200220528020441ffffffff0371450d002005280200102f20032802940621050b2005102f0b024020032d00a0064109470d0002402023280200220528020441ffffffff0371450d002005280200102f20032802a40621050b2005102f0b024020032d00b0064109470d0002402012280200220528020441ffffffff0371450d002005280200102f20032802b40621050b2005102f0b024020032d00c0064109470d0002402001280200220528020441ffffffff0371450d002005280200102f20032802c40621050b2005102f0b024020032d00d0064109470d0002402013280200220528020441ffffffff0371450d002005280200102f20032802d40621050b2005102f0b024020032d00e0064109470d0002402034280200220528020441ffffffff0371450d002005280200102f20032802e40621050b2005102f0b024020032d00f0064109470d000240202f280200220528020441ffffffff0371450d002005280200102f20032802f40621050b2005102f0b024020032d0080074109470d0002402030280200220528020441ffffffff0371450d002005280200102f20032802840721050b2005102f0b024020032d0090074109470d0002402031280200220528020441ffffffff0371450d002005280200102f20032802940721050b2005102f0b024020032d00a0074109470d0002402035280200220528020441ffffffff0371450d002005280200102f20032802a40721050b2005102f0b024020032d00b0074109470d0002402036280200220528020441ffffffff0371450d002005280200102f20032802b40721050b2005102f0b024020032d00c0074109470d0002402037280200220528020441ffffffff0371450d002005280200102f20032802c40721050b2005102f0b024020032d00d0074109470d0002402033280200220528020441ffffffff0371450d002005280200102f20032802d40721050b2005102f0b200a4280808080808c0184210a202841016a212820252029470d020c040b02402006450d002006417f6a2106200720084102746a4194036a28020021070c010b0b0b41b8b0ca0041800141b8b1ca001055000b103d000b02402015450d00202b102f0b200341f0056a200341b0016a418c0110e8061a200341e0046a200341f0056a10d2040240200341e0046a41106a2802002205450d0020032802e8042215200541306c6a21290340024020152d000041786a220541024b0d0002400240024020050e03000102000b201528020c2205450d0220152802042206200541146c6a212503400240200628020c0d002006280210210c202721052026210e03400240024020052f010622240d00410021070c010b200541286a210d20244102742108200541086a2109417f21070340024020080d00202421070c020b2009280200210b200d41206a210d200741016a21072008417c6a2108200941046a21090240417f200b200c47200b200c4b1b41016a0e03020001020b0b0240200d417c6a280200450d002006200d2802003602100c030b41c8b1ca0041354180b2ca001055000b200e450d01200e417f6a210e200520074102746a4194036a28020021050c000b0b200641146a22062025470d000c030b0b2015280204210e202721052026210b03400240024020052f0106220c0d00410021070c010b200541286a2106200c4102742108200541086a2109417f21070340024020080d00200c21070c020b2009280200210d200641206a2106200741016a21072008417c6a2108200941046a21090240417f200d200e47200d200e4b1b41016a0e03020001020b0b02402006417c6a280200450d00201520062802003602040c040b41c8b1ca0041354180b2ca001055000b200b450d02200b417f6a210b200520074102746a4194036a28020021050c000b0b201528020c2205450d002015280204222a2005411c6c6a210f03400240202a2802182205450d00202a280210222420054102746a212803402024222541046a21242025280200210e202721052026210b024003400240024020052f0106220c0d00410021070c010b200541286a2106200c4102742108200541086a2109417f21070340024020080d00200c21070c020b2009280200210d200641206a2106200741016a21072008417c6a2108200941046a21090240417f200d200e47200d200e4b1b41016a0e03020001020b0b02402006417c6a280200450d00202520062802003602000c030b41c8b1ca0041354180b2ca001055000b200b450d01200b417f6a210b200520074102746a4194036a28020021050c000b0b20242028470d000b0b202a411c6a222a200f470d000b0b201541306a22152029470d000b0b200341ec046a290200210a20032802e004210520032902e404212c20272026203810bc06200041106a200a370200200041086a202c37020020002005360204200041003602002011450d042010102f200424000f0b4102211a0b410121080c000b0b1036000b200424000f0b1038000b91fa0104077f017e157f017e230041e0006b220324000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e10020103100f0e0d0c0b09070806050400020b200141286a2802002104200141246a2802002105200141206a28020021062001411c6a2802002107200141186a2802002108200141146a28020021092001410c6a290200210a200141086a280200210b200141046a280200210c0240200241046a280200200241086a280200220d460d002002280200210e0c160b200d41016a220e200d490d13200d410174220f200e200f200e4b1b220f4100480d1302400240200d0d00200f102d210e0c010b2002280200200d200f1031210e0b200e450d122002200e360200200241046a200f360200200241086a280200210d0c150b200141186a2802002110200141146a2802002111200141106a28020021122001410c6a2802002107200141086a2802002109200141046a280200210402400240200241046a280200200241086a280200220d460d002002280200210e0c010b200d41016a220e200d490d13200d410174220f200e200f200e4b1b220f4100480d1302400240200d0d00200f102d210e0c010b2002280200200d200f1031210e0b200e450d122002200e360200200241046a200f360200200241086a280200210d0b4101210f200241086a200d41016a36020041002113200e200d6a41003a0000200341146a2010360200200341106a20113602002003201236020c200320073602082003200936020420032004360200200341d0006a20032002109e06200320032900513703382003200341d0006a41086a29000037003f024020032d0050220d411f470d0041002112410121070c170b2000200d3a000020002003290338370001200041086a200329003f3700000c240b2001410c6a280200210e200141086a2802002110200141046a280200211320012d0001211102400240200241046a280200200241086a280200220d460d002002280200210f0c010b200d41016a220f200d490d12200d4101742212200f2012200f4b1b22124100480d1202400240200d0d002012102d210f0c010b2002280200200d20121031210f0b200f450d112002200f360200200241046a2012360200200241086a280200210d0b200241086a2212200d41016a360200200f200d6a20113a000002400240200241046a280200220f2012280200220d6b200e490d002002280200210f0c010b200d200e6a2211200d490d12200f410174220d2011200d20114b1b220d4100480d1202400240200f0d00200d102d210f0c010b2002280200200f200d1031210f0b200f450d112002200f360200200241046a200d360200200241086a280200210d0b200241086a200d200e6a360200200f200d6a2013200e10e8061a4100210241012107024020100d00410121120c170b2013102f410121120c160b2001410c6a2802002112200141086a2802002114200141046a280200210502400240200241046a280200200241086a280200220d460d002002280200210e0c010b200d41016a220e200d490d11200d410174220f200e200f200e4b1b220f4100480d1102400240200d0d00200f102d210e0c010b2002280200200d200f1031210e0b200e450d102002200e360200200241046a200f360200200241086a280200210d0b200241086a200d41016a360200200e200d6a41013a0000200520124104746a210c4100210f4100210e41002111410121102012210d03400240200e2011470d00200f200e41016a2213200f20134b1b22114100480d1202400240200f0d002011102d21100c010b2010200e2011103121100b2010450d110b2010200e6a200d41807f72200d41ff0071200d41077622131b3a0000200f41026a210f200e41016a210e2013210d20130d000b024020120d00200521090c0e0b2005210d0340200d41106a2109200d2d000d22084105460d0e200d2d000c210f200d2802082104200d280204210b200d280200210602402011200e470d00200e41016a220d200e490d12200e4101742213200d2013200d4b1b22114100480d1202400240200e0d002011102d21100c010b2010200e2011103121100b2010450d110b2010200e6a200f3a0000200e41016a210d200e410174220e41046a2107200e41026a210f2004210e0340200721120240200d2011470d00200d41016a2213200d490d13200f2013200f20134b1b22114100480d1302400240200d0d002011102d21100c010b2010200d2011103121100b2010450d120b2010200d6a200e41807f72200e41ff0071200e41077622131b3a0000201241026a2107200f41026a210f200d41016a210d2013210e20130d000b0240024020040d00200d210e0c010b4100210f0340200d200f6a210e41fc00211302400240024002402006200f6a2d00000e050200010305020b41fe0021130c020b41fd0021130c010b41ff0021130b0240200e2011470d00200e41016a2211200e490d1420122011201220114b1b22114100480d1402400240200e0d002011102d21100c010b2010200e2011103121100b2010450d130b2010200d6a200f6a20133a0000201241026a21122004200f41016a220f470d000b200d200f6a210e0b0240200b450d002006102f0b4100210d024020084104460d0002402011200e470d00200e41016a220d200e490d13200e410174220f200d200f200d4b1b22114100480d1302400240200e0d002011102d21100c010b2010200e2011103121100b2010450d120b2010200e6a41013a0000200e41016a210e200841077141ff0073210d0b02402011200e470d00200e41016a220f200e490d12200e4101742213200f2013200f4b1b22114100480d1202400240200e0d002011102d21100c010b2010200e2011103121100b2010450d110b2010200e6a200d3a0000200e41016a210e2009210d2009200c470d000c0f0b0b2001412c6a2802002114200141286a2802002115200141246a280200210c200141206a28020021162001411c6a2802002117200141186a2802002118200141146a280200210b2001410c6a290200210a200141086a2802002119200141046a280200210802400240200241046a280200200241086a280200220d460d002002280200210e0c010b200d41016a220e200d490d13200d410174220f200e200f200e4b1b220f4100480d1302400240200d0d00200f102d210e0c010b2002280200200d200f1031210e0b200e450d212002200e360200200241046a200f360200200241086a280200210d0b41012113200241086a200d41016a36020041002110200e200d6a41003a00004104102d2205450d20200541eec2b5ab063600000240024020080d00410021064100211a0c010b410121124100210d41002110200aa72211210e034002400240200d2010460d00200d21132010210d0c010b200d41016a220f200d490d15200d4101742213200f2013200f4b1b22134100480d1502400240200d0d002013102d21120c010b2012200d2013103121120b2012450d230b2012200d6a200e41807f72200e41ff0071200e410776220f1b3a0000200d41016a21102013210d200f210e200f0d000b02400240201320106b2011490d00201321090c010b201020116a220d2010490d142013410174220e200d200e200d4b1b22094100480d14024020130d002009102d22120d010c230b20122013200910312212450d220b201220106a2008201110e8061a02402019450d002008102f0b4101102d2213450d21201341003a00004101210d4101210e201020116a2207210f034002400240200d200e460d00200d21100c010b200d41016a220e200d490d15200d4101742210200e2010200e4b1b22104100480d1502400240200d0d002010102d21130c010b2013200d2010103121130b2013450d23200d210e2010210d0b2013200e6a200f41807f72200f41ff0071200f41077622111b3a0000200e41016a210e2011210f20110d000b02402010200e6b20074f0d00200e20076a220d200e490d142010410174220f200d200f200d4b1b220d4100480d140240024020100d00200d102d21130c010b20132010200d103121130b2013450d22200d21100b2013200e6a2012200710e8061a200e20076a21064101211a2009450d002012102f0b0240024002400240024002400240200b0d004101211b0c010b4100211b20034100360240200342013703382003410c6a2017360200200341086a20183602002003200b3602042003200a4220883e0200200341d0006a2003200341386a109f0620032d00502204411f470d010240024020102006460d002010210d0c010b201041016a220d2010490d192010410174220e200d200e200d4b1b220d4100480d190240024020100d00200d102d21130c010b20132010200d103121130b2013450d27201021060b201320066a41013a0000200641016a210e20032802402212210f034002400240200d200e460d00200d21100c010b200d41016a220e200d490d1a200d4101742210200e2010200e4b1b22104100480d1a02400240200d0d002010102d21130c010b2013200d2010103121130b2013450d28200d210e2010210d0b2013200e6a200f41807f72200f41ff0071200f41077622111b3a0000200e41016a210e2011210f20110d000b2003280238210d02402010200e6b20124f0d00200e20126a220f200e490d1920104101742211200f2011200f4b1b220f4100480d190240024020100d00200f102d21130c010b20132010200f103121130b2013450d27200f21100b2013200e6a200d201210e8061a0240200328023c450d00200d102f0b200e20126a21064100211b0b02400240200c0d00410021110c010b2003410036024020034201370338410121124100210f4100210d2016210e03400240200d200f470d00200f41016a2211200f490d1a200f41017422072011200720114b1b22114100480d1a02400240200f0d002011102d21120c010b2012200f2011103121120b2012450d282003201136023c200320123602382011210f0b2003200d41016a22073602402012200d6a200e41807f72200e41ff0071200e41077622111b3a00002007210d2011210e20110d000b200c20144104746a210902400240024020160d00200c21120c010b200c21122014450d00200941706a211c4100210d200c211d02400340201d211102400340201141046a28020022040d01200d41016a210d2009201141106a2211470d000c050b0b201141106a211d200d41016a211e2016417f6a2116201141086a290200210a2011280200211f200328023c210f2003280240210e034002400240200e200f460d00200328023821120c010b200f41016a2212200f490d1e200f41017422072012200720124b1b22074100480d1e02400240200f0d002007102d21120c010b2003280238200f2007103121120b2012450d2c2003200736023c200320123602382007210f0b2003200e41016a22073602402012200e6a200d41807f72200d41ff0071200d41077622121b3a00002007210e2012210d20120d000b2003200a370308200320043602042003201f360200200341d0006a2003200341386a109f06024020032d00502204411f470d002016450d02201e210d201c2011470d010c020b0b20032d0053210720032f0051211d200328025421162003290358210a0240200941706a2011460d00201141106a211203402012221141106a211202402011280204220d450d0002402011410c6a280200220e450d00200e410c6c210e03400240200d280200220f450d00200d41046a280200450d00200f102f0b200d410c6a210d200e41746a220e0d000b0b201141086a280200450d002011280204102f0b20122009470d000b0b2007411074210d02402015450d00200c102f0b201d200d72210941012111200328023c450d052003280238102f0c050b201141106a21120b20092012460d0003402012221141106a211202402011280204220d450d0002402011410c6a280200220e450d00200e410c6c210e03400240200d280200220f450d00200d41046a280200450d00200f102f0b200d410c6a210d200e41746a220e0d000b0b201141086a280200450d002011280204102f0b20122009470d000b0b02402015450d00200c102f0b0240024020102006460d002010210d0c010b201041016a220d2010490d192010410174220e200d200e200d4b1b220d4100480d190240024020100d00200d102d21130c010b20132010200d103121130b2013450d27201021060b201320066a41023a0000200641016a210e20032802402212210f034002400240200d200e460d00200d21100c010b200d41016a220e200d490d1a200d4101742210200e2010200e4b1b22104100480d1a02400240200d0d002010102d21130c010b2013200d2010103121130b2013450d28200d210e2010210d0b2013200e6a200f41807f72200f41ff0071200f41077622111b3a0000200e41016a210e2011210f20110d000b2003280238210d02402010200e6b20124f0d00200e20126a220f200e490d1920104101742211200f2011200f4b1b220f4100480d190240024020100d00200f102d21130c010b20132010200f103121130b2013450d27200f21100b2013200e6a200d201210e8061a0240200328023c450d00200d102f0b200e20126a2106410121110b0240201a200845720d002019450d002008102f0b0240200b450d00201b4101730d0002402017450d002017410c6c210e200b210d03400240200d280200220f450d00200d41046a280200450d00200f102f0b200d410c6a210d200e41746a220e0d000b0b2018450d00200b102f0b2011200c45720d0202402014450d00200c20144104746a2107200c211203402012221141106a211202402011280204220d450d0002402011410c6a280200220e450d00200e410c6c210e03400240200d280200220f450d00200d41046a280200450d00200f102f0b200d410c6a210d200e41746a220e0d000b0b201141086a280200450d002011280204102f0b20122007470d000b0b2015450d02200c102f0c020b20032f005120032d0053411074722109200341d0006a41086a290300210a200328025421160240200328023c450d002003280238102f0b410021110b0240201a200845720d002019450d002008102f0b0240200b450d00201b4101730d0002402017450d002017410c6c210e200b210d03400240200d280200220f450d00200d41046a280200450d00200f102f0b200d410c6a210d200e41746a220e0d000b0b2018450d00200b102f0b0240200c452011720d0002402014450d00200c20144104746a2107200c211203402012221141106a211202402011280204220d450d0002402011410c6a280200220e450d00200e410c6c210e03400240200d280200220f450d00200d41046a280200450d00200f102f0b200d410c6a210d200e41746a220e0d000b0b201141086a280200450d002011280204102f0b20122007470d000b0b2015450d00200c102f0b2004411f460d002009410874200472210d02402010450d002013102f0b2000200d360200200041086a200a370200200041046a20163602002005102f0c010b200341146a2006360200200341106a20103602002003201336020c20034284808080c00037020420032005360200200341d0006a20032002109e06200320032900513703382003200341d0006a41086a29000037003f20032d0050220d411f460d012000200d3a000020002003290338370001200041086a200329003f3700000b410021124101210f41012113410121074101210241012109410121044101210e41012110410121110c290b41002111410121074101211241012102410121084101210b4101210941012104410121064101210c410121134101210e4101210f410121100c1e0b2001410c6a2802002111200141086a2802002107200141046a280200211202400240200241046a280200200241086a280200220d460d002002280200210e0c010b200d41016a220e200d490d12200d410174220f200e200f200e4b1b220f4100480d1202400240200d0d00200f102d210e0c010b2002280200200d200f1031210e0b200e450d202002200e360200200241046a200f360200200241086a280200210d0b200241086a200d41016a360200200e200d6a410b3a0000200341c4006a41003602002003420137023c2003200236023820122011411c6c6a210c4100210d4100210e2011210f034002400240200d200e460d00200328023c210d0c010b200d41016a2213200d490d13200d41017422102013201020134b1b22134100480d1302400240200d0d002013102d210d0c010b200328023c200d20131031210d0b200d450d21200320133602402003200d36023c0b2003200e41016a360244200d200e6a200f41807f72200f41ff0071200f410776220f1b3a00000240200f450d002003280240210d2003280244210e200f210f0c010b0b2003200c36025c20032012360258200320073602542003201236025002402011450d000240024003402012220d411c6a2112200d2802102207450d02200d410c6a2802002102200d41086a2802002109200d2802042111200d41146a290200210a200d280200210e03400240024020032802402003280244220d460d00200328023c210f0c010b200d41016a220f200d490d17200d4101742213200f2013200f4b1b22134100480d1702400240200d0d002013102d210f0c010b200328023c200d20131031210f0b200f450d25200320133602402003200f36023c2003280244210d0b2003200d41016a360244200f200d6a200e41807f72200e41ff0071200e410776220d1b3a0000200d210e200d0d000b0240024020110d00410121040c010b200320023602302003200936022c200320113602282003200341286a200341386a10900620032d0000220d411f470d02410021040b200aa72106200a422088a72210210e03400240024020032802402003280244220d460d00200328023c210f0c010b200d41016a220f200d490d17200d4101742213200f2013200f4b1b22134100480d1702400240200d0d002013102d210f0c010b200328023c200d20131031210f0b200f450d25200320133602402003200f36023c2003280244210d0b2003200d41016a360244200f200d6a200e41807f72200e41ff0071200e410776220d1b3a0000200d210e200d0d000b024002402003280240220e2003280244220d6b2010490d00200328023c210e0c010b200d20106a220f200d490d16200e410174220d200f200d200f4b1b220d4100480d1602400240200e0d00200d102d210e0c010b200328023c200e200d1031210e0b200e450d242003200d3602402003200e36023c2003280244210d0b2003200d20106a360244200e200d6a2007201010e8061a02402006450d002007102f0b02402004450d002011450d0002402002450d002002410474210e2011210d03400240200d2d00004109470d000240200d41046a2213280200220f28020441ffffffff0371450d00200f280200102f2013280200210f0b200f102f0b200d41106a210d200e41706a220e0d000b0b2009450d002011102f0b2012200c470d000b200c21120c010b20032d0003411074210e20032f0001210f20032903082120200328020421130240200aa7450d002007102f0b200f200e72210e20032012360258200341d0006a10a00602402003280240450d00200328023c102f0b2000200e3b00012000200d3a0000200041036a200e4110763a0000200041086a2020370000200041046a2013360000410021114101210f41012113410121074101210241012109410121044101210e41012110410121120c290b200320123602580b200341d0006a10a00620032802402109200328023c21022003280238221041086a2113201041046a211120032802442207210e03400240024020112802002013280200220d460d002010280200210f0c010b200d41016a220f200d490d13200d4101742212200f2012200f4b1b22124100480d1302400240200d0d002012102d210f0c010b2010280200200d20121031210f0b200f450d212010200f360200201120123602002013280200210d0b2013200d41016a360200200f200d6a200e41807f72200e41ff0071200e410776220d1b3a0000200d210e200d0d000b02400240201041046a280200220e201041086a280200220d6b2007490d002010280200210e0c010b200d20076a220f200d490d12200e410174220d200f200d200f4b1b220d4100480d1202400240200e0d00200d102d210e0c010b2010280200200e200d1031210e0b200e450d202010200e360200201041046a200d360200201041086a280200210d0b201041086a200d20076a360200200e200d6a2002200710e8061a02402009450d002002102f0b41002110410121074101211241012102410121084101210b4101210941012104410121064101210c410121134101210e4101210f410121110c1d0b2001410c6a2802002112200141086a2802002107200141046a280200211302400240200241046a280200200241086a280200220d460d002002280200210e0c010b200d41016a220e200d490d0e200d410174220f200e200f200e4b1b220f4100480d0e02400240200d0d00200f102d210e0c010b2002280200200d200f1031210e0b200e450d0d2002200e360200200241046a200f360200200241086a280200210d0b200241086a200d41016a360200200e200d6a410a3a0000200341246a41003602002003420137021c200320023602182013201241186c6a21054100210d4100210e2012210f034002400240200d200e460d00200328021c210d0c010b200d41016a2210200d490d0f200d41017422112010201120104b1b22104100480d0f02400240200d0d002010102d210d0c010b200328021c200d20101031210d0b200d450d0e200320103602202003200d36021c0b2003200e41016a360224200d200e6a200f41807f72200f41ff0071200f410776220f1b3a00000240200f450d002003280220210d2003280224210e200f210f0c010b0b20032005360234200320133602302003200736022c2003201336022802402012450d0020034101722102200341026a210702400340201341186a210620132802002209450d01201341146a280200210c201341106a2802002108201328020c21042013280208210f2013280204210b4100210e200341003602442003420137023c2009200f4103746a21122003200341186a3602384100210d034002400240200e200d460d00200328023c210e0c010b200e41016a220d200e490d15200e4101742213200d2013200d4b1b220d4100480d1502400240200e0d00200d102d210e0c010b200328023c200e200d1031210e0b200e450d112003200d3602402003200e36023c2003280244210d0b2003200d41016a360244200e200d6a200f41807f72200f41ff0071200f410776220f1b3a00000240200f450d002003280240210e2003280244210d200f210f0c010b0b024020122009460d002009211003402010290200220a422088a7220d41ff01714104460d01201041086a2110200d4118744118752111200aa7210e03400240024020032802402003280244220d460d00200328023c210f0c010b200d41016a220f200d490d17200d4101742213200f2013200f4b1b22134100480d1702400240200d0d002013102d210f0c010b200328023c200d20131031210f0b200f450d25200320133602402003200f36023c2003280244210d0b2003200d41016a360244200f200d6a200e41807f72200e41ff0071200e410776220d1b3a0000200d210e200d0d000b0240024020032802402003280244220d460d00200328023c210e0c010b200d41016a220e200d490d16200d410174220f200e200f200e4b1b220f4100480d1602400240200d0d00200f102d210e0c010b200328023c200d200f1031210e0b200e450d242003200f3602402003200e36023c2003280244210d0b2003200d41016a360244200e200d6a2011417f73220d413f7141c00072200d2011417f4a1b3a000020102012470d000b0b0240200b450d002009102f0b2004200c410474220e6a210f2004210d024002400240200c450d00200e41706a21132004210d0340200d2d0000210e2007200d41036a2d00003a00002003200d41016a2f00003b01000240200e41ac01470d00200d41106a210d0c020b200341cc006a41026a20072d000022103a0000200320032f010022113b014c200d41046a2802002112200d41086a290300210a200220113b0000200241026a20103a00002003200e3a00002003200a37030820032012360204200341d0006a2003200341386a109806024020032d00502211411f4722100d00201341706a2113200d41106a220d200f470d010c030b0b20032d0053210920032f0051210c2003280254210b2003290358210a02402013450d004100210e03400240200d200e6a220f41106a2d00004109470d000240200f41146a2212280200220f28020441ffffffff0371450d00200f280200102f2012280200210f0b200f102f0b2013200e41106a220e470d000b0b02402008450d002004102f0b02402003280240450d00200328023c102f0b2010450d02200c200941107472210d20032006360230200341286a10a10602402003280220450d00200328021c102f0b2000200d3b0001200020113a0000200041036a200d4110763a0000200041086a200a370000200041046a200b360000410021104101210f41012113410121074101210241012109410121044101210e0c2b0b200f200d460d000340200d41106a210e0240200d2d00004109470d000240200d41046a2213280200220d28020441ffffffff0371450d00200d280200102f2013280200210d0b200d102f0b200e210d200f200e470d000b0b02402008450d002004102f0b2003280240210c200328023c21042003280238210f20032802442209210e034002400240200f41086a2211280200200f410c6a2210280200220d460d00200f28020421130c010b200d41016a2213200d490d16200d41017422122013201220134b1b22124100480d1602400240200d0d002012102d21130c010b200f280204200d2012103121130b2013450d24200f2013360204201120123602002010280200210d0b2010200d41016a3602002013200d6a200e41807f72200e41ff0071200e410776220d1b3a0000200d210e200d0d000b024002402011280200220e2010280200220d6b2009490d00200f280204210e0c010b200d20096a2213200d490d15200e410174220d2013200d20134b1b220d4100480d1502400240200e0d00200d102d210e0c010b200f280204200e200d1031210e0b200e450d23200f200e3602042011200d3602002010280200210d0b2010200d20096a360200200e200d6a2004200910e8061a200c450d002004102f0b2006211320062005470d000b200521060b200320063602300b200341286a10a10620032802202109200328021c21022003280218221041086a2113201041046a211120032802242207210e03400240024020112802002013280200220d460d002010280200210f0c010b200d41016a220f200d490d12200d4101742212200f2012200f4b1b22124100480d1202400240200d0d002012102d210f0c010b2010280200200d20121031210f0b200f450d202010200f360200201120123602002013280200210d0b2013200d41016a360200200f200d6a200e41807f72200e41ff0071200e410776220d1b3a0000200d210e200d0d000b02400240201041046a280200220e201041086a280200220d6b2007490d002010280200210e0c010b200d20076a220f200d490d11200e410174220d200f200d200f4b1b220d4100480d1102400240200e0d00200d102d210e0c010b2010280200200e200d1031210e0b200e450d1f2010200e360200201041046a200d360200201041086a280200210d0b201041086a200d20076a360200200e200d6a2002200710e8061a02402009450d002002102f0b4100210f410121074101211241012102410121084101210b4101210941012104410121064101210c410121134101210e0c1b0b2001410c6a2802002111200141086a2802002112200141046a280200210902400240200241046a280200200241086a280200220d460d002002280200210e0c010b200d41016a220e200d490d0d200d410174220f200e200f200e4b1b220f4100480d0d02400240200d0d00200f102d210e0c010b2002280200200d200f1031210e0b200e450d0c2002200e360200200241046a200f360200200241086a280200210d0b200241086a200d41016a360200200e200d6a41093a0000200341c4006a41003602002003420137023c2003200236023820092011411c6c6a21084100210d4100210e2011210f034002400240200d200e460d00200328023c210d0c010b200d41016a2213200d490d0e200d41017422102013201020134b1b22134100480d0e02400240200d0d002013102d210d0c010b200328023c200d20131031210d0b200d450d0d200320133602402003200d36023c0b2003200e41016a360244200d200e6a200f41807f72200f41ff0071200f410776220f1b3a00000240200f450d002003280240210d2003280244210e200f210f0c010b0b2003200836025c20032009360258200320123602542003200936025002402011450d000240024003402009220d411c6a2109200d2802102212450d02200d410c6a2802002102200d41086a2802002104200d2802042107200d41146a290200210a200d280200210e03400240024020032802402003280244220d460d00200328023c210f0c010b200d41016a220f200d490d12200d4101742213200f2013200f4b1b22134100480d1202400240200d0d002013102d210f0c010b200328023c200d20131031210f0b200f450d11200320133602402003200f36023c2003280244210d0b2003200d41016a360244200f200d6a200e41807f72200e41ff0071200e410776220d1b3a0000200d210e200d0d000b0240024020070d004101210c0c010b200320023602302003200436022c200320073602282003200341286a200341386a10900620032d0000220d411f470d024100210c0b2012200a422088a7220e4102746a2111200aa7210603400240024020032802402003280244220d460d00200328023c210f0c010b200d41016a220f200d490d12200d4101742213200f2013200f4b1b22134100480d1202400240200d0d002013102d210f0c010b200328023c200d20131031210f0b200f450d11200320133602402003200f36023c2003280244210d0b2003200d41016a360244200f200d6a200e41807f72200e41ff0071200e410776220d1b3a0000200d210e200d0d000b024020112012460d002012211003402010280200210e03400240024020032802402003280244220d460d00200328023c210f0c010b200d41016a220f200d490d14200d4101742213200f2013200f4b1b22134100480d1402400240200d0d002013102d210f0c010b200328023c200d20131031210f0b200f450d13200320133602402003200f36023c2003280244210d0b2003200d41016a360244200f200d6a200e41807f72200e41ff0071200e410776220d1b3a0000200d210e200d0d000b201041046a22102011470d000b0b02402006450d002012102f0b02402007450d00200c450d0002402002450d002002410474210e2007210d03400240200d2d00004109470d000240200d41046a2213280200220f28020441ffffffff0371450d00200f280200102f2013280200210f0b200f102f0b200d41106a210d200e41706a220e0d000b0b2004450d002007102f0b20092008470d000b200821090c010b20032d0003411074210e20032f0001210f20032903082120200328020421130240200aa7450d002012102f0b200f200e72210e20032009360258200341d0006a10a00602402003280240450d00200328023c102f0b2000200e3b00012000200d3a0000200041036a200e4110763a0000200041086a2020370000200041046a20133600004100210e4101210f41012113410121074101210241012109410121040c250b200320093602580b200341d0006a10a00620032802402109200328023c21022003280238221041086a2113201041046a211120032802442207210e03400240024020112802002013280200220d460d002010280200210f0c010b200d41016a220f200d490d0e200d4101742212200f2012200f4b1b22124100480d0e02400240200d0d002012102d210f0c010b2010280200200d20121031210f0b200f450d0d2010200f360200201120123602002013280200210d0b2013200d41016a360200200f200d6a200e41807f72200e41ff0071200e410776220d1b3a0000200d210e200d0d000b02400240201041046a280200220e201041086a280200220d6b2007490d002010280200210e0c010b200d20076a220f200d490d0d200e410174220d200f200d200f4b1b220d4100480d0d02400240200e0d00200d102d210e0c010b2010280200200e200d1031210e0b200e450d0c2010200e360200201041046a200d360200201041086a280200210d0b201041086a200d20076a360200200e200d6a2002200710e8061a02402009450d002002102f0b4100210e410121074101211241012102410121084101210b4101210941012104410121064101210c410121130c190b200141046a280200210d02400240200241046a280200200241086a280200220e460d002002280200210f0c010b200e41016a220f200e490d0c200e4101742213200f2013200f4b1b22134100480d0c02400240200e0d002013102d210f0c010b2002280200200e20131031210f0b200f450d0b2002200f360200200241046a2013360200200241086a280200210e0b200241086a200e41016a360200200f200e6a410c3a000041012112410021134100210e03400240200e2013470d002013410174220f201341016a2210200f20104b1b220f4100480d0d0240024020130d00200f102d21120c010b20122013200f103121120b2012450d0c200f21130b2012200e6a200d41807f72200d41ff0071200d410776220f1b3a0000200e41016a210e200f210d200f0d000b200e417f6a2104200241086a2111200241046a2107200e210f03400240024020072802002011280200220d460d00200228020021100c010b200d41016a2210200d490d0d200d41017422092010200920104b1b22094100480d0d02400240200d0d002009102d21100c010b2002280200200d2009103121100b2010450d0c20022010360200200720093602002011280200210d0b2011200d41016a3602002010200d6a200f41807f72200f41ff0071200f410776220d1b3a0000200d210f200d0d000b02400240200241046a280200220f200241086a280200220d6b20044d0d002002280200210f0c010b200d200e6a2210200d490d0c200f410174220d2010200d20104b1b220d4100480d0c02400240200f0d00200d102d210f0c010b2002280200200f200d1031210f0b200f450d0b2002200f360200200241046a200d360200200241086a280200210d0b200241086a200d200e6a360200200f200d6a2012200e10e8061a410121072013450d012012102f410121120c0f0b200141046a280200210d02400240200241046a280200200241086a280200220e460d002002280200210f0c010b200e41016a220f200e490d0b200e4101742213200f2013200f4b1b22134100480d0b02400240200e0d002013102d210f0c010b2002280200200e20131031210f0b200f450d0a2002200f360200200241046a2013360200200241086a280200210e0b200241086a200e41016a360200200f200e6a41083a000041012112410021134100210e03400240200e2013470d002013410174220f201341016a2210200f20104b1b220f4100480d0c0240024020130d00200f102d21120c010b20122013200f103121120b2012450d0b200f21130b2012200e6a200d41807f72200d41ff0071200d410776220f1b3a0000200e41016a210e200f210d200f0d000b200e417f6a2104200241086a2111200241046a2107200e210f03400240024020072802002011280200220d460d00200228020021100c010b200d41016a2210200d490d0c200d41017422092010200920104b1b22094100480d0c02400240200d0d002009102d21100c010b2002280200200d2009103121100b2010450d0b20022010360200200720093602002011280200210d0b2011200d41016a3602002010200d6a200f41807f72200f41ff0071200f410776220d1b3a0000200d210f200d0d000b02400240200241046a280200220f200241086a280200220d6b20044d0d002002280200210f0c010b200d200e6a2210200d490d0b200f410174220d2010200d20104b1b220d4100480d0b02400240200f0d00200d102d210f0c010b2002280200200f200d1031210f0b200f450d0a2002200f360200200241046a200d360200200241086a280200210d0b200241086a200d200e6a360200200f200d6a2012200e10e8061a410121072013450d002012102f410121120c0e0b410121120c0d0b2001410c6a2802002112200141086a2802002105200141046a280200210b02400240200241046a280200200241086a280200220d460d002002280200210e0c010b200d41016a220e200d490d09200d410174220f200e200f200e4b1b220f4100480d0902400240200d0d00200f102d210e0c010b2002280200200d200f1031210e0b200e450d082002200e360200200241046a200f360200200241086a280200210d0b200241086a200d41016a360200200e200d6a41073a0000200b201241146c6a2106410021104100210d4100210f4101210e2012211303400240200d200f470d002010200d41016a220f2010200f4b1b220f4100480d0a0240024020100d00200f102d210e0c010b200e200d200f1031210e0b200e450d090b200e200d6a201341807f72201341ff0071201341077622111b3a0000201041026a2110200d41016a210d2011211320110d000b02400240024020120d00200b21070c010b200b21100340201041146a2107201028020c220c4104460d012010280204210820102802002104200d4101742111201041106a280200211320102802082209211003400240200d200f470d00200d41016a220f200d490d0d2011200f2011200f4b1b220f4100480d0d02400240200d0d00200f102d210e0c010b200e200d200f1031210e0b200e450d0c0b200e200d6a201041807f72201041ff0071201041077622121b3a0000201141026a2111200d41016a210d2012211020120d000b0240200f200d6b20094f0d00200d20096a2210200d490d0c200f41017422112010201120104b1b22104100480d0c02400240200f0d002010102d210e0c010b200e200f20101031210e0b200e450d0b2010210f0b200e200d6a2004200910e8061a2009200f6b200d6a211002402008450d002004102f0b024020100d00200f41016a2210200f490d0c200f41017422112010201120104b1b22104100480d0c02400240200f0d002010102d210e0c010b200e200f20101031210e0b200e450d0b2010210f0b200e20096a200d6a200c3a00002009200d6a41016a210d03400240200d200f470d00200d41016a220f200d490d0d200d4101742210200f2010200f4b1b220f4100480d0d02400240200d0d00200f102d210e0c010b200e200d200f1031210e0b200e450d0c0b200e200d6a201341807f72201341ff0071201341077622101b3a0000200d41016a210d2010211320100d000b2007211020072006470d000c020b0b20062007460d000340200741146a21130240200741046a280200450d002007280200102f0b2013210720062013470d000b0b02402005450d00200b102f0b200241086a2112200241046a2107200d2110034002400240200728020020122802002213460d00200228020021110c010b201341016a22112013490d0a201341017422092011200920114b1b22094100480d0a0240024020130d002009102d21110c010b200228020020132009103121110b2011450d092002201136020020072009360200201228020021130b2012201341016a360200201120136a201041807f72201041ff0071201041077622131b3a00002013211020130d000b02400240200241046a2802002210200241086a28020022136b200d490d00200228020021100c010b2013200d6a22112013490d09201041017422132011201320114b1b22134100480d090240024020100d002013102d21100c010b200228020020102013103121100b2010450d0820022010360200200241046a2013360200200241086a28020021130b200241086a2013200d6a360200201020136a200e200d10e8061a41002113410121070240200f450d00200e102f0b4101211241012102410121084101210b4101210941012104410121064101210c0c140b2001410c6a2802002104200141086a2802002106200141046a280200210902400240200241046a280200200241086a280200220d460d002002280200210e0c010b200d41016a220e200d490d08200d410174220f200e200f200e4b1b220f4100480d0802400240200d0d00200f102d210e0c010b2002280200200d200f1031210e0b200e450d072002200e360200200241046a200f360200200241086a280200210d0b200241086a200d41016a360200200e200d6a41063a0000200341dc006a41003602002003420137025420032002360250200920044104746a21114100210d4100210e2004210f034002400240200d200e460d002003280254210d0c010b200d41016a2213200d490d09200d41017422102013201020134b1b22134100480d0902400240200d0d002013102d210d0c010b2003280254200d20131031210d0b200d450d08200320133602582003200d3602540b2003200e41016a36025c200d200e6a200f41807f72200f41ff0071200f410776220f1b3a00000240200f450d002003280258210d200328025c210e200f210f0c010b0b20092110024002402004450d004100210f0340200341086a220d2009200f6a220e41086a2802003602002003200e2902003703000240200e410d6a2d000022104102470d00200e41106a21100c020b200341186a41086a200d280200220d36020020032003290300220a370318200e410c6a2d00002112200341286a41086a2207200d3602002003200a370328024002402003280258200328025c220d460d00200328025421130c010b200d41016a2213200d490d0b200d41017422022013200220134b1b22024100480d0b02400240200d0d002002102d21130c010b2003280254200d2002103121130b2013450d0a2003200236025820032013360254200328025c210d0b2003200d41016a36025c2013200d6a41fdf9ff77201241037441187141107376413f7141c000723a0000024002402003280258200328025c220d460d00200328025421130c010b200d41016a2213200d490d0b200d41017422122013201220134b1b22124100480d0b02400240200d0d002012102d21130c010b2003280254200d2012103121130b2013450d0a2003201236025820032013360254200328025c210d0b2003200d41016a36025c2013200d6a20104100473a0000200341386a41086a2007280200360200200320032903283703382003200341386a200341d0006a109006024020032d00002212411f470d00200f41106a210f200e41106a2011470d010c030b0b20032d0003210720032f000121022003280204210c2003290308210a0240200441047441706a200f460d00200e41106a2110034002402010280208220e450d002010280200210d200e410474210e03400240200d2d00004109470d000240200d41046a2213280200220f28020441ffffffff0371450d00200f280200102f2013280200210f0b200f102f0b200d41106a210d200e41706a220e0d000b0b201041106a210d0240201041046a280200450d002010280200102f0b200d2110200d2011470d000b0b2007411074210d02402006450d002009102f0b2002200d72210d02402003280258450d002003280254102f0b2000200d3b0001200020123a0000200041036a200d4110763a0000200041086a200a370000200041046a200c360000410021044101210f410121134101210741012102410121090c1f0b20112010460d00034002402010280208220e450d002010280200210d200e410474210e03400240200d2d00004109470d000240200d41046a2213280200220f28020441ffffffff0371450d00200f280200102f2013280200210f0b200f102f0b200d41106a210d200e41706a220e0d000b0b201041106a210d0240201041046a280200450d002010280200102f0b200d2110200d2011470d000b0b02402006450d002009102f0b20032802582109200328025421022003280250221041086a2113201041046a2111200328025c2207210e03400240024020112802002013280200220d460d002010280200210f0c010b200d41016a220f200d490d09200d4101742212200f2012200f4b1b22124100480d0902400240200d0d002012102d210f0c010b2010280200200d20121031210f0b200f450d082010200f360200201120123602002013280200210d0b2013200d41016a360200200f200d6a200e41807f72200e41ff0071200e410776220d1b3a0000200d210e200d0d000b02400240201041046a280200220e201041086a280200220d6b2007490d002010280200210e0c010b200d20076a220f200d490d08200e410174220d200f200d200f4b1b220d4100480d0802400240200e0d00200d102d210e0c010b2010280200200e200d1031210e0b200e450d072010200e360200201041046a200d360200201041086a280200210d0b201041086a200d20076a360200200e200d6a2002200710e8061a02402009450d002002102f0b4100210c410121074101211241012102410121084101210b4101210941012104410121060c120b2001410c6a2802002107200141086a2802002109200141046a280200211202400240200241046a280200200241086a280200220d460d002002280200210e0c010b200d41016a220e200d490d07200d410174220f200e200f200e4b1b220f4100480d0702400240200d0d00200f102d210e0c010b2002280200200d200f1031210e0b200e450d062002200e360200200241046a200f360200200241086a280200210d0b200241086a200d41016a360200200e200d6a41053a0000200341dc006a41003602002003420137025420032002360250410121104100210f4100210d2007210e03400240200d200f470d00200f41016a2213200f490d08200f41017422112013201120134b1b22134100480d0802400240200f0d002013102d21100c010b2010200f2013103121100b2010450d0720032013360258200320103602542013210f0b2003200d41016a221136025c2010200d6a200e41807f72200e41ff0071200e41077622131b3a00002011210d2013210e20130d000b024002402007450d002007410c6c21134100210d03402012200d6a220e41046a280200220f4102460d012003200e280200200f200e41086a280200200341d0006a109b0620032d0000220e411f470d022013200d410c6a220d470d000b0b02402009450d002012102f0b20032802582109200328025421022003280250221041086a2113201041046a2111200328025c2207210e03400240024020112802002013280200220d460d002010280200210f0c010b200d41016a220f200d490d09200d4101742212200f2012200f4b1b22124100480d0902400240200d0d002012102d210f0c010b2010280200200d20121031210f0b200f450d082010200f360200201120123602002013280200210d0b2013200d41016a360200200f200d6a200e41807f72200e41ff0071200e410776220d1b3a0000200d210e200d0d000b02400240201041046a280200220e201041086a280200220d6b2007490d002010280200210e0c010b200d20076a220f200d490d08200e410174220d200f200d200f4b1b220d4100480d0802400240200e0d00200d102d210e0c010b2010280200200e200d1031210e0b200e450d072010200e360200201041046a200d360200201041086a280200210d0b201041086a200d20076a360200200e200d6a2002200710e8061a02402009450d002002102f0b41002106410121074101211241012102410121084101210b41012109410121040c110b20032d0003411074210d20032f0001210f2003290308210a2003280204211302402009450d002012102f0b200f200d72210d02402003280258450d002003280254102f0b2000200d3b00012000200e3a0000200041036a200d4110763a0000200041086a200a370000200041046a2013360000410021094101210f4101211341012107410121020c1b0b2001410c6a2802002112200141086a2802002109200141046a280200210702400240200241046a280200200241086a280200220d460d002002280200210e0c010b200d41016a220e200d490d06200d410174220f200e200f200e4b1b220f4100480d0602400240200d0d00200f102d210e0c010b2002280200200d200f1031210e0b200e450d052002200e360200200241046a200f360200200241086a280200210d0b200241086a200d41016a360200200e200d6a41043a0000200341dc006a41003602002003420137025420032002360250410121104100210f4100210d2012210e03400240200d200f470d00200f41016a2213200f490d07200f41017422112013201120134b1b22134100480d0702400240200f0d002013102d21100c010b2010200f2013103121100b2010450d0620032013360258200320103602542013210f0b2003200d41016a221136025c2010200d6a200e41807f72200e41ff0071200e41077622131b3a00002011210d2013210e20130d000b024002402012450d002012410c6c21024100210e03402007200e6a220d41046a28020022134102460d01200d2802002110200d41086a2802002111024002402003280258200328025c220d460d002003280254210f0c010b200d41016a220f200d490d09200d4101742212200f2012200f4b1b22124100480d0902400240200d0d002012102d210f0c010b2003280254200d20121031210f0b200f450d08200320123602582003200f3602540b2003200d41016a36025c200f200d6a41f0003a00002003201020132011200341d0006a109b0620032d0000220d411f470d022002200e410c6a220e470d000b0b02402009450d002007102f0b20032802582109200328025421022003280250221041086a2113201041046a2111200328025c2207210e03400240024020112802002013280200220d460d002010280200210f0c010b200d41016a220f200d490d08200d4101742212200f2012200f4b1b22124100480d0802400240200d0d002012102d210f0c010b2010280200200d20121031210f0b200f450d072010200f360200201120123602002013280200210d0b2013200d41016a360200200f200d6a200e41807f72200e41ff0071200e410776220d1b3a0000200d210e200d0d000b02400240201041046a280200220e201041086a280200220d6b2007490d002010280200210e0c010b200d20076a220f200d490d07200e410174220d200f200d200f4b1b220d4100480d0702400240200e0d00200d102d210e0c010b2010280200200e200d1031210e0b200e450d062010200e360200201041046a200d360200201041086a280200210d0b201041086a200d20076a360200200e200d6a2002200710e8061a02402009450d002002102f0b41002104410121074101211241012102410121084101210b410121090c0f0b20032d0003411074210e20032f0001210f2003290308210a2003280204211302402009450d002007102f0b200f200e72210e02402003280258450d002003280254102f0b2000200e3b00012000200d3a0000200041036a200e4110763a0000200041086a200a370000200041046a2013360000410021024101210f41012113410121070c190b2001410c6a2802002112200141086a2802002104200141046a280200210902400240200241046a280200200241086a280200220d460d002002280200210e0c010b200d41016a220e200d490d05200d410174220f200e200f200e4b1b220f4100480d0502400240200d0d00200f102d210e0c010b2002280200200d200f1031210e0b200e450d042002200e360200200241046a200f360200200241086a280200210d0b200241086a200d41016a360200200e200d6a41033a0000200920124102746a21074100210f4100210d41002111410121102012210e03400240200d2011470d00200f200d41016a2213200f20134b1b22114100480d0602400240200f0d002011102d21100c010b2010200d2011103121100b2010450d050b2010200d6a200e41807f72200e41ff0071200e41077622131b3a0000200f41026a210f200d41016a210d2013210e20130d000b02402012450d00200921120340200d410174210f2012280200210e03400240200d2011470d00200d41016a2213200d490d08200f2013200f20134b1b22114100480d0802400240200d0d002011102d21100c010b2010200d2011103121100b2010450d070b2010200d6a200e41807f72200e41ff0071200e41077622131b3a0000200f41026a210f200d41016a210d2013210e20130d000b201241046a22122007470d000b0b02402004450d002009102f0b200241086a2112200241046a2107200d210f03400240024020072802002012280200220e460d00200228020021130c010b200e41016a2213200e490d06200e41017422092013200920134b1b22094100480d0602400240200e0d002009102d21130c010b2002280200200e2009103121130b2013450d0520022013360200200720093602002012280200210e0b2012200e41016a3602002013200e6a200f41807f72200f41ff0071200f410776220e1b3a0000200e210f200e0d000b02400240200241046a280200220f200241086a280200220e6b200d490d002002280200210f0c010b200e200d6a2213200e490d05200f410174220e2013200e20134b1b220e4100480d0502400240200f0d00200e102d210f0c010b2002280200200f200e1031210f0b200f450d042002200f360200200241046a200e360200200241086a280200210e0b200241086a200e200d6a360200200f200e6a2010200d10e8061a410021094101210702402011450d002010102f0b4101211241012102410121084101210b0c0c0b2001410c6a2802002111200141086a2802002116200141046a280200211402400240200241046a280200200241086a280200220d460d002002280200210e0c010b200d41016a220e200d490d04200d410174220f200e200f200e4b1b220f4100480d0402400240200d0d00200f102d210e0c010b2002280200200d200f1031210e0b200e450d032002200e360200200241046a200f360200200241086a280200210d0b200241086a200d41016a360200200e200d6a41023a0000200341dc006a410036020020034201370254200320023602502014201141286c6a21024100210d4100210e2011210f034002400240200d200e460d002003280254210d0c010b200d41016a2213200d490d05200d41017422102013201020134b1b22134100480d0502400240200d0d002013102d210d0c010b2003280254200d20131031210d0b200d450d04200320133602582003200d3602540b2003200e41016a36025c200d200e6a200f41807f72200f41ff0071200f410776220f1b3a00000240200f450d002003280258210d200328025c210e200f210f0c010b0b20142112024002402011450d00201141286c41586a21092014211203402012220d41286a2112200d2d0018220c4104460d01200d41196a2f0000200d411b6a2d0000411074722105200d41206a290000210a200d411c6a2800002110200d41146a2802002107200d41106a2802002108200d28020c2104200d280204210b200d2802002106200d2802082211210e0340024002402003280258200328025c220d460d002003280254210f0c010b200d41016a220f200d490d08200d4101742213200f2013200f4b1b22134100480d0802400240200d0d002013102d210f0c010b2003280254200d20131031210f0b200f450d07200320133602582003200f3602540b2003200d41016a36025c200f200d6a200e41807f72200e41ff0071200e410776220d1b3a0000200d210e200d0d000b024002402003280258220d200328025c220f6b2011490d00200328025421130c010b200f20116a220e200f490d07200d4101742213200e2013200e4b1b220e4100480d0702400240200d0d00200e102d21130c010b2003280254200d200e103121130b2013450d062003200e36025820032013360254200e210d0b2003200f20116a220e36025c2013200f6a2006201110e8061a0240200b450d002006102f0b2007210f034002400240200d200e460d002003280254210d0c010b200d41016a2213200d490d08200d41017422112013201120134b1b22134100480d0802400240200d0d002013102d210d0c010b2003280254200d20131031210d0b200d450d07200320133602582003200d3602540b2003200e41016a36025c200d200e6a200f41807f72200f41ff0071200f410776220f1b3a00000240200f450d002003280258210d200328025c210e200f210f0c010b0b024002402003280258220d200328025c220f6b2007490d002003280254210e0c010b200f20076a220e200f490d07200d4101742213200e2013200e4b1b22134100480d0702400240200d0d002013102d210e0c010b2003280254200d20131031210e0b200e450d06200320133602582003200e3602542013210d0b2003200f20076a221336025c200e200f6a2004200710e8061a02402008450d002004102f0b024002400240024002400240200c0e0400010203000b0240200d2013470d00200d41016a220f200d490d0c200d4101742211200f2011200f4b1b220f4100480d0c02400240200d0d00200f102d210e0c010b200e200d200f1031210e0b200e450d0b2003200f3602582003200e3602540b2003201341016a36025c200e20136a41003a00000340024002402003280258200328025c220d460d002003280254210e0c010b200d41016a220e200d490d0d200d410174220f200e200f200e4b1b220f4100480d0d02400240200d0d00200f102d210e0c010b2003280254200d200f1031210e0b200e450d0c2003200f3602582003200e3602540b2003200d41016a36025c200e200d6a201041807f72201041ff00712010410776220d1b3a0000200d2110200d0d000c040b0b0240200d2013470d00200d41016a220f200d490d0b200d4101742211200f2011200f4b1b220f4100480d0b02400240200d0d00200f102d210e0c010b200e200d200f1031210e0b200e450d0a2003200f3602582003200e3602540b2003201341016a36025c200e20136a41013a0000024002402003280258200328025c220d460d002003280254210e0c010b200d41016a220e200d490d0b200d410174220f200e200f200e4b1b220f4100480d0b02400240200d0d00200f102d210e0c010b2003280254200d200f1031210e0b200e450d0a2003200f3602582003200e3602540b2003200d41016a36025c200e200d6a41f0003a000020032010200aa7200a422088a7200341d0006a109b0620032d0000220d411f460d0220032f000120032d000341107472210e0c030b0240200d2013470d00200d41016a220f200d490d0a200d4101742211200f2011200f4b1b220f4100480d0a02400240200d0d00200f102d210e0c010b200e200d200f1031210e0b200e450d092003200f3602582003200e3602540b2003201341016a36025c200e20136a41023a000020032010200aa7200a422088a7200341d0006a109b0620032d0000220d411f460d0120032f000120032d000341107472210e0c020b0240200d2013470d00200d41016a220f200d490d09200d4101742210200f2010200f4b1b220f4100480d0902400240200d0d00200f102d210e0c010b200e200d200f1031210e0b200e450d082003200f3602582003200e3602540b2003201341016a36025c200e20136a41033a0000024002402003280258200328025c220d460d002003280254210e0c010b200d41016a220e200d490d09200d410174220f200e200f200e4b1b220f4100480d0902400240200d0d00200f102d210e0c010b2003280254200d200f1031210e0b200e450d082003200f3602582003200e3602540b2003200d41016a36025c200e200d6a2005417f73220d413f7141c00072200d2005411874411875417f4a1b3a0000024002402003280258200328025c220d460d002003280254210e0c010b200d41016a220e200d490d09200d410174220f200e200f200e4b1b220f4100480d0902400240200d0d00200f102d210e0c010b2003280254200d200f1031210e0b200e450d082003200f3602582003200e3602540b2003200d41016a36025c200e200d6a20054180fe03714100473a00000b200941586a210920122002470d010c030b0b2003290308210a2003280204210f024020022012460d0003400240201241046a280200450d002012280200102f0b0240201241106a280200450d002012410c6a280200102f0b201241286a2112200941586a22090d000b0b02402016450d002014102f0b02402003280258450d002003280254102f0b2000200e3b00012000200d3a0000200041036a200e4110763a0000200041086a200a370000200041046a200f360000410021074101210f410121130c180b20022012460d0003400240201241046a280200450d002012280200102f0b201241286a210d0240201241106a280200450d002012410c6a280200102f0b200d21122002200d470d000b0b02402016450d002014102f0b20032802582109200328025421022003280250221041086a2113201041046a2111200328025c2207210e03400240024020112802002013280200220d460d002010280200210f0c010b200d41016a220f200d490d05200d4101742212200f2012200f4b1b22124100480d0502400240200d0d002012102d210f0c010b2010280200200d20121031210f0b200f450d042010200f360200201120123602002013280200210d0b2013200d41016a360200200f200d6a200e41807f72200e41ff0071200e410776220d1b3a0000200d210e200d0d000b02400240201041046a280200220e201041086a280200220d6b2007490d002010280200210e0c010b200d20076a220f200d490d04200e410174220d200f200d200f4b1b220d4100480d0402400240200e0d00200d102d210e0c010b2010280200200e200d1031210e0b200e450d032010200e360200201041046a200d360200201041086a280200210d0b201041086a200d20076a360200200e200d6a2002200710e8061a02402009450d002002102f0b4100210b410121074101211241012102410121080c0a0b200c2009460d000340200941106a210d0240200941046a280200450d002009280200102f0b200d2109200c200d470d000b0b02402014450d002005102f0b200241086a2112200241046a2107200e210f03400240024020072802002012280200220d460d00200228020021130c010b200d41016a2213200d490d03200d41017422092013200920134b1b22094100480d0302400240200d0d002009102d21130c010b2002280200200d2009103121130b2013450d0220022013360200200720093602002012280200210d0b2012200d41016a3602002013200d6a200f41807f72200f41ff0071200f410776220d1b3a0000200d210f200d0d000b02400240200241046a280200220f200241086a280200220d6b200e490d002002280200210f0c010b200d200e6a2213200d490d02200f410174220d2013200d20134b1b220d4100480d0202400240200f0d00200d102d210f0c010b2002280200200f200d1031210f0b200f450d012002200f360200200241046a200d360200200241086a280200210d0b200241086a200d200e6a360200200f200d6a2010200e10e8061a41002108410121072011450d022010102f0c020b1036000b1038000b41012112410121020c040b200241086a200d41016a360200200e200d6a41003a0000200341dc006a41003602002003420137025420032002360250200a422088a721134100210d4100210e200aa72212210f034002400240200d200e460d002003280254210d0c010b200d41016a2210200d490d02200d41017422112010201120104b1b22104100480d0202400240200d0d002010102d210d0c010b2003280254200d20101031210d0b200d450d10200320103602582003200d3602540b2003200e41016a36025c200d200e6a200f41807f72200f41ff0071200f41077622101b3a00002003280258210d200328025c210e2010210f20100d000b02400240200d200e6b2012490d00200328025421100c010b200e20126a220f200e490d01200d4101742210200f2010200f4b1b220f4100480d0102400240200d0d00200f102d21100c010b2003280254200d200f103121100b2010450d0f2003200f36025820032010360254200f210d0b2003200e20126a220f36025c2010200e6a200c201210e8061a0240200b450d00200c102f0b034002400240200d200f460d002003280254210d0c010b200d41016a220e200d490d02200d4101742210200e2010200e4b1b220e4100480d0202400240200d0d00200e102d210d0c010b2003280254200d200e1031210d0b200d450d102003200e3602582003200d3602540b2003200f41016a36025c200d200f6a201341807f72201341ff00712013410776220e1b3a00000240200e450d002003280258210d200328025c210f200e21130c010b0b4101210202402009450d002007210e0340024002402003280258200328025c220d460d002003280254210f0c010b200d41016a220f200d490d03200d4101742213200f2013200f4b1b22134100480d0302400240200d0d002013102d210f0c010b2003280254200d20131031210f0b200f450d11200320133602582003200f3602540b2003200d41016a36025c200f200d6a200e41807f72200e41ff0071200e410776220d1b3a0000200d210e200d0d000b024002402003280258220e200328025c220d6b2007490d002003280254210e0c010b200d20076a220f200d490d02200e4101742213200f2013200f4b1b220f4100480d0202400240200e0d00200f102d210e0c010b2003280254200e200f1031210e0b200e450d102003200f3602582003200e3602540b2003200d20076a36025c200e200d6a2009200710e8061a410021022008450d002009102f0b200620044104746a21072004210e0340024002402003280258200328025c220d460d002003280254210f0c010b200d41016a220f200d490d02200d4101742213200f2013200f4b1b22134100480d0202400240200d0d002013102d210f0c010b2003280254200d20131031210f0b200f450d10200320133602582003200f3602540b2003200d41016a36025c200f200d6a200e41807f72200e41ff0071200e410776220d1b3a0000200d210e200d0d000b02402004450d002006211003402010280200220f4108460d012010410c6a2802002112201041086a280200210d2010280204210e024002400240024002400240024002400240024002400240200f0e080102030405060700010b02402003280258200328025c220f460d00200328025421130c090b200f41016a2213200f490d0d200f41017422112013201120134b1b22114100480d0d02400240200f0d002011102d21130c010b2003280254200f2011103121130b2013450d1b20032011360258200320133602540c080b024002402003280258200328025c220f460d00200328025421130c010b200f41016a2213200f490d0d200f41017422112013201120134b1b22114100480d0d02400240200f0d002011102d21130c010b2003280254200f2011103121130b2013450d1b20032011360258200320133602540b2003200f41016a36025c2013200f6a41003a00000340024002402003280258200328025c220f460d00200328025421130c010b200f41016a2213200f490d0e200f41017422112013201120134b1b22114100480d0e02400240200f0d002011102d21130c010b2003280254200f2011103121130b2013450d1c20032011360258200320133602540b2003200f41016a36025c2013200f6a200e41807f72200e41ff0071200e410776220f1b3a0000200f210e200f0d000b0340024002402003280258200328025c220e460d002003280254210f0c010b200e41016a220f200e490d0e200e4101742213200f2013200f4b1b22134100480d0e02400240200e0d002013102d210f0c010b2003280254200e20131031210f0b200f450d1c200320133602582003200f3602540b2003200e41016a36025c200f200e6a200d41807f72200d41ff0071200d410776220e1b3a0000200e210d200e0d000c090b0b024002402003280258200328025c220f460d00200328025421130c010b200f41016a2213200f490d0c200f41017422112013201120134b1b22114100480d0c02400240200f0d002011102d21130c010b2003280254200f2011103121130b2013450d1a20032011360258200320133602540b2003200f41016a36025c2013200f6a41013a00000340024002402003280258200328025c220f460d00200328025421130c010b200f41016a2213200f490d0d200f41017422112013201120134b1b22114100480d0d02400240200f0d002011102d21130c010b2003280254200f2011103121130b2013450d1b20032011360258200320133602540b2003200f41016a36025c2013200f6a200e41807f72200e41ff0071200e410776220f1b3a0000200f210e200f0d000b0340024002402003280258200328025c220e460d002003280254210f0c010b200e41016a220f200e490d0d200e4101742213200f2013200f4b1b22134100480d0d02400240200e0d002013102d210f0c010b2003280254200e20131031210f0b200f450d1b200320133602582003200f3602540b2003200e41016a36025c200f200e6a200d41807f72200d41ff0071200d410776220e1b3a0000200e210d200e0d000c080b0b024002402003280258200328025c220f460d00200328025421130c010b200f41016a2213200f490d0b200f41017422112013201120134b1b22114100480d0b02400240200f0d002011102d21130c010b2003280254200f2011103121130b2013450d1920032011360258200320133602540b2003200f41016a36025c2013200f6a41023a00000340024002402003280258200328025c220f460d00200328025421130c010b200f41016a2213200f490d0c200f41017422112013201120134b1b22114100480d0c02400240200f0d002011102d21130c010b2003280254200f2011103121130b2013450d1a20032011360258200320133602540b2003200f41016a36025c2013200f6a200e41807f72200e41ff0071200e410776220f1b3a0000200f210e200f0d000b0340024002402003280258200328025c220e460d002003280254210f0c010b200e41016a220f200e490d0c200e4101742213200f2013200f4b1b22134100480d0c02400240200e0d002013102d210f0c010b2003280254200e20131031210f0b200f450d1a200320133602582003200f3602540b2003200e41016a36025c200f200e6a200d41807f72200d41ff0071200d410776220e1b3a0000200e210d200e0d000c070b0b024002402003280258200328025c220f460d00200328025421130c010b200f41016a2213200f490d0a200f41017422112013201120134b1b22114100480d0a02400240200f0d002011102d21130c010b2003280254200f2011103121130b2013450d1820032011360258200320133602540b2003200f41016a36025c2013200f6a41033a00000340024002402003280258200328025c220f460d00200328025421130c010b200f41016a2213200f490d0b200f41017422112013201120134b1b22114100480d0b02400240200f0d002011102d21130c010b2003280254200f2011103121130b2013450d1920032011360258200320133602540b2003200f41016a36025c2013200f6a200e41807f72200e41ff0071200e410776220f1b3a0000200f210e200f0d000b0340024002402003280258200328025c220e460d002003280254210f0c010b200e41016a220f200e490d0b200e4101742213200f2013200f4b1b22134100480d0b02400240200e0d002013102d210f0c010b2003280254200e20131031210f0b200f450d19200320133602582003200f3602540b2003200e41016a36025c200f200e6a200d41807f72200d41ff0071200d410776220e1b3a0000200e210d200e0d000b20032012200341d0006a10930620032d0000220d411f460d0620032f000120032d000341107472210e0c030b024002402003280258200328025c220f460d00200328025421130c010b200f41016a2213200f490d09200f41017422112013201120134b1b22114100480d0902400240200f0d002011102d21130c010b2003280254200f2011103121130b2013450d1720032011360258200320133602540b2003200f41016a36025c2013200f6a41043a00000340024002402003280258200328025c220f460d00200328025421130c010b200f41016a2213200f490d0a200f41017422112013201120134b1b22114100480d0a02400240200f0d002011102d21130c010b2003280254200f2011103121130b2013450d1820032011360258200320133602540b2003200f41016a36025c2013200f6a200e41807f72200e41ff0071200e410776220f1b3a0000200f210e200f0d000b0340024002402003280258200328025c220e460d002003280254210f0c010b200e41016a220f200e490d0a200e4101742213200f2013200f4b1b22134100480d0a02400240200e0d002013102d210f0c010b2003280254200e20131031210f0b200f450d18200320133602582003200f3602540b2003200e41016a36025c200f200e6a200d41807f72200d41ff0071200d410776220e1b3a0000200e210d200e0d000b20032012200341d0006a10930620032d0000220d411f460d0520032f000120032d000341107472210e0c020b024002402003280258200328025c220f460d00200328025421130c010b200f41016a2213200f490d08200f41017422112013201120134b1b22114100480d0802400240200f0d002011102d21130c010b2003280254200f2011103121130b2013450d1620032011360258200320133602540b2003200f41016a36025c2013200f6a41053a00000340024002402003280258200328025c220f460d00200328025421130c010b200f41016a2213200f490d09200f41017422112013201120134b1b22114100480d0902400240200f0d002011102d21130c010b2003280254200f2011103121130b2013450d1720032011360258200320133602540b2003200f41016a36025c2013200f6a200e41807f72200e41ff0071200e410776220f1b3a0000200f210e200f0d000b0340024002402003280258200328025c220e460d002003280254210f0c010b200e41016a220f200e490d09200e4101742213200f2013200f4b1b22134100480d0902400240200e0d002013102d210f0c010b2003280254200e20131031210f0b200f450d17200320133602582003200f3602540b2003200e41016a36025c200f200e6a200d41807f72200d41ff0071200d410776220e1b3a0000200e210d200e0d000b20032012200341d0006a10930620032d0000220d411f460d0420032f000120032d000341107472210e0c010b024002402003280258200328025c220f460d00200328025421130c010b200f41016a2213200f490d07200f41017422112013201120134b1b22114100480d0702400240200f0d002011102d21130c010b2003280254200f2011103121130b2013450d1520032011360258200320133602540b2003200f41016a36025c2013200f6a41063a00000340024002402003280258200328025c220f460d00200328025421130c010b200f41016a2213200f490d08200f41017422112013201120134b1b22114100480d0802400240200f0d002011102d21130c010b2003280254200f2011103121130b2013450d1620032011360258200320133602540b2003200f41016a36025c2013200f6a200e41807f72200e41ff0071200e410776220f1b3a0000200f210e200f0d000b0340024002402003280258200328025c220e460d002003280254210f0c010b200e41016a220f200e490d08200e4101742213200f2013200f4b1b22134100480d0802400240200e0d002013102d210f0c010b2003280254200e20131031210f0b200f450d16200320133602582003200f3602540b2003200e41016a36025c200f200e6a200d41807f72200d41ff0071200d410776220e1b3a0000200e210d200e0d000c030b0b2003290308210a2003280204210f02402005450d002006102f0b2003280258450d122003280254102f0c120b2003200f41016a36025c2013200f6a41073a00000340024002402003280258200328025c220f460d00200328025421130c010b200f41016a2213200f490d06200f41017422112013201120134b1b22114100480d0602400240200f0d002011102d21130c010b2003280254200f2011103121130b2013450d1420032011360258200320133602540b2003200f41016a36025c2013200f6a200e41807f72200e41ff0071200e410776220f1b3a0000200f210e200f0d000b0340024002402003280258200328025c220e460d002003280254210f0c010b200e41016a220f200e490d06200e4101742213200f2013200f4b1b22134100480d0602400240200e0d002013102d210f0c010b2003280254200e20131031210f0b200f450d14200320133602582003200f3602540b2003200e41016a36025c200f200e6a200d41807f72200d41ff0071200d410776220e1b3a0000200e210d200e0d000b0b2003411f3a00000b201041106a22102007470d000b0b02402005450d002006102f0b20032802582106200328025421042003280250221041086a2113201041046a2111200328025c2207210e03400240024020112802002013280200220d460d002010280200210f0c010b200d41016a220f200d490d02200d4101742212200f2012200f4b1b22124100480d0202400240200d0d002012102d210f0c010b2010280200200d20121031210f0b200f450d102010200f360200201120123602002013280200210d0b2013200d41016a360200200f200d6a200e41807f72200e41ff0071200e410776220d1b3a0000200d210e200d0d000b02400240201041046a280200220e201041086a280200220d6b2007490d002010280200210e0c010b200d20076a220f200d490d01200e410174220d200f200d200f4b1b220d4100480d0102400240200e0d00200d102d210e0c010b2010280200200e200d1031210e0b200e450d0f2010200e360200201041046a200d360200201041086a280200210d0b201041086a200d20076a360200200e200d6a2004200710e8061a02402006450d002004102f0b41012112410021072009450d012002450d012008450d012009102f0c010b1038000b410121020b410121080b4101210b0b410121090b410121040b410121060b4101210c0b410121130b4101210e0b4101210f0b41012110410121110b2000411f3a000020012d0000220d410f4b0d0a02400240024002400240024002400240024002400240024002400240200d0e100001020304050607081809180a0b0c0d000b2002450d17200141086a280200450d17200141046a280200102f0c170b2012450d160240200141086a280200450d00200141046a280200102f0b200141146a280200450d16200141106a280200102f0c160b2008450d1502402001410c6a280200220e450d00200141046a280200210d200e410474210e03400240200d41046a280200450d00200d280200102f0b200d41106a210d200e41706a220e0d000b0b200141086a280200450d152001280204102f0c150b200b450d1402402001410c6a280200220e450d00200141046a280200210d200e41286c210e03400240200d41046a280200450d00200d280200102f0b0240200d41106a280200450d00200d410c6a280200102f0b200d41286a210d200e41586a220e0d000b0b200141086a280200450d142001280204102f0c140b2009450d13200141086a280200450d13200141046a280200102f0c130b2004450d12200141086a280200450d12200141046a280200102f0c120b2006450d11200141086a280200450d11200141046a280200102f0c110b200c450d1002402001410c6a280200220d450d00200141046a2802002210200d4104746a2111034002402010280208220e450d002010280200210d200e410474210e03400240200d2d00004109470d000240200d41046a2213280200220f28020441ffffffff0371450d00200f280200102f2013280200210f0b200f102f0b200d41106a210d200e41706a220e0d000b0b201041106a210d0240201041046a280200450d002010280200102f0b200d2110200d2011470d000b0b200141086a280200450d102001280204102f0c100b2013450d0f02402001410c6a280200220e450d00200141046a280200210d200e41146c210e03400240200d41046a280200450d00200d280200102f0b200d41146a210d200e416c6a220e0d000b0b200141086a280200450d0f2001280204102f0c0f0b200e450d0e200141046a220d10a206200141086a280200450d0e200d280200102f0c0e0b200f450d0d02402001410c6a280200220d450d00200141046a2802002210200d41186c6a211103400240201041046a280200450d002010280200102f0b0240201041146a280200220e450d00201028020c210d200e410474210e03400240200d2d00004109470d000240200d41046a2213280200220f28020441ffffffff0371450d00200f280200102f2013280200210f0b200f102f0b200d41106a210d200e41706a220e0d000b0b201041186a210d0240201041106a280200450d00201028020c102f0b200d2110200d2011470d000b0b200141086a280200450d0d2001280204102f0c0d0b2010450d0c200141046a220d10a206200141086a280200450d0c200d280200102f0c0c0b2011450d0b0240200141046a280200220d450d00200141086a280200450d00200d102f0b0240200141146a280200220d450d0002402001411c6a280200220e450d00200e410c6c210e03400240200d280200220f450d00200d41046a280200450d00200f102f0b200d410c6a210d200e41746a220e0d000b0b200141186a280200450d002001280214102f0b200141246a2802002210450d0b02402001412c6a280200220d450d002010200d4104746a211103402010221341106a211002402013280204220d450d0002402013410c6a280200220e450d00200e410c6c210e03400240200d280200220f450d00200d41046a280200450d00200f102f0b200d410c6a210d200e41746a220e0d000b0b201341086a280200450d002013280204102f0b20102011470d000b0b200141286a280200450d0b2001280224102f0c0b0b2007450d0a0240200141086a280200450d00200141046a280200102f0b0240200141146a280200220d450d00200141186a280200450d00200d102f0b200141246a280200450d0a200141206a280200102f0c0a0b02402009450d002002450d002008450d002009102f0b2000200e3b00012000200d3a0000200041036a200e4110763a0000200041086a200a370000200041046a200f360000410121134100210f0c010b1036000b410121070b410121020b410121090b410121040b4101210e0b410121100b41012111410121120b20012d0000220d410f4b0d0002400240024002400240024002400240024002400240024002400240200d0e100001020304050607080e090e0a0b0c0d000b200141086a280200450d0d200141046a280200102f0c0d0b2013450d0c0240200141086a280200450d00200141046a280200102f0b200141146a280200450d0c200141106a280200102f0c0c0b02402001410c6a280200220e450d00200141046a280200210d200e410474210e03400240200d41046a280200450d00200d280200102f0b200d41106a210d200e41706a220e0d000b0b200141086a280200450d0b2001280204102f0c0b0b2007450d0a02402001410c6a280200220e450d00200141046a280200210d200e41286c210e03400240200d41046a280200450d00200d280200102f0b0240200d41106a280200450d00200d410c6a280200102f0b200d41286a210d200e41586a220e0d000b0b200141086a280200450d0a2001280204102f0c0a0b200141086a280200450d09200141046a280200102f0c090b2002450d08200141086a280200450d08200141046a280200102f0c080b2009450d07200141086a280200450d07200141046a280200102f0c070b2004450d0602402001410c6a280200220d450d00200141046a2802002210200d4104746a2111034002402010280208220e450d002010280200210d200e410474210e03400240200d2d00004109470d000240200d41046a2213280200220f28020441ffffffff0371450d00200f280200102f2013280200210f0b200f102f0b200d41106a210d200e41706a220e0d000b0b201041106a210d0240201041046a280200450d002010280200102f0b200d2110200d2011470d000b0b200141086a280200450d062001280204102f0c060b02402001410c6a280200220e450d00200141046a280200210d200e41146c210e03400240200d41046a280200450d00200d280200102f0b200d41146a210d200e416c6a220e0d000b0b200141086a280200450d052001280204102f0c050b200e450d04200141046a220d10a206200141086a280200450d04200d280200102f0c040b2010450d0302402001410c6a280200220d450d00200141046a2802002210200d41186c6a211103400240201041046a280200450d002010280200102f0b0240201041146a280200220e450d00201028020c210d200e410474210e03400240200d2d00004109470d000240200d41046a2213280200220f28020441ffffffff0371450d00200f280200102f2013280200210f0b200f102f0b200d41106a210d200e41706a220e0d000b0b201041186a210d0240201041106a280200450d00201028020c102f0b200d2110200d2011470d000b0b200141086a280200450d032001280204102f0c030b2011450d02200141046a220d10a206200141086a280200450d02200d280200102f0c020b2012450d010240200141046a280200220d450d00200141086a280200450d00200d102f0b0240200141146a280200220d450d0002402001411c6a280200220e450d00200e410c6c210e03400240200d280200220f450d00200d41046a280200450d00200f102f0b200d410c6a210d200e41746a220e0d000b0b200141186a280200450d002001280214102f0b200141246a2802002210450d0102402001412c6a280200220d450d002010200d4104746a211103402010221341106a211002402013280204220d450d0002402013410c6a280200220e450d00200e410c6c210e03400240200d280200220f450d00200d41046a280200450d00200f102f0b200d410c6a210d200e41746a220e0d000b0b201341086a280200450d002013280204102f0b20102011470d000b0b200141286a280200450d012001280224102f0c010b200f450d000240200141086a280200450d00200141046a280200102f0b0240200141146a280200220d450d00200141186a280200450d00200d102f0b200141246a280200450d00200141206a280200102f0b200341e0006a24000b1300200041073602042000418c97c6003602000b3400200041eba1c60036020420004100360200200041146a4102360200200041106a4180a2c600360200200041086a42133702000bca09020b7f027e230041106b220224002002410036020820024201370300024002404120102d2203450d002003200029004c370000200341186a2204200041e4006a290000370000200341106a2205200041dc006a290000370000200341086a2206200041d4006a2900003700004120102d2207450d00200242a080808080043702042002200736020020072003290000370000200741086a2006290000370000200741106a2005290000370000200741186a20042900003700002003102f2007412041c00010312203450d002003200029006c370020200341286a200041f4006a290000370000200341306a200041fc006a290000370000200341386a20004184016a290000370000200242c08080808008370204200220033602000240024020002903004201510d00200341c00041800110312203450d02200341003a00402002428081808090083702042002200336020041c10021070c010b200341c00041800110312203450d01200341013a00402003200041086a2207290000370041200341e9006a200041306a2903003700002003200041286a290300370061200341c9006a200741086a290000370000200341d1006a200741106a290000370000200341d9006a200741186a29000037000020024280818080900e3702042002200336020041f10021070b0240024020002802384101460d002002200741016a360208200320076a41003a00000c010b2002200741016a360208200320076a41013a00002000413c6a28020021040240024020022802042207200228020822036b4104490d00200228020021070c010b200341046a22052003490d03200741017422062005200620054b1b22054100480d030240024020070d002005102d21070c010b200228020020072005103121070b2007450d0220022005360204200220073602000b2002200341046a360208200720036a20043600000b20002802402108200041c8006a2802002200200210690240024020000d002002280208210020022802042104200228020021070c010b2008200041306c6a210941002002280208220a6b210520022802042104410021030340200a20036a210602400240200420056a4120490d00200228020021070c010b200641206a22002006490d04200441017422072000200720004b1b22004100480d040240024020040d002000102d21070c010b200228020020042000103121070b2007450d032002200036020420022007360200200021040b2007200a6a20036a220b41186a200820036a220041186a290000370000200b41106a200041106a290000370000200b41086a200041086a2900003700002002200641206a220c360208200b2000290000370000200041286a290300210d200041206a290300210e0240200420056a41606a410f4b0d00200c41106a220b200c490d042004410174220c200b200c200b4b1b220b4100480d040240024020040d00200b102d21070c010b20072004200b103121070b2007450d032002200b36020420022007360200200b21040b2007200a6a20036a220b41286a200d370000200b41206a200e3700002002200641306a360208200541506a2105200341306a21032009200041306a470d000b200a20036a21000b20012902002000ad4220862007ad84100402402004450d002007102f0b200241106a24000f0b1036000b1038000bbd0101037f230041206b2203240002400240200241286c4104722204417f4c0d002004102d2205450d01200341003602102003200436020c200320053602082002200341086a106902402002450d002001200241286c6a21020340200341086a200141201082012003200141206a290300370318200341086a200341186a41081082012002200141286a2201470d000b0b20002003290308370200200041086a200341086a41086a280200360200200341206a24000f0b103d000b1036000bb91107027f037e037f027e017f027e047f230041d0006b220324000240024002400240024020002802002d0000200141ff0171460d002000280208210441c6b5c400ad4280808080f00084100122002900002105200341106a41086a200041086a290000370300200320053703102000102f41f6dbc400ad4280808080f00084100122002900002105200341206a41086a200041086a290000370300200320053703202000102f4120102d2200450d0120002002290000370000200041186a200241186a290000370000200041106a200241106a290000370000200041086a200241086a2900003700002000ad4280808080800484100322012900002105200141086a2900002106200141106a2900002107200341306a41186a2208200141186a290000370300200341306a41106a22092007370300200341306a41086a2006370300200320053703302001102f2000102f41c000102d2200450d01200020032903103700002000200329032037001020002003290330370020200041086a200341106a41086a290300370000200041186a200341206a41086a290300370000200041286a200341306a41086a290300370000200041306a2009290300370000200041386a2008290300370000200341306a200010b70420032902342105200328023021012000102f2001410820011b210a428080d287e2bc2d210b4200210702402005420020011b220c422088a7220d450d0002400240200d41186c22000d0042002107428080d287e2bc2d210b410021010c010b200a20006a210842002106428080d287e2bc2d210541002101200a21000240034002402005200041086a290300220e7d220b2005562006200041106a290300220f7d2005200e54ad7d220720065620072006511b450d00200041086a200e20057d370300200041106a200f20067d200e200554ad7d3703004200210b420021070c020b200141016a2101200b2105200721062008200041186a2200470d000b0b2001200d4b0d040b41c6b5c400ad4280808080f00084100122002900002105200341106a41086a200041086a290000370300200320053703102000102f41f6dbc400ad4280808080f00084100122002900002105200341206a41086a200041086a290000370300200320053703202000102f4120102d2200450d0220002002290000370000200041186a200241186a290000370000200041106a200241106a290000370000200041086a200241086a2900003700002000ad4280808080800484100322082900002105200841086a2900002106200841106a290000210e200341306a41186a2209200841186a290000370300200341306a41106a2210200e370300200341306a41086a2006370300200320053703302008102f2000102f41c000102d2211450d02201120032903103700002011200329032037001020112003290330370020201141086a200341106a41086a290300370000201141186a200341206a41086a290300370000201141286a200341306a41086a290300370000201141306a2010290300370000201141386a2009290300370000200d20016b220841186c4104722200417f4c0d042000102d2209450d022003410036023820032000360234200320093602302008200341306a1069024002402001200d470d002003280238210020032802342108200328023021010c010b200a200141186c6a2109200a200d41186c6a21124100200328023822006b210d20032802342108034020092802002110024002402008200d6a4104490d00200328023021010c010b200041046a22012000490d08200841017422132001201320014b1b22134100480d080240024020080d002013102d21010c010b200328023020082013103121010b2001450d052003201336023420032001360230201321080b2003200041046a2213360238200120006a2010360000200941106a2903002105200941086a290300210602402008200d6a417c6a410f4b0d00201341106a22102013490d08200841017422132010201320104b1b22104100480d080240024020080d002010102d21010c010b200120082010103121010b2001450d052003201036023420032001360230201021080b200120006a2210410c6a2005370000201041046a20063700002003200041146a2200360238200d416c6a210d200941186a22092012470d000b0b2011ad42808080808008842000ad4220862001ad84100402402008450d002001102f0b2011102f0b0240200ca7450d00200a102f0b41c6b5c400ad4280808080f00084100122002900002105200341106a41086a200041086a290000370300200320053703102000102f41efdbc400ad4280808080f00084100122002900002105200341206a41086a200041086a290000370300200320053703202000102f4120102d2200450d0120002002290000370000200041186a200241186a290000370000200041106a200241106a290000370000200041086a200241086a2900003700002000ad4280808080800484100322012900002105200141086a2900002106200141106a290000210e200341306a41186a2208200141186a290000370300200341306a41106a2209200e370300200341306a41086a2006370300200320053703302001102f2000102f41c000102d2200450d01428080d287e2bc2d200b7d210542002007200b428080d287e2bc2d56ad7c7d2106200020032903103700002000200329032037001020002003290330370020200041086a200341106a41086a290300370000200041186a200341206a41086a290300370000200041286a200341306a41086a290300370000200041306a2009290300370000200041386a2008290300370000200341086a200041c0001095012003200328020c41016a410120032802081b22013602302000ad4280808080800884200341306aad4280808080c0008410042000102f02402001410a490d00200210b5040b2004200520042903007c2207370300200441086a2200200620002903007c2007200554ad7c370300410021020b200341d0006a240020020f0b1036000b2001200d104b000b103d000b1038000b950201047f230041d0006b22012400200141c00036020420012000360200200141086a2000ad42808080808008841002107302400240200128020822020d00410221000c010b200128020c210302400240200141106a280200450d0020022d0000220441014b0d0041002100024020040e020200020b410121000c010b20014100360220200142013703182001410b36022c200120013602282001200141186a360234200141cc006a41013602002001420137023c200141b885c7003602382001200141286a360248200141346a41d8dbc100200141386a103c1a200135022042208620013502188410080240200128021c450d002001280218102f0b410221000b2003450d002002102f0b200141d0006a240020000b8b0503027f017e047f230041d0006b220224004180a3ca00ad4280808080800184100122032900002104200241086a200341086a290000370300200220043703002003102f41a084c600ad4280808080f00084100122032900002104200241106a41086a200341086a290000370300200220043703102003102f024002404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad4280808080800484100622012900003703302001102f200241c4006a200341206a360200200241003a0048200220033602402002200241306a41086a36023c2002200241306a360238200241206a200241386a106c2003102f02400240024002402002280228220541206a2201417f4c0d0020022802202106024002402001450d002001102d2203450d062001410f4d0d01200121070c050b411021074110102d21030c030b200141017422084110200841104b1b220741004e0d010c050b103d000b200320012007103121030b2003450d010b20032002290300370000200341086a200241086a2903003700000240024020074170714110460d00200721080c010b200741017422084120200841204b1b22084100480d0220032007200810312203450d010b20032002290310370010200341186a200241106a41086a29030037000002400240200841606a2005490d00200821070c010b2005415f4b0d02200841017422072001200720014b1b22074100480d0220032008200710312203450d010b200341206a2006200510e8061a20002001360208200020073602042000200336020002402002280224450d002006102f0b200241d0006a24000f0b1036000b1038000b8b0503027f017e047f230041d0006b220224004180a3ca00ad4280808080800184100122032900002104200241086a200341086a290000370300200220043703002003102f41c883c600ad4280808080c00084100122032900002104200241106a41086a200341086a290000370300200220043703102003102f024002404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad4280808080800484100622012900003703302001102f200241c4006a200341206a360200200241003a0048200220033602402002200241306a41086a36023c2002200241306a360238200241206a200241386a106c2003102f02400240024002402002280228220541206a2201417f4c0d0020022802202106024002402001450d002001102d2203450d062001410f4d0d01200121070c050b411021074110102d21030c030b200141017422084110200841104b1b220741004e0d010c050b103d000b200320012007103121030b2003450d010b20032002290300370000200341086a200241086a2903003700000240024020074170714110460d00200721080c010b200741017422084120200841204b1b22084100480d0220032007200810312203450d010b20032002290310370010200341186a200241106a41086a29030037000002400240200841606a2005490d00200821070c010b2005415f4b0d02200841017422072001200720014b1b22074100480d0220032008200710312203450d010b200341206a2006200510e8061a20002001360208200020073602042000200336020002402002280224450d002006102f0b200241d0006a24000f0b1036000b1038000b9f1005097f037e027f037e037f230041f0026b220324002003200236020c20032001360208200341106a2002ad4220862001ad8410021073024002400240024020032802102204450d00200328021421052003200341186a28020022063602a401200320043602a00141002107200341003a00e8022004210220062101024002400240024002400340200721082001450d01200341c8026a20086a20022d00003a000020032001417f6a22013602a4012003200241016a22023602a0012003200841016a22073a00e80220074120470d000b200341a8016a41086a200341c8026a41086a290300370300200341a8016a41106a200341c8026a41106a290300370300200341a8016a41186a200341c8026a41186a290300370300200320032903c8023703a80141002107200341003a00e802200620086b417e6a2108034020012007460d02200341c8026a20076a200220076a22062d00003a00002003200641016a3602a0012003200741016a22063a00e802200320083602a4012008417f6a21082006210720064120470d000b200341c8016a41086a200341c8026a41086a290300370300200341c8016a41106a200341c8026a41106a290300370300200341c8016a41186a200341c8026a41186a290300370300200320032903c8023703c80120012006460d06200220066a22092d00002102200320083602a4012003200941016a22073602a001200241014b0d0620020e020302030b200841ff0171450d05200341003a00e8020c050b200741ff0171450d04200341003a00e8020c040b200941116a210741002102200341003a00e802200120066b416f6a21010240034020082002460d01200341c8026a20026a200920026a41016a2d00003a000020032001410f6a3602a4012003200741716a3602a0012003200241016a22063a00e8022001417f6a2101200741016a21072006210220064120470d000b200341a8026a41186a2202200341c8026a41186a290300370300200341a8026a41106a220a200341c8026a41106a290300370300200341a8026a41086a220b200341c8026a41086a290300370300200320032903c8023703a802200820066b4110490d04200920066a220841096a290000210c200841016a290000210d20034188026a41086a200b29030037030020034188026a41106a200a29030037030020034188026a41186a2002290300370300200320013602a401200320073602a001200320032903a802370388024201210e200121080c020b200241ff0171450d03200341003a00e8020c030b4200210e0b200341e8016a41186a20034188026a41186a290300370300200341e8016a41106a20034188026a41106a290300370300200341e8016a41086a20034188026a41086a29030037030020032003290388023703e8012008450d0120072d0000210120032008417f6a22023602a4012003200741016a3602a001200141014b0d01410021060240024020010e020100010b20024104490d022007280001210920032008417b6a3602a4012003200741056a3602a001410121060b200341c8026a200341a0016a10f70320032802c802450d01200341f0006a41086a2202200341c8026a41086a2201280200360200200341d0006a41086a2207200341a8016a41086a290300370300200341d0006a41106a2208200341a8016a41106a290300370300200341d0006a41186a220a200341a8016a41186a290300370300200341306a41086a220b200341c8016a41086a290300370300200341306a41106a220f200341c8016a41106a290300370300200341306a41186a2210200341c8016a41186a290300370300200320032903c802370370200320032903a801370350200320032903c80137033020034180016a41186a200341e8016a41186a290300221137030020034180016a41106a200341e8016a41106a290300221237030020034180016a41086a200341e8016a41086a290300221337030020012013370300200341c8026a41106a22142012370300200341c8026a41186a22152011370300200341206a41086a22162002280200360200200320032903e801221137038001200320113703c80220032003290370370320200341a8026a41186a2202200a290300370300200341a8026a41106a220a2008290300370300200341a8026a41086a22082007290300370300200320032903503703a80220034188026a41186a2207201029030037030020034188026a41106a2210200f29030037030020034188026a41086a220f200b2903003703002003200329033037038802200041306a200c370300200041286a200d3703002000413c6a2009360200200041386a2006360200200041206a2015290300370300200041186a2014290300370300200041106a2001290300370300200020032903c802370308200041c0006a2003290320370300200041c8006a2016280200360200200020032903a80237024c200041d4006a2008290300370200200041dc006a200a290300370200200041e4006a200229030037020020004184016a2007290300370200200041fc006a2010290300370200200041f4006a200f290300370200200020032903880237026c0c020b200042023703000c020b200341003602b002200342013703a8022003410b36028c022003200341086a360288022003200341a8026a3602e801200341dc026a4101360200200342013702cc02200341b885c7003602c802200320034188026a3602d802200341e8016a41d8dbc100200341c8026a103c1a20033502b00242208620033502a802841008024020032802ac02450d0020032802a802102f0b4202210e0b2000200e3703002005450d002004102f0b200341f0026a24000b830303047f017e027f230041d0006b22012400200141206a41186a4200370300200141206a41106a22024200370300200141206a41086a220342003703002001420037032041bd98ca00ad42808080808002841001220429000021052003200441086a290000370300200120053703202004102f41ebdec700ad4280808080f00084100122042900002105200141c0006a41086a2206200441086a290000370300200120053703402004102f200220012903402205370300200141086a2003290300370300200141106a2005370300200141186a200629030037030020012001290320370300200141206a200110e40420012802202204410820041b2107410021030240024002402001290224420020041b2205422088a7220441014b0d0020040e020201020b03402004410176220220036a220620032007200641306c6a2000412010ea064101481b2103200420026b220441014b0d000b0b2007200341306c6a2000412010ea064521030b02402005a7450d002007102f0b200141d0006a240020030b8b0503027f017e047f230041d0006b220224004180a3ca00ad4280808080800184100122032900002104200241086a200341086a290000370300200220043703002003102f41c883c600ad4280808080c00084100122032900002104200241106a41086a200341086a290000370300200220043703102003102f024002404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad4280808080800484100622012900003703302001102f200241c4006a200341206a360200200241003a0048200220033602402002200241306a41086a36023c2002200241306a360238200241206a200241386a106c2003102f02400240024002402002280228220541206a2201417f4c0d0020022802202106024002402001450d002001102d2203450d062001410f4d0d01200121070c050b411021074110102d21030c030b200141017422084110200841104b1b220741004e0d010c050b103d000b200320012007103121030b2003450d010b20032002290300370000200341086a200241086a2903003700000240024020074170714110460d00200721080c010b200741017422084120200841204b1b22084100480d0220032007200810312203450d010b20032002290310370010200341186a200241106a41086a29030037000002400240200841606a2005490d00200821070c010b2005415f4b0d02200841017422072001200720014b1b22074100480d0220032008200710312203450d010b200341206a2006200510e8061a20002001360208200020073602042000200336020002402002280224450d002006102f0b200241d0006a24000f0b1036000b1038000b970404047f017e057f027e230041d0006b22012400200141206a41186a4200370300200141206a41106a22024200370300200141206a41086a220342003703002001420037032041bd98ca00ad42808080808002841001220429000021052003200441086a290000370300200120053703202004102f41ebdec700ad4280808080f00084100122042900002105200141c0006a41086a2206200441086a290000370300200120053703402004102f200220012903402205370300200141086a2003290300370300200141106a2005370300200141186a200629030037030020012001290320370300200141206a200110e40441002102024002400240024020012902244200200128022022031b2205422088a7220441306c22060d0041012107410021080c010b200641306d220641ffffff3f712006470d02200641057422064100480d022006102d2207450d01200641057621080b2005a721092003410820031b210a02402004450d00200441306c21064100210220072103200a21040340200441086a2900002105200441106a290000210b2004290000210c200341186a200441186a290000370000200341106a200b370000200341086a20053700002003200c370000200241016a2102200341206a2103200441306a2104200641506a22060d000b0b02402009450d00200a102f0b200020023602082000200836020420002007360200200141d0006a24000f0b1036000b1038000bc00201027f230041e0006b220224002002412036020c20022001360208200241106a2001ad4280808080800484100210730240024020022802102201450d00200228021421032002200241106a41086a28020036022420022001360220200241c8006a200241206a10f703024002402002280248450d0020002002290348370200200041086a200241c8006a41086a2802003602000c010b20024100360230200242013703282002410b36023c2002200241086a3602382002200241286a360244200241dc006a41013602002002420137024c200241b885c7003602482002200241386a360258200241c4006a41d8dbc100200241c8006a103c1a200235023042208620023502288410080240200228022c450d002002280228102f0b200041003602000b2003450d012001102f0c010b200041003602000b200241e0006a24000b130020004101360204200041bca4c6003602000bd71e03077f027e077f230041b0026b22052400200028020021064100210702400240024002400240024002400240024002400240200041086a280200220841014b0d0020080e020201020b20082109034020072009410176220a20076a220b2006200b41e8006c6a220b41386a290300200256200b41c0006a290300220c200356200c2003511b1b21072009200a6b220941014b0d000b0b2006200741e8006c6a220941386a290300220d200285200941c0006a290300220c20038584500d012007200d200254200c200354200c2003511b6a21070b200541b0016a41086a200441086a290300370300200541b0016a41106a200441106a290300370300200541b0016a41186a200441186a290300370300200541b0016a41206a200441206a290300370300200541b0016a41286a200441286a290300370300200541b0016a41306a200441306a290300370300200541286a41086a200141086a290000370300200541286a41106a200141106a290000370300200541286a41186a200141186a290000370300200520042903003703b0012005200129000037032820082007490d0202402008200041046a280200220b470d00200841016a22092008490d072008410174220a2009200a20094b1bad42e8007e220c422088a70d07200ca722094100480d070240024020080d002009102d21060c010b2006200841e8006c2009103121060b2006450d0420002006360200200041046a200941e8006e220b3602000b2006200741e8006c6a220941e8006a2009200820076b41e8006c10e9061a200941c0006a200337030020092002370338200941306a200541b0016a41306a290300370300200941286a200541b0016a41286a290300370300200941206a200541b0016a41206a290300370300200941186a200541b0016a41186a290300370300200941106a200541b0016a41106a290300370300200941086a200541b0016a41086a290300370300200920052903b00137030020092005290328370348200941d0006a200541286a41086a290300370300200941d8006a200541286a41106a290300370300200941e0006a200541286a41186a290300370300200041086a200841016a22093602000c010b0240024002400240024020070d002006210a0c010b20082007417f6a22094d0d012006200941e8006c6a41e8006a210a0b200a2006200841e8006c6a460d00200820074d0d06200a290338200256200a41c0006a290300220c200356200c2003511b0d01200a41e8006a2109200841e8006c20066a200a6b41987f6a210a0340200a450d01200741016a21072009290338210c200941c0006a210b200a41987f6a210a200941e8006a2109200c200256200b290300220c200356200c2003511b0d020c000b0b200541286a41186a2209200141186a290000370300200541286a41106a220a200141106a290000370300200541286a41086a220e200141086a290000370300200541b0016a41086a220f200441086a290300370300200541b0016a41106a2210200441106a290300370300200541b0016a41186a2211200441186a290300370300200541b0016a41206a2212200441206a290300370300200541b0016a41286a2213200441286a290300370300200541b0016a41306a2214200441306a29030037030020052001290000370328200520042903003703b00102402008200041046a280200220b470d00200841016a22072008490d082008410174220b2007200b20074b1bad42e8007e220c422088a70d08200ca722074100480d080240024020080d002007102d21060c010b2006200841e8006c2007103121060b2006450d0520002006360200200041046a200741e8006e220b3602000b2006200841e8006c6a22072002370338200720052903b00137030020072005290328370348200741c0006a2003370300200741306a2014290300370300200741286a2013290300370300200741206a2012290300370300200741186a2011290300370300200741106a2010290300370300200741086a200f290300370300200741d0006a200e290300370300200741d8006a200a290300370300200741e0006a20092903003703000c010b200541b0016a41086a200441086a290300370300200541b0016a41106a200441106a290300370300200541b0016a41186a200441186a290300370300200541b0016a41206a200441206a290300370300200541b0016a41286a200441286a290300370300200541b0016a41306a200441306a290300370300200541286a41086a200141086a290000370300200541286a41106a200141106a290000370300200541286a41186a200141186a290000370300200520042903003703b0012005200129000037032820082007490d0502402008200041046a280200220b470d00200841016a22092008490d072008410174220a2009200a20094b1bad42e8007e220c422088a70d07200ca722094100480d070240024020080d002009102d21060c010b2006200841e8006c2009103121060b2006450d0420002006360200200041046a200941e8006e220b3602000b2006200741e8006c6a220941e8006a2009200820076b41e8006c10e9061a200941c0006a200337030020092002370338200941306a200541b0016a41306a290300370300200941286a200541b0016a41286a290300370300200941206a200541b0016a41206a290300370300200941186a200541b0016a41186a290300370300200941106a200541b0016a41106a290300370300200941086a200541b0016a41086a290300370300200920052903b00137030020092005290328370348200941d0006a200541286a41086a290300370300200941d8006a200541286a41106a290300370300200941e0006a200541286a41186a2903003703000b200041086a200841016a22093602000b0240200941e907490d00200041086a2009417f6a22093602002006200941e8006c6a220741106a2903002103200741086a290300210c20072d0000210a20072800012101200741046a280000210e200541f8006a41186a2208200741306a290300370300200541f8006a41106a2204200741286a290300370300200541f8006a41086a2200200741206a290300370300200741186a2903002102200541b0016a41286a220f200741e0006a290300370300200541b0016a41206a2210200741d8006a29030037030020052002370378200541b0016a41186a2211200741d0006a290300370300200541b0016a41106a2212200741c8006a290300370300200541b0016a41086a2213200741c0006a2903003703002005200e36000320052001360200200520072903383703b001200a4102460d06200541d8006a41086a22072000290300370300200541d8006a41106a22012004290300370300200541d8006a41186a220e2008290300370300200541286a41086a2013290300370300200541286a41106a22132012290300370300200541286a41186a22122011290300370300200541286a41206a22112010290300370300200541286a41286a2210200f2903003703002005200528000336009b01200520052802003602980120052005290378370358200520052903b001370328200541186a2010290300370300200541106a2011290300370300200541086a20122903003703002005201329030037030020052005280298013602202005200528009b0136002320002007290300370300200420012903003703002008200e2903003703002005200529035837037802400240200a410171450d0020054198016a41086a220a200541f8006a41086a2d00003a0000200520052802203602a801200520052800233600ab01200520052903783703980141c6b5c400ad4280808080f00084100122072900002102200541d8006a41086a200741086a290000370300200520023703582007102f41d8cdc500ad4280808080800184100122072900002102200541286a41086a200741086a290000370300200520023703282007102f4120102d2207450d042007200c370007200720052802a80136000020072005290398013700172007410f6a2003370000200741036a20052800ab013600002007411f6a200a2d00003a00002007ad42808080808004841003220a2900002103200a41086a290000210c200a41106a2900002102200541b0016a41186a2208200a41186a290000370300200541b0016a41106a22042002370300200541b0016a41086a200c370300200520033703b001200a102f2007102f41c000102d2207450d042007200529035837000020072005290328370010200720052903b001370020200741086a200541d8006a41086a290300370000200741186a200541286a41086a290300370000200741286a200541b0016a41086a290300370000200741306a2004290300370000200741386a20082903003700002007ad428080808080088410052007102f0c010b2005200c37035820052003370360200c200384500d002005200536029801200541286a2005200541d8006a20054198016a10960120052903284201520d0020052903302103200541e8016a200541286a41106a290300370300200541e0016a2003370300200541b0016a41086a41003a0000200541b9016a2005290300370000200541c1016a200541086a290300370000200541c9016a200541106a290300370000200541d1016a200541186a290300370000200541033a00b00141c8e1ca004100200541b0016a108c010b200541b0016a41086a41033a0000200541b9016a2005290300370000200541c1016a200541086a290300370000200541c9016a200541106a290300370000200541d1016a200541186a290300370000200541123a00b00141c8e1ca004100200541b0016a108c010b200541b0016a41186a4200370300200541b0016a41106a22084200370300200541b0016a41086a22074200370300200542003703b00141c6b5c400ad4280808080f000841001220a29000021032007200a41086a290000370300200520033703b001200a102f41b4dac400ad4280808080c000841001220a2900002103200541f8006a41086a2204200a41086a29000037030020052003370378200a102f200820052903782203370300200541286a41086a2007290300370300200541286a41106a2003370300200541286a41186a2004290300370300200520052903b001370328200541b0016a2006200910b104200541286aad428080808080048420053502b80142208620052802b0012207ad841004024020052802b401450d002007102f0b0240200b450d002006102f0b200541b0026a24000f0b419ae3c300411e41f8b4ca001039000b1036000b41c4c2ca0020072008103b000b419ae3c300411e41f8b4ca001039000b1038000b419da5c600411341b0a5c6001055000bb00a05047f017e017f017e077f230041e0006b22022400200241306a41186a22034200370300200241306a41106a22044200370300200241306a41086a220542003703002002420037033041c6b5c400ad4280808080f0008422061001220729000021082005200741086a290000370300200220083703302007102f41ebdec700ad4280808080f00084100122092900002108200241d0006a41086a2207200941086a290000370300200220083703502009102f200420022903502208370300200241106a41086a220a2005290300370300200241106a41106a220b2008370300200241106a41186a220c200729030037030020022002290330370310200241306a200241106a412010aa02024002402002280230220d0d004101210d420021084100210e4100210f0c010b20022902342208422088a7210f2008a7210e0b2003420037030020044200370300200542003703002002420037033020061001220929000021062007200941086a290000370300200220063703502009102f200520072903003703002002200229035037033041cdb5c400ad4280808080a001841001220929000021062007200941086a290000370300200220063703502009102f200420022903502206370300200a2005290300370300200b2006370300200c200729030037030020022002290330370310200241086a200241106a412010950102400240024002400240024002400240024002400240200f200228020c410020022802081b4f0d00024002400240200f41014b0d0041002105200f0e020201020b200f210741002105034020052007410176220920056a2203200d20034105746a2001412010ea0641004a1b2105200720096b220741014b0d000b0b200d20054105746a2001412010ea062207450d022007411f7620056a21050b200241306a41186a200141186a290000370300200241306a41106a200141106a290000370300200241306a41086a200141086a29000037030020022001290000370330200f2005490d07200f200e470d04200e2008a7470d04200e41016a2207200e490d09200e41017422092007200920074b1b220741ffffff3f712007470d09200741057422074100480d09200e0d022007102d210d0c030b20004183323b0100200041086a410a360200200041046a41cdb5c400360200200041026a410f3a00002008a7450d09200d102f0c090b200e0d030c040b200d200e41057420071031210d0b200d450d042007410576ad21080b200d20054105746a220741206a2007200f20056b41057410e9061a200741186a200241306a41186a2209290300370000200741106a200241306a41106a2203290300370000200741086a200241306a41086a2205290300370000200720022903303700002009420037030020034200370300200542003703002002420037033041c6b5c400ad4280808080f00084100122012900002106200241d0006a41086a2207200141086a290000370300200220063703502001102f200520072903003703002002200229035037033041ebdec700ad4280808080f000841001220129000021062007200141086a290000370300200220063703502001102f20042002290350370000200441086a2007290300370000200241106a41086a2005290300370300200241106a41106a2003290300370300200241106a41186a200929030037030020022002290330370310200241203602342002200241106a360230200d200f41016a200241306a10aa012008a7450d010b200d102f0b200041043a00000c030b419ae3c300411e41f8b4ca001039000b1036000b1038000b200241e0006a24000b810b031d7f017e017f230041b0016b2202240041012103024020012d00000d002001411d6a2d000021042001411c6a2d000021052001411a6a2f00002106200141196a2d00002107200141186a2d00002108200141166a2f00002109200141156a2d0000210a200141146a2d0000210b200141126a2f0000210c200141116a2d0000210d200141106a2d0000210e2001410e6a2f0000210f2001410d6a2d000021102001410c6a2d000021112001410a6a2f00002112200141096a2d00002113200141086a2d00002114200141066a2f00002115200141056a2d00002116200141046a2d00002117200141026a2f0000211820012d00012103200141206a2d00002119200141216a2d0000211a2001411e6a2f0000211b20024190016a41186a221c420037030020024190016a41106a221d420037030020024190016a41086a22014200370300200242003703900141c6b5c400ad4280808080f000841001221e290000211f2001201e41086a2900003703002002201f37039001201e102f4193b6c400ad4280808080f000841001221e290000211f200241c8006a41086a2220201e41086a2900003703002002201f370348201e102f201d2002290348221f370300200241f0006a41086a2001290300370300200241f0006a41106a201f370300200241f0006a41186a20202903003703002002200229039001370370200241c8006a200241f0006a412010ad0220022d0048211e201c200241c8006a41196a290000370300201d200241c8006a41116a2900003703002001200241c8006a41096a2900003703002002200229004937039001410021010240201e4101470d00200241f0006a41186a20024190016a41186a290300370300200241f0006a41106a20024190016a41106a290300370300200241f0006a41086a20024190016a41086a2903003703002002200229039001370370410121010b200241206a201a3a00002002411f6a20193a00002002411d6a201b3b00002002411c6a20043a00002002411b6a20053a0000200241196a20063b0000200241186a20073a0000200241176a20083a0000200241156a20093b0000200241146a200a3a0000200241136a200b3a0000200241116a200c3b0000200241106a200d3a00002002410f6a200e3a00002002410d6a200f3b00002002410c6a20103a00002002410b6a20113a0000200241096a20123b0000200241086a20133a0000200220013a0021200220143a0007200220153b0005200220163a0004200220173a0003200220183b0001200220033a00002002413a6a200241f0006a41186a290300370100200241326a200241f0006a41106a2903003701002002412a6a200241f0006a41086a290300370100200241226a221d20022903703701000240200341ff01714101470d002001450d0020024101722201201d412010ea060d00200241c8006a41026a200141026a2d000022033a0000200220012f000022013b01482002410a6a2f0100211d2002410e6a2f0100211e200241126a2f01002105200241166a2f010021082002411a6a2f0100210b2002411e6a2f0100210e20022f01062111200041036a20033a0000200020013b0001200041206a201a3a00002000411e6a200e3b00002000411d6a201b3a00002000411c6a20043a00002000411a6a200b3b0000200041196a20063a0000200041186a20073a0000200041166a20083b0000200041156a20093a0000200041146a200a3a0000200041126a20053b0000200041116a200c3a0000200041106a200d3a00002000410e6a201e3b00002000410d6a200f3a00002000410c6a20103a00002000410a6a201d3b0000200041096a20123a0000200041086a20133a0000200041066a20113b0000200041056a20153a0000200041046a20163a0000410021030c010b410121030b200020033a0000200241b0016a24000b130020004108360204200041c0a5c6003602000b130020004112360204200041d8aac6003602000bd40401057f230041106b22022400200241003a000502400240024002400240024020012802002203280204220420044100472205490d00200241056a20032802002206200510e8061a2003200420056b3602042003200620056a360200024020040d00410021040c050b024020022d0005220441037122034103460d000240024020030e03070001070b200241003b0106200220043a00064101210420012802002201280204220320034100472205490d04200241066a41017220012802002204200510e80621062001200320056b3602042001200420056a360200024020030d00200620056a22044100200241066a20046b41026a10e7061a0b20022f0106220441ff014d0d0220044102762103410021040c070b20024100360208200220043a0008200241086a4101722001280200220428020020042802042205410320054103491b220310e8062106200428020422012003490d042004200120036b3602042004200428020020036a3602000240200541024b0d00200620036a22044100200241086a20046b41046a10e7061a0b2002280208220341808004492104200341027621030c060b200441034d0d010b410121040c040b2002410036020c2002410c6a20012802002204280200220120042802042203410420034104491b220510e8061a2004200320056b3602042004200120056a3602000240200341034b0d002002410c6a20056a4100410420056b10e7061a0b200228020c22034180808080044921040c030b0c020b20032001104b000b20044102762103410021040b2000200336020420002004360200200241106a24000b130020004100360204200041c8e1ca003602000bbf0202027f017e23004180016b220224002000280200210002400240024002400240200128020022034110710d002000290300210420034120710d01200441012001104521000c020b20002903002104410021000340200220006a41ff006a2004a7410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200442048822044200520d000b20004180016a22034181014f0d022001410141bc8ac0004102200220006a4180016a410020006b104821000c010b410021000340200220006a41ff006a2004a7410f712203413072200341376a2003410a491b3a00002000417f6a2100200442048822044200520d000b20004180016a22034181014f0d022001410141bc8ac0004102200220006a4180016a410020006b104821000b20024180016a240020000f0b2003418001104b000b2003418001104b000bd50505067f017e047f017e027f23004180026b2202240002400240024002402000280200220320002802044f0d00200028020c2104200141086a2105200241a0016a4102722106024003402000200341016a360200200241186a2000280208280200220710f30220022d00184101460d0120022900192108200241086a200710e60120022802080d012007280204200228020c2203490d012003417f4c0d0302400240024020030d00410121090c010b200310332209450d0720072802042003490d0120092007280200200310e8061a2007280204220a2003490d062007200a20036b3602042007200728020020036a3602000b20022008370310024002402001280200220b4190bdc600460d002001280204210c0c010b2006410041da0010e7061a200241186a410041840110e7061a41e401102d220b450d074100210c200b4100360200200b41046a200241a0016a41dc0010e8061a200b41e0006a200241186a41840110e8061a200141003602042001200b3602000b2003ad220d422086200d84210d02400240034002400240200b2f0106220e0d004100210a0c010b200e4103742103200b41086a2107417f210a0340024020030d00200e210a0c020b200a41016a210a200241106a2007410810ea06220f450d03200341786a2103200741086a2107200f417f4a0d000b0b0240200c450d00200c417f6a210c200b200a4102746a41e4016a280200210b0c010b0b2002200837022c200220053602282002200a360224200220013602202002200b36021c200241003602182002200d3702a401200220093602a001200241186a200241a0016a109b020c010b200b200a410c6c6a220341e4006a2207280200210a2007200d370200200341e0006a22072802002103200720093602002003450d00200a450d002003102f0b200028020022032000280204490d010c030b0b2009102f0b200441013a00000b20024180026a24000f0b103d000b2003200a104b000b1036000b810605027f027e017f027e027f230041a0016b220224002000280200210002400240024002400240024002400240200128020022034110710d00200041086a29030021042000290300210520034120710d0220054290ce005441002004501b450d012005a72103412721000c060b200041086a2903002105200029030021044180012100024003402000450d01200241206a20006a417f6a2004a7410f712203413072200341d7006a2003410a491b3a00002000417f6a210020044204882005423c8684220420054204882205844200520d000b0b20004181014f0d022001410141bc8ac0004102200241206a20006a41800120006b104821000c060b41272100200241186a21060340200241106a200520044290ce00420010ee062002200229031022072006290300220842f0b17f427f10ed06200241206a20006a2203417c6a200520022903007ca7220941ffff037141e4006e220a41017441e684c0006a2f00003b00002003417e6a200a419c7f6c20096a41ffff037141017441e684c0006a2f00003b0000200542ffc1d72f56210320044200522109200450210a2000417c6a2100200721052008210420032009200a1b0d000c040b0b4180012100024003402000450d01200241206a20006a417f6a2005a7410f712203413072200341376a2003410a491b3a00002000417f6a210020054204882004423c8684220520044204882204844200520d000b0b20004181014f0d012001410141bc8ac0004102200241206a20006a41800120006b104821000c040b2000418001104b000b2000418001104b000b2007a721030b02400240200341e3004a0d00200321090c010b200241206a2000417e6a22006a2003200341ffff037141e4006e2209419c7f6c6a41ffff037141017441e684c0006a2f00003b00000b024002402009410a480d00200241206a2000417e6a22006a200941017441e684c0006a2f00003b00000c010b200241206a2000417f6a22006a200941306a3a00000b2001410141c8e1ca004100200241206a20006a412720006b104821000b200241a0016a240020000bdd0604017f017e017f057e230041c0016b220624000240200341ff0171450d00200641d0006a2001ad42004280c8afa025420010ed06200641c0006a2002418094ebdc032002418094ebdc03491bad420042e807420010ed0620064190016a41186a420037030020064190016a41106a2201420037030020064190016a41086a22024200370300200642003703900141e7a2ca00ad42808080808001841001220329000021072002200341086a29000037030020062007370390012003102f41efa2ca00ad4280808080900284100122032900002107200641b0016a41086a2208200341086a290000370300200620073703b0012003102f200120062903b0012207370300200641f0006a41086a2002290300370300200641f0006a41106a2007370300200641f0006a41186a20082903003703002006200629039001370370200641c0006a41086a290300200641d0006a41086a2903007c2006290340220920062903507c2207200954ad7c2109200641e0006a200641f0006a10e3010240024020062802600d00410021024200210a0c010b2006290368220a4200552102200a427f550d00428080808080808080807f4200200a7d200a428080808080808080807f511b210a0b200641206a20072009428094ebdc03420010ee06200641106a2006290320220b200641206a41086a290300220c4280ec94a37c427f10ed06200641306a20072009200a428094ebdc0380220d420010ed062006200a200d4280ec94a37c7e7ca72203360290012006418094ebdc03360294012006200b200c20064190016a2003418094ebdc034b4102746a350200220a420010ed06427f200641306a41086a290300200641086a2903007c2006290330220c20062903007c220b200c54ad7c200b200a200720062903107c7e220a200a428094ebdc0380220a4280ec94a37c7e7c4280cab5ee0156200aa76aad7c220a200b54ad7c220b20097c200a20077c220c200a54ad7c42002009200b7d2007200a54ad7d220b2007200a7d220a200756200b200956200b2009511b22031b20021b200c4200200a20031b20021b22094280a094a58d1d7c2207200954ad7c220920057c200720047c22042007542202ad7c22072002200720095420072009511b22021b2105427f200420021b21040b2000200437030020002005370308200641c0016a24000b810603087f017e047f23004180086b22022400200241b8046a200110f6030240024020022802bc042203450d00200241c4046a280200210420022802c004210520022802b8042106200241106a200241c8046a41e00010e8061a200241086a200110e601024002400240024020022802080d00200228020c2207200128020441c8036e2208200820074b1b2209ad42c8037e220a422088a70d01200aa72208417f4c0d010240024020080d004108210b0c010b2008102d220b450d03200841c8036e21090b024002402007450d004100210c410021084100210d0340200241b8046a200110a40420022903a0054203510d02200d41016a210e200241f0006a200241b8046a41c80310e8061a0240200d2009470d00200c200e200c200e4b1bad42c8037e220a422088a70d07200aa722094100480d0702400240200d0d002009102d210b0c010b200b200820091031210b0b200b450d06200941c8036e21090b200b20086a200241f0006a41c80310e8061a200c41026a210c200841c8036a2108200e210d2007200e470d000b0b200b450d01200241b8046a200241106a41e00010e8061a2000410c6a2004360200200020053602082000200336020420002006360200200041106a200241b8046a41e00010e8061a200041f8006a2007360200200041f4006a2009360200200041f0006a200b3602000c060b0240200d450d00200b4198016a210e0340200e108d01200e41c8036a210e200841b87c6a22080d000b0b2009450d00200b102f0b2000410036020402402004450d00200441246c210e2003210803400240024020082d0000220d41044b0d00024002400240200d0e050400010204040b2008410c6a280200450d03200841086a280200102f0c030b2008410c6a280200450d02200841086a280200102f0c020b2008410c6a280200450d01200841086a280200102f0c010b200841086a280200450d00200841046a280200102f0b200841246a2108200e415c6a220e0d000b0b2005450d042003102f0c040b103d000b1036000b1038000b200041003602040b20024180086a24000b8c0201037f024002400240024002400240024020012802000e0400010203000b410121024101102d2201450d05200141003a0000410121030c040b4101102d2202450d04200241013a00002001280204210320024101410510312202450d042002200336000120012802082104410a210320024105410a10312201450d04200120043600050c020b410121024101102d2201450d03200141023a0000410121030c020b4101102d2202450d02200241033a00002001280204210320024101410510312202450d022002200336000120012802082104410a210320024105410a10312201450d02200120043600050b410921020b2000200236020820002003360204200020013602000f0b1036000bd60402067f047e230041f0006b220224002002412036020c20022001360208200241106a2001ad4280808080800484100210730240024020022802102203450d002002280214210402400240200241186a2802002205450d0020032d0000220641014b0d004100210102400240024020060e020100010b41002101200241003a0068200341016a21072005417f6a2106034020062001460d02200241c8006a20016a200720016a2d00003a00002002200141016a22053a00682005210120054120470d000b200241206a41186a200241c8006a41186a290300370300200241206a41106a200241c8006a41106a290300370300200241206a41086a200241c8006a41086a29030037030020022002290348370320410121010b200241c8006a41186a200241206a41186a2903002208370300200241c8006a41106a200241206a41106a2903002209370300200241c8006a41086a200241206a41086a290300220a37030020022002290320220b370348200041196a2008370000200041116a2009370000200041096a200a3700002000200b3700010c020b200141ff0171450d00200241003a00680b20024100360228200242013703202002410b3602442002200241086a3602402002200241206a36026c200241dc006a41013602002002420137024c200241b885c7003602482002200241c0006a360258200241ec006a41d8dbc100200241c8006a103c1a2002350228422086200235022084100802402002280224450d002002280220102f0b410221010b200020013a00002004450d012003102f0c010b200041023a00000b200241f0006a24000b830301067f230041106b2203240002400240024020014105744104722204417f4c0d002004102d2205450d012003410036020820032004360204200320053602002001200310690240024020010d002003280208210520032802042106200328020021070c010b20014105742108200328020021072003280204210420032802082101034002400240200420016b4120490d00200141206a2105200421060c010b200141206a22052001490d05200441017422062005200620054b1b22064100480d050240024020040d002006102d21070c010b200720042006103121070b2007450d040b200720016a22012000290000370000200141186a200041186a290000370000200141106a200041106a290000370000200141086a200041086a2900003700002006210420052101200041206a2100200841606a22080d000b2003200636020420032005360208200320073602000b20022902002005ad4220862007ad84100402402006450d002007102f0b200341106a24000f0b103d000b1036000b1038000b9b0304017f017e017f027e230041d0006b22042400200341086a290300210520032802042106024002400240024002400240024020032802000e06000102030504000b2006ad21050c040b2004200129034842002006ad420010ed06427f210720042903084200520d04200429030021050c030b200441106a200129035042002006ad420010ed06427f210720042903184200520d03200429031021050c020b200441206a200129031842002006ad420010ed06427f210720042903284200520d02200429032021050c010b200441306a200129032842002006ad420010ed06200441c0006a20012903204200200542ffffffff0f83420010ed06427f210720042903484200520d0120042903384200520d012004290340220520042903307c22082005540d01200820012903307c22052008540d010b200521070b200042002000290308220520077d220720072005561b37030841002103024020072005580d0002402002280200450d0020022802042203450d00200241086a280200450d002003102f0b20024201370200410121030b200441d0006a240020030be304020b7f017e230041106b22052400024002400240200128020041016a220641004c0d0020012006360200200141046a2106200141086a2802002107024002400240034002400240200628020022082f010622090d004100210a0c010b2009410574210620084198036a210b200841086a210c417f210a0340024020060d002009210a0c020b2002200c412010ea06220d450d03200641606a2106200b41e0006a210b200a41016a210a200c41206a210c200d417f4a0d000b0b2007450d022007417f6a21072008200a4102746a41880b6a21060c000b0b200b41046a2802002109200b21060240024003404100210e4100210a0240200628020022072f0106220f450d00200f4105742106200741f0026a210d200741086a210c417f210a0340024020060d00200f210a0c020b2004200c412010ea062208450d03200641606a2106200d410c6a210d200a41016a210a200c41206a210c2008417f4a0d000b0b2009450d022009417f6a21092007200a4102746a41ec036a21060c000b0b02400240200d41786a280200220a0d0041002106420021100c010b200d280200220c417f4c0d0502400240200c0d00410121060c010b200c102d2206450d070b2006200a200c10e8061a200cad21100b201042208620108421104101210e0b02400240200b412d6a2d0000450d0020064100200e1b21060c010b200e450d010b20002010370204200020063602000c010b20002001280210200220032004200141146a28020028020c1106000b20012001280200417f6a360200200541106a24000f0b41c6c4ca004118200541086a41cc90c70041f0c4ca00103e000b103d000b1036000b9203020a7f037e230041206b220324000240200128020041016a220441004c0d0020012004360200200141046a2105200141086a2802002106024002400240034002400240200528020022072f010622080d00410021090c010b20084105742105200741c5036a210a200741086a210b417f21090340024020050d00200821090c020b2002200b412010ea06220c450d03200541606a2105200a41e0006a210a200941016a2109200b41206a210b200c417f4a0d000b0b2006450d022006417f6a2106200720094102746a41880b6a21050c000b0b200a41436a2205290300210d200a41bb7f6a290300210e200541086a290300210f0240200a2d00000d00200ea721054201210e2005450d010c020b200e4202520d010b200320012802102002200141146a280200280214110300200341106a290300210f200128020021042003290308210d2003290300210e0b20012004417f6a360200200041106a200f3703002000200d3703082000200e370300200341206a24000f0b41c6c4ca004118200341186a41cc90c70041f0c4ca00103e000b290020004101360204200041086a200128020420012802006b41a0016e2201360200200020013602000bf40101047f230041d0006b21020240200128020022032001280204470d00200041003602000f0b2001200341a0016a3602002002200341c2006a29000037012a2002200341ca006a290000370132200241106a220120022903303703002002200341d2006a29000037013a200241186a220420022903383703002002200341da006a2800003601422002200341de006a2f00003b0146200241206a220520022903403703002002200341c0006a2f00003b01282002200229032837030820002003360200200020022903083700042000410c6a2001290300370000200041146a20042903003700002000411c6a20052903003700000bf30801087f230041f0006b2103024002402001280200220420012802042205460d00200241016a210603402001200441a0016a2202360200200341003a0068200441c0006a2d00002107200341013a0068200320073a0048200441c1006a2d00002107200341023a0068200320073a0049200441c2006a2d00002107200341033a0068200320073a004a200441c3006a2d00002107200341043a0068200320073a004b200441c4006a2d00002107200341053a0068200320073a004c200441c5006a2d00002107200341063a0068200320073a004d200441c6006a2d00002107200341073a0068200320073a004e2003200441c7006a2d00003a004f200341083a0068200441c8006a2d00002107200341093a0068200320073a0050200441c9006a2d000021072003410a3a0068200320073a0051200441ca006a2d000021072003410b3a0068200320073a0052200441cb006a2d000021072003410c3a0068200320073a0053200441cc006a2d000021072003410d3a0068200320073a0054200441cd006a2d000021072003410e3a0068200320073a0055200441ce006a2d000021072003410f3a0068200320073a00562003200441cf006a2d00003a0057200341103a0068200441d0006a2d00002107200341113a0068200320073a0058200441d1006a2d00002107200341123a0068200320073a0059200441d2006a2d00002107200341133a0068200320073a005a200441d3006a2d00002107200341143a0068200320073a005b200441d4006a2d00002107200341153a0068200320073a005c200441d5006a2d00002107200341163a0068200320073a005d200441d6006a2d00002107200341173a0068200320073a005e2003200441d7006a2d00003a005f200341183a0068200441d8006a2d00002107200341193a0068200320073a0060200441d9006a2d000021072003411a3a0068200320073a0061200441da006a2d000021072003411b3a0068200320073a0062200441db006a2d000021072003411c3a0068200320073a0063200441dc006a2d000021072003411d3a0068200320073a0064200441dd006a2d000021072003411e3a0068200320073a0065200441de006a2d000021072003411f3a0068200320073a0066200441df006a2d00002107200341203a0068200320073a0067200341286a41086a22072003290350370300200341286a41106a22082003290358370300200341286a41186a2209200329036037030020032003290348370328200341086a41086a220a2007290300370300200341086a41106a22072008290300370300200341086a41186a2208200929030037030020032003290328370308200341c8006a41186a2008290300370300200341c8006a41106a2007290300370300200341c8006a41086a200a290300370300200320032903083703482006417f6a2206450d022002210420052002470d000b0b200041003602000f0b20002004360200200020032903483702042000410c6a200341d0006a290300370200200041146a200341d8006a2903003702002000411c6a200341e0006a2903003702000b13002000410136020420004184c6c6003602000b3400200041b89bca0036020420004100360200200041146a4107360200200041106a41f8c6c600360200200041086a420f3702000b2c01017f02404108102d22020d001036000b20004288808080800137020420002002360200200242003700000b2201017f230041106b22022400200241003602002000200210f204200241106a24000bed0303027f037e027f230041c0006b2202240041e7a2ca00ad4280808080800184100122032900002104200241086a200341086a290000370300200220043703002003102f41f9b5c600ad4280808080d00084100122032900002104200241106a41086a200341086a290000370300200220043703102003102f02404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100322012900002104200141086a2900002105200141106a2900002106200241206a41186a2207200141186a290000370300200241206a41106a22082006370300200241206a41086a2005370300200220043703202001102f2003102f41c000102d2203450d00200320022903003700002003200229031037001020032002290320370020200341086a200241086a290300370000200341186a200241106a41086a290300370000200341286a200241206a41086a290300370000200341306a2008290300370000200341386a2007290300370000200241206a200341c00010ca030240024020022802202201450d0020002002290224370204200020013602000c010b20004100360208200042083702000b2003102f200241c0006a24000f0b1036000bd2190e027f017e017f027e037f017e027f047e027f017e017f017e017f047e230041d0046b22032400418de6c300ad4280808080e00084100122042900002105200341d8006a41086a200441086a290000370300200320053703582004102f41f0e8c600ad4280808080f00084100122042900002105200341086a41086a200441086a290000370300200320053703082004102f02404120102d2204450d0020042000290000370000200441186a200041186a290000370000200441106a200041106a290000370000200441086a200041086a2900003700002004ad4280808080800484100322062900002105200641086a2900002107200641106a2900002108200341d0036a41186a2209200641186a290000370300200341d0036a41106a220a2008370300200341d0036a41086a2007370300200320053703d0032006102f2004102f41c000102d220b450d00200b2003290358370000200b2003290308370010200b20032903d003370020200b41086a200341d8006a41086a2204290300370000200b41186a200341086a41086a290300370000200b41286a200341d0036a41086a290300370000200b41306a200a290300370000200b41386a2009290300370000200341086a200b10f6022003290308210c4200210520034200370308200341d0006a280200210d20032d0054210e02400240200c4201510d00200341d8006a41386a4200370300200341d8006a41306a4200370300200341d8006a41286a4200370300200341d8006a41206a4200370300200341f0006a4200370300200341e8006a42003703002004420037030020034200370358420021074200210f420021100c010b200341086a41386a2903002108200341086a41306a2903002111200341086a41206a2903002107200341086a41186a2903002105200341086a41c0006a2903002112200329031821102003290310210f200341d8006a41206a200341086a41286a290300370300200341d8006a41286a2011370300200341d8006a41306a2008370300200341e8006a20053703002003200737037020032012370390012003200f370358200320103703600b4200210820034190016a22134200370300200341d8006a41306a4200370300200341d8006a41286a2214420037030020034200370378201020077c200f20057c2215200f542216ad7c2117200341d8006a41106a211802402002450d002002410574210942002108420021124200211942002111200121040340024002400240200441186a220a2d00002206417f6a41ff017141014b0d0020142011200441086a290300220520192004290300220756201120055620112005511b22061b221137030020032019200720061b2219370378200a2d000022064102460d010b200641ff01710d01200441086a2903002105200429030021070b2013200820052012200756200820055620082005511b22061b220837030020032012200720061b2212370388010b200441206a2104200941606a22090d000b0b201720105121042017201054210620034198016a41186a201841086a290300220537030020034198016a41206a220a201841106a29030037030020034198016a41286a201841186a29030037030020034198016a41306a201841206a2903003703002003201829030022073703a8012003200f37039801200320103703a00102400240427f200f20077c22072007200f542209201020057c2009ad7c220520105420052010511b22091b2207428080e983b1de16544100427f200520091b2211501b0d00200341a8016a2903002107200341c8016a2903002111200341c0016a2903002112200a290300211920032903a001211a200329039801211b4201210520032903b001211c0c010b4200210502402007201184500d0020072011109a0120034188046a201137030020034180046a2007370300200341d0036a41086a41013a0000200341d9036a2000290000370000200341e1036a200041086a290000370000200341e9036a200041106a290000370000200341f1036a200041186a290000370000200341033a00d00341c8e1ca004100200341d0036a108c010b0b2016200620041b2104200341306a2019370300200341386a2012370300200341186a201a370300200341c0006a2011370300200341206a20073703002003201c370328200320083703482003201b3703102003200e4100200c42015122061b3a00542003200d410020061b360250200320054201512206ad3703080240024020060d00200bad428080808080088410050c010b200341c0003602d4032003200b3602d003200341106a200341d0036a1090030b427f201720041b2107427f201520041b2108200b102f20054201522104024002400240200c4201510d0020040d0041032106200341d0026a21040c010b200c4201522004410173720d0141042106200341d0016a21040b200441046a20063a0000200441003a0000200441056a20002900003700002004410d6a200041086a290000370000200441156a200041106a2900003700002004411d6a200041186a29000037000041c8e1ca0041002004108c010b024020082007844200520d0020034188046a201037030020034180046a200f370300200341d0036a41086a41003a0000200341d9036a2000290000370000200341e1036a200041086a290000370000200341e9036a200041106a290000370000200341f1036a200041186a290000370000200341033a00d00341c8e1ca004100200341d0036a108c010b41e7a2ca00ad4280808080800184100122042900002105200341d0016a41086a200441086a290000370300200320053703d0012004102f41f9b5c600ad4280808080d00084100122042900002105200341d0026a41086a200441086a290000370300200320053703d0022004102f4120102d2204450d0020042000290000370000200441186a200041186a290000370000200441106a200041106a290000370000200441086a200041086a2900003700002004ad4280808080800484100322062900002105200641086a2900002107200641106a2900002108200341d0036a41186a2209200641186a290000370300200341d0036a41106a220a2008370300200341d0036a41086a2007370300200320053703d0032006102f2004102f41c000102d2204450d00200420032903d001370000200420032903d002370010200420032903d003370020200441086a200341d0016a41086a2206290300370000200441186a200341d0026a41086a220b290300370000200441286a200341d0036a41086a290300370000200441306a200a290300370000200441386a20092903003700002003200441c00041c8e1ca004100410010b501200328020021092004102f41e7a2ca00ad42808080808001841001220429000021052006200441086a290000370300200320053703d0012004102f41f9b5c600ad4280808080d00084100122042900002105200b200441086a290000370300200320053703d0022004102f4120102d2104024002402002450d002004450d0220042000290000370000200441186a200041186a290000370000200441106a200041106a290000370000200441086a200041086a2900003700002004ad4280808080800484100322062900002105200641086a2900002107200641106a2900002108200341d0036a41186a220a200641186a290000370300200341d0036a41106a220b2008370300200341d0036a41086a22132007370300200320053703d0032006102f2004102f41c000102d2204450d02200420032903d001370000200420032903d002370010200420032903d003370020200441086a200341d0016a41086a290300370000200441186a200341d0026a41086a290300370000200441286a2013290300370000200441306a200b290300370000200441386a200a290300370000200341d0036a20012002109d042004ad428080808080088420033502d80342208620032802d0032206ad841004024020032802d403450d002006102f0b2004102f20094101460d01200010d0020c010b2004450d0120042000290000370000200441186a200041186a290000370000200441106a200041106a290000370000200441086a200041086a2900003700002004ad4280808080800484100322062900002105200641086a2900002107200641106a2900002108200341d0036a41186a220a200641186a290000370300200341d0036a41106a220b2008370300200341d0036a41086a22132007370300200320053703d0032006102f2004102f41c000102d2204450d01200420032903d001370000200420032903d002370010200420032903d003370020200441086a200341d0016a41086a290300370000200441186a200341d0026a41086a290300370000200441286a2013290300370000200441306a200b290300370000200441386a200a2903003700002004ad428080808080088410052004102f20094101470d00200010ca020b200341d0046a24000f0b1036000b1300200041043602042000419cd2c6003602000b3400200041e7a2ca0036020420004100360200200041146a4104360200200041106a41ece5c600360200200041086a42083702000b830101017f02404110102d2202450d00200242003700082002420037000020024110412010312202450d0020024200370010200241186a42003700002002412041c00010312202450d002002420037003020024200370020200042c0808080800837020420002002360200200241386a4200370000200241286a42003700000f0b1036000b130020004101360204200041acedc6003602000ba50205017e027f027e017f047e420121020240200128020422034110490d002001280200220441086a2900002105200429000021062001200441106a3602002001200341706a220736020420074110490d00200441186a2900002108200429001021092001200341606a22073602042001200441206a36020020074110490d00200441286a290000210a2004290020210b2001200341506a22073602042001200441306a3602002007410f4d0d0020002006370308200041386a2004290030370300200041306a200a370300200041286a200b370300200041206a2008370300200041186a2009370300200041106a2005370300200041c0006a200441386a2900003703002001200341406a3602042001200441c0006a360200420021020b200020023703000b3400200041ed9bca0036020420004100360200200041146a4103360200200041106a41b4eec600360200200041086a42083702000b3400200041e7a2ca0036020420004100360200200041146a4101360200200041106a41c0f6c600360200200041086a42083702000b130020004102360204200041b4f7c6003602000b3400200041dcbec60036020420004100360200200041146a4101360200200041106a41f8f9c600360200200041086a42183702000bac0707017f047e037f017e057f047e017f23004180026b22022400200241c0006a2001109c030240024002400240024002402002290340a70d00200241c0006a41106a290300210320022903482104200241286a2001109c032002290328a70d02200241286a41106a290300210520022903302106200241206a200110e60120022802200d0320022802242207200128020441306e2208200820074b1b2209ad42307e220a422088a7450d010c050b200041003602200c030b200aa72208417f4c0d0302400240024020080d004108210b0c010b2008102d220b450d01200841306e21090b02402007450d004100210c0340200241003a00f801200c220d41016a210c2001280204417f6a21084100210e024002400240024003402008417f460d01200241d8016a200e6a2001280200220f2d00003a0000200120083602042001200f41016a3602002002200e41016a220f3a00f8012008417f6a2108200f210e200f4120470d000b200241b8016a41186a2208200241d8016a41186a290300370300200241b8016a41106a220e200241d8016a41106a290300370300200241b8016a41086a220f200241d8016a41086a290300370300200220022903d8013703b801200241086a2001109c032002290308a70d01200241086a41106a290300210a20022903102110200241f8006a41086a200f2903002211370300200241f8006a41106a200e2903002212370300200241f8006a41186a20082903002213370300200241d8006a41086a220e2011370300200241d8006a41106a220f2012370300200241d8006a41186a22142013370300200220022903b8012211370378200220113703582009200d470d030240200d4101742208200c2008200c4b1bad42307e2211422088a70d002011a7220841004e0d030b1038000b200e41ff0171450d00200241003a00f8010b200241f8006a41086a20024198016a41086a2903003703002009450d06200b102f0c060b02400240200d0d002008102d210b0c010b200b200d41306c20081031210b0b200b450d03200841306e21090b200b200d41306c6a2208200a3703082008201037030020082002290358370310200841186a200e290300370300200841206a200f290300370300200841286a2014290300370300200c2007470d000b0b200b450d0220002004370300200020093602242000200b3602202000200637031020002003370308200041286a2007360200200041186a20053703000c030b1036000b200041003602200c010b200041003602200b20024180026a24000f0b103d000b130020004104360204200041bcfcc6003602000b130020004108360204200041a480c7003602000bcb0102037f037e230041206b2205240002400240024020030d00200041003602000c010b2003280208220641164d0d01200328020021072004ad4280808080800484100322032900002108200341086a2900002109200341106a290000210a200541186a200341186a290000370300200541106a200a370300200541086a2009370300200520083703002003102f20002006ad4220862007ad84200641696aad422086200741176aad8441012005ad4280808080800484101010730b200541206a24000f0b41172006104b000baf0201027f23004190016b220324002003200210e8010240024020032d000022024102460d00200341e0006a200341286a290300370300200341e8006a200341306a290300370300200341d8006a41186a200341386a290300370300200341d8006a41206a200341c0006a290300370300200341d8006a41286a200341c8006a290300370300200341d8006a41306a200341d0006a2802003602002003200341206a29030037035802402002450d00200041003a00000c020b2003411c6a2802002102200341186a28020021042000200329026c370001200041013a0000200041196a20034184016a290200370000200041116a200341fc006a290200370000200041096a200341d8006a411c6a2902003700002002450d012004102f0c010b200041003a00000b20034190016a24000b870102017f037e230041e0006b22032400200341086a200210e8010240024020032d000822024102470d00420021040c010b2002410173ad2104200341186a2903002105200341106a290300210620020d00200341246a280200450d00200341206a280200102f0b2000200637030820002004370300200041106a2005370300200341e0006a24000bd70303027f037e027f230041d0006b2202240041aa97ca00ad4280808080800184100122032900002104200241106a41086a200341086a290000370300200220043703102003102f41cbcec100ad4280808080e00184100122032900002104200241206a41086a200341086a290000370300200220043703202003102f02404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100322012900002104200141086a2900002105200141106a2900002106200241306a41186a2207200141186a290000370300200241306a41106a22082006370300200241306a41086a2005370300200220043703302001102f2003102f41c000102d2203450d00200320022903103700002003200229032037001020032002290330370020200341086a200241106a41086a290300370000200341186a200241206a41086a290300370000200341286a200241306a41086a290300370000200341306a2008290300370000200341386a2007290300370000200241086a200341c00041c8e1ca004100410010b501200228020821012003102f200241d0006a240020014101460f0b1036000b3a02017f017e230041c0006b2203240020032002108d02200329030021042000200341086a29030037030820002004370300200341c0006a24000bd10903067f017e057f230041f0016b220224000240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a22063602042001200441016a3602002005417f6a220541014b0d0320050e020102010b200041023a00000c030b0240024020064104490d002004280001210720012003417b6a22053602042001200441056a360200024020054108490d00200429000521082001200341736a36020420012004410d6a36020041002105200241003a00b001410d20036b2109200341726a210602400340200920056a450d0120024190016a20056a200420056a220a410d6a2d00003a0000200120063602042001200a410e6a3602002002200541016a220a3a00b0012006417f6a2106200a2105200a4120470d000b200241f0006a41186a20024190016a41186a290300370300200241f0006a41106a20024190016a41106a290300370300200241f0006a41086a20024190016a41086a290300370300200220022903900137037041002105200241003a00d0012004200a6a2109200a20036b410d6a210a0340200a20056a450d0420024190016a20056a200920056a2204410d6a2d00003a00002001200636020420012004410e6a3602002002200541016a22043a00d0012006417f6a210620042105200441c000470d000b200241106a41386a220120024190016a41386a290300370300200241106a41306a220520024190016a41306a290300370300200241106a41286a220620024190016a41286a290300370300200241106a41206a220420024190016a41206a290300370300200241106a41186a220a20024190016a41186a290300370300200241106a41106a220320024190016a41106a290300370300200241106a41086a220920024190016a41086a290300370300200241d0006a41086a220b200241f0006a41086a290300370300200241d0006a41106a220c200241f0006a41106a290300370300200241d0006a41186a220d200241f0006a41186a290300370300200220022903900137031020022002290370370350200041003a000020002002290350370001200041096a200b290300370000200041116a200c290300370000200041196a200d290300370000200041216a2002290310370000200041296a2009290300370000200041316a2003290300370000200041396a200a290300370000200041c1006a2004290300370000200041c9006a2006290300370000200041d1006a2005290300370000200041d9006a2001290300370000200041e3006a2002410f6a2d00003a0000200041e1006a20022f000d3b0000200041e8006a2008370300200041e4006a20073602000c060b0240200541ff0171450d00200241003a00b0010b200041023a00000c050b200041023a00000c040b200041023a00000c030b0240200541ff0171450d00200241003a00d0010b200041023a00000c020b024020064104490d002004280001210620012003417b6a22053602042001200441056a36020020054108490d00200041013a0000200020022f00103b0001200429000521082001200341736a36020420012004410d6a360200200041086a2008370300200041046a2006360200200041036a200241126a2d00003a0000200041106a20024190016a41e00010e8061a0c020b200041023a00000c010b200041023a00000b200241f0016a24000bf90303027f037e027f230041e0006b2202240041bd98ca00ad4280808080800284100122032900002104200241206a41086a200341086a290000370300200220043703202003102f41ce89c700ad4280808080f00084100122032900002104200241306a41086a200341086a290000370300200220043703302003102f02404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100322012900002104200141086a2900002105200141106a2900002106200241c0006a41186a2207200141186a290000370300200241c0006a41106a22082006370300200241c0006a41086a2005370300200220043703402001102f2003102f41c000102d2203450d00200320022903203700002003200229033037001020032002290340370020200341086a200241206a41086a290300370000200341186a200241306a41086a290300370000200341286a200241c0006a41086a290300370000200341306a2008290300370000200341386a2007290300370000200241086a200341c000109c01200241086a41106a290300210420022903102105200228020821012003102f20002004420020011b37030820002005420020011b370300200241e0006a24000f0b1036000ba62c07017f017e017f027e017f027e197f23004190036b2207240002400240024002402001200284500d002003200484500d004201210820074198016a200320012003200156200420025620042002511b22091b220a2004200220091b220b20054201200542015620064200522006501b220c1b220520064200200c1b220610ee0620074188016a200729039801220d20074198016a41086a290300220e2005200610ed062002200420091b21022001200320091b2104200a20072903880185200b20074188016a41086a290300858450450d01200d210a200e210b420021060c020b20004100360200200041106a4200370300200041086a42003703000c020b200741f8006a200420022005200610ee06200741e8006a20072903782201200741f8006a41086a29030022032005200610ed064200200620042007290368852002200741e8006a41086a29030085845022091b21064201200520091b21082003200220091b21022001200420091b21040b200741386a200b42002004420010ed06200741c8006a20024200200a420010ed06200741d8006a200a42002004420010ed06024002400240024002400240024002400240024002400240024002400240200b420052200242005271200729034042005272200729035042005272200741d8006a41086a2903002201200729033820072903487c7c2203200154724101470d004110102d2209450d0d2009200a3e020c2009200a4220883e02082009200b3e02042009200b4220883e020020074284808080c0003702ac02200720093602a802200741a8026a10ca06200741a8016a41086a20072802b002360200200720072903a8023703a8014110102d2209450d0d200920043e020c200920044220883e0208200920023e0204200920024220883e020020074284808080c0003702ac02200720093602a802200741a8026a10ca06200741b8016a41086a20072802b002360200200720072903a8023703b8014110102d2209450d0d20092008a7220f36020c200920084220883e0208200920063e0204200920064220883e020020074284808080c0003702ac02200720093602a802200741a8026a10ca06200741c8016a41086a20072802b002360200200720072903a8023703c80120074180036a41086a200741b8016a41086a280200360200200720072903b80137038003200741a8026a41086a200741a8016a41086a280200360200200720072903a8013703a802200741d8016a200741a8026a20074180036a10cc060240200728028403450d00200728028003102f0b200741d8016a10ca0620072802d00122104101460d0120072802dc01211120072802d80121122010450d0a20072802c801220c280200450d0a024020072802e0012213450d002012280200450d0b201320104d0d0b200720103602e401201320106b221441016a22154101201541014b1b221641ffffffff03712016470d0320164102742209417f4c0d030240024020090d0041042117201621180c010b200910332217450d0f200941027621180b201041ffffffff03712010470d0320104102742209417f4c0d030240024020090d00410421192010211a0c010b200910332219450d0f2009410276211a0b410221094101210f200c280200220c67221b211c0240200c41ffffffff034b0d0041022109201b210c4101210f034020094101200c4101711b200f6c210f200c41034b211d200920096c2109200c410176221c210c201d0d000b0b2007201336028803200720113602840320072012360280034104102d220c450d0e200c20094101201c4101461b200f6c220f36020020074281808080103702ac022007200c3602a802200741e8016a20074180036a200741a8026a10cc06200c102f20074180036a200741c8016a10cf064104102d2209450d0e2009200f36020020074281808080103702ac02200720093602a802200741f8016a20074180036a200741a8026a10cc062009102f0240024020072802e40120156a220920072802f001220c4d0d00024002402009200c6b22090d004104210f4100211d410021090c010b200941ffffffff03712009470d022009410274221d4100480d02201d102d220f450d11200f4100200941027410e7061a201d410276211d0b20072802e801211c0240201d20096b200c4f0d002009200c6a22122009490d02201d41017422112012201120124b1b221241ffffffff03712012470d02201241027422124100480d0202400240201d0d002012102d210f0c010b200f201d41027420121031210f0b200f450d112012410276211d0b200f20094102746a201c200c41027410e8061a2009200c6a2109024020072802ec01450d00201c102f0b200720093602f0012007201d3602ec012007200f3602e8010b200741f8016a10ca060240024002400240024002400240024002400240034020072014221e36028402024020072802f001220920072802e401220c201e6a220f417f736a221d2009490d0041c4c2ca00201d2009103b000b0240024002400240024002400240024002400240024002400240024020092009200f6b220f4d0d0020072802800222092009200c6b220c4d0d0120072802f801200c4102746a35020022024200510d02201e201e4100476b211420072802e8012209201d4102746a35020021012009200f4102746a3502002104200741003602880220072004200142208684200280220137039002200741003602980220072004200120027e7d42ffffffff0f833703a002200720074184026a3602bc022007200741e8016a3602b8022007200741e4016a3602b4022007200741f8016a3602b002200720074198026a3602ac02200720074188026a3602a802200741a8026a10cd061a034020072802980241016a41004c0d04024020072903a00242ffffffff0f560d00200741a8026a10cd060d010b0b2007290390022102200728028402210920072802e401210c200741003a0088032007200c20096a3602840320072009360280032007200741e8016a36028c03200741c0026a20074180036a10d006200741f0026a200741f8016a10cf064108102d2209450d2820092002a7221f360204200920024220883e02002007428280808020370284032007200936028003200741d0026a200741f0026a20074180036a10cc062009102f20072802c802222020072802d8022221202020214b1b22124101201241014b1b220c41ffffffff0371200c470d1d200c410274220f417f4c0d1d20072802c402212220072802c002212302400240200f0d0041042124200c21250c010b200f10332224450d29200f41027621250b2012450d062021417f6a221520214b211320072802d00221262020417f6a222720204b0d04200c417f6a21092024200f6a417c6a211c4100210f4200210203404100211d024020202027200f6b22114d0d004100211d201120274b0d00202320114102746a280200211d0b201dad21044100211d024020130d0020212015200f6b22114d0d00201120154b0d00202620114102746a280200211d0b024002402004201dad22037d22012004560d00200120027d220a2001560d00200a42ffffffff0f832104420021020c010b20044280808080108420027d20037d2104420121020b200c20094d0d09201c20043e0200201c417c6a211c2009417f6a2109200f41016a220f2012490d000c060b0b41c4c2ca00200f2009103b000b41c4c2ca00200c2009103b000b4190c4ca00411941acc3ca001039000b41c6c4ca00411820074180036a41e0c4ca0041f0c4ca00103e000b200c417f6a21092024200f6a417c6a211d4100211c4200210203404100210f024020130d004100210f20212015201c6b22114d0d004100210f201120154b0d00202620114102746a280200210f0b024002404200200fad22017d22044200520d00200420027d22032004560d00200342ffffffff0f832104420021020c010b428080808010200220017c7d2104420121020b200c20094d0d04201d20043e0200201d417c6a211d2009417f6a2109201c41016a221c2012490d000b0b41012111200250450d010b410021110b02402022450d002023102f0b20072802e401221d200728028402220f6a2213201d490d05200f20134f0d01200f417f7321090340200c200c200f6a20096a221c4d0d03200920072802f00122126a220f20094f0d0420072802e801200f4102746a2024201c4102746a2802003602002009417f6a2109200728028402210f201d417f6a221d0d000c050b0b419cc3ca002009200c103b000b201d450d020c030b41c4c2ca0020212020202120204b1b22074101200741014b1b200f6a20096a200c103b000b419cc3ca00200f2012103b000b200c200c2013417f7322096a200f6a220f4d0d0220072802f001220c20096a2209200c4f0d0320072802e80120094102746a2024200f4102746a280200360200200728028402210f0b2016200f417f736a220920164f0d03201720094102746a201f36020002402011450d002016200728028402417f736a220920164f0d05201720094102746a22092009280200417f6a360200200728028402210920072802e401210c200741003a0088032007200c20096a3602840320072009360280032007200741e8016a36028c03200741e0026a20074180036a10d00620074180036a200741f8016a10cf06200741f0026a20074180036a200741e0026a10cb06024020072802e401220920072802840222126a220c2009490d00024002402012200c4f0d00200c417f73210920072802f002211120072802f802210f2012211d0340200f200f201d6a20096a221d4d0d0a200920072802f00122136a221c20094f0d0b20072802e801201c4102746a2011201d4102746a280200360200200941016a2109200728028402211d2012200c417f6a220c490d000c020b0b20090d0120072802f802210f2012211d0b201d2012417f7322096a220c200f6a221d200c4f0d0920072802f001220c20096a2209200c4f0d0a20072802e80120094102746a20072802f002201d4102746a2802003602000b024020072802f402450d0020072802f002102f0b20072802e402450d0020072802e002102f0b02402025450d002024102f0b024020072802d402450d0020072802d002102f0b201e0d000b0240201b450d004101210920072802e401220c4101460d134100200c6b2112201b411f7121114100201b6b411f712113201041027420196a417c6a210c417f210903400240200920072802f001221d6a220f2009490d0041c4c2ca00200f201d103b000b201d200f417f6a221c4d0d0a201020096a221d20104f0d0b200c20072802e801221d201c4102746a280200201374201d200f4102746a28020020117672360200200c417c6a210c20122009417f6a2209460d130c000b0b4100210920072802f001211020072802ec01210f20072802e801211d201a450d132019102f0c130b41c4c2ca00200f200c103b000b419cc3ca002009200c103b000b419cc3ca0020092016103b000b41c4c2ca0020092016103b000b41c4c2ca00201d200f103b000b419cc3ca00201c2013103b000b41c4c2ca00201d200f103b000b419cc3ca002009200c103b000b41c4c2ca00200f417f6a201d103b000b419cc3ca00201d2010103b000b1038000b41c4c2ca0041004100103b000b200741286a200729035820032008200610ee0620004100360200200041106a200741286a41086a290300370300200041086a20072903283703000c0e0b200741a8026a41086a200741d8016a41086a280200221c360200200720072903d8013703a802201c4101201c41014b1b221d41ffffffff0371201d470d00201d4102742209417f4c0d000240024020090d0041042115201d21270c010b200910332215450d0c200941027621270b201c450d02201c417f6a21122015201d201c6b22114102746a210c200f4101200f41014b1bad2102420021044100210920072802a802210f0340201d201120096a22134d0d02200c2004422086200f35020084220420028022013e020020122009460d03200c41046a210c200f41046a210f2004200120027e7d2104201c200941016a22094b0d000b41c4c2ca002009201c103b000b103d000b419cc3ca002013201d103b000b2007201d360288032007202736028403200720153602800320072802ac02450d0720072802a802102f0c070b20072802e40121090b20072802f001220c200c20096b220f4d0d012010201020096b22094d0d02201920094102746a20072802e801200f4102746a280200201b411f717636020041012109201a210f2019211d0b024020072802fc01450d0020072802f801102f0b2009450d0320072802ec01450d0320072802e801102f0c030b41c4c2ca00200f200c103b000b419cc3ca0020092010103b000b4100211702402011450d002012102f0b0b4104102d2209450d01200941003602004104102d220c450d01200c41003602004101211c0240024020170d00200921174101211841012116200c211d4101210f410121100c010b2009102f200c102f0b20072016360290022007201836028c022007201736028802200720103602b0022007200f3602ac022007201d3602a802200741a8026a10ca06420021020240024020072802b00222094105744180014d0d00421d21040c010b4100211c024020090d00420021040c010b20072802a802220c200941027422096a417c6a220f280200211d0240200c200f470d00201dad21040c010b200c41786a210f201dad2104200741206a211d4120210c420021020340200741186a200f20096a3502004200200c41e0007110eb06201d29030020027c2007290318220220047c2204200254ad7c2102200c41206a210c2009417c6a22094104470d000b0b024020072802ac02450d0020072802a802102f0b201c0d020240200420084201882006423f8684562002200642018822045620022004511b450d0020074198026a41086a20074188026a41086a2802003602002007200729038802370398024110102d2209450d0220094280808080103702082009420037020020074284808080c0003702ac02200720093602a802200741a8026a10ca0620074180036a41086a20072802b002360200200720072903a8023703800320074188026a20074198026a20074180036a10cb06200728028403450d00200728028003102f0b20074180036a41086a20074188026a41086a2802003602002007200729038802370380030b20074180036a10ca06200741a8026a41086a220920074180036a41086a28020036020020072007290380033703a802200741a8026a10ca064200210202400240200928020022094105744180014d0d00421d21044101211c0c010b4100211c024020090d00420021040c010b20072802a802220c200941027422096a417c6a220f280200211d0240200c200f470d00201dad21040c010b200c41786a210f201dad2104200741106a211d4120210c420021020340200741086a200f20096a3502004200200c41e0007110eb06201d29030020027c2007290308220220047c2204200254ad7c2102200c41206a210c2009417c6a22094104470d000b0b024020072802ac02450d0020072802a802102f0b02400240201c450d00200041c4c6ca00360204200041086a4119360200410121090c010b200041106a2002370300200041086a2004370300410021090b2000200936020020072802cc01450d0220072802c801102f0c020b1036000b200720043e02ac02200741a9c4ca003602a80241f4c5ca00412f200741a8026a41a4c6ca0041b4c6ca00103e000b20074190036a24000bd30201037f230041d0006b220824000240024002402002200685200320078584500d00200220038450450d01410121090c020b417f20002004852001200585844200522000200454200120055420012005511b1b21090c010b0240200620078450450d0041ff0121090c010b200841206a2000200110d106200841306a2006200710d106200841c0006a41086a2209200841206a41086a220a280200360200200820082903203703402008200841c0006a200841306a10cc0602402008280234450d002008280230102f0b200841206a2004200510d106200841306a2002200310d1062009200a28020036020020082008290320370340200841106a200841c0006a200841306a10cc0602402008280234450d002008280230102f0b2008200841106a10ce06210902402008280214450d002008280210102f0b2008280204450d002008280200102f0b200841d0006a240020090beb0203017f047e017f230041d0006b2202240002400240200029031022032001290310220485200041186a2903002205200141186a29030022068584500d00200241206a2000290300200041086a29030010d106200241306a2004200610d106200241c0006a41086a2200200241206a41086a2207280200360200200220022903203703402002200241c0006a200241306a10cc0602402002280234450d002002280230102f0b200241206a2001290300200141086a29030010d106200241306a2003200510d1062000200728020036020020022002290320370340200241106a200241c0006a200241306a10cc0602402002280234450d002002280230102f0b2002200241106a10ce06210002402002280214450d002002280210102f0b200041ff0171210002402002280204450d002002280200102f0b20004521000c010b2000290300200129030085200041086a290300200141086a29030085845021000b200241d0006a240020000b930901157f230041206b220524002003410020041b21062001410020021b2107200341206a200320041b2108200141206a200120021b2109200120024105746a210a200320044105746a210b4100210c4100210d4101210e4100210f410021104101211102400340200c4101742112200c4105742113024003402012211420132104200c2102200d2115200e2116200821032006210102400340024020010d004100210620070d022000201636020c2000200f3602082000201036020420002011360200200041146a2002360200200041106a2015360200200541206a24000f0b024020070d00200541186a2203200641186a290000370300200541106a2202200641106a290000370300200541086a2207200641086a290000370300200520062900003703000240200c200d470d00200c41016a2201200c490d07200c41017422042001200420014b1b220141ffffff3f712001470d07200141057422014100480d0702400240200c0d002001102d210e0c010b200e200c41057420011031210e0b200e450d052001410576210d0b200e200c4105746a22012005290300370000200141186a2003290300370000200141106a2002290300370000200141086a200729030037000041002107410020082008200b4622011b2106201241026a2112201341206a2113200c41016a210c2008200841206a20011b21080c030b0240024020012007460d0020012007412010ea0622170d010b2003200341206a2003200b4622011b2108410020092009200a4622041b21074100200320011b21062002210c2015210d2016210e2009200941206a20041b21090c050b02402017417f4c0d00200121060c020b200541186a2217200141186a290000370300200541106a2218200141106a290000370300200541086a2219200141086a29000037030020052001290000370300024020022015470d00200241016a22012002490d0620142001201420014b1b220141ffffff3f712001470d06200141057422014100480d060240024020020d002001102d21160c010b201620042001103121160b2016450d04200141057621150b201620046a22012005290300370000200141186a2017290300370000200141106a2018290300370000200141086a2019290300370000410020032003200b4622171b2101201441026a2114200441206a2104200241016a21022003200341206a20171b21030c000b0b0b200541186a2204200741186a290000370300200541106a2214200741106a290000370300200541086a2217200741086a290000370300200520072900003703000240200f2010470d00200f41016a2201200f490d03200f41017422072001200720014b1b220141ffffff3f712001470d03200141057422014100480d0302400240200f0d002001102d21110c010b2011200f4105742001103121110b2011450d01200141057621100b2011200f4105746a22012005290300370000200141186a2004290300370000200141106a2014290300370000200141086a2017290300370000410020092009200a4622011b2107200f41016a210f2002210c2015210d2016210e2009200941206a20011b2109200321080c010b0b1036000b1038000bb512080a7f027e047f017e047f027e027f057e23002204210520044180016b416071220424000240024002400240024002400240200141ffffff3f712001470d0020014105742206417f4c0d00024020060d00200020014105746a210741012108200121090c030b2006102d2208450d05200020014105746a21072006410576220920014f0d02200941017422062001200620014b1b220641ffffff3f712006470d01200641057422064100480d010240024020090d002006102d21080c010b200820094105742006103121080b2008450d05200641057621090c030b103d000b1038000b20010d00410021060c010b200720006b210a410021060340200820066a2207200020066a220b290000370000200741186a200b41186a290000370000200741106a200b41106a290000370000200741086a200b41086a290000370000200a200641206a2206470d000b200020014105746a20006b41606a41057641016a21060b20042006360208200420093602042004200836020020082006410041202006676b10e003200441206a41186a220a4200370300200441206a41106a220c4200370300200441206a41086a220d42003703002004420037032041f2cbc700ad4280808080b00284220e10012206290000210f200d200641086a2900003703002004200f3703202006102f41e2dec700ad428080808090018410012206290000210f200441c8006a41086a2200200641086a2900003703002004200f3703482006102f200c2004290348220f370300200441e0006a41086a2210200d290300370300200441e0006a41106a2211200f370300200441e0006a41186a2212200029030037030020042004290320370360200441206a200441e0006a412010aa0220042802202206410120061b21132004290224420020061b2214422088a72206450d0120064105742115200441e0006a410c722116200441206a410c6a2101200441206a4114722117200441206a4108722118201321070340200a200741186a290000370300200c200741106a290000370300200d200741086a29000037030020042007290000370320200e10012206290000210f200441106a41086a2208200641086a2900003703002004200f3703102006102f41f2dec700ad4280808080e0008410012206290000210f2000200641086a2900003703002004200f3703482006102f4120102d2206450d0120062004290320370000200641186a200a290300370000200641106a200c290300370000200641086a200d2903003700002006ad42808080808004841003220b290000210f200b41086a2900002119200b41106a290000211a2012200b41186a2900003703002011201a370300201020193703002004200f370360200b102f2006102f41c000102d2206450d01200620042903103700002006200429034837001020062004290360370020200641086a2008290300370000200641186a2000290300370000200641286a2010290300370000200641306a2011290300370000200641386a2012290300370000200441206a200610a1052000200141086a290200370300200441c8006a41106a2209200141106a280200360200200420012902003703482004280240211b02402004280228220b450d002004290320210f20162004290348370200201641086a2000290300370200201641106a20092802003602002004200f370360201b211c0b2004200b360268200441003602282004290378211a20042004290338221d3703782004290370211e20042004290330221f370370200429036021202004200429032022193703602004290368210f2004200429032822213703682021a7210b02400240200fa722090d002021210f201f211e201d211a0c010b200420203703202004200f3703282004201e3703302004201a37033820042009201ea74105746a360254200420093602502004200f422088a736024c2004200936024820042004360258200441106a200441c8006a10f803201841086a2008280200360200201820042903103702002004201e422088a72209201a422088a74105746a360254200420093602502004201aa736024c2004200936024820042004360258200441106a200441c8006a10f803201741086a2008280200360200201720042903103702002004290328210f200429032021192004290338211a2004290330211e0240200b450d00201da7210802402021422088a7450d00200b102f0b2008450d00201f422088a7102f0b200420193703602004200f3703682004201e3703702004201a370378200fa7210b201b211c0b2004200f3703282004201e370330200a201a370300200420193703202004201c360240200fa7210802400240200b0d002006ad428080808080088410050c010b200441c00036024c20042006360248200441206a200441c8006a10b7050b02402008450d00201aa7210b0240200f422088a7450d002008102f0b200b450d00201e422088a7102f0b200741206a21072006102f201541606a22150d000c020b0b1036000b02402014a7450d002013102f0b200441e0006a41186a220a4200370300200441e0006a41106a22074200370300200441e0006a41086a220642003703002004420037036041f2cbc700ad4280808080b00284220f100122002900002119200441106a41086a220b200041086a290000370300200420193703102000102f2006200b2903003703002004200429031037036041ebdec700ad4280808080f00084100122082900002119200441c8006a41086a2200200841086a290000370300200420193703482008102f200720042903482219370300200441206a41086a22012006290300370300200441206a41106a22092019370300200441206a41186a221c200029030037030020042004290360370320200441203602642004200441206a36026020022003200441e0006a10ad01200a4200370300200742003703002006420037030020044200370360200f10012208290000210f200b200841086a2900003703002004200f3703102008102f2006200b2903003703002004200429031037036041fbd4c700ad4280808080d000841001220b290000210f2000200b41086a2900003703002004200f370348200b102f20072004290348220f370300200120062903003703002009200f370300201c200029030037030020042004290360370320200441206aad4280808080800484100502402004280204450d002004280200102f0b200524000bab0704067f017e087f037e230041a0016b220224002002412036021420022001360210200241186a2001ad42808080808004841002107302400240024002400240024020022802182203450d00200228021c21042002200241206a28020036022c20022003360228200241086a200241286a10e60120022802080d03200228020c2205200228022c220641286e2201200120054b1b2207ad42287e2208422088a70d012008a72201417f4c0d010240024020010d00410821090c010b2001102d2209450d03200141286e21070b02402005450d004100210a0340200241003a009801200a220b41016a210a410021010240024002400240034020062001460d01200241f8006a20016a2002280228220c2d00003a00002002200c41016a3602282002200141016a220d3a009801200d2101200d4120470d000b200241d8006a41086a220e200241f8006a41086a290300370300200241d8006a41106a220f200241f8006a41106a290300370300200241d8006a41186a2210200241f8006a41186a2903003703002002200229037837035820022006200d6b220136022c20014108490d01200241386a41086a220d200e290300370300200241386a41106a220e200f290300370300200241386a41186a220f2010290300370300200220022903583703382002200c41096a3602282002200141786a220636022c200c29000121082007200b470d030240200b4101742201200a2001200a4b1bad42287e2211422088a70d002011a7220141004e0d030b1038000b2002410036022c200141ff0171450d00200241003a0098010b2007450d072009102f0c070b02400240200b0d002001102d21090c010b2009200b41286c2001103121090b2009450d05200141286e21070b2009200b41286c6a22012002290338370300200d2903002111200e2903002112200f290300211320012008370320200141186a2013370300200141106a2012370300200141086a2011370300200a2005470d000b0b2009450d032000200736020420002009360200200041086a20053602000c040b200041003602000c040b103d000b1036000b20024100360260200242013703582002410b36023c2002200241106a3602382002200241d8006a3602342002418c016a41013602002002420137027c200241b885c7003602782002200241386a36028801200241346a41d8dbc100200241f8006a103c1a200235026042208620023502588410080240200228025c450d002002280258102f0b200041003602000b2004450d002003102f0b200241a0016a24000bd00a06067f017e097f017e037f037e230041b0016b22022400200241c00036020c20022001360208200241106a2001ad428080808080088410021073024002400240024002400240024020022802102203450d00200228021421042002200241186a280200360224200220033602202002200241206a10e60120022802000d04200228020422052002280224220641d8006e2201200120054b1b2207ad42d8007e2208422088a70d012008a72201417f4c0d010240024020010d00410821090c010b2001102d2209450d03200141d8006e21070b02402005450d004100210a4100210b0340200241003a00a801200b41016a210c4100210102400240024002400240034020062001460d0120024188016a20016a2002280220220d2d00003a00002002200d41016a3602202002200141016a220e3a00a801200e2101200e4120470d000b200241e8006a41086a220f20024188016a41086a290300370300200241e8006a41106a221020024188016a41106a290300370300200241e8006a41186a221120024188016a41186a290300370300200220022903880137036820022006200e6b220136022420014110490d032002200d41116a3602202002200141706a360224200d41096a2900002108200d290001211220024188016a200241206a10f703200228028801220e450d032002280290012113200228028c01210d20024188016a200241206a10980320022802880122060d01200d0d020c030b20024100360224200141ff0171450d02200241003a00a8010c020b200228028c01211420022802242201410f4b0d0202402014450d002006102f0b200d450d010b200e102f0b0240200b450d00200941306a210103400240200141746a280200450d00200141706a280200102f0b02402001280200450d002001417c6a280200102f0b200141d8006a2101200a41a87f6a220a0d000b0b2007450d072009102f0c070b2002280290012115200241c8006a41086a200f2903002216370300200241c8006a41106a20102903002217370300200241c8006a41186a20112903002218370300200241286a41086a220f2016370300200241286a41106a22102017370300200241286a41186a221120183703002002200229036822163703482002200141706a36022420022002280220220141106a36022020022016370328200141086a29000021162001290000211702402007200b470d00200b4101742201200c2001200c4b1bad42d8007e2218422088a70d062018a722014100480d0602400240200b0d002001102d21090c010b2009200b41d8006c2001103121090b2009450d05200141d8006e21070b2009200b41d8006c6a2201201737031020012008370308200120123703002001200636022c2001200e360220200141186a2016370300200141346a2015360200200141306a2014360200200141286a2013360200200141246a200d36020020012002290328370338200141c0006a200f290300370300200141c8006a2010290300370300200141d0006a2011290300370300200c2005460d01200a41d8006a210a20022802242106200c210b0c000b0b2009450d042000200736020420002009360200200041086a20053602000c050b200041003602000c050b103d000b1036000b1038000b20024100360270200242013703682002410b36024c2002200241086a3602482002200241e8006a3602282002419c016a41013602002002420137028c01200241b885c700360288012002200241c8006a36029801200241286a41d8dbc10020024188016a103c1a200235027042208620023502688410080240200228026c450d002002280268102f0b200041003602000b2004450d002003102f0b200241b0016a24000bae0403047f027e057f230041e0006b22022400200241c00036020c20022001360208200241106a2001ad428080808080088410021073024002400240024020022802102201450d00200228021421032002200241186a280200220436022420022001360220024020044104490d002002200141046a36022020022004417c6a220536022420054110490d002001280000210520022004416c6a3602242002200141146a3602202001410c6a290000210620012900042107200241c8006a200241206a10980320022802482204450d00200228024c21082002280224220941024f0d022008450d002004102f0b20024100360230200242013703282002410b36023c2002200241086a3602382002200241286a360244200241dc006a41013602002002420137024c200241b885c7003602482002200241386a360258200241c4006a41d8dbc100200241c8006a103c1a200235023042208620023502288410080240200228022c450d002002280228102f0b200041003602140c020b200041003602140c020b200241d0006a280200210a200241386a41046a200241286a41046a2f0100220b3b010020022002280128220c36023820022009417e6a36022420022002280220220941026a36022020092f000021092000200637030820002007370300200041206a20093b01002000411c6a200a3602002000200836021820002004360214200020053602102000200c360122200041266a200b3b01000b2003450d002001102f0b200241e0006a24000bda04010a7f230041e0006b22022400200241c00036020c20022001360208200241106a2001ad428080808080088410021073024002400240024020022802102201450d00200228021421032002200241186a2802002204360224200220013602200240024020044104490d002002200141046a36022020022004417c6a220536022420054104490d00200128000021062002200141086a3602202002200441786a220536022420054104490d00200128000421052002200441746a36022420022001410c6a360220200128000821072002200241206a10e60120022802000d0020022802242208200228020422094102742204490d002004417f4c0d040240024020040d004101210a0c010b20041033220a450d06200a2002280220220b200410e8061a2002200820046b3602242002200b20046a3602200b200a450d000240024002402004450d00200a4103710d02200941ffffffff037122040d01200a102f0b4104210a410021040b41000d01200a450d01200020043602102000200a36020c200020073602082000200536020420002006360200200041146a20043602000c020b200a102f0b20024100360230200242013703282002410b36023c2002200241086a3602382002200241286a360244200241dc006a41013602002002420137024c200241b885c7003602482002200241386a360258200241c4006a41d8dbc100200241c8006a103c1a200235023042208620023502288410080240200228022c450d002002280228102f0b2000410036020c0b2003450d012001102f0c010b2000410036020c0b200241e0006a24000f0b103d000b1036000b9205010c7f230041e0006b220224002002412036020c20022001360208200241106a2001ad4280808080800484100210730240024002400240024020022802102203450d00200228021421042002200241186a280200360224200220033602202002200241206a10e6010240024020022802000d0020022802042205200228022422064103762201200120054b1b22074103742201417f4c0d040240024020070d00410421080c010b2001102d2208450d060b024002402005450d00410021094100210a4100210b03402002410036024820064104490d0220022006417c6a220636022420022002280220220141046a3602202001280000210c2002410036024820064104490d02200b41016a210d20022006417c6a22063602242002200141086a360220200128000421010240200b2007470d002009200d2009200d4b1b220741ffffffff01712007470d0a200741037422074100480d0a02400240200b0d002007102d21080c010b2008200a2007103121080b2008450d09200741037621070b2008200a6a220b200c360200200b41046a2001360200200941026a2109200a41086a210a200d210b2005200d470d000b0b2008450d012000200736020420002008360200200041086a20053602000c020b2007450d002008102f0b20024100360230200242013703282002410b36023c2002200241086a3602382002200241286a360244200241dc006a41013602002002420137024c200241b885c7003602482002200241386a360258200241c4006a41d8dbc100200241c8006a103c1a200235023042208620023502288410080240200228022c450d002002280228102f0b200041003602000b2004450d012003102f0c010b200041003602000b200241e0006a24000f0b103d000b1036000b1038000b9e0302037f037e230041e0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100210730240024020032802102201450d00200328021421042003200341186a2802002202360224200320013602200240024020024104490d002003200141046a36022020032002417c6a220536022420054110490d002001280000210520032002416c6a3602242003200141146a3602202001410c6a290000210620012900042107200341c8006a200341206a10980320032802482202450d00200329024c210820002006370308200020073703002000200837031820002002360214200020053602100c010b20034100360230200342013703282003410b36023c2003200341086a3602382003200341286a360244200341dc006a41013602002003420137024c200341b885c7003602482003200341386a360258200341c4006a41d8dbc100200341c8006a103c1a200335023042208620033502288410080240200328022c450d002003280228102f0b200041003602140b2004450d012001102f0c010b200041003602140b200341e0006a24000baa06020f7f047e230041a0016b22022400200241c00036020c20022001360208200241106a2001ad428080808080088410021073024002400240024020022802102203450d00200228021421042002200241186a28020022013602242002200336022020014104490d0120022001417c6a3602242002200341046a360220200328000021052002200241206a10e60120022802000d01200228020421062002420037022c20024190bdc60036022802402006450d0020022802242107410021080340200241003a009801200841016a210841002101024002400240034020072001460d01200241f8006a20016a200228022022092d00003a00002002200941016a3602202002200141016a220a3a009801200a2101200a4120470d000b200241d8006a41186a220b200241f8006a41186a220c290300370300200241d8006a41106a220d200241f8006a41106a220e290300370300200241d8006a41086a220f200241f8006a41086a2210290300370300200220022903783703582007200a6b220141034b0d02200220013602240c010b20024100360224200141ff0171450d00200241003a0098010b2002280228200229022c2211a72011422088a710a3020c040b200241386a41086a200f2903002211370300200241386a41106a200d2903002212370300200241386a41186a200b29030022133703002002200229035822143703382002200941056a3602202009280001210a200c2013370300200e20123703002010201137030020022014370378200241286a200241f8006a200a10ed012001417c6a210720082006470d000b20022001417c6a3602240b20022802282201450d012000200229022c37020820002001360204200020053602000c020b200041003602040c020b20024100360260200242013703582002410b36023c2002200241086a3602382002200241d8006a3602282002418c016a41013602002002420137027c200241b885c7003602782002200241386a36028801200241286a41d8dbc100200241f8006a103c1a200235026042208620023502588410080240200228025c450d002002280258102f0b200041003602040b2004450d002003102f0b200241a0016a24000bd90704057f047e067f037e230041c0016b22022400200241c00036023420022001360230200241386a2001ad4280808080800884100210730240024020022802382203450d00200228023c21042002200241c0006a280200220536026c2002200336026841002101200241003a00b801024002400240024002400240034020052001460d0120024198016a20016a200320016a22062d00003a00002002200641016a3602682002200141016a22063a00b8012006210120064120470d000b200241f8006a41086a20024198016a41086a290300370300200241f8006a41106a20024198016a41106a290300370300200241f8006a41186a20024198016a41186a29030037030020022002290398013703782002200520066b36026c200241186a200241e8006a109c032002290318a70d04200241186a41106a2903002107200229032021082002200241e8006a109c032002290300a70d04200241106a29030021092002290308210a20024198016a200241e8006a10c3032002280298012206450d04200228029c012105200228026c220b450d03200241a0016a280200210c2002200b417f6a220d36026c20022002280268220e41016a360268200e2d0000220f41014b0d0341002101200f0e020201020b2002410036026c200141ff0171450d03200241003a00b8010c030b200d4104490d012002200b417b6a36026c2002200e41056a360268200e2800012110410121010b200241c8006a41186a200241f8006a41186a2903002211370300200241c8006a41106a200241f8006a41106a2903002212370300200241c8006a41086a200241f8006a41086a290300221337030020024198016a41086a220b201337030020024198016a41106a220e201237030020024198016a41186a220f2011370300200220022903782211370348200041186a20093703002000200a37031020002007370308200020083703002000200c3602282000200536022420002006360220200220113703980120002010360230200041346a2002290398013702002000413c6a200b290300370200200041c4006a200e290300370200200041cc006a200f2903003702000c020b2005450d002006102f0b2002410036028001200242013703782002410b36024c2002200241306a3602482002200241f8006a360274200241ac016a41013602002002420137029c01200241b885c700360298012002200241c8006a3602a801200241f4006a41d8dbc10020024198016a103c1a20023502800142208620023502788410080240200228027c450d002002280278102f0b410221010b2000200136022c2004450d012003102f0c010b2000410236022c0b200241c0016a24000bb704010b7f230041e0006b22022400200241c00036020c20022001360208200241106a2001ad428080808080088410021073024002400240024020022802102201450d00200228021421032002200241186a280200220436022420022001360220024020044104490d002002200141046a36022020022004417c6a220536022420054104490d00200128000021062002200441786a3602242002200141086a36022020012800042107200241c8006a200241206a10980320022802482204450d00200241c8006a41086a2802002108200228024c2105200241c8006a200241206a109803024020022802482209450d00200228024c210a2002280224220b41044f0d03200a450d002009102f0b2005450d002004102f0b20024100360230200242013703282002410b36023c2002200241086a3602382002200241286a360244200241dc006a41013602002002420137024c200241b885c7003602482002200241386a360258200241c4006a41d8dbc100200241c8006a103c1a200235023042208620023502288410080240200228022c450d002002280228102f0b200041003602080c020b200041003602080c020b200241d0006a280200210c2000200536020c200020043602082000200736020420002006360200200041206a200228022022042800003602002000411c6a200c360200200041186a200a360200200041146a2009360200200041106a20083602002002200b417c6a3602242002200441046a3602200b2003450d002001102f0b200241e0006a24000be80203017f017e027f23004190056b22022400200241c0003602b402200220013602b002200241b8026a2001ad42808080808008842203100210730240024020022802b80222010d00411b21010c010b20022802bc0221042002200241c0026a2802003602fc04200220013602f804200241c8026a200241f8046a10b3020240024020022802c8022205411b460d002002200241c8026a41047241ac0210e8061a0c010b20024100360208200242013703002002410b360284052002200241b0026a360280052002200236028c05200241dc026a4101360200200242013702cc02200241b885c7003602c802200220024180056a3602d8022002418c056a41d8dbc100200241c8026a103c1a200235020842208620023502008410082002280204450d002002280200102f0b02402004450d002001102f0b411b21012005411b460d0020031005200521010b20002001360200200041046a200241ac0210e8061a20024190056a24000bf11a04027f027e087f067e230041800c6b22082400200728024021090240024020020d00200941d8006a290300210a0c010b02402001290310220b200141186a290300220a8450450d004200210a0c010b200841206a200941a0016a290300200941a8016a290300200b200a10ee062008290320427f200841286a290300501b210a0b200142002001290308220b200a7d220a200a200b561b37030802400240200a200b580d00200041003a0000200041086a4122360200200041046a41ea93c7003602000c010b0240024002400240024002400240200728021841016a220c41004c0d002007200c360218200741206a280200210d2007411c6a220e21010240024002400340024002402001280200220f2f010622100d00410021020c010b20104105742101200f41c5036a2111200f41086a2109417f21020340024020010d00201021020c020b20032009412010ea062212450d03200141606a2101201141e0006a2111200241016a2102200941206a21092012417f4a0d000b0b200d450d02200d417f6a210d200f20024102746a41880b6a21010c000b0b2011310000201141a37f6a290300220b200b5022011ba7450d004200201141ab7f6a220941086a29030020011b210b4200200929030020011b210a0c010b200841106a200741286a28020020032007412c6a28020028021c110300200841186a290300210b2007280218210c2008290310210a0b2007200c417f6a22133602180240200a20057d2214200a56200b20067d200a200554ad7d220a200b56200a200b511b4101470d00200041003a0000200041086a411d360200200041046a418c94c7003602000c080b200c41004c0d012007200c3602182007280220210d200e21010240024002400340024002402001280200220f2f010622100d00410021020c010b20104105742101200f41c5036a2111200f41086a2109417f21020340024020010d00201021020c020b20042009412010ea062212450d03200141606a2101201141e0006a2111200241016a2102200941206a21092012417f4a0d000b0b200d450d02200d417f6a210d200f20024102746a41880b6a21010c000b0b2011310000201141a37f6a290300220b200b5022011ba7450d004200201141ab7f6a220941086a29030020011b210b4200200929030020011b21150c010b2008200741286a28020020042007412c6a28020028021c1103002007280218417f6a2113200841086a290300210b200829030021150b2007201336021802402015200b844200520d00200728024022012903800120055820014188016a290300221620065820162006511b0d00200041003a0000200041086a411f360200200041046a41a994c7003602000c080b02402005200684500d0020084180016a2003108d0220082903a001201456200841a8016a2903002216200a562016200a511b0d030b0240201520057c22162015542201200b20067c2001ad7c2215200b542015200b511b450d00200041003a0000200041086a412d360200200041046a41c894c7003602000c080b024020032004460d0020032004412010ea06450d0020072802180d042007417f360218200841e0006a41186a200341186a290000370300200841e0006a41106a200341106a290000370300200841e0006a41086a200341086a2900003703002008200329000037036002400240200728021c220f4190bdc600460d002007280220210d0c010b4100210d200841a0096a410041e00210e7061a20084180016a410041a00810e7061a41880b102d220f450d06200f41003b0106200f4100360200200f41086a200841a0096a41e00210e8061a200f41e8026a20084180016a41a00810e8061a200741003602202007200f36021c0b02400240034002400240200f2f010622100d00410021020c010b20104105742101200f41e8026a2111200f41086a2109417f21020340024020010d00201021020c020b200841e0006a2009412010ea062212450d03200141606a2101201141e0006a2111200241016a2102200941206a21092012417f4a0d000b0b0240200d450d00200d417f6a210d200f20024102746a41880b6a280200210f0c010b0b200841c0006a41186a200841e0006a41186a290300220b370300200841c0006a41106a200841e0006a41106a2903002217370300200841c0006a41086a200841e0006a41086a2903002218370300200820082903602219370340200841bc096a2018370200200841a0096a41246a2017370200200841cc096a200b3702002008200741246a3602b009200820023602ac092008200e3602a8092008200f3602a409200841003602a009200820193702b409200841b4016a4200370200200841bc016a41003a000020084190bdc6003602b00120084200370398012008420037038001200841003a00dd01200841a0096a20084180016a10970221110c010b20084198016a420037030020084194016a4190bdc600360200200841003602a0012008410036029001200842003703880120084190bdc60036028401200841003602800120084180016a1090020b201141106a200a370300201120143703082011420137030020072007280218220141016a2209360218200920014f0d062007417f360218200841e0006a41186a200441186a290000370300200841e0006a41106a200441106a290000370300200841e0006a41086a200441086a2900003703002008200429000037036002400240200728021c220f4190bdc600460d002007280220210d0c010b4100210d200841a0096a410041e00210e7061a20084180016a410041a00810e7061a41880b102d220f450d06200f41003b0106200f4100360200200f41086a200841a0096a41e00210e8061a200f41e8026a20084180016a41a00810e8061a200741003602202007200f36021c0b02400240034002400240200f2f010622100d00410021020c010b20104105742101200f41e8026a2111200f41086a2109417f21020340024020010d00201021020c020b200841e0006a2009412010ea062212450d03200141606a2101201141e0006a2111200241016a2102200941206a21092012417f4a0d000b0b0240200d450d00200d417f6a210d200f20024102746a41880b6a280200210f0c010b0b200841c0006a41186a200841e0006a41186a290300220b370300200841c0006a41106a200841e0006a41106a290300220a370300200841c0006a41086a200841e0006a41086a2903002214370300200820082903602217370340200841bc096a2014370200200841a0096a41246a200a370200200841cc096a200b3702002008200741246a3602b009200820023602ac092008200e3602a8092008200f3602a409200841003602a009200820173702b409200841b4016a4200370200200841bc016a41003a000020084190bdc6003602b00120084200370398012008420037038001200841003a00dd01200841a0096a20084180016a10970221110c010b20084198016a420037030020084194016a4190bdc600360200200841003602a0012008410036029001200842003703880120084190bdc60036028401200841003602800120084180016a1090020b201141106a201537030020112016370308201142013703002007200728021841016a360218200841a0096a41086a2209200341086a290000370300200841a0096a41106a2202200341106a290000370300200841a0096a41186a2211200341186a290000370300200841e0006a41086a2212200441086a290000370300200841e0006a41106a220f200441106a290000370300200841e0006a41186a220d200441186a290000370300200820032900003703a0092008200429000037036002402007413c6a2802002201200741386a280200470d00200141016a22032001490d08200141017422042003200420034b1bad42d8027e220b422088a70d08200ba722034100480d080240024020010d002003102d21010c010b2007280234200141d8026c2003103121010b2001450d0620072001360234200741386a200341d8026e360200200728023c21010b2007280234200141d8026c6a220141003a0000200120082f003d3b00012001420037000820014101360004200120082903a00937001120012008290360370031200141036a2008413f6a2d00003a0000200141106a41003a0000200141196a2009290300370000200141216a2002290300370000200141296a2011290300370000200141396a2012290300370000200141c1006a200f290300370000200141c9006a200d29030037000020012005370358200141e0006a2006370300200141d4006a200841366a41036a2800003600002001200828003636005120012008290340370368200141f0006a200841c0006a41086a290300370300200141f8006a200841c0006a41106a29030037030020014180016a200841c0006a41186a29030037030020014188016a20084180016a41d00110e8061a2007200728023c41016a36023c0b200041043a00000c070b41c6c4ca00411820084180016a41cc90c70041f0c4ca00103e000b41c6c4ca00411820084180016a41cc90c70041f0c4ca00103e000b200041830c3b0100200041086a4115360200200041046a41abb5c600360200200041026a41013a00000c040b41c3c5ca00411020084180016a41dc90c70041e4c5ca00103e000b1036000b41c3c5ca00411020084180016a41dc90c70041e4c5ca00103e000b1038000b200841800c6a24000b9f2107087f017e057f057e147f047e017f230041f00c6b220224000240024020002802000d002000417f360200200128020821032001280200210402400240200128020422050d00200421010c010b2005210620042101034020012802880b21012006417f6a22060d000b0340200420042f01064102746a41880b6a28020021042005417f6a22050d000b0b2002411c6a20042f010636020041002105200241186a4100360200200241146a2004360200200220033602202002410036021020024200370308200220013602042002410036020002402003450d0020022003417f6a22073602200240024020012f0106450d004100210420012108410021090c010b4100210441002109034002400240024020014190bdc600460d00200128020022080d012009ad210a410021080c020b41edb3ca00412841f8b4ca001039000b200441016a210420013301044220862009ad84210a0b2001102f200aa7210920082101200a422088a7220520082f01064f0d000b0b200241d00c6a41186a2206200820054105746a220141206a290000370300200241d00c6a41106a2203200141186a290000370300200241d00c6a41086a220b200141106a2900003703002002200141086a2900003703d00c2008200541e0006c6a220141a4036a2d0000210c200141a0036a280200210d2001419c036a280200210e20014198036a280200210f20014190036a290300211020014188036a290300211120014180036a2903002112200141f8026a2903002113200141f0026a2903002114200141e8026a290300210a200241d0016a41186a2215200141bd036a290000370300200241d0016a41106a2216200141b5036a290000370300200241d0016a41086a2217200141ad036a2900003703002002200141a5036a2900003703d001200541016a2118200141c6036a2f01002119200141c5036a2d0000211a02402004450d00200820184102746a41880b6a2802002108410021182004417f6a2201450d00034020082802880b21082001417f6a22010d000b0b200241f0096a41186a2006290300370300200241f0096a41106a2003290300370300200241f0096a41086a200b29030037030020024188016a41086a201729030037030020024188016a41106a201629030037030020024188016a41186a2015290300370300200220022903d00c3703f009200220022903d001370388012002201836020c200220093602082002200836020420024100360200200a4202510d002000410c6a211b200041046a211c200241d0016a41206a210b200241840a6a211d2002418d026a211e200241d0016a41286a211f0340200241c8006a41186a2201200241f0096a41186a2216290300370300200241c8006a41106a2204200241f0096a41106a2217290300370300200241c8006a41086a2205200241f0096a41086a2220290300370300200241286a41086a220620024188016a41086a2221290300370300200241286a41106a220320024188016a41106a2222290300370300200241286a41186a221520024188016a41186a2223290300370300200220022903f0093703482002200229038801370328200241e8006a41186a22242015290300370300200241e8006a41106a22252003290300370300200241e8006a41086a2226200629030037030020022002290328370368202320012903003703002022200429030037030020212005290300370300200220022903483703880102400240201c28020022034190bdc600460d00200028020821270c010b200241f0096a410041e00210e7061a200241d0016a410041a00810e7061a41880b102d2203450d0441002127200341003b010620034100360200200341086a200241f0096a41e00210e8061a200341e8026a200241d0016a41a00810e8061a20004100360208200020033602040b0240024003400240024020032f010622280d00410021040c010b20284105742115417f210441002101410021050340024020152001470d00202821040c020b20024188016a200320016a41086a412010ea062206450d03200141206a2101200541e0006a2105200441016a21042006417f4a0d000b0b02402027450d002027417f6a2127200320044102746a41880b6a28020021030c010b0b200241d00c6a41186a20232903002229370300200241d00c6a41106a2022290300222a370300200241d00c6a41086a2021290300222b3703002002200229038801222c3703d00c201d202c370200201d41086a202b370200201d41106a202a370200201d41186a20293702002002201b3602800a200220043602fc092002201c3602f809200220033602f409200241003602f009201f2010370300200241d0016a41106a2013370300200220113703f001200220143703d8012002200c3a008c022002200d360288022002200e360284022002200f36028002200220123703e8012002200a3703d001201e2002290368370000201e41086a2026290300370000201e41106a2025290300370000201e41186a2024290300370000200220193b01ae022002201a3a00ad02200241f0096a200241d0016a1097021a0c010b200320056a21030240201a4101710d00200341e8026a22012001290300200a200a5022011b370300200341f0026a22042004290300201420011b370300200341f8026a22042004290300201320011b370300201620242903003703002017202529030037030020202026290300370300200220022903683703f009200341a4036a22042d00002105200241d0016a41186a2228200341bd036a2206290000370300200241d0016a41106a221a200341b5036a2215290000370300200241d0016a41086a2224200341ad036a22272900003703002002200341a5036a22252900003703d0012021200241f0096a200241d0016a200c41ff0171410146220c1b220141086a2900003703002022200141106a2900003703002023200141186a2900003703002002200129000037038801200441012005200c1b3a0000202520022903880137000020272021290300370000201520222903003700002006202329030037000020034188036a2201201120012903002012a722011b37030020034190036a22042010200429030020011b37030020034180036a22042012200429030020011b37030002400240200e0d00200f21010c010b200e2104200f2101034020012802ec0321012004417f6a22040d000b0340200f200f2f01064102746a41ec036a280200210f200e417f6a220e0d000b0b200f2f010621042002200d3602a801200220043602a401200241003602a0012002200f36029c01200241003602980120024200370390012002200136028c0120024100360288010240200d450d0020034198036a210c410021064100210503402002200d417f6a220d3602a80102400240200620012f01064f0d0041002103200121040c010b41002103034002400240024020014190bdc600460d00200128020022040d012005ad210a410021040c020b41edb3ca00412841f8b4ca001039000b200341016a210320013301044220862005ad84210a0b2001102f200aa7210520042101200a422088a7220620042f01064f0d000b0b200241d00c6a41186a2215200420064105746a220141206a290000370300200241d00c6a41106a220f200141186a290000370300200241d00c6a41086a220e200141106a2900003703002002200141086a2900003703d00c200241b0016a41086a222720042006410c6c6a220141f0026a2802003602002002200141e8026a2902003703b001200641016a21060240024020030d00200421010c010b200420064102746a41ec036a2802002101410021062003417f6a2204450d00034020012802ec0321012004417f6a22040d000b0b200b20022903b001370200200b41086a220420272802003602002020200e2903003703002017200f29030037030020162015290300370300200241f0096a41206a2203200b290300370300200241f0096a41286a2227201f280200360200200220022903d00c3703f009200220063602940120022005360290012002200136028c012002410036028801201f2027280200360200200b200329030037030020282016290300370300201a201729030037030020242020290300370300200220022903f0093703d00120152016290300370300200f2017290300370300200e2020290300370300200220022903f0093703d00c200241c0016a41086a20042802003602002002200b2902003703c001200241b0016a200c200241d00c6a200241c0016a109802024020022802b001450d0020022802b4012204450d0020022802b801450d002004102f0b200d0d000b0b20024188016a1090020c010b200341a0036a2215280200212720034198036a22282802002101024002402003419c036a222d28020022050d00200121040c010b2005210620012104034020042802ec0321042006417f6a22060d000b0340200120012f01064102746a41ec036a28020021012005417f6a22050d000b0b200220273602f001200241003602e801200241003602e001200242003703d801200220043602d401200241003602d001200220013602e401200220012f01063602ec01200241d0016a109002200341e8026a200a37030020034190036a201037030020034188036a2011370300200341f8026a2013370300200341f0026a201437030020034180036a2012370300200341a4036a200c3a00002015200d3602002028200f360200202d200e360200200341a5036a2002290368370000200341ad036a2026290300370000200341b5036a2025290300370000200341bd036a2024290300370000200341c6036a20193b0100200341c5036a201a3a00000b2007450d0120022007417f6a22073602204100210402400240201820082f01064f0d00200821010c010b41002104034002400240024020084190bdc600460d00200828020022010d012009ad210a410021010c020b41edb3ca00412841f8b4ca001039000b200441016a210420083301044220862009ad84210a0b2008102f200aa7210920012108200a422088a7221820012f01064f0d000b0b200241d00c6a41186a2206200120184105746a220541206a290000370300200241d00c6a41106a2203200541186a290000370300200241d00c6a41086a2215200541106a2900003703002002200541086a2900003703d00c2001201841e0006c6a220541a4036a2d0000210c200541a0036a280200210d2005419c036a280200210e20054198036a280200210f20054190036a290300211020054188036a290300211120054180036a2903002112200541f8026a2903002113200541f0026a2903002114200541e8026a290300210a200241d0016a41186a2227200541bd036a290000370300200241d0016a41106a2228200541b5036a290000370300200241d0016a41086a2224200541ad036a2900003703002002200541a5036a2900003703d001201841016a2118200541c6036a2f01002119200541c5036a2d0000211a0240024020040d00200121080c010b200120184102746a41880b6a2802002108410021182004417f6a2201450d00034020082802880b21082001417f6a22010d000b0b201620062903003703002017200329030037030020202015290300370300202120242903003703002022202829030037030020232027290300370300200220022903d00c3703f009200220022903d001370388012002201836020c200220093602082002200836020420024100360200200a4202520d000b0b2002108a022000200028020041016a360200200241f00c6a24000f0b41c3c5ca004110200241d0016a41dc90c70041e4c5ca00103e000b1036000bc50101057f230041306b220124002000410c6a28020021022000280204210302400240200041086a28020022040d00200321000c010b2004210520032100034020002802880b21002005417f6a22050d000b0340200320032f01064102746a41880b6a28020021032004417f6a22040d000b0b200141246a20032f0106360200200141206a41003602002001411c6a20033602002001200236022820014100360218200142003703102001200036020c20014100360208200141086a108a02200141306a24000be104010a7f230041c0006b220324000240200128020041016a220441004c0d0020012004360200200141046a2105200141086a28020021060240024002400240034002400240200528020022072f010622080d00410021090c010b20084105742105200741c5036a210a200741086a210b417f21090340024020050d00200821090c020b2002200b412010ea06220c450d03200541606a2105200a41e0006a210a200941016a2109200b41206a210b200c417f4a0d000b0b2006450d022006417f6a2106200720094102746a41880b6a21050c000b0b02400240200a2d00000d00200a415f6a2d0000210b200341206a41186a2209200a41606a220541186a290000370300200341206a41106a220a200541106a290000370300200341206a41086a220c200541086a2900003703002003200529000037032041022105200b4101470d01200341186a2009290300370300200341106a200a290300370300200341086a200c29030037030020032003290320370300410121050c010b200a415f6a2d00002105200341186a200a41606a220b41186a290000370300200341106a200b41106a290000370300200341086a200b41086a2900003703002003200b2900003703000b200541ff01714102470d010b200020012802102002200141146a280200280210110300200128020021040c010b200020053a000020002003290300370001200041096a200341086a290300370000200041116a200341106a290300370000200041196a200341186a2903003700000b20012004417f6a360200200341c0006a24000f0b41c6c4ca004118200341206a41cc90c70041f0c4ca00103e000bcd02010a7f230041106b220224000240200028020041016a220341004c0d0020002003360200200041046a2104200041086a28020021050240024002400240034002400240200428020022062f010622070d00410021080c010b20074105742104200641a4036a2109200641086a210a417f21080340024020040d00200721080c020b2001200a412010ea06220b450d03200441606a2104200941e0006a2109200841016a2108200a41206a210a200b417f4a0d000b0b2005450d022005417f6a2105200620084102746a41880b6a21040c000b0b20092d000022044101410220044101461b200941216a2d00001b22044102470d010b20002802102001200041146a2802002802181101002104200028020021030c010b200441004721040b20002003417f6a360200200241106a240020040f0b41c6c4ca004118200241086a41cc90c70041f0c4ca00103e000bff02020a7f027e230041206b220324000240200128020041016a220441004c0d0020012004360200200141046a2105200141086a2802002106024002400240034002400240200528020022072f010622080d00410021090c010b20084105742105200741c5036a210a200741086a210b417f21090340024020050d00200821090c020b2002200b412010ea06220c450d03200541606a2105200a41e0006a210a200941016a2109200b41206a210b200c417f4a0d000b0b2006450d022006417f6a2106200720094102746a41880b6a21050c000b0b200a310000200a41a37f6a290300220d200d5022051ba7450d004200200a41ab7f6a220b41086a29030020051b210d4200200b29030020051b210e0c010b200341086a20012802102002200141146a28020028021c110300200341106a290300210d200128020021042003290308210e0b20012004417f6a3602002000200d3703082000200e370300200341206a24000f0b41c6c4ca004118200341186a41cc90c70041f0c4ca00103e000b1300200041013602042000419096c7003602000b34002000419487ca0036020420004100360200200041146a4103360200200041106a419097c700360200200041086a420a3702000b130020004106360204200041ec9ac7003602000b3400200041bd98ca0036020420004100360200200041146a4106360200200041106a41f8b3c700360200200041086a42103702000b13002000410536020420004180bdc7003602000b2e01017f02404104102d22020d001036000b20004284808080c0003702042000200236020020024180a70c3600000b2c01017f02404104102d22020d001036000b20004284808080c00037020420002002360200200241073600000b2c01017f02404104102d22020d001036000b20004284808080c000370204200020023602002002410d3600000b3a01017f02404110102d22020d001036000b2002420037000820024280809aa6eaafe301370000200042908080808002370204200020023602000b130020004107360204200041b0c0c7003602000bd70303027f037e027f230041d0006b2201240041bd98ca00ad4280808080800284100122022900002103200141106a41086a200241086a290000370300200120033703102002102f41ce89c700ad4280808080f00084100122022900002103200141206a41086a200241086a290000370300200120033703202002102f02404120102d2202450d0020022000290000370000200241186a200041186a290000370000200241106a200041106a290000370000200241086a200041086a2900003700002002ad4280808080800484100322002900002103200041086a2900002104200041106a2900002105200141306a41186a2206200041186a290000370300200141306a41106a22072005370300200141306a41086a2004370300200120033703302000102f2002102f41c000102d2202450d00200220012903103700002002200129032037001020022001290330370020200241086a200141106a41086a290300370000200241186a200141206a41086a290300370000200241286a200141306a41086a290300370000200241306a2007290300370000200241386a2006290300370000200141086a200241c00041c8e1ca004100410010b501200128020821002002102f200141d0006a240020004101460f0b1036000b9f1705027f017e017f027e047f230041a0046b2202240041bd98ca00ad4280808080800284100122032900002104200241d0006a41086a200341086a290000370300200220043703502003102f41ae85c700ad4280808080f0008410012203290000210420024190036a41086a200341086a29000037030020022004370390032003102f02404120102d2203450d0020032000290000370000200341186a200041186a290000370000200341106a200041106a290000370000200341086a200041086a2900003700002003ad4280808080800484100322052900002104200541086a2900002106200541106a2900002107200241e0016a41186a2208200541186a290000370300200241e0016a41106a22092007370300200241e0016a41086a2006370300200220043703e0012005102f2003102f41c000102d2203450d00200320022903503700002003200229039003370010200320022903e001370020200341086a200241d0006a41086a290300370000200341186a20024190036a41086a290300370000200341286a200241e0016a41086a290300370000200341306a2009290300370000200341386a2008290300370000200241e0016a200341c000109504024020022d00ec0122054102460d002003ad428080808080088410050b20022902e401210420022802e00121082002410c6a200241ed016a41c30010e8061a200241d0006a2002410c6a41c30010e8061a0240024020054102470d002003102f0c010b200220053a00980120024198016a410172200241d0006a41c10010e806210a200241ba016a21090240024020022d00b901220b4101460d00200241003602e0020c010b200241e0026a20091094040b0240024002400240024020054101460d00200241003602f0020c010b200241f0026a200a10940420022802f0020d010b0240200b4101460d0041bd98ca00ad4280808080800284100122052900002106200241f0036a41086a2209200541086a290000370300200220063703f0032005102f41a185c700ad4280808080d0018410012205290000210620024190036a41086a220b200541086a29000037030020022006370390032005102f200241e0016a41086a2009290300370300200241f8016a200b290300370300200220022903f0033703e00120022002290390033703f00120024190036a200241e0016a1088012002350298034220862002280290032205ad841005200228029403450d022005102f0c020b41bd98ca00ad4280808080800284100122052900002106200241f0036a41086a220b200541086a290000370300200220063703f0032005102f41a185c700ad4280808080d0018410012205290000210620024190036a41086a220a200541086a29000037030020022006370390032005102f200241e0016a41086a200b290300370300200241e0016a41186a200a290300370300200220022903f0033703e00120022002290390033703f00120024190036a200241e0016a108801200228029003210b20023502980321064120102d2205450d0420052009290000370000200541186a200941186a290000370000200541106a200941106a290000370000200541086a200941086a2900003700002006422086200bad842005ad428080808080048410042005102f200228029403450d01200b102f0c010b20024180036a41086a200241f0026a41086a2802002205360200200220022903f00222063703800320024190036a2006a7220b20051095040240024020022d009c034102460d00200241e0016a20024190036a41d00010e8061a200241ad026a200241b9016a220941206a2d00003a0000200241a5026a200941186a2900003700002002419d026a200941106a29000037000020024195026a200941086a2900003700002002418d026a2009290000370000200220053602f4032002200b3602f003200241e0016a200241f0036a10ef0320022802e401450d0120022802e001102f0c010b200241003602e803200242013703e003200241f0036a41146a4129360200200241fc036a410b3602002002411036028c04200241bd98ca00360288042002410b3602f4032002410736029404200241ae85c70036029004200220024180036a36028004200220024190046a3602f803200220024188046a3602f0032002200241e0036a36029c04200241e0016a41146a4103360200200242033702e4012002419090c4003602e0012002200241f0036a3602f0012002419c046a41d8dbc100200241e0016a103c1a20023502e80342208620023502e00384100820022802e403450d0020022802e003102f0b0240200228028403450d00200228028003102f0b410121090c010b410021090b0240024020022802e00222050d004100210b0c010b20024180036a41086a200241e0026a41086a280200220b360200200220022903e00222063703800320024190036a2006a7220a200b1095040240024020022d009c034102460d00200241e0016a20024190036a41d00010e8061a2002418c026a200241b8016a2d00003a000020024184026a200241b0016a290300370200200241fc016a200241a8016a290300370200200241f4016a20024198016a41086a29030037020020022002290398013702ec012002200b3602f4032002200a3602f003200241e0016a200241f0036a10ef0320022802e401450d0120022802e001102f0c010b200241003602e803200242013703e003200241f0036a41146a4129360200200241fc036a410b3602002002411036028c04200241bd98ca00360288042002410b3602f4032002410736029404200241ae85c70036029004200220024180036a36028004200220024190046a3602f803200220024188046a3602f0032002200241e0036a36029c04200241e0016a41146a4103360200200242033702e401200241b48fc4003602e0012002200241f0036a3602f0012002419c046a41d8dbc100200241e0016a103c1a20023502e80342208620023502e00384100820022802e403450d0020022802e003102f0b0240200228028403450d00200228028003102f0b4101210b0b0240200920022802f002220a45720d0020022802f402450d00200a102f0b0240200b200545720d0020022802e402450d002005102f0b2003102f2008450d002004a7450d002008102f0b41bd98ca00ad4280808080800284100122032900002104200241d0006a41086a200341086a290000370300200220043703502003102f41ce89c700ad4280808080f0008410012203290000210420024190036a41086a200341086a29000037030020022004370390032003102f4120102d2203450d0020032000290000370000200341186a200041186a290000370000200341106a200041106a290000370000200341086a200041086a2900003700002003ad4280808080800484100322052900002104200541086a2900002106200541106a2900002107200241e0016a41186a2208200541186a290000370300200241e0016a41106a22092007370300200241e0016a41086a2006370300200220043703e0012005102f2003102f41c000102d2203450d00200320022903503700002003200229039003370010200320022903e001370020200341086a200241d0006a41086a290300370000200341186a20024190036a41086a290300370000200341286a200241e0016a41086a290300370000200341306a2009290300370000200341386a20082903003700002003ad428080808080088410052003102f200242f0d0c9abc6add9b1f4003703002002200010b10102402001450d00200242003703582002428080e983b1de163703502002200036020c20024190036a2000200241d0006a2002410c6a1096012002290390034201520d00200229039803210420024198026a20024190036a41106a29030037030020024190026a2004370300200241e0016a41086a41003a0000200241e9016a2000290000370000200241f1016a200041086a290000370000200241f9016a200041106a29000037000020024181026a200041186a290000370000200241033a00e00141c8e1ca004100200241e0016a108c010b200241a0046a24000f0b1036000b9d1606017f017e037f017e067f097e230041c0016b2202240042002103200241a0016a41186a4200370300200241a0016a41106a22044200370300200241a0016a41086a22054200370300200242003703a00141bd98ca00ad42808080808002841001220629000021072005200641086a290000370300200220073703a0012006102f41ebdec700ad4280808080f00084100122062900002107200241e0006a41086a2208200641086a290000370300200220073703602006102f20042002290360220737030020024180016a41086a200529030037030020024180016a41106a200737030020024180016a41186a2008290300370300200220022903a00137038001200241c0006a20024180016a10e404024002400240200228024022090d00410821090c010b4100210502400240200229024422034220882207a7220a41014b0d00200a0e020201020b200a210603402006410176220820056a220b20052009200b41306c6a2001412010ea064101481b2105200620086b220641014b0d000b0b2009200541306c6a2001412010ea060d000240024002400240024002402005200a4f0d002009200541306c6a2206200641306a200a2005417f736a41306c10e9061a200241a0016a41186a220c4200370300200241a0016a41106a220d4200370300200241a0016a41086a220a4200370300200242003703a00141bd98ca00ad4280808080800284220e10012205290000210f200a200541086a2900003703002002200f3703a0012005102f419691c700ad4280808080900184221010012206290000210f200241e0006a41086a2205200641086a2900003703002002200f3703602006102f20042002290360370000200441086a200529030037000020024180016a41086a2206200a29030037030020024180016a41106a200d29030037030020024180016a41186a200c290300370300200220022903a00137038001200742ffffffff0f7c210f200241a0016a20024180016a10e40420022802a0012208410820081b210b0240024020022902a401420020081b2207422088221150450d00420021120c010b200c200b201142ffffffff0f7c2211a741306c6a220841186a290300370300200d200841106a290300370300200a200841086a290300370300200220082903003703a0012011422086200742ffffffff0f83842107200841286a290300211320082903202114420121120b200342ffffffff0f832115200f4220862111200241e0006a41186a4200370300200241e0006a41106a220442003703002005420037030020024200370360200e10012208290000210e2006200841086a2900003703002002200e370380012008102f200520062903003703002002200229038001370360201010012208290000210e2006200841086a2900003703002002200e370380012008102f2004200229038001220e370300200241c0006a41086a2005290300370300200241c0006a41106a200e370300200241c0006a41186a20062903003703002002200229036037034002400240200b0d00200241c0006aad428080808080048410050c010b20024120360284012002200241c0006a36028001200b2007422088a720024180016a10ab012007a7450d00200b102f0b20152011842107200241186a200241a0016a41186a290300220e370300200241106a200241a0016a41106a2903002210370300200241086a200241a0016a41086a2903002215370300200220022903a0012216370300200241206a41186a2205200e370300200241206a41106a22062010370300200241206a41086a22082015370300200220163703204100210c0240201250450d004100210a0c040b20024180016a41186a200529030037030020024180016a41106a200629030037030020024180016a41086a2008290300370300200220022903203703800141002105024002400240200fa7220a41014b0d00200a0e020201020b200a210603402006410176220820056a220b20052009200b41306c6a20024180016a412010ea064101481b2105200620086b220641014b0d000b0b2009200541306c6a20024180016a412010ea062206450d022006411f7620056a21050b200241c0006a41186a20024180016a41186a290300220f370300200241c0006a41106a20024180016a41106a290300220e370300200241c0006a41086a20024180016a41086a290300221037030020022002290380012212370340200241e0006a41186a200f370300200241e0006a41106a200e370300200241e0006a41086a201037030020022012370360200241a0016a41186a200f370300200241a0016a41106a200e370300200241a0016a41086a2010370300200220123703a0012005200a4b0d020240200a2003a7470d00200a41016a2206200a490d06200a41017422082006200820064b1bad42307e2207422088a70d062007a722064100480d0602400240200a0d002006102d21090c010b2009200a41306c2006103121090b2009450d052011200641306ead8421070b2009200541306c6a220641306a2006200a20056b41306c10e9061a200641286a201337030020062014370320200641186a200241a0016a41186a290300370300200641106a200241a0016a41106a290300370300200641086a200241a0016a41086a290300370300200620022903a001370300200742ffffffff0f832003428080808070838421074101210a0c030b41b8e3c300411d41f8b4ca001039000b200241c0006a41186a20024180016a41186a290300370300200241c0006a41106a20024180016a41106a290300370300200241c0006a41086a20024180016a41086a29030037030020022002290380013703404100210a0c010b419ae3c300411e41f8b4ca001039000b200241e0006a41186a220b4200370300200241e0006a41106a220d4200370300200241e0006a41086a220642003703002002420037036041bd98ca00ad428080808080028410012208290000210320024180016a41086a2205200841086a29000037030020022003370380012008102f20062005290300370300200220022903800137036041ebdec700ad4280808080f000841001220829000021032005200841086a29000037030020022003370380012008102f2004200229038001370000200441086a2005290300370000200241c0006a41086a2006290300370300200241c0006a41106a200d290300370300200241c0006a41186a200b29030037030020022002290360370340200241203602a4012002200241c0006a3602a00120092007422088a72205200241a0016a10ab0102400240200541306c22060d00410121040c010b200641306d220641ffffff3f712006470d02200641057422064100480d022006102d2204450d012006410576210c0b2007a7210d0240024020050d00410021080c010b200541306c210b4100210820042105200921060340200641086a2900002103200641106a29000021072006290000210f200541186a200641186a290000370000200541106a2007370000200541086a20033700002005200f370000200841016a2108200541206a2105200641306a2106200b41506a220b0d000b0b0240200d450d002009102f0b200241a0016a41186a200141186a290000370300200241a0016a41106a200141106a290000370300200241a0016a41086a200141086a290000370300200220012900003703a001200241a0016a4101200420081098052000200a3a0001200041003a0000200041026a200229018001370100200041086a20024186016a290100370100200c450d032004102f0c030b1036000b1038000b200041013a00002000410c6a4109360200200041086a41d1d5c700360200200041066a410d3a0000200041046a41831a3b01002003a7450d002009102f0b200241c0016a24000b13002000410e36020420004184c4c7003602000bcf0601087f230041106b22022400200241003602082002420137030020002802002103024002404104102d2204450d0020024284808080c00037020420022004360200200420033600002000280204210320044104410810312204450d00200242888080808001370204200420033600042002200436020020002802082104200041106a28020022032002106902402003450d00200341057421052002280204210620022802082103034002400240200620036b4120490d00200341206a2107200228020021080c010b200341206a22072003490d04200641017422082007200820074b1b22094100480d040240024020060d002009102d21080c010b200228020020062009103121080b2008450d032002200936020420022008360200200921060b200820036a220341086a200441086a290000370000200341106a200441106a290000370000200341186a200441186a290000370000200220073602082003200429000037000020072103200441206a2104200541606a22050d000b0b200028021421042000411c6a2802002203200210690240024020030d0020022802042108200228020821030c010b200341057421054100200228020822036b210620022802042108034002400240200820066a4120490d00200228020021070c010b200341206a22072003490d04200841017422092007200920074b1b22094100480d040240024020080d002009102d21070c010b200228020020082009103121070b2007450d032002200936020420022007360200200921080b200720036a220741086a200441086a290000370000200741106a200441106a290000370000200741186a200441186a2900003700002002200341206a220336020820072004290000370000200641606a2106200441206a2104200541606a22050d000b0b2000280220210702400240200820036b4104490d00200228020021040c010b200341046a22042003490d02200841017422062004200620044b1b22064100480d020240024020080d002006102d21040c010b200228020020082006103121040b2004450d012002200636020420022004360200200621080b200420036a20073600002001290200200341046aad4220862004ad84100402402008450d002004102f0b200241106a24000f0b1036000b1038000b1300200041093602042000418cdfc7003602000b3400200041e796c80036020420004100360200200041146a4103360200200041106a41f096c800360200200041086a42083702000b130020004105360204200041a49dc8003602000b3400200041dfcbc70036020420004100360200200041146a4106360200200041106a41dcafc800360200200041086a42133702000b3400200041f2cbc70036020420004100360200200041146a4106360200200041106a41dcafc800360200200041086a42133702000bcf0601087f230041106b22022400200241003602082002420137030020002802002103024002404104102d2204450d0020024284808080c00037020420022004360200200420033600002000280204210320044104410810312204450d00200242888080808001370204200420033600042002200436020020002802082104200041106a28020022032002106902402003450d00200341057421052002280204210620022802082103034002400240200620036b4120490d00200341206a2107200228020021080c010b200341206a22072003490d04200641017422082007200820074b1b22094100480d040240024020060d002009102d21080c010b200228020020062009103121080b2008450d032002200936020420022008360200200921060b200820036a220341086a200441086a290000370000200341106a200441106a290000370000200341186a200441186a290000370000200220073602082003200429000037000020072103200441206a2104200541606a22050d000b0b200028021421042000411c6a2802002203200210690240024020030d0020022802042108200228020821030c010b200341057421054100200228020822036b210620022802042108034002400240200820066a4120490d00200228020021070c010b200341206a22072003490d04200841017422092007200920074b1b22094100480d040240024020080d002009102d21070c010b200228020020082009103121070b2007450d032002200936020420022007360200200921080b200720036a220741086a200441086a290000370000200741106a200441106a290000370000200741186a200441186a2900003700002002200341206a220336020820072004290000370000200641606a2106200441206a2104200541606a22050d000b0b2000280220210702400240200820036b4104490d00200228020021040c010b200341046a22042003490d02200841017422062004200620044b1b22064100480d020240024020080d002006102d21040c010b200228020020082006103121040b2004450d012002200636020420022004360200200621080b200420036a20073600002001290200200341046aad4220862004ad84100402402008450d002004102f0b200241106a24000f0b1036000b1038000bdd0303037f027e047f230041106b22022400200241003602082002420137030020002802102103024002404104102d2204450d0020024284808080c0003702042002200436020020042003360000200041086a29030021052000290300210620044104411410312204450d00200420063700042004410c6a200537000020024294808080c00237020420022004360200200028021421042000411c6a2802002200200210690240024020000d002002280208210720022802042108200228020021090c010b2000410574210a200228020021092002280204210320022802082100034002400240200320006b4120490d00200041206a2107200321080c010b200041206a22072000490d04200341017422082007200820074b1b22084100480d040240024020030d002008102d21090c010b200920032008103121090b2009450d030b200920006a22002004290000370000200041186a200441186a290000370000200041106a200441106a290000370000200041086a200441086a2900003700002008210320072100200441206a2104200a41606a220a0d000b2002200836020420022007360208200220093602000b20012902002007ad4220862009ad84100402402008450d002009102f0b200241106a24000f0b1036000b1038000bdb0403027f037e027f230041e0006b2202240041e796c800ad4280808080800184100122032900002104200241306a41086a200341086a290000370300200220043703302003102f41d49ac800ad4280808080d00084100122032900002104200241086a41086a200341086a290000370300200220043703082003102f02404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100322012900002104200141086a2900002105200141106a2900002106200241c0006a41186a2207200141186a290000370300200241c0006a41106a22082006370300200241c0006a41086a2005370300200220043703402001102f2003102f41c000102d2203450d00200320022903303700002003200229030837001020032002290340370020200341086a200241306a41086a290300370000200341186a200241086a41086a290300370000200341286a200241c0006a41086a2201290300370000200341306a2008290300370000200341386a2007290300370000200241086a200341c00010ad022001200241086a41096a2900003703002008200241086a41116a2900003703002007200241086a41196a290000370300200220022900093703400240024020022d00084101460d00200041003a00000c010b200041013a000020002002290340370001200041096a2001290300370000200041116a200241d0006a290300370000200041196a200241d8006a2903003700000b2003102f200241e0006a24000f0b1036000b8b0503027f017e047f230041d0006b2202240041e796c800ad4280808080800184100122032900002104200241086a200341086a290000370300200220043703002003102f41d899c800ad4280808080800284100122032900002104200241106a41086a200341086a290000370300200220043703102003102f024002404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad4280808080800484100622012900003703302001102f200241c4006a200341206a360200200241003a0048200220033602402002200241306a41086a36023c2002200241306a360238200241206a200241386a106c2003102f02400240024002402002280228220541206a2201417f4c0d0020022802202106024002402001450d002001102d2203450d062001410f4d0d01200121070c050b411021074110102d21030c030b200141017422084110200841104b1b220741004e0d010c050b103d000b200320012007103121030b2003450d010b20032002290300370000200341086a200241086a2903003700000240024020074170714110460d00200721080c010b200741017422084120200841204b1b22084100480d0220032007200810312203450d010b20032002290310370010200341186a200241106a41086a29030037000002400240200841606a2005490d00200821070c010b2005415f4b0d02200841017422072001200720014b1b22074100480d0220032008200710312203450d010b200341206a2006200510e8061a20002001360208200020073602042000200336020002402002280224450d002006102f0b200241d0006a24000f0b1036000b1038000bc60403027f037e047f230041d0006b2202240041e796c800ad4280808080800184100122032900002104200241286a41086a200341086a290000370300200220043703282003102f41f898c800ad4280808080b00184100122032900002104200241386a41086a200341086a290000370300200220043703382003102f02404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100322012900002104200141086a2900002105200141106a2900002106200241186a2207200141186a290000370300200241106a22082006370300200241086a2005370300200220043703002001102f2003102f41c000102d2203450d00200320022903283700002003200229033837001020032002290300370020200341086a200241286a41086a2201290300370000200341186a200241386a41086a2209290300370000200341286a200241086a220a290300370000200341306a2008290300370000200341386a200729030037000020022003109b052009200a290300370300200241386a41106a20082802003602002001200241206a2903003703002002200229030037033820022002290318370328024020022802142208450d002000200229033837030020002002290328370318200041106a200241386a41106a280200360200200041086a2009290300370300200041206a20012903003703000b200020083602142003102f200241d0006a24000f0b1036000b860401057f230041d0006b22032400200341206a200110c005024002404120102d2201450d0020012002290000370000200141186a200241186a290000370000200141106a200241106a290000370000200141086a200241086a29000037000020032001ad4280808080800484100622022900003703482002102f2003410c6a200141206a360200200341003a0010200320013602082003200341c8006a41086a3602042003200341c8006a360200200341306a2003106c2001102f200328023021040240024020032802242205200328022822026b20032802382206490d00200328022021010c010b200220066a22012002490d02200541017422072001200720014b1b22074100480d020240024020050d002007102d21010c010b200328022020052007103121010b2001450d012003200736022420032001360220200721050b2003200220066a2207360228200120026a2004200610e8061a02402003280234450d002004102f0b200320012007109e05200341306a41106a2206200341106a280200360200200341306a41086a2204200341086a29030037030020032003290300370330024020032802142202450d002000200329033037030020002003290318370318200041086a2004290300370300200041106a20062802003602000b2000200236021402402005450d002001102f0b200341d0006a24000f0b1036000b1038000b130020004110360204200041acb4c8003602000ba20403027f037e027f230041d0006b2202240041dfcbc700ad4280808080b00284100122032900002104200241286a41086a200341086a290000370300200220043703282003102f41f2dec700ad4280808080e00084100122032900002104200241386a41086a200341086a290000370300200220043703382003102f02404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100322012900002104200141086a2900002105200141106a2900002106200241186a2207200141186a290000370300200241106a22082006370300200241086a2005370300200220043703002001102f2003102f41c000102d2203450d00200320022903283700002003200229033837001020032002290300370020200341086a200241286a41086a290300370000200341186a200241386a41086a2201290300370000200341286a200241086a290300370000200341306a2008290300370000200341386a20072903003700002002200310a1052001200241146a290200370300200241386a41106a2002411c6a2902003703002002200229020c370338024020022802082207450d00200020022903003702002000200229033837020c200041146a20012903003702002000411c6a200241c8006a2903003702000b200020073602082003102f200241d0006a24000f0b1036000ba81509017f017e027f027e057f027e017f017e087f230041b0076b2204240002400240024002400240024020000d0041dfcbc700ad4280808080b00284100122002900002105200441b0026a41086a200041086a290000370300200420053703b0022000102f41f0abc800ad4280808080a00184100122002900002105200441c0026a41086a200041086a290000370300200420053703c0022000102f4120102d2200450d0220002003290000370000200041186a200341186a2201290000370000200041106a200341106a2206290000370000200041086a200341086a2900003700002000ad4280808080800484100322072900002105200741086a2900002108200741106a290000210920044180056a41186a220a200741186a29000037030020044180056a41106a220b200937030020044180056a41086a200837030020042005370380052007102f2000102f41c000102d2200450d02200020042903b002370000200020042903c0023700102000200429038005370020200041086a200441b0026a41086a290300370000200041186a200441c0026a41086a290300370000200041286a20044180056a41086a290300370000200041306a200b290300370000200041386a200a2903003700002000ad428080808080088410052000102f200441dd026a200341086a290000370000200441e5026a2006290000370000200441ed026a2001290000370000200441033a00d402200441083a00d002200420032900003700d50241c8e1ca004100200441d0026a108c010c010b200441e5026a200341106a2207290000370000200441ed026a200341186a2206290000370000200441083a00d002200441dd026a200341086a220a290000370000200441023a00d402200420032900003700d50241c8e1ca004100200441d0026a108c0141dfcbc700ad4280808080b00284100122002900002105200441b0026a41086a200041086a290000370300200420053703b0022000102f41f0abc800ad4280808080a00184100122002900002105200441c0026a41086a200041086a290000370300200420053703c0022000102f4120102d2200450d0120002003290000370000200041186a2006290000370000200041106a2007290000370000200041086a200a2900003700002000ad4280808080800484100322072900002105200741086a2900002108200741106a290000210920044180056a41186a200741186a29000037030020044180056a41106a200937030020044180056a41086a200837030020042005370380052007102f2000102f41c000102d2200450d01200020042903b002370000200020042903c0023700102000200429038005370020200041086a200441b0026a41086a290300370000200041186a200441c0026a41086a290300370000200041286a20044180056a41086a220a290300370000200041306a20044180056a41106a290300370000200041386a20044180056a41186a290300370000200441d0026a200010a20520042802d002210620044180056a200441d0026a410472220b41ac0210e8061a02402006411b470d002000102f0c010b200420044180056a41ac0210e80621072000102f20022802042100200720063602d002200b200741ac0210e8061a2007418c056a2001360200200a2000360200200741003a008405200741023a008005200741c0026a200741d0026a20074180056a108b01200741f5026a20072d00c0024104463a0000200741dd026a200341086a290000370000200741e5026a200341106a290000370000200741ed026a200341186a290000370000200741043a00d402200741083a00d002200720032900003700d50241c8e1ca004100200741d0026a108c010b41dfcbc700ad4280808080b00284100122002900002105200441b0026a41086a200041086a290000370300200420053703b0022000102f41f2dec700ad4280808080e00084100122002900002105200441c0026a41086a200041086a290000370300200420053703c0022000102f4120102d2200450d0020002003290000370000200041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a2900003700002000ad4280808080800484100322072900002105200741086a2900002108200741106a290000210920044180056a41186a2201200741186a29000037030020044180056a41106a2206200937030020044180056a41086a200837030020042005370380052007102f2000102f41c000102d2200450d00200020042903b002370000200020042903c0023700102000200429038005370020200041086a200441b0026a41086a220c290300370000200041186a200441c0026a41086a220d290300370000200041286a20044180056a41086a220e290300370000200041306a2006290300370000200041386a20012903003700002000ad428080808080088410052000102f200441d0026a41186a4200370300200441d0026a41106a22074200370300200441d0026a41086a220b4200370300200442003703d00241dfcbc700ad4280808080b00284220f100122002900002105200b200041086a290000370300200420053703d0022000102f41e2dec700ad42808080809001842210100122002900002105200441086a220a200041086a290000370300200420053703002000102f200720042903002205370300200e200b290300370300200620053703002001200a290300370300200420042903d00237038005200441d0026a20044180056a412010aa0220042802d0022200410120001b211120042902d402420020001b2212422088a72206450d03410021072011210041002101034002400240024020032000460d0020002003412010ea06450d0020070d01410021070c020b200741016a21070c010b200120076b220a20064f0d03200441d0026a41186a2213200020074105746b220a41186a2214290000370300200441d0026a41106a2215200a41106a2216290000370300200b200a41086a22172900003703002004200a2900003703d002200041086a22182900002105200041106a22192900002108200041186a221a2900002109200a2000290000370000201420093700002016200837000020172005370000201a2013290300370000201920152903003700002018200b290300370000200020042903d0023700000b200041206a21002006200141016a2201460d030c000b0b1036000b4188bbca00200a2006103b000b2007417f6a20064f0d00200620076bad422086201242ffffffff0f838421120b20044180056a41186a420037030020044180056a41106a22074200370300200e42003703002004420037038005200f100122002900002105200c200041086a290000370300200420053703b0022000102f200e200c290300370300200420042903b002370380052010100122002900002105200d200041086a290000370300200420053703c0022000102f200720042903c0022205370300200b200e290300370300200441d0026a41106a2005370300200441d0026a41186a200d29030037030020042004290380053703d0020240024020110d00200441d0026aad428080808080048410050c010b20044120360284052004200441d0026a3602800520112012422088a720044180056a1083012012a7450d002011102f0b02402002410c6a280200450d002002280208102f0b0240200241186a280200450d002002280214102f0b200441b0076a24000ba20403027f037e027f230041d0006b2202240041f2cbc700ad4280808080b00284100122032900002104200241286a41086a200341086a290000370300200220043703282003102f41f2dec700ad4280808080e00084100122032900002104200241386a41086a200341086a290000370300200220043703382003102f02404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100322012900002104200141086a2900002105200141106a2900002106200241186a2207200141186a290000370300200241106a22082006370300200241086a2005370300200220043703002001102f2003102f41c000102d2203450d00200320022903283700002003200229033837001020032002290300370020200341086a200241286a41086a290300370000200341186a200241386a41086a2201290300370000200341286a200241086a290300370000200341306a2008290300370000200341386a20072903003700002002200310a1052001200241146a290200370300200241386a41106a2002411c6a2902003703002002200229020c370338024020022802082207450d00200020022903003702002000200229033837020c200041146a20012903003702002000411c6a200241c8006a2903003702000b200020073602082003102f200241d0006a24000f0b1036000ba81509017f017e027f027e057f027e017f017e087f230041b0076b2204240002400240024002400240024020000d0041f2cbc700ad4280808080b00284100122002900002105200441b0026a41086a200041086a290000370300200420053703b0022000102f41f0abc800ad4280808080a00184100122002900002105200441c0026a41086a200041086a290000370300200420053703c0022000102f4120102d2200450d0220002003290000370000200041186a200341186a2201290000370000200041106a200341106a2206290000370000200041086a200341086a2900003700002000ad4280808080800484100322072900002105200741086a2900002108200741106a290000210920044180056a41186a220a200741186a29000037030020044180056a41106a220b200937030020044180056a41086a200837030020042005370380052007102f2000102f41c000102d2200450d02200020042903b002370000200020042903c0023700102000200429038005370020200041086a200441b0026a41086a290300370000200041186a200441c0026a41086a290300370000200041286a20044180056a41086a290300370000200041306a200b290300370000200041386a200a2903003700002000ad428080808080088410052000102f200441dd026a200341086a290000370000200441e5026a2006290000370000200441ed026a2001290000370000200441033a00d402200441073a00d002200420032900003700d50241c8e1ca004100200441d0026a108c010c010b200441dd026a200341086a2207290000370000200441e5026a200341106a2206290000370000200441ed026a200341186a220a290000370000200441023a00d402200441073a00d002200420032900003700d50241c8e1ca004100200441d0026a108c0141f2cbc700ad4280808080b00284100122002900002105200441b0026a41086a200041086a290000370300200420053703b0022000102f41f0abc800ad4280808080a00184100122002900002105200441c0026a41086a200041086a290000370300200420053703c0022000102f4120102d2200450d0120002003290000370000200041186a200a290000370000200041106a2006290000370000200041086a20072900003700002000ad4280808080800484100322072900002105200741086a2900002108200741106a290000210920044180056a41186a200741186a29000037030020044180056a41106a200937030020044180056a41086a200837030020042005370380052007102f2000102f41c000102d2200450d01200020042903b002370000200020042903c0023700102000200429038005370020200041086a200441b0026a41086a290300370000200041186a200441c0026a41086a290300370000200041286a20044180056a41086a220a290300370000200041306a20044180056a41106a290300370000200041386a20044180056a41186a290300370000200441d0026a200010a20520042802d002210620044180056a200441d0026a410472220b41ac0210e8061a02402006411b470d002000102f0c010b200420044180056a41ac0210e80621072000102f20022802042100200720063602d002200b200741ac0210e8061a2007418c056a2001360200200a2000360200200741003a008405200741013a008005200741c0026a200741d0026a20074180056a108b01200741f5026a20072d00c0024104463a0000200741dd026a200341086a290000370000200741e5026a200341106a290000370000200741ed026a200341186a290000370000200741043a00d402200741073a00d002200720032900003700d50241c8e1ca004100200741d0026a108c010b41f2cbc700ad4280808080b00284100122002900002105200441b0026a41086a200041086a290000370300200420053703b0022000102f41f2dec700ad4280808080e00084100122002900002105200441c0026a41086a200041086a290000370300200420053703c0022000102f4120102d2200450d0020002003290000370000200041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a2900003700002000ad4280808080800484100322072900002105200741086a2900002108200741106a290000210920044180056a41186a2201200741186a29000037030020044180056a41106a2206200937030020044180056a41086a200837030020042005370380052007102f2000102f41c000102d2200450d00200020042903b002370000200020042903c0023700102000200429038005370020200041086a200441b0026a41086a220c290300370000200041186a200441c0026a41086a220d290300370000200041286a20044180056a41086a220e290300370000200041306a2006290300370000200041386a20012903003700002000ad428080808080088410052000102f200441d0026a41186a4200370300200441d0026a41106a22074200370300200441d0026a41086a220b4200370300200442003703d00241f2cbc700ad4280808080b00284220f100122002900002105200b200041086a290000370300200420053703d0022000102f41e2dec700ad42808080809001842210100122002900002105200441086a220a200041086a290000370300200420053703002000102f200720042903002205370300200e200b290300370300200620053703002001200a290300370300200420042903d00237038005200441d0026a20044180056a412010aa0220042802d0022200410120001b211120042902d402420020001b2212422088a72206450d03410021072011210041002101034002400240024020032000460d0020002003412010ea06450d0020070d01410021070c020b200741016a21070c010b200120076b220a20064f0d03200441d0026a41186a2213200020074105746b220a41186a2214290000370300200441d0026a41106a2215200a41106a2216290000370300200b200a41086a22172900003703002004200a2900003703d002200041086a22182900002105200041106a22192900002108200041186a221a2900002109200a2000290000370000201420093700002016200837000020172005370000201a2013290300370000201920152903003700002018200b290300370000200020042903d0023700000b200041206a21002006200141016a2201460d030c000b0b1036000b4188bbca00200a2006103b000b2007417f6a20064f0d00200620076bad422086201242ffffffff0f838421120b20044180056a41186a420037030020044180056a41106a22074200370300200e42003703002004420037038005200f100122002900002105200c200041086a290000370300200420053703b0022000102f200e200c290300370300200420042903b002370380052010100122002900002105200d200041086a290000370300200420053703c0022000102f200720042903c0022205370300200b200e290300370300200441d0026a41106a2005370300200441d0026a41186a200d29030037030020042004290380053703d0020240024020110d00200441d0026aad428080808080048410050c010b20044120360284052004200441d0026a3602800520112012422088a720044180056a1083012012a7450d002011102f0b02402002410c6a280200450d002002280208102f0b0240200241186a280200450d002002280214102f0b200441b0076a24000b130020004107360204200041dcbec8003602000bdb0901097f230041e0006b22022400200241386a4100280288a943360200200241306a4100290280a943370300200241286a41002902f8a843370300200241206a41002902f0a843370300200241186a41002902e8a843370300200241106a41002902e0a843370300200241086a41002902d8a843370300200241002902d0a8433703002002410036024820024201370340200241d0006a200210ca0520022802502103024002400240024020022802442204200228024822056b20022802582206490d00410121040c010b200520066a22072005490d02200441017422082007200820074b1b22074100480d020240024020040d002007102d21040c010b410120042007103121040b2004450d0120022007360244200220043602400b2002200520066a360248200420056a2003200610e8061a02402002280254450d002003102f0b200241d0006a200241106a10ca05200228025021080240024020022802442205200228024822036b20022802582207490d00200521060c010b200320076a22062003490d02200541017422092006200920064b1b22064100480d020240024020050d002006102d21040c010b200420052006103121040b2004450d0120022006360244200220043602400b2002200320076a2205360248200420036a2008200710e8061a02402002280254450d002008102f0b02400240200620056b4104490d00200541046a21030c010b200541046a22032005490d02200641017422072003200720034b1b22074100480d020240024020060d002007102d21040c010b200420062007103121040b2004450d0120022007360244200220043602400b20022003360248200420056a410a3600000240024020022802442204200228024822056b4104490d00200228024021040c010b200541046a22062005490d02200441017422032006200320064b1b22064100480d020240024020040d002006102d21040c010b200228024020042006103121040b2004450d0120022006360244200220043602400b2002200541046a360248200420056a41e701360000024020022802442206200228024822056b41034b0d00200541046a22032005490d02200641017422072003200720034b1b22034100480d020240024020060d002003102d21040c010b200420062003103121040b2004450d0120022003360244200220043602400b2002200541046a360248200420056a4100360000200241306a2802002107410c200241c0006a106920074190016a21092002280244210620022802482103034002400240200620036b4108490d00200341086a2104200228024021050c010b200341086a22042003490d03200641017422052004200520044b1b22084100480d030240024020060d002008102d21050c010b200228024020062008103121050b2005450d022002200836024420022005360240200821060b20022004360248200520036a2007290000370000200741086a28020021080240200620046b41034b0d00200441046a22032004490d032006410174220a2003200a20034b1b22034100480d030240024020060d002003102d21050c010b200520062003103121050b2005450d022002200336024420022005360240200321060b2002200441046a2203360248200520046a20083600002007410c6a22072009470d000b200241e0006a24002003ad4220862005ad840f0b1036000b1038000bf90301067f20012802042102024002400240024020012802004101470d002001410c6a280200220141046a2203417f4c0d01024002400240024002400240024002402003450d002003102d2204450d0a200141c000490d04200141808001490d052001418080808004490d06200441033a00002003417f6a41034d0d01200321050c030b410121034101102d2204450d09200441033a0000410521050c010b200341017422064105200641054b1b22054100480d090b20042003200510312204450d070b20042001360001410521060c030b200420014102743a000041012106200321050c020b02400240200341014d0d00200321050c010b20042003200341017422064102200641024b1b220510312204450d050b41022106200420014102744101723b00000c010b02400240200341034d0d00200321050c010b200341017422064104200641044b1b22054100480d0520042003200510312204450d040b20042001410274410272360000410421060b02400240200520066b2001490d00200521030c010b200620016a22032006490d04200541017422072003200720034b1b22034100480d0420042005200310312204450d030b200420066a2002200110e8061a2000200620016a36020820002003360204200020043602000f0b20002002200141086a28020010d4050f0b103d000b1036000b1038000be11b04027f017e087f017e230041a00e6b22022400024002402001450d00200220003602300c010b200241c8e1ca003602300b20022001360234200241c00a6a200241306a10f10402400240024020022802c40a450d00200241386a200241c00a6a41fc0010e8061a200241b8016a200241386a41fc0010e8061a200241b8016a10b903024020022802b8012201450d00200241c00a6a2001417f6a10fa02200241c00a6a200241c8016a412010ea060d0002400240200241b0026a28020022010d004104210341002101410021000c010b024002402001ad420c7e2204422088a70d002004a722054100480d0020022802a80221002005102d22030d011036000b1038000b200141c8036c210620014103742107200321010340200220003602e806200241c00a6a200241e8066a10a903200141086a200241c00a6a41086a280200360200200120022903c00a3702002001410c6a2101200041c8036a2100200641b87c6a22060d000b2005410c6e2101200741786a41037641016a21000b200220003602f006200220013602ec06200220033602e806200241c00a6a200241e8066a10cc05024020024188026a2201200241c00a6a412010ea06450d0041cccbca00ad4280808080e0018410082001ad42808080808004841020200241c00a6aad428080808080048410200b02402001200241c00a6a412010ea060d00200241ac026a280200210720022802a802210520022802b0022106200241b8026a200241b8016a41f00010e8061a2005200641c8036c6a210020022802b8022108200521010240024002402006450d00200241e8066a41f0006a2103200521010240034020024180066a200141e80010e8061a200141e8006a2903002104200241a8036a200141f0006a41d80210e8061a20044203510d01200241e8066a20024180066a41e80010e8061a200220043703d0072003200241a8036a41d80210e8061a2002200241e8066a3602b00a200241c00a6a200241b00a6a10a90320022802c80a2106024020022802c40a450d0020022802c00a102f0b200241c00a6a200241e8066a41c80310e8061a200241003602880e200241b00a6a200241c00a6a2006200241880e6a10d00320022d00b00a4101460d04200141c8036a22012000470d000c030b0b200141c8036a21010b20002001460d00034020014198016a108d012000200141c8036a2201470d000b0b02402007450d002005102f0b200241206a4180e5c3004110109501200228022421050240200228022022074101470d004180e5c300ad428080808080028410050b200241c00a6a41186a22094200370300200241c00a6a41106a22004200370300200241c00a6a41086a22014200370300200242003703c00a418de6c300ad4280808080e000841001220629000021042001200641086a290000370300200220043703c00a2006102f41bc80c400ad4280808080e00184100122032900002104200241a8036a41086a2206200341086a290000370300200220043703a8032003102f200020022903a8032204370300200241e8066a41086a220a2001290300370300200241e8066a41106a220b2004370300200241e8066a41186a220c2006290300370300200220022903c00a3703e80620022005410020071b3602c00a200241e8066aad42808080808004842204200241c00a6aad4280808080c000841004200942003703002000420037030020014200370300200242003703c00a41aa97ca00ad428080808080018410012203290000210d2001200341086a2900003703002002200d3703c00a2003102f41b297ca00ad428080808080018410012203290000210d2006200341086a2900003703002002200d3703a8032003102f200020022903a803220d370300200a2001290300370300200b200d370300200c2006290300370300200220022903c00a3703e80620041005200810a904200241c00a6a109204200241186a200241b8026a410472220110d6032002200228021c22003602980e200241106a200241c00a6a410472220610d60320022002280214220336029c0e20002003470d05200241086a200110d603200228020821052002200610d60320022802042201200228020c2200200020014b1b2209450d042002280200210741002106418d85c700ad4280808080c002842104410021030340024002400240024002400240024002400240200520066a22012d00002208200720066a22002d0000470d0002400240024002400240024020080e06000102030405000b20052007460d0d200141016a200041016a412010ea060d050c060b024020052007460d00200141016a280000200041016a280000470d050b200141106a2802002208200041106a280200470d04200141086a280200220a200041086a280200220b460d0a200a200b200810ea060d040c0a0b024020052007460d00200141016a280000200041016a280000470d040b200141106a2802002208200041106a280200470d03200141086a280200220a200041086a280200220b460d08200a200b200810ea060d030c080b024020052007460d00200141016a280000200041016a280000470d030b200141106a2802002208200041106a280200470d02200141086a280200220a200041086a280200220b460d06200a200b200810ea060d020c060b200141046a2802002208200041046a280200470d012008450d04200141086a280200200041086a280200470d012001410c6a2802002000410c6a280200470d010c040b2001410c6a28020022082000410c6a280200470d00200141046a280200220a200041046a280200220b460d02200a200b200810ea06450d020b20041008200241e8066a200110ea0220023502f00642208620022802e8062208ad841020024020022802ec06450d002008102f0b200241e8066a200010ea0220023502f00642208620022802e8062208ad841020024020022802ec06450d002008102f0b20012d000020002d00002208470d06024020080e06000605040302000b20052007460d070b200141016a200041016a412010ea060d050c060b2001410c6a28020022082000410c6a280200470d04200141046a2802002201200041046a2802002200460d0520012000200810ea060d040c050b200141046a2802002208200041046a280200470d032008450d04200141086a280200200041086a280200470d032001410c6a2802002000410c6a280200460d040c030b024020052007460d00200141016a280000200041016a280000470d030b200141106a2802002208200041106a280200470d02200141086a2802002201200041086a2802002200460d0320012000200810ea060d020c030b024020052007460d00200141016a280000200041016a280000470d020b200141106a2802002208200041106a280200470d01200141086a2802002201200041086a2802002200460d0220012000200810ea060d010c020b024020052007460d00200141016a280000200041016a280000470d010b200141106a2802002208200041106a280200470d00200141086a2802002201200041086a2802002200460d0120012000200810ea06450d010b418cd1c300412741f8b4ca001039000b200641246a2106200341016a22032009490d000c050b0b200241286a20022f00b10a20022d00b30a4110747210d5032002280228200228022c41f8b4ca001039000b41e0d0c300412441f8b4ca001039000b41c4d0c300411c41f8b4ca001039000b200241b4036a4104360200200241fc066a4102360200200242023702ec06200241b8c2c8003602e806200241043602ac03200241b0c2c8003602a803200241003602bc01200241c8e1ca003602b8012002200241a8036a3602f8062002200241b8016a3602b003200241e8066a41c8c2c8001043000b0240200241b8026a41306a2201200241c00a6a41306a2200412010ea06450d0041cccbca00ad4280808080e0018410082001ad428080808080048410202000ad428080808080048410200b024020012000412010ea06450d0041b3d1c300412841f8b4ca001039000b0240200241c00a6a410c6a2802002200450d0020022802c40a2101200041246c210003400240024020012d0000220641044b0d0002400240024020060e050400010204040b2001410c6a280200450d03200141086a280200102f0c030b2001410c6a280200450d02200141086a280200102f0c020b2001410c6a280200450d01200141086a280200102f0c010b200141086a280200450d00200141046a280200102f0b200141246a21012000415c6a22000d000b0b0240200241c80a6a280200450d0020022802c40a102f0b0240200241b8026a410c6a2802002200450d0020022802bc022101200041246c210003400240024020012d0000220641044b0d0002400240024020060e050400010204040b2001410c6a280200450d03200141086a280200102f0c030b2001410c6a280200450d02200141086a280200102f0c020b2001410c6a280200450d01200141086a280200102f0c010b200141086a280200450d00200141046a280200102f0b200141246a21012000415c6a22000d000b0b0240200241c0026a280200450d0020022802bc02102f0b200241a00e6a240042010f0b200241a8036a41146a4109360200200241b4036a410a36020020024180066a41146a41033602002002200241980e6a3602880e20022002419c0e6a3602b00a200241e8066a41146a41003602002002420337028406200241b4e0ca00360280062002410a3602ac03200241c8e1ca003602f806200242013702ec0620024184d1c3003602e8062002200241a8036a360290062002200241e8066a3602b8032002200241b00a6a3602b0032002200241880e6a3602a80320024180066a41e8d8c9001043000bc504020b7f037e230041206b2202240002400240024020012802082203410c6c41046a2204417f4c0d00200128020021050240024020040d00410121060c010b2004102d2206450d020b2002410036020820022004360204200220063602002003200210690240024020030d002002280208210720022802042108200228020021090c010b20052003410c6c6a210a2005210603402006280200210b200641086a28020022042002106902400240200228020422082002280208220c6b2004490d00200228020021090c010b200c20046a2209200c490d05200841017422072009200720094b1b22074100480d050240024020080d002007102d21090c010b200228020020082007103121090b2009450d042002200736020420022009360200200721080b2002200c20046a22073602082009200c6a200b200410e8061a2006410c6a2206200a470d000b0b2007ad4220862009ad8410242204290000210d200441086a290000210e200441106a290000210f200241186a2206200441186a290000370300200241106a220c200f370300200241086a220b200e3703002002200d3703002004102f200041186a2006290300370000200041106a200c290300370000200041086a200b2903003700002000200229030037000002402008450d002009102f0b02402003450d002003410c6c21062005210403400240200441046a280200450d002004280200102f0b2004410c6a2104200641746a22060d000b0b0240200141046a280200450d002005102f0b200241206a24000f0b103d000b1036000b1038000ba60301027f23004180026b22022400024002402001450d00200220003602000c010b200241c8e1ca003602000b20022001360204200241f8006a200210f6030240200228027c450d00200241086a200241f8006a41f00010e8061a200241086a10b9030240200241086a410c6a2802002200450d00200228020c2101200041246c210003400240024020012d0000220341044b0d0002400240024020030e050400010204040b2001410c6a280200450d03200141086a280200102f0c030b2001410c6a280200450d02200141086a280200102f0c020b2001410c6a280200450d01200141086a280200102f0c010b200141086a280200450d00200141046a280200102f0b200141246a21012000415c6a22000d000b0b0240200241106a280200450d00200228020c102f0b20024180026a240042010f0b200241f4016a41043602002002411c6a41023602002002420237020c200241b8c2c800360208200241043602ec01200241c8c3c8003602e801200241003602fc01200241c8e1ca003602f8012002200241e8016a3602182002200241f8016a3602f001200241086a41c8c2c8001043000ba10202077f017e230041206b22022400200210a0030240024002402002280208220341046a2204417f4c0d00200228020021050240024020040d00410121060c010b2004102d2206450d020b2002410036021820022004360214200220063602102003200241106a10690240024020022802142206200228021822046b2003490d00200228021021060c010b200420036a22072004490d03200641017422082007200820074b1b22074100480d030240024020060d002007102d21060c010b200228021020062007103121060b2006450d0220022007360214200220063602100b200620046a2005200310e8061a200420036aad4220862006ad84210902402002280204450d002005102f0b200241206a240020090f0b103d000b1036000b1038000beb0602057f027e230041900b6b22022400024002402001450d00200220003602000c010b200241c8e1ca003602000b20022001360204200241b8076a200210a40402400240024020022903a0084203510d00200241186a200241b8076a41c80310e8061a200241e0036a200241186a41c80310e8061a2002200241e0036a3602b807200241a8076a200241b8076a10a90320022802b0072101200241b8076a200241e0036a41c80310e8061a200241880b6a20022802b007360200200220022903a8073703800b200241086a200241b8076a2001200241800b6a10d0034101410220022d000822034101461b2200102d2201450d01200241003602c007200220003602bc07200220013602b8070240024020034101470d00200141013a0000200241013602c007200241086a410172200241b8076a10a1030c010b200141003a0000200241023602c007024020022d000c22034104460d0041012104200141013a00010240024002400240024020030e0400010203000b410021040b200220043a00e003410221030c020b41022103200241023a00e003410221040c010b200241033a00e0034104210020014102410410312201450d04200141033a000220024284808080303702bc07200220013602b807200220022d000d22043a00e003024041010d0041000d0641034101742200410341016a2203200020034b1b22004100480d060240024041030d002000102d21010c010b200141032000103121010b2001450d05200220003602bc07200220013602b8070b2002410341016a22033602c007200141036a20043a0000200220022d000e22043a00e0030b024020002003470d0041000d0520004101742205200041016a2206200520064b1b22054100480d050240024020000d002005102d21010c010b200120002005103121010b2001450d04200220053602bc07200220013602b8070b2002200341016a3602c007200120036a20043a00000c010b200141003a00010b20023502c007210720023502b8072108200241900b6a240020082007422086840f0b200241246a4104360200200241f4036a4102360200200242023702e403200241b8c2c8003602e0032002410436021c200241e0c3c8003602182002410036020c200241c8e1ca003602082002200241186a3602f0032002200241086a360220200241e0036a41c8c2c8001043000b1036000b1038000ba21607067f017e017f027e067f017e067f23004180026b22022400200241186a4180e5c3004110109501200228021c21030240200228021822044101470d004180e5c300ad428080808080028410050b200241b0016a41186a22054200370300200241b0016a41106a22064200370300200241b0016a41086a22074200370300200242003703b001418de6c300ad4280808080e00084220810012209290000210a2007200941086a2900003703002002200a3703b0012009102f41bc80c400ad4280808080e00184220a10012209290000210b200241f0016a41086a220c200941086a2900003703002002200b3703f0012009102f200620022903f001220b37030020024190016a41086a220d200729030037030020024190016a41106a2209200b37030020024190016a41186a220e200c290300370300200220022903b001370390014100210f20022003410020041b36022020024190016aad4280808080800484220b200241206aad4280808080c000841004200241206a41186a22104200370300200241206a41106a22044200370300200241206a41086a221142003703002002420037032020081001220329000021122011200341086a290000370300200220123703202003102f419ce6c300ad4280808080e000841001220329000021122007200341086a290000370300200220123703b0012003102f200420022903b0012212370300200241d0016a41086a22132011290300370300200241d0016a41106a2012370300200241d0016a41186a22142007290300370300200220022903203703d001200241106a200241d0016a41201095012002280214210420022802102115200542003703002006420037030020074200370300200242003703b00141aa97ca00ad42808080808001841001220329000021122007200341086a290000370300200220123703b0012003102f41b297ca00ad4280808080800184100122032900002112200c200341086a290000370300200220123703f0012003102f200620022903f0012212370300200d200729030037030020092012370300200e200c290300370300200220022903b00137039001200b10052004410020151b10a904200542003703002006420037030020074200370300200242003703b0012008100122032900002112200c200341086a290000370300200220123703f0012003102f2007200c290300370300200220022903f0013703b001200a10012203290000210a200c200341086a2900003703002002200a3703f0012003102f200620022903f001220a370300200d20072903003703002009200a370300200e200c290300370300200220022903b00137039001200241086a20024190016a41201095010240024002400240200228020c410020022802081b22160d0041042117410021160c010b2016ad420c7e220a422088a70d01200aa722094100480d012009102d2217450d022009410c6e210f41002109201721030340200241d0016a200910d203200241206a20022802d001221520022802d8012218109302024020022802202204450d002018ad4220862015ad8410050b200941016a21092002290224420020041b210a2004410120041b2104024020022802d401450d002015102f0b20032004360200200341046a200a3702002003410c6a210320162009470d000b0b200220163602282002200f36022420022017360220200241d0016a200241206a10cc0520102014290300370300200241206a41106a2203200241d0016a41106a29030037030020112013290300370300200220022903d00137032020054200370300200241b0016a41106a2204420037030020074200370300200242003703b001200810012209290000210a200c200941086a2900003703002002200a3703f0012009102f2007200c290300370300200220022903f0013703b00141ace6c300ad4280808080e0018410012209290000210a200c200941086a2900003703002002200a3703f0012009102f200620022903f001370000200641086a200c290300370000200d200729030037030020024190016a41106a2004290300370300200e2005290300370300200220022903b001370390014120102d2209450d0120092002290320370000200941186a200241206a41186a2204290300370000200941106a2003290300370000200941086a200241206a41086a290300370000200b2009ad428080808080048410042009102f200241206a109204200241003602b801200242013703b0014120102d2209450d0120092002290330370000200941186a200241c8006a290300370000200941106a2215200241206a41206a290300370000200941086a20042903003700004120102d2203450d01200242a080808080043702b401200220033602b00120032009290000370000200341086a200941086a290000370000200341106a2015290000370000200341186a200941186a2900003700002009102f200241206a200241b0016a1095024120102d2209450d0120092002290350370000200941186a200241e8006a290300370000200941106a200241e0006a290300370000200941086a200241d8006a2903003700000240024020022802b401221520022802b80122186b4120490d00201841206a210320022802b00121040c010b201841206a22032018490d01201541017422042003200420034b1b22164100480d010240024020150d002016102d21040c010b20022802b00120152016103121040b2004450d02200220163602b401200220043602b001201621150b200420186a221841086a200941086a290000370000201841106a200941106a290000370000201841186a200941186a290000370000200220033602b801201820092900003700002009102f4120102d2209450d0120092002290370370000200941186a20024188016a290300370000200941106a20024180016a290300370000200941086a200241f8006a2903003700000240201520036b411f4b0d00200341206a22182003490d01201541017422162018201620184b1b22184100480d010240024020150d002018102d21040c010b200420152018103121040b2004450d02200220183602b401200220043602b0010b200420036a220441086a200941086a290000370000200441106a200941106a290000370000200441186a200941186a2900003700002002200341206a3602b801200420092900003700002009102f2002280224210d2002412c6a2802002205200241b0016a10690240024020050d0020022802b801210320022802b00121040c010b200541246c210c20022802b401211620022802b8012109200d21150340200241d0016a201510ea0220022802d001210702400240201620096b20022802d8012218490d00200920186a210320022802b00121040c010b200920186a22032009490d03201641017422042003200420034b1b22064100480d030240024020160d002006102d21040c010b20022802b00120162006103121040b2004450d04200220063602b401200220043602b001200621160b200220033602b801200420096a2007201810e8061a024020022802d401450d002007102f0b201541246a211520032109200c415c6a220c0d000b0b2003ad422086210a2004ad210802402005450d00200541246c2103200d210903400240024020092d0000220441044b0d0002400240024020040e050400010204040b2009410c6a280200450d03200941086a280200102f0c030b2009410c6a280200450d02200941086a280200102f0c020b2009410c6a280200450d01200941086a280200102f0c010b200941086a280200450d00200941046a280200102f0b200941246a21092003415c6a22030d000b0b200a200884210a0240200241286a280200450d00200d102f0b20024180026a2400200a0f0b1038000b1036000bcc2507017f017e017f017e0e7f027e087f23004180056b22022400024002402001450d00200220003602200c010b200241c8e1ca003602200b20022001360224200241186a200241206a10e601024020022802180d00200228021c21012002200241206a3602e802200241003a00e004200242003702d40320024190bdc6003602d0032002200136023c200241003602382002200241e0046a3602442002200241e8026a360240200241386a200241d0036a10ee0420022802d003210120022902d4032103024020022d00e004450d0020012003a72003422088a710e4010c010b2001450d002002200337022c20022001360228200241386a200241286a10d205024002400240024002400240024020022802384101460d00200241386a41086a22012903002103200241386a41186a4200370300200241386a41106a22044200370300200142003703002002420037033841d5a2ca00ad42808080809001841001220029000021052001200041086a290000370300200220053703382000102f41ecb0c000ad42808080803084100122002900002105200241e8026a41086a2206200041086a290000370300200220053703e8022000102f200420022903e8022205370300200241d0036a41086a2001290300370300200241d0036a41106a2005370300200241d0036a41186a2006290300370300200220022903383703d003200241086a200241d0036a10e301200229031021052002280208210141c803102d2207450d042007200241d0036a41e80010e806220842023703682008410336029801200820022903e802370370200841f8006a200629030037030020084180016a200241e8026a41106a29030037030020084188016a200241e8026a41186a29030037030020084190016a20024188036a29030037030020082003200542dc0b7c42dc0b20011b220520032005561b3703a001200841a8016a200241386a41a00210e8061a200241286a2101200228022c21090240024003404100210a4100210602402001280200220b2f0106220c450d00200c4103742101200b41e8006a2104200b41086a2100417f21060340024020010d00200c21060c020b41feb2c0002000410810ea06220d450d03200141786a21012004410c6a2104200641016a2106200041086a2100200d417f4a0d000b0b024020090d0042002103420021050c030b2009417f6a2109200b20064102746a41e4016a21010c000b0b200441786a2802002101200220042802003602d403200220013602d003200241386a200241d0036a109a032002280238220a450d03200241c0006a3502004220862103200235023c21050b200a4104200a1b210e20052003844200200a1b2203a7210f02402003422088a7220b450d00200241d8026a10f80220022802d802210d20022802dc02211002400240024020022802e002220c450d00200d200c41c4006c22016a2104200141bc7f6a2106200d2101034020012d00002100200241386a200141016a41c30010e8061a20004102460d01200241d0036a41186a200241386a41186a290000370300200241d0036a41106a200241386a41106a290000370300200241d0036a41086a200241386a41086a290000370300200220022900383703d00320004101460d02200641bc7f6a2106200141c4006a22012004470d000b0b410021114101210902402010450d00200d102f0b410021120c010b200241e8026a41086a2200200241d0036a41086a290300370300200241e8026a41106a220a200241d0036a41106a290300370300200241e8026a41186a2213200241d0036a41186a290300370300200220022903d00322033703c004200220033703e8024120102d2209450d06200920022903e802370000200941186a2013290300370000200941106a200a290300370000200941086a20002903003700000240024020060d0041012112410121110c010b200141c4006a2100200c41c4006c200d6a41bc7f6a21134101211241012111034020002101034020012d00002100200241386a200141016a41c30010e8061a20004102460d02200241d0036a41186a2206200241386a41186a290000370300200241d0036a41106a220c200241386a41106a290000370300200241d0036a41086a220a200241386a41086a290000370300200220022900383703d003024020004101460d00200141c4006a22012004470d010c030b0b200241e8026a41086a200a2903002203370300200241e8026a41106a200c2903002205370300200241e8026a41186a20062903002214370300200220022903d00322153703e802200241c0046a41186a220c2014370300200241c0046a41106a220a2005370300200241c0046a41086a22162003370300200220153703c004024020112012470d00201241016a22002012490d0b201241017422062000200620004b1b220041ffffff3f712000470d0b200041057422004100480d0b0240024020120d002000102d21090c010b200920124105742000103121090b2009450d09200041057621110b200141c4006a2100200920124105746a220620022903c004370000200641186a200c290300370000200641106a200a290300370000200641086a2016290300370000201241016a211220132001470d000b0b2010450d00200d102f0b200e200b41f0006c6a2116200241d0036a41106a2117200241386a41106a210d200241d0036a41086a21184200210541042119200e210403402004280204210b20042802002106200241386a200441086a41e80010e8061a200441f0006a21040240200b0d00201121060c040b200241e8026a200241386a41e80010e8061a2002200b3602d403200220063602d0032018200241e8026a41e80010e8061a200241386a41186a221a4200370300200d4200370300200241386a41086a220c420037030020024200370338418de6c300ad4280808080e00084100122012900002103200c200141086a290000370300200220033703382001102f419ce6c300ad4280808080e00084100122012900002103200241c0046a41086a2200200141086a290000370300200220033703c0042001102f200d20022903c004370000200d41086a2000290300370000200241e0046a41086a221b200c290300370300200241e0046a41106a221c200d290300370300200241e0046a41186a221d201a290300370300200220022903383703e0042002200241e0046a41201095012002280200210120022802042100200241e0046a200241d0036a10f902024002402006417f6a220a2000410020011b22014f0d00200241386a200a10fa02200241386a2017412010ea060d00200641002001417b6a2200200020014b1b490d0020124105742110200241e0046a20096b21134100210102400340024020102001470d004100210a0c020b4101210a20132001460d01200920016a2100200141206a21012000200241e0046a412010ea060d000b0b200241386a200610fa02200241386a200241e0046a412010ea062101200a0d002001450d00200241e0046a200241d0036a10f902200241386a200241d0036a41f00010e8061a0240024020054220882203a722012005a7460d00200121000c010b200141016a22062001490d0b2003a72200410174220b20062006200b491bad42f0007e2203422088a70d0b2003a722064100480d0b0240024020010d002006102d21190c010b2019200141f0006c2006103121190b2019450d09200641f0006ead21050b2019200041f0006c6a200241386a41f00010e8061a201a201d290300370300200d201c290300370300200c201b290300370300200220022903e0043703380240024020122011460d0020112106201221110c010b201141016a22012011490d0b201141017422062001200620014b1b220141ffffff3f712001470d0b200141057422014100480d0b0240024020110d002001102d21090c010b200920114105742001103121090b2009450d09200141057621060b200542ffffffff0f83200041016a2200ad422086842105200920114105746a22012002290338370000200141186a201a290300370000200141106a200d290300370000200141086a200c2903003700002000410a460d05201141016a2112200621110c010b024020022802dc032201450d00200141246c2100200b210103400240024020012d0000220641044b0d0002400240024020060e050400010204040b2001410c6a280200450d03200141086a280200102f0c030b2001410c6a280200450d02200141086a280200102f0c020b2001410c6a280200450d01200141086a280200102f0c010b200141086a280200450d00200141046a280200102f0b200141246a21012000415c6a22000d000b0b20022802d803450d00200b102f0b20042016470d000b20112106201621040c020b4101210c200f450d03200e102f0c030b200241d8036a200241c4006a2902003703002002200229023c3703d003418aeec0004128200241d0036a41b4eec00041c4eec000103e000b024020162004460d000340200441046a2200109701200441f0006a21010240200441086a280200450d002000280200102f0b2001210420162001470d000b0b0240200f450d00200e102f0b02402006450d002009102f0b0240200542ffffffff0f560d004101210c2005a7450d022019102f0c020b2019450d00200841c80341900710312207450d02200741c8036a200241d0036a41e80010e8061a200742023703b004200720053703e804200720193602e404200741043602e004200720022903e8023703b804200741c0046a200241f0026a290300370300200741c8046a200241f8026a290300370300200741d0046a20024180036a290300370300200741d8046a20024188036a290300370300200741f0046a200241386a41a00210e8061a4102210c0c010b4101210c0b200241286a2101200228022c210b02400240024002400340024002402001280200220d2f010622090d00410021060c010b20094103742101200d41086a2100417f21060340024020010d00200921060c020b200641016a210641a9b4c0002000410810ea062204450d03200141786a2101200041086a21002004417f4a0d000b0b200b450d02200b417f6a210b200d20064102746a41e4016a21010c000b0b200d41e0006a2006410c6c6a22012802084104490d002001280200280000210d200241d0036a41186a4200370300200241d0036a41106a22064200370300200241d0036a41086a22014200370300200242003703d00341d5a2ca00ad42808080809001841001220029000021032001200041086a290000370300200220033703d0032000102f41f4c8c300ad4280808080b00184100122002900002103200241c0046a41086a2204200041086a290000370300200220033703c0042000102f200620022903c0042203370300200241e8026a41086a2001290300370300200241e8026a41106a2003370300200241e8026a41186a2004290300370300200220022903d0033703e802200241386a200241e8026a10fe0320022802382201410420011b2106410021000240200229023c420020011b2203422088a72201417f6a220420014b0d00200420014f0d00200620044102746a2201450d002001280200200d4721000b02402003a7450d002006102f0b20000d010b200c21100c010b2007200c41c8036c2201200c4101742200200c41016a2210200020104b1b41c8036c10312207450d01200720016a200241d0036a41e80010e80622014202370368200120022903e802370370200141f8006a200241f0026a29030037030020014180016a200241f8026a29030037030020014188016a20024180036a29030037030020014190016a20024188036a2903003703002001419c016a200d3602002001410e36029801200141a8016a200241386a41a00210e8061a0b2002280228200228022c200228023010e401201041c8036c220c4104722201417f4c0d012001102d2200450d00200241003602d803200220013602d403200220003602d0032010200241d0036a106920022802d403210b20022802d8032101200721060340200220063602e802200241386a200241e8026a10a9032002280238210902400240200b20016b2002280240220d490d002001200d6a210020022802d00321040c010b2001200d6a22002001490d04200b41017422042000200420004b1b220a4100480d0402400240200b0d00200a102d21040c010b20022802d003200b200a103121040b2004450d022002200a3602d403200220043602d003200a210b0b200220003602d803200420016a2009200d10e8061a0240200228023c450d002009102f0b200641c8036a210620002101200c41b87c6a220c0d000b201041c8036c210620074198016a21012000ad4220862004ad84210303402001108d01200141c8036a2101200641b87c6a22060d000b2007102f20024180056a240020030f0b1036000b103d000b1038000b200241dc036a4104360200200241cc006a41023602002002420237023c200241b8c2c800360238200241043602d403200241f8c3c8003602d003200241003602ec02200241c8e1ca003602e8022002200241d0036a3602482002200241e8026a3602d803200241386a41c8c2c8001043000b920201067f200128020421020240024002400240034002400240200128020022032f010622040d00410021050c010b20044103742101200341086a2106417f21050340024020010d00200421050c020b200541016a210541fca1ca002006410810ea062207450d03200141786a2101200641086a21062007417f4a0d000b0b2002450d022002417f6a2102200320054102746a41e4016a21010c000b0b200341e0006a2005410c6c6a22012802084108490d01200041086a2001280200290000370300200041003602000f0b200041003602042000410c6a4128360200200041086a4184a2ca003602000c010b200041003602042000410c6a4129360200200041086a41aca2ca003602000b200041013602000beb2107077f017e0d7f047e017f017e027f230041d0026b22022400024002402001450d00200220003602180c010b200241c8e1ca003602180b2002200136021c200241e8006a200241186a10f104024002400240024002400240024002400240200228026c2203450d00200241e0016a2802002104200241dc016a2802002105200241d8016a2802002106200241e8006a410c6a280200210720022802702108200241106a200241186a10e60120022802100d08200228021421012002200241186a360240200241003a0030200242003702f40120024190bdc6003602f0012002200136026c200241003602682002200241306a3602742002200241c0006a360270200241e8006a200241f0016a10ee0420022802f001210120022902f4012109024020022d0030450d0020012009a72009422088a710e4010c090b2001450d0820022009370224200220013602204101210a200241013b013c200242003702344190bdc600210b20024190bdc600360230024020040d004100210c4100210d4100210e0c040b2006200441c8036c6a210b200241306a41086a210f200241c0006a4104722110200241f0016a4102722111200241e8006a41106a210e200621120340201241e8006a2903004202520d0202400240024002400240201228029801220c410347220d0d0020122903a0012109200241206a21012002280224211302400240024002400240034002400240200128020022142f010622150d00410021160c010b20154103742101201441086a2100417f21160340024020010d00201521160c020b201641016a211641b3c7ca002000410810ea06220a450d03200141786a2101200041086a2100200a417f4a0d000b0b2013450d022013417f6a2113201420164102746a41e4016a21010c000b0b0240201441e0006a2016410c6c6a220128020841074b0d00201742808080807083422984210941bbc7ca0021130c020b200942b8178020012802002900002217510d034131211541cbdbc90021130c020b201742808080807083421c84210941e4c7ca0021130b2009a721150b0240024020022d003d450d004131210141c6efc00021000c010b20022802302002280234200228023810e4012002420037023420024190bdc600360230200242e2c289abb68edbb7f40037034041002116200241f0016a410272410041da0010e7061a200241e8006a410041840110e7061a41e401102d2214450d0c20144100360200201441046a200241f0016a41dc0010e8061a201441e0006a200241e8006a41840110e8061a20024100360234200220143602300240024020142f01062212450d0020124103742101201441086a2100417f21160340024020010d00201221160c020b200241c0006a2000410810ea06220a450d02200141786a2101201641016a2116200041086a2100200a417f4a0d000b0b200242e2c289abb68edbb7f40037027c2002200f360278200220163602742002201436026c4100210a200241003602682002200241306a360270200241f0016a2013201510d405200241e8006a200241f0016a109b0220024180023b013c4101210c0c0b0b412d21014199efc00021000b2002200136026c2002200036026841f7efc0004122200241e8006a419cf0c00041acf0c000103e000b200d0d0020122903a0012118200241e8006a200241206a10d20502400240024020022802684101460d0020022903702109200241e8006a41186a22164200370300200e4200370300200241e8006a41086a220142003703002002420037036841d5a2ca00ad42808080809001841001220029000021192001200041086a290000370300200220193703682000102f41ecb0c000ad42808080803084100122002900002119200241c0006a41086a220a200041086a290000370300200220193703402000102f200e2002290340370000200e41086a200a290300370000200241f0016a41086a2001290300370300200241f0016a41106a200e290300370300200241f0016a41186a2016290300370300200220022903683703f0012002200241f0016a10e30102402018200942b0ea017c560d004100210c2018200229030842dc0b7c42dc0b20022802001b2209540d020c030b201a42808080807083211a41bcf0c000ad4280808080d0048421094101210c4100211b0c010b20022903702109200228026c211b4101210c201c42808080807083200235027884221c211a0b2002201a3703502002201b3602442002200c3602402002200937034802400240024020022d003d450d004131210141c6efc00021000c010b024002400240200c450d0020022802302002280234200228023810e4012002420037023420024190bdc600360230200242f4d2b59bc7ae98b8303703580c010b20022802302114200242f4d2b59bc7ae98b83037035820144190bdc600460d00200228023421130c010b2011410041da0010e7061a200241e8006a410041840110e7061a41e401102d2214450d0e4100211320144100360200201441046a200241f0016a41dc0010e8061a201441e0006a200241e8006a41840110e8061a20024100360234200220143602300b2009422088a7211d2009a7211e024003400240024020142f010622150d00410021160c010b20154103742101201441086a2100417f21160340024020010d00201521160c020b200241d8006a2000410810ea06220a450d03200141786a2101201641016a2116200041086a2100200a417f4a0d000b0b02402013450d002013417f6a2113201420164102746a41e4016a28020021140c010b0b200242f4d2b59bc7ae98b83037027c2002200f360278200220163602742002201436026c200241003602682002200241306a3602704101102d210102400240200c0d002001450d10200141003a000020014101410910312201450d102001200937000141092116410921000c010b2001450d0f200141013a0000200241f0016a201010ca0520022802f00121140240024020022802f801220a0d0041012116200a41016a21000c010b200a41016a2200200a490d1120004102200041024b1b22164100480d1120014101201610312201450d100b200141016a2014200a10e8061a20022802f401450d002014102f0b200220003602f801200220163602f401200220013602f001200241e8006a200241f0016a109b022002200c3a003d200241003a003c200c0d02200c450d03201b450d03201d450d03201e102f0c030b412d21014199efc00021000b200220003602682002200136026c41f7efc0004122200241e8006a419cf0c00041acf0c000103e000b2002280238210d2002280234210e2002280230210b201b450d02201d450d02201e102f0c020b201228029801210c0b200c4104470d03201241a4016a280200410b490d032002410d3602482002419387c70036024420024100360240024020022d003d450d004131210141c6efc00021000c030b20022802302002280234200228023810e4012002420037023420024190bdc600360230200242f5dc8de3d6ec9c9830370358200241f0016a410272410041da0010e7061a200241e8006a410041840110e7061a41e401102d2214450d0920144100360200201441046a200241f0016a41dc0010e8061a201441e0006a200241e8006a41840110e8061a200241003602342002201436023041002116024020142f01062213450d0020134103742101201441086a2100417f21160340024020010d00201321160c020b200241d8006a2000410810ea06220a450d03200141786a2101201641016a2116200041086a2100200a417f4a0d000b0b200242f5dc8de3d6ec9c983037027c2002200f360278200220163602742002201436026c200241003602682002200241306a3602704101102d2201450d09200141003a0000200241f0016a200241c0006a10ca0520022802f001210a0240024020022802f80122000d0041012114200041016a21160c010b200041016a22162000490d0b20164102201641024b1b22144100480d0b20014101201410312201450d0a0b4101210c200141016a200a200010e8061a024020022802f401450d00200a102f0b200220163602602002201436025c20022001360258200241e8006a200241d8006a109b0220024180023b013c2002280230210b2002280234210e2002280238210d0b4100210a0c070b412d21014199efc00021000b200220003602682002200136026c41f7efc0004122200241e8006a419cf0c00041acf0c000103e000b201241c8036a2212200b470d000c020b0b200241cc006a410436020020024184026a4102360200200242023702f401200241b8c2c8003602f0012002410436024420024194c4c80036024020024100360234200241c8e1ca003602302002200241c0006a360280022002200241306a360248200241f0016a41c8c2c8001043000b20022d003d210c20022d003c210a0b2002280238210d2002280234210e2002280230210b0b20022802202002280224200228022810e40102402007450d00200741246c21002003210103400240024020012d0000221641044b0d0002400240024020160e050400010204040b2001410c6a280200450d03200141086a280200102f0c030b2001410c6a280200450d02200141086a280200102f0c020b2001410c6a280200450d01200141086a280200102f0c010b200141086a280200450d00200141046a280200102f0b200141246a21012000415c6a22000d000b0b02402008450d002003102f0b02402004450d00200441c8036c210020064198016a210103402001108d01200141c8036a2101200041b87c6a22000d000b0b02402005450d002006102f0b20024100360270200242013703684101102d2201450d00200242818080801037026c200220013602682001200a3a000020014101410210312201450d00200242828080802037026c200220013602682001200c3a0001200d200241e8006a1069200b21010240200e450d00200e2100200b2101034020012802e40121012000417f6a22000d000b0b200d450d0241002114200d2115034002400240201420012f0106490d004100210a024003400240200128020022000d0041002116410021000c020b200a41016a210a20012f0104211620002101201620002f01064f0d000b0b201641016a21140240200a0d00200021010c020b200020144102746a41e4016a280200210141002114200a417f6a220a450d01034020012802e4012101200a417f6a220a0d000c020b0b2001210020142116201441016a21140b02400240200228026c22132002280270220a6b4108490d00200228026821130c010b200a41086a2212200a490d032013410174220c2012200c20124b1b22124100480d030240024020130d002012102d21130c010b200228026820132012103121130b2013450d022002201236026c200220133602680b2002200a41086a3602702013200a6a200020164103746a41086a290000370000200041e0006a2016410c6c6a2200280200211320002802082200200241e8006a106902400240200228026c220a200228027022166b2000490d002002280268210a0c010b201620006a22122016490d03200a410174220c2012200c20124b1b22124100480d0302400240200a0d002012102d210a0c010b2002280268200a20121031210a0b200a450d022002201236026c2002200a3602680b2002201620006a2212360270200a20166a2013200010e8061a2015417f6a22150d000c040b0b1036000b1038000b200228027021122002280268210a0b200b200e200d10e401200241d0026a24002012ad422086200aad840f0b200241f0016a410c6a4104360200200241fc006a41023602002002420237026c200241b8c2c800360268200241043602f40120024194c4c8003602f00120024100360244200241c8e1ca003602402002200241f0016a3602782002200241c0006a3602f801200241e8006a41c8c2c8001043000bcd0301057f024002400240200241046a2203417f4c0d00024002400240024002400240024002402003450d002003102d2204450d09200241c000490d04200241808001490d052002418080808004490d06200441033a00002003417f6a41034d0d01200321050c030b410121034101102d2204450d08200441033a0000410521050c010b200341017422064105200641054b1b22054100480d080b20042003200510312204450d060b20042002360001410521060c030b200420024102743a000041012106200321050c020b02400240200341014d0d00200321050c010b20042003200341017422064102200641024b1b220510312204450d040b41022106200420024102744101723b00000c010b02400240200341034d0d00200321050c010b200341017422064104200641044b1b22054100480d0420042003200510312204450d030b20042002410274410272360000410421060b02400240200520066b2002490d00200521030c010b200620026a22032006490d03200541017422072003200720034b1b22034100480d0320042005200310312204450d020b200420066a2001200210e8061a2000200620026a36020820002003360204200020043602000f0b103d000b1036000b1038000bb90101067f230041206b22022400200241c8e1ca00410010ac0402404120102d2203450d0020032002290300370000200341186a2204200241186a290300370000200341106a2205200241106a290300370000200341086a2206200241086a2903003700004120102d2207450d0020072003290000370000200741186a2004290000370000200741106a2005290000370000200741086a20062900003700002003102f200241206a24002007ad42808080808004840f0b1036000b8f3e05037f017e067f057e067f230041f0116b22022400024002402001450d00200220003602100c010b200241c8e1ca003602100b20022001360214200241e80a6a200241106a10a4040240024002400240024002400240024020022903d00b4203510d00200241d0006a200241e80a6a41c80310e8061a20024198046a200241d0006a41c80310e8061a200220024198046a3602e007200241e80a6a200241e0076a10a90320022802f00a2103024020022802ec0a450d0020022802e80a102f0b200241e80a6a20024198046a41c80310e8061a200241e0076a200241e80a6a10d10341012100024020022d00e0074101460d00200241e80a6a200241e0076a41086a220141800310e8061a200241b00e6a200241b80b6a220410f10220022903b00e210502400240024020022903880b4202520d00200241186a41206a22014200370300200241186a41186a22004280808080c000370300200241013a0040200242043703282002427f37032020024200370318200241e0076a41206a22064200370300200241e0076a41186a22074280808080c000370300200241013a008808200242043703f0072002427f3703e807200242003703e007200241a00f6a200241186a200241e0076a10d705200241186a41286a2208200241a00f6a41286a2903003703002001200241a00f6a41206a2903003703002000200241a00f6a41186a290300370300200241186a41106a2209200241a00f6a41106a290300370300200241186a41086a220a200241a00f6a41086a290300370300200220022903a00f3703182006420037030020074280808080c000370300200241013a008808200242043703f0072002427f3703e807200242003703e007200241d00f6a200241186a200241e0076a10d7052008200241d00f6a41286a2903003703002001200241d00f6a41206a2903003703002000200241d00f6a41186a2903003703002009200241d00f6a41106a290300370300200a200241d00f6a41086a290300370300200220022903d00f3703182006420037030020074280808080c000370300200241013a008808200242043703f0072002427f3703e807200242003703e00720024180106a200241186a200241e0076a10d705200820024180106a41286a290300370300200120024180106a41206a290300370300200020024180106a41186a290300370300200920024180106a41106a290300370300200a20024180106a41086a29030037030020022002290380103703182006420037030020074280808080c000370300200241013a008808200242043703f0072002427f3703e807200242003703e007200241b0106a200241186a200241e0076a10d705200241c0116a41286a200241b0106a41286a290300370300200241c0116a41206a220b200241b0106a41206a290300370300200241c0116a41186a220a200241b0106a41186a290300370300200241c0116a41106a200241b0106a41106a290300370300200241c0116a41086a200241b0106a41086a290300370300200220022903b0103703c0112002200537039011200241e0076a20024190116a200310a604024020022d00e0074101470d0020022d00e307210620022f00e107210720022802d01121030240200a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102f0b2001410c6a2101200041746a22000d000b0b0240200241d4116a280200450d002003102f0b20022802dc1121030240200241e4116a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102f0b2001410c6a2101200041746a22000d000b0b0240200241e0116a280200450d002003102f0b4101450d02200720064110747221010c080b200820024190086a2903003703002001200241e0076a41286a2903003703002000200629030037030020092007290300370300200241186a41086a2203200241e0076a41106a290300370300200220022903e807370318200241e0106a200241c0116a200241186a10d7052008200241e0106a41286a2903003703002001200241e0106a41206a2903003703002000200241e0106a41186a2903003703002009200241e0106a41106a2903003703002003200241e0106a41086a290300370300200220022903e0103703182006420037030020074280808080c000370300200241013a008808200242043703f0072002427f3703e807200242003703e00720024190116a200241186a200241e0076a10d705200820024190116a41286a290300370300200120024190116a41206a290300370300200020024190116a41186a290300370300200920024190116a41106a290300370300200320024190116a41086a29030037030020022002290390113703182006420037030020074280808080c000370300200241013a008808200242043703f0072002427f3703e807200242003703e007200241c0116a200241186a200241e0076a10d705200241fc0e6a200241c0116a41086a290300370200200220022903c0113702f40e41000d07200241d4116a2802002108200a2802002101200b2802002109200241e4116a280200210320022802d011210620022802dc11210720022903e81121050c020b200241186a41206a22064200370300200241186a41186a22074280808080c000370300200241013a004020024204370328427f210c2002427f37032020024200370318200241e0076a41206a22084200370300200241e0076a41186a22004280808080c000370300200241013a008808200242043703f0072002427f3703e807200242003703e007200241c00e6a200241186a200241e0076a10d705200241186a41286a2209200241c00e6a41286a2903003703002006200241c00e6a41206a2903003703002007200241c00e6a41186a290300370300200241186a41106a220a200241c00e6a41106a290300370300200241186a41086a220b200241c00e6a41086a290300370300200220022903c00e3703182008420037030020004280808080c000370300200241013a008808200242043703f0072002427f3703e807200242003703e007200241f00e6a200241186a200241e0076a10d7052009200241f00e6a41286a2903003703002006200241f00e6a41206a2903003703002007200241f00e6a41186a290300370300200a200241f00e6a41106a290300370300200b200241f00e6a41086a290300370300200220022903f00e37031820004200370300200241e0076a41106a2207420037030020014200370300200242003703e007418de6c300ad4280808080e00084220d10012206290000210e2001200641086a2900003703002002200e3703e0072006102f419ce6c300ad4280808080e0008410012206290000210e20024190116a41086a2209200641086a2900003703002002200e370390112006102f2007200229039011220e370300200241c0116a41086a2001290300370300200241c0116a41106a200e370300200241c0116a41186a2009290300370300200220022903e0073703c011200241086a200241c0116a4120109501200228020c410020022802081bad210e024020022903880b4201520d0020022903900b220c4200510d05200e200241980b6a290300220f200f200e541b2210200c7c2010200f7d200c827d210c0b2008420037030020004280808080c000370300200241013a008808200242043703f007200242003703e00720024200200c200e7d220e200e200c561b3703e807200241a00f6a200241186a200241e0076a10d70520024190116a41286a200241a00f6a41286a29030037030020024190116a41206a200241a00f6a41206a29030037030020024190116a41186a200241a00f6a41186a29030037030020024190116a41106a200241a00f6a41106a29030037030020024190116a41086a200241a00f6a41086a290300370300200220022903a00f3703901120022802b00b2106200d10012201290000210c200241e0106a41086a200141086a2900003703002002200c3703e0102001102f41f0e8c600ad4280808080f0008410012201290000210c200241186a41086a200141086a2900003703002002200c3703182001102f4120102d2201450d09200120022903e80a370000200141186a200241e80a6a41186a290300370000200141106a200241e80a6a41106a290300370000200141086a200241e80a6a41086a2903003700002001ad428080808080048410032200290000210c200041086a290000210e200041106a290000210d200241e0076a41186a2207200041186a290000370300200241e0076a41106a2208200d370300200241e0076a41086a200e3703002002200c3703e0072000102f2001102f41c000102d2201450d09200120022903e01037000020012002290318370010200120022903e007370020200141086a200241e0106a41086a290300370000200141186a200241186a41086a290300370000200141286a200241e0076a41086a290300370000200141306a2008290300370000200141386a2007290300370000200241e0076a200110f602200241a8086a280200210020022903e007210c2001102f024002400240024020004100200c4201511b220720064b0d00410c102d2200450d0d4104102d2201450d0d20014104412010312201450d0d200120022903e80a370000200141186a200241e80a6a41186a290300370000200141106a200241e80a6a41106a290300370000200141086a200241e80a6a41086a2903003700002001412041c00010312201450d0d20012006360020200042c0808080c004370204200020013602000240024020072006490d0041002101410421070c010b410c102d2207450d0e4104102d2201450d0e20014104412010312201450d0e200120022903e80a370000200141186a200241e80a6a41186a290300370000200141106a200241e80a6a41106a290300370000200141086a200241e80a6a41086a2903003700002001412041c00010312201450d0e20012006417f6a360020200742c0808080c00437020420072001360200410121010b200241c0116a41206a2206428180808010370300200241c0116a41186a22082001360200200241d4116a2001360200200220022800b0103602b80e2002200241b3106a2800003600bb0e200241ec116a20022800bb0e360000200220003602dc11200220073602d0112002427f3703c8112002200542ffffffff0f833703c011200220022802b80e3600e911200241013a00e811200241d00f6a20024190116a200241c0116a10d70520024190116a41286a2200200241d00f6a41286a29030037030020024190116a41206a2207200241d00f6a41206a29030037030020024190116a41186a2201200241d00f6a41186a29030037030020024190116a41106a2209200241d00f6a41106a29030037030020024190116a41086a220a200241d00f6a41086a290300370300200220022903d00f3703901120022005370318200241e0076a200241186a200310a60420022d00e0074101460d01200241c0116a41286a20024190086a220b2903003703002006200241e0076a41286a2903003703002008200241e0076a41206a290300370300200241c0116a41106a200241e0076a41186a290300370300200241c0116a41086a200241e0076a41106a290300370300200220022903e8073703c01120024180106a20024190116a200241c0116a10d705200020024180106a41286a290300370300200720024180106a41206a290300370300200120024180106a41186a290300370300200920024180106a41106a290300370300200a20024180106a41086a29030037030020022002290380103703901120022005370318200241e0076a20022903a00b200241a80b6a290300200241e80a6a200241186a200310d40320022d00e0074101460d02200241c0116a41286a2201200b290300370300200241c0116a41206a2200200241e0076a41286a2203290300370300200241c0116a41186a2206200241e0076a41206a2207290300370300200241c0116a41106a2208200241e0076a41186a2209290300370300200241c0116a41086a220a200241e0076a41106a220b290300370300200220022903e8073703c011200241b0106a20024190116a200241c0116a10d70520024190116a41286a200241b0106a41286a29030037030020024190116a41206a200241b0106a41206a29030037030020024190116a41186a2211200241b0106a41186a29030037030020024190116a41106a200241b0106a41106a29030037030020024190116a41086a200241b0106a41086a290300370300200220022903b01037039011200241e0076a200410e20120022d00e0074101460d032001200241e0076a41306a290300370300200020032903003703002006200729030037030020082009290300370300200a200b290300370300200220022903e8073703c011200241e0106a20024190116a200241c0116a10d705200241186a41086a20022903e010370300200241186a41106a200241e0106a41086a290300370300200241186a41186a200241e0106a41106a290300370300200241186a41206a200241e0106a41186a290300370300200241186a41286a200241e0106a41206a290300370300200241186a41306a200241e0106a41286a290300370300200241003a00180c0b0b200220022800b0103602b80e2002200241b3106a2800003600bb0e200241003a001b20024180063b0019200241013a001820022802a01121030240200241a8116a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102f0b2001410c6a2101200041746a22000d000b0b0240200241a4116a280200450d002003102f0b20022802ac1121030240200241b4116a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102f0b2001410c6a2101200041746a22000d000b0b200241b0116a280200450d0a2003102f0c0a0b200220022d00e3073a001b200220022f00e1073b0019200241013a001820022802a0112103024020012802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102f0b2001410c6a2101200041746a22000d000b0b0240200241a4116a280200450d002003102f0b20022802ac1121030240200241b4116a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102f0b2001410c6a2101200041746a22000d000b0b200241b0116a280200450d092003102f0c090b200220022d00e3073a001b200220022f00e1073b0019200241013a001820022802a01121030240200241a8116a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102f0b2001410c6a2101200041746a22000d000b0b0240200241a4116a280200450d002003102f0b20022802ac1121030240200241b4116a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102f0b2001410c6a2101200041746a22000d000b0b200241b0116a280200450d082003102f0c080b200220022d00e3073a001b200220022f00e1073b0019200241013a001820022802a0112103024020112802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102f0b2001410c6a2101200041746a22000d000b0b0240200241a4116a280200450d002003102f0b20022802ac1121030240200241b4116a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102f0b2001410c6a2101200041746a22000d000b0b200241b0116a280200450d072003102f0c070b0b200241c80e6a200241fc0e6a290200370300200220022902f40e3703c00e0240024020022802b80b4113460d00200241003a00e307418102210020024181023b00e107200241013a00e0070c010b200241e0076a200241bc0b6a10a20320022d00e0074101470d0420022f00e10720022d00e3074110747221000b200241013a0018200220003b0019200220004110763a001b02402001450d002001410c6c21002006210103400240200141046a280200450d002001280200102f0b2001410c6a2101200041746a22000d000b0b02402008450d002006102f0b02402003450d002003410c6c21002007210103400240200141046a280200450d002001280200102f0b2001410c6a2101200041746a22000d000b0b2009450d052007102f0c050b200220022d00e3073a001b200220022f00e1073b0019200241013a00180c050b200241dc006a4104360200200241ac046a41023602002002420237029c04200241b8c2c8003602980420024104360254200241acc4c800360250200241003602e407200241c8e1ca003602e0072002200241d0006a3602a8042002200241e0076a36025820024198046a41c8c2c8001043000b41d0caca00411941eccaca001039000b200241e0106a41286a2200200241e0076a41306a290300370300200241e0106a41206a220a200241e0076a41286a220b290300370300200241e0106a41186a2211200241e0076a41206a2212290300370300200241e0106a41106a2213200241e0076a41186a2214290300370300200241e0106a41086a2215200241e0076a41106a2216290300370300200220022903e8073703e010200241c0116a41086a200241c00e6a41086a290300370300200241e4116a2003360200200241c0116a41206a2009360200200241c0116a41186a2001360200200241d4116a2008360200200220022903c00e3703c011200220053703e811200220073602dc11200220063602d011200b20002903003703002012200a2903003703002014201129030037030020162013290300370300200241e0076a41086a2015290300370300200220022903e0103703e00720024190116a200241c0116a200241e0076a10d705200241186a41086a200229039011370300200241186a41106a20024190116a41086a290300370300200241186a41186a20024190116a41106a290300370300200241186a41206a20024190116a41186a290300370300200241186a41286a20024190116a41206a290300370300200241186a41306a20024190116a41286a290300370300200241003a00180c010b200241013a0018200220013b0019200220014110763a001b0b2004108e0120022d001821000b4101102d2201450d00200242013702ec0a200220013602e80a02400240200041ff01714101470d00200241013602f00a200141013a0000200241186a410172200241e80a6a10a10320022802f00a210020022802e80a21010c010b200241013602f00a200141003a0000200241206a2903002105024020022802ec0a2200417f6a41074b0d00200041017422034109200341094b1b22034100480d0320012000200310312201450d02200220033602ec0a200220013602e80a0b200241093602f00a20012005370001200241306a2802002100200241386a2802002201200241e80a6a106902402001450d0020002001410c6c6a2109034020002802002107200041086a2802002201200241e80a6a10690240024020022802ec0a220620022802f00a22036b2001490d0020022802e80a21060c010b200320016a22082003490d05200641017422042008200420084b1b22084100480d050240024020060d002008102d21060c010b20022802e80a20062008103121060b2006450d04200220083602ec0a200220063602e80a0b2002200320016a3602f00a200620036a2007200110e8061a2000410c6a22002009470d000b0b2002413c6a2802002100200241c4006a2802002201200241e80a6a10690240024020010d0020022802ec0a210620022802f00a21090c010b20002001410c6c6a2104034020002802002108200041086a2802002201200241e80a6a10690240024020022802ec0a220620022802f00a22036b2001490d0020022802e80a21070c010b200320016a22072003490d05200641017422092007200920074b1b22094100480d050240024020060d002009102d21070c010b20022802e80a20062009103121070b2007450d04200220093602ec0a200220073602e80a200921060b2002200320016a22093602f00a200720036a2008200110e8061a2000410c6a22002004470d000b0b200241286a290300210502400240200620096b4108490d0020022802e80a21010c010b200941086a22012009490d03200641017422002001200020014b1b22004100480d030240024020060d002000102d21010c010b20022802e80a20062000103121010b2001450d02200220003602ec0a200220013602e80a200021060b2002200941086a3602f00a200120096a2005370000200241c8006a2d000021070240200620022802f00a2203470d00200641016a22002006490d03200641017422082000200820004b1b22004100480d030240024020060d002000102d21010c010b200120062000103121010b2001450d02200220003602ec0a200220013602e80a0b2002200341016a22003602f00a200120036a20073a00000b2000ad4220862001ad842105024020022d00180d000240200241386a2802002200450d00200241306a28020021012000410c6c210003400240200141046a280200450d002001280200102f0b2001410c6a2101200041746a22000d000b0b0240200241346a280200450d002002280230102f0b0240200241c4006a2802002200450d002002413c6a28020021012000410c6c210003400240200141046a280200450d002001280200102f0b2001410c6a2101200041746a22000d000b0b200241c0006a280200450d00200228023c102f0b200241f0116a240020050f0b1036000b1038000bc80505017f027e077f017e017f230041206b220324002002290300210420012903002105200141106a210620022802102107024002400240024002400240200141146a2802002208200141186a28020022096b200241186a280200220a490d00200628020021080c010b2009200a6a220b2009490d022008410174220c200b200c200b4b1bad420c7e220d422088a70d02200da7220b4100480d020240024020080d00200b102d21080c010b20062802002008410c6c200b103121080b2008450d0120012008360210200141146a200b410c6e3602000b20082009410c6c6a2007200a410c6c10e8061a200141186a2009200a6a36020020024100360218200341086a200641086a280200360200200320062902003703002001411c6a2106200228021c210b02400240200141206a2802002208200141246a28020022096b200241246a280200220a490d00200628020021080c010b2009200a6a220c2009490d022008410174220e200c200e200c4b1bad420c7e220d422088a70d02200da7220c4100480d020240024020080d00200c102d21080c010b20062802002008410c6c200c103121080b2008450d012001200836021c200141206a200c410c6e3602000b427f200520047c220420042005541b210520082009410c6c6a200b200a410c6c10e8061a200141246a2009200a6a36020020024100360224200341106a41086a200641086a28020036020020032006290200370310200229030822042001290308220d200d2004561b210420012d0028450d024101210120022d0028450d020c030b1036000b1038000b410021010b20002005370300200020032903003702102000200329031037021c200020013a002820002004370308200041186a200341086a280200360200200041246a200341106a41086a2802003602000240200241146a280200450d002007102f0b0240200241206a280200450d00200b102f0b200341206a24000b9d3008057f027e077f017e037f017e137f017e230022022103200241a0046b41607122042400024002402001450d00200420003602380c010b200441c8e1ca003602380b2004200136023c200441b0026a200441386a10f6030240024002400240024002400240024020042802b402450d00200441c0006a200441b0026a41f00010e8061a200441b0016a200441c0006a10ba032004280240200441d0006a20044190016a200441b0016a410010ce03410041002802a8e24a2201410120011b3602a8e24a0240200141014b0d000240024020010e020001000b410041b4a5c0003602b0e24a410041c8e1ca003602ace24a410041023602a8e24a0c010b034041002802a8e24a4101460d000b0b2004410020042802402201417f6a2202200220014b1b22053602bc0110214101470d01200441b0026a41186a22064200370300200441b0026a41106a22024200370300200441b0026a41086a22014200370300200442003703b00241d39bca00ad428080808080018422071001220029000021082001200041086a290000370300200420083703b0022000102f41bdc5c300ad4280808080e00184100122092900002108200441e8016a41086a2200200941086a290000370300200420083703e8012009102f200220042903e8012208370300200441c0036a41086a220a2001290300370300200441c0036a41106a220b2008370300200441c0036a41186a220c2000290300370300200420042903b0023703c003200441306a200441c0036a412010950102402004280234410020042802301b220920054d0d0041002100200441c0036a21010c060b200642003703002002420037030020014200370300200442003703b002419c9eca00ad4280808080f000841001220929000021082001200941086a290000370300200420083703b0022009102f41a39eca00ad4280808080c001841001220929000021082000200941086a290000370300200420083703e8012009102f200220042903e8012208370300200a2001290300370300200b2008370300200c2000290300370300200420042903b0023703c003200441286a200441c0036a4120109501200428022c210d2004280228210e200642003703002002420037030020014200370300200442003703b00220071001220929000021082001200941086a290000370300200420083703b0022009102f419087ca00ad4280808080c000841001220929000021082000200941086a290000370300200420083703e8012009102f200220042903e8012208370300200a2001290300370300200b2008370300200c2000290300370300200420042903b0023703c003200441b0026a200441c0036a108d0320042802b002210f20042902b4022110200441b0026a41e9dabdf30610d90520042802b002210920042802b402210b024002400240024020042802b80222010d004101211141002112410021130c010b2001410574220a410575220241ffffff3f712002470d0a200a4100480d0a200a102d2211450d012009200a6a210c20014105742106410021010340200920016a22022900002108200241086a2900002107200241106a2900002114201120016a220041186a200241186a290000370000200041106a2014370000200041086a2007370000200020083700002006200141206a2201470d000b200a4105762112200c20096b41606a41057641016a21130b0240200b450d002009102f0b20134115490d054101450d0120134104744160712201417f4c0d012001102d2215450d00201141606a2116201141a07f6a211720014105762118410421194100211a4100211b4100211c2013211d0340201d210a4100211d410121060240200a417f6a2200450d00024002400240024002400240201120004105746a200a410574220b20116a41406a412010ea064100480d00200a417e6a21092017200b6a21014100211d410021020340024020092002470d00200a21060c080b200241016a2102200141206a2001412010ea062100200141606a21012000417f4a0d000b200241016a21062002417f73200a6a21000c010b2017200b6a210102400340024020004101470d00410021000c020b2000417f6a2100200141206a2001412010ea062102200141606a210120024100480d000b0b200a2000490d01200a20134b0d03200a20006b22064101762209450d002016200b6a2101201120004105746a21020340200441b0026a41186a220b200241186a220c290000370300200441b0026a41106a221e200241106a221f290000370300200441b0026a41086a2220200241086a2221290000370300200420022900003703b002200141086a22222900002108200141106a22232900002107200141186a221d290000211420022001290000370000200c2014370000201f200737000020212008370000201d200b2903003700002023201e29030037000020222020290300370000200120042903b002370000200141606a2101200241206a21022009417f6a22090d000b0b024020000d002000211d0c050b0240200641094d0d002000211d0c050b200a20134b0d01200a20006b2109201120004105746a210b0340200a2000417f6a221d490d040240200a201d6b22064102490d00201120004105746a22012011201d4105746a2200412010ea06417f4a0d00200441b0026a41186a2220200041186a2202290000370300200441b0026a41106a2221200041106a220c290000370300200441b0026a41086a2222200041086a221e290000370300200420002900003703b00220002001290000370000201e200141086a290000370000200c200141106a2900003700002002200141186a2900003700004101211f024020064103490d00200041c0006a200441b0026a412010ea06417f4a0d0041022102200b210102400340200141186a200141386a290000370000200141106a200141306a290000370000200141086a200141286a2900003700002001200141206a220c29000037000020092002460d01200141c0006a211e2002211f200c2101200241016a2102201e200441b0026a412010ea06417f4a0d020c000b0b2002211f0b2000201f4105746a220120042903b002370000200141186a2020290300370000200141106a2021290300370000200141086a20222903003700000b201d450d05200b41606a210b200941016a2109201d21002006410a4f0d050c000b0b2000200a104b000b200a2000417f6a221d490d010b200a2013104a000b201d200a104b000b0240201c201a470d00201a41016a2201201a490d0b201a41017422022001200220014b1b220141ffffffff01712001470d0b200141037422014100480d0b02400240201a0d002001102d21190c010b2019201a4103742001103121190b2019450d022001410376211a201b211c0b2019201c4103746a220120063602042001201d360200201b41016a221c211b0240201c4102490d000240034002400240024002402019201c417f6a221b4103746a2201280200450d00201c41037420196a220941746a2802002200200128020422024d0d000240201c41024b0d00201c211b4102211c201d450d0d0c080b2019201c417d6a22204103746a2802042201200220006a4d0d010240201c41034b0d00201c211b4103211c201d450d0d0c080b200941646a280200200120006a4d0d01201c211b0c060b201c4103490d01200128020421022019201c417d6a22204103746a28020421010b20012002490d010b201c417e6a21200b024002400240024002400240201c202041016a22244b2225450d00201c20204b2226450d01201920204103746a2221280204222720212802006a2201201920244103746a22222802002223490d02200120134b0d03201120234105746a221e2022280204221f41057422026a210920014105742100200120236b220a201f6b2201201f4f0d04201520092001410574220210e806220c20026a210602400240201f4101480d00200141014e0d010b20092101200c21020c060b201620006a21002009210103402000200141606a2209200641606a220a200a2009412010ea06410048220b1b2202290000370000200041186a200241186a290000370000200041106a200241106a290000370000200041086a200241086a2900003700002006200a200b1b21060240201e20092001200b1b2201490d00200c21020c070b200041606a2100200c2102200c2006490d000c060b0b41c4c2ca002024201c103b000b41c4c2ca002020201c103b000b20232001104b000b20012013104a000b2015201e200210e806220c20026a210602400240201f4101480d00200a201f4a0d010b201e2101200c21020c010b201120006a210b200c2102201e2101034020012009200220092002412010ea06410048220a1b2200290000370000200141186a200041186a290000370000200141106a200041106a290000370000200141086a200041086a2900003700002002200241206a200a1b2102200141206a2101200941206a2009200a1b2209200b4f0d01200620024b0d000b0b20012002200620026b41607110e8061a02402026450d0020212023360200202141046a2027201f6a3602002025450d022022202241086a201c2024417f736a41037410e9061a201b211c201b41014d0d030c010b0b419cc3ca002020201c103b000b41b8e3c300411d41f8b4ca001039000b201d450d050c000b0b1036000b103d000b200441cc036a4104360200200441d4006a410236020020044202370244200441b8c2c800360240200441043602c403200441c8c4c8003602c003200441003602ec01200441c8e1ca003602e8012004200441c0036a3602502004200441e8016a3602c803200441c0006a41c8c2c8001043000b41002802a4e24a4105490d042004412e3602c4032004200441bc016a3602c00341002802b0e24a210141002802ace24a210241002802a8e24a2100200441f0026a41e502360200200441e8026a42c580808010370300200441e4026a4188ccc300360200200441dc026a4210370200200441d8026a41f8cbc300360200200441d0026a4201370300200441c0026a4202370300200441b0026a41086a4108360200200441cc026a200441c0036a360200200441e0cbc3003602bc02200441f0cbc3003602b402200441053602b002200241cca5c000200041024622001b200441b0026a200141e4a5c00020001b2802101102000c040b0240201a450d002019102f0b2018450d012015102f0c010b20134102490d0020112013417f6a22024105746a21064101210003400240024002400240201320022201417f6a2202490d00201320026b220a4102490d03201120014105746a2201201120024105746a2209412010ea06417f4a0d03200441b0026a41186a221c200941186a220b290000370300200441b0026a41106a221f200941106a220c290000370300200441b0026a41086a2219200941086a221e290000370300200420092900003703b00220092001290000370000201e200141086a290000370000200c200141106a290000370000200b200141186a29000037000041012101200a4103490d02200941c0006a200441b0026a412010ea06417f4a0d024100210a200621010340200141186a200141386a290000370000200141106a200141306a290000370000200141086a200141286a2900003700002001200141206a220c2900003700002000200a220b460d02200b417f6a210a200141c0006a211e200c2101201e200441b0026a412010ea06417f4a0d020c000b0b20022013104b000b4102200b6b21010b200920014105746a220120042903b002370000200141186a201c290300370000200141106a201f290300370000200141086a20192903003700000b200641606a21062000417f6a210020020d000b0b200420053602dc032004200d4100200e1b22013602d803200420133602d403200420123602d003200420113602cc03200441003602c803200420053602cc02200420013602c802200420133602c402200420123602c002200420113602bc02200441003602b8022004200f4101200f1b22003602b002200420003602c0032004200020104200200f1b2208422088a74105746a22013602b402200420013602c4032008a72109200441c0036a21010b20044190026a41086a2206200141086a29020037030020044190026a41106a220a200141106a29020037030020044190026a41186a220b200141186a290200370300200441e8016a41086a220c200441b0026a41086a221e290200370300200441e8016a41106a221c200441b0026a41106a221f290200370300200441e8016a41186a2219200441b0026a41186a2202290200370300200441e8016a41206a2220200441b0026a41206a22212802003602002004200129020037039002200420042902b0023703e801200441c0016a41206a2201200441c0036a41206a280200360200200441c0016a41186a2222200441c0036a41186a290200370300200441c0016a41106a2223200441c0036a41106a290200370300200441c0016a41086a221d200441c0036a41086a290200370300200420042902c0033703c001200420093602b402200420003602b002201e200429039002370300201f20062903003703002002200a2903003703002021200b290300370300200441003602d802200441dc026a20042903e801370200200441e4026a200c290300370200200441ec026a201c290300370200200441f4026a2019290300370200200441fc026a20202802003602002004410036028003200441a4036a20012802003602002004419c036a202229030037020020044194036a20232903003702002004418c036a201d29030037020020044184036a20042903c00137020020044180036a211e200441d8026a2106200441e0026a210a200441e8026a210b200441f0026a210c4100210103400240024002400240024002402001450d00200441206a200610a403200428022022014108460d00200428022421090c010b20022903002107200220042903d803370300200441003602c00320042903c0022114200420042903d0033703c00220042903b8022110200420042903c8033703b80220042903b0022108200420042903c00322283703b00202402008a72201450d0020042903d0022128024020042802d8022200450d00024020042802dc02450d002000102f0b20042802f002450d0020042802ec02102f0b200a2010370300200b2014370300200c2007370300200420083703d802200420283703f8020c060b200428028003450d01200441186a201e10a403200428021c2109200428021821010b200141796a220041014b0d02024020000e020400040b20042802b00221010c010b2028a721010b02402001450d00024020042802b402450d002001102f0b200441c8026a280200450d00200441c4026a280200102f0b024020042802d8022201450d00024020042802dc02450d002001102f0b20042802f002450d0020042802ec02102f0b2004280280032201450d03024020044184036a280200450d002001102f0b20044198036a280200450d0320044194036a280200102f0c030b200420013602a803200420093602ac0341002802a4e24a4104490d00200441363602bc032004412e3602b4032004200441a8036a3602b8032004200441bc016a3602b00341002802b0e24a210141002802ace24a210041002802a8e24a2109200441dc0236028004200442c5808080103703f80320044188ccc3003602f403200442103702ec03200441f8cbc3003602e803200442023703e003200442023703d003200441d0cbc3003602cc03200441083602c803200441f0cbc3003602c403200441043602c003200141e4a5c000200941024622091b28021021012004200441b0036a3602dc03200041cca5c00020091b200441c0036a20011102000b20042802d80221010c000b0b20042802b0012109024020042802b8012201450d00200141246c21022009210103400240024020012d0000220041044b0d0002400240024020000e050400010204040b2001410c6a280200450d03200141086a280200102f0c030b2001410c6a280200450d02200141086a280200102f0c020b2001410c6a280200450d01200141086a280200102f0c010b200141086a280200450d00200141046a280200102f0b200141246a21012002415c6a22020d000b0b024020042802b401450d002009102f0b0240200441c0006a410c6a2802002202450d0020042802442101200241246c210203400240024020012d0000220041044b0d0002400240024020000e050400010204040b2001410c6a280200450d03200141086a280200102f0c030b2001410c6a280200450d02200141086a280200102f0c020b2001410c6a280200450d01200141086a280200102f0c010b200141086a280200450d00200141046a280200102f0b200141246a21012002415c6a22020d000b0b0240200441c8006a280200450d002004280244102f0b2003240042010f0b1038000bb20503017f017e0b7f230041e0006b220224002002200136020c024002400240024002402002410c6a102a2203422088a722010d0020004100360208200042013702000c010b2002200136021420022003a722043602102002200241106a10e60120022802000d0320022802042205200228021422064105762201200120054b1b22014105742207417f4c0d010240024020010d00410121080c010b2007102d2208450d030b2001ad2103024002402005450d004100210903402006210a200241003a0058200941016a2109410021010240024002400340200a2001460d01200241386a20016a200228021022072d00003a00002002200741016a3602102002200141016a22073a00582007210120074120470d000b200241186a41186a220b200241386a41186a290300370300200241186a41106a220c200241386a41106a290300370300200241186a41086a220d200241386a41086a290300370300200220022903383703182003a72003422088a72201470d020240200141016a22062001490d002001410174220e20062006200e491b220641ffffff3f712006470d002006410574220641004e0d020b1038000b200241003602140240200141ff0171450d00200241003a00580b2003a7450d082008102f0c080b0240024020010d002006102d21080c010b200820014105742006103121080b2008450d062003428080808070832006410576ad8421030b200a20076b2106200820014105746a22012002290318370000200141186a200b290300370000200141106a200c290300370000200141086a200d29030037000020034280808080107c210320092005470d000b2002200a20076b3602140c010b2008450d040b20002003370204200020083602002004102f0b200241e0006a24000f0b103d000b1036000b41f4c8ca00412e200241386a41e4c8ca004180c8ca00103e000bac0604067f017e027f047e230041e0006b220224002002411436020c200241c7b4c600360208200241106a41c7b4c600ad4280808080c00284100210730240024020022802102203450d00200228021421042002200241186a2802002205360224200220033602200240024002402005450d0020022005417f6a3602242002200341016a36022020032d00002105200241c8006a200241206a10ee0320022802482206450d00200228024c2107200541ff01714101460d012007450d002006102f0b20024100360230200242013703282002410b36023c2002200241086a3602382002200241286a36024441012105200241dc006a41013602002002420137024c200241b885c7003602482002200241386a360258200241c4006a41d8dbc100200241c8006a103c1a200235023042208620023502288410080240200228022c450d002002280228102f0b410221070c010b200241d0006a3502004220862007ad84210841012107410021050b02402004450d002003102f0b20050d0020074101460d010240024002400240024020062802082203ad42287e2208422088a70d002008a72204417f4c0d0020062802002107024020040d002007200341286c6a210941082106200321050c020b024002402004102d2206450d002007200341286c6a2109200441286e220520034f0d032005410174220a2003200a20034b1b220a41286c22034100480d0102400240200441274b0d002003102d21060c010b2006200541286c2003103121060b20060d040b1036000b1038000b103d000b2003450d012005210a0b200920076b210942002108410021040340200720046a2203290300210b200341086a290300210c200341106a290300210d200341186a290300210e200620046a220541206a200341206a290300370300200541186a200e370300200541106a200d370300200541086a200c3703002005200b37030020084280808080107c21082009200441286a2204470d000b200a21050c010b420021080b20082005ad8421080c010b42002108410821060b200241c8006a20062008422088a710db042002350250422086200235024884210b02402008a7450d002006102f0b200241e0006a2400200b0ba30e05047f017e017f017e047f23004190016b22022400200241c8006a41186a22034200370300200241c8006a41106a22044200370300200241c8006a41086a220542003703002002420037034841aa87ca00ad4280808080c000842206100122072900002108200241286a41086a2209200741086a290000370300200220083703282007102f200520092903003703002002200229032837034841b887ca00ad4280808080b001841001220729000021082009200741086a290000370300200220083703282007102f200420022903282208370300200241f0006a41086a220a2005290300370300200241f0006a41106a220b2008370300200241f0006a41186a220c200929030037030020022002290348370370200241c8006a200241f0006a10990520022802482107200229024c21082003420037030020044200370300200542003703002002420037034820061001220329000021062009200341086a290000370300200220063703282003102f200520092903003703002002200229032837034841d987ca00ad4280808080a001841001220329000021062009200341086a290000370300200220063703282003102f200420022903282206370300200a2005290300370300200b2006370300200c200929030037030020022002290348370370200241c8006a200241f0006a10850420022d00482105200c200241e1006a290000370300200b200241d9006a290000370300200a200241d1006a290000370300200220022900493703700240024020054101460d00200241286a41186a4200370300200241286a41106a420037030020094200370300200242003703280c010b200241286a41186a200c290300370300200241286a41106a200b2903003703002009200a290300370300200220022903703703280b200241086a41086a200241286a41086a290300370300200241086a41106a200241286a41106a290300370300200241086a41186a200241286a41186a290300370300200220022903283703082002410036025020024201370348024002404108102d2209450d0020024288808080800137024c20022009360248200942b81737000020094108411010312209450d0020024290808080800237024c200942c8013700082002200936024802404110200228025022056b41074b0d00200541086a22042005490d024110410174220a2004200a20044b1b22044100480d020240024041100d002004102d21090c010b200941102004103121090b2009450d012002200436024c200220093602480b2002200541086a360250200920056a42013700000240200228024c2204200228025022056b41074b0d00200541086a220a2005490d022004410174220b200a200b200a4b1b220a4100480d020240024020040d00200a102d21090c010b20092004200a103121090b2009450d012002200a36024c200220093602480b2007410820071b21032002200541086a360250200920056a42043700002008420020071b2208422088a72209200241c8006a1069200228024c21042002280250210a02402009450d002003200941286c6a210c200321090340024002402004200a6b4120490d00200a41206a2105200228024821070c010b200a41206a2205200a490d04200441017422072005200720054b1b220b4100480d040240024020040d00200b102d21070c010b20022802482004200b103121070b2007450d032002200b36024c20022007360248200b21040b2007200a6a220a41186a200941186a290000370000200a41106a200941106a290000370000200a41086a200941086a29000037000020022005360250200a2009290000370000200941206a29030021060240200420056b41074b0d00200541086a220a2005490d042004410174220b200a200b200a4b1b220a4100480d040240024020040d00200a102d21070c010b20072004200a103121070b2007450d032002200a36024c20022007360248200a21040b2002200541086a220a360250200720056a2006370000200c200941286a2209470d000b0b024002402004200a6b4120490d00200228024821090c010b200a41206a2209200a490d02200441017422052009200520094b1b22054100480d020240024020040d002005102d21090c010b200228024820042005103121090b2009450d012002200536024c20022009360248200521040b2009200a6a220541086a200241086a41086a290300370000200541106a200241086a41106a290300370000200541186a200241086a41186a2903003700002002200a41206a220736025020052002290308370000024020042007470d00200441016a22052004490d022004410174220b2005200b20054b1b22054100480d020240024020040d002005102d21090c010b200920042005103121090b2009450d012002200536024c200220093602480b200920076a41013a0000200a41216aad4220862009ad84210602402008a7450d002003102f0b20024190016a240020060f0b1036000b1038000b2b02017e017f10fc03210202404108102d22030d001036000b200320023700002003ad42808080808001840bfb0a04047f017e0a7f017e230041a0016b22022400200241f8006a41186a4200370300200241f8006a41106a22034200370300200241f8006a41086a220442003703002002420037037841fe86ca00ad4280808080a002841001220529000021062004200541086a290000370300200220063703782005102f419087ca00ad4280808080c00084100122052900002106200241d8006a41086a2207200541086a290000370300200220063703582005102f200320022903582206370300200241086a41086a2004290300370300200241086a41106a2006370300200241086a41186a2007290300370300200220022903783703082002412036022c2002200241086a360228200241306a200241086aad42808080808004841002107302400240024002400240200228023022080d00410021070c010b200228023421092002200241306a41086a280200360244200220083602402002200241c0006a10e6010240024020022802000d002002280204220a2002280244220441057622052005200a4b1b220b4105742205417f4c0d0302400240200b0d00410121070c010b2005102d2207450d050b02400240200a450d004100210c034020042103200241003a009801200c220d41016a210c41002104024002400240034020032004460d01200241f8006a20046a200228024022052d00003a00002002200541016a3602402002200441016a22053a0098012005210420054120470d000b200241d8006a41186a220e200241f8006a41186a290300370300200241d8006a41106a220f200241f8006a41106a290300370300200241d8006a41086a2210200241f8006a41086a29030037030020022002290378370358200b200d470d02200d4101742204200c2004200c4b1b220441ffffff3f712004470d0b2004410574220441004e0d010c0b0b200241003602440240200441ff0171450d00200241003a0098010b200b0d040c050b02400240200d0d002004102d21070c010b2007200d4105742004103121070b2007450d082004410576210b0b200320056b21042007200d4105746a220d2002290358370000200d41186a200e290300370000200d41106a200f290300370000200d41086a2010290300370000200c200a470d000b2002200320056b3602440b200aad422086200bad84210620070d020c010b2007102f0b4100210720024100360260200242013703582002410b36024c2002200241286a3602482002200241d8006a3602542002418c016a41013602002002420137027c200241b885c7003602782002200241c8006a36028801200241d4006a41d8dbc100200241f8006a103c1a20023502604220862002350258841008200228025c450d002002280258102f0b2009450d002008102f0b2006420020071b2206422088a72204410574220c4104722205417f4c0d002005102d2203450d012007410120071b210b20024100360280012002200536027c200220033602782004200241f8006a10690240024020040d002002280280012105200228027821090c010b410020022802800122056b210720022802782109200228027c2103200b2104034002400240200320076a411f4d0d00200321080c010b200541206a22082005490d052003410174220a2008200a20084b1b22084100480d050240024020030d002008102d21090c010b200920032008103121090b2009450d040b200920056a22032004290000370000200341186a200441186a290000370000200341106a200441106a290000370000200341086a200441086a290000370000200741606a2107200541206a210520082103200441206a2104200c41606a220c0d000b2002200836027c2002200536028001200220093602780b2005ad4220862009ad84211102402006a7450d00200b102f0b200241a0016a240020110f0b103d000b1036000b1038000bbe0605037f027e017f027e027f230041b0016b2202240041002103200241003a0040200041c8e1ca0020011b2104024002400240034020012003460d01200241206a20036a200420036a2d00003a00002002200341016a22003a00402000210320004120470d000b200241186a200241206a41186a22012903002205370300200241106a200241206a41106a22042903002206370300200241086a200241206a41086a22072903002208370300200220022903202209370300200241f0006a41186a22002005370300200241f0006a41106a220a2006370300200241f0006a41086a220b200837030020022009370370418de6c300ad4280808080e0008410012203290000210520024190016a41086a200341086a29000037030020022005370390012003102f41f0e8c600ad4280808080f00084100122032900002105200241a0016a41086a200341086a290000370300200220053703a0012003102f4120102d22030d010c020b0240200341ff0171450d00200241003a00400b200241346a4102360200200241fc006a410436020020024202370224200241b8c2c80036022020024104360274200241e0c4c80036027020024100360204200241c8e1ca003602002002200241f0006a36023020022002360278200241206a41c8c2c8001043000b20032002290370370000200341186a2000290300370000200341106a200a290300370000200341086a200b2903003700002003ad4280808080800484100322002900002105200041086a2900002106200041106a29000021082001200041186a2900003703002004200837030020072006370300200220053703202000102f2003102f41c000102d2203450d002003200229039001370000200320022903a00137001020032002290320370020200341086a20024190016a41086a290300370000200341186a200241a0016a41086a290300370000200341286a200241206a41086a290300370000200341306a200241306a290300370000200341386a200241206a41186a290300370000200241206a200310f602200241e8006a2802002100200229032021052003102f4104102d2203450d0020032000410020054201511b360000200241b0016a24002003ad4280808080c000840f0b1036000bf30e03057f047e017f230041d0016b22022400024020010d0041c8e1ca0021000b200220003602102002200136021441002103200241003a00782001417f6a2104024002400240024002400240034020012003460d01200241d8006a20036a200020036a22052d00003a00002002200541016a3602102002200341016a22053a0078200220043602142004417f6a21042005210320054120470d000b200241186a41086a200241d8006a41086a290300370300200241186a41106a200241d8006a41106a290300370300200241186a41186a200241d8006a41186a2903003703002002200229035837031841002103200241003a0078200120056b2106200020056a2100417f2101034020062003460d02200241d8006a20036a200020036a22052d00003a00002002200420036b3602142002200541016a3602102002200341016a22053a00782001417f6a21012005210320054120470d000b200241386a41086a200241d8006a41086a290300370300200241386a41106a200241d8006a41106a290300370300200241386a41186a200241d8006a41186a29030037030020022002290358370338200420056b220441016a4110490d022002200020056a220341106a3602102002200441716a220536021420054108490d0320032900002107200341086a29000021082002200441696a3602142002200341186a360210200341106a2900002109200241086a200241106a10e60120022802080d0520022802142205200228020c22034f0d040c050b0240200341ff0171450d00200241003a00780b200241ec006a4102360200200241ac016a41043602002002420237025c200241b8c2c800360258200241043602a401200241f8c4c8003602a0012002410036023c200241c8e1ca003602382002200241a0016a3602682002200241386a3602a801200241d8006a41c8c2c8001043000b0240200341ff0171450d00200241003a00780b200241ec006a4102360200200241ac016a41043602002002420237025c200241b8c2c800360258200241043602a401200241f8c4c8003602a0012002410036023c200241c8e1ca003602382002200241a0016a3602682002200241386a3602a801200241d8006a41c8c2c8001043000b200241ac016a4104360200200241ec006a41023602002002420237025c200241b8c2c800360258200241043602a401200241f8c4c8003602a0012002410036028401200241c8e1ca00360280012002200241a0016a360268200220024180016a3602a801200241d8006a41c8c2c8001043000b200241ac016a4104360200200241ec006a41023602002002420237025c200241b8c2c800360258200241043602a401200241f8c4c8003602a0012002410036028401200241c8e1ca00360280012002200241a0016a360268200220024180016a3602a801200241d8006a41c8c2c8001043000b0240024002402003417f4c0d000240024020030d00410121040c010b200310332204450d03200420022802102201200310e8061a2002200520036b3602142002200120036a3602100b2004450d03200241a0016a41186a200241186a41186a290300370300200241a0016a41106a200241186a41106a290300370300200241a0016a41086a200241186a41086a290300370300200220022903183703a001200241d8006a41186a200241386a41186a290300370300200241d8006a41106a200241386a41106a290300370300200241d8006a41086a200241386a41086a2903003703002002200229033837035820022003ad220a422086200a843702c401200220043602c00120024180016a200241a0016a200241d8006a200720082009200241c0016a108302024002402002280280014101460d002002418c016a280200210520024180016a41086a280200210020024180016a41106a2d0000210120022802840121040c010b41002104024020024194016a280200450d0020024190016a280200102f0b0b20024100360260200242013703584101102d2103024002402004450d002003450d04200341003a0000200242818080801037025c2002200336025820034101410210312203450d04200320013a0001200242828080802037025c200220033602582005200241d8006a106902400240200228025c2203200228026022016b2005490d00200228025821030c010b200120056a22062001490d042003410174220b2006200b20064b1b22064100480d040240024020030d002006102d21030c010b200228025820032006103121030b2003450d052002200636025c200220033602580b2002200120056a2206360260200320016a2004200510e8061a2006ad42208621070c010b2003450d03200341013a0000200242818080801037025c2002200336025842808080801021070b20072003ad84210702402000450d002004450d002004102f0b200241d0016a240020070f0b103d000b1038000b1036000b200241ac016a4104360200200241ec006a41023602002002420237025c200241b8c2c800360258200241043602a401200241f8c4c8003602a0012002410036028401200241c8e1ca00360280012002200241a0016a360268200220024180016a3602a801200241d8006a41c8c2c8001043000bb51003067f037e017f230041f0016b2202240041002103200241003a00a801200041c8e1ca0020011b2104024002400240024002400240024002400240034020012003460d0120024188016a20036a200420036a2d00003a00002002200341016a22003a00a8012000210320004120470d000b200241086a41086a20024188016a41086a290300370300200241086a41106a20024188016a41106a290300370300200241086a41186a20024188016a41186a290300370300200220022903880137030841002103200241003a00a801200420006a2104200120006b2101034020012003460d0220024188016a20036a200420036a2d00003a00002002200341016a22003a00a8012000210320004120470d000b200241286a41086a220320024188016a41086a290300370300200241286a41106a220020024188016a41106a290300370300200241286a41186a220120024188016a41186a22052903003703002002200229038801370328200241e8006a41186a200241086a41186a290300370300200241e8006a41106a200241086a41106a290300370300200241e8006a41086a200241086a41086a29030037030020022002290308370368200241c8006a41186a2001290300370300200241c8006a41106a2000290300370300200241c8006a41086a20032903003703002002200229032837034820024188016a200241e8006a10e80120022d00880122034102460d03410121062003450d02410121030c040b0240200341ff0171450d00200241003a00a8010b2002419c016a4102360200200241f4006a41043602002002420237028c01200241b8c2c800360288012002410436026c20024180c5c8003602682002410036024c200241c8e1ca003602482002200241e8006a360298012002200241c8006a36027020024188016a41c8c2c8001043000b0240200341ff0171450d00200241003a00a8010b2002419c016a4102360200200241f4006a41043602002002420237028c01200241b8c2c800360288012002410436026c20024180c5c8003602682002410036024c200241c8e1ca003602482002200241e8006a360298012002200241c8006a36027020024188016a41c8c2c8001043000b41012103200241b4016a2802004102460d01200241a8016a280200220141164d0d02200241a4016a280200210720052802002100200241c8006aad4280808080800484100322032900002108200341086a2900002109200341106a290000210a20024188016a41186a200341186a29000037030020024188016a41106a200a37030020024188016a41086a200937030020022008370388012003102f200241e0016a2001ad4220862000ad84200141696aad422086200041176aad84410120024188016aad428080808080048410101073200241e0016a41086a280200210120022802e001210420022802e401210b41002103024020070d000c020b2000102f0c010b41012103410021060b41012100024002400240024020030d00200141066a410220041b2200417f4c0d052000450d010b2000102d2205450d054100210720024100360290012002200036028c0120022005360288012003450d012002410136029001200541013a0000200228028c01210120022802900121000240200641ff01714101460d000240024020012000460d0020022802880121010c010b200041016a22012000490d08200041017422052001200520014b1b22054100480d080240024020000d002005102d21010c010b20022802880120002005103121010b2001450d072002200536028c01200220013602880120022802900121000b2002200041016a36029001200120006a41003a00000c030b0240024020012000460d0020022802880121010c010b200041016a22012000490d07200041017422052001200520014b1b22054100480d070240024020000d002005102d21010c010b20022802880120002005103121010b2001450d062002200536028c01200220013602880120022802900121000b2002200041016a36029001200120006a41013a00000c020b200241003602900120024201370388014101102d2205450d042002410136028c01200220053602880120022802900121070b2002200741016a36029001200520076a41003a0000200228028c0121052002280290012100024020040d000240024020052000460d0020022802880121010c010b200041016a22012000490d06200041017422052001200520014b1b22054100480d060240024020000d002005102d21010c010b20022802880120002005103121010b2001450d052002200536028c01200220013602880120022802900121000b2002200041016a36029001200120006a41003a00000c010b0240024020052000460d0020022802880121050c010b200041016a22052000490d05200041017422072005200720054b1b22074100480d050240024020000d002007102d21050c010b20022802880120002007103121050b2005450d042002200736028c01200220053602880120022802900121000b2002200041016a36029001200520006a41013a0000200120024188016a106902400240200228028c01220520022802900122006b2001490d0020022802880121050c010b200020016a22072000490d05200541017422002007200020074b1b22004100480d050240024020050d002000102d21050c010b20022802880120052000103121050b2005450d042002200036028c01200220053602880120022802900121000b2002200020016a36029001200520006a2004200110e8061a0b200235029001422086200235028801842108024020030d002004450d00200b450d002004102f0b200241f0016a240020080f0b41172001104b000b103d000b1036000b1038000ba00f04047f057e027f037e230041e0036b2202240041002103200241003a00b802200041c8e1ca0020011b2104024002400240024002400240034020012003460d0120024198026a20036a200420036a2d00003a00002002200341016a22003a00b8022000210320004120470d000b200241e8006a41186a20024198026a41186a22052903002206370300200241e8006a41106a20024198026a41106a22042903002207370300200241e8006a41086a20024198026a41086a220329030022083703002002200229039802220937036820024188016a41186a200637030020024188016a41106a200737030020024188016a41086a20083703002002200937038801200241a8016a20024188016a10e8014101210020022d00a801417f6a41ff01714102490d05200241a8016a41106a2903002109200241a8016a41086a2201290300210a200241cc016a280200210b200241d0016a280200210c420021062005420037030020044200370300200342003703002002420037039802418de6c300ad4280808080e000841001220029000021072003200041086a29000037030020022007370398022000102f419ce6c300ad4280808080e00084100122002900002107200241c0036a41086a2205200041086a290000370300200220073703c0032000102f200420022903c0032207370300200241f0026a41086a2003290300370300200241f0026a41106a2007370300200241f0026a41186a200529030037030020022002290398023703f002200241e0006a200241f0026a412010950141002002280264410020022802601b2203200c6b2200200020034b1b2204450d0420024198026a20024188016a108d0242002106200241d0006a200229039802220820024198026a41086a290300220d428080a8ec85afd1b101420010ee064200200bad22072002290350220e7d220f200f2007564200200241d0006a41086a2903002007200e54ad7c7d22074200522007501b22001b220e4200200720001b220784500d04420121062008428080d287e2bc2d544100200d501b0d04200241c0006a2004ad4200200e200710ed06200241306a2002290340200241c0006a41086a290300428080e983b1de16420010ed062008428080aef89dc3527c2206200a200a2006562009200d2006200854ad7c427f7c22065620092006511b22001b22072002290330220a2007200a542006200920001b2207200241306a41086a29030022095420072009511b22001b22062007200920001b220784500d0120024198026a20024188016a108d0220022903b802220a4200200820067d22092009200856200d20077d2008200654ad7d2208200d562008200d511b22041b220e58200241c0026a29030022094200200820041b220858200920085122041bad210d200a200e56200920085620041b0d032000450d020c030b0240200341ff0171450d00200241003a00b8020b200241ac026a4102360200200241b4016a41043602002002420237029c02200241b8c2c80036029802200241043602ac0120024194c5c8003602a801200241003602f402200241c8e1ca003602f0022002200241a8016a3602a8022002200241f0026a3602b00120024198026a41c8c2c8001043000b4201210d20000d010b20022006370380022002200737038802420321060c010b20024190026a200737030020022006370388022002200d37038002420221060b200241f0026a200141d00010e8061a200241c0036a41106a20024180026a41086a290300370300200241c0036a41186a20024180026a41106a290300370300200220063703c00320022002290380023703c80320024198026a20024188016a200241f0026a2003200241c0036a109f024101210141012100024020022d009802417f6a41ff01714102490d0020024198026a41106a290300210720024198026a41086a2903002109200241b4026a280200210420024198026a41186a280200210c200241bc026a3502002106200241f0026a20024188016a108d02200241206a20022903f0022208200241f0026a41086a290300220d428080a8ec85afd1b101420010ee06200241106a420020062002290320220a7d220e200e2006564200200241206a41086a2903002006200a54ad7c7d22064200522006501b22001b220a4200200620001b2206428080e983b1de16420010ed060240200a200684500d0002402008428080d287e2bc2d544100200d501b0d0020022008428080aef89dc3527c2206200920092006562007200d2006200854ad7c427f7c22065620072006511b22001b2006200720001b2002290310200241106a41086a29030010ee0620022903002206a7417f2006428080808010544100200241086a290300501b1b210002402004450d00200c102f0b200020036a210c41002101410021000c030b4196a7c400419b0141b4a8c4001055000b410021002004450d00200c102f0b0b02404101102d2203450d000240024002402000450d00200341013a000020034101410210312203450d03200341013a00010c010b200341003a000020034101410210312103024020014101460d002003450d03200341003a000120034102410610312203450d032003200c3600024280808080e00021060c020b2003450d02200341013a00010b42808080802021060b200241e0036a240020062003ad840f0b1036000bb00402027f027e230041c0076b22022400024002402001450d00200220003602100c010b200241c8e1ca003602100b20022001360214200241f8036a200241106a10a40402400240024020022903e0044203510d00200241186a200241f8036a41c80310e8061a200228021422014104490d0120022802102200280000210320022001417c6a3602142002200041046a360210200241f8036a200241186a41c80310e8061a200241e0036a20024190056a220110f1022002200320022903e0032204a722002004422888a74200420010f004200241086a29030021042002290300210520022d00e40321032001108e014104102d2201450d022001200036000020014104410810312201450d02200120033a000420014108411510312201450d02200120053700052001410d6a2004370000200241c0076a24002001ad4280808080d002840f0b200241ec036a41043602002002412c6a41023602002002420237021c200241b8c2c800360218200241043602e403200241acc5c8003602e003200241003602f403200241c8e1ca003602f0032002200241e0036a3602282002200241f0036a3602e803200241186a41c8c2c8001043000b200241ec036a41043602002002418c046a4102360200200242023702fc03200241b8c2c8003602f803200241043602e403200241acc5c8003602e003200241003602f403200241c8e1ca003602f0032002200241e0036a360288042002200241f0036a3602e803200241f8036a41c8c2c8001043000b1036000bb11305037f017e027f037e037f230041a0026b220224000240024020010d002002200136020c200241c8e1ca003602080c010b20022001417f6a36020c2002200041016a36020820002d0000220041014b0d00410021010240024002400240024020000e020100010b2002200241086a10e60120022802000d04200228020c220320022802042200490d042000417f4c0d010240024020000d00410121010c010b200010332201450d03200120022802082204200010e8061a2002200320006b36020c2002200420006a3602080b2001450d042000ad220542208620058421050b0240024020010d00410021040c010b2005422088a72200417f4c0d01024020000d00410121040c010b2000102d2204450d0220042001200010e8061a0b200241f0016a41086a2000360200200220003602f401200220043602f001200241e7e485f3063602d001200241106a200241f0016a10f40120022802142106200241d0016a200235021842208620022802102207ad84102222032900002108200341086a2900002109200341106a290000210a200241106a41186a220b200341186a290000370300200241106a41106a220c200a370300200241106a41086a220d2009370300200220083703102003102f20024190016a41186a200b29030037030020024190016a41106a200c29030037030020024190016a41086a200d290300370300200220022903103703900102402006450d002007102f0b02402004450d002000450d002004102f0b0240024020010d00410021040c010b2005422088a72200417f4c0d01024020000d00410121040c010b2000102d2204450d0220042001200010e8061a0b200241f0016a41086a2000360200200220003602f401200220043602f001200241e2c289ab063602d001200241106a200241f0016a10f40120022802142106200241d0016a200235021842208620022802102207ad84102322032900002108200341086a2900002109200341106a290000210a200241106a41186a220b200341186a290000370300200241106a41106a220c200a370300200241106a41086a220d2009370300200220083703102003102f200241b0016a41186a200b290300370300200241b0016a41106a200c290300370300200241b0016a41086a200d290300370300200220022903103703b00102402006450d002007102f0b02402004450d002000450d002004102f0b0240024020010d00410021040c010b2005422088a72200417f4c0d01024020000d00410121040c010b2000102d2204450d0220042001200010e8061a0b200241f0016a41086a2000360200200220003602f401200220043602f001200241e9dabdf30636029002200241106a200241f0016a10f4012002280214210620024190026a200235021842208620022802102207ad84102322032900002108200341086a2900002109200341106a290000210a200241106a41186a220b200341186a290000370300200241106a41106a220c200a370300200241106a41086a220d2009370300200220083703102003102f200241d0016a41186a200b290300370300200241d0016a41106a200c290300370300200241d0016a41086a200d290300370300200220022903103703d00102402006450d002007102f0b02402004450d002000450d002004102f0b0240024020010d00410021040c010b2005422088a72200417f4c0d01024020000d00410121040c010b2000102d2204450d0220042001200010e8061a0b20024190026a41086a200036020020022000360294022002200436029002200241e1ea91cb0636029c02200241106a20024190026a10f401200228021421062002419c026a200235021842208620022802102207ad84102322032900002108200341086a2900002109200341106a290000210a200241106a41186a220b200341186a290000370300200241106a41106a220c200a370300200241106a41086a220d2009370300200220083703102003102f200241f0016a41186a200b290300370300200241f0016a41106a200c290300370300200241f0016a41086a200d290300370300200220022903103703f00102402006450d002007102f0b02402004450d002000450d002004102f0b200241106a41086a220320024190016a41086a290300370300200241106a41106a220420024190016a41106a290300370300200241106a41186a220620024190016a41186a290300370300200241386a200241b0016a41086a290300370300200241c0006a200241b0016a41106a290300370300200241c8006a200241b0016a41186a2903003703002002200229039001370310200220022903b001370330200241e8006a200241d0016a41186a290300370300200241e0006a200241d0016a41106a290300370300200241d8006a200241d0016a41086a290300370300200241f8006a200241f0016a41086a29030037030020024180016a200241f0016a41106a29030037030020024188016a200241f0016a41186a290300370300200220022903d001370350200220022903f0013703704120102d2200450d0120002002290310370000200041186a2006290300370000200041106a2004290300370000200041086a20032903003700002000412041c00010312200450d012000200241106a41206a2203290000370020200041386a200341186a290000370000200041306a200341106a290000370000200041286a200341086a290000370000200041c00041800110312200450d012000200241106a41c0006a22032900003700402000200241f0006a2204290000370060200041d8006a200341186a290000370000200041d0006a200341106a290000370000200041c8006a200341086a290000370000200041e8006a200441086a290000370000200041f0006a200441106a290000370000200041f8006a200441186a29000037000002402001450d002005a7450d002001102f0b418401102d2201450d01200242840137021420022001360210418001200241106a10690240024020022802142201200228021822036b418001490d0020034180016a2104200228021021010c010b20034180016a22042003490d03200141017422062004200620044b1b22064100480d030240024020010d002006102d21010c010b200228021020012006103121010b2001450d0220022006360214200220013602100b200120036a200041800110e8061a2000102f200241a0026a24002004ad4220862001ad840f0b103d000b1036000b1038000b200241fc016a4104360200200241246a410236020020024202370214200241b8c2c800360210200241043602f401200241c0c5c8003602f001200241003602d401200241c8e1ca003602d0012002200241f0016a3602202002200241d0016a3602f801200241106a41c8c2c8001043000b890803037f017e057f230041b0026b22022400024002402001450d00200220003602080c010b200241c8e1ca003602080b2002200136020c2002200241086a10e60102400240024020022802000d00200228020c220320022802042201490d0002402001417f4c0d000240024020010d00410121000c010b200110332200450d03200020022802082204200110e8061a2002200320016b36020c2002200420016a3602080b2000450d0120022001ad220542208620058422054220883e02ac02200220003602a802200241a0016a200241a8026a10ee020240024020022d00a0014101470d00200241003602100c010b200241206a200241a0016a41017241800110e8061a200241a0016a200241206a41800110e8061a200241106a200241a0016a10ed020b02402005a7450d002000102f0b02400240200228021022060d00410121000c010b200241186a2802004104744105722200417f4c0d010b2000102d2201450d02200241013602a801200220003602a401200220013602a0010240024020060d00200141003a00002001ad4280808080108421050c010b200141013a0000200241106a41086a2802002201200241a0016a10690240024020010d0020023502a80142208620023502a0018421050c010b200620014104746a210720062103034020032802002108200341086a2802002209200241a0016a10690240024020022802a401220020022802a801220a6b2009490d0020022802a00121010c010b200a20096a2201200a490d07200041017422042001200420014b1b22044100480d070240024020000d002004102d21010c010b20022802a00120002004103121010b2001450d06200220043602a401200220013602a001200421000b2002200a20096a22043602a8012001200a6a2008200910e8061a0240200020046b41034b0d00200441046a22092004490d072000410174220a2009200a20094b1b22094100480d070240024020000d002009102d21010c010b200120002009103121010b2001450d06200220093602a401200220013602a0010b2002200441046a22003602a801200120046a2003410c6a280000360000200341106a22032007470d000b2000ad4220862001ad8421052006450d010b0240200241186a2802002201450d00200141047421002006210103400240200141046a280200450d002001280200102f0b200141106a2101200041706a22000d000b0b2002280214450d002006102f0b200241b0026a240020050f0b103d000b2002412c6a4104360200200241b4016a4102360200200242023702a401200241b8c2c8003602a00120024104360224200241e0c5c80036022020024100360214200241c8e1ca003602102002200241206a3602b0012002200241106a360228200241a0016a41c8c2c8001043000b1036000b1038000b02000ba20405027f017e027f027e027f230041d0006b2203240041eba1ca00ad4280808080f00084100122042900002105200341086a41086a2206200441086a290000370300200320053703082004102f4183cbc800ad4280808080b00284100122042900002105200341186a41086a2207200441086a290000370300200320053703182004102f2003200136024c200341cc006aad4280808080c00084100322042900002105200441086a2900002108200441106a2900002109200341286a41186a2201200441186a290000370300200341286a41106a220a2009370300200341286a41086a220b2008370300200320053703282004102f024041c000102d2204450d00200420032903083700002004200329031837001020042003290328370020200441086a2006290300370000200441186a2007290300370000200441286a200b290300370000200441306a200a290300370000200441386a20012903003700004120102d2201450d0020012002290000370000200141186a200241186a290000370000200141106a200241106a290000370000200141086a200241086a2900003700002001ad4280808080800484100122022900002105200341286a41086a2206200241086a290000370300200320053703282002102f2001102f200441c00041800110312204450d0020042003290328370040200441c8006a200629030037000020004280818080800a37020420002004360200200341d0006a24000f0b1036000ba20405027f017e027f027e027f230041d0006b2203240041eba1ca00ad4280808080f00084100122042900002105200341086a41086a2206200441086a290000370300200320053703082004102f4196cbc800ad4280808080b00284100122042900002105200341186a41086a2207200441086a290000370300200320053703182004102f2003200136024c200341cc006aad4280808080c00084100322042900002105200441086a2900002108200441106a2900002109200341286a41186a2201200441186a290000370300200341286a41106a220a2009370300200341286a41086a220b2008370300200320053703282004102f024041c000102d2204450d00200420032903083700002004200329031837001020042003290328370020200441086a2006290300370000200441186a2007290300370000200441286a200b290300370000200441306a200a290300370000200441386a20012903003700004120102d2201450d0020012002290000370000200141186a200241186a290000370000200141106a200241106a290000370000200141086a200241086a2900003700002001ad4280808080800484100122022900002105200341286a41086a2206200241086a290000370300200320053703282002102f2001102f200441c00041800110312204450d0020042003290328370040200441c8006a200629030037000020004280818080800a37020420002004360200200341d0006a24000f0b1036000bbe1203027f037e047f230041e0036b2201240041eba1ca00ad4280808080f00084100122022900002103200141d0006a41086a200241086a290000370300200120033703502002102f41a5c6c800ad4280808080a0018410012202290000210320014190026a41086a200241086a29000037030020012003370390022002102f024002400240024002404120102d2202450d0020022000290000370000200241186a200041186a290000370000200241106a200041106a290000370000200241086a200041086a2900003700002002ad4280808080800484100322002900002103200041086a2900002104200041106a2900002105200141d8026a41186a2206200041186a290000370300200141d8026a41106a22072005370300200141d8026a41086a2004370300200120033703d8022000102f2002102f41c000102d2202450d00200220012903503700002002200129039002370010200220012903d802370020200241086a200141d0006a41086a290300370000200241186a20014190026a41086a290300370000200241286a200141d8026a41086a290300370000200241306a2007290300370000200241386a2006290300370000200141d8026a200241c000109b04024020012d00dc02220041024622060d002002ad428080808080088410050b2001410d6a200141d8026a41057241c30010e8061a200141d0006a2001410d6a41c30010e8061a20060d04200120003a00980120014198016a410172200141d0006a41c10010e8062108200141ba016a21060240024020012d00b90122074101460d00200141003602e0010c010b200141e0016a2006109a040b02400240024020004101460d00200141003602f0010c010b200141f0016a2008109a0420012802f0010d010b024020074101460d0041eba1ca00ad4280808080f00084100122002900002103200141b0036a41086a2206200041086a290000370300200120033703b0032000102f4195c6c800ad428080808080028410012200290000210320014190026a41086a2207200041086a29000037030020012003370390022000102f200141d8026a41086a2006290300370300200141f0026a2007290300370300200120012903b0033703d80220012001290390023703e80220014190026a200141d8026a1088012001350298024220862001280290022200ad841005200128029402450d042000102f0c040b41eba1ca00ad4280808080f00084100122002900002103200141b0036a41086a2207200041086a290000370300200120033703b0032000102f4195c6c800ad428080808080028410012200290000210320014190026a41086a2208200041086a29000037030020012003370390022000102f200141d8026a41086a2007290300370300200141d8026a41186a2008290300370300200120012903b0033703d80220012001290390023703e80220014190026a200141d8026a108801200128029002210720013502980221034120102d2200450d0120002006290000370000200041186a200641186a290000370000200041106a200641106a290000370000200041086a200641086a29000037000020034220862007ad842000ad428080808080048410042000102f200128029402450d032007102f0c030b20014180026a41086a200141f0016a41086a2802002200360200200120012903f00122033703800220014190026a2003a722072000109b04024020012d0094024102470d00200141003602a803200142013703a003200141b0036a41146a4129360200200141bc036a410b360200200141073602cc03200141eba1ca003602c8032001410b3602b4032001410a3602d403200141a5c6c8003602d003200120014180026a3602c0032001200141d0036a3602b8032001200141c8036a3602b0032001200141a0036a3602dc03200141d8026a41146a4103360200200142033702dc022001419090c4003602d8022001200141b0036a3602e802200141dc036a41d8dbc100200141d8026a103c1a20013502a80342208620013502a00384100820012802a403450d0220012802a003102f0c020b200141d8026a20014190026a41c80010e8061a2001419d036a200141b9016a220641206a2d00003a000020014195036a200641186a2900003700002001418d036a200641106a29000037000020014185036a200641086a290000370000200141fd026a2006290000370000200141003602b803200142013703b003200141d8026a200141b0036a109502200141d8026a410472200141b0036a10ce0220012802b40321062000ad4220862007ad8420013502b80342208620012802b0032200ad8410042006450d012000102f0c010b1036000b0240200128028402450d00200128028002102f0b410121060c010b410021060b0240024020012802e00122000d00410021070c010b20014180026a41086a200141e0016a41086a2802002207360200200120012903e00122033703800220014190026a2003a722082007109b040240024020012d0094024102470d00200141003602a803200142013703a003200141b0036a41146a4129360200200141bc036a410b360200200141073602cc03200141eba1ca003602c8032001410b3602b4032001410a3602d403200141a5c6c8003602d003200120014180026a3602c0032001200141d0036a3602b8032001200141c8036a3602b0032001200141a0036a3602dc03200141d8026a41146a4103360200200142033702dc02200141b48fc4003602d8022001200141b0036a3602e802200141dc036a41d8dbc100200141d8026a103c1a20013502a80342208620013502a00384100820012802a403450d0120012802a003102f0c010b200141d8026a20014190026a41c80010e8061a200141fc026a200141b8016a2d00003a0000200141f4026a200141b0016a290300370200200141ec026a200141a8016a290300370200200141e4026a20014198016a41086a29030037020020012001290398013702dc02200141003602b803200142013703b003200141d8026a200141b0036a109502200141d8026a410472200141b0036a10ce0220012802b40321092007ad4220862008ad8420013502b80342208620012802b0032207ad8410042009450d002007102f0b0240200128028402450d00200128028002102f0b410121070b0240200620012802f001220845720d0020012802f401450d002008102f0b2007200045720d0020012802e401450d002000102f0b2002102f200141e0036a24000bf11105027f017e027f037e047f230041f0036b2201240041eba1ca00ad4280808080f0008410012202290000210320014180026a41086a200241086a29000037030020012003370380022002102f418bc6c800ad4280808080a0018410012202290008210320022800042104200228000021052002102f024002400240024002404120102d2202450d0020022000290000370000200241186a200041186a290000370000200241106a200041106a290000370000200241086a200041086a2900003700002002ad4280808080800484100322002900002106200041086a2900002107200041106a2900002108200141d8026a41186a2209200041186a290000370300200141d8026a41106a220a2008370300200141d8026a41086a2007370300200120063703d8022000102f2002102f41c000102d2202450d002002200129038002370000200220033700182002200436001420022005360010200220012903d802370020200241086a20014180026a41086a290300370000200241286a200141d8026a41086a290300370000200241306a200a290300370000200241386a2009290300370000200141d8026a200241c000109804024020012d00e802220041024622040d002002ad428080808080088410050b20012802dc02210520012802d80221092001200141ec026a41c40010e806220141c4006a200141c40010e8061a024020040d0020014188016a200141c4006a41c20010e8061a200141aa016a21040240024020012d00a901220a4101460d00200141003602d0010c010b200141d0016a20041097040b02400240024020012d0088014101460d00200141003602e0010c010b200141e0016a20014188016a41017210970420012802e0010d010b0240200a4101460d0041eba1ca00ad4280808080f00084100122042900002103200141c0036a41086a220a200441086a290000370300200120033703c0032004102f41fbc5c800ad428080808080028410012204290000210320014180026a41086a220b200441086a29000037030020012003370380022004102f200141d8026a41086a200a290300370300200141f0026a200b290300370300200120012903c0033703d80220012001290380023703e80220014180026a200141d8026a1088012001350288024220862001280280022204ad841005200128028402450d052004102f0c050b41eba1ca00ad4280808080f000841001220a2900002103200141c0036a41086a220b200a41086a290000370300200120033703c003200a102f41fbc5c800ad42808080808002841001220a290000210320014180026a41086a220c200a41086a2900003703002001200337038002200a102f200141d8026a41086a200b290300370300200141d8026a41186a200c290300370300200120012903c0033703d80220012001290380023703e80220014180026a200141d8026a108801200128028002210b20013502880221034120102d220a450d02200a2004290000370000200a41186a200441186a290000370000200a41106a200441106a290000370000200a41086a200441086a2900003700002003422086200bad84200aad42808080808004841004200a102f200128028402450d04200b102f0c040b200141f0016a41086a200141e0016a41086a2802002204360200200120012903e00122033703f00120014180026a2003a7220b2004109804024020012d0090024102460d00200141d8026a20014180026a41d80010e8061a200141ad036a200141a9016a220a41206a2d00003a0000200141a5036a200a41186a2900003700002001419d036a200a41106a29000037000020014195036a200a41086a2900003700002001418d036a200a290000370000200120043602c4032001200b3602c003200141d8026a200141c0036a10ea0520012802dc02450d0320012802d802102f0c030b200141003602b803200142013703b003200141c0036a41146a4129360200200141cc036a410b360200200141073602dc03200141eba1ca003602d8032001410b3602c4032001410a3602e4032001418bc6c8003602e0032001200141f0016a3602d0032001200141e0036a3602c8032001200141d8036a3602c0032001200141b0036a3602ec03200141d8026a41146a4103360200200142033702dc022001419090c4003602d8022001200141c0036a3602e802200141ec036a41d8dbc100200141d8026a103c1a20013502b80342208620013502b00384100820012802b403450d0220012802b003102f0c020b0c040b1036000b024020012802f401450d0020012802f001102f0b4101210a0c010b4100210a0b0240024020012802d00122040d004100210b0c010b200141f0016a41086a200141d0016a41086a280200220b360200200120012903d00122033703f00120014180026a2003a7220c200b1098040240024020012d0090024102460d00200141d8026a20014180026a41d80010e8061a2001418c036a200141a8016a2d00003a000020014184036a200141a0016a290300370200200141fc026a20014198016a290300370200200141f4026a20014188016a41086a29030037020020012001290388013702ec022001200b3602c4032001200c3602c003200141d8026a200141c0036a10ea0520012802dc02450d0120012802d802102f0c010b200141003602b803200142013703b003200141c0036a41146a4129360200200141cc036a410b360200200141073602dc03200141eba1ca003602d8032001410b3602c4032001410a3602e4032001418bc6c8003602e0032001200141f0016a3602d0032001200141e0036a3602c8032001200141d8036a3602c0032001200141b0036a3602ec03200141d8026a41146a4103360200200142033702dc02200141b48fc4003602d8022001200141c0036a3602e802200141ec036a41d8dbc100200141d8026a103c1a20013502b80342208620013502b00384100820012802b403450d0020012802b003102f0b024020012802f401450d0020012802f001102f0b4101210b0b0240200a20012802e001220c45720d0020012802e401450d00200c102f0b0240200b200445720d0020012802d401450d002004102f0b20054521040b2002102f024020004102460d0020044101710d002009102f0b200141f0036a24000b800501087f230041106b220224002002410036020820024201370300200028020021032000280208220420021069024002400240024020040d0020022802042105200228020821060c010b200441057421072002280204210520022802082104034002400240200520046b4120490d00200441206a2106200228020021080c010b200441206a22062004490d04200541017422082006200820064b1b22094100480d040240024020050d002009102d21080c010b200228020020052009103121080b2008450d032002200936020420022008360200200921050b200820046a220441086a200341086a290000370000200441106a200341106a290000370000200441186a200341186a290000370000200220063602082004200329000037000020062104200341206a2103200741606a22070d000b0b200028020c210702400240200520066b4104490d00200641046a2103200228020021040c010b200641046a22032006490d02200541017422042003200420034b1b22084100480d020240024020050d002008102d21040c010b200228020020052008103121040b2004450d012002200836020420022004360200200821050b20022003360208200420066a200736000020002d00102106024020052003470d00200341016a22052003490d02200341017422082005200820054b1b22054100480d020240024020030d002005102d21040c010b200420032005103121040b2004450d0120022005360204200220043602000b2002200341016a360208200420036a20063a0000200041146a200210ce02200228020421032001290200200235020842208620022802002204ad84100402402003450d002004102f0b200241106a24000f0b1036000b1038000b860403027f037e037f230041c0006b2202240041eba1ca00ad4280808080f00084100122032900002104200241086a200341086a290000370300200220043703002003102f41a9cbc800ad4280808080d00184100122032900002104200241106a41086a200341086a290000370300200220043703102003102f02404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100322012900002104200141086a2900002105200141106a2900002106200241206a41186a2207200141186a290000370300200241206a41106a22082006370300200241206a41086a2005370300200220043703202001102f2003102f41c000102d2203450d00200320022903003700002003200229031037001020032002290320370020200341086a200241086a290300370000200341186a200241106a41086a2201290300370000200341286a200241206a41086a2209290300370000200341306a2008290300370000200341386a2007290300370000200241206a2003109c0520012009280200360200200220022903203703100240200228022c2207450d002000200229031037020020002002290330370210200041086a20012802003602000b2000200736020c2003102f200241c0006a24000f0b1036000b960603027f037e047f230041c0006b2202240041eba1ca00ad4280808080f00084100122032900002104200241086a200341086a290000370300200220043703002003102f41a9cbc800ad4280808080d00184100122032900002104200241106a41086a200341086a290000370300200220043703102003102f024002404120102d2203450d0020032000290000370000200341186a200041186a290000370000200341106a200041106a290000370000200341086a200041086a2900003700002003ad4280808080800484100322002900002104200041086a2900002105200041106a2900002106200241206a41186a2207200041186a290000370300200241206a41106a22082006370300200241206a41086a2005370300200220043703202000102f2003102f41c000102d2203450d00200320022903003700002003200229031037001020032002290320370020200341086a200241086a290300370000200341186a200241106a41086a290300370000200341286a200241206a41086a290300370000200341306a2008290300370000200341386a20072903003700002002410036022820024201370320200128020021074104102d2200450d002000200736000020024284808080c000370224200220003602202001280204210720004104410810312200450d0020002007360004200242888080808001370224200220003602202001280208210720004108411010312200450d00200020073600082002410c3602282002411036022420022000360220200128020c2109200141146a2802002201200241206a10690240024020022802242207200228022822006b20014102742208490d00200228022021010c010b200020086a22012000490d022007410174220a2001200a20014b1b220a4100480d020240024020070d00200a102d21010c010b20022802202007200a103121010b2001450d012002200a36022420022001360220200a21070b200120006a2009200810e8061a2003ad4280808080800884200020086aad4220862001ad84100402402007450d002001102f0b2003102f200241c0006a24000f0b1036000b1038000be80302027f037e230041c0006b2201240041eba1ca00ad4280808080f00084100122022900002103200141086a200241086a290000370300200120033703002002102f41b6cbc800ad4280808080900184100122022900002103200141106a41086a200241086a290000370300200120033703102002102f02404104102d2202450d0020024104412010312202450d0020022000290000370000200241186a200041186a290000370000200241106a200041106a290000370000200241086a200041086a290000370000200028022021002002412041c00010312202450d00200220003600202002ad4280808080c00484100322002900002103200041086a2900002104200041106a2900002105200141206a41186a200041186a290000370300200141206a41106a2005370300200141206a41086a2004370300200120033703202000102f2002102f41c000102d2200450d00200020012903003700002000200129031037001020002001290320370020200041086a200141086a290300370000200041186a200141106a41086a290300370000200041286a200141206a41086a290300370000200041306a200141306a290300370000200041386a200141206a41186a2903003700002000ad428080808080088410052000102f200141c0006a24000f0b1036000bab0b05027f027e027f047e037f230041d0006b22012400200141286a200010bd03200135023042208620012802282202ad8410130240200128022c450d002002102f0b200141286a200010c003200135023042208620012802282202ad8410130240200128022c450d002002102f0b200141286a200010c203200135023042208620012802282202ad8410130240200128022c450d002002102f0b41eba1ca00ad4280808080f000842203100122022900002104200141086a41086a2205200241086a290000370300200120043703082002102f4197cfc800ad4280808080b00284100122022900002104200141186a41086a2206200241086a290000370300200120043703182002102f2001200036024c200141cc006aad22044280808080c000842207100322022900002108200241086a2900002109200241106a290000210a200141286a41186a220b200241186a290000370300200141286a41106a220c200a370300200141286a41086a220d2009370300200120083703282002102f024041c000102d2202450d00200220012903083700002002200129031837001020022001290328370020200241086a2005290300370000200241186a2006290300370000200241286a200d290300370000200241306a200c290300370000200241386a200b2903003700002002ad428080808080088410052002102f20031001220229000021032005200241086a290000370300200120033703082002102f41e5cac800ad42808080808002841001220229000021032006200241086a290000370300200120033703182002102f2001200036024c2007100322022900002103200241086a2900002107200241106a2900002108200b200241186a290000370300200c2008370300200d2007370300200120033703282002102f41c000102d2202450d00200220012903083700002002200129031837001020022001290328370020200241086a200141086a41086a2205290300370000200241186a200141186a41086a2206290300370000200241286a200141286a41086a220b290300370000200241306a200141286a41106a220c290300370000200241386a200141286a41186a220d2903003700002002ad428080808080088410052002102f41eba1ca00ad4280808080f0008422031001220229000021072005200241086a290000370300200120073703082002102f41f5cac800ad4280808080e001841001220229000021072006200241086a290000370300200120073703182002102f2001200036024c20044280808080c000842204100322022900002107200241086a2900002108200241106a2900002109200d200241186a290000370300200c2009370300200b2008370300200120073703282002102f41c000102d2202450d00200220012903083700002002200129031837001020022001290328370020200241086a2005290300370000200241186a2006290300370000200241286a200b290300370000200241306a200c290300370000200241386a200d2903003700002002ad428080808080088410052002102f20031001220229000021032005200241086a290000370300200120033703082002102f41dca0ca00ad4280808080d002841001220229000021032006200241086a290000370300200120033703182002102f2001200036024c2004100322022900002103200241086a2900002104200241106a2900002107200d200241186a290000370300200c2007370300200b2004370300200120033703282002102f41c000102d2202450d00200220012903083700002002200129031837001020022001290328370020200241086a200141086a41086a290300370000200241186a200141186a41086a290300370000200241286a200141286a41086a290300370000200241306a200141386a290300370000200241386a200141286a41186a2903003700002002ad428080808080088410052002102f200141d0006a24000f0b1036000b8a0504017f027e037f027e230041c0016b220224002002200110b50302400240024020022d00004101460d0042002103420021040c010b20024180016a41186a2205200241196a29000037030020024180016a41106a2206200241116a29000037030020024180016a41086a2207200241096a290000370300200220022900013703800141eba1ca00ad4280808080f00084100122012900002103200241a0016a41086a200141086a290000370300200220033703a0012001102f41a7cac800ad4280808080e00084100122012900002103200241b0016a41086a200141086a290000370300200220033703b0012001102f4120102d2201450d012001200229038001370000200141186a2005290300370000200141106a2006290300370000200141086a20072903003700002001ad4280808080800484100322052900002103200541086a2900002104200541106a2900002108200241286a41186a200541186a290000370300200241286a41106a2008370300200241286a41086a2004370300200220033703282005102f2001102f41c000102d2201450d01200120022903a001370000200120022903b00137001020012002290328370020200141086a200241a0016a41086a290300370000200141186a200241b0016a41086a290300370000200141286a200241286a41086a290300370000200141306a200241386a290300370000200141386a200241286a41186a2205290300370000200241286a200110a0052005290300210820022903382109200228024c210620022802482107200228025421052001102f420021034200210420054102460d0002402006450d002007102f0b20092103200821040b2000200337030020002004370308200241c0016a24000f0b1036000be20603027f017e057f230041d0006b2203240041eba1ca00ad4280808080f00084100122042900002105200341086a200441086a290000370300200320053703002004102f41b6cac800ad4280808080b00184100122042900002105200341106a41086a200441086a290000370300200320053703102004102f2003200136022c20032003412c6aad4280808080c00084100622042900003703302004102f200341c4006a200341306a360200200341003a00482003200341306a41086a220636023c20032003412c6a3602402003200341306a360238200341206a200341386a106c0240024002400240024002402003280228220741206a2208417f4c0d0020032802202109024002402008450d002008102d2204450d062008410f4d0d012008210a0c050b4110210a4110102d21040c030b200841017422014110200141104b1b220a41004e0d010c050b103d000b20042008200a103121040b2004450d010b20042003290300370000200441086a200341086a29030037000002400240200a4170714110460d00200a21010c010b200a41017422014120200141204b1b22014100480d022004200a200110312204450d010b20042003290310370010200441186a200341106a41086a29030037000002400240200141606a2007490d002001210a0c010b2007415f4b0d022001410174220a2008200a20084b1b220a4100480d0220042001200a10312204450d010b200441206a2009200710e8061a02402003280224450d002009102f0b4120102d2201450d0020012002290000370000200141186a200241186a290000370000200141106a200241106a290000370000200141086a200241086a29000037000020032001ad4280808080800484100622022900003703302002102f200341c4006a200141206a360200200341003a0048200320013602402003200636023c2003200341306a360238200341106a200341386a106c2001102f2003280210210702400240200a20086b20032802182201490d00200120086a2102200a21090c010b200820016a22022008490d02200a41017422092002200920024b1b22094100480d022004200a200910312204450d010b200420086a2007200110e8061a02402003280214450d002007102f0b200020023602082000200936020420002004360200200341d0006a24000f0b1036000b1038000be20603027f017e057f230041d0006b2203240041eba1ca00ad4280808080f00084100122042900002105200341086a200441086a290000370300200320053703002004102f41c1cac800ad4280808080a00284100122042900002105200341106a41086a200441086a290000370300200320053703102004102f2003200136022c20032003412c6aad4280808080c00084100622042900003703302004102f200341c4006a200341306a360200200341003a00482003200341306a41086a220636023c20032003412c6a3602402003200341306a360238200341206a200341386a106c0240024002400240024002402003280228220741206a2208417f4c0d0020032802202109024002402008450d002008102d2204450d062008410f4d0d012008210a0c050b4110210a4110102d21040c030b200841017422014110200141104b1b220a41004e0d010c050b103d000b20042008200a103121040b2004450d010b20042003290300370000200441086a200341086a29030037000002400240200a4170714110460d00200a21010c010b200a41017422014120200141204b1b22014100480d022004200a200110312204450d010b20042003290310370010200441186a200341106a41086a29030037000002400240200141606a2007490d002001210a0c010b2007415f4b0d022001410174220a2008200a20084b1b220a4100480d0220042001200a10312204450d010b200441206a2009200710e8061a02402003280224450d002009102f0b4120102d2201450d0020012002290000370000200141186a200241186a290000370000200141106a200241106a290000370000200141086a200241086a29000037000020032001ad4280808080800484100622022900003703302002102f200341c4006a200141206a360200200341003a0048200320013602402003200636023c2003200341306a360238200341106a200341386a106c2001102f2003280210210702400240200a20086b20032802182201490d00200120086a2102200a21090c010b200820016a22022008490d02200a41017422092002200920024b1b22094100480d022004200a200910312204450d010b200420086a2007200110e8061a02402003280214450d002007102f0b200020023602082000200936020420002004360200200341d0006a24000f0b1036000b1038000be20603027f017e057f230041d0006b2203240041eba1ca00ad4280808080f00084100122042900002105200341086a200441086a290000370300200320053703002004102f41d3cac800ad4280808080a00284100122042900002105200341106a41086a200441086a290000370300200320053703102004102f2003200136022c20032003412c6aad4280808080c00084100622042900003703302004102f200341c4006a200341306a360200200341003a00482003200341306a41086a220636023c20032003412c6a3602402003200341306a360238200341206a200341386a106c0240024002400240024002402003280228220741206a2208417f4c0d0020032802202109024002402008450d002008102d2204450d062008410f4d0d012008210a0c050b4110210a4110102d21040c030b200841017422014110200141104b1b220a41004e0d010c050b103d000b20042008200a103121040b2004450d010b20042003290300370000200441086a200341086a29030037000002400240200a4170714110460d00200a21010c010b200a41017422014120200141204b1b22014100480d022004200a200110312204450d010b20042003290310370010200441186a200341106a41086a29030037000002400240200141606a2007490d002001210a0c010b2007415f4b0d022001410174220a2008200a20084b1b220a4100480d0220042001200a10312204450d010b200441206a2009200710e8061a02402003280224450d002009102f0b4120102d2201450d0020012002290000370000200141186a200241186a290000370000200141106a200241106a290000370000200141086a200241086a29000037000020032001ad4280808080800484100622022900003703302002102f200341c4006a200141206a360200200341003a0048200320013602402003200636023c2003200341306a360238200341106a200341386a106c2001102f2003280210210702400240200a20086b20032802182201490d00200120086a2102200a21090c010b200820016a22022008490d02200a41017422092002200920024b1b22094100480d022004200a200910312204450d010b200420086a2007200110e8061a02402003280214450d002007102f0b200020023602082000200936020420002004360200200341d0006a24000f0b1036000b1038000bc60501067f230041106b220224002002410036020820024201370300024002404120102d2203450d00200242a080808080043702042002200336020020032000290034370000200341086a2000413c6a290000370000200341106a200041c4006a290000370000200341186a200041cc006a2900003700002002200036020c2002410c6a200210c2022002200041106a36020c2002410c6a200210c20220002802202103200041286a28020022042002106902402004450d002003200441186c6a210403402002200336020c2002410c6a200210c202200341106a20021095022004200341186a2203470d000b0b02400240200028022c4101460d00024002402002280204220420022802082205460d00200228020021030c010b200541016a22032005490d04200541017422042003200420034b1b22044100480d040240024020050d002004102d21030c010b200228020020052004103121030b2003450d0320022004360204200220033602000b2002200541016a2200360208200320056a41003a00000c010b024002402002280204220420022802082205460d00200228020021030c010b200541016a22032005490d03200541017422042003200420034b1b22044100480d030240024020050d002004102d21030c010b200228020020052004103121030b2003450d0220022004360204200220033602000b2002200541016a2206360208200320056a41013a00002000280230210702400240200420066b4104490d00200541056a21000c010b200641046a22002006490d03200441017422052000200520004b1b22054100480d030240024020040d002005102d21030c010b200320042005103121030b2003450d022002200536020420022003360200200521040b20022000360208200320066a20073600000b20012902002000ad4220862003ad84100402402004450d002003102f0b200241106a24000f0b1036000b1038000b130020004115360204200041f0cfc8003602000bab0407047f017e017f017e017f017e037f230041d0006b22002400200041206a41186a22014200370300200041206a41106a22024200370300200041206a41086a220342003703002000420037032041eba1ca00ad4280808080f000842204100122052900002106200041c0006a41086a2207200541086a290000370300200020063703402005102f200320072903003703002000200029034037032041f1a0ca00ad428080808080018422081001220529000021062007200541086a290000370300200020063703402005102f200220002903402206370300200041086a22092003290300370300200041106a220a2006370300200041186a220b200729030037030020002000290320370300024002400240410020001081042205200541ff01714104461b41ff0171417f6a220541024b0d0020050e03010001010b2001420037030020024200370300200342003703002000420037032020041001220529000021062007200541086a290000370300200020063703402005102f200320072903003703002000200029034037032020081001220529000021062007200541086a290000370300200020063703402005102f20022000290340370000200241086a200729030037000020092003290300370300200a2002290300370300200b2001290300370300200020002903203703004101102d2207450d01200741013a00002000ad42808080808004842007ad4280808080108410042007102f0b200041d0006a24000f0b1036000b3400200041eba1ca0036020420004100360200200041146a411d360200200041106a41d495c900360200200041086a42073702000b5301017f02404110102d2202450d00200242003700082002420037000020024110412010312202450d0020024200370010200042a0808080800437020420002002360200200241186a42003700000f0b1036000b4b01027f230041106b2202240002404101102d22030d001036000b200341003a0000200041086a4101360200200241013602042002200336020020002002290300370200200241106a24000b9a0302047f017e230041206b2203240002400240200241d8006c4104722204417f4c0d002004102d2205450d0120034100360208200320043602042003200536020020022003106902402002450d002001200241d8006c6a210603402003200141386a4120108201200129030021072003200141086a290300370318200320073703102003200341106a411010820120012802202102200128022822042003106902402004450d002002200441306c6a21040340200320024120108201200241206a29030021072003200241286a290300370318200320073703102003200341106a41101082012004200241306a2202470d000b0b200141d8006a2105200128022c2102200141346a28020022042003106902402004450d00200441057421040340200320024120108201200241206a2102200441606a22040d000b0b200129031021072003200141186a290300370318200320073703102003200341106a41101082012005210120052006470d000b0b20002003290300370200200041086a200341086a280200360200200341206a24000f0b103d000b1036000b3301017f02404110102d22020d001036000b2002420037000820024200370000200042908080808002370204200020023602000b7b01027f230041106b22022400200241003602082002420137030002404104102d22030d001036000b2003410036000020024284808080c000370204200220033602004190bdc60041004100200210e501200041086a2002280208360200200020022903003702004190bdc6004100410010a302200241106a24000be30101047f230041106b220224002002410036020c02404101102d2203450d000240024002400240200228020c220441c000490d00200441808001490d012004418080808004490d02200341033a0000200228020c21044105210520034101410510312203450d04200320043600010c030b200320044102743a0000410121050c020b4102210520034101410210312203450d02200320044102744101723b00000c010b4104210520034101410410312203450d01200320044102744102723600000b200020053602082000200536020420002003360200200241106a24000f0b1036000bd40301077f230041c0006b22022400200241186a4200370300200241106a22034200370300200241086a4200370300200241286a22044100360200200242003703002002420837032020024100360238200242013703302002200236023c2002413c6a200241306a10c2022002200336023c2002413c6a200241306a10c2022002280220210320042802002204200241306a10690240024002402004450d00200441306c210503400240024020022802342206200228023822046b4120490d00200441206a2107200228023021060c010b200441206a22072004490d04200641017422082007200820074b1b22084100480d040240024020060d002008102d21060c010b200228023020062008103121060b2006450d0320022008360234200220063602300b200620046a220441086a200341186a290000370000200441106a200341206a290000370000200441186a200341286a290000370000200220073602382004200341106a2900003700002002200336023c2002413c6a200241306a10c202200341306a2103200541506a22050d000b0b20002002290330370200200041086a200241306a41086a28020036020002402002280224450d002002280220102f0b200241c0006a24000f0b1036000b1038000b2c01017f02404104102d22020d001036000b20004284808080c00037020420002002360200200241043600000b2d01017f02404104102d22020d001036000b20004284808080c00037020420002002360200200241d4003600000b130020004102360204200041accfc9003602000b2d01017f02404104102d22020d001036000b20004284808080c00037020420002002360200200241a0053600000b2c01017f02404104102d22020d001036000b20004284808080c00037020420002002360200200241063600000bb21307027f017e057f017e027f017e027f23004190016b2202240041eba1ca00ad4280808080f00084100122032900002104200241c8006a41086a200341086a290000370300200220043703482003102f41a1cac800ad4280808080e0008410012203290000210420024180016a41086a200341086a29000037030020022004370380012003102f02400240024002400240024002404120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100322052d00002106200241ef006a2207200541186a290000370000200241d8006a41106a2208200541116a290000370300200241d8006a41086a200541096a290000370300200220052900013703582005102f2003102f41c000102d2203450d00200320022903483700002003200229038001370010200320063a002020032002290358370021200341086a200241c8006a41086a290300370000200341186a20024180016a41086a290300370000200341296a200241d8006a41086a2209290300370000200341316a2008290300370000200341386a2007290000370000200241d8006a200341c00010ad02024020022d00582207450d002003ad428080808080088410050b200241286a41176a2205200241f1006a290000370000200241286a41106a2206200241ea006a290100370300200241286a41086a200241e2006a29010022043703002002200229015a220a37032820022d00592108200241d8006a41176a220b2005290000370000200241d8006a41106a220c2006290300370300200920043703002002200a37035820074101470d01200241086a41176a2207200b290000370000200241086a41106a2209200c290300370300200241086a41086a220b200241d8006a41086a220c290300370300200220022903583703082003102f2005200729000037000020062009290300370300200241286a41086a2205200b2903003703002002200229030837032841eba1ca00ad4280808080f00084100122032900002104200241c8006a41086a200341086a290000370300200220043703482003102f41a7cac800ad4280808080e0008410012203290000210420024180016a41086a200341086a29000037030020022004370380012003102f4120102d2203450d00200320083a000020032002290328370001200341096a2005290300370000200341116a200241286a41106a290300370000200341186a200241286a41176a2900003700002003ad4280808080800484100322052d00002106200241d8006a41176a2207200541186a290000370000200241d8006a41106a2208200541116a290000370300200c200541096a290000370300200220052900013703582005102f2003102f41c000102d2203450d00200320022903483700002003200229038001370010200320063a002020032002290358370021200341086a200241c8006a41086a2205290300370000200341186a20024180016a41086a2206290300370000200341296a200241d8006a41086a2209290300370000200341316a2008290300370000200341386a20072900003700002003ad428080808080088410052003102f41eba1ca00ad4280808080f000841001220329000021042005200341086a290000370300200220043703482003102f41c8abc900ad4280808080d000841001220329000021042006200341086a29000037030020022004370380012003102f4120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100322052d00002106200241ef006a2207200541186a290000370000200241d8006a41106a2208200541116a2900003703002009200541096a290000370300200220052900013703582005102f2003102f41c000102d2203450d00200320022903483700002003200229038001370010200320063a002020032002290358370021200341086a200241c8006a41086a290300370000200341186a20024180016a41086a2205290300370000200341296a200241d8006a41086a2206290300370000200341316a2008290300370000200341386a20072900003700002003ad428080808080088410052003102f200110e805200110e90541eba1ca00ad4280808080f000841001220329000021042005200341086a29000037030020022004370380012003102f41a9cbc800ad4280808080d00184100122032900002104200241086a41086a200341086a290000370300200220043703082003102f4120102d2203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100322052900002104200541086a290000210a200541106a290000210d200241d8006a41186a2207200541186a290000370300200241d8006a41106a2208200d3703002006200a370300200220043703582005102f2003102f41c000102d2203450d0020032002290380013700002003200229030837001020032002290358370020200341086a20024180016a41086a290300370000200341186a200241086a41086a290300370000200341286a200241d8006a41086a290300370000200341306a2008290300370000200341386a2007290300370000200241d8006a2003109c0502402002280264220e450d002003ad428080808080088410050b200229036821042002280258210b2003102f200e450d05200e2004422088a74102746a210c2004a7210f200b2108200e2106410021070240410041ff01710e03030400030b410021030c040b1036000b2003102f200041086a4108360200200041046a41d6c7c800360200200041026a41013a000020004183103b01000c040b410121030c010b410221030b0340024002400240024002400240024020030e03000102020b2006200c460d03200641046a2106410221032008417f6a220521080c020b41002103024020074102460d0041022107200b21050c020b2006200c460d02200641046a2106410221072008417f6a22052108410221030c010b200741024721094101210341022107200b21052009450d010b200241d8006a41186a200141186a290000370300200241d8006a41106a200141106a290000370300200241d8006a41086a200141086a2900003703002002200536027820022001290000370358200241d8006a10ed050240200341ff01710e03000203000b410121030c030b200f450d03200e102f0c030b410221030c010b410021030c000b0b200110ca02200041043a00000b20024190016a24000baf0305027f017e027f027e027f230041e0006b2202240041eba1ca00ad4280808080f00084100122032900002104200241186a41086a2205200341086a290000370300200220043703182003102f4197cfc800ad4280808080b00284100122032900002104200241286a41086a2206200341086a290000370300200220043703282003102f2002200136025c200241dc006aad4280808080c00084100322032900002104200341086a2900002107200341106a2900002108200241386a41186a2201200341186a290000370300200241386a41106a22092008370300200241386a41086a220a2007370300200220043703382003102f024041c000102d22030d001036000b200320022903183700002003200229032837001020032002290338370020200341086a2005290300370000200341186a2006290300370000200341286a200a290300370000200341306a2009290300370000200341386a20012903003700002002200341c000109c01200241106a290300210720022903002104200229030821082003102f200041106a2007370300200020083703082000200442002004a71b370300200241e0006a24000bc70305027f017e027f027e027f230041d0006b2202240041eba1ca00ad4280808080f00084100122032900002104200241086a41086a2205200341086a290000370300200220043703082003102f41e5cac800ad4280808080800284100122032900002104200241186a41086a2206200341086a290000370300200220043703182003102f2002200136024c200241cc006aad4280808080c00084100322032900002104200341086a2900002107200341106a2900002108200241286a41186a2201200341186a290000370300200241286a41106a22092008370300200241286a41086a220a2007370300200220043703282003102f024041c000102d2203450d00200320022903083700002003200229031837001020032002290328370020200341086a2005290300370000200341186a2006290300370000200341286a200a290300370000200341306a2009290300370000200341386a2001290300370000200241286a2003109f0502400240200228022c2201450d0020002001360204200041086a2002290330370200200228022821010c010b20004190bdc600360204200041086a4200370200410021010b200020013602002003102f200241d0006a24000f0b1036000b871505027f017e017f027e0e7f23004190046b2204240041eba1ca00ad4280808080f00084100122052900002106200441f0016a41086a200541086a290000370300200420063703f0012005102f41c8abc900ad4280808080d0008410012205290000210620044190036a41086a200541086a29000037030020042006370390032005102f024002400240024002404120102d2205450d0020052001290000370000200541186a200141186a290000370000200541106a200141106a290000370000200541086a200141086a2900003700002005ad4280808080800484100322072900002106200741086a2900002108200741106a2900002109200441d0016a41186a220a200741186a290000370300200441d0016a41106a220b2009370300200441d0016a41086a2008370300200420063703d0012007102f2005102f41c000102d2205450d00200520042903f0013700002005200429039003370010200520042903d001370020200541086a200441f0016a41086a290300370000200541186a20044190036a41086a290300370000200541286a200441d0016a41086a290300370000200541306a200b290300370000200541386a200a290300370000200441c0003602e402200420053602e00220044180016a2005ad42808080808008841002107302402004280280012207450d00200428028401210b0240024020044180016a41086a280200450d0020072d0000220a4103490d010b200441003602f801200442013703f0012004410b3602342004200441e0026a3602302004200441f0016a360208200441a4036a41013602002004420137029403200441b885c700360290032004200441306a3602a003200441086a41d8dbc10020044190036a103c1a20043502f80142208620043502f001841008024020042802f401450d0020042802f001102f0b4103210a0b0240200b450d002007102f0b200a4103470d020b2005102f0c020b1036000b2005102f02400240200a0e03020001020b2004200237038001200420033703880102400240200220038450450d004200210342002106420021020c010b20042001360230200441f0016a200120044180016a200441306a10a002024020042802f0014101470d004200210620042903f8012103420121020c010b20044198026a290300210620044190026a29030021034200210220042903f8014201520d00200441f0016a41106a2903002108200441c8036a200441f0016a41186a290300370300200441c0036a200837030020044190036a41086a41003a000020044199036a2001290000370000200441a1036a200141086a290000370000200441a9036a200141106a290000370000200441b1036a200141186a290000370000200441033a00900341c8e1ca00410020044190036a108c010b200242018521020c030b20044180016a200110b50320042d0080014101470d01200441c8006a20044199016a290000370300200441c0006a20044191016a290000370300200441386a20044189016a2900003703002004200429008101370330200420023703e002200420033703e80202400240200220038450450d004200210242002103420021060c010b2004200441306a360208200441f0016a200441306a200441e0026a200441086a10a002024020042802f0014101470d004200210620042903f8012103420121020c010b20044198026a290300210620044190026a29030021034200210220042903f8014201520d00200441f0016a41106a2903002108200441c8036a200441f0016a41186a290300370300200441c0036a200837030020044190036a41086a41003a000020044199036a2004290330370000200441a1036a200441306a41086a290300370000200441a9036a200441306a41106a290300370000200441b1036a200441306a41186a290300370000200441033a00900341c8e1ca00410020044190036a108c010b200242018521020c020b20044180016a200110b50320042d0080014101470d00200441e0026a41186a20044199016a2205290000370300200441e0026a41106a20044191016a2207290000370300200441e0026a41086a20044189016a220a29000037030020042004290081013703e00220044190036a200441e0026a108103200441d0016a41186a220b2005290000370300200441d0016a41106a22052007290000370300200441d0016a41086a2207200a29000037030020042004290081013703d00120042802bc03220c4102460d00200441f0016a41186a220a200b290300370300200441f0016a41106a220d2005290300370300200441f0016a41086a220e2007290300370300200441f0016a41286a220f20044190036a41086a290300370300200441f0016a41306a221020044190036a41106a290300370300200441f0016a41386a221120044190036a41186a290300370300200441f0016a41c0006a221220044190036a41206a290300370300200441f0016a41c8006a221320044190036a41286a280200360200200420042903d0013703f001200420042903900337039002200441086a41206a221420044190036a41d0006a290300370300200441086a41186a221520044190036a41c8006a290300370300200441086a41106a221620044190036a41c0006a290300370300200441086a41086a221720044190036a41386a290300370300200420042903c003370308200441306a200441f0016a41cc0010e8061a20044180016a200441306a41cc0010e8061a200b200441306a41186a2903003703002005200441306a41106a2903003703002007200441306a41086a290300370300200420042903303703d001200f20044180016a41c8006a280200360200200441f0016a41206a20044180016a41c0006a290300370300200a20044180016a41386a290300370300200d20044180016a41306a290300370300200e20044180016a41286a290300370300200420042903a0013703f0012004200c36029c0220102004290308370300201120172903003703002012201629030037030020132015290300370300200441f0016a41d0006a2014290300370300200a2903002106200d200d290300220820027c2209370300200a200620037c2009200854ad7c370300200e2903002106200420042903f001220820027c22093703f001200e200620037c2009200854ad7c370300200420033703d002200420023703c80202400240200220038450450d004200210242002103420021060c010b200420013602dc02200441e0026a2001200441c8026a200441dc026a10a002024020042802e0024101470d004200210620042903e8022103420121020c010b20044188036a290300210620044180036a29030021034200210220042903e8024201520d00200441e0026a41106a2903002108200441c8036a200441e0026a41186a290300370300200441c0036a200837030020044190036a41086a41003a000020044199036a2001290000370000200441a1036a200141086a290000370000200441a9036a200141106a290000370000200441b1036a200141186a290000370000200441033a00900341c8e1ca00410020044190036a108c010b200441d0016a200441f0016a10b603024020044194026a280200450d00200428029002102f0b200242018521020c010b420021020b2000200337030820002002370300200041106a200637030020044190046a24000b13002000410d360204200041c4d1c9003602000b3400200041aa87ca0036020420004100360200200041146a4109360200200041106a4188ddc900360200200041086a42043702000b910101057f230041206b22022400200241186a22034200370300200241106a22044200370300200241086a220542003703002002420037030002404120102d22060d001036000b20062002290300370000200042a0808080800437020420002006360200200641186a2003290300370000200641106a2004290300370000200641086a2005290300370000200241206a24000b130020004102360204200041f8eec9003602000b2d01017f02404108102d22020d001036000b20004288808080800137020420002002360200200242b8173700000b2d01017f02404108102d22020d001036000b20004288808080800137020420002002360200200242c8013700000b130020004104360204200041c8f5c9003602000b34002000419bd9c90036020420004100360200200041146a4101360200200041106a41d085ca00360200200041086a42073702000b100020002802002000280204200110640bbe04020d7f017e230041c0006b22032400200128020822044104742105200128020421062001280200220721010240024002402004450d00200341306a410172210841002104200341306a41026a2109200341206a410172220a41076a210b03402009200720046a220141036a2d00003a00002003200141016a2f00003b0130024020012d0000220c41ac01470d00200141106a21010c020b2003410c6a41026a20092d0000220d3a0000200320032f0130220e3b010c200141046a280200210f200141086a29030021102008200e3b0000200841026a200d3a00002003200c3a0030200320103703382003200f360234200341206a200341306a20021091062003200a2900003703102003200b290000370017024020032d0020220c411f470d002005200441106a2204470d010c030b0b2000200c3a000020002003290310370001200041086a20032900173700000240200541706a2004460d00200141146a2101200520046b41706a2104034002402001417c6a2d00004109470d0002402001280200220928020441ffffffff0371450d002009280200102f200128020021090b2009102f0b200141106a2101200441706a22040d000b0b2006450d022007102f0c020b200720056a22092001460d000340200141106a2104024020012d00004109470d000240200141046a2208280200220128020441ffffffff0371450d002001280200102f200828020021010b2001102f0b2004210120092004470d000b0b02402006450d002007102f0b2000411f3a00000b200341c0006a24000bb4c10202097f017e230041106b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000eac01000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa01ab01000b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dae01200441017422062005200620054b1b22064100480dae010240024020040d002006102d21050c010b200228020420042006103121050b2005450dad0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41003a00000cab010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dad01200441017422062005200620054b1b22064100480dad010240024020040d002006102d21050c010b200228020420042006103121050b2005450dac0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41013a00000caa010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490dac01200441017422082005200820054b1b22084100480dac010240024020040d002008102d21050c010b200628020020042008103121050b2005450dab0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41023a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490dac01200441017422082005200820054b1b22084100480dac010240024020040d002008102d21050c010b200628020020042008103121050b2005450dab0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca9010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490dab01200441017422082005200820054b1b22084100480dab010240024020040d002008102d21050c010b200628020020042008103121050b2005450daa0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41033a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490dab01200441017422082005200820054b1b22084100480dab010240024020040d002008102d21050c010b200628020020042008103121050b2005450daa0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca8010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490daa01200441017422082005200820054b1b22084100480daa010240024020040d002008102d21050c010b200628020020042008103121050b2005450da90120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41043a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490daa01200441017422082005200820054b1b22084100480daa010240024020040d002008102d21050c010b200628020020042008103121050b2005450da90120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca7010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da901200441017422062005200620054b1b22064100480da9010240024020040d002006102d21050c010b200228020420042006103121050b2005450da80120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41053a00000ca6010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da801200441017422062005200620054b1b22064100480da8010240024020040d002006102d21050c010b200228020420042006103121050b2005450da70120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a410b3a00000ca5010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490da701200441017422072006200720064b1b22074100480da7010240024020040d002007102d21060c010b200928020020042007103121060b2006450da60120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a410c3a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490da8012004410174220a2006200a20064b1b220a4100480da8010240024020040d00200a102d21060c010b20092802002004200a103121060b2006450da701200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca5010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490da601200441017422072006200720064b1b22074100480da6010240024020040d002007102d21060c010b200928020020042007103121060b2006450da50120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a410d3a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490da7012004410174220a2006200a20064b1b220a4100480da7010240024020040d00200a102d21060c010b20092802002004200a103121060b2006450da601200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca4010b0b200241046a210902400240200241086a2802002002410c6a2802002204460d00200928020021050c010b200441016a22052004490da501200441017422062005200620054b1b22064100480da5010240024020040d002006102d21050c010b200928020020042006103121050b2005450da40120022005360204200241086a20063602002002410c6a28020021040b2002410c6a2207200441016a360200200520046a410e3a0000200320012802042204280204220520042802002204200420054102746a20021092062003210420032d0000411f470dab0120012802042802082105200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490da6012004410174220a2006200a20064b1b220a4100480da6010240024020040d00200a102d21060c010b20092802002004200a103121060b2006450da501200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca3010b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da401200441017422062005200620054b1b22064100480da4010240024020040d002006102d21050c010b200228020420042006103121050b2005450da30120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a410f3a00000ca1010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490da301200441017422072006200720064b1b22074100480da3010240024020040d002007102d21060c010b200928020020042007103121060b2006450da20120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41103a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490da4012004410174220a2006200a20064b1b220a4100480da4010240024020040d00200a102d21060c010b20092802002004200a103121060b2006450da301200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca1010b0b200241046a2109200141046a280200210520012d0001210b02400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490da201200441017422072006200720064b1b22074100480da2010240024020040d002007102d21060c010b200928020020042007103121060b2006450da10120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41113a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490da3012004410174220a2006200a20064b1b220a4100480da3010240024020040d00200a102d21060c010b20092802002004200a103121060b2006450da201200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b02400240200241086a2802002002410c6a2802002204460d00200928020021050c010b200441016a22052004490da201200441017422062005200620054b1b22064100480da2010240024020040d002006102d21050c010b200928020020042006103121050b2005450da10120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a200b3a00000c9f010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da101200441017422062005200620054b1b22064100480da1010240024020040d002006102d21050c010b200228020420042006103121050b2005450da00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a411a3a00000c9e010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da001200441017422062005200620054b1b22064100480da0010240024020040d002006102d21050c010b200228020420042006103121050b2005450d9f0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a411b3a00000c9d010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9f01200441017422072006200720064b1b22074100480d9f010240024020040d002007102d21060c010b200928020020042007103121060b2006450d9e0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41203a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490da0012004410174220a2006200a20064b1b220a4100480da0010240024020040d00200a102d21060c010b20092802002004200a103121060b2006450d9f01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9d010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9e01200441017422072006200720064b1b22074100480d9e010240024020040d002007102d21060c010b200928020020042007103121060b2006450d9d0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41213a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490d9f012004410174220a2006200a20064b1b220a4100480d9f010240024020040d00200a102d21060c010b20092802002004200a103121060b2006450d9e01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9c010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9d01200441017422072006200720064b1b22074100480d9d010240024020040d002007102d21060c010b200928020020042007103121060b2006450d9c0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41223a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490d9e012004410174220a2006200a20064b1b220a4100480d9e010240024020040d00200a102d21060c010b20092802002004200a103121060b2006450d9d01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9b010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9c01200441017422072006200720064b1b22074100480d9c010240024020040d002007102d21060c010b200928020020042007103121060b2006450d9b0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41233a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490d9d012004410174220a2006200a20064b1b220a4100480d9d010240024020040d00200a102d21060c010b20092802002004200a103121060b2006450d9c01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9a010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9b01200441017422072006200720064b1b22074100480d9b010240024020040d002007102d21060c010b200928020020042007103121060b2006450d9a0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41243a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490d9c012004410174220a2006200a20064b1b220a4100480d9c010240024020040d00200a102d21060c010b20092802002004200a103121060b2006450d9b01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c99010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9a01200441017422082007200820074b1b22084100480d9a010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d990120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41283a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9b012004410174220b2007200b20074b1b220b4100480d9b010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d9a01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9b01200441017422092006200920064b1b22094100480d9b010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d9a012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c98010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9901200441017422082007200820074b1b22084100480d99010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d980120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41293a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9a012004410174220b2007200b20074b1b220b4100480d9a010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d9901200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9a01200441017422092006200920064b1b22094100480d9a010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d99012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c97010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9801200441017422082007200820074b1b22084100480d98010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d970120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412a3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d99012004410174220b2007200b20074b1b220b4100480d99010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d9801200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9901200441017422092006200920064b1b22094100480d99010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d98012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c96010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9701200441017422082007200820074b1b22084100480d97010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d960120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412b3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d98012004410174220b2007200b20074b1b220b4100480d98010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d9701200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9801200441017422092006200920064b1b22094100480d98010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d97012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c95010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9601200441017422082007200820074b1b22084100480d96010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d950120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412c3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d97012004410174220b2007200b20074b1b220b4100480d97010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d9601200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9701200441017422092006200920064b1b22094100480d97010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d96012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c94010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9501200441017422082007200820074b1b22084100480d95010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d940120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412d3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d96012004410174220b2007200b20074b1b220b4100480d96010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d9501200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d9601200441017422092005200920054b1b22094100480d96010240024020040d002009102d21050c010b200a28020020042009103121050b2005450d95012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c93010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9401200441017422082007200820074b1b22084100480d94010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d930120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412e3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d95012004410174220b2007200b20074b1b220b4100480d95010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d9401200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d9501200441017422092005200920054b1b22094100480d95010240024020040d002009102d21050c010b200a28020020042009103121050b2005450d94012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c92010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9301200441017422082007200820074b1b22084100480d93010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d920120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412f3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d94012004410174220b2007200b20074b1b220b4100480d94010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d9301200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9401200441017422092006200920064b1b22094100480d94010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d93012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c91010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9201200441017422082007200820074b1b22084100480d92010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d910120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41303a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d93012004410174220b2007200b20074b1b220b4100480d93010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d9201200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9301200441017422092006200920064b1b22094100480d93010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d92012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c90010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9101200441017422082007200820074b1b22084100480d91010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d900120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41313a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d92012004410174220b2007200b20074b1b220b4100480d92010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d9101200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d9201200441017422092005200920054b1b22094100480d92010240024020040d002009102d21050c010b200a28020020042009103121050b2005450d91012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c8f010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9001200441017422082007200820074b1b22084100480d90010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d8f0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41323a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d91012004410174220b2007200b20074b1b220b4100480d91010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d9001200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d9101200441017422092005200920054b1b22094100480d91010240024020040d002009102d21050c010b200a28020020042009103121050b2005450d90012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c8e010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8f01200441017422082007200820074b1b22084100480d8f010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d8e0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41333a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d90012004410174220b2007200b20074b1b220b4100480d90010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d8f01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9001200441017422092006200920064b1b22094100480d90010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d8f012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8d010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8e01200441017422082007200820074b1b22084100480d8e010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d8d0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41343a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8f012004410174220b2007200b20074b1b220b4100480d8f010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d8e01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8f01200441017422092006200920064b1b22094100480d8f010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d8e012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8c010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8d01200441017422082007200820074b1b22084100480d8d010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d8c0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41353a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8f012004410174220b2007200b20074b1b220b4100480d8f010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d8d01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8f01200441017422092006200920064b1b22094100480d8f010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d90012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8b010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8d01200441017422082007200820074b1b22084100480d8d010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d8e0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41363a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8e012004410174220b2007200b20074b1b220b4100480d8e010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d8f01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8e01200441017422092006200920064b1b22094100480d8e010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d8f012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8a010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8c01200441017422082007200820074b1b22084100480d8c010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d8d0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41373a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8d012004410174220b2007200b20074b1b220b4100480d8d010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d8e01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d8d01200441017422092005200920054b1b22094100480d8d010240024020040d002009102d21050c010b200a28020020042009103121050b2005450d8e012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c89010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8b01200441017422082007200820074b1b22084100480d8b010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d8c0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41383a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8c012004410174220b2007200b20074b1b220b4100480d8c010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d8d01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8c01200441017422092006200920064b1b22094100480d8c010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d8d012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c88010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8a01200441017422082007200820074b1b22084100480d8a010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d8b0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41393a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8b012004410174220b2007200b20074b1b220b4100480d8b010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d8c01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d8b01200441017422092005200920054b1b22094100480d8b010240024020040d002009102d21050c010b200a28020020042009103121050b2005450d8c012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c87010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8901200441017422082007200820074b1b22084100480d89010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d8a0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413a3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8a012004410174220b2007200b20074b1b220b4100480d8a010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d8b01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d8a01200441017422092005200920054b1b22094100480d8a010240024020040d002009102d21050c010b200a28020020042009103121050b2005450d8b012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c86010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8801200441017422082007200820074b1b22084100480d88010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d890120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413b3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d89012004410174220b2007200b20074b1b220b4100480d89010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d8a01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8901200441017422092006200920064b1b22094100480d89010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d8a012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c85010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8701200441017422082007200820074b1b22084100480d87010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d880120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413c3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d88012004410174220b2007200b20074b1b220b4100480d88010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d8901200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8801200441017422092006200920064b1b22094100480d88010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d89012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c84010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8601200441017422082007200820074b1b22084100480d86010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d870120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413d3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d87012004410174220b2007200b20074b1b220b4100480d87010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d8801200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8701200441017422092006200920064b1b22094100480d87010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d88012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c83010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8501200441017422082007200820074b1b22084100480d85010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d860120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413e3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d86012004410174220b2007200b20074b1b220b4100480d86010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d8701200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8601200441017422092006200920064b1b22094100480d86010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d87012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c82010b0b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d8401200441017422082005200820054b1b22084100480d84010240024020040d002008102d21050c010b200628020020042008103121050b2005450d850120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a413f3a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490d8401200441017422082005200820054b1b22084100480d84010240024020040d002008102d21050c010b200628020020042008103121050b2005450d850120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a20073a00000c80010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d8301200441017422082005200820054b1b22084100480d83010240024020040d002008102d21050c010b200628020020042008103121050b2005450d840120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41c0003a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490d8301200441017422082005200820054b1b22084100480d83010240024020040d002008102d21050c010b200628020020042008103121050b2005450d840120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a20073a00000c7f0b200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8201200441017422072005200720054b1b22074100480d82010240024020040d002007102d21050c010b200228020420042007103121050b2005450d830120022005360204200241086a20073602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c1003a00002003200620021093062003210420032d0000411f470d87010c7e0b200141086a290300210c02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8101200441017422062005200620054b1b22064100480d81010240024020040d002006102d21050c010b200228020420042006103121050b2005450d820120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c2003a00002003200c20021094062003210420032d0000411f470d86010c7d0b200241046a2106200141046a280200210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d8001200441017422082005200820054b1b22084100480d80010240024020040d002008102d21050c010b200628020020042008103121050b2005450d810120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41c3003a000002400240200241086a2802002205200828020022046b4104490d00200628020021050c010b200441046a22082004490d8001200541017422042008200420084b1b22044100480d80010240024020050d002004102d21050c010b200628020020052004103121050b2005450d810120022005360204200241086a20043602002002410c6a28020021040b2002410c6a200441046a360200200520046a20073600000c7c0b200241046a2106200141086a290300210c02400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d7f200441017422072005200720054b1b22074100480d7f0240024020040d002007102d21050c010b200628020020042007103121050b2005450d800120022005360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200520046a41c4003a000002400240200241086a2802002205200728020022046b4108490d00200628020021050c010b200441086a22072004490d7f200541017422042007200420074b1b22044100480d7f0240024020050d002004102d21050c010b200628020020052004103121050b2005450d800120022005360204200241086a20043602002002410c6a28020021040b2002410c6a200441086a360200200520046a200c3700000c7b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7e200441017422062005200620054b1b22064100480d7e0240024020040d002006102d21050c010b200228020420042006103121050b2005450d7f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c5003a00000c7a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7d200441017422062005200620054b1b22064100480d7d0240024020040d002006102d21050c010b200228020420042006103121050b2005450d7e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c6003a00000c790b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7c200441017422062005200620054b1b22064100480d7c0240024020040d002006102d21050c010b200228020420042006103121050b2005450d7d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c7003a00000c780b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7b200441017422062005200620054b1b22064100480d7b0240024020040d002006102d21050c010b200228020420042006103121050b2005450d7c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c8003a00000c770b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7a200441017422062005200620054b1b22064100480d7a0240024020040d002006102d21050c010b200228020420042006103121050b2005450d7b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c9003a00000c760b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d79200441017422062005200620054b1b22064100480d790240024020040d002006102d21050c010b200228020420042006103121050b2005450d7a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ca003a00000c750b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d78200441017422062005200620054b1b22064100480d780240024020040d002006102d21050c010b200228020420042006103121050b2005450d7920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cb003a00000c740b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d77200441017422062005200620054b1b22064100480d770240024020040d002006102d21050c010b200228020420042006103121050b2005450d7820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cc003a00000c730b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d76200441017422062005200620054b1b22064100480d760240024020040d002006102d21050c010b200228020420042006103121050b2005450d7720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cd003a00000c720b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d75200441017422062005200620054b1b22064100480d750240024020040d002006102d21050c010b200228020420042006103121050b2005450d7620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ce003a00000c710b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d74200441017422062005200620054b1b22064100480d740240024020040d002006102d21050c010b200228020420042006103121050b2005450d7520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cf003a00000c700b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d73200441017422062005200620054b1b22064100480d730240024020040d002006102d21050c010b200228020420042006103121050b2005450d7420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d0003a00000c6f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d72200441017422062005200620054b1b22064100480d720240024020040d002006102d21050c010b200228020420042006103121050b2005450d7320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d1003a00000c6e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d71200441017422062005200620054b1b22064100480d710240024020040d002006102d21050c010b200228020420042006103121050b2005450d7220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d2003a00000c6d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d70200441017422062005200620054b1b22064100480d700240024020040d002006102d21050c010b200228020420042006103121050b2005450d7120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d3003a00000c6c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6f200441017422062005200620054b1b22064100480d6f0240024020040d002006102d21050c010b200228020420042006103121050b2005450d7020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d4003a00000c6b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6e200441017422062005200620054b1b22064100480d6e0240024020040d002006102d21050c010b200228020420042006103121050b2005450d6f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d5003a00000c6a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6d200441017422062005200620054b1b22064100480d6d0240024020040d002006102d21050c010b200228020420042006103121050b2005450d6e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d6003a00000c690b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6c200441017422062005200620054b1b22064100480d6c0240024020040d002006102d21050c010b200228020420042006103121050b2005450d6d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d7003a00000c680b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6b200441017422062005200620054b1b22064100480d6b0240024020040d002006102d21050c010b200228020420042006103121050b2005450d6c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d8003a00000c670b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6a200441017422062005200620054b1b22064100480d6a0240024020040d002006102d21050c010b200228020420042006103121050b2005450d6b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d9003a00000c660b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d69200441017422062005200620054b1b22064100480d690240024020040d002006102d21050c010b200228020420042006103121050b2005450d6a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41da003a00000c650b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d68200441017422062005200620054b1b22064100480d680240024020040d002006102d21050c010b200228020420042006103121050b2005450d6920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41db003a00000c640b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d67200441017422062005200620054b1b22064100480d670240024020040d002006102d21050c010b200228020420042006103121050b2005450d6820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41dc003a00000c630b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d66200441017422062005200620054b1b22064100480d660240024020040d002006102d21050c010b200228020420042006103121050b2005450d6720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41dd003a00000c620b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d65200441017422062005200620054b1b22064100480d650240024020040d002006102d21050c010b200228020420042006103121050b2005450d6620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41de003a00000c610b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d64200441017422062005200620054b1b22064100480d640240024020040d002006102d21050c010b200228020420042006103121050b2005450d6520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41df003a00000c600b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d63200441017422062005200620054b1b22064100480d630240024020040d002006102d21050c010b200228020420042006103121050b2005450d6420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e0003a00000c5f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d62200441017422062005200620054b1b22064100480d620240024020040d002006102d21050c010b200228020420042006103121050b2005450d6320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e1003a00000c5e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d61200441017422062005200620054b1b22064100480d610240024020040d002006102d21050c010b200228020420042006103121050b2005450d6220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e2003a00000c5d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d60200441017422062005200620054b1b22064100480d600240024020040d002006102d21050c010b200228020420042006103121050b2005450d6120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e3003a00000c5c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5f200441017422062005200620054b1b22064100480d5f0240024020040d002006102d21050c010b200228020420042006103121050b2005450d6020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e4003a00000c5b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5e200441017422062005200620054b1b22064100480d5e0240024020040d002006102d21050c010b200228020420042006103121050b2005450d5f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e5003a00000c5a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5d200441017422062005200620054b1b22064100480d5d0240024020040d002006102d21050c010b200228020420042006103121050b2005450d5e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e6003a00000c590b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5c200441017422062005200620054b1b22064100480d5c0240024020040d002006102d21050c010b200228020420042006103121050b2005450d5d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e7003a00000c580b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5b200441017422062005200620054b1b22064100480d5b0240024020040d002006102d21050c010b200228020420042006103121050b2005450d5c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e8003a00000c570b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5c200441017422062005200620054b1b22064100480d5c0240024020040d002006102d21050c010b200228020420042006103121050b2005450d5b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e9003a00000c560b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5b200441017422062005200620054b1b22064100480d5b0240024020040d002006102d21050c010b200228020420042006103121050b2005450d5c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ea003a00000c550b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5a200441017422062005200620054b1b22064100480d5a0240024020040d002006102d21050c010b200228020420042006103121050b2005450d5b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41eb003a00000c540b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d59200441017422062005200620054b1b22064100480d590240024020040d002006102d21050c010b200228020420042006103121050b2005450d5a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ec003a00000c530b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d58200441017422062005200620054b1b22064100480d580240024020040d002006102d21050c010b200228020420042006103121050b2005450d5920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ed003a00000c520b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d57200441017422062005200620054b1b22064100480d570240024020040d002006102d21050c010b200228020420042006103121050b2005450d5820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ee003a00000c510b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d56200441017422062005200620054b1b22064100480d560240024020040d002006102d21050c010b200228020420042006103121050b2005450d5720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ef003a00000c500b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d55200441017422062005200620054b1b22064100480d550240024020040d002006102d21050c010b200228020420042006103121050b2005450d5620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f0003a00000c4f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d54200441017422062005200620054b1b22064100480d540240024020040d002006102d21050c010b200228020420042006103121050b2005450d5520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f1003a00000c4e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d53200441017422062005200620054b1b22064100480d530240024020040d002006102d21050c010b200228020420042006103121050b2005450d5420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f2003a00000c4d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d52200441017422062005200620054b1b22064100480d520240024020040d002006102d21050c010b200228020420042006103121050b2005450d5320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f3003a00000c4c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d51200441017422062005200620054b1b22064100480d510240024020040d002006102d21050c010b200228020420042006103121050b2005450d5220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f4003a00000c4b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d50200441017422062005200620054b1b22064100480d500240024020040d002006102d21050c010b200228020420042006103121050b2005450d5120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f5003a00000c4a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4f200441017422062005200620054b1b22064100480d4f0240024020040d002006102d21050c010b200228020420042006103121050b2005450d5020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f6003a00000c490b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4e200441017422062005200620054b1b22064100480d4e0240024020040d002006102d21050c010b200228020420042006103121050b2005450d4f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f7003a00000c480b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4d200441017422062005200620054b1b22064100480d4d0240024020040d002006102d21050c010b200228020420042006103121050b2005450d4e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f8003a00000c470b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4c200441017422062005200620054b1b22064100480d4c0240024020040d002006102d21050c010b200228020420042006103121050b2005450d4d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f9003a00000c460b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4b200441017422062005200620054b1b22064100480d4b0240024020040d002006102d21050c010b200228020420042006103121050b2005450d4c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fa003a00000c450b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4a200441017422062005200620054b1b22064100480d4a0240024020040d002006102d21050c010b200228020420042006103121050b2005450d4b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fb003a00000c440b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d49200441017422062005200620054b1b22064100480d490240024020040d002006102d21050c010b200228020420042006103121050b2005450d4a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fc003a00000c430b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d48200441017422062005200620054b1b22064100480d480240024020040d002006102d21050c010b200228020420042006103121050b2005450d4920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fd003a00000c420b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d47200441017422062005200620054b1b22064100480d470240024020040d002006102d21050c010b200228020420042006103121050b2005450d4820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fe003a00000c410b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d46200441017422062005200620054b1b22064100480d460240024020040d002006102d21050c010b200228020420042006103121050b2005450d4720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ff003a00000c400b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d45200441017422062005200620054b1b22064100480d450240024020040d002006102d21050c010b200228020420042006103121050b2005450d4620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4180013a00000c3f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d44200441017422062005200620054b1b22064100480d440240024020040d002006102d21050c010b200228020420042006103121050b2005450d4520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4181013a00000c3e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d43200441017422062005200620054b1b22064100480d430240024020040d002006102d21050c010b200228020420042006103121050b2005450d4420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4182013a00000c3d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d42200441017422062005200620054b1b22064100480d420240024020040d002006102d21050c010b200228020420042006103121050b2005450d4320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4183013a00000c3c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d41200441017422062005200620054b1b22064100480d410240024020040d002006102d21050c010b200228020420042006103121050b2005450d4220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4184013a00000c3b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d40200441017422062005200620054b1b22064100480d400240024020040d002006102d21050c010b200228020420042006103121050b2005450d4120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4185013a00000c3a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3f200441017422062005200620054b1b22064100480d3f0240024020040d002006102d21050c010b200228020420042006103121050b2005450d4020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4186013a00000c390b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3e200441017422062005200620054b1b22064100480d3e0240024020040d002006102d21050c010b200228020420042006103121050b2005450d3f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4187013a00000c380b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3d200441017422062005200620054b1b22064100480d3d0240024020040d002006102d21050c010b200228020420042006103121050b2005450d3e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4188013a00000c370b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3c200441017422062005200620054b1b22064100480d3c0240024020040d002006102d21050c010b200228020420042006103121050b2005450d3d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4189013a00000c360b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3b200441017422062005200620054b1b22064100480d3b0240024020040d002006102d21050c010b200228020420042006103121050b2005450d3c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418a013a00000c350b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3a200441017422062005200620054b1b22064100480d3a0240024020040d002006102d21050c010b200228020420042006103121050b2005450d3b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418b013a00000c340b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d39200441017422062005200620054b1b22064100480d390240024020040d002006102d21050c010b200228020420042006103121050b2005450d3a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418c013a00000c330b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d38200441017422062005200620054b1b22064100480d380240024020040d002006102d21050c010b200228020420042006103121050b2005450d3920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418d013a00000c320b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d37200441017422062005200620054b1b22064100480d370240024020040d002006102d21050c010b200228020420042006103121050b2005450d3820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418e013a00000c310b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d36200441017422062005200620054b1b22064100480d360240024020040d002006102d21050c010b200228020420042006103121050b2005450d3720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418f013a00000c300b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d35200441017422062005200620054b1b22064100480d350240024020040d002006102d21050c010b200228020420042006103121050b2005450d3620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4190013a00000c2f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d34200441017422062005200620054b1b22064100480d340240024020040d002006102d21050c010b200228020420042006103121050b2005450d3520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4191013a00000c2e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d33200441017422062005200620054b1b22064100480d330240024020040d002006102d21050c010b200228020420042006103121050b2005450d3420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4192013a00000c2d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d32200441017422062005200620054b1b22064100480d320240024020040d002006102d21050c010b200228020420042006103121050b2005450d3320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4193013a00000c2c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d31200441017422062005200620054b1b22064100480d310240024020040d002006102d21050c010b200228020420042006103121050b2005450d3220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4194013a00000c2b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d30200441017422062005200620054b1b22064100480d300240024020040d002006102d21050c010b200228020420042006103121050b2005450d3120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4195013a00000c2a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2f200441017422062005200620054b1b22064100480d2f0240024020040d002006102d21050c010b200228020420042006103121050b2005450d3020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4196013a00000c290b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2e200441017422062005200620054b1b22064100480d2e0240024020040d002006102d21050c010b200228020420042006103121050b2005450d2f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4197013a00000c280b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2d200441017422062005200620054b1b22064100480d2d0240024020040d002006102d21050c010b200228020420042006103121050b2005450d2e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4198013a00000c270b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2c200441017422062005200620054b1b22064100480d2c0240024020040d002006102d21050c010b200228020420042006103121050b2005450d2d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4199013a00000c260b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2b200441017422062005200620054b1b22064100480d2b0240024020040d002006102d21050c010b200228020420042006103121050b2005450d2c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419a013a00000c250b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2a200441017422062005200620054b1b22064100480d2a0240024020040d002006102d21050c010b200228020420042006103121050b2005450d2b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419b013a00000c240b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d29200441017422062005200620054b1b22064100480d290240024020040d002006102d21050c010b200228020420042006103121050b2005450d2a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419c013a00000c230b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d28200441017422062005200620054b1b22064100480d280240024020040d002006102d21050c010b200228020420042006103121050b2005450d2920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419d013a00000c220b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d27200441017422062005200620054b1b22064100480d270240024020040d002006102d21050c010b200228020420042006103121050b2005450d2820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419e013a00000c210b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d26200441017422062005200620054b1b22064100480d260240024020040d002006102d21050c010b200228020420042006103121050b2005450d2720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419f013a00000c200b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d25200441017422062005200620054b1b22064100480d250240024020040d002006102d21050c010b200228020420042006103121050b2005450d2620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a0013a00000c1f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d24200441017422062005200620054b1b22064100480d240240024020040d002006102d21050c010b200228020420042006103121050b2005450d2520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a1013a00000c1e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d23200441017422062005200620054b1b22064100480d230240024020040d002006102d21050c010b200228020420042006103121050b2005450d2420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a2013a00000c1d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d22200441017422062005200620054b1b22064100480d220240024020040d002006102d21050c010b200228020420042006103121050b2005450d2320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a3013a00000c1c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102d21050c010b200228020420042006103121050b2005450d2220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a4013a00000c1b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d20200441017422062005200620054b1b22064100480d200240024020040d002006102d21050c010b200228020420042006103121050b2005450d2120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a5013a00000c1a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1f200441017422062005200620054b1b22064100480d1f0240024020040d002006102d21050c010b200228020420042006103121050b2005450d2020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a6013a00000c190b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1e200441017422062005200620054b1b22064100480d1e0240024020040d002006102d21050c010b200228020420042006103121050b2005450d1f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a7013a00000c180b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1d200441017422062005200620054b1b22064100480d1d0240024020040d002006102d21050c010b200228020420042006103121050b2005450d1e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a8013a00000c170b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1c200441017422062005200620054b1b22064100480d1c0240024020040d002006102d21050c010b200228020420042006103121050b2005450d1d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a9013a00000c160b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1b200441017422062005200620054b1b22064100480d1b0240024020040d002006102d21050c010b200228020420042006103121050b2005450d1c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41aa013a00000c150b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1a200441017422062005200620054b1b22064100480d1a0240024020040d002006102d21050c010b200228020420042006103121050b2005450d1b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ab013a00000c140b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d19200441017422062005200620054b1b22064100480d190240024020040d002006102d21050c010b200228020420042006103121050b2005450d1a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ac013a00000c130b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d18200441017422062005200620054b1b22064100480d180240024020040d002006102d21050c010b200228020420042006103121050b2005450d1920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ad013a00000c120b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d17200441017422062005200620054b1b22064100480d170240024020040d002006102d21050c010b200228020420042006103121050b2005450d1820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ae013a00000c110b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d16200441017422062005200620054b1b22064100480d160240024020040d002006102d21050c010b200228020420042006103121050b2005450d1720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41af013a00000c100b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d15200441017422062005200620054b1b22064100480d150240024020040d002006102d21050c010b200228020420042006103121050b2005450d1620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b0013a00000c0f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d14200441017422062005200620054b1b22064100480d140240024020040d002006102d21050c010b200228020420042006103121050b2005450d1520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b1013a00000c0e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d13200441017422062005200620054b1b22064100480d130240024020040d002006102d21050c010b200228020420042006103121050b2005450d1420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b2013a00000c0d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d12200441017422062005200620054b1b22064100480d120240024020040d002006102d21050c010b200228020420042006103121050b2005450d1320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b3013a00000c0c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d14200441017422062005200620054b1b22064100480d140240024020040d002006102d21050c010b200228020420042006103121050b2005450d1220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b4013a00000c0b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d13200441017422062005200620054b1b22064100480d130240024020040d002006102d21050c010b200228020420042006103121050b2005450d1220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b5013a00000c0a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d12200441017422062005200620054b1b22064100480d120240024020040d002006102d21050c010b200228020420042006103121050b2005450d1120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b6013a00000c090b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d11200441017422062005200620054b1b22064100480d110240024020040d002006102d21050c010b200228020420042006103121050b2005450d1020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b7013a00000c080b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d10200441017422062005200620054b1b22064100480d100240024020040d002006102d21050c010b200228020420042006103121050b2005450d0f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b8013a00000c070b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0f200441017422062005200620054b1b22064100480d0f0240024020040d002006102d21050c010b200228020420042006103121050b2005450d0e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b9013a00000c060b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0e200441017422062005200620054b1b22064100480d0e0240024020040d002006102d21050c010b200228020420042006103121050b2005450d0d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ba013a00000c050b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0d200441017422062005200620054b1b22064100480d0d0240024020040d002006102d21050c010b200228020420042006103121050b2005450d0c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bb013a00000c040b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0c200441017422062005200620054b1b22064100480d0c0240024020040d002006102d21050c010b200228020420042006103121050b2005450d0b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bc013a00000c030b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0b200441017422062005200620054b1b22064100480d0b0240024020040d002006102d21050c010b200228020420042006103121050b2005450d0a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bd013a00000c020b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0a200441017422062005200620054b1b22064100480d0a0240024020040d002006102d21050c010b200228020420042006103121050b2005450d0920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41be013a00000c010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d09200441017422062005200620054b1b22064100480d090240024020040d002006102d21050c010b200228020420042006103121050b2005450d0820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bf013a00000b2000411f3a000020012d00004109470d090240200141046a280200220228020441ffffffff0371450d002002280200102f200128020421020b2002102f0c090b1036000b1038000b1038000b1036000b1038000b1036000b1036000b1038000b20002004290200370200200041086a200441086a29020037020020012d00004109470d000240200141046a280200220228020441ffffffff0371450d002002280200102f200128020421020b2002102f0b200341106a24000ba80301057f2004410c6a2105200441086a210602400240034002400240200628020020052802002207460d00200428020421080c010b200741016a22082007490d03200741017422092008200920084b1b22094100480d030240024020070d002009102d21080c010b200428020420072009103121080b2008450d022004200836020420062009360200200528020021070b2005200741016a360200200820076a200141807f72200141ff0071200141077622071b3a00002007210120070d000b024020022003460d002004410c6a2105200441086a2106034020022802002101034002400240200628020020052802002207460d00200428020421080c010b200741016a22082007490d05200741017422092008200920084b1b22094100480d050240024020070d002009102d21080c010b200428020420072009103121080b2008450d042004200836020420062009360200200528020021070b2005200741016a360200200820076a200141807f72200141ff0071200141077622071b3a00002007210120070d000b200241046a22022003470d000b0b2000411f3a00000f0b1036000b1038000ba40301067f02400240024020014107752203200141c00071220472452003417f4720044572734101470d002002410c6a2105200241086a2106034002400240200628020020052802002204460d00200228020421070c010b200441016a22072004490d04200441017422082007200820074b1b22084100480d040240024020040d002008102d21070c010b200228020420042008103121070b2007450d032002200736020420062008360200200528020021040b2005200441016a360200200720046a200141807f723a0000200341c000712104200321012003410775220721032007200472452007417f4720044572470d000b0b02400240200241086a2802002002410c6a2802002204460d00200228020421030c010b200441016a22032004490d02200441017422072003200720034b1b22074100480d020240024020040d002007102d21030c010b200228020420042007103121030b2003450d0120022003360204200241086a20073602002002410c6a28020021040b2002410c6a200441016a360200200320046a200141ff00713a00002000411f3a00000f0b1036000b1038000ba80302017e067f02400240024020014207872203502001a7220441c00071452205712003427f52200572734101470d002002410c6a2106200241086a2107034002400240200728020020062802002205460d00200228020421080c010b200541016a22082005490d04200541017422092008200920084b1b22094100480d040240024020050d002009102d21080c010b200228020420052009103121080b2008450d032002200836020420072009360200200628020021050b2006200541016a360200200820056a200441807f723a00002003a72104200342078722012103200150200441c00071452205712001427f52200572470d000b0b02400240200241086a2802002002410c6a2802002205460d00200228020421080c010b200541016a22082005490d02200541017422062008200620084b1b22064100480d020240024020050d002006102d21080c010b200228020420052006103121080b2008450d0120022008360204200241086a20063602002002410c6a28020021050b2002410c6a200541016a360200200820056a200441ff00713a00002000411f3a00000f0b1036000b1038000be403010a7f230041306b22022400200241216a220341076a210441002105410021064100210741002108410821090240024002400340200241186a2001109606024020022802184101470d002000200229021c370204200041013602002000410c6a200241186a410c6a29020037020002402007450d00200921070340024020072d00004109470d000240200741046a220a280200220528020441ffffffff0371450d002005280200102f200a28020021050b2005102f0b200741106a2107200641706a22060d000b0b2008450d042009102f0c040b200220032900003703082002200429000037000f20022d0020210a2002200229000f37001f200220022903083703180240024020072008470d00200741016a220b2007490d032005200b2005200b4b1b220b41ffffffff0071200b470d03200b410474220b4100480d030240024020070d00200b102d21090c010b20092006200b103121090b2009450d01200b41047621080b200920066a220b200a3a0000200b41016a2002290318370000200b41086a200229001f370000200541026a2105200641106a2106200741016a2107200a41ff01714106460d030c010b0b1036000b1038000b20002009360204200041003602002000410c6a2007360200200041086a20083602000b200241306a24000ba8b501020b7f017e230041f0006b2202240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802082203200128020c2204460d00200441016a22052004490dad0120032005490dae012001280200220620046a2d000021072001410c6a22082005360200200741bf014b0d0120070ec001b502b502020304b502010101010105060708090a0b01010101010101010c0d010101010e0f101112010101131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa01b5020b200241013a0048200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241c8006a360238200241086a200241d8006a103a200241336a200241106a2802003600002002200229030837002b2002200229002837031820022002412f6a29000037001f200041053a0004200020022903183700052000410c6a200229001f370000200041013602000cb6020b2000410b3a000420004101360200200041056a20073a00000cb5020b024002400240024002400240024020032005460d00200441026a21092005417f460db30120032009490db401200620056a2c00002101200820093602004100210a0240200141004e0d00411921090c020b0240200141017441807f71200172220141ff0171220541847e6a220941034d0d0041062109200541c001470d034104210a410221070cba020b20090e0405040306050b200241013a0047200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241c7006a360238200241c8006a200241d8006a103a200241326a200241d0006a2802003601002002200229034837012a2002200229012837031820022002412e6a29010037011e410521090b2002200229011e37010e200220022903183703080b200020013a0005200020093a000420002002290308370106200041013602002000410c6a200229010e3701000cb8020b4101210a410221070cb5020b4102210a410221070cb4020b4103210a0b410221070cb2020b024002400240024002400240024020032005460d00200441026a21092005417f460db40120032009490db501200620056a2c00002101200820093602004100210a0240200141004e0d00411921090c020b0240200141017441807f71200172220141ff0171220541847e6a220941034d0d0041062109200541c001470d034104210a410321070cb9020b20090e0405040306050b200241013a0047200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241c7006a360238200241c8006a200241d8006a103a200241326a200241d0006a2802003601002002200229034837012a2002200229012837031820022002412e6a29010037011e410521090b2002200229011e37010e200220022903183703080b200020013a0005200020093a000420002002290308370106200041013602002000410c6a200229010e3701000cb7020b4101210a410321070cb4020b4102210a410321070cb3020b4103210a0b410321070cb1020b024002400240024002400240024020032005460d00200441026a21092005417f460db50120032009490db601200620056a2c00002101200820093602004100210a0240200141004e0d00411921090c020b0240200141017441807f71200172220141ff0171220541847e6a220941034d0d0041062109200541c001470d034104210a410421070cb8020b20090e0405040306050b200241013a0047200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241c7006a360238200241c8006a200241d8006a103a200241326a200241d0006a2802003601002002200229034837012a2002200229012837031820022002412e6a29010037011e410521090b2002200229011e37010e200220022903183703080b200020013a0005200020093a000420002002290308370106200041013602002000410c6a200229010e3701000cb6020b4101210a410421070cb3020b4102210a410421070cb2020b4103210a0b410421070cb0020b410621070caf020b410021014100210902400240034002402001411f4d0d00410f21010c030b20032005460d012005417f460db1012003200541016a2207490df601200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b024020014120490d00410d21012004410f4b0d020b410721070cb0020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000cb0020b410021014100210902400240034002402001411f4d0d00410f21010c030b20032005460d012005417f460db1012003200541016a2207490df601200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b024020014120490d00410d21012004410f4b0d020b410821070caf020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000caf020b200241d8006a2001109706410421042002280258220a4101460da201200241e0006a280200210b41002106200228025c210c410021070240200241e4006a28020022054102742209450d002009410275220341ffffffff03712003470daf0120094100480daf012009102d2204450dae02200941027621070b02402005450d00200541027421032009417c6a210620042109200c2105034020092005280200360200200941046a2109200541046a21052003417c6a22030d000b200641027641016a21060b0240200b450d00200c102f0b20022d005c4105470dab02200a450dab0220022802640da3010cab020b410a21070cab020b410021014100210902400240034002402001411f4d0d00410f21010c030b20032005460d012005417f460db0012003200541016a2207490df401200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b024020014120490d00410d21012004410f4b0d020b410b21070cac020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000cac020b410021014100210902400240024002400240034002402001411f4d0d00410f21010c030b20032005460d012005417f460db3012003200541016a2204490df701200620056a2d0000210720082004360200200741ff00712001411f71742009722109200141076a2101200421052007418001710d000b024020014120490d00410d21012007410f4b0d020b20032004460d03200441016a22012004490db301200320014f0d0220012003104a000b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000cae020b200620046a2d000021052008200136020020050d01410c21074100210a0cab020b200241013a0048200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241c8006a360238200241086a200241d8006a103a200241336a200241106a2802003600002002200229030837002b2002200229002837031820022002412f6a29000037001f200041053a0004200020022903183700052000410c6a200229001f370000200041013602000cac020b200041163a000420004101360200200041056a20053a00000cab020b410d21070ca8020b410e21070ca7020b410021014100210902400240034002402001411f4d0d00410f21010c030b20032005460d012005417f460daf012003200541016a2207490df201200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b024020014120490d00410d21012004410f4b0d020b410f21070ca8020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000ca8020b410021014100210902400240034002402001411f4d0d00410f21010c030b20032005460d012005417f460daf012003200541016a2207490df201200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b024020014120490d00410d21012004410f4b0d020b411021070ca7020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000ca7020b410021014100210902400240034002402001411f4d0d00410f21010c030b20032005460d012005417f460daf012003200541016a2207490df201200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b024020014120490d00410d21012004410f4b0d020b411121070ca6020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000ca6020b410021014100210902400240034002402001411f4d0d00410f21010c030b20032005460d012005417f460daf012003200541016a2207490df201200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b024020014120490d00410d21012004410f4b0d020b411221070ca5020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000ca5020b410021014100210902400240034002402001411f4d0d00410f21010c030b20032005460d012005417f460daf012003200541016a2207490df201200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b024020014120490d00410d21012004410f4b0d020b411321070ca4020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000ca4020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450db10120032001490df401200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460db2012003200141016a2207490df501200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210d411421070ca5020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a20022802282103200228022c210520022802302109410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a20033602000ca5020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000ca3020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450db20120032001490df501200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460db3012003200141016a2207490df601200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210d411521070ca4020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a20022802282103200228022c210520022802302109410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a20033602000ca4020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000ca2020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450db30120032001490df601200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460db4012003200141016a2207490df701200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210d411621070ca3020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a20022802282103200228022c210520022802302109410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a20033602000ca3020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000ca1020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450db40120032001490df701200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460db5012003200141016a2207490df801200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210d411721070ca2020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a20022802282103200228022c210520022802302109410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a20033602000ca2020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000ca0020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450db50120032001490df801200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460db6012003200141016a2207490df901200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210d411821070ca1020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a20022802282103200228022c210520022802302109410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a20033602000ca1020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c9f020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450db60120032001490df901200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460db7012003200141016a2207490dfa01200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210d411921070ca0020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a20022802282103200228022c210520022802302109410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a20033602000ca0020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c9e020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450db70120032001490dfa01200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460db8012003200141016a2207490dfb01200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210d411a21070c9f020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a20022802282103200228022c210520022802302109410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a20033602000c9f020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c9d020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450db80120032001490dfb01200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460db9012003200141016a2207490dfc01200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210d411b21070c9e020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a20022802282103200228022c210520022802302109410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a20033602000c9e020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c9c020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450db90120032001490dfc01200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dba012003200141016a2207490dfd01200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210d411c21070c9d020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a20022802282103200228022c210520022802302109410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a20033602000c9d020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c9b020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dba0120032001490dfd01200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dbb012003200141016a2207490dfe01200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210d411d21070c9c020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a20022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9c020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c9a020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dbb0120032001490dfe01200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dbc012003200141016a2207490dff01200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210d411e21070c9b020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a20022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9b020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c99020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dbc0120032001490dff01200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dbd012003200141016a2207490d8002200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210d411f21070c9a020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a20022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9a020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c98020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dbd0120032001490d8002200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dbe012003200141016a2207490d8102200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b41202107024020054120490d00410d21012004410f4b0d040b200aad210d0c99020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a20022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c99020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c97020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dbe0120032001490d8102200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dbf012003200141016a2207490d8202200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210d412121070c98020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a20022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c98020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c96020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dbf0120032001490d8202200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dc0012003200141016a2207490d8302200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210d412221070c97020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a20022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c97020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c95020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dc00120032001490d8302200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dc1012003200141016a2207490d8402200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210d412321070c96020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a20022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c96020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c94020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dc10120032001490d8402200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dc2012003200141016a2207490d8502200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210d412421070c95020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a20022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c95020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c93020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dc20120032001490d8502200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dc3012003200141016a2207490d8602200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210d412521070c94020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a20022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c94020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c92020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dc30120032001490d8602200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dc4012003200141016a2207490d8702200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210d412621070c93020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a20022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c93020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c91020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dc40120032001490d8702200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dc5012003200141016a2207490d8802200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210d412721070c92020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a20022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c92020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c90020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dc50120032001490d8802200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dc6012003200141016a2207490d8902200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210d412821070c91020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a20022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c91020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c8f020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dc60120032001490d8902200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dc7012003200141016a2207490d8a02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210d412921070c90020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a20022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c90020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c8e020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dc70120032001490d8a02200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dc8012003200141016a2207490d8b02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210d412a21070c8f020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a20022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c8f020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c8d020b0240024020032005460d00200441026a21012005417f460dc50120032001490dc601200620056a2d000021092008200136020020090d01412b21074100210a0c8c020b200241013a0048200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241c8006a360238200241086a200241d8006a103a200241336a200241106a2802003600002002200229030837002b2002200229002837031820022002412f6a29000037001f200041053a0004200020022903183700052000410c6a200229001f370000200041013602000c8d020b200041153a000420004101360200200041056a20093a00000c8c020b0240024020032005460d00200441026a21012005417f460dc60120032001490dc701200620056a2d000021092008200136020020090d01412c21074100210a0c8b020b200241013a0048200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241c8006a360238200241086a200241d8006a103a200241336a200241106a2802003600002002200229030837002b2002200229002837031820022002412f6a29000037001f200041053a0004200020022903183700052000410c6a200229001f370000200041013602000c8c020b200041153a000420004101360200200041056a20093a00000c8b020b4100210141002109024002400340410d210a2001411f4b0d0220032005460d012005417f460dc8012003200541016a2207490d8702200620056a2c0000210420082007360200200441ff00712001411f71742009722109200141076a21012007210520044100480d000b200441c00071210502402001411f4b0d0020050dc9010b02400240024020014120490d0020050d010b200441ff01714108490d0120014120490d0120050d010c030b20044180017241ff017141f801490d020b412d21070c8a020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a4105210a0b2000200a36020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c8a020b4200210d4100210102400340410e21072001413f4b0d860220032005460d012005417f460dc8012003200541016a2209490dc901200620056a2d0000210420082009360200200441ff0071220aad2001413f71ad86200d84210d200141076a21012009210520044118744118752209417f4c0d000b200941c0007121050240024002402001413f4b0d0020050d010b02400240200141c000490d0020050d010b200141c000490d022009450d020c88020b200a41ff00470d87020c010b200d428080808080808080807f427f2001413f712201ad862001413f461b84210d0b412e21070c88020b200241013a0008200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241086a360238200241286a200241d8006a103a2002290328210d20022802302101410521070c85020b0240200320056b4104490d00200441056a21012005417b4b0dc80120032001490dc901200620056a280000210920082001360200412f21070c87020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a20004281808080d000370300200041086a2002290328370200200041106a200241286a41086a2802003602000c88020b0240200320056b4108490d00200441096a2101200541774b0dc90120032001490dca01200620056a290000210d20082001360200413021070c86020b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a2002290328210d200041106a2002280230360200200041086a200d37020020004281808080d0003703000c87020b413121070c84020b413221070c83020b413321070c82020b413421070c81020b413521070c80020b413621070cff010b413721070cfe010b413821070cfd010b413921070cfc010b413a21070cfb010b413b21070cfa010b413c21070cf9010b413d21070cf8010b413e21070cf7010b413f21070cf6010b41c00021070cf5010b41c10021070cf4010b41c20021070cf3010b41c30021070cf2010b41c40021070cf1010b41c50021070cf0010b41c60021070cef010b41c70021070cee010b41c80021070ced010b41c90021070cec010b41ca0021070ceb010b41cb0021070cea010b41cc0021070ce9010b41cd0021070ce8010b41ce0021070ce7010b41cf0021070ce6010b41d00021070ce5010b41d10021070ce4010b41d20021070ce3010b41d30021070ce2010b41d40021070ce1010b41d50021070ce0010b41d60021070cdf010b41d70021070cde010b41d80021070cdd010b41d90021070cdc010b41da0021070cdb010b41db0021070cda010b41dc0021070cd9010b41dd0021070cd8010b41de0021070cd7010b41df0021070cd6010b41e00021070cd5010b41e10021070cd4010b41e20021070cd3010b41e30021070cd2010b41e40021070cd1010b41e50021070cd0010b41e60021070ccf010b41e70021070cce010b41e80021070ccd010b41e90021070ccc010b41ea0021070ccb010b41eb0021070cca010b41ec0021070cc9010b41ed0021070cc8010b41ee0021070cc7010b41ef0021070cc6010b41f00021070cc5010b41f10021070cc4010b41f20021070cc3010b41f30021070cc2010b41f40021070cc1010b41f50021070cc0010b41f60021070cbf010b41f70021070cbe010b41f80021070cbd010b41f90021070cbc010b41fa0021070cbb010b41fb0021070cba010b41fc0021070cb9010b41fd0021070cb8010b41fe0021070cb7010b41ff0021070cb6010b41800121070cb5010b41810121070cb4010b41820121070cb3010b41830121070cb2010b41840121070cb1010b41850121070cb0010b41860121070caf010b41870121070cae010b41880121070cad010b41890121070cac010b418a0121070cab010b418b0121070caa010b418c0121070ca9010b418d0121070ca8010b418e0121070ca7010b418f0121070ca6010b41900121070ca5010b41910121070ca4010b41920121070ca3010b41930121070ca2010b41940121070ca1010b41950121070ca0010b41960121070c9f010b41970121070c9e010b41980121070c9d010b41990121070c9c010b419a0121070c9b010b419b0121070c9a010b419c0121070c99010b419d0121070c98010b419e0121070c97010b419f0121070c96010b41a00121070c95010b41a10121070c94010b41a20121070c93010b41a30121070c92010b41a40121070c91010b41a50121070c90010b41a60121070c8f010b41a70121070c8e010b41a80121070c8d010b41a90121070c8c010b41aa0121070c8b010b41ab0121070c8a010b200041013602002000200241d8006a41047222012902003702042000410c6a200141086a2902003702000c8b010b2002280260102f0c87010b417f2005104b000b20052003104a000b417f2009104b000b20092003104a000b417f2009104b000b20092003104a000b417f2009104b000b20092003104a000b417f200541016a104b000b417f200541016a104b000b1038000b417f200541016a104b000b417f200541016a104b000b417f2001104b000b417f200541016a104b000b417f200541016a104b000b417f200541016a104b000b417f200541016a104b000b417f200541016a104b000b417f2001104b000b417f200141016a104b000b417f2001104b000b417f200141016a104b000b417f2001104b000b417f200141016a104b000b417f2001104b000b417f200141016a104b000b417f2001104b000b417f200141016a104b000b417f2001104b000b417f200141016a104b000b417f2001104b000b417f200141016a104b000b417f2001104b000b417f200141016a104b000b417f2001104b000b417f200141016a104b000b417f2001104b000b417f200141016a104b000b417f2001104b000b417f200141016a104b000b417f2001104b000b417f200141016a104b000b417f2001104b000b417f200141016a104b000b417f2001104b000b417f200141016a104b000b417f2001104b000b417f200141016a104b000b417f2001104b000b417f200141016a104b000b417f2001104b000b417f200141016a104b000b417f2001104b000b417f200141016a104b000b417f2001104b000b417f200141016a104b000b417f2001104b000b417f200141016a104b000b417f2001104b000b417f200141016a104b000b417f2001104b000b417f200141016a104b000b417f2001104b000b417f200141016a104b000b417f2001104b000b20012003104a000b417f2001104b000b20012003104a000b417f200541016a104b000b2009417f2001411f7174722109412d21070c410b417f200541016a104b000b200541016a2003104a000b20052001104b000b20012003104a000b20052001104b000b20012003104a000b200541016a2003104a000b200541016a2003104a000b200541016a2003104a000b200541016a2003104a000b200541016a2003104a000b200541016a2003104a000b200541016a2003104a000b200541016a2003104a000b200541016a2003104a000b20012003104a000b200141016a2003104a000b20012003104a000b200141016a2003104a000b20012003104a000b200141016a2003104a000b20012003104a000b200141016a2003104a000b20012003104a000b200141016a2003104a000b20012003104a000b200141016a2003104a000b20012003104a000b200141016a2003104a000b20012003104a000b200141016a2003104a000b20012003104a000b200141016a2003104a000b20012003104a000b200141016a2003104a000b20012003104a000b200141016a2003104a000b20012003104a000b200141016a2003104a000b20012003104a000b200141016a2003104a000b20012003104a000b200141016a2003104a000b20012003104a000b200141016a2003104a000b20012003104a000b200141016a2003104a000b20012003104a000b200141016a2003104a000b20012003104a000b200141016a2003104a000b20012003104a000b200141016a2003104a000b20012003104a000b200141016a2003104a000b20012003104a000b200141016a2003104a000b20012003104a000b200141016a2003104a000b20012003104a000b200141016a2003104a000b200541016a2003104a000b0b200020073a0004200020022f00183b000520004101360200200041106a2001360200200041086a200d370200200041076a2002411a6a2d00003a00000c030b0240024002400240024002400240024020072006470d002004210a0c010b20072006490d01024020060d004104210a2007450d012004102f0c010b2004200741027420064102741031220a450d080b4100210941002104034002402009411f4d0d00410f21010c060b20012802082207200128020c2205460d04200541016a22032005490d0220072003490d03200128020020056a2d0000210520082003360200200541ff00712009411f71742004722104200941076a21092005418001710d000b20094120490d05410d21012005410f4d0d050c040b41ebafca00412441f8b4ca001039000b417f2003104b000b20032007104a000b200241013a0018200241ec006a41013602002002420137025c200241b4afca003602582002412836023c2002200241386a3602682002200241186a360238200241286a200241d8006a103a410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a280200360200200641ffffffff0371450d03200a102f0c030b410c102d2209450d0120092004360208200920063602042009200a360200410921070b20004100360200200041106a200d3703002000410c6a2009360200200041096a200a3a0000200041086a20073a00000c010b1036000b200241f0006a24000bd607020c7f017e230041d0006b220224004100210341002104024002400240024002400240024002400240034002402003411f4d0d00410f21030c090b20012802082205200128020c2206460d07200641016a22072006490d0120052007490d04200128020020066a2d000021062001200736020c200641ff00712003411f71742004722104200341076a21032006418001710d000b024020034120490d00410d21032006410f4b0d080b20024100360210200242043703082004450d05410421084100210341002109024002400240024003402003210a2009220b41016a2109410021034100210503402003411f4b0d02024002402001280208220c200128020c2206460d00200641016a22072006490d09200c20074f0d012007200c104a000b2002200a36020c2002200b360210200241013a0027200241cc006a41013602002002420137023c200241b4afca003602382002412836021c2002200241186a3602482002200241276a360218200241286a200241386a103a20022802282103200228022c2106200228023021074100210d410521010c060b200128020020066a2d000021062001200736020c200641ff00712003411f71742005722105200341076a21032006418001710d000b024020034120490d002006410f4b0d030b024002400240200b200a460d00200a2103200b210a0c010b200a41016a2203200a490d01200a41017422062003200620034b1b220341ffffffff03712003470d01200341027422034100480d0102400240200a0d002003102d21080c010b2008200a4102742003103121080b2008450d0920022008360208200341027621030b2005410876210d2008200a4102746a200536020020092004460d0a0c010b0b1038000b2002200a36020c2002200b360210410f21010c010b2002200a36020c2002200b360210410d21010b0b20004101360200200041106a20073602002000410c6a2006360200200041086a20033602002000200d410874200172360204200a450d082008102f0c080b417f2007104b000b417f2007104b000b1036000b20072005104a000b2002200336020c200220093602100b20002002290308370204200041003602002000410c6a200241106a2802003602000c020b200241013a0027200241cc006a41013602002002420137023c200241b4afca003602382002412836021c2002200241186a3602482002200241276a360218200241286a200241386a103a410521030b200241086a41086a200241286a41086a280200220136020020022002290328220e37030820002003360204200041086a200e370200200041106a2001360200200041013602000b200241d0006a24000bb4c10202097f017e230041106b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000eac01000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa01ab01000b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dae01200441017422062005200620054b1b22064100480dae010240024020040d002006102d21050c010b200228020420042006103121050b2005450dad0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41003a00000cab010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dad01200441017422062005200620054b1b22064100480dad010240024020040d002006102d21050c010b200228020420042006103121050b2005450dac0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41013a00000caa010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490dac01200441017422082005200820054b1b22084100480dac010240024020040d002008102d21050c010b200628020020042008103121050b2005450dab0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41023a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490dac01200441017422082005200820054b1b22084100480dac010240024020040d002008102d21050c010b200628020020042008103121050b2005450dab0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca9010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490dab01200441017422082005200820054b1b22084100480dab010240024020040d002008102d21050c010b200628020020042008103121050b2005450daa0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41033a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490dab01200441017422082005200820054b1b22084100480dab010240024020040d002008102d21050c010b200628020020042008103121050b2005450daa0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca8010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490daa01200441017422082005200820054b1b22084100480daa010240024020040d002008102d21050c010b200628020020042008103121050b2005450da90120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41043a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490daa01200441017422082005200820054b1b22084100480daa010240024020040d002008102d21050c010b200628020020042008103121050b2005450da90120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca7010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da901200441017422062005200620054b1b22064100480da9010240024020040d002006102d21050c010b200228020420042006103121050b2005450da80120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41053a00000ca6010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da801200441017422062005200620054b1b22064100480da8010240024020040d002006102d21050c010b200228020420042006103121050b2005450da70120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a410b3a00000ca5010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490da701200441017422072006200720064b1b22074100480da7010240024020040d002007102d21060c010b200928020020042007103121060b2006450da60120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a410c3a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490da8012004410174220a2006200a20064b1b220a4100480da8010240024020040d00200a102d21060c010b20092802002004200a103121060b2006450da701200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca5010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490da601200441017422072006200720064b1b22074100480da6010240024020040d002007102d21060c010b200928020020042007103121060b2006450da50120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a410d3a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490da7012004410174220a2006200a20064b1b220a4100480da7010240024020040d00200a102d21060c010b20092802002004200a103121060b2006450da601200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca4010b0b200241046a210902400240200241086a2802002002410c6a2802002204460d00200928020021050c010b200441016a22052004490da501200441017422062005200620054b1b22064100480da5010240024020040d002006102d21050c010b200928020020042006103121050b2005450da40120022005360204200241086a20063602002002410c6a28020021040b2002410c6a2207200441016a360200200520046a410e3a0000200320012802042204280204220520042802002204200420054102746a20021092062003210420032d0000411f470dab0120012802042802082105200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490da6012004410174220a2006200a20064b1b220a4100480da6010240024020040d00200a102d21060c010b20092802002004200a103121060b2006450da501200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca3010b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da401200441017422062005200620054b1b22064100480da4010240024020040d002006102d21050c010b200228020420042006103121050b2005450da30120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a410f3a00000ca1010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490da301200441017422072006200720064b1b22074100480da3010240024020040d002007102d21060c010b200928020020042007103121060b2006450da20120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41103a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490da4012004410174220a2006200a20064b1b220a4100480da4010240024020040d00200a102d21060c010b20092802002004200a103121060b2006450da301200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca1010b0b200241046a2109200141046a280200210520012d0001210b02400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490da201200441017422072006200720064b1b22074100480da2010240024020040d002007102d21060c010b200928020020042007103121060b2006450da10120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41113a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490da3012004410174220a2006200a20064b1b220a4100480da3010240024020040d00200a102d21060c010b20092802002004200a103121060b2006450da201200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b02400240200241086a2802002002410c6a2802002204460d00200928020021050c010b200441016a22052004490da201200441017422062005200620054b1b22064100480da2010240024020040d002006102d21050c010b200928020020042006103121050b2005450da10120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a200b3a00000c9f010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da101200441017422062005200620054b1b22064100480da1010240024020040d002006102d21050c010b200228020420042006103121050b2005450da00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a411a3a00000c9e010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da001200441017422062005200620054b1b22064100480da0010240024020040d002006102d21050c010b200228020420042006103121050b2005450d9f0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a411b3a00000c9d010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9f01200441017422072006200720064b1b22074100480d9f010240024020040d002007102d21060c010b200928020020042007103121060b2006450d9e0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41203a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490da0012004410174220a2006200a20064b1b220a4100480da0010240024020040d00200a102d21060c010b20092802002004200a103121060b2006450d9f01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9d010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9e01200441017422072006200720064b1b22074100480d9e010240024020040d002007102d21060c010b200928020020042007103121060b2006450d9d0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41213a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490d9f012004410174220a2006200a20064b1b220a4100480d9f010240024020040d00200a102d21060c010b20092802002004200a103121060b2006450d9e01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9c010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9d01200441017422072006200720064b1b22074100480d9d010240024020040d002007102d21060c010b200928020020042007103121060b2006450d9c0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41223a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490d9e012004410174220a2006200a20064b1b220a4100480d9e010240024020040d00200a102d21060c010b20092802002004200a103121060b2006450d9d01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9b010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9c01200441017422072006200720064b1b22074100480d9c010240024020040d002007102d21060c010b200928020020042007103121060b2006450d9b0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41233a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490d9d012004410174220a2006200a20064b1b220a4100480d9d010240024020040d00200a102d21060c010b20092802002004200a103121060b2006450d9c01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9a010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9b01200441017422072006200720064b1b22074100480d9b010240024020040d002007102d21060c010b200928020020042007103121060b2006450d9a0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41243a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490d9c012004410174220a2006200a20064b1b220a4100480d9c010240024020040d00200a102d21060c010b20092802002004200a103121060b2006450d9b01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c99010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9a01200441017422082007200820074b1b22084100480d9a010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d990120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41283a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9b012004410174220b2007200b20074b1b220b4100480d9b010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d9a01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9b01200441017422092006200920064b1b22094100480d9b010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d9a012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c98010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9901200441017422082007200820074b1b22084100480d99010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d980120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41293a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9a012004410174220b2007200b20074b1b220b4100480d9a010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d9901200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9a01200441017422092006200920064b1b22094100480d9a010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d99012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c97010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9801200441017422082007200820074b1b22084100480d98010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d970120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412a3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d99012004410174220b2007200b20074b1b220b4100480d99010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d9801200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9901200441017422092006200920064b1b22094100480d99010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d98012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c96010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9701200441017422082007200820074b1b22084100480d97010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d960120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412b3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d98012004410174220b2007200b20074b1b220b4100480d98010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d9701200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9801200441017422092006200920064b1b22094100480d98010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d97012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c95010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9601200441017422082007200820074b1b22084100480d96010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d950120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412c3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d97012004410174220b2007200b20074b1b220b4100480d97010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d9601200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9701200441017422092006200920064b1b22094100480d97010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d96012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c94010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9501200441017422082007200820074b1b22084100480d95010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d940120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412d3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d96012004410174220b2007200b20074b1b220b4100480d96010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d9501200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d9601200441017422092005200920054b1b22094100480d96010240024020040d002009102d21050c010b200a28020020042009103121050b2005450d95012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c93010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9401200441017422082007200820074b1b22084100480d94010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d930120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412e3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d95012004410174220b2007200b20074b1b220b4100480d95010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d9401200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d9501200441017422092005200920054b1b22094100480d95010240024020040d002009102d21050c010b200a28020020042009103121050b2005450d94012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c92010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9301200441017422082007200820074b1b22084100480d93010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d920120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412f3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d94012004410174220b2007200b20074b1b220b4100480d94010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d9301200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9401200441017422092006200920064b1b22094100480d94010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d93012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c91010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9201200441017422082007200820074b1b22084100480d92010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d910120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41303a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d93012004410174220b2007200b20074b1b220b4100480d93010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d9201200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9301200441017422092006200920064b1b22094100480d93010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d92012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c90010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9101200441017422082007200820074b1b22084100480d91010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d900120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41313a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d92012004410174220b2007200b20074b1b220b4100480d92010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d9101200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d9201200441017422092005200920054b1b22094100480d92010240024020040d002009102d21050c010b200a28020020042009103121050b2005450d91012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c8f010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9001200441017422082007200820074b1b22084100480d90010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d8f0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41323a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d91012004410174220b2007200b20074b1b220b4100480d91010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d9001200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d9101200441017422092005200920054b1b22094100480d91010240024020040d002009102d21050c010b200a28020020042009103121050b2005450d90012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c8e010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8f01200441017422082007200820074b1b22084100480d8f010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d8e0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41333a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d90012004410174220b2007200b20074b1b220b4100480d90010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d8f01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9001200441017422092006200920064b1b22094100480d90010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d8f012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8d010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8e01200441017422082007200820074b1b22084100480d8e010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d8d0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41343a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8f012004410174220b2007200b20074b1b220b4100480d8f010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d8e01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8f01200441017422092006200920064b1b22094100480d8f010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d8e012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8c010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8d01200441017422082007200820074b1b22084100480d8d010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d8c0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41353a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8f012004410174220b2007200b20074b1b220b4100480d8f010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d8d01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8f01200441017422092006200920064b1b22094100480d8f010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d90012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8b010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8d01200441017422082007200820074b1b22084100480d8d010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d8e0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41363a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8e012004410174220b2007200b20074b1b220b4100480d8e010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d8f01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8e01200441017422092006200920064b1b22094100480d8e010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d8f012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8a010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8c01200441017422082007200820074b1b22084100480d8c010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d8d0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41373a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8d012004410174220b2007200b20074b1b220b4100480d8d010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d8e01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d8d01200441017422092005200920054b1b22094100480d8d010240024020040d002009102d21050c010b200a28020020042009103121050b2005450d8e012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c89010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8b01200441017422082007200820074b1b22084100480d8b010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d8c0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41383a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8c012004410174220b2007200b20074b1b220b4100480d8c010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d8d01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8c01200441017422092006200920064b1b22094100480d8c010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d8d012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c88010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8a01200441017422082007200820074b1b22084100480d8a010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d8b0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41393a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8b012004410174220b2007200b20074b1b220b4100480d8b010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d8c01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d8b01200441017422092005200920054b1b22094100480d8b010240024020040d002009102d21050c010b200a28020020042009103121050b2005450d8c012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c87010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8901200441017422082007200820074b1b22084100480d89010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d8a0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413a3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8a012004410174220b2007200b20074b1b220b4100480d8a010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d8b01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d8a01200441017422092005200920054b1b22094100480d8a010240024020040d002009102d21050c010b200a28020020042009103121050b2005450d8b012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c86010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8801200441017422082007200820074b1b22084100480d88010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d890120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413b3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d89012004410174220b2007200b20074b1b220b4100480d89010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d8a01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8901200441017422092006200920064b1b22094100480d89010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d8a012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c85010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8701200441017422082007200820074b1b22084100480d87010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d880120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413c3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d88012004410174220b2007200b20074b1b220b4100480d88010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d8901200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8801200441017422092006200920064b1b22094100480d88010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d89012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c84010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8601200441017422082007200820074b1b22084100480d86010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d870120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413d3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d87012004410174220b2007200b20074b1b220b4100480d87010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d8801200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8701200441017422092006200920064b1b22094100480d87010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d88012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c83010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8501200441017422082007200820074b1b22084100480d85010240024020040d002008102d21070c010b200a28020020042008103121070b2007450d860120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413e3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d86012004410174220b2007200b20074b1b220b4100480d86010240024020040d00200b102d21070c010b200a2802002004200b103121070b2007450d8701200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8601200441017422092006200920064b1b22094100480d86010240024020040d002009102d21060c010b200a28020020042009103121060b2006450d87012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c82010b0b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d8401200441017422082005200820054b1b22084100480d84010240024020040d002008102d21050c010b200628020020042008103121050b2005450d850120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a413f3a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490d8401200441017422082005200820054b1b22084100480d84010240024020040d002008102d21050c010b200628020020042008103121050b2005450d850120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a20073a00000c80010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d8301200441017422082005200820054b1b22084100480d83010240024020040d002008102d21050c010b200628020020042008103121050b2005450d840120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41c0003a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490d8301200441017422082005200820054b1b22084100480d83010240024020040d002008102d21050c010b200628020020042008103121050b2005450d840120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a20073a00000c7f0b200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8201200441017422072005200720054b1b22074100480d82010240024020040d002007102d21050c010b200228020420042007103121050b2005450d830120022005360204200241086a20073602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c1003a00002003200620021093062003210420032d0000411f470d87010c7e0b200141086a290300210c02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8101200441017422062005200620054b1b22064100480d81010240024020040d002006102d21050c010b200228020420042006103121050b2005450d820120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c2003a00002003200c20021094062003210420032d0000411f470d86010c7d0b200241046a2106200141046a280200210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d8001200441017422082005200820054b1b22084100480d80010240024020040d002008102d21050c010b200628020020042008103121050b2005450d810120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41c3003a000002400240200241086a2802002205200828020022046b4104490d00200628020021050c010b200441046a22082004490d8001200541017422042008200420084b1b22044100480d80010240024020050d002004102d21050c010b200628020020052004103121050b2005450d810120022005360204200241086a20043602002002410c6a28020021040b2002410c6a200441046a360200200520046a20073600000c7c0b200241046a2106200141086a290300210c02400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d7f200441017422072005200720054b1b22074100480d7f0240024020040d002007102d21050c010b200628020020042007103121050b2005450d800120022005360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200520046a41c4003a000002400240200241086a2802002205200728020022046b4108490d00200628020021050c010b200441086a22072004490d7f200541017422042007200420074b1b22044100480d7f0240024020050d002004102d21050c010b200628020020052004103121050b2005450d800120022005360204200241086a20043602002002410c6a28020021040b2002410c6a200441086a360200200520046a200c3700000c7b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7e200441017422062005200620054b1b22064100480d7e0240024020040d002006102d21050c010b200228020420042006103121050b2005450d7f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c5003a00000c7a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7d200441017422062005200620054b1b22064100480d7d0240024020040d002006102d21050c010b200228020420042006103121050b2005450d7e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c6003a00000c790b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7c200441017422062005200620054b1b22064100480d7c0240024020040d002006102d21050c010b200228020420042006103121050b2005450d7d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c7003a00000c780b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7b200441017422062005200620054b1b22064100480d7b0240024020040d002006102d21050c010b200228020420042006103121050b2005450d7c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c8003a00000c770b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7a200441017422062005200620054b1b22064100480d7a0240024020040d002006102d21050c010b200228020420042006103121050b2005450d7b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c9003a00000c760b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d79200441017422062005200620054b1b22064100480d790240024020040d002006102d21050c010b200228020420042006103121050b2005450d7a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ca003a00000c750b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d78200441017422062005200620054b1b22064100480d780240024020040d002006102d21050c010b200228020420042006103121050b2005450d7920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cb003a00000c740b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d77200441017422062005200620054b1b22064100480d770240024020040d002006102d21050c010b200228020420042006103121050b2005450d7820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cc003a00000c730b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d76200441017422062005200620054b1b22064100480d760240024020040d002006102d21050c010b200228020420042006103121050b2005450d7720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cd003a00000c720b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d75200441017422062005200620054b1b22064100480d750240024020040d002006102d21050c010b200228020420042006103121050b2005450d7620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ce003a00000c710b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d74200441017422062005200620054b1b22064100480d740240024020040d002006102d21050c010b200228020420042006103121050b2005450d7520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cf003a00000c700b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d73200441017422062005200620054b1b22064100480d730240024020040d002006102d21050c010b200228020420042006103121050b2005450d7420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d0003a00000c6f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d72200441017422062005200620054b1b22064100480d720240024020040d002006102d21050c010b200228020420042006103121050b2005450d7320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d1003a00000c6e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d71200441017422062005200620054b1b22064100480d710240024020040d002006102d21050c010b200228020420042006103121050b2005450d7220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d2003a00000c6d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d70200441017422062005200620054b1b22064100480d700240024020040d002006102d21050c010b200228020420042006103121050b2005450d7120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d3003a00000c6c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6f200441017422062005200620054b1b22064100480d6f0240024020040d002006102d21050c010b200228020420042006103121050b2005450d7020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d4003a00000c6b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6e200441017422062005200620054b1b22064100480d6e0240024020040d002006102d21050c010b200228020420042006103121050b2005450d6f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d5003a00000c6a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6d200441017422062005200620054b1b22064100480d6d0240024020040d002006102d21050c010b200228020420042006103121050b2005450d6e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d6003a00000c690b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6c200441017422062005200620054b1b22064100480d6c0240024020040d002006102d21050c010b200228020420042006103121050b2005450d6d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d7003a00000c680b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6b200441017422062005200620054b1b22064100480d6b0240024020040d002006102d21050c010b200228020420042006103121050b2005450d6c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d8003a00000c670b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6a200441017422062005200620054b1b22064100480d6a0240024020040d002006102d21050c010b200228020420042006103121050b2005450d6b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d9003a00000c660b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d69200441017422062005200620054b1b22064100480d690240024020040d002006102d21050c010b200228020420042006103121050b2005450d6a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41da003a00000c650b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d68200441017422062005200620054b1b22064100480d680240024020040d002006102d21050c010b200228020420042006103121050b2005450d6920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41db003a00000c640b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d67200441017422062005200620054b1b22064100480d670240024020040d002006102d21050c010b200228020420042006103121050b2005450d6820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41dc003a00000c630b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d66200441017422062005200620054b1b22064100480d660240024020040d002006102d21050c010b200228020420042006103121050b2005450d6720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41dd003a00000c620b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d65200441017422062005200620054b1b22064100480d650240024020040d002006102d21050c010b200228020420042006103121050b2005450d6620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41de003a00000c610b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d64200441017422062005200620054b1b22064100480d640240024020040d002006102d21050c010b200228020420042006103121050b2005450d6520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41df003a00000c600b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d63200441017422062005200620054b1b22064100480d630240024020040d002006102d21050c010b200228020420042006103121050b2005450d6420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e0003a00000c5f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d62200441017422062005200620054b1b22064100480d620240024020040d002006102d21050c010b200228020420042006103121050b2005450d6320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e1003a00000c5e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d61200441017422062005200620054b1b22064100480d610240024020040d002006102d21050c010b200228020420042006103121050b2005450d6220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e2003a00000c5d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d60200441017422062005200620054b1b22064100480d600240024020040d002006102d21050c010b200228020420042006103121050b2005450d6120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e3003a00000c5c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5f200441017422062005200620054b1b22064100480d5f0240024020040d002006102d21050c010b200228020420042006103121050b2005450d6020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e4003a00000c5b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5e200441017422062005200620054b1b22064100480d5e0240024020040d002006102d21050c010b200228020420042006103121050b2005450d5f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e5003a00000c5a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5d200441017422062005200620054b1b22064100480d5d0240024020040d002006102d21050c010b200228020420042006103121050b2005450d5e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e6003a00000c590b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5c200441017422062005200620054b1b22064100480d5c0240024020040d002006102d21050c010b200228020420042006103121050b2005450d5d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e7003a00000c580b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5b200441017422062005200620054b1b22064100480d5b0240024020040d002006102d21050c010b200228020420042006103121050b2005450d5c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e8003a00000c570b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5c200441017422062005200620054b1b22064100480d5c0240024020040d002006102d21050c010b200228020420042006103121050b2005450d5b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e9003a00000c560b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5b200441017422062005200620054b1b22064100480d5b0240024020040d002006102d21050c010b200228020420042006103121050b2005450d5c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ea003a00000c550b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5a200441017422062005200620054b1b22064100480d5a0240024020040d002006102d21050c010b200228020420042006103121050b2005450d5b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41eb003a00000c540b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d59200441017422062005200620054b1b22064100480d590240024020040d002006102d21050c010b200228020420042006103121050b2005450d5a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ec003a00000c530b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d58200441017422062005200620054b1b22064100480d580240024020040d002006102d21050c010b200228020420042006103121050b2005450d5920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ed003a00000c520b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d57200441017422062005200620054b1b22064100480d570240024020040d002006102d21050c010b200228020420042006103121050b2005450d5820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ee003a00000c510b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d56200441017422062005200620054b1b22064100480d560240024020040d002006102d21050c010b200228020420042006103121050b2005450d5720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ef003a00000c500b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d55200441017422062005200620054b1b22064100480d550240024020040d002006102d21050c010b200228020420042006103121050b2005450d5620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f0003a00000c4f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d54200441017422062005200620054b1b22064100480d540240024020040d002006102d21050c010b200228020420042006103121050b2005450d5520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f1003a00000c4e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d53200441017422062005200620054b1b22064100480d530240024020040d002006102d21050c010b200228020420042006103121050b2005450d5420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f2003a00000c4d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d52200441017422062005200620054b1b22064100480d520240024020040d002006102d21050c010b200228020420042006103121050b2005450d5320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f3003a00000c4c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d51200441017422062005200620054b1b22064100480d510240024020040d002006102d21050c010b200228020420042006103121050b2005450d5220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f4003a00000c4b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d50200441017422062005200620054b1b22064100480d500240024020040d002006102d21050c010b200228020420042006103121050b2005450d5120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f5003a00000c4a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4f200441017422062005200620054b1b22064100480d4f0240024020040d002006102d21050c010b200228020420042006103121050b2005450d5020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f6003a00000c490b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4e200441017422062005200620054b1b22064100480d4e0240024020040d002006102d21050c010b200228020420042006103121050b2005450d4f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f7003a00000c480b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4d200441017422062005200620054b1b22064100480d4d0240024020040d002006102d21050c010b200228020420042006103121050b2005450d4e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f8003a00000c470b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4c200441017422062005200620054b1b22064100480d4c0240024020040d002006102d21050c010b200228020420042006103121050b2005450d4d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f9003a00000c460b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4b200441017422062005200620054b1b22064100480d4b0240024020040d002006102d21050c010b200228020420042006103121050b2005450d4c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fa003a00000c450b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4a200441017422062005200620054b1b22064100480d4a0240024020040d002006102d21050c010b200228020420042006103121050b2005450d4b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fb003a00000c440b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d49200441017422062005200620054b1b22064100480d490240024020040d002006102d21050c010b200228020420042006103121050b2005450d4a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fc003a00000c430b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d48200441017422062005200620054b1b22064100480d480240024020040d002006102d21050c010b200228020420042006103121050b2005450d4920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fd003a00000c420b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d47200441017422062005200620054b1b22064100480d470240024020040d002006102d21050c010b200228020420042006103121050b2005450d4820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fe003a00000c410b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d46200441017422062005200620054b1b22064100480d460240024020040d002006102d21050c010b200228020420042006103121050b2005450d4720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ff003a00000c400b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d45200441017422062005200620054b1b22064100480d450240024020040d002006102d21050c010b200228020420042006103121050b2005450d4620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4180013a00000c3f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d44200441017422062005200620054b1b22064100480d440240024020040d002006102d21050c010b200228020420042006103121050b2005450d4520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4181013a00000c3e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d43200441017422062005200620054b1b22064100480d430240024020040d002006102d21050c010b200228020420042006103121050b2005450d4420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4182013a00000c3d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d42200441017422062005200620054b1b22064100480d420240024020040d002006102d21050c010b200228020420042006103121050b2005450d4320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4183013a00000c3c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d41200441017422062005200620054b1b22064100480d410240024020040d002006102d21050c010b200228020420042006103121050b2005450d4220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4184013a00000c3b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d40200441017422062005200620054b1b22064100480d400240024020040d002006102d21050c010b200228020420042006103121050b2005450d4120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4185013a00000c3a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3f200441017422062005200620054b1b22064100480d3f0240024020040d002006102d21050c010b200228020420042006103121050b2005450d4020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4186013a00000c390b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3e200441017422062005200620054b1b22064100480d3e0240024020040d002006102d21050c010b200228020420042006103121050b2005450d3f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4187013a00000c380b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3d200441017422062005200620054b1b22064100480d3d0240024020040d002006102d21050c010b200228020420042006103121050b2005450d3e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4188013a00000c370b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3c200441017422062005200620054b1b22064100480d3c0240024020040d002006102d21050c010b200228020420042006103121050b2005450d3d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4189013a00000c360b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3b200441017422062005200620054b1b22064100480d3b0240024020040d002006102d21050c010b200228020420042006103121050b2005450d3c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418a013a00000c350b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3a200441017422062005200620054b1b22064100480d3a0240024020040d002006102d21050c010b200228020420042006103121050b2005450d3b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418b013a00000c340b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d39200441017422062005200620054b1b22064100480d390240024020040d002006102d21050c010b200228020420042006103121050b2005450d3a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418c013a00000c330b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d38200441017422062005200620054b1b22064100480d380240024020040d002006102d21050c010b200228020420042006103121050b2005450d3920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418d013a00000c320b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d37200441017422062005200620054b1b22064100480d370240024020040d002006102d21050c010b200228020420042006103121050b2005450d3820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418e013a00000c310b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d36200441017422062005200620054b1b22064100480d360240024020040d002006102d21050c010b200228020420042006103121050b2005450d3720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418f013a00000c300b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d35200441017422062005200620054b1b22064100480d350240024020040d002006102d21050c010b200228020420042006103121050b2005450d3620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4190013a00000c2f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d34200441017422062005200620054b1b22064100480d340240024020040d002006102d21050c010b200228020420042006103121050b2005450d3520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4191013a00000c2e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d33200441017422062005200620054b1b22064100480d330240024020040d002006102d21050c010b200228020420042006103121050b2005450d3420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4192013a00000c2d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d32200441017422062005200620054b1b22064100480d320240024020040d002006102d21050c010b200228020420042006103121050b2005450d3320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4193013a00000c2c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d31200441017422062005200620054b1b22064100480d310240024020040d002006102d21050c010b200228020420042006103121050b2005450d3220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4194013a00000c2b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d30200441017422062005200620054b1b22064100480d300240024020040d002006102d21050c010b200228020420042006103121050b2005450d3120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4195013a00000c2a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2f200441017422062005200620054b1b22064100480d2f0240024020040d002006102d21050c010b200228020420042006103121050b2005450d3020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4196013a00000c290b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2e200441017422062005200620054b1b22064100480d2e0240024020040d002006102d21050c010b200228020420042006103121050b2005450d2f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4197013a00000c280b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2d200441017422062005200620054b1b22064100480d2d0240024020040d002006102d21050c010b200228020420042006103121050b2005450d2e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4198013a00000c270b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2c200441017422062005200620054b1b22064100480d2c0240024020040d002006102d21050c010b200228020420042006103121050b2005450d2d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4199013a00000c260b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2b200441017422062005200620054b1b22064100480d2b0240024020040d002006102d21050c010b200228020420042006103121050b2005450d2c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419a013a00000c250b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2a200441017422062005200620054b1b22064100480d2a0240024020040d002006102d21050c010b200228020420042006103121050b2005450d2b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419b013a00000c240b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d29200441017422062005200620054b1b22064100480d290240024020040d002006102d21050c010b200228020420042006103121050b2005450d2a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419c013a00000c230b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d28200441017422062005200620054b1b22064100480d280240024020040d002006102d21050c010b200228020420042006103121050b2005450d2920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419d013a00000c220b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d27200441017422062005200620054b1b22064100480d270240024020040d002006102d21050c010b200228020420042006103121050b2005450d2820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419e013a00000c210b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d26200441017422062005200620054b1b22064100480d260240024020040d002006102d21050c010b200228020420042006103121050b2005450d2720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419f013a00000c200b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d25200441017422062005200620054b1b22064100480d250240024020040d002006102d21050c010b200228020420042006103121050b2005450d2620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a0013a00000c1f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d24200441017422062005200620054b1b22064100480d240240024020040d002006102d21050c010b200228020420042006103121050b2005450d2520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a1013a00000c1e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d23200441017422062005200620054b1b22064100480d230240024020040d002006102d21050c010b200228020420042006103121050b2005450d2420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a2013a00000c1d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d22200441017422062005200620054b1b22064100480d220240024020040d002006102d21050c010b200228020420042006103121050b2005450d2320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a3013a00000c1c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102d21050c010b200228020420042006103121050b2005450d2220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a4013a00000c1b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d20200441017422062005200620054b1b22064100480d200240024020040d002006102d21050c010b200228020420042006103121050b2005450d2120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a5013a00000c1a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1f200441017422062005200620054b1b22064100480d1f0240024020040d002006102d21050c010b200228020420042006103121050b2005450d2020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a6013a00000c190b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1e200441017422062005200620054b1b22064100480d1e0240024020040d002006102d21050c010b200228020420042006103121050b2005450d1f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a7013a00000c180b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1d200441017422062005200620054b1b22064100480d1d0240024020040d002006102d21050c010b200228020420042006103121050b2005450d1e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a8013a00000c170b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1c200441017422062005200620054b1b22064100480d1c0240024020040d002006102d21050c010b200228020420042006103121050b2005450d1d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a9013a00000c160b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1b200441017422062005200620054b1b22064100480d1b0240024020040d002006102d21050c010b200228020420042006103121050b2005450d1c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41aa013a00000c150b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1a200441017422062005200620054b1b22064100480d1a0240024020040d002006102d21050c010b200228020420042006103121050b2005450d1b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ab013a00000c140b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d19200441017422062005200620054b1b22064100480d190240024020040d002006102d21050c010b200228020420042006103121050b2005450d1a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ac013a00000c130b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d18200441017422062005200620054b1b22064100480d180240024020040d002006102d21050c010b200228020420042006103121050b2005450d1920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ad013a00000c120b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d17200441017422062005200620054b1b22064100480d170240024020040d002006102d21050c010b200228020420042006103121050b2005450d1820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ae013a00000c110b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d16200441017422062005200620054b1b22064100480d160240024020040d002006102d21050c010b200228020420042006103121050b2005450d1720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41af013a00000c100b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d15200441017422062005200620054b1b22064100480d150240024020040d002006102d21050c010b200228020420042006103121050b2005450d1620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b0013a00000c0f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d14200441017422062005200620054b1b22064100480d140240024020040d002006102d21050c010b200228020420042006103121050b2005450d1520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b1013a00000c0e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d13200441017422062005200620054b1b22064100480d130240024020040d002006102d21050c010b200228020420042006103121050b2005450d1420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b2013a00000c0d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d12200441017422062005200620054b1b22064100480d120240024020040d002006102d21050c010b200228020420042006103121050b2005450d1320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b3013a00000c0c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d14200441017422062005200620054b1b22064100480d140240024020040d002006102d21050c010b200228020420042006103121050b2005450d1220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b4013a00000c0b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d13200441017422062005200620054b1b22064100480d130240024020040d002006102d21050c010b200228020420042006103121050b2005450d1220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b5013a00000c0a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d12200441017422062005200620054b1b22064100480d120240024020040d002006102d21050c010b200228020420042006103121050b2005450d1120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b6013a00000c090b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d11200441017422062005200620054b1b22064100480d110240024020040d002006102d21050c010b200228020420042006103121050b2005450d1020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b7013a00000c080b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d10200441017422062005200620054b1b22064100480d100240024020040d002006102d21050c010b200228020420042006103121050b2005450d0f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b8013a00000c070b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0f200441017422062005200620054b1b22064100480d0f0240024020040d002006102d21050c010b200228020420042006103121050b2005450d0e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b9013a00000c060b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0e200441017422062005200620054b1b22064100480d0e0240024020040d002006102d21050c010b200228020420042006103121050b2005450d0d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ba013a00000c050b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0d200441017422062005200620054b1b22064100480d0d0240024020040d002006102d21050c010b200228020420042006103121050b2005450d0c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bb013a00000c040b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0c200441017422062005200620054b1b22064100480d0c0240024020040d002006102d21050c010b200228020420042006103121050b2005450d0b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bc013a00000c030b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0b200441017422062005200620054b1b22064100480d0b0240024020040d002006102d21050c010b200228020420042006103121050b2005450d0a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bd013a00000c020b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0a200441017422062005200620054b1b22064100480d0a0240024020040d002006102d21050c010b200228020420042006103121050b2005450d0920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41be013a00000c010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d09200441017422062005200620054b1b22064100480d090240024020040d002006102d21050c010b200228020420042006103121050b2005450d0820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bf013a00000b2000411f3a000020012d00004109470d090240200141046a280200220228020441ffffffff0371450d002002280200102f200128020421020b2002102f0c090b1036000b1038000b1038000b1036000b1038000b1036000b1036000b1038000b20002004290200370200200041086a200441086a29020037020020012d00004109470d000240200141046a280200220228020441ffffffff0371450d002002280200102f200128020421020b2002102f0b200341106a24000b8007010b7f230041d0086b22022400410021034100210402400240024002400240024002400240024002400240034002402003411f4d0d00410f21030c030b20012802082205200128020c2206460d01200641016a22072006490d0420052007490d092001280200220820066a2d000021062001200736020c200641ff00712003411f71742004722104200341076a21032006418001710d000b024020034120490d00410d21032006410f4b0d020b20040d022000428080808010370200200041086a42003702000c0a0b200241013a0089082002411c6a41013602002002420137020c200241b4afca003602082002412836029c08200220024198086a360218200220024189086a36029808200241b8086a200241086a103a410521030b2000200336020420004101360200200041086a20022903b808370200200041106a200241b8086a41086a2802003602000c080b200241086a410041800810e7061a410121094100210a410021064100210b02400340200520076b2004200b6b22034180082003418008491b2203490d01200720036a220c2007490d032005200c490d04200241086a200820076a200310e8061a2001200c36020c02400240200a20066b2003490d00200320066a210c0c010b200620036a220c2006490d07200a4101742207200c2007200c4b1b22074100480d0702400240200a0d002007102d21090c010b2009200a2007103121090b2009450d062007210a0b200920066a200241086a200310e8061a20042003200b6a220b4d0d08200128020c21072001280208210520012802002108200c21060c000b0b200241013a00a708200241cc086a4101360200200242013702bc08200241b4afca003602b8082002412836029c08200220024198086a3602c8082002200241a7086a36029808200241a8086a200241b8086a103a20024194086a200241b0086a280200360000200220022903a80837008c08200041053a000420002002290089083700052000410c6a20024190086a29000037000020004101360200200a450d072009102f0c070b417f2007104b000b2007200c104b000b200c2005104a000b1036000b1038000b20072005104a000b200241086a2009200c1066024020022802084101470d000240200a450d002009102f0b200041083a0004200041013602000c010b200020093602042000410c6a200c360200200041086a200a360200200041003602000b200241d0086a24000b15002001200028020022002802002000280208104c0bb30401067f200441046a21050240024002400240200441086a2802002004410c6a2802002206460d00200528020021070c010b200641016a22072006490d02200641017422082007200820074b1b22084100480d020240024020060d002008102d21070c010b200528020020062008103121070b2007450d0120042007360204200441086a20083602002004410c6a28020021060b2004410c6a2208200641016a360200200720066a20024101463a0000200441086a2109034002400240200928020020082802002206460d00200528020021070c010b200641016a22072006490d032006410174220a2007200a20074b1b220a4100480d030240024020060d00200a102d21070c010b20052802002006200a103121070b2007450d02200420073602042009200a360200200828020021060b2008200641016a360200200720066a200141807f72200141ff0071200141077622061b3a00002006210120060d000b024020024101470d002004410c6a2107200441086a2108034002400240200828020020072802002206460d00200528020021010c010b200641016a22012006490d04200641017422092001200920014b1b22094100480d040240024020060d002009102d21010c010b200528020020062009103121010b2001450d032004200136020420082009360200200728020021060b2007200641016a360200200120066a200341807f72200341ff0071200341077622061b3a00002006210320060d000b0b2000411f3a00000f0b1036000b1038000baa07010a7f230041d0006b220224000240024002400240024002400240024002400240024020012802082203200128020c2204460d00200441016a22052004490d0220032005490d032001280200220620046a2d000021072001200536020c20074102490d01200041173a000420004101360200200041056a20073a00000c0a0b200241013a001f200241cc006a41013602002002420137023c200241b4afca00360238200241283602342002200241306a36024820022002411f6a360230200241206a200241386a103a2002411b6a200241286a28020036000020022002290320370013200220022900103703002002200241176a290000370007200041053a0004200020022903003700052000410c6a2002290007370000200041013602000c090b410120036b2108200441026a21044100210541002109034002402005411f4d0d00410f21050c090b200820046a4102460d072004450d0320032004490d05200620046a417f6a2d0000210a2001200436020c200a41ff00712005411f71742009722109200441016a2104200541076a2105200a418001710d000b024020054120490d00410d2105200a410f4b0d080b410021050240024002402007410171450d002004417f6a2104410021054100210b034002402005411f4d0d00410f21040c040b20032004460d022004417f460d072003200441016a2208490d09200620046a2d0000210a2001200836020c200a41ff00712005411f7174200b72210b200541076a210520082104200a418001710d000b024020054120490d00410d2104200a410f4b0d030b410121050b20002009360204200041003602002000410c6a200b360200200041086a20053602000c0a0b200241013a0000200241cc006a41013602002002420137023c200241b4afca00360238200241283602342002200241306a36024820022002360230200241106a200241386a103a410521040b2000200436020420004101360200200041086a2002290310370200200041106a200241106a41086a2802003602000c080b417f2005104b000b20052003104a000b417f2004104b000b417f200441016a104b000b20042003104a000b200441016a2003104a000b200241013a0000200241cc006a41013602002002420137023c200241b4afca00360238200241283602342002200241306a36024820022002360230200241106a200241386a103a410521050b2000200536020420004101360200200041086a2002290310370200200041106a200241106a41086a2802003602000b200241d0006a24000bee0201067f230041c0006b2202240041002103410021040240024003400240024002402003411f4b0d002001280204220520012802082206460d01200641016a22072006490d04200520074f0d0220072005104a000b200041013602002000410f3a00040c040b200241013a000f200241346a410136020020024201370224200241b4afca003602202002412836023c2002200241386a36023020022002410f6a360238200241106a200241206a103a2002410b6a200241186a28020036000020022002290310370003200041053a0004200020022900003700052000410c6a200241076a290000370000200041013602000c030b200128020020066a2d0000210620012007360208200641ff00712003411f71742004722104200341076a21032006418001710d000b0240024020034120490d002006410f4b0d010b20004100360200200020043602040c020b200041013602002000410d3a00040c010b417f2007104b000b200241c0006a24000ba806010a7f2001280204210320012802002104410021054101210641002107200128020822082109024002400340024020072005470d002005410174220a200541016a220b200a200b4b1b220a4100480d030240024020050d00200a102d21060c010b20062005200a103121060b2006450d02200a21050b200620076a200941807f72200941ff00712009410776220a1b3a0000200741016a2107200a2109200a0d000b0240200520076b20084f0d00200720086a22092007490d022005410174220a2009200a20094b1b22094100480d020240024020050d002009102d21060c010b200620052009103121060b2006450d01200921050b200620076a2004200810e8061a02402003450d002004102f0b200128020c210302400240200520086b20076b200141146a2802002209490d00200820096a20076a21042005210c0c010b200820076a220a20096a2204200a490d022005410174220a2004200a20044b1b220c4100480d020240024020050d00200c102d21060c010b20062005200c103121060b2006450d010b200620086a20076a2003200910e8061a200241086a210a200241046a210b20042109034002400240200b280200200a2802002207460d00200228020021050c010b200741016a22052007490d03200741017422082005200820054b1b22084100480d030240024020070d002008102d21050c010b200228020020072008103121050b2005450d0220022005360200200b2008360200200a28020021070b200a200741016a360200200520076a200941807f72200941ff0071200941077622071b3a00002007210920070d000b02400240200241046a2802002209200241086a28020022076b2004490d00200228020021090c010b200720046a22052007490d02200941017422072005200720054b1b22074100480d020240024020090d002007102d21090c010b200228020020092007103121090b2009450d0120022009360200200241046a2007360200200241086a28020021070b200241086a200720046a360200200920076a2006200410e8061a0240200c450d002006102f0b2000411f3a00000240200141106a280200450d002003102f0b0f0b1036000b1038000bd707030e7f017e017f200241086a2103200241046a210420012802002205210602400240024002400240034002400240200428020020032802002207460d00200228020021080c010b200741016a22082007490d03200741017422092008200920084b1b22094100480d030240024020070d002009102d21080c010b200228020020072009103121080b2008450d022002200836020020042009360200200328020021070b2003200741016a360200200820076a200641807f72200641ff0071200641077622071b3a00002007210620070d000b2001280204220a2001410c6a2802002206410c6c6a210b200141086a280200210c200a21072006450d03200a21072005450d03200b41746a210d200241086a210841002107200a210e0340200e2103024003402003280200220f0d01200741016a2107200b2003410c6a2203470d000c070b0b2003410c6a210e200741016a21102005417f6a2105200341046a2902002111034002400240200241046a220428020020082802002206460d00200228020021090c010b200641016a22092006490d04200641017422012009200120094b1b22014100480d040240024020060d002001102d21090c010b200228020020062001103121090b2009450d032002200936020020042001360200200828020021060b2008200641016a360200200920066a200741807f72200741ff0071200741077622061b3a00002006210720060d000b2011422088a722122106034002400240200428020020082802002207460d00200228020021090c010b200741016a22092007490d04200741017422012009200120094b1b22014100480d040240024020070d002001102d21090c010b200228020020072001103121090b2009450d032002200936020020042001360200200828020021070b2008200741016a360200200920076a200641807f72200641ff0071200641077622071b3a00002007210620070d000b0240024020042802002206200828020022076b2012490d00200228020021060c010b200720126a22092007490d03200641017422072009200720094b1b22074100480d030240024020060d002007102d21060c010b200228020020062007103121060b2006450d022002200636020020042007360200200828020021070b2008200720126a360200200620076a200f201210e8061a02402011a7450d00200f102f0b200d2003460d032010210720050d000c030b0b1036000b1038000b2003410c6a21070b200b2007460d00034020072206410c6a2107024020062802002202450d00200641046a280200450d002002102f0b200b2007470d000b0b0240200c450d00200a102f0b2000411f3a00000bed0101067f2000410c6a280200200028020822016b2202411c6d210302402002450d0020012003411c6c6a21040340024020012802042202450d0002402001410c6a2802002203450d00200341047421030340024020022d00004109470d000240200241046a2205280200220628020441ffffffff0371450d002006280200102f200528020021060b2006102f0b200241106a2102200341706a22030d000b0b200141086a280200450d002001280204102f0b2001411c6a21020240200141146a280200450d002001280210102f0b2002210120022004470d000b0b02402000280204450d002000280200102f0b0bea0101067f2000410c6a280200200028020822016b220241186d210302402002450d002001200341186c6a210403400240200141046a280200450d002001280200102f0b0240200141146a2802002203450d00200128020c2102200341047421030340024020022d00004109470d000240200241046a2205280200220628020441ffffffff0371450d002006280200102f200528020021060b2006102f0b200241106a2102200341706a22030d000b0b200141186a21020240200141106a280200450d00200128020c102f0b2002210120022004470d000b0b02402000280204450d002000280200102f0b0bce0101057f024020002802082201450d00200028020022022001411c6c6a21030340024020022802042200450d0002402002410c6a2802002201450d00200141047421010340024020002d00004109470d000240200041046a2204280200220528020441ffffffff0371450d002005280200102f200428020021050b2005102f0b200041106a2100200141706a22010d000b0b200241086a280200450d002002280204102f0b2002411c6a21000240200241146a280200450d002002280210102f0b2000210220002003470d000b0b0bed04010b7f230041c080016b2202240020022001109d06410121030240024020022802004101460d0020022802042104200241004180800110e706210541002106410021070240024002400240024002402004450d004100210841002106410121034100210903402001280204220a200128020822076b200420096b220b41808001200b41808001491b220b490d022007200b6a220c2007490d03200a200c490d042005200128020020076a200b10e806210a2001200c36020802400240200620086b200b490d00200b20086a21070c010b2008200b6a22072008490d072006410174220c2007200c20074b1b220c4100480d070240024020060d00200c102d21030c010b20032006200c103121030b2003450d06200c21060b200320086a200a200b10e8061a200721082004200b20096a22094b0d000b0b2000200336020420004100360200200041146a2007360200200041106a41003602002000410c6a2007360200200041086a20063602000c060b200541013a008f8001200541b480016a4101360200200542013702a48001200541b4afca003602a08001200541283602bc80012005200541b880016a3602b0800120052005418f80016a3602b880012005419080016a200541a080016a103a2005418b80016a2005419880016a2802003600002005200529039080013700838001200041053a00042000200529008080013700052000410c6a2005418780016a290000370000200041013602002006450d052003102f0c050b2007200c104b000b200c200a104a000b1036000b1038000b20002002290204370204200041013602002000410c6a2002410c6a2902003702000b200241c080016a24000b801f03127f017e037f23004180026b220524000240024020014115490d00410121064101210702400240034020012108200021092006200771410173210a024002400240034002400240024002402004450d00024020064101710d002000200110a5062004417f6a21040b2001410276220741036c210b2007410174210c4100210d20014132490d03200741016a210e200020074103746a220f28020020002007417f6a220d4103746a2210280200201041046a2802002210200f41046a280200220f200f20104b1b10ea062211450d01417f410120114100481b21100c020b2000200110a6060c0b0b417f200f201047200f2010491b21100b2007200d2010417f4622101b210f024002402000200e4103746a22112802002000200d200720101b22124103746a2207280200200741046a2802002207201141046a280200220d200d20074b1b10ea062211450d00417f410120114100481b21070c010b417f200d200747200d2007491b21070b4102410120101b20102007417f4622071b210d024002402000200e201220071b22114103746a22102802002000200f4103746a2207280200200741046a2802002207201041046a2802002210201020074b1b10ea06220e450d00417f4101200e4100481b21100c010b417f201020074720102007491b21100b200c4101722107200d2010417f4622126a2113024002402000200c4103746a220d2802002000200c417f6a22104103746a220e280200200e41046a280200220e200d41046a280200220d200d200e4b1b10ea062214450d00417f410120144100481b210e0c010b417f200d200e47200d200e491b210e0b200c2010200e417f46220e1b210d2013200e6a211302400240200020074103746a221428020020002010200c200e1b220e4103746a220c280200200c41046a280200220c201441046a28020022102010200c4b1b10ea062214450d00417f410120144100481b210c0c010b417f2010200c472010200c491b210c0b2013200c417f46220c6a21100240024020002007200e200c1b22134103746a220c2802002000200d4103746a2207280200200741046a2802002207200c41046a280200220c200c20074b1b10ea06220e450d00417f4101200e4100481b210c0c010b417f200c200747200c2007491b210c0b200b41016a21072010200c417f4622146a2115024002402000200b4103746a220e2802002000200b417f6a220c4103746a2210280200201041046a2802002210200e41046a280200220e200e20104b1b10ea062216450d00417f410120164100481b21100c010b417f200e201047200e2010491b21100b200b200c2010417f4622101b210e201520106a211502400240200020074103746a22162802002000200c200b20101b22104103746a220c280200200c41046a280200220c201641046a280200220b200b200c4b1b10ea062216450d00417f410120164100481b210c0c010b417f200b200c47200b200c491b210c0b2015200c417f46220c6a211502400240200020072010200c1b220b4103746a220c2802002000200e4103746a2207280200200741046a2802002207200c41046a280200220c200c20074b1b10ea062210450d00417f410120104100481b21100c010b417f200c200747200c2007491b21100b200f201120121b2107200d201320141b210c200e200b2010417f4622101b210b201520106a210d0b024002402000200c4103746a220e280200200020074103746a2210280200201041046a2802002210200e41046a280200220e200e20104b1b10ea06220f450d00417f4101200f4100481b21100c010b417f200e201047200e2010491b21100b200c20072010417f46220e1b2110200d200e6a210d024002402000200b4103746a220f28020020002007200c200e1b220e4103746a2207280200200741046a2802002207200f41046a280200220c200c20074b1b10ea06220f450d00417f4101200f4100481b21070c010b417f200c200747200c2007491b21070b200d2007417f46220c6a2107024002400240024002402000200b200e200c1b220d4103746a220b280200200020104103746a220c280200200c41046a280200220c200b41046a280200220b200b200c4b1b10ea06220e450d00200e4100480d010c020b200b200c4f0d010b200741016a2207410c490d0102402001410176220b450d00200020014103746a41786a21072000210c0340200c2902002117200c200729020037020020072017370200200c41086a210c200741786a2107200b417f6a220b0d000b0b20012010417f736a2110410121070c020b200d21100b20074521070b0240200745200a724101710d002000200110a7060d090b2003450d010240201020014f0d00024002402003280200200020104103746a2207280200200741046a280200220c200341046a280200220b200b200c4b1b10ea06220e450d00200e41004e0d010c050b200b200c490d040b200029020021172000200729020037020020072017370200200041786a21122000410c6a2113200041086a2114200028020421072000280200210d4100210b2001210e0340024002400240200b200e417f6a22114f0d002013200b4103746a210c034002400240200d200c417c6a280200200c28020022102007200720104b1b10ea06220f450d00200f4100480d030c010b20072010490d020b200c41086a210c2011200b41016a220b470d000c020b0b0240200b20114f0d002012200e4103746a210c2011210e034002400240200d200c280200200c41046a28020022102007200720104b1b10ea06220f450d00200f4100480d010c050b200720104f0d040b200c41786a210c200b200e417f6a220e490d000b0b200b21110b200020073602042000200d36020002402001201141016a2207490d00200020074103746a2100200120076b220141154f0d040c0b0b20072001104b000b2014200b4103746a221029020021172010200c290200370200200c2017370200200b41016a210b0c000b0b0b41d4bbca0020102001103b000b20080d014188bbca0041004100103b000b20002109200121080b201020084f0d02200929020021172009200920104103746a2207290200370200200720173702002009280204210c200928020021124100210e410021184100211902402008417f6a220d450d002009410c6a21074100211803400240024002402007417c6a2802002012200c2007280200220b200b200c4b1b10ea062210450d00201041004e0d010c020b200b200c490d010b200d21190240200d20184d0d00200920084103746a41786a2107200d211903400240024020072802002012200c200741046a280200220b200b200c4b1b10ea062210450d00201041004e0d010c030b200b200c490d020b200741786a21072019417f6a221920184b0d000b0b0240024020192018490d00200d2019490d010c040b20182019104b000b2019200d104a000b200741086a2107200d201841016a2218470d000b200d2118200d21190b200941086a220720194103746a210d41800121144100211141002110410021014180012106200720184103746a221a210003400240200d20006b22074187104b220a0d002007410376220741807f6a20072011200e492001201049220b72220f1b21070240200f450d0020062007200b1b210620072014200b1b21140c010b2007200741017622066b21140b024020012010470d00024020060d002005221021010c010b41002107200521102000210b0340201020073a0000200741016a210702400240200b2802002012200c200b41046a280200220f200f200c4b1b10ea062201450d00417f410120014100481b210f0c010b417f200f200c47200f200c491b210f0b200b41086a210b2010200f417f476a211020062007470d000b200521010b02402011200e470d00024020140d0020054180016a220e21110c010b200d41786a21074100210b20054180016a210e0340200e200b3a0000200b41016a210b0240024020072802002012200c200741046a280200220f200f200c4b1b10ea062211450d00417f410120114100481b210f0c010b417f200f200c47200f200c491b210f0b200741786a2107200e200f417f466a210e2014200b470d000b20054180016a21110b0240200e20116b2207201020016b220b200b20074b1b2213450d00200020012d00004103746a22072802042115200728020021162007200d20112d0000417f734103746a290200370200024020134101460d00410021070340200d201120076a220b2d0000417f734103746a2000200120076a41016a220f2d00004103746a2902003702002000200f2d00004103746a200d200b41016a2d0000417f734103746a290200370200200741026a210b200741016a220f2107200b2013490d000b2011200f6a21112001200f6a21010b200d20112d0000417f734103746a2207201536020420072016360200201141016a2111200141016a21010b200d20144103746b200d2011200e461b210d200020064103746a200020012010461b2100200a0d000b02400240200120104f0d00200d2107034020002010417f6a22102d00004103746a220b2902002117200b200741786a22072902003702002007201737020020012010490d000c020b0b200021072011200e4f0d000340200729020021172007200d200e417f6a220e2d0000417f734103746a220b290200370200200b2017370200200741086a21072011200e490d000b0b2009200c36020420092012360200024020082007201a6b41037620186a22014d0d00200929020021172009200920014103746a220729020037020020072017370200200820016b220c450d02200c20012001200c4b1b210b20084103762110200741086a2100024002402001200c417f6a220c490d002000200c20022007200410a406200921000c010b2009200120022003200410a40620072103200c21010b200b20104f2106201920184d2107200141154f0d010c040b0b4198bbca0020012008103b000b41a8bbca00411c41c4bbca001039000b4198bbca0020102008103b000b20014102490d00200041786a2111410021124101210f0340200f4103742107200f417f6a210c200f41016a210f024002400240200020076a2210280200220d2000200c4103746a2207280200200741046a280200220e201041046a280200220b200b200e4b1b10ea062213450d0020134100480d010c020b200b200e4f0d010b201020072902003702000240200c450d002012210c201121070240034002400240200d2007280200200741046a2802002210200b200b20104b1b10ea06220e450d00200e41004e0d030c010b200b20104f0d020b200741086a2007290200370200200741786a2107200c41016a2210200c49210e2010210c200e450d000b0b200741086a21070b2007200d3602002007200b3602040b2012417f6a2112201141086a2111200f2001470d000b0b20054180026a24000bf50202057f017e02400240024020014108490d00200141017641feffffff07712202417f6a220320014f0d022001410d74200173220441117620047322044105742004732205417f2001417f6a677622067122044100200120042001491b6b220420014f0d01200020034103746a220329020021072003200020044103746a220429020037020020042007370200024020022001490d00200221030c030b2005410d7420057322044111762004732204410574200473220520067122044100200120042001491b6b220420014f0d01200020024103746a220329020021072003200020044103746a2204290200370200200420073702002002410172220320014f0d022005410d742005732204411176200473220441057420047320067122044100200120042001491b6b220420014f0d01200020034103746a220129020021072001200020044103746a2200290200370200200020073702000b0f0b4198bbca0020042001103b000b4188bbca0020032001103b000bb20102037f017e024020014101762202450d00200020012002417f6a10a8062002417e6a210203402002417f460d0120002001200210a8062002417f6a21020c000b0b0240024020014102490d00200141037420006a41786a21022001210303402003417f6a220420014f0d0220002902002105200020022902003702002002200537020020002004410010a806200241786a210220042103200441014b0d000b0b0f0b4198bbca002003417f6a2001103b000b8f06050a7f017e017f017e037f200041686a2102200041786a210320014132492104410121054100210602400240024003400240024020052001490d00410021070c010b200320054103746a210841012107034002400240200841086a22092802002008280200200841046a280200220a2008410c6a28020022082008200a4b1b10ea06220b450d00200b4100480d030c010b2008200a490d020b4101210a200541016a220520014921072009210820012005470d000c030b0b2005200146210a20040d0120052001460d012005417f6a220820014f0d032007410171450d02200020084103746a2208290200210c200820002005410374220d6a2209290200220e3702002009200c370200024020054102490d0002400240200ea7220f20002005417e6a22074103746a220b280200200b41046a2802002210200841046a280200220a200a20104b1b10ea062211450d0020114100480d010c020b200a20104f0d010b2008200b29020037020002402007450d002002200d6a21080240034002400240200f2008280200200841046a280200220b200a200a200b4b1b10ea062210450d00201041004e0d030c010b200a200b4f0d020b200841086a2008290200370200200841786a21082007417f6a22070d000b0b200841086a210b0b200b200f360200200b200a3602040b200641016a21060240200120056b220f4102490d000240024020092802082009280200220d200941046a280200220b2009410c6a28020022082008200b4b1b10ea06220a450d00200a4100480d010c020b2008200b4f0d010b200941086a2111200920092902083702000240200f4103490d004103210a41022107034002400240200920074103746a2208280200200d200b200841046a28020022072007200b4b1b10ea062210450d00201041004e0d030c010b2007200b4f0d020b200841786a20082902003702000240200a200f4f0d00200a2107200a41016a210a200821110c010b0b200821110b2011200d3602002011200b3602040b20064105470d000b4100210a0b200a0f0b4198bbca0020052001103b000b4188bbca0020082001103b000bb60202057f017e03402002410174220341017221040240024002400240200341026a220320014f0d00200420014f0d0102400240200020044103746a2205280200200020034103746a2206280200200641046a2802002206200541046a2802002205200520064b1b10ea062207450d00417f410120074100481b21060c010b417f200520064720052006491b21060b200320042006417f461b21040b0240200420014f0d00200220014f0d020240200020024103746a2202280200200020044103746a2203280200200341046a2802002206200241046a2802002205200520064b1b10ea062207450d00200741004e0d010c040b20052006490d030b0f0b41b0bcca0020042001103b000b41c0bcca0020022001103b000b200229020021082002200329020037020020032008370200200421020c000b0b8d0302037f017e230041c0006b22022400200141086a28020021032001280204210420022001280200220136020002400240024002402001418080044b0d002004450d022002200336020402400240200120034b0d002003418080044d0d042002413c6a41013602002002420237022c200241f4d7ca003602282002410136020c200241d0d7ca003602082002200241086a360238200241186a200241286a103a200241186a21010c010b2002413c6a4102360200200241246a41013602002002420237022c200241e4d7ca003602282002410136021c2002200241186a360238200220023602202002200241046a360218200241086a200241286a103a200241086a21010b20012902042105200128020021010c010b2002413c6a41013602002002420237022c200241d4d7ca003602282002410136020c200241d0d7ca003602082002200241086a360238200241186a200241286a103a20022802182101200229021c21050b2001450d0020002005370204200020013602000c010b200041003602000b200241c0006a24000be00501037f230041f0006b2204240002400240024020012802084102460d00412e102d2201450d01200041013a0000200141266a41002900e8d94a370000200141206a41002900e2d94a370000200141186a41002900dad94a370000200141106a41002900d2d94a370000200141086a41002900cad94a370000200141002900c2d94a370000200041086a42ae808080e005370200200041046a20013602000c020b0240024002400240024002400240200128020022052d0000416e6a2201411e4b0d004100210620010e1f03000000000000000000000000000000000000000000000000000006040102030b4120102d2201450d06200041013a0000200141186a4100290088da4a370000200141106a4100290080da4a370000200141086a41002900f8d94a370000200141002900f0d94a370000200041086a42a08080808004370200200041046a20013602000c070b410221060c040b410321060c030b20042005280204220136020c0240024020012003490d004190daca002105200441e8006a2103200441d0006a2101200441c0006a21020c010b200220014101746a22012d0001450d0241a0daca002105200441386a2103200441206a2101200441106a21020b20034101360204200141146a410136020020012003360210200142023702042001200536020020032004410c6a36020020022001103a200041013a00002000410c6a200241086a280200360200200041046a20022902003702000c040b410121060c010b20012d000021060b0240200541106a2d00004106470d00200041003a0000200020063a00010c020b4129102d2201450d00200041013a0000200141286a41002d00d8da4a3a0000200141206a41002900d0da4a370000200141186a41002900c8da4a370000200141106a41002900c0da4a370000200141086a41002900b8da4a370000200141002900b0da4a370000200041086a42a98080809005370200200041046a20013602000c010b1036000b200441f0006a24000b8f0201017f230041106b220224000240024002400240024020002d00000e0401020300010b200220012802184198afca0041032001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c030b20022001280218419bafca0041032001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c020b20022001280218419eafca0041032001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c010b2002200128021841a1afca0041032001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040b200241106a240020000be2bd0205047f017e047f017e017f230041f0006b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020022d00000eac0101ca0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa0100010b200341d8006a200141186a2204200141286a410110d706024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490dc801200241017422062005200620054b1b22054100480dc8010240024020020d002005102d21020c010b200428020020022005103121020b2002450dc701200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000ccb010b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450dca012003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b2001450dca010cc9010b200328025c2201450dc901200341e0006a29030021070cc8010b02400240200141306a2802002202417f6a220420024f0d00200420024d0d010b4118102d2201450dc4012003421837025c20032001360258200341d8006a4100411810d80620032003280260220141186a3602602001200328025822006a41184192ddca00411810d9062003200329025c37025c20032000360258418fd1ca00413b200341d8006a41ccd1ca0041dcd1ca00103e000b02400240200128022820044103746a22052802002204200141206a220628020022024b0d00200421010c010b024002402001411c6a280200220820026b200420026b2209490d0020012802182108200221010c010b200220096a220a2002490dc6012008410174220b200a200b200a4b1b220a4100480dc6010240024020080d00200a102d21080c010b20012802182008200a103121080b2008450dc501200120083602182001411c6a200a360200200141206a28020021010b200820016a210a0240024020094102490d00200a410420042002417f736a220210e7061a2008200220016a22016a210a0c010b2009450d010b200a41043a0000200141016a21010b20062001360200200541013a00060cc8010b0240200141306a2802002204200141346a22052802004f0d0020023100012107200141206a350200210c024020042001412c6a280200470d00200441016a22022004490dc501200441017422052002200520024b1b220241ffffffff01712002470dc501200241037422024100480dc5010240024020040d002002102d21040c010b200128022820044103742002103121040b2004450dc401200120043602282001412c6a2002410376360200200141306a28020021040b200128022820044103746a2007422886200c84370200200141306a2201200128020041016a3602000cc8010b200341ec006a220141013602002003420137025c200341fcdeca00360258200341013602042003200536020020032003360268200341106a200341d8006a103a20032802102202450dc7012003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b2001450dc70120002007370204200020013602000cc8010b0240200141306a2802002204200141346a22052802004f0d0020023100012107200141206a350200210c024020042001412c6a280200470d00200441016a22022004490dc401200441017422052002200520024b1b220241ffffffff01712002470dc401200241037422024100480dc4010240024020040d002002102d21040c010b200128022820044103742002103121040b2004450dc301200120043602282001412c6a2002410376360200200141306a28020021040b200128022820044103746a2007422886200c8442808080803084370200200141306a2201200128020041016a3602000cc7010b200341ec006a220141013602002003420137025c200341fcdeca00360258200341013602042003200536020020032003360268200341106a200341d8006a103a20032802102202450dc6012003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b2001450dc60120002007370204200020013602000cc7010b20023100012107200341d8006a200141186a200141286a2204410010d70620032d00584101460da6010240200141306a2802002202200141346a22052802004f0d00200141206a350200210c024020022001412c6a280200470d00200241016a22052002490dc301200241017422062005200620054b1b220541ffffffff01712005470dc301200541037422054100480dc3010240024020020d002005102d21020c010b200428020020024103742005103121020b2002450dc201200120023602282001412c6a2005410376360200200141306a28020021020b200128022820024103746a2007422886200c8442808080801084370200200141306a2201200128020041016a3602000cc6010b200341ec006a220141013602002003420137025c200341fcdeca00360258200341013602042003200536020020032003360268200341106a200341d8006a103a20032802102202450dc5012003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b2001450dc50120002007370204200020013602000cc6010b02400240200141306a2802002202417f6a220420024f0d00200420024d0d010b4118102d2201450dc0012003421837025c20032001360258200341d8006a4100411810d80620032003280260220141186a3602602001200328025822006a41184192ddca00411810d9062003200329025c37025c2003200036025841ecd1ca004134200341d8006a41ccd1ca0041a0d2ca00103e000b02400240200141286a220228020020044103746a22042d00044101470d0020043100052107200341d8006a200141186a200210da062003280258450d0120002003290358370200200041086a200341d8006a41086a2802003602000cc7010b411a102d2201450dc001200141186a41002f00c8d24a3b0000200141106a41002900c0d24a370000200141086a41002900b8d24a370000200141002900b0d24a3700002000429a808080a003370204200020013602000cc6010b0240200141306a2802002204200141346a22052802004f0d00200141206a350200210c024020042001412c6a280200470d00200441016a22052004490dc201200441017422062005200620054b1b220541ffffffff01712005470dc201200541037422054100480dc2010240024020040d002005102d21020c010b200228020020044103742005103121020b2002450dc101200120023602282001412c6a2005410376360200200141306a28020021040b200128022820044103746a2007422886200c8442808080802084370200200141306a2201200128020041016a3602000cc5010b200341ec006a220141013602002003420137025c200341fcdeca00360258200341013602042003200536020020032003360268200341106a200341d8006a103a20032802102202450dc4012003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b2001450dc40120002007370204200020013602000cc5010b02400240200141306a2802002202417f6a220420024f0d00200420024d0d010b4118102d2201450dbf012003421837025c20032001360258200341d8006a4100411810d80620032003280260220141186a3602602001200328025822006a41184192ddca00411810d9062003200329025c37025c2003200036025841ecd1ca004134200341d8006a41ccd1ca0041a0d2ca00103e000b200141286a220628020020044103746a22042d00052105024020042d00044101470d00200541ff01714104470da6010b02400240024002400240024020024101460d00200341d8006a200141186a2202200610da0620032802580d01200541ff01714104460dc901200141206a2802002204200141246a22062802004f0d0520042001411c6a280200470d04200441016a22062004490dc501200441017422082006200820064b1b22064100480dc50120040d022006102d21020c030b024020012d003822024104460d00200341d8006a200141186a2006200210db062003280258450d0020002003290358370200200041086a200341d8006a41086a2802003602000cca010b200341d8006a200141186a200610da062003280258450dc80120002003290358370200200041086a200341d8006a41086a2802003602000cc9010b20002003290358370200200041086a200341d8006a41086a2802003602000cc8010b200228020020042006103121020b2002450dc001200120023602182001411c6a2006360200200141206a28020021040b200128021820046a20053a0000200141206a2201200128020041016a3602000cc4010b200341ec006a220141013602002003420137025c200341fcdeca00360258200341013602042003200636020020032003360268200341106a200341d8006a103a20032802102202450dc3012003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b2001450dc30120002007370204200020013602000cc4010b2003200241046a280200220236024802400240200141306a280200220420024d0d0020042002417f736a220220044f0da701200141286a220428020020024103746a22022d00044103460d0120022d0005220241ff01714104460d01200341d8006a200141186a2004200210db0620032802582202450d01200329025c21070cc2010b200341ec006a220241023602002003411c6a41013602002003420237025c200341acddca0036025820034101360214200320043602002003200341106a360268200320033602182003200341c8006a360210200341386a200341d8006a103a200328023821042003200329023c37023c20032004360238200241013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102102200329021421070240200328023c450d002003280238102f0b20020dc1010b024002400240200141306a2802002202417f6a220420024f0d00200420024b0d00200128022820044103746a22052802002204200141206a220628020022024b0d01200421010c020b4118102d2201450dbf012003421837025c20032001360258200341d8006a4100411810d80620032003280260220141186a3602602001200328025822006a41184192ddca00411810d9062003200329025c37025c20032000360258418fd1ca00413b200341d8006a41ccd1ca0041dcd1ca00103e000b024002402001411c6a280200220820026b200420026b2209490d0020012802182108200221010c010b200220096a220a2002490dc0012008410174220b200a200b200a4b1b220a4100480dc0010240024020080d00200a102d21080c010b20012802182008200a103121080b2008450dbf01200120083602182001411c6a200a360200200141206a28020021010b200820016a210a0240024020094102490d00200a410420042002417f736a220210e7061a2008200220016a22016a210a0c010b2009450d010b200a41043a0000200141016a21010b20062001360200200541013a00060cc2010b200241046a2802002102200341d8006a200141186a2205200141286a2204410010d70602400240024020032d00584101460d00200141306a2802002101200320023602480240200120024d0d0020012002417f736a220220014f0db001200428020020024103746a22012d00044103460dc50120012d0005220141ff01714104460dc501200341d8006a20052004200110db0620032802582201450dc501200329025c21070c030b200341ec006a220241023602002003411c6a41013602002003420237025c200341acddca0036025820034101360214200320013602002003200341106a360268200320033602182003200341c8006a360210200341386a200341d8006a103a200328023821012003200329023c37023c20032001360238200241013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a2003280210210120032902142107200328023c450d012003280238102f0c010b200341e0006a2903002107200328025c21010b2001450dc2010b20002007370204200020013602000cc2010b200241046a2802002202280204210620022802002104200320022802082205360248200141306a280200220220054d0db90120022005417f736a220520024f0da4014104210a0240200141286a220d280200220820054103746a22052d00044103460d0020052d0005210a0b2003200a3a00302006450db301200a41ff0171220b4104460db201200641027421060340200320042802002205360248200220054d0db50120022005417f736a220520024f0dbe01200820054103746a22052d00044103460db60120052d000522094104460db601200b2009470db601200441046a21042006417c6a22060d000cb4010b0b024020012d003822024104460d00200341d8006a200141186a200141286a200210db062003280258450d0020002003290358370200200041086a200341d8006a41086a2802003602000cc1010b02400240200141306a2802002202417f6a220420024f0d00200420024d0d010b4118102d2201450dbb012003421837025c20032001360258200341d8006a4100411810d80620032003280260220141186a3602602001200328025822006a41184192ddca00411810d9062003200329025c37025c20032000360258418fd1ca00413b200341d8006a41ccd1ca0041dcd1ca00103e000b02400240200128022820044103746a22052802002204200141206a220628020022024b0d00200421010c010b024002402001411c6a280200220820026b200420026b2209490d0020012802182108200221010c010b200220096a220a2002490dbd012008410174220b200a200b200a4b1b220a4100480dbd010240024020080d00200a102d21080c010b20012802182008200a103121080b2008450dbc01200120083602182001411c6a200a360200200141206a28020021010b200820016a210a0240024020094102490d00200a410420042002417f736a220210e7061a2008200220016a22016a210a0c010b2009450d010b200a41043a0000200141016a21010b20062001360200200541013a00060cbf010b200128020021042003200241046a2802002202360254024002400240024002400240024002400240200441386a28020020024d0d002003200428023020024102746a2802002202360200024002402004412c6a28020020024d0d002003411c6a200428022420024104746a22042d000d22083a0000200341186a2004280208220236020020042802002104410021050c010b41012105200341ec006a41013602002003420237025c20034184dcca003602582003410136024c2003200341c8006a36026820032003360248200341386a200341d8006a103a200341186a200329023c22073703002007422088a72108200328023821042007a721020b200320053602102003200436021420050d0102402002450d002004417f6a2104200141286a2105200141186a21060340200341d8006a20062005200420026a2d000010d70620032d00584101460d082002417f6a22020d000b0b200841ff01714104460dc701200141206a2802002202200141246a22042802004f0d0520022001411c6a280200470d04200241016a22042002490dc301200241017422052004200520044b1b22044100480dc30120020d022004102d21020c030b200341ec006a41013602002003420237025c200341e0dbca00360258200341013602342003200341306a3602682003200341d4006a360230200341386a200341d8006a103a200341186a200329023c370300200341013602102003200328023822043602140b200341186a21010c050b200128021820022004103121020b2002450dbe01200120023602182001411c6a2004360200200141206a28020021020b200128021820026a20083a0000200141206a2201200128020041016a3602000cc2010b200341ec006a220141013602002003420137025c200341fcdeca00360258200341013602042003200436020020032003360268200341106a200341d8006a103a20032802102202450dc1012003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102104200329021421070240200328023c450d002003280238102f0b20040d020cc1010b200341e0006a2101200328025c21040b2004450dbf01200129020021070b20002007370204200020043602000cbf010b200241046a28020021062001280200210220034100360238200241146a280200450da201200341d8006a200141186a2204200141286a2205410010d70620032d00584101460da30120012802002208412c6a28020021022003200636023802400240024002400240200220064d0d00200828022420064104746a22062d000d2108024020062802082202450d002006280200417f6a21060340200341d8006a20042005200620026a2d000010d70620032d00584101460dab012002417f6a22020d000b0b200841ff01714104460dc201200141206a2802002202200141246a22052802004f0d0420022001411c6a280200470d03200241016a22052002490dbe01200241017422062005200620054b1b22054100480dbe0120020d012005102d21020c020b200341ec006a41013602002003420237025c20034184dcca0036025820034101360204200320033602682003200341386a360200200341106a200341d8006a103a0cb1010b200428020020022005103121020b2002450dba01200120023602182001411c6a2005360200200141206a28020021020b200128021820026a20083a0000200141206a2201200128020041016a3602000cbe010b200341ec006a220141013602002003420137025c200341fcdeca00360258200341013602042003200536020020032003360268200341106a200341d8006a103a20032802102202450dbd012003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a2003280210210120032902142107200328023c450dae012003280238102f0cae010b200341d8006a200141186a200141286a410410d70620032d00584101470dbc01200328025c2201450dbc012000200341e0006a290300370204200020013602000cbd010b200341d8006a200141186a2204200141286a2205410010d706200341d8006a21020240024020032d00584101460d00200341d8006a20042005410410d706200341d8006a210220032d00584101460d00200341d8006a2004200520032d0059220610d706200341d8006a210220032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490dbb01200241017422082005200820054b1b22054100480dbb010240024020020d002005102d21020c010b200428020020022005103121020b2002450dba01200120023602182001411c6a2005360200200141206a28020021020b200128021820026a20063a0000200141206a2201200128020041016a3602000cbe010b200341ec006a220141013602002003420137025c200341fcdeca00360258200341013602042003200536020020032003360268200341106a200341d8006a103a20032802102202450dbd012003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010cbd010b200241046a2802002201450dbc01200241086a29020021070b20002007370204200020013602000cbc010b200341d8006a200141046a200241046a28020010dc060240024020032d00584101460d000240200141206a2802002202200141246a22042802004f0d0020032d00592104024020022001411c6a280200470d00200241016a22052002490dba01200241017422062005200620054b1b22054100480dba010240024020020d002005102d21020c010b200128021820022005103121020b2002450db901200120023602182001411c6a2005360200200141206a28020021020b200128021820026a20043a0000200141206a2201200128020041016a3602000cbd010b200341ec006a220141013602002003420137025c200341fcdeca00360258200341013602042003200436020020032003360268200341106a200341d8006a103a20032802102202450dbc012003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010cbc010b200328025c2201450dbb01200341e0006a29030021070b20002007370204200020013602000cbb010b2003200241046a2802002202360200200341d8006a200141046a200210dc060240024020032d00584101460d00200320032d005922023a0030200341d8006a200141186a200141286a410410d7060240024020032d00584101460d00200320032d005922013a004820014104460dbd01200241ff01712001460dbd01200341106a41146a41373602002003411c6a4130360200200341d8006a41146a41033602002003420337025c200341ecd2ca00360258200341013602142003200341106a3602682003200341c8006a3602202003200341306a36021820032003360210200341386a200341d8006a103a0c010b200341c0006a200341e4006a2802003602002003200329025c3703380b200329023c2107200328023821010c010b2003200328025c22013602382003200341e0006a290300220737023c0b2001450db90120002007370204200020013602000cba010b200341d8006a200141046a200241046a28020010dc060240024020032d00584101460d00200341d8006a200141186a200141286a20032d005910db0620032802582201450dba01200329025c21070c010b200328025c2201450db901200341e0006a29030021070b20002007370204200020013602000cb9010b200128020021042003200241046a280200220236023802400240200441206a28020020024d0d000240200141206a2802002205200141246a22062802004f0d00200428021820024101746a2d00002102024020052001411c6a280200470d00200541016a22042005490db701200541017422062004200620044b1b22044100480db7010240024020050d002004102d21050c010b200128021820052004103121050b2005450db601200120053602182001411c6a2004360200200141206a28020021050b200128021820056a20023a0000200141206a2201200128020041016a3602000cba010b200341ec006a220141013602002003420137025c200341fcdeca00360258200341013602042003200636020020032003360268200341106a200341d8006a103a20032802102202450db9012003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010cb9010b200341ec006a41013602002003420237025c200341a4dcca003602582003410136024c2003200341c8006a3602682003200341386a360248200341106a200341d8006a103a20032802102201450db801200329021421070b20002007370204200020013602000cb8010b2003200241046a28020022023602282001280200210420032002360254200441206a28020020024d0d9e010240200428021820024101746a22022d00010d00200341ec006a41013602002003420237025c200341b4dcca0036025820034101360204200320033602682003200341d4006a360200200341106a200341d8006a103a0ca5010b200320022d000022023a002f200341d8006a200141186a200141286a410410d70620032d00584101470da201200341c0006a200341e4006a2802003602002003200329025c3703380ca3010b200341d8006a2001200241046a2802004104410010de062003280258450db50120002003290358370200200041086a200341d8006a41086a2802003602000cb6010b200341d8006a2001200241046a2802004108410110de062003280258450db40120002003290358370200200041086a200341d8006a41086a2802003602000cb5010b200341d8006a2001200241046a2802004104410210de062003280258450db30120002003290358370200200041086a200341d8006a41086a2802003602000cb4010b200341d8006a2001200241046a2802004108410310de062003280258450db20120002003290358370200200041086a200341d8006a41086a2802003602000cb3010b200341d8006a2001200241046a2802004101410010de062003280258450db10120002003290358370200200041086a200341d8006a41086a2802003602000cb2010b200341d8006a2001200241046a2802004101410010de062003280258450db00120002003290358370200200041086a200341d8006a41086a2802003602000cb1010b200341d8006a2001200241046a2802004102410010de062003280258450daf0120002003290358370200200041086a200341d8006a41086a2802003602000cb0010b200341d8006a2001200241046a2802004102410010de062003280258450dae0120002003290358370200200041086a200341d8006a41086a2802003602000caf010b200341d8006a2001200241046a2802004101410110de062003280258450dad0120002003290358370200200041086a200341d8006a41086a2802003602000cae010b200341d8006a2001200241046a2802004101410110de062003280258450dac0120002003290358370200200041086a200341d8006a41086a2802003602000cad010b200341d8006a2001200241046a2802004102410110de062003280258450dab0120002003290358370200200041086a200341d8006a41086a2802003602000cac010b200341d8006a2001200241046a2802004102410110de062003280258450daa0120002003290358370200200041086a200341d8006a41086a2802003602000cab010b200341d8006a2001200241046a2802004104410110de062003280258450da90120002003290358370200200041086a200341d8006a41086a2802003602000caa010b200341d8006a2001200241046a2802004104410110de062003280258450da80120002003290358370200200041086a200341d8006a41086a2802003602000ca9010b200341d8006a2001200241046a2802004104410010df062003280258450da70120002003290358370200200041086a200341d8006a41086a2802003602000ca8010b200341d8006a2001200241046a2802004108410110df062003280258450da60120002003290358370200200041086a200341d8006a41086a2802003602000ca7010b200341d8006a2001200241046a2802004104410210df062003280258450da50120002003290358370200200041086a200341d8006a41086a2802003602000ca6010b200341d8006a2001200241046a2802004108410310df062003280258450da40120002003290358370200200041086a200341d8006a41086a2802003602000ca5010b200341d8006a2001200241046a2802004101410010df062003280258450da30120002003290358370200200041086a200341d8006a41086a2802003602000ca4010b200341d8006a2001200241046a2802004102410010df062003280258450da20120002003290358370200200041086a200341d8006a41086a2802003602000ca3010b200341d8006a2001200241046a2802004101410110df062003280258450da10120002003290358370200200041086a200341d8006a41086a2802003602000ca2010b200341d8006a2001200241046a2802004102410110df062003280258450da00120002003290358370200200041086a200341d8006a41086a2802003602000ca1010b200341d8006a2001200241046a2802004104410110df062003280258450d9f0120002003290358370200200041086a200341d8006a41086a2802003602000ca0010b20012802002102200341003602380240024020022802080d00200341ec006a41013602002003420237025c20034190dbca0036025820034101360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102202450d00200329021421070c010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490d9d01200241017422052004200520044b1b22044100480d9d010240024020020d002004102d21020c010b200128021820022004103121020b2002450d9c01200120023602182001411c6a2004360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000ca0010b200341ec006a220141013602002003420137025c200341fcdeca00360258200341013602042003200436020020032003360268200341106a200341d8006a103a20032802102202450d9f012003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102102200329021421070240200328023c450d002003280238102f0b2002450d9f010b20002007370204200020023602000c9f010b20012802002102200341003602380240024020022802080d00200341ec006a41013602002003420237025c20034190dbca0036025820034101360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102202450d00200329021421070c010b200341d8006a200141186a2204200141286a410010d706024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d9d01200241017422062005200620054b1b22054100480d9d010240024020020d002005102d21020c010b200428020020022005103121020b2002450d9c01200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000ca0010b200341ec006a220141013602002003420137025c200341fcdeca00360258200341013602042003200536020020032003360268200341106a200341d8006a103a20032802102202450d9f012003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102102200329021421070240200328023c450d002003280238102f0b20020d010c9f010b200328025c2202450d9e01200341e0006a29030021070b20002007370204200020023602000c9e010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490d9a01200241017422052004200520044b1b22044100480d9a010240024020020d002004102d21020c010b200128021820022004103121020b2002450d9901200120023602182001411c6a2004360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c9d010b200341ec006a220141013602002003420137025c200341fcdeca00360258200341013602042003200436020020032003360268200341106a200341d8006a103a20032802102202450d9c012003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b2001450d9c0120002007370204200020013602000c9d010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490d9901200241017422052004200520044b1b22044100480d99010240024020020d002004102d21020c010b200128021820022004103121020b2002450d9801200120023602182001411c6a2004360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000c9c010b200341ec006a220141013602002003420137025c200341fcdeca00360258200341013602042003200436020020032003360268200341106a200341d8006a103a20032802102202450d9b012003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b2001450d9b0120002007370204200020013602000c9c010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490d9801200241017422052004200520044b1b22044100480d98010240024020020d002004102d21020c010b200128021820022004103121020b2002450d9701200120023602182001411c6a2004360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c9b010b200341ec006a220141013602002003420137025c200341fcdeca00360258200341013602042003200436020020032003360268200341106a200341d8006a103a20032802102202450d9a012003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b2001450d9a0120002007370204200020013602000c9b010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490d9701200241017422052004200520044b1b22044100480d97010240024020020d002004102d21020c010b200128021820022004103121020b2002450d9601200120023602182001411c6a2004360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c9a010b200341ec006a220141013602002003420137025c200341fcdeca00360258200341013602042003200436020020032003360268200341106a200341d8006a103a20032802102202450d99012003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b2001450d990120002007370204200020013602000c9a010b200341d8006a200141186a2204200141286a410010d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d9801200241017422062005200620054b1b22054100480d98010240024020020d002005102d21020c010b200428020020022005103121020b2002450d9701200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c9b010b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d9a012003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c9a010b200328025c2201450d9901200341e0006a29030021070b20002007370204200020013602000c99010b200341d8006a2001410010e0062003280258450d970120002003290358370200200041086a200341d8006a41086a2802003602000c98010b200341d8006a2001410010e0062003280258450d960120002003290358370200200041086a200341d8006a41086a2802003602000c97010b200341d8006a2001410010e0062003280258450d950120002003290358370200200041086a200341d8006a41086a2802003602000c96010b200341d8006a2001410010e0062003280258450d940120002003290358370200200041086a200341d8006a41086a2802003602000c95010b200341d8006a2001410010e0062003280258450d930120002003290358370200200041086a200341d8006a41086a2802003602000c94010b200341d8006a2001410010e0062003280258450d920120002003290358370200200041086a200341d8006a41086a2802003602000c93010b200341d8006a2001410010e0062003280258450d910120002003290358370200200041086a200341d8006a41086a2802003602000c92010b200341d8006a2001410010e0062003280258450d900120002003290358370200200041086a200341d8006a41086a2802003602000c91010b200341d8006a2001410010e0062003280258450d8f0120002003290358370200200041086a200341d8006a41086a2802003602000c90010b200341d8006a2001410010e0062003280258450d8e0120002003290358370200200041086a200341d8006a41086a2802003602000c8f010b200341d8006a200141186a2204200141286a410110d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d8d01200241017422062005200620054b1b22054100480d8d010240024020020d002005102d21020c010b200428020020022005103121020b2002450d8c01200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c90010b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d8f012003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c8f010b200328025c2201450d8e01200341e0006a29030021070b20002007370204200020013602000c8e010b200341d8006a2001410110e0062003280258450d8c0120002003290358370200200041086a200341d8006a41086a2802003602000c8d010b200341d8006a2001410110e0062003280258450d8b0120002003290358370200200041086a200341d8006a41086a2802003602000c8c010b200341d8006a2001410110e0062003280258450d8a0120002003290358370200200041086a200341d8006a41086a2802003602000c8b010b200341d8006a2001410110e0062003280258450d890120002003290358370200200041086a200341d8006a41086a2802003602000c8a010b200341d8006a2001410110e0062003280258450d880120002003290358370200200041086a200341d8006a41086a2802003602000c89010b200341d8006a2001410110e0062003280258450d870120002003290358370200200041086a200341d8006a41086a2802003602000c88010b200341d8006a2001410110e0062003280258450d860120002003290358370200200041086a200341d8006a41086a2802003602000c87010b200341d8006a2001410110e0062003280258450d850120002003290358370200200041086a200341d8006a41086a2802003602000c86010b200341d8006a2001410110e0062003280258450d840120002003290358370200200041086a200341d8006a41086a2802003602000c85010b200341d8006a2001410110e0062003280258450d830120002003290358370200200041086a200341d8006a41086a2802003602000c84010b200341d8006a2001410210e0062003280258450d820120002003290358370200200041086a200341d8006a41086a2802003602000c83010b200341d8006a2001410210e0062003280258450d810120002003290358370200200041086a200341d8006a41086a2802003602000c82010b200341d8006a2001410210e0062003280258450d800120002003290358370200200041086a200341d8006a41086a2802003602000c81010b200341d8006a2001410210e0062003280258450d7f20002003290358370200200041086a200341d8006a41086a2802003602000c80010b200341d8006a2001410210e0062003280258450d7e20002003290358370200200041086a200341d8006a41086a2802003602000c7f0b200341d8006a2001410210e0062003280258450d7d20002003290358370200200041086a200341d8006a41086a2802003602000c7e0b200341d8006a2001410310e0062003280258450d7c20002003290358370200200041086a200341d8006a41086a2802003602000c7d0b200341d8006a2001410310e0062003280258450d7b20002003290358370200200041086a200341d8006a41086a2802003602000c7c0b200341d8006a2001410310e0062003280258450d7a20002003290358370200200041086a200341d8006a41086a2802003602000c7b0b200341d8006a2001410310e0062003280258450d7920002003290358370200200041086a200341d8006a41086a2802003602000c7a0b200341d8006a2001410310e0062003280258450d7820002003290358370200200041086a200341d8006a41086a2802003602000c790b200341d8006a2001410310e0062003280258450d7720002003290358370200200041086a200341d8006a41086a2802003602000c780b200341d8006a200141186a2204200141286a410010d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d76200241017422062005200620054b1b22054100480d760240024020020d002005102d21020c010b200428020020022005103121020b2002450d75200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c790b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d782003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c780b200328025c2201450d77200341e0006a29030021070b20002007370204200020013602000c770b200341d8006a200141186a2204200141286a410010d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d75200241017422062005200620054b1b22054100480d750240024020020d002005102d21020c010b200428020020022005103121020b2002450d74200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c780b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d772003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c770b200328025c2201450d76200341e0006a29030021070b20002007370204200020013602000c760b200341d8006a200141186a2204200141286a410010d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d74200241017422062005200620054b1b22054100480d740240024020020d002005102d21020c010b200428020020022005103121020b2002450d73200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c770b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d762003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c760b200328025c2201450d75200341e0006a29030021070b20002007370204200020013602000c750b200341d8006a2001410010e1062003280258450d7320002003290358370200200041086a200341d8006a41086a2802003602000c740b200341d8006a2001410010e1062003280258450d7220002003290358370200200041086a200341d8006a41086a2802003602000c730b200341d8006a2001410010e1062003280258450d7120002003290358370200200041086a200341d8006a41086a2802003602000c720b200341d8006a2001410010e1062003280258450d7020002003290358370200200041086a200341d8006a41086a2802003602000c710b200341d8006a2001410010e1062003280258450d6f20002003290358370200200041086a200341d8006a41086a2802003602000c700b200341d8006a2001410010e1062003280258450d6e20002003290358370200200041086a200341d8006a41086a2802003602000c6f0b200341d8006a2001410010e1062003280258450d6d20002003290358370200200041086a200341d8006a41086a2802003602000c6e0b200341d8006a2001410010e1062003280258450d6c20002003290358370200200041086a200341d8006a41086a2802003602000c6d0b200341d8006a2001410010e1062003280258450d6b20002003290358370200200041086a200341d8006a41086a2802003602000c6c0b200341d8006a2001410010e1062003280258450d6a20002003290358370200200041086a200341d8006a41086a2802003602000c6b0b200341d8006a2001410010e1062003280258450d6920002003290358370200200041086a200341d8006a41086a2802003602000c6a0b200341d8006a2001410010e1062003280258450d6820002003290358370200200041086a200341d8006a41086a2802003602000c690b200341d8006a2001410010e1062003280258450d6720002003290358370200200041086a200341d8006a41086a2802003602000c680b200341d8006a2001410010e1062003280258450d6620002003290358370200200041086a200341d8006a41086a2802003602000c670b200341d8006a2001410010e1062003280258450d6520002003290358370200200041086a200341d8006a41086a2802003602000c660b200341d8006a200141186a2204200141286a410110d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d64200241017422062005200620054b1b22054100480d640240024020020d002005102d21020c010b200428020020022005103121020b2002450d63200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000c670b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d662003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c660b200328025c2201450d65200341e0006a29030021070b20002007370204200020013602000c650b200341d8006a200141186a2204200141286a410110d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d63200241017422062005200620054b1b22054100480d630240024020020d002005102d21020c010b200428020020022005103121020b2002450d62200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000c660b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d652003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c650b200328025c2201450d64200341e0006a29030021070b20002007370204200020013602000c640b200341d8006a200141186a2204200141286a410110d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d62200241017422062005200620054b1b22054100480d620240024020020d002005102d21020c010b200428020020022005103121020b2002450d61200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000c650b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d642003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c640b200328025c2201450d63200341e0006a29030021070b20002007370204200020013602000c630b200341d8006a2001410110e1062003280258450d6120002003290358370200200041086a200341d8006a41086a2802003602000c620b200341d8006a2001410110e1062003280258450d6020002003290358370200200041086a200341d8006a41086a2802003602000c610b200341d8006a2001410110e1062003280258450d5f20002003290358370200200041086a200341d8006a41086a2802003602000c600b200341d8006a2001410110e1062003280258450d5e20002003290358370200200041086a200341d8006a41086a2802003602000c5f0b200341d8006a2001410110e1062003280258450d5d20002003290358370200200041086a200341d8006a41086a2802003602000c5e0b200341d8006a2001410110e1062003280258450d5c20002003290358370200200041086a200341d8006a41086a2802003602000c5d0b200341d8006a2001410110e1062003280258450d5b20002003290358370200200041086a200341d8006a41086a2802003602000c5c0b200341d8006a2001410110e1062003280258450d5a20002003290358370200200041086a200341d8006a41086a2802003602000c5b0b200341d8006a2001410110e1062003280258450d5920002003290358370200200041086a200341d8006a41086a2802003602000c5a0b200341d8006a2001410110e1062003280258450d5820002003290358370200200041086a200341d8006a41086a2802003602000c590b200341d8006a2001410110e1062003280258450d5720002003290358370200200041086a200341d8006a41086a2802003602000c580b200341d8006a2001410110e1062003280258450d5620002003290358370200200041086a200341d8006a41086a2802003602000c570b200341d8006a2001410110e1062003280258450d5520002003290358370200200041086a200341d8006a41086a2802003602000c560b200341d8006a2001410110e1062003280258450d5420002003290358370200200041086a200341d8006a41086a2802003602000c550b200341d8006a2001410110e1062003280258450d5320002003290358370200200041086a200341d8006a41086a2802003602000c540b200341d8006a200141186a2204200141286a410210d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d52200241017422062005200620054b1b22054100480d520240024020020d002005102d21020c010b200428020020022005103121020b2002450d51200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c550b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d542003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c540b200328025c2201450d53200341e0006a29030021070b20002007370204200020013602000c530b200341d8006a200141186a2204200141286a410210d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d51200241017422062005200620054b1b22054100480d510240024020020d002005102d21020c010b200428020020022005103121020b2002450d50200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c540b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d532003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c530b200328025c2201450d52200341e0006a29030021070b20002007370204200020013602000c520b200341d8006a200141186a2204200141286a410210d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d50200241017422062005200620054b1b22054100480d500240024020020d002005102d21020c010b200428020020022005103121020b2002450d4f200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c530b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d522003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c520b200328025c2201450d51200341e0006a29030021070b20002007370204200020013602000c510b200341d8006a200141186a2204200141286a410210d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d4f200241017422062005200620054b1b22054100480d4f0240024020020d002005102d21020c010b200428020020022005103121020b2002450d4e200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c520b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d512003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c510b200328025c2201450d50200341e0006a29030021070b20002007370204200020013602000c500b200341d8006a200141186a2204200141286a410210d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d4e200241017422062005200620054b1b22054100480d4e0240024020020d002005102d21020c010b200428020020022005103121020b2002450d4d200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c510b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d502003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c500b200328025c2201450d4f200341e0006a29030021070b20002007370204200020013602000c4f0b200341d8006a200141186a2204200141286a410210d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d4d200241017422062005200620054b1b22054100480d4d0240024020020d002005102d21020c010b200428020020022005103121020b2002450d4c200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c500b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d4f2003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c4f0b200328025c2201450d4e200341e0006a29030021070b20002007370204200020013602000c4e0b200341d8006a200141186a2204200141286a410210d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d4c200241017422062005200620054b1b22054100480d4c0240024020020d002005102d21020c010b200428020020022005103121020b2002450d4b200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c4f0b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d4e2003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c4e0b200328025c2201450d4d200341e0006a29030021070b20002007370204200020013602000c4d0b200341d8006a2001410210e1062003280258450d4b20002003290358370200200041086a200341d8006a41086a2802003602000c4c0b200341d8006a2001410210e1062003280258450d4a20002003290358370200200041086a200341d8006a41086a2802003602000c4b0b200341d8006a2001410210e1062003280258450d4920002003290358370200200041086a200341d8006a41086a2802003602000c4a0b200341d8006a2001410210e1062003280258450d4820002003290358370200200041086a200341d8006a41086a2802003602000c490b200341d8006a2001410210e1062003280258450d4720002003290358370200200041086a200341d8006a41086a2802003602000c480b200341d8006a2001410210e1062003280258450d4620002003290358370200200041086a200341d8006a41086a2802003602000c470b200341d8006a2001410210e1062003280258450d4520002003290358370200200041086a200341d8006a41086a2802003602000c460b200341d8006a200141186a2204200141286a410310d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d44200241017422062005200620054b1b22054100480d440240024020020d002005102d21020c010b200428020020022005103121020b2002450d43200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c470b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d462003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c460b200328025c2201450d45200341e0006a29030021070b20002007370204200020013602000c450b200341d8006a200141186a2204200141286a410310d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d43200241017422062005200620054b1b22054100480d430240024020020d002005102d21020c010b200428020020022005103121020b2002450d42200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c460b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d452003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c450b200328025c2201450d44200341e0006a29030021070b20002007370204200020013602000c440b200341d8006a200141186a2204200141286a410310d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d42200241017422062005200620054b1b22054100480d420240024020020d002005102d21020c010b200428020020022005103121020b2002450d41200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c450b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d442003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c440b200328025c2201450d43200341e0006a29030021070b20002007370204200020013602000c430b200341d8006a200141186a2204200141286a410310d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d41200241017422062005200620054b1b22054100480d410240024020020d002005102d21020c010b200428020020022005103121020b2002450d40200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c440b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d432003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c430b200328025c2201450d42200341e0006a29030021070b20002007370204200020013602000c420b200341d8006a200141186a2204200141286a410310d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d40200241017422062005200620054b1b22054100480d400240024020020d002005102d21020c010b200428020020022005103121020b2002450d3f200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c430b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d422003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c420b200328025c2201450d41200341e0006a29030021070b20002007370204200020013602000c410b200341d8006a200141186a2204200141286a410310d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d3f200241017422062005200620054b1b22054100480d3f0240024020020d002005102d21020c010b200428020020022005103121020b2002450d3e200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c420b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d412003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c410b200328025c2201450d40200341e0006a29030021070b20002007370204200020013602000c400b200341d8006a200141186a2204200141286a410310d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d3e200241017422062005200620054b1b22054100480d3e0240024020020d002005102d21020c010b200428020020022005103121020b2002450d3d200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c410b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d402003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c400b200328025c2201450d3f200341e0006a29030021070b20002007370204200020013602000c3f0b200341d8006a2001410310e1062003280258450d3d20002003290358370200200041086a200341d8006a41086a2802003602000c3e0b200341d8006a2001410310e1062003280258450d3c20002003290358370200200041086a200341d8006a41086a2802003602000c3d0b200341d8006a2001410310e1062003280258450d3b20002003290358370200200041086a200341d8006a41086a2802003602000c3c0b200341d8006a2001410310e1062003280258450d3a20002003290358370200200041086a200341d8006a41086a2802003602000c3b0b200341d8006a2001410310e1062003280258450d3920002003290358370200200041086a200341d8006a41086a2802003602000c3a0b200341d8006a2001410310e1062003280258450d3820002003290358370200200041086a200341d8006a41086a2802003602000c390b200341d8006a2001410310e1062003280258450d3720002003290358370200200041086a200341d8006a41086a2802003602000c380b200341d8006a200141186a2204200141286a410110d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d36200241017422062005200620054b1b22054100480d360240024020020d002005102d21020c010b200428020020022005103121020b2002450d35200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c390b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d382003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c380b200328025c2201450d37200341e0006a29030021070b20002007370204200020013602000c370b200341d8006a200141186a2204200141286a410210d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d35200241017422062005200620054b1b22054100480d350240024020020d002005102d21020c010b200428020020022005103121020b2002450d34200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c380b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d372003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c370b200328025c2201450d36200341e0006a29030021070b20002007370204200020013602000c360b200341d8006a200141186a2204200141286a410210d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d34200241017422062005200620054b1b22054100480d340240024020020d002005102d21020c010b200428020020022005103121020b2002450d33200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c370b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d362003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c360b200328025c2201450d35200341e0006a29030021070b20002007370204200020013602000c350b200341d8006a200141186a2204200141286a410310d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d33200241017422062005200620054b1b22054100480d330240024020020d002005102d21020c010b200428020020022005103121020b2002450d32200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c360b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d352003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c350b200328025c2201450d34200341e0006a29030021070b20002007370204200020013602000c340b200341d8006a200141186a2204200141286a410310d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d32200241017422062005200620054b1b22054100480d320240024020020d002005102d21020c010b200428020020022005103121020b2002450d31200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c350b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d342003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c340b200328025c2201450d33200341e0006a29030021070b20002007370204200020013602000c330b200341d8006a200141186a2204200141286a410010d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d31200241017422062005200620054b1b22054100480d310240024020020d002005102d21020c010b200428020020022005103121020b2002450d30200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000c340b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d332003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c330b200328025c2201450d32200341e0006a29030021070b20002007370204200020013602000c320b200341d8006a200141186a2204200141286a410010d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d30200241017422062005200620054b1b22054100480d300240024020020d002005102d21020c010b200428020020022005103121020b2002450d2f200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000c330b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d322003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c320b200328025c2201450d31200341e0006a29030021070b20002007370204200020013602000c310b200341d8006a200141186a2204200141286a410210d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d2f200241017422062005200620054b1b22054100480d2f0240024020020d002005102d21020c010b200428020020022005103121020b2002450d2e200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000c320b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d312003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c310b200328025c2201450d30200341e0006a29030021070b20002007370204200020013602000c300b200341d8006a200141186a2204200141286a410210d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d2e200241017422062005200620054b1b22054100480d2e0240024020020d002005102d21020c010b200428020020022005103121020b2002450d2d200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000c310b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d302003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c300b200328025c2201450d2f200341e0006a29030021070b20002007370204200020013602000c2f0b200341d8006a200141186a2204200141286a410310d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d2d200241017422062005200620054b1b22054100480d2d0240024020020d002005102d21020c010b200428020020022005103121020b2002450d2c200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000c300b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d2f2003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c2f0b200328025c2201450d2e200341e0006a29030021070b20002007370204200020013602000c2e0b200341d8006a200141186a2204200141286a410310d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d2c200241017422062005200620054b1b22054100480d2c0240024020020d002005102d21020c010b200428020020022005103121020b2002450d2b200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000c2f0b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d2e2003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c2e0b200328025c2201450d2d200341e0006a29030021070b20002007370204200020013602000c2d0b200341d8006a200141186a2204200141286a410010d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d2b200241017422062005200620054b1b22054100480d2b0240024020020d002005102d21020c010b200428020020022005103121020b2002450d2a200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c2e0b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d2d2003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c2d0b200328025c2201450d2c200341e0006a29030021070b20002007370204200020013602000c2c0b200341d8006a200141186a2204200141286a410010d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d2a200241017422062005200620054b1b22054100480d2a0240024020020d002005102d21020c010b200428020020022005103121020b2002450d29200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c2d0b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d2c2003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c2c0b200328025c2201450d2b200341e0006a29030021070b20002007370204200020013602000c2b0b200341d8006a200141186a2204200141286a410110d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d29200241017422062005200620054b1b22054100480d290240024020020d002005102d21020c010b200428020020022005103121020b2002450d28200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c2c0b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d2b2003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c2b0b200328025c2201450d2a200341e0006a29030021070b20002007370204200020013602000c2a0b200341d8006a200141186a2204200141286a410110d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d28200241017422062005200620054b1b22054100480d280240024020020d002005102d21020c010b200428020020022005103121020b2002450d27200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c2b0b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d2a2003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c2a0b200328025c2201450d29200341e0006a29030021070b20002007370204200020013602000c290b200341d8006a200141186a2204200141286a410310d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d27200241017422062005200620054b1b22054100480d270240024020020d002005102d21020c010b200428020020022005103121020b2002450d26200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c2a0b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d292003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c290b200328025c2201450d28200341e0006a29030021070b20002007370204200020013602000c280b200341d8006a200141186a2204200141286a410010d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d26200241017422062005200620054b1b22054100480d260240024020020d002005102d21020c010b200428020020022005103121020b2002450d25200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c290b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d282003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c280b200328025c2201450d27200341e0006a29030021070b20002007370204200020013602000c270b200341d8006a200141186a2204200141286a410010d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d25200241017422062005200620054b1b22054100480d250240024020020d002005102d21020c010b200428020020022005103121020b2002450d24200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c280b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d272003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c270b200328025c2201450d26200341e0006a29030021070b20002007370204200020013602000c260b200341d8006a200141186a2204200141286a410110d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d24200241017422062005200620054b1b22054100480d240240024020020d002005102d21020c010b200428020020022005103121020b2002450d23200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c270b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d262003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c260b200328025c2201450d25200341e0006a29030021070b20002007370204200020013602000c250b200341d8006a200141186a2204200141286a410110d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d23200241017422062005200620054b1b22054100480d230240024020020d002005102d21020c010b200428020020022005103121020b2002450d22200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c260b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d252003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c250b200328025c2201450d24200341e0006a29030021070b20002007370204200020013602000c240b200341d8006a200141186a2204200141286a410210d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d22200241017422062005200620054b1b22054100480d220240024020020d002005102d21020c010b200428020020022005103121020b2002450d21200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c250b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d242003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c240b200328025c2201450d23200341e0006a29030021070b20002007370204200020013602000c230b200341d8006a200141186a2204200141286a410210d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d21200241017422062005200620054b1b22054100480d210240024020020d002005102d21020c010b200428020020022005103121020b2002450d20200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c240b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d232003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c230b200328025c2201450d22200341e0006a29030021070b20002007370204200020013602000c220b200341d8006a200141186a2204200141286a410310d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d20200241017422062005200620054b1b22054100480d200240024020020d002005102d21020c010b200428020020022005103121020b2002450d1f200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000c230b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d222003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c220b200328025c2201450d21200341e0006a29030021070b20002007370204200020013602000c210b200341d8006a200141186a2204200141286a410010d7060240024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d0d200241017422062005200620054b1b22054100480d0d0240024020020d002005102d21020c010b200428020020022005103121020b2002450d0c200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c220b200341ec006a220141013602002003420137025c200341fcdeca003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103a20032802102202450d212003200329021437023c20032002360238200141013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102101200329021421070240200328023c450d002003280238102f0b20010d010c210b200328025c2201450d20200341e0006a29030021070b20002007370204200020013602000c200b2000200329025c370200200041086a200341e4006a2802003602000c1f0b200341ec006a41013602002003420237025c200341ccd2ca003602582003413836023c2003200441056a3602382003200341386a360268200341106a200341d8006a103a200041086a200341106a41086a280200360200200020032903103702000c1e0b41eeddca00411d418cdeca001055000b41eeddca00411d418cdeca001055000b200341d8006a41146a41013602002003420237025c200341c0dbca0036025820034101360204200320033602682003200341386a360200200341106a200341d8006a103a0c0a0b200341e0006a2903002107200328025c21010c0a0b200341e0006a2903002107200328025c21010c090b200341ec006a41013602002003420237025c200341a4dcca003602582003410136024c2003200341c8006a3602682003200341d4006a360248200341106a200341d8006a103a0c050b1036000b1038000b41eeddca00411d418cdeca001055000b200320032d005922013a00002001200241ff0171460d1320014104460d13200341106a41146a41373602002003411c6a4137360200200341d8006a41146a41033602002003420337025c20034184d3ca00360258200341013602142003200341106a3602682003200336022020032003412f6a3602182003200341286a360210200341386a200341d8006a103a0b200329023c2107200328023821010c010b2003280210210120032003290214220737023c200320013602380b2001450d1020002007370204200020013602000c110b20032802102101200329021421070b2001450d0e20002007370204200020013602000c0f0b200641027421060340200320042802002205360248200220054d0d0220022005417f736a220520024f0d0b0240200820054103746a22052d00044103460d0020052d00054104470d040b200441046a21042006417c6a22060d000b4104210a0b200341d8006a200141186a2202200d410010d70620032d00584101460d02200a41ff01714104470d030c040b200341ec006a220441023602002003411c6a41013602002003420237025c200341acddca0036025820034101360214200320023602002003200341106a360268200320033602182003200341c8006a360210200341386a200341d8006a103a200328023821022003200329023c37023c20032002360238200441013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102102200329021421070240200328023c450d002003280238102f0b20032007370204200320023602000c050b2003411c6a4138360200200341ec006a41023602002003420237025c200341dcd2ca003602582003200541056a360218200341383602142003200341106a3602682003200341306a3602102003200341d8006a103a0c040b200341086a200341e4006a2802003602002003200329025c3703000c030b200341d8006a2002200d200a10db062003280258450d00200341086a200341d8006a41086a280200360200200320032903583703000c020b200341003602000c010b200341ec006a220441023602002003411c6a41013602002003420237025c200341acddca0036025820034101360214200320023602002003200341106a360268200320033602182003200341c8006a360210200341386a200341d8006a103a200328023821022003200329023c37023c20032002360238200441013602002003420137025c200341c0d7ca0036025820034131360204200320033602682003200341386a360200200341106a200341d8006a103a20032802102102200329021421070240200328023c450d002003280238102f0b20032007370204200320023602000b0240200328020022020d0002400240200141306a2802002202417f6a220420024f0d00200420024d0d010b4118102d2201450d022003421837025c20032001360258200341d8006a4100411810d80620032003280260220141186a3602602001200328025822006a41184192ddca00411810d9062003200329025c37025c20032000360258418fd1ca00413b200341d8006a41ccd1ca0041dcd1ca00103e000b02400240200128022820044103746a22052802002204200141206a220628020022024b0d00200421010c010b024002402001411c6a280200220820026b200420026b2209490d0020012802182108200221010c010b200220096a220a2002490d042008410174220b200a200b200a4b1b220a4100480d040240024020080d00200a102d21080c010b20012802182008200a103121080b2008450d03200120083602182001411c6a200a360200200141206a28020021010b200820016a210a0240024020094102490d00200a410420042002417f736a220210e7061a2008200220016a22016a210a0c010b2009450d010b200a41043a0000200141016a21010b20062001360200200541013a00060c060b20002003290204370204200020023602000c060b1036000b1038000b41eeddca00411d418cdeca001055000b20002007370204200020023602000c020b20002007370204200020013602000c010b200041003602000b200341f0006a24000b6401017f230041206b2202240020024139360204200220003602002001411c6a2802002100200128021821012002411c6a41013602002002420137020c2002419cdfca003602082002200236021820012000200241086a103c2101200241206a240020010b0c002000280200200110b1060b19002000200141186a280200360204200020012802103602000bcf05010a7f200141096a2d0000210220012d000821032001280204210420012802002105024002400240024002400240024002400240024020012d000a22060e03010002010b200341ff017141014621070c020b200341ff01714101462201200420056b6a220720014f0d01410021084100210141002107410121090240410041ff01710e03030400030b410021060c040b200420056b21070b0240024020070d00410121090c010b20074100480d042007102d2209450d050b4100210102400240200341ff01710d00200921080c010b20092108200641014b0d00200920023a0000200941016a2108410121010b200641024b0d05024020060e03000600000b20052004460d05200120056b21010340200820052d00003a0000200841016a21082004200541016a2205470d000b200420016a21010c050b410121060c010b410221060b0340024002400240024020060e03000102020b20052004460d0620052d0000210a41022106200541016a21052002210b200a21020c020b200341017121064100210302402006450d00410021064100210b0c020b20052004460d0520052d0000210241022106200541016a21054100210b0c010b410121062003410171210a410021034100210b200a450d040b024020012007470d00024002400240024020060e03010200010b200420056b21070c020b417f200341ff01714101462207200420056b6a220a200a2007491b21070c010b200341ff017141014621070b2001417f200741016a220a200a2007491b6a22072001490d0220082007200820074b1b22074100480d020240024020010d002007102d21090c010b200920012007103121090b2009450d030b200920016a20023a0000200841026a2108200141016a2101200b2102024002400240200641ff01710e03000102000b410121060c020b410221060c010b410021060c000b0b1038000b1036000b2000200136020820002007360204200020093602000bc76501037f230041206b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020002d00000eac010102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa01ab0100010b2002200128021841d7a3ca0041112001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000cab010b2002200128021841e8a3ca00410b2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000caa010b2002200128021841f3a3ca0041032001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000ca9010b2002200128021841f6a3ca0041052001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a41fca3ca00106121000ca8010b20022001280218418ca4ca0041042001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a41fca3ca00106121000ca7010b200220012802184190a4ca0041022001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a41fca3ca00106121000ca6010b200220012802184192a4ca0041042001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000ca5010b200220012802184196a4ca0041032001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000ca4010b200220012802184199a4ca0041022001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121000ca3010b20022001280218419ba4ca0041042001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121000ca2010b20022001280218419fa4ca0041072001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8a4ca00106121000ca1010b2002200128021841b8a4ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000ca0010b2002200128021841bea4ca0041042001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121000c9f010b2002200128021841c2a4ca00410c2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121012002200041016a36020c20012002410c6a41d0a4ca00106121000c9e010b2002200128021841e0a4ca0041042001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c9d010b2002200128021841e4a4ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c9c010b2002200128021841eaa4ca0041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121000c9b010b2002200128021841f2a4ca0041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121000c9a010b2002200128021841faa4ca0041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121000c99010b200220012802184182a5ca0041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121000c98010b20022001280218418ba5ca0041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121000c97010b200220012802184194a5ca0041072001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121012002200041086a36020c20012002410c6a41a0a3ca00106121000c96010b20022001280218419ba5ca0041072001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121012002200041086a36020c20012002410c6a41a0a3ca00106121000c95010b2002200128021841a2a5ca0041072001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121012002200041086a36020c20012002410c6a41a0a3ca00106121000c94010b2002200128021841a9a5ca0041072001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121012002200041086a36020c20012002410c6a41a0a3ca00106121000c93010b2002200128021841b0a5ca0041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121012002200041086a36020c20012002410c6a41a0a3ca00106121000c92010b2002200128021841b9a5ca0041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121012002200041086a36020c20012002410c6a41a0a3ca00106121000c91010b2002200128021841c2a5ca00410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121012002200041086a36020c20012002410c6a41a0a3ca00106121000c90010b2002200128021841cca5ca00410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121012002200041086a36020c20012002410c6a41a0a3ca00106121000c8f010b2002200128021841d6a5ca0041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121012002200041086a36020c20012002410c6a41a0a3ca00106121000c8e010b2002200128021841dfa5ca0041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121012002200041086a36020c20012002410c6a41a0a3ca00106121000c8d010b2002200128021841e8a5ca00410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121012002200041086a36020c20012002410c6a41a0a3ca00106121000c8c010b2002200128021841f2a5ca00410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121012002200041086a36020c20012002410c6a41a0a3ca00106121000c8b010b2002200128021841fca5ca00410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121012002200041086a36020c20012002410c6a41a0a3ca00106121000c8a010b200220012802184186a6ca00410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121012002200041086a36020c20012002410c6a41a0a3ca00106121000c89010b200220012802184190a6ca0041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121012002200041086a36020c20012002410c6a41a0a3ca00106121000c88010b200220012802184198a6ca0041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121012002200041086a36020c20012002410c6a41a0a3ca00106121000c87010b2002200128021841a0a6ca0041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121012002200041086a36020c20012002410c6a41a0a3ca00106121000c86010b2002200128021841a8a6ca0041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121012002200041086a36020c20012002410c6a41a0a3ca00106121000c85010b2002200128021841b0a6ca0041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121012002200041086a36020c20012002410c6a41a0a3ca00106121000c84010b2002200128021841b9a6ca00410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121012002200041086a36020c20012002410c6a41a0a3ca00106121000c83010b2002200128021841c3a6ca0041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121012002200041086a36020c20012002410c6a41a0a3ca00106121000c82010b2002200128021841cca6ca00410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121012002200041086a36020c20012002410c6a41a0a3ca00106121000c81010b2002200128021841d6a6ca00410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121012002200041086a36020c20012002410c6a41a0a3ca00106121000c80010b2002200128021841e0a6ca00410d2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a41d0a4ca00106121000c7f0b2002200128021841eda6ca00410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a41d0a4ca00106121000c7e0b2002200128021841f7a6ca0041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4180a7ca00106121000c7d0b200220012802184190a7ca0041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041086a36020c200241106a2002410c6a4198a7ca00106121000c7c0b2002200128021841a8a7ca0041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0a3ca00106121000c7b0b2002200128021841b0a7ca0041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041086a36020c200241106a2002410c6a41b8a7ca00106121000c7a0b2002200128021841c8a7ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c790b2002200128021841cea7ca0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c780b2002200128021841d3a7ca0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c770b2002200128021841d8a7ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c760b2002200128021841dea7ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c750b2002200128021841e4a7ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c740b2002200128021841eaa7ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c730b2002200128021841f0a7ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c720b2002200128021841f6a7ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c710b2002200128021841fca7ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c700b200220012802184182a8ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6f0b200220012802184188a8ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6e0b20022001280218418ea8ca0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6d0b200220012802184193a8ca0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6c0b200220012802184198a8ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6b0b20022001280218419ea8ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6a0b2002200128021841a4a8ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c690b2002200128021841aaa8ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c680b2002200128021841b0a8ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c670b2002200128021841b6a8ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c660b2002200128021841bca8ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c650b2002200128021841c2a8ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c640b2002200128021841c8a8ca0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c630b2002200128021841cda8ca0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c620b2002200128021841d2a8ca0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c610b2002200128021841d7a8ca0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c600b2002200128021841dca8ca0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5f0b2002200128021841e1a8ca0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5e0b2002200128021841e6a8ca0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5d0b2002200128021841eba8ca0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5c0b2002200128021841f0a8ca0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5b0b2002200128021841f5a8ca0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5a0b2002200128021841faa8ca0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c590b2002200128021841ffa8ca0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c580b200220012802184184a9ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c570b20022001280218418aa9ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c560b200220012802184190a9ca0041092001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c550b200220012802184199a9ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c540b20022001280218419fa9ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c530b2002200128021841a5a9ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c520b2002200128021841aba9ca0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c510b2002200128021841b2a9ca0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c500b2002200128021841b9a9ca0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4f0b2002200128021841c0a9ca0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4e0b2002200128021841c7a9ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4d0b2002200128021841cda9ca0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4c0b2002200128021841d2a9ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4b0b2002200128021841d8a9ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4a0b2002200128021841dea9ca0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c490b2002200128021841e5a9ca0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c480b2002200128021841eca9ca0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c470b2002200128021841f3a9ca0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c460b2002200128021841faa9ca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c450b200220012802184180aaca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c440b200220012802184186aaca0041092001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c430b20022001280218418faaca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c420b200220012802184195aaca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c410b20022001280218419baaca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c400b2002200128021841a1aaca0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3f0b2002200128021841a8aaca0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3e0b2002200128021841afaaca0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3d0b2002200128021841b6aaca0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3c0b2002200128021841bdaaca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3b0b2002200128021841c3aaca0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3a0b2002200128021841c8aaca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c390b2002200128021841ceaaca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c380b2002200128021841d4aaca0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c370b2002200128021841dbaaca0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c360b2002200128021841e2aaca0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c350b2002200128021841e9aaca0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c340b2002200128021841f0aaca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c330b2002200128021841f6aaca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c320b2002200128021841fcaaca0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c310b200220012802184183abca0041082001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c300b20022001280218418babca0041082001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2f0b200220012802184193abca00410a2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2e0b20022001280218419dabca0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2d0b2002200128021841a4abca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2c0b2002200128021841aaabca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2b0b2002200128021841b0abca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2a0b2002200128021841b6abca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c290b2002200128021841bcabca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c280b2002200128021841c2abca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c270b2002200128021841c8abca00410b2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c260b2002200128021841d3abca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c250b2002200128021841d9abca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c240b2002200128021841dfabca0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c230b2002200128021841e6abca0041082001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c220b2002200128021841eeabca0041082001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c210b2002200128021841f6abca00410a2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c200b200220012802184180acca0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1f0b200220012802184187acca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1e0b20022001280218418dacca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1d0b200220012802184193acca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1c0b200220012802184199acca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1b0b20022001280218419facca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1a0b2002200128021841a5acca0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c190b2002200128021841abacca00410b2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c180b2002200128021841b6acca00410a2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c170b2002200128021841c0acca00410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c160b2002200128021841ccacca00410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c150b2002200128021841d8acca00410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c140b2002200128021841e4acca00410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c130b2002200128021841f0acca00410d2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c120b2002200128021841fdacca00410d2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c110b20022001280218418aadca00410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c100b200220012802184196adca00410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0f0b2002200128021841a2adca00410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0e0b2002200128021841aeadca00410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0d0b2002200128021841baadca00410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0c0b2002200128021841c8adca00410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0b0b2002200128021841d6adca00410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0a0b2002200128021841e4adca00410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c090b2002200128021841f2adca00410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c080b2002200128021841feadca00410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c070b20022001280218418caeca00410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c060b20022001280218419aaeca00410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c050b2002200128021841a8aeca00410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c040b2002200128021841b6aeca00410d2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c030b2002200128021841c3aeca0041112001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c020b2002200128021841d4aeca0041112001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c010b2002200128021841e5aeca0041112001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000b20002d00082101024020002802042203450d00200141ff0171210441012101024020040d00024020034101470d0020002d0009450d00200028020022042d00004104710d004101210120042802184196a5c00041012004411c6a28020028020c1100000d010b2000280200220128021841e4d3ca0041012001411c6a28020028020c11000021010b200020013a00080b200241206a2400200141ff01714100470bc50201037f230041206b2202240002400240200028020022002d00004104470d002002200128021841a4afca0041082001411c6a28020028020c11000022003a001820022001360210200241003a0019200241003602140c010b2002200128021841acafca0041052001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200036020c200241106a2002410c6a4188afca001061210120022d0018210020022802142203450d00200041ff0171210441012100024020040d00024020034101470d0020012d0009450d00200128020022042d00004104710d004101210020042802184196a5c00041012004411c6a28020028020c1100000d010b2001280200220028021841e4d3ca0041012000411c6a28020028020c11000021000b200120003a00080b200241206a2400200041ff01714100470bc00201037f230041206b220224000240024020002d00004104470d002002200128021841a4afca0041082001411c6a28020028020c11000022003a001820022001360210200241003a0019200241003602140c010b2002200128021841acafca0041052001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200036020c200241106a2002410c6a4188afca001061210120022d0018210020022802142203450d00200041ff0171210441012100024020040d00024020034101470d0020012d0009450d00200128020022042d00004104710d004101210020042802184196a5c00041012004411c6a28020028020c1100000d010b2001280200220028021841e4d3ca0041012000411c6a28020028020c11000021000b200120003a00080b200241206a2400200041ff01714100470bc00201037f23004180016b220224002000280200210002400240024002400240200128020022034110710d0020002d0000210420034120710d012004ad42ff018341012001104521000c020b20002d00002104410021000340200220006a41ff006a2004410f712203413072200341d7006a2003410a491b3a00002000417f6a21002004410476410f7122040d000b20004180016a22044181014f0d022001410141bc8ac0004102200220006a4180016a410020006b104821000c010b410021000340200220006a41ff006a2004410f712203413072200341376a2003410a491b3a00002000417f6a21002004410476410f7122040d000b20004180016a22044181014f0d022001410141bc8ac0004102200220006a4180016a410020006b104821000b20024180016a240020000f0b2004418001104b000b2004418001104b000bcd0203027f017e017f23004180016b220224002000280200210002400240024002400240200128020022034110710d002000280200210020034120710d012000ac22042004423f8722047c2004852000417f73411f762001104521000c020b20002802002103410021000340200220006a41ff006a2003410f712205413072200541d7006a2005410a491b3a00002000417f6a2100200341047622030d000b20004180016a22034181014f0d022001410141bc8ac0004102200220006a4180016a410020006b104821000c010b410021030340200220036a41ff006a2000410f712205413072200541376a2005410a491b3a00002003417f6a2103200041047622000d000b20034180016a22004181014f0d022001410141bc8ac0004102200220036a4180016a410020036b104821000b20024180016a240020000f0b2003418001104b000b2000418001104b000bcd0202027f027e23004180016b220224002000280200210002400240024002400240200128020022034110710d002000290300210420034120710d0120042004423f8722057c2005852004427f552001104521000c020b20002903002104410021000340200220006a41ff006a2004a7410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200442048822044200520d000b20004180016a22034181014f0d022001410141bc8ac0004102200220006a4180016a410020006b104821000c010b410021000340200220006a41ff006a2004a7410f712203413072200341376a2003410a491b3a00002000417f6a2100200442048822044200520d000b20004180016a22034181014f0d022001410141bc8ac0004102200220006a4180016a410020006b104821000b20024180016a240020000f0b2003418001104b000b2003418001104b000b8a0201027f230041106b2202240020002802002802002100200128021841b0a3ca00410b2001411c6a28020028020c1100002103200241003a0005200220033a0004200220013602002002200036020c200241bba3ca0041052002410c6a41c0a3ca00105b21012002200041086a36020c200141d0a3ca0041072002410c6a41a0a3ca00105b1a20022d00042101024020022d0005450d00200141ff0171210041012101024020000d0020022802002201411c6a28020028020c210020012802182103024020012d00004104710d0020034190a5c0004102200011000021010c010b20034192a5c0004101200011000021010b200220013a00040b200241106a2400200141ff01714100470bcc0101047f230041106b220224002000280200220041046a2802002103200028020021004101210420012802184199a5c00041012001411c6a28020028020c1100002105200241003a0005200220053a00042002200136020002402003450d002003410274210103402002200036020c20022002410c6a41f8aeca0010621a200041046a21002001417c6a22010d000b20022d000421050b0240200541ff01710d00200228020022002802184198a5c00041012000411c6a28020028020c11000021040b200241106a240020040b8c0902047f017e230041106b2202240002400240024020010d00200041ac013a00000c010b024002400240024020012d00002203414f6a41fb004f0d000c010b02400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020030e312c2c0001022c2c0304052c06072c2c08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292c0b20012d00012104410221030c2b0b20012d00012104410321030c2a0b20012d00012104410421030c290b200141046a2802002105410721030c270b200141046a2802002105410821030c260b200141046a2802002101410c102d2205450d28200241086a2001280200200141046a28020010ba06200229030821062005200128020836020820052006370200410921030c250b200141046a2802002105410b21030c240b200141046a280200210520012d00012104410c21030c240b200141046a2802002105410f21030c220b200141046a2802002105411021030c210b200141046a2802002105411121030c200b200141046a2802002105411221030c1f0b200141046a2802002105411321030c1e0b200141046a280200210520013502082106411421030c1d0b200141046a280200210520013502082106411521030c1c0b200141046a280200210520013502082106411621030c1b0b200141046a280200210520013502082106411721030c1a0b200141046a280200210520013502082106411821030c190b200141046a280200210520013502082106411921030c180b200141046a280200210520013502082106411a21030c170b200141046a280200210520013502082106411b21030c160b200141046a280200210520013502082106411c21030c150b200141046a280200210520013502082106411d21030c140b200141046a280200210520013502082106411e21030c130b200141046a280200210520013502082106411f21030c120b200141046a280200210520013502082106412021030c110b200141046a280200210520013502082106412121030c100b200141046a280200210520013502082106412221030c0f0b200141046a280200210520013502082106412321030c0e0b200141046a280200210520013502082106412421030c0d0b200141046a280200210520013502082106412521030c0c0b200141046a280200210520013502082106412621030c0b0b200141046a280200210520013502082106412721030c0a0b200141046a280200210520013502082106412821030c090b200141046a280200210520013502082106412921030c080b200141046a280200210520013502082106412a21030c070b20012d00012104412b21030c070b20012d00012104412c21030c060b200141046a2802002105412d21030c040b20012903082106412e21030c020b200141046a2802002105412f21030c020b20012903082106413021030b0b0b200020043a0001200020033a0000200041086a2006370300200041046a20053602000b200241106a24000f0b1036000ba20201037f0240024002400240200241ffffffff03712002470d0020024102742203417f4c0d000240024020030d0041042104200221030c010b2003102d2204450d022003410276220320024f0d00200341017422052002200520024b1b220541ffffffff03712005470d03200541027422054100480d030240024020030d002005102d21040c010b200420034102742005103121040b2004450d02200541027621030b200420012002410274220510e80621010240024020032002470d00200121040c010b20032002490d04024020020d0041002102410421042003450d012001102f0c010b20012003410274200510312204450d020b20002002360204200020043602000f0b103d000b1036000b1038000b41ebafca00412441f8b4ca001039000bba0201037f230041106b220224000240024020002802000d00200220012802184193b0ca0041042001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c010b20022001280218418fb0ca0041042001411c6a28020028020c1100003a000820022001360200200241003a0009200241003602042002200036020c20022002410c6a4198b0ca001061210120022d0008210020022802042203450d00200041ff0171210441012100024020040d00024020034101470d0020012d0009450d00200128020022042d00004104710d004101210020042802184196a5c00041012004411c6a28020028020c1100000d010b2001280200220028021841e4d3ca0041012000411c6a28020028020c11000021000b200120003a00080b200241106a2400200041ff01714100470b880301067f02402001450d00034020002802940321002001417f6a22010d000b0b02402002450d0041002103034002400240200320002f01064f0d0041002104200021010c010b41002104034002400240024020004190bdc600460d00200028020022010d0141002103410021010c020b41edb3ca00412841f8b4ca001039000b200441016a210420002f010421030b2000102f20012100200320012f01064f0d000b0b200341016a2105200120034105746a220041c4006a2802002106200041386a2802002107200041346a28020021080240024020040d0020012100200521030c010b200120054102746a4194036a2802002100410021032004417f6a2201450d00034020002802940321002001417f6a22010d000b0b20064102460d012002417f6a210202402007450d002008102f0b20020d000b0b0240024020004190bdc600460d00200028020021012000102f2001450d00034020014190bdc600460d02200128020021002001102f2000210120000d000b0b0f0b41edb3ca00412841f8b4ca001039000bab0902027f017e230041106b220224000240024020012d00002203414f6a41fb00490d0002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020030e312a2a0001022a2a0304052a06072a2a08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a0b200020012d00013a0001410221030c290b200020012d00013a0001410321030c280b200020012d00013a0001410421030c270b200041046a200141046a280200360200410721030c260b200041046a200141046a280200360200410821030c250b200141046a2802002103410c102d2201450d25200241086a2003280200200341046a28020010ba06200229030821042001200328020836020820012004370200200041046a2001360200410921030c240b200041046a200141046a280200360200410b21030c230b200020012d00013a0001200041046a200141046a280200360200410c21030c220b200041046a200141046a280200360200410f21030c210b200041046a200141046a280200360200411021030c200b200041046a200141046a280200360200411121030c1f0b200041046a200141046a280200360200411221030c1e0b200041046a200141046a280200360200411321030c1d0b200041046a200141046a290200370200411421030c1c0b200041046a200141046a290200370200411521030c1b0b200041046a200141046a290200370200411621030c1a0b200041046a200141046a290200370200411721030c190b200041046a200141046a290200370200411821030c180b200041046a200141046a290200370200411921030c170b200041046a200141046a290200370200411a21030c160b200041046a200141046a290200370200411b21030c150b200041046a200141046a290200370200411c21030c140b200041046a200141046a290200370200411d21030c130b200041046a200141046a290200370200411e21030c120b200041046a200141046a290200370200411f21030c110b200041046a200141046a290200370200412021030c100b200041046a200141046a290200370200412121030c0f0b200041046a200141046a290200370200412221030c0e0b200041046a200141046a290200370200412321030c0d0b200041046a200141046a290200370200412421030c0c0b200041046a200141046a290200370200412521030c0b0b200041046a200141046a290200370200412621030c0a0b200041046a200141046a290200370200412721030c090b200041046a200141046a290200370200412821030c080b200041046a200141046a290200370200412921030c070b200041046a200141046a290200370200412a21030c060b200020012d00013a0001412b21030c050b200020012d00013a0001412c21030c040b200041046a200141046a280200360200412d21030c030b200041086a200141086a290300370300412e21030c020b200041046a200141046a280200360200412f21030c010b200041086a200141086a290300370300413021030b200020033a0000200241106a24000f0b1036000b8c0301067f230041106b220224000240024002400240200041046a2802002203200041086a28020022046b20012802042205200128020022066b4104762207490d00200028020021030c010b200420076a22062004490d02200341017422052006200520064b1b220641ffffffff00712006470d02200641047422064100480d020240024020030d002006102d21030c010b200028020020034104742006103121030b2003450d0120002003360200200041046a2006410476360200200041086a280200210420012802042105200128020021060b0240024020062005470d00410021060c010b2001200641106a3602000b2002200610b906024020022d000041ac01460d00200320044104746a2106034020062002290300370300200641086a200241086a29030037030002400240200128020022052001280204470d00410021050c010b2001200541106a3602000b200441016a2104200641106a21062002200510b90620022d000041ac01470d000b0b200041086a2004360200200241106a24000f0b1036000b1038000bcc0201027f230041106b2202240020002802002802002100200128021841c2b5ca0041052001411c6a28020028020c1100002103200241003a0005200220033a00042002200136020020022000410c6a36020c200241c7b5ca00410e2002410c6a41d8b5ca00105b21012002200036020c200141e8b5ca0041092002410c6a41f4b5ca00105b21012002200041046a36020c20014184b6ca00410c2002410c6a41f4b5ca00105b21012002200041086a36020c20014190b6ca00410c2002410c6a41f4b5ca00105b1a20022d00042100024020022d0005450d00200041ff0171210141012100024020010d0020022802002200411c6a28020028020c210120002802182103024020002d00004104710d0020034190a5c0004102200111000021000c010b20034192a5c0004101200111000021000b200220003a00040b200241106a2400200041ff01714100470bdd60010c7f230041a0016b22032400200320013602242002280208220441546a2105200241106a280200220641306c21010240024002400240024002400240024003402001450d01200141506a21012005412c6a2107200541306a2208210520072d00004104470d000b200641306c2101200441546a210503402001450d02200141506a21012005412c6a2107200541306a2209210520072d0000410c470d000b200641306c2101200441546a210503402001450d04200141506a21012005412c6a2107200541306a2204210520072d00004102470d000b024041002802a4e24a4105490d00200341013602442003200341246a36024041002802b0e24a210141002802ace24a210541002802a8e24a210720034198016a41980136020020034190016a42ed808080103703002003418c016a41bcb8ca0036020020034184016a422537020020034180016a41b3b9ca00360200200341f8006a4201370300200341e8006a4201370300200341e0006a410a360200200341f4006a200341c0006a360200200341d0b6ca00360264200341a9b9ca0036025c20034105360258200541cca5c000200741024622071b200341d8006a200141e4a5c00020071b2802101102000b200341186a200810d603200328021c200328022422014d0d04200328021820014102746a2201450d04200341106a200410d60302402003280214200128020022014d0d00200328021020014104746a22010d060b4125102d2201450d072001411d6a41002900f5b64a370000200141186a41002900f0b64a370000200141106a41002900e8b64a370000200141086a41002900e0b64a370000200141002900d8b64a370000200041086a42a5808080d00437020020002001360204200041013602000c060b4113102d22010d010c060b410f102d2201450d05200141076a41002900b6b64a370000200141002900afb64a370000200041086a428f808080f00137020020002001360204200041013602000c040b2001410f6a41002800abb64a360000200141086a41002900a4b64a3700002001410029009cb64a370000200041086a4293808080b00237020020002001360204200041013602000c030b410f102d2201450d03200141076a41002900c5b64a370000200141002900beb64a370000200041086a428f808080f00137020020002001360204200041013602000c020b4125102d2201450d022001411d6a41002900f5b64a370000200141186a41002900f0b64a370000200141106a41002900e8b64a370000200141086a41002900e0b64a370000200141002900d8b64a370000200041086a42a5808080d00437020020002001360204200041013602000c010b0240200941086a280200200328022422054b0d004127102d2201450d022001411f6a41002900a7b74a370000200141186a41002900a0b74a370000200141106a4100290098b74a370000200141086a4100290090b74a37000020014100290088b74a370000200041086a42a7808080f00437020020002001360204200041013602000c010b20092802002109200341286a41086a420037030020034280808080c00037032820012d000d2107410021012003410036024820032007410447220a3602442003200a360240200341003a004c02400240024002400240024041002802a4e24a41044b0d00200341d8006a41086a200341c0006a41086a29030037030020032003290340370358200341286a410472210b200341d8006a21070c010b2003413a3602542003200341c0006a36025041002802b0e24a210141002802ace24a210741002802a8e24a210820034198016a41cb0036020020034190016a42ed808080103703002003418c016a41bcb8ca0036020020034184016a422537020020034180016a41b3b9ca00360200200341f8006a4201370300200341e8006a4201370300200341d8006a41086a2206410a360200200341f4006a200341d0006a36020020034180b7ca00360264200341a9b9ca0036025c20034105360258200741cca5c000200841024622081b200341d8006a200141e4a5c00020081b28021011020020032802342108200328023021012006200341c0006a41086a29030037030020032003290340370358200341286a410472210b200341d8006a210720082001470d010b200141016a22082001490d01200141017422062008200620084b1b220841ffffffff00712008470d01200841047422084100480d010240024020010d002008102d21010c010b200b28020020014104742008103121010b2001450d05200b200136020020032008410476360230200328023421080b200b28020020084104746a22012007290200370200200141086a200741086a2902003702002003200328023441016a360234410021072009200541186c6a2201280214450d022009200541186c6a410c6a2109200141146a2108200341d8006a410472210c410021074100210103400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200328022820074d0d00200341d8006a200341286a410010c20620032802584101460d0120072003280228200328025c2d000c1b21070b2001200828020022054f0d1d2003200928020020014104746a220536023c024041002802a4e24a4105490d002003413236024420032003413c6a36024041002802b0e24a210541002802ace24a210641002802a8e24a210d200341c90136029801200342ed8080801037039001200341bcb8ca0036028c012003422537028401200341b3b9ca003602800120034201370378200342013703682003419cdfca003602642003410a360260200341a9b9ca0036025c20034105360258200541e4a5c000200d410246220d1b28021021052003200341c0006a360274200641cca5c000200d1b200341d8006a2005110200200328023c21050b20052d000022060eac01033201010132020405060708090a0b0c0d0e0f10111111111111111111111111111112121212121212121213141515151516171717171717171717171617171717171717171717171717171717171717171717181818191919191919191919191919191919181818191919191919191919191919191919181818181818181919191919191918181818181818191919191919191a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a030b200041013602002000200c2902003702042000410c6a200c41086a2802003602000c340b20052d000121052003200328022836024820032005410447220536024020032006410347200571360244200341003a004c024041002802a4e24a4105490d002003413a3602542003200341c0006a36025041002802b0e24a210541002802ace24a210641002802a8e24a210d200341cb0036029801200342ed8080801037039001200341bcb8ca0036028c012003422537028401200341b3b9ca0036028001200342013703782003420137036820034180b7ca003602642003410a360260200341a9b9ca0036025c20034105360258200541e4a5c000200d410246220d1b28021021052003200341d0006a360274200641cca5c000200d1b200341d8006a20051102000b200341d8006a41086a2206200341c0006a41086a290300370300200320032903403703580240200328023422052003280230470d00200541016a220d2005490d332005410174220e200d200e200d4b1b220d41ffffffff0071200d470d33200d410474220d4100480d330240024020050d00200d102d21050c010b200b2802002005410474200d103121050b2005450d37200b20053602002003200d410476360230200328023421050b200b28020020054104746a22052003290358370200200541086a20062903003702002003200328023441016a3602340c300b41002105024041002802a4e24a4105490d00024020032802342206417f6a220d20064b0d00200b280200200d4104746a4100200d2006491b21050b2003413b360254200320053602402003200341c0006a36025041002802b0e24a210541002802ace24a210641002802a8e24a210d200341d30036029801200342ed8080801037039001200341bcb8ca0036028c012003422537028401200341b3b9ca00360280012003420137037820034201370368200341b0b7ca003602642003410a360260200341a9b9ca0036025c20034105360258200541e4a5c000200d410246220d1b28021021052003200341d0006a360274200641cca5c000200d1b200341d8006a20051102000b024020032802342205450d0020032005417f6a2205360234200b28020020054104746a22052d000c4102470d1a0b4117102d2201450d352001410f6a41002900c7b74a370000200141086a41002900c0b74a370000200141002900b8b74a370000200041086a4297808080f00237020020002001360204200041013602000c320b024041002802a4e24a4105490d0041002802b0e24a210541002802ace24a210641002802a8e24a210d200341c10036029801200342ed8080801037039001200341bcb8ca0036028c012003422537028401200341b3b9ca003602800120034200370378200341c8e1ca0036027420034201370368200341d0b7ca003602642003410a360260200341a9b9ca0036025c20034105360258200641cca5c000200d410246220d1b200341d8006a200541e4a5c000200d1b2802101102000b024020032802342205417f6a220620054f0d00200620054d0d180b4117102d2201450d342001410f6a41002900c7b74a370000200141086a41002900c0b74a370000200141002900b8b74a370000200041086a4297808080f00237020020002001360204200041013602000c310b200341d8006a200341286a200541046a28020010c20620032802584101460d19200341d8006a200341286a200328025c28020410c306024020032802580d00024041002802a4e24a4105490d0041002802b0e24a210541002802ace24a210641002802a8e24a210d200341c10036029801200342ed8080801037039001200341bcb8ca0036028c012003422537028401200341b3b9ca003602800120034200370378200341c8e1ca0036027420034201370368200341d0b7ca003602642003410a360260200341a9b9ca0036025c20034105360258200641cca5c000200d410246220d1b200341d8006a200541e4a5c000200d1b2802101102000b0240024020032802342205417f6a220620054f0d00200620054d0d010b4117102d2201450d352001410f6a41002900c7b74a370000200141086a41002900c0b74a370000200141002900b8b74a370000200041086a4297808080f00237020020002001360204200041013602000c320b200b28020020064104746a41013a000c0c2e0b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c300b200341d8006a200341286a200541046a28020010c20620032802584101460d19200341d8006a200341286a200328025c280204220510c30620032802580d1a200341d8006a200341286a410110c30620032802580d1b20032005360250024041002802a4e24a4105490d00200341013602442003200341d0006a36024041002802b0e24a210541002802ace24a210641002802a8e24a210d200341e30036029801200342ed8080801037039001200341bcb8ca0036028c012003422537028401200341b3b9ca00360280012003420137037820034201370368200341d8b7ca003602642003410a360260200341a9b9ca0036025c20034105360258200541e4a5c000200d410246220d1b28021021052003200341c0006a360274200641cca5c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c2d0b410e102d2201450d32200141066a41002900e6b74a370000200141002900e0b74a370000200041086a428e808080e00137020020002001360204200041013602000c2f0b200341d8006a200341286a200541046a28020028020810c20620032802584101460d1b200328025c280204210d2005280204220628020441027421052006280200210602400340024020050d00200341d8006a200341286a200d10c30620032802580d20024041002802a4e24a4105490d0041002802b0e24a210541002802ace24a210641002802a8e24a210d200341c10036029801200342ed8080801037039001200341bcb8ca0036028c012003422537028401200341b3b9ca003602800120034200370378200341c8e1ca0036027420034201370368200341d0b7ca003602642003410a360260200341a9b9ca0036025c20034105360258200641cca5c000200d410246220d1b200341d8006a200541e4a5c000200d1b2802101102000b20032802342205417f6a220620054f0d02200620054b0d02200b28020020064104746a41013a000c0c2e0b200341d8006a200341286a200628020010c20620032802584101460d1e2005417c6a2105200641046a2106200328025c280204200d460d000b4127102d2201450d322001411f6a410029008db84a370000200141186a4100290086b84a370000200141106a41002900feb74a370000200141086a41002900f6b74a370000200141002900eeb74a370000200041086a42a7808080f00437020020002001360204200041013602000c2f0b4117102d2201450d312001410f6a41002900c7b74a370000200141086a41002900c0b74a370000200141002900b8b74a370000200041086a4297808080f00237020020002001360204200041013602000c2e0b200341d8006a200341286a200a10c306024020032802580d00024041002802a4e24a4105490d0041002802b0e24a210541002802ace24a210641002802a8e24a210d200341c10036029801200342ed8080801037039001200341bcb8ca0036028c012003422537028401200341b3b9ca003602800120034200370378200341c8e1ca0036027420034201370368200341d0b7ca003602642003410a360260200341a9b9ca0036025c20034105360258200641cca5c000200d410246220d1b200341d8006a200541e4a5c000200d1b2802101102000b0240024020032802342205417f6a220620054f0d00200620054d0d010b4117102d2201450d322001410f6a41002900c7b74a370000200141086a41002900c0b74a370000200141002900b8b74a370000200041086a4297808080f00237020020002001360204200041013602000c2f0b200b28020020064104746a41013a000c0c2b0b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c2d0b200341d8006a200541046a280200200210c40620032802584101460d1c200341d8006a200341286a200328025c220528020810c30620032802580d1d200320052d000d4104472205360250024041002802a4e24a4105490d00200341013602442003200341d0006a36024041002802b0e24a210541002802ace24a210641002802a8e24a210d200341e30036029801200342ed8080801037039001200341bcb8ca0036028c012003422537028401200341b3b9ca00360280012003420137037820034201370368200341d8b7ca003602642003410a360260200341a9b9ca0036025c20034105360258200541e4a5c000200d410246220d1b28021021052003200341c0006a360274200641cca5c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c2a0b410e102d2201450d2f200141066a41002900e6b74a370000200141002900e0b74a370000200041086a428e808080e00137020020002001360204200041013602000c2c0b200341086a200410d60302400240200328020c200541046a28020022054d0d002003280208220620054104746a220d450d00200341d8006a200341286a200620054104746a28020810c30620032802580d1f2003200d2d000d4104472205360250024041002802a4e24a4105490d00200341013602442003200341d0006a36024041002802b0e24a210541002802ace24a210641002802a8e24a210d200341e30036029801200342ed8080801037039001200341bcb8ca0036028c012003422537028401200341b3b9ca00360280012003420137037820034201370368200341d8b7ca003602642003410a360260200341a9b9ca0036025c20034105360258200541e4a5c000200d410246220d1b28021021052003200341c0006a360274200641cca5c000200d1b200341d8006a2005110200200328025021050b2003280228220620056a22052006490d01200320053602280c2a0b410e102d2201450d2f200141066a410029009bb84a37000020014100290095b84a370000200041086a428e808080e00137020020002001360204200041013602000c2c0b410e102d2201450d2e200141066a41002900e6b74a370000200141002900e0b74a370000200041086a428e808080e00137020020002001360204200041013602000c2b0b200341d8006a200341286a410110c3062003280258450d2720002003290358370204200041013602002000410c6a200341e0006a2802003602000c2a0b200341d8006a200341286a410210c30620032802580d1c41012105200341d8006a200341286a410110c30620032802580d1d20034101360250024041002802a4e24a4105490d00200341013602442003200341d0006a36024041002802b0e24a210541002802ace24a210641002802a8e24a210d200341e30036029801200342ed8080801037039001200341bcb8ca0036028c012003422537028401200341b3b9ca00360280012003420137037820034201370368200341d8b7ca003602642003410a360260200341a9b9ca0036025c20034105360258200541e4a5c000200d410246220d1b28021021052003200341c0006a360274200641cca5c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c270b410e102d2201450d2c200141066a41002900e6b74a370000200141002900e0b74a370000200041086a428e808080e00137020020002001360204200041013602000c290b4101210520034101360250024041002802a4e24a4105490d00200341013602442003200341d0006a36024041002802b0e24a210541002802ace24a210641002802a8e24a210d200341e30036029801200342ed8080801037039001200341bcb8ca0036028c012003422537028401200341b3b9ca00360280012003420137037820034201370368200341d8b7ca003602642003410a360260200341a9b9ca0036025c20034105360258200541e4a5c000200d410246220d1b28021021052003200341c0006a360274200641cca5c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c260b410e102d2201450d2b200141066a41002900e6b74a370000200141002900e0b74a370000200041086a428e808080e00137020020002001360204200041013602000c280b200341d8006a200341286a410110c3062003280258450d2420002003290358370204200041013602002000410c6a200341e0006a2802003602000c270b41012105200341d8006a200341286a410110c30620032802580d1b20034101360250024041002802a4e24a4105490d00200341013602442003200341d0006a36024041002802b0e24a210541002802ace24a210641002802a8e24a210d200341e30036029801200342ed8080801037039001200341bcb8ca0036028c012003422537028401200341b3b9ca00360280012003420137037820034201370368200341d8b7ca003602642003410a360260200341a9b9ca0036025c20034105360258200541e4a5c000200d410246220d1b28021021052003200341c0006a360274200641cca5c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c240b410e102d2201450d29200141066a41002900e6b74a370000200141002900e0b74a370000200041086a428e808080e00137020020002001360204200041013602000c260b4101210520034101360250024041002802a4e24a4105490d00200341013602442003200341d0006a36024041002802b0e24a210541002802ace24a210641002802a8e24a210d200341e30036029801200342ed8080801037039001200341bcb8ca0036028c012003422537028401200341b3b9ca00360280012003420137037820034201370368200341d8b7ca003602642003410a360260200341a9b9ca0036025c20034105360258200541e4a5c000200d410246220d1b28021021052003200341c0006a360274200641cca5c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c230b410e102d2201450d28200141066a41002900e6b74a370000200141002900e0b74a370000200041086a428e808080e00137020020002001360204200041013602000c250b200341d8006a200341286a410110c3062003280258450d2120002003290358370204200041013602002000410c6a200341e0006a2802003602000c240b41012105200341d8006a200341286a410110c30620032802580d1920034101360250024041002802a4e24a4105490d00200341013602442003200341d0006a36024041002802b0e24a210541002802ace24a210641002802a8e24a210d200341e30036029801200342ed8080801037039001200341bcb8ca0036028c012003422537028401200341b3b9ca00360280012003420137037820034201370368200341d8b7ca003602642003410a360260200341a9b9ca0036025c20034105360258200541e4a5c000200d410246220d1b28021021052003200341c0006a360274200641cca5c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c210b410e102d2201450d26200141066a41002900e6b74a370000200141002900e0b74a370000200041086a428e808080e00137020020002001360204200041013602000c230b200341d8006a200341286a410210c3062003280258450d1f20002003290358370204200041013602002000410c6a200341e0006a2802003602000c220b4101210520034101360250024041002802a4e24a4105490d00200341013602442003200341d0006a36024041002802b0e24a210541002802ace24a210641002802a8e24a210d200341e30036029801200342ed8080801037039001200341bcb8ca0036028c012003422537028401200341b3b9ca00360280012003420137037820034201370368200341d8b7ca003602642003410a360260200341a9b9ca0036025c20034105360258200541e4a5c000200d410246220d1b28021021052003200341c0006a360274200641cca5c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c1f0b410e102d2201450d24200141066a41002900e6b74a370000200141002900e0b74a370000200041086a428e808080e00137020020002001360204200041013602000c210b41012105200341d8006a200341286a410110c30620032802580d1720034101360250024041002802a4e24a4105490d00200341013602442003200341d0006a36024041002802b0e24a210541002802ace24a210641002802a8e24a210d200341e30036029801200342ed8080801037039001200341bcb8ca0036028c012003422537028401200341b3b9ca00360280012003420137037820034201370368200341d8b7ca003602642003410a360260200341a9b9ca0036025c20034105360258200541e4a5c000200d410246220d1b28021021052003200341c0006a360274200641cca5c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c1e0b410e102d2201450d23200141066a41002900e6b74a370000200141002900e0b74a370000200041086a428e808080e00137020020002001360204200041013602000c200b4101210520034101360250024041002802a4e24a4105490d00200341013602442003200341d0006a36024041002802b0e24a210541002802ace24a210641002802a8e24a210d200341e30036029801200342ed8080801037039001200341bcb8ca0036028c012003422537028401200341b3b9ca00360280012003420137037820034201370368200341d8b7ca003602642003410a360260200341a9b9ca0036025c20034105360258200541e4a5c000200d410246220d1b28021021052003200341c0006a360274200641cca5c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c1d0b410e102d2201450d22200141066a41002900e6b74a370000200141002900e0b74a370000200041086a428e808080e00137020020002001360204200041013602000c1f0b41012105200341d8006a200341286a410110c30620032802580d1620034101360250024041002802a4e24a4105490d00200341013602442003200341d0006a36024041002802b0e24a210541002802ace24a210641002802a8e24a210d200341e30036029801200342ed8080801037039001200341bcb8ca0036028c012003422537028401200341b3b9ca00360280012003420137037820034201370368200341d8b7ca003602642003410a360260200341a9b9ca0036025c20034105360258200541e4a5c000200d410246220d1b28021021052003200341c0006a360274200641cca5c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c1c0b410e102d2201450d21200141066a41002900e6b74a370000200141002900e0b74a370000200041086a428e808080e00137020020002001360204200041013602000c1e0b200341d8006a200341286a410210c30620032802580d164101210520034101360250024041002802a4e24a4105490d00200341013602442003200341d0006a36024041002802b0e24a210541002802ace24a210641002802a8e24a210d200341e30036029801200342ed8080801037039001200341bcb8ca0036028c012003422537028401200341b3b9ca00360280012003420137037820034201370368200341d8b7ca003602642003410a360260200341a9b9ca0036025c20034105360258200541e4a5c000200d410246220d1b28021021052003200341c0006a360274200641cca5c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c1b0b410e102d2201450d20200141066a41002900e6b74a370000200141002900e0b74a370000200041086a428e808080e00137020020002001360204200041013602000c1d0b41012105200341d8006a200341286a410110c30620032802580d1620034101360250024041002802a4e24a4105490d00200341013602442003200341d0006a36024041002802b0e24a210541002802ace24a210641002802a8e24a210d200341e30036029801200342ed8080801037039001200341bcb8ca0036028c012003422537028401200341b3b9ca00360280012003420137037820034201370368200341d8b7ca003602642003410a360260200341a9b9ca0036025c20034105360258200541e4a5c000200d410246220d1b28021021052003200341c0006a360274200641cca5c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c1a0b410e102d2201450d1f200141066a41002900e6b74a370000200141002900e0b74a370000200041086a428e808080e00137020020002001360204200041013602000c1c0b200341d8006a200341286a410210c30620032802580d164101210520034101360250024041002802a4e24a4105490d00200341013602442003200341d0006a36024041002802b0e24a210541002802ace24a210641002802a8e24a210d200341e30036029801200342ed8080801037039001200341bcb8ca0036028c012003422537028401200341b3b9ca00360280012003420137037820034201370368200341d8b7ca003602642003410a360260200341a9b9ca0036025c20034105360258200541e4a5c000200d410246220d1b28021021052003200341c0006a360274200641cca5c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c190b410e102d2201450d1e200141066a41002900e6b74a370000200141002900e0b74a370000200041086a428e808080e00137020020002001360204200041013602000c1b0b41012105200341d8006a200341286a410110c30620032802580d1620034101360250024041002802a4e24a4105490d00200341013602442003200341d0006a36024041002802b0e24a210541002802ace24a210641002802a8e24a210d200341e30036029801200342ed8080801037039001200341bcb8ca0036028c012003422537028401200341b3b9ca00360280012003420137037820034201370368200341d8b7ca003602642003410a360260200341a9b9ca0036025c20034105360258200541e4a5c000200d410246220d1b28021021052003200341c0006a360274200641cca5c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c180b410e102d2201450d1d200141066a41002900e6b74a370000200141002900e0b74a370000200041086a428e808080e00137020020002001360204200041013602000c1a0b200b28020020064104746a41013a000c0c160b20052802002106200320052802082205360240024041002802a4e24a4105490d00200341013602542003200341c0006a36025041002802b0e24a210541002802ace24a210d41002802a8e24a210e200341db0036029801200342ed8080801037039001200341bcb8ca0036028c012003422537028401200341b3b9ca00360280012003420137037820034201370368200341a4b8ca003602642003410a360260200341a9b9ca0036025c20034105360258200541e4a5c000200e410246220e1b28021021052003200341d0006a360274200d41cca5c000200e1b200341d8006a2005110200200328024021050b2003200536022820032006360250024041002802a4e24a4105490d00200341013602442003200341d0006a36024041002802b0e24a210541002802ace24a210641002802a8e24a210d200341e30036029801200342ed8080801037039001200341bcb8ca0036028c012003422537028401200341b3b9ca00360280012003420137037820034201370368200341d8b7ca003602642003410a360260200341a9b9ca0036025c20034105360258200541e4a5c000200d410246220d1b28021021052003200341c0006a360274200641cca5c000200d1b200341d8006a200511020020032802282105200328025021060b0240200520066a22062005490d00200320063602280c160b410e102d2201450d1b200141066a41002900e6b74a370000200141002900e0b74a370000200041086a428e808080e00137020020002001360204200041013602000c180b41acb8ca0020012005103b000b200041013602002000200c2902003702042000410c6a200c41086a2802003602000c160b200041013602002000200c2902003702042000410c6a200c41086a2802003602000c150b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c140b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c130b200041013602002000200c2902003702042000410c6a200c41086a2802003602000c120b200041013602002000200c2902003702042000410c6a200c41086a2802003602000c110b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c100b200041013602002000200c2902003702042000410c6a200c41086a2802003602000c0f0b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c0e0b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c0d0b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c0c0b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c0b0b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c0a0b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c090b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c080b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c070b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c060b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c050b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c040b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c030b200141016a22012008280200490d000c030b0b1038000b2003280230450d01200b280200102f0c010b20004100360200200020073602042003280230450d00200b280200102f0b200341a0016a24000f0b1036000bc20201027f230041106b22022400200128021841c2b5ca0041052001411c6a28020028020c1100002103200241003a0005200220033a00042002200136020020022000410c6a36020c200241c7b5ca00410e2002410c6a41d8b5ca00105b21012002200036020c200141e8b5ca0041092002410c6a41f4b5ca00105b21012002200041046a36020c20014184b6ca00410c2002410c6a41f4b5ca00105b21012002200041086a36020c20014190b6ca00410c2002410c6a41f4b5ca00105b1a20022d00042100024020022d0005450d00200041ff0171210141012100024020010d0020022802002200411c6a28020028020c210120002802182103024020002d00004104710d0020034190a5c0004102200111000021000c010b20034192a5c0004101200111000021000b200220003a00040b200241106a2400200041ff01714100470b900201027f024002400240024002402001410c6a2802002203417f6a220420034d0d004116102d22010d010c040b200420026b220220044d0d02411b102d2201450d0320002001360204200141176a41002800ecba4a360000200141106a41002900e5ba4a370000200141086a41002900ddba4a370000200141002900d5ba4a370000200041086a429b808080b0033702000c010b200020013602042001410e6a41002900cdba4a370000200141086a41002900c7ba4a370000200141002900bfba4a370000200041086a4296808080e0023702000b200041013602000f0b0240200320024d0d002000200128020420024104746a360204200041003602000f0b41c4c2ca0020022003103b000b1036000bd00401037f230041e0006b220324002003200236020c024041002802a4e24a4105490d002003410136021420032003410c6a36021041002802b0e24a210241002802ace24a210441002802a8e24a2105200341d8006a41ef00360200200341d0006a42ed80808010370300200341cc006a41bcb8ca00360200200341c4006a4225370200200341c0006a41b3b9ca00360200200341386a4201370300200341286a4201370300200341206a410a360200200341346a200341106a360200200341e8b9ca00360224200341a9b9ca0036021c20034105360218200441cca5c000200541024622051b200341186a200241e4a5c00020051b280210110200200328020c21020b02400240024002400240024002402002450d00200341186a2001410010c20620032802184101460d0120012802002202200328021c2204280208460d022002200328020c6b220420024d0d03410f102d22020d040c060b200041003602000c040b2000200341186a4104722202290200370200200041086a200241086a2802003602000c030b024020042d000c0d004125102d2202450d04200042a5808080d004370204200020023602002002411d6a410029008dba4a370000200241186a4100290088ba4a370000200241106a4100290080ba4a370000200241086a41002900f8b94a370000200241002900f0b94a3700000c030b200041003602000c020b20004100360200200120043602000c010b2000428f808080f00137020420002002360200200241076a410029009cba4a37000020024100290095ba4a3700000b200341e0006a24000f0b1036000bb507010b7f230041e0006b22032400200320013602202002280208220441546a2105200241106a280200220641306c210202400340024020020d00410021070c020b200241506a21022005412c6a2107200541306a2208210520072d00004102470d000b200341186a200810d60320032802182107200328021c21020b2002410020071b2109200641306c2102200441546a2105200741c8e1ca0020071b210a02400340024020020d004100210b0c020b200241506a21022005412c6a2107200541306a2208210520072d00004104470d000b200341106a200810d6032003280210210b2003280214210c0b200641306c2102200441546a2105200b41c8e1ca00200b1b210d02400240024002400240024002400240024003402002450d01200241506a21022005412c6a2107200541306a2208210520072d00004103470d000b200841086a2802002202450d00200241286c2107200828020041186a2102410021050340200520022d0000456a2105200241286a2102200741586a22070d000b200520014d0d01200641306c2102200441546a210503402002450d07200241506a21022005412c6a2107200541306a2208210520072d00004103470d000b200341086a200810d603200328020c220b41286c210520032802082204210703402005450d08200541586a2105200741186a2108200741286a2202210720082d00000d000b20010d02200241586a21020c030b410021050b0240200c4100200b1b200120056b22024d0d00200d20024102746a22020d030b200341dc006a41013602002003420237024c200341e0c1ca003602482003410136022c2003200341286a3602582003200341206a360228200341386a200341c8006a103a200341386a21020c030b2004200b41286c6a210803402001417f6a2101034020082002460d06200241186a2105200241286a2207210220052d00000d000b2007210220010d000b200741586a21020b2002411c6a21020b2003200228020022023602240240200920024d0d00200a20024104746a2202450d0020002002360204410021020c040b200341dc006a4102360200200341c4006a41013602002003420337024c200341f0c1ca003602482003410136023c2003200341386a3602582003200341206a3602402003200341246a360238200341286a200341c8006a103a200341286a21020b20022802002105200041086a200229020437020020002005360204410121020c020b41adc0ca0041c20041f0c0ca001055000b4180c1ca0041dd0041f0c0ca001055000b20002002360200200341e0006a24000bd50302047f017e024020014101762202450d0003402002417f6a2202210302400240024003402003410174220441017221050240200441026a220420014f0d00200520014f0d0220042005200020054103746a280200200020044103746a280200491b21050b200520014f0d03200320014f0d02200020034103746a2203280200200020054103746a22042802004f0d03200329020021062003200429020037020020042006370200200521030c000b0b41b0bcca0020052001103b000b41c0bcca0020032001103b000b20020d000b0b0240024020014102490d002001210403402004417f6a220420014f0d02200029020021062000200020044103746a2205290200370200200520063702004100210302400240024003402003410174220241017221050240200241026a220220044f0d00200520044f0d0220022005200020054103746a280200200020024103746a280200491b21050b200520044f0d03200320044f0d02200020034103746a2203280200200020054103746a22022802004f0d03200329020021062003200229020037020020022006370200200521030c000b0b41b0bcca0020052004103b000b41c0bcca0020032004103b000b200441014b0d000b0b0f0b4198bbca0020042001103b000bea04050a7f017e017f017e027f200041686a21022001417f6a2103200041086a2104410021052001413249210641012107024003400240024020072001490d00410021080c010b410121082000200741037422096a220a280200220b200a41786a280200490d00200420096a210803404101210a20032007460d03200741016a21072008280200220a200b4f2109200841086a2108200a210b20090d000b200720014921080b2007200146210a20060d0120072001460d010240024002400240024002402007417f6a220b20014f0d002008450d012000200b4103746a220b290200210c200b20002007410374220d6a2208290200220e3702002008200c37020020074102490d0520002007417e6a220a4103746a220f280200200ea722094d0d05200b200f290200370200200a450d0420002007417d6a220a4103746a28020020094d0d042002200d6a210b0340200b41086a200b290200370200200a450d03200a417f6a210a200b41786a220b28020020094b0d000b200a41016a210b0c030b4188bbca00200b2001103b000b4198bbca0020072001103b000b4100210b0b2000200b4103746a210f0b200f200e3702000b200541016a21050240200120076b220a4102490d00200828020820082802004f0d002008290200210c20082008290208370200200841086a210f0240200a4103490d002008280210200ca722104f0d00200841106a21094103210b4102210d0340200d41037420086a220f41786a2009290200370200200b200a4f0d01200b4103742109200b210d200b41016a210b200820096a22092802002010490d000b0b200f200c3702000b20054105470d000b4100210a0b200a0b2600024020002802002d00000d00200141c5a4c0004105104c0f0b200141caa4c0004104104c0bc60501087f230041106b220324002002280208220441546a2105200241106a280200220641306c210702400340410021082007450d01200741506a21072005412c6a2109200541306a220a210520092d00004103470d000b200a41086a2802002207450d00200741286c2105200a28020041186a2107410021080340200820072d0000456a2108200741286a2107200541586a22050d000b0b024002400240024002400240200120086b220a20014b0d00200641306c2107200441546a210503402007450d02200741506a21072005412c6a2108200541306a2209210520082d0000410c470d000b200941086a280200200a4b0d03411e102d2207450d052000200736020420004101360200200741166a41002900a5c04a370000200741106a410029009fc04a370000200741086a4100290097c04a3700002007410029008fc04a370000200041086a429e808080e0033702000c040b412c102d22070d010c040b412c102d2207450d032000200736020420004101360200200741286a410028008bc04a360000200741206a4100290083c04a370000200741186a41002900fbbf4a370000200741106a41002900f3bf4a370000200741086a41002900ebbf4a370000200741002900e3bf4a370000200041086a42ac808080c0053702000c020b2000200736020420004101360200200741286a41002800dfbf4a360000200741206a41002900d7bf4a370000200741186a41002900cfbf4a370000200741106a41002900c7bf4a370000200741086a41002900bfbf4a370000200741002900b7bf4a370000200041086a42ac808080c0053702000c010b2009280200200a41186c6a28020821072003200a200210c006024020032802004101470d0020002003290204370204200041013602002000410c6a2003410c6a2802003602000c010b20032802042105200041003602002000200520076a3602040b200341106a24000f0b1036000b100020002802003502004101200110450b890301087f02400240024002400240200041086a2802002201450d00410020014102746b2102417f210320002802002204210503402002450d01200341016a2103200241046a210220052802002106200541046a21052006450d000b4100200641004741016a41017122056b2003460d002001200520036a2207490d012001200641004741016a4101716b20036b220541ffffffff03712005470d0220054102742208417f4c0d02200521034104210102402008450d002008102d2201450d042008410276220320054f0d00200341017422082005200820054b1b220841ffffffff03712008470d05200841027422084100480d050240024020030d002008102d21010c010b200120034102742008103121010b2001450d04200841027621030b2001200420074102746a4104200641004741016a41017141027420026a6b10e80621020240200041046a280200450d002000280200102f0b20002002360200200041086a2005360200200041046a20033602000b0f0b20072001104b000b103d000b1036000b1038000bc60403077f017e097f02400240024002400240200141086a2802002203200241086a2802002204200320044b1b220541016a22064101200641014b1b220741ffffffff03712007470d0020074102742206417f4c0d000240024020060d0041042108200721090c010b200610332208450d02200641027621090b024020050d004200210a0c040b2004417f6a220b20044b210c2002280200210d2003417f6a220e20034b0d022001280200210f20082007417f6a22064102746a2110410021024200210a03404100211102402003200e20026b22124d0d00410021112012200e4b0d00200f20124102746a28020021110b410021120240200c0d002004200b20026b22134d0d002013200b4b0d00200d20134102746a28020021120b200720064d0d052010200a2011ad7c2012ad7c220a3e02002010417c6a21102006417f6a2106200a422088210a200241016a22022005490d000c040b0b103d000b1036000b20082007417f6a22064102746a2111410021104200210a0340410021020240200c0d00410021022004200b20106b22124d0d00410021022012200b4b0d00200d20124102746a28020021020b200720064d0d022011200a2002ad7c220a3e02002011417c6a21112006417f6a2106200a422088210a201041016a22102005490d000b0b024020072005417f736a220620074f0d00200020073602082000200936020420002008360200200820064102746a200a3e02000240200141046a280200450d002001280200102f0b0f0b419cc3ca0020062007103b000b419cc3ca0020062007103b000bc604030e7f017e017f02400240200241086a2802002203200141086a28020022046a22054101200541014b1b220641ffffffff03712006470d0020064102742205417f4c0d0002400240024020050d0041042107200621080c010b200510332207450d01200541027621080b2004450d022001280200210902400240024020030d0020092004417f6a22054102746a210320072006417f6a22024102746a210a0340200420054d0d0302402003280200450d00200620024d0d03200a41003602000b2003417c6a2103200a417c6a210a2002417f6a21022005417f6a2205417f470d000c060b0b200641027420076a417c6a210b200341027420022802006a417c6a210c4100210d2006210e03402004200d417f736a220520044f0d020240200920054102746a220f2802002210450d0042002111417f2105200b2102200c210a024003402006200e20056a22124d0d012002200a3502002010ad7e20117c20023502007c22113e0200201142208821110240200320056a0d002006200d20036a417f736a220220064f0d05200720024102746a20113e02000c030b2002417c6a2102200a417c6a210a200f280200211020032005417f6a22056a22122003490d000b41c4c2ca0020122003103b000b41c4c2ca0020122006103b000b200b417c6a210b200e417f6a210e200d41016a220d2004460d050c000b0b419cc3ca0020022006103b000b41c4c2ca0020052004103b000b1036000b103d000b2000200636020820002008360204200020073602000240200141046a280200450d002001280200102f0b0bca0302097f017e230041106b2201240002400240024002400240024002402000280200220228020041016a41004c0d002000280204220328020041016a41004c0d012000280208220441086a28020022054101200028020c22062802006b22076a220820054f0d02200720002802142802006b22052000280210220741086a28020022006a220920054f0d03024002402002290308220a42ffffffff0f560d0041002100200a200428020020084102746a3502007e2003290308422086200728020020094102746a35020084580d010b20022802000d052002410036020020022002290308427f7c370308200441086a2802002200200020062802006b22024d0d0620032802000d07200428020020024102746a350200210a200341003602002003200a20032903087c370308410121000b200141106a240020000f0b41c6c4ca004118200141086a41e0c4ca0041f0c4ca00103e000b41c6c4ca004118200141086a41e0c4ca0041f0c4ca00103e000b41c4c2ca0020082005103b000b41c4c2ca0020092000103b000b41c3c5ca004110200141086a41d4c5ca0041e4c5ca00103e000b41c4c2ca0020022000103b000b41c3c5ca004110200141086a41d4c5ca0041e4c5ca00103e000b9e0301087f200028020822024102742103410021042000280200220521000240024003402003450d012004417f6a21042003417c6a210320002802002106200041046a21002006450d000b410121072004417f73200641004741016a4101716a21080c010b41002107410020046b21080b200128020822094102742103410021042001280200220121000240024003402003450d012004417f6a21042003417c6a210320002802002106200041046a21002006450d000b410021032004417f73200641004741016a4101716a21000c010b410020046b2100410121030b024020070d00410020034101736b0f0b4101210402400240024020030d0020022008490d0120092000490d02417f200220086b2203200920006b22064720032006491b22040d0020062003200320064b1b2107200120004102746a2103200520084102746a2100417f210103400240200141016a22012007490d0041000f0b2003280200210420002802002106200341046a2103200041046a2100417f200620044720062004491b2204450d000b0b20040f0b20082002104b000b20002009104b000bbc0101067f0240024002402001280208220241ffffffff03712002470d0020024102742203417f4c0d00200128020021040240024020030d002002410274210541042101200221060c010b2003102d2201450d02200241027421052003410276220620024f0d00200341017622062002200620024b1b220641027422074100480d0320012003200710312201450d020b20012004200510e80621032000200236020820002006360204200020033602000f0b103d000b1036000b1038000ba505010b7f024002400240024002400240024002402001280204220220012802002203490d0020012d000841ff01710d00200128000c210441002105024002404100200220036b2206200620024b1b220741016a220120074f0d00200441086a2106410021084100210741002101410021054104210903402006280200220a2002417f736a220b200a4f0d07200320024f210a200220032002496b21022004280200200b4102746a280200210b024020012005470d002001417f41004100417f4100200220036b2205200520024b1b220541016a220c200c2005491b200a1b20022003491b220541016a220c200c2005491b6a22052001490d0320082005200820054b1b220541ffffffff03712005470d03200541027422054100480d030240024020010d002005102d21090c010b200920072005103121090b2009450d09200541027621050b200920076a200b360200200841026a2108200741046a2107200141016a21012002200349200a72450d000c060b0b0240024020010d00410421090c010b200141ffffffff03712001470d01200141027422014100480d012001102d2209450d07200141027621050b200220034d0d022002417f732101200441086a210a2009210703402001200a280200220b6a220820014f0d082007200428020020084102746a280200360200200141016a2101200741046a210720032002417f6a2202490d000b200641016a21010c030b1038000b4104210941002101410021050c020b4100210120022003470d0141012101200921070b200441086a28020022022003417f736a220320024f0d042007200428020020034102746a2802003602000b2000200136020820002005360204200020093602000f0b41c4c2ca00200b200a103b000b1036000b41c4c2ca002008200b103b000b41c4c2ca0020032002103b000b7301027f230041106b2203240002404110102d22040d001036000b200420013e020c200420014220883e0208200420023e0204200420024220883e020020034284808080c00037020420032004360200200310ca06200041086a200328020836020020002003290300370200200341106a24000b1c00200128021841ffcbca00410f2001411c6a28020028020c1100000bb00301047f230041c0006b22022400200028020021034101210002402001280218418ca4c000410c2001411c6a28020028020c1100000d0002400240200328020822000d0020032802002200200328020428020c11070042e4aec285979ba58811520d012002200036020c2002413436021420022002410c6a36021020012802182104200128021c2105410121002002413c6a41013602002002420237022c20024198a4c0003602282002200241106a36023820042005200241286a103c0d020c010b2002200036020c2002410836021420022002410c6a36021020012802182104200128021c2105410121002002413c6a41013602002002420237022c20024198a4c0003602282002200241106a36023820042005200241286a103c0d010b200328020c2100200241106a41146a4101360200200241106a410c6a410136020020022000410c6a3602202002200041086a360218200241043602142002200036021020012802182100200128021c2101200241286a41146a41033602002002420337022c200241a8a4c0003602282002200241106a36023820002001200241286a103c21000b200241c0006a240020000b21002000417f6a41ff01712002ad4220862001ad842004ad4220862003ad8410000b1c00200128021841ffcbca00410f2001411c6a28020028020c1100000b1c00200128021841ffcbca00410f2001411c6a28020028020c1100000ba70601037f230041d0006b22042400200420033a000f024002400240024020022802082205417f6a220620054f0d00200620054d0d010b4118102d2202450d012004421837023420042002360230200441306a4100411810d80620042004280238220241186a3602382002200428023022056a41184192ddca00411810d906200420042902343702342004200536023041ecd1ca004134200441306a41ccd1ca0041a0d2ca00103e000b200141086a2802002105200228020020064103746a220628020021020240024020062d0006450d0020052002460d010b02400240200520024d0d00200141086a2005417f6a2202360200200128020020026a2d00002205417c6a220241014b0d01024020020e020300030b4118102d2202450d03200241106a41002900a2dd4a370000200241086a410029009add4a37000020024100290092dd4a37000020044298808080800337022420042002360220200441c4006a410136020020044201370234200441c0d7ca003602302004413136024c2004200441c8006a3602402004200441206a360248200441106a200441306a103a02402004280224450d002004280220102f0b200041013a0000200041046a20042903103702002000410c6a200441106a41086a2802003602000c040b412b102d2202450d02200041013a0000200241276a41002800fcd64a360000200241206a41002900f5d64a370000200241186a41002900edd64a370000200241106a41002900e5d64a370000200241086a41002900ddd64a370000200241002900d5d64a370000200041086a42ab808080b005370200200041046a20023602000c030b02400240200341ff017122024104460d0020052002470d010b200041003a0000200020053a00010c030b200420053a0048200441c4006a4102360200200441206a410c6a41373602002004420237023420044180d7ca00360230200441373602242004200441206a3602402004200441c8006a36022820042004410f6a360220200441106a200441306a103a2000410c6a200441186a280200360200200041046a2004290310370200200041013a00000c020b20004180083b01000c010b1036000b200441d0006a24000b7d01017f024002400240200041046a280200220320016b20024f0d00200120026a22022001490d01200341017422012002200120024b1b22014100480d010240024020030d002001102d21020c010b200028020020032001103121020b2002450d0220002002360200200041046a20013602000b0f0b1038000b1036000bea0101017f230041e0006b22042400200420013602082004200336020c024020012003470d0020002002200110e8061a200441e0006a24000f0b200441286a41146a4109360200200441346a410a360200200441106a41146a41033602002004200441086a36024020042004410c6a360244200441c8006a41146a410036020020044203370214200441b4e0ca003602102004410a36022c200441c8e1ca003602582004420137024c20044188e1ca003602482004200441286a3602202004200441c8006a3602382004200441c4006a3602302004200441c0006a360228200441106a41c8e1ca001043000bef0502047f017e230041d0006b2203240002400240024002400240200241086a2802002204417f6a220520044f0d00200520044d0d010b4118102d2202450d01200241106a41002900a2dd4a370000200241086a410029009add4a37000020024100290092dd4a37000020034298808080800337021420032002360210200341cc006a41013602002003420137023c200341c0d7ca00360238200341313602342003200341306a3602482003200341106a360230200341206a200341386a103a200041086a200341206a41086a280200360200200020032903203702002003280214450d032003280210102f0c030b0240024002402002280200220620054103746a2d000522054104460d00200341386a20012002200510d706024020032d00384101470d002000200329023c370200200041086a200341c4006a2802003602000c060b200241086a2802002204450d01200228020021060b200241086a2004417f6a2202360200200620024103746a290200220742808080808080c0ff0083428080808080808001520d010b4118102d2202450d01200241106a41002900a2dd4a370000200241086a410029009add4a37000020024100290092dd4a37000020034298808080800337021420032002360210200341cc006a41013602002003420137023c200341c0d7ca00360238200341313602342003200341306a3602482003200341106a360230200341206a200341386a103a200041086a200341206a41086a280200360200200020032903203702002003280214450d032003280210102f0c030b200141086a28020021022003200737030820022007a7470d01200041003602000c020b1036000b200341cc006a41023602002003412c6a41013602002003420237023c200341c4d5ca0036023820034101360224200320023602302003200341206a3602482003200341086a3602282003200341306a360220200341106a200341386a103a200041086a200341106a41086a280200360200200020032903103702000b200341d0006a24000be30302037f017e230041c0006b22042400200441286a20012002200310d7060240024002400240024020042d00284101460d0002400240200141086a2802002202200128020c4f0d0002402002200141046a280200470d00200241016a22052002490d06200241017422062005200620054b1b22054100480d060240024020020d002005102d21020c010b200128020020022005103121020b2002450d0520012002360200200141046a2005360200200141086a28020021020b200128020020026a20033a0000200141086a2201200128020041016a3602000c010b2004413c6a220341013602002004420137022c200441fcdeca003602282004410136021420042001410c6a3602102004200441106a360238200441186a200441286a103a20042802182201450d002004200429021c37020420042001360200200341013602002004420137022c200441c0d7ca00360228200441313602142004200441106a36023820042004360210200441186a200441286a103a20042802182101200429021c210702402004280204450d002004280200102f0b20010d020b200041003602000c040b2000200429022c370200200041086a200441346a2802003602000c030b20002007370204200020013602000c020b1036000b1038000b200441c0006a24000ba80301057f230041c0006b2203240020032002360200024002402001280204220420024b0d002001280208417c6a21052001410c6a280200410374210102400340024020010d00200320043602042003412c6a4102360200200341306a410c6a41013602002003420337021c200341dcdfca00360218200341013602342003200341306a3602282003200341046a36023820032003360230200341086a200341186a103a2000410c6a200341106a280200360200200041046a2003290308370200200041013a00000c040b2004200541046a2802006a22062004490d01200141786a2101200541086a2105200420024b21072006210420070d0020062104200620024d0d000b20052d00002104200041003a0000200020043a00010c020b02404120102d2204450d00200041013a0000200441186a41002900d4df4a370000200441106a41002900ccdf4a370000200441086a41002900c4df4a370000200441002900bcdf4a370000200041086a42a08080808004370200200041046a20043602000c020b1036000b200041003a00002000200128020020026a2d00003a00010b200341c0006a24000bbd0201037f230041106b220224000240024020002d00004104470d002002200128021841b8d4ca0041032001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c010b20022001280218419dd4ca0041082001411c6a28020028020c1100003a000820022001360200200241003a0009200241003602042002200036020c20022002410c6a41a8d4ca001061210120022d0008210020022802042203450d00200041ff0171210441012100024020040d00024020034101470d0020012d0009450d00200128020022042d00004104710d004101210020042802184196a5c00041012004411c6a28020028020c1100000d010b2001280200220028021841e4d3ca0041012000411c6a28020028020c11000021000b200120003a00080b200241106a2400200041ff01714100470b860602037f017e230041d0006b22052400200520023602082005200336020c024002400240417f41012002411f71742002411f4b1b20034b0d00200541386a200141186a2203200141286a410010d70620052d00384101470d012000200529023c370200200041086a200541c4006a2802003602000c020b200541cc006a41023602002005411c6a41013602002005420337023c2005419cd3ca00360238200541013602142005200541106a36024820052005410c6a3602182005200541086a360210200541206a200541386a103a200041086a200541206a41086a280200360200200020052903203702000c010b20012802002102200541003602200240024020022802080d00200541cc006a41013602002005420237023c20054190dbca00360238200541013602342005200541306a3602482005200541206a360230200541106a200541386a103a200528021022020d010b02400240024002400240200141206a2802002202200141246a22062802004f0d00024020022001411c6a280200470d00200241016a22062002490d05200241017422072006200720064b1b22064100480d050240024020020d002006102d21020c010b200328020020022006103121020b2002450d04200120023602182001411c6a2006360200200141206a28020021020b200128021820026a20043a0000200141206a2202200228020041016a3602000c010b200541cc006a220241013602002005420137023c200541fcdeca0036023820054101360234200520063602302005200541306a360248200541106a200541386a103a20052802102201450d002005200529021437022420052001360220200241013602002005420137023c200541c0d7ca00360238200541313602342005200541306a3602482005200541206a360230200541106a200541386a103a200528021021022005290214210802402005280224450d002005280220102f0b20020d010b200041003602000c040b20002008370204200020023602000c030b1036000b1038000b20002005290214370204200020023602000b200541d0006a24000bb00301017f230041d0006b22052400200520023602082005200336020c02400240024002400240417f41012002411f71742002411f4b1b20034b0d002001280200210220054100360234024020022802080d00200541cc006a41013602002005420237023c20054190dbca00360238200541013602142005200541106a3602482005200541346a360210200541206a200541386a103a200528022022020d020b200541386a200141186a2202200141286a2203200410d70620052d00384101460d02200541386a20022003410010d70620052d00384101460d03200041003602000c040b200541cc006a41023602002005412c6a41013602002005420337023c2005419cd3ca00360238200541013602242005200541206a36024820052005410c6a3602282005200541086a360220200541106a200541386a103a200041086a200541106a41086a280200360200200020052903103702000c030b20002005290224370204200020023602000c020b2000200529023c370200200041086a200541c4006a2802003602000c010b2000200529023c370200200041086a200541c4006a2802003602000b200541d0006a24000ba60402047f017e230041c0006b22032400200341286a200141186a2204200141286a2205200210d70602400240024020032d00284101460d00200341286a20042005200210d70620032d00284101470d012000200329022c370200200041086a200341346a2802003602000c020b2000200329022c370200200041086a200341346a2802003602000c010b02400240024002400240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d05200241017422062005200620054b1b22054100480d050240024020020d002005102d21020c010b200428020020022005103121020b2002450d04200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c010b2003413c6a220141013602002003420137022c200341fcdeca0036022820034101360214200320053602102003200341106a360238200341186a200341286a103a20032802182202450d002003200329021c37020420032002360200200141013602002003420137022c200341c0d7ca00360228200341313602142003200341106a36023820032003360210200341186a200341286a103a20032802182101200329021c210702402003280204450d002003280200102f0b20010d010b200041003602000c030b20002007370204200020013602000c020b1036000b1038000b200341c0006a24000ba60402057f017e230041c0006b22032400200341286a200141186a2204200141286a2205200210d70602400240024020032d00284101460d00200341286a20042005200210d70620032d00284101470d012000200329022c370200200041086a200341346a2802003602000c020b2000200329022c370200200041086a200341346a2802003602000c010b02400240024002400240200141206a2802002205200141246a22062802004f0d00024020052001411c6a280200470d00200541016a22062005490d05200541017422072006200720064b1b22064100480d050240024020050d002006102d21040c010b200428020020052006103121040b2004450d04200120043602182001411c6a2006360200200141206a28020021050b200128021820056a20023a0000200141206a2201200128020041016a3602000c010b2003413c6a220141013602002003420137022c200341fcdeca0036022820034101360214200320063602102003200341106a360238200341186a200341286a103a20032802182202450d002003200329021c37020420032002360200200141013602002003420137022c200341c0d7ca00360228200341313602142003200341106a36023820032003360210200341186a200341286a103a20032802182101200329021c210802402003280204450d002003280200102f0b20010d010b200041003602000c030b20002008370204200020013602000c020b1036000b1038000b200341c0006a24000b17000240200041046a280200450d002000280200102f0b0b0c002000280200200110ab060b1500200028020022002802002000280208200110640b1000200120002802002000280208104c0bfb0101027f230041106b220224002002200128021841a4dfca0041052001411c6a28020028020c1100003a000820022001360200200241003a0009200241003602042002200036020c20022002410c6a41acdfca0010611a20022d00082101024020022802042203450d00200141ff0171210041012101024020000d00024020034101470d0020022d000941ff0171450d00200228020022002d00004104710d004101210120002802184196a5c00041012000411c6a28020028020c1100000d010b2002280200220128021841e4d3ca0041012001411c6a28020028020c11000021010b200220013a00080b200241106a2400200141ff01714100470b2c01017f02402002450d00200021030340200320013a0000200341016a21032002417f6a22020d000b0b20000b3601017f02402002450d00200021030340200320012d00003a0000200341016a2103200141016a21012002417f6a22020d000b0b20000b7101017f0240024020012000490d002002450d01200021030340200320012d00003a0000200141016a2101200341016a21032002417f6a22020d000c020b0b2002450d002001417f6a21012000417f6a21030340200320026a200120026a2d00003a00002002417f6a22020d000b0b20000b4a01037f4100210302402002450d000240034020002d0000220420012d00002205470d01200041016a2100200141016a21012002417f6a2202450d020c000b0b200420056b21030b20030b5701017e02400240200341c000710d002003450d012001410020036b413f71ad8820022003413f71ad220486842102200120048621010c010b20012003413f71ad862102420021010b20002001370300200020023703080b5701017e02400240200341c000710d002003450d0120012003413f71ad2204882002410020036b413f71ad86842101200220048821020c010b20022003413f71ad882101420021020b20002001370300200020023703080b7501027e200020034220882205200142208822067e200320027e7c200420017e7c200342ffffffff0f832203200142ffffffff0f8322017e2204422088200320067e7c22034220887c200342ffffffff0f83200520017e7c22034220887c37030820002003422086200442ffffffff0f83843703000b3e01017f230041106b2205240020052001200220032004410010f006200529030021012000200541086a29030037030820002001370300200541106a24000b4c01017f230041206b22052400200542003703182005420037031020052001200220032004200541106a10f006200529031021012000200529031837030820002001370300200541206a24000be20502037f067e230041306b2206240002400240024002400240024002400240024002402002500d002003500d012004500d02200479a7200279a76b2207413f4b0d0341ff0020076b2108200741016a21070c080b02402004500d0020050d040c060b024002402005450d0020034200510d0620054200370308200520012003823703000c010b20034200510d050b200120038021010c060b2004500d030240024002402001500d0020047b4201510d01200479a7200279a76b2207413e4b0d0241ff0020076b2108200741016a21070c090b02402005450d0020054200370300200520022004823703080b200220048021010c070b02402005450d002005200137030020052004427f7c2002833703080b200220047a423f838821010c060b2005450d040c020b024020037b4201510d0041bf7f200379a7200279a76b22076b2108200741c1006a21070c060b02402005450d002005420037030820052003427f7c2001833703000b20034201510d06200641206a2001200220037aa710ec06200641286a2903002102200629032021010c060b2005450d020b2005200137030020052002370308420021010c020b00000b420021010b420021020c010b200620012002200841ff007110eb06200641106a20012002200741ff007110ec06200641086a2903002102200641106a41086a2903002109200629030021012006290310210a0240024020070d004200210b4200210c0c010b4200210c4200210d03402009420186200a423f8884220b200b427f8520047c200a4201862002423f8884220a427f85220b20037c200b54ad7c423f87220b2004837d200a200b200383220e54ad7d2109200a200e7d210a420020024201862001423f8884842102200d2001420186842101200b420183220b210d2007417f6a22070d000b0b02402005450d002005200a370300200520093703080b200c20024201862001423f8884842102200b20014201868421010b2000200137030020002002370308200641306a24000b0bcce20a0300418080c0000ba1e20a6361706163697479206f766572666c6f770000002400100017000000f0020000050000007372632f6c6962616c6c6f632f7261775f7665632e727300cb0010004600000058010000130000003c00000004000000040000003d0000003e0000003f0000006120666f726d617474696e6720747261697420696d706c656d656e746174696f6e2072657475726e656420616e206572726f72003c000000000000000100000040000000b8001000130000003b020000050000007372632f6c6962616c6c6f632f666d742e72732f72757374632f373563663431616662343638313532363131323132323731626165303236393438636433626134362f7372632f6c6962636f72652f666d742f6d6f642e727301010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000202020202020202020202020202020202020202020202020202020202020303030303030303030303030303030304040404040000000000000000000000000000340210002000000054021000120000003c000000000000000100000041000000696e646578206f7574206f6620626f756e64733a20746865206c656e20697320206275742074686520696e646578206973203030303130323033303430353036303730383039313031313132313331343135313631373138313932303231323232333234323532363237323832393330333133323333333433353336333733383339343034313432343334343435343634373438343935303531353235333534353535363537353835393630363136323633363436353636363736383639373037313732373337343735373637373738373938303831383238333834383538363837383838393930393139323933393439353936393739383939000068031000060000006e031000220000005003100018000000b30a0000050000007372632f6c6962636f72652f736c6963652f6d6f642e7273696e64657820206f7574206f662072616e676520666f7220736c696365206f66206c656e67746820b003100016000000c60310000d0000005003100018000000b90a000005000000736c69636520696e64657820737461727473206174202062757420656e6473206174205b2e2e2e5dba0410000b000000ca11100016000000f904100001000000a4041000160000009208000009000000a81110000e000000b611100004000000ba11100010000000f904100001000000a404100016000000960800000500000063616c6c656420604f7074696f6e3a3a756e77726170282960206f6e206120604e6f6e65602076616c756500a404100016000000a70800000e000000ba0410000b000000c504100026000000eb04100008000000f304100006000000f904100001000000a404100016000000a9080000050000007372632f6c6962636f72652f7374722f6d6f642e72736279746520696e64657820206973206e6f742061206368617220626f756e646172793b20697420697320696e7369646520202862797465732029206f6620606000003a051000020000002405100016000000460400002400000024051000160000003c040000110000007372632f6c6962636f72652f666d742f6d6f642e72732e2e3078040f151b190312171100000e160000000000000000000000000000000000000000000000000000000006130000000000000000000000000000000000000002070a00080c1d1c181a00000000000000000000000000000000000005010000000000000000000000000000000000000010000000000b00090014000d00000000000000000000000000000000000000000000000000000000000f12000000000000000000000000001f0000000000000000000000000000004946661d0000000000000000000000008a3e000000000000000000000000004b530000000000000000000000006723420000000000000000000000003d0000000000230000000000000000007500002d000000000000000000000000824e3c0000000000000000000000006300000025005a000000000000008136000003000000000000000000002f000000000000000010000000000013000800000000000000000000000000430072008900000000000000000000070000007d05183f003787094064000021000000000000000000000000000a0000410000000000000000000000000c0030005c00000019777100604735442e0000743911652c515e7f500000003431000000530000000000003a00000000381a00885f2b6b695d4f5d84802a68143b0017000000000000000000000000005500005700000083000000000000000059000000000000266e1b1600000000006d4a1c000000000000000000002400007c0052007b06150000000048000000007e2876276c2900225b0e610d567062048520780200007a1e7901540033000000867358004d456f0b6a0000326c4c0000898a00008a8a8a3e0000000000000000000000280c10001a000000380000000f000000280c10001a000000390000001000000000000000000000000000000001000000000000000d000000000000001c000000000000004000000000000000b600000000000000bf00000000000000f803000000000000f007000000000000ff070000000000000010000000000000001e0000000000000038000000000000003f000000000000807f0000000000000080000000000000c0ff01000000000080ff030000000000008007000000000000007f000000000001208000000000000000a3000000000000fc7f030000000000000006000000000000ff070000000000008009000000000000000e0000000080007e0e00000000642000200000000040fe0f2000000000010000300000000000000040000000005c00004000000000000000600000000000845c8000000000000000c000000000000000e00000000000000000010000000000f00c01000000443060000c000000c13d60000c0000001e2080000c0000001e20c0000c000000fe21fe000c00000000000000200000000000000060000000440800006000000000000000f000000060000000000200007ffffff9db07000000000080f8070000000000e0bc0f00000000000020210000030000003c3b0000e70f0000003c00000000c09f9f3d00000000c0fbef3e000000000000c03f00000000000000f000000000000000fc0000100000f8feff0000ffff0000ffff0000ffffffffffff000000f8ffff0000010000000000c0ff01000000ffffffff0100000000000000030000000000008003000000000040a30300000000000000080000000c0000000c000400000000f80f00000000000000180000001c0000001c00000000c301001e000000000000001f0001008000c01f1f000700000080ef1f00ffffffffff1f20008639020000002300020000000030400000000000007e66000000fcfffffc6d000000000000007f00000000000028bf000000000000f0cf00000000030000a0020000f7fffd2110030300000000007806000000000080ff06000000000000c007000000000000f207000000008701040e0600000000000010081000000000001007000000000000140f0000000000f017000000000000f21fdfe0fffeffffff1f00000000000000200000000000f80f20070000000000c833000000000000b03f000000000080f73f04000000000000401e2080000c000040000000000080d340020000000000005003000000000000580000000000e0fd66fe0700000000f879030000000000c07f000000000000fe7f000000000000ff7f00000000000000807f0000000000008030000000ffff03806ef000000000008702000000000000900000407fe51ff89f000000000000f9a5000000000000f8a70000000000803cb00000000000007eb40000000000007fbf0000feffffffffbf11000000000000c00000000000009dc102000000000000d000000000a0c307f8ffffffffffff7ff8fffffffffffffffbbe2100000c0000fc00000000000000ff02000000000000ff000002000000ffff0000f8fffbffffff00000000ffffffffffffffffffffffff7372632f6c6962636f72652f756e69636f64652f6d6f642e727300010305050606030706080809110a1c0b190c140d120e0d0f0410031212130916011705180219031a071c021d011f1620032b042c022d0b2e01300331023201a702a902aa04ab08fa02fb05fd04fe03ff09ad78798b8da23057588b8c901c1ddd0e0f4b4cfbfc2e2f3f5c5d5fb5e2848d8e9192a9b1babbc5c6c9cadee4e5ff00041112293134373a3b3d494a5d848e92a9b1b4babbc6cacecfe4e500040d0e11122931343a3b4546494a5e646584919b9dc9cecf0d112945495764658d91a9b4babbc5c9dfe4e5f0040d1145496465808184b2bcbebfd5d7f0f183858ba4a6bebfc5c7cecfdadb4898bdcdc6cecf494e4f57595e5f898e8fb1b6b7bfc1c6c7d71116175b5cf6f7feff800d6d71dedf0e0f1f6e6f1c1d5f7d7eaeafbbbcfa16171e1f46474e4f585a5c5e7e7fb5c5d4d5dcf0f1f572738f747596972f5f262e2fa7afb7bfc7cfd7df9a409798308f1fc0c1ceff4e4f5a5b07080f10272feeef6e6f373d3f42459091feff536775c8c9d0d1d8d9e7feff00205f2282df048244081b04061181ac0e80ab351e1580e003190801042f043404070301070607110a500f1207550802041c0a090308030703020303030c0405030b06010e15053a0311070605100757070207150d500443032d03010411060f0c3a041d255f206d046a2580c80582b0031a0682fd035907150b1709140c140c6a060a061a0659072b05460a2c040c040103310b2c041a060b0380ac060a061f414c042d0374083c030f033c0738082b0582ff1118082f112d032010210f808c048297190b158894052f053b07020e180980b030740c80d61a0c0580ff0580b605240c9bc60ad23010848d033709815c1480b80880c73035040a06380846080c06740b1e035a0459098083181c0a16094808808a06aba40c170431a10481da26070c050580a511816d1078282a064c04808d0480be031b030f0d0088111000200000001a000000280000000006010103010402080809020a050b02100111041205131114021502170219041c051d0824016a036b02bc02d102d40cd509d602d702da01e005e102e802ee20f004f906fa020c273b3e4e4f8f9e9e9f060709363d3e56f3d0d104141836375657bd35cecfe01287898e9e040d0e11122931343a4546494a4e4f64655a5cb6b71b1ca8a9d8d909379091a8070a3b3e66698f926f5feeef5a629a9b2728559da0a1a3a4a7a8adbabcc4060b0c151d3a3f4551a6a7cccda007191a22253e3fc5c604202325262833383a484a4c50535556585a5c5e606365666b73787d7f8aa4aaafb0c0d00c72a3a4cbcc6e6f5e227b0503042d036504012f2e80821d03310f1c0424091e052b0544040e2a80aa06240424042808340b018090813709160a088098390363080930160521031b05014038044b052f040a070907402027040c0936033a051a07040c07504937330d33072e080a81261f808128082a808617094e041e0f430e19070a0647092709750b3f412a063b050a0651060105100305808b602048080a80a65e22450b0a060d1339070a362c041080c03c64530c0180a0451b4808531d398107460a1d03474937030e080a0639070a81361980c7320d839b66750b80c48abc842f8fd18247a1b98239072a040260260a460a28051382b05b654b0439071140041c97f80882f3a50d811f3103110408818c89046b050d03090710936080f60a73086e1746809a140c570919808781470385420f1585502b80d52d031a040281703a0501850080d7294c040a04028311444c3d80c23c06010455051b3402810e2c04640c560a0d035d033d391d0d2c040907020e06809a83d60a0d030b05740c59070c140c0438080a0628081e527703310380a60c14040305030d06856a7372632f6c6962636f72652f756e69636f64652f7072696e7461626c652e7273626567696e203c3d20656e642028203c3d2029207768656e20736c6963696e672060206973206f7574206f6620626f756e6473206f662060426f72726f774572726f72426f72726f774d75744572726f72000000c8b0120000000000b92112000200000070616e69636b65642061742041121000010000004212100003000000c8b0120000000000401210000100000040121000010000003a27272c2066616c73657472756520202020207b202c20207b0a00003c0000000c000000040000004200000043000000440000002c0a00003c0000000400000004000000450000004600000047000000207d7d28280a2c0a5d5b00003c000000040000000400000048000000490000004a0000003c00000000000000010000004b0000004c0000004d0000003c00000000000000010000004e0000004f0000004d0000003c00000000000000010000004e0000004f0000004d00000054696d657374616d70206d7573742062652075706461746564206f6e636520696e2074686520626c6f636b556e657870656374656454696d65706f696e7457726f6e6754696d65706f696e744e6f54696d65706f696e7453656e646572496e5369676e61746f726965735369676e61746f726965734f75744f664f72646572546f6f4d616e795369676e61746f72696573546f6f4665775369676e61746f726965734e6f417070726f76616c734e6565646564416c7265616479417070726f766564626174636861735f73756261735f6d756c7469617070726f76655f61735f6d756c746963616e63656c5f61735f6d756c746900000000f814100010000000000000000815100002000000000000000000000018151000020000000000000000000000281510000e00000000000000c8b0120000000000000000000000000038151000010000000000000000000000401510000b0000000000000080e811000200000000000000000000004c1510000200000000000000000000005c15100010000000000000006c15100003000000000000000000000084151000020000000000000000000000941510001000000000000000a4151000040000000000000000000000c4151000020000000000000000000000d415100011000000000000006c151000030000000000000000000000e815100002000000000000004261746368496e7465727275707465648472120003000000f2a512000d000000031810005600000059181000130000004261746368436f6d706c657465640000d0171000330000004e65774d756c7469736967005e17100052000000b0171000200000004d756c7469736967417070726f76616cc26d120009000000e416100016000000c26d1200090000000817100056000000ba1610002a0000004d756c74697369674578656375746564c26d120009000000e416100016000000c26d120009000000fa1610000e0000006f1610004b000000ba1610002a0000004d756c746973696743616e63656c6c6564000000f81510004c000000441610002b0000002041206d756c7469736967206f7065726174696f6e20686173206265656e2063616e63656c6c65642e20466972737420706172616d20697320746865206163636f756e7420746861742069732063616e63656c6c696e672c20746869726420697320746865206d756c7469736967206163636f756e742e2041206d756c7469736967206f7065726174696f6e20686173206265656e2065786563757465642e20466972737420706172616d20697320746865206163636f756e74207468617420697320617070726f76696e672c20746869726420697320746865206d756c7469736967206163636f756e742e54696d65706f696e743c426c6f636b4e756d6265723e4469737061746368526573756c742041206d756c7469736967206f7065726174696f6e20686173206265656e20617070726f76656420627920736f6d656f6e652e20466972737420706172616d20697320746865206163636f756e7420746861742069732041206e6577206d756c7469736967206f7065726174696f6e2068617320626567756e2e20466972737420706172616d20697320746865206163636f756e74207468617420697320617070726f76696e672c207365636f6e6420697320746865206d756c7469736967206163636f756e742e204261746368206f66206469737061746368657320636f6d706c657465642066756c6c792077697468206e6f206572726f722e204261746368206f66206469737061746368657320646964206e6f7420636f6d706c6574652066756c6c792e20496e646578206f66206669727374206661696c696e6720646973706174636820676976656e2c2061732077656c6c20617320746865206572726f722e4e6f7773657443757272656e74456c656374656443757272656e744572615374617274536c6f745374616b655374616b65727300b018100048000000bb0100002d0000002f72757374632f373563663431616662343638313532363131323132323731626165303236393438636433626134362f7372632f6c6962636f72652f6f70732f61726974682e72730000000000000000617474656d707420746f20646976696465206279207a65726f0000003c0000000800000004000000500000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f7072696d6974697665732f61726974686d657469632f7372632f7065725f7468696e67732e7273756e636c6573303071202f2028712f246d617829203c202832202a20246d6178292e204d6163726f2070726576656e747320616e792074797065206265696e672063726561746564207468617420646f6573206e6f74207361746973667920746869733b2071656400002c19100052000000880000002d0000002c191000520000008f0000002d0000002c191000520000009a000000210000004661696c656420746f20636f6e7665727466696e616c6e756d00000000000000be1310000500000000000000101b1000010000000000000000000000281b1000120000000000000000000000c31310000600000000000000b81b1000020000000000000000000000e81b1000070000000000000000000000c91310000800000000000000201c1000040000000000000000000000801c1000290000000000000000000000d11310001000000000000000c81d1000040000000000000000000000281e1000200000000000000000000000e11310000f00000000000000281f1000040000000000000000000000881f1000160000000000000000000000402c10000500000000000000452c100017000000002a100020000000c8b0120000000000202a10003b000000c8b01200000000005b2a10001f000000c8b01200000000007a2a10003c000000c8b01200000000002a7f12000b000000b62a100029000000857f12000d000000927f12000c000000c8b0120000000000df2a100056000000352b10004d000000822b100056000000d82b1000540000002c2c100014000000000000001f8212000500000000000000e60812000300000000000000fb8512000400000000000000500b120017000000c829100038000000c8b01200000000007881120034000000c8b01200000000002a7f12000b000000e90a120025000000927f12000c00000000000000dd0812000900000000000000e608120003000000000000007d2310001100000000000000e03c120011000000000000005a2710000f00000000000000692710002100000000000000fb8512000400000000000000500b120017000000b9231000560000000f2410003f000000c8b01200000000008a2710002d000000c8b01200000000004e24100054000000a224100058000000fa2410000e000000c8b01200000000007881120034000000c8b0120000000000c0201000560000001621100051000000672110001c00000008251000570000005f25100055000000b425100036000000b727100023000000c8b0120000000000da271000480000002228100047000000c8b01200000000006928100057000000c0281000560000001629100038000000c8b01200000000002a7f12000b0000004e2910001500000038221000340000006c22100050000000bc2210005200000063291000490000000e2310003000000038261000360000006e2610003f000000857f12000d000000ac2910001c000000ad2610004c000000f9261000240000001d2710003d000000927f12000c00000000000000dd0812000900000000000000e608120003000000000000007d2310001100000000000000e03c120011000000000000005a2710000f00000000000000692710002100000000000000b023100009000000000000001472120008000000b9231000560000000f2410003f000000c8b01200000000004e24100054000000a224100058000000fa2410000e000000c8b01200000000007881120034000000c8b0120000000000c0201000560000001621100051000000672110001c00000008251000570000005f25100055000000b425100036000000fa21100034000000c8b0120000000000ea2510004e000000c8b01200000000002a7f12000b0000002e2210000a00000038221000340000006c22100050000000bc221000520000000e2310003000000038261000360000006e2610003f000000857f12000d000000ad2610004c000000f9261000240000001d2710003d000000927f12000c00000000000000dd0812000900000000000000e608120003000000000000007d2310001100000000000000e03c120011000000000000008e2310000900000000000000972310001900000000000000b02310000900000000000000147212000800000038201000560000008e20100032000000c8b01200000000007881120034000000c8b0120000000000c0201000560000001621100051000000672110001c0000008321100058000000db2110001f000000fa21100034000000c8b01200000000002a7f12000b0000002e2210000a00000038221000340000006c22100050000000bc221000520000000e23100030000000857f12000d0000003e23100022000000602310001d000000927f12000c0000002043616e63656c2061207072652d6578697374696e672c206f6e2d676f696e67206d756c7469736967207472616e73616374696f6e2e20416e79206465706f7369742072657365727665642070726576696f75736c7920666f722074686973206f7065726174696f6e2077696c6c20626520756e7265736572766564206f6e20737563636573732e202d20607468726573686f6c64603a2054686520746f74616c206e756d626572206f6620617070726f76616c7320666f722074686973206469737061746368206265666f72652069742069732065786563757465642e202d20606f746865725f7369676e61746f72696573603a20546865206163636f756e747320286f74686572207468616e207468652073656e646572292077686f2063616e20617070726f766520746869732064697370617463682e204d6179206e6f7420626520656d7074792e202d206074696d65706f696e74603a205468652074696d65706f696e742028626c6f636b206e756d62657220616e64207472616e73616374696f6e20696e64657829206f662074686520666972737420617070726f76616c207472616e73616374696f6e20666f7220746869732064697370617463682e202d206063616c6c5f68617368603a205468652068617368206f66207468652063616c6c20746f2062652065786563757465642e202d20604f285329602e202d20557020746f206f6e652062616c616e63652d72657365727665206f7220756e72657365727665206f7065726174696f6e2e202d204f6e6520706173737468726f756768206f7065726174696f6e2c206f6e6520696e736572742c20626f746820604f285329602077686572652060536020697320746865206e756d626572206f662020207369676e61746f726965732e206053602069732063617070656420627920604d61785369676e61746f72696573602c207769746820776569676874206265696e672070726f706f7274696f6e616c2e202d204f6e6520656e636f6465202620686173682c20626f7468206f6620636f6d706c657869747920604f285329602e202d20492f4f3a2031207265616420604f285329602c206f6e652072656d6f76652e202d2053746f726167653a2072656d6f766573206f6e65206974656d2e6f746865725f7369676e61746f7269657374696d65706f696e7454696d65706f696e743c543a3a426c6f636b4e756d6265723e63616c6c5f6861736820526567697374657220617070726f76616c20666f72206120646973706174636820746f206265206d6164652066726f6d20612064657465726d696e697374696320636f6d706f73697465206163636f756e7420696620617070726f766564206279206120746f74616c206f6620607468726573686f6c64202d203160206f6620606f746865725f7369676e61746f72696573602e205061796d656e743a20604d756c74697369674465706f73697442617365602077696c6c20626520726573657276656420696620746869732069732074686520666972737420617070726f76616c2c20706c757320607468726573686f6c64602074696d657320604d756c74697369674465706f736974466163746f72602e2049742069732072657475726e6564206f6e636520746869732064697370617463682068617070656e73206f722069732063616e63656c6c65642e202d20606d617962655f74696d65706f696e74603a20496620746869732069732074686520666972737420617070726f76616c2c207468656e2074686973206d75737420626520604e6f6e65602e204966206974206973206e6f742074686520666972737420617070726f76616c2c207468656e206974206d7573742062652060536f6d65602c2077697468207468652074696d65706f696e742028626c6f636b206e756d62657220616e64207472616e73616374696f6e20696e64657829206f662074686520666972737420617070726f76616c207472616e73616374696f6e2e204e4f54453a2049662074686973206973207468652066696e616c20617070726f76616c2c20796f752077696c6c2077616e7420746f20757365206061735f6d756c74696020696e73746561642e202d20557020746f206f6e652062696e6172792073656172636820616e6420696e736572742028604f286c6f6753202b20532960292e202d20492f4f3a2031207265616420604f285329602c20757020746f2031206d757461746520604f285329602e20557020746f206f6e652072656d6f76652e202d2053746f726167653a20696e7365727473206f6e65206974656d2c2076616c75652073697a6520626f756e64656420627920604d61785369676e61746f72696573602c207769746820612020206465706f7369742074616b656e20666f7220697473206c69666574696d65206f66202020604d756c74697369674465706f73697442617365202b207468726573686f6c64202a204d756c74697369674465706f736974466163746f72602e6d617962655f74696d65706f696e744f7074696f6e3c54696d65706f696e743c543a3a426c6f636b4e756d6265723e3e2049662074686572652061726520656e6f7567682c207468656e206469737061746368207468652063616c6c2e202d206063616c6c603a205468652063616c6c20746f2062652065786563757465642e204e4f54453a20556e6c6573732074686973206973207468652066696e616c20617070726f76616c2c20796f752077696c6c2067656e6572616c6c792077616e7420746f207573652060617070726f76655f61735f6d756c74696020696e73746561642c2073696e6365206974206f6e6c7920726571756972657320612068617368206f66207468652063616c6c2e20526573756c74206973206571756976616c656e7420746f20746865206469737061746368656420726573756c7420696620607468726573686f6c64602069732065786163746c79206031602e204f7468657277697365206f6e20737563636573732c20726573756c7420697320604f6b6020616e642074686520726573756c742066726f6d2074686520696e746572696f722063616c6c2c206966206974207761732065786563757465642c206d617920626520666f756e6420696e20746865206465706f736974656420604d756c7469736967457865637574656460206576656e742e202d20604f2853202b205a202b2043616c6c29602e202d204f6e652063616c6c20656e636f6465202620686173682c20626f7468206f6620636f6d706c657869747920604f285a296020776865726520605a602069732074782d6c656e2e202d2054686520776569676874206f6620746865206063616c6c602e2053656e6420612063616c6c207468726f75676820616e20696e64657865642070736575646f6e796d206f66207468652073656e6465722e2053656e642061206261746368206f662064697370617463682063616c6c732e20546869732077696c6c206578656375746520756e74696c20746865206669727374206f6e65206661696c7320616e64207468656e2073746f702e204d61792062652063616c6c65642066726f6d20616e79206f726967696e2e202d206063616c6c73603a205468652063616c6c7320746f20626520646973706174636865642066726f6d207468652073616d65206f726967696e2e202d205468652073756d206f66207468652077656967687473206f6620746865206063616c6c73602e20546869732077696c6c2072657475726e20604f6b6020696e20616c6c2063697263756d7374616e6365732e20546f2064657465726d696e65207468652073756363657373206f66207468652062617463682c20616e206576656e74206973206465706f73697465642e20496620612063616c6c206661696c656420616e64207468652062617463682077617320696e7465727275707465642c207468656e2074686520604261746368496e74657272757074656460206576656e74206973206465706f73697465642c20616c6f6e67207769746820746865206e756d626572206f66207375636365737366756c2063616c6c73206d61646520616e6420746865206572726f72206f6620746865206661696c65642063616c6c2e20496620616c6c2077657265207375636365737366756c2c207468656e2074686520604261746368436f6d706c6574656460206576656e74206973206465706f73697465642e63616c6c735665633c3c542061732054726169743e3a3a43616c6c3e00000000b42c1000090000000205020000000000138212000c00000000000000147212000800000000000000bd2c10003400000000000000c8b01200f42c10000000000000000000042d10000100000000000000000000004d756c7469736967734d756c74697369673c543a3a426c6f636b4e756d6265722c2042616c616e63654f663c543e2c20543a3a4163636f756e7449643e0000003c0000000000000001000000510000000c2d1000250000002054686520736574206f66206f70656e206d756c7469736967206f7065726174696f6e732e557067726164696e67206163636f756e742062616c616e6365732e2e2e4672656542616c616e6365526573657276656442616c616e63654163636f756e744e6f6e6365000000006f1810000300000000000000a02d1000010000000000000000000000b82d10000900000000000000000000003a2f100003000000000000003d2f100012000000002e100016000000c8b0120000000000162e1000560000006c2e100036000000c8b0120000000000a22e100051000000f32e100011000000c8b0120000000000042f10003600000020536574207468652063757272656e742074696d652e20546869732063616c6c2073686f756c6420626520696e766f6b65642065786163746c79206f6e63652070657220626c6f636b2e2049742077696c6c2070616e6963206174207468652066696e616c697a6174696f6e2070686173652c20696620746869732063616c6c206861736e2774206265656e20696e766f6b656420627920746861742074696d652e205468652074696d657374616d702073686f756c642062652067726561746572207468616e207468652070726576696f7573206f6e652062792074686520616d6f756e742073706563696669656420627920604d696e696d756d506572696f64602e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d7573742062652060496e686572656e74602e6e6f77436f6d706163743c543a3a4d6f6d656e743e00000000006c181000030000000000000000000000297812000900000000000000000000000000000000000000000000000000000000000000c8b0120000301000000000000000000010301000010000000000000001000000000000005e91120009000000000000000000000000ee11000400000000000000000000000000000000000000000000000000000000000000c8b01200183010000000000000000000283010000100000000000000010000003c0000000000000001000000520000005d301000240000003c000000000000000100000051000000303010002d00000020446964207468652074696d657374616d7020676574207570646174656420696e207468697320626c6f636b3f2043757272656e742074696d6520666f72207468652063757272656e7420626c6f636b2e00000000000000bc3010000d00000000000000297812000900000000000000c8b01200cc3010000000000000000000dc30100004000000000000004d696e696d756d506572696f640000003c000000000000000100000053000000fc3010005a000000563110005a000000b031100059000000093210001c00000020546865206d696e696d756d20706572696f64206265747765656e20626c6f636b732e204265776172652074686174207468697320697320646966666572656e7420746f20746865202a65787065637465642a20706572696f6420746861742074686520626c6f636b2070726f64756374696f6e206170706172617475732070726f76696465732e20596f75722063686f73656e20636f6e73656e7375732073797374656d2077696c6c2067656e6572616c6c7920776f726b2077697468207468697320746f2064657465726d696e6520612073656e7369626c6520626c6f636b2074696d652e20652e672e20466f7220417572612c2069742077696c6c20626520646f75626c65207468697320706572696f64206f6e2064656661756c742073657474696e67732e6d6f646c70792f7574696c697375626154696d657374616d70206d7573742062652075706461746564206f6e6c79206f6e636520696e2074686520626c6f636b54696d657374616d70206d75737420696e6372656d656e74206279206174206c65617374203c4d696e696d756d506572696f643e206265747765656e2073657175656e7469616c20626c6f636b730000000000aae611000d0000000000000004341000010000000000000000000000af1310000f000000000000000c3410000100000000000000000000009e1310001100000000000000143410000100000000000000000000008d13100011000000000000001c3410000100000000000000000000007b1310001200000000000000243410000100000000000000000000006613100015000000000000002c34100001000000000000000000000053131000130000000000000034341000010000000000000000000000843a100008000000000000003c341000010000000000000000000000886c1200080000000000000044341000010000000000000000000000481310000b000000000000004c3410000100000000000000000000003a1310000e00000000000000543410000100000000000000000000002713100013000000000000005c3410000100000000000000ed3610001d000000c13610002c00000099361000280000006e3610002b000000423610002c000000fe35100044000000ba351000440000008235100038000000363510004c000000ee34100048000000a23410004c000000643410003e00000020412074696d65706f696e742077617320676976656e2c20796574206e6f206d756c7469736967206f7065726174696f6e20697320756e6465727761792e204120646966666572656e742074696d65706f696e742077617320676976656e20746f20746865206d756c7469736967206f7065726174696f6e207468617420697320756e6465727761792e204e6f2074696d65706f696e742077617320676976656e2c2079657420746865206d756c7469736967206f7065726174696f6e20697320616c726561647920756e6465727761792e204f6e6c7920746865206163636f756e742074686174206f726967696e616c6c79206372656174656420746865206d756c74697369672069732061626c6520746f2063616e63656c2069742e204d756c7469736967206f7065726174696f6e206e6f7420666f756e64207768656e20617474656d7074696e6720746f2063616e63656c2e205468652073656e6465722077617320636f6e7461696e656420696e20746865206f74686572207369676e61746f726965733b2069742073686f756c646e27742062652e20546865207369676e61746f7269657320776572652070726f7669646564206f7574206f66206f726465723b20746865792073686f756c64206265206f7264657265642e2054686572652061726520746f6f206d616e79207369676e61746f7269657320696e20746865206c6973742e2054686572652061726520746f6f20666577207369676e61746f7269657320696e20746865206c6973742e2043616c6c20646f65736e2774206e65656420616e7920286d6f72652920617070726f76616c732e2043616c6c20697320616c726561647920617070726f7665642062792074686973207369676e61746f72792e205468726573686f6c6420697320746f6f206c6f7720287a65726f292e4765747320616e64206465636f6465732074696d657374616d7020696e686572656e7420646174610000540000001000000004000000550000005437100045000000cc0000001f0000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f6672616d652f74696d657374616d702f7372632f6c69622e7273496e686572656e7420776974682073616d65206964656e74696669657220616c726561647920657869737473214e6f206f74686572206572726f72732061726520616363657074656420616674657220616e2068617264206572726f72215468657265206973206f6e6c79206f6e6520666174616c206572726f723b207165640000003c0000000800000004000000560000005821120046000000670200000100000054696d657374616d7020746f6f2066617220696e2066757475726520746f20616363657074416d6f756e744c6f774e6f7456657374696e6776657374766573745f6f746865727665737465645f7472616e7366657200000000000000ec3810000e000000000000004c261200020000000000000000000000fc3810000200000000000000000000000c39100010000000000000005ce811000100000000000000000000001c391000010000000000000056657374696e675570646174656400006f39100056000000c53910004600000056657374696e67436f6d706c65746564243910004b00000020416e206163636f756e742028676976656e2920686173206265636f6d652066756c6c79207665737465642e204e6f20667572746865722076657374696e672063616e2068617070656e2e2054686520616d6f756e742076657374656420686173206265656e20757064617465642e205468697320636f756c6420696e646963617465206d6f72652066756e64732061726520617661696c61626c652e205468652062616c616e636520676976656e2069732074686520616d6f756e74207768696368206973206c65667420756e7665737465642028616e642074687573206c6f636b6564292e546f6f4d616e794669656c6473496e76616c6964546172676574496e76616c6964496e646578496e76616c69644a756467656d656e744a756467656d656e74476976656e537469636b794a756467656d656e744e6f4964656e746974794665654368616e676564456d707479496e6465784e6f744e616d65644e6f74466f756e64546f6f4d616e795375624163636f756e74736164645f7265676973747261727365745f6964656e746974797365745f73756273636c6561725f6964656e74697479726571756573745f6a756467656d656e7463616e63656c5f726571756573747365745f6665657365745f6163636f756e745f69647365745f6669656c647370726f766964655f6a756467656d656e746b696c6c5f6964656e7469747953757065724f6600000000643c10000b000000000000005ce81100010000000000000000000000703c1000010000000000000000000000783c10000f000000000000004c261200020000000000000000000000883c1000010000000000000000000000903c10000e000000000000004c261200020000000000000000000000a03c1000010000000000000000000000a83c10001200000000000000bc3c1000020000000000000000000000cc3c1000010000000000000000000000d43c10001400000000000000bc3c1000020000000000000000000000e83c1000010000000000000000000000413a10000e00000000000000bc3c1000020000000000000000000000f03c1000010000000000000000000000f83c10000e00000000000000083d1000010000000000000000000000103d100001000000000000004964656e7469747953657400143e10003c0000004964656e74697479436c656172656400e03d1000340000004964656e746974794b696c6c65640000ae3d1000320000004a756467656d656e745265717565737465640000c26d1200090000002f3d10000e000000863d1000280000004a756467656d656e74556e726571756573746564633d1000230000003d3d100026000000526567697374726172416464656400002f3d10000e000000183d100017000000204120726567697374726172207761732061646465642e526567697374726172496e6465782041206a756467656d656e742077617320676976656e2062792061207265676973747261722e2041206a756467656d656e74207265717565737420776173207265747261637465642e2041206a756467656d656e74207761732061736b65642066726f6d2061207265676973747261722e2041206e616d65207761732072656d6f76656420616e642074686520676976656e2062616c616e636520736c61736865642e2041206e616d652077617320636c65617265642c20616e642074686520676976656e2062616c616e63652072657475726e65642e2041206e616d652077617320736574206f72207265736574202877686963682077696c6c2072656d6f766520616c6c206a756467656d656e7473292e456e636f756e7465726564206572726f7220696e206d6967726174696f6e206f66205374616b696e673a3a4c6564676572206d61702e546865206e756d626572206f662072656d6f766564206b65792f76616c75652069733a00000000000000743810000400000000000000c8b01200000000000000000000000000303f10000d0000000000000000000000783810000a0000000000000054cf1100010000000000000000000000983f1000100000000000000000000000823810000f0000000000000018401000020000000000000000000000484010000e000000000000007f4310002f000000c8b0120000000000ae43100058000000bd4210001a000000c8b0120000000000d742100035000000c8b01200000000002a7f12000b000000357f12000a000000284310001e0000004643100039000000857f12000d000000927f12000c000000394210002f000000c8b01200000000007881120034000000c8b01200000000006842100055000000bd4210001a000000c8b0120000000000d742100035000000c8b01200000000002a7f12000b000000357f12000a0000000c4310001c000000284310001e0000004643100039000000857f12000d000000927f12000c00000000000000ffd711000600000000000000203f12002300000000000000a477100008000000000000001042100029000000b84010001b000000c8b01200000000007881120034000000c8b0120000000000d3401000450000001841100040000000584110003d000000c8b01200000000009541100018000000c8b01200000000002a7f12000b000000ad41100046000000f34110001d000000927f12000c00000020437265617465206120766573746564207472616e736665722e20202d2060746172676574603a20546865206163636f756e7420746861742073686f756c64206265207472616e7366657272656420746865207665737465642066756e64732e202d2060616d6f756e74603a2054686520616d6f756e74206f662066756e647320746f207472616e7366657220616e642077696c6c206265207665737465642e202d20607363686564756c65603a205468652076657374696e67207363686564756c6520617474616368656420746f20746865207472616e736665722e20456d697473206056657374696e6743726561746564602e202d20437265617465732061206e65772073746f7261676520656e7472792c206275742069732070726f7465637465642062792061206d696e696d756d207472616e7366657209202020616d6f756e74206e656564656420746f20737563636565642e56657374696e67496e666f3c42616c616e63654f663c543e2c20543a3a426c6f636b4e756d6265723e20556e6c6f636b20616e79207665737465642066756e6473206f662061206074617267657460206163636f756e742e202d2060746172676574603a20546865206163636f756e742077686f7365207665737465642066756e64732073686f756c6420626520756e6c6f636b65642e204d75737420686176652066756e6473207374696c6c206c6f636b656420756e6465722074686973206d6f64756c652e20456d69747320656974686572206056657374696e67436f6d706c6574656460206f72206056657374696e6755706461746564602e202d20557020746f206f6e65206163636f756e74206c6f6f6b75702e202d204f6e652062616c616e63652d6c6f636b206f7065726174696f6e2e202d204f6e652073746f7261676520726561642028636f64656320604f283129602920616e6420757020746f206f6e652072656d6f76616c2e20556e6c6f636b20616e79207665737465642066756e6473206f66207468652073656e646572206163636f756e742e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e64207468652073656e646572206d75737420686176652066756e6473207374696c6c000000000000ade21000070000000101000000000000138212000c00000000000000104210002900000000000000000000000000000000000000c8b01200604410000000000000000000704410000100000000000000000000003c000000000000000100000051000000784410003600000020496e666f726d6174696f6e20726567617264696e67207468652076657374696e67206f66206120676976656e206163636f756e742e000000000000e84410001100000000000000845712000c00000000000000c8b01200fc44100000000000000000000c45100001000000000000004d696e5665737465645472616e736665720000003c000000000000000100000057000000144510004700000020546865206d696e696d756d20616d6f756e7420746f206265207472616e7366657272656420746f206372656174652061206e65772076657374696e67207363686564756c652e00000000009e3a10000d0000000000000068f31100010000000000000000000000404710000d0000000000000000000000ab3a10000c00000000000000a8471000010000000000000000000000c0471000120000000000000000000000b73a100008000000000000005048100001000000000000000000000068481000100000000000000000000000bf3a10000e00000000000000c8b01200000000000000000000000000e84810000f0000000000000000000000cd3a100011000000000000006049100002000000000000000000000090491000170000000000000000000000de3a10000e00000000000000484a1000010000000000000000000000604a1000110000000000000000000000ec3a10000700000000000000e84a1000020000000000000000000000184b10000c0000000000000000000000f33a10000e00000000000000784b1000020000000000000000000000a84b10000c0000000000000000000000013b10000a00000000000000084c1000020000000000000000000000384c10000c00000000000000000000000b3b10001100000000000000984c1000030000000000000000000000e04c10001300000000000000000000001c3b10000d0000000000000054cf1100010000000000000000000000784d10001300000000000000175c10001f000000c8b0120000000000365c100047000000c8b01200000000007d5c10002b000000c8b0120000000000a85c100026000000c8b01200000000002a7f12000b000000ce5c100039000000af7d110027000000857f12000d000000927f12000c00000000000000075c100004000000000000000b5c10000c0000006a5a10004b000000c8b0120000000000b55a1000560000000b5b100015000000c8b0120000000000f6571000590000004f5810000a000000c8b0120000000000205b100024000000c8b0120000000000445b100023000000c8b01200000000002a7f12000b000000675b100057000000c559100022000000be5b100049000000857f12000d000000927f12000c000000000000004d5a10000400000000000000515a1000190000009d58100024000000c8b0120000000000c158100056000000175910004c000000c8b0120000000000f6571000590000004f5810000a000000c8b01200000000006359100027000000c8b01200000000002a7f12000b0000008a5910003b000000c559100022000000e759100050000000375a100016000000927f12000c0000006c5710004e000000c8b0120000000000ba5710003c000000c8b0120000000000f6571000590000004f5810000a000000c8b01200000000005958100027000000c8b01200000000002a7f12000b00000013501000120000002550100021000000805810001d000000857f12000d000000927f12000c000000000000005c52100009000000000000006552100017000000000000006557100007000000000000008147120015000000b155100026000000c8b0120000000000d7551000560000002d56100007000000c8b0120000000000ad5410004e000000fb54100015000000c8b012000000000034561000480000007c56100056000000c8b0120000000000d25610000d000000df561000290000000857100004000000c8b01200000000000c5710002a000000c8b01200000000002a7f12000b000000d75110000e0000002550100021000000365710002f000000857f12000d000000927f12000c000000000000005c52100009000000000000002f3d10000e000000535410001b000000c8b01200000000006e5410003f000000c8b0120000000000ad5410004e000000fb54100015000000c8b01200000000001055100052000000c8b0120000000000625510002c000000c8b01200000000002a7f12000b000000d75110000e00000025501000210000008e55100023000000857f12000d000000927f12000c000000000000001f82120005000000000000006552100017000000000000005054100003000000000000008147120015000000f353100047000000c8b01200000000009250100056000000be52100029000000c8b0120000000000e75210003e0000003a54100016000000c8b01200000000002a7f12000b000000695310000a000000735310001f000000927f12000c000000000000001f8212000500000000000000655210001700000000000000108212000300000000000000138212000c000000a653100030000000c8b01200000000009250100056000000be52100029000000c8b0120000000000e75210003e000000d65310001d000000c8b01200000000002a7f12000b000000695310000a000000735310001f000000927f12000c000000000000001f8212000500000000000000655210001700000000000000925310000600000000000000985310000e000000935210002b000000c8b01200000000009250100056000000be52100029000000c8b0120000000000e75210003e0000002553100044000000c8b01200000000002a7f12000b000000695310000a000000735310001f000000927f12000c000000000000005c5210000900000000000000655210001700000000000000ffd711000600000000000000203f120023000000000000000e46110009000000000000007c52100017000000635010002f000000c8b01200000000009250100056000000e85010002d000000c8b01200000000001551100049000000794f100056000000cf4f10001e0000005e51100053000000c8b0120000000000b151100026000000c8b01200000000002a7f12000b000000d75110000e000000e55110002200000007521000260000002d5210002f000000857f12000d000000927f12000c000000104e100051000000c8b0120000000000614e100059000000ba4e1000520000000c4f100021000000c8b01200000000002d4f10004c000000c8b0120000000000794f100056000000cf4f10001e000000c8b0120000000000ed4f100026000000c8b01200000000002a7f12000b00000013501000120000002550100021000000465010001d000000857f12000d000000927f12000c0000002052656d6f766520616e206163636f756e742773206964656e7469747920616e64207375622d6163636f756e7420696e666f726d6174696f6e20616e6420736c61736820746865206465706f736974732e205061796d656e743a2052657365727665642062616c616e6365732066726f6d20607365745f737562736020616e6420607365745f6964656e74697479602061726520736c617368656420616e642068616e646c65642062792060536c617368602e20566572696669636174696f6e2072657175657374206465706f7369747320617265206e6f742072657475726e65643b20746865792073686f756c642062652063616e63656c6c6564206d616e75616c6c79207573696e67206063616e63656c5f72657175657374602e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f526f6f745f206f72206d617463682060543a3a466f7263654f726967696e602e202d2060746172676574603a20746865206163636f756e742077686f7365206964656e7469747920746865206a756467656d656e742069732075706f6e2e2054686973206d75737420626520616e206163636f756e742020207769746820612072656769737465726564206964656e746974792e20456d69747320604964656e746974794b696c6c656460206966207375636365737366756c2e202d20604f2852202b2053202b205829602e202d204f6e652062616c616e63652d72657365727665206f7065726174696f6e2e202d206053202b2032602073746f72616765206d75746174696f6e732e2050726f766964652061206a756467656d656e7420666f7220616e206163636f756e742773206964656e746974792e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e64207468652073656e646572206d75737420626520746865206163636f756e74206f6620746865207265676973747261722077686f736520696e64657820697320607265675f696e646578602e202d20607265675f696e646578603a2074686520696e646578206f6620746865207265676973747261722077686f7365206a756467656d656e74206973206265696e67206d6164652e202d20606a756467656d656e74603a20746865206a756467656d656e74206f662074686520726567697374726172206f6620696e64657820607265675f696e646578602061626f75742060746172676574602e20456d69747320604a756467656d656e74476976656e60206966207375636365737366756c2e202d20604f2852202b205829602e202d204f6e652062616c616e63652d7472616e73666572206f7065726174696f6e2e202d20557020746f206f6e65206163636f756e742d6c6f6f6b7570206f7065726174696f6e2e202d2053746f726167653a2031207265616420604f285229602c2031206d757461746520604f2852202b205829602e7265675f696e646578436f6d706163743c526567697374726172496e6465783e4a756467656d656e743c42616c616e63654f663c543e3e2053657420746865206669656c6420696e666f726d6174696f6e20666f722061207265676973747261722e206f6620746865207265676973747261722077686f736520696e6465782069732060696e646578602e202d2060696e646578603a2074686520696e646578206f6620746865207265676973747261722077686f73652066656520697320746f206265207365742e202d20606669656c6473603a20746865206669656c64732074686174207468652072656769737472617220636f6e6365726e73207468656d73656c76657320776974682e202d20604f285229602e202d204f6e652073746f72616765206d75746174696f6e20604f285229602e6669656c64734964656e746974794669656c6473204368616e676520746865206163636f756e74206173736f63696174656420776974682061207265676973747261722e202d20606e6577603a20746865206e6577206163636f756e742049442e20536574207468652066656520726571756972656420666f722061206a756467656d656e7420746f206265207265717565737465642066726f6d2061207265676973747261722e202d2060666565603a20746865206e6577206665652e6665652043616e63656c20612070726576696f757320726571756573742e205061796d656e743a20412070726576696f75736c79207265736572766564206465706f7369742069732072657475726e6564206f6e20737563636573732e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e64207468652073656e646572206d757374206861766520612072656769737465726564206964656e746974792e202d20607265675f696e646578603a2054686520696e646578206f6620746865207265676973747261722077686f7365206a756467656d656e74206973206e6f206c6f6e676572207265717565737465642e20456d69747320604a756467656d656e74556e72657175657374656460206966207375636365737366756c2e202d204f6e652073746f72616765206d75746174696f6e20604f2852202b205829602e20526571756573742061206a756467656d656e742066726f6d2061207265676973747261722e205061796d656e743a204174206d6f737420606d61785f666565602077696c6c20626520726573657276656420666f72207061796d656e7420746f2074686520726567697374726172206966206a756467656d656e7420676976656e2e202d20607265675f696e646578603a2054686520696e646578206f6620746865207265676973747261722077686f7365206a756467656d656e74206973207265717565737465642e202d20606d61785f666565603a20546865206d6178696d756d206665652074686174206d617920626520706169642e20546869732073686f756c64206a757374206265206175746f2d706f70756c617465642061733a206060606e6f636f6d70696c652053656c663a3a72656769737472617273287265675f696e646578292e756e7772617028292e6665652060606020456d69747320604a756467656d656e7452657175657374656460206966207375636365737366756c2e202d2053746f726167653a2031207265616420604f285229602c2031206d757461746520604f2858202b205229602e6d61785f66656520436c65617220616e206163636f756e742773206964656e7469747920696e666f20616e6420616c6c207375622d6163636f756e7420616e642072657475726e20616c6c206465706f736974732e205061796d656e743a20416c6c2072657365727665642062616c616e636573206f6e20746865206163636f756e74206172652072657475726e65642e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e64207468652073656e646572206d757374206861766520612072656769737465726564206964656e746974792e20456d69747320604964656e74697479436c656172656460206966207375636365737366756c2e202d206053202b2032602073746f726167652064656c6574696f6e732e2053657420746865207375622d6163636f756e7473206f66207468652073656e6465722e205061796d656e743a20416e79206167677265676174652062616c616e63652072657365727665642062792070726576696f757320607365745f73756273602063616c6c732077696c6c2062652072657475726e656420616e6420616e20616d6f756e7420605375624163636f756e744465706f736974602077696c6c20626520726573657276656420666f722065616368206974656d20696e206073756273602e202d206073756273603a20546865206964656e746974792773207375622d6163636f756e74732e202d20604f285329602077686572652060536020737562732d636f756e742028686172642d20616e64206465706f7369742d626f756e646564292e202d204174206d6f73742074776f2062616c616e6365206f7065726174696f6e732e202d204174206d6f7374204f2832202a2053202b2031292073746f72616765206d75746174696f6e733b20636f64656320636f6d706c657869747920604f2831202a2053202b2053202a20312960293b2020206f6e652073746f726167652d6578697374732e737562735665633c28543a3a4163636f756e7449642c2044617461293e2053657420616e206163636f756e742773206964656e7469747920696e666f726d6174696f6e20616e6420726573657276652074686520617070726f707269617465206465706f7369742e20496620746865206163636f756e7420616c726561647920686173206964656e7469747920696e666f726d6174696f6e2c20746865206465706f7369742069732074616b656e2061732070617274207061796d656e7420666f7220746865206e6577206465706f7369742e202d2060696e666f603a20546865206964656e7469747920696e666f726d6174696f6e2e20456d69747320604964656e7469747953657460206966207375636365737366756c2e202d20604f2858202b205827202b2052296020776865726520605860206164646974696f6e616c2d6669656c642d636f756e7420286465706f7369742d626f756e64656420616e6420636f64652d626f756e646564292e202d204f6e652073746f72616765206d75746174696f6e2028636f6465632d7265616420604f285827202b205229602c20636f6465632d777269746520604f2858202b20522960292e696e666f4964656e74697479496e666f2041646420612072656769737472617220746f207468652073797374656d2e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d75737420626520605265676973747261724f726967696e60206f722060526f6f74602e202d20606163636f756e74603a20746865206163636f756e74206f6620746865207265676973747261722e20456d6974732060526567697374726172416464656460206966207375636365737366756c2e202d20604f2852296020776865726520605260207265676973747261722d636f756e742028676f7665726e616e63652d626f756e646564292e0000000000685e10000a0000000101000000000000138212000c00000000000000725e10001a00000000000000000000000000000000000000c8b012008c5e100000000000000000009c5e100001000000000000000000000000000000293b1000070000000101000000000000138212000c00000000000000a45e10001400000000000000000000000000000000000000c8b01200b85e10000000000000000000c85e100002000000000000000000000000000000d85e1000060000000101000000000000138212000c0000000000000008be10002100000000000000000000000000000000000000c8b01200e05e10000000000000000000f05e100003000000000000000100000000000000085f10000a0000000000000000000000125f10003600000000000000000000000000000000000000000000000000000000000000c8b01200485f10000000000000000000585f10000400000000000000010000004964656e746974794f66526567697374726174696f6e3c42616c616e63654f663c543e3e3c000000000000000100000051000000606110004800000028543a3a4163636f756e7449642c2044617461293c000000000000000100000051000000b4601000580000000c61100054000000537562734f6600003c0000000000000001000000580000003f6010002e000000c8b01200000000006d60100047000000526567697374726172735665633c4f7074696f6e3c526567697374726172496e666f3c42616c616e63654f663c543e2c20543a3a4163636f756e7449643e3e3e3c000000000000000100000059000000785f100053000000cb5f10002a000000c8b0120000000000f55f10004a0000002054686520736574206f6620726567697374726172732e204e6f7420657870656374656420746f206765742076657279206269672061732063616e206f6e6c79206265206164646564207468726f7567682061207370656369616c206f726967696e20286c696b656c79206120636f756e63696c206d6f74696f6e292e2054686520696e64657820696e746f20746869732063616e206265206361737420746f2060526567697374726172496e6465786020746f2067657420612076616c69642076616c75652e20416c7465726e6174697665202273756222206964656e746974696573206f662074686973206163636f756e742e20546865206669727374206974656d20697320746865206465706f7369742c20746865207365636f6e64206973206120766563746f72206f6620746865206163636f756e74732e205468652073757065722d6964656e74697479206f6620616e20616c7465726e6174697665202273756222206964656e7469747920746f676574686572207769746820697473206e616d652c2077697468696e207468617420636f6e746578742e20496620746865206163636f756e74206973206e6f7420736f6d65206f74686572206163636f756e742773207375622d6964656e746974792c207468656e206a75737420604e6f6e65602e20496e666f726d6174696f6e20746861742069732070657274696e656e7420746f206964656e746966792074686520656e7469747920626568696e6420616e206163636f756e742e7573657220646f6573206e6f74206861766520616e206578697374696e672076657374696e67207363686564756c653b20712e652e642e003c0000000c000000040000005a0000000062100043000000f80000000d0000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f6672616d652f76657374696e672f7372632f6c69622e7273657865632e7072656661625f6d6f64756c652e696e697469616c2063616e27742062652067726561746572207468616e20657865632e7072656661625f6d6f64756c652e6d6178696d756d3b0a09090909090974687573204d656d6f72793a3a6e6577206d757374206e6f74206661696c3b0a09090909090971656400000000006a3810000a0000000000000014631000010000000000000000000000669a110017000000000000001c631000010000000000000000000000613810000900000000000000246310000100000000000000c5631000220000006e631000570000002c6310004200000020416d6f756e74206265696e67207472616e7366657272656420697320746f6f206c6f7720746f2063726561746520612076657374696e67207363686564756c652e20416e206578697374696e672076657374696e67207363686564756c6520616c72656164792065786973747320666f722074686973206163636f756e7420746861742063616e6e6f7420626520636c6f6262657265642e20546865206163636f756e7420676976656e206973206e6f742076657374696e672e00000000008c3a1000120000000000000038651000010000000000000000000000843a10000800000000000000406510000100000000000000000000007c3a1000080000000000000048651000010000000000000000000000723a10000a0000000000000050651000010000000000000000000000683a10000a00000000000000586510000100000000000000000000005e3a10000a00000000000000606510000100000000000000000000004f3a10000f0000000000000068651000010000000000000000000000413a10000e0000000000000070651000010000000000000000000000313a1000100000000000000078651000010000000000000000000000253a10000c0000000000000080651000010000000000000000000000183a10000d00000000000000886510000100000000000000000000000b3a10000d0000000000000090651000010000000000000071661000180000005c6610001500000047661000150000003a6610000d0000002a6610001000000017661000130000000566100012000000f465100011000000e165100013000000cb65100016000000b465100017000000986510001c00000020546f6f206d616e79206164646974696f6e616c206669656c64732e205468652074617267657420697320696e76616c69642e2054686520696e64657820697320696e76616c69642e20496e76616c6964206a756467656d656e742e204a756467656d656e7420676976656e2e20537469636b79206a756467656d656e742e204e6f206964656e7469747920666f756e642e20466565206973206368616e6765642e20456d70747920696e6465782e204163636f756e742069736e2774206e616d65642e204163636f756e742069736e277420666f756e642e20546f6f206d616e7920737562732d6163636f756e74732e436865636b426c6f636b4761734c696d6974496e76616c6964436f6e74726163744f726967696e496e76616c6964546f6d6273746f6e65496e76616c696444657374696e6174696f6e436f6e7472616374496e76616c6964536f75726365436f6e7472616374496e76616c6964537572636861726765436c61696d496e76616c69645363686564756c6556657273696f6e7570646174655f7363686564756c657075745f636f6465696e7374616e7469617465636c61696d5f737572636861726765436f6e7472616374496e666f4f66476173507269636500000000000000049c110008000000000000000c9c1100030000000000000000000000c4681000010000000000000000000000cc6810000c0000000000000080e81100020000000000000000000000d8681000010000000000000000000000e068100007000000000000005c1f1100020000000000000000000000e86810000600000000000000000000001869100008000000000000002069100005000000000000000000000048691000090000000000000000000000906910000a00000000000000b0ec11000100000000000000000000009c691000010000000000000000000000a46910000f00000000000000ec1f1100010000000000000000000000b4691000010000000000000000000000bc6910000a000000000000005c1f1100020000000000000000000000c8691000020000000000000000000000d86910001100000000000000ec691000020000000000000000000000fc69100001000000000000007b6d10005a000000496e7374616e746961746564446d10003700000045766963746564007b6c100039000000c8b01200000000003e6b100009000000c8b0120000000000b46c100043000000f76c10004d000000526573746f726564c26d120009000000c26d12000900000065ed110004000000902712000700000000ee1100040000000f6b10002f000000c8b01200000000003e6b100009000000c8b0120000000000476b10003d000000846b10003b000000bf6b10003a000000f96b1000460000003f6c10003c000000436f646553746f7265640000e16a10002e0000005363686564756c655570646174656400b16a100030000000446973706174636865640000466a10004e000000946a10001d000000436f6e7472616374457865637574696f6e000000c26d12000900000070a3110007000000046a10004200000020416e206576656e74206465706f73697465642075706f6e20657865637574696f6e206f66206120636f6e74726163742066726f6d20746865206163636f756e742e20412063616c6c2077617320646973706174636865642066726f6d2074686520676976656e206163636f756e742e2054686520626f6f6c207369676e616c73207768657468657220697420776173207375636365737366756c20657865637574696f6e206f72206e6f742e20547269676765726564207768656e207468652063757272656e74207363686564756c6520697320757064617465642e20436f646520776974682074686520737065636966696564206861736820686173206265656e2073746f7265642e20526573746f726174696f6e20666f72206120636f6e747261637420686173206265656e20696e697469617465642e202320506172616d73202d2060646f6e6f72603a20604163636f756e744964603a204163636f756e74204944206f662074686520726573746f72696e6720636f6e7472616374202d206064657374603a20604163636f756e744964603a204163636f756e74204944206f662074686520726573746f72656420636f6e7472616374202d2060636f64655f68617368603a206048617368603a20436f64652068617368206f662074686520726573746f72656420636f6e7472616374202d206072656e745f616c6c6f77616e63653a206042616c616e6365603a2052656e7420616c6c6f77616e6365206f662074686520726573746f72656420636f6e7472616374202d206073756363657373603a2060626f6f6c603a20547275652069662074686520726573746f726174696f6e20776173207375636365737366756c20436f6e747261637420686173206265656e206576696374656420616e64206973206e6f7720696e20746f6d6273746f6e652073746174652e202d2060636f6e7472616374603a20604163636f756e744964603a20546865206163636f756e74204944206f6620746865206576696374656420636f6e74726163742e202d2060746f6d6273746f6e65603a2060626f6f6c603a205472756520696620746865206576696374656420636f6e7472616374206c65667420626568696e64206120746f6d6273746f6e652e20436f6e7472616374206465706c6f7965642062792061646472657373206174207468652073706563696669656420616464726573732e205472616e736665722068617070656e6564206066726f6d6020746f2060746f60207769746820676976656e206076616c7565602061732070617274206f662061206063616c6c60206f722060696e7374616e7469617465602e0000003c000000040000000400000048000000490000005b0000003c000000000000000100000040000000086e10001c00000056617269616e74206973206e6576657220636f6e737472756374656473657269616c697a656420617267732073686f756c642062652070726f7669646564206279207468652072756e74696d653b0a090909636f72726563746c792073657269616c697a656420646174612073686f756c6420626520646573657269616c697a61626c653b0a09090971656410a8120053000000ba0000001000000064656661756c743a000000001a6710000f00000000000000886f1000010000000000000000000000a06f1000030000000000000000000000296710000800000000000000b86f1000020000000000000000000000e86f1000020000000000000000000000fb8512000400000000000000f86f100004000000000000000000000058701000070000000000000000000000316710000b0000000000000090701000040000000000000000000000f07010000a00000000000000000000003c6710000f000000000000004071100002000000000000000000000070711000050000000000000000000000a47710000800000000000000ac77100008000000347710002d000000c8b0120000000000617710004300000000000000e67410000900000000000000ef7410000c0000000000000077fa1000040000000000000070a3110007000000a876100057000000ff76100035000000000000001dad11000400000000000000203f120023000000000000007c4712000500000000000000814712001500000000000000e67410000900000000000000ef7410000c000000000000000f751000040000000000000070a31100070000001375100042000000c8b0120000000000557510004a0000009f7510002c000000cb751000460000001176100052000000637610004500000000000000dd7410000900000000000000814712001500000000000000e67410000900000000000000ef7410000c00000000000000fb7410000900000000000000047510000b000000000000000f751000040000000000000070a3110007000000bc7210006f000000c8b01200000000002b73100026000000c8b01200000000005173100050000000a173100041000000e27310005b0000003d74100057000000947410002a000000be7410001f000000000000001dad11000400000000000000138212000c00000000000000b27210000a00000000000000c815120014000000987110005c000000f471100045000000c8b0120000000000397210004e000000877210002b00000020416c6c6f777320626c6f636b2070726f64756365727320746f20636c61696d206120736d616c6c2072657761726420666f72206576696374696e67206120636f6e74726163742e204966206120626c6f636b2070726f6475636572206661696c7320746f20646f20736f2c206120726567756c61722075736572732077696c6c20626520616c6c6f77656420746f20636c61696d20746865207265776172642e20496620636f6e7472616374206973206e6f742065766963746564206173206120726573756c74206f6620746869732063616c6c2c206e6f20616374696f6e73206172652074616b656e20616e64207468652073656e646572206973206e6f7420656c696769626c6520666f7220746865207265776172642e6175785f73656e64657220496e7374616e7469617465732061206e657720636f6e74726163742066726f6d207468652060636f646568617368602067656e65726174656420627920607075745f636f6465602c206f7074696f6e616c6c79207472616e7366657272696e6720736f6d652062616c616e63652e20496e7374616e74696174696f6e20697320657865637574656420617320666f6c6c6f77733a202d205468652064657374696e6174696f6e206164647265737320697320636f6d7075746564206261736564206f6e207468652073656e64657220616e642068617368206f662074686520636f64652e202d2054686520736d6172742d636f6e7472616374206163636f756e7420697320637265617465642061742074686520636f6d707574656420616464726573732e202d20546865206063746f725f636f64656020697320657865637574656420696e2074686520636f6e74657874206f6620746865206e65776c792d63726561746564206163636f756e742e204275666665722072657475726e656420202061667465722074686520657865637574696f6e206973207361766564206173207468652060636f646560206f6620746865206163636f756e742e205468617420636f64652077696c6c20626520696e766f6b656420202075706f6e20616e792063616c6c2072656365697665642062792074686973206163636f756e742e202d2054686520636f6e747261637420697320696e697469616c697a65642e656e646f776d656e746761735f6c696d6974436f6d706163743c4761733e636f64655f68617368436f6465486173683c543e64617461204d616b657320612063616c6c20746f20616e206163636f756e742c206f7074696f6e616c6c79207472616e7366657272696e6720736f6d652062616c616e63652e202a20496620746865206163636f756e74206973206120736d6172742d636f6e7472616374206163636f756e742c20746865206173736f63696174656420636f64652077696c6c20626520657865637574656420616e6420616e792076616c75652077696c6c206265207472616e736665727265642e202a20496620746865206163636f756e74206973206120726567756c6172206163636f756e742c20616e792076616c75652077696c6c206265207472616e736665727265642e202a204966206e6f206163636f756e742065786973747320616e64207468652063616c6c2076616c7565206973206e6f74206c657373207468616e20606578697374656e7469616c5f6465706f736974602c206120726567756c6172206163636f756e742077696c6c206265206372656174656420616e6420616e792076616c75652077696c6c206265207472616e736665727265642e2053746f7265732074686520676976656e2062696e617279205761736d20636f646520696e746f2074686520636861696e27732073746f7261676520616e642072657475726e73206974732060636f646568617368602e20596f752063616e20696e7374616e746961746520636f6e747261637473206f6e6c7920776974682073746f72656420636f64652e205570646174657320746865207363686564756c6520666f72206d65746572696e6720636f6e7472616374732e20546865207363686564756c65206d7573742068617665206120677265617465722076657273696f6e207468616e207468652073746f726564207363686564756c652e7363686564756c655363686564756c6500000000b28b12000800000000000000000000001c7a10000300000000000000000000000000000000000000000000000000000000000000c8b01200907a10000000000000000000207a100001000000000000000100000000000000ba8b12000f0000000000000000000000ac7710000800000000000000000000000000000000000000000000000000000000000000c8b01200287a10000000000000000000387a100001000000000000000100000000000000407a10000c0000000101000000000000047510000b0000000000000070a311000700000000000000000000000000000000000000c8b012004c7a100000000000000000005c7a100001000000000000000000000000000000647a10000b0000000101000000000000047510000b000000000000006f7a10001600000000000000000000000000000000000000c8b01200b87a10000000000000000000887a100001000000000000000000000000000000c98b12000e0000000000000000000000a07112000300000000000000000000000000000000000000000000000000000000000000c8b01200907a10000000000000000000a07a1000010000000000000001000000000000004b6710000e0000000101000000000000138212000c00000000000000a87a10000f00000000000000000000000000000000000000c8b01200b87a10000000000000000000c87a10000100000000000000000000000000000059671000080000000000000000000000845712000c00000000000000000000000000000000000000000000000000000000000000c8b01200d07a10000000000000000000e07a1000010000000000000001000000476173001c7c1000200000003c00000000000000010000005c000000f77b1000250000005072697374696e65436f64653c00000000000000010000005d0000009e7b100059000000436f646553746f726167657761736d3a3a5072656661625761736d4d6f64756c65000000457b1000590000003c000000000000000100000052000000307b100015000000436f6e7472616374496e666f3c543e003c000000000000000100000051000000067b10002a0000003c00000000000000010000005e000000e87a10001e00000020546865207072696365206f66206f6e6520756e6974206f66206761732e2054686520636f6465206173736f6369617465642077697468206120676976656e206163636f756e742e20546865207375627472696520636f756e7465722e2041206d617070696e67206265747765656e20616e206f726967696e616c20636f6465206861736820616e6420696e737472756d656e746564207761736d20636f64652c20726561647920666f7220657865637574696f6e2e2041206d617070696e672066726f6d20616e206f726967696e616c20636f6465206861736820746f20746865206f726967696e616c20636f64652c20756e746f756368656420627920696e737472756d656e746174696f6e2e2043757272656e7420636f7374207363686564756c6520666f7220636f6e7472616374732e20476173207370656e7420736f2066617220696e207468697320626c6f636b2e000000004c7f10001300000000000000f50812000e00000000000000c8b01200607f10000000000000000000707f1000040000000000000000000000907f10001000000000000000845712000c00000000000000c8b01200e87f10000000000000000000a07f1000010000000000000000000000a87f10001100000000000000847212000300000000000000c8b01200bc7f10000000000000000000cc7f1000020000000000000000000000dc7f10000b00000000000000845712000c00000000000000c8b01200e87f10000000000000000000f87f1000010000000000000000000000008010001100000000000000845712000c00000000000000c8b01200148010000000000000000000248010000700000000000000000000005c8010000f00000000000000845712000c00000000000000c8b012006c80100000000000000000007c80100002000000000000000000000024bc11001200000000000000845712000c00000000000000c8b01200a8801000000000000000000048bc110001000000000000000000000050bc11001200000000000000845712000c00000000000000c8b012008c801000000000000000000074bc11000100000000000000000000009c8010000b00000000000000845712000c00000000000000c8b01200a88010000000000000000000b8801000020000000000000000000000c88010000b000000000000001c7a10000300000000000000c8b01200f88010000000000000000000d4801000020000000000000000000000e480100012000000000000001c7a10000300000000000000c8b01200f8801000000000000000000008811000020000000000000000000000188110000800000000000000847212000300000000000000c8b0120020811000000000000000000030811000020000000000000000000000408110000c00000000000000847212000300000000000000c8b012004c81100000000000000000005c811000010000000000000000000000648110000d000000000000001c7a10000300000000000000c8b012007481100000000000000000008481100002000000000000005369676e6564436c61696d48616e6469636170003c00000000000000010000005f0000006f86100038000000c8b0120000000000a786100043000000ea8610001a000000546f6d6273746f6e654465706f7369743a8610003500000053746f7261676553697a654f66667365740000003c000000000000000100000060000000bc85100055000000118610002900000052656e7442797465466565003c0000000000000001000000610000006f8510004d00000052656e744465706f7369744f66667365740000003c000000000000000100000062000000f7831000410000003884100016000000c8b01200000000004e8410005a000000a884100056000000fe84100053000000518510001e000000537572636861726765526577617264003c000000000000000100000063000000a483100039000000dd8310001a0000003c000000000000000100000064000000436f6e7472616374466565003c0000000000000001000000650000004d831000500000009d8310000700000043616c6c4261736546656500f8821000470000003f8310000e000000496e7374616e74696174654261736546656500003c000000000000000100000066000000a28210004e000000f0821000080000004d617844657074683c000000000000000100000067000000488210004c000000948210000e0000004d617856616c756553697a653c000000000000000100000068000000fa8110004e000000426c6f636b4761734c696d69740000003c0000000000000001000000690000009481100049000000dd8110001d00000020546865206d6178696d756d20616d6f756e74206f6620676173207468617420636f756c6420626520657870656e6465642070657220626c6f636b2e204120726561736f6e61626c652064656661756c742076616c75652069732031305f3030305f3030302e20546865206d6178696d756d2073697a65206f6620612073746f726167652076616c756520696e2062797465732e204120726561736f6e61626c652064656661756c74206973203136204b69422e20546865206d6178696d756d206e657374696e67206c6576656c206f6620612063616c6c2f696e7374616e746961746520737461636b2e204120726561736f6e61626c652064656661756c742076616c7565206973203130302e20546865206261736520666565206368617267656420666f7220696e7374616e74696174696e67206120636f6e74726163742e204120726561736f6e61626c652064656661756c742076616c7565206973203137352e20546865206261736520666565206368617267656420666f722063616c6c696e6720696e746f206120636f6e74726163742e204120726561736f6e61626c652064656661756c742076616c7565206973203133352e205468652066656520726571756972656420746f20696e7374616e7469617465206120636f6e747261637420696e7374616e63652e204120726561736f6e61626c652064656661756c742076616c75652069732032312e205265776172642074686174206973207265636569766564206279207468652070617274792077686f736520746f75636820686173206c656420746f2072656d6f76616c206f66206120636f6e74726163742e2054686520616d6f756e74206f662066756e6473206120636f6e74726163742073686f756c64206465706f73697420696e206f7264657220746f206f66667365742074686520636f7374206f66206f6e6520627974652e204c6574277320737570706f736520746865206465706f73697420697320312c303030204255202862616c616e636520756e697473292f6279746520616e64207468652072656e7420697320312042552f627974652f6461792c207468656e206120636f6e7472616374207769746820312c3030302c3030302042552074686174207573657320312c303030206279746573206f662073746f7261676520776f756c6420706179206e6f2072656e742e20427574206966207468652062616c616e6365207265647563656420746f203530302c30303020425520616e64207468652073746f7261676520737461796564207468652073616d6520617420312c3030302c207468656e20697420776f756c6420706179203530302042552f6461792e205072696365206f6620612062797465206f662073746f7261676520706572206f6e6520626c6f636b20696e74657276616c2e2053686f756c642062652067726561746572207468616e20302e2053697a65206f66206120636f6e7472616374206174207468652074696d65206f6620696e7374616e74696174696f6e2e205468697320697320612073696d706c652077617920746f20656e73757265207468617420656d70747920636f6e747261637473206576656e7475616c6c7920676574732064656c657465642e20546865206d696e696d756d20616d6f756e7420726571756972656420746f2067656e6572617465206120746f6d6273746f6e652e204e756d626572206f6620626c6f636b2064656c617920616e2065787472696e73696320636c61696d20737572636861726765206861732e205768656e20636c61696d207375726368617267652069732063616c6c656420627920616e2065787472696e736963207468652072656e7420697320636865636b656420666f722063757272656e745f626c6f636b202d2064656c6179636f6465206973206e6f7420666f756e647072697374696e6520636f6465206973206e6f7420666f756e647468657265206973206e6f7420656e6f7567682067617320666f722073746f72696e672074686520636f6465000000000004671000160000000000000004881000010000000000000000000000ef66100015000000000000000c881000010000000000000000000000da661000150000000000000014881000010000000000000000000000c06610001a000000000000001c881000010000000000000000000000b06610001000000000000000248810000100000000000000000000009b66100015000000000000002c88100001000000000000003889100041000000e388100055000000ac881000370000007b881000310000006388100018000000348810002f00000020416e206f726967696e20547269654964207772697474656e20696e207468652063757272656e7420626c6f636b2e20546f6d6273746f6e657320646f6e2774206d617463682e2043616e6e6f7420726573746f726520746f206e6f6e6578697374696e67206f7220616c69766520636f6e74726163742e2043616e6e6f7420726573746f72652066726f6d206e6f6e6578697374696e67206f7220746f6d6273746f6e6520636f6e74726163742e20416e206f726967696e206d757374206265207369676e6564206f7220696e686572656e7420616e6420617578696c696172792073656e646572206f6e6c792070726f7669646564206f6e20696e686572656e742e2041206e6577207363686564756c65206d7573742068617665206120677265617465722076657273696f6e207468616e207468652063757272656e74206f6e652e486561644f6644656c65676174696f6e7344656c65676174696f6e734e6f7441637469766557726f6e674f70656e4e6f744f70656e4e6f74457870697265644e6f744c6f636b65644e6f6e6557616974696e67507265696d616765496e76616c69645265666572656e64756d496e76616c6964507265696d6167654d697373696e67496d6d696e656e744561726c794e6f74496d6d696e656e744475706c6963617465507265696d6167654e6f7444656c65676174656457726f6e6750726f7879416c72656164795665746f65644e6f50726f706f73616c496e76616c6964486173684e6f7453696d706c654d616a6f7269747950726f706f73616c426c61636b6c6973746564416c726561647943616e63656c6564426164496e6465784e6f7450726f787956616c75654c6f777365636f6e6470726f78795f766f7465656d657267656e63795f63616e63656c65787465726e616c5f70726f706f736565787465726e616c5f70726f706f73655f6d616a6f7269747965787465726e616c5f70726f706f73655f64656661756c74666173745f747261636b7665746f5f65787465726e616c63616e63656c5f7265666572656e64756d63616e63656c5f71756575656461637469766174655f70726f7879636c6f73655f70726f7879646561637469766174655f70726f787964656c6567617465756e64656c6567617465636c6561725f7075626c69635f70726f706f73616c736e6f74655f707265696d6167656e6f74655f696d6d696e656e745f707265696d616765726561705f707265696d616765756e6c6f636b6f70656e5f70726f78795265666572656e64756d496e666f4f66566f74654f660000000030ec11000800000000000000d08e1000020000000000000000000000e08e1000010000000000000000000000e88e10000600000000000000f08e1000030000000000000000000000088f1000010000000000000000000000108f10000e00000000000000c8b01200000000000000000000000000208f1000010000000000000000000000288f10000700000000000000308f1000020000000000000000000000408f1000010000000000000000000000488f10000600000000000000508f1000010000000000000000000000588f1000010000000000000000000000608f10000900000000000000508f10000100000000000000000000006c8f1000010000000000000000000000748f10000900000000000000508f1000010000000000000000000000808f1000010000000000000000000000d4ec11000800000000000000888f1000020000000000000000000000988f1000010000000000000000000000a08f1000090000000000000080e81100020000000000000000000000ac8f1000010000000000000000000000b48f10000b000000000000005ce81100010000000000000000000000c08f1000010000000000000000000000c88f10000600000000000000d08f1000030000000000000000000000e88f1000010000000000000000000000f08f10000d000000000000000027110003000000000000000000000000901000010000000000000000000000089010000c000000000000000027110003000000000000000000000014901000010000000000000000000000cc8910000f000000000000001c9010000200000000000000000000002c901000010000000000000000000000ec8910000f000000000000001c901000020000000000000000000000349010000100000000000000000000003c9010000e000000000000004c9010000400000000000000000000006c9010000100000000000000000000007490100008000000000000005ce811000100000000000000000000007c9010000100000000000000d3931000090000009027120007000000dc931000300000005461626c65640000d3931000090000009027120007000000a42111000e0000009c9310003700000045787465726e616c5461626c65640000769310002600000053746172746564008c9110000f000000699310000d000000519310001800000050617373656400008c9110000f000000259310002c0000004e6f74506173736564000000f99210002c00000043616e63656c6c6564000000d8921000210000008c9110000f00000000ee110004000000bb9210001d00000044656c6567617465640000008392100038000000556e64656c65676174656400499210003a0000005665746f65640000c26d12000900000065ed1100040000003e9210000b0000001892100026000000507265696d6167654e6f746564000000e091100038000000507265696d616765557365649b9110004500000065ed1100040000008c9110000f00000049911000430000000691100043000000507265696d616765526561706564000065ed110004000000c26d1200090000009027120007000000c26d120009000000af90100057000000556e6c6f636b6564849010002b00000020416e206163636f756e7420686173206265656e20756e6c6f636b6564207375636365737366756c6c792e2041207265676973746572656420707265696d616765207761732072656d6f76656420616e6420746865206465706f73697420636f6c6c6563746564206279207468652072656170657220286c617374206974656d292e20412070726f706f73616c20636f756c64206e6f7420626520657865637574656420626563617573652069747320707265696d61676520776173206d697373696e672e20412070726f706f73616c20636f756c64206e6f7420626520657865637574656420626563617573652069747320707265696d6167652077617320696e76616c69642e5265666572656e64756d496e64657820412070726f706f73616c20707265696d616765207761732072656d6f76656420616e6420757365642028746865206465706f736974207761732072657475726e6564292e20412070726f706f73616c277320707265696d61676520776173206e6f7465642c20616e6420746865206465706f7369742074616b656e2e20416e2065787465726e616c2070726f706f73616c20686173206265656e207665746f65642e426c6f636b4e756d62657220416e206163636f756e74206861732063616e63656c6c656420612070726576696f75732064656c65676174696f6e206f7065726174696f6e2e20416e206163636f756e74206861732064656c65676174656420746865697220766f746520746f20616e6f74686572206163636f756e742e20412070726f706f73616c20686173206265656e20656e61637465642e2041207265666572656e64756d20686173206265656e2063616e63656c6c65642e20412070726f706f73616c20686173206265656e2072656a6563746564206279207265666572656e64756d2e20412070726f706f73616c20686173206265656e20617070726f766564206279207265666572656e64756d2e2041207265666572656e64756d2068617320626567756e2e566f74655468726573686f6c6420416e2065787465726e616c2070726f706f73616c20686173206265656e207461626c65642e2041207075626c69632070726f706f73616c20686173206265656e207461626c656420666f72207265666572656e64756d20766f74652e50726f70496e6465782041206d6f74696f6e20686173206265656e2070726f706f7365642062792061207075626c6963206163636f756e742e44697370617463685175657565507265696d61676573566f74657273466f725075626c696350726f70734465706f7369744f664e65787445787465726e616c0000000000ecea1100070000000000000040981000020000000000000000000000709810000e0000000000000000000000a78a10000600000000000000e0981000010000000000000000000000f89810000b0000000000000000000000f3ea1100040000000000000050991000020000000000000000000000809910000c0000000000000000000000ad8a10000a0000000000000050991000020000000000000000000000e09910000c0000000000000000000000b78a10001000000000000000409a1000010000000000000000000000589a10000a0000000000000000000000c78a10001000000000000000a89a1000010000000000000000000000c09a10000b0000000000000000000000d78a10001900000000000000a89a1000010000000000000000000000189b10000e0000000000000000000000f08a10001800000000000000a89a1000010000000000000000000000889b10000e0000000000000000000000088b10000a00000000000000f89b1000030000000000000000000000409c1000130000000000000000000000128b10000d00000000000000a89a1000010000000000000000000000d89c10000e00000000000000000000001f8b10001100000000000000489d1000010000000000000000000000609d1000090000000000000000000000308b10000d00000000000000a89d1000010000000000000000000000c09d10000900000000000000000000003d8b10000e00000000000000089e1000010000000000000000000000209e10000b00000000000000000000004b8b10000b00000000000000c8b01200000000000000000000000000789e1000090000000000000000000000568b10001000000000000000089e1000010000000000000000000000c09e10000d0000000000000000000000668b10000800000000000000289f1000020000000000000000000000589f10000f00000000000000000000006e8b10000a00000000000000c8b01200000000000000000000000000d09f10000d0000000000000000000000788b10001600000000000000c8b0120000000000000000000000000038a010000800000000000000000000008e8b10000d0000000000000078a0100001000000000000000000000090a010000d00000000000000000000009b8b1000160000000000000078a01000010000000000000000000000f8a010000c0000000000000000000000b18b10000d00000000000000a89a100001000000000000000000000058a110000f0000000000000000000000be8b10000600000000000000d0a11000010000000000000000000000e8a110000b0000000000000000000000c48b10000a00000000000000d0a1100001000000000000000000000040a210000d0000000000000000000000d2af10000d000000000000008113120007000000000000007c4712000500000000000000814712001500000053b6100028000000c8b01200000000007bb6100046000000c1b6100021000000c8b0120000000000e2b610003600000018b7100046000000c8b01200000000005eb7100012000000c8b01200000000002a7f12000b000000357f12000a00000070b7100020000000927f12000c0000000000000079131200080000000000000041b61000120000005ab510002e000000c8b012000000000088b5100041000000c9b5100045000000c8b01200000000000eb6100033000000c8b01200000000002a7f12000b000000357f12000a0000006247120010000000927f12000c000000000000001bac1000090000000000000024ac10001800000000000000f3ea11000400000000000000bc1f110004000000a6b410004d000000f3b410002f000000c8b0120000000000aea3100033000000c8b012000000000022b510003800000065b4100022000000c8b01200000000002a7f12000b000000357f12000a00000087b410001f000000927f12000c00000096b3100054000000eab310003d000000c8b0120000000000aea3100033000000c8b012000000000027b410003e00000065b4100022000000c8b01200000000002a7f12000b000000357f12000a00000087b410001f000000927f12000c000000000000001bac100009000000000000008c9110000f0000008cb210005400000045b210000c000000c8b0120000000000e0b210003f000000c8b01200000000001fb3100035000000c8b01200000000002a7f12000b00000054b3100042000000927f12000c00000000000000d2af10000d000000000000008113120007000000f9b110004c00000045b210000c000000c8b012000000000051b210003b000000c8b01200000000009fb0100036000000c8b01200000000002a7f12000b000000357f12000a0000004531110011000000927f12000c0000004fb1100056000000a5b1100018000000c8b0120000000000bdb110003c000000a2ac1000010000009fb0100036000000c8b0120000000000d5b010005300000028b1100027000000c8b01200000000002a7f12000b000000357f12000a0000004531110011000000927f12000c000000f1af10005200000043b0100021000000c8b012000000000064b010003b000000c8b01200000000009fb0100036000000c8b0120000000000d5b010005300000028b1100027000000c8b01200000000002a7f12000b000000357f12000a0000004531110011000000927f12000c00000000000000d2af10000d00000000000000811312000700000000000000dfaf10000d00000000000000f50812000e00000000000000ecaf10000500000000000000f50812000e00000064ad100054000000b8ad10005900000011ae10003b000000c8b01200000000004cae100035000000c8b012000000000081ae10003e000000bfae10005800000017af1000260000003daf10005500000092af10002f000000c8b0120000000000c1af100011000000c8b01200000000002a7f12000b000000977e1100100000004531110011000000650b110016000000927f12000c0000003cac10002f000000c8b01200000000006bac100037000000a2ac100001000000a3ac10004c000000c8b0120000000000efac100010000000c8b01200000000002a7f12000b000000ffac100012000000977e11001000000011ad10004200000053ad100011000000927f12000c000000000000001bac1000090000000000000024ac100018000000d0ab100015000000c8b01200000000009ca7100031000000c8b0120000000000e5ab100036000000c8b01200000000002a7f12000b000000357f12000a000000927f12000c00000000000000cbab100005000000000000008c9110000f00000071ab100028000000c8b01200000000009ca7100031000000c8b012000000000099ab100032000000c8b01200000000002a7f12000b0000004531110011000000927f12000c000000000000006cab10000500000000000000138212000c000000ceaa100041000000c8b01200000000000fab100025000000c8b0120000000000aea3100033000000c8b012000000000034ab100038000000c8b01200000000002a7f12000b000000650b110016000000927f12000c00000080aa100026000000c8b0120000000000a6aa100028000000c8b0120000000000aea3100033000000c8b01200000000002a7f12000b000000977e110010000000927f12000c000000b1a910004b000000c8b0120000000000fca9100022000000c8b01200000000001eaa100028000000c8b0120000000000aea3100033000000c8b012000000000046aa10003a000000c8b01200000000002a7f12000b000000977e110010000000927f12000c000000000000009ba910000200000000000000138212000c000000000000009da910000a00000000000000a7a910000a000000b5a810000f000000c8b0120000000000c4a810003f000000c8b0120000000000aea3100033000000c8b012000000000003a910003600000039a91000460000007fa9100009000000c8b012000000000088a9100013000000c8b01200000000002a7f12000b000000650b110016000000927f12000c000000cda7100011000000c8b0120000000000dea710004200000020a810004200000062a810003e000000c8b0120000000000aea3100033000000c8b0120000000000a0a8100015000000c8b01200000000002a7f12000b000000bc48120008000000927f12000c0000007fa710001d000000c8b01200000000009ca7100031000000c8b01200000000002a7f12000b000000357f12000a000000977e110010000000927f12000c000000000000006fa71000100000000000000070a311000700000078a6100058000000d0a6100049000000c8b0120000000000aea3100033000000c8b012000000000000a6100032000000c8b012000000000032a6100017000000c8b01200000000002a7f12000b00000019a71000420000005ba7100014000000927f12000c00000082a5100051000000d3a510002d000000c8b0120000000000aea3100033000000c8b012000000000000a6100032000000c8b012000000000032a6100017000000c8b01200000000002a7f12000b00000049a610002f000000927f12000c00000022a410003d000000c8b0120000000000aea3100033000000c8b01200000000005fa4100034000000c8b012000000000093a4100054000000e7a41000570000003ea510002c000000c8b01200000000006aa5100018000000c8b01200000000002a7f12000b000000977e110010000000927f12000c00000000000000ffd711000600000000000000138212000c00000085a3100029000000c8b0120000000000aea3100033000000c8b0120000000000e1a310002f000000c8b012000000000010a4100012000000c8b01200000000002a7f12000b000000357f12000a000000927f12000c000000a8a2100010000000c8b0120000000000b8a2100037000000c8b0120000000000efa2100019000000c8b012000000000008a310003b000000c8b012000000000043a3100042000000c8b01200000000002a7f12000b000000650b110016000000927f12000c000000204265636f6d6520612070726f78792e2054686973206d7573742062652063616c6c6564207072696f7220746f2061206c61746572206061637469766174655f70726f7879602e204f726967696e206d7573742062652061205369676e65642e202d2060746172676574603a20546865206163636f756e742077686f736520766f7465732077696c6c206c617465722062652070726f786965642e2060636c6f73655f70726f787960206d7573742062652063616c6c6564206265666f726520746865206163636f756e742063616e2062652064657374726f7965642e20556e6c6f636b20746f6b656e732074686174206861766520616e2065787069726564206c6f636b2e20546865206469737061746368206f726967696e206f6620746869732063616c6c206d757374206265205f5369676e65645f2e202d2060746172676574603a20546865206163636f756e7420746f2072656d6f766520746865206c6f636b206f6e2e20456d6974732060556e6c6f636b6564602e2052656d6f766520616e20657870697265642070726f706f73616c20707265696d61676520616e6420636f6c6c65637420746865206465706f7369742e202d206070726f706f73616c5f68617368603a2054686520707265696d6167652068617368206f6620612070726f706f73616c2e20546869732077696c6c206f6e6c7920776f726b2061667465722060566f74696e67506572696f646020626c6f636b732066726f6d207468652074696d6520746861742074686520707265696d61676520776173206e6f7465642c2069662069742773207468652073616d65206163636f756e7420646f696e672069742e2049662069742773206120646966666572656e74206163636f756e742c207468656e206974276c6c206f6e6c7920776f726b20616e206164646974696f6e616c2060456e6163746d656e74506572696f6460206c617465722e20456d6974732060507265696d616765526561706564602e2052656769737465722074686520707265696d61676520666f7220616e207570636f6d696e672070726f706f73616c2e2054686973207265717569726573207468652070726f706f73616c20746f20626520696e207468652064697370617463682071756575652e204e6f206465706f736974206973206e65656465642e202d2060656e636f6465645f70726f706f73616c603a2054686520707265696d616765206f6620612070726f706f73616c2e20456d6974732060507265696d6167654e6f746564602e202d20446570656e64656e74206f6e207468652073697a65206f662060656e636f6465645f70726f706f73616c602e2052656769737465722074686520707265696d61676520666f7220616e207570636f6d696e672070726f706f73616c2e205468697320646f65736e27742072657175697265207468652070726f706f73616c20746f20626520696e207468652064697370617463682071756575652062757420646f657320726571756972652061206465706f7369742c2072657475726e6564206f6e636520656e61637465642e202d20446570656e64656e74206f6e207468652073697a65206f662060656e636f6465645f70726f706f73616c60206275742070726f7465637465642062792061202020207265717569726564206465706f7369742e656e636f6465645f70726f706f73616c20436c6561727320616c6c207075626c69632070726f706f73616c732e20546865206469737061746368206f726967696e206f6620746869732063616c6c206d757374206265205f526f6f745f2e20556e64656c656761746520766f74652e204d7573742062652073656e742066726f6d20616e206163636f756e742074686174206861732063616c6c65642064656c65676174652070726576696f75736c792e2054686520746f6b656e732077696c6c20626520726564756365642066726f6d20616e20696e646566696e697465206c6f636b20746f20746865206d6178696d756d20706f737369626c65206163636f7264696e6720746f2074686520636f6e76696374696f6e206f6620746865207072696f722064656c65676174696f6e2e20456d6974732060556e64656c656761746564602e2044656c656761746520766f74652e2043757272656e6379206973206c6f636b656420696e646566696e6974656c7920666f72206173206c6f6e6720617320697427732064656c6567617465642e202d2060746f603a20546865206163636f756e7420746f206d616b6520612064656c6567617465206f66207468652073656e6465722e202d2060636f6e76696374696f6e603a2054686520636f6e76696374696f6e20746861742077696c6c20626520617474616368656420746f207468652064656c656761746564202020766f7465732e20456d697473206044656c656761746564602e746f636f6e76696374696f6e436f6e76696374696f6e2044656163746976617465207468652070726f78792c20627574206c65617665206f70656e20746f2074686973206163636f756e742e2043616c6c6564206279207468652073746173682e205468652070726f7879206d75737420616c7265616479206265206163746976652e204e4f54453a205573656420746f2062652063616c6c6564206072656d6f76655f70726f7879602e202d206070726f7879603a20546865206163636f756e7420746861742077696c6c2062652064656163746976617465642061732070726f78792e20436c656172207468652070726f78792e2043616c6c6564206279207468652070726f78792e204e4f54453a205573656420746f2062652063616c6c6564206072657369676e5f70726f7879602e205370656369667920612070726f7879207468617420697320616c7265616479206f70656e20746f2075732e2043616c6c6564206279207468652073746173682e204e4f54453a205573656420746f2062652063616c6c656420607365745f70726f7879602e202d206070726f7879603a20546865206163636f756e7420746861742077696c6c206265206163746976617465642061732070726f78792e70726f78792043616e63656c20612070726f706f73616c2071756575656420666f7220656e6163746d656e742e202d20607768696368603a2054686520696e646578206f6620746865207265666572656e64756d20746f2063616e63656c2e77686963682052656d6f76652061207265666572656e64756d2e202d20607265665f696e646578603a2054686520696e646578206f6620746865207265666572656e64756d20746f2063616e63656c2e7265665f696e646578436f6d706163743c5265666572656e64756d496e6465783e205665746f20616e6420626c61636b6c697374207468652065787465726e616c2070726f706f73616c20686173682e20546865206469737061746368206f726967696e206f6620746869732063616c6c206d75737420626520605665746f4f726967696e602e20202d206070726f706f73616c5f68617368603a2054686520707265696d6167652068617368206f66207468652070726f706f73616c20746f207665746f20616e6420626c61636b6c6973742e20456d69747320605665746f6564602e202d2054776f20444220656e74726965732e202d20506572666f726d7320612062696e61727920736561726368206f6e20606578697374696e675f7665746f657273602077686963682073686f756c64206e6f7420202062652076657279206c617267652e205363686564756c65207468652063757272656e746c792065787465726e616c6c792d70726f706f736564206d616a6f726974792d63617272696573207265666572656e64756d20746f206265207461626c656420696d6d6564696174656c792e204966207468657265206973206e6f2065787465726e616c6c792d70726f706f736564207265666572656e64756d2063757272656e746c792c206f72206966207468657265206973206f6e6520627574206974206973206e6f742061206d616a6f726974792d63617272696573207265666572656e64756d207468656e206974206661696c732e20546865206469737061746368206f6620746869732063616c6c206d757374206265206046617374547261636b4f726967696e602e202d206070726f706f73616c5f68617368603a205468652068617368206f66207468652063757272656e742065787465726e616c2070726f706f73616c2e202d2060766f74696e675f706572696f64603a2054686520706572696f64207468617420697320616c6c6f77656420666f7220766f74696e67206f6e20746869732070726f706f73616c2e20496e6372656173656420746f20202060456d657267656e6379566f74696e67506572696f646020696620746f6f206c6f772e202d206064656c6179603a20546865206e756d626572206f6620626c6f636b20616674657220766f74696e672068617320656e64656420696e20617070726f76616c20616e6420746869732073686f756c64206265202020656e61637465642e205468697320646f65736e277420686176652061206d696e696d756d20616d6f756e742e20456d697473206053746172746564602e70726f706f73616c5f68617368766f74696e675f706572696f6464656c6179205363686564756c652061206e656761746976652d7475726e6f75742d62696173207265666572656e64756d20746f206265207461626c6564206e657874206f6e6365206974206973206c6567616c20746f207363686564756c6520616e2065787465726e616c207265666572656e64756d2e20546865206469737061746368206f6620746869732063616c6c206d757374206265206045787465726e616c44656661756c744f726967696e602e202d206070726f706f73616c5f68617368603a2054686520707265696d6167652068617368206f66207468652070726f706f73616c2e20556e6c696b65206065787465726e616c5f70726f706f7365602c20626c61636b6c697374696e6720686173206e6f20656666656374206f6e207468697320616e64206974206d6179207265706c6163652061207072652d7363686564756c6564206065787465726e616c5f70726f706f7365602063616c6c2e205363686564756c652061206d616a6f726974792d63617272696573207265666572656e64756d20746f206265207461626c6564206e657874206f6e6365206974206973206c6567616c20746f207363686564756c6520616e2065787465726e616c207265666572656e64756d2e20546865206469737061746368206f6620746869732063616c6c206d757374206265206045787465726e616c4d616a6f726974794f726967696e602e205363686564756c652061207265666572656e64756d20746f206265207461626c6564206f6e6365206974206973206c6567616c20746f207363686564756c6520616e2065787465726e616c207265666572656e64756d2e20546865206469737061746368206f726967696e206f6620746869732063616c6c206d757374206265206045787465726e616c4f726967696e602e205363686564756c6520616e20656d657267656e63792063616e63656c6c6174696f6e206f662061207265666572656e64756d2e2043616e6e6f742068617070656e20747769636520746f207468652073616d6520546865206469737061746368206f726967696e206f6620746869732063616c6c206d757374206265206043616e63656c6c6174696f6e4f726967696e602e202d607265665f696e646578603a2054686520696e646578206f6620746865207265666572656e64756d20746f2063616e63656c2e202d20446570656e6473206f6e2073697a65206f662073746f72616765207665632060566f74657273466f726020666f722074686973207265666572656e64756d2e20566f746520696e2061207265666572656e64756d206f6e20626568616c66206f6620612073746173682e2049662060766f74652e69735f6179652829602c2074686520766f746520697320746f20656e616374207468652070726f706f73616c3b206f7468657277697365206974206973206120766f746520746f206b65657020746865207374617475732071756f2e202d20607265665f696e646578603a2054686520696e646578206f6620746865207265666572656e64756d20746f2070726f787920766f746520666f722e202d2060766f7465603a2054686520766f746520636f6e66696775726174696f6e2e202d204f6e65204442206368616e67652c206f6e6520444220656e7472792e20566f746520696e2061207265666572656e64756d2e2049662060766f74652e69735f6179652829602c2074686520766f746520697320746f20656e616374207468652070726f706f73616c3b206f7468657277697365206974206973206120766f746520746f206b65657020746865207374617475732071756f2e202d20607265665f696e646578603a2054686520696e646578206f6620746865207265666572656e64756d20746f20766f746520666f722e205369676e616c732061677265656d656e742077697468206120706172746963756c61722070726f706f73616c2e20546865206469737061746368206f726967696e206f6620746869732063616c6c206d757374206265205f5369676e65645f20616e64207468652073656e646572206d75737420686176652066756e647320746f20636f76657220746865206465706f7369742c20657175616c20746f20746865206f726967696e616c206465706f7369742e202d206070726f706f73616c603a2054686520696e646578206f66207468652070726f706f73616c20746f207365636f6e642e436f6d706163743c50726f70496e6465783e2050726f706f736520612073656e73697469766520616374696f6e20746f2062652074616b656e2e20546865206469737061746368206f726967696e206f6620746869732063616c6c206d757374206265205f5369676e65645f20616e64207468652073656e646572206d75737420686176652066756e647320746f20636f76657220746865206465706f7369742e202d206070726f706f73616c5f68617368603a205468652068617368206f66207468652070726f706f73616c20707265696d6167652e202d206076616c7565603a2054686520616d6f756e74206f66206465706f73697420286d757374206265206174206c6561737420604d696e696d756d4465706f73697460292e20456d697473206050726f706f736564602e202d2054776f204442206368616e6765732c206f6e6520444220656e7472792e00000000f48b12000f0000000000000000000000d39310000900000000000000000000000000000000000000000000000000000000000000c8b012004cbe1000000000000000000068bd1000010000000000000001000000000000002b9410000b000000000000000000000070bd10002700000000000000000000000000000000000000000000000000000000000000c8b0120098bd10000000000000000000a8bd10000100000000000000010000000000000019941000090000000101000000000000811312000700000000000000b0bd10003500000000000000000000000000000000000000c8b01200e8bd10000000000000000000f8bd10000200000000000000000000000000000036941000090000000101000000000000d3931000090000000000000008be10002100000000000000000000000000000000000000c8b012002cbe100000000000000000003cbe100001000000000000000000000000000000038c12000f00000000000000000000008c9110000f00000000000000000000000000000000000000000000000000000000000000c8b012004cbe1000000000000000000044be1000010000000000000001000000000000001b8c12000d00000000000000000000008c9110000f00000000000000000000000000000000000000000000000000000000000000c8b012004cbe100000000000000000005cbe100002000000000000000100000000000000ce8b10001000000001010000000000008c9110000f000000000000006cbe10002700000000000000000000000000000000000000c8b0120000c01000000000000000000094be1000010000000000000000000000000000000c9410000d00000000000000000000009cbe10002f00000000000000000000000000000000000000000000000000000000000000c8b01200ccbe10000000000000000000dcbe100001000000000000000100000000000000229410000900000001010000000000008c9110000f00000000000000e03c12001100000000000000000000000000000000000000c8b01200e4be10000000000000000000f4be100001000000000000000100000000000000de8b1000060000000101000000000000fcbe10001f00000000000000bc1f11000400000000000000000000000000000000000000c8b012001cbf100000000000000000002cbf100004000000000000000100000000000000540d1200050000000101000000000000138212000c000000000000004cbf10001800000000000000000000000000000000000000c8b0120064bf1000000000000000000074bf1000020000000000000000000000000000008a8910000b0000000101010000000000138212000c0000000000000084bf10001a00000000000000000000000000000000000000c8b01200a0bf10000000000000000000b0bf100001000000000000000100000000000000f99a1100050000000101000000000000138212000c00000000000000f50812000e00000000000000000000000000000000000000c8b01200b8bf10000000000000000000c8bf100002000000000000000000000000000000288c120015000000000000000000000000ee11000400000000000000000000000000000000000000000000000000000000000000c8b012008cc010000000000000000000d8bf1000020000000000000001000000000000003f9410000c0000000000000000000000e8bf10001800000000000000000000000000000000000000000000000000000000000000c8b0120000c01000000000000000000010c010000400000000000000000000000000000030c0100009000000010100000000000081131200070000000000000039c010002300000000000000000000000000000000000000c8b012005cc0100000000000000000006cc01000020000000000000000000000000000007cc010000d000000010100000000000081131200070000000000000000ee11000400000000000000000000000000000000000000c8b012008cc0100000000000000000009cc01000010000000000000001000000e4c710003d0000005665633c2850726f70496e6465782c20543a3a486173682c20543a3a4163636f756e744964293e003c0000000000000001000000590000009cc7100048000000285665633c75383e2c20543a3a4163636f756e7449642c2042616c616e63654f663c543e2c20543a3a426c6f636b4e756d626572290000003c00000000000000010000006a0000000bc710005800000063c71000390000002842616c616e63654f663c543e2c205665633c543a3a4163636f756e7449643e290000003c00000000000000010000006a000000eac61000210000009ec610004c0000003c00000000000000010000006b0000001ec610004900000067c61000370000005265666572656e64756d496e666f3c543a3a426c6f636b4e756d6265722c20543a3a486173683e00f1c510002d0000005665633c28543a3a426c6f636b4e756d6265722c20543a3a486173682c205265666572656e64756d496e646578293e003c000000000000000100000059000000a1c51000500000003c00000000000000010000005900000078c5100029000000285265666572656e64756d496e6465782c20543a3a4163636f756e74496429003c00000000000000010000005100000033c41000580000008bc4100053000000dec410005700000035c510004300000050726f787953746174653c543a3a4163636f756e7449643e3c000000000000000100000051000000c5c310004c00000011c410002200000028543a3a4163636f756e7449642c20436f6e76696374696f6e2900003c00000000000000010000006c00000075c31000500000003c000000000000000100000051000000cac210005700000021c31000540000006ac2100056000000c0c210000a00000028543a3a486173682c20566f74655468726573686f6c64293c0000000000000001000000510000007cc1100056000000d2c110005500000027c210002900000050c210001a000000426c61636b6c69737428543a3a426c6f636b4e756d6265722c205665633c543a3a4163636f756e7449643e293c00000000000000010000006a000000eec010005400000042c110003a00000043616e63656c6c6174696f6e730000003c000000000000000100000051000000a4c010004a000000205265636f7264206f6620616c6c2070726f706f73616c7320746861742068617665206265656e207375626a65637420746f20656d657267656e63792063616e63656c6c6174696f6e2e2041207265636f7264206f662077686f207665746f656420776861742e204d6170732070726f706f73616c206861736820746f206120706f737369626c65206578697374656e7420626c6f636b206e756d6265722028756e74696c207768656e206974206d6179206e6f742062652072657375626d69747465642920616e642077686f207665746f65642069742e20546865207265666572656e64756d20746f206265207461626c6564207768656e6576657220697420776f756c642062652076616c696420746f207461626c6520616e2065787465726e616c2070726f706f73616c2e20546869732068617070656e73207768656e2061207265666572656e64756d206e6565647320746f206265207461626c656420616e64206f6e65206f662074776f20636f6e646974696f6e7320617265206d65743a202d20604c6173745461626c656457617345787465726e616c60206973206066616c7365603b206f72202d20605075626c696350726f70736020697320656d7074792e205472756520696620746865206c617374207265666572656e64756d207461626c656420776173207375626d69747465642065787465726e616c6c792e2046616c7365206966206974207761732061207075626c69632070726f706f73616c2e204163636f756e747320666f7220776869636820746865726520617265206c6f636b7320696e20616374696f6e207768696368206d61792062652072656d6f76656420617420736f6d6520706f696e7420696e20746865206675747572652e205468652076616c75652069732074686520626c6f636b206e756d62657220617420776869636820746865206c6f636b206578706972657320616e64206d61792062652072656d6f7665642e2047657420746865206163636f756e742028616e64206c6f636b20706572696f64732920746f20776869636820616e6f74686572206163636f756e742069732064656c65676174696e6720766f74652e2057686f2069732061626c6520746f20766f746520666f722077686f6d2e2056616c7565206973207468652066756e642d686f6c64696e67206163636f756e742c206b65792069732074686520766f74652d7472616e73616374696f6e2d73656e64696e67206163636f756e742e204765742074686520766f746520696e206120676976656e207265666572656e64756d206f66206120706172746963756c617220766f7465722e2054686520726573756c74206973206d65616e696e6766756c206f6e6c792069662060766f746572735f666f726020696e636c756465732074686520766f746572207768656e2063616c6c6564207769746820746865207265666572656e64756d2028796f75276c6c20676574207468652064656661756c742060566f7465602076616c7565206f7468657277697365292e20496620796f7520646f6e27742077616e7420746f20636865636b2060766f746572735f666f72602c207468656e20796f752063616e20616c736f20636865636b20666f722073696d706c65206578697374656e636520776974682060566f74654f663a3a636f6e7461696e735f6b6579602066697273742e204765742074686520766f7465727320666f72207468652063757272656e742070726f706f73616c2e205175657565206f66207375636365737366756c207265666572656e646120746f20626520646973706174636865642e2053746f726564206f72646572656420627920626c6f636b206e756d6265722e20496e666f726d6174696f6e20636f6e6365726e696e6720616e7920676976656e207265666572656e64756d2e20546865206c6f77657374207265666572656e64756d20696e64657820726570726573656e74696e6720616e20756e62616b6564207265666572656e64756d2e20457175616c20746f20605265666572656e64756d436f756e74602069662074686572652069736e2774206120756e62616b6564207265666572656e64756d2e20546865206e6578742066726565207265666572656e64756d20696e6465782c20616b6120746865206e756d626572206f66207265666572656e6461207374617274656420736f206661722e2054686f73652077686f2068617665206c6f636b65642061206465706f7369742e204d6170206f662068617368657320746f207468652070726f706f73616c20707265696d6167652c20616c6f6e6720776974682077686f207265676973746572656420697420616e64207468656972206465706f7369742e2054686520626c6f636b206e756d6265722069732074686520626c6f636b20617420776869636820697420776173206465706f73697465642e20546865207075626c69632070726f706f73616c732e20556e736f727465642e20546865207365636f6e64206974656d206973207468652070726f706f73616c277320686173682e20546865206e756d626572206f6620287075626c6963292070726f706f73616c7320746861742068617665206265656e206d61646520736f206661722e00000000000000acc910000f00000000000000f50812000e00000000000000c8b01200bcc910000000000000000000ccc91000050000000000000000000000f4c910000c00000000000000f50812000e00000000000000c8b0120084ca1000000000000000000000ca100001000000000000000000000008ca10000c00000000000000f50812000e00000000000000c8b0120084ca1000000000000000000014ca10000100000000000000000000001cca10000e00000000000000845712000c00000000000000c8b012002cca100000000000000000003cca100001000000000000000000000044ca10001500000000000000f50812000e00000000000000c8b012005cca100000000000000000006cca100001000000000000000000000074ca10000d00000000000000f50812000e00000000000000c8b0120084ca1000000000000000000094ca10000100000000000000000000009cca10001300000000000000845712000c00000000000000c8b01200b0ca10000000000000000000c0ca10000100000000000000456e6163746d656e74506572696f64003c00000000000000010000006d00000059cc10005c000000c8b0120000000000b5cc10004c00000001cd10005a0000005bcd1000270000004c61756e6368506572696f6420cc100039000000566f74696e67506572696f64f2cb10002e0000004d696e696d756d4465706f73697400003c000000000000000100000057000000a5cb10004d000000456d657267656e6379566f74696e67506572696f640000003c00000000000000010000006e0000006acb10003b000000436f6f6c6f6666506572696f640000003c00000000000000010000006f00000012cb100058000000507265696d616765427974654465706f736974003c000000000000000100000065000000c8ca10004a0000002054686520616d6f756e74206f662062616c616e63652074686174206d757374206265206465706f7369746564207065722062797465206f6620707265696d6167652073746f7265642e20506572696f6420696e20626c6f636b7320776865726520616e2065787465726e616c2070726f706f73616c206d6179206e6f742062652072652d7375626d6974746564206166746572206265696e67207665746f65642e204d696e696d756d20766f74696e6720706572696f6420616c6c6f77656420666f7220616e20656d657267656e6379207265666572656e64756d2e20546865206d696e696d756d20616d6f756e7420746f20626520757365642061732061206465706f73697420666f722061207075626c6963207265666572656e64756d2070726f706f73616c2e20486f77206f6674656e2028696e20626c6f636b732920746f20636865636b20666f72206e657720766f7465732e20486f77206f6674656e2028696e20626c6f636b7329206e6577207075626c6963207265666572656e646120617265206c61756e636865642e20546865206d696e696d756d20706572696f64206f66206c6f636b696e6720616e642074686520706572696f64206265747765656e20612070726f706f73616c206265696e6720617070726f76656420616e6420656e61637465642e2049742073686f756c642067656e6572616c6c792062652061206c6974746c65206d6f7265207468616e2074686520756e7374616b6520706572696f6420746f20656e73757265207468617420766f74696e67207374616b657273206861766520616e206f70706f7274756e69747920746f2072656d6f7665207468656d73656c7665732066726f6d207468652073797374656d20696e207468652063617365207768657265207468657920617265206f6e20746865206c6f73696e672073696465206f66206120766f74652e0000000000009f8a1000080000000000000078d01000010000000000000000000000b1ea11000f0000000000000080d01000010000000000000000000000978a1000080000000000000088d010000100000000000000000000008f8a1000080000000000000090d01000010000000000000000000000808a10000f0000000000000098d01000010000000000000000000000c0ea11001100000000000000a0d010000100000000000000000000006d8a10001300000000000000a8d010000100000000000000000000005c8a10001100000000000000b0d01000010000000000000000000000518a10000b00000000000000b8d01000010000000000000000000000478a10000a00000000000000c0d010000100000000000000000000003a8a10000d00000000000000c8d0100001000000000000000000000005e611000c00000000000000d0d01000010000000000000000000000308a10000a00000000000000d8d01000010000000000000000000000248a10000c00000000000000e0d01000010000000000000000000000138a10001100000000000000e8d01000010000000000000000000000088a10000b00000000000000f0d01000010000000000000000000000038a10000500000000000000f8d01000010000000000000000000000fb891000080000000000000000d11000010000000000000000000000ec8910000f0000000000000008d11000010000000000000000000000db891000110000000000000010d11000010000000000000000000000cc8910000f0000000000000018d11000010000000000000000000000c18910000b0000000000000020d11000010000000000000000000000b8891000090000000000000028d11000010000000000000000000000ae8910000a0000000000000030d11000010000000000000000000000a7891000070000000000000038d110000100000000000000000000009e891000090000000000000040d1100001000000000000000000000095891000090000000000000048d1100001000000000000003fd410000e00000027d41000180000001bd410000c0000000dd410000e000000e7d3100026000000d1d3100016000000b6d310001b0000008bd310002b0000007ed310000d00000069d310001500000042d310002700000032d310001000000026d310000c00000018d310000e00000001d3100017000000f4d210000d000000ead210000a000000e1d2100009000000ced2100013000000acd21000220000009bd210001100000086d21000150000005dd210002900000021d210003c000000e2d110003f00000094d110004e00000050d110004400000020412070726f78792d64652d70616972696e672077617320617474656d7074656420746f20616e206163636f756e74207468617420776173206e6f74206163746976652e20412070726f78792d70616972696e672077617320617474656d7074656420746f20616e206163636f756e74207468617420776173206f70656e20746f20616e6f74686572206163636f756e742e20412070726f78792d70616972696e672077617320617474656d7074656420746f20616e206163636f756e74207468617420776173206e6f74206f70656e2e20546865206c6f636b206f6e20746865206163636f756e7420746f20626520756e6c6f636b656420686173206e6f742079657420657870697265642e2054686520746172676574206163636f756e7420646f6573206e6f7420686176652061206c6f636b2e204e6f2070726f706f73616c732077616974696e6720496e76616c696420707265696d61676520566f746520676976656e20666f7220696e76616c6964207265666572656e64756d20507265696d616765206e6f7420666f756e6420496d6d696e656e7420546f6f206561726c79204e6f7420696d6d696e656e7420507265696d61676520616c7265616479206e6f746564204e6f742064656c6567617465642057726f6e672070726f787920416c726561647920612070726f7879204964656e74697479206d6179206e6f74207665746f20612070726f706f73616c207477696365204e6f2065787465726e616c2070726f706f73616c20496e76616c69642068617368204e6578742065787465726e616c2070726f706f73616c206e6f742073696d706c65206d616a6f726974792050726f706f73616c207374696c6c20626c61636b6c69737465642050726f706f73616c20616c7265616479206d6164652043616e6e6f742063616e63656c207468652073616d652070726f706f73616c20747769636520556e6b6e6f776e20696e646578204e6f7420612070726f78792050726f706f73616c20646f6573206e6f742065786973742056616c756520746f6f206c6f77000000000000008cd4100004000000000000000000000090d410000e000000000000000a000000e70000000000000000000000a0d410000c000000000000006e6f64657375627374726174652d6e6f64650000df6acb689907609b0200000037e397fc7c91f5e40100000040fe3ad401f8959a04000000d2bc9897eed08f1501000000f78b278be53f454c02000000ed99c5acb25eedf502000000cbca25e39f14238701000000687ad44ad37f03c201000000bc9d89904f5b923f0100000068b66ba122c93fa70100000037c8bb1350a9a2a801000000ab3c0572291feb8b010000006772616e62616265696d6f6e617564690000000040787d010065cd1d00e1f505d85aae1ec0542205b0508f1f38e4750488467020d853e903603c5121d0bf760338323222a8591903402013236039cd02480ef423a82a8f0268f8d42470955c02b8dab525c05a3302d8c4962648bd1102e0b27727a855f601e8a05828e8fedf0180773929c0cacd01586d1a2af8f1be019053fb2a50d8b201d00edc2be0fca80138edbc2c48f2a001e06d9d2d80669a01c80d7e2e500f9501c0575e2f08b6900140323f30e0278d0148202031b0418a0108a3ff3120e8870120bedf32f0fb85013856c03398698401f0fda03478218301b8d87f35d8178201d8c26036183d8101b8223e37508d800188d21c38c8fc7f0168b5f93898877f01a829d139d8297f0120d6ab3ab8db7e0168ae803b389d7e0100ca9a3b68957e01000000000df31000060000000000000070000000000000000000000000000000000000000000000000000000000000007100000000000000000000000000000072000000000000000000000000000000730000000000000000000000000000007400000000000000000000000000000038e210000700000000000000750000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000770000000000000000000000000000007300000000000000000000000000000078000000000000000000000000000000aa8312000400000000000000790000000000000000000000000000000000000000000000000000000000000073000000000000000000000002000000000000000000000000000000000000007a000000000000000000000000000000730000000000000000000000000000005591120009000000000000007b000000000000000000000000000000000000000000000000000000000000007c000000000000000000000002000000000000000000000000000000000000007d00000000000000000000000000000073000000000000000000000000000000948312000a000000000000007e000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000020000000000000000000000000000000000000073000000000000000000000000000000800000000000000000000000000000009b6c120007000000000000008100000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000008300000000000000000000000000000073000000000000000000000000000000730000000000000000000000000000006791120008000000000000008400000000000000000000000000000000000000000000000000000000000000850000000000000000000000000000008600000000000000000000000000000087000000000000000000000000000000880000000000000000000000000000003fe210001200000000000000890000000000000000000000000000000000000000000000000000000200000000000000000000000000000002000000000000000000000000000000000000008a00000000000000000000000000000073000000000000000000000000000000eb90120007000000000000008b000000000000000000000000000000000000000000000000000000000000008c0000000000000000000000000000008d0000000000000000000000000000008e0000000000000000000000000000008f0000000000000000000000000000001c8f12000700000000000000900000000000000000000000000000000000000000000000000000000000000091000000000000000000000000000000920000000000000000000000000000009300000000000000000000000000000094000000000000000000000000000000128c1200090000000000000095000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000097000000000000000000000000000000980000000000000000000000000000009900000000000000000000000000000051e2100007000000000000009a000000000000000000000000000000000000000000000000000000000000009b0000000000000000000000000000009c000000000000000000000000000000730000000000000000000000000000009d00000000000000000000000000000058e2100012000000000000009e000000000000000000000000000000000000000000000000000000000000009b0000000000000000000000000000009c000000000000000000000000000000730000000000000000000000000000009d0000000000000000000000000000006ae2100009000000000000009f00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000a1000000000000000000000000000000a2000000000000000000000000000000a300000000000000000000000000000073e210001300000000000000a400000000000000000000000000000000000000000000000000000000000000a5000000000000000000000000000000a6000000000000000000000000000000730000000000000000000000000000007300000000000000000000000000000086e210000f000000020000000000000000000000000000000000000000000000000000000000000000000000a700000000000000000000000200000000000000000000000000000000000000a8000000000000000000000000000000a900000000000000000000000000000095e210000700000000000000aa00000000000000000000000000000000000000000000000000000000000000ab000000000000000000000000000000ac00000000000000000000000000000073000000000000000000000000000000ad000000000000000000000000000000809112000800000000000000ae00000000000000000000000000000000000000000000000000000000000000af000000000000000000000000000000b0000000000000000000000000000000b1000000000000000000000000000000b20000000000000000000000000000009ce210000900000000000000b300000000000000000000000000000000000000000000000000000000000000b4000000000000000000000000000000b5000000000000000000000000000000b6000000000000000000000000000000b7000000000000000000000000000000a43111000400000000000000b800000000000000000000000000000000000000000000000000000000000000b9000000000000000000000000000000ba00000000000000000000000000000073000000000000000000000000000000bb000000000000000000000000000000d38d12000800000000000000bc00000000000000000000000000000000000000000000000000000000000000bd000000000000000000000000000000be00000000000000000000000000000073000000000000000000000000000000bf0000000000000000000000000000007e8312001200000002000000000000000000000000000000000000000000000000000000000000000000000073000000000000000000000002000000000000000000000000000000000000007300000000000000000000000000000073000000000000000000000000000000ed8d12000800000000000000c00000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000c100000000000000000000000000000073000000000000000000000000000000730000000000000000000000000000005c9f11001800000000000000c20000000000000000000000000000000000000000000000000000000000000073000000000000000000000002000000000000000000000000000000000000007300000000000000000000000000000073000000000000000000000000000000a5e210000800000000000000c300000000000000000000000000000000000000000000000000000000000000c4000000000000000000000000000000c500000000000000000000000000000073000000000000000000000000000000c6000000000000000000000000000000c61a11000700000000000000c700000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000000000c9000000000000000000000000000000ca000000000000000000000000000000cb000000000000000000000000000000670b12000800000000000000cc00000000000000000000000000000000000000000000000000000000000000cd000000000000000000000000000000ce00000000000000000000000000000073000000000000000000000000000000cf000000000000000000000000000000ade210000700000000000000d000000000000000000000000000000000000000000000000000000000000000d1000000000000000000000000000000d2000000000000000000000000000000d3000000000000000000000000000000d400000000000000000000005574696c6974795472616e73616374696f6e5061796d656e74436f756e63696c546563686e6963616c436f6d6d6974746565456c656374696f6e73546563686e6963616c4d656d6265727368697046696e616c697479547261636b65724772616e647061436f6e7472616374734964656e7469747956657374696e676865617274626561744865617274626561744166746572000000000050e31000110000000000000064e310000100000000000000000000006ce3100001000000000000000000000074e310000700000000000000c8b012000000000000000000000000007ce3100001000000000000000000000084e310000b0000000000000090e3100001000000000000000000000098e310000100000000000000486561727462656174526563656976656400000069e410000b00000039e4100030000000416c6c476f6f640004e4100035000000536f6d654f66666c696e6500ece3100018000000a0e310004c0000002041742074686520656e64206f66207468652073657373696f6e2c206174206c65617374206f6e63652076616c696461746f722077617320666f756e6420746f206265206f66666c696e652e5665633c4964656e74696669636174696f6e5475706c653e2041742074686520656e64206f66207468652073657373696f6e2c206e6f206f6666656e63652077617320636f6d6d69747465642e2041206e657720686561727462656174207761732072656365697665642066726f6d2060417574686f72697479496460417574686f726974794964526563656e7448696e747366696e616c5f68696e74000000b4e2100009000000417574686f726564426c6f636b735570646174654f72646572656448696e74734d656469616e616c77617973206174206c65617374206f6e6520726563656e742073616d706c653b2071656483e510004c0000006d0000002b000000726563656e7420616e64206f72646572656420636f6e7461696e207468652073616d65206974656d733b2071656400003c00000004000000040000002e00000083e510004c000000780000001b0000007072756e696e672064696374617465642062792077696e646f775f73697a6520776869636820697320616c776179732073617475726174656420617420313b207165642f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f6672616d652f66696e616c6974792d747261636b65722f7372632f6c69622e7273004de6100016000000b9211200020000004de610001600000063e6100012000000696d6f6e6c696e6570616c6c65745f696d5f6f6e6c696e652f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f6672616d652f696d2d6f6e6c696e652f7372632f6c69622e7273536b697070696e6720686561727462656174206174202e204e6f7420612076616c696461746f722e00000087e710001c00000059e710002e00000027e710001a00000041e71000180000000be710000a00000015e7100012000000f3e6100018000000dde6100016000000c0e610001d0000004661696c656420746f206665746368206e6574776f726b2073746174654661696c656420746f2061637175697265206c6f636b4661696c656420746f207369676e20686561727462656174417574686f726974792020697320616c7265616479206f6e6c696e6548656172746265617420616c72656164792073656e74206174202e2057616974696e6720666f7220696e636c7573696f6e2e546f6f206561726c7920746f2073656e64206865617274626561742c206e657874206578706563746564206174204661696c656420746f207375626d6974207472616e73616374696f6e7061726974792f696d2d6f6e6c696e652d6865617274626561742f0000e0e7100008000000e8e710002000000008e810000b0000009d841200030000005b696e6465783a205d205265706f7274696e6720696d2d6f6e6c696e6520617420626c6f636b3a20202873657373696f6e3a2000c8b0120000000000c8b01200000000003c0000000400000004000000d50000003c0000000400000004000000d5000000506172656e7420686173682073686f756c642062652076616c69642e5472616e73616374696f6e207472696520726f6f74206d7573742062652076616c69642edbe8100032000000446967657374206974656d206d757374206d6174636820746861742063616c63756c617465642e53746f7261676520726f6f74206d757374206d6174636820746861742063616c63756c617465642e4e756d626572206f6620646967657374206974656d73206d757374206d6174636820746861742063616c63756c617465642e00000000000000b4e2100009000000000000003ce91000020000000000000000000000c8b01200000000000000000000000000b4e2100009000000000000006ce91000190000000000000085e910000a000000000000008fe910002f0000004865617274626561743c543a3a426c6f636b4e756d6265723e5f7369676e61747572653c543a3a417574686f7269747949642061732052756e74696d654170705075626c69633e3a3a5369676e6174757265000000000000bde210000e0000000000000000000000f50812000e00000000000000000000000000000000000000000000000000000000000000c8b01200a8eb1000000000000000000020eb1000060000000000000001000000000000009083120004000000000000000000000050eb10001300000000000000000000000000000000000000000000000000000000000000c8b0120064eb1000000000000000000074eb100001000000000000000100000000000000db8d1200120000000201010000000000179012000c000000000000007ceb1000090000000000000070a311000700000000000000c8b0120088eb1000000000000000000098eb10000200000000000000000000000000000094e410000e0000000201010000000000179012000c000000000000006c0f11000e00000000000000847212000300000000000000c8b01200a8eb10000000000000000000b8eb1000020000000000000001000000cfec10004c000000c8b01200000000001bed1000440000005fed10003400000093ed100040000000d3ed10004e0000005665633c543a3a417574686f7269747949643e003c0000000000000001000000590000009bec10003400000041757468496e6465780000003c0000000000000001000000510000003fec10003900000078ec1000230000003c00000000000000010000006b000000c8eb1000450000000dec10003200000020466f7220656163682073657373696f6e20696e6465782c207765206b6565702061206d617070696e67206f662060543a3a56616c696461746f7249646020746f20746865206e756d626572206f6620626c6f636b7320617574686f7265642062792074686520676976656e20617574686f726974792e20466f7220656163682073657373696f6e20696e6465782c207765206b6565702061206d617070696e67206f66206041757468496e6465786020746f20606f6666636861696e3a3a4f70617175654e6574776f726b5374617465602e205468652063757272656e7420736574206f66206b6579732074686174206d61792069737375652061206865617274626561742e2054686520626c6f636b206e756d6265722061667465722077686963682069742773206f6b20746f2073656e64206865617274626561747320696e2063757272656e742073657373696f6e2e2041742074686520626567696e6e696e67206f6620656163682073657373696f6e20776520736574207468697320746f20612076616c756520746861742073686f756c642066616c6c20726f7567686c7920696e20746865206d6964646c65206f66207468652073657373696f6e206475726174696f6e2e20546865206964656120697320746f206669727374207761697420666f72207468652076616c696461746f727320746f2070726f64756365206120626c6f636b20696e207468652063757272656e742073657373696f6e2c20736f20746861742074686520686561727462656174206c61746572206f6e2077696c6c206e6f74206265206e65636573736172792e000000000000007fe410000a0000000000000050ee100001000000000000000000000068ee1000020000000000000000000000d0ee10000400000000000000d4ee10001700000078ee10003d000000b5ee10001b0000002048696e7420746861742074686520617574686f72206f66207468697320626c6f636b207468696e6b732074686520626573742066696e616c697a656420626c6f636b2069732074686520676976656e206e756d6265722e68696e74436f6d706163743c543a3a426c6f636b4e756d6265723e00000000005cef10000a00000000000000f50812000e00000000000000c8b0120068ef1000000000000000000078ef100001000000000000000000000080ef10000d00000000000000f50812000e00000000000000c8b0120090ef10000000000000000000a0ef1000010000000000000057696e646f7753697a6500003c0000000000000001000000d6000000efef1000460000005265706f72744c6174656e63790000003c0000000000000001000000d7000000a8ef100047000000205468652064656c617920616674657220776869636820706f696e74207468696e6773206265636f6d6520737573706963696f75732e2044656661756c7420697320313030302e20546865206e756d626572206f6620726563656e742073616d706c657320746f206b6565702066726f6d207468697320636861696e2e2044656661756c74206973203130312e0000000100000001000000000000000000000000000000010000004475706c696361746564486561727462656174496e76616c69644b65790000000000000063f010000a00000000000000a8f0100001000000000000000000000050f010001300000000000000b0f010000100000000000000cef0100019000000b8f0100016000000204475706c696361746564206865617274626561742e204e6f6e206578697374656e74207075626c6963206b65792e416c72656164795570646174656442616448696e7400000000e7f010000e0000000000000034f11000010000000000000000000000f5f0100007000000000000003cf11000010000000000000068f110003200000044f11000240000002046696e616c697a6564206865696768742061626f766520626c6f636b206e756d6265722046696e616c2068696e74206d7573742062652075706461746564206f6e6c79206f6e636520696e2074686520626c6f636b617373657274696f6e206661696c65643a20696e646578203c3d206c656e617373657274696f6e206661696c65643a20696e646578203c206c656e4e6f6e5a65726f526566436f756e744e6f6e44656661756c74436f6d706f736974654661696c6564546f4578747261637452756e74696d6556657273696f6e537065634f72496d706c56657273696f6e4e656564546f496e637265617365496d706c56657273696f6e4e6f74416c6c6f776564546f44656372656173655370656356657273696f6e4e6f74416c6c6f776564546f4465637265617365496e76616c6964537065634e616d653a65787472696e7369635f696e64657866696c6c5f626c6f636b72656d61726b7365745f686561705f70616765737365745f636f64657365745f636f64655f776974686f75745f636865636b737365745f6368616e6765735f747269655f636f6e6669677365745f73746f726167656b696c6c5f73746f726167656b696c6c5f7072656669787375696369646553797374656d426c6f636b486173684e756d626572506172656e744861736845787472696e73696373526f6f74446967657374000000001cf4100010000000000000002cf4100001000000000000000000000034f410000100000000000000000000003cf410000f000000000000004cf410000200000000000000000000005cf4100001000000000000000000000064f410000b00000000000000c8b0120000000000000000000000000070f4100001000000000000000000000078f410000a000000000000005ce8110001000000000000000000000084f410000100000000000000000000008cf410000d000000000000005ce811000100000000000000000000009cf41000010000000000000045787472696e7369635375636365737300f510000c0000000cf510002500000045787472696e7369634661696c656400f2a512000d00000000f510000c000000ebf4100015000000436f64655570646174656400d6f41000150000004e65774163636f756e740000bbf410001b0000004b696c6c65644163636f756e74000000a4f410001700000020416e206163636f756e7420776173207265617065642e2041206e6577206163636f756e742077617320637265617465642e20603a636f6465602077617320757064617465642e20416e2065787472696e736963206661696c65642e4469737061746368496e666f20416e2065787472696e73696320636f6d706c65746564207375636365737366756c6c792e4e6f4b6579734475706c6963617465644b65794e6f4173736f63696174656456616c696461746f724964496e76616c696450726f6f663a73657373696f6e3a6b6579737365745f6b65797370757267655f6b6579734e6578744b65797300003c0000000400000004000000d80000003c0000000000000001000000400000005175657565644b6579734576656e74734576656e74546f70696373000000000090f210000a0000000000000084f710000100000000000000000000009cf710000100000000000000000000009af210000600000000000000a4f71000010000000000000000000000bcf71000010000000000000000000000a0f210000e00000000000000c4f71000010000000000000000000000dcf71000010000000000000000000000aef210000800000000000000e4f71000010000000000000000000000fcf71000010000000000000000000000b6f210001700000000000000e4f7100001000000000000000000000004f81000010000000000000000000000cdf2100017000000000000000cf8100001000000000000000000000024f81000010000000000000000000000e4f210000b000000000000002cf8100001000000000000000000000044f81000010000000000000000000000eff210000c000000000000004cf8100001000000000000000000000064f81000010000000000000000000000fbf210000b000000000000006cf8100001000000000000000000000084f8100001000000000000000000000006f310000700000000000000c8b012000000000000000000000000008cf8100002000000000000000000000023fb100006000000000000001858120007000000e1fa10004200000000000000dafa1000070000000000000070a3110007000000bffa10001b00000000000000bafa10000500000000000000a0711200030000007bfa10003f0000000000000077fa1000040000000000000070a31100070000005dfa10001a00000016fa10004700000000000000e3f910001300000000000000f6f9100020000000bbf910002800000000000000a9f910000500000000000000aef910000d0000008ef910001b0000000000000082f91000040000000000000086f910000800000064f910001e000000000000005ef910000600000000000000003211000300000019f91000450000009cf8100059000000f5f8100024000000204b696c6c207468652073656e64696e67206163636f756e742c20617373756d696e6720746865726520617265206e6f207265666572656e636573206f75747374616e64696e6720616e642074686520636f6d706f73697465206461746120697320657175616c20746f206974732064656661756c742076616c75652e204b696c6c20616c6c2073746f72616765206974656d7320776974682061206b657920746861742073746172747320776974682074686520676976656e207072656669782e707265666978204b696c6c20736f6d65206974656d732066726f6d2073746f726167652e6b6579735665633c4b65793e2053657420736f6d65206974656d73206f662073746f726167652e6974656d735665633c4b657956616c75653e2053657420746865206e6577206368616e676573207472696520636f6e66696775726174696f6e2e6368616e6765735f747269655f636f6e6669674f7074696f6e3c4368616e67657354726965436f6e66696775726174696f6e3e2053657420746865206e65772072756e74696d6520636f646520776974686f757420646f696e6720616e7920636865636b73206f662074686520676976656e2060636f6465602e2053657420746865206e65772072756e74696d6520636f64652e636f64652053657420746865206e756d626572206f6620706167657320696e2074686520576562417373656d626c7920656e7669726f6e6d656e74277320686561702e7061676573204d616b6520736f6d65206f6e2d636861696e2072656d61726b2e5f72656d61726b204120646973706174636820746861742077696c6c2066696c6c2074686520626c6f636b2077656967687420757020746f2074686520676976656e20726174696f2e5f726174696f0000000000000070b41100070000000101000000000000138212000c00000000000000fcff10002500000000000000000000000000000000000000c8b0120024001100000000000000000034001100010000000000000001000000000000003c0011000e0000000000000000000000847212000300000000000000000000000000000000000000000000000000000000000000c8b012008800110000000000000000004c0011000100000000000000000000000000000054001100130000000000000000000000670011000600000000000000000000000000000000000000000000000000000000000000c8b01200880011000000000000000000700011000100000000000000000000000000000078001100100000000000000000000000847212000300000000000000000000000000000000000000000000000000000000000000c8b01200880011000000000000000000980011000100000000000000000000000000000013f31000090000000101000000000000f50812000e00000000000000811312000700000000000000000000000000000000000000c8b01200e00011000000000000000000a000110001000000000000000100000000000000a80011000d000000010500000000000084721200030000000000000070a311000700000000000000000000000000000000000000c8b01200b80011000000000000000000c8001100010000000000000001000000000000001cf31000060000000000000000000000f50812000e00000000000000000000000000000000000000000000000000000000000000c8b01200cc0e11000000000000000000d00011000100000000000000010000000000000022f310000a0000000000000000000000811312000700000000000000000000000000000000000000000000000000000000000000c8b01200e00011000000000000000000d8001100010000000000000001000000000000002cf310000e0000000000000000000000811312000700000000000000000000000000000000000000000000000000000000000000c8b01200e00011000000000000000000f0001100010000000000000001000000000000003af31000060000000000000000000000f80011000b00000000000000000000000000000000000000000000000000000000000000c8b012000401110000000000000000001401110001000000000000000100000000000000baf510000600000000000000000000001c0111002300000000000000000000000000000000000000000000000000000000000000c8b012004001110000000000000000005001110001000000000000000100000000000000580111000a0000000000000000000000620111000a00000000000000000000000000000000000000000000000000000000000000c8b01200cc0e110000000000000000006c01110001000000000000000100000000000000c0f510000b0000000101000000000000811312000700000000000000740111002100000000000000000000000000000000000000c8b01200980111000000000000000000a80111000a000000000000000100000000000000f80111000f000000000000000000000000ee11000400000000000000000000000000000000000000000000000000000000000000c8b01200e40e11000000000000000000080211000100000000000000010000004163636f756e74496e666f3c543a3a496e6465782c20543a3a4163636f756e74446174613e0000003c0000000000000001000000d9000000e70611003a00000045787472696e736963436f756e740000b90611002e000000416c6c45787472696e736963735765696768745765696768740000007406110045000000416c6c45787472696e736963734c656e3c0000000000000001000000510000002406110050000000fe0511002600000045787472696e736963446174610000003c000000000000000100000059000000af0511004f0000006d05110042000000510511001c0000003c0000000000000001000000da0000000c051100450000004469676573744f663c543e003c000000000000000100000059000000d00411003c0000005665633c4576656e745265636f72643c543a3a4576656e742c20543a3a486173683e3e003c0000000000000001000000db000000a8041100280000004576656e74436f756e744576656e74496e6465787a0411002e0000005665633c28543a3a426c6f636b4e756d6265722c204576656e74496e646578293e0000003c00000000000000010000005900000048021100490000009102110025000000c8b0120000000000b6021100540000000a031100510000005b03110039000000c8b01200000000009403110053000000e7031100530000003a0411004000000052756e74696d655570677261646564001002110038000000204120626f6f6c20746f20747261636b206966207468652072756e74696d6520776173207570677261646564206c61737420626c6f636b2e204d617070696e67206265747765656e206120746f7069632028726570726573656e74656420627920543a3a486173682920616e64206120766563746f72206f6620696e6465786573206f66206576656e747320696e2074686520603c4576656e74733c543e3e60206c6973742e20416c6c20746f70696320766563746f727320686176652064657465726d696e69737469632073746f72616765206c6f636174696f6e7320646570656e64696e67206f6e2074686520746f7069632e205468697320616c6c6f7773206c696768742d636c69656e747320746f206c6576657261676520746865206368616e67657320747269652073746f7261676520747261636b696e67206d656368616e69736d20616e6420696e2063617365206f66206368616e67657320666574636820746865206c697374206f66206576656e7473206f6620696e7465726573742e205468652076616c756520686173207468652074797065206028543a3a426c6f636b4e756d6265722c204576656e74496e646578296020626563617573652069662077652075736564206f6e6c79206a7573742074686520604576656e74496e64657860207468656e20696e20636173652069662074686520746f70696320686173207468652073616d6520636f6e74656e7473206f6e20746865206e65787420626c6f636b206e6f206e6f74696669636174696f6e2077696c6c20626520747269676765726564207468757320746865206576656e74206d69676874206265206c6f73742e20546865206e756d626572206f66206576656e747320696e2074686520604576656e74733c543e60206c6973742e204576656e7473206465706f736974656420666f72207468652063757272656e7420626c6f636b2e20446967657374206f66207468652063757272656e7420626c6f636b2c20616c736f2070617274206f662074686520626c6f636b206865616465722e2045787472696e7369637320726f6f74206f66207468652063757272656e7420626c6f636b2c20616c736f2070617274206f662074686520626c6f636b206865616465722e2048617368206f66207468652070726576696f757320626c6f636b2e205468652063757272656e7420626c6f636b206e756d626572206265696e672070726f6365737365642e205365742062792060657865637574655f626c6f636b602e2045787472696e73696373206461746120666f72207468652063757272656e7420626c6f636b20286d61707320616e2065787472696e736963277320696e64657820746f206974732064617461292e204d6170206f6620626c6f636b206e756d6265727320746f20626c6f636b206861736865732e20546f74616c206c656e6774682028696e2062797465732920666f7220616c6c2065787472696e736963732070757420746f6765746865722c20666f72207468652063757272656e7420626c6f636b2e20546f74616c2077656967687420666f7220616c6c2065787472696e736963732070757420746f6765746865722c20666f72207468652063757272656e7420626c6f636b2e20546f74616c2065787472696e7369637320636f756e7420666f72207468652063757272656e7420626c6f636b2e205468652066756c6c206163636f756e7420696e666f726d6174696f6e20666f72206120706172746963756c6172206163636f756e742049442e4e6f646520697320636f6e6669677572656420746f20757365207468652073616d6520686173683b207165640000007007110042000000510300001c000000700711004200000059030000110000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f6672616d652f73797374656d2f7372632f6c69622e72730000cc07110023000000c8b0120000000000ef0711001e0000004552524f523a20436f727275707465642073746174653a206c696e6b6564206d6170203a206e6578742076616c756520646f65736e277420657869737420617420000000cc07110023000000c8b012000000000028081100220000003a2070726576696f75732076616c756520646f65736e2774206578697374206174200000cc07110023000000c8b0120000000000640811001e0000003a20686561642076616c756520646f65736e27742065786973742061742000000000000074f510000800000000000000dc0811000200000000000000000000000c0911000c00000000000000000000007cf510000a00000000000000c8b012000000000000000000000000006c0911000a000000000000000000000082f910000400000000000000290c11000700000000000000300c1100050000000000000070a3110007000000c10a11003a000000fb0a110048000000ef09110031000000c8b0120000000000200a110035000000c8b01200000000002a7f12000b000000430b110022000000650b1100160000007b0b110059000000d40b110055000000927f12000c000000bc09110033000000ef09110031000000c8b0120000000000200a110035000000c8b01200000000002a7f12000b000000550a11001f000000740a11001c000000900a110031000000927f12000c0000002052656d6f76657320616e792073657373696f6e206b6579287329206f66207468652066756e6374696f6e2063616c6c65722e205468697320646f65736e27742074616b652065666665637420756e74696c20746865206e6578742073657373696f6e2e20546865206469737061746368206f726967696e206f6620746869732066756e6374696f6e206d757374206265207369676e65642e202d204f284e2920696e206e756d626572206f66206b65792074797065732e202d2052656d6f766573204e202b203120444220656e74726965732e202d20526564756365732073797374656d206163636f756e742072656673206279206f6e65206f6e20737563636573732e2053657473207468652073657373696f6e206b6579287329206f66207468652066756e6374696f6e2063616c6c657220746f20606b657973602e20416c6c6f777320616e206163636f756e7420746f20736574206974732073657373696f6e206b6579207072696f7220746f206265636f6d696e6720612076616c696461746f722e202d204f286c6f67206e2920696e206e756d626572206f66206163636f756e74732e202d204f6e6520657874726120444220656e7472792e202d20496e637265617365732073797374656d206163636f756e742072656673206279206f6e65206f6e20737563636573732069666620746865726520776572652070726576696f75736c79206e6f206b657973207365742e202020496e207468697320636173652c2070757267655f6b6579732077696c6c206e65656420746f2062652063616c6c6564206265666f726520746865206163636f756e742063616e2062652072656d6f7665642e543a3a4b65797370726f6f6600000000000000252312000a0000000000000000000000a00e11001300000000000000000000000000000000000000000000000000000000000000c8b01200b40e11000000000000000000c40e110001000000000000000100000000000000238f12000c0000000000000000000000179012000c00000000000000000000000000000000000000000000000000000000000000c8b01200cc0e11000000000000000000dc0e1100010000000000000001000000000000002f8f12000d000000000000000000000000ee11000400000000000000000000000000000000000000000000000000000000000000c8b01200e40e11000000000000000000f40e110002000000000000000100000000000000b0f510000a0000000000000000000000040f11001e00000000000000000000000000000000000000000000000000000000000000c8b01200240f11000000000000000000340f1100020000000000000001000000000000003c8f1200120000000000000000000000083c12000800000000000000000000000000000000000000000000000000000000000000c8b01200440f11000000000000000000540f11000300000000000000010000000000000086f5100008000000020501000000000070a3110007000000000000006c0f11000e00000000000000290c11000700000000000000c8b012007c0f110000000000000000008c0f110004000000000000000000000000000000ac0f110008000000020501000000000070a311000700000000000000b40f110014000000000000006c0f11000e00000000000000c8b01200c80f11000000000000000000d80f11000400000000000000000000005665633c543a3a56616c696461746f7249643e003c0000000000000001000000590000009f1211001f0000003c00000000000000010000006b000000811211001e0000003c0000000000000001000000510000000a1211004e00000058121100290000005665633c28543a3a56616c696461746f7249642c20543a3a4b657973293e00003c000000000000000100000059000000831111004f000000d2111100380000003c0000000000000001000000590000001611110020000000c8b0120000000000361111004d000000543a3a56616c696461746f72496400003c000000000000000100000051000000ef10110027000000c8b0120000000000411011005600000097101100580000004b65794f776e6572284b65795479706549642c205665633c75383e293c000000000000000100000051000000f80f110049000000c8b01200000000004110110056000000971011005800000020546865206f776e6572206f662061206b65792e20546865207365636f6e64206b65792069732074686520604b657954797065496460202b2074686520656e636f646564206b65792e20546865206669727374206b657920697320616c77617973206044454455505f4b45595f5052454649586020746f206861766520616c6c20746865206461746120696e207468652073616d65206272616e6368206f662074686520747269652e20486176696e6720616c6c206461746120696e207468652073616d65206272616e63682073686f756c642070726576656e7420736c6f77696e6720646f776e206f7468657220717565726965732e20546865206e6578742073657373696f6e206b65797320666f7220612076616c696461746f722e20496e6469636573206f662064697361626c65642076616c696461746f72732e205468652073657420697320636c6561726564207768656e20606f6e5f73657373696f6e5f656e64696e67602072657475726e732061206e657720736574206f66206964656e7469746965732e2054686520717565756564206b65797320666f7220746865206e6578742073657373696f6e2e205768656e20746865206e6578742073657373696f6e20626567696e732c207468657365206b6579732077696c6c206265207573656420746f2064657465726d696e65207468652076616c696461746f7227732073657373696f6e206b6579732e20547275652069662074686520756e6465726c79696e672065636f6e6f6d6963206964656e746974696573206f7220776569676874696e6720626568696e64207468652076616c696461746f727320686173206368616e67656420696e20746865207175657565642076616c696461746f72207365742e2043757272656e7420696e646578206f66207468652073657373696f6e2e205468652063757272656e7420736574206f662076616c696461746f72732e000000000000f81211001000000000000000081311000500000000000000c8b0120010131100000000000000000020131100020000000000000044454455505f4b45595f505245464958265b75385d0000003c0000000000000001000000dc0000003013110059000000891311000d0000002055736564206173206669727374206b657920666f7220604e6578744b6579736020616e6420604b65794f776e65726020746f2070757420616c6c20746865206461746120696e746f207468652073616d65206272616e6368206f662074686520747269652e74686520636f6e74726163742065786973747320616e6420696e2074686520616c6976652073746174653b0a090974686520757064617465642062616c616e6365206d7573742062652067726561746572207468616e2073756273697374656e6365206465706f7369743b0a0909746869732066756e6374696f6e20646f65736e27742072657475726e20604e6f6e65603b0a09097165640a0909000000441411004600000074010000170000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f6672616d652f636f6e7472616374732f7372632f72656e742e7273436865636b56657273696f6e436865636b47656e65736973436865636b457261436865636b4e6f6e6365436865636b5765696768743a6865617070616765733a636f64653a6368616e6765735f74726965000000000071f210000f00000000000000a015110002000000000000000000000052f210001f00000000000000b015110002000000000000000000000033f210001f00000000000000c015110002000000000000000000000014f210001f00000000000000d0151100020000000000000000000000f7f110001d00000000000000e0151100030000000000000000000000e4f110001300000000000000f8151100010000000000000000000000d5f110000f000000000000000016110001000000000000003f18110045000000d917110015000000ee17110051000000d9171100150000008717110052000000d917110015000000151711004d0000006217110025000000961611003c000000c8b0120000000000d2161100430000005616110040000000081611004e0000002054686572652069732061206e6f6e2d7a65726f207265666572656e636520636f756e742070726576656e74696e6720746865206163636f756e742066726f6d206265696e67207075726765642e20537569636964652063616c6c6564207768656e20746865206163636f756e7420686173206e6f6e2d64656661756c7420636f6d706f7369746520646174612e204661696c656420746f2065787472616374207468652072756e74696d652076657273696f6e2066726f6d20746865206e65772072756e74696d652e204569746865722063616c6c696e672060436f72655f76657273696f6e60206f72206465636f64696e67206052756e74696d6556657273696f6e60206661696c65642e205468652073706563696669636174696f6e206f722074686520696d706c656d656e746174696f6e2076657273696f6e206e65656420746f20696e637265617365206265747765656e207468652063757272656e742072756e74696d6520616e6420746865206e65772072756e74696d652e2054686520696d706c656d656e746174696f6e2076657273696f6e206973206e6f7420616c6c6f77656420746f206465637265617365206265747765656e207468652063757272656e742072756e74696d6520616e6420746865206e65772072756e74696d652e205468652073706563696669636174696f6e2076657273696f6e206973206e6f7420616c6c6f77656420746f206465637265617365206265747765656e207468652063757272656e742072756e74696d6520546865206e616d65206f662073706563696669636174696f6e20646f6573206e6f74206d61746368206265747765656e207468652063757272656e742072756e74696d65000000005bf510000c00000000000000f418110001000000000000000000000044f510001700000000000000fc18110001000000000000000000000037f510000d000000000000000419110001000000000000000000000031f5100006000000000000000c1911000100000000000000801911001900000058191100280000003e1911001a000000141911002a000000204e6f206b65797320617265206173736f63696174656420776974682074686973206163636f756e742e2052656769737465726564206475706c6963617465206b65792e204e6f206173736f6369617465642076616c696461746f7220494420666f72206163636f756e742e20496e76616c6964206f776e6572736869702070726f6f662e526571756972655375646f7375646f7365745f6b65797375646f5f61730000000000003c1a11000500000000000000441a11000100000000000000000000004c1a1100010000000000000000000000541a11000a000000000000005ce81100010000000000000000000000601a1100010000000000000000000000681a11000a00000000000000441a11000100000000000000000000004c1a11000100000000000000537564696400000000ee110004000000ae1a1100180000004b65794368616e6765640000721a11003c0000005375646f4173446f6e6520546865207375646f6572206a757374207377697463686564206964656e746974793b20746865206f6c64206b657920697320737570706c6965642e2041207375646f206a75737420746f6f6b20706c6163652e536f63696574794d61784d656d62657273566f7465734e6f74486561644e6f74466f756e6465724e6f7443616e646964617465416c726561647943616e646964617465416c7265616479426964466f756e646572486561644e6f74566f756368696e67416c7265616479566f756368696e67496e73756666696369656e74506f74416c7265616479466f756e6465644e6f5061796f75744e6f7453757370656e64656453757370656e646564416c72656164794d656d626572426164506f736974696f6e626964756e626964766f756368746970756e766f756368646566656e6465725f766f74657061796f7574666f756e64756e666f756e646a756467655f73757370656e6465645f6d656d6265726a756467655f73757370656e6465645f63616e6469646174657365745f6d61785f6d656d62657273000000000000941e110007000000000000005ce811000100000000000000000000009c1e1100010000000000000000000000a41e110003000000000000004c261200020000000000000000000000a81e1100020000000000000000000000b81e11000500000000000000c01e1100030000000000000000000000d81e1100020000000000000000000000e81e110009000000000000005ce81100010000000000000000000000f41e1100010000000000000000000000fc1e110005000000000000005ce81100010000000000000000000000041f11000100000000000000000000000c1f110007000000000000005ce81100010000000000000000000000141f11000100000000000000000000001c1f11000800000000000000241f1100020000000000000000000000341f1100020000000000000000000000441f110018000000000000005c1f11000200000000000000000000006c1f1100010000000000000000000000741f110012000000000000005ce81100010000000000000000000000881f1100010000000000000000000000901f11000f000000000000005ce81100010000000000000000000000a01f1100010000000000000000000000a81f11000a000000000000005ce81100010000000000000000000000b41f1100010000000000000000000000bc1f110004000000000000002cc61100030000000000000000000000c01f1100010000000000000000000000c81f11000c000000000000005c1f1100020000000000000000000000d41f1100010000000000000000000000dc1f11000d00000000000000ec1f1100010000000000000000000000f41f1100010000000000000000000000fc1f110009000000000000005ce81100010000000000000000000000082011000100000000000000466f756e64656400592311002e00000042696400f2221100580000004a2311000f000000566f756368000000c26d1200090000009027120007000000c26d1200090000005e22110058000000b62211003c0000004175746f556e6269640000001c22110042000000556e626964000000f02111002c000000556e766f75636800b22111003e000000496e647563746564c26d120009000000a42111000e0000003121110056000000872111001d00000053757370656e6465644d656d6265724a756467656d656e74c26d12000900000000ee1100040000000e2111002300000043616e64696461746553757370656e6465640000ef2011001f0000004d656d62657253757370656e64656400d32011001c0000004368616c6c656e6765640000b62011001d000000566f74658620110030000000446566656e646572566f74654a2011003c0000004e65774d61784d656d6265727300000084721200030000002620110024000000556e666f756e646564000000102011001600000020536f636965747920697320756e666f756e6465642e2041206e6577206d6178206d656d62657220636f756e7420686173206265656e20736574204120766f746520686173206265656e20706c6163656420666f72206120646566656e64696e67206d656d6265722028766f7465722c20766f746529204120766f746520686173206265656e20706c61636564202863616e6469646174652c20766f7465722c20766f7465292041206d656d62657220686173206265656e206368616c6c656e6765642041206d656d62657220686173206265656e2073757370656e64656420412063616e64696461746520686173206265656e2073757370656e64656420412073757370656e646564206d656d62657220686173206265656e206a756467656420412067726f7570206f662063616e646964617465732068617665206265656e20696e6475637465642e205468652062617463682773207072696d617279206973207468652066697273742076616c75652c2074686520626174636820696e2066756c6c20697320746865207365636f6e642e5665633c4163636f756e7449643e20412063616e646964617465207761732064726f70706564202862792072657175657374206f662077686f20766f756368656420666f72207468656d292e20412063616e646964617465207761732064726f70706564202862792074686569722072657175657374292e20412063616e646964617465207761732064726f70706564202864756520746f20616e20657863657373206f66206269647320696e207468652073797374656d292e2041206d656d6265727368697020626964206a7573742068617070656e656420627920766f756368696e672e2054686520676976656e206163636f756e74206973207468652063616e646964617465277320494420616e64207468656972206f6666657220697320746865207365636f6e642e2054686520766f756368696e67207061727479206973207468652074686972642e2041206d656d6265727368697020626964206a7573742068617070656e65642e2054686520676976656e206163636f756e74206973207468652063616e646964617465277320494420616e64207468656972206f6666657220697320746865207365636f6e642e2054686520736f636965747920697320666f756e6465642062792074686520676976656e206964656e746974792e5072656d61747572655374696c6c4f70656e4e6f7446696e646572556e6b6e6f776e546970416c72656164794b6e6f776e526561736f6e546f6f426967496e76616c696450726f706f73616c496e646578496e73756666696369656e7450726f706f7365727342616c616e636570792f747273727970726f706f73655f7370656e6472656a6563745f70726f706f73616c617070726f76655f70726f706f73616c7265706f72745f617765736f6d65726574726163745f7469707469705f6e6577636c6f73655f7469700000000000000030ec1100080000000000000038261100010000000000000000000000402611000100000000000000000000004826110008000000000000005026110001000000000000000000000058261100010000000000000000000000602611000700000000000000682611000300000000000000000000008026110001000000000000000000000088261100080000000000000090261100020000000000000000000000a0261100010000000000000000000000a8261100050000000000000050261100010000000000000000000000b0261100010000000000000000000000b8261100080000000000000050261100010000000000000000000000c0261100010000000000000000000000589c1100070000000000000050261100010000000000000000000000c8261100010000000000000000000000d02611000600000000000000b0ec1100010000000000000000000000d8261100010000000000000000000000e02611000a00000000000000b0ec1100010000000000000000000000ec261100010000000000000000000000f426110009000000000000000027110003000000000000000000000018271100010000000000000000000000202711000c00000000000000b0ec11000100000000000000000000002c271100010000000000000055ef11000d000000ee2811000e0000005370656e64696e679027120007000000b42811003a000000417761726465640055ef11000d0000009027120007000000c26d120009000000942811002000000052656a656374656455ef11000d0000009027120007000000672811002d0000004275726e740000004428110023000000526f6c6c6f766572f82711004c000000d8271100200000004e65775469700000b227110026000000546970436c6f73696e6700007b27110037000000546970436c6f73656400000065ed110004000000c26d1200090000009027120007000000592711002200000054697052657472616374656434271100250000002041207469702073756767657374696f6e20686173206265656e207265747261637465642e2041207469702073756767657374696f6e20686173206265656e20636c6f7365642e2041207469702073756767657374696f6e206861732072656163686564207468726573686f6c6420616e6420697320636c6f73696e672e2041206e6577207469702073756767657374696f6e20686173206265656e206f70656e65642e20536f6d652066756e64732068617665206265656e206465706f73697465642e205370656e64696e67206861732066696e69736865643b20746869732069732074686520616d6f756e74207468617420726f6c6c73206f76657220756e74696c206e657874207370656e642e20536f6d65206f66206f75722066756e64732068617665206265656e206275726e742e20412070726f706f73616c207761732072656a65637465643b2066756e6473207765726520736c61736865642e20536f6d652066756e64732068617665206265656e20616c6c6f63617465642e205765206861766520656e6465642061207370656e6420706572696f6420616e642077696c6c206e6f7720616c6c6f636174652066756e64732e204e65772070726f706f73616c2e6164645f6d656d626572737761705f6d656d62657272657365745f6d656d626572736368616e67655f6b65797365745f7072696d65636c6561725f7072696d6500000000442a11000b00000000000000c8b01200000000000000000000000000502a1100010000000000000000000000582a11000d00000000000000c8b01200000000000000000000000000682a1100010000000000000000000000702a11000e00000000000000c8b01200000000000000000000000000802a1100010000000000000000000000882a11000c00000000000000c8b01200000000000000000000000000942a1100010000000000000000000000541a11000a00000000000000c8b012000000000000000000000000009c2a1100010000000000000000000000a42a11000500000000000000ac2a1100010000000000000000000000b42a110001000000000000004d656d626572416464656400e12b1100390000004d656d62657252656d6f766564000000a62b11003b0000004d656d626572735377617070656400006f2b1100370000004d656d626572735265736574292b110046000000072b11002200000044756d6d79000000d82a11002f000000bc2a11001c000000205068616e746f6d206d656d6265722c206e6576657220757365642e73705f7374643a3a6d61726b65723a3a5068616e746f6d446174613c284163636f756e7449642c204576656e74293e204f6e65206f6620746865206d656d6265727327206b657973206368616e6765642e20546865206d656d62657273686970207761732072657365743b2073656520746865207472616e73616374696f6e20666f722077686f20746865206e6577207365742069732e2054776f206d656d62657273207765726520737761707065643b2073656520746865207472616e73616374696f6e20666f722077686f2e2054686520676976656e206d656d626572207761732072656d6f7665643b2073656520746865207472616e73616374696f6e20666f722077686f2e2054686520676976656e206d656d626572207761732061646465643b2073656520746865207472616e73616374696f6e20666f722077686f2e496e636f6e73697374656e74207374617465202d20636f756c646e277420736574746c6520696d62616c616e636520666f722066756e6473207370656e74206279207472656173757279506f74736f63696574795f726f746174696f6e000000000000000000617474656d707420746f20646976696465206279207a65726f0000009c2d1100430000002d0600001d0000009c2d110043000000810400000f00000070792f736f6369657061796f757473652e31206f662066696e616c206974656d203d3d20746f74616c5f617070726f76616c733b20776f72737420636173652066696e642077696c6c20616c776179732072657475726e2074686174206974656d3b2071656400009c2d110043000000780500001f00000042696473657869746564206966206d656d6265727320656d7074793b207165649c2d110043000000970500001f000000446566656e646572446566656e646572566f746573736f63696574795f6368616c6c656e676500009c2d1100430000000e0600001e0000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f6672616d652f736f63696574792f7372632f6c69622e727353757370656e6465644d656d62657273537472696b65735061796f757473000000617474656d707420746f2063616c63756c617465207468652072656d61696e646572207769746820612064697669736f72206f66207a65726f0000009c2d110043000000880400000500000000000000a41911000400000000000000d02e1100010000000000000000000000e82e11000a0000000000000000000000a81911000700000000000000382f1100010000000000000000000000502f1100090000000000000000000000af1911000700000000000000982f1100020000000000000000000000c82f11000b0000000000000000000000fb8512000400000000000000500b120017000000563111004e000000c8b01200000000007881120034000000c8b01200000000002a7f12000b000000bc4812000800000085301100190000009e30110018000000b630110032000000927f12000c00000000000000108212000300000000000000203f120023000000e83011005d000000c8b01200000000007881120034000000c8b01200000000002a7f12000b000000bc4812000800000085301100190000004531110011000000927f12000c0000000000000097d211000300000000000000203f12002300000000000000fb8512000400000000000000500b12001700000020301100540000007430110011000000c8b01200000000007881120034000000c8b01200000000002a7f12000b000000bc4812000800000085301100190000009e30110018000000b630110032000000927f12000c0000002041757468656e7469636174657320746865207375646f206b657920616e64206469737061746368657320612066756e6374696f6e2063616c6c207769746820605369676e656460206f726967696e2066726f6d206120676976656e206163636f756e742e202d204c696d697465642073746f726167652072656164732e202d204f6e6520444220777269746520286576656e74292e202d20576569676874206f662064657269766174697665206063616c6c6020657865637574696f6e202b2031302c3030302e2041757468656e74696361746573207468652063757272656e74207375646f206b657920616e6420736574732074686520676976656e204163636f756e7449642028606e6577602920617320746865206e6577207375646f206b65792e202d204f6e65204442206368616e67652e2041757468656e7469636174657320746865207375646f206b657920616e64206469737061746368657320612066756e6374696f6e2063616c6c20776974682060526f6f7460206f726967696e2e5375646f0000000000321100030000000000000000000000138212000c00000000000000000000000000000000000000000000000000000000000000c8b01200043211000000000000000000143211000100000000000000010000004b6579003c0000000000000001000000dd0000001c321100210000002054686520604163636f756e74496460206f6620746865207375646f206b65792e000000000000008a1b1100030000000000000050341100010000000000000000000000683411002100000000000000000000008d1b110005000000000000007035110001000000000000000000000088351100130000000000000000000000921b1100050000000000000020361100030000000000000000000000683611002c00000000000000000000009a1b1100070000000000000070351100010000000000000000000000c8371100110000000000000000000000f3ea110004000000000000005038110002000000000000000000000080381100130000000000000000000000a11b11000d000000000000001839110001000000000000000000000030391100100000000000000000000000ae1b11000600000000000000c8b01200000000000000000000000000b0391100140000000000000000000000b41b11000500000000000000503a1100030000000000000000000000983a1100130000000000000000000000b91b11000700000000000000c8b01200000000000000000000000000303b11000d0000000000000000000000c01b11001600000000000000983b1100020000000000000000000000c83b11001b0000000000000000000000d61b11001900000000000000a03c1100020000000000000000000000d03c1100280000000000000000000000ef1b11000f00000000000000103e1100010000000000000000000000283e11000e00000000000000000000007c47120005000000000000006a5c11000f000000b45e110038000000c8b0120000000000ec5e11004e0000003a5f11003c000000c8b01200000000007881120034000000c8b012000000000007f811000c000000765f110056000000c8b01200000000002a7f12000b000000cc5f1100550000002758110011000000ac5811003b000000e7581100380000001f59110037000000565911003d00000038581100320000009359110012000000e859110060000000485a110040000000885a110017000000cf5a11004b0000001a5b1100310000004b5b11001e000000695b110027000000905b110048000000d85b11000a000000216011001a000000fa5b11003f000000c8b0120000000000395c110031000000927f12000c00000000000000b15e110003000000000000008472120003000000795c110036000000af5c110040000000ef5c110021000000c8b0120000000000105d11003f000000c8b01200000000004f5d110041000000c8b012000000000007f811000c000000905d110046000000c8b01200000000002a7f12000b000000d65d11002c000000025e110043000000455e110051000000857f12000d000000c8b0120000000000965e11001b000000927f12000c0000000000000097d211000300000000000000138212000c000000000000007c47120005000000000000006a5c11000f00000000000000971b110003000000000000006a5c11000f000000b954110051000000c8b01200000000000a551100550000005f55110057000000b655110050000000c8b012000000000006561100560000005c56110054000000c8b01200000000003b50110041000000c8b012000000000007f811000c000000b056110033000000e35611005400000037571100190000005057110052000000a257110045000000c8b01200000000002a7f12000b000000e757110040000000275811001100000038581100320000006a58110042000000ac5811003b000000e7581100380000001f59110037000000565911003d0000009359110012000000a559110043000000e859110060000000485a110040000000885a1100170000009f5a110030000000cf5a11004b0000001a5b1100310000004b5b11001e000000695b110027000000905b110048000000d85b11000a000000e25b110018000000fa5b11003f000000c8b0120000000000395c110031000000927f12000c000000e65211004b0000003153110025000000c8b0120000000000565311004a000000c8b012000000000007f811000c000000a05311004b000000c8b01200000000002a7f12000b000000eb531100150000000054110042000000425411003b0000007d54110025000000857f12000d000000c8b0120000000000a254110017000000927f12000c00000000000000dd5211000900000000000000203f1200230000000000000016141200070000000000000000ee1100040000009051110022000000c8b01200000000003b50110041000000c8b012000000000007f811000c000000b2511100430000007c5011003d000000f551110036000000c8b01200000000002a7f12000b0000002b5211002f000000fc501100470000005a52110016000000705211004b000000435111002f000000857f12000d000000c8b0120000000000bb52110022000000927f12000c0000000000000016141200070000000000000000ee1100040000001850110023000000c8b01200000000003b50110041000000c8b012000000000007f811000c0000007c5011003d000000b950110029000000c8b01200000000002a7f12000b000000e25011001a000000fc50110047000000435111002f000000857f12000d000000c8b0120000000000725111001e000000927f12000c000000204d110051000000c8b0120000000000714d11005a000000c8b0120000000000cb4d110048000000134e11001e000000c8b0120000000000314e110045000000764e110013000000c8b01200000000002a7f12000b000000894e110047000000d04e110049000000194f110039000000524f1100390000008b4f110023000000ae4f110044000000c8b0120000000000f24f110026000000927f12000c00000000000000094d11000700000000000000138212000c00000000000000104d11000b000000000000008472120003000000000000001b4d1100050000000000000070a3110007000000f04a110013000000c8b0120000000000034b11003c0000003f4b110046000000c8b0120000000000854b110047000000c8b012000000000007f811000c000000cc4b110046000000124c110045000000574c11003d000000c8b01200000000002a7f12000b000000944c110038000000cc4c11003d000000857f12000d000000c8b0120000000000a83f110017000000927f12000c000000e049110023000000c8b0120000000000034a1100570000005a4a110056000000b04a110008000000c8b01200000000002a7f12000b000000b84a11001a000000d24a11001e000000857f12000d000000c8b0120000000000a83f110017000000927f12000c0000000000000097d211000300000000000000138212000c00000000000000d9491100070000000000000000ee110004000000204611004b000000c8b01200000000006b46110056000000c146110033000000c8b0120000000000f4461100520000004647110040000000c8b01200000000009841110050000000c8b012000000000007f811000c000000864711002d000000b34711004d0000000048110049000000c8b01200000000002a7f12000b0000004948110029000000724811003e000000b04811005c0000000c4911003e0000004a491100510000007d451100350000009b4911001c000000c94511001f000000c8b0120000000000b749110022000000927f12000c0000000000000097d211000300000000000000138212000c000000000000000e46110009000000000000001746110009000000c23f11004d000000c8b01200000000000f40110057000000664011001d000000c8b01200000000008340110055000000d840110044000000c8b01200000000001c411100570000007341110025000000c8b01200000000009841110050000000c8b012000000000007f811000c000000e8411100300000001842110031000000c8b01200000000002a7f12000b000000494211003d000000864211003c000000c242110032000000f44211001000000004431100450000004943110037000000804311003a000000ba4311002d000000e7431100280000000f4411002c0000003b441100530000008e4411000f0000009d44110037000000d44411004b0000001f4511000e0000002d451100500000007d45110035000000b245110017000000c94511001f000000c8b0120000000000e845110026000000927f12000c00000000000000bf3f110003000000000000008472120003000000983e110047000000df3e11002d000000c8b01200000000000c3f110037000000c8b012000000000007f811000c000000433f110039000000c8b01200000000002a7f12000b0000007c3f11002c000000857f12000d000000c8b0120000000000a83f110017000000927f12000c00000020416c6c6f777320726f6f74206f726967696e20746f206368616e676520746865206d6178696d756d206e756d626572206f66206d656d6265727320696e20736f63696574792e204d6178206d656d6265727368697020636f756e74206d7573742062652067726561746572207468616e20312e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d7573742062652066726f6d205f524f4f545f2e202d20606d617860202d20546865206d6178696d756d206e756d626572206f66206d656d6265727320666f722074686520736f63696574792e202d204f6e652073746f7261676520777269746520746f2075706461746520746865206d61782e204f28312920546f74616c20436f6d706c65786974793a204f2831296d617820416c6c6f772073757370656e646564206a756467656d656e74206f726967696e20746f206d616b65206a756467656d656e74206f6e20612073757370656e6465642063616e6469646174652e20496620746865206a756467656d656e742069732060417070726f7665602c20776520616464207468656d20746f20736f63696574792061732061206d656d62657220776974682074686520617070726f707269617465207061796d656e7420666f72206a6f696e696e6720736f63696574792e20496620746865206a756467656d656e74206973206052656a656374602c2077652065697468657220736c61736820746865206465706f736974206f6620746865206269642c20676976696e67206974206261636b20746f2074686520736f63696574792074726561737572792c206f722077652062616e2074686520766f75636865722066726f6d20766f756368696e6720616761696e2e20496620746865206a756467656d656e7420697320605265626964602c20776520707574207468652063616e646964617465206261636b20696e207468652062696420706f6f6c20616e64206c6574207468656d20676f207468726f7567682074686520696e64756374696f6e2070726f6365737320616761696e2e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d7573742062652066726f6d20746865205f53757370656e73696f6e4a756467656d656e744f726967696e5f2e202d206077686f60202d205468652073757370656e6465642063616e64696461746520746f206265206a75646765642e202d20606a756467656d656e7460202d2060417070726f7665602c206052656a656374602c206f7220605265626964602e204b65793a204220286c656e206f662062696473292c204d20286c656e206f66206d656d62657273292c2058202862616c616e636520616374696f6e29202d204f6e652073746f72616765207265616420746f20636865636b206077686f6020697320612073757370656e6465642063616e6469646174652e202d204f6e652073746f726167652072656d6f76616c206f66207468652073757370656e6465642063616e6469646174652e202d20417070726f7665204c6f67696320092d204f6e652073746f72616765207265616420746f206765742074686520617661696c61626c6520706f7420746f2070617920757365727320776974682e204f28312920092d204f6e652073746f7261676520777269746520746f207570646174652074686520617661696c61626c6520706f742e204f28312920092d204f6e652073746f72616765207265616420746f20676574207468652063757272656e7420626c6f636b206e756d6265722e204f28312920092d204f6e652073746f72616765207265616420746f2067657420616c6c206d656d626572732e204f284d2920092d20557020746f206f6e6520756e726573657276652063757272656e637920616374696f6e2e20092d20557020746f2074776f206e65772073746f726167652077726974657320746f207061796f7574732e20092d20557020746f206f6e652073746f726167652077726974652077697468204f286c6f67204d292062696e6172792073656172636820746f206164642061206d656d62657220746f20736f63696574792e202d2052656a656374204c6f67696320092d20557020746f206f6e6520726570617472696174652072657365727665642063757272656e637920616374696f6e2e204f28582920092d20557020746f206f6e652073746f7261676520777269746520746f2062616e2074686520766f756368696e67206d656d6265722066726f6d20766f756368696e6720616761696e2e202d205265626964204c6f67696320092d2053746f72616765206d75746174652077697468204f286c6f672042292062696e6172792073656172636820746f20706c616365207468652075736572206261636b20696e746f20626964732e202d20557020746f206f6e65206164646974696f6e616c206576656e7420696620756e766f7563682074616b657320706c6163652e202d204f6e652073746f726167652072656d6f76616c2e202d204f6e65206576656e7420666f7220746865206a756467656d656e742e20546f74616c20436f6d706c65786974793a204f284d202b206c6f674d202b2042202b2058296a756467656d656e744a756467656d656e7420416c6c6f772073757370656e73696f6e206a756467656d656e74206f726967696e20746f206d616b65206a756467656d656e74206f6e20612073757370656e646564206d656d6265722e20496620612073757370656e646564206d656d62657220697320666f72676976656e2c2077652073696d706c7920616464207468656d206261636b2061732061206d656d6265722c206e6f7420616666656374696e6720616e79206f6620746865206578697374696e672073746f72616765206974656d7320666f722074686174206d656d6265722e20496620612073757370656e646564206d656d6265722069732072656a65637465642c2072656d6f766520616c6c206173736f6369617465642073746f72616765206974656d732c20696e636c7564696e67207468656972207061796f7574732c20616e642072656d6f766520616e7920766f7563686564206269647320746865792063757272656e746c7920686176652e202d206077686f60202d205468652073757370656e646564206d656d62657220746f206265206a75646765642e202d2060666f726769766560202d204120626f6f6c65616e20726570726573656e74696e672077686574686572207468652073757370656e73696f6e206a756467656d656e74206f726967696e202020202020202020202020202020666f726769766573202860747275656029206f722072656a6563747320286066616c7365602920612073757370656e646564206d656d6265722e204b65793a204220286c656e206f662062696473292c204d20286c656e206f66206d656d6265727329202d204f6e652073746f72616765207265616420746f20636865636b206077686f6020697320612073757370656e646564206d656d6265722e204f283129202d20557020746f206f6e652073746f72616765207772697465204f284d292077697468204f286c6f67204d292062696e6172792073656172636820746f206164642061206d656d626572206261636b20746f20736f63696574792e202d20557020746f20332073746f726167652072656d6f76616c73204f28312920746f20636c65616e20757020612072656d6f766564206d656d6265722e202d20557020746f206f6e652073746f72616765207772697465204f2842292077697468204f2842292073656172636820746f2072656d6f766520766f7563686564206269642066726f6d20626964732e202d204f6e652073746f726167652072656d6f76616c2e204f28312920546f74616c20436f6d706c65786974793a204f284d202b206c6f674d202b204229666f726769766520416e6e756c2074686520666f756e64696e67206f662074686520736f63696574792e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205369676e65642c20616e6420746865207369676e696e67206163636f756e74206d75737420626520626f7468207468652060466f756e6465726020616e6420746865206048656164602e205468697320696d706c6965732074686174206974206d6179206f6e6c7920626520646f6e65207768656e207468657265206973206f6e65206d656d6265722e202d2054776f2073746f72616765207265616473204f2831292e202d20466f75722073746f726167652072656d6f76616c73204f2831292e20466f756e642074686520736f63696574792e205468697320697320646f6e65206173206120646973637265746520616374696f6e20696e206f7264657220746f20616c6c6f7720666f7220746865206d6f64756c6520746f20626520696e636c7564656420696e746f20612072756e6e696e6720636861696e20616e642063616e206f6e6c7920626520646f6e65206f6e63652e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d7573742062652066726f6d20746865205f466f756e6465725365744f726967696e5f2e202d2060666f756e64657260202d20546865206669727374206d656d62657220616e642068656164206f6620746865206e65776c7920666f756e64656420736f63696574792e202d20606d61785f6d656d6265727360202d2054686520696e697469616c206d6178206e756d626572206f66206d656d6265727320666f722074686520736f63696574792e202d206072756c657360202d205468652072756c6573206f66207468697320736f636965747920636f6e6365726e696e67206d656d626572736869702e202d2054776f2073746f72616765206d75746174657320746f207365742060486561646020616e642060466f756e646572602e204f283129202d204f6e652073746f7261676520777269746520746f2061646420746865206669727374206d656d62657220746f20736f63696574792e204f283129666f756e6465726d61785f6d656d6265727372756c6573205472616e7366657220746865206669727374206d617475726564207061796f757420666f72207468652073656e64657220616e642072656d6f76652069742066726f6d20746865207265636f7264732e204e4f54453a20546869732065787472696e736963206e6565647320746f2062652063616c6c6564206d756c7469706c652074696d657320746f20636c61696d206d756c7469706c65206d617475726564207061796f7574732e205061796d656e743a20546865206d656d6265722077696c6c20726563656976652061207061796d656e7420657175616c20746f207468656972206669727374206d617475726564207061796f757420746f20746865697220667265652062616c616e63652e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e642061206d656d6265722077697468207061796f7574732072656d61696e696e672e204b65793a204d20286c656e206f66206d656d62657273292c205020286e756d626572206f66207061796f75747320666f72206120706172746963756c6172206d656d62657229202d204f6e652073746f726167652072656164204f284d2920616e64204f286c6f67204d292073656172636820746f20636865636b207369676e65722069732061206d656d6265722e202d204f6e652073746f726167652072656164204f28502920746f2067657420616c6c207061796f75747320666f722061206d656d6265722e202d204f6e652073746f726167652072656164204f28312920746f20676574207468652063757272656e7420626c6f636b206e756d6265722e202d204f6e652063757272656e6379207472616e736665722063616c6c2e204f285829202d204f6e652073746f72616765207772697465206f722072656d6f76616c20746f2075706461746520746865206d656d6265722773207061796f7574732e204f28502920546f74616c20436f6d706c65786974793a204f284d202b206c6f674d202b2050202b2058292041732061206d656d6265722c20766f7465206f6e2074686520646566656e6465722e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e642061206d656d6265722e202d2060617070726f7665603a204120626f6f6c65616e2077686963682073617973206966207468652063616e6469646174652073686f756c6420626520617070726f766564202860747275656029206f722072656a656374656420286066616c736560292e202d204b65793a204d20286c656e206f66206d656d6265727329202d204f6e652073746f726167652072656164204f284d2920616e64204f286c6f67204d292073656172636820746f20636865636b20757365722069732061206d656d6265722e202d204f6e652073746f7261676520777269746520746f2061646420766f746520746f20766f7465732e204f28312920546f74616c20436f6d706c65786974793a204f284d202b206c6f674d292041732061206d656d6265722c20766f7465206f6e20612063616e6469646174652e202d206063616e646964617465603a205468652063616e646964617465207468617420746865206d656d62657220776f756c64206c696b6520746f20626964206f6e2e2020202020202020202020202020617070726f766564202860747275656029206f722072656a656374656420286066616c736560292e204b65793a204320286c656e206f662063616e64696461746573292c204d20286c656e206f66206d656d6265727329202d204f6e65206163636f756e74206c6f6f6b75702e202d204f6e652073746f726167652072656164204f28432920616e64204f2843292073656172636820746f20636865636b2074686174207573657220697320612063616e6469646174652e20546f74616c20436f6d706c65786974793a204f284d202b206c6f674d202b20432963616e646964617465204173206120766f756368696e67206d656d6265722c20756e766f7563682061206269642e2054686973206f6e6c7920776f726b73207768696c6520766f75636865642075736572206973206f6e6c792061206269646465722028616e64206e6f7420612063616e646964617465292e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e64206120766f756368696e67206d656d6265722e202d2060706f73603a20506f736974696f6e20696e207468652060426964736020766563746f72206f6620746865206269642077686f2073686f756c6420626520756e766f75636865642e204b65793a204220286c656e206f66206269647329202d204f6e652073746f726167652072656164204f28312920746f20636865636b20746865207369676e6572206973206120766f756368696e67206d656d6265722e202d204f6e652073746f72616765206d757461746520746f20726574726965766520616e64207570646174652074686520626964732e204f284229202d204f6e6520766f756368696e672073746f726167652072656d6f76616c2e204f28312920546f74616c20436f6d706c65786974793a204f2842292041732061206d656d6265722c20766f75636820666f7220736f6d656f6e6520746f206a6f696e20736f636965747920627920706c6163696e67206120626964206f6e20746865697220626568616c662e205468657265206973206e6f206465706f73697420726571756972656420746f20766f75636820666f722061206e6577206269642c206275742061206d656d6265722063616e206f6e6c7920766f75636820666f72206f6e652062696420617420612074696d652e2049662074686520626964206265636f6d657320612073757370656e6465642063616e64696461746520616e6420756c74696d6174656c792072656a6563746564206279207468652073757370656e73696f6e206a756467656d656e74206f726967696e2c20746865206d656d6265722077696c6c2062652062616e6e65642066726f6d20766f756368696e6720616761696e2e204173206120766f756368696e67206d656d6265722c20796f752063616e20636c61696d206120746970206966207468652063616e6469646174652069732061636365707465642e2054686973207469702077696c6c2062652070616964206173206120706f7274696f6e206f66207468652072657761726420746865206d656d6265722077696c6c207265636569766520666f72206a6f696e696e672074686520736f63696574792e202d206077686f603a2054686520757365722077686f20796f7520776f756c64206c696b6520746f20766f75636820666f722e202d206076616c7565603a2054686520746f74616c2072657761726420746f2062652070616964206265747765656e20796f7520616e64207468652063616e6469646174652069662074686579206265636f6d652061206d656d62657220696e2074686520736f63696574792e202d2060746970603a20596f757220637574206f662074686520746f74616c206076616c756560207061796f7574207768656e207468652063616e64696461746520697320696e64756374656420696e746f2074686520736f63696574792e2054697073206c6172676572207468616e206076616c7565602077696c6c206265207361747572617465642075706f6e207061796f75742e204b65793a204220286c656e206f662062696473292c204320286c656e206f662063616e64696461746573292c204d20286c656e206f66206d656d6265727329202d2053746f726167652052656164733a20092d204f6e652073746f72616765207265616420746f20726574726965766520616c6c206d656d626572732e204f284d2920092d204f6e652073746f72616765207265616420746f20636865636b206d656d626572206973206e6f7420616c726561647920766f756368696e672e204f28312920092d204f6e652073746f72616765207265616420746f20636865636b20666f722073757370656e6465642063616e6469646174652e204f28312920092d204f6e652073746f72616765207265616420746f20636865636b20666f722073757370656e646564206d656d6265722e204f28312920092d204f6e652073746f72616765207265616420746f20726574726965766520616c6c2063757272656e7420626964732e204f28422920092d204f6e652073746f72616765207265616420746f20726574726965766520616c6c2063757272656e742063616e646964617465732e204f284329202d2053746f72616765205772697465733a20092d204f6e652073746f7261676520777269746520746f20696e7365727420766f756368696e672073746174757320746f20746865206d656d6265722e204f28312920092d204f6e652073746f72616765206d757461746520746f206164642061206e65772062696420746f2074686520766563746f72204f2842292028544f444f3a20706f737369626c65206f7074696d697a6174696f6e20772f20726561642920092d20557020746f206f6e652073746f726167652072656d6f76616c206966206269642e6c656e2829203e204d41585f4249445f434f554e542e204f283129202d204e6f7461626c6520436f6d7075746174696f6e3a20092d204f286c6f67204d292073656172636820746f20636865636b2073656e6465722069732061206d656d6265722e20092d204f2842202b2043202b206c6f67204d292073656172636820746f20636865636b2075736572206973206e6f7420616c726561647920612070617274206f6620736f63696574792e20092d204f286c6f672042292073656172636820746f20696e7365727420746865206e65772062696420736f727465642e202d2045787465726e616c204d6f64756c65204f7065726174696f6e733a20092d204f6e652062616c616e63652072657365727665206f7065726174696f6e2e204f28582920092d20557020746f206f6e652062616c616e636520756e72657365727665206f7065726174696f6e20696620626964732e6c656e2829203e204d41585f4249445f434f554e542e202d204576656e74733a20092d204f6e65206576656e7420666f7220766f7563682e20092d20557020746f206f6e65206576656e7420666f72204175746f556e626964206966206269642e6c656e2829203e204d41585f4249445f434f554e542e20546f74616c20436f6d706c65786974793a204f284d202b2042202b2043202b206c6f674d202b206c6f6742202b20582942616c616e63654f663c542c20493e2041206269646465722063616e2072656d6f76652074686569722062696420666f7220656e74727920696e746f20736f63696574792e20427920646f696e6720736f2c20746865792077696c6c20686176652074686569722063616e646964617465206465706f7369742072657475726e6564206f7220746865792077696c6c20756e766f75636820746865697220766f75636865722e205061796d656e743a2054686520626964206465706f73697420697320756e7265736572766564206966207468652075736572206d6164652061206269642e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e642061206269646465722e202d2060706f73603a20506f736974696f6e20696e207468652060426964736020766563746f72206f6620746865206269642077686f2077616e747320746f20756e6269642e204b65793a204220286c656e206f662062696473292c2058202862616c616e636520756e7265736572766529202d204f6e652073746f72616765207265616420616e6420777269746520746f20726574726965766520616e64207570646174652074686520626964732e204f284229202d20456974686572206f6e6520756e726573657276652062616c616e636520616374696f6e204f285829206f72206f6e6520766f756368696e672073746f726167652072656d6f76616c2e204f28312920546f74616c20436f6d706c65786974793a204f2842202b205829706f7320412075736572206f757473696465206f662074686520736f63696574792063616e206d616b6520612062696420666f7220656e7472792e205061796d656e743a206043616e6469646174654465706f736974602077696c6c20626520726573657276656420666f72206d616b696e672061206269642e2049742069732072657475726e6564207768656e2074686520626964206265636f6d65732061206d656d6265722c206f7220696620746865206269642063616c6c732060756e626964602e202d206076616c7565603a2041206f6e652074696d65207061796d656e74207468652062696420776f756c64206c696b6520746f2072656365697665207768656e206a6f696e696e672074686520736f63696574792e204b65793a204220286c656e206f662062696473292c204320286c656e206f662063616e64696461746573292c204d20286c656e206f66206d656d62657273292c2058202862616c616e636520726573657276652920092d204f6e65206576656e7420666f72206e6577206269642e0000000000131b1100070000000000000000000000138212000c00000000000000000000000000000000000000000000000000000000000000c8b01200c89111000000000000000000bc65110001000000000000000000000000000000c4651100050000000000000000000000811312000700000000000000000000000000000000000000000000000000000000000000c8b01200cc6511000000000000000000dc651100020000000000000000000000000000008cc811000a0000000000000000000000ec6511002700000000000000000000000000000000000000000000000000000000000000c8b01200c0661100000000000000000014661100010000000000000001000000000000001c661100130000000101000000000000138212000c000000000000002f6611003900000000000000000000000000000000000000c8b012006866110000000000000000007866110001000000000000000000000000000000642c11000300000000000000000000006a5c11000f00000000000000000000000000000000000000000000000000000000000000c8b0120080661100000000000000000090661100010000000000000001000000000000001a1b1100040000000000000000000000138212000c00000000000000000000000000000000000000000000000000000000000000c8b01200c8911100000000000000000098661100010000000000000000000000000000006bef1100070000000000000000000000e03c12001100000000000000000000000000000000000000000000000000000000000000c8b01200b09111000000000000000000a066110001000000000000000100000000000000df2d1100100000000101000000000000138212000c0000000000000000ee11000400000000000000000000000000000000000000c8b01200a86611000000000000000000b866110001000000000000000100000000000000342d1100040000000000000000000000ec6511002700000000000000000000000000000000000000000000000000000000000000c8b01200c06611000000000000000000d066110001000000000000000100000000000000d8661100080000000101000000000000138212000c00000000000000e06611000e00000000000000000000000000000000000000c8b01200f066110000000000000000000067110001000000000000000000000000000000f62d1100070000000101000000000000138212000c00000000000000086711002600000000000000000000000000000000000000c8b012003067110000000000000000004067110001000000000000000100000000000000ef2d1100070000000101000000000000138212000c00000000000000486711000b00000000000000000000000000000000000000c8b012004881110000000000000000005467110001000000000000000100000000000000d71a1100050000000205050000000000138212000c00000000000000138212000c00000000000000bc1f11000400000000000000c8b012006c67110000000000000000005c67110001000000000000000000000000000000642d1100080000000000000000000000138212000c00000000000000000000000000000000000000000000000000000000000000c8b01200c8911100000000000000000064671100010000000000000000000000000000006c2d11000d0000000105000000000000138212000c00000000000000bc1f11000400000000000000000000000000000000000000c8b012006c67110000000000000000007c67110001000000000000000000000000000000cd1a11000a0000000000000000000000847212000300000000000000000000000000000000000000000000000000000000000000c8b0120048811100000000000000000084671100010000000000000001000000e26a11001200000052756c65730000003c000000000000000100000051000000796a110054000000cd6a1100150000005665633c4269643c543a3a4163636f756e7449642c2042616c616e63654f663c542c20493e3e3e002b6a11004e00000053757370656e64656443616e646964617465732842616c616e63654f663c542c20493e2c204269644b696e643c543a3a4163636f756e7449642c2042616c616e63654f663c542c20493e3e293c0000000000000001000000510000000a6a1100210000003c0000000000000001000000de000000ba69110050000000806911003a0000005b691100250000003c0000000000000001000000510000003d6911001e0000003c000000000000000100000059000000036911003a000000566f756368696e67566f756368696e6753746174757300003c000000000000000100000051000000ca681100390000005665633c28543a3a426c6f636b4e756d6265722c2042616c616e63654f663c542c20493e293e00003c0000000000000001000000590000007768110053000000537472696b65436f756e740040681100370000000c68110034000000db671100310000003c000000000000000100000051000000c3671100180000008c6711003700000020546865206d6178206e756d626572206f66206d656d6265727320666f722074686520736f6369657479206174206f6e652074696d652e20566f74657320666f722074686520646566656e6465722e2054686520646566656e64696e67206d656d6265722063757272656e746c79206265696e67206368616c6c656e6765642e20446f75626c65206d61702066726f6d2043616e646964617465202d3e20566f746572202d3e20284d617962652920566f74652e20546865206f6e676f696e67206e756d626572206f66206c6f73696e6720766f746573206361737420627920746865206d656d6265722e2050656e64696e67207061796f7574733b206f72646572656420627920626c6f636b206e756d6265722c20776974682074686520616d6f756e7420746861742073686f756c642062652070616964206f75742e204d656d626572732063757272656e746c7920766f756368696e67206f722062616e6e65642066726f6d20766f756368696e6720616761696e205468652063757272656e7420626964732c2073746f726564206f726465726564206279207468652076616c7565206f6620746865206269642e2054686520736574206f662073757370656e646564206d656d626572732e205468652063757272656e7420736574206f66206d656d626572732c206f7264657265642e20546865206d6f7374207072696d6172792066726f6d20746865206d6f737420726563656e746c7920617070726f766564206d656d626572732e20416d6f756e74206f66206f7572206163636f756e742062616c616e63652074686174206973207370656369666963616c6c7920666f7220746865206e65787420726f756e642773206269642873292e2054686520736574206f662073757370656e6465642063616e646964617465732e205468652063757272656e7420736574206f662063616e646964617465733b206269646465727320746861742061726520617474656d7074696e6720746f206265636f6d65206d656d626572732e20412068617368206f66207468652072756c6573206f66207468697320736f636965747920636f6e6365726e696e67206d656d626572736869702e2043616e206f6e6c7920626520736574206f6e636520616e64206f6e6c792062792074686520666f756e6465722e20546865206669727374206d656d6265722e00000000446c110010000000000000006a5c11000f00000000000000c8b01200546c11000000000000000000646c11000100000000000000000000006c6c110012000000000000006a5c11000f00000000000000c8b01200806c11000000000000000000906c1100020000000000000000000000a06c11000a00000000000000847212000300000000000000c8b01200ac6c11000000000000000000bc6c1100020000000000000000000000cc6c11000b000000000000006a5c11000f00000000000000c8b01200d86c11000000000000000000e86c1100010000000000000000000000f06c11000e00000000000000f50812000e00000000000000c8b01200006d11000000000000000000106d1100010000000000000000000000186d11000f00000000000000f50812000e00000000000000c8b01200286d11000000000000000000386d1100010000000000000043616e6469646174654465706f7369743c0000000000000001000000df000000036f11003f00000057726f6e6753696465446564756374696f6e00003c0000000000000001000000e00000007e6e110055000000d36e1100300000004d6178537472696b657300003c0000000000000001000000e1000000036e11005d000000606e11001e000000506572696f645370656e64003c0000000000000001000000e2000000b86d11004b000000526f746174696f6e506572696f6400003c0000000000000001000000e3000000746d1100440000004368616c6c656e6765506572696f64003c0000000000000001000000e4000000406d11003400000020546865206e756d626572206f6620626c6f636b73206265747765656e206d656d62657273686970206368616c6c656e6765732e20546865206e756d626572206f6620626c6f636b73206265747765656e2063616e6469646174652f6d656d6265727368697020726f746174696f6e20706572696f64732e2054686520616d6f756e74206f6620696e63656e7469766520706169642077697468696e206561636820706572696f642e20446f65736e277420696e636c75646520566f7465725469702e20546865206e756d626572206f662074696d65732061206d656d626572206d617920766f7465207468652077726f6e672077617920286f72206e6f7420617420616c6c2c207768656e207468657920617265206120736b657074696329206265666f72652074686579206265636f6d652073757370656e6465642e2054686520616d6f756e74206f662074686520756e70616964207265776172642074686174206765747320646564756374656420696e207468652063617365207468617420656974686572206120736b657074696320646f65736e277420766f7465206f7220736f6d656f6e6520766f74657320696e207468652077726f6e67207761792e20546865206d696e696d756d20616d6f756e74206f662061206465706f73697420726571756972656420666f7220612062696420746f206265206d6164652e000000000000fc2311000d00000000000000a4701100020000000000000000000000d4701100090000000000000000000000092411000f000000000000001c711100010000000000000000000000347111000700000000000000000000001824110010000000000000001c7111000100000000000000000000006c711100080000000000000000000000282411000e00000000000000ac711100020000000000000000000000dc711100130000000000000000000000362411000b00000000000000747211000100000000000000000000008c721100130000000000000000000000412411000700000000000000247311000300000000000000000000006c731100130000000000000000000000971b11000300000000000000047411000200000000000000000000003474110013000000000000000000000048241100090000000000000074721100010000000000000000000000cc7411000e00000000000000000000007c4712000500000000000000814712001500000000000000847f11000b00000000000000203f120023000000b27e11004b000000fd7e11004d0000004a7f110015000000c8b01200000000002a7f12000b000000bc4812000800000085301100190000005f7f110025000000927f12000c00000000000000a77e11000b000000000000008813120016000000587e11003f000000c8b01200000000002a7f12000b000000bc481200080000008530110019000000977e110010000000927f12000c000000d67d1100570000002d7e11002b000000c8b01200000000002a7f12000b000000bc4812000800000085301100190000004531110011000000927f12000c00000000000000ed7a1100060000000000000070a31100070000000000000097d211000300000000000000138212000c000000a77c110057000000c8b01200000000007881120034000000c8b0120000000000fe7c110055000000537d110035000000c8b012000000000041791100580000009979110017000000b07911003b000000c8b0120000000000eb7911001e000000c8b01200000000002a7f12000b000000887d1100270000005d7c110019000000af7d110027000000857f12000d000000927f12000c00000000000000f778110004000000000000008113120007000000f37a110055000000c8b0120000000000487b110038000000c8b0120000000000807b110054000000d47b110051000000257c110014000000c8b01200000000009a75110059000000f375110058000000c8b0120000000000397c110024000000c8b01200000000002a7f12000b0000004b761100090000005d7c110019000000767c110031000000857f12000d000000927f12000c00000000000000ed7a1100060000000000000070a31100070000000000000097d211000300000000000000138212000c00000000000000fb7811000900000000000000845712000c000000047911003d000000c8b0120000000000dc76110055000000317711001d000000c8b012000000000041791100580000009979110017000000b07911003b000000b4771100540000000878110036000000c8b0120000000000eb7911001e000000c8b01200000000002a7f12000b000000097a110050000000597a110051000000aa7a110043000000857f12000d000000927f12000c00000000000000f77811000400000000000000811312000700000000000000fb7811000900000000000000845712000c000000af7611002d000000c8b0120000000000dc76110055000000317711001d000000c8b01200000000009a751100590000004e77110058000000a67711000e000000b4771100540000000878110036000000c8b01200000000003e78110059000000977811000d000000c8b01200000000002a7f12000b0000004b76110009000000a478110040000000e478110013000000927f12000c0000003c75110018000000c8b01200000000007881120034000000c8b01200000000005475110046000000c8b01200000000009a75110059000000f375110058000000c8b01200000000002a7f12000b0000004b7611000900000054761100390000008d76110022000000927f12000c00000020436c6f736520616e64207061796f75742061207469702e2054686520746970206964656e74696669656420627920606861736860206d75737420686176652066696e69736865642069747320636f756e74646f776e20706572696f642e202d206068617368603a20546865206964656e74697479206f6620746865206f70656e2074697020666f722077686963682061207469702076616c7565206973206465636c617265642e205468697320697320666f726d65642020206173207468652068617368206f6620746865207475706c65206f6620746865206f726967696e616c207469702060726561736f6e6020616e64207468652062656e6566696369617279206163636f756e742049442e202d20604f28542960202d204f6e652073746f726167652072657472696576616c2028636f64656320604f285429602920616e642074776f2072656d6f76616c732e202d20557020746f2074687265652062616c616e6365206f7065726174696f6e732e204465636c6172652061207469702076616c756520666f7220616e20616c72656164792d6f70656e207469702e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e6420746865207369676e696e67206163636f756e74206d7573742062652061206d656d626572206f662074686520605469707065727360207365742e2020206173207468652068617368206f6620746865207475706c65206f66207468652068617368206f6620746865206f726967696e616c207469702060726561736f6e6020616e64207468652062656e65666963696172792020206163636f756e742049442e202d20607469705f76616c7565603a2054686520616d6f756e74206f66207469702074686174207468652073656e64657220776f756c64206c696b6520746f20676976652e20546865206d656469616e2074697020202076616c7565206f662061637469766520746970706572732077696c6c20626520676976656e20746f20746865206077686f602e20456d6974732060546970436c6f73696e676020696620746865207468726573686f6c64206f66207469707065727320686173206265656e207265616368656420616e642074686520636f756e74646f776e20706572696f642068617320737461727465642e202d204f6e652073746f72616765206d75746174696f6e2028636f64656320604f28542960292c206f6e652073746f72616765207265616420604f283129602e202d20557020746f206f6e65206576656e742e686173687469705f76616c7565204769766520612074697020666f7220736f6d657468696e67206e65773b206e6f2066696e6465722773206665652077696c6c2062652074616b656e2e202d2060726561736f6e603a2054686520726561736f6e20666f722c206f7220746865207468696e6720746861742064657365727665732c20746865207469703b2067656e6572616c6c7920746869732077696c6c20626520202061205554462d382d656e636f6465642055524c2e202d206077686f603a20546865206163636f756e742077686963682073686f756c6420626520637265646974656420666f7220746865207469702e20456d69747320604e657754697060206966207375636365737366756c2e202d20604f2852202b2054296020776865726520605260206c656e677468206f662060726561736f6e602c2060546020697320746865206e756d626572206f6620746970706572732e206054602069732020206e61747572616c6c79206361707065642061732061206d656d62657273686970207365742c20605260206973206c696d69746564207468726f756768207472616e73616374696f6e2d73697a652e202d2054776f2073746f7261676520696e73657274696f6e732028636f6465637320604f285229602c20604f28542960292c206f6e65207265616420604f283129602e726561736f6e20526574726163742061207072696f72207469702d7265706f72742066726f6d20607265706f72745f617765736f6d65602c20616e642063616e63656c207468652070726f63657373206f662074697070696e672e204966207375636365737366756c2c20746865206f726967696e616c206465706f7369742077696c6c20626520756e72657365727665642e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e642074686520746970206964656e74696669656420627920606861736860206d7573742068617665206265656e207265706f7274656420627920746865207369676e696e67206163636f756e74207468726f75676820607265706f72745f617765736f6d65602028616e64206e6f74207468726f75676820607469705f6e657760292e20456d697473206054697052657472616374656460206966207375636365737366756c2e202d204f6e652062616c616e6365206f7065726174696f6e2e202d2054776f2073746f726167652072656d6f76616c7320286f6e6520726561642c20636f64656320604f28542960292e205265706f727420736f6d657468696e672060726561736f6e60207468617420646573657276657320612074697020616e6420636c61696d20616e79206576656e7475616c207468652066696e6465722773206665652e205061796d656e743a20605469705265706f72744465706f73697442617365602077696c6c2062652072657365727665642066726f6d20746865206f726967696e206163636f756e742c2061732077656c6c20617320605469705265706f72744465706f736974506572427974656020666f722065616368206279746520696e2060726561736f6e602e202d20604f2852296020776865726520605260206c656e677468206f662060726561736f6e602e202d204f6e652073746f72616765206d75746174696f6e2028636f64656320604f28522960292e20417070726f766520612070726f706f73616c2e2041742061206c617465722074696d652c207468652070726f706f73616c2077696c6c20626520616c6c6f636174656420746f207468652062656e656669636961727920616e6420746865206f726967696e616c206465706f7369742077696c6c2062652072657475726e65642e2052656a65637420612070726f706f736564207370656e642e20546865206f726967696e616c206465706f7369742077696c6c20626520736c61736865642e202d204f6e6520444220636c6561722e70726f706f73616c5f69642050757420666f727761726420612073756767657374696f6e20666f72207370656e64696e672e2041206465706f7369742070726f706f7274696f6e616c20746f207468652076616c756520697320726573657276656420616e6420736c6173686564206966207468652070726f706f73616c2069732072656a65637465642e2049742069732072657475726e6564206f6e6365207468652070726f706f73616c20697320617761726465642e202d204f6e65204442206368616e67652c206f6e6520657874726120444220656e7472792e62656e65666963696172790000000000889112000d000000000000000000000055ef11000d00000000000000000000000000000000000000000000000000000000000000c8b01200488111000000000000000000588111000100000000000000010000000000000062ef110009000000010100000000000055ef11000d00000000000000608111002400000000000000000000000000000000000000c8b012008481110000000000000000009481110001000000000000000000000000000000959112000900000000000000000000009c8111001200000000000000000000000000000000000000000000000000000000000000c8b01200b08111000000000000000000c081110001000000000000000100000000000000c8811100040000000105000000000000811312000700000000000000cc8111003c00000000000000000000000000000000000000c8b01200c8911100000000000000000008821100030000000000000000000000000000002082110007000000010500000000000081131200070000000000000070a311000700000000000000000000000000000000000000c8b01200288211000000000000000000388211000200000000000000000000003c00000000000000010000006b000000148411002900000050726f706f73616c3c543a3a4163636f756e7449642c2042616c616e63654f663c543e3e3c000000000000000100000051000000f58311001f0000005665633c50726f706f73616c496e6465783e00003c000000000000000100000059000000b78311003e000000546970734f70656e5469703c543a3a4163636f756e7449642c2042616c616e63654f663c543e2c20543a3a426c6f636b4e756d6265722c20543a3a486173683ef282110056000000488311004f0000009783110020000000526561736f6e73003c00000000000000010000005d00000048821100520000009a821100580000002053696d706c6520707265696d616765206c6f6f6b75702066726f6d2074686520726561736f6e2773206861736820746f20746865206f726967696e616c20646174612e20416761696e2c2068617320616e20696e73656375726520656e756d657261626c6520686173682073696e636520746865206b65792069732067756172616e7465656420746f2062652074686520726573756c74206f6620612073656375726520686173682e2054697073207468617420617265206e6f742079657420636f6d706c657465642e204b65796564206279207468652068617368206f66206028726561736f6e2c2077686f29602066726f6d207468652076616c75652e2054686973206861732074686520696e73656375726520656e756d657261626c6520686173682066756e6374696f6e2073696e636520746865206b657920697473656c6620697320616c72656164792067756172616e7465656420746f20626520612073656375726520686173682e2050726f706f73616c20696e646963657320746861742068617665206265656e20617070726f76656420627574206e6f742079657420617761726465642e2050726f706f73616c7320746861742068617665206265656e206d6164652e204e756d626572206f662070726f706f73616c7320746861742068617665206265656e206d6164652e00000000000000008611000c000000000000000c8611000700000000000000c8b0120014861100000000000000000024861100020000000000000000000000348611001300000000000000845712000c00000000000000c8b01200e4861100000000000000000048861100010000000000000000000000508611000b00000000000000f50812000e00000000000000c8b012008c86110000000000000000005c8611000100000000000000000000006486110004000000000000000c8611000700000000000000c8b0120068861100000000000000000078861100010000000000000000000000808611000c00000000000000f50812000e00000000000000c8b012008c86110000000000000000009c861100010000000000000000000000a48611000d00000000000000b18611000700000000000000c8b01200b88611000000000000000000c8861100010000000000000000000000d08611001400000000000000845712000c00000000000000c8b01200e48611000000000000000000f4861100010000000000000000000000fc8611001700000000000000845712000c00000000000000c8b0120014871100000000000000000024871100010000000000000050726f706f73616c426f6e645065726d696c6c003c0000000000000001000000e5000000f8881100550000004d8911004400000050726f706f73616c426f6e644d696e696d756d00a6881100520000005370656e64506572696f640084881100220000004275726e3c0000000000000001000000e60000004088110044000000546970436f756e74646f776e3c0000000000000001000000e7000000ef8711005100000054697046696e6465727346656550657263656e743c0000000000000001000000e8000000a38711004c0000005469705265706f72744465706f736974426173653c0000000000000001000000610000006e871100350000005469705265706f72744465706f73697450657242797465003c0000000000000001000000650000002c871100420000002054686520616d6f756e742068656c64206f6e206465706f7369742070657220627974652077697468696e2074686520746970207265706f727420726561736f6e2e2054686520616d6f756e742068656c64206f6e206465706f73697420666f7220706c6163696e67206120746970207265706f72742e2054686520616d6f756e74206f66207468652066696e616c2074697020776869636820676f657320746f20746865206f726967696e616c207265706f72746572206f6620746865207469702e2054686520706572696f6420666f722077686963682061207469702072656d61696e73206f70656e20616674657220697320686173206163686965766564207468726573686f6c6420746970706572732e2050657263656e74616765206f662073706172652066756e64732028696620616e7929207468617420617265206275726e7420706572207370656e6420706572696f642e20506572696f64206265747765656e2073756363657373697665207370656e64732e204d696e696d756d20616d6f756e74206f662066756e647320746861742073686f756c6420626520706c6163656420696e2061206465706f73697420666f72206d616b696e6720612070726f706f73616c2e204672616374696f6e206f6620612070726f706f73616c27732076616c756520746861742073686f756c6420626520626f6e64656420696e206f7264657220746f20706c616365207468652070726f706f73616c2e20416e2061636365707465642070726f706f73616c2067657473207468657365206261636b2e20412072656a65637465642070726f706f73616c20646f6573206e6f742e6d656d6f727976616c69646174696f6e3a20696d706f727420656e74727920706f696e747320746f2061206e6f6e2d6578697374656e74207479706543616e6e6f7420696d706f727420676c6f62616c736d6f64756c6520696d706f7274732061206e6f6e2d6578697374656e742066756e6374696f6e6d6f64756c6520696d706f72747320606578745f7072696e746c6e60206275742064656275672066656174757265732064697361626c656443616e6e6f7420696d706f7274207461626c65736d6f64756c652068617320696d706f7274732066726f6d2061206e6f6e2d27656e7627206e616d6573706163654d656d6f727920696d706f7274206d757374206861766520746865206669656c64206e616d6520276d656d6f7279274d756c7469706c65206d656d6f727920696d706f72747320646566696e65644d6178696d756d206e756d626572206f662070616765732073686f756c6420626520616c77617973206465636c617265642e52657175657374656420696e697469616c206e756d626572206f662070616765732073686f756c64206e6f74206578636565642074686520726571756573746564206d6178696d756d4d6178696d756d206e756d626572206f662070616765732073686f756c64206e6f74206578636565642074686520636f6e66696775726564206d6178696d756d2e0000000000fc2811000a00000000000000c08c1100010000000000000000000000d88c1100030000000000000000000000c1c411000d00000000000000c08c1100010000000000000000000000f08c1100030000000000000000000000062911000b00000000000000088d1100020000000000000000000000388d1100050000000000000000000000112911000d00000000000000608d1100010000000000000000000000788d11000400000000000000000000001e2911000a00000000000000988d1100010000000000000000000000b08d1100050000000000000000000000282911000900000000000000c08c1100010000000000000000000000d88d1100010000000000000000000000312911000b00000000000000c8b01200000000000000000000000000e08d110001000000000000000000000097d211000300000000000000138212000c0000009f9011001f000000c8b0120000000000be9011002d0000004b90110024000000c8b01200000000006f9011003000000000000000429011000600000000000000138212000c00000000000000489011000300000000000000138212000c000000a08f110030000000c8b0120000000000d08f11002e000000c8b0120000000000fe8f11004400000000000000998f11000700000000000000e03c120011000000f98e1100560000004f8f11001b000000c8b01200000000006a8f11002f00000000000000108212000300000000000000138212000c0000003e8e110036000000c8b0120000000000748e11003d000000c8b0120000000000b18e1100480000000e8e110030000000e88d1100260000002052656d6f766520746865207072696d65206d656d626572206966206974206578697374732e2053657420746865207072696d65206d656d6265722e204d75737420626520612063757272656e74206d656d6265722e2053776170206f7574207468652073656e64696e67206d656d62657220666f7220736f6d65206f74686572206b657920606e6577602e204d6179206f6e6c792062652063616c6c65642066726f6d20605369676e656460206f726967696e206f6620612063757272656e74206d656d6265722e205072696d65206d656d62657273686970206973207061737365642066726f6d20746865206f726967696e206163636f756e7420746f20606e6577602c20696620657874616e742e204368616e676520746865206d656d6265727368697020746f2061206e6577207365742c20646973726567617264696e6720746865206578697374696e67206d656d626572736869702e204265206e69636520616e64207061737320606d656d6265727360207072652d736f727465642e204d6179206f6e6c792062652063616c6c65642066726f6d206052657365744f726967696e60206f7220726f6f742e6d656d626572732053776170206f7574206f6e65206d656d626572206072656d6f76656020666f7220616e6f746865722060616464602e204d6179206f6e6c792062652063616c6c65642066726f6d2060537761704f726967696e60206f7220726f6f742e205072696d65206d656d62657273686970206973202a6e6f742a207061737365642066726f6d206072656d6f76656020746f2060616464602c20696620657874616e742e72656d6f76656164642052656d6f76652061206d656d626572206077686f602066726f6d20746865207365742e204d6179206f6e6c792062652063616c6c65642066726f6d206052656d6f76654f726967696e60206f7220726f6f742e204164642061206d656d626572206077686f6020746f20746865207365742e204d6179206f6e6c792062652063616c6c65642066726f6d20604164644f726967696e60206f7220726f6f742e496e7374616e6365314d656d626572736869700000000000006bef1100070000000000000000000000e03c12001100000000000000000000000000000000000000000000000000000000000000c8b01200b09111000000000000000000c0911100010000000000000001000000000000007bea1100050000000000000000000000138212000c00000000000000000000000000000000000000000000000000000000000000c8b01200c89111000000000000000000d89111000100000000000000000000003c00000000000000010000005900000009921100320000003c000000000000000100000051000000e091110029000000205468652063757272656e74207072696d65206d656d6265722c206966206f6e65206578697374732e205468652063757272656e74206d656d626572736869702c2073746f72656420617320616e206f726465726564205665632e0000000000991911000b0000000000000058921100010000000000000060921100200000002053656e646572206d75737420626520746865205375646f206163636f756e74696e636f7272656374206964656e746974796e6f7420766f7563686564622e6c656e2829203e20313030303b207165649c2d110043000000bc0400003100000000000000d82311001c00000000000000a0931100010000000000000000000000c42311001400000000000000a8931100010000000000000000000000b82311000c00000000000000b0931100010000000000000000000000ac2311000c00000000000000b8931100010000000000000000000000a22311000a00000000000000c0931100010000000000000000000000992311000900000000000000c8931100010000000000000000000000902311000900000000000000d0931100010000000000000000000000872311000900000000000000d89311000100000000000000399511001f0000001e9511001b000000fc94110022000000d994110023000000c09411001900000078941100480000002d9411004b000000e09311004d00000020546865207469702063616e6e6f7420626520636c61696d65642f636c6f73656420626563617573652069742773207374696c6c20696e2074686520636f756e74646f776e20706572696f642e20546865207469702063616e6e6f7420626520636c61696d65642f636c6f736564206265636175736520746865726520617265206e6f7420656e6f7567682074697070657273207965742e20546865206163636f756e7420617474656d7074696e6720746f20726574726163742074686520746970206973206e6f74207468652066696e646572206f6620746865207469702e2054686520746970206861736820697320756e6b6e6f776e2e20546865207469702077617320616c726561647920666f756e642f737461727465642e2054686520726561736f6e20676976656e206973206a75737420746f6f206269672e204e6f2070726f706f73616c206174207468617420696e6465782e2050726f706f73657227732062616c616e636520697320746f6f206c6f772e000000007f1b11000b0000000000000050971100010000000000000000000000d1ea1100090000000000000058971100010000000000000000000000721b11000d0000000000000060971100010000000000000000000000691b11000900000000000000689711000100000000000000000000005d1b11000c0000000000000070971100010000000000000000000000551b1100080000000000000078971100010000000000000000000000471b11000e0000000000000080971100010000000000000000000000381b11000f0000000000000088971100010000000000000000000000291b11000f00000000000000909711000100000000000000000000001e1b11000b00000000000000989711000100000000000000000000001a1b11000400000000000000a0971100010000000000000000000000131b11000700000000000000a8971100010000000000000000000000091b11000a00000000000000b0971100010000000000000000000000f91a11001000000000000000b8971100010000000000000000000000ed1a11000c00000000000000c0971100010000000000000000000000cd1a11000a00000000000000c8971100010000000000000000000000e31a11000a00000000000000d0971100010000000000000000000000dc1a11000700000000000000d89711000100000000000000ce99110024000000b8991100160000009e9911001a0000008b991100130000007499110017000000619911001300000048991100190000002199110027000000e79811003a000000cf98110018000000aa981100250000008f9811001b000000729811001d000000559811001d0000003c981100190000001b98110021000000fc9711001f000000e09711001c000000205468652063616c6c6572206973206e6f742074686520686561642e205468652063616c6c6572206973206e6f742074686520666f756e6465722e20546f6f206d616e79206d656d6265727320696e2074686520736f63696574792e2055736572206973206e6f7420612063616e6469646174652e205573657220697320616c726561647920612063616e6469646174652e20557365722068617320616c7265616479206d6164652061206269642e2043616e6e6f742072656d6f76652074686520666f756e6465722e2043616e6e6f742072656d6f7665207468652068656164206f662074686520636861696e2e204d656d626572206973206e6f7420766f756368696e672e204d656d62657220697320616c726561647920766f756368696e67206f722062616e6e65642066726f6d20766f756368696e6720616761696e2e204e6f7420656e6f75676820696e20706f7420746f206163636570742063616e6469646174652e20536f636965747920616c726561647920666f756e6465642e204e6f7468696e6720746f207061796f75742e2055736572206973206e6f742073757370656e6465642e20557365722069732073757370656e6465642e205573657220697320616c72656164792061206d656d6265722e2055736572206973206e6f742061206d656d6265722e20416e20696e636f727265637420706f736974696f6e207761732070726f76696465642e4368617267655472616e73616374696f6e5061796d656e74546f6f536f6f6e4368616e676550656e64696e67526573756d654661696c656450617573654661696c65647265706f72745f6d69736265686176696f723a6772616e6470615f617574686f726974696573446561644163636f756e744578697374696e6756657374696e675363686564756c654b656570416c6976654578697374656e7469616c4465706f736974496e73756666696369656e7442616c616e63654c69717569646974795265737472696374696f6e7356657374696e6742616c616e63657365745f62616c616e63657472616e736665725f6b6565705f616c697665546f74616c49737375616e63654c6f636b73000000000000dc9b110007000000000000004c261200020000000000000000000000e49b1100010000000000000000000000ec9b110008000000000000004c261200020000000000000000000000f49b1100020000000000000000000000049c110008000000000000000c9c1100030000000000000000000000249c11000100000000000000000000002c9c11000a00000000000000389c1100030000000000000000000000509c1100010000000000000000000000589c110007000000000000004c261200020000000000000000000000609c11000100000000000000456e646f77656400659d11002f000000447573744c6f7374f69c110050000000469d11001f0000005472616e73666572c26d120009000000c26d1200090000009027120007000000d09c11002600000042616c616e63655365740000c26d120009000000902712000700000090271200070000009f9c1100310000004465706f73697400689c11003700000020536f6d6520616d6f756e7420776173206465706f73697465642028652e672e20666f72207472616e73616374696f6e2066656573292e20412062616c616e6365207761732073657420627920726f6f74202877686f2c20667265652c207265736572766564292e205472616e7366657220737563636565646564202866726f6d2c20746f2c2076616c7565292e20416e206163636f756e74207761732072656d6f7665642077686f73652062616c616e636520776173206e6f6e2d7a65726f206275742062656c6f77204578697374656e7469616c4465706f7369742c20726573756c74696e6720696e20616e206f75747269676874206c6f73732e20416e206163636f756e74207761732063726561746564207769746820736f6d6520667265652062616c616e63652e5265706f727473656e74697265206e65775f7365742077617320676976656e20746f206275696c645f737570706f72745f6d61703b20656e20656e747279206d757374206265206372656174656420666f722065616368206974656d3b20716564000000089e11004e000000a9020000230000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f6672616d652f656c656374696f6e732d70687261676d656e2f7372632f6c69622e727350726576696f7573206d617463682061726d206d61746368657320616e7974696e67206c657373207468616e20325e33303b20716564000000000000000000000000a09e11003d000000736869667465642073756666696369656e74206269747320726967687420746f206c656164206f6e6c79206c656164696e67207a65726f733b2071656400000000000000000000000000000000000000009f11004a00000033000000120000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f7072696d6974697665732f72756e74696d652f7372632f63757276652e727350656e64696e674368616e6765537461746552616e646f6d6e657373436f6c6c656374697665466c697052616e646f6d4d6174657269616c707265636f6e646974696f6e3a20616c6c20696d706f7274732073686f756c6420626520636865636b656420616761696e737420746865207369676e617475726573206f6620636f72726573706f6e64696e670a09090909090966756e6374696f6e7320646566696e65642062792060646566696e655f656e762160206d6163726f206279207468652075736572206f6620746865206d6163726f3b0a0909090909097369676e617475726573206f662074686573652066756e6374696f6e7320646566696e6564206279206024706172616d73603b0a09090909090963616c6c7320616c77617973206d616465207769746820617267756d656e7473207479706573206f662077686963682061726520646566696e65642062792074686520636f72726573706f6e64696e6720696d706f7274733b0a09090909090974687573207479706573206f6620617267756d656e74732073686f756c6420626520657175616c20746f2074797065206c69737420696e206024706172616d736020616e640a0909090909096c656e677468206f6620617267756d656e74206c69737420616e642024706172616d732073686f756c6420626520657175616c3b0a0909090909097468757320746869732063616e206e6576657220626520604e6f6e65603b0a0909090909097165643b0a090909090909000088a111005500000046000000110000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f6672616d652f636f6e7472616374732f7372632f7761736d2f656e765f6465662f6d6163726f732e72735374616c6c65643c0000000800000004000000e9000000ea0000000000000000000000eb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004e657874466f72636564000000000000359a1100120000000000000030a3110001000000000000000000000048a3110001000000000000000000000069a31100070000000000000070a311000700000050a3110019000000205265706f727420736f6d65206d69736265686176696f722e5f7265706f72745665633c75383e0000000000b88312000b00000000000000000000009f8d12000d00000000000000000000000000000000000000000000000000000000000000c8b01200e0a511000000000000000000f0a5110004000000000000000100000000000000579f110005000000000000000000000010a611001b00000000000000000000000000000000000000000000000000000000000000c8b012002ca6110000000000000000003ca61100010000000000000001000000000000004a9f11000d000000000000000000000044a611002300000000000000000000000000000000000000000000000000000000000000c8b0120080b81100000000000000000068a6110001000000000000000000000000000000f8a211000a0000000000000000000000f50812000e00000000000000000000000000000000000000000000000000000000000000c8b01200d8a61100000000000000000070a6110001000000000000000000000000000000dda1110007000000000000000000000078a611002000000000000000000000000000000000000000000000000000000000000000c8b0120098a611000000000000000000a8a6110001000000000000000000000000000000ac8d12000c0000000000000000000000b0a611000500000000000000000000000000000000000000000000000000000000000000c8b01200b8a611000000000000000000c8a6110002000000000000000100000000000000c78d12000c0000000101000000000000b0a611000500000000000000179012000c00000000000000000000000000000000000000c8b01200d8a611000000000000000000e8a611000100000000000000000000003c00000000000000010000005900000090a811000b000000c8b01200000000009ba8110058000000f3a811002600000053746f72656453746174653c543a3a426c6f636b4e756d6265723e003c0000000000000001000000ec0000006ca811002400000053746f72656450656e64696e674368616e67653c543a3a426c6f636b4e756d6265723e003ba81100310000000ca811002f00000028543a3a426c6f636b4e756d6265722c20543a3a426c6f636b4e756d626572293c000000000000000100000051000000e8a711002400000053657449640000003c00000000000000010000005200000060a7110057000000b7a71100310000003c000000000000000100000051000000f0a61100700000002041206d617070696e672066726f6d206772616e6470612073657420494420746f2074686520696e646578206f6620746865202a6d6f737420726563656e742a2073657373696f6e20666f7220776869636820697473206d656d62657273207765726520726573706f6e7369626c652e20546865206e756d626572206f66206368616e6765732028626f746820696e207465726d73206f66206b65797320616e6420756e6465726c79696e672065636f6e6f6d696320726573706f6e736962696c69746965732920696e20746865202273657422206f66204772616e6470612076616c696461746f72732066726f6d2067656e657369732e20607472756560206966207765206172652063757272656e746c79207374616c6c65642e206e65787420626c6f636b206e756d6265722077686572652077652063616e20666f7263652061206368616e67652e2050656e64696e67206368616e67653a20287369676e616c65642061742c207363686564756c6564206368616e6765292e205374617465206f66207468652063757272656e7420617574686f72697479207365742e20444550524543415445442054686973207573656420746f2073746f7265207468652063757272656e7420617574686f72697479207365742c20776869636820686173206265656e206d6967726174656420746f207468652077656c6c2d6b6e6f776e204752414e4450415f415554484f5249544945535f4b455920756e686173686564206b65792e00000000000000a76c12000800000000000000cca91100020000000000000000000000fca91100180000000000000000000000ce9a11000b00000000000000bcaa110003000000000000000000000004ab11000d0000000000000000000000b36c12000e000000000000006cab1100030000000000000000000000b4ab1100020000000000000000000000d99a11001300000000000000cca91100020000000000000000000000c4ab11000600000000000000000000001dad11000400000000000000203f120023000000000000007c471200050000000000000021ad110013000000caae110036000000c8b012000000000000af11004200000042af1100480000008aaf110045000000cfaf11002d000000c8b0120000000000fcaf110046000000c8b01200000000002a7f12000b00000042b011004c0000008eb0110033000000c1b011005a000000c8b01200000000001bb1110013000000c8b01200000000002eb111005400000082b111004b000000cdb111003500000002b21100580000005ab2110052000000acb211003e000000c8b0120000000000927f12000c0000000000000097d211000300000000000000203f12002300000000000000b6ae1100080000000000000021ad11001300000000000000beae11000c0000000000000021ad11001300000034ad110025000000c8b012000000000059ad110048000000a1ad110042000000e3ad11004600000029ae110040000000c8b012000000000069ae11002d000000c8b01200000000002a7f12000b00000096ae110020000000b337120031000000927f12000c0000000000000017ad11000600000000000000203f120023000000000000001dad11000400000000000000203f120023000000000000007c471200050000000000000021ad110013000000b8ac1100540000000cad11000b000000f4ab11005400000048ac110010000000c8b012000000000058ac11002f000000c8b012000000000087ac1100310000002053616d6520617320746865205b607472616e73666572605d2063616c6c2c206275742077697468206120636865636b207468617420746865207472616e736665722077696c6c206e6f74206b696c6c20746865206f726967696e206163636f756e742e20393925206f66207468652074696d6520796f752077616e74205b607472616e73666572605d20696e73746561642e205b607472616e73666572605d3a207374727563742e4d6f64756c652e68746d6c236d6574686f642e7472616e736665722045786163746c7920617320607472616e73666572602c2065786365707420746865206f726967696e206d75737420626520726f6f7420616e642074686520736f75726365206163636f756e74206d6179206265207370656369666965642e736f7572636564657374436f6d706163743c543a3a42616c616e63653e20536574207468652062616c616e636573206f66206120676976656e206163636f756e742e20546869732077696c6c20616c74657220604672656542616c616e63656020616e642060526573657276656442616c616e63656020696e2073746f726167652e2069742077696c6c20616c736f2064656372656173652074686520746f74616c2069737375616e6365206f66207468652073797374656d202860546f74616c49737375616e636560292e20496620746865206e65772066726565206f722072657365727665642062616c616e63652069732062656c6f7720746865206578697374656e7469616c206465706f7369742c2069742077696c6c20726573657420746865206163636f756e74206e6f6e63652028606672616d655f73797374656d3a3a4163636f756e744e6f6e636560292e20546865206469737061746368206f726967696e20666f7220746869732063616c6c2069732060726f6f74602e202d20496e646570656e64656e74206f662074686520617267756d656e74732e6e65775f667265656e65775f7265736572766564205472616e7366657220736f6d65206c697175696420667265652062616c616e636520746f20616e6f74686572206163636f756e742e20607472616e73666572602077696c6c207365742074686520604672656542616c616e636560206f66207468652073656e64657220616e642072656365697665722e2049742077696c6c2064656372656173652074686520746f74616c2069737375616e6365206f66207468652073797374656d2062792074686520605472616e73666572466565602e204966207468652073656e6465722773206163636f756e742069732062656c6f7720746865206578697374656e7469616c206465706f736974206173206120726573756c74206f6620746865207472616e736665722c20746865206163636f756e742077696c6c206265207265617065642e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d75737420626520605369676e65646020627920746865207472616e736163746f722e202d20446570656e64656e74206f6e20617267756d656e747320627574206e6f7420637269746963616c2c20676976656e2070726f70657220696d706c656d656e746174696f6e7320666f72202020696e70757420636f6e6669672074797065732e205365652072656c617465642066756e6374696f6e732062656c6f772e202d20497420636f6e7461696e732061206c696d69746564206e756d626572206f6620726561647320616e642077726974657320696e7465726e616c6c7920616e64206e6f20636f6d706c657820636f6d7075746174696f6e2e2052656c617465642066756e6374696f6e733a2020202d2060656e737572655f63616e5f77697468647261776020697320616c776179732063616c6c656420696e7465726e616c6c792062757420686173206120626f756e64656420636f6d706c65786974792e2020202d205472616e7366657272696e672062616c616e63657320746f206163636f756e7473207468617420646964206e6f74206578697374206265666f72652077696c6c20636175736520202020202060543a3a4f6e4e65774163636f756e743a3a6f6e5f6e65775f6163636f756e746020746f2062652063616c6c65642e2020202d2052656d6f76696e6720656e6f7567682066756e64732066726f6d20616e206163636f756e742077696c6c20747269676765722060543a3a4475737452656d6f76616c3a3a6f6e5f756e62616c616e636564602e2020202d20607472616e736665725f6b6565705f616c6976656020776f726b73207468652073616d652077617920617320607472616e73666572602c206275742068617320616e206164646974696f6e616c2020202020636865636b207468617420746865207472616e736665722077696c6c206e6f74206b696c6c20746865206f726967696e206163636f756e742e000000000000ec9a11000d00000000000000000000004cb411000a00000000000000000000000000000000000000000000000000000000000000c8b0120058b41100000000000000000068b411000100000000000000010000000000000070b41100070000000101000000000000138212000c0000000000000077b411001700000000000000000000000000000000000000c8b0120090b411000000000000000000a0b4110006000000000000000100000000000000f99a1100050000000101000000000000138212000c00000000000000d0b411001c00000000000000000000000000000000000000c8b01200ecb411000000000000000000fcb4110002000000000000000100000000000000ac9012000e0000000000000000000000145a12000800000000000000000000000000000000000000000000000000000000000000c8b012000cb5110000000000000000002c5a1200030000000000000001000000543a3a42616c616e636500003c0000000000000001000000de00000084b61100260000004163636f756e744163636f756e74446174613c543a3a42616c616e63653e00003c0000000000000001000000ed00000093b511001b000000c8b0120000000000aeb511005600000004b6110030000000c8b012000000000034b61100500000005665633c42616c616e63654c6f636b3c543a3a42616c616e63653e3e3c0000000000000001000000590000001cb511002e0000004ab51100490000003c00000000000000010000005100000020416e79206c6971756964697479206c6f636b73206f6e20736f6d65206163636f756e742062616c616e6365732e204e4f54453a2053686f756c64206f6e6c79206265206163636573736564207768656e2073657474696e672c206368616e67696e6720616e642066726565696e672061206c6f636b2e205468652062616c616e6365206f6620616e206163636f756e742e204e4f54453a2054484953204d4159204e4556455220424520494e204558495354454e434520414e4420594554204841564520412060746f74616c28292e69735f7a65726f2829602e2049662074686520746f74616c2069732065766572207a65726f2c207468656e2074686520656e747279202a4d5553542a2062652072656d6f7665642e204e4f54453a2054686973206973206f6e6c79207573656420696e20746865206361736520746861742074686973206d6f64756c65206973207573656420746f2073746f72652062616c616e6365732e2054686520746f74616c20756e6974732069737375656420696e207468652073797374656d2e000000000000869a110012000000000000004cb411000a00000000000000c8b01200e4b611000000000000000000f4b6110001000000000000003c000000000000000100000061000000fcb611003500000020546865206d696e696d756d20616d6f756e7420726571756972656420746f206b65657020616e206163636f756e74206f70656e2e00000000000000949d11000700000001010000000000003cb811000d0000000000000049b811003400000000000000000000000000000000000000c8b0120080b81100000000000000000090b811000100000000000000000000000000000098b81100160000000201010000000000ff8e12000400000000000000038f12000e00000000000000aeb811001200000000000000c8b0120050bd11000000000000000000c0b8110001000000000000000100000000000000f58d1200120000000101000000000000ff8e1200040000000000000070a311000700000000000000000000000000000000000000c8b01200c8b811000000000000000000d8b811000600000000000000010000005265706f727449644f663c543e4f6666656e636544657461696c733c543a3a4163636f756e7449642c20543a3a4964656e74696669636174696f6e5475706c653e0000003c00000000000000010000005100000071ba110052000000436f6e63757272656e745265706f727473496e6465785665633c5265706f727449644f663c543e3e27ba11004a0000003c00000000000000010000005900000008b9110044000000c8b01200000000004cb911002f000000c8b01200000000007bb9110052000000cdb911005a00000020456e756d65726174657320616c6c207265706f727473206f662061206b696e6420616c6f6e672077697468207468652074696d6520746865792068617070656e65642e20416c6c207265706f7274732061726520736f72746564206279207468652074696d65206f66206f6666656e63652e204e6f74652074686174207468652061637475616c2074797065206f662074686973206d617070696e6720697320605665633c75383e602c207468697320697320626563617573652076616c756573206f6620646966666572656e7420747970657320617265206e6f7420737570706f7274656420617420746865206d6f6d656e7420736f2077652061726520646f696e6720746865206d616e75616c2073657269616c697a6174696f6e2e204120766563746f72206f66207265706f727473206f66207468652073616d65206b696e6420746861742068617070656e6564206174207468652073616d652074696d6520736c6f742e20546865207072696d61727920737472756374757265207468617420686f6c647320616c6c206f6666656e6365207265636f726473206b65796564206279207265706f7274206964656e746966696572732e72616e206f7574206f662067617320647572696e6720636f6e747261637420657865637574696f6e72657475726e2074797065206572726f7276616c69646174696f6e206572726f72636f6e7472616374207472617070656420647572696e6720657865637574696f6e000000696d2d6f6e6c696e653a6f66666c696e000000006f91120011000000000000000000000098bb11000a00000000000000000000000000000000000000000000000000000000000000c8b01200a4bb11000000000000000000c8b012000000000000000000010000004d756c7469706c69657200003c0000000000000001000000520000000000000024bc11001200000000000000845712000c00000000000000c8b0120038bc1100000000000000000048bc110001000000000000000000000050bc11001200000000000000845712000c00000000000000c8b0120064bc1100000000000000000074bc110001000000000000005472616e73616374696f6e4261736546656500003c000000000000000100000065000000bfbc1100370000005472616e73616374696f6e4279746546656500003c0000000000000001000000640000007cbc110043000000205468652066656520746f206265207061696420666f72206d616b696e672061207472616e73616374696f6e3b20746865207065722d6279746520706f7274696f6e2e205468652066656520746f206265207061696420666f72206d616b696e672061207472616e73616374696f6e3b2074686520626173652e000000000000749f11000e0000000000000000000000dc1512000c00000000000000000000000000000000000000000000000000000000000000c8b0120050bd1100000000000000000060bd11000300000000000000010000003c00000000000000010000005900000078bd110058000000d0bd11005800000028be11001100000020536572696573206f6620626c6f636b20686561646572732066726f6d20746865206c61737420383120626c6f636b73207468617420616374732061732072616e646f6d2073656564206d6174657269616c2e205468697320697320617272616e67656420617320612072696e672062756666657220776974682060626c6f636b5f6e756d626572202520383160206265696e672074686520696e64657820696e746f20746865206056656360206f6620746865206f6c6465737420686173682e000000000000002a9a11000b00000000000000acbe11000200000000000000000000001e9a11000c00000000000000bcbe1100020000000000000000000000119a11000d00000000000000ccbe11000100000000000000000000000a9a11000700000000000000d4be11000100000000000000b5bf110042000000f7bf11002a00000047bf1100450000008cbf1100290000000cbf11003b000000dcbe1100300000002043616e6e6f74207369676e616c20666f72636564206368616e676520736f20736f6f6e206166746572206c6173742e20417474656d707420746f207369676e616c204752414e445041206368616e67652077697468206f6e6520616c72656164792070656e64696e672e20417474656d707420746f207369676e616c204752414e44504120726573756d65207768656e2074686520617574686f72697479207365742069736e2774207061757365642028656974686572206c697665206f7220616c72656164792070656e64696e6720726573756d65292e20417474656d707420746f207369676e616c204752414e445041207061757365207768656e2074686520617574686f72697479207365742069736e2774206c697665202865697468657220706175736564206f7220616c72656164792070656e64696e67207061757365292e00000000000000c09a11000e0000000000000004c11100010000000000000000000000ab9a110015000000000000000cc1110001000000000000000000000011e61100080000000000000014c11100010000000000000000000000989a110013000000000000001cc11100010000000000000000000000869a1100120000000000000024c111000100000000000000000000007d9a110009000000000000002cc11100010000000000000000000000669a1100170000000000000034c111000100000000000000000000005b9a11000b000000000000003cc11100010000000000000066c211002700000034c211003200000017c211001d000000f9c111001e000000bec111003b0000009ac111002400000067c111003300000044c11100230000002042656e6566696369617279206163636f756e74206d757374207072652d657869737420412076657374696e67207363686564756c6520616c72656164792065786973747320666f722074686973206163636f756e74205472616e736665722f7061796d656e7420776f756c64206b696c6c206163636f756e742056616c756520746f6f206c6f7720746f20637265617465206163636f756e742064756520746f206578697374656e7469616c206465706f7369742042616c616e636520746f6f206c6f7720746f2073656e642076616c756520476f7420616e206f766572666c6f7720616674657220616464696e67204163636f756e74206c6971756964697479207265737472696374696f6e732070726576656e74207769746864726177616c2056657374696e672062616c616e636520746f6f206869676820746f2073656e642076616c75654469676573744974656d206e6f7420657175616c486561644f66566f7465734f66566f7465734f66000000c0c211001a0000004552524f523a20436f7272757074656420737461746520617420417574686f726f766572666c6f77206d756c7469706c79696e6720676173206c696d6974206279207072696365003c0000000000000001000000ee000000ef000000f0000000f1000000f2000000f3000000636f6e74726163742073756273797374656d20726573756c74696e6720696e20706f73697469766520696d62616c616e6365214f6c64556e636c65556e636c65416c7265616479496e636c75646564546f6f48696768556e636c6547656e65736973556e636c65546f6f4d616e79556e636c6573556e636c6573416c7265616479536574496e76616c6964556e636c65506172656e747365745f756e636c6573496e76616c69644f726967696e496e73756666696369656e7443616e64696461746546756e647352756e6e65725375626d69744d656d6265725375626d69744475706c69636174656443616e6469646174655265706f727453656c664d7573744265566f746572556e61626c65546f506179426f6e644c6f7742616c616e63654d6178696d756d566f7465734578636565646564546f6f4d616e79566f7465734e6f566f746573556e61626c65546f566f746572656d6f76655f766f7465727265706f72745f646566756e63745f766f7465727375626d69745f63616e64696461637972656e6f756e63655f63616e64696461637972656d6f76655f6d656d6265725374616b654f6600000000000000b4c511000700000000000000bcc51100010000000000000000000000c4c51100020000000000000000000000d4c511000900000000000000c8b01200000000000000000000000000e0c51100010000000000000000000000e8c511000c000000000000005ce81100010000000000000000000000f4c5110002000000000000000000000004c611000f000000000000005ce8110001000000000000000000000014c611000100000000000000000000001cc611000d000000000000002cc6110003000000000000000000000044c6110002000000000000004e65775465726d0031c81100190000008bc7110055000000e0c7110051000000456d7074795465726d00000055c71100360000004d656d6265724b69636b6564f7c611005100000048c711000d0000004d656d62657252656e6f756e63656400cfc6110028000000566f7465725265706f72746564000000c26d120009000000c26d12000900000000ee11000400000054c6110058000000acc6110023000000204120766f7465722028666972737420656c656d656e742920776173207265706f72746564202862797420746865207365636f6e6420656c656d656e742920776974682074686520746865207265706f7274206265696e67207375636365737366756c206f72206e6f742028746869726420656c656d656e74292e2041206d656d626572206861732072656e6f756e6365642074686569722063616e6469646163792e2041206d656d62657220686173206265656e2072656d6f7665642e20546869732073686f756c6420616c7761797320626520666f6c6c6f7765642062792065697468657220604e65775465726d60206f742060456d7074795465726d602e204e6f20286f72206e6f7420656e6f756768292063616e64696461746573206578697374656420666f72207468697320726f756e642e2041206e6577207465726d2077697468206e6577206d656d626572732e205468697320696e64696361746573207468617420656e6f7567682063616e6469646174657320657869737465642c206e6f74207468617420656e6f756768206861766520686173206265656e20656c65637465642e2054686520696e6e65722076616c7565206d757374206265206578616d696e656420666f72207468697320707572706f73652e5665633c284163636f756e7449642c2042616c616e6365293e00003c0000000000000001000000f40000003c0000000000000001000000f500000076616c75652073697a652065786365656473206d6178696d756d556e636c657343616e6469646174657352756e6e657273557072656163686564206d6178696d756d2064657074682c2063616e6e6f74206d616b6520612063616c6c6e6f7420656e6f7567682067617320746f2070617920626173652063616c6c2066656500f60000001800000004000000f7000000f8000000f9000000fa000000fb000000fc00000061206e657374656420657865637574696f6e20636f6e74657874206d7573742068617665206120706172656e743b207165640000a4c91100460000009801000026000000636f6e74726163742063616e6e6f742062652064657374726f79656420647572696e672072656375727369766520657865637574696f6e636f6e747261637420686173206265656e20657669637465642f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f6672616d652f636f6e7472616374732f7372632f657865632e72736e6f7420656e6f7567682067617320746f20706179207472616e736665722066656562616c616e636520746f6f206c6f7720746f2073656e642076616c756576616c756520746f6f206c6f7720746f20637265617465206163636f756e7464657374696e6174696f6e2062616c616e636520746f6f206869676820746f20726563656976652076616c756572656163686564206d6178696d756d2064657074682c2063616e6e6f7420696e7374616e7469617465416c69766520636f6e7472616374206f7220746f6d6273746f6e6520616c726561647920657869737473696e73756666696369656e742072656d61696e696e672062616c616e63656e6f7420656e6f7567682067617320746f20706179206261736520696e7374616e74696174652066656500000000c2c311000a000000000000003ccb110001000000000000000000000054cb110001000000000000000000000075cb11000a000000000000007fcb11000e0000005ccb1100190000002050726f76696465206120736574206f6620756e636c65732e6e65775f756e636c65735665633c543a3a4865616465723e0000000000000086c8110006000000000000000000000098cc11003a00000000000000000000000000000000000000000000000000000000000000c8b01200d4cc11000000000000000000e4cc110001000000000000000100000000000000dac21100060000000000000000000000138212000c00000000000000000000000000000000000000000000000000000000000000c8b01200eccc11000000000000000000fccc1100010000000000000000000000000000009e8312000c000000000000000000000000ee11000400000000000000000000000000000000000000000000000000000000000000c8b0120004cd1100000000000000000014cd11000100000000000000010000005665633c556e636c65456e7472794974656d3c543a3a426c6f636b4e756d6265722c20543a3a486173682c20543a3a4163636f756e7449643e3e00003c00000000000000010000005900000064cd1100070000003c0000000000000001000000510000004bcd1100190000003c0000000000000001000000510000001ccd11002f000000205768657468657220756e636c6573207765726520616c72656164792073657420696e207468697320626c6f636b2e20417574686f72206f662063757272656e7420626c6f636b2e20556e636c65730000000000f3ea1100040000000000000074ce1100020000000000000000000000a4ce11000f00000000000000000000007fc411000c00000000000000c8b012000000000000000000000000001ccf11000700000000000000000000008bc41100140000000000000054cf11000100000000000000000000006ccf11000d00000000000000000000009fc411001000000000000000c8b01200000000000000000000000000d4cf11000d0000000000000000000000afc411001200000000000000c8b012000000000000000000000000003cd01100090000000000000000000000c1c411000d0000000000000084d011000100000000000000000000009cd011000d0000000000000000000000f3d911000500000000000000e03c120011000000000000007c4712000500000000000000814712001500000059d8110041000000c8b01200000000009ad8110014000000aed8110012000000c0d811002b000000c8b0120000000000ebd811005700000042d911005700000099d9110028000000c8b01200000000002a7f12000b0000005fd211000b0000004dd811000c000000c1d9110032000000927f12000c00000005d8110048000000c8b01200000000002a7f12000b0000005fd211000b0000004dd811000c00000046d611000d000000927f12000c00000000000000ffd711000600000000000000203f12002300000053d6110057000000aad611005700000001d7110017000000c8b012000000000018d71100220000003ad71100530000008dd711002d000000c8b01200000000002a7f12000b0000005fd211000b000000bad711004500000046d611000d000000927f12000c00000004d511001e000000c8b012000000000022d51100190000003bd511003b00000076d511004b000000c1d511005500000016d611000d000000c8b01200000000002a7f12000b0000005fd211000b00000023d611002300000046d611000d000000927f12000c0000009ad2110054000000eed2110010000000fed21100500000004ed311003d0000008bd3110056000000e1d311002100000002d411005300000055d4110056000000abd41100590000000000000097d211000300000000000000203f12002300000004d11100570000005bd1110020000000c8b01200000000007bd1110056000000d1d111003d000000c8b01200000000000ed2110051000000c8b01200000000002a7f12000b0000005fd211000b0000006ad211001600000080d2110017000000927f12000c0000002052656d6f7665206120706172746963756c6172206d656d6265722066726f6d20746865207365742e20546869732069732065666665637469766520696d6d6564696174656c7920616e642074686520626f6e64206f6620746865206f7574676f696e67206d656d62657220697320736c61736865642e20496620612072756e6e65722d757020697320617661696c61626c652c207468656e2074686520626573742072756e6e65722d75702077696c6c2062652072656d6f76656420616e64207265706c6163657320746865206f7574676f696e67206d656d6265722e204f74686572776973652c2061206e65772070687261676d656e20726f756e6420697320737461727465642e204e6f74652074686174207468697320646f6573206e6f7420616666656374207468652064657369676e6174656420626c6f636b206e756d626572206f6620746865206e65787420656c656374696f6e2e20232323232053746174652052656164733a204f28646f5f70687261676d656e29205772697465733a204f28646f5f70687261676d656e2977686f2052656e6f756e6365206f6e65277320696e74656e74696f6e20746f20626520612063616e64696461746520666f7220746865206e65787420656c656374696f6e20726f756e642e203320706f74656e7469616c206f7574636f6d65732065786973743a202d20606f726967696e6020697320612063616e64696461746520616e64206e6f7420656c656374656420696e20616e79207365742e20496e207468697320636173652c2074686520626f6e64206973202020756e72657365727665642c2072657475726e656420616e64206f726967696e2069732072656d6f76656420617320612063616e6469646174652e202d20606f726967696e6020697320612063757272656e742072756e6e65722075702e20496e207468697320636173652c2074686520626f6e6420697320756e72657365727665642c2072657475726e656420616e642020206f726967696e2069732072656d6f76656420617320612072756e6e65722e202d20606f726967696e6020697320612063757272656e74206d656d6265722e20496e207468697320636173652c2074686520626f6e6420697320756e726573657276656420616e64206f726967696e20697320202072656d6f7665642061732061206d656d6265722c20636f6e73657175656e746c79206e6f74206265696e6720612063616e64696461746520666f7220746865206e65787420726f756e6420616e796d6f72652e20202053696d696c617220746f205b6072656d6f76655f766f746572605d2c206966207265706c6163656d656e742072756e6e657273206578697374732c20746865792061726520696d6d6564696174656c7920757365642e205375626d6974206f6e6573656c6620666f722063616e6469646163792e20412063616e6469646174652077696c6c206569746865723a2020202d204c6f73652061742074686520656e64206f6620746865207465726d20616e6420666f7266656974207468656972206465706f7369742e2020202d2057696e20616e64206265636f6d652061206d656d6265722e204d656d626572732077696c6c206576656e7475616c6c7920676574207468656972207374617368206261636b2e2020202d204265636f6d6520612072756e6e65722d75702e2052756e6e6572732d75707320617265207265736572766564206d656d6265727320696e2063617365206f6e65206765747320666f72636566756c6c79202020202072656d6f7665642e2052656164733a204f284c6f674e2920476976656e204e2063616e646964617465732e205772697465733a204f283129205265706f727420607461726765746020666f72206265696e6720616e20646566756e637420766f7465722e20496e2063617365206f6620612076616c6964207265706f72742c20746865207265706f727465722069732072657761726465642062792074686520626f6e6420616d6f756e74206f662060746172676574602e204f74686572776973652c20746865207265706f7274657220697473656c662069732072656d6f76656420616e6420746865697220626f6e6420697320736c61736865642e204120646566756e637420766f74657220697320646566696e656420746f2062653a2020202d206120766f7465722077686f73652063757272656e74207375626d697474656420766f7465732061726520616c6c20696e76616c69642e20692e652e20616c6c206f66207468656d20617265206e6f20202020206c6f6e67657220612063616e646964617465206e6f7220616e20616374697665206d656d6265722e2052656164733a204f284e4c6f674d2920676976656e204d2063757272656e742063616e6469646174657320616e64204e20766f74657320666f722060746172676574602e7461726765742052656d6f766520606f726967696e60206173206120766f7465722e20546869732072656d6f76657320746865206c6f636b20616e642072657475726e732074686520626f6e642e2052656164733a204f28312920566f746520666f72206120736574206f662063616e6469646174657320666f7220746865207570636f6d696e6720726f756e64206f6620656c656374696f6e2e205468652060766f746573602073686f756c643a2020202d206e6f7420626520656d7074792e2020202d206265206c657373207468616e20746865206e756d626572206f662063616e646964617465732e2055706f6e20766f74696e672c206076616c75656020756e697473206f66206077686f6027732062616c616e6365206973206c6f636b656420616e64206120626f6e6420616d6f756e742069732072657365727665642e2049742069732074686520726573706f6e736962696c697479206f66207468652063616c6c657220746f206e6f7420706c61636520616c6c206f662074686569722062616c616e636520696e746f20746865206c6f636b20616e64206b65657020736f6d6520666f722066757274686572207472616e73616374696f6e732e205772697465733a204f28562920676976656e2060566020766f7465732e205620697320626f756e6465642062792031362e766f746573000000006bef110007000000000000000000000008dc11002100000000000000000000000000000000000000000000000000000000000000c8b0120034dc110000000000000000002cdc11000100000000000000010000000000000096c8110009000000000000000000000008dc11002100000000000000000000000000000000000000000000000000000000000000c8b0120034dc1100000000000000000044dc1100010000000000000001000000000000004d8c12000e0000000000000000000000847212000300000000000000000000000000000000000000000000000000000000000000c8b012004cdc110000000000000000005cdc110001000000000000000100000000000000aec21100070000000101010000000000138212000c00000000000000e03c12001100000000000000000000000000000000000000c8b0120084dc1100000000000000000064dc110001000000000000000100000000000000cec41100070000000101000000000000138212000c00000000000000845712000c00000000000000000000000000000000000000c8b012006cdc110000000000000000007cdc1100010000000000000001000000000000008cc811000a0000000000000000000000e03c12001100000000000000000000000000000000000000000000000000000000000000c8b0120084dc1100000000000000000094dc11000200000000000000010000005665633c28543a3a4163636f756e7449642c2042616c616e63654f663c543e293e00000044de11003c0000003c000000000000000100000059000000f2dd1100520000003c00000000000000010000006b000000a2dd11005000000062dd1100400000003c0000000000000001000000de00000049dd1100190000003c000000000000000100000059000000a4dc110059000000fddc11004c000000205468652070726573656e742063616e646964617465206c6973742e20536f72746564206261736564206f6e206163636f756e742d69642e20412063757272656e74206d656d626572206f7220612072756e6e65722063616e206e6576657220656e746572207468697320766563746f7220616e6420697320616c7761797320696d706c696369746c7920617373756d656420746f20626520612063616e6469646174652e204c6f636b6564207374616b65206f66206120766f7465722e20566f746573206f66206120706172746963756c617220766f7465722c20776974682074686520726f756e6420696e646578206f662074686520766f7465732e2054686520746f74616c206e756d626572206f6620766f746520726f756e6473207468617420686176652068617070656e65642c206578636c7564696e6720746865207570636f6d696e67206f6e652e205468652063757272656e742072756e6e6572735f75702e20536f72746564206261736564206f6e206c6f7720746f2068696768206d657269742028776f72736520746f20626573742072756e6e6572292e205468652063757272656e7420656c6563746564206d656d626572736869702e20536f72746564206261736564206f6e206163636f756e742069642e0000000098df11000d00000000000000845712000c00000000000000c8b01200a8df11000000000000000000c8b01200000000000000000000000000b8df11000a00000000000000845712000c00000000000000c8b01200c4df11000000000000000000c8b01200000000000000000000000000d4df11000e00000000000000847212000300000000000000c8b01200e4df11000000000000000000c8b01200000000000000000000000000f4df11001000000000000000847212000300000000000000c8b0120004e011000000000000000000c8b0120000000000000000000000000014e011000c00000000000000f50812000e00000000000000c8b0120020e011000000000000000000c8b01200000000000000000043616e646964616379426f6e640000003c0000000000000001000000df000000566f74696e67426f6e6400003c000000000000000100000061000000446573697265644d656d6265727300003c0000000000000001000000fd0000004465736972656452756e6e65727355703c0000000000000001000000fe0000005465726d4475726174696f6e3c0000000000000001000000e400000000000000b0c311001200000000000000f4e01100010000000000000000000000a0c311001000000000000000fce0110001000000000000000000000093c311000d0000000000000004e1110001000000000000000000000087c311000c000000000000000ce111000100000000000000000000007bc311000c0000000000000014e1110001000000000000000000000067c3110014000000000000001ce111000100000000000000000000005fc31100080000000000000024e111000100000000000000e1e1110023000000c0e1110021000000afe111001100000099e111001600000079e11100200000005ae111001f0000002ce111002e0000002054686520756e636c652069736e277420726563656e7420656e6f75676820746f20626520696e636c756465642e2054686520756e636c6520697320616c726561647920696e636c756465642e2054686520756e636c6520697320746f6f206869676820696e20636861696e2e2054686520756e636c652069732067656e657369732e20546f6f206d616e7920756e636c65732e20556e636c657320616c72656164792073657420696e2074686520626c6f636b2e2054686520756e636c6520706172656e74206e6f7420696e2074686520636861696e2e0000000073c411000c000000000000008ce311000100000000000000000000006cc41100070000000000000094e3110001000000000000000000000060c411000c000000000000009ce311000100000000000000000000004cc411001400000000000000a4e3110001000000000000000000000042c411000a00000000000000ace3110001000000000000000000000033c411000f00000000000000b4e3110001000000000000000000000028c411000b00000000000000bce311000100000000000000000000001ec411000a00000000000000c4e311000100000000000000000000000bc411001300000000000000cce31100010000000000000000000000ffc311000c00000000000000d4e31100010000000000000000000000f3c311000c00000000000000dce31100010000000000000000000000d9c311001a00000000000000e4e31100010000000000000000000000ccc311000d00000000000000ece31100010000000000000000000000d1ea11000900000000000000f4e311000100000000000000aee511003100000088e511002600000066e51100220000003fe51100270000000de5110032000000eee411001f000000dde4110011000000c9e4110014000000a8e411002100000085e411002300000062e41100230000003ce41100260000000ae4110032000000fce311000e000000204e6f742061206d656d6265722e204f726967696e206973206e6f7420612063616e6469646174652c206d656d626572206f7220612072756e6e65722075702e2043616e64696461746520646f6573206e6f74206861766520656e6f7567682066756e64732e2052756e6e65722063616e6e6f742072652d7375626d69742063616e6469646163792e204d656d6265722063616e6e6f742072652d7375626d69742063616e6469646163792e204475706c6963617465642063616e646964617465207375626d697373696f6e2e2043616e6e6f74207265706f72742073656c662e204d757374206265206120766f7465722e20566f7465722063616e206e6f742070617920766f74696e6720626f6e642e2043616e6e6f7420766f74652077697468207374616b65206c657373207468616e206d696e696d756d2062616c616e63652e2043616e6e6f7420766f7465206d6f7265207468616e206d6178696d756d20616c6c6f7765642e2043616e6e6f7420766f7465206d6f7265207468616e2063616e646964617465732e204d75737420766f746520666f72206174206c65617374206f6e652063616e6469646174652e2043616e6e6f7420766f7465207768656e206e6f2063616e64696461746573206f72206d656d626572732065786973742e496e7374616e636532436f6c6c656374697665496e7374616e636531436f6c6c656374697665416c726561647950726f78794f766572666c6f775374696c6c4163746976655468726573686f6c64416c7265616479566f756368656444656c6179506572696f644e6f74467269656e644e6f7453746172746564416c726561647953746172746564416c72656164795265636f76657261626c654e6f745265636f76657261626c654e6f74536f727465644d6178467269656e64734e6f74456e6f756768467269656e64735a65726f5468726573686f6c644e6f74416c6c6f77656461735f7265636f76657265647365745f7265636f76657265646372656174655f7265636f76657279696e6974696174655f7265636f76657279766f7563685f7265636f76657279636c61696d5f7265636f76657279636c6f73655f7265636f7665727972656d6f76655f7265636f7665727963616e63656c5f7265636f766572656400000000004ce811000f000000000000005ce8110001000000000000000000000064e811000100000000000000000000006ce81100110000000000000080e8110002000000000000000000000090e8110001000000000000000000000098e811000f00000000000000a8e81100030000000000000000000000c0e81100010000000000000000000000c8e811000e0000000000000080e81100020000000000000000000000d8e81100010000000000000000000000e0e81100100000000000000080e81100020000000000000000000000f0e81100010000000000000000000000f8e811000f000000000000005ce8110001000000000000000000000008e9110001000000000000005265636f766572794372656174656400c26d12000900000049ea1100320000005265636f76657279496e69746961746564000000c26d120009000000c26d12000900000008ea1100410000005265636f76657279566f756368656400c26d120009000000c26d120009000000c26d120009000000b8e91100500000005265636f76657279436c6f73656400007ae911003e0000004163636f756e745265636f766572656443e91100370000005265636f7665727952656d6f7665640010e91100330000002041207265636f766572792070726f6365737320686173206265656e2072656d6f76656420666f7220616e206163636f756e74204163636f756e745f3120686173206265656e207375636365737366756c6c79207265636f7665726564206279206163636f756e745f322041207265636f766572792070726f6365737320666f72206163636f756e745f31206279206163636f756e745f3220686173206265656e20636c6f7365642041207265636f766572792070726f6365737320666f72206163636f756e745f31206279206163636f756e745f3220686173206265656e20766f756368656420666f72206279206163636f756e745f332041207265636f766572792070726f6365737320686173206265656e20696e6974696174656420666f72206163636f756e745f31206279206163636f756e745f322041207265636f766572792070726f6365737320686173206265656e2073657420757020666f7220616e206163636f756e745072696d65546f6f4561726c79416c7265616479496e697469616c697a65644475706c6963617465566f746557726f6e67496e64657850726f706f73616c4d697373696e674475706c696361746550726f706f73616c4e6f744d656d6265727365745f6d656d626572736578656375746570726f706f7365766f7465636c6f73650000000030ec1100080000000000000038ec110004000000000000000000000058ec110002000000000000000000000068ec1100050000000000000070ec110005000000000000000000000098ec1100020000000000000000000000a8ec11000800000000000000b0ec1100010000000000000000000000b8ec1100010000000000000000000000c0ec11000b00000000000000b0ec1100010000000000000000000000ccec1100010000000000000000000000d4ec11000800000000000000dcec1100020000000000000000000000ecec1100010000000000000000000000f4ec11000e00000000000000dcec110002000000000000000000000004ed11000100000000000000000000000ced1100060000000000000014ed11000300000000000000000000002ced1100010000000000000050726f706f736564c26d12000900000055ef11000d00000065ed11000400000069ed11000b000000f2ee11005300000045ef110010000000566f746564000000c26d12000900000065ed11000400000000ee11000400000069ed11000b00000069ed11000b0000006aee110042000000acee110046000000417070726f76656465ed11000400000039ee110031000000446973617070726f7665640004ee110035000000457865637574656465ed11000400000000ee110004000000bfed1100410000004d656d6265724578656375746564000074ed11004b000000436c6f736564000065ed11000400000069ed11000b00000069ed11000b00000034ed11003100000020412070726f706f73616c2077617320636c6f73656420616674657220697473206475726174696f6e207761732075702e486173684d656d626572436f756e7420412073696e676c65206d656d6265722064696420736f6d6520616374696f6e3b2060626f6f6c6020697320747275652069662072657475726e656420776974686f7574206572726f722e2041206d6f74696f6e207761732065786563757465643b2060626f6f6c6020697320747275652069662072657475726e656420776974686f7574206572726f722e626f6f6c2041206d6f74696f6e20776173206e6f7420617070726f76656420627920746865207265717569726564207468726573686f6c642e2041206d6f74696f6e2077617320617070726f76656420627920746865207265717569726564207468726573686f6c642e2041206d6f74696f6e2028676976656e20686173682920686173206265656e20766f746564206f6e20627920676976656e206163636f756e742c206c656176696e6720612074616c6c79202879657320766f74657320616e64206e6f20766f74657320676976656e20726573706563746976656c7920617320604d656d626572436f756e7460292e2041206d6f74696f6e2028676976656e20686173682920686173206265656e2070726f706f7365642028627920676976656e206163636f756e742920776974682061207468726573686f6c642028676976656e20604d656d626572436f756e7460292e50726f706f73616c496e64657850726f706f73616c734d656d62657273566f74696e67486973746f726963616c53657373696f6e73000000000000c1e611000c0000000000000018f1110002000000000000000000000048f111000d0000000000000000000000cde611000d00000000000000b0f11100020000000000000000000000e0f111000d0000000000000000000000dae611000f0000000000000048f2110003000000000000000000000090f211001b0000000000000000000000e9e61100110000000000000068f3110001000000000000000000000080f31100160000000000000000000000fae611000e00000000000000b0f1110002000000000000000000000030f4110019000000000000000000000008e711000e0000000000000068f31100010000000000000000000000f8f4110014000000000000000000000016e711000e0000000000000098f51100010000000000000000000000b0f5110014000000000000000000000024e711000f00000000000000c8b0120000000000000000000000000050f6110015000000000000000000000033e71100100000000000000068f31100010000000000000000000000f8f611000b0000000000000000000000250512000700000000000000138212000c00000000000000fb8512000400000000000000500b120017000000370a120029000000c8b012000000000088f7110045000000cdf711003a000000c8b012000000000007f811000c000000600a120049000000a90a120040000000c8b01200000000002a7f12000b000000e90a1200250000000e0b120042000000927f12000c00000000000000330a12000400000000000000138212000c00000000000000b3fd11000700000000000000138212000c00000003091200470000004a0912001d000000c8b01200000000006709120032000000c8b012000000000007f811000c000000990912002e000000c709120047000000c8b01200000000002a7f12000b0000000e0a120019000000270a12000c000000927f12000c00000000000000d60812000700000000000000e03c12001100000000000000dd0812000900000000000000e60812000300000000000000e90812000c00000000000000f50812000e0000002c05120057000000c8b0120000000000830512004c000000cf05120052000000210612002f000000c8b01200000000007881120034000000c8b012000000000007f811000c00000050061200490000009906120035000000ce0612004c0000001a071200470000006107120025000000860712004f000000d50712003a000000c8b01200000000002a7f12000b0000000f0812001a000000290812004b000000740812003b000000e304120027000000af08120027000000857f12000d000000c8b012000000000078fb11001b000000927f12000c00000000000000250512000700000000000000138212000c000000d30212003b000000c8b01200000000000e0312004700000055031200490000009e0312002e000000c8b01200000000007881120034000000c8b012000000000007f811000c000000cc031200450000001104120040000000c8b01200000000002a7f12000b000000510412003e0000008f04120054000000e30412002700000002001200390000000a0512001b000000857f12000d000000c8b012000000000078fb11001b000000927f12000c0000007d0012004a000000c70012001a000000c8b0120000000000e10012004a0000002b0112001d000000c8b012000000000007f811000c00000048011200350000007d01120044000000c101120015000000c8b0120000000000d6011200490000001f02120009000000c8b01200000000002a7f12000b00000034ff11003f00000073ff110047000000baff110048000000280212003b00000063021200470000003b00120027000000857f12000d000000c8b0120000000000aa02120029000000927f12000c000000bafd11003d000000c8b0120000000000f7fd11004b00000042fe11004700000089fe11004c000000c8b012000000000007f811000c000000d5fe11004b00000020ff110014000000c8b01200000000002a7f12000b00000034ff11003f00000073ff110047000000baff11004800000002001200390000003b00120027000000857f12000d000000c8b0120000000000620012001b000000927f12000c00000000000000b3fd11000700000000000000138212000c00000093fb110045000000d8fb11001a000000c8b0120000000000f2fb1100480000003afc11003e000000c8b012000000000027fa11004100000078fc11003c000000c8b012000000000007f811000c000000b4fc110044000000c8b01200000000002a7f12000b000000f8fc11002100000019fd11004f00000068fd110030000000857f12000d000000c8b012000000000098fd11001b000000927f12000c0000009df8110057000000c8b0120000000000f4f811004500000039f9110042000000c8b01200000000007bf9110049000000c4f9110026000000eaf911003d000000c8b012000000000027fa11004100000068fa110039000000c8b01200000000002a7f12000b000000a1fa110018000000b9fa11004a00000003fb11004e00000051fb110027000000857f12000d000000c8b012000000000078fb11001b000000927f12000c00000050f7110038000000c8b012000000000088f7110045000000cdf711003a000000c8b012000000000007f811000c00000013f8110046000000c8b01200000000002a7f12000b00000059f8110044000000927f12000c0000002043616e63656c20746865206162696c69747920746f20757365206061735f7265636f76657265646020666f7220606163636f756e74602e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e64207265676973746572656420746f2062652061626c6520746f206d616b652063616c6c73206f6e20626568616c66206f6620746865207265636f7665726564206163636f756e742e20506172616d65746572733a202d20606163636f756e74603a20546865207265636f7665726564206163636f756e7420796f75206172652061626c6520746f2063616c6c206f6e2d626568616c662d6f662e202d204f6e652073746f72616765206d75746174696f6e20746f20636865636b206163636f756e74206973207265636f7665726564206279206077686f602e204f2831292052656d6f766520746865207265636f766572792070726f6365737320666f7220796f7572206163636f756e742e205265636f7665726564206163636f756e747320617265207374696c6c2061636365737369626c652e204e4f54453a205468652075736572206d757374206d616b65207375726520746f2063616c6c2060636c6f73655f7265636f7665727960206f6e20616c6c20616374697665207265636f7665727920617474656d707473206265666f72652063616c6c696e6720746869732066756e6374696f6e20656c73652069742077696c6c206661696c2e205061796d656e743a2042792063616c6c696e6720746869732066756e6374696f6e20746865207265636f76657261626c65206163636f756e742077696c6c20756e72657365727665207468656972207265636f7665727920636f6e66696775726174696f6e206465706f7369742e202860436f6e6669674465706f7369744261736560202b2060467269656e644465706f736974466163746f7260202a20235f6f665f667269656e64732920546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e64206d7573742062652061207265636f76657261626c65206163636f756e742028692e652e206861732061207265636f7665727920636f6e66696775726174696f6e292e204b65793a204620286c656e206f6620667269656e647329202d204f6e652073746f72616765207265616420746f206765742074686520707265666978206974657261746f7220666f7220616374697665207265636f7665726965732e204f283129202d204f6e652073746f7261676520726561642f72656d6f766520746f2067657420746865207265636f7665727920636f6e66696775726174696f6e2e204f2831292c20436f646563204f284629202d204f6e652062616c616e63652063616c6c20746f20756e72657365727665642e204f28582920546f74616c20436f6d706c65786974793a204f2846202b2058292041732074686520636f6e74726f6c6c6572206f662061207265636f76657261626c65206163636f756e742c20636c6f736520616e20616374697665207265636f766572792070726f6365737320666f7220796f7572206163636f756e742e205061796d656e743a2042792063616c6c696e6720746869732066756e6374696f6e2c20746865207265636f76657261626c65206163636f756e742077696c6c207265636569766520746865207265636f76657279206465706f73697420605265636f766572794465706f7369746020706c616365642062792074686520726573637565722e207265636f76657261626c65206163636f756e74207769746820616e20616374697665207265636f766572792070726f6365737320666f722069742e202d206072657363756572603a20546865206163636f756e7420747279696e6720746f207265736375652074686973207265636f76657261626c65206163636f756e742e204b65793a205620286c656e206f6620766f756368696e6720667269656e647329202d204f6e652073746f7261676520726561642f72656d6f766520746f206765742074686520616374697665207265636f766572792070726f636573732e204f2831292c20436f646563204f285629202d204f6e652062616c616e63652063616c6c20746f20726570617472696174652072657365727665642e204f28582920546f74616c20436f6d706c65786974793a204f2856202b2058297265736375657220416c6c6f772061207375636365737366756c207265736375657220746f20636c61696d207468656972207265636f7665726564206163636f756e742e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e64206d7573742062652061202272657363756572222077686f20686173207375636365737366756c6c7920636f6d706c6574656420746865206163636f756e74207265636f766572792070726f636573733a20636f6c6c656374656420607468726573686f6c6460206f72206d6f726520766f75636865732c20776169746564206064656c61795f706572696f646020626c6f636b732073696e636520696e6974696174696f6e2e202d20606163636f756e74603a20546865206c6f7374206163636f756e74207468617420796f752077616e7420746f20636c61696d20686173206265656e207375636365737366756c6c792020207265636f766572656420627920796f752e204b65793a204620286c656e206f6620667269656e647320696e20636f6e666967292c205620286c656e206f6620766f756368696e6720667269656e647329202d204f6e652073746f72616765207265616420746f2067657420746865207265636f7665727920636f6e66696775726174696f6e2e204f2831292c20436f646563204f284629202d204f6e652073746f72616765207265616420746f206765742074686520616374697665207265636f766572792070726f636573732e204f2831292c20436f646563204f285629202d204f6e652073746f72616765207265616420746f20676574207468652063757272656e7420626c6f636b206e756d6265722e204f283129202d204f6e652073746f726167652077726974652e204f2831292c20436f646563204f2856292e20546f74616c20436f6d706c65786974793a204f2846202b20562920416c6c6f7720612022667269656e6422206f662061207265636f76657261626c65206163636f756e7420746f20766f75636820666f7220616e20616374697665207265636f766572792070726f6365737320666f722074686174206163636f756e742e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e64206d75737420626520612022667269656e642220666f7220746865207265636f76657261626c65206163636f756e742e202d20606c6f7374603a20546865206c6f7374206163636f756e74207468617420796f752077616e7420746f207265636f7665722e202d206072657363756572603a20546865206163636f756e7420747279696e6720746f2072657363756520746865206c6f7374206163636f756e74207468617420796f7520202077616e7420746f20766f75636820666f722e2054686520636f6d62696e6174696f6e206f662074686573652074776f20706172616d6574657273206d75737420706f696e7420746f20616e20616374697665207265636f766572792070726f636573732e202d204f6e652062696e6172792073656172636820746f20636f6e6669726d2063616c6c6572206973206120667269656e642e204f286c6f674629202d204f6e652062696e6172792073656172636820746f20636f6e6669726d2063616c6c657220686173206e6f7420616c726561647920766f75636865642e204f286c6f67562920546f74616c20436f6d706c65786974793a204f2846202b206c6f6746202b2056202b206c6f67562920496e697469617465207468652070726f6365737320666f72207265636f766572696e672061207265636f76657261626c65206163636f756e742e205061796d656e743a20605265636f766572794465706f736974602062616c616e63652077696c6c20626520726573657276656420666f7220696e6974696174696e6720746865207265636f766572792070726f636573732e2054686973206465706f7369742077696c6c20616c7761797320626520726570617472696174656420746f20746865206163636f756e7420747279696e6720746f206265207265636f76657265642e205365652060636c6f73655f7265636f76657279602e202d20606163636f756e74603a20546865206c6f7374206163636f756e74207468617420796f752077616e7420746f207265636f7665722e2054686973206163636f756e742020206e6565647320746f206265207265636f76657261626c652028692e652e20686176652061207265636f7665727920636f6e66696775726174696f6e292e202d204f6e652073746f72616765207265616420746f20636865636b2074686174206163636f756e74206973207265636f76657261626c652e204f284629202d204f6e652073746f72616765207265616420746f20636865636b20746861742074686973207265636f766572792070726f63657373206861736e277420616c726561647920737461727465642e204f283129202d204f6e652063757272656e63792072657365727665206f7065726174696f6e2e204f285829202d204f6e652073746f726167652077726974652e204f2831292e6163636f756e74204372656174652061207265636f7665727920636f6e66696775726174696f6e20666f7220796f7572206163636f756e742e2054686973206d616b657320796f7572206163636f756e74207265636f76657261626c652e205061796d656e743a2060436f6e6669674465706f7369744261736560202b2060467269656e644465706f736974466163746f7260202a20235f6f665f667269656e64732062616c616e63652077696c6c20626520726573657276656420666f722073746f72696e6720746865207265636f7665727920636f6e66696775726174696f6e2e2054686973206465706f7369742069732072657475726e656420696e2066756c6c207768656e2074686520757365722063616c6c73206072656d6f76655f7265636f76657279602e202d2060667269656e6473603a2041206c697374206f6620667269656e647320796f7520747275737420746f20766f75636820666f72207265636f7665727920617474656d7074732e20202053686f756c64206265206f72646572656420616e6420636f6e7461696e206e6f206475706c69636174652076616c7565732e202d20607468726573686f6c64603a20546865206e756d626572206f6620667269656e64732074686174206d75737420766f75636820666f722061207265636f7665727920617474656d70742020206265666f726520746865206163636f756e742063616e206265207265636f76657265642e2053686f756c64206265206c657373207468616e206f7220657175616c20746f202020746865206c656e677468206f6620746865206c697374206f6620667269656e64732e202d206064656c61795f706572696f64603a20546865206e756d626572206f6620626c6f636b732061667465722061207265636f7665727920617474656d707420697320696e697469616c697a656420202074686174206e6565647320746f2070617373206265666f726520746865206163636f756e742063616e206265207265636f76657265642e202d204b65793a204620286c656e206f6620667269656e647329202d204f6e652073746f72616765207265616420746f20636865636b2074686174206163636f756e74206973206e6f7420616c7265616479207265636f76657261626c652e204f2831292e202d204120636865636b20746861742074686520667269656e6473206c69737420697320736f7274656420616e6420756e697175652e204f284629202d204f6e652073746f726167652077726974652e204f2831292e20436f646563204f2846292e667269656e64737468726573686f6c6475313664656c61795f706572696f64543a3a426c6f636b4e756d62657220416c6c6f7720524f4f5420746f2062797061737320746865207265636f766572792070726f6365737320616e642073657420616e20612072657363756572206163636f756e7420666f722061206c6f7374206163636f756e74206469726563746c792e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f524f4f545f2e202d20606c6f7374603a2054686520226c6f7374206163636f756e742220746f206265207265636f76657265642e202d206072657363756572603a20546865202272657363756572206163636f756e74222077686963682063616e2063616c6c20617320746865206c6f7374206163636f756e742e202d204f6e652073746f72616765207772697465204f283129202d204f6e65206576656e746c6f73742053656e6420612063616c6c207468726f7567682061207265636f7665726564206163636f756e742e202d20606163636f756e74603a20546865207265636f7665726564206163636f756e7420796f752077616e7420746f206d616b6520612063616c6c206f6e2d626568616c662d6f662e202d206063616c6c603a205468652063616c6c20796f752077616e7420746f206d616b65207769746820746865207265636f7665726564206163636f756e742e202d2054686520776569676874206f6620746865206063616c6c60202b2031302c3030302e202d204f6e652073746f72616765206c6f6f6b757020746f20636865636b206163636f756e74206973207265636f7665726564206279206077686f602e204f283129426f783c3c542061732054726169743e3a3a43616c6c3e5265636f766572790000000000780c12000b0000000101000000000000138212000c00000000000000830c12003a00000000000000000000000000000000000000c8b01200c00c12000000000000000000d00c120001000000000000000000000000000000d80c1200100000000205050000000000138212000c00000000000000138212000c00000000000000e80c12003a00000000000000c8b01200240d12000000000000000000340d120004000000000000000000000000000000540d1200050000000101000000000000138212000c00000000000000138212000c00000000000000000000000000000000000000c8b012001c1a120000000000000000005c0d12000300000000000000000000005265636f76657261626c655265636f76657279436f6e6669673c543a3a426c6f636b4e756d6265722c2042616c616e63654f663c543e2c20543a3a4163636f756e7449643e0000003c000000000000000100000051000000600e1200420000004163746976655265636f7665726965734163746976655265636f766572793c543a3a426c6f636b4e756d6265722c2042616c616e63654f663c543e2c20543a3a4163636f756e7449643e00003c000000000000000100000051000000d60d12001a000000c8b0120000000000f00d120045000000350e12002b00000050726f7879000000740d120024000000c8b0120000000000980d12003e00000020546865206c697374206f6620616c6c6f7765642070726f7879206163636f756e74732e204d61702066726f6d2074686520757365722077686f2063616e2061636365737320697420746f20746865207265636f7665726564206163636f756e742e20416374697665207265636f7665727920617474656d7074732e204669727374206163636f756e7420697320746865206163636f756e7420746f206265207265636f76657265642c20616e6420746865207365636f6e64206163636f756e7420697320746865207573657220747279696e6720746f207265636f76657220746865206163636f756e742e2054686520736574206f66207265636f76657261626c65206163636f756e747320616e64207468656972207265636f7665727920636f6e66696775726174696f6e2e000000000000daea11000b00000000000000800f1200020000000000000000000000b00f1200060000000000000000000000e5ea11000700000000000000e00f1200010000000000000000000000f80f1200030000000000000000000000ecea110007000000000000001010120002000000000000000000000040101200040000000000000000000000f3ea1100040000000000000060101200030000000000000000000000a8101200040000000000000000000000f7ea11000500000000000000c8101200020000000000000000000000f81012000d0000000000000000000000b81512000b00000000000000e03c12001100000000000000c31512000500000000000000c8151200140000000915120021000000c8b01200000000002a1512003f0000006915120039000000c8b0120000000000a21512001600000000000000791312000800000000000000831412001e000000a11412003d000000c8b0120000000000de1412002b00000000000000dd08120009000000000000006f1412001400000000000000791312000800000000000000831412001e0000002a7f12000b0000001d14120024000000411412002e000000927f12000c000000000000007913120008000000000000008113120007000000000000001f821200050000000000000088131200160000000000000016141200070000000000000000ee1100040000002a7f12000b0000009e13120023000000c113120055000000927f12000c000000000000007913120008000000000000008113120007000000000000001f821200050000000000000088131200160000006011120054000000b411120026000000c8b0120000000000da111200570000003112120019000000c8b01200000000004a121200250000006f121200200000008f12120043000000d21212002c000000fe1212001e0000001c131200270000004313120036000000204d61792062652063616c6c656420627920616e79207369676e6564206163636f756e742061667465722074686520766f74696e67206475726174696f6e2068617320656e64656420696e206f7264657220746f2066696e69736820766f74696e6720616e6420636c6f7365207468652070726f706f73616c2e2041627374656e74696f6e732061726520636f756e7465642061732072656a656374696f6e7320756e6c6573732074686572652069732061207072696d65206d656d6265722073657420616e6420746865207072696d65206d656d626572206361737420616e20617070726f76616c2e202d2074686520776569676874206f66206070726f706f73616c6020707265696d6167652e202d20757020746f207468726565206576656e7473206465706f73697465642e202d206f6e6520726561642c2074776f2072656d6f76616c732c206f6e65206d75746174696f6e2e2028706c7573207468726565207374617469632072656164732e29202d20636f6d7075746174696f6e20616e6420692f6f20604f2850202b204c202b204d29602077686572653a2020202d20604d60206973206e756d626572206f66206d656d626572732c2020202d20605060206973206e756d626572206f66206163746976652070726f706f73616c732c2020202d20604c602069732074686520656e636f646564206c656e677468206f66206070726f706f73616c6020707265696d6167652e70726f706f73616c543a3a48617368436f6d706163743c50726f706f73616c496e6465783e202d20426f756e6465642073746f72616765207265616420616e64207772697465732e202d2057696c6c20626520736c696768746c792068656176696572206966207468652070726f706f73616c20697320617070726f766564202f20646973617070726f7665642061667465722074686520766f74652e617070726f7665202d20426f756e6465642073746f7261676520726561647320616e64207772697465732e202d20417267756d656e7420607468726573686f6c6460206861732062656172696e67206f6e207765696768742e436f6d706163743c4d656d626572436f756e743e426f783c3c542061732054726169743c493e3e3a3a50726f706f73616c3e20446973706174636820612070726f706f73616c2066726f6d2061206d656d626572207573696e672074686520604d656d62657260206f726967696e2e204f726967696e206d7573742062652061206d656d626572206f662074686520636f6c6c6563746976652e205365742074686520636f6c6c6563746976652773206d656d626572736869702e202d20606e65775f6d656d62657273603a20546865206e6577206d656d626572206c6973742e204265206e69636520746f2074686520636861696e20616e64202d20607072696d65603a20546865207072696d65206d656d6265722077686f736520766f74652073657473207468652064656661756c742e20526571756972657320726f6f74206f726967696e2e6e65775f6d656d626572737072696d654f7074696f6e3c543a3a4163636f756e7449643e5665633c543a3a486173683eb81712002400000050726f706f73616c4f663c542061732054726169743c493e3e3a3a50726f706f73616c008517120033000000566f7465733c543a3a4163636f756e7449642c20543a3a426c6f636b4e756d6265723e00581712002d0000004617120012000000f81612004e0000006816120057000000bf1612003900000020546865206d656d6265722077686f2070726f7669646573207468652064656661756c7420766f746520666f7220616e79206f74686572206d656d62657273207468617420646f206e6f7420766f7465206265666f7265207468652074696d656f75742e204966204e6f6e652c207468656e206e6f206d656d6265722068617320746861742070726976696c6567652e205468652063757272656e74206d656d62657273206f662074686520636f6c6c6563746976652e20546869732069732073746f72656420736f7274656420286a7573742062792076616c7565292e2050726f706f73616c7320736f206661722e20566f746573206f6e206120676976656e2070726f706f73616c2c206966206974206973206f6e676f696e672e2041637475616c2070726f706f73616c20666f72206120676976656e20686173682c20696620697427732063757272656e742e2054686520686173686573206f6620746865206163746976652070726f706f73616c732e0000000062ef1100090000000000000000000000dc1512000c00000000000000000000000000000000000000000000000000000000000000c8b01200ec1912000000000000000000e815120001000000000000000100000000000000f01512000a0000000101000000000000811312000700000000000000fa1512001900000000000000000000000000000000000000c8b012001c1a12000000000000000000141612000100000000000000000000000000000072ef11000600000001010000000000008113120007000000000000001c1612002300000000000000000000000000000000000000c8b012001c1a120000000000000000004016120001000000000000000000000000000000889112000d0000000000000000000000847212000300000000000000000000000000000000000000000000000000000000000000c8b01200fc191200000000000000000048161200010000000000000001000000000000006bef1100070000000000000000000000e03c12001100000000000000000000000000000000000000000000000000000000000000c8b012000c1a1200000000000000000050161200010000000000000001000000000000007bea1100050000000000000000000000138212000c00000000000000000000000000000000000000000000000000000000000000c8b012001c1a12000000000000000000581612000200000000000000000000003c0000000000000001000000590000003c00000000000000010000006b0000003c0000000000000001000000590000003c00000000000000010000005100000000000000b7e611000a00000000000000ec1b1200010000000000000000000000aae611000d00000000000000f41b12000100000000000000000000009ae611001000000000000000fc1b120001000000000000000000000090e611000a00000000000000041c120001000000000000000000000087e6110009000000000000000c1c120001000000000000000000000079e611000e00000000000000141c120001000000000000000000000067e6110012000000000000001c1c120001000000000000000000000059e611000e00000000000000241c12000100000000000000000000004fe611000a000000000000002c1c120001000000000000000000000046e611000900000000000000341c12000100000000000000000000003be611000b000000000000003c1c12000100000000000000000000002de611000e00000000000000441c120001000000000000000000000024e6110009000000000000004c1c120001000000000000000000000019e611000b00000000000000541c120001000000000000000000000011e6110008000000000000005c1c120001000000000000000000000005e611000c000000000000001c1c120001000000000000001f1f12003d000000fb1e120024000000c61e1200350000009b1e12002b000000681e120033000000401e120028000000141e12002c000000dc1d120038000000a81d1200340000007d1d12002b000000361d120047000000061d120030000000cb1c12003b0000008b1c120040000000641c1200270000002054686572652077617320616e206f766572666c6f7720696e20612063616c63756c6174696f6e20546865726520617265207374696c6c20616374697665207265636f7665727920617474656d7074732074686174206e65656420746f20626520636c6f73656420546865207468726573686f6c6420666f72207265636f766572696e672074686973206163636f756e7420686173206e6f74206265656e206d6574205468697320757365722068617320616c726561647920766f756368656420666f722074686973207265636f766572792054686520667269656e64206d757374207761697420756e74696c207468652064656c617920706572696f6420746f20766f75636820666f722074686973207265636f766572792054686973206163636f756e74206973206e6f74206120667269656e642077686f2063616e20766f7563682041207265636f766572792070726f6365737320686173206e6f74207374617274656420666f72207468697320726573637565722041207265636f766572792070726f636573732068617320616c7265616479207374617274656420666f722074686973206163636f756e742054686973206163636f756e7420697320616c72656164792073657420757020666f72207265636f766572792054686973206163636f756e74206973206e6f742073657420757020666f72207265636f7665727920467269656e6473206c697374206d75737420626520736f7274656420616e642066726565206f66206475706c69636174657320467269656e6473206c697374206d757374206265206c657373207468616e206d617820667269656e647320467269656e6473206c697374206d7573742062652067726561746572207468616e207a65726f20616e64207468726573686f6c64205468726573686f6c64206d7573742062652067726561746572207468616e207a65726f2055736572206973206e6f7420616c6c6f77656420746f206d616b6520612063616c6c206f6e20626568616c66206f662074686973206163636f756e7400000000d1ea1100090000000000000020201200010000000000000000000000c0ea1100110000000000000028201200010000000000000000000000b1ea11000f0000000000000030201200010000000000000000000000a7ea11000a00000000000000382012000100000000000000000000009aea11000d000000000000004020120001000000000000000000000088ea110012000000000000004820120001000000000000000000000080ea110008000000000000005020120001000000000000001521120018000000f520120020000000e120120014000000d020120011000000b920120017000000982012002100000058201200400000002054686520636c6f73652063616c6c206973206d61646520746f6f206561726c792c206265666f72652074686520656e64206f662074686520766f74696e672e204d656d626572732061726520616c726561647920696e697469616c697a656421204475706c696361746520766f74652069676e6f726564204d69736d61746368656420696e6465782050726f706f73616c206d757374206578697374204475706c69636174652070726f706f73616c73206e6f7420616c6c6f776564204163636f756e74206973206e6f742061206d656d626572000000bb2112000d0000009e2112001b000000b9211200020000005821120046000000a9020000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f62696e2f6e6f64652f72756e74696d652f7372632f6c69622e727342616420696e70757420646174612070726f766964656420746f203a20657865637574655f626c6f636bd021120010000000696e697469616c697a655f626c6f636be82112000f0000006170706c795f65787472696e736963000022120013000000696e686572656e745f65787472696e73696373001c2212000f000000636865636b5f696e686572656e747300342212001400000076616c69646174655f7472616e73616374696f6e502212000f0000006f6666636861696e5f776f726b657200682212000d0000006163636f756e745f6e6f6e6365000000fb85120004000000882212000b0000006765745f73746f72616765009c2212000f00000072656e745f70726f6a656374696f6e00b42212000a00000071756572795f696e666f0000c82212001500000067656e65726174655f73657373696f6e5f6b657973000000e8221200130000006465636f64655f73657373696f6e5f6b657973486561644f664e6f6d696e61746f72734e6f6d696e61746f7273486561644f6656616c696461746f727356616c696461746f7273496e76616c69644e756d6265724f664e6f6d696e6174696f6e73496e76616c6964457261546f52657761726446756e6465645461726765744e6f556e6c6f636b4368756e6b4e6f4d6f72654368756e6b73496e73756666696369656e7456616c7565496e76616c6964536c617368496e6465784475706c6963617465496e646578456d70747954617267657473416c7265616479506169726564416c7265616479426f6e6465644e6f7453746173684e6f74436f6e74726f6c6c65725761726e696e673a20412073657373696f6e206170706561727320746f2068617665206265656e20736b69707065642e626f6e64626f6e645f6578747261756e626f6e6477697468647261775f756e626f6e64656476616c69646174656e6f6d696e6174656368696c6c7365745f70617965657365745f636f6e74726f6c6c65727365745f76616c696461746f725f636f756e74666f7263655f6e6f5f65726173666f7263655f6e65775f6572617365745f696e76756c6e657261626c6573666f7263655f756e7374616b65666f7263655f6e65775f6572615f616c7761797363616e63656c5f64656665727265645f736c6173687061796f75745f6e6f6d696e61746f727061796f75745f76616c696461746f727265626f6e647365745f686973746f72795f6465707468726561705f7374617368426f6e6465644c6564676572416374697665457261457261735374616b657273457261735374616b657273436c69707065644572617356616c696461746f72507265667345726173526577617264506f696e747345726173546f74616c5374616b6556616c696461746f72536c617368496e4572614e6f6d696e61746f72536c617368496e457261536c617368696e675370616e735370616e536c61736800000000004426120006000000000000004c2612000200000000000000000000005c2612000100000000000000000000006426120005000000000000004c2612000200000000000000000000006c261200010000000000000000000000742612001a00000000000000888f12000100000000000000000000009026120002000000000000005265776172640000c26d1200090000009027120007000000422712004e000000536c617368000000f9261200490000004f6c64536c617368696e675265706f72744469736361726465640000a026120047000000e72612001200000020416e206f6c6420736c617368696e67207265706f72742066726f6d2061207072696f72206572612077617320646973636172646564206265636175736520697420636f756c64206e6f742062652070726f6365737365642e204f6e652076616c696461746f722028616e6420697473206e6f6d696e61746f72732920686173206265656e20736c61736865642062792074686520676976656e20616d6f756e742e20546865207374616b657220686173206265656e207265776172646564206279207468697320616d6f756e742e204163636f756e74496420697320636f6e74726f6c6c6572206163636f756e742e42616c616e63654572617356616c696461746f725265776172644572726f723a2073746172745f73657373696f6e5f696e646578206d7573742062652073657420666f722063757272656e745f657261556e6170706c696564536c6173686573000000001b24120004000000000000008c2b1200030000000000000000000000d42b12000f00000000000000000000001f2412000a000000000000004c2c1200010000000000000000000000642c12000e0000000000000000000000292412000600000000000000d42c1200010000000000000000000000ec2c12001800000000000000000000002f2412001100000000000000c8b01200000000000000000000000000ac2d12001000000000000000000000004024120008000000000000002c2e1200010000000000000000000000442e12000b00000000000000000000004824120008000000000000009c2e1200010000000000000000000000b42e12000b0000000000000000000000502412000500000000000000c8b012000000000000000000000000000c2f12000b0000000000000000000000552412000900000000000000642f12000100000000000000000000007c2f12000b00000000000000000000005e2412000e00000000000000d42f1200010000000000000000000000ec2f12000b00000000000000000000006c2412001300000000000000443012000100000000000000000000005c3012000100000000000000000000007f2412000d00000000000000c8b01200000000000000000000000000643012000500000000000000000000008c2412000d00000000000000c8b012000000000000000000000000008c301200060000000000000000000000992412001100000000000000bc301200010000000000000000000000d4301200010000000000000000000000aa2412000d00000000000000dc301200010000000000000000000000f4301200010000000000000000000000b72412001400000000000000c8b01200000000000000000000000000fc301200050000000000000000000000cb24120015000000000000002431120002000000000000000000000054311200070000000000000000000000e024120010000000000000008c311200020000000000000000000000bc311200170000000000000000000000f02412001000000000000000743212000100000000000000000000008c3212000f0000000000000000000000002512000600000000000000d42c120001000000000000000000000004331200060000000000000000000000062512001100000000000000343312000100000000000000000000004c331200030000000000000000000000172512000a00000000000000dc30120001000000000000000000000064331200070000000000000000000000163f12000a00000000000000203f120023000000000000007c4712000500000000000000814712001500000000000000c63f12000500000000000000cb3f120011000000d2481200590000002b49120021000000c8b01200000000004c4912004c000000c8b01200000000009849120049000000c8b01200000000002a7f12000b000000e149120035000000bc48120008000000164a12001a000000c8b0120000000000304a12005b0000008b4a120049000000927f12000c00000000000000c44812000e0000000000000081471200150000009647120059000000ef4712000d000000c8b0120000000000fc471200540000005048120059000000a948120013000000c8b01200000000002f3e120055000000c8b01200000000002a7f12000b000000843e12003a000000bc481200080000006247120010000000927f12000c000000000000007c471200050000000000000081471200150000008f43120055000000e4431200400000002444120049000000c8b01200000000006d44120052000000bf44120030000000c8b0120000000000ef4412004f0000003e4512004f0000008d4512003f000000c8b0120000000000713f120055000000c8b0120000000000cc45120026000000c8b01200000000002a7f12000b000000f245120050000000be3e12002600000042461200590000009b4612005c000000f7461200540000004b471200170000006247120010000000724712000a000000884112004b000000c8b0120000000000d34112004d0000002042120013000000c8b0120000000000713f120055000000c8b0120000000000334212001b000000c8b01200000000002a7f12000b0000004e42120055000000a342120051000000f44212003d000000314312005e000000e43e120032000000927f12000c000000000000007541120005000000000000007a4112000e0000003b4112003a000000c8b0120000000000f83d120037000000c8b0120000000000713f120055000000c8b01200000000002a7f12000b000000843e12003a000000be3e120026000000e43e120032000000927f12000c000000000000000c411200070000000000000013411200280000002340120044000000c8b0120000000000f83d120037000000c8b0120000000000713f120055000000c8b01200000000002a7f12000b0000006740120049000000b040120026000000d640120036000000927f12000c000000dc3f120032000000c8b0120000000000f83d120037000000c8b0120000000000713f120055000000c8b01200000000002a7f12000b000000843e12003a0000000e40120015000000e43e120032000000927f12000c00000000000000c63f12000500000000000000cb3f120011000000433f12002e000000c8b0120000000000f83d120037000000c8b0120000000000713f120055000000c8b01200000000002a7f12000b000000843e12003a000000be3e120026000000e43e120032000000927f12000c00000000000000163f12000a00000000000000203f120023000000d43d120024000000c8b0120000000000f83d120037000000c8b01200000000002f3e120055000000c8b01200000000002a7f12000b000000843e12003a000000be3e120026000000e43e120032000000927f12000c00000000000000108212000300000000000000c83d12000c000000a83d1200200000007c3d12002c000000c8b01200000000002a7f12000b0000006c3d120010000000927f12000c000000f13c120053000000443d120028000000c8b01200000000002a7f12000b0000006c3d120010000000927f12000c00000000000000163b12000a00000000000000e03c120011000000ad3c12003300000000000000a83c12000500000000000000138212000c000000653c120043000000103c120041000000c8b01200000000002a7f12000b000000513c120014000000927f12000c00000000000000e43712000300000000000000e73712000800000000000000fb3b12000d00000000000000083c120008000000383b120051000000893b12001c000000a53b120041000000c8b01200000000002a7f12000b000000e63b120015000000927f12000c00000000000000e43712000300000000000000e73712000800000000000000163b12000a00000000000000203b120018000000ef37120029000000c8b0120000000000183812003f0000003f36120059000000983612004c0000005738120056000000ad38120048000000f538120028000000c8b0120000000000e4361200570000003b3712000e000000c8b01200000000004937120051000000c8b01200000000002a7f12000b0000001d3912005700000074391200270000009b3912004e000000e939120037000000203a120050000000703a120052000000c23a120054000000927f12000c00000000000000e43712000300000000000000e737120008000000d735120029000000c8b0120000000000003612003f0000003f36120059000000983612004c000000c8b0120000000000e4361200570000003b3712000e000000c8b01200000000004937120051000000c8b01200000000002a7f12000b0000009a37120019000000b337120031000000927f12000c0000002635120038000000c8b01200000000002a7f12000b0000005e3512003c0000009a3512003d000000927f12000c000000000000000435120011000000000000001535120011000000d634120019000000c8b0120000000000ef341200150000009c3312004e000000ea331200580000004234120030000000c8b01200000000007234120024000000c8b012000000000096341200400000002052656d6f766520616c6c20646174612073747275637475726520636f6e6365726e696e672061207374616b65722f7374617368206f6e6365206974732062616c616e6365206973207a65726f2e205468697320697320657373656e7469616c6c79206571756976616c656e7420746f206077697468647261775f756e626f6e64656460206578636570742069742063616e2062652063616c6c656420627920616e796f6e6520616e6420746865207461726765742060737461736860206d7573742068617665206e6f2066756e6473206c6566742e20546869732063616e2062652063616c6c65642066726f6d20616e79206f726967696e2e202d20607374617368603a20546865207374617368206163636f756e7420746f20726561702e204974732062616c616e6365206d757374206265207a65726f2e2053657420686973746f72795f64657074682076616c75652e204f726967696e206d75737420626520726f6f742e6e65775f686973746f72795f6465707468436f6d706163743c457261496e6465783e205265626f6e64206120706f7274696f6e206f6620746865207374617368207363686564756c656420746f20626520756e6c6f636b65642e202d2054696d6520636f6d706c65786974793a204f2831292e20426f756e64656420627920604d41585f554e4c4f434b494e475f4348554e4b53602e202d2053746f72616765206368616e6765733a2043616e277420696e6372656173652073746f726167652c206f6e6c792064656372656173652069742e204d616b65206f6e652076616c696461746f722773207061796f757420666f72206f6e65206572612e202d206077686f602069732074686520636f6e74726f6c6c6572206163636f756e74206f66207468652076616c696461746f7220746f20706179206f75742e202d206065726160206d6179206e6f74206265206c6f776572207468616e206f6e6520666f6c6c6f77696e6720746865206d6f737420726563656e746c792070616964206572612e204966206974206973206869676865722c2020207468656e20697420696e6469636174657320616e20696e737472756374696f6e20746f20736b697020746865207061796f7574206f6620616c6c2070726576696f757320657261732e205741524e494e473a206f6e636520616e2065726120697320706179656420666f7220612076616c696461746f7220737563682076616c696461746f722063616e277420636c61696d20746865207061796f7574206f662070726576696f7573206572612e205741524e494e473a20496e636f727265637420617267756d656e747320686572652063616e20726573756c7420696e206c6f7373206f66207061796f75742e2042652076657279206361726566756c2e202d2054696d6520636f6d706c65786974793a204f2831292e202d20436f6e7461696e732061206c696d69746564206e756d626572206f6620726561647320616e64207772697465732e657261457261496e646578204d616b65206f6e65206e6f6d696e61746f722773207061796f757420666f72206f6e65206572612e202d206077686f602069732074686520636f6e74726f6c6c6572206163636f756e74206f6620746865206e6f6d696e61746f7220746f20706179206f75742e202d206076616c696461746f72736020697320746865206c697374206f6620616c6c2076616c696461746f72732074686174206077686f6020686164206578706f7375726520746f20647572696e672060657261602e202020496620697420697320696e636f6d706c6574652c207468656e206c657373207468616e207468652066756c6c207265776172642077696c6c2062652070616964206f75742e2020204974206d757374206e6f742065786365656420604d41585f4e4f4d494e4154494f4e53602e202d204e756d626572206f662073746f726167652072656164206f6620604f2876616c696461746f727329603b206076616c696461746f7273602069732074686520617267756d656e74206f66207468652063616c6c2c202020616e6420697320626f756e64656420627920604d41585f4e4f4d494e4154494f4e53602e202d20456163682073746f72616765207265616420697320604f284e29602073697a6520616e64206465636f646520636f6d706c65786974793b20604e602069732074686520206d6178696d756d2020206e6f6d696e6174696f6e7320746861742063616e20626520676976656e20746f20612073696e676c652076616c696461746f722e202d20436f6d7075746174696f6e20636f6d706c65786974793a20604f284d41585f4e4f4d494e4154494f4e53202a206c6f674e29603b20604d41585f4e4f4d494e4154494f4e5360206973207468652020206d6178696d756d206e756d626572206f662076616c696461746f72732074686174206d6179206265206e6f6d696e6174656420627920612073696e676c65206e6f6d696e61746f722c206974206973202020626f756e646564206f6e6c792065636f6e6f6d6963616c6c792028616c6c206e6f6d696e61746f72732061726520726571756972656420746f20706c6163652061206d696e696d756d207374616b65292e76616c696461746f72735665633c28543a3a4163636f756e7449642c20753332293e2043616e63656c20656e6163746d656e74206f66206120646566657272656420736c6173682e2043616e2062652063616c6c6564206279206569746865722074686520726f6f74206f726967696e206f72207468652060543a3a536c61736843616e63656c4f726967696e602e2070617373696e67207468652065726120616e6420696e6469636573206f662074686520736c617368657320666f7220746861742065726120746f206b696c6c2e202d204f6e652073746f726167652077726974652e736c6173685f696e64696365735665633c7533323e20466f72636520746865726520746f2062652061206e6577206572612061742074686520656e64206f662073657373696f6e7320696e646566696e6974656c792e202d204f6e652073746f7261676520777269746520466f72636520612063757272656e74207374616b657220746f206265636f6d6520636f6d706c6574656c7920756e7374616b65642c20696d6d6564696174656c792e737461736820536574207468652076616c696461746f72732077686f2063616e6e6f7420626520736c61736865642028696620616e79292e5665633c543a3a4163636f756e7449643e20466f72636520746865726520746f2062652061206e6577206572612061742074686520656e64206f6620746865206e6578742073657373696f6e2e20416674657220746869732c2069742077696c6c20626520726573657420746f206e6f726d616c20286e6f6e2d666f7263656429206265686176696f75722e202d204e6f20617267756d656e74732e20466f72636520746865726520746f206265206e6f206e6577206572617320696e646566696e6974656c792e2054686520696465616c206e756d626572206f662076616c696461746f72732e436f6d706163743c7533323e202852652d297365742074686520636f6e74726f6c6c6572206f6620612073746173682e20456666656374732077696c6c2062652066656c742061742074686520626567696e6e696e67206f6620746865206e657874206572612e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f206279207468652073746173682c206e6f742074686520636f6e74726f6c6c65722e202d20496e646570656e64656e74206f662074686520617267756d656e74732e20496e7369676e69666963616e7420636f6d706c65786974792e202d20436f6e7461696e732061206c696d69746564206e756d626572206f662072656164732e202d2057726974657320617265206c696d6974656420746f2074686520606f726967696e60206163636f756e74206b65792e636f6e74726f6c6c65723c543a3a4c6f6f6b7570206173205374617469634c6f6f6b75703e3a3a536f75726365202852652d2973657420746865207061796d656e742074617267657420666f72206120636f6e74726f6c6c65722e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f2062792074686520636f6e74726f6c6c65722c206e6f74207468652073746173682e706179656552657761726444657374696e6174696f6e204465636c617265206e6f2064657369726520746f206569746865722076616c6964617465206f72206e6f6d696e6174652e202d20436f6e7461696e73206f6e6520726561642e204465636c617265207468652064657369726520746f206e6f6d696e6174652060746172676574736020666f7220746865206f726967696e20636f6e74726f6c6c65722e202d20546865207472616e73616374696f6e277320636f6d706c65786974792069732070726f706f7274696f6e616c20746f207468652073697a65206f66206074617267657473602c2077686963682069732063617070656420617420604d41585f4e4f4d494e4154494f4e53602e202d20426f74682074686520726561647320616e642077726974657320666f6c6c6f7720612073696d696c6172207061747465726e2e746172676574735665633c3c543a3a4c6f6f6b7570206173205374617469634c6f6f6b75703e3a3a536f757263653e204465636c617265207468652064657369726520746f2076616c696461746520666f7220746865206f726967696e20636f6e74726f6c6c65722e707265667356616c696461746f7250726566732052656d6f766520616e7920756e6c6f636b6564206368756e6b732066726f6d207468652060756e6c6f636b696e67602071756575652066726f6d206f7572206d616e6167656d656e742e205468697320657373656e7469616c6c7920667265657320757020746861742062616c616e636520746f206265207573656420627920746865207374617368206163636f756e7420746f20646f2077686174657665722069742077616e74732e2053656520616c736f205b6043616c6c3a3a756e626f6e64605d2e202d20436f756c6420626520646570656e64656e74206f6e2074686520606f726967696e6020617267756d656e7420616e6420686f77206d7563682060756e6c6f636b696e6760206368756e6b732065786973742e2020497420696d706c6965732060636f6e736f6c69646174655f756e6c6f636b656460207768696368206c6f6f7073206f76657220604c65646765722e756e6c6f636b696e67602c2077686963682069732020696e6469726563746c7920757365722d636f6e74726f6c6c65642e20536565205b60756e626f6e64605d20666f72206d6f72652064657461696c2e202d20436f6e7461696e732061206c696d69746564206e756d626572206f662072656164732c20796574207468652073697a65206f6620776869636820636f756c64206265206c61726765206261736564206f6e20606c6564676572602e205363686564756c65206120706f7274696f6e206f662074686520737461736820746f20626520756e6c6f636b656420726561647920666f72207472616e73666572206f75742061667465722074686520626f6e6420706572696f6420656e64732e2049662074686973206c656176657320616e20616d6f756e74206163746976656c7920626f6e646564206c657373207468616e20543a3a43757272656e63793a3a6d696e696d756d5f62616c616e636528292c207468656e20697420697320696e6372656173656420746f207468652066756c6c20616d6f756e742e204f6e63652074686520756e6c6f636b20706572696f6420697320646f6e652c20796f752063616e2063616c6c206077697468647261775f756e626f6e6465646020746f2061637475616c6c79206d6f7665207468652066756e6473206f7574206f66206d616e6167656d656e7420726561647920666f72207472616e736665722e204e6f206d6f7265207468616e2061206c696d69746564206e756d626572206f6620756e6c6f636b696e67206368756e6b73202873656520604d41585f554e4c4f434b494e475f4348554e4b5360292063616e20636f2d657869737473206174207468652073616d652074696d652e20496e207468617420636173652c205b6043616c6c3a3a77697468647261775f756e626f6e646564605d206e65656420746f2062652063616c6c656420666972737420746f2072656d6f766520736f6d65206f6620746865206368756e6b732028696620706f737369626c65292e2053656520616c736f205b6043616c6c3a3a77697468647261775f756e626f6e646564605d2e202d20496e646570656e64656e74206f662074686520617267756d656e74732e204c696d697465642062757420706f74656e7469616c6c79206578706c6f697461626c6520636f6d706c65786974792e202d20456163682063616c6c20287265717569726573207468652072656d61696e646572206f662074686520626f6e6465642062616c616e636520746f2062652061626f766520606d696e696d756d5f62616c616e6365602920202077696c6c2063617573652061206e657720656e74727920746f20626520696e73657274656420696e746f206120766563746f722028604c65646765722e756e6c6f636b696e676029206b65707420696e2073746f726167652e202020546865206f6e6c792077617920746f20636c65616e207468652061666f72656d656e74696f6e65642073746f72616765206974656d20697320616c736f20757365722d636f6e74726f6c6c6564207669612020206077697468647261775f756e626f6e646564602e202d204f6e6520444220656e7472792e203c2f7765696768743e76616c7565436f6d706163743c42616c616e63654f663c543e3e2041646420736f6d6520657874726120616d6f756e742074686174206861766520617070656172656420696e207468652073746173682060667265655f62616c616e63656020696e746f207468652062616c616e636520757020666f72207374616b696e672e20557365207468697320696620746865726520617265206164646974696f6e616c2066756e647320696e20796f7572207374617368206163636f756e74207468617420796f75207769736820746f20626f6e642e20556e6c696b65205b60626f6e64605d206f72205b60756e626f6e64605d20746869732066756e6374696f6e20646f6573206e6f7420696d706f736520616e79206c696d69746174696f6e206f6e2074686520616d6f756e7420746861742063616e2062652061646465642e202d204f2831292e6d61785f6164646974696f6e616c2054616b6520746865206f726967696e206163636f756e74206173206120737461736820616e64206c6f636b207570206076616c756560206f66206974732062616c616e63652e2060636f6e74726f6c6c6572602077696c6c20626520746865206163636f756e74207468617420636f6e74726f6c732069742e206076616c756560206d757374206265206d6f7265207468616e2074686520606d696e696d756d5f62616c616e636560207370656369666965642062792060543a3a43757272656e6379602e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20627920746865207374617368206163636f756e742e202d20496e646570656e64656e74206f662074686520617267756d656e74732e204d6f64657261746520636f6d706c65786974792e202d20546872656520657874726120444220656e74726965732e204e4f54453a2054776f206f66207468652073746f726167652077726974657320286053656c663a3a626f6e646564602c206053656c663a3a7061796565602920617265205f6e657665725f20636c65616e656420756e6c6573732074686520606f726967696e602066616c6c732062656c6f77205f6578697374656e7469616c206465706f7369745f20616e6420676574732072656d6f76656420617320647573742e00000000239012000c0000000000000000000000847212000300000000000000000000000000000000000000000000000000000000000000c8b01200cc5412000000000000000000dc541200070000000000000001000000000000002f9012000e0000000000000000000000847212000300000000000000000000000000000000000000000000000000000000000000c8b0120014551200000000000000000024551200010000000000000001000000000000003d901200150000000000000000000000847212000300000000000000000000000000000000000000000000000000000000000000c8b012002c55120000000000000000003c55120001000000000000000100000000000000445512000d0000000000000000000000e03c12001100000000000000000000000000000000000000000000000000000000000000c8b01200545512000000000000000000645512000300000000000000010000000000000021251200060000000101000000000000138212000c00000000000000138212000c00000000000000000000000000000000000000c8b01200b055120000000000000000007c5512000100000000000000000000000000000027251200060000000101000000000000138212000c00000000000000845512002900000000000000000000000000000000000000c8b01200b05512000000000000000000c055120001000000000000000000000000000000c8551200050000000101000000000000138212000c00000000000000cb3f12001100000000000000000000000000000000000000c8b01200d05512000000000000000000e055120001000000000000000100000000000000252312000a0000000101010000000000138212000c000000000000007a4112000e00000000000000000000000000000000000000c8b012004c5712000000000000000000e8551200010000000000000001000000000000000b2312000a0000000101010000000000138212000c00000000000000f05512001900000000000000000000000000000000000000c8b012000c56120000000000000000001c56120001000000000000000000000000000000529012000a0000000000000000000000e73712000800000000000000000000000000000000000000000000000000000000000000c8b01200fc591200000000000000000024561200040000000000000000000000000000002d251200090000000000000000000000445612001a00000000000000000000000000000000000000000000000000000000000000c8b0120060561200000000000000000070561200040000000000000000000000000000005c901200150000000101000000000000e73712000800000000000000179012000c00000000000000000000000000000000000000c8b01200fc59120000000000000000009056120001000000000000000000000000000000362512000b0000000205050000000000e73712000800000000000000138212000c00000000000000985612002400000000000000c8b01200ec5612000000000000000000bc5612000600000000000000010000000000000041251200120000000205050000000000e73712000800000000000000138212000c00000000000000985612002400000000000000c8b01200ec5612000000000000000000fc5612000a00000000000000010000000000000053251200120000000205050000000000e73712000800000000000000138212000c000000000000007a4112000e00000000000000c8b012004c57120000000000000000005c5712000500000000000000010000000000000097271200130000000101000000000000e73712000800000000000000845712000c00000000000000000000000000000000000000c8b012004c5912000000000000000000905712000300000000000000000000000000000065251200100000000101000000000000e73712000800000000000000a85712001d00000000000000000000000000000000000000c8b01200c85712000000000000000000d857120002000000000000000100000000000000752512000e0000000101000000000000e73712000800000000000000845712000c00000000000000000000000000000000000000c8b012005c5812000000000000000000e85712000200000000000000010000000000000071901200080000000000000000000000f85712000700000000000000000000000000000000000000000000000000000000000000c8b01200005812000000000000000000105812000100000000000000010000000000000079901200130000000000000000000000185812000700000000000000000000000000000000000000000000000000000000000000c8b01200205812000000000000000000305812000300000000000000010000000000000048581200130000000000000000000000845712000c00000000000000000000000000000000000000000000000000000000000000c8b012005c58120000000000000000006c58120002000000000000000100000000000000e0271200100000000101000000000000e737120008000000000000007c5812002f00000000000000000000000000000000000000c8b01200ac5812000000000000000000bc581200010000000000000001000000000000008c9012000a0000000000000000000000c45812001d00000000000000000000000000000000000000000000000000000000000000c8b01200e45812000000000000000000f45812000400000000000000010000000000000083251200130000000201030000000000e73712000800000000000000138212000c00000000000000145912001700000000000000c8b012002c59120000000000000000003c5912000200000000000000000000000000000096251200130000000201030000000000e73712000800000000000000138212000c00000000000000845712000c00000000000000c8b012004c59120000000000000000005c59120001000000000000000000000000000000a92512000d0000000101000000000000138212000c00000000000000645912001700000000000000000000000000000000000000c8b012007c59120000000000000000008c59120001000000000000000000000000000000b6251200090000000101000000000000945912002300000000000000b75912002200000000000000000000000000000000000000c8b01200dc5912000000000000000000ec5912000200000000000000010000000000000096901200160000000000000000000000e73712000800000000000000000000000000000000000000000000000000000000000000c8b01200fc59120000000000000000000c5a120001000000000000000000000000000000ac9012000e0000000000000000000000145a12000800000000000000000000000000000000000000000000000000000000000000c8b012001c5a120000000000000000002c5a12000300000000000000010000003c0000000000000001000000ff0000008b66120022000000c8b0120000000000ad6612004c000000c8b0120000000000f9661200420000003b6712002b00000066671200440000003c00000000000000010000006b000000616612002a0000003c0000000000000001000000000100001166120050000000496e76756c6e657261626c65730000003c0000000000000001000000590000003d651200560000009365120053000000e66512002b000000fd641200400000005374616b696e674c65646765723c543a3a4163636f756e7449642c2042616c616e63654f663c543e3e0000003c000000000000000100000051000000ac6412005100000050617965650000003c000000000000000100000051000000736412003900000022641200510000004e6f6d696e6174696f6e733c543a3a4163636f756e7449643e0000003c000000000000000100000051000000c9631200590000003d63120017000000c8b01200000000005463120055000000a963120020000000416374697665457261496e666f3c4d6f6d656e744f663c543e3e00003c0000000000000001000000510000008e62120036000000c8b0120000000000c46212002e000000f26212004b000000436212004b0000004578706f737572653c543a3a4163636f756e7449642c2042616c616e63654f663c543e3ecd6112001e000000c8b0120000000000eb61120058000000c8b0120000000000646012002a0000007d611200500000003c0000000000000001000000010100008e60120026000000c8b0120000000000b4601200550000000961120037000000406112003d000000c8b01200000000000d60120057000000c8b0120000000000646012002a0000007d611200500000003c000000000000000100000002010000c85f120045000000c8b01200000000000d60120057000000c8b0120000000000646012002a00000042616c616e63654f663c543e3e5f120042000000c8b0120000000000805f120048000000457261526577617264506f696e74733c543a3a4163636f756e7449643e0000003c000000000000000100000003010000ca5e12002b000000f55e120049000000485e12003b000000835e120047000000466f7263696e67003c000000000000000100000051000000015e12004700000050657262696c6c003c00000000000000010000006b0000008a5d12003e000000c8b0120000000000c85d12003900000043616e63656c6564536c6173685061796f7574003c0000000000000001000000de0000000a5d1200450000004f5d12003b0000005665633c556e6170706c696564536c6173683c543a3a4163636f756e7449642c2042616c616e63654f663c543e3e3e003c000000000000000100000059000000d95c1200310000005665633c28457261496e6465782c2053657373696f6e496e646578293e0000003c0000000000000001000000590000002f5c120049000000c8b0120000000000785c120032000000aa5c12002f0000002850657262696c6c2c2042616c616e63654f663c543e29003c000000000000000100000051000000c25b120051000000135c12001c0000003c0000000000000001000000510000006a5b120058000000736c617368696e673a3a536c617368696e675370616e73003c00000000000000010000006a000000475b12002300000028543a3a4163636f756e7449642c20736c617368696e673a3a5370616e496e64657829736c617368696e673a3a5370616e5265636f72643c42616c616e63654f663c543e3e0000003c000000000000000100000004010000ca5a12004f000000195b12002e0000003c0000000000000001000000510000008b5a12003f00000052656c65617365733c000000000000000100000051000000445a12001f000000c8b0120000000000635a1200280000002053746f726167652076657273696f6e206f66207468652070616c6c65742e20546869732069732073657420746f2076322e302e3020666f72206e6577206e6574776f726b732e20546865206561726c696573742065726120666f72207768696368207765206861766520612070656e64696e672c20756e6170706c69656420736c6173682e205265636f72647320696e666f726d6174696f6e2061626f757420746865206d6178696d756d20736c617368206f6620612073746173682077697468696e206120736c617368696e67207370616e2c2061732077656c6c20617320686f77206d7563682072657761726420686173206265656e2070616964206f75742e20536c617368696e67207370616e7320666f72207374617368206163636f756e74732e20416c6c20736c617368696e67206576656e7473206f6e206e6f6d696e61746f72732c206d61707065642062792065726120746f20746865206869676865737420736c6173682076616c7565206f6620746865206572612e20416c6c20736c617368696e67206576656e7473206f6e2076616c696461746f72732c206d61707065642062792065726120746f20746865206869676865737420736c6173682070726f706f7274696f6e20616e6420736c6173682076616c7565206f6620746865206572612e2041206d617070696e672066726f6d207374696c6c2d626f6e646564206572617320746f207468652066697273742073657373696f6e20696e646578206f662074686174206572612e204d75737420636f6e7461696e7320696e666f726d6174696f6e20666f72206572617320666f72207468652072616e67653a20605b6163746976655f657261202d20626f756e64696e675f6475726174696f6e3b206163746976655f6572615d6020416c6c20756e6170706c69656420736c61736865732074686174206172652071756575656420666f72206c617465722e2054686520616d6f756e74206f662063757272656e637920676976656e20746f207265706f7274657273206f66206120736c617368206576656e74207768696368207761732063616e63656c65642062792065787472616f7264696e6172792063697263756d7374616e6365732028652e672e20676f7665726e616e6365292e205468652070657263656e74616765206f662074686520736c617368207468617420697320646973747269627574656420746f207265706f72746572732e205468652072657374206f662074686520736c61736865642076616c75652069732068616e646c6564206279207468652060536c617368602e205472756520696620746865206e6578742073657373696f6e206368616e67652077696c6c2062652061206e657720657261207265676172646c657373206f6620696e6465782e2054686520746f74616c20616d6f756e74207374616b656420666f7220746865206c6173742060484953544f52595f44455054486020657261732e20496620746f74616c206861736e2774206265656e20736574206f7220686173206265656e2072656d6f766564207468656e2030207374616b652069732072657475726e65642e205265776172647320666f7220746865206c6173742060484953544f52595f44455054486020657261732e20496620726577617264206861736e2774206265656e20736574206f7220686173206265656e2072656d6f766564207468656e2030207265776172642069732072657475726e65642e2054686520746f74616c2076616c696461746f7220657261207061796f757420666f7220746865206c6173742060484953544f52595f44455054486020657261732e2045726173207468617420686176656e27742066696e697368656420796574206f7220686173206265656e2072656d6f76656420646f65736e27742068617665207265776172642e2053696d696c61726c7920746f2060457261735374616b65727360207468697320686f6c64732074686520707265666572656e636573206f662076616c696461746f72732e2054686973206973206b657965642066697374206279207468652065726120696e64657820746f20616c6c6f772062756c6b2064656c6574696f6e20616e64207468656e20746865207374617368206163636f756e742e2049732069742072656d6f7665642061667465722060484953544f52595f44455054486020657261732e20436c6970706564204578706f73757265206f662076616c696461746f72206174206572612e20546869732069732073696d696c617220746f205b60457261735374616b657273605d20627574206e756d626572206f66206e6f6d696e61746f7273206578706f7365642069732072656475636520746f207468652060543a3a4d61784e6f6d696e61746f72526577617264656450657256616c696461746f72602062696767657374207374616b6572732e2054686973206973207573656420746f206c696d69742074686520692f6f20636f737420666f7220746865206e6f6d696e61746f72207061796f75742e204966207374616b657273206861736e2774206265656e20736574206f7220686173206265656e2072656d6f766564207468656e20656d707479206578706f737572652069732072657475726e65642e204578706f73757265206f662076616c696461746f72206174206572612e2054686973206973206b65796564206669727374206279207468652065726120696e64657820746f20616c6c6f772062756c6b2064656c6574696f6e20616e64207468656e20746865207374617368206163636f756e742e205468652073657373696f6e20696e646578206174207768696368207468652065726120737461727420666f7220746865206c6173742060484953544f52595f444550544860206572617320546865206163746976652065726120696e666f726d6174696f6e2c20697420686f6c647320696e64657820616e642073746172742e20546865206163746976652065726120697320746865206572612063757272656e746c792072657761726465642e2056616c696461746f7220736574206f66207468697320657261206d75737420626520657175616c20746f206053657373696f6e496e746572666163653a3a76616c696461746f7273602e205468652063757272656e742065726120696e6465782e205468697320697320746865206c617465737420706c616e6e6564206572612c20646570656e64696e67206f6e20686f772073657373696f6e206d6f64756c6520717565756573207468652076616c696461746f72207365742c206974206d6967687420626520616374697665206f72206e6f742e20546865206d61702066726f6d206e6f6d696e61746f72207374617368206b657920746f2074686520736574206f66207374617368206b657973206f6620616c6c2076616c696461746f727320746f206e6f6d696e6174652e20546865206d61702066726f6d202877616e6e616265292076616c696461746f72207374617368206b657920746f2074686520707265666572656e636573206f6620746861742076616c696461746f722e2057686572652074686520726577617264207061796d656e742073686f756c64206265206d6164652e204b657965642062792073746173682e204d61702066726f6d20616c6c2028756e6c6f636b6564292022636f6e74726f6c6c657222206163636f756e747320746f2074686520696e666f20726567617264696e6720746865207374616b696e672e204d61702066726f6d20616c6c206c6f636b65642022737461736822206163636f756e747320746f2074686520636f6e74726f6c6c6572206163636f756e742e20416e792076616c696461746f72732074686174206d6179206e6576657220626520736c6173686564206f7220666f726369626c79206b69636b65642e20497427732061205665632073696e63652074686579277265206561737920746f20696e697469616c697a6520616e642074686520706572666f726d616e636520686974206973206d696e696d616c2028776520657870656374206e6f206d6f7265207468616e20666f757220696e76756c6e657261626c65732920616e64207265737472696374656420746f20746573746e6574732e204d696e696d756d206e756d626572206f66207374616b696e67207061727469636970616e7473206265666f726520656d657267656e637920636f6e646974696f6e732061726520696d706f7365642e2054686520696465616c206e756d626572206f66207374616b696e67207061727469636970616e74732e204e756d626572206f662065726120746f206b65657020696e20686973746f72792e20496e666f726d6174696f6e206973206b65707420666f72206572617320696e20605b63757272656e745f657261202d20686973746f72795f64657074683b2063757272656e745f6572615d204d757374206265206d6f7265207468616e20746865206e756d626572206f66206572612064656c617965642062792073657373696f6e206f74686572776973652e20692e652e2061637469766520657261206d75737420616c7761797320626520696e20686973746f72792e20692e652e20606163746976655f657261203e2063757272656e745f657261202d20686973746f72795f646570746860206d7573742062652067756172616e746565642e0000000000001c6812000e00000000000000179012000c00000000000000c8b012002c68120000000000000000003c681200010000000000000000000000446812000f00000000000000e73712000800000000000000c8b0120054681200000000000000000064681200010000000000000053657373696f6e7350657245726100003c000000000000000100000005010000a56812001c000000426f6e64696e674475726174696f6e003c0000000000000001000000060100006c68120039000000204e756d626572206f6620657261732074686174207374616b65642066756e6473206d7573742072656d61696e20626f6e64656420666f722e204e756d626572206f662073657373696f6e7320706572206572612e00000000000000de2312000d00000000000000306a1200010000000000000000000000d62312000800000000000000386a1200010000000000000000000000c92312000d00000000000000406a1200010000000000000000000000bc2312000d00000000000000486a1200010000000000000000000000b02312000c00000000000000506a1200010000000000000000000000a22312000e00000000000000586a1200010000000000000000000000912312001100000000000000606a1200010000000000000000000000802312001100000000000000686a1200010000000000000000000000742312000c00000000000000706a1200010000000000000000000000672312000d00000000000000786a12000100000000000000000000005b2312000c00000000000000806a1200010000000000000000000000492312001200000000000000886a12000100000000000000000000002f2312001a00000000000000906a120001000000000000001a6c12001a000000056c120015000000ec6b120019000000ce6b12001e000000b56b120019000000a46b120011000000826b1200220000004f6b1200330000002a6b120025000000016b120029000000ce6a120033000000b76a120017000000986a12001f00000020496e76616c6964206e756d626572206f66206e6f6d696e6174696f6e732e20496e76616c69642065726120746f207265776172642e20417474656d7074696e6720746f2074617267657420612073746173682074686174207374696c6c206861732066756e64732e2043616e206e6f74207265626f6e6420776974686f757420756e6c6f636b696e67206368756e6b732e2043616e206e6f74207363686564756c65206d6f726520756e6c6f636b206368756e6b732e2043616e206e6f7420626f6e6420776974682076616c7565206c657373207468616e206d696e696d756d2062616c616e63652e20536c617368207265636f726420696e646578206f7574206f6620626f756e64732e204475706c696361746520696e6465782e20546172676574732063616e6e6f7420626520656d7074792e20436f6e74726f6c6c657220697320616c7265616479207061697265642e20537461736820697320616c726561647920626f6e6465642e204e6f742061207374617368206163636f756e742e204e6f74206120636f6e74726f6c6c6572206163636f756e742e3c6c12002a000000696e7465726e616c206572726f723a20656e746572656420756e726561636861626c6520636f64653a200000889a12001e00000005000000320000004e6f745472616e73666572496e5573654e6f744f776e65724e6f7441737369676e6564496e6469636573636c61696d7472616e7366657266726565666f7263655f7472616e736665724163636f756e747300000000000000246d12000d00000000000000346d1200020000000000000000000000446d12000100000000000000000000004c6d12000a00000000000000586d1200010000000000000000000000606d12000100000000000000496e64657841737369676e6564000000c26d120009000000986d12000c000000a46d12001e000000496e64657846726565640000986d12000c000000686d1200300000002041206163636f756e7420696e64657820686173206265656e2066726565642075702028756e61737369676e6564292e4163636f756e74496e6465782041206163636f756e7420696e646578207761732061737369676e65642e4163636f756e74496474696d657374616d702073657420696e20626c6f636b20646f65736e2774206d6174636820736c6f7420696e207365616c046e1200230000005f5f5068616e746f6d4974656d2073686f756c64206e6576657220626520757365642e00386e12002e000000666e12000d0000004552524f523a2072657475726e6564206e6578745f6b657920686173206e6f2076616c75653a0a6b6579206973200a6e6578745f6b6579206973204e657874456e756d536574456e756d53657400000000000000ae8312000a0000000000000000000000a07112000300000000000000000000000000000000000000000000000000000000000000c8b01200fc7112000000000000000000a471120001000000000000000100000000000000b88312000b0000000000000000000000ac7112002700000000000000000000000000000000000000000000000000000000000000c8b01200d47112000000000000000000e471120001000000000000000100000000000000c38312000b0000000000000000000000a07112000300000000000000000000000000000000000000000000000000000000000000c8b01200fc7112000000000000000000ec71120002000000000000000100000000000000ce8312000b0000000000000000000000a07112000300000000000000000000000000000000000000000000000000000000000000c8b01200fc71120000000000000000000c72120001000000000000000100000000000000d98312000a0000000000000000000000147212000800000000000000000000000000000000000000000000000000000000000000c8b012006c72120000000000000000001c7212000a000000000000000100000000000000e38312000e0000000000000000000000147212000800000000000000000000000000000000000000000000000000000000000000c8b012006c72120000000000000000007c72120001000000000000000100000000000000f18312000c0000000000000000000000847212000300000000000000000000000000000000000000000000000000000000000000c8b012008872120000000000000000009872120009000000000000000100000000000000fd831200110000000101000000000000847212000300000000000000e07212000d00000000000000000000000000000000000000c8b01200f07212000000000000000000c8b01200000000000000000001000000000000005b8c12000b0000000000000000000000007312000800000000000000000000000000000000000000000000000000000000000000c8b01200087312000000000000000000187312000200000000000000000000007536340063771200150000005665633c28417574686f7269747949642c2042616265417574686f72697479576569676874293e003c000000000000000100000059000000487712001b000000e67612003e00000024771200240000003c000000000000000100000052000000d1761200150000005b75383b2033325d0b7512002e000000c8b0120000000000397512000b000000c8b01200000000004475120041000000857512003e000000c37512004500000008761200450000004d761200410000008e761200430000003c000000000000000100000007010000f474120017000000753332003c00000000000000010000006b000000af7312001f000000c8b0120000000000ce7312003d0000000b741200400000004b74120025000000c8b0120000000000707412003b000000ab74120042000000ed741200070000005665633c5b75383b2033325d3e0000003c0000000000000001000000590000004d617962655672663c000000000000000100000051000000287312004000000068731200470000002054656d706f726172792076616c75652028636c656172656420617420626c6f636b2066696e616c697a6174696f6e292077686963682069732060536f6d6560206966207065722d626c6f636b20696e697469616c697a6174696f6e2068617320616c7265616479206265656e2063616c6c656420666f722063757272656e7420626c6f636b2e2052616e646f6d6e65737320756e64657220636f6e737472756374696f6e2e205765206d616b6520612074726164656f6666206265747765656e2073746f7261676520616363657373657320616e64206c697374206c656e6774682e2057652073746f72652074686520756e6465722d636f6e737472756374696f6e2072616e646f6d6e65737320696e207365676d656e7473206f6620757020746f2060554e4445525f434f4e535452554354494f4e5f5345474d454e545f4c454e475448602e204f6e63652061207365676d656e7420726561636865732074686973206c656e6774682c20776520626567696e20746865206e657874206f6e652e20576520726573657420616c6c207365676d656e747320616e642072657475726e20746f206030602061742074686520626567696e6e696e67206f662065766572792065706f63682e204e6578742065706f63682072616e646f6d6e6573732e205468652065706f63682072616e646f6d6e65737320666f7220746865202a63757272656e742a2065706f63682e20232053656375726974792054686973204d555354204e4f54206265207573656420666f722067616d626c696e672c2061732069742063616e20626520696e666c75656e6365642062792061206d616c6963696f75732076616c696461746f7220696e207468652073686f7274207465726d2e204974204d4159206265207573656420696e206d616e792063727970746f677261706869632070726f746f636f6c732c20686f77657665722c20736f206c6f6e67206173206f6e652072656d656d626572732074686174207468697320286c696b652065766572797468696e6720656c7365206f6e2d636861696e29206974206973207075626c69632e20466f72206578616d706c652c2069742063616e20626520757365642077686572652061206e756d626572206973206e656564656420746861742063616e6e6f742068617665206265656e2063686f73656e20627920616e206164766572736172792c20666f7220707572706f7365732073756368206173207075626c69632d636f696e207a65726f2d6b6e6f776c656467652070726f6f66732e2043757272656e7420736c6f74206e756d6265722e2054686520736c6f74206174207768696368207468652066697273742065706f63682061637475616c6c7920737461727465642e2054686973206973203020756e74696c2074686520666972737420626c6f636b206f662074686520636861696e2e2043757272656e742065706f636820617574686f7269746965732e2043757272656e742065706f636820696e6465782e00000000e87712000d00000000000000a07112000300000000000000c8b01200f8771200000000000000000008781200020000000000000000000000187812001100000000000000297812000900000000000000c8b0120034781200000000000000000044781200050000000000000045706f63684475726174696f6e0000003c0000000000000001000000080100009c79120043000000df7912003f0000004578706563746564426c6f636b54696d65543a3a4d6f6d656e7400003c0000000000000001000000090100006c78120041000000ad78120044000000f1781200410000003279120042000000747912002800000020546865206578706563746564206176657261676520626c6f636b2074696d6520617420776869636820424142452073686f756c64206265206372656174696e6720626c6f636b732e2053696e636520424142452069732070726f626162696c6973746963206974206973206e6f74207472697669616c20746f20666967757265206f7574207768617420746865206578706563746564206176657261676520626c6f636b2074696d652073686f756c64206265206261736564206f6e2074686520736c6f74206475726174696f6e20616e642074686520736563757269747920706172616d657465722060636020287768657265206031202d20636020726570726573656e7473207468652070726f626162696c697479206f66206120736c6f74206265696e6720656d707479292e20546865206e756d626572206f66202a2a736c6f74732a2a207468617420616e2065706f63682074616b65732e20576520636f75706c652073657373696f6e7320746f2065706f6368732c20692e652e2077652073746172742061206e65772073657373696f6e206f6e636520746865206e65772065706f636820626567696e732e65706f636820696e64696365732077696c6c206e6576657220726561636820325e3634206265666f726520746865206465617468206f662074686520756e6976657273653b2071656400887a1200400000004f0100001b000000887a12004000000057010000200000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f6672616d652f626162652f7372632f6c69622e727300000000a26c12000500000000000000787b1200010000000000000000000000907b1200100000000000000000000000a76c12000800000000000000107c1200020000000000000000000000407c1200100000000000000000000000af6c12000400000000000000787b1200010000000000000000000000c07c1200100000000000000000000000b36c12000e00000000000000107c1200020000000000000000000000407d12001000000000000000000000001f8212000500000000000000248212000f0000003382120027000000c8b01200000000005a82120038000000c8b01200000000007881120034000000c8b0120000000000928212003d000000c8b0120000000000057f120025000000c8b01200000000002a7f12000b000000357f12000a0000003f7f120027000000d880120019000000857f12000d000000927f12000c00000000000000108212000300000000000000138212000c000000000000001f8212000500000000000000248212000f000000f180120058000000498112002f000000c8b01200000000007881120034000000c8b0120000000000ac8112004a000000ad7e120058000000c8b0120000000000057f120025000000c8b01200000000002a7f12000b000000357f12000a0000003f7f120027000000f68112001a000000857f12000d000000927f12000c0000009e7f120026000000c8b0120000000000c47f120058000000c8b01200000000001c80120056000000c8b01200000000007280120044000000c8b0120000000000b680120022000000c8b01200000000002a7f12000b000000357f12000a0000003f7f120027000000d880120019000000857f12000d000000927f12000c000000c07d120056000000167e12003b000000c8b0120000000000517e120032000000c8b0120000000000837e12002a000000ad7e120058000000c8b0120000000000057f120025000000c8b01200000000002a7f12000b000000357f12000a0000003f7f120027000000667f12001f000000857f12000d000000927f12000c00000020466f72636520616e20696e64657820746f20616e206163636f756e742e205468697320646f65736e277420726571756972652061206465706f7369742e2049662074686520696e64657820697320616c72656164792068656c642c207468656e20616e79206465706f736974206973207265696d62757273656420746f206974732063757272656e74206f776e65722e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f526f6f745f2e202d2060696e646578603a2074686520696e64657820746f206265202872652d2961737369676e65642e202d20606e6577603a20746865206e6577206f776e6572206f662074686520696e6465782e20546869732066756e6374696f6e2069732061206e6f2d6f7020696620697420697320657175616c20746f2073656e6465722e20456d6974732060496e64657841737369676e656460206966207375636365737366756c2e2023203c7765696768743e202d20604f283129602e202d204f6e652073746f72616765206d75746174696f6e2028636f64656320604f28312960292e202d20557020746f206f6e652072657365727665206f7065726174696f6e2e202d204f6e65206576656e742e2023203c2f7765696768743e204672656520757020616e20696e646578206f776e6564206279207468652073656e6465722e205061796d656e743a20416e792070726576696f7573206465706f73697420706c6163656420666f722074686520696e64657820697320756e726573657276656420696e207468652073656e646572206163636f756e742e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e64207468652073656e646572206d757374206f776e2074686520696e6465782e202d2060696e646578603a2074686520696e64657820746f2062652066726565642e2054686973206d757374206265206f776e6564206279207468652073656e6465722e20456d6974732060496e646578467265656460206966207375636365737366756c2e202d204f6e652072657365727665206f7065726174696f6e2e2041737369676e20616e20696e64657820616c7265616479206f776e6564206279207468652073656e64657220746f20616e6f74686572206163636f756e742e205468652062616c616e6365207265736572766174696f6e206973206566666563746976656c79207472616e7366657272656420746f20746865206e6577206163636f756e742e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f2e202d2060696e646578603a2074686520696e64657820746f2062652072652d61737369676e65642e2054686973206d757374206265206f776e6564206279207468652073656e6465722e202d204f6e65207472616e73666572206f7065726174696f6e2e6e6577543a3a4163636f756e744964696e646578543a3a4163636f756e74496e6465782041737369676e20616e2070726576696f75736c7920756e61737369676e656420696e6465782e205061796d656e743a20604465706f736974602069732072657365727665642066726f6d207468652073656e646572206163636f756e742e202d2060696e646578603a2074686520696e64657820746f20626520636c61696d65642e2054686973206d757374206e6f7420626520696e207573652e0000000000c16c1200080000000102000000000000248212000f00000000000000288312001c00000000000000000000000000000000000000c8b012004483120000000000000000005483120001000000000000000000000028543a3a4163636f756e7449642c2042616c616e63654f663c543e293c0000000000000001000000510000005c8312002200000020546865206c6f6f6b75702066726f6d20696e64657820746f206163636f756e742e417574686f72697479446973636f766572794b657973417574686f7273686970446964536574556e636c65734261626545706f6368496e646578417574686f72697469657347656e65736973536c6f7443757272656e74536c6f7452616e646f6d6e6573734e65787452616e646f6d6e6573735365676d656e74496e646578556e646572436f6e737472756374696f6e746f6f206d616e7920696e737472756374696f6e734e6f6e2d656d7074792066756e6374696f6e20626f6479206578706563746564008c8412000f0000009b841200020000009d84120003000000617373657274696f6e206661696c65643a20636f6e746578742e6672616d655f737461636b2e69735f656d7074792829417420696e737472756374696f6e202840293a2043616e2774206465636f6465207761736d20636f64654d6f64756c65206973206e6f742076616c69646d6f64756c65206465636c6172657320696e7465726e616c206d656d6f72796d756c7469706c65207461626c6573206465636c617265647461626c652065786365656473206d6178696d756d2073697a6520616c6c6f776564757365206f6620666c6f6174696e6720706f696e74207479706520696e2066756e6374696f6e20747970657320697320666f7262696464656e757365206f6620666c6f6174696e6720706f696e74207479706520696e206c6f63616c7320697320666f7262696464656e757365206f6620666c6f6174696e6720706f696e74207479706520696e20676c6f62616c7320697320666f7262696464656e67617320696e737472756d656e746174696f6e206661696c6564737461636b2068656967687420696e737472756d656e746174696f6e206661696c656463616c6c6465706c6f796465706c6f792066756e6374696f6e2069736e2774206578706f72746564756e6b6e6f776e206578706f72743a20657870656374696e67206f6e6c79206465706c6f7920616e642063616c6c2066756e6374696f6e7366756e6374696f6e206861732061206e6f6e2d6578697374656e7420747970656578706f72742072656665727320746f206e6f6e2d6578697374656e742066756e6374696f6e657870656374656420612066756e6374696f6e656e74727920706f696e7420706f696e747320746f20616e20696d706f727465642066756e6374696f6e656e74727920706f696e74206861732077726f6e67207369676e617475726563616c6c2066756e6374696f6e2069736e2774206578706f727465646572726f722073657269616c697a696e6720696e737472756d656e746564206d6f64756c6552657475726e207479706573206c656e6774682073686f756c642062652030206f7220310000ec8912001e0000000a8a12001f00000066756e6374696f6e5f73656374696f6e5f6c656e20213d20303b2071656400008f8912005d000000d10000002000000066756e6374696f6e5f73656374696f6e5f6c656e20213d20303b2066756e6374696f6e5f73656374696f6e5f6c656e203d3d20636f64655f73656374696f6e5f6c656e3b207165648f8912005d000000d40000001c000000758912001a000000508912000a0000005a8912001b00000073746172742066756e6374696f6e20657870656374656420746f20686176652074797065205b5d202d3e205b5d0000003f891200110000001f89120020000000ff88120020000000d78812002800000070617373697665206d656d6f7279207365676d656e747320617265206e6f7420737570706f727465647365676d656e74206f66667365742073686f756c642072657475726e204933327061737369766520656c656d656e74207365676d656e747320617265206e6f7420737570706f72746564746f6f206d616e79206d656d6f727920726567696f6e7320696e20696e6465782073706163653a20746f6f206d616e79207461626c657320696e20696e6465782073706163653a20747279696e6720746f20696d706f7274206d757461626c6520676c6f62616c206475706c6963617465206578706f72742046756e6374696f6e20232072656164696e672f76616c69646174696f6e206572726f723a204d697373696e6720626f647920666f722066756e6374696f6e202f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f7761736d692d76616c69646174696f6e2d302e332e302f7372632f6c69622e72736c656e677468206f662066756e6374696f6e2073656374696f6e206973202c207768696c65206c656e206f6620636f64652073656374696f6e206973206578745f7365745f73746f726167656578745f6765745f73746f726167656578745f63616c6c6578745f696e7374616e74696174656578745f72657475726e6578745f63616c6c65726578745f616464726573736578745f6761735f70726963656578745f6761735f6c6566746578745f62616c616e63656578745f76616c75655f7472616e736665727265646578745f72616e646f6d6578745f6e6f776578745f6d696e696d756d5f62616c616e63656578745f746f6d6273746f6e655f6465706f7369746578745f64697370617463685f63616c6c6578745f726573746f72655f746f6578745f736372617463685f73697a656578745f736372617463685f726561646578745f736372617463685f77726974656578745f6465706f7369745f6576656e746578745f7365745f72656e745f616c6c6f77616e63656578745f72656e745f616c6c6f77616e63656578745f7072696e746c6e6578745f626c6f636b5f6e756d6265726578745f6765745f72756e74696d655f73746f72616765436f6e74726163744761735370656e7443757272656e745363686564756c654163636f756e74436f756e74657200000000000100000002000000040000000800000010000000200000005075626c696350726f70436f756e745265666572656e64756d436f756e7444656d6f63726163794c6f77657374556e62616b65644c6173745461626c656457617345787465726e616c50687261676d656e456c656374696f6e456c656374696f6e526f756e6473496e697469616c697a6564000000000000ec8c12000e00000000000000fc8c1200010000000000000000000000048d12000100000000000000000000000c8d12000600000000000000c8b01200000000000000000000000000148d12000100000000000000000000001c8d12000700000000000000c8b01200000000000000000000000000248d120001000000000000004e6577417574686f72697469657300009f8d12000d0000007b8d1200240000005061757365640000548d120027000000526573756d6564002c8d1200280000002043757272656e7420617574686f726974792073657420686173206265656e20726573756d65642e2043757272656e7420617574686f726974792073657420686173206265656e207061757365642e204e657720617574686f726974792073657420686173206265656e206170706c6965642e417574686f726974794c69737443757272656e7453657449644772616e64706146696e616c697479536574496453657373696f6e496d4f6e6c696e655265636569766564486561727462656174734f6666656e6365735265706f72747342794b696e64496e6465780000000000348e120007000000000000003c8e12000200000000000000000000004c8e120002000000000000004f6666656e636500ff8e120004000000038f12000e0000005c8e120055000000b18e12004e00000020546865726520697320616e206f6666656e6365207265706f72746564206f662074686520676976656e20606b696e64602068617070656e656420617420746865206073657373696f6e5f696e6465786020616e6420286b696e642d7370656369666963292074696d6520736c6f742e2054686973206576656e74206973206e6f74206465706f736974656420666f72206475706c696361746520736c61736865732e4b696e644f706171756554696d65536c6f7453746f72656452616e676553657373696f6e43757272656e74496e6465785175657565644368616e67656444697361626c656456616c696461746f72730000000000007c8f12000a00000000000000888f1200010000000000000000000000908f120002000000000000004e657753657373696f6e0000179012000c000000a08f120055000000f58f120022000000204e65772073657373696f6e206861732068617070656e65642e204e6f746520746861742074686520617267756d656e74206973207468652073657373696f6e20696e6465782c206e6f742074686520626c6f636b206e756d626572206173207468652074797065206d6967687420737567676573742e53657373696f6e496e646578486973746f7279446570746856616c696461746f72436f756e744d696e696d756d56616c696461746f72436f756e7443757272656e7445726145726173537461727453657373696f6e496e646578466f726365457261536c6173685265776172644672616374696f6e426f6e646564457261734561726c69657374556e6170706c696564536c61736853746f7261676556657273696f6e43757272656e74457261537461727453657373696f6e496e64657843757272656e74457261506f696e74734561726e65645374616b696e674973557067726164656474696d737461703054696d657374616d7020696e686572656e742064617461206973206e6f742070726f76696465642e496e76616c69642074696d657374616d7020696e686572656e74206461746120656e636f64696e672e54696d657374616d7044696455706461746542616c616e6365734e6578744665654d756c7469706c696572547265617375727950726f706f73616c436f756e74417070726f76616c7300003c00000004000000040000000a00000042725461626c65446174617461626c653c00000004000000040000000a01000064656661756c744636345265696e74657270726574493634556e726561636861626c654e6f70426c6f636b003c00000004000000040000000b0100004c6f6f704966456c7365456e6442724272496642725461626c6500003c00000004000000040000000c01000052657475726e43616c6c43616c6c496e64697265637400003c0000000400000004000000d800000044726f7053656c6563744765744c6f63616c5365744c6f63616c5465654c6f63616c476574476c6f62616c536574476c6f62616c4933324c6f61644936344c6f61644633324c6f61644636344c6f61644933324c6f616438534933324c6f616438554933324c6f61643136534933324c6f61643136554936344c6f616438534936344c6f616438554936344c6f61643136534936344c6f61643136554936344c6f61643332534936344c6f616433325549333253746f726549363453746f726546333253746f726546363453746f726549333253746f72653849333253746f7265313649363453746f72653849363453746f7265313649363453746f7265333243757272656e744d656d6f727947726f774d656d6f7279493332436f6e7374003c00000004000000040000000d010000493634436f6e73743c00000004000000040000000e010000463332436f6e7374463634436f6e73743c00000004000000040000002b00000049333245717a49333245714933324e654933324c74534933324c74554933324774534933324774554933324c65534933324c655549333247655349333247655549363445717a49363445714936344e654936344c74534936344c74554936344774534936344774554936344c65534936344c655549363447655349363447655546333245714633324e654633324c7446333247744633324c65463332476546363445714636344e654636344c7446363447744636344c654636344765493332436c7a49333243747a493332506f70636e744933324164644933325375624933324d756c493332446976534933324469765549333252656d5349333252656d55493332416e644933324f72493332586f7249333253686c4933325368725349333253687255493332526f746c493332526f7472493634436c7a49363443747a493634506f70636e744936344164644936345375624936344d756c493634446976534936344469765549363452656d5349363452656d55493634416e644936344f72493634586f7249363453686c4936345368725349363453687255493634526f746c493634526f74724633324162734633324e65674633324365696c463332466c6f6f724633325472756e634633324e656172657374463332537172744633324164644633325375624633324d756c4633324469764633324d696e4633324d6178463332436f70797369676e4636344162734636344e65674636344365696c463634466c6f6f724636345472756e634636344e656172657374463634537172744636344164644636345375624636344d756c4636344469764636344d696e4636344d6178463634436f70797369676e493332577261704936344933325472756e63534633324933325472756e63554633324933325472756e63534636344933325472756e6355463634493634457874656e6453493332493634457874656e64554933324936345472756e63534633324936345472756e63554633324936345472756e63534636344936345472756e6355463634463332436f6e7665727453493332463332436f6e7665727455493332463332436f6e7665727453493634463332436f6e766572745549363446333244656d6f7465463634463634436f6e7665727453493332463634436f6e7665727455493332463634436f6e7665727453493634463634436f6e766572745549363446363450726f6d6f74654633324933325265696e746572707265744633324936345265696e746572707265744636344633325265696e7465727072657449333200003c00000004000000040000000a0000003c00000004000000040000000f0100004636344933324936344633324e6f526573756c7456616c7565000000bc9712000b000000492f4f204572726f723a20496e76616c696444617461547261696c696e6744617461556e6578706563746564456f66547269656420746f20736872696e6b20746f2061206c6172676572206361706163697479536f6d654e6f6e65003c00000004000000040000001001000078991200120000008a9912000c0000006066756e635f696478602073686f756c6420636f6d652066726f6d20606e6565645f7468756e6b73603b0a09090909606e6565645f7468756e6b736020697320706f70756c617465642077697468207468652073616d65206974656d73207468617420696e20607265706c6163656d656e745f6d6170603b0a09090909716564109912006800000050000000190000004174207468697320706f696e7420616e20696e646578206d7573742062652061737369676e656420746f2065616368207468756e6b0000001099120068000000890000001d0000002f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e31322e302f7372632f737461636b5f6865696768742f7468756e6b2e727366756e6374696f6e207769746820696478202069736e277420666f756e64617373657274696f6e206661696c65643a20656467652e686569676874203d3d2073656c662e686569676874202d2031617373657274696f6e206661696c65643a2073656c662e6c656e2829203c204341504143495459617373657274696f6e206661696c65643a202173656c662e69735f7368617265645f726f6f742829617373657274696f6e206661696c65643a202173656c662e6e6f64652e69735f7368617265645f726f6f742829617373657274696f6e206661696c65643a20656467652e686569676874203d3d2073656c662e6e6f64652e686569676874202d203100889a12001e00000002000000020000003c3a3a636f72653a3a6d6163726f733a3a70616e6963206d6163726f733e617373657274696f6e206661696c65643a20656e64203c3d206c656e4672616d6569735f706f6c796d6f72706869630000003c000000040000000400000011010000656e645f61726974790000003c00000004000000040000000a0000006272616e63685f617269747973746172745f6865696768744e6f2066756e6374696f6e2073656374696f6e4e6f20636f64652073656374696f6e4e6f20747970652073656374696f6e0000007c9d12000a00000046756e6374696f6e206973206e6f7420666f756e6420696e2066756e632073656374696f6e000000709d12000c00000046756e6374696f6e20626f647920666f722074686520696e6465782069736e277420666f756e6400349d12000b000000737461636b206d757374206265206e6f6e2d656d70747900299d12000b000000df9c120006000000737461636b206f766572666c6f774172697479206f6620616c6c206a756d702d74617267657473206d75737420626520657175616c54797065206e6f7420666f756e6400d89c1200070000003c9c12006d000000c8000000170000002f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e31322e302f7372632f737461636b5f6865696768742f6d61785f6865696768742e72736d61785f686569676874707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768747472756e633a20707573683a20000000249d120005000000747279696e6720746f20706f70206d6f72652076616c756573207468616e20707573686564737461636b20756e646572666c6f77706f703a20756e726561636861626c65706f705f6672616d653a20636f6e74726f6c20737461636b20697320656d707479636f6e74726f6c20737461636b206f75742d6f662d626f756e6473707573685f6672616d653a2066756e635f6964783a20000054a11200480000000e0200002300000054a11200480000000f02000023000000617373657274696f6e206661696c65643a206d6964203c3d206c656ed8b01200490000000a00000009000000e49d1200490000008e0200001d0000002f72757374632f373563663431616662343638313532363131323132323731626165303236393438636433626134362f7372632f6c6962636f72652f736c6963652f736f72742e7273000000e49d120049000000a100000030000000e49d120049000000a400000030000000656e766761730000689e12005d000000120100001c0000002f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e31322e302f7372632f6761732f6d6f642e72736c6173745f696e6465782069732067726561746572207468616e20303b206c6173745f696e64657820697320737461636b2073697a65202d20313b20716564689e12005d000000a600000026000000519f12006600000010010000200000002c9f12002500000043616c6c20746f2066756e6374696f6e2074686174206f75742d6f662d626f756e64733a202f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e31322e302f7372632f737461636b5f6865696768742f6d6f642e7273546869732073686f756c64206265206120696e646578206f66206120646566696e65642066756e6374696f6e44756520746f2076616c69646174696f6e20636f64652073656374696f6e2073686f756c642065786973747346756e6374696f6e20626f6479206973206f7574206f6620626f756e647366756e6374696f6e20696d706f727420636f756e74206973206e6f74207a65726f3b20696d706f72742073656374696f6e206d757374206578697374733b2071656400519f120066000000590100000900000066756e635f696478206973206c657373207468616e2066756e6374696f6e20696d706f72747320636f756e743b0a090909096e74682066756e6374696f6e20696d706f7274206d7573742062652060536f6d65603b0a09090909716564000000f0ad12001200000035a112000f00000008a112000a00000012a112001400000026a112000f0000005369676e61747572652020287370656369666965642062792066756e6320292069736e277420646566696e6564206973206e6f7420646566696e656454a1120048000000280b00000a0000002f72757374632f373563663431616662343638313532363131323132323731626165303236393438636433626134362f7372632f6c6962636f72652f736c6963652f6d6f642e727354a11200480000002e0b00000e000000bca112004f000000440000000d0000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f7072696d6974697665732f61726974686d657469632f7372632f62696775696e742e72730000000000617474656d707420746f20646976696465206279207a65726f63616e6e6f74206669742061206e756d62657220696e746f2075313238616c7265616479206d757461626c7920626f72726f77656400003c0000000000000001000000f400000080a21200430000001e030000090000002f72757374632f373563663431616662343638313532363131323132323731626165303236393438636433626134362f7372632f6c6962636f72652f63656c6c2e7273616c726561647920626f72726f776564003c0000000000000001000000f500000080a21200430000006e0300000900000072656d696e646572206f6620646976206279206320697320616c77617973206c657373207468616e20633b20716564003c0000000800000004000000500000005da3120056000000680000001b000000726573756c742063616e6e6f742066697420696e20753132382f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f7072696d6974697665732f61726974686d657469632f7372632f68656c706572735f3132386269742e727362616265736c6f74436f756c64206e6f74206465636f64652072657175657374656420696e686572656e742074797065214241424520696e686572656e742064617461206e6f7420666f756e6410a4120054000000cd0000000d0000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f7072696d6974697665732f72756e74696d652d696e746572666163652f7372632f696d706c732e72733c000000000000000100000040000000486f737420746f207761736d2076616c7565732061726520656e636f64656420636f72726563746c793b207165640000b4a412005600000008010000090000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f7072696d6974697665732f72756e74696d652d696e746572666163652f7372632f706173735f62792e727300003c00000000000000010000004000000072756e74696d6552756e74696d65206d656d6f7279206578686175737465642e2041626f7274696e670000000000000000000000617474656d707420746f20646976696465206279207a65726f0000007ca51200500000005f0000002b0000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f7072696d6974697665732f72756e74696d652f7372632f67656e657269632f6572612e727348617368206e6f7420657175616c426164206f726967696e43616e206e6f74206c6f6f6b757044697370617463684572726f723c7761736d3a73747269707065643e5472616e73616374696f6e20776f756c642065786861757374732074686520626c6f636b206c696d6974735472616e73616374696f6e2068617320616e20616e6369656e7420626972746820626c6f636b5472616e73616374696f6e20686173206120626164207369676e61747572655472616e73616374696f6e206973206f757464617465645472616e73616374696f6e2077696c6c2062652076616c696420696e2074686520667574757265496e6162696c69747920746f2070617920736f6d6520666565732028652e672e206163636f756e742062616c616e636520746f6f206c6f77295472616e73616374696f6e2063616c6c206973206e6f74206578706563746564496e76616c69645472616e73616374696f6e20637573746f6d206572726f72436f756c64206e6f742066696e6420616e20756e7369676e65642076616c696461746f7220666f722074686520756e7369676e6564207472616e73616374696f6e436f756c64206e6f74206c6f6f6b757020696e666f726d6174696f6e20726571756972656420746f2076616c696461746520746865207472616e73616374696f6e556e6b6e6f776e5472616e73616374696f6e20637573746f6d206572726f72696e7465726e616c206572726f723a20656e746572656420756e726561636861626c6520636f646500000010a81200530000005a000000120000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f7072696d6974697665732f73616e64626f782f7372632f2e2e2f776974686f75745f7374642e72730010a812005300000068000000120000004475706c69636174655265706f72744f6666656e63654572726f726d616b655f746f705f6672616d655f706f6c796d6f72706869632069732063616c6c6564207769746820656d707479206672616d6520737461636b0000120100000c0000000400000013010000f7aa12005e0000004204000011000000746869732066756e6374696f6e2063616e27742062652063616c6c6564207769746820656d707479206672616d6520737461636bf7aa12005e000000b2040000050000004d6973706c6163656420656c736520696e737472756374696f6e000077aa120047000000beaa1200050000003baa12003700000072aa12000500000006aa120017000000fda9120009000000aeac120014000000e5a9120018000000fda9120009000000aeac120014000000b4a912001d000000d1a9120013000000e4a9120001000000546f6f206c61726765206d656d6f727920616c69676e6d656e7420325e20286578706563746564206174206d6f73742029547279696e6720746f2075706461746520676c6f62616c20206f66207479706520547279696e6720746f20757064617465206c6f63616c2053706563696669630000003c00000004000000040000000f010000416e794c6162656c7320696e2062725f7461626c6520706f696e747320746f20626c6f636b206f6620646966666572656e742074797065733a2020616e6420496620626c6f636b20776974686f757420656c736520726571756972656420746f2068617665204e6f526573756c7420626c6f636b20747970652e204275742069742068617320207479706500d4aa120018000000ecaa12000b000000556e657870656374656420737461636b20686569676874202c206578706563746564202f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f7761736d692d76616c69646174696f6e2d302e332e302f7372632f66756e632e7273547279696e6720746f2061636365737320706172656e74206672616d6520737461636b2076616c7565732e90ab120017000000a7ab12001600000045787065637465642076616c7565206f66207479706520206f6e20746f70206f6620737461636b2e20476f7420000000c8ab120007000000537461636b3a20000000010052ac12002400000028ac1200060000002eac12000e0000003cac12001600000004ac12002400000028ac1200060000006d6178696d756d206d656d6f72792073697a65206d757374206265206174206d6f7374202070616765736d6178696d756d206c696d697420206973206c657373207468616e206d696e696d756d20696e697469616c206d656d6f72792073697a65206d757374206265206174206d6f737420000088ac120026000000aeac120014000000547279696e6720746f20696e697469616c697a65207661726961626c65206f6620747970652020776974682076616c7565206f66207479706520496e69742065787072657373696f6e2073686f756c6420616c776179732062652077697468206c656e67746820324e6f6e20636f6e7374616e74206f70636f646520696e20696e6974206578707259ad1200070000006bad12002200000059ad12000700000060ad12000b00000045787072657373696f6e20646f65736e277420656e647320776974682060656e6460206f70636f6465476c6f62616c20206973206d757461626c6520646f65736e277420657869737473206f72206e6f742079657420646566696e6564000000a0ad120010000000b0ad12000f0000004d656d6f727920617420696e6465782020646f65736e27742065786973747300d0ad12000f000000b0ad12000f0000005461626c6520617420696e6465782000f0ad120012000000b0ad12000f00000046756e6374696f6e20617420696e64657820000014ae12000e000000b0ad12000f0000005479706520617420696e64657820000082ae120010000000b0ad12000f00000054ae12001000000074ae12000e00000054ae12001000000064ae120010000000457870656374656420676c6f62616c2020746f20626520696d6d757461626c6520746f206265206d757461626c65476c6f62616c20617420696e646578206e6f6e2d656d70747920737461636b2065787065637465640000bcae120020000000dcae120012000000747279696e6720746f206765742076616c756520617420706f736974696f6e20206f6e20737461636b206f662073697a6520636865636b656420636f75706c65206f66206c696e65732061626f7665001caf12005f0000004b0000000c0000002f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f7761736d692d76616c69646174696f6e2d302e332e302f7372632f737461636b2e72730084af120015000000657863656564656420737461636b206c696d697420000000c8b01200000000004572726f720000003c0000000400000004000000140100004c6f63616c732072616e6765206e6f7420696e2033322d6269742072616e6765f4af12002200000016b01200150000002bb0120007000000547279696e6720746f20616363657373206c6f63616c207769746820696e64657820207768656e20746865726520617265206f6e6c7920206c6f63616c7300004cb012002d00000079b012000c00000085b0120003000000617373657274696f6e206661696c65643a2060286c656674203d3d20726967687429600a20206c6566743a2060602c0a2072696768743a2060603a2090b012003400000064657374696e6174696f6e20616e6420736f7572636520736c69636573206861766520646966666572656e74206c656e6774687300000000d8b0120049000000120000000d0000002f72757374632f373563663431616662343638313532363131323132323731626165303236393438636433626134362f7372632f6c6962636f72652f6d6163726f732f6d6f642e72730041a4e2ca000b0800000000000000000041ace2ca000b08cc121000cc12100000f2c404046e616d6501e9c404f10600196578745f6c6f6767696e675f6c6f675f76657273696f6e5f31011e6578745f68617368696e675f74776f785f3132385f76657273696f6e5f3102196578745f73746f726167655f6765745f76657273696f6e5f3103206578745f68617368696e675f626c616b65325f3235365f76657273696f6e5f3104196578745f73746f726167655f7365745f76657273696f6e5f31051b6578745f73746f726167655f636c6561725f76657273696f6e5f31061d6578745f68617368696e675f74776f785f36345f76657273696f6e5f3107206578745f68617368696e675f626c616b65325f3132385f76657273696f6e5f31081d6578745f6d6973635f7072696e745f757466385f76657273696f6e5f3109206578745f73616e64626f785f6d656d6f72795f6e65775f76657273696f6e5f310a256578745f73616e64626f785f6d656d6f72795f74656172646f776e5f76657273696f6e5f310b216578745f73616e64626f785f696e7374616e74696174655f76657273696f6e5f310c1c6578745f73616e64626f785f696e766f6b655f76657273696f6e5f310d276578745f73616e64626f785f696e7374616e63655f74656172646f776e5f76657273696f6e5f310e206578745f73746f726167655f6368696c645f726f6f745f76657273696f6e5f310f1f6578745f73746f726167655f6368696c645f7365745f76657273696f6e5f31101f6578745f73746f726167655f6368696c645f6765745f76657273696f6e5f3111216578745f73746f726167655f6368696c645f636c6561725f76657273696f6e5f3112226578745f6d6973635f72756e74696d655f76657273696f6e5f76657273696f6e5f3113226578745f73746f726167655f636c6561725f7072656669785f76657273696f6e5f3114236578745f63727970746f5f737232353531395f7665726966795f76657273696f6e5f3115286578745f6f6666636861696e5f6c6f63616c5f73746f726167655f6765745f76657273696f6e5f3116346578745f6f6666636861696e5f6c6f63616c5f73746f726167655f636f6d706172655f616e645f7365745f76657273696f6e5f3117286578745f6f6666636861696e5f6c6f63616c5f73746f726167655f7365745f76657273696f6e5f31181e6578745f73746f726167655f6e6578745f6b65795f76657273696f6e5f31191c6578745f6d6973635f7072696e745f6e756d5f76657273696f6e5f311a236578745f63727970746f5f656432353531395f7665726966795f76657273696f6e5f311b1a6578745f73746f726167655f726f6f745f76657273696f6e5f311c226578745f73746f726167655f6368616e6765735f726f6f745f76657273696f6e5f311d286578745f73746f726167655f6368696c645f73746f726167655f6b696c6c5f76657273696f6e5f311e206578745f73616e64626f785f6d656d6f72795f6765745f76657273696f6e5f311f206578745f73616e64626f785f6d656d6f72795f7365745f76657273696f6e5f31201c6578745f6d6973635f7072696e745f6865785f76657273696f6e5f3121236578745f6f6666636861696e5f69735f76616c696461746f725f76657273696f6e5f3122256578745f63727970746f5f656432353531395f67656e65726174655f76657273696f6e5f3123256578745f63727970746f5f737232353531395f67656e65726174655f76657273696f6e5f31242a6578745f747269655f626c616b65325f3235365f6f7264657265645f726f6f745f76657273696f6e5f3125296578745f6f6666636861696e5f7375626d69745f7472616e73616374696f6e5f76657273696f6e5f3126246578745f6f6666636861696e5f6e6574776f726b5f73746174655f76657273696f6e5f31271e6578745f616c6c6f6361746f725f6d616c6c6f635f76657273696f6e5f31281c6578745f616c6c6f6361746f725f667265655f76657273696f6e5f31291a6578745f73746f726167655f726561645f76657273696f6e5f312a286578745f63727970746f5f737232353531395f7075626c69635f6b6579735f76657273696f6e5f312b216578745f63727970746f5f737232353531395f7369676e5f76657273696f6e5f312c376578745f63727970746f5f736563703235366b315f65636473615f7265636f7665725f636f6d707265737365645f76657273696f6e5f312d0c5f5f727573745f616c6c6f632e0a5f5f72675f616c6c6f632f0e5f5f727573745f6465616c6c6f63300c5f5f72675f6465616c6c6f63310e5f5f727573745f7265616c6c6f63320c5f5f72675f7265616c6c6f6333135f5f727573745f616c6c6f635f7a65726f656434115f5f72675f616c6c6f635f7a65726f65643509686173685f746573743633616c6c6f633a3a616c6c6f633a3a68616e646c655f616c6c6f635f6572726f723a3a68393863633632326233333565336231383708727573745f6f6f6d3834616c6c6f633a3a7261775f7665633a3a63617061636974795f6f766572666c6f773a3a68393266393538663031366165396534303929636f72653a3a70616e69636b696e673a3a70616e69633a3a68373766616436613063346238343866633a25616c6c6f633a3a666d743a3a666f726d61743a3a68363732663232663234366533383334373b36636f72653a3a70616e69636b696e673a3a70616e69635f626f756e64735f636865636b3a3a68636431353737666636356361353266333c23636f72653a3a666d743a3a77726974653a3a68633335393734306635326363326164363d48616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68303233313133306636316466393435303e33636f72653a3a6f7074696f6e3a3a6578706563745f6e6f6e655f6661696c65643a3a68333630623065356662623963666665633f3a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a6836663863346338626263383935333233403b3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f636861723a3a6839653438653033343234353036333435413a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f666d743a3a68653030326533356637393162303633354239636f72653a3a6f70733a3a66756e6374696f6e3a3a466e4f6e63653a3a63616c6c5f6f6e63653a3a6864643862366261353261353436373866432d636f72653a3a70616e69636b696e673a3a70616e69635f666d743a3a6831333338646430613363363164376664444e636f72653a3a666d743a3a6e756d3a3a696d703a3a3c696d706c20636f72653a3a666d743a3a446973706c617920666f72207533323e3a3a666d743a3a6861313066393132373130663165326561452f636f72653a3a666d743a3a6e756d3a3a696d703a3a666d745f7536343a3a68353639313534323039373433303839314611727573745f626567696e5f756e77696e6447313c5420617320636f72653a3a616e793a3a416e793e3a3a747970655f69643a3a68343037333235646131643963636165624835636f72653a3a666d743a3a466f726d61747465723a3a7061645f696e74656772616c3a3a68323834343736336162386631306563654943636f72653a3a666d743a3a466f726d61747465723a3a7061645f696e74656772616c3a3a77726974655f7072656669783a3a68383763663261376232366534656335384a34636f72653a3a736c6963653a3a736c6963655f696e6465785f6c656e5f6661696c3a3a68653436373831333337323763623431374b36636f72653a3a736c6963653a3a736c6963655f696e6465785f6f726465725f6661696c3a3a68643861366261623162346633313438384c2c636f72653a3a666d743a3a466f726d61747465723a3a7061643a3a68333361366338623734343139326330314d2e636f72653a3a7374723a3a736c6963655f6572726f725f6661696c3a3a68623839616531653339656361343530354e323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a68623939393638303239646133613138344f4a3c636f72653a3a6f70733a3a72616e67653a3a52616e67653c4964783e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a683561393164656261646135386437353550323c6368617220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68366563306131623562303730333438635145636f72653a3a636861723a3a6d6574686f64733a3a3c696d706c20636861723e3a3a6573636170655f64656275675f6578743a3a68383034383633316465336536373833665249636f72653a3a666d743a3a6e756d3a3a3c696d706c20636f72653a3a666d743a3a446562756720666f72207573697a653e3a3a666d743a3a683166353865633261653138373133376453453c636f72653a3a63656c6c3a3a426f72726f774572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a683137376363363338653065323863623354483c636f72653a3a63656c6c3a3a426f72726f774d75744572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6838326437643263323466373735373638552e636f72653a3a6f7074696f6e3a3a6578706563745f6661696c65643a3a683738353666646133626263333636383456303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a686639303533386264313738613763376357323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a683439623434633834353630373163363358323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a683231336530316139336632343132356459533c636f72653a3a666d743a3a6275696c646572733a3a5061644164617074657220617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a68646237313735633237633365313235655a2e636f72653a3a736c6963653a3a6d656d6368723a3a6d656d6368723a3a68373066373266326162393430373865325b3a636f72653a3a666d743a3a6275696c646572733a3a44656275675374727563743a3a6669656c643a3a68306435376133613939323933306233615c2f636f72653a3a666d743a3a57726974653a3a77726974655f636861723a3a68333432366263386131623034653464615d2e636f72653a3a666d743a3a57726974653a3a77726974655f666d743a3a68343936633231613562393662333161325e3a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a68303039303634333334616237343464665f3b3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f636861723a3a6833343638386131613664333462326163603a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f666d743a3a68613132306366623537383439663936346139636f72653a3a666d743a3a6275696c646572733a3a44656275675475706c653a3a6669656c643a3a68393439613634303135356633373735646237636f72653a3a666d743a3a6275696c646572733a3a44656275675365743a3a656e7472793a3a683166643632636337623839363433373463443c636f72653a3a666d743a3a417267756d656e747320617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a683238303438363465333036346131306664313c73747220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6863643237666231643033333034356361658001636f72653a3a7374723a3a7472616974733a3a3c696d706c20636f72653a3a736c6963653a3a536c696365496e6465783c7374723e20666f7220636f72653a3a6f70733a3a72616e67653a3a52616e67653c7573697a653e3e3a3a696e6465783a3a7b7b636c6f737572657d7d3a3a68303433663863393439626236353431616627636f72653a3a7374723a3a66726f6d5f757466383a3a6834646334653364346237656265386433673e3c636f72653a3a666d743a3a4572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a683130386535373466383838353564316468693c6672616d655f6d657461646174613a3a4465636f6465446966666572656e743c422c4f3e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6834316562646630616533643333366637696c3c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68336663333934616335346230356234356a693c6672616d655f6d657461646174613a3a4465636f6465446966666572656e743c422c4f3e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68316337346263393630653733653136636b483c5b545d206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68343931613463666566343639623533396c513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a68306364313866656265353166303365646d3a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a68343737316336343830343137363934316e3b3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f636861723a3a68333534343436653634396539323631666f3a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f666d743a3a6833393233353063636566316536346564704d3c6672616d655f737570706f72743a3a64656275673a3a52756e74696d654c6f67676572206173206c6f673a3a4c6f673e3a3a656e61626c65643a3a683564623261396535313563343135303671493c6672616d655f737570706f72743a3a64656275673a3a52756e74696d654c6f67676572206173206c6f673a3a4c6f673e3a3a6c6f673a3a686138653037336533326438323339333872486672616d655f737570706f72743a3a73746f726167653a3a6d6967726174696f6e3a3a686176655f73746f726167655f76616c75653a3a6833366531343164663733373465636366737c3c73705f72756e74696d655f696e746572666163653a3a706173735f62793a3a436f6465633c543e2061732073705f72756e74696d655f696e746572666163653a3a706173735f62793a3a506173734279496d706c3c543e3e3a3a66726f6d5f6666695f76616c75653a3a686134373561363161363032613162653174383c6c6f673a3a4e6f704c6f67676572206173206c6f673a3a4c6f673e3a3a656e61626c65643a3a683966343464666637613833316338383975343c6c6f673a3a4e6f704c6f67676572206173206c6f673a3a4c6f673e3a3a6c6f673a3a683865363439313661383933393933353476363c6c6f673a3a4e6f704c6f67676572206173206c6f673a3a4c6f673e3a3a666c7573683a3a686162393438313737346264643530633377fa01616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6e6f64653a3a48616e646c653c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6e6f64653a3a4e6f64655265663c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6e6f64653a3a6d61726b65723a3a4d75742c4b2c562c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6e6f64653a3a6d61726b65723a3a4c6561663e2c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6e6f64653a3a6d61726b65723a3a456467653e3a3a696e736572743a3a683263336231373539363764303637366678fe01616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6e6f64653a3a48616e646c653c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6e6f64653a3a4e6f64655265663c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6e6f64653a3a6d61726b65723a3a4d75742c4b2c562c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6e6f64653a3a6d61726b65723a3a496e7465726e616c3e2c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6e6f64653a3a6d61726b65723a3a456467653e3a3a696e736572743a3a6830383638633039313065353563356334793c70616c6c65745f7574696c6974793a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a68383733376431643362656334333562387a3e70616c6c65745f7574696c6974793a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a68303765653961626364383630366163317b3e70616c6c65745f74696d657374616d703a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a68363637636631366136643734363830637c4070616c6c65745f74696d657374616d703a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a68386661363063306661343163633362617d4970616c6c65745f74696d657374616d703a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a68383961353433353831363936353865367e9b013c70616c6c65745f74696d657374616d703a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d696e696d756d506572696f6444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68646163393737393237643333613666367f84017061726974795f7363616c655f636f6465633a3a636f6465633a3a696e6e65725f7475706c655f696d706c3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f72202850302c2051302c205230293e3a3a656e636f64655f746f3a3a68333461383963663132343165623365358001437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a683235393634646337663630303237376481013c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a68303139373762303532373164626634308201543c616c6c6f633a3a7665633a3a5665633c75383e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4f75747075743e3a3a77726974653a3a68363739653065373035366365356366658301437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a68363834626235623635363163663064318401437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a683862393339613337343030663964393985013c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a686336356132393564363835663262616386014a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a683065333563363139633931303433333387012b616c6c6f633a3a736c6963653a3a6d657267655f736f72743a3a6832313534326138626135366265366434880133616c6c6f633a3a736c6963653a3a3c696d706c205b545d3e3a3a636f6e6361743a3a68313933313032346664316364636637628901483c5b545d206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68313733383833323765613463636431658a015a3c70616c6c65745f7574696c6974793a3a43616c6c3c543e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a68666535393232353336363265616638658b01553c6e6f64655f72756e74696d653a3a43616c6c2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a68643536616431303261373838643238308c01416672616d655f73797374656d3a3a4d6f64756c653c543e3a3a6465706f7369745f6576656e745f696e64657865643a3a68613965313735633163316362313863668d012b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a68613464643335613231313331613565348e012b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a68613464643335613231313331613565348f014670616c6c65745f7574696c6974793a3a4d6f64756c653c543e3a3a656e737572655f736f727465645f616e645f696e736572743a3a68633065356663353064303262346463399001437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a686561393132663633623339303266343391016e6e6f64655f72756e74696d653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f72206e6f64655f72756e74696d653a3a43616c6c3e3a3a656e636f64655f746f3a3a68336138663861356164613466383134359201706672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a68376161666364616433613232636436379301386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68616463353738383431373232323436639401b2013c6672616d655f73797374656d3a3a4d6f64756c653c543e206173206672616d655f737570706f72743a3a7472616974733a3a53746f7265644d61703c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449642c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e74446174613e3e3a3a7472795f6d75746174655f6578697374733a3a68666364303961373765366364336237669501386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68666536363833666630313930656235389601b2013c6672616d655f73797374656d3a3a4d6f64756c653c543e206173206672616d655f737570706f72743a3a7472616974733a3a53746f7265644d61703c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449642c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e74446174613e3e3a3a7472795f6d75746174655f6578697374733a3a68363330633432313765646234363636339701463c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a683466623865363364393563646466666698015f3c70616c6c65745f7574696c6974793a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a686466613364366631353063346536303499012b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a68366235346132656262326639353864659a01456672616d655f737570706f72743a3a7472616974733a3a4f6e556e62616c616e6365643a3a6f6e5f756e62616c616e6365643a3a68623532313131643833326533396266389b01743c70616c6c65745f62616c616e6365733a3a696d62616c616e6365733a3a4e65676174697665496d62616c616e63653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a54727944726f703e3a3a7472795f64726f703a3a68383737356336383865653434396134639c01386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68306634356636333266666437643063349d01456672616d655f737570706f72743a3a7472616974733a3a5369676e6564496d62616c616e63653c422c503e3a3a6d657267653a3a68393662623738383763616438333232619e013c70616c6c65745f76657374696e673a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a68313132303839386430396431623861389f013e70616c6c65745f76657374696e673a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6832653235316535656332656263376634a0014770616c6c65745f76657374696e673a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6836363239396433636663663135363163a1013d70616c6c65745f6964656e746974793a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6839383738623733653563336336636136a2013f70616c6c65745f6964656e746974793a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6835316465343034333663323630303530a3016b3c70616c6c65745f6964656e746974793a3a5f5f47657442797465537472756374537562734f663c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6865393530656566386363623564353037a4012b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a6839353738373230303738626262323435a501820170616c6c65745f6964656e746974793a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722070616c6c65745f6964656e746974793a3a4a756467656d656e743c42616c616e63653e3e3a3a656e636f64655f746f3a3a6830343064616363386165313530303933a6017c70616c6c65745f6964656e746974793a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722070616c6c65745f6964656e746974793a3a4964656e74697479496e666f3e3a3a656e636f64655f746f3a3a6836666635353535373339306331376563a701573c70616c6c65745f6964656e746974793a3a44617461206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64653a3a6863393165613464303563316365653461a801573c70616c6c65745f6964656e746974793a3a44617461206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6831326333353561613466613863353634a901573c70616c6c65745f6964656e746974793a3a44617461206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6837636133383066353032393432656232aa01437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6834343765376131653638326162346635ab01437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6834373339663661376137643761383736ac01437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6837396366366664396334383433623737ad014a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6831333131353531323962323761626339ae013970616c6c65745f76657374696e673a3a4d6f64756c653c543e3a3a7570646174655f6c6f636b3a3a6862616433633764356566626538333837af01303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6833626532653661366430373033386663b0018d013c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a4c6f636b61626c6543757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a7365745f6c6f636b3a3a6864323937343037326339613966383632b10190013c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a4c6f636b61626c6543757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a72656d6f76655f6c6f636b3a3a6838656161316666663131333030376336b2015b3c70616c6c65745f6964656e746974793a3a43616c6c3c543e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6861323235323539636461353338626634b301386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6839626231376662613334616432383034b401386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6839333431653764653064373838343462b5014373705f696f3a3a73746f726167653a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a726561643a3a6862313536376130356164373062636539b601386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6836656165383638396261623039636436b701776672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a72656d6f76653a3a6864613336353438356637663663623735b801437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6830656637383365646363343165646235b901756672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a74616b653a3a6832313031613265643539323864366135ba013c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6864616166396438626630616361623862bb015a3c70616c6c65745f696e64696365733a3a4d6f64756c653c543e2061732073705f72756e74696d653a3a7472616974733a3a5374617469634c6f6f6b75703e3a3a6c6f6f6b75703a3a6837313364343638613163643335353866bc019a013c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a52657365727661626c6543757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a726570617472696174655f72657365727665643a3a6830356366666465303732373331396430bd01b2013c6672616d655f73797374656d3a3a4d6f64756c653c543e206173206672616d655f737570706f72743a3a7472616974733a3a53746f7265644d61703c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449642c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e74446174613e3e3a3a7472795f6d75746174655f6578697374733a3a6830626634393562316139623631363136be01456672616d655f737570706f72743a3a7472616974733a3a4f6e556e62616c616e6365643a3a6f6e5f756e62616c616e6365643a3a6839336464313066356239626436316532bf015d3c70616c6c65745f636f6e7472616374733a3a7761736d3a3a5761736d566d2061732070616c6c65745f636f6e7472616374733a3a657865633a3a566d3c543e3e3a3a657865637574653a3a6830616231303436396539613265633436c0016a3c70616c6c65745f636f6e7472616374733a3a7761736d3a3a5761736d566d2061732070616c6c65745f636f6e7472616374733a3a657865633a3a566d3c543e3e3a3a657865637574653a3a7b7b636c6f737572657d7d3a3a6834366233336639333361666331623763c10181013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6761733a3a6837386632636636346164646431343361c2018d013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f7365745f73746f726167653a3a6865636636323032383332323662373832c3018d013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6765745f73746f726167653a3a6861316636323737613331313130393663c40186013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f63616c6c3a3a6835663230636636663165333839393563c5018d013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f696e7374616e74696174653a3a6864326532663539636465306138353130c60188013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f72657475726e3a3a6832396461353161396162646234303561c70188013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f63616c6c65723a3a6864656633663032383134636361353231c80189013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f616464726573733a3a6838363865653237653462343861353831c9018b013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6761735f70726963653a3a6838316537663035313265643362373466ca018a013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6761735f6c6566743a3a6830323362363536383233336135643562cb0189013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f62616c616e63653a3a6833373533346361366335393763656365cc0193013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f76616c75655f7472616e736665727265643a3a6839643532393035373536616536656334cd0188013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f72616e646f6d3a3a6835323963343639616539633636613265ce0185013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6e6f773a3a6864303339646232663361373133333062cf0191013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6d696e696d756d5f62616c616e63653a3a6833383066663563313534633435326139d00193013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f746f6d6273746f6e655f6465706f7369743a3a6831373233646136613864666162336265d1018f013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f64697370617463685f63616c6c3a3a6864656237366538396137353465393239d2018c013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f726573746f72655f746f3a3a6835333538653031613762356330323661d3018e013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f736372617463685f73697a653a3a6832326366363133306331333139393665d4018e013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f736372617463685f726561643a3a6864623333366664343434653230626561d5018f013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f736372617463685f77726974653a3a6831393062363833343835346334613038d6018f013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6465706f7369745f6576656e743a3a6863626133613366323965316631636331d70194013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f7365745f72656e745f616c6c6f77616e63653a3a6832373836383431393861646365373234d80190013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f72656e745f616c6c6f77616e63653a3a6863306338613638333737383764643965d90189013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f7072696e746c6e3a3a6837353265393162333164363565656363da018e013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f626c6f636b5f6e756d6265723a3a6836616438613932323135336566613130db0195013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6765745f72756e74696d655f73746f726167653a3a6865356330316164393839303662636531dc013273705f73616e64626f783a3a696d703a3a64697370617463685f7468756e6b3a3a6832636535326261616330666564666539dd017673705f7761736d5f696e746572666163653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722073705f7761736d5f696e746572666163653a3a56616c75653e3a3a6465636f64653a3a6839313739656230363031656533383836de015f3c70616c6c65745f76657374696e673a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6830646439393530393564373262353463df01603c70616c6c65745f6964656e746974793a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6833663566636439386265313137303437e0013a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f666d743a3a6833653531353264366636393366323138e101763c70616c6c65745f617574686f726974795f646973636f766572793a3a43616c6c3c543e206173206672616d655f737570706f72743a3a776569676874733a3a4765744469737061746368496e666f3e3a3a6765745f64697370617463685f696e666f3a3a6866393163313136663435613438343064e2016d3c70616c6c65745f636f6e7472616374733a3a436865636b426c6f636b4761734c696d69743c543e2061732073705f72756e74696d653a3a7472616974733a3a5369676e6564457874656e73696f6e3e3a3a76616c69646174653a3a6862663066343538646438323534633637e301386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6833353631386263323061643263613533e401613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6864393066656662656632323737333362e501723c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6863353262383862393764653164663663e6016b3c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c7533323e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6833616161343464303637643966393839e7017973705f7761736d5f696e746572666163653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722073705f7761736d5f696e746572666163653a3a56616c75653e3a3a656e636f64655f746f3a3a6834643861343162616434623230643364e801746672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a6765743a3a6835343864373232376232643037633430e901776672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a6830303337653433303935393165346337ea01a40170616c6c65745f636f6e7472616374733a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722070616c6c65745f636f6e7472616374733a3a526177416c697665436f6e7472616374496e666f3c436f6465486173682c42616c616e63652c426c6f636b4e756d6265723e3e3a3a656e636f64655f746f3a3a6861316130663965323139306439396462eb01776672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a6862343962393235313735323264323630ec01776672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a72656d6f76653a3a6836336536666330643963316533366634ed0148616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e3a3a696e736572743a3a6837363937636365653339363865616236ee014b616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a566163616e74456e7472793c4b2c563e3a3a696e736572743a3a6835613966376333393662653462643339ef0196013c70616c6c65745f636f6e7472616374733a3a54726965496446726f6d506172656e74436f756e7465723c543e2061732070616c6c65745f636f6e7472616374733a3a54726965496447656e657261746f723c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a747269655f69643a3a6832636363666634323635323632633537f0013e70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6831666364396535623831306162613631f1014070616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6836396132326261376438663336313562f2016e3c70616c6c65745f636f6e7472616374733a3a5f5f4765744279746553747275637447617350726963653c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6832313933383630343736616536643161f301723c70616c6c65745f636f6e7472616374733a3a5f5f476574427974655374727563745072697374696e65436f64653c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6866303165636637666430633738653561f4013c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6836326263326333363362626461396362f501753c70616c6c65745f636f6e7472616374733a3a5f5f4765744279746553747275637443757272656e745363686564756c653c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6861316162373937613336646662393538f6017a70616c6c65745f636f6e7472616374733a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722070616c6c65745f636f6e7472616374733a3a5363686564756c653e3a3a656e636f64655f746f3a3a6839316533333465313534386462636435f7014970616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6835356134613666383464343536393137f8019b013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a426c6f636b4761734c696d697444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6862306333613464356264316163336364f9019a013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d617856616c756553697a6544656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6865353538393163646262356665653137fa0196013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d6178446570746844656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6835646538346138626334653730653631fb0199013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a43616c6c4261736546656544656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6862356364303861386132383430306465fc0199013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a436f6e747261637446656544656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6839356632376435306234633563396539fd01a0013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5472616e73616374696f6e4279746546656544656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6834396539323330633263653965326439fe019d013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a53757263686172676552657761726444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6836346431373063663439663765613561ff019f013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a52656e744465706f7369744f666673657444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6837653566646530393834663365336436800299013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a52656e744279746546656544656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a683539613039636661343265373338653181029f013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a53746f7261676553697a654f666673657444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68313962353564306261353461323862388202a1013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5369676e6564436c61696d48616e646963617044656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a683361383937616664656433323233313283023970616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a626172655f63616c6c3a3a686336636332643061363433326236653084023170616c6c65745f636f6e7472616374733a3a6761733a3a6275795f6761733a3a68653765383535386530336633616466638502386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a686434323039623536316261396662643586024870616c6c65745f636f6e7472616374733a3a657865633a3a457865637574696f6e436f6e746578743c542c562c4c3e3a3a63616c6c3a3a68303237613963386439393335653930378702783c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6d6d69743a3a683330303963313230356230303237323588023b70616c6c65745f636f6e7472616374733a3a6761733a3a726566756e645f756e757365645f6761733a3a686534666639326335613434343135343189023a70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a726573746f72655f746f3a3a68393833393634383630336662373065338a02613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a68613863343435373161346665336464338b0268636f72653a3a6f70733a3a66756e6374696f6e3a3a696d706c733a3a3c696d706c20636f72653a3a6f70733a3a66756e6374696f6e3a3a466e4d75743c413e20666f7220266d757420463e3a3a63616c6c5f6d75743a3a68343961363066366433323062313937668c02437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a68363363303464386163333238383865618d02a4013c6672616d655f73797374656d3a3a4d6f64756c653c543e206173206672616d655f737570706f72743a3a7472616974733a3a53746f7265644d61703c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449642c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e74446174613e3e3a3a6765743a3a68313135643639326232623562306536378e0291013c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a43757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6d616b655f667265655f62616c616e63655f62653a3a68303036633065343463626462386335378f02b2013c6672616d655f73797374656d3a3a4d6f64756c653c543e206173206672616d655f737570706f72743a3a7472616974733a3a53746f7265644d61703c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449642c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e74446174613e3e3a3a7472795f6d75746174655f6578697374733a3a68373837313763663034356638646639379002613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a683161376130343432613333343435353791027770616c6c65745f636f6e7472616374733a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722070616c6c65745f636f6e7472616374733a3a5363686564756c653e3a3a6465636f64653a3a686637373162646261633963646636356692023b70616c6c65745f636f6e7472616374733a3a7761736d3a3a636f64655f63616368653a3a6c6f61643a3a68386436643935613931356135356361669302386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a686131613839643738396639386366663994024470616c6c65745f636f6e7472616374733a3a7761736d3a3a707265706172653a3a707265706172655f636f6e74726163743a3a683963346466376637656264333336306595026f3c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163745265663c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a686534306530336162653065363761633196023c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a683537373764663566376362613233326197024b616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a566163616e74456e7472793c4b2c563e3a3a696e736572743a3a6835356638373935633738353034613239980248616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e3a3a696e736572743a3a6830313365376231616330616238396664990248616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e3a3a696e736572743a3a68316538663462633234356236613936309a0248616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e3a3a696e736572743a3a68326666653366663463656230306334349b024b616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a566163616e74456e7472793c4b2c563e3a3a696e736572743a3a68353635363837323631353035383561619c025c3c70616c6c65745f636f6e7472616374733a3a43616c6c3c543e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a68613531393237346630613339326339359d02437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a68353631376562306538303763376661619e024f70616c6c65745f636f6e7472616374733a3a657865633a3a457865637574696f6e436f6e746578743c542c562c4c3e3a3a696e7374616e74696174653a3a68663939323535613062626434333264369f023870616c6c65745f636f6e7472616374733a3a72656e743a3a656e6163745f766572646963743a3a6833663932353133653465303634383231a002b2013c6672616d655f73797374656d3a3a4d6f64756c653c543e206173206672616d655f737570706f72743a3a7472616974733a3a53746f7265644d61703c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449642c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e74446174613e3e3a3a7472795f6d75746174655f6578697374733a3a6837376362363235323563613138313361a102613c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6866373932333238663439646534353835a202613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6831373930336362376239393933666237a302613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6834613032316234663762396331353035a4023f70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a6c61756e63685f65787465726e616c3a3a6864636435383264653630313266353739a502386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6836613264393532346438653338623938a6024170616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a696e6a6563745f7265666572656e64756d3a3a6837656665363237353866636565663161a7023d70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a6c61756e63685f7075626c69633a3a6861653531363131363131663531343739a8023a70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a6465706f7369745f6f663a3a6864343737613236653738633964366530a9023a70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a766f746572735f666f723a3a6861313564373563666162636439623538aa02386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6832343333626537383965646237643264ab023770616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a766f74655f6f663a3a6865313532363036346565353538313837ac023f70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a64656c6567617465645f766f7465733a3a6838663066383063616638376130373630ad02386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6834636163346139323662373065653130ae0285013c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a456e756d657261746f723c4b2c562c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6832663561306362623432353032326630af024070616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a636c6561725f7265666572656e64756d3a3a6862353335303165396538633865373162b0024470616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a69735f6163746976655f7265666572656e64756d3a3a6836393530613263613866663866366263b1023e70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a656e6163745f70726f706f73616c3a3a6830333739393831663836626535663631b202386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6831316664313364366633643966326666b3026b6e6f64655f72756e74696d653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f72206e6f64655f72756e74696d653a3a43616c6c3e3a3a6465636f64653a3a6835623764626236663631316161646532b4024873705f72756e74696d653a3a7472616974733a3a4163636f756e744964436f6e76657273696f6e3a3a696e746f5f6163636f756e743a3a6863636231373236653862303264366236b502446672616d655f737570706f72743a3a7472616974733a3a43757272656e63793a3a7265736f6c76655f6372656174696e673a3a6861346566313663366462636431646335b602696672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a4b6579466f726d61743a3a73746f726167655f6c696e6b65645f6d61705f66696e616c5f6b65793a3a6861383738393835613830353365383963b7023e70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6837623835393735313135623264346164b8023f70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a7265666572656e64756d5f696e666f3a3a6839333538333539646364333663323833b9024070616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6830396363356161386362633238366630ba02713c70616c6c65745f64656d6f63726163793a3a5f5f4765744279746553747275637444656c65676174696f6e733c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6833383038366163643261363561356466bb02713c70616c6c65745f64656d6f63726163793a3a5f5f476574427974655374727563745075626c696350726f70733c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6833663430353665376564636663623331bc024970616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6831633066343861616332363266616361bd029a013c70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4c61756e6368506572696f6444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6863396563396332356233636634626563be02a3013c70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a456d657267656e6379566f74696e67506572696f6444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6864613834666262353431366439313939bf029c013c70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d696e696d756d4465706f73697444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6864373463363933613134633834636266c0029d013c70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a456e6163746d656e74506572696f6444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6862313932333663386663313563663464c1027970616c6c65745f64656d6f63726163793a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722070616c6c65745f64656d6f63726163793a3a43616c6c3c543e3e3a3a656e636f64655f746f3a3a6839316362646638646466653163326563c202723c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163745265663c753132383e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6830396337336132333262623137633637c3025c3c70616c6c65745f64656d6f63726163793a3a43616c6c3c543e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6836393037383137373764306533313833c402497061726974795f7363616c655f636f6465633a3a656e636f64655f617070656e643a3a657874726163745f6c656e6774685f646174613a3a6861323737633931663966633832343536c502703c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6836373132303034303161363232316536c6023770616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a646f5f766f74653a3a6838306564663337383637623230633734c702386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6861613032313139336661353466313466c802386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6864666563643863613434303466653366c902386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6831663364373439653865393736373433ca02336672616d655f73797374656d3a3a4d6f64756c653c543e3a3a6465635f7265663a3a6866623736663362613165303766633035cb02386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6866373062353963393134653466366664cc02403c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6835376438666264666661356536313336cd02cc016672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f72206672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a456e636f64654c696b654c696e6b6167653c504b65792c4e4b65792c4b65793e3e3a3a656e636f64655f746f3a3a6831623735616532313532353064303065ce02b8016672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f72206672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a4c696e6b6167653c4b65793e3e3a3a656e636f64655f746f3a3a6830663661353638316331663339346166cf02776672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a6833653830653835353338653637393234d002336672616d655f73797374656d3a3a4d6f64756c653c543e3a3a696e635f7265663a3a6836646332373763313136386261333231d102303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6831323538623636633732623036643265d20290013c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a4c6f636b61626c6543757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a657874656e645f6c6f636b3a3a6833643665336338646436656636303639d302613c70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6837633139316333333337663637653031d402466e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f6672616d655f73797374656d3a3a6865623931306334346537323036373461d502486e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f7574696c6974793a3a6836363863623035333837373130383430d602486e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f696e64696365733a3a6836643166363239306366636639393733d702496e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f62616c616e6365733a3a6832616664353261663736316465366137d802486e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f7374616b696e673a3a6833303138613065373830313333323064d902486e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f73657373696f6e3a3a6864646437393836396561336166633536da024a6e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f64656d6f63726163793a3a6838333037376431393062653939376239db02556e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f636f6c6c6563746976655f496e7374616e6365313a3a6865313232383762356362376564343737dc02536e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f656c656374696f6e735f70687261676d656e3a3a6863303834306631623039353333626464dd02556e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f6d656d626572736869705f496e7374616e6365313a3a6839376663336538323662343138396665de02486e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f6772616e6470613a3a6834656130353731613762343664373239df02496e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f74726561737572793a3a6830373363306637653237663761663665e0024a6e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f636f6e7472616374733a3a6839353032663465633532356235343834e102456e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f7375646f3a3a6836663862323963636236643033656432e2024a6e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f696d5f6f6e6c696e653a3a6837306461633661323161326663343233e302496e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f6f6666656e6365733a3a6837653935663965313737343138396465e402496e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f6964656e746974793a3a6864323566616461376531383665623030e502486e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f736f63696574793a3a6864353132313661373839333164396230e602496e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f7265636f766572793a3a6866626139646162636665633364396464e702486e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f76657374696e673a3a6861363262353761313065343930346632e8023f7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64655f746f3a3a6838343038363961353863306238633831e902713c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163745265663c7536343e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6865663737323932393138336431383266ea026f3c73705f72756e74696d653a3a67656e657269633a3a6469676573743a3a4469676573744974656d3c486173683e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64653a3a6831313834343738393863386135316431eb027d3c70616c6c65745f696e64696365733a3a616464726573733a3a416464726573733c4163636f756e7449642c4163636f756e74496e6465783e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6866373564666366356336376563393039ec027d70616c6c65745f636f6c6c6563746976653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722070616c6c65745f636f6c6c6563746976653a3a43616c6c3c542c493e3e3a3a656e636f64655f746f3a3a6830336137386332646162616262353639ed02426e6f64655f72756e74696d653a3a53657373696f6e4b6579733a3a696e746f5f7261775f7075626c69635f6b6579733a3a6865363666373333336261333361656138ee02726e6f64655f72756e74696d653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f72206e6f64655f72756e74696d653a3a53657373696f6e4b6579733e3a3a6465636f64653a3a6866383733633364623931393465663334ef026f6e6f64655f72756e74696d653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f72206e6f64655f72756e74696d653a3a4576656e743e3a3a656e636f64655f746f3a3a6836626563363563353439336235386430f0028e0170616c6c65745f636f6c6c6563746976653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722070616c6c65745f636f6c6c6563746976653a3a5261774576656e743c486173682c4163636f756e7449642c493e3e3a3a656e636f64655f746f3a3a6865303133366466313030306239663335f102653c6e6f64655f72756e74696d653a3a43616c6c206173206672616d655f737570706f72743a3a776569676874733a3a4765744469737061746368496e666f3e3a3a6765745f64697370617463685f696e666f3a3a6834643231363136623235343830393733f20285013c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a43757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a7472616e736665723a3a6838613464363664643134303736633435f302483c5b543b20385d206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6862313130666166363137363031643033f402386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6836363337366131376538323362356639f502437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6838363233323763633465313534353935f602386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6839623530666537326538663164333134f702386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6835333763326636653234643430373466f802766672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a76616c75653a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f7261676556616c75653c543e20666f7220473e3a3a6765743a3a6839363766366165353436323166386432f902437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6834653330353461386138396466613831fa02366672616d655f73797374656d3a3a4d6f64756c653c543e3a3a626c6f636b5f686173683a3a6832343433373138633535643534383837fb023770616c6c65745f617574686f72736869703a3a4d6f64756c653c543e3a3a617574686f723a3a6830346631366664353137633465323134fc023b70616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a7265776172645f62795f6964733a3a6833363239333634383232366539633037fd023f70616c6c65745f696d5f6f6e6c696e653a3a4d6f64756c653c543e3a3a6e6f74655f617574686f72736869703a3a6838373535346134356237343833666139fe025c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6831636464336665313164376232616363ff02386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a686464373839356134636236346362323380035a3c70616c6c65745f7374616b696e673a3a43616c6c3c543e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a686539373436323161663739613036626581033470616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a6c65646765723a3a68623765613233396435313531636631338203706672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a68353538323037653965363563333261378303386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68363332383862316439316339383966358403706672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a683835376436303732653465333161626485035f3c70616c6c65745f636f6c6c6563746976653a3a43616c6c3c542c493e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a686332656361626135373066333935643186035f3c70616c6c65745f636f6c6c6563746976653a3a43616c6c3c542c493e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a68336364396433343333353132646130348703653c70616c6c65745f656c656374696f6e735f70687261676d656e3a3a43616c6c3c543e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6838613562626239613433653037616562880399013c70616c6c65745f636f6c6c6563746976653a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a4368616e67654d656d626572733c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6368616e67655f6d656d626572735f736f727465643a3a683334633463386337383039346134376189038d013c70616c6c65745f636f6c6c6563746976653a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a4368616e67654d656d626572733c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a7365745f7072696d653a3a68663237303363366332376662323132358a034b6672616d655f737570706f72743a3a7472616974733a3a4368616e67654d656d626572733a3a7365745f6d656d626572735f736f727465643a3a68616163356163383434656339636335638b035b3c70616c6c65745f74726561737572793a3a43616c6c3c543e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a68653062373261643462393733306435648c03563c73705f72756e74696d653a3a44697370617463684572726f722061732073705f72756e74696d653a3a7472616974733a3a5072696e7461626c653e3a3a7072696e743a3a68633066373138633935356130643634378d03386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68303264623332613236646134313439648e035b3c70616c6c65745f7265636f766572793a3a43616c6c3c543e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a68613935396666393732666665386434658f035c3c70616c6c65745f736f63696574793a3a43616c6c3c542c493e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a683332353566313531643664303961346390034a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a683963333434653630633631653562336191033c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a683035353864643065373561356432613292032f636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a68613464643335613231313331613565342e31393693032b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a686462303138343034393838663262343594032b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a686130623962343764626266346632373395032b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a683030366334333662383333643465313396032b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a68353434316663386636616165373266369703543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68366636323035663034376166636165629803543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a683366323637663033373665616234663499036b3c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c7536343e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68376362326332663830623762623961359a03543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68386165376366653737663163373662649b037a3c70616c6c65745f696e64696365733a3a616464726573733a3a416464726573733c4163636f756e7449642c4163636f756e74496e6465783e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68613363643430363432386437373633329c036c3c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c753132383e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68393066663333616465356538656439379d037a70616c6c65745f636f6c6c6563746976653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722070616c6c65745f636f6c6c6563746976653a3a43616c6c3c542c493e3e3a3a6465636f64653a3a68363861393935633264643030666335659e036c70616c6c65745f7375646f3a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722070616c6c65745f7375646f3a3a43616c6c3c543e3e3a3a6465636f64653a3a68313635623762323539656631626237349f037470616c6c65745f7265636f766572793a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722070616c6c65745f7265636f766572793a3a43616c6c3c543e3e3a3a6465636f64653a3a6862626431623264323936633537373263a0039b063c6e6f64655f72756e74696d653a3a52756e74696d652061732073705f6170693a3a72756e74696d655f6465636c5f666f725f4d657461646174613a3a4d657461646174613c73705f72756e74696d653a3a67656e657269633a3a626c6f636b3a3a426c6f636b3c73705f72756e74696d653a3a67656e657269633a3a6865616465723a3a4865616465723c7533322c73705f72756e74696d653a3a7472616974733a3a426c616b6554776f3235363e2c73705f72756e74696d653a3a67656e657269633a3a756e636865636b65645f65787472696e7369633a3a556e636865636b656445787472696e7369633c3c70616c6c65745f696e64696365733a3a4d6f64756c653c6e6f64655f72756e74696d653a3a52756e74696d653e2061732073705f72756e74696d653a3a7472616974733a3a5374617469634c6f6f6b75703e3a3a536f757263652c6e6f64655f72756e74696d653a3a43616c6c2c73705f72756e74696d653a3a4d756c74695369676e61747572652c286672616d655f73797374656d3a3a436865636b56657273696f6e3c6e6f64655f72756e74696d653a3a52756e74696d653e2c206672616d655f73797374656d3a3a436865636b47656e657369733c6e6f64655f72756e74696d653a3a52756e74696d653e2c206672616d655f73797374656d3a3a436865636b4572613c6e6f64655f72756e74696d653a3a52756e74696d653e2c206672616d655f73797374656d3a3a436865636b4e6f6e63653c6e6f64655f72756e74696d653a3a52756e74696d653e2c206672616d655f73797374656d3a3a436865636b5765696768743c6e6f64655f72756e74696d653a3a52756e74696d653e2c2070616c6c65745f7472616e73616374696f6e5f7061796d656e743a3a4368617267655472616e73616374696f6e5061796d656e743c6e6f64655f72756e74696d653a3a52756e74696d653e2c2070616c6c65745f636f6e7472616374733a3a436865636b426c6f636b4761734c696d69743c6e6f64655f72756e74696d653a3a52756e74696d653e293e3e3e3e3a3a6d657461646174613a3a6839316236333832656330386563373266a103aa0173705f72756e74696d653a3a7472616e73616374696f6e5f76616c69646974793a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722073705f72756e74696d653a3a7472616e73616374696f6e5f76616c69646974793a3a5472616e73616374696f6e56616c69646974794572726f723e3a3a656e636f64655f746f3a3a6864373562303334313263386431613964a2036b3c70616c6c65745f696d5f6f6e6c696e653a3a4d6f64756c653c543e2061732073705f72756e74696d653a3a7472616974733a3a56616c6964617465556e7369676e65643e3a3a76616c69646174655f756e7369676e65643a3a6837623336343161326139316430653263a3033d70616c6c65745f696d5f6f6e6c696e653a3a4d6f64756c653c543e3a3a69735f6f6e6c696e655f6175783a3a6836356138323233393863633765333436a403633c636f72653a3a697465723a3a61646170746572733a3a4d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6863333836373734376630383533333761a5034d73705f696f3a3a6f6666636861696e3a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a6e6574776f726b5f73746174653a3a6835386163656333386634646635653633a6034a73705f696f3a3a63727970746f3a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a737232353531395f7369676e3a3a6862313662346664653430613036303833a703473c70616c6c65745f696d5f6f6e6c696e653a3a43616c6c3c543e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6831613936633561383337333835663638a80347636f72653a3a666d743a3a6e756d3a3a3c696d706c20636f72653a3a666d743a3a446562756720666f72207533323e3a3a666d743a3a6834383834303938396633316662393031a9033e73705f72756e74696d653a3a67656e657269633a3a656e636f64655f776974685f7665635f7072656669783a3a6861666233356534386630336131633465aa035273705f696f3a3a6f6666636861696e3a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a7375626d69745f7472616e73616374696f6e3a3a6866643232643034323535663638396634ab03583c70616c6c65745f696d5f6f6e6c696e653a3a4f6666636861696e4572723c426c6f636b4e756d6265723e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6862353663383330653462646339643934ac03383c285431302c205431312920617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6862363365393836373462613837326431ad03303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6838343338373437393439393761346636ae0396013c70616c6c65745f696d5f6f6e6c696e653a3a4d6f64756c653c543e2061732070616c6c65745f73657373696f6e3a3a4f6e6553657373696f6e48616e646c65723c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6f6e5f6265666f72655f73657373696f6e5f656e64696e673a3a6835326264663665323061663230616233af03d3023c70616c6c65745f7374616b696e673a3a4578706f737572654f663c543e2061732073705f72756e74696d653a3a7472616974733a3a436f6e766572743c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449642c636f72653a3a6f7074696f6e3a3a4f7074696f6e3c70616c6c65745f7374616b696e673a3a4578706f737572653c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449642c3c3c542061732070616c6c65745f7374616b696e673a3a54726169743e3a3a43757272656e6379206173206672616d655f737570706f72743a3a7472616974733a3a43757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a42616c616e63653e3e3e3e3a3a636f6e766572743a3a6864336563323230643131303961653731b003443c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6837316233383732353337356534613433b103706672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a6866313464336431333934636663663461b20368636f72653a3a6f70733a3a66756e6374696f6e3a3a696d706c733a3a3c696d706c20636f72653a3a6f70733a3a66756e6374696f6e3a3a466e4d75743c413e20666f7220266d757420463e3a3a63616c6c5f6d75743a3a6833613439393630306633646462633366b303f4013c70616c6c65745f7374616b696e673a3a4d6f64756c653c543e2061732073705f7374616b696e673a3a6f6666656e63653a3a4f6e4f6666656e636548616e646c65723c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449642c283c542061732070616c6c65745f73657373696f6e3a3a54726169743e3a3a56616c696461746f7249642c203c542061732070616c6c65745f73657373696f6e3a3a686973746f726963616c3a3a54726169743e3a3a46756c6c4964656e74696669636174696f6e293e3e3a3a6f6e5f6f6666656e63653a3a6865323661336162313866616434366362b4033570616c6c65745f7374616b696e673a3a736c617368696e673a3a646f5f736c6173683a3a6835316433626631383463363062666264b5033470616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a626f6e6465643a3a6836383731343534656366306135396566b6033b70616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a7570646174655f6c65646765723a3a6836363232636237373934613763323731b7034970616c6c65745f7374616b696e673a3a736c617368696e673a3a496e7370656374696e675370616e733c543e3a3a6572615f7370616e3a3a6864333736336438623638363764626463b8035e70616c6c65745f7374616b696e673a3a736c617368696e673a3a496e7370656374696e675370616e733c543e3a3a636f6d706172655f616e645f7570646174655f7370616e5f736c6173683a3a6830383866303961623436356330353464b903726672616d655f6578656375746976653a3a4578656375746976653c53797374656d2c426c6f636b2c436f6e746578742c556e7369676e656456616c696461746f722c416c6c4d6f64756c65733e3a3a696e697469616c697a655f626c6f636b3a3a6838643534356164393831393863336636ba03746672616d655f6578656375746976653a3a4578656375746976653c53797374656d2c426c6f636b2c436f6e746578742c556e7369676e656456616c696461746f722c416c6c4d6f64756c65733e3a3a657874726163745f7072655f6469676573743a3a6865333534653561626234386137663365bb03437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6830376536373730333530373833656436bc03386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6861326437366139663161623532383733bd03716672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b6579313a3a6865373436346265383633313432373532be034a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6835346434363165306161633464373939bf032d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a6861613633323434613665653438656434c003716672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b6579313a3a6838383536616163313135363263636137c103386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6830656362303838376238633237393736c203716672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b6579313a3a6864636135303635303264633961666634c303543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6865396565343764623562313863356563c403437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6839346666363633626539396531633266c5037a3c6672616d655f737570706f72743a3a73746f726167653a3a6d6967726174696f6e3a3a53746f726167654974657261746f723c543e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6831373562343535613262623832323030c603476672616d655f737570706f72743a3a73746f726167653a3a6d6967726174696f6e3a3a7075745f73746f726167655f76616c75653a3a6833306138306533636233303166313264c703476672616d655f737570706f72743a3a73746f726167653a3a6d6967726174696f6e3a3a7075745f73746f726167655f76616c75653a3a6865373532383032313863616533303938c803476672616d655f737570706f72743a3a73746f726167653a3a6d6967726174696f6e3a3a6765745f73746f726167655f76616c75653a3a6833366530623033306631633562393836c9037a3c6672616d655f737570706f72743a3a73746f726167653a3a6d6967726174696f6e3a3a53746f726167654974657261746f723c543e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6835383261616133646632616264346238ca03386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6833663862646362333164663162646663cb037a3c6672616d655f737570706f72743a3a73746f726167653a3a6d6967726174696f6e3a3a53746f726167654974657261746f723c543e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6839376666626631653130386564646461cc03486672616d655f737570706f72743a3a73746f726167653a3a6d6967726174696f6e3a3a74616b655f73746f726167655f76616c75653a3a6861376363353162666564653361656135cd034b6672616d655f73797374656d3a3a4d6f64756c653c543e3a3a72656769737465725f65787472615f7765696768745f756e636865636b65643a3a6861373334663833333132613335386634ce03366672616d655f73797374656d3a3a4d6f64756c653c543e3a3a696e697469616c697a653a3a6861366633623938363765326336326339cf03733c285475706c65456c656d656e74302c205475706c65456c656d656e7431292061732073705f72756e74696d653a3a7472616974733a3a4f6e496e697469616c697a653c426c6f636b4e756d6265723e3e3a3a6f6e5f696e697469616c697a653a3a6830363934306464326139363764343331d0037a6672616d655f6578656375746976653a3a4578656375746976653c53797374656d2c426c6f636b2c436f6e746578742c556e7369676e656456616c696461746f722c416c6c4d6f64756c65733e3a3a6170706c795f65787472696e7369635f776974685f6c656e3a3a6861623933646434343165633861376231d1039f013c73705f72756e74696d653a3a67656e657269633a3a756e636865636b65645f65787472696e7369633a3a556e636865636b656445787472696e7369633c416464726573732c43616c6c2c5369676e61747572652c45787472613e2061732073705f72756e74696d653a3a7472616974733a3a436865636b61626c653c4c6f6f6b75703e3e3a3a636865636b3a3a6838356661333738313536613735323032d2035c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6865656334656163333836303065663964d303406672616d655f73797374656d3a3a436865636b5765696768743c543e3a3a646f5f7072655f64697370617463683a3a6835363737346566346462643931396133d4037d3c70616c6c65745f7472616e73616374696f6e5f7061796d656e743a3a4368617267655472616e73616374696f6e5061796d656e743c543e2061732073705f72756e74696d653a3a7472616974733a3a5369676e6564457874656e73696f6e3e3a3a76616c69646174653a3a6861613565313635386566313133336263d503363c5420617320636f72653a3a636f6e766572743a3a496e746f3c553e3e3a3a696e746f3a3a6861366631653164373332623438343138d603467061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a436f646553656374696f6e3a3a626f646965733a3a6830613263616439623032326331373162d7033e70616c6c65745f696d5f6f6e6c696e653a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6836353063333436636663323066366539d8034070616c6c65745f696d5f6f6e6c696e653a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6863666562343031626262393331366338d9034570616c6c65745f66696e616c6974795f747261636b65723a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6863373533353930333435623035626436da035070616c6c65745f66696e616c6974795f747261636b65723a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6862633538306330326534653434616137db03a2013c70616c6c65745f66696e616c6974795f747261636b65723a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5265706f72744c6174656e637944656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6832323938306530353931623165643666dc039f013c70616c6c65745f66696e616c6974795f747261636b65723a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a57696e646f7753697a6544656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6831363063393361316436313534623165dd0334636f72653a3a736c6963653a3a736f72743a3a627265616b5f7061747465726e733a3a6831323438383566306438653036623037de032e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a6863663161613466313036646532353033df033c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a6836613661393737383033306439363061e0032d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a6862363037313061353363363061616630e10334636f72653a3a736c6963653a3a736f72743a3a627265616b5f7061747465726e733a3a6837646333626436363865626561376462e2032e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a6831373930643832323038393461373038e3033c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a6835323737626231363136323834363632e4032d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a6864303138386633353034386432333663e50334636f72653a3a736c6963653a3a736f72743a3a627265616b5f7061747465726e733a3a6838356538663638636139653863616532e6032e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a6839616630646135613731666561663835e7033c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a6866616464313535383135636538663934e803573c49642061732073705f72756e74696d653a3a7472616974733a3a4163636f756e744964436f6e76657273696f6e3c543e3e3a3a696e746f5f7375625f6163636f756e743a3a6831336533616531303362303733353130e903553c73705f72756e74696d653a3a4d756c74695369676e61747572652061732073705f72756e74696d653a3a7472616974733a3a5665726966793e3a3a7665726966793a3a6838343238646263656161303237353965ea036073705f696f3a3a63727970746f3a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a736563703235366b315f65636473615f7265636f7665725f636f6d707265737365643a3a6832393038643332346433613331366539eb03613c70616c6c65745f696d5f6f6e6c696e653a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6838313830643536343735383630663934ec03683c70616c6c65745f66696e616c6974795f747261636b65723a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6866633135656635383130353232346135ed037d7061726974795f7363616c655f636f6465633a3a636f6465633a3a696e6e65725f7475706c655f696d706c3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f72202851302c205230293e3a3a6465636f64653a3a6861393832396435663965303637306637ee03543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6831643130383766386135353334333433ef03437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6838633538323632396537656530386639f003303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6835343266353666663539323633666630f103393c54206173206672616d655f737570706f72743a3a7472616974733a3a4c656e3e3a3a6c656e3a3a6863343463386439663762623033383161f2032d616c6c6f633a3a7665633a3a5665633c543e3a3a726573697a653a3a6830336532313730326130343162613935f303443c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6831636232396664353236653137643163f403463c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6838343634333533643836646563633965f503543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6832653338333466336137313262363366f603723c73705f72756e74696d653a3a67656e657269633a3a6865616465723a3a4865616465723c4e756d6265722c486173683e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6833383166383730333239313664353538f703543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6839383337376237656362663436333239f803513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a6836336236343538336535646333613337f903513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a6839306462366562313630333038353364fa03733c285475706c65456c656d656e74302c205475706c65456c656d656e7431292061732073705f72756e74696d653a3a7472616974733a3a4f6e496e697469616c697a653c426c6f636b4e756d6265723e3e3a3a6f6e5f696e697469616c697a653a3a6832363161613066376437646137356437fb033870616c6c65745f626162653a3a4d6f64756c653c543e3a3a646f5f696e697469616c697a653a3a6863613262366666333064623965643466fc033e70616c6c65745f626162653a3a4d6f64756c653c543e3a3a63757272656e745f65706f63685f73746172743a3a6866613161653966323663373761316164fd03386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6863613461346432316630373239303065fe03386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6836356537383964666166633936376462ff033770616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a73746172745f6572613a3a686235313437356561346234313636313780043570616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a6e65775f6572613a3a68346439386131373866643831353638648104386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68356636323535626532306433353463328204776672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a68343237323961343932343232653131398304386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a686562326636626634356364326134633884043d70616c6c65745f6772616e6470613a3a4d6f64756c653c543e3a3a7363686564756c655f6368616e67653a3a68353962323530333063386232366634648504386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68393035386161303733373865386330328604386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a683665636135313764646237323539383987043c70616c6c65745f626162653a3a4d6f64756c653c543e3a3a6465706f7369745f636f6e73656e7375733a3a686339643233333135643832333236363888042b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a68633031303439663033633938346435378904386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68333631636530366634366330633564628a04376672616d655f73797374656d3a3a4d6f64756c653c543e3a3a6465706f7369745f6c6f673a3a68396266343464313637373665613037338b043a6672616d655f73797374656d3a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a68343638646531353062656435303435368c043c6672616d655f73797374656d3a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a68306636363562636531666639316539628d04703c70616c6c65745f73657373696f6e3a3a5f5f4765744279746553747275637443757272656e74496e6465783c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68366438636264323339366535626135318e04683c6672616d655f73797374656d3a3a5f5f476574427974655374727563744576656e74733c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68656439376363303933656438623464348f04703c6672616d655f73797374656d3a3a5f5f4765744279746553747275637445787472696e73696373526f6f743c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68623663366163613935306233363138649004703c6672616d655f73797374656d3a3a5f5f4765744279746553747275637445787472696e736963436f756e743c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68613438336337326433633963303161669104693c6672616d655f73797374656d3a3a5f5f476574427974655374727563744163636f756e743c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68653130663639666536356336383931629204346672616d655f73797374656d3a3a4d6f64756c653c543e3a3a66696e616c697a653a3a6861333061323831663063363435393834930485013c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a456e756d657261746f723c4b2c562c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a68306666316438326133653164336666669404696672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a4b6579466f726d61743a3a73746f726167655f6c696e6b65645f6d61705f66696e616c5f6b65793a3a68313638333738373563336632353635329504386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6836366135613838613330376563316639960485013c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a456e756d657261746f723c4b2c562c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a68316531666161306332363733663661649704696672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a4b6579466f726d61743a3a73746f726167655f6c696e6b65645f6d61705f66696e616c5f6b65793a3a68646632333331346336336337356264649804386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6832616162306362303164613465313131990485013c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a456e756d657261746f723c4b2c562c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a68353662643439663662646438316338629a04696672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a4b6579466f726d61743a3a73746f726167655f6c696e6b65645f6d61705f66696e616c5f6b65793a3a68336665643063333931666639616463309b04386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68623865633930613264313361366462389c044a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a68383033323135663636663530346563399d043c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a68636433653434303562366362373966619e043c70616c6c65745f73657373696f6e3a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a68666539616263656334653932356361309f043e70616c6c65745f73657373696f6e3a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6837353435313161666338396166353565a0044770616c6c65745f73657373696f6e3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6861386132383637626637343931323961a1049c013c70616c6c65745f73657373696f6e3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a44454455505f4b45595f50524546495844656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6863303466636434366265346264653334a2043570616c6c65745f73657373696f6e3a3a4d6f64756c653c543e3a3a64697361626c653a3a6861393934323761663135663236636630a304437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6836613966336232366434363130353439a4049c013c73705f72756e74696d653a3a67656e657269633a3a756e636865636b65645f65787472696e7369633a3a556e636865636b656445787472696e7369633c416464726573732c43616c6c2c5369676e61747572652c45787472613e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6831623035623364306138373866306436a504b2013c6672616d655f73797374656d3a3a4d6f64756c653c543e206173206672616d655f737570706f72743a3a7472616974733a3a53746f7265644d61703c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449642c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e74446174613e3e3a3a7472795f6d75746174655f6578697374733a3a6834396135396639353464376461383039a6043c6672616d655f73797374656d3a3a436865636b5765696768743c543e3a3a646f5f76616c69646174653a3a6833376639363263363262376330636138a7045d3c6672616d655f73797374656d3a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6865323231363936613636653762653964a8045f3c70616c6c65745f73657373696f6e3a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6831376638636666393031313164333963a9046f3c285475706c65456c656d656e74302c205475706c65456c656d656e7431292061732073705f72756e74696d653a3a7472616974733a3a4f6e46696e616c697a653c426c6f636b4e756d6265723e3e3a3a6f6e5f66696e616c697a653a3a6863613639353039343261363066343466aa04386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6839316338643937666233323264316236ab046f3c285475706c65456c656d656e74302c205475706c65456c656d656e7431292061732073705f72756e74696d653a3a7472616974733a3a4f6e46696e616c697a653c426c6f636b4e756d6265723e3e3a3a6f6e5f66696e616c697a653a3a6864643264313938386262343036356462ac0490013c70616c6c65745f72616e646f6d6e6573735f636f6c6c6563746976655f666c69703a3a4d6f64756c653c543e206173206672616d655f737570706f72743a3a7472616974733a3a52616e646f6d6e6573733c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a486173683e3e3a3a72616e646f6d3a3a6838623438303031316563393832363031ad04386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6837303666303832313061366661346232ae0468636f72653a3a6f70733a3a66756e6374696f6e3a3a696d706c733a3a3c696d706c20636f72653a3a6f70733a3a66756e6374696f6e3a3a466e4d75743c413e20666f7220266d757420463e3a3a63616c6c5f6d75743a3a6835643665346535376531643836336432af042d70616c6c65745f736f63696574793a3a7069636b5f7573697a653a3a6861313339316563613731346431383831b0043b70616c6c65745f736f63696574793a3a4d6f64756c653c542c493e3a3a62756d705f7061796f75743a3a6866633931313461663334373965353863b1043c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6832393232356239643265636531343138b204706672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a6838646365626133336331326432353035b3045c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6833303031616338376665366430373930b404396672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a74616b653a3a6861316631303063663633313131663031b5043e70616c6c65745f736f63696574793a3a4d6f64756c653c542c493e3a3a73757370656e645f6d656d6265723a3a6861643435633639366330383266376632b6044470616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a646f5f70687261676d656e3a3a6864326531616662306631333233323064b704386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6835303934643436346164333364663064b804437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6831353630366539353939653834636139b9043970616c6c65745f7375646f3a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6838366131353032633764646633323136ba043b70616c6c65745f7375646f3a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6834383830663966626337376666383039bb04643c70616c6c65745f7375646f3a3a5f5f476574427974655374727563744b65793c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6835343631316264623365356261313939bc043e70616c6c65745f736f63696574793a3a4d6f64756c653c542c493e3a3a63616c6c5f66756e6374696f6e733a3a6830653464393031396339343066613561bd044070616c6c65745f736f63696574793a3a4d6f64756c653c542c493e3a3a73746f726167655f6d657461646174613a3a6839306430626637386333373938383831be044970616c6c65745f736f63696574793a3a4d6f64756c653c542c493e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6863316661323230366563336363666333bf049e013c70616c6c65745f736f63696574793a3a4d6f64756c653c542c493e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a526f746174696f6e506572696f6444656661756c74427974654765747465723c542c493e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6865653837383138393735633434396362c0049b013c70616c6c65745f736f63696574793a3a4d6f64756c653c542c493e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a506572696f645370656e6444656661756c74427974654765747465723c542c493e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6831643836656139396431643038663938c1049a013c70616c6c65745f736f63696574793a3a4d6f64756c653c542c493e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d6178537472696b657344656661756c74427974654765747465723c542c493e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6835613765373830373334383936646237c204a2013c70616c6c65745f736f63696574793a3a4d6f64756c653c542c493e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a57726f6e6753696465446564756374696f6e44656661756c74427974654765747465723c542c493e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6839636439633864373135623130643239c304850170616c6c65745f736f63696574793a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722070616c6c65745f736f63696574793a3a4269644b696e643c4163636f756e7449642c42616c616e63653e3e3a3a6465636f64653a3a6865336265323830653333616261393437c4043d70616c6c65745f74726561737572793a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6864393733613163613237313631343730c5043f70616c6c65745f74726561737572793a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6836386531663064643431333037653066c6044870616c6c65745f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6836336666666561313538363835353462c7049a013c70616c6c65745f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a54697046696e6465727346656544656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6833653438623263353930393862646537c80498013c70616c6c65745f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5370656e64506572696f6444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6865613434626261396639616231326631c90491013c70616c6c65745f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4275726e44656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6862613436613435363034653231323365ca0499013c70616c6c65745f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a50726f706f73616c426f6e6444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6834363330343133336437623531356461cb04443c7061726974795f7761736d3a3a696f3a3a4572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6865386662346165393338366663353734cc046f3c7061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a53656374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6865613766356338653866623764383163cd042b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a6861323931376539633633386130386339ce04347761736d695f76616c69646174696f6e3a3a76616c69646174655f6d6f64756c653a3a6830346136386562343466626635623738cf0448616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e3a3a696e736572743a3a6836326231383837323861393963303830d0043c7061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a66726f6d5f6d6f64756c653a3a6830363635613134666339343330393763d104537061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a4d6f64756c654275696c6465723c463e3a3a7265736f6c76655f747970655f7265663a3a6831353837383863343566666539616566d204a9017061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a3c696d706c20636f72653a3a636f6e766572743a3a46726f6d3c7061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a4d6f64756c6553636166666f6c643e20666f72207061726974795f7761736d3a3a656c656d656e74733a3a6d6f64756c653a3a4d6f64756c653e3a3a66726f6d3a3a6866633639656565353635653932393835d30444707761736d5f7574696c733a3a6761733a3a436f756e7465723a3a66696e616c697a655f6d6574657265645f626c6f636b3a3a6864393833643833313031623561386535d4042d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a6836653865663132366235363563383365d504507061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a4d6f64756c654275696c6465723c463e3a3a707573685f66756e6374696f6e3a3a6833613061326634636332643634366162d6043c707761736d5f7574696c733a3a737461636b5f6865696768743a3a696e6a6563745f6c696d697465723a3a6838376435353561613436373461636566d7046b3c7061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a53656374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6832666634636163653661323937613735d8044170616c6c65745f6d656d626572736869703a3a4d6f64756c653c542c493e3a3a63616c6c5f66756e6374696f6e733a3a6835396635303536356536363838363265d9044370616c6c65745f6d656d626572736869703a3a4d6f64756c653c542c493e3a3a73746f726167655f6d657461646174613a3a6866363434663835393434633133666264da04437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6866613564656438353362333739643039db043c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6866353161666334303938653136326266dc0468636f72653a3a6f70733a3a66756e6374696f6e3a3a696d706c733a3a3c696d706c20636f72653a3a6f70733a3a66756e6374696f6e3a3a466e4d75743c413e20666f7220266d757420463e3a3a63616c6c5f6d75743a3a6836363761326132656265393764626563dd04386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6839363136643362343035313534396432de045c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6838313730643033303963376132316231df045c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6863363432616562643938356665613835e004386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6865653036386531326530656662613531e1044270616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a69735f6d656d6265723a3a6862333265636133396534633833323662e2045c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6863643264376161656233653035393038e30493013c70616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e206173206672616d655f737570706f72743a3a7472616974733a3a436f6e7461696e733c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a736f727465645f6d656d626572733a3a6833653137623636316633633638396637e404386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6830333630326465666238326134613937e5045c3c70616c6c65745f7375646f3a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6861613566363966396431353163326334e6043770616c6c65745f736f63696574793a3a4d6f64756c653c542c493e3a3a7075745f6269643a3a6838646135313434343439393330333865e7043a70616c6c65745f736f63696574793a3a4d6f64756c653c542c493e3a3a6164645f6d656d6265723a3a6831643836363035623636326362333433e8044273705f72756e74696d653a3a7472616974733a3a456e737572654f726967696e3a3a656e737572655f6f726967696e3a3a6865336566396636393138336531666138e904603c70616c6c65745f74726561737572793a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6830383030323039656462386234643037ea04613c70616c6c65745f736f63696574793a3a4d6f64756c653c542c493e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6834633234623361636236353433656330eb046b3c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c7533323e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6863326231633262353665333432646565ec04753c70616c6c65745f72616e646f6d6e6573735f636f6c6c6563746976655f666c69703a3a43616c6c3c543e206173206672616d655f737570706f72743a3a7472616974733a3a47657443616c6c4e616d653e3a3a6765745f63616c6c5f6e616d65733a3a6830663033343935353264336430373266ed04303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6861363534353137616431643466366439ee046f3c636f72653a3a697465723a3a61646170746572733a3a526573756c745368756e743c492c453e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a7472795f666f6c643a3a6832303535373938336535363336666432ef04303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6837616433376333343363333139306132f0045770616c6c65745f7472616e73616374696f6e5f7061796d656e743a3a4368617267655472616e73616374696f6e5061796d656e743c543e3a3a636f6d707574655f6665653a3a6835353838323765623762393839306338f1049a0173705f72756e74696d653a3a67656e657269633a3a626c6f636b3a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722073705f72756e74696d653a3a67656e657269633a3a626c6f636b3a3a426c6f636b3c4865616465722c45787472696e7369633e3e3a3a6465636f64653a3a6837666434643136643933633039303332f2043c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6863633339343936333437353237626438f304386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6838666634303138633539633336363138f404437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6837653635376634323630373866633838f5043e70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a6368617267655f6761733a3a6835636235653339653134326336333430f60481013c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f73746f726167653a3a6864646637313161353264313466656634f70488013c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f72656e745f616c6c6f77616e63653a3a6834373866323737663365313565353562f804683c636f72653a3a697465723a3a61646170746572733a3a4d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a73697a655f68696e743a3a6831393862383136373563353665363465f904633c636f72653a3a697465723a3a61646170746572733a3a4d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6831633565346165666436616430306532fa043e636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723a3a6e74683a3a6835653166333639636633343632643666fb043c70616c6c65745f6772616e6470613a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6833386537396134666339616339633663fc043e70616c6c65745f6772616e6470613a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6865623239663365613962333135363232fd04703c70616c6c65745f6772616e6470613a3a5f5f4765744279746553747275637443757272656e7453657449643c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6835343461383439373366353635336631fe04693c70616c6c65745f6772616e6470613a3a5f5f4765744279746553747275637453746174653c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6839303031613235613937653730346239ff043670616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e3a3a6c6f636b733a3a683661383831386135366164663734356180053d70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e3a3a7570646174655f6c6f636b733a3a686661326236663361643636623031646181053f70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e3a3a63616c6c5f66756e6374696f6e733a3a683763303365636264336266326636333382054170616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e3a3a73746f726167655f6d657461646174613a3a686137343937323234356435616263353483056e3c70616c6c65745f62616c616e6365733a3a5f5f476574427974655374727563744163636f756e743c542c493e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a683365373331643964366139633630383184054a70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a68643164383438613237643638333834668505810170616c6c65745f62616c616e6365733a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722070616c6c65745f62616c616e6365733a3a4163636f756e74446174613c42616c616e63653e3e3a3a6465636f64653a3a686433373830383365633664643432633286053f70616c6c65745f6f6666656e6365733a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a683463656635333165303731383437363287054a70616c6c65745f7472616e73616374696f6e5f7061796d656e743a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a683861613530356138396232616636303488055370616c6c65745f7472616e73616374696f6e5f7061796d656e743a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a683466343362653265353561363035303189055170616c6c65745f72616e646f6d6e6573735f636f6c6c6563746976655f666c69703a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a68653238363064396334396633323466328a05860170616c6c65745f7374616b696e673a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722070616c6c65745f7374616b696e673a3a4578706f737572653c4163636f756e7449642c42616c616e63653e3e3a3a6465636f64653a3a68306563383736383235343234303034648b055f3c70616c6c65745f6772616e6470613a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a68313662616463373865643862303665638c05623c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a68616436656630653262396237393434348d057d3c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f73746f726167653a3a68386661623331356636396364613634628e057f3c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f636f64655f686173683a3a68313866316333323538323034353836618f0584013c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f72656e745f616c6c6f77616e63653a3a6836383561636664373462303935396561900581013c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6e74726163745f6578697374733a3a683130663464383939386565386261396391057d3c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f62616c616e63653a3a686339353433303035303436396661363392058f0173705f636f6e73656e7375735f626162653a3a646967657374733a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722073705f636f6e73656e7375735f626162653a3a646967657374733a3a5261775072654469676573743e3a3a6465636f64653a3a683433343637626438333338313430633293054870616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a6c6f636b65645f7374616b655f6f663a3a683934386136303064666263303835646694054673705f61726974686d657469633a3a68656c706572735f3132386269743a3a6d756c7469706c795f62795f726174696f6e616c3a3a68653631313936646137623839666437619505533c73705f61726974686d657469633a3a726174696f6e616c3132383a3a526174696f6e616c31323820617320636f72653a3a636d703a3a4f72643e3a3a636d703a3a68633963383932646362363831653661379605583c73705f61726974686d657469633a3a726174696f6e616c3132383a3a526174696f6e616c31323820617320636f72653a3a636d703a3a5061727469616c45713e3a3a65713a3a686639336562373839616435663637363897054d6672616d655f737570706f72743a3a7472616974733a3a4368616e67654d656d626572733a3a636f6d707574655f6d656d626572735f646966663a3a6837383561376662303830653366383434980599013c70616c6c65745f636f6c6c6563746976653a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a4368616e67654d656d626572733c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6368616e67655f6d656d626572735f736f727465643a3a68383765393962646332376666323464379905386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68306633666161633962383864336137629a05386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68336437663239373464306564653539619b05386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68363830316233623632613032336261369c05386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68363965366462386532663261343465369d05386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68373637326165343964363764316230359e05386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68393830373164366634353933363063309f05386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6861623239303139633132336163353831a005386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6863633436633435306364396335393665a105386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6865303165313338323063653961623664a205396672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a74616b653a3a6837313965363362643131366664613332a3053370616c6c65745f636f6e7472616374733a3a657865633a3a7472616e736665723a3a6837333832353661386633626335356637a4057c3c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6d6d69743a3a6838353332666135353064323134323264a5052b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a6831623561373034363062313439316663a60583013c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f636f64655f686173683a3a6863613437396433636665613038376566a70585013c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6e74726163745f6578697374733a3a6835313835613262393338336462626262a80581013c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f62616c616e63653a3a6837313563313464643635666162663062a9053f70616c6c65745f617574686f72736869703a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6835333336366266333631333437353565aa054170616c6c65745f617574686f72736869703a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6834623930396261316464363765323731ab054770616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6836646230323662366462303235303437ac054970616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6831656439613037336536333766343934ad055270616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6863623237333933363766346432313339ae05a3013c70616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5465726d4475726174696f6e44656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6835373462386439623034303230303162af05a7013c70616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4465736972656452756e6e657273557044656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6830373063623034333434623464636132b005a5013c70616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a446573697265644d656d6265727344656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6834626366393965653732316437336666b105a4013c70616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a43616e646964616379426f6e6444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6837636230336665386231343330326264b205623c70616c6c65745f617574686f72736869703a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6835343031623966656263393935626235b3054170616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a69735f766f7465723a3a6863333235343861353633636232383861b4054870616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a646f5f72656d6f76655f766f7465723a3a6862393334343233333065303163316563b5055270616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a72656d6f76655f616e645f7265706c6163655f6d656d6265723a3a6833373866363734663932633637613865b6056a3c70616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6862336262393462656635356661363835b7054a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6861386637633236313234333339663137b8053d70616c6c65745f7265636f766572793a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6863396239353532393632323035623638b9053f70616c6c65745f7265636f766572793a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6863333038366633656138393132333763ba054170616c6c65745f636f6c6c6563746976653a3a4d6f64756c653c542c493e3a3a63616c6c5f66756e6374696f6e733a3a6836613765336134386339386161623464bb054370616c6c65745f636f6c6c6563746976653a3a4d6f64756c653c542c493e3a3a73746f726167655f6d657461646174613a3a6831386266323565356163366262366334bc054370616c6c65745f636f6c6c6563746976653a3a4d6f64756c653c542c493e3a3a73746f726167655f6d657461646174613a3a6866656261383436646564666539623663bd05437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6833633735346639393531303431613832be054a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6834316336613465656363326665666637bf053470616c6c65745f7265636f766572793a3a4d6f64756c653c543e3a3a70726f78793a3a6861636536313331306431366664333862c005716672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b6579313a3a6865373030636435633866663261316130c1053e70616c6c65745f7265636f766572793a3a4d6f64756c653c543e3a3a7265636f766572795f636f6e6669673a3a6839373334336330666230326134393062c2053e70616c6c65745f7265636f766572793a3a4d6f64756c653c543e3a3a6163746976655f7265636f766572793a3a6834636635353038353536663431343433c305603c70616c6c65745f7265636f766572793a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6861333866323563646363346264633333c4053970616c6c65745f636f6c6c6563746976653a3a4d6f64756c653c542c493e3a3a766f74696e673a3a6837626435393033386663633830356136c5054470616c6c65745f636f6c6c6563746976653a3a4d6f64756c653c542c493e3a3a66696e616c697a655f70726f706f73616c3a3a6835306531366361656334306335393065c6053970616c6c65745f636f6c6c6563746976653a3a4d6f64756c653c542c493e3a3a766f74696e673a3a6865656531616135306233306265366530c7054470616c6c65745f636f6c6c6563746976653a3a4d6f64756c653c542c493e3a3a66696e616c697a655f70726f706f73616c3a3a6833333632633934666533333763343831c805643c70616c6c65745f636f6c6c6563746976653a3a4d6f64756c653c542c493e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6833613764323036333266363938356466c9050c436f72655f76657273696f6eca056b3c73705f72756e74696d653a3a72756e74696d655f737472696e673a3a52756e74696d65537472696e67206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64653a3a6864333032633964306561306431383862cb0512436f72655f657865637574655f626c6f636bcc055373705f696f3a3a747269653a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a626c616b65325f3235365f6f7264657265645f726f6f743a3a6862643564616338353534313232356637cd0515436f72655f696e697469616c697a655f626c6f636bce05114d657461646174615f6d65746164617461cf051c426c6f636b4275696c6465725f6170706c795f65787472696e736963d0051b426c6f636b4275696c6465725f66696e616c697a655f626c6f636bd10520426c6f636b4275696c6465725f696e686572656e745f65787472696e73696373d2053a70616c6c65745f74696d657374616d703a3a657874726163745f696e686572656e745f646174613a3a6861396365383836326639306365343634d3051c426c6f636b4275696c6465725f636865636b5f696e686572656e7473d405453c737472206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64653a3a6838313935666665383031663034386566d50518426c6f636b4275696c6465725f72616e646f6d5f73656564d6052b5461676765645472616e73616374696f6e51756575655f76616c69646174655f7472616e73616374696f6ed7055373705f72756e74696d653a3a7472616e73616374696f6e5f76616c69646974793a3a56616c69645472616e73616374696f6e3a3a636f6d62696e655f776974683a3a6832356238666565616136386534636161d805214f6666636861696e576f726b65724170695f6f6666636861696e5f776f726b6572d9055173705f696f3a3a63727970746f3a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a737232353531395f7075626c69635f6b6579733a3a6834653530383333303662393361363064da051e4772616e6470614170695f6772616e6470615f617574686f726974696573db0515426162654170695f636f6e66696775726174696f6edc051b426162654170695f63757272656e745f65706f63685f7374617274dd0521417574686f72697479446973636f766572794170695f617574686f726974696573de051d4163636f756e744e6f6e63654170695f6163636f756e745f6e6f6e6365df0511436f6e7472616374734170695f63616c6ce00518436f6e7472616374734170695f6765745f73746f72616765e1051c436f6e7472616374734170695f72656e745f70726f6a656374696f6ee205205472616e73616374696f6e5061796d656e744170695f71756572795f696e666fe3052153657373696f6e4b6579735f67656e65726174655f73657373696f6e5f6b657973e4051f53657373696f6e4b6579735f6465636f64655f73657373696f6e5f6b657973e5052b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a6830313736373263396538616631356164e605706672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a6830653132393735616562386233613132e705706672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a6866626432336665616564303431636330e80584016672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654c696e6b65644d61703c4b2c563e20666f7220473e3a3a72656d6f76653a3a6830643063663665343463396331323934e90584016672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654c696e6b65644d61703c4b2c563e20666f7220473e3a3a72656d6f76653a3a6862653765396437613938373463303765ea05437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6836343331333363393866626466616133eb05746672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a6765743a3a6862633031353834653137653335363231ec05776672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a6837306265643137393435353365346632ed05776672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a72656d6f76653a3a6837393330383366626435303234323336ee054370616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a636c6561725f6572615f696e666f726d6174696f6e3a3a6832373165376534656134623334663161ef054270616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a736c61736861626c655f62616c616e63655f6f663a3a6864383730643031366234303234623564f005706672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a6830333264616666373033653431373966f105706672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a6837663966356432653339313661396431f205706672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a6831653739663162303265643232346131f3054a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6830393537366430316537343936653564f4053c70616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6839376664303633306330613561353961f5053c70616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a656e737572655f6e65775f6572613a3a6862663338663335383132373464616163f6053e70616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6863616232343063353334633838333334f7056d3c70616c6c65745f7374616b696e673a3a5f5f476574427974655374727563745370616e536c6173683c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6861653065386638373765396166653766f805713c70616c6c65745f7374616b696e673a3a5f5f47657442797465537472756374536c617368696e675370616e733c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6835373862663431393538656134313666f9053c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6837333162653966323536663166393831fa05723c70616c6c65745f7374616b696e673a3a5f5f4765744279746553747275637445726173546f74616c5374616b653c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6838363065346631663034333330353966fb05743c70616c6c65745f7374616b696e673a3a5f5f4765744279746553747275637445726173526577617264506f696e74733c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6834376337396338306136616332323830fc05763c70616c6c65745f7374616b696e673a3a5f5f476574427974655374727563744572617356616c696461746f7250726566733c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6863666561396562663164313263613234fd05763c70616c6c65745f7374616b696e673a3a5f5f47657442797465537472756374457261735374616b657273436c69707065643c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6834313038373633376436333539353365fe05793c70616c6c65745f7374616b696e673a3a5f5f476574427974655374727563744d696e696d756d56616c696461746f72436f756e743c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6865653061666161633364656636643161ff05703c70616c6c65745f7374616b696e673a3a5f5f47657442797465537472756374486973746f727944657074683c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a683963323230623330353866306236326480064770616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a683933356163313261393466366635626581069b013c70616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a426f6e64696e674475726174696f6e44656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a686664663862663638346461313832353982069a013c70616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a53657373696f6e7350657245726144656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a686537376438613934366365353637333483063870616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a6b696c6c5f73746173683a3a68663134376436346362313737346337358406746672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a6765743a3a68656232383238353266663232626437358506746672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a6765743a3a686434336266393732383535313235333486063970616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a6d616b655f7061796f75743a3a683664383361333239383364303339653587065f3c70616c6c65745f7374616b696e673a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a686236346236623762623135383236643088063b70616c6c65745f626162653a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a683231646533646464303836356230396289066b3c70616c6c65745f626162653a3a5f5f4765744279746553747275637452616e646f6d6e6573733c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68643539376235396262336430303031618a064470616c6c65745f626162653a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a68396333396137353465333966376165628b069a013c70616c6c65745f626162653a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4578706563746564426c6f636b54696d6544656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68336165316533626238626536303232368c0696013c70616c6c65745f626162653a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a45706f63684475726174696f6e44656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68326166346134383338336436666435338d063c70616c6c65745f696e64696365733a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a68303738613638343039386132633938308e063e70616c6c65745f696e64696365733a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a68633936386334626136376566383963648f06303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68306462313537363964633162333434639006683c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e697445787072206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a683766326332376562356339363136653891066b3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a683964666665656538623835303261633092067d3c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a436f756e7465644c6973745772697465723c492c543e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a683238363963336233663636616637386693066f3c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a566172496e743332206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a683336333666363435323464643363623794066f3c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a566172496e743634206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a683931643330363634386361636464656195066c3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e697445787072206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a683761336665623262333963346339353196066f3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a68333730323366313566643065386539399706793c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a436f756e7465644c6973743c543e206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a683462303564393031366130333936643698066b3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6862663262343837383763343234623366990686017061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a3c696d706c207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a6520666f7220616c6c6f633a3a737472696e673a3a537472696e673e3a3a646573657269616c697a653a3a68366233313539396532313063633765659a06323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a68383164393037643233303337353334389b06783c7061726974795f7761736d3a3a656c656d656e74733a3a696d706f72745f656e7472793a3a526573697a61626c654c696d697473206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a68316238623235616632643561306463339c067c3c7061726974795f7761736d3a3a656c656d656e74733a3a696d706f72745f656e7472793a3a526573697a61626c654c696d697473206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a68306631333864613330396264356565659d06743c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a56617255696e743332206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a68623332323431376664353831393535639e06713c7061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a437573746f6d53656374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a68626137353136313761393562653237349f06713c7061726974795f7761736d3a3a656c656d656e74733a3a696e6465785f6d61703a3a496e6465784d61703c543e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6838616530376530333537376366623832a0064b3c616c6c6f633a3a7665633a3a496e746f497465723c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6835336665646534366339396461396333a1064b3c616c6c6f633a3a7665633a3a496e746f497465723c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6836316334323261373262393666373061a206463c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6863363736656361306662353932623131a306457061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a53656374696f6e5265616465723a3a6e65773a3a6864346431393633336631313935363965a4062d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a6837306231356566393130353565666630a50634636f72653a3a736c6963653a3a736f72743a3a627265616b5f7061747465726e733a3a6837653038393363343938343730373562a6062e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a6832303661383365613461653862316463a7063c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a6838303034393639663534353637316232a8063b636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a7b7b636c6f737572657d7d3a3a6866633630353832303238353365323161a906397761736d695f76616c69646174696f6e3a3a76616c69646174655f6d656d6f72795f747970653a3a6865656437623930326631383838326332aa06347761736d695f76616c69646174696f6e3a3a657870725f636f6e73745f747970653a3a6832653838346361613933363839613732ab06553c7061726974795f7761736d3a3a656c656d656e74733a3a74797065733a3a56616c75655479706520617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6836633862656664316131653936643761ac064a7761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a737465703a3a6833643563366363393965343162303734ad06473c7761736d695f76616c69646174696f6e3a3a4572726f7220617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6862343038313364306532343233643935ae06303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6861373137636136333337356237313230af06457061726974795f7761736d3a3a656c656d656e74733a3a7365676d656e743a3a446174615365676d656e743a3a76616c75653a3a6837303734316631313732623664306539b006513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a6834323430623238313131303831303562b106553c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6836663133636237663332313730343139b206303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6832386465373265383333393463313632b306553c7061726974795f7761736d3a3a656c656d656e74733a3a74797065733a3a426c6f636b5479706520617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6865376235633238643737326432316461b406303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6832376436653531613936663361373939b506303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6861663033323733366163393232366563b606303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6862366466313239313134323638363564b706303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6835613131623766643365356531626535b806303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6862356135363864386435636465393938b90633636f72653a3a6f7074696f6e3a3a4f7074696f6e3c26543e3a3a636c6f6e65643a3a6863653437396230643866326537396430ba06483c616c6c6f633a3a626f7865643a3a426f783c5b545d3e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6836373334656639343534303938643534bb06453c636f72653a3a6f7074696f6e3a3a4f7074696f6e3c543e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6838643430616163386465346337333231bc06613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6837363264613865633632636634396237bd06593c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6831663838643533646661373565306531be06533c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a737065635f657874656e643a3a6831343363643033623936373635396637bf06303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6836393630636132353635643063346434c00641707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a636f6d707574653a3a6834353063306263363138336434633535c1065a3c707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a4672616d6520617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6832363061336434303134326434333236c20646707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a537461636b3a3a6672616d653a3a6837653461643836656461383931373664c3064b707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a537461636b3a3a706f705f76616c7565733a3a6834326363656238383163373963613966c4063f707761736d5f7574696c733a3a737461636b5f6865696768743a3a7265736f6c76655f66756e635f747970653a3a6836353737303063373533333862326265c5062e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a6830306533646436316634396566376632c6063c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a6866333135633931666164376262663739c706303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6838353436633439376236623032643462c80640707761736d5f7574696c733a3a737461636b5f6865696768743a3a636f6d707574655f737461636b5f636f73743a3a6833303861666362393934343234306632c906323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6864623065393638333831373838343031ca063a73705f61726974686d657469633a3a62696775696e743a3a42696755696e743a3a6c73747269703a3a6863623664303365333064396432643464cb063773705f61726974686d657469633a3a62696775696e743a3a42696755696e743a3a6164643a3a6830373963386164613333633838613732cc063773705f61726974686d657469633a3a62696775696e743a3a42696755696e743a3a6d756c3a3a6836656162346130363334383336316265cd064473705f61726974686d657469633a3a62696775696e743a3a42696755696e743a3a6469763a3a7b7b636c6f737572657d7d3a3a6863353835623639343338346161386430ce064b3c73705f61726974686d657469633a3a62696775696e743a3a42696755696e7420617320636f72653a3a636d703a3a4f72643e3a3a636d703a3a6862343363313732333832366430336337cf06443c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6833333533343866363161643932636139d006513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a6861316533393533646463643739643539d1063d73705f61726974686d657469633a3a68656c706572735f3132386269743a3a746f5f6269675f75696e743a3a6862636462613735396230373335663539d206413c73705f696e686572656e74733a3a4572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6862313731333133313063636331623433d306323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6831303464643534316437356430326234d4064273705f696f3a3a6c6f6767696e673a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a6c6f673a3a6865356430363361643834626138653534d506573c73705f72756e74696d653a3a72756e74696d655f737472696e673a3a52756e74696d65537472696e6720617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6839313334336531613631353464613961d606473c73705f72756e74696d653a3a44697370617463684572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6834376166343262636666646462633835d706347761736d695f76616c69646174696f6e3a3a66756e633a3a706f705f76616c75653a3a6836303837393039376166613930353730d80637616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6862353162653534303338653337386263d9063b636f72653a3a736c6963653a3a3c696d706c205b545d3e3a3a636f70795f66726f6d5f736c6963653a3a6835363036313665666265393566353261da06347761736d695f76616c69646174696f6e3a3a66756e633a3a706f705f6c6162656c3a3a6864323165346265393364353964306466db06347761736d695f76616c69646174696f6e3a3a66756e633a3a7465655f76616c75653a3a6835383866623135353464623734363834dc06407761736d695f76616c69646174696f6e3a3a7574696c3a3a4c6f63616c733a3a747970655f6f665f6c6f63616c3a3a6866623763313263363733356663316532dd06543c7761736d695f76616c69646174696f6e3a3a66756e633a3a537461636b56616c75655479706520617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6834393861636561383235383936633437de06537761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f6c6f61643a3a6865623166653561353537616566316637df06547761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f73746f72653a3a6866343130303539353132313935323733e006547761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f72656c6f703a3a6835303633393733663730373930356533e106547761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f62696e6f703a3a6834356362613431303962333266363736e2062b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a6835323133323761366331623330333634e306303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6837313764633066383539633630303834e406303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6862306135333064326237356661633439e506453c616c6c6f633a3a737472696e673a3a537472696e6720617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6861646530363532663932613936653433e6064c3c7761736d695f76616c69646174696f6e3a3a737461636b3a3a4572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6832333432363936303939633862393637e706066d656d736574e806066d656d637079e906076d656d6d6f7665ea060462636d70eb06095f5f6173686c746933ec06095f5f6c736872746933ed06085f5f6d756c746933ee06095f5f75646976746933ef06095f5f756d6f64746933f0060c5f5f756469766d6f6474693400550970726f64756365727302086c616e6775616765010452757374000c70726f6365737365642d62790105727573746325312e34332e302d6e696768746c79202837356366343161666220323032302d30332d303429", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9bed2903186223711a06d85784e730efd547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65": "0x00000000030000c16ff28623000000000000000000000000000000000000000000000000000000c16ff286230000000000000000000000c16ff28623000000000000000000", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195082c7c7fe191a6e68696d6f6e80482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a": "0x547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65", + "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e169037441588f5c9a91b3f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663": "0x00", + "0x5f3e4907f716ac89b6347d15ececedca8bde0a0ea8864605e3b68ed9cb2da01bb4def25cfda6ef3a000000007441588f5c9a91b3f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663": "0x0ff6ffc06ff286230ff6ffc06ff2862300", + "0x5f3e4907f716ac89b6347d15ececedca8bde0a0ea8864605e3b68ed9cb2da01bb4def25cfda6ef3a0000000054352b71083d945a9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12": "0x0ff6ffc06ff286230ff6ffc06ff2862300", + "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe707441588f5c9a91b3f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663": "0x66bc1e5d275da50b72b15de072a2468a5ad414919ca9054d2695767cf650012f", "0x492a52699edf49c972c21db794cfcf57ba7fb8745735dc3be2a2c61a72c39e78": "0x00", - "0x5f3e4907f716ac89b6347d15ececedca42982b9d6c7acc99faa9094c912372c2b4def25cfda6ef3a0000000054352b71083d945a9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12": "0x0ff6ffc06ff286230ff6ffc06ff2862300", - "0x5f3e4907f716ac89b6347d15ececedcaf7dad0317324aecae8744b87fc95f2f3": "0x00", - "0x5f3e4907f716ac89b6347d15ececedca28dccb559b95c40168a1b2696581b5a7": "0x00000000000000000000000000000000", - "0x11f3ba2e1cdd6d62f2ff9b5589e7ff81ba7fb8745735dc3be2a2c61a72c39e78": "0x049ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809", - "0x34b9dcaacddd89d5a94929dccb7131534a9d2f70e9ee596bc867d128cd9ec759": "0x00ca9a3b000000000000000000000000", + "0x4342193e496fab7ec59d615ed0dc5530d2d505c0e6f76fd7ce0796ebe187401c": "0x0000000020a107000000000020a107000000000020a107000000000020a107000000000020a107000000000020a107000000000020a1070000000000e0f7050400000000e024370500000000e0f705040000000020a107000000000020a107000000000080f0fa020000000000e1f50500000000040000000000010010000000004000000020000000", "0x5f3e4907f716ac89b6347d15ececedca5579297f4dfb9609e7e4c2ebab9ce40a": "0x109c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d1268655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", - "0x8985776095addd4789fccbce8ca77b23ba7fb8745735dc3be2a2c61a72c39e78": "0x049ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809", - "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc6711590f60a214f6f06502eb29dd14f55aa04e72e2fa12c098ba4fa5a00c57fa9": "0x047374616b696e67200000c16ff2862300000000000000000002", - "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9895bb514540b8e8932c5863ecb0da1513485b5c2e55041c1ac3bc875e4338763": "0x00000000000000a0dec5adc9353600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b6579731143fa96e07eb73af3db3a1b057d18899f864e6fc5d2f905f9296ca641565564": "0x9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b65797320733fcc641421fafd1fd2f3b4d938bf25bc3fe2f74d34c47239b2c2217446bb": "0x9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b6579732c1312343dce08149336968907c27cc602536aaf7a2b105d6fa07058a3803d31": "0xf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b657973d1ae046d940202772415992434f839d8c546542e3055143c430f7eec87f7cb69": "0xf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", - "0x5f3e4907f716ac89b6347d15ececedca308ce9615de0775a82f8a94dc3d285a1": "0x01", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b657973dc4036f96ca26a30da6d8637ca1431896c1069bf172c419e98dc08109e7b23b5": "0x68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78", - "0x426e15054d267946093858132eb537f195999521c6c89cd80b677e53ce20f98c": "0x9ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809", - "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe70711590f60a214f6f06502eb29dd14f55aa04e72e2fa12c098ba4fa5a00c57fa9": "0xc8dc79e36b29395413399edaec3e20fcca7205fb19776ed8ddb25d6f427ec40e", - "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade9894f72a73893fbd00b11fcce65a014cc5b9ff5066ec15aa6be068b4cabfe67fdb": "0x00", + "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e1690379091c57296b2634547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65": "0x00", + "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade9854352b71083d945a9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12": "0x00", + "0x5f3e4907f716ac89b6347d15ececedcaad811cd65a470ddc5f1d628ff0550982b4def25cfda6ef3a00000000": "0x00000000", "0x5f3e4907f716ac89b6347d15ececedcac29a0310e1bb45d20cace77ccb62c97d": "0x00e1f505", - "0xf2794c22e353e9a839f12faab03a911b7f17cdfbfa73331856cca0acddd7842e": "0x00000000", - "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc67f325c981c2b001f5fe8c51cc7b89e50ebb1f60feb7ab3fa3bc79d6ab71d45cb": "0x047374616b696e67200000c16ff2862300000000000000000002", - "0x26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850": "0x07000000", - "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9e54094c2d5af8ae10b91e1288f4f59f2946d7738f2c509b7effd909e5e9ba0ad": "0x00000000030000c16ff28623000000000000000000000000000000000000000000000000000000c16ff286230000000000000000000000c16ff28623000000000000000000", - "0x5c0d1176a568c1f92944340dbfed9e9c530ebca703c85910e7164cb7d1c9e47b": "0x9ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809", - "0x5f3e4907f716ac89b6347d15ececedca682db92dde20a10d96d00ff0e9e221c0b4def25cfda6ef3a000000007441588f5c9a91b3f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663": "0x00", - "0x5f3e4907f716ac89b6347d15ececedcaea07de2b8f010516dca3f7ef52f7ac5a": "0x040000000000000000", - "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9711590f60a214f6f06502eb29dd14f55aa04e72e2fa12c098ba4fa5a00c57fa9": "0x00000000030000c16ff28623000000000000000000000000000000000000000000000000000000c16ff286230000000000000000000000c16ff28623000000000000000000", - "0x5f3e4907f716ac89b6347d15ececedca138e71612491192d68deab7e6f563fe1": "0x08000000", "0xc2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80": "0x00401eae822458363600000000000000", - "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e169037f325c981c2b001f5fe8c51cc7b89e50ebb1f60feb7ab3fa3bc79d6ab71d45cb": "0x000168655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde7800", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b65797399a2fc4b1339e668345bac7e1aadd1a834b90939a4ea40b64f30433a1d475817": "0x9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b657973be035f25cd43adc80f1dcf505f5ffd158d1592ab3719f354a256a4c3b7571934": "0x547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65", - "0xf2794c22e353e9a839f12faab03a911bbdcb0c5143a8617ed38ae3810dd45bc6": "0x00000000", - "0x1cb6f36e027abb2091cfb5110ab5087f5e0621c4869aa60c02be9adcc98a0d1d": "0x1000299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f43780100000000000000482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a0100000000000000482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e01000000000000006e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f91060100000000000000", - "0x5f3e4907f716ac89b6347d15ececedca487df464e44a534ba6b0cbb32407b587": "0x0000000000", - "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc694f72a73893fbd00b11fcce65a014cc5b9ff5066ec15aa6be068b4cabfe67fdb": "0x047374616b696e67200000c16ff2862300000000000000000002", - "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc6e54094c2d5af8ae10b91e1288f4f59f2946d7738f2c509b7effd909e5e9ba0ad": "0x047374616b696e67200000c16ff2862300000000000000000002", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b65797301dd273832961ca94116fd224019ea1370c0e3d27bebb1041b35651146d17832": "0x68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b65797397dddc7aba561f16ac00da4bae75ab812aa7b81418bebdab74425f0d6aa31cee": "0x547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65", - "0xf2794c22e353e9a839f12faab03a911be2f6cb0456905c189bcb0458f9440f13": "0x00000000", - "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb39fe6329cc0b39e09343a73657373696f6e3a6b6579737f325c981c2b001f5fe8c51cc7b89e50ebb1f60feb7ab3fa3bc79d6ab71d45cb": "0x9becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe96993326e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f91066e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f91066e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106", - "0x2371e21684d2fae99bcb4d579242f74a8a2d09463effcc78a22d75b9cb87dffc": "0x0000000000000000", - "0x5f3e4907f716ac89b6347d15ececedca8bde0a0ea8864605e3b68ed9cb2da01bb4def25cfda6ef3a0000000054352b71083d945a9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12": "0x0ff6ffc06ff286230ff6ffc06ff2862300", - "0x5f3e4907f716ac89b6347d15ececedca8bde0a0ea8864605e3b68ed9cb2da01bb4def25cfda6ef3a000000007441588f5c9a91b3f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663": "0x0ff6ffc06ff286230ff6ffc06ff2862300", - "0x5f3e4907f716ac89b6347d15ececedcaa141c4fe67c2d11f4a10c6aca7a79a0411da6d1f761ddf9bdb4c9d6e5303ebd41f61858d0a5647a1a7bfe089bf921be9": "0xd8ff03bfc91b8e000000000000000000", - "0x2099d7f109d6e535fb000bba623fd4409f99a2ce711f3a31b2fc05604c93f179": "0x1000299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e6e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b657973890f14b1fcdd7ae841d324d5212f9d95f6c10c64f34dcb0b5f8b8687e6be854e": "0xf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", - "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc42e1b161d81ab54d65f3f57de68292fa3b62e6a3fa2a951dee23c0f8766303861": "0x9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d120f0000c16ff286230f0000c16ff286230000", - "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e1690394f72a73893fbd00b11fcce65a014cc5b9ff5066ec15aa6be068b4cabfe67fdb": "0x000001547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b6579739b9b11e996dcc26adf561753356c27f768521a8eced25b7311744e61cb1ebfbc": "0x68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78", - "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe7094f72a73893fbd00b11fcce65a014cc5b9ff5066ec15aa6be068b4cabfe67fdb": "0x66bc1e5d275da50b72b15de072a2468a5ad414919ca9054d2695767cf650012f", + "0x11f3ba2e1cdd6d62f2ff9b5589e7ff81ba7fb8745735dc3be2a2c61a72c39e78": "0x049ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809", + "0x5f3e4907f716ac89b6347d15ececedca0b6a45321efae92aea15e0740ec7afe7": "0x00000000", "0x5f3e4907f716ac89b6347d15ececedcaac0a2cbf8e355f5ea6cb2de8727bfb0c": "0x54000000", - "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb39fe6329cc0b39e09343a73657373696f6e3a6b657973e54094c2d5af8ae10b91e1288f4f59f2946d7738f2c509b7effd909e5e9ba0ad": "0x5633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a", - "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da96b1ab1274bcbe3a4176e17eb2917654904f19b3261911ec3f7a30a473a04dcc8": "0x000000000000407a10f35a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "0x5f3e4907f716ac89b6347d15ececedca682db92dde20a10d96d00ff0e9e221c0b4def25cfda6ef3a0000000079091c57296b2634547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65": "0x00", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b65797340944475c781bbdc9726766a78b1964888e039600b1c865c62586ab8f98c171e": "0x547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65", - "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb39fe6329cc0b39e09343a73657373696f6e3a6b657973711590f60a214f6f06502eb29dd14f55aa04e72e2fa12c098ba4fa5a00c57fa9": "0x7932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e", + "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb379091c57296b2634547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65": "0x5633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a", + "0x3a636f6465": "0x0061736d01000000018e033760037f7f7f017f60027f7f017f60027f7f0060017f0060037f7f7f0060057f7f7f7f7f0060047f7f7f7f0060017f017e60037f7e7e0060017e017f60027e7e0060017e017e60017e006000006000017f60027f7e017e60047f7e7e7e017f60027e7e017e60037e7e7e0060037f7e7f017f60047f7e7e7f017f60067f7e7e7f7f7f017f60047f7f7f7f017f6000017e60037e7e7f017e60017f017f60027f7e017f60027f7f017e60037f7f7e017e60037e7f7f017f60067f7f7f7f7f7f017f60077f7f7f7f7f7f7f017f60057f7f7f7f7f017f60027f7e0060047f7f7e7e0060057f7e7e7f7f0060057f7f7f7e7e0060067f7f7f7f7f7f0060057f7f7e7e7f0060047e7e7e7e017f60067f7f7f7e7e7f0060077f7e7e7e7e7e7e0060067f7f7e7f7e7e0060077f7f7f7e7e7f7f0060077f7f7f7f7e7e7f0060087e7e7e7e7e7e7e7e017f60047f7f7f7f017e60067f7f7f7f7e7e0060057f7e7e7e7e0060087f7f7f7f7f7e7e7f0060077f7f7e7e7f7f7f0060027e7f0060037f7e7f0060067f7e7e7e7e7f0060047f7e7e7f0002cd103403656e76066d656d6f727902001403656e76196578745f6c6f6767696e675f6c6f675f76657273696f6e5f31000803656e761e6578745f68617368696e675f74776f785f3132385f76657273696f6e5f31000903656e76196578745f73746f726167655f7365745f76657273696f6e5f31000a03656e761d6578745f68617368696e675f74776f785f36345f76657273696f6e5f31000903656e76206578745f68617368696e675f626c616b65325f3132385f76657273696f6e5f31000903656e76196578745f73746f726167655f6765745f76657273696f6e5f31000b03656e761d6578745f6d6973635f7072696e745f757466385f76657273696f6e5f31000c03656e761b6578745f73746f726167655f636c6561725f76657273696f6e5f31000c03656e76226578745f73746f726167655f636c6561725f7072656669785f76657273696f6e5f31000c03656e76206578745f68617368696e675f626c616b65325f3235365f76657273696f6e5f31000903656e761c6578745f6d6973635f7072696e745f6865785f76657273696f6e5f31000c03656e76276578745f63727970746f5f73746172745f62617463685f7665726966795f76657273696f6e5f31000d03656e76286578745f63727970746f5f66696e6973685f62617463685f7665726966795f76657273696f6e5f31000e03656e76236578745f6f6666636861696e5f69735f76616c696461746f725f76657273696f6e5f31000e03656e76286578745f6f6666636861696e5f6c6f63616c5f73746f726167655f6765745f76657273696f6e5f31000f03656e76346578745f6f6666636861696e5f6c6f63616c5f73746f726167655f636f6d706172655f616e645f7365745f76657273696f6e5f31001003656e76276578745f64656661756c745f6368696c645f73746f726167655f6765745f76657273696f6e5f31001103656e76306578745f64656661756c745f6368696c645f73746f726167655f73746f726167655f6b696c6c5f76657273696f6e5f31000c03656e76276578745f64656661756c745f6368696c645f73746f726167655f7365745f76657273696f6e5f31001203656e76296578745f64656661756c745f6368696c645f73746f726167655f636c6561725f76657273696f6e5f31000a03656e76226578745f6f6666636861696e5f72616e646f6d5f736565645f76657273696f6e5f31000e03656e76236578745f63727970746f5f737232353531395f7665726966795f76657273696f6e5f32001303656e76286578745f6f6666636861696e5f6c6f63616c5f73746f726167655f7365745f76657273696f6e5f31000803656e76206578745f73616e64626f785f6d656d6f72795f6e65775f76657273696f6e5f31000103656e76256578745f73616e64626f785f6d656d6f72795f74656172646f776e5f76657273696f6e5f31000303656e76216578745f73616e64626f785f696e7374616e74696174655f76657273696f6e5f31001403656e761c6578745f73616e64626f785f696e766f6b655f76657273696f6e5f31001503656e76276578745f73616e64626f785f696e7374616e63655f74656172646f776e5f76657273696f6e5f31000303656e76206578745f73616e64626f785f6d656d6f72795f6765745f76657273696f6e5f31001603656e76206578745f73616e64626f785f6d656d6f72795f7365745f76657273696f6e5f31001603656e761e6578745f68617368696e675f736861325f3235365f76657273696f6e5f31000903656e76206578745f68617368696e675f6b656363616b5f3235365f76657273696f6e5f31000903656e76236578745f63727970746f5f656432353531395f7665726966795f76657273696f6e5f31001303656e76286578745f64656661756c745f6368696c645f73746f726167655f726f6f745f76657273696f6e5f31000b03656e761c6578745f73746f726167655f617070656e645f76657273696f6e5f31000a03656e761a6578745f73746f726167655f726f6f745f76657273696f6e5f31001703656e76226578745f73746f726167655f6368616e6765735f726f6f745f76657273696f6e5f31000b03656e76226578745f6d6973635f72756e74696d655f76657273696f6e5f76657273696f6e5f31000b03656e761c6578745f6d6973635f7072696e745f6e756d5f76657273696f6e5f31000c03656e761e6578745f73746f726167655f6e6578745f6b65795f76657273696f6e5f31000b03656e762a6578745f747269655f626c616b65325f3235365f6f7264657265645f726f6f745f76657273696f6e5f31000903656e76246578745f6f6666636861696e5f6e6574776f726b5f73746174655f76657273696f6e5f31001703656e76296578745f6f6666636861696e5f7375626d69745f7472616e73616374696f6e5f76657273696f6e5f31000b03656e761a6578745f73746f726167655f726561645f76657273696f6e5f31001803656e761e6578745f616c6c6f6361746f725f6d616c6c6f635f76657273696f6e5f31001903656e761c6578745f616c6c6f6361746f725f667265655f76657273696f6e5f31000303656e76256578745f63727970746f5f656432353531395f67656e65726174655f76657273696f6e5f31001a03656e76376578745f63727970746f5f736563703235366b315f65636473615f7265636f7665725f636f6d707265737365645f76657273696f6e5f31001b03656e76256578745f63727970746f5f737232353531395f67656e65726174655f76657273696f6e5f31001a03656e76286578745f63727970746f5f737232353531395f7075626c69635f6b6579735f76657273696f6e5f31000703656e76216578745f63727970746f5f737232353531395f7369676e5f76657273696f6e5f31001c03f407f20719190303000019191b0d0d0d04040204000d0d0500010102010202020204011d0303071e1604040005010101191f01010104010100062001010001010000010003040102020402040200010104010201010203040404040404040404040404040402040404040404040404040404040404040404040402040302020401020304040202020202020202040202020403210202020102070205220502040206040404040404040302040202042308020202030d1903020202040202020202020102030202020202040306022002020401192402040402020425020203020426020220022722010403060604020303030d020202020506060402030102030106020404040402020402030302190202020402040402020202040204040402020401040404020204020402020202040404020404010228020319220204020228060303020303030202030202020206250103020604020204030419190402020303290303040404040402020202020202020202020202020d02020204040402020403031b021b0203020202060d0303020202011b021b031b02021b021b02020202021b041b041b020204042a04021b020502010201020d1b021b1b1b1b021b2b022c1b02041b05051b1b04041b02020d020203040504010406020203020302020405040104020202030302292d01052700030303030202020202020202022206020402040402020303010403050101010d020302020402040c02020407021d21030303030303030302040202010102030001012e02020602020602020402020202060402040202030303020303030202020203020202020302020204020602020202022f020202063002250d06060606060606060606060606060606060606060606060606060606060606060606163132060303020102020202020403030303030303030303030303030303030303030303030303030303030302020202020202020202020202020216040202020203040202020d0406040404040406020404040202020202040303030202020302020202020402030302040306030206040122040402030204070202020303020303030202020203030302020202020200020202020202032602020303023002330504020204030302020203030203060202010206020204040203030303020201020604000406020201030302020203030303030203020202040302020602020206020304040504340202020102040201050202030303040202060102040101050202040403030303020202010402010101010101010101040201020104010401040403010204010304041901010201010501010604060401050504040204060301010130353035300d300b1111111108300303303030111108303035303000000000363636360407017001a902a9020619037f01418080c0000b7f00419cb5cc000b7f00419cb5cc000b07e8051a195f5f696e6469726563745f66756e6374696f6e5f7461626c65010009686173685f74657374003b0c436f72655f76657273696f6e00b30312436f72655f657865637574655f626c6f636b00b50315436f72655f696e697469616c697a655f626c6f636b00c303114d657461646174615f6d6574616461746100c5031c426c6f636b4275696c6465725f6170706c795f65787472696e73696300c7031b426c6f636b4275696c6465725f66696e616c697a655f626c6f636b00ca0320426c6f636b4275696c6465725f696e686572656e745f65787472696e7369637300cc031c426c6f636b4275696c6465725f636865636b5f696e686572656e747300d20318426c6f636b4275696c6465725f72616e646f6d5f7365656400d4032b5461676765645472616e73616374696f6e51756575655f76616c69646174655f7472616e73616374696f6e00d603214f6666636861696e576f726b65724170695f6f6666636861696e5f776f726b657200de031e4772616e6470614170695f6772616e6470615f617574686f72697469657300e70315426162654170695f636f6e66696775726174696f6e00e9031b426162654170695f63757272656e745f65706f63685f737461727400ea0321417574686f72697479446973636f766572794170695f617574686f72697469657300eb031d4163636f756e744e6f6e63654170695f6163636f756e745f6e6f6e636500ec0311436f6e7472616374734170695f63616c6c00ee0318436f6e7472616374734170695f6765745f73746f7261676500f2031c436f6e7472616374734170695f72656e745f70726f6a656374696f6e00f503205472616e73616374696f6e5061796d656e744170695f71756572795f696e666f00f8032153657373696f6e4b6579735f67656e65726174655f73657373696f6e5f6b65797300f9031f53657373696f6e4b6579735f6465636f64655f73657373696f6e5f6b65797300fc030a5f5f646174615f656e6403010b5f5f686561705f62617365030209be04010041010ba8024b51655cee075d5e8201c60171dd04c203e203e403bd04be049c059d059e059f05a005a105a205a305a405a505a605a705a805a905aa05ab05ac05ad05ae05af05b005b105b205b305b405b505b605b705b805b905ba05bb05bc05bd05e304dc04c505aa07b907bc07bd07ae0766e507f607d2078008dc07de07544748497555676a6b6c6d6e7c7d7e80018101850183018401f001eb06ef018105e8019a06ee01ed01ec01eb01e901e701f501f40162f302f702a904ee05fd02fc02fb02fa0263e6068c048f048e04a804a704a604a504b804f007bf04d804eb07e004e104e204fe04ff048605fa04850584058305e706f10799069806cc059d06a90693039203cd058907b2038b048d04d604d504d704fb06fa06880799049804ce05f202f102cf05f4028803d005d105e601e301d205f3019f02ea06e906d305f906fd04fc04d4058205c30591078f07d505a1079007f602f502d605f9029003a606a506d705d805d905da05e506e406db05f806c606c506dc05c706d906dd05de05df05e005e105bc06bb06e205d506d404d204e305df04fb04e4059307a204a104e505a404b704bf06be06e605c006da068e078d07e7059807f804f704e805f904c2058705e905f005ef05ed05ec05eb05ea05f205f105f505f405f605d4079c069b06a206a106a0069f069e06bd06c406c306c206c106cc06cb06ca06c906c80684048504870486048304f003e206e106e306e806ec06910492049404930490049504ed07ce07d107cf07d307d507d007e207d807fe078108ff070a9ca066f2070600200010340b06002000102c0b0600200010360b06002000102d0b0a0020002001200210380b2801017f02402002102c2203450d002003200020022001200120024b1b109d081a2000102d0b20030b06002000103a0b1c01017f02402000102c2201450d00200141002000109f081a0b20010bff0202017f037e230041206b220224002001ad42adfed5e4d485fda8d8007e42b9e0007c210302400240024002400240200141084b0d00200141014b0d0120010d02420021040c030b0240200141104b0d00200241106a2000290000200385420042adfed5e4d485fda8d8004200108408200241186a29030020022903107c200120006a41786a2900008521040c040b200120006a41786a2900002105200321040340200029000020048542adfed5e4d485fda8d8007e42178942adfed5e4d485fda8d8007e2003852103200041086a2100200442cf829ebbefefde82147c2104200141786a220141084b0d000b200320058521040c030b0240200141034b0d00200120006a417e6a33000042108620003300008420038521040c030b200120006a417c6a35000042208620003500008420038521040c020b200031000021040b200420038521040b20022004420042adfed5e4d485fda8d8004200108408200241086a290300210420022903002103200241206a2400200420037c42c300850b0500103d000b2400410041d09bcc00ad4280808080f0008441d79bcc00ad4280808080a00484100000000b1100418080c0004111419480c000103f000b4701017f230041206b22032400200341146a4100360200200341b0b4cc00360210200342013702042003200136021c200320003602182003200341186a36020020032002104c000bdd0101047f0240024002400240200041046a2802002203200041086a28020022046b200220016b2202490d00200028020021050c010b200420026a22052004490d01200341017422062005200620054b1b22064100480d010240024002402003450d00200028020022050d010b024020060d00410121050c020b2006103322050d010c040b024020032006460d00200520032006103721050b2005450d03200041086a28020021040b20002005360200200041046a20063602000b200520046a20012002109d081a200041086a200420026a3602000f0b103e000b103c000b8b0301067f230041306b2202240020012802002103024002402001280204220441037422050d00410021060c010b200341046a2107410021060340200728020020066a2106200741086a2107200541786a22050d000b0b024002400240024002400240200141146a2802000d00200621070c010b024020040d004100410041bc80c0001042000b024002402006410f4b0d00200341046a280200450d010b200620066a220720064f0d010b4100210741012105200241086a21060c010b2007417f4c0d01200241086a2106024020070d0041002107410121050c010b200710332205450d020b20024100360210200220053602082002200736020c2002200241086a360214200241186a41106a200141106a290200370300200241186a41086a200141086a29020037030020022001290200370318200241146a41cc80c000200241186a10430d0220002006290200370200200041086a200641086a280200360200200241306a24000f0b1044000b1045000b41e480c0004133200241186a419881c00041a881c0001046000b6c01017f230041306b2203240020032001360204200320003602002003411c6a41023602002003412c6a41013602002003420237020c200341c886c000360208200341013602242003200341206a360218200320033602282003200341046a360220200341086a2002104c000bba06010a7f230041306b22032400200341246a2001360200200341033a002820034280808080800437030820032000360220410021042003410036021820034100360210024002400240024020022802082205450d0020022802002106200228020422072002410c6a2802002208200820074b1b2209450d01200241146a280200210a2002280210210b41012108200020062802002006280204200128020c1100000d03200541106a2102200641086a2100410121040240024003402003200241746a28020036020c20032002410c6a2d00003a00282003200241786a280200360208200241086a28020021084100210541002101024002400240200241046a2802000e03010002010b2008200a4f0d032008410374210c41002101200b200c6a220c2802044102470d01200c28020028020021080b410121010b2003200836021420032001360210200228020021080240024002402002417c6a2802000e03010002010b2008200a4f0d0420084103742101200b20016a22012802044102470d01200128020028020021080b410121050b2003200836021c200320053602180240200241706a2802002208200a4f0d00200b20084103746a2208280200200341086a20082802041101000d06200420094f0d05200041046a210120002802002105200241206a2102200041086a210041012108200441016a2104200328022020052001280200200328022428020c110000450d010c070b0b2008200a41a08bc0001042000b2008200a41908bc0001042000b2008200a41908bc0001042000b2002280200210620022802042207200241146a2802002208200820074b1b220a450d002002280210210241012108200020062802002006280204200128020c1100000d02200641086a21004101210403402002280200200341086a200241046a2802001101000d022004200a4f0d01200041046a210120002802002105200241086a2102200041086a210041012108200441016a2104200328022020052001280200200328022428020c110000450d000c030b0b0240200720044d0d00410121082003280220200620044103746a22022802002002280204200328022428020c1100000d020b410021080c010b410121080b200341306a240020080b0500103e000b0500103c000b7e01017f230041c0006b220524002005200136020c2005200036020820052003360214200520023602102005412c6a41023602002005413c6a41033602002005420237021c200541cc92c800360218200541043602342005200541306a3602282005200541106a3602382005200541086a360230200541186a2004104c000b120020002802002001200120026a104041000bcb0301047f230041106b22022400200028020021000240024002400240024002402001418001490d002002410036020c2001418010490d012002410c6a210302402001418080044f0d0020022001413f71418001723a000e20022001410676413f71418001723a000d20022001410c76410f7141e001723a000c410321010c050b20022001413f71418001723a000f2002200141127641f001723a000c20022001410676413f71418001723a000e20022001410c76413f71418001723a000d410421010c040b0240024020002802082203200041046a280200460d00200028020021040c010b200341016a22042003490d02200341017422052004200520044b1b22054100480d020240024002402003450d00200028020022040d010b024020050d00410121040c020b2005103322040d010c050b024020032005460d00200420032005103721040b2004450d04200028020821030b20002004360200200041046a20053602000b200420036a20013a00002000200028020841016a3602080c040b20022001413f71418001723a000d20022001410676411f7141c001723a000c2002410c6a2103410221010c020b103e000b103c000b20002003200320016a10400b200241106a240041000b6301017f230041206b2202240020022000280200360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a41cc80c000200241086a10432101200241206a240020010b6f01017f230041306b2202240020022001360204200220003602002002411c6a41023602002002412c6a41013602002002420337020c2002419482c000360208200241013602242002200241206a3602182002200241046a36022820022002360220200241086a41ac82c000104c000b0d0020003502004101200110520b3401017f230041106b220224002002200136020c20022000360208200241d886c000360204200241b0b4cc0036020020021053000b6f01017f230041306b2202240020022001360204200220003602002002411c6a41023602002002412c6a41013602002002420337020c200241fc82c000360208200241013602242002200241206a3602182002200241046a36022820022002360220200241086a419483c000104c000b6f01017f230041306b2202240020022001360204200220003602002002411c6a41023602002002412c6a41013602002002420337020c200241d083c000360208200241013602242002200241206a3602182002200241046a36022820022002360220200241086a41e883c000104c000b6f01017f230041306b2202240020022001360204200220003602002002411c6a41023602002002412c6a41013602002002420337020c2002418c84c000360208200241013602242002200241206a3602182002200241046a36022820022002360220200241086a41a484c000104c000bc40101037f0240024002402002417f4c0d000240024020020d0041002103410121040c010b20022103200210332204450d020b0240024020032002490d00200321050c010b02400240200341017422052002200520024b1b22054100480d00024002402003450d0020040d010b2005103322040d030c060b20032005470d01200321050c020b103e000b20042003200510372204450d030b200420012002109d0821032000200236020820002005360204200020033602000f0b1044000b1045000b103c000b0d0020002802001a037f0c000b0bd40203027f017e037f230041306b22032400412721040240024020004290ce005a0d00200021050c010b412721040340200341096a20046a2206417c6a200020004290ce0080220542f0b17f7e7ca7220741ffff037141e4006e2208410174419a87c0006a2f00003b00002006417e6a2008419c7f6c20076a41ffff0371410174419a87c0006a2f00003b00002004417c6a2104200042ffc1d72f5621062005210020060d000b0b02402005a7220641e3004c0d00200341096a2004417e6a22046a2005a7220741ffff037141e4006e2206419c7f6c20076a41ffff0371410174419a87c0006a2f00003b00000b024002402006410a480d00200341096a2004417e6a22046a2006410174419a87c0006a2f00003b00000c010b200341096a2004417f6a22046a200641306a3a00000b2002200141b0b4cc004100200341096a20046a412720046b10562104200341306a240020040b6f01017f230041c0006b220124002001200036020c200141346a41013602002001420137022420014188b2cc003602202001410536023c2001200141386a36023020012001410c6a360238200141106a200141206a1041410141d09bcc0041072001280210200128021810ef0700000b02000b0d0042a98089cda5ebd0e9ae7f0b830601067f024002402001450d00412b418080c4002000280200220641017122011b2107200120056a21080c010b200541016a210820002802002106412d21070b0240024020064104710d00410021020c010b4100210902402003450d002003210a200221010340200920012d000041c00171418001466a2109200141016a2101200a417f6a220a0d000b0b200820036a20096b21080b410121010240024020002802084101460d00200020072002200310570d012000280218200420052000411c6a28020028020c11000021010c010b02402000410c6a280200220920084b0d00200020072002200310570d012000280218200420052000411c6a28020028020c1100000f0b0240024020064108710d0041002101200920086b22092108024002400240410120002d0020220a200a4103461b0e0402010001020b20094101762101200941016a41017621080c010b41002108200921010b200141016a210103402001417f6a2201450d0220002802182000280204200028021c280210110100450d000b41010f0b200028020421062000413036020420002d0020210b41012101200041013a0020200020072002200310570d0141002101200920086b220a2103024002400240410120002d0020220920094103461b0e0402010001020b200a4101762101200a41016a41017621030c010b41002103200a21010b200141016a2101024003402001417f6a2201450d0120002802182000280204200028021c280210110100450d000b41010f0b2000280204210a41012101200028021820042005200028021c28020c1100000d01200341016a2109200028021c210320002802182102024003402009417f6a2209450d01410121012002200a20032802101101000d030c000b0b2000200b3a00202000200636020441000f0b2000280204210a41012101200020072002200310570d00200028021820042005200028021c28020c1100000d00200841016a2109200028021c210320002802182100034002402009417f6a22090d0041000f0b410121012000200a2003280210110100450d000b0b20010b5401017f024002402001418080c400460d0041012104200028021820012000411c6a2802002802101101000d010b024020020d0041000f0b2000280218200220032000411c6a28020028020c11000021040b20040b6c01017f230041306b2203240020032001360204200320003602002003411c6a41023602002003412c6a41013602002003420237020c200341e488c000360208200341013602242003200341206a3602182003200341046a36022820032003360220200341086a2002104c000b6c01017f230041306b2203240020032001360204200320003602002003411c6a41023602002003412c6a41013602002003420237020c2003419c89c000360208200341013602242003200341206a3602182003200341046a36022820032003360220200341086a2002104c000b9307010c7f200041106a28020021030240024002400240200041086a28020022044101460d0020034101460d012000280218200120022000411c6a28020028020c11000021030c030b20034101470d010b0240024020020d00410021020c010b200120026a2105200041146a28020041016a21064100210720012103200121080340200341016a210902400240024020032c0000220a417f4a0d000240024020092005470d004100210b200521030c010b20032d0001413f71210b200341026a220921030b200a411f71210c0240200a41ff0171220a41df014b0d00200b200c41067472210a0c020b0240024020032005470d004100210d2005210e0c010b20032d0000413f71210d200341016a2209210e0b200d200b41067472210b0240200a41f0014f0d00200b200c410c7472210a0c020b02400240200e2005470d004100210a200921030c010b200e41016a2103200e2d0000413f71210a0b200b410674200c411274418080f0007172200a72220a418080c400470d020c040b200a41ff0171210a0b200921030b02402006417f6a2206450d00200720086b20036a21072003210820052003470d010c020b0b200a418080c400460d00024002402007450d0020072002460d0041002103200720024f0d01200120076a2c00004140480d010b200121030b2007200220031b21022003200120031b21010b20044101460d002000280218200120022000411c6a28020028020c1100000f0b4100210902402002450d002002210a200121030340200920032d000041c00171418001466a2109200341016a2103200a417f6a220a0d000b0b0240200220096b200028020c2206490d002000280218200120022000411c6a28020028020c1100000f0b410021074100210902402002450d00410021092002210a200121030340200920032d000041c00171418001466a2109200341016a2103200a417f6a220a0d000b0b200920026b20066a2209210a024002400240410020002d0020220320034103461b0e0402010001020b20094101762107200941016a410176210a0c010b4100210a200921070b200741016a2103024003402003417f6a2203450d0120002802182000280204200028021c280210110100450d000b41010f0b2000280204210941012103200028021820012002200028021c28020c1100000d00200a41016a2103200028021c210a20002802182100034002402003417f6a22030d0041000f0b20002009200a280210110100450d000b41010f0b20030bc80801067f230041f0006b220524002005200336020c20052002360208410121062001210702402001418102490d00410020016b2108418002210903400240200920014f0d00200020096a2c000041bf7f4c0d0041002106200921070c020b2009417f6a21074100210620094101460d01200820096a210a20072109200a4101470d000b0b200520073602142005200036021020054100410520061b36021c200541b0b4cc0041e089c00020061b3602180240024002400240200220014b22090d00200320014b0d00200220034b0d01024002402002450d0020012002460d00200120024d0d01200020026a2c00004140480d010b200321020b200520023602202002450d0220022001460d02200141016a210a03400240200220014f0d00200020026a2c000041404e0d040b2002417f6a210920024101460d04200a2002462107200921022007450d000c040b0b20052002200320091b360228200541306a41146a4103360200200541c8006a41146a4104360200200541d4006a410436020020054203370234200541e889c0003602302005410136024c2005200541c8006a3602402005200541186a3602582005200541106a3602502005200541286a360248200541306a2004104c000b200541e4006a4104360200200541c8006a41146a4104360200200541d4006a4101360200200541306a41146a410436020020054204370234200541808ac0003602302005410136024c2005200541c8006a3602402005200541186a3602602005200541106a36025820052005410c6a3602502005200541086a360248200541306a2004104c000b200221090b024020092001460d00410121070240024002400240200020096a220a2c00002202417f4a0d0041002106200020016a220721010240200a41016a2007460d00200a41026a2101200a2d0001413f7121060b2002411f71210a200241ff017141df014b0d012006200a4106747221010c020b2005200241ff0171360224200541286a21020c020b4100210020072108024020012007460d00200141016a210820012d0000413f7121000b200020064106747221010240200241ff017141f0014f0d002001200a410c747221010c010b41002102024020082007460d0020082d0000413f7121020b2001410674200a411274418080f00071722002722201418080c400460d020b2005200136022441012107200541286a21022001418001490d00410221072001418010490d0041034104200141808004491b21070b200520093602282005200720096a36022c200541306a41146a4105360200200541ec006a4104360200200541e4006a4104360200200541c8006a41146a4106360200200541d4006a410736020020054205370234200541a08ac000360230200520023602582005410136024c2005200541c8006a3602402005200541186a3602682005200541106a3602602005200541246a3602502005200541206a360248200541306a2004104c000b41958dcc00412b2004103f000b1000200120002802002000280204105a0b800101037f230041206b22022400024002402000280200200110610d002001411c6a2802002103200128021821042002411c6a4100360200200241b0b4cc003602182002420137020c200241888bc00036020820042003200241086a1043450d010b200241206a240041010f0b2000280204200110612101200241206a240020010bdd0502047f017e410121020240200128021841272001411c6a2802002802101101000d0041022103024002400240024002402000280200220041776a2204411e4d0d00200041dc00470d010c020b41f40021050240024020040e1f05010202000202020202020202020202020202020202020202030202020203050b41f20021050c040b41ee0021050c030b0240024002402000105f0d00024002400240200041808004490d00200041808008490d0120004190fc476a4190fc0b490d02200041b5d9736a41b5db2b490d02200041e28b746a41e20b490d022000419fa8746a419f18490d02200041dee2746a410e490d02200041feffff0071419ef00a460d02200041a2b2756a4122490d02200041cb91756a410a4b0d050c020b200041f08bc000412941c28cc00041a20241e48ec00041b5021060450d010c040b2000419991c000412641e591c00041af01419493c00041a30310600d030b200041017267410276410773ad4280808080d0008421060c010b200041017267410276410773ad4280808080d0008421060b410321030c020b410121030c010b0b200021050b03402003210441dc002100410121024101210302400240024002400240024020040e0402010500020b02400240024002402006422088a741ff01710e06050302010006050b200642ffffffff8f608342808080803084210641f50021000c060b200642ffffffff8f608342808080802084210641fb0021000c050b20052006a72204410274411c7176410f712203413072200341d7006a2003410a491b210002402004450d002006427f7c42ffffffff0f832006428080808070838421060c050b200642ffffffff8f60834280808080108421060c040b200642ffffffff8f6083210641fd0021000c030b41002103200521000c030b20012802184127200128021c2802101101000f0b200642ffffffff8f60834280808080c0008421060b410321030b20012802182000200128021c280210110100450d000b0b20020b9d0301057f0240024002404100410f200041a49a04491b2201200141086a2201200141027441f896c0006a280200410b742000410b7422014b1b2202200241046a2202200241027441f896c0006a280200410b7420014b1b2202200241026a2202200241027441f896c0006a280200410b7420014b1b2202200241016a2202200241027441f896c0006a280200410b7420014b1b220241027441f896c0006a280200410b74220320014620032001496a20026a2201411e4b0d002001410274210241b105210302402001411e460d00200241fc96c0006a2204450d00200428020041157621030b4100210402402001417f6a220520014b0d002005411f4f0d03200541027441f896c0006a28020041ffffff007121040b02402003200241f896c0006a280200411576220141016a460d00200020046b21022003417f6a2103410021000340200141b0054b0d0320002001418498c0006a2d00006a220020024b0d012003200141016a2201470d000b0b20014101710f0b2001411f41b89dc0001042000b200141b10541c89dc0001042000b2005411f41f497c0001042000bea0201067f200120024101746a210720004180fe0371410876210841002109200041ff0171210a0240024002400340200141026a210b200920012d000122026a210c024020012d000022012008460d00200120084b0d03200c2109200b2101200b2007470d010c030b0240200c2009490d00200c20044b0d02200320096a2101024003402002450d012002417f6a210220012d00002109200141016a21012009200a470d000b410021020c050b200c2109200b2101200b2007470d010c030b0b2009200c41b896c0001059000b200c200441b896c0001058000b200041ffff03712109200520066a210c4101210202400340200541016a210a0240024020052d00002201411874411875220b4100480d00200a21050c010b200a200c460d02200b41ff007141087420052d0001722101200541026a21050b200920016b22094100480d02200241017321022005200c470d000c020b0b41958dcc00412b41c896c000103f000b20024101710bab0201037f23004180016b2202240002400240024002400240200128020022034110710d0020034120710d012000ad41012001105221000c020b410021030340200220036a41ff006a2000410f712204413072200441d7006a2004410a491b3a00002003417f6a2103200041047622000d000b20034180016a22004181014f0d022001410141d88bc0004102200220036a4180016a410020036b105621000c010b410021030340200220036a41ff006a2000410f712204413072200441376a2004410a491b3a00002003417f6a2103200041047622000d000b20034180016a22004181014f0d022001410141d88bc0004102200220036a4180016a410020036b105621000b20024180016a240020000f0b200041800141c88bc0001059000b200041800141c88bc0001059000b1c00200128021841c99ec000410b2001411c6a28020028020c1100000b1c00200128021841d49ec000410e2001411c6a28020028020c1100000b5b01017f230041306b220324002003200136020c20032000360208200341246a41013602002003420137021420034188b2cc003602102003410436022c2003200341286a3602202003200341086a360228200341106a2002104c000b140020002802002001200028020428020c1101000b15002001200028020022002802002000280204105a0bb10401077f230041306b220324000240024020020d00410021040c010b200341286a210502400240024002400340024020002802082d0000450d00200028020041a69fc0004104200028020428020c1100000d050b2003410a3602282003428a808080103703202003200236021c200341003602182003200236021420032001360210200341086a410a200120021068024002400240024020032802084101470d00200328020c210403402003200420032802186a41016a2204360218024002402004200328022422064f0d00200328021421070c010b200328021422072004490d00200641054f0d072003280210200420066b22086a22092005460d0420092005200610a008450d040b200328021c22092004490d0220072009490d0220032006200341106a6a41176a2d0000200328021020046a200920046b10682003280204210420032802004101460d000b0b2003200328021c3602180b200028020841003a0000200221040c010b200028020841013a0000200841016a21040b2000280204210920002802002106024020044520022004467222070d00200220044d0d03200120046a2c000041bf7f4c0d030b200620012004200928020c1100000d04024020070d00200220044d0d04200120046a2c000041bf7f4c0d040b200120046a2101200220046b22020d000b410021040c040b2006410441ac9fc0001058000b200120024100200441bc9fc000105b000b200120022004200241d089c000105b000b410121040b200341306a240020040bf80201067f410021040240024020024103712205450d00410420056b2205450d0020032005200520034b1b210441002105200141ff01712106034020042005460d01200220056a2107200541016a210520072d000022072006470d000b410121032007200141ff01714641016a41017120056a417f6a21050c010b200141ff017121060240024020034108490d002004200341786a22084b0d00200641818284086c210502400340200220046a220741046a2802002005732209417f73200941fffdfb776a7120072802002005732207417f73200741fffdfb776a7172418081828478710d01200441086a220420084d0d000b0b200420034b0d010b200220046a2109200320046b210241002103410021050240034020022005460d01200920056a2107200541016a210520072d000022072006470d000b410121032007200141ff01714641016a41017120056a417f6a21050b200520046a21050c010b2004200341e89fc0001059000b20002005360204200020033602000bbb0302047f027e230041c0006b2205240041012106024020002d00040d0020002d000521070240200028020022082d00004104710d004101210620082802184196a0c0004193a0c000200741ff017122071b4102410320071b2008411c6a28020028020c1100000d014101210620002802002208280218200120022008411c6a28020028020c1100000d01410121062000280200220828021841dc92c80041022008411c6a28020028020c1100000d0120032000280200200428020c11010021060c010b0240200741ff01710d004101210620082802184198a0c00041032008411c6a28020028020c1100000d01200028020021080b41012106200541013a0017200541346a419ca0c000360200200520082902183703082005200541176a360210200829020821092008290210210a200520082d00203a00382005200a37032820052009370320200520082902003703182005200541086a360230200541086a2001200210670d00200541086a41dc92c800410210670d002003200541186a200428020c1101000d00200528023041b4a0c0004102200528023428020c11000021060b200041013a0005200020063a0004200541c0006a240020000b8b0201027f230041106b220224002002410036020c02400240024002402001418001490d002001418010490d012002410c6a21032001418080044f0d0220022001413f71418001723a000e20022001410676413f71418001723a000d20022001410c76410f7141e001723a000c410321010c030b200220013a000c2002410c6a2103410121010c020b20022001413f71418001723a000d20022001410676411f7141c001723a000c2002410c6a2103410221010c010b20022001413f71418001723a000f2002200141127641f001723a000c20022001410676413f71418001723a000e20022001410c76413f71418001723a000d410421010b20002003200110672101200241106a240020010b6001017f230041206b2202240020022000360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a41b8a0c000200241086a10432101200241206a240020010b0d0020002802002001200210670b0b0020002802002001106a0b6301017f230041206b2202240020022000280200360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a41b8a0c000200241086a10432101200241206a240020010bd30202047f027e230041c0006b2203240041012104024020002d00080d00200028020421050240200028020022062d00004104710d004101210420062802184196a0c00041d3a0c00020051b4102410120051b2006411c6a28020028020c1100000d0120012000280200200228020c11010021040c010b024020050d0041012104200628021841d4a0c00041022006411c6a28020028020c1100000d01200028020021060b41012104200341013a0017200341346a419ca0c000360200200320062902183703082003200341176a3602102006290208210720062902102108200320062d00203a00382003200837032820032007370320200320062902003703182003200341086a3602302001200341186a200228020c1101000d00200328023041b4a0c0004102200328023428020c11000021040b200020043a00082000200028020441016a360204200341c0006a240020000bd40202037f027e230041c0006b2203240041012104024020002d00040d0020002d000521040240200028020022052d00004104710d000240200441ff0171450d004101210420052802184196a0c00041022005411c6a28020028020c1100000d02200028020021050b20012005200228020c11010021040c010b0240200441ff01710d0041012104200528021841d7a0c00041012005411c6a28020028020c1100000d01200028020021050b41012104200341013a0017200341346a419ca0c000360200200320052902183703082003200341176a3602102005290208210620052902102107200320052d00203a00382003200737032820032006370320200320052902003703182003200341086a3602302001200341186a200228020c1101000d00200328023041b4a0c0004102200328023428020c11000021040b200041013a0005200020043a0004200341c0006a240020000b6401027f230041206b220224002001411c6a280200210320012802182101200241086a41106a200041106a290200370300200241086a41086a200041086a2902003703002002200029020037030820012003200241086a10432100200241206a240020000bd70a020c7f017e230041206b220324004101210402400240200228021841222002411c6a2802002802101101000d000240024020010d00410021050c010b200020016a21064100210520002107410021080240034020072109200741016a210a02400240024020072c0000220b417f4a0d0002400240200a2006470d004100210c200621070c010b20072d0001413f71210c200741026a220a21070b200b411f7121040240200b41ff0171220b41df014b0d00200c200441067472210c0c020b0240024020072006470d004100210d2006210e0c010b20072d0000413f71210d200741016a220a210e0b200d200c41067472210c0240200b41f0014f0d00200c2004410c7472210c0c020b02400240200e2006470d004100210b200a21070c010b200e41016a2107200e2d0000413f71210b0b200c4106742004411274418080f0007172200b72220c418080c400470d020c040b200b41ff0171210c0b200a21070b4102210a024002400240024002400240200c41776a220b411e4d0d00200c41dc00470d010c020b41f400210e02400240200b0e1f05010202000202020202020202020202020202020202020202030202020203050b41f200210e0c040b41ee00210e0c030b0240200c105f0d0002400240200c41808004490d00200c41808008490d01200c4190fc476a4190fc0b490d02200c41b5d9736a41b5db2b490d02200c41e28b746a41e20b490d02200c419fa8746a419f18490d02200c41dee2746a410e490d02200c41feffff0071419ef00a460d02200c41a2b2756a4122490d02200c41cb91756a410a4d0d020c060b200c41f08bc000412941c28cc00041a20241e48ec00041b5021060450d010c050b200c419991c000412641e591c00041af01419493c00041a30310600d040b200c41017267410276410773ad4280808080d00084210f4103210a0c010b0b200c210e0b2003200136020420032000360200200320053602082003200836020c0240024020082005490d0002402005450d0020052001460d00200520014f0d01200020056a2c000041bf7f4c0d010b02402008450d0020082001460d00200820014f0d01200020086a2c000041bf7f4c0d010b2002280218200020056a200820056b200228021c28020c110000450d01410121040c060b20032003410c6a3602182003200341086a36021420032003360210200341106a1073000b0340200a210b4101210441dc0021054101210a024002400240024002400240200b0e0402010500020b0240024002400240200f422088a741ff01710e06050302010006050b200f42ffffffff8f608342808080803084210f4103210a41f50021050c070b200f42ffffffff8f608342808080802084210f4103210a41fb0021050c060b200e200fa7220b410274411c7176410f71220a413072200a41d7006a200a410a491b21050240200b450d00200f427f7c42ffffffff0f83200f4280808080708384210f0c050b200f42ffffffff8f608342808080801084210f0c040b200f42ffffffff8f6083210f4103210a41fd0021050c040b4100210a200e21050c030b4101210a0240200c418001490d004102210a200c418010490d0041034104200c41808004491b210a0b200a20086a21050c040b200f42ffffffff8f60834280808080c00084210f0b4103210a0b20022802182005200228021c280210110100450d000c050b0b200820096b20076a210820062007470d000b0b2005450d0020052001460d00200520014f0d02200020056a2c000041bf7f4c0d020b410121042002280218200020056a200120056b200228021c28020c1100000d0020022802184122200228021c28021011010021040b200341206a240020040f0b200020012005200141d089c000105b000b2b01017f2000280200220128020020012802042000280204280200200028020828020041dca0c000105b000bee0704057f017e017f017e02400240024002402002450d00410020016b410020014103711b2103200241796a4100200241074b1b210441002105034002400240200120056a2d000022064118744118752207417f4a0d004280808080802021080240200641c884c0006a2d0000417e6a220941024d0d00428080808010210a0c070b0240024002400240024020090e03000102000b200541016a22062002490d024200210a0c090b4200210a200541016a220920024f0d08200120096a2d0000210902400240200641a07e6a2206410d4b0d000240024020060e0e0002020202020202020202020201000b200941e0017141a001460d02428080808010210a0c0c0b02402009411874411875417f4c0d00428080808010210a0c0c0b200941ff017141a001490d01428080808010210a0c0b0b02402007411f6a41ff0171410b4b0d0002402009411874411875417f4c0d00428080808010210a0c0c0b200941ff017141c001490d01428080808010210a0c0b0b0240200941ff017141bf014d0d00428080808010210a0c0b0b0240200741fe017141ee01460d00428080808010210a0c0b0b2009411874411875417f4c0d00428080808010210a0c0a0b42002108200541026a220620024f0d09200120066a2d000041c00171418001460d020c070b4200210a200541016a220920024f0d07200120096a2d0000210902400240200641907e6a220641044b0d000240024020060e050002020201000b200941f0006a41ff01714130490d02428080808010210a0c0b0b02402009411874411875417f4c0d00428080808010210a0c0b0b200941ff0171419001490d01428080808010210a0c0a0b0240200941ff017141bf014d0d00428080808010210a0c0a0b02402007410f6a41ff017141024d0d00428080808010210a0c0a0b2009411874411875417f4c0d00428080808010210a0c090b200541026a220620024f0d07200120066a2d000041c00171418001470d0642002108200541036a220620024f0d08200120066a2d000041c00171418001460d01428080808080e0002108428080808010210a0c080b428080808010210a200120066a2d000041c00171418001470d070b200641016a21050c010b0240200320056b4103710d000240200520044f0d000340200120056a220641046a280200200628020072418081828478710d01200541086a22052004490d000b0b200520024f0d010340200120056a2c00004100480d022002200541016a2205470d000c040b0b200541016a21050b20052002490d000b0b20002001360204200041086a2002360200200041003602000f0b428080808080c0002108428080808010210a0c010b420021080b2000200a2005ad84200884370204200041013602000b1c0020012802184190b2cc0041052001411c6a28020028020c1100000bb30101037f200028020421020240024020002802004101470d002000410c6a28020022002001107720004103742200450d01200220006a2103034020022802002100200241046a2802002204200110772001200020041078200241086a22022003470d000c020b0b200041086a28020022002001107720004103742200450d00200220006a2103034020022802002100200241046a2802002204200110772001200020041078200241086a22022003470d000b0b0bab0101017f230041106b220224000240024002400240200041c000490d00200041808001490d012000418080808004490d02200241033a00032001200241036a41011078200220003602042001200241046a410410780c030b200220004102743a00032001200241036a410110780c020b200220004102744101723b010a20012002410a6a410210780c010b2002200041027441027236020c20012002410c6a410410780b200241106a24000bcd0101047f0240024002400240200041046a2802002203200041086a28020022046b2002490d00200028020021050c010b200420026a22052004490d01200341017422062005200620054b1b22064100480d010240024020030d00024020060d00410121050c020b2006103322050d010c040b2000280200210520032006460d0020052003200610372205450d03200041086a28020021040b20002005360200200041046a20063602000b200520046a20012002109d081a200041086a200420026a3602000f0b103e000b103c000bff0101037f200028020421020240024020002802004101470d002000410c6a2802002200200110772000450d01200041186c2103200241146a21000340200041706a2802002102200041746a28020022042001107720012002200410782000417c6a280200210220002802002204200110772001200220041078200041186a2100200341686a22030d000c020b0b200041086a2802002200200110772000450d00200041186c2103200241146a21000340200041706a2802002102200041746a28020022042001107720012002200410782000417c6a280200210220002802002204200110772001200220041078200041186a2100200341686a22030d000b0b0ba90701057f230041206b2203240020012002107702402001450d00200141d8006c2104410021050340200020056a220141046a2802002106200141086a28020022072002107720022006200710782003200141d4006a2d00003a000d20022003410d6a4101107802402001410c6a2d0000220641024b0d0002400240024020060e03000102000b200341003a000e20022003410e6a41011078200141146a2802002106200141186a28020022072002107720022006200710780c020b200341013a000e20022003410e6a4101107802402001410d6a2d0000220641064b0d000240024002400240024002400240024020060e0700010203040506000b200341003a000f0c060b200341013a000f0c050b200341023a000f0c040b200341033a000f0c030b200341043a000f0c020b200341053a000f0c010b200341063a000f0b20022003410f6a410110780b200141146a2802002106200141186a2802002207200210772002200620071078200141206a2802002106200141246a280200220720021077200220062007107820032001410e6a2d00003a000e20022003410e6a410110780c010b200341023a000e20022003410e6a4101107802402001410d6a2d0000220641064b0d000240024002400240024002400240024020060e0700010203040506000b200341003a000f0c060b200341013a000f0c050b200341023a000f0c040b200341033a000f0c030b200341043a000f0c020b200341053a000f0c010b200341063a000f0b20022003410f6a410110780b200141146a2802002106200141186a2802002207200210772002200620071078200141206a2802002106200141246a28020022072002107720022006200710782001412c6a2802002106200141306a28020022072002107720022006200710782001410e6a2d0000220641064b0d000240024002400240024002400240024020060e0700010203040506000b200341003a000f0c060b200341013a000f0c050b200341023a000f0c040b200341033a000f0c030b200341043a000f0c020b200341053a000f0c010b200341063a000f0b20022003410f6a410110780b02400240200141346a2802004101470d00200141386a2802002106200141c0006a28020022072002107720022006200710780c010b200341106a200141386a2802002001413c6a28020028020c11020020032802102106200328021822072002107720022006200710782003280214450d00200610350b200141c4006a200210762004200541d8006a2205470d000b0b200341206a24000b8605010e7f2001410c6a2802002102200128020821032001280204210402400240024002400240024002400240200128020022050d0020030d010c060b200420056b2101024020030d00200121060c020b2001200220036b6a220620014f0d010240024020042005460d00200541016a21070c010b20022003460d064100210720032105200341016a21030b4100210841002106410121090340200420076b210a2008410174210b20022003220c6b210d410021010340200720016a210e20052d000021030240200820016a22052006470d002005417f417f2004200e6b2206200d6a220f200f2006491b200d200e1b220641016a220f200f2006491b6a22062005490d06200b2006200b20064b1b22064100480d06024020050d00024020060d00410121090c020b2006103322090d010c080b20052006460d0020092005200610372209450d070b200920086a20016a20033a00000240200e450d00200a2001460d00200b41026a210b200141016a2101200e21050c010b0b200c2002460d03200541016a2108200c41016a210341002107200c21050c000b0b200220036b21060b0240024020060d00410121090c010b20064100480d02200610332209450d030b4100210b0240024020050d00200921010c010b024020042005470d00200921010c010b200921012005210e03402001200e2d00003a0000200141016a21012004200e41016a220e470d000b200420056b210b0b2003450d0420022003460d042003210e03402001200e2d00003a0000200141016a21012002200e41016a220e470d000b2002200b20036b6a210b0c040b200541016a210b0c030b103e000b103c000b410121094100210b410021060b2000200b36020820002006360204200020093602000bd40101037f02400240024002402000280200220041046a2802002203200041086a28020022046b2002490d00200028020021050c010b200420026a22052004490d01200341017422042005200420054b1b22044100480d010240024020030d00024020040d00410121050c020b2004103322050d010c040b2000280200210520032004460d0020052003200410372205450d030b20002005360200200041046a2004360200200041086a28020021040b200520046a20012002109d081a200041086a200420026a36020041000f0b103e000b103c000bbf0301047f230041106b22022400200028020021002002410036020c02400240024002402001418001490d002001418010490d012001418080044f0d0220022001413f71418001723a000e20022001410676413f71418001723a000d20022001410c76410f7141e001723a000c410321010c030b200220013a000c410121010c020b20022001413f71418001723a000d20022001410676411f7141c001723a000c410221010c010b20022001413f71418001723a000f2002200141127641f001723a000c20022001410676413f71418001723a000e20022001410c76413f71418001723a000d410421010b0240024002400240200041046a2802002203200041086a28020022046b2001490d00200028020021050c010b200420016a22052004490d01200341017422042005200420054b1b22044100480d010240024020030d00024020040d00410121050c020b2004103322050d010c040b2000280200210520032004460d0020052003200410372205450d030b20002005360200200041046a2004360200200041086a28020021040b200520046a2002410c6a2001109d081a200041086a200420016a360200200241106a240041000f0b103e000b103c000b6301017f230041206b2202240020022000280200360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a41e4a1c000200241086a10432101200241206a240020010bcd0101037f0240024002400240200041046a2802002203200041086a28020022046b2002490d00200028020021050c010b200420026a22052004490d01200341017422042005200420054b1b22044100480d010240024020030d00024020040d00410121050c020b2004103322050d010c040b2000280200210520032004460d0020052003200410372205450d030b20002005360200200041046a2004360200200041086a28020021040b200520046a20012002109d081a200041086a200420026a3602000f0b103e000b103c000b040041010bb60101017f230041c0006b2202240020024100360210200242013703082002410836021c20022001410c6a3602202002200241206a3602182002200241086a3602242002413c6a41013602002002420137022c20024188b2cc003602282002200241186a360238200241246a41e4a1c000200241286a10431a20012d0000417f6a41ff0171200141046a290200200235021042208620023502088410000240200228020c450d00200228020810350b200241c0006a24000b6901037f230041206b220224002001411c6a280200210320012802182104200241086a41106a2000280200220141106a290200370300200241086a41086a200141086a2902003703002002200129020037030820042003200241086a10432101200241206a240020010b040041000b02000b02000bc00101017f0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1b220141ffffffff03712001470d00200141027422014100480d00024020030d0020010d02410421020c040b20002802002102200341027422032001460d03024020030d0020010d02410421020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a20014102763602000b0bbe0102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad420c7e2204422088a70d002004a722014100480d00024020030d0020010d02410421020c040b200028020021022003410c6c22032001460d03024020030d0020010d02410421020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a2001410c6e3602000b0bbe0102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad42307e2204422088a70d002004a722014100480d00024020030d0020010d02410821020c040b20002802002102200341306c22032001460d03024020030d0020010d02410821020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a200141306e3602000b0bbe0102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad42307e2204422088a70d002004a722014100480d00024020030d0020010d02410421020c040b20002802002102200341306c22032001460d03024020030d0020010d02410421020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a200141306e3602000b0bbf0101017f0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1b220141ffffff3f712001470d00200141057422014100480d00024020030d0020010d02410121020c040b20002802002102200341057422032001460d03024020030d0020010d02410121020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a20014105763602000b0bbe0102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad42387e2204422088a70d002004a722014100480d00024020030d0020010d02410821020c040b20002802002102200341386c22032001460d03024020030d0020010d02410821020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a200141386e3602000b0bc00101017f0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1b220141ffffffff00712001470d00200141047422014100480d00024020030d0020010d02410421020c040b20002802002102200341047422032001460d03024020030d0020010d02410421020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a20014104763602000b0bbe0102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad42247e2204422088a70d002004a722014100480d00024020030d0020010d02410421020c040b20002802002102200341246c22032001460d03024020030d0020010d02410421020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a200141246e3602000b0bb40101027f0240200041046a280200220320016b20024f0d000240024002400240200120026a22042001490d00200341017422022004200220044b1b220420046a22012004490d0020014100480d00024020030d0020010d02410221030c040b2000280200210320022001460d03024020020d0020010d02410221030c040b20032002200110372203450d020c030b103e000b2001103322030d010b103c000b20002003360200200041046a20014101763602000b0bbe0102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad42287e2204422088a70d002004a722014100480d00024020030d0020010d02410821020c040b20002802002102200341286c22032001460d03024020030d0020010d02410821020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a200141286e3602000b0bc00101017f0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1b220141ffffffff01712001470d00200141037422014100480d00024020030d0020010d02410421020c040b20002802002102200341037422032001460d03024020030d0020010d02410421020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a20014103763602000b0bbf0101017f0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1b220141ffffff3f712001470d00200141057422014100480d00024020030d0020010d02410421020c040b20002802002102200341057422032001460d03024020030d0020010d02410421020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a20014105763602000b0bc10102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad42b0027e2204422088a70d002004a722014100480d00024020030d0020010d02410821020c040b20002802002102200341b0026c22032001460d03024020030d0020010d02410821020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a200141b0026e3602000b0bc10102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad42f0007e2204422088a70d002004a722014100480d00024020030d0020010d02410421020c040b20002802002102200341f0006c22032001460d03024020030d0020010d02410421020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a200141f0006e3602000b0bba0101027f0240200041046a2802002001470d000240024002400240200141016a22022001490d00200141017422032002200320024b1b220241ffffff1f712002470d00200241067422024100480d00024020010d0020020d02410821030c040b20002802002103200141067422012002460d03024020010d0020020d02410821030c040b20032001200210372203450d020c030b103e000b2002103322030d010b103c000b20002003360200200041046a20024106763602000b0bc10102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad42d8027e2204422088a70d002004a722014100480d00024020030d0020010d02410821020c040b20002802002102200341d8026c22032001460d03024020030d0020010d02410821020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a200141d8026e3602000b0bc10102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad42e8007e2204422088a70d002004a722014100480d00024020030d0020010d02410821020c040b20002802002102200341e8006c22032001460d03024020030d0020010d02410821020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a200141e8006e3602000b0bbe0102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad42187e2204422088a70d002004a722014100480d00024020030d0020010d02410421020c040b20002802002102200341186c22032001460d03024020030d0020010d02410421020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a200141186e3602000b0bbe0102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad422c7e2204422088a70d002004a722014100480d00024020030d0020010d02410421020c040b200028020021022003412c6c22032001460d03024020030d0020010d02410421020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a2001412c6e3602000b0bbe0102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad42147e2204422088a70d002004a722014100480d00024020030d0020010d02410421020c040b20002802002102200341146c22032001460d03024020030d0020010d02410421020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a200141146e3602000b0bc00101017f0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1b220141ffffffff00712001470d00200141047422014100480d00024020030d0020010d02410821020c040b20002802002102200341047422032001460d03024020030d0020010d02410821020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a20014104763602000b0bc10102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad42d8007e2204422088a70d002004a722014100480d00024020030d0020010d02410821020c040b20002802002102200341d8006c22032001460d03024020030d0020010d02410821020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a200141d8006e3602000b0bbe0102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad42187e2204422088a70d002004a722014100480d00024020030d0020010d02410821020c040b20002802002102200341186c22032001460d03024020030d0020010d02410821020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a200141186e3602000b0bbe0102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad42287e2204422088a70d002004a722014100480d00024020030d0020010d02410421020c040b20002802002102200341286c22032001460d03024020030d0020010d02410421020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a200141286e3602000b0bbe0102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad42227e2204422088a70d002004a722014100480d00024020030d0020010d02410221020c040b20002802002102200341226c22032001460d03024020030d0020010d02410221020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a200141226e3602000b0bc10102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad42c4007e2204422088a70d002004a722014100480d00024020030d0020010d02410421020c040b20002802002102200341c4006c22032001460d03024020030d0020010d02410421020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a200141c4006e3602000b0bc10102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad42a0017e2204422088a70d002004a722014100480d00024020030d0020010d02410121020c040b20002802002102200341a0016c22032001460d03024020030d0020010d02410121020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a200141a0016e3602000b0bbf0101017f0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1b220141ffffff3f712001470d00200141057422014100480d00024020030d0020010d02410821020c040b20002802002102200341057422032001460d03024020030d0020010d02410821020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a20014105763602000b0bbe0102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad42387e2204422088a70d002004a722014100480d00024020030d0020010d02410421020c040b20002802002102200341386c22032001460d03024020030d0020010d02410421020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a200141386e3602000b0bc10102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad42d0007e2204422088a70d002004a722014100480d00024020030d0020010d02410821020c040b20002802002102200341d0006c22032001460d03024020030d0020010d02410821020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a200141d0006e3602000b0bc10102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad42e0007e2204422088a70d002004a722014100480d00024020030d0020010d02410821020c040b20002802002102200341e0006c22032001460d03024020030d0020010d02410821020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a200141e0006e3602000b0bbe0102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad42347e2204422088a70d002004a722014100480d00024020030d0020010d02410421020c040b20002802002102200341346c22032001460d03024020030d0020010d02410421020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a200141346e3602000b0bbf0101017f0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1b220141ffffff1f712001470d00200141067422014100480d00024020030d0020010d02410421020c040b20002802002102200341067422032001460d03024020030d0020010d02410421020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a20014106763602000b0bc10102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad42d0027e2204422088a70d002004a722014100480d00024020030d0020010d02410821020c040b20002802002102200341d0026c22032001460d03024020030d0020010d02410821020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a200141d0026e3602000b0bc10102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad42c8007e2204422088a70d002004a722014100480d00024020030d0020010d02410421020c040b20002802002102200341c8006c22032001460d03024020030d0020010d02410421020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a200141c8006e3602000b0bbc0102027f017e0240200041046a2802002001470d000240024002400240200141016a22022001490d00200141017422032002200320024b1bad42c8037e2204422088a70d002004a722024100480d00024020010d0020020d02410821030c040b20002802002103200141c8036c22012002460d03024020010d0020020d02410821030c040b20032001200210372203450d020c030b103e000b2002103322030d010b103c000b20002003360200200041046a200241c8036e3602000b0bbe0102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad423c7e2204422088a70d002004a722014100480d00024020030d0020010d02410421020c040b200028020021022003413c6c22032001460d03024020030d0020010d02410421020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a2001413c6e3602000b0b800b04047f017e127f037e230041d0036b22012400200141f0006a41186a4200370300200141f0006a41106a22024200370300200141f0006a41086a220342003703002001420037037041f7edcb00ad4280808080f000841001220429000021052003200441086a290000370300200120053703702004103541eeedcb00ad4280808080900184100122042900002105200141206a41086a2206200441086a2900003703002001200537032020041035200220012903202205370300200141c0006a41086a22042003290300370300200141c0006a41106a2005370300200141c0006a41186a200629030037030020012001290370370340200141f0006a200141c0006a10ac0102400240024020012903704202510d002000280208210320002802042107200028020021082001200228020010ad01200141f0006a200128020022092001280208220a10ae012004200141f0006a410c6a290200370300200120012902743703400240024020012802704101460d00200141106a410c6a4100360200200142003703100c010b200141106a41086a200141c0006a41086a290300370300200120012903403703100b02402003450d002008200341246c6a210b20014184016a210c2001411c6a210d200141106a410472210e200141e8006a210f200141c0006a41206a211020082111034020112802202112200141206a41186a2213201141186a290000370300200141206a41106a2214201141106a290000370300200141206a41086a2215201141086a290000370300200120112900003703200240024020012802142206450d00200128021821160c010b200141f0006a410041e002109f081a200f410036020020104200370300200141c0006a41186a22004200370300200141c0006a41106a22034200370300200141c0006a41086a220442003703002001420037034041940310332206450d0541002116200641003b010620064100360200200641086a200141f0006a41e002109d081a20064190036a200f28020036020020064188036a201029030037020020064180036a2000290300370200200641f8026a2003290300370200200641f0026a2004290300370200200620012903403702e80220014100360218200120063602140b201141246a2111024002400340200641086a210320062f01062217410574210041002104024003402000450d01200141206a2003412010a0082202450d03200041606a2100200441016a2104200341206a21032002417f4a0d000b2004417f6a21170b02402016450d002016417f6a2116200620174102746a4194036a28020021060c010b0b200141c0006a41186a20132903002205370300200141c0006a41106a20142903002218370300200141c0006a41086a2015290300221937030020012001290320221a370340200c201a370200200c41086a2019370200200c41106a2018370200200c41186a20053702002001200d360280012001201736027c2001200e3602782001200636027420014100360270200141f0006a410010af0121000c010b200620044102746a41e8026a21000b2000200028020020126a3602002001200128021020126a3602102011200b470d000b0b02402007450d00200741246c450d00200810350b200141fc006a200141106a41086a290300370200200120012903102205370274200141013602702001410036024820014201370340410410332200450d0220002005a73600002001200036024020014284808080c000370244200141f0006a41086a2200200141c0006a10b00120012802442103200aad4220862009ad84200135024842208620012802402204ad84100202402003450d00200410350b200010b1012001280204450d01200910350c010b200041046a2802002203450d00200341246c450d00200028020010350b200141d0036a24000f0b103c000bd60202057f027e230041d0006b220224002002412036020420022001360200200241086a2001ad4280808080800484100510c20102400240200228020822010d00200042023703000c010b200228020c210302400240200241106a28020022044104490d0020044104460d0020012d0004220541014b0d0020012800002106420021070240024020050e020100010b2004417b6a4108490d0120012900052108420121070b20002008370308200041106a20063602000c010b20024100360220200242013703182002410936022c200220023602282002200241186a360234200241cc006a41013602002002420137023c200241c888c2003602382002200241286a360248200241346a41e88ac500200241386a10431a200235022042208620023502188410060240200228021c450d00200228021810350b420221070b200020073703002003450d00200110350b200241d0006a24000bfc0403027f017e057f230041d0006b2202240041f7edcb00ad4280808080f00084100122032900002104200241086a41086a200341086a290000370300200220043703082003103541ccb5c000ad4280808080800284100122032900002104200241186a41086a200341086a2900003703002002200437031820031035200220013602342002200241346aad4280808080c000841003220329000037033820031035200241cc006a200241386a3602002002200241386a41086a3602442002200241346a3602482002200241386a360240200241286a200241c0006a107b02400240024002402002280230220541206a2206417f4c0d00200228022821070240024020060d0041002101410121030c010b200610332203450d02200621010b024002402001410f4d0d00200121080c010b200141017422084110200841104b1b22084100480d03024020010d002008103322030d010c050b20012008460d0020032001200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821010c010b200841017422014120200141204b1b22014100480d0320082001460d0020032008200110372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200141606a2005490d00200121080c010b200541206a22082005490d03200141017422092008200920084b1b22084100480d0320012008460d0020032001200810372203450d040b200341206a20072005109d081a2000200636020820002008360204200020033602000240200228022c450d00200710350b200241d0006a24000f0b1044000b1045000b103e000b103c000bcd0b030e7f047e087f230041a0046b220324002003200236021420032001360210200341186a2002ad4220862001ad84100510c20102400240200328021822040d00200041003602000c010b200328021c21052003200341206a280200220136022c2003200436022802400240024020014104490d0020032001417c6a36022c2003200441046a36022820042800002106200341086a200341286a10c40120032802080d00200328020c21072003410036024820034100360240200341c0006a41086a210802400240024002402007450d00200341d4016a2109200328022c210a200341b8016a210b4100210c034041002101200341003a00e001200c41016a210c024002400340200a2001460d01200341c0016a20016a2003280228220d2d00003a00002003200d41016a3602282003200141016a22023a00e0012002210120024120470d000b20034190016a41086a220e200341c0016a41086a29030037030020034190016a41106a220f200341c0016a41106a29030037030020034190016a41186a2210200341c0016a41186a290300370300200320032903c001370390012003200a20026b220136022c200141044f0d010c050b2003410036022c200141ff0171450d04200341003a00e001410021010c050b200341d0006a41086a200e2903002211370300200341d0006a41106a200f2903002212370300200341d0006a41186a20102903002213370300200320032903900122143703502003200d41056a36022820032001417c6a220a36022c200d2800012115200341f0006a41186a22162013370300200341f0006a41106a22172012370300200341f0006a41086a22182011370300200320143703700240024020032802402219450d002003280244211a0c010b200341c0016a410041e002109f081a200b410036020020034190016a41206a2201420037030020104200370300200f4200370300200e4200370300200342003703900141940310332219450d034100211a201941003b010620194100360200201941086a200341c0016a41e002109d081a20194190036a200b28020036020020194188036a200129030037020020194180036a2010290300370200201941f8026a200f290300370200201941f0026a200e29030037020020192003290390013702e80220034100360244200320193602400b024002400340201941086a210220192f0106221b41057421014100210d024003402001450d01200341f0006a2002412010a008221c450d03200141606a2101200d41016a210d200241206a2102201c417f4a0d000b200d417f6a211b0b0240201a450d00201a417f6a211a2019201b4102746a4194036a28020021190c010b0b201020162903002211370300200f20172903002212370300200e201829030022133703002003200329037022143703900120092014370200200941086a2013370200200941106a2012370200200941186a2011370200200320083602d0012003201b3602cc01200320193602c401200341003602c0012003200341c0006a3602c801200341c0016a201510af011a0c010b2019200d4102746a41e8026a20153602000b200c2007470d000b0b410121010c020b103c000b410021010b200341306a41086a20082802002202360200200320032903402211370330200341c0016a41086a2002360200200320113703c00120010d01200341c0016a10b1010b4100210120034100360298012003420137039001200341093602742003200341106a360270200320034190016a360250200341d4016a4101360200200342013702c401200341c888c2003602c0012003200341f0006a3602d001200341d0006a41e88ac500200341c0016a10431a200335029801422086200335029001841006200328029401450d0120032802900110350c010b20034190016a41086a200341c0016a41086a2802002201360200200320032903c00122113703900120002006360204200041086a2011370200200041106a2001360200410121010b200020013602002005450d00200410350b200341a0046a24000bed0701087f23004190046b2202240020002802102203200328020041016a360200200241086a2203200041086a29020037030020022000290200370300200241306a41186a2000412c6a290000370300200241306a41106a200041246a290000370300200241306a41086a2000411c6a29000037030020022000290014370330200241d0006a2002200241306a200110fe0202400240024020022d00504101470d002003200241d9006a290000370300200241106a200241e1006a290000370300200241186a200241e9006a29000037030020022002290051370300200241d0006a412c6a280200210120024188016a280200210420024184016a280200210320024180016a2802002105200228028c012106200241f8006a28020022002802002207450d0120002f01042108200241f4006a2802002109200241d0006a410172210003402002200841ffff037136022c20022001360228200220073602242002200941016a360220200241306a41186a200241186a2201290300370300200241306a41106a200241106a2207290300370300200241306a41086a200241086a220829030037030020022002290300370330200241d0006a200241206a200241306a20052003200410ff0220022d00504101470d032008200041086a2900003703002007200041106a2900003703002001200041186a29000037030020022000290000370300200228027c2101200228028801210420022802840121032002280280012105200228027822082802002207450d0220082f01042108200228027421090c000b0b200241d0006a41086a280200200241d0006a41106a2802004102746a41e8026a21060c010b200241d0006a410272410041be03109f081a02400240024041c40310332200450d0020004100360200200041046a200241d0006a41c003109d081a200020012802002207360294032001200036020020012001280204220841016a360204200741003b010420072000360200200241d0006a41186a200241186a290300370300200241d0006a41106a200241106a290300370300200241d0006a41086a200241086a2903003703002002200229030037035020082004470d0120002f01062201410a4b0d02200020014105746a220441206a200241d0006a41186a290300370000200441186a200241d0006a41106a290300370000200441106a200241d0006a41086a290300370000200441086a2002290350370000200020014102746a41e8026a20053602002000200141016a22014102746a4194036a2003360200200020013b0106200320013b0104200320003602000c030b103c000b41ff83cc00413041c086cc00103f000b41af84cc00412741c086cc00103f000b20024190046a240020060bef0403057f027e027f230041c0006b22022400200041086a28020022032001107702400240024020002802002204450d00024020002802042205450d002005210020042106034020062802940321062000417f6a22000d000b200421000340200020002f01064102746a4194036a28020021002005417f6a22050d000b200241186a2105200621040c020b200241186a2105200421000c010b410021042002410036021c200241186a21050c010b2002200036021c200241246a20002f010636020020024100360220200241003602180b200241086a41086a200541086a2902002207370300200220052902002208370308200241306a2007370300200242003703202002200436021c20024100360218200220083703282002200336023802402003450d00034020022003417f6a360238200241186a410020041b2206280200210020062802082109024002400240200628020c2205200628020422032f01064f0d00200321040c010b0240034020032802002204450d01200041016a210020032f0104210520042103200520042f0106490d020c000b0b2009ad2107410021040c010b2005ad4220862009ad8421070b2007422088a7220941016a21052007a7210a0240024020000d00200421030c010b200420054102746a4194036a2802002103410021052000417f6a2200450d00034020032802940321032000417f6a22000d000b0b2006200536020c2006200a36020820062003360204200641003602002001200420094105746a41086a412010782002200420094102746a41e8026a28020036023c20012002413c6a4104107820022802382203450d01200228021c21040c000b0b200241c0006a24000bb50201047f024020002802002201450d0020002802082102024020002802042200450d00034020012802940321012000417f6a22000d000b0b02402002450d004100210303400240024002402001450d002002417f6a2102200320012f0106490d0141002104034002400240200128020022000d0041002103410021000c010b200441016a210420012f010421030b2001103520002101200320002f01064f0d000b200341016a2103024020040d00200021010c030b200020034102746a4194036a2802002101410021032004417f6a2200450d02034020012802940321012000417f6a22000d000c030b0b41958dcc00412b41c08dcc00103f000b200341016a21030b20020d000b0b2001450d0020012802002100200110352000450d00034020002802002101200010352001210020010d000b0b0ba20703027f017e067f230041e0006b2203240041f7edcb00ad4280808080f00084100122042900002105200341086a41086a200441086a290000370300200320053703082004103541d6a9c000ad4280808080b00284100122042900002105200341186a41086a200441086a2900003703002003200537031820041035200320013602382003200341386aad4280808080c000841003220429000037034820041035200341dc006a22012003413c6a3602002003200341c8006a41086a22063602542003200341386a3602582003200341c8006a360250200341286a200341d0006a107b0240024002400240412010332204450d0020042002290000370000200441186a200241186a290000370000200441106a200241106a290000370000200441086a200241086a29000037000020032004ad428080808080048410032202290000370348200210352001200441206a36020020032004360258200320063602542003200341c8006a360250200341386a200341d0006a107b200410352003280230220741206a2206200328024022086a2202417f4c0d01200328023821092003280228210a0240024020020d004100210b410121040c010b200210332204450d012002210b0b02400240200b410f4d0d00200b21010c010b200b41017422014110200141104b1b22014100480d030240200b0d002001103322040d010c050b200b2001460d002004200b200110372204450d040b20042003290308370000200441086a200341086a41086a2903003700000240024020014170714110460d002001210b0c010b2001410174220b4120200b41204b1b220b4100480d032001200b460d0020042001200b10372204450d040b20042003290318370010200441186a200341186a41086a29030037000002400240200b41606a2007490d00200b21010c010b2007415f4b0d03200b41017422012006200120064b1b22014100480d03200b2001460d002004200b200110372204450d040b200441206a200a2007109d081a02400240200120066b2008490d002001210b0c010b20022006490d032001410174220b2002200b20024b1b220b4100480d03024020010d000240200b0d00410121040c020b200b10332204450d050c010b2001200b460d0020042001200b10372204450d040b200420066a20092008109d081a200020023602082000200b360204200020043602000240200328023c450d00200910350b0240200328022c450d00200a10350b200341e0006a24000f0b1045000b1044000b103e000b103c000ba20703027f017e067f230041e0006b2203240041f7edcb00ad4280808080f00084100122042900002105200341086a41086a200441086a290000370300200320053703082004103541e9a9c000ad4280808080b00284100122042900002105200341186a41086a200441086a2900003703002003200537031820041035200320013602382003200341386aad4280808080c000841003220429000037034820041035200341dc006a22012003413c6a3602002003200341c8006a41086a22063602542003200341386a3602582003200341c8006a360250200341286a200341d0006a107b0240024002400240412010332204450d0020042002290000370000200441186a200241186a290000370000200441106a200241106a290000370000200441086a200241086a29000037000020032004ad428080808080048410032202290000370348200210352001200441206a36020020032004360258200320063602542003200341c8006a360250200341386a200341d0006a107b200410352003280230220741206a2206200328024022086a2202417f4c0d01200328023821092003280228210a0240024020020d004100210b410121040c010b200210332204450d012002210b0b02400240200b410f4d0d00200b21010c010b200b41017422014110200141104b1b22014100480d030240200b0d002001103322040d010c050b200b2001460d002004200b200110372204450d040b20042003290308370000200441086a200341086a41086a2903003700000240024020014170714110460d002001210b0c010b2001410174220b4120200b41204b1b220b4100480d032001200b460d0020042001200b10372204450d040b20042003290318370010200441186a200341186a41086a29030037000002400240200b41606a2007490d00200b21010c010b2007415f4b0d03200b41017422012006200120064b1b22014100480d03200b2001460d002004200b200110372204450d040b200441206a200a2007109d081a02400240200120066b2008490d002001210b0c010b20022006490d032001410174220b2002200b20024b1b220b4100480d03024020010d000240200b0d00410121040c020b200b10332204450d050c010b2001200b460d0020042001200b10372204450d040b200420066a20092008109d081a200020023602082000200b360204200020043602000240200328023c450d00200910350b0240200328022c450d00200a10350b200341e0006a24000f0b1045000b1044000b103e000b103c000bb10503027f017e047f230041d0006b2202240041f7edcb00ad4280808080f00084100122032900002104200241086a41086a200341086a290000370300200220043703082003103541c0a9c000ad4280808080e00084100122032900002104200241186a41086a200341086a29000037030020022004370318200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad42808080808004841003220129000037033820011035200241cc006a200341206a360200200220033602482002200241386a41086a3602442002200241386a360240200241286a200241c0006a107b200310352002280230220541206a2201417f4c0d01200228022821060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a2000200136020820002008360204200020033602000240200228022c450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000bb10503027f017e047f230041d0006b2202240041f7edcb00ad4280808080f00084100122032900002104200241086a41086a200341086a290000370300200220043703082003103541f393ca00ad4280808080a00184100122032900002104200241186a41086a200341086a29000037030020022004370318200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad42808080808004841003220129000037033820011035200241cc006a200341206a360200200220033602482002200241386a41086a3602442002200241386a360240200241286a200241c0006a107b200310352002280230220541206a2201417f4c0d01200228022821060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a2000200136020820002008360204200020033602000240200228022c450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000bda0503027f017e047f230041d0006b2202240041f7edcb00ad4280808080f00084100122032900002104200241086a41086a200341086a29000037030020022004370308200310354189aac000ad4280808080900184100122032900002104200241186a41086a200341086a29000037030020022004370318200310350240024002400240410410332203450d0020034104412010372203450d0320032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a290000370000200128022021052003412041c00010372201450d032001200536002020022001ad4280808080c004841003220329000037033820031035200241cc006a200141246a360200200220013602482002200241386a41086a3602442002200241386a360240200241286a200241c0006a107b200110352002280230220641206a2203417f4c0d01200228022821070240024020030d0041002105410121010c010b200310332201450d01200321050b024002402005410f4d0d00200521080c010b200541017422084110200841104b1b22084100480d03024020050d002008103322010d010c050b20052008460d0020012005200810372201450d040b20012002290308370000200141086a200241086a41086a2903003700000240024020084170714110460d00200821050c010b200841017422054120200541204b1b22054100480d0320082005460d0020012008200510372201450d040b20012002290318370010200141186a200241186a41086a29030037000002400240200541606a2006490d00200521080c010b2006415f4b0d03200541017422082003200820034b1b22084100480d0320052008460d0020012005200810372201450d040b200141206a20072006109d081a2000200336020820002008360204200020013602000240200228022c450d00200710350b200241d0006a24000f0b1045000b1044000b103e000b103c000bc20503027f017e047f230041d0006b2202240041f7edcb00ad4280808080f00084100122032900002104200241086a200341086a290000370300200220043703002003103541c6a9c000ad4280808080e00084100122032900002104200241106a41086a200341086a29000037030020022004370310200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100422012900002104200241306a41086a200141086a2900003703002002200437033020011035200241cc006a200341206a360200200220033602482002200241306a41106a3602442002200241306a360240200241206a200241c0006a107b200310352002280228220541206a2201417f4c0d01200228022021060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290300370000200341086a200241086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290310370010200341186a200241106a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a20002001360208200020083602042000200336020002402002280224450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000bfc0403027f017e057f230041d0006b2202240041f7edcb00ad4280808080f00084100122032900002104200241086a41086a200341086a290000370300200220043703082003103541feedcb00ad4280808080d00284100122032900002104200241186a41086a200341086a2900003703002002200437031820031035200220013602342002200241346aad4280808080c000841003220329000037033820031035200241cc006a200241386a3602002002200241386a41086a3602442002200241346a3602482002200241386a360240200241286a200241c0006a107b02400240024002402002280230220541206a2206417f4c0d00200228022821070240024020060d0041002101410121030c010b200610332203450d02200621010b024002402001410f4d0d00200121080c010b200141017422084110200841104b1b22084100480d03024020010d002008103322030d010c050b20012008460d0020032001200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821010c010b200841017422014120200141204b1b22014100480d0320082001460d0020032008200110372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200141606a2005490d00200121080c010b200541206a22082005490d03200141017422092008200920084b1b22084100480d0320012008460d0020032001200810372203450d040b200341206a20072005109d081a2000200636020820002008360204200020033602000240200228022c450d00200710350b200241d0006a24000f0b1044000b1045000b103e000b103c000bb10503027f017e047f230041d0006b2202240041f7edcb00ad4280808080f00084100122032900002104200241086a41086a200341086a290000370300200220043703082003103541cca9c000ad4280808080a00184100122032900002104200241186a41086a200341086a29000037030020022004370318200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad42808080808004841003220129000037033820011035200241cc006a200341206a360200200220033602482002200241386a41086a3602442002200241386a360240200241286a200241c0006a107b200310352002280230220541206a2201417f4c0d01200228022821060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a2000200136020820002008360204200020033602000240200228022c450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000bb10503027f017e047f230041d0006b2202240041f7edcb00ad4280808080f00084100122032900002104200241086a41086a200341086a290000370300200220043703082003103541fca9c000ad4280808080d00184100122032900002104200241186a41086a200341086a29000037030020022004370318200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad42808080808004841003220129000037033820011035200241cc006a200341206a360200200220033602482002200241386a41086a3602442002200241386a360240200241286a200241c0006a107b200310352002280230220541206a2201417f4c0d01200228022821060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a2000200136020820002008360204200020033602000240200228022c450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000b890603027f017e047f230041d0006b2202240041f7edcb00ad4280808080f00084100122032900002104200241186a41086a200341086a290000370300200220043703182003103541fca9c000ad4280808080d00184100122032900002104200241286a41086a200341086a2900003703002002200437032820031035200128020021010240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad428080808080048410032201290000370348200110352002410c6a200341206a360200200220033602082002200241c8006a41086a3602042002200241c8006a360200200241386a2002107b200310352002280240220541206a2201417f4c0d01200228023821060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290318370000200341086a200241186a41086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290328370010200341186a200241286a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a0240200228023c450d00200610350b20022003200110bc01200241286a41086a2207200241086a280200360200200220022903003703280240200228020c2201450d002000200229032837020020002002290310370210200041086a20072802003602000b2000200136020c02402008450d00200310350b200241d0006a24000f0b1045000b1044000b103e000b103c000ba20503067f017e027f230041e0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100510c20102400240200328021022010d002000410036020c0c010b200328021421042003200341186a2802002202360224200320013602200240024020024104490d002003200141046a36022020032002417c6a220536022420054104490d00200128000021062003200141086a3602202003200241786a220536022420054104490d00200128000421052003200241746a36022420032001410c6a360220200128000821072003200341206a10c40120032802000d002003280224220820032802044102742202490d0002400240024002402002417f4c0d000240024020020d00420021094101210a0c010b20021039220a450d02200a2003280220220b2002109d081a2003200820026b3602242003200b20026a3602202002ad21090b200a450d04024020092002ad422086842209422088a722020d002009a721020c030b0240200a2002724103710d002009a722024103710d0020024102762208450d032009422288a7210b0c040b2009a7450d04200a10350c040b1044000b1045000b4100210b02402002450d00200a10350b410021084104210a0b41000d00200a450d00200020083602102000200a36020c200020073602082000200536020420002006360200200041146a200b3602000c010b20034100360230200342013703282003410936023c2003200341086a3602382003200341286a360244200341dc006a41013602002003420137024c200341c888c2003602482003200341386a360258200341c4006a41e88ac500200341c8006a10431a200335023042208620033502288410060240200328022c450d00200328022810350b2000410036020c0b2004450d00200110350b200341e0006a24000bfc0403027f017e057f230041d0006b2202240041f7edcb00ad4280808080f00084100122032900002104200241086a41086a200341086a290000370300200220043703082003103541efb5c000ad4280808080e00184100122032900002104200241186a41086a200341086a2900003703002002200437031820031035200220013602342002200241346aad4280808080c000841003220329000037033820031035200241cc006a200241386a3602002002200241386a41086a3602442002200241346a3602482002200241386a360240200241286a200241c0006a107b02400240024002402002280230220541206a2206417f4c0d00200228022821070240024020060d0041002101410121030c010b200610332203450d02200621010b024002402001410f4d0d00200121080c010b200141017422084110200841104b1b22084100480d03024020010d002008103322030d010c050b20012008460d0020032001200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821010c010b200841017422014120200141204b1b22014100480d0320082001460d0020032008200110372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200141606a2005490d00200121080c010b200541206a22082005490d03200141017422092008200920084b1b22084100480d0320012008460d0020032001200810372203450d040b200341206a20072005109d081a2000200636020820002008360204200020033602000240200228022c450d00200710350b200241d0006a24000f0b1044000b1045000b103e000b103c000bfc0403027f017e057f230041d0006b2202240041f7edcb00ad4280808080f00084100122032900002104200241086a41086a200341086a290000370300200220043703082003103541dcb5c000ad4280808080b00284100122032900002104200241186a41086a200341086a2900003703002002200437031820031035200220013602342002200241346aad4280808080c000841003220329000037033820031035200241cc006a200241386a3602002002200241386a41086a3602442002200241346a3602482002200241386a360240200241286a200241c0006a107b02400240024002402002280230220541206a2206417f4c0d00200228022821070240024020060d0041002101410121030c010b200610332203450d02200621010b024002402001410f4d0d00200121080c010b200141017422084110200841104b1b22084100480d03024020010d002008103322030d010c050b20012008460d0020032001200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821010c010b200841017422014120200141204b1b22014100480d0320082001460d0020032008200110372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200141606a2005490d00200121080c010b200541206a22082005490d03200141017422092008200920084b1b22084100480d0320012008460d0020032001200810372203450d040b200341206a20072005109d081a2000200636020820002008360204200020033602000240200228022c450d00200710350b200241d0006a24000f0b1044000b1045000b103e000b103c000b9b540f047f017e017f017e027f017e067f027e017f017e037f017e087f047e047f230041c0046b22022400200241d0006a41186a22034200370300200241d0006a41106a22044200370300200241d0006a41086a220542003703002002420037035041f7edcb00ad4280808080f000842206100122072900002108200241e0026a41086a2209200741086a290000370300200220083703e0022007103520052009290300370300200220022903e00237035041e4edcb00ad4280808080a0018422081001220a290000210b200241b0036a41086a2207200a41086a2900003703002002200b3703b003200a1035200420022903b003220b37030020024190046a41086a220c200529030037030020024190046a41106a220d200b37030020024190046a41186a220e20072903003703002002200229035037039004200241286a20024190046a412010c0012002280228210f200228022c21102003420037030020044200370300200542003703002002420037035020061001220a290000210b2009200a41086a2900003703002002200b3703e002200a103520052009290300370300200220022903e00237035020081001220a29000021082007200a41086a290000370300200220083703b003200a1035200420022903b0032208370300200c2005290300370300200d2008370300200e20072903003703002002200229035037039004410121054100210a2002201041016a4100200f1b221136025020024190046aad42808080808004842212200241d0006aad22134280808080c00084100220061001220329000021062009200341086a290000370300200220063703e0022003103541feedcb00ad4280808080d002841001220929000021062007200941086a290000370300200220063703b00320091035200220113602f0032002200241f0036aad4280808080c00084100322092900003703900420091035200241dc006a200241f4036a3602002002200c3602542002200241f0036a360258200220024190046a36025020024190026a200241d0006a107b024002400240024002400240024002400240024002400240024002400240200228029802220341206a220c417f4c0d00200228029002210d0240200c450d00200c10332205450d07200c210a0b02400240200a410f4d0d00200a21070c010b200a41017422094110200941104b1b22074100480d0b0240200a0d002007103322050d010c100b200a2007460d002005200a200710372205450d0f0b200520022903e002370000200541086a200241e0026a41086a2903003700000240024020074170714110460d00200721090c010b200741017422094120200941204b1b22094100480d0b20072009460d0020052007200910372205450d0f0b200520022903b003370010200541186a200241b0036a41086a29030037000002400240200941606a2003490d00200921070c010b200341206a22072003490d0b2009410174220a2007200a20074b1b22074100480d0b20092007460d0020052009200710372205450d0f0b200541206a200d2003109d081a0240200228029402450d00200d10350b20022001360250200cad4220862005ad8420134280808080c00084100202402007450d00200510350b200241d0006a41186a220a4200370300200241d0006a41106a22144200370300200241d0006a41086a220542003703002002420037035041f7edcb00ad4280808080f000842206100122072900002108200241e0026a41086a2209200741086a290000370300200220083703e0022007103520052009290300370300200220022903e00237035041b5edcb00ad4280808080c001841001220c2900002108200241b0036a41086a2207200c41086a290000370300200220083703b003200c1035200420022903b003370000200441086a200729030037000020024190046a41086a200529030037030020024190046a41106a201429030037030020024190046a41186a200a2903003703002002200229035037039004200241206a20024190046a412010c00102402011200228022441016a41d50020022802201b6b220c20114b0d00200c10c1010b200a420037030020144200370300200542003703002002420037035020061001220a29000021062009200a41086a290000370300200220063703e002200a103520052009290300370300200220022903e00237035041b3b6c000ad4280808080d001841001220929000021062007200941086a290000370300200220063703b00320091035201420022903b0032206370300200241306a41086a2005290300370300200241306a41106a2006370300200241306a41186a200729030037030020022002290350370330200241203602d4012002200241306a3602d001200241d8016a200241306aad42808080808004842215100510c20120022802d8012216450d0520022802dc0121172002200241d8016a41086a2802003602ec01200220163602e801200241d0006a200241e8016a10c30120022802502218450d03200241d0006a41086a35020021192002280254211a200241186a200241e8016a10c40120022802180d01200228021c221b20022802ec01220741d0006e22052005201b4b1bad42d0007e2206422088a70d002006a72205417f4c0d000240024020050d004108211c0c010b20051033221c450d070b4100210a200241003602f8012002201c3602f0012002200541d0006e221d3602f4010240201b450d00200241b4046a211e200241d0006a41206a211f4100210a4100210c02400340200241003a00d003200c41016a210c41002105024002400240034020072005460d01200241b0036a20056a20022802e80122092d00003a00002002200941016a3602e8012002200541016a22093a00d0032009210520094120470d000b200241f0036a41086a2205200241b0036a41086a2203290300370300200241f0036a41106a220d200241b0036a41106a2201290300370300200241f0036a41186a220e200241b0036a41186a220f290300370300200220022903b0033703f0032002200720096b3602ec0120024190046a200241e8016a10c50120022802b00422090d01410021090c020b200241003602ec010240200541ff0171450d00200241003a00d0030b410021090c010b201f200229039004370300200241d0006a41186a2207200e290300370300200241d0006a41106a220e200d290300370300200241d0006a41086a220d2005290300370300201f41086a20024190046a41086a290300370300201f41106a20024190046a41106a290300370300201f41186a20024190046a41186a290300370300200241a0036a41086a201e41086a280200360200200220022903f0033703502002201e2902003703a003200241b0036a41386a200241d0006a41386a290300370300200241b0036a41306a200241d0006a41306a290300370300200241b0036a41286a200241d0006a41286a290300370300200241b0036a41206a201f290300370300200f20072903003703002001200e2903003703002003200d290300370300200220022903503703b0030b200241e0026a41386a2205200241b0036a41386a290300370300200241e0026a41306a2207200241b0036a41306a290300370300200241e0026a41286a2203200241b0036a41286a290300370300200241e0026a41206a220d200241b0036a41206a290300370300200241e0026a41186a2201200241b0036a41186a290300370300200241e0026a41106a220e200241b0036a41106a290300370300200241e0026a41086a220f200241b0036a41086a290300370300200241d0026a41086a2210200241a0036a41086a280200360200200220022903b0033703e002200220022903a0033703d00202402009450d0020024190026a41386a2220200529030037030020024190026a41306a2221200729030037030020024190026a41286a2207200329030037030020024190026a41206a2203200d29030037030020024190026a41186a220d200129030037030020024190026a41106a2201200e29030037030020024190026a41086a220e200f29030037030020024180026a41086a220f2010280200360200200220022903e00237039002200220022903d002370380020240200a20022802f401470d00200241f0016a200a410110a30120022802f001211c20022802f801210a0b201c200a41d0006c6a220520022903900237030020012903002106200d29030021082003290300210b200729030021222021290300212320202903002124200e290300212520052009360240200541086a20253703002005200229038002370244200541cc006a200f280200360200200541386a2024370300200541306a2023370300200541286a2022370300200541206a200b370300200541186a2008370300200541106a20063703002002200a41016a220a3602f801200c201b460d0220022802ec0121070c010b0b0240200a450d00200a41d0006c2109201c41c4006a21050340024020052802002207450d00200741306c450d002005417c6a28020010350b200541d0006a2105200941b07f6a22090d000b0b20022802f4012205450d03200541d0006c450d03201c10350c030b20022802f401211d0b201c450d010240024020022802ec012205450d0020022005417f6a3602ec01200220022802e801220541016a3602e80120052d000022264103490d010b0240200a450d00200a41d0006c2109201c41c4006a21050340024020052802002207450d00200741306c450d002005417c6a28020010350b200541d0006a2105200941b07f6a22090d000b0b0240201d450d00201d41d0006c450d00201c10350b201a41ffffff3f71450d040c030b2019422086201aad8421240c040b1044000b201a41ffffff3f71450d010b201810350b200241003602b803200242013703b003200241093602e4022002200241d0016a3602e0022002200241b0036a36029002200241e4006a410136020020024201370254200241c888c2003602502002200241e0026a36026020024190026a41e88ac500200241d0006a10431a20023502b80342208620023502b003841006024020022802b403450d0020022802b00310350b410321260b02402017450d00201610350b20264103460d00201510070c040b200241003602d802200242083703d002200241003602a803200242013703a00341f7edcb00ad4280808080f00084100122052900002106200241e0026a41086a2209200541086a290000370300200220063703e0022005103541f393ca00ad4280808080a00184100122052900002106200241b0036a41086a2207200541086a290000370300200220063703b00320051035412010332205450d00200520022903e002370000200520022903b003370010200541086a2009290300370000200541186a220a2007290300370000412010332209450d0020092005290000370000200941186a200a290000370000200941106a200541106a290000370000200941086a200541086a290000370000200241306a41026a220a200241d0006a41026a2d00003a0000200220022f00503b0130200241f0036a41106a42a0808080800437030041002107200241003a008804200220053602fc03200242a080808080043702f403200220093602f0032002418b046a200a2d00003a0000200220022f01303b008904200241d0006a200241f0036a10c701024020022802504101470d00200241d0006a410472210a410121164108211b4100210c0340200241b0036a41206a200a41206a280200360200200241b0036a41186a2205200a41186a2902002206370300200241b0036a41106a2209200a41106a2902002208370300200241b0036a41086a2220200a41086a290200220b3703002002200a29020022223703b00320024190026a41186a220e200637030020024190026a41106a220f200837030020024190026a41086a2210200b3703002002202237039002200241d0006a41186a22032005290300370300200241d0006a41106a220d2009290300370300200241d0006a41086a22012020290300370300200220022903b00337035020024190026a10c8012106412010332209450d0a2009200229039002370000200941186a200e290300370000200941106a200f290300370000200941086a2010290300370000200241e0026a41086a20012903002208370300200241e0026a41106a200d290300220b370300200241e0026a41186a200329030022223703002002200229035022233703e00220024190046a41186a2220202237030020024190046a41106a2221200b37030020024190046a41086a221f200837030020022023370390040240200c20022802d402470d00200241d0026a200c4101108b0120022802d002211b20022802d802210c0b201b200c41386c6a22052006370300201f2903002106202129030021082020290300210b20022903900421222005412c6a4281808080103702002005200936022820052022370308200541206a200b370300200541186a2008370300200541106a20063703002002200c41016a220c3602d8022003200e290300370300200d200f2903003703002001201029030037030020022002290390023703500240200720022802a403470d00200241a0036a20074101108a0120022802a003211620022802a80321070b201620074105746a22052002290350370000200541186a2003290300370000200541106a200d290300370000200541086a20012903003700002002200741016a22073602a803200241d0006a200241f0036a10c70120022802504101460d000b0b024020022802f403450d0020022802f00310350b0240200228028004450d0020022802fc0310350b41f7edcb00ad4280808080f00084100122052900002106200241e0026a41086a2209200541086a290000370300200220063703e0022005103541cca9c000ad4280808080a00184100122052900002106200241b0036a41086a2207200541086a290000370300200220063703b00320051035412010332205450d00200520022903e002370000200520022903b003370010200541086a2009290300370000200541186a220a2007290300370000412010332209450d0020092005290000370000200941186a200a290000370000200941106a200541106a290000370000200941086a200541086a29000037000020024190026a41026a220a200241d0006a41026a2d00003a0000200220022f00503b019002200241d0006a41106a220742a080808080043703002002200536025c200242a0808080800437025420022009360250200241003a0068200241eb006a200a2d00003a0000200220022f0190023b0069200241d0026a200241d0006a10c901200241d0006a41186a220a420037030020074200370300200241d0006a41086a220542003703002002420037035041f7edcb00ad4280808080f000842206100122092900002108200241e0026a41086a220c200941086a290000370300200220083703e002200910352005200c290300370300200220022903e00237035041c1edcb00ad4280808080e00184100122032900002108200241b0036a41086a2209200341086a290000370300200220083703b00320031035201420022903b003370000201441086a220d2009290300370000200241306a41086a22012005290300370300200241306a41106a220e2007290300370300200241306a41186a220f200a29030037030020022002290350370330200241106a200241306a412010c0012002280214211020022802102120200a42003703002007420037030020054200370300200242003703502006100122032900002106200c200341086a290000370300200220063703e002200310352005200c290300370300200220022903e00237035041cfedcb00ad4280808080d002841001220c29000021062009200c41086a290000370300200220063703b003200c1035201420022903b003370000200d200929030037000020012005290300370300200e2007290300370300200f200a29030037030020022002290350370330200241086a200241306a412010c001200228020c21072002280208210a2009200241a0036a41086a280200360200200220022903a0033703b0032005200241d0026a41086a280200360200200220022903d00237035020024190046a2010410020201b20074104200a1b22054101200541014b1b200241b0036a200241d0006a10ca01024020022802900422170d00410321260c040b200241a4046a280200210c20024190046a41106a28020021162002419c046a280200211f20024190046a41086a2802002105200228029404211b2002410036025820024201370350200241d0006a4100200541306c220741306e108a012002280258210a0240024020070d00200228025021180c010b20022802502218200a4105746a210520172109034020052009290000370000200541186a200941186a290000370000200541106a200941106a290000370000200541086a200941086a290000370000200a41016a210a200541206a2105200941306a2109200741506a22070d000b0b20023502542108200241003602f803200242043703f003200241f0036a4100200c412c6c2205412c6d109801201f20056a210d20022802f803210320022802f00321210240200c0d00201f21050c020b200241b0036a410c6a212020212003412c6c6a2109200241b0036a410472210720024190026a41206a210120024190026a41186a210e20024190026a41106a210f20024190026a41086a2110201f210503402005280200210c2001200541246a290200370300200e2005411c6a290200370300200f200541146a29020037030020102005410c6a2902003703002002200541046a290200370390020240200c0d002005412c6a21050c030b2007200229039002370200200741086a2010290300370200200741106a200f290300370200200741186a200e290300370200200741206a20012903003702002002200c3602b003202010c8012106200241d0006a41286a200241b0036a41286a280200360200200241d0006a41206a200241b0036a41206a290300370300200241d0006a41186a200241b0036a41186a290300370300200241d0006a41106a200241b0036a41106a290300370300200241d0006a41086a200241b0036a41086a290300370300200220022903b003370350200241e0026a200241d0006a2006420010cb01200941286a200241e0026a41286a280200360200200941206a200241e0026a41206a290300370200200941186a200241e0026a41186a290300370200200941106a200241e0026a41106a290300370200200941086a200241e0026a41086a290300370200200920022903e002370200200341016a21032009412c6a21092005412c6a2205200d470d000b200220033602f8030c020b1045000b200220033602f8032005200d460d00034020052209412c6a21050240200941046a2802002207450d00200741246c450d00200928020010350b200d2005470d000b0b02402016450d002016412c6c450d00201f10350b20022802f403210d200241d0006a2018200a2021200310cc01024002402002280250220c0d00410021054100210c410021010c010b2002280258210102400240200228025422090d00200c21050c010b20092105200c2107034020072802c80521072005417f6a22050d000b200c21050340200520052f01064102746a41c8056a28020021052009417f6a22090d000b2007210c0b20052f010621090b200241ec006a2009360200200241e8006a4100360200200241e4006a20053602002002200136027020024100360260200242003703582002200c36025420024100360250200aad21062002200241306a360274200241b0036a200241d0006a10cd0120022802b003211c20022802b403211d20022802b803210a02402003450d002003412c6c21092021210503400240200541046a2802002207450d00200741306c450d00200528020010350b2005412c6a2105200941546a22090d000b0b200642208621060240200d450d00200d412c6c450d00202110350b2006200884212441002126201b450d00201b41306c450d00201710350b200241d0006a41186a22094200370300200241d0006a41106a22074200370300200241d0006a41086a220542003703002002420037035041f7edcb00ad4280808080f0008422081001220c2900002106200241e0026a41086a2203200c41086a290000370300200220063703e002200c103520052003290300370300200220022903e00237035041ceeecb00ad4280808080b001841001220c2900002106200241b0036a41086a220d200c41086a290000370300200220063703b003200c1035201420022903b003370000201441086a200d290300370000200241306a41086a2005290300370300200241306a41106a2007290300370300200241306a41186a200929030037030020022002290350370330201510074100210c20264103460d032009420037030020074200370300200542003703002002420037035020081001220c29000021062003200c41086a290000370300200220063703e002200c103520052003290300370300200220022903e00237035041b6aac000ad42808080809002841001220c2900002106200d200c41086a290000370300200220063703b003200c1035200420022903b003370000200441086a200d29030037000020024190046a41086a200529030037030020024190046a41106a200729030037030020024190046a41186a20092903003703002002200229035037039004410110332205450d04200541003a000020122005ad4280808080108410022005103542002108200241d0006a41186a22274200370300200241d0006a41106a22284200370300200241d0006a41086a221a42003703002002420037035041f7edcb00ad4280808080f00084220610012205290000210b200241e0026a41086a2229200541086a2900003703002002200b3703e00220051035201a2029290300370300200220022903e0023703504192aac000ad4280808080a0028410012205290000210b200241b0036a41086a220e200541086a2900003703002002200b3703b00320051035200420022903b003370000200441086a2209200e29030037000020024190046a41086a2221201a29030037030020024190046a41106a221f202829030037030020024190046a41186a221620272903003703002002200229035037039004201210072027420037030020284200370300201a42003703002002420037035020061001220529000021062029200541086a290000370300200220063703e00220051035201a2029290300370300200220022903e00237035041a4aac000ad4280808080a00284100122052900002106200e200541086a290000370300200220063703b00320051035200420022903b0033700002009200e2903003700002021201a290300370300201f202829030037030020162027290300370300200220022903503703900420121007201c200a41d0006c6a21200240200a0d00201c210d420021060c020b200241e0026a41106a211b20024190026a41106a210f200241b4026a2104200241d0006a41206a21014200210842002106201c210d0340200241b0036a41386a220a200d220541386a290300370300200241b0036a41306a220c200541306a290300370300200241b0036a41286a2203200541286a290300370300200241b0036a41206a2210200541206a290300370300200241b0036a41186a2209200541186a290300370300200241b0036a41106a2207200541106a290300370300200e200541086a2903003703002005290300210b200241d0026a41086a2214200541cc006a2802003602002002200b3703b0032002200541c4006a2902003703d002200541d0006a210d200541c0006a2802002205450d02200241d0006a41386a200a290300370300200241d0006a41306a200c290300370300200241d0006a41286a2003290300370300200120102903003703002027200929030037030020282007290300370300201a200e290300370300200220022903b003370350200241f0036a41186a2009290300370300200241f0036a41106a2007290300370300200241f0036a41086a200e290300370300200220022903b0033703f00320024190026a41186a2217200141186a290300370300200f200141106a29030037030020024190026a41086a221e200141086a290300220b370300200220053602b00220022001290300222237039002200420022903d002370200200441086a201428020036020020024190046a2011200241f0036a10ce0120023502980421232002280290042110200241003602e802200242013703e002200220024190026a360230200241306a200241e0026a10cf012002200f360230200241306a200241e0026a10cf0120022802b002210520022802b8022209200241e0026a107702402009450d00200941306c210c03400240024020022802e402220a20022802e80222096b4120490d0020022802e00221070c010b200941206a22072009490d04200a41017422032007200320074b1b22034100480d0402400240200a0d00024020030d00410121070c020b200310332207450d0a0c010b20022802e0022107200a2003460d002007200a200310372207450d090b200220033602e402200220073602e0020b200720096a2207200541106a290000370000200741186a200541286a290000370000200741106a200541206a290000370000200741086a200541186a2900003700002002200941206a3602e80220022005360230200241306a200241e0026a10cf01200541306a2105200c41506a220c0d000b0b20022802e402210520234220862010ad8420023502e80242208620022802e0022209ad84100202402005450d00200910350b0240200228029404450d00201010350b20162017290300370300201f200f2903003703002021201e29030037030020022002290390023703900420022802bc02210720022802b402210a20022802b0022109024020022802b802220541c100490d0020092005410041202005676b10d00141c00021050b200241e0026a41186a2016290300370300201b201f2903003703002029202129030037030020022002290390043703e0022002200736028c0320022005360288032002200a360284032002200936028003200241a0036a2011200241f0036a10d10120023502a803212320022802a003211020024100360238200242013703302002200241e0026a3602800220024180026a200241306a10cf012002201b3602800220024180026a200241306a10cf0120022802800321052002280288032209200241306a107702402009450d00200941306c210c0340024002402002280234220a200228023822096b4120490d00200228023021070c010b200941206a22072009490d04200a41017422032007200320074b1b22034100480d0402400240200a0d00024020030d00410121070c020b200310332207450d0a0c010b20022802302107200a2003460d002007200a200310372207450d090b20022003360234200220073602300b200720096a2207200541106a290000370000200741186a200541286a290000370000200741106a200541206a290000370000200741086a200541186a2900003700002002200941206a360238200220053602800220024180026a200241306a10cf01200541306a2105200c41506a220c0d000b0b2006200b7c200820227c220b2008542205ad7c21082002280234210920234220862010ad84200235023842208620022802302207ad84100202402009450d00200710350b2008200651210920082006542107024020022802a403450d00201010350b2005200720091b210502402002280284032209450d00200941306c450d0020022802800310350b427f200820051b2106427f200b20051b2108200d2020470d000c030b0b103e000b2020200d460d000340200d220541d0006a210d0240200541c4006a2802002209450d00200941306c450d00200541c0006a28020010350b2020200d470d000b0b0240201d450d00201d41d0006c450d00201c10350b200241b0036a201110bd0120022802b003210520023502b803210b2002200637035820022008370350200b4220862005ad84201342808080808002841002024020022802b403450d00200510350b02402024422088a7410574220a450d00200241b0036aad210b201821050340200241d0006a200510b501200220022802502207200228025810d2012002280204410020022802001b210902402002280254450d00200710350b200241d0006a2011200510d3012002350258210620022802502107200241003a00b5030240024002400240200941c000490d00200941808001490d012009418080808004490d02200241053a00b503200241033a00b003200220093600b1034280808080d00021080c030b200241013a00b503200220094102743a00b00342808080801021080c020b200241023a00b503200220094102744101723b01b00342808080802021080c010b200241043a00b503200220094102744102723602b0034280808080c00021080b20064220862007ad842008200b841002024020022d00b503450d00200241003a00b5030b02402002280254450d00200710350b200541206a2105200a41606a220a0d000b0b200241d9006a20263a0000200241d8006a41043a0000200241043a005041b0b4cc004100200241d0006a10d4012018210c0b200020243702042000200c360200200241c0046a24000f0b103c000b8f0201037f230041d0006b220324002003200236020420032001360200200341086a2002ad4220862001ad84100510c20102400240200328020822040d00410021010c010b200328020c210502400240200341106a2802004104490d0020042800002102410121010c010b4100210120034100360220200342013703182003410936022c200320033602282003200341186a360234200341cc006a41013602002003420137023c200341c888c2003602382003200341286a360248200341346a41e88ac500200341386a10431a200335022042208620033502188410060240200328021c450d00200328021810350b0b2005450d00200410350b2000200236020420002001360200200341d0006a24000bd71704027f017e077f017e230041d0006b2201240041f7edcb00ad4280808080f00084100122022900002103200141086a41086a200241086a290000370300200120033703082002103541e4b6c000ad4280808080b00184100122022900002103200141186a41086a200241086a2900003703002001200337031820021035200120003602342001200141346aad22034280808080c000841003220229000037033820021035200141cc006a200141386a3602002001200141386a41086a22043602442001200141346a3602482001200141386a360240200141286a200141c0006a107b02400240024002402001280230220541206a2206417f4c0d00200128022821070240024020060d0041002108410121020c010b200610332202450d02200621080b024002402008410f4d0d00200821090c010b200841017422094110200941104b1b22094100480d03024020080d002009103322020d010c050b20082009460d0020022008200910372202450d040b20022001290308370000200241086a200141086a41086a2903003700000240024020094170714110460d00200921080c010b200941017422084120200841204b1b22084100480d0320092008460d0020022009200810372202450d040b20022001290318370010200241186a200141186a41086a29030037000002400240200841606a2005490d00200821090c010b200541206a22092005490d032008410174220a2009200a20094b1b22094100480d0320082009460d0020022008200910372202450d040b200241206a20072005109d081a0240200128022c450d00200710350b2006ad4220862002ad84100802402009450d00200210350b41f7edcb00ad4280808080f0008410012202290000210b200141086a41086a200241086a2900003703002001200b3703082002103541d2b6c000ad4280808080a0028410012202290000210b200141186a41086a200241086a2900003703002001200b3703182002103520012000360234200120034280808080c000841003220229000037033820021035200141cc006a200141386a360200200120043602442001200141346a3602482001200141386a360240200141286a200141c0006a107b2001280230220541206a2208417f4c0d00200128022821070240024020080d0041002109410121020c010b200810332202450d02200821090b024002402009410f4d0d00200921060c010b200941017422064110200641104b1b22064100480d03024020090d00200610332202450d050c010b20092006460d0020022009200610372202450d040b20022001290308370000200241086a200141086a41086a2903003700000240024020064170714110460d00200621090c010b200641017422094120200941204b1b22094100480d0320062009460d0020022006200910372202450d040b20022001290318370010200241186a200141186a41086a29030037000002400240200941606a2005490d00200921060c010b2005415f4b0d03200941017422062008200620084b1b22064100480d0320092006460d0020022009200610372202450d040b200241206a20072005109d081a0240200128022c450d00200710350b2008ad4220862002ad84100802402006450d00200210350b41f7edcb00ad4280808080f0008410012202290000210b200141086a41086a200241086a2900003703002001200b3703082002103541c0b6c000ad4280808080a0028410012202290000210b200141186a41086a200241086a2900003703002001200b3703182002103520012000360234200120034280808080c000841003220229000037033820021035200141cc006a200141386a360200200120043602442001200141346a3602482001200141386a360240200141286a200141c0006a107b2001280230220541206a2208417f4c0d00200128022821070240024020080d0041002109410121020c010b200810332202450d02200821090b024002402009410f4d0d00200921060c010b200941017422064110200641104b1b22064100480d03024020090d00200610332202450d050c010b20092006460d0020022009200610372202450d040b20022001290308370000200241086a200141086a41086a2903003700000240024020064170714110460d00200621090c010b200641017422094120200941204b1b22094100480d0320062009460d0020022006200910372202450d040b20022001290318370010200241186a200141186a41086a29030037000002400240200941606a2005490d00200921060c010b2005415f4b0d03200941017422062008200620084b1b22064100480d0320092006460d0020022009200610372202450d040b200241206a20072005109d081a0240200128022c450d00200710350b2008ad4220862002ad84100802402006450d00200210350b41f7edcb00ad4280808080f0008410012202290000210b200141086a41086a200241086a2900003703002001200b3703082002103541dcb5c000ad4280808080b0028410012202290000210b200141186a41086a200241086a2900003703002001200b3703182002103520012000360234200120034280808080c000841003220229000037033820021035200141cc006a200141386a360200200120043602442001200141346a3602482001200141386a360240200141286a200141c0006a107b2001280230220541206a2208417f4c0d00200128022821070240024020080d0041002109410121020c010b200810332202450d02200821090b024002402009410f4d0d00200921060c010b200941017422064110200641104b1b22064100480d03024020090d00200610332202450d050c010b20092006460d0020022009200610372202450d040b20022001290308370000200241086a200141086a41086a2903003700000240024020064170714110460d00200621090c010b200641017422094120200941204b1b22094100480d0320062009460d0020022006200910372202450d040b20022001290318370010200241186a200141186a41086a29030037000002400240200941606a2005490d00200921060c010b2005415f4b0d03200941017422062008200620084b1b22064100480d0320092006460d0020022009200610372202450d040b200241206a20072005109d081a0240200128022c450d00200710350b2008ad4220862002ad84100702402006450d00200210350b200141c0006a200010ad01200135024842208620012802402202ad84100702402001280244450d00200210350b41f7edcb00ad4280808080f0008410012202290000210b200141086a41086a200241086a2900003703002001200b3703082002103541efb5c000ad4280808080e0018410012202290000210b200141186a41086a200241086a2900003703002001200b3703182002103520012000360234200120034280808080c000841003220229000037033820021035200141cc006a200141386a360200200120043602442001200141346a3602482001200141386a360240200141286a200141c0006a107b2001280230220641206a2208417f4c0d00200128022821050240024020080d0041002104410121020c010b200810332202450d02200821040b024002402004410f4d0d00200421090c010b200441017422094110200941104b1b22094100480d03024020040d00200910332202450d050c010b20042009460d0020022004200910372202450d040b20022001290308370000200241086a200141086a41086a2903003700000240024020094170714110460d00200921040c010b200941017422044120200441204b1b22044100480d0320092004460d0020022009200410372202450d040b20022001290318370010200241186a200141186a41086a29030037000002400240200441606a2006490d00200421090c010b2006415f4b0d03200441017422092008200920084b1b22094100480d0320042009460d0020022004200910372202450d040b200241206a20052006109d081a0240200128022c450d00200510350b2008ad4220862002ad84100702402009450d00200210350b200141c0006a200010b801200135024842208620012802402202ad84100702402001280244450d00200210350b200141d0006a24000f0b1044000b1045000b103e000b103c000bb10201067f230041206b22022400024002402001422088a722030d00410121040c010b2001a721040b200220033602142002200436021002402003450d0020042d0000210520022003417f6a3602142002200441016a360210200541014b0d0041002106024002400240024020050e020100010b200241086a200241106a10c40120022802080d0320022802142205200228020c2203490d032003417f4c0d010240024020030d0042002101410121060c010b200310392206450d032006200228021022072003109d081a2002200520036b3602142002200720036a3602102003ad21010b2006450d0320012003ad4220868421010b200020013702042000200636020020041035200241206a24000f0b1044000b1045000b41b89acc00412e200241186a41c09bcc0041e89acc001046000ba20401097f230041e0006b220224002002200110c40102400240024002402002280200450d00200041003602000c010b2002280204220320012802044105762204200420034b1b22044105742205417f4c0d010240024020040d00410121060c010b200510332206450d030b41002107200241003602102002200436020c20022006360208024002402003450d0041002108034041002105200241003a0058200841016a21082001280204417f6a210403402004417f460d03200241386a20056a200128020022092d00003a0000200120043602042001200941016a3602002002200541016a22093a00582004417f6a21042009210520094120470d000b200241186a41186a2205200241386a41186a290300370300200241186a41106a2209200241386a41106a290300370300200241186a41086a220a200241386a41086a2903003703002002200229033837031802402007200228020c470d00200241086a20074101108a0120022802082106200228021021070b200620074105746a22042002290318370000200441186a2005290300370000200441106a2009290300370000200441086a200a2903003700002002200741016a220736021020082003470d000b0b20002002290308370200200041086a200241086a41086a2802003602000c010b0240200541ff0171450d00200241003a00580b20004100360200200228020c41ffffff3f71450d00200610350b200241e0006a24000f0b1044000b1045000bcf0201067f0240024020012802042202450d00200128020022032d0000210420012002417f6a2205360204410121062001200341016a3602000240200441037122074103460d0002400240024020070e03000102000b20044102762107410021060c040b41012106024020050d000c040b20032d0001210520012002417e6a3602042001200341026a3602002005410874200472220141ffff0371418002490d03200141fcff03714102762107410021060c030b20054103490d01200341036a2d0000210620032f0001210720012002417c6a3602042001200341046a3602002007200641107472410874200472220141808004492106200141027621070c020b0240200441034d0d000c020b20054104490d012003280001210720012002417b6a3602042001200341056a36020020074180808080044921060c010b410121060b20002007360204200020063602000b990707017f047e027f017e057f047e017f23004190026b22022400200241c0006a200110f60102400240024002400240024002402002290340a70d00200241c0006a41106a290300210320022903482104200241286a200110f6012002290328a70d03200241286a41106a290300210520022903302106200241206a200110c40120022802200d0220022802242207200128020441306e2208200820074b1bad42307e2209422088a7450d010c060b200041003602200c040b2009a72208417f4c0d040240024020080d004108210a0c010b20081033220a450d030b4100210b200241003602602002200a3602582002200841306e36025c0240024002402007450d004100210c03404100210d200241003a008802200c41016a210c2001280204417f6a210803402008417f460d03200241e8016a200d6a2001280200220e2d00003a0000200120083602042001200e41016a3602002002200d41016a220e3a0088022008417f6a2108200e210d200e4120470d000b200241c8016a41186a2208200241e8016a41186a290300370300200241c8016a41106a220d200241e8016a41106a290300370300200241c8016a41086a220e200241e8016a41086a290300370300200220022903e8013703c801200241086a200110f6012002290308a70d03200241086a41106a29030021092002290310210f20024188016a41086a200e290300221037030020024188016a41106a200d290300221137030020024188016a41186a20082903002212370300200241e8006a41086a220d2010370300200241e8006a41106a220e2011370300200241e8006a41186a22132012370300200220022903c801221037038801200220103703680240200b200228025c470d00200241d8006a200b41011088012002280258210a2002280260210b0b200a200b41306c6a220820093703082008200f37030020082002290368370310200841186a200d290300370300200841206a200e290300370300200841286a20132903003703002002200b41016a220b360260200c2007470d000b0b200a450d02200229025c210920002004370300200020093702242000200a3602202000200637031020002003370308200041186a20053703000c050b200d41ff0171450d00200241003a0088020b20024188016a41086a200241a8016a41086a290300370300200228025c2201450d00200141306c450d00200a10350b200041003602200c020b200041003602200c010b1045000b20024190026a24000f0b1044000bbd0101047f230041106b22022400200028020421032000280200210041012104200128021841d9a0c00041012001411c6a28020028020c1100002105200241003a0005200220053a00042002200136020002402003450d0003402002200036020c20022002410c6a41accfc70010701a200041016a21002003417f6a22030d000b20022d000421050b0240200541ff01710d002002280200220028021841d8a0c00041012000411c6a28020028020c11000021040b200241106a240020040b8a0604057f017e047f037e230041f0006b22022400200241286a200141146a350200422086200135020c84102710c2010240024020022802282203450d00200141086a2104200141106a210503400240024020042802002206200229022c2207422088a722084b0d00200128020022092003460d0120092003200610a008450d010b2007a7450d02200310350c020b02402005280200450d00200128020c10350b2001200336020c2005200737020020022003200810d201024002402002280200450d002002280204210a024020012d0018450d002001350214422086200135020c8410070b2001280214220820042802002203490d0102400240200820036b22084108490d00200841786a2106200128020c20036a41086a21090c010b410021060240410028028cb54c0d0041b0b4cc0021090c010b410021064100280298b54c21034100280294b54c21084100280290b54c210b200241e500360268200242b48080801037036020024187a1c00036025c20024213370254200241f4a0c0003602502002420037034841b0b4cc002109200241b0b4cc0036024420024201370338200241eca0c00036023420024113360230200241f4a0c00036022c20024101360228200841aca2c000200b410246220b1b200241286a200341c4a2c000200b1b2802101102000b41002103200241003a00480240034020062003460d01200241286a20036a200920036a2d00003a00002002200341016a22083a00482008210320084120470d000b200241086a41186a200241286a41186a2903002207370300200241086a41106a200241286a41106a290300220c370300200241086a41086a200241286a41086a290300220d37030020022002290328220e3703082000411c6a2007370000200041146a200c3700002000410c6a200d3700002000200e370004200041246a200a360200200041013602000c050b200341ff0171450d00200241003a00480b200241286a2001350214422086200135020c84102710c201200228022822030d010c020b0b2003200841889aca001059000b200041003602000b200241f0006a24000bda0b04047f017e027f027e23004190026b2201240020014180026a200010b401200141d8006a200128028002220020012802880210d501200141e0016a41086a2202200141e1006a290000370300200141e0016a41106a2203200141e9006a290000370300200141e0016a41186a2204200141f1006a290000370300200120012900593703e0010240024002400240024002400240024020012d00584101470d00200141386a41186a2004290300370300200141386a41106a2003290300370300200141386a41086a2002290300370300200120012903e0013703380240200128028402450d00200010350b200141d8006a41186a2202200141386a41186a290300370300200141d8006a41106a2203200141386a41106a290300370300200141d8006a41086a2204200141386a41086a2903003703002001200129033837035841f7edcb00ad4280808080f00084100122002900002105200141b0016a41086a200041086a290000370300200120053703b0012000103541c6a9c000ad4280808080e00084100122002900002105200141c0016a41086a200041086a290000370300200120053703c00120001035412010332200450d0420002001290358370000200041186a2002290300370000200041106a2003290300370000200041086a20042903003700002000ad428080808080048410042202290000210520014180026a41086a200241086a290000370300200120053703800220021035200141ec016a200041206a360200200120003602e801200120014180026a41106a3602e401200120014180026a3602e001200141d0016a200141e0016a107b2000103520012802d801220641206a2202417f4c0d0520012802d00121070240024020020d0041002103410121000c010b200210332200450d05200221030b024002402003410f4d0d00200321040c010b200341017422044110200441104b1b22044100480d07024020030d002004103322000d010c090b20032004460d0020002003200410372200450d080b200020012903b001370000200041086a200141b0016a41086a2903003700000240024020044170714110460d00200421030c010b200441017422034120200341204b1b22034100480d0720042003460d0020002004200310372200450d080b200020012903c001370010200041186a200141c0016a41086a29030037000002400240200341606a2006490d00200321040c010b2006415f4b0d07200341017422042002200420024b1b22044100480d0720032004460d0020002003200410372200450d080b200041206a20072006109d081a024020012802d401450d00200710350b200141d8006a2000200210d60120012802782203450d01200141f0006a290300210820014188016a280200210620014184016a280200210720012903682109200128027c210202402004450d00200010350b02402002450d00200241186c450d00200310350b200641ffffffff0371450d03200710350c030b200128028402450d01200010350c010b2004450d00200010350b42002109420021080b200141d8006a41186a4200370300200141d8006a41106a22034200370300200141d8006a41086a220042003703002001420037035841b6fdc600ad42808080808001841001220229000021052000200241086a290000370300200120053703582002103541e489c200ad4280808080d00184100122022900002105200141386a41086a2204200241086a2900003703002001200537033820021035200320012903382205370300200141e0016a41086a2000290300370300200141e0016a41106a2005370300200141e0016a41186a2004290300370300200120012903583703e001200141206a200141e0016a412010d701200141106a2001290328200141206a41106a290300427f420010980820012009200820012903104200200128022022001b220542012005420156200141106a41086a290300420020001b22054200522005501b22001b2005420020001b1098082001290300210520014190026a240020050f0b1045000b1044000b103e000b103c000be80808097f017e0c7f017e017f017e017f037e230041f0016b22022400200241086a41186a200141186a280200360200200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241e8006a200241086a10c905024020022d0098014102460d00200041046a21030340200241a0016a41286a200241e8006a41286a280200360200200241a0016a41206a200241e8006a41206a2201290300370300200241a0016a41186a2204200241e8006a41186a2205290300370300200241a0016a41106a2206200241e8006a41106a2207290300370300200241a0016a41086a2208200241e8006a41086a2209290300370300200220022903683703a0012001280200210a0240200229028c01220b422088a7220c450d00200228029401210d4100210e200a21014100210f024002400340200220013602cc01200241d0016a200241cc016a10bb01024002400240024020022802dc012210450d0020022802d8012111024020022802e00141ffffffff0371450d00201010350b2011200d4b0d010b200e0d014100210e0c020b200e41016a210e0c010b200f200e6b2210200c4f0d02200241d0016a41186a22112001200e4105746b221041186a2212290000370300200241d0016a41106a2213201041106a2214290000370300200241d0016a41086a2215201041086a2216290000370300200220102900003703d001200141086a22172900002118200141106a2219290000211a200141186a221b290000211c201020012900003700002012201c3700002014201a37000020162018370000201b20112903003700002019201329030037000020172015290300370000200120022903d0013700000b200141206a2101200c200f41016a220f460d020c000b0b2010200c41f485cc001042000b200e417f6a200c4f0d00200b42ffffffff0f83200c200e6bad42208684210b0b200241c8006a41186a22012004290300370300200241c8006a41106a220e2006290300370300200241c8006a41086a220f2008290300370300200220022903a001370348200a450d01200520012903003703002007200e2903003703002009200f29030037030020022002290348370368200241e8006a10c8012118200241286a41186a2001290300221a370300200241286a41106a200e290300221c370300200241286a41086a200f290300221d37030020022002290348221e3703282005201a3703002007201c3703002009201d3703002002201e3703680240200041086a220f280200220e2003280200470d002000200e4101108b010b2000280200200e41386c6a22012002290368370308200120183703002001200a360228200141106a2009290300370300200141186a2007290300370300200141206a20052903003703002001412c6a200b370200200f200e41016a360200200241e8006a200241086a10c90520022d0098014102470d000b0b0240200228020c450d00200228020810350b0240200241186a280200450d00200228021410350b200241f0016a24000bab2104027f017e107f077e23004190026b2205240020054100360238200541003602300240024002400240200441086a280200200341086a28020022066aad42e0007e2207422088a70d002007a72208417f4c0d0041082109024002402008450d00200810332209450d010b20054100360248200520093602402005200841e0006e3602442003280204210a2003280200210b2005410036029801200542083703900120054190016a410020064105742209410575109b01200528029801210c02402006450d00200941606a410576210d200528029001200c41d8006c6a210e200541f0016a2108200541e8016a210f41002106200b21030340200541a0016a41186a2210200341186a2211290000370300200541a0016a41106a2212200341106a2213290000370300200541a0016a41086a2214200341086a2215290000370300200520032900003703a001200541e0006a41186a2011290000370300200541e0006a41106a2013290000370300200541e0006a41086a201529000037030020052003290000370360200541306a200541e0006a2006108403200541c0016a41086a4200370300200541c0016a41106a4200370300200541c0016a41186a4200370300200541c0016a41206a4200370300200f4200370300200841186a2010290300370000200841106a2012290300370000200841086a2014290300370000200820052903a001370000200542003703c001200e200541c0016a41d000109d08220e41d0006a41003a0000200e41d8006a210e200341206a2103200641016a2106200941606a22090d000b200c200d6a41016a210c0b2005200c360298010240200a41ffffff3f71450d00200b10350b200541d0006a41086a20054190016a41086a2802002203360200200520052903900137035020032002490d032004280204210620042802002103200541c0006a2005280248200441086a28020041386c220941386d10a4012005280240210e20052802482108200541d4016a200541d0006a3602002005200320096a3602cc01200520033602c801200520063602c401200520033602c0012005200541306a3602d001200541e0006a41086a20083602002005200541c8006a3602642005200e200841e0006c6a360260200541c0016a200541e0006a109a042001ad42307e2207422088a70d012007a72208417f4c0d01200528025821030240024020080d00410821040c010b200810332204450d010b20054100360218200520043602102005200841306e3602142001412c6c2208417f4c0d010240024020080d00410421160c010b200810332216450d010b4100210b2005410036022820052001360224200520163602202003200120032001491b2217450d024100210b200541c0016a41186a210a200541c0016a41106a210f200541c0016a41086a210d4100210203402005280250210602402003450d00200341d8006c21082006210303400240200341d0006a2d00000d0002400240200341206a2903002218200341286a29030022198450450d0042002107427f2118427f21190c010b427f21072005427f427f20182019109808200541086a2903002119200529030021180b2003201837030020032019370308200341106a2007370300200341186a20073703000b200341d8006a2103200841a87f6a22080d000b0b0240024020052802482203450d0020052802402209200341e0006c6a21120340024020092802382203450d00200341c8006c2106200928023041206a210303402005280258220e200328020022084d0d0402402005280250200841d8006c6a22082d00500d0020082903202207200841286a290300221884500d00200541c0016a2009290310200941186a2903002009290300200941086a29030020072018109b04200820082903002207427f2007427f20052903c80120052802c001410146220e1b22197c221820182007542210200841086a22112903002207427f200f290300200e1b221a7c2010ad7c221820075420182007511b220e1b2019201a845022101b37030020112007427f2018200e1b20101b3703000b200341c8006a2103200641b87f6a22060d000b0b200941e0006a22092012470d000b200528025021060b200241016a2102200528025841d8006c2103200641a87f6a210803402003450d05200341a87f6a2103200841d8006a2108200641d0006a2109200641d8006a220e210620092d00000d000b02402003450d00200841086a2903002107200841186a2903002118200841106a29030021192008290300211a4100210603400240200e20066a220941d0006a2d00000d00200941086a290300221b2007201a2007201920182009290300221c201b200941106a290300221d200941186a290300221e109c0441ff017141014622101b2107201c201a20101b211a201e201820101b2118201d201920101b21192009200820101b21080b2003200641d8006a2206470d000b2008450d050b200841013a0050024020052802482203450d0020052802402206200341e0006c6a21012008410c6a2114200841306a21150340200641e0006a210c024020062802382209450d0020062802302103200941c8006c210903400240024020142003460d00200341246a2015412010a0080d010b200641186a220e290300211a200841086a2210290300210720062903102119200829030021182008290310211b200341186a200841186a2211290300370300200341106a201b3703002003200742002007201a7d2018201954ad7d221b201820197d221c201856201b200756201b2007511b22121b2019201a845022131b370308200320184200201c20121b20131b37030020102903002107201129030021182008290300211920062008290310370320200641286a201837030020062019370310200e20073703000b200341c8006a2103200941b87f6a22090d000b0b200c2106200c2001470d000b0b200a200841c8006a290000370300200f200841c0006a290000370300200d200841386a290000370300200520082900303703c001200841286a2903002107200829032021180240200b2005280214470d00200541106a200b4101108801200528021021042005280218210b0b2004200b41306c6a220320052903c001370300200d2903002119200f290300211a200a290300211b20032018370320200341286a2007370300200341186a201b370300200341106a201a370300200341086a20193703002005200b41016a220b360218200220174f0d04200528025821030c010b0b2008200e41f4c4c8001042000b1045000b1044000b024020052802482203450d0020052802402214200341e0006c6a2102200b41306c210c200541ec006a220b41186a210a200b41106a210d200b41086a2117410021010340200b201429003c370000200a201441d4006a290000370000200d201441cc006a2900003700002017201441c4006a2900003700002005410036026820054204370360024020142802382203450d0020142802302212200341c8006c6a2115201441106a210f410021114104211303402012221041246a2106201041c8006a211241002109200c210820042103024003402008450d01024020062003460d0020032006412010a008210e200941016a2109200841506a2108200341306a2103200e0d010b0b418094ebdc0321080240200f2010109d040d004100210302402010290310201429032085201041186a290300201441286a29030085844200520d00200541c0016a428094ebdc0342002010290300201041086a290300200f290300200f41086a290300109b04427f20052903c80120052802c00141014622031b221842ffffffff0f56427f200541c0016a41106a29030020031b22074200522007501b0d012018a7220341ff93ebdc034b0d010b200321080b200541c0016a41186a22062010413c6a290000370300200541c0016a41106a2209201041346a290000370300200541c0016a41086a220e2010412c6a290000370300200520102900243703c001024020112005280264470d00200541e0006a20114101108d0120052802602113200528026821110b2013201141246c6a220320052903c001370200200e2903002107200929030021182006290300211920032008360220200341186a2019370200200341106a2018370200200341086a20073702002005201141016a22113602680b20122015470d000b024002402011450d0002400240201141246c22060d00410021030c010b201341206a2108410021030340417f200320082802006a220920092003491b2103200841246a21082006415c6a22060d000b0b02404100418094ebdc0320036b22032003418094ebdc034b1b221020116e2203418094ebdc032003418094ebdc03491b220e450d00201341206a210341002108034020112008460d032005417f20032802002206200e6a220920092006491b22063602c0012005418094ebdc033602c4012003200541c0016a2006418094ebdc034b4102746a280200360200200341246a21032011200841016a2208470d000b0b02402010200e20116c6b220e450d004100210303402005417f2013200320117041246c6a2208280220220641016a220920092006491b22063602c0012005418094ebdc033602c4012008200541c0016a2006418094ebdc034b4102746a280200360220200341016a2203200e490d000b0b200541c0016a41286a2208200541e0006a41286a280200360200200541c0016a41206a2206200541e0006a41206a290300370300200541c0016a41186a2209200541e0006a41186a290300370300200541c0016a41106a220e200541e0006a41106a290300370300200541c0016a41086a2210200541e0006a41086a290300370300200520052903603703c001024020012005280224470d00200541206a2001410110980120052802202116200528022821010b20162001412c6c6a220320052903c001370200200341286a2008280200360200200341206a2006290300370200200341186a2009290300370200200341106a200e290300370200200341086a20102903003702002005200141016a22013602280c020b20052802642203450d01200341246c450d01201310350c010b200820114184c5c8001042000b201441e0006a22142002470d000b0b200541c0016a41086a2203200541106a41086a280200360200200541d4016a200541206a41086a28020036020020002005290310370200200520052903203702cc01200041086a2003290300370200200041106a200541c0016a41106a290300370200024020052802542203450d00200341d8006c450d00200528025010350b024020052802482203450d00200341e0006c2108200528024041346a21030340024020032802002206450d00200641c8006c450d002003417c6a28020010350b200341e0006a2103200841a07f6a22080d000b0b024020052802442203450d00200341e0006c450d00200528024010350b200541306a10b1010c010b20004100360200024020052802542203450d00200341d8006c450d00200528025010350b024020052802482203450d00200341e0006c2108200528024041346a21030340024020032802002206450d00200641c8006c450d002003417c6a28020010350b200341e0006a2103200841a07f6a22080d000b0b024020052802442203450d00200341e0006c450d00200528024010350b200541306a10b101200428020021060240200441086a2802002203450d00200341386c21082006412c6a210303400240200328020041ffffff3f71450d002003417c6a28020010350b200341386a2103200841486a22080d000b0b200441046a2802002203450d00200341386c450d00200610350b20054190026a24000be80b08077f017e017f037e027f037e027f037e230041d0016b22042400200128020421052001280200210602400240024020012802082207450d00200741246c2108410021090340200620096a220741206a280200210a200441b0016a41186a200741186a290000370300200441b0016a41106a200741106a290000370300200441b0016a41086a200741086a290000370300200420072900003703b001200a0d022008200941246a2209470d000b0b4200210b4108210c4100210902402005450d00200541246c450d00200610354200210b0b4200210d410021070c010b200441306a20022003428094ebdc034200109808200441206a2004290330220e200441306a41086a290300220f4280ec94a37c427f108408200441106a200e200f200aad220d4200108408200441d0006a41086a220a200441b0016a41086a290300370300200441d0006a41106a2210200441b0016a41106a290300370300200441d0006a41186a2211200441b0016a41186a290300370300200420042903b001220b3703702004200b370350200d200429032020027c22127e220d428094ebdc0380210b20042903102113200441106a41086a29030021140240024041301033220c450d00200c2013200ba7417f200d428080808080c0b2cd3b541b200d200b4280ec94a37c7e7c4280cab5ee01566aad7c220b370320200c2004290350370300200c41286a2014200b201354ad7c220d370300200c41186a2011290300370300200c41106a2010290300370300200c41086a200a29030037030020044281808080103702442004200c36024002402008415c6a2009470d00410121090c020b200741c4006a210a200820096b41b87f6a2108410121090340200a2802002115200441b0016a41186a2210200a41606a220741186a290000370300200441b0016a41106a2211200741106a290000370300200441b0016a41086a2216200741086a290000370300200420072900003703b0010240024020150d002008450d040c010b2004200e200f2015ad22134200108408200441f0006a41086a20162903002214370300200441f0006a41106a20112903002217370300200441f0006a41186a20102903002218370300200420042903b0012219370370201020183703002011201737030020162014370300200420193703b001200b20042903002214201320127e2213428094ebdc03802217a7417f2013428080808080c0b2cd3b541b201320174280ec94a37c7e7c4280cab5ee01566aad7c22137c2217200b542207200d200441086a2903002013201454ad7c22147c2007ad7c220b200d54200b200d511b2107024020092004280244470d00200441c0006a200941011088012004280240210c0b427f200b20071b210d427f201720071b210b200c200941306c6a220720042903b00137030020162903002117201129030021182010290300211920072013370320200741286a2014370300200741186a2019370300200741106a2018370300200741086a20173703002004200941016a22093602482008450d030b2008415c6a2108200a41246a210a0c000b0b1045000b02402005450d00200541246c450d00200610350b200428024421070b024002402002200b7d22142002562003200d7d2002200b54ad7d221320035620132003511b4101470d00200b20027d2213200b56200d20037d200b200254ad7d220b200d56200b200d511b0d012009450d01200941306c200c6a41706a220a4200200a290300220d20137d22142014200d56200a41086a220a2903002214200b7d200d201354ad7d220d201456200d2014511b22081b370300200a4200200d20081b3703000c010b2009450d00200941306c200c6a41706a220a427f200a290300220d20147c220b200b200d542208200a41086a220a290300220d20137c2008ad7c220b200d54200b200d511b22081b370300200a427f200b20081b3703000b20002009360208200020073602042000200c3602002000200129020c37020c200041146a200141146a2902003702002000411c6a2001411c6a290200370200200041246a200141246a290200370200200441d0016a24000ba028030f7f047e1b7f230022052106200541e00b6b41607122072400200741003602182007410036021002400240024002402002450d00200120024105746a2108200741e0056a41027221094100210a034020074200370348200742003703402007410036025820074208370350200741a8026a41186a220b200141186a290000370300200741a8026a41106a220c200141106a290000370300200741a8026a41086a220d200141086a290000370300200720012900003703a80202400240200a450d002007280214210e0c010b200741e0056a410041e002109f081a200741f8026a410041e002109f081a41c8051033220a450d054100210e200a41003b0106200a4100360200200a41086a200741e0056a41e002109d081a200a41e8026a200741f8026a41e002109d081a200741003602142007200a3602100b200141206a21010240024002400240024002400340200a41066a210f200a2f01062210410574210241002111200a41086a22122105024003402002450d01200741a8026a2005412010a0082213450d03200241606a2102201141016a2111200541206a21052013417f4a0d000b2011417f6a21100b0240200e450d00200e417f6a210e200a20104102746a41c8056a280200210a0c010b0b200741f0006a41186a2202200b290300370300200741f0006a41106a200c2903002214370300200741f0006a41086a200d2903002215370300200720072903a80222163703702007200728021841016a360218200c2014370300200d2015370300200b2002290300370300200720163703a80220072903582114200729035021152007290348211620072903402117200f2f01002205410b490d01200741e0056a410041e002109f081a200741f8026a410041e002109f081a41c80510332218450d0a201841003b010620184100360200201841086a200741e0056a41e002109d082105201841e8026a200741f8026a41e002109d082111200741e0056a41086a2219200a41b0046a290300370300200741e0056a41106a221a200a41b8046a290300370300200741e0056a41186a221b200a41c0046a2903003703002007200a41db016a2900003703e0022007200a41e0016a2900003700e5022007200a41a8046a2903003703e0052007200a41c8016a2f00003b01f4022007200a41ca016a2d00003a00f602200a41cb016a280000211c200a41cf016a280000211d200a41d3016a280000211e200a41d7016a280000211f2005200a41e8016a200a2f010641796a22024105742213109d0821052011200a41c8046a2013109d082111200a41063b0106201820023b0106200720072f01f4023b01dc02200720072d00f6023a00de02200720072903e0023703c802200720072900e5023700cd02200741f8026a41186a2220201b290300370300200741f8026a41106a2221201a290300370300200741f8026a41086a22222019290300370300200720072903e0053703f8020240024020104107490d002005201041057441c07e6a220e6a2005201041796a221341057422106a2205200241ffff037120136b410574109e081a200541186a200b290300370000200541106a200c290300370000200541086a200d290300370000200520072903a8023700002011200e6a201120106a2202201841066a220f2f010020136b410574109e081a200241186a20143703002002201537031020022016370308200220173703000c010b20122010410574220541206a22116a201220056a2202200f2f010020106b410574109e081a200241186a200b290300370000200241106a200c290300370000200241086a200d290300370000200220072903a802370000200a41e8026a220220116a200220056a2202200f2f010020106b410574109e081a200241186a20143703002002201537031020022016370308200220173703000b200f200f2f010041016a3b010020074190026a41026a220220072d00de023a0000200741d8016a41086a22232022290300370300200741d8016a41106a22242021290300370300200741d8016a41186a22252020290300370300200720072f01dc023b019002200720072903c8023703c801200720072900cd023700cd01200720072903f8023703d801200741a4016a41026a222620022d00003a0000200720072f0190023b01a401200720072900cd0137009501200720072903c80137039001200741a8016a41186a22272025290300370300200741a8016a41106a22282024290300370300200741a8016a41086a22292023290300370300200720072903d8013703a8010240200a280200220e0d004100212a200741106a21020c040b200a2f0104210f4100212a0340200741a4026a41026a222b20262d00003a0000200720072f01a4013b01a402200720072903900137039002200720072900950137009502200b2027290300370300200c2028290300370300200d2029290300370300200720072903a8013703a80241000d03200f41ffff0371210a024002400240200e2f01062202410b490d002009410041f205109f081a41f80510332213450d0e20134100360200201341046a200741e0056a41f405109d081a2007200e2f00c8013b01f4022007200e41ca016a2d00003a00f6022007200e41db016a2900003703e0022007200e41e0016a2900003700e502200e41cb016a280000212c200e41cf016a280000212d200e41d3016a280000212e200e41d7016a280000212f201b200e41c0046a290300370300201a200e41b8046a2903003703002019200e41b0046a2903003703002007200e2903a8043703e005201341086a200e41e8016a200e2f0106220241796a22054105742211109d082130201341e8026a200e41c8046a2011109d082131201341c8056a200e41e4056a2002417a6a2210410274109d082112200e41063b0106201320053b010602402010450d00410021022012210503402005280200221120023b010420112013360200200541046a21052010200241016a2202470d000b0b2020201b2903003703002021201a29030037030020222019290300370300200720072903e0053703f802200720072f01f4023b01dc02200720072d00f6023a00de02200720072903e0023703c802200720072900e5023700cd02200741dc056a41026a221020072d00de023a0000200720072f01dc023b01dc05200720072903c8023703c801200720072900cd023700cd01201b2020290300370300201a202129030037030020192022290300370300200720072903f8023703e005200f41ffff037122054107490d012030200a417a6a2211410574220f6a2030200a41796a220241057422326a220520132f010620026b410574109e081a200541186a2007290095023700002005201f36000f2005201e36000b2005201d3600072005201c360003200541026a202b2d00003a0000200520072f01a4023b000020052007290390023700132031200f6a203120326a220520132f0106220f20026b410574109e081a200541186a200b290300370300200541106a200c290300370300200541086a200d290300370300200520072903a8023703002013200f41016a22053b0106200a410274221c20126a416c6a201220114102746a220f200541ffff0371220a20116b410274109e081a200f2018360200200a2011490d022013201c6a41b0056a2105034020052802002211200241016a22023b010420112013360200200541046a21052002200a490d000c030b0b200e41086a2205200a41016a221141057422136a2005200a41057422106a22052002200a6b410574220f109e081a2005201f36000f2005201e36000b2005201d3600072005201c360003200541026a202b2d00003a0000200520072f01a4023b00002005200729039002370013200541186a200729009502370000200e41e8026a220520136a200520106a2205200f109e081a200541186a200b290300370300200541106a200c290300370300200541086a200d290300370300200520072903a802370300200e200241016a22023b0106200a410274200e41c8056a22056a41086a200520114102746a2205200241ffff037120116b410274109e081a20052018360200200a200e2f010622024f0d07201820113b01042018200e360200201120024f0d072002417f6a2113200e2011417f6a22024102746a41d0056a2105034020052802002211200241026a3b01042011200e360200200541046a21052013200241016a2202470d000c080b0b200e41086a2202200a41016a2211410574220f6a2002200a41057422126a2202200e2f01062230200a6b4105742231109e081a2002201f36000f2002201e36000b2002201d3600072002201c360003200241026a202b2d00003a0000200220072f01a4023b00002002200729039002370013200241186a200729009502370000200e41e8026a2202200f6a200220126a22022031109e081a200241186a200b290300370300200241106a200c290300370300200241086a200d290300370300200220072903a802370300200e203041016a22023b0106200a4102742212200e41c8056a220f6a41086a200f20114102746a220f200241ffff037120116b410274109e081a200f20183602002005200e2f010622114f0d00200e20126a41cc056a2102034020022802002205200a41016a220a3b01042005200e360200200241046a21022011200a470d000b0b202a41016a212a2007418c026a41026a220220102d00003a0000202320192903003703002024201a2903003703002025201b290300370300200720072f01dc053b018c02200720072903c8013703f801200720072900cd013700fd01200720072903e0053703d801202620022d00003a0000200720072f018c023b01a401200720072900fd0137009501200720072903f80137039001202720252903003703002028202429030037030020292023290300370300200720072903d8013703a8010240200e28020022020d00200741106a2102202c211c202f211f202e211e202d211d201321180c050b200e2f0104210f202c211c202f211f202e211e202d211d2002210e201321180c000b0b200a20114105746a22024180036a2205290300211520052007290358370300200241f8026a2205290300211420052007290350370300200241f0026a2205290300211620052007290348370300200241e8026a2202290300211720022007290340370300200720153703f805200720143703f005200720163703e805200720173703e0052014a72202450d0420072802f4052205450d04200541306c450d04200210350c040b20122010410574221141206a22136a201220116a2202200520106b410574109e081a200241186a200b290300370000200241106a200c290300370000200241086a200d290300370000200220072903a802370000200a41e8026a220220136a200220116a2202200a2f010620106b410574109e081a200241186a2014370300200220153703102002201637030820022017370300200a200a2f010641016a3b0106200741003602f0050c030b41d684cc00413541c086cc00103f000b2009410041f205109f081a41f80510332205450d0620054100360200200541046a200741e0056a41f405109d081a2005200228020022113602c8052002200536020020022002280204221341016a360204201141003b010420112005360200200741a8026a41026a220a20262d00003a0000200720072f01a4013b01a80220072007290390013703f80220072007290095013700fd02201b2027290300370300201a202829030037030020192029290300370300200720072903a8013703e0052013202a470d0520052f01062211410a4b0d04200520114105746a2202410a6a200a2d00003a0000200241086a20072f01a8023b0000200241176a201f360000200241136a201e3600002002410f6a201d3600002002410b6a201c3600002002411b6a20072903f802370000200241206a20072900fd02370000200241e8026a20072903e005370300200241f0026a2019290300370300200241f8026a201a29030037030020024180036a201b2903003703002005201141016a22024102746a41c8056a2018360200200520023b0106201820023b0104201820053602000b200741003602f0050b20012008460d012007280210210a0c000b0b0240024020040d004100210b0c010b20032004412c6c6a210d4100210b034020032202412c6a21030240200228020841306c2205450d002002280200220a20056a210c2002410c6a21120340200a41306a210f0240024002402007280210220e450d00200728021421010340200e41086a2105200e2f01062210410574210241002111024003402002450d01200a2005412010a0082213450d04200241606a2102201141016a2111200541206a21052013417f4a0d000b2011417f6a21100b2001450d012001417f6a2101200e20104102746a41c8056a280200210e0c000b0b417f200b41016a22022002200b491b210b0c010b200e20114105746a220241e8026a2205427f20052903002214200a2903207c221520152014542205200241f0026a22112903002214200a41286a22132903007c2005ad7c221520145420152014511b22051b3703002011427f201520051b37030020122900002114200741e0056a41086a220e201241086a290000370300200741e0056a41106a2201201241106a290000370300200741e0056a41186a2210201241186a290000370300200720143703e00520132903002114200a2903202115200241f8026a2113024020024180036a22052802002211200241fc026a280200470d00201320114101108801200528020021110b2013280200201141306c6a220220072903e00537030020022015370320200241186a2010290300370300200241106a2001290300370300200241086a200e290300370300200241286a20143703002005200528020041016a3602000b200f210a200f200c470d000b0b2003200d470d000b0b200020072903103702002000200b36020c200041086a200741106a41086a280200360200200624000f0b41af84cc00412741c086cc00103f000b41ff83cc00413041c086cc00103f000b103c000be91105077f017e047f017e097f230041a0026b2202240002400240024002400240024002400240024020012802202203450d0020012003417f6a220436022020012802042203450d02200128020821052001280200210602402001410c6a280200220720032f0106490d00034002400240200328020022080d002005ad2109410021080c010b200641016a210620033301044220862005ad8421090b200310352009a72105200821032009422088a7220720082f01064f0d000b200821030b20024190016a41186a220a200320074105746a220841206a29000037030020024190016a41106a220b200841186a29000037030020024190016a41086a220c200841106a2900003703002002200841086a29000037039001200241f0016a41086a220d20084184036a2802003602002002200841fc026a2902003703f001200741016a2107200841f0026a2903002109200841e8026a290300210e200841f8026a280200210f02402006450d00200320074102746a41c8056a2802002103410021072006417f6a2208450d00034020032802c80521032008417f6a22080d000b0b200241186a41186a200a290300370300200241186a41106a200b290300370300200241186a41086a200c29030037030020024190026a41086a200d2802003602002002200229039001370318200220022903f001370390022001200736020c200120053602082001200336020420014100360200200f0d010b20024180016a41003602000c060b200241b8016a2009370300200241c0016a200f360200200241c4016a20022903900237020020024190016a41186a200241186a41186a29030037030020024190016a41106a200241186a41106a29030037030020024190016a41086a200241186a41086a290300370300200241cc016a20024190026a41086a2802003602002002200e3703b0012002200229031837039001200241c0006a200141246a20024190016a10860220024180016a280200450d0520024190016a200241c0006a41d000109d081a417f200441016a220320032004491bad42d0007e2209422088a70d012009a72203417f4c0d01200310332210450d02201020024190016a41d000109d082108200241013602102002200341d0006e36020c20022008360208200241186a41206a200141206a2902002209370300200241186a41186a200141186a290200370300200241186a41106a200141106a290200370300200241186a41086a200141086a29020037030020022001290200370318024002402009a72203450d0020022003417f6a220f360238200228021c2203450d0520022802202105200228021821070240200241246a280200220620032f0106490d00034002400240200328020022080d002005ad2109410021080c010b200741016a210720033301044220862005ad8421090b200310352009a72105200821032009422088a7220620082f01064f0d000b200821030b20024190016a41186a2201200320064105746a220841206a29000037030020024190016a41106a220b200841186a29000037030020024190016a41086a220c200841106a2900003703002002200841086a2900003703900120024190026a41086a220d20084184036a2802003602002002200841fc026a29020037039002200641016a2106200841f0026a2903002109200841e8026a290300210e200841f8026a280200210a02402007450d00200320064102746a41c8056a2802002103410021062007417f6a2208450d00034020032802c80521032008417f6a22080d000b0b200241f0016a41186a2001290300370300200241f0016a41106a200b290300370300200241f0016a41086a200c290300370300200241e0016a41086a200d28020036020020022002290390013703f00120022002290390023703e00120022006360224200220053602202002200336021c20024100360218200a450d002002413c6a2111200241c4016a2104200241b8016a2112410121010340200420022903e0013702002012200937030020024190016a41186a220b200241f0016a41186a221329030037030020024190016a41106a220c200241f0016a41106a221429030037030020024190016a41086a220d200241f0016a41086a2215290300370300200441086a200241e0016a41086a22162802003602002002200e3703b001200220022903f001370390012002200a3602c001200241c0006a201120024190016a108602200228028001450d0220024190016a200241c0006a41d000109d081a02402001200228020c470d00200241086a2001417f200f41016a22082008200f491b10a301200228020821100b2010200141d0006c6a20024190016a41d000109d081a2002200141016a2201360210200f450d012002200f417f6a220f3602382003450d07410021070240200620032f0106490d00034002400240200328020022080d002005ad2109410021080c010b200741016a210720033301044220862005ad8421090b200310352009a72105200821032009422088a7220620082f01064f0d000b200821030b200b200320064105746a220841206a290000370300200c200841186a290000370300200d200841106a2900003703002002200841086a29000037039001200841f8026a280200210a20024190026a41086a221720084184036a2802003602002002200841fc026a29020037039002200641016a2106200841f0026a2903002109200841e8026a290300210e02402007450d00200320064102746a41c8056a2802002103410021062007417f6a2208450d00034020032802c80521032008417f6a22080d000b0b2013200b2903003703002014200c2903003703002015200d2903003703002016201728020036020020022002290390013703f00120022002290390023703e00120022006360224200220053602202002200336021c20024100360218200a0d000b0b20024100360280010b200241186a109e02200041086a200241086a41086a280200360200200020022903083702000c060b41958dcc00412b41c08dcc00103f000b1044000b1045000b41958dcc00412b41c08dcc00103f000b41958dcc00412b41c08dcc00103f000b20004100360208200042083702002001109e020b200241a0026a24000ba20703027f017e067f230041e0006b2203240041f7edcb00ad4280808080f00084100122042900002105200341086a41086a200441086a290000370300200320053703082004103541e4b6c000ad4280808080b00184100122042900002105200341186a41086a200441086a2900003703002003200537031820041035200320013602382003200341386aad4280808080c000841003220429000037034820041035200341dc006a22012003413c6a3602002003200341c8006a41086a22063602542003200341386a3602582003200341c8006a360250200341286a200341d0006a107b0240024002400240412010332204450d0020042002290000370000200441186a200241186a290000370000200441106a200241106a290000370000200441086a200241086a29000037000020032004ad428080808080048410032202290000370348200210352001200441206a36020020032004360258200320063602542003200341c8006a360250200341386a200341d0006a107b200410352003280230220741206a2206200328024022086a2202417f4c0d01200328023821092003280228210a0240024020020d004100210b410121040c010b200210332204450d012002210b0b02400240200b410f4d0d00200b21010c010b200b41017422014110200141104b1b22014100480d030240200b0d002001103322040d010c050b200b2001460d002004200b200110372204450d040b20042003290308370000200441086a200341086a41086a2903003700000240024020014170714110460d002001210b0c010b2001410174220b4120200b41204b1b220b4100480d032001200b460d0020042001200b10372204450d040b20042003290318370010200441186a200341186a41086a29030037000002400240200b41606a2007490d00200b21010c010b2007415f4b0d03200b41017422012006200120064b1b22014100480d03200b2001460d002004200b200110372204450d040b200441206a200a2007109d081a02400240200120066b2008490d002001210b0c010b20022006490d032001410174220b2002200b20024b1b220b4100480d03024020010d000240200b0d00410121040c020b200b10332204450d050c010b2001200b460d0020042001200b10372204450d040b200420066a20092008109d081a200020023602082000200b360204200020043602000240200328023c450d00200910350b0240200328022c450d00200a10350b200341e0006a24000f0b1045000b1044000b103e000b103c000ba50403017f027e027f230041e0006b220224000240024020002802002200290300220342c000544100200041086a29030022045022051b0d0002400240024020034280800154410020051b0d00200342808080800454410020051b0d01411020047920037942c0007c20044200521ba741037622056b4104490d022002413320054102746b3a00482001200241c8006a41011078200029030021032002200041086a290300220437030820022003370300200541706a21000340200220033c00482001200241c8006a410110782003420888200442388684210320044208882104200041016a22052000492106200521002006450d000b20022003370300200220043703082003200484500d04200241286a41146a410a360200200241346a410b360200200241106a41146a410336020020022002360240200241d0caca00360244200241c8006a41146a410036020020024203370214200241a0b3cc003602102002410b36022c200241b0b4cc003602582002420137024c20024188caca003602482002200241286a3602202002200241c8006a3602382002200241c4006a3602302002200241c0006a360228200241106a41b0b4cc00104c000b20022003a74102744101723b01482001200241c8006a410210780c030b20022003a74102744102723602482001200241c8006a410410780c020b41c6c9ca00413641c086cc00103f000b20022003a74102743a00482001200241c8006a410110780b200241e0006a24000bf12c080a7f017e017f047e147f017e017f017e230041d0026b220424000240024020014115490d0041012105410121060240024002400340200121072000210820052006714101732109024002400240024002400240034002400240024002402003450d00024020054101710d00200020011085072003417f6a21030b2001410276220a41036c210b200a410174210c4100210d024020014132490d00410241012000200a41306c6a220d290300220e200d41506a220f290300221056200d41086a2903002211200f41086a29030022125620112012511b220f1b200f200d41306a29030022132010200e200f1b221056200d41386a290300220e20122011200f1b221156200e2011511b22141b2013201020141b2000200a200a417f6a2215200f1b221641306c6a220d29030056200e201120141b2211200d41086a29030022125620112012511b22176a2000200c41306c6a220d290300220e200d41506a2218290300221056200d41086a2903002211201841086a29030022125620112012511b22186a2000200c410172221941306c6a220d29030022132010200e20181b221056200d41086a290300220e2012201120181b221156200e2011511b221a6a20132010201a1b2000200c200c417f6a221b20181b221c41306c6a220d29030056200e2011201a1b2211200d41086a29030022125620112012511b221d6a2000200b41306c6a220d290300220e200d41506a221e290300221056200d41086a2903002211201e41086a29030022125620112012511b221e6a200d41306a29030022132010200e201e1b221056200d41386a290300220e20122011201e1b221156200e2011511b221f6a20132010201f1b2000200b200b417f6a2220201e1b222141306c6a220d29030056200e2011201f1b2211200d41086a29030022125620112012511b22066a210d2021200b41016a2020200b201e1b201f1b20061b210b201c2019201b200c20181b201a1b201d1b210c2016200a41016a2015200a200f1b20141b20171b210a0b200d2000200c41306c6a220f290300220e2000200a41306c6a2218290300221056200f41086a2903002211201841086a29030022125620112012511b220f6a2000200b41306c6a220d29030022132010200e200f1b221056200d41086a290300220e20122011200f1b221156200e2011511b220d6a211820132010200d1b2000200c200a200f1b222141306c6a221e29030058200e2011200d1b2211201e41086a29030022125820112012511b450d01200b200a200c200f1b200d1b21210c020b200020011086070c0f0b201841016a2218410c490d0002402001410176220b450d002000200141306c6a41506a210a2000210c0340200441a0026a41286a220f200c41286a220d290300370300200441a0026a41206a2218200c41206a221e290300370300200441a0026a41186a2214200c41186a221a290300370300200441a0026a41106a221f200c41106a2215290300370300200441a0026a41086a2216200c41086a22172903003703002004200c2903003703a002200a41086a22192903002111200a41106a221b2903002112200a41186a221c290300210e200a41206a221d2903002110200a41286a22202903002113200c200a290300370300200d2013370300201e2010370300201a200e37030020152012370300201720113703002020200f290300370300201d2018290300370300201c2014290300370300201b201f29030037030020192016290300370300200a20042903a002370300200c41306a210c200a41506a210a200b417f6a220b0d000b0b20012021417f736a21214101210a0c010b201845210a0b0240200a452009724101710d00200020011087070d0d0b2002450d02202120014f0d01024020022903002000202141306c6a220a29030056200241086a2903002211200a41086a220c29030022125620112012511b450d0020002108200121070c040b200441a0026a41286a221a200041286a2218290300370300200441a0026a41206a221f200041206a221e290300370300200441a0026a41186a2215200041186a2214290300370300200441a0026a41106a2216200041106a220b290300370300200441a0026a41086a2217200041086a220f290300370300200420002903003703a002200c2903002111200a41106a220d2903002112200a41186a2219290300210e200a41206a221b2903002110200a41286a221c29030021132000200a29030037030020182013370300201e20103703002014200e370300200b2012370300200f2011370300201c201a290300370300201b201f29030037030020192015290300370300200d2016290300370300200c2017290300370300200a20042903a002370300200f29030021112000290300210e200441186a221c2018290300370300200441106a221d201e290300370300200441086a222020142903003703002004200b290300370300200041506a2119200041306a211b4100210c2001210b03400240200c200b417f6a220f4f0d00201b200c41306c6a210a0340200e200a290300582011200a41086a29030022125820112012511b450d01200a41306a210a200f200c41016a220c470d000b200f210c0b2019200b41306c6a210a02400340200c200b417f6a220b4f0d01200a2903002112200a41086a210f200a41506a220d210a200e2012562011200f29030022125620112012511b0d000b201a201b200c41306c6a220a41286a220f290300370300201f200a41206a22212903003703002015200a41186a22062903003703002016200a41106a22222903003703002017200a41086a22232903003703002004200a2903003703a002200d41386a22242903002112200d41c0006a22252903002110200d41c8006a22262903002113200d41d0006a22272903002128200d41d8006a2229290300212a200a200d41306a220d290300370300200f202a370300202120283703002006201337030020222010370300202320123703002029201a2903003703002027201f290300370300202620152903003703002025201629030037030020242017290300370300200d20042903a002370300200c41016a210c0c010b0b2000200e370300200020113703082000200429030037031020142020290300370300201e201d2903003703002018201c29030037030002402001200c41016a220a490d002000200a41306c6a21002001200a6b220141154f0d010c0c0b0b200a200141e485cc001059000b2021200141d086cc001042000b2007450d010b202120074f0d01200441a0026a41286a2217200841286a2222290300370300200441a0026a41206a2219200841206a2223290300370300200441a0026a41186a221b200841186a2224290300370300200441a0026a41106a221c200841106a2225290300370300200441a0026a41086a221d200841086a2226290300370300200420082903003703a0022008202141306c6a220a41086a220c2903002111200a41106a220b2903002112200a41186a220f290300210e200a41206a220d2903002110200a41286a220029030021132008200a29030037030020222013370300202320103703002024200e370300202520123703002026201137030020002017290300370300200d2019290300370300200f201b290300370300200b201c290300370300200c201d290300370300200a20042903a0023703002026290300211120082903002112200441186a22272022290300370300200441106a22292023290300370300200441086a2205202429030037030020042025290300370300200841306a2101410021212007417f6a220f450d022001210a0340200a290300201256200a41086a290300220e201156200e2011511b450d03200a41306a210a200f202141016a2221470d000b200f21210c020b4100410041f485cc001042000b20212007418486cc001042000b2008200741306c6a210a200f210b02400340200a2100200b220c20214d22060d01200c417f6a210b200041506a220a290300201258200a41086a290300220e201158200e2011511b0d000b0b0240200c2021490d00200f200c490d0241800121154100210d4100211a4100210f4100211441800121162001202141306c6a220921010340200020016b220a41306e210c0240200a41afe0004b22200d00200c41807f6a200c201a200d492014200f49220b7222181b210a02402018450d002016200a200b1b2116200a2015200b1b21150c010b200a200a41017622166b21150b02402014200f470d00024020160d00200441206a220f21140c010b4100210c200441206a2214210f2001210a0340200f200c3a0000200f410041014102200a2903002210201285200a41086a290300220e20118584501b2010201254200e201154200e2011511b1b41027441c4cfca006a2802006a210f200a41306a210a2016200c41016a220c470d000b0b0240201a200d470d00024020150d00200441a0016a220d211a0c010b200041506a210a4100210c200441a0016a221a210d0340200d200c3a0000200d410041014102200a2903002210201285200a41086a290300220e20118584501b2010201254200e201154200e2011511b1b41027441d0cfca006a2802006a210d200a41506a210a2015200c41016a220c470d000b0b0240200d201a6b220a200f20146b220c200c200a4b1b221f450d002017200120142d000041306c6a220a41286a2903003703002019200a41206a290300370300201b200a41186a290300370300201c200a41106a290300370300201d200a41086a2903003703002004200a2903003703a002200120142d000041306c6a220a2000201a2d0000417f7341306c6a220c290300370300200a41286a200c41286a290300370300200a41206a200c41206a290300370300200a41186a200c41186a290300370300200a41106a200c41106a290300370300200a41086a200c41086a2903003703000240201f4101460d004100210b03402000201a200b6a22182d0000417f7341306c6a220a20012014200b6a41016a221e2d000041306c6a220c290300370300200a41286a200c41286a290300370300200a41206a200c41206a290300370300200a41186a200c41186a290300370300200a41106a200c41106a290300370300200a41086a200c41086a2903003703002001201e2d000041306c6a220a2000201841016a2d0000417f7341306c6a220c290300370300200a41286a200c41286a290300370300200a41206a200c41206a290300370300200a41186a200c41186a290300370300200a41106a200c41106a290300370300200a41086a200c41086a290300370300200b41026a210a200b41016a220c210b200a201f490d000b201a200c6a211a2014200c6a21140b2000201a2d0000417f7341306c6a220a20042903a002370300200a41286a2017290300370300200a41206a2019290300370300200a41186a201b290300370300200a41106a201c290300370300200a41086a201d290300370300201a41016a211a201441016a21140b2001201641306c6a20012014200f461b21012000410020156b41306c6a2000201a200d461b210020200d000b024002402014200f4f0d002000210a034020172001200f417f6a220f2d000041306c6a220c41286a220b2903003703002019200c41206a220d290300370300201b200c41186a2200290300370300201c200c41106a2218290300370300201d200c41086a221e2903003703002004200c2903003703a002200a41506a220a41086a221a290300210e200a41106a221f2903002110200a41186a22152903002113200a41206a22162903002128200a41286a2220290300212a200c200a290300370300200b202a370300200d20283703002000201337030020182010370300201e200e37030020202017290300370300201620192903003703002015201b290300370300201f201c290300370300201a201d290300370300200a20042903a0023703002014200f490d000c020b0b2001210a201a200d4f0d000340200d417f6a220d2d0000210c2017200a41286a220b2903003703002019200a41206a220f290300370300201b200a41186a2201290300370300201c200a41106a2218290300370300201d200a41086a221e2903003703002004200a2903003703a0022000200c417f7341306c6a220c41086a2214290300210e200c41106a221f2903002110200c41186a22152903002113200c41206a22162903002128200c41286a2220290300212a200a200c290300370300200b202a370300200f20283703002001201337030020182010370300201e200e37030020202017290300370300201620192903003703002015201b290300370300201f201c2903003703002014201d290300370300200c20042903a002370300200a41306a210a201a200d490d000b0b2008201137030820082012370300200820042903003703102024200529030037030020232029290300370300202220272903003703002007200a20096b41306e20216a22014d0d032017202229030037030020192023290300370300201b2024290300370300201c2025290300370300201d2026290300370300200420082903003703a0022008200141306c6a220a41086a220c2903002111200a41106a220b2903002112200a41186a220f290300210e200a41206a220d2903002110200a41286a220029030021132008200a29030037030020222013370300202320103703002024200e370300202520123703002026201137030020002017290300370300200d2019290300370300200f201b290300370300200b201c290300370300200c201d290300370300200a20042903a002370300200720016b220c450d04200c20012001200c4b1b210b2007410376210f200a41306a2100024002402001200c417f6a220c490d002000200c200a200310d001200821000c010b200820012002200310d001200a2102200c21010b200b200f4f2105200141154f0d010c050b0b2021200c419486cc001059000b200c200f419486cc001058000b20012007418486cc001042000b41a486cc00411c41c086cc00103f000b20014102490d00200041a07f6a210d410021184101210c0340200c41016a210f02402000200c41306c6a220b290300220e200b41506a220a29030058200b41086a221e2903002211200a41086a221429030022125820112012511b0d00200441186a221a200b41286a221f290300370300200441106a2215200b41206a2216290300370300200441086a2217200b41186a22192903003703002004200b290310370300200b200a290300370300201e2014290300370300200b41106a200a41106a2903003703002019200a41186a2903003703002016200a41206a290300370300201f200a41286a2903003703002000200c417f6a221e41306c6a211402400240201e0d004100211e0c010b2018210c200d210a200e200b41a07f6a220b290300582011200b41086a29030022125820112012511b0d00024002400340200a4188016a200a41d8006a290300370300200a4180016a200a41d0006a290300370300200a41f8006a200a41c8006a290300370300200a41f0006a200a41c0006a290300370300200a41e8006a200a41386a290300370300200a41e0006a200a41306a290300370300200c4101460d01200a2903002112200a41086a210b200c417f6a210c200a41506a210a200e2012562011200b29030022125620112012511b0d000c020b0b4100210c0b2000200c41306c6a2114200c211e0b2014200e370300201420113703082000201e41306c6a220a41286a201a290300370300200a41206a2015290300370300200a41186a2017290300370300200a20042903003703100b201841016a2118200d41306a210d200f210c200f2001470d000b0b200441d0026a24000ba20703027f017e067f230041e0006b2203240041f7edcb00ad4280808080f00084100122042900002105200341086a41086a200441086a290000370300200320053703082004103541d2b6c000ad4280808080a00284100122042900002105200341186a41086a200441086a2900003703002003200537031820041035200320013602382003200341386aad4280808080c000841003220429000037034820041035200341dc006a22012003413c6a3602002003200341c8006a41086a22063602542003200341386a3602582003200341c8006a360250200341286a200341d0006a107b0240024002400240412010332204450d0020042002290000370000200441186a200241186a290000370000200441106a200241106a290000370000200441086a200241086a29000037000020032004ad428080808080048410032202290000370348200210352001200441206a36020020032004360258200320063602542003200341c8006a360250200341386a200341d0006a107b200410352003280230220741206a2206200328024022086a2202417f4c0d01200328023821092003280228210a0240024020020d004100210b410121040c010b200210332204450d012002210b0b02400240200b410f4d0d00200b21010c010b200b41017422014110200141104b1b22014100480d030240200b0d002001103322040d010c050b200b2001460d002004200b200110372204450d040b20042003290308370000200441086a200341086a41086a2903003700000240024020014170714110460d002001210b0c010b2001410174220b4120200b41204b1b220b4100480d032001200b460d0020042001200b10372204450d040b20042003290318370010200441186a200341186a41086a29030037000002400240200b41606a2007490d00200b21010c010b2007415f4b0d03200b41017422012006200120064b1b22014100480d03200b2001460d002004200b200110372204450d040b200441206a200a2007109d081a02400240200120066b2008490d002001210b0c010b20022006490d032001410174220b2002200b20024b1b220b4100480d03024020010d000240200b0d00410121040c020b200b10332204450d050c010b2001200b460d0020042001200b10372204450d040b200420066a20092008109d081a200020023602082000200b360204200020043602000240200328023c450d00200910350b0240200328022c450d00200a10350b200341e0006a24000f0b1045000b1044000b103e000b103c000bac0201037f230041e0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100510c20102400240200328021022010d00410021020c010b200328021421042003200341186a280200360224200320013602202003200341206a10c4010240024020032802000d0020032802042105410121020c010b4100210220034100360230200342013703282003410936023c2003200341086a3602382003200341286a360244200341dc006a41013602002003420137024c200341c888c2003602482003200341386a360258200341c4006a41e88ac500200341c8006a10431a200335023042208620033502288410060240200328022c450d00200328022810350b0b2004450d00200110350b2000200536020420002002360200200341e0006a24000ba20703027f017e067f230041e0006b2203240041f7edcb00ad4280808080f00084100122042900002105200341086a41086a200441086a290000370300200320053703082004103541c0b6c000ad4280808080a00284100122042900002105200341186a41086a200441086a2900003703002003200537031820041035200320013602382003200341386aad4280808080c000841003220429000037034820041035200341dc006a22012003413c6a3602002003200341c8006a41086a22063602542003200341386a3602582003200341c8006a360250200341286a200341d0006a107b0240024002400240412010332204450d0020042002290000370000200441186a200241186a290000370000200441106a200241106a290000370000200441086a200241086a29000037000020032004ad428080808080048410032202290000370348200210352001200441206a36020020032004360258200320063602542003200341c8006a360250200341386a200341d0006a107b200410352003280230220741206a2206200328024022086a2202417f4c0d01200328023821092003280228210a0240024020020d004100210b410121040c010b200210332204450d012002210b0b02400240200b410f4d0d00200b21010c010b200b41017422014110200141104b1b22014100480d030240200b0d002001103322040d010c050b200b2001460d002004200b200110372204450d040b20042003290308370000200441086a200341086a41086a2903003700000240024020014170714110460d002001210b0c010b2001410174220b4120200b41204b1b220b4100480d032001200b460d0020042001200b10372204450d040b20042003290318370010200441186a200341186a41086a29030037000002400240200b41606a2007490d00200b21010c010b2007415f4b0d03200b41017422012006200120064b1b22014100480d03200b2001460d002004200b200110372204450d040b200441206a200a2007109d081a02400240200120066b2008490d002001210b0c010b20022006490d032001410174220b2002200b20024b1b220b4100480d03024020010d000240200b0d00410121040c020b200b10332204450d050c010b2001200b460d0020042001200b10372204450d040b200420066a20092008109d081a200020023602082000200b360204200020043602000240200328023c450d00200910350b0240200328022c450d00200a10350b200341e0006a24000f0b1045000b1044000b103e000b103c000bf52a07047f017e047f027e017f027e057f230041c0026b22032400200341c8016a41186a4200370300200341c8016a41106a22044200370300200341c8016a41086a22054200370300200342003703c80141d1c4c700ad4280808080e00084100122062900002107200341e8016a41086a2208200641086a290000370300200320073703e8012006103520052008290300370300200320032903e8013703c80141e7c4c700ad4280808080e00084100122062900002107200341a0026a41086a2208200641086a290000370300200320073703a00220061035200420032903a0022207370300200341a8016a41086a2005290300370300200341a8016a41106a2007370300200341a8016a41186a2008290300370300200320032903c8013703a801200341086a200341a8016a412010c001024002400240024002402003280208450d00200328020c2209450d00200341c8016a41186a220a4200370300200341c8016a41106a220b4200370300200341c8016a41086a22054200370300200342003703c80141d1c4c700ad4280808080e00084100122062900002107200341e8016a41086a2208200641086a290000370300200320073703e8012006103520052008290300370300200320032903e8013703c8014188f2c700ad4280808080e00184100122062900002107200341a0026a41086a2208200641086a290000370300200320073703a00220061035200420032903a002370000200441086a2008290300370000200341a8016a41086a2005290300370300200341a8016a41106a200b290300370300200341a8016a41186a200a290300370300200320032903c8013703a8012003412036028c022003200341a8016a36028802200341a0026a200341a8016aad220c4280808080800484220d100510c2010240024020032802a00222060d00410321050c010b20032802a402210b02400240024020082802002208450d0020062d0000220e41024b0d004101210502400240200e0e03000401000b2008417f6a4104490d012006280001210a410021050c030b410221050c010b200341003602d001200342013703c801200341093602ec01200320034188026a3602e8012003200341c8016a3602f801200341246a410136020020034201370214200341c888c2003602102003200341e8016a360220200341f8016a41e88ac500200341106a10431a20033502d00142208620033502c801841006024020032802cc01450d0020032802c80110350b410321050b0b200b450d00200610350b200341003602d001200342013703c801200341c8016a41002001108a014102200520054103461b210b20032802d001210602402001450d0020032802c80120064105746a210520062001410574220841606a4105766a210e20002106034020052006290000370000200541086a200641086a290000370000200541106a200641106a290000370000200541186a200641186a290000370000200541206a2105200641206a2106200841606a22080d000b200e41016a21060b200341a8016a41086a2208200636020020034194016a200a360200200320032903c8013703a8012003200b36029001200341106a2002418001109d081a200341a0016a2008280200360200200320032903a80137039801200341c8016a41186a22064200370300200341c8016a41106a22024200370300200341c8016a41086a22054200370300200342003703c80141d1c4c700ad4280808080e00084220f1001220a2900002107200341e8016a41086a220b200a41086a290000370300200320073703e801200a10352005200b290300370300200320032903e8013703c8014198f0c700ad4280808080a0018422101001220a2900002107200341a0026a41086a220e200a41086a290000370300200320073703a002200a1035200420032903a002370000200441086a220a200e29030037000020082005290300370300200341a8016a41106a22112002290300370300200341a8016a41186a22122006290300370300200320032903c8013703a8012003200341a8016a412010c00102402003280204410020032802001b221341016a221420134f0d00200341106a21060c040b200642003703002002420037030020054200370300200342003703c801200f100122152900002107200b201541086a290000370300200320073703e801201510352005200b290300370300200320032903e8013703c80120101001220b2900002107200e200b41086a290000370300200320073703a002200b1035200420032903a002370000200a200e290300370000200820052903003703002011200229030037030020122006290300370300200320032903c8013703a801200320143602c801200d200341c8016aad4280808080c000841002200341003602d001200342013703c801024002400240200328029001220541024b0d0002400240024020050e03000102000b410110332205450d07200341013602cc01200320053602c801200541003a0000200341013602d00120032802940121020240024020032802cc012208417f6a4104490d004101210520032802c80121060c010b41012105200841017422064105200641054b1b220a4100480d0420032802c801210602402008200a460d0020062008200a10372206450d0920032802d00121050b2003200a3602cc01200320063602c8010b200620056a20023600002003200541046a3602d0010c020b410110332205450d06200341013602cc01200320053602c801200541013a0000200341013602d0010c010b410110332205450d05200341013602cc01200320053602c801200541023a0000200341013602d0010b200341106a200341c8016a1082062003280298012106200341a0016a2802002205200341c8016a107702402005450d002005410574210b0340412010332205450d0320052006290000370000200541186a220e200641186a290000370000200541106a2211200641106a290000370000200541086a2212200641086a2900003700000240024020032802cc01220a20032802d00122086b4120490d0020032802c80121020c010b200841206a22022008490d03200a41017422142002201420024b1b22144100480d0302400240200a0d00024020140d00410121020c020b2014103322020d010c090b20032802c8012102200a2014460d002002200a201410372202450d0820032802d00121080b200320143602cc01200320023602c8010b200641206a2106200220086a22022005290000370000200241186a200e290000370000200241106a2011290000370000200241086a20122900003700002003200841206a3602d00120051035200b41606a220b0d000b0b20032802cc01210220032802c801210820033502d0012107200341c8016a41186a220a4200370300200341c8016a41106a220b4200370300200341c8016a41086a22054200370300200342003703c80141d1c4c700ad4280808080e0008410012206290000210d200341e8016a41086a220e200641086a2900003703002003200d3703e801200610352005200e290300370300200320032903e8013703c80141cccfc700ad4280808080e0008410012206290000210d200341a0026a41086a220e200641086a2900003703002003200d3703a00220061035200420032903a002370000200441086a200e290300370000200341a8016a41086a2005290300370300200341a8016a41106a200b290300370300200341a8016a41186a200a290300370300200320032903c8013703a801200c428080808080048420074220862008ad84102202402002450d00200810350b2001450d0320014105742112200341a8016a41106a210441d1c4c700ad4280808080e00084210c41d2cfc700ad4280808080b00184210d0340200c100122052900002107200341e8016a41086a220e200541086a290000370300200320073703e80120051035200d100122052900002107200341a0026a41086a2211200541086a290000370300200320073703a00220051035412010332205450d0220052000290000370000200541186a200041186a290000370000200541106a200041106a290000370000200541086a200041086a2900003700002005ad4280808080800484100422062900002107200341a8016a41086a2214200641086a290000370300200320073703a801200610352003200541206a3602d401200320053602d001200320043602cc012003200341a8016a3602c80120034188026a200341c8016a107b2005103502400240024002400240024002400240200328029002220a41206a2206417f4c0d00200328028802210b0240024020060d0041002108410121050c010b200610332205450d0b200621080b024002402008410f4d0d00200821020c010b200841017422024110200241104b1b22024100480d0a024020080d00200210332205450d0f0c010b20082002460d0020052008200210372205450d0e0b200520032903e801370000200541086a200e2903003700000240024020024170714110460d00200221080c010b200241017422084120200841204b1b22084100480d0a20022008460d0020052002200810372205450d0e0b200520032903a002370010200541186a201129030037000002400240200841606a200a490d00200821020c010b200a415f4b0d0a200841017422022006200220064b1b22024100480d0a20082002460d0020052008200210372205450d0e0b200541206a200b200a109d081a0240200328028c02450d00200b10350b200341a8016a2006ad4220862005ad842207100510c2010240024020032802a801450d00200341f8016a41086a2014280200360200200320032903a8013703f8010c010b410410332206450d0b200342043702cc01200320063602c8014100200341c8016a1077200341f8016a41086a20032802d001360200200320032903c8013703f8010b20034188026a41086a200341f8016a41086a2802002206360200200320032903f80137038802024002400240024002402006450d00200341c8016a2003280288022006410110f10420032802c8014101460d0420032802cc01210b20032802d401220820032802d001220a460d0320062008200a6b6a220641046a220e417f4c0d05200e0d014100210e410121110c020b410120034188026a107702400240200328028c02220a20032802900222066b4104490d0020032802880221080c010b200641046a22082006490d0e200a410174220b2008200b20084b1b220b4100480d0e02400240200a0d000240200b0d00410121080c020b200b10332208450d140c010b2003280288022108200a200b460d002008200a200b10372208450d1320032802900221060b2003200b36028c0220032008360288020b200820066a20093600002003200641046a22063602900202400240200328028c02220a20066b4104490d0020032802880221080c010b200641046a22082006490d0e200a410174220b2008200b20084b1b220b4100480d0e02400240200a0d000240200b0d00410121080c020b200b10332208450d140c010b2003280288022108200a200b460d002008200a200b10372208450d1320032802900221060b2003200b36028c0220032008360288020b200820066a2013360000200641046a21080c090b200e10332211450d0d0b200320113602e8012003200e3602ec01200320063602f0012003200341e8016a3602c801200b200341c8016a200810f20420062008490d0320032802f001220b2006490d04200328029002220b200a490d0520032802e801210e20032802880221112003200620086b2206360298022003200b200a6b220b36029c022006200b470d06200e20086a2011200a6a2006109d081a0240024020032802ec01220a20032802f00122066b4104490d0020032802e80121080c010b200641046a22082006490d0c200a410174220b2008200b20084b1b220b4100480d0c02400240200a0d000240200b0d00410121080c020b200b10332208450d120c010b20032802e8012108200a200b460d002008200a200b10372208450d1120032802f00121060b2003200b3602ec01200320083602e8010b200820066a20093600002003200641046a22063602f0010240024020032802ec01220a20066b4104490d0020032802e80121080c010b200641046a22082006490d0c200a410174220b2008200b20084b1b220b4100480d0c02400240200a0d000240200b0d00410121080c020b200b10332208450d120c010b20032802e8012108200a200b460d002008200a200b10372208450d1120032802f00121060b2003200b3602ec01200320083602e8010b200820066a2013360000200641046a210820032802e801210620032802ec01210a200328028c02450d0820032802880210350c080b200320034188026a3602c801200b200341c8016a200a10f20402400240200328028c02220a20032802900222066b4104490d0020032802880221080c010b200641046a22082006490d0b200a410174220b2008200b20084b1b220b4100480d0b02400240200a0d000240200b0d00410121080c020b200b10332208450d110c010b2003280288022108200a200b460d002008200a200b10372208450d1020032802900221060b2003200b36028c0220032008360288020b200820066a20093600002003200641046a22063602900202400240200328028c02220a20066b4104490d0020032802880221080c010b200641046a22082006490d0b200a410174220b2008200b20084b1b220b4100480d0b02400240200a0d000240200b0d00410121080c020b200b10332208450d110c010b2003280288022108200a200b460d002008200a200b10372208450d1020032802900221060b2003200b36028c0220032008360288020b200820066a2013360000200641046a21080c060b200328028c02450d0720032802880210350c070b1044000b2008200641e88cc5001059000b2006200b41e88cc5001058000b200a200b41f88cc5001059000b200341a8016a41146a410a360200200341b4016a410c360200200341a0026a41146a4103360200200320034198026a3602b80220032003419c026a3602bc02200341c8016a41146a4100360200200342033702a402200341a0b3cc003602a0022003410c3602ac01200341b0b4cc003602d801200342013702cc01200341f4b3cc003602c8012003200341a8016a3602b0022003200341c8016a3602b8012003200341bc026a3602b0012003200341b8026a3602a801200341a0026a41b0b4cc00104c000b2003200836029002200328028c02210a20032802880221060b2006450d0020072008ad4220862006ad8410020240200a450d00200610350b02402002450d00200510350b200041206a2100201241606a22120d010c050b0b200341106a21062002450d05200510350c050b103e000b1045000b20021097060c030b200341106a1097062003419c016a28020041ffffff3f71450d0220032802980110350c020b103c000b20061097062003419c016a28020041ffffff3f71450d0020032802980110350b200341c0026a24000bd50302047f047e230041f0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100510c20102400240200328021022040d00200041003a00000c010b200341186a28020021052003280214210641002101200341003a006802400240034020052001460d01200341c8006a20016a200420016a2d00003a00002003200141016a22023a00682002210120024120470d000b200341206a41186a200341c8006a41186a2903002207370300200341206a41106a200341c8006a41106a2903002208370300200341206a41086a200341c8006a41086a290300220937030020032003290348220a370320200041196a2007370000200041116a2008370000200041096a20093700002000200a370001410121010c010b0240200141ff0171450d00200341003a00680b410021012003410036022820034201370320200341093602442003200341086a3602402003200341206a36026c200341dc006a41013602002003420137024c200341c888c2003602482003200341c0006a360258200341ec006a41e88ac500200341c8006a10431a200335022842208620033502208410062003280224450d00200328022010350b200020013a00002006450d00200410350b200341f0006a24000b970b06047f057e027f017e027f027e230041f0016b220324002003200236026420032001360260200341e8006a2002ad4220862001ad84100510c201024002400240200328026822040d00200041003602200c010b200328026c21052003200341f0006a280200220636029c01200320043602980141002101200341003a00e8010240024002400240034020062001460d01200341c8016a20016a200420016a22022d00003a00002003200241016a360298012003200141016a22023a00e8012002210120024120470d000b200341a8016a41086a200341c8016a41086a290300370300200341a8016a41106a200341c8016a41106a290300370300200341a8016a41186a200341c8016a41186a290300370300200320032903c8013703a8012003200620026b36029c01200341c8006a20034198016a10f6012003290348a70d02200341c8006a41106a290300210720032903502108200341306a20034198016a10f6012003290330a70d02200341306a41106a29030021092003290338210a200341286a20034198016a10c40120032802280d02200328022c2206200328029c0141186e2201200120064b1bad42187e220b422088a7450d010c050b2003410036029c01200141ff0171450d01200341003a00e8010c010b200ba72202417f4c0d03024002400240024002400240024020020d004108210c0c010b20021033220c450d010b41002101200341003602d0012003200c3602c8012003200241186e22023602cc0102400240024002402006450d0041002101200341206a210d0340200341106a20034198016a10f6012003290310a70d02200d290300210b2003290318210e200341086a20034198016a10c40120032802080d02200328020c210f0240200120032802cc01470d00200341c8016a20014101109c0120032802c801210c20032802d00121010b200c200141186c6a2202200f3602102002200b3703082002200e3703002003200141016a22013602d0012006417f6a22060d000b20032802cc0121020b200c450d08200320034198016a10c40120032802000d06200328029c01220d20032802044102742206490d062006417f4c0d0b20060d014200210b4101210f0c020b20032802cc012201450d07200141186c0d060c070b20061039220f450d01200f20032802980122102006109d081a2003200d20066b36029c012003201020066a360298012006ad210b0b200f450d030240200b2006ad42208684220b422088a722060d00200ba721060c020b0240200f2006724103710d00200ba722064103710d002006410276220d450d02200b422288a721100c030b200ba7450d03200f10350c030b1045000b4100211002402006450d00200f10350b4100210d4104210f0b41000d00200f450d00200341f8006a41186a200341a8016a41186a290300220b370300200341f8006a41106a200341a8016a41106a290300220e370300200341f8006a41086a200341a8016a41086a2903002211370300200320032903a8012212370378200041186a20093703002000200a3703102000200737030820002008370300200041346a2010360200200041306a200d3602002000412c6a200f360200200041286a2001360200200020023602242000200c360220200041386a2012370300200041c0006a2011370300200041c8006a200e370300200041d0006a200b3703000c030b2002450d01200241186c450d010b200c10350b200341003602b001200342013703a8012003410936027c2003200341e0006a3602782003200341a8016a3602a401200341dc016a4101360200200342013702cc01200341c888c2003602c8012003200341f8006a3602d801200341a4016a41e88ac500200341c8016a10431a20033502b00142208620033502a801841006024020032802ac01450d0020032802a80110350b200041003602200b2005450d00200410350b200341f0016a24000f0b1044000ba80202017f037e230041d0006b220324002003200236020420032001360200200341086a2002ad4220862001ad84100510c20102400240200328020822010d00420021040c010b200328020c210202400240200341086a41086a2802004110490d00200141086a290000210520012900002106420121040c010b20034100360220200342013703182003410936022c200320033602282003200341186a360234200341cc006a41013602002003420137023c200341c888c2003602382003200341286a360248200341346a41e88ac500200341386a10431a200335022042208620033502188410060240200328021c450d00200328021810350b420021040b2002450d00200110350b2000200637030820002004370300200041106a2005370300200341d0006a24000b9f4014047f017e017f017e017f017e057f017e087f017e037f017e017f017e077f027e037f017e037f067e230041e0036b22012400200141e0026a41186a22024200370300200141e0026a41106a22034200370300200141e0026a41086a22044200370300200142003703e00241f7edcb00ad4280808080f000842205100122062900002107200141d0006a41086a2208200641086a290000370300200120073703502006103520042008290300370300200120012903503703e00241eeedcb00ad428080808090018422071001220629000021092008200641086a2900003703002001200937035020061035200320012903502209370300200141a8016a41086a220a2004290300370300200141a8016a41106a220b2009370300200141a8016a41186a220c2008290300370300200120012903e0023703a801200141e0026a200141a8016a10ac012003280200210d20012903e0022109200242003703002003420037030020044200370300200142003703e00220051001220629000021052008200641086a290000370300200120053703502006103520042008290300370300200120012903503703e00220071001220629000021052008200641086a2900003703002001200537035020061035200320012903502205370300200a2004290300370300200b2005370300200c2008290300370300200120012903e0023703a80102400240410410332208450d0020084100200d41016a20094202511b220e36000020084104410810372208450d0041002102200841003a0004200141a8016aad220f42808080808004842008ad4280808080d00084100220081035200141e0026a41186a220a4200370300200141e0026a41106a220b4200370300200141e0026a41086a22044200370300200142003703e00241f7edcb00ad4280808080f00084100122062900002105200141d0006a41086a2208200641086a290000370300200120053703502006103520042008290300370300200120012903503703e00241aeeecb00ad4280808080a001841001220629000021052008200641086a290000370300200120053703502006103520032001290350370000200341086a2008290300370000200141a8016a41086a2004290300370300200141a8016a41106a200b290300370300200141a8016a41186a200a290300370300200120012903e0023703a801200141a0026a200141a8016a10d90102400240024020012802a00222100d00200141003602900120014204370388010c010b20012902a402210520012010360288012001200537028c012005422088a722082005a72202470d010b20014188016a20024101109001200128028801211020012802900121080b201020084103746a220420003602042004200e3602002001200841016a2211360290010240024002400240200e41a1054f0d00201121120c010b024020110d004100211220014100360290010c010b200e41e07a6a2104200841ffffffff017141016a2106410021132010210802400340200828020020044f0d01200841086a21082006201341016a2213470d000b0b0240024020112013490d004100211220014100360290012013450d0120134103742114200141a0026aad4280808080c000842105200141a4026a2115200141d0006a41086a21162010210c0340200c280200210d41f7edcb00ad4280808080f00084220710012208290000210920014180026a41086a2200200841086a29000037030020012009370380022008103541d6a9c000ad4280808080b0028410012208290000210920014190026a41086a220a200841086a2900003703002001200937039002200810352001200d3602a002200120051003220829000037035020081035200120153602ec02200120163602e4022001200141a0026a3602e8022001200141d0006a3602e002200141a8016a200141e0026a107b20012802b001220b41206a2204417f4c0d0720012802a80121170240024020040d0041002106410121080c010b200410332208450d06200421060b024002402006410f4d0d00200621020c010b200641017422024110200241104b1b22024100480d05024020060d002002103322080d010c080b20062002460d0020082006200210372208450d070b2008200129038002370000200841086a20002903003700000240024020024170714110460d00200221060c010b200241017422064120200641204b1b22064100480d0520022006460d0020082002200610372208450d070b2008200129039002370010200841186a200a29030037000002400240200641606a200b490d00200621020c010b2004200b490d05200641017422022004200220044b1b22024100480d0520062002460d0020082006200210372208450d070b200841206a2017200b109d081a024020012802ac01450d00201710350b2004ad4220862008ad84100802402002450d00200810350b20071001220829000021072000200841086a29000037030020012007370380022008103541e9a9c000ad4280808080b00284100122082900002107200a200841086a2900003703002001200737039002200810352001200d3602a002200120051003220829000037035020081035200120153602ec02200120163602e4022001200141a0026a3602e8022001200141d0006a3602e002200141a8016a200141e0026a107b20012802b001220b41206a2204417f4c0d0720012802a801210d0240024020040d0041002106410121080c010b200410332208450d06200421060b024002402006410f4d0d00200621020c010b200641017422024110200241104b1b22024100480d05024020060d00200210332208450d080c010b20062002460d0020082006200210372208450d070b2008200129038002370000200841086a20002903003700000240024020024170714110460d00200221060c010b200241017422064120200641204b1b22064100480d0520022006460d0020082002200610372208450d070b2008200129039002370010200841186a200a29030037000002400240200641606a200b490d00200621020c010b200b415f4b0d05200641017422022004200220044b1b22024100480d0520062002460d0020082006200210372208450d070b200841206a200d200b109d081a024020012802ac01450d00200d10350b2004ad4220862008ad84100802402002450d00200810350b200c41086a210c201441786a22140d000c020b0b20132011104f000b201120136b2214450d0002402013450d002010201020134103746a2014410374109e081a0b200120143602900120102802042112200141e0026a41186a4200370300200141e0026a41106a22134200370300200141e0026a41086a22084200370300200142003703e00241a3edcb00ad4280808080f0008410012204290000210520014180026a41086a2206200441086a2900003703002001200537038002200410352008200629030037030020012001290380023703e00241aaedcb00ad4280808080b0018410012204290000210520014190026a41086a2206200441086a29000037030020012005370390022004103520132001290390022205370300200141a0026a41086a2008290300370300200141a0026a41106a2005370300200141a0026a41186a2006290300370300200120012903e0023703a002200141e0026a200141a0026a412010da014101210820012902e40221180240024020012802e00222044101460d00200441014621080c010b2018422088a722112012201220114b1b22172018a72200490d000240201720004d0d00200141a0026aad4280808080c000842107200141a4026a2115200141d0006a41086a211641a3edcb00ad4280808080f0008421090340200910012208290000210520014180026a41086a220c200841086a2900003703002001200537038002200810354196eaca00ad4280808080a0028410012208290000210520014190026a41086a220d200841086a290000370300200120053703900220081035200120003602a002200120071003220829000037035020081035200120153602ec02200120163602e4022001200141a0026a3602e8022001200141d0006a3602e002200141a8016a200141e0026a107b20012802b001220a41206a2204417f4c0d0720012802a801210b0240024020040d0041002106410121080c010b200410332208450d06200421060b024002402006410f4d0d00200621020c010b200641017422024110200241104b1b22024100480d05024020060d00200210332208450d080c010b20062002460d0020082006200210372208450d070b2008200129038002370000200841086a200c2903003700000240024020024170714110460d00200221060c010b200241017422064120200641204b1b22064100480d0520022006460d0020082002200610372208450d070b2008200129039002370010200841186a200d29030037000002400240200641606a200a490d00200621020c010b200a415f4b0d05200641017422022004200220044b1b22024100480d0520062002460d0020082006200210372208450d070b200841206a200b200a109d081a024020012802ac01450d00200b10350b200041016a21002004ad4220862008ad84100702402002450d00200810350b20172000470d000b0b201220114921082018428080808070832017ad8421180b200120183702ac01200120083602a8010240024020080d00200141e0026a41186a22064200370300200141e0026a41106a22024200370300200141e0026a41086a22084200370300200142003703e00241a3edcb00ad4280808080f0008410012204290000210520014180026a41086a2200200441086a2900003703002001200537038002200410352008200029030037030020012001290380023703e00241aaedcb00ad4280808080b0018410012204290000210520014190026a41086a2200200441086a2900003703002001200537039002200410352013200129039002370000201341086a2000290300370000200141a0026a41086a2008290300370300200141a0026a41106a2002290300370300200141a0026a41186a2006290300370300200120012903e0023703a002200141a0026aad428080808080048410070c010b200141e0026a41186a22064200370300200141e0026a41106a22024200370300200141e0026a41086a22084200370300200142003703e00241a3edcb00ad4280808080f0008410012204290000210520014180026a41086a2200200441086a2900003703002001200537038002200410352008200029030037030020012001290380023703e00241aaedcb00ad4280808080b0018410012204290000210520014190026a41086a2200200441086a2900003703002001200537039002200410352013200129039002370000201341086a2000290300370000200141a0026a41086a2008290300370300200141a0026a41106a2002290300370300200141a0026a41186a2006290300370300200120012903e0023703a002200141203602e4022001200141a0026a3602e002200141a8016a410472200141e0026a10db010b201421120b200128028c012115200141e0026a41186a22024200370300200141e0026a41106a22004200370300200141e0026a41086a22044200370300200142003703e00241f7edcb00ad4280808080f00084100122062900002105200141d0006a41086a2208200641086a290000370300200120053703502006103520042008290300370300200120012903503703e00241aeeecb00ad4280808080a001841001220629000021052008200641086a290000370300200120053703502006103520032001290350370000200341086a2008290300370000200141a8016a41086a2004290300370300200141a8016a41106a2000290300370300200141a8016a41186a2002290300370300200120012903e0023703a8010240024020100d00200f428080808080048410070c010b20124103744104722208417f4c0d04200810332204450d02200141003602e802200120083602e402200120043602e0022012200141e0026a10770240024020120d0020012802e802210820012802e00221020c010b201020124103746a2114410020012802e802220b6b210020012802e4022104410021080340200b20086a210a201020086a220c280200210d02400240200420006a4104490d0020012802e0022102200421060c010b200a41046a2206200a490d04200441017422022006200220064b1b22064100480d040240024020040d00024020060d00410121020c020b200610332202450d080c010b20012802e002210220042006460d0020022004200610372202450d070b200120063602e402200120023602e0020b2002200b6a20086a200d3600002001200a41046a22043602e802200c41046a280200210d02400240200620006a417c6a41034d0d00200621040c010b200441046a22172004490d04200641017422042017200420174b1b22044100480d040240024020060d00024020040d00410121020c020b200410332202450d080c010b20062004460d0020022006200410372202450d070b200120043602e402200120023602e0020b2002200b6a20086a41046a200d3600002001200a41086a3602e802200041786a2100200841086a2108200c41086a2014470d000b200b20086a21080b20012802e4022104200f42808080808004842008ad4220862002ad84100202402004450d00200210350b201541ffffffff0171450d00201010350b200141e0026a41186a22194200370300200141e0026a41106a221a4200370300200141e0026a41086a221b4200370300200142003703e00241f7edcb00ad4280808080f00084221c100122082900002105200141d0006a41086a221d200841086a2900003703002001200537035020081035201b201d290300370300200120012903503703e00241b8eecb00ad4280808080e00284221e100122082900002105201d200841086a290000370300200120053703502008103520032001290350370000200341086a221f201d290300370000200141a8016a41086a2220201b290300370300200141a8016a41106a2221201a290300370300200141a8016a41186a22222019290300370300200120012903e0023703a801200141c8006a200141a8016a412010c001200128024c21230240200128024822244101470d00024020234100200e41d87e6a22082008200e4b1b22254f0d00200141e0026aad42808080808002842126200141a0026aad42808080808004842127200141e0026a41106a210a200141e0016a2128200141a8016a41246a2100200141e0026a41286a2114202321290340200141a8016a202910dc01200141e0026a20012802a801220820012802b001220410dd010240024020012802e002222a0d004200212b4108212a0c010b2004ad4220862008ad84100720012902e402212b0b024020012802ac01450d00200810350b202a202b422088a7220841d8006c6a2117202a210202402008450d000340200141a8016a41186a2208200241186a290300370300200141a8016a41106a2204200241106a290300370300200141a8016a41086a2206200241086a2903003703002002280220210c20022903002105200141e0026a41206a2210200241c4006a2902003703002014200241cc006a290200370300200141e0026a41306a2215200241d4006a280200360200200141e0026a41086a220b2002412c6a290200370300200a200241346a290200370300200141e0026a41186a220d2002413c6a290200370300200120053703a8012001200241246a2902003703e002200241d8006a2102200c450d0120014188016a41186a2216200829030037030020014188016a41106a2213200429030037030020014188016a41086a220e2006290300370300200141d0006a41086a2212200b290300370300200141d0006a41106a2211200a290300370300200141d0006a41186a222c200d290300370300200141d0006a41206a222d2010290300370300200141d0006a41286a22102014290300370300200141d0006a41306a222e2015280200360200200120012903a80137038801200120012903e00237035020082016290300370300200420132903003703002006200e29030037030020002001290350370200200041086a2012290300370200200041106a2011290300370200200041186a202c290300370200200041206a202d290300370200200041286a2010290300370200200041306a202e28020036020020012001290388013703a8012001200c3602c801200142003703c802200142003703c002200120082903003703d802200120042903003703d002202820012903a8012006290300200141d0026a200141c0026a10de01024020012802d0012208450d00200841306c2104200c210803402008200841206a290300200841286a290300200141d0026a200141c0026a10de01200841306a2108200441506a22040d000b0b200141c0026a41086a290300212f20012903c002213020012802d4012110024002400240024020012903d0022207200141d0026a41086a290300220584500d0020012802dc012208450d00200141386a203020072030200754202f200554202f2005511b22041b2231202f200520041b22322008ad420010980820084105742104200141386a41086a29030021092001290338213320312105203221072010210803402008203320052005203356200720095620072009511b22061b22182009200720061b223410df01200720347d2005201854ad7d2107200520187d2105200841206a2108200441606a22040d000b427f203020317d220920057c220520052009542208202f20327d2030203154ad7d220520077c2008ad7c220720055420072005511b22081b2205427f200720081b2207844200520d01200d4200370300200a4200370300200b4200370300200142003703e00241b6fdc600ad4280808080800184220510012204290000210720014180026a41086a2208200441086a290000370300200120073703800220041035200b200829030037030020012001290380023703e00241e489c200ad4280808080d00184220710012206290000210920014190026a41086a2204200641086a290000370300200120093703900220061035200a200129039002370000200a41086a22162004290300370000200141a0026a41086a2213200b290300370300200141a0026a41106a220e200a290300370300200141a0026a41186a2212200d290300370300200120012903e0023703a002200141206a200141a0026a412010d701200141206a41106a29030021092001290328211820012802202106200d4200370300200a4200370300200b4200370300200142003703e00220051001221529000021052008201541086a290000370300200120053703800220151035200b200829030037030020012001290380023703e00220071001220829000021052004200841086a290000370300200120053703900220081035200a200129039002370000201620042903003700002013200b290300370300200e200a2903003703002012200d290300370300200120012903e0023703a00220012009420020061b3703e80220012018420020061b3703e0022027202610020c030b2030202f844200520d01200d4200370300200a4200370300200b4200370300200142003703e00241b6fdc600ad4280808080800184220510012204290000210720014180026a41086a2208200441086a290000370300200120073703800220041035200b200829030037030020012001290380023703e00241e489c200ad4280808080d00184220710012206290000210920014190026a41086a2204200641086a290000370300200120093703900220061035200a200129039002370000200a41086a22162004290300370000200141a0026a41086a2213200b290300370300200141a0026a41106a220e200a290300370300200141a0026a41186a2212200d290300370300200120012903e0023703a002200141086a200141a0026a412010d701200141086a41106a29030021092001290310211820012802082106200d4200370300200a4200370300200b4200370300200142003703e00220051001221529000021052008201541086a290000370300200120053703800220151035200b200829030037030020012001290380023703e00220071001220829000021052004200841086a290000370300200120053703900220081035200a200129039002370000201620042903003700002013200b290300370300200e200a2903003703002012200d290300370300200120012903e0023703a00220012009420020061b3703e80220012018420020061b3703e0022027202610020c020b200142f0f2bda1a7ee9cb9f9003703a002200141e0026a200141a0026a10e001200141e0026a2005200710df01200d2007370300200120053703f002200141063a00e8022001410c3a00e00241b0b4cc004100200141e0026a10d4010c010b200142f0f2bda1a7ee9cb9f9003703a002200141e0026a200141a0026a10e001200141e0026a2030202f10df01200d202f370300200120303703f002200141063a00e8022001410c3a00e00241b0b4cc004100200141e0026a10d4010b024020012802cc012208450d00200841306c450d00200c10350b024020012802d80141ffffff3f71450d00201010350b20022017470d000b201721020b202ba72104024020172002460d0003400240200241246a2802002208450d00200841306c450d00200241206a28020010350b200241d8006a21080240200241306a28020041ffffff3f71450d002002412c6a28020010350b2008210220172008470d000b0b202941016a212902402004450d00200441d8006c450d00202a10350b20292025470d000b0b20232025202320254b1b21230b20194200370300201a4200370300201b4200370300200142003703e002201c100122082900002105201d200841086a2900003703002001200537035020081035201b201d290300370300200120012903503703e002201e100122082900002105201d200841086a290000370300200120053703502008103520032001290350370000201f201d2903003700002020201b2903003703002021201a29030037030020222019290300370300200120012903e0023703a8010240024020240d00200f428080808080048410070c010b200120233602e002200f4280808080800484200141e0026aad4280808080c0008410020b200141e0036a24000f0b103e000b1045000b103c000b1044000bed0401097f230041e0006b220224002002412036020c20022001360208200241106a2001ad4280808080800484100510c2010240024002400240200228021022030d00200041003602000c010b200228021421042002200241186a280200360224200220033602202002200241206a10c4010240024020022802000d0020022802042205200228022422064103762201200120054b1b22014103742207417f4c0d030240024020010d00410421080c010b200710332208450d050b200241003602502002200136024c200220083602480240024002402005450d004100210103402002410036022820064104490d0320022002280220220741046a36022020072800002109200241003602282006417c6a4104490d022002200741086a3602202007280004210702402001200228024c470d00200241c8006a2001410110900120022802482108200228025021010b200641786a2106200820014103746a220a2007360204200a20093602002002200141016a22013602502005417f6a22050d000b200220063602240b2008450d022000200229024c370204200020083602000c030b2006417c6a21060b20022006360224200228024c41ffffffff0171450d00200810350b20024100360230200242013703282002410936023c2002200241086a3602382002200241286a360244200241dc006a41013602002002420137024c200241c888c2003602482002200241386a360258200241c4006a41e88ac500200241c8006a10431a200235023042208620023502288410060240200228022c450d00200228022810350b200041003602000b2004450d00200310350b200241e0006a24000f0b1044000b1045000bbb0201037f230041d0006b220324002003200236020420032001360200200341086a2002ad4220862001ad84100510c20102400240200328020822010d00200041003602000c010b200341106a2802002102200328020c2104200341003602380240024020024104490d0020012800002105200341003602382002417c714104460d00200041086a200128000436020020002005360204410121020c010b20034100360220200342013703182003410936022c200320033602282003200341186a360234200341cc006a41013602002003420137023c200341c888c2003602382003200341286a360248200341346a41e88ac500200341386a10431a200335022042208620033502188410060240200328021c450d00200328021810350b410021020b200020023602002004450d00200110350b200341d0006a24000b3c01017f02404108103322020d001045000b200220002802003600002002200028020436000420012902002002ad42808080808001841002200210350bfc0403027f017e057f230041d0006b2202240041f7edcb00ad4280808080f00084100122032900002104200241086a41086a200341086a290000370300200220043703082003103541efb6c000ad4280808080800284100122032900002104200241186a41086a200341086a2900003703002002200437031820031035200220013602342002200241346aad4280808080c000841003220329000037033820031035200241cc006a200241386a3602002002200241386a41086a3602442002200241346a3602482002200241386a360240200241286a200241c0006a107b02400240024002402002280230220541206a2206417f4c0d00200228022821070240024020060d0041002101410121030c010b200610332203450d02200621010b024002402001410f4d0d00200121080c010b200141017422084110200841104b1b22084100480d03024020010d002008103322030d010c050b20012008460d0020032001200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821010c010b200841017422014120200141204b1b22014100480d0320082001460d0020032008200110372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200141606a2005490d00200121080c010b200541206a22082005490d03200141017422092008200920084b1b22084100480d0320012008460d0020032001200810372203450d040b200341206a20072005109d081a2000200636020820002008360204200020033602000240200228022c450d00200710350b200241d0006a24000f0b1044000b1045000b103e000b103c000b800b06057f017e077f017e037f037e230041e0016b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100510c2010240024002400240200328021022040d00200041003602000c010b200328021421052003200341186a280200360224200320043602202003200341206a10c40102400240024020032802000d00200328020422062003280224220741d8006e2201200120064b1bad42d8007e2208422088a70d042008a72201417f4c0d040240024020010d00410821090c010b200110332209450d060b4100210a20034100360230200320093602282003200141d8006e36022c02402006450d004100210b034041002101200341003a00d801200b41016a210b02400240024002400240034020072001460d01200341b8016a20016a2003280220220c2d00003a00002003200c41016a3602202003200141016a22023a00d8012002210120024120470d000b20034198016a41086a220d200341b8016a41086a29030037030020034198016a41106a220e200341b8016a41106a29030037030020034198016a41186a220f200341b8016a41186a290300370300200320032903b801370398012003200720026b220136022420014110490d032003200c41116a3602202003200141706a360224200c41096a2900002108200c2900012110200341b8016a200341206a10aa0220032802b801220c450d0320032802c001211120032802bc012102200341b8016a200341206a10c30120032802b80122070d012002450d03200241306c0d020c030b20034100360224200141ff0171450d02200341003a00d8010c020b20032802bc01211220032802242201410f4b0d020240201241ffffff3f71450d00200710350b2002450d01200241306c450d010b200c10350b200341d8006a41086a200341f8006a41086a2903003703000240200a450d00200a41d8006c2102200941306a210103400240200141746a280200220c450d00200c41306c450d00200141706a28020010350b0240200128020041ffffff3f71450d002001417c6a28020010350b200141d8006a2101200241a87f6a22020d000b0b200328022c2201450d03200141d8006c450d03200910350c030b20032802c0012113200341d8006a41086a200d2903002214370300200341d8006a41106a200e2903002215370300200341d8006a41186a200f2903002216370300200341386a41186a220d2016370300200341386a41106a220e2015370300200341386a41086a220f20143703002003200141706a36022420032003280220220141106a3602202003200329039801221437035820032014370338200141086a2900002114200129000021150240200a200328022c470d00200341286a200a4101109b01200328022821092003280230210a0b2009200a41d8006c6a2201201537031020012008370308200120103703002001200c360220200141186a2014370300200141346a2013360200200141306a20123602002001412c6a2007360200200141286a2011360200200141246a2002360200200141386a2003290338370200200141c0006a200f290300370200200141c8006a200e290300370200200141d0006a200d2903003702002003200a41016a220a360230200b2006460d01200328022421070c000b0b20090d010b200341003602a00120034201370398012003410936027c2003200341086a360278200320034198016a360258200341cc016a4101360200200342013702bc01200341c888c2003602b8012003200341f8006a3602c801200341d8006a41e88ac500200341b8016a10431a20033502a0014220862003350298018410060240200328029c01450d0020032802980110350b200041003602000c010b2000200329022c370204200020093602000b2005450d00200410350b200341e0016a24000f0b1044000b1045000b8d22020f7f137e23004190066b22052400200541386a200010b401200541e0046a20052802382206200528024010d501200541e0036a41086a2207200541e9046a290000370300200541e0036a41106a2208200541f1046a290000370300200541e0036a41186a2209200541f9046a290000370300200520052900e1043703e0034100210a024020052d00e0044101470d00200541e0026a41186a2009290300370300200541e0026a41106a2008290300370300200541e0026a41086a2007290300370300200520052903e0033703e0024101210a0b0240200528023c450d00200610350b02400240200a450d00200541186a41186a200541e0026a41186a2206290300370300200541186a41106a200541e0026a41106a2207290300370300200541186a41086a200541e0026a41086a2208290300370300200520052903e002370318200541f0016a200541186a10b701200541e0046a20052802f001220920052802f80110d601200541a0016a41086a220b200541e0046a41086a290300370300200541a0016a41106a220c200541e0046a41106a290300370300200541a0016a41186a220d200541e0046a41186a290300370300200541e0036a41086a220e2005418c056a290200370300200541e0036a41106a220f20054194056a290200370300200541e0036a41186a22102005419c056a290200370300200541e0036a41206a2211200541a4056a290200370300200541e0036a41286a2212200541ac056a290200370300200541e0036a41306a2213200541b4056a280200360200200520052903e0043703a00120052005290284053703e0030240200528028005220a450d00200541a8026a41186a200d290300370300200541a8026a41106a200c290300370300200541a8026a41086a200b2903003703002008200e2903003703002007200f29030037030020062010290300370300200541e0026a41206a2011290300370300200541e0026a41286a2012290300370300200541e0026a41306a2013280200360200200520052903a0013703a802200520052903e0033703e0020b024020052802f401450d00200910350b200a450d00200541dc006a20052903e002370200200541386a41186a2206200541a8026a41186a290300370300200541386a41106a2207200541a8026a41106a290300370300200541386a41086a2208200541a8026a41086a290300370300200541e4006a200541e0026a41086a290300370200200541ec006a200541e0026a41106a290300370200200541f4006a200541e0026a41186a290300370200200541fc006a20054180036a29030037020020054184016a200541e0026a41286a2903003702002005418c016a20054190036a280200360200200520052903a8023703382005200a36025820082903002114200529033821150240024020072903002216200120162001542006290300221720025420172002511b22071b22182017200220071b22198450450d002015211a2014211b0c010b2006201720197d2016201854ad7d221c3703002005201620187d221a37034802400240201a428080e983b1de1656201c420052201c501b450d0020182116201921170c010b200541d0006a420037030020054200370348201c20027c201a20017c2201201a54ad7c21020b20054200201420177d2015201654ad7d2218201520167d221c201556201820145620182014511b22061b221b37034020054200201c20061b221a370338200220177d2001201654ad7d2102200120167d21010b02400240200541386a41286a28020022060d004100210a410021060c010b200641186c21084100210603400240200a2903002216200120012016562002200a41086a220929030022175620022017511b22071b22182017200220071b221984500d00200a201620187d221a370300200a201720197d2016201854ad7d221c37030802400240201a428080e983b1de1656201c420052201c501b450d002001211c20182116201921170c010b200a4200370308200a42003703002002201c7c2001201a7c221c200154ad7c21020b200541386a41086a220742002007290300220120177d20052903382218201654ad7d2219201820167d221a201856201920015620192001511b22071b221b37030020054200201a20071b221a370338200220177d201c201654ad7d2102201c20167d210120092903002117200a29030021160b024020162017844200520d00200a41186a210a200641016a2106200841686a22080d010b0b2005280260220a2006490d020b200541003602600240200a20066b220a450d0002402006450d00200528025822072007200641186c6a200a41186c109e081a0b2005200a3602600b024042002015201a7d221620162015562014201b7d2015201a54ad7d221620145620162014511b220a1b220242002016200a1b220184500d0020054190016a2000108e02200541a0016a20052802900122062005280298012208108f0220052903a001211b200542003703a001200541e8016a280200210920052d00ec01210b02400240201b4201510d004200211c200541f0016a41306a4200370300200541f0016a41286a4200370300200541f0016a41206a4200370300200541f0016a41186a420037030020054180026a4200370300200541f8016a4200370300200542003703f0014200211942002117420021164200211d0c010b200541d8016a2903002118200541a0016a41306a290300211a200541a0016a41206a2903002119200541a0016a41186a290300211c200541e0016a290300211d20052903b001211620052903a8012117200541f0016a41206a200541a0016a41286a290300370300200541f0016a41286a201a370300200541f0016a41306a201837030020054180026a201c3703002005201937038802200520173703f001200520163703f8010b20052017200220172017200256201620015620162001511b220a1b221a7d22143703f0012005201620012016200a1b221e7d2017201a54ad7d22183703f801201620197c211f2017201c7c2220201754220cad2121200541f0016a41106a210a024002402002201a7d22152001201e7d2002201a54ad7d22228450450d004200211c420021222002211e200121230c010b20054188026a201920222019201c201556201920225620192022511b22071b22237d201c2015201c20071b221754ad7d3703002005201c20177d37038002202220237d2015201754ad7d21222023201e7c2017201a7c221e201754ad7c2123201520177d211c0b201f20217c2117200541a8026a41186a200a41086a2903002219370300200541a8026a41206a2207200a41106a290300370300200541d0026a220d200a41186a290300370300200541d8026a220e200a41206a2903003703002005200a290300221a3703b802200520143703a802200520183703b00202400240427f2014201a7c221a201a201454220a201820197c200aad7c221920185420192018511b220a1b221a428080e983b1de16544100427f2019200a1b2215501b0d00200541b8026a290300211a200e2903002115200d290300211f2007290300212120052903b002212420052903a80221254201211920052903c00221260c010b02400240201a20158450450d00420021190c010b42002119200541e0046a41186a220f4200370300200541e0046a41106a220d4200370300200541e0046a41086a22074200370300200542003703e00441b6fdc600ad4280808080800184221f1001220e290000212120054180066a41086a220a200e41086a2900003703002005202137038006200e10352007200a29030037030020052005290380063703e00441e489c200ad4280808080d0018422211001220e2900002124200a200e41086a2900003703002005202437038006200e1035200d2005290380062224370300200541e0056a41086a22102007290300370300200541e0056a41106a22112024370300200541e0056a41186a2212200a290300370300200520052903e0043703e0052005200541e0056a412010d701200541106a2903002124200529030821252005280200210e200f4200370300200d420037030020074200370300200542003703e004201f1001220f290000211f200a200f41086a2900003703002005201f37038006200f10352007200a29030037030020052005290380063703e00420211001220f290000211f200a200f41086a2900003703002005201f37038006200f1035200d200529038006221f370300201020072903003703002011201f3703002012200a290300370300200520052903e0043703e0052005420020244200200e1b221f20157d20254200200e1b2221201a54ad7d22242021201a7d22252021562024201f562024201f511b220a1b3703e804200542002025200a1b3703e004200541e0056aad4280808080800484200541e0046aad4280808080800284100220054198056a201537030020054190056a201a370300200741013a0000200541e9046a2000290000370000200541f1046a200041086a290000370000200541f9046a200041106a29000037000020054181056a200041186a290000370000200541033a00e00441b0b4cc004100200541e0046a10d4010b0b2017201651210a20172016542107200541c8016a2021370300200541d0016a201f370300200541b0016a2024370300200541d8016a2015370300200541b8016a201a370300200520263703c0012005201d3703e001200520253703a8012005200b4100201b420151220d1b3a00ec01200520094100200d1b3602e801200520194201512209ad3703a0010240024020090d002008ad4220862006ad8410070c010b200520083602e404200520063602e004200541a8016a200541e0046a10e7020b200c2007200a1b210a0240200528029401450d00200610350b427f2017200a1b2116427f2020200a1b21172019420152210a024002400240201b4201510d00200a0d0041032106200541e0036a210a0c010b201b420152200a410173720d0141042106200541e0026a210a0b200a41086a20063a0000200a41003a0000200a41096a2000290000370000200a41116a200041086a290000370000200a41196a200041106a290000370000200a41216a200041186a29000037000041b0b4cc004100200a10d4010b024020172016844200520d0020054198056a201837030020054190056a2014370300200541e0046a41086a41003a0000200541e9046a2000290000370000200541f1046a200041086a290000370000200541f9046a200041106a29000037000020054181056a200041186a290000370000200541033a00e00441b0b4cc004100200541e0046a10d4010b2004427f20042903002216201e7c22172017201654220a200441086a2206290300221620237c200aad7c221720165420172016511b220a1b3703002006427f2017200a1b3703000240201c202284500d002003420020032903002216201c7d22172017201656200341086a220a290300221720227d2016201c54ad7d221620175620162017511b22061b370300200a4200201620061b3703000b200542f3e885db96cddbb3203703e002200541e0026a200541386a41386a2005290338200541386a41086a290300411f109002200541e0046a200541186a10b70120052802e004210a200520052802e8043602e4032005200a3602e003200541386a200541e0036a10e101024020052802e404450d00200a10350b200541e0046a41386a200137030020054190056a2002370300200541e0046a41086a41023a0000200541e9046a2000290000370000200541f1046a200041086a290000370000200541f9046a200041106a29000037000020054181056a200041186a290000370000200541043a00e00441b0b4cc004100200541e0046a10d4010b0240200528025c220a450d00200a41186c450d00200528025810350b200541e8006a28020041ffffffff0371450d00200528026410350b20054190066a24000f0b2006200a104f000bbf0908017f037e037f017e017f017e047f037e230041e0016b22032400200320023703582003200137035002400240200120028450450d0042002104420021050c010b2003200036021c200341206a2000200341d0006a2003411c6a10b002024020032903204201520d00200341306a2903002105200329032821040c010b200341c8006a2903002105200341c0006a290300210420032903284201520d00200341206a41106a290300210620034198016a200341206a41186a29030037030020034190016a2006370300200341e0006a41086a41003a0000200341e9006a2000290000370000200341f1006a200041086a290000370000200341f9006a200041106a29000037000020034181016a200041186a290000370000200341033a006041b0b4cc004100200341e0006a10d4010b200341e0006a41186a22074200370300200341e0006a41106a22084200370300200341e0006a41086a220942003703002003420037036041b6fdc600ad4280808080800184220a1001220b2900002106200341d0006a41086a2200200b41086a29000037030020032006370350200b1035200920002903003703002003200329035037036041e489c200ad4280808080d00184220c1001220b29000021062000200b41086a29000037030020032006370350200b1035200820032903502206370300200341206a41086a220d2009290300370300200341206a41106a220e2006370300200341206a41186a220f2000290300370300200320032903603703202003200341206a412010d701200220057d2001200454ad7d200520027d2004200154ad7d200420015820052002582005200251220b1b22101b2111200120047d200420017d20101b2112200341106a2903004200200328020022101b21062003290308420020101b21130240024020042001562005200256200b1b0d0020074200370300200842003703002009420037030020034200370360200a1001220b29000021012000200b41086a29000037030020032001370350200b10352009200029030037030020032003290350370360200c1001220b29000021012000200b41086a29000037030020032001370350200b103520082003290350370000200841086a2000290300370000200d2009290300370300200e2008290300370300200f20072903003703002003200329036037032020034200200620117d2013201254ad7d2201201320127d2202201356200120065620012006511b22001b37036820034200200220001b370360200341e0006a21000c010b20074200370300200842003703002009420037030020034200370360200a1001220b29000021012000200b41086a29000037030020032001370350200b10352009200029030037030020032003290350370360200c1001220b29000021012000200b41086a29000037030020032001370350200b103520082003290350370000200841086a2000290300370000200d2009290300370300200e2008290300370300200f2007290300370300200320032903603703202003427f200620117c201320127c22022013542200ad7c22012000200120065420012006511b22001b3703682003427f200220001b370360200341e0006a21000b200341206aad42808080808004842000ad42808080808002841002200341e0016a24000bdd0201067f230041d0006b22022400024002400240410410332203450d00200341edde91e306360000410c210420034104410c10372205450d0120052001290000370004200241003a004820052101410021060340200241003a0008200241086a200120044100472203109d081a024020040d00200241003a00080b20042003490d03200241286a20066a20022d00083a00002002200641016a22073a0048200420036b2104200120036a21012007210620074120470d000b200241086a41186a2204200241286a41186a290300370300200241086a41106a2203200241286a41106a290300370300200241086a41086a2201200241286a41086a2903003703002002200229032837030820051035200041186a2004290300370000200041106a2003290300370000200041086a200129030037000020002002290308370000200241d0006a24000f0b1045000b103c000b2003200441b89dcc001059000bd80301067f230041106b2202240020024100360208200242013703000240412010332203450d0020032000290038370000200341086a200041c0006a290000370000200341106a200041c8006a290000370000200341186a200041d0006a29000037000020022003360200200242a080808080043702042002200036020c2002410c6a200210cf012002200041106a36020c2002410c6a200210cf0120002802202103200041286a28020022042002107702402004450d002003200441186c6a210403402002200336020c2002410c6a200210cf01200341106a200210e2012004200341186a2203470d000b0b200028022c2105200041346a28020022032002107702400240024020022802042206200228020822046b20034102742200490d0020022802002103200621070c010b200420006a22032004490d01200641017422072003200720034b1b22074100480d010240024020060d00024020070d00410121030c020b2007103322030d010c040b2002280200210320062007460d0020032006200710372203450d030b20022007360204200220033602000b200320046a20052000109d081a2001290200200420006aad4220862003ad84100202402007450d00200310350b200241106a24000f0b103e000b103c000bb30101027f230041106b2202240002400240024002402000280200220341c000490d00200341808001490d012003418080808004490d02200241033a00032001200241036a41011078200220002802003602042001200241046a410410780c030b200220034102743a00032001200241036a410110780c020b200220034102744101723b010a20012002410a6a410210780c010b2002200341027441027236020c20012002410c6a410410780b200241106a24000b13002000411836020420004180b7c0003602000bab0407047f017e017f017e017f017e037f230041d0006b22002400200041206a41186a22014200370300200041206a41106a22024200370300200041206a41086a220342003703002000420037032041f7edcb00ad4280808080f000842204100122052900002106200041c0006a41086a2207200541086a290000370300200020063703402005103520032007290300370300200020002903403703204193eecb00ad428080808080018422081001220529000021062007200541086a2900003703002000200637034020051035200220002903402206370300200041086a22092003290300370300200041106a220a2006370300200041186a220b2007290300370300200020002903203703000240024002404100200010e5012205200541ff01714104461b41ff0171417f6a220541024b0d0020050e03010001010b2001420037030020024200370300200342003703002000420037032020041001220529000021062007200541086a2900003703002000200637034020051035200320072903003703002000200029034037032020081001220529000021062007200541086a290000370300200020063703402005103520022000290340370000200241086a200729030037000020092003290300370300200a2002290300370300200b200129030037030020002000290320370300410110332207450d01200741013a00002000ad42808080808004842007ad428080808010841002200710350b200041d0006a24000f0b103c000b810201037f230041d0006b220124002001412036020420012000360200200141086a2000ad4280808080800484100510c20102400240200128020822020d00410421000c010b200128020c210302400240200141106a280200450d0020022d000022004104490d010b20014100360220200142013703182001410936022c200120013602282001200141186a360234200141cc006a41013602002001420137023c200141c888c2003602382001200141286a360248200141346a41e88ac500200141386a10431a200135022042208620013502188410060240200128021c450d00200128021810350b410421000b2003450d00200210350b200141d0006a240020000b3400200041f7edcb0036020420004100360200200041146a4124360200200041106a41bcaac100360200200041086a42073702000b2b01017f02404101103322020d00103c000b200042818080801037020420002002360200200241023a00000b2b01017f02404101103322020d00103c000b200042818080801037020420002002360200200241003a00000b5301017f0240411010332202450d00200242003700082002420037000020024110412010372202450d0020024200370010200042a0808080800437020420002002360200200241186a42003700000f0b103c000b940302047f017e230041206b2203240002400240200241d8006c4104722204417f4c0d00200410332205450d0120034100360208200320043602042003200536020020022003107702402002450d002001200241d8006c6a210603402003200141386a41201078200129030021072003200141086a290300370318200320073703102003200341106a4110107820012802202102200128022822042003107702402004450d002002200441306c6a210403402003200241201078200241206a29030021072003200241286a290300370318200320073703102003200341106a411010782004200241306a2202470d000b0b200141d8006a2105200128022c2102200141346a28020022042003107702402004450d002004410574210403402003200241201078200241206a2102200441606a22040d000b0b200129031021072003200141186a290300370318200320073703102003200341106a411010782005210120052006470d000b0b20002003290300370200200041086a200341086a280200360200200341206a24000f0b1044000b1045000b3301017f02404110103322020d001045000b2002420037000820024200370000200042908080808002370204200020023602000b860101027f230041206b220224002002410c6a410036020020024200370300200241003602182002420137031002404104103322030d00103c000b200341003600002002200336021020024284808080c00037021420024104722203200241106a10b001200041086a200228021836020020002002290310370200200310b101200241206a24000be90101047f230041106b220224002002410036020c02400240410110332203450d000240024002400240200228020c220441c000490d00200441808001490d012004418080808004490d02200341033a0000200228020c21044105210520034101410510372203450d05200320043600010c030b200320044102743a0000410121050c020b4102210520034101410210372203450d03200320044102744101723b00000c010b4104210520034101410410372203450d02200320044102744102723600000b200020053602082000200536020420002003360200200241106a24000f0b1045000b103c000bf60301087f230041c0006b22022400200241186a4200370300200241106a22034200370300200241086a4200370300200241286a22044100360200200242003703002002420837032020024100360238200242013703302002200236023c2002413c6a200241306a10cf012002200336023c2002413c6a200241306a10cf012002280220210320042802002204200241306a10770240024002402004450d00200441306c210503400240024020022802342206200228023822046b4120490d00200441206a2107200228023021080c010b200441206a22072004490d03200641017422082007200820074b1b22094100480d030240024020060d00024020090d00410121080c020b2009103322080d010c060b2002280230210820062009460d0020082006200910372208450d050b20022009360234200220083602300b200820046a2204200341106a290000370000200441186a200341286a290000370000200441106a200341206a290000370000200441086a200341186a290000370000200220073602382002200336023c2002413c6a200241306a10cf01200341306a2103200541506a22050d000b0b20002002290330370200200041086a200241306a41086a280200360200024020022802242203450d00200341306c450d00200228022010350b200241c0006a24000f0b103e000b103c000b2c01017f02404104103322020d001045000b20004284808080c00037020420002002360200200241043600000b2d01017f02404104103322020d001045000b20004284808080c00037020420002002360200200241d4003600000b820b06057f017e017f017e047f0a7e23004190016b22022400200241386a41186a2203420037030041102104200241386a41106a22054200370300200241386a41086a220642003703002002420037033841f7edcb00ad4280808080f000842207100122082900002109200241d8006a41086a220a200841086a29000037030020022009370358200810352006200a2903003703002002200229035837033841b6aac000ad4280808080900284100122082900002109200a200841086a2900003703002002200937035820081035200520022903582209370300200241186a41086a220b2006290300370300200241186a41106a2009370300200241186a41186a220c200a29030037030020022002290338370318200241106a200241186a10f20102402002280210417d71450d002003420037030041102104200241386a41106a220d420037030020064200370300200242003703382007100122082900002109200a200841086a29000037030020022009370358200810352006200a2903003703002002200229035837033841e4edcb00ad4280808080a00184100122082900002109200a200841086a290000370300200220093703582008103520052002290358370000200541086a200a290300370000200b2006290300370300200241186a41106a200d290300370300200c200329030037030020022002290338370318200241086a200241186a412010c001024020022802084101470d00200228020c2001470d010b42002109200241386a41186a22044200370300200241386a41106a22034200370300200241386a41086a220642003703002002420037033841f7edcb00ad4280808080f00084100122082900002107200241d8006a41086a220a200841086a29000037030020022007370358200810352006200a2903003703002002200229035837033841ceeecb00ad4280808080b00184100122082900002107200a200841086a290000370300200220073703582008103520052002290358370000200541086a200a290300370000200241186a41086a2006290300370300200241186a41106a2003290300370300200241186a41186a2004290300370300200220022903383703182002412036026c2002200241186a360268200241f0006a200241186aad4280808080800484100510c201024002402002280270220a0d000c010b20022802742106024002400240200241f0006a41086a28020022054110490d00200541707122054110460d0020054120470d010b200241003602602002420137035820024109360284012002200241e8006a360280012002200241d8006a36028c01200241cc006a41013602002002420137023c200241c888c200360238200220024180016a3602482002418c016a41e88ac500200241386a10431a200235026042208620023502588410060240200228025c450d00200228025810350b420021090c010b200a41086a290000210e200a290000210f200a41286a2900002107200a41186a2900002110200a2900202111200a2900102112420121090b2006450d00200a10350b0240024002402009500d00200041286a2903002109200041186a2903002113200041086a290300211420002903202115200029031021162000290300211741031033220a450d01200a417f20152011852009200785844200522015201154200920075420092007511b22081b3a0002200a417f20162012852013201085844200522016201254201320105420132010511b1b22053a0001200a417f2017200f852014200e85844200522017200f542014200e542014200e511b1b22063a0000200641014b0d020240024020060e020001000b200541014b0d03024020050e020001000b200a1035411121042008450d040c010b200a10350b411d21040c020b103c000b200a1035411121040b20024190016a240020040bb40201067f230041d0006b220224002002412036020420022001360200200241086a2001ad4280808080800484100510c20102400240200228020822030d00410221010c010b200228020c210402400240200241106a2802002205450d0020032d0000220641014b0d0041002101024020060e020200020b2005417f6a4104490d0020032800012107410121010c010b20024100360220200242013703182002410936022c200220023602282002200241186a360234200241cc006a41013602002002420137023c200241c888c2003602382002200241286a360248200241346a41e88ac500200241386a10431a200235022042208620023502188410060240200228021c450d00200228021810350b410221010b2004450d00200310350b2000200736020420002001360200200241d0006a24000b130020004102360204200041f0f0c1003602000b2d01017f02404104103322020d001045000b20004284808080c00037020420002002360200200241a0053600000b2c01017f02404104103322020d001045000b20004284808080c00037020420002002360200200241063600000bde0506067f017e017f017e017f017e230041206b220224000240024020012802042203450d00200128020022042d0000210520012003417f6a22063602042001200441016a360200024002400240200541037122074103460d0002400240024020070e03000102000b2005410276ad21080c040b410121072006450d0220042d0001210620012003417e6a3602042001200441026a3602002006410874200572220141ffff0371418002490d02200141fcff0371410276ad21080c030b4101210720064103490d01200441036a2d0000210620042f0001210920012003417c6a3602042001200441046a3602002009200641107472410874200572220141808004490d012001410276ad21080c020b024020054102762209410c4b0d0002400240024020090e0d00030303010303030303030302000b20064104490d052004350001210820012003417b6a3602042001200441056a36020020084280808080045421074200210a0c060b20064108490d04200429000121082001200341776a3602042001200441096a3602002008428080808080808080015421074200210a0c050b20064110490d03200441096a290000210a2004290001210820012003416f6a3602042001200441116a360200200a428080808080808080015421070c040b200941046a220641104b0d022003417e6a2103200441026a21044100210541012107200241186a210b420021084200210a03402003417f460d01200241106a2004417f6a3100004200200541037441f8007110a30820012003360204200120043602002003417f6a2103200441016a2104200b290300200a84210a20022903102008842108200541016a220541ff01712006490d000b2002427f427f41e80020094103746b41f8007110a4082008200229030058200a200241086a290300220c58200a200c511b21070c030b0c020b4200210a410021070c010b410121070b20002008370308200041106a200a37030020002007ad370300200241206a24000bd53901037f230041106b2202240020002802002103200028020822042001107702402004450d00200320044103746a210403402002200328020036020c20012002410c6a410410782002200341046a2f01003b010c20012002410c6a41021078200341086a22032004470d000b0b200028020c2103200041146a28020022042001107702402004450d0020032004410c6c6a210403402002200328020036020c20012002410c6a410410782002200341046a2f01003b010c20012002410c6a410210782002200341066a2f01003b010c20012002410c6a410210782002200341086a2f01003b010c20012002410c6a410210782003410c6a22032004470d000b0b20002802182103200041206a28020022042001107702402004450d00200320044104746a210403402002200328020036020c20012002410c6a410410782002200341046a2f01003b010c20012002410c6a410210782002200341066a2f01003b010c20012002410c6a410210782002200341086a2f01003b010c20012002410c6a4102107820022003410a6a2f01003b010c20012002410c6a4102107820022003410c6a2f01003b010c20012002410c6a41021078200341106a22032004470d000b0b200028022421032000412c6a28020022042001107702402004450d002003200441146c6a210403402002200328020036020c20012002410c6a410410782002200341046a2f01003b010c20012002410c6a410210782002200341066a2f01003b010c20012002410c6a410210782002200341086a2f01003b010c20012002410c6a4102107820022003410a6a2f01003b010c20012002410c6a4102107820022003410c6a2f01003b010c20012002410c6a4102107820022003410e6a2f01003b010c20012002410c6a410210782002200341106a2f01003b010c20012002410c6a41021078200341146a22032004470d000b0b20002802302103200041386a28020022042001107702402004450d002003200441186c6a210403402002200328020036020c20012002410c6a410410782002200341046a2f01003b010c20012002410c6a410210782002200341066a2f01003b010c20012002410c6a410210782002200341086a2f01003b010c20012002410c6a4102107820022003410a6a2f01003b010c20012002410c6a4102107820022003410c6a2f01003b010c20012002410c6a4102107820022003410e6a2f01003b010c20012002410c6a410210782002200341106a2f01003b010c20012002410c6a410210782002200341126a2f01003b010c20012002410c6a410210782002200341146a2f01003b010c20012002410c6a41021078200341186a22032004470d000b0b200028023c2103200041c4006a28020022042001107702402004450d0020032004411c6c6a210403402002200328020036020c20012002410c6a410410782002200341046a2f01003b010c20012002410c6a410210782002200341066a2f01003b010c20012002410c6a410210782002200341086a2f01003b010c20012002410c6a4102107820022003410a6a2f01003b010c20012002410c6a4102107820022003410c6a2f01003b010c20012002410c6a4102107820022003410e6a2f01003b010c20012002410c6a410210782002200341106a2f01003b010c20012002410c6a410210782002200341126a2f01003b010c20012002410c6a410210782002200341146a2f01003b010c20012002410c6a410210782002200341166a2f01003b010c20012002410c6a410210782002200341186a2f01003b010c20012002410c6a410210782003411c6a22032004470d000b0b20002802482103200041d0006a28020022042001107702402004450d00200320044105746a210403402002200328020036020c20012002410c6a410410782002200341046a2f01003b010c20012002410c6a410210782002200341066a2f01003b010c20012002410c6a410210782002200341086a2f01003b010c20012002410c6a4102107820022003410a6a2f01003b010c20012002410c6a4102107820022003410c6a2f01003b010c20012002410c6a4102107820022003410e6a2f01003b010c20012002410c6a410210782002200341106a2f01003b010c20012002410c6a410210782002200341126a2f01003b010c20012002410c6a410210782002200341146a2f01003b010c20012002410c6a410210782002200341166a2f01003b010c20012002410c6a410210782002200341186a2f01003b010c20012002410c6a4102107820022003411a6a2f01003b010c20012002410c6a4102107820022003411c6a2f01003b010c20012002410c6a41021078200341206a22032004470d000b0b20002802542103200041dc006a28020022042001107702402004450d002003200441246c6a210403402002200328020036020c20012002410c6a410410782002200341046a2f01003b010c20012002410c6a410210782002200341066a2f01003b010c20012002410c6a410210782002200341086a2f01003b010c20012002410c6a4102107820022003410a6a2f01003b010c20012002410c6a4102107820022003410c6a2f01003b010c20012002410c6a4102107820022003410e6a2f01003b010c20012002410c6a410210782002200341106a2f01003b010c20012002410c6a410210782002200341126a2f01003b010c20012002410c6a410210782002200341146a2f01003b010c20012002410c6a410210782002200341166a2f01003b010c20012002410c6a410210782002200341186a2f01003b010c20012002410c6a4102107820022003411a6a2f01003b010c20012002410c6a4102107820022003411c6a2f01003b010c20012002410c6a4102107820022003411e6a2f01003b010c20012002410c6a410210782002200341206a2f01003b010c20012002410c6a41021078200341246a22032004470d000b0b20002802602103200041e8006a28020022042001107702402004450d002003200441286c6a210403402002200328020036020c20012002410c6a410410782002200341046a2f01003b010c20012002410c6a410210782002200341066a2f01003b010c20012002410c6a410210782002200341086a2f01003b010c20012002410c6a4102107820022003410a6a2f01003b010c20012002410c6a4102107820022003410c6a2f01003b010c20012002410c6a4102107820022003410e6a2f01003b010c20012002410c6a410210782002200341106a2f01003b010c20012002410c6a410210782002200341126a2f01003b010c20012002410c6a410210782002200341146a2f01003b010c20012002410c6a410210782002200341166a2f01003b010c20012002410c6a410210782002200341186a2f01003b010c20012002410c6a4102107820022003411a6a2f01003b010c20012002410c6a4102107820022003411c6a2f01003b010c20012002410c6a4102107820022003411e6a2f01003b010c20012002410c6a410210782002200341206a2f01003b010c20012002410c6a410210782002200341226a2f01003b010c20012002410c6a410210782002200341246a2f01003b010c20012002410c6a41021078200341286a22032004470d000b0b200028026c2103200041f4006a28020022042001107702402004450d0020032004412c6c6a210403402002200328020036020c20012002410c6a410410782002200341046a2f01003b010c20012002410c6a410210782002200341066a2f01003b010c20012002410c6a410210782002200341086a2f01003b010c20012002410c6a4102107820022003410a6a2f01003b010c20012002410c6a4102107820022003410c6a2f01003b010c20012002410c6a4102107820022003410e6a2f01003b010c20012002410c6a410210782002200341106a2f01003b010c20012002410c6a410210782002200341126a2f01003b010c20012002410c6a410210782002200341146a2f01003b010c20012002410c6a410210782002200341166a2f01003b010c20012002410c6a410210782002200341186a2f01003b010c20012002410c6a4102107820022003411a6a2f01003b010c20012002410c6a4102107820022003411c6a2f01003b010c20012002410c6a4102107820022003411e6a2f01003b010c20012002410c6a410210782002200341206a2f01003b010c20012002410c6a410210782002200341226a2f01003b010c20012002410c6a410210782002200341246a2f01003b010c20012002410c6a410210782002200341266a2f01003b010c20012002410c6a410210782002200341286a2f01003b010c20012002410c6a410210782003412c6a22032004470d000b0b2000280278210320004180016a28020022042001107702402004450d002003200441306c6a210403402002200328020036020c20012002410c6a410410782002200341046a2f01003b010c20012002410c6a410210782002200341066a2f01003b010c20012002410c6a410210782002200341086a2f01003b010c20012002410c6a4102107820022003410a6a2f01003b010c20012002410c6a4102107820022003410c6a2f01003b010c20012002410c6a4102107820022003410e6a2f01003b010c20012002410c6a410210782002200341106a2f01003b010c20012002410c6a410210782002200341126a2f01003b010c20012002410c6a410210782002200341146a2f01003b010c20012002410c6a410210782002200341166a2f01003b010c20012002410c6a410210782002200341186a2f01003b010c20012002410c6a4102107820022003411a6a2f01003b010c20012002410c6a4102107820022003411c6a2f01003b010c20012002410c6a4102107820022003411e6a2f01003b010c20012002410c6a410210782002200341206a2f01003b010c20012002410c6a410210782002200341226a2f01003b010c20012002410c6a410210782002200341246a2f01003b010c20012002410c6a410210782002200341266a2f01003b010c20012002410c6a410210782002200341286a2f01003b010c20012002410c6a4102107820022003412a6a2f01003b010c20012002410c6a4102107820022003412c6a2f01003b010c20012002410c6a41021078200341306a22032004470d000b0b20002802840121032000418c016a28020022042001107702402004450d002003200441346c6a210403402002200328020036020c20012002410c6a410410782002200341046a2f01003b010c20012002410c6a410210782002200341066a2f01003b010c20012002410c6a410210782002200341086a2f01003b010c20012002410c6a4102107820022003410a6a2f01003b010c20012002410c6a4102107820022003410c6a2f01003b010c20012002410c6a4102107820022003410e6a2f01003b010c20012002410c6a410210782002200341106a2f01003b010c20012002410c6a410210782002200341126a2f01003b010c20012002410c6a410210782002200341146a2f01003b010c20012002410c6a410210782002200341166a2f01003b010c20012002410c6a410210782002200341186a2f01003b010c20012002410c6a4102107820022003411a6a2f01003b010c20012002410c6a4102107820022003411c6a2f01003b010c20012002410c6a4102107820022003411e6a2f01003b010c20012002410c6a410210782002200341206a2f01003b010c20012002410c6a410210782002200341226a2f01003b010c20012002410c6a410210782002200341246a2f01003b010c20012002410c6a410210782002200341266a2f01003b010c20012002410c6a410210782002200341286a2f01003b010c20012002410c6a4102107820022003412a6a2f01003b010c20012002410c6a4102107820022003412c6a2f01003b010c20012002410c6a4102107820022003412e6a2f01003b010c20012002410c6a410210782002200341306a2f01003b010c20012002410c6a41021078200341346a22032004470d000b0b200028029001210320004198016a28020022042001107702402004450d002003200441386c6a210403402002200328020036020c20012002410c6a410410782002200341046a2f01003b010c20012002410c6a410210782002200341066a2f01003b010c20012002410c6a410210782002200341086a2f01003b010c20012002410c6a4102107820022003410a6a2f01003b010c20012002410c6a4102107820022003410c6a2f01003b010c20012002410c6a4102107820022003410e6a2f01003b010c20012002410c6a410210782002200341106a2f01003b010c20012002410c6a410210782002200341126a2f01003b010c20012002410c6a410210782002200341146a2f01003b010c20012002410c6a410210782002200341166a2f01003b010c20012002410c6a410210782002200341186a2f01003b010c20012002410c6a4102107820022003411a6a2f01003b010c20012002410c6a4102107820022003411c6a2f01003b010c20012002410c6a4102107820022003411e6a2f01003b010c20012002410c6a410210782002200341206a2f01003b010c20012002410c6a410210782002200341226a2f01003b010c20012002410c6a410210782002200341246a2f01003b010c20012002410c6a410210782002200341266a2f01003b010c20012002410c6a410210782002200341286a2f01003b010c20012002410c6a4102107820022003412a6a2f01003b010c20012002410c6a4102107820022003412c6a2f01003b010c20012002410c6a4102107820022003412e6a2f01003b010c20012002410c6a410210782002200341306a2f01003b010c20012002410c6a410210782002200341326a2f01003b010c20012002410c6a410210782002200341346a2f01003b010c20012002410c6a41021078200341386a22032004470d000b0b200028029c012103200041a4016a28020022042001107702402004450d0020032004413c6c6a210403402002200328020036020c20012002410c6a410410782002200341046a2f01003b010c20012002410c6a410210782002200341066a2f01003b010c20012002410c6a410210782002200341086a2f01003b010c20012002410c6a4102107820022003410a6a2f01003b010c20012002410c6a4102107820022003410c6a2f01003b010c20012002410c6a4102107820022003410e6a2f01003b010c20012002410c6a410210782002200341106a2f01003b010c20012002410c6a410210782002200341126a2f01003b010c20012002410c6a410210782002200341146a2f01003b010c20012002410c6a410210782002200341166a2f01003b010c20012002410c6a410210782002200341186a2f01003b010c20012002410c6a4102107820022003411a6a2f01003b010c20012002410c6a4102107820022003411c6a2f01003b010c20012002410c6a4102107820022003411e6a2f01003b010c20012002410c6a410210782002200341206a2f01003b010c20012002410c6a410210782002200341226a2f01003b010c20012002410c6a410210782002200341246a2f01003b010c20012002410c6a410210782002200341266a2f01003b010c20012002410c6a410210782002200341286a2f01003b010c20012002410c6a4102107820022003412a6a2f01003b010c20012002410c6a4102107820022003412c6a2f01003b010c20012002410c6a4102107820022003412e6a2f01003b010c20012002410c6a410210782002200341306a2f01003b010c20012002410c6a410210782002200341326a2f01003b010c20012002410c6a410210782002200341346a2f01003b010c20012002410c6a410210782002200341366a2f01003b010c20012002410c6a410210782002200341386a2f01003b010c20012002410c6a410210782003413c6a22032004470d000b0b20002802a8012103200041b0016a28020022042001107702402004450d00200320044106746a210403402002200328020036020c20012002410c6a410410782002200341046a2f01003b010c20012002410c6a410210782002200341066a2f01003b010c20012002410c6a410210782002200341086a2f01003b010c20012002410c6a4102107820022003410a6a2f01003b010c20012002410c6a4102107820022003410c6a2f01003b010c20012002410c6a4102107820022003410e6a2f01003b010c20012002410c6a410210782002200341106a2f01003b010c20012002410c6a410210782002200341126a2f01003b010c20012002410c6a410210782002200341146a2f01003b010c20012002410c6a410210782002200341166a2f01003b010c20012002410c6a410210782002200341186a2f01003b010c20012002410c6a4102107820022003411a6a2f01003b010c20012002410c6a4102107820022003411c6a2f01003b010c20012002410c6a4102107820022003411e6a2f01003b010c20012002410c6a410210782002200341206a2f01003b010c20012002410c6a410210782002200341226a2f01003b010c20012002410c6a410210782002200341246a2f01003b010c20012002410c6a410210782002200341266a2f01003b010c20012002410c6a410210782002200341286a2f01003b010c20012002410c6a4102107820022003412a6a2f01003b010c20012002410c6a4102107820022003412c6a2f01003b010c20012002410c6a4102107820022003412e6a2f01003b010c20012002410c6a410210782002200341306a2f01003b010c20012002410c6a410210782002200341326a2f01003b010c20012002410c6a410210782002200341346a2f01003b010c20012002410c6a410210782002200341366a2f01003b010c20012002410c6a410210782002200341386a2f01003b010c20012002410c6a4102107820022003413a6a2f01003b010c20012002410c6a4102107820022003413c6a2f01003b010c20012002410c6a41021078200341c0006a22032004470d000b0b20002802b4012103200041bc016a28020022002001107702402000450d002003200041c4006c6a210003402002200328020036020c20012002410c6a410410782002200341046a2f01003b010c20012002410c6a410210782002200341066a2f01003b010c20012002410c6a410210782002200341086a2f01003b010c20012002410c6a4102107820022003410a6a2f01003b010c20012002410c6a4102107820022003410c6a2f01003b010c20012002410c6a4102107820022003410e6a2f01003b010c20012002410c6a410210782002200341106a2f01003b010c20012002410c6a410210782002200341126a2f01003b010c20012002410c6a410210782002200341146a2f01003b010c20012002410c6a410210782002200341166a2f01003b010c20012002410c6a410210782002200341186a2f01003b010c20012002410c6a4102107820022003411a6a2f01003b010c20012002410c6a4102107820022003411c6a2f01003b010c20012002410c6a4102107820022003411e6a2f01003b010c20012002410c6a410210782002200341206a2f01003b010c20012002410c6a410210782002200341226a2f01003b010c20012002410c6a410210782002200341246a2f01003b010c20012002410c6a410210782002200341266a2f01003b010c20012002410c6a410210782002200341286a2f01003b010c20012002410c6a4102107820022003412a6a2f01003b010c20012002410c6a4102107820022003412c6a2f01003b010c20012002410c6a4102107820022003412e6a2f01003b010c20012002410c6a410210782002200341306a2f01003b010c20012002410c6a410210782002200341326a2f01003b010c20012002410c6a410210782002200341346a2f01003b010c20012002410c6a410210782002200341366a2f01003b010c20012002410c6a410210782002200341386a2f01003b010c20012002410c6a4102107820022003413a6a2f01003b010c20012002410c6a4102107820022003413c6a2f01003b010c20012002410c6a4102107820022003413e6a2f01003b010c20012002410c6a410210782002200341c0006a2f01003b010c20012002410c6a41021078200341c4006a22032000470d000b0b200241106a24000bd2ae0109097f017e067f037e217f027e0b7f017e047f23004190046b22022400200241f8006a200110c4010240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020022802780d00200228027c220320012802044103762204200420034b1b22054103742204417f4c0d020240024020050d00410421060c010b200410332206450d040b41002104200241003602980320022005360294032002200636029003024002402003450d00410021040340200128020422054104490d0220012802002207280000210820012005417c6a22093602042001200741046a220736020020094102490d0220072f0000210920012005417a6a3602042001200741026a36020002402004200228029403470d0020024190036a20044101109001200228029003210620022802980321040b200620044103746a220520093b0104200520083602002002200441016a2204360298032003417f6a22030d000b20022802940321050b2006450d01200241f0006a200110c4012002280270450d020c180b20022802940341ffffffff0171450d00200610350b200041003602000c180b2002280274220a2001280204410c6e22072007200a4b1bad420c7e220b422088a70d00200ba72203417f4c0d000240024020030d004104210c0c010b20031033220c450d020b4100210720024100360298032002200c3602900320022003410c6e220d36029403024002400240200a450d00410021070340200128020422034104490d0220012802002209280000210e20012003417c6a220d3602042001200941046a2208360200200d4102490d0220082f0000210f20012003417a6a220d3602042001200841026a360200200d4102490d0220092f0006210d2001200341786a22083602042001200941086a220936020020084102490d0220092f000021082001200341766a3602042001200941026a36020002402007200228029403470d0020024190036a20074101108701200228029003210c20022802980321070b200c2007410c6c6a220320083b01082003200f3b01042003200e360200200341066a200d3b01002002200741016a220736029803200a417f6a220a0d000b200228029403210d0b200c450d17200241e8006a200110c4012002280268450d010c160b2002280294032201450d162001410c6c450d16200c10350c160b4104210f200228026c220e200128020441047622032003200e4b1b22034104742209417f4c0d0002402003450d0020091033220f450d020b41002108200241003602980320022003360294032002200f36029003024002400240200e450d00410021080340200128020422034104490d0220012802002209280000211020012003417c6a22113602042001200941046a220a36020020114102490d02200a330000210b20012003417a6a22113602042001200a41026a36020020114102490d02200933000621122001200341786a22113602042001200941086a220a36020020114102490d02200a33000021132001200341766a22113602042001200a41026a36020020114102490d02200933000a21142001200341746a220a36020420012009410c6a2209360200200a4102490d0220092f0000210a2001200341726a3602042001200941026a3602002014423086201342208684201242108684200b84210b02402008200228029403470d0020024190036a20084101108c01200228029003210f20022802980321080b200f20084104746a2203200a3b010c2003200b370204200320103602002002200841016a220836029803200e417f6a220e0d000b20022802940321030b200f450d16200241e0006a200110c4012002280260450d010c150b20022802940341ffffffff0071450d15200f10350c150b20022802642210200128020441146e2209200920104b1bad42147e220b422088a70d00200ba72209417f4c0d000240024020090d00410421150c010b200910332215450d020b4100210e200241003602980320022015360290032002200941146e2211360294030240024002402010450d004100210e0340200128020422094104490d022001280200220a280000211620012009417c6a22173602042001200a41046a221136020020174102490d0220112f0000211820012009417a6a22173602042001201141026a36020020174102490d02200a2f000621192001200941786a22173602042001200a41086a221136020020174102490d0220112f0000211a2001200941766a22173602042001201141026a36020020174102490d02200a2f000a211b2001200941746a22173602042001200a410c6a221136020020174102490d0220112f0000211c2001200941726a22173602042001201141026a36020020174102490d02200a2f000e21172001200941706a22113602042001200a41106a220a36020020114102490d02200a2f0000211120012009416e6a3602042001200a41026a3602000240200e200228029403470d0020024190036a200e41011099012002280290032115200228029803210e0b2015200e41146c6a220920113b0110200920183b0104200920163602002009410e6a20173b01002009410c6a201c3b01002009410a6a201b3b0100200941086a201a3b0100200941066a20193b01002002200e41016a220e360298032010417f6a22100d000b20022802940321110b2015450d15200241d8006a200110c4012002280258450d010c140b2002280294032201450d14200141146c450d14201510350c140b200228025c2217200128020441186e2209200920174b1bad42187e220b422088a70d00200ba72209417f4c0d000240024020090d00410421180c010b200910332218450d020b41002110200241003602980320022018360290032002200941186e2216360294030240024002402017450d00410021100340200128020422094104490d022001280200220a280000211a20012009417c6a22193602042001200a41046a221636020020194102490d0220162f0000211b20012009417a6a22193602042001201641026a36020020194102490d02200a2f0006211c2001200941786a22193602042001200a41086a221636020020194102490d0220162f0000211d2001200941766a22193602042001201641026a36020020194102490d02200a2f000a211e2001200941746a22193602042001200a410c6a221636020020194102490d0220162f0000211f2001200941726a22193602042001201641026a36020020194102490d02200a2f000e21202001200941706a22193602042001200a41106a221636020020194102490d0220162f0000212120012009416e6a22193602042001201641026a36020020194102490d02200a2f0012211920012009416c6a22163602042001200a41146a220a36020020164102490d02200a2f0000211620012009416a6a3602042001200a41026a36020002402010200228029403470d0020024190036a20104101109701200228029003211820022802980321100b2018201041186c6a220920163b01142009201b3b01042009201a360200200941126a20193b0100200941106a20213b01002009410e6a20203b01002009410c6a201f3b01002009410a6a201e3b0100200941086a201d3b0100200941066a201c3b01002002201041016a2210360298032017417f6a22170d000b20022802940321160b2018450d14200241d0006a200110c4012002280250450d010c130b2002280294032201450d13200141186c450d13201810350c130b200228025422192001280204411c6e2209200920194b1bad421c7e220b422088a70d00200ba72209417f4c0d000240024020090d004104211b0c010b20091033221b450d020b4100211720024100360298032002201b3602900320022009411c6e221a360294030240024002402019450d00410021170340200128020422094104490d022001280200220a280000211d20012009417c6a221c3602042001200a41046a221a360200201c4102490d02201a2f0000211e20012009417a6a221c3602042001201a41026a360200201c4102490d02200a2f0006211f2001200941786a221c3602042001200a41086a221a360200201c4102490d02201a2f000021202001200941766a221c3602042001201a41026a360200201c4102490d02200a2f000a21212001200941746a221c3602042001200a410c6a221a360200201c4102490d02201a2f000021222001200941726a221c3602042001201a41026a360200201c4102490d02200a2f000e21232001200941706a221c3602042001200a41106a221a360200201c4102490d02201a2f0000212420012009416e6a221c3602042001201a41026a360200201c4102490d02200a2f0012212520012009416c6a221c3602042001200a41146a221a360200201c4102490d02201a2f0000212620012009416a6a221c3602042001201a41026a360200201c4102490d02200a2f0016211c2001200941686a221a3602042001200a41186a220a360200201a4102490d02200a2f0000211a2001200941666a3602042001200a41026a36020002402017200228029403470d0020024190036a2017410110f901200228029003211b20022802980321170b201b2017411c6c6a2209201a3b01182009201e3b01042009201d360200200941166a201c3b0100200941146a20263b0100200941126a20253b0100200941106a20243b01002009410e6a20233b01002009410c6a20223b01002009410a6a20213b0100200941086a20203b0100200941066a201f3b01002002201741016a2217360298032019417f6a22190d000b200228029403211a0b201b450d13200241c8006a200110c4012002280248450d010c120b2002280294032201450d122001411c6c450d12201b10350c120b200228024c221c200128020441057622092009201c4b1b2209410574220a417f4c0d000240024020090d004104211e0c010b200a1033221e450d020b41002119200241003602980320022009360294032002201e36029003024002400240201c450d00410021190340200128020422094104490d022001280200220a280000212020012009417c6a221f3602042001200a41046a221d360200201f4102490d02201d2f0000212120012009417a6a221f3602042001201d41026a360200201f4102490d02200a2f000621222001200941786a221f3602042001200a41086a221d360200201f4102490d02201d2f000021232001200941766a221f3602042001201d41026a360200201f4102490d02200a2f000a21242001200941746a221f3602042001200a410c6a221d360200201f4102490d02201d2f000021252001200941726a221f3602042001201d41026a360200201f4102490d02200a2f000e21262001200941706a221f3602042001200a41106a221d360200201f4102490d02201d2f0000212720012009416e6a221f3602042001201d41026a360200201f4102490d02200a2f0012212820012009416c6a221f3602042001200a41146a221d360200201f4102490d02201d2f0000212920012009416a6a221f3602042001201d41026a360200201f4102490d02200a2f0016212a2001200941686a221f3602042001200a41186a221d360200201f4102490d02201d2f0000212b2001200941666a221f3602042001201d41026a360200201f4102490d02200a2f001a211f2001200941646a221d3602042001200a411c6a220a360200201d4102490d02200a2f0000211d2001200941626a3602042001200a41026a36020002402019200228029403470d0020024190036a20194101109101200228029003211e20022802980321190b201e20194105746a2209201d3b011c200920213b0104200920203602002009411a6a201f3b0100200941186a202b3b0100200941166a202a3b0100200941146a20293b0100200941126a20283b0100200941106a20273b01002009410e6a20263b01002009410c6a20253b01002009410a6a20243b0100200941086a20233b0100200941066a20223b01002002201941016a221936029803201c417f6a221c0d000b20022802940321090b201e450d12200241c0006a200110c4012002280240450d010c110b20022802940341ffffff3f71450d11201e10350c110b2002280244221f200128020441246e220a200a201f4b1bad42247e220b422088a70d00200ba7220a417f4c0d0002400240200a0d00410421210c010b200a10332221450d020b4100211d200241003602980320022021360290032002200a41246e222036029403024002400240201f450d004100211d03402001280204220a4104490d022001280200221c28000021232001200a417c6a22223602042001201c41046a222036020020224102490d0220202f000021242001200a417a6a22223602042001202041026a36020020224102490d02201c2f000621252001200a41786a22223602042001201c41086a222036020020224102490d0220202f000021262001200a41766a22223602042001202041026a36020020224102490d02201c2f000a21272001200a41746a22223602042001201c410c6a222036020020224102490d0220202f000021282001200a41726a22223602042001202041026a36020020224102490d02201c2f000e21292001200a41706a22223602042001201c41106a222036020020224102490d0220202f0000212a2001200a416e6a22223602042001202041026a36020020224102490d02201c2f0012212b2001200a416c6a22223602042001201c41146a222036020020224102490d0220202f0000212c2001200a416a6a22223602042001202041026a36020020224102490d02201c2f0016212d2001200a41686a22223602042001201c41186a222036020020224102490d0220202f0000212e2001200a41666a22223602042001202041026a36020020224102490d02201c2f001a212f2001200a41646a22223602042001201c411c6a222036020020224102490d0220202f000021302001200a41626a22223602042001202041026a36020020224102490d02201c2f001e21222001200a41606a22203602042001201c41206a221c36020020204102490d02201c2f000021202001200a415e6a3602042001201c41026a3602000240201d200228029403470d0020024190036a201d4101108d012002280290032121200228029803211d0b2021201d41246c6a220a20203b0120200a20243b0104200a2023360200200a411e6a20223b0100200a411c6a20303b0100200a411a6a202f3b0100200a41186a202e3b0100200a41166a202d3b0100200a41146a202c3b0100200a41126a202b3b0100200a41106a202a3b0100200a410e6a20293b0100200a410c6a20283b0100200a410a6a20273b0100200a41086a20263b0100200a41066a20253b01002002201d41016a221d36029803201f417f6a221f0d000b20022802940321200b2021450d11200241386a200110c4012002280238450d010c100b2002280294032201450d10200141246c450d10202110350c100b200228023c2222200128020441286e220a200a20224b1bad42287e220b422088a70d00200ba7220a417f4c0d0002400240200a0d00410421230c010b200a10332223450d020b4100211f200241003602980320022023360290032002200a41286e2224360294030240024002402022450d004100211f03402001280204220a4104490d022001280200221c28000021262001200a417c6a22253602042001201c41046a222436020020254102490d0220242f000021272001200a417a6a22253602042001202441026a36020020254102490d02201c2f000621282001200a41786a22253602042001201c41086a222436020020254102490d0220242f000021292001200a41766a22253602042001202441026a36020020254102490d02201c2f000a212a2001200a41746a22253602042001201c410c6a222436020020254102490d0220242f0000212b2001200a41726a22253602042001202441026a36020020254102490d02201c2f000e212c2001200a41706a22253602042001201c41106a222436020020254102490d0220242f0000212d2001200a416e6a22253602042001202441026a36020020254102490d02201c2f0012212e2001200a416c6a22253602042001201c41146a222436020020254102490d0220242f0000212f2001200a416a6a22253602042001202441026a36020020254102490d02201c2f001621302001200a41686a22253602042001201c41186a222436020020254102490d0220242f000021312001200a41666a22253602042001202441026a36020020254102490d02201c2f001a21322001200a41646a22253602042001201c411c6a222436020020254102490d0220242f000021332001200a41626a22253602042001202441026a36020020254102490d02201c2f001e21342001200a41606a22253602042001201c41206a222436020020254102490d0220242f000021352001200a415e6a22253602042001202441026a36020020254102490d02201c2f002221252001200a415c6a22243602042001201c41246a221c36020020244102490d02201c2f000021242001200a415a6a3602042001201c41026a3602000240201f200228029403470d0020024190036a201f4101109d012002280290032123200228029803211f0b2023201f41286c6a220a20243b0124200a20273b0104200a2026360200200a41226a20253b0100200a41206a20353b0100200a411e6a20343b0100200a411c6a20333b0100200a411a6a20323b0100200a41186a20313b0100200a41166a20303b0100200a41146a202f3b0100200a41126a202e3b0100200a41106a202d3b0100200a410e6a202c3b0100200a410c6a202b3b0100200a410a6a202a3b0100200a41086a20293b0100200a41066a20283b01002002201f41016a221f360298032022417f6a22220d000b20022802940321240b2023450d10200241306a200110c4012002280230450d010c0f0b2002280294032201450d0f200141286c450d0f202310350c0f0b200228023422252001280204412c6e220a200a20254b1bad422c7e220b422088a70d00200ba7220a417f4c0d0002400240200a0d00410421260c010b200a10332226450d020b41002122200241003602880120022026360280012002200a412c6e22273602840102402025450d004100212203402001280204220a4104490d0e2001280200221c280000212b2001200a417c6a22283602042001201c41046a2227360200200241003a00b403200241003b01d00320284102490d0e20272f000021292001200a417a6a22283602042001202741026a360200200241003b01d00320284102490d0e201c2f000621282001200a41786a222a3602042001201c41086a2227360200200220293b019003200241013a00b403200220283b019203200241003b01d003202a4102490d0d20272f000021292001200a41766a22283602042001202741026a360200200241003b01d003202841014d0d0d201c2f000a21282001200a41746a222a3602042001201c410c6a2227360200200220293b019403200220283b019603200241023a00b403200241003b01d003202a4102490d0d20272f000021292001200a41726a22283602042001202741026a360200200241003b01d00320284102490d0d201c2f000e21282001200a41706a222a3602042001201c41106a2227360200200220293b019803200241033a00b403200220283b019a03200241003b01d003202a4102490d0d20272f000021292001200a416e6a22283602042001202741026a360200200241003b01d00320284102490d0d201c2f001221282001200a416c6a222a3602042001201c41146a2227360200200220293b019c03200241043a00b403200220283b019e03200241003b01d003202a4102490d0d20272f000021292001200a416a6a22283602042001202741026a360200200241003b01d00320284102490d0d201c2f001621282001200a41686a222a3602042001201c41186a2227360200200220293b01a003200241053a00b403200220283b01a203200241003b01d003202a4102490d0d20272f000021292001200a41666a22283602042001202741026a360200200241003b01d00320284102490d0d201c2f001a21282001200a41646a222a3602042001201c411c6a2227360200200220293b01a403200241063a00b403200220283b01a603200241003b01d003202a4102490d0d20272f000021292001200a41626a22283602042001202741026a360200200241003b01d00320284102490d0d201c2f001e21282001200a41606a222a3602042001201c41206a2227360200200220293b01a803200241073a00b403200220283b01aa03200241003b01d003202a4102490d0d20272f000021292001200a415e6a22283602042001202741026a360200200241003b01d00320284102490d0d201c2f002221282001200a415c6a222a3602042001201c41246a2227360200200220293b01ac03200241083a00b403200220283b01ae03200241003b01d003202a4102490d0d20272f000021292001200a415a6a22283602042001202741026a360200200241003b01d00320284102490d0d201c2f002621272001200a41586a22283602042001201c41286a221c360200200220293b01b003200241093a00b403200220273b01b203200241d0036a41206a20022802b0032227360200200241d0036a41186a20024190036a41186a290300220b370300200241d0036a41106a20024190036a41106a2903002212370300200241d0036a41086a20024190036a41086a2903002213370300200220022903900322143703d003200241d0026a41206a22292027360200200241d0026a41186a2227200b370300200241d0026a41106a222a2012370300200241d0026a41086a222c2013370300200220143703d00220284102490d0e201c2f000021282001200a41566a3602042001201c41026a36020020024190026a41106a202a290300220b370300200241d0016a41086a202c2903002212370300200241d0016a41106a200b370300200241d0016a41186a20272903002213370300200241d0016a41206a2029280200220a360200200220022903d00222143703d00120024190016a41206a221c200a36020020024190016a41186a2227201337030020024190016a41106a2229200b37030020024190016a41086a222a2012370300200220143703900102402022200228028401470d0020024180016a20224101109801200228028001212620022802880121220b20262022412c6c6a220a202b360200200a200229039001370204201c280200211c2027290300210b20292903002112202a2903002113200a20283b0128200a410c6a2013370200200a41146a2012370200200a411c6a200b370200200a41246a201c3602002002202241016a2222360288012025417f6a22250d000b20022802840121270b2026450d0d200241286a200110c40120022802280d0a200228022c2228200128020441306e220a200a20284b1bad42307e220b422088a70d00200ba7220a417f4c0d0002400240200a0d00410421290c010b200a10332229450d020b41002125200241003602880120022029360280012002200a41306e222a3602840102402028450d004100212503402001280204220a4104490d0b2001280200221c280000212e2001200a417c6a222b3602042001201c41046a222a360200200241003a00b803200241003b01d003202b4102490d0b202a2f0000212c2001200a417a6a222b3602042001202a41026a360200200241003b01d003202b4102490d0b201c2f0006212b2001200a41786a222d3602042001201c41086a222a3602002002202c3b019003200241013a00b8032002202b3b019203200241003b01d003202d4102490d0a202a2f0000212c2001200a41766a222b3602042001202a41026a360200200241003b01d003202b41014d0d0a201c2f000a212b2001200a41746a222d3602042001201c410c6a222a3602002002202c3b0194032002202b3b019603200241023a00b803200241003b01d003202d4102490d0a202a2f0000212c2001200a41726a222b3602042001202a41026a360200200241003b01d003202b4102490d0a201c2f000e212b2001200a41706a222d3602042001201c41106a222a3602002002202c3b019803200241033a00b8032002202b3b019a03200241003b01d003202d4102490d0a202a2f0000212c2001200a416e6a222b3602042001202a41026a360200200241003b01d003202b4102490d0a201c2f0012212b2001200a416c6a222d3602042001201c41146a222a3602002002202c3b019c03200241043a00b8032002202b3b019e03200241003b01d003202d4102490d0a202a2f0000212c2001200a416a6a222b3602042001202a41026a360200200241003b01d003202b4102490d0a201c2f0016212b2001200a41686a222d3602042001201c41186a222a3602002002202c3b01a003200241053a00b8032002202b3b01a203200241003b01d003202d4102490d0a202a2f0000212c2001200a41666a222b3602042001202a41026a360200200241003b01d003202b4102490d0a201c2f001a212b2001200a41646a222d3602042001201c411c6a222a3602002002202c3b01a403200241063a00b8032002202b3b01a603200241003b01d003202d4102490d0a202a2f0000212c2001200a41626a222b3602042001202a41026a360200200241003b01d003202b4102490d0a201c2f001e212b2001200a41606a222d3602042001201c41206a222a3602002002202c3b01a803200241073a00b8032002202b3b01aa03200241003b01d003202d4102490d0a202a2f0000212c2001200a415e6a222b3602042001202a41026a360200200241003b01d003202b4102490d0a201c2f0022212b2001200a415c6a222d3602042001201c41246a222a3602002002202c3b01ac03200241083a00b8032002202b3b01ae03200241003b01d003202d4102490d0a202a2f0000212c2001200a415a6a222b3602042001202a41026a360200200241003b01d003202b4102490d0a201c2f0026212b2001200a41586a222d3602042001201c41286a222a3602002002202c3b01b003200241093a00b8032002202b3b01b203200241003b01d003202d4102490d0a202a2f0000212c2001200a41566a222b3602042001202a41026a360200200241003b01d003202b4102490d0a201c2f002a212a2001200a41546a222b3602042001201c412c6a221c3602002002202c3b01b4032002410a3a00b8032002202a3b01b603200241d0036a41206a20024190036a41206a290300220b370300200241d0036a41186a20024190036a41186a2903002212370300200241d0036a41106a20024190036a41106a2903002213370300200241d0036a41086a20024190036a41086a2903002214370300200220022903900322363703d003200241d0026a41206a222a200b370300200241d0026a41186a222c2012370300200241d0026a41106a222d2013370300200241d0026a41086a222f2014370300200220363703d002202b4102490d0b201c2f0000212b2001200a41526a3602042001201c41026a36020020024190026a41106a202d290300220b370300200241d0016a41086a202f2903002212370300200241d0016a41106a200b370300200241d0016a41186a202c2903002213370300200241d0016a41206a202a2903002214370300200220022903d00222363703d00120024190016a41206a221c201437030020024190016a41186a222a201337030020024190016a41106a222c200b37030020024190016a41086a222d2012370300200220363703900102402025200228028401470d0020024180016a20254101108901200228028001212920022802880121250b2029202541306c6a220a202e360200200a200229039001370204201c290300210b202a2903002112202c2903002113202d2903002114200a202b3b012c200a410c6a2014370200200a41146a2013370200200a411c6a2012370200200a41246a200b3702002002202541016a2225360288012028417f6a22280d000b200228028401212a0b2029450d0a200241206a200110c40120022802200d072002280224222b200128020441346e220a200a202b4b1bad42347e220b422088a70d00200ba7220a417f4c0d0002400240200a0d004104212c0c010b200a1033222c450d020b4100212820024100360288012002202c360280012002200a41346e222d360284010240202b450d004100212803402001280204220a4104490d082001280200221c28000021312001200a417c6a222e3602042001201c41046a222d360200200241003a00bc03200241003b01d003202e4102490d08202d2f0000212f2001200a417a6a222e3602042001202d41026a360200200241003b01d003202e4102490d08201c2f0006212e2001200a41786a22303602042001201c41086a222d3602002002202f3b019003200241013a00bc032002202e3b019203200241003b01d00320304102490d07202d2f0000212f2001200a41766a222e3602042001202d41026a360200200241003b01d003202e41014d0d07201c2f000a212e2001200a41746a22303602042001201c410c6a222d3602002002202f3b0194032002202e3b019603200241023a00bc03200241003b01d00320304102490d07202d2f0000212f2001200a41726a222e3602042001202d41026a360200200241003b01d003202e4102490d07201c2f000e212e2001200a41706a22303602042001201c41106a222d3602002002202f3b019803200241033a00bc032002202e3b019a03200241003b01d00320304102490d07202d2f0000212f2001200a416e6a222e3602042001202d41026a360200200241003b01d003202e4102490d07201c2f0012212e2001200a416c6a22303602042001201c41146a222d3602002002202f3b019c03200241043a00bc032002202e3b019e03200241003b01d00320304102490d07202d2f0000212f2001200a416a6a222e3602042001202d41026a360200200241003b01d003202e4102490d07201c2f0016212e2001200a41686a22303602042001201c41186a222d3602002002202f3b01a003200241053a00bc032002202e3b01a203200241003b01d00320304102490d07202d2f0000212f2001200a41666a222e3602042001202d41026a360200200241003b01d003202e4102490d07201c2f001a212e2001200a41646a22303602042001201c411c6a222d3602002002202f3b01a403200241063a00bc032002202e3b01a603200241003b01d00320304102490d07202d2f0000212f2001200a41626a222e3602042001202d41026a360200200241003b01d003202e4102490d07201c2f001e212e2001200a41606a22303602042001201c41206a222d3602002002202f3b01a803200241073a00bc032002202e3b01aa03200241003b01d00320304102490d07202d2f0000212f2001200a415e6a222e3602042001202d41026a360200200241003b01d003202e4102490d07201c2f0022212e2001200a415c6a22303602042001201c41246a222d3602002002202f3b01ac03200241083a00bc032002202e3b01ae03200241003b01d00320304102490d07202d2f0000212f2001200a415a6a222e3602042001202d41026a360200200241003b01d003202e4102490d07201c2f0026212e2001200a41586a22303602042001201c41286a222d3602002002202f3b01b003200241093a00bc032002202e3b01b203200241003b01d00320304102490d07202d2f0000212f2001200a41566a222e3602042001202d41026a360200200241003b01d003202e4102490d07201c2f002a212e2001200a41546a22303602042001201c412c6a222d3602002002202f3b01b4032002410a3a00bc032002202e3b01b603200241003b01d00320304102490d07202d2f0000212f2001200a41526a222e3602042001202d41026a360200200241003b01d003202e4102490d07201c2f002e212d2001200a41506a222e3602042001201c41306a221c3602002002202f3b01b8032002410b3a00bc032002202d3b01ba03200241d0036a41286a20022802b803222d360200200241d0036a41206a20024190036a41206a290300220b370300200241d0036a41186a20024190036a41186a2903002212370300200241d0036a41106a20024190036a41106a2903002213370300200241d0036a41086a20024190036a41086a2903002214370300200220022903900322363703d003200241d0026a41286a222f202d360200200241d0026a41206a222d200b370300200241d0026a41186a22302012370300200241d0026a41106a22322013370300200241d0026a41086a22332014370300200220363703d002202e4102490d08201c2f0000212e2001200a414e6a3602042001201c41026a36020020024190026a41106a2032290300220b37030020024190026a41186a20302903002212370300200241d0016a41086a220a2033290300370300200241d0016a41106a221c200b370300200241d0016a41186a22302012370300200241d0016a41206a2232202d290300370300200241d0016a41286a222d202f280200360200200220022903d0023703d00120024190016a41286a222f202d28020036020020024190016a41206a222d203229030037030020024190016a41186a2232203029030037030020024190016a41106a2230201c29030037030020024190016a41086a221c200a290300370300200220022903d0013703900102402028200228028401470d0020024180016a2028410110a501200228028001212c20022802880121280b202c202841346c6a220a2031360200200a200229039001370204202f280200212f202d290300210b2032290300211220302903002113201c2903002114200a202e3b0130200a410c6a2014370200200a41146a2013370200200a411c6a2012370200200a41246a200b370200200a412c6a202f3602002002202841016a222836028801202b417f6a222b0d000b200228028401212d0b202c450d07200241186a200110c40120022802180d04200228021c222e200128020441386e220a200a202e4b1bad42387e220b422088a70d00200ba7220a417f4c0d0002400240200a0d004104212f0c010b200a1033222f450d020b4100212b20024100360288012002202f360280012002200a41386e2234360284010240202e450d004100212b03402001280204220a4104490d052001280200221c28000021342001200a417c6a22313602042001201c41046a2230360200200241003a00c003200241003b01d00320314102490d0520302f000021322001200a417a6a22313602042001203041026a360200200241003b01d00320314102490d05201c2f000621312001200a41786a22333602042001201c41086a2230360200200220323b019003200241013a00c003200220313b019203200241003b01d00320334102490d0420302f000021322001200a41766a22313602042001203041026a360200200241003b01d003203141014d0d04201c2f000a21312001200a41746a22333602042001201c410c6a2230360200200220323b019403200220313b019603200241023a00c003200241003b01d00320334102490d0420302f000021322001200a41726a22313602042001203041026a360200200241003b01d00320314102490d04201c2f000e21312001200a41706a22333602042001201c41106a2230360200200220323b019803200241033a00c003200220313b019a03200241003b01d00320334102490d0420302f000021322001200a416e6a22313602042001203041026a360200200241003b01d00320314102490d04201c2f001221312001200a416c6a22333602042001201c41146a2230360200200220323b019c03200241043a00c003200220313b019e03200241003b01d00320334102490d0420302f000021322001200a416a6a22313602042001203041026a360200200241003b01d00320314102490d04201c2f001621312001200a41686a22333602042001201c41186a2230360200200220323b01a003200241053a00c003200220313b01a203200241003b01d00320334102490d0420302f000021322001200a41666a22313602042001203041026a360200200241003b01d00320314102490d04201c2f001a21312001200a41646a22333602042001201c411c6a2230360200200220323b01a403200241063a00c003200220313b01a603200241003b01d00320334102490d0420302f000021322001200a41626a22313602042001203041026a360200200241003b01d00320314102490d04201c2f001e21312001200a41606a22333602042001201c41206a2230360200200220323b01a803200241073a00c003200220313b01aa03200241003b01d00320334102490d0420302f000021322001200a415e6a22313602042001203041026a360200200241003b01d00320314102490d04201c2f002221312001200a415c6a22333602042001201c41246a2230360200200220323b01ac03200241083a00c003200220313b01ae03200241003b01d00320334102490d0420302f000021322001200a415a6a22313602042001203041026a360200200241003b01d00320314102490d04201c2f002621312001200a41586a22333602042001201c41286a2230360200200220323b01b003200241093a00c003200220313b01b203200241003b01d00320334102490d0420302f000021322001200a41566a22313602042001203041026a360200200241003b01d00320314102490d04201c2f002a21312001200a41546a22333602042001201c412c6a2230360200200220323b01b4032002410a3a00c003200220313b01b603200241003b01d00320334102490d0420302f000021322001200a41526a22313602042001203041026a360200200241003b01d00320314102490d04201c2f002e21312001200a41506a22333602042001201c41306a2230360200200220323b01b8032002410b3a00c003200220313b01ba03200241003b01d00320334102490d0420302f000021322001200a414e6a22313602042001203041026a360200200241003b01d00320314102490d04201c2f003221302001200a414c6a22313602042001201c41346a221c360200200220323b01bc032002410c3a00c003200220303b01be03200241d0036a41286a20024190036a41286a290300220b370300200241d0036a41206a20024190036a41206a2903002212370300200241d0036a41186a20024190036a41186a2903002213370300200241d0036a41106a20024190036a41106a2903002214370300200241d0036a41086a20024190036a41086a2903002236370300200220022903900322373703d003200241d0026a41286a2230200b370300200241d0026a41206a22322012370300200241d0026a41186a22332013370300200241d0026a41106a22352014370300200241d0026a41086a22382036370300200220373703d00220314102490d05201c2f000021312001200a414a6a3602042001201c41026a36020020024190026a41106a2035290300220b37030020024190026a41186a20332903002212370300200241d0016a41086a220a2038290300370300200241d0016a41106a221c200b370300200241d0016a41186a22332012370300200241d0016a41206a22352032290300370300200241d0016a41286a22322030290300370300200220022903d0023703d00120024190016a41286a2230203229030037030020024190016a41206a2232203529030037030020024190016a41186a2235203329030037030020024190016a41106a2233201c29030037030020024190016a41086a221c200a290300370300200220022903d001370390010240202b200228028401470d0020024180016a202b410110a201200228028001212f200228028801212b0b202f202b41386c6a220a2034360200200a2002290390013702042030290300210b203229030021122035290300211320332903002114201c2903002136200a20313b0134200a410c6a2036370200200a41146a2014370200200a411c6a2013370200200a41246a2012370200200a412c6a200b3702002002202b41016a222b36028801202e417f6a222e0d000b20022802840121340b202f450d04200241106a200110c401024002400240024002400240024020022802100d00200228021422392001280204413c6e220a200a20394b1bad423c7e220b422088a70d07200ba7220a417f4c0d0702400240200a0d004104213a0c010b200a1033223a450d090b4100213b20024100360288012002203a360280012002200a413c6e2235360284010240024002402039450d004100213b4100213c0340200128020422354104490d03203c41016a213c417c211c20012802002238280000213d20012035417c6a3602042001203841046a3602004100210a200241003a00c403410021310340200241003b01d0032035201c6a222e4102490d032038200a6a223041046a2f000021322001202e417e6a222e3602042001203041066a2230360200200241003b01d003202e4102490d0320024190036a200a6a223320323b0100203341026a20302f00003b01002001202e417e6a3602042001203041026a3602002002203141016a22313a00c403201c417c6a211c200a41046a220a4134470d000b200241d0036a41306a222e20024190036a41306a280200360200200241d0036a41286a223020024190036a41286a290300370300200241d0036a41206a223220024190036a41206a290300370300200241d0036a41186a223320024190036a41186a290300370300200241d0036a41106a223e20024190036a41106a290300370300200241d0036a41086a223f20024190036a41086a29030037030020022002290390033703d003203141ff0171410d490d03200241d0026a41306a2231202e280200360200200241d0026a41286a222e2030290300370300200241d0026a41206a22302032290300370300200241d0026a41186a22322033290300370300200241d0026a41106a2233203e290300370300200241d0026a41086a223e203f290300370300200220022903d0033703d0022035201c6a41014d0d032038200a6a221c41046a2f0000213820012035200a6b417a6a3602042001201c41066a36020020024190026a41086a203e290300220b37030020024190026a41106a2033290300221237030020024190026a41186a2032290300221337030020024190026a41206a2030290300221437030020024190026a41286a202e290300223637030020024190026a41306a2031280200220a360200200220022903d002223737039002200241d0016a41306a221c200a360200200241d0016a41286a220a2036370300200241d0016a41206a222e2014370300200241d0016a41186a22302013370300200241d0016a41106a22312012370300200241d0016a41086a2232200b370300200220373703d00120024190016a41306a2233201c28020036020020024190016a41286a221c200a29030037030020024190016a41206a2235202e29030037030020024190016a41186a222e203029030037030020024190016a41106a2230203129030037030020024190016a41086a22312032290300370300200220022903d001370390010240203b200228028401470d0020024180016a203b410110aa01200228028001213a200228028801213b0b203a203b413c6c6a220a203d360200200a20022903900137020420332802002132201c290300210b20352903002112202e29030021132030290300211420312903002136200a20383b0138200a410c6a2036370200200a41146a2014370200200a411c6a2013370200200a41246a2012370200200a412c6a200b370200200a41346a20323602002002203b41016a223b36028801203c2039470d000b20022802840121350b203a450d02200241086a200110c40120022802080d05200228020c223d2001280204410676220a200a203d4b1b221c410674220a417f4c0d09201c0d034104213c0c040b203141ff0171450d00200241003a00c4030b200241d0016a41306a20024190026a41306a280200360200200241d0016a41286a20024190026a41286a290300370300200241d0016a41206a20024190026a41206a290300370300200241d0016a41186a20024190026a41186a2903003703002002280284012201450d002001413c6c450d00203a10350b2000410036020002402034450d00203441386c450d00202f10350b0240202d450d00202d41346c450d00202c10350b0240202a450d00202a41306c450d00202910350b02402027450d002027412c6c450d00202610350b02402024450d00202441286c450d00202310350b02402020450d00202041246c450d00202110350b0240200941ffffff3f71450d00201e10350b0240201a450d00201a411c6c450d00201b10350b02402016450d00201641186c450d00201810350b02402011450d00201141146c450d00201510350b0240200341ffffffff0071450d00200f10350b0240200d450d00200d410c6c450d00200c10350b200541ffffffff01710d1c0c1d0b200a1033223c450d060b4100213e20024100360288012002201c360284012002203c36028001024002400240203d450d004100213e4100213f0340200128020422384104490d03203f41016a213f417c211c20012802002239280000214020012038417c6a3602042001203941046a3602004100210a200241003a00c803410021310340200241003b01d0032038201c6a222e4102490d032039200a6a223041046a2f000021322001202e417e6a222e3602042001203041066a2230360200200241003b01d003202e4102490d0320024190036a200a6a223320323b0100203341026a20302f00003b01002001202e417e6a3602042001203041026a3602002002203141016a22313a00c803201c417c6a211c200a41046a220a4138470d000b200241d0036a41306a222e20024190036a41306a290300370300200241d0036a41286a223020024190036a41286a290300370300200241d0036a41206a223220024190036a41206a290300370300200241d0036a41186a223320024190036a41186a290300370300200241d0036a41106a224120024190036a41106a290300370300200241d0036a41086a224220024190036a41086a29030037030020022002290390033703d003203141ff0171410e490d03200241d0026a41306a2231202e290300370300200241d0026a41286a222e2030290300370300200241d0026a41206a22302032290300370300200241d0026a41186a22322033290300370300200241d0026a41106a22332041290300370300200241d0026a41086a22412042290300370300200220022903d0033703d0022038201c6a41014d0d032039200a6a221c41046a2f0000213920012038200a6b417a6a3602042001201c41066a36020020024190026a41086a2041290300220b37030020024190026a41106a2033290300221237030020024190026a41186a2032290300221337030020024190026a41206a2030290300221437030020024190026a41286a202e290300223637030020024190026a41306a20312903002237370300200220022903d002224337039002200241d0016a41306a220a2037370300200241d0016a41286a221c2036370300200241d0016a41206a222e2014370300200241d0016a41186a22302013370300200241d0016a41106a22312012370300200241d0016a41086a2232200b370300200220433703d00120024190016a41306a2233200a29030037030020024190016a41286a2238201c29030037030020024190016a41206a221c202e29030037030020024190016a41186a222e203029030037030020024190016a41106a2230203129030037030020024190016a41086a22312032290300370300200220022903d001370390010240203e200228028401470d0020024180016a203e410110a601200228028001213c200228028801213e0b203c203e4106746a220a2040360200200a2002290390013702042033290300210b20382903002112201c2903002113202e29030021142030290300213620312903002137200a20393b013c200a410c6a2037370200200a41146a2036370200200a411c6a2014370200200a41246a2013370200200a412c6a2012370200200a41346a200b3702002002203e41016a223e36028801203f203d470d000b200228028401211c0b203c450d022002200110c40120022802000d0520022802042240200128020441c4006e220a200a20404b1bad42c4007e220b422088a70d06200ba7220a417f4c0d06200a0d034104213f0c040b203141ff0171450d00200241003a00c8030b200241d0016a41306a20024190026a41306a290300370300200241d0016a41286a20024190026a41286a290300370300200241d0016a41206a20024190026a41206a290300370300200241d0016a41186a20024190026a41186a29030037030020022802840141ffffff1f71450d00203c10350b2000410036020002402035450d002035413c6c450d00203a10350b02402034450d00203441386c450d00202f10350b0240202d450d00202d41346c450d00202c10350b0240202a450d00202a41306c450d00202910350b02402027450d002027412c6c450d00202610350b02402024450d00202441286c450d00202310350b02402020450d00202041246c450d00202110350b0240200941ffffff3f71450d00201e10350b0240201a450d00201a411c6c450d00201b10350b02402016450d00201641186c450d00201810350b02402011450d00201141146c450d00201510350b0240200341ffffffff0071450d00200f10350b0240200d450d00200d410c6c450d00200c10350b200541ffffffff01710d190c1a0b200a1033223f450d030b20024100360288012002203f360280012002200a41c4006e360284010240024002402040450d0041002142410021410340200128020422394104490d03204141016a2141417c212e2001280200223d280000214420012039417c6a3602042001203d41046a3602004100210a200241003a00cc03410021320340200241003b01d0032039202e6a22304102490d03203d200a6a223141046a2f0000213320012030417e6a22303602042001203141066a2231360200200241003b01d00320304102490d0320024190036a200a6a223820333b0100203841026a20312f00003b010020012030417e6a3602042001203141026a3602002002203241016a22323a00cc03202e417c6a212e200a41046a220a413c470d000b200241d0036a41386a223020024190036a41386a280200360200200241d0036a41306a223120024190036a41306a290300370300200241d0036a41286a223320024190036a41286a290300370300200241d0036a41206a223820024190036a41206a290300370300200241d0036a41186a224520024190036a41186a290300370300200241d0036a41106a224620024190036a41106a290300370300200241d0036a41086a224720024190036a41086a29030037030020022002290390033703d003203241ff0171410f490d03200241d0026a41386a22322030280200360200200241d0026a41306a22302031290300370300200241d0026a41286a22312033290300370300200241d0026a41206a22332038290300370300200241d0026a41186a22382045290300370300200241d0026a41106a22452046290300370300200241d0026a41086a22462047290300370300200220022903d0033703d0022039202e6a41014d0d03203d200a6a222e41046a2f0000213d20012039200a6b417a6a3602042001202e41066a36020020024190026a41086a220a204629030037030020024190026a41106a222e204529030037030020024190026a41186a2239203829030037030020024190026a41206a2238203329030037030020024190026a41286a2233203129030037030020024190026a41306a2231203029030037030020024190026a41386a22302032280200360200200220022903d00237039002200241d0016a41086a200a290300220b370300200241d0016a41106a202e2903002212370300200241d0016a41186a20392903002213370300200241d0016a41206a20382903002214370300200241d0016a41286a20332903002236370300200241d0016a41306a20312903002237370300200241d0016a41386a2030280200220a36020020024190016a41086a222e200b37030020024190016a41106a2230201237030020024190016a41186a2231201337030020024190016a41206a2232201437030020024190016a41286a2233203637030020024190016a41306a2238203737030020024190016a41386a2239200a3602002002200229039002220b3703d0012002200b3703900102402042200228028401470d0020024180016a20424101109f01200228028001213f20022802880121420b203f204241c4006c6a220a2044360200200a200229039001370204203928020021392038290300210b20332903002112203229030021132031290300211420302903002136202e2903002137200a203d3b0140200a410c6a2037370200200a41146a2036370200200a411c6a2014370200200a41246a2013370200200a412c6a2012370200200a41346a200b370200200a413c6a20393602002002204241016a22423602880120412040470d000b0b203f450d02200229028401210b2000200536020420002006360200200041b8016a200b370200200041b4016a203f360200200041b0016a203e360200200041ac016a201c360200200041a8016a203c360200200041a4016a203b360200200041a0016a20353602002000419c016a203a36020020004198016a202b36020020004194016a203436020020004190016a202f3602002000418c016a202836020020004188016a202d36020020004184016a202c36020020004180016a2025360200200041fc006a202a360200200041f8006a2029360200200041f4006a2022360200200041f0006a2027360200200041ec006a2026360200200041e8006a201f360200200041e4006a2024360200200041e0006a2023360200200041dc006a201d360200200041d8006a2020360200200041d4006a2021360200200041d0006a2019360200200041cc006a2009360200200041c8006a201e360200200041c4006a2017360200200041c0006a201a3602002000413c6a201b360200200041386a2010360200200041346a2016360200200041306a20183602002000412c6a200e360200200041286a2011360200200041246a2015360200200041206a20083602002000411c6a2003360200200041186a200f360200200041146a2007360200200041106a200d3602002000410c6a200c360200200041086a20043602000c1a0b203241ff0171450d00200241003a00cc030b200241d0016a41386a20024190026a41386a280200360200200241d0016a41306a20024190026a41306a290300370300200241d0016a41286a20024190026a41286a290300370300200241d0016a41206a20024190026a41206a290300370300200241d0016a41186a20024190026a41186a2903003703002002280284012201450d00200141c4006c450d00203f10350b200041003602000240201c41ffffff1f71450d00203c10350b02402035450d002035413c6c450d00203a10350b02402034450d00203441386c450d00202f10350b0240202d450d00202d41346c450d00202c10350b0240202a450d00202a41306c450d00202910350b02402027450d002027412c6c450d00202610350b02402024450d00202441286c450d00202310350b02402020450d00202041246c450d00202110350b0240200941ffffff3f71450d00201e10350b0240201a450d00201a411c6c450d00201b10350b02402016450d00201641186c450d00201810350b02402011450d00201141146c450d00201510350b0240200341ffffffff0071450d00200f10350b0240200d450d00200d410c6c450d00200c10350b200541ffffffff0171450d170c160b1044000b1045000b200241003a00c0030b200241d0016a41286a20024190026a41286a290300370300200241d0016a41206a20024190026a41206a290300370300200241d0016a41186a20024190026a41186a2903003703002002280284012201450d00200141386c450d00202f10350b200041003602000240202d450d00202d41346c450d00202c10350b0240202a450d00202a41306c450d00202910350b02402027450d002027412c6c450d00202610350b02402024450d00202441286c450d00202310350b02402020450d00202041246c450d00202110350b0240200941ffffff3f71450d00201e10350b0240201a450d00201a411c6c450d00201b10350b02402016450d00201641186c450d00201810350b02402011450d00201141146c450d00201510350b0240200341ffffffff0071450d00200f10350b0240200d450d00200d410c6c450d00200c10350b200541ffffffff01710d110c120b200241003a00bc030b200241d0016a41286a20024190026a41286a280200360200200241d0016a41206a20024190026a41206a290300370300200241d0016a41186a20024190026a41186a2903003703002002280284012201450d00200141346c450d00202c10350b200041003602000240202a450d00202a41306c450d00202910350b02402027450d002027412c6c450d00202610350b02402024450d00202441286c450d00202310350b02402020450d00202041246c450d00202110350b0240200941ffffff3f71450d00201e10350b0240201a450d00201a411c6c450d00201b10350b02402016450d00201641186c450d00201810350b02402011450d00201141146c450d00201510350b0240200341ffffffff0071450d00200f10350b0240200d450d00200d410c6c450d00200c10350b200541ffffffff01710d0e0c0f0b200241003a00b8030b200241d0016a41206a20024190026a41206a290300370300200241d0016a41186a20024190026a41186a2903003703002002280284012201450d00200141306c450d00202910350b2000410036020002402027450d002027412c6c450d00202610350b02402024450d00202441286c450d00202310350b02402020450d00202041246c450d00202110350b0240200941ffffff3f71450d00201e10350b0240201a450d00201a411c6c450d00201b10350b02402016450d00201641186c450d00201810350b02402011450d00201141146c450d00201510350b0240200341ffffffff0071450d00200f10350b0240200d450d00200d410c6c450d00200c10350b200541ffffffff01710d0b0c0c0b200241003a00b4030b200241d0016a41206a20024190026a41206a280200360200200241d0016a41186a20024190026a41186a2903003703002002280284012201450d002001412c6c450d00202610350b2000410036020002402024450d00202441286c450d00202310350b02402020450d00202041246c450d00202110350b0240200941ffffff3f71450d00201e10350b0240201a450d00201a411c6c450d00201b10350b02402016450d00201641186c450d00201810350b02402011450d00201141146c450d00201510350b0240200341ffffffff0071450d00200f10350b0240200d450d00200d410c6c450d00200c10350b200541ffffffff01710d080c090b2000410036020002402020450d00202041246c450d00202110350b0240200941ffffff3f71450d00201e10350b0240201a450d00201a411c6c450d00201b10350b02402016450d00201641186c450d00201810350b02402011450d00201141146c450d00201510350b0240200341ffffffff0071450d00200f10350b0240200d450d00200d410c6c450d00200c10350b200541ffffffff01710d070c080b200041003602000240200941ffffff3f71450d00201e10350b0240201a450d00201a411c6c450d00201b10350b02402016450d00201641186c450d00201810350b02402011450d00201141146c450d00201510350b0240200341ffffffff0071450d00200f10350b0240200d450d00200d410c6c450d00200c10350b200541ffffffff01710d060c070b200041003602000240201a450d00201a411c6c450d00201b10350b02402016450d00201641186c450d00201810350b02402011450d00201141146c450d00201510350b0240200341ffffffff0071450d00200f10350b0240200d450d00200d410c6c450d00200c10350b200541ffffffff01710d050c060b2000410036020002402016450d00201641186c450d00201810350b02402011450d00201141146c450d00201510350b0240200341ffffffff0071450d00200f10350b0240200d450d00200d410c6c450d00200c10350b200541ffffffff01710d040c050b2000410036020002402011450d00201141146c450d00201510350b0240200341ffffffff0071450d00200f10350b0240200d450d00200d410c6c450d00200c10350b200541ffffffff01710d030c040b200041003602000240200341ffffffff0071450d00200f10350b0240200d450d00200d410c6c450d00200c10350b200541ffffffff01710d020c030b200041003602000240200d450d00200d410c6c450d00200c10350b200541ffffffff01710d010c020b20004100360200200541ffffffff0171450d010b200610350b20024190046a24000bbe0102017f017e0240200041046a280200220320016b20024f0d000240024002400240200120026a22022001490d00200341017422012002200120024b1bad421c7e2204422088a70d002004a722014100480d00024020030d0020010d02410421020c040b200028020021022003411c6c22032001460d03024020030d0020010d02410421020c040b20022003200110372202450d020c030b103e000b2001103322020d010b103c000b20002002360200200041046a2001411c6e3602000b0bf70301017f0240200041046a28020041ffffffff0171450d00200028020010350b0240200041106a2802002201450d002001410c6c450d00200028020c10350b02402000411c6a28020041ffffffff0071450d00200028021810350b0240200041286a2802002201450d00200141146c450d00200028022410350b0240200041346a2802002201450d00200141186c450d00200028023010350b0240200041c0006a2802002201450d002001411c6c450d00200028023c10350b0240200041cc006a28020041ffffff3f71450d00200028024810350b0240200041d8006a2802002201450d00200141246c450d00200028025410350b0240200041e4006a2802002201450d00200141286c450d00200028026010350b0240200041f0006a2802002201450d002001412c6c450d00200028026c10350b0240200041fc006a2802002201450d00200141306c450d00200028027810350b024020004188016a2802002201450d00200141346c450d0020002802840110350b024020004194016a2802002201450d00200141386c450d0020002802900110350b0240200041a0016a2802002201450d002001413c6c450d00200028029c0110350b0240200041ac016a28020041ffffff1f71450d0020002802a80110350b0240200041b8016a2802002201450d00200141c4006c450d0020002802b40110350b0be49301032a7f047e247f23004180026b22042400200441b8016a4200370300200441b0016a22054280808080c000370300200441a0016a420037030020044198016a22064280808080c00037030020044188016a420037030020044180016a22074280808080c000370300200441f0006a4200370300200441e8006a22084280808080c000370300200441d8006a4200370300200441d0006a22094280808080c000370300200441c0006a4200370300200441386a220a4280808080c000370300200441286a4200370300200441206a220b4280808080c000370300200441106a4200370300200442043703a8012004420437039001200442043703782004420437036020044204370348200442043703302004420437031820044280808080c000370308200442043703002001280200220c2001280208220d412c6c220e6a210f20012802042110200c2101024002400240200d450d00200441bc016a2111200441b4016a2112200441a8016a2113200441a4016a21142004419c016a211520044190016a21162004418c016a211720044184016a2118200441f8006a2119200441f4006a211a200441ec006a211b200441e0006a211c200441dc006a211d200441d4006a211e200441c8006a211f200441c4006a21202004413c6a2121200441306a21222004412c6a2123200441246a2124200441186a2125200441146a21262004410c6a2127200441086a2128200e41546a210d200441e0016a41086a2129200441e0016a41106a212a200441e0016a41186a212b200c210e0340200e280208212c200e280204212d2029200e41146a290200370300202a200e411c6a290200370300202b200e41246a2902003703002004200e29020c3703e001200e412c6a2101200e280200220e450d01200441c0016a41186a202b290300222e370300200441c0016a41106a202a290300222f370300200441c0016a41086a20292903002230370300200420042903e00122313703c001202b202e370300202a202f37030020292030370300200420313703e001024002400240202c41104d0d00410121320c010b024002400240024002400240024002400240024002400240024002400240024002400240202c0e11000102030405060708090a0b0c0d0e0f10000b0240202d450d00202d41226c450d00200e10350b2001200f460d150c120b4102213220022802082233450d102002280200212c203341057421344100213302400340200441e0016a202c460d012033202c200441e0016a412010a00822354100476a21332035450d01202c41206a212c203441606a22340d000c120b0b20032802082234450d102003280200212c203441057421354100213402400340200e202c460d012034202c200e412010a00822364100476a21342036450d01202c41206a212c203541606a22350d000c120b0b2034418080044f0d1002402004280208222c2004280204470d002004202c41011090012004280208212c0b2004280200202c4103746a222c20343b0104202c20333602002028212c0c0f0b4102213220022802082233450d0f2002280200212c203341057421344100213302400340200441e0016a202c460d012033202c200441e0016a412010a00822354100476a21332035450d01202c41206a212c203441606a22340d000c110b0b2003280208222c450d0f41002135202c4105742237213620032802002234212c02400340200e202c460d012035202c200e412010a00822384100476a21352038450d01202c41206a212c203641606a22360d000c110b0b203541ffff034b0d0f200e41226a2136200e2f012021394100212c0240034020362034460d01202c20342036412010a00822384100476a212c2038450d01203441206a2134203741606a22370d000c110b0b202c41ffff034b0d0f0240200428021422322004280210470d00202720324101108701200428021421320b200428020c2032410c6c6a2232202c3b0108203220353b010420322033360200203241066a20393b01002026212c0c0e0b4102213220022802082233450d0e2002280200212c203341057421344100213302400340200441e0016a202c460d012033202c200441e0016a412010a00822354100476a21332035450d01202c41206a212c203441606a22340d000c100b0b2003280208222c450d0e41002134202c410574223a213520032802002238212c02400340200e202c460d012034202c200e412010a00822364100476a21342036450d01202c41206a212c203541606a22350d000c100b0b203441ffff034b0d0e200e41226a2136200e2f0120213b41002135203a21372038212c024003402036202c460d012035202c2036412010a00822394100476a21352039450d01202c41206a212c203741606a22370d000c100b0b203541ffff034b0d0e200e41c4006a2136200e41c2006a2f010021394100212c0240034020362038460d01202c20382036412010a00822374100476a212c2037450d01203841206a2138203a41606a223a0d000c100b0b202c41ffff034b0d0e024020042802202232200428021c470d00202520324101108c01200428022021320b200428021820324104746a2232202c3b010c203220343b0104203220333602002032410a6a20393b0100203241086a20353b0100203241066a203b3b0100200b212c0c0d0b4102213220022802082233450d0d2002280200212c203341057421344100213302400340200441e0016a202c460d012033202c200441e0016a412010a00822354100476a21332035450d01202c41206a212c203441606a22340d000c0f0b0b2003280208222c450d0d41002134202c410574223b213520032802002237212c02400340200e202c460d012034202c200e412010a00822364100476a21342036450d01202c41206a212c203541606a22350d000c0f0b0b203441ffff034b0d0d200e41226a2136200e2f0120213c41002135203b21382037212c024003402036202c460d012035202c2036412010a00822394100476a21352039450d01202c41206a212c203841606a22380d000c0f0b0b203541ffff034b0d0d200e41c4006a2138200e41c2006a2f0100213d41002136203b21392037212c024003402038202c460d012036202c2038412010a008223a4100476a2136203a450d01202c41206a212c203941606a22390d000c0f0b0b203641ffff034b0d0d200e41e6006a2138200e41e4006a2f0100213a4100212c0240034020382037460d01202c20372038412010a00822394100476a212c2039450d01203741206a2137203b41606a223b0d000c0f0b0b202c41ffff034b0d0d0240200428022c22322004280228470d00202420324101109901200428022c21320b2004280224203241146c6a2232202c3b0110203220343b0104203220333602002032410e6a203a3b01002032410c6a20363b01002032410a6a203d3b0100203241086a20353b0100203241066a203c3b01002023212c0c0c0b4102213220022802082233450d0c2002280200212c203341057421344100213302400340200441e0016a202c460d012033202c200441e0016a412010a00822354100476a21332035450d01202c41206a212c203441606a22340d000c0e0b0b2003280208222c450d0c41002134202c410574223b213520032802002239212c02400340200e202c460d012034202c200e412010a00822364100476a21342036450d01202c41206a212c203541606a22350d000c0e0b0b203441ffff034b0d0c200e41226a2136200e2f0120213d41002135203b21382039212c024003402036202c460d012035202c2036412010a00822374100476a21352037450d01202c41206a212c203841606a22380d000c0e0b0b203541ffff034b0d0c200e41c4006a2138200e41c2006a2f0100213e41002136203b21372039212c024003402038202c460d012036202c2038412010a008223a4100476a2136203a450d01202c41206a212c203741606a22370d000c0e0b0b203641ffff034b0d0c200e41e6006a2137200e41e4006a2f0100213f41002138203b213a2039212c024003402037202c460d012038202c2037412010a008223c4100476a2138203c450d01202c41206a212c203a41606a223a0d000c0e0b0b203841ffff034b0d0c200e4188016a2137200e4186016a2f0100213c4100212c0240034020372039460d01202c20392037412010a008223a4100476a212c203a450d01203941206a2139203b41606a223b0d000c0e0b0b202c41ffff034b0d0c0240200428023822322004280234470d00202220324101109701200428023821320b2004280230203241186c6a2232202c3b0114203220343b010420322033360200203241126a203c3b0100203241106a20383b01002032410e6a203f3b01002032410c6a20363b01002032410a6a203e3b0100203241086a20353b0100203241066a203d3b0100200a212c0c0b0b4102213220022802082233450d0b2002280200212c203341057421344100213302400340200441e0016a202c460d012033202c200441e0016a412010a00822354100476a21332035450d01202c41206a212c203441606a22340d000c0d0b0b2003280208222c450d0b41002134202c410574223c21352003280200223a212c02400340200e202c460d012034202c200e412010a00822364100476a21342036450d01202c41206a212c203541606a22350d000c0d0b0b203441ffff034b0d0b200e41226a2136200e2f0120213e41002135203c2138203a212c024003402036202c460d012035202c2036412010a00822374100476a21352037450d01202c41206a212c203841606a22380d000c0d0b0b203541ffff034b0d0b200e41c4006a2138200e41c2006a2f0100213f41002136203c2137203a212c024003402038202c460d012036202c2038412010a00822394100476a21362039450d01202c41206a212c203741606a22370d000c0d0b0b203641ffff034b0d0b200e41e6006a2137200e41e4006a2f0100214041002138203c2139203a212c024003402037202c460d012038202c2037412010a008223b4100476a2138203b450d01202c41206a212c203941606a22390d000c0d0b0b203841ffff034b0d0b200e4188016a2139200e4186016a2f0100214141002137203c213b203a212c024003402039202c460d012037202c2039412010a008223d4100476a2137203d450d01202c41206a212c203b41606a223b0d000c0d0b0b203741ffff034b0d0b200e41aa016a2139200e41a8016a2f0100213d4100212c024003402039203a460d01202c203a2039412010a008223b4100476a212c203b450d01203a41206a213a203c41606a223c0d000c0d0b0b202c41ffff034b0d0b0240200428024422322004280240470d0020212032410110f901200428024421320b200428023c2032411c6c6a2232202c3b0118203220343b010420322033360200203241166a203d3b0100203241146a20373b0100203241126a20413b0100203241106a20383b01002032410e6a20403b01002032410c6a20363b01002032410a6a203f3b0100203241086a20353b0100203241066a203e3b01002020212c0c0a0b4102213220022802082233450d0a2002280200212c203341057421344100213302400340200441e0016a202c460d012033202c200441e0016a412010a00822354100476a21332035450d01202c41206a212c203441606a22340d000c0c0b0b2003280208222c450d0a41002134202c410574223c21352003280200223a212c02400340200e202c460d012034202c200e412010a00822364100476a21342036450d01202c41206a212c203541606a22350d000c0c0b0b203441ffff034b0d0a200e41226a2136200e2f0120213f41002135203c2138203a212c024003402036202c460d012035202c2036412010a00822374100476a21352037450d01202c41206a212c203841606a22380d000c0c0b0b203541ffff034b0d0a200e41c4006a2138200e41c2006a2f0100214041002136203c2137203a212c024003402038202c460d012036202c2038412010a00822394100476a21362039450d01202c41206a212c203741606a22370d000c0c0b0b203641ffff034b0d0a200e41e6006a2137200e41e4006a2f0100214141002138203c2139203a212c024003402037202c460d012038202c2037412010a008223b4100476a2138203b450d01202c41206a212c203941606a22390d000c0c0b0b203841ffff034b0d0a200e4188016a2139200e4186016a2f0100214241002137203c213b203a212c024003402039202c460d012037202c2039412010a008223d4100476a2137203d450d01202c41206a212c203b41606a223b0d000c0c0b0b203741ffff034b0d0a200e41aa016a213b200e41a8016a2f0100214341002139203c213d203a212c02400340203b202c460d012039202c203b412010a008223e4100476a2139203e450d01202c41206a212c203d41606a223d0d000c0c0b0b203941ffff034b0d0a200e41cc016a213b200e41ca016a2f0100213e4100212c02400340203b203a460d01202c203a203b412010a008223d4100476a212c203d450d01203a41206a213a203c41606a223c0d000c0c0b0b202c41ffff034b0d0a024020042802502232200428024c470d00201f20324101109101200428025021320b200428024820324105746a2232202c3b011c203220343b0104203220333602002032411a6a203e3b0100203241186a20393b0100203241166a20433b0100203241146a20373b0100203241126a20423b0100203241106a20383b01002032410e6a20413b01002032410c6a20363b01002032410a6a20403b0100203241086a20353b0100203241066a203f3b01002009212c0c090b4102213220022802082233450d092002280200212c203341057421344100213302400340200441e0016a202c460d012033202c200441e0016a412010a00822354100476a21332035450d01202c41206a212c203441606a22340d000c0b0b0b2003280208222c450d0941002134202c410574223d21352003280200223b212c02400340200e202c460d012034202c200e412010a00822364100476a21342036450d01202c41206a212c203541606a22350d000c0b0b0b203441ffff034b0d09200e41226a2136200e2f0120214041002135203d2138203b212c024003402036202c460d012035202c2036412010a00822374100476a21352037450d01202c41206a212c203841606a22380d000c0b0b0b203541ffff034b0d09200e41c4006a2138200e41c2006a2f0100214141002136203d2137203b212c024003402038202c460d012036202c2038412010a00822394100476a21362039450d01202c41206a212c203741606a22370d000c0b0b0b203641ffff034b0d09200e41e6006a2137200e41e4006a2f0100214241002138203d2139203b212c024003402037202c460d012038202c2037412010a008223a4100476a2138203a450d01202c41206a212c203941606a22390d000c0b0b0b203841ffff034b0d09200e4188016a2139200e4186016a2f0100214341002137203d213a203b212c024003402039202c460d012037202c2039412010a008223c4100476a2137203c450d01202c41206a212c203a41606a223a0d000c0b0b0b203741ffff034b0d09200e41aa016a213a200e41a8016a2f0100214441002139203d213c203b212c02400340203a202c460d012039202c203a412010a008223e4100476a2139203e450d01202c41206a212c203c41606a223c0d000c0b0b0b203941ffff034b0d09200e41cc016a213c200e41ca016a2f010021454100213a203d213e203b212c02400340203c202c460d01203a202c203c412010a008223f4100476a213a203f450d01202c41206a212c203e41606a223e0d000c0b0b0b203a41ffff034b0d09200e41ee016a213c200e41ec016a2f0100213f4100212c02400340203c203b460d01202c203b203c412010a008223e4100476a212c203e450d01203b41206a213b203d41606a223d0d000c0b0b0b202c41ffff034b0d090240200428025c22322004280258470d00201e20324101108d01200428025c21320b2004280254203241246c6a2232202c3b0120203220343b0104203220333602002032411e6a203f3b01002032411c6a203a3b01002032411a6a20453b0100203241186a20393b0100203241166a20443b0100203241146a20373b0100203241126a20433b0100203241106a20383b01002032410e6a20423b01002032410c6a20363b01002032410a6a20413b0100203241086a20353b0100203241066a20403b0100201d212c0c080b4102213220022802082233450d082002280200212c203341057421344100213302400340200441e0016a202c460d012033202c200441e0016a412010a00822354100476a21332035450d01202c41206a212c203441606a22340d000c0a0b0b2003280208222c450d0841002134202c410574223d21352003280200223b212c02400340200e202c460d012034202c200e412010a00822364100476a21342036450d01202c41206a212c203541606a22350d000c0a0b0b203441ffff034b0d08200e41226a2136200e2f0120214141002135203d2138203b212c024003402036202c460d012035202c2036412010a00822374100476a21352037450d01202c41206a212c203841606a22380d000c0a0b0b203541ffff034b0d08200e41c4006a2138200e41c2006a2f0100214241002136203d2137203b212c024003402038202c460d012036202c2038412010a00822394100476a21362039450d01202c41206a212c203741606a22370d000c0a0b0b203641ffff034b0d08200e41e6006a2137200e41e4006a2f0100214341002138203d2139203b212c024003402037202c460d012038202c2037412010a008223a4100476a2138203a450d01202c41206a212c203941606a22390d000c0a0b0b203841ffff034b0d08200e4188016a2139200e4186016a2f0100214441002137203d213a203b212c024003402039202c460d012037202c2039412010a008223c4100476a2137203c450d01202c41206a212c203a41606a223a0d000c0a0b0b203741ffff034b0d08200e41aa016a213a200e41a8016a2f0100214541002139203d213c203b212c02400340203a202c460d012039202c203a412010a008223e4100476a2139203e450d01202c41206a212c203c41606a223c0d000c0a0b0b203941ffff034b0d08200e41cc016a213c200e41ca016a2f010021464100213a203d213e203b212c02400340203c202c460d01203a202c203c412010a008223f4100476a213a203f450d01202c41206a212c203e41606a223e0d000c0a0b0b203a41ffff034b0d08200e41ee016a213e200e41ec016a2f010021474100213c203d213f203b212c02400340203e202c460d01203c202c203e412010a00822404100476a213c2040450d01202c41206a212c203f41606a223f0d000c0a0b0b203c41ffff034b0d08200e4190026a213e200e418e026a2f010021404100212c02400340203e203b460d01202c203b203e412010a008223f4100476a212c203f450d01203b41206a213b203d41606a223d0d000c0a0b0b202c41ffff034b0d080240200428026822322004280264470d00201c20324101109d01200428026821320b2004280260203241286c6a2232202c3b0124203220343b010420322033360200203241226a20403b0100203241206a203c3b01002032411e6a20473b01002032411c6a203a3b01002032411a6a20463b0100203241186a20393b0100203241166a20453b0100203241146a20373b0100203241126a20443b0100203241106a20383b01002032410e6a20433b01002032410c6a20363b01002032410a6a20423b0100203241086a20353b0100203241066a20413b01002008212c0c070b4102213220022802082233450d072002280200212c203341057421344100213302400340200441e0016a202c460d012033202c200441e0016a412010a00822354100476a21332035450d01202c41206a212c203441606a22340d000c090b0b2003280208222c450d0741002134202c410574223d21352003280200223c212c02400340200e202c460d012034202c200e412010a00822364100476a21342036450d01202c41206a212c203541606a22350d000c090b0b203441ffff034b0d07200e41226a2136200e2f0120214241002135203d2138203c212c024003402036202c460d012035202c2036412010a00822374100476a21352037450d01202c41206a212c203841606a22380d000c090b0b203541ffff034b0d07200e41c4006a2138200e41c2006a2f0100214341002136203d2137203c212c024003402038202c460d012036202c2038412010a00822394100476a21362039450d01202c41206a212c203741606a22370d000c090b0b203641ffff034b0d07200e41e6006a2137200e41e4006a2f0100214441002138203d2139203c212c024003402037202c460d012038202c2037412010a008223a4100476a2138203a450d01202c41206a212c203941606a22390d000c090b0b203841ffff034b0d07200e4188016a2139200e4186016a2f0100214541002137203d213a203c212c024003402039202c460d012037202c2039412010a008223b4100476a2137203b450d01202c41206a212c203a41606a223a0d000c090b0b203741ffff034b0d07200e41aa016a213a200e41a8016a2f0100214641002139203d213b203c212c02400340203a202c460d012039202c203a412010a008223e4100476a2139203e450d01202c41206a212c203b41606a223b0d000c090b0b203941ffff034b0d07200e41cc016a213b200e41ca016a2f010021474100213a203d213e203c212c02400340203b202c460d01203a202c203b412010a008223f4100476a213a203f450d01202c41206a212c203e41606a223e0d000c090b0b203a41ffff034b0d07200e41ee016a213e200e41ec016a2f010021484100213b203d213f203c212c02400340203e202c460d01203b202c203e412010a00822404100476a213b2040450d01202c41206a212c203f41606a223f0d000c090b0b203b41ffff034b0d07200e4190026a213f200e418e026a2f010021494100213e203d2140203c212c02400340203f202c460d01203e202c203f412010a00822414100476a213e2041450d01202c41206a212c204041606a22400d000c090b0b203e41ffff034b0d07200e41b2026a213f200e41b0026a2f010021414100212c02400340203f203c460d01202c203c203f412010a00822404100476a212c2040450d01203c41206a213c203d41606a223d0d000c090b0b202c41ffff034b0d070240200428027422322004280270470d00201b20324101109801200428027421320b200428026c2032412c6c6a2232202c3b0128203220343b010420322033360200203241266a20413b0100203241246a203e3b0100203241226a20493b0100203241206a203b3b01002032411e6a20483b01002032411c6a203a3b01002032411a6a20473b0100203241186a20393b0100203241166a20463b0100203241146a20373b0100203241126a20453b0100203241106a20383b01002032410e6a20443b01002032410c6a20363b01002032410a6a20433b0100203241086a20353b0100203241066a20423b0100201a212c0c060b4102213220022802082233450d062002280200212c203341057421344100213302400340200441e0016a202c460d012033202c200441e0016a412010a00822354100476a21332035450d01202c41206a212c203441606a22340d000c080b0b2003280208222c450d0641002134202c410574223d21352003280200223c212c02400340200e202c460d012034202c200e412010a00822364100476a21342036450d01202c41206a212c203541606a22350d000c080b0b203441ffff034b0d06200e41226a2136200e2f0120214241002135203d2138203c212c024003402036202c460d012035202c2036412010a00822374100476a21352037450d01202c41206a212c203841606a22380d000c080b0b203541ffff034b0d06200e41c4006a2138200e41c2006a2f0100214441002136203d2137203c212c024003402038202c460d012036202c2038412010a00822394100476a21362039450d01202c41206a212c203741606a22370d000c080b0b203641ffff034b0d06200e41e6006a2137200e41e4006a2f0100214541002138203d2139203c212c024003402037202c460d012038202c2037412010a008223a4100476a2138203a450d01202c41206a212c203941606a22390d000c080b0b203841ffff034b0d06200e4188016a2139200e4186016a2f0100214641002137203d213a203c212c024003402039202c460d012037202c2039412010a008223b4100476a2137203b450d01202c41206a212c203a41606a223a0d000c080b0b203741ffff034b0d06200e41aa016a213a200e41a8016a2f0100214741002139203d213b203c212c02400340203a202c460d012039202c203a412010a008223e4100476a2139203e450d01202c41206a212c203b41606a223b0d000c080b0b203941ffff034b0d06200e41cc016a213b200e41ca016a2f010021484100213a203d213e203c212c02400340203b202c460d01203a202c203b412010a008223f4100476a213a203f450d01202c41206a212c203e41606a223e0d000c080b0b203a41ffff034b0d06200e41ee016a213e200e41ec016a2f010021494100213b203d213f203c212c02400340203e202c460d01203b202c203e412010a00822404100476a213b2040450d01202c41206a212c203f41606a223f0d000c080b0b203b41ffff034b0d06200e4190026a213f200e418e026a2f0100214a4100213e203d2140203c212c02400340203f202c460d01203e202c203f412010a00822414100476a213e2041450d01202c41206a212c204041606a22400d000c080b0b203e41ffff034b0d06200e41b2026a2140200e41b0026a2f0100214b4100213f203d2141203c212c024003402040202c460d01203f202c2040412010a00822434100476a213f2043450d01202c41206a212c204141606a2241450d080c000b0b203f41ffff034b0d06200e41d4026a2140200e41d2026a2f010021434100212c024003402040203c460d01202c203c2040412010a00822414100476a212c2041450d01203c41206a213c203d41606a223d450d080c000b0b202c41ffff034b0d0602402004280280012232200428027c470d0020192032410110890120042802800121320b2004280278203241306c6a2232202c3b012c203220343b0104203220333602002032412a6a20433b0100203241286a203f3b0100203241266a204b3b0100203241246a203e3b0100203241226a204a3b0100203241206a203b3b01002032411e6a20493b01002032411c6a203a3b01002032411a6a20483b0100203241186a20393b0100203241166a20473b0100203241146a20373b0100203241126a20463b0100203241106a20383b01002032410e6a20453b01002032410c6a20363b01002032410a6a20443b0100203241086a20353b0100203241066a20423b01002007212c0c050b4102213220022802082233450d052002280200212c203341057421344100213302400340200441e0016a202c460d012033202c200441e0016a412010a00822354100476a21332035450d01202c41206a212c203441606a2234450d070c000b0b2003280208222c450d0541002134202c410574223d21352003280200223c212c02400340200e202c460d012034202c200e412010a00822364100476a21342036450d01202c41206a212c203541606a2235450d070c000b0b203441ffff034b0d05200e41226a2136200e2f0120214241002135203d2138203c212c024003402036202c460d012035202c2036412010a00822374100476a21352037450d01202c41206a212c203841606a2238450d070c000b0b203541ffff034b0d05200e41c4006a2138200e41c2006a2f0100214441002136203d2137203c212c024003402038202c460d012036202c2038412010a00822394100476a21362039450d01202c41206a212c203741606a2237450d070c000b0b203641ffff034b0d05200e41e6006a2137200e41e4006a2f0100214641002138203d2139203c212c024003402037202c460d012038202c2037412010a008223a4100476a2138203a450d01202c41206a212c203941606a2239450d070c000b0b203841ffff034b0d05200e4188016a2139200e4186016a2f0100214741002137203d213a203c212c024003402039202c460d012037202c2039412010a008223b4100476a2137203b450d01202c41206a212c203a41606a223a450d070c000b0b203741ffff034b0d05200e41aa016a213a200e41a8016a2f0100214841002139203d213b203c212c02400340203a202c460d012039202c203a412010a008223e4100476a2139203e450d01202c41206a212c203b41606a223b450d070c000b0b203941ffff034b0d05200e41cc016a213b200e41ca016a2f010021494100213a203d213e203c212c02400340203b202c460d01203a202c203b412010a008223f4100476a213a203f450d01202c41206a212c203e41606a223e450d070c000b0b203a41ffff034b0d05200e41ee016a213e200e41ec016a2f0100214a4100213b203d213f203c212c02400340203e202c460d01203b202c203e412010a00822404100476a213b2040450d01202c41206a212c203f41606a223f450d070c000b0b203b41ffff034b0d05200e4190026a213f200e418e026a2f0100214b4100213e203d2140203c212c02400340203f202c460d01203e202c203f412010a00822414100476a213e2041450d01202c41206a212c204041606a2240450d070c000b0b203e41ffff034b0d05200e41b2026a2140200e41b0026a2f0100214c4100213f203d2141203c212c024003402040202c460d01203f202c2040412010a00822434100476a213f2043450d01202c41206a212c204141606a2241450d070c000b0b203f41ffff034b0d05200e41d4026a2141200e41d2026a2f0100214d41002140203d2143203c212c024003402041202c460d012040202c2041412010a00822454100476a21402045450d01202c41206a212c204341606a2243450d070c000b0b204041ffff034b0d05200e41f6026a2141200e41f4026a2f010021454100212c024003402041203c460d01202c203c2041412010a00822434100476a212c2043450d01203c41206a213c203d41606a223d450d070c000b0b202c41ffff034b0d050240200428028c012232200428028801470d0020182032410110a501200428028c0121320b200428028401203241346c6a2232202c3b0130203220343b0104203220333602002032412e6a20453b01002032412c6a20403b01002032412a6a204d3b0100203241286a203f3b0100203241266a204c3b0100203241246a203e3b0100203241226a204b3b0100203241206a203b3b01002032411e6a204a3b01002032411c6a203a3b01002032411a6a20493b0100203241186a20393b0100203241166a20483b0100203241146a20373b0100203241126a20473b0100203241106a20383b01002032410e6a20463b01002032410c6a20363b01002032410a6a20443b0100203241086a20353b0100203241066a20423b01002017212c0c040b4102213220022802082233450d042002280200212c203341057421344100213302400340200441e0016a202c460d012033202c200441e0016a412010a00822354100476a21332035450d01202c41206a212c203441606a2234450d060c000b0b2003280208222c450d0441002134202c410574223d21352003280200223c212c02400340200e202c460d012034202c200e412010a00822364100476a21342036450d01202c41206a212c203541606a2235450d060c000b0b203441ffff034b0d04200e41226a2136200e2f0120214241002135203d2138203c212c024003402036202c460d012035202c2036412010a00822374100476a21352037450d01202c41206a212c203841606a2238450d060c000b0b203541ffff034b0d04200e41c4006a2138200e41c2006a2f0100214441002136203d2137203c212c024003402038202c460d012036202c2038412010a00822394100476a21362039450d01202c41206a212c203741606a2237450d060c000b0b203641ffff034b0d04200e41e6006a2137200e41e4006a2f0100214641002138203d2139203c212c024003402037202c460d012038202c2037412010a008223a4100476a2138203a450d01202c41206a212c203941606a2239450d060c000b0b203841ffff034b0d04200e4188016a2139200e4186016a2f0100214841002137203d213a203c212c024003402039202c460d012037202c2039412010a008223b4100476a2137203b450d01202c41206a212c203a41606a223a450d060c000b0b203741ffff034b0d04200e41aa016a213a200e41a8016a2f0100214941002139203d213b203c212c02400340203a202c460d012039202c203a412010a008223e4100476a2139203e450d01202c41206a212c203b41606a223b450d060c000b0b203941ffff034b0d04200e41cc016a213b200e41ca016a2f0100214a4100213a203d213e203c212c02400340203b202c460d01203a202c203b412010a008223f4100476a213a203f450d01202c41206a212c203e41606a223e450d060c000b0b203a41ffff034b0d04200e41ee016a213e200e41ec016a2f0100214b4100213b203d213f203c212c02400340203e202c460d01203b202c203e412010a00822404100476a213b2040450d01202c41206a212c203f41606a223f450d060c000b0b203b41ffff034b0d04200e4190026a213f200e418e026a2f0100214c4100213e203d2140203c212c02400340203f202c460d01203e202c203f412010a00822414100476a213e2041450d01202c41206a212c204041606a2240450d060c000b0b203e41ffff034b0d04200e41b2026a2140200e41b0026a2f0100214d4100213f203d2141203c212c024003402040202c460d01203f202c2040412010a00822434100476a213f2043450d01202c41206a212c204141606a2241450d060c000b0b203f41ffff034b0d04200e41d4026a2141200e41d2026a2f0100214e41002140203d2143203c212c024003402041202c460d012040202c2041412010a00822454100476a21402045450d01202c41206a212c204341606a2243450d060c000b0b204041ffff034b0d04200e41f6026a2143200e41f4026a2f0100214f41002141203d2145203c212c024003402043202c460d012041202c2043412010a00822474100476a21412047450d01202c41206a212c204541606a2245450d060c000b0b204141ffff034b0d04200e4198036a2143200e4196036a2f010021474100212c024003402043203c460d01202c203c2043412010a00822454100476a212c2045450d01203c41206a213c203d41606a223d450d060c000b0b202c41ffff034b0d0402402004280298012232200428029401470d0020162032410110a20120042802980121320b200428029001203241386c6a2232202c3b0134203220343b010420322033360200203241326a20473b0100203241306a20413b01002032412e6a204f3b01002032412c6a20403b01002032412a6a204e3b0100203241286a203f3b0100203241266a204d3b0100203241246a203e3b0100203241226a204c3b0100203241206a203b3b01002032411e6a204b3b01002032411c6a203a3b01002032411a6a204a3b0100203241186a20393b0100203241166a20493b0100203241146a20373b0100203241126a20483b0100203241106a20383b01002032410e6a20463b01002032410c6a20363b01002032410a6a20443b0100203241086a20353b0100203241066a20423b01002006212c0c030b4102213220022802082233450d032002280200212c203341057421344100213302400340200441e0016a202c460d012033202c200441e0016a412010a00822354100476a21332035450d01202c41206a212c203441606a2234450d050c000b0b2003280208222c450d0341002134202c410574223d21352003280200223c212c02400340200e202c460d012034202c200e412010a00822364100476a21342036450d01202c41206a212c203541606a2235450d050c000b0b203441ffff034b0d03200e41226a2136200e2f0120214241002135203d2138203c212c024003402036202c460d012035202c2036412010a00822374100476a21352037450d01202c41206a212c203841606a2238450d050c000b0b203541ffff034b0d03200e41c4006a2138200e41c2006a2f0100214441002136203d2137203c212c024003402038202c460d012036202c2038412010a00822394100476a21362039450d01202c41206a212c203741606a2237450d050c000b0b203641ffff034b0d03200e41e6006a2137200e41e4006a2f0100214641002138203d2139203c212c024003402037202c460d012038202c2037412010a008223a4100476a2138203a450d01202c41206a212c203941606a2239450d050c000b0b203841ffff034b0d03200e4188016a2139200e4186016a2f0100214841002137203d213a203c212c024003402039202c460d012037202c2039412010a008223b4100476a2137203b450d01202c41206a212c203a41606a223a450d050c000b0b203741ffff034b0d03200e41aa016a213a200e41a8016a2f0100214a41002139203d213b203c212c02400340203a202c460d012039202c203a412010a008223e4100476a2139203e450d01202c41206a212c203b41606a223b450d050c000b0b203941ffff034b0d03200e41cc016a213b200e41ca016a2f0100214b4100213a203d213e203c212c02400340203b202c460d01203a202c203b412010a008223f4100476a213a203f450d01202c41206a212c203e41606a223e450d050c000b0b203a41ffff034b0d03200e41ee016a213e200e41ec016a2f0100214c4100213b203d213f203c212c02400340203e202c460d01203b202c203e412010a00822404100476a213b2040450d01202c41206a212c203f41606a223f450d050c000b0b203b41ffff034b0d03200e4190026a213f200e418e026a2f0100214d4100213e203d2140203c212c02400340203f202c460d01203e202c203f412010a00822414100476a213e2041450d01202c41206a212c204041606a2240450d050c000b0b203e41ffff034b0d03200e41b2026a2140200e41b0026a2f0100214e4100213f203d2141203c212c024003402040202c460d01203f202c2040412010a00822434100476a213f2043450d01202c41206a212c204141606a2241450d050c000b0b203f41ffff034b0d03200e41d4026a2141200e41d2026a2f0100214f41002140203d2143203c212c024003402041202c460d012040202c2041412010a00822454100476a21402045450d01202c41206a212c204341606a2243450d050c000b0b204041ffff034b0d03200e41f6026a2143200e41f4026a2f0100215041002141203d2145203c212c024003402043202c460d012041202c2043412010a00822474100476a21412047450d01202c41206a212c204541606a2245450d050c000b0b204141ffff034b0d03200e4198036a2145200e4196036a2f0100215141002143203d2147203c212c024003402045202c460d012043202c2045412010a00822494100476a21432049450d01202c41206a212c204741606a2247450d050c000b0b204341ffff034b0d03200e41ba036a2145200e41b8036a2f010021494100212c024003402045203c460d01202c203c2045412010a00822474100476a212c2047450d01203c41206a213c203d41606a223d450d050c000b0b202c41ffff034b0d03024020042802a401223220042802a001470d0020152032410110aa0120042802a40121320b200428029c012032413c6c6a2232202c3b0138203220343b010420322033360200203241366a20493b0100203241346a20433b0100203241326a20513b0100203241306a20413b01002032412e6a20503b01002032412c6a20403b01002032412a6a204f3b0100203241286a203f3b0100203241266a204e3b0100203241246a203e3b0100203241226a204d3b0100203241206a203b3b01002032411e6a204c3b01002032411c6a203a3b01002032411a6a204b3b0100203241186a20393b0100203241166a204a3b0100203241146a20373b0100203241126a20483b0100203241106a20383b01002032410e6a20463b01002032410c6a20363b01002032410a6a20443b0100203241086a20353b0100203241066a20423b01002014212c0c020b4102213220022802082233450d022002280200212c203341057421344100213302400340200441e0016a202c460d012033202c200441e0016a412010a00822354100476a21332035450d01202c41206a212c203441606a2234450d040c000b0b2003280208222c450d0241002134202c410574223d21352003280200223c212c02400340200e202c460d012034202c200e412010a00822364100476a21342036450d01202c41206a212c203541606a2235450d040c000b0b203441ffff034b0d02200e41226a2136200e2f0120214241002135203d2138203c212c024003402036202c460d012035202c2036412010a00822374100476a21352037450d01202c41206a212c203841606a2238450d040c000b0b203541ffff034b0d02200e41c4006a2138200e41c2006a2f0100214441002136203d2137203c212c024003402038202c460d012036202c2038412010a00822394100476a21362039450d01202c41206a212c203741606a2237450d040c000b0b203641ffff034b0d02200e41e6006a2137200e41e4006a2f0100214641002138203d2139203c212c024003402037202c460d012038202c2037412010a008223a4100476a2138203a450d01202c41206a212c203941606a2239450d040c000b0b203841ffff034b0d02200e4188016a2139200e4186016a2f0100214841002137203d213a203c212c024003402039202c460d012037202c2039412010a008223b4100476a2137203b450d01202c41206a212c203a41606a223a450d040c000b0b203741ffff034b0d02200e41aa016a213a200e41a8016a2f0100214a41002139203d213b203c212c02400340203a202c460d012039202c203a412010a008223e4100476a2139203e450d01202c41206a212c203b41606a223b450d040c000b0b203941ffff034b0d02200e41cc016a213b200e41ca016a2f0100214c4100213a203d213e203c212c02400340203b202c460d01203a202c203b412010a008223f4100476a213a203f450d01202c41206a212c203e41606a223e450d040c000b0b203a41ffff034b0d02200e41ee016a213e200e41ec016a2f0100214d4100213b203d213f203c212c02400340203e202c460d01203b202c203e412010a00822404100476a213b2040450d01202c41206a212c203f41606a223f450d040c000b0b203b41ffff034b0d02200e4190026a213f200e418e026a2f0100214e4100213e203d2140203c212c02400340203f202c460d01203e202c203f412010a00822414100476a213e2041450d01202c41206a212c204041606a2240450d040c000b0b203e41ffff034b0d02200e41b2026a2140200e41b0026a2f0100214f4100213f203d2141203c212c024003402040202c460d01203f202c2040412010a00822434100476a213f2043450d01202c41206a212c204141606a2241450d040c000b0b203f41ffff034b0d02200e41d4026a2141200e41d2026a2f0100215041002140203d2143203c212c024003402041202c460d012040202c2041412010a00822454100476a21402045450d01202c41206a212c204341606a2243450d040c000b0b204041ffff034b0d02200e41f6026a2143200e41f4026a2f0100215141002141203d2145203c212c024003402043202c460d012041202c2043412010a00822474100476a21412047450d01202c41206a212c204541606a2245450d040c000b0b204141ffff034b0d02200e4198036a2145200e4196036a2f0100215241002143203d2147203c212c024003402045202c460d012043202c2045412010a00822494100476a21432049450d01202c41206a212c204741606a2247450d040c000b0b204341ffff034b0d02200e41ba036a2147200e41b8036a2f0100215341002145203d2149203c212c024003402047202c460d012045202c2047412010a008224b4100476a2145204b450d01202c41206a212c204941606a2249450d040c000b0b204541ffff034b0d02200e41dc036a2147200e41da036a2f0100214b4100212c024003402047203c460d01202c203c2047412010a00822494100476a212c2049450d01203c41206a213c203d41606a223d450d040c000b0b202c41ffff034b0d02024020042802b001223220042802ac01470d0020132032410110a60120042802b00121320b20042802a80120324106746a2232202c3b013c203220343b0104203220333602002032413a6a204b3b0100203241386a20453b0100203241366a20533b0100203241346a20433b0100203241326a20523b0100203241306a20413b01002032412e6a20513b01002032412c6a20403b01002032412a6a20503b0100203241286a203f3b0100203241266a204f3b0100203241246a203e3b0100203241226a204e3b0100203241206a203b3b01002032411e6a204d3b01002032411c6a203a3b01002032411a6a204c3b0100203241186a20393b0100203241166a204a3b0100203241146a20373b0100203241126a20483b0100203241106a20383b01002032410e6a20463b01002032410c6a20363b01002032410a6a20443b0100203241086a20353b0100203241066a20423b01002005212c0c010b4102213220022802082233450d012002280200212c203341057421344100213302400340200441e0016a202c460d012033202c200441e0016a412010a00822354100476a21332035450d01202c41206a212c203441606a2234450d030c000b0b2003280208222c450d0141002134202c410574223d21352003280200223c212c02400340200e202c460d012034202c200e412010a00822364100476a21342036450d01202c41206a212c203541606a2235450d030c000b0b203441ffff034b0d01200e41226a2136200e2f0120214241002135203d2138203c212c024003402036202c460d012035202c2036412010a00822374100476a21352037450d01202c41206a212c203841606a2238450d030c000b0b203541ffff034b0d01200e41c4006a2138200e41c2006a2f0100214441002136203d2137203c212c024003402038202c460d012036202c2038412010a00822394100476a21362039450d01202c41206a212c203741606a2237450d030c000b0b203641ffff034b0d01200e41e6006a2137200e41e4006a2f0100214641002138203d2139203c212c024003402037202c460d012038202c2037412010a008223a4100476a2138203a450d01202c41206a212c203941606a2239450d030c000b0b203841ffff034b0d01200e4188016a2139200e4186016a2f0100214841002137203d213a203c212c024003402039202c460d012037202c2039412010a008223b4100476a2137203b450d01202c41206a212c203a41606a223a450d030c000b0b203741ffff034b0d01200e41aa016a213a200e41a8016a2f0100214a41002139203d213b203c212c02400340203a202c460d012039202c203a412010a008223e4100476a2139203e450d01202c41206a212c203b41606a223b450d030c000b0b203941ffff034b0d01200e41cc016a213b200e41ca016a2f0100214c4100213a203d213e203c212c02400340203b202c460d01203a202c203b412010a008223f4100476a213a203f450d01202c41206a212c203e41606a223e450d030c000b0b203a41ffff034b0d01200e41ee016a213e200e41ec016a2f0100214e4100213b203d213f203c212c02400340203e202c460d01203b202c203e412010a00822404100476a213b2040450d01202c41206a212c203f41606a223f450d030c000b0b203b41ffff034b0d01200e4190026a213f200e418e026a2f0100214f4100213e203d2140203c212c02400340203f202c460d01203e202c203f412010a00822414100476a213e2041450d01202c41206a212c204041606a2240450d030c000b0b203e41ffff034b0d01200e41b2026a2140200e41b0026a2f010021504100213f203d2141203c212c024003402040202c460d01203f202c2040412010a00822434100476a213f2043450d01202c41206a212c204141606a2241450d030c000b0b203f41ffff034b0d01200e41d4026a2141200e41d2026a2f0100215141002140203d2143203c212c024003402041202c460d012040202c2041412010a00822454100476a21402045450d01202c41206a212c204341606a2243450d030c000b0b204041ffff034b0d01200e41f6026a2143200e41f4026a2f0100215241002141203d2145203c212c024003402043202c460d012041202c2043412010a00822474100476a21412047450d01202c41206a212c204541606a2245450d030c000b0b204141ffff034b0d01200e4198036a2145200e4196036a2f0100215341002143203d2147203c212c024003402045202c460d012043202c2045412010a00822494100476a21432049450d01202c41206a212c204741606a2247450d030c000b0b204341ffff034b0d01200e41ba036a2147200e41b8036a2f0100215441002145203d2149203c212c024003402047202c460d012045202c2047412010a008224b4100476a2145204b450d01202c41206a212c204941606a2249450d030c000b0b204541ffff034b0d01200e41dc036a2149200e41da036a2f0100215541002147203d214b203c212c024003402049202c460d012047202c2049412010a008224d4100476a2147204d450d01202c41206a212c204b41606a224b450d030c000b0b204741ffff034b0d01200e41fe036a2149200e41fc036a2f0100214d4100212c024003402049203c460d01202c203c2049412010a008224b4100476a212c204b450d01203c41206a213c203d41606a223d450d030c000b0b202c41ffff034b0d01024020042802bc01223220042802b801470d00201220324101109f0120042802bc0121320b20042802b401203241c4006c6a2232202c3b0140203220343b0104203220333602002032413e6a204d3b01002032413c6a20473b01002032413a6a20553b0100203241386a20453b0100203241366a20543b0100203241346a20433b0100203241326a20533b0100203241306a20413b01002032412e6a20523b01002032412c6a20403b01002032412a6a20513b0100203241286a203f3b0100203241266a20503b0100203241246a203e3b0100203241226a204f3b0100203241206a203b3b01002032411e6a204e3b01002032411c6a203a3b01002032411a6a204c3b0100203241186a20393b0100203241166a204a3b0100203241146a20373b0100203241126a20483b0100203241106a20383b01002032410e6a20463b01002032410c6a20363b01002032410a6a20443b0100203241086a20353b0100203241066a20423b01002011212c0b202c202c28020041016a3602000240202d450d00202d41226c450d00200e10350b2001200f460d040c010b200041013a0000200020323a00010240202d450d00202d41226c450d00200e10350b0240200f2001460d0003400240200141046a280200220e450d00200e41226c450d00200128020010350b2001412c6a2101200d41546a220d0d000b0b02402010450d002010412c6c450d00200c10350b200410fa010c040b200d41546a210d2001210e0c000b0b200f2001460d0003402001220d412c6a21010240200d41046a280200220e450d00200e41226c450d00200d28020010350b200f2001470d000b0b02402010450d002010412c6c450d00200c10350b200041046a200441c001109d081a200041003a00000b20044180026a24000bdb0401097f230041c0016b2202240020024188016a200110b701200241306a200228028801220320022802900110d60120024198016a41086a2204200241ec006a29020037030020024198016a41106a2205200241f4006a29020037030020024198016a41186a2206200241fc006a29020037030020024198016a41206a220720024184016a2802003602002002200241e4006a290200370398010240024020022802502208450d00200241e0006a2802002109200241dc006a280200210a20022802542101200241086a41206a2007280200360200200241086a41186a2006290300370300200241086a41106a2005290300370300200241086a41086a200429030037030020022002290398013703080240200228028c01450d00200310350b200241306a41106a200241086a41106a290300370300200241306a41086a200241086a41086a290300370300200241306a41186a200241086a41186a290300370300200241306a41206a200241086a41206a28020036020020024198016a41086a2002413c6a29020037030020024198016a41106a200241c4006a29020037030020024198016a41186a200241cc006a29020037030020022002290308370330200220022902343703980102402001450d00200141186c450d00200810350b0240200941ffffffff0371450d00200a10350b2000200229039801370001200041196a200241b0016a290300370000200041116a200241a8016a290300370000200041096a200241a0016a290300370000410121010c010b0240200228028c01450d00200310350b410021010b200020013a0000200241c0016a24000bea4711047f017e017f017e0c7f017e017f017e067f027e027f037e017f017e047f017e017f23004180046b22052400200541f8026a41186a22064200370300200541f8026a41106a22074200370300200541f8026a41086a22084200370300200542003703f80241f7edcb00ad4280808080f0008422091001220a290000210b200541a8026a41086a220c200a41086a2900003703002005200b3703a802200a10352008200c290300370300200520052903a8023703f80241b6aac000ad42808080809002841001220a290000210b200541b8026a41086a220d200a41086a2900003703002005200b3703b802200a1035200720052903b802220b370300200541b8036a41086a220a2008290300370300200541b8036a41106a220e200b370300200541b8036a41186a220f200d290300370300200520052903f8023703b803200541e0016a200541b8036a10f20141012110024020052802e001417d710d00200642003703002007420037030020084200370300200542003703f802200910012210290000210b200c201041086a2900003703002005200b3703a802201010352008200c290300370300200520052903a8023703f802419beecb00ad4280808080b002841001220c290000210b200d200c41086a2900003703002005200b3703b802200c1035200720052903b802370000200741086a200d290300370000200a2008290300370300200e2007290300370300200f2006290300370300200520052903f8023703b803200541203602bc022005200541b8036a3602b802200541e8016a200541b8036aad42808080808004842209100510c201410021100240024020052802e80122080d00410021110c010b20052802ec01210a02400240200541f0016a2802004104490d00410121112008280000220f418194ebdc03490d010b4100211120054100360290022005420137038802200541093602e4032005200541b8026a3602e003200520054188026a3602a8022005418c036a4101360200200542013702fc02200541c888c2003602f8022005200541e0036a36028803200541a8026a41e88ac500200541f8026a10431a200535029002422086200535028802841006200528028c02450d0020052802880210350b200a450d00200810350b200541f8026a41186a220d4200370300200541f8026a41106a220c4200370300200541f8026a41086a22084200370300200542003703f80241f7edcb00ad4280808080f000841001220a290000210b200541a8026a41086a2206200a41086a2900003703002005200b3703a802200a103520082006290300370300200520052903a8023703f80241eeedcb00ad42808080809001841001220a290000210b200541b8026a41086a2206200a41086a2900003703002005200b3703b802200a1035200720052903b802370000200741086a2006290300370000200541b8036a41086a2008290300370300200541b8036a41106a200c290300370300200541b8036a41186a200d290300370300200520052903f8023703b803200541f8026a200541b8036a10ac0120052903f8024202510d00200541f8026a200c280200221210b801200541d8016a20052802f802220a20052802800310c00120052802dc01210c20052802d8012108024020052802fc02450d00200a10350b02400240024020080d0041fdb5c000ad4280808080e0068410064100201241e07a6a2208200820124b1b2113201221140c010b4100201241e07a6a2208200820124b1b21130240200c20044b0d00201221140c010b200541f8026a41186a220c4200370300200541f8026a41106a220d4200370300200541f8026a41086a22084200370300200542003703f80241f7edcb00ad4280808080f000841001220a290000210b200541a8026a41086a2206200a41086a2900003703002005200b3703a802200a103520082006290300370300200520052903a8023703f80241aeeecb00ad4280808080a001841001220a290000210b200541b8026a41086a2206200a41086a2900003703002005200b3703b802200a1035200720052903b802370000200741086a2006290300370000200541b8036a41086a2008290300370300200541b8036a41106a200d290300370300200541b8036a41186a200c290300370300200520052903f8023703b803200541f8026a200541b8036a10d90120052802f8022208410420081b220d20052902fc02420020081b220b422088a741037422086a210a03402008450d02200841786a2108200a417c6a210c200a41786a210a200c28020020044b0d000b200d20086a2802002114200b42ffffffff0183500d00200d10350b200541f8026a41186a22154200370300200541f8026a41106a22164200370300200541f8026a41086a22174200370300200542003703f80241f7edcb00ad4280808080f00084221810012208290000210b200541a8026a41086a2219200841086a2900003703002005200b3703a8022008103520172019290300370300200520052903a8023703f80241b8eecb00ad4280808080e00284220b10012208290000211a200541b8026a41086a221b200841086a2900003703002005201a3703b80220081035200720052903b802370000200741086a221c201b290300370000200541b8036a41086a220e2017290300370300200541b8036a41106a221d2016290300370300200541b8036a41186a221e2015290300370300200520052903f8023703b803200541d0016a200541b8036a412010c00120052802d401210a20052802d001210c201542003703002016420037030020174200370300200542003703f802201810012208290000211a2019200841086a2900003703002005201a3703a8022008103520172019290300370300200520052903a8023703f802200b10012208290000210b201b200841086a2900003703002005200b3703b80220081035200720052903b802370000201c201b290300370000200e2017290300370300201d2016290300370300201e2015290300370300200520052903f8023703b8032005200a2012200c4101461b3602f8022009200541f8026aad220b4280808080c00084100220032001200120034b1b221f450d01200f410020111b2120200541a8036aad4280808080c000842121200b42808080808002842122200541a8036a41046a2123200541e0036a41086a2111200021034100212402400240024002400340201542003703002016420037030020174200370300200542003703f802201810012208290000210b2019200841086a2900003703002005200b3703a8022008103520172019290300370300200520052903a8023703f8024194c4c100ad4280808080d0018410012208290000210b201b200841086a2900003703002005200b3703b80220081035200720052903b802370000201c201b290300370000200e2017290300370300201d2016290300370300201e2015290300370300200520052903f8023703b803200541f8026a200541b8036a10fe0120052902fc02420020052802f80222081b220b422088a7410574210a2024220c41016a21242002200c4102746a21042000200c41e0006c6a210f2008410120081b22102108024003400240200a0d004100210d0c020b4101210d20032008460d012008200f412010a008210c200a41606a210a200841206a2108200c0d000b0b0240200b42ffffff3f83500d00201010350b0240200d0d0020042802002108200542003703b002200542003703a802200541c0016a200f290320220b200f41286a290300428094ebdc034200109808200541a0016a200f2903302209200f41386a290300428094ebdc034200109808200541b0016a20052903c001221a200541c0016a41086a29030022254280ec94a37c427f108408200541f0006a201a20252008ad2226420010840820054190016a20052903a001221a200541a0016a41086a29030022254280ec94a37c427f10840820054180016a201a202520264200108408200542003703c002200542003703b802202620092005290390017c7e221a428094ebdc0380212502400240200529037042002026200b20052903b0017c7e220b428094ebdc03802209a7417f200b428080808080c0b2cd3b541b200b20094280ec94a37c7e7c4280cab5ee01566a220aad7d85200541f0006a41086a2903004200200a410047ad7d8584500d00200529038001210920054180016a41086a2903002127200541e8016a2014200f10b20120052802e801210a200520052802f001220c3602f4032005200a3602f00320054188026a200cad422086200aad84100510c20102400240200528028802220c0d004200210b0c010b200528028c0221100240024020052802900222044104490d00200c280000220d418094ebdc034b0d004201210b2004417c6a410f4b0d010b200541003602c003200542013703b803200541093602e4032005200541f0036a3602e0032005200541b8036a3602a8032005410136028c03200542013702fc02200541c888c2003602f8022005200541e0036a36028803200541a8036a41e88ac500200541f8026a10431a20053502c00342208620053502b803841006024020052802bc03450d0020052802b80310350b4200210b2028210d0b02402010450d00200c10350b200d21280b024020052802ec01450d00200a10350b200820284100200b4200521b22064d0d02200541f8026a2014200f10b201200535028003212920052802f802210c41101033220a0d010c070b200542003703f001200542003703e80120054200370390022005420037038802200541f0036a200f10ba01200541b8036a20052802f003220a20052802f80310bc012011200e280200360200200520052903b8033703e003024020052802c4032208450d00200541a8036a41086a2011280200360200200520052903e0033703a80320052903c803210b0b024020052802f403450d00200a10350b0240024020080d00200542003703c80320054280808080c0003703c003200520133602bc03200541003602b803200541f0036a200f10ba0120052802f0032108200520052802f8033602e403200520083602e003200541b8036a200541e0036a10ff01024020052802f403450d00200810350b2011200e280200360200200520052903b8033703e00320052903c803210b410421080c010b2011200541a8036a41086a280200360200200520052903a8033703e0030b201720052903e003370200201741086a2011280200360200200541003a00a4032005200f3602fc02200520133602f802200520203602a0032005200b370390032005200836028c03200520054188026a36029c032005200541e8016a36029803200541b8036a200541f8026a2014108002024020052802c0034102460d0020052802b803200528028003470d002017201210810221082005410120052d00a40320081b22083a00a403200541b8036a200f10b50120053502c00342208620052802b803220aad841007024020052802bc03450d00200a10350b200541b8036a200f10b90120053502c00342208620052802b803220aad841007024020052802bc03450d00200a10350b0240200f10820241ff0171220a4102460d00200a410171450d0010e4010b200841ff0171450d00200528029403220f41027421084101210d200528028c03210a200528028003210120052802f80221042005280284032206210c02400340024020080d00200520062004200620044b1b360284030c020b200d417f6a210d2008417c6a2108200c20044b2110200c200a2802006b210c200a41046a210a20100d000b200f21080240200f2010200d6b220a490d002005200a36029403200a21080b200520062004200620044b1b3602840341000d002001200f6b220a200120086b4f0d00200f20086b210c20052802fc0221080340201e200841186a290000370300201d200841106a290000370300200e200841086a290000370300200520082900003703b8032005200a3602d803200541f0036a200541b8036a10b60120053502f80342208620052802f003220dad841007024020052802f403450d00200d10350b200a41016a210a200c417f6a220c0d000b0b200541b8036a20052802fc0210ba0120052802b8032108200520052802c0033602f403200520083602f0032017200541f0036a10ff0120052802bc03450d00200810350b20052802900341ffffffff0371450d01200528028c0310350c010b200a2008360000200a4110412010372208450d04200820092025a7417f201a428080808080c0b2cd3b541b201a20254280ec94a37c7e7c4280cab5ee01566aad7c220b3700042008410c6a2027200b200954ad7c221a3700002029422086200cad842008ad4280808080c00284100220081035024020052802fc02450d00200c10350b20054188026a200f10ba01200541b8036a200528028802220a20052802900210bc012011200e280200360200200520052903b8033703e003024020052802c4032208450d00200541e8016a41086a2011280200360200200520052903e0033703e80120052903c80321090b0240200528028c02450d00200a10350b0240024020080d00200542003703c80320054280808080c0003703c003200520133602bc03200541003602b80320054188026a200f10ba01200528028802210820052005280290023602f403200520083602f003200541b8036a200541f0036a10ff010240200528028c02450d00200810350b200541f0036a41086a200e280200360200200520052903b8033703f00320052903c8032109410421080c010b200541f0036a41086a200541e8016a41086a280200360200200520052903e8013703f0030b201720052903f003370200201741086a222a200541f0036a41086a280200360200200541003a00a4032005200f3602fc02200520133602f802200520203602a00320052009370390032005200836028c032005200541b8026a36029c032005200541a8026a36029803200541e8006a200541f8026a2014200b201a10830202400240024020052802684101470d00200528026c200528028003460d010b20052d00a40321080c010b2017201210810221082005410120052d00a40320081b22083a00a403200541b8036a200f10b50120053502c00342208620052802b803220aad841007024020052802bc03450d00200a10350b200541b8036a200f10b90120053502c00342208620052802b803220aad841007024020052802bc03450d00200a10350b200f10820241ff0171220a4102460d00200a410171450d0010e4010b0240200841ff0171450d00200528029403222b41027421084101210d200528028c03210a200528028003212c20052802f80221042005280284032201210c02400340024020080d00200520012004200120044b1b360284030c020b200d417f6a210d2008417c6a2108200c20044b2110200c200a2802006b210c200a41046a210a20100d000b202b21080240202b2010200d6b220a490d002005200a36029403200a21080b200520012004200120044b1b3602840341000d00202c202b6b220a202c20086b4f0d00202b20086b210c20052802fc0221080340201e200841186a290000370300201d200841106a290000370300200e200841086a290000370300200520082900003703b8032005200a3602d80320054188026a200541b8036a10b601200535029002422086200528028802220dad8410070240200528028c02450d00200d10350b200a41016a210a200c417f6a220c0d000b0b200541b8036a20052802fc0210ba0120052802b8032108200520052802c00336028c022005200836028802201720054188026a10ff0120052802bc03450d00200810350b024020052802900341ffffffff0371450d00200528028c0310350b200541003602d002200542083703c802200542003703f001200542003703e801200541c8026a4100200f41c8006a220828020010880102400240200828020022080d004200210920052802c802210d4200211a0c010b200f2802402201200841306c6a212d2006ad2127034020054200370390022005420037038802200541c0006a2001290300221a200141086a290300428094ebdc034200109808200541306a2005290340220b200541c0006a41086a29030022094280ec94a37c427f108408200541206a200b200920274200108408200541106a200b200920264200108408200541f8026a2014200141106a220610b301200541d0006a20052802f802220a20052802800310d7014200200541106a41086a290300200529031022092026201a20052903307c221a7e220b428094ebdc03802225a7417f200b428080808080c0b2cd3b541b200b20254280ec94a37c7e7c4280cab5ee01566aad7c220b200954ad7c2209200541206a41086a290300200529032022252027201a7e221a428094ebdc03802229a7417f201a428080808080c0b2cd3b541b201a20294280ec94a37c7e7c4280cab5ee01566aad7c221a202554ad7c7d200b201a54ad7d2225200b201a7d221a200b56202520095620252009511b22081b21094200201a20081b210b200541d0006a41106a290300211a2005290358212520052802502108024020052802fc02450d00200a10350b200541b8036a2014200610b30120052802b803210a20053502c003212920052025420020081b2225200b7c220b3703f8022005201a420020081b20097c200b202554ad7c2209370380032029422086200aad8420221002024020052802bc03450d00200a10350b200541f0036a200610ba01200541b8036a20052802f003220a20052802f80310bc012011200e280200360200200520052903b8033703e003024020052802c4032208450d00200541a8036a41086a2011280200360200200520052903e0033703a80320052903c803212e0b024020052802f403450d00200a10350b0240024020080d00200542003703c80320054280808080c0003703c003200520133602bc03200541003602b803200541f0036a200610ba0120052802f0032108200520052802f8033602e403200520083602e003200541b8036a200541e0036a10ff01024020052802f403450d00200810350b2011200e280200360200200520052903b8033703e00320052903c803211a410421080c010b2011200541a8036a41086a280200360200200520052903a8033703e003202e211a0b201720052903e003370200202a2011280200360200200541003a00a403200520063602fc02200520133602f802200520203602a0032005201a370390032005200836028c03200520054188026a36029c032005200541e8016a36029803200541086a200541f8026a2014200b20091083020240024020052802084101470d00200528020c200528028003470d002017201210810221082005410120052d00a40320081b22083a00a4030c010b20052d00a40321080b0240200841ff0171450d00200528029403222c41027421084101210d200528028c03210a200528028003212f20052802f8022104200528028403222b210c02400340024020080d002005202b2004202b20044b1b360284030c020b200d417f6a210d2008417c6a2108200c20044b2110200c200a2802006b210c200a41046a210a20100d000b202c21080240202c2010200d6b220a490d002005200a36029403200a21080b2005202b2004202b20044b1b3602840341000d00202f202c6b220a202f20086b4f0d00202c20086b210c20052802fc0221080340201e200841186a290000370300201d200841106a290000370300200e200841086a290000370300200520082900003703b8032005200a3602d803200541f0036a200541b8036a10b60120053502f80342208620052802f003220dad841007024020052802f403450d00200d10350b200a41016a210a200c417f6a220c0d000b0b200541b8036a20052802fc0210ba0120052802b8032108200520052802c0033602f403200520083602f0032017200541f0036a10ff0120052802bc03450d00200810350b024020052802900341ffffffff0371450d00200528028c0310350b200141306a2101200641086a290000210b200629000021092015200641186a2900003703002016200641106a2900003703002017200b370300200520093703f80220054188026a41086a290300210b2005290388022109024020052802d002220a20052802cc02470d00200541c8026a200a410110880120052802d002210a0b20052802c802220d200a41306c6a22082009370320200820052903f802370300200841286a200b370300200841086a2017290300370300200841106a2016290300370300200841186a20152903003703002005200a41016a3602d0022001202d470d000b200541e8016a41086a290300211a20052903e80121090b2019290300212520052903a802210b200541e8016a41086a2208200f41086a290300370300200541e8016a41106a220a200f41106a290300370300200541e8016a41186a220c200f41186a2903003703002005200f2903003703e801200d450d00201b290300212620052903b802212720052902cc02212920054188026a41186a2204200c29030037030020054188026a41106a2201200a29030037030020054188026a41086a222b2008290300370300200520052903e80137038802200f280258221041ffffff3f712010470d022010410574220c417f4c0d02200f280250210802400240200c0d004101210a0c010b200c1033220a450d060b20054100360280032005200a3602f8022005200c4105763602fc02200541f8026a41002010108a0120052802800321060240024020100d0020052802f802212c0c010b20052802f802222c20064105746a210a0340200a2008290000370000200a41186a200841186a290000370000200a41106a200841106a290000370000200a41086a200841086a290000370000200a41206a210a200841206a2108200c41606a220c0d000b201041057441606a41057620066a41016a21060b20052802fc02212f201e2004290300370300201d2001290300370300200e202b29030037030020052005290388023703b803201810012208290000212e2019200841086a2900003703002005202e3703a8022008103541efb6c000ad428080808080028410012208290000212e201b200841086a2900003703002005202e3703b80220081035200520123602a80320052021100322082900003703e003200810352005202336028403200520113602fc022005200541a8036a360280032005200541e0036a3602f802200541f0036a200541f8026a107b20052802f803220441206a220a417f4c0d0220052802f003210f02400240200a0d0041002108410121100c010b200a10332210450d06200a21080b024002402008410f4d0d002008210c0c010b2008410174220c4110200c41104b1b220c4100480d04024020080d00200c103322100d010c060b2008200c460d0020102008200c10372210450d050b201020052903a802370000201041086a201929030037000002400240200c4170714110460d00200c21080c010b200c41017422084120200841204b1b22084100480d04200c2008460d002010200c200810372210450d050b201020052903b802370010201041186a201b29030037000002400240200841606a2004490d00200821010c010b2004415f4b0d042008410174220c200a200c200a4b1b22014100480d0420082001460d0020102008200110372210450d050b200b20097c2209200b542108201041206a200f2004109d081a024020052802f403450d00200f10350b2025201a7c210b2008ad211a200541f8026a2010200a10dd010240024020052802f80222040d004100210f200541003602c002200542083703b802410821044100210c0c010b200520052902fc0222253702bc02200520043602b8022025422088a7210c2025a7210f0b200b201a7c210b2015201e2903003703002016201d2903003703002017200e290300370300200520052903b8033703f8020240200c200f470d00200541b8026a200c4101109b0120052802bc02210f20052802b802210420052802c002210c0b2004200c41d8006c222b6a2208200937031020082026370308200820273703002008202c36022c2008200d360220200841186a200b370300200841346a2006360200200841306a202f360200200841246a2029370200200820052903f802370338200841c0006a2017290300370300200841c8006a2016290300370300200841d0006a20152903003703002005200c41016a22083602c0020240024020040d00200aad4220862010ad8410070c010b200541f8026a2004200810ea01200aad4220862010ad8420053502800342208620052802f802220aad841002024020052802fc02450d00200a10350b02402008450d00200441306a2108202b41d8006a210a03400240200841746a280200220c450d00200c41306c450d00200841706a28020010350b0240200828020041ffffff3f71450d002008417c6a28020010350b200841d8006a2108200a41a87f6a220a0d000b0b200f450d00200f41d8006c450d00200410350b2001450d00201010350b200341e0006a21032024201f490d000b410021100c050b1044000b103e000b103c000b1045000b41002110200b42ffffffff0183500d00200d10350b20054180046a240020100bbf0201027f230041e0006b220224002002412036020c20022001360208200241106a2001ad4280808080800484100510c20102400240200228021022010d00200041003602000c010b200228021421032002200241106a41086a28020036022420022001360220200241c8006a200241206a10c3010240024020022802480d0020024100360230200242013703282002410936023c2002200241086a3602382002200241286a360244200241dc006a41013602002002420137024c200241c888c2003602482002200241386a360258200241c4006a41e88ac500200241c8006a10431a200235023042208620023502288410060240200228022c450d00200228022810350b200041003602000c010b20002002290348370200200041086a200241c8006a41086a2802003602000b2003450d00200110350b200241e0006a24000b8f0301067f230041106b220224002002410036020820024201370300200028020021030240410410332204450d002004200336000020024284808080c000370204200220043602002000280204210320044104410810372204450d0020042003360004200242888080808001370204200220043602002000280208210320044108411010372204450d002004200336000820024290808080c00137020420022004360200200028020c2105200041146a28020022002002107702400240024020022802042206200228020822046b20004102742203490d0020022802002100200621070c010b200420036a22002004490d01200641017422072000200720004b1b22074100480d010240024020060d00024020070d00410121000c020b2007103322000d010c040b2002280200210020062007460d0020002006200710372200450d030b20022007360204200220003602000b200020046a20052003109d081a2001290200200420036aad4220862000ad84100202402007450d00200010350b200241106a24000f0b103e000b103c000bbd0101057f2001280208210302402001410c6a280200220420024b0d002000410036020820002004ad4220862003ad843702000f0b024002402001411c6a2802002205450d00200141146a2802002101200541027421062003417f6a2103034002402004200128020022076b220520024b0d00200420024b0d030b200141046a21012003417f6a2103200521042006417c6a22060d000b0b200041023602080f0b2000200736020c2000410136020820002005ad4220862003ad843702000ba00201067f410021020240200141016a2203200028020422044d0d000240200041146a22052802002201200041106a280200470d000240024002400240200141016a22022001490d00200141017422062002200620024b1b220241ffffffff03712002470d00200241027422024100480d00024020010d0020020d02410421060c040b200028020c2106200141027422072002460d03024020070d0020020d02410421060c040b20062007200210372206450d020c030b103e000b2002103322060d010b103c000b2000200636020c200041106a20024102763602000b200028020c220241046a20022001410274109e081a2002200320046b36020020002003360204410121022005200141016a3602002000200028020041016a3602000b20020bd20f07047f017e047f017e047f017e017f23004190016b22012400200141386a41186a4200370300200141386a41106a22024200370300200141386a41086a220342003703002001420037033841a3edcb00ad4280808080f000841001220429000021052003200441086a290000370300200120053703382004103541f393ca00ad4280808080a00184100122042900002105200141286a41086a2206200441086a2900003703002001200537032820041035200220012903282205370300200141e8006a41086a2003290300370300200141e8006a41106a2005370300200141e8006a41186a200629030037030020012001290338370368200141386a200141e8006a10fe0120012802382203410120031b21074102210802400240200129023c420020031b2205422088a72203450d002003410574210241002104200721030240034020002003460d01200420032000412010a00822064100476a21042006450d01200341206a2103200241606a22020d000c020b0b200141386a41186a4200370300200141386a41106a22094200370300200141386a41086a220042003703002001420037033841a3edcb00ad4280808080f0008410012202290000210a200141286a41086a2203200241086a2900003703002001200a37032820021035200020032903003703002001200129032837033841beebcb00ad4280808080a0028410012202290000210a2003200241086a2900003703002001200a3703282002103520092001290328220a370300200141e8006a41086a2000290300370300200141e8006a41106a200a370300200141e8006a41186a200329030037030020012001290338370368200141186a200141e8006a10c5020240024002402001280218220b0d004100210c20014100360210200142043703084104210b4100210d410021030c010b200129021c210a2001200b3602082001200a37020c200aa7210d4100210302400240200a422088a7220c41014b0d00200c0e020201020b200c2100034020032000410176220220036a22062004200b20064102746a280200491b2103200020026b220041014b0d000b0b4100210802402004200b20034102746a2802002200470d00410021060c020b2003200420004b6a21030b200141386a41186a22084200370300200141386a41106a220e4200370300200141386a41086a220242003703002001420037033841a3edcb00ad4280808080f0008410012206290000210a200141286a41086a2200200641086a2900003703002001200a37032820061035200220002903003703002001200129032837033841f393ca00ad4280808080a0018410012206290000210a2000200641086a2900003703002001200a3703282006103520092001290328370000200941086a2000290300370000200141e8006a41086a2002290300370300200141e8006a41106a200e290300370300200141e8006a41186a200829030037030020012001290338370368200141286a200141e8006aad4280808080800484100510c201024002400240024020012802282202450d00200128022c21062001200028020036023c200120023602382001200141386a10c4012001280200450d01410021000c020b2001420037023c20014101360238200141386a108a0321000c020b200128020421000b2006450d00200210350b20002000418094ebdc036e22024180ec94a37c6c6aad4280fd87d1007e220f428094ebdc0380210a200c2003490d0220024180fd87d1006c200f200a4280ec94a37c7e7c4280cab5ee015672200aa76a21020240200c200d470d00200141086a200d4101108601200128020c210d2001280208210b0b200b20034102746a220041046a2000200c20036b410274109e081a20002004360200410121062001200c41016a220c360210200c20024b21080b200141386a41186a220e4200370300200141386a41106a22104200370300200141386a41086a220042003703002001420037033841a3edcb00ad4280808080f0008410012202290000210a200141286a41086a2203200241086a2900003703002001200a37032820021035200020032903003703002001200129032837033841beebcb00ad4280808080a0028410012202290000210a2003200241086a2900003703002001200a3703282002103520092001290328370000200941086a2003290300370000200141e8006a41086a2000290300370300200141e8006a41106a2010290300370300200141e8006a41186a200e2903003703002001200129033837036802400240200b0d00200141e8006aad428080808080048410070c010b2001412036023c2001200141e8006a360238200b200c200141386a109503200d41ffffffff0371450d00200b10350b2006450d00200141e8006a41086a22032004ad37030020014102360268200141386a200141e8006a108805200141336a2200200141386a41086a2802003600002001200129033837002b200141386a410c6a2001412f6a2202290000370000200141c6a4b9da04360039200141023a00382001200129002837003d200141386a108204200141013602382001200436023c200141e8006a200141386a108104200020032802003600002001200129036837002b200141e8006a410c6a2002290000370000200141c28289aa04360069200141023a00682001200129002837006d200141e8006a1082040b0240200542ffffff3f83500d00200710350b20014190016a240020080f0b2003200c104d000b9a0d04047f017e027f067e230041d0026b22052400200541c8016a2001200210800202400240024002400240024020052802d0014102460d0020052802c8012106200541c8016a41086a2001280204220741086a290000370300200541c8016a41106a200741106a290000370300200541c8016a41186a200741186a290000370300200520063602e801200520072900003703c801200541f0016a200541c8016a10b60120052802f0012108200520052802f801220736028402200520083602800220054188026a2007ad4220862008ad84100510c2010240024020052802880222070d00420021090c010b200528028c02210a02400240024020054188026a41086a280200220b4110490d00200b4170714110470d010b200541003602a0022005420137039802200541093602ac02200520054180026a3602a802200520054198026a3602b402200541cc026a4101360200200542013702bc02200541c888c2003602b8022005200541a8026a3602c802200541b4026a41e88ac500200541b8026a10431a20053502a0024220862005350298028410060240200528029c02450d0020052802980210350b420021090c010b200741186a290000210c200741086a290000210d2007290010210e2007290000210f420121090b200a450d00200710350b200d4200200942005222071b210d200f420020071b210f024020052802f401450d00200810350b200c420020071b210c200e420020071b210e200f200354200d200454200d2004511b0d01200f200385200d2004858450450d03200541b8016a20032004428094ebdc034200109808200541a8016a20052903b801220d200541b8016a41086a290300220f4280ec94a37c427f10840820054198016a200d200f20013502282209420010840820054188016a4200200529039801220f200920052903a80120037c7e220d428094ebdc03802209a7417f200d428080808080c0b2cd3b541b200d20094280ec94a37c7e7c4280cab5ee01566aad7c220d200e7d22092009200d5620054198016a41086a290300200d200f54ad7c220f200c7d200d200e54ad7d220d200f56200d200f511b22021b220f4200200d20021b428094ebdc034200109808200541f8006a200529038801220d20054188016a41086a29030022094280ec94a37c427f108408200541e8006a200d20094280cab5ee014200108408200541e8006a41086a29030020052903682209200f20052903787c220d420188220fa7417f200d4280cab5ee017e220d428080808080c0b2cd3b541b200d200f4280ec94a37c7e7c4280cab5ee01566aad7c220d200954ad7c210f410021020c020b410021010c040b200541c8006a20032004428094ebdc034200109808200541d8006a20032004428094ebdc034200108608200541386a2005290348200541c8006a41086a290300200135022822094200108408200541286a420020052903382210200920052903587e2209428094ebdc03802211a7417f2009428080808080c0b2cd3b541b200920114280ec94a37c7e7c4280cab5ee01566aad7c2209200e7d22112011200956200541386a41086a2903002009201054ad7c2210200c7d2009200e54ad7d220920105620092010511b22071b22104200200920071b428094ebdc034200109808200541186a20052903282209200541286a41086a29030022114280ec94a37c427f108408200541086a200920114280cab5ee014200108408200128022422072003200f7d220920072903007c2211370300200741086a22072004200d7d2003200f54ad7d20072903007c2011200954ad7c370300200141106a2207200728020022072002200720024b1b360200200541086a41086a2903002005290308220f201020052903187c220d4201882209a7417f200d4280cab5ee017e220d428080808080c0b2cd3b541b200d20094280ec94a37c7e7c4280cab5ee01566aad7c220d200f54ad7c210f410121020b02400240200d200f84500d002001280220220220022903002209200d7c2210370300200241086a22022002290300200f7c2010200954ad7c370300200c200f7c200e200d7c220d200e54ad7c210c200d210e0c010b2002450d010b200141013a002c200541b8026a200541c8016a10b60120053502c002210d20052802b8022102411010332201450d01200120033700002001200437000820014110412010372201450d012001200e370010200141186a200c370000200d4220862002ad842001ad428080808080048410022001103520052802bc02450d00200210350b410121010c010b103c000b2000200636020420002001360200200541d0026a24000be70403057f017e037f23004180016b22022400200241206a41186a22034200370300200241206a41106a22044200370300200241206a41086a220542003703002002420037032041f7edcb00ad4280808080f000841001220629000021072005200641086a290000370300200220073703202006103541eeedcb00ad4280808080900184100122062900002107200241086a2208200641086a2900003703002002200737030020061035200420022903002207370300200241e0006a41086a22062005290300370300200241e0006a41106a22092007370300200241e0006a41186a220a200829030037030020022002290320370360200241206a200241e0006a10ac010240024020022903204202520d00200041003602200c010b200241d0006a2004280200200110ce01200241206a200228025022082002280258108502200a2003290300370300200920042903003703002006200529030037030020022002290320370360200241cc006a280200210402400240200228024022050d0042002107200241186a4200370300200241106a420037030041082105200241086a4200370300200242003703000c010b200241086a200241e0006a41086a290300370300200241106a200241e0006a41106a290300370300200241186a200241e0006a41186a29030037030020022002290360370300200229024421070b02402002280254450d00200810350b2000200229030037030020002007370224200020053602202000412c6a2004360200200041186a200241186a290300370300200041106a200241106a290300370300200041086a200241086a2903003703000b20024180016a24000b860301017f230041f0006b220324002003200236020420032001360200200341086a2002ad4220862001ad84100510c20102400240200328020822010d00200041003602200c010b200328020c21022003200341086a41086a28020036024c20032001360248200341186a200341c8006a10c5010240024020032802380d00200341003602582003420137035020034109360264200320033602602003200341d0006a36026c2003412c6a41013602002003420137021c200341c888c2003602182003200341e0006a360228200341ec006a41e88ac500200341186a10431a2003350258422086200335025084100602402003280254450d00200328025010350b200041003602200c010b20002003290318370300200041286a200341186a41286a290300370300200041206a200341186a41206a290300370300200041186a200341186a41186a290300370300200041106a200341186a41106a290300370300200041086a200341186a41086a2903003703000b2002450d00200110350b200341f0006a24000bc00908057f047e027f027e067f017e037f017e230041e0016b22032400200241386a2802002104200241346a2802002105200241306a2802002106200341c0006a41186a200241186a290000370300200341c0006a41106a200241106a290000370300200341c0006a41086a200241086a290000370300200320022900003703404100210720034100360268200342083703600240024020040d0042002108420021094200210a4200210b0c010b200441306c210c200341b0016a41106a21044108210d42002108420021094200210a4200210b200621020340200241286a290300210e200241206a290300210f200341f0006a41186a2210200241186a290300370300200341f0006a41106a2211200241106a290300370300200341f0006a41086a2212200241086a29030037030020032002290300370370200341b0016a41186a2213420037030020044200370300200341b0016a41086a22144200370300200342003703b00141b6fdc600ad42808080808001841001221529000021162014201541086a290000370300200320163703b0012015103541e489c200ad4280808080d00184100122152900002116200341d0016a41086a2217201541086a290000370300200320163703d00120151035200420032903d001370000200441086a201729030037000020034190016a41086a2215201429030037030020034190016a41106a2217200429030037030020034190016a41186a22182013290300370300200320032903b00137039001200341286a20034190016a412010d701200341186a2003290330200341286a41106a290300427f4200109808200341086a20032903184200200328022822191b221642012016420156200341186a41086a290300420020191b22164200522016501b22191b2016420020191b200f200e1084082018201029030037030020172011290300370300201520122903003703002003200329037037039001200341086a41086a29030021162003290308210e0240024020034190016a200341c0006a412010a008450d0020132018290300370300200420172903003703002014201529030037030020032003290390013703b001024020072003280264470d00200341e0006a200741011088012003280260210d200328026821070b200d200741306c6a221520163703082015200e370300201520032903b001370310201541186a2014290300370300201541206a2004290300370300201541286a20132903003703002003200741016a22073602680c010b427f200920167c2008200e7c221a2008542214ad7c220f2014200f200954200f2009511b22141b2109427f201a20141b21080b200241306a2102427f200b20167c200a200e7c2216200a542214ad7c220a2014200a200b54200a200b511b22141b210b427f201620141b210a200c41506a220c0d000b0b02402005450d00200541306c450d00200610350b2000200a37032020002003290340370000200041386a2009370300200041306a2008370300200041286a200b370300200041c0006a2003290360370200200041186a200341c0006a41186a290300370000200041106a200341c0006a41106a290300370000200041086a200341c0006a41086a290300370000200041c8006a200341e0006a41086a280200360200200341e0016a24000ba21904047f017e047f037e230041d0016b22022400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d0000417f6a220341174b0d0020030e180102030405060708090a0b0c0d0e0f101112131415161718010b41cfa2cc00412841c086cc00103f000b4101210302400240200141046a2d00004101470d00200141086a28020021040c010b200241c2016a200141076a2d00003a0000200241086a200141146a290000370300200241106a2001411c6a290000370300200241186a200141246a2d00003a00002002200141056a2f00003b01c00120022001410c6a290000370300200141086a2800002104410021030b200041286a2001290328370300200041046a20033a0000200041056a20022f01c0013b0000200041086a20043602002000410c6a2002290300370200200041306a200141306a290300370300200041076a200241c2016a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a28020036020020012d00012101200041013a0000200020013a00010c170b200041023a0000200041106a200141106a290300370300200041086a200141086a2903003703000c160b200041033a0000200041106a200141106a290300370300200041086a200141086a2903003703000c150b200041043a00000c140b200041053a0000200041046a200141046a2802003602000c130b2001410c6a2802002205ad42247e2206422088a70d132006a72204417f4c0d13200141046a28020021030240024020040d00410421010c010b200410332201450d150b200241003602c801200220013602c0012002200441246e3602c401200241c0016a41002005108d0120022802c801210402402005450d00200541246c210520022802c001200441246c6a2101200241ce016a210703400240024020032d00004101470d00200341046a2802002108410121090c010b2007200341036a2d00003a0000200341046a2800002108200341016a2f00002109200241086a200341106a290000370300200241106a200341186a290000370300200241186a200341206a2d00003a0000200220093b01cc012002200341086a290000370300410021090b200341246a2103200120093a0000200141046a2008360200200141016a20022f01cc013b0000200141036a20072d00003a0000200141086a2002290300370200200141106a200241086a290300370200200141186a200241106a290300370200200141206a200241186a280200360200200141246a2101200441016a21042005415c6a22050d000b0b200241086a2004360200200220022903c00122063703002000410c6a2004360200200041046a2006370200200041063a00000c120b200041073a00000c110b200041083a0000200020012d00013a00010c100b4101210302400240200141046a2d00004101470d00200141086a28020021010c010b200241c2016a200141076a2d00003a0000200241086a200141146a290000370300200241106a2001411c6a290000370300200241186a200141246a2d00003a00002002200141056a2f00003b01c00120022001410c6a290000370300200141086a2800002101410021030b200041093a0000200041046a20033a0000200041056a20022f01c0013b0000200041086a20013602002000410c6a2002290300370200200041076a200241c2016a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a2802003602000c0f0b2000410a3a0000200041046a200141046a2802003602000c0e0b2000410b3a00000c0d0b2000410c3a00000c0c0b2001410c6a280200220741ffffff3f712007470d0c20074105742203417f4c0d0c200141046a28020021050240024020030d00410121040c010b200310332204450d0e0b41002101200241003602082002200436020020022003410576360204200241002007108a012002280208210a02402007450d00200741057421082002280200200a4105746a21090340200920016a2203200520016a2204290000370000200341186a200441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002008200141206a2201470d000b200741057441606a410576200a6a41016a210a0b200241c8016a200a3602002002200229030022063703c0012000410c6a200a360200200041046a20063702002000410d3a00000c0b0b2000410e3a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000c0a0b2000410f3a00000c090b200141106a280200220341ffffffff03712003470d0920034102742204417f4c0d09200141046a2802002105200141086a28020021084104210102402004450d00200410332201450d0b0b2002410036020820022001360200200220044102763602042002410020031086012002280200200228020822014102746a20082003410274109d081a200241c0016a41086a200120036a22013602002002200229030022063703c001200041046a2005360200200041086a2006370200200041106a2001360200200041103a00000c080b200141106a2802002203ad42247e2206422088a70d082006a72204417f4c0d08200141046a2802002108200141086a28020021010240024020040d00410421050c010b200410332205450d0a0b20024100360208200220053602002002200441246e360204200241002003108d012002280208210402402003450d00200341246c21052002280200200441246c6a21030340200141086a2902002106200141106a290200210b200141186a290200210c2001290200210d200341206a200141206a280200360200200341186a200c370200200341106a200b370200200341086a20063702002003200d370200200341246a2103200441016a2104200141246a21012005415c6a22050d000b0b200241c0016a41086a20043602002002200229030022063703c001200041046a2008360200200041086a2006370200200041106a2004360200200041113a00000c070b200041123a0000200041046a200141046a2802003602000c060b200041133a000020002001290001370001200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a290000370000200041246a200141246a2802003602000c050b200041143a0000200041106a200141106a290300370300200041086a200141086a2903003703000c040b200041153a0000200041046a200141046a2802003602000c030b200041163a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000c020b2001410c6a280200220320036a22042003490d022004417f4c0d02200141046a28020021050240024020040d00410221080c010b200410332208450d040b200241003602082002200836020020022004410176360204200241002003108e012002280200200228020822044101746a20052003410174109d081a200241c0016a41086a2205200420036a360200200220022903003703c0012002200141106a108802200041046a20022903c0013702002000410c6a200528020036020020012802d0012103200041106a200241c001109d081a200041d0016a2003360200200041173a000020004180026a200141d8016a220141286a290300370300200041f8016a200141206a290300370300200041f0016a200141186a290300370300200041e8016a200141106a290300370300200041e0016a200141086a290300370300200041d8016a20012903003703000c010b2001410c6a280200220320036a22042003490d012004417f4c0d01200141046a28020021050240024020040d00410221080c010b200410332208450d030b200241003602082002200836020020022004410176360204200241002003108e012002280200200228020822044101746a20052003410174109d081a200241c0016a41086a2205200420036a360200200220022903003703c0012002200141106a108802200041046a20022903c0013702002000410c6a200528020036020020012802d0012103200041106a200241c001109d081a200041d0016a2003360200200041183a000020004180026a200141d8016a220141286a290300370300200041f8016a200141206a290300370300200041f0016a200141186a290300370300200041e8016a200141106a290300370300200041e0016a200141086a290300370300200041d8016a20012903003703000b200241d0016a24000f0b1044000b1045000bc11702057f017e23004180026b22022400024002402001280208220341ffffffff01712003470d0020034103742204417f4c0d00200128020021050240024020040d00410421060c010b200410332206450d020b200241003602f801200220063602f001200220044103763602f401200241f0016a4100200310900120022802f00120022802f80122044103746a20052003410374109d081a200041086a200420036a360200200020022903f001370200200141146a2802002204ad420c7e2207422088a70d002007a72203417f4c0d00200128020c21064104210502402003450d00200310332205450d020b200241003602f801200220053602f00120022003410c6e3602f401200241f0016a4100200410870120022802f00120022802f8012205410c6c6a20062003109d081a200241086a200520046a360200200220022903f001370300200141206a280200220341ffffffff00712003470d0020034104742204417f4c0d00200128021821064104210502402004450d00200410332205450d020b200241003602f801200220053602f001200220044104763602f401200241f0016a41002003108c0120022802f00120022802f80122044104746a20062003410474109d081a200241186a200420036a360200200220022903f0013703102001412c6a2802002204ad42147e2207422088a70d002007a72203417f4c0d00200128022421050240024020030d00410421060c010b200310332206450d020b200241003602f801200220063602f0012002200341146e3602f401200241f0016a4100200410990120022802f00120022802f801220641146c6a20052003109d081a200241286a200620046a360200200220022903f001370320200141386a2802002204ad42187e2207422088a70d002007a72203417f4c0d00200128023021050240024020030d00410421060c010b200310332206450d020b200241003602f801200220063602f0012002200341186e3602f401200241f0016a4100200410970120022802f00120022802f801220641186c6a20052003109d081a200241386a200620046a360200200220022903f001370330200141c4006a2802002204ad421c7e2207422088a70d002007a72203417f4c0d00200128023c21050240024020030d00410421060c010b200310332206450d020b200241003602f801200220063602f00120022003411c6e3602f401200241f0016a4100200410f90120022802f00120022802f8012206411c6c6a20052003109d081a200241c8006a200620046a360200200220022903f001370340200141d0006a280200220341ffffff3f712003470d0020034105742204417f4c0d00200128024821050240024020040d00410421060c010b200410332206450d020b200241003602f801200220063602f001200220044105763602f401200241f0016a4100200310910120022802f00120022802f80122044105746a20052003410574109d081a200241d8006a200420036a360200200220022903f001370350200141dc006a2802002204ad42247e2207422088a70d002007a72203417f4c0d00200128025421050240024020030d00410421060c010b200310332206450d020b200241003602f801200220063602f0012002200341246e3602f401200241f0016a41002004108d0120022802f00120022802f801220641246c6a20052003109d081a200241e8006a200620046a360200200220022903f001370360200141e8006a2802002204ad42287e2207422088a70d002007a72203417f4c0d00200128026021050240024020030d00410421060c010b200310332206450d020b200241003602f801200220063602f0012002200341286e3602f401200241f0016a41002004109d0120022802f00120022802f801220641286c6a20052003109d081a200241f8006a200620046a360200200220022903f001370370200141f4006a2802002204ad422c7e2207422088a70d002007a72203417f4c0d00200128026c21050240024020030d00410421060c010b200310332206450d020b200241003602f801200220063602f00120022003412c6e3602f401200241f0016a4100200410980120022802f00120022802f8012206412c6c6a20052003109d081a20024188016a200620046a360200200220022903f0013703800120014180016a2802002204ad42307e2207422088a70d002007a72203417f4c0d00200128027821050240024020030d00410421060c010b200310332206450d020b200241003602f801200220063602f0012002200341306e3602f401200241f0016a4100200410890120022802f00120022802f801220641306c6a20052003109d081a20024198016a200620046a360200200220022903f001370390012001418c016a2802002204ad42347e2207422088a70d002007a72203417f4c0d0020012802840121050240024020030d00410421060c010b200310332206450d020b200241003602f801200220063602f0012002200341346e3602f401200241f0016a4100200410a50120022802f00120022802f801220641346c6a20052003109d081a200241a8016a200620046a360200200220022903f0013703a00120014198016a2802002204ad42387e2207422088a70d002007a72203417f4c0d0020012802900121050240024020030d00410421060c010b200310332206450d020b200241003602f801200220063602f0012002200341386e3602f401200241f0016a4100200410a20120022802f00120022802f801220641386c6a20052003109d081a200241b8016a200620046a360200200220022903f0013703b001200141a4016a2802002204ad423c7e2207422088a70d002007a72203417f4c0d00200128029c0121050240024020030d00410421060c010b200310332206450d020b200241003602f801200220063602f00120022003413c6e3602f401200241f0016a4100200410aa0120022802f00120022802f8012206413c6c6a20052003109d081a200241c8016a200620046a360200200220022903f0013703c001200141b0016a280200220341ffffff1f712003470d0020034106742204417f4c0d0020012802a80121050240024020040d00410421060c010b200410332206450d020b200241003602f801200220063602f001200220044106763602f401200241f0016a4100200310a60120022802f00120022802f80122044106746a20052003410674109d081a200241d8016a200420036a360200200220022903f0013703d001200141bc016a2802002204ad42c4007e2207422088a70d002007a72203417f4c0d0020012802b40121010240024020030d00410421050c010b200310332205450d020b200241003602f801200220053602f0012002200341c4006e3602f401200241f0016a41002004109f0120022802f00120022802f801220541c4006c6a20012003109d081a200241e0016a41086a2201200520046a360200200220022903f0013703e001200041146a200241086a2802003602002000200229030037020c20002002290310370218200041206a200241106a41086a280200360200200020022903203702242000412c6a200241206a41086a28020036020020002002290330370230200041386a200241306a41086a280200360200200041c4006a200241c0006a41086a2802003602002000200229034037023c200041d0006a200241d0006a41086a28020036020020002002290350370248200041dc006a200241e0006a41086a28020036020020002002290360370254200041e8006a200241f0006a41086a28020036020020002002290370370260200041f4006a20024180016a41086a280200360200200020022903800137026c20004180016a20024190016a41086a28020036020020002002290390013702782000418c016a200241a0016a41086a280200360200200020022903a0013702840120004198016a200241b0016a41086a280200360200200020022903b00137029001200041a4016a200241c0016a41086a280200360200200020022903c00137029c01200041b0016a200241d0016a41086a280200360200200020022903d0013702a801200041bc016a2001280200360200200020022903e0013702b40120024180026a24000f0b1044000b1045000b89f0020a017f027e017f017e127f037e037f037e067f047e230041900c6b220324000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e19000102030405061a1917161514131211100f0e0d0c0b0a0908000b200341940a6a4101360200200342013702840a200341e8d4ca003602800a200341043602f4062003419cd5ca003602f0062003200341f0066a3602900a200341800a6a41b0b4cc00104c000b200141306a2903002104200141286a290300210520012d0001210620034190076a200141246a280200360200200341f0066a41186a2001411c6a290200370300200341f0066a41106a200141146a290200370300200341f0066a41086a2001410c6a2902003703002003200141046a2902003703f0062002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241086a2d00002115200241066a2f01002116200241056a2d00002117200241046a2d00002118200241026a2f0100211941012101024020022d00000d0020022d000141014721010b200320073701e80b200320083a00e70b200320093a00e60b2003200a3b01e40b2003200b3a00e30b2003200c3a00e20b2003200d3b01e00b2003200e3a00df0b2003200f3a00de0b200320103b01dc0b200320113a00db0b200320123a00da0b200320133b01d80b200320143a00d70b200320153a00d60b200320163b01d40b200320173a00d30b200320183a00d20b200320193b01d00b0240024020010d00200341e0086a41186a200341d00b6a41186a290100370300200341e0086a41106a200341d00b6a41106a290100370300200341e0086a41086a200341d00b6a41086a290100370300200320032901d00b3703e008200341800a6a200341e0086a10b401200341206a20032802800a220220032802880a41b0b4cc0041004100108a0220032802202101024020032802840a450d00200210350b4103210220014101470d0141a1a6c0002101410d21084180800821090c260b41022102410021090c250b200341800a6a41206a200341f0066a41206a280200360200200341800a6a41186a200341f0066a41186a290300370300200341800a6a41106a200341f0066a41106a290300370300200341800a6a41086a200341f0066a41086a290300370300200320032903f0063703800a200341d0096a200341800a6a108b0220032d00d0094101460d05200341d0096a41086a2d00002101200341d9096a2f00002108200341db096a2d00002109200341dc096a2d0000210a200341dd096a2f0000210b200341df096a2d0000210c200341d0096a41106a2d0000210d200341e1096a2f0000210e200341e3096a2d0000210f200341e4096a2d00002110200341e5096a2f00002111200341e7096a2d00002112200341d0096a41186a2d0000211320032d00d109211420032d00d209211520032d00d309211620032d00d409211720032f00d509211820032d00d70921192003200341e9096a2900003703a009200320133a009f09200320123a009e09200320113b019c09200320103a009b092003200f3a009a092003200e3b0198092003200d3a0097092003200c3a0096092003200b3b0194092003200a3a009309200320093a009209200320083b019009200320013a008f09200320193a008e09200320183b018c09200320173a008b09200320163a008a09200320153a008909200320143a008809200341800a6a20034188096a10b701200341186a20032802800a220820032802880a41b0b4cc0041004100108a0220032802182101024020032802840a450d00200810350b024020014101470d004194a6c0002101410d21084180800c21090c250b02402005428080e983b1de165441002004501b450d0041d8a5c0002101411121084180801c21090c250b200341800a6a200341e0086a10b40120033502880a210720032802800a2101412010332202450d162002200329038809370000200241186a20034188096a41186a290300370000200241106a20034188096a41106a290300370000200241086a20034188096a41086a29030037000020074220862001ad842002ad4280808080800484100220021035024020032802840a450d00200110350b200341800a6a200341e0086a108c0220033502880a210720032802800a210102400240200641037122024103470d00410121024200211a410121080c010b024002400240024020020e03000102000b410021080c020b410121080c010b410221080b200320083a00f00b410110332202450d22200220083a000041002108428080808010211a0b20074220862001ad84201a2002ad841002024020080d00200210350b024020032802840a450d00200110350b200341e0086a108d0241f7edcb00ad4280808080f0008422071001220228000021012002290004211a200228000c21082002103541e4edcb00ad4280808080a0018410012202290000211b2002290008211c200210352003201c3701c8082003201b3701c008200320083601bc082003201a3701b408200320013601b008200341106a200341b0086a412010c0012003280214210120032802102108200710012202280000210920022900042107200228000c210a2002103541b5edcb00ad4280808080c0018410012202290000211a2002290008211b200210352003201b3701c8082003201a3701c0082003200a3601bc08200320073701b408200320093601b008200341086a200341b0086a412010c001200328020c210220032802082109200341d0096a200341e0086a108e02200341800a6a20032802d009220a20032802d809108f0241002001410020081b2208200241d40020091b6b2202200220084b1b2102200341800a6a41106a290300420020032903800a42015122011b210720032903880a420020011b211a024020032802d409450d00200a10350b200341800a6a41086a41053a0000200341890a6a20032903e008370000200341910a6a200341e0086a41086a2201290300370000200341990a6a200341e0086a41106a2209290300370000200341a10a6a200341e0086a41186a220a290300370000200341b80a6a220b20072004201a200554200720045420072004511b220c1b2207370300200341b00a6a201a2005200c1b2204370300200341043a00800a41b0b4cc004100200341800a6a10d40120012f0100210c20092f0100210d200a290300210520032f01e008210e20032d00e208210f20032d00e308211020032f01e408211120032d00e608211220032d00e708211320032d00ea08211420032d00eb08211520032f01ec08211620032d00ee08211720032d00ef08211820032d00f208211920032d00f308210620032f01f408211d20032d00f608211e20032d00f708211f200341003602d809200342043703d009200341d0096a41004100200820026b220a200a20084b1b10860120032802d80921090240200820024d0d0020032802d00920094102746a2101034020012002360200200141046a21012008200241016a2202470d000b200a20096a21090b200341b0086a41086a22022009360200200341d00a6a2005370300200341cf0a6a201f3a0000200341ce0a6a201e3a0000200341cc0a6a201d3b0100200341cb0a6a20063a0000200341ca0a6a20193a0000200341c80a6a200d3b0100200341c70a6a20183a0000200341c60a6a20173a0000200341c40a6a20163b0100200341c30a6a20153a0000200341c20a6a20143a0000200341c00a6a200c3b0100200341bf0a6a20133a0000200341be0a6a20123a0000200341bc0a6a20113b0100200341bb0a6a20103a0000200341ba0a6a200f3a0000200320032903d0093703b0082003200e3b01b80a200341800a6a41186a2007370300200341a80a6a4100360200200341b40a6a2002280200360200200320043703900a200320073703880a200320043703800a200342083703a00a200320032903b0083702ac0a200342f3e885db96cddbb3203703f00b200341f00b6a200b20042007411f109002200341d0096a20034188096a10b70120032802d0092102200320032802d8093602b408200320023602b008200341800a6a200341b0086a10e101024020032802d409450d00200210350b024020032802a40a2202450d00200241186c450d0020032802a00a10350b200341b00a6a28020041ffffffff0371450d2320032802ac0a10350c230b200141106a290300211b200141086a290300211c2002411a6a290100211a200241196a2d0000210c200241186a2d0000210d200241166a2f0100210e200241156a2d0000210f200241146a2d00002110200241126a2f01002111200241116a2d00002112200241106a2d00002113410e21012002410e6a2f010021142002410d6a2d000021152002410c6a2d000021162002410a6a2f01002117200241096a2d00002118200241086a2d00002119200241066a2f01002106200241056a2d0000211d200241046a2d0000211e200241026a2f0100211f20022d0001210b20022d0000210a41f7edcb00ad4280808080f0008410012202280000210820022900042107200228000c21092002103541b6aac000ad42808080809002841001220229000021042002290008210520021035200320053701c808200320043701c008200320093601bc08200320073701b408200320083601b008200341286a200341b0086a10f2014103210202402003280228417d71450d0041dca2c0002108418080ec0021090c220b02400240200a41ff01710d00200b41ff01714101470d002003201a3703880c2003200c3a00870c2003200d3a00860c2003200e3b01840c2003200f3a00830c200320103a00820c200320113b01800c200320123a00ff0b200320133a00fe0b200320143b01fc0b200320153a00fb0b200320163a00fa0b200320173b01f80b200320183a00f70b200320193a00f60b200320063b01f40b2003201d3a00f30b2003201e3a00f20b2003201f3b01f00b200341f0066a200341f00b6a10b401200341800a6a20032802f006220920032802f80610d501200341990a6a2900002107200341980a6a2d0000210a200341970a6a2d0000210b200341950a6a2f0000210c200341940a6a2d0000210d200341930a6a2d0000210e200341910a6a2f0000210f200341900a6a2d000021102003418f0a6a2d000021112003418d0a6a2f000021122003418c0a6a2d000021132003418b0a6a2d00002114200341890a6a2f0000211541082101200341800a6a41086a2d0000211620032d00870a211720032f00850a211820032d00840a211920032d00830a210620032d00820a211d20032d00810a211e20032d00800a2108024020032802f406450d00200910350b200841ff01714101460d0141aea6c00021084180800421090c230b41022102410021090c220b200320073703e8092003200a3a00e7092003200b3a00e6092003200c3b01e4092003200d3a00e3092003200e3a00e2092003200f3b01e009200320103a00df09200320113a00de09200320123b01dc09200320133a00db09200320143a00da09200320153b01d809200320163a00d709200320173a00d609200320183b01d409200320193a00d309200320063a00d2092003201d3a00d1092003201e3a00d009200341d00b6a200341d0096a10b701200341800a6a20032802d00b220120032802d80b10d601200341b0086a41086a2208200341bc0a6a290200370300200341b0086a41106a2209200341c40a6a290200370300200341b0086a41186a220a200341cc0a6a290200370300200341b0086a41206a220b200341d40a6a2802003602002003200341b40a6a2902003703b0080240024020032802a00a220c450d00200341800a6a41186a2903002105200341800a6a41086a2903002104200341b00a6a2802002102200341ac0a6a280200210d200341a80a6a280200210e20032903900a211a20032903800a210720032802a40a210f20034188096a41206a200b28020036020020034188096a41186a200a29030037030020034188096a41106a200929030037030020034188096a41086a2008290300370300200320032903b00837038809024020032802d40b450d00200110350b200341e0086a41086a220120034188096a41086a290300370300200341e0086a41106a220820034188096a41106a290300370300200341e0086a41186a220920034188096a41186a290300370300200341e0086a41206a220a20034188096a41206a280200360200200341f0066a41186a2005370300200341a0076a200236020020034198076a200e36020020034194076a200f36020020032003290388093703e0082003201a37038007200320073703f0062003200d36029c072003200c36029007200320043703f806200341c4076a200a280200360200200341bc076a2009290300370200200341b4076a2008290300370200200341ac076a2001290300370200200341a4076a20032903e008370200200341b0086a200341f00b6a108e02200341800a6a20032802b008220120032802b808108f02200341800a6a41106a290300420020032903800a42015122021b210520032903880a420020021b211a024020032802b408450d0020011035200341f0066a41086a290300210420032903f00621070b201a20077d2220201a56200520047d201a200754ad7d221a200556201a2005511b0d01200341f0066a41186a2202290300212120032003290380072222201c20202020201c56201a201b56201a201b511b22011b22057c221c3703800720022021201b201a20011b221a7c201c202254ad7c3703002003200520077c22073703f0062003201a20047c2007200554ad7c22043703f806200341800a6a41386a201a370300200341b00a6a2005370300200341800a6a41086a41053a0000200341890a6a20032903f00b370000200341910a6a200341f00b6a41086a290300370000200341990a6a200341800c6a290300370000200341a10a6a200341f00b6a41186a290300370000200341043a00800a41b0b4cc004100200341800a6a10d401200342f3e885db96cddbb3203703880920034188096a200341f0066a41386a20072004411f109002200341800a6a200341d0096a10b70120032802800a2102200320032802880a3602b408200320023602b008200341f0066a200341b0086a10e101024020032802840a450d00200210350b02402003280294072202450d00200241186c450d0020032802900710350b20032802a00741ffffffff0371450d24200328029c0710350c240b024020032802d40b450d00200110350b41b6a6c0002108410d2101410021090c220b02402003280294072202450d00200241186c450d0020032802900710350b20032802a00741ffffffff0371450d22200328029c0710350c220b200141106a290300211b200141086a290300211c2002411a6a290100211a200241196a2d0000210c200241186a2d0000210d200241166a2f0100210e200241156a2d0000210f200241146a2d00002110200241126a2f01002111200241116a2d00002112200241106a2d00002113410e21012002410e6a2f010021142002410d6a2d000021152002410c6a2d000021162002410a6a2f01002117200241096a2d00002118200241086a2d00002119200241066a2f01002106200241056a2d0000211d200241046a2d0000211e200241026a2f0100211f20022d0001210b20022d0000210a41f7edcb00ad4280808080f0008410012202280000210820022900042107200228000c21092002103541b6aac000ad42808080809002841001220229000021042002290008210520021035200320053701c808200320043701c008200320093601bc08200320073701b408200320083601b008200341386a200341b0086a10f201410321020240024002402003280238417d71450d0041dca2c0002108418090ec0021090c010b0240200a41ff01710d00200b41ff01714101470d002003201a3703e8092003200c3a00e7092003200d3a00e6092003200e3b01e4092003200f3a00e309200320103a00e209200320113b01e009200320123a00df09200320133a00de09200320143b01dc09200320153a00db09200320163a00da09200320173b01d809200320183a00d709200320193a00d609200320063b01d4092003201d3a00d3092003201e3a00d2092003201f3b01d009200341f00b6a200341d0096a10b701200341800a6a20032802f00b220b20032802f80b10d601200341b0086a41086a220c200341bc0a6a290200370300200341b0086a41106a220d200341c40a6a290200370300200341b0086a41186a220e200341cc0a6a290200370300200341b0086a41206a220f200341d40a6a2802003602002003200341b40a6a2902003703b008024020032802a00a2209450d00200341800a6a41186a2903002107200341800a6a41086a2903002105200341b00a6a280200210a200341ac0a6a2802002110200341a80a6a280200210120032903900a210420032903800a211a20032802a40a210820034188096a41206a200f28020036020020034188096a41186a200e29030037030020034188096a41106a200d29030037030020034188096a41086a200c290300370300200320032903b00837038809024020032802f40b450d00200b10350b200341e0086a41086a220b20034188096a41086a290300370300200341e0086a41106a220c20034188096a41106a290300370300200341e0086a41186a220d20034188096a41186a290300370300200341e0086a41206a220e20034188096a41206a280200360200200341f0066a41186a2007370300200341a0076a200a36020020034198076a200136020020034194076a200836020020032003290388093703e00820032004370380072003201a3703f0062003201036029c072003200936029007200320053703f806200341c4076a200e280200360200200341bc076a200d290300370200200341b4076a200c290300370200200341ac076a200b290300370200200341a4076a20032903e0083702002001411f4d0d0302402008450d00200841186c450d002009103520032802a007210a0b0240200a41ffffffff0371450d00200328029c0710350b41cca5c0002108410c21014180902021090c020b024020032802f40b450d00200b10350b41b6a6c0002108410d210141801021090c010b4102210241801021090b20004200370308200041206a20013602002000411c6a2008360200200041186a20092002723602000c240b200341f0066a41206a210202402004201c2004201c542007201b542007201b511b220a1b22052007201b200a1b221a844200510d00200341f0066a41186a42002007201a7d2004200554ad7d221b200420057d221c428080e983b1de16544100201b501b220a1b37030020034200201c200a1b3703800741f7edcb00ad4280808080f000841001220b280000210c200b290004211b200b28000c210d200b103541e4edcb00ad4280808080a001841001220b290000211c200b2900082120200b1035200320203701c8082003201c3701c0082003200d3601bc082003201b3701b4082003200c3601b008200341306a200341b0086a412010c0012007201a200a1b210720042005200a1b2104200328023441a0056a41a00520032802301b210a024020012008470d00200220084101109c01200328029807210120032802900721090b2009200141186c6a22012007370308200120043703002001200a360210200320032802980741016a36029807200342f3e885db96cddbb3203703880920034188096a200341f0066a41386a20032903f006200341f0066a41086a290300411f109002200341800a6a200341d0096a10b70120032802800a2101200320032802880a3602b408200320013602b008200341f0066a200341b0086a10e101024020032802840a450d00200110350b200341800a6a41386a2007370300200341b00a6a2004370300200341800a6a41086a41063a0000200341890a6a20032903a807370000200341910a6a200341b0076a290300370000200341990a6a200341b8076a290300370000200341a10a6a200341c0076a290300370000200341043a00800a41b0b4cc004100200341800a6a10d4010b0240200241046a2802002201450d00200141186c450d00200228020010350b20032802a00741ffffffff0371450d21200328029c0710350c210b2002411a6a290100211a200241196a2d0000210e200241186a2d0000210f200241166a2f01002110200241156a2d00002111200241146a2d00002112200241126a2f01002113200241116a2d00002114200241106a2d00002115410e21082002410e6a2f010021162002410d6a2d000021172002410c6a2d000021182002410a6a2f01002119200241096a2d0000210641082101200241086a2d0000211d200241066a2f0100211e200241056a2d0000211f200241046a2d00002123200241026a2f0100210b20022d0001210d20022d0000210c41f7edcb00ad4280808080f0008410012202280000210920022900042107200228000c210a2002103541b6aac000ad42808080809002841001220229000021042002290008210520021035200320053701c808200320043701c0082003200a3601bc08200320073701b408200320093601b008200341c8006a200341b0086a10f20141032102024002402003280248417d710d000240200c41ff01710d00200d41ff01714101470d002003201a3703880c2003200e3a00870c2003200f3a00860c200320103b01840c200320113a00830c200320123a00820c200320133b01800c200320143a00ff0b200320153a00fe0b200320163b01fc0b200320173a00fb0b200320183a00fa0b200320193b01f80b200320063a00f70b2003201d3a00f60b2003201e3b01f40b2003201f3a00f30b200320233a00f20b2003200b3a00f00b2003200b4108763a00f10b200341d0096a200341f00b6a10b701200341800a6a20032802d009220220032802d80910d601200341b0086a41086a2201200341bc0a6a290200370300200341b0086a41106a2208200341c40a6a290200370300200341b0086a41186a2209200341cc0a6a290200370300200341b0086a41206a220a200341d40a6a2802003602002003200341b40a6a2902003703b00802400240024020032802a00a220b450d00200341800a6a41186a2903002107200341800a6a41086a290300211b200341b00a6a280200210c200341ac0a6a280200210d200341a80a6a280200210e20032903900a210420032903800a211c20032802a40a210f20034188096a41206a200a28020036020020034188096a41186a200929030037030020034188096a41106a200829030037030020034188096a41086a2001290300370300200320032903b00837038809024020032802d409450d00200210350b200341e0086a41086a220220034188096a41086a290300370300200341e0086a41106a220120034188096a41106a290300370300200341e0086a41186a220820034188096a41186a290300370300200341e0086a41206a220920034188096a41206a280200360200200341f0066a41186a220a2007370300200341a0076a200c36020020034198076a200e36020020034194076a200f36020020032003290388093703e00820032004370380072003201c3703f0062003200d36029c072003200b360290072003201b3703f806200341c4076a2009280200360200200341bc076a220c2008290300370200200341b4076a220d2001290300370200200341ac076a220e2002290300370200200341a4076a20032903e008370200200341d0096a41186a200341c0076a220f290300370300200341d0096a41106a200341b8076a2210290300370300200341d0096a41086a200341b0076a2211290300370300200320032903a8073703d00941f7edcb00ad4280808080f0008410012202280000210120022900042107200228000c21082002103541e4edcb00ad4280808080a001841001220229000021042002290008210520021035200320053701c808200320043701c008200320083601bc08200320073701b408200320013601b008200341c0006a200341b0086a412010c00120032802404101460d01200a2903002120200329038007212120032802980721080c020b024020032802d409450d00200210350b41b6a6c0002109410d210841032102410821014100210a4100210b0c040b20032802442109200341b0086a41086a2003419c076a220b41086a2802003602002003200b2902003703b0082003280290072112200a2903002120200341aa076a2d00002113200341ab076a2d00002114200e2f01002115200341ae076a2d00002116200341af076a2d0000211720112f01002111200341b2076a2d00002118200341b3076a2d00002119200d2f01002106200341b6076a2d0000211d200341b7076a2d0000211e20102f01002110200341ba076a2d0000211f200341bb076a2d00002123200c2f01002124200341be076a2d00002125200341bf076a2d00002126200f2903002122200329038007212120032f01a807210f200328029407210d201c2107201b2104024002400240200328029807220e450d002012200e41186c6a210a200e41186c41686a2101201c2107201b2104201221020340200241086a290300211a200229030021052009200241106a2802002208490d0242002004201a7d2007200554ad7d221a200720057d2205200756201a200456201a2004511b22081b21044200200520081b2107200141686a2101200241186a2202200a470d000b0b4108210c410021080240200d450d00200d41186c450d00201210350b410021020c010b41181033220c450d18200c2005370300200c2008360210200c201a37030820034281808080103702840a2003200c3602800a0240024020010d00410121080c010b200241186a2127200e41186c20126a41686a21284101210803402027210202400340200241086a290300211a200229030021052009200241106a2802002201490d0142002004201a7d2007200554ad7d221a200720057d2205200756201a200456201a2004511b22011b21044200200520011b2107200241186a2202200a470d000c030b0b0240200820032802840a470d00200341800a6a20084101109c0120032802800a210c0b200241186a2127200c200841186c6a220e2001360210200e201a370308200e20053703002003200841016a22083602880a20282002470d000b0b0240200d450d00200d41186c450d00201210350b20032802840a21020b200b20032903b00837020020034188076a2020370300200b41086a200341b0086a41086a2802003602002003202137038007200320073703f006200320083602980720032002360294072003200c36029007200320223703c007200320263a00bf07200320253a00be07200320243b01bc07200320233a00bb072003201f3a00ba07200320103b01b8072003201e3a00b7072003201d3a00b607200320063b01b407200320193a00b307200320183a00b207200320113b01b007200320173a00af07200320163a00ae07200320153b01ac07200320143a00ab07200320133a00aa072003200f3b01a807200320043703f8060b024002400240024020080d002021202084500d010b200342f3e885db96cddbb3203703880920034188096a200341a8076a20032903f006200341f8066a290300411f109002200341800a6a200341f00b6a10b70120032802800a2102200320032802880a3602b408200320023602b008200341f0066a200341b0086a10e10120032802840a450d01200210350c010b200341800a6a200341d0096a10910220032d00800a22024104470d01200342f3e885db96cddbb3203703d00b200341d00b6a200341d0096a1092020b0240201c20032903f006220458201b200341f0066a41086a290300220758201b2007511b0d00200341b00a6a201c20047d370300200341800a6a41086a41073a0000200341890a6a20032903d009370000200341910a6a200341d0096a41086a290300370000200341990a6a200341e0096a290300370000200341a10a6a200341e8096a290300370000200341b80a6a201b20077d201c200454ad7d370300200341043a00800a41b0b4cc004100200341800a6a10d4010b02402003280294072202450d00200241186c450d0020032802900710350b20032802a00741ffffffff0371450d24200328029c0710350c240b20032d00830a411074210120032f00810a210820032902840a210702402003280294072209450d00200941186c450d0020032802900710350b2008200172210120074220882104024020032802a00741ffffffff0371450d00200328029c0710350b2001411076210a2001410876210b2004a721082007a721090c020b410221020b41dca2c0002109411b210b4100210a0b20004200370308200041206a20083602002000411c6a2009360200200041186a200a411874200b411074418080fc07717220014108744180fe0371722002723602000c220b2002411a6a290100211a200241196a2d0000210d200241186a2d0000210e200241166a2f0100210f200241156a2d00002110200241146a2d00002111200241126a2f01002112200241116a2d00002113200241106a2d00002114410e21082002410e6a2f010021152002410d6a2d000021162002410c6a2d000021172002410a6a2f01002118200241096a2d00002119200241086a2d00002106200241066a2f0100211d200241056a2d0000211e200241046a2d0000211f200241026a2f01002123200141046a280200210b20022d0001210c20022d0000210a41f7edcb00ad4280808080f0008410012202280000210120022900042107200228000c21092002103541b6aac000ad42808080809002841001220229000021042002290008210520021035200320053701c808200320043701c008200320093601bc08200320073701b408200320013601b008200341d0006a200341b0086a10f20141032102024002402003280250417d71450d0041dca2c0002101418090ec0021090c010b0240200a41ff01710d00200c41ff01714101470d002003201a3703e8092003200d3a00e7092003200e3a00e6092003200f3b01e409200320103a00e309200320113a00e209200320123b01e009200320133a00df09200320143a00de09200320153b01dc09200320163a00db09200320173a00da09200320183b01d809200320193a00d709200320063a00d6092003201d3b01d4092003201e3a00d3092003201f3a00d209200320233b01d009200341f00b6a200341d0096a10b701200341800a6a20032802f00b220a20032802f80b10d601200341b0086a41086a220c200341bc0a6a290200370300200341b0086a41106a220d200341c40a6a290200370300200341b0086a41186a220e200341cc0a6a290200370300200341b0086a41206a220f200341d40a6a2802003602002003200341b40a6a2902003703b008024020032802a00a2201450d00200341800a6a41186a2903002107200341800a6a41086a2903002104200341b00a6a2802002108200341ac0a6a2802002109200341a80a6a280200211020032903900a210520032903800a211a20032802a40a210220034188096a41206a200f28020036020020034188096a41186a200e29030037030020034188096a41106a200d29030037030020034188096a41086a200c290300370300200320032903b00837038809024020032802f40b450d00200a10350b200341e0086a41086a220a20034188096a41086a290300370300200341e0086a41106a220c20034188096a41106a290300370300200341e0086a41186a220d20034188096a41186a290300370300200341e0086a41206a220e20034188096a41206a280200360200200341f0066a41186a2007370300200341a0076a200836020020034198076a201036020020034194076a200236020020032003290388093703e00820032005370380072003201a3703f0062003200936029c072003200136029007200320043703f806200341c4076a200e280200360200200341bc076a200d290300370200200341b4076a200c290300370200200341ac076a200a290300370200200341a4076a20032903e008370200200341800a6a200341a8076a220a10b90120033502880a42208620032802800a220cad841007024020032802840a450d00200c10350b200341800a6a200a10b50120033502880a210720032802800a210a200341003a00b5080240024002400240200b41c000490d00200b41808001490d01200b418080808004490d02200341053a00b508200341033a00b0082003200b3600b1084280808080d00021040c030b200341013a00b5082003200b4102743a00b00842808080801021040c020b200341023a00b5082003200b4102744101723b01b00842808080802021040c010b200341043a00b5082003200b4102744102723602b0084280808080c00021040b2007422086200aad842004200341b0086aad841002024020032d00b508450d00200341003a00b5080b024020032802840a450d00200a10350b02402002450d00200241186c450d00200110350b200841ffffffff0371450d22200910350c220b024020032802f40b450d00200a10350b41b6a6c0002101410d210841801021090c010b4102210241801021090b20004200370308200041206a20083602002000411c6a2001360200200041186a20092002723602000c210b2001410c6a280200210e200141086a2802002108200141046a280200210b2002411a6a290100211a200241196a2d0000210f200241186a2d00002110200241166a2f01002111200241156a2d00002112200241146a2d00002113200241126a2f01002114200241116a2d00002115200241106a2d00002116410e21012002410e6a2f010021172002410d6a2d000021182002410c6a2d000021192002410a6a2f01002106200241096a2d0000211d200241086a2d0000211e200241066a2f0100211f200241056a2d00002123200241046a2d00002124200241026a2f0100212520022d0001210d20022d0000210c41f7edcb00ad4280808080f0008410012202280000210920022900042107200228000c210a2002103541b6aac000ad42808080809002841001220229000021042002290008210520021035200320053701c808200320043701c0082003200a3601bc08200320073701b408200320093601b008200341e0006a200341b0086a10f2014103210202402003280260417d71450d0041dca2c0002109411b210a0c170b200c41ff01710d14200d41ff01714101470d142003201a3703c8092003200f3a00c709200320103a00c609200320113b01c409200320123a00c309200320133a00c209200320143b01c009200320153a00bf09200320163a00be09200320173b01bc09200320183a00bb09200320193a00ba09200320063b01b8092003201d3a00b7092003201e3a00b6092003201f3b01b409200320233a00b309200320243a00b209200320253b01b009200341d0096a200341b0096a10b701200341800a6a20032802d009220c20032802d80910d601200341b0086a41086a220d200341bc0a6a290200370300200341b0086a41106a220f200341c40a6a290200370300200341b0086a41186a2210200341cc0a6a290200370300200341b0086a41206a2211200341d40a6a2802003602002003200341b40a6a2902003703b008024002400240024020032802a00a2209450d00200341800a6a41186a2903002107200341800a6a41086a2903002104200341b00a6a280200210a200341ac0a6a2802002112200341a80a6a280200211320032903900a210520032903800a211a20032802a40a210120034188096a41206a201128020036020020034188096a41186a201029030037030020034188096a41106a200f29030037030020034188096a41086a200d290300370300200320032903b00837038809024020032802d409450d00200c10350b200341e0086a41086a220c20034188096a41086a290300370300200341e0086a41106a220d20034188096a41106a290300370300200341e0086a41186a220f20034188096a41186a290300370300200341e0086a41206a221020034188096a41206a280200360200200341f0066a41186a2007370300200341a0076a200a36020020034198076a2013360200200341f0066a41246a200136020020032003290388093703e00820032005370380072003201a3703f0062003201236029c072003200936029007200320043703f806200341c4076a2010280200360200200341bc076a200f290300370200200341b4076a200d290300370200200341ac076a200c290300370200200341a4076a20032903e008370200200e450d190240200e41246c2202450d00200341d0096a41086a220c200b41096a290000370300200341d0096a41106a220d200b41116a290000370300200341d0096a41186a220f200b41196a290000370300200341ef096a2210200b41206a2800003600002003200b2900013703d009200b2d000022114102470d020b4100210c0c020b024020032802d409450d00200c10350b41b6a6c0002109410d21014100210a0c190b200341800a6a41096a200c290300370000200341800a6a41116a200d290300370000200341800a6a41196a200f290300370000200341800a6a41206a2010280000360000200320113a00800a200320032903d0093700810a200341b0086a200341800a6a108b0220034188096a41086a200341b0086a41096a29000037030020034188096a41106a200341b0086a41116a29000037030020034188096a41186a200341b0086a41196a290000370300200320032900b108370388094101210c20032d00b0084101470d01200341f00b6a41086a200341e0086a41086a290300370300200341f00b6a41106a200341e0086a41106a290300370300200341f00b6a41186a200341e0086a41186a290300370300200320032903e0083703f00b0b4100210e4101210f02402008450d00200841246c450d00200b10350b410021020c190b200341d00b6a41086a220c20034188096a41086a290300370300200341d00b6a41106a220d20034188096a41106a290300370300200341d00b6a41186a221020034188096a41186a290300370300200320032903880922073703f00b200320073703d00b41201033220f450d11200f20032903d00b370000200f41186a2010290300370000200f41106a200d290300370000200f41086a200c29030037000020034281808080103702c40b2003200f3602c00b02400240200b20026a200b41246a460d00200341d0096a41086a2202200b412d6a290000370300200341d0096a41106a220c200b41356a290000370300200341d0096a41186a220d200b413d6a290000370300200341ef096a2210200b41c4006a2800003600002003200b2900253703d009200b2d002422114102460d00200341800a6a41096a2002290300370000200341800a6a41116a200c290300370000200341800a6a41196a200d290300370000200341800a6a41206a2010280000360000200320113a00800a200320032903d0093700810a200341b0086a200341800a6a108b0220034188096a41086a200341b0086a41096a29000037030020034188096a41106a200341b0086a41116a29000037030020034188096a41186a200341b0086a41196a290000370300200320032900b1083703880920032d00b0084101470d01200341f00b6a41086a200341e0086a41086a290300370300200341f00b6a41106a200341e0086a41106a290300370300200341f00b6a41186a200341e0086a41186a290300370300200320032903e0083703f00b4101210c410121020c190b4100210c410121020c180b200b41c8006a210d200341f00b6a41086a222420034188096a41086a221d2903002207370300200341d00b6a41186a221420034188096a41186a221e290300370300200341d00b6a41106a221520034188096a41106a221f290300370300200341d00b6a41086a22162007370300200320032903880922073703f00b200320073703d00b200e41246c41b87f6a2113200341b0086a4101722110200341800a6a410172210e200341d0096a411f6a210641202111410221024101210c0340200341800a6a41186a22172014290300370300200341800a6a41106a22182015290300370300200341800a6a41086a22192016290300370300200320032903d00b3703800a02402002417f6a200c470d00200341c00b6a200c4101108a0120032802c00b210f0b200f20116a220c20032903800a370000200c41186a2017290300370000200c41106a2018290300370000200c41086a2019290300370000200320023602c80b4100210c20024110460d182013450d18200341d0096a41086a2217200d41096a290000370300200341d0096a41106a2218200d41116a290000370300200341d0096a41186a2219200d41196a2900003703002006200d41206a2800003600002003200d2900013703d009200d2d000022234102460d18200e20032903d009370000200e41086a2017290300370000200e41106a2018290300370000200e41186a2019290300370000200e411f6a2006280000360000200320233a00800a200341b0086a200341800a6a108b02201d201041086a290000370300201f201041106a290000370300201e201041186a2900003703002003201029000037038809024020032d00b0084101470d00200341f00b6a41086a200341e0086a41086a290300370300200341f00b6a41106a200341e0086a41106a290300370300200341f00b6a41186a200341e0086a41186a290300370300200320032903e0083703f00b4101210c0c190b200d41246a210d2024201d29030022073703002014201e2903003703002015201f29030037030020162007370300200320032903880922073703f00b200320073703d00b201141206a2111200241016a21022013415c6a211320032802c40b210c0c000b0b41012102410021090c1e0b2001410c6a280200210a200141086a2802002108200141046a2802002109200141d0016a280200210b200341f0066a200141106a41c001109d081a200341d8086a20014180026a290300370300200341d0086a200141f8016a290300370300200341c8086a200141f0016a290300370300200341b0086a41106a200141e8016a290300370300200341b0086a41086a200141e0016a2903003703002003200141d8016a2903003703b0080240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020022d00000d0020022d000141ff01714102470d002003200a360290092003200836028c092003200936028809200341800a6a200341f0066a41c001109d081a200341d0096a41286a200341b0086a41286a290300370300200341d0096a41206a200341b0086a41206a290300370300200341d0096a41186a200341b0086a41186a290300370300200341d0096a41106a200341b0086a41106a290300370300200341d0096a41086a200341b0086a41086a290300370300200320032903b0083703d00920034188096a200341800a6a4102200341d0096a200b109302220941ff0171411d460d3c41dca2c0002102410e2108418080ec0021012009411f710e1d0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d010b200341f0066a10fa012008450d1d200841ffffffff0771450d1d200910350c1d0b200341940a6a4101360200200342013702840a200341e8d4ca003602800a200341043602d409200341f0d5ca003602d0092003200341d0096a3602900a200341800a6a41b0b4cc00104c000b41b6a6c0002102410d2108410021010c1a0b41aea6c0002102410821084180800421010c190b41a1a6c0002102410d21084180800821010c180b4194a6c0002102410d21084180800c21010c170b4188a6c0002102410c21084180801021010c160b41faa5c00021024180801421010c150b41e9a5c0002102411121084180801821010c140b41d8a5c0002102411121084180801c21010c130b41cca5c0002102410c21084180802021010c120b41bfa5c0002102410d21084180802421010c110b41b3a5c0002102410c21084180802821010c100b41a1a5c0002102411221084180802c21010c0f0b4187a5c0002102411a21084180803021010c0e0b41f5a4c0002102411221084180803421010c0d0b41e7a4c00021024180803821010c0c0b41d0a4c0002102411721084180803c21010c0b0b41baa4c000210241162108418080c00021010c0a0b41a7a4c000210241132108418080c40021010c090b418fa4c000210241182108418080c80021010c080b41fca3c000210241132108418080cc0021010c070b41e8a3c000210241142108418080d00021010c060b41d2a3c000210241162108418080d40021010c050b41bba3c000210241172108418080d80021010c040b41a2a3c000210241192108418080dc0021010c030b418da3c000210241152108418080e00021010c020b41fca2c000210241112108418080e40021010c010b41eaa2c000210241122108418080e80021010b410321090c010b41022109410021010b20004200370308200041206a20083602002000411c6a2002360200200041186a2001418080fc0071200972418010723602000c1e0b2001410c6a280200210a200141086a2802002108200141046a2802002109200141d0016a280200210b200341f0066a200141106a41c001109d081a200341d8086a20014180026a290300370300200341d0086a200141f8016a290300370300200341c8086a200141f0016a290300370300200341b0086a41106a200141e8016a290300370300200341b0086a41086a200141e0016a2903003703002003200141d8016a2903003703b0080240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020022d00000d0020022d00014101470d002003200a360290092003200836028c092003200936028809200341800a6a200341f0066a41c001109d081a200341d0096a41286a200341b0086a41286a290300370300200341d0096a41206a200341b0086a41206a290300370300200341d0096a41186a200341b0086a41186a290300370300200341d0096a41106a200341b0086a41106a290300370300200341d0096a41086a200341b0086a41086a290300370300200320032903b0083703d00920034188096a200341800a6a4101200341d0096a200b109302220941ff0171411d460d3b41dca2c0002102410e2108418080ec0021012009411f710e1d0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d010b200341f0066a10fa012008450d1d200841ffffffff0771450d1d200910350c1d0b200341940a6a4101360200200342013702840a200341e8d4ca003602800a200341043602d409200341f0d5ca003602d0092003200341d0096a3602900a200341800a6a41b0b4cc00104c000b41b6a6c0002102410d2108410021010c1a0b41aea6c0002102410821084180800421010c190b41a1a6c0002102410d21084180800821010c180b4194a6c0002102410d21084180800c21010c170b4188a6c0002102410c21084180801021010c160b41faa5c00021024180801421010c150b41e9a5c0002102411121084180801821010c140b41d8a5c0002102411121084180801c21010c130b41cca5c0002102410c21084180802021010c120b41bfa5c0002102410d21084180802421010c110b41b3a5c0002102410c21084180802821010c100b41a1a5c0002102411221084180802c21010c0f0b4187a5c0002102411a21084180803021010c0e0b41f5a4c0002102411221084180803421010c0d0b41e7a4c00021024180803821010c0c0b41d0a4c0002102411721084180803c21010c0b0b41baa4c000210241162108418080c00021010c0a0b41a7a4c000210241132108418080c40021010c090b418fa4c000210241182108418080c80021010c080b41fca3c000210241132108418080cc0021010c070b41e8a3c000210241142108418080d00021010c060b41d2a3c000210241162108418080d40021010c050b41bba3c000210241172108418080d80021010c040b41a2a3c000210241192108418080dc0021010c030b418da3c000210241152108418080e00021010c020b41fca2c000210241112108418080e40021010c010b41eaa2c000210241122108418080e80021010b410321090c010b41022109410021010b20004200370308200041206a20083602002000411c6a2002360200200041186a2001418080fc0071200972418010723602000c1d0b200341f0066a41186a200141196a290000370300200341f0066a41106a200141116a290000370300200341f8066a200141096a290000370300200320012900013703f006200341d0096a200341f0066a108e02200341800a6a20032802d009220120032802d809108f02200341800a6a41106a290300420020032903800a42015122021b210720032903880a420020021b2104200341a00a6a290300420020021b2105200341800a6a41186a290300420020021b211a024020032802d409450d00200110350b024002400240427f2004201a7c221a201a2004542202200720057c2002ad7c220420075420042007511b22021b427f200420021b844200520d00200341800a6a200341f0066a10910220032d00800a22024104460d0220032f00810a20032d00830a4110747241087422094180fe037121012009418080fc077121082009418080807871210920032902840a2207422088a7210a2007a7210b0c010b41b3a5c000210b410c210a410321024180102101418080282108410021090b20004200370308200041206a200a3602002000411c6a200b360200200041186a20092008722001722002723602000c1d0b200342f3e885db96cddbb3203703b008200341b0086a200341f0066a1092020c1a0b024020022d000120022d0000410047720d00200141046a280200210841f7edcb00ad4280808080f00084221a10012202280000210120022900042107200228000c21092002103541e4edcb00ad4280808080a001841001220229000021042002290008210520021035200320053701c808200320043701c008200320093601bc08200320073701b408200320013601b008200341e8066a200341b0086a412010c00120032802e8064101470d1a20032802ec062101201a10012202280000210920022900042107200228000c210a2002103541b5edcb00ad4280808080c0018422041001220229000021052002290008211a200210352003201a3701c808200320053701c0082003200a3601bc08200320073701b408200320093601b008200341e0066a200341b0086a412010c00102404100200120032802e40641d40020032802e0061b6b2202200220014b1b22024100200120086b2209200920014b1b22014f0d000340200210c1012001200241016a2202470d000b0b41f7edcb00ad4280808080f0008410012202280000210120022900042107200228000c21092002103520041001220229000021042002290008210520021035200320053701c808200320043701c008200320093601bc08200320073701b408200320013601b008200320083602800a200341b0086aad4280808080800484200341800a6aad4280808080c0008410020c1a0b20004200370308200041186a41023602000c1b0b200141106a2903002107200141086a290300211b2002411a6a290100211c200241196a2d0000210c200241186a2d0000210d200241166a2f0100210e200241156a2d0000210f200241146a2d00002110200241126a2f01002111200241116a2d00002112200241106a2d00002113410e21012002410e6a2f010021142002410d6a2d000021152002410c6a2d000021162002410a6a2f01002117200241096a2d00002118200241086a2d00002119200241066a2f01002106200241056a2d0000211d200241046a2d0000211e200241026a2f0100211f20022d0001210b20022d0000210a41f7edcb00ad4280808080f0008410012202280000210820022900042104200228000c21092002103541b6aac000ad42808080809002841001220229000021052002290008211a200210352003201a3701c808200320053701c008200320093601bc08200320043701b408200320083601b008200341d8066a200341b0086a10f201410321020240024020032802d806417d71450d0041dca2c0002108418090ec0021090c010b02400240200a41ff01710d00200b41ff01714101470d002003201c3703880c2003200c3a00870c2003200d3a00860c2003200e3b01840c2003200f3a00830c200320103a00820c200320113b01800c200320123a00ff0b200320133a00fe0b200320143b01fc0b200320153a00fb0b200320163a00fa0b200320173b01f80b200320183a00f70b200320193a00f60b200320063b01f40b2003201d3a00f30b2003201e3a00f20b2003201f3b01f00b200341f0066a200341f00b6a10b701200341800a6a20032802f006220820032802f80610d601200341b0086a41086a220a200341bc0a6a290200370300200341b0086a41106a220b200341c40a6a290200370300200341b0086a41186a220c200341cc0a6a290200370300200341b0086a41206a220d200341d40a6a2802003602002003200341b40a6a2902003703b00820032802a00a2209450d01200341800a6a41186a290300211c200341800a6a41086a2903002129200341b00a6a280200210f200341ac0a6a2802002110200341a80a6a280200210120032903900a212020032903800a212a20032802a40a210e20034188096a41206a200d28020036020020034188096a41186a200c29030037030020034188096a41106a200b29030037030020034188096a41086a200a290300370300200320032903b00837038809024020032802f406450d00200810350b200341e0086a41106a20034188096a41106a2903002204370300200341d0096a41086a220820034188096a41086a290300370300200341d0096a41106a220a2004370300200341d0096a41186a220b20034188096a41186a290300370300200341d0096a41206a220c20034188096a41206a28020036020020032003290388093703d00902402001450d00200341f0066a41206a200c280200360200200341f0066a41186a200b290300370300200341f0066a41106a200a290300370300200341f0066a41086a2008290300370300200320032903d0093703f006200141186c20096a41686a2102420021214200212202400340024020010d00410021010c020b02402002290300220420217c2205201b58200241086a290300222b20227c2005200454ad7c221a200758201a20075122081b0d0020022004201b20217d22057d3703002002202b200720227d201b202154ad7d22077d2004200554ad7d3703082007201c7c200520207c2220200554ad7c211c0c020b2001417f6a2101202b201c7c200420207c2220200454ad7c211c200241686a210220052121201a21222005201b54201a20075420081b0d000b0b200341800a6a41186a201c370300200341b00a6a200f360200200341a80a6a2001360200200341a40a6a200e360200200341b40a6a20032903f006370200200341bc0a6a200341f8066a290300370200200341c40a6a20034180076a290300370200200341cc0a6a200341f0066a41186a290300370200200341d40a6a20034190076a280200360200200320203703900a2003202a3703800a200320103602ac0a200320093602a00a200320293703880a200342f3e885db96cddbb3203703880920034188096a200341b80a6a202a2029411f109002200341f0066a200341f00b6a10b70120032802f0062102200320032802f8063602b408200320023602b008200341800a6a200341b0086a10e101024020032802f406450d00200210350b024020032802a40a2202450d00200241186c450d0020032802a00a10350b20032802b00a41ffffffff0371450d1c20032802ac0a10350c1c0b0240200e450d00200e41186c450d00200910350b0240200f41ffffffff0371450d00201010350b41bfa5c0002108410d21014180902421090c020b4102210241801021090c010b024020032802f406450d00200810350b41b6a6c0002108410d210141801021090b20004200370308200041206a20013602002000411c6a2008360200200041186a20092002723602000c1a0b200141246a280200210a20022d0001210b20022d00002109200341c8096a200141196a290000370300200341c0096a200141116a290000370300200341b8096a200141096a290000370300200320012900013703b00941f7edcb00ad4280808080f0008410012202280000210120022900042107200228000c21082002103541b6aac000ad42808080809002841001220229000021042002290008210520021035200320053701e80b200320043701e00b200320083601dc0b200320073701d40b200320013601d00b200341d0066a200341d00b6a10f201410321020240024002400240024002400240024002400240024020032802d006417d710d0041022102200941ff01710d00200b41ff01714101470d00200341f00b6a41186a200341b0096a41186a290300370300200341f00b6a41106a200341b0096a41106a290300370300200341f00b6a41086a200341b0096a41086a290300370300200320032903b0093703f00b41f7edcb00ad4280808080f0008410012202280000210120022900042107200228000c21082002103541e4edcb00ad4280808080a001841001220229000021042002290008210520021035200320053701e80b200320043701e00b200320083601dc0b200320073701d40b200320013601d00b200341c8066a200341d00b6a412010c00141a1a5c0002101411221084180802c210920032802c806450d0220032802cc06220b200a490d0241f7edcb00ad4280808080f00084221a10012202280000210c20022900042107200228000c210d2002103541b5edcb00ad4280808080c001841001220229000021042002290008210520021035200320053701e80b200320043701e00b2003200d3601dc0b200320073701d40b2003200c3601d00b200341c0066a200341d00b6a412010c001200a4100200b20032802c40641d40020032802c0061b6b22022002200b4b1b220b490d02201a10012202280000210c20022900042107200228000c210d2002103541eeeecb00ad4280808080a001841001220229000021042002290008210520021035200320053701e80b200320043701e00b2003200d3601dc0b200320073701d40b2003200c3601d00b200341b8066a200341d00b6a412010c001024020032802b8064101470d0020032802bc06200a4b0d030b200341800a6a200a10be01200341a0066a20032802800a220c20032802880a10d701200341b0066a290300210420032903a806210720032802a0062102024020032802840a450d00200c10350b2002450d02200341f0066a200341f00b6a10b401200341800a6a20032802f006220120032802f80610d501200341990a6a2900002105200341980a6a2d00002108200341970a6a2d00002109200341950a6a2f0000210c200341940a6a2d0000210d200341930a6a2d0000210e200341910a6a2f0000210f200341900a6a2d000021102003418f0a6a2d000021112003418d0a6a2f000021122003418c0a6a2d000021132003418b0a6a2d00002114200341890a6a2f00002115200341880a6a2d0000211620032d00870a211720032f00850a211820032d00840a211920032d00830a210620032d00820a211d20032d00810a211e20032d00800a2102024020032802f406450d00200110350b200241ff01714101470d01200320053703e809200320083a00e709200320093a00e6092003200c3b01e4092003200d3a00e3092003200e3a00e2092003200f3b01e009200320103a00df09200320113a00de09200320123b01dc09200320133a00db09200320143a00da09200320153b01d809200320163a00d709200320173a00d609200320183b01d409200320193a00d309200320063a00d2092003201d3a00d1092003201e3a00d009200341e0086a200341d0096a10b701200341800a6a20032802e008220220032802e80810d601200341b0086a41086a2208200341bc0a6a290200370300200341b0086a41106a2209200341c40a6a290200370300200341b0086a41186a220c200341cc0a6a290200370300200341b0086a41206a220d200341d40a6a2802003602002003200341b40a6a2902003703b00802400240024020032802a00a220e450d00200341800a6a41186a2903002105200341800a6a41086a290300211a200341b00a6a280200210f200341ac0a6a2802002101200341a80a6a280200211020032903900a211b20032903800a211c20032802a40a211120034188096a41206a200d28020036020020034188096a41186a200c29030037030020034188096a41106a200929030037030020034188096a41086a2008290300370300200320032903b00837038809024020032802e408450d00200210350b200341f0066a41186a2005370300200341a0076a200f36020020034198076a201036020020034194076a2011360200200341a4076a2202200329038809370200200341ac076a20034190096a290300370200200341b4076a20034198096a290300370200200341bc076a20034188096a41186a290300370200200341c4076a200341a8096a2802003602002003201b370380072003201c3703f0062003200136029c072003200e360290072003201a3703f8060240200228020022090d0041002108410021020c030b41002102410021080340024002400240200b2001280200220c4b0d0020020d01410021020c020b200241016a21020c010b200820026b220d20094f0d08200120024102746b220d280200210e200d200c3602002001200e3602000b200141046a21012009200841016a2208470d000b024002402002450d0020032802a407220c200920026b2202490d01200320023602a4072002210c0c010b20032802a407210c0b200328029c0721014100210802400240200c41014b0d0041002102200c0e020401040b200c2102034020082002410176220920086a220b200a2001200b4102746a280200491b2108200220096b220241014b0d000b0b41032102200a200120084102746a2802002209470d010c0a0b024020032802e408450d00200210350b41b6a6c0002101410d210841032102410021090c0a0b200c2008200a20094b6a2208490d05200c21020b0240200220032802a007470d002003419c076a20024101108601200328029c0721010b200120084102746a220141046a2001200220086b410274109e081a2001200a3602002003200241016a3602a407200341b0086a200a200341a8076a220c10d101200341800a6a20032802b008220220032802b8081085020240024020032802a00a22160d00420021054100211541082116410021104200211a4200211c420021200c010b200341880a6a2903002120200341980a6a290300211a200341a80a6a280200211020032903800a211c20032903900a210520032802a40a21150b024020032802b408450d00200210350b200341800a6a200341d0096a10b70120032802800a2102200320032802880a3602b408200320023602b008200341f0066a200341b0086a10e101024020032802840a450d00200210350b200341d00b6a200a10940241042102200341d00b6a41047221170240024020032802d40b220d450d0020032802d00b2111200341d00b6a41086a280200210e0340200d41086a2108200d2f0106220f4105742101410021090240024003402001450d01200c2008412010a008220b450d02200141606a2101200941016a2109200841206a2108200b417f4a0d000b2009417f6a210f0b200e450d02200e417f6a210e200d200f4102746a4194036a280200210d0c010b0b200d20094102746a41e8026a2802002201450d0020114101201141014b1b2202418094ebdc036e220820022008418094ebdc036c476a22084101200841014b1b220820024b0d0720034188066a20072004428094ebdc034200109808200341f8056a200329038806220420034188066a41086a290300221b4280ec94a37c427f108408200341e8056a2004201b2002200120022001491b20086ead428094ebdc037e200220086ead8042ffffffff0f8322214200108408200341800a6a200a200341f00b6a10d30120034198066a20032802800a220120032802880a10d201200341e8056a41086a29030020032903e80522042021200720032903f8057c7e2207428094ebdc0380221ba7417f2007428080808080c0b2cd3b541b2007201b4280ec94a37c7e7c4280cab5ee01566aad7c2207200454ad7c211b200328029c0641002003280298061b2102024020032802840a450d00200110350b200341c0056a2007201b428094ebdc034200109808200341b0056a20032903c0052204200341c0056a41086a29030022214280ec94a37c427f108408200341a0056a200420212002ad2222420010840820034190056a200720032903a00522212022200720032903b0057c7e2204428094ebdc03802222a7417f2004428080808080c0b2cd3b541b200420224280ec94a37c7e7c4280cab5ee01566aad7c22047d222b201b200341a0056a41086a2903002004202154ad7c22297d2007200454ad7d428094ebdc03420010980820034180056a200329039005222120034190056a41086a29030022224280ec94a37c427f108408200341f0046a202120222005201a201c2020109502ad22054200108408200341d0056a200c20032903f004221a20047c2207202b2003290380057c222b20057e2204428094ebdc03802205a7417f2004428080808080c0b2cd3b541b200420054280ec94a37c7e7c4280cab5ee01566aad7c2204200341f0046a41086a29030020297c2007201a54ad7c2004200754ad7c109602200341d0056a41106a290300210720032903d805210420032903d0052205a74101470d01200341b0076a2903002105200341b8076a290300211a200341c0076a290300211b20032903a8072129200341b80a6a2007370300200341b00a6a2004370300200341a10a6a201b370000200341990a6a201a370000200341910a6a2005370000200341890a6a2029370000200341800a6a41086a220241013a0000200341043a00800a41b0b4cc004100200341800a6a10d40120034188096a41186a220a420037030020034188096a41106a2208420037030020034188096a41086a22014200370300200342003703880941b6fdc600ad4280808080800184220510012209290000211a2002200941086a2900003703002003201a3703800a2009103520012002290300370300200320032903800a3703880941e489c200ad4280808080d00184221a10012209290000211b2002200941086a2900003703002003201b3703800a20091035200820032903800a221b370300200341e0086a41086a220b2001290300370300200341e0086a41106a220c201b370300200341e0086a41186a220d200229030037030020032003290388093703e008200341c0046a200341e0086a412010d701200341c0046a41106a290300211b20032903c804212920032802c0042109200a42003703002008420037030020014200370300200342003703880920051001220a29000021052002200a41086a290000370300200320053703800a200a103520012002290300370300200320032903800a37038809201a1001220a29000021052002200a41086a290000370300200320053703800a200a1035200820032903800a2205370300200b2001290300370300200c2005370300200d200229030037030020032003290388093703e0082003427f201b420020091b220520077c2029420020091b220720047c22042007542202ad7c22072002200720055420072005511b22021b3703880a2003427f200420021b3703800a200341e0086aad4280808080800484200341800a6aad428080808080028410020c080b201710b1012015450d08201541306c450d08201610350c080b20054201520d0620034188096a41186a220a420037030020034188096a41106a2208420037030020034188096a41086a22014200370300200342003703880941b6fdc600ad4280808080800184220510012209290000211a200341800a6a41086a2202200941086a2900003703002003201a3703800a2009103520012002290300370300200320032903800a3703880941e489c200ad4280808080d00184221a10012209290000211b2002200941086a2900003703002003201b3703800a20091035200820032903800a221b370300200341e0086a41086a220b2001290300370300200341e0086a41106a220c201b370300200341e0086a41186a220d200229030037030020032003290388093703e008200341d8046a200341e0086a412010d701200341d8046a41106a290300211b20032903e004212920032802d8042109200a42003703002008420037030020014200370300200342003703880920051001220a29000021052002200a41086a290000370300200320053703800a200a103520012002290300370300200320032903800a37038809201a1001220a29000021052002200a41086a290000370300200320053703800a200a1035200820032903800a2205370300200b2001290300370300200c2005370300200d200229030037030020032003290388093703e0082003427f201b420020091b220520077c2029420020091b220720047c22042007542202ad7c22072002200720055420072005511b22021b3703880a2003427f200420021b3703800a200341e0086aad4280808080800484200341800a6aad428080808080028410020c060b41dca2c0002101410e2108418080ec0021090c080b41aea6c0002101410821084180800421090b410321020c060b200d200941f485cc001042000b2008200c104d000b4190edc40041194180efc400103f000b0240201041306c2202450d00201620026a210f201641286a2102200341800a6aad4280808080800284212a200341e0086aad4280808080800484212c20034188096a41106a2101200341890a6a210b200341b80a6a2114034020034198046a20212022200241586a2208290300200841086a290300201c2020109502ad22074200108408200341a8046a200241686a220a20032903980422042007202b7e2207428094ebdc03802205a7417f2007428080808080c0b2cd3b541b200720054280ec94a37c7e7c4280cab5ee01566aad7c220720034198046a41086a2903002007200454ad7c109602200341a8046a41106a290300210720032903b004210402400240024020032903a8042205a74101470d00200241786a2900002105200a290000211a2002290000211b2003200241706a29000022293701b8082003201a3701b008200320053701c0082003201b3701c808200b201a370000200b41086a2029370000200b41106a2005370000200b41186a201b370000200320043703b00a20142007370300200341013a00880a200341043a00800a41b0b4cc004100200341800a6a10d40120034188096a41186a220c42003703002001420037030020034188096a41086a22094200370300200342003703880941b6fdc600ad428080808080018422051001220d290000211a200341800a6a41086a2208200d41086a2900003703002003201a3703800a200d103520092008290300370300200320032903800a3703880941e489c200ad4280808080d00184221a1001220d290000211b2008200d41086a2900003703002003201b3703800a200d1035200120032903800a370000200141086a22102008290300370000200341e0086a41086a22112009290300370300200341e0086a41106a22122001290300370300200341e0086a41186a2213200c29030037030020032003290388093703e008200341e8036a200341e0086a412010d701200341e8036a41106a290300211b20032903f003212920032802e803210d200c42003703002001420037030020094200370300200342003703880920051001220e29000021052008200e41086a290000370300200320053703800a200e103520092008290300370300200320032903800a37038809201a1001220e29000021052008200e41086a290000370300200320053703800a200e1035200120032903800a3700002010200829030037000020112009290300370300201220012903003703002013200c29030037030020032003290388093703e0082003427f201b4200200d1b220520077c20294200200d1b220720047c22042007542208ad7c22072008200720055420072005511b22081b3703880a2003427f200420081b3703800a0c010b20054201520d0120034188096a41186a220c42003703002001420037030020034188096a41086a22094200370300200342003703880941b6fdc600ad428080808080018422051001220d290000211a200341800a6a41086a2208200d41086a2900003703002003201a3703800a200d103520092008290300370300200320032903800a3703880941e489c200ad4280808080d00184221a1001220d290000211b2008200d41086a2900003703002003201b3703800a200d1035200120032903800a370000200141086a22102008290300370000200341e0086a41086a22112009290300370300200341e0086a41106a22122001290300370300200341e0086a41186a2213200c29030037030020032003290388093703e00820034180046a200341e0086a412010d70120034180046a41106a290300211b2003290388042129200328028004210d200c42003703002001420037030020094200370300200342003703880920051001220e29000021052008200e41086a290000370300200320053703800a200e103520092008290300370300200320032903800a37038809201a1001220e29000021052008200e41086a290000370300200320053703800a200e1035200120032903800a3700002010200829030037000020112009290300370300201220012903003703002013200c29030037030020032003290388093703e0082003427f201b4200200d1b220520077c20294200200d1b220720047c22042007542208ad7c22072008200720055420072005511b22081b3703880a2003427f200420081b3703800a0b202c202a10020b200241306a2102200a41206a200f470d000b0b201710b10102402015450d00201541306c450d00201610350b02402003280294072202450d00200241186c450d0020032802900710350b024020032802a00741ffffffff0371450d00200328029c0710350b420021070c030b02402003280294072201450d00200141186c450d0020032802900710350b41e7a4c0002101410e210841808038210920032802a00741ffffffff0371450d00200328029c0710350b4200210720024104460d010b200041206a20083602002000411c6a2001360200200041186a2009418080fc007120027241801072360200420121070b200042003703080c1a0b4102210802400240024002400240024002400240024002400240024020022d00000d0020022d00014101470d00200141046a28020021082002411a6a2901002107200241196a2d00002109200241186a2d0000210a200241166a2f0100210b200241156a2d0000210c200241146a2d0000210d200241126a2f0100210e200241116a2d0000210f200241106a2d000021102002410e6a2f010021112002410d6a2d000021122002410c6a2d000021132002410a6a2f01002114200241086a2d00002115200241066a2f01002116200241056a2d00002117200241046a2d00002118200241026a2f010021012003200241096a2d00003a00d70b200320153a00d60b200320163b01d40b200320173a00d30b200320183a00d20b200320013a00d00b200320014108763a00d10b2003200f3a00df0b200320103a00de0b200320113b01dc0b200320123a00db0b200320133a00da0b200320143b01d80b200320093a00e70b2003200a3a00e60b2003200b3b01e40b2003200c3a00e30b2003200d3a00e20b2003200e3b01e00b200320073701e80b200341e8096a2007370300200341e0096a20032901e00b370300200341d0096a41086a20032901d80b370300200320032901d00b3703d00941f7edcb00ad4280808080f0008410012202280000210120022900042107200228000c21092002103541eeeecb00ad4280808080a001841001220229000021042002290008210520021035200320053701c808200320043701c008200320093601bc08200320073701b408200320013601b008200341e0036a200341b0086a412010c00141a1a5c0002102411221094180802c210120032802e003450d0420032802e40320084d0d0441f7edcb00ad4280808080f000841001220a280000210b200a2900042107200a28000c210c200a103541e4edcb00ad4280808080a001841001220a2900002104200a2900082105200a1035200320053701c808200320043701c0082003200c3601bc08200320073701b4082003200b3601b008200341d8036a200341b0086a412010c00120032802d803450d0420032802dc03220b2008490d0441f7edcb00ad4280808080f000841001220a280000210c200a2900042107200a28000c210d200a103541b5edcb00ad4280808080c001841001220a2900002104200a2900082105200a1035200320053701c808200320043701c0082003200d3601bc08200320073701b4082003200c3601b008200341d0036a200341b0086a412010c0014100200b20032802d40341d40020032802d0031b6b220a200a200b4b1b220a20084b0d04200341800a6a200810be01200341b8036a20032802800a220c20032802880a10d701200341c8036a290300210420032903c003210720032802b803210b024020032802840a450d00200c10350b200b450d04200341e0086a200341d0096a10b701200341800a6a20032802e008220220032802e80810d601200341b0086a41086a2201200341bc0a6a290200370300200341b0086a41106a2209200341c40a6a290200370300200341b0086a41186a220b200341cc0a6a290200370300200341b0086a41206a220c200341d40a6a2802003602002003200341b40a6a2902003703b0080240024020032802a00a220d450d00200341800a6a41186a2903002105200341800a6a41086a290300211a200341b00a6a280200210e200341ac0a6a280200210f200341a80a6a280200211020032903900a211b20032903800a211c20032802a40a211120034188096a41206a200c28020036020020034188096a41186a200b29030037030020034188096a41106a200929030037030020034188096a41086a2001290300370300200320032903b00837038809024020032802e408450d00200210350b200341f0066a41186a2005370300200341a0076a200e36020020034198076a201036020020034194076a2011360200200341a4076a200329038809370200200341ac076a20034190096a290300370200200341b4076a20034198096a290300370200200341bc076a20034188096a41186a290300370200200341c4076a200341a8096a2802003602002003201b370380072003201c3703f0062003200f36029c072003200d360290072003201a3703f80641f7edcb00ad4280808080f0008410012202280000210120022900042105200228000c21092002103541b6aac000ad428080808090028410012202290000211a2002290008211b200210352003201b3701c8082003201a3701c008200320093601bc08200320053701b408200320013601b008200341b0036a200341b0086a10f20120032802b003417d71450d01200341800a6a200341a8076a108c0220032802800a220220032802880a10970241ff01712109024020032802840a450d00200210350b200941034b0d0141dca2c0002102418080ec00210120090e0405010105050b024020032802e408450d00200210350b41b6a6c0002102410d210941002101410321080c080b200328029c072102024020032802a407220b0d0041002101410021090c070b41002101410021090340024002400240200a2002280200220c4b0d0020010d01410021010c020b200141016a21010c010b200920016b220d200b4f0d03200220014102746b220d280200210e200d200c3602002002200e3602000b200241046a2102200b200941016a2209470d000b024002402001450d0020032802a407220c200b20016b2202490d01200320023602a4072002210c0c010b20032802a407210c0b200328029c072102410021010240200c41014b0d0041002109200c0e020703070b200c2109034020012009410176220a20016a220b20082002200b4102746a280200491b21012009200a6b220941014b0d000c030b0b410021010c060b200d200b41f485cc001042000b2008200220014102746a2802002209470d0241e7a4c00021024180803821010b02402003280294072208450d00200841186c450d0020032802900710350b024020032802a00741ffffffff0371450d00200328029c0710350b410e21090b410321080c020b200c2001200820094b6a2201490d02200c21090b0240200920032802a007470d002003419c076a20094101108601200328029c0721020b200220014102746a220241046a2002200920016b410274109e081a200220083602002003200941016a3602a407200341800a6a200341d0096a10b70120032802800a2102200320032802880a3602b408200320023602b008200341f0066a200341b0086a10e101024020032802840a450d00200210350b200341b0086a2008109402200341800a6a2008200341a8076a220a10d301200341a8036a20032802800a220220032802880a10d20120032802a803210f20032802ac032110024020032802840a450d00200210350b20034188096a2008200a10d101200341800a6a20032802880922022003280290091085020240024020032802a00a22120d0042002105410821124100210e4200211a4200211b4200211c0c010b200341880a6a290300211a200341980a6a290300211c20032903800a210520032903900a211b20032802a40a210e0b0240200328028c09450d00200210350b201b201c2005201a10950221110240024020032802b408220b0d00410021010c010b200341b0086a41086a280200210c0340200b41086a2101200b2f0106220d4105742102410021080240024003402002450d01200a2001412010a0082209450d02200241606a2102200841016a2108200141206a21012009417f4a0d000b2008417f6a210d0b0240200c0d00410021010c030b200c417f6a210c200b200d4102746a4194036a280200210b0c010b0b200b20084102746a41e8026a28020021010b20032802b00822024101200241014b1b2202418094ebdc036e220820022008418094ebdc036c476a22084101200841014b1b220820024b0d0220034180036a20072004428094ebdc034200109808200341f0026a200329038003220420034180036a41086a29030022054280ec94a37c427f1084082003418094ebdc033602840a20032011ad4100418094ebdc0320104100200f1b22096b220b200b418094ebdc034b1bad7e428094ebdc0380a7220b3602800a200341800a6a200b418094ebdc034b4102746a280200210b2003418094ebdc033602840a2003417f2009200b6a220b200b2009491b22093602800a200341800a6a2009418094ebdc034b4102746a350200211a2003418094ebdc033602840a2003201a2002200120022001491b20086ead428094ebdc037e200220086ead8042ffffffff0f837e428094ebdc0380a722023602800a200341e0026a20042005200341800a6a2002418094ebdc034b4102746a350200221a420010840820034190036a200a20032903e0022204201a200720032903f0027c7e2207428094ebdc03802205a7417f2007428080808080c0b2cd3b541b200720054280ec94a37c7e7c4280cab5ee01566aad7c2207200341e0026a41086a2903002007200454ad7c10960220034190036a41106a2903002107200329039803210402402003290390032205a74101470d0020032903d009210520032903d809211a20032903e009211b20032903e809211c200341b80a6a2007370300200341b00a6a2004370300200341a10a6a201c370000200341990a6a201b370000200341910a6a201a370000200341890a6a2005370000200341800a6a41086a220241013a0000200341043a00800a41b0b4cc004100200341800a6a10d40120034188096a41186a220a420037030020034188096a41106a2208420037030020034188096a41086a22014200370300200342003703880941b6fdc600ad4280808080800184220510012209290000211a2002200941086a2900003703002003201a3703800a2009103520012002290300370300200320032903800a3703880941e489c200ad4280808080d00184221a10012209290000211b2002200941086a2900003703002003201b3703800a20091035200820032903800a221b370300200341e0086a41086a220b2001290300370300200341e0086a41106a220c201b370300200341e0086a41186a220d200229030037030020032003290388093703e008200341b0026a200341e0086a412010d701200341b0026a41106a290300211b20032903b802211c20032802b0022109200a42003703002008420037030020014200370300200342003703880920051001220a29000021052002200a41086a290000370300200320053703800a200a103520012002290300370300200320032903800a37038809201a1001220a29000021052002200a41086a290000370300200320053703800a200a1035200820032903800a2205370300200b2001290300370300200c2005370300200d200229030037030020032003290388093703e0082003427f201b420020091b220520077c201c420020091b220720047c22042007542202ad7c22072002200720055420072005511b22021b3703880a2003427f200420021b3703800a200341e0086aad4280808080800484200341800a6aad428080808080028410020c040b20054201520d0320034188096a41186a220a420037030020034188096a41106a2208420037030020034188096a41086a22014200370300200342003703880941b6fdc600ad4280808080800184220510012209290000211a200341800a6a41086a2202200941086a2900003703002003201a3703800a2009103520012002290300370300200320032903800a3703880941e489c200ad4280808080d00184221a10012209290000211b2002200941086a2900003703002003201b3703800a20091035200820032903800a221b370300200341e0086a41086a220b2001290300370300200341e0086a41106a220c201b370300200341e0086a41186a220d200229030037030020032003290388093703e008200341c8026a200341e0086a412010d701200341c8026a41106a290300211b20032903d002211c20032802c8022109200a42003703002008420037030020014200370300200342003703880920051001220a29000021052002200a41086a290000370300200320053703800a200a103520012002290300370300200320032903800a37038809201a1001220a29000021052002200a41086a290000370300200320053703800a200a1035200820032903800a2205370300200b2001290300370300200c2005370300200d200229030037030020032003290388093703e0082003427f201b420020091b220520077c201c420020091b220720047c22042007542202ad7c22072002200720055420072005511b22021b3703880a2003427f200420021b3703800a200341e0086aad4280808080800484200341800a6aad428080808080028410020c030b200041206a20093602002000411c6a2002360200200041186a2001418080fc007120087241801072360200420121070c030b2001200c104d000b4190edc40041194180efc400103f000b200341b0086a41047221020240200e450d00200e41306c450d00201210350b200210b10102402003280294072202450d00200241186c450d0020032802900710350b024020032802a00741ffffffff0371450d00200328029c0710350b420021070b200042003703080c190b2001410c6a2802002108200141086a280200210b41022109024002400240024002400240024002400240024002400240024020022d00000d0020022d00014101470d00200141106a280200210c200141046a28020021092002411a6a2901002107200241196a2d0000210a200241186a2d0000210d200241166a2f0100210e200241156a2d0000210f200241146a2d00002110200241126a2f01002111200241116a2d00002112200241106a2d000021132002410e6a2f010021142002410d6a2d000021152002410c6a2d000021162002410a6a2f01002117200241086a2d00002118200241066a2f01002119200241056a2d00002106200241046a2d0000211d200241026a2f010021012003200241096a2d00003a00d70b200320183a00d60b200320193b01d40b200320063a00d30b2003201d3a00d20b200320013a00d00b200320014108763a00d10b200320123a00df0b200320133a00de0b200320143b01dc0b200320153a00db0b200320163a00da0b200320173b01d80b2003200a3a00e70b2003200d3a00e60b2003200e3b01e40b2003200f3a00e30b200320103a00e20b200320113b01e00b200320073701e80b200341880c6a2007370300200341f00b6a41106a20032901e00b370300200341f00b6a41086a20032901d80b370300200320032901d00b3703f00b0240200c41104d0d004187a5c0002102411a210a410c21010c0b0b41f7edcb00ad4280808080f0008410012202280000210120022900042107200228000c210a2002103541eeeecb00ad4280808080a001841001220229000021042002290008210520021035200320053701c808200320043701c0082003200a3601bc08200320073701b408200320013601b008200341a8026a200341b0086a412010c00141a1a5c00021024112210a410b210120032802a802450d0a200920032802ac024f0d0a41f7edcb00ad4280808080f000841001220d280000210e200d2900042107200d28000c210f200d103541e4edcb00ad4280808080a001841001220d2900002104200d2900082105200d1035200320053701c808200320043701c0082003200f3601bc08200320073701b4082003200e3601b008200341a0026a200341b0086a412010c00120032802a002450d0a200920032802a402220e4b0d0a41f7edcb00ad4280808080f000841001220d280000210f200d2900042107200d28000c2110200d103541b5edcb00ad4280808080c001841001220d2900002104200d2900082105200d1035200320053701c808200320043701c008200320103601bc08200320073701b4082003200f3601b00820034198026a200341b0086a412010c00120094100200e200328029c0241d4002003280298021b6b220d200d200e4b1b220d490d0a200341800a6a200910be0120034180026a20032802800a220f20032802880a10d70120034190026a290300211a2003290388022105200328028002210e024020032802840a450d00200f10350b200e450d0a200341d0096a200341f00b6a10b701200341800a6a20032802d009220220032802d80910d601200341b0086a41086a2201200341bc0a6a290200370300200341b0086a41106a220a200341c40a6a290200370300200341b0086a41186a220e200341cc0a6a290200370300200341b0086a41206a220f200341d40a6a2802003602002003200341b40a6a2902003703b0080240024020032802a00a2210450d00200341800a6a41186a2903002107200341800a6a41086a2903002104200341b00a6a2802002111200341ac0a6a2802002112200341a80a6a280200211320032903900a211b20032903800a211c20032802a40a211420034188096a41206a200f28020036020020034188096a41186a200e29030037030020034188096a41106a200a29030037030020034188096a41086a2001290300370300200320032903b00837038809024020032802d409450d00200210350b200341f0066a41186a2007370300200341a0076a201136020020034198076a201336020020034194076a2014360200200341a4076a200329038809370200200341ac076a20034190096a290300370200200341b4076a20034198096a290300370200200341bc076a20034188096a41186a290300370200200341c4076a200341a8096a2802003602002003201b370380072003201c3703f0062003201236029c072003201036029007200320043703f80641f7edcb00ad4280808080f0008410012202280000210120022900042107200228000c210a2002103541b6aac000ad42808080809002841001220229000021042002290008211b200210352003201b3701c808200320043701c0082003200a3601bc08200320073701b408200320013601b008200341f8016a200341b0086a10f20120032802f801417d71450d01200341800a6a200341a8076a108c0220032802800a220220032802880a10970241ff0171210a024020032802840a450d00200210350b200a41034b0d0141dca2c0002102411b2101200a0e0406010106060b024020032802d409450d00200210350b41b6a6c0002102410d210a410021010c0b0b200328029c072102024020032802a407220e0d00410021014100210a0c070b410021014100210a0340024002400240200d2002280200220f4b0d0020010d01410021010c020b200141016a21010c010b200a20016b2210200e4f0d03200220014102746b221028020021112010200f360200200220113602000b200241046a2102200e200a41016a220a470d000b024002402001450d0020032802a407220f200e20016b2202490d01200320023602a4072002210f0c010b20032802a407210f0b200328029c072102410021010240200f41014b0d004100210a200f0e020704070b200f210a03402001200a410176220d20016a220e20092002200e4102746a280200491b2101200a200d6b220a41014b0d000c040b0b2008450d01200841246c450d01200b10350c0a0b2010200e41f485cc001042000b0c080b2009200220014102746a280200220a470d0141e7a4c0002102410e21010b02402003280294072209450d00200941186c450d0020032802900710350b024020032802a00741ffffffff0371450d00200328029c0710350b410e210a0c050b200f20012009200a4b6a2201490d01200f210a0b0240200a20032802a007470d002003419c076a200a4101108601200328029c0721020b200220014102746a220241046a2002200a20016b410274109e081a200220093602002003200a41016a3602a407200341800a6a200341f00b6a10b70120032802800a2102200320032802880a3602d409200320023602d009200341f0066a200341d0096a10e101024020032802840a450d00200210350b200341b0086a20091094020240200c41246c22020d00410021150c030b200b20026a2213415c6a2118200341a8076a2110200b2101410021150340200121020340200241206a2802002101200341d0096a41186a200241186a290000370300200341d0096a41106a200241106a290000370300200341d0096a41086a200241086a290000370300200320022900003703d009200341800a6a2009200341d0096a10d301200341f0016a20032802800a220a20032802880a10d20120032802f001211120032802f4012112024020032802840a450d00200a10350b20034188096a2009200341d0096a10d101200341800a6a200328028809220e2003280290091085020240024020032802a00a220c0d00420021074100210d4108210c4100210a420021040c010b200341800a6a41086a290300210420032903800a210720032802a40a210d20032802a80a210a0b0240200328028c09450d00200e10350b02400240200a20014d0d00200c200141306c6a2201450d0002402010200141106a220a460d00200a2010412010a0080d020b2001290300200141086a2903002007200410950221190240024020032802b40822140d004100210a0c010b20032802b80821160340201441086a210a20142f0106221741057421014100210e0240024003402001450d01200341d0096a200a412010a008220f450d02200141606a2101200e41016a210e200a41206a210a200f417f4a0d000b200e417f6a21170b024020160d004100210a0c030b2016417f6a2116201420174102746a4194036a28020021140c010b0b2014200e4102746a41e8026a280200210a0b20032802b00822014101200141014b1b2201418094ebdc036e220e2001200e418094ebdc036c476a220e4101200e41014b1b220e20014b0d052003418094ebdc033602840a20032001200a2001200a491b200e6ead428094ebdc037e2001200e6ead8042ffffffff0f834100418094ebdc032012410020111b6b22012001418094ebdc034b1bad7e428094ebdc0380a722013602800a200341800a6a2001418094ebdc034b4102746a35020021072003418094ebdc033602840a200320072019ad7e428094ebdc0380a722013602800a200341800a6a2001418094ebdc034b4102746a28020021012003418094ebdc033602840a2003417f201520016a220120012015491b22013602800a200341800a6a2001418094ebdc034b4102746a28020021150b0240200d450d00200d41306c450d00200c10350b200241246a210120182002460d050c020b200241246a21020240200d450d00200d41306c450d00200c10350b20132002460d040c000b0b0b2001200f104d000b4190edc40041194180efc400103f000b02402008450d00200841246c450d00200b10350b200341c8016a2005201a428094ebdc034200109808200341b8016a20032903c8012207200341c8016a41086a29030022044280ec94a37c427f108408200341a8016a200720042015ad221a4200108408200341d8016a200341f0066a41386a20032903a8012204201a200520032903b8017c7e2207428094ebdc03802205a7417f2007428080808080c0b2cd3b541b200720054280ec94a37c7e7c4280cab5ee01566aad7c2207200341a8016a41086a2903002007200454ad7c109602200341d8016a41106a290300210720032903e00121040240024020032903d8012205a74101470d0020032903f00b210520032903f80b211a20032903800c211b20032903880c211c200341800a6a41386a2007370300200341b00a6a2004370300200341a10a6a201c370000200341990a6a201b370000200341910a6a201a370000200341890a6a2005370000200341800a6a41086a220241013a0000200341043a00800a41b0b4cc004100200341800a6a10d40120034188096a41186a220a420037030020034188096a41106a2208420037030020034188096a41086a22014200370300200342003703880941b6fdc600ad4280808080800184220510012209290000211a2002200941086a2900003703002003201a3703800a2009103520012002290300370300200320032903800a3703880941e489c200ad4280808080d00184221a10012209290000211b2002200941086a2900003703002003201b3703800a20091035200820032903800a221b370300200341e0086a41086a220b2001290300370300200341e0086a41106a220c201b370300200341e0086a41186a220d200229030037030020032003290388093703e008200341f8006a200341e0086a412010d701200341f8006a41106a290300211b200329038001211c20032802782109200a42003703002008420037030020014200370300200342003703880920051001220a29000021052002200a41086a290000370300200320053703800a200a103520012002290300370300200320032903800a37038809201a1001220a29000021052002200a41086a290000370300200320053703800a200a1035200820032903800a2205370300200b2001290300370300200c2005370300200d200229030037030020032003290388093703e0082003427f201b420020091b220520077c201c420020091b220720047c22042007542202ad7c22072002200720055420072005511b22021b3703880a2003427f200420021b3703800a200341e0086aad4280808080800484200341800a6aad428080808080028410020c010b20054201520d0020034188096a41186a220a420037030020034188096a41106a2208420037030020034188096a41086a22014200370300200342003703880941b6fdc600ad4280808080800184220510012209290000211a200341800a6a41086a2202200941086a2900003703002003201a3703800a2009103520012002290300370300200320032903800a3703880941e489c200ad4280808080d00184221a10012209290000211b2002200941086a2900003703002003201b3703800a20091035200820032903800a221b370300200341e0086a41086a220b2001290300370300200341e0086a41106a220c201b370300200341e0086a41186a220d200229030037030020032003290388093703e00820034190016a200341e0086a412010d70120034190016a41106a290300211b200329039801211c2003280290012109200a42003703002008420037030020014200370300200342003703880920051001220a29000021052002200a41086a290000370300200320053703800a200a103520012002290300370300200320032903800a37038809201a1001220a29000021052002200a41086a290000370300200320053703800a200a1035200820032903800a2205370300200b2001290300370300200c2005370300200d200229030037030020032003290388093703e0082003427f201b420020091b220520077c201c420020091b220720047c22042007542202ad7c22072002200720055420072005511b22021b3703880a2003427f200420021b3703800a200341e0086aad4280808080800484200341800a6aad428080808080028410020b200341b0086a41047210b10102402003280294072202450d00200241186c450d0020032802900710350b024020032802a00741ffffffff0371450d00200328029c0710350b420021070c020b02402008450d00200841246c450d00200b10350b410321090b200041206a200a3602002000411c6a2002360200200041186a200141ff017141107420097241801072360200420121070b200042003703080c180b4102210a200241036a2d0000210820022f00012109200141106a280200210b2001410c6a2802002113200141086a2802002112200141046a280200211402400240024020022d0000220c417f6a220141024b0d00024020010e03000102000b200241046a2d00000d00200241086a2802004102742002410c6a28020041036c4f0d010b2009200841107472200c4100477241ff0171450d0041801021020c010b4103210a0240200b0d004188a6c0002108410c21014180901021020c010b200b41016a210120122102024003402001417f6a22014102490d01200241046a210820022802002109200241046a210220092008280200490d000b41f5a4c0002108411221014180903421020c010b200341800a6a201410dc01200341f0066a20032802800a220120032802880a10dd0120032902f406420020032802f00622021b2107024020032802840a450d00200110350b2002410820021b211102400240200b410274220b20126a417c6a2802002007422088a722024f0d0041002101417f210820122109034020012009280200220c6a22022007422088a7220d4f0d022011200241d8006c6a220228022c210f20022802202110200241306a280200210e200241246a280200210a2002200241d8006a2008200d6a200c6b41d8006c109e081a0240200a450d00200a41306c450d00201010350b0240200e41ffffff3f71450d00200f10350b200941046a210920074280808080707c2107200841016a21082001417f6a2101200b417c6a220b0d000b0240201341ffffffff0371450d00201210350b200341f0066a201410dc0120032802f006210220033502f8062104200341800a6a20112007422088a7220110ea0120044220862002ad8420033502880a42208620032802800a2208ad841002024020032802840a450d00200810350b024020032802f406450d00200210350b02402001450d00201141306a21022007422088a741d8006c210103400240200241746a2802002208450d00200841306c450d00200241706a28020010350b0240200228020041ffffff3f71450d002002417c6a28020010350b200241d8006a2102200141a87f6a22010d000b0b2007a72202450d17200241d8006c450d17201110350c170b02402002450d00200241d8006c2101201141306a210203400240200241746a2802002208450d00200841306c450d00200241706a28020010350b0240200228020041ffffff3f71450d002002417c6a28020010350b200241d8006a2102200141a87f6a22010d000b0b41e9a5c0002108411121014180901821022007a72209450d01200941d8006c450d01201110350c010b2002200d104e000b0240201341ffffffff0371450d00201210350b20004200370308200041206a20013602002000411c6a2008360200200041186a2002200a723602000c160b024020022d000120022d0000410047720d0041f7edcb00ad4280808080f0008410012202280000210120022900042107200228000c2108200210354193eecb00ad42808080808001841001220229000021042002290008210520021035200320053701c808200320043701c008200320083601bc08200320073701b408200320013601b008200341033a00f00b410110332202450d12200220032d00f00b3a0000200341b0086aad42808080808004842002ad428080808010841002200210350c140b20004200370308200041186a41023602000c150b200341980a6a200141196a290000370300200341800a6a41106a200141116a290000370300200341880a6a200141096a290000370300200320012900013703800a4100210102400240024020022d000120022d0000410047720d00200341f0066a200341800a6a10910220032d00f00622024104460d0220032902f406210720032f00f10620032d00f3064110747241087421010c010b410221020b200042003703082000411c6a2007370200200041186a20012002723602000c150b200342f3e885db96cddbb3203703d009200341d0096a200341800a6a1092020c120b200141086a2802002108200141046a2802002109024020022d000120022d0000410047720d002001410c6a280200210141f7edcb00ad4280808080f0008410012202280000210a20022900042107200228000c210b200210354194c4c100ad4280808080d001841001220229000021042002290008210520021035200320053701c808200320043701c0082003200b3601bc08200320073701b4082003200a3601b008200341203602840a2003200341b0086a3602800a20092001200341800a6a109802200841ffffff3f71450d12200910350c120b0240200841ffffff3f71450d00200910350b20004200370308200041186a41023602000c130b024020022d000120022d0000410047720d0041f7edcb00ad4280808080f0008410012202280000210120022900042107200228000c2108200210354193eecb00ad42808080808001841001220229000021042002290008210520021035200320053701c808200320043701c008200320083601bc08200320073701b408200320013601b008200341013a00f00b410110332202450d0f200220032d00f00b3a0000200341b0086aad42808080808004842002ad428080808010841002200210350c110b20004200370308200041186a41023602000c120b024020022d000120022d0000410047720d0041f7edcb00ad4280808080f0008410012202280000210120022900042107200228000c2108200210354193eecb00ad42808080808001841001220229000021042002290008210520021035200320053701c808200320043701c008200320083601bc08200320073701b408200320013601b008200341023a00f00b410110332202450d0e200220032d00f00b3a0000200341b0086aad42808080808004842002ad428080808010841002200210350c100b20004200370308200041186a41023602000c110b024020022d000120022d000041004772450d0020004200370308200041186a41023602000c110b200141046a280200210141f7edcb00ad4280808080f0008410012202280000210820022900042107200228000c21092002103541c1edcb00ad4280808080e001841001220229000021042002290008210520021035200320053701c808200320043701c008200320093601bc08200320073701b408200320083601b008200320013602800a200341b0086aad4280808080800484200341800a6aad4280808080c0008410020c0e0b200341a8096a200141246a28020036020020034188096a41186a2001411c6a29020037030020034188096a41106a200141146a29020037030020034188096a41086a2001410c6a2902003703002003200141046a290200370388092002411a6a2901002107200241196a2d00002109200241186a2d0000210a200241166a2f0100210b200241156a2d0000210c200241146a2d0000210d200241126a2f0100210e200241116a2d0000210f200241106a2d000021102002410e6a2f010021112002410d6a2d000021122002410c6a2d000021132002410a6a2f01002114200241096a2d00002115200241086a2d00002116200241066a2f01002117200241056a2d00002118200241046a2d0000211941022101200241026a2f0100210641012108024020022d00000d0020022d000141014721080b200320073701c808200320093a00c7082003200a3a00c6082003200b3b01c4082003200c3a00c3082003200d3a00c2082003200e3b01c0082003200f3a00bf08200320103a00be08200320113b01bc08200320123a00bb08200320133a00ba08200320143b01b808200320153a00b708200320163a00b608200320173b01b408200320183a00b308200320193a00b208200320063b01b0080240024002402008450d0041801021080c010b200341d00b6a41186a200341b0086a41186a290100370300200341d00b6a41106a200341b0086a41106a290100370300200341d00b6a41086a200341b0086a41086a290100370300200320032901b0083703d00b200341f0066a200341d00b6a10b401200341800a6a20032802f006220120032802f80610d50120032802f4062102024020032d00800a4101470d00200341990a6a2900002107200341800a6a41186a2d00002108200341970a6a2d00002109200341950a6a2f0000210a200341940a6a2d0000210b200341930a6a2d0000210c200341910a6a2f0000210d200341800a6a41106a2d0000210e2003418f0a6a2d0000210f2003418d0a6a2f000021102003418c0a6a2d000021112003418b0a6a2d00002112200341890a6a2f00002113200341800a6a41086a2d0000211420032d00870a211520032f00850a211620032d00840a211720032d00830a211820032d00820a211920032d00810a210602402002450d00200110350b200320073703880c200320083a00870c200320093a00860c2003200a3b01840c2003200b3a00830c2003200c3a00820c2003200d3b01800c2003200e3a00ff0b2003200f3a00fe0b200320103b01fc0b200320113a00fb0b200320123a00fa0b200320133b01f80b200320143a00f70b200320153a00f60b200320163b01f40b200320173a00f30b200320183a00f20b200320193a00f10b200320063a00f00b200341800a6a41206a20034188096a41206a280200360200200341800a6a41186a20034188096a41186a290300370300200341800a6a41106a20034188096a41106a290300370300200341800a6a41086a20034188096a41086a29030037030020032003290388093703800a200341f0066a200341800a6a108b0241012101410d2102024020032d00f0064101460d00200341f0066a41086a2d00002101200341f9066a2f00002108200341fb066a2d00002109200341fc066a2d0000210a200341f0066a410d6a2f0000210b200341ff066a2d0000210c200341f0066a41106a2d0000210d20034181076a2f0000210e20034183076a2d0000210f20034184076a2d0000211020034185076a2f0000211120034187076a2d00002112200341f0066a41186a2d0000211320032d00f106211420032d00f206211520032d00f306211620032d00f406211720032f00f506211820032d00f7062119200320034189076a2900003703f808200320133a00f708200320123a00f608200320113b01f408200320103a00f3082003200f3a00f2082003200e3b01f0082003200d3a00ef082003200c3a00ee082003200b3b01ec082003200a3a00eb08200320093a00ea08200320083b01e808200320013a00e708200320193a00e608200320183b01e408200320173a00e308200320163a00e208200320153a00e108200320143a00e008200341800a6a200341e0086a10b701200341f0006a20032802800a220120032802880a41b0b4cc0041004100108a0220032802702108024020032802840a450d00200110350b4103210120084101470d030b4194a6c00021094180900c21080c010b02402002450d00200110350b41aea6c000210941082102410321014180900421080b200041206a20023602002000411c6a2009360200200041186a2008200172360200200042003703080c100b200341e0086a200341f00b6a412010a008450d0d200341800a6a200341d00b6a10b40120033502880a210720032802800a2101412010332202450d00200220032903e008370000200241186a200341e0086a41186a290300370000200241106a200341e0086a41106a290300370000200241086a200341e0086a41086a29030037000020074220862001ad842002ad4280808080800484100220021035024020032802840a450d00200110350b200341b0096a200341f00b6a10b701200341800a6a20032802b009220120032802b809220810d601024020032802a00a2202450d002008ad4220862001ad8410070b200341f0066a41086a2208200341bc0a6a290200370300200341f0066a41106a2209200341c40a6a290200370300200341f0066a41186a220a200341cc0a6a290200370300200341f0066a41206a220b200341d40a6a2802003602002003200341b40a6a2902003703f006200341800a6a41186a2903002107200341800a6a41086a2903002104200341b00a6a280200210c200341ac0a6a280200210d200341a80a6a280200210e20032903900a210520032903800a211a20032802a40a210f200341b0086a41206a2210200b280200360200200341b0086a41186a220b200a290300370300200341b0086a41106a220a2009290300370300200341b0086a41086a22092008290300370300200320032903f0063703b00802402002450d00200341d0096a41206a2010280200360200200341d0096a41186a200b290300370300200341d0096a41106a200a290300370300200341d0096a41086a2009290300370300200320032903b0083703d009024020032802b409450d00200110350b200341800a6a41186a2007370300200341b00a6a200c360200200341a80a6a200e360200200341a40a6a200f360200200341b40a6a20032903d009370200200341bc0a6a200341d0096a41086a290300370200200341c40a6a200341d0096a41106a290300370200200341cc0a6a200341d0096a41186a290300370200200341d40a6a200341d0096a41206a280200360200200320053703900a200320043703880a2003201a3703800a2003200d3602ac0a200320023602a00a200341b0086a200341e0086a10b70120033502b808210720032802b008210b200341003602f806200342013703f006412010332202450d0c200220032903b80a370000200241086a200341c00a6a290300370000200241106a200341c80a6a290300370000200241186a200341d00a6a290300370000200320023602f006200342a080808080043702f4062003200341800a6a3602b009200341b0096a200341f0066a10cf012003200341800a6a41106a3602b009200341b0096a200341f0066a10cf0120032802a00a210220032802a80a2201200341f0066a107702402001450d002002200141186c6a21010340200320023602b009200341b0096a200341f0066a10cf01200241106a200341f0066a10e2012001200241186a2202470d000b0b20032802ac0a210c20032802b40a2202200341f0066a10770240024020032802f406220a20032802f80622016b20024102742208490d0020032802f0062102200a21090c010b200120086a22022001490d0c200a41017422092002200920024b1b22094100480d0c02400240200a0d00024020090d00410121020c020b200910332202450d0f0c010b20032802f0062102200a2009460d002002200a200910372202450d0e0b200320093602f406200320023602f0060b200220016a200c2008109d081a2007422086200bad84200120086aad4220862002ad84100202402009450d00200210350b024020032802b408450d00200b10350b024020032802a40a2202450d00200241186c450d0020032802a00a10350b20032802b00a41ffffffff0371450d0e20032802ac0a10350c0e0b20032802b409450d0d200110350c0d0b1045000b4182102108024020022d00000d0020022d00014101470d0020012d00012119200241196a2d00002108200241186a2d00002109200241166a2f0100210a200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241086a2d00002115200241066a2f01002116200241056a2d00002117200241046a2d00002118200241026a2f0100210120032002411a6a2901003703e809200320083a00e709200320093a00e6092003200a3b01e4092003200b3a00e3092003200c3a00e2092003200d3b01e0092003200e3a00df092003200f3a00de09200320103b01dc09200320113a00db09200320123a00da09200320133b01d809200320143a00d709200320153a00d609200320163b01d409200320173a00d309200320183a00d209200320013a00d009200320014108763a00d109200341f00b6a200341d0096a10b701200341800a6a20032802f00b220120032802f80b10d601200341b0086a41086a220b200341bc0a6a290200370300200341b0086a41106a220c200341c40a6a290200370300200341b0086a41186a220d200341cc0a6a290200370300200341b0086a41206a220e200341d40a6a2802003602002003200341b40a6a2902003703b008024020032802a00a2208450d00200341800a6a41186a2903002107200341800a6a41086a2903002104200341b00a6a2802002109200341ac0a6a280200210a200341a80a6a280200210f20032903900a210520032903800a211a20032802a40a210220034188096a41206a200e28020036020020034188096a41186a200d29030037030020034188096a41106a200c29030037030020034188096a41086a200b290300370300200320032903b00837038809024020032802f40b450d00200110350b200341e0086a41086a220120034188096a41086a290300370300200341e0086a41106a220b20034188096a41106a290300370300200341e0086a41186a220c20034188096a41186a290300370300200341e0086a41206a220d20034188096a41206a280200360200200341f0066a41186a2007370300200341a0076a200936020020034198076a200f36020020034194076a200236020020032003290388093703e00820032005370380072003201a3703f0062003200a36029c072003200836029007200320043703f806200341c4076a200d280200360200200341bc076a200c290300370200200341b4076a200b290300370200200341ac076a2001290300370200200341a4076a20032903e008370200200341800a6a200341a8076a108c0220033502880a210720032802800a210b02400240201941037122014103470d0041012101420021044101210c0c010b024002400240024020010e03000102000b4100210c0c020b4101210c0c010b4102210c0b2003200c3a00f00b410110332201450d0c2001200c3a00004100210c42808080801021040b2007422086200bad8420042001ad8410020240200c0d00200110350b024020032802840a450d00200b10350b02402002450d00200241186c450d00200810350b200941ffffffff0371450d0d200a10350c0d0b024020032802f40b450d00200110350b41831021080b20004200370308200041206a410d3602002000411c6a41b6a6c000360200200041186a20083602000c0d0b2002411a6a290100211a200241196a2d0000210c200241186a2d0000210d200241166a2f0100210e200241156a2d0000210f200241146a2d00002110200241126a2f01002111200241116a2d00002112200241106a2d00002113410e21012002410e6a2f010021142002410d6a2d000021152002410c6a2d000021162002410a6a2f01002117200241096a2d00002118200241086a2d00002119200241066a2f01002106200241056a2d0000211d200241046a2d0000211e200241026a2f0100211f20022d0001210b20022d0000210a41f7edcb00ad4280808080f0008410012202280000210820022900042107200228000c21092002103541b6aac000ad42808080809002841001220229000021042002290008210520021035200320053701c808200320043701c008200320093601bc08200320073701b408200320083601b008200341e8006a200341b0086a10f20141032102024002402003280268417d71450d0041dca2c0002108418090ec0021090c010b0240200a41ff01710d00200b41ff01714101470d002003201a3703e8092003200c3a00e7092003200d3a00e6092003200e3b01e4092003200f3a00e309200320103a00e209200320113b01e009200320123a00df09200320133a00de09200320143b01dc09200320153a00db09200320163a00da09200320173b01d809200320183a00d709200320193a00d609200320063b01d4092003201d3a00d3092003201e3a00d2092003201f3b01d009200341f00b6a200341d0096a10b701200341800a6a20032802f00b220a20032802f80b10d601200341b0086a41086a220b200341bc0a6a290200370300200341b0086a41106a220c200341c40a6a290200370300200341b0086a41186a220d200341cc0a6a290200370300200341b0086a41206a220e200341d40a6a2802003602002003200341b40a6a2902003703b008024020032802a00a2201450d00200341800a6a41186a2903002107200341800a6a41086a2903002104200341b00a6a2802002108200341ac0a6a2802002109200341a80a6a280200210f20032903900a210520032903800a211a20032802a40a210220034188096a41206a200e28020036020020034188096a41186a200d29030037030020034188096a41106a200c29030037030020034188096a41086a200b290300370300200320032903b00837038809024020032802f40b450d00200a10350b200341e0086a41086a220a20034188096a41086a290300370300200341e0086a41106a220b20034188096a41106a290300370300200341e0086a41186a220c20034188096a41186a290300370300200341e0086a41206a220d20034188096a41206a280200360200200341f0066a41186a2007370300200341a0076a200836020020034198076a200f36020020034194076a200236020020032003290388093703e00820032005370380072003201a3703f0062003200936029c072003200136029007200320043703f806200341c4076a200d280200360200200341bc076a200c290300370200200341b4076a200b290300370200200341ac076a200a290300370200200341a4076a20032903e008370200200341800a6a200341a8076a220a10b50120033502880a42208620032802800a220bad841007024020032802840a450d00200b10350b200341800a6a200a10b90120033502880a42208620032802800a220aad841007024020032802840a450d00200a10350b02402002450d00200241186c450d00200110350b200841ffffffff0371450d0d200910350c0d0b024020032802f40b450d00200a10350b41b6a6c0002108410d210141801021090c010b4102210241801021090b20004200370308200041206a20013602002000411c6a2008360200200041186a20092002723602000c0c0b410221020c010b02402001450d00200141186c450d00200910350b0240200a41ffffffff0371450d00201210350b4188a6c0002109410c21014104210a0b2008450d02200841246c450d02200b10350c020b02402008450d00200841246c450d00200b10350b20032802c40b41ffffff3f71210e0b02400240200c450d00200e450d01200f10350c010b200f0d020b02402001450d00200141186c450d00200910350b0240200a41ffffffff0371450d00201210350b410121020b20004200370308200041206a20013602002000411c6a2009360200200041186a200a41ff0171411074200272418010723602000c060b41f7edcb00ad4280808080f0008410012201280000210820012900042107200128000c21092001103541e4edcb00ad4280808080a001841001220129000021042001290008210520011035200320053701c808200320043701c008200320093601bc08200320073701b408200320083601b008200341d8006a200341b0086a412010c001200328025c211120032802582112200341800a6a200341a8076a220110b50120033502880a42208620032802800a2208ad841007024020032802840a450d00200810350b200341d0096a200110b90120033502d809210720032802d0092110200341003602880a200342013703800a2002200341800a6a10770240024020020d0020032802840a210920032802880a21010c010b2002410574210b410020032802880a22016b210a20032802800a210d20032802840a2109200f210c0340200c210202402009200a6a411f4b0d00200141206a22082001490d032009410174220c2008200c20084b1b22084100480d03024002400240024020090d00024020080d004101210d0c020b20081033210d0c030b20092008470d010b200821090c020b200d200920081037210d0b20082109200d450d040b200241206a210c200d20016a22082002290000370000200841186a200241186a290000370000200841106a200241106a290000370000200841086a200241086a290000370000200a41606a210a200141206a2101200b41606a220b0d000b200320093602840a200320013602880a2003200d3602800a0b02400240200920016b4104490d0020032802800a2108200921020c010b200141046a22022001490d01200941017422082002200820024b1b22024100480d010240024020090d00024020020d00410121080c020b200210332208450d040c010b20032802800a210820092002460d0020082009200210372208450d030b200320023602840a200320083602800a0b200820016a2011410020121b3600002003200141046a22013602880a41002109200341003a00f00b0240024020022001460d00200121020c010b200241016a22012002490d01200241017422092001200920014b1b22014100480d010240024020020d0041002102024020010d00410121080c020b200110332208450d040c010b20022001460d0020082002200110372208450d030b200320013602840a200320083602800a20032d00f00b21090b200820026a20093a000020032802840a210120074220862010ad84200241016aad42208620032802800a2202ad84100202402001450d00200210350b024020032802d409450d00201010350b0240200e450d00200f10350b02402003280294072202450d00200241186c450d0020032802900710350b20032802a00741ffffffff0371450d03200328029c0710350c030b103e000b103c000b20004200370308200041206a20013602002000411c6a2008360200200041186a2009418080fc0071200272418010723602000c020b42002107200042003703080c020b200041206a20083602002000411c6a200136020020004200370308200041186a20094180801c71200272418010723602000b420121070b20002007370300200341900c6a24000b9d0102017f017e230041106b2206240002402002ad4220862001ad842004ad4220862003ad842005102b2207422088a72204450d002007a722052d0000220341014b0d00410021010240024020030e020100010b2004417f6a4104490d0120052800012102410121010b200510352000200236020420002001360200200641106a24000f0b41b89acc00412e200641086a41c09bcc0041e89acc001046000b850501067f230041c0016b22022400200241ce006a2203200141036a2d00003a0000200241306a41086a2204200141106a290200370300200241306a41106a2205200141186a290200370300200241306a41186a2206200141206a280200360200200220012f00013b014c2002200141086a290200370330200141046a280200210702400240024020012d00004101470d0020024188016a2007109604200241d0006a200228028801220120022802900110cb0220024198016a41086a200241e7006a29000037030020024198016a41106a200241ef006a29000037030020024198016a41186a200241f7006a2d00003a0000200220022f01583b01b8012002200241da006a2d00003a00ba012002200229005f37039801024020022903504201520d00200241db006a2800002107200241086a41086a20024198016a41086a290300370300200241086a41106a20024198016a41106a290300370300200241086a41186a20024198016a41186a2d00003a0000200220022d00ba013a002a200220022f01b8013b01282002200229039801370308200228028c01450d02200110350c020b0240200228028c01450d00200110350b410121010c020b200241086a41086a2004290300370300200241086a41106a2005290300370300200241086a41186a20062d00003a0000200220022f014c3b012820022002290330370308200220032d00003a002a0b200041036a20022d002a3a0000200020022f01283b0001200041046a2007360000200041086a2002290308370000200041106a200241086a41086a290300370000200041186a200241086a41106a290300370000200041206a200241086a41186a2d00003a0000410021010b200020013a0000200241c0016a24000bb10503027f017e047f230041d0006b2202240041f7edcb00ad4280808080f00084100122032900002104200241086a41086a200341086a29000037030020022004370308200310354188c5c100ad4280808080d00084100122032900002104200241186a41086a200341086a29000037030020022004370318200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad42808080808004841003220129000037033820011035200241cc006a200341206a360200200220033602482002200241386a41086a3602442002200241386a360240200241286a200241c0006a107b200310352002280230220541206a2201417f4c0d01200228022821060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a2000200136020820002008360204200020033602000240200228022c450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000bce0203027f017e037f23004180026b22012400200141086a2000108e02200141e0006a2001280208220020012802102202108f0220012903602103200141b8016a200141e8006a41c400109d081a200141b4016a41026a2204200141af016a2d00003a0000200120012f00ad013b01b4010240024020034201510d0041002105200141186a410041c400109f081a0c010b20012d00ac012105200141186a200141b8016a41c400109d081a200141146a41026a20042d00003a0000200120012f01b4013b01140b200141e8006a200141186a41c400109d082104200141af016a200141166a2d00003a0000200142013703602001417f2005411874220541808080086a220620062005491b4118763a00ac01200120012f01143b00ad01200120023602bc01200120003602b8012004200141b8016a10e7020240200128020c450d00200010350b20014180026a24000bc20503027f017e047f230041d0006b2202240041d1c4c700ad4280808080e00084100122032900002104200241086a200341086a290000370300200220043703002003103541d7c4c700ad4280808080f00084100122032900002104200241106a41086a200341086a29000037030020022004370310200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100422012900002104200241306a41086a200141086a2900003703002002200437033020011035200241cc006a200341206a360200200220033602482002200241306a41106a3602442002200241306a360240200241206a200241c0006a107b200310352002280228220541206a2201417f4c0d01200228022021060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290300370000200341086a200241086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290310370010200341186a200241106a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a20002001360208200020083602042000200336020002402002280224450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000baa0406027f017e017f037e017f037e230041d0006b220324002003200236020420032001360200200341086a2002ad4220862001ad84100510c20102400240200328020822010d00200042003703000c010b200328020c2102024002400240200341106a28020022044104490d0020044104460d002004417b6a4110490d002004416b6a4110490d002004415b6a4110490d002004414b6a410f4b0d010b20034100360220200342013703182003410936022c200320033602282003200341186a360234200341cc006a41013602002003420137023c200341c888c2003602382003200341286a360248200341346a41e88ac500200341386a10431a200335022042208620033502188410060240200328021c450d00200328021810350b420021050c010b2001280000210420012d000421062001410d6a2900002105200129000521072001411d6a290000210820012900152109200341286a41026a220a200341386a41026a2d00003a0000200320032f00383b01282001412d6a290000210b2001290025210c2001290035210d200041c0006a2001413d6a290000370300200041386a200d370300200041306a200b370300200041286a200c370300200041206a2008370300200041186a2009370300200041106a200537030020002007370308200020063a004c200041c8006a2004360200200020032f01283b004d200041cf006a200a2d00003a0000420121050b200020053703002002450d00200110350b200341d0006a24000be80e03037f017e0d7f230022052106200541e0016b41607122052400024002402002200384500d00200441ff01712207450d002000290000210841002109024020074101460d004102410120044101711b21090b20052002370300200520093a00182005200837031020052003370308200541c0016a200110eb0220052802c001210a20052802c401210b02400240024020052802c801220c450d00200a200c41057422046a210d200441606a210e200541a0016a411072210f200541a0016a4119722110200a21040340200541e8006a41106a2211200441106a290300370300200541e8006a41086a2212200441086a29030037030020052004290300370368200441186a2d000021072005200441196a28000036023820052004411c6a28000036003b20074103460d0120102005280238360000201041036a200528003b360000200520112903003703b001200520122903003703a801200520052903683703a001200520073a00b80102400240200f2000460d00200f2900002000290000510d00200520052903b801220237039801200520052903b00137039001200520052903a80137038801200520052903a001370380010c010b200541033a00d80120052005290318220237039801200520052903103703900120052005290308370388012005200529030037038001200520052903d001370310200520052903c801370308200520052903c001370300200520052903d80122033703182003a721090b2002a7220741ff01714103470d02200e41606a210e200441206a2204200d470d000b0b200541003602a801200542083703a001200b41ffffff3f71450d01200a10350c010b200541d0006a41106a2210200529039001370300200541d0006a41086a22112005290388013703002005200528009c0136004320052005280099013602402005200529038001370350200520052802403602482005200528004336004b41201033220f450d02200f2005290350370300200f20073a0018200f2005280248360019200f411c6a200528004b360000200f41106a2010290300370300200f41086a2011290300370300200542818080801037022c2005200f3602280240200e450d00200441206a210e200c410574200a6a41606a211320054180016a4119722114200541a0016a4110722112200541a0016a41197221104101210c0340200e21040340200541e8006a41106a220e200441106a290300370300200541e8006a41086a2211200441086a29030037030020052004290300370368200441186a2d000021072005200441196a28000036023820052004411c6a28000036003b20074103460d0220102005280238360000201041036a200528003b3600002005200e2903003703b001200520112903003703a801200520052903683703a001200520073a00b8010240024020122000460d0020122900002000290000510d00200520052903b801220237039801200520052903b00137039001200520052903a80137038801200520052903a001370380010c010b200541033a00d80120052005290318220237039801200520052903103703900120052005290308370388012005200529030037038001200520052903d001370310200520052903c801370308200520052903c001370300200520052903d80122033703182003a721090b02402002a7220741ff01714103470d00200441206a2204200d470d010c030b0b200541d0006a41106a220e200529039001370300200541d0006a41086a2211200529038801370300200520142800003602402005201441036a2800003600432005200529038001370350200520052802403602482005200528004336004b200541c0016a41086a22152011290300370300200541c0016a41106a2211200e290300370300200520052903503703c001200520052802483602a0012005200528004b3600a3010240200c200528022c470d00200541286a200c410110a1012005280228210f0b200441206a210e201529030021022011290300210320052903c0012108200f200c4105746a221120073a001820112008370300201120052802a0013600192011411c6a20052800a301360000201141106a2003370300201141086a20023703002005200c41016a220c36023020132004470d000b0b0240200b41ffffff3f71450d00200a10350b200541a0016a41086a200541286a41086a280200360200200520052903283703a0010b02400240200941ff01714103470d0020052802a801210420052802a0012107200541a0016a21050c010b200541c0016a41186a22102005290318370300200541c0016a41106a220e2005290310370300200541c0016a41086a22112005290308370300200520052903003703c001024020052802a801220420052802a401470d00200541a0016a2004410110a10120052802a80121040b20052802a001220720044105746a220020052903c001370300200041086a2011290300370300200041106a200e290300370300200041186a20102903003703002005200441016a22043602a801200541a0016a21050b20012007200410ec02200541046a28020041ffffff3f71450d00200528020010350b200624000f0b1045000bf90703057f027e037f230041a0016b22022400200241e8006a200110b401200241f8006a200228026822032002280270220410d501024020022d00782205450d002004ad4220862003ad8410070b200241086a41176a220420024191016a290000370000200241086a41106a22062002418a016a290100370300200241086a41086a20024182016a29010022073703002002200229017a220837030820022d00792109200241f8006a41176a220a2004290000370000200241f8006a41106a22042006290300370300200241f8006a41086a22062007370300200220083703780240024020054101470d00200241c8006a41176a200a290000370000200241c8006a41106a2004290300370300200241c8006a41086a2006290300370300200220022903783703480240200228026c450d00200310350b200241286a41176a2203200241c8006a41176a290000370000200241286a41106a2205200241c8006a41106a290300370300200241116a200241d0006a290300370000200241196a2005290300370000200241206a2003290000370000200220093a000820022002290348370009200241f8006a200241086a10b70120023502800142208620022802782203ad8410070240200228027c450d00200310350b200241f8006a2001108c0220023502800142208620022802782203ad8410070240200228027c450d00200310350b200241f8006a200110b50120023502800142208620022802782203ad8410070240200228027c450d00200310350b200241f8006a200110b90120023502800142208620022802782203ad8410070240200228027c450d00200310350b200241c8006a200110ba01200241f8006a200228024822032002280250220510bc010240200228028401220b450d002005ad4220862003ad8410070b2002290388012107200228027821090240200228024c450d00200310350b0240200b450d00200b2007422088a74102746a210a41002103200b21052009210602400340024002402003417e714102460d0041022103200921040c010b2005450d02200a2005460d02200541046a2105410321032006417f6a220621040b200241f8006a41186a200141186a290000370300200241f8006a41106a200141106a290000370300200241f8006a41086a200141086a290000370300200220043602980120022001290000370378200241c8006a200241f8006a10b601200235025042208620022802482204ad841007200228024c450d00200410350c000b0b200742ffffffff0383500d00200b10350b2001109902200041043a00000c010b0240200228026c450d00200310350b200041086a4108360200200041046a41aea6c000360200200041026a41013a000020004183103b01000b200241a0016a24000bac0304107f027e017f017e230041306b220224002002200110eb022002280200210302400240200228020822040d00410021040c010b200041706a210541002106200321074100210802400240034002400240024020052007460d00200741106a22092900002000290000510d0020060d01410021060c020b200641016a21060c010b200820066b220a20044f0d02200241106a41186a220b200720064105746b220a41186a220c290300370300200241106a41106a220d200a41106a220e290300370300200241106a41086a220f200a41086a22102903003703002002200a290300370310200741086a2211290300211220092903002113200741186a22142903002115200a2007290300370300200c2015370300200e2013370300201020123703002014200b2903003703002009200d2903003703002011200f290300370300200720022903103703000b200741206a21072004200841016a2208460d020c000b0b200a200441f485cc001042000b2006417f6a20044f0d002002200420066b22043602080b20012003200410ec020240200228020441ffffff3f71450d00200310350b200241306a24000bcb3e0a027f017e017f027e017f017e117f017e077f077e230041a0036b22052400200541e0006a41286a200341286a290300370300200541e0006a41206a200341206a290300370300200541e0006a41186a200341186a290300370300200541e0006a41106a200341106a290300370300200541e0006a41086a200341086a290300370300200520032903003703600240024002400240024002400240024002400240024002400240024002400240024002400240200541e0006a200410f101220441ff0171411d470d0020054180036a41086a22044200370300200542003703800341f7edcb00ad4280808080f0008410012206290000210720054190036a41086a2208200641086a290000370300200520073703900320061035200420082903003703002005200529039003370380034192aac000ad4280808080a002841001220629000021072006290008210920061035200541e0026a41086a2004290300370300200520093703f802200520073703f00220052005290380033703e002200541e0006a200541e0026aad4280808080800484220a100510c2010240024020052802602204450d00200528026421062005200541e8006a2802003602a402200520043602a002200541386a200541a0026a10c401024002402005280238450d004101210b41b0b4cc0021080c010b200528023c21084100210b0b02402006450d00200410350b41122104200b450d010c020b410021080b20054180036a41086a22064200370300200542003703800341f7edcb00ad4280808080f00084220c10012204290000210720054190036a41086a220b200441086a2900003703002005200737039003200410352006200b29030037030020052005290390033703800341c1edcb00ad4280808080e001841001220429000021072004290008210920041035200541e0026a41086a220d2006290300370300200520093703f802200520073703f00220052005290380033703e002200541306a200541e0026a412010c00141132104200041086a28020020082005280234410020052802301b220e200e20084b1b2208470d00200642003703002005420037038003200c100122042900002107200b200441086a2900003703002005200737039003200410352006200b2903003703002005200529039003370380034192aac000ad4280808080a002841001220429000021072004290008210920041035200d2006290300370300200520093703f802200520073703f00220052005290380033703e002200541e0006a200541e0026a10fe01024020052802602206450d00200520052902642207370244200520063602402000280200210f20002802042110024020080d00411d21040c050b411421042007422088a7200f2f010022004d0d04200541e8006a220b200620004105746a220441096a290000370300200541f0006a2200200441116a290000370300200541f7006a2206200441186a2900003700002005200429000137036020042d0000210441201033220e450d06200e20043a0000200e2005290360370001200e41096a200b290300370000200e41116a2000290300370000200e41186a200629000037000020054281808080103702e4022005200e3602e0024101210b411d210420084101460d032005280248200f2f010222004d0d02200541a0026a41086a2211200528024020004105746a220041096a290000370300200541a0026a41106a2212200041116a290000370300200541a0026a41176a2213200041186a290000370000200520002900013703a002200f41046a210d2008410174417c6a210820002d00002114412121064102210b410121000340200541e0006a41176a22152013290000370000200541e0006a41106a22162012290300370300200541e0006a41086a22172011290300370300200520052903a0023703600240200b417f6a2000470d00200541e0026a20004101108a0120052802e002210e0b200e20066a2200417f6a20143a000020002005290360370000200041086a2017290300370000200041106a2016290300370000200041176a20152900003700002005200b3602e8022008450d042005280248200d2f010022004d0d032011200528024020004105746a220041096a2900003703002012200041116a2900003703002013200041186a290000370000200520002900013703a0022008417e6a2108200d41026a210d200641206a2106200b41016a210b20002d0000211420052802e40221000c000b0b411221040b200110fa01200041046a28020041808080807872418080808078460d11200028020010350c110b411421040b0240201041808080807872418080808078460d00200f10350b20052802e40241ffffff3f7121110c010b410021114101210e0240201041808080807872418080808078460d00200f10350b4100210b0b02402004411d460d00410121032011450d0d0c0c0b20054180036a41086a22044200370300200542003703800341f7edcb00ad4280808080f0008410012200290000210720054190036a41086a2206200041086a2900003703002005200737039003200010352004200629030037030020052005290390033703800341a4aac000ad4280808080a002841001220029000021072000290008210920001035200541e0026a41086a2004290300370300200520093703f802200520073703f00220052005290380033703e002200541e0006a200541e0026a10fe0120052802602214450d0820052005290264220737025420052014360250200541e0006a200141c001109d081a200541a0026a200541e0006a200541d0006a200541c0006a109b022007a7211720052d00a0024101460d0620052802a4022218200541a0026a410c6a2802002219412c6c221a6a211b200541a0026a41086a221c280200211d0240201a450d00200541e0026a41086a210f41f7edcb00ad4280808080f00084210741f393ca00ad4280808080a00184211e201821120340200710012204290000210920054190036a41086a2213200441086a290000370300200520093703900320041035201e1001220429000821092004280004211f2004280000212020041035412010332204450d0220042012410c6a2200290000370000200441186a200041186a2221290000370000200441106a200041106a2222290000370000200441086a200041086a222329000037000020052004ad4280808080800484100322062900003703e002200610352005200441206a36026c200520043602682005200f3602642005200541e0026a360260200541a0026a200541e0006a107b2004103520052802a802221541206a2206417f4c0d0c20052802a00221160240024020060d0041002108410121040c010b200610332204450d03200621080b024002402008410f4d0d002008210d0c010b2008410174220d4110200d41104b1b220d4100480d04024020080d00200d103322040d010c090b2008200d460d0020042008200d10372204450d080b2004200529039003370000200441086a201329030037000002400240200d4170714110460d00200d21080c010b200d41017422084120200841204b1b22084100480d04200d2008460d002004200d200810372204450d080b200420093700182004201f3600142004202036001002400240200841606a2015490d002008210d0c010b2015415f4b0d042008410174220d2006200d20064b1b220d4100480d042008200d460d0020042008200d10372204450d080b200441206a20162015109d081a024020052802a402450d00201610350b200541286a2004200641b0b4cc0041004100108a022005280228211f0240200d450d00200410350b20071001220429000021092013200441086a29000037030020052009370390032004103541cca9c000ad4280808080a00184100122042900082109200428000421202004280000212420041035412010332204450d0220042000290000370000200441186a2021290000370000200441106a2022290000370000200441086a202329000037000020052004ad4280808080800484100322062900003703e002200610352005200441206a36026c200520043602682005200f3602642005200541e0026a360260200541a0026a200541e0006a107b2004103520052802a802221541206a2206417f4c0d0c20052802a00221160240024020060d0041002108410121040c010b200610332204450d03200621080b024002402008410f4d0d002008210d0c010b2008410174220d4110200d41104b1b220d4100480d04024020080d00200d10332204450d090c010b2008200d460d0020042008200d10372204450d080b2004200529039003370000200441086a201329030037000002400240200d4170714110460d00200d21080c010b200d41017422084120200841204b1b22084100480d04200d2008460d002004200d200810372204450d080b20042009370018200420203600142004202436001002400240200841606a2015490d002008210d0c010b2015415f4b0d042008410174220d2006200d20064b1b220d4100480d042008200d460d0020042008200d10372204450d080b200441206a20162015109d081a024020052802a402450d00201610350b200541e0006a20042006109c02024020052d0070220641024622130d0020052802602110200528026421252005290368210c0b0240200d450d00200410350b02400240024002400240201f410146220420064102472208460d002004450d010240201241086a2802004101470d000240201228020022042000460d0020042000412010a0080d010b20042f012041ffff03460d030b4119210420064102460d0b202541ffffff3f710d0a0c0b0b4116210420064102460d0a202541ffffff3f71450d0a0c090b02402008450d00024020122802082204450d002012280200220d200441226c6a2115200c422088a72116200ca7410574211303402005200d22063602a002200641226a210d20132100201021040340024020000d00411721040c0c0b024020062004460d0020042006412010a0082108200041606a2100200441206a210420080d010b0b200541e0006a200541a0026a10bb010240200528026c2204450d00200528026821000240200528027041ffffffff0371450d00200410350b200020164d0d00411821040c0b0b200d2015470d000b0b202541ffffff3f71450d030c020b4185f3c10041fd004184f4c1001064000b20130d01202541ffffff3f71450d010b201010350b2012412c6a2212201b470d000b0b200541003602e802200542043703e002200541e0026a4100201a412c6d10980120052802e002210020052802e80221042005201b36026c200520183602682005201d36026420052018360260200520054190036a360270201c20043602002005200541e0026a41086a3602a402200520002004412c6c6a3602a002200541e0006a200541a0026a109d0220052802e4022110200541e0006a200e200b20052802e002222020052802e802221f10cc012005280268210f2005280264211220052802602116411a21040240200528026c0d000240024002402016450d0002402012450d002012210420162100034020002802c80521002004417f6a22040d000b20162104201221060340200420042f01064102746a41c8056a28020021042006417f6a22060d000b200541e0006a21060c020b200541e0006a210620162100201621040c010b4100210020054100360264200541e0006a21060c010b20052004360264200541ec006a20042f010636020020054100360268200541003602600b200541e0026a41086a200641086a29020022073703002005200629020022093703e002200541e0006a41186a200737030042002126200542003703682005200036026420054100360260200520093703702005200f3602800102400240200f0d00427f21274200210c4200212842002129427f211e0c010b2005200f417f6a36028001200541e0006a410020001b220d2802002106200d28020821130240024002400240200d28020c2208200d28020422042f01064f0d00200421000c010b034020042802002200450d02200641016a210620042f0104210820002104200820002f01064f0d000b0b2008ad4220862013ad8421070c010b2013ad2107410021000b2007422088a7221341016a21082007a721150240024020060d00200021040c010b200020084102746a41c8056a2802002104410021082006417f6a2206450d00034020042802c80521042006417f6a22060d000b0b200d200836020c200d2015360208200d2004360204200d4100360200200020134105746a41e8026a2104427f2127427f211e4200212842002129420021264200210c0340200541086a200441086a29030022094200200429030022074200108408200541186a2007420020074200108408427f200c427f200541186a41086a290300222a2005290308222b202b7c7c222b20092005290310222c84202c84420052202b202a547222041b7c2026427f200529031820041b7c222a2026542204ad7c222620042026200c542026200c511b22041b210c427f202a20041b21262009201e20072027542009201e542009201e511b22041b211e2007202720041b2127200920297c200720287c2228200754ad7c21292005280280012204450d0120052004417f6a36028001200541e0006a410020052802641b220d2802002106200d2802082113024002400240200d28020c2208200d28020422042f01064f0d00200421000c010b0240034020042802002200450d01200641016a210620042f0104210820002104200820002f0106490d020c000b0b2013ad2107410021000c010b2008ad4220862013ad8421070b2007422088a7221341016a21082007a721150240024020060d00200021040c010b200020084102746a41c8056a2802002104410021082006417f6a2206450d00034020042802c80521042006417f6a22060d000b0b200d200836020c200d2015360208200d2004360204200d4100360200200020134105746a41e8026a21040c000b0b200541c8026a200c370300200541a0026a41186a2029370300200520263703c002200520283703b002200520273703a0022005201e3703a80202400240200541a0026a2003460d00200541a0026a2003413010a0080d010b0240024020160d0041002116410021034100210f0c010b0240024020120d00201621030c010b2012210320162104034020042802c80521042003417f6a22030d000b201621030340200320032f01064102746a41c8056a28020021032012417f6a22120d000b200421160b20032f010621040b200541fc006a2004360200200541e0006a41186a4100360200200541f4006a20033602002005200f3602800120054100360270200542003703682005201636026420054100360260200520054190036a36028401200541d0026a200541e0006a10cd0120052802d002211320052802d402211520052802d802211220054180036a41086a22034200370300200542003703800341f7edcb00ad4280808080f0008410012204290000210720054190036a41086a2200200441086a2900003703002005200737039003200410352003200029030037030020052005290390033703800341b3b6c000ad4280808080d001841001220429000021072004290008210920041035200541e0026a41086a2003290300370300200520093703f802200520073703f00220052005290380033703e0022005410036026820054201370360200b200541e0006a10770240200b450d00200b410574210b4100200528026822046b210120052802642106200e2103034002400240200620016a4120490d00200528026021000c010b200441206a22002004490d06200641017422082000200820004b1b22084100480d060240024020060d00024020080d00410121000c020b200810332200450d0c0c010b2005280260210020062008460d0020002006200810372200450d0b0b2005200836026420052000360260200821060b200020046a22002003290000370000200041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a2900003700002005200441206a2204360268200141606a2101200341206a2103200b41606a220b0d000b0b2012200541e0006a107702402012450d002013201241d0006c6a210d2013210b03400240024020052802642200200528026822036b4120490d00200528026021040c010b200341206a22042003490d06200041017422012004200120044b1b22014100480d060240024020000d00024020010d00410121040c020b200110332204450d0c0c010b2005280260210420002001460d0020042000200110372204450d0b0b20052001360264200520043602600b200420036a2204200b290000370000200441186a200b41186a290000370000200441106a200b41106a290000370000200441086a200b41086a2900003700002005200341206a3602682005200b41206a3602900320054190036a200541e0006a10cf012005200b41306a3602900320054190036a200541e0006a10cf01200b2802402103200b2802482204200541e0006a107702402004450d00200441306c210603400240024020052802642201200528026822046b4120490d00200528026021000c010b200441206a22002004490d08200141017422082000200820004b1b22084100480d080240024020010d00024020080d00410121000c020b200810332200450d0e0c010b2005280260210020012008460d0020002001200810372200450d0d0b20052008360264200520003602600b200020046a2200200341106a290000370000200041186a200341286a290000370000200041106a200341206a290000370000200041086a200341186a2900003700002005200441206a360268200520033602900320054190036a200541e0006a10cf01200341306a2103200641506a22060d000b0b200d200b41d0006a220b470d000b0b024002400240024002400240200241ff0171220341024b0d0020030e03010203010b2005280268210320052802642100200528026021040c040b410021010c020b410121010c010b410221010b200520013a009003024002402005280264220020052802682203460d00200528026021040c010b200341016a22042003490d05200341017422002004200020044b1b22004100480d050240024020030d0041002103024020000d00410121040c020b200010332204450d0b0c010b2005280260210420032000460d0020042003200010372204450d0a0b20052000360264200520043602600b200420036a20013a00002005200341016a22033602680b200a2003ad4220862004ad84100202402000450d00200410350b02402011450d00200e10350b02402012450d00201241d0006c2104201341c4006a21030340024020032802002200450d00200041306c450d002003417c6a28020010350b200341d0006a2103200441b07f6a22040d000b0b02402015450d00201541d0006c450d00201310350b200541e0006a41286a2200200541a0026a41286a290300370300200541e0006a41206a2201200541a0026a41206a290300370300200541e0006a41186a2206200541a0026a41186a290300370300200541e0006a41106a2208200541a0026a41106a290300370300200541e0006a41086a220b200541a0026a41086a290300370300200520052903a00237036020054180036a41086a22034200370300200542003703800341f7edcb00ad4280808080f0008410012204290000210720054190036a41086a2202200441086a2900003703002005200737039003200410352003200229030037030020052005290390033703800341ceeecb00ad4280808080b001841001220429000021072004290008210920041035200541e0026a41086a2003290300370300200520093703f802200520073703f00220052005290380033703e002413010332203450d0220032005290360370000200341286a2000290300370000200341206a2001290300370000200341186a2006290300370000200341106a2008290300370000200341086a200b290300370000200a2003ad42808080808006841002200310350240201f450d00201f412c6c21042020210303400240200341046a2802002200450d00200041306c450d00200328020010350b2003412c6a2103200441546a22040d000b0b02402010450d002010412c6c450d00202010350b0240201741ffffff3f71450d00201410350b0240200528024441ffffff3f71450d00200528024010350b411d21040c0f0b411b21040b0240024020160d004100210f200541f4006a4100360200200541003602640c010b0240024020120d00201621030c010b2012210320162100034020002802c80521002003417f6a22030d000b201621030340200320032f01064102746a41c8056a28020021032012417f6a22120d000b200021160b200541fc006a20032f0106360200200541f8006a4100360200200541f4006a2003360200200541003602702005420037036820052016360264200541003602600b2005200f36028001200541e0006a109e020240201f450d00201f412c6c21002020210303400240200341046a2802002206450d00200641306c450d00200328020010350b2003412c6a2103200041546a22000d000b0b2010450d072010412c6c450d07202010350c070b1045000b103e000b202541ffffff3f71450d010b201010350b02402019450d002019412c6c21002018210303400240200341046a2802002206450d00200641226c450d00200328020010350b2003412c6a2103200041546a22000d000b0b201d450d02201d412c6c450d02201810350c020b103c000b411521040b41002103201741ffffff3f71450d012014103520110d030c040b41122104410121030b20110d010c020b1044000b200e10350b0240200528024441ffffff3f71450d00200528024010350b2003450d00200110fa010b200541a0036a240020040be10503027f017e057f230041e0006b2202240041f7edcb00ad4280808080f00084100122032900002104200241206a41086a200341086a290000370300200220043703202003103541ccb5c000ad4280808080800284100122032900002104200241c0006a41086a200341086a2900003703002002200437034020031035200220013602542002200241d4006aad4280808080c000841003220329000037035820031035200241146a200241d8006a3602002002200241d8006a41086a36020c2002200241d4006a3602102002200241d8006a360208200241306a200241086a107b02400240024002402002280238220541206a2206417f4c0d00200228023021070240024020060d0041002101410121030c010b200610332203450d02200621010b024002402001410f4d0d00200121080c010b200141017422084110200841104b1b22084100480d03024020010d002008103322030d010c050b20012008460d0020032001200810372203450d040b20032002290320370000200341086a200241206a41086a2903003700000240024020084170714110460d00200821010c010b200841017422014120200141204b1b22014100480d0320082001460d0020032008200110372203450d040b20032002290340370010200341186a200241c0006a41086a29030037000002400240200141606a2005490d00200121080c010b200541206a22082005490d03200141017422092008200920084b1b22084100480d0320012008460d0020032001200810372203450d040b200341206a20072005109d081a02402002280234450d00200710350b200241086a2003200610ae01200241c0006a41086a2201200241086a410c6a2902003703002002200229020c3703400240024020022802084101460d00200042003702002000410c6a41003602000c010b20002002290340370200200041086a20012903003702000b02402008450d00200310350b200241e0006a24000f0b1044000b1045000b103e000b103c000bbb0302027f037e230041d0006b22042400200441386a20024201200242015620034200522003501b22051b22022003420020051b2203428094ebdc034200109808200441286a20042903382206200441386a41086a2903002207428094ebdc034200108408200441186a20022003200620022004290328852003200441286a41086a2903008584420052ad7c22084201200842015620072008200654ad7c22064200522006501b22051b22082006420020051b220710980802400240024020042903182206428080808010544100200441186a41086a290300501b450d00200441086a200220002002200054200320015420032001511b22051b2003200120051b2008200710980820042903082203428080808010544100200441086a41086a290300501b450d012006a7450d02200441d0006a2400200342ffffffff0f83428094ebdc037e200642ffffffff0f8380a70f0b2004411136024c20044190efc40036024841bcedc40041de00200441c8006a41acedc400419ceec4001046000b2004411136024c20044190efc40036024841bcedc40041de00200441c8006a41acedc40041f0eec4001046000b4190edc40041194180efc400103f000bf619020c7f087e23004190046b2204240020044190036a2001108c024100200428029003220520042802980310970241ff0171220620064103461b21060240200428029403450d00200510350b0240024002400240024020060e03000201000b200441a0016a200110b40120044190036a20042802a001220620042802a80110d50120044180026a41086a220520044199036a29000037030020044180026a41106a2207200441a1036a29000037030020044180026a41186a2208200441a9036a29000037030020042004290091033703800202400240024020042d0090034101470d0020044180016a41186a200829030037030020044180016a41106a200729030037030020044180016a41086a2005290300370300200420042903800237038001024020042802a401450d00200610350b200441e0016a41186a20044180016a41186a290300370300200441e0016a41106a20044180016a41106a290300370300200441e0016a41086a20044180016a41086a29030037030020042004290380013703e001200441c0006a200441e0016a10b70120044190036a20042802402209200428024810d601200441a0016a41086a220520044190036a41086a290300370300200441a0016a41106a220720044190036a41106a290300370300200441a0016a41186a220820044190036a41186a29030037030020044180026a41086a220a200441bc036a29020037030020044180026a41106a220b200441c4036a29020037030020044180026a41186a220c200441cc036a29020037030020044180026a41206a220d200441d4036a29020037030020044180026a41286a220e200441dc036a29020037030020044180026a41306a220f200441e4036a28020036020020042004290390033703a001200420042902b4033703800220042802b0032206450d01200441e0026a41186a2008290300370300200441e0026a41106a2007290300370300200441e0026a41086a2005290300370300200441086a41086a200a290300370300200441086a41106a200b290300370300200441086a41186a200c290300370300200441086a41206a200d290300370300200441086a41286a200e290300370300200441086a41306a200f280200360200200420042903a0013703e002200420042903800237030802402004280244450d00200910350b20044180026a41186a200441e0016a41186a290300221037030020044180026a41106a200441e0016a41106a290300221137030020044180026a41086a200441e0016a41086a2903002212370300200420042903e00122133703800220044190036a41186a201037030020044190036a41106a201137030020044190036a41086a201237030020044190036a41286a200441e0026a41086a290300221437030020044190036a41306a200441e0026a41106a290300221537030020044190036a41386a200441e0026a41186a29030022163703002004201337039003200420042903e00222173703b003200441c0006a41386a2016370300200441c0006a41306a2015370300200441c0006a41286a2014370300200441e0006a2017370300200441c0006a41186a2010370300200441c0006a41106a2011370300200441c0006a41086a2012370300200420133703400c020b20042802a401450d04200610350c040b02402004280244450d00200910350b20044180026a41186a200441e0016a41186a29030037030020044180026a41106a200441e0016a41106a29030037030020044180026a41086a200441e0016a41086a290300370300200420042903e001370380020b2006450d02200441a0016a41386a2207200441c0006a41386a290300370300200441a0016a41306a2208200441c0006a41306a290300370300200441a0016a41286a220a200441c0006a41286a290300370300200441a0016a41206a220b200441c0006a41206a290300370300200441a0016a41186a200441c0006a41186a2205290300370300200441a0016a41106a200441c0006a41106a220c290300370300200441a0016a41086a200441c0006a41086a220d290300370300200420042903403703a001200441e0016a41186a2005290300370300200441e0016a41106a200c290300370300200441e0016a41086a200d290300370300200420042903403703e00120044180026a41186a2205200729030037030020044180026a41106a2207200829030037030020044180026a41086a2208200a290300370300200420063602a0022004200b29030037038002200441a4026a2004290308370200200441ac026a200441086a41086a290300370200200441b4026a200441086a41106a290300370200200441bc026a200441086a41186a290300370200200441c4026a200441086a41206a290300370200200441cc026a200441086a41286a290300370200200441d4026a200441086a41306a2802003602002005290300211020072007290300221120027c22123703002005201020037c2012201154ad7c3703002008200829030020037c200429038002221020027c2211201054ad7c221237030020042011370380022004200337038801200420023703800102400240200220038450450d004200210342002110420021020c010b200420013602dc02200441e0026a200120044180016a200441dc026a109a02024020042802e0024101470d004200211020042903e8022103420121020c010b20044188036a290300211020044180036a29030021034200210220042903e8024201520d00200441e0026a41106a2903002113200441c8036a200441e0026a41186a290300370300200441c0036a201337030020044190036a41086a41003a000020044199036a2001290000370000200441a1036a200141086a290000370000200441a9036a200141106a290000370000200441b1036a200141186a290000370000200441033a00900341b0b4cc00410020044190036a10d4010b200442f3e885db96cddbb3203703800120044180016a20044180026a41386a20112012411f10900220044190036a200441e0016a10b701200428029003210120042004280298033602e402200420013602e00220044180026a200441e0026a10e1010240200428029403450d00200110350b024020042802a4022201450d00200141186c450d0020042802a00210350b0240200441b0026a28020041ffffffff0371450d0020042802ac0210350b200242018521020c030b200441a0016a200110b40120044190036a20042802a001220120042802a80110d50120044180026a41086a220620044199036a29000037030020044180026a41106a2205200441a1036a29000037030020044180026a41186a2207200441a9036a290000370300200420042900910337038002024020042d0090034101470d00200441c0006a41186a2007290300370300200441c0006a41106a2005290300370300200441c0006a41086a20062903003703002004200429038002370340024020042802a401450d00200110350b200441a0016a41186a200441c0006a41186a290300370300200441a0016a41106a200441c0006a41106a290300370300200441a0016a41086a200441c0006a41086a290300370300200420042903403703a001200420023703082004200337031002400240200220038450450d004200210242002103420021100c010b2004200441a0016a3602e00220044180026a200441a0016a200441086a200441e0026a109a0202402004280280024101470d00420021102004290388022103420121020c010b200441a8026a2903002110200441a0026a2903002103420021022004290388024201520d0020044180026a41106a2903002111200441c8036a20044180026a41186a290300370300200441c0036a201137030020044190036a41086a41003a000020044199036a20042903a001370000200441a1036a200441a0016a41086a290300370000200441a9036a200441a0016a41106a290300370000200441b1036a200441a0016a41186a290300370000200441033a00900341b0b4cc00410020044190036a10d4010b200242018521020c030b20042802a401450d0120011035420021020c020b200420023703a001200420033703a80102400240200220038450450d004200210342002110420021020c010b2004200136024020044180026a2001200441a0016a200441c0006a109a0202402004280280024101470d00420021102004290388022103420121020c010b200441a8026a2903002110200441a0026a2903002103420021022004290388024201520d0020044180026a41106a2903002111200441c8036a20044180026a41186a290300370300200441c0036a201137030020044190036a41086a41003a000020044199036a2001290000370000200441a1036a200141086a290000370000200441a9036a200141106a290000370000200441b1036a200141186a290000370000200441033a00900341b0b4cc00410020044190036a10d4010b200242018521020c010b420021020b2000200337030820002002370300200041106a201037030020044190046a24000b800201027f230041d0006b220224002002200136020420022000360200200241086a2001ad4220862000ad84100510c20102400240200228020822010d00410321000c010b200228020c210302400240200241106a280200450d0020012d000022004103490d010b20024100360220200242013703182002410936022c200220023602282002200241186a360234200241cc006a41013602002002420137023c200241c888c2003602382002200241286a360248200241346a41e88ac500200241386a10431a200235022042208620023502188410060240200228021c450d00200228021810350b410321000b2003450d00200110350b200241d0006a240020000ba30301067f230041106b22032400024020014105744104722204417f4c0d000240200410332205450d002003410036020820032004360204200320053602002001200310770240024020010d002003280208210520032802042106200328020021070c010b20014105742108200328020021072003280204210620032802082105034020002101024002402006200522046b4120490d00200441206a21050c010b024002400240200441206a22052004490d00200641017422002005200020054b1b22004100480d000240024020060d00024020000d00410121070c020b2000103321070c040b20062000470d020b200021060c030b103e000b200720062000103721070b2000210620070d00103c000b200141206a2100200720046a22042001290000370000200441186a200141186a290000370000200441106a200141106a290000370000200441086a200141086a290000370000200841606a22080d000b2003200636020420032005360208200320073602000b20022902002005ad4220862007ad84100202402006450d00200710350b200341106a24000f0b1045000b1044000bce0203027f017e037f23004180026b22012400200141086a2000108e02200141e0006a2001280208220020012802102202108f0220012903602103200141b8016a200141e8006a41c400109d081a200141b4016a41026a2204200141af016a2d00003a0000200120012f00ad013b01b4010240024020034201510d0041002105200141186a410041c400109f081a0c010b20012d00ac012105200141186a200141b8016a41c400109d081a200141146a41026a20042d00003a0000200120012f01b4013b01140b200141e8006a200141186a41c400109d082104200141af016a200141166a2d00003a000020014201370360200141002005411874220541808080786a2206200620054b1b4118763a00ac01200120012f01143b00ad01200120023602bc01200120003602b8012004200141b8016a10e7020240200128020c450d00200010350b20014180026a24000bbe1007047f027e027f067e037f067e047f230041d0036b2204240020032802002105200441206a2001108e02200441a0016a2004280220220620042802282207108f0220042903a001210842002109200442003703a001200441e8016a280200210a20042d00ec01210b02400240200842015122030d00200441306a41306a4200370300200441306a41286a4200370300200441306a41206a4200370300200441306a41186a4200370300200441c0006a4200370300200441386a4200370300200442003703304200210c4200210d4200210e4200210f0c010b200441d8016a2903002110200441a0016a41306a2903002111200441a0016a41206a290300210c200441a0016a41186a2903002109200441e0016a290300210f20042903b001210e20042903a801210d200441306a41206a200441a0016a41286a290300370300200441306a41286a2011370300200441306a41306a2010370300200441c0006a20093703002004200c3703482004200d3703302004200e3703380b024002400240427f200d20097c22092009200d542212200e200c7c2012ad7c2209200e542009200e511b22121b427f200920121b84500d000240200d2002290300220c7c2209200d542212200e200241086a29030022107c2012ad7c220d200e54200d200e511b450d00200441a0026a41086a4108360200200441a7d6ca003602a402200441023a00a202200441830c3b01a002200441a0026a21020c020b200420093703302004200d370338200441e8006a41186a200441c0006a220241086a290300220e370300200441e8006a41206a2212200241106a29030037030020044190016a2213200241186a29030037030020044198016a2214200241206a2903003703002004200d3703702004200937036820042002290300221137037802400240427f200920117c221120112009542202200d200e7c2002ad7c220e200d54200e200d511b22021b2211428080e983b1de16544100427f200e20021b220e501b0d00200441e8006a41106a290300210e201429030021112013290300211520122903002116200429037021172004290368211842012119200429038001211a0c010b024002402011200e8450450d00420021190c010b42002119200441a0026a41186a221b4200370300200441a0026a41106a22134200370300200441a0026a41086a22124200370300200442003703a00241b6fdc600ad42808080808001842215100122142900002116200441c0036a41086a2202201441086a290000370300200420163703c0032014103520122002290300370300200420042903c0033703a00241e489c200ad4280808080d0018422161001221429000021172002201441086a290000370300200420173703c00320141035201320042903c0032217370300200441a0036a41086a221c2012290300370300200441a0036a41106a221d2017370300200441a0036a41186a221e2002290300370300200420042903a0023703a003200441086a200441a0036a412010d701200441086a41106a29030021172004290310211820042802082114201b42003703002013420037030020124200370300200442003703a00220151001221b29000021152002201b41086a290000370300200420153703c003201b103520122002290300370300200420042903c0033703a00220161001221b29000021152002201b41086a290000370300200420153703c003201b1035201320042903c0032215370300201c2012290300370300201d2015370300201e2002290300370300200420042903a0023703a003200442002017420020141b2215200e7d2018420020141b2216201154ad7d2217201620117d2218201656201720155620172015511b22021b3703a80220044200201820021b3703a002200441a0036aad4280808080800484200441a0026aad42808080808002841002200441d8026a200e370300200441d0026a2011370300201241013a0000200441a9026a2005290000370000200441b1026a200541086a290000370000200441b9026a200541106a290000370000200441c1026a200541186a290000370000200441033a00a00241b0b4cc004100200441a0026a10d4010b0b200441c8016a2016370300200441d0016a2015370300200441b0016a2017370300200441d8016a2011370300200441b8016a200e3703002004201a3703c0012004200f3703e001200420183703a8014201210e410021022004200b4100200842015122121b3a00ec012004200a410020121b3602e801200420194201512212ad3703a001024020120d002007ad4220862006ad8410074200210e420021080c030b200420073602a402200420063602a002200441a8016a200441a0026a10e702420021080c020b200441a8026a410b360200200441ea88c2003602a402200441073a00a202200441830c3b01a002200441a0026a21020b200241046a290200220d4280807c832108200d42088842ff0183210e200da7210320022802002112410121020b02402004280224450d00200610350b024002402002450d0020002012360204200041086a200e4208862003ad42ff018384200884370200410121010c010b024002400240200341ff017122030d00200e4200510d0041032102200441a0026a21030c010b2003450d01200e4200520d0141042102200441a0016a21030b200341086a20023a0000200341003a0000200341096a2001290000370000200341116a200141086a290000370000200341196a200141106a290000370000200341216a200141186a29000037000041b0b4cc004100200310d4010b200041286a2010370300200041206a200c370300200041186a200d370300200041106a2009370300200041086a4200370300410021010b20002001360200200441d0036a24000bf6c8010e077f017e057f017e0b7f017e037f017e017f017e017f017e017f017e230041d0016b220424002004200336020c20044100360218200442043703102001280204210520012802002106024002400240024002400240024002400240024020012802082203450d0020034103742107200441b0016a41106a2108200441b0016a41176a21092006210a03402002280208200a290200220ba722034d0d07200441b0016a41086a220c200228020020034105746a220341096a2900003703002008200341116a2900003703002009200341186a290000370000200420032900013703b00120032d0000210d412210332203450d02200428020c220e280208200b422088a741ffff0371220f4d0d06200441c0006a41106a2210200e280200200f4105746a220e41116a290000370300200441c0006a41176a220f200e41186a290000370000200441c0006a41086a200e41096a2900002211370300200e290001210b2003200e2d00003a00002003200b370001200341096a2011370000200341ffff033b0120200341116a2010290300370000200341186a200f2900003700002004200b37034020044190016a41176a220f200929000037000020044190016a41106a2210200829030037030020044190016a41086a2212200c290300370300200420042903b0013703900102402004280218220e2004280214470d00200441106a200e41011098012004280218210e0b200a41086a210a2004280210200e412c6c6a220e200d3a000c200e428180808010370204200e2003360200200e410d6a200429039001370000200e41156a2012290300370000200e411d6a2010290300370000200e41246a200f2900003700002004200428021841016a360218200741786a22070d000b0b0240200541ffffffff0171450d00200610350b200128020c2113200141106a2802002114200141146a2802002203450d0320132003410c6c6a211520044190016a41106a210720044190016a41176a210c2013210a034002400240200a41066a2f0100220841ffff03460d002002280208200a28020022034b0d0120004181043b01000c050b200041013b01000c040b200a41086a2f01002109200a41046a2f0100210e20044190016a41086a2210200228020020034105746a220341096a2900003703002007200341116a290000370300200c200341186a290000370000200420032900013703900120032d0000211241c40010332203450d01200428020c220d280208220f200e4d0d02200441b0016a41086a2206200d280200220d200e4105746a220e41096a290000370300200441b0016a41106a2205200e41116a290000370300200441b0016a41176a2216200e41186a2900003700002004200e2900013703b0010240200f20094d0d00200e2d0000210f200441c0006a41086a2217200d20094105746a220e41096a290000370300200441c0006a41106a2209200e41116a290000370300200441c0006a41176a220d200e41186a290000370000200e290001210b200e2d0000210e2003200f3a0000200320042903b001370001200341096a2006290300370000200341116a2005290300370000200341186a20162900003700002003200e3a0022200320083b01202004200b370340200320042903403700232003412b6a2017290300370000200341336a20092903003700002003413a6a200d29000037000020032008417f733b0142200441206a41176a2208200c290000370000200441206a41106a22092007290300370300200441206a41086a220d2010290300370300200420042903900137032002402004280218220e2004280214470d00200441106a200e41011098012004280218210e0b2004280210200e412c6c6a220e20123a000c200e428280808020370204200e2003360200200e410d6a2004290320370000200e41156a200d290300370000200e411d6a2009290300370000200e41246a20082900003700002004200428021841016a360218200a410c6a220a2015470d010c050b0b20004181043b0100200310350c020b103c000b20004181043b0100200310350b4100210641012102200441106a210802402014450d002014410c6c450d00201310350b4101210941012105410121164101211741012115410121074101210c410121004101210d4101210f4101211041012112410121140c040b02402014450d002014410c6c450d00201310350b200128021821172001411c6a28020021150240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200141206a2802002203450d00201720034104746a2116200441c0006a41086a210e200441c0006a41106a210a200441c0006a41176a2108201721090240024003402009410c6a2f0100210c2009280200210d2004200941046a290200220b3703800102400240200428020c2203280208200ba741ffff037122074d0d00200e200328020020074105746a220341096a290000370300200a200341116a2900003703002008200341186a2900003700002004200329000137034020032d00002107412210332203450d06200320073a0000200320042903403700012003200b421088a722123b0120200341096a200e290300370000200341116a200a290300370000200341186a20082900003700002004428180808010370294012004200336029001200428020c220f28020820042f01840122104b0d0141000d004122450d00200310350b20004181043b01000c3a0b20042f0186012107200441b0016a41176a2206200f28020020104105746a220341186a290000370000200441b0016a41106a2210200341116a290000370300200441b0016a41086a220f200341096a290000220b3703002004200329000122113703b00120032d0000210520082006290000370000200a2010290300370300200e200b3703002004201137034020044190016a41014101109e01200428029001220320053a0022200341236a20042903403700002003412b6a200e290300370000200341336a200a2903003700002003413a6a2008290000370000200341c2006a20073b01002004410236022820042004280294012210360224200420033602200240417f2012411074221220074110746a220720072012491b411076220741ffff03470d00200041013b01000c030b200428020c2212280208200c4d0d012007417f732106200e2012280200200c4105746a220741096a290000370300200a200741116a2900003703002008200741186a290000370000200420072900013703404102210c20072d00002107024020104102470d00200441206a41024101109e01200428022021032004280228210c0b2003200c41226c6a220320073a000020032004290340370001200320063b0120200341096a200e290300370000200341116a200a290300370000200341186a20082900003700002004200428022841016a36022802402002280208200d4d0d0020022802002103200f200441206a41086a280200360200200e2003200d4105746a220341096a290000370300200a200341116a2900003703002008200341186a290000370000200420042903203703b0012004200329000137034020032d000021070240200428021822032004280214470d00200441106a20034101109801200428021821030b20042802102003412c6c6a220320042903b001370200200320073a000c200341086a200f2802003602002003410d6a2004290340370000200341156a200e2903003700002003411d6a200a290300370000200341246a20082900003700002004200428021841016a360218200941106a22092016470d010c040b0b20004181043b0100200428022421100c010b20004181043b01000b2010450d36201041226c450d36200428022010350c360b0240201541ffffffff0071450d00201710350b20012802242118200141286a280200211902402001412c6a2802002203450d002018200341146c6a211a2004418a016a211b20044180016a41086a211c200441c0006a41106a2107200441c0006a41176a210c20182115024002400240034020152f01102114201528020021132015290104210b201c2015410c6a2801003602002004200b3703800102400240200428020c2203280208200ba741ffff0371220a4d0d0020042f018201210e200441c0006a41086a220d2003280200200a4105746a220341096a2900003703002007200341116a290000370300200c200341186a2900003700002004200329000137034020032d0000210341221033220f450d07200f20033a0000200f2004290340370001200f200e3b0120200f41096a200d290300370000200f41116a2007290300370000200f41186a200c2900003700002004428180808010370294012004200f360290010240200428020c220328020820042f018401220a4b0d00410221034101210a0c390b201541146a2115417f200e411074220e20042f01860122064110746a22082008200e491b4110762110200441b0016a41086a22122003280200200a4105746a220341096a290000370300200441b0016a41106a2205200341116a290000370300200441b0016a41176a2216200341186a290000370000200420032900013703b00120032d000021174101210341c200210a4102210e201b21080340200c201629000037000020072005290300370300200d2012290300370300200420042903b0013703400240200e417f6a2003470d0020044190016a20034101109e01200428029001210f0b200f200a6a220941606a20173a0000200941616a22032004290340370000200c290000210b20072903002111200d290300211d200920063b0100200341086a201d370000200341106a2011370000200341176a200b3700002004200e360298010240200a41e400470d00410321030c030b417f2010411074220320082f010022064110746a220920092003491b41107621100240200428020c22032802082008417e6a2f010022094b0d00410221030c030b2012200328020020094105746a220341096a2900003703002005200341116a2900003703002016200341186a290000370000200420032900013703b001200e41016a210e200a41226a210a200841046a210820032d0000211720042802940121030c000b0b410221030c380b200428029401210a20034103470d362004200e3602282004200a3602242004200f3602200240201041ffff037141ffff03460d00200428020c220328020820144d0d022010417f732108200d200328020020144105746a220341096a2900003703002007200341116a290000370300200c200341186a2900003700002004200329000137034020032d000021090240200a200e470d00200441206a200e4101109e012004280220210f2004280228210e0b200f200e41226c6a220320093a000020032004290340370001200c290000210b20072903002111200d290300211d200320083b0120200341096a201d370000200341116a2011370000200341186a200b3700002004200428022841016a360228200228020820134d0d03200228020021032012200441206a41086a280200360200200d200320134105746a220341096a2900003703002007200341116a290000370300200c200341186a290000370000200420042903203703b0012004200329000137034020032d0000210e0240200428021822032004280214470d00200441106a20034101109801200428021821030b20042802102003412c6c6a220320042903b0013702002003200e3a000c200341086a20122802003602002003410d6a2004290340370000200341156a200d2903003700002003411d6a2007290300370000200341246a200c2900003700002004200428021841016a3602182015201a470d010c050b0b200041013b01000c020b20004181043b01000c010b20004181043b01002004280224210a0b200a450d34200a41226c450d34200428022010350c340b02402019450d00201941146c450d00201810350b20012802302118200141346a28020021190240200141386a2802002203450d002018200341186c6a211a2004419a016a211b20044190016a41086a211c200441c0006a41106a2107200441c0006a41176a210c20182115024002400240034020152f01142114201528020021132015290104210b201c2015410c6a2901003703002004200b3703900102400240200428020c2203280208200ba741ffff0371220a4d0d0020042f019201210e200441c0006a41086a220d2003280200200a4105746a220341096a2900003703002007200341116a290000370300200c200341186a2900003700002004200329000137034020032d0000210341221033220f450d07200f20033a0000200f2004290340370001200f200e3b0120200f41096a200d290300370000200f41116a2007290300370000200f41186a200c29000037000020044281808080103702242004200f3602200240200428020c220328020820042f019401220a4b0d00410221034101210a0c350b201541186a2115417f200e411074220e20042f01960122064110746a22082008200e491b4110762110200441b0016a41086a22122003280200200a4105746a220341096a290000370300200441b0016a41106a2205200341116a290000370300200441b0016a41176a2216200341186a290000370000200420032900013703b00120032d000021174101210341c200210a4102210e201b21080340200c201629000037000020072005290300370300200d2012290300370300200420042903b0013703400240200e417f6a2003470d00200441206a20034101109e012004280220210f0b200f200a6a220941606a20173a0000200941616a22032004290340370000200c290000210b20072903002111200d290300211d200920063b0100200341086a201d370000200341106a2011370000200341176a200b3700002004200e3602280240200a418601470d00410321030c030b417f2010411074220320082f010022064110746a220920092003491b41107621100240200428020c22032802082008417e6a2f010022094b0d00410221030c030b2012200328020020094105746a220341096a2900003703002005200341116a2900003703002016200341186a290000370000200420032900013703b001200e41016a210e200a41226a210a200841046a210820032d00002117200428022421030c000b0b410221030c340b2004280224210a20034103470d322004200e360288012004200a360284012004200f360280010240201041ffff037141ffff03460d00200428020c220328020820144d0d022010417f732108200d200328020020144105746a220341096a2900003703002007200341116a290000370300200c200341186a2900003700002004200329000137034020032d000021090240200a200e470d0020044180016a200e4101109e01200428028001210f200428028801210e0b200f200e41226c6a220320093a000020032004290340370001200c290000210b20072903002111200d290300211d200320083b0120200341096a201d370000200341116a2011370000200341186a200b370000200420042802880141016a36028801200228020820134d0d0320022802002103201220044180016a41086a280200360200200d200320134105746a220341096a2900003703002007200341116a290000370300200c200341186a29000037000020042004290380013703b0012004200329000137034020032d0000210e0240200428021822032004280214470d00200441106a20034101109801200428021821030b20042802102003412c6c6a220320042903b0013702002003200e3a000c200341086a20122802003602002003410d6a2004290340370000200341156a200d2903003700002003411d6a2007290300370000200341246a200c2900003700002004200428021841016a3602182015201a470d010c050b0b200041013b01000c020b20004181043b01000c010b20004181043b0100200428028401210a0b200a450d30200a41226c450d3020042802800110350c300b02402019450d00201941186c450d00201810350b200128023c2119200141c0006a280200211e0240200141c4006a2802002203450d0020192003411c6c6a21182004419a016a211a20044190016a41106a211c20044190016a41086a211b200441c0006a41176a210720192115024002400240034020152f01182114201528020021132015410c6a29010021112015290104210b201c201541146a280100360200201b20113703002004200b3703900102400240200428020c2203280208200ba741ffff0371220a4d0d0020042f019201210e200441c0006a41086a220c2003280200200a4105746a220341096a290000370300200441c0006a41106a220d200341116a2900003703002007200341186a2900003700002004200329000137034020032d0000210341221033220f450d07200f20033a0000200f2004290340370001200f200e3b0120200f41096a200c290300370000200f41116a200d290300370000200f41186a200729000037000020044281808080103702242004200f3602200240200428020c220328020820042f019401220a4b0d00410221034101210a0c310b2015411c6a2115417f200e411074220e20042f01960122064110746a22082008200e491b4110762110200441b0016a41086a22122003280200200a4105746a220341096a290000370300200441b0016a41106a2205200341116a290000370300200441b0016a41176a2216200341186a290000370000200420032900013703b00120032d000021174101210341c200210a4102210e201a2108034020072016290000370000200d2005290300370300200c2012290300370300200420042903b0013703400240200e417f6a2003470d00200441206a20034101109e012004280220210f0b200f200a6a220941606a20173a0000200941616a220320042903403700002007290000210b200d2903002111200c290300211d200920063b0100200341086a201d370000200341106a2011370000200341176a200b3700002004200e3602280240200a41a801470d00410321030c030b417f2010411074220320082f010022064110746a220920092003491b41107621100240200428020c22032802082008417e6a2f010022094b0d00410221030c030b2012200328020020094105746a220341096a2900003703002005200341116a2900003703002016200341186a290000370000200420032900013703b001200e41016a210e200a41226a210a200841046a210820032d00002117200428022421030c000b0b410221030c300b2004280224210a20034103470d2e2004200e360288012004200a360284012004200f360280010240201041ffff037141ffff03460d00200428020c220328020820144d0d022010417f732108200c200328020020144105746a220341096a290000370300200d200341116a2900003703002007200341186a2900003700002004200329000137034020032d000021090240200a200e470d0020044180016a200e4101109e01200428028001210f200428028801210e0b200f200e41226c6a220320093a0000200320042903403700012007290000210b200d2903002111200c290300211d200320083b0120200341096a201d370000200341116a2011370000200341186a200b370000200420042802880141016a36028801200228020820134d0d0320022802002103201220044180016a41086a280200360200200c200320134105746a220341096a290000370300200d200341116a2900003703002007200341186a29000037000020042004290380013703b0012004200329000137034020032d0000210e0240200428021822032004280214470d00200441106a20034101109801200428021821030b20042802102003412c6c6a220320042903b0013702002003200e3a000c200341086a20122802003602002003410d6a2004290340370000200341156a200c2903003700002003411d6a200d290300370000200341246a20072900003700002004200428021841016a36021820152018470d010c050b0b200041013b01000c020b20004181043b01000c010b20004181043b0100200428028401210a0b200a450d2c200a41226c450d2c20042802800110350c2c0b0240201e450d00201e411c6c450d00201910350b20012802482119200141cc006a280200211e0240200141d0006a2802002203450d00201920034105746a21182004419a016a211a20044190016a41106a211c20044190016a41086a211b200441c0006a41176a210720192115024002400240034020152f011c2114201528020021132015410c6a29010021112015290104210b201c201541146a290100370300201b20113703002004200b3703900102400240200428020c2203280208200ba741ffff0371220a4d0d0020042f019201210e200441c0006a41086a220c2003280200200a4105746a220341096a290000370300200441c0006a41106a220d200341116a2900003703002007200341186a2900003700002004200329000137034020032d0000210341221033220f450d07200f20033a0000200f2004290340370001200f200e3b0120200f41096a200c290300370000200f41116a200d290300370000200f41186a200729000037000020044281808080103702242004200f3602200240200428020c220328020820042f019401220a4b0d00410221034101210a0c2d0b201541206a2115417f200e411074220e20042f01960122064110746a22082008200e491b4110762110200441b0016a41086a22122003280200200a4105746a220341096a290000370300200441b0016a41106a2205200341116a290000370300200441b0016a41176a2216200341186a290000370000200420032900013703b00120032d000021174101210341c200210a4102210e201a2108034020072016290000370000200d2005290300370300200c2012290300370300200420042903b0013703400240200e417f6a2003470d00200441206a20034101109e012004280220210f0b200f200a6a220941606a20173a0000200941616a220320042903403700002007290000210b200d2903002111200c290300211d200920063b0100200341086a201d370000200341106a2011370000200341176a200b3700002004200e3602280240200a41ca01470d00410321030c030b417f2010411074220320082f010022064110746a220920092003491b41107621100240200428020c22032802082008417e6a2f010022094b0d00410221030c030b2012200328020020094105746a220341096a2900003703002005200341116a2900003703002016200341186a290000370000200420032900013703b001200e41016a210e200a41226a210a200841046a210820032d00002117200428022421030c000b0b410221030c2c0b2004280224210a20034103470d2a2004200e360288012004200a360284012004200f360280010240201041ffff037141ffff03460d00200428020c220328020820144d0d022010417f732108200c200328020020144105746a220341096a290000370300200d200341116a2900003703002007200341186a2900003700002004200329000137034020032d000021090240200a200e470d0020044180016a200e4101109e01200428028001210f200428028801210e0b200f200e41226c6a220320093a0000200320042903403700012007290000210b200d2903002111200c290300211d200320083b0120200341096a201d370000200341116a2011370000200341186a200b370000200420042802880141016a36028801200228020820134d0d0320022802002103201220044180016a41086a280200360200200c200320134105746a220341096a290000370300200d200341116a2900003703002007200341186a29000037000020042004290380013703b0012004200329000137034020032d0000210e0240200428021822032004280214470d00200441106a20034101109801200428021821030b20042802102003412c6c6a220320042903b0013702002003200e3a000c200341086a20122802003602002003410d6a2004290340370000200341156a200c2903003700002003411d6a200d290300370000200341246a20072900003700002004200428021841016a36021820152018470d010c050b0b200041013b01000c020b20004181043b01000c010b20004181043b0100200428028401210a0b200a450d28200a41226c450d2820042802800110350c280b0240201e41ffffff3f71450d00201910350b2001280254211f200141d8006a280200211e0240200141dc006a2802002203450d00201f200341246c6a21192004419a016a211820044190016a41186a211c20044190016a41106a211b20044190016a41086a211a200441c0006a41176a2107201f2115024002400240034020152f01202114201528020021132015410c6a2901002111201541146a290100211d2015290104210b201c2015411c6a280100360200201b201d370300201a20113703002004200b3703900102400240200428020c2203280208200ba741ffff0371220a4d0d0020042f019201210e200441c0006a41086a220c2003280200200a4105746a220341096a290000370300200441c0006a41106a220d200341116a2900003703002007200341186a2900003700002004200329000137034020032d0000210341221033220f450d07200f20033a0000200f2004290340370001200f200e3b0120200f41096a200c290300370000200f41116a200d290300370000200f41186a200729000037000020044281808080103702242004200f3602200240200428020c220328020820042f019401220a4b0d00410221034101210a0c290b201541246a2115417f200e411074220e20042f01960122064110746a22082008200e491b4110762110200441b0016a41086a22122003280200200a4105746a220341096a290000370300200441b0016a41106a2205200341116a290000370300200441b0016a41176a2216200341186a290000370000200420032900013703b00120032d000021174101210341c200210a4102210e20182108034020072016290000370000200d2005290300370300200c2012290300370300200420042903b0013703400240200e417f6a2003470d00200441206a20034101109e012004280220210f0b200f200a6a220941606a20173a0000200941616a220320042903403700002007290000210b200d2903002111200c290300211d200920063b0100200341086a201d370000200341106a2011370000200341176a200b3700002004200e3602280240200a41ec01470d00410321030c030b417f2010411074220320082f010022064110746a220920092003491b41107621100240200428020c22032802082008417e6a2f010022094b0d00410221030c030b2012200328020020094105746a220341096a2900003703002005200341116a2900003703002016200341186a290000370000200420032900013703b001200e41016a210e200a41226a210a200841046a210820032d00002117200428022421030c000b0b410221030c280b2004280224210a20034103470d262004200e360288012004200a360284012004200f360280010240201041ffff037141ffff03460d00200428020c220328020820144d0d022010417f732108200c200328020020144105746a220341096a290000370300200d200341116a2900003703002007200341186a2900003700002004200329000137034020032d000021090240200a200e470d0020044180016a200e4101109e01200428028001210f200428028801210e0b200f200e41226c6a220320093a0000200320042903403700012007290000210b200d2903002111200c290300211d200320083b0120200341096a201d370000200341116a2011370000200341186a200b370000200420042802880141016a36028801200228020820134d0d0320022802002103201220044180016a41086a280200360200200c200320134105746a220341096a290000370300200d200341116a2900003703002007200341186a29000037000020042004290380013703b0012004200329000137034020032d0000210e0240200428021822032004280214470d00200441106a20034101109801200428021821030b20042802102003412c6c6a220320042903b0013702002003200e3a000c200341086a20122802003602002003410d6a2004290340370000200341156a200c2903003700002003411d6a200d290300370000200341246a20072900003700002004200428021841016a36021820152019470d010c050b0b200041013b01000c020b20004181043b01000c010b20004181043b0100200428028401210a0b200a450d24200a41226c450d2420042802800110350c240b0240201e450d00201e41246c450d00201f10350b2001280260211f200141e4006a280200211e0240200141e8006a2802002203450d00201f200341286c6a2119200441ca006a2118200441c0006a41186a211c200441c0006a41106a211b200441c0006a41086a211a200441b0016a41176a2107201f2115024002400240034020152f01242114201528020021132015410c6a2901002111201541146a290100211d2015290104210b201c2015411c6a290100370300201b201d370300201a20113703002004200b37034002400240200428020c2203280208200ba741ffff0371220a4d0d0020042f0142210e200441b0016a41086a220c2003280200200a4105746a220341096a290000370300200441b0016a41106a220d200341116a2900003703002007200341186a290000370000200420032900013703b00120032d0000210341221033220f450d07200f20033a0000200f20042903b001370001200f200e3b0120200f41096a200c290300370000200f41116a200d290300370000200f41186a200729000037000020044281808080103702242004200f3602200240200428020c220328020820042f0144220a4b0d00410221034101210a0c250b201541286a2115417f200e411074220e20042f014622064110746a22082008200e491b411076211020044190016a41086a22122003280200200a4105746a220341096a29000037030020044190016a41106a2205200341116a29000037030020044190016a41176a2216200341186a290000370000200420032900013703900120032d000021174101210341c200210a4102210e20182108034020072016290000370000200d2005290300370300200c201229030037030020042004290390013703b0010240200e417f6a2003470d00200441206a20034101109e012004280220210f0b200f200a6a220941606a20173a0000200941616a220320042903b0013700002007290000210b200d2903002111200c290300211d200920063b0100200341086a201d370000200341106a2011370000200341176a200b3700002004200e3602280240200a418e02470d00410321030c030b417f2010411074220320082f010022064110746a220920092003491b41107621100240200428020c22032802082008417e6a2f010022094b0d00410221030c030b2012200328020020094105746a220341096a2900003703002005200341116a2900003703002016200341186a2900003700002004200329000137039001200e41016a210e200a41226a210a200841046a210820032d00002117200428022421030c000b0b410221030c240b2004280224210a20034103470d222004200e360288012004200a360284012004200f360280010240201041ffff037141ffff03460d00200428020c220328020820144d0d022010417f732108200c200328020020144105746a220341096a290000370300200d200341116a2900003703002007200341186a290000370000200420032900013703b00120032d000021090240200a200e470d0020044180016a200e4101109e01200428028001210f200428028801210e0b200f200e41226c6a220320093a0000200320042903b0013700012007290000210b200d2903002111200c290300211d200320083b0120200341096a201d370000200341116a2011370000200341186a200b370000200420042802880141016a36028801200228020820134d0d0320022802002103201220044180016a41086a280200360200200c200320134105746a220341096a290000370300200d200341116a2900003703002007200341186a290000370000200420042903800137039001200420032900013703b00120032d0000210e0240200428021822032004280214470d00200441106a20034101109801200428021821030b20042802102003412c6c6a22032004290390013702002003200e3a000c200341086a20122802003602002003410d6a20042903b001370000200341156a200c2903003700002003411d6a200d290300370000200341246a20072900003700002004200428021841016a36021820152019470d010c050b0b200041013b01000c020b20004181043b01000c010b20004181043b0100200428028401210a0b200a450d20200a41226c450d2020042802800110350c200b0240201e450d00201e41286c450d00201f10350b200128026c211f200141f0006a28020021200240200141f4006a2802002203450d00201f2003412c6c6a211e200441ca006a2119200441e0006a211c200441c0006a41186a211b200441c0006a41106a211a200441c0006a41086a2118200441b0016a41176a2107201f2115024002400240034020152f01282114201528020021132015410c6a2901002111201541146a290100211d2015411c6a29010021212015290104210b201c201541246a280100360200201b2021370300201a201d370300201820113703002004200b37034002400240200428020c2203280208200ba741ffff0371220a4d0d0020042f0142210e200441b0016a41086a220c2003280200200a4105746a220341096a290000370300200441b0016a41106a220d200341116a2900003703002007200341186a290000370000200420032900013703b00120032d0000210341221033220f450d07200f20033a0000200f20042903b001370001200f200e3b0120200f41096a200c290300370000200f41116a200d290300370000200f41186a200729000037000020044281808080103702242004200f3602200240200428020c220328020820042f0144220a4b0d00410221034101210a0c210b2015412c6a2115417f200e411074220e20042f014622064110746a22082008200e491b411076211020044190016a41086a22122003280200200a4105746a220341096a29000037030020044190016a41106a2205200341116a29000037030020044190016a41176a2216200341186a290000370000200420032900013703900120032d000021174101210341c200210a4102210e20192108034020072016290000370000200d2005290300370300200c201229030037030020042004290390013703b0010240200e417f6a2003470d00200441206a20034101109e012004280220210f0b200f200a6a220941606a20173a0000200941616a220320042903b0013700002007290000210b200d2903002111200c290300211d200920063b0100200341086a201d370000200341106a2011370000200341176a200b3700002004200e3602280240200a41b002470d00410321030c030b417f2010411074220320082f010022064110746a220920092003491b41107621100240200428020c22032802082008417e6a2f010022094b0d00410221030c030b2012200328020020094105746a220341096a2900003703002005200341116a2900003703002016200341186a2900003700002004200329000137039001200e41016a210e200a41226a210a200841046a210820032d00002117200428022421030c000b0b410221030c200b2004280224210a20034103470d1e2004200e360288012004200a360284012004200f360280010240201041ffff037141ffff03460d00200428020c220328020820144d0d022010417f732108200c200328020020144105746a220341096a290000370300200d200341116a2900003703002007200341186a290000370000200420032900013703b00120032d000021090240200a200e470d0020044180016a200e4101109e01200428028001210f200428028801210e0b200f200e41226c6a220320093a0000200320042903b0013700012007290000210b200d2903002111200c290300211d200320083b0120200341096a201d370000200341116a2011370000200341186a200b370000200420042802880141016a36028801200228020820134d0d0320022802002103201220044180016a41086a280200360200200c200320134105746a220341096a290000370300200d200341116a2900003703002007200341186a290000370000200420042903800137039001200420032900013703b00120032d0000210e0240200428021822032004280214470d00200441106a20034101109801200428021821030b20042802102003412c6c6a22032004290390013702002003200e3a000c200341086a20122802003602002003410d6a20042903b001370000200341156a200c2903003700002003411d6a200d290300370000200341246a20072900003700002004200428021841016a3602182015201e470d010c050b0b200041013b01000c020b20004181043b01000c010b20004181043b0100200428028401210a0b200a450d1c200a41226c450d1c20042802800110350c1c0b02402020450d002020412c6c450d00201f10350b20012802782120200141fc006a280200211f024020014180016a2802002203450d002020200341306c6a211e200441ca006a2119200441e0006a211c200441c0006a41186a211b200441c0006a41106a211a200441c0006a41086a2118200441b0016a41176a210720202115024002400240034020152f012c2114201528020021132015410c6a2901002111201541146a290100211d2015411c6a29010021212015290104210b201c201541246a290100370300201b2021370300201a201d370300201820113703002004200b37034002400240200428020c2203280208200ba741ffff0371220a4d0d0020042f0142210e200441b0016a41086a220c2003280200200a4105746a220341096a290000370300200441b0016a41106a220d200341116a2900003703002007200341186a290000370000200420032900013703b00120032d0000210341221033220f450d07200f20033a0000200f20042903b001370001200f200e3b0120200f41096a200c290300370000200f41116a200d290300370000200f41186a200729000037000020044281808080103702242004200f3602200240200428020c220328020820042f0144220a4b0d00410221034101210a0c1d0b201541306a2115417f200e411074220e20042f014622064110746a22082008200e491b411076211020044190016a41086a22122003280200200a4105746a220341096a29000037030020044190016a41106a2205200341116a29000037030020044190016a41176a2216200341186a290000370000200420032900013703900120032d000021174101210341c200210a4102210e20192108034020072016290000370000200d2005290300370300200c201229030037030020042004290390013703b0010240200e417f6a2003470d00200441206a20034101109e012004280220210f0b200f200a6a220941606a20173a0000200941616a220320042903b0013700002007290000210b200d2903002111200c290300211d200920063b0100200341086a201d370000200341106a2011370000200341176a200b3700002004200e3602280240200a41d202470d00410321030c030b417f2010411074220320082f010022064110746a220920092003491b41107621100240200428020c22032802082008417e6a2f010022094b0d00410221030c030b2012200328020020094105746a220341096a2900003703002005200341116a2900003703002016200341186a2900003700002004200329000137039001200e41016a210e200a41226a210a200841046a210820032d00002117200428022421030c000b0b410221030c1c0b2004280224210a20034103470d1a2004200e360288012004200a360284012004200f360280010240201041ffff037141ffff03460d00200428020c220328020820144d0d022010417f732108200c200328020020144105746a220341096a290000370300200d200341116a2900003703002007200341186a290000370000200420032900013703b00120032d000021090240200a200e470d0020044180016a200e4101109e01200428028001210f200428028801210e0b200f200e41226c6a220320093a0000200320042903b0013700012007290000210b200d2903002111200c290300211d200320083b0120200341096a201d370000200341116a2011370000200341186a200b370000200420042802880141016a36028801200228020820134d0d0320022802002103201220044180016a41086a280200360200200c200320134105746a220341096a290000370300200d200341116a2900003703002007200341186a290000370000200420042903800137039001200420032900013703b00120032d0000210e0240200428021822032004280214470d00200441106a20034101109801200428021821030b20042802102003412c6c6a22032004290390013702002003200e3a000c200341086a20122802003602002003410d6a20042903b001370000200341156a200c2903003700002003411d6a200d290300370000200341246a20072900003700002004200428021841016a3602182015201e470d010c050b0b200041013b01000c020b20004181043b01000c010b20004181043b0100200428028401210a0b200a450d18200a41226c450d1820042802800110350c180b0240201f450d00201f41306c450d00202010350b200128028401212020014188016a280200212202402001418c016a2802002203450d002020200341346c6a211f200441ca006a211e200441e8006a211c200441e0006a211b200441c0006a41186a211a200441c0006a41106a2118200441c0006a41086a2119200441b0016a41176a210720202115024002400240034020152f01302114201528020021132015410c6a2901002111201541146a290100211d2015411c6a2901002121201541246a29010021232015290104210b201c2015412c6a280100360200201b2023370300201a20213703002018201d370300201920113703002004200b37034002400240200428020c2203280208200ba741ffff0371220a4d0d0020042f0142210e200441b0016a41086a220c2003280200200a4105746a220341096a290000370300200441b0016a41106a220d200341116a2900003703002007200341186a290000370000200420032900013703b00120032d0000210341221033220f450d07200f20033a0000200f20042903b001370001200f200e3b0120200f41096a200c290300370000200f41116a200d290300370000200f41186a200729000037000020044281808080103702242004200f3602200240200428020c220328020820042f0144220a4b0d00410221034101210a0c190b201541346a2115417f200e411074220e20042f014622064110746a22082008200e491b411076211020044190016a41086a22122003280200200a4105746a220341096a29000037030020044190016a41106a2205200341116a29000037030020044190016a41176a2216200341186a290000370000200420032900013703900120032d000021174101210341c200210a4102210e201e2108034020072016290000370000200d2005290300370300200c201229030037030020042004290390013703b0010240200e417f6a2003470d00200441206a20034101109e012004280220210f0b200f200a6a220941606a20173a0000200941616a220320042903b0013700002007290000210b200d2903002111200c290300211d200920063b0100200341086a201d370000200341106a2011370000200341176a200b3700002004200e3602280240200a41f402470d00410321030c030b417f2010411074220320082f010022064110746a220920092003491b41107621100240200428020c22032802082008417e6a2f010022094b0d00410221030c030b2012200328020020094105746a220341096a2900003703002005200341116a2900003703002016200341186a2900003700002004200329000137039001200e41016a210e200a41226a210a200841046a210820032d00002117200428022421030c000b0b410221030c180b2004280224210a20034103470d162004200e360288012004200a360284012004200f360280010240201041ffff037141ffff03460d00200428020c220328020820144d0d022010417f732108200c200328020020144105746a220341096a290000370300200d200341116a2900003703002007200341186a290000370000200420032900013703b00120032d000021090240200a200e470d0020044180016a200e4101109e01200428028001210f200428028801210e0b200f200e41226c6a220320093a0000200320042903b0013700012007290000210b200d2903002111200c290300211d200320083b0120200341096a201d370000200341116a2011370000200341186a200b370000200420042802880141016a36028801200228020820134d0d0320022802002103201220044180016a41086a280200360200200c200320134105746a220341096a290000370300200d200341116a2900003703002007200341186a290000370000200420042903800137039001200420032900013703b00120032d0000210e0240200428021822032004280214470d00200441106a20034101109801200428021821030b20042802102003412c6c6a22032004290390013702002003200e3a000c200341086a20122802003602002003410d6a20042903b001370000200341156a200c2903003700002003411d6a200d290300370000200341246a20072900003700002004200428021841016a3602182015201f470d010c050b0b200041013b01000c020b20004181043b01000c010b20004181043b0100200428028401210a0b200a450d14200a41226c450d1420042802800110350c140b02402022450d00202241346c450d00202010350b200128029001212020014194016a2802002122024020014198016a2802002203450d002020200341386c6a211f200441ca006a211e200441e8006a211c200441e0006a211b200441c0006a41186a211a200441c0006a41106a2118200441c0006a41086a2119200441b0016a41176a210720202115024002400240034020152f01342114201528020021132015410c6a2901002111201541146a290100211d2015411c6a2901002121201541246a29010021232015290104210b201c2015412c6a290100370300201b2023370300201a20213703002018201d370300201920113703002004200b37034002400240200428020c2203280208200ba741ffff0371220a4d0d0020042f0142210e200441b0016a41086a220c2003280200200a4105746a220341096a290000370300200441b0016a41106a220d200341116a2900003703002007200341186a290000370000200420032900013703b00120032d0000210341221033220f450d07200f20033a0000200f20042903b001370001200f200e3b0120200f41096a200c290300370000200f41116a200d290300370000200f41186a200729000037000020044281808080103702242004200f3602200240200428020c220328020820042f0144220a4b0d00410221034101210a0c150b201541386a2115417f200e411074220e20042f014622064110746a22082008200e491b411076211020044190016a41086a22122003280200200a4105746a220341096a29000037030020044190016a41106a2205200341116a29000037030020044190016a41176a2216200341186a290000370000200420032900013703900120032d000021174101210341c200210a4102210e201e2108034020072016290000370000200d2005290300370300200c201229030037030020042004290390013703b0010240200e417f6a2003470d00200441206a20034101109e012004280220210f0b200f200a6a220941606a20173a0000200941616a220320042903b0013700002007290000210b200d2903002111200c290300211d200920063b0100200341086a201d370000200341106a2011370000200341176a200b3700002004200e3602280240200a419603470d00410321030c030b417f2010411074220320082f010022064110746a220920092003491b41107621100240200428020c22032802082008417e6a2f010022094b0d00410221030c030b2012200328020020094105746a220341096a2900003703002005200341116a2900003703002016200341186a2900003700002004200329000137039001200e41016a210e200a41226a210a200841046a210820032d00002117200428022421030c000b0b410221030c140b2004280224210a20034103470d122004200e360288012004200a360284012004200f360280010240201041ffff037141ffff03460d00200428020c220328020820144d0d022010417f732108200c200328020020144105746a220341096a290000370300200d200341116a2900003703002007200341186a290000370000200420032900013703b00120032d000021090240200a200e470d0020044180016a200e4101109e01200428028001210f200428028801210e0b200f200e41226c6a220320093a0000200320042903b0013700012007290000210b200d2903002111200c290300211d200320083b0120200341096a201d370000200341116a2011370000200341186a200b370000200420042802880141016a36028801200228020820134d0d0320022802002103201220044180016a41086a280200360200200c200320134105746a220341096a290000370300200d200341116a2900003703002007200341186a290000370000200420042903800137039001200420032900013703b00120032d0000210e0240200428021822032004280214470d00200441106a20034101109801200428021821030b20042802102003412c6c6a22032004290390013702002003200e3a000c200341086a20122802003602002003410d6a20042903b001370000200341156a200c2903003700002003411d6a200d290300370000200341246a20072900003700002004200428021841016a3602182015201f470d010c050b0b200041013b01000c020b20004181043b01000c010b20004181043b0100200428028401210a0b200a450d10200a41226c450d1020042802800110350c100b02402022450d00202241386c450d00202010350b200128029c012124200141a0016a28020021220240200141a4016a2802002203450d0020242003413c6c6a2120200441ca006a211f200441f0006a211c200441e8006a211b200441e0006a211a200441c0006a41186a2118200441c0006a41106a2119200441c0006a41086a211e200441b0016a41176a210720242115024002400240034020152f01382114201528020021132015410c6a2901002111201541146a290100211d2015411c6a2901002121201541246a29010021232015412c6a29010021252015290104210b201c201541346a280100360200201b2025370300201a2023370300201820213703002019201d370300201e20113703002004200b37034002400240200428020c2203280208200ba741ffff0371220a4d0d0020042f0142210e200441b0016a41086a220c2003280200200a4105746a220341096a290000370300200441b0016a41106a220d200341116a2900003703002007200341186a290000370000200420032900013703b00120032d0000210341221033220f450d07200f20033a0000200f20042903b001370001200f200e3b0120200f41096a200c290300370000200f41116a200d290300370000200f41186a200729000037000020044281808080103702242004200f3602200240200428020c220328020820042f0144220a4b0d00410221034101210a0c110b2015413c6a2115417f200e411074220e20042f014622064110746a22082008200e491b411076211020044190016a41086a22122003280200200a4105746a220341096a29000037030020044190016a41106a2205200341116a29000037030020044190016a41176a2216200341186a290000370000200420032900013703900120032d000021174101210341c200210a4102210e201f2108034020072016290000370000200d2005290300370300200c201229030037030020042004290390013703b0010240200e417f6a2003470d00200441206a20034101109e012004280220210f0b200f200a6a220941606a20173a0000200941616a220320042903b0013700002007290000210b200d2903002111200c290300211d200920063b0100200341086a201d370000200341106a2011370000200341176a200b3700002004200e3602280240200a41b803470d00410321030c030b417f2010411074220320082f010022064110746a220920092003491b41107621100240200428020c22032802082008417e6a2f010022094b0d00410221030c030b2012200328020020094105746a220341096a2900003703002005200341116a2900003703002016200341186a2900003700002004200329000137039001200e41016a210e200a41226a210a200841046a210820032d00002117200428022421030c000b0b410221030c100b2004280224210a20034103470d0e2004200e360288012004200a360284012004200f360280010240201041ffff037141ffff03460d00200428020c220328020820144d0d022010417f732108200c200328020020144105746a220341096a290000370300200d200341116a2900003703002007200341186a290000370000200420032900013703b00120032d000021090240200a200e470d0020044180016a200e4101109e01200428028001210f200428028801210e0b200f200e41226c6a220320093a0000200320042903b0013700012007290000210b200d2903002111200c290300211d200320083b0120200341096a201d370000200341116a2011370000200341186a200b370000200420042802880141016a36028801200228020820134d0d0320022802002103201220044180016a41086a280200360200200c200320134105746a220341096a290000370300200d200341116a2900003703002007200341186a290000370000200420042903800137039001200420032900013703b00120032d0000210e0240200428021822032004280214470d00200441106a20034101109801200428021821030b20042802102003412c6c6a22032004290390013702002003200e3a000c200341086a20122802003602002003410d6a20042903b001370000200341156a200c2903003700002003411d6a200d290300370000200341246a20072900003700002004200428021841016a36021820152020470d010c050b0b200041013b01000c020b20004181043b01000c010b20004181043b0100200428028401210a0b200a450d0c200a41226c450d0c20042802800110350c0c0b02402022450d002022413c6c450d00202410350b20012802a8012122200141ac016a28020021240240200141b0016a2802002203450d00202220034106746a2120200441ca006a211f200441f0006a211c200441e8006a211b200441e0006a211a200441c0006a41186a2118200441c0006a41106a2119200441c0006a41086a211e200441b0016a41176a210720222115024002400240034020152f013c2114201528020021132015410c6a2901002111201541146a290100211d2015411c6a2901002121201541246a29010021232015412c6a29010021252015290104210b201c201541346a290100370300201b2025370300201a2023370300201820213703002019201d370300201e20113703002004200b37034002400240200428020c2203280208200ba741ffff0371220a4d0d0020042f0142210e200441b0016a41086a220c2003280200200a4105746a220341096a290000370300200441b0016a41106a220d200341116a2900003703002007200341186a290000370000200420032900013703b00120032d0000210341221033220f450d07200f20033a0000200f20042903b001370001200f200e3b0120200f41096a200c290300370000200f41116a200d290300370000200f41186a200729000037000020044281808080103702242004200f3602200240200428020c220328020820042f0144220a4b0d00410221034101210a0c0e0b201541c0006a2115417f200e411074220e20042f014622064110746a22082008200e491b411076211020044190016a41086a22122003280200200a4105746a220341096a29000037030020044190016a41106a2205200341116a29000037030020044190016a41176a2216200341186a290000370000200420032900013703900120032d000021174101210341c200210a4102210e201f2108034020072016290000370000200d2005290300370300200c201229030037030020042004290390013703b0010240200e417f6a2003470d00200441206a20034101109e012004280220210f0b200f200a6a220941606a20173a0000200941616a220320042903b0013700002007290000210b200d2903002111200c290300211d200920063b0100200341086a201d370000200341106a2011370000200341176a200b3700002004200e3602280240200a41da03470d00410321030c030b417f2010411074220320082f010022064110746a220920092003491b41107621100240200428020c22032802082008417e6a2f010022094b0d00410221030c030b2012200328020020094105746a220341096a2900003703002005200341116a2900003703002016200341186a2900003700002004200329000137039001200e41016a210e200a41226a210a200841046a210820032d00002117200428022421030c000b0b410221030c0d0b2004280224210a20034103470d0b2004200e360288012004200a360284012004200f360280010240201041ffff037141ffff03460d00200428020c220328020820144d0d022010417f732108200c200328020020144105746a220341096a290000370300200d200341116a2900003703002007200341186a290000370000200420032900013703b00120032d000021090240200a200e470d0020044180016a200e4101109e01200428028001210f200428028801210e0b200f200e41226c6a220320093a0000200320042903b0013700012007290000210b200d2903002111200c290300211d200320083b0120200341096a201d370000200341116a2011370000200341186a200b370000200420042802880141016a36028801200228020820134d0d0320022802002103201220044180016a41086a280200360200200c200320134105746a220341096a290000370300200d200341116a2900003703002007200341186a290000370000200420042903800137039001200420032900013703b00120032d0000210e0240200428021822032004280214470d00200441106a20034101109801200428021821030b20042802102003412c6c6a22032004290390013702002003200e3a000c200341086a20122802003602002003410d6a20042903b001370000200341156a200c2903003700002003411d6a200d290300370000200341246a20072900003700002004200428021841016a36021820152020470d010c050b0b200041013b01000c020b20004181043b01000c010b20004181043b0100200428028401210a0b200a450d09200a41226c450d0920042802800110350c090b0240202441ffffff1f71450d00202210350b20012802b4012126200141b8016a2802002124200141bc016a2802002203450d022026200341c4006c6a2122200441ca006a2120200441f8006a211c200441f0006a211b200441e8006a211a200441e0006a2118200441c0006a41186a2119200441c0006a41106a211e200441c0006a41086a211f200441b0016a41176a21072026211502400240034020152f01402114201528020021132015410c6a290100210b201541146a29010021112015411c6a290100211d201541246a29010021212015412c6a2901002123201541346a290100212520152901042127201c2015413c6a280100360200201b2025370300201a2023370300201820213703002019201d370300201e2011370300201f200b3703002004202737034002400240200428020c220328020820042f0140220a4d0d0020042f0142210e200441b0016a41086a220c2003280200200a4105746a220341096a290000370300200441b0016a41106a220d200341116a2900003703002007200341186a290000370000200420032900013703b00120032d0000210341221033220f450d05200f20033a0000200f20042903b001370001200f200e3b0120200f41096a200c290300370000200f41116a200d290300370000200f41186a200729000037000020044281808080103702242004200f3602200240200428020c220328020820042f0144220a4b0d00410221034101210a0c090b201541c4006a2115417f200e411074220e20042f014622064110746a22082008200e491b411076211020044190016a41086a22122003280200200a4105746a220341096a29000037030020044190016a41106a2205200341116a29000037030020044190016a41176a2216200341186a290000370000200420032900013703900120032d000021174101210341c200210a4102210e20202108034020072016290000370000200d2005290300370300200c201229030037030020042004290390013703b0010240200e417f6a2003470d00200441206a20034101109e012004280220210f0b200f200a6a220941606a20173a0000200941616a220320042903b0013700002007290000210b200d2903002111200c290300211d200920063b0100200341086a201d370000200341106a2011370000200341176a200b3700002004200e3602280240200a41fc03470d00410321030c030b417f2010411074220320082f010022064110746a220920092003491b41107621100240200428020c22032802082008417e6a2f010022094b0d00410221030c030b2012200328020020094105746a220341096a2900003703002005200341116a2900003703002016200341186a2900003700002004200329000137039001200e41016a210e200a41226a210a200841046a210820032d00002117200428022421030c000b0b410221030c080b2004280224210a20034103470d062004200e360288012004200a360284012004200f360280010240201041ffff037141ffff03460d00200428020c220328020820144d0d022010417f732108200c200328020020144105746a220341096a290000370300200d200341116a2900003703002007200341186a290000370000200420032900013703b00120032d000021090240200a200e470d0020044180016a200e4101109e01200428028001210f200428028801210e0b200f200e41226c6a220320093a0000200320042903b0013700012007290000210b200d2903002111200c290300211d200320083b0120200341096a201d370000200341116a2011370000200341186a200b370000200420042802880141016a36028801200228020820134d0d0320022802002103201220044180016a41086a280200360200200c200320134105746a220341096a290000370300200d200341116a2900003703002007200341186a290000370000200420042903800137039001200420032900013703b00120032d0000210e0240200428021822032004280214470d00200441106a20034101109801200428021821030b20042802102003412c6c6a22032004290390013702002003200e3a000c200341086a20122802003602002003410d6a20042903b001370000200341156a200c2903003700002003411d6a200d290300370000200341246a20072900003700002004200428021841016a36021820152022470d010c060b0b200041013b01000c030b20004181043b01000c020b20004181043b0100200428028401210a0c010b1045000b200a450d03200a41226c450d0320042802800110350c030b02402024450d00202441c4006c450d00202610350b200041003a0000200041046a20042903103702002000410c6a200441186a2802003602000c370b200a450d00200a41226c450d00200f10350b200041013a0000200020033a00010b41002102200441106a210802402024450d00202441c4006c450d00202610350b41002109410021050c060b200a450d00200a41226c450d00200f10350b200041013a0000200020033a00010b4100210941012102200441106a21080240202441ffffff1f710d00410021050c040b20221035410021050c030b200a450d00200a41226c450d00200f10350b200041013a0000200020033a00010b4100210541012102200441106a210802402022450d002022413c6c450d00202410350b410121090b410021160c030b200a450d00200a41226c450d00200f10350b200041013a0000200020033a00010b4100211641012102200441106a210802402022450d00202241386c450d00202010350b41012109410121050b410021170c030b200a450d00200a41226c450d00200f10350b200041013a0000200020033a00010b4100211741012102200441106a210802402022450d00202241346c450d00202010350b4101210941012105410121160b410021150c030b200a450d00200a41226c450d00200f10350b200041013a0000200020033a00010b4100211541012102200441106a21080240201f450d00201f41306c450d00202010350b410121094101210541012116410121170b410021070c030b200a450d00200a41226c450d00200f10350b200041013a0000200020033a00010b4100210741012102200441106a210802402020450d002020412c6c450d00201f10350b41012109410121054101211641012117410121150b4100210c0c030b200a450d00200a41226c450d00200f10350b200041013a0000200020033a00010b4100210c41012102200441106a21080240201e450d00201e41286c450d00201f10350b4101210941012105410121164101211741012115410121070b410021000c030b200a450d00200a41226c450d00200f10350b200041013a0000200020033a00010b4100210041012102200441106a21080240201e450d00201e41246c450d00201f10350b4101210941012105410121164101211741012115410121074101210c0b4100210d0c030b200a450d00200a41226c450d00200f10350b200041013a0000200020033a00010b4100210d41012102200441106a21080240201e41ffffff3f71450d00201910350b4101210941012105410121164101211741012115410121074101210c410121000b4100210f0c030b200a450d00200a41226c450d00200f10350b200041013a0000200020033a00010b4100210f41012102200441106a21080240201e450d00201e411c6c450d00201910350b4101210941012105410121164101211741012115410121074101210c410121004101210d0b410021100c030b200a450d00200a41226c450d00200f10350b200041013a0000200020033a00010b4100211041012102200441106a210802402019450d00201941186c450d00201810350b4101210941012105410121164101211741012115410121074101210c410121004101210d4101210f0b410021120c030b200a450d00200a41226c450d00200f10350b200041013a0000200020033a00010b4100211241012102200441106a210802402019450d00201941146c450d00201810350b4101210941012105410121164101211741012115410121074101210c410121004101210d4101210f410121100b41002114410021060c040b4100211441012102200441106a21080240201541ffffffff0071450d00201710350b4101210941012105410121164101211741012115410121074101210c410121004101210d4101210f4101211041012112410021060c030b20004181043b0100200310350c010b20004181043b01000b41012102200441106a21080240200541ffffffff0171450d00200610350b4101210941012105410121164101211741012115410121074101210c410121004101210d4101210f410121104101211241012114410121060b02402004280218220e450d0020042802102103200e412c6c210e03400240200341046a280200220a450d00200a41226c450d00200328020010350b2003412c6a2103200e41546a220e0d000b0b0240200841046a2802002203450d002003412c6c450d00200828020010350b02402006450d00200141106a2802002203450d002003410c6c450d00200128020c10350b02402014450d002001411c6a28020041ffffffff0071450d00200128021810350b02402012450d00200141286a2802002203450d00200341146c450d00200128022410350b02402010450d00200141346a2802002203450d00200341186c450d00200128023010350b0240200f450d00200141c0006a2802002203450d002003411c6c450d00200128023c10350b0240200d450d00200141cc006a28020041ffffff3f71450d00200128024810350b02402000450d00200141d8006a2802002203450d00200341246c450d00200128025410350b0240200c450d00200141e4006a2802002203450d00200341286c450d00200128026010350b02402007450d00200141f0006a2802002203450d002003412c6c450d00200128026c10350b02402015450d00200141fc006a2802002203450d00200341306c450d00200128027810350b02402017450d0020014188016a2802002203450d00200341346c450d0020012802840110350b02402016450d0020014194016a2802002203450d00200341386c450d0020012802900110350b02402005450d00200141a0016a2802002203450d002003413c6c450d00200128029c0110350b02402009450d00200141ac016a28020041ffffff1f71450d0020012802a80110350b2002450d00200141b8016a2802002203450d00200341c4006c450d0020012802b40110350b200441d0016a24000bb00401087f230041e0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100510c20102400240200328021022010d00200041023a00100c010b200328021421042003200341106a41086a28020036022420032001360220200341c8006a200341206a10c301024002400240024020032802482205450d00200328024c2106024002400240200328022422024104490d00200341c8006a41086a280200210720032002417c6a220836022420032003280220220941046a220a3602202008450d012009280000210920032002417b6a3602242003200a41016a360220200a2d0000220a41014b0d0141002102200a0e020504050b200641ffffff3f710d010c020b200641ffffff3f71450d010b200510350b20034100360230200342013703282003410936023c2003200341086a3602382003200341286a360244200341dc006a41013602002003420137024c200341c888c2003602482003200341386a360258200341c4006a41e88ac500200341c8006a10431a200335023042208620033502288410060240200328022c450d00200328022810350b410221020c020b410121020b200341386a41026a200341286a41026a2d0000220a3a0000200341c8006a41026a200a3a0000200320032f002822083b01382000200936020c200020073602082000200636020420002005360200200320083b0148200041136a200a3a0000200020083b00110b200020023a00102004450d00200110350b200341e0006a24000bcb0f0a0f7f017e087f017e017f017e017f027e047f057e230041d0026b22022400200141086a2802002103200128020421042000280204210520002802002106024020002802082207200028020c2208460d0020012802002109200241f0006a410c6a210a200241f0006a410472210b200241c8006a41086a210c200241c8006a41106a210d200241c8006a41186a210e200241c8006a41206a210f0340200c20072200410c6a290200370300200d200041146a290200370300200e2000411c6a290200370300200f200041246a290200370300200220002902043703482000412c6a210720002802002210450d01200b2002290348370200200b41086a200c290300370200200b41106a200d290300370200200b41186a200e290300370200200b41206a200f29030037020020022010360270200a10c8012111200241a0016a41086a2212200a41086a290200370300200241a0016a41106a2213200a41106a290200370300200241a0016a41186a2214200a41186a2902003703002002200a2902003703a00120022802742115024002400240200228027841226c2201450d00201021000340200041206a2f01002116200241b0026a41186a2217200041186a290000370300200241b0026a41106a2218200041106a290000370300200241b0026a41086a2219200041086a290000370300200220002900003703b00220160d02200041226a21002001415e6a22010d000b0b4200211a4108211b4100210002402015450d00201541226c450d00201010354200211a0b4200211c4100211d0c010b200241386a2011420042ffff034200109808200241286a2002290338221e200241386a41086a290300221f4281807c427f108408200241186a201e201f2016ad4200108408200241d0016a41086a22202019290300370300200241d0016a41106a22212018290300370300200241d0016a41186a22222017290300370300200220022903b002221c3703f0012002201c3703d0012016200229032820117ca722236c221641ffff036e211d2002290318211c200241186a41086a29030021240240024041301033221b450d00201b201c201d417f20164180807c491b2016201d4181807c6c6a41ffff014b6aad42ffff03837c221a370320201b20022903d001370300201b41286a2024201a201c54ad7c221c370300201b41186a2022290300370300201b41106a2021290300370300201b41086a202029030037030020024281808080103702c4012002201b3602c001024020014122470d004101211d0c020b200141bc7f6a21214101211d410021160340200020166a220141c2006a2f0100212020172001413a6a2900003703002018200141326a29000037030020192001412a6a2900003703002002200141226a2900003703b0020240024020200d0020212016460d040c010b200241086a201e201f2020ad4200108408200241f0016a41086a20192903002224370300200241f0016a41106a20182903002225370300200241f0016a41186a20172903002226370300200220022903b00222273703f001201720263703002018202537030020192024370300200220273703b002201a20022903082225202020236c220141ffff036e2220417f20014180807c491b200120204181807c6c6a41ffff014b6aad42ffff03837c22247c2226201a542201201c200241086a41086a2903002024202554ad7c22257c2001ad7c221a201c54201a201c511b21010240201d20022802c401470d00200241c0016a201d410110880120022802c001211b0b427f201a20011b211c427f202620011b211a201b201d41306c6a220120022903b00237030020192903002126201829030021272017290300212820012024370320200141286a2025370300200141186a2028370300200141106a2027370300200141086a20263703002002201d41016a221d3602c80120212016460d030b201641226a21160c000b0b1045000b02402015450d00201541226c450d00201010350b20022802c40121000b024002402011201a7d22252011564200201c2011201a54ad7c7d22244200522024501b4101470d00201a20117d2224201a56201c201a201154ad7d2225201c56201a20115a1b0d01201d450d01201d41306c201b6a41706a220142002001290300221c20247d221a201a201c56200141086a2201290300221a20257d201c202454ad7d221c201a56201c201a511b22171b37030020014200201c20171b3703000c010b201d450d00201d41306c201b6a41706a2201427f2001290300221c20257c221a201a201c542217200141086a2201290300221c20247c2017ad7c221a201c54201a201c511b22171b3703002001427f201a20171b3703000b200241b0026a41186a22012014290300370300200241b0026a41106a22172013290300370300200241b0026a41086a22182012290300370300200220022903a0013703b002200920003602042009201d3602082009201b360200200920022903b00237020c200941146a20182903003702002009411c6a2017290300370200200941246a2001290300370200200341016a21032009412c6a210920072008470d000b200821070b20042003360200200820076b2200412c6d210102402000450d002001412c6c210003400240200741046a2802002201450d00200141226c450d00200728020010350b2007412c6a2107200041546a22000d000b0b02402005450d002005412c6c450d00200610350b200241d0026a24000b880303057f017e027f02400240024020002802202201450d00034020002001417f6a36022020002802042201450d0320002802082102200028020021030240200028020c220420012f0106490d00034002400240200128020022050d002002ad2106410021050c010b200341016a210320013301044220862002ad8421060b200110352006a72102200521012006422088a7220420052f01064f0d000b200521010b200441016a2107200120044105746a220541fc026a2802002104200541f8026a280200210802402003450d00200120074102746a41c8056a2802002101410021072003417f6a2205450d00034020012802c80521012005417f6a22050d000b0b2000200736020c2000200236020820002001360204200041003602002008450d0202402004450d00200441306c450d00200810350b200028022022010d000b0b200028020421010b02402001450d0020012802002105200110352005450d00034020052802002101200510352001210520010d000b0b0f0b41958dcc00412b41c08dcc00103f000b13002000411c360204200041c8f4c1003602000be60203047f017e017f024020002802002201450d0020002802082102024020002802042200450d00034020012802e40121012000417f6a22000d000b0b02402002450d0041002103024003402001450d01410021040240200320012f0106490d00034002400240200128020022000d0041002103410021000c010b200441016a210420012f010421030b2001103520002101200320002f01064f0d000b200021010b200341016a210020012003410c6c6a220341e4006a2902002105200341e0006a28020021060240024020040d00200021030c010b200120004102746a41e4016a2802002101410021032004417f6a2200450d00034020012802e40121012000417f6a22000d000b0b2006450d022002417f6a210202402005a7450d00200610350b20020d000c020b0b41958dcc00412b41c08dcc00103f000b2001450d0020012802002100200110352000450d00034020002802002101200010352001210020010d000b0b0b9a9e0106047f017e087f047e287f037e230041c0056b22002400200041b0036a41186a4200370300200041b0036a41106a22014200370300200041b0036a41086a22024200370300200042003703b00341a0e4cb00ad42808080808002841001220329000021042002200341086a290000370300200020043703b0032003103541e1b8c800ad4280808080a0018410012203290000210420004190056a41086a2205200341086a29000037030020002004370390052003103520012000290390052204370300200041f8026a41086a2002290300370300200041f8026a41106a2004370300200041f8026a41186a2005290300370300200020002903b0033703f802200041b0036a200041f8026a10fe010240024020002802b00322020d004100210620004100360298022000420137039002410121020c010b200020002902b40322043702940220002002360290022004422088a721060b024002400240200641ffffff3f712006470d0020064105742203417f4c0d000240024020030d00410121050c010b200310332205450d020b200041003602b803200020053602b003200020034105763602b403200041b0036a41002006108a0120002802b80321070240024020060d0020002802b00321080c010b2006410574210520002802b003220820074105746a2103034020032002290000370000200341186a200241186a290000370000200341106a200241106a290000370000200341086a200241086a290000370000200341206a2103200241206a2102200541606a22050d000b200641057441606a41057620076a41016a21070b20002802b4032109200041b0036a41186a22054200370300200041b0036a41106a220a4200370300200041b0036a41086a22024200370300200042003703b00341a0e4cb00ad42808080808002841001220329000021042002200341086a290000370300200020043703b003200310354189eaca00ad4280808080f0008410012203290000210420004190056a41086a220b200341086a2900003703002000200437039005200310352001200029039005370000200141086a200b290300370000200041f8026a41086a2002290300370300200041f8026a41106a200a290300370300200041f8026a41186a2005290300370300200020002903b0033703f802200041b0036a200041f8026a10a20220002802b003210220002902b4032104200041003602b803200042013703b003200041b0036a41002004420020021b2204422088a7220341306c220a41306d108a012004a7210b2002410820021b210c20002802b803210502402003450d0020002802b00320054105746a2102200c21030340200341086a2900002104200341106a290000210d2003290000210e200241186a200341186a290000370000200241106a200d370000200241086a20043700002002200e370000200541016a2105200241206a2102200341306a2103200a41506a220a0d000b0b200020053602b8030240200b450d00200b41306c450d00200c10350b20002802b403210320002802b003210220004190026a20062005108a01200028029002200028029802220a4105746a20022005410574109d081a2000200a20056a220b360298020240200341ffffff3f71450d00200210350b200041b0036a41186a22054200370300200041b0036a41106a220a4200370300200041b0036a41086a22024200370300200042003703b00341a0e4cb00ad42808080808002841001220329000021042002200341086a290000370300200020043703b0032003103541c699c200ad428080808090018410012203290000210420004190056a41086a2206200341086a2900003703002000200437039005200310352001200029039005370000200141086a2006290300370000200041f8026a41086a2002290300370300200041f8026a41106a200a290300370300200041f8026a41186a2005290300370300200020002903b0033703f802200041b0036a200041f8026a10a20220002802b003210220002902b4032104200041003602b803200042013703b003200041b0036a41002004420020021b2204422088a7220341306c220a41306d108a012004a721062002410820021b210120002802b803210502402003450d0020002802b00320054105746a2102200121030340200341086a2900002104200341106a290000210d2003290000210e200241186a200341186a290000370000200241106a200d370000200241086a20043700002002200e370000200541016a2105200241206a2102200341306a2103200a41506a220a0d000b0b200020053602b80302402006450d00200641306c450d00200110350b20002802b403210320002802b003210220004190026a200b2005108a01200028029002200028029802220a4105746a20022005410574109d081a2000200a20056a360298020240200341ffffff3f71450d00200210350b41a0e4cb00ad4280808080800284100122022900002104200041f0046a41086a2203200241086a290000370300200020043703f004200210354190eaca00ad4280808080e0008410012202290000210420004190056a41086a2205200241086a290000370300200020043703900520021035412010332202450d01200220002903f0043700002002200029039005370010200241086a2003290300370000200241186a220a2005290300370000412010332203450d0120032002290000370000200341186a200a290000370000200341106a200241106a290000370000200341086a200241086a290000370000200041b8026a41026a2205200041b0036a41026a2d00003a0000200020002f00b0033b01b802200041d8026a41106a42a08080808004370300200041003a00f002200020023602e402200042a080808080043702dc02200020033602d802200041f3026a20052d00003a0000200020002f01b8023b00f102200020004190056a3602f402200041b0036a200041d8026a10a3020240024020002802e0032205450d00200041f0046a41186a220a200041b0036a41186a290300370300200041f0046a41106a2206200041b0036a41106a290300370300200041f0046a41086a220b200041b0036a41086a290300370300200020002903b0033703f004200041d8036a290300210d20002903d003210e20002902e403210f200041f8026a41186a4200370300200041f8026a41106a22014200370300200041f8026a41086a22024200370300200042003703f80241b6fdc600ad42808080808001841001220329000021042002200341086a290000370300200020043703f8022003103541e489c200ad4280808080d00184100122032900002104200041b0056a41086a220c200341086a290000370300200020043703b00520031035200120002903b005220437030020004190056a41086a200229030037030020004190056a41106a200437030020004190056a41186a200c290300370300200020002903f80237039005200041f8016a20004190056a412010d701200041e8016a200029038002200041f8016a41106a290300427f420010980820002802f8012102200041b0046a41186a2203200a290300370300200041b0046a41106a2006290300370300200041b0046a41086a200b290300370300200020002903f0043703b004200041e8016a41086a290300210420002903e8012110413810332211450d03200041d8016a200e200d2010420020021b2210420120104201562004420020021b22044200522004501b22021b2004420020021b109808201120002903b0043703082011200f37022c20112005360228201141106a200041b0046a41086a2202290300370300201141186a200041b0046a41106a2205290300370300201141206a2003290300370300201120002903d80137030020004281808080103702a402200020113602a0022003200041d8026a41186a2903003703002005200041d8026a41106a2903003703002002200041d8026a41086a290300370300200020002903d8023703b004200041b0036a200041b0046a10a3020240024020002802e003220b0d00410121120c010b200041b0036a41286a21134138210a41012106410121030340200041d0046a41186a220c200041b0036a41186a290300370300200041d0046a41106a2214200041b0036a41106a290300370300200041d0046a41086a2215200041b0036a41086a290300370300200020002903b0033703d0042013290300210d20002902e403210e20002903d003210f200041f8026a41186a22164200370300200041f8026a41106a22174200370300200041f8026a41086a22024200370300200042003703f80241b6fdc600ad42808080808001841001220529000021042002200541086a290000370300200020043703f8022005103541e489c200ad4280808080d00184100122052900002104200041b0056a41086a2218200541086a290000370300200020043703b00520051035200120002903b005370000200141086a201829030037000020004190056a41086a200229030037030020004190056a41106a201729030037030020004190056a41186a2016290300370300200020002903f80237039005200041c0016a20004190056a412010d701200041b0016a20002903c801200041c0016a41106a290300427f4200109808200041a0016a200f200d20002903b001420020002802c00122021b220442012004420156200041b0016a41086a290300420020021b22044200522004501b22021b2004420020021b109808200041f0046a41186a2205200c290300370300200041f0046a41106a220c2014290300370300200041f0046a41086a22142015290300370300200020002903d0043703f00420002903a0012104024020032006470d00200041a0026a20064101108b0120002802a00221110b2011200a6a22022004370300200241086a20002903f00437030020052903002104200c290300210d2014290300210f2002412c6a200e370200200241286a200b360200200241106a200f370300200241186a200d370300200241206a20043703002000200341016a22023602a802200041b0036a200041b0046a10a302024020002802e003220b450d00200a41386a210a20002802a4022106200221030c010b0b200341016a21120b024020002802b404450d0020002802b00410350b0240200041c0046a280200450d0020002802bc0410350b20002802a40221190c010b024020002802dc02450d0020002802d80210350b4108211141002112024020002802e802450d0020002802e40210350b410021190b20004190056a41086a20004190026a41086a2802003602002000200029039002370390052012ad42387e2204422088a70d002004a72202417f4c0d000240024020020d00410821030c010b200210332203450d020b2000410036028003200020033602f8022000200241386e3602fc02200041f8026a41002012108b01200028028003210102402012450d00201241386c210a20002802f802200141386c6a2102201241037441786a410376210b200041b0036a41286a2106200041b0036a41086a2105201121030340200541186a200341206a290300370300200541106a200341186a290300370300200541086a200341106a2903003703002005200341086a290300370300200020032903003703b0032006200341286a10a402200241306a200041b0036a41306a290300370300200241286a2006290300370300200241206a200041b0036a41206a290300370300200241186a200041b0036a41186a290300370300200241106a200041b0036a41106a290300370300200241086a2005290300370300200220002903b003370300200241386a2102200341386a2103200a41486a220a0d000b2001200b6a41016a21010b4108210a200041b0036a41086a22022001360200200020002903f8023703b003200041a0026a4114410020004190056a200041b0036a10ca010240024020002802a002220c0d0041012118200041013a00b403200041093a00b00341b0b4cc004100200041b0036a10d401200041f8026a2101200041b0036a21060c010b200041a0026a41146a2802002115200041a0026a41106a2802002116200041ac026a2802002101200041a0026a41086a280200210b20002802a402211442002104200041b0036a41186a4200370300200041b0036a41106a221a420037030020024200370300200042003703b00341a0e4cb00ad428080808080028410012203290000210d200041f0046a41086a2205200341086a2900003703002000200d3703f0042003103520022005290300370300200020002903f0043703b0034189eaca00ad4280808080f0008410012203290000210d20004190056a41086a2205200341086a2900003703002000200d3703900520031035201a200029039005220d370300200041f8026a41086a2002290300370300200041f8026a41106a200d370300200041f8026a41186a2005290300370300200020002903b0033703f802200041b0036a200041f8026a10a202024020002802b0032202450d00200041f8026aad4280808080800484100720002902b40321042002210a0b200041003602b803200042013703b003200041b0036a41002004422088a7220241306c220541306d108a012004a7210620002802b803211b02402002450d0020002802b003201b4105746a2102200a21030340200341086a2900002104200341106a290000210d2003290000210e200241186a200341186a290000370000200241106a200d370000200241086a20043700002002200e370000201b41016a211b200241206a2102200341306a2103200541506a22050d000b0b2000201b3602b80302402006450d00200641306c450d00200a10350b20002802b403211c20002802b003211d42002104200041b0036a41186a22054200370300200041b0036a41106a220642003703004108210a200041b0036a41086a22024200370300200042003703b00341a0e4cb00ad428080808080028410012203290000210d200041f0046a41086a2217200341086a2900003703002000200d3703f0042003103520022017290300370300200020002903f0043703b00341c699c200ad428080808090018410012203290000210d20004190056a41086a2217200341086a2900003703002000200d3703900520031035201a200029039005370000201a41086a2017290300370000200041f8026a41086a2002290300370300200041f8026a41106a2006290300370300200041f8026a41186a2005290300370300200020002903b0033703f802200041b0036a200041f8026a10a202024020002802b0032202450d00200041f8026aad4280808080800484100720002902b40321042002210a0b200041003602b803200042013703b003200041b0036a41002004422088a7220241306c220541306d108a012004a7210620002802b803211e02402002450d0020002802b003201e4105746a2102200a21030340200341086a2900002104200341106a290000210d2003290000210e200241186a200341186a290000370000200241106a200d370000200241086a20043700002002200e370000201e41016a211e200241206a2102200341306a2103200541506a22050d000b0b2000201e3602b80302402006450d00200641306c450d00200a10350b20002802b403211f20002802b0032120024002400240200b41306c2203450d00200c21020340200241286a2903002104200241206a290300210d200041f8026a41186a200241186a290000370300200041f8026a41106a200241106a290000370300200041f8026a41086a200241086a290000370300200020022900003703f802200d2004844200520d02200241306a2102200341506a22030d000b0b410121214100210b02402014450d00201441306c450d00200c10350b410021220c010b200041b0046a41086a2205200041f8026a41086a290300370300200041b0046a41106a220a200041f8026a41106a290300370300200041b0046a41186a2206200041f8026a41186a290300370300200020002903f80222043703d004200020043703b004412010332221450d03202120002903b004370000202141186a2006290300370000202141106a200a290300370000202141086a200529030037000020004281808080103702b403200020213602b0030240024020034130470d004101210b0c010b200241306a2105200c200b41306c6a220641506a21174101210b03402005210202400340200241286a2903002104200241206a290300210d200041f8026a41186a2203200241186a290000370300200041f8026a41106a2205200241106a290000370300200041f8026a41086a220a200241086a290000370300200020022900003703f802200d2004844200520d012006200241306a2202470d000c030b0b20004190056a41086a200a290300220437030020004190056a41106a2005290300220d37030020004190056a41186a2003290300220e370300200020002903f802220f37039005200041d0046a41186a220a200e370300200041d0046a41106a2218200d370300200041d0046a41086a221320043703002000200f3703d0040240200b20002802b403470d00200041b0036a200b4101108a0120002802b00321210b200241306a21052021200b4105746a220320002903d004370000200341186a200a290300370000200341106a2018290300370000200341086a20132903003700002000200b41016a220b3602b80320172002470d000b0b02402014450d00201441306c450d00200c10350b20002802b40321220b200020004190056a3602f0042000410036029805200042043703900520004190056a41002015412c6c2203412c6d109801200028029005210520002802980521022000200120036a3602bc03200020013602b803200020163602b403200020013602b0032000200041f0046a3602c003200041f8026a41086a22162002360200200020004190056a41086a22233602fc02200020052002412c6c6a3602f802200041b0036a200041f8026a10a5022000280294052124200041b0036a2021200b2000280290052225200028029805222610cc01200041b8026a41086a200041b0036a41086a2217280200360200200020002903b0033703b802200041003602d804200042083703d004200041d0046a4100200b410574220241057510880120002802d804212720002802d004212802402002450d00202120026a21292028202741306c6a2101200041f8026a41106a211541b6fdc600ad4280808080800184210f2021210b0340200b41086a2900002104200b41106a290000210d200b290000210e200041b0036a41186a2218200b41186a290000370300200041b0036a41106a2213200d370300201720043703002000200e3703b0030240024020002802b8022206450d00200b41206a210b20002802bc02210c0340200641086a210320062f01062214410574210241002105024003402002450d01200041b0036a2003412010a008220a450d04200241606a2102200541016a2105200341206a2103200a417f4a0d000b2005417f6a21140b200c450d01200c417f6a210c200620144102746a41c8056a28020021060c000b0b41b894ca0041da00419495ca001064000b200041f0046a41186a22032018290300370300200041f0046a41106a220a2013290300370300200041f0046a41086a220c2017290300370300200020002903b0033703f004200620054105746a220241f0026a290300210d200241e8026a290300210e200041f8026a41186a220542003703002015420037030020164200370300200042003703f802200f1001220229000021042016200241086a290000370300200020043703f8022002103541e489c200ad4280808080d00184100122022900002104200041b0056a41086a2206200241086a290000370300200020043703b00520021035201520002903b005370000201541086a20062903003700002023201629030037030020004190056a41106a201529030037030020004190056a41186a2005290300370300200020002903f8023703900520004188016a20004190056a412010d701200041f8006a20002903900120004188016a41106a290300427f4200109808200041e8006a2000290378420020002802880122021b220442012004420156200041f8006a41086a290300420020021b22044200522004501b22021b2004420020021b200e200d108408200141186a2003290300370300200141106a200a290300370300200141086a200c290300370300200120002903f004370300200141286a200041e8006a41086a29030037030020012000290368370320202741016a2127200141306a2101200b2029470d000b0b200020273602d8040240202241ffffff3f71450d00202110350b20002802d404212a024002402027410d2027410d491b222b0d00200041003602b803200042083703b003200041b0036a4100410010880120002802b80321290c010b202b41306c220510332202450d03200041003602b8032000202b3602b403200020023602b003200041b0036a4100202b10880120002802b00320002802b803222941306c6a2102202821030340200341086a2903002104200341106a290300210d200341186a290300210e2003290300210f200241286a200341286a290300370300200241206a200341206a290300370300200241186a200e370300200241106a200d370300200241086a20043703002002200f370300200241306a2102202941016a2129200341306a2103200541506a22050d000b200020293602b8030b20002802b403212c20002802b00321170240024020294115490d002029410176ad42307e2204422088a70d032004a7222d417f4c0d03202d1033222e450d042000410036028003200042043703f802201741506a212f201741f07e6a21304104210541002103410021312029212303402023210b410021234101210c0240200b417f6a2206450d000240024002400240024002402017200641306c6a200b41306c220220176a41a07f6a412010a0084100480d00200b417e6a2101203020026a2102410021234100210a034002402001200a470d00200b210c0c080b200a41016a210a200241306a2002412010a0082106200241506a21022006417f4a0d000b200a41016a210c200a417f73200b6a21060c010b2030200b41066c41037422146a210202400340024020064101470d00410021060c020b2006417f6a2106200241306a2002412010a008210a200241506a2102200a4100480d000b0b200b2006490d01200b20294b0d02200b20066b220c4101762201450d00202f20146a21022017200641306c6a210a0340200041b0036a41286a2214200a41286a2215290300370300200041b0036a41206a2216200a41206a2218290300370300200041b0036a41186a2213200a41186a2223290300370300200041b0036a41106a2221200a41106a2222290300370300200041b0036a41086a2232200a41086a22332903003703002000200a2903003703b003200241086a22342903002104200241106a2235290300210d200241186a2236290300210e200241206a2237290300210f200241286a22382903002110200a2002290300370300201520103703002018200f3703002023200e3703002022200d370300203320043703002038201429030037030020372016290300370300203620132903003703002035202129030037030020342032290300370300200220002903b003370300200241506a2102200a41306a210a2001417f6a22010d000b0b024020060d00200621230c050b0240200c41094d0d00200621230c050b200b20294b0d02200b20066b21012017200641306c6a21140340200b2006417f6a2223490d040240200b20236b220c4102490d002017200641306c6a22022017202341306c6a2206412010a008417f4a0d002006290300210420062002290300370300200041b0036a41286a2213200641286a220a290300370300200041b0036a41206a2221200641206a2215290300370300200041b0036a41186a2222200641186a2216290300370300200041b0036a41106a2232200641106a2218290300370300200041b0036a41086a2233200641086a22342903003703002034200241086a2903003703002018200241106a2903003703002016200241186a2903003703002015200241206a290300370300200a200241286a290300370300200020043703b003410121180240200c4103490d00200641e0006a200041b0036a412010a008417f4a0d004102210a2014210202400340200241286a200241d8006a290300370300200241206a200241d0006a290300370300200241186a200241c8006a290300370300200241106a200241c0006a290300370300200241086a200241386a2903003703002002200241306a22152903003703002001200a460d01200241e0006a2116200a211820152102200a41016a210a2016200041b0036a412010a008417f4a0d020c000b0b200a21180b2006201841306c6a220220002903b003370300200241286a2013290300370300200241206a2021290300370300200241186a2022290300370300200241106a2032290300370300200241086a20332903003703000b2023450d05201441506a2114200141016a210120232106200c410a4f0d050c000b0b2006200b41eccfca001059000b200b202941eccfca001058000b200b2006417f6a2223490d00200b202941fccfca001058000b2023200b41fccfca001059000b0240203120002802fc02470d00200041f8026a2031410110900120002802f8022105200028028003220321310b200520314103746a2202200c360204200220233602002000200341016a22033602800320032131024020034102490d000240024003400240024002400240024020052003417f6a4103746a2202280200450d00200341037420056a220141746a28020022062002280204220a4b0d010b20034103490d022002280204210a20052003417d6a22164103746a28020421020c010b41022131200341024d0d0620052003417d6a22164103746a2802042202200a20066a4d0d0041032131200341034d0d06200141646a280200200220066a4b0d050b2002200a490d010b2003417e6a21160b02400240024002400240024002402003201641016a22184d0d00200320164d0d012005201641037422216a2202280204222220022802006a22022005201841037422326a22032802002213490d02200220294b0d032017201341306c6a22142003280204221541306c22036a210a200241306c2105200220136b220120156b220220154f0d04202e200a200241306c2203109d08220c20036a210620154101480d0520024101480d05202f20056a2103200a210203402003200241506a220a200641506a22012001200a412010a008410048220b1b2205290300370300200341286a200541286a290300370300200341206a200541206a290300370300200341186a200541186a290300370300200341106a200541106a290300370300200341086a200541086a29030037030020062001200b1b210602402014200a2002200b1b2202490d00200c21050c080b200341506a2103200c2105200c2006490d000c070b0b20182003418cd0ca001042000b20162003419cd0ca001042000b2013200241acd0ca001059000b2002202941acd0ca001058000b202e20142003109d08220c20036a2106024020154101480d00200120154c0d00201720056a210b200c21052014210203402002200a2005200a2005412010a00841004822011b2203290300370300200241286a200341286a290300370300200241206a200341206a290300370300200241186a200341186a290300370300200241106a200341106a290300370300200241086a200341086a2903003703002005200541306a20011b2105200241306a2102200a41306a200a20011b220a200b4f0d03200620054b0d000c030b0b20142102200c21050c010b200a2102200c21050b20022005200620056b220320034130706b109d081a0240200028028003220220164d0d0020002802f802220520216a2203202220156a36020420032013360200200220184d0d02200520326a2203200341086a20022018417f736a410374109e081a20002002417f6a220336028003200341014b0d010c030b0b2016200241bcd0ca001042000b20182002104e000b200321310b20230d000b024020002802fc0241ffffffff0171450d00200510350b202d4130702102202d4130490d01202d2002460d01202e10350c010b20294102490d002029417f6a2103202941306c20176a41506a21064101210503400240024002400240202920032202417f6a2203490d00202920036b22014102490d032017200241306c6a22022017200341306c6a220a412010a008417f4a0d03200a2903002104200a2002290300370300200041b0036a41286a2215200a41286a220b290300370300200041b0036a41206a2216200a41206a220c290300370300200041b0036a41186a2218200a41186a2214290300370300200041b0036a41106a2213200a41106a2223290300370300200041b0036a41086a2221200a41086a22222903003703002022200241086a2903003703002023200241106a2903003703002014200241186a290300370300200c200241206a290300370300200b200241286a290300370300200020043703b0034101210220014103490d02200a41e0006a200041b0036a412010a008417f4a0d0241002101200621020340200241286a200241d8006a290300370300200241206a200241d0006a290300370300200241186a200241c8006a290300370300200241106a200241c0006a290300370300200241086a200241386a2903003703002002200241306a220c29030037030020052001220b460d02200b417f6a2101200241e0006a2114200c21022014200041b0036a412010a008417f4a0d020c000b0b2003202941dccfca001059000b4102200b6b21020b200a200241306c6a220220002903b003370300200241286a2015290300370300200241206a2016290300370300200241186a2018290300370300200241106a2013290300370300200241086a20212903003703000b200641506a21062005417f6a210520030d000b0b200041003602b803200042083703b003200041b0036a4100202941306c221341306e2223109a0120002802b803210b0240024020130d0020002802b00321010c010b20002802b0032201200b4104746a21022013210520172103034020022003360200200241086a4200370300200241106a2102200b41016a210b200341306a2103200541506a22050d000b0b2011201241386c6a211520002802b403212102400240024020120d002011210c0c010b200b41014b2118201121020340200241386a210c20022802282216450d0102402002412c6a290200220e422088a74105742203450d002002290300210d024020180d000240200b0e020200020b2001280200210542102104201621020340024020052002412010a0080d0020012001290308200d200442ffffffff0f837e7c3703080b200241206a21022004427f7c2104200341606a22030d000c020b0b201620036a21144200210420162106024003400240200b450d0041002102200b210303402003410176220520026a220a20022001200a4104746a2802002006412010a0084101481b2102200320056b220341014b0d000b200120024104746a22032802002006412010a0080d00200b20024d0d0220032003290308200d421020047d42ffffffff0f837e7c3703080b200442017c21042014200641206a2206460d020c000b0b2002200b41d099c2001042000b0240200e42ffffff3f83500d00201610350b200c2102200c2015470d000c020b0b2015200c460d000340200c41386a21020240200c412c6a28020041ffffff3f71450d00200c41286a28020010350b2002210c20152002470d000b0b02402019450d00201941386c450d00201110350b201720136a210c024002400240200b450d0020012802002203450d000240200b4101460d002001200b4104746a2106200141106a210220012903082104034020022802002205450d012004200241086a290300220d2004200d56220a1b210420032005200a1b2103200241106a22022006470d000b0b0240202141ffffffff0071450d00200110350b20030d01410021160c020b41002116202141ffffffff0071450d01200110350c010b200041d8026a41186a200341186a290000370300200041d8026a41106a200341106a290000370300200041d8026a41086a200341086a290000370300200020032900003703d802410121160b200041003602b803200042013703b003200041b0036a41002023108a0120002802b8032105024002402017200c4722310d0020002802b00321340c010b202941306c210a20002802b003223420054105746a210220172103034020022003290000370000200241186a200341186a290000370000200241106a200341106a290000370000200241086a200341086a290000370000200541016a2105200241206a2102200341306a2103200a41506a220a0d000b0b20002802b403212f200041003602b803200042083703b003200041b0036a41002028202741306c22026a22032028202b41306c220a6a6b41306e10880120002802b8032115024002402027410d4b0d0020002802b00321360c010b200a20026b210a20002802b0032236201541306c6a2102200341506a21030340200341086a2903002104200341106a290300210d200341186a290300210e2003290300210f200241286a200341286a290300370300200241206a200341206a290300370300200241186a200e370300200241106a200d370300200241086a20043703002002200f370300200241306a2102200341506a2103201541016a2115200a41306a220a0d000b0b20002802b4032137200041003602b803200042013703b003200041b0036a41002015108a0120002802b803210a02400240201541306c22060d0020002802b00321210c010b20002802b0032221200a4105746a210220362103034020022003290000370000200241186a200341186a290000370000200241106a200341106a290000370000200241086a200341086a290000370000200a41016a210a200241206a2102200341306a2103200641506a22060d000b0b20002802b4032127200041b0036a20342005201d201b10a602200041c4036a280200220b41ffffff3f71200b470d01200b4105742201417f4c0d01200041c0036a280200211b20002802bc03212220002802b403213020002802b003212b0240024020010d00410121020c010b200110332202450d030b200041003602b803200020023602b0032000200141057622183602b403200041b0036a4100200b108a0120002802b803210c02400240200b0d0020002802b00321140c010b200b410574210620002802b0032214200c4105746a210220222103034020022003290000370000200241186a200341186a290000370000200241106a200341106a290000370000200241086a200341086a290000370000200241206a2102200341206a2103200641606a22060d000b200b41057441606a410576200c6a41016a210c0b20002802b40321022014200c2034200510a7020240200241ffffff3f71450d00201410350b200041b0046a41186a2202200041d8026a41186a290300370300200041b0046a41106a2203200041d8026a41106a290300370300200041b0046a41086a2205200041d8026a41086a290300370300200020002903d8023703b0040240024020160d00200041f8026a41186a4200370300200041f8026a41106a22054200370300200041f8026a41086a22024200370300200042003703f80241dad5ca00ad4280808080b002841001220329000021042002200341086a290000370300200020043703f80220031035419cdfca00ad4280808080d00084100122032900002104200041b0056a41086a2206200341086a290000370300200020043703b00520031035200520002903b0052204370300200041f0046a41086a2002290300370300200041f0046a41106a2004370300200041f0046a41186a2006290300370300200020002903f8023703f004200041f0046aad428080808080048410070c010b200041b0036a41186a2002290300370300200041b0036a41106a2003290300370300200041b0036a41086a2005290300370300200020002903b0043703b00320004190056a41186a420037030020004190056a41106a2205420037030020004190056a41086a22024200370300200042003703900541dad5ca00ad4280808080b002841001220329000021042002200341086a290000370300200020043703900520031035419cdfca00ad4280808080d00084100122032900002104200041f8026a41086a2206200341086a290000370300200020043703f80220031035200520002903f8022204370300200041d0046a41086a2002290300370300200041d0046a41106a2004370300200041d0046a41186a200629030037030020002000290390053703d004412010332202450d03200220002903b003370000200241186a200041b0036a41186a290300370000200241106a200041b0036a41106a290300370000200241086a200041b0036a41086a290300370000200041d0046aad42808080808004842002ad42808080808004841002200210350b0240024020010d00410121030c010b200110332203450d030b41002102200041003602b803200020183602b403200020033602b003200041b0036a4100200b108a0120002802b803210c0240200b450d00200b410574210620002802b003200c4105746a21010340200120026a2203202220026a2205290000370000200341186a200541186a290000370000200341106a200541106a290000370000200341086a200541086a2900003700002006200241206a2202470d000b200b41057441606a410576200c6a41016a210c0b200041b8046a200c360200200020002903b0033703b004200041b0036a2021200a2020201e10a602200041c4036a2802002103200041c0036a280200210520002802bc032102024020002802b40341ffffff3f71450d0020002802b00310350b200041b0046a20002802b804200341057422034105752206108a0120002802b004222e20002802b80422014105746a20022003109d081a2000200120066a22383602b8040240200541ffffff3f71450d00200210350b02402007450d00200820074105746a2118200a4105742113200041b0036aad42808080808002842139200041f8026aad4280808080800484213a200041b0036a41106a2101200041b9036a2132202941014b2123200041e8036a21352008210b0340200b41086a2900002104200b41106a290000210d200b290000210e20004190056a41186a220c200b41186a29000037030020004190056a41106a2214200d37030020004190056a41086a221620043703002000200e37039005200b41206a210b410021030240024002400240024020230d0020290e020201020b202921050340200041b0036a41186a20172005410176220a20036a220641306c6a220241186a2900003703002001200241106a290000370300200041b0036a41086a200241086a290000370300200020022900003703b00320062003200041b0036a20004190056a412010a0084101481b21032005200a6b220541014b0d000b0b200041b0036a41186a2017200341306c6a220241186a2900003703002001200241106a290000370300200041b0036a41086a200241086a290000370300200020022900003703b0032013210320212102200041b0036a20004190056a412010a0080d010c020b20132103202121020b024003402003450d0120004190056a2002460d02200341606a2103200220004190056a412010a0082105200241206a210220050d000c020b0b200042003703f80420004280809aa6eaafe3013703f004200020004190056a3602d004200041f8026a20004190056a200041f0046a200041d0046a10a802200041f8026a41206a290300210d2000290390032104024020002903f8024201520d00200029038003210e2035200041f8026a41106a2903003703002032200029039005370000203241086a2016290300370000203241106a2014290300370000203241186a200c2903003700002000200e3703e003200041003a00b803200041033a00b00341b0b4cc004100200041b0036a10d4010b200020043703d0042000200d3703d804024002402004200d844200520d00200041b0036a41186a2205420037030020014200370300200041b0036a41086a22034200370300200042003703b00341b6fdc600ad428080808080018422041001220a290000210d200041f0046a41086a2202200a41086a2900003703002000200d3703f004200a103520032002290300370300200020002903f0043703b00341e489c200ad4280808080d00184220d1001220a290000210e2002200a41086a2900003703002000200e3703f004200a1035200120002903f004370000200141086a220c2002290300370000200041f8026a41086a22142003290300370300200041f8026a41106a22162001290300370300200041f8026a41186a22332005290300370300200020002903b0033703f802200041386a200041f8026a412010d701200041386a41106a290300210e2000290340210f2000280238210a200542003703002001420037030020034200370300200042003703b00320041001220629000021042002200641086a290000370300200020043703f0042006103520032002290300370300200020002903f0043703b003200d1001220629000021042002200641086a290000370300200020043703f00420061035200120002903f004370000200c2002290300370000201420032903003703002016200129030037030020332005290300370300200020002903b0033703f8022000200e4200200a1b3703b8032000200f4200200a1b3703b0030c010b200020043703d0042000200d3703d804200041b0036a41186a2205420037030020014200370300200041b0036a41086a22034200370300200042003703b00341b6fdc600ad4280808080800184220e1001220a290000210f200041f0046a41086a2202200a41086a2900003703002000200f3703f004200a103520032002290300370300200020002903f0043703b00341e489c200ad4280808080d00184220f1001220a29000021102002200a41086a290000370300200020103703f004200a1035200120002903f004370000200141086a220c2002290300370000200041f8026a41086a22142003290300370300200041f8026a41106a22162001290300370300200041f8026a41186a22332005290300370300200020002903b0033703f802200041d0006a200041f8026a412010d701200041d0006a41106a29030021102000290358213b2000280250210a200542003703002001420037030020034200370300200042003703b003200e10012206290000210e2002200641086a2900003703002000200e3703f0042006103520032002290300370300200020002903f0043703b003200f10012206290000210e2002200641086a2900003703002000200e3703f00420061035200120002903f004370000200c2002290300370000201420032903003703002016200129030037030020332005290300370300200020002903b0033703f8022000420020104200200a1b220e200d7d203b4200200a1b220d200454ad7d220f200d20047d2204200d56200f200e56200f200e511b22021b3703b80320004200200420021b3703b0030b203a203910020b200b2018470d000b0b0240200941ffffff3f71450d00200810350b20002802b404213302402038450d0020384105742101200041b0036aad42808080808002842139200041f8026aad4280808080800484213a200041b0036a41106a2102200041b9036a210b200041e8036a2132202e21030340200341086a2900002104200341106a290000210d2003290000210e20004190056a41186a2205200341186a29000037030020004190056a41106a220a200d37030020004190056a41086a220620043703002000200e37039005200042003703f80420004280809aa6eaafe3013703f004200020004190056a3602d004200041f8026a20004190056a200041f0046a200041d0046a10a802200041f8026a41206a290300210d2000290390032104024020002903f8024201520d00200029038003210e2032200041f8026a41106a290300370300200b200029039005370000200b41086a2006290300370000200b41106a200a290300370000200b41186a20052903003700002000200e3703e003200041003a00b803200041033a00b00341b0b4cc004100200041b0036a10d4010b200020043703d0042000200d3703d804024002402004200d844200520d00200041b0036a41186a2206420037030020024200370300200041b0036a41086a220a4200370300200042003703b00341b6fdc600ad428080808080018422041001220c290000210d200041f0046a41086a2205200c41086a2900003703002000200d3703f004200c1035200a2005290300370300200020002903f0043703b00341e489c200ad4280808080d00184220d1001220c290000210e2005200c41086a2900003703002000200e3703f004200c1035200220002903f004370000200241086a22162005290300370000200041f8026a41086a2218200a290300370300200041f8026a41106a22132002290300370300200041f8026a41186a22232006290300370300200020002903b0033703f802200041086a200041f8026a412010d701200041086a41106a290300210e2000290310210f2000280208210c2006420037030020024200370300200a4200370300200042003703b00320041001221429000021042005201441086a290000370300200020043703f00420141035200a2005290300370300200020002903f0043703b003200d1001221429000021042005201441086a290000370300200020043703f00420141035200220002903f004370000201620052903003700002018200a2903003703002013200229030037030020232006290300370300200020002903b0033703f8022000200e4200200c1b3703b8032000200f4200200c1b3703b0030c010b200020043703d0042000200d3703d804200041b0036a41186a2206420037030020024200370300200041b0036a41086a220a4200370300200042003703b00341b6fdc600ad4280808080800184220e1001220c290000210f200041f0046a41086a2205200c41086a2900003703002000200f3703f004200c1035200a2005290300370300200020002903f0043703b00341e489c200ad4280808080d00184220f1001220c29000021102005200c41086a290000370300200020103703f004200c1035200220002903f004370000200241086a22162005290300370000200041f8026a41086a2218200a290300370300200041f8026a41106a22132002290300370300200041f8026a41186a22232006290300370300200020002903b0033703f802200041206a200041f8026a412010d701200041206a41106a29030021102000290328213b2000280220210c2006420037030020024200370300200a4200370300200042003703b003200e10012214290000210e2005201441086a2900003703002000200e3703f00420141035200a2005290300370300200020002903f0043703b003200f10012214290000210e2005201441086a2900003703002000200e3703f00420141035200220002903f004370000201620052903003700002018200a2903003703002013200229030037030020232006290300370300200020002903b0033703f8022000420020104200200c1b220e200d7d203b4200200c1b220d200454ad7d220f200d20047d2204200d56200f200e56200f200e511b22051b3703b80320004200200420051b3703b0030b203a20391002200341206a2103200141606a22010d000b0b0240203341ffffff3f71450d00202e10350b200041b0036a41186a22034200370300200041b0036a41106a22054200370300200041b0036a41086a22024200370300200042003703b00341a0e4cb00ad4280808080800284220410012206290000210d200041f0046a41086a220a200641086a2900003703002000200d3703f004200610352002200a290300370300200020002903f0043703b0034189eaca00ad4280808080f0008410012201290000210d20004190056a41086a2206200141086a2900003703002000200d3703900520011035201a200029039005370000201a41086a220b2006290300370000200041f8026a41086a220c2002290300370300200041f8026a41106a22142005290300370300200041f8026a41186a22162003290300370300200020002903b0033703f802200041203602b4032000200041f8026a3602b00320172029200041b0036a10a902200342003703002005420037030020024200370300200042003703b0032004100122012900002104200a200141086a290000370300200020043703f004200110352002200a290300370300200020002903f0043703b00341c699c200ad42808080809001841001220a29000021042006200a41086a2900003703002000200437039005200a1035201a200029039005370000200b2006290300370000200c20022903003703002014200529030037030020162003290300370300200020002903b0033703f802200041203602b4032000200041f8026a3602b00320362015200041b0036a10a9022029ad42307e2204422088a70d012004a72202417f4c0d010240024020020d00410821030c010b200210332203450d030b200041003602b803200020033602b0032000200241306e3602b403200041b0036a4100202910880120002802b80321050240024020310d0020002802b00321010c010b202941306c210a20002802b0032201200541306c6a2102201721030340200341086a2903002104200341106a290300210d200341186a290300210e2003290300210f200241286a200341286a290300370300200241206a200341206a290300370300200241186a200e370300200241106a200d370300200241086a20043703002002200f370300200241306a2102200541016a2105200341306a2103200a41506a220a0d000b0b2005ad42307e2204422088a70d012004a72202417f4c0d0120002802b40321060240024020020d00410821030c010b200210332203450d030b200041003602b803200020033602b0032000200241306e3602b403200041b0036a4100200510880120002802b803210a0240200541306c2205450d0020002802b003200a41306c6a2102200121030340200341086a2903002104200341106a290300210d200341186a290300210e2003290300210f200241286a200341286a290300370300200241206a200341206a290300370300200241186a200e370300200241106a200d370300200241086a20043703002002200f370300200241306a2102200a41016a210a200341306a2103200541506a22050d000b0b20004183036a200a360000200020002903b0033700fb02200041bc036a200041ff026a290000370000200041003a00b403200041093a00b003200020002900f8023700b50341b0b4cc004100200041b0036a10d40102402006450d00200641306c450d00200110350b0240201b41ffffff3f71450d00202210350b0240203041ffffff3f71450d00202b10350b0240202741ffffff3f71450d00202110350b02402037450d00203741306c450d00203610350b0240202f41ffffff3f71450d00203410350b0240202c450d00202c41306c450d00201710350b0240202a450d00202a41306c450d00202810350b0240024020002802b802220a0d0041002106200041c4036a4100360200200041003602b4030c010b20002802c00221060240024020002802bc0222030d00200a21020c010b20032102200a2105034020052802c80521052002417f6a22020d000b200a21020340200220022f01064102746a41c8056a28020021022003417f6a22030d000b2005210a0b200041cc036a20022f0106360200200041c8036a4100360200200041c4036a2002360200200041003602c003200042003703b8032000200a3602b403200041003602b0030b200020063602d003200041b0036a109e0202402026450d002026412c6c21032025210203400240200241046a2802002205450d00200541306c450d00200228020010350b2002412c6a2102200341546a22030d000b0b02402024450d002024412c6c450d00202510350b0240201f41ffffff3f71450d00202010350b41002118200041b0036a2106200041f8026a2101201c41ffffff3f71450d00201d10350b200041b0036a41186a220b4200370300200041b0036a41106a22024200370300200041b0036a41086a22034200370300200042003703b00341a0e4cb00ad428080808080028422041001220a290000210d200041f0046a41086a2205200a41086a2900003703002000200d3703f004200a1035200641086a220c2005290300370000200620002903f00437000041e1b8c800ad4280808080a0018410012214290000210d20004190056a41086a220a201441086a2900003703002000200d37039005201410352002200029039005220d370300200041f8026a41086a22142003290300370300200041f8026a41106a2215200d370300200041f8026a41186a2216200a290300370300200020002903b0033703f8022001ad42808080808004841007200b42003703002002420037030020034200370300200042003703b003200410012217290000210d2005201741086a2900003703002000200d3703f00420171035200c2005290300370000200620002903f00437000041b0e4cb00ad4280808080e00184220d10012217290000210e200a201741086a2900003703002000200e37039005201710352002200029039005220e370300201420032903003703002015200e3703002016200a290300370300200020002903b0033703f80220002001412010c0012000280200211720002802042113200b42003703002002420037030020034200370300200042003703b00320041001220129000021042005200141086a290000370300200020043703f00420011035200c2005290300370000200620002903f004370000200d100122052900002104200a200541086a2900003703002000200437039005200510352002200029039005220437030020142003290300370300201520043703002016200a290300370300200020002903b0033703f8022000201341016a410120171b3602b003200041f8026aad4280808080800484200041b0036aad4280808080c0008410020240024020002802a00222020d0020180d010c040b2018450d03024020002802a4022203450d00200341306c450d00200210350b200041ac026a280200210a0240200041b4026a2802002202450d002002412c6c2103200a210203400240200241046a2802002205450d00200541246c450d00200228020010350b2002412c6a2102200341546a22030d000b0b200041b0026a2802002202450d002002412c6c450d00200a10350b02402012450d00201241386c21032011412c6a210203400240200228020041ffffff3f71450d002002417c6a28020010350b200241386a2102200341486a22030d000b0b02402019450d00201941386c450d00201110350b200941ffffff3f71450d02200810350c020b1044000b1045000b200041c0056a24000bbf0201027f230041e0006b220224002002412036020c20022001360208200241106a2001ad4280808080800484100510c20102400240200228021022010d00200041003602000c010b200228021421032002200241106a41086a28020036022420022001360220200241c8006a200241206a10aa020240024020022802480d0020024100360230200242013703282002410936023c2002200241086a3602382002200241286a360244200241dc006a41013602002002420137024c200241c888c2003602482002200241386a360258200241c4006a41e88ac500200241c8006a10431a200235023042208620023502288410060240200228022c450d00200228022810350b200041003602000c010b20002002290348370200200041086a200241c8006a41086a2802003602000b2003450d00200110350b200241e0006a24000ba00605057f017e037f027e027f230041f0006b22022400200241286a200141146a350200422086200135020c84102710c2010240024020022802282203450d00200141086a2104200141106a210503400240024020042802002206200229022c2207422088a722084b0d00200128020022092003460d0120092003200610a008450d010b2007a7450d02200310350c020b02402005280200450d00200128020c10350b2001200336020c20052007370200200241086a2003200810cc02024002402002280218220a450d00200241086a41086a29030021072002290308210b2002290320210c200228021c210d024020012d0018450d002001350214422086200135020c8410070b2001280214220820042802002203490d0102400240200820036b22084108490d00200841786a2106200128020c20036a41086a21090c010b410021060240410028028cb54c0d0041b0b4cc0021090c010b410021064100280298b54c21034100280294b54c21084100280290b54c210e200241e500360268200242b48080801037036020024187a1c00036025c20024213370254200241f4a0c0003602502002420037034841b0b4cc002109200241b0b4cc0036024420024201370338200241eca0c00036023420024113360230200241f4a0c00036022c20024101360228200841aca2c000200e410246220e1b200241286a200341c4a2c000200e1b2802101102000b41002103200241003a00480240034020062003460d01200241286a20036a200920036a2d00003a00002002200341016a22083a00482008210320084120470d000b20002002290328370000200041186a200241286a41186a290300370000200041106a200241286a41106a290300370000200041086a200241286a41086a290300370000200041286a20073703002000200b370320200041386a200c3703002000200d3602342000200a3602300c050b0240200341ff0171450d00200241003a00480b200d41ffffff3f71450d00200a10350b200241286a2001350214422086200135020c84102710c201200228022822030d010c020b0b2003200841889aca001059000b200041003602300b200241f0006a24000ba10201087f230041106b22022400024002402001280208220341ffffff3f712003470d0020034105742204417f4c0d00200128020021050240024020040d00410121060c010b200410332206450d020b41002101200241003602082002200636020020022004410576360204200241002003108a012002280208210702402003450d0020034105742108200228020020074105746a21090340200920016a2204200520016a2206290000370000200441186a200641186a290000370000200441106a200641106a290000370000200441086a200641086a2900003700002008200141206a2201470d000b200341057441606a41057620076a41016a21070b20002002290300370200200041086a2007360200200241106a24000f0b1044000b1045000b8509050f7f027e017f017e027f23004180026b22022400200141086a2802002103200128020421042000280204210520002802002106024020002802082207200028020c2208460d002001280200210020024190016a410c6a2109200241c0016a41106a210120024190016a410472210a200241386a41206a210b200241386a41186a210c200241386a41086a210d024003402007280200210e200b200741246a290200370300200c2007411c6a290200370300200241386a41106a220f200741146a290200370300200d2007410c6a2902003703002002200741046a290200370338200e450d01200a2002290338370200200a41086a200d290300370200200a41106a200f290300370200200a41186a200c290300370200200a41206a200b2903003702002002200e36029001200241e0006a200910e502200241c0016a20022802602210200228026810cc02200241c0016a41086a220e290300211120022802d001210f20022903c001211220022802d401211302402002280264450d00201010350b20114200200f1b211420124200200f1b21120240200f450d00201341ffffff3f71450d00200f4101200f1b10350b200241c0016a41186a220f420037030020014200370300200e4200370300200242003703c00141b6fdc600ad4280808080800184100122132900002111200e201341086a290000370300200220113703c0012013103541e489c200ad4280808080d00184100122132900002111200241f0016a41086a2210201341086a290000370300200220113703f00120131035200120022903f001370000200141086a2010290300370000200241e0006a41086a2213200e290300370300200241e0006a41106a22102001290300370300200241e0006a41186a2215200f290300370300200220022903c001370360200241206a200241e0006a412010d701200241106a2002290328200241206a41106a290300427f420010980820022012201420022903104200200228022022161b221142012011420156200241106a41086a290300420020161b22114200522011501b22161b2011420020161b109808200241c0016a41286a20024190016a41286a280200360200200241c0016a41206a20024190016a41206a290300370300200f20024190016a41186a290300370300200120024190016a41106a290300370300200e20024190016a41086a29030037030020022002290390013703c001200241e0006a200241c0016a2002290300420010cb01200041286a200241e0006a41286a280200360200200041206a200241e0006a41206a290300370200200041186a2015290300370200200041106a2010290300370200200041086a201329030037020020002002290360370200200341016a21032000412c6a21002007412c6a22072008470d000b200821070c010b2007412c6a21070b20042003360200200820076b2200412c6d210102402000450d002001412c6c210003400240200741046a2802002201450d00200141246c450d00200728020010350b2007412c6a2107200041546a22000d000b0b02402005450d002005412c6c450d00200610350b20024180026a24000bd907010f7f230041c0006b22052400200541003602082005420137030020054100360218200542013703102003410020041b21062001410020021b2107200341206a200320041b2108200141206a200120021b2109200120024105746a210a200320044105746a210b4101210c4100210d4101210e4101210f410021100340200e211120102102200821032006210102400340024020010d004100210620070d02200020052903003702002000200529031037020c200041086a200541086a280200360200200041146a200541106a41086a280200360200200541c0006a24000f0b024020070d00200541206a41186a2203200641186a290000370300200541206a41106a2202200641106a290000370300200541206a41086a2207200641086a29000037030020052006290000370320024020102005280214470d00200541106a20104101108a012005280210210e200528021821100b200e20104105746a22012005290320370000200141186a2003290300370000200141106a2002290300370000200141086a20072903003700002005201041016a221036021841002107410020082008200b4622011b2106200e210f2008200841206a20011b21080c030b0240024020012007460d0020012007412010a00822040d010b2003200341206a2003200b4622011b2108410020092009200a4622041b21074100200320011b21062011210e200221102009200941206a20041b21090c030b02402004417f4c0d00200121060c020b200541206a41186a2204200141186a290000370300200541206a41106a2212200141106a290000370300200541206a41086a2213200141086a29000037030020052001290000370320024020022005280214470d00200541106a20024101108a012005280218210220052802102211210f0b200f20024105746a22012005290320370000200141186a2004290300370000200141106a2012290300370000200141086a20132903003700002005200241016a2202360218410020032003200b4622041b21012003200341206a20041b21030c000b0b200541206a41186a2204200741186a290000370300200541206a41106a2212200741106a290000370300200541206a41086a2213200741086a290000370300200520072900003703200240200d2005280204470d002005200d4101108a012005280200210c2005280208210d0b200c200d4105746a22012005290320370000200141186a2004290300370000200141106a2012290300370000200141086a20132903003700002005200d41016a220d360208410020092009200a4622011b21072011210e200221102009200941206a20011b2109200321080c000b0be80f06087f017e047f017e057f077e230022042105200441a0016b41607122042400024002400240200141ffffff3f712001470d0020014105742206417f4c0d000240024020060d00410121070c010b200610332207450d020b41002108200441003602282004200736022020042006410576360224200441206a41002001108a012004280228210902402001450d002001410574210a200428022020094105746a210b0340200b20086a2206200020086a2207290000370000200641186a200741186a290000370000200641106a200741106a290000370000200641086a200741086a290000370000200a200841206a2208470d000b200141057441606a41057620096a41016a21090b200441086a200936020020042004290320220c370300200ca72009410041202009676b10c105200441206a41186a22014200370300200441206a41106a220d4200370300200441206a41086a220e42003703002004420037032041dad5ca00ad4280808080b0028410012208290000210c200e200841086a2900003703002004200c370320200810354180eaca00ad428080808090018410012208290000210c200441e8006a41086a220f200841086a2900003703002004200c37036820081035200d2004290368220c37030020044180016a41086a200e29030037030020044180016a41106a200c37030020044180016a41186a200f2903003703002004200429032037038001200441206a20044180016a412010b50220042802202208410120081b21102004290224420020081b2211422088a72208450d022008410574210920044180016a410c722112200441206a410c6a2100200441206a4114722113200441206a41087221142010210803402001200841186a290000370300200d200841106a290000370300200e200841086a29000037030020042008290000370320200441106a200441206a108c07200441206a2004280210220b2004280218221510de02200f200041086a290200370300200441e8006a41106a220a200041106a2802003602002004200029020037036820042802402106024020042802282207450d002004290320210c20122004290368370200201241086a200f290300370200201241106a200a2802003602002004200c37038001200621160b200420073602880120044100360228200429039801211720042004290338221837039801200429039001211920042004290330221a37039001200429038001211b20042004290320221c37038001200429038801210c20042004290328221d37038801201da7210702400240200ca7220a0d00201d210c201a211920182117201621060c010b2004201b3703202004200c37032820042019370330200420173703382004200a2019a74105746a3602742004200a3602702004200c422088a736026c2004200a36026820042004360278200441d8006a200441e8006a10ca05201441086a200441d8006a41086a22162802003602002014200429035837020020042019422088a7220a2017422088a74105746a3602742004200a36027020042017a736026c2004200a36026820042004360278200441d8006a200441e8006a10ca05201341086a2016280200360200201320042903583702002004290328210c2004290320211c200429033821172004290330211902402007450d002018a7210a0240201d422088a741ffffff3f71450d00200710350b200a41ffffff3f71450d00201a422088a710350b2004201c370380012004200c3703880120042019370390012004201737039801200ca721070b2004200c37032820042019370330200120173703002004201c37032020042006360240200ca7210a0240024020070d002015ad422086200bad8410070c010b2004201536026c2004200b360268200441206a200441e8006a108b070b0240200a450d002017a721070240200c422088a741ffffff3f71450d00200a10350b200741ffffff3f71450d002019422088a710350b02402004280214450d00200b10350b200841206a210820062116200941606a22090d000c030b0b1044000b1045000b0240201142ffffff3f83500d00201010350b200441206a41186a220a4200370300200441206a41106a22074200370300200441206a41086a220642003703002004420037032041dad5ca00ad4280808080b00284220c10012200290000211c200441e8006a41086a2208200041086a2900003703002004201c3703682000103520062008290300370300200420042903683703204189eaca00ad4280808080f0008410012200290000211c2008200041086a2900003703002004201c3703682000103520072004290368221c37030020044180016a41086a220b200629030037030020044180016a41106a2201201c37030020044180016a41186a22092008290300370300200420042903203703800120044120360224200420044180016a36022020022003200441206a10a806200a4200370300200742003703002006420037030020044200370320200c10012200290000210c2008200041086a2900003703002004200c370368200010352006200829030037030020042004290368370320419cdfca00ad4280808080d0008410012200290000210c2008200041086a2900003703002004200c3703682000103520072004290368220c370300200b20062903003703002001200c37030020092008290300370300200420042903203703800120044180016aad428080808080048410070240200428020441ffffff3f71450d00200428020010350b200524000b9d0f07037f027e027f0a7e037f067e047f230041d0036b2204240020032802002105200441206a2001108e02200441a0016a2004280220220320042802282206108f0220042903a001210742002108200442003703a001200441e8016a280200210920042d00ec01210a0240024020074201510d00200441306a41306a4200370300200441306a41286a4200370300200441306a41206a4200370300200441306a41186a4200370300200441c0006a4200370300200441386a4200370300200442003703304200210b4200210c4200210d4200210e0c010b200441d8016a290300210f200441a0016a41306a2903002110200441a0016a41206a290300210b200441a0016a41186a2903002108200441e0016a290300210e20042903b001210d20042903a801210c200441306a41206a200441a0016a41286a290300370300200441306a41286a2010370300200441306a41306a200f370300200441c0006a20083703002004200b3703482004200c3703302004200d3703380b200441306a41186a200b200241086a2903002210200b20082002290300221156200b201056200b2010511b22021b22127d20082011200820021b220f54ad7d221337030020042008200f7d2214370340200441e8006a41186a2013370300200441e8006a41206a2215200441306a41206a290300370300200441e8006a41286a2216200441306a41286a290300370300200441e8006a41306a2217200441306a41306a290300370300200420143703782004200c3703682004200d370370427f200d200b7c200c20087c220b200c542202ad7c220820022008200d542008200d511b22021b2118427f200b20021b211902400240427f200c20147c22082008200c542202200d20137c2002ad7c2208200d542008200d511b22021b220b428080e983b1de16544100427f200820021b2213501b0d00200441f8006a290300210b20172903002113201629030021142015290300211a2004290370211b2004290368211c42012108200429038001211d0c010b02400240200b20138450450d00420021080c010b42002108200441a0026a41186a221e4200370300200441a0026a41106a22164200370300200441a0026a41086a22154200370300200442003703a00241b6fdc600ad4280808080800184221410012217290000211a200441c0036a41086a2202201741086a2900003703002004201a3703c0032017103520152002290300370300200420042903c0033703a00241e489c200ad4280808080d00184221a10012217290000211b2002201741086a2900003703002004201b3703c00320171035201620042903c003221b370300200441a0036a41086a221f2015290300370300200441a0036a41106a2220201b370300200441a0036a41186a22212002290300370300200420042903a0023703a003200441086a200441a0036a412010d701200441086a41106a290300211b2004290310211c20042802082117201e42003703002016420037030020154200370300200442003703a00220141001221e29000021142002201e41086a290000370300200420143703c003201e103520152002290300370300200420042903c0033703a002201a1001221e29000021142002201e41086a290000370300200420143703c003201e1035201620042903c0032214370300201f20152903003703002020201437030020212002290300370300200420042903a0023703a00320044200201b420020171b221420137d201c420020171b221a200b54ad7d221b201a200b7d221c201a56201b201456201b2014511b22021b3703a80220044200201c20021b3703a002200441a0036aad4280808080800484200441a0026aad42808080808002841002200441d8026a2013370300200441d0026a200b370300201541013a0000200441a9026a2005290000370000200441b1026a200541086a290000370000200441b9026a200541106a290000370000200441c1026a200541186a290000370000200441033a00a00241b0b4cc004100200441a0026a10d4010b0b2011200f54210220192018842118200441c8016a201a370300200441d0016a2014370300200441b0016a201b370300200441d8016a2013370300200441b8016a200b3703002004201d3703c0012004200e3703e0012004201c3703a8012004200a4100200742015122051b3a00ec0120042009410020051b3602e801200420084201512205ad3703a0010240024020050d002006ad4220862003ad8410070c010b200420063602a402200420033602a002200441a8016a200441a0026a10e7020b201020127d210b2002ad2110201850210202402004280224450d00200310350b200b20107d210b2002ad21102011200f7d21112008420152210202400240024020074201510d0020020d0041032103200441a0026a21020c010b20074201522002410173720d0141042103200441a0016a21020b200241086a20033a0000200241003a0000200241096a2001290000370000200241116a200141086a290000370000200241196a200141106a290000370000200241216a200141186a29000037000041b0b4cc004100200210d4010b2000200f3703182000200c37030820002010370300200041306a200b370300200041286a2011370300200041206a2012370300200041106a200d370300200441d0036a24000bac0402067f027e230041106b220324000240024002400240200141306c4104722204417f4c0d00200410332205450d012003410036020820032004360204200320053602002001200310770240024020010d002003280208210120032802042105200328020021060c010b2000200141306c6a2107200328020021062003280204210520032802082101034002400240200520016b4120490d00200141206a2104200521080c010b200141206a22042001490d05200541017422082004200820044b1b22084100480d05024020050d00024020080d00410121060c020b2008103322060d010c070b20052008460d0020062005200810372206450d060b200620016a22012000290000370000200141186a200041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200041286a2903002109200041206a290300210a02400240200820046b4110490d00200441106a2101200821050c010b200441106a22012004490d05200841017422052001200520014b1b22054100480d05024020080d00024020050d00410121060c020b200510332206450d070c010b20082005460d0020062008200510372206450d060b200620046a220420093700082004200a3700002007200041306a2200470d000b2003200536020420032001360208200320063602000b20022902002001ad4220862006ad84100202402005450d00200610350b200341106a24000f0b1044000b1045000b103e000b103c000bcf0504037f017e087f047e23004180016b220224002002200110c40102400240024002402002280200450d00200041003602000c010b20022802042203200128020441306e2204200420034b1bad42307e2205422088a70d012005a72204417f4c0d010240024020040d00410821060c010b200410332206450d030b4100210720024100360210200220063602082002200441306e36020c0240024002402003450d0041002108034041002104200241003a0078200841016a210820012802042109417f210a034020092004460d03200241d8006a20046a2001280200220b2d00003a000020012009200a6a3602042001200b41016a3602002002200441016a220c3a0078200a417f6a210a200c2104200c4120470d000b200241386a41186a2204200241d8006a41186a290300370300200241386a41106a220a200241d8006a41106a290300370300200241386a41086a220d200241d8006a41086a290300370300200220022903583703382009200c6b220c4110490d03200b41096a2900002105200b290001210e2001200c41706a3602042001200b41116a360200200241186a41086a220c200d290300370300200241186a41106a2209200a290300370300200241186a41186a220a20042903003703002002200229033837031802402007200228020c470d00200241086a2007410110880120022802082106200228021021070b2006200741306c6a22042002290318370300200c290300210f20092903002110200a29030021112004200e370320200441286a2005370300200441186a2011370300200441106a2010370300200441086a200f3703002002200741016a220736021020082003470d000b0b20002002290308370200200041086a200241086a41086a2802003602000c020b200441ff0171450d00200241003a00780b20004100360200200228020c2204450d00200441306c450d00200610350b20024180016a24000f0b1044000b1045000bcaf80102517f0d7e230041d0106b2201240020014100360210200141003602080240024002400240024002400240200041086a22022802002203450d00200141f8076a4102722104200141fd026a2105200141d0026a41206a2106200141386a41206a2107200141f8076a41206a2108200141186a41186a2109200141186a41106a210a4100210b034002402002280200220c200b4b0d00200b200c41e099c2001042000b20092000280200200b412c6c220d6a220e41246a290000370300200a200e411c6a290000370300200141186a41086a220f200e41146a2900003703002001200e29000c370318200e280200210c200e280208210e2001410036028008200142013703f807200141f8076a4100200e108a01200128028008211002400240200e41306c22110d0020012802f80721120c010b20012802f807221220104105746a210e0340200e200c290000370000200e41186a200c41186a290000370000200e41106a200c41106a290000370000200e41086a200c41086a290000370000201041016a2110200e41206a210e200c41306a210c201141506a22110d000b0b20012802fc072113024020104102490d00024002402010417f6a221420106c410176220c41ffffff1f71200c470d00200c410674220c417f4c0d00024002400240200c0d00410121150c010b200c10332215450d010b201241206a2116200c4106762117410021184100210c03400240200c41016a221920104f0d002012200c4105746a21112014211a2016210e0340200141f8076a41086a221b201141086a290000370300200141f8076a41106a221c201141106a290000370300200141f8076a41186a221d201141186a290000370300200120112900003703f8072008200e290000370000200841086a200e41086a290000370000200841106a200e41106a290000370000200841186a200e41186a290000370000024020182017470d00024002400240201741016a220c2017490d002017410174221e200c201e200c4b1b220c41ffffff1f71200c470d00200c410674220c4100480d00024020170d00200c0d02410121150c030b20174106742217200c460d02024020170d00200c0d02410121150c030b20152017200c10372215450d120c020b103e000b200c10332215450d100b200c41067621170b201520184106746a220c20012903f807370000200c41386a200141f8076a41386a290300370000200c41306a200141f8076a41306a290300370000200c41286a200141f8076a41286a290300370000200c41206a2008290300370000200c41186a201d290300370000200c41106a201c290300370000200c41086a201b290300370000200e41206a210e201841016a2118201a417f6a221a0d000b0b2014417f6a2114201641206a21162019210c20192010470d000b2018450d02201520184106746a211f2015211e02400340200141386a41386a201e41386a290000370300200141386a41306a201e41306a290000370300200141386a41286a201e41286a2900003703002007201e41206a290000370300200141386a41186a201e41186a220c290000370300200141386a41106a201e41106a220e290000370300200141386a41086a201e41086a22112900003703002001201e290000370338200141f8006a41186a2218200c290000370300200141f8006a41106a220c200e290000370300200141f8006a41086a220e20112900003703002001201e29000037037820014198016a41186a200741186a221129000037030020014198016a41106a200741106a221a29000037030020014198016a41086a200741086a221b2900003703002001200729000037039801200141d0026a41186a22202018290300370300200141d0026a41106a2221200c290300370300200141d0026a41086a2222200e29030037030020062007290000370000200641086a201b290000370000200641106a201a290000370000200641186a2011290000370000200120012903783703d002024002402001280208221b450d00200128020c211c0c010b200141f8076a410041c005109f081a200141e8046a410041e002109f081a41a8081033221b450d0e4100211c201b41003b0106201b4100360200201b41086a200141f8076a41c005109d081a201b41c8056a200141e8046a41e002109d081a2001410036020c2001201b3602080b201e41c0006a211e024002400240024002400240024002400240024002400240024003400240201b2f0106221a410674220e450d00201b41286a210c41002111034002400240200141d0026a200c41606a412010a0082218450d00201841004e0d012011211a0c030b2006200c412010a0082218450d04201841004e0d002011211a0c020b201141016a2111200c41c0006a210c200e41406a220e0d000b0b201c450d02201c417f6a211c201b201a4102746a41a8086a280200211b0c000b0b20022802002219200b4d0d032000280200221d200d6a220c28020841306c221a450d0a201b201141057422236a41c8056a2110200c280200210c4100211803404101210e0240200141f8006a200c460d00200c200141f8006a412010a008450d00024020014198016a200c470d004101210e0c010b200c20014198016a412010a00845210e0b200c41306a210c200e20186a2118201a41506a221a0d000b20184102470d0a2019412c6c210e0340201d210c200e450d0b0240200c410c6a22182010460d00200e41546a210e200c412c6a211d20182010412010a0080d010b0b0240200c41086a280200220e450d00200e41306c211a200141f8006a200c28020022186b211d20014198016a20186b21194100210c0340201d200c460d032018200c6a220e200141f8006a412010a008450d032019200c460d03200e20014198016a412010a008450d03201a200c41306a220c470d000b0b41082124410021250c070b200141b8016a41386a220c200141d0026a41386a290300370300200141b8016a41306a220e200141d0026a41306a290300370300200141b8016a41286a2211200141d0026a41286a290300370300200141b8016a41206a22182006290300370300200141b8016a41186a221c2020290300370300200141b8016a41106a221d2021290300370300200141b8016a41086a22102022290300370300200120012903d0023703b8012001200128021041016a360210200141a0036a41386a2226200c290300370300200141a0036a41306a2227200e290300370300200141a0036a41286a22282011290300370300200141a0036a41206a22242018290300370300200141a0036a41186a2223201c290300370300200141a0036a41106a2225201d290300370300200141a0036a41086a22292010290300370300200120012903b8013703a003200141d0076a41186a222a2009290300370300200141d0076a41106a222b200a290300370300200141d0076a41086a222c200f290300370300200120012903183703d0070240201b2f0106220e410b490d00200141f8076a410041c005109f081a200141e8046a410041e002109f081a41a8081033220c450d19200c41003b0106200c4100360200200c41086a200141f8076a41c005109d08210e200c41c8056a200141e8046a41e002109d082118200141f8076a41086a2210201b41a3036a290000370300200141f8076a41106a2219201b41ab036a290000370300200141f8076a41186a2214201b41b3036a2900003703002008201b41bb036a290000370300200141f8076a41256a2216201b41c0036a2900003700002001201b4188036a2f00003b0188042001201b418a036a2d00003a008a042001201b419b036a2900003703f807201b418b036a280000212d201b418f036a280000212e201b4193036a280000212f201b4197036a2800002130200141c8046a41186a2231201b41a0076a290000370300200141c8046a41106a2232201b4198076a290000370300200141c8046a41086a2233201b4190076a2900003703002001201b290088073703c804200e201b41c8036a201b2f010641796a2211410674109d08210e2018201b41a8076a2011410574109d082118201b41063b0106200c20113b0106200141e0036a41026a221c20012d008a043a0000200141e8046a41086a22342010290300370300200141e8046a41106a22352019290300370300200141e8046a41186a22362014290300370300200141e8046a41206a22372008290300370300200141e8046a41256a22382016290000370000200120012f0188043b01e003200120012903f8073703e804200141a8046a41186a22392031290300370300200141a8046a41106a223a2032290300370300200141a8046a41086a223b2033290300370300200120012903c8043703a80402400240201a4107490d00200e201a417a6a221d4106746a200e201a41796a221a4106746a220e201141ffff0371201a6b410674109e081a200e41386a2026290300370000200e41306a2027290300370000200e41286a2028290300370000200e41206a2024290300370000200e41186a2023290300370000200e41106a2025290300370000200e41086a2029290300370000200e20012903a0033700002018201d4105746a2018201a4105746a220e200c2f0106201a6b410574109e081a200e41186a202a290300370000200e41106a202b290300370000200e41086a202c290300370000200e20012903d007370000200c200c2f010641016a3b01060c010b201b41086a220e201a41016a22114106746a200e201a4106746a220e201b2f0106201a6b410674109e081a200e41386a2026290300370000200e41306a2027290300370000200e41286a2028290300370000200e41206a2024290300370000200e41186a2023290300370000200e41106a2025290300370000200e41086a2029290300370000200e20012903a003370000201b41c8056a220e20114105746a200e201a4105746a220e201b2f0106201a6b410574109e081a200e41186a202a290300370000200e41106a202b290300370000200e41086a202c290300370000200e20012903d007370000201b201b2f010641016a3b01060b200520012903a804370000200141f4076a41026a220e201c2d00003a000020222034290300370300202120352903003703002020203629030037030020062037290300370300200141d0026a41256a22282038290000370000200541086a2211203b290300370000200541106a2218203a290300370000200541186a221a2039290300370000200120012f01e0033b01f407200120012903e8043703d002200141cc026a41026a223c200e2d00003a000020014198026a41086a223d202229030037030020014198026a41106a223e202129030037030020014198026a41186a223f202029030037030020014198026a41206a2240200629030037030020014198026a41256a22412028290000370000200120012f01f4073b01cc02200120012903d00237039802200141f8016a41186a2242201a290000370300200141f8016a41106a22432018290000370300200141f8016a41086a22442011290000370300200120052900003703f8010240201b28020022180d004100211d200141086a210e200c21110c0a0b201b2f0104212641002145200c2146034020014184046a41026a2247203c2d00003a00002022203d2903003703002021203e2903003703002020203f2903003703002006204029030037030020282041290000370000200120012f01cc023b01840420012001290398023703d00220014188046a41186a2248204229030037030020014188046a41106a2249204329030037030020014188046a41086a224a2044290300370300200120012903f8013703880441000d03202641ffff0371211c02400240024020182f0106220c410b490d002004410041d208109f081a41d8081033221a450d1d201a4100360200201a41046a200141f8076a41d408109d081a200141d0076a41026a224b2018418a036a2d00003a00002010201841a3036a2900003703002019201841ab036a2900003703002014201841b3036a2900003703002008201841bb036a2900003703002016201841c0036a290000370000200120184188036a2f00003b01d00720012018419b036a2900003703f8072018418b036a280000214c2018418f036a280000214d20184193036a280000214e20184197036a280000214f2031201841a0076a290000370300203220184198076a290000370300203320184190076a29000037030020012018290088073703c804201a41086a201841c8036a20182f0106220e41796a220c410674109d082150201a41c8056a201841a8076a200c410574109d082151201a41a8086a201841c4086a200e417a6a221d410274109d082127201841063b0106201a200c3b01060240201d450d004100210c2027210e0340200e2802002211200c3b01042011201a360200200e41046a210e201d200c41016a220c470d000b0b2034201029030037030020352019290300370300203620142903003703002037200829030037030020382016290000370000203b2033290300370300203a203229030037030020392031290300370300200120012f01d0073b01f407200120012903f8073703e804200120012903c8043703a8042001204b2d00003a00f607200141cc076a41026a221d20012d00f6073a00002010203429030037030020192035290300370300201420362903003703002008203729030037030020162038290000370000200120012f01f4073b01cc07200120012903e8043703f807202a2039290300370300202b203a290300370300202c203b290300370300200120012903a8043703d007202641ffff037122264107490d012050201c417a6a22114106746a2050201c41796a220c4106746a220e201a2f0106200c6b410674109e081a200e203036000f200e202f36000b200e202e360007200e202d360003200e41026a20472d00003a0000200e20012f0184043b0000200e20012903d002370013200e411b6a2022290300370000200e41236a2021290300370000200e412b6a2020290300370000200e41336a2006290300370000200e41386a2028290000370000205120114105746a2051200c4105746a220e201a2f01062226200c6b410574109e081a200e41186a2048290300370000200e41106a2049290300370000200e41086a204a290300370000200e200129038804370000201a202641016a220e3b0106201c410274222620276a416c6a202720114102746a221c200e41ffff037120116b410274109e081a201c20463602002011201a2f0106221c4b0d02201a20266a4190086a210e0340200e2802002211200c41016a220c3b01042011201a360200200e41046a210e200c201c490d000c030b0b201841086a220e201c41016a22114106746a200e201c4106746a220e200c201c6b410674109e081a200e203036000f200e202f36000b200e202e360007200e202d360003200e41026a20472d00003a0000200e20012f0184043b0000200e20012903d002370013200e411b6a2022290300370000200e41236a2021290300370000200e412b6a2020290300370000200e41336a2006290300370000200e41386a2028290000370000201841c8056a220c20114105746a200c201c4105746a220c20182f0106220e201c6b410574109e081a200c41186a2048290300370000200c41106a2049290300370000200c41086a204a290300370000200c2001290388043700002018200e41016a220c3b0106201c410274201841a8086a220e6a41086a200e20114102746a220e200c41ffff037120116b410274109e081a200e20463602000240201c20182f0106221a4f0d0020182011417f6a220c4102746a41ac086a210e0340200e2802002211200c41016a220c3b010420112018360200200e41046a210e200c201a490d000b0b41001a200141086a1a201b1a0c0d0b201841086a220c201c41016a220e4106746a200c201c4106746a220c20182f0106201c6b410674109e081a200c203036000f200c202f36000b200c202e360007200c202d360003200c41026a20472d00003a0000200c20012f0184043b0000200c20012903d002370013200c411b6a2022290300370000200c41236a2021290300370000200c412b6a2020290300370000200c41336a2006290300370000200c41386a2028290000370000201841c8056a220c200e4105746a200c201c4105746a220c20182f01062211201c6b410574109e081a200c41186a2048290300370000200c41106a2049290300370000200c41086a204a290300370000200c2001290388043700002018201141016a220c3b0106201c4102742227201841a8086a22116a41086a2011200e4102746a2211200c41ffff0371200e6b410274109e081a20112046360200202620182f010622114f0d00201820276a41ac086a210c0340200c280200220e201c41016a221c3b0104200e2018360200200c41046a210c2011201c470d000b0b204541016a210c20014180046a41026a220e201d2d00003a000020292010290300370300202520192903003703002023201429030037030020242008290300370300200141a0036a41256a22112016290000370000200141e0036a41086a221c202c290300370300200141e0036a41106a221d202b290300370300200141e0036a41186a2226202a290300370300200120012f01cc073b018004200120012903f8073703a003200120012903d0073703e003203c200e2d00003a0000203d2029290300370300203e2025290300370300203f20232903003703002040202429030037030020412011290000370000200120012f0180043b01cc02200120012903a00337039802204220262903003703002043201d2903003703002044201c290300370300200120012903e0033703f80102402018280200220e0d00204c212d200141086a220e1a20181a204f2130204e212f204d212e200c211d201a21110c0b0b20182f01042126200141086a1a204c212d20181a204f2130204e212f204d212e200e2118201a2146200c21450c000b0b201b41086a220c201a41016a22114106746a200c201a4106746a220c200e201a6b410674109e081a200c41386a2026290300370000200c41306a2027290300370000200c41286a2028290300370000200c41206a2024290300370000200c41186a2023290300370000200c41106a2025290300370000200c41086a2029290300370000200c20012903a003370000201b41c8056a220c20114105746a200c201a4105746a220c201b2f0106201a6b410574109e081a200c41186a202a290300370000200c41106a202b290300370000200c41086a202c290300370000200c20012903d007370000201b201b2f010641016a3b01060c090b200141f8076a41086a22292018200c6a220e41086a290300370300200141f8076a41106a222a200e41106a290300370300200141f8076a41186a222b200e41186a2903003703002001200e2903003703f807200e41286a2903002152200e41206a2903002153413010332224450d0c20242053370320202420012903f807370300202441286a2052370300202441186a202b290300370300202441106a202a290300370300202441086a202929030037030020014281808080103702ec04200120243602e8040240201a41506a200c470d0020012802ec0421250c060b200e41306a211d2018201a6a220e41506a21204101211a0340201d210c024002400340200141f8006a200c460d01200c200141f8006a412010a008450d0120014198016a200c460d01200c20014198016a412010a008450d01200e200c41306a220c470d000c020b0b200c41286a2903002152200c41206a2903002153200141c8046a41186a2219200c41186a290300370300200141c8046a41106a2214200c41106a290300370300200141c8046a41086a2216200c41086a2903003703002001200c2903003703c8040240201a20012802ec04470d00200141e8046a201a410110880120012802e80421240b200c41306a211d2024201a41306c6a221820012903c80437030020162903002154201429030021552019290300215620182053370320201841286a2052370300201841186a2056370300201841106a2055370300201841086a20543703002001201a41016a221a3602f0042020200c470d010b0b20012802ec042125201a4102490d05201a4102470d0441e0001033221d450d0c2001420237029c022001201d3602980202402002280200220c200b4d0d000240024002402000280200200d6a220c28020841306c221a0d004102210c0c010b200c280200210c41002118034002400240200141f8006a200c460d00200c200141f8006a412010a008210e20014198016a200c460d00200e450d00200c20014198016a412010a0080d010b200141f8016a41186a2219200c41186a290300370300200141f8016a41106a2214200c41106a290300370300200141f8016a41086a2216200c41086a2903003703002001200c2903003703f801200c41286a2903002152200c41206a290300215302402018200128029c02470d0020014198026a20184101108801200128029802211d20012802a00221180b201d201841306c6a220e20012903f801370300201629030021542014290300215520192903002156200e2053370320200e41286a2052370300200e41186a2056370300200e41106a2055370300200e41086a20543703002001201841016a22183602a0020b200c41306a210c201a41506a221a0d000b20184102460d01200128029c02210c0b200c450d08200c41306c450d08201d10350c080b0240201d2024460d002024201d412010a008450d00200141f8076a41286a220c202441286a220e2903003703002008202441206a2218290300370300202b202441186a221a290300370300202a202441106a22192903003703002029202441086a2214290300370300200120242903003703f807200e202441d8006a22162903003703002018202441d0006a220e290300370300201a202441c8006a22182903003703002019202441c0006a221a2903003703002014202441386a2219290300370300202420242903303703002016200c290300370300200e20082903003703002018202b290300370300201a202a29030037030020192029290300370300202420012903f8073703300b2001427f3703f0042001427f3703e8044100211a200141003602d0072001410036028008200142083703f807200141f8076a4100410410880120012802f8072235200128028008221641306c6a210c0240201d450d00200141e8046a41086a290300215420012903e8042157410021194100211a03400240201d20196a220e41206a2903002253205756200e41286a290300225220545620522054511b0d00200120533703e8042001201a3602d007200120523703f00420532157205221540b200c20196a2218200e290300370300200e41086a2903002155200e41106a2903002156200e41186a2903002158201841286a2052370300201841206a2053370300201841186a2058370300201841106a2056370300201841086a2055370300201a41016a211a201941306a221941e000470d000b2016201a6a2116200c20196a210c0b02402024450d00202441e0006a221d2024460d00200141e8046a41086a290300215420012903e80421572024210e0340200e41306a21180240200e41206a2903002253205756200e41286a290300225220545620522054511b0d00200120533703e8042001201a3602d007200120523703f00420532157205221540b200c200e290300370300200e41086a2903002155200e41106a2903002156200e41186a2903002158200c41286a2052370300200c41206a2053370300200c41186a2058370300200c41106a2056370300200c41086a2055370300200c41306a210c201a41016a211a201641016a21162018210e201d2018470d000b0b20012802fc072131200141003602c001200142043703b801200141003602a803200142043703a00320012802d007210c200141a0036a4100410110860120012802a003222820012802a803220e4102746a200c3602002001200e41016a220c3602a80302400240024020012802d00722184102490d00200141b8016a4100410110860120012802b80120012802c001220e4102746a201841017141037322183602002001200e41016a220e3602c0012018417e6a21180240200c20012802a403470d00200141a0036a200c410110860120012802a003212820012802a803210c0b2028200c4102746a20183602002001200c41016a22343602a80320012802d007417e6a210c200e20012802bc01470d02200141b8016a200e41011086010c010b200141b8016a4100410110860120012802b80120012802c001220e4102746a410120186b3602002001200e41016a220e3602c001410320186b21180240200c20012802a403470d00200141a0036a200c410110860120012802a003212820012802a803210c0b2028200c4102746a20183602002001200c41016a22343602a80320012802d00741026a210c200e20012802bc01470d01200141b8016a200e41011086010b20012802c001210e0b20012802b8012227200e4102746a200c3602002001200e41016a220c3602c00141041033222c450d0d200142013702d4022001202c3602d00220012802bc0121360240200c450d002027200c4102746a212620272122034002400240202228020022214102490d00202b201041186a290000370300202a201041106a2900003703002029201041086a290000370300200120102900003703f8070c010b202b2009290300370300202a200a2903003703002029200f290300370300200120012903183703f8070b02402002280200220c450d0020002802002219200c412c6c6a21142035202141306c6a211a034002400240200141f8076a2019410c6a220c460d00200c200141f8076a412010a0080d010b2019280208210c0240201620214d0d00200c41306c210e4100211820192802002220210c02400340200e450d03201a200c460d01200c201a412010a008211d201841016a2118200e41506a210e200c41306a210c201d0d000b201d4541016a41017120186a417f6a21180b2020201841306c6a220c427f200c290320225220012903e8047c22532053205254220e200c41286a220c2903002252200141e8046a41086a2903007c200ead7c225320525420532052511b220e1b370320200c427f2053200e1b3703000c010b200c450d002021201641909ac2001042000b2019412c6a22192014470d000b0b202241046a22222026470d000b0b0240203641ffffffff0371450d00202710350b20012802a40321320240024020340d00410021270c010b202820344102746a21364100212720282134034002400240203428020022224102490d00202b201041186a290000370300202a201041106a2900003703002029201041086a290000370300200120102900003703f8070c010b202b2009290300370300202a200a2903003703002029200f290300370300200120012903183703f8070b02402002280200220c450d0020002802002219200c412c6c6a21202035202241306c6a211a034002400240200141f8076a2019410c6a220c460d00200c200141f8076a412010a0080d010b201941086a2226280200211402400240201620224d0d00201441306c210e4100211820192802002221210c02400340200e450d04201a200c460d01200c201a412010a008211d201841016a2118200e41506a210e200c41306a210c201d0d000b201d4541016a41017120186a417f6a21180b42002021201841306c6a220c290320225220012903e80422547d22532053205256200c41286a2903002253200141e8046a41086a2903007d2052205454ad7d225220535620522053511b220e1b225342002052200e1b225284500d01200c41206a220c2053370300200c20523703080c020b2014450d012022201641a09ac2001042000b200c200c41306a20142018417f736a41306c109e081a20262014417f6a3602000240202720012802d402470d00200141d0026a2027410110860120012802d80221270b20012802d002222c20274102746a20223602002001202741016a22273602d8020b2019412c6a22192020470d000b0b203441046a22342036470d000b0b0240203241ffffffff0371450d00202810350b202c417c6a21182027410274220c210e024003400240200e0d00410021180c020b200e417c6a210e201841046a221828020041014b0d000b0b20012802d402211d202c210e024003400240200c0d004100210c0c020b200c417c6a210c200e280200211a200e41046a210e201a4102490d000b4101210c0b0240201d41ffffffff0371450d00202c10350b0240024020180d00200c450d0120102001290318370000201041186a2009290300370000201041106a200a290300370000201041086a200f2903003700000c060b200c450d0520012001280210417f6a360210201b41086a210c02400240201c450d00201c417f6a210e200c20114106746a2118201b20114102746a41a8086a280200210c02400340200c2f01062111200e450d01200e417f6a210e200c20114102746a41a8086a280200210c0c000b0b200c410020111b221b41086a220e2011417f6a410020111b22114106746a220c2900002152200c2900082153200c2900102154200c41186a2900002155200c2900202156200c41286a2900002158200c41306a2900002157200c41386a290000215941012137200c200e201141016a221a4106746a2011417f73220e201b2f01066a410674109e081a201b41c8056a221c20114105746a220c290000215a200c290008215b200c290010215c200c41186a290000215d200c201c201a4105746a200e201b2f01066a410574109e081a201b201b2f0106417f6a3b0106201841386a2059370000201841306a2057370000201841286a205837000020182056370020201841186a2055370000201820543700102018205337000820182052370000201041186a205d3700002010205c3700102010205b3700082010205a370000201b2f0106210c0c010b200c20114106746a200c201141016a220e4106746a2011417f73220c201b2f01066a410674109e081a201b41c8056a221820236a2018200e4105746a200c201b2f01066a410574109e081a201b201b2f0106417f6a220c3b0106410021370b200c41ffff037141044b0d0441002122200141086a210e201b210c410021200240024002400240024002400240024002400240024002400240024002400340200c280200221a450d1402400240200c33010422524200520d0041002121201a4100201a2f0106220c1b211a42002052422086200c1b200ead8421520c010b2052422086200ead844280808080707c2152410121210b02400240201a41a8086a220e2052422088a7221841016a220c41027422276a221c28020022192f01062210200e201841027422236a2226280200221d2f010622146a2233410b490d0020210d052010450d01201941c0006a2900002152201941386a2900002153201941306a2900002154201941286a2900002155201941206a2900002156201941186a2900002158201941106a290000215720192900082159201941086a201941c8006a201041067441406a109e081a201941e0056a290000215a201941d8056a290000215b201941d0056a290000215c20192900c805215d201941c8056a201941e8056a201041057441606a109e081a20200d034100211d0c040b202041016a2120201a2f01062116200141f8076a41386a222c201a41086a223420184106746a220e41386a290000370300200141f8076a41306a2236200e41306a290000370300200141f8076a41286a2228200e41286a2900003703002008200e41206a290000370300202b200e41186a290000370300202a200e41106a2900003703002029200e41086a2900003703002001200e2900003703f807200e2034200c4106746a20162018417f7322346a410674109e081a201d41086a223220144106746a220e41386a202c290300370000200e41306a2036290300370000200e41286a2028290300370000200e41206a2008290300370000200e41186a202b290300370000200e41106a202a290300370000200e41086a2029290300370000200e20012903f8073700002032201441016a22164106746a201941086a2010410674109d081a201a2f0106212c200141c8046a41186a2236201a41c8056a222820184105746a220e41186a290000370300200141c8046a41106a2218200e41106a290000370300200141c8046a41086a2232200e41086a2900003703002001200e2900003703c804200e2028200c4105746a2034202c6a410574109e081a201d41c8056a222c20144105746a220e41186a2036290300370000200e41106a2018290300370000200e41086a2032290300370000200e20012903c804370000202c20164105746a201941c8056a2010410574109d081a201c202641086a412c20276b109e081a0240200c201a2f0106221c4f0d00201a20236a41ac086a210e0340200e2802002218200c3b01042018201a360200200e41046a210e201c200c41016a220c470d000b201a2f0106211c0b201a201c417f6a3b0106201d2010201d2f01066a41016a3b0106024020204102490d00201d20164102746a41a8086a201941a8086a201041027441046a109d081a2016203341026a4f0d00201041016a2118201d20144102746a41ac086a210c2016210e0340200c280200221c200e3b0104201c201d360200200c41046a210c200e41016a210e2018417f6a22180d000b0b20191035024020222021417f73724101710d0020204101470d102016410020211b20116a2111201a20236a41a8086a280200211b0b2052a7210e201a220c2f01062218450d064101212220184105490d010c150b0b41e4dec600412041c086cc00103f000b20192802a808211d201941a8086a220c201941ac086a2010410274109e081a4100210e201d41003602000340200c280200221c200e3b0104201c2019360200200c41046a210c2010200e41016a220e470d000b2020417f6a211c20192f010621100b20192010417f6a3b0106201a20184106746a220c41206a220e290000215e200e2056370000200c41186a220e2900002156200e2058370000200c41106a220e2900002158200e2057370000200c41086a220e2900002157200e2059370000200c41c0006a220e2900002159200e2052370000200c41386a220e2900002152200e2053370000200c41306a220e2900002153200e2054370000200c41286a220c2900002154200c2055370000201a20184105746a220c41d8056a220e2900002155200e205b370000200c41d0056a220e290000215b200e205c370000200c41c8056a220e290000215c200e205d370000200c41e0056a220c290000215d200c205a3700002026280200210c02402020450d00201d450d052020417f6a201c470d06200c2f01062218410a4b0d07200c20184106746a220e41c0006a2059370000200e41386a2052370000200e41306a2053370000200e41286a2054370000200e41206a205e370000200e41186a2056370000200e41106a2058370000200e41086a2057370000200c20184105746a220e41e0056a205d370000200e41d8056a2055370000200e41d0056a205b370000200e41c8056a205c370000200c201841016a220e4102746a41a8086a2218201d360200200c200c2f010641016a3b010620182802002218200e3b01042018200c3602000c020b200c2f01062218410b4f0d07200c20184106746a220e41c0006a2059370000200e41386a2052370000200e41306a2053370000200e41286a2054370000200e41206a205e370000200e41186a2056370000200e41106a2058370000200e41086a2057370000200c20184105746a220e41d8056a2055370000200e41d0056a205b370000200e41c8056a205c370000200e41e0056a205d370000200c200c2f010641016a3b01060c010b0240024002402014450d00201d2014417f6a220e4105746a220c41e0056a2900002152200c41d8056a2900002153200c41d0056a2900002154200c41c8056a2900002155201d200e4106746a220c41c0006a2900002156200c41386a2900002158200c41306a2900002157200c41286a2900002159200c41206a290000215a200c41186a290000215b200c41106a290000215c200c41086a290000215d20200d014100210e0c020b41e4dec600412041c086cc00103f000b201d20144102746a41a8086a280200220e41003602002020417f6a2110201d2f010621140b201d2014417f6a3b0106201a20184106746a220c41206a221d290000215e201d205a370000200c41186a221d290000215a201d205b370000200c41106a221d290000215b201d205c370000200c41086a221d290000215c201d205d370000200c41c0006a221d290000215d201d2056370000200c41386a221d2900002156201d2058370000200c41306a221d2900002158201d2057370000200c41286a220c2900002157200c2059370000201a20184105746a220c41d8056a2218290000215920182053370000200c41d0056a2218290000215320182054370000200c41c8056a2218290000215420182055370000200c41e0056a220c2900002155200c2052370000201c280200211802402020450d00200e450d082020417f6a2010470d09024020182f0106220c410a4b0d00201841c8006a201841086a200c410674109e081a201841386a2056370000201841306a2058370000201841286a2057370000201841186a205a370000201841106a205b3700002018205c370008201841c0006a205d370000201841206a205e370000201841e8056a201841c8056a200c410574109e081a201841e0056a2055370000201841d8056a2059370000201841d0056a2053370000201820543700c805201841ac086a201841a8086a220c20182f010641027441046a109e081a2018200e3602a808201820182f010641016a220e3b0106200e41ffff037141016a211c4100210e0340200c280200221a200e3b0104201a2018360200200c41046a210c201c200e41016a220e470d000c030b0b41af84cc00412741c086cc00103f000b20182f0106220c410b4f0d09201841c8006a201841086a200c410674109e081a201841386a2056370000201841306a2058370000201841286a2057370000201841186a205a370000201841106a205b3700002018205c370008201841c0006a205d370000201841206a205e370000201841e8056a201841c8056a200c410574109e081a201841e0056a2055370000201841d8056a2059370000201841d0056a2053370000201820543700c805201820182f010641016a3b01060b2022417f732021710d010c0f0b0240200e2802042218450d00200e280200221a2802a808210c200e2018417f6a360204200e200c360200200c4100360200201a10350c0f0b41c3dec600412141c086cc00103f000b2011201b2f0106490d084100210e024003400240201b280200220c0d00410021114100210c0c020b200e41016a210e201b2f01042111200c211b2011200c2f01064f0d000b0b201141016a21110240200e0d00200c211b0c0e0b200c20114102746a41a8086a280200211b41002111200e417f6a220c450d0d0340201b2802a808211b200c417f6a220c0d000c0e0b0b41958dcc00412b41ecdfc600103f000b41ff83cc00413041c086cc00103f000b41af84cc00412741c086cc00103f000b41af84cc00412741c086cc00103f000b41958dcc00412b4184dfc600103f000b41ff83cc00413041c086cc00103f000b41af84cc00412741c086cc00103f000b41cfa2cc00412841c086cc00103f000b201141016a21110c040b41b09ac200412941c086cc00103f000b200b200c41809ac2001042000b41d684cc00413541c086cc00103f000b200b201941f099c2001042000b2037450d002011201b2f0106490d000340201b280200220c450d01201b2f0104210e200c211b200e200c2f01064f0d000b0b02402031450d00203141306c450d00203510350b200128029c02220c450d00200c41306c450d0020012802980210350b2025450d03202541306c450d03202410350c030b20102001290318370000201041186a2009290300370000201041106a200a290300370000201041086a200f2903003700000b2025450d01202541306c450d01202410350c010b2004410041d208109f081a41d8081033220c450d0f200c4100360200200c41046a200141f8076a41d408109d081a200c200e28020022183602a808200e200c360200200e200e280204221a41016a360204201841003b01042018200c360200200141d0026a41026a221c203c2d00003a00002010203d2903003703002019203e2903003703002014203f2903003703002008204029030037030020162041290000370000200120012f01cc023b01d00220012001290398023703f807203620422903003703002035204329030037030020342044290300370300200120012903f8013703e804201a201d470d01200c2f01062218410a4b0d03200c20184106746a220e410a6a201c2d00003a0000200e41086a20012f01d0023b0000200e41176a2030360000200e41136a202f360000200e410f6a202e360000200e410b6a202d360000200e41c0006a2016290000370000200e413b6a2008290300370000200e41236a2010290300370000200e411b6a20012903f807370000200e41336a2014290300370000200e412b6a2019290300370000200c20184105746a220e41e0056a2036290300370000200e41d8056a2035290300370000200e41d0056a2034290300370000200e41c8056a20012903e804370000200c201841016a220e4102746a41a8086a2011360200200c200e3b01062011200c3602002011200e3b010441001a201b1a0b201e201f470d010c050b0b41ff83cc00413041c086cc00103f000b41af84cc00412741c086cc00103f000b1045000b1044000b201741ffffff1f71450d00201510350b200b41016a210b0240201341ffffff3f71450d00201210350b200b2003470d000b2001280208220c0d010b2001418c086a41003602002001410036029808200141003602fc070c010b2001280210211702400240200128020c22110d00200c210e0c010b2011210e200c2108034020082802a8082108200e417f6a220e0d000b200c210e0340200e200e2f01064102746a41a8086a280200210e2011417f6a22110d000b2008210c0b20014194086a200e2f0106360200200141f8076a41186a41003602002001418c086a200e3602002001201736029808200141003602f807200141003602880820014200370380082001200c3602fc0702402017450d00200141a0036a41186a211a200141b0036a211b200141a8036a211c4100211841002111034020012017417f6a221736029808200c450d034100210802402018200c2f0106490d00034002400240200c280200220e0d002011ad21524100210e0c010b200841016a2108200c3301044220862011ad8421520b200c10352052a72111200e210c2052422088a72218200e2f01064f0d000b200e210c0b201a200c20184105746a220e41e0056a290000370300201b200e41d8056a290000370300201c200e41d0056a2900003703002001200e41c8056a2900003703a003201841016a211802402008450d00200c20184102746a41a8086a280200210c410021182008417f6a220e450d000340200c2802a808210c200e417f6a220e0d000b0b200120183602840820012011360280082001200c3602fc07200141003602f80720170d000b0b200c450d00200c280200210e200c1035200e450d000340200e280200210c200e1035200c210e200c0d000b0b200141003602d004200141003602c80402400240200041086a22322802002204450d00200141c8046a41086a21412000280200210c200141e8046a41186a2139200141d0076a41106a2146200141d0076a41086a2147200141d0026a41016a222e41286a2149202e41206a214a200141f5026a21452004210e4100212303400240200e20234b0d002023200e41dc9ac2001042000b200141d0076a41186a2248200c2023412c6c22406a221141246a29000037030020462011411c6a2900003703002047201141146a2900003703002001201129000c3703d00702402011280208450d00410021370340200c20406a280200210c200141386a41186a22152048290300370300200141386a41106a22062046290300370300200141386a41086a221e2047290300370300200120012903d007370338200141003a0058200141b8016a41186a2210200c203741306c6a220c41186a290000370300200141b8016a41106a2219200c41106a290000370300200141b8016a41086a2207200c41086a2900003703004101211d200141013a00d8012001200c2900003703b8010240024020012802c80422170d004100210c410021140c010b2017211a20012802cc04221b211c02400340201a41286a210c201a2f0106221d41216c210e41002108024002400340200821110240200e0d00201d21110c020b02400240200141386a200c41606a412010a0082208450d0041012118200841004e0d010c030b200c2d00002208450d03417f410120081b21180b201141016a2108200e415f6a210e200c41216a210c2018417f470d000b0b0240201c0d004101211d0c030b201c417f6a211c201a20114102746a41a0036a280200211a0c010b0b4100211d0b2017211a02400340201a41286a210c201a2f0106221c41216c210e41002108024002400340200821110240200e0d00201c21110c020b02400240200141b8016a200c41606a412010a0082208450d0041012118200841004e0d010c030b200c2d000022084101460d03417f4101200841014b1b21180b201141016a2108200e415f6a210e200c41216a210c2018417f470d000b0b0240201b0d00410021140c030b201b417f6a211b201a20114102746a41a0036a280200211a0c010b0b201a20114102746a41f4026a21140b2017210c0b200141a0036a41186a223a2015290300370300200141a0036a41106a223b2006290300370300200141a0036a41086a222d201e290300370300200120012903383703a003200141003a00c00302400240200c450d0020012802cc04211a0c010b200141f8076a410041eb02109f081a20494100360000204a4200370000202e41186a4200370000202e41106a4200370000202e41086a4200370000202e420037000041a00310332217450d094100211a201741003b010620174100360200201741086a200141f8076a41eb02109d081a20174198036a204529000037000020174193036a200141d0026a41206a2900003700002017418b036a200141d0026a41186a29000037000020174183036a200141d0026a41106a290000370000201741fb026a200141d0026a41086a290000370000201720012900d0023700f302200141003602cc04200120173602c8040b024002400340201741286a210c20172f0106221b41216c210e4100210802400340200821110240200e0d00201b21110c020b02400240200141a0036a200c41606a412010a0082208450d0041012118200841004e0d010c030b200c2d00002208450d04417f410120081b21180b201141016a2108200e415f6a210e200c41216a210c2018417f470d000b0b0240201a450d00201a417f6a211a201720114102746a41a0036a28020021170c010b0b203920012903a003370000203941086a202d290300370000203941106a203b290300370000203941186a203a290300370000203941206a200141a0036a41206a2d00003a0000200120413602fc04200120113602f804200120173602f0044100210c200141003602ec042001200141c8046a3602f4040c010b200120413602fc04200120113602f804200120173602f0042001201a3602ec042001200141c8046a3602f4044101210c0b2001200c3602e804200141f8076a41086a2234201e290300370300200141f8076a41106a22352006290300370300200141f8076a41186a22362015290300370300200141f8076a41206a221c200141386a41206a2d00003a0000200120012903383703f80741341033220c450d08200c4200370208200c428180808010370200200c20012903f807370210200c20012f00d0023b0031200c41186a2034290300370200200c41206a2035290300370200200c41286a2036290300370200200c41306a201c2d00003a0000200c41336a200141d0026a41026a22152d00003a000002400240024002400240024002400240200141e8046a200c10ac02280200222628020041016a220c41014d0d002026200c360200203a2010290300370300203b2019290300370300202d2007290300370300200120012903b8013703a003200141013a00c0030240024020012802c8042217450d0020012802cc04211a0c010b200141f8076a410041eb02109f081a20494100360000204a4200370000202e41186a4200370000202e41106a4200370000202e41086a4200370000202e420037000041a00310332217450d114100211a201741003b010620174100360200201741086a200141f8076a41eb02109d081a20174198036a204529000037000020174193036a200141d0026a41206a2900003700002017418b036a200141d0026a41186a29000037000020174183036a200141d0026a41106a290000370000201741fb026a200141d0026a41086a290000370000201720012900d0023700f302200141003602cc04200120173602c8040b024002400340201741286a210c20172f0106221b41216c210e4100210802400340200821110240200e0d00201b21110c020b02400240200141a0036a200c41606a412010a0082208450d0041012118200841004e0d010c030b200c2d000022084101460d04417f4101200841014b1b21180b201141016a2108200e415f6a210e200c41216a210c2018417f470d000b0b0240201a450d00201a417f6a211a201720114102746a41a0036a28020021170c010b0b203920012903a003370000203941086a202d290300370000203941106a203b290300370000203941186a203a290300370000203941206a200141a0036a41206a2d00003a0000200120413602fc04200120113602f804200120173602f0044100210c200141003602ec042001200141c8046a3602f4040c010b200120413602fc04200120113602f804200120173602f0042001201a3602ec042001200141c8046a3602f4044101210c0b2001200c3602e804203420072903003703002035201929030037030020362010290300370300201c200141b8016a41206a2d00003a0000200120012903b8013703f80741341033220c450d10200c4200370208200c428180808010370200200c20012903f807370210200c20012f00d0023b0031200c41186a2034290300370200200c41206a2035290300370200200c41286a2036290300370200200c41306a201c2d00003a0000200c41336a20152d00003a0000200141e8046a200c10ac022802002227280200220e41016a220c41014d0d002027200c360200024002400240024002400240024002400240024002400240024002400240024002400240201d450d0020140d03202628020041016a220c41014d0d122026200c36020020272802080d0b2027417f360208202728020c220c0d014100210c0c020b2014450d03200141f8076a202610ad022001280284082144200128028008214e20012802fc07213820012802f807212f200141f8076a202710ad022001280284082142200128028008214f20012802fc0721300240202f20012802f807223e460d00202f28020841016a220c41004c0d0d202f200c360208203e280208220c41016a220e41004c0d0c203e200e360208202f41106a203e41106a412010a0080d0e202f2d0030203e2d0030470d0e203e200c360208202f202f280208417f6a3602080b20302042410274222b6a211c20382044410274222a6a2111202a0d04410021170c050b200c200c280200417f6a3602000240202728020c220c2802000d000240200c28020c220e450d00200e200e280200417f6a360200200c28020c220e2802000d000240200e28020c450d00200e410c6a10ae02200c28020c210e0b200e200e280204417f6a360204200c28020c220c2802040d00200c10350b202728020c220c200c280204417f6a360204202728020c220c2802040d00200c10350b202728020841016a210c0b2027200c3602080c130b200e417e4f0d0e2027200e41026a36020020262802080d062026417f36020802400240202628020c220c0d004100210c0c010b200c200c280200417f6a3602000240202628020c220c2802000d000240200c28020c220e450d00200e200e280200417f6a360200200c28020c220e2802000d000240200e28020c450d00200e410c6a10ae02200c28020c210e0b200e200e280204417f6a360204200c28020c220c2802040d00200c10350b202628020c220c200c280204417f6a360204202628020c220c2802040d00200c10350b202628020841016a210c0b2026200c3602082026202736020c0c130b202628020041016a220c41014d0d0d2026200c36020020272802080d042027417f3602080240202728020c220c0d00202741003602080c120b200c200c280200417f6a3602000240202728020c220c2802000d000240200c28020c220e450d00200e200e280200417f6a360200200c28020c220e2802000d000240200e28020c450d00200e410c6a10ae02200c28020c210e0b200e200e280204417f6a360204200c28020c220c2802040d00200c10350b202728020c220c200c280204417f6a360204202728020c220c2802040d00200c10350b2027202728020841016a3602080c110b41002117201c210820112118034020302008460d01024002402018417c6a2218280200220c2008417c6a2208280200220e460d00200c28020841016a221a41004c0d05200c201a360208200e280208221a41016a221b41004c0d04200e201b360208200c41106a200e41106a412010a0080d01200c2d0030200e2d0030470d01200e201a360208200c200c280208417f6a3602080b201741016a211720382018470d010c020b0b200e201a360208200c200c280208417f6a3602080b2001410036028008200142043703f807204420176b211a204220176b220b41016a210e024020300d004100210c2038450d0a201a450d0a201a201120386b410276220c200c201a4b1b210c0c0a0b2038450d084100210c410021080240200e450d00200e201c20306b41027622082008200e4b1b21080b0240201a450d00201a201120386b410276220c200c201a4b1b210c0b2008200c6a220c20084f0d09410421144100211841002115203021080340024002402008450d000240200e0d004100210e0c010b200e417f6a210e201c2008460d002008280200220c28020041016a221741014d0d0e200c2017360200200c450d00200841046a21080c010b201a450d0c201120386b410276220c4100200c201a6b22082008200c4b1b220c4d0d0c2011200c4102746b417c6a2211280200220c28020041016a220841014d0d0d200c2008360200200c450d0c201a417f6a211a410021080b0240201520012802fc07470d0002400240024020080d00201a0d01410021170c020b4100211b410021170240200e450d00200e201c20086b41027622172017200e4b1b21170b0240201a450d00201a201120386b410276221b201b201a4b1b211b0b417f2017201b6a221b201b2017491b21170c010b201a201120386b41027622172017201a4b1b21170b200141f8076a2015417f201741016a221b201b2017491b10860120012802f80721140b201420186a200c3602002001201541016a221536028008201841046a21180c000b0b41ac96cc004118200141a8046a41fc9ac20041d496cc001046000b41ac96cc004118200141a8046a41fc9ac20041d496cc001046000b41a797cc004110200141a8046a41a08bc50041c897cc001046000b41a797cc004110200141a8046a41a08bc50041c897cc001046000b41a797cc004110200141a8046a41a08bc50041c897cc001046000b41ac96cc004118200141a8046a41fc9ac20041d496cc001046000b41ac96cc004118200141a8046a41fc9ac20041d496cc001046000b203e200c360208202f202f280208417f6a360208204fad4220862030ad842252204ead4220862038ad842253204420424b22151b2254a7211d02400240024002402042204420151b2206410274220e450d00201d200e6a211c41012118201d2111201d21080340024002402018450d00201c20116b41027620184d0d03201120184102746a21110c010b201c2011460d020b2008280200221728020041016a220c41014d0d082017200c3602002011280200220c2802080d02200841046a2108200c417f360208410021184100211a0240200c28020c221b450d00201b201b280200417f6a3602000240200c28020c221a2802000d000240201a28020c221b450d00201b201b280200417f6a360200201a28020c221b2802000d000240201b28020c450d00201b410c6a10ae02201a28020c211b0b201b201b280204417f6a360204201a28020c221a2802040d00201a10350b200c28020c221a201a280204417f6a360204200c28020c221a2802040d00201a10350b200c28020841016a211a0b201141046a2111200c201a360208200c201736020c201c2008470d000b0b2006450d0102402044204220151b22180d0041004100419c9bc2001042000b2053205220151b2252a72217280200221128020041016a220c41014d0d062011200c360200201d280200220c2802080d02200c417f36020802400240200c28020c22080d00410021080c010b20082008280200417f6a3602000240200c28020c22082802000d000240200828020c221a450d00201a201a280200417f6a360200200828020c221a2802000d000240201a28020c450d00201a410c6a10ae02200828020c211a0b201a201a280204417f6a360204200828020c22082802040d00200810350b200c28020c22082008280204417f6a360204200c28020c22082802040d00200810350b200c28020841016a21080b2052422088215220544220882153200c2008360208200c201136020c201841027421112017210c0340200c28020022082008280200417f6a3602000240200c28020022082802000d000240200828020c2218450d0020182018280200417f6a360200200828020c22182802000d000240201828020c450d002018410c6a10ae02200828020c21180b20182018280204417f6a360204200828020c22082802040d00200810350b200c28020022082008280204417f6a360204200c28020022082802040d00200810350b200c41046a210c2011417c6a22110d000b02402052500d002052a7410274450d00201710350b201d210c0340200c28020022112011280200417f6a3602000240200c28020022112802000d000240201128020c2208450d0020082008280200417f6a360200201128020c22082802000d000240200828020c450d002008410c6a10ae02201128020c21080b20082008280204417f6a360204201128020c22112802040d00201110350b200c28020022112011280204417f6a360204200c28020022112802040d00201110350b200c41046a210c200e417c6a220e0d000b02402053500d002053a7410274450d00201d10350b203e203e280200417f6a220c360200203741016a2137200c0d090240203e28020c220c450d00200c200c280200417f6a360200203e28020c220c2802000d000240200c28020c450d00200c410c6a10ae02203e28020c210c0b200c200c280204417f6a360204203e28020c220c2802040d00200c10350b203e203e280204417f6a220c360204200c0d09203e10350c090b41a797cc004110200141a8046a41a08bc50041c897cc001046000b41004100418c9bc2001042000b41a797cc004110200141a8046a41a08bc50041c897cc001046000b0240200e0d004100210c0c010b200e201c20306b410276220c200c200e4b1b210c0b200141f8076a4100200c10860120012802f807221420012802800822154102746a210c02402030450d00200e450d00203020424102746a211b2042417f7320176a21082030210e0340201b200e460d01200e280200221828020041016a221741014d0d0320182017360200200c2018360200201541016a2115200c41046a210c200e41046a210e200841016a221820084f21172018210820170d000b0b02402038450d00201a450d000240201120386b410276220e201a4d0d00200e201a417f736a2208200e4f0d01201120084102746b417c6a21110b20112038460d0003402011417c6a2211280200220e28020041016a220841014d0d03200e2008360200200c200e360200201541016a2115200c41046a210c20382011470d000b0b20012015360280080b20012802fc07215120014198026a41186a224b420037030020014198026a41106a224c420037030020014198026a41086a224d42003703002001420037039802203a4200370300203b4200370300202d4200370300200142003703a0034100211e0240024020150d00427f2152427f2153410021074100212c410021250c010b2015417f6a2116427f215241002107427f21534100212c41002125427f2155427f21544100211a0240024002400240024003402014201a4102746a280200220c28020841016a220e41004c0d01201a41016a211b0240200c2d00300d00200c200e360208200141d0026a41186a221c200c41286a290000370300200141d0026a41106a221d200c41206a290000370300200141d0026a41086a2206200c41186a290000370300200c200c280208417f6a3602082001200c2900103703d0022015201b41002016201a4b1b220c4d0d032014200c4102746a280200220c28020841016a220e41004c0d04200c200e3602082039200c41286a290000370300200141e8046a41106a2210200c41206a290000370300200141e8046a41086a2219200c41186a290000370300200c200c280208417f6a3602082001200c2900103703e8042015201a2015201a1b417f6a220c4d0d052014200c4102746a280200220c28020841016a220e41004c0d06200c200e3602082036200c41286a2900003703002035200c41206a2900003703002034200c41186a290000370300200c200c280208417f6a3602082001200c2900103703f8072032280200412c6c220e2111200028020022082118024003402018210c2011450d010240200141d0026a200c410c6a2217460d00201141546a2111200c412c6a21182017200141d0026a412010a0080d010b0b200c41086a28020041306c2111200c280200211803402018210c2011450d010240200141e8046a200c460d00201141506a2111200c41306a2118200c200141e8046a412010a0080d010b0b2052200c41206a2903002258582054200c41286a29030022565820542056511b0d00204b2039290300370300204c2010290300370300204d2019290300370300202d2006290300370300203b201d290300370300203a201c290300370300200120012903e80437039802200120012903d0023703a0034101212c2058215220562153201a2107201a212520562155205621540b03402008210c200e450d010240200141d0026a200c410c6a2211460d00200e41546a210e200c412c6a21082011200141d0026a412010a0080d010b0b200c41086a28020041306c210e200c280200211103402011210c200e450d010240200141f8076a200c460d00200e41506a210e200c41306a2111200c200141f8076a412010a0080d010b0b205521542052200c41206a2903002258582055200c41286a29030022565820552056511b0d00204b2036290300370300204c2035290300370300204d2034290300370300202d2006290300370300203b201d290300370300203a201c290300370300200120012903f80737039802200120012903d0023703a0034100212c2058215220562153201a2107201a212520562155205621540b201b211a201b2015460d060c000b0b41ac96cc004118200141a8046a41fc9ac20041d496cc001046000b200c201541ac9bc2001042000b41ac96cc004118200141a8046a41fc9ac20041d496cc001046000b200c201541bc9bc2001042000b41ac96cc004118200141a8046a41fc9ac20041d496cc001046000b200141003602d802200142043703d0022025202c6a21500240024020150d0041012119417f213f0c010b2015417f6a213f41012119205041017121434100211e202c212041002106024003400240024002400240024002400240201420064102746a2229280200221028020841016a220c41004c0d00200641016a21222010200c36020820102d00300d0620152006201520061b417f6a220c4d0d012014200c4102746a2233280200222828020841016a220c41004c0d022028200c36020802402032280200220c0d002022210c2006211b0c060b20002802002217200c412c6c6a211d202841106a210e201041106a211a202c45200620074671213120430d034100211c2006211b034002400240201a2017410c6a220c460d00200c201a412010a0080d010b201741086a2224280200222141306c21114100210820172802002216210c024003402011450d02200e200c460d01200c200e412010a0082118200841016a2108201141506a2111200c41306a210c20180d000b20184541016a41017120086a417f6a21080b0240427f2016200841306c6a220c290320225520527c225420542055542211200c41286a290300225420537c2011ad7c225620545420562054511b22111b4200205520527d22582058205556205420537d2055205254ad7d225520545620552054511b22181b201b41017122161b2254427f205620111b4200205520181b20161b225584500d00200c41206a220c2054370300200c20553703080c010b200c200c41306a20212008417f736a41306c109e081a20242021417f6a36020041002120410020192023201c461b211902402031450d00200721252007211b0c010b2029280200220c28020041016a221141014d0d0c200c20113602002033280200221128020041016a220841014d0d0c201120083602000240201e20012802d402470d00200141d0026a201e410110900120012802d802211e0b20012802d002201e4103746a220820113602042008200c3602002001201e41016a221e3602d802202c2120200721252006211b0b201c41016a211c2017412c6a2217201d470d000c050b0b41ac96cc004118200141a8046a41fc9ac20041d496cc001046000b200c201541cc9bc2001042000b41ac96cc004118200141a8046a41fc9ac20041d496cc001046000b4100211c2006211b034002400240201a2017410c6a220c460d00200c201a412010a0080d010b201741086a2224280200222141306c21114100210820172802002216210c024003402011450d02200e200c460d01200c200e412010a0082118200841016a2108201141506a2111200c41306a210c20180d000b20184541016a41017120086a417f6a21080b024042002016200841306c6a220c290320225520527d22542054205556200c41286a290300225420537d2055205254ad7d225620545620562054511b22111b427f205520527c225820582055542218205420537c2018ad7c225520545420552054511b22181b201b41017122161b22544200205620111b427f205520181b20161b225584500d00200c41206a220c2054370300200c20553703080c010b200c200c41306a20212008417f736a41306c109e081a20242021417f6a36020041002120410020192023201c461b211902402031450d00200721252007211b0c010b2029280200220c28020041016a22114102490d08200c20113602002033280200221128020041016a22084102490d08201120083602000240201e20012802d402470d00200141d0026a201e410110900120012802d802211e0b20012802d002201e4103746a220820113602042008200c3602002001201e41016a221e3602d802202c2120200721252006211b0b201c41016a211c2017412c6a2217201d470d000b0b201b41016a210c0b024002400240024002402015200c4100203f201b4b1b220c4d0d002014200c4102746a280200223128020841016a220c41004c0d012031200c3602082032280200220e450d0420002802002217200e412c6c6a211d202c4101462006200746712133203141106a210e201041106a211a201420224100203f20064b1b223c4102746a213d20430d024100211c034002400240201a2017410c6a220c460d00200c201a412010a0080d010b201741086a2224280200222141306c21114100210820172802002216210c024003402011450d02200e200c460d01200c200e412010a0082118200841016a2108201141506a2111200c41306a210c20180d000b20184541016a41017120086a417f6a21080b024042002016200841306c6a220c290320225520527d22542054205556200c41286a290300225420537d2055205254ad7d225620545620562054511b22111b427f205520527c225820582055542218205420537c2018ad7c225520545420552054511b22181b201b41017122161b22544200205620111b427f205520181b20161b225584500d00200c41206a220c2054370300200c20553703080c010b200c200c41306a20212008417f736a41306c109e081a20242021417f6a360200410020192023201c461b21194101212002402033450d00200721252007211b0c010b2029280200220c28020041016a221141014d0d0b200c20113602002015203c4d0d09203d280200221128020041016a220841014d0d0b201120083602000240201e20012802d402470d00200141d0026a201e410110900120012802d802211e0b20012802d002201e4103746a220820113602042008200c3602002001201e41016a221e3602d802202c2120200721252006211b0b201c41016a211c2017412c6a2217201d470d000c040b0b200c201541dc9bc2001042000b41ac96cc004118200141a8046a41fc9ac20041d496cc001046000b4100211c034002400240201a2017410c6a220c460d00200c201a412010a0080d010b201741086a2224280200222141306c21114100210820172802002216210c024003402011450d02200e200c460d01200c200e412010a0082118200841016a2108201141506a2111200c41306a210c20180d000b20184541016a41017120086a417f6a21080b0240427f2016200841306c6a220c290320225520527c225420542055542211200c41286a290300225420537c2011ad7c225620545420562054511b22111b4200205520527d22582058205556205420537d2055205254ad7d225520545620552054511b22181b201b41017122161b2254427f205620111b4200205520181b20161b225584500d00200c41206a220c2054370300200c20553703080c010b200c200c41306a20212008417f736a41306c109e081a20242021417f6a360200410020192023201c461b21194101212002402033450d00200721252007211b0c010b2029280200220c28020041016a22114102490d08200c20113602002015203c4d0d06203d280200221128020041016a22084102490d08201120083602000240201e20012802d402470d00200141d0026a201e410110900120012802d802211e0b20012802d002201e4103746a220820113602042008200c3602002001201e41016a221e3602d802202c2120200721252006211b0b201c41016a211c2017412c6a2217201d470d000b0b2031280208210c0b2031200c417f6a36020820282028280208417f6a3602082010280208210c0b2010200c417f6a3602082022210620222015470d000b2020212c0c010b203c201541ec9bc2001042000b0240202c4101470d002025203f460d030b41c0001033220e450d10200e20012903a003370000200e200129039802370020200e41186a203a290300370000200e41106a203b290300370000200e41086a202d290300370000200e41286a204d290300370000200e41306a204c290300370000200e41386a204b290300370000024002402050200b4b0d002042417f6a221b450d014100210802400240024002400240034020082042460d01203020084102746a2217280200220c280200221141016a221841014d0d08200c2018360200200c28020841016a41004c0d02200c20113602002039200c41286a290000370300200141e8046a41106a200c41206a290000370300200141e8046a41086a200c41186a2900003703002001200c2900103703e8042042200841016a22084d0d03203020084102746a221a280200220c280200221141016a221841014d0d08200c2018360200200c28020841016a41004c0d04200c20113602002036200c41286a2900003703002035200c41206a2900003703002034200c41186a2900003703002001200c2900103703f8074100210c02400340200c41c000460d01200e200c6a2111200c41206a210c2011200141e8046a412010a0080d000b4100210c0340200c41c000460d01200e200c6a2111200c41206a210c2011200141f8076a412010a0080d000c090b0b2017280200221128020041016a220c41014d0d082011200c360200201a280200220c2802080d05200c417f36020802400240200c28020c22180d00410021180c010b20182018280200417f6a3602000240200c28020c22182802000d000240201828020c2217450d0020172017280200417f6a360200201828020c22172802000d000240201728020c450d002017410c6a10ae02201828020c21170b20172017280204417f6a360204201828020c22182802040d00201810350b200c28020c22182018280204417f6a360204200c28020c22182802040d00201810350b200c28020841016a21180b200c2018360208200c201136020c2008201b470d000c070b0b20422042419c9cc2001042000b41ac96cc004118200141a8046a41fc9ac20041d496cc001046000b2008204241ac9cc2001042000b41ac96cc004118200141a8046a41fc9ac20041d496cc001046000b41a797cc004110200141a8046a41a08bc50041c897cc001046000b02402044417f6a221b450d004100210802400240024002400240034020082044460d01203820084102746a2217280200220c280200221141016a221841014d0d08200c2018360200200c28020841016a41004c0d02200c20113602002039200c41286a290000370300200141e8046a41106a200c41206a290000370300200141e8046a41086a200c41186a2900003703002001200c2900103703e8042044200841016a22084d0d03203820084102746a221a280200220c280200221141016a221841014d0d08200c2018360200200c28020841016a41004c0d04200c20113602002036200c41286a2900003703002035200c41206a2900003703002034200c41186a2900003703002001200c2900103703f8074100210c02400340200c41c000460d01200e200c6a2111200c41206a210c2011200141e8046a412010a0080d000b4100210c0340200c41c000460d01200e200c6a2111200c41206a210c2011200141f8076a412010a0080d000c080b0b2017280200221128020041016a220c41014d0d082011200c360200201a280200220c2802080d05200c417f36020802400240200c28020c22180d00410021180c010b20182018280200417f6a3602000240200c28020c22182802000d000240201828020c2217450d0020172017280200417f6a360200201828020c22172802000d000240201728020c450d002017410c6a10ae02201828020c21170b20172017280204417f6a360204201828020c22182802040d00201810350b200c28020c22182018280204417f6a360204200c28020c22182802040d00201810350b200c28020841016a21180b200c2018360208200c201136020c2008201b470d000c060b0b2044204441fc9bc2001042000b41ac96cc004118200141a8046a41fc9ac20041d496cc001046000b20082044418c9cc2001042000b41ac96cc004118200141a8046a41fc9ac20041d496cc001046000b41a797cc004110200141a8046a41a08bc50041c897cc001046000b202728020041016a220c41014d0d012027200c360200024020262802080d002026417f36020802400240202628020c220c0d004100210c0c010b200c200c280200417f6a3602000240202628020c220c2802000d000240200c28020c2211450d0020112011280200417f6a360200200c28020c22112802000d000240201128020c450d002011410c6a10ae02200c28020c21110b20112011280204417f6a360204200c28020c220c2802040d00200c10350b202628020c220c200c280204417f6a360204202628020c220c2802040d00200c10350b202628020841016a210c0b2026200c3602082026202736020c200e10350c040b41a797cc004110200141a8046a41a08bc50041c897cc001046000b202628020041016a220c41014d0d002026200c36020020272802080d012027417f36020802400240202728020c220c0d004100210c0c010b200c200c280200417f6a3602000240202728020c220c2802000d000240200c28020c2211450d0020112011280200417f6a360200200c28020c22112802000d000240201128020c450d002011410c6a10ae02200c28020c21110b20112011280204417f6a360204200c28020c220c2802040d00200c10350b202728020c220c200c280204417f6a360204202728020c220c2802040d00200c10350b202728020841016a210c0b2027200c3602082027202636020c200e10350c020b00000b41a797cc004110200141a8046a41a08bc50041c897cc001046000b20012802d0022217201e4103746a210820012802d402211b2017210e0240024002400240201e450d0020172111024003402011280200220c450d010240024002400240200c201141046a280200220e10af020d00200e200c10af02450d03200e2802080d09200e417f360208200e28020c22180d01410021180c020b200c2802080d07200c417f36020802400240200c28020c22180d00410021180c010b20182018280200417f6a3602000240200c28020c22182802000d000240201828020c221a450d00201a201a280200417f6a360200201828020c221a2802000d000240201a28020c450d00201a410c6a10ae02201828020c211a0b201a201a280204417f6a360204201828020c22182802040d00201810350b200c28020c22182018280204417f6a360204200c28020c22182802040d00201810350b200c28020841016a21180b200c2018360208200c410036020c0c020b20182018280200417f6a3602000240200e28020c22182802000d000240201828020c221a450d00201a201a280200417f6a360200201828020c221a2802000d000240201a28020c450d00201a410c6a10ae02201828020c211a0b201a201a280204417f6a360204201828020c22182802040d00201810350b200e28020c22182018280204417f6a360204200e28020c22182802040d00201810350b200e28020841016a21180b200e2018360208200e410036020c0b200e200e280200417f6a2218360200024020180d000240200e28020c2218450d0020182018280200417f6a360200200e28020c22182802000d000240201828020c450d002018410c6a10ae02200e28020c21180b20182018280204417f6a360204200e28020c22182802040d00201810350b200e200e280204417f6a221836020420180d00200e10350b200c200c280200417f6a220e3602000240200e0d000240200c28020c220e450d00200e200e280200417f6a360200200c28020c220e2802000d000240200e28020c450d00200e410c6a10ae02200c28020c210e0b200e200e280204417f6a360204200c28020c220e2802040d00200e10350b200c200c280204417f6a220e360204200e0d00200c10350b201141086a22112008470d000c030b0b201141086a210e0b2008200e460d000340200e220c280200220e200e280200417f6a3602000240200c280200220e2802000d000240200e28020c2211450d0020112011280200417f6a360200200e28020c22112802000d000240201128020c450d002011410c6a10ae02200e28020c21110b20112011280204417f6a360204200e28020c220e2802040d00200e10350b200c280200220e200e280204417f6a360204200c280200220e2802040d00200e10350b200c41086a210e200c41046a220c28020022112011280200417f6a3602000240200c28020022112802000d000240201128020c2218450d0020182018280200417f6a360200201128020c22182802000d000240201828020c450d002018410c6a10ae02201128020c21180b20182018280204417f6a360204201128020c22112802040d00201110350b200c28020022112011280204417f6a360204200c280200220c2802040d00200c10350b2008200e470d000b0b0240201b41ffffffff0171450d00201710350b02402015450d002015410274210e2014210c0340200c28020022112011280200417f6a3602000240200c28020022112802000d000240201128020c2208450d0020082008280200417f6a360200201128020c22082802000d000240200828020c450d002008410c6a10ae02201128020c21080b20082008280204417f6a360204201128020c22112802040d00201110350b200c28020022112011280204417f6a360204200c28020022112802040d00201110350b200c41046a210c200e417c6a220e0d000b0b0240205141ffffffff0371450d00201410350b02402042450d002030210c0340200c280200220e200e280200417f6a3602000240200c280200220e2802000d000240200e28020c2211450d0020112011280200417f6a360200200e28020c22112802000d000240201128020c450d002011410c6a10ae02200e28020c21110b20112011280204417f6a360204200e28020c220e2802040d00200e10350b200c280200220e200e280204417f6a360204200c280200220e2802040d00200e10350b200c41046a210c202b417c6a222b0d000b0b0240204f41ffffffff0371450d00203010350b203e203e280200417f6a220c3602000240200c0d000240203e28020c220c450d00200c200c280200417f6a360200203e28020c220c2802000d000240200c28020c450d00200c410c6a10ae02203e28020c210c0b200c200c280204417f6a360204203e28020c220c2802040d00200c10350b203e203e280204417f6a220c360204200c0d00203e10350b201941ff0171210802402044450d002038210c0340200c280200220e200e280200417f6a3602000240200c280200220e2802000d000240200e28020c2211450d0020112011280200417f6a360200200e28020c22112802000d000240201128020c450d002011410c6a10ae02200e28020c21110b20112011280204417f6a360204200e28020c220e2802040d00200e10350b200c280200220e200e280204417f6a360204200c280200220e2802040d00200e10350b200c41046a210c202a417c6a222a0d000b0b203720086a2137204e41ffffffff0371450d02203810350c020b41a797cc004110200141a8046a41a08bc50041c897cc001046000b41a797cc004110200141a8046a41a08bc50041c897cc001046000b202f202f280200417f6a220c3602000240200c0d000240202f28020c220c450d00200c200c280200417f6a360200202f28020c220c2802000d000240200c28020c450d00200c410c6a10ae02202f28020c210c0b200c200c280204417f6a360204202f28020c220c2802040d00200c10350b202f202f280204417f6a220c360204200c0d00202f10350b20272027280200417f6a220c3602000240200c0d000240202728020c220c450d00200c200c280200417f6a360200202728020c220c2802000d000240200c28020c450d00200c410c6a10ae02202728020c210c0b200c200c280204417f6a360204202728020c220c2802040d00200c10350b20272027280204417f6a220c360204200c0d00202710350b20262026280200417f6a220c360200200c0d030240202628020c220c450d00200c200c280200417f6a360200202628020c220c2802000d000240200c28020c450d00200c410c6a10ae02202628020c210c0b200c200c280204417f6a360204202628020c220c2802040d00200c10350b20262026280204417f6a220c360204200c0d030c020b2027202636020c0b20272027280200417f6a220c3602000240200c0d000240202728020c220c450d00200c200c280200417f6a360200202728020c220c2802000d000240200c28020c450d00200c410c6a10ae02202728020c210c0b200c200c280204417f6a360204202728020c220c2802040d00200c10350b20272027280204417f6a220c360204200c0d00202710350b203741016a213720262026280200417f6a220c360200200c0d010240202628020c220c450d00200c200c280200417f6a360200202628020c220c2802000d000240200c28020c450d00200c410c6a10ae02202628020c210c0b200c200c280204417f6a360204202628020c220c2802040d00200c10350b20262026280204417f6a220c360204200c0d010b202610350b02402032280200220e20234d0d002000280200220c20406a28020820374d0d020c010b0b2023200e41ec9ac2001042000b202341016a22232004470d000b20012802c804220c0d010b2001418c086a41003602002001410036029808200141003602fc070c030b20012802d004211a0240024020012802cc0422110d00200c210e0c010b2011210e200c2108034020082802a0032108200e417f6a220e0d000b200c210e0340200e200e2f01064102746a41a0036a280200210e2011417f6a22110d000b2008210c0b20014194086a200e2f010636020020014190086a41003602002001418c086a200e3602002001201a36029808200141003602f807200141003602880820014200370380082001200c3602fc07201a450d014100211841002111024003402001201a417f6a221a36029808200c450d014100210802402018200c2f0106490d00034002400240200c280200220e0d002011ad21524100210e0c010b200841016a2108200c3301044220862011ad8421520b200c10352052a72111200e210c2052422088a72218200e2f01064f0d000b200e210c0b201841016a210e200c20184102746a41f4026a2802002117200c201841216c6a41286a2d0000211b0240024020080d00200e21180c010b200c200e4102746a41a0036a280200210c410021182008417f6a220e450d000340200c2802a003210c200e417f6a220e0d000b0b200120183602840820012011360280082001200c3602fc07200141003602f807201b41ff01714102460d0320172017280200417f6a220e3602000240200e0d000240201728020c220e450d00200e200e280200417f6a360200201728020c220e2802000d000240200e28020c450d00200e410c6a10ae02201728020c210e0b200e200e280204417f6a360204201728020c220e2802040d00200e10350b20172017280204417f6a220e360204200e0d00201710350b201a0d000c030b0b41958dcc00412b41c08dcc00103f000b41958dcc00412b41c08dcc00103f000b200c450d00200c280200210e200c1035200e450d000340200e280200210c200e1035200c210e200c0d000b0b200141d0106a24000f0b103c000bdb21011d7f230041b0046b220224000240024002400240024002400240024020002802004101460d00200041146a2802002203200328020041016a360200200041106a28020021042000410c6a2802002105200041086a280200210320002802042106200241e0006a41206a2207200041386a2d00003a0000200241e0006a41186a2208200041306a290000370300200241e0006a41106a2209200041286a290000370300200241e0006a41086a220a200041206a2900003703002002200041186a29000037036020032f0106220b410b490d01200241c0016a410041eb02109f081a200241d9006a4100360000200241306a41216a4200370000200241c9006a4200370000200241c1006a4200370000200241396a42003700002002420037003141a0031033220c450d05200c41003b0106200c4100360200200c41086a200241c0016a41eb02109d082107200c4198036a200241d5006a290000370000200c4193036a200241306a41206a290000370000200c418b036a200241306a41186a290000370000200c4183036a200241306a41106a290000370000200c41fb026a200241306a41086a290000370000200c20022900303700f3022002200341ce016a2f00003b01182002200341d0016a2d00003a001a200341d1016a280000210d200341d5016a280000210e200341d9016a280000210f200341dd016a28000021102002200341e7016a2900003701c6012002200341e1016a2900003703c001200328028c0321112007200341ef016a20032f010641796a220041216c109d082107200c41f4026a20034190036a2000410274109d082108200341063b0106200c20003b01062002412c6a41026a20022d001a3a0000200220022f01183b012c200220022903c001370330200220022901c6013701360240024020044107490d00200441216c20076a220741ba7e6a200741997e6a2207200041ffff0371200441796a22096b41216c109e081a200741206a200241e0006a41206a2d00003a0000200741186a200241e0006a41186a290300370000200741106a200241e0006a41106a290300370000200741086a200241e0006a41086a29030037000020072002290360370000200441027420086a41686a2107200820094102746a2112200c41066a22002f010020096b21040c010b200341086a200441216c6a220741216a2007200341066a22002f010020046b41216c109e081a200741206a200241e0006a41206a2d00003a0000200741186a200241e0006a41186a290300370000200741106a200241e0006a41106a290300370000200741086a200241e0006a41086a29030037000020072002290360370000200341f4026a20044102746a221241046a210720002f010020046b21040b200720122004410274109e081a20122001360200200241146a41026a2002412c6a41026a22132d000022013a0000200020002f010041016a3b0100200241106a41026a221420013a000020022002290136370196012002200229033037039001200220022f012c22003b0114200220003b0110200220022903900137030020022002290196013701060240200328020022070d00410021000c040b20032f01042115200241c0016a4102722116200241306a41016a210a410021000340201320142d00003a0000200220022f01103b012c200220022903003703182002200229010637011e20062000470d03201541ffff0371210802400240024020072f01062200410b490d00200a41286a4100360000200a41206a4200370000200a41186a4200370000200a41106a4200370000200a41086a4200370000200a42003700002016410041ed02109f081a200241e0006a41086a22004200370300200241e0006a41106a22034200370300200241e0006a41186a22044200370300200241e0006a41206a22094200370300200241e0006a41286a220b420037030020024190016a41256a2217200241306a41256a29000037000020024190016a41206a2218200241306a41206a29000037030020024190016a41186a2219200241306a41186a29000037030020024190016a41106a221a200241306a41106a29000037030020024190016a41086a221b200241306a41086a29000037030020024200370360200220022900303703900141d00310332201450d0920014100360200200141046a200241c0016a41ef02109d081a20014198036a201729000037000020014193036a20182903003700002001418b036a201929030037000020014183036a201a290300370000200141fb026a201b29030037000020012002290390013700f302200120022903603702a003200141a8036a2000290300370200200141b0036a2003290300370200200141b8036a2004290300370200200141c0036a2009290300370200200141c8036a200b29030037020020024190016a41026a220b200741d0016a2d00003a00002002200741ce016a2f00003b0190012002200741e1016a2900003703c0012002200741e7016a2900003701c601200741d1016a2800002118200741d5016a2800002119200741d9016a280000211a200741dd016a280000211b200728028c03211c200141086a200741ef016a20072f0106220341796a220041216c109d08211d200141f4026a20074190036a2000410274109d08211e200141a0036a200741bc036a2003417a6a2209410274109d082117200741063b0106200120003b010602402009450d00410021002017210303402003280200220420003b010420042001360200200341046a21032009200041016a2200470d000b0b200220022f01900122003b0130200220022903c001370360200220022901c6013701662002200b2d000022033a0032200b20033a0000200220003b019001200220022903603703c001200220022901663701c601201541ffff037122034107490d01200841216c201d6a220041ba7e6a200041997e6a220320012f0106200841796a22006b41216c109e081a2003201036000f2003200f36000b2003200e3600072003200d360003200341026a20132d00003a0000200320022f012c3b000020032002290318370013200341196a200229011e370000201e2008417a6a220341027422046a201e20004102746a220920012f0106221520006b410274109e081a200920113602002001201541016a22093b01062008410274221520176a416c6a201720046a2204200941ffff0371220820036b410274109e081a2004200c36020020082003490d02200120156a4188036a2103034020032802002204200041016a22003b010420042001360200200341046a210320002008490d000c030b0b2007200841216c6a220341296a200341086a2201200020086b41216c109e081a200341176a2010360000200341136a200f3600002003410f6a200e3600002003410b6a200d3600002003410a6a2002412c6a41026a2d00003a0000200120022f012c3b00002003411b6a2002290318370000200341216a200229011e370000200741f4026a2203200841016a220041027422016a2003200841027422046a220320072f0106220920086b410274109e081a200320113602002007200941016a22033b01062004200741a0036a22086a41086a200820016a2201200341ffff0371220420006b410274109e081a2001200c360200201541ffff037120044f0d0720072000417f6a22004102746a41a4036a2103034020032802002201200041016a22003b010420012007360200200341046a210320002004490d000c080b0b200741086a200841216c6a220041216a200020072f010620086b41216c109e081a2000201036000f2000200f36000b2000200e3600072000200d360003200041026a20132d00003a0000200020022f012c3b000020002002290318370013200041196a200229011e370000200741f4026a2204200841016a220941027422156a2004200841027422006a220420072f0106221720086b410274109e081a200420113602002007201741016a22043b01062000200741a0036a22176a41086a201720156a2215200441ffff0371220420096b410274109e081a2015200c360200200320044f0d00200720006a41a4036a2100034020002802002203200841016a22083b010420032007360200200041046a210020042008470d000b0b200641016a21002014200b2d00003a0000200220022f0190013b0110200220022903c001370300200220022901c6013701060240200728020022030d002018210d201b2110201a210f2019210e2001210c201c21110c050b20072f010421152018210d201b2110201a210f2019210e20032107201c21112001210c200021060c000b0b20012001280200417f6a2203360200200041086a280200200041106a2802004102746a41f4026a211220030d030240200128020c2200450d0020002000280200417f6a360200200128020c22002802000d000240200028020c450d002000410c6a10ae02200128020c21000b20002000280204417f6a360204200128020c22002802040d00200010350b20012001280204417f6a220036020420000d03200110350c030b2003200441216c6a220041296a200041086a220c200b20046b41216c109e081a200041286a20072d00003a0000200041206a2008290300370000200041186a2009290300370000200041106a200a290300370000200c2002290360370000200320044102746a220041f8026a200041f4026a221220032f010620046b410274109e081a20122001360200200320032f010641016a3b01060c020b41d684cc00413541c086cc00103f000b200241b9016a4100360000200241b1016a4200370000200241a9016a4200370000200241a1016a420037000020024199016a42003700002002420037009101200241c0016a410272410041ed02109f081a200241e0006a41086a22014200370300200241e0006a41106a22044200370300200241e0006a41186a22074200370300200241e0006a41206a2208420037030020024188016a22094200370300200241306a41256a220a20024190016a41256a290000370000200241306a41206a220b20024190016a41206a290000370300200241306a41186a220620024190016a41186a290000370300200241306a41106a221520024190016a41106a290000370300200241306a41086a221720024190016a41086a29000037030020024200370360200220022900900137033041d00310332203450d0120034100360200200341046a200241c0016a41ef02109d081a20034198036a200a29000037000020034193036a200b2903003700002003418b036a200629030037000020034183036a2015290300370000200341fb026a2017290300370000200320022903303700f302200320022903603702a003200341a8036a2001290300370200200341b0036a2004290300370200200341b8036a2007290300370200200341c0036a2008290300370200200341c8036a20092903003702002003200528020022013602a0032005200336020020052005280204220441016a360204200141003b010420012003360200200241e0006a41026a200241106a41026a2d00003a0000200220022f01103b0160200220022903003703c001200220022901063701c60120042000470d0220032f01062201410a4b0d032003200141216c6a2200410a6a200241e0006a41026a2d00003a0000200041086a20022f01603b0000200041176a2010360000200041136a200f3600002000410f6a200e3600002000410b6a200d3600002000411b6a20022903c001370000200041216a20022901c6013700002003200141016a22004102746a41a0036a200c360200200320014102746a41f4026a2011360200200320003b0106200c20003b0104200c20033602000b200241b0046a240020120f0b103c000b41ff83cc00413041c086cc00103f000b41af84cc00412741c086cc00103f000baf0b010c7f230041306b220224002002410036021020024204370308200241003602202002420437031802400240024002400240200128020041016a220341014d0d0020012003360200200241086a4100410110860120022802082204200228021022034102746a20013602002002200341016a22053602102001280200220341016a41014d0d002001200341016a360200200241186a4100410110860120022802182206200228022022034102746a20013602002002200341016a2207360220200128020041016a220841014d0d00200120083602000340200841016a220341014d0d0120012003360200200128020841016a220941004c0d0220012009360208200128020c2208450d0502402007450d002007410274210a200841106a210b20062109034002400240200928020022032008460d00200328020841016a220c41004c0d072003200c3602082008280208220c41016a220d41004c0d082008200d360208200341106a200b412010a0080d0120032d003020082d0030470d012008200c36020820032003280208417f6a3602080b20012802002103200128020821090c080b200941046a21092008200c36020820032003280208417f6a360208200a417c6a220a0d000b200128020c21080b200828020041016a220341014d0d012008200336020002402005200228020c470d00200241086a2005410110860120022802082104200228021021050b200420054102746a20083602002002200541016a2205360210200128020c220328020041016a220841014d0d012003200836020020012001280200417f6a2208360200024020080d000240200128020c2208450d0020082008280200417f6a360200200128020c22082802000d000240200828020c450d002008410c6a10ae02200128020c21080b20082008280204417f6a360204200128020c22082802040d00200810350b20012001280204417f6a220836020420080d00200110350b200328020041016a220841014d0d012003200836020002402007200228021c470d00200241186a2007410110860120022802182106200228022021070b200620074102746a200336020020012001280208417f6a36020820012001280200417f6a22083602002002200741016a2207360220024020080d000240200128020c2208450d0020082008280200417f6a360200200128020c22082802000d000240200828020c450d002008410c6a10ae02200128020c21080b20082008280204417f6a360204200128020c22082802040d00200810350b20012001280204417f6a220836020420080d00200110350b20032802002108200321010c000b0b00000b41ac96cc004118200241286a41808bc50041d496cc001046000b41ac96cc004118200241286a41e495ca0041d496cc001046000b41ac96cc004118200241286a41e495ca0041d496cc001046000b20012003417f6a220336020020012009417f6a360208024020030d000240200128020c2203450d0020032003280200417f6a360200200128020c22032802000d000240200328020c450d002003410c6a10ae02200128020c21030b20032003280204417f6a360204200128020c22032802040d00200310350b20012001280204417f6a220336020420030d00200110350b20002001360200200020022903083702042000410c6a200241106a28020036020002402007450d0020074102742108200621030340200328020022092009280200417f6a3602000240200328020022092802000d000240200928020c2201450d0020012001280200417f6a360200200928020c22012802000d000240200128020c450d002001410c6a10ae02200928020c21010b20012001280204417f6a360204200928020c22092802040d00200910350b200328020022092009280204417f6a360204200328020022092802040d00200910350b200341046a21032008417c6a22080d000b0b0240200228021c41ffffffff0371450d00200610350b200241306a24000b5c01017f200028020022012001280200417f6a3602000240200028020022012802000d000240200128020c450d002001410c6a10ae02200028020021010b20012001280204417f6a360204200028020022002802040d00200010350b0ba50201047f230041106b22022400410021030240024002400240024002400240200028020841016a220441004c0d00200028020c2205450d0620002004360208024020052001470d00410121030c060b200528020841016a220341004c0d01200520033602082001280208220441016a220341004c0d0220012003360208200541106a200141106a412010a0080d034101210320052d003020012d0030470d030c040b41ac96cc004118200241086a41808bc50041d496cc001046000b41ac96cc004118200241086a41808bc50041d496cc001046000b41ac96cc004118200241086a41808bc50041d496cc001046000b410021030b2001200436020820052005280208417f6a360208200028020821040b20002004417f6a3602080b200241106a240020030b80150c047f027e027f067e017f037e037f027e037f037e037f017e230041e0036b2204240020032802002105200441306a2001108e02200441b0016a2004280230220620042802382207108f0220042903b001210842002109200442003703b001200441f8016a280200210a20042d00fc01210b02400240200842015122030d00200441c0006a41306a4200370300200441c0006a41286a4200370300200441c0006a41206a4200370300200441c0006a41186a4200370300200441d0006a4200370300200441c8006a4200370300200442003703404200210c4200210d4200210e4200210f0c010b200441e8016a2903002110200441b0016a41306a2903002111200441b0016a41206a290300210c200441b0016a41186a2903002109200441f0016a290300210f20042903c001210e20042903b801210d200441c0006a41206a200441b0016a41286a290300370300200441c0006a41286a2011370300200441c0006a41306a2010370300200441d0006a20093703002004200c3703582004200d3703402004200e3703480b427f200e200c7c200d20097c220c200d542212ad7c220920122009200e542009200e511b22121b2113427f200c20121b21144200210c024002402002290300221542ffffe883b1de1656200241086a29030022094200522009501b0d00201420138450450d0041002103410021124200210e410121020c010b4200200e20097c200d20157c2210200d542202ad7c220d2002200d200e54200d200e511b22021b210e4200201020021b2111024020024101470d002011421088200e42308684210c200e421088210e2011420888a721122011a72103410121020c010b200441b0026a41186a22164200370300200441b0026a41106a22174200370300200441b0026a41086a22124200370300200442003703b00241b6fdc600ad4280808080800184220c100122182900002119200441d0036a41086a2202201841086a290000370300200420193703d0032018103520122002290300370300200420042903d0033703b00241e489c200ad4280808080d00184221910012218290000211a2002201841086a2900003703002004201a3703d00320181035201720042903d003221a370300200441b0036a41086a221b2012290300370300200441b0036a41106a221c201a370300200441b0036a41186a221d2002290300370300200420042903b0023703b003200441186a200441b0036a412010d701200441186a41106a290300211a2004290320211e20042802182118201642003703002017420037030020124200370300200442003703b002200c10012216290000210c2002201641086a2900003703002004200c3703d0032016103520122002290300370300200420042903d0033703b002201910012216290000210c2002201641086a2900003703002004200c3703d00320161035201720042903d003220c370300201b2012290300370300201c200c370300201d2002290300370300200420042903b0023703b0032004201a420020181b3703b8022004201e420020181b3703b002200441b0036aad4280808080800484221a200441b0026aad221e428080808080028410022004200e37034820042011370340200441f8006a41186a200441d0006a220241086a290300220c370300200441f8006a41206a2212200241106a290300370300200441a0016a2218200241186a290300370300200441a8016a2216200241206a2903003703002004200e37038001200420113703782004200229030022193703880102400240427f201120197c221920192011542202200e200c7c2002ad7c220c200e54200c200e511b22021b220e428080e983b1de16544100427f200c20021b220c501b0d00200441f8006a41106a290300210e2016290300210c2018290300211120122903002119200429038001211a2004290378211e4201211f20042903900121200c010b02400240200e200c8450450d004200211f0c010b4200211f200441b0026a41186a22184200370300200441b0026a41106a22164200370300200441b0026a41086a22124200370300200442003703b00241b6fdc600ad428080808080018422111001221b2900002119200441d0036a41086a2202201b41086a290000370300200420193703d003201b103520122002290300370300200420042903d0033703b00241e489c200ad4280808080d0018422191001221b29000021202002201b41086a290000370300200420203703d003201b1035201720042903d003370000201741086a221d2002290300370000200441b0036a41086a22212012290300370300200441b0036a41106a22222016290300370300200441b0036a41186a22232018290300370300200420042903b0023703b0032004200441b0036a412010d701200441106a2903002120200429030821242004280200211b201842003703002016420037030020124200370300200442003703b00220111001221c29000021112002201c41086a290000370300200420113703d003201c103520122002290300370300200420042903d0033703b00220191001221c29000021112002201c41086a290000370300200420113703d003201c1035201720042903d003370000201d2002290300370000202120122903003703002022201629030037030020232018290300370300200420042903b0023703b0032004420020204200201b1b2211200c7d20244200201b1b2219200e54ad7d22202019200e7d2224201956202020115620202011511b22021b3703b80220044200202420021b3703b002201a201e42808080808002841002200441e8026a200c370300200441e0026a200e370300201241013a0000200441b9026a2005290000370000200441c1026a200541086a290000370000200441c9026a200541106a290000370000200441d1026a200541186a290000370000200441033a00b00241b0b4cc004100200441b0026a10d4010b0b200441d8016a2019370300200441e0016a2011370300200441c0016a201a370300200441e8016a200c370300200441c8016a200e370300200420203703d0012004200f3703f0012004201e3703b801410021022004200b4100200842015122121b3a00fc012004200a410020121b3602f8012004201f4201512212ad3703b001201420138450ad423086210c4200210e024020120d002007ad4220862006ad841007410021120c010b200420073602b402200420063602b002200441b8016a200441b0026a10e70241012112410021020b02402004280234450d00200610350b024002402002450d00200041106a200e421086200c4230888437030020002012ad42ff01834208862003ad42ff018384200c421086843703084201210e0c010b200c423088200e42108684210e024002400240200341ff017122020d00201241ff0171450d0041032103200441b0026a21020c010b2002450d01201241ff01710d0141042103200441b0016a21020b200241086a20033a0000200241003a0000200241096a2001290000370000200241116a200141086a290000370000200241196a200141106a290000370000200241216a200141186a29000037000041b0b4cc004100200210d4010b2000200e370308200041286a2009370300200041206a2015370300200041186a200d370300200041106a20103703004200210e0b2000200e370300200441e0036a24000bd60302057f047e230041f0006b220224002002412036020c20022001360208200241106a2001ad4280808080800484100510c20102400240200228021022030d00200041003a00000c010b200241186a28020021042002280214210541002101200241003a006802400240034020042001460d01200241c8006a20016a200320016a2d00003a00002002200141016a22063a00682006210120064120470d000b200241206a41186a200241c8006a41186a2903002207370300200241206a41106a200241c8006a41106a2903002208370300200241206a41086a200241c8006a41086a290300220937030020022002290348220a370320200041196a2007370000200041116a2008370000200041096a20093700002000200a370001410121010c010b0240200141ff0171450d00200241003a00680b410021012002410036022820024201370320200241093602442002200241086a3602402002200241206a36026c200241dc006a41013602002002420137024c200241c888c2003602482002200241c0006a360258200241ec006a41e88ac500200241c8006a10431a200235022842208620023502208410062002280224450d00200228022010350b200020013a00002005450d00200310350b200241f0006a24000ba11005097f037e027f037e037f230041f0026b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100510c20102400240200328021022040d00200042023703000c010b200328021421052003200341186a28020022063602a401200320043602a00141002107200341003a00e8022004210220062101024002400240024002400240024002400340200721082001450d01200341c8026a20086a20022d00003a000020032001417f6a22013602a4012003200241016a22023602a0012003200841016a22073a00e80220074120470d000b200341a8016a41086a200341c8026a41086a290300370300200341a8016a41106a200341c8026a41106a290300370300200341a8016a41186a200341c8026a41186a290300370300200320032903c8023703a80141002107200341003a00e802200620086b417e6a2108034020012007460d02200341c8026a20076a200220076a22062d00003a00002003200641016a3602a0012003200741016a22063a00e802200320083602a4012008417f6a21082006210720064120470d000b200341c8016a41086a200341c8026a41086a290300370300200341c8016a41106a200341c8026a41106a290300370300200341c8016a41186a200341c8026a41186a290300370300200320032903c8023703c80120012006460d05200220066a22092d00002102200320083602a4012003200941016a22073602a001200241014b0d0520020e020302030b200841ff0171450d04200341003a00e8020c040b200741ff0171450d03200341003a00e8020c030b200941116a210741002102200341003a00e802200120066b416f6a21010240034020082002460d01200341c8026a20026a200920026a41016a2d00003a000020032001410f6a3602a4012003200741716a3602a0012003200241016a22063a00e8022001417f6a2101200741016a21072006210220064120470d000b200341a8026a41186a2202200341c8026a41186a290300370300200341a8026a41106a220a200341c8026a41106a290300370300200341a8026a41086a220b200341c8026a41086a290300370300200320032903c8023703a802200820066b4110490d03200920066a220841096a290000210c200841016a290000210d20034188026a41086a200b29030037030020034188026a41106a200a29030037030020034188026a41186a2002290300370300200320013602a401200320073602a001200320032903a802370388024201210e200121080c020b200241ff0171450d02200341003a00e8020c020b4200210e0b200341e8016a41186a20034188026a41186a290300370300200341e8016a41106a20034188026a41106a290300370300200341e8016a41086a20034188026a41086a29030037030020032003290388023703e8012008450d0020072d0000210120032008417f6a22023602a4012003200741016a3602a001200141014b0d00410021060240024020010e020100010b20024104490d012007280001210920032008417b6a3602a4012003200741056a3602a001410121060b200341c8026a200341a0016a10aa0220032802c8020d010b200341003602b002200342013703a8022003410936028c022003200341086a360288022003200341a8026a3602e801200341dc026a4101360200200342013702cc02200341c888c2003602c802200320034188026a3602d802200341e8016a41e88ac500200341c8026a10431a20033502b00242208620033502a802841006024020032802ac02450d0020032802a80210350b4202210e0c010b200341f0006a41086a2202200341c8026a41086a2201280200360200200341d0006a41086a2207200341a8016a41086a290300370300200341d0006a41106a2208200341a8016a41106a290300370300200341d0006a41186a220a200341a8016a41186a290300370300200341306a41086a220b200341c8016a41086a290300370300200341306a41106a220f200341c8016a41106a290300370300200341306a41186a2210200341c8016a41186a290300370300200320032903c802370370200320032903a801370350200320032903c80137033020034180016a41186a200341e8016a41186a290300221137030020034180016a41106a200341e8016a41106a290300221237030020034180016a41086a200341e8016a41086a290300221337030020012013370300200341c8026a41106a22142012370300200341c8026a41186a22152011370300200341206a41086a22162002280200360200200320032903e801221137038001200320113703c80220032003290370370320200341a8026a41186a2202200a290300370300200341a8026a41106a220a2008290300370300200341a8026a41086a22082007290300370300200320032903503703a80220034188026a41186a2207201029030037030020034188026a41106a2210200f29030037030020034188026a41086a220f200b2903003703002003200329033037038802200041306a200c370300200041286a200d3703002000413c6a2009360200200041386a2006360200200041206a2015290300370300200041186a2014290300370300200041106a2001290300370300200020032903c802370308200041c0006a2003290320370300200041c8006a2016280200360200200020032903a80237024c200041d4006a2008290300370200200041dc006a200a290300370200200041e4006a200229030037020020004184016a2007290300370200200041fc006a2010290300370200200041f4006a200f290300370200200020032903880237026c0b2000200e3703002005450d00200410350b200341f0026a24000be00903067f067e057f230041a0016b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100510c20102400240200328021022040d00200041023a00000c010b2003280214210502400240200341186a2802002206450d0020042d0000220141014b0d002006417f6a210202400240024020010e020001000b20024104490d022004280001210741002101200341003a0098012006417b6a21080240034020082001460d01200341f8006a20016a200420016a41056a2d00003a00002003200141016a22023a0098012002210120024120470d000b200341d8006a41186a200341f8006a41186a290300370300200341d8006a41106a200341f8006a41106a290300370300200341d8006a41086a200341f8006a41086a290300370300200320032903783703582006417b6a2002460d03200420026a220141056a2d0000220841034f0d03200620026b2202417a6a4104490d03200241766a4110490d03200241666a4110490d03200241566a4110490d03200141066a2800002106200141126a29000021092001410a6a290000210a200341286a41086a200341d8006a41086a290300370300200341286a41106a200341d8006a41106a290300370300200341286a41186a200341d8006a41186a29030037030020032003290358370328200320032800503602202003200341d3006a280000360023200141326a290000210b2001412a6a290000210c200141226a290000210d2001411a6a290000210e200320032f014e3b014c410021010c020b200141ff0171450d02200341003a0098010c020b2002450d0120042d0001220141014b0d012006417e6a2108410021020240024020010e020100010b410121020b200841034d0d01200341286a41086a200341f8006a41086a290300370300200341286a41106a200341f8006a41106a290300370300200341286a41186a200341f8006a41186a29030037030020032003290378370328200320032800583602202003200341d8006a41036a2800003600232004280002210f410121010b200341f8006a41086a2210200341286a41086a290300370300200341f8006a41106a2211200341286a41106a290300370300200341f8006a41186a2212200341286a41186a290300370300200320032f014c22133b015020032003290328370378200320032802203602582003200328002336005b200041306a200b370000200041286a200c370000200041206a200d370000200041186a200e370000200041106a2009370000200041086a200a370000200020023a00012000413c6a2006360000200041386a2007360000200041046a200f360000200041026a20133b0000200041e0006a20083a0000200041c0006a2003290378370000200041c8006a2010290300370000200041d0006a2011290300370000200041d8006a2012290300370000200041e1006a2003280258360000200041e4006a200328005b3600000c010b20034100360260200342013703582003410936022c2003200341086a3602282003200341d8006a3602502003418c016a41013602002003420137027c200341c888c2003602782003200341286a36028801200341d0006a41e88ac500200341f8006a10431a200335026042208620033502588410060240200328025c450d00200328025810350b410221010b200020013a00002005450d00200410350b200341a0016a24000b880504057f017e027f017e230041e0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100510c2010240024002400240200328021022040d00200041003602000c010b200328021421052003200341186a280200360224200320043602202003200341206a10c4010240024020032802000d00200328020422062003280224220741186e2201200120064b1bad42187e2208422088a70d032008a72202417f4c0d030240024020020d00410821090c010b200210332209450d050b4100210120034100360250200320093602482003200241186e36024c0240024002402006450d00034020074104490d0320032003280220220241046a3602202007417c6a4110490d022002280000210a2003200241146a3602202002410c6a29000021082002290004210b02402001200328024c470d00200341c8006a20014101109c0120032802482109200328025021010b2007416c6a21072009200141186c6a2202200a3602002002200b370308200241106a20083703002003200141016a22013602502006417f6a22060d000b200320073602240b2009450d022000200329024c370204200020093602000c030b2007417c6a21070b20032007360224200328024c2201450d00200141186c450d00200910350b20034100360230200342013703282003410936023c2003200341086a3602382003200341286a360244200341dc006a41013602002003420137024c200341c888c2003602482003200341386a360258200341c4006a41e88ac500200341c8006a10431a200335023042208620033502288410060240200328022c450d00200328022810350b200041003602000b2005450d00200410350b200341e0006a24000f0b1044000b1045000bbe0201017f230041e0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100510c20102400240200328021022010d00200041003602000c010b200328021421022003200341106a41086a28020036022420032001360220200341c8006a200341206a10c3010240024020032802480d0020034100360230200342013703282003410936023c2003200341086a3602382003200341286a360244200341dc006a41013602002003420137024c200341c888c2003602482003200341386a360258200341c4006a41e88ac500200341c8006a10431a200335023042208620033502288410060240200328022c450d00200328022810350b200041003602000c010b20002003290348370200200041086a200341c8006a41086a2802003602000b2002450d00200110350b200341e0006a24000b901304057f017e107f027e230041e0026b220224002002412036020c20022001360208200241106a2001ad4280808080800484100510c2010240024002400240200228021022030d00200041003602000c010b200228021421042002200241186a280200360224200220033602202002200241206a10c4010240024020022802000d00200228020422052002280224220641c4006e2201200120054b1bad42c4007e2207422088a70d032007a72201417f4c0d030240024020010d00410421080c010b200110332208450d050b20024100360230200220083602282002200141c4006e36022c0240024002402005450d00200241b8026a41077221094100210a4100210b03402006450d0220022006417f6a220c36022420022002280220220d41016a360220200d2d0000220141014b0d0202400240024020010e020001000b200c4104490d04200241f4016a41026a200241f8016a41026a2d00003a0000200241d8016a41086a20024198026a41086a290200370300200241d8016a41106a20024198026a41106a290200370300200241d8016a41186a20024198026a41186a2d00003a0000200241b8016a41086a200241b8026a41086a290100370300200241b8016a41106a200241b8026a41106a290100370300200241b8016a41186a200241b8026a41186a290100370300200220022f00f8013b01f40120022002290298023703d801200220022901b8023703b80120022006417b6a220e3602242002200d41056a360220200d280001210f200220022f0194023b01b601410021100c010b41002111200241003a00d8022006417e6a2110024002400240024002400340200c20112201460d01200241b8026a20016a200d20016a221141016a2d00003a00002002201141026a3602202002200141016a22113a00d802200220103602242010417f6a211020114120470d000b20024194026a41026a221220022d00ba023a0000200241f8016a41086a2213200941086a290000370300200241f8016a41106a2214200941106a290000370300200241f8016a41186a2215200941186a2d00003a0000200220022f01b8023b019402200220092900003703f8014100210e200c2011460d0220022800bb022116200220103602242002200d20116a220c41026a360220200c41016a2d0000221141014d0d012010210e410221100c050b0240200141ff0171450d00200241003a00d8020b4100210e410221100c040b024020110e020200020b41002111200241003a00d802200620016b417c6a21010240034020102011460d01200241b8026a20116a200c20116a220d41026a2d00003a00002002200d41036a3602202002201141016a220d3a00d802200220013602242001417f6a2101200d2111200d4120470d000b20024198026a41186a200241b8026a41186a29030037030020024198026a41106a200241b8026a41106a29030037030020024198026a41086a200241b8026a41086a290300370300200220022903b802370398022010200d6b210e410121170c030b0240201141ff0171450d00200241003a00d8020b4100210e0b410221100c020b410021172010210e0b200241b8016a41186a20024198026a41186a290300370300200241b8016a41106a20024198026a41106a290300370300200241b8016a41086a20024198026a41086a290300370300200241f4016a41026a20122d00003a0000200241d8016a41086a2013290300370300200241d8016a41106a2014290300370300200241d8016a41186a20152d00003a000020022002290398023703b801200220022f0194023b01f401200220022903f8013703d801410121102016210f0b200241b2016a41026a2201200241f4016a41026a2d00003a000020024198016a41086a2211200241d8016a41086a29030037030020024198016a41106a220d200241d8016a41106a29030037030020024198016a41186a220c200241d8016a41186a2d00003a0000200241f8006a41086a2206200241b8016a41086a290300370300200241f8006a41106a2212200241b8016a41106a290300370300200241f8006a41186a2213200241b8016a41186a290300370300200220022f01f4013b01b201200220022903d80137039801200220022903b801370378200220022f01b6013b017620104102460d03200b41016a210b200241f2006a41026a221420012d00003a0000200241d8006a41086a22152011290300370300200241d8006a41106a2211200d290300370300200241d8006a41186a220d200c2d00003a0000200241386a41086a220c2006290300370300200241386a41106a22062012290300370300200241386a41186a22122013290300370300200220022f01b2013b0172200220022903980137035820022002290378370338200220022f01763b01360240200a200228022c470d00200241286a200a4101109f01200228022821082002280230210a0b2008200a41c4006c6a220120103a00002001200f360004200141036a20142d00003a0000200120022f01723b0001200d2d00002110201129030021072015290300211820022903582119200120173a002120012019370008200141106a2018370000200141186a2007370000200141206a20103a000020012002290338370022200c29030021072006290300211820122903002119200120022f01363b00422001413a6a2019370000200141326a20183700002001412a6a20073700002002200a41016a220a360230200e2106200b2005470d000b0b2008450d022000200229022c370204200020083602000c030b200241b2016a41026a200241f4016a41026a2d00003a000020024198016a41086a200241d8016a41086a29030037030020024198016a41106a200241d8016a41106a29030037030020024198016a41186a200241d8016a41186a2d00003a0000200241f8006a41086a200241b8016a41086a290300370300200241f8006a41106a200241b8016a41106a290300370300200241f8006a41186a200241b8016a41186a290300370300200220022f01f4013b01b201200220022903d80137039801200220022903b801370378200220022f01b6013b01760b200228022c2201450d00200141c4006c450d00200810350b200241003602a0022002420137039802200241093602bc012002200241086a3602b801200220024198026a360278200241cc026a4101360200200242013702bc02200241c888c2003602b8022002200241b8016a3602c802200241f8006a41e88ac500200241b8026a10431a20023502a0024220862002350298028410060240200228029c02450d0020022802980210350b200041003602000b2004450d00200310350b200241e0026a24000f0b1044000b1045000bd20402067f047e230041f0006b220224002002412036020420022001360200200241086a2001ad4280808080800484100510c20102400240200228020822030d00200041023a00000c010b200228020c210402400240200241106a2802002205450d0020032d0000220641014b0d004100210102400240024020060e020100010b41002101200241003a0068200341016a21072005417f6a2106034020062001460d02200241c8006a20016a200720016a2d00003a00002002200141016a22053a00682005210120054120470d000b200241186a41186a200241c8006a41186a290300370300200241186a41106a200241c8006a41106a290300370300200241186a41086a200241c8006a41086a29030037030020022002290348370318410121010b200241c8006a41186a200241186a41186a2903002208370300200241c8006a41106a200241186a41106a2903002209370300200241c8006a41086a200241186a41086a290300220a37030020022002290318220b370348200041196a2008370000200041116a2009370000200041096a200a3700002000200b3700010c020b200141ff0171450d00200241003a00680b20024100360220200242013703182002410936023c200220023602382002200241186a360244200241dc006a41013602002002420137024c200241c888c2003602482002200241386a360258200241c4006a41e88ac500200241c8006a10431a200235022042208620023502188410060240200228021c450d00200228021810350b410221010b200020013a00002004450d00200310350b200241f0006a24000ba90d03047f017e147f230041e00c6b220324002003200236021c20032001360218200341206a2002ad4220862001ad84100510c2010240024002400240200328022022040d00200041003602000c010b200328022421052003200341286a28020036023420032004360230200341106a200341306a10c40102400240024020032802100d00200328021422062003280234220141d0026e2202200220064b1bad42d0027e2207422088a70d052007a72208417f4c0d050240024020080d00410821090c010b200810332209450d050b4100210220034100360240200320093602382003200841d0026e36023c02402006450d002006417f6a21080340024002402001450d002003280230220a2d0000210b20032001417f6a220c3602342003200a41016a360230200b41014b0d00410221060240200b0e020200020b024002400240200c0d00410221060c010b200a2d0001210b20032001417e6a220c360234410221062003200a41026a36023002400240200b41014b0d0041002101024002400240200b0e020100010b200341086a200341306a10c40120032802080d022003280234200328020c220b490d02200b417f4c0d0f02400240200b0d004100210a410121010c010b200b10392201450d0f2003280234200b490d0220012003280230200b109d081a2003280234220a200b490d042003200a200b6b36023420032003280230200b6a360230200b210a0b2001450d02200bad422086200aad8421072003280234210c0b2007a7210b02400240024002400240200c450d002003280230220d2d0000210a2003200c417f6a3602342003200d41016a360230200341b00a6a200341306a10b90220032802b00a411b460d0320034180086a200341b00a6a41b002109d081a2003280234220c450d042003280230220e2d0000210d2003200c417f6a220f3602342003200e41016a360230200d41014b0d0441002106200d0e020201020b2001450d07200b450d070c040b200f4104490d02200e280001210d2003200e41056a3602302003200c417b6a220636023420064104490d02200e28000521102003200c41776a3602342003200e41096a36023041012106200d21110b2007422088a72112200341b00a6a20034180086a41b002109d081a200320032800f9073602f0072003200341f9076a41036a2800003600f3070c060b2001450d04200b450d040c010b20034180086a10ba022001450d01200b450d010b200110350b2013210a2014210b20152101410221060c020b200b200a41a4f0cb001059000b2013210a2014210b201521010b200341c0056a200341b00a6a41b002109d081a200320032800f3073600bb05200320032802f0073602b805024020064102460d00200341b00a6a200341c0056a41b002109d081a200320032800bb0536008308200320032802b8053602800820012116200b211720122118200a21192010211a2011211b200a2113200b2114200121150c020b200a2113200b2114200121150b410321060b20034188036a200341b00a6a41b002109d081a200320032800830836008303200320032802800836028003024020064103460d00200341d0006a20034188036a41b002109d081a200320032800830336004b200320032802800336024802402002200328023c470d00200341386a2002410110a70120032802382109200328024021020b2009200241d0026c6a200341d0006a41b002109d08220141c8026a20193a0000200141c4026a201a3602002001201b3602c002200120063602bc02200120183602b802200120173602b402200120163602b002200141c9026a2003280248360000200141cc026a200328004b3600002003200241016a22023602402008450d022008417f6a2108200328023421010c010b0b02402002450d00200241d0026c21022009210103400240200141bc026a2802004102460d000240200141b0026a2802002206450d00200141b4026a280200450d00200610350b200110bb020b200141d0026a2101200241b07d6a22020d000b0b200328023c2201450d01200141d0026c450d01200910350c010b20090d010b20034100360288082003420137038008200341093602c4052003200341186a3602c005200320034180086a36028803200341c40a6a4101360200200342013702b40a200341c888c2003602b00a2003200341c0056a3602c00a20034188036a41e88ac500200341b00a6a10431a2003350288084220862003350280088410060240200328028408450d0020032802800810350b200041003602000c010b2000200329023c370204200020093602000b2005450d00200410350b200341e00c6a24000f0b1045000b1044000bd2870307087f027e0b7f087e057f027e1b7f23004190116b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a22063602042001200441016a3602002005411b4b0d25200141046a210720050e1c0102030405060708090a0b0c0d0e0f10111213141516171819222324010b2000411b3602000c600b2006450d5e20042d0001210520012003417e6a22083602042001200441026a360200200541094b0d5e410a2109024002400240024002400240024002400240024020050e0a00010203040506070809000b20084104490d672004280002210620012003417a6a3602042001200441066a3602002006418194ebdc034f0d67410121090c080b2002200110c40120022802000d66200728020020022802042204490d662004417f4c0d2c0240024020040d004200210a410121060c010b200410392206450d2120072802002004490d66200620012802002004109d081a200128020422032004490d2e2001200320046b3602042001200128020020046a3602002004ad210a0b2006450d66200a2004ad42208684210a410221090c070b20084108490d652004290002210a2001200341766a36020420012004410a6a360200410321090c060b200241086a200110c40120022802080d642007280200200228020c2204490d642004417f4c0d2a0240024020040d004200210a410121060c010b200410392206450d1f20072802002004490d64200620012802002004109d081a200128020422032004490d2d2001200320046b3602042001200128020020046a3602002004ad210a0b2006450d64200a2004ad42208684210a410421090c050b200241106a200110c40120022802100d63200728020020022802142204490d632004417f4c0d290240024020040d004200210a410121060c010b200410392206450d1e20072802002004490d63200620012802002004109d081a200128020422032004490d2d2001200320046b3602042001200128020020046a3602002004ad210a0b2006450d63200a2004ad42208684210a410521090c040b2008450d6220042d0002210520012003417d6a22073602042001200441036a360200200541014b0d624106210941002106024020050e020400040b20074104490d622004350003210a2001200341796a22053602042001200441076a36020020054104490d622004350007210b2001200341756a36020420012004410b6a360200200b422086200a84210a410121060c030b200241286a200110c40120022802280d61200228022c2209200728020041186e2204200420094b1bad42187e220a422088a70d27200aa72204417f4c0d270240024020040d00410421060c010b200410332206450d1c0b41002105200241003602b80c200220063602b00c2002200441186e3602b40c024002400240024002402009450d000340200241206a200110c40120022802200d05200728020020022802242204490d052004417f4c0d2d0240024020040d004100210c410121080c010b200410392208450d2220072802002004490d05200820012802002004109d081a200128020422032004490d322001200320046b3602042001200128020020046a3602002004210c0b200241186a200110c40120022802180d032007280200200228021c2203490d032003417f4c0d2d0240024020030d004100210d4101210e0c010b20031039220e450d2220072802002003490d03200e20012802002003109d081a2001280204220d2003490d332001200d20036b3602042001200128020020036a3602002003210d0b2004ad422086200cad84210a2003ad422086200dad84210b0240200520022802b40c470d00200241b00c6a2005410110970120022802b00c210620022802b80c21050b2006200541186c6a2204200e36020c2004200a37020420042008360200200441106a200b3702002002200541016a22053602b80c2009417f6a22090d000b0b2006450d6520022902b40c210a410721090c060b200e10350b200c450d010b200810350b02402005450d00200541186c21042006210103400240200141046a280200450d00200128020010350b0240200141106a280200450d002001410c6a28020010350b200141186a2101200441686a22040d000b0b20022802b40c2201450d61200141186c450d610c600b200241386a200110c40120022802380d60200228023c22092007280200410c6e2204200420094b1bad420c7e220a422088a70d26200aa72204417f4c0d260240024020040d00410421060c010b200410332206450d1b0b41002103200241003602b80c200220063602b00c20022004410c6e3602b40c0240024002402009450d000340200241306a200110c40120022802300d03200728020020022802342204490d032004417f4c0d2a0240024020040d0041002108410121050c010b200410392205450d1f20072802002004490d03200520012802002004109d081a200128020422082004490d312001200820046b3602042001200128020020046a360200200421080b2004ad4220862008ad84210a0240200320022802b40c470d00200241b00c6a2003410110870120022802b00c210620022802b80c21030b20062003410c6c6a2204200a370204200420053602002002200341016a22033602b80c2009417f6a22090d000b0b2006450d6220022902b40c210a410821090c030b200510350b02402003450d002003410c6c21042006210103400240200141046a280200450d00200128020010350b2001410c6a2101200441746a22040d000b0b20022802b40c2201450d602001410c6c0d5f0c600b200241c0006a200110c40120022802400d5f200728020020022802442204490d5f2004417f4c0d250240024020040d004200210a410121060c010b200410392206450d1a20072802002004490d5f200620012802002004109d081a200128020422032004490d2d2001200320046b3602042001200128020020046a3602002004ad210a0b2006450d5f200a2004ad42208684210a410921090b20004100360200200041106a200a3702002000410c6a2006360200200041086a2009360200200041186a200241e00e6a419802109d081a0c5f0b2006450d5a20042d0001210520012003417e6a22063602042001200441026a360200200541044b0d5a02400240024002400240024002400240024020050e050001020304000b200241e00e6a200110c80520022802e00e2204450d622004411876210f20022902e40e220aa722034118762110200a422088a7210d41012111410021120c050b20064102490d6120042f0002210520012003417c6a3602042001200441046a360200200241e00e6a200110b90220022802e00e2101200241b00c6a200241e00e6a41047241ac02109d081a2001411b460d61200241e00e6a200241b00c6a41ac02109d081a41b002103322040d030c620b20064102490d6020042f0002210520012003417c6a3602042001200441046a360200200241e00e6a200110c30120022802e00e2204450d6020022802e40e2103024020072802002206450d00200241e80e6a280200210d200128020022092d0000210720012006417f6a22083602042001200941016a360200200741014b0d004200210a4100210e0240024020070e020100010b20084104490d012009350001210a20012006417b6a22073602042001200941056a36020020074104490d01200928000521132001200641776a3602042001200941096a360200200a422086210a4101210e0b200241e00e6a200110b90220022802e00e2106200241b00c6a200241e00e6a41047241ac02109d081a2006411b460d06200241e00e6a200241b00c6a41ac02109d081a41b00210332201450d62200a200ead84210a20012006360200200141046a200241e00e6a41ac02109d081a200341187621102004411876210f20054180fe03714108762112410321110c040b200341ffffff3f71450d600c5f0b20064102490d5f20042f0002210820012003417c6a3602042001200441046a360200200241e00e6a200110c30120022802e00e2206450d5f20022802e40e2109024020072802002204450d00200241e80e6a2802002107200128020022052d0000210320012004417f6a220d3602042001200541016a360200200341014b0d004100210e0240024020030e020100010b200d4104490d012005280001210c20012004417b6a22033602042001200541056a36020020034104490d01200528000521142001200441776a220d3602042001200541096a3602004101210e0b41002103200241003a00800f200d417f6a2104024003402004417f460d01200241e00e6a20036a200128020022052d00003a0000200120043602042001200541016a3602002002200341016a22053a00800f2004417f6a21042005210320054120470d000b200220022800e30e3600c30b200220022802e00e22153602c00b20022900e70e220aa72203411876211020022800c30b2204411876210f20022f00c10b2205410876211220022900f70e220b422088a72101200a422088a7210d200241ef0e6a290000210a200241ff0e6a2d00002116200ba72113410421110c050b0240200341ff0171450d00200241003a00800f0b200941ffffff3f71450d60200610350c600b200941ffffff3f71450d5f200610350c5f0b20064102490d5e20042f0002210820012003417c6a3602042001200441046a360200200241e00e6a200110c30120022802e00e2206450d5e20022802e40e21090240200728020022034104490d00200241e80e6a28020021072001280200220d280000210e20012003417c6a22043602042001200d41046a36020020044104490d00200d280004210c2001200341786a22143602042001200d41086a36020041002104200241003a00800f200341776a21030240034020142004460d01200241e00e6a20046a200d20046a220541086a2d00003a0000200120033602042001200541096a3602002002200441016a22053a00800f2003417f6a21032005210420054120470d000b200220022800e30e3600c30b200220022802e00e22153602c00b20022801c20b2212410876210420022900f70e2217422088a7210120022900e70e220b422088a7210d200b421888a72110200241ef0e6a290000210a200241ff0e6a2d0000211620022d00c10b210520022d00c60b210f2017a72113200ba72103410521110c040b0240200441ff0171450d00200241003a00800f0b200941ffffff3f71450d5f200610350c5f0b200941ffffff3f71450d5e200610350c5e0b20042001360200200441046a200241e00e6a41ac02109d081a2004411876210f20054180fe037141087621122002280288092113200228028408210c200228028808211441022111410021100b0b200020153a0005200020113a0004200041013602002000413c6a2014360200200041386a200c360200200041346a200e360200200041306a20073602002000412c6a2009360200200041286a2006360200200041266a20083b0100200041246a20163a0000200041206a20013602002000411c6a2013360200200041146a200a370200200041106a200d3602002000410c6a2010411874200341ffffff077172360200200041086a200f411874200441ffffff077172360200200041066a2012410874200541ff0171723b0100200041c0006a20024190066a41f001109d081a0c5f0b200341ffffff3f710d590c5a0b02402006450d0020012003417e6a3602042001200441026a3602000b2000411b3602000c5d0b02402006450d0020042d0001210520012003417e6a3602042001200441026a36020020050d00200241c8006a20011091062002290348a70d002002290350210a20004103360200200041086a200a370300200041106a200241e00e6a41a002109d081a0c5d0b2000411b3602000c5c0b02402006450d0020042d0001210520012003417e6a3602042001200441026a36020020050d00200241b00c6a200110cf0320022802b00c2201450d00200041086a20022902b40c3702002000200136020420004104360200200041106a200241e00e6a41a002109d081a0c5c0b2000411b3602000c5b0b02402006450d0020042d0001210520012003417e6a22063602042001200441026a360200200541034b0d00024002400240024020050e0400010203000b20064104490d032004280002210920012003417a6a3602042001200441066a3602004200210a410121060c570b41002105200241003a00d00c2003417e6a2109417d21060240034020092005460d01200241b00c6a20056a200420056a220741026a2d00003a00002001200320066a3602042001200741036a3602002002200541016a22073a00d00c2006417f6a21062007210520074120470d000b200220022800b30c3600c30b200220022802b00c22053602c00b200320076b2203417e6a4104490d03200241b00c6a410f6a290000210b200241cf0c6a310000211820022900b70c211720022900c70c210a20022f00c10b210820022800c30b210941022106200420076a220441026a280000210e20012003417a6a3602042001200441066a36020020022017370380082002200b370388082002200a37039008200a423888201842ff018342088684a721042017421888a721012017420888a7210320024180086a410f6a290000210b200229008708210a2017a721070c580b200541ff0171450d02200241003a00d00c0c020b20064104490d012004280002210920012003417a6a3602042001200441066a3602004200210a410321060c550b41002105200241003a00d00c2003417e6a2109417d21060240034020092005460d01200241b00c6a20056a200420056a220741026a2d00003a00002001200320066a3602042001200741036a3602002002200541016a22073a00d00c2006417f6a21062007210520074120470d000b200241e80b6a41106a200241b00c6a410f6a290000220a4238883c0000200241f40b6a200a4218883e0200200220022800b30c3600c30b200220022802b00c22053602c00b200220022d00c60b3a00e80b200220022900b70c220ba722063b00e90b200220064110763a00eb0b2002200b421888200a422886843702ec0b41042106200320076b2203417e6a4104490d01200241cf0c6a310000210b20022900c70c210a20022d00c10b210c20022801c20b2108200420076a220441026a280000210e20012003417a6a3602042001200441066a36020020024180096a41086a200241e80b6a410172220141086a2900003703002002200129000022173703800920022d00e80b41187420084108767221092002200a37039009200a423888200b42ff018342088684a72104200c200841087472210820024180096a410f6a290000210b200228008309210120022f0081092103200229008709210a2017a721070c560b200541ff0171450d00200241003a00d00c0b2000411b3602000c5a0b02402006450d0020042d0001210520012003417e6a3602042001200441026a360200200541034b0d00024002400240024020050e0400010203000b200241b00c6a200110920620022d00b00c4102460d03200241c40c6a290200210a200241bc0c6a290200210b200241cc0c6a2902002117200241b80c6a280200210420022802b40c210320022802b00c2105200241d8006a200110f60120022802580d03200241e8006a290300211841012101200229036021190c550b200241b00c6a200110920620022d00b00c4102460d02200241c40c6a290200210a200241bc0c6a290200210b200241cc0c6a2902002117200241b80c6a280200210420022802b40c210320022802b00c210520024188016a200110f601200229038801a70d0220024188016a41106a29030021182002290390012119200241f0006a200110f6012002290370a70d02200241f0006a41106a290300211a2002290378211b410221010c540b200241b00c6a200110920620022d00b00c4102460d01200241c40c6a290200210a200241bc0c6a290200210b200241cc0c6a2902002117200241b00c6a41086a2206280200210420022802b40c210320022802b00c2105200241b00c6a200110920620022d00b00c4102460d0120024190066a41206a2207200241b00c6a41206a28020036020020024190066a41186a2209200241b00c6a41186a29030037030020024190066a41106a2208200241b00c6a41106a29030037030020024190066a41086a2006290300370300200220022903b00c37039006200241a0016a200110f60120022903a001a70d01200241a0016a41106a290300211c20022903a801211d2009290300211a2008290300211b20024198066a29030021182007350200211e2002290390062119410321010c530b200241b00c6a200110920620022d00b00c4102460d00200241c40c6a290200210a200241bc0c6a290200210b200241cc0c6a2902002117200241b80c6a280200210420022802b40c210320022802b00c2105200241b8016a200110f60120022802b8010d00200241c8016a29030021184104210120022903c00121190c520b2000411b3602000c590b2006450d4d20042d0001210520012003417e6a221f3602042001200441026a360200200541174b0d4d4104210d02400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020050e1800010267030405060708090a0b0c0d0e0f10111213151617000b200241e00e6a200110920620022d00e00e4102460d64200241fc0e6a290200210b200241f40e6a290200210a200241ec0e6a290200211920022902e40e211e20022802e00e2109200241d0016a200110f60120022903d001a70d6420072802002204450d64200241e0016a290300211820022903d8012117200128020022032d0000210e20012004417f6a3602044101210d2001200341016a360200200e41024b0d64200241a80b6a41106a200241b00c6a41106a290200370300200241a80b6a41086a200241b00c6a41086a290200370300200241900b6a41086a20024180096a41086a290300370300200241900b6a41106a20024180096a41106a290300370300200241f80a6a41086a20024180086a41086a290200370300200241f80a6a41106a20024180086a41106a290200370300200220022902b00c3703a80b20022002290380093703900b20022002290280083703f80a200241e00a6a41106a200241980c6a41106a290300370300200241e00a6a41086a200241980c6a41086a290300370300200220022903980c3703e00a201e422088a72106200b422088a7210f200b421088a72120200b420888a721212019422088a72114201ea721082019a7210c0c660b200241e8016a200110f60120022903e801a70d63200241e8016a41106a290300210a20022903f001210b200241a80b6a41106a200241e00e6a41106a290200370300200241a80b6a41086a200241e00e6a41086a290200370300200241900b6a41086a200241b00c6a41086a290300370300200241900b6a41106a200241b00c6a41106a290300370300200241f80a6a41086a20024180096a41086a290200370300200241f80a6a41106a20024180096a41106a290200370300200220022902e00e3703a80b200220022903b00c3703900b20022002290280093703f80a200241e00a6a41106a20024180086a41106a290300370300200241e00a6a41086a20024180086a41086a29030037030020022002290380083703e00a200b422088a72106200a422088a72114200ba72108200aa7210c4102210d0c650b20024180026a200110f601200229038002a70d6220024180026a41106a290300210a200229038802210b200241a80b6a41106a200241e00e6a41106a290200370300200241a80b6a41086a200241e00e6a41086a290200370300200241900b6a41086a200241b00c6a41086a290300370300200241900b6a41106a200241b00c6a41106a290300370300200241f80a6a41086a20024180096a41086a290200370300200241f80a6a41106a20024180096a41106a290200370300200220022902e00e3703a80b200220022903b00c3703900b20022002290280093703f80a200241e00a6a41106a20024180086a41106a290300370300200241e00a6a41086a20024180086a41086a29030037030020022002290380083703e00a200b422088a72106200a422088a72114200ba72108200aa7210c4103210d0c640b20024198026a200110c4012002280298020d61200228029c022109200241a80b6a41106a200241e00e6a41106a290200370300200241a80b6a41086a200241e00e6a41086a290200370300200241900b6a41086a200241b00c6a41086a290300370300200241900b6a41106a200241b00c6a41106a290300370300200241f80a6a41086a20024180096a41086a290200370300200241f80a6a41106a20024180096a41106a290200370300200220022902e00e3703a80b200220022903b00c3703900b20022002290280093703f80a200241e00a6a41106a20024180086a41106a290300370300200241e00a6a41086a20024180086a41086a29030037030020022002290380083703e00a4105210d0c620b200241a0026a200110c40120022802a0020d6020022802a4022203200728020041246e2204200420034b1bad42247e220a422088a70d30200aa72204417f4c0d300240024020040d00410421090c010b200410332209450d250b41002106200241003602880c200220093602800c2002200441246e22083602840c024002402003450d0041002106200241e00e6a41206a2114200241e00e6a41106a21130340200241e00e6a200110920620022802840c210420022d00e00e22054102460d022014310000210a2013290300210b20022903f80e211720022903e80e211820022f01820f210720022d00810f210820022802e40e210e20022f01e20e210c20022d00e10e210d024020062004470d00200241800c6a20064101108d0120022802800c210920022802880c21060b2009200641246c6a220420073b0022200420083a0021200420173700182004200e3600042004200c3b00022004200d3a0001200420053a0000200441206a200a3c000020042018370008200441106a200b3700002002200641016a22063602880c2003417f6a22030d000b20022802840c21080b2009450d61200241a80b6a41106a200241b00c6a41106a290200370300200241a80b6a41086a200241b00c6a41086a290200370300200241900b6a41086a20024180096a41086a290300370300200241900b6a41106a20024180096a41106a290300370300200241f80a6a41086a20024180086a41086a290200370300200241f80a6a41106a20024180086a41106a290200370300200220022902b00c3703a80b20022002290380093703900b20022002290280083703f80a200241e00a6a41106a200241980c6a41106a290300370300200241e00a6a41086a200241980c6a41086a290300370300200220022903980c3703e00a4106210d0c630b2004450d60200441246c0d5d0c600b4107210d0c610b201f450d5e20042d0002210e20012003417d6a3602042001200441036a360200200e41024b0d5e200241a80b6a41106a200241e00e6a41106a2901003703004108210d200241a80b6a41086a200241e00e6a41086a290100370300200241900b6a41086a200241b00c6a41086a290100370300200241900b6a41106a200241b00c6a41106a290100370300200241f80a6a41086a20024180096a41086a290100370300200241f80a6a41106a20024180096a41106a290100370300200220022901e00e3703a80b200220022901b00c3703900b20022002290180093703f80a200241e00a6a41106a20024180086a41106a290100370300200241e00a6a41086a20024180086a41086a29010037030020022002290180083703e00a410021144100210c410021060c600b200241e00e6a200110920620022d00e00e4102460d5d200241d00b6a41086a2201200241fc0e6a280200360200200241a80b6a41086a200241b00c6a41086a290200370300200241a80b6a41106a200241b00c6a41106a2902003703002002200241f40e6a290200220a3703d00b200220022902b00c3703a80b200241800f6a280200210f200241ec0e6a290200211720022802e00e210920022902e40e21182001310000210b20022f01da0b212020022d00d90b2121200241900b6a41106a20024180096a41106a290300370300200241900b6a41086a20024180096a41086a29030037030020022002290380093703900b200241f80a6a41106a20024180086a41106a290200370300200241f80a6a41086a20024180086a41086a29020037030020022002290280083703f80a200241e00a6a41106a200241980c6a41106a290300370300200241e00a6a41086a200241980c6a41086a290300370300200220022903980c3703e00a2018422088a721062017422088a721142018a721082017a7210c4109210d0c5f0b200241a8026a200110c40120022802a8020d5c20022802ac022109200241a80b6a41106a200241e00e6a41106a290200370300200241a80b6a41086a200241e00e6a41086a290200370300200241900b6a41086a200241b00c6a41086a290300370300200241900b6a41106a200241b00c6a41106a290300370300200241f80a6a41086a20024180096a41086a290200370300200241f80a6a41106a20024180096a41106a290200370300200220022902e00e3703a80b200220022903b00c3703900b20022002290280093703f80a200241e00a6a41106a20024180086a41106a290300370300200241e00a6a41086a20024180086a41086a29030037030020022002290380083703e00a410a210d0c5d0b410b210d0c5d0b410c210d0c5c0b200241980c6a200110c30120022802980c2209450d59200241a80b6a41086a200241e00e6a41086a290200370300200241a80b6a41106a200241e00e6a41106a290200370300200241900b6a41086a200241b00c6a41086a290300370300200241900b6a41106a200241b00c6a41106a290300370300200241f80a6a41086a20024180096a41086a290200370300200241f80a6a41106a20024180096a41106a290200370300200220022902e00e3703a80b200220022903b00c3703900b20022002290280093703f80a200229029c0c210a200241e00a6a41106a20024180086a41106a290300370300200241e00a6a41086a20024180086a41086a29030037030020022002290380083703e00a200a422088a72106200aa72108410d210d0c5b0b41002105200241003a00800f2003417e6a21072003417d6a21030240034020072005460d01200241e00e6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00800f2003417f6a21032006210520064120470d000b20024198096a2201200241ff0e6a2d00003a000020024180096a41106a200241f70e6a290000220a370300200241a80b6a41086a200241b00c6a41086a290000370300200241a80b6a41106a200241b00c6a41106a290000370300200220022900b00c3703a80b200241ef0e6a290000211720022800e30e210920022f00e10e212220022d00e00e210e20022900e70e21182001310000210b200241900b6a41106a20024180086a41106a290000370300200241900b6a41086a20024180086a41086a29000037030020022002290080083703900b200241f80a6a41106a200241980c6a41106a290000370300200241f80a6a41086a200241980c6a41086a290000370300200220022900980c3703f80a200241e00a6a41106a200241800c6a41106a290000370300200241e00a6a41086a200241800c6a41086a290000370300200220022900800c3703e00a2018422088a721062017422088a721142018a721082017a7210c410e210d0c5b0b200541ff0171450d58200241003a00800f0c580b410f210d0c590b201f4104490d562004280002210920012003417a6a3602042001200441066a360200200241b0026a200110c40120022802b0020d56200728020020022802b4024102742204490d562004417f4c0d260240024020040d004200210a410121080c010b200410392208450d1b20072802002004490d30200820012802002004109d081a200128020422032004490d2f2001200320046b3602042001200128020020046a3602002004ad210a0b2008450d560240200a2004ad42208684220a422088a722010d00200aa721010c550b024020082001724103710d00200aa722014103710d0020014102762206450d55200a422288a7210c0c560b200aa7450d56200810350c560b201f4104490d552004280002210920012003417a6a3602042001200441066a360200200241b8026a200110c40120022802b8020d5520022802bc02220d200728020041246e22042004200d4b1bad42247e220a422088a70d25200aa72204417f4c0d250240024020040d00410421080c010b200410332208450d1a0b4100210c200241003602880c200220083602800c2002200441246e22063602840c024002400240200d450d00200241ef0e6a2113200241e00e6a411f6a210f200241f40b6a2110200241f00b6a21114100210c410021140340200241003a00800f201441016a211420072802002106417f210341002104034020062004460d03200241e00e6a20046a2001280200220e2d00003a00002001200620036a3602042001200e41016a3602002002200441016a22053a00800f2003417f6a21032005210420054120470d000b200220022800e30e3600c30b200220022802e00e3602c00b200620056b22044104490d032013290000210a200f310000211720022900e70e210b20022900f70e2118200e28000121032001200e41056a36020020012004417c6a360204200241e80b6a41106a2205200a4238883c00002010200a4218883e0200200220022d00c60b3a00e80b2002200ba722043b00e90b200220044110763a00eb0b2002200b421888200a422886843702ec0b20022d00c00b210620022d00c10b210e20022801c20b21120240200c20022802840c470d00200241800c6a200c4101108d0120022802800c210820022802880c210c0b2008200c41246c6a220420123601022004200e3a0001200420063a000020052d000021052011290200210a20022902e80b210b2004411f6a20173c0000200420183700172004200b370106200420033602202004410e6a200a370100200441166a20053a00002002200c41016a220c3602880c2014200d470d000b20022802840c21060b2008450d57200241a80b6a41106a200241b00c6a41106a290200370300200241a80b6a41086a200241b00c6a41086a290200370300200241900b6a41086a20024180096a41086a290200370300200241900b6a41106a20024180096a41106a290200370300200241f80a6a41086a20024180086a41086a290200370300200241f80a6a41106a20024180086a41106a290200370300200220022902b00c3703a80b20022002290280093703900b20022002290280083703f80a200241e00a6a41106a200241980c6a41106a290200370300200241e00a6a41086a200241980c6a41086a290200370300200220022902980c3703e00a4111210d0c590b200441ff0171450d00200241003a00800f0b20022802840c2201450d55200141246c450d55200810350c550b201f4104490d542004280002210920012003417a6a3602042001200441066a360200200241a80b6a41086a20024180096a41086a290200370300200241a80b6a41106a20024180096a41106a290200370300200241900b6a41086a200241980c6a41086a290300370300200241900b6a41106a200241980c6a41106a29030037030020022002290280093703a80b200220022903980c3703900b20022d00d90b212120022f01da0b212020022802dc0b210f200241f80a6a41106a200241800c6a41106a290200370300200241f80a6a41086a200241800c6a41086a290200370300200241e00a6a41086a200241e80b6a41086a290300370300200241e00a6a41106a200241e80b6a41106a290300370300200220022902800c3703f80a200220022903e80b3703e00a200241c80c6a290300211a20022903c00c211b4112210d0c030b41002105200241003a00800f2003417e6a2109417d21060240034020092005460d01200241e00e6a20056a200420056a220741026a2d00003a00002001200320066a3602042001200741036a3602002002200541016a22073a00800f2006417f6a21062007210520074120470d000b20024180096a41186a2205200241ff0e6a2d00003a000020024180096a41106a200241f70e6a290000220a370300200320076b2203417e6a4104490d54200241ef0e6a290000211720022800e30e210920022f00e10e212220022d00e00e210e20022900e70e21182005310000210b200420076a220441026a280000210f20012003417a6a3602042001200441066a360200200241a80b6a41086a200241980c6a41086a290200370300200241a80b6a41106a200241980c6a41106a290200370300200241900b6a41086a200241800c6a41086a290300370300200241900b6a41106a200241800c6a41106a290300370300200241f80a6a41086a200241e80b6a41086a290200370300200241f80a6a41106a200241e80b6a41106a290200370300200220022902980c3703a80b200220022903800c3703900b200220022902e80b3703f80a200241e00a6a41106a200241d00b6a41106a290300370300200241e00a6a41086a200241d00b6a41086a290300370300200220022903d00b3703e00a2018422088a721062017422088a72114200241b00c6a41186a290300211a20022903c00c211b2018a721082017a7210c4113210d0c560b200541ff0171450d53200241003a00800f0c530b200241c0026a200110f60120022903c002a70d52200241c0026a41106a290300210a20022903c802210b200241a80b6a41106a200241e00e6a41106a290200370300200241a80b6a41086a200241e00e6a41086a290200370300200241900b6a41086a200241b00c6a41086a290300370300200241900b6a41106a200241b00c6a41106a290300370300200241f80a6a41086a20024180096a41086a290200370300200241f80a6a41106a20024180096a41106a290200370300200220022902e00e3703a80b200220022903b00c3703900b20022002290280093703f80a200241e00a6a41106a20024180086a41106a290300370300200241e00a6a41086a20024180086a41086a29030037030020022002290380083703e00a200b422088a72106200a422088a72114200ba72108200aa7210c4114210d0c540b200241d8026a200110c40120022802d8020d5120022802dc022109200241a80b6a41086a20024180096a41086a290200370300200241a80b6a41106a20024180096a41106a290200370300200241900b6a41086a20024180086a41086a290300370300200241900b6a41106a20024180086a41106a290300370300200241f80a6a41086a200241980c6a41086a290200370300200241f80a6a41106a200241980c6a41106a29020037030020022002290280093703a80b20022002290380083703900b200220022902980c3703f80a20022802f40b210f20022f01f20b212020022d00f10b2121200241e00a6a41106a200241800c6a41106a290300370300200241e00a6a41086a200241800c6a41086a290300370300200220022903800c3703e00a200241c80c6a290300211a20022903c00c211b4115210d0b410021144100210c41002106410021080c520b41002105200241003a00800f2003417e6a21072003417d6a21030240034020072005460d01200241e00e6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00800f2003417f6a21032006210520064120470d000b20024198096a2201200241ff0e6a2d00003a000020024180096a41106a200241f70e6a290000220a370300200241a80b6a41086a200241b00c6a41086a290000370300200241a80b6a41106a200241b00c6a41106a290000370300200220022900b00c3703a80b200241ef0e6a290000211720022800e30e210920022f00e10e212220022d00e00e210e20022900e70e21182001310000210b200241900b6a41106a20024180086a41106a290000370300200241900b6a41086a20024180086a41086a29000037030020022002290080083703900b200241f80a6a41106a200241980c6a41106a290000370300200241f80a6a41086a200241980c6a41086a290000370300200220022900980c3703f80a200241e00a6a41106a200241800c6a41106a290000370300200241e00a6a41086a200241800c6a41086a290000370300200220022900800c3703e00a2018422088a721062017422088a721142018a721082017a7210c4116210d0c520b200541ff0171450d4f200241003a00800f0c4f0b200241e0026a200110c40120022802e0020d4e200728020020022802e4024101742204490d4e2004417f4c0d1e0240024020040d004200210a410121090c010b200410392209450d1320072802002004490d4c200920012802002004109d081a200128020422032004490d292001200320046b3602042001200128020020046a3602002004ad210a0b2009450d4e02402004ad422086200a84220a422088a722040d00200aa721040c4a0b024020092004724101710d00200aa722044101710d0020044101762208450d4a200a422188a721060c4b0b200aa70d4b0c4e0b200241e8026a200110c40120022802e8020d4d200728020020022802ec024101742204490d4d2004417f4c0d1d0240024020040d004200210a410121090c010b200410392209450d1220072802002004490d4b200920012802002004109d081a200128020422032004490d292001200320046b3602042001200128020020046a3602002004ad210a0b2009450d4d02402004ad422086200a84220a422088a722040d00200aa721040c470b024020092004724101710d00200aa722044101710d0020044101762208450d47200a422188a721060c480b200aa70d4a0c4d0b2006450d2a20042d0001210520012003417e6a3602042001200441026a360200200541014b0d2a410021040240024020050e020001000b200241b00c6a200110c20220022d00b00c4101460d2b20024190066a200241b00c6a410172418001109d081a200241f0026a200110c40120022802f0020d2b200728020020022802f4022203490d2b2003417f4c0d1d0240024020030d004200210a410121040c010b200310392204450d1220072802002003490d2b200420012802002003109d081a200128020422052003490d2a2001200520036b3602042001200128020020036a3602002003ad210a0b2004450d2b200a2003ad42208684210a20024180096a20024190066a418001109d081a0b20024180086a20024180096a418001109d081a200041086a200a3702002000200436020420004108360200200041106a20024180086a418001109d081a20004190016a200241e00e6a41a001109d081a0c570b02402006450d0020042d0001210520012003417e6a22233602042001200441026a3602002005411c4b0d00410e2113410021090240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020050e1d000102030405060708090a0b0c610d0e0f101112131415161718191a1b000b41002105200241003a00d00c2003417e6a21072003417d6a21030240034020072005460d01200241b00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00d00c2003417f6a21032006210520064120470d000b200220022800b30c3600c30b200220022802b00c22063602c00b200241bf0c6a2900002119200241cf0c6a310000210a20022900b70c210b20022900c70c211e200241c50b6a2d0000210420022d00c10b210820022d00c20b210e20022d00c60b210d20022f00c30b2103200241f8026a200110f60120022903f802a70d1d200241f8026a41106a29030021182002290380032117201e422088200a42ff018342208684210a200320044110747241ffffff077121092019420888a721122019421088a7210f2019422088a72111201ea721102019a72116410121130c610b200541ff0171450d1c200241003a00d00c0c1c0b20024190036a200110c4012002280290030d1b2002280294032209411876210d410221130c5d0b20024198036a200110c4012002280298030d1a200228029c032109200241b00c6a200110ca0220022d00b00c4102460d1a2009411876210d200241c40c6a350200200241b00c6a41186a31000042208684210a200241d00c6a2903002117200241cc0c6a2802002114200241ca0c6a2f01002115200241c90c6a2d0000210c200241c00c6a2802002110200241bc0c6a2802002111200241ba0c6a2f0100210f200241b90c6a2d00002112200241b80c6a2d0000211620022903b00c210b42002118410321134100210e0c5e0b200241a0036a200110c40120022802a0030d1920022802a4032109200241b00c6a200110ca0220022d00b00c4102460d192009411876210d200241c40c6a350200200241b00c6a41186a31000042208684210a200241d00c6a2903002117200241cc0c6a2802002114200241ca0c6a2f01002115200241c90c6a2d0000210c200241c00c6a2802002110200241bc0c6a2802002111200241ba0c6a2f0100210f200241b90c6a2d00002112200241b80c6a2d0000211620022903b00c210b42002118410421134100210e0c5d0b20234104490d182004280002210920012003417a6a3602042001200441066a3602002009411876210d410521130c5a0b41002105200241003a00d00c2003417e6a21072003417d6a21030240034020072005460d01200241b00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00d00c2003417f6a21032006210520064120470d000b200220022800b30c3600c30b200220022802b00c22063602c00b20022900c70c2218422088200241cf0c6a31000042208684210a20022f00c30b200241c50b6a2d0000411074722109200241bf0c6a2900002217422088a721112017421088a7210f2017420888a7211220022900b70c210b20022d00c10b210820022d00c20b210e20022d00c60b210d2018a721102017a72116410621130c5c0b200541ff0171450d17200241003a00d00c0c170b41002105200241003a00d00c2003417e6a21072003417d6a21030240034020072005460d01200241b00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00d00c2003417f6a21032006210520064120470d000b200220022800b30c3600c30b200220022802b00c22063602c00b20022900c70c2218422088200241cf0c6a31000042208684210a20022f00c30b200241c50b6a2d0000411074722109200241bf0c6a2900002217422088a721112017421088a7210f2017420888a7211220022900b70c210b20022d00c10b210820022d00c20b210e20022d00c60b210d2018a721102017a72116410721130c5b0b200541ff0171450d16200241003a00d00c0c160b41002105200241003a00d00c2003417e6a21072003417d6a21030240034020072005460d01200241b00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00d00c2003417f6a21032006210520064120470d000b200220022800b30c3600c30b200220022802b00c22063602c00b20022900c70c2218422088200241cf0c6a31000042208684210a20022f00c30b200241c50b6a2d0000411074722109200241bf0c6a2900002217422088a721112017421088a7210f2017420888a7211220022900b70c210b20022d00c10b210820022d00c20b210e20022d00c60b210d2018a721102017a72116410821130c5a0b200541ff0171450d15200241003a00d00c0c150b41002105200241003a00d00c2003417e6a2109417d21060240034020092005460d01200241b00c6a20056a200420056a220741026a2d00003a00002001200320066a3602042001200741036a3602002002200541016a22073a00d00c2006417f6a21062007210520074120470d000b200220022800b30c3600c30b200220022802b00c22063602c00b200320076b2203417e6a4104490d15200241c50b6a2d0000210920022f00c30b210c200241bf0c6a290000210a200241cf0c6a310000211920022900b70c210b20022900c70c211820022d00c10b210820022d00c20b210e20022d00c60b210d200420076a220441026a280000211420012003417a6a22053602042001200441066a220736020020054104490d15200a422088a72111200a421088a7210f200a420888a72112200aa72116200735000021172001200341766a36020420012004410a6a3602002018422088201942ff018342208684210a200c20094110747241ffffff077121092018a7211042002118410921130c590b200541ff0171450d14200241003a00d00c0c140b41002105200241003a00d00c2003417e6a21072003417d6a21030240034020072005460d01200241b00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00d00c2003417f6a21032006210520064120470d000b200220022800b30c3600c30b200220022802b00c22063602c00b20022900c70c2218422088200241cf0c6a31000042208684210a20022f00c30b200241c50b6a2d0000411074722109200241bf0c6a2900002217422088a721112017421088a7210f2017420888a7211220022900b70c210b20022d00c10b210820022d00c20b210e20022d00c60b210d2018a721102017a72116410a21130c580b200541ff0171450d13200241003a00d00c0c130b200241a8036a200110c40120022802a8030d1220022802ac032209411876210d410b21130c540b20234104490d112004280002210920012003417a6a3602042001200441066a3602002009411876210d410c21130c530b41002105200241003a00d00c2003417e6a21072003417d6a21030240034020072005460d01200241b00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00d00c2003417f6a21032006210520064120470d000b200220022800b30c3600c30b200220022802b00c22063602c00b20022900c70c2218422088200241cf0c6a31000042208684210a20022f00c30b200241c50b6a2d0000411074722109200241bf0c6a2900002217422088a721112017421088a7210f2017420888a7211220022900b70c210b20022d00c10b210820022d00c20b210e20022d00c60b210d2018a721102017a72116410d21130c550b200541ff0171450d10200241003a00d00c0c100b41002105200241003a00d00c2003417e6a21072003417d6a21030240034020072005460d01200241b00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00d00c2003417f6a21032006210520064120470d000b200220022800b30c3600c30b200220022802b00c22063602c00b20022900c70c2218422088200241cf0c6a31000042208684210a20022f00c30b200241c50b6a2d0000411074722109410f2113200241b00c6a410f6a2900002217422088a721112017421088a7210f2017420888a7211220022900b70c210b20022d00c10b210820022d00c20b210e20022d00c60b210d2018a721102017a721160c540b200541ff0171450d0f200241003a00d00c0c0f0b41002105200241003a00d00c2003417e6a2108417d21070240034020082005460d01200241b00c6a20056a200420056a220641026a2d00003a00002001200320076a3602042001200641036a3602002002200541016a22093a00d00c2007417f6a21072009210520094120470d000b200220022800b30c3600c30b200220022802b00c22063602c00b2003417e6a2009460d0f200241c50b6a2d0000211420022f00c30b2110200241bf0c6a290000210a200241cf0c6a310000211e20022900b70c210b20022900c70c211920022d00c10b210820022d00c20b210e20022d00c60b210d200420096a220441026a2d0000210c2001200320076a22053602042001200441036a360200200c41064b0d0f4110211320054110490d0f200a422088a72111200a421088a7210f200a420888a72112200aa721162004410b6a2900002118200441036a29000021172001200320096b416d6a3602042001200441136a3602002019422088201e42ff018342208684210a201020144110747241ffffff077121092019a721100c530b200541ff0171450d0e200241003a00d00c0c0e0b411121130c500b411221130c4f0b200241b0036a200110c40120022802b0030d0b200728020020022802b4032204490d0b2004417f4c0d270240024020040d004200210a410121090c010b200410392209450d1c20072802002004490d0b200920012802002004109d081a200128020422032004490d372001200320046b3602042001200128020020046a3602002004ad210a0b2009450d0b200a2004ad42208684210b2009411876210d411321134100210e0c4f0b200241b8036a200110c40120022802b8030d0a200728020020022802bc032204490d0a2004417f4c0d260240024020040d004200210a410121090c010b200410392209450d1b20072802002004490d0a200920012802002004109d081a200128020422032004490d372001200320046b3602042001200128020020046a3602002004ad210a0b2009450d0a200a2004ad42208684210b2009411876210d411421134100210e0c4e0b41002105200241003a00d00c2003417e6a21072003417d6a21030240034020072005460d01200241b00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00d00c2003417f6a21032006210520064120470d000b200220022800b30c3600c30b200220022802b00c22063602c00b20022900c70c2218422088200241cf0c6a31000042208684210a20022f00c30b200241c50b6a2d0000411074722109200241bf0c6a2900002217422088a721112017421088a7210f2017420888a7211220022900b70c210b20022d00c10b210820022d00c20b210e20022d00c60b210d2018a721102017a72116411521130c4e0b200541ff0171450d09200241003a00d00c0c090b41002105200241003a00d00c2003417e6a21072003417d6a21030240034020072005460d01200241b00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00d00c2003417f6a21032006210520064120470d000b200220022800b30c3600c30b200220022802b00c22063602c00b20022900c70c2218422088200241cf0c6a31000042208684210a20022800c30b2209411876210d20022f00c10b2208410876210e200241bf0c6a2900002217422088a721112017421088a7210f2017420888a7211220022900b70c210b2018a721102017a72116411621130c4d0b200541ff0171450d08200241003a00d00c0c080b41002105200241003a00d00c2003417e6a21072003417d6a21030240034020072005460d01200241b00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00d00c2003417f6a21032006210520064120470d000b200220022800b30c3600c30b200220022802b00c22063602c00b20022900c70c2218422088200241cf0c6a31000042208684210a20064180fe0371410876210820022801c20b220e4108762109200241bf0c6a2900002217422088a721112017421088a7210f2017420888a7211220022900b70c210b20022d00c60b210d2018a721102017a72116411721130c4c0b200541ff0171450d07200241003a00d00c0c070b20234104490d062004280002210920012003417a6a3602042001200441066a360200411821132009411876210d0c480b41002105200241003a00d00c2003417e6a2109417d21060240034020092005460d01200241b00c6a20056a200420056a220741026a2d00003a00002001200320066a3602042001200741036a3602002002200541016a22073a00d00c2006417f6a21062007210520074120470d000b20024198086a200241cf0c6a310000220a3c0000200220022800b30c3600c30b200220022802b00c22063602c00b200220022900c70c221837039008200220022900b70c220b370380082002200241bf0c6a290000221737038808200320076b2203417e6a4104490d06200241c50b6a2d0000210520022f00c30b210920022d00c10b210820022d00c20b210e20022d00c60b210d200420076a220441026a280000211420012003417a6a3602042001200441066a3602002018422088200a42ff018342208684210a200920054110747241ffffff077121092017422088a72111201742ffffffff0f832219421088a7210f2019420888a721122018a721102017a72116411921130c4a0b200541ff0171450d05200241003a00d00c0c050b41002105200241003a00d00c2003417e6a2109417d21070240034020092005460d01200241b00c6a20056a200420056a220641026a2d00003a00002001200320076a3602042001200641036a3602002002200541016a220e3a00d00c2007417f6a2107200e2105200e4120470d000b200220022800b30c3600c30b200220022802b00c22063602c00b2003417e6a200e460d05200241bf0c6a2900002119200241cf0c6a310000210a20022900b70c210b20022900c70c211e20022f00c10b210820022800c30b21092004200e6a220441026a2d0000210c2001200320076a22053602042001200441036a360200200c41064b0d0520054110490d052004410b6a2900002118200441036a290000211720012003200e6b416d6a3602042001200441136a360200201e422088200a42ff018342208684210a2009411876210d20084180fe0371410876210e2019422088a721112019421088a7210f2019420888a72112201ea721102019a72116411a21130c490b200541ff0171450d04200241003a00d00c0c040b411b21130c460b20234104490d022004280002210920012003417a6a3602042001200441066a3602002009411876210d411c21130c440b41002105200241003a00d00c2003417e6a2109417d21060240034020092005460d01200241b00c6a20056a200420056a220741026a2d00003a00002001200320066a3602042001200741036a3602002002200541016a22073a00d00c2006417f6a21062007210520074120470d000b200241e80b6a41106a200241bf0c6a290000220a4238883c0000200241f40b6a200a4218883e0200200220022800b30c3600c30b200220022802b00c22063602c00b200220022d00c60b3a00e80b200220022900b70c220ba722053b00e90b200220054110763a00eb0b2002200b421888200a422886843702ec0b200320076b2203417e6a4104490d02200241cf0c6a310000210a20022900c70c211720022d00c10b210820022801c20b210e200420076a220441026a280000211420012003417a6a3602042001200441066a36020020024180096a41086a200241e80b6a410172220141086a290000220b3703002017422088200a42ff018342208684210a200e4108762109200ba721162001290000210b20022d00e80b210d20022d008909211220022f018a09210f200228028c0921112017a72110411d21130c460b200541ff0171450d01200241003a00d00c0c010b200910350b2000411b3602000c560b200241b00c6a2001109306024020022d00b00c4106460d0020024190066a41286a200241b00c6a41286a290300220a37030020024190066a41206a200241b00c6a41206a290300220b37030020024190066a41186a200241b00c6a41186a290300221737030020024190066a41106a200241b00c6a41106a290300221837030020024190066a41086a200241b00c6a41086a2903002219370300200220022903b00c221e370390062000410a3602002000201e3702042000410c6a2019370200200041146a20183702002000411c6a2017370200200041246a200b3702002000412c6a200a370200200041346a200241e00e6a41fc01109d081a0c560b2000411b3602000c550b200241b00c6a2001109306024020022d00b00c4106460d0020024190066a41286a200241b00c6a41286a290300220a37030020024190066a41206a200241b00c6a41206a290300220b37030020024190066a41186a200241b00c6a41186a290300221737030020024190066a41106a200241b00c6a41106a290300221837030020024190066a41086a200241b00c6a41086a2903002219370300200220022903b00c221e370390062000410b3602002000201e3702042000410c6a2019370200200041146a20183702002000411c6a2017370200200041246a200b3702002000412c6a200a370200200041346a200241e00e6a41fc01109d081a0c550b2000411b3602000c540b2006450d3d20042d0001210520012003417e6a360204410221032001200441026a360200200541054b0d3d02400240024002400240024020050e06000501020304000b200241b00c6a200110c30120022802b00c2204450d42200241b80c6a280200210720022802b40c2106200241c0036a200110f601024020022903c003a70d00200241d0036a290300211720022903c803210b410121030c050b200641ffffff3f71450d42200410350c420b200241b00c6a200110920620022d00b00c4102460d41200241c40c6a2902002117200241bc0c6a290200210b200241cc0c6a290200210a200241b80c6a280200210720022802b40c210620022802b00c2104410321030c030b410421030c020b410521030c010b200241b00c6a200110920620022d00b00c4102460d3e200241c40c6a2902002117200241bc0c6a290200210b200241cc0c6a290200210a200241b80c6a280200210720022802b40c210620022802b00c2104410621030b2000410c360200200041206a2017370200200041186a200b370200200041286a200a370200200041146a2007360200200041106a20063602002000410c6a2004360200200041086a2003360200200041306a200241e00e6a418002109d081a0c530b02402006450d0020042d0001210520012003417e6a3602042001200441026a360200200541064b0d004200211941072106410021074200211c4200211b4200211a4200210b420021244200212502400240024002400240024020050e0700010203040542000b41002105200241003a00d00c2003417e6a21072003417d6a21030240034020072005460d01200241b00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00d00c2003417f6a21032006210520064120470d000b200241e80b6a41106a200241bf0c6a290000220a4238883c0000200241f40b6a200a4218883e0200200220022800b30c3600c30b200220022802b00c22083602c00b200220022900b70c220ba722013b00e90b200220014110763a00eb0b2002200b421888200a422886843702ec0b20022900c70c220b422088200241cf0c6a31000042208684210a20022801c20b2209410876210720022d00c10b210e20022d00c60b210c200241f10b6a290000211820022900e90b2117200ba7211142002119410121060c400b200541ff0171450d05200241003a00d00c0c050b41002105200241003a00d00c2003417e6a21072003417d6a21030240034020072005460d01200241b00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00d00c2003417f6a21032006210520064120470d000b200241e80b6a41106a2201200241bf0c6a290000220a4238883c0000200241f40b6a200a4218883e020020024190066a41106a20012d00003a0000200220022900b70c220b421888200a422886843702ec0b20024190066a41086a200241e80b6a41086a290200370300200220022800b30c3600c30b200220022d00c60b3a00e80b2002200ba722013b00e90b200220014110763a00eb0b200220022802b00c22083602c00b200220022902e80b3703900620022d00c10b210e20022801c20b210920022900c70c210b200241a9066a200241cf0c6a310000220a3c00002002200b3700a106200b422088200a42208684210a2009410876210720024199066a2900002118200229009106211720022d009006210c200ba7211142002119410221060c3f0b200541ff0171450d04200241003a00d00c0c040b41002105200241003a00d00c410220036b21092003417d6a2106024002400340200920056a450d01200241b00c6a20056a200420056a220741026a2d00003a0000200120063602042001200741036a3602002002200541016a22073a00d00c2006417f6a21062007210520074120470d000b200241e80b6a41106a200241bf0c6a290000220a4238883c0000200241f40b6a200a4218883e0200200220022802b00c22083602c00b200220022800b30c3600c30b200220022900b70c220ba722053b00e90b200220054110763a00eb0b2002200b421888200a422886843702ec0b200241cf0c6a310000210a20022900c70c210b20022d00c10b210e20022d00c60b210c20022801c20b2109200241f10b6a290000211820022900e90b211741002105200241003a00d00c200420076a210d200720036b41026a2103200941087621070340200320056a450d02200241b00c6a20056a200d20056a220441026a2d00003a0000200120063602042001200441036a3602002002200541016a22043a00d00c2006417f6a21062004210520044120470d000b200241e80b6a41106a200241bf0c6a29000022194238883c0000200241f40b6a20194218883e0200200220022800b30c3600c30b200220022802b00c22103602c00b200220022900b70c221ea722013b00e90b200220014110763a00eb0b2002201e4218882019422886843702ec0b20022d00c60b41187420022801c20b2201410876722113200b422088200a42ff018342208684210a200141087420022d00c10b72210f20022900e90b221e42ffffffff0f832119201e42808080807083211b200241f10b6a290000221e42ffffffff0f832124201e428080808070832125200241cf0c6a310000211d20022900c70c211e200ba721114200211c410321064200211a4200210b0c410b200541ff0171450d04200241003a00d00c0c040b200541ff0171450d03200241003a00d00c0c030b200241b00c6a200110c30120022802b00c2207450d022007411876210c20023502840920024188096a31000042208684210a20022902b40c211720022d008909211020022f018a09210f20022d008908210d20022f018a082114420021184104210641002109420021190c3d0b41002105200241003a00d00c2003417e6a21072003417d6a21030240034020072005460d01200241b00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00d00c2003417f6a21032006210520064120470d000b200220022800b30c3600c30b200220022802b00c22083602c00b20022900c70c220b422088200241cf0c6a31000042208684210a20022801c20b22094108762107200241bf0c6a290000211820022900b70c211720022d00c10b210e20022d00c60b210c200ba7211142002119410521060c3c0b200541ff0171450d01200241003a00d00c0c010b41002105200241003a00d00c2003417e6a21072003417d6a21030240034020072005460d01200241b00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00d00c2003417f6a21032006210520064120470d000b200241e80b6a41106a200241bf0c6a290000220a4238883c0000200241f40b6a200a4218883e0200200220022900b70c220b421888200a422886843702ec0b20024180096a41086a2201200241f10b6a290000370300200220022800b30c3600c30b2002200ba722043b00e90b200220044110763a00eb0b200220022802b00c22083602c00b200220022d00c60b220c3a00e80b200220022900e90b3703800920022d00c10b210e20022801c20b210920022900c70c210b20024198096a200241cf0c6a310000220a3c00002002200b37039009200b422088200a42208684210a20094108762107200129030021182002290380092117200ba7211142002119410621060c3b0b200541ff0171450d00200241003a00d00c0b2000411b3602000c520b02402006450d0020042d0001210520012003417e6a3602042001200441026a36020020050d00200241d8036a200110c40120022802d8030d0020022802dc0321012000410e36020020002001360204200041086a200241e00e6a41a802109d081a0c520b2000411b3602000c510b02402006450d0020042d0001210520012003417e6a3602042001200441026a36020020050d00200241e0036a200110c40120022802e0030d00200728020020022802e4032204490d002004417f4c0d1602400240024020040d004200210a410121030c010b200410392203450d0c20072802002004490d01200320012802002004109d081a200128020422052004490d292001200520046b3602042001200128020020046a3602002004ad210a0b2003450d01200020033602042000410f360200200041086a200a2004ad42208684370200200041106a200241e00e6a41a002109d081a0c520b200310350b2000411b3602000c500b2006450d3320042d0001210520012003417e6a3602042001200441026a360200200541074b0d3302400240024002400240024002400240024020050e080001020304050607000b200241e8036a200110f60120022903e803a70d3b200241f8036a290300210a20022903f003210b200241b00c6a200110920620022d00b00c4102460d3b200241d80b6a2205200241cc0c6a2802003602002002200b3703980c2002200a3703a00c20022902b40c2219421888200241bc0c6a290200220b42288684210a20022802b00c22034118762101200b4218882118200241c40c6a290200210b200241d00c6a28020021042005310000211720022f01da0b210720022d00d90b21092019a721084101210e4100210c0c3d0b20024180046a200110c4012002280280040d3a2002280284042103200241980c6a41106a200241b00c6a41106a290300370300200241980c6a41086a200241b00c6a41086a290300370300200220022903b00c3703980c200341187621014200210a4102210e0c3b0b20024188046a200110c4012002280288040d39200228028c042103200241980c6a41106a200241b00c6a41106a290300370300200241980c6a41086a200241b00c6a41086a290300370300200220022903b00c3703980c200341187621014200210a4103210e0c3a0b20024190046a200110c4012002280290040d3820072802002002280294042206490d382006417f4c0d1902400240024020060d004200210a410121040c010b200610392204450d0f20072802002006490d01200420012802002006109d081a200128020422032006490d2d2001200320066b3602042001200128020020066a3602002006ad210a0b2004450d3941002105200241003a00d00c2007280200417f6a2103200a2006ad42208684220a422088a72109200aa72107024003402003417f460d01200241b00c6a20056a200128020022062d00003a0000200120033602042001200641016a3602002002200541016a22063a00d00c2003417f6a21032006210520064120470d000b200220022800b30c3600c30b200220022802b00c22053602c00b2002200936029c0c200220073602980c20022900b70c2219421888200241bf0c6a290000220b42288684210a20054180fe03714108762106200b421888211820022801c20b220c4108762103200241cf0c6a310000211720022900c70c210b20022d00c60b21012019a721084104210e0c3c0b0240200541ff0171450d00200241003a00d00c0b2007450d390b200410350c380b41002105200241003a00d00c2003417e6a21072003417d6a21030240034020072005460d01200241b00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00d00c2003417f6a21032006210520064120470d000b200241980c6a41086a20024190066a41086a290000370300200241980c6a41106a20024190066a41106a290000370300200220022800b30c3600c30b200220022802b00c22053602c00b20022002290090063703980c20022900b70c2219421888200241bf0c6a290000220b42288684210a200b421888211820022800c30b2203411876210120022f00c10b2206410876210c200241cf0c6a310000211720022900c70c210b2019a721084105210e0c3a0b200541ff0171450d37200241003a00d00c0c370b20024198046a200110c4012002280298040d362007280200200228029c042205490d362005417f4c0d170240024020050d004200210a410121040c010b200510392204450d0c20072802002005490d36200420012802002005109d081a200128020422032005490d2b2001200320056b3602042001200128020020056a3602002005ad210a0b2004450d3641002103200241003a00d00c200a2005ad42208684220a422088a7210e200aa7210820072802002107417f21050240034020072003460d01200241b00c6a20036a200128020022092d00003a00002001200720056a3602042001200941016a3602002002200341016a22063a00d00c2005417f6a21052006210320064120470d000b200220022800b30c3600c30b200220022802b00c22053602c00b200720066b22074110490d03200241bf0c6a2900002118200241cf0c6a310000211720022900b70c211920022900c70c210b20022f00c10b210620022800c30b2103200241980c6a41106a200941096a2900003703002009290001210a2001200741706a3602042001200941116a3602002002200e36029c0c200220083602980c2002200a3703a00c2019421888201842288684210a200341187621012018421888211820064180fe0371410876210c2019a721084106210e0c390b0240200341ff0171450d00200241003a00d00c0b2008450d360c350b41002105200241003a00d00c2003417e6a2109417d21060240034020092005460d01200241b00c6a20056a200420056a220741026a2d00003a00002001200320066a3602042001200741036a3602002002200541016a22073a00d00c2006417f6a21062007210520074120470d000b20024180096a41186a200241cf0c6a31000022173c0000200220022800b30c3600c30b200220022802b00c22053602c00b200220022900c70c220b37039009200220022900b70c2219370380092002200241bf0c6a290000221837038809200320076b2209417e6a4110490d3620022f00c10b210620022800c30b2103200420076a220441026a290000210a2004410a6a290000211e20012009416e6a3602042001200441126a3602002002201e3703a00c2002200a3703980c2019421888201842288684210a200341187621012018421888211820064180fe0371410876210c2019a721084107210e0c380b200541ff0171450d35200241003a00d00c0c350b41002105200241003a00d00c2003417e6a21072003417d6a21030240034020072005460d01200241b00c6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00d00c2003417f6a21032006210520064120470d000b4108210e200241980c6a41086a20024190066a41086a290000370300200241980c6a41106a20024190066a41106a290000370300200220022800b30c3600c30b200220022802b00c22053602c00b200220022900b70c220aa722084110763a00eb0b20022002290090063703980c200a421888200241bf0c6a290000220b42288684210a200b421888211820022801c20b220c4108762103200241cf0c6a310000211720022900c70c210b20022d00c10b210620022d00c60b21010c370b200541ff0171450d34200241003a00d00c0c340b20080d320c330b02402006450d0020042d0001210520012003417e6a3602042001200441026a360200200541044b0d0002400240024002400240024002400240024020050e050001020304000b200241e00e6a200110db0220022d00e80f4102460d08200241a80b6a41086a200241e00e6a41106a290300370300200241a80b6a41106a200241f80e6a2d00003a0000200241980c6a41086a200241900f6a290300370300200241980c6a41106a200241980f6a290300370300200220022903e80e3703a80b200220022903880f3703980c200241fc0e6a2802002104200241840f6a280200210c20022903e00e210a20022d00f90e210520022d00fa0e210620022d00fb0e210820022802800f210d20022903a00f210b20024190066a200241e00e6a41c8006a41c800109d081a200241b00a6a41026a20024180086a41026a2d00003a0000200220022f0080083b01b00a410121010c050b200241a0046a200110c40120022802a0040d07200728020020022802a4042204490d072004417f4c0d1b02400240024020040d004200210a410121090c010b200410392209450d1120072802002004490d01200920012802002004109d081a200128020422032004490d312001200320046b3602042001200128020020046a3602002004ad210a0b2009450d08200a2004ad42208684210a41022101200241b00a6a41026a200241d00b6a41026a2d00003a0000200241a80b6a41086a200241e80b6a41086a290300370300200241a80b6a41106a200241e80b6a41106a2d00003a0000200241980c6a41086a20024180086a41086a290300370300200241980c6a41106a20024180086a41106a290300370300200220022f00d00b3b01b00a200220022903e80b3703a80b20022002290380083703980c20024190066a200241e00e6a41c800109d081a0c040b200910350c070b20024180086a200110920620022d0080084102460d06200241f00b6a20024194086a290200370300200241e80b6a41106a2002419c086a2d00003a000020022002418c086a2902003703e80b2002419d086a2d000021052002419e086a2d000021062002419f086a2d00002108200241a0086a2802002104200229028408210a2002280280082109200241c0046a200110f60120022903c004a70d06200241c0046a41106a290300211720022903c8042118200241b0046a200110910620022903b004a70d0620022903b804210b200241a8046a200110c40120022802a8040d06200728020020022802ac042203490d062003417f4c0d1a0240024020030d00420021194101210d0c010b20031039220d450d0f20072802002003490d06200d20012802002003109d081a200128020422072003490d302001200720036b3602042001200128020020036a3602002003ad21190b200d450d06200241a80b6a41106a200241e80b6a41106a2d00003a0000200241a80b6a41086a200241e80b6a41086a290300370300200241980c6a41106a2017370300200241b00a6a41026a200241d00b6a41026a2d00003a0000200220022903e80b3703a80b200220183703a00c200220022f00d00b3b01b00a200220192003ad4220868422174220883e02980c20024190066a200241e00e6a41c800109d081a2017a7210c410321010c030b200241f0046a200110f60120022903f004a70d0520024180056a290300210b20022903f8042117200241e0046a200110910620022903e004a70d0520022903e804211841002103200241003a00a0082007280200417f6a2104024002400240024003402004417f460d0120024180086a20036a200128020022052d00003a0000200120043602042001200541016a3602002002200341016a22053a00a0082004417f6a21042005210320054120470d000b200241e20a6a20022d0082083a0000200241e00b6a2002419f086a2d00003a0000200241d80b6a20024197086a2900003703002002200229008f08220a3703e80b200220022f0180083b01e00a2002200a3703d00b200229008708210a2002280083082109200241d8046a200110c40120022802d8040d09200728020020022802dc04220c490d09200c417f4c0d1d200c0d01410121044101450d094100210d0c020b200341ff0171450d08200241003a00a0080c080b200c10392204450d0f2007280200200c490d0120042001280200200c109d08210320012802042205200c490d3120012005200c6b36020420012001280200200c6a3602002003450d07200c210d0b200241b00a6a41026a200241e00a6a41026a2d00003a0000200241a80b6a41086a200241d00b6a41086a290300370300200241a80b6a41106a200241d00b6a41106a2d00003a0000200220022f01e00a3b01b00a200220022903d00b3703a80b200220173703980c200220183703a80c2002200b3703a00c20024190066a200241e00e6a41c800109d081a410421010c020b200410350c050b41002105200241003a00a0082003417e6a21092003417d6a2106024002400240034020092005460d0120024180086a20056a200420056a220741026a2d00003a0000200120063602042001200741036a3602002002200541016a22073a00a0082006417f6a21062007210520074120470d000b200241c80a6a41026a20022d0082083a0000200241e00b6a2002419f086a2d00003a0000200241d80b6a20024197086a2900003703002002200229008f08220a3703e80b200220022f0180083b01c80a2002200a3703d00b2003417e6a2007460d07200229008708210a2002280083082109200420076a220e41026a2d00002114200120063602042001200e41036a360200201441014b0d074100210520140e020201020b200541ff0171450d06200241003a00a0080c060b41002104200241003a00a008200720036b41036a2106200320076b417c6a21030340200620046a450d0420024180086a20046a200e20046a220541036a2d00003a0000200120033602042001200541046a3602002002200441016a22053a00a0082003417f6a21032005210420054120470d000b200241e80b6a41106a22012002418f086a290000220b4238883c0000200241f40b6a200b4218883e020020022002280083083600c30b200220022802800822063602c00b200220022d00c60b3a00e80b20022002290087082217a722043b00e90b200220044110763a00eb0b200220174218882218200b422886843702ec0b2002419f086a3100002117200229009708210b20022d00c10b210820022801c20b210420022802e80b210d200241800b6a20012d00003a0000200220022902f00b3703f80a2018a7210c410121050b200241a90c6a20173c0000200241980c6a41086a200241f80a6a41086a2d00003a0000200241b00a6a41026a200241c80a6a41026a2d00003a0000200241a80b6a41086a200241d00b6a41086a290300370300200241a80b6a41106a200241d00b6a41106a2d00003a00002002200b3700a10c200220022903f80a3703980c200220022f01c80a3b01b00a200220022903d00b3703a80b200241ae0c6a200241e40a6a2f01003b0100200220022801e00a3601aa0c20024190066a200241e00e6a41c800109d081a410521010b0b200241980a6a41026a2203200241b00a6a41026a2d00003a0000200241900b6a41086a2207200241a80b6a41086a290300370300200241900b6a41106a220e200241a80b6a41106a2d00003a0000200241800c6a41086a2214200241980c6a41086a290300370300200241800c6a41106a2213200241980c6a41106a290300370300200220022f01b00a3b01980a200220022903a80b3703900b200220022903980c3703800c20024180096a20024190066a41c800109d081a200041086a20013a000020004111360200200020022f01980a3b00092000410b6a20032d00003a0000200041106a200a3702002000410c6a2009360200200041186a20022903900b370000200041206a2007290300370000200041286a200e2d00003a0000200041346a200c360200200041306a200d3602002000412c6a2004360200200020083a002b200020063a002a200020053a0029200041d0006a200b370200200041c8006a2013290300370200200041c0006a2014290300370200200041386a20022903800c370200200041d8006a20024180096a41c800109d081a200041a0016a200241b00c6a419001109d081a0c510b200441ff0171450d01200241003a00a0080c010b200d10350b2000411b3602000c4e0b200241b00c6a2001109406024020022802b00c4104460d0020024190066a41286a200241b00c6a41286a280200220136020020024190066a41206a200241b00c6a41206a290300220a37030020024190066a41186a200241b00c6a41186a290300220b37030020024190066a41106a200241b00c6a41106a290300221737030020024190066a41086a200241b00c6a41086a2903002218370300200220022903b00c22193703900620004112360200200020193702042000410c6a2018370200200041146a20173702002000411c6a200b370200200041246a200a3702002000412c6a2001360200200041306a200241e00e6a418002109d081a0c4e0b2000411b3602000c4d0b02402006450d0020042d0001210520012003417e6a22063602042001200441026a36020020050d0020064104490d002004280002210520012003417a6a3602042001200441066a36020020024198056a200110c4012002280298050d002007280200200228029c052204490d002004417f4c0d1202400240024002400240024002400240024020040d0041002103410121060c010b200410392206450d0e20072802002004490d01200620012802002004109d081a200128020422032004490d312001200320046b3602042001200128020020046a360200200421030b2006450d0720024190056a200110c4012004ad4220862003ad84220ba7210d02402002280290050d0020022802940522082007280200410c6e2204200420084b1bad420c7e220a422088a70d1a200aa72204417f4c0d1a0240024020040d004104210e0c010b20041033220e450d0f0b41002103200241003602b80c2002200e3602b00c20022004410c6e22093602b40c0240024002402008450d0041002103034020024188056a200110c4012002280288050d032007280200200228028c052204490d032004417f4c0d1e0240024020040d004100210c410121090c010b200410392209450d1320072802002004490d03200920012802002004109d081a2001280204220c2004490d372001200c20046b3602042001200128020020046a3602002004210c0b2004ad422086200cad84210a0240200320022802b40c470d00200241b00c6a2003410110870120022802b00c210e20022802b80c21030b200e2003410c6c6a2204200a370204200420093602002002200341016a22033602b80c2008417f6a22080d000b20022802b40c21090b200e450d022006450d0a200728020022074104490d042001280200220c280000211320012007417c6a22043602042001200c41046a36020020044104490d05200c280004210f2001200741786a22043602042001200c41086a36020020044104490d06200b422088a72110200c28000821112001200741746a22143602042001200c410c6a36020041002104200241003a00f00c200741736a2107034020142004460d08200241b00c6a20046a200c20046a2208410c6a2d00003a00002001200736020420012008410d6a3602002002200441016a22083a00f00c2007417f6a210720082104200841c000470d000b200841ff017141c000490d082006450d0a200241e80c6a290300210a200241b80c6a290300210b20022903e00c211720022903b00c211820022802dc0c210120022902d40c211920022802d00c210420022802cc0c210720022f01ca0c210820022d00c80c210c20022903c00c211e200020022d00c90c3a00452000200536020420004113360200200041e4006a200a370200200041dc006a2017370200200041346a200b3702002000412c6a2018370200200041d8006a2001360200200041d0006a2019370200200041cc006a2004360200200041c8006a2007360200200041c6006a20083b0100200041c4006a200c3a00002000413c6a201e370200200041286a2011360200200041246a200f360200200041206a20133602002000411c6a2003360200200041186a2009360200200041146a200e360200200041106a20103602002000410c6a200d360200200041086a2006360200200041ec006a200241e00e6a41c401109d081a0c570b200910350b02402003450d002003410c6c2104200e210103400240200141046a280200450d00200128020010350b2001410c6a2101200441746a22040d000b0b20022802b40c2201450d002001410c6c450d00200e10350b200d450d070b200610350c060b0240200d450d00200610350b02402003450d002003410c6c2104200e210103400240200141046a280200450d00200128020010350b2001410c6a2101200441746a22040d000b0b2009450d052009410c6c0d040c050b0240200d450d00200610350b02402003450d002003410c6c2104200e210103400240200141046a280200450d00200128020010350b2001410c6a2101200441746a22040d000b0b2009450d042009410c6c0d030c040b0240200d450d00200610350b02402003450d002003410c6c2104200e210103400240200141046a280200450d00200128020010350b2001410c6a2101200441746a22040d000b0b2009450d032009410c6c0d020c030b200441ff0171450d00200241003a00f00c0b0240200d450d00200610350b02402003450d002003410c6c2104200e210103400240200141046a280200450d00200128020010350b2001410c6a2101200441746a22040d000b0b2009450d012009410c6c450d010b200e10350b2000411b3602000c4c0b02402006450d0020012003417e6a3602042001200441026a3602000b2000411b3602000c4b0b02402006450d0020012003417e6a3602042001200441026a3602000b2000411b3602000c4a0b02402006450d0020012003417e6a3602042001200441026a3602000b2000411b3602000c490b2006450d2a20042d0001210620012003417e6a22263602042001200441026a3602002006410a4b0d2a410421274200212402400240024002400240024002400240024002400240024020060e0b0001020b03040506070809000b41002105200241003a00800f2003417e6a21072003417d6a21030240034020072005460d01200241e00e6a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00800f2003417f6a21032006210520064120470d000b200241a80b6a41086a200241b00c6a41086a290000370300200241a80b6a41106a200241b00c6a41106a290000370300200241900b6a41086a20024190066a41086a290000370300200241900b6a41106a20024190066a41106a290000370300200220022900b00c3703a80b20022002290090063703900b200241ef0e6a290000210b200241ff0e6a310000210a20022800e30e210920022f00e10e212820022d00e00e212920022900e70e211720022900f70e2118200241f80a6a41106a20024180096a41106a290000370300200241f80a6a41086a20024180096a41086a29000037030020022002290080093703f80a200241e00a6a41106a20024180086a41106a290000370300200241e00a6a41086a20024180086a41086a29000037030020022002290080083703e00a2018422088200a42208684210a2017422088a72105200b422088a7210f200b4280feffff0f83420888a7212a2018a721142017a72108200ba7210c41012127410021100c0b0b200541ff0171450d35200241003a00800f0c350b200241a0056a200110c40120022802a0050d3420022802a4052206200728020041c8006e2204200420064b1bad42c8007e220a422088a70d17200aa72204417f4c0d170240024020040d00410421090c010b200410332209450d0c0b41002105200241003602c80b200220093602c00b2002200441c8006e22083602c40b0240024002402006450d00200241b00c6a410c6a2110410021050340200241b00c6a200110ad040240024020022d00b00c22034106470d00410621030c010b200241980c6a41086a220e201041086a290200370300200241980c6a41106a220c201041106a290200370300200220102902003703980c20022802b80c210420022802b40c210820022f01b20c210d20022d00b10c2114200241e00e6a200110ad04024020022d00e00e4106470d00024020034101470d002004450d00200810350b410621030c010b200241800c6a41106a200c290300370300200241800c6a41086a200e29030037030020024190066a41086a200241e00e6a41086a29030037030020024190066a41106a200241e00e6a41106a29030037030020024190066a41186a200241e00e6a41186a29030037030020024190066a41206a200241e00e6a41206a280200360200200220022903980c3703800c200220022903e00e37039006200d21112014211220042116200821150b200241e80b6a41086a2204200241800c6a41086a290300370300200241e80b6a41106a2208200241800c6a41106a29030037030020024180096a41086a220e20024190066a41086a29030037030020024180096a41106a220c20024190066a41106a29030037030020024180096a41186a220d20024190066a41186a29030037030020024180096a41206a221420024190066a41206a280200360200200220022903800c3703e80b20022002290390063703800920034106460d02200241d00b6a41106a22132008290300370300200241d00b6a41086a2208200429030037030020024180086a41086a220f200e29030037030020024180086a41106a220e200c29030037030020024180086a41186a220c200d29030037030020024180086a41206a220d2014280200360200200220022903e80b3703d00b2002200229038009370380080240200520022802c40b470d00200241c00b6a2005410110a80120022802c00b210920022802c80b21050b2009200541c8006c6a220420123a0001200420033a0000200441086a2016360000200441046a2015360000200441026a20113b00002004410c6a20022903d00b370000200441146a20082903003700002004411c6a2013290300370000200441246a2002290380083700002004412c6a200f290300370000200441346a200e2903003700002004413c6a200c290300370000200441c4006a200d2802003600002002200541016a22053602c80b2006417f6a22060d000b20022802c40b21080b20090d010c360b02402005450d002009200541c8006c6a2104200921010340024020012d00004101470d00200141086a280200450d00200141046a28020010350b0240200141246a2d00004101470d002001412c6a280200450d00200141286a28020010350b200141c8006a22012004470d000b0b20022802c40b2201450d35200141c8006c450d35200910350c350b200241e00e6a200110ad0402400240024002400240024002400240024020022d00e00e220c4106460d00200241800f6a280200210d200241f80e6a290300210b200241f40e6a2204280200210e200241ec0e6a2203290200210a200241e80e6a2206280200211420022802e40e210f20022f01e20e212720022d00e10e2128200241e00e6a200110ad0420022d00e00e22104106460d01200241fc0e6a2216290200211920042902002118200329020021172006280200211120022802e40e211320023301e20e212420023100e10e2125200241e00e6a200110ad0420022d00e00e22124106460d0220024180086a41086a200241f40e6a220429020037030020024180086a41106a20162902003703002002200241ec0e6a220329020037038008200241e00e6a41086a2206280200211620022802e40e211520022f01e20e212b20022d00e10e212c200241e00e6a200110ad0420022d00e00e22234106460d0320024180096a41086a200429020037030020024180096a41106a200241fc0e6a220429020037030020022003290200370380092006280200212d20022802e40e212e20022f01e20e212020022d00e10e212f200241e00e6a200110ad0420022d00e00e22304106460d0620024190066a41086a200241f40e6a290200370300200241a0066a20042902003703002002200241ec0e6a29020037039006200241e00e6a41086a280200212220022802e40e212120072802002204450d0720022f01e20e213120022d00e10e2132200128020022032d0000210620012004417f6a22073602042001200341016a360200200641014b0d074200211e410021334200211d20060e020504050b02402005450d002009200541c8006c6a2104200921010340024020012d00004101470d00200141086a280200450d00200141046a28020010350b0240200141246a2d00004101470d002001412c6a280200450d00200141286a28020010350b200141c8006a22012004470d000b0b2008450d3c200841c8006c450d3c200910350c3c0b0240200c4101470d002014450d00200f10350b02402005450d002009200541c8006c6a2104200921010340024020012d00004101470d00200141086a280200450d00200141046a28020010350b0240200141246a2d00004101470d002001412c6a280200450d00200141286a28020010350b200141c8006a22012004470d000b0b2008450d3b200841c8006c450d3b200910350c3b0b024020104101470d002011450d00201310350b0240200c4101470d002014450d00200f10350b02402005450d002009200541c8006c6a2104200921010340024020012d00004101470d00200141086a280200450d00200141046a28020010350b0240200141246a2d00004101470d002001412c6a280200450d00200141286a28020010350b200141c8006a22012004470d000b0b2008450d3a200841c8006c450d3a200910350c3a0b024020124101470d002016450d00201510350b024020104101470d002011450d00201310350b0240200c4101470d002014450d00200f10350b02402005450d002009200541c8006c6a2104200921010340024020012d00004101470d00200141086a280200450d00200141046a28020010350b0240200141246a2d00004101470d002001412c6a280200450d00200141286a28020010350b200141c8006a22012004470d000b0b2008450d39200841c8006c450d39200910350c390b2007450d0220032d0001213420012004417e6a22063602042001200341026a3602002006450d0220032d0002210720012004417d6a22063602042001200341036a3602002006450d0220032d0003213520012004417c6a22063602042001200341046a3602002006450d0220032d0004213620012004417b6a22063602042001200341056a3602002006450d0220032d0005213320012004417a6a22063602042001200341066a3602002006450d0220032d000621372001200441796a22063602042001200341076a3602002006450d0220032d000721382001200441786a22063602042001200341086a3602002006450d0220032d0008211f2001200441776a22063602042001200341096a3602002006450d0220032d000921392001200441766a220636020420012003410a6a3602002006450d0220032d000a213a2001200441756a220636020420012003410b6a3602002006450d0220032d000b21292001200441746a220636020420012003410c6a3602002006450d0220032d000c213b2001200441736a220636020420012003410d6a3602002006450d0220032d000d213c2001200441726a220636020420012003410e6a3602002006450d0220032d000e213d2001200441716a220636020420012003410f6a3602002006450d0220032d000f212a2001200441706a22063602042001200341106a3602002006450d0220032d0010213e20012004416f6a22063602042001200341116a3602002006450d0220032d0011212620012004416e6a22063602042001200341126a3602002006450d0220032d0012213f20012004416d6a22063602042001200341136a3602002006450d0220032d0013214020012004416c6a22063602042001200341146a3602002006450d022003310014211e20012004416b6a3602042001200341156a3602002002203641187420354110747220074108747222042034723602e00e2002203bad4238862029ad42ff018342308684203aad42ff0183422886842039ad42ff018342208684201fad42ff018342188684221d2038ad42ff0183421086842037ad42ff0183420886842033ad42ff0183843702e40e201d421888201e4238862040ad42ff018342308684203fad42ff0183422886842026ad42ff018342208684203ead42ff018342188684202aad42ff018342108684203dad42ff018342088684203cad42ff018384221d42288684211e20044108762135201d421888211d20022800e30e2136410121330b200241e00e6a200110ad0420022d00e00e22374106460d02200241b00c6a41086a2204200241f40e6a290200370300200241b00c6a41106a2203200241fc0e6a2902003703002002200241ec0e6a22062902003703b00c200241e00e6a41086a2207280200213820022802e40e211f20022f01e20e213a20022d00e10e2139200241e00e6a200110ad0420022d00e00e4106470d0b024020374101470d002038450d00201f10350b024020304101470d002022450d00202110350b024020234101470d00202d450d00202e10350b024020124101470d002016450d00201510350b024020104101470d002011450d00201310350b0240200c4101470d002014450d00200f10350b02402005450d002009200541c8006c6a2104200921010340024020012d00004101470d00200141086a280200450d00200141046a28020010350b0240200141246a2d00004101470d002001412c6a280200450d00200141286a28020010350b200141c8006a22012004470d000b0b2008450d37200841c8006c450d37200910350c370b024020234101470d00202d450d00202e10350b024020124101470d002016450d00201510350b024020104101470d002011450d00201310350b0240200c4101470d002014450d00200f10350b02402005450d002009200541c8006c6a2104200921010340024020012d00004101470d00200141086a280200450d00200141046a28020010350b0240200141246a2d00004101470d002001412c6a280200450d00200141286a28020010350b200141c8006a22012004470d000b0b2008450d36200841c8006c450d36200910350c360b024020304101470d002022450d00202110350b024020234101470d00202d450d00202e10350b024020124101470d002016450d00201510350b024020104101470d002011450d00201310350b0240200c4101470d002014450d00200f10350b02402005450d002009200541c8006c6a2104200921010340024020012d00004101470d00200141086a280200450d00200141046a28020010350b0240200141246a2d00004101470d002001412c6a280200450d00200141286a28020010350b200141c8006a22012004470d000b0b2008450d35200841c8006c450d35200910350c350b024020304101470d002022450d00202110350b024020234101470d00202d450d00202e10350b024020124101470d002016450d00201510350b024020104101470d002011450d00201310350b0240200c4101470d002014450d00200f10350b02402005450d002009200541c8006c6a2104200921010340024020012d00004101470d00200141086a280200450d00200141046a28020010350b0240200141246a2d00004101470d002001412c6a280200450d00200141286a28020010350b200141c8006a22012004470d000b0b2008450d34200841c8006c450d34200910350c340b200241a8056a200110c40120022802a8050d3320022802ac052215200728020041c4006e2204200420154b1bad42c4007e220a422088a70d16200aa72204417f4c0d160240024020040d00410421090c010b200410332209450d0b0b200241003602880c200220093602800c2002200441c4006e3602840c024002402015450d00200241e80b6a410172210c20024180096a41186a2123200241f40b6a212c4100210641002108034041002103200241003a00800f200841016a21082007280200417f6a210402400240024003402004417f460d01200241e00e6a20036a200128020022052d00003a0000200120043602042001200541016a3602002002200341016a22053a00800f2004417f6a21042005210320054120470d000b200220022800e30e3600c30b200220022802e00e3602c00b200241e00e6a410f6a2900002117200241e00e6a411f6a310000211b20022900e70e211820022900f70e211a200241e00e6a200110ad0420022d00e00e22034106470d01410621030c020b0240200341ff0171450d00200241003a00800f0b410621030c010b200241e80b6a41106a20174238883c0000202c20174218883e0200200220022d00c60b3a00e80b20022018a722043b00e90b200220044110763a00eb0b200220184218882017422886843702ec0b200241e00e6a41106a290300211e200241e00e6a41206a310000211c20022903e80e211920022903f80e211d20022801c20b210e20022d00c10b211420022d00c00b211320022d00e10e210f20022f01e20e211020022802e40e211120022d00810f211220022f01820f2116201a210a201b210b0b2023200b3c000020024180096a41086a2204200c41086a2900003703002002200a370390092002200c2900003703800920034106460d0220022d00e80b2105200e410876210d2004290300211720022903800921180240200620022802840c470d00200241800c6a20064101109f0120022802800c210920022802880c21060b2009200641c4006c6a220420163b0042200420123a00412004201d37003820042011360024200420103b00222004200f3a0021200420033a00202004200a37001720042005411874200d723600032004200e410874201441ff0171723b0001200420133a0000200441c0006a201c3c00002004411f6a200b3c00002004201937002820042018370007200441306a201e3700002004410f6a20173700002002200641016a22063602880c20082015470d000b0b2009450d3420022902840c210a200241a80b6a41106a200241b00c6a41106a290200370300200241a80b6a41086a200241b00c6a41086a290200370300200241900b6a41086a20024190066a41086a290300370300200241900b6a41106a20024190066a41106a290300370300200241f80a6a41086a20024180086a41086a290200370300200241f80a6a41106a20024180086a41106a290200370300200220022902b00c3703a80b20022002290390063703900b20022002290280083703f80a200241e00a6a41106a200241980c6a41106a290300370300200241e00a6a41086a200241980c6a41086a290300370300200220022903980c3703e00a200a422088a72105200aa7210841032127410021100c090b02402006450d00200641c4006c2104200941286a210103400240200141786a2d00004101470d002001280200450d002001417c6a28020010350b200141c4006a2101200441bc7f6a22040d000b0b20022802840c2201450d33200141c4006c450d33200910350c330b200241c8056a200110c40120022802c8050d3220022802cc052109200241b0056a200110f60120022903b005a70d32200241b0056a41106a290300210a20022903b805210b200241a80b6a41106a200241e00e6a41106a290200370300200241a80b6a41086a200241e00e6a41086a290200370300200241900b6a41086a200241b00c6a41086a290300370300200241900b6a41106a200241b00c6a41106a290300370300200241f80a6a41086a20024190066a41086a290200370300200241f80a6a41106a20024190066a41106a290200370300200220022902e00e3703a80b200220022903b00c3703900b20022002290290063703f80a200241e00a6a41106a20024180096a41106a290300370300200241e00a6a41086a20024180096a41086a29030037030020022002290380093703e00a200b422088a72105200a422088a7210f200a4280feffff0f83420888a7212a200ba72108200aa7210c41052127410021100c070b20264104490d312004280002210920012003417a6a360204410621272001200441066a360200200241a80b6a41086a200241e00e6a41086a290200370300200241a80b6a41106a200241e00e6a41106a290200370300200241900b6a41086a200241b00c6a41086a290300370300200241900b6a41106a200241b00c6a41106a290300370300200241f80a6a41086a20024190066a41086a290200370300200241f80a6a41106a20024190066a41106a290200370300200220022902e00e3703a80b200220022903b00c3703900b20022002290290063703f80a200241e00a6a41106a20024180096a41106a290300370300200241e00a6a41086a20024180096a41086a29030037030020022002290380093703e00a410021054100212a4100210c410021100c060b200241e8056a200110c40120022802e8050d3020022802ec052109200241d0056a200110f60120022903d005a70d30200241d0056a41106a290300210a20022903d805210b200241a80b6a41106a200241e00e6a41106a290200370300200241a80b6a41086a200241e00e6a41086a290200370300200241900b6a41086a200241b00c6a41086a290300370300200241900b6a41106a200241b00c6a41106a290300370300200241f80a6a41086a20024190066a41086a290200370300200241f80a6a41106a20024190066a41106a290200370300200220022902e00e3703a80b200220022903b00c3703900b20022002290290063703f80a200241e00a6a41106a20024180096a41106a290300370300200241e00a6a41086a20024180096a41086a29030037030020022002290380093703e00a200b422088a72105200a422088a7210f200a4280feffff0f83420888a7212a200ba72108200aa7210c41072127410021100c050b200241f0056a200110c40120022802f0050d2f20022802f405210e41002103200241003a00800f2007280200417f6a2104024003402004417f460d01200241e00e6a20036a200128020022052d00003a0000200120043602042001200541016a3602002002200341016a22053a00800f2004417f6a21042005210320054120470d000b41082127200241a80b6a41086a20024180096a41086a290200370300200241a80b6a41106a20024180096a41106a290200370300200241900b6a41086a200241980c6a41086a290300370300200241900b6a41106a200241980c6a41106a29030037030020022002290280093703a80b200220022903980c3703900b200241ef0e6a290000210b200241ff0e6a310000210a20022800e30e210920022f00e10e212820022d00e00e212920022900e70e211820022900f70e211920022802d40b211120022903d80b2117200241f80a6a41106a200241800c6a41106a290200370300200241f80a6a41086a200241800c6a41086a290200370300200220022902800c3703f80a200241e00a6a41106a200241e80b6a41106a290300370300200241e00a6a41086a200241e80b6a41086a290300370300200220022903e80b3703e00a2019422088200a42208684210a2018422088a72105200b422088a7210f200b4280feffff0f83420888a7212a200241c40c6a290200211d20022902bc0c211e20022802cc0c213e20022802b80c213620022f01b60c213520022d00b50c213420022d00b40c213320022802b00c213d2019a721142018a72108200ba7210c410021100c050b200341ff0171450d2f200241003a00800f0c2f0b200241f8056a200110c40120022802f8050d2e200728020022044108490d2e20022802fc05210920012802002203290000210a2001200441786a3602042001200341086a360200200a4280025a0d2e200241a80b6a41106a200241e00e6a41106a290200370300200241a80b6a41086a200241e00e6a41086a290200370300200241900b6a41086a200241b00c6a41086a290300370300200241900b6a41106a200241b00c6a41106a290300370300200241f80a6a41086a20024190066a41086a290200370300200241f80a6a41106a20024190066a41106a290200370300200220022902e00e3703a80b200220022903b00c3703900b20022002290290063703f80a200241e00a6a41106a20024180096a41106a290300370300200241e00a6a41086a20024180096a41086a29030037030020022002290380093703e00a200a422088a72105200aa7210841092127410021100c030b20024180066a200110c4012002280280060d2d2002280284062109200241e00e6a200110920620022d00e00e4102460d2d20072802002203450d2d200241e80e6a3502002118200241800f6a350200210b200241fc0e6a280200210e200241f40e6a290200210a200241f00e6a2802002114200241ec0e6a280200210f20022903e00e2119200128020022052d0000210420012003417f6a22063602042001200541016a360200200441064b0d2d42002117410021114100210d0240024002400240024002400240024020040e0707000501020304070b20064110490d34200541096a29000021172005290001211e20012003416f6a3602042001200541116a360200201e422088a72111201ea721134101210d0c060b4103210d0c040b4104210d0c030b4105210d0c020b4106210d0c010b4102210d0b0b200241a80b6a41106a200241980c6a41106a290200370300200241a80b6a41086a200241980c6a41086a290200370300200241900b6a41086a200241800c6a41086a290300370300200241900b6a41106a200241800c6a41106a290300370300200241f80a6a41086a200241e80b6a41086a290200370300200241f80a6a41106a200241e80b6a41106a290200370300200220022902980c3703a80b200220022903800c3703900b200220022902e80b3703f80a200241e00a6a41106a200241d00b6a41106a290300370300200241e00a6a41086a200241d00b6a41086a290300370300200220022903d00b3703e00a2019422088a7210520184280feffff0f83420888a7212a200241c40c6a290200211d20022802b80c213620022802cc0c213e20022902bc0c211e20022f01b60c213520022d00b50c213420022d00b40c21332019a721082018a7210c410a212741002110420021240c020b200241e00e6a200110920620022d00e00e4102460d2c200241d00b6a41086a200241fc0e6a280200360200200241a80b6a41086a20024180096a41086a290200370300200241a80b6a41106a20024180096a41106a2902003703002002200241e00e6a41146a29020022193703d00b20022002290280093703a80b200241800f6a280200210e200241ec0e6a290200210b20022802e00e210920022902e40e211820022802ec0b211120022903f00b211720022902d40b210a200241900b6a41106a20024180086a41106a290300370300200241900b6a41086a20024180086a41086a29030037030020022002290380083703900b200241f80a6a41106a200241980c6a41106a290200370300200241f80a6a41086a200241980c6a41086a290200370300200220022902980c3703f80a200241e00a6a41106a200241800c6a41106a290300370300200241e00a6a41086a200241800c6a41086a290300370300200220022903800c3703e00a2018422088a72105200b422088a7210f200b4280feffff0f83420888a7212a200241b00c6a41146a290200211d20022902bc0c211e20022802cc0c213e20022802b80c213620022f01b60c213520022d00b50c213420022d00b40c21332018a721082019a72114200ba7210c410b2127410021100c010b200241a80b6a41086a20024180086a41086a290300370300200241a80b6a41106a20024180086a41106a290300370300200241900b6a41086a20024180096a41086a290300370300200241900b6a41106a20024180096a41106a29030037030020022002290380083703a80b20022002290380093703900b200241f80e6a290300211a200241e00e6a41106a290300211b200241800f6a280200213d2006280200213c2007280200213b20022903e00e211c200241f80a6a41106a20024190066a41106a290300370300200241f80a6a41086a20024190066a41086a29030037030020022002290390063703f80a200241e00a6a41106a2003290300370300200241e00a6a41086a2004290300370300200220022903b00c3703e00a2027410874202841ff017172212a20244208862025842124410221270b200241c80a6a41106a2201200241a80b6a41106a290300370300200241c80a6a41086a2204200241a80b6a41086a290300370300200241b00a6a41086a2203200241900b6a41086a290300370300200241b00a6a41106a2206200241900b6a41106a290300370300200241980a6a41086a2207200241f80a6a41086a290300370300200241980a6a41106a2226200241f80a6a41106a290300370300200220022903a80b3703c80a200220022903900b3703b00a200220022903f80a3703980a200241800a6a41106a223f200241e00a6a41106a290300370300200241800a6a41086a2240200241e00a6a41086a290300370300200220022903e00a3703800a200041d8006a2019370200200041d0006a2018370200200041186a202a410874ad200cad42ff0183843e0200200041106a2005ad4220862008ad84370200200041e8006a2016360200200041e4006a20153602002000202b3b00622000202c3a0061200041e0006a20123a0000200041c8006a2017370200200041c4006a2011360200200041c0006a2013360200200041386a20244228862010ad42ff018342208684200dad84370200200041306a200b3702002000412c6a200e360200200041246a200a370200200041206a20143602002000411c6a200f3602002000410c6a2009360200200020283b000a200020293a0009200041086a20273a00002000411736020020004188016a202e3602002000418c016a202d360200200020203b0086012000202f3a00850120004184016a20233a0000200041a8016a20303a0000200020323a00a901200020313b00aa01200041b0016a2022360200200041ac016a2021360200200041fc006a2001290300370200200041f4006a2004290300370200200041ec006a20022903c80a37020020004190016a20022903b00a37020020004198016a2003290300370200200041a0016a2006290300370200200041cc016a20373a0000200020393a00cd012000203a3b00ce01200041d4016a2038360200200041d0016a201f360200200041a4026a201d3700002000419c026a201e37000020004188026a201a37020020004180026a201b37020020004194026a20333a0000200020343a009502200020353b009602200041ac026a203e36020020004198026a203636000020004190026a203d360200200041fc016a203c360200200041f8016a203b360200200041f0016a201c370200200041c4016a2026290300370200200041bc016a2007290300370200200041b4016a20022903980a370200200041d8016a20022903800a370200200041e0016a2040290300370200200041e8016a203f2903003702000c480b2006450d0720042d0001210520012003417e6a22123602042001200441026a3602002005410b4b0d074107210d4200211d4100211141002106024002400240024002400240024020050e0c0001020304052f0608090a0b000b20124110490d0d2004410a6a29000021172004290002210b20012003416e6a3602042001200441126a3602004101210d4200211e410021064200211d0c2e0b20124104490d0c2004280002210c20012003417a6a3602042001200441066a3602004102210d0c2c0b41002105200241003a00d00c2003417e6a2109417d21060240034020092005460d01200241b00c6a20056a200420056a220741026a2d00003a00002001200320066a3602042001200741036a3602002002200541016a22073a00d00c2006417f6a21062007210520074120470d000b200220022800b30c3600c30b200220022802b00c22083602c00b200320076b2203417e6a4110490d0c200241bf0c6a2900002117200241cf0c6a310000211c20022900b70c210b20022900c70c210a20022f00c10b211420022800c30b210c200420076a2204410e6a2800002113200441066a290000211d200441026a280000210620012003416e6a22053602042001200441126a220736020020054110490d0c2004411a6a29000021192007290000211820012003415e6a3602042001200441226a360200201d421088211e20064180807c712111201ca741ff017121104103210d0c2d0b200541ff0171450d0b200241003a00d00c0c0b0b4104210d20124104490d0a2004280002210c20012003417a6a3602042001200441066a3602000c2a0b200241b00c6a200110920620022d00b00c4102460d0920072802002203450d09200241bc0c6a2902002117200241d00c6a280200210e200241ce0c6a2f0100210f200241cd0c6a2d00002109200241cc0c6a2d00002110200241c40c6a290200210a20022902b40c210b20022802b00c210c200128020022052d0000210420012003417f6a3602042001200541016a360200200441014b0d09410021080240024020040e020100010b410121080b20023502900620023301940642208684211e200241a2066a2901002119200229019a06211820022801960621134105210d41002111410021060c2a0b2012450d0820042d0002210520012003417d6a3602042001200441036a360200200541014b0d084106210d410021114200211e410021064200211d4100210820050e022906290b41002105200241003a00d00c2003417e6a2108417d2106024002400240034020082005460d01200241b00c6a20056a200420056a220941026a2d00003a00002001200320066a3602042001200941036a3602002002200541016a22093a00d00c2006417f6a21062009210520094120470d000b20024198086a200241cf0c6a31000022183c0000200220022800b30c3600c30b200220022802b00c22083602c00b200220022900c70c220a37039008200220022900b70c220b370380082002200241bf0c6a290000221737038808200320096b2203417e6a4104490d0a200241c50b6a2d0000210520022f00c30b210c20022d00c10b211420022d00c20b211320022d00c60b210d200420096a220441026a280000210e20012003417a6a3602042001200441066a36020020024188066a200110c4012002280288060d0a2007280200200228028c062204490d0a2004417f4c0d0f20040d0142002119410121060c020b200541ff0171450d09200241003a00d00c0c090b200410392206450d0120072802002004490d07200620012802002004109d081a200128020422032004490d262001200320046b3602042001200128020020046a3602002004ad21190b2006450d07200d411874200c20054110747241ffffff077172210c20192004ad42208684221d421088211e20064180807c7121114108210d201341087420147221142018a741ff017121100c280b1045000b4109210d410021060c260b41002105200241003a00d00c2003417e6a21092003417d6a2106024002400240034020092005460d01200241b00c6a20056a200420056a220741026a2d00003a0000200120063602042001200741036a3602002002200541016a22073a00d00c2006417f6a21062007210520074120470d000b200220022800b30c3600c30b200220022802b00c22083602c00b2003417e6a2007460d07200241bf0c6a2900002117200241cf0c6a310000211820022900b70c210b20022900c70c210a20022f00c10b211420022800c30b210c200420076a220341026a2d00002104200120063602042001200341036a360200200441014b0d074100210920040e020201020b200541ff0171450d06200241003a00d00c0c060b410121090b2018a741ff01712110410a210d0c230b41002105200241003a00d00c2003417e6a21092003417d6a21060240034020092005460d01200241b00c6a20056a200420056a220741026a2d00003a0000200120063602042001200741036a3602002002200541016a22073a00d00c2006417f6a21062007210520074120470d000b200241e80b6a41106a200241bf0c6a290000220a4238883c0000200241f40b6a200a4218883e0200200220022800b30c3600c30b200220022802b00c22083602c00b200220022d00c60b3a00e80b200220022900b70c220ba722053b00e90b200220054110763a00eb0b2002200b421888200a422886843702ec0b2003417e6a2007460d04200241cf0c6a310000210b20022900c70c210a20022d00c10b210520022801c20b2103200420076a220441026a2d00002109200120063602042001200441036a360200200941034f0d0420022d00e80b411874200341087672210c20034108742005722114200ba741ff01712110200241e80b6a410172220141086a29000021172001290000210b410b210d0c230b200541ff0171450d03200241003a00d00c0c030b20124104490d022004280002210c20012003417a6a3602042001200441066a360200410c210d0c220b410121084200211e41002111410021064200211d0c220b200610350b2000411b3602000c3f0b200241b00c6a2001109506024020022d00b00c410a460d0020024190066a200241b00c6a41c400109d081a20004119360200200041046a20024190066a41c400109d081a200041c8006a200241e00e6a41e801109d081a0c3f0b2000411b3602000c3e0b02402006450d0020042d0001210520012003417e6a3602042001200441026a360200200541024b0d004101210402400240024020050e03020001020b200241b00c6a20011092064102210420022d00b00c4102460d02200241c40c6a2902002117200241bc0c6a290200210b200241cc0c6a290200210a200241b80c6a280200210320022802b40c210620022802b00c21090c010b200241b00c6a200110920620022d00b00c4102460d01200728020022054110490d01200241c40c6a2902002117200241bc0c6a290200210b200241cc0c6a290200210a200241b00c6a41086a280200210320022802b40c210620022802b00c21092001280200220441086a2900002119200429000021182001200441106a3602002001200541706a220736020420074110490d01200441186a290000211d2004290010211e2001200541606a22073602042001200441206a36020020074104490d012004280020210820012005415c6a3602042001200441246a360200410321040b2000411a360200200041c8006a201d370200200041c0006a201e370200200041386a2019370200200041306a2018370200200041206a2017370200200041186a200b370200200041d0006a2008360200200041286a200a370200200041146a2003360200200041106a20063602002000410c6a2009360200200041086a2004360200200041d8006a200241e00e6a41d801109d081a0c3e0b2000411b3602000c3d0b02402006450d0020012003417e6a3602042001200441026a3602000b2000411b3602000c3c0b2000411b3602000c3b0b1044000b2004200341a4f0cb001059000b2004200341a4f0cb001059000b2004200341a4f0cb001059000b2004200341a4f0cb001059000b2003200d41a4f0cb001059000b2004200841a4f0cb001059000b2004200341a4f0cb001059000b2004200341a4f0cb001059000b200810350c260b2004200341a4f0cb001059000b2004200341a4f0cb001059000b2003200541a4f0cb001059000b200410350b2000411b3602000c2c0b2004200341a4f0cb001059000b2004200341a4f0cb001059000b2004200541a4f0cb001059000b2006200341a4f0cb001059000b2005200341a4f0cb001059000b2004200341a4f0cb001059000b2003200741a4f0cb001059000b200c200541a4f0cb001059000b2004200341a4f0cb001059000b2004200c41a4f0cb001059000b2004200341a4f0cb001059000b4200211e41002111410021064200211d0c010b4200211e410021064200211d0b2000200f3b012a200020093a0029200020143b010a200020083a000920004118360200200041c8006a2019370200200041c0006a2018370200200041186a2017370200200041106a200b3702002000413c6a20133602002000412c6a200e360200200041286a20103a0000200041206a200a3702002000410c6a200c360200200041086a200d3a0000200041346a201e421086201d42ffff038384370200200041306a2011200641ffff037172360200200041d0006a200241e00e6a41e001109d081a0c1e0b2000411b3602000c1d0b200410350b2000411b3602000c1b0b4100210c420021180b200241800c6a41106a200241980c6a41106a2903002219370300200241800c6a41086a200241980c6a41086a290300221e370300200220022903980c221d3703800c200041286a20173c0000200041206a200b370200200041186a2018421886200a42288884370200200041106a200a4218862008ad42ffffff0783843702002000412c6a20043602002000412a6a20073b0100200020093a00292000410c6a2001411874200341ffffff0771723602002000200c410874200641ff0171723b000a200020053a0009200041086a200e3a000020004110360200200041306a201d370200200041386a201e370200200041c0006a2019370200200041c8006a200241e00e6a41e801109d081a0c190b0b4200211c4200211b4200211a4200210b42002124420021250b200020143b00462000200d3a00452000200f3b0026200020103a0025200020083a0005200020063a00042000410d360200200041246a200a4220883c0000200041206a200a3e0000200041c4006a201d3c00002000413c6a201e370000200041146a20183700002000410c6a2017370000200041286a20133600002000411c6a2011360000200041086a200c411874200741ffffff07717236000020002009410874200e41ff0171723b00062000412c6a200b200b84201b84201984370000200041346a2025202484201a84201c84370000200041c8006a200241e00e6a41e801109d081a0c160b2000411b3602000c150b4100210e0b0b200020153b012a2000200c3a00292000200f3b011a200020123a0019200020063a000920004109360200200041286a200a4220883c0000200041246a200a3e0200200041386a2018370200200041306a20173702002000412c6a2014360200200041206a20103602002000411c6a2011360200200041186a20163a0000200041106a200b370200200041086a20133a00002000410c6a200d411874200941ffffff0771723602002000200e410874200841ff0171723b000a200041c0006a200241e00e6a41f001109d081a0c120b4100210802402004450d00200910350b41022109410021060b41000d052009450d05200241e00e6a200110f80102400240024020022802e00e450d00200241b00c6a200241e00e6a41c001109d081a200728020022034110490d012001280200220441086a290000211e200429000021192001200441106a3602002001200341706a220536020420054110490d01200441186a290000211c2004290010211d2001200341606a22053602042001200441206a36020020054110490d01200441286a290000211a2004290020211b2001200341506a22053602042001200441306a36020020054104490d022004280030211320012003414c6a3602042001200441346a360200200241a80b6a41086a200241ec0c6a290200370300200241a80b6a41106a200241f40c6a2902003703002002200241b00c6a41346a2902003703a80b200241b00c6a41106a310000210b200241d00c6a2903002118200241c40c6a280200210f200241b00c6a41286a2d00002110200241dc0c6a280200211120022903b80c210a20022903c80c211720022802b00c210c20022802b40c211420022d00c10c212120022f01c20c212020022d00d90c213220022f01da0c213120022802e00c2112200241900b6a41086a200241900d6a290300370300200241900b6a41106a200241980d6a290300370300200241f80a6a41086a200241b40d6a290200370300200241f80a6a41106a200241bc0d6a2902003703002002200241880d6a2903003703900b2002200241ac0d6a2902003703f80a200241800d6a2802002115200241fc0c6a2d00002116200241a40d6a280200212b200241a00d6a2d0000212c20022802840d212320022f01fe0c213520022d00fd0c213420022802a80d212d20022f01a20d213320022d00a10d2136200241e00a6a41106a200241e00d6a290300370300200241e00a6a41086a200241d80d6a2903003703002002200241d00d6a2903003703e00a200241c80d6a2802002130200241c40d6a2d0000212e200241e80d6a290300212420022802cc0d212f20022f01c60d213820022d00c50d21374118210d0c0a0b20080d040c070b200241b00c6a10fa01200841808080807872418080808078470d030c060b200241b00c6a10fa012008450d050c020b4100210802402004450d00200910350b41022109410021060b41000d032009450d03200241e00e6a200110f80102400240024020022802e00e450d00200241b00c6a200241e00e6a41c001109d081a200728020022034110490d012001280200220441086a290000211e200429000021192001200441106a3602002001200341706a220536020420054110490d01200441186a290000211c2004290010211d2001200341606a22053602042001200441206a36020020054110490d01200441286a290000211a2004290020211b2001200341506a22053602042001200441306a36020020054104490d022004280030211320012003414c6a3602042001200441346a360200200241a80b6a41086a200241ec0c6a290200370300200241a80b6a41106a200241f40c6a2902003703002002200241b00c6a41346a2902003703a80b200241b00c6a41106a310000210b200241d00c6a2903002118200241c40c6a280200210f200241b00c6a41286a2d00002110200241dc0c6a280200211120022903b80c210a20022903c80c211720022802b00c210c20022802b40c211420022d00c10c212120022f01c20c212020022d00d90c213220022f01da0c213120022802e00c2112200241900b6a41086a200241900d6a290300370300200241900b6a41106a200241980d6a290300370300200241f80a6a41086a200241b40d6a290200370300200241f80a6a41106a200241bc0d6a2902003703002002200241880d6a2903003703900b2002200241ac0d6a2902003703f80a200241800d6a2802002115200241fc0c6a2d00002116200241a40d6a280200212b200241a00d6a2d0000212c20022802840d212320022f01fe0c213520022d00fd0c213420022802a80d212d20022f01a20d213320022d00a10d2136200241e00a6a41106a200241e00d6a290300370300200241e00a6a41086a200241d80d6a2903003703002002200241d00d6a2903003703e00a200241c80d6a2802002130200241c40d6a2d0000212e200241e80d6a290300212420022802cc0d212f20022f01c60d213820022d00c50d21374117210d0c080b20080d020c050b200241b00c6a10fa01200841808080807872418080808078470d010c040b200241b00c6a10fa012008450d030b200910350c020b4100210602402001450d00200810350b410421084100210c0b41000d002008450d004110210d200241a80b6a41106a200241e00e6a41106a290200370300200241a80b6a41086a200241e00e6a41086a290200370300200241900b6a41086a200241b00c6a41086a290200370300200241900b6a41106a200241b00c6a41106a290200370300200241f80a6a41086a20024180096a41086a290200370300200241f80a6a41106a20024180096a41106a290200370300200220022902e00e3703a80b200220022902b00c3703900b20022002290280093703f80a200241e00a6a41106a20024180086a41106a290200370300200241e00a6a41086a20024180086a41086a29020037030020022002290280083703e00a0c020b2000411b3602000c0a0b410021144100210c410021060b200241c80a6a41106a2201200241a80b6a41106a290300370300200241c80a6a41086a2204200241a80b6a41086a290300370300200241b00a6a41086a2203200241900b6a41086a290300370300200241b00a6a41106a2205200241900b6a41106a290300370300200241980a6a41086a2207200241f80a6a41086a290300370300200241980a6a41106a221f200241f80a6a41106a290300370300200220022903a80b3703c80a200220022903900b3703b00a200220022903f80a3703980a200241800a6a41106a2239200241e00a6a41106a290300370300200241800a6a41086a223a200241e00a6a41086a290300370300200220022903e00a3703800a200041386a2018370200200041306a2017370200200041286a200b3c0000200041206a200a370200200041186a2014ad422086200cad84370200200041106a2006ad4220862008ad84370200200041c8006a2012360200200041c4006a2011360200200020313b0042200020323a0041200041c0006a20103a00002000412c6a200f360200200020203b012a200020213a00292000410c6a2009360200200020223b010a2000200e3a0009200041086a200d3a000020004107360200200041e8006a2015360200200041ec006a2023360200200020353b0066200020343a0065200041e4006a20163a0000200041cc006a20022903c80a370200200041d4006a2004290300370200200041dc006a20012903003702002000418c016a202b36020020004190016a202d360200200020333b008a01200020363a00890120004188016a202c3a0000200041f0006a20022903b00a370200200041f8006a200329030037020020004180016a2005290300370200200041a4016a201f2903003702002000419c016a200729030037020020004194016a20022903980a370200200041b4016a202f360200200041b0016a2030360200200020383b00ae01200020373a00ad01200041ac016a202e3a0000200041c8016a2039290300370200200041c0016a203a290300370200200041b8016a20022903800a37020020004188026a201a37020020004180026a201b370200200041f8016a201c370200200041f0016a201d370200200041e8016a201e370200200041e0016a2019370200200041d8016a2013360200200041d0016a2024370200200041a8026a20024190066a41186a290300370300200041a0026a20024190066a41106a29030037030020004198026a20024190066a41086a29030037030020004190026a2002290390063703000c080b20004106360200200041e0006a201c370200200041d8006a201d370200200041c8006a201a370200200041c0006a201b370200200041386a2018370200200041306a2019370200200041206a200a370200200041186a200b370200200041d0006a201e370200200041286a2017370200200041146a2004360200200041106a20033602002000410c6a2005360200200041086a2001360200200041e8006a200241e00e6a41c801109d081a0c070b410021014200210b410021034100210e0b200041003a0025200020043b0023200020083b0006200020053a0005200020063a0004200041053602002000411b6a200b370000200041136a200a370000200041286a200e360200200041266a41003b01002000410f6a20013600002000410d6a20033b00002000410c6a20073a0000200041086a20093602002000412c6a200241e00e6a418402109d081a0c050b200410350b2000411b3602000c030b103c000b200610350b2000411b3602000b20024190116a24000b9d1401037f02402000280200220141194b0d0002400240024002400240024002400240024002400240024002400240024002400240024020010e1a0001121202121203040506070809120a0b0c0d0e1212120f1011000b200041086a280200417e6a220141074b0d1102400240024002400240024020010e080017010217030405000b200041106a280200450d162000410c6a28020010350f0b200041106a280200450d152000410c6a28020010350f0b200041106a280200450d142000410c6a28020010350f0b0240200041146a2802002202450d002000410c6a2802002101200241186c210203400240200141046a280200450d00200128020010350b0240200141106a280200450d002001410c6a28020010350b200141186a2101200241686a22020d000b0b200041106a2802002201450d13200141186c450d13200028020c10350f0b0240200041146a2802002202450d002000410c6a28020021012002410c6c210203400240200141046a280200450d00200128020010350b2001410c6a2101200241746a22020d000b0b200041106a2802002201450d122001410c6c450d12200028020c10350f0b200041106a280200450d112000410c6a28020010350f0b024020002d0004220141044b0d00024002400240024020010e051500010203150b0240200041106a2802002202450d00200041086a2802002101200241b0026c21020340200110bb02200141b0026a2101200241d07d6a22020d000b0b2000410c6a2802002201450d14200141b0026c450d14200028020810350f0b200041086a220128020010ba02200128020010350f0b02402000410c6a28020041ffffff3f71450d00200041086a28020010350b200041206a220128020010ba02200128020010350f0b2000412c6a28020041ffffff3f71450d11200041286a28020010350f0b2000412c6a28020041ffffff3f71450d10200041286a28020010350f0b02402000410c6a2802002201450d00200141f0006c2102200028020441046a21010340200110b1030240200141046a2802002203450d00200341246c450d00200128020010350b200141f0006a2101200241907f6a22020d000b0b200041086a2802002201450d0f200141f0006c450d0f200028020410350f0b0240200041086a2d0000220141174b0d000240024002400240024020010e18141414141414001414141414140114140203141414141404140b200041106a2802002201450d13200141246c450d132000410c6a28020010350f0b200041106a28020041ffffff3f71450d122000410c6a28020010350f0b200041146a28020041ffffffff0371450d11200041106a28020010350f0b200041146a2802002201450d10200141246c450d10200041106a28020010350f0b0240200041106a28020041808080807872418080808078460d002000410c6a28020010350b200041186a10fa010f0b0240200041106a28020041808080807872418080808078460d002000410c6a28020010350b200041186a10fa010f0b20002802042201450d0d200041086a280200450d0d200110350f0b200041086a2d0000416d6a220141014b0d0c0240024020010e020001000b200041106a280200450d0d2000410c6a28020010350f0b200041106a280200450d0c2000410c6a28020010350f0b20002d0004417f6a220141024b0d0b02400240024020010e03000102000b2000412c6a28020041ffffff3f71450d0d200041286a28020010350f0b200041086a220128020010ba02200128020010350f0b2000410c6a220128020010ba02200128020010350f0b20002d0004417f6a220141024b0d0a02400240024020010e03000102000b2000412c6a28020041ffffff3f71450d0c200041286a28020010350f0b200041086a220128020010ba02200128020010350f0b2000410c6a220128020010ba02200128020010350f0b200041086a2802004101470d09200041106a28020041ffffff3f71450d092000410c6a28020010350f0b20002d00044104470d082000410c6a28020041ffffff3f71450d08200041086a28020010350f0b200041086a280200450d07200028020410350f0b200041086a2d0000417c6a220141024b0d060240024020010e03000801000b200041306a280200450d072000412c6a28020010350f0b200041306a280200450d062000412c6a28020010350f0b200041086a2d0000417e6a220141024b0d0502400240024020010e03000102000b200041106a280200450d072000410c6a28020010350c070b200041346a280200450d06200041306a28020010350f0b200041306a280200450d052000412c6a28020010350f0b02402000280204220141024b0d00024020010e03060006060b200041086a220128020010ba02200128020010350f0b2000412c6a220128020010ba02200128020010350f0b02402000410c6a280200450d00200041086a28020010350b02402000411c6a2802002202450d00200041146a28020021012002410c6c210203400240200141046a280200450d00200128020010350b2001410c6a2101200241746a22020d000b0b200041186a2802002201450d032001410c6c450d03200028021410350f0b200041086a2d0000417e6a220141014b0d020240024020010e020001000b0240200041146a2802002202450d002000410c6a2802002201200241c8006c6a21020340024020012d00004101470d00200141086a280200450d00200141046a28020010350b0240200141246a2d00004101470d002001412c6a280200450d00200141286a28020010350b200141c8006a22012002470d000b0b0240200041106a2802002201450d00200141c8006c450d00200028020c10350b0240200041186a2d00004101470d00200041206a280200450d002000411c6a28020010350b02402000413c6a2d00004101470d00200041c4006a280200450d00200041c0006a28020010350b0240200041e0006a2d00004101470d00200041e8006a280200450d00200041e4006a28020010350b024020004184016a2d00004101470d002000418c016a280200450d0020004188016a28020010350b0240200041a8016a2d00004101470d00200041b0016a280200450d00200041ac016a28020010350b0240200041cc016a2d00004101470d00200041d4016a280200450d00200041d0016a28020010350b200041f0016a2d00004101470d03200041f8016a280200450d03200041f4016a28020010350f0b0240200041146a2802002201450d00200141c4006c21022000410c6a28020041286a210103400240200141786a2d00004101470d002001280200450d002001417c6a28020010350b200141c4006a2101200241bc7f6a22020d000b0b200041106a2802002201450d02200141c4006c450d02200028020c10350f0b200041086a2d00004108470d01200041346a280200450d01200041306a28020010350f0b20002d0004417f6a220141024b0d000240024020010e03000201000b200041286a220128020010ba02200128020010350f0b2000410c6a28020041ffffff3f71450d00200041086a28020010350f0b0b9d1401037f02402000280200220141194b0d0002400240024002400240024002400240024002400240024002400240024002400240024020010e1a0001121202121203040506070809120a0b0c0d0e1212120f1011000b200041086a280200417e6a220141074b0d1102400240024002400240024020010e080017010217030405000b200041106a280200450d162000410c6a28020010350f0b200041106a280200450d152000410c6a28020010350f0b200041106a280200450d142000410c6a28020010350f0b0240200041146a2802002202450d002000410c6a2802002101200241186c210203400240200141046a280200450d00200128020010350b0240200141106a280200450d002001410c6a28020010350b200141186a2101200241686a22020d000b0b200041106a2802002201450d13200141186c450d13200028020c10350f0b0240200041146a2802002202450d002000410c6a28020021012002410c6c210203400240200141046a280200450d00200128020010350b2001410c6a2101200241746a22020d000b0b200041106a2802002201450d122001410c6c450d12200028020c10350f0b200041106a280200450d112000410c6a28020010350f0b024020002d0004220141044b0d00024002400240024020010e051500010203150b0240200041106a2802002202450d00200041086a2802002101200241b0026c21020340200110bb02200141b0026a2101200241d07d6a22020d000b0b2000410c6a2802002201450d14200141b0026c450d14200028020810350f0b200041086a220128020010bb02200128020010350f0b02402000410c6a28020041ffffff3f71450d00200041086a28020010350b200041206a220128020010bb02200128020010350f0b2000412c6a28020041ffffff3f71450d11200041286a28020010350f0b2000412c6a28020041ffffff3f71450d10200041286a28020010350f0b02402000410c6a2802002201450d00200141f0006c2102200028020441046a21010340200110b1030240200141046a2802002203450d00200341246c450d00200128020010350b200141f0006a2101200241907f6a22020d000b0b200041086a2802002201450d0f200141f0006c450d0f200028020410350f0b0240200041086a2d0000220141174b0d000240024002400240024020010e18141414141414001414141414140114140203141414141404140b200041106a2802002201450d13200141246c450d132000410c6a28020010350f0b200041106a28020041ffffff3f71450d122000410c6a28020010350f0b200041146a28020041ffffffff0371450d11200041106a28020010350f0b200041146a2802002201450d10200141246c450d10200041106a28020010350f0b0240200041106a28020041808080807872418080808078460d002000410c6a28020010350b200041186a10fa010f0b0240200041106a28020041808080807872418080808078460d002000410c6a28020010350b200041186a10fa010f0b20002802042201450d0d200041086a280200450d0d200110350f0b200041086a2d0000416d6a220141014b0d0c0240024020010e020001000b200041106a280200450d0d2000410c6a28020010350f0b200041106a280200450d0c2000410c6a28020010350f0b20002d0004417f6a220141024b0d0b02400240024020010e03000102000b2000412c6a28020041ffffff3f71450d0d200041286a28020010350f0b200041086a220128020010bb02200128020010350f0b2000410c6a220128020010bb02200128020010350f0b20002d0004417f6a220141024b0d0a02400240024020010e03000102000b2000412c6a28020041ffffff3f71450d0c200041286a28020010350f0b200041086a220128020010bb02200128020010350f0b2000410c6a220128020010bb02200128020010350f0b200041086a2802004101470d09200041106a28020041ffffff3f71450d092000410c6a28020010350f0b20002d00044104470d082000410c6a28020041ffffff3f71450d08200041086a28020010350f0b200041086a280200450d07200028020410350f0b200041086a2d0000417c6a220141024b0d060240024020010e03000801000b200041306a280200450d072000412c6a28020010350f0b200041306a280200450d062000412c6a28020010350f0b200041086a2d0000417e6a220141024b0d0502400240024020010e03000102000b200041106a280200450d072000410c6a28020010350c070b200041346a280200450d06200041306a28020010350f0b200041306a280200450d052000412c6a28020010350f0b02402000280204220141024b0d00024020010e03060006060b200041086a220128020010bb02200128020010350f0b2000412c6a220128020010bb02200128020010350f0b02402000410c6a280200450d00200041086a28020010350b02402000411c6a2802002202450d00200041146a28020021012002410c6c210203400240200141046a280200450d00200128020010350b2001410c6a2101200241746a22020d000b0b200041186a2802002201450d032001410c6c450d03200028021410350f0b200041086a2d0000417e6a220141014b0d020240024020010e020001000b0240200041146a2802002202450d002000410c6a2802002201200241c8006c6a21020340024020012d00004101470d00200141086a280200450d00200141046a28020010350b0240200141246a2d00004101470d002001412c6a280200450d00200141286a28020010350b200141c8006a22012002470d000b0b0240200041106a2802002201450d00200141c8006c450d00200028020c10350b0240200041186a2d00004101470d00200041206a280200450d002000411c6a28020010350b02402000413c6a2d00004101470d00200041c4006a280200450d00200041c0006a28020010350b0240200041e0006a2d00004101470d00200041e8006a280200450d00200041e4006a28020010350b024020004184016a2d00004101470d002000418c016a280200450d0020004188016a28020010350b0240200041a8016a2d00004101470d00200041b0016a280200450d00200041ac016a28020010350b0240200041cc016a2d00004101470d00200041d4016a280200450d00200041d0016a28020010350b200041f0016a2d00004101470d03200041f8016a280200450d03200041f4016a28020010350f0b0240200041146a2802002201450d00200141c4006c21022000410c6a28020041286a210103400240200141786a2d00004101470d002001280200450d002001417c6a28020010350b200141c4006a2101200241bc7f6a22020d000b0b200041106a2802002201450d02200141c4006c450d02200028020c10350f0b200041086a2d00004108470d01200041346a280200450d01200041306a28020010350f0b20002d0004417f6a220141024b0d000240024020010e03000201000b200041286a220128020010bb02200128020010350f0b2000410c6a28020041ffffff3f71450d00200041086a28020010350f0b0bad0204017f017e017f027e230041d0006b220224002002412036020420022001360200200241086a2001ad4280808080800484100510c20102400240200228020822010d00420021030c010b200228020c210402400240200241086a41086a2802004110490d00200141086a290000210520012900002106420121030c010b20024100360220200242013703182002410936022c200220023602282002200241186a360234200241cc006a41013602002002420137023c200241c888c2003602382002200241286a360248200241346a41e88ac500200241386a10431a200235022042208620023502188410060240200228021c450d00200228021810350b420021030b2004450d00200110350b2000200637030820002003370300200041106a2005370300200241d0006a24000b950201047f230041d0006b220124002001412036020420012000360200200141086a2000ad4280808080800484100510c20102400240200128020822020d00410221000c010b200128020c210302400240200141106a280200450d0020022d0000220441014b0d0041002100024020040e020200020b410121000c010b20014100360220200142013703182001410936022c200120013602282001200141186a360234200141cc006a41013602002001420137023c200141c888c2003602382001200141286a360248200141346a41e88ac500200141386a10431a200135022042208620013502188410060240200128021c450d00200128021810350b410221000b2003450d00200210350b200141d0006a240020000bad0e04057f017e107f047e230041a0036b220224002002412036021420022001360210200241186a2001ad4280808080800484100510c2010240024002400240200228021822030d00200041003602000c010b200228021c21042002200241206a28020036022c20022003360228200241086a200241286a10c40102400240024020022802080d00200228020c2205200228022c220641e8006e2201200120054b1bad42e8007e2207422088a70d052007a72201417f4c0d050240024020010d00410821080c010b200110332208450d050b20024100360238200220083602302002200141e8006e36023402402005450d00200241e8026a41017221094100210a4100210b034041002101200241003a008803200b41016a210b0240024002400240034020062001460d01200241e8026a20016a2002280228220c2d00003a00002002200c41016a3602282002200141016a220c3a008803200c2101200c4120470d000b20024190026a41086a2201200241e8026a41086a220d29030037030020024190026a41106a220e200241e8026a41106a220f29030037030020024190026a41186a2210200241e8026a41186a2211290300370300200220022903e8023703900220022006200c6b36022c200241e8026a200241286a10bf0220022d00e802220c4102470d010c020b2002410036022c200141ff0171450d01200241003a0088034102210c0c020b200241b0026a412f6a22062009412f6a290000370000200241b0026a41286a2212200941286a290000370300200241b0026a41206a2213200941206a290000370300200241b0026a41186a2214200941186a290000370300200241b0026a41106a2215200941106a290000370300200241b0026a41086a2216200941086a290000370300200220092900003703b002200228022c22174110490d00200241f0016a41086a2001290300370300200241f0016a41106a200e290300370300200241f0016a41186a2010290300370300200d2016290300370300200f201529030037030020112014290300370300200241e8026a41206a2013290300370300200241e8026a41286a2012290300370300200241e8026a412f6a200629000037000020022002290390023703f001200220022903b0023703e8022002201741706a36022c20022002280228220141106a360228200141086a2900002118200129000021190c010b4102210c0b200241b8016a412f6a2201200241e8026a412f6a290000370000200241b8016a41286a2206200241e8026a41286a290300370300200241b8016a41206a220d200241e8026a41206a290300370300200241b8016a41186a220e200241e8026a41186a290300370300200241b8016a41106a220f200241e8026a41106a290300370300200241b8016a41086a2210200241e8026a41086a29030037030020024198016a41086a2211200241f0016a41086a29030037030020024198016a41106a2212200241f0016a41106a29030037030020024198016a41186a2213200241f0016a41186a290300370300200220022903e8023703b801200220022903f001370398010240200c4102460d00200241e0006a412f6a22142001290000370000200241e0006a41286a22152006290300370300200241e0006a41206a2206200d290300370300200241e0006a41186a220d200e290300370300200241e0006a41106a220e200f290300370300200241e0006a41086a220f2010290300370300200241c0006a41086a22102011290300370300200241c0006a41106a22112012290300370300200241c0006a41186a22122013290300370300200220022903b80137036020022002290398013703400240200a2002280234470d00200241306a200a4101109601200228023021082002280238210a0b2008200a41e8006c6a2201200c3a0000200141196a200d290300370000200141116a200e290300370000200141096a200f29030037000020012002290360370001201429000021072015290300211a2006290300211b200141c0006a2018370000200141386a2019370000200141216a201b370000200141296a201a370000200141306a2007370000200141c8006a2002290340370000200141d0006a2010290300370000200141d8006a2011290300370000200141e0006a20122903003700002002200a41016a220a360238200b2005460d02200228022c21060c010b0b20022802342201450d01200141e8006c450d01200810350c010b20080d010b200241003602b802200242013703b002200241093602bc012002200241106a3602b8012002200241b0026a360260200241fc026a4101360200200242013702ec02200241c888c2003602e8022002200241b8016a3602f802200241e0006a41e88ac500200241e8026a10431a20023502b80242208620023502b002841006024020022802b402450d0020022802b00210350b200041003602000c010b20002002290234370204200020083602000b2004450d00200310350b200241a0036a24000f0b1045000b1044000bcc0502077f067e230041f0006b2102024002400240024020012802042203450d00200128020022042d0000210520012003417f6a22063602042001200441016a360200200541014b0d0320050e020102010b200041023a00000f0b024020064110490d00200041003a000020002002280028360001200041086a2004290001370300200041186a2002290348370300200041106a200441096a29000037030020012003416f6a3602042001200441116a360200200041046a2002412b6a280000360000200041206a200241c8006a41086a290300370300200041286a200241c8006a41106a290300370300200041306a200241c8006a41186a2903003703000f0b200041023a00000f0b41002105200241003a00682003417f6a2107417e210602400240034020072005460d01200241c8006a20056a200420056a220841016a2d00003a00002001200320066a3602042001200841026a3602002002200541016a22083a00682006417f6a21062008210520084120470d000b200241286a41186a2205200241c8006a41186a290300370300200241286a41106a2206200241c8006a41106a290300370300200241286a41086a2207200241c8006a41086a290300370300200220022903483703282008417f7320036a4110490d01200241086a41086a20072903002209370300200241086a41106a2006290300220a370300200241086a41186a2005290300220b370300200420086a220541016a290000210c200541096a290000210d2001200320086b416f6a3602042001200541116a36020020022002290328220e370308200041013a00002000200e370001200041096a2009370000200041116a200a370000200041196a200b370000200041306a200d370300200041286a200c370300200041216a2002280001360000200041246a200241046a2800003600000f0b200541ff0171450d00200241003a00680b200041023a00000f0b200041023a00000bfe0301057f230041f0006b220224002002412036020c20022001360208200241106a2001ad4280808080800484100510c20102400240200228021022030d00200041033a00200c010b200241186a28020021042002280214210541002101200241003a0068024002400240034020042001460d01200241c8006a20016a200320016a2d00003a00002002200141016a22063a00682006210120064120470d000b200241286a41186a200241c8006a41186a290300370300200241286a41106a200241c8006a41106a290300370300200241286a41086a200241c8006a41086a2903003703002002200229034837032820042006460d01200320066a2d0000220141034f0d0120002002290328370000200041186a200241286a41186a290300370000200041106a200241286a41106a290300370000200041086a200241286a41086a2903003700000c020b200141ff0171450d00200241003a00680b2002410036023020024201370328200241093602242002200241086a3602202002200241286a36026c200241dc006a41013602002002420137024c200241c888c2003602482002200241206a360258200241ec006a41e88ac500200241c8006a10431a200235023042208620023502288410060240200228022c450d00200228022810350b410321010b200020013a00202005450d00200310350b200241f0006a24000bd60201027f230041c0026b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100510c20102400240200328021022010d00200041003a00000c010b200328021421042003200341186a2802003602ac02200320013602a802200341a0016a200341a8026a10c202410121020240024020032d00a0014101470d00410021022003410036022820034201370320200341093602b4022003200341086a3602b0022003200341206a3602bc02200341b4016a4101360200200342013702a401200341c888c2003602a0012003200341b0026a3602b001200341bc026a41e88ac500200341a0016a10431a200335022842208620033502208410062003280224450d01200328022010350c010b200341206a200341a0016a410172418001109d081a200041016a200341206a418001109d081a0b200020023a00002004450d00200110350b200341c0026a24000ba60901077f230041d0026b2202240041002103200241003a002820012802042104417f210502400240024002400240034020042003460d01200241086a20036a200128020022062d00003a00002001200420056a3602042001200641016a3602002002200341016a22073a00282005417f6a21052007210320074120470d000b20024188016a41086a200241086a41086a29030037030020024188016a41106a200241086a41106a29030037030020024188016a41186a200241086a41186a290300370300200220022903083703880141002108200241003a0028200420076b2107200420056a2103034020072008460d02200241086a20086a200620086a220541016a2d00003a0000200120033602042001200541026a3602002002200841016a22053a00282003417f6a21032005210820054120470d000b200241a8016a41086a200241086a41086a290300370300200241a8016a41106a200241086a41106a290300370300200241a8016a41186a200241086a41186a290300370300200220022903083703a80141002107200241003a0028200620056a210803402003417f460d03200241086a20076a200820076a220541016a2d00003a0000200120033602042001200541026a3602002002200741016a22053a00282003417f6a21032005210720054120470d000b200241c8016a41086a200241086a41086a290300370300200241c8016a41106a200241086a41106a290300370300200241c8016a41186a200241086a41186a290300370300200220022903083703c80141002107200241003a00c802200820056a41016a210503402003417f460d04200241a8026a20076a20052d00003a0000200120033602042001200541016a22053602002002200741016a22083a00c8022003417f6a21032008210720084120470d000b200241e8016a41086a2201200241a8026a41086a290300370300200241e8016a41106a2203200241a8026a41106a290300370300200241e8016a41186a2205200241a8026a41186a290300370300200241086a41086a20024188016a41086a290300370300200241086a41106a20024188016a41106a290300370300200241086a41186a20024188016a41186a290300370300200220022903a8023703e8012002200229038801370308200241c0006a200241a8016a41186a290300370300200241386a200241a8016a41106a290300370300200241306a200241a8016a41086a290300370300200220022903a801370328200241e0006a200241c8016a41186a290300370300200241d8006a200241c8016a41106a290300370300200241d0006a200241c8016a41086a290300370300200220022903c80137034820024180016a2005290300370300200241f8006a2003290300370300200241f0006a2001290300370300200220022903e801370368200041016a200241086a418001109d081a200041003a00000c040b0240200341ff0171450d00200241003a00280b200041013a00000c030b0240200841ff0171450d00200241003a00280b200041013a00000c020b0240200741ff0171450d00200241003a00280b200041013a00000c010b0240200741ff0171450d00200241003a00c8020b200041013a00000b200241d0026a24000b8a06010c7f23004190016b220324002003200236021420032001360210200341186a2002ad4220862001ad84100510c2010240024002400240200328021822040d00200041003602000c010b200328021c21052003200341206a28020036022c20032004360228200341086a200341286a10c4010240024020032802080d00200328020c2206200328022c22074105762201200120064b1b22014105742202417f4c0d030240024020010d00410121080c010b200210332208450d050b41002109200341003602402003200136023c20032008360238024002402006450d004100210a03402007210b41002101200341003a008801200a41016a210a0340200b2001460d03200341e8006a20016a200328022822022d00003a00002003200241016a3602282003200141016a22023a0088012002210120024120470d000b200341c8006a41186a220c200341e8006a41186a290300370300200341c8006a41106a220d200341e8006a41106a290300370300200341c8006a41086a220e200341e8006a41086a2903003703002003200329036837034802402009200328023c470d00200341386a20094101108a0120032802382108200328024021090b200b20026b2107200820094105746a22012003290348370000200141186a200c290300370000200141106a200d290300370000200141086a200e2903003700002003200941016a2209360240200a2006470d000b2003200b20026b36022c0b2008450d012000200329023c370204200020083602000c020b2003410036022c0240200141ff0171450d00200341003a0088010b200328023c41ffffff3f71450d00200810350b20034100360250200342013703482003410936023c2003200341106a3602382003200341c8006a360234200341fc006a41013602002003420137026c200341c888c2003602682003200341386a360278200341346a41e88ac500200341e8006a10431a200335025042208620033502488410060240200328024c450d00200328024810350b200041003602000b2005450d00200410350b20034190016a24000f0b1044000b1045000bab0602057f047e23004190016b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100510c20102400240200328021022040d00200041023a00000c010b2003280214210502400240200341186a2802002201450d0020042d0000220241014b0d002001417f6a2106024002400240024020020e020001000b41002101200341003a008801200441016a21070240034020062001460d01200341e8006a20016a200720016a2d00003a00002003200141016a22023a0088012002210120024120470d000b200341c8006a41186a200341e8006a41186a2903002208370300200341206a41086a200341e8006a41086a290300370300200341206a41106a200341e8006a41106a290300370300200341206a41186a200837030020032003290368370320410021010c020b200141ff0171450d03200341003a0088010c030b41002101200341003a008801200441016a2107034020062001460d02200341e8006a20016a200720016a2d00003a00002003200141016a22023a0088012002210120024120470d000b200341c8006a41186a200341e8006a41186a2903002208370300200341206a41086a200341e8006a41086a290300370300200341206a41106a200341e8006a41106a290300370300200341206a41186a200837030020032003290368370320410121010b200341e8006a41186a200341206a41186a2903002208370300200341e8006a41106a200341206a41106a2903002209370300200341e8006a41086a200341206a41086a290300220a37030020032003290320220b370368200041196a2008370000200041116a2009370000200041096a200a3700002000200b3700010c020b200141ff0171450d00200341003a0088010b2003410036025020034201370348200341093602242003200341086a3602202003200341c8006a360244200341fc006a41013602002003420137026c200341c888c2003602682003200341206a360278200341c4006a41e88ac500200341e8006a10431a200335025042208620033502488410060240200328024c450d00200328024810350b410221010b200020013a00002005450d00200410350b20034190016a24000ba20403047f017e027f230041e0006b220224002002412036020c20022001360208200241106a2001ad4280808080800484100510c20102400240200228021022010d00200041003602000c010b200228021421032002200241186a280200360224200220013602202002200241206a10c4010240024020022802000d002002280224220420022802044102742205490d0002400240024002402005417f4c0d000240024020050d0042002106410121070c010b200510392207450d022007200228022022082005109d081a2002200420056b3602242002200820056a3602202005ad21060b2007450d04024020062005ad422086842206422088a722050d002006a721050c030b024020072005724103710d002006a722054103710d0020054102762204450d032006422288a721080c040b2006a7450d04200710350c040b1044000b1045000b4100210802402005450d00200710350b41002104410421070b41000d002007450d002000200436020420002007360200200041086a20083602000c010b20024100360230200242013703282002410936023c2002200241086a3602382002200241286a360244200241dc006a41013602002002420137024c200241c888c2003602482002200241386a360258200241c4006a41e88ac500200241c8006a10431a200235023042208620023502288410060240200228022c450d00200228022810350b200041003602000b2003450d00200110350b200241e0006a24000bef1104047f017e137f047e23004180036b220224002002412036022420022001360220200241286a2001ad4280808080800484100510c2010240024002400240200228022822030d00200041003602000c010b200228022c21042002200241306a28020036023c20022003360238200241186a200241386a10c4010240024020022802180d00200228021c2205200228023c411c6e2201200120054b1bad421c7e2206422088a70d032006a72201417f4c0d030240024020010d00410421070c010b200110332207450d050b200241003602482002200736024020022001411c6e36024402400240024002400240024002402005450d00200241a0026a41c4006a2108410021094100210a0340200241106a200241386a10c40120022802100d072002280214220b200228023c41e0006e22012001200b4b1bad42e0007e2206422088a70d0b2006a72201417f4c0d0b0240024020010d004108210c0c010b20011033220c450d0d0b200241003602582002200c3602502002200141e0006e3602540240024002400240200b450d004100210d0340200241a0026a200241386a10c702200241e0016a41386a2201200241a0026a41386a290300370300200241e0016a41306a220e200241a0026a41306a290300370300200241e0016a41286a220f200241a0026a41286a290300370300200241e0016a41206a2210200241a0026a41206a290300370300200241e0016a41186a2211200241a0026a41186a290300370300200241e0016a41106a2212200241a0026a41106a290300370300200241e0016a41086a2213200241a0026a41086a290300370300200241c0016a41086a2214200841086a290200370300200241c0016a41106a2215200841106a290200370300200241c0016a41186a2216200841186a280200360200200220022903a0023703e001200220082902003703c00120022802e0022217450d0220024180016a41386a2218200129030037030020024180016a41306a2219200e29030037030020024180016a41286a220e200f29030037030020024180016a41206a220f201029030037030020024180016a41186a2210201129030037030020024180016a41106a2211201229030037030020024180016a41086a22122013290300370300200241e0006a41086a22132014290300370300200241e0006a41106a22142015290300370300200241e0006a41186a22152016280200360200200220022903e00137038001200220022903c0013703600240200d2002280254470d00200241d0006a200d410110a4012002280250210c2002280258210d0b200c200d41e0006c6a2201200229038001370300200141106a2011290300370300200141086a2012290300370300201929030021062018290300211a200e290300211b200f290300211c2010290300211d200141c0006a2017360200200141186a201d370300200141206a201c370300200141286a201b370300200141c4006a2002290360370200200141386a201a370300200141306a2006370300200141cc006a2013290300370200200141d4006a2014290300370200200141dc006a20152802003602002002200d41016a220d360258200b417f6a220b0d000b0b200c450d0a20022902542106200241086a200241386a10c40120022802080d07200228020c220b200228023c220d41027622012001200b4b1b2201410274220e417f4c0d0e20010d014104210f0c020b0240200d450d00200d41e0006c210d200c41d4006a210103400240200141706a2802002208450d00200841306c450d002001416c6a28020010350b0240200128020041ffffff3f71450d002001417c6a28020010350b200141e0006a2101200d41a07f6a220d0d000b0b20022802542201450d09200141e0006c0d080c090b200e1033220f450d0d0b200241003602a802200220013602a4022002200f3602a0020240200b450d00410021010340200d4104490d0520022002280238220e41046a360238200e280000220e418094ebdc034b0d040240200120022802a402470d00200241a0026a2001410110860120022802a002210f20022802a80221010b200d417c6a210d200f20014102746a200e3602002002200141016a22013602a802200b417f6a220b0d000b2002200d36023c0b200f450d0420022902a402211a200d4104490d05200a41016a210a2002200d417c6a36023c20022002280238220141046a3602382001280000210d024020092002280244470d00200241c0006a2009410110f90120022802402107200228024821090b20072009411c6c6a2201200d360218200120063702042001200c360200200141106a201a3702002001410c6a200f3602002002200941016a2209360248200a2005470d000b0b2007450d0620002002290244370204200020073602000c070b200d417c6a210d0b2002200d36023c20022802a40241ffffffff0371450d00200f10350b02402006422088a72201450d00200141e0006c210d200c41d4006a210103400240200141706a2802002208450d00200841306c450d002001416c6a28020010350b0240200128020041ffffff3f71450d002001417c6a28020010350b200141e0006a2101200d41a07f6a220d0d000b0b2006a72201450d02200141e0006c0d010c020b0240201a42ffffffff0383500d00200f10350b02402006422088a72201450d00200141e0006c210d200c41d4006a210103400240200141706a2802002208450d00200841306c450d002001416c6a28020010350b0240200128020041ffffff3f71450d002001417c6a28020010350b200141e0006a2101200d41a07f6a220d0d000b0b2006a72201450d01200141e0006c450d010b200c10350b2007200910c80220022802442201450d002001411c6c450d00200710350b200241003602e801200242013703e00120024109360284012002200241206a360280012002200241e0016a3602c001200241b4026a4101360200200242013702a402200241c888c2003602a002200220024180016a3602b002200241c0016a41e88ac500200241a0026a10431a20023502e80142208620023502e001841006024020022802e401450d0020022802e00110350b200041003602000b2004450d00200310350b20024180036a24000f0b1044000b1045000b9e06020a7f017e230041d0016b2202240041002103200241003a00c0012001280204417f6a2104024002400240024003402004417f460d01200241a0016a20036a200128020022052d00003a0000200120043602042001200541016a3602002002200341016a22053a00c0012004417f6a21042005210320054120470d000b20024180016a41186a2204200241a0016a41186a220329030037030020024180016a41106a2205200241a0016a41106a220629030037030020024180016a41086a2207200241a0016a41086a2208290300370300200220022903a00137038001200241a0016a200110c50120022802c0012209450d01200241c0006a41186a220a2004290300370300200241c0006a41106a220b2005290300370300200241c0006a41086a22052007290300370300200241c0006a41286a22072008290300370300200241c0006a41306a22082006290300370300200241c0006a41386a220620032903003703002002200229038001370340200220022903a001370360200241c4016a2802002104200241a0016a41286a290300210c200241086a2005290300370300200241106a200b290300370300200241186a200a290300370300200241206a22032002290360370300200241286a22052007290300370300200241306a22072008290300370300200241386a2208200629030037030020022002290340370300200241c0006a200110c3012002280240450d02200241a0016a41086a2201200241c0006a41086a280200360200200220022903403703a001200041386a2008290300370300200041306a2007290300370300200041286a2005290300370300200041206a2003290300370300200041186a200241186a290300370300200041106a200241106a290300370300200041086a200241086a29030037030020002002290300370300200041c8006a200c3703002000200436024420002009360240200041d0006a20022903a001370300200041d8006a20012802003602000c030b200341ff0171450d00200241003a00c0010b200041003602400c010b200041003602402004450d00200441306c450d00200910350b200241d0016a24000bd90101037f02402001450d0020002001411c6c6a21020340024020002802082201450d00200141e0006c2103200028020041d4006a210103400240200141706a2802002204450d00200441306c450d002001416c6a28020010350b0240200128020041ffffff3f71450d002001417c6a28020010350b200141e0006a2101200341a07f6a22030d000b0b0240200041046a2802002201450d00200141e0006c450d00200028020010350b2000411c6a21010240200041106a28020041ffffffff0371450d00200028020c10350b2001210020012002470d000b0b0bbb1005057f017e067f077e017f230041c0016b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100510c2010240024002400240200328021022020d00200041023a00000c010b200328021421042003200341186a280200220536025420032002360250024002402005450d0020022d0000210120032005417f6a22063602542003200241016a360250200141014b0d00024002400240024020010e020001000b2003200341d0006a10c40120032802000d03200328020422062003280254220141306e2207200720064b1bad42307e2208422088a70d062008a72207417f4c0d060240024020070d00410821090c010b200710332209450d080b4100210a20034100360268200320093602602003200741306e220b36026402402006450d002006417f6a210720034198016a41017221064100210a02400240034020014104490d0120032802502205350000210820032001417c6a3602542003200541046a36025020034198016a200341d0006a10ca0220032d00980122054102460d01200341f0006a411f6a220b2006411f6a290000370000200341f0006a41186a220c200641186a290000370300200341f0006a41106a220d200641106a290000370300200341f0006a41086a220e200641086a290000370300200320062900003703700240200a2003280264470d00200341e0006a200a4101108801200328026021092003280268210a0b2009200a41306c6a220120053a000820012008370300200141096a2003290370370000200141116a200e290300370000200141196a200d290300370000200141216a200c290300370000200141286a200b2900003700002003200a41016a220a3602682007450d022007417f6a2107200328025421010c000b0b20032802642201450d05200141306c450d05200910350c050b2003280264210b0b2009450d0302400240200328025422014110490d0020032003280250220641106a3602502003200141706a220736025420074110490d00200641086a290000210f200629000021102003200641206a3602502003200141606a220736025420074104490d01200641186a2900002108200629001021112003200641246a36025020032001415c6a220736025420074110490d0120062800202107200341386a2006412c6a290000370300200341cc006a41026a200341dd006a41026a2d00003a000020032011370320200320032f005d3b014c20032007360240200320062900243703302003200837032820032001414c6a3602542003200641346a360250410021010c030b200b450d04200b41306c450d04200910350c040b200b450d03200b41306c450d03200910350c030b20064110490d0220032005416f6a220a3602542003200241116a360250200241096a29000021082002290001211141002101200341003a00b801416e21060340200a2001460d0220034198016a20016a200220016a220741116a2d00003a00002003200520066a3602542003200741126a3602502003200141016a22073a00b8012006417f6a21062007210120074120470d000b200341e2006a20032d009a013a0000200320032f0198013b01602005416f6a2007460d02200341af016a290000210f20032900a7012110200328009b012109200328009f01210b20032800a301210a20032d00b701210d200220076a220141116a2d0000210c2003200520066a22063602542003200141126a360250200c41074f0d0220064110490d022003200141226a220e3602502003200520076b2207415e6a220636025420064110490d022001411a6a2900002112200141126a29000021132003200141326a220536025020032007414e6a220636025420064104490d022001412a6a2900002114200e2900002115200528000021062003200141366a220e36025020032007414a6a220536025420054110490d02200341cc006a41026a200341e0006a41026a2d00003a0000200341c0006a2012370300200341206a41106a2008370300200320032f01603b014c2003200741ba7f6a3602542003200141c6006a36025020032013370338200320113703282003200c3a00212003200d3a0020200320032801703601222003200341f4006a2f01003b01262001413e6a2900002111200e2900002108410121010b200341f0006a41026a200341cc006a41026a2d000022073a000020034198016a41086a2205200341206a41086a29030037030020034198016a41106a220c200341206a41106a29030037030020034198016a41186a220d200341206a41186a29030037030020034198016a41206a220e200341206a41206a290300370300200320032f014c22163b01702003200329032037039801200041186a200f370000200041106a2010370000200041036a20073a0000200020163b00012000410c6a200a360000200041086a200b360000200041046a2009360000200041e8006a2006360000200041e0006a2011370000200041d8006a2008370000200041d0006a2014370000200041c8006a2015370000200041206a200329039801370000200041286a2005290300370000200041306a200c290300370000200041386a200d290300370000200041c0006a200e2903003700000c020b200141ff0171450d00200341003a00b8010b2003410036022820034201370320200341093602742003200341086a3602702003200341206a360260200341ac016a41013602002003420137029c01200341c888c200360298012003200341f0006a3602a801200341e0006a41e88ac50020034198016a10431a2003350228422086200335022084100602402003280224450d00200328022010350b410221010b200020013a00002004450d00200210350b200341c0016a24000f0b1044000b1045000b840402067f047e230041206b21020240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a22063602042001200441016a2207360200200541014b0d0320050e020102010b200041023a00000f0b02402006450d0020042d0001210520012003417e6a22063602042001200441026a360200200541ff0071220741064b0d0020064110490d00200041003a0000200041086a2004290002370300200041026a20073a0000200020054107763a0001200041036a2002280009360000200041186a2002290310370300200041106a2004410a6a29000037030020012003416e6a3602042001200441126a360200200041076a2002410d6a2d00003a0000200041206a200241106a41086a2903003703000f0b200041023a00000f0b200241106a41086a220542003703002002420037031020064110490d01200741086a29000021082007290000210920012003416f6a22063602042001200441116a2207360200200542003703002002420037031020064110490d01200741086a290000210a2007290000210b20012003415f6a3602042001200441216a360200200041206a200a370300200041186a200b370300200041106a2008370300200041086a2009370300200041013a000020002002280009360001200041046a2002410c6a2800003600000f0b200041023a00000f0b200041023a00000bbb0402097f057e230041f0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100510c20102400240200328021022040d00200042003703000c010b200341186a28020021052003280214210641002101200341003a0068024002400240034020052001460d01200341c8006a20016a200420016a2d00003a00002003200141016a22023a00682002210120024120470d000b200341286a41186a2201200341c8006a41186a2207290300370300200341286a41106a2208200341c8006a41106a2209290300370300200341286a41086a220a200341c8006a41086a220b29030037030020032003290348370328200520026b410f4d0d01200b200a290300220c37030020092008290300220d37030020072001290300220e37030020032003290328220f370348200420026a22012900002110200041306a200141086a290000370300200041286a2010370300200041206a200e370300200041186a200d370300200041106a200c3703002000200f3703084201210c0c020b200141ff0171450d00200341003a00680b2003410036023020034201370328200341093602242003200341086a3602202003200341286a36026c200341dc006a41013602002003420137024c200341c888c2003602482003200341206a360258200341ec006a41e88ac500200341c8006a10431a200335023042208620033502288410060240200328022c450d00200328022810350b4200210c0b2000200c3703002006450d00200410350b200341f0006a24000bf80202027f037e230041e0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100510c20102400240200328021022010d00200041003602100c010b200328021421042003200341106a41086a28020022023602242003200136022002400240024020024110490d002003200241706a3602242003200141106a360220200141086a290000210520012900002106200341c8006a200341206a10c301200328024822020d010b20034100360230200342013703282003410936023c2003200341086a3602382003200341286a360244200341dc006a41013602002003420137024c200341c888c2003602482003200341386a360258200341c4006a41e88ac500200341c8006a10431a200335023042208620033502288410060240200328022c450d00200328022810350b200041003602100c010b200329024c2107200020053703082000200637030020002007370214200020023602100b2004450d00200110350b200341e0006a24000bde0201037f230041e0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100510c20102400240200328021022010d00200041003602040c010b200328021421042003200341186a28020022023602242003200136022002400240024020024104490d0020032002417c6a3602242003200141046a36022020012800002102200341c8006a200341206a10c301200328024822050d010b20034100360230200342013703282003410936023c2003200341086a3602382003200341286a360244200341dc006a41013602002003420137024c200341c888c2003602482003200341386a360258200341c4006a41e88ac500200341c8006a10431a200335023042208620033502288410060240200328022c450d00200328022810350b200041003602040c010b2000200329024c37020820002005360204200020023602000b2004450d00200110350b200341e0006a24000bb10201037f230041e0006b220224002002412036020c20022001360208200241106a2001ad4280808080800484100510c20102400240200228021022010d00200041003602000c010b200228021421032002200241186a28020036022420022001360220200241c8006a200241206a10cf0202400240200228024822040d0020024100360230200242013703282002410936023c2002200241086a3602382002200241286a360244200241dc006a41013602002002420137024c200241c888c2003602482002200241386a360258200241c4006a41e88ac500200241c8006a10431a200235023042208620023502288410060240200228022c450d00200228022810350b200041003602000c010b2000200229024c370204200020043602000b2003450d00200110350b200241e0006a24000b8f0d05037f017e0a7f017e047f23004180016b22022400200241086a200110c40102400240024002402002280208450d00200041003602000c010b200228020c2203200128020441246e2204200420034b1bad42247e2205422088a70d022005a72204417f4c0d020240024020040d00410421060c010b200410332206450d020b4100210720024100360218200220063602102002200441246e36021402402003450d00200241cd006a2108200241eb006a220941056a210a4100210b0340024002400240024002402001280204220c450d002001280200220d2d000021042001200c417f6a220e3602042001200d41016a360200200441074b0d00024002400240024002400240024020040e080007010703040205000b2002200110c40120022802000d06200128020420022802042204490d062004417f4c0d0f024020040d004101210f4101450d074100210d0c090b20041039220f450d0e20012802042004490d05200f20012802002004109d08210c2001280204220d2004490d072001200d20046b3602042001200128020020046a360200200c450d062004210d0c080b41002104200241003a0078200c417e6a210c02400340200e2004460d01200241d8006a20046a200d20046a220f41016a2d00003a00002001200c3602042001200f41026a3602002002200441016a220f3a0078200c417f6a210c200f2104200f4120470d000b200220092900003703402002200a290000370045200228005f210d20022f0158210420022d005a210c200228005b210f20022900632110200841026a200241d5006a41026a2d00003a0000200820022f00553b00002010428080808070832105200f41087621112004200c41107472210c2010a721044100210e0c0a0b200441ff0171450d05200241003a00780c050b200241d8006a200110c405200228025c220d450d0420022f015820022d005a41107472210c20022d005b210f200229036022104280808080708321052010a721044101210e0c080b200241d8006a200110c405200228025c220d450d0320022f015820022d005a41107472210c20022d005b210f200229036022104280808080708321052010a721044102210e0c070b200241d8006a200110c405200228025c220d450d0220022f015820022d005a41107472210c20022d005b210f200229036022104280808080708321052010a721044103210e0c060b200e450d01200d2d000121042001200c417e6a220f3602042001200d41026a36020020040d01200f450d01200d2d000221042001200c417d6a220e3602042001200d41036a360200200441014b0d014100210f0240024020040e020100010b200e4104490d02200d28000321122001200c41796a22043602042001200d41076a36020020044104490d02200d28000721132001200c41756a3602042001200d410b6a3602004101210f0b200241c0006a41086a200241d8006a41086a290200370300200220022902583703404104210e4200210541002111201321042012210d0c040b200f10350b200241306a41086a200241c0006a41086a290300370300200220022903403703302000410036020002402007450d00200741246c21042006210103400240024020012d0000220c41044b0d00024002400240200c0e050400010204040b2001410c6a280200450d03200141086a28020010350c030b2001410c6a280200450d02200141086a28020010350c020b2001410c6a280200450d01200141086a28020010350c010b200141086a280200450d00200141046a28020010350b200141246a21012004415c6a22040d000b0b20022802142201450d06200141246c450d06200610350c060b2004200d41a4f0cb001059000b200241c0006a41086a200241d8006a41086a29020037030020022002290258370340200f41087621114105210e420021050b0b200b41016a210b200241306a41086a200241c0006a41086a2903002210370300200241206a41086a22142010370300200220022903402210370330200220103703202011410874200f41ff017172210f20052004ad842105024020072002280214470d00200241106a20074101108d0120022802102106200228021821070b2006200741246c6a2204200537000c2004200d3600082004200f3600042004200c3b00012004200e3a0000200441036a200c4110763a0000200420022903203700142004411c6a20142903003700002002200741016a2207360218200b2003470d000b0b20002002290310370200200041086a200241106a41086a2802003602000b20024180016a24000f0b1045000b1044000ba00302037f037e230041e0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100510c20102400240200328021022010d00200041003602140c010b200328021421042003200341186a28020022023602242003200136022002400240024020024104490d002003200141046a36022020032002417c6a220536022420054110490d002001280000210520032002416c6a3602242003200141146a3602202001410c6a290000210620012900042107200341c8006a200341206a10c301200328024822020d010b20034100360230200342013703282003410936023c2003200341086a3602382003200341286a360244200341dc006a41013602002003420137024c200341c888c2003602482003200341386a360258200341c4006a41e88ac500200341c8006a10431a200335023042208620033502288410060240200328022c450d00200328022810350b200041003602140c010b200329024c210820002006370308200020073703002000200837031820002002360214200020053602100b2004450d00200110350b200341e0006a24000b940201037f230041d0006b220224002002200136020420022000360200200241086a2001ad4220862000ad84100510c20102400240200228020822010d00410221000c010b200228020c210302400240200241106a280200450d0020012d0000220441014b0d0041002100024020040e020200020b410121000c010b20024100360220200242013703182002410936022c200220023602282002200241186a360234200241cc006a41013602002002420137023c200241c888c2003602382002200241286a360248200241346a41e88ac500200241386a10431a200235022042208620023502188410060240200228021c450d00200228021810350b410221000b2003450d00200110350b200241d0006a240020000bd70b06057f017e057f017e027f037e230041a0016b220324002003200236021420032001360210200341186a2002ad4220862001ad84100510c2010240024002400240200328021822010d00200041023a00000c010b200328021c21042003200341206a280200220236024c20032001360248024002402002450d0020012d0000210520032002417f6a220636024c2003200141016a360248200541014b0d000240024002400240024020050e020001000b20064104490d04200341c4006a41026a200341d8006a41026a2d00003a0000200341286a41086a200341f8006a41086a290300370300200341286a41106a200341f8006a41106a290300370300200341286a41186a200341f8006a41186a280200360200200320032f00583b0144200320032903783703282001280001210520032002417b6a36024c2003200141056a360248410021020c010b200341086a200341c8006a10c40120032802080d03200328024c2207200328020c2205490d032005417f4c0d060240024020050d0042002108410121090c010b200510392209450d082009200328024822022005109d081a2003200720056b220736024c2003200220056a3602482005ad21080b2009450d0341002102200341003a0098012005ad4220862008842208422088a7210a2008a7210b417f21050240024002400240034020072002460d01200341f8006a20026a2003280248220c2d00003a00002003200720056a36024c2003200c41016a3602482003200241016a22063a0098012005417f6a21052006210220064120470d000b200341d2006a20032d007a3a0000200341e0006a20034187016a290000370300200341d8006a41106a2003418f016a290000370300200341f0006a20034197016a2d00003a0000200320032f01783b01502003200329007f370358200720066b22024110490d01200328007b21052003200c41116a3602482003200241706a220d36024c200d4104490d05200c41096a290000210e200c29000121082003200c41156a36024820032002416c6a36024c2007416c6a2006460d05200c28001121062003200c41166a36024820032002416b6a220f36024c200c2d0015221041014b0d054100210d20100e020302030b200241ff0171450d00200341003a0098010b200b0d040c050b200f4104490d022003200c411a6a3602482003200241676a36024c200c28001621074101210d0b200341c4006a41026a200341d0006a41026a2d00003a0000200341286a41086a200341d8006a41086a290300370300200341286a41106a200341d8006a41106a290300370300200341286a41186a200341d8006a41186a2d00003a0000200341c3006a200341d5006a41026a2d00003a0000200320032f01503b014420032003290358370328200320032f00553b0041410121020b200341d8006a41026a200341c4006a41026a2d0000220c3a0000200341f8006a41086a200341286a41086a2903002211370300200341f8006a41106a200341286a41106a2903002212370300200341f8006a41186a200341286a41186a2802002210360200200320032f0144220f3b0158200320032903282213370378200041036a200c3a00002000200f3b0001200041046a2005360000200041c8006a200e370000200041c0006a2008370000200041086a2013370000200041106a2011370000200041186a2012370000200041206a2010360000200041386a2007360000200041346a200d360000200041306a20063600002000412c6a200a360000200041286a200b360000200041246a20093600000c030b200b450d010b200910350b20034100360230200342013703282003410936025c2003200341106a3602582003200341286a3602502003418c016a41013602002003420137027c200341c888c2003602782003200341d8006a36028801200341d0006a41e88ac500200341f8006a10431a200335023042208620033502288410060240200328022c450d00200328022810350b410221020b200020023a00002004450d00200110350b200341a0016a24000f0b1044000b1045000b850604067f027e027f057e23004190016b220324002003200236020420032001360200200341086a2002ad4220862001ad84100510c20102400240200328020822020d00200041003602180c010b200328020c21042003200341106a280200220136023c200320023602380240024020014104490d002003200241046a36023820032001417c6a220536023c20054104490d00200228000021062003200241086a3602382003200141786a220536023c20054110490d00200228000421072003200141686a220836023c2003200241186a360238200241106a29000021092002290008210a41002101200341003a0088010240034020082001460d01200341e8006a20016a200220016a220541186a2d00003a00002003200541196a3602382003200141016a22053a0088012005210120054120470d000b200341c8006a41086a2201200341e8006a41086a290300370300200341c8006a41106a220b200341e8006a41106a290300370300200341c8006a41186a220c200341e8006a41186a290300370300200320032903683703482003200820056b36023c200341e8006a200341386a10c30120032802682205450d01200341186a41086a2001290300220d370300200341186a41106a200b290300220e370300200341186a41186a200c290300220f370300200320032903482210370318200329026c2111200020093703082000200a3703002000201137021c200020053602182000200736021420002006360210200041246a20103702002000412c6a200d370200200041346a200e3702002000413c6a200f3702000c020b2003410036023c200141ff0171450d00200341003a0088010b20034100360250200342013703482003410936021c200320033602182003200341c8006a360244200341fc006a41013602002003420137026c200341c888c2003602682003200341186a360278200341c4006a41e88ac500200341e8006a10431a200335025042208620033502488410060240200328024c450d00200328024810350b200041003602180b2004450d00200210350b20034190016a24000bfa4f07087f017e017f017e017f027e4f7f230041d0086b220324002003200236021420032001360210200341186a2002ad4220862001ad84100510c20102400240200328021822040d00200041023a00a4020c010b200328021c21052003200341186a41086a280200360294022003200436029002200320034190026a36028804200341086a20034188046a10d5020240024020032802080d004108210602400240200328020c22074180012007418001491b2201450d00200141057410332206450d010b2003410036028808200320013602840820032006360280080240024002400240024002402007450d00200341b0086a2108410021010340200341003602a808200341a8086a20032802900222092003280294022202410420024104491b220a109d081a20032002200a6b3602940220032009200a6a360290020240200241034b0d00200341a8086a200a6a41004104200a6b109f081a0b20033502a808210b200341003a00a80820032802940222022002410047220a490d02200341a8086a2003280290022209200a109d081a20032002200a6b220c3602940220032009200a6a220a3602900202400240024020020d004200210d0c010b20032d00a808220241064b0d044200210d02400240024002400240024020020e0707000102030405070b200341a8086a200c4110200c4110491b22026a41004100411020026b22092002410f4b1b109f08210e200341a8086a200a2002109d081a2003200c20026b360294022003200a20026a360290020240200c410f4b0d00200e41002009109f081a0b2008290300210f20032903a80821104201210d0c060b4202210d0c040b4203210d0c030b4204210d0c020b4205210d0c010b4206210d0b0b02402001200328028408470d0020034180086a2001410110a101200328028008210620032802880821010b200620014105746a2202200d3703082002200b370300200241186a200f370300200241106a20103703002003200141016a2201360288082007417f6a22070d000b0b2006450d06200329028408210d200341b0086a220a4200370300200342003703a808200341a8086a20032802900222072003280294022201411020014110491b2202109d081a2003200120026b360294022003200720026a3602900202402001410f4b0d00200341a8086a20026a4100411020026b109f081a0b200a290300210f20032903a8082110200320034188046a10d50220032802000d0320032802042209413820094138491b22070d014104210a0c020b20032802840841ffffff3f71450d0520061035410221010c060b200741c8006c1033220a450d030b410021022003410036028006200320073602fc052003200a3602f805024002400240024002400240024002402009450d0020034180086a410c6a211120034180086a410172211241002102034020034180086a20034188046a10d6020240024020032d00800822074106470d00410621070c010b200341fc076a41026a2208201241026a2d00003a0000200341e0076a41086a220e201141086a290200370300200341e0076a41106a2213201141106a290200370300200320122f00003b01fc07200320112902003703e007200328028408210c2003280288082101200341a8086a20034188046a10d602024020032d00a8084106470d00024020074101470d002001450d00200c10350b410621070c010b200341dc076a41026a20082d00003a0000200341c0076a41086a200e290300370300200341c0076a41106a201329030037030020034198076a41086a200341a8086a41086a29030037030020034198076a41106a200341a8086a41106a29030037030020034198076a41186a200341a8086a41186a29030037030020034198076a41206a200341a8086a41206a280200360200200320032f01fc073b01dc07200320032903e0073703c007200320032903a8083703980720012114200c21150b20034194076a41026a2201200341dc076a41026a2d00003a0000200341f8066a41086a220c200341c0076a41086a290300370300200341f8066a41106a2208200341c0076a41106a290300370300200341d0066a41086a220e20034198076a41086a290300370300200341d0066a41106a221320034198076a41106a290300370300200341d0066a41186a221620034198076a41186a290300370300200341d0066a41206a221720034198076a41206a280200360200200320032f01dc073b019407200320032903c0073703f80620032003290398073703d00620074106460d02200341cc066a41026a221820012d00003a0000200341b0066a41086a2219200c290300370300200341b0066a41106a220c200829030037030020034188066a41086a2208200e29030037030020034188066a41106a220e201329030037030020034188066a41186a2213201629030037030020034188066a41206a22162017280200360200200320032f0194073b01cc06200320032903f8063703b006200320032903d006370388060240200220032802fc05470d00200341f8056a2002410110a80120032802f805210a20032802800621020b200a200241c8006c6a220120073a0000200141086a2014360000200141046a2015360000200141036a20182d00003a0000200120032f01cc063b0001200141146a20192903003700002001411c6a200c2903003700002001410c6a20032903b006370000200141246a200329038806370000200141346a200e2903003700002001412c6a20082903003700002001413c6a2013290300370000200141c4006a20162802003600002003200241016a2202360280062009417f6a22090d000b20032802fc0521070b200a450d07200341a8086a20034188046a10d60220032d00a80822094106460d0120034194076a41026a20032d00ab083a0000200341c0076a41086a200341bc086a2201290200370300200341c0076a41106a200341c4086a2213290200370300200320032f00a9083b0194072003200341b4086a22162902003703c007200341a8086a41086a2217280200210c20032802ac082108200341a8086a20034188046a10d60220032d00a808220e4106460d02200341dc076a41026a20032d00ab083a0000200341e0076a41086a2001290200370300200341e0076a41106a2013290200370300200320032f00a9083b01dc07200320162902003703e0072017280200211320032802ac082116200341a8086a20034188046a10d60220032d00a80822174106460d03200341fc076a41026a20032d00ab083a000020034188066a41086a200341bc086a220129020037030020034188066a41106a200341c4086a2214290200370300200320032f00a9083b01fc072003200341b4086a221529020037038806200341a8086a41086a2212280200211820032802ac082119200341a8086a20034188046a10d60220032d00a80822114106460d04200341f8056a41026a20032d00ab083a0000200341d0066a41086a2001290200370300200341d0066a41106a2014290200370300200320032f00a9083b01f805200320152902003703d0062012280200211420032802ac082115200341a8086a20034188046a10d60220032d00a80822124106470d05024020114101470d002014450d00201510350b024020174101470d002018450d00201910350b0240200e4101470d002013450d00201610350b024020094101470d00200c450d00200810350b02402002450d00200a200241c8006c6a2102200a21010340024020012d00004101470d00200141086a280200450d00200141046a28020010350b0240200141246a2d00004101470d002001412c6a280200450d00200141286a28020010350b200141c8006a22012002470d000b0b2007450d07200741c8006c0d060c070b02402002450d00200a200241c8006c6a2102200a21010340024020012d00004101470d00200141086a280200450d00200141046a28020010350b0240200141246a2d00004101470d002001412c6a280200450d00200141286a28020010350b200141c8006a22012002470d000b0b20032802fc052201450d06200141c8006c0d050c060b02402002450d00200a200241c8006c6a2102200a21010340024020012d00004101470d00200141086a280200450d00200141046a28020010350b0240200141246a2d00004101470d002001412c6a280200450d00200141286a28020010350b200141c8006a22012002470d000b0b2007450d05200741c8006c0d040c050b024020094101470d00200c450d00200810350b02402002450d00200a200241c8006c6a2102200a21010340024020012d00004101470d00200141086a280200450d00200141046a28020010350b0240200141246a2d00004101470d002001412c6a280200450d00200141286a28020010350b200141c8006a22012002470d000b0b2007450d04200741c8006c0d030c040b0240200e4101470d002013450d00201610350b024020094101470d00200c450d00200810350b02402002450d00200a200241c8006c6a2102200a21010340024020012d00004101470d00200141086a280200450d00200141046a28020010350b0240200141246a2d00004101470d002001412c6a280200450d00200141286a28020010350b200141c8006a22012002470d000b0b2007450d03200741c8006c0d020c030b024020174101470d002018450d00201910350b0240200e4101470d002013450d00201610350b024020094101470d00200c450d00200810350b02402002450d00200a200241c8006c6a2102200a21010340024020012d00004101470d00200141086a280200450d00200141046a28020010350b0240200141246a2d00004101470d002001412c6a280200450d00200141286a28020010350b200141c8006a22012002470d000b0b2007450d02200741c8006c0d010c020b200341b2066a20032d00ab083a000020034198076a41086a200341bc086a290200370300200341a8076a200341c4086a290200370300200320032f00a9083b01b0062003200341b4086a29020037039807200341a8086a41086a280200211a20032802ac08211b200341003a00a8080240024020032802940222012001410047221c490d00200341a8086a200328029002221d201c109d081a20032001201c6b221e360294022003201d201c6a221f360290020240024020010d00410021010c010b20032d00a808222041014b0d0141002101024020200e020100010b200341003a00a808201e201e4100472201490d01200341a8086a201f2001109d081a2003201e20016b221d360294022003201f20016a22213602900202400240201e450d0020032d00a808211c0c010b4100211c200341003a00a8080b200341003a00a808201d201d4100472201490d01200341a8086a20212001109d081a2003201d20016b2222360294022003202120016a22213602900202400240201d450d0020032d00a808211d0c010b4100211d200341003a00a8080b200341003a00a808202220224100472201490d01200341a8086a20212001109d081a2003202220016b2223360294022003202120016a222436029002024002402022450d0020032d00a80821210c010b41002121200341003a00a8080b200341003a00a808202320234100472201490d01200341a8086a20242001109d081a2003202320016b2225360294022003202420016a222436029002024002402023450d0020032d00a80821220c010b41002122200341003a00a8080b200341003a00a808202520254100472201490d01200341a8086a20242001109d081a2003202520016b2226360294022003202420016a222436029002024002402025450d0020032d00a80821230c010b41002123200341003a00a8080b200341003a00a808202620264100472201490d01200341a8086a20242001109d081a2003202620016b2225360294022003202420016a222736029002024002402026450d0020032d00a80821240c010b41002124200341003a00a8080b200341003a00a808202520254100472201490d01200341a8086a20272001109d081a2003202520016b2226360294022003202720016a222736029002024002402025450d0020032d00a80821250c010b41002125200341003a00a8080b200341003a00a808202620264100472201490d01200341a8086a20272001109d081a2003202620016b2228360294022003202720016a222736029002024002402026450d0020032d00a80821260c010b41002126200341003a00a8080b200341003a00a808202820284100472201490d01200341a8086a20272001109d081a2003202820016b2229360294022003202720016a222a36029002024002402028450d0020032d00a80821270c010b41002127200341003a00a8080b200341003a00a808202920294100472201490d01200341a8086a202a2001109d081a2003202920016b222b360294022003202a20016a222a36029002024002402029450d0020032d00a80821280c010b41002128200341003a00a8080b200341003a00a808202b202b4100472201490d01200341a8086a202a2001109d081a2003202b20016b222c360294022003202a20016a222a3602900202400240202b450d0020032d00a80821290c010b41002129200341003a00a8080b200341003a00a808202c202c4100472201490d01200341a8086a202a2001109d081a2003202c20016b222b360294022003202a20016a222d3602900202400240202c450d0020032d00a808212a0c010b4100212a200341003a00a8080b200341003a00a808202b202b4100472201490d01200341a8086a202d2001109d081a2003202b20016b222c360294022003202d20016a222d3602900202400240202b450d0020032d00a808212b0c010b4100212b200341003a00a8080b200341003a00a808202c202c4100472201490d01200341a8086a202d2001109d081a2003202c20016b222e360294022003202d20016a222d3602900202400240202c450d0020032d00a808212c0c010b4100212c200341003a00a8080b200341003a00a808202e202e4100472201490d01200341a8086a202d2001109d081a2003202e20016b222f360294022003202d20016a22303602900202400240202e450d0020032d00a808212d0c010b4100212d200341003a00a8080b200341003a00a808202f202f4100472201490d01200341a8086a20302001109d081a2003202f20016b2231360294022003203020016a22303602900202400240202f450d0020032d00a808212e0c010b4100212e200341003a00a8080b200341003a00a808203120314100472201490d01200341a8086a20302001109d081a2003203120016b2232360294022003203020016a223036029002024002402031450d0020032d00a808212f0c010b4100212f200341003a00a8080b200341003a00a808203220324100472201490d01200341a8086a20302001109d081a2003203220016b2231360294022003203020016a221e36029002024002402032450d0020032d00a80821300c010b41002130200341003a00a8080b200341003a00a808203120314100472201490d01200341a8086a201e2001109d081a2003203120016b2232360294022003201e20016a221e36029002024002402031450d0020032d00a80821310c010b41002131200341003a00a8080b200341003a00a808203220324100472201490d01200341a8086a201e2001109d081a2003203220016b360294022003201e20016a36029002024002402032450d0020032d00a80821320c010b41002132200341003a00a8080b410121010b200341a8086a20034188046a10d60220032d00a808221e4106460d01200341f8066a41026a223320032d00ab083a000020034180086a41086a2234200341bc086a29020037030020034180086a41106a2235200341c4086a290200370300200320032f00a9083b01f8062003200341b4086a29020037038008200341a8086a41086a2236280200211f20032802ac082120200341a8086a20034188046a10d60220032d00a8084106470d040240201e4101470d00201f450d00202010350b024020124101470d00201a450d00201b10350b024020114101470d002014450d00201510350b024020174101470d002018450d00201910350b0240200e4101470d002013450d00201610350b024020094101470d00200c450d00200810350b02402002450d00200a200241c8006c6a2102200a21010340024020012d00004101470d00200141086a280200450d00200141046a28020010350b0240200141246a2d00004101470d002001412c6a280200450d00200141286a28020010350b200141c8006a22012002470d000b0b2007450d03200741c8006c0d020c030b024020124101470d00201a450d00201b10350b024020114101470d002014450d00201510350b024020174101470d002018450d00201910350b0240200e4101470d002013450d00201610350b024020094101470d00200c450d00200810350b02402002450d00200a200241c8006c6a2102200a21010340024020012d00004101470d00200141086a280200450d00200141046a28020010350b0240200141246a2d00004101470d002001412c6a280200450d00200141286a28020010350b200141c8006a22012002470d000b0b2007450d02200741c8006c0d010c020b024020124101470d00201a450d00201b10350b024020114101470d002014450d00201510350b024020174101470d002018450d00201910350b0240200e4101470d002013450d00201610350b024020094101470d00200c450d00200810350b02402002450d00200a200241c8006c6a2102200a21010340024020012d00004101470d00200141086a280200450d00200141046a28020010350b0240200141246a2d00004101470d002001412c6a280200450d00200141286a28020010350b200141c8006a22012002470d000b0b2007450d01200741c8006c450d010b200a10350b200d42ffffff3f83500d0220061035410221010c030b20034190046a41206a2237200341a8086a41206a223828020036020020034190046a41186a2239200341a8086a41186a223a29030037030020034190046a41106a223b200341a8086a41106a223c29030037030020034190046a41086a223d2036290300370300200341f2056a41026a223e20034194076a41026a223f2d00003a0000200341d8056a41086a2240200341c0076a41086a2241290300370300200341d8056a41106a2242200341c0076a41106a2243290300370300200320032903a80837039004200320032f0194073b01f205200320032903c0073703d805200341d4056a41026a2244200341dc076a41026a22452d00003a0000200320032f01dc073b01d405200341b8056a41106a2246200341e0076a41106a2247290300370300200341b8056a41086a2248200341e0076a41086a2249290300370300200320032903e0073703b805200341b4056a41026a224a200341fc076a41026a224b2d00003a0000200320032f01fc073b01b40520034198056a41106a224c20034188066a41106a224d29030037030020034198056a41086a224e20034188066a41086a224f29030037030020032003290388063703980520034194056a41026a2250200341f8056a41026a22512d00003a0000200320032f01f8053b019405200341f8046a41106a2252200341d0066a41106a2253290300370300200341f8046a41086a2254200341d0066a41086a2255290300370300200320032903d0063703f804200341f4046a41026a2256200341b0066a41026a22572d00003a0000200320032f01b0063b01f404200341d8046a41106a225820034198076a41106a2259290300370300200341d8046a41086a225a20034198076a41086a225b29030037030020032003290398073703d804200341d4046a41026a225c20332d00003a0000200320032f01f8063b01d404200341b8046a41106a225d2035290300370300200341b8046a41086a225e203429030037030020032003290380083703b8042003418c046a41026a225f200341f5056a41026a2d00003a0000200320032f00f5053b018c042033203e2d00003a0000200320032f01f2053b01f8062035204229030037030020342040290300370300200320032903d80537038008205720442d00003a0000200320032f01d4053b01b00620592046290300370300205b2048290300370300200320032903b805370398072051204a2d00003a0000200320032f01b4053b01f8052053204c2903003703002055204e29030037030020032003290398053703d006204b20502d00003a0000200320032f0194053b01fc07204d2052290300370300204f2054290300370300200320032903f80437038806204520562d00003a0000200320032f01f4043b01dc07204720582903003703002049205a290300370300200320032903d8043703e007203f205c2d00003a0000200320032f01d4043b0194072043205d2903003703002041205e290300370300200320032903b8043703c00720382037280200360200203a2039290300370300203c203b2903003703002036203d29030037030020032003290390043703a808200341cc066a41026a205f2d00003a0000200320032f018c043b01cc060c020b1045000b410221010b20034184046a41026a200341f8066a41026a2d00003a0000200341e8036a41086a20034180086a41086a290300370300200341e8036a41106a223320034180086a41106a290300370300200341e4036a41026a200341b0066a41026a2d00003a0000200341c8036a41086a20034198076a41086a290300370300200341c8036a41106a223420034198076a41106a290300370300200320032f01f8063b01840420032003290380083703e803200320032f01b0063b01e40320032003290398073703c803200341c4036a41026a200341f8056a41026a2d00003a0000200341a8036a41086a200341d0066a41086a290300370300200341a8036a41106a2235200341d0066a41106a290300370300200341a4036a41026a200341fc076a41026a2d00003a000020034188036a41086a20034188066a41086a29030037030020034188036a41106a223620034188066a41106a290300370300200320032f01f8053b01c403200320032903d0063703a803200320032f01fc073b01a40320032003290388063703880320034184036a41026a200341dc076a41026a2d00003a0000200341e8026a41106a2237200341e0076a41106a290300370300200341e8026a41086a200341e0076a41086a290300370300200341e4026a41026a20034194076a41026a2d00003a0000200341c8026a41106a2238200341c0076a41106a290300370300200341c8026a41086a200341c0076a41086a290300370300200320032f01dc073b018403200320032903e0073703e802200320032f0194073b01e402200320032903c0073703c802200341a0026a41206a2239200341a8086a41206a280200360200200341a0026a41186a223a200341a8086a41186a290300370300200341a0026a41106a223b200341a8086a41106a290300370300200341a0026a41086a200341a8086a41086a290300370300200320032903a8083703a0022003419c026a41026a200341cc066a41026a2d00003a0000200320032f01cc063b019c020240024020014102470d00200341003602880820034201370380082003410936029c072003200341106a36029807200320034180086a3602d006200341bc086a4101360200200342013702ac08200341c888c2003602a808200320034198076a3602b808200341d0066a41e88ac500200341a8086a10431a200335028808422086200335028008841006200328028408450d0120032802800810350c010b2003418c026a41026a223c20034184046a41026a2d00003a0000200341f0016a41086a223d200341e8036a41086a290300370300200341f0016a41106a223e2033290300370300200341ec016a41026a2233200341e4036a41026a2d00003a0000200341d0016a41086a223f200341c8036a41086a290300370300200341d0016a41106a22402034290300370300200320032f0184043b018c02200320032903e8033703f001200320032f01e4033b01ec01200320032903c8033703d001200341cc016a41026a2234200341c4036a41026a2d00003a0000200341b0016a41086a2241200341a8036a41086a290300370300200341b0016a41106a22422035290300370300200341ac016a41026a2235200341a4036a41026a2d00003a000020034190016a41086a224320034188036a41086a29030037030020034190016a41106a22442036290300370300200320032f01c4033b01cc01200320032903a8033703b001200320032f01a4033b01ac012003200329038803370390012003418c016a41026a223620034184036a41026a2d00003a0000200341f0006a41106a22452037290300370300200341f0006a41086a2237200341e8026a41086a290300370300200341ec006a41026a2246200341e4026a41026a2d00003a0000200341d0006a41106a22472038290300370300200341d0006a41086a2238200341c8026a41086a290300370300200320032f0184033b018c01200320032903e802370370200320032f01e4023b016c200320032903c802370350200341286a41206a22482039280200360200200341286a41186a2239203a290300370300200341286a41106a223a203b290300370300200341286a41086a223b200341a0026a41086a290300370300200320032903a002370328200341a8086a41026a22492003419c026a41026a2d00003a0000200320032f019c023b01a8082000200f37030820002010370300200020093a002820002002360224200020073602202000200a36021c2000200d370214200020063602102000200c3602302000200836022c200020032f018c023b00292000412b6a203c2d00003a0000200020032903f0013702342000413c6a203d290300370200200041c4006a203e2903003702002000200e3a004c200041cf006a20332d00003a0000200020032f01ec013b004d2000201336025420002016360250200041e8006a2040290300370200200041e0006a203f290300370200200020032903d001370258200020173a0070200041f3006a20342d00003a0000200020032f01cc013b007120002018360278200020193602742000418c016a204229030037020020004184016a2041290300370200200020032903b00137027c200020113a00940120004197016a20352d00003a0000200020032f01ac013b0095012000201436029c012000201536029801200041b0016a2044290300370200200041a8016a204329030037020020002003290390013702a001200020123a00b801200041bb016a20362d00003a0000200020032f018c013b00b9012000201a3602c0012000201b3602bc01200041d4016a2045290300370200200041cc016a2037290300370200200020032903703702c4012000201e3a00dc01200041df016a20462d00003a0000200020032f016c3b00dd012000201f3602e401200020203602e001200041f8016a2047290300370200200041f0016a2038290300370200200020032903503702e801200041a0026a204828020036020020004198026a203929030037020020004190026a203a29030037020020004188026a203b2903003702002000200329032837028002200041b8026a20323a0000200041b7026a20313a0000200041b6026a20303a0000200041b5026a202f3a0000200041b4026a202e3a0000200041b3026a202d3a0000200041b2026a202c3a0000200041b1026a202b3a0000200041b0026a202a3a0000200041af026a20293a0000200041ae026a20283a0000200041ad026a20273a0000200041ac026a20263a0000200041ab026a20253a0000200041aa026a20243a0000200041a9026a20233a0000200041a8026a20223a0000200041a7026a20213a0000200041a6026a201d3a00002000201c3a00a502200041bb026a20492d00003a0000200041b9026a20032f01a8083b00000b200020013a00a4022005450d00200410350b200341d0086a24000bd90401057f230041106b22022400200241003a000502400240024002400240024020012802002203280204220420044100472205490d00200241056a200328020022062005109d081a2003200420056b3602042003200620056a360200024020040d00410021040c050b024020022d0005220441037122034103460d000240024020030e03070001070b200241003b0106200220043a00064101210420012802002201280204220320034100472205490d04200241066a410172200128020022042005109d0821062001200320056b3602042001200420056a360200024020030d00200620056a22044100200241066a20046b41026a109f081a0b20022f0106220441ff014d0d0220044102762103410021040c070b20024100360208200220043a0008200241086a4101722001280200220428020020042802042205410320054103491b2203109d082106200428020422012003490d042004200120036b3602042004200428020020036a3602000240200541024b0d00200620036a22044100200241086a20046b41046a109f081a0b2002280208220341808004492104200341027621030c060b200441034d0d010b410121040c040b2002410036020c2002410c6a20012802002204280200220120042802042203410420034104491b2205109d081a2004200320056b3602042004200120056a3602000240200341034b0d002002410c6a20056a4100410420056b109f081a0b200228020c22034180808080044921040c030b0c020b2003200141a4f0cb001059000b20044102762103410021040b2000200336020420002004360200200241106a24000b8913010b7f23004180016b22022400200241003a004002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802002203280204220420044100472205490d00200241c0006a200328020022062005109d081a2003200420056b3602042003200620056a360200024020040d00410021062002410d6a2107200241106a2108200241246a21090c140b2002410d6a2107200241106a2108200241246a210920022d0040220a41254b0d0141002106200a0e261301010101010101010101010101010101010101010101010101010101010101010102030405130b200041063a00000c130b0240200a417f6a220441ff01714121490d00200041063a00000c130b024020040d00410121034100210441002105410121060c120b0240200410392203450d002003200128020022012802002001280204220a2004200a2004491b2205109d08210b200128020422062005490d052001200620056b3602042001200128020020056a360200410121060240200a20044f0d00200b20056a22014100200b20046a20016b109f081a0b200421050c120b1045000b200241003a00784100210a02400340200241003a004020012802002203280204220420044100472205490d01200a41016a2106200241c0006a2003280200220b2005109d081a2003200420056b3602042003200b20056a360200024002402004450d0020022d004021040c010b41002104200241003a00400b200241d8006a200a6a20043a0000200220063a00782006210a20064120470d000b200241d6006a20022d005a3a0000200241c8006a200241ef006a290000370300200241d0006a200241f7006a2d00003a0000200220022f01583b0154200220022900673703404100210120022800632104200228005f2105200228005b21030c100b41012101200a41ff01710d040c0e0b200241003a00784100210a02400340200241003a004020012802002203280204220420044100472205490d01200a41016a2106200241c0006a2003280200220b2005109d081a2003200420056b3602042003200b20056a360200024002402004450d0020022d004021040c010b41002104200241003a00400b200241d8006a200a6a20043a0000200220063a00782006210a20064120470d000b200241d6006a20022d005a3a0000200241c8006a200241ef006a290000370300200241d0006a200241f7006a2d00003a0000200220022f01583b0154200220022900673703404100210120022800632104200228005f2105200228005b21030c0d0b41012101200a41ff01710d040c0b0b200241003a00784100210a02400340200241003a004020012802002203280204220420044100472205490d01200a41016a2106200241c0006a2003280200220b2005109d081a2003200420056b3602042003200b20056a360200024002402004450d0020022d004021040c010b41002104200241003a00400b200241d8006a200a6a20043a0000200220063a00782006210a20064120470d000b200241d6006a20022d005a3a0000200241c8006a200241ef006a290000370300200241d0006a200241f7006a2d00003a0000200220022f01583b0154200220022900673703404100210120022800632104200228005f2105200228005b21030c0a0b41012101200a41ff01710d040c080b200241003a00784100210a02400340200241003a004020012802002203280204220420044100472205490d01200a41016a2106200241c0006a2003280200220b2005109d081a2003200420056b3602042003200b20056a360200024002402004450d0020022d004021040c010b41002104200241003a00400b200241d8006a200a6a20043a0000200220063a00782006210a20064120470d000b200241d6006a20022d005a3a0000200241c8006a200241ef006a290000370300200241d0006a200241f7006a2d00003a0000200220022f01583b0154200220022900673703404100210120022800632104200228005f2105200228005b21030c070b41012101200a41ff01710d040c050b2005200641a4f0cb001059000b200241003a00780c090b200241003a00780c060b200241003a00780c030b200241003a00780b0b2002413c6a41026a2206200241d4006a41026a2d00003a0000200241286a41086a220a200241c0006a41086a290300370300200241286a41106a220b200241c0006a41106a2d00003a0000200220022f01543b013c20022002290340370328024020010d00200241246a41026a20062d00003a0000200241106a41086a200a290300370300200241106a41106a200b2d00003a0000200220022f013c3b012420022002290328370310410521060c070b200041063a00000c070b0b2002413c6a41026a2206200241d4006a41026a2d00003a0000200241286a41086a220a200241c0006a41086a290300370300200241286a41106a220b200241c0006a41106a2d00003a0000200220022f01543b013c20022002290340370328024020010d00200241246a41026a20062d00003a0000200241106a41086a200a290300370300200241106a41106a200b2d00003a0000200220022f013c3b012420022002290328370310410421060c050b200041063a00000c050b0b2002413c6a41026a2206200241d4006a41026a2d00003a0000200241286a41086a220a200241c0006a41086a290300370300200241286a41106a220b200241c0006a41106a2d00003a0000200220022f01543b013c20022002290340370328024020010d00200241246a41026a20062d00003a0000200241106a41086a200a290300370300200241106a41106a200b2d00003a0000200220022f013c3b012420022002290328370310410321060c030b200041063a00000c030b0b410221062002413c6a41026a220a200241d4006a41026a2d00003a0000200241286a41086a220b200241c0006a41086a290300370300200241286a41106a220c200241c0006a41106a2d00003a0000200220022f01543b013c20022002290340370328024020010d00200241246a41026a200a2d00003a0000200241106a41086a200b290300370300200241106a41106a200c2d00003a0000200220022f013c3b0124200220022903283703100c010b200041063a00000c010b200020063a0000200020092f00003b00012000410c6a2004360000200041086a2005360000200041046a2003360000200041106a2008290000370000200041216a20072f00003b0000200041036a200941026a2d00003a0000200041186a200841086a290000370000200041206a200841106a2d00003a0000200041236a200741026a2d00003a00000b20024180016a24000bb10201017f230041a0016b220324002003200236020420032001360200200341086a2002ad4220862001ad84100510c20102400240200328020822010d00200041003602400c010b200328020c21022003200341106a28020036027c20032001360278200341186a200341f8006a10c7020240024020032802580d002003410036028801200342013703800120034109360294012003200336029001200320034180016a36029c012003412c6a41013602002003420137021c200341c888c200360218200320034190016a3602282003419c016a41e88ac500200341186a10431a2003350288014220862003350280018410060240200328028401450d0020032802800110350b200041003602400c010b2000200341186a41e000109d081a0b2002450d00200110350b200341a0016a24000b8b06010d7f23004190016b220224002002412036021420022001360210200241186a2001ad4280808080800484100510c2010240024002400240200228021822030d00200041003602000c010b200228021c21042002200241206a28020036022c20022003360228200241086a200241286a10c4010240024020022802080d00200228020c2205200228022c22064105762201200120054b1b22014105742207417f4c0d030240024020010d00410121080c010b200710332208450d050b41002109200241003602402002200136023c20022008360238024002402005450d004100210a03402006210b41002101200241003a008801200a41016a210a0340200b2001460d03200241e8006a20016a200228022822072d00003a00002002200741016a3602282002200141016a22073a0088012007210120074120470d000b200241c8006a41186a220c200241e8006a41186a290300370300200241c8006a41106a220d200241e8006a41106a290300370300200241c8006a41086a220e200241e8006a41086a2903003703002002200229036837034802402009200228023c470d00200241386a20094101108a0120022802382108200228024021090b200b20076b2106200820094105746a22012002290348370000200141186a200c290300370000200141106a200d290300370000200141086a200e2903003700002002200941016a2209360240200a2005470d000b2002200b20076b36022c0b2008450d012000200229023c370204200020083602000c020b2002410036022c0240200141ff0171450d00200241003a0088010b200228023c41ffffff3f71450d00200810350b20024100360250200242013703482002410936023c2002200241106a3602382002200241c8006a360234200241fc006a41013602002002420137026c200241c888c2003602682002200241386a360278200241346a41e88ac500200241e8006a10431a200235025042208620023502488410060240200228024c450d00200228024810350b200041003602000b2004450d00200310350b20024190016a24000f0b1044000b1045000bb80c07057f017e067f017e037f027e017f23004190016b220324002003200236021420032001360210200341186a2002ad4220862001ad84100510c20102400240200328021822040d00200041023a00000c010b200328021c21052003200341206a280200220236023c20032004360238024002402002450d0020042d0000210120032002417f6a36023c2003200441016a360238200141014b0d00024002400240024002400240024020010e020001000b200341086a200341386a10c40120032802080d06200328023c2206200328020c2201490d062001417f4c0d030240024020010d0041002102410121070c010b200110392207450d052007200328023822022001109d081a2003200620016b220636023c2003200220016a360238200121020b2007450d062001ad4220862002ad842208a7210902400240024002400240024020064104490d002008422088a7210a2003280238220b280000210c20032006417c6a220d36023c2003200b41046a36023841002101200341003a008801417b210202400340200d2001460d01200341e8006a20016a200b20016a220e41046a2d00003a00002003200620026a36023c2003200e41056a3602382003200141016a220e3a0088012002417f6a2102200e2101200e4120470d000b2003200328006b3600432003200328026836024020032003280240360250200320032800433600532006200e6b2201417c6a4110490d06200341f7006a2900002108200329006f210f200328007f2102200328008301210d20032d00870121102003200b200e6a221141146a221236023820032001416c6a220b36023c200b4104490d042011410c6a2900002113201141046a29000021142012280000210b2003200141686a36023c2003201141186a2212360238200641686a200e460d0520122d000021122003200141676a221536023c2003201141196a360238201241014b0d054100210e20120e020302030b0240200141ff0171450d00200341003a0088010b2009450d0c0c0b0b2009450d0b200710350c0b0b20154104490d02201141196a28000021062003200141636a36023c20032011411d6a3602384101210e0b2003200328005336006320032003280250360260200320032802603602282003200328006336002b200320032800593602302003200341dc006a280000360033410021010c040b2009450d08200710350c080b2009450d07200710350c070b20090d050c060b41002101200341003a0088012002417f6a21062002417e6a2102034020062001460d02200341e8006a20016a200420016a220e41016a2d00003a00002003200e41026a3602382003200141016a220e3a0088012003200236023c2002417f6a2102200e2101200e4120470d000b2003200328006b3600432003200328026836024020032003280043360053200320032802403602502003200328025036026020032003280053360063200341f7006a2900002113200329006f2114200328007f2107200328008301210920032d008701210a20032003280063360033200320032802603602302003200341dc006a28000036002b20032003280059360228410121010b2003200328003336006b20032003280230360268200320032802283602402003200328002b360043200041106a2013370000200041086a2014370000200041046a200328006b36000020002003280268360001200041306a20063600002000412c6a200e360000200041286a200b360000200041246a200c360000200041206a200a3600002000411c6a2009360000200041186a2007360000200041c3006a20083700002000413b6a200f370000200041d3006a20103a0000200041cf006a200d360000200041cb006a2002360000200041346a2003280240360000200041376a20032800433600000c050b200141ff0171450d03200341003a0088010c030b1044000b1045000b200710350b2003410036024820034201370340200341093602542003200341106a3602502003200341c0006a360260200341fc006a41013602002003420137026c200341c888c2003602682003200341d0006a360278200341e0006a41e88ac500200341e8006a10431a2003350248422086200335024084100602402003280244450d00200328024010350b410221010b200020013a00002005450d00200410350b20034190016a24000bf30201047f230041d0016b220224002002412036020420022001360200200241086a2001ad4280808080800484100510c20102400240200228020822010d00200041023a0088010c010b200228020c21032002200241106a2802003602ac01200220013602a801200241186a200241a8016a10db020240024020022d00a00122044102470d00200241003602b801200242013703b001200241093602c401200220023602c0012002200241b0016a3602cc012002412c6a41013602002002420137021c200241c888c2003602182002200241c0016a360228200241cc016a41e88ac500200241186a10431a20023502b80142208620023502b00184100620022802b401450d0120022802b00110350c010b2000200241186a418801109d0821052002200241186a418c016a2800003600b301200220022800a1013602b0012005418c016a20022800b301360000200520022802b001360089010b200020043a0088012003450d00200110350b200241d0016a24000bfe0703057f0e7e067f230041106b21020240200128020422034104490d0020012802002204280000210520012003417c6a22063602042001200441046a36020020064108490d00200429000421072001200341746a220636020420012004410c6a36020020064108490d00200429000c210820012003416c6a22063602042001200441146a36020020064108490d00200429001421092001200341646a220636020420012004411c6a36020020064108490d00200429001c210a20012003415c6a22063602042001200441246a36020020064108490d002004290024210b2001200341546a220636020420012004412c6a36020020064108490d00200429002c210c20012003414c6a22063602042001200441346a36020020064108490d002004290034210d2001200341446a220636020420012004413c6a36020020064108490d00200429003c210e2001200341bc7f6a22063602042001200441c4006a36020020064108490d002004290044210f2001200341b47f6a22063602042001200441cc006a36020020064108490d00200429004c21102001200341ac7f6a22063602042001200441d4006a36020020064108490d00200429005421112001200341a47f6a22063602042001200441dc006a36020020064108490d00200429005c211220012003419c7f6a22063602042001200441e4006a36020020064108490d00200429006421132001200341947f6a22063602042001200441ec006a36020020064108490d00200429006c211420012003418c7f6a22063602042001200441f4006a36020020064104490d00200428007421152001200341887f6a22063602042001200441f8006a36020020064104490d00200428007821162001200341847f6a22063602042001200441fc006a36020020064104490d00200428007c21172001200341807f6a2206360204200120044180016a36020020064104490d0020042800800121182001200341fc7e6a2206360204200120044184016a22043602002006450d0020042d000021062001200341fb7e6a22193602042001200441016a360200200641014b0d004100211a0240024020060e020100010b4101211a0b20194104490d00200428000121062001200341f77e6a3602042001200441056a3602002000201a3a008801200020063602840120002018360280012000201736027c20002016360278200020153602742000200536027020002014370368200020133703602000201237035820002011370350200020103703482000200f3703402000200e3703382000200d3703302000200c3703282000200b3703202000200a3703182000200937031020002008370308200020073703002000418c016a2002410c6a28000036000020002002280009360089010f0b200041023a0088010b8b0a040a7f017e037f037e23004180026b220224002002412036020c20022001360208200241106a2001ad4280808080800484100510c2010240024002400240200228021022030d00200041003602000c010b200228021421042002200241186a280200360224200220033602202002200241206a10c4010240024020022802000d0020022802042205200228022422064106762201200120054b1b22014106742207417f4c0d030240024020010d00410821080c010b200710332208450d050b41002109200241003602302002200136022c200220083602280240024002402005450d004100210a03400240024002402006450d0020022002280220220b41016a3602202006417f6a2107200b2d0000220141014b0d054200210c20010e020201020b200241003602240c050b41002101200241003a00f8012006417f6a210d024002400240024002400340200d2001460d01200241d8016a20016a200b20016a220741016a2d00003a00002002200741026a3602202002200141016a22073a00f8012007210120074120470d000b200241b8016a41186a220d200241d8016a41186a290300370300200241b8016a41106a220e200241d8016a41106a290300370300200241b8016a41086a220f200241d8016a41086a290300370300200220022903d8013703b8012007417f7320066a4110490d022002200b20076a220141116a220b360220200620076b2207416f6a41074b0d012007416f6a21010c030b0240200141ff0171450d00200241003a00f8010b410021010c020b200141096a2900002110200141016a29000021112002200141196a360220200b2900002212428002540d02200741676a21010c010b2007417f7320066a21010b200241f8006a41086a20024198016a41086a290300370300200241f8006a41106a20024198016a41106a2903003703002002200229039801370378200220013602240c050b200741676a2107200241f8006a41086a200f290300220c370300200241d8006a41186a200d290300370300200241d8006a41106a200e290300370300200241d8006a41086a200c370300200220022903b801220c3703782002200c3703584201210c0b200a41016a210a200241386a41186a220b200241d8006a41186a290300370300200241386a41106a220d200241d8006a41106a290300370300200241386a41086a2206200241d8006a41086a2903003703002002200229035837033802402009200228022c470d00200241286a200910940120022802282108200228023021090b200820094106746a220120113703082001200c370300200141106a2010370300200141186a2012370300200141206a2002290338370300200141286a2006290300370300200141306a200d290300370300200141386a200b2903003703002002200941016a220936023020072106200a2005470d000b200220073602240b2008450d022000200229022c370204200020083602000c030b200220073602240b200228022c41ffffff1f71450d00200810350b200241003602c001200242013703b8012002410936029c012002200241086a360298012002200241b8016a360278200241ec016a4101360200200242013702dc01200241c888c2003602d801200220024198016a3602e801200241f8006a41e88ac500200241d8016a10431a20023502c00142208620023502b801841006024020022802bc01450d0020022802b80110350b200041003602000b2004450d00200310350b20024180026a24000f0b1044000b1045000b980704057f017e087f037e230041a0016b220224002002412036020c20022001360208200241106a2001ad4280808080800484100510c2010240024002400240200228021022030d00200041003602000c010b200228021421042002200241186a280200360224200220033602202002200241206a10c4010240024020022802000d00200228020422052002280224220641286e2201200120054b1bad42287e2207422088a70d032007a72201417f4c0d030240024020010d00410821080c010b200110332208450d050b4100210920024100360230200220083602282002200141286e36022c02400240024002402005450d004100210a034041002101200241003a009801200a41016a210a034020062001460d03200241f8006a20016a2002280220220b2d00003a00002002200b41016a3602202002200141016a220c3a009801200c2101200c4120470d000b200241d8006a41186a2201200241f8006a41186a290300370300200241d8006a41106a220d200241f8006a41106a290300370300200241d8006a41086a220e200241f8006a41086a290300370300200220022903783703582006200c6b220c4108490d03200241386a41086a220f200e290300370300200241386a41106a220e200d290300370300200241386a41186a220d2001290300370300200220022903583703382002200b41096a360220200b290001210702402009200228022c470d00200241286a20094101108f0120022802282108200228023021090b200c41786a21062008200941286c6a22012002290338370300200f2903002110200e2903002111200d290300211220012007370320200141186a2012370300200141106a2011370300200141086a20103703002002200941016a2209360230200a2005470d000b2002200c41786a3602240b2008450d032000200229022c370204200020083602000c040b20024100360224200141ff0171450d01200241003a0098010c010b2002200c3602240b200228022c2201450d00200141286c450d00200810350b20024100360260200242013703582002410936023c2002200241086a3602382002200241d8006a3602282002418c016a41013602002002420137027c200241c888c2003602782002200241386a36028801200241286a41e88ac500200241f8006a10431a200235026042208620023502588410060240200228025c450d00200228025810350b200041003602000b2004450d00200310350b200241a0016a24000f0b1044000b1045000bd304010a7f230041e0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100510c20102400240200328021022010d00200041003602080c010b200328021421042003200341186a28020022023602242003200136022002400240024020024104490d002003200141046a36022020032002417c6a220536022420054104490d00200128000021062003200241786a3602242003200141086a36022020012800042107200341c8006a200341206a10c30120032802482202450d00200341c8006a41086a2802002108200328024c2105200341c8006a200341206a10c3010240024020032802482209450d00200328024c210a2003280224220b41044f0d030240200a41ffffff3f71450d00200910350b200541ffffff3f710d010c020b200541ffffff3f71450d010b200210350b20034100360230200342013703282003410936023c2003200341086a3602382003200341286a360244200341dc006a41013602002003420137024c200341c888c2003602482003200341386a360258200341c4006a41e88ac500200341c8006a10431a200335023042208620033502288410060240200328022c450d00200328022810350b200041003602080c010b200341d0006a280200210c2000200536020c200020023602082000200736020420002006360200200041206a200328022022022800003602002000411c6a200c360200200041186a200a360200200041146a2009360200200041106a20083602002003200b417c6a3602242003200241046a3602200b2004450d00200110350b200341e0006a24000be70804067f027e077f027e230041e0016b220324002003200236020420032001360200200341086a2002ad4220862001ad84100510c20102400240200328020822040d00200042003703000c010b200341106a2802002105200328020c210641002101200341003a00d801200541706a21070240024002400240034020052001460d01200341b8016a20016a200420016a2d00003a00002003200141016a22023a00d8012007417f6a21072002210120024120470d000b200341d8006a41086a200341b8016a41086a290300370300200341d8006a41106a200341b8016a41106a290300370300200341d8006a41186a200341b8016a41186a290300370300200320032903b801370358200520026b22084110490d02200420026a22052900002109200541086a290000210a41002101200341003a00d801200841706a2108034020082001460d02200341b8016a20016a200520016a41106a2d00003a00002003200141016a22023a00d8012002210120024120470d000b200341f8006a41086a220b200341b8016a41086a2201290300370300200341f8006a41106a220c200341b8016a41106a2208290300370300200341f8006a41186a220d200341b8016a41186a220e290300370300200320032903b801370378200720026b410f4d0d02200341386a41086a2207200341d8006a41086a290300370300200341386a41106a220f200341d8006a41106a290300370300200341386a41186a2210200341d8006a41186a290300370300200341186a41086a2211200b290300370300200341186a41106a220b200c290300370300200341186a41186a220c200d2903003703002003200329035837033820032003290378370318200520026a220241106a2900002112200241186a2900002113200120072903003703002008200f290300370300200e201029030037030020034198016a41086a2202201129030037030020034198016a41106a2207200b29030037030020034198016a41186a2205200c290300370300200320032903383703b8012003200329031837039801200041206a2013370300200041186a2012370300200041106a200a37030020002009370308200041286a20032903b801370300200041306a2001290300370300200041386a2008290300370300200041c0006a200e290300370300200041c8006a200329039801370300200041d0006a2002290300370300200041d8006a2007290300370300200041e0006a2005290300370300420121090c030b200141ff0171450d01200341003a00d8010c010b200141ff0171450d00200341003a00d8010b200341003602a00120034201370398012003410936027c20032003360278200320034198016a360258200341cc016a4101360200200342013702bc01200341c888c2003602b8012003200341f8006a3602c801200341d8006a41e88ac500200341b8016a10431a20033502a0014220862003350298018410060240200328029c01450d0020032802980110350b420021090b200020093703002006450d00200410350b200341e0016a24000ba30303037f017e027f230041e0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100510c2010240024002400240200328021022010d00200041003602000c010b200328021421022003200341186a280200360224200320013602202003200341206a10c40102400240024020032802000d002003280224220420032802042205490d002005417f4c0d040240024020050d0042002106410121070c010b200510392207450d062007200328022022082005109d081a2003200420056b3602242003200820056a3602202005ad21060b20070d010b20034100360230200342013703282003410936023c2003200341086a3602382003200341286a360244200341dc006a41013602002003420137024c200341c888c2003602482003200341386a360258200341c4006a41e88ac500200341c8006a10431a200335023042208620033502288410060240200328022c450d00200328022810350b200041003602000c010b200020062005ad42208684370204200020073602000b2002450d00200110350b200341e0006a24000f0b1044000b1045000b990204017f017e017f017e230041d0006b220224002002412036020420022001360200200241086a2001ad4280808080800484100510c20102400240200228020822010d00420021030c010b200228020c210402400240200241086a41086a2802004108490d0020012900002105420121030c010b20024100360220200242013703182002410936022c200220023602282002200241186a360234200241cc006a41013602002002420137023c200241c888c2003602382002200241286a360248200241346a41e88ac500200241386a10431a200235022042208620023502188410060240200228021c450d00200228021810350b420021030b2004450d00200110350b2000200537030820002003370300200241d0006a24000bb20403037f027e057f230041e0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad84100510c20102400240200328021022010d00200041003602140c010b200328021421042003200341186a28020022023602242003200136022002400240024020024104490d002003200141046a36022020032002417c6a220536022420054110490d002001280000210520032002416c6a3602242003200141146a3602202001410c6a290000210620012900042107200341c8006a200341206a10c30120032802482202450d00200328024c21082003280224220941024f0d01200841ffffff3f71450d00200210350b20034100360230200342013703282003410936023c2003200341086a3602382003200341286a360244200341dc006a41013602002003420137024c200341c888c2003602482003200341386a360258200341c4006a41e88ac500200341c8006a10431a200335023042208620033502288410060240200328022c450d00200328022810350b200041003602140c010b200341d0006a280200210a200341386a41046a200341286a41046a2f0100220b3b010020032003280128220c36023820032009417e6a36022420032003280220220941026a36022020092f000021092000200637030820002007370300200041206a20093b01002000411c6a200a3602002000200836021820002002360214200020053602102000200c360122200041266a200b3b01000b2004450d00200110350b200341e0006a24000be70203017f017e017f23004190056b22032400200320023602b402200320013602b002200341b8026a2002ad4220862001ad842204100510c2010240024020032802b80222010d00411b21010c010b20032802bc0221052003200341c0026a2802003602fc04200320013602f804200341c8026a200341f8046a10b9020240024020032802c8022202411b470d00200341003602082003420137030020034109360284052003200341b0026a360280052003200336028c05200341dc026a4101360200200342013702cc02200341c888c2003602c802200320034180056a3602d8022003418c056a41e88ac500200341c8026a10431a200335020842208620033502008410062003280204450d01200328020010350c010b2003200341c8026a41047241ac02109d081a0b02402005450d00200110350b411b21012002411b460d0020041007200221010b20002001360200200041046a200341ac02109d081a20034190056a24000b9b0203017f017e017f230041d0006b220224002002200136020420022000360200200241086a2001ad4220862000ad842203100510c20102400240200228020822010d00410321000c010b200228020c210402400240200241106a280200450d0020012d000022004103490d010b20024100360220200242013703182002410936022c200220023602282002200241186a360234200241cc006a41013602002002420137023c200241c888c2003602382002200241286a360248200241346a41e88ac500200241386a10431a200235022042208620023502188410060240200228021c450d00200228021810350b02402004450d00200110350b410321000c010b02402004450d00200110350b200310070b200241d0006a240020000bb10503027f017e047f230041d0006b2202240041a0e4cb00ad4280808080800284100122032900002104200241086a41086a200341086a29000037030020022004370308200310354190eaca00ad4280808080e00084100122032900002104200241186a41086a200341086a29000037030020022004370318200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad42808080808004841003220129000037033820011035200241cc006a200341206a360200200220033602482002200241386a41086a3602442002200241386a360240200241286a200241c0006a107b200310352002280230220541206a2201417f4c0d01200228022821060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a2000200136020820002008360204200020033602000240200228022c450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000b8e280b037f027e037f047e027f017e027f087e017f027e087f230041f0086b22062400200620043703402006200337033820062001360234200620053a004f024002400240024020012002460d002003200484500d0020012002412010a008450d00200641d0006a2002108e02200641e0006a2006280250220720062802582208108f02200629036021094200210a20064200370360200641a8016a280200210b20062d00ac01210c024002402009420151220d0d00200641b0016a41386a4200370300200641b0016a41306a4200370300200641b0016a41286a4200370300200641d0016a4200370300200641b0016a41186a4200370300200641c0016a4200370300200641b8016a4200370300200642003703b0014200210e4200210f420021100c010b200641e0006a41386a2903002103200641e0006a41306a2903002104200641e0006a41206a290300210e200641e0006a41186a290300210a200641a0016a2903002111200629037021102006290368210f200641d0016a200641e0006a41286a290300370300200641b0016a41286a2004370300200641b0016a41306a2003370300200641c0016a200a3703002006200e3703c801200620113703e8012006200f3703b001200620103703b8010b200641f0036a20062802342212108e0220064180046a20062802f003221320062802f8032201108f022006290380042114420021032006420037038004200641c8046a280200211520062d00cc04211602400240201442015122050d00200641d0046a41306a4200370300200641d0046a41286a4200370300200641d0046a41206a4200370300200641d0046a41186a4200370300200641d0046a41106a4200370300200641d8046a4200370300200642003703d004420021044200211742002118420021190c010b200641b8046a290300211120064180046a41306a290300211a20064180046a41206a290300211820064180046a41186a2903002117200641c0046a290300211920062903900421042006290388042103200641d0046a41206a20064180046a41286a290300370300200641d0046a41286a201a370300200641d0046a41306a2011370300200641d0046a41106a2017370300200620183703e804200620033703d004200620043703d8040b0240024020032006290338221b7d221a2003562004200641386a41086a290300221c7d2003201b54ad7d221120045620112004511b450d00419089c20021054280808080b00221114180800c21010c010b2006201a3703d004200620113703d804024020062903b001221d201b7c221e201d54221f200641b0016a41086a2903002220201c7c201fad7c221d202054201d2020511b450d0041a7d6ca0021054280808080800121114180800821010c010b2006201e3703b001200641c8016a29030021202006201d3703b8010240427f201e20062903c0017c22212021201e54221f201d20207c201fad7c2220201d542020201d511b221f1b428080e983b1de16544100427f2020201f1b501b450d0041fe88c20021054280808080a00221114180801021010c010b0240201b201c84500d0020064188056a2006280234108e02200641c0076a2006280288052222200628029005108f02200641f0076a290300420020062903c007420151221f1b211b200641e8076a2903004200201f1b211d0240200628028c05450d00202210350b201d201a56201b201156201b2011511b450d004180800421014280808080d002211141a389c20021050c010b0240024020062d004f4101460d00201a428080e983b1de165441002011501b0d010c040b20064188056a2006280234108e02200641c0076a200628028805221f200628029005108f0220062d008c08212220062903c007211b0240200628028c05450d00201f10350b201a42ffffe883b1de165620114200522011501b0d03201b4201520d03202241ff0171450d030b41f588c20021054280808080900121114180801421010b20014180801c7141830c7221152005ad220342088842ff018321042011200384428080fcffff0383211b4101211f0c020b200041043a00000c020b20064188056a41186a200641d0046a41186a290300221b37030020064188056a41206a2222200641d0046a41206a29030037030020064188056a41286a2223200641d0046a41286a29030037030020064188056a41306a2224200641d0046a41306a290300370300200620062903e004221d370398052006201a370388052006201137039005427f200320177c221c201c200354221f200420187c201fad7c220320045420032004511b221f1b427f2003201f1b8450212502400240427f201a201d7c22032003201a54221f2011201b7c201fad7c220320115420032011511b221f1b2204428080e983b1de16544100427f2003201f1b2203501b0d0020064198056a29030021042024290300211d2023290300211c20222903002117200629039005211820062903880521204201211b20062903a005211e0c010b02400240200420038450450d004200211b0c010b4200211b200641c0076a41186a22264200370300200641c0076a41106a22234200370300200641c0076a41086a22224200370300200642003703c00741b6fdc600ad4280808080800184221d10012224290000211c200641e0086a41086a221f202441086a2900003703002006201c3703e008202410352022201f290300370300200620062903e0083703c00741e489c200ad4280808080d00184221c100122242900002117201f202441086a290000370300200620173703e00820241035202320062903e0082217370300200641c0086a41086a22272022290300370300200641c0086a41106a22282017370300200641c0086a41186a2229201f290300370300200620062903c0073703c008200641186a200641c0086a412010d701200641186a41106a29030021172006290320211820062802182124202642003703002023420037030020224200370300200642003703c007201d10012226290000211d201f202641086a2900003703002006201d3703e008202610352022201f290300370300200620062903e0083703c007201c10012226290000211d201f202641086a2900003703002006201d3703e00820261035202320062903e008221d370300202720222903003703002028201d3703002029201f290300370300200620062903c0073703c008200642002017420020241b221d20037d2018420020241b221c200454ad7d2217201c20047d2218201c562017201d562017201d511b221f1b3703c807200642002018201f1b3703c007200641c0086aad4280808080800484200641c0076aad42808080808002841002200641f8076a2003370300200641f0076a2004370300202241013a0000200641c9076a2012290000370000200641d1076a201241086a290000370000200641d9076a201241106a290000370000200641e1076a201241186a290000370000200641033a00c00741b0b4cc004100200641c0076a10d4010b0b2025ad2103200641a8046a2017370300200641b0046a201c37030020064190046a2018370300200641b8046a201d37030020064198046a20043703002006201e3703a004200620193703c0042006202037038804420121044100211f200620164100201442015122221b3a00cc0420062015410020221b3602c8042006201b4201512215ad37038004024020150d002001ad4220862013ad841007420021044200211b0c010b200620013602c407200620133602c00720064188046a200641c0076a10e7024200211b0b024020062802f403450d00201310350b200641b0016a41106a210102400240201f0d00024002400240200541ff017122050d0020044200510d0041032115200641c0066a21050c010b2005450d0120044200520d0141042115200641c0056a21050b200541086a20153a0000200541003a0000200541096a2012290000370000200541116a201241086a290000370000200541196a201241106a290000370000200541216a201241186a29000037000041b0b4cc004100200510d4010b410421154100210520034201520d01200641f8076a2011370300200641f0076a201a37030041002105200641c0076a41086a41003a0000200641c9076a2012290000370000200641d1076a201241086a290000370000200641d9076a201241106a290000370000200641e1076a201241186a290000370000200641033a00c00741b0b4cc004100200641c0076a10d4010c010b20044208862005ad42ff018384201b842103201541807e7121050b200641c0056a41086a2212200141086a290300370300200641c0056a41106a221f200141106a290300370300200641c0056a41186a2213200141186a290300370300200641c0056a41206a2216200141206a290300370300200620012903003703c005200641b0016a41086a290300210420062903b001211102400240201541ff017122014104460d0020034280807c83211a200342088842ff01832110200520017221012003a7210d410121050c010b20062903e801211a200641c0066a41186a2012290300221b370300200641c0066a41206a201f290300370300200641e8066a22052013290300370300200641f0066a22152016290300370300200620062903c00522143703d006200620113703c006200620043703c806427f200f200a7c22032003200f5422012010200e7c2001ad7c220320105420032010511b22011b427f200320011b8450211202400240427f201120147c2203200320115422012004201b7c2001ad7c220320045420032004511b22011b2210428080e983b1de16544100427f200320011b2203501b0d00200641d0066a29030021102015290300211b2005290300210a200641e0066a290300210f20062903c806211420062903c006210e4201211d20062903d806211c0c010b02400240201020038450450d004200211d0c010b4200211d200641c0076a41186a22134200370300200641c0076a41106a22154200370300200641c0076a41086a22054200370300200642003703c00741b6fdc600ad4280808080800184221b1001221f290000210a200641e0086a41086a2201201f41086a2900003703002006200a3703e008201f103520052001290300370300200620062903e0083703c00741e489c200ad4280808080d00184220a1001221f290000210f2001201f41086a2900003703002006200f3703e008201f1035201520062903e008220f370300200641c0086a41086a22162005290300370300200641c0086a41106a2222200f370300200641c0086a41186a22252001290300370300200620062903c0073703c0082006200641c0086a412010d701200641106a290300210f200629030821142006280200211f201342003703002015420037030020054200370300200642003703c007201b10012213290000211b2001201341086a2900003703002006201b3703e0082013103520052001290300370300200620062903e0083703c007200a10012213290000211b2001201341086a2900003703002006201b3703e00820131035201520062903e008221b370300201620052903003703002022201b37030020252001290300370300200620062903c0073703c00820064200200f4200201f1b221b20037d20144200201f1b220a201054ad7d220f200a20107d2214200a56200f201b56200f201b511b22011b3703c80720064200201420011b3703c007200641c0086aad4280808080800484200641c0076aad42808080808002841002200641f8076a2003370300200641f0076a2010370300200541013a0000200641c9076a2002290000370000200641d1076a200241086a290000370000200641d9076a200241106a290000370000200641e1076a200241186a290000370000200641033a00c00741b0b4cc004100200641c0076a10d4010b0b2012ad210320064188016a200f37030020064190016a200a370300200641f0006a201437030020064198016a201b370300200641f8006a20103703002006201c370380012006201a3703a0012006200e37036842012110410021052006200c4100200942015122011b3a00ac012006200b410020011b3602a8012006201d4201512201ad370360024020010d002008ad4220862007ad841007420021104200211a0c010b200620083602c407200620073602c007200641e8006a200641c0076a10e7024200211a0b02402006280254450d00200710350b02400240024020050d00024002400240200d41ff017122010d0020104200510d0041032105200641f0026a21010c010b2001450d0120104200520d0141042105200641f0016a21010b200141086a20053a0000200141003a0000200141096a2002290000370000200141116a200241086a290000370000200141196a200241106a290000370000200141216a200241186a29000037000041b0b4cc004100200110d4010b20034201520d01200641f8076a2004370300200641f0076a2011370300200641c0076a41086a41003a0000200641c9076a2002290000370000200641d1076a200241086a290000370000200641d9076a200241106a290000370000200641e1076a200241186a290000370000200641033a00c00741b0b4cc004100200641c0076a10d4010c010b200141ff01714104470d010b200628023421012006290338210320064198086a200641386a41086a29030037030020064190086a2003370300200641c0076a41086a41023a0000200641c9076a2001290000370000200641d1076a200141086a290000370000200641d9076a200141106a290000370000200641e1076a200141186a290000370000200641e9076a2002290000370000200641f1076a200241086a290000370000200641f9076a200241106a29000037000020064181086a200241186a290000370000200641033a00c00741b0b4cc004100200641c0076a10d401200041043a00000c010b2000200141087622023b0001200020013a0000200041036a20024110763a0000200041046a2010420886200dad42ff018384201a843700000b200641f0086a24000bfd0102027f027e200028024021020240410410332203450d002003200236000020002d0044210220034104410810372203450d00200320023a0004200041086a29030021042000290300210520034108411510372203450d00200320053700052003410d6a2004370000200041186a29030021042000290310210520034115412a10372203450d00200320053700152003411d6a2004370000200041286a2903002104200029032021052003412a41d40010372203450d00200320053700252003412d6a2004370000200320002903303700352003413d6a200041386a29030037000020012902002003ad4280808080d008841002200310350f0b103c000b830404047f017e037f027e230041d0006b22012400200141206a41186a4200370300200141206a41106a22024200370300200141206a41086a220342003703002001420037032041a0e4cb00ad42808080808002841001220429000021052003200441086a29000037030020012005370320200410354189eaca00ad4280808080f00084100122042900002105200141c0006a41086a2206200441086a2900003703002001200537034020041035200220012903402205370300200141086a2003290300370300200141106a2005370300200141186a200629030037030020012001290320370300200141206a200110a20220012802202103200129022421052001410036022820014201370320200141206a41002005420020031b2205422088a7220441306c220641306d108a012005a721072003410820031b21082001280228210202402004450d00200128022020024105746a2103200821040340200441086a2900002105200441106a29000021092004290000210a200341186a200441186a290000370000200341106a2009370000200341086a20053700002003200a370000200241016a2102200341206a2103200441306a2104200641506a22060d000b0b2001200236022802402007450d00200741306c450d00200810350b20002001290320370200200041086a200141206a41086a280200360200200141d0006a24000b8d0303047f017e027f230041d0006b22012400200141206a41186a4200370300200141206a41106a22024200370300200141206a41086a220342003703002001420037032041a0e4cb00ad42808080808002841001220429000021052003200441086a29000037030020012005370320200410354189eaca00ad4280808080f00084100122042900002105200141c0006a41086a2206200441086a2900003703002001200537034020041035200220012903402205370300200141086a2003290300370300200141106a2005370300200141186a200629030037030020012001290320370300200141206a200110a20220012802202204410820041b2107410021030240024002402001290224420020041b2205422088a7220441014b0d0020040e020201020b03402004410176220220036a220620032007200641306c6a2000412010a0084101481b2103200420026b220441014b0d000b0b2007200341306c6a2000412010a0084521030b02402005a72204450d00200441306c450d00200710350b200141d0006a240020030bc00c07027f017e027f017e087f057e017f230022042105200441a0016b4160712204240002402002200384500d002000290000210620044180016a200110eb022004280280012107200428028401210842012109024002400240200428028801220a450d002007200a410574220a6a210b200a41406a210c200441e0006a41106a210d200441e0006a41196a210e2007210a02400340200441c0006a41106a220f200a41106a290300370300200441c0006a41086a2210200a41086a2903003703002004200a290300370340200a41186a2d000021112004200a41196a2800003602282004200a411c6a28000036002b20114103460d02200d200f290300370300200441e0006a41086a2010290300370300200e2004280228360000200e41036a200428002b36000020042004290340370360200420113a00780240024002400240200d2000460d00200d2900002000290000510d002004200e2800003602582004200e41036a28000036005b200441e8006a290300211220042903602113200429037021140c010b2009a7210f200441033a0098012004290390012106200429038001211520042903880121162004290398012109200f41ff01714103460d01200441e8006a2903002212200320042903602213200256201220035620122003511b220d1b211220132002200d1b2113201141022011200f41ff0171461b21112004290370211420152102201621030b2004200428005b36003320042004280258360230200420042802303602382004200428003336003b0240412010332217450d0020172013370300201720113a00182017201437031020172004280238360019201720123703082017411c6a200428003b360000200442818080801037021c20042017360218200c4160460d02200a41206a210a200441e0006a41106a210f200441e0006a41196a21104101210e0340200441c0006a41106a220d200a41106a290300370300200441c0006a41086a220b200a41086a2903003703002004200a290300370340200a41186a2d000021112004200a41196a2800003602282004200a411c6a28000036002b20114103460d03200f200d290300370300200441e0006a41086a220d200b29030037030020102004280228360000201041036a220b200428002b36000020042004290340370360200420113a0078024002400240200f2000460d00200f2900002000290000510d00200420102800003602582004200b28000036005b200d2903002112200429036021132004290370211420022115200321160c010b2009a7210b200441033a00980120042903900121062004290380012115200429038801211620042903980121090240200b41ff0171220b4103460d00200d2903002212200320042903602213200256201220035620122003511b220d1b211220132002200d1b2113201141022011200b461b2111200429037021140c010b200c450d070c010b2004200428005b36003320042004280258360230200420042802303602382004200428003336003b2004200428003b3600830120042004280238360280010240200e200428021c470d00200441186a200e410110a101200428021821170b2017200e4105746a220d20113a0018200d2014370310200d200428028001360019200d411c6a200428008301360000200d2012370308200d20133703002004200e41016a220e360220200c450d060b200a41206a210a200c41606a210c20152102201621030c000b0b1045000b200c41606a210c2015210220162103200a41206a220a200b470d010c040b0b20022115200321160b0240200841ffffff3f71450d00200710350b20044180016a41086a200441186a41086a28020036020020042004290318370380010c020b20022115200321160b20044100360288012004420837038001200841ffffff3f71450d00200710350b02400240200942ff01834203854200520d00200428028801210a200428028001210c20044180016a21040c010b0240200428028801220a200428028401470d0020044180016a200a410110a101200428028801210a0b200428028001220c200a4105746a221120063703102011201637030820112015370300201141186a20093703002004200a41016a220a3602880120044180016a21040b2001200c200a10ec02200441046a28020041ffffff3f71450d00200428020010350b200524000ba70704087f017e027f057e23004190016b22022400200241106a200110ed022002280210210320022002280218220136022420022003360220200241286a2001ad4220862003ad84100510c2010240024002400240024020022802282204450d00200228022c21052002200241306a28020036023c20022004360238200241086a200241386a10c40102400240024002402002280208450d0041002106200241003602400c010b200228020c2207200228023c4105762201200120074b1b22014105742206417f4c0d070240024020010d00410821080c010b200610332208450d070b41002106200241003602582002200136025420022008360250024002402007450d00034020024180016a200241386a10ee020240024020022d0080014101460d0041032109200228023c22014110490d01200229008101210a2002200141706a220b36023c20022002280238220c41106a360238200b450d01200c41086a290000210d200c290000210e20022001416f6a36023c2002200c41116a36023841032109200c2d0010220141034f0d012002200228008001360278200220024180016a41036a28000036007b200a210f200e2110200d2111200121090c010b410321090b200220022802783602702002200228007b36007320094103460d022002200228007336006b20022002280270360268024020062002280254470d00200241d0006a2006410110a10120022802502108200228025821060b200820064105746a220120093a00182001200f370310200120022802683600192001411c6a200228006b36000020012011370308200120103703002002200641016a22063602582007417f6a22070d000b0b200241c0006a41086a200241d0006a41086a28020036020020022002290350220f370340200fa722064521012006450d022002290244210f0c030b4100210620024100360240200228025441ffffff3f71450d00200810350b410121010b200241003602482002420137034020024109360284012002200241206a360280012002200241c0006a360278200241e4006a410136020020024201370254200241c888c200360250200220024180016a360260200241f8006a41e88ac500200241d0006a10431a2002350248422086200235024084100602402002280244450d00200228024010350b0b02402005450d00200410350b2001450d010b20004100360208200042083702000c010b2000200f370204200020063602000b02402002280214450d00200310350b20024190016a24000f0b1045000b1044000bb0180d037f027e027f067e027f027e017f017e027f017e037f027e017f230041b0056b22032400200341286a2000108e02200341386a2003280228220420032802302205108f0220032903382106420021072003420037033820034180016a280200210820032d00840121090240024020064201510d0020034188016a41386a420037030020034188016a41306a420037030020034188016a41286a420037030020034188016a41206a420037030020034188016a41186a420037030020034198016a420037030020034190016a420037030020034200370388014200210a4200210b4200210c0c010b200341386a41386a290300210d200341386a41306a290300210e200341386a41206a290300210a200341386a41186a2903002107200341f8006a290300210f2003290348210c2003290340210b20034188016a41206a200341386a41286a29030037030020034188016a41286a200e37030020034188016a41306a200d37030020034198016a20073703002003200a3703a0012003200f3703c0012003200b370388012003200c370390010b4200210d200341c0016a2210420037030020034188016a41306a420037030020034188016a41286a22114200370300200342003703a801200c200a7c2112200b20077c2213200b542214ad211520034188016a41106a211602402002450d00200241057421174200210d4200210f420021184200210e200121190340024002400240201941186a221a2d0000221b417f6a41ff017141014b0d002011200e201941086a290300220720182019290300220a56200e200756200e2007511b221b1b220e37030020032018200a201b1b22183703a801201a2d0000221b4102460d010b201b41ff01710d01201941086a29030021072019290300210a0b2010200d2007200f200a56200d200756200d2007511b221b1b220d3703002003200f200a201b1b220f3703b8010b201941206a2119201741606a22170d000b0b201220157c2107200341c8016a41186a201641086a290300220a370300200341c8016a41206a221b201641106a290300370300200341c8016a41286a201641186a290300370300200341c8016a41306a201641206a29030037030020032016290300220e3703d8012003200b3703c8012003200c3703d00102400240427f200b200e7c220e200e200b542219200c200a7c2019ad7c220a200c54200a200c511b22191b220e428080e983b1de16544100427f200a20191b220f501b0d00200341d8016a290300210e200341f8016a290300210f200341f0016a2903002118201b290300211220032903d001211520032903c801211c4201210a20032903e001211d0c010b02400240200e200f8450450d004200210a0c010b4200210a20034180046a41186a2210420037030020034180046a41106a2217420037030020034180046a41086a221b4200370300200342003703800441b6fdc600ad428080808080018422181001221a2900002112200341a0056a41086a2219201a41086a290000370300200320123703a005201a1035201b2019290300370300200320032903a0053703800441e489c200ad4280808080d0018422121001221a29000021152019201a41086a290000370300200320153703a005201a1035201720032903a005221537030020034180056a41086a2211201b29030037030020034180056a41106a2216201537030020034180056a41186a221e2019290300370300200320032903800437038005200341106a20034180056a412010d701200341106a41106a29030021152003290318211c2003280210211a2010420037030020174200370300201b4200370300200342003703800420181001221029000021182019201041086a290000370300200320183703a00520101035201b2019290300370300200320032903a0053703800420121001221029000021182019201041086a290000370300200320183703a00520101035201720032903a00522183703002011201b29030037030020162018370300201e20192903003703002003200329038004370380052003420020154200201a1b2218200f7d201c4200201a1b2212200e54ad7d22152012200e7d221c201256201520185620152018511b22191b3703880420034200201c20191b3703800420034180056aad428080808080048420034180046aad42808080808002841002200341b8046a200f370300200341b0046a200e370300201b41013a000020034189046a200029000037000020034191046a200041086a29000037000020034199046a200041106a290000370000200341a1046a200041186a290000370000200341033a00800441b0b4cc00410020034180046a10d4010b0b2007200c5121192007200c54211b200341e0006a2012370300200341e8006a2018370300200341c8006a2015370300200341f0006a200f370300200341d0006a200e3703002003201d3703582003200d3703782003201c370340200320094100200642015122171b3a00840120032008410020171b360280012003200a4201512217ad3703380240024020170d002005ad4220862004ad8410070c010b20032005360284042003200436028004200341c0006a20034180046a10e7020b2014201b20191b21190240200328022c450d00200410350b427f200720191b2107427f201320191b210d200a420152211902400240024020064201510d0020190d004103211b20034180036a21190c010b20064201522019410173720d014104211b20034180026a21190b201941086a201b3a0000201941003a0000201941096a2000290000370000201941116a200041086a290000370000201941196a200041106a290000370000201941216a200041186a29000037000041b0b4cc004100201910d4010b0240200d2007844200520d00200341b8046a200c370300200341b0046a200b37030020034180046a41086a41003a000020034189046a200029000037000020034191046a200041086a29000037000020034199046a200041106a290000370000200341a1046a200041186a290000370000200341033a00800441b0b4cc00410020034180046a10d4010b20034180046a200010ed02200341086a200328028004221920032802880441b0b4cc0041004100108a02200328020821040240200328028404450d00201910350b0240024002400240024002402002450d0020034180036a200010ed0220024105744104722219417f4c0d02200335028803210d200328028003210520191033221b450d03200341003602880420032019360284042003201b36028004200220034180046a107720024105742111200328028404211a2003280288042117034002400240201a20176b4108490d00200328028004211b201a21100c010b201741086a22192017490d06201a410174221b2019201b20194b1b22104100480d0602400240201a0d00024020100d004101211b0c020b20101033221b0d010c090b200328028004211b201a2010460d00201b201a20101037221b450d080b20032010360284042003201b360280040b201b20176a200141106a2900003700002003201741086a221a36028804200141086a29030021072001290300210a024002402010201a6b410f4d0d00201021190c010b201a41106a2219201a490d06201041017422162019201620194b1b22194100480d060240024020100d00024020190d004101211b0c020b20191033221b450d090c010b20102019460d00201b201020191037221b450d080b20032019360284042003201b360280040b201b201a6a221a2007370008201a200a3700002003201741186a221736028804200141186a2d000021100240024020192017460d002019211a201721190c010b201941016a22172019490d062019410174221a2017201a20174b1b221a4100480d060240024020190d00410021190240201a0d004101211b0c020b201a1033221b450d090c010b2019201a460d00201b2019201a1037221b450d080b2003201a360284042003201b360280040b200141206a2101201b20196a20103a00002003201941016a221736028804201141606a22110d000b2003280284042119200d4220862005ad842017ad422086200328028004221bad84100202402019450d00201b10350b0240200328028403450d00200510350b20044101460d012000108d020c010b20034180046a200010ed022003350288044220862003280280042219ad8410070240200328028404450d00201910350b20044101470d0020001099020b200341b0056a24000f0b1044000b1045000b103e000b103c000bc20503027f017e047f230041d0006b2202240041b6fdc600ad4280808080800184100122032900002104200241086a200341086a290000370300200220043703002003103541b8a2c600ad4280808080d00084100122032900002104200241106a41086a200341086a29000037030020022004370310200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100422012900002104200241306a41086a200141086a2900003703002002200437033020011035200241cc006a200341206a360200200220033602482002200241306a41106a3602442002200241306a360240200241206a200241c0006a107b200310352002280228220541206a2201417f4c0d01200228022021060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290300370000200341086a200241086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290310370010200341186a200241106a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a20002001360208200020083602042000200336020002402002280224450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000bf00204027f017e017f077e0240024020012802042202450d0020012802002203310000210420012002417f6a22053602042001200341016a3602002005450d012003310001210620012002417e6a22053602042001200341026a3602002005450d012003310002210720012002417d6a22053602042001200341036a3602002005450d012003310003210820012002417c6a22053602042001200341046a3602002005450d012003310004210920012002417b6a22053602042001200341056a3602002005450d012003310005210a20012002417a6a22053602042001200341066a3602002005450d012003310006210b2001200241796a22053602042001200341076a3602002005450d01200041003a00002003310007210c2001200241786a3602042001200341086a3602002000200c423886200b42308684200a422886842009422086842008421886842007421086842006420886842004843700010f0b200041013a00000f0b200041013a00000bb3270f037f017e037f057e037f017e037f027e017f027e017f017e027f047e047f230041900a6b220624002006200437034020062003370338200620053a004f024002400240024002400240024002400240024002402003200484500d0020012002460d0320012002412010a008450d03200641d0016a2002108e02200641e0016a20062802d001220720062802d8012208108f0220062903e001210942002104200642003703e001200641a8026a280200210a20062d00ac02210b2009420151220c0d01200641b0026a41386a4200370300200641b0026a41306a4200370300200641b0026a41286a4200370300200641d0026a4200370300200641b0026a41186a4200370300200641c0026a4200370300200641b8026a4200370300200642003703b002420021034200210d4200210e0c020b20004100360200200041106a4200370300200041086a42003703000c090b200641e0016a41386a290300210f200641e0016a41306a2903002110200641e0016a41206a290300210e200641e0016a41186a290300210d200641a0026a290300211120062903f001210320062903e8012104200641d0026a200641e0016a41286a290300370300200641b0026a41286a2010370300200641b0026a41306a200f370300200641c0026a200d3703002006200e3703c802200620113703e802200620043703b002200620033703b8020b200641b0026a41106a2105427f2004200d7c220d200d20045422122003200e7c2012ad7c220420035420042003511b22121b427f200420121b84500d01200641f0046a2001108e0220064180056a20062802f004221320062802f8042214108f022006290380052115420021032006420037038005200641c8056a280200211620062d00cc05211702400240201542015122180d00200641d0056a41306a4200370300200641d0056a41286a4200370300200641d0056a41206a4200370300200641d0056a41186a4200370300200641e0056a4200370300200641d8056a4200370300200642003703d005420021044200210e4200210d420021190c010b200641b8056a290300210f20064180056a41306a290300211020064180056a41206a290300210420064180056a41186a2903002103200641c0056a2903002119200629039005210d200629038805210e200641d0056a41206a20064180056a41286a290300370300200641d0056a41286a2010370300200641d0056a41306a200f370300200641e0056a2003370300200620043703e8052006200e3703d0052006200d3703d8050b200641386a41086a2903002210200420032006290338221156200420105620042010511b22121b211a2011200320121b210f0240024020062d004f4101470d00200641d0066a21122005211b20062903c002221c200f7c221d201c54221e200641c8026a290300221f201a7c201ead7c221c201f54201c201f511b0d010c040b200641c0066a2112200641b0026a211b20062903b002221c200f7c221d201c54221e200641b0026a41086a290300221f201a7c201ead7c221c201f54201c201f511b4101470d030b201241086a4108360200201241046a221841a7d6ca00360200201241026a41023a0000201241830c3b0100201829020022034280807c83210f200342088842ff018321042003a721182012280200211b410121120c030b02402005450d00200641e0076a2001108e02200641e0086a20062802e007220220062802e807108f0220064180096a290300420020062903e00842015122011b210e200641f8086a290300420020011b210d024020062802e407450d00200210350b20004100360200200041106a42002004200e7d2003200d54ad7d220e2003200d7d220d200356200e200456200e2004511b22011b370300200041086a4200200d20011b3703000c070b200620033703e006200620043703e806200620013602f003200641e0076a2001200641e0066a200641f0036a10f00220064180086a290300210320062903f8072104024020062903e0074201520d0020062903e807210d20064198096a200641e0076a41106a29030037030020064190096a200d370300200641e0086a41086a41003a0000200641e9086a2001290000370000200641f1086a200141086a290000370000200641f9086a200141106a29000037000020064181096a200141186a290000370000200641033a00e00841b0b4cc004100200641e0086a10d4010b200041106a2003370300200041086a2004370300200041003602000c060b200641e0066a41206a200541206a290300370300200641e0066a41186a200541186a290300370300200641e0066a41106a200541106a290300370300200641e0066a41086a200541086a290300370300200620052903003703e00641ea88c200ad4280808080b0018421034200211041838c1c211b0c020b201b201d370300201b201c370308200641d0056a41186a2004201a7d2003200f54ad7d37030020062003200f7d3703e00520064188066a41186a200641e0056a221241086a290300221c37030020064188066a41206a221b201241106a290300370300200641b0066a2220201241186a290300370300200641b8066a2221201241206a29030037030020062012290300221d370398062006200e370388062006200d370390062010201a7d21102011200f54ad211a427f200e20037c22032003200e542212200d20047c2012ad7c2203200d542003200d511b22121b427f200320121b8450211e02400240427f200e201d7c22032003200e542212200d201c7c2012ad7c2203200d542003200d511b22121b2204428080e983b1de16544100427f200320121b2203501b0d0020064188066a41106a29030021042021290300211c2020290300211d201b290300211f200629039006212220062903880621234201212420062903a00621250c010b02400240200420038450450d00420021240c010b42002124200641e0086a41186a22264200370300200641e0086a41106a22204200370300200641e0086a41086a221b4200370300200642003703e00841b6fdc600ad4280808080800184221c10012221290000211d200641800a6a41086a2212202141086a2900003703002006201d3703800a20211035201b2012290300370300200620062903800a3703e00841e489c200ad4280808080d00184221d10012221290000211f2012202141086a2900003703002006201f3703800a20211035202020062903800a221f370300200641e0096a41086a2227201b290300370300200641e0096a41106a2228201f370300200641e0096a41186a22292012290300370300200620062903e0083703e009200641206a200641e0096a412010d701200641206a41106a290300211f20062903282122200628022021212026420037030020204200370300201b4200370300200642003703e008201c10012226290000211c2012202641086a2900003703002006201c3703800a20261035201b2012290300370300200620062903800a3703e008201d10012226290000211c2012202641086a2900003703002006201c3703800a20261035202020062903800a221c3703002027201b2903003703002028201c37030020292012290300370300200620062903e0083703e00920064200201f420020211b221c20037d2022420020211b221d200454ad7d221f201d20047d2222201d56201f201c56201f201c511b22121b3703e80820064200202220121b3703e008200641e0096aad4280808080800484200641e0086aad4280808080800284100220064198096a200337030020064190096a2004370300201b41013a0000200641e9086a2001290000370000200641f1086a200141086a290000370000200641f9086a200141106a29000037000020064181096a200141186a290000370000200641033a00e00841b0b4cc004100200641e0086a10d4010b0b2010201a7d21102011200f7d2111201ead2103200641a8056a201f370300200641b0056a201d37030020064190056a2022370300200641b8056a201c37030020064198056a2004370300200620253703a005200620193703c005200620233703880542012104410021122006201741002015420151221b1b3a00cc05200620164100201b1b3602c80520062024420151221bad370380050240201b0d002014ad4220862013ad841007420021044200210f0c010b200620143602e408200620133602e00820064188056a200641e0086a10e7024200210f0b024020062802f404450d00201310350b024002402012450d0020044208862018ad42ff018384200f842103410121180c010b02400240201841ff017122120d0020044200510d0041032118200641e0076a21120c010b410021182012450d0120044200520d0141042118200641e0066a21120b201241086a20183a000041002118201241003a0000201241096a2001290000370000201241116a200141086a290000370000201241196a200141106a290000370000201241216a200141186a29000037000041b0b4cc004100201210d4010b024002402018450d0042002110410121120c010b41002112024020034201520d0020064198096a200d37030020064190096a200e37030041002112200641e0086a41086a41003a0000200641e9086a2001290000370000200641f1086a200141086a290000370000200641f9086a200141106a29000037000020064181096a200141186a290000370000200641033a00e00841b0b4cc004100200641e0086a10d4010b201121030b200641b0026a41086a290300210420062903b002210d20062903e802210e200641e0066a41206a2201200541206a290300370300200641e0066a41186a2218200541186a290300370300200641e0066a41106a2213200541106a290300370300200641e0066a41086a2216200541086a290300370300200620052903003703e0062012450d010b20034280807c83210d200342088842ff018321042003a7210c410121010c010b200641e0076a41186a2016290300220f370300200641e0076a41206a201329030037030020064188086a2205201829030037030020064190086a22122001290300370300200620062903e00622113703f0072006200d3703e007200620043703e80702400240427f200d20117c22112011200d5422012004200f7c2001ad7c220d200454200d2004511b22011b2204428080e983b1de16544100427f200d20011b220d501b0d00200641f0076a29030021042012290300210d2005290300210f20064180086a290300211120062903e807211a20062903e00721154201211c20062903f80721190c010b024002402004200d8450450d004200211c0c010b4200211c200641e0086a41186a22134200370300200641e0086a41106a22124200370300200641e0086a41086a22054200370300200642003703e00841b6fdc600ad4280808080800184220f100122182900002111200641800a6a41086a2201201841086a290000370300200620113703800a2018103520052001290300370300200620062903800a3703e00841e489c200ad4280808080d00184221110012218290000211a2001201841086a2900003703002006201a3703800a20181035201220062903800a221a370300200641e0096a41086a22162005290300370300200641e0096a41106a2217201a370300200641e0096a41186a22142001290300370300200620062903e0083703e009200641086a200641e0096a412010d701200641086a41106a290300211a2006290310211520062802082118201342003703002012420037030020054200370300200642003703e008200f10012213290000210f2001201341086a2900003703002006200f3703800a2013103520052001290300370300200620062903800a3703e008201110012213290000210f2001201341086a2900003703002006200f3703800a20131035201220062903800a220f370300201620052903003703002017200f37030020142001290300370300200620062903e0083703e00920064200201a420020181b220f200d7d2015420020181b2211200454ad7d221a201120047d2215201156201a200f56201a200f511b22011b3703e80820064200201520011b3703e008200641e0096aad4280808080800484200641e0086aad4280808080800284100220064198096a200d37030020064190096a2004370300200541013a0000200641e9086a2002290000370000200641f1086a200241086a290000370000200641f9086a200241106a29000037000020064181096a200241186a290000370000200641033a00e00841b0b4cc004100200641e0086a10d4010b0b20064188026a201137030020064190026a200f370300200641f0016a201a37030020064198026a200d370300200641f8016a200437030020062019370380022006200e3703a002200620153703e80142012104410021012006200b4100200942015122051b3a00ac022006200a410020051b3602a8022006201c4201512205ad3703e0010240024020050d002008ad4220862007ad841007420021040c010b200620083602e408200620073602e008200641e8016a200641e0086a10e7020b4200210d0b024020062802d401450d00200710350b024020010d00024002400240200c41ff017122010d0020044200510d0041032105200641f0036a21010c010b2001450d0120044200520d0141042105200641f0026a21010b200141086a20053a0000200141003a0000200141096a2002290000370000200141116a200241086a290000370000200141196a200241106a290000370000200141216a200241186a29000037000041b0b4cc004100200110d4010b200041106a2010370300200041086a2003370300200041003602000c010b2000201b360204200041086a2004420886200cad42ff018384200d84370200200041013602000b200641900a6a24000bc50f07037f027e027f0c7e037f047e047f230041d0036b2204240020032802002105200441206a2001108e02200441a0016a2004280220220320042802282206108f0220042903a001210742002108200442003703a001200441e8016a280200210920042d00ec01210a0240024020074201510d00200441306a41306a4200370300200441306a41286a4200370300200441306a41206a4200370300200441306a41186a4200370300200441c0006a4200370300200441386a4200370300200442003703304200210b4200210c4200210d4200210e0c010b200441d8016a290300210f200441a0016a41306a2903002110200441a0016a41206a290300210b200441a0016a41186a2903002108200441e0016a290300210e20042903b001210d20042903a801210c200441306a41206a200441a0016a41286a290300370300200441306a41286a2010370300200441306a41306a200f370300200441c0006a20083703002004200b3703482004200c3703302004200d3703380b200441306a41186a200b200241086a2903002211200b20082002290300221256200b201156200b2011511b22021b22137d20082012200820021b221054ad7d22143703002004200820107d22153703402004427f200d20137c200c20107c2216200c542202ad7c220f2002200f200d54200f200d511b22021b220f3703382004427f201620021b2216370330200441e8006a41186a2014370300200441e8006a41206a2217200441306a41206a290300370300200441e8006a41286a2218200441306a41286a290300370300200441e8006a41306a2219200441306a41306a2903003703002004200f3703702004201637036820042015370378427f200d200b7c200c20087c220b200c542202ad7c220820022008200d542008200d511b22021b210c427f200b20021b211a02400240427f201620157c220d200d2016542202200f20147c2002ad7c220d200f54200d200f511b22021b2208428080e983b1de16544100427f200d20021b220b501b0d00200441f8006a29030021082019290300210b20182903002114201729030021152004290370211b2004290368211c4201210d200429038001211d0c010b024002402008200b8450450d004200210d0c010b4200210d200441a0026a41186a221e4200370300200441a0026a41106a22184200370300200441a0026a41086a22174200370300200442003703a00241b6fdc600ad42808080808001842214100122192900002115200441c0036a41086a2202201941086a290000370300200420153703c0032019103520172002290300370300200420042903c0033703a00241e489c200ad4280808080d00184221510012219290000211b2002201941086a2900003703002004201b3703c00320191035201820042903c003221b370300200441a0036a41086a221f2017290300370300200441a0036a41106a2220201b370300200441a0036a41186a22212002290300370300200420042903a0023703a003200441086a200441a0036a412010d701200441086a41106a290300211b2004290310211c20042802082119201e42003703002018420037030020174200370300200442003703a00220141001221e29000021142002201e41086a290000370300200420143703c003201e103520172002290300370300200420042903c0033703a00220151001221e29000021142002201e41086a290000370300200420143703c003201e1035201820042903c0032214370300201f20172903003703002020201437030020212002290300370300200420042903a0023703a00320044200201b420020191b2214200b7d201c420020191b2215200854ad7d221b201520087d221c201556201b201456201b2014511b22021b3703a80220044200201c20021b3703a002200441a0036aad4280808080800484200441a0026aad42808080808002841002200441d8026a200b370300200441d0026a2008370300201741013a0000200441a9026a2005290000370000200441b1026a200541086a290000370000200441b9026a200541106a290000370000200441c1026a200541186a290000370000200441033a00a00241b0b4cc004100200441a0026a10d4010b0b20122010542102201a200c84210c200441c8016a2015370300200441d0016a2014370300200441b0016a201b370300200441d8016a200b370300200441b8016a20083703002004201d3703c0012004200e3703e0012004201c3703a8012004200a4100200742015122051b3a00ec0120042009410020051b3602e8012004200d4201512205ad3703a0010240024020050d002006ad4220862003ad8410070c010b200420063602a402200420033602a002200441a8016a200441a0026a10e7020b201120137d21082002ad210b200c50210202402004280224450d00200310350b2008200b7d21082002ad210b201220107d210c200d420152210202400240024020074201510d0020020d0041032103200441a0026a21020c010b20074201522002410173720d0141042103200441a0016a21020b200241086a20033a0000200241003a0000200241096a2001290000370000200241116a200141086a290000370000200241196a200141106a290000370000200241216a200141186a29000037000041b0b4cc004100200210d4010b2000200c370318200020163703082000200b370300200041206a2008370300200041106a200f370300200441d0036a24000b130020004104360204200041f89cc2003602000b3400200041b6fdc60036020420004100360200200041146a4104360200200041106a41c4b6c200360200200041086a42083702000b830101017f0240411010332202450d00200242003700082002420037000020024110412010372202450d0020024200370010200241186a42003700002002412041c00010372202450d002002420037003020024200370020200042c0808080800837020420002002360200200241386a4200370000200241286a42003700000f0b103c000b130020004101360204200041f4bec2003602000b130020004106360204200041ecbfc2003602000b3400200041a0e4cb0036020420004100360200200041146a4105360200200041106a41d8d8c200360200200041086a42103702000b3a01017f230041206b22022400200241186a41003602002002420037030820024200370300200242013703102000200210f802200241206a24000bad0301077f230041106b220224000240200141186a28020022034105744114722204417f4c0d000240200410332205450d00200520012903003700002005200141086a2903003700082002411036020820022004360204200220053602002001280210210620032002107702402003450d0020034105742107200228020021082002280204210420022802082103034020062101024002402004200322056b4120490d00200541206a21030c010b024002400240200541206a22032005490d00200441017422062003200620034b1b22064100480d000240024020040d00024020060d00410121080c020b2006103321080c040b20042006470d020b200621040c030b103e000b200820042006103721080b2006210420080d00103c000b200141206a2106200820056a22052001290000370000200541186a200141186a290000370000200541106a200141106a290000370000200541086a200141086a290000370000200741606a22070d000b2002200436020420022003360208200220083602000b20002002290300370200200041086a200241086a280200360200200241106a24000f0b1045000b1044000b130020004106360204200041d8e0c2003602000b3501017f02404108103322020d001045000b20004288808080800137020420002002360200200242f0d0c9abc6add9b1f4003700000b2e01017f02404104103322020d001045000b20004284808080c0003702042000200236020020024180a70c3600000b2c01017f02404104103322020d001045000b20004284808080c00037020420002002360200200241073600000b2c01017f02404104103322020d001045000b20004284808080c000370204200020023602002002410d3600000b8709010f7f23004190036b2204240002400240200141046a28020022052f01062206410b490d002001280208210720012802002108200441306a410041e002109f081a200441286a22064100360200200441206a22094200370300200441186a220a4200370300200441106a220b4200370300200441086a220c42003703002004420037030002404194031033220d450d00200d41003b0106200d4100360200200d41086a200441306a41e002109d08210e200d4190036a2006280200360200200d4188036a2009290300370200200d4180036a200a290300370200200d41f8026a200b290300370200200d41f0026a200c290300370200200d20042903003702e802200441306a41086a2209200541d0016a290000370300200441306a41106a220f200541d8016a290000370300200441306a41186a2210200541e0016a290000370300200420052900c8013703302005280280032111200e200541e8016a20052f010641796a2206410574109d08210e200d41e8026a20054184036a2006410274109d082112200541063b0106200d20063b0106200a2010290300370300200b200f290300370300200c20092903003703002004200429033037030002400240200128020c22014107490d00200d41066a210a200e2001417a6a220c4105746a200e200141796a22014105746a220b200641ffff037120016b410574109e081a200b41186a200241186a290000370000200b41106a200241106a290000370000200b41086a200241086a290000370000200b20022900003700002012200c4102746a2106201220014102746a21020c010b200541086a220a200141016a220b4105746a200a20014105746a2206200541066a220a2f010020016b410574109e081a200641186a200241186a290000370000200641106a200241106a290000370000200641086a200241086a29000037000020062002290000370000200541e8026a220620014102746a21022006200b4102746a2106200121010b20062002200a2f010020016b410274109e081a20022003360200200041013a00002000200236023c200041386a4100360200200041346a200d360200200041306a20113602002000412c6a2007360000200041286a2005360000200041246a200836000020002004290300370001200041096a200441086a290300370000200041116a200441106a290300370000200041196a200441186a290300370000200a200a2f010041016a3b01000c020b103c000b200541086a220a200128020c220d41016a220b4105746a200a200d4105746a220a2006200d6b410574109e081a200a41186a200241186a290000370000200a41106a200241106a290000370000200a41086a200241086a290000370000200a2002290000370000200541e8026a2202200b4102746a2002200d4102746a220220052f0106200d6b410274109e081a20022003360200200520052f010641016a3b0106200441306a410b6a200141086a280000360000200041003a00002000200236023c200041106a200d3600002004200129000037003320002004290030370001200041086a200441376a2900003700000b20044190036a24000be60b020f7f047e23004180046b220624000240024020012802002207417f6a2005470d000240024002400240200141046a28020022082f01062209410b490d002001280208210a200641c0006a410272410041be03109f081a41c4031033220b450d05200b4100360200200b41046a200641c0006a41c003109d081a200641c0006a41186a220c200841e0016a290000370300200641c0006a41106a220d200841d8016a290000370300200641c0006a41086a220e200841d0016a290000370300200620082900c801370340200828028003210f200b41086a200841e8016a20082f0106221041796a2205410574109d082111200b41e8026a20084184036a2005410274109d082112200b4194036a200841b0036a2010417a6a2213410274109d082114200841063b0106200b20053b010602402013450d00410021052014211003402010280200220920053b01042009200b360200201041046a21102013200541016a2205470d000b0b200641206a41186a200c2903002215370300200641206a41106a200d2903002216370300200641206a41086a200e2903002217370300200620062903402218370320200641186a2015370300200641106a2016370300200641086a201737030020062018370300200128020c22054107490d0120112005417a6a22014105746a2011200541796a22104105746a2209200b2f010620106b410574109e081a200941186a200241186a290000370000200941106a200241106a290000370000200941086a200241086a290000370000200920022900003700002012200141027422096a201220104102746a2213200b2f010620106b410274109e081a20132003360200200b200b2f010641016a22133b01062005410274220220146a416c6a201420096a2205201341ffff037120016b410274109e081a200520043602002001200b2f010622134b0d022002200b6a41fc026a2105034020052802002209201041016a22103b01042009200b360200200541046a210520102013490d000c030b0b200841086a2205200128020c221341016a22104105746a200520134105746a2205200920136b410574109e081a200541186a200241186a290000370000200541106a200241106a290000370000200541086a200241086a29000037000020052002290000370000200841e8026a22092010410274220b6a2009201341027422056a220920082f010620136b410274109e081a20092003360200200820082f010641016a22093b0106200520084194036a22026a41086a2002200b6a220b200941ffff037120106b410274109e081a200b20043602000240201020082f0106220b4b0d00200820056a4198036a210520132110034020052802002209201041016a22103b010420092008360200200541046a21052010200b490d000b0b200041003a0000200041046a2001290200370200200041106a20133602002000410c6a200141086a2802003602000c020b200841086a2210200541016a22094105746a201020054105746a221020082f010620056b410574109e081a201041186a200241186a290000370000201041106a200241106a290000370000201041086a200241086a29000037000020102002290000370000200841e8026a2213200941027422016a2013200541027422106a221320082f010620056b410274109e081a20132003360200200820082f010641016a22133b0106201020084194036a22026a41086a200220016a2201201341ffff037120096b410274109e081a20012004360200200520082f010622134f0d00200820106a4198036a2110034020102802002209200541016a22053b010420092008360200201041046a211020132005470d000b0b20002006290300370001200041013a00002000412c6a200a360200200041286a2008360200200041246a2007360200200041386a2007360200200041346a200b360200200041306a200f360200200041096a200641086a290300370000200041116a200641106a290300370000200041196a200641186a2903003700000b20064180046a24000f0b41d684cc00413541c086cc00103f000b103c000bb71a01197f230041d0116b2202240020002802102203200328020041016a360200200028020c2104200028020821052000280200210620002802042103200241206a41186a22072000412c6a290000370300200241206a41106a2208200041246a290000370300200241206a41086a22092000411c6a29000037030020022000290014370320200241a0026a200141e000109d081a024002400240024002400240024020032f01062201410b490d00200241b0036a410041e002109f081a20024198066a410041a008109f081a41880b1033220a450d04200a41003b0106200a4100360200200a41086a200241b0036a41e002109d082101200a41e8026a20024198066a41a008109d0821072002200341c8016a2f00003b01ac032002200341ca016a2d00003a00ae032002200341db016a290000370398032002200341e0016a29000037009d03200341cb016a280000210b200341cf016a280000210c200341d3016a280000210d200341d7016a280000210e20024198066a200341a8076a41e000109d081a2001200341e8016a20032f010641796a2200410574109d082101200720034188086a200041e0006c109d082107200341063b0106200a20003b0106200220022f01ac033b019403200220022d00ae033a0096032002200229039803370380032002200229009d0337008503200241b0036a20024198066a41e000109d081a0240024020044107490d00200441057420016a41c07e6a2001200441796a22084105746a2201200041ffff037120086b410574109e081a200141186a200241206a41186a290300370000200141106a200241206a41106a290300370000200141086a200241206a41086a29030037000020012002290320370000200441e0006c20076a220041c07b6a200041e07a6a220f200a41066a22002f010020086b41e0006c109e081a200f200241a0026a41e000109d081a0c010b200341086a20044105746a220141206a2001200341066a22002f010020046b410574109e081a200141186a200241206a41186a290300370000200141106a200241206a41106a290300370000200141086a200241206a41086a29030037000020012002290320370000200341e8026a200441e0006c6a220f41e0006a200f20002f010020046b41e0006c109e081a200f200241a0026a41e000109d081a0b20024188026a41026a220420022d0096033a0000200020002f010041016a3b0100200220022f0194033b01880220022002290380033703800120022002290085033700850120024190016a200241b0036a41e000109d081a2002411c6a41026a221020042d00003a0000200220022f0188023b011c2002200229038001370308200220022900850137000d200241206a20024190016a41e000109d081a200328020022070d01410021030c020b200320044105746a220041286a200041086a2206200120046b410574109e081a200041206a2007290300370000200041186a2008290300370000200041106a2009290300370000200620022903203700002003200441e0006c6a220041c8036a200041e8026a220f20032f010620046b41e0006c109e081a200f200241a0026a41e000109d081a200320032f010641016a3b01060c020b20032f0104211120024198066a410272211241002103024003402002419c026a41026a221320102d00003a0000200220022f011c3b019c0220022002290308370388022002200229000d37008d02200241a0026a200241206a41e000109d081a20062003470d01201141ffff0371210802400240024020072f01062203410b490d002012410041b20b109f081a41b80b10332201450d0720014100360200200141046a20024198066a41b40b109d081a200220072f00c8013b01ac032002200741ca016a2d00003a00ae032002200741db016a290000370398032002200741e0016a29000037009d03200741cb016a2800002114200741cf016a2800002115200741d3016a2800002116200741d7016a280000211720024198066a200741a8076a41e000109d081a200141086a200741e8016a20072f0106220041796a2203410574109d082118200141e8026a20074188086a200341e0006c109d082119200141880b6a200741a40b6a2000417a6a2209410274109d08211a200741063b0106200120033b010602402009450d0041002103201a210003402000280200220420033b010420042001360200200041046a21002009200341016a2203470d000b0b200241b0036a20024198066a41e000109d081a200220022d00ae0322033a009603200220022f01ac0322003b0194032002200229009d033700850320022002290398033703800320024194066a41026a220920033a0000200220003b01940620022002290380033703800120022002290085033700850120024198066a200241b0036a41e000109d081a201141ffff037122004107490d0120182008417a6a22044105746a2018200841796a22034105746a220020012f010620036b410574109e081a200041186a200229008d023700002000200e36000f2000200d36000b2000200c3600072000200b360003200041026a20132d00003a0000200020022f019c023b00002000200229038802370013200841e0006c20196a220041c07b6a200041e07a6a220020012f010620036b41e0006c109e081a2000200241a0026a41e000109d081a200120012f010641016a22003b01062008410274220b201a6a416c6a201a20044102746a2211200041ffff0371220820046b410274109e081a2011200a36020020082004490d022001200b6a41f00a6a2100034020002802002204200341016a22033b010420042001360200200041046a210020032008490d000c030b0b200741086a2200200841016a22044105746a200020084105746a2200200320086b2201410574109e081a2000200e36000f2000200d36000b2000200c3600072000200b360003200041026a2002419c026a41026a2d00003a0000200020022f019c023b00002000200229038802370013200041186a200229008d023700002007200841e0006c6a220041c8036a200041e8026a2200200141e0006c109e081a2000200241a0026a41e000109d081a2007200341016a22033b01062008410274200741880b6a22006a41086a200020044102746a2200200341ffff037120046b410274109e081a2000200a360200201141ffff037120072f010622034f0d05200a20043b0104200a2007360200200420034f0d052003417f6a210120072004417f6a22034102746a41900b6a2100034020002802002204200341026a3b010420042007360200200041046a21002001200341016a2203470d000c060b0b200741086a2203200841016a22044105746a200320084105746a220320072f0106221120086b221a410574109e081a2003200e36000f2003200d36000b2003200c3600072003200b360003200341026a20132d00003a0000200320022f019c023b00002003200229038802370013200341186a200229008d02370000200741e8026a200841e0006c6a220341e0006a2003201a41e0006c109e081a2003200241a0026a41e000109d081a2007201141016a22033b01062008410274221a200741880b6a22116a41086a201120044102746a2211200341ffff037120046b410274109e081a2011200a360200200020072f010622044f0d002007201a6a418c0b6a2103034020032802002200200841016a22083b010420002007360200200341046a210320042008470d000b0b200641016a210320024184026a41026a220020092d00003a0000200220022f0194063b01840220022002290380013703f00120022002290085013700f50120024190016a20024198066a41e000109d081a201020002d00003a0000200220022f0184023b011c200220022903f001370308200220022900f50137000d200241206a20024190016a41e000109d081a0240200728020022000d002014210b2017210e2016210d2015210c2001210a0c030b20072f010421112014210b2017210e2016210d2015210c200021072001210a200321060c000b0b41d684cc00413541c086cc00103f000b20024198066a410272410041b20b109f081a41b80b10332200450d0120004100360200200041046a20024198066a41b40b109d081a2000200528020022043602880b2005200036020020052005280204220141016a360204200441003b010420042000360200200241a0026a41026a2002411c6a41026a2d00003a0000200220022f011c3b01a002200220022903083703b0032002200229000d3700b50320024198066a200241206a41e000109d081a20012003470d0220002f01062204410a4b0d03200020044105746a2203410a6a200241a0026a41026a2d00003a0000200341086a20022f01a0023b0000200341176a200e360000200341136a200d3600002003410f6a200c3600002003410b6a200b3600002003411b6a20022903b003370000200341206a20022900b5033700002000200441e0006c6a41e8026a20024198066a41e000109d081a2000200441016a22034102746a41880b6a200a360200200020033b0106200a20033b0104200a20003602000b200241d0116a2400200f0f0b103c000b41ff83cc00413041c086cc00103f000b41af84cc00412741c086cc00103f000bfb0203057f017e027f0240024020002802202201450d00034020002001417f6a36022020002802042201450d0220002802082102200028020021030240200028020c220420012f0106490d00034002400240200128020022050d002002ad2106410021050c010b200341016a210320013301044220862002ad8421060b200110352006a72102200521012006422088a7220420052f01064f0d000b200521010b200441016a210720012004410c6c6a220541ec026a2802002108200541e8026a280200210402402003450d00200120074102746a41ec036a2802002101410021072003417f6a2205450d00034020012802ec0321012005417f6a22050d000b0b2000200736020c20002002360208200020013602042000410036020002402004450d002008450d00200410350b200028022022010d000b0b024020002802042205450d0020052802002101200510352001450d00034020012802002105200110352005210120050d000b0b0f0b41958dcc00412b41c08dcc00103f000bc91305027f017e067f037e0a7f230041b0036b2202240020002802102203200328020041016a36020020002902142104200028020c2105200028020821062000280200210320002802042100200241f0016a41086a2207200141086a280200360200200220012902003703f001024002400240024002400240024020002f01062201410b490d00200241d0026a410272410041da00109f081a200241386a4100418401109f081a41e40110332208450d0420084100360200200841046a200241d0026a41dc00109d081a200841e0006a200241386a418401109d082107200241386a41086a2209200041b0016a280200360200200220002902a8013703382000413f6a2d0000210a200041386a350000210b2000413c6a330000210c2000413e6a310000210d200841086a200041c0006a20002f010641796a2201410374109d08210e2007200041b4016a2001410c6c109d082107200041063b0106200820013b0106200241d0026a41086a2009280200360200200220022903383703d002200b200c200d4210868442208684210b0240024020054107490d002005410374200e6a41506a200e200541796a22094103746a220e200141ffff037120096b410374109e081a200e20043700002005410c6c20076a220541b87f6a200541ac7f6a2205200841066a22012f010020096b410c6c109e081a200541086a200241f0016a41086a280200360200200520022903f0013702000c010b200041086a20054103746a220741086a2007200041066a22012f010020056b410374109e081a20072004370000200041e0006a2005410c6c6a2207410c6a200720012f010020056b410c6c109e081a200741086a200241f0016a41086a280200360200200720022903f0013702000b200120012f010041016a3b0100200241286a41086a220f200241d0026a41086a22102802002205360200200241086a221120053602002002200a3a0017200220022903d00222043703282002200b3e02102002200b4230883c00162002200b4220883d01142002200437030020022903102104200028020022090d01410021120c020b200020054103746a220341106a200341086a2203200120056b410374109e081a2003200437000020002005410c6c6a220341ec006a200341e0006a220120002f010620056b410c6c109e081a200341e8006a2007280200360200200120022903f001370200200020002f010641016a3b01060c020b20002f01042113200241d0026a41027221144100210002400340200220093602242002200341016a2212360220200f20112802003602002002200229030037032820032000470d01201341ffff0371210702400240024020092f01062203410b490d002014410041da00109f081a200241f0016a200241d0026a41dc00109d081a200241386a410041b401109f081a41940210332201450d0720014100360200200141046a200241f0016a41dc00109d081a200141e0006a200241386a41b401109d0821002009290038210b200241386a41086a220e200941b0016a280200360200200220092902a801370338200141086a200941c0006a20092f0106220541796a2203410374109d0821152000200941b4016a2003410c6c109d082116200141e4016a20094180026a2005417a6a220a410274109d082117200941063b0106200120033b01060240200a450d00410021032017210003402000280200220520033b010420052001360200200041046a2100200a200341016a2203470d000b0b2010200e280200220336020020022002290338220c3703d002200e20033602002002200c370338201341ffff037122004107490d0120152007417a6a22004103746a2015200741796a22034103746a220520012f010620036b410374109e081a200520043700002007410c6c20166a220541b87f6a200541ac7f6a220520012f0106220a20036b410c6c109e081a200541086a200f280200360200200520022903283702002001200a41016a22053b01062007410274221320176a416c6a201720004102746a220a200541ffff0371220720006b410274109e081a200a200836020020072000490d02200120136a41cc016a2100034020002802002205200341016a22033b010420052001360200200041046a210020032007490d000c030b0b200941086a2205200741016a22004103746a200520074103746a2205200320076b2201410374109e081a2005200437000020092007410c6c6a220541ec006a200541e0006a220a2001410c6c109e081a200541e8006a200241286a41086a280200360200200a20022903283702002009200341016a22033b01062007410274200941e4016a22056a41086a200520004102746a2205200341ffff0371220120006b410274109e081a20052008360200201341ffff037120014f0d0520092000417f6a22034102746a41e8016a2100034020002802002205200341016a22033b010420052009360200200041046a210020032001490d000c060b0b200941086a2203200741016a220a4103746a200320074103746a220320092f0106220520076b2213410374109e081a20032004370000200941e0006a2007410c6c6a2203410c6a20032013410c6c109e081a200341086a200f280200360200200320022903283702002009200541016a22033b010620074102742217200941e4016a22056a41086a2005200a4102746a2213200341ffff03712205200a6b410274109e081a20132008360200200020054f0d00200920176a41e8016a2103034020032802002200200741016a22073b010420002009360200200341046a210320052007470d000b0b200241106a41086a200e280200220336020020112003360200200220022903382204370310200220043703000240200928020022030d0020012108200b21040c030b20092f0104211320032109200b21042001210820122100201221030c000b0b41d684cc00413541c086cc00103f000b200241d0026a410272410041da00109f081a200241f0016a200241d0026a41dc00109d081a200241386a410041b401109f081a41940210332203450d0120034100360200200341046a200241f0016a41dc00109d081a200341e0006a200241386a41b401109d0821052003200628020022003602e4012006200336020020062006280204220141016a360204200041003b010420002003360200200241386a41086a200241086a2802003602002002200229030037033820012012470d0220032f01062200410a4b0d0320052000410c6c6a22052002290338370200200320004103746a41086a2004370000200541086a200241386a41086a2802003602002003200041016a22004102746a41e4016a2008360200200320003b0106200820003b0104200820033602000b200241b0036a24000f0b103c000b41ff83cc00413041c086cc00103f000b41af84cc00412741c086cc00103f000bfa20021b7f017e23004180076b22042400200441e0006a41186a200241186a290000370300200441e0006a41106a200241106a290000370300200441e0006a41086a200241086a290000370300200420022900003703600240024002400240024020012802002205450d00200128020421060c010b41002106200441e8026a410041e002109f081a200441c0016a4100418401109f081a41ec0310332205450d01200541003b010620054100360200200541086a200441e8026a41e002109d081a200541e8026a200441c0016a418401109d081a20014100360204200120053602000b200420013602c801200420053602c401200420063602c00102400240024002400340200541086a2107200541066a210820052f0106220941057421024100210a024002400240024003402002450d010240200441e0006a2007412010a008220b0d00410021022006210c0c030b200241606a2102200a41016a210a200741206a2107200b417f4a0d000b200a417f6a21090b20060d01410121024100210c2009210a0b200441e8026a41106a200a360200200441e8026a410c6a2001360200200441e8026a41086a22072005360200200420013602c801200420053602c401200420063602c0012004200c3602ec02200420023602e80202402002450d00200441086a41186a2207200441e0006a41186a2202290300370300200441086a41106a220b200441e0006a41106a2206290300370300200441086a41086a2209200441e0006a41086a220d290300370300200420042903603703082001200128020841016a360208200220072903003703002006200b290300370300200d200929030037030020042004290308370360200441d8026a41086a200341086a280200360200200420032902003703d80220082f0100220b410b490d02200441e8026a410041e002109f081a200441c0016a4100418401109f081a41ec0310332203450d08200341003b010620034100360200200341086a200441e8026a41e002109d082107200341e8026a200441c0016a418401109d08210b200441e8026a41086a2206200541b8036a2802003602002004200541db016a2900003703a8012004200541e0016a2900003700ad01200420052902b0033703e8022004200541c8016a2f00003b01bc012004200541ca016a2d00003a00be01200541cb016a280000210e200541cf016a280000210f200541d3016a2800002110200541d7016a28000021112007200541e8016a20052f010641796a2202410574109d082107200b200541bc036a2002410c6c109d08210b200541063b0106200320023b0106200420042f01bc013b01a401200420042d00be013a00a601200420042903a8013703c001200420042900ad013700c501200441286a41086a2006280200360200200420042903e80237032802400240200a4107490d00200a41057420076a41c07e6a2007200a41796a22064105746a2207200241ffff037120066b410574109e081a200741186a200441e0006a41186a290300370000200741106a200441e0006a41106a290300370000200741086a200441e0006a41086a29030037000020072004290360370000200a410c6c200b6a220241b87f6a200241ac7f6a2202200341066a22082f010020066b410c6c109e081a200241086a200441d8026a41086a280200360200200220042903d8023702000c010b200541086a200a4105746a220241206a200220082f0100200a6b410574109e081a200241186a200441e0006a41186a290300370000200241106a200441e0006a41106a290300370000200241086a200441e0006a41086a29030037000020022004290360370000200541e8026a200a410c6c6a2202410c6a200220082f0100200a6b410c6c109e081a200241086a200441d8026a41086a280200360200200220042903d8023702000b200820082f010041016a3b010020044198016a41026a220220042d00a6013a0000200441c8026a41086a2212200441286a41086a280200360200200420042f01a4013b019801200420042903c001370350200420042900c501370055200420042903283703c8022004413c6a41026a221320022d00003a0000200420042f0198013b013c2004200429005537002d20042004290350370328200441c0006a41086a22142012280200360200200420042903c8023703400240200528020022060d00410021020c060b20052f01042108200441e8026a410272211541002102034020044194016a41026a221620132d00003a0000200420042f013c3b019401200420042903283703602004200429002d37006520044198016a41086a221720142802003602002004200429034037039801200c2002470d05200841ffff0371210502400240024020062f01062202410b490d0020154100419604109f081a419c041033220b450d0c200b4100360200200b41046a200441e8026a419804109d081a2004200641c8016a2f00003b01bc012004200641ca016a2d00003a00be012004200641db016a2900003703a8012004200641e0016a2900003700ad01200641cb016a2800002118200641cf016a2800002119200641d3016a280000211a200641d7016a280000211b200441e8026a41086a221c200641b8036a280200360200200420062902b0033703e802200b41086a200641e8016a20062f0106220741796a2202410574109d08211d200b41e8026a200641bc036a2002410c6c109d08211e200b41ec036a20064188046a2007417a6a2209410274109d08210d200641063b0106200b20023b010602402009450d0041002102200d210703402007280200220a20023b0104200a200b360200200741046a21072009200241016a2202470d000b0b200441d8026a41086a2202201c280200360200200420042d00be0122073a00a601200420042f01bc01220a3b01a401200420042903a8013703c001200420042900ad013700c501200420042903e8023703d802200441c4026a41026a220920073a00002004200a3b01c402200420042903c0013703e802200420042900c5013700ed0220122002280200360200200420042903d8023703c802200841ffff037122074107490d01201d2005417a6a220a4105746a201d200541796a22024105746a2207200b2f010620026b410574109e081a200741186a20042900653700002007201136000f2007201036000b2007200f3600072007200e360003200741026a20162d00003a0000200720042f0194013b0000200720042903603700132005410c6c201e6a220741b87f6a200741ac7f6a2207200b2f0106220820026b410c6c109e081a200741086a20172802003602002007200429039801370200200b200841016a22073b01062005410274220e200d6a416c6a200d200a4102746a2208200741ffff03712205200a6b410274109e081a200820033602002005200a490d02200b200e6a41d4036a210703402007280200220a200241016a22023b0104200a200b360200200741046a210720022005490d000c030b0b200641086a2207200541016a220a4105746a200720054105746a2207200220056b410574109e081a200741186a20042900653700002007201136000f2007201036000b2007200f3600072007200e360003200741026a20044194016a41026a2d00003a0000200720042f0194013b00002007200429036037001320062005410c6c6a220241f4026a200241e8026a220720062f0106220b20056b410c6c109e081a200241f0026a20044198016a41086a28020036020020072004290398013702002006200b41016a22023b01062005410274200641ec036a22076a41086a2007200a4102746a2207200241ffff0371220b200a6b410274109e081a20072003360200200841ffff0371200b4f0d092006200a417f6a22024102746a41f0036a210703402007280200220a200241016a22023b0104200a2006360200200741046a21072002200b490d000c0a0b0b200641086a2202200541016a22084105746a200220054105746a220220062f010620056b410574109e081a200241186a20042900653700002002201136000f2002201036000b2002200f3600072002200e360003200241026a20162d00003a0000200220042f0194013b000020022004290360370013200641e8026a2005410c6c6a2202410c6a200220062f0106220a20056b410c6c109e081a200241086a201728020036020020022004290398013702002006200a41016a22023b01062005410274220e200641ec036a220a6a41086a200a20084102746a220d200241ffff0371220a20086b410274109e081a200d20033602002007200a4f0d002006200e6a41f0036a2102034020022802002207200541016a22053b010420072006360200200241046a2102200a2005470d000b0b200c41016a210220044190016a41026a220720092d00003a000020044180016a41086a220a2012280200360200200420042f01c40222053b019001200420042903e802370350200420042900ed02370055200420042903c80237038001201320072d00003a0000200420053b013c2004200429005537002d200420042903503703282014200a28020036020020042004290380013703400240200628020022070d002018210e201b2111201a21102019210f200b21030c070b20062f010421082018210e201b2111201a21102019210f20072106200b21032002210c0c000b0b20072005200a410c6c6a220241f0026a220a2802003602002004200241e8026a22022902003703e80220022003290200370200200a200341086a280200360200200441c0016a41086a20072802002202360200200420042903e802221f3703c0012000410c6a20023602002000201f370204200041013602000c060b2006417f6a2106200520094102746a41ec036a28020021050c010b0b2005200a4105746a220741286a200741086a2206200b200a6b410574109e081a200741206a2002290300370000200741186a200441e0006a41106a290300370000200741106a200441e0006a41086a290300370000200620042903603700002005200a410c6c6a220241f4026a200241e8026a220720052f0106200a6b410c6c109e081a200241f0026a200441d8026a41086a280200360200200720042903d802370200200520052f010641016a3b01060c020b41d684cc00413541c086cc00103f000b200441e8026a4102724100419604109f081a419c0410332207450d0220074100360200200741046a200441e8026a419804109d081a20072001280200220a3602ec032001200736020020012001280204220b41016a360204200a41003b0104200a2007360200200441e0006a41026a2004413c6a41026a2d00003a0000200420042f013c3b0160200420042903283703e8022004200429002d3700ed02200441c0016a41086a200441c0006a41086a280200360200200420042903403703c001200b2002470d0320072f0106220a410a4b0d042007200a4105746a2202410a6a200441e0006a41026a2d00003a0000200241086a20042f01603b0000200241176a2011360000200241136a20103600002002410f6a200f3600002002410b6a200e3600002002411b6a20042903e802370000200241206a20042900ed023700002007200a410c6c6a220241f0026a200441c0016a41086a280200360200200241e8026a20042903c0013702002007200a41016a22024102746a41ec036a2003360200200720023b0106200320023b0104200320073602000b200041003602000b20044180076a24000f0b103c000b41ff83cc00413041c086cc00103f000b41af84cc00412741c086cc00103f000bf70c01087f230041c0046b22032400200341206a41186a200141186a290000370300200341206a41106a200141106a290000370300200341206a41086a200141086a290000370300200320012900003703200240024002400240024020002802002204450d00200028020421050c010b4100210520034180016a410041e002109f081a200341f8006a22014100360200200341f0006a22064200370300200341d0006a41186a4200370300200341d0006a41106a4200370300200341d0006a41086a42003703002003420037035041940310332204450d01200441003b010620044100360200200441086a20034180016a41e002109d081a20044190036a200128020036020020044188036a200629030037020020044180036a200341e8006a290300370200200441f8026a200341e0006a290300370200200441f0026a200341d0006a41086a290300370200200420032903503702e80220004100360204200020043602000b2003200036025820032004360254200320053602500240034020042f01062207410574210841002101410021060240024002400240034020082001460d010240200341206a200420016a41086a412010a00822090d0041002101200521090c030b200141206a2101200641016a21062009417f4a0d000b2006417f6a21070b20050d014101210141002109200721060b20034180016a41106a20063602002003418c016a200036020020034180016a41086a20043602002003200036025820032004360254200320053602502003200936028401200320013602800102402001450d00200341186a2201200341206a41186a2207290300370300200341106a2208200341206a41106a290300370300200341086a2205200341206a41086a290300370300200320032903203703002000200028020841016a3602082003200636024c200320003602482003200436024420032009360240200341d0006a41186a2001290300370300200341d0006a41106a2008290300370300200341d0006a41086a20052903003703002003200329030037035020034180016a200341c0006a200341d0006a200210fe0220032d0080014101470d04200341206a41086a220520034189016a290000370300200341206a41106a220020034191016a290000370300200720034199016a2900003703002003200329008101370320200341ac016a2802002106200341b8016a2802002108200341b4016a2802002109200341b0016a2802002104200341a8016a28020022012802002207450d0220012f01042102200341a4016a280200210a20034180016a410172210103402003200241ffff037136024c20032006360248200320073602442003200a41016a360240200341d0006a41186a200341206a41186a2206290300370300200341d0006a41106a2000290300370300200341d0006a41086a20052903003703002003200329032037035020034180016a200341c0006a200341d0006a20042009200810ff0220032d0080014101470d052005200141086a2900003703002000200141106a2900003703002006200141186a2900003703002003200129000037032020032802ac01210620032802b801210820032802b401210920032802b001210420032802a80122022802002207450d0320022f0104210220032802a401210a0c000b0b200420064102746a41e8026a20023602000c030b2005417f6a2105200420074102746a4194036a28020021040c010b0b20034180016a410272410041be03109f081a41c40310332201450d0120014100360200200141046a20034180016a41c003109d081a200120062802002205360294032006200136020020062006280204220041016a360204200541003b01042005200136020020034180016a41186a200341206a41186a29030037030020034180016a41106a200341206a41106a29030037030020034180016a41086a200341206a41086a290300370300200320032903203703800120002008470d0220012f01062206410a4b0d03200120064105746a220841206a20034180016a41186a290300370000200841186a20034180016a41106a290300370000200841106a20034180016a41086a290300370000200841086a200329038001370000200120064102746a41e8026a20043602002001200641016a22064102746a4194036a2009360200200120063b0106200920063b0104200920013602000b200341c0046a24000f0b103c000b41ff83cc00413041c086cc00103f000b41af84cc00412741c086cc00103f000b920c02057f027e230041d0006b220224000240024002400240024002402001280200417f6a220341034b0d0020030e0401020304010b41cfa2cc00412841c086cc00103f000b410121030240024020012d00044101470d00200141086a28020021040c010b2002410a6a200141046a220341036a2d00003a0000200241306a41086a200141146a290200370300200241c0006a2001411c6a290200370300200241c8006a200141246a2d00003a0000200220032f00013b010820022001410c6a290200370330200141086a2802002104410021030b200020033a0004200020022f01083b000520004101360200200041286a2001290328370300200041086a20043602002000410c6a2002290330370200200041306a200141306a290300370300200041076a2002410a6a2d00003a0000200041146a200241306a41086a2903003702002000411c6a200241c0006a290300370200200041246a200241c8006a2802003602000c030b410121030240024020012d00044101470d00200141086a28020021040c010b2002410a6a200141046a220341036a2d00003a0000200241306a41086a200141146a290200370300200241c0006a2001411c6a290200370300200241c8006a200141246a2d00003a0000200220032f00013b010820022001410c6a290200370330200141086a2802002104410021030b200020033a0004200020022f01083b0005200041286a2001290328370300200041386a2001290338370300200041086a20043602002000410c6a2002290330370200200041306a200141306a290300370300200041c0006a200141c0006a290300370300200041076a200241086a41026a2d00003a0000200041146a200241306a41086a2903003702002000411c6a200241c0006a290300370200200041246a200241c8006a280200360200200041023602000c020b200141286a2103410121040240024020012d00044101470d00200141086a28020021050c010b2002412a6a200141046a220441036a2d00003a0000200241086a41086a200141146a290200370300200241186a2001411c6a290200370300200241206a200141246a2d00003a0000200220042f00013b012820022001410c6a290200370308200141086a2802002105410021040b410121060240024020032d00004101470d002001412c6a28020021030c010b2002412e6a200341036a2d00003a0000200241386a200141386a290200370300200241c0006a200141c0006a290200370300200241c8006a200141c8006a2d00003a0000200220032f00013b012c2002200141306a2902003703302001412c6a2802002103410021060b200020043a0004200020022f01283b0005200020022f012c3b0029200041086a20053602002000410c6a2002290308370200200041286a20063a0000200041076a200241286a41026a2d00003a0000200041146a200241086a41086a2903003702002000411c6a200241086a41106a290300370200200041246a200241086a41186a2802003602002000412b6a2002412c6a41026a2d00003a0000200141d8006a2903002107200129035021082000412c6a2003360200200041d0006a2008370300200041d8006a200737030020004103360200200041306a2002290330370200200041386a200241306a41086a290300370200200041c0006a200241306a41106a290300370200200041c8006a200241306a41186a2802003602000c010b410121030240024020012d00044101470d00200141086a28020021040c010b2002410a6a200141046a220341036a2d00003a0000200241306a41086a200141146a290200370300200241c0006a2001411c6a290200370300200241c8006a200141246a2d00003a0000200220032f00013b010820022001410c6a290200370330200141086a2802002104410021030b200020033a0004200020022f01083b000520004104360200200041286a2001290328370300200041086a20043602002000410c6a2002290330370200200041306a200141306a290300370300200041076a2002410a6a2d00003a0000200041146a200241306a41086a2903003702002000411c6a200241c0006a290300370200200041246a200241c8006a2802003602000b200241d0006a24000bbe0702097f017e230041306b2202240002400240024002400240024002400240024002402001280200417f6a220341054b0d0020030e06010203040506010b41cfa2cc00412841c086cc00103f000b2001410c6a280200220441ffffff3f712004470d0620044105742205417f4c0d06200128020421060240024020050d00410121070c010b200510332207450d080b41002103200241003602182002200736021020022005410576360214200241106a41002004108a012002280218210802402004450d0020044105742109200228021020084105746a210a0340200a20036a2205200620036a2207290000370000200541186a200741186a290000370000200541106a200741106a290000370000200541086a200741086a2900003700002009200341206a2203470d000b200441057441606a41057620086a41016a21080b200241086a200836020020022002290310220b3703002000200b3702042000410c6a200836020020004101360200200041186a200141186a290300370300200041106a20012903103703000c050b200041023602000c040b410121030240024020012d00044101470d00200141086a28020021050c010b200241026a200141046a220341036a2d00003a0000200241106a41086a200141146a290200370300200241206a2001411c6a290200370300200241286a200141246a2d00003a0000200220032f00013b010020022001410c6a290200370310200141086a2802002105410021030b200020033a0004200020022f01003b000520004103360200200041086a20053602002000410c6a2002290310370200200041076a200241026a2d00003a0000200041146a200241106a41086a2903003702002000411c6a200241206a290300370200200041246a200241286a2802003602000c030b200041043602000c020b200041053602000c010b410121030240024020012d00044101470d00200141086a28020021050c010b200241026a200141046a220341036a2d00003a0000200241106a41086a200141146a290200370300200241206a2001411c6a290200370300200241286a200141246a2d00003a0000200220032f00013b010020022001410c6a290200370310200141086a2802002105410021030b200020033a0004200020022f01003b000520004106360200200041086a20053602002000410c6a2002290310370200200041076a200241026a2d00003a0000200041146a200241106a41086a2903003702002000411c6a200241206a290300370200200041246a200241286a2802003602000b200241306a24000f0b1044000b1045000bf64006017f027e117f0e7e027f017e230041d0066b220324000240024002400240024002400240024002400240024020012802000e050001020304000b200341ac056a41013602002003420137029c05200341e8d4ca00360298052003410436029c042003419cd5ca0036029804200320034198046a3602a80520034198056a41b0b4cc00104c000b200141306a2903002104200141286a2903002105200341b8046a200141246a28020036020020034198046a41186a2001411c6a29020037030020034198046a41106a200141146a29020037030020034198046a41086a2001410c6a2902003703002003200129020437039804410221010240024020022d00000d0020022d00014101470d00200241196a2d00002101200241186a2d00002106200241166a2f01002107200241156a2d00002108200241146a2d00002109200241126a2f0100210a200241116a2d0000210b200241106a2d0000210c2002410e6a2f0100210d2002410d6a2d0000210e2002410c6a2d0000210f2002410a6a2f01002110200241096a2d00002111200241086a2d00002112200241066a2f01002113200241056a2d00002114200241046a2d00002115200241026a2f0100211620032002411a6a2901003703f802200320013a00f702200320063a00f602200320073b01f402200320083a00f302200320093a00f2022003200a3b01f0022003200b3a00ef022003200c3a00ee022003200d3b01ec022003200e3a00eb022003200f3a00ea02200320103b01e802200320113a00e702200320123a00e602200320133b01e402200320143a00e302200320153a00e202200320163b01e00220034198056a41206a20034198046a41206a28020036020020034198056a41186a20034198046a41186a29030037030020034198056a41106a20034198046a41106a29030037030020034198056a41086a20034198046a41086a29030037030020032003290398043703980520034198036a20034198056a108b02200341a0066a41086a2201200341a1036a290000370300200341a0066a41106a2202200341a9036a290000370300200341a0066a41186a2206200341b1036a29000037030020032003290099033703a006024020032d0098034101460d00200341d8016a41186a2006290300370300200341d8016a41106a2002290300370300200341d8016a41086a2001290300370300200320032903a0063703d80120034198056a200341e0026a200341d8016a20052004410110e60220032d00980522014104460d0a20032f00990520032d009b05411074722102200329029c0521040c020b410121010b0b200042003703082000411c6a2004370200200041186a20024108742001723602000c050b200141c0006a2903002117200141386a2903002118200141306a2903002104200141286a290300210520034180016a41206a2206200141246a28020036020020034180016a41186a22072001411c6a29020037030020034180016a41106a2208200141146a29020037030020034180016a41086a22092001410c6a29020037030020032001290204370380014102210120022d000120022d0000410047720d0320034198056a41206a200628020036020020034198056a41186a200729030037030020034198056a41106a200829030037030020034198056a41086a200929030037030020032003290380013703980520034198046a20034198056a108b02200341a0066a41086a200341a1046a290000370300200341a0066a41106a200341a9046a290000370300200341a0066a41186a200341b1046a29000037030020032003290099043703a0064101210120032d0098044101460d03200341a8016a41186a200341a0066a41186a290300370300200341a8016a41106a200341a0066a41106a290300370300200341a8016a41086a200341a0066a41086a290300370300200320032903a0063703a801200341c8016a200341a8016a108e02200341d8016a20032802c801220820032802d0012209108f0220032903d8012119200342003703d80142002004201820057c221a428080e983b1de16544100201720047c201a201854ad7c501b22011b21044200200520011b2105200341a0026a280200210a20032d00a402210b0240024020194201510d00200341a8026a41306a4200370300200341a8026a41286a4200370300200341a8026a41206a4200370300200341a8026a41186a4200370300200341a8026a41106a4200370300200341a8026a41086a4200370300200342003703a8024200211b4200211c4200211d4200211a4200211e0c010b20034190026a290300211f200341d8016a41306a2903002120200341d8016a41206a290300211c200341d8016a41186a290300211b20034198026a290300211e20032903e801211a20032903e001211d200341a8026a41206a200341d8016a41286a290300370300200341a8026a41286a2020370300200341a8026a41306a201f370300200341a8026a41106a201b3703002003201c3703c0022003201d3703a8022003201a3703b0020b4200201720011b21174200201820011b2118201d201b7c2220201d5421062005201d562004201a562004201a5122011b0d022005201d542004201a5420011b450d052003201d20057d3703e0022003201a20047d201d200554ad7d3703e8022003200341e0026a36029c0620034198056a41186a220d420037030020034198056a41106a2207420037030020034198056a41086a22024200370300200342003703980541b6fdc600ad4280808080800184221f1001220c290000211d200341c0066a41086a2201200c41086a2900003703002003201d3703c006200c103520022001290300370300200320032903c0063703980541e489c200ad4280808080d0018422211001220c290000211d2001200c41086a2900003703002003201d3703c006200c1035200720032903c006221d370300200341a0066a41086a220e2002290300370300200341a0066a41106a220f201d370300200341a0066a41186a2210200129030037030020032003290398053703a006200341e8006a200341a0066a412010d701200341e8006a41106a2903002122200329037021232003280268210c20032903e802212420032903e002211d200d420037030020074200370300200242003703002003420037039805201f1001220d290000211f2001200d41086a2900003703002003201f3703c006200d103520022001290300370300200320032903c0063703980520211001220d290000211f2001200d41086a2900003703002003201f3703c006200d1035200720032903c006221f370300200e2002290300370300200f201f3703002010200129030037030020032003290398053703a0062003420020224200200c1b221f20247d20234200200c1b2221201d54ad7d22222021201d7d221d2021562022201f562022201f511b22011b3703a00520034200201d20011b37039805200341a0066aad428080808080048420034198056aad428080808080028410020c050b200141d8006a2903002104200141d0006a290300210520034198036a41206a2206200141246a28020036020020034198036a41186a22072001411c6a29020037030020034198036a41106a2208200141146a29020037030020034198036a41086a22092001410c6a290200370300200320012902043703980320034198046a41206a200141c8006a28020036020020034198046a41186a200141c0006a29020037030020034198046a41106a200141386a29020037030020034198046a41086a200141306a2902003703002003200141286a29020037039804410221010240024020022d000120022d0000410047720d0020034198056a41206a200628020036020020034198056a41186a200729030037030020034198056a41106a200829030037030020034198056a41086a2009290300370300200320032903980337039805200341d8016a20034198056a108b024101210120032d00d8014101460d00200341d8016a41086a2d00002101200341e1016a22022f00002106200341e3016a2d00002107200341d8016a410c6a2d00002108200341e5016a2f00002109200341e7016a2d0000210a200341d8016a41106a2d0000210b200341e9016a220c2f0000210d200341eb016a2d0000210e200341d8016a41146a2d0000210f200341ed016a2f00002110200341ef016a2d00002111200341d8016a41186a2d0000211220032f00d901211320032d00db01211420032d00dc01211520032f00dd01211620032d00df0121252003200341f1016a22262900003703c002200320123a00bf02200320113a00be02200320103b01bc022003200f3a00bb022003200e3a00ba022003200d3b01b8022003200b3a00b7022003200a3a00b602200320093b01b402200320083a00b302200320073a00b202200320063b01b002200320013a00af02200320253a00ae02200320163b01ac02200320153a00ab02200320143a00aa02200320133b01a80220034198056a41206a20034198046a41206a28020036020020034198056a41186a20034198046a41186a29030037030020034198056a41106a20034198046a41106a29030037030020034198056a41086a20034198046a41086a290300370300200320032903980437039805200341d8016a20034198056a108b02200341a0066a41086a22012002290000370300200341a0066a41106a2202200c290000370300200341a0066a41186a22062026290000370300200320032900d9013703a006024020032d00d8014101460d00200341e0026a41186a2006290300370300200341e0026a41106a2002290300370300200341e0026a41086a2001290300370300200320032903a0063703e00220034198056a200341a8026a200341e0026a20052004410110e60220032d00980522014104460d0820032f00990520032d009b05411074722102200329029c0521040c020b410121010b0b200042003703082000411c6a2004370200200041186a20024108742001723602000c030b200141306a2903002104200141286a2903002105200341b8046a200141246a28020036020020034198046a41186a2001411c6a29020037030020034198046a41106a200141146a29020037030020034198046a41086a2001410c6a2902003703002003200129020437039804410221010240024020022d00000d0020022d00014101470d00200241196a2d00002101200241186a2d00002106200241166a2f01002107200241156a2d00002108200241146a2d00002109200241126a2f0100210a200241116a2d0000210b200241106a2d0000210c2002410e6a2f0100210d2002410d6a2d0000210e2002410c6a2d0000210f2002410a6a2f01002110200241096a2d00002111200241086a2d00002112200241066a2f01002113200241056a2d00002114200241046a2d00002115200241026a2f0100211620032002411a6a2901003703f802200320013a00f702200320063a00f602200320073b01f402200320083a00f302200320093a00f2022003200a3b01f0022003200b3a00ef022003200c3a00ee022003200d3b01ec022003200e3a00eb022003200f3a00ea02200320103b01e802200320113a00e702200320123a00e602200320133b01e402200320143a00e302200320153a00e202200320163b01e00220034198056a41206a20034198046a41206a28020036020020034198056a41186a20034198046a41186a29030037030020034198056a41106a20034198046a41106a29030037030020034198056a41086a20034198046a41086a29030037030020032003290398043703980520034198036a20034198056a108b02200341a0066a41086a2201200341a1036a290000370300200341a0066a41106a2202200341a9036a290000370300200341a0066a41186a2206200341b1036a29000037030020032003290099033703a006024020032d0098034101460d00200341d8016a41186a2006290300370300200341d8016a41106a2002290300370300200341d8016a41086a2001290300370300200320032903a0063703d80120034198056a200341e0026a200341d8016a20052004410010e60220032d00980522014104460d0720032f00990520032d009b05411074722102200329029c0521040c020b410121010b0b200042003703082000411c6a2004370200200041186a20024108742001723602000c020b20032005201d7d3703e00220032004201a7d2005201d54ad7d3703e8022003200341e0026a36029c0620034198056a41186a220d420037030020034198056a41106a2207420037030020034198056a41086a22024200370300200342003703980541b6fdc600ad4280808080800184221d1001220c290000211f200341c0066a41086a2201200c41086a2900003703002003201f3703c006200c103520022001290300370300200320032903c0063703980541e489c200ad4280808080d00184221f1001220c29000021212001200c41086a290000370300200320213703c006200c1035200720032903c0062221370300200341a0066a41086a220e2002290300370300200341a0066a41106a220f2021370300200341a0066a41186a2210200129030037030020032003290398053703a006200341d0006a200341a0066a412010d701200341d0006a41106a2903002121200329035821222003280250210c20032903e802212320032903e0022124200d420037030020074200370300200242003703002003420037039805201d1001220d290000211d2001200d41086a2900003703002003201d3703c006200d103520022001290300370300200320032903c00637039805201f1001220d290000211d2001200d41086a2900003703002003201d3703c006200d1035200720032903c006221d370300200e2002290300370300200f201d3703002010200129030037030020032003290398053703a0062003427f202320214200200c1b221d7c202420224200200c1b221f7c2221201f542201ad7c221f2001201f201d54201f201d511b22011b3703a0052003427f202120011b37039805200341a0066aad428080808080048420034198056aad428080808080028410020c020b20004200370308200041186a20013602000b420121040c020b201a201c7c211d2006ad211f200341a8026a41106a2101024002402018201b562017201c562017201c5122021b0d002018201b542017201c5420021b450d012003201b20187d3703e0022003201c20177d201b201854ad7d3703e8022003200341e0026a36029c0620034198056a41186a220e420037030020034198056a41106a220c420037030020034198056a41086a22074200370300200342003703980541b6fdc600ad4280808080800184221b1001220d290000211c200341c0066a41086a2202200d41086a2900003703002003201c3703c006200d103520072002290300370300200320032903c0063703980541e489c200ad4280808080d0018422211001220d290000211c2002200d41086a2900003703002003201c3703c006200d1035200c20032903c006221c370300200341a0066a41086a220f2007290300370300200341a0066a41106a2210201c370300200341a0066a41186a2211200229030037030020032003290398053703a006200341386a200341a0066a412010d701200341386a41106a2903002122200329034021232003280238210d20032903e802212420032903e002211c200e4200370300200c4200370300200742003703002003420037039805201b1001220e290000211b2002200e41086a2900003703002003201b3703c006200e103520072002290300370300200320032903c0063703980520211001220e290000211b2002200e41086a2900003703002003201b3703c006200e1035200c20032903c006221b370300200f20072903003703002010201b3703002011200229030037030020032003290398053703a0062003420020224200200d1b221b20247d20234200200d1b2221201c54ad7d22222021201c7d221c2021562022201b562022201b511b22021b3703a00520034200201c20021b37039805200341a0066aad428080808080048420034198056aad428080808080028410020c010b20032018201b7d3703e00220032017201c7d2018201b54ad7d3703e8022003200341e0026a36029c0620034198056a41186a220e420037030020034198056a41106a220c420037030020034198056a41086a22074200370300200342003703980541b6fdc600ad4280808080800184221c1001220d290000211b200341c0066a41086a2202200d41086a2900003703002003201b3703c006200d103520072002290300370300200320032903c0063703980541e489c200ad4280808080d00184221b1001220d29000021212002200d41086a290000370300200320213703c006200d1035200c20032903c0062221370300200341a0066a41086a220f2007290300370300200341a0066a41106a22102021370300200341a0066a41186a2211200229030037030020032003290398053703a006200341206a200341a0066a412010d701200341206a41106a2903002121200329032821222003280220210d20032903e802212320032903e0022124200e4200370300200c4200370300200742003703002003420037039805201c1001220e290000211c2002200e41086a2900003703002003201c3703c006200e103520072002290300370300200320032903c00637039805201b1001220e290000211c2002200e41086a2900003703002003201c3703c006200e1035200c20032903c006221c370300200f20072903003703002010201c3703002011200229030037030020032003290398053703a0062003427f202320214200200d1b221c7c202420224200200d1b221b7c2221201b542202ad7c221b2002201b201c54201b201c511b22021b3703a0052003427f202120021b37039805200341a0066aad428080808080048420034198056aad428080808080028410020b201d201f7c211d200320053703a802200320173703c002200320183703b802200320043703b002200341e0026a41186a200141086a290300221c370300200341e0026a41206a2202200141106a29030037030020034188036a2207200141186a29030037030020034190036a220c200141206a290300370300200320043703e802200320053703e00220032001290300221b3703f00202400240427f2005201b7c221b201b20055422012004201c7c2001ad7c221c200454201c2004511b22011b221b428080e983b1de16544100427f201c20011b221f501b0d00200341e0026a41106a290300211b200c290300211f200729030021212002290300212220032903e802212320032903e00221244201211c20032903f80221270c010b02400240201b201f8450450d004200211c0c010b4200211c20034198056a41186a220d420037030020034198056a41106a2207420037030020034198056a41086a22024200370300200342003703980541b6fdc600ad428080808080018422211001220c2900002122200341c0066a41086a2201200c41086a290000370300200320223703c006200c103520022001290300370300200320032903c0063703980541e489c200ad4280808080d0018422221001220c29000021232001200c41086a290000370300200320233703c006200c1035200720032903c0062223370300200341a0066a41086a220e2002290300370300200341a0066a41106a220f2023370300200341a0066a41186a2210200129030037030020032003290398053703a006200341086a200341a0066a412010d701200341086a41106a2903002123200329031021242003280208210c200d42003703002007420037030020024200370300200342003703980520211001220d29000021212001200d41086a290000370300200320213703c006200d103520022001290300370300200320032903c0063703980520221001220d29000021212001200d41086a290000370300200320213703c006200d1035200720032903c0062221370300200e2002290300370300200f20213703002010200129030037030020032003290398053703a0062003420020234200200c1b2221201f7d20244200200c1b2222201b54ad7d22232022201b7d2224202256202320215620232021511b22011b3703a00520034200202420011b37039805200341a0066aad428080808080048420034198056aad42808080808002841002200341d0056a201f370300200341c8056a201b370300200241013a0000200341a1056a20032903a801370000200341a9056a200341a8016a41086a290300370000200341b1056a200341a8016a41106a290300370000200341b9056a200341a8016a41186a290300370000200341033a00980541b0b4cc00410020034198056a10d4010b0b201d201a512101201d201a54210220034180026a202237030020034188026a2021370300200341e8016a202337030020034190026a201f370300200341f0016a201b370300200320273703f8012003201e37039802200320243703e0012003200b4100201942015122071b3a00a4022003200a410020071b3602a0022003201c4201512207ad3703d8010240024020070d002009ad4220862008ad8410070c010b2003200936029c052003200836029805200341e0016a20034198056a10e7020b2006200220011b2101024020032802cc01450d00200810350b427f201d20011b211a427f202020011b211d201c420152210102400240024020194201510d0020010d004103210220034198046a21010c010b20194201522001410173720d014104210220034198036a21010b200141086a20023a0000200141096a20032903a801370000200141003a0000200141116a200341a8016a41086a290300370000200141196a200341b8016a290300370000200141216a200341c0016a29030037000041b0b4cc004100200110d4010b0240201d201a8450450d00200341d0056a2004370300200341c8056a200537030020034198056a41086a41003a0000200341a1056a20032903a801370000200341a9056a200341a8016a41086a290300370000200341b1056a200341b8016a290300370000200341b9056a200341c0016a290300370000200341033a00980541b0b4cc00410020034198056a10d4010b200341e0056a2017370300200341d8056a2018370300200341d0056a2004370300200341c8056a200537030020034198056a41086a41033a0000200341a1056a20032903a801370000200341a9056a200341a8016a41086a290300370000200341b1056a200341b8016a290300370000200341b9056a200341c0016a290300370000200341033a00980541b0b4cc00410020034198056a10d4010b42002104200042003703080b20002004370300200341d0066a24000b130020004108360204200041e0e4c2003602000b847c05057f027e107f057e037f230041e0036b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802000e0700010203040506000b200341d4026a4101360200200342013702c402200341e8d4ca003602c0022003410436028c022003419cd5ca0036028802200320034188026a3602d002200341c0026a41b0b4cc00104c000b200141086a280200210420012802042105410221064100210720022d00000d1920022d00014101470d19200141186a2903002108200141106a29030021092001410c6a2802002101200241196a2d00002106200241186a2d00002107200241166a2f0100210a200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241086a2d00002115200241066a2f01002116200241056a2d00002117200241046a2d00002118200241026a2f0100211920032002411a6a2901003703b801200320063a00b701200320073a00b6012003200a3b01b4012003200b3a00b3012003200c3a00b2012003200d3b01b0012003200e3a00af012003200f3a00ae01200320103b01ac01200320113a00ab01200320123a00aa01200320133b01a801200320143a00a701200320153a00a601200320163b01a401200320173a00a301200320183a00a201200320193b01a00141a0e4cb00ad428080808080028410012202290000211a2002290008211b2002103541e1b8c800ad4280808080a0018410012202290000211c2002290008211d200210352003201d3701d8022003201c3701d0022003201b3701c8022003201a3701c002200341e8016a200341c0026aad4280808080800484221a100510c201024002400240024020032802e8012202450d0020032802ec0121072003200341f0016a28020036028c022003200236028802200341206a20034188026a10c4012003280220450d01410021060c020b2003420037028c02200341013602880220034188026a108a0321060c020b200328022421060b2007450d00200210350b41a0e4cb00ad428080808080028410012202290000211b2002290008211c200210354189eaca00ad4280808080f0008410012202290000211d2002290008211e200210352003201e3701d8022003201d3701d0022003201c3701c8022003201b3701c002200341e8016a201a100510c201024002400240024020032802e8012202450d0020032802ec01210a2003200341f0016a28020036028c022003200236028802200341186a20034188026a10c4012003280218450d01410021070c020b2003420037028c02200341083602880220034188026a108b0321070c020b200328021c21070b200a450d00200210350b41a0e4cb00ad428080808080028410012202290000211b2002290008211c2002103541c699c200ad428080808090018410012202290000211d2002290008211e200210352003201e3701d8022003201d3701d0022003201c3701c8022003201b3701c002200341e8016a201a100510c201024002400240024020032802e8012202450d0020032802ec01210b2003200341f0016a28020036028c022003200236028802200341106a20034188026a10c4012003280210450d014100210a0c020b2003420037028c02200341083602880220034188026a108b03210a0c020b2003280214210a0b200b450d00200210350b410c21020240200720066a200a6a22060d00418790c2002101410021070c190b0240200120064d0d0041f48fc20021014180800821070c190b0240200141104d0d0041e08fc2002101411421024180800c21070c190b024020010d00418090c2002101410721024180800421070c190b02402009428180e983b1de165441002008501b450d0041d68fc2002101410a21024180801021070c190b200341c0026a200341a0016a10e502200341086a20032802c002220620032802c80241b0b4cc0041004100108a0220032802082102024020032802c402450d00200610350b024020024101460d00200342003703f0012003428080e983b1de163703e8012003200341a0016a3602d0032003200341a0016a3602c8012003200341c8016a3602c8022003200341d0036a3602c4022003200341e8016a3602c00220034188026a200341a0016a200341c0026a108c0302402003280288024101470d0020032d008c024104460d0141c78fc2002101410f21024180801421070c1a0b20034188026a41086a2903004201520d0020034188026a41106a290300211a20032802c8012102200341f8026a20034188026a41186a290300370300200341f0026a201a370300200341c0026a41086a41003a0000200341c9026a2002290000370000200341d1026a200241086a290000370000200341d9026a200241106a290000370000200341e1026a200241186a290000370000200341033a00c00241b0b4cc004100200341c0026a10d4010b20034188026a200341a0016a108e02200341c0026a2003280288022207200328029002108f02200341d0026a290300420020032903c00242015122021b211a20032903c802420020021b211b200341e0026a290300420020021b211c200341d8026a2206290300420020021b211d0240200328028c02450d00200710350b200342f0d0c9abc6add9b1f4003703d003200341d0036a200341a0016a427f201b201d7c221d201d201b542202201a201c7c2002ad7c221b201a54201b201a511b22021b221a2009201a200954427f201b20021b221a200854201a2008511b22021b221b201a200820021b221a411e10900220062001360200200341d4026a20043602002003201a3703c8022003201b3703c002200320053602d00220034188026a200341a0016a10e502200328028802210220032003280290023602ec01200320023602e801200341c0026a200341e8016a108d030240200328028c02450d00200210350b200441ffffff3f71450d17200510350c170b41829a182101024020022d00000d0020022d00014101470d00200241196a2d00002101200241186a2d00002106200241166a2f01002107200241156a2d00002104200241146a2d00002105200241126a2f0100210a200241116a2d0000210b200241106a2d0000210c2002410e6a2f0100210d2002410d6a2d0000210e2002410c6a2d0000210f2002410a6a2f01002110200241096a2d00002111200241086a2d00002112200241066a2f01002113200241056a2d00002114200241046a2d00002115200241026a2f0100211620032002411a6a2901003703b801200320013a00b701200320063a00b601200320073b01b401200320043a00b301200320053a00b2012003200a3b01b0012003200b3a00af012003200c3a00ae012003200d3b01ac012003200e3a00ab012003200f3a00aa01200320103b01a801200320113a00a701200320123a00a601200320133b01a401200320143a00a301200320153a00a201200320163b01a001200341c0026a200341a0016a10e502200341286a20032802c002220120032802c80241b0b4cc0041004100108a0220032802282102024020032802c402450d00200110350b41839a18210120024101470d00200341c0026a200341a0016a10e50220033502c80242208620032802c0022202ad841007024020032802c402450d00200210350b200342f0d0c9abc6add9b1f4003703d00320034188026a200341a0016a10eb022003280288022113024020032802900222070d00410021070c170b200341c0036a210a4100210120132102410021060340024002400240200a2002460d00200241106a220529000020032903d003510d0020010d01410021010c020b200141016a21010c010b200620016b220420074f0d07200341c0026a41186a220b200220014105746b220441186a220c290300370300200341c0026a41106a220d200441106a220e290300370300200341c0026a41086a220f200441086a2210290300370300200320042903003703c002200241086a2211290300211a2005290300211b200241186a2212290300211c20042002290300370300200c201c370300200e201b3703002010201a3703002012200b2903003703002005200d2903003703002011200f290300370300200220032903c0023703000b200241206a21022007200641016a2206460d160c000b0b20004200370308200041206a410b3602002000411c6a41bc8fc200360200200041186a20013602004201211a0c1a0b200341c0016a200141246a280200360200200341a0016a41186a2001411c6a290200370300200341a0016a41106a200141146a290200370300200341a0016a41086a2001410c6a290200370300200320012902043703a0012002411a6a290100211a200241196a2d00002106200241186a2d00002107200241166a2f01002104200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241086a2d00002114200241066a2f01002115200241056a2d00002116200241046a2d0000211741022101200241026a2f0100211841012105024020022d00000d0020022d000141014721050b2003201a3701d802200320063a00d702200320073a00d602200320043b01d4022003200a3a00d3022003200b3a00d2022003200c3b01d0022003200d3a00cf022003200e3a00ce022003200f3b01cc02200320103a00cb02200320113a00ca02200320123b01c802200320133a00c702200320143a00c602200320153b01c402200320163a00c302200320173a00c202200320183b01c0024100210a4100210641002102024020050d00200341c8016a41186a200341c0026a41186a2202290100370300200341c8016a41106a200341c0026a41106a2201290100370300200341c8016a41086a200341c0026a41086a2206290100370300200320032901c0023703c801200341c0026a41206a200341a0016a41206a2802003602002002200341a0016a41186a2903003703002001200341a0016a41106a2903003703002006200341a0016a41086a290300370300200320032903a0013703c00220034188026a200341c0026a108b0241012101410021064100210220032d0088024101460d0020034188026a41086a2d0000210220034191026a2f0000210120034193026a2d0000210620034194026a2d0000210720034195026a2f0000210420034197026a2d0000210520034188026a41106a2d0000210b20034199026a2f0000210c2003419b026a2d0000210d2003419c026a2d0000210e2003419d026a2f0000210f2003419f026a2d0000211020034188026a41186a2d0000211120032f008902211220032d008b02211320032d008c02211420032f008d02211520032d008f0221162003200341a1026a29000037038002200320113a00ff01200320103a00fe012003200f3b01fc012003200e3a00fb012003200d3a00fa012003200c3b01f8012003200b3a00f701200320053a00f601200320043b01f401200320073a00f301200320063a00f201200320013b01f001200320023a00ef01200320163a00ee01200320153b01ec01200320143a00eb01200320133a00ea01200320123b01e8014103210141801a21020240200341c8016a200341e8016a412010a0080d0041b28fc2002104410a21074180801c21060c010b200341c0026a200341c8016a10e502200341e8006a20032802c002220720032802c80241b0b4cc0041004100108a0220032802682106024020032802c402450d00200710350b024020064101460d0041bc8fc2002104410b21074180801821060c010b200341c0026a200341e8016a10e502200341e0006a20032802c002220120032802c80241b0b4cc0041004100108a0220032802602102024020032802c402450d00200110350b02400240024002400240024020024101470d0020034188026a200341e8016a10e502200341c0026a200328028802220120032802900210cc0220032902d402420020032802d00222021b211a2002410120021b210d0240200328028c02450d00200110350b200d201a422088a74105746a210e200341c0026a41106a2105200d210603402006200e460d020240200610e9020d00200641206a2110200341c0026a41186a220b420037030020054200370300200341c0026a41086a220a4200370300200342003703c00241a0e4cb00ad4280808080800284221c10012202290000211b200a200241086a2900003703002003201b3703c0022002103541c699c200ad428080808090018410012202290000211b200341d0036a41086a220c200241086a2900003703002003201b3703d00320021035200520032903d003370000200541086a2211200c29030037000020034188026a41086a2212200a29030037030020034188026a41106a2213200529030037030020034188026a41186a2214200b290300370300200320032903c00237038802200341c0026a20034188026a10a20220032902c402420020032802c00222021b221b422088a741306c2101410021072002410820021b220f2102024003402001450d01024020062002460d0020022006412010a0082104200741016a2107200141506a2101200241306a210220040d010b0b201ba72202450d01200241306c450d01200f10350c010b0240201ba72202450d00200241306c450d00200f10350b200b420037030020054200370300200a4200370300200342003703c002201c10012202290000211b200a200241086a2900003703002003201b3703c0022002103541e1b8c800ad4280808080a0018410012202290000211b200c200241086a2900003703002003201b3703d00320021035200520032903d0033700002011200c2903003700002012200a290300370300201320052903003703002014200b290300370300200320032903c00237038802200341c0026a20034188026a10fe0120032802c0022201410120011b210a4100210202400240024020032902c402420020011b221b422088a7220141014b0d0020010e020201020b03402001410176220720026a22042002200a20044105746a2006412010a0084101481b2102200120076b220141014b0d000b0b200a20024105746a2006412010a0084521020b0240201b42ffffff3f83500d00200a10350b201021062002450d010b0b201a42ffffff3f83500d00200d10350b200342003703d8032003428080e983b1de163703d0032003200341c8016a3602c00320034188026a200341c8016a200341d0036a200341c0036a10a802200341a8026a290300211b20032903a002211a02402003290388024201520d00200329039002211c200341f8026a20034188026a41106a290300370300200341f0026a201c370300200341c0026a41086a41003a0000200341c9026a20032903c801370000200341d1026a200341c8016a41086a290300370000200341d9026a200341c8016a41106a290300370000200341e1026a200341e0016a290300370000200341033a00c00241b0b4cc004100200341c0026a10d4010b2003201a3703c0032003201b3703c803201a201b844200520d01200341c0026a41186a22044200370300200341c0026a41106a22064200370300200341c0026a41086a22014200370300200342003703c00241b6fdc600ad4280808080800184221a10012207290000211b200341d0036a41086a2202200741086a2900003703002003201b3703d0032007103520012002290300370300200320032903d0033703c00241e489c200ad4280808080d00184221b10012207290000211c2002200741086a2900003703002003201c3703d00320071035200620032903d003221c37030020034188026a41086a2205200129030037030020034188026a41106a220a201c37030020034188026a41186a220b2002290300370300200320032903c00237038802200341306a20034188026a412010d701200341306a41106a290300211c2003290338211d20032802302107200442003703002006420037030020014200370300200342003703c002201a10012204290000211a2002200441086a2900003703002003201a3703d0032004103520012002290300370300200320032903d0033703c002201b10012204290000211a2002200441086a2900003703002003201a3703d00320041035200620032903d003221a37030020052001290300370300200a201a370300200b2002290300370300200320032903c002370388022003201c420020071b3703c8022003201d420020071b3703c00220034188026aad4280808080800484200341c0026aad428080808080028410020c020b0240201a42ffffff3f83500d00200d10350b200341c0026a200341e8016a200341c8016a428080e983b1de164200410010ef0220032802c0024101460d03200341c0026a200341e8016a10e50220033502c80242208620032802c0022202ad841007024020032802c402450d00200210350b200342f0d0c9abc6add9b1f4003703d00320034188026a200341e8016a10eb02200328028802211320032802900222070d02410021070c140b2003201a3703c0032003201b3703c803200341c0026a41186a22044200370300200341c0026a41106a22064200370300200341c0026a41086a22014200370300200342003703c00241b6fdc600ad4280808080800184221c10012207290000211d200341d0036a41086a2202200741086a2900003703002003201d3703d0032007103520012002290300370300200320032903d0033703c00241e489c200ad4280808080d00184221d10012207290000211e2002200741086a2900003703002003201e3703d00320071035200620032903d003221e37030020034188026a41086a2205200129030037030020034188026a41106a220a201e37030020034188026a41186a220b2002290300370300200320032903c00237038802200341c8006a20034188026a412010d701200341c8006a41106a290300211e2003290350210820032802482107200442003703002006420037030020014200370300200342003703c002201c10012204290000211c2002200441086a2900003703002003201c3703d0032004103520012002290300370300200320032903d0033703c002201d10012204290000211c2002200441086a2900003703002003201c3703d00320041035200620032903d003221c37030020052001290300370300200a201c370300200b2002290300370300200320032903c0023703880220034200201e420020071b221c201b7d2008420020071b221b201a54ad7d221d201b201a7d221a201b56201d201c56201d201c511b22021b3703c80220034200201a20021b3703c00220034188026aad4280808080800484200341c0026aad428080808080028410020b200341c0026a200341c8016a10e50220033502c80242208620032802c0022202ad841007024020032802c402450d00200210350b200342f0d0c9abc6add9b1f4003703d00320034188026a200341c8016a10eb02410021142003280288022113410021022003280290022207450d14200341c0036a210a4100210120132102410021060340024002400240200a2002460d00200241106a220529000020032903d003510d0020010d01410021010c020b200141016a21010c010b200620016b220420074f0d09200341c0026a41186a220b200220014105746b220441186a220c290300370300200341c0026a41106a220d200441106a220e290300370300200341c0026a41086a220f200441086a2210290300370300200320042903003703c002200241086a2211290300211a2005290300211b200241186a2212290300211c20042002290300370300200c201c370300200e201b3703002010201a3703002012200b2903003703002005200d2903003703002011200f290300370300200220032903c0023703000b200241206a21022007200641016a2206460d140c000b0b200341c0036a210a4100210120132102410021060340024002400240200a2002460d00200241106a220529000020032903d003510d0020010d01410021010c020b200141016a21010c010b200620016b220420074f0d09200341c0026a41186a220b200220014105746b220441186a220c290300370300200341c0026a41106a220d200441106a220e290300370300200341c0026a41086a220f200441086a2210290300370300200320042903003703c002200241086a2211290300211a2005290300211b200241186a2212290300211c20042002290300370300200c201c370300200e201b3703002010201a3703002012200b2903003703002005200d2903003703002011200f290300370300200220032903c0023703000b200241206a21022007200641016a2206460d110c000b0b20032802c402220541ff017122014104460d16200341cc026a2802002107200341c8026a280200210420054180fe037121022005418080fc077121062005418080807871210a0b20004200370308200041206a20073602002000411c6a2004360200200041186a200a2006722002722001723602004201211a0c190b410221014100210620022d00000d0b20022d00014101470d0b200241196a2d00002101200241186a2d00002106200241166a2f01002107200241156a2d00002104200241146a2d00002105200241126a2f0100210a200241116a2d0000210b200241106a2d0000210c2002410e6a2f0100210d2002410d6a2d0000210e2002410c6a2d0000210f2002410a6a2f01002110200241096a2d00002111200241086a2d00002112200241066a2f01002113200241056a2d00002114200241046a2d00002115200241026a2f0100211620032002411a6a2901003703b801200320013a00b701200320063a00b601200320073b01b401200320043a00b301200320053a00b2012003200a3b01b0012003200b3a00af012003200c3a00ae012003200d3b01ac012003200e3a00ab012003200f3a00aa01200320103b01a801200320113a00a701200320123a00a601200320133b01a401200320143a00a301200320153a00a201200320163b01a001200341c0026a41186a4200370300200341c0026a41106a22054200370300200341c0026a41086a22024200370300200342003703c00241a0e4cb00ad428080808080028410012201290000211a2002200141086a2900003703002003201a3703c0022001103541e1b8c800ad4280808080a0018410012201290000211a200341d0036a41086a2206200141086a2900003703002003201a3703d00320011035200520032903d003221a37030020034188026a41086a200229030037030020034188026a41106a201a37030020034188026a41186a2006290300370300200320032903c00237038802200341c0026a20034188026a10fe0120032802c0022201410120011b21044100210a41002102024020032902c402420020011b221a422088a7220141014b0d004100210b20010e020b0a0b0b03402001410176220620026a22072002200420074105746a200341a0016a412010a0084101481b2102200120066b220141014b0d000c0a0b0b410221010240024020022d00000d0020022d00014101470d00200241196a2d00002101200241186a2d00002106200241166a2f01002107200241156a2d00002104200241146a2d00002105200241126a2f0100210a200241116a2d0000210b200241106a2d0000210c2002410e6a2f0100210d2002410d6a2d0000210e2002410c6a2d0000210f2002410a6a2f01002110200241096a2d00002111200241086a2d00002112200241066a2f01002113200241056a2d00002114200241046a2d00002115200241026a2f0100211620032002411a6a2901003703b801200320013a00b701200320063a00b601200320073b01b401200320043a00b301200320053a00b2012003200a3b01b0012003200b3a00af012003200c3a00ae012003200d3b01ac012003200e3a00ab012003200f3a00aa01200320103b01a801200320113a00a701200320123a00a601200320133b01a401200320143a00a301200320153a00a201200320163b01a001200341c8016a200341a0016a108e030240024002400240024020032d00c801450d00200341c0026a41186a4200370300200341c0026a41106a22044200370300200341c0026a41086a22024200370300200342003703c00241a0e4cb00ad428080808080028410012201290000211a2002200141086a2900003703002003201a3703c0022001103541c699c200ad428080808090018410012201290000211a200341d0036a41086a2206200141086a2900003703002003201a3703d00320011035200420032903d003221a37030020034188026a41086a200229030037030020034188026a41106a201a37030020034188026a41186a2006290300370300200320032903c00237038802200341c0026a20034188026a10a20220032902c402420020032802c00222021b221a422088a7220a41306c2101410021062002410820021b22052102024003402001450d03200341a0016a2002460d01200641016a2106200141506a21012002200341a0016a412010a0082107200241306a210220070d000b20074541016a41017120066a417f6a21060b2005200641306c6a2202200241306a2006417f73200a6a41306c109e081a200342003703f00120034280809aa6eaafe3013703e8012003200341a0016a3602c80120034188026a200341a0016a200341e8016a200341c8016a10f00202402003290388024201520d00200329039002211b200341f8026a20034188026a41106a290300370300200341c0026a41306a201b370300200341c0026a41086a41003a0000200341c9026a20032903a001370000200341d1026a200341a0016a41086a290300370000200341d9026a200341a0016a41106a290300370000200341e1026a200341b8016a290300370000200341033a00c00241b0b4cc004100200341c0026a10d4010b41a0e4cb00ad428080808080028410012202290000211b2002290008211c2002103541c699c200ad428080808090018410012202290000211d2002290008211e200210352003201e3701d8022003201d3701d0022003201c3701c8022003201b3701c0022003412036028c022003200341c0026a360288022005200a417f6a20034188026a10a902201aa72202450d03200241306c0d020c030b200342003703f00120034280809aa6eaafe3013703e8012003200341a0016a3602d00320034188026a200341a0016a200341e8016a200341d0036a10f00202402003290388024201520d00200329039002211a200341f8026a20034188026a41106a290300370300200341f0026a201a370300200341c0026a41086a41003a0000200341c9026a20032903a001370000200341d1026a200341a0016a41086a290300370000200341d9026a200341a0016a41106a290300370000200341e1026a200341b8016a290300370000200341033a00c00241b0b4cc004100200341c0026a10d4010b200341cd026a200341a8016a290300370000200341d5026a200341b0016a290300370000200341dd026a200341b8016a290300370000200341033a00c402200341093a00c002200320032903a0013700c50241b0b4cc004100200341c0026a10d4014200211a0c050b200341c0026a41186a22064200370300200341c0026a41106a22074200370300200341c0026a41086a22024200370300200342003703c00241a0e4cb00ad428080808080028410012201290000211b2002200141086a2900003703002003201b3703c0022001103541e1b8c800ad4280808080a0018410012201290000211b200341d0036a41086a220a200141086a2900003703002003201b3703d00320011035200420032903d003370000200441086a200a29030037000020034188026a41086a200229030037030020034188026a41106a200729030037030020034188026a41186a2006290300370300200320032903c00237038802200341c0026a20034188026a10fe0120032802c0022201410120011b2104410021020240024020032902c402420020011b221b422088a7220a41014b0d00200a0e020401040b200a210103402001410176220620026a22072002200420074105746a200341a0016a412010a0084101481b2102200120066b220141014b0d000b0b200420024105746a200341a0016a412010a0080d022002200a4f0d09200420024105746a2201200141206a2002417f73200a6a410574109e081a200342003703f00120034280809aa6eaafe3013703e8012003200341a0016a3602c80120034188026a200341a0016a200341e8016a200341c8016a10f00202402003290388024201520d00200329039002211c200341f8026a20034188026a41106a290300370300200341f0026a201c370300200341c0026a41086a41003a0000200341c9026a20032903a001370000200341d1026a200341a0016a41086a290300370000200341d9026a200341a0016a41106a290300370000200341e1026a200341b8016a290300370000200341033a00c00241b0b4cc004100200341c0026a10d4010b41a0e4cb00ad428080808080028410012202290000211c2002290008211d2002103541e1b8c800ad4280808080a0018410012202290000211e2002290008210820021035200320083701d8022003201e3701d0022003201d3701c8022003201c3701c0022003412036028c022003200341c0026a360288022004200a417f6a20034188026a1098020240201b42ffffff3f83500d00200410350b201aa72202450d01200241306c450d010b200510350b4200211a0c020b0240201b42ffffff3f83500d00200410350b0240201aa72202450d00200241306c450d00200510350b410321010b200041206a410d3602002000411c6a41e08ec200360200200041186a200141809a30723602004201211a0b200042003703080c170b200341a0016a41206a2207200141246a280200360200200341a0016a41186a22042001411c6a290200370300200341a0016a41106a2205200141146a290200370300200341a0016a41086a220a2001410c6a290200370300200320012902043703a001410021064102210120022d000120022d0000410047720d04200341c0026a41206a2007280200360200200341c0026a41186a2004290300370300200341c0026a41106a2005290300370300200341c0026a41086a200a290300370300200320032903a0013703c00220034188026a200341c0026a108b024101210120032d0088024101460d0420034188026a41086a2d0000210220034191026a2f0000210120034193026a2d0000210620034188026a410c6a2d0000210720034195026a2f0000210420034197026a2d0000210520034188026a41106a2d0000210a20034199026a2f0000210b2003419b026a2d0000210c20034188026a41146a2d0000210d2003419d026a2f0000210e2003419f026a2d0000210f20034188026a41186a2d0000211020032f008902211120032d008b02211220032d008c02211320032f008d02211420032d008f0221152003200341a1026a29000037038002200320103a00ff012003200f3a00fe012003200e3b01fc012003200d3a00fb012003200c3a00fa012003200b3b01f8012003200a3a00f701200320053a00f601200320043b01f401200320073a00f301200320063a00f201200320013b01f001200320023a00ef01200320153a00ee01200320143b01ec01200320133a00eb01200320123a00ea01200320113b01e801200341c0036a200341e8016a108e03024020032d00c0034101460d0020032d00c1032107200342003703d00120034280809aa6eaafe3013703c8012003200341e8016a3602d00320034188026a200341e8016a200341c8016a200341d0036a10a802200341a8026a290300211b20032903a002211a02402003290388024201520d00200329039002211c200341f8026a20034188026a41106a290300370300200341f0026a201c370300200341c0026a41086a41003a0000200341c9026a20032903e801370000200341d1026a200341e8016a41086a290300370000200341d9026a200341e8016a41106a290300370000200341e1026a20034180026a290300370000200341033a00c00241b0b4cc004100200341c0026a10d4010b2003201a3703d0032003201b3703d80302400240201a201b844200520d00200341c0026a41186a22054200370300200341c0026a41106a22064200370300200341c0026a41086a22014200370300200342003703c00241b6fdc600ad4280808080800184221a10012204290000211b200341c8016a41086a2202200441086a2900003703002003201b3703c8012004103520012002290300370300200320032903c8013703c00241e489c200ad4280808080d00184221b10012204290000211c2002200441086a2900003703002003201c3703c80120041035200620032903c801221c37030020034188026a41086a220a200129030037030020034188026a41106a220b201c37030020034188026a41186a220c2002290300370300200320032903c00237038802200341f0006a20034188026a412010d701200341f0006a41106a290300211c2003290378211d20032802702104200542003703002006420037030020014200370300200342003703c002201a10012205290000211a2002200541086a2900003703002003201a3703c8012005103520012002290300370300200320032903c8013703c002201b10012205290000211a2002200541086a2900003703002003201a3703c80120051035200620032903c801221a370300200a2001290300370300200b201a370300200c2002290300370300200320032903c002370388022003201c420020041b3703c8022003201d420020041b3703c00220034188026aad4280808080800484200341c0026aad428080808080028410020c010b2003201a3703d0032003201b3703d803200341c0026a41186a22054200370300200341c0026a41106a22064200370300200341c0026a41086a22014200370300200342003703c00241b6fdc600ad4280808080800184221c10012204290000211d200341c8016a41086a2202200441086a2900003703002003201d3703c8012004103520012002290300370300200320032903c8013703c00241e489c200ad4280808080d00184221d10012204290000211e2002200441086a2900003703002003201e3703c80120041035200620032903c801221e37030020034188026a41086a220a200129030037030020034188026a41106a220b201e37030020034188026a41186a220c2002290300370300200320032903c0023703880220034188016a20034188026a412010d70120034188016a41106a290300211e20032903900121082003280288012104200542003703002006420037030020014200370300200342003703c002201c10012205290000211c2002200541086a2900003703002003201c3703c8012005103520012002290300370300200320032903c8013703c002201d10012205290000211c2002200541086a2900003703002003201c3703c80120051035200620032903c801221c370300200a2001290300370300200b201c370300200c2002290300370300200320032903c0023703880220034200201e420020041b221c201b7d2008420020041b221b201a54ad7d221d201b201a7d221a201b56201d201c56201d201c511b22021b3703c80220034200201a20021b3703c00220034188026aad4280808080800484200341c0026aad428080808080028410020b200341cd026a200341f0016a290300370000200341d5026a200341f8016a290300370000200341dd026a20034180026a290300370000200341023a00c402200341093a00c002200320032903e8013700c50241b0b4cc004100200341c0026a10d4010240200741ff01710d0010a1020b4200211a0c070b4200211a20032802c403220141ff01714104460d06200141807e712106200341c8036a290300211a0c050b2004200741f485cc001042000b2004200741f485cc001042000b2004200741f485cc001042000b2002200a104e000b0b2000411c6a201a370200200041186a2006200141ff0171723602004201211a0b200042003703080c0f0b0240200420024105746a200341a0016a412010a00822010d004101210a2002210b0c010b2001411f7620026a210b0b0240201a42ffffff3f83500d00200410350b02400240200a450d00419f8fc2002102411321074180802021060c010b410c21070240200341a0016a10e902450d0041938fc20021024180802421060c010b200341c0026a41186a22064200370300200341c0026a41106a22044200370300200341c0026a41086a22024200370300200342003703c00241a0e4cb00ad428080808080028410012201290000211a2002200141086a2900003703002003201a3703c0022001103541c699c200ad428080808090018410012201290000211a200341d0036a41086a220a200141086a2900003703002003201a3703d00320011035200520032903d003370000200541086a200a29030037000020034188026a41086a200229030037030020034188026a41106a200429030037030020034188026a41186a2006290300370300200320032903c00237038802200341c0026a20034188026a10a20220032902c402420020032802c00222021b221a422088a741306c2101410021062002410820021b220a2102024003402001450d010240200341a0016a2002460d00200641016a2106200141506a21012002200341a0016a412010a0082104200241306a210220040d010b0b41878fc2002102418080282106201aa72201450d01200141306c450d01200a10350c010b0240201aa72202450d00200241306c450d00200a10350b200342003703f00120034280809aa6eaafe3013703e8012003200341a0016a3602d0032003200341a0016a3602c8012003200341c8016a3602c8022003200341d0036a3602c4022003200341e8016a3602c00220034188026a200341a0016a200341c0026a108c03024002402003280288024101470d0020032d008c024104460d0141ed8ec2002102411a21074180802c21060c020b20034188026a41086a2903004201520d0020034188026a41106a290300211a20032802c8012102200341f8026a20034188026a41186a290300370300200341f0026a201a370300200341c0026a41086a41003a0000200341c9026a2002290000370000200341d1026a200241086a290000370000200341d9026a200241106a290000370000200341e1026a200241186a290000370000200341033a00c00241b0b4cc004100200341c0026a10d4010b20032903b801211a20032d00b701210420032d00b601210a20032f01b401210c20032d00b301210d20032d00b201210e20032f01b001210f20032d00af01211020032d00ae01211120032f01ac01211220032d00ab01211320032d00aa01211420032f01a801211520032d00a701211620032d00a601211720032f01a401211820032d00a301211920032d00a201211f20032f01a0012120200341c0026a41186a22064200370300200341c0026a41106a22074200370300200341c0026a41086a22024200370300200342003703c00241a0e4cb00ad428080808080028410012201290000211b2002200141086a2900003703002003201b3703c0022001103541e1b8c800ad4280808080a0018410012201290000211b200341d0036a41086a2221200141086a2900003703002003201b3703d00320011035200520032903d003370000200541086a202129030037000020034188026a41086a200229030037030020034188026a41106a200729030037030020034188026a41186a2006290300370300200320032903c00237038802200341c0026a20034188026a10fe010240024020032802c00222010d00410021072003410036029002200342013703880241012101410021060c010b200320032902c402221b37028c022003200136028802201b422088a72106201ba721070b02402006200b490d00024020062007470d0020034188026a20074101108a01200328028c02210720032802880221010b2001200b4105746a220241206a20022006200b6b410574109e081a2002201a370018200220043a00172002200a3a00162002200c3b00142002200d3a00132002200e3a00122002200f3b0010200220103a000f200220113a000e200220123b000c200220133a000b200220143a000a200220153b0008200220163a0007200220173a0006200220183b0004200220193a00032002201f3a0002200220203b00002003200641016a22063602900241a0e4cb00ad428080808080028410012202290000211a2002290008211b2002103541e1b8c800ad4280808080a0018410012202290000211c2002290008211d200210352003201d3701d8022003201c3701d0022003201b3701c8022003201a3701c002024020010d00200341c0026aad428080808080048410070c0c0b200341203602ec012003200341c0026a3602e80120012006200341e8016a109802200741ffffff3f71450d0b200110350c0b0b200b2006104d000b410321010c010b0b20004200370308200041206a20073602002000411c6a2002360200200041186a20064180803c7120017241801a723602004201211a0c0b0b2001417f6a20074f0d002003200720016b2207360290020b200341e8016a2013200710ec0241012114200328028c0241ffffff3f71450d02201310350c020b02402001417f6a2007490d00200721020c010b2003200720016b2202360290020b200341c8016a2013200210ec02200328028c0241ffffff3f71450d00201310350b200341cd026a200341e8016a41086a290300370000200341d5026a200341e8016a41106a290300370000200341dd026a200341e8016a41186a290300370000200341e5026a20032903c801370000200341ed026a200341c8016a41086a290300370000200341f5026a200341c8016a41106a290300370000200341fd026a200341c8016a41186a290300370000200341043a00c402200341093a00c002200320032903e8013700c50220034185036a20143a000041b0b4cc004100200341c0026a10d4010c020b2001417f6a20074f0d002003200720016b2207360290020b200341a0016a2013200710ec020240200328028c0241ffffff3f71450d00201310350b4200211a200342003703f0012003428080e983b1de163703e8012003200341a0016a3602c80120034188026a200341a0016a200341e8016a200341c8016a10f00202402003290388024201520d00200329039002211b200341f8026a20034188026a41106a290300370300200341f0026a201b370300200341c0026a41086a41003a0000200341c9026a20032903a001370000200341d1026a200341a0016a41086a290300370000200341d9026a200341a0016a41106a290300370000200341e1026a200341b8016a290300370000200341033a00c00241b0b4cc004100200341c0026a10d4010b200042003703080c040b4200211a200042003703080c030b410321060c010b0b0240200441ffffff3f71450d00200510350b20004200370308200041206a20023602002000411c6a2001360200200041186a20074180801c7120067241801a723602004201211a0b2000201a370300200341e0036a24000bbb0201097f230041106b22012400024002402000280208220241ffffff3f712002470d0020024105742203417f4c0d00200028020021040240024020030d00410121050c010b200310332205450d020b41002100200141003602082001200536020020012003410576360204200141002002108a01200128020821060240024020020d00200128020021070c010b200241057421082001280200220720064105746a21090340200920006a2203200420006a2205290000370000200341186a200541186a290000370000200341106a200541106a290000370000200341086a200541086a2900003700002008200041206a2200470d000b200241057441606a41057620066a41016a21060b200641057441057521000240200128020441ffffff3f71450d00200710350b200141106a240020000f0b1044000b1045000be30204027f017e037f037e230041106b220124000240024020002802082202ad42307e2203422088a70d002003a72204417f4c0d00200028020021000240024020040d00410821050c010b200410332205450d020b20014100360208200120053602002001200441306e3602042001410020021088012001280208210502400240200241306c22020d00200128020021060c010b20012802002206200541306c6a21040340200041086a2903002103200041106a2903002107200041186a290300210820002903002109200441286a200041286a290300370300200441206a200041206a290300370300200441186a2008370300200441106a2007370300200441086a200337030020042009370300200441306a2104200541016a2105200041306a2100200241506a22020d000b0b200541306c41306d2100024020012802042204450d00200441306c450d00200610350b200141106a240020000f0b1044000b1045000be61107067f027e027f0a7e037f017e047f230041d0036b22032400200228020821042002280204210520022802002106200341206a2001108e02200341a0016a2003280220220720032802282208108f0220032903a00121094200210a200342003703a001200341e8016a280200210b20032d00ec01210c02400240200942015122020d00200341306a41306a4200370300200341306a41286a4200370300200341306a41206a4200370300200341306a41186a4200370300200341c0006a4200370300200341386a4200370300200342003703304200210d4200210e4200210f420021100c010b200341d8016a2903002111200341a0016a41306a2903002112200341a0016a41206a290300210f200341a0016a41186a290300210e200341e0016a290300211020032903b001210d20032903a801210a200341306a41206a200341a0016a41286a290300370300200341306a41286a2012370300200341306a41306a2011370300200341c0006a200e3703002003200f3703482003200a3703302003200d3703380b0240024002400240200a200629030022127d2213200a56200d200641086a29030022147d200a201254ad7d2211200d562011200d511b450d0041838c0c2108419089c20021024280808080b00221120c010b200320133703302003201137033802400240200e20127c2215200e542206200f20147c2006ad7c2216200f542016200f511b450d0041838c08210841a7d6ca0021024280808080800121120c010b200341306a41186a2016370300200320153703402012201484500d02200341e8006a2005280200108e02200341a0026a200328026822052003280270108f02200341d0026a290300420020032903a00242015122061b2112200341c8026a290300420020061b21140240200328026c450d00200510350b2014201358201220115820122011511b0d0241838c04210841a389c20021024280808080d00221120b2013210a2011210d0b2002ad221142088842ff0183210f20122011428080fcff0f8384210e410121060c010b20042802002104200341e8006a41186a200341c0006a220641086a2903002212370300200341e8006a41206a2205200641106a29030037030020034190016a2217200641186a29030037030020034198016a2218200641206a2903003703002003200629030022143703782003201337036820032011370370427f200a200e7c220e200e200a542206200d200f7c2006ad7c220a200d54200a200d511b22061b427f200a20061b8450211902400240427f201320147c220a200a2013542206201120127c2006ad7c220a201154200a2011511b22061b220d428080e983b1de16544100427f200a20061b220a501b0d00200341e8006a41106a290300210a2018290300210d2017290300210f2005290300210e200329037021142003290368211642012115200329038001211a0c010b02400240200d200a8450450d00420021150c010b42002115200341a0026a41186a221b4200370300200341a0026a41106a22174200370300200341a0026a41086a22054200370300200342003703a00241b6fdc600ad4280808080800184220f100122182900002112200341c0036a41086a2206201841086a290000370300200320123703c0032018103520052006290300370300200320032903c0033703a00241e489c200ad4280808080d00184221210012218290000210e2006201841086a2900003703002003200e3703c00320181035201720032903c003220e370300200341a0036a41086a221c2005290300370300200341a0036a41106a221d200e370300200341a0036a41186a221e2006290300370300200320032903a0023703a003200341086a200341a0036a412010d701200341086a41106a290300210e2003290310211420032802082118201b42003703002017420037030020054200370300200342003703a002200f1001221b290000210f2006201b41086a2900003703002003200f3703c003201b103520052006290300370300200320032903c0033703a00220121001221b290000210f2006201b41086a2900003703002003200f3703c003201b1035201720032903c003220f370300201c2005290300370300201d200f370300201e2006290300370300200320032903a0023703a00320034200200e420020181b220f200a7d2014420020181b2212200d54ad7d220e2012200d7d2214201256200e200f56200e200f511b22061b3703a80220034200201420061b3703a002200341a0036aad4280808080800484200341a0026aad42808080808002841002200341d8026a200a370300200341d0026a200d370300200541013a0000200341a9026a2004290000370000200341b1026a200441086a290000370000200341b9026a200441106a290000370000200341c1026a200441186a290000370000200341033a00a00241b0b4cc004100200341a0026a10d4010b0b2019ad2112200341c8016a200e370300200341d0016a200f370300200341b0016a2014370300200341d8016a200d370300200341b8016a200a3703002003201a3703c001200320103703e001200320163703a8014201210f410021062003200c4100200942015122041b3a00ec012003200b410020041b3602e801200320154201512204ad3703a001024020040d002008ad4220862007ad8410074200210f2013210a2011210d4200210e0c010b200320083602a402200320073602a002200341a8016a200341a0026a10e7024200210e2013210a2011210d0b02402003280224450d00200710350b024002402006450d0020002008360204200041086a200f4208862002ad42ff018384200e84370200410121020c010b024002400240200241ff017122020d00200f4200510d0041032106200341a0026a21020c010b2002450d01200f4200520d0141042106200341a0016a21020b200241086a20063a0000200241003a0000200241096a2001290000370000200241116a200141086a290000370000200241196a200141106a290000370000200241216a200141186a29000037000041b0b4cc004100200210d4010b200041186a200d370300200041106a200a370300200041086a2012370300410021020b20002002360200200341d0036a24000bc90301077f230041106b220224000240200041186a28020022034105744114722204417f4c0d000240200410332205450d00200520002903003700002005200041086a290300370008200241103602082002200436020420022005360200200028021021062003200210770240024020030d002002280208210320022802042104200228020021070c010b20034105742108200228020021072002280204210420022802082103034020062100024002402004200322056b4120490d00200541206a21030c010b024002400240200541206a22032005490d00200441017422062003200620034b1b22064100480d000240024020040d00024020060d00410121070c020b2006103321070c040b20042006470d020b200621040c030b103e000b200720042006103721070b2006210420070d00103c000b200041206a2106200720056a22052000290000370000200541186a200041186a290000370000200541106a200041106a290000370000200541086a200041086a290000370000200841606a22080d000b2002200436020420022003360208200220073602000b20012902002003ad4220862007ad84100202402004450d00200710350b200241106a24000f0b1045000b1044000bea1508047f017e077f027e037f017e017f037e230041d0016b22022400200241b0016a41186a4200370300200241b0016a41106a22034200370300200241b0016a41086a22044200370300200242003703b00141a0e4cb00ad42808080808002841001220529000021062004200541086a290000370300200220063703b001200510354189eaca00ad4280808080f00084100122052900002106200241f0006a41086a2207200541086a290000370300200220063703702005103520032002290370220637030020024190016a41086a200429030037030020024190016a41106a200637030020024190016a41186a2007290300370300200220022903b00137039001200241d0006a20024190016a10a202024002400240200228025022080d00410021092002410036020820024208370300410821080c010b200220022902542206370204200220083602002006a7210941002104024002402006422088a7220a41014b0d00200a0e020201020b200a210503402005410176220720046a220b20042008200b41306c6a2001412010a0084101481b2104200520076b220541014b0d000b0b2008200441306c6a2001412010a0080d0002400240024002402004200a4f0d002008200441306c6a2205200541306a200a2004417f736a41306c109e081a2002200a417f6a220c360208200241b0016a41186a220b4200370300200241b0016a41106a220d4200370300200241b0016a41086a22044200370300200242003703b00141a0e4cb00ad4280808080800284220e1001220529000021062004200541086a290000370300200220063703b0012005103541c699c200ad4280808080900184220f100122072900002106200241f0006a41086a2205200741086a290000370300200220063703702007103520032002290370370000200341086a200529030037000020024190016a41086a2203200429030037030020024190016a41106a2210200d29030037030020024190016a41186a2211200b290300370300200220022903b00137039001200241b0016a20024190016a10a20220022802b0012207410820071b21120240024020022902b401420020071b2206422088a722070d00420021130c010b200b20122007417f6a221441306c6a220741186a290300370300200d200741106a2903003703002004200741086a290300370300200220072903003703b0012014ad422086200642ffffffff0f83842106200741286a290300211520072903202116420121130b2011200b2903003703002010200d29030037030020032004290300370300200220022903b00137039001200241f0006a41186a4200370300200241f0006a41106a220342003703002005420037030020024200370370200e10012207290000210e2004200741086a2900003703002002200e3703b0012007103520052004290300370300200220022903b001370370200f10012207290000210e2004200741086a2900003703002002200e3703b00120071035200320022903b001220e370300200241d0006a41086a2005290300370300200241d0006a41106a200e370300200241d0006a41186a2004290300370300200220022903703703500240024020120d00200241d0006aad428080808080048410070c010b200241203602b4012002200241d0006a3602b00120122006422088a7200241b0016a10a9022006a72204450d00200441306c450d00201210350b200241106a41186a20024190016a41186a22042903002206370300200241106a41106a20024190016a41106a2205290300220e370300200241106a41086a20024190016a41086a2207290300220f37030020022002290390012217370310200241306a41186a220b2006370300200241306a41106a220d200e370300200241306a41086a2212200f370300200220173703300240201350450d00200c210a4100210d0c040b2004200b2903003703002005200d29030037030020072012290300370300200220022903303703900141002104024002400240200a417f6a220541014b0d0020050e020201020b200c210503402005410176220720046a220b20042008200b41306c6a20024190016a412010a0084101481b2104200520076b220541014b0d000b0b2008200441306c6a20024190016a412010a0082205450d022005411f7620046a21040b200241d0006a41186a20024190016a41186a2903002206370300200241d0006a41106a20024190016a41106a290300220e370300200241d0006a41086a20024190016a41086a290300220f37030020022002290390012213370350200241f0006a41186a2006370300200241f0006a41106a200e370300200241f0006a41086a200f37030020022013370370200241b0016a41186a2006370300200241b0016a41106a200e370300200241b0016a41086a200f370300200220133703b001200c2004490d020240200c2009470d0020022009410110880120022802042109200228020021080b2008200441306c6a220541306a2005200c20046b41306c109e081a200541286a201537030020052016370320200541186a200241b0016a41186a290300370300200541106a200241b0016a41106a290300370300200541086a200241b0016a41086a290300370300200520022903b0013703002002200a3602084101210d0c030b2004200a104e000b200241d0006a41186a20024190016a41186a290300370300200241d0006a41106a20024190016a41106a290300370300200241d0006a41086a20024190016a41086a29030037030020022002290390013703504100210d200c210a0c010b2004200c104d000b200241f0006a41186a220b4200370300200241f0006a41106a22124200370300200241f0006a41086a220542003703002002420037037041a0e4cb00ad4280808080800284100122072900002106200241b0016a41086a2204200741086a290000370300200220063703b0012007103520052004290300370300200220022903b0013703704189eaca00ad4280808080f000841001220729000021062004200741086a290000370300200220063703b00120071035200320022903b001370000200341086a2004290300370000200241d0006a41086a2005290300370300200241d0006a41106a2012290300370300200241d0006a41186a200b29030037030020022002290370370350200241203602b4012002200241d0006a3602b0012008200a200241b0016a10a902200241003602b801200242013703b001200241b0016a4100200a41306c220b41306d108a0120022802b80121070240200a450d0020022802b00120074105746a2104200821050340200541086a2900002106200541106a290000210e2005290000210f200441186a200541186a290000370000200441106a200e370000200441086a20063700002004200f370000200741016a2107200441206a2104200541306a2105200b41506a220b0d000b0b200220073602b80102402009450d00200941306c450d00200810350b20022802b401210520022802b0012104200241b0016a41186a200141186a290000370300200241b0016a41106a200141106a290000370300200241b0016a41086a200141086a290000370300200220012900003703b001200241b0016a41012004200710a7022000200d3a0001200041003a0000200041026a200229019001370100200041086a20024196016a290100370100200541ffffff3f71450d01200410350c010b200041013a00002000410c6a4109360200200041086a41f2dfca00360200200041066a410d3a0000200041046a41831a3b01002009450d00200941306c450d00200810350b200241d0016a24000bd30403067f017e037f230041306b220124000240024020002802202202450d000240034020002002417f6a36022020002802042202450d0120002802082103200028020021040240200028020c220520022f0106490d00034002400240200228020022060d002003ad2107410021060c010b200441016a210420023301044220862003ad8421070b200210352007a72103200621022007422088a7220520062f01064f0d000b200621020b200541016a21082002200541e0006c6a220541a0036a28020021092005419c036a280200210620054198036a280200210a200541e8026a290300210702402004450d00200220084102746a41880b6a2802002102410021082004417f6a2204450d00034020022802880b21022004417f6a22040d000b0b2000200836020c20002003360208200020023602042000410036020020074202510d0302400240200a0d00410021092001410036021c2001410036020c0c010b0240024020060d00200a21020c010b20062102200a2103034020032802ec0321032002417f6a22020d000b200a21020340200220022f01064102746a41ec036a28020021022006417f6a22060d000b2003210a0b2001410036022020014100360218200142003703102001200a36020c200141003602082001200236021c200120022f01063602240b20012009360228200141086a108103200028022022020d000c020b0b41958dcc00412b41c08dcc00103f000b200028020421020b02402002450d0020022802002106200210352006450d00034020062802002102200610352002210620020d000b0b200141306a24000b13002000410e360204200041cce9c2003602000bb30201027f230041206b220724002004a7210802400240024002402001a70d0020080d01427f200320067c200220057c22052002542208ad7c22022008200220035420022003511b22081b2103427f200520081b21020c020b024020084101460d00200741086a200420052006200120022003109103200741186a290300210320072903102102200729030821050c030b427f200320067c200220057c22052002542208ad7c22022008200220035420022003511b22081b2103427f200520081b2102420121050c020b02402002200556200320065620032006511b0d00200620037d2005200254ad7d2103200520027d2102420121050c020b200320067d2002200554ad7d2103200220057d21020b420021050b2000200237030820002005370300200041106a2003370300200741206a24000b130020004105360204200041b8fdc2003602000b3400200041a8fdc60036020420004100360200200041146a4101360200200041106a41a8a8c300360200200041086a42073702000bb10201057f230041106b220324000240024002400240200141046a2204417f4c0d000240024020040d0041012105410021040c010b200410332205450d020b2003410036020820032005360200200320043602042001200310770240024020032802042206200328020822056b2001490d0020032802002104200621070c010b200520016a22042005490d03200641017422072004200720044b1b22074100480d030240024020060d00024020070d00410121040c020b2007103322040d010c060b2003280200210420062007460d0020042006200710372204450d050b20032007360204200320043602000b200420056a20002001109d081a2002290200200520016aad4220862004ad84100202402007450d00200410350b200341106a24000f0b1044000b1045000b103e000b103c000bb60201057f230041106b2203240002400240024002402001410274220441046a2205417f4c0d000240024020050d0041012106410021050c010b200510332206450d020b2003410036020820032006360200200320053602042001200310770240024020032802042207200328020822016b2004490d0020032802002105200721060c010b200120046a22052001490d03200741017422062005200620054b1b22064100480d030240024020070d00024020060d00410121050c020b2006103322050d010c060b2003280200210520072006460d0020052007200610372205450d050b20032006360204200320053602000b200520016a20002004109d081a2002290200200120046aad4220862005ad84100202402006450d00200510350b200341106a24000f0b1044000b1045000b103e000b103c000ba00402067f027e230041106b220324000240024002400240200141186c4104722204417f4c0d00200410332205450d0120034100360208200320043602042003200536020020012003107702400240200141186c22010d002003280208210120032802042104200328020021060c010b200020016a2107200328020421042003280208210103402000280200210802400240200420016b4104490d0020032802002106200421050c010b200141046a22052001490d05200441017422062005200620054b1b22054100480d050240024020040d00024020050d00410121060c020b2005103322060d010c080b2003280200210620042005460d0020062004200510372206450d070b20032005360204200320063602000b200620016a20083600002003200141046a2208360208200041106a2903002109200041086a290300210a02400240200520086b4110490d00200141146a2101200521040c010b200841106a22012008490d05200541017422042001200420014b1b22044100480d050240024020050d00024020040d00410121060c020b200410332206450d080c010b20052004460d0020062005200410372206450d070b20032004360204200320063602000b200620086a220520093700082005200a37000020032001360208200041186a22002007470d000b0b20022902002001ad4220862006ad84100202402004450d00200610350b200341106a24000f0b1044000b1045000b103e000b103c000bdf0301057f230041106b220324000240024002400240200141046a2204417f4c0d000240024020040d0041012105410021040c010b200410332205450d020b2003410036020820032005360200200320043602042001200310770240024020032802042204200328020822066b2001490d0020032802002105200421070c010b200620016a22052006490d03200441017422072005200720054b1b22074100480d030240024020040d00024020070d00410121050c020b2007103322050d010c060b2003280200210520042007460d0020052004200710372205450d050b20032007360204200320053602000b200520066a20002001109d081a02400240200241046a2802002200200241086a28020022046b200620016a2201490d00200228020021060c010b200420016a22062004490d03200041017422042006200420064b1b22044100480d030240024020000d00024020040d00410121060c020b200410332206450d060c010b2002280200210620002004460d0020062000200410372206450d050b20022006360200200241046a2004360200200241086a28020021040b200620046a20052001109d081a200241086a200420016a36020002402007450d00200510350b200341106a24000f0b1044000b1045000b103e000b103c000bf00201057f230041206b220324000240024002400240200241046a2204417f4c0d000240024020040d0041012105410021040c010b200410332205450d020b2003410036021820032005360210200320043602142002200341106a10770240024020032802142206200328021822056b2002490d0020032802102104200621070c010b200520026a22042005490d03200641017422072004200720044b1b22074100480d030240024020060d00024020070d00410121040c020b2007103322040d010c060b2003280210210420062007460d0020042006200710372204450d050b20032007360214200320043602100b200420056a20012002109d081a2003200520026a2202ad4220862004ad8410032205290000370308200510352003411c6a200420026a360200200320043602182003200341106a3602142003200341086a3602102000200341106a107b02402007450d00200410350b200341206a24000f0b1044000b1045000b103e000b103c000b960503037f027e057f230041106b220224002002410036020820024201370300200028021021030240410410332204450d0020024104360204200220043602002004200336000020024104360208200041146a280200210320044104410810372204450d0020024108360204200420033600042002200436020020024108360208200041086a29030021052000290300210620044108411810372204450d0020042006370008200441106a200537000020022004360200200242988080808003370204024041000d0020044118413810372204450d010b20042000290024370018200441206a2000412c6a290000370000200441286a200041346a290000370000200441306a2000413c6a29000037000020024138360204200220043602002002413836020820002802182104200041206a28020022002002107702400240024020000d002002280208210020022802042107200228020021080c010b200041057421094100200228020822006b210a2002280204210b034002400240200b200a6a4120490d0020022802002108200b21070c010b200041206a22032000490d03200b41017422082003200820034b1b22074100480d0302400240200b0d00024020070d00410121080c020b2007103322080d010c060b20022802002108200b2007460d002008200b200710372208450d050b20022007360204200220083602002007210b0b200820006a22032004290000370000200341186a200441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002002200041206a2200360208200a41606a210a200441206a2104200941606a22090d000b0b20012902002000ad4220862008ad84100202402007450d00200810350b200241106a24000f0b103e000b103c000be20c03037f017e077f230041c0026b22022400024002400240024002400240024002400240024020012d0000417f6a220341044b0d0020030e050102030405010b41cfa2cc00412841c086cc00103f000b2001410c6a2802002204ad42b0027e2205422088a70d052005a72206417f4c0d05200141046a28020021030240024020060d00410821070c010b200610332207450d070b20024100360208200220073602002002200641b0026e3602042002410020041092012002280208210102402004450d00200441b0026c21062002280200200141b0026c6a2107200441047441706a41047621040340200241106a2003109b032007200241106a41b002109d0841b0026a2107200341b0026a2103200641d07d6a22060d000b200120046a41016a21010b200241186a20013602002002200229030022053703102000410c6a2001360200200041046a2005370200200041013a00000c040b200141026a2f0100210641b00210332203450d062003200141046a280200109c03200041046a2003360200200041026a20063b0100200041023a00000c030b2001410c6a280200220841ffffff3f712008470d0320084105742206417f4c0d03200141026a2f01002109200141046a28020021040240024020060d00410121070c010b200610332207450d050b41002103200241003602182002200736021020022006410576360214200241106a41002008108a012002280218210a02402008450d002008410574210b2002280210200a4105746a210c0340200c20036a2206200420036a2207290000370000200641186a200741186a290000370000200641106a200741106a290000370000200641086a200741086a290000370000200b200341206a2203470d000b200841057441606a410576200a6a41016a210a0b200241086a2206200a36020020022002290310370300200141186a2802002107200141146a28020021042001280210210b41b00210332203450d0520032001411c6a280200109c03200041026a20093b01002000411c6a2003360200200041186a2007360200200041146a2004360200200041106a200b360200200041033a0000200041046a20022903003702002000410c6a20062802003602000c020b2001412c6a280200220841ffffff3f712008470d0220084105742206417f4c0d02200141226a2f01002109200141246a28020021040240024020060d00410121070c010b200610332207450d040b41002103200241003602182002200736021020022006410576360214200241106a41002008108a012002280218210a02402008450d002008410574210b2002280210200a4105746a210c0340200c20036a2206200420036a2207290000370000200641186a200741186a290000370000200641106a200741106a290000370000200641086a200741086a290000370000200b200341206a2203470d000b200841057441606a410576200a6a41016a210a0b200241086a200a360200200220022903102205370300200041226a20093b0100200041246a20053702002000412c6a200a360200200041043a0000200041386a200141386a280200360200200041306a200129023037020020002001290001370001200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a2900003700000c010b2001412c6a280200220841ffffff3f712008470d0120084105742206417f4c0d01200141226a2f01002109200141246a28020021040240024020060d00410121070c010b200610332207450d030b41002103200241003602182002200736021020022006410576360214200241106a41002008108a012002280218210a02402008450d002008410574210b2002280210200a4105746a210c0340200c20036a2206200420036a2207290000370000200641186a200741186a290000370000200641106a200741106a290000370000200641086a200741086a290000370000200b200341206a2203470d000b200841057441606a410576200a6a41016a210a0b200241086a200a360200200220022903102205370300200041226a20093b0100200041246a20053702002000412c6a200a360200200041053a0000200041306a20012902303702002000200141016a290000370001200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a2900003700000b200241c0026a24000f0b1044000b1045000b103c000b881c04057f017e017f037e230041b0036b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802000e1c00011302030405060708090a0b0c0d0e0f1011121313131415161713000b20024180016a200141086a109d0320004100360200200041106a20024180016a41086a290300370300200041086a2002290380013703000c170b20024180016a200141046a109a03200041013602002000413c6a200241b8016a280200360200200041346a200241b0016a2903003702002000412c6a200241a8016a290300370200200041246a200241a0016a2903003702002000411c6a20024198016a290300370200200041146a20024190016a2903003702002000410c6a20024188016a29030037020020002002290380013702040c160b20004103360200200041086a200141086a2903003703000c150b20024180016a200141046a109e03200041043602002000410c6a20024188016a28020036020020002002290380013702040c140b02400240024002400240024020012d0004417f6a220341034b0d00200141046a210420030e0401020304010b41cfa2cc00412841c086cc00103f000b200141086a2802002103410121050c030b41022105200241026a200441036a2d00003a000020024180016a41086a200141146a29020037030020024190016a2001411c6a29020037030020024198016a200141246a2d00003a0000200220042f00013b010020022001410c6a29020037038001200141086a2802002103200141286a28020021010c020b200141086a2802002103410321050c010b200241026a200441036a2d00003a000020024180016a41086a200141146a29020037030020024190016a2001411c6a29020037030020024198016a200141246a2d00003a0000200220042f00013b010020022001410c6a29020037038001200141086a2802002103200141286a2802002101410421050b200020053a0004200020022f01003b000520004105360200200041086a20033602002000410c6a200229038001370200200041286a2001360200200041076a200241026a2d00003a0000200041146a20024180016a41086a2903003702002000411c6a20024190016a290300370200200041246a20024198016a2802003602000c130b20024180016a200141086a108503200041086a20024180016a41e000109d081a200041063602000c120b20024180016a200141086a108702200041086a20024180016a418802109d081a200041073602000c110b02400240200128020422060d00410021030c010b20024180016a41186a200141286a29000037030020024180016a41106a200141206a29000037030020024188016a200141186a29000037030020024180016a41286a200141386a29000037030020024180016a41306a200141c0006a29000037030020024180016a41386a200141c8006a29000037030020024180016a41c8006a200141d8006a29000037030020024180016a41d0006a200141e0006a29000037030020024180016a41d8006a200141e8006a2900003703002002200141106a290000370380012002200141306a2900003703a0012002200141d0006a2900003703c00120024180016a41f8006a20014188016a29000037030020024180016a41f0006a20014180016a29000037030020024180016a41e8006a200141f8006a2900003703002002200141f0006a2900003703e0012001410c6a2802002201417f4c0d120240024020010d0041002105410121030c010b200110332203450d14200121050b0240024020052001490d00200521040c010b200541017422042001200420014b1b22044100480d15024020050d002004103322030d010c170b20052004460d0020032005200410372203450d160b200320062001109d081a200220024180016a418001109d081a2001ad4220862004ad8421070b20002003360204200041086a2007370200200041106a2002418001109d081a200041083602000c100b20024180016a200141086a10a00320004109360200200041386a20024180016a41306a290300370300200041306a20024180016a41286a290300370300200041286a20024180016a41206a290300370300200041206a20024180016a41186a290300370300200041186a20024180016a41106a290300370300200041106a20024180016a41086a290300370300200041086a2002290380013703000c0f0b20024180016a200141046a10a1032000410a3602002000412c6a200241a8016a290300370200200041246a200241a0016a2903003702002000411c6a20024198016a290300370200200041146a20024190016a2903003702002000410c6a20024188016a29030037020020002002290380013702040c0e0b20024180016a200141046a10a1032000410b3602002000412c6a200241a8016a290300370200200041246a200241a0016a2903003702002000411c6a20024198016a290300370200200041146a20024190016a2903003702002000410c6a20024188016a29030037020020002002290380013702040c0d0b20024180016a200141086a1086032000410c360200200041286a20024180016a41206a290300370300200041206a20024180016a41186a290300370300200041186a20024180016a41106a290300370300200041106a20024180016a41086a290300370300200041086a2002290380013703000c0c0b20024180016a200141046a10a203200041046a20024180016a41c400109d081a2000410d3602000c0b0b2000410e360200200020012802043602040c0a0b2001410c6a2802002203417f4c0d0a200128020421060240024020030d0041002101410121040c010b200310332204450d0c200321010b0240024020012003490d00200121050c010b200141017422052003200520034b1b22054100480d0d024020010d00200510332204450d0f0c010b20012005460d0020042001200510372204450d0e0b200420062003109d0821012000410c6a2003360200200041086a2005360200200020013602042000410f3602000c090b20024180016a200141086a10a30320004110360200200041c0006a20024180016a41386a290300370300200041386a20024180016a41306a290300370300200041306a20024180016a41286a290300370300200041286a20024180016a41206a290300370300200041206a20024180016a41186a290300370300200041186a20024180016a41106a290300370300200041106a20024180016a41086a290300370300200041086a2002290380013703000c080b20024180016a200141086a10a403200041086a20024180016a419801109d081a200041113602000c070b20024180016a200141046a10a503200041123602002000412c6a200241a8016a280200360200200041246a200241a0016a2903003702002000411c6a20024198016a290300370200200041146a20024190016a2903003702002000410c6a20024188016a29030037020020002002290380013702040c060b20024180016a200141046a10de04200041046a20024180016a41e800109d081a200041133602000c050b10a703000b20024180016a200141086a10a803200041086a20024180016a41a802109d081a200041173602000c030b20024180016a200141086a10a903200041086a20024180016a41c800109d081a200041183602000c020b20024180016a200141046a10aa03200041046a20024180016a41c400109d081a200041193602000c010b0240024002400240200141086a280200417f6a220841024b0d004101210520080e03030102030b41cfa2cc00412841c086cc00103f000b41012103024002402001410c6a22052d00004101470d00200141106a28020021060c010b200241ae036a200541036a2d00003a000020024188016a2001411c6a29020037030020024180016a41106a200141246a29020037030020024198016a2001412c6a2d00003a0000200220052f00013b01ac032002200141146a29020037038001200141106a2802002106410021030b41022105200241a8036a41026a200241ac036a41026a2d00003a0000200241086a20024180016a41086a290300370300200241106a20024180016a41106a290300370300200241186a20024180016a41186a280200360200200220022f01ac033b01a80320022002290380013703000c010b41012103024002402001410c6a22052d00004101470d00200141106a28020021060c010b200241ae036a200541036a2d00003a000020024188016a2001411c6a29020037030020024180016a41106a200141246a29020037030020024198016a2001412c6a2d00003a0000200220052f00013b01ac032002200141146a29020037038001200141106a2802002106410021030b200241a8036a41026a200241ac036a41026a2d00003a0000200241086a20024180016a41086a290300370300200241106a20024180016a41106a290300370300200241186a20024180016a41186a280200360200200220022f01ac033b01a8032002200229038001370300200141c8006a2903002109200141c0006a2903002107200141386a290300210a200141d0006a28020021042001290330210b410321050b200020022f01a8033b000d200041c8006a2009370300200041c0006a2007370300200041386a200a370300200041306a200b3703002000410c6a20033a0000200041086a2005360200200041106a2006360200200041146a2002290300370200200041d0006a20043602002000410f6a200241aa036a2d00003a00002000411c6a200241086a290300370200200041246a200241106a2903003702002000412c6a200241186a2802003602002000411a3602000b200241b0036a24000f0b1044000b1045000b103e000b103c000ba91a03047f047e027f230041c0036b22022400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802000e1c00011302030405060708090a0b0c0d0e0f1011121313131415161713000b2002200141086a109d0320004100360200200041106a200241086a290300370300200041086a20022903003703000c170b2002200141046a109a03200041013602002000413c6a200241386a280200360200200041346a200241306a2903003702002000412c6a200241286a290300370200200041246a200241206a2903003702002000411c6a200241186a290300370200200041146a200241106a2903003702002000410c6a200241086a290300370200200020022903003702040c160b20004103360200200041086a200141086a2903003703000c150b2002200141046a109e03200041043602002000410c6a200241086a280200360200200020022903003702040c140b02400240024002400240024020012d0004417f6a220341034b0d00200141046a210420030e0401020304010b41cfa2cc00412841c086cc00103f000b200141086a2802002103410121050c030b41022105200241b0026a41026a200441036a2d00003a0000200241086a200141146a290200370300200241106a2001411c6a290200370300200241186a200141246a2d00003a0000200220042f00013b01b00220022001410c6a290200370300200141086a2802002103200141286a28020021010c020b200141086a2802002103410321050c010b200241b2026a200441036a2d00003a0000200241086a200141146a290200370300200241106a2001411c6a290200370300200241186a200141246a2d00003a0000200220042f00013b01b00220022001410c6a290200370300200141086a2802002103200141286a2802002101410421050b200020053a0004200020022f01b0023b000520004105360200200041086a20033602002000410c6a2002290300370200200041286a2001360200200041076a200241b2026a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a2802003602000c130b2002200141086a108503200041086a200241e000109d081a200041063602000c120b2002200141086a108702200041086a2002418802109d081a200041073602000c110b024002402001280204450d00200241b0026a41186a200141286a290000370300200241b0026a41106a200141206a290000370300200241b8026a200141186a290000370300200241b0026a41286a200141386a290000370300200241b0026a41306a200141c0006a290000370300200241b0026a41386a200141c8006a290000370300200241b0026a41c8006a200141d8006a290000370300200241b0026a41d0006a200141e0006a290000370300200241b0026a41d8006a200141e8006a2900003703002002200141106a2900003703b0022002200141306a2900003703d0022002200141d0006a2900003703f002200241b0026a41f8006a20014188016a290000370300200241b0026a41f0006a20014180016a290000370300200241b0026a41e8006a200141f8006a2900003703002002200141f0006a290000370390032002200141046a109f032002410c6a200241b0026a418001109d081a0c010b200241003602000b200041046a2002418c01109d081a200041083602000c100b2002200141086a10a00320004109360200200041386a200241306a290300370300200041306a200241286a290300370300200041286a200241206a290300370300200041206a200241186a290300370300200041186a200241106a290300370300200041106a200241086a290300370300200041086a20022903003703000c0f0b2002200141046a10a1032000410a3602002000412c6a200241286a290300370200200041246a200241206a2903003702002000411c6a200241186a290300370200200041146a200241106a2903003702002000410c6a200241086a290300370200200020022903003702040c0e0b2002200141046a10a1032000410b3602002000412c6a200241286a290300370200200041246a200241206a2903003702002000411c6a200241186a290300370200200041146a200241106a2903003702002000410c6a200241086a290300370200200020022903003702040c0d0b2002200141086a1086032000410c360200200041286a200241206a290300370300200041206a200241186a290300370300200041186a200241106a290300370300200041106a200241086a290300370300200041086a20022903003703000c0c0b2002200141046a10a203200041046a200241c400109d081a2000410d3602000c0b0b2000410e360200200020012802043602040c0a0b2002200141046a109f032000410f3602002000410c6a200241086a280200360200200020022903003702040c090b2002200141086a10a30320004110360200200041c0006a200241386a290300370300200041386a200241306a290300370300200041306a200241286a290300370300200041286a200241206a290300370300200041206a200241186a290300370300200041186a200241106a290300370300200041106a200241086a290300370300200041086a20022903003703000c080b2002200141086a10a403200041086a2002419801109d081a200041113602000c070b2002200141046a10a503200041123602002000412c6a200241286a280200360200200041246a200241206a2903003702002000411c6a200241186a290300370200200041146a200241106a2903003702002000410c6a200241086a290300370200200020022903003702040c060b200128020421032002200141086a109f03200241b0036a200141146a10a603200241146a200241b0036a41086a280200360200200220022903b00337020c200241b0026a41106a200241106a2903002206370300200241b0026a41086a200241086a29030022073703002002200229030022083703b002200141206a2902002109200141286a280200210520002003360204200041086a2008370200200041106a2007370200200041186a2006370200200041286a2005360200200041206a20093702002000412c6a2001412c6a290200370200200041346a200141346a2902003702002000413c6a2001413c6a290200370200200041c4006a200141c4006a290200370200200041cc006a200141cc006a290200370200200041d4006a200141d4006a290200370200200041dc006a200141dc006a290200370200200041e4006a200141e4006a290200370200200041133602000c050b10a703000b2002200141086a10a803200041086a200241a802109d081a200041173602000c030b2002200141086a10a903200041086a200241c800109d081a200041183602000c020b2002200141046a10aa03200041046a200241c400109d081a200041193602000c010b0240024002400240200141086a280200417f6a220a41024b0d0041012105200a0e03030102030b41cfa2cc00412841c086cc00103f000b41012103024002402001410c6a22052d00004101470d00200141106a280200210b0c010b200241b2036a200541036a2d00003a0000200241086a2001411c6a290200370300200241106a200141246a290200370300200241186a2001412c6a2d00003a0000200220052f00013b01b0032002200141146a290200370300200141106a280200210b410021030b41022105200241ac026a41026a200241b0036a41026a2d00003a0000200241b0026a41086a200241086a290300370300200241b0026a41106a200241106a290300370300200241b0026a41186a200241186a280200360200200220022f01b0033b01ac02200220022903003703b0020c010b41012103024002402001410c6a22052d00004101470d00200141106a280200210b0c010b200241b2036a200541036a2d00003a0000200241086a2001411c6a290200370300200241106a200141246a290200370300200241186a2001412c6a2d00003a0000200220052f00013b01b0032002200141146a290200370300200141106a280200210b410021030b200241ac026a41026a200241b0036a41026a2d00003a0000200241b0026a41086a200241086a290300370300200241b0026a41106a200241106a290300370300200241b0026a41186a200241186a280200360200200220022f01b0033b01ac02200220022903003703b002200141c8006a2903002107200141c0006a2903002106200141386a2903002109200141d0006a280200210420012903302108410321050b200020022f01ac023b000d200041c8006a2007370300200041c0006a2006370300200041386a2009370300200041306a20083703002000410c6a20033a0000200041086a2005360200200041106a200b360200200041146a20022903b002370200200041d0006a20043602002000410f6a200241ae026a2d00003a00002000411c6a200241b0026a41086a290300370200200041246a200241b0026a41106a2903003702002000412c6a200241c8026a2802003602002000411a3602000b200241c0036a24000bf20b03057f017e017f230041306b2202240002400240024002400240024002400240024002400240024002400240024002402001280200417f6a220341094b0d0020030e0a0102030405060708090a010b41cfa2cc00412841c086cc00103f000b20004101360200200020012802043602040c090b2001410c6a2802002203417f4c0d09200128020421040240024020030d0041002101410121050c010b200310332205450d0b200321010b0240024020012003490d00200121060c010b200141017422062003200620034b1b22064100480d0c024020010d002006103322050d010c0e0b20012006460d0020052001200610372205450d0d0b200520042003109d0821012000410c6a2003360200200041086a200636020020002001360204200041023602000c080b20004103360200200041086a200141086a2903003703000c070b2001410c6a2802002203417f4c0d07200128020421040240024020030d0041002101410121050c010b200310332205450d09200321010b0240024020012003490d00200121060c010b200141017422062003200620034b1b22064100480d0a024020010d00200610332205450d0c0c010b20012006460d0020052001200610372205450d0b0b200520042003109d0821012000410c6a2003360200200041086a200636020020002001360204200041043602000c060b2001410c6a2802002203417f4c0d06200128020421040240024020030d0041002101410121050c010b200310332205450d08200321010b0240024020012003490d00200121060c010b200141017422062003200620034b1b22064100480d09024020010d00200610332205450d0b0c010b20012006460d0020052001200610372205450d0a0b200520042003109d0821012000410c6a2003360200200041086a200636020020002001360204200041053602000c050b20004106360200200020012902043702042000410c6a2001410c6a2802003602000c040b2001410c6a2802002205ad42187e2207422088a70d042007a72206417f4c0d04200128020421030240024020060d00410421010c010b200610332201450d060b20024100360228200220013602202002200641186e360224200241206a410020051097012002280228210402402005450d002003200541186c6a21062002280220200441186c6a2101200541037441786a4103762108200241086a410c6a21050340200241086a2003109f0320052003410c6a109f03200141106a200241086a41106a290300370200200141086a200241086a41086a29030037020020012002290308370200200141186a2101200341186a22032006470d000b200420086a41016a21040b200241106a20043602002002200229032022073703082000410c6a200436020020002007370204200041073602000c030b2001410c6a2802002204ad420c7e2207422088a70d032007a72206417f4c0d03200128020421030240024020060d00410421010c010b200610332201450d050b200241003602282002200136022020022006410c6e360224200241206a410020041087012002280228210502402004450d002004410c6c210620022802202005410c6c6a21012004410274417c6a41027621040340200241086a2003109f03200141086a200241086a41086a280200360200200120022903083702002001410c6a21012003410c6a2103200641746a22060d000b200520046a41016a21050b200241086a41086a20053602002002200229032022073703082000410c6a200536020020002007370204200041083602000c020b2001410c6a2802002203417f4c0d02200128020421040240024020030d0041002101410121050c010b200310332205450d04200321010b0240024020012003490d00200121060c010b200141017422062003200620034b1b22064100480d05024020010d00200610332205450d070c010b20012006460d0020052001200610372205450d060b200520042003109d0821012000410c6a2003360200200041086a200636020020002001360204200041093602000c010b2000410a3602000b200241306a24000f0b1044000b1045000b103e000b103c000ba10e03027f017e177f230041a0016b22022400024002400240024020012802082203ad42f0007e2204422088a70d002004a72205417f4c0d00200128020021060240024020050d00410421010c010b200510332201450d020b20024100360208200220013602002002200541f0006e3602042002410020031093012002280208210502402003450d002006200341f0006c6a21072002280200200541f0006c6a21082005200341047441706a4104766a21090340200241d0006a41086a220a200641186a290000370300200241d0006a41106a220b200641206a290000370300200241d0006a41186a220c200641286a290000370300200241306a41086a220d200641386a29000037030020062900102104200241306a41106a220e200641c0006a290000370300200241306a41186a220f200641c8006a290000370300200241106a41186a2210200641e8006a290000370300200241106a41106a2211200641e0006a290000370300200241106a41086a2212200641d8006a290000370300200220043703502002200629003037033020022006290050370310200628020c2205ad42247e2204422088a70d022004a72203417f4c0d0220062802002113200628020421140240024020030d00410421010c010b200310332201450d040b20024100360278200220013602702002200341246e360274200241f0006a41002005108d012002280278211502402005450d00200541246c21162002280270201541246c6a211741002101034002400240024002400240024002400240201420016a22032d00000e06010203040500010b2003410c6a2802002218417f4c0d0b200341046a28020021190240024020180d0041002103410121050c010b201810332205450d0d201821030b0240024020032018490d002003211a0c010b2003410174221a2018201a20184b1b221a4100480d0e024020030d00201a103322050d010c100b2003201a460d0020052003201a10372205450d0f0b2002200520192018109d0836009301410521190c050b2002200341046a28000036009b012002200341016a280000360298012002200341146a290000370380012002200341196a290000370085012002200228029801360290012002200228009b0136009301200341086a280000211a2003410c6a2800002118200341106a2800002105410021190c050b200341106a2802002205417f4c0d09200341086a2802002119200341016a280000211b0240024020050d00410021034101211a0c010b20051033221a450d0b200521030b0240024020032005490d00200321180c010b200341017422182005201820054b1b22184100480d0c024020030d0020181033221a450d0e0c010b20032018460d00201a200320181037221a450d0d0b201a20192005109d081a2002201b36029001410121190c040b200341106a2802002205417f4c0d08200341086a2802002119200341016a280000211b0240024020050d00410021034101211a0c010b20051033221a450d0a200521030b0240024020032005490d00200321180c010b200341017422182005201820054b1b22184100480d0b024020030d0020181033221a450d0d0c010b20032018460d00201a200320181037221a450d0c0b201a20192005109d081a2002201b36029001410221190c030b200341106a2802002205417f4c0d07200341086a2802002119200341016a280000211b0240024020050d00410021034101211a0c010b20051033221a450d09200521030b0240024020032005490d00200321180c010b200341017422182005201820054b1b22184100480d0a024020030d0020181033221a450d0c0c010b20032018460d00201a200320181037221a450d0b0b201a20192005109d081a2002201b36029001410321190c020b410421192002200341046a280200360093012003410c6a2802002118200341086a280200211a0b0b201720016a220320193a0000200341016a200228029001360000200341046a200228009301360000200341106a20053602002003410c6a2018360200200341086a201a360200200341146a2002290380013702002003411c6a20024180016a41086a290300370200201541016a21152016200141246a2201470d000b0b20024180016a41086a2015360200200220022903702204370380012008410c6a20153602002008200437020420082002290350370210200841186a200a29030037020020082013360200200841206a200b290300370200200841286a200c29030037020020082002290330370230200841386a200d290300370200200841c0006a200e290300370200200841c8006a200f290300370200200841e8006a2010290300370200200841e0006a2011290300370200200841d8006a201229030037020020082002290310370250200841f0006a2108200641f0006a22062007470d000b200941016a21050b20002002290300370200200041086a2005360200200241a0016a24000f0b1044000b1045000b103e000b103c000bc80101047f02400240024020012802082202417f4c0d00200128020021030240024020020d0041002101410121040c010b200210332204450d02200221010b0240024020012002490d00200121050c010b02400240200141017422052002200520024b1b22054100480d00024020010d002005103322040d030c060b20012005470d01200121050c020b103e000b20042001200510372204450d030b200420032002109d0821012000200236020820002005360204200020013602000f0b1044000b1045000b103c000bc01203037f027e027f230041106b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d0000417f6a2203411c4b0d0020030e1d0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d010b41cfa2cc00412841c086cc00103f000b200041013a000020002001290001370001200041306a200141306a290300370300200041286a200141286a290300370300200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a2900003700000c1c0b200041023a0000200041046a200141046a2802003602000c1b0b200141046a28020021044101210302400240200141086a2d00004101470d00200141286a2903002105200141206a29030021060c010b200141096a2d000041017121072001410a6a2d00002108410021030b200041033a0000200041286a2005370300200041206a2006370300200041106a20012903103703002000410a6a20083a0000200041096a20073a0000200041086a20033a0000200041046a20043602002000410b6a2002280006360000200041186a200141186a2903003703002000410f6a200241066a41046a2d00003a00000c1a0b200141046a28020021044101210302400240200141086a2d00004101470d00200141286a2903002105200141206a29030021060c010b200141096a2d000041017121072001410a6a2d00002108410021030b200041043a0000200041286a2005370300200041206a2006370300200041106a20012903103703002000410a6a20083a0000200041096a20073a0000200041086a20033a0000200041046a20043602002000410b6a200228000b360000200041186a200141186a2903003703002000410f6a2002410b6a41046a2d00003a00000c190b200041053a0000200041046a200141046a2802003602000c180b200041063a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000c170b200041073a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000c160b200041083a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000c150b200041093a000020002001290001370001200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a290000370000200041246a200141246a2902003702000c140b2000410a3a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000c130b2000410b3a0000200041046a200141046a2802003602000c120b2000410c3a0000200041046a200141046a2802003602000c110b2000410d3a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000c100b2000410e3a00000c0f0b2000410f3a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000c0e0b200041103a000020002001290001370001200041306a200141306a290300370300200041286a200141286a290300370300200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a290000370000200041216a200141216a2d00003a00000c0d0b200041113a00000c0c0b200041123a00000c0b0b2001410c6a2802002203417f4c0d0b200141046a28020021070240024020030d0041002101410121080c010b200310332208450d0d200321010b0240024020012003490d00200121040c010b200141017422042003200420034b1b22044100480d0e024020010d002004103322080d010c100b20012004460d0020082001200410372208450d0f0b200820072003109d0821012000410c6a2003360200200041086a2004360200200041046a2001360200200041133a00000c0a0b2001410c6a2802002203417f4c0d0a200141046a28020021070240024020030d0041002101410121080c010b200310332208450d0c200321010b0240024020012003490d00200121040c010b200141017422042003200420034b1b22044100480d0d024020010d00200410332208450d0f0c010b20012004460d0020082001200410372208450d0e0b200820072003109d0821012000410c6a2003360200200041086a2004360200200041046a2001360200200041143a00000c090b200041153a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000c080b200041163a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000c070b200041173a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000c060b200041183a0000200041046a200141046a2802003602000c050b200041193a000020002001290001370001200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a290000370000200041246a200141246a2802003602000c040b2000411a3a000020002001290001370001200041306a200141306a290300370300200041286a200141286a290300370300200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a290000370000200041216a200141216a2d00003a00000c030b2000411b3a00000c020b2000411c3a0000200041046a200141046a2802003602000c010b2000411d3a000020002001290001370001200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a290000370000200041246a200141246a2802003602000b200241106a24000f0b1044000b1045000b103e000b103c000bcd0601097f230041306b22022400024002400240024002400240024002400240024020012d0000417f6a220341044b0d0020030e050102030405010b41cfa2cc00412841c086cc00103f000b2001412c6a280200220441ffffff3f712004470d0520044105742205417f4c0d05200141246a28020021060240024020050d00410121070c010b200510332207450d070b41002103200241003602182002200736021020022005410576360214200241106a41002004108a012002280218210802402004450d0020044105742109200228021020084105746a210a0340200a20036a2205200620036a2207290000370000200541186a200741186a290000370000200541106a200741106a290000370000200541086a200741086a2900003700002009200341206a2203470d000b200441057441606a41057620086a41016a21080b200241086a220520083602002002200229031037030041002103024020012d00014101470d00200241286a2001411a6a290000370300200241206a200141126a290000370300200241106a41086a2001410a6a2900003703002002200141026a290000370310410121030b200020033a0001200041013a0000200041246a2002290300370200200041026a20022903103700002000412c6a20052802003602002000410a6a200241106a41086a290300370000200041126a200241206a2903003700002000411a6a200241286a2903003700000c040b41b00210332203450d062003200141046a280200109b03200041023a0000200041046a20033602000c030b200141046a280200210541b00210332203450d052003200141086a280200109b03200041086a2003360200200041046a2005360200200041033a00000c020b200041043a000020002001290001370001200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a290000370000200041246a200141246a280200360200200041216a200141216a2d00004100473a00000c010b200041053a000020002001290001370001200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a290000370000200041246a200141246a2802003602000b200241306a24000f0b1044000b1045000b103c000ba60602087f017e230041206b220224000240024002400240024002400240024002400240024020012d0000417f6a220341064b0d0020030e0701020304050607010b41cfa2cc00412841c086cc00103f000b200041013a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000c060b200041023a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000c050b200041033a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a290000370000200041216a200141216a290000370000200041296a200141296a290000370000200041316a200141316a290000370000200041396a200141396a2900003700000c040b2001410c6a280200220441ffffff3f712004470d0420044105742203417f4c0d04200141046a28020021050240024020030d00410121060c010b200310332206450d060b41002101200241003602182002200636021020022003410576360214200241106a41002004108a012002280218210702402004450d0020044105742108200228021020074105746a21090340200920016a2203200520016a2206290000370000200341186a200641186a290000370000200341106a200641106a290000370000200341086a200641086a2900003700002008200141206a2201470d000b200441057441606a41057620076a41016a21070b200241086a200736020020022002290310220a3703002000410c6a2007360200200041046a200a370200200041043a00000c030b200041053a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000c020b200041063a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000c010b200041073a00000b200241206a24000f0b1044000b1045000bc30903027f027e047f230041206b220224000240024002400240024002400240024002400240024002400240024020012d0000417f6a220341074b0d0020030e080102030405060708010b41cfa2cc00412841c086cc00103f000b200141306a2903002104200141286a29030021054101210302400240200141046a2d00004101470d00200141086a28020021010c010b2002411e6a200141076a2d00003a0000200241086a200141146a290000370300200241106a2001411c6a290000370300200241186a200141246a2d00003a00002002200141056a2f00003b011c20022001410c6a290000370300200141086a2800002101410021030b200041013a0000200041306a2004370300200041286a2005370300200041046a20033a0000200041056a20022f011c3b0000200041086a20013602002000410c6a2002290300370200200041076a2002411e6a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a2802003602000c070b200041023a0000200041046a200141046a2802003602000c060b200041033a0000200041046a200141046a2802003602000c050b2001412c6a2802002203417f4c0d05200141246a28020021060240024020030d0041002107410121080c010b200310332208450d07200321070b0240024020072003490d00200721090c010b200741017422092003200920034b1b22094100480d08024020070d002009103322080d010c0a0b20072009460d0020082007200910372208450d090b200820062003109d0821072000412c6a2003360200200041286a2009360200200041246a2007360200200041043a000020002001290001370001200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a2900003700000c040b200041053a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000c030b2001412c6a2802002203417f4c0d03200141246a28020021060240024020030d0041002107410121080c010b200310332208450d05200321070b0240024020072003490d00200721090c010b200741017422092003200920034b1b22094100480d06024020070d00200910332208450d080c010b20072009460d0020082007200910372208450d070b200820062003109d0821072000412c6a2003360200200041286a2009360200200041246a2007360200200041063a0000200041386a200141386a290300370300200041306a200129033037030020002001290001370001200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a2900003700000c020b200041073a000020002001290001370001200041306a200141306a290300370300200041286a200141286a290300370300200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a2900003700000c010b200041083a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000b200241206a24000f0b1044000b1045000b103e000b103c000bd20e03027f107e057f230041c0006b220224000240024002400240024002400240024002400240024020012d0000417f6a220341044b0d0020030e050102030405010b41cfa2cc00412841c086cc00103f000b20014190016a2d00002103200141086a2903002104200141106a2903002105200141186a2903002106200141206a2903002107200141286a2903002108200141306a2903002109200141386a290300210a200141c0006a290300210b200141c8006a290300210c200141d0006a290300210d200141d8006a290300210e200141e0006a290300210f200141e8006a2903002110200141f0006a2903002111200141f8006a290300211220014180016a290300211320004188016a20014188016a29030037030020004180016a2013370300200041f8006a2012370300200041f0006a2011370300200041e8006a2010370300200041e0006a200f370300200041d8006a200e370300200041d0006a200d370300200041c8006a200c370300200041c0006a200b370300200041386a200a370300200041306a2009370300200041286a2008370300200041206a2007370300200041186a2006370300200041106a2005370300200041086a200437030020004190016a20034100473a0000200041013a000020004194016a200241236a28000036000020004191016a20022800203600000c040b2001410c6a2802002203417f4c0d04200141046a28020021140240024020030d0041002101410121150c010b200310332215450d06200321010b0240024020012003490d00200121160c010b200141017422162003201620034b1b22164100480d07024020010d002016103322150d010c090b20012016460d0020152001201610372215450d080b201520142003109d0821012000410c6a2003360200200041086a2016360200200041046a2001360200200041023a00000c030b4101211502400240200141046a2d00004101470d00200141086a28020021170c010b200241026a200141076a2d00003a0000200241206a41086a200141146a290000370300200241306a2001411c6a290000370300200241386a200141246a2d00003a00002002200141056a2f00003b010020022001410c6a290000370320200141086a2800002117410021150b200141306a2802002203417f4c0d03200141c0006a29030021042001290338210520012802282118200129034821060240024020030d0041002101410121140c010b200310332214450d05200321010b0240024020012003490d00200121160c010b200141017422162003201620034b1b22164100480d06024020010d00201610332214450d080c010b20012016460d0020142001201610372214450d070b201420182003109d082101200041c0006a2004370300200041386a2005370300200041046a20153a0000200041086a2017360200200041c8006a2006370300200041306a20033602002000412c6a2016360200200041286a2001360200200041056a20022f01003b0000200041076a200241026a2d00003a00002000410c6a2002290320370200200041146a200241206a41086a2903003702002000411c6a200241306a290300370200200041246a200241386a280200360200200041033a00000c020b200141386a2903002104200141306a2903002105200141c0006a2903002106200241386a200141196a290000370300200241306a200141116a290000370300200241286a200141096a290000370300200220012900013703202001412c6a2802002203417f4c0d02200141246a28020021140240024020030d0041002101410121150c010b200310332215450d04200321010b0240024020012003490d00200121160c010b200141017422162003201620034b1b22164100480d05024020010d00201610332215450d070c010b20012016460d0020152001201610372215450d060b201520142003109d082101200041386a2004370300200041306a2005370300200041c0006a20063703002000412c6a2003360200200041286a2016360200200041246a2001360200200041043a000020002002290320370001200041096a200241286a290300370000200041116a200241306a290300370000200041196a200241386a2903003700000c010b200241186a2216200141196a290000370300200241106a2215200141116a290000370300200241086a2214200141096a29000037030020022001290001370300410021030240200141216a2d00004101470d00200241206a41186a2001413a6a290000370300200241206a41106a200141326a290000370300200241206a41086a2001412a6a2900003703002002200141226a290000370320410121030b20002002290300370001200041216a20033a0000200041226a2002290320370000200041196a2016290300370000200041116a2015290300370000200041096a20142903003700002000412a6a200241206a41086a290300370000200041326a200241206a41106a2903003700002000413a6a200241206a41186a290300370000200041053a00000b200241c0006a24000f0b1044000b1045000b103e000b103c000b890501047f230041206b220224000240024002400240024002402001280200417f6a220341024b0d0020030e03010203010b41cfa2cc00412841c086cc00103f000b41b00210332203450d032003200128020410d10620004101360200200020033602040c020b410121030240024020012d00044101470d00200141086a28020021010c010b2002411e6a200141046a220341036a2d00003a0000200241086a200141146a290200370300200241106a2001411c6a290200370300200241186a200141246a2d00003a0000200220032f00013b011c20022001410c6a290200370300200141086a2802002101410021030b200020033a0004200020022f011c3b000520004102360200200041086a20013602002000410c6a2002290300370200200041076a2002411c6a41026a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a2802003602000c010b410121040240024020012d00044101470d00200141086a28020021050c010b2002411e6a200141046a220341036a2d00003a0000200241086a200141146a290200370300200241106a2001411c6a290200370300200241186a200141246a2d00003a0000200220032f00013b011c20022001410c6a290200370300200141086a2802002105410021040b41b00210332203450d012003200128022810d106200020043a0004200041086a2005360200200041286a200336020020004103360200200020022f011c3b0005200041076a2002411e6a2d00003a00002000410c6a2002290300370200200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a2802003602000b200241206a24000f0b103c000b920203027f017e037f230041206b220224000240024020012802082203ad420c7e2204422088a70d002004a72205417f4c0d00200128020021010240024020050d00410421060c010b200510332206450d020b200241003602082002200636020020022005410c6e3602042002410020031087012002280208210702402003450d002003410c6c210620022802002007410c6c6a21052003410274417c6a41027621030340200241106a2001109f03200541086a200241106a41086a280200360200200520022903103702002005410c6a21052001410c6a2101200641746a22060d000b200720036a41016a21070b20002002290300370200200041086a2007360200200241206a24000f0b1044000b1045000b110041cfa2cc00412841c086cc00103f000bc95704027f017e3a7f017e230041e0036b220224000240024002400240024002400240024002400240024002400240024002400240024020012d0000417f6a2203410a4b0d0020030e0b0102030405060708090a0b010b41cfa2cc00412841c086cc00103f000b200041013a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000c0a0b2001410c6a2802002203ad42c8007e2204422088a70d0a2004a72205417f4c0d0a200141046a28020021060240024020050d00410421070c010b200510332207450d0c0b200241003602d003200220073602c8032002200541c8006e3602cc03200241c8036a4100200310a80120022802d003210802402003450d002006200341c8006c6a210920022802c803200841c8006c6a210a4100210703404100210b4100210c024002400240024002400240200620076a22052d00000e06050102030400050b20024188026a41086a200541186a29000037030020024188026a41106a200541206a2d00003a00002002200541036a2d00003a009a032002200541016a2f00003b0198032002200541106a290000370388022005410c6a280000210d200541086a280000210e200541046a280000210f4105210c0c040b2005410c6a280200220d417f4c0d10200541046a280200210c02400240200d0d00410021034101210f0c010b200d1033220f450d12200d21030b024002402003200d490d002003210e0c010b2003410174220e200d200e200d4b1b220e4100480d13024020030d00200e1033220f0d010c150b2003200e460d00200f2003200e1037220f450d140b200f200c200d109d081a4101210c0c030b20024188026a41086a200541186a29000037030020024188026a41106a200541206a2d00003a00002002200541036a2d00003a009a032002200541016a2f00003b0198032002200541106a290000370388022005410c6a280000210d200541086a280000210e200541046a280000210f4102210c0c020b20024188026a41086a200541186a29000037030020024188026a41106a200541206a2d00003a00004103210c2002200541036a2d00003a009a032002200541016a2f00003b0198032002200541106a290000370388022005410c6a280000210d200541086a280000210e200541046a280000210f0c010b20024188026a41086a200541186a29000037030020024188026a41106a200541206a2d00003a00002002200541036a2d00003a009a032002200541016a2f00003b0198032002200541106a290000370388022005410c6a280000210d200541086a280000210e4104210c200541046a280000210f0b024002400240024002400240200541246a2d00000e06050102030400050b200241e8026a41026a200541276a2d00003a0000200241086a41086a2005413c6a290000370300200241086a41106a200541c4006a2d00003a00002002200541256a2f00003b01e8022002200541346a290000370308200541306a28000021102005412c6a2800002111200541286a28000021124105210b0c040b200541306a2802002210417f4c0d10200541286a280200210b0240024020100d0041002103410121120c010b201010332212450d12201021030b0240024020032010490d00200321110c010b200341017422112010201120104b1b22114100480d13024020030d00201110332212450d150c010b20032011460d0020122003201110372212450d140b2012200b2010109d081a4101210b0c030b4102210b200241e8026a41026a200541276a2d00003a0000200241086a41086a2005413c6a290000370300200241086a41106a200541c4006a2d00003a00002002200541256a2f00003b01e8022002200541346a290000370308200541306a28000021102005412c6a2800002111200541286a28000021120c020b200241e8026a41026a200541276a2d00003a0000200241086a41086a2005413c6a290000370300200241086a41106a200541c4006a2d00003a00002002200541256a2f00003b01e8022002200541346a290000370308200541306a28000021102005412c6a2800002111200541286a28000021124103210b0c010b200241e8026a41026a200541276a2d00003a0000200241086a41086a2005413c6a290000370300200241086a41106a200541c4006a2d00003a00002002200541256a2f00003b01e8022002200541346a290000370308200541306a28000021102005412c6a2800002111200541286a28000021124104210b0b200a20076a2203200c3a0000200341016a20022f0198033b0000200341036a20022d009a033a00002003410c6a200d360000200341086a200e360000200341046a200f360000200341106a200229038802370000200341216a20022f0080033b0000200341186a20024188026a41086a290300370000200341206a20024188026a41106a2d00003a0000200341236a20024180036a41026a2d00003a0000200341246a200b3a0000200341286a20123600002003412c6a2011360000200341306a2010360000200341256a20022f01e8023b0000200341276a200241e8026a41026a2d00003a0000200341346a20022903083700002003413c6a200241086a41086a290300370000200341c4006a200241086a41106a2d00003a0000200341c5006a20022f00b0033b0000200341c7006a200241b0036a41026a2d00003a0000200741c8006a2107200841016a2108200541c8006a2009470d000b0b200241a8026a41086a2008360200200220022903c8033703a8024100211341002114024002400240024002400240200141106a2d00000e06050102030400050b200241cc026a200141136a2d00003a0000200241b8026a41086a200141286a290000370300200241b8026a41106a200141306a2d00003a00002002200141116a2f00003b01ca022002200141206a2900003703b8022001411c6a2800002103200141186a280000210a200141146a2800002108410521140c040b2001411c6a2802002203417f4c0d0e200141146a28020021070240024020030d0041002105410121080c010b200310332208450d10200321050b0240024020052003490d002005210a0c010b2005410174220b2003200b20034b1b220a4100480d11024020050d00200a10332208450d130c010b2005200a460d0020082005200a10372208450d120b200820072003109d081a410121140c030b41022114200241ca026a41026a200141136a2d00003a0000200241b8026a41086a200141286a290000370300200241b8026a41106a200141306a2d00003a00002002200141116a2f00003b01ca022002200141206a2900003703b8022001411c6a2800002103200141186a280000210a200141146a28000021080c020b200241cc026a200141136a2d00003a0000200241b8026a41086a200141286a290000370300200241b8026a41106a200141306a2d00003a00002002200141116a2f00003b01ca022002200141206a2900003703b8022001411c6a2800002103200141186a280000210a200141146a2800002108410321140c010b200241cc026a200141136a2d00003a0000200241b8026a41086a200141286a290000370300200241b8026a41106a200141306a2d00003a00002002200141116a2f00003b01ca022002200141206a2900003703b8022001411c6a2800002103200141186a280000210a200141146a2800002108410421140b024002400240024002400240200141346a2d00000e06050102030400050b200241e4026a200141376a2d00003a0000200241d8026a200141cc006a290000370300200241e0026a200141d4006a2d00003a00002002200141356a2f00003b01e2022002200141c4006a2900003703d002200141c0006a28000021052001413c6a2800002115200141386a280000210f410521130c040b200141c0006a2802002205417f4c0d0e200141386a280200210b0240024020050d00410021074101210f0c010b20051033220f450d10200521070b0240024020072005490d00200721150c010b2007410174220c2005200c20054b1b22154100480d11024020070d0020151033220f450d130c010b20072015460d00200f200720151037220f450d120b200f200b2005109d081a410121130c030b41022113200241e2026a41026a200141376a2d00003a0000200241d8026a200141cc006a290000370300200241e0026a200141d4006a2d00003a00002002200141356a2f00003b01e2022002200141c4006a2900003703d002200141c0006a28000021052001413c6a2800002115200141386a280000210f0c020b200241e4026a200141376a2d00003a0000200241d8026a200141cc006a290000370300200241e0026a200141d4006a2d00003a00002002200141356a2f00003b01e2022002200141c4006a2900003703d002200141c0006a28000021052001413c6a2800002115200141386a280000210f410321130c010b200241e4026a200141376a2d00003a0000200241d8026a200141cc006a290000370300200241e0026a200141d4006a2d00003a00002002200141356a2f00003b01e2022002200141c4006a2900003703d002200141c0006a28000021052001413c6a2800002115200141386a280000210f410421130b4100211641002117024002400240024002400240200141d8006a2d00000e06050102030400050b200241fc026a200141db006a2d00003a0000200241f0026a200141f0006a290000370300200241f8026a200141f8006a2d00003a00002002200141d9006a2f00003b01fa022002200141e8006a2900003703e802200141e4006a2800002107200141e0006a2800002118200141dc006a2800002112410521170c040b200141e4006a2802002207417f4c0d0e200141dc006a280200210c0240024020070d004100210b410121120c010b200710332212450d102007210b0b02400240200b2007490d00200b21180c010b200b410174220d2007200d20074b1b22184100480d110240200b0d00201810332212450d130c010b200b2018460d002012200b201810372212450d120b2012200c2007109d081a410121170c030b41022117200241fa026a41026a200141db006a2d00003a0000200241f0026a200141f0006a290000370300200241f8026a200141f8006a2d00003a00002002200141d9006a2f00003b01fa022002200141e8006a2900003703e802200141e4006a2800002107200141e0006a2800002118200141dc006a28000021120c020b200241fc026a200141db006a2d00003a0000200241f0026a200141f0006a290000370300200241f8026a200141f8006a2d00003a00002002200141d9006a2f00003b01fa022002200141e8006a2900003703e802200141e4006a2800002107200141e0006a2800002118200141dc006a2800002112410321170c010b200241fc026a200141db006a2d00003a0000200241f0026a200141f0006a290000370300200241f8026a200141f8006a2d00003a00002002200141d9006a2f00003b01fa022002200141e8006a2900003703e802200141e4006a2800002107200141e0006a2800002118200141dc006a2800002112410421170b024002400240024002400240200141fc006a2d00000e06050102030400050b20024194036a200141ff006a2d00003a000020024188036a20014194016a29000037030020024190036a2001419c016a2d00003a00002002200141fd006a2f00003b01920320022001418c016a2900003703800320014188016a280000210b20014184016a280000211920014180016a280000210e410521160c040b20014188016a280200220b417f4c0d0e20014180016a280200210d02400240200b0d004100210c4101210e0c010b200b1033220e450d10200b210c0b02400240200c200b490d00200c21190c010b200c4101742210200b2010200b4b1b22194100480d110240200c0d0020191033220e450d130c010b200c2019460d00200e200c20191037220e450d120b200e200d200b109d081a410121160c030b4102211620024192036a41026a200141ff006a2d00003a000020024188036a20014194016a29000037030020024190036a2001419c016a2d00003a00002002200141fd006a2f00003b01920320022001418c016a2900003703800320014188016a280000210b20014184016a280000211920014180016a280000210e0c020b20024194036a200141ff006a2d00003a000020024188036a20014194016a29000037030020024190036a2001419c016a2d00003a00002002200141fd006a2f00003b01920320022001418c016a2900003703800320014188016a280000210b20014184016a280000211920014180016a280000210e410321160c010b20024194036a200141ff006a2d00003a000020024188036a20014194016a29000037030020024190036a2001419c016a2d00003a00002002200141fd006a2f00003b01920320022001418c016a2900003703800320014188016a280000210b20014184016a280000211920014180016a280000210e410421160b4100211a4100211b024002400240024002400240200141a0016a2d00000e06050102030400050b200241ac036a200141a3016a2d00003a0000200241a0036a200141b8016a290000370300200241a8036a200141c0016a2d00003a00002002200141a1016a2f00003b01aa032002200141b0016a29000037039803200141ac016a280000210c200141a8016a280000211c200141a4016a28000021114105211b0c040b200141ac016a280200220c417f4c0d0e200141a4016a280200211002400240200c0d004100210d410121110c010b200c10332211450d10200c210d0b02400240200d200c490d00200d211c0c010b200d4101742206200c2006200c4b1b221c4100480d110240200d0d00201c10332211450d130c010b200d201c460d002011200d201c10372211450d120b20112010200c109d081a4101211b0c030b4102211b200241aa036a41026a200141a3016a2d00003a0000200241a0036a200141b8016a290000370300200241a8036a200141c0016a2d00003a00002002200141a1016a2f00003b01aa032002200141b0016a29000037039803200141ac016a280000210c200141a8016a280000211c200141a4016a28000021110c020b200241ac036a200141a3016a2d00003a0000200241a0036a200141b8016a290000370300200241a8036a200141c0016a2d00003a00002002200141a1016a2f00003b01aa032002200141b0016a29000037039803200141ac016a280000210c200141a8016a280000211c200141a4016a28000021114103211b0c010b200241ac036a200141a3016a2d00003a0000200241a0036a200141b8016a290000370300200241a8036a200141c0016a2d00003a00002002200141a1016a2f00003b01aa032002200141b0016a29000037039803200141ac016a280000210c200141a8016a280000211c200141a4016a28000021114104211b0b02402001418c026a2d00004101470d0020024198026a2001419d026a28000036020020024190026a20014195026a29000037030020022001418d026a290000370388024101211a0b4100211d4100211e024002400240024002400240200141c4016a2d00000e06050102030400050b200241c4036a200141c7016a2d00003a0000200241b8036a200141dc016a290000370300200241c0036a200141e4016a2d00003a00002002200141c5016a2f00003b01c2032002200141d4016a2900003703b003200141d0016a280000210d200141cc016a280000211f200141c8016a28000021064105211e0c040b200141d0016a280200220d417f4c0d0e200141c8016a280200210902400240200d0d0041002110410121060c010b200d10332206450d10200d21100b024002402010200d490d002010211f0c010b2010410174221f200d201f200d4b1b221f4100480d11024020100d00201f10332206450d130c010b2010201f460d0020062010201f10372206450d120b20062009200d109d081a4101211e0c030b4102211e200241c2036a41026a200141c7016a2d00003a0000200241b8036a200141dc016a290000370300200241c0036a200141e4016a2d00003a00002002200141c5016a2f00003b01c2032002200141d4016a2900003703b003200141d0016a280000210d200141cc016a280000211f200141c8016a28000021060c020b200241c4036a200141c7016a2d00003a0000200241b8036a200141dc016a290000370300200241c0036a200141e4016a2d00003a00002002200141c5016a2f00003b01c2032002200141d4016a2900003703b003200141d0016a280000210d200141cc016a280000211f200141c8016a28000021064103211e0c010b200241c4036a200141c7016a2d00003a0000200241b8036a200141dc016a290000370300200241c0036a200141e4016a2d00003a00002002200141c5016a2f00003b01c2032002200141d4016a2900003703b003200141d0016a280000210d200141cc016a280000211f200141c8016a28000021064104211e0b024002400240024002400240200141e8016a2d00000e06050102030400050b200241de036a200141eb016a2d00003a0000200241d0036a20014180026a290000370300200241d8036a20014188026a2d00003a00002002200141e9016a2f00003b01dc032002200141f8016a2900003703c803200141f4016a2800002110200141f0016a2800002120200141ec016a28000021094105211d0c040b200141f4016a2802002210417f4c0d0e200141ec016a280200211d0240024020100d0041002101410121090c010b201010332209450d10201021010b0240024020012010490d00200121200c010b200141017422202010202020104b1b22204100480d11024020010d00202010332209450d130c010b20012020460d0020092001202010372209450d120b2009201d2010109d081a4101211d0c030b4102211d200241dc036a41026a200141eb016a2d00003a0000200241d0036a20014180026a290000370300200241d8036a20014188026a2d00003a00002002200141e9016a2f00003b01dc032002200141f8016a2900003703c803200141f4016a2800002110200141f0016a2800002120200141ec016a28000021090c020b200241de036a200141eb016a2d00003a0000200241d0036a20014180026a290000370300200241d8036a20014188026a2d00003a00002002200141e9016a2f00003b01dc032002200141f8016a2900003703c803200141f4016a2800002110200141f0016a2800002120200141ec016a28000021094103211d0c010b200241de036a200141eb016a2d00003a0000200241d0036a20014180026a290000370300200241d8036a20014188026a2d00003a00002002200141e9016a2f00003b01dc032002200141f8016a2900003703c803200141f4016a2800002110200141f0016a2800002120200141ec016a28000021094104211d0b200241f8016a41086a2201200241a8026a41086a280200360200200241f4016a41026a2221200241ca026a41026a2d00003a0000200241e0016a41086a2222200241b8026a41086a290300370300200241e0016a41106a2223200241b8026a41106a2d00003a0000200241dc016a41026a2224200241b5026a41026a2d00003a0000200220022903a8023703f801200220022f01ca023b01f401200220022903b8023703e001200220022f00b5023b01dc01200241d8016a41026a2225200241e2026a41026a2d00003a0000200241c0016a41086a2226200241d0026a41086a290300370300200241c0016a41106a2227200241d0026a41106a2d00003a0000200241bc016a41026a2228200241cd026a41026a2d00003a0000200241b8016a41026a2229200241fa026a41026a2d00003a0000200220022f01e2023b01d801200220022903d0023703c001200220022f00cd023b01bc01200220022f01fa023b01b801200241a0016a41106a222a200241e8026a41106a2d00003a0000200241a0016a41086a222b200241e8026a41086a2903003703002002419c016a41026a222c200241e5026a41026a2d00003a000020024198016a41026a222d20024192036a41026a2d00003a000020024180016a41106a222e20024180036a41106a2d00003a000020024180016a41086a222f20024180036a41086a290300370300200220022903e8023703a001200220022f00e5023b019c01200220022f0192033b019801200220022903800337038001200241fc006a41026a2230200241fd026a41026a2d00003a0000200220022f00fd023b017c200241f8006a41026a2231200241aa036a41026a2d00003a0000200220022f01aa033b0178200241e0006a41106a223220024198036a41106a2d00003a0000200241e0006a41086a223320024198036a41086a2903003703002002200229039803370360200241dc006a41026a223420024195036a41026a2d00003a0000200220022f0095033b015c200241086a41106a223520024188026a41106a280200360200200241086a41086a223620024188026a41086a2903003703002002200229038802370308200241d8006a41026a2237200241c2036a41026a2d00003a0000200220022f01c2033b0158200241c0006a41106a2238200241b0036a41106a2d00003a0000200241c0006a41086a2239200241b0036a41086a290300370300200220022903b0033703402002413c6a41026a223a200241ad036a41026a2d00003a0000200220022f00ad033b013c200241386a41026a223b200241dc036a41026a2d00003a0000200220022f01dc033b0138200241206a41106a223c200241c8036a41106a2d00003a0000200241206a41086a223d200241c8036a41086a290300370300200220022903c8033703202002411c6a41026a223e200241c5036a41026a2d00003a0000200220022f00c5033b011c200041106a20143a00002000410c6a2001280200360200200041046a20022903f8013702002000411c6a2003360000200041186a200a360000200041146a2008360000200041116a20022f01f4013b0000200041136a20212d00003a0000200041206a20022903e001370000200041286a2022290300370000200041306a20232d00003a0000200041336a20242d00003a0000200041316a20022f01dc013b0000200041346a20133a0000200041376a20252d00003a0000200041356a20022f01d8013b0000200041c0006a20053600002000413c6a2015360000200041386a200f360000200041d4006a20272d00003a0000200041cc006a2026290300370000200041c4006a20022903c001370000200041d7006a20282d00003a0000200041d5006a20022f01bc013b0000200041d8006a20173a0000200041db006a20292d00003a0000200041d9006a20022f01b8013b0000200041e4006a2007360000200041e0006a2018360000200041dc006a2012360000200041f8006a202a2d00003a0000200041f0006a202b290300370000200041e8006a20022903a001370000200041fb006a202c2d00003a0000200041f9006a20022f019c013b0000200041fc006a20163a0000200041ff006a202d2d00003a0000200041fd006a20022f0198013b000020004188016a200b36000020004184016a201936000020004180016a200e3600002000419c016a202e2d00003a000020004194016a202f2903003700002000418c016a2002290380013700002000419f016a20302d00003a00002000419d016a20022f017c3b0000200041a0016a201b3a0000200041a3016a20312d00003a0000200041a1016a20022f01783b0000200041ac016a200c360000200041a8016a201c360000200041a4016a2011360000200041c0016a20322d00003a0000200041b8016a2033290300370000200041b0016a2002290360370000200041c3016a20342d00003a0000200041c1016a20022f015c3b0000200041c4016a201e3a0000200041c7016a20372d00003a0000200041c5016a20022f01583b0000200041d0016a200d360000200041cc016a201f360000200041c8016a2006360000200041e4016a20382d00003a0000200041dc016a2039290300370000200041d4016a2002290340370000200041e7016a203a2d00003a0000200041e5016a20022f013c3b0000200041e8016a201d3a0000200041eb016a203b2d00003a0000200041e9016a20022f01383b0000200041f4016a2010360000200041f0016a2020360000200041ec016a200936000020004188026a203c2d00003a000020004180026a203d290300370000200041f8016a20022903203700002000418b026a203e2d00003a000020004189026a20022f011c3b00002000418c026a201a3a00002000419d026a203528020036000020004195026a20362903003700002000418d026a2002290308370000200041a3026a20024188026a41026a2d00003a0000200041a1026a20022f0088023b0000200041023a00000c090b2001410c6a2802002203ad42c4007e2204422088a70d092004a72205417f4c0d09200141046a28020021060240024020050d00410421070c010b200510332207450d0b0b41002101200241003602b803200220073602b0032002200541c4006e3602b403200241b0036a41002003109f0120022802b803210b02402003450d002006200341c4006c6a210920022802b003200b41c4006c6a210a20024188026a41086a210c20024188026a41106a210d0340200c200620016a220541176a290000370300200d2005411f6a2d00003a0000200220052f01003b0198032002200541026a2d00003a009a0320022005410f6a290000370388022005410b6a2800002110200541076a2800002108200541036a280000210f41002107024002400240024002400240200541206a2d00000e06050102030400050b200241e8026a41026a200541236a2d00003a0000200241086a41086a200541386a290000370300200241086a41106a200541c0006a2d00003a00002002200541216a2f00003b01e8022002200541306a2900003703082005412c6a2800002111200541286a280000210e200541246a2800002112410521070c040b200241c8036a200541246a109f0320022802d003211120022802cc03210e20022802c8032112410121070c030b41022107200241e8026a41026a200541236a2d00003a0000200241086a41086a200541386a290000370300200241086a41106a200541c0006a2d00003a00002002200541216a2f00003b01e8022002200541306a2900003703082005412c6a2800002111200541286a280000210e200541246a28000021120c020b200241e8026a41026a200541236a2d00003a0000200241086a41086a200541386a290000370300200241086a41106a200541c0006a2d00003a00002002200541216a2f00003b01e8022002200541306a2900003703082005412c6a2800002111200541286a280000210e200541246a2800002112410321070c010b200241e8026a41026a200541236a2d00003a0000200241086a41086a200541386a290000370300200241086a41106a200541c0006a2d00003a00002002200541216a2f00003b01e8022002200541306a2900003703082005412c6a2800002111200541286a280000210e200541246a2800002112410421070b200a20016a220320022f0198033b0100200341026a20022d009a033a00002003410b6a2010360000200341076a2008360000200341036a200f3600002003410f6a200229038802370000200341176a200c2903003700002003411f6a200d2d00003a0000200341206a20073a0000200341216a20022f01e8023b0000200341236a200241e8026a41026a2d00003a00002003412c6a2011360000200341286a200e360000200341246a2012360000200341306a2002290308370000200341386a200241086a41086a290300370000200341c0006a200241086a41106a2d00003a0000200341c1006a20022f0080033b0000200341c3006a20024180036a41026a2d00003a0000200141c4006a2101200b41016a210b200541c4006a2009470d000b0b20024190026a200b360200200220022903b0032204370388022000410c6a200b360200200041046a2004370200200041033a00000c080b200041043a00000c070b200041053a0000200041106a200141106a290300370300200041086a200141086a290300370300200041046a200141046a2802003602000c060b200041063a0000200041046a200141046a2802003602000c050b200041073a0000200041106a200141106a290300370300200041086a200141086a290300370300200041046a200141046a2802003602000c040b200041083a000020002001290001370001200041246a200141246a280200360200200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a2900003700000c030b200041093a0000200041086a200141086a290300370300200041046a200141046a2802003602000c020b200141046a28020021054101210302400240200141086a2d00004101470d002001410c6a28020021070c010b2002410a6a2001410b6a2d00003a000020024188026a41086a200141186a29000037030020024188026a41106a200141206a29000037030020024188026a41186a200141286a2d00003a00002002200141096a2f00003b01082002200141106a290000370388022001410c6a2800002107410021030b200041086a20033a0000200041046a2005360200200041096a20022f01083b00002000410c6a2007360200200041106a2002290388023702002000410b6a2002410a6a2d00003a0000200041186a20024188026a41086a290300370200200041206a20024188026a41106a290300370200200041286a20024188026a41186a280200360200200141386a29030021042001350230213f200041c0006a200141c0006a290300370300200041386a2004370300200041306a203f3703002000410a3a00000c010b4101210302400240200141046a2d00004101470d00200141086a28020021050c010b2002410a6a200141076a2d00003a000020024188026a41086a200141146a29000037030020024198026a2001411c6a290000370300200241a0026a200141246a2d00003a00002002200141056a2f00003b010820022001410c6a29000037038802200141086a2800002105410021030b2000410b3a0000200041046a20033a0000200041056a20022f01083b0000200041086a20053602002000410c6a200229038802370200200041076a2002410a6a2d00003a0000200041146a20024188026a41086a2903003702002000411c6a20024198026a290300370200200041246a200241a0026a2802003602000b200241e0036a24000f0b1044000b1045000b103e000b103c000ba80901067f230041306b2202240002400240024002400240024002400240024002400240024002400240024002400240024020012d0000417f6a2203410b4b0d0020030e0c0102030405060708090a0b0c010b41cfa2cc00412841c086cc00103f000b200041013a0000200041106a200141106a290300370300200041086a200141086a2903003703000c0b0b200041023a0000200041046a200141046a2802003602000c0a0b200041033a000020002001290001370001200041c0006a200141c0006a290300370300200041386a200141386a290300370300200041306a200141306a290300370300200041286a200141286a290300370300200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a2900003700000c090b200041043a0000200041046a200141046a2802003602000c080b4101210302400240200141046a2d00004101470d00200141086a28020021040c010b2002410e6a200141076a2d00003a0000200241106a41086a200141146a290000370300200241206a2001411c6a290000370300200241286a200141246a2d00003a00002002200141056a2f00003b010c20022001410c6a290000370310200141086a2800002104410021030b200041053a0000200041046a20033a0000200041056a20022f010c3b0000200041086a20043602002000410c6a2002290310370200200041076a2002410e6a2d00003a0000200041146a200241106a41086a2903003702002000411c6a200241206a290300370200200041246a200241286a280200360200200020012d00014100473a00010c070b200041063a0000200020012d00014100473a00010c060b200041073a00000c050b200241286a200141196a290000370300200241206a200141116a290000370300200241186a200141096a29000037030020022001290001370310200141306a2802002203417f4c0d05200141286a2802002105200141246a28020021060240024020030d0041002101410121070c010b200310332207450d07200321010b0240024020012003490d00200121040c010b200141017422042003200420034b1b22044100480d08024020010d002004103322070d010c0a0b20012004460d0020072001200410372207450d090b200720052003109d082101200041306a20033602002000412c6a2004360200200041286a2001360200200041246a2006360200200041083a0000200041196a200241286a290300370000200041116a200241206a290300370000200041096a200241106a41086a290300370000200020022903103700010c040b200041093a00000c030b2000410a3a000020002001290001370001200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a290000370000200041216a200141216a2d00004100473a00000c020b2000410b3a000020002001290001370001200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a290000370000200041216a200141216a2d00003a00000c010b2000410c3a0000200041046a200141046a2802003602000b200241306a24000f0b1044000b1045000b103e000b103c000be90802097f017e230041306b220224000240024002400240024002400240024002400240024002400240024020012d0000417f6a220341084b0d0020030e09010203040506070809010b41cfa2cc00412841c086cc00103f000b200241186a2204200141196a290000370300200241106a2205200141116a290000370300200241086a2206200141096a2900003703002002200129000137030041b00210332203450d092003200141246a280200109b03200041246a2003360200200041013a0000200041196a2004290300370000200041116a2005290300370000200041096a2006290300370000200020022903003700010c080b200041023a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a290000370000200041216a200141216a290000370000200041296a200141296a290000370000200041316a200141316a290000370000200041396a200141396a2900003700000c070b2001410c6a280200220741ffffff3f712007470d0820074105742204417f4c0d08200141046a28020021060240024020040d00410121050c010b200410332205450d0a0b41002103200241003602082002200536020020022004410576360204200241002007108a012002280208210802402007450d0020074105742109200228020020084105746a210a0340200a20036a2204200620036a2205290000370000200441186a200541186a290000370000200441106a200541106a290000370000200441086a200541086a2900003700002009200341206a2203470d000b200741057441606a41057620086a41016a21080b200241286a200836020020022002290300220b370320200041046a200b3702002000410c6a2008360200200041033a0000200041106a2001280210360200200041026a20012f01023b01000c060b200041043a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000c050b200041053a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a290000370000200041216a200141216a290000370000200041296a200141296a290000370000200041316a200141316a290000370000200041396a200141396a2900003700000c040b200041063a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000c030b200041073a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000c020b200041083a00000c010b200041093a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000b200241306a24000f0b103c000b1044000b1045000bda9b01070b7f017e097f027e037f017e177f230041a00a6b220324000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e06000102030405000b200341f4066a4101360200200342013702e406200341e8d4ca003602e0062003410436029c032003419cd5ca0036029803200320034198036a3602f006200341e0066a41b0b4cc00104c000b200341e8056a41026a2204200241076a2d00003a00002003200241056a2f00003b01e805200141046a28020022052001410c6a280200220641b0026c22076a2108200141086a280200210920052101024002402006450d00200241046a2d0000210a200241026a2f0100210b200241086a280200210c2002410c6a280200210d200241106a290200210e200241186a280200210f200241246a2d0000211020022d0001211120022d0000211220034198036a410272211320034198036a4105722114200741d07d6a2106200341bd036a2115200341c0066a4103722116200341e0066a41047221172002411c6a29020022184220882119200341de066a211a4100211b2005210103402001280200210220034198036a200141046a220741ac02109d081a200341e0066a200741ac02109d081a02402002411b470d00200141b0026a21010c2b0b200341e8006a200341e0066a41ac02109d081a200320023602e0062017200341e8006a41ac02109d081a024002400240024020120e03000102000b4102210202400240024020110e03000102000b410021020c010b201620032f01e8053b0000200320183e01da06201a20193d0100201641026a20042d00003a00002003200a3a00c2062003200b3b01c0062003200f3601d6062003200e3701ce062003200d3601ca062003200c3601c606410121020b201320032903c006370000201341086a200341c0066a41086a290300370000201341106a200341c0066a41106a290300370000201341186a200341c0066a41186a290300370000200320023a009903200341003a0098030c020b41022102024002400240200a0e03000102000b410021020c010b20034188066a41026a20042d00003a0000200320032f01e8053b018806410121020b201420032f0188063b0000201520032f00b8093b0000201441026a20034188066a41026a2d00003a0000201541026a200341b8096a41026a2d00003a0000200320023a009c03200320103a00bc03200320183702b4032003200f3602b0032003200e3703a8032003200d3602a4032003200c3602a003200341013a0098030c010b41022102024002400240200a0e03000102000b410021020c010b200341c4056a41026a20042d00003a0000200320032f01e8053b01c405201c41807e71201072211c410121020b201420032f01c4053b0000200341023a009803201441026a200341c4056a41026a2d00003a0000200320023a009c032003201c3602bc03200320183702b4032003200f3602b0032003200e3703a8032003200d3602a4032003200c3602a0030b20034190096a200341e0066a20034198036a10ac032003290390094201510d02201b41016a211b200641d07d6a2106200141b0026a22012008470d000b200821010b200341e0066a20034198036a41ac02109d081a0c280b20034198036a41186a200341b0096a290300220e37030020034198036a41106a20034190096a41186a290300221837030020034198036a41086a20034190096a41106a290300370300200320032903980937039803200341e0066a41086a201b360200200341ec066a2018370200200341f4066a200e3e0200200341003a00e406200341013a00e00641b0b4cc004100200341e0066a10d40102402006450d00200141b0026a21010340200110bb02200141b0026a2101200641d07d6a22060d000b0b2009450d28200941b0026c450d28200510350c280b41022106200141046a280200210820022d00000d0520022d00014101470d052002411a6a290100210e200241196a2d00002106200241186a2d00002107200241166a2f0100211b200241156a2d00002113200241146a2d00002114200241126a2f01002112200241116a2d00002117200241106a2d0000210a2002410e6a2f0100210c2002410d6a2d0000210d2002410c6a2d0000210f2002410a6a2f01002115200241096a2d0000211c200241086a2d00002110200241066a2f01002104200241056a2d00002105200241046a2d00002111200241026a2f01002102200141026a2f01002109411210332201450d03200141086a4100290085aa43370000200141002900fda94337000020014112413010372201450d042001200e370028200120063a0027200120073a00262001201b3b0024200120133a0023200120143a0022200120123b0020200120173a001f2001200a3a001e2001200c3b001c2001200d3a001b2001200f3a001a200120153b00182001201c3a0017200120103a0016200120043b0014200120053a0013200120113a0012200120023b00102001413041e00010372202450d04200220093b00302002ad4280808080a0068410092201290000210e200141086a2900002118200141106a2900002119200341c0066a41186a2206200141186a290000370300200341c0066a41106a22072019370300200341c0066a41086a221b20183703002003200e3703c0062001103520021035200341093a0080072003410a3a0080072003410b3a008007200320032f01c0063b01e006200320032801c2063601e206200320032f01c6063b01e6062003201b2f01003b01e806200320032d00ca063a00ea062003410c3a008007200320032d00cb063a00eb062003410d3a008007200320032d00cc063a00ec062003410e3a008007200320032d00cd063a00ed062003410f3a008007200320032d00ce063a00ee06200341103a008007200320032d00cf063a00ef06200341113a008007200320072d00003a00f006200320032d00d1063a00f106200341123a008007200341133a008007200320032d00d2063a00f206200341143a008007200320032d00d3063a00f306200341153a008007200320032d00d4063a00f406200341163a008007200320032d00d5063a00f506200341173a008007200320032d00d6063a00f606200341183a008007200320032d00d7063a00f706200341193a008007200320062d00003a00f806200320032d00d9063a00f9062003411a3a0080072003411b3a008007200320032d00da063a00fa062003411c3a008007200320032d00db063a00fb062003411d3a008007200320032d00dc063a00fc062003411e3a008007200320032d00dd063a00fd062003411f3a008007200320032d00de063a00fe06200341203a008007200320032d00df063a00ff0620034190096a41186a220120032903f80637030020034190096a41106a220220032903f00637030020034190096a41086a220620032903e806370300200320032903e006370390092006290300210e2002290300211820012903002119200329039009211d200341e0066a200841b002109d081a20034198036a411a6a201937010020034198036a41126a201837010020034198036a410a6a200e3701002003201d37019a0320034180023b019803200341e8006a200341e0066a20034198036a10ac030240024020032903684201520d0020032903704202520d010b200810354200210e0c260b200341e8006a411c6a2902002118200341e8006a41186a2802002106200810354200210e200641ff01714104460d25200641807e7121010c240b2001411c6a280200210841022106200141086a2802002107200141046a280200211b024020022d00000d0020022d00014101470d00200141186a280200211e200141146a280200211f200141106a2802002120200141026a2f010021062001410c6a2802002101200241196a2d00002113200241186a2d00002114200241166a2f01002112200241156a2d00002117200241146a2d0000210a200241126a2f0100210c200241116a2d0000210d200241106a2d0000210f2002410e6a2f010021152002410d6a2d0000211c2002410c6a2d000021102002410a6a2f01002104200241096a2d00002105200241086a2d00002111200241066a2f01002109200241056a2d00002116200241046a2d0000210b200241026a2f0100211a20032002411a6a2901003703e005200320133a00df05200320143a00de05200320123b01dc05200320173a00db052003200a3a00da052003200c3b01d8052003200d3a00d7052003200f3a00d605200320153b01d4052003201c3a00d305200320103a00d205200320043b01d005200320053a00cf05200320113a00ce05200320093b01cc05200320163a00cb052003200b3a00ca052003201a3b01c805200641ffff0371450d062001450d07200141e4004f0d08200320013602702003200736026c2003201b360268200341e0066a41186a200341c8056a41186a290300370300200341e0066a41106a200341c8056a41106a290300370300200341e0066a41086a2202200341c8056a41086a290300370300200320032903c8053703e00620034198036a200341e8006a200341e0066a10ad032003280298034101460d0920034198036a41086a2802002121200328029c032117200220034198036a410c6a280200360200200320063b01ec06200320173602e406200341fda9c3003602e006200341c0066a200341e0066a10ae03200341083a0080072003410b3a0080072003410c3a008007200320032f01c0063b01e006200320032801c2063601e206200320032d00c6063a00e606200320032800c7063600e706200320032d00cb063a00eb062003410d3a008007200320032d00cc063a00ec062003410e3a008007200320032d00cd063a00ed062003410f3a008007200320032d00ce063a00ee06200320032d00cf063a00ef06200341103a008007200341113a008007200320032d00d0063a00f006200341123a008007200320032d00d1063a00f106200341133a008007200320032d00d2063a00f206200341143a008007200320032d00d3063a00f306200341153a008007200320032d00d4063a00f406200341163a008007200320032d00d5063a00f506200341173a008007200320032d00d6063a00f606200320032d00d7063a00f706200341183a008007200341193a008007200320032d00d8063a00f8062003411a3a008007200320032d00d9063a00f9062003411b3a008007200320032d00da063a00fa062003411c3a008007200320032d00db063a00fb062003411d3a008007200320032d00dc063a00fc062003411e3a008007200320032d00dd063a00fd062003411f3a008007200320032d00de063a00fe06200341203a008007200320032d00df063a00ff0620034190096a41186a220220032903f80637030020034190096a41106a220720032903f00637030020034190096a41086a221b20032903e806370300200320032903e00637039009200341e8056a41186a2002290300370300200341e8056a41106a2007290300370300200341e8056a41086a201b29030037030020032003290390093703e805200341003602e806200342013703e0062008200341e0066a10af0320032802e406210720033502e80642208620032802e006221bad8410092202290018210e20022d0017210a20022d0016210c20022f0014210d20022d0013210f20022d0012211520022f0010211c20022d000f211020022d000e210420022f000c210520022d000b211120022d000a210920022f0008211620022d0007210b20022d0006211a20022f0004212220022d0003212320022d0002212420022f000021252002103502402007450d00201b10350b2003200e3703d8062003200a3a00d7062003200c3a00d6062003200d3b01d4062003200f3a00d306200320153a00d2062003201c3b01d006200320103a00cf06200320043a00ce06200320053b01cc06200320113a00cb06200320093a00ca06200320163b01c8062003200b3a00c7062003201a3a00c606200320223b01c406200320233a00c306200320243a00c206200320253b01c00620034198036a200341e8056a200341c0066a10b003200341e0066a200328029803220720032802a00310d302200341c0066a41086a221b200341e0066a41086a290300370300200341c0066a41106a2213200341e0066a41106a29030037030020034190096a41086a221420034188076a29030037030020034190096a41106a222620034190076a29030037030020034190096a41186a222720034198076a29030037030020034190096a41206a200341a0076a290300370300200320032903e0063703c0062003200341e0066a41206a2903003703900920032802fc062112024020032802f8062202450d00200341d8096a41106a2013290300370300200341d8096a41086a201b29030037030020034188066a41086a201429030037030020034188066a41106a202629030037030020034188066a41186a202729030037030020034188066a41206a20034190096a41206a290300370300200320032903c0063703d8092003200329039009370388060b0240200328029c03450d00200710350b02400240024002400240024020020d004101210720204101460d01200641ffff037141014b0d02200341e0066a200841b002109d081a200341a2036a200341f0056a290300370100200341aa036a200341e8056a41106a290300370100200341b2036a200341e8056a41186a29030037010020034180023b019803200320032903e80537019a03200341e8006a200341e0066a20034198036a10ac0320032903684201520d0320032003290081013703e006200320034188016a2800003600e706200341e8006a41186a2d00002106200341e8006a41106a290300210e20032903702218a70d042003418c016a28020021010c050b200341b4036a201236020020034198036a41206a20032903880637030020034198036a41106a200341d8096a41106a29030037030020034198036a41086a200341d8096a41086a290300370300200341c0036a20034188066a41086a290300370300200341c8036a20034188066a41106a290300370300200341d0036a20034188066a41186a290300370300200341d8036a20034188066a41206a290300370300200320032903d80937039803200320023602b0034101210702400240024002400240024020204101470d0020032802a803201f470d04200341ac036a280200201e470d0420032802b803222041014b0d014100210720200e020302030b2003410b36005f200341c8f1c20036005b20034181123b00580c280b410021072020211b0340201b410176221320076a22142007200220144105746a200341c8056a412010a0084101481b2107201b20136b221b41014b0d000b0b200220074105746a200341c8056a412010a008221b450d02201b411f7620076a21070b2006417f6a41ffff0371202041ffff03714b0d240c230b2003410e36005f200341baf1c20036005b20034181143b00580c240b200641ffff0371202041ffff03714d0d212003410f36005f200341aff2c20036005b20034181023b0058410121070c230b2003411336005f200341a7f1c20036005b20034181163b01584100211b4201211942002118410321060c250b200341186a2006ad42ffff038342004280a0e5b9c2910142001084082003200329031822194280c0dfda8ee9067c22183703682003200341186a41086a2903002018201954ad7c22193703702003200341c8056a3602b8092003200341c8056a36029009200320034190096a3602e8062003200341b8096a3602e4062003200341e8006a3602e00620034198036a200341c8056a200341e0066a108c03024002402003280298034101470d00200341a4036a280200210720034198036a41086a280200211b20032d009f03211320032d009e03211420032d009d03212020032d009c0321060c010b41042106024020034198036a41086a2903004201520d0020034198036a41106a290300211d200328029009210720034198076a20034198036a41186a29030037030020034190076a201d370300200341e0066a41086a41003a0000200341e9066a2007290000370000200341f1066a200741086a290000370000200341f9066a200741106a29000037000020034181076a200741186a290000370000200341033a00e00641b0b4cc004100200341e0066a10d4010b0b0240200641ff01714104470d0020034198036a41186a420037030020034198036a41106a2213420037030020034198036a41086a22074200370300200342003703980341d1c4c700ad4280808080e000841001221b290000211d200341e0066a41086a2206201b41086a2900003703002003201d3703e006201b103520072006290300370300200320032903e0063703980341e7c4c700ad4280808080e000841001221b290000211d2006201b41086a2900003703002003201d3703e006201b1035201320032903e006221d37030020034190096a41086a200729030037030020034190096a41106a201d37030020034190096a41186a2006290300370300200320032903980337039009200341106a20034190096a412010c001200328021421072003280210211b200341086a41c4c3c700411010c001200328020c21132003280208211420032f01c805212020032d00ca05211f20032d00cb05211e20032f01cc05212620032d00ce05212720032d00cf05212820032f01d005212920032d00d205212a20032d00d305212b20032f01d405212c20032d00d605212d20032d00d705212e20032f01d805212f20032d00da05213020032d00db05213120032f01dc05213220032d00de05213320032d00df05213420032903e005211d412010332206450d08200620032903c805370000200641186a200341c8056a41186a290300370000200641106a200341c8056a41106a290300370000200641086a200341c8056a41086a290300370000200341f4066a2013410020141b3602002003419c076a201d3702002003419b076a20343a00002003419a076a20333a000020034198076a20323b010020034197076a20313a000020034196076a20303a000020034194076a202f3b010020034193076a202e3a000020034192076a202d3a000020034190076a202c3b01002003418f076a202b3a00002003418e076a202a3a00002003418c076a20293b01002003418b076a20283a00002003418a076a20273a000020034188076a20263b010020034187076a201e3a000020034186076a201f3a0000200320193703e806200320183703e006200320074100201b1b3602f006200320203b018407200341fc066a428180808010370200200320063602f8062003200e3703d8062003200a3a00d7062003200c3a00d6062003200d3b01d4062003200f3a00d306200320153a00d2062003201c3b01d006200320103a00cf06200320043a00ce06200320053b01cc06200320113a00cb06200320093a00ca06200320163b01c8062003200b3a00c7062003201a3a00c606200320223b01c406200320233a00c306200320243a00c206200320253b01c00620034198036a200341e8056a200341c0066a10b0032003280298032106200320032802a00336026c20032006360268200341e0066a200341e8006a1099030240200328029c03450d00200610350b024020032802fc0641ffffff3f71450d0020032802f80610350b20034185076a20032903e805370000200341ed066a200341c8056a41086a290300370000200341f5066a200341c8056a41106a290300370000200341fd066a200341c8056a41186a2903003700002003418d076a200341e8056a41086a29030037000020034195076a200341e8056a41106a2903003700002003419d076a200341e8056a41186a290300370000200341023a00e40641012107200341013a00e006200320032903c8053700e506200341bd076a200e370000200341bc076a200a3a0000200341bb076a200c3a0000200341b9076a200d3b0000200341b8076a200f3a0000200341b7076a20153a0000200341b5076a201c3b0000200341b4076a20103a0000200341b3076a20043a0000200341b1076a20053b0000200341b0076a20113a0000200341af076a20093a0000200341ad076a20163b0000200341ac076a200b3a0000200341ab076a201a3a0000200341a9076a20223b0000200341a8076a20233a0000200341a7076a20243a0000200341a5076a20253b00004100211b41b0b4cc004100200341e0066a10d4012001ad4290a10f7e42c0c09bd8007c210e42002119420121180c250b2003200736005f2003201b36005b200320133a005a200320143a0059200320203a00584100211b4101210742012119420021180c240b420021190240024020032903704201510d00420021180c010b427f427f427f200341f8006a290300220e42808ece1c7c22182018200e541b220e2001ad4290a10f7e7c22182018200e541b220e42c0b2cd3b7c22182018200e541b210e420121180b0c1d0b427f427f427f200e42808ece1c7c22182018200e541b220e2001ad4290a10f7e7c22182018200e541b220e42c0b2cd3b7c22182018200e541b210e420121180b200320032800e70636005f200320032903e006370358420121190c1b0b200341023a00e006200341e0066a21010c180b200141286a2802002106200141246a28020021134102210820022d00000d1320022d00014101470d13200141196a290000210e200141186a2d0000211a200141176a2d00002120200141156a2f0000211f200141146a2d0000211e200141136a2d00002122200141116a2f00002123200141106a2d000021242001410f6a2d000021252001410d6a2f000021212001410c6a2d000021262001410b6a2d00002127200141096a2f00002128200141086a2d00002129200141076a2d0000212a200141056a2f0000212b200141046a2d0000212c200141036a2d0000212d2001412c6a2802002107200141386a2802002131200141346a2802002130200141306a280200212f200141226a2f0100211420012f0001212e200241196a2d00002101200241186a2d00002108200241166a2f0100211b200241156a2d00002112200241146a2d00002117200241126a2f0100210a200241116a2d0000210c200241106a2d0000210d2002410e6a2f0100210f2002410d6a2d000021152002410c6a2d0000211c2002410a6a2f01002110200241096a2d00002104200241086a2d00002105200241066a2f01002111200241056a2d00002109200241046a2d00002116200241026a2f0100210b20032002411a6a2901003703d009200320013a00cf09200320083a00ce092003201b3b01cc09200320123a00cb09200320173a00ca092003200a3b01c8092003200c3a00c7092003200d3a00c6092003200f3b01c409200320153a00c3092003201c3a00c209200320103b01c009200320043a00bf09200320053a00be09200320113b01bc09200320093a00bb09200320163a00ba092003200b3b01b809024020140d0041c0d7ca00211b410d210741032108410021020c150b41032108024020070d00418df2c200211b41112107410321020c150b0240200741e3004d0d0041fbf1c200211b41122107410421020c150b200320073602702003200636026c20032013360268200341e0066a41186a200341b8096a41186a290300370300200341e0066a41106a2202200341b8096a41106a290300370300200341e0066a41086a2201200341b8096a41086a290300370300200320032903b8093703e00620034198036a200341e8006a200341e0066a10ad0302402003280298034101460d0020034198036a41086a2802002112200328029c032113200120034198036a410c6a280200360200200320143b01ec06200320133602e406200341fda9c3003602e006200341c0066a200341e0066a10ae03200341083a0080072003410b3a0080072003410c3a008007200320032f01c0063b01e006200320032801c2063601e206200320032d00c6063a00e606200320032800c7063600e706200320032d00cb063a00eb062003410d3a008007200320032d00cc063a00ec062003410e3a008007200320032d00cd063a00ed062003410f3a008007200320032d00ce063a00ee06200320032d00cf063a00ef06200341103a008007200341113a008007200320032d00d0063a00f006200341123a008007200320032d00d1063a00f106200341133a008007200320032d00d2063a00f206200341143a008007200320032d00d3063a00f306200341153a008007200320032d00d4063a00f406200341163a008007200320032d00d5063a00f506200341173a008007200320032d00d6063a00f606200320032d00d7063a00f706200341183a008007200341193a008007200320032d00d8063a00f8062003411a3a008007200320032d00d9063a00f9062003411b3a008007200320032d00da063a00fa062003411c3a008007200320032d00db063a00fb062003411d3a008007200320032d00dc063a00fc062003411e3a008007200320032d00dd063a00fd062003411f3a008007200320032d00de063a00fe06200320032d00df063a00ff06200341203a00800720034190096a41186a220820032903f80637030020034190096a41106a220620032903f00637030020034190096a41086a220720032903e806370300200320032903e0063703900920034188066a41186a200829030037030020034188066a41106a200629030037030020034188066a41086a20072903003703002003200329039009370388062003200e3703d8062003201a3a00d706200320203a00d6062003201f3b01d4062003201e3a00d306200320223a00d206200320233b01d006200320243a00cf06200320253a00ce06200320213b01cc06200320263a00cb06200320273a00ca06200320283b01c806200320293a00c7062003202a3a00c6062003202b3b01c4062003202c3a00c3062003202d3a00c2062003202e3b01c00620034198036a20034188066a200341c0066a10b003200341e0066a200328029803221b20032802a00310d302200341c0066a41086a2001290300370300200341c0066a41106a2002290300370300200720034188076a290300370300200620034190076a290300370300200820034198076a29030037030020034190096a41206a2202200341a0076a290300370300200320032903e0063703c0062003200341e0066a41206a2903003703900920032802fc062106024020032802f8062201450d00200341e8056a41106a200341c0066a41106a290300370300200341e8056a41086a200341c0066a41086a290300370300200341e8006a41086a20034190096a41086a290300370300200341e8006a41106a20034190096a41106a290300370300200341e8006a41186a20034190096a41186a290300370300200341e8006a41206a2002290300370300200320032903c0063703e80520032003290390093703680b0240200328029c03450d00201b10350b0240024020010d004101210141032108201441014b0d01419ef2c200211b41112107410221020c140b200341b4036a200636020020034198036a41206a200329036837030020034198036a41106a200341e8056a41106a29030037030020034198036a41086a200341e8056a41086a290300370300200341c0036a200341e8006a41086a290300370300200341c8036a200341e8006a41106a290300370300200341d0036a200341e8006a41186a290300370300200341d8036a200341e8006a41206a290300370300200320032903e80537039803200320013602b0030240202f4101460d0041c8f1c200211b410b2107410921020c130b41baf1c200211b410e2107410a210220032802a8032030470d12200341ac036a2802002031470d12024020032802b80322172014490d00419ef2c200211b41112107410221020c130b410021020240201741014b0d00024020170e020010000b200341e0066a41186a200341b8096a41186a290300370300200341e0066a41106a200341b8096a41106a290300370300200341e0066a41086a200341b8096a41086a290300370300200320032903b8093703e00641002102200341e0066a21080c100b2017210803402008410176220720026a221b20022001201b4105746a200341b8096a412010a0084101481b2102200820076b220841014b0d000c0f0b0b410121010240202f4101470d0041a7f1c200211b41132107410b21020c130b200341386a2014ad42004280a0e5b9c2910142001084082003200329033822194280c0dfda8ee9067c2218370390092003200341386a41086a2903002018201954ad7c2219370398092003200341b8096a3602c8052003200341b8096a3602c0062003200341c0066a3602e8062003200341c8056a3602e406200320034190096a3602e00620034198036a200341b8096a200341e0066a108c03024002402003280298034101470d00200341a4036a280200210720034198036a41086a280200211b20032d009f03210620032d009e03210220032d009d03210120032d009c0321080c010b41042108024020034198036a41086a2903004201520d0020034198036a41106a290300211d20032802c006210120034198076a20034198036a41186a29030037030020034190076a201d370300200341e0066a41086a41003a0000200341e9066a2001290000370000200341f1066a200141086a290000370000200341f9066a200141106a29000037000020034181076a200141186a290000370000200341033a00e00641b0b4cc004100200341e0066a10d4010b0b200841ff01714104470d1320034198036a41186a420037030020034198036a41106a2206420037030020034198036a41086a22024200370300200342003703980341d1c4c700ad4280808080e0008410012208290000211d200341e0066a41086a2201200841086a2900003703002003201d3703e0062008103520022001290300370300200320032903e0063703980341e7c4c700ad4280808080e0008410012208290000211d2001200841086a2900003703002003201d3703e00620081035200620032903e006221d37030020034190096a41086a200229030037030020034190096a41106a201d37030020034190096a41186a2001290300370300200320032903980337039009200341306a20034190096a412010c0012003280234210220032802302108200341286a41c4c3c700411010c001200328022c21062003280228210720032f01b809211b20032d00ba09211420032d00bb09211720032f01bc09210a20032d00be09210c20032d00bf09210d20032f01c009210f20032d00c209211520032d00c309211c20032f01c409211020032d00c609210420032d00c709210520032f01c809211120032d00ca09210920032d00cb09211620032f01cc09210b20032d00ce09212f20032d00cf09213020032903d009211d412010332201450d03200120032903b809370000200141186a200341b8096a41186a290300370000200141106a200341b8096a41106a290300370000200141086a200341b8096a41086a290300370000200341f4066a2006410020071b3602002003419c076a201d3702002003419b076a20303a00002003419a076a202f3a000020034198076a200b3b010020034197076a20163a000020034196076a20093a000020034194076a20113b010020034193076a20053a000020034192076a20043a000020034190076a20103b01002003418f076a201c3a00002003418e076a20153a00002003418c076a200f3b01002003418b076a200d3a00002003418a076a200c3a000020034188076a200a3b010020034187076a20173a000020034186076a20143a0000200320193703e806200320183703e00620032002410020081b3602f0062003201b3b018407200341fc066a428180808010370200200320013602f8062003200e3703d8062003201a3a00d706200320203a00d6062003201f3b01d4062003201e3a00d306200320223a00d206200320233b01d006200320243a00cf06200320253a00ce06200320213b01cc06200320263a00cb06200320273a00ca06200320283b01c806200320293a00c7062003202a3a00c6062003202b3b01c4062003202c3a00c3062003202d3a00c2062003202e3b01c00620034198036a20034188066a200341c0066a10b0032003280298032101200320032802a003360294092003200136029009200341e0066a20034190096a1099030240200328029c03450d00200110350b024020032802fc0641ffffff3f71450d0020032802f80610350b20034185076a200329038806370000200341ed066a200341b8096a41086a290300370000200341f5066a200341b8096a41106a290300370000200341fd066a200341b8096a41186a2903003700002003418d076a20034188066a41086a29030037000020034195076a20034188066a41106a2903003700002003419d076a20034188066a41186a290300370000200341023a00e406200341013a00e006200320032903b8093700e506200341bd076a200e370000200341bc076a201a3a0000200341bb076a20203a0000200341b9076a201f3b0000200341b8076a201e3a0000200341b7076a20223a0000200341b5076a20233b0000200341b4076a20243a0000200341b3076a20253a0000200341b1076a20213b0000200341b0076a20263a0000200341af076a20273a0000200341ad076a20283b0000200341ac076a20293a0000200341ab076a202a3a0000200341a9076a202b3b0000200341a8076a202c3a0000200341a7076a202d3a0000200341a5076a202e3b000041b0b4cc004100200341e0066a10d4010c0f0b4200210e200328029c03220841ff01714104460d16200841187621062008411076210220084108762101200341a4036a280200210720034198036a41086a280200211b0c150b2001412c6a2802002106200141286a2802002108200141246a280200211b200141346a2802002114200141306a2802002113200141226a2f01002107200341e8056a41186a200141196a290000370300200341e8056a41106a200141116a290000370300200341e8056a41086a200141096a290000370300200320012900013703e8054102210120022d00000d0720022d00014101470d07200241196a2d00002101200241186a2d00002112200241166a2f01002117200241156a2d0000210a200241146a2d0000210c200241126a2f0100210d200241116a2d0000210f200241106a2d000021152002410e6a2f0100211c2002410d6a2d000021102002410c6a2d000021042002410a6a2f01002105200241096a2d00002111200241086a2d00002109200241066a2f01002116200241056a2d0000210b200241046a2d0000211a200241026a2f0100212020032002411a6a2901003703d009200320013a00cf09200320123a00ce09200320173b01cc092003200a3a00cb092003200c3a00ca092003200d3b01c8092003200f3a00c709200320153a00c6092003201c3b01c409200320103a00c309200320043a00c209200320053b01c009200320113a00bf09200320093a00be09200320163b01bc092003200b3a00bb092003201a3a00ba09200320203b01b8090240200741ffff03710d0041c0d7ca002107410d210641032101410021020c090b41032101024020060d00418df2c200210741112106410321020c090b0240200641e3004d0d0041fbf1c200210741122106410421020c090b200320063602702003200836026c2003201b360268200341e0066a41186a200341b8096a41186a290300370300200341e0066a41106a2202200341b8096a41106a290300370300200341e0066a41086a2201200341b8096a41086a290300370300200320032903b8093703e00620034198036a200341e8006a200341e0066a10ad0302402003280298034101460d0020034198036a41086a2802002112200328029c03211b200120034198036a410c6a280200360200200320073b01ec062003201b3602e406200341fda9c3003602e006200341c0066a200341e0066a10ae03200341083a0080072003410b3a0080072003410c3a008007200320032f01c0063b01e006200320032801c2063601e206200320032d00c6063a00e606200320032800c7063600e706200320032d00cb063a00eb062003410d3a008007200320032d00cc063a00ec062003410e3a008007200320032d00cd063a00ed062003410f3a008007200320032d00ce063a00ee06200320032d00cf063a00ef06200341103a008007200341113a008007200320032d00d0063a00f006200341123a008007200320032d00d1063a00f106200341133a008007200320032d00d2063a00f206200341143a008007200320032d00d3063a00f306200341153a008007200320032d00d4063a00f406200341163a008007200320032d00d5063a00f506200341173a008007200320032d00d6063a00f606200320032d00d7063a00f706200341183a008007200341193a008007200320032d00d8063a00f8062003411a3a008007200320032d00d9063a00f9062003411b3a008007200320032d00da063a00fa062003411c3a008007200320032d00db063a00fb062003411d3a008007200320032d00dc063a00fc062003411e3a008007200320032d00dd063a00fd062003411f3a008007200320032d00de063a00fe06200320032d00df063a00ff06200341203a00800720034190096a41186a220820032903f80637030020034190096a41106a220620032903f00637030020034190096a41086a220720032903e806370300200320032903e0063703900920034188066a41186a200829030037030020034188066a41106a200629030037030020034188066a41086a20072903003703002003200329039009370388062003200341e8056a41186a2903003703d8062003200341e8056a41106a2903003703d0062003200341e8056a41086a2903003703c806200320032903e8053703c006200341900a6a20034188066a200341c0066a10b003200341e0066a20032802900a221720032802980a10d302200341c0066a41086a2001290300370300200341c0066a41106a2002290300370300200720034188076a290300370300200620034190076a290300370300200820034198076a29030037030020034190096a41206a2202200341a0076a290300370300200320032903e0063703c0062003200341e0066a41206a2903003703900902400240024020032802f8062201450d0020032802fc062108200341f8096a41106a2206200341c0066a41106a290300370300200341f8096a41086a2207200341c0066a41086a290300370300200341e8006a41086a220a20034190096a41086a290300370300200341e8006a41106a220c20034190096a41106a290300370300200341e8006a41186a220d20034190096a41186a290300370300200341e8006a41206a2002290300370300200320032903c0063703f8092003200329039009370368024020032802940a450d00201710350b200341c8056a41166a2006290300220e370100410e2106200341c8056a410e6a2007290300370100200341d8096a41166a2202200e370100200341d8096a41106a200341c8056a41106a290100370300200320032903f8093701ce05200341d8096a41086a200341c8056a41086a290100370300200320032901c8053703d80920034198036a41106a2217200229010037030020034198036a41086a200341d8096a410e6a290100370300200320032901de0937039803200341b4036a2008360200200320013602b003200341d8036a200341e8006a41206a290300370300200341d0036a200d290300370300200341c8036a200c290300370300200341c0036a200a29030037030020034198036a41206a200329036837030041baf1c2002107410a2102024020172802002013470d00200341ac036a2802002014470d00200341bc036a2202200341b8096a412010a008450d0341fbb5c300210741082102410821060b200841ffffff3f71450d01200110350c010b024020032802940a450d00201710350b41d0b9c300210741082106410721020b0240201241ffffff3f71450d00201b10350b41002108418002211b410321010c0b0b200329039803210e200320034198036a41086a2903002218370398092003200e370390090240200e201884500d00200320023602c006200341e8006a200220034190096a200341c0066a10f00220032903684201520d002003290370210e20034198076a200341e8006a41106a29030037030020034190076a200e370300200341e0066a41086a41003a0000200341e9066a2002290000370000200341f1066a200241086a290000370000200341f9066a200241106a29000037000020034181076a200241186a290000370000200341033a00e00641b0b4cc004100200341e0066a10d4010b200341c0066a41186a200341e8056a41186a2201290300370300200341c0066a41106a200341e8056a41106a2202290300370300200341c0066a41086a200341e8056a41086a290300370300200320032903e8053703c006200341e0066a20034188066a200341c0066a10b00320033502e80642208620032802e0062208ad841007024020032802e406450d00200810350b20034185076a200329038806370000200341ed066a200341b8096a41086a290300370000200341f5066a200341b8096a41106a290300370000200341fd066a200341b8096a41186a2903003700002003418d076a20034188066a41086a29030037000020034195076a20034188066a41106a2903003700002003419d076a20034188066a41186a290300370000200341053a00e406200341013a00e006200320032903b8093700e506200341c8076a2013360200200341cc076a2014360200200341bd076a2001290300370000200341b5076a2002290300370000200341ad076a200341e8056a41086a290300370000200341a5076a20032903e80537000041b0b4cc004100200341e0066a10d401024020032802b40341ffffff3f71450d0020032802b00310350b0240201241ffffff3f71450d00201b10350b4200210e0c0b0b4200210e200328029c03220141ff01714104460d0a2001418080807871210820014110762102200141807e71211b200341a4036a280200210620034198036a41086a28020021070c090b1045000b103c000b200810ba0220081035410021010c1e0b200341e8066a410d360200200341c0d7ca003602e406200341003a00e20620034183023b01e006200341e0066a2101410321060c120b200341e8066a41113602002003418df2c2003602e40641032106200341033a00e20620034183023b01e006200341e0066a21010c110b200341e8066a4112360200200341fbf1c2003602e406200341043a00e20620034183023b01e006200341e0066a2101410321060c100b2003200329009d033703582003200341a4036a28000036005f20032d009c032106200810ba0220081035420021180c100b0b0240200841ffffff3f71450d00201b10350b41002108418002211b0b200041206a20063602002000411c6a2007360200200041186a2008200241ff017141107472201b4180fe037172200141ff0171723602004201210e0b2000200e370300200042003703080c1a0b0240200120024105746a200341b8096a412010a00822070d0041aff2c200211b410f2107410121020c040b200341e0066a41186a200341b8096a41186a290300370300200341e0066a41106a200341b8096a41106a290300370300200341e0066a41086a200341b8096a41086a290300370300200320032903b8093703e006200341e0066a210820172007411f7620026a2202490d020b024020172006470d0020034198036a41186a20064101108a0120032802b00321010b200120024105746a220141206a2001201720026b410574109e081a200141186a200841186a290000370000200141106a200841106a290000370000200141086a200841086a290000370000200120082900003700002003201741016a3602b803200341e0066a20034198036a41c800109d081a2003200e3703d8062003201a3a00d706200320203a00d6062003201f3b01d4062003201e3a00d306200320223a00d206200320233b01d006200320243a00cf06200320253a00ce06200320213b01cc06200320263a00cb06200320273a00ca06200320283b01c806200320293a00c7062003202a3a00c6062003202b3b01c4062003202c3a00c3062003202d3a00c2062003202e3b01c00620034190096a20034188066a200341c0066a10b003200328029009210120032003280298093602c406200320013602c006200341e0066a200341c0066a1099030240200328029409450d00200110350b0240200341fc066a28020041ffffff3f71450d0020032802f80610350b20034185076a200329038806370000200341ed066a200341b8096a41086a290300370000200341f5066a200341b8096a41106a290300370000200341fd066a200341b8096a41186a2903003700002003418d076a20034188066a41086a29030037000020034195076a20034188066a41106a2903003700002003419d076a20034188066a41186a290300370000200341033a00e406200341013a00e006200320032903b8093700e506200341cc076a2031360200200341c8076a2030360200200341bd076a200e370000200341bc076a201a3a0000200341bb076a20203a0000200341b9076a201f3b0000200341b8076a201e3a0000200341b7076a20223a0000200341b5076a20233b0000200341b4076a20243a0000200341b3076a20253a0000200341b1076a20213b0000200341b0076a20263a0000200341af076a20273a0000200341ad076a20283b0000200341ac076a20293a0000200341ab076a202a3a0000200341a9076a202b3b0000200341a8076a202c3a0000200341a7076a202d3a0000200341a5076a202e3b000041b0b4cc004100200341e0066a10d4010b0240201241ffffff3f71450d00201310350b4200210e0c070b20022017104d000b0240200641ffffff3f71450d00200110350b41032108410121010b0b201241ffffff3f71450d02201310350c020b0b410121010240200641ffffff3f710d000c010b201310350b200041206a20073602002000411c6a201b360200200041186a2006411874200241ff017141107472200141ff017141087472200841ff0171723602004201210e0b2000200e370300200042003703080c0f0b200320012900013703582003200141086a28000036005f200810ba022008103542002118200741ffffff3f71450d00201b10350b0c080b410021074100211b0c060b200341e0066a200841b002109d081a200341f2006a200341e8056a41086a290300370100200341fa006a200341f8056a29030037010020034182016a20034180066a29030037010020034180023b0168200320032903e80537016a20034190096a200341e0066a200341e8006a10ac032003290398032118200320034198036a41086a29030022193703c009200320183703b80902402018201984500d002003200341bc036a22013602c006200341e8006a2001200341b8096a200341c0066a10f00220032903684201520d002003290370211820034198076a200341e8006a41106a29030037030020034190076a2018370300200341e0066a41086a41003a0000200341e9066a2001290000370000200341f1066a200141086a290000370000200341f9066a200141106a29000037000020034181076a200141186a290000370000200341033a00e00641b0b4cc004100200341e0066a10d4010b2003200e3703d8062003200a3a00d7062003200c3a00d6062003200d3b01d4062003200f3a00d306200320153a00d2062003201c3b01d006200320103a00cf06200320043a00ce06200320053b01cc06200320113a00cb06200320093a00ca06200320163b01c8062003200b3a00c7062003201a3a00c606200320223b01c406200320233a00c306200320243a00c206200320253b01c006200341e0066a200341e8056a200341c0066a10b00320033502e80642208620032802e0062201ad841007024020032802e406450d00200110350b200341e8006a41186a200341c8056a41186a290300370300200341e8006a41106a200341c8056a41106a290300370300200341e8006a41086a200341c8056a41086a290300370300200320032903c805370368200341e0066a41186a200341e8056a41186a290300370300200341e0066a41106a200341e8056a41106a290300370300200341e0066a41086a200341e8056a41086a290300370300200320032903e8053703e00620034190096a41186a2d0000210620032903980921192003290390092118200320032900a9093703b8092003200341b0096a2800003600bf090240024020184201510d00410421010c010b200320032800bf093600ff09200320032903b8093703f8094104210120194202510d00200320032800ff093600970a200320032903f8093703900a200621010b200341b8096a41086a2206200341e8006a41086a290300370300200341b8096a41106a2207200341e8006a41106a290300370300200341b8096a41186a221b200341e8006a41186a290300370300200341c0066a41086a2213200341e0066a41086a290300370300200341c0066a41106a2214200341e0066a41106a290300370300200341c0066a41186a2220200341e0066a41186a290300370300200320032903683703b809200320032903e0063703c006200320032800970a3600b706200320032903900a3703b006200341ed066a2006290300370000200341f5066a2007290300370000200341fd066a201b29030037000020034185076a20032903c0063700002003418d076a201329030037000020034195076a20142903003700002003419d076a2020290300370000200341043a00e406200341013a00e006200320032903b8093700e506200341bd076a200e370000200341bc076a200a3a0000200341bb076a200c3a0000200341b9076a200d3b0000200341b8076a200f3a0000200341b7076a20153a0000200341b5076a201c3b0000200341b4076a20103a0000200341b3076a20043a0000200341b1076a20053b0000200341b0076a20113a0000200341af076a20093a0000200341ad076a20163b0000200341ac076a200b3a0000200341ab076a201a3a0000200341a9076a20223b0000200341a8076a20233a0000200341a7076a20243a0000200341a5076a20253b0000200341d0076a20013a0000200341cc076a201e360200200341c8076a201f360200200341c7076a200341c6056a2d00003a0000200341c5076a20032f00c4053b0000200341d8076a20032800b706360000200341d1076a20032903b0063700004100210741b0b4cc004100200341e0066a10d4014200211920032802b40321010c020b200341e0066a41186a200341c8056a41186a290300370300200341e0066a41106a200341c8056a41106a290300370300200341e0066a41086a200341c8056a41086a290300370300200320032903c8053703e006024020202007490d0020022106024020202012470d0020034198036a41186a20124101108a0120032802b00321060b200620074105746a220641206a2006202020076b410574109e081a200641186a200341e0066a41186a290300370000200641106a200341e0066a41106a290300370000200641086a200341e0066a41086a290300370000200620032903e0063700002003202041016a3602b803200341e0066a20034198036a41c800109d081a2003200e3703d8062003200a3a00d7062003200c3a00d6062003200d3b01d4062003200f3a00d306200320153a00d2062003201c3b01d006200320103a00cf06200320043a00ce06200320053b01cc06200320113a00cb06200320093a00ca06200320163b01c8062003200b3a00c7062003201a3a00c606200320223b01c406200320233a00c306200320243a00c206200320253b01c006200341e8006a200341e8056a200341c0066a10b0032003280268210620032003280270360294092003200636029009200341e0066a20034190096a1099030240200328026c450d00200610350b0240200341fc066a28020041ffffff3f71450d0020032802f80610350b20034185076a20032903e805370000200341ed066a200341c8056a41086a290300370000200341f5066a200341c8056a41106a290300370000200341fd066a200341c8056a41186a2903003700002003418d076a200341e8056a41086a29030037000020034195076a200341e8056a41106a2903003700002003419d076a200341e8056a41186a290300370000200341033a00e40641012107200341013a00e006200320032903c8053700e506200341cc076a201e360200200341c8076a201f360200200341bd076a200e370000200341bc076a200a3a0000200341bb076a200c3a0000200341b9076a200d3b0000200341b8076a200f3a0000200341b7076a20153a0000200341b5076a201c3b0000200341b4076a20103a0000200341b3076a20043a0000200341b1076a20053b0000200341b0076a20113a0000200341af076a20093a0000200341ad076a20163b0000200341ac076a200b3a0000200341ab076a201a3a0000200341a9076a20223b0000200341a8076a20233a0000200341a7076a20243a0000200341a5076a20253b000041b0b4cc004100200341e0066a10d4012001ad4290a10f7e42c0c09bd8007c210e42002119420121180c030b20072020104d000b42012119201221010b420021180240200141ffffff3f710d000c010b20032802b00310350b4101211b410321060b0b0240202141ffffff3f71450d00201710350b0240201241ffffff3f71450d00200245201b720d00200210350b02402007450d00200810ba020b20081035201950450d0020002018370308200041106a200e370300200042003703000c050b2003200328005f36004f20032003290358370348200041186a20063a0000200041106a200e3703002000201837030820002003290348370019200041206a200328004f360000200041246a2001360200200042013703000c040b2000411c6a2018370200200041186a2001200641ff0171723602004201210e0b2000200e370300200042003703080c020b024020082001460d000340200110bb022008200141b0026a2201470d000b0b02402009450d00200941b0026c450d00200510350b200341013a00e406200341013a00e00641b0b4cc004100200341e0066a10d4010b20004200370300200041086a42003703000b200341a00a6a24000bebca010a017f017e017f017e017f017e057f017e287f0c7e230041f0116b220324000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802000e1b010200030405060708090a0b0c0d0e0f1011121300000014151617010b000b20034198066a41086a200141106a2903003703002003200141086a29030037039806200341a80b6a41206a200241206a290200370300200341a80b6a41186a200241186a290200370300200341a80b6a41106a200241106a290200370300200341a80b6a41086a200241086a290200370300200320022902003703a80b200020034198066a200341a80b6a1085060c280b200341e00b6a2001413c6a280200360200200341d80b6a200141346a290200370300200341d00b6a2001412c6a290200370300200341a80b6a41206a200141246a290200370300200341a80b6a41186a2001411c6a290200370300200341a80b6a41106a200141146a290200370300200341a80b6a41086a2001410c6a290200370300200320012902043703a80b20034198066a41206a200241206a29020037030020034198066a41186a200241186a29020037030020034198066a41106a200241106a29020037030020034198066a41086a200241086a29020037030020032002290200370398062000200341a80b6a20034198066a10ab030c270b0240024020022d00000d0020022d000141ff01714102470d00200141086a2903002104200341a80b6a41186a22054200370300200341a80b6a41106a22014200370300200341a80b6a41086a22024200370300200342003703a80b41d1efcb00ad42808080809001842206100122072900002108200341a0116a41086a2209200741086a290000370300200320083703a0112007103520022009290300370300200320032903a0113703a80b41daefcb00ad42808080809001841001220a2900002108200341f8106a41086a2207200a41086a290000370300200320083703f810200a1035200120032903f810220837030020034198066a41086a220b200229030037030020034198066a41106a220c200837030020034198066a41186a220d2007290300370300200320032903a80b37039806200341186a20034198066a412041b0b4cc0041004100108a0220032802184101460d16200542003703002001420037030020024200370300200342003703a80b20061001220a29000021062009200a41086a290000370300200320063703a011200a103520022009290300370300200320032903a0113703a80b41ebc3c400ad4280808080308422061001220929000021082007200941086a290000370300200320083703f81020091035200120032903f810370000200141086a2007290300370000200b2002290300370300200c2001290300370300200d2005290300370300200320032903a80b37039806200341086a20034198066a10e1022003290310220842dc0b7c2004580d012008500d012003280208450d0141beebc40041ce0041c086cc00103f000b20004200370308200041186a4102360200200042013703000c270b200341a80b6a41186a22094200370300200341a80b6a41106a22074200370300200341a80b6a41086a22024200370300200342003703a80b41d1efcb00ad428080808090018422081001220a290000210e200341a0116a41086a2205200a41086a2900003703002003200e3703a011200a103520022005290300370300200320032903a0113703a80b20061001220b2900002106200341f8106a41086a220a200b41086a290000370300200320063703f810200b1035200120032903f810370000200141086a220c200a29030037000020034198066a41086a220d200229030037030020034198066a41106a220f200729030037030020034198066a41186a22102009290300370300200320032903a80b37039806200320043703a80b20034198066aad42808080808004842204200341a80b6aad42808080808001841002200942003703002007420037030020024200370300200342003703a80b20081001220b29000021062005200b41086a290000370300200320063703a011200b103520022005290300370300200320032903a0113703a80b41daefcb00ad4280808080900184100122052900002106200a200541086a290000370300200320063703f81020051035200120032903f810370000200c200a290300370000200d2002290300370300200f200729030037030020102009290300370300200320032903a80b37039806200341013a00d00f2004200341d00f6aad42808080801084100220004200370308200042003703000c260b200341b00b6a2001410c6a280200360200200320012902043703a80b2000200341a80b6a20022d000020022d00011086060c250b20034198066a41206a200141246a29020037030020034198066a41186a2001411c6a29020037030020034198066a41106a200141146a29020037030020034198066a41086a2001410c6a2902003703002003200129020437039806200341a80b6a41206a200241206a290200370300200341a80b6a41186a200241186a290200370300200341a80b6a41106a200241106a290200370300200341a80b6a41086a200241086a290200370300200320022902003703a80b200020034198066a200341a80b6a10b1040c240b200341a80b6a200141086a41e000109d081a20034198066a41206a200241206a29020037030020034198066a41186a200241186a29020037030020034198066a41106a200241106a29020037030020034198066a41086a200241086a29020037030020032002290200370398062000200341a80b6a20034198066a1087030c230b200341a80b6a200141086a418802109d081a20034198066a41206a200241206a29020037030020034198066a41186a200241186a29020037030020034198066a41106a200241106a29020037030020034198066a41086a200241086a29020037030020032002290200370398062000200341a80b6a20034198066a1089020c220b200341a80b6a200141046a418c01109d081a20034198066a41206a200241206a29020037030020034198066a41186a200241186a29020037030020034198066a41106a200241106a29020037030020034198066a41086a200241086a29020037030020032002290200370398062000200341a80b6a20034198066a1087060c210b200341a80b6a41306a200141386a290300370300200341a80b6a41286a200141306a290300370300200341a80b6a41206a200141286a290300370300200341a80b6a41186a200141206a290300370300200341a80b6a41106a200141186a290300370300200341a80b6a41086a200141106a2903003703002003200141086a2903003703a80b20034198066a41206a200241206a29020037030020034198066a41186a200241186a29020037030020034198066a41106a200241106a29020037030020034198066a41086a200241086a29020037030020032002290200370398062000200341a80b6a20034198066a108b050c200b200341d00b6a2001412c6a290200370300200341a80b6a41206a200141246a290200370300200341a80b6a41186a2001411c6a290200370300200341a80b6a41106a200141146a290200370300200341a80b6a41086a2001410c6a290200370300200320012902043703a80b20034198066a41206a200241206a29020037030020034198066a41186a200241186a29020037030020034198066a41106a200241106a29020037030020034198066a41086a200241086a29020037030020032002290200370398062000200341a80b6a20034198066a1088060c1f0b200341d00b6a2001412c6a290200370300200341a80b6a41206a200141246a290200370300200341a80b6a41186a2001411c6a290200370300200341a80b6a41106a200141146a290200370300200341a80b6a41086a2001410c6a290200370300200320012902043703a80b20034198066a41206a200241206a29020037030020034198066a41186a200241186a29020037030020034198066a41106a200241106a29020037030020034198066a41086a200241086a29020037030020032002290200370398062000200341a80b6a20034198066a1089060c1e0b20034198066a41206a200141286a29030037030020034198066a41186a200141206a29030037030020034198066a41106a200141186a29030037030020034198066a41086a200141106a2903003703002003200141086a29030037039806200341a80b6a41206a200241206a290200370300200341a80b6a41186a200241186a290200370300200341a80b6a41106a200241106a290200370300200341a80b6a41086a200241086a290200370300200320022902003703a80b200020034198066a200341a80b6a1089030c1d0b200341a80b6a200141046a41c400109d081a20034198066a41206a200241206a29020037030020034198066a41186a200241186a29020037030020034198066a41106a200241106a29020037030020034198066a41086a200241086a29020037030020032002290200370398062000200341a80b6a20034198066a108a060c1c0b4102210741002109024002400240024020022d0000450d000c010b20022d000141ff01714102470d0020012802042105200341a80b6a41186a4200370300200341a80b6a41106a22074200370300200341a80b6a41086a22014200370300200342003703a80b41bee4cb00ad4280808080f00184100122092900002104200341c00a6a41086a2202200941086a290000370300200320043703c00a2009103520012002290300370300200320032903c00a3703a80b418cc0c700ad4280808080e000841001220929000021042002200941086a290000370300200320043703c00a20091035200720032903c00a2204370300200341d00f6a41086a2001290300370300200341d00f6a41106a2004370300200341d00f6a41186a2002290300370300200320032903a80b3703d00f41002109200341286a200341d00f6a412041b0b4cc0041004100108a020240024020032802284101470d00410e210541d0b8c700210a0c010b200341d8106a41186a4200370300200341d8106a41106a220a4200370300200341d8106a41086a22024200370300200342003703d81041d1c4c700ad4280808080e000841001220929000021042002200941086a290000370300200320043703d8102009103541e7c4c700ad4280808080e000841001220929000021042001200941086a290000370300200320043703a80b20091035200a20032903a80b2204370300200341b8106a41086a2002290300370300200341b8106a41106a2004370300200341b8106a41186a2001290300370300200320032903d8103703b810200341206a200341b8106a412010c0012003280224410020032802201b20054f0d024107210541e8b8c700210a4180800421090b410321070b200041206a20053602002000411c6a200a360200200041186a2009418080047120077241801e72360200420121040c010b42002104200341a80b6a41186a220a4200370300200341a80b6a41106a220b4200370300200341a80b6a41086a22024200370300200342003703a80b41bee4cb00ad4280808080f00184100122092900002106200341c00a6a41086a2201200941086a290000370300200320063703c00a2009103520022001290300370300200320032903c00a3703a80b418cc0c700ad4280808080e000841001220929000021062001200941086a290000370300200320063703c00a20091035200720032903c00a370000200741086a2001290300370000200341d00f6a41086a2002290300370300200341d00f6a41106a200b290300370300200341d00f6a41186a200a290300370300200320032903a80b3703d00f200320053602a80b200341d00f6aad4280808080800484200341a80b6aad4280808080c0008410020b20002004370300200042003703080c1b0b200141086a280200210920012802042101024020022d00000d0020022d000141ff01714101470d0002402009450d00200110350b20004200370308200042003703000c1b0b02402009450d00200110350b20004200370308200041186a4102360200200042013703000c1a0b200341a80b6a41386a200141c0006a290300370300200341a80b6a41306a200141386a290300370300200341a80b6a41286a200141306a290300370300200341a80b6a41206a200141286a290300370300200341a80b6a41186a200141206a290300370300200341a80b6a41106a200141186a290300370300200341a80b6a41086a200141106a2903003703002003200141086a2903003703a80b20034198066a41206a200241206a29020037030020034198066a41186a200241186a29020037030020034198066a41106a200241106a29020037030020034198066a41086a200241086a29020037030020032002290200370398062000200341a80b6a20034198066a108b060c190b20014180016a2802002111200141d0006a2903002106200141346a2d00002112200141306a2d0000210f2001412c6a2d00002113200141086a2d0000210920012f0036211420012d0035211520012f0032211020012d0031211620012f002e211720012d002d211820012f002a211920012d0029211a20034194026a41026a221b2001410b6a2d00003a000020034180026a41086a2205200141206a29000037030020034180026a41106a220a200141286a2d00003a0000200341e8016a41086a221c200141c0006a290300370300200341e8016a41106a221d200141c8006a290300370300200320012f00093b0194022003200141186a290000370380022003200141386a2903003703e8012001410c6a2800002107200141106a280000210b200141146a280000210c200341c0016a41206a221e200141f8006a290300370300200341c0016a41186a221f200141f0006a290300370300200341c0016a41106a2220200141e8006a290300370300200341c0016a41086a2221200141e0006a290300370300200341a0016a41186a22222001419c016a280200360200200341a0016a41106a222320014194016a290200370300200341a0016a41086a22242001418c016a2902003703002003200141d8006a2903003703c001200320014184016a2902003703a0012002411a6a2901002104200241196a2d00002125200241186a2d00002126200241166a2f01002127200241156a2d00002128200241146a2d00002129200241126a2f0100212a200241116a2d0000212b200241106a2d0000212c2002410e6a2f0100212d2002410d6a2d0000212e2002410c6a2d0000212f2002410a6a2f01002130200241096a2d00002131200241086a2d00002132200241066a2f01002133200241056a2d00002134200241046a2d00002135200241026a2f0100213620022d0001210d20022d0000210102400240024002400240024020090e06000102030405000b200341a80b6a41146a4101360200200342013702ac0b200341e8d4ca003602a80b2003410436029c062003419cd5ca0036029806200320034198066a3602b80b200341a80b6a41b0b4cc00104c000b200341c8046a41086a2005290300370300200341c8046a41106a200a2d00003a000020034188036a41086a201c29030037030020034188036a41106a201d29030037030020034198066a41086a202129030037030020034198066a41106a202029030037030020034198066a41186a201f29030037030020034198066a41206a201e29030037030020032003290380023703c804200320032903e80137038803200320032903c00137039806200341800e6a41186a2022280200360200200341800e6a41106a2023290300370300200341800e6a41086a2024290300370300200320032903a0013703800e024002400240200d200141ff01714100477241ff01710d00200341f0086a41186a22054200370300200341f0086a41106a22094200370300200341f0086a41086a22024200370300200342003703f00841f1d8cb00ad42808080809001842208100122072900002104200341c00a6a41086a2201200741086a290000370300200320043703c00a2007103520022001290300370300200320032903c00a3703f00841e2d8cb00ad4280808080f00184220e1001220729000021042001200741086a290000370300200320043703c00a20071035200920032903c00a2204370300200341b8026a41086a22072002290300370300200341b8026a41106a220a2004370300200341b8026a41186a220d2001290300370300200320032903f0083703b802200341a80b6a200341b8026a10da020240410020032802980c20032d00b00c4102461b2011490d0041832421010c020b200341b40b6a2011360200200341a80b6a41086a41053a00002003410d3a00a80b41b0b4cc004100200341a80b6a10d401200341a80b6a41106a200341c8046a41086a290300370300200341a80b6a41186a200341c8046a41106a2d00003a00002003200c3602ac0b2003200b3602a80b200320032903c8043703b00b200320143b01ce0b200320153a00cd0b200320123a00cc0b200320103b01ca0b200320163a00c90b2003200f3a00c80b200320173b01c60b200320183a00c50b200320133a00c40b200320193b01c20b2003201a3a00c10b200341e00b6a20034188036a41106a290300370300200341d80b6a20034188036a41086a290300370300200341f80b6a20034198066a41086a290300370300200341800c6a20034198066a41106a290300370300200341880c6a20034198066a41186a290300370300200341900c6a200341b8066a290300370300200320063703e80b200320113602980c20032003290388033703d00b20032003290398063703f00b200341b40c6a200341800e6a41186a280200360200200341ac0c6a200341800e6a41106a290300370200200341a40c6a200341800e6a41086a290300370200200320032903800e37029c0c200542003703002009420037030020024200370300200342003703f00820081001220b29000021042001200b41086a290000370300200320043703c00a200b103520022001290300370300200320032903c00a3703f008200e1001220b29000021042001200b41086a290000370300200320043703c00a200b1035200920032903c00a370000200941086a200129030037000020072002290300370300200a2009290300370300200d2005290300370300200320032903f0083703b802200341003602f808200342013703f008200341a80b6a200341f0086a10f30520032802f4082101200341b8026aad428080808080048420033502f80842208620032802f0082202ad84100202402001450d00200210350b420021040c020b41822421010b200041206a41163602002000411c6a41bcffc600360200200041186a2001360200420121040b20004200370308200020043703000c1c0b024002400240200141ff01710d00200d41ff01714101470d00200341f0086a41186a420037030041102105200341f0086a41106a220a4200370300200341f0086a41086a22024200370300200342003703f00841f1d8cb00ad4280808080900184100122092900002104200341c00a6a41086a2201200941086a290000370300200320043703c00a2009103520022001290300370300200320032903c00a3703f00841e2d8cb00ad4280808080f001841001220929000021042001200941086a290000370300200320043703c00a20091035200a20032903c00a2204370300200341b8026a41086a2002290300370300200341b8026a41106a2004370300200341b8026a41186a2001290300370300200320032903f0083703b802200341a80b6a200341b8026a10da0220032903a80b210420032903b00b210620032903b80b210820032903c00b210e20032903c80b213720032903d00b213820032903d80b213920032903e00b213a20032903e80b213b20032903f00b213c20032903f80b213d20032903800c213e20032903880c213f20032903900c214020032802980c210f200328029c0c210220032802a00c210920032802a40c211020032802a80c210a20032802ac0c210d20032d00b00c21012003200341a80b6a418c016a2800003600f308200320032800b10c3602f0080240024020014102470d0020034280c2d72f3703800720034280e1eb173703f806200342a0c21e3703f006200342a0c21e3703e806200342e0ef97203703e006200342e0c9dc293703d806200342e0ef97203703d006200342a0c21e3703c806200342a0c21e3703c006200342a0c21e3703b806200342a0c21e3703b006200342a0c21e3703a806200342a0c21e3703a006200342a0c21e370398064100210120034100360288074120210d41808001210a418080042109410421020c010b20034198066a418c016a20032800f3083600002003200f3602880720032040370380072003203f3703f8062003203e3703f0062003203d3703e8062003203c3703e0062003203b3703d8062003203a3703d006200320393703c806200320383703c006200320373703b8062003200e3703b006200320083703a806200320063703a0062003200437039806200320032802f0083600a107201021050b200320013a00a0072003200d36029c072003200a36029807200320053602940720032009360290072003200236028c07200341a80b6a2007200c20034198066a108c06024020032802a80b4101460d00200341800e6a41186a2202200341a80b6a410472220141186a280200360200200341800e6a41106a2209200141106a290200370300200341800e6a41086a220d200141086a290200370300200320012902003703800e200341c00a6a41026a220f200cad4220862007ad841009220141026a2d00003a0000200128000321052001280007210a20012f00002110200341c8046a410d6a2216200141186a290000370000200341c8046a41086a221b200141136a290000370300200320103b01c00a2003200129000b3703c80420011035200341a80b6a41186a2002280200360200200341a80b6a41106a2009290300370300200341a80b6a41086a200d290300370300200320032903800e3703a80b200341d00f6a41026a2202200f2d00003a000020034188036a41086a2209201b29030037030020034188036a410d6a220d2016290000370000200320032f01c00a3b01d00f200320032903c8043703880341f1d8cb00ad4280808080900184100122012900002104200341a0116a41086a200141086a290000370300200320043703a0112001103541a0e0c600ad4280808080b00184100122012900002104200341f8106a41086a200141086a290000370300200320043703f81020011035412010332201450d0e200120032f01d00f3b00002001200a36000720012005360003200120032903880337000b200141026a20022d00003a0000200141136a2009290300370000200141186a200d290000370000412010332202450d0e20022001290000370000200241186a2209200141186a290000370000200241106a220d200141106a290000370000200241086a220f200141086a2900003700002001103541c00010332201450d0e200120032903f810370010200120032903a011370000200141086a200341a0116a41086a290300370000200141186a200341f8106a41086a29030037000020012002290000370020200141286a200f290000370000200141306a200d290000370000200141386a20092900003700002002103520034100360290032003420137038803200341a80b6a20034188036a10e201200341a80b6a41047220034188036a10e201200341a80b6a41086a20034188036a10e201200320032d00c00b220d3a00d00f02400240200328028c032003280290032202460d0020032802880321090c010b200241016a22092002490d112002410174220d2009200d20094b1b220d4100480d110240024020020d00410021020240200d0d00410121090c020b200d103322090d010c230b20032802880321092002200d460d0020092002200d10372209450d220b2003200d36028c03200320093602880320032d00d00f210d0b200920026a200d3a00002003200241016a3602900320032802b40b2116200341bc0b6a280200220220034188036a107702400240200328028c032210200328029003220d6b2002490d0020032802880321092010210f0c010b200d20026a2209200d490d112010410174220f2009200f20094b1b220f4100480d110240024020100d000240200f0d00410121090c020b200f10332209450d230c010b20032802880321092010200f460d0020092010200f10372209450d220b2003200f36028c0320032009360288030b2009200d6a20162002109d081a2001ad4280808080800884200d20026aad4220862009ad8410020240200f450d00200910350b200110350240200341b80b6a280200450d00201610350b20034188036a41026a2202200341c00a6a41026a2d00003a0000200341a80b6a41086a2209200341c8046a41086a290300370300200341a80b6a410d6a220d200341c8046a410d6a290000370000200320032f01c00a3b018803200320032903c8043703a80b41f1d8cb00ad4280808080900184100122012900002104200341a0116a41086a200141086a290000370300200320043703a011200110354194e0c600ad4280808080c00184100122012900002104200341f8106a41086a200141086a290000370300200320043703f81020011035412010332201450d0e200120032f0188033b00002001200a36000720012005360003200120032903a80b37000b200141026a20022d00003a0000200141136a2009290300370000200141186a2209200d290000370000412010332202450d0e20022001290000370000200241186a2009290000370000200241106a2209200141106a290000370000200241086a220d200141086a2900003700002001103541c00010332201450d0e200120032903f810370010200120032903a011370000200141086a200341a0116a41086a290300370000200141186a200341f8106a41086a29030037000020012002290000370020200141286a200d290000370000200141306a2009290000370000200141386a200241186a29000037000020021035200341c0003602ac0b200320013602a80b2007200c200341a80b6a109403200110350240200b450d00200710350b200341d8106a41026a200341c00a6a41026a2d000022013a0000200341f0086a41086a2202200341c8046a41086a290300370300200341f0086a410d6a2209200341c8046a410d6a290000370000200320032f01c00a22073b01d810200320032903c8043703f008200341a80b6a41086a41043a0000200341b10b6a20073b0000200341b30b6a20013a0000200341b80b6a200a360200200341b40b6a20053602002003410d3a00a80b200341bc0b6a20032903f008370200200341c40b6a2002290300370200200341c90b6a200929000037000041b0b4cc004100200341a80b6a10d401420021040c030b200341b00b6a350200210420033502ac0b21060240200b450d00200710350b20044220862006842104410021010c010b410221010240200b450d00200710350b0b2000411c6a2004370200200041186a2001360200420121040b20004200370308200020043703000c1b0b201d290300210820032903f001210e20032802e8012109200341a0116a41106a200a2d00003a0000200341a0116a41086a200529030037030020032003290380023703a0112016410874200f72201041107472210202400240200141ff01710d00200d41ff01714101470d00200320043701e80f200320253a00e70f200320263a00e60f200320273b01e40f200320283a00e30f200320293a00e20f2003202a3b01e00f2003202b3a00df0f2003202c3a00de0f2003202d3b01dc0f2003202e3a00db0f2003202f3a00da0f200320303b01d80f200320313a00d70f200320323a00d60f200320333b01d40f200320343a00d30f200320353a00d20f200320363b01d00f200341a80b6a41086a2201200c360200200341b40b6a20032903a011370200200341bc0b6a200341a0116a41086a290300370200200341c40b6a200341a0116a41106a2d00003a0000200341ca0b6a20173b0100200341c90b6a20183a0000200341c80b6a20133a0000200341c60b6a20193b0100200341c50b6a201a3a00002003200b3602ac0b200320073602a80b20034198066a200341a80b6a108b02200341800e6a41086a2207200341a1066a290000370300200341800e6a41106a2205200341a9066a290000370300200341800e6a41186a220a200341b1066a29000037030020032003290099063703800e20032d0098064101470d01410121072015410874201272201441107472450d190c180b4102210720154108742012722014411074720d170c180b200341b8026a41086a220b2007290300370300200341b8026a41106a22072005290300370300200341b8026a41186a2205200a290300370300200320032903800e3703b8022003200637038011200320063703f810200341c8046a41186a200341d00f6a41186a290100370300200341c8046a41106a200341d00f6a41106a290100370300200341c8046a41086a200341d00f6a41086a290100370300200320032901d00f3703c80420034188036a41186a200529030037030020034188036a41106a200729030037030020034188036a41086a200b290300370300200320032903b802370388032003200341f8106a3602b805200341d8106a41186a4200370300200341d8106a41106a22074200370300200341d8106a41086a22054200370300200342003703d81041f1d8cb00ad42808080809001841001220a29000021042005200a41086a290000370300200320043703d810200a103541e2d8cb00ad4280808080f001841001220a29000021042001200a41086a290000370300200320043703a80b200a1035200720032903a80b2204370300200341b8106a41086a2005290300370300200341b8106a41106a2004370300200341b8106a41186a2001290300370300200320032903d8103703b810200341a80b6a200341b8106a10da0220032903a80b210420032903b00b210620032903b80b213720032903c00b213820032903c80b213920032903d00b213a20032903d80b213b20032903e00b213c20032903e80b213d20032903f00b213e20032903f80b213f20032903800c214020032903880c214120032903900c214220032802980c2110200328029c0c210520032802a00c210a20032802a40c210b20032802a80c210c20032802ac0c210d20032d00b00c21012003200341a80b6a418c016a2800003600f308200320032800b10c3602f0082015410874201272201441107472210f0240024020014102470d0020034280c2d72f3703e80e20034280e1eb173703e00e200342a0c21e3703d80e200342a0c21e3703d00e200342e0ef97203703c80e200342e0c9dc293703c00e200342e0ef97203703b80e200342a0c21e3703b00e200342a0c21e3703a80e200342a0c21e3703a00e200342a0c21e3703980e200342a0c21e3703900e200342a0c21e3703880e200342a0c21e3703800e41002101200341003602f00e4120210d41808001210c4110210b41808004210a410421050c010b200341800e6a418c016a20032800f308360000200320103602f00e200320423703e80e200320413703e00e200320403703d80e2003203f3703d00e2003203e3703c80e2003203d3703c00e2003203c3703b80e2003203b3703b00e2003203a3703a80e200320393703a00e200320383703980e200320373703900e200320063703880e200320043703800e200320032802f0083600890f0b200341a80f6a4200370300200341980f6a4200370300200320013a00880f2003200d3602840f2003200c3602800f2003200b3602fc0e2003200a3602f80e200320053602f40e2003428080e983b1de163703a00f2003428080e983b1de163703900f200342a08080808080103703b00f2003200341800e6a360298022003200341800e6a3602e802200341d8106a41186a220a4200370300200341d8106a41106a220b4200370300200341d8106a41086a22014200370300200342003703d81041d1efcb00ad42808080809001841001220529000021042001200541086a290000370300200320043703d8102005103541ebc3c400ad428080808030841001220c2900002104200341a80b6a41086a2205200c41086a290000370300200320043703a80b200c1035200720032903a80b370000200741086a220d2005290300370000200341b8106a41086a22102001290300370300200341b8106a41106a2216200b290300370300200341b8106a41186a221b200a290300370300200320032903d8103703b810200341386a200341b8106a10e102200329034021042003280238211c200a4200370300200b420037030020014200370300200342003703d81041d1c4c700ad4280808080e000841001220c29000021062001200c41086a290000370300200320063703d810200c103541e7c4c700ad4280808080e000841001220c29000021062005200c41086a290000370300200320063703a80b200c1035200720032903a80b370000200d2005290300370000201020012903003703002016200b290300370300201b200a290300370300200320032903d8103703b810200341306a200341b8106a412010c001200341a8096a42003703002003419c096a419494ca0036020020034198096a41b0b4cc0036020020034194096a4100360200200341c8096a200341c8046a41086a290300370300200341d0096a200341c8046a41106a290300370300200341d8096a200341c8046a41186a2903003703002003428080808080013703a0092003420037038809200342003703f808200320032903c8043703c00920032802302101200328023421072003200341e8026a3602b809200320034198026a3602b4092003200341800e6a3602b00920032007410020011b3602bc09200320044200201c1b3703f008200341a80b6a41186a20034188036a41186a290300370300200341a80b6a41106a20034188036a41106a290300370300200520034188036a41086a29030037030020032003290388033703a80b200320093602a0062003200f36029c062003200236029806200341c00a6a200341f0086a200341a80b6a200e2008200341f8106a20034198066a10ef034101210b024020032802c00a220c0d00200341c00a6a41106a2d00000d00200341a80b6a41086a20034190096a29030037030020034198066a41086a200341b40b6a28020036020020032003290388093703a80b200320032902ac0b37039806200341e8116a20034198066a10f0034100210b0b20032802a409220520032802ac09220141d8026c6a210920032802a809210a2003200341b8056a3602d81020052102024002402001450d00200341a80b6a4101722107200521010240034020012d0000210220034198066a200141016a41d702109d081a20024103460d01200320023a00a80b200720034198066a41d702109d081a200341d8106a200341a80b6a108d06200141d8026a22012009470d000c030b0b200141d8026a21020b20092002460d0003402002220141d8026a21020240024020012d0000220741014b0d000240024020070e020001000b0240200141086a28020041ffffff3f71450d00200141046a28020010350b200141106a2d00004107470d02200141386a280200450d02200141346a28020010350c020b200141286a10bb020c010b200141e8006a28020041ffffff3f71450d00200141e4006a28020010350b20092002470d000b0b0240200a450d00200a41d8026c450d00200510350b200341d40a6a290200210e200341c00a6a41106a280200210a200341c80a6a290300210820032802c40a2107024020032802fc082201450d00200341f0086a41106a280200450d00200110350b0240200b450d0002400240200328028c0922050d004100210b200341bc0b6a4100360200200341003602ac0b0c010b200328029409210b0240024020034190096a28020022020d00200521010c010b2002210120052109034020092802880b21092001417f6a22010d000b200521010340200120012f01064102746a41880b6a28020021012002417f6a22020d000b200921050b200341c40b6a20012f0106360200200341c00b6a4100360200200341bc0b6a2001360200200341003602b80b200342003703b00b200320053602ac0b200341003602a80b0b2003200b3602c80b200341a80b6a108f030b200329038011210420032903f810210602400240200c450d000240200ea7450d00200a10350b200620047d210e410121010c010b200620047d210e410021012008a7450d00200710350b42002104420121062001450d190c180b201c290300210820032903e801210e20032903f8012106200341af026a2005290300370000200341b7026a200a2d00003a00002003201b2d00003a009a02200320032f0194023b0198022003200c3600a3022003200b36009f022003200736009b0220032003290380023700a7022018410874201372201741107472210a02400240200141ff01710d00200d41ff01714101470d00200320313a00bf02200320323a00be02200320333b01bc02200320343a00bb02200320353a00ba02200320363b01b8022003202b3a00c7022003202c3a00c6022003202d3b01c4022003202e3a00c3022003202f3a00c202200320303b01c002200320253a00cf02200320263a00ce02200320273b01cc02200320283a00cb02200320293a00ca022003202a3b01c802200320043701d002200320063703e002200320063703d802200341e8026a41186a200437030041102107200341e8026a41106a20032901c802370300200341e8026a41086a20032901c002370300200320032901b8023703e802200341d8106a41186a4200370300200341d8106a41106a22024200370300200341d8106a41086a22014200370300200342003703d81041f1d8cb00ad42808080809001841001220929000021042001200941086a290000370300200320043703d8102009103541e2d8cb00ad4280808080f00184100122092900002104200341a80b6a41086a2205200941086a290000370300200320043703a80b20091035200220032903a80b2204370300200341b8106a41086a2001290300370300200341b8106a41106a2004370300200341b8106a41186a2005290300370300200320032903d8103703b810200341a80b6a200341b8106a10da0220032903a80b210420032903b00b210620032903b80b213720032903c00b213820032903c80b213920032903d00b213a20032903d80b213b20032903e00b213c20032903e80b213d20032903f00b213e20032903f80b213f20032903800c214020032903880c214120032903900c214220032802980c211b200328029c0c210920032802a00c210520032802a40c211c20032802a80c210b20032802ac0c210c20032d00b00c21012003200341a80b6a418c016a2800003600f308200320032800b10c3602f0082016410874200f72201041107472210d0240024020014102470d0020034280c2d72f3703f00320034280e1eb173703e803200342a0c21e3703e003200342a0c21e3703d803200342e0ef97203703d003200342e0c9dc293703c803200342e0ef97203703c003200342a0c21e3703b803200342a0c21e3703b003200342a0c21e3703a803200342a0c21e3703a003200342a0c21e37039803200342a0c21e37039003200342a0c21e3703880341002101200341003602f8034120210c41808001210b418080042105410421090c010b20034188036a418c016a20032800f3083600002003201b3602f803200320423703f003200320413703e803200320403703e0032003203f3703d8032003203e3703d0032003203d3703c8032003203c3703c0032003203b3703b8032003203a3703b003200320393703a803200320383703a003200320373703980320032006370390032003200437038803200320032802f00836009104201c21070b200341b0046a4200370300200341a0046a4200370300200320013a0090042003200c36028c042003200b3602880420032007360284042003200536028004200320093602fc032003428080e983b1de163703a8042003428080e983b1de1637039804200342a08080808080103703b804200320034188036a3602c004200320034188036a3602c404200341d8106a41186a22094200370300200341d8106a41106a22074200370300200341d8106a41086a22014200370300200342003703d81041d1efcb00ad42808080809001841001220529000021042001200541086a290000370300200320043703d8102005103541ebc3c400ad428080808030841001220b2900002104200341a80b6a41086a2205200b41086a290000370300200320043703a80b200b1035200220032903a80b370000200241086a220c2005290300370000200341b8106a41086a220f2001290300370300200341b8106a41106a22102007290300370300200341b8106a41186a22162009290300370300200320032903d8103703b810200341d0006a200341b8106a10e102200329035821042003280250211b200942003703002007420037030020014200370300200342003703d81041d1c4c700ad4280808080e000841001220b29000021062001200b41086a290000370300200320063703d810200b103541e7c4c700ad4280808080e000841001220b29000021062005200b41086a290000370300200320063703a80b200b1035200220032903a80b370000200c2005290300370000200f20012903003703002010200729030037030020162009290300370300200320032903d8103703b810200341c8006a200341b8106a412010c00120034180056a4200370300200341f4046a419494ca00360200200341c8046a41286a41b0b4cc00360200200341ec046a4100360200200341a0056a200341e8026a41086a290300370300200341a8056a200341e8026a41106a290300370300200341b0056a200341e8026a41186a2903003703002003428080808080013703f804200342003703e004200342003703d004200320032903e8023703980520032802482101200328024c21022003200341c4046a360290052003200341c0046a36028c05200320034188036a3602880520032002410020011b36029405200320044200201b1b3703c804200320143b01a206200320153a00a106200320123a00a0062003200d36029c062003200a36029806200341a80b6a200341c8046a200e2008200341d8026a20034198026a20034198066a10c0054101211a200341a80b6a41047221010240024020032802a80b4101470d00200341cc056a200141106a290200370200200341c4056a200141086a2902003702004101211a200341013602b805200320012902003702bc05200341b8056a410472212f0c010b200341b8056a410c6a200141286a2902003702002003200141206a2902003702bc05200341003602b805200341b8056a410472212f200341b8056a41106a2d00000d00200341a80b6a41086a200341e8046a29030037030020034198066a41086a200341a80b6a410c6a280200360200200320032903e0043703a80b200320032902ac0b37039806200341e8116a20034198066a10f0034100211a0b20032802fc042235200328028405220141d8026c6a210720032802800521362035210202402001450d00200341f10b6a211620034181106a210f200341a80b6a41017221302003419f066a2131200341a80b6a41186a211b200341b10b6a210c200341a0116a41116a211d200341a0116a410272211420034198066a41e0006a2132200341d00f6a41186a2133200341d10b6a211c200341a4106a2115200341a0116a410f6a2112200341d00f6a41116a2110200341b8106a410f6a2113200341e8066a2134203521010240034020012d00002102200341a40b6a41026a220d200141036a2d00003a00002003200141016a2f00003b01a40b200141046a2802002109200141086a28020021052001410c6a280200210a200341c00a6a200141106a41e000109d081a200141f8006a2903002104200141f0006a290300210620014180016a2903002108200341f0086a20014188016a41d001109d081a20024103460d01200341b4106a41026a220b200d2d00003a0000200320032f01a40b3b01b410200341d00f6a200341c00a6a41e000109d081a200341800e6a200341f0086a41d001109d081a024002400240024020020e03010200010b201320032900d00f370000201341086a200341d00f6a41086a2202290000370000201341106a200341d00f6a41106a220d2d00003a0000200320032f01b4103b01b8102003200a3600c310200320053600bf10200320093600bb102003200b2d00003a00ba10200341d8106a41186a2217201041186a2218290000370300200341d8106a41106a2225201041106a2226290000370300200341d8106a41086a2227201041086a2228290000370300200320102900003703d810200341f8106a41186a2229200f41186a222a290000370300200341f8106a41106a222b200f41106a222c290000370300200341f8106a41086a222d200f41086a222e2900003703002003200f2900003703f8102003200a3600ab11200320053600a711200320093600a3112003200b2d00003a00a211200320032f01b4103b01a011201220032900d00f370000201241086a2002290000370000201241106a200d2d00003a000020034198066a41186a201829000037030020034198066a41106a202629000037030020034198066a41086a20282900003703002003201029000037039806201b202a290000370300200341a80b6a41106a202c290000370300200341a80b6a41086a202e2900003703002003200f2900003703a80b200341d8116a41086a201541086a280000360200200320152900003703d811200341c8116a200341a0116a20034198066a200341a80b6a20062004200341d8116a10f10320032d00c8112102200c20032903b810370000200c41086a200341b8106a41086a290300370000200c41106a200341b8106a41106a290300370000200c41186a200341b8106a41186a290300370000201c20032903d810370000201c41086a2027290300370000201c41106a2025290300370000201c41186a2017290300370000200341033a00b00b2003410d3a00a80b200341a80b6a41f8006a2004370300201641186a2029290300370000201641106a202b290300370000201641086a202d290300370000201620032903f810370000200320063703980c200320024104463a00910c41b0b4cc004100200341a80b6a10d4010c020b2031200341d00f6a41e000109d081a2003410d3a00a80b203020034198066a41e700109d081a200341a80b6a41f0006a2004370300200320063703900c200320083703a00c2009200a200341a80b6a10d401200541ffffff3f71450d01200910350c010b200341d8116a41026a2202200b2d00003a0000200341d8106a41086a220d200341d00f6a41086a2217290000370300200341d8106a41106a2218200341d00f6a41106a22252d00003a0000200320032f01b4103b01d811200320032900d00f3703d81020034198066a203341c800109d081a20342004370300200320063703e006200320083703f0062032200341800e6a41d001109d081a200341b8106a20034198066a10d803200341a80b6a20034198066a41b002109d081a201420032f01b4103b0000201441026a200b2d00003a0000201d20032900d00f370000201d41086a2017290000370000201d41106a20252d00003a000020034180023b01a0112003200a3600ad11200320053600a911200320093600a511200341f8106a200341a80b6a200341a0116a10ac034200210402402003290380114201520d00420020032903b81022042003290388117d220620062004561b21040b2003427f20032903e002220620047c220420042006541b220420032903d802220620042006561b3703e00220032903f8102104200c20032f01d8113b0000200c41026a20022d00003a0000201b20032903d810370000201b41086a200d290300370000201b41106a20182d00003a0000200341063a00b00b2003410d3a00a80b2003200a3602bc0b200320053602b80b200320093602b40b20032004503a00d10b41b0b4cc004100200341a80b6a10d4010b200141d8026a22012007470d000b200721020c010b200141d8026a21020b024020072002460d0003402002220141d8026a21020240024020012d0000220941014b0d000240024020090e020001000b0240200141086a28020041ffffff3f71450d00200141046a28020010350b200141106a2d00004107470d02200141386a280200450d02200141346a28020010350c020b200141286a10bb020c010b200141e8006a28020041ffffff3f71450d00200141e4006a28020010350b20072002470d000b0b02402036450d00203641d8026c450d00203510350b202f290210210e202f28020c210b202f2902042104202f280200210720032802b8052105024020032802d4042201450d00200341d8046a280200450d00200110350b0240201a450d000240024020032802e404220a0d004100210c200341bc0b6a4100360200200341003602ac0b0c010b20032802ec04210c02400240200341e8046a28020022020d00200a21010c010b20022101200a2109034020092802880b21092001417f6a22010d000b200a21010340200120012f01064102746a41880b6a28020021012002417f6a22020d000b2009210a0b200341c40b6a20012f0106360200200341c00b6a4100360200200341bc0b6a2001360200200341003602b80b200342003703b00b2003200a3602ac0b200341003602a80b0b2003200c3602c80b200341a80b6a108f030b20032903e002210620032903d802210820054101470d010240200ea7450d00200b10350b200820067d2108420121060c150b420021064102210702402016410874200f722010411074720d000c150b200a10350c140b02402004a7450d00200710350b200820067d210842002104420121060c140b20032901f201210620032d00f101210220032d00f001210920032f01ee01211c20032d00ed01211d20032d00ec01211e20032f01ea01211f20032d00e901212020032d00e8012121200320032f0194023b01c00a2003200c3600cb0a2003200b3600c70a200320073600c30a2003201b2d00003a00c20a200341d70a6a2005290300370000200341df0a6a200a2d00003a000020032003290380023700cf0a200141ff01710d0f02400240201a4101710d0041022107200d41ff01714101460d010c110b41002107201c2127201f212a2014212d2010213020172133201921362013213520182134200f2132201621312012212f2015212e2021212c2020212b201e2129201d2128200921262002212520062104200d41ff01714102470d100b200320043703e80f200320253a00e70f200320263a00e60f200320273b01e40f200320283a00e30f200320293a00e20f2003202a3b01e00f2003202b3a00df0f2003202c3a00de0f2003202d3b01dc0f2003202e3a00db0f2003202f3a00da0f200320303b01d80f200320313a00d70f200320323a00d60f200320333b01d40f200320343a00d30f200320353a00d20f200320363b01d00f200341f0086a200341c00a6a10f303200341a80b6a20032802f008220220032802f80810d90220032d00a80b210120034198066a200341a80b6a41017241d700109d081a024020014102460d00200341800e6a20034198066a41d700109d081a0b024020032802f408450d00200210350b024002402001417f6a41ff01714102490d00200341f0086a200341870e6a41d000109d081a200341a80b6a41186a4200370300200341a80b6a41106a22094200370300200341a80b6a41086a22014200370300200342003703a80b41d1c4c700ad4280808080e000841001220229000021042001200241086a290000370300200320043703a80b2002103541e7c4c700ad4280808080e00084100122022900002104200341f8106a41086a2205200241086a290000370300200320043703f81020021035200920032903f810220437030020034198066a41086a200129030037030020034198066a41106a200437030020034198066a41186a2005290300370300200320032903a80b37039806200341f8006a20034198066a412010c001200341c8046a200341c00a6a200328027c410020032802781b22012007200341f0086a10f603024020032802c804417f6a41014b0d0020034198066a200341f0086a41d000109d081a20034188036a41186a200341c8046a41186a29030037030020034188036a41106a200341c8046a41106a29030037030020034188036a41086a200341c8046a41086a290300370300200320032903c80437038803200341a80b6a200341c00a6a20034198066a200120034188036a10f703024020032d00a80b0d00200341c40b6a280200450d00200341c00b6a28020010350b42002104200342003703880e200342808086bdbacdd21a3703800e2003200341d00f6a3602f00820034198066a200341d00f6a200341800e6a200341f0086a109a022003280298064101460d02200341c0066a290300210820034198066a41206a290300210e024020034198066a41086a220b2903004201520d0020034198066a41106a2903002104200341e00b6a20034198066a41186a290300370300200341d80b6a2004370300200341a80b6a41086a41003a0000200341b10b6a20032903d00f370000200341b90b6a200341d00f6a41086a290300370000200341c10b6a200341d00f6a41106a290300370000200341c90b6a200341d00f6a41186a290300370000200341033a00a80b41b0b4cc004100200341a80b6a10d4010b42002104200341a80b6a41186a22024200370300200341a80b6a41106a22074200370300200341a80b6a41086a22014200370300200342003703a80b41b6fdc600ad428080808080018422061001220a2900002137200341a0116a41086a2205200a41086a290000370300200320373703a011200a103520012005290300370300200320032903a0113703a80b41e489c200ad4280808080d0018422371001220c2900002138200341f8106a41086a220a200c41086a290000370300200320383703f810200c1035200920032903f810370000200941086a220f200a290300370000200b200129030037030020034198066a41106a2210200729030037030020034198066a41186a22162002290300370300200320032903a80b37039806200341e0006a20034198066a412010d701200341e0006a41106a2903002138200329036821392003280260210c200242003703002007420037030020014200370300200342003703a80b20061001220d29000021062005200d41086a290000370300200320063703a011200d103520012005290300370300200320032903a0113703a80b2037100122052900002106200a200541086a290000370300200320063703f81020051035200920032903f810370000200f200a290300370000200b20012903003703002010200729030037030020162002290300370300200320032903a80b370398062003427f20384200200c1b220620087c20394200200c1b2208200e7c220e2008542201ad7c22082001200820065420082006511b22011b3703b00b2003427f200e20011b3703a80b20034198066aad4280808080800484200341a80b6aad428080808080028410020c140b20034184096a280200450d0020032802800910350b420021040c120b200328029c06220141ff01714104460d112001418080807871210220014180807c712109200141807e712107200341a0066a2903002204422088a721052004a7210a0c100b200341d00b6a2001412c6a280200360200200341a80b6a41206a200141246a290200370300200341a80b6a41186a2001411c6a290200370300200341a80b6a41106a200141146a290200370300200341a80b6a41086a2001410c6a290200370300200320012902043703a80b20034198066a41206a200241206a29020037030020034198066a41186a200241186a29020037030020034198066a41106a200241106a29020037030020034198066a41086a200241086a29020037030020032002290200370398062000200341a80b6a20034198066a108e060c170b2001411c6a280200210d200141186a280200210f200141146a28020021102001410c6a2802002116200141086a280200211c410021094102210702400240024020022d0000450d000c010b20022d000141ff01714102470d00200141246a280200211b200141106a2802002107200341a80b6a41186a22054200370300200341a80b6a41106a22014200370300200341a80b6a41086a22024200370300200342003703a80b41a3edcb00ad4280808080f000841001220929000021042002200941086a290000370300200320043703a80b2009103541a5ebcb00ad4280808080c001841001220a2900002104200341f8106a41086a2209200a41086a290000370300200320043703f810200a1035200120032903f810220437030020034198066a41086a220b200229030037030020034198066a41106a220c200437030020034198066a41186a221d2009290300370300200320032903a80b3703980620034188016a20034198066a412010c001200341a80b6a200328028c0141002003280288011b2213201b10ba0420034180016a20032802a80b220a20032802b00b41b0b4cc0041004100108a022003280280012112024020032802ac0b450d00200a10350b200542003703002001420037030020024200370300200342003703a80b4188e8cb00ad42808080808001841001220a29000021042002200a41086a290000370300200320043703a80b200a1035418fd1cb00ad4280808080c000841001220a29000021042009200a41086a290000370300200320043703f810200a1035200120032903f810370000200141086a2009290300370000200b2002290300370300200c2001290300370300201d2005290300370300200320032903a80b37039806200341a80b6a20034198066a10d80220032802a80b2201410120011b211d20032902ac0b420020011b21040240201241014622020d00201d201b4105746a4100201b2004422088a7491b22010d020b41eec3c4004181c4c40020021b21054113410a20021b210a2002411074210941032107200442ffffff3f83500d00201d10350b02402016450d00201c10350b0240200d450d00200d410c6c21022010210103400240200141046a280200450d00200128020010350b2001410c6a2101200241746a22020d000b0b0240200f450d00200f410c6c450d00201010350b20004200370308200041206a200a3602002000411c6a2005360200200041186a200920077241802872360200200042013703000c170b200141086a2900002106200141106a29000021082001290000210e20034198066a41186a200141186a290000223737030020034198066a41106a200837030020034198066a41086a20063703002003200e37039806200341b50b6a2006370000200341bd0b6a2008370000200341c50b6a2037370000200341003a00ac0b2003410f3a00a80b2003200e3700ad0b41b0b4cc004100200341a80b6a10d401200341003602b00b200342013703a80b2007200341a80b6a10770240024020032802ac0b220920032802b00b22016b2007490d0020032802a80b21020c010b200120076a22022001490d08200941017422052002200520024b1b22054100480d080240024020090d00024020050d00410121020c020b200510332202450d1a0c010b20032802a80b210220092005460d0020022009200510372202450d190b200320053602ac0b200320023602a80b0b200220016a201c2007109d081a2003200120076a3602b00b200d200341a80b6a1077200d450d062010200d410c6c6a210c2010210203402002280200210b200241086a2802002201200341a80b6a10770240024020032802ac0b220720032802b00b22096b2001490d0020032802a80b21052007210a0c010b200920016a22052009490d092007410174220a2005200a20054b1b220a4100480d090240024020070d000240200a0d00410121050c020b200a10332205450d1b0c010b20032802a80b21052007200a460d0020052007200a10372205450d1a0b2003200a3602ac0b200320053602a80b0b200520096a200b2001109d081a2003200920016a22013602b00b2002410c6a2202200c470d000c0d0b0b200341a80b6a200141086a41a802109d081a20034198066a41206a200241206a29020037030020034198066a41186a200241186a29020037030020034198066a41106a200241106a29020037030020034198066a41086a200241086a29020037030020032002290200370398062000200341a80b6a20034198066a10b3040c150b200341a80b6a200141086a41c800109d081a20034198066a41206a200241206a29020037030020034198066a41186a200241186a29020037030020034198066a41106a200241106a29020037030020034198066a41086a200241086a29020037030020032002290200370398062000200341a80b6a20034198066a108f060c140b200341a80b6a200141046a41c400109d081a20034198066a41206a200241206a29020037030020034198066a41186a200241186a29020037030020034198066a41106a200241106a29020037030020034198066a41086a200241086a29020037030020032002290200370398062000200341a80b6a20034198066a1090060c130b200341800e6a41086a2207200141146a290200370300200341800e6a41106a22052001411c6a290200370300200341800e6a41186a220a200141246a290200370300200341800e6a41206a220b2001412c6a28020036020020032001410c6a2902003703800e2002411a6a2901002104200241196a2d0000210d200241186a2d0000210f200241166a2f01002110200241156a2d00002116200241146a2d0000211b200241126a2f0100211c200241116a2d0000211d200241106a2d000021122002410e6a2f010021132002410d6a2d000021142002410c6a2d000021152002410a6a2f01002117200241096a2d00002118200241086a2d00002125200241066a2f01002126200241056a2d00002127200241046a2d000021284102210c200241026a2f0100212920022d0001210920022d000021020240024002400240200141086a2802000e0400010203000b200341a80b6a41146a4101360200200342013702ac0b200341e8d4ca003602a80b2003410436029c062003419cd5ca0036029806200320034198066a3602b80b200341a80b6a41b0b4cc00104c000b02400240024002400240200241ff01710d00200941ff01714101460d010b200341023a0098060c010b200320043703c00b2003200d3a00bf0b2003200f3a00be0b200320103b01bc0b200320163a00bb0b2003201b3a00ba0b2003201c3b01b80b2003201d3a00b70b200320123a00b60b200320133b01b40b200320143a00b30b200320153a00b20b200320173b01b00b200320183a00af0b200320253a00ae0b200320263b01ac0b200320273a00ab0b200320283a00aa0b200320293b01a80b20034198066a200341a80b6a10890520032d0098064104460d010b20032802980621012000411c6a200329029c06370200200041186a2001360200420121040c010b420021040b200042003703080c090b20034198066a41206a200b28020036020020034198066a41186a200a29030037030020034198066a41106a200529030037030020034198066a41086a2007290300370300200320032903800e37039806200241ff01710d05200941ff01714101470d05200341a80b6a41206a20034198066a41206a280200360200200341a80b6a41186a20034198066a41186a290300370300200341a80b6a41106a20034198066a41106a290300370300200341a80b6a41086a20034198066a41086a29030037030020032003290398063703a80b200341f0086a200341a80b6a108b02024020032d00f0084101470d00200341013a00c8040c070b200341f0086a41086a2d00002101200341f9086a2f00002102200341fb086a2d00002109200341fc086a2d00002107200341fd086a2f00002105200341ff086a2d0000210a200341f0086a41106a2d0000210b20034181096a2f0000210c20034183096a2d0000210d20034184096a2d0000210f20034185096a2f0000211020034187096a2d00002116200341f0086a41186a2d0000211b20032f00f108211c20032d00f308211d20032d00f408211220032f00f508211320032d00f7082114200320034189096a2900003703a0032003201b3a009f03200320163a009e03200320103b019c032003200f3a009b032003200d3a009a032003200c3b0198032003200b3a0097032003200a3a009603200320053b019403200320073a009303200320093a009203200320023b019003200320013a008f03200320143a008e03200320133b018c03200320123a008b032003201d3a008a032003201c3b018803200341c8046a20034188036a10890520032d00c8044104470d06420021040c070b200141c8006a290300210e200141c0006a2903002137200141386a2903002106200141306a2903002108200141d0006a280200212a20034198066a41206a200b28020036020020034198066a41186a200a29030037030020034198066a41106a200529030037030020034198066a41086a2007290300370300200320032903800e37039806024002400240200241ff01710d00200941ff01714101470d00200320043703e0042003200d3a00df042003200f3a00de04200320103b01dc04200320163a00db042003201b3a00da042003201c3b01d8042003201d3a00d704200320123a00d604200320133b01d404200320143a00d304200320153a00d204200320173b01d004200320183a00cf04200320253a00ce04200320263b01cc04200320273a00cb04200320283a00ca04200320293b01c8044103210c200842808084fea6dee1115441002006501b0d00200341a80b6a41206a20034198066a41206a280200360200200341a80b6a41186a20034198066a41186a290300370300200341a80b6a41106a20034198066a41106a290300370300200341a80b6a41086a20034198066a41086a29030037030020032003290398063703a80b200341f0086a200341a80b6a108b024101210c024020032d00f0084101470d000c020b200341f0086a41086a2d00002101200341f9086a2f00002102200341fb086a2d00002109200341fc086a2d00002107200341fd086a2f00002105200341ff086a2d0000210a200341f0086a41106a2d0000210b20034181096a2f0000210c20034183096a2d0000210d20034184096a2d0000210f20034185096a2f0000211020034187096a2d00002116200341f0086a41186a2d0000211b20032f00f108211c20032d00f308211d20032d00f408211220032f00f508211320032d00f7082114200320034189096a2900003703a0032003201b3a009f03200320163a009e03200320103b019c032003200f3a009b032003200d3a009a032003200c3b0198032003200b3a0097032003200a3a009603200320053b019403200320073a009303200320093a009203200320023b019003200320013a008f03200320143a008e03200320133b018c03200320123a008b032003201d3a008a032003201c3b018803200341a80b6a20034188036a108a0520034198016a20032802a80b220120032802b00b41b0b4cc0041004100108a022003280298012102024020032802ac0b450d00200110350b41012101024020024101470d00411b21074103210c4117210941aaefc40021020c020b200341a80b6a200341c8046a20034188036a20082006410110e602024020032d00a80b220c4104460d00200341b00b6a280200210920032802ac0b210220032d00ab0b210520032d00aa0b210120032d00a90b21070c030b200341a80b6a20034188036a108a0520034190016a20032802a80b220220032802b00b41b0b4cc0041004100108a022003280290012101024020032802ac0b450d00200210350b024020014101460d00200341a80b6a20034188036a108a0520033502b00b210420032802a80b2102411010332201450d17200120083700002001200637000820014110412010372201450d1720012037370010200141186a200e3700002001412041c00010372201450d172001202a36002020044220862002ad842001ad4280808080c00484100220011035024020032802ac0b450d00200210350b200341a80b6a41186a20034188036a41186a290300370300200341a80b6a41106a20034188036a41106a290300370300200341a80b6a41086a20034188036a41086a29030037030020032003290388033703a80b200341f0086a200341a80b6a10890542002104200042003703080c0b0b200341b00b6a4117360200200341aaefc4003602ac0b200341013a00aa0b20034183363b01a80b4188bfc6004137200341a80b6a41c0bfc60041d0bfc6001046000b41022101411b21074109210941a1efc40021020b0b20004200370308200041206a20093602002000411c6a2002360200200041186a2005411874200141ff017141107472200741ff017141087472200c72360200420121040c070b418eebc400413041c086cc00103f000b1045000b20032802b00b210120032802ac0b210a20032802a80b21050c050b103e000b200341023a00c8040b20032802c80421012000411c6a20032902cc04370200200041186a2001360200420121040b200042003703080b200020043703000c0a0b200341a80b6a2013201b10ba0420032802a80b2102200320032802b00b36029c0620032002360298062005200120034198066a109403024020032802ac0b450d00200210350b0240200a450d00200510350b0240200442ffffff3f83500d00201d10350b02402016450d00201c10350b0240200d450d00200d410c6c21022010210103400240200141046a280200450d00200128020010350b2001410c6a2101200241746a22020d000b0b0240200f450d00200f410c6c450d00201010350b20004200370308200042003703000c090b410021024180800421094180242107410321014115210541dcffc600210a0b200041206a20053602002000411c6a200a360200200041186a20074180fe0371200141ff0171722009418080fc077172200272360200420121040b20004200370308200020043703000c060b2000411c6a2004370200200041186a2007360200420121040b20002006370308200041106a2008370300200020043703000c040b200210350b420021060b2000411c6a2008370200200041186a2007360200420121040b20002006370308200041106a200e370300200020043703000b200341f0116a24000f0b103c000bbf0403027f017e047f230041306b22032400200341086a200141086a28020022043602002003200129020022053703002005a72106024002400240024020040d00410021070c010b200441057421084100210941002107200621010240034002402009450d0020092001412010a0084100480d00200341186a4115360200200341e6f1c200360214200341053a001220034183023b0110200341106a21010c020b0240024020012002412010a008220941004a0d0020022001460d012009450d01200741016a21070b20012109200141206a2101200841606a2208450d030c010b0b200341186a4113360200200341d3f1c200360214200341063a001220034183023b0110200341106a21010b20004101360200200020012902003702042000410c6a200141086a280200360200200328020441ffffff3f71450d01200610350c010b200341106a41186a200241186a290000370300200341106a41106a200241106a290000370300200341106a41086a200241086a2900003703002003200229000037031020042007490d01024020042003280204470d00200320044101108a01200328020021060b200620074105746a220141206a2001200420076b410574109e081a200141186a200341106a41186a290300370000200141106a200341106a41106a290300370000200141086a200341106a41086a290300370000200120032903103700002003200441016a22013602082000410c6a200136020020002003290300370204200041003602000b200341306a24000f0b20072004104d000bba0502087f037e230041106b2202240002400240200141086a28020022034105744116722204417f4c0d000240200410332205450d00200520012802002206290000370000200541086a200641086a290000370000200241103602082002200436020420022005360200200141046a280200210720032002107702400240024020030d0020022802042106200228020821040c010b20034105742108200228020021092002280204210620022802082104034020072105024002402006200422036b4120490d00200341206a21040c010b200341206a22042003490d03200641017422072004200720044b1b22074100480d03024002400240024020060d00024020070d00410121090c020b2007103321090c030b20062007470d010b200721060c020b200920062007103721090b200721062009450d060b200541206a2107200920036a22032005290000370000200341186a200541186a290000370000200341106a200541106a290000370000200341086a200541086a290000370000200841606a22080d000b2002200636020420022004360208200220093602000b20012f010c210802400240200620046b4102490d00200441026a210520022802002103200621070c010b200441026a22052004490d01200641017422032005200320054b1b22074100480d010240024020060d00024020070d00410121030c020b200710332203450d060c010b2002280200210320062007460d0020032006200710372203450d050b20022007360204200220033602000b200320046a20083b00002005ad4220862003ad8410092205290000210a200541086a290000210b200541106a290000210c200041186a200541186a290000370000200041106a200c370000200041086a200b3700002000200a3700002005103502402007450d00200310350b200241106a24000f0b103e000b1045000b1044000b103c000b855802057f017e230041206b220224000240024020002802002203411b4b0d000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020030e1c000102030405060708090a0b0c0d0e0f101112131415161718191a1b000b200241003a00102001200241106a41011078200041086a280200417f6a220341094b0d1c024002400240024002400240024002400240024020030e0a00010203040506070809000b200241003a00042001200241046a4101107820022000410c6a2802003602102001200241106a410410780c250b200241013a00042001200241046a410110782000410c6a2802002103200041146a28020022002001107720012003200010780c240b200241023a00042001200241046a410110782002200041106a2903003703102001200241106a410810780c230b200241033a00042001200241046a410110782000410c6a2802002103200041146a28020022002001107720012003200010780c220b200241043a00042001200241046a410110782000410c6a2802002103200041146a28020022002001107720012003200010780c210b200241053a00042001200241046a4101107802402000410c6a2802004101460d00200241003a00042001200241046a410110780c210b200241013a00042001200241046a410110782002200041106a2802003602102001200241106a410410782002200041146a2802003602102001200241106a410410780c200b200241063a00042001200241046a410110782000410c6a2802002103200041146a2802002200200110772000450d1f2003200041186c6a2104034020032802002100200341086a28020022052001107720012000200510782003410c6a2802002100200341146a2802002205200110772001200020051078200341186a22032004470d000c200b0b200241073a00042001200241046a410110782000410c6a2802002103200041146a2802002200200110772000450d1e20032000410c6c6a2104034020032802002100200341086a28020022052001107720012000200510782003410c6a22032004470d000c1f0b0b200241083a00042001200241046a410110782000410c6a2802002103200041146a28020022002001107720012003200010780c1d0b200241093a00042001200241046a410110780c1c0b200241013a00102001200241106a4101107820002d0004417f6a220341044b0d1b200041046a21040240024002400240024020030e050001020304000b200241003a00042001200241046a41011078200041086a2802002103200041106a2802002200200110772000450d1f200041b0026c210003402003200110af03200341b0026a2103200041d07d6a22000d000c200b0b200241013a00042001200241046a41011078200220002f01063b01102001200241106a41021078200041086a280200200110af030c1e0b200241023a00042001200241046a41011078200220002f01063b01102001200241106a41021078200041086a2802002103200041106a28020022052001107702402005450d002005410574210503402001200341201078200341206a2103200541606a22050d000b0b0240024020002802144101460d00200241003a00042001200241046a410110780c010b200241013a00042001200241046a410110782002200041186a2802003602102001200241106a4104107820022000411c6a2802003602102001200241106a410410780b2000280220200110af030c1d0b200241033a00042001200241046a41011078200220002f01263b01102001200241106a41021078200041286a2802002103200041306a28020022052001107702402005450d002005410574210503402001200341201078200341206a2103200541606a22050d000b0b200441016a21030240024020002802344101460d00200241003a00042001200241046a410110780c010b200241013a00042001200241046a410110782002200041386a2802003602102001200241106a4104107820022000413c6a2802003602102001200241106a410410780b20012003412010780c1c0b200241043a00042001200241046a41011078200220002f01263b01102001200241106a41021078200041286a2802002103200041306a280200220520011077200441016a210402402005450d002005410574210503402001200341201078200341206a2103200541606a22050d000b0b200220002802343602102001200241106a410410782002200041386a2802003602102001200241106a4104107820012004412010780c1b0b200241023a00102001200241106a410110780c190b200241033a00102001200241106a41011078200241003a00102001200241106a41011078200041086a200110fb050c190b200241043a00102001200241106a41011078200241003a00102001200241106a41011078200028020421032000410c6a2802002200200110772000450d182003200041f0006c6a21060340412010332200450d1a20002003290010370000200041186a200341286a290000370000200041106a200341206a290000370000200041086a200341186a2900003700002001200041201078200010352003200110e201412010332200450d1a20002003290030370000200041186a200341c8006a290000370000200041106a200341c0006a290000370000200041086a200341386a290000370000200120004120107820001035412010332200450d1a200341f0006a210420002003290050370000200041186a200341e8006a290000370000200041106a200341e0006a290000370000200041086a200341d8006a29000037000020012000412010782000103520032802042100200328020c22032001107702402003450d00200341246c21030340200241106a200010c0032001200228021022052002280218107802402002280214450d00200510350b200041246a21002003415c6a22030d000b0b2004210320042006470d000c190b0b200241053a00102001200241106a4101107820002d0004417f6a220341034b0d17200041046a21050240024002400240024020030e0400010203000b200241003a00042001200241046a410110782002200041086a280200360210200241106a21000c030b200241013a00042001200241046a410110782001200541016a412010782002200041286a280200360210200241106a21000c020b200241023a00042001200241046a410110782002200041086a280200360210200241106a21000c010b200241033a00042001200241046a410110782001200541016a412010782002200041286a280200360210200241106a21000b20012000410410780c170b200241063a00102001200241106a41011078200041086a280200417f6a220341034b0d160240024002400240024020030e0400010203000b200241003a00042001200241046a410110782000410c6a200110fc05200041306a2103200221000c030b200241013a00042001200241046a410110782000410c6a200110fc052002200041306a360204200241046a200110cf01200041c0006a2103200241086a21000c020b200241023a00042001200241046a410110782000410c6a200110fc05200041306a200110fc05200041d8006a21032002410c6a21000c010b200241033a00042001200241046a410110782000410c6a200110fc05200041306a2103200241106a21000b200020033602002000200110cf010c160b200241073a00102001200241106a41011078200041086a22052d0000417f6a220341174b0d1502400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020030e18000102030405060708090a0b0c0d0e0f1011121314151617000b200241003a00102001200241106a410110782000410c6a200110fc052002200041306a360210200241106a200110cf0120002d0009220041024b0d2c02400240024020000e03000102000b200241003a00102001200241106a410110780c2e0b200241013a00102001200241106a410110780c2d0b200241023a00102001200241106a410110780c2c0b200241013a00102001200241106a410110782002200041106a360210200241106a200110cf010c2b0b200241023a00102001200241106a410110782002200041106a360210200241106a200110cf010c2a0b200241033a00102001200241106a410110780c290b200241043a00102001200241106a410110780240024002402000410c6a280200220341c000490d00200341808001490d012003418080808004490d02200241033a00042001200241046a410110782002200028020c3602102001200241106a410410780c2b0b200220034102743a00042001200241046a410110780c2a0b200220034102744101723b01102001200241106a410210780c290b200220034102744102723602102001200241106a410410780c280b200241053a00102001200241106a410110782000410c6a2802002103200041146a2802002200200110772000450d27200041246c210003402003200110fc05200341246a21032000415c6a22000d000c280b0b200241063a00102001200241106a410110780c260b200241073a00102001200241106a4101107820052d0001220041024b0d2502400240024020000e03000102000b200241003a00102001200241106a410110780c270b200241013a00102001200241106a410110780c260b200241023a00102001200241106a410110780c250b200241083a00102001200241106a410110782000410c6a200110fc050c240b200241093a00102001200241106a410110782000410c6a200110e2010c230b2002410a3a00102001200241106a410110780c220b2002410b3a00102001200241106a410110780c210b2002410c3a00102001200241106a410110782000410c6a2802002103200041146a2802002200200110772000450d202000410574210003402001200341201078200341206a2103200041606a22000d000c210b0b2002410d3a00102001200241106a410110782001200541016a412010780c1f0b2002410e3a00102001200241106a410110780c1e0b2002410f3a00102001200241106a4101107820022000410c6a2802003602102001200241106a41041078200041106a2802002103200041186a28020022002001107720012003200041027410780c1d0b200241103a00102001200241106a4101107820022000410c6a2802003602102001200241106a41041078200041106a2802002103200041186a2802002200200110772000450d1c2003200041246c6a2100034020012003412010782002200341206a2802003602102001200241106a410410782000200341246a2203470d000c1d0b0b200241113a00102001200241106a4101107820022000410c6a2802003602102001200241106a410410780c1b0b200241123a00102001200241106a410110782001200541016a4120107820022000412c6a2802003602102001200241106a410410780c1a0b200241133a00102001200241106a410110782002200041106a360210200241106a200110cf010c190b200241143a00102001200241106a410110782000410c6a200110e2010c180b200241153a00102001200241106a410110782001200541016a412010780c170b200241163a00102001200241106a410110782000410c6a2802002103200041146a2802002205200110772001200320054101741078200041186a200110f7012001200041e0016a413010782002200041d8016a2802003602102001200241106a410410780c160b200241173a00102001200241106a410110782000410c6a2802002103200041146a2802002205200110772001200320054101741078200041186a200110f7012001200041e0016a413010782002200041d8016a2802003602102001200241106a410410780c150b200241083a00102001200241106a4101107802402000280204450d00200241003a00042001200241046a410110782001200041106a412010782001200041306a412010782001200041d0006a412010782001200041f0006a41201078200028020421032000410c6a28020022002001107720012003200010780c150b200241013a00042001200241046a410110780c140b200241093a00102001200241106a41011078200041086a22032d0000417f6a2205411c4b0d130240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020050e1d000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c000b200241003a00102001200241106a41011078412010332205450d3020052003290001370000200541186a200341196a290000370000200541106a200341116a290000370000200541086a200341096a2900003700002001200541201078200510352002200041306a360210200241106a200110cf010c2f0b200241013a00102001200241106a410110782000410c6a200110e2010c2e0b200241023a00102001200241106a410110782000410c6a200110e201200041106a200110fd050c2d0b200241033a00102001200241106a410110782000410c6a200110e201200041106a200110fd050c2c0b200241043a00102001200241106a4101107820022000410c6a2802003602102001200241106a410410780c2b0b200241053a00102001200241106a41011078412010332200450d2b20002003290001370000200041186a200341196a290000370000200041106a200341116a290000370000200041086a200341096a2900003700002001200041201078200010350c2a0b200241063a00102001200241106a41011078412010332200450d2a20002003290001370000200041186a200341196a290000370000200041106a200341116a290000370000200041086a200341096a2900003700002001200041201078200010350c290b200241073a00102001200241106a41011078412010332200450d2920002003290001370000200041186a200341196a290000370000200041106a200341116a290000370000200041086a200341096a2900003700002001200041201078200010350c280b200241083a00102001200241106a41011078412010332205450d2820052003290001370000200541186a200341196a290000370000200541106a200341116a290000370000200541086a200341096a29000037000020012005412010782005103520022000412c6a2802003602102001200241106a410410782002200041306a2802003602102001200241106a410410780c270b200241093a00102001200241106a41011078412010332200450d2720002003290001370000200041186a200341196a290000370000200041106a200341116a290000370000200041086a200341096a2900003700002001200041201078200010350c260b2002410a3a00102001200241106a410110782000410c6a200110e2010c250b2002410b3a00102001200241106a4101107820022000410c6a2802003602102001200241106a410410780c240b2002410c3a00102001200241106a410110782001200341016a412010780c230b2002410d3a00102001200241106a410110780c220b2002410e3a00102001200241106a410110782001200341016a412010780c210b2002410f3a00102001200241106a410110782001200341016a41201078024020002d0029220341064b0d000240024002400240024002400240024020030e0700010203040506000b200241003a00040c060b200241013a00040c050b200241023a00040c040b200241033a00040c030b200241043a00040c020b200241053a00040c010b200241063a00040b2001200241046a410110780b200029033021072002200041386a290300370318200220073703102001200241106a411010780c200b200241103a00102001200241106a410110780c1f0b200241113a00102001200241106a410110780c1e0b200241123a00102001200241106a410110782000410c6a2802002103200041146a28020022002001107720012003200010780c1d0b200241133a00102001200241106a410110782000410c6a2802002103200041146a28020022002001107720012003200010780c1c0b200241143a00102001200241106a41011078412010332200450d1c20002003290001370000200041186a200341196a290000370000200041106a200341116a290000370000200041086a200341096a2900003700002001200041201078200010350c1b0b200241153a00102001200241106a410110782001200341016a412010780c1a0b200241163a00102001200241106a410110782001200341016a412010780c190b200241173a00102001200241106a4101107820022000410c6a2802003602102001200241106a410410780c180b200241183a00102001200241106a410110782001200341016a4120107820022000412c6a2802003602102001200241106a410410780c170b200241193a00102001200241106a410110782001200341016a41201078024020002d0029220341064b0d000240024002400240024002400240024020030e0700010203040506000b200241003a00040c060b200241013a00040c050b200241023a00040c040b200241033a00040c030b200241043a00040c020b200241053a00040c010b200241063a00040b2001200241046a410110780b200029033021072002200041386a290300370318200220073703102001200241106a411010780c160b2002411a3a00102001200241106a410110780c150b2002411b3a00102001200241106a4101107820022000410c6a2802003602102001200241106a410410780c140b2002411c3a00102001200241106a41011078412010332205450d1420052003290001370000200541186a200341196a290000370000200541106a200341116a290000370000200541086a200341096a29000037000020012005412010782005103520022000412c6a2802003602102001200241106a410410780c130b2002410a3a00102001200241106a41011078200041046a200110fe050c120b2002410b3a00102001200241106a41011078200041046a200110fe050c110b2002410c3a00102001200241106a41011078200041086a280200417f6a220341054b0d1002400240024002400240024020030e06000102030405000b200241003a00042001200241046a410110782000410c6a2802002103200041146a280200220520011077200041186a210402402005450d002005410574210003402001200341201078200341206a2103200041606a22000d000b0b20022004360210200241106a200110cf010c150b200241013a00042001200241046a410110780c140b200241023a00042001200241046a410110782000410c6a200110fc050c130b200241033a00042001200241046a410110780c120b200241043a00042001200241046a410110780c110b200241053a00042001200241046a410110782000410c6a200110fc050c100b2002410d3a00102001200241106a4101107820002d0004417f6a220341064b0d0f200041046a2105024002400240024002400240024020030e0700010203040506000b200241003a00042001200241046a410110782001200541016a412010780c150b200241013a00042001200241046a410110782001200541016a412010780c140b200241023a00042001200241046a410110782001200541016a412010782001200541216a412010780c130b200241033a00042001200241046a41011078200041086a2802002103200041106a2802002200200110772000450d122000410574210003402001200341201078200341206a2103200041606a22000d000c130b0b200241043a00042001200241046a410110782001200541016a412010780c110b200241053a00042001200241046a410110782001200541016a412010780c100b200241063a00042001200241046a410110780c0f0b2002410e3a00102001200241106a41011078200241003a00102001200241106a41011078200041046a200110e2010c0e0b2002410f3a00102001200241106a41011078200241003a00102001200241106a41011078200028020421032000410c6a28020022002001107720012003200010780c0d0b200241103a00102001200241106a41011078200041086a22032d0000417f6a220541074b0d0c0240024002400240024002400240024020050e080001020304050607000b200241003a00042001200241046a410110782002200041306a360210200241106a200110cf012000410c6a200110fc050c130b200241013a00042001200241046a410110782000410c6a200110e2010c120b200241023a00042001200241046a410110782000410c6a200110e2010c110b200241033a00042001200241046a410110782000412c6a2802002105200041346a28020022002001107720012005200010782001200341016a412010780c100b200241043a00042001200241046a41011078412010332200450d1020002003290001370000200041186a200341196a290000370000200041106a200341116a290000370000200041086a200341096a2900003700002001200041201078200010350c0f0b200241053a00042001200241046a410110782000412c6a2802002105200041346a28020022042001107720012005200410782001200341016a41201078200041386a29030021072002200041c0006a290300370318200220073703102001200241106a411010780c0e0b200241063a00042001200241046a41011078412010332205450d0e20052003290001370000200541186a200341196a290000370000200541106a200341116a290000370000200541086a200341096a290000370000200120054120107820051035200041306a29030021072002200041386a290300370318200220073703102001200241106a411010780c0d0b200241073a00042001200241046a41011078412010332200450d0d20002003290001370000200041186a200341196a290000370000200041106a200341116a290000370000200041086a200341096a2900003700002001200041201078200010350c0c0b200241113a00102001200241106a41011078200041086a22032d0000417f6a220541044b0d0b0240024002400240024020050e050001020304000b200241003a00042001200241046a41011078200041106a200110f3050c0f0b200241013a00042001200241046a410110782000410c6a2802002103200041146a28020022002001107720012003200010780c0e0b200241023a00042001200241046a410110782000410c6a200110fc052002200041c0006a360210200241106a200110cf01200041d0006a200110fb05200041306a2802002103200041386a28020022002001107720012003200010780c0d0b200241033a00042001200241046a410110782002200041386a360210200241106a200110cf01200041c8006a200110fb05412010332205450d0d20052003290001370000200541186a200341196a290000370000200541106a200341116a290000370000200541086a200341096a2900003700002001200541201078200510352000412c6a2802002103200041346a28020022002001107720012003200010780c0c0b200241043a00042001200241046a410110782001200341016a412010780240200341216a2d00004101460d00200241003a00042001200241046a410110780c0c0b200241013a00042001200241046a410110782001200341226a412010780c0b0b200241123a00102001200241106a410110782000280204417f6a220341024b0d0a02400240024020030e03000102000b200241003a00042001200241046a41011078200041086a280200200110af030c0c0b200241013a00042001200241046a41011078200041086a200110fc050c0b0b200241023a00042001200241046a41011078200041086a200110fc052000412c6a280200200110af030c0a0b200241133a00102001200241106a41011078200241003a00102001200241106a41011078200220002802043602102001200241106a41041078200041086a2802002103200041106a2802002205200110772001200320051078200041146a28020021032000411c6a28020022052001107702402005450d0020032005410c6c6a2106034020032802002105200341086a28020022042001107720012005200410782003410c6a22032006470d000b0b2002200041206a2802003602102001200241106a410410782002200041246a2802003602102001200241106a410410782002200041286a2802003602102001200241106a4104107820012000412c6a41c00010780c090b200241143a00102001200241106a410110780c070b200241153a00102001200241106a410110780c060b200241163a00102001200241106a410110780c050b200241173a00102001200241106a41011078200041086a22052d0000417f6a2203410a4b0d050240024002400240024002400240024002400240024020030e0b000102030405060708090a000b200241003a00042001200241046a410110782001200541016a412010780c0f0b200241013a00042001200241046a410110782000410c6a200110ab040c0e0b200241023a00042001200241046a410110782000410c6a2802002103200041146a2802002200200110772000450d0d2003200041c4006c6a210503402001200341201078200241106a200341206a220010ac042001200228021022032002280218107802402002280214450d00200310350b2005200041246a2203470d000c0e0b0b200241033a00042001200241046a410110780c0c0b200241043a00042001200241046a410110782000410c6a200110e2012002200041106a360210200241106a200110cf010c0b0b200241053a00042001200241046a4101107820022000410c6a2802003602102001200241106a410410780c0a0b200241063a00042001200241046a410110782000410c6a200110e2012002200041106a360210200241106a200110cf010c090b200241073a00042001200241046a410110782000412c6a200110e2012001200541016a412010780c080b200241083a00042001200241046a410110782000410c6a200110e2012002200041106a2903003703102001200241106a410810780c070b200241093a00042001200241046a410110782000410c6a200110e201200041106a200110fc05200041386a200110aa040c060b2002410a3a00042001200241046a410110782000410c6a200110fc050c050b200241183a00102001200241106a41011078200041086a22052d0000417f6a2203410b4b0d0402400240024002400240024002400240024002400240024020030e0c000102030405060708090a0b000b200241003a00042001200241046a41011078200041106a29030021072002200041186a290300370318200220073703102001200241106a411010780c0f0b200241013a00042001200241046a4101107820022000410c6a2802003602102001200241106a410410780c0e0b200241023a00042001200241046a410110782001200541016a41201078200041306a29030021072002200041386a290300370318200220073703102001200241106a41101078200041c0006a29030021072002200041c8006a290300370318200220073703102001200241106a411010780c0d0b200241033a00042001200241046a4101107820022000410c6a2802003602102001200241106a410410780c0c0b200241043a00042001200241046a410110782000410c6a200110fc05200220002d00093a00042001200241046a410110780c0b0b200241053a00042001200241046a41011078200220052d00013a00042001200241046a410110780c0a0b200241063a00042001200241046a410110780c090b200241073a00042001200241046a410110782001200541016a4120107820022000412c6a2802003602102001200241106a41041078200041306a2802002103200041386a28020022002001107720012003200010780c080b200241083a00042001200241046a410110780c070b200241093a00042001200241046a410110782001200541016a412010782002200541216a2d00003a00042001200241046a410110780c060b2002410a3a00042001200241046a410110782001200541016a41201078200541216a2d0000220041024b0d0502400240024020000e03000102000b200241003a00042001200241046a410110780c070b200241013a00042001200241046a410110780c060b200241023a00042001200241046a410110780c050b2002410b3a00042001200241046a4101107820022000410c6a2802003602102001200241106a410410780c040b200241193a00102001200241106a4101107820002d0004417f6a220341084b0d03200041046a210502400240024002400240024002400240024020030e09000102030405060708000b200241003a00042001200241046a410110782001200541016a41201078200041286a280200200110af030c0b0b200241013a00042001200241046a410110782001200541016a412010782001200541216a412010780c0a0b200241023a00042001200241046a41011078200041086a2802002103200041106a28020022052001107702402005450d002005410574210503402001200341201078200341206a2103200541606a22050d000b0b200220002f01063b01102001200241106a41021078200220002802143602102001200241106a410410780c090b200241033a00042001200241046a410110782001200541016a412010780c080b200241043a00042001200241046a410110782001200541016a412010782001200541216a412010780c070b200241053a00042001200241046a410110782001200541016a412010780c060b200241063a00042001200241046a410110782001200541016a412010780c050b200241073a00042001200241046a410110780c040b200241083a00042001200241046a410110782001200541016a412010780c030b2002411a3a00102001200241106a41011078200041086a280200417f6a220341024b0d0202400240024020030e03000102000b200241003a00042001200241046a410110780c040b200241013a00042001200241046a410110782000410c6a200110fc050c030b200241023a00042001200241046a410110782000410c6a200110fc05200041306a29030021072002200041386a290300370318200220073703102001200241106a41101078200041c0006a29030021072002200041c8006a290300370318200220073703102001200241106a411010782002200041d0006a2802003602102001200241106a410410780c020b2002411b3a00102001200241106a410110780b200110ff050b200241206a24000f0b1045000bf30703027f017e067f230041e0006b2203240041a8fdc600ad4280808080f00084100122042900002105200341086a200441086a29000037030020032005370300200410354180a9c300ad4280808080900184100122042900002105200341106a41086a200441086a29000037030020032005370310200410350240024002400240412010332204450d0020042001290000370000200441186a200141186a290000370000200441106a200141106a290000370000200441086a200141086a29000037000020032004ad42808080808004841003220129000037034020011035200341dc006a2206200441206a360200200320043602582003200341c0006a41086a3602542003200341c0006a360250200341206a200341d0006a107b20041035412010332204450d0020042002290000370000200441186a200241186a290000370000200441106a200241106a290000370000200441086a200241086a2900003700002004ad4280808080800484100422012900002105200341c0006a41086a200141086a29000037030020032005370340200110352006200441206a360200200320043602582003200341c0006a41106a3602542003200341c0006a360250200341306a200341d0006a107b200410352003280228220741206a2206200328023822086a2201417f4c0d01200328023021092003280220210a0240024020010d004100210b410121040c010b200110332204450d012001210b0b02400240200b410f4d0d00200b21020c010b200b41017422024110200241104b1b22024100480d030240200b0d002002103322040d010c050b200b2002460d002004200b200210372204450d040b20042003290300370000200441086a200341086a2903003700000240024020024170714110460d002002210b0c010b2002410174220b4120200b41204b1b220b4100480d032002200b460d0020042002200b10372204450d040b20042003290310370010200441186a200341106a41086a29030037000002400240200b41606a2007490d00200b21020c010b2007415f4b0d03200b41017422022006200220064b1b22024100480d03200b2002460d002004200b200210372204450d040b200441206a200a2007109d081a02400240200220066b2008490d002002210b0c010b20012006490d032002410174220b2001200b20014b1b220b4100480d03024020020d000240200b0d00410121040c020b200b10332204450d050c010b2002200b460d0020042002200b10372204450d040b200420066a20092008109d081a200020013602082000200b3602042000200436020002402003280234450d00200910350b02402003280224450d00200a10350b200341e0006a24000f0b1045000b1044000b103e000b103c000bb10101027f024020002802082201450d0020002802002100200141246c210103400240024020002d0000220241044b0d0002400240024020020e050400010204040b2000410c6a280200450d03200041086a28020010350c030b2000410c6a280200450d02200041086a28020010350c020b2000410c6a280200450d01200041086a28020010350c010b200041086a280200450d00200041046a28020010350b200041246a21002001415c6a22010d000b0b0b13002000410c36020420004190aac3003602000beb0d02097f027e230041e0006b22022400200241386a4100290288e146370300200241306a4100290280e146370300200241286a41002902f8e046370300200241206a41002902f0e046370300200241186a41002902e8e046370300200241106a41002902e0e046370300200241086a41002902d8e046370300200241002902d0e0463703002002410036024820024201370340200241d0006a200210b40320022802502103024002400240024020022802442204200228024822056b20022802582206490d00200228024021070c010b200520066a22072005490d01200441017422082007200820074b1b22084100480d010240024020040d00024020080d00410121070c020b2008103322070d010c040b2002280240210720042008460d0020072004200810372207450d030b20022008360244200220073602400b200720056a20032006109d081a2002200520066a36024802402002280254450d00200310350b200241d0006a200241106a10b403200228025021080240024020022802442204200228024822056b20022802582203490d0020022802402106200421070c010b200520036a22062005490d01200441017422072006200720064b1b22074100480d010240024020040d00024020070d00410121060c020b200710332206450d040c010b2002280240210620042007460d0020062004200710372206450d030b20022007360244200220063602400b200620056a20082003109d081a2002200520036a220336024802402002280254450d00200810350b02400240200720036b4104490d00200341046a21050c010b200341046a22052003490d01200741017422042005200420054b1b22044100480d010240024020070d00024020040d00410121060c020b200410332206450d040c010b20072004460d0020062007200410372206450d030b20022004360244200220063602400b200620036a410a3600002002200536024820022802242103024002402002280244220720056b4104490d00200228024021060c010b200541046a22062005490d01200741017422042006200420064b1b22044100480d010240024020070d00024020040d00410121060c020b200410332206450d040c010b2002280240210620072004460d0020062007200410372206450d030b20022004360244200220063602400b200620056a20033600002002200541046a220636024820022802282104024002402002280244220320066b4104490d00200228024021070c010b200641046a22072006490d01200341017422082007200820074b1b22084100480d010240024020030d00024020080d00410121070c020b200810332207450d040c010b2002280240210720032008460d0020072003200810372207450d030b20022008360244200220073602400b200720066a20043600002002200541086a360248200241306a2802002108200241386a200241346a200228022c4101461b2802002205200241c0006a1077024002402005410c6c22050d00200228024821040c010b200820056a21092002280244210620022802482104034002400240200620046b4108490d00200441086a210520022802402103200621070c010b200441086a22052004490d03200641017422072005200720054b1b22074100480d030240024020060d00024020070d00410121030c020b200710332203450d060c010b2002280240210320062007460d0020032006200710372203450d050b20022007360244200220033602400b200320046a200829000037000020022005360248200841086a280200210402400240200720056b41034d0d00200721060c010b200541046a22062005490d032007410174220a2006200a20064b1b22064100480d030240024020070d00024020060d00410121030c020b200610332203450d060c010b20072006460d0020032007200610372203450d050b20022006360244200220033602400b200320056a20043600002002200541046a22043602482008410c6a22082009470d000b0b200228023c2107024002402002280244220620046b4104490d00200228024021050c010b200441046a22052004490d01200641017422032005200320054b1b22034100480d010240024020060d00024020030d00410121050c020b200310332205450d040c010b2002280240210520062003460d0020052006200310372205450d030b20022003360244200220053602400b200520046a2007360000200441046aad210b2002350240210c02402002280200450d00200241086a280200450d00200228020410350b200b422086210b02402002280210450d00200241186a280200450d00200241146a28020010350b200b200c84210b0240200228022c450d0020022802342205450d002005410c6c450d00200228023010350b200241e0006a2400200b0f0b103e000b103c000bd80401067f20012802042102024002400240024020012802004101470d002001410c6a280200220141046a2203417f4c0d0102400240024002400240024002400240024002402003450d00200310332204450d0c200141c000490d04200141808001490d052001418080808004490d0620030d010b41012103410110332204450d07200441033a0000410521050c010b200441033a000002402003417f6a41034d0d00200321050c020b200341017422064105200641054b1b22054100480d0720032005460d010b20042003200510372204450d050b20042001360001410521060c030b024020030d0041012103410110332204450d040b200420014102743a000041012106200321050c020b02400240200341014d0d00200321050c010b200341017422064102200641024b1b2105024020030d002005103322040d010c040b20032005460d0020042003200510372204450d030b41022106200420014102744101723b00000c010b02400240200341034d0d00200321050c010b200341017422064104200641044b1b22054100480d03024020030d002005103322040d010c030b20032005460d0020042003200510372204450d020b20042001410274410272360000410421060b0240200520066b2001490d00200521030c060b200620016a22032006490d01200541017422072003200720034b1b22034100480d0120052003460d05200420052003103722040d050b103c000b103e000b20002002200141086a28020010d3030f0b1044000b1045000b200420066a20022001109d081a2000200620016a36020820002003360204200020043602000b9b1a03047f017e057f230041a00e6b22022400024002402001450d00200220003602300c010b200241b0b4cc003602300b20022001360234200241c00a6a200241306a10b60302400240024020022802c40a450d00200241386a200241c00a6a41fc00109d081a200241b8016a200241386a41fc00109d081a200241b8016a10b703024020022802b8012201450d00200241b8026a2001417f6a10b803200241c00a6a20022802b802220120022802c00210d501200241e8066a41086a2200200241c90a6a290000370300200241e8066a41106a2203200241d10a6a290000370300200241e8066a41186a2204200241d90a6a290000370300200220022900c10a3703e8060240024020022d00c00a4101460d00200241a8036a41186a4200370300200241a8036a41106a4200370300200241a8036a41086a4200370300200242003703a8030c010b200241a8036a41186a2004290300370300200241a8036a41106a2003290300370300200241a8036a41086a2000290300370300200220022903e8063703a8030b024020022802bc02450d00200110350b200241a8036a200241c8016a412010a0080d00200241b0026a280200210120022802a8022100200241003602f006200242043703e806200241e8066a4100200110870120022802f006210402402001450d00200141c8036c21032001410374210520022802e8062004410c6c6a21010340200220003602a803200241c00a6a200241a8036a10b903200141086a200241c00a6a41086a280200360200200120022903c00a3702002001410c6a2101200041c8036a2100200341b87c6a22030d000b200541786a41037620046a41016a21040b200241a8036a41086a2004360200200220022903e80622063703a803200241e8066a41086a2004360200200220063703e806200241c00a6a200241e8066a10ba03024020024188026a2201200241c00a6a412010a008450d0041ec9ccc00ad4280808080e0018410062001ad4280808080800484100a200241c00a6aad4280808080800484100a0b02402001200241c00a6a412010a0080d00100b200241ac026a280200210720022802a802210520022802b0022103200241b8026a200241b8016a41f000109d081a2005200341c8036c6a210020022802b8022108200521010240024002402003450d00200241e8066a41f0006a2104200521010240034020024180066a200141e800109d081a200141e8006a2903002106200241a8036a200141f0006a41d802109d081a20064203510d01200241e8066a20024180066a41e800109d081a200220063703d0072004200241a8036a41d802109d081a2002200241e8066a3602b00a200241c00a6a200241b00a6a10b90320022802c80a2103024020022802c40a450d0020022802c00a10350b200241c00a6a200241e8066a41c803109d081a200241003602880e200241b00a6a200241c00a6a2003200241880e6a10bb0320022d00b00a4101460d04200141c8036a22012000470d000c030b0b200141c8036a21010b20002001460d00034020014198016a10bb022000200141c8036a2201470d000b0b02402007450d00200741c8036c450d00200510350b10bc03200810bd030240100c4101470d00200241c00a6a10be03200241206a200241b8026a410472220110bf032002200228022422003602980e200241186a200241c00a6a410472220310bf032002200228021c220436029c0e20002004470d06200241106a200110bf0320022802102105200241086a200310bf03200228020c220120022802142200200020014b1b2209450d05200228020821074100210341edc5ca00ad4280808080c002842106410021040340024002400240024002400240024002400240200520036a22012d00002208200720036a22002d0000470d0002400240024002400240024020080e06000102030405000b20052007460d0d200141016a200041016a412010a0080d050c060b024020052007460d00200141016a280000200041016a280000470d050b200141106a2802002208200041106a280200470d04200141086a280200220a200041086a280200220b460d0a200a200b200810a0080d040c0a0b024020052007460d00200141016a280000200041016a280000470d040b200141106a2802002208200041106a280200470d03200141086a280200220a200041086a280200220b460d08200a200b200810a0080d030c080b024020052007460d00200141016a280000200041016a280000470d030b200141106a2802002208200041106a280200470d02200141086a280200220a200041086a280200220b460d06200a200b200810a0080d020c060b200141046a2802002208200041046a280200470d012008450d04200141086a280200200041086a280200470d012001410c6a2802002000410c6a280200470d010c040b2001410c6a28020022082000410c6a280200470d00200141046a280200220a200041046a280200220b460d02200a200b200810a008450d020b20061006200241e8066a200110c00320023502f00642208620022802e8062208ad84100a024020022802ec06450d00200810350b200241e8066a200010c00320023502f00642208620022802e8062208ad84100a024020022802ec06450d00200810350b20012d000020002d00002208470d06024020080e06000605040302000b20052007460d070b200141016a200041016a412010a0080d050c060b2001410c6a28020022082000410c6a280200470d04200141046a2802002201200041046a2802002200460d0520012000200810a0080d040c050b200141046a2802002208200041046a280200470d032008450d04200141086a280200200041086a280200470d032001410c6a2802002000410c6a280200460d040c030b024020052007460d00200141016a280000200041016a280000470d030b200141106a2802002208200041106a280200470d02200141086a2802002201200041086a2802002200460d0320012000200810a0080d020c030b024020052007460d00200141016a280000200041016a280000470d020b200141106a2802002208200041106a280200470d01200141086a2802002201200041086a2802002200460d0220012000200810a0080d010c020b024020052007460d00200141016a280000200041016a280000470d010b200141106a2802002208200041106a280200470d00200141086a2802002201200041086a2802002200460d0120012000200810a008450d010b4188cfc400412741c086cc00103f000b200341246a2103200441016a22042009490d000c060b0b41d7cfc400411e41c086cc00103f000b200241286a20022f00b10a20022d00b30a4110747210c1032002280228200228022c41c086cc00103f000b41dccec400412441c086cc00103f000b41c0cec400411c41c086cc00103f000b200241b4036a4104360200200241fc066a4102360200200242023702ec06200241f0b2c3003602e806200241043602ac03200241e8b2c3003602a803200241003602bc01200241b0b4cc003602b8012002200241a8036a3602f8062002200241b8016a3602b003200241e8066a4180b3c300104c000b0240200241b8026a41306a2201200241c00a6a41306a2200412010a008450d0041ec9ccc00ad4280808080e0018410062001ad4280808080800484100a2000ad4280808080800484100a0b024020012000412010a008450d0041afcfc400412841c086cc00103f000b0240200241c00a6a410c6a2802002200450d0020022802c40a2101200041246c210003400240024020012d0000220341044b0d0002400240024020030e050400010204040b2001410c6a280200450d03200141086a28020010350c030b2001410c6a280200450d02200141086a28020010350c020b2001410c6a280200450d01200141086a28020010350c010b200141086a280200450d00200141046a28020010350b200141246a21012000415c6a22000d000b0b0240200241c80a6a2802002201450d00200141246c450d0020022802c40a10350b0240200241b8026a410c6a2802002200450d0020022802bc022101200041246c210003400240024020012d0000220341044b0d0002400240024020030e050400010204040b2001410c6a280200450d03200141086a28020010350c030b2001410c6a280200450d02200141086a28020010350c020b2001410c6a280200450d01200141086a28020010350c010b200141086a280200450d00200141046a28020010350b200141246a21012000415c6a22000d000b0b0240200241c0026a2802002201450d00200141246c450d0020022802bc0210350b200241a00e6a240042010f0b200241a8036a41146a410a360200200241b4036a410c36020020024180066a41146a41033602002002200241980e6a3602880e20022002419c0e6a3602b00a200241e8066a41146a41003602002002420337028406200241a0b3cc00360280062002410c3602ac03200241b0b4cc003602f806200242013702ec0620024180cfc4003602e8062002200241a8036a360290062002200241e8066a3602b8032002200241b00a6a3602b0032002200241880e6a3602a80320024180066a41b0b4cc00104c000bc10603077f017e037f230041c00b6b22022400200241f8076a200110c4030240024020022802fc072203450d0020024184086a2802002104200228028008210520022802f8072106200241086a20024188086a41e000109d081a2002200110c40102400240024020022802000d0020022802042207200128020441c8036e2208200820074b1bad42c8037e2209422088a70d012009a7220a417f4c0d0102400240200a0d004108210b0c010b200a1033220b450d030b41002108200241003602702002200b3602682002200a41c8036e36026c024002402007450d00200241f8076a41f0006a210c0340200241f8076a200110c80320024190076a200241f8076a41e800109d081a20022903e0082109200241b8046a200c41d802109d081a20094203510d02200241d0036a20024190076a41e800109d081a200241f8006a200241b8046a41d802109d081a02402008200228026c470d00200241e8006a200810a9012002280268210b200228027021080b200b200841c8036c6a200241d0036a41e800109d08220a2009370368200a41f0006a200241f8006a41d802109d081a2002200841016a22083602702007417f6a22070d000b0b200b450d01200229026c2109200241f8076a200241086a41e000109d081a2000410c6a2004360200200020053602082000200336020420002006360200200041106a200241f8076a41e000109d081a200041f4006a2009370200200041f0006a200b3602000c050b02402008450d00200841c8036c2107200b4198016a21080340200810bb02200841c8036a2108200741b87c6a22070d000b0b200228026c2208450d00200841c8036c450d00200b10350b2000410036020402402004450d00200441246c21072003210803400240024020082d0000220141044b0d0002400240024020010e050400010204040b2008410c6a280200450d03200841086a28020010350c030b2008410c6a280200450d02200841086a28020010350c020b2008410c6a280200450d01200841086a28020010350c010b200841086a280200450d00200841046a28020010350b200841246a21082007415c6a22070d000b0b2005450d03200541246c450d03200310350c030b1044000b1045000b200041003602040b200241c00b6a24000bb83a05047f017e057f017e107f230041f01a6b22012400200141186a200010df03200141c8156a41186a4200370300200141c8156a41106a22024200370300200141c8156a41086a22034200370300200142003703c81541d1c4c700ad4280808080e000841001220429000021052003200441086a290000370300200120053703c8152004103541c8f1c700ad4280808080a00284100122042900002105200141b8106a41086a2206200441086a290000370300200120053703b81020041035200220012903b8102205370300200141a0186a41086a2003290300370300200141a0186a41106a2005370300200141a0186a41186a2006290300370300200120012903c8153703a0182001412036028c062001200141a0186a36028806200141e80d6a200141a0186aad22054280808080800484100510c20102400240024002400240024002400240024002400240024020012802e80d22040d00410221030c010b20012802ec0d21072001200141e80d6a41086a2802003602dc08200120043602d808200141106a200141d8086a10c401200128021421080240024020012802100d00200141086a200141d8086a10c40120012802080d0020012802dc082209200128020c2203490d002003417f4c0d030240024020030d0041002109410121060c010b200310392206450d09200620012802d808220a2003109d081a2001200920036b3602dc082001200a20036a3602d808200321090b2006450d002003ad4220862009ad84210b410121030c010b200141003602c010200142013703b810200141093602ac0b200120014188066a3602a80b2001200141b8106a3602b803200141dc156a4101360200200142013702cc15200141c888c2003602c8152001200141a80b6a3602d815200141b8036a41e88ac500200141c8156a10431a20013502c01042208620013502b810841006024020012802bc10450d0020012802b81010350b410221030b2007450d00200410350b02400240024002400240024020034102460d00200ba72104410121070240200841f501490d00410021080240200b422088a7200420034101461b4104470d004101210820064190e1c600460d00200628000041eede91ab064621080b200841017321070b02402004450d00200610350b2007450d010b200141c4106a41002902d8e046370200200141f5013602b810200141002902d0e0463702bc10200141c8156a41186a4200370300200141c8156a41106a22064200370300200141c8156a41086a22034200370300200142003703c81541d1c4c700ad4280808080e0008410012204290000210b2003200441086a2900003703002001200b3703c8152004103541c8f1c700ad4280808080a0028410012204290000210b200141286a41086a2208200441086a2900003703002001200b3703282004103520062001290328220b370300200141a0186a41086a2003290300370300200141a0186a41106a200b370300200141a0186a41186a2008290300370300200120012903c8153703a018200141003602f00d200142013703e80d41f501200141e80d6a1077200141c8156a200141b8106a41047210b40320012802c81521090240024020012802ec0d220720012802f00d22046b20012802d0152206490d0020012802e80d2103200721080c010b200420066a22032004490d02200741017422082003200820034b1b22084100480d020240024020070d00024020080d00410121030c020b2008103322030d010c110b20012802e80d210320072008460d0020032007200810372203450d100b200120083602ec0d200120033602e80d0b200320046a20092006109d081a2001200420066a22043602f00d024020012802cc15450d00200910350b200542808080808004842004ad4220862003ad84100202402008450d00200310350b420010c8040b2000280200200041106a200041d0006a200141186a410110e00320012000280200220c36023c2001428089fa00370340200141a0186a200c10c904200141c8156a20012802a018220020012802a818220310b8020240024020012802c815220d0d00420021054108210d0c010b2003ad4220862000ad84100720012902cc1521050b024020012802a418450d00200010350b200d2005422088a7220341d0026c22066a21042005a7210e200d21002003450d07200641b07d6a2107200141c8156a41046a210f200141a0186a41046a210a200141e80d6a41046a211041002106200141d8006a41086a2108200d210002400340200141e8006a200041bc02109d081a200041bc026a28020021032008200041c8026a2903003703002001200041c0026a290300370358024020034103470d00200041d0026a21000c0a0b2010200141e8006a41bc02109d082111200141a0186a200141e80d6a41c002109d081a20014188136a200a41bc02109d081a200141f8126a41086a22092008290300370300200120012903583703f8120240024020034102470d00410121090c010b200f20014188136a41bc02109d081a200141a80b6a200141c8156a41c002109d081a200141980b6a41086a2009290300370300200120012903f8123703980b41002109200621120b200141d8086a200141a80b6a41c002109d081a200141c8086a41086a200141980b6a41086a290300370300200120012903980b3703c8082009450d01200641016a2106200741b07d6a2107200041d0026a22002004470d000b200421000c080b200141b8036a200141d8086a41c002109d081a200141a8036a41086a2208200141c8086a41086a290300370300200120012903c8083703a803200141b8106a200141b8036a41c002109d081a200141a8106a41086a22092008290300370300200120012903a8033703a810200041d0026a210020034102460d0720014188066a200141b8106a41c002109d081a200141f8056a41086a22082009290300370300200120012903a8103703f805200141c8156a20014188066a41c002109d081a200141a0186a41086a2008290300370300200120012903f8053703a01841d80210332213450d0920132012360200201341046a200141c8156a41c002109d081a201320033602c402201320012903a0183703c802201341d0026a200141a0186a41086a290300370300200142818080801037024c20012013360248200421032007450d02200641016a2108200141b8106a41046a2109200141980b6a41086a210302400340200141b8036a200041bc02109d081a200041bc026a28020021062003200041c8026a2903003703002001200041c0026a2903003703980b024020064103470d00200041d0026a21030c050b2009200141b8036a41bc02109d081a200141a0186a200141b8106a41c002109d081a20014188136a200a41bc02109d081a200141f8126a41086a22072003290300370300200120012903980b3703f8120240024020064102470d00410121070c010b200f20014188136a41bc02109d081a200141e80d6a200141c8156a41c002109d081a200141e8006a41086a2007290300370300200120012903f81237036841002107200821100b200141a80b6a200141e80d6a41c002109d081a200141a8106a41086a200141e8006a41086a290300370300200120012903683703a8102007450d01200841016a2108200041d0026a22002004470d000b20042103410121140c040b200141d8086a200141a80b6a41c002109d081a200141c8086a41086a2209200141a8106a41086a2215290300370300200120012903a8103703c808200041d0026a21034101211420064102460d03200841016a210020014188066a200141d8086a41c002109d081a200141f8056a41086a22162009290300370300200120012903c8083703f80541012108410121140340200141c8156a20014188066a41c002109d081a200141a0186a41086a22072016290300370300200120012903f8053703a018024020142008470d00200141c8006a20084101109501200128024821130b2013201441d8026c6a22082010360200200841046a200141c8156a41c002109d081a200841c4026a2006360200200841c8026a20012903a018370300200841d0026a20072903003703002001201441016a2214360250024020032004470d00200421030c050b02400340200141e8006a200341bc02109d081a200341bc026a2802002106200141d8006a41086a2208200341c8026a2903003703002001200341c0026a290300370358024020064103470d00200341d0026a21030c070b2011200141e8006a41bc02109d081a200141a0186a200141e80d6a41c002109d081a20014188136a200a41bc02109d081a200141f8126a41086a22072008290300370300200120012903583703f8120240024020064102470d00410121080c010b200f20014188136a41bc02109d081a200141a80b6a200141c8156a41c002109d081a200141286a41086a20072903002205370300200141980b6a41086a2005370300200120012903f8122205370328200120053703980b41002108200021120b200141d8086a200141a80b6a41c002109d081a2009200141980b6a41086a290300370300200120012903980b3703c8082008450d01200041016a2100200341d0026a22032004470d000b200421030c050b200141b8036a200141d8086a41c002109d081a200141a8036a41086a22082009290300370300200120012903c8083703a803200141b8106a200141b8036a41c002109d081a20152008290300370300200120012903a8033703a81020064102460d02200341d0026a2103200041016a210020014188066a200141b8106a41c002109d081a20162015290300370300200120012903a8103703f805200128024c2108201221100c000b0b103e000b200341d0026a21030c010b410121140b024020042003460d000340200341d0026a21000240200341bc026a2802004102460d000240200341b0026a2802002206450d00200341b4026a280200450d00200610350b200310bb020b2000210320042000470d000b0b0240200e450d00200e41d0026c450d00200d10350b200128024c211720144115490d022014410176ad42d8027e2205422088a70d002005a72218417f4c0d00201810332219450d0541002100200141003602a818200142043703a018201341a87d6a211a201341c87a6a211b410421034100210f20142112034020122109410021124101210702402009417f6a220e450d000240024002400240024002402013200e41d8026c6a41d0026a2d0000200941d8026c221020136a41a07d6a2d00002206490d002009417e6a210a201b20106a2108410021124100210403400240200a2004470d00200921070c080b200441016a2104200641ff0171210720082d00002106200841a87d6a2108200720064f0d000b200441016a21072004417f7320096a21040c010b201b20106a2108200e210402400340024020044101470d00410021040c020b2004417f6a2104200641ff0171210720082d00002106200841a87d6a210820072006490d000b0b20092004490d02200920144b0d01200920046b2207410176220a450d002013200441d8026c6a2106201a20106a21080340200141c8156a200641d802109d081a2006200841d802109e0841d8026a21062008200141c8156a41d802109d0841a87d6a2108200a417f6a220a0d000b0b024020040d00200421120c050b0240200741094d0d00200421120c050b200920144b0d022013200441d8026c6a2110034020092004417f6a2212490d040240200920126b22074102490d002013200441d8026c6a220841d0026a2d00002013201241d8026c6a220641d0026a2d0000220d4f0d00200141c8156a200641d002109d081a2001200641d4026a2800003600bb102001200641d1026a2800003602b8102006200841d802109d082111024020074103490d00200e210a2010210620114180086a2d0000200d4f0d0003402006200641d8026a220841d802109d0821112004200a417f6a220a460d012008210620114180086a2d0000200d490d000b0b2008200141c8156a41d002109d08220441d0026a200d3a0000200441d1026a20012802b810360000200441d4026a20012800bb103600000b2012450d05201041a87d6a2110201221042007410a4f0d050c000b0b2009201441eccfca001058000b2004200941eccfca001059000b20092004417f6a2212490d002009201441fccfca001058000b2012200941fccfca001059000b0240200f20012802a418470d00200141a0186a200f410110900120012802a018210320012802a8182200210f0b2003200f4103746a22042007360204200420123602002001200041016a22003602a8182000210f024020004102490d000240024003400240024002400240024020032000417f6a4103746a2204280200450d00200041037420036a220741746a2802002208200428020422064b0d010b20004103490d022004280204210620032000417d6a22114103746a28020421040c010b4102210f200041024d0d0620032000417d6a22114103746a2802042204200620086a4d0d004103210f200041034d0d06200741646a280200200420086a4b0d050b20042006490d010b2000417e6a21110b02400240024002400240024002402000201141016a220d4d0d00200020114d0d0120032011410374220e6a2200280204221520002802006a22002003200d41037422166a2203280200220f490d02200020144b0d032013200f41d8026c6a220a2003280204221041d8026c22036a2106200041d8026c21072000200f6b220820106b220020104f0d0420192006200041d8026c2203109d08220820036a210420104101480d0520004101480d05201a20076a21072006210303402007200341a87d6a2206200441a87d6a2209200441786a2d0000200341786a2d00004922001b41d802109d0821072004200920001b21040240200a2006200320001b2203490d00200821000c080b200741a87d6a21072008210020082004490d000c070b0b200d2000418cd0ca001042000b20112000419cd0ca001042000b200f200041acd0ca001059000b2000201441acd0ca001058000b2019200a2003109d08220020036a2104024020104101480d00200820104c0d00201320076a210920002100200a2103034020062000200641d0026a2d0000200041d0026a2d00004922081b21072000200041d8026a20081b21002003200741d802109d0841d8026a2103200641d8026a200620081b220620094f0d03200420004b0d000c030b0b200a2103200021000c010b20062103200821000b20032000200420006b2204200441d802706b109d081a024020012802a818220020114d0d0020012802a0182203200e6a2204201520106a3602042004200f3602002000200d4d0d02200320166a2204200441086a2000200d417f736a410374109e081a20012000417f6a22003602a818200041014b0d010c030b0b2011200041bcd0ca001042000b200d2000104e000b2000210f0b2012450d020c000b0b1044000b024020012802a41841ffffffff0171450d00200310350b201841d802702100201841d802490d0220182000460d02201910350c020b20144102490d012014417f6a21032013201441d8026c6a2106410021080340024002400240201420032200417f6a2203490d00201420036b22074102490d022013200041d8026c6a220041d0026a2d00002013200341d8026c6a220441d0026a2d000022094f0d02200141c8156a200441d002109d081a2001200441d4026a2800003600bb102001200441d1026a2800003602b8102004200041d802109d08210a20074103490d012008210420062107200a4180086a2d000020094f0d0103402007220041a87d6a200041d802109d081a2004417f6a2204450d02200041d8026a2107200041a8056a2d000020094f0d020c000b0b2003201441dccfca001059000b2000200141c8156a41d002109d08220041d0026a20093a0000200041d1026a20012802b810360000200041d4026a20012800bb103600000b200841016a2108200641a87d6a210620030d000c020b0b024020042000460d000340200041d0026a21030240200041bc026a2802004102460d000240200041b0026a2802002206450d00200041b4026a280200450d00200610350b200010bb020b2003210020042003470d000b0b41002114410821130240200e450d00200e41d0026c450d00200d10350b410021170b200142003703d808200141800e6a4100360200200141fc0d6a2013201441d8026c6a360200200141f80d6a2013360200200141f40d6a2017360200200141900e6a200141d8086a3602002001418c0e6a2001413c6a360200200120133602f00d200142003703e80d2001200141c0006a3602880e200141a0186a200141e80d6a10ca04024020012802dc1a4103460d00200141c8156a200141a0186a41d002109d081a41d00210332206450d012006200141c8156a41d002109d08210020014281808080103702ac0b200120003602a80b200141b8106a41286a200141e80d6a41286a290300370300200141b8106a41206a200141e80d6a41206a290300370300200141b8106a41186a200141e80d6a41186a290300370300200141b8106a41106a2208200141e80d6a41106a290300370300200141b8106a41086a200141e80d6a41086a290300370300200120012903e80d3703b810200141a0186a200141b8106a10ca04024020012802dc1a4103470d00410121030c030b4102210341d0022100410121040340200141c8156a200141a0186a41d002109d081a02402003417f6a2004470d00200141a80b6a2004410110a70120012802a80b21060b200620006a200141c8156a41d002109d081a200120033602b00b200141a0186a200141b8106a10ca0420012802dc1a4103460d03200041d0026a2100200341016a210320012802ac0b21040c000b0b20012802fc0d20012802f80d22046b220041d8026d210302402000450d00200341d8026c2103200441bc026a2100034002402000417c6a2802002204450d002000280200450d00200410350b200041cc7d6a10bb02200041d8026a2100200341a87d6a22030d000b0b024020012802f40d2200450d00200041d8026c450d0020012802f00d10350b41082106410021080c020b1045000b200141cc106a280200200828020022086b220041d8026d210402402000450d00200441d8026c2104200841bc026a2100034002402000417c6a2802002208450d002000280200450d00200810350b200041cc7d6a10bb02200041d8026a2100200441a87d6a22040d000b0b0240200141c4106a2802002200450d00200041d8026c450d0020012802c01010350b20012802ac0b21082003450d00200128023c41016a2006200310cb04200341d0026c210320012903d80821052006210003400240200041bc026a2802004102460d000240200041b0026a2802002204450d00200041b4026a280200450d00200410350b200010bb020b200041d0026a2100200341b07d6a22030d000c020b0b20012903d80821050b02402008450d00200841d0026c450d00200610350b427f427f2005200c10cc047c220b200b2005541b22054280e497d0127c220b200b2005541b10c804200142003703e80d200141c8156a41186a22044200370300200141c8156a41106a22064200370300200141c8156a41086a22004200370300200142003703c81541d1c4c700ad4280808080e000841001220329000021052000200341086a290000370300200120053703c815200310354188f2c700ad4280808080e00184100122032900002105200141b8106a41086a2208200341086a290000370300200120053703b81020031035200220012903b810370000200241086a2008290300370000200141a0186a41086a2000290300370300200141a0186a41106a2006290300370300200141a0186a41186a2004290300370300200120012903c8153703a018200141203602cc152001200141a0186a3602c815200141e80d6a200141c8156a10cd0420012802182106024020012802202200450d00200041246c21032006210003400240024020002d0000220441044b0d0002400240024020040e050400010204040b2000410c6a280200450d03200041086a28020010350c030b2000410c6a280200450d02200041086a28020010350c020b2000410c6a280200450d01200041086a28020010350c010b200041086a280200450d00200041046a28020010350b200041246a21002003415c6a22030d000b0b0240200128021c2200450d00200041246c450d00200610350b200141f01a6a24000f0b103c000bfc0403027f017e057f230041d0006b2202240041d1c4c700ad4280808080e00084100122032900002104200241086a41086a200341086a290000370300200220043703082003103541dec4c700ad4280808080900184100122032900002104200241186a41086a200341086a2900003703002002200437031820031035200220013602342002200241346aad4280808080c000841003220329000037033820031035200241cc006a200241386a3602002002200241386a41086a3602442002200241346a3602482002200241386a360240200241286a200241c0006a107b02400240024002402002280230220541206a2206417f4c0d00200228022821070240024020060d0041002101410121030c010b200610332203450d02200621010b024002402001410f4d0d00200121080c010b200141017422084110200841104b1b22084100480d03024020010d002008103322030d010c050b20012008460d0020032001200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821010c010b200841017422014120200141204b1b22014100480d0320082001460d0020032008200110372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200141606a2005490d00200121080c010b200541206a22082005490d03200141017422092008200920084b1b22084100480d0320012008460d0020032001200810372203450d040b200341206a20072005109d081a2000200636020820002008360204200020033602000240200228022c450d00200710350b200241d0006a24000f0b1044000b1045000b103e000b103c000b981103067f027e067f230041c0006b22022400024002400240024041ca0310332203450d00200241ca0336020420022003360200200341003b00002002410236020802400240200128020022032903684202520d00024020022802044102470d0020022802004102410410372201450d0620024104360204200220013602000b200228020041043a00022002200228020841016a3602080c010b024020022802044102470d0020022802004102410410372201450d0520024104360204200220013602000b20022802004184013a00022002200228020841016a3602082003200210fc05024020032d0024220141024b0d000240024002400240024020010e03000102000b410021040c020b410121040c010b41022104200241023a001041c10021050c010b200220043a001041c00021050b02400240200228020420022802082201460d00200228020021060c010b200141016a22062001490d05200141017422072006200720064b1b22074100480d050240024020010d0041002101024020070d00410121060c020b2007103322060d010c080b2002280200210620012007460d0020062001200710372206450d070b20022007360204200220063602000b200620016a20043a00002002200141016a2201360208024002402002280204220420016b2005490d00200228020021060c010b200120056a22062001490d05200441017422072006200720064b1b22074100480d050240024020040d00024020070d00410121060c020b200710332206450d080c010b2002280200210620042007460d0020062004200710372206450d070b20022007360204200220063602000b200620016a200341256a2005109d081a2002200120056a3602080b02400240200341e8006a22012903004201520d00200129031020012903082208420c882209420120094201561b8021090240024020022802042204200228020822056b4102490d00200228020021060c010b200541026a22062005490d06200441017422072006200720064b1b22074100480d060240024020040d00024020070d00410121060c020b200710332206450d090c010b2002280200210620042007460d0020062004200710372206450d080b20022007360204200220063602000b200620056a2009a741047420087aa7417f6a22064101200641014b1b2206410f2006410f491b723b0000200541026a21050c010b02400240200228020420022802082205460d00200228020021060c010b200541016a22062005490d05200541017422042006200420064b1b22044100480d050240024020050d0041002105024020040d00410121060c020b200410332206450d080c010b2002280200210620052004460d0020062005200410372206450d070b20022004360204200220063602000b200620056a41003a0000200541016a21050b20022005360208200141186a200210e2012002200141206a360210200241106a200210cf010b20034198016a200210af0320022802082103410410332201450d0020024204370214200220013602102003417e6a200241106a10772002280208220341014d0d01200228021821012002280214210a200220022802102207360224200241286a200720016a2205360200200241023602102002411c6a2002280200220641026a2204360200410021012002410036020820022003417e6a22033602142002200436021820022002360220200241246a210b0240024002402003450d0020072103034020032005460d032002200341016a360224200620016a20032d00003a00002002200228020841016a36020820014101460d02200141016a210120022802242103200228022821050c000b0b2002200b10c7050c010b024020022802282204200228022422036b2201450d00024002402002280220220641046a280200220c2002280214220d2002280210220e6a22056b2001490d00200628020021050c010b200520016a220f2005490d05200c4101742205200f2005200f4b1b220f4100480d0502400240200c0d000240200f0d00410121050c020b200f10332205450d080c010b20062802002105200c200f460d002005200c200f10372205450d070b20062005360200200641046a200f3602000b2005200e20016a22016a2005200e6a200d109e081a20022001360210200120062802082205460d00200520036a417f732004200e6a6a2101200628020020056a2105034020032004460d022002200341016a360224200520032d00003a00002006200628020841016a3602082001450d01200541016a21052001417f6a210120022802242103200228022821040c000b0b2002410036023820024201370330200241306a200b10c7052002280234210b2002280230210e024020022802382203450d00024002402002280220220641046a28020022042002280214220c200228021022056a22016b2003490d00200628020021010c010b200120036a220d2001490d0520044101742201200d2001200d4b1b220d4100480d050240024020040d000240200d0d00410121010c020b200d10332201450d080c010b200628020021012004200d460d0020012004200d10372201450d070b20062001360200200641046a200d3602000b2001200520036a22046a200120056a200c109e081a20022004360210200420062802082201460d00200120056b2104200628020020016a2101200e210503402003450d01200120052d00003a00002006200628020841016a360208200541016a2105200141016a210120042003417f6a2203470d000b0b200b450d00200e10350b02402002280218200228021c2203460d00200220033602180b024020022802142203450d000240200228021022062002280220220441086a22052802002201460d002004280200220420016a200420066a2003109e081a0b2005200320016a3602000b0240200a450d00200710350b20002002290300370200200041086a200241086a280200360200200241c0006a24000f0b1045000b41022003104f000b103e000b103c000bf104020b7f037e230041206b22022400024002400240024020012802082203410c6c41046a2204417f4c0d00200128020021050240024020040d0041012106410021040c010b200410332206450d020b2002410036020820022006360200200220043602042003200210770240024020030d002002280208210420022802042107200228020021080c010b20052003410c6c6a21092005210603402006280200210a200641086a280200220420021077024002402002280204220b2002280208220c6b2004490d0020022802002108200b21070c010b200c20046a2208200c490d05200b41017422072008200720084b1b22074100480d0502400240200b0d00024020070d00410121080c020b2007103322080d010c080b20022802002108200b2007460d002008200b200710372208450d070b20022007360204200220083602000b2008200c6a200a2004109d081a2002200c20046a22043602082006410c6a22062009470d000b0b2004ad4220862008ad8410282204290000210d200441086a290000210e200441106a290000210f200241186a2206200441186a290000370300200241106a220c200f370300200241086a220b200e3703002002200d37030020041035200041186a2006290300370000200041106a200c290300370000200041086a200b2903003700002000200229030037000002402007450d00200810350b02402003450d002003410c6c21062005210403400240200441046a280200450d00200428020010350b2004410c6a2104200641746a22060d000b0b0240200141046a2802002204450d002004410c6c450d00200510350b200241206a24000f0b1044000b1045000b103e000b103c000bdd3d04057f027e077f0b7e230041c00e6b22042400200441b8086a200141c803109d081a200441b0056a200441b8086a10d7034101210502400240024002400240024002400240024020042d00b0054101460d00200441b0026a200441b0056a41086a418003109d081a024020032802002201450d00200341086a280200210620032802042107200441a8026a41c4c3c700411010c00141002105200441b8086a20042802ac02410020042802a8021b10cb0320042802b8082108200420042802c0083602b405200420083602b00520012006200441b0056a109403024020042802bc08450d00200810350b2007450d00200110350b200441800c6a20044180036a10d803200441b8086a200441b0026a418003109d081a024002400240024020042903d80822094202520d0020042903800c220920042d00880c2206200210ce04220841ff01714102470d094200210a200441800d6a41086a22074200370300200441800d6a41106a220b4200370300200441800d6a41186a220c4200370300200442003703800d2004280288094113470d02200441b0056a2004418c096a10dd0320042d00b0054101460d01200441dc056a280200210d200441d8056a280200210e200441d4056a280200210f200441cc056a2802002110200441c8056a28020021110240200441d0056a2802002208450d002008410c6c21022011210803400240200841046a280200450d00200828020010350b2008410c6a2108200241746a22020d000b0b02402010450d002010410c6c450d00201110350b0240200d450d00200d410c6c2102200f210803400240200841046a280200450d00200828020010350b2008410c6a2108200241746a22020d000b0b200e450d02200e410c6c450d02200f10350c020b200441800d6a41186a200441b8086a41186a290300370300200441800d6a41106a200441b8086a41106a290300370300200441800d6a41086a200441b8086a41086a290300370300200420042903b8083703800d20044180096a2903002112200441f8086a290300210a200441f0086a280200210820042903e008211342002114200441900e6a41186a4200370300200441900e6a41106a220b4200370300200441900e6a41086a22064200370300200442003703900e41d1c4c700ad4280808080e000841001220729000021152006200741086a290000370300200420153703900e2007103541e7c4c700ad4280808080e00084100122072900002115200441f80d6a41086a220c200741086a290000370300200420153703f80d20071035200b20042903f80d2215370300200441b0056a41086a2006290300370300200441b0056a41106a2015370300200441b0056a41186a200c290300370300200420042903900e3703b005200441a0026a200441b0056a412010c001024020094201520d0020134200510d060b200441900e6a200441800d6a108e02200441b0056a20042802900e220720042802980e108f020240024020042903b0054201510d0041002106420021094200211542002113420021164200211742002118420021194100210b0c010b200441c0056a2903002119200441d0056a2903002117200441c8056a2903002116200441e0056a2903002113200441d8056a2903002115200441f0056a2903002109200441e8056a2903002114200441f8056a280200210620042903b805211820042802fc05210b0b024020042802940e450d00200710350b024020062008470d00200441b0056a200441800d6a108e0220043502b805211a20042802b0052107410410332206450d072006200841016a36000020064104410810372208450d072008200b3a000420084108411510372208450d07200820183700052008410d6a201937000020084115412a10372208450d07200820163700152008411d6a20173700002008412a41d40010372208450d0720082014370035200820153700252008413d6a20093700002008412d6a2013370000201a4220862007ad842008ad4280808080d00884100220081035024020042802b405450d00200710350b418012210820042d00880c22064102460d0920042903800c22092006200210ce04220841ff01714102470d0920044190026a2002200920042d00890c200a201210db0302400240200429039002221420044190026a41086a29030022158450450d00420021160c010b200441003a00a80d200420153703e80c200420143703e00c41012102200441014111200a201284501b3a008c0e2004200441800d6a3602f80d2004200441800d6a3602c00c2004200441c00c6a3602c00520042004418c0e6a3602bc052004200441f80d6a3602b8052004200441a80d6a3602b4052004200441e00c6a3602b005200441900e6a200441800d6a200441b0056a10dc030240024020042802900e4101470d004200211520042903980e21140c010b200441b80e6a2903002115200441b00e6a2903002114024020042903980e4201510d00410021020c010b200441900e6a41106a290300211320042802c00c2108200441e8056a200441900e6a41186a290300370300200441e0056a201337030041002102200441b0056a41086a41003a0000200441b9056a2008290000370000200441c1056a200841086a290000370000200441c9056a200841106a290000370000200441d1056a200841186a290000370000200441033a00b00541b0b4cc004100200441b0056a10d4010b42012116418002210820020d0a0b200441b80d6a41186a200441800d6a41186a2903002213370300200441b80d6a41106a200441800d6a41106a2903002217370300200441b80d6a41086a200441800d6a41086a2903002218370300200441d80d6a41086a2018370300200441d80d6a41106a2017370300200441d80d6a41186a2013370300200420042903800d22133703b80d200420133703d80d4101210d0c030b418006418004200620084b1b21080c080b20042d00b10522084102470d060b200441b80d6a41186a200c290300370300200441b80d6a41106a200b290300370300200441b80d6a41086a2007290300370300200420042903800d3703b80d4100210d42002112420021160b200441c00c6a41186a2210200441d80d6a41186a2208290300370300200441c00c6a41106a220f200441d80d6a41106a2202290300370300200441c00c6a41086a2211200441d80d6a41086a2207290300370300200420042903d80d3703c00c200441e00c6a41186a200441b80d6a41186a220b290300370300200441e00c6a41106a200441b80d6a41106a220c290300370300200441e00c6a41086a200441b80d6a41086a220e290300370300200420042903b80d3703e00c200441b0056a20044188096a41b002109d081a200820102903003703002002200f29030037030020072011290300370300200420042903c00c3703d80d410221100240200d450d00200b2008290300370300200c2002290300370300200e2007290300370300200420042903d80d3703b80d410121100b2004419a0e6a200e290300370100200441a20e6a200c290300370100200441aa0e6a200b290300370100200420103a00910e200420042903b80d3701920e200441003a00900e200441800d6a200441b0056a200441900e6a10ac03200441800d6a41106a290300211720042903880d2113200420042900990d3703b0052004200441a00d6a2800003600b7050240024020042903800d4201510d00410421080c010b200441800d6a41186a2d00002102200420042800b7053600970e200420042903b0053703900e4104210820134202510d00200420042800970e3600af0d200420042903900e3703a80d200221080b200441b80d6a41186a200441e00c6a41186a290300370300200441b80d6a41106a200441e00c6a41106a290300370300200441b80d6a41086a200441e00c6a41086a290300370300200420042903e00c3703b80d0240024002400240200841ff01714104460d00200641ff01714102460d010b20134201520d024200200920177d221820182009561b2219500d02200441b0056a41186a220c4200370300200441b0056a41106a22074200370300200441b0056a41086a22064200370300200442003703b00541d1c4c700ad4280808080e00084221a1001220b2900002118200441d80d6a41086a2202200b41086a290000370300200420183703d80d200b103520062002290300370300200420042903d80d3703b0054184eec700ad4280808080b00284221b1001220b29000021182002200b41086a290000370300200420183703d80d200b1035200720042903d80d2218370300200441900e6a41086a220e2006290300370300200441900e6a41106a22102018370300200441900e6a41186a220d2002290300370300200420042903b0053703900e20044180026a200441900e6a10e1022004290388022118200429038002211c200c42003703002007420037030020064200370300200442003703b005201a1001220b290000211a2002200b41086a2900003703002004201a3703d80d200b103520062002290300370300200420042903d80d3703b005201b1001220b290000211a2002200b41086a2900003703002004201a3703d80d200b1035200720042903d80d221a370300200e20062903003703002010201a370300200d2002290300370300200420042903b0053703900e201ca70d01200441900e6aad428080808080048410070c020b41801021082016500d08200441900e6a41186a220c4200370300200441900e6a41106a22074200370300200441900e6a41086a22064200370300200442003703900e41b6fdc600ad428080808080018422091001220b2900002112200441f80d6a41086a2202200b41086a290000370300200420123703f80d200b103520062002290300370300200420042903f80d3703900e41e489c200ad4280808080d0018422121001220b290000210a2002200b41086a2900003703002004200a3703f80d200b1035200720042903f80d220a370300200441b0056a41086a220e2006290300370300200441b0056a41106a2210200a370300200441b0056a41186a220d2002290300370300200420042903900e3703b005200441086a200441b0056a412010d701200441086a41106a290300210a200429031021132004280208210b200c42003703002007420037030020064200370300200442003703900e20091001220c29000021092002200c41086a290000370300200420093703f80d200c103520062002290300370300200420042903f80d3703900e20121001220c29000021092002200c41086a290000370300200420093703f80d200c1035200720042903f80d2209370300200e200629030037030020102009370300200d2002290300370300200420042903900e3703b00520044200200a4200200b1b220920157d20134200200b1b2215201454ad7d2212201520147d2214201556201220095620122009511b22021b3703980e20044200201420021b3703900e200441b0056aad4280808080800484200441900e6aad428080808080028410020c080b20044200201820197d221920192018561b3703b005200441900e6aad4280808080800484200441b0056aad428080808080018410020b200441d80d6a41186a200441b80d6a41186a290300370300200441d80d6a41106a200441b80d6a41106a290300370300200441d80d6a41086a200441b80d6a41086a290300370300200420042903b80d3703d80d02402016500d0042002116200441f0016a4200200920177d221720172009561b420020134201511b10cf0420042903f00121092004200441f0016a41086a29030022133703800e200420093703f80d02400240024002400240200920138450450d00420021090c010b2004200441d80d6a36028c0e200441900e6a200441d80d6a200441f80d6a2004418c0e6a109a0220042802900e4101460d01200441b80e6a2903002109200441b00e6a2903002116200441900e6a41086a2903004201520d00200441900e6a41106a2903002113200441e8056a200441900e6a41186a290300370300200441e0056a2013370300200441b0056a41086a41003a0000200441b9056a20042903d80d370000200441c1056a200441d80d6a41086a290300370000200441c9056a200441d80d6a41106a290300370000200441d1056a200441d80d6a41186a290300370000200441033a00b00541b0b4cc004100200441b0056a10d4010b20142016542202201520095420152009511b0d01201520097d2002ad7d2115201420167d21140b200441f0006a201220152014200a56201520125620152012511b22021b2212420042d0004200108408200441b0016a200a201420021b2209420042d000420010840820044180016a4200420020094200108408200441d0016a20042903b001200441b0016a41086a290300220a20042903702004290380017c7c221342e4004200109808200441a0016a201520127d2014200954ad7d2215420042d0004200108408200441c0016a201420097d2214420042d000420010840820044190016a4200420020144200108408200441e0016a20042903c001200441c0016a41086a290300221620042903a0012004290390017c7c221742e4004200109808427f201242dc9e8aae8f85d7c702200441d0016a41086a2903002004290378200429038801844200522013200a547222021b220a201242c2eba3e1f5d1f0fa2820042903d00120021b2213200954200a201254200a2012511b22021b22187d20092013200920021b221254ad7d220a201542dc9e8aae8f85d7c702200441e0016a41086a29030020042903a8012004290398018442005220172016547222021b2213201542c2eba3e1f5d1f0fa2820042903e00120021b2216201454201320155420132015511b22021b22137d20142016201420021b221554ad7d7c200920127d2209201420157d7c22162009542202ad7c220920022009200a542009200a511b22021b2114427f201620021b210a02400240201520127c2209201320187c2009201554ad7c2215844200520d00200441900e6a41186a220c4200370300200441900e6a41106a22074200370300200441900e6a41086a22064200370300200442003703900e41b6fdc600ad428080808080018422091001220b2900002115200441f80d6a41086a2202200b41086a290000370300200420153703f80d200b103520062002290300370300200420042903f80d3703900e41e489c200ad4280808080d0018422151001220b29000021122002200b41086a290000370300200420123703f80d200b1035200720042903f80d2212370300200441b0056a41086a220e2006290300370300200441b0056a41106a22102012370300200441b0056a41186a220d2002290300370300200420042903900e3703b005200441d8006a200441b0056a412010d701200441d8006a41106a2903002112200429036021132004280258210b200c42003703002007420037030020064200370300200442003703900e20091001220c29000021092002200c41086a290000370300200420093703f80d200c103520062002290300370300200420042903f80d3703900e20151001220c29000021092002200c41086a290000370300200420093703f80d200c1035200720042903f80d2209370300200e200629030037030020102009370300200d2002290300370300200420042903900e3703b005200420124200200b1b3703980e200420134200200b1b3703900e200441b0056aad4280808080800484200441900e6aad428080808080028410020c010b200442f0f2bda1a7ee9cb9f9003703900e200441b0056a200441900e6a10e001200441b0056a2009201510df01200441c8056a2015370300200441c0056a2009370300200441b0056a41086a41063a00002004410c3a00b00541b0b4cc004100200441b0056a10d4010b200a2014844200520d01200441900e6a41186a220c4200370300200441900e6a41106a22074200370300200441900e6a41086a22064200370300200442003703900e41b6fdc600ad428080808080018422091001220b2900002114200441f80d6a41086a2202200b41086a290000370300200420143703f80d200b103520062002290300370300200420042903f80d3703900e41e489c200ad4280808080d0018422141001220b29000021152002200b41086a290000370300200420153703f80d200b1035200720042903f80d2215370300200441b0056a41086a220e2006290300370300200441b0056a41106a22102015370300200441b0056a41186a220d2002290300370300200420042903900e3703b005200441c0006a200441b0056a412010d701200441c0006a41106a2903002115200429034821122004280240210b200c42003703002007420037030020064200370300200442003703900e20091001220c29000021092002200c41086a290000370300200420093703f80d200c103520062002290300370300200420042903f80d3703900e20141001220c29000021092002200c41086a290000370300200420093703f80d200c1035200720042903f80d2209370300200e200629030037030020102009370300200d2002290300370300200420042903900e3703b005200420154200200b1b3703980e200420124200200b1b3703900e200441b0056aad4280808080800484200441900e6aad428080808080028410020c020b200441900e6a41186a220b4200370300200441900e6a41106a22064200370300200441900e6a41086a22024200370300200442003703900e41b6fdc600ad4280808080800184221210012207290000210a200441f80d6a41086a2208200741086a2900003703002004200a3703f80d2007103520022008290300370300200420042903f80d3703900e41e489c200ad4280808080d00184220a1001220729000021132008200741086a290000370300200420133703f80d20071035200620042903f80d2213370300200441b0056a41086a220c2002290300370300200441b0056a41106a220e2013370300200441b0056a41186a22102008290300370300200420042903900e3703b005200441206a200441b0056a412010d701200441206a41106a29030021132004290328211720042802202107200b42003703002006420037030020024200370300200442003703900e20121001220b29000021122008200b41086a290000370300200420123703f80d200b103520022008290300370300200420042903f80d3703900e200a1001220b29000021122008200b41086a290000370300200420123703f80d200b1035200620042903f80d2212370300200c2002290300370300200e201237030020102008290300370300200420042903900e3703b0052004427f2013420020071b2212200920157d2016201454ad7d7c2017420020071b2209201620147d7c22142009542208ad7c22092008200920125420092012511b22081b3703980e2004427f201420081b3703900e200441b0056aad4280808080800484200441900e6aad4280808080800284100241800221080c080b200441b0056a10d004200441b0056a200a201410df010b200420042800af0d3600b70c200420042903a80d3703b00c200420042903b00c3703a00c200420042800b70c3600a70c200420083a00900c200441900c6a41086a20042800a70c360000200420042903a00c3700910c200441800d6a41086a200441800c6a41086a290300370300200420042903800c3703800d41072102410021060240200841ff01714104460d00200441900c6a10d104200441bb056a200441980c6a280200360000200420042903900c3700b30541012106410f21020b200441b0056a20026a220820042903800d370000200841086a200441800d6a41086a290300370000200441b8086a41086a20063a0000200441c1086a20042900b005370000200441c9086a200441b0056a41086a2208290000370000200441d1086a200441b0056a41106a2202290000370000200441b8086a41206a200441c7056a290000370000200441003a00b80841b0b4cc004100200441b8086a10d401200441386a41c4c3c700411010c0012004200428023c41016a410120042802381b22063602b80841c4c3c700ad4280808080800284200441b8086aad4280808080c000841002200420063602dc0d200441003602d80d200441b0056a41186a42003703002002420037030020084200370300200442003703b00541d1c4c700ad4280808080e000841001220629000021092008200641086a290000370300200420093703b005200610354188f2c700ad4280808080e00184100122062900002109200441f80d6a41086a2207200641086a290000370300200420093703f80d20061035200220042903f80d2209370300200441900e6a41086a2008290300370300200441900e6a41106a2009370300200441900e6a41186a2007290300370300200420042903b0053703900e200441203602bc082004200441900e6a3602b808200441d80d6a200441b8086a10cd042000410c6a200441900c6a41086a280200360200200041046a20042903900c370200200041003a00002001450d0820050d010c080b200020042f00b1053b0001200041013a0000200041036a20042d00b3053a000020032802002101410021000c060b200341046a280200450d06200110350c060b41809ccc004119419c9ccc00103f000b103c000b20042f01b20541087420087221080b20044188096a10ba020b200420042903b00c3703a00c200420042800b70c3600a70c200041036a20084110763a0000200020083b0001200041013a000020054521000b20000d002001450d00200341046a280200450d00200110350b200441c00e6a24000bcc0405067f017e017f017e047f230041e0006b22002400200041c4c3c700411010c001200028020421010240200028020022024101470d0041c4c3c700ad428080808080028410070b200041306a41186a22034200370300200041306a41106a22044200370300200041306a41086a220542003703002000420037033041d1c4c700ad4280808080e000842206100122072900002108200041d0006a41086a2209200741086a2900003703002000200837035020071035200520092903003703002000200029035037033041ecedc700ad4280808080e001841001220729000021082009200741086a2900003703002000200837035020071035200420002903502208370300200041106a41086a220a2005290300370300200041106a41106a220b2008370300200041106a41186a220c20092903003703002000200029033037031020002001410020021b360230200041106aad4280808080800484200041306aad4280808080c000841002200041013602082003420037030020044200370300200542003703002000420037033020061001220729000021062009200741086a290000370300200020063703502007103520052009290300370300200020002903503703304188f2c700ad4280808080e001841001220729000021062009200741086a2900003703002000200637035020071035200420002903502206370300200a2005290300370300200b2006370300200c200929030037030020002000290330370310200041203602342000200041106a360230200041086a200041306a10cd04200041e0006a24000b956808047f017e017f027e077f017e057f067e230041c0036b22012400200141a8016a41186a4200370300200141a8016a41106a22024200370300200141a8016a41086a22034200370300200142003703a80141a8e7cb00ad4280808080f00184100122042900002105200141c0026a41086a2206200441086a290000370300200120053703c0022004103520032006290300370300200120012903c0023703a80141b697ca00ad4280808080d001841001220429000021052006200441086a290000370300200120053703c00220041035200220012903c002220537030020014190036a41086a200329030037030020014190036a41106a200537030020014190036a41186a2006290300370300200120012903a80137039003200141203602ac02200120014190036a3602a802200141c0026a20014190036aad220742808080808004842208100510c2010240024020012802c00222030d004102210620014102360284030c010b20012802c40221092001200628020022063602b402200120033602b0020240024020064104490d002001200341046a3602b00220012006417c6a22043602b40220044104490d002003280000210a2001200641786a3602b4022001200341086a3602b0022003280004210b200141a8016a200141b0026a10e80320012802a801220c450d0020012902ac012105410021060240024020012802b402220d0d000c010b2001200d417f6a220e3602b402200120012802b002220f41016a3602b0020240200f2d00004101460d000c010b200e4104490d002001200d417b6a3602b4022001200f41056a3602b002200f2800012104410121060b2001200436028803200120053702fc022001200c3602f8022001200b3602f4022001200a3602f0020c010b200141003602d802200142013703d002200141093602b4032001200141a8026a3602b0032001200141d0026a3602bc02200141bc016a4101360200200142013702ac01200141c888c2003602a8012001200141b0036a3602b801200141bc026a41e88ac500200141a8016a10431a20013502d80242208620013502d002841006024020012802d402450d0020012802d00210350b410221060b20012006360284032009450d00200310350b200141a8016a41106a2203200141f0026a41106a2209280200360200200141a8016a41086a220a200141f0026a41086a220b290300370300200120012903f0023703a8010240024002400240024002400240024020064102460d00200141d0026a41106a20032802002203360200200141d0026a41086a200a2903002210370300200120012903a80122053703d00220092003360200200b201037030020014188036a2004360200200120053703f002200120063602840302402005a722032000470d000240024020064101460d0020012802f4022106200141a8016a200141f0026a41086a10c605200141a0036a200636020020014190036a410c6a200141a8016a41086a22062802003602002001410036029003200120012903a80137029403200141a8016a20014190036a108805200141cb026a2006280200360000200120012903a8013700c302200141a8016a410c6a200141c7026a290000370000200141c6a4b9da043600a901200141023a00a801200120012900c0023700ad01200141a8016a10820420014190036a41086a2802002206450d01200641286c450d0120012802940310350c010b20012802f4022106200141a8016a200141f0026a41086a10c605200141a4036a200636020020014190036a41086a20012903a801370300200141a0036a200141a8016a41086a220628020036020020012004360294032001410136029003200141a8016a20014190036a108805200141cb026a2006280200360000200120012903a8013700c302200141a8016a410c6a200141c7026a290000370000200141c6a4b9da043600a901200141023a00a801200120012900c0023700ad01200141a8016a10820420014190036a410c6a2802002206450d00200641286c450d0020012802980310350b20012802f00221030b024020012802f40220036a2000470d002001200141f8026a220d3602ac01200141003602a80120014180036a28020041286c4105722206417f4c0d02200610332203450d03200341013a000020012006360294032001200336029003200141013602980320012802f8022106200128028003220320014190036a10770240024020030d002001280298032103200128029003210b0c010b2006200341286c6a210c20012802940321092001280298032103034002400240200920036b4120490d00200341206a2104200128029003210b2009210a0c010b200341206a22042003490d072009410174220a2004200a20044b1b220a4100480d070240024020090d000240200a0d004101210b0c020b200a1033220b0d010c0d0b200128029003210b2009200a460d00200b2009200a1037220b450d0c0b2001200a360294032001200b360290030b200b20036a22032006290000370000200341186a200641186a290000370000200341106a200641106a290000370000200341086a200641086a2900003700002001200436029803200641206a290300210502400240200a20046b4108490d00200441086a2103200a21090c010b200441086a22032004490d07200a41017422092003200920034b1b22094100480d0702400240200a0d00024020090d004101210b0c020b20091033220b450d0d0c010b200a2009460d00200b200a20091037220b450d0c0b20012009360294032001200b360290030b200b20046a20053700002001200336029803200c200641286a2206470d000b0b2001280294032106419793ca00ad4280808080c002842003ad422086200bad84100202402006450d00200b10350b024020012802a801450d00200141b0016a2802002206450d00200641286c450d0020012802ac0110350b200141a8016a41086a2206200d290000370300200141a8016a41106a2204200d41086a280000360200200141003602ac012001410b3a00a80141b0b4cc004100200141a8016a10d401200141a8016a41186a220a42003703002004420037030020064200370300200142003703a80141a8e7cb00ad4280808080f00184100122092900002105200141c0026a41086a2203200941086a290000370300200120053703c0022009103520062003290300370300200120012903c0023703a80141b697ca00ad4280808080d001841001220929000021052003200941086a290000370300200120053703c00220091035200220012903c002370000200241086a200329030037000020014190036a41086a200629030037030020014190036a41106a200429030037030020014190036a41186a200a290300370300200120012903a80137039003200810070c010b200141fc026a2802002206450d00200641286c450d0020012802f80210350b200141a8016a41186a22094200370300200141a8016a41106a220a4200370300200141a8016a41086a22034200370300200142003703a80141a8e7cb00ad4280808080f00184100122042900002105200141c0026a41086a2206200441086a290000370300200120053703c0022004103520032006290300370300200120012903c0023703a80141c397ca00ad4280808080d000841001220429000021052006200441086a290000370300200120053703c00220041035200220012903c002370000200241086a200629030037000020014190036a41086a200329030037030020014190036a41106a200a29030037030020014190036a41186a2009290300370300200120012903a80137039003200141203602c402200120014190036a3602c002200141d0026a2008100510c20120012802d0022206450d0520012802d4022104024002400240200141d0026a41086a2802002209450d0020062d0000220a41034b0d0041002103024002400240200a0e0405000102050b2009417f6a4108490d0220062900012105410121030c040b410221030c020b2009417f6a4108490d0020062900012105410321030c020b200141003602f802200142013703f002200141093602b4032001200141c0026a3602b0032001200141f0026a3602b002200141bc016a4101360200200142013702ac01200141c888c2003602a8012001200141b0036a3602b801200141b0026a41e88ac500200141a8016a10431a20013502f80242208620013502f002841006024020012802f402450d0020012802f00210350b410421030b0b02402004450d00200610350b2003417f6a220641024b0d0520060e03040503040b1044000b1045000b103e000b2005422088a7210602402005a722032000470d0020014104360290032001200636029403200141a8016a20014190036a108805200141cb026a200141b0016a280200360000200120012903a8013700c302200141b4016a200141c7026a290000370000200141c6a4b9da043600a901200141023a00a801200120012900c0023700ad01200141a8016a1082040b200620036a2000470d01200141003602f002200141a8016a41186a22094200370300200141a8016a41106a220a4200370300200141a8016a41086a22034200370300200142003703a80141a8e7cb00ad4280808080f00184100122042900002105200141c0026a41086a2206200441086a290000370300200120053703c0022004103520032006290300370300200120012903c0023703a80141c397ca00ad4280808080d000841001220429000021052006200441086a290000370300200120053703c00220041035200220012903c002370000200241086a200629030037000020014190036a41086a200329030037030020014190036a41106a200a29030037030020014190036a41186a2009290300370300200120012903a80137039003200141a8016a200141f0026a10db06200820013502b00142208620012802a8012206ad841002024020012802ac01450d00200610350b200141023602ac012001410b3a00a80141b0b4cc004100200141a8016a10d4010c010b2005422088a7210602402005a722032000470d0020014103360290032001200636029403200141a8016a20014190036a108805200141cb026a200141b0016a280200360000200120012903a8013700c302200141b4016a200141c7026a290000370000200141c6a4b9da043600a901200141023a00a801200120012900c0023700ad01200141a8016a1082040b200620036a2000470d00200141023602f002200141a8016a41186a22094200370300200141a8016a41106a220a4200370300200141a8016a41086a22034200370300200142003703a80141a8e7cb00ad4280808080f00184100122042900002105200141c0026a41086a2206200441086a290000370300200120053703c0022004103520032006290300370300200120012903c0023703a80141c397ca00ad4280808080d000841001220429000021052006200441086a290000370300200120053703c00220041035200220012903c002370000200241086a200629030037000020014190036a41086a200329030037030020014190036a41106a200a29030037030020014190036a41186a2009290300370300200120012903a80137039003200141a8016a200141f0026a10db06200820013502b00142208620012802a8012206ad841002024020012802ac01450d00200610350b200141013602ac012001410b3a00a80141b0b4cc004100200141a8016a10d4010b200141a8016a41186a22044200370300200141a8016a41106a220d4200370300200141a8016a41086a22034200370300200142003703a80141bee4cb00ad4280808080f001842205100122092900002108200141f0026a41086a2206200941086a290000370300200120083703f0022009103520032006290300370300200120012903f0023703a801418cc0c700ad4280808080e000841001220929000021082006200941086a290000370300200120083703f00220091035200d20012903f002220837030020014190036a41086a220a200329030037030020014190036a41106a220b200837030020014190036a41186a220c2006290300370300200120012903a80137039003200141a0016a20014190036a412010c00120012802a401210f024020012802a00122024101470d002007428080808080048410070b20044200370300200d420037030020034200370300200142003703a80120051001220929000021052006200941086a290000370300200120053703f0022009103520032006290300370300200120012903f0023703a80141cde4cb00ad4280808080b001841001220929000021052006200941086a290000370300200120053703f00220091035200d20012903f002370000200d41086a2006290300370000200a2003290300370300200b200d290300370300200c2004290300370300200120012903a801370390030240024020014190036a10bd02220641ff01714102460d0020064101710d010b41041033220a450d01200a4100360200200141a8016a41186a22044200370300200141a8016a41106a22094200370300200141a8016a41086a22034200370300200142003703a80141bee4cb00ad4280808080f0018422051001220b2900002108200141f0026a41086a2206200b41086a290000370300200120083703f002200b103520032006290300370300200120012903f0023703a80141b9e0c600ad4280808080b001841001220b29000021082006200b41086a290000370300200120083703f002200b1035200d20012903f002370000200d41086a220b200629030037000020014190036a41086a220c200329030037030020014190036a41106a2200200929030037030020014190036a41186a220e2004290300370300200120012903a80137039003200141203602ac01200120014190036a3602a801200a4101200141a8016a109503200a103541041033220a450d01200a4100360200200442003703002009420037030020034200370300200142003703a80120051001221129000021082006201141086a290000370300200120083703f0022011103520032006290300370300200120012903f0023703a8014192c0c700ad4280808080c001841001221129000021082006201141086a290000370300200120083703f00220111035200d20012903f002370000200b2006290300370000200c200329030037030020002009290300370300200e2004290300370300200120012903a80137039003200141203602ac01200120014190036a3602a801200a4101200141a8016a109503200a1035200442003703002009420037030020034200370300200142003703a80120051001220a29000021082006200a41086a290000370300200120083703f002200a103520032006290300370300200120012903f0023703a801419ec0c700ad4280808080e000841001220a29000021082006200a41086a290000370300200120083703f002200a1035200d20012903f002370000200b2006290300370000200c200329030037030020002009290300370300200e2004290300370300200120012903a80137039003200141003602a801200742808080808004842208200141a8016aad22104280808080c000841002200442003703002009420037030020034200370300200142003703a80120051001220a29000021052006200a41086a290000370300200120053703f002200a103520032006290300370300200120012903f0023703a80141cde4cb00ad4280808080b001841001220a29000021052006200a41086a290000370300200120053703f002200a1035200d20012903f002370000200b2006290300370000200c200329030037030020002009290300370300200e2004290300370300200120012903a80137039003200141013a00a801200820104280808080108410020b200141a8016a41186a4200370300200141a8016a41106a22124200370300200141a8016a41086a22064200370300200142003703a80141bee4cb00ad4280808080f001841001220329000021052006200341086a290000370300200120053703a8012003103541b9e0c600ad4280808080b00184100122032900002105200141f0026a41086a2204200341086a290000370300200120053703f00220031035201220012903f002220537030020014190036a41086a200629030037030020014190036a41106a200537030020014190036a41186a2004290300370300200120012903a80137039003200141a8016a20014190036a10c5020240024020012802a801220e0d0041002113200141003602c802200142043703c0024104210e410021110c010b200120012902ac0122053702c4022001200e3602c0022005422088a721112005a721130b200141a8016a41186a22094200370300200141a8016a41106a220a4200370300200141a8016a41086a22034200370300200142003703a80141bee4cb00ad4280808080f00184100122042900002105200141f0026a41086a2206200441086a290000370300200120053703f0022004103520032006290300370300200120012903f0023703a8014192c0c700ad4280808080c001841001220429000021052006200441086a290000370300200120053703f00220041035200d20012903f002370000200d41086a200629030037000020014190036a41086a200329030037030020014190036a41106a200a29030037030020014190036a41186a2009290300370300200120012903a80137039003200141a8016a20014190036a10c5020240024020012802a801220a0d0041002114200141003602d802200142043703d0024104210a4100210c0c010b200120012902ac0122053702d4022001200a3602d0022005422088a7210c2005a721140b0240024002400240024020020d002011450d012011410274200e6a417c6a280200210f0b201141002011419c7f6a22062006201141016a4b1b2215490d01200141003602c8022015450d03200e20154102746a2100200e210203402002280200210b02400240024002400240200c41014b0d0041002106200c0e020201020b41002106200c2103034020062003410176220420066a2209200b200a20094102746a280200491b2106200320046b220341014b0d000b0b200b200a200641027422036a2802002204460d022006200b20044b6a21060c010b410021060b200120063602a80141dcc0c700412e200141a8016a418cc1c700419cc1c7001046000b200c20064d0d03200a20036a2203200341046a2006417f73200c6a410274109e081a2001200c417f6a220c3602d802200241046a22022000470d000c040b0b41a4c0c700412641ccc0c7001064000b20152011104f000b2006200c104e000b410021064100210b0240201120156b2203450d0002402015450d00200e200e20154102746a2003410274109e081a0b200120033602c8022003210b0b024002400240200c41014b0d00200c0e020201020b41002106200c2103034020062003410176220420066a2209200f200a20094102746a280200491b2106200320046b220341014b0d000b0b0240200f200a20064102746a2802002203460d002006200f20034b6a21060b200c20064f0d002006200c104d000b0240200c2014470d00200141d0026a2014410110860120012802d002210a0b200a20064102746a220341046a2003200c20066b410274109e081a2003200f3602002001200c41016a22033602d8020240200b2013470d00200141c0026a2013410110860120012802c002210e20012802c802210b0b200e200b4102746a200f3602002001200b41016a220b3602c80202400240024002400240024002402003450d00200341017621062003410171450d01200320064d0d03200a20064102746a28020021000c020b41acc1c70041c30041c086cc00103f000b200320064d0d0220032006417f6a22044d0d03200a20044102746a280200200a20064102746a2802006a41017621000b20012802c4022102200141a8016a41186a22094200370300200141a8016a41106a220a4200370300200141a8016a41086a22044200370300200142003703a80141bee4cb00ad4280808080f0018422051001220c2900002108200141f0026a41086a2206200c41086a290000370300200120083703f002200c103520042006290300370300200120012903f0023703a80141b9e0c600ad4280808080b001841001220c29000021082006200c41086a290000370300200120083703f002200c1035200d20012903f002370000200d41086a220f200629030037000020014190036a41086a2211200429030037030020014190036a41106a2215200a29030037030020014190036a41186a22132009290300370300200120012903a80137039003200141203602ac01200120014190036a3602a801200e200b200141a8016a1095030240200241ffffffff0371450d00200e10350b20012802d402210e20012802d002210220094200370300200a420037030020044200370300200142003703a80120051001220c29000021052006200c41086a290000370300200120053703f002200c103520042006290300370300200120012903f0023703a8014192c0c700ad4280808080c001841001220c29000021052006200c41086a290000370300200120053703f002200c1035200d20012903f002370000200f2006290300370000201120042903003703002015200a29030037030020132009290300370300200120012903a80137039003200141203602ac01200120014190036a3602a80120022003200141a8016a1095030240200e41ffffffff0371450d00200210350b200141a8016a41186a22094200370300200141a8016a41106a22044200370300200141a8016a41086a22034200370300200142003703a80141bee4cb00ad4280808080f001841001220a2900002105200141f0026a41086a2206200a41086a290000370300200120053703f002200a103520032006290300370300200120012903f0023703a801419ec0c700ad4280808080e000841001220a29000021052006200a41086a290000370300200120053703f002200a1035200d20012903f002370000200d41086a200629030037000020014190036a41086a220a200329030037030020014190036a41106a220c200429030037030020014190036a41186a22022009290300370300200120012903a80137039003200120003602a80120074280808080800484200141a8016aad22164280808080c0008410020240200b41e500470d00200942003703002004420037030020034200370300200142003703a80141d1c4c700ad4280808080e000841001220b29000021052003200b41086a290000370300200120053703a801200b103541e7c4c700ad4280808080e000841001220b29000021052006200b41086a290000370300200120053703f002200b1035201220012903f002370000201241086a2006290300370000200a2003290300370300200c200429030037030020022009290300370300200120012903a8013703900320014198016a20014190036a412010c0010b200942003703002004420037030020034200370300200142003703a80141f7edcb00ad4280808080f0008422081001220929000021052006200941086a290000370300200120053703f0022009103520032006290300370300200120012903f0023703a80141eeedcb00ad428080808090018422101001220929000021052006200941086a290000370300200120053703f00220091035200420012903f0022205370300200a2003290300370300200c200537030020022006290300370300200120012903a80137039003200141a8016a20014190036a10ac01024020012903a801427f7c4202540d0020042903002117200141a8016a41186a220a4200370300200141a8016a41106a22094200370300200141a8016a41086a22064200370300200142003703a80141d1efcb00ad42808080809001841001220329000021052006200341086a290000370300200120053703a8012003103541ebc3c400ad428080808030841001220b2900002105200141f0026a41086a2203200b41086a290000370300200120053703f002200b1035200920012903f002220537030020014190036a41086a220c200629030037030020014190036a41106a2202200537030020014190036a41186a22002003290300370300200120012903a8013703900320014188016a20014190036a10e102200141f8006a20012903900142002001280288011b221842e807802219420042e8074200108408200a42003703002009420037030020064200370300200142003703a80120081001220b29000021052003200b41086a290000370300200120053703f002200b103520062003290300370300200120012903f0023703a80120101001220b29000021052003200b41086a290000370300200120053703f002200b1035200420012903f002370000200441086a2003290300370000200c2006290300370300200220092903003703002000200a290300370300200120012903a8013703900320012903782105200141f8006a41086a2903002108410410332206450d05200620173e000020064104410810372206450d05200641013a000420064108411010372206450d0520062005201820194298787e7c42ff07837c2210427f20082010200554ad7c501b370005200742808080808004842006ad4280808080d001841002200610350b200141a8016a41186a220b4200370300200141a8016a41106a22094200370300200141a8016a41086a22034200370300200142003703a80141e3efcb00ad4280808080a00284100122042900002105200141f0026a41086a2206200441086a290000370300200120053703f0022004103520032006290300370300200120012903f0023703a80141f5efcb00ad42808080809002841001220429000021052006200441086a290000370300200120053703f00220041035200920012903f002220537030020014190036a41086a200329030037030020014190036a41106a200537030020014190036a41186a2006290300370300200120012903a80137039003200141e0006a20014190036a10bc02200141e0006a41106a29030021172001290368211920012802602104200141f0026a41186a4200370300200141f0026a41106a220c420037030020064200370300200142003703f00241d1c4c700ad4280808080e000841001220a29000021052006200a41086a290000370300200120053703f002200a10354184eec700ad4280808080b002841001220a2900002105200141c0026a41086a2202200a41086a290000370300200120053703c002200a1035200c20012903c00222053703002003200629030037030020092005370300200b2002290300370300200120012903f0023703a801200141d0006a200141a8016a10e102200141106a2001290358420020012802501b2205428090cad2c60e2005428090cad2c60e5622061b428090cad2c60e200520061b7d420042a0c21e4200108408200141c0006a20012903102208200141106a41086a29030022102008201010dc06200141c0006a41086a290300211a2001290340211b200141306a428080aace938c0942002008201010dc06200141306a41086a290300210820012903302118200141206a428090bcfd024200201b201a10dc062017420020041b21102019420020041b2119200141206a41086a29030021172001290320211a02400240200542ff8fcad2c60e560d0042ffffffffffffffffff00428080808080808080807f201042ffffffffffffffffff00428080808080808080807f200820177d2018201a54ad7d22054200531b200541012008427f552008501b220641012017427f552017501b47200641012005427f552005501b477122061b22087d20192005423f872018201a7d20061b221754ad7d22054200531b200541012010427f552010501b220641012008427f552008501b47200641012005427f552005501b477122061b2208427f2005423f87201920177d20061b2205428080f0c4c5a9d28f72562008427f552008427f511b22061b21082005428080f0c4c5a9d28f7220061b21050c010b42ffffffffffffffffff00428080808080808080807f201042ffffffffffffffffff00428080808080808080807f200820177c2018201a7c221a201854ad7c22054200531b200541012008427f552008501b220641012017427f552017501b46200641012005427f552005501b477122061b22087c20192005423f87201a20061b7c2217201954ad7c22054200531b200541012010427f552010501b220641012008427f552008501b46200641012005427f552005501b477122061b21082005423f87201720061b21050b200141a8016a41186a220a4200370300200141a8016a41106a22044200370300200141a8016a41086a22034200370300200142003703a80141e3efcb00ad4280808080a002841001220b2900002110200141f0026a41086a2206200b41086a290000370300200120103703f002200b103520032006290300370300200120012903f0023703a80141f5efcb00ad42808080809002841001220b29000021102006200b41086a290000370300200120103703f002200b1035200920012903f002370000200941086a200629030037000020014190036a41086a2209200329030037030020014190036a41106a220b200429030037030020014190036a41186a220c200a290300370300200120012903a80137039003200120083703b001200120053703a801200742808080808004842205201642808080808002841002200a42003703002004420037030020034200370300200142003703a8014193d1cb00ad4280808080a0018422081001220229000021102006200241086a290000370300200120103703f0022002103520032006290300370300200120012903f0023703a80141d8c7ca00ad4280808080e000841001220229000021102006200241086a290000370300200120103703f00220021035200420012903f002221037030020092003290300370300200b2010370300200c2006290300370300200120012903a8013703900320051007200a42003703002004420037030020034200370300200142003703a80120081001220229000021082006200241086a290000370300200120083703f0022002103520032006290300370300200120012903f0023703a801419dd1cb00ad4280808080c001841001220229000021082006200241086a290000370300200120083703f00220021035200420012903f002220837030020092003290300370300200b2008370300200c2006290300370300200120012903a8013703900320051007200a42003703002004420037030020034200370300200142003703a80141d1efcb00ad42808080809001841001220a29000021082003200a41086a290000370300200120083703a801200a103541daefcb00ad42808080809001841001220a29000021082006200a41086a290000370300200120083703f002200a1035200420012903f002220837030020092003290300370300200b2008370300200c2006290300370300200120012903a8013703900320014190036a10bd02220641ff01714102460d03200510072006410171450d03200141a8016a41186a4200370300200141a8016a41106a22064200370300200141a8016a41086a22034200370300200142003703a80141a9d1cb00ad4280808080c000841001220429000021052003200441086a290000370300200120053703a8012004103541cde4cb00ad4280808080b00184100122042900002105200141c0026a41086a2209200441086a290000370300200120053703c00220041035200620012903c002220537030020014190036a41086a200329030037030020014190036a41106a200537030020014190036a41186a2009290300370300200120012903a80137039003200141a8016a20014190036a10b702024020012d00a80122034102460d00200742808080808004841007200141d0026a41086a200141b1016a290000370300200141d0026a41106a200141b9016a290000370300200141d0026a41186a200141c1016a290000370300200120012900a9013703d0020240200341037122034103460d0020030e03010001010b200141f0026a41186a200141d0026a41186a290300370300200141f0026a41106a200141d0026a41106a290300370300200141f0026a41086a200141d0026a41086a290300370300200120012903d0023703f002200141a8016a41186a22094200370300200141a8016a41106a220a4200370300200141a8016a41086a22034200370300200142003703a80141a9d1cb00ad4280808080c000841001220429000021052003200441086a290000370300200120053703a8012004103541f0d1cb00ad4280808080c00184100122042900002105200141c0026a41086a220b200441086a290000370300200120053703c00220041035200620012903c002370000200641086a200b29030037000020014190036a41086a200329030037030020014190036a41106a200a29030037030020014190036a41186a2009290300370300200120012903a80137039003200141086a20014190036a412010c00141002109200141a8016a200128020c410020012802081b220a10fe0320014190036a20012802a801220b20012802b00110c3020240024020012802900322040d00200141003602b803200142013703b00341012104410021030c010b200120012902940322053702b403200120043602b0032005422088a721032005a721090b024020012802ac01450d00200b10350b024002402003418002490d00412010332203450d07200320012903f002370000200341186a200141f0026a41186a290300370000200341106a200141f0026a41106a290300370000200341086a200141f0026a41086a290300370000200141a8016a200a41016a220910fe0320012802a8012104200120012802b0013602940320012004360290032003410120014190036a109802024020012802ac01450d00200410350b20031035200141a8016a41186a220a4200370300200141a8016a41106a220b4200370300200141a8016a41086a22034200370300200142003703a80141a9d1cb00ad4280808080c000841001220429000021052003200441086a290000370300200120053703a8012004103541f0d1cb00ad4280808080c00184100122042900002105200141c0026a41086a220c200441086a290000370300200120053703c00220041035200620012903c002370000200641086a200c29030037000020014190036a41086a200329030037030020014190036a41106a200b29030037030020014190036a41186a200a290300370300200120012903a80137039003200120093602a8012007428080808080048420164280808080c000841002200141b0036a21030c010b200141a8016a41186a220b200141f0026a41186a290300370300200141a8016a41106a220c200141f0026a41106a290300370300200141a8016a41086a2202200141f0026a41086a290300370300200120012903f0023703a801024020032009470d00200141b0036a20094101108a0120012802b003210420012802b80321030b200420034105746a220920012903a801370000200941186a200b290300370000200941106a200c290300370000200941086a20022903003700002001200341016a22093602b803200141a8016a200a10fe0320012802a8012103200120012802b0013602940320012003360290032004200920014190036a109802024020012802ac01450d00200310350b200141b0036a21030b200341046a28020041ffffff3f71450d00200328020010350b200141a8016a41186a22094200370300200141a8016a41106a220a4200370300200141a8016a41086a22034200370300200142003703a80141a9d1cb00ad4280808080c000841001220429000021052003200441086a290000370300200120053703a801200410354199c2c300ad4280808080800184100122042900002105200141c0026a41086a220b200441086a290000370300200120053703c00220041035200620012903c002370000200641086a200b29030037000020014190036a41086a200329030037030020014190036a41106a200a29030037030020014190036a41186a2009290300370300200120012903a80137039003200742808080808004841007200141c0036a24000f0b2006200341f0c1c7001042000b200620034180c2c7001042000b200420034190c2c7001042000b41c0c3c400412b41c086cc00103f000b103c000ba41d08047f017e017f017e047f017e047f017e230041e0016b2201240020014190016a41186a2202420037030020014190016a41106a2203420037030020014190016a41086a22044200370300200142003703900141d1c4c700ad4280808080e000842205100122062900002107200141b8016a41086a2208200641086a290000370300200120073703b8012006103520042008290300370300200120012903b801370390014188f2c700ad4280808080e001841001220629000021072008200641086a290000370300200120073703b80120061035200320012903b8012207370300200141f0006a41086a22062004290300370300200141f0006a41106a22092007370300200141f0006a41186a220a20082903003703002001200129039001370370200141f0006aad428080808080048422071007200242003703002003420037030020044200370300200142003703900120051001220b290000210c2008200b41086a2900003703002001200c3703b801200b103520042008290300370300200120012903b8013703900141ecedc700ad4280808080e001841001220b290000210c2008200b41086a2900003703002001200c3703b801200b1035200320012903b801220c370300200620042903003703002009200c370300200a2008290300370300200120012903900137037020071007200242003703002003420037030020044200370300200142003703900120051001220b290000210c2008200b41086a2900003703002001200c3703b801200b103520042008290300370300200120012903b801370390014184eec700ad4280808080b002841001220b290000210c2008200b41086a2900003703002001200c3703b801200b1035200320012903b801220c370300200620042903003703002009200c370300200a2008290300370300200120012903900137037020071007200242003703002003420037030020044200370300200142003703900120051001220b290000210c2008200b41086a2900003703002001200c3703b801200b103520042008290300370300200120012903b8013703900141b8eec700ad42808080808002841001220b290000210c2008200b41086a2900003703002001200c3703b801200b1035200320012903b801220c370300200620042903003703002009200c370300200a2008290300370300200120012903900137037020071007200242003703002003420037030020044200370300200142003703900120051001220b290000210c2008200b41086a2900003703002001200c3703b801200b103520042008290300370300200120012903b8013703900141e7c4c700ad4280808080e000841001220b290000210c2008200b41086a2900003703002001200c3703b801200b1035200320012903b801220c370300200620042903003703002009200c370300200a20082903003703002001200129039001370370200141086a200141f0006a412010c001200128020c210d02402001280208220e4101470d00200710070b200242003703002003420037030020044200370300200142003703900120051001220b29000021052008200b41086a290000370300200120053703b801200b103520042008290300370300200120012903b8013703900141edc4c700ad4280808080a001841001220b29000021052008200b41086a290000370300200120053703b801200b1035200320012903b801370000200341086a20082903003700002006200429030037030020092003290300370300200a20022903003703002001200129039001370370200141b8016a200141f0006a412010d501024002400240024020012d00b80122080d00200141a8016a200141d1016a290000370300200141a0016a200141c9016a29000037030020014198016a200141c1016a290000370300200120012900b901370390010c010b2007100720014190016a41186a2204200141d1016a29000037030020014190016a41106a2202200141c9016a29000037030020014190016a41086a2206200141c1016a290000370300200120012900b9013703900120084101460d010b200141286a4200370300200141206a4200370300200141186a4200370300200142003703100c010b200141106a41186a2004290300370300200141106a41106a2002290300370300200141106a41086a200629030037030020012001290390013703100b20014190016a41186a2206420037030020014190016a41106a2209420037030020014190016a41086a22044200370300200142003703900141d1c4c700ad4280808080e00084100122022900002105200141b8016a41086a2208200241086a290000370300200120053703b8012002103520042008290300370300200120012903b801370390014185c5c700ad4280808080e000841001220229000021052008200241086a290000370300200120053703b80120021035200320012903b801370000200341086a2008290300370000200141f0006a41086a2004290300370300200141f0006a41106a2009290300370300200141f0006a41186a20062903003703002001200129039001370370200141b8016a200141f0006a10ce020240024020012802b801220f0d004100210a20014100360238200142043703304104210f410021100c010b200710072001200f360230200120012902bc0122053702342005422088a7210a2005a721100b200d4100200e1b210620014190016a41186a2202420037030020014190016a41106a2209420037030020014190016a41086a22084200370300200142003703900141d1c4c700ad4280808080e000841001220b2900002105200141b8016a41086a2204200b41086a290000370300200120053703b801200b103520082004290300370300200120012903b8013703900141f7c4c700ad4280808080e001841001220b29000021052004200b41086a290000370300200120053703b801200b1035200320012903b801370000200341086a2004290300370000200141f0006a41086a2008290300370300200141f0006a41106a2009290300370300200141f0006a41186a20022903003703002001200129039001370370200141b8016a200141f0006a412010d501024002400240024020012d00b80122030d002002200141d1016a2900003703002009200141c9016a2900003703002008200141c1016a290000370300200120012900b901370390010c010b200710072002200141d1016a2900003703002009200141c9016a2900003703002008200141c1016a290000370300200120012900b9013703900120034101460d010b200141d8006a4200370300200141d0006a4200370300200141c8006a4200370300200142003703400c010b200141c0006a41186a20014190016a41186a290300370300200141c0006a41106a20014190016a41106a290300370300200141c0006a41086a20014190016a41086a29030037030020012001290390013703400b0240200641fb01490d00200641857e6a2208450d00200141b8016a200810b80320013502c00142208620012802b8012208ad84100720012802bc01450d00200810350b41012109024010232207422088a72202450d002007a721090b41002108200141003a00d801200921030240024002400240034020022008460d01200141b8016a20086a20032d00003a00002001200841016a22043a00d801200341016a21032004210820044120470d000b200141f0006a41186a200141b8016a41186a290300370300200141f0006a41106a200141b8016a41106a290300370300200141f0006a41086a200141b8016a41086a290300370300200120012903b80137037002402002450d00200910350b412010332208450d0220082001290310370000200841186a2204200141106a41186a290300370000200841106a2202200141106a41106a290300370000200841086a2209200141106a41086a290300370000412010332203450d0320032008290000370000200341186a2004290000370000200341106a2002290000370000200341086a200929000037000020081035200141e0006a2003ad4280808080800484102410c20120031035024020012802602204450d00200141e8006a28020021022001280264210b41002108200141003a00d801034020022008460d03200141b8016a20086a200420086a2d00003a00002001200841016a22033a00d8012003210820034120470d000b20014190016a41186a200141b8016a41186a2203290300220737030020014190016a41106a200141b8016a41106a2202290300220537030020014190016a41086a200141b8016a41086a2209290300220c370300200120012903b8012211370390012009200c3703002002200537030020032007370300200141b4016a41026a220d200141ed006a41026a2d00003a0000200120113703b801200120012f006d3b01b4010240200a2010470d00200141306a20104101108d012001280230210f2001280238210a0b200f200a41246c6a220841003a0000200820012903b80137000120032903002107200229030021052009290300210c200820012f01b4013b0021200841236a200d2d00003a0000200841096a200c370000200841116a2005370000200841196a20073700002001200a41016a360238200b450d00200410350b200020012903103700102000200636020020002001290370370030200041286a200141106a41186a290300370000200041206a200141106a41106a290300370000200041186a200141106a41086a290300370000200041386a200141f0006a41086a290300370000200041c0006a200141f0006a41106a290300370000200041c8006a200141f0006a41186a290300370000200041e8006a200141c0006a41186a290300370000200041e0006a200141c0006a41106a290300370000200041d8006a200141c0006a41086a290300370000200020012903403700502000410c6a200141306a41086a28020036020020002001290330370204200141e0016a24000f0b0240200841ff0171450d00200141003a00d8010b41b983c800412c200141b8016a41bccfc70041e883c8001046000b0240200841ff0171450d00200141003a00d8010b41b983c800412c200141b8016a41bccfc70041f883c8001046000b1045000b103c000b160020002001280208360204200020012802003602000bff1001067f230041106b22022400024002400240024002400240024002400240024020012d00000e06010402030500010b2002410036020820024201370300410110332203450d082002410136020420022003360200200341003a000020024101360208200141046a28020021042001410c6a2802002201200210770240024020022802042205200228020822036b2001490d00200228020021060c010b200320016a22062003490d08200541017422072006200720064b1b22074100480d080240024020050d00024020070d00410121060c020b2007103322060d010c0b0b2002280200210620052007460d0020062005200710372206450d0a0b20022007360204200220063602000b200620036a20042001109d081a2002200320016a3602080c050b2002410036020820024201370300410110332203450d072002410136020420022003360200200341023a000020024101360208412010332203450d0520032001290001370000200341186a200141196a290000370000200341106a200141116a290000370000200341086a200141096a2900003700000240024020022802042206417f6a4120490d00200228020021010c010b200641017422014121200141214b1b22054100480d0720022802002101024020062005460d0020012006200510372201450d090b20022005360204200220013602000b20012003290000370001200141196a200341186a290000370000200141116a200341106a290000370000200141096a200341086a29000037000020024121360208200310350c040b2002410036020820024201370300410110332203450d062002410136020420022003360200200341043a0000200241013602080240024020022802042206417f6a4104490d00200228020021030c010b200641017422034105200341054b1b22054100480d0620022802002103024020062005460d0020032006200510372203450d080b20022005360204200220033602000b200320012800013600012002410536020820012802082104200141106a2802002201200210770240024020022802042205200228020822036b2001490d00200228020021060c010b200320016a22062003490d06200541017422072006200720064b1b22074100480d060240024020050d00024020070d00410121060c020b200710332206450d090c010b2002280200210620052007460d0020062005200710372206450d080b20022007360204200220063602000b200620036a20042001109d081a2002200320016a3602080c030b2002410036020820024201370300410110332203450d052002410136020420022003360200200341053a0000200241013602080240024020022802042206417f6a4104490d00200228020021030c010b200641017422034105200341054b1b22054100480d0520022802002103024020062005460d0020032006200510372203450d070b20022005360204200220033602000b200320012800013600012002410536020820012802082104200141106a2802002201200210770240024020022802042205200228020822036b2001490d00200228020021060c010b200320016a22062003490d05200541017422072006200720064b1b22074100480d050240024020050d00024020070d00410121060c020b200710332206450d080c010b2002280200210620052007460d0020062005200710372206450d070b20022007360204200220063602000b200620036a20042001109d081a2002200320016a3602080c020b2002410036020820024201370300410110332203450d042002410136020420022003360200200341063a0000200241013602080240024020022802042206417f6a4104490d00200228020021030c010b200641017422034105200341054b1b22054100480d0420022802002103024020062005460d0020032006200510372203450d060b20022005360204200220033602000b200320012800013600012002410536020820012802082104200141106a2802002201200210770240024020022802042205200228020822036b2001490d00200228020021060c010b200320016a22062003490d04200541017422072006200720064b1b22074100480d040240024020050d00024020070d00410121060c020b200710332206450d070c010b2002280200210620052007460d0020062005200710372206450d060b20022007360204200220063602000b200620036a20042001109d081a2002200320016a3602080c010b2002410036020820024201370300410110332203450d032002410136020420022003360200200341073a00002002410136020820022802002103024020022802044101470d0020034101410210372203450d0420024102360204200220033602000b200341003a0001200241023602082002280200210320022802042106024020012802044101460d00024020064102470d0020034102410410372203450d0520024104360204200220033602000b200341003a0002200241033602080c010b024020064102470d0020034102410410372203450d0420024104360204200220033602000b200341013a000220024103360208200141086a28020021050240024020022802042206417d6a4104490d00200228020021030c010b200641017422034107200341074b1b22044100480d0320022802002103024020062004460d0020032006200410372203450d050b20022004360204200220033602000b20032005360003200241073602082001410c6a2802002106024002402002280204220341796a4104490d00200228020021010c010b20034101742201410b2001410b4b1b22054100480d0320022802002101024020032005460d0020012003200510372201450d050b20022005360204200220013602000b200120063600072002410b3602080b200020022201290200370200200041086a200141086a280200360200200241106a24000f0b1045000b103e000b103c000b8f0201027f20014180feff07714108762102024002402001410171450d00411f210341b0a2cc00210102400240200241ff01710e03000103000b41c100210341efa1cc0021010c020b41c100210341aea1cc0021010c010b411f2103418fa1cc002101024002400240024002400240024002400240200241ff01710e0a00060102030405090708000b4120210341efa0cc0021010c080b41272103418fa0cc0021010c070b4117210341f89fcc0021010c060b41d99fcc0021010c050b4126210341b39fcc0021010c040b412b210341889fcc0021010c030b4139210341b6a0cc0021010c020b413b210341cd9ecc0021010c010b41d100210341fc9dcc0021010b20002003360204200020013602000bc00201037f23004180016b220224002000280200210002400240024002400240200128020022034110710d002000280200210420034120710d012004ad41012001105221000c020b20002802002104410021000340200220006a41ff006a2004410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d022001410141d88bc0004102200220006a4180016a410020006b105621000c010b410021000340200220006a41ff006a2004410f712203413072200341376a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d022001410141d88bc0004102200220006a4180016a410020006b105621000b20024180016a240020000f0b200441800141c88bc0001059000b200441800141c88bc0001059000bb00301027f23004180026b22022400024002402001450d00200220003602000c010b200241b0b4cc003602000b20022001360204200241f8006a200210c4030240200228027c450d00200241086a200241f8006a41f000109d081a200241086a10b7030240200241086a410c6a2802002200450d00200228020c2101200041246c210003400240024020012d0000220341044b0d0002400240024020030e050400010204040b2001410c6a280200450d03200141086a28020010350c030b2001410c6a280200450d02200141086a28020010350c020b2001410c6a280200450d01200141086a28020010350c010b200141086a280200450d00200141046a28020010350b200141246a21012000415c6a22000d000b0b0240200241106a2802002201450d00200141246c450d00200228020c10350b20024180026a240042010f0b200241f4016a41043602002002411c6a41023602002002420237020c200241f0b2c300360208200241043602ec01200241b8b3c3003602e801200241003602fc01200241b0b4cc003602f8012002200241e8016a3602182002200241f8016a3602f001200241086a4180b3c300104c000ba00a03077f037e057f230041d0026b2202240041002103200241003a00c8022001280204417f6a210402400240024002400240024003402004417f460d01200241a8026a20036a200128020022052d00003a0000200120043602042001200541016a3602002002200341016a22053a00c8022004417f6a21042005210320054120470d000b200241e8006a41086a200241a8026a41086a290300370300200241e8006a41106a200241a8026a41106a290300370300200241e8006a41186a200241a8026a41186a290300370300200220022903a8023703682002200110c40120022802000d022002280204210641002104200241003a00c80220012802042107417f2103034020072004460d02200241a8026a20046a200128020022082d00003a00002001200720036a3602042001200841016a3602002002200441016a22053a00c8022003417f6a21032005210420054120470d000b200241a8016a41086a200241a8026a41086a2903002209370300200241a8016a41106a200241a8026a41106a290300220a370300200241a8016a41186a200241a8026a41186a290300220b37030020024188016a41086a200937030020024188016a41106a200a37030020024188016a41186a200b370300200220022903a80222093703a801200220093703880141002104200241003a00c802200720056b210c200720036a21030340200c2004460d04200241a8026a20046a200820046a220541016a2d00003a0000200120033602042001200541026a3602002002200441016a22053a00c8022003417f6a21032005210420054120470d000b200241e8016a41086a200241a8026a41086a2903002209370300200241e8016a41106a200241a8026a41106a290300220a370300200241e8016a41186a200241a8026a41186a290300220b370300200241c8016a41086a22042009370300200241c8016a41106a2203200a370300200241c8016a41186a2205200b370300200220022903a80222093703e801200220093703c801200241a8026a200110cf0220022802a8022201450d04200241c8006a41086a2208200241e8006a41086a290300370300200241c8006a41106a2207200241e8006a41106a290300370300200241c8006a41186a220c200241e8006a41186a290300370300200241286a41086a220d20024188016a41086a290300370300200241286a41106a220e20024188016a41106a290300370300200241286a41186a220f20024188016a41186a29030037030020022002290368370348200220022903880137032820022902ac022109200241086a41186a22102005290300370300200241086a41106a22052003290300370300200241086a41086a22032004290300370300200220022903c801370308200020093702082000200136020420002006360200200041106a2002290348370200200041186a2008290300370200200041206a2007290300370200200041286a200c290300370200200041306a2002290328370200200041386a200d290300370200200041c0006a200e290300370200200041c8006a200f290300370200200041e8006a2010290300370200200041e0006a2005290300370200200041d8006a2003290300370200200041d0006a20022903083702000c050b0240200341ff0171450d00200241003a00c8020b200041003602040c040b0240200441ff0171450d00200241003a00c8020b200041003602040c030b200041003602040c020b0240200441ff0171450d00200241003a00c8020b200041003602040c010b200041003602040b200241d0026a24000bc30202077f017e230041206b22022400200210c60302400240024002402002280208220341046a2204417f4c0d00200228020021050240024020040d0041012106410021040c010b200410332206450d020b2002410036021820022006360210200220043602142003200241106a10770240024020022802142207200228021822046b2003490d00200228021021060c010b200420036a22062004490d03200741017422082006200820064b1b22084100480d030240024020070d00024020080d00410121060c020b2008103322060d010c060b2002280210210620072008460d0020062007200810372206450d050b20022008360214200220063602100b200620046a20052003109d081a200420036aad4220862006ad84210902402002280204450d00200510350b200241206a240020090f0b1044000b1045000b103e000b103c000bbc34010f7f230041d0006b2201240020014100360238200142043703300240410810332202450d002002410c360204200241ba84c800360200200141306a41004101109001200128023020012802384103746a20022902003702002001200128023841016a36023820021035410810332202450d002002410c360204200241c684c800360200200141306a20012802384101109001200128023020012802384103746a20022902003702002001200128023841016a36023820021035410810332202450d0020024108360204200241d284c800360200200141306a20012802384101109001200128023020012802384103746a20022902003702002001200128023841016a36023820021035410810332202450d002002410a360204200241da84c800360200200141306a20012802384101109001200128023020012802384103746a20022902003702002001200128023841016a36023820021035410810332202450d002002410b360204200241e484c800360200200141306a20012802384101109001200128023020012802384103746a20022902003702002001200128023841016a36023820021035410810332202450d0020024118360204200241fcdfc600360200200141306a20012802384101109001200128023020012802384103746a200229020037020020012001280238220341016a22043602382002103520012802342105200128023021062001410036023820014204370330200141306a41002004410374220241037510870120012802382107024020042003490d00200620026a210820012802302007410c6c6a210220062104034020042802002203450d01200241086a200441046a280200360200200241046a2003360200200241003602002002410c6a2102200741016a2107200441086a22042008470d000b0b200120073602380240200541ffffffff0171450d00200610350b200128023421092001280230210a2001410036022820014201370320410410332202450d002001410436022420012002360220200241edcad18b063600002001410436022820012802202102024020012802244104470d0020024104410810372202450d0120014108360224200120023602200b2002410b3a000420014105360228411d200141206a107741ece4c600210b02400340200b2802042105200b2802082203200141206a10770240024020012802242206200128022822086b2003490d0020012802202104200621020c010b200820036a22022008490d02200641017422042002200420024b1b22024100480d020240024020060d00024020020d00410121040c020b2002103322040d010c050b2001280220210420062002460d0020042006200210372204450d040b20012002360224200120043602200b200420086a20052003109d081a2001200820036a220336022802400240200b28020c4102470d000240024020022003460d00200321020c010b200241016a22032002490d04200241017422082003200820034b1b22034100480d040240024020020d0041002102024020030d00410121040c020b200310332204450d070c010b20022003460d0020042002200310372204450d060b20012003360224200120043602200b200420026a41003a00002001200241016a22023602280c010b0240024020022003460d00200321020c010b200241016a22032002490d03200241017422082003200820034b1b22034100480d030240024020020d0041002102024020030d00410121040c020b200310332204450d060c010b20022003460d0020042002200310372204450d050b20012003360224200120043602200b200420026a41013a00002001200241016a36022802400240200b28020c4101470d00200b2802142106200b2802182202200141206a10770240024020012802242208200128022822046b2002490d00200128022021030c010b200420026a22032004490d05200841017422052003200520034b1b22054100480d050240024020080d00024020050d00410121030c020b200510332203450d080c010b2001280220210320082005460d0020032008200510372203450d070b20012005360224200120033602200b200320046a20062002109d081a2001200420026a360228200b28022021020240200b28021c4101470d002002200b280228200141206a107a0c020b2002200b41246a280200200141206a107a0c010b200141306a200b2802101103002001280234210620012802382202200141206a10770240024020012802242208200128022822046b2002490d00200128022021030c010b200420026a22032004490d04200841017422052003200520034b1b22054100480d040240024020080d00024020050d00410121030c020b200510332203450d070c010b2001280220210320082005460d0020032008200510372203450d060b20012005360224200120033602200b200320046a20062002109d081a2001200420026a360228200128024021030240200128023c4101460d0020032001280244200141206a107a0c010b200320012802482202200141206a107a02402002450d00200241d8006c21084100210403400240200320046a220241346a280200450d002002413c6a280200450d00200241386a28020010350b0240200241c4006a280200450d00200241cc006a28020041ffffffff0171450d00200241c8006a28020010350b2008200441d8006a2204470d000b0b20012802442202450d00200241d8006c450d00200310350b200128022821020b2001280224210402400240200b28022c4102470d000240024020042002460d00200128022021040c010b200241016a22042002490d04200241017422032004200320044b1b22034100480d040240024020020d0041002102024020030d00410121040c020b200310332204450d070c010b2001280220210420022003460d0020042002200310372204450d060b20012003360224200120043602200b200420026a41003a00002001200241016a22023602280c010b0240024020042002460d00200128022021040c010b200241016a22042002490d03200241017422032004200320044b1b22034100480d030240024020020d0041002102024020030d00410121040c020b200310332204450d060c010b2001280220210420022003460d0020042002200310372204450d050b20012003360224200120043602200b200420026a41013a00002001200241016a36022802400240200b28022c4101470d00200b2802302104200b2802382202200141206a10772002450d012002412c6c21052004411c6a21020340200241686a280200210c2002416c6a2802002204200141206a10770240024020012802242206200128022822036b2004490d00200128022021080c010b200320046a22082003490d062006410174220d2008200d20084b1b220d4100480d060240024020060d000240200d0d00410121080c020b200d10332208450d090c010b200128022021082006200d460d0020082006200d10372208450d080b2001200d360224200120083602200b200820036a200c2004109d081a2001200320046a360228200241706a200141206a10792002200141206a10762002412c6a2102200541546a22050d000c020b0b200141186a200b28023011030020012802182104200128021c2202200141206a10772002450d002002412c6c21052004411c6a21020340200241686a280200210c2002416c6a2802002204200141206a10770240024020012802242206200128022822036b2004490d00200128022021080c010b200320046a22082003490d052006410174220d2008200d20084b1b220d4100480d050240024020060d000240200d0d00410121080c020b200d10332208450d080c010b200128022021082006200d460d0020082006200d10372208450d070b2001200d360224200120083602200b200820036a200c2004109d081a2001200320046a360228200241706a200141206a10792002200141206a10762002412c6a2102200541546a22050d000b0b200128022821020b2001280224210402400240200b28023c4102470d000240024020042002460d00200128022021040c010b200241016a22042002490d04200241017422032004200320044b1b22034100480d040240024020020d0041002102024020030d00410121040c020b200310332204450d070c010b2001280220210420022003460d0020042002200310372204450d060b20012003360224200120043602200b200420026a41003a00002001200241016a3602280c010b0240024020042002460d00200128022021040c010b200241016a22042002490d03200241017422032004200320044b1b22034100480d030240024020020d0041002102024020030d00410121040c020b200310332204450d060c010b2001280220210420022003460d0020042002200310372204450d050b20012003360224200120043602200b200420026a41013a00002001200241016a3602280240200b28023c4101470d00200b2802402104200b2802482202200141206a10772002450d012002412c6c21052004411c6a21020340200241686a280200210c2002416c6a2802002204200141206a10770240024020012802242206200128022822036b2004490d00200128022021080c010b200320046a22082003490d052006410174220d2008200d20084b1b220d4100480d050240024020060d000240200d0d00410121080c020b200d10332208450d080c010b200128022021082006200d460d0020082006200d10372208450d070b2001200d360224200120083602200b200820036a200c2004109d081a2001200320046a360228200241706a200141206a10762002200141206a10762002412c6a2102200541546a22050d000c020b0b200141106a200b2802401103002001280210210420012802142202200141206a10772002450d002002412c6c21052004411c6a21020340200241686a280200210c2002416c6a2802002204200141206a10770240024020012802242206200128022822036b2004490d00200128022021080c010b200320046a22082003490d042006410174220d2008200d20084b1b220d4100480d040240024020060d000240200d0d00410121080c020b200d10332208450d070c010b200128022021082006200d460d0020082006200d10372208450d060b2001200d360224200120083602200b200820036a200c2004109d081a2001200320046a360228200241706a200141206a10762002200141206a10762002412c6a2102200541546a22050d000b0b02400240200b28024c4101470d00200b280250210e200b2802582202200141206a10772002450d01200241386c210f410021080340200e20086a220241046a280200210c200241086a2802002204200141206a10770240024020012802242205200128022822036b2004490d00200128022021060c010b200320046a22062003490d052005410174220d2006200d20064b1b220d4100480d050240024020050d000240200d0d00410121060c020b200d10332206450d080c010b200128022021062005200d460d0020062005200d10372206450d070b2001200d360224200120063602200b200620036a200c2004109d081a2001200320046a360228200241106a280200210c200241146a2802002204200141206a10770240024020012802242205200128022822036b2004490d00200128022021060c010b200320046a22062003490d052005410174220d2006200d20064b1b220d4100480d050240024020050d000240200d0d00410121060c020b200d10332206450d080c010b200128022021062005200d460d0020062005200d10372206450d070b2001200d360224200120063602200b200620036a200c2004109d081a2001200320046a36022802400240200241186a2802004101470d002002411c6a280200210c200241246a2802002204200141206a10770240024020012802242205200128022822036b2004490d00200128022021060c010b200320046a22062003490d072005410174220d2006200d20064b1b220d4100480d070240024020050d000240200d0d00410121060c020b200d10332206450d0a0c010b200128022021062005200d460d0020062005200d10372206450d090b2001200d360224200120063602200b200620036a200c2004109d081a2001200320046a3602280c010b200141306a2002411c6a280200200241206a28020028020c1102002001280230210520012802382204200141206a1077024002402001280224220c200128022822036b2004490d00200128022021060c010b200320046a22062003490d06200c410174220d2006200d20064b1b220d4100480d0602400240200c0d000240200d0d00410121060c020b200d10332206450d090c010b20012802202106200c200d460d002006200c200d10372206450d080b2001200d360224200120063602200b200620036a20052004109d081a2001200320046a3602282001280234450d00200510350b200241286a200141206a1076200f200841386a2208470d000c020b0b200141086a200b2802501103002001280208210e200128020c2202200141206a10772002450d00200241386c210f410021080340200e20086a220241046a280200210c200241086a2802002204200141206a10770240024020012802242205200128022822036b2004490d00200128022021060c010b200320046a22062003490d042005410174220d2006200d20064b1b220d4100480d040240024020050d000240200d0d00410121060c020b200d10332206450d070c010b200128022021062005200d460d0020062005200d10372206450d060b2001200d360224200120063602200b200620036a200c2004109d081a2001200320046a360228200241106a280200210c200241146a2802002204200141206a10770240024020012802242205200128022822036b2004490d00200128022021060c010b200320046a22062003490d042005410174220d2006200d20064b1b220d4100480d040240024020050d000240200d0d00410121060c020b200d10332206450d070c010b200128022021062005200d460d0020062005200d10372206450d060b2001200d360224200120063602200b200620036a200c2004109d081a2001200320046a36022802400240200241186a2802004101470d002002411c6a280200210c200241246a2802002204200141206a10770240024020012802242205200128022822036b2004490d00200128022021060c010b200320046a22062003490d062005410174220d2006200d20064b1b220d4100480d060240024020050d000240200d0d00410121060c020b200d10332206450d090c010b200128022021062005200d460d0020062005200d10372206450d080b2001200d360224200120063602200b200620036a200c2004109d081a2001200320046a3602280c010b200141306a2002411c6a280200200241206a28020028020c1102002001280230210520012802382204200141206a1077024002402001280224220c200128022822036b2004490d00200128022021060c010b200320046a22062003490d05200c410174220d2006200d20064b1b220d4100480d0502400240200c0d000240200d0d00410121060c020b200d10332206450d080c010b20012802202106200c200d460d002006200c200d10372206450d070b2001200d360224200120063602200b200620036a20052004109d081a2001200320046a3602282001280234450d00200510350b200241286a200141206a1076200f200841386a2208470d000b0b02400240200b28025c4101470d00200b2802602104200b2802682202200141206a10772002450d012002411c6c21052004410c6a21020340200241786a280200210c2002417c6a2802002204200141206a10770240024020012802242206200128022822036b2004490d00200128022021080c010b200320046a22082003490d052006410174220d2008200d20084b1b220d4100480d050240024020060d000240200d0d00410121080c020b200d10332208450d080c010b200128022021082006200d460d0020082006200d10372208450d070b2001200d360224200120083602200b200820036a200c2004109d081a2001200320046a3602282002200141206a10762002411c6a2102200541646a22050d000c020b0b2001200b2802601103002001280200210420012802042202200141206a10772002450d002002411c6c21052004410c6a21020340200241786a280200210c2002417c6a2802002204200141206a10770240024020012802242206200128022822036b2004490d00200128022021080c010b200320046a22082003490d042006410174220d2008200d20084b1b220d4100480d040240024020060d000240200d0d00410121080c020b200d10332208450d070c010b200128022021082006200d460d0020082006200d10372208450d060b2001200d360224200120083602200b200820036a200c2004109d081a2001200320046a3602282002200141206a10762002411c6a2102200541646a22050d000b0b200b41ec006a220b41a8fdc600470d000b02400240200128022420012802282202460d00200128022021040c010b200241016a22042002490d01200241017422032004200320044b1b22034100480d010240024020020d0041002102024020030d00410121040c020b200310332204450d040c010b2001280220210420022003460d0020042002200310372204450d030b20012003360224200120043602200b200420026a41043a00002001200241016a3602282007200141206a107702402007450d002007410c6c2105200a41086a210403402004417c6a280200210c20042802002202200141206a10770240024020012802242206200128022822036b2002490d00200128022021080c010b200320026a22082003490d032006410174220d2008200d20084b1b220d4100480d030240024020060d000240200d0d00410121080c020b200d10332208450d060c010b200128022021082006200d460d0020082006200d10372208450d050b2001200d360224200120083602200b200820036a200c2002109d081a2001200320026a3602282004410c6a2104200541746a22050d000b0b20002001290320370200200041086a200141206a41086a28020036020002402009450d002009410c6c450d00200a10350b200141d0006a24000f0b103e000b103c000bbc0602057f017e230041900b6b22022400024002402001450d00200220003602000c010b200241b0b4cc003602000b20022001360204200241b8076a200210c803024002400240024020022903a0084203510d00200241186a200241b8076a41c803109d081a200241e0036a200241186a41c803109d081a2002200241e0036a3602b807200241a8076a200241b8076a10b90320022802b0072101200241b8076a200241e0036a41c803109d081a200241880b6a20022802b007360200200220022903a8073703800b200241086a200241b8076a2001200241800b6a10bb034101410220022d000822034101461b220010332201450d01200241003602c007200220003602bc07200220013602b8070240024020034101470d00200141013a0000200241013602c007200241086a410172200241b8076a10c90320022802c00721010c010b200141003a0000200241013602c0070240024020022d000c22044104460d00200141013a000141022103200241023602c00702400240024002400240024020040e0400010203000b410021040c030b410121040c020b200241023a00e003410221040c020b200241033a00e0034104210020014102410410372201450d07200141033a0002200220013602b80720024284808080303702bc07200220022d000d22033a00e003024041010d004106210020014103410610372201450d08200241063602bc07200220013602b8070b200120033a000341042103200241043602c00720022d000e21040b200220043a00e0030b024020002003470d0041000d070240200020004101742205200041016a2206200520064b1b2205460d0020012000200510372201450d070b200220053602bc07200220013602b8070b200120036a20043a0000200341017221010c010b200141003a0001410221010b200220013602c0070b20023502b8072107200241900b6a240020072001ad422086840f0b200241246a4104360200200241f4036a4102360200200242023702e403200241f0b2c3003602e0032002410436021c200241d0b3c3003602182002410036020c200241b0b4cc003602082002200241186a3602f0032002200241086a360220200241e0036a4180b3c300104c000b1045000b103c000b103e000bfb1104047f017e037f047e230041c0086b22022400200241286a200110c401024002400240024002400240024020022802280d0020012802042203450d01200128020022042d0000210520012003417f6a3602042001200441016a360200200541ff00714104470d0220054118744118754100480d03420221060c040b200042033703680c050b200042033703680c040b200042033703680c030b20024198076a20011092060240024020022d0098074102460d00200241f0066a41206a20024198076a41206a280200360200200241f0066a41186a20024198076a41186a290300370300200241f0066a41106a20024198076a41106a290300370300200241f0066a41086a20024198076a41086a29030037030020022002290398073703f00620012802042205450d00200128020022042d0000210320012005417f6a3602042001200441016a360200200341024b0d00024002400240024002400240024020030e03000102000b41002103200241003a00f8042005417f6a2107417e21080240034020072003460d01200241b8046a20036a200420036a220941016a2d00003a00002001200520086a3602042001200941026a3602002002200341016a22093a00f8042008417f6a210820092103200941c000470d000b20024180086a41386a200241b8046a41386a290300220637030020024180086a41306a200241b8046a41306a290300220a37030020024180086a41286a200241b8046a41286a290300220b37030020024180086a41206a200241b8046a41206a290300220c37030020024180086a41186a200241b8046a41186a290300220d37030020024188026a41086a200241b8046a41086a29030037030020024188026a41106a200241b8046a41106a29030037030020024188026a41186a200d37030020024188026a41206a200c37030020024188026a41286a200b37030020024188026a41306a200a37030020024188026a41386a2006370300200220022903b804370388022009417f7320056a2105200420096a41016a2104410021030c030b200341ff0171450d06200241003a00f804420221060c070b41002103200241003a00f8042005417f6a2107417e21080240034020072003460d01200241b8046a20036a200420036a220941016a2d00003a00002001200520086a3602042001200941026a3602002002200341016a22093a00f8042008417f6a210820092103200941c000470d000b20024180086a41386a200241b8046a41386a290300220637030020024180086a41306a200241b8046a41306a290300220a37030020024180086a41286a200241b8046a41286a290300220b37030020024180086a41206a200241b8046a41206a290300220c37030020024180086a41186a200241b8046a41186a290300220d37030020024188026a41086a200241b8046a41086a29030037030020024188026a41106a200241b8046a41106a29030037030020024188026a41186a200d37030020024188026a41206a200c37030020024188026a41286a200b37030020024188026a41306a200a37030020024188026a41386a2006370300200220022903b804370388022009417f7320056a210541012103200420096a41016a21040c020b200341ff0171450d05200241003a00f804420221060c060b41002103200241003a00f9042005417f6a2107417e2108034020072003460d02200241b8046a20036a200420036a220941016a2d00003a00002001200520086a3602042001200941026a3602002002200341016a22093a00f9042008417f6a210820092103200941c100470d000b20024188026a200241b8046a41c100109d081a2009417f7320056a2105200420096a41016a2104410221030b200241bf076a20024188026a41c100109d081a2005450d032004310000210b20012005417f6a22083602042001200441016a360200200b50450d01420021060c020b200341ff0171450d02200241003a00f904420221060c030b2008450d012004310001210c20012005417e6a3602042001200441026a3602004202200b420f8386220a4204540d0142012106200c420886200b84420488200a420c88220b4201200b4201561b7e220b200a5a0d010b200241206a200110c40120022802200d0020022802242105200241086a200110f6012002290308a70d00200241086a41106a290300210d2002290310210c20024180086a41206a200241f0066a41206a28020036020020024180086a41186a200241f0066a41186a29030037030020024180086a41106a200241f0066a41106a29030037030020024180086a41086a200241f0066a41086a290300370300200220022903f00637038008200241b8046a200241bf076a41c100109d081a200220022f01ee063b0186020c010b420221060b200241e0016a41086a220420024180086a41086a290300370300200241e0016a41106a220820024180086a41106a290300370300200241e0016a41186a220920024180086a41186a290300370300200241e0016a41206a220720024180086a41206a28020036020020022002290380083703e0012002419f016a200241b8046a41c100109d081a200220022f0186023b019c0120064202510d01200241f8006a41206a2007280200360200200241f8006a41186a2009290300370300200241f8006a41106a2008290300370300200241f8006a41086a2004290300370300200220022903e001370378200241376a2002419f016a41c100109d081a200220022f019c013b01340b200241b8046a200110b90220022802b804210120024188026a200241b8046a41047241ac02109d081a02402001411b460d0020002002290378370300200020033a0024200041206a200241f8006a41206a280200360200200041186a200241f8006a41186a290300370300200041106a200241f8006a41106a290300370300200041086a200241f8006a41086a290300370300200041256a200241376a41c100109d081a200020022f01343b016620004190016a200d37030020004188016a200c37030020004198016a200136020020004180016a2005360200200041f8006a200b3703002000200a370370200020063703682000419c016a20024188026a41ac02109d081a0c020b200042033703680c010b200042033703680b200241c0086a24000bb30301027f230041106b220224000240024020002d00004101460d00200241003a000e20012002410e6a4101107820002d0001220341094b0d010240024002400240024002400240024002400240024020030e0a00010203040506070809000b200241003a000f2002410f6a21000c090b200241013a000f2002410f6a21000c080b200241023a000f2002410f6a21000c070b200241033a000f2002410f6a21000c060b200241043a000f2002410f6a21000c050b200241053a000f2002410f6a21000c040b200241063a000f2002410f6a21000c030b200241073a000f20012002410f6a410110782002200041026a2d00003a000f2002410f6a21000c020b200241083a000f2002410f6a21000c010b200241093a000f2002410f6a21000b20012000410110780c010b200241013a000e20012002410e6a4101107820002d0001220341024b0d0002400240024020030e03000102000b200241003a000e20012002410e6a410110780c020b200241013a000e20012002410e6a410110780c010b200241023a000e20012002410e6a410110782002200041026a2d00003a000e20012002410e6a410110780b200241106a24000be11305047f017e017f017e0b7f23004180026b2202240010bc03200241106a41186a22034200370300200241106a41106a22044200370300200241106a41086a220542003703002002420037031041d1c4c700ad4280808080e000842206100122072900002108200241d0016a41086a2209200741086a290000370300200220083703d0012007103520052009290300370300200220022903d00137031041e7c4c700ad4280808080e00084100122072900002108200241b0016a41086a220a200741086a290000370300200220083703b00120071035200420022903b001220837030020092005290300370300200241d0016a41106a220b2008370300200241d0016a41186a220c200a290300370300200220022903103703d001200241086a200241d0016a412010c00141002107200228020c410020022802081b10bd032003420037030020044200370300200542003703002002420037031020061001220d2900002108200241f0016a41086a220e200d41086a290000370300200220083703f001200d10352005200e290300370300200220022903f00137031041ecedc700ad4280808080e001841001220d2900002108200e200d41086a290000370300200220083703f001200d1035200420022903f001220837030020092005290300370300200b2008370300200c200e290300370300200220022903103703d0012002200241d0016a412010c0012002280204210d2002280200210f200241003602b801200242043703b001200241b0016a4100200d4100200f1b221010870120022802b801211102402010450d0020022802b0012011410c6c6a210d0340200241d0016a200710cb03200241106a20022802d001221220022802d801221310e00202402002280210220f450d002013ad4220862012ad8410070b200741016a210720022902144200200f1b2108200f4101200f1b210f024020022802d401450d00201210350b200d200f360200200d41046a2008370200200d410c6a210d20102007470d000b201120106a21110b20024180016a41086a2011360200200220022903b001220837038001200520113602002002200837031020024190016a200241106a10ba03200241b0016a41186a20024190016a41186a290300370300200241b0016a41106a20024190016a41106a290300370300200a20024190016a41086a29030037030020022002290390013703b001200342003703002004420037030020054200370300200242003703102006100122072900002108200e200741086a290000370300200220083703f001200710352005200e290300370300200220022903f00137031041f7c4c700ad4280808080e00184100122072900002108200e200741086a290000370300200220083703f00120071035200420022903f001370000200441086a200e29030037000020092005290300370300200b2004290300370300200c2003290300370300200220022903103703d001024002400240412010332207450d00200720022903b001370000200741186a200241b0016a41186a290300370000200741106a200241b0016a41106a290300370000200741086a200241b0016a41086a290300370000200241d0016aad42808080808004842007ad4280808080800484100220071035200241106a10be03200241003602b801200242013703b001412010332207450d0020072002290320370000200741186a200241386a290300370000200741106a200241106a41206a290300370000200741086a200241106a41186a29030037000041201033220d450d02200241203602b4012002200d3602b001200d2007290000370000200d41086a200741086a290000370000200d41106a200741106a290000370000200d41186a200741186a290000370000200241203602b80120071035200241106a200241b0016a10e201412010332207450d0020072002290340370000200741186a200241d8006a290300370000200741106a200241d0006a290300370000200741086a200241c8006a2903003700000240024020022802b401221020022802b80122136b4120490d00201341206a210d20022802b001210f201021120c010b201341206a220d2013490d022010410174220f200d200f200d4b1b22124100480d020240024020100d00024020120d004101210f0c020b20121033220f0d010c050b20022802b001210f20102012460d00200f201020121037220f450d040b200220123602b4012002200f3602b0010b200f20136a22132007290000370000201341186a200741186a290000370000201341106a200741106a290000370000201341086a200741086a2900003700002002200d3602b80120071035412010332207450d0020072002290360370000200741186a200241f8006a290300370000200741106a200241f0006a290300370000200741086a200241e8006a29030037000002402012200d6b411f4b0d00200d41206a2213200d490d02201241017422102013201020134b1b22134100480d020240024020120d00024020130d004101210f0c020b20131033220f450d050c010b20122013460d00200f201220131037220f450d040b200220133602b4012002200f3602b0010b200f200d6a220f2007290000370000200f41186a200741186a290000370000200f41106a200741106a290000370000200f41086a200741086a2900003700002002200d41206a3602b80120071035200228021421112002411c6a2802002209200241b0016a10770240024020090d0020022802b801210d20022802b00121050c010b200941246c210e20022802b401210f20022802b8012107201121130340200241d0016a201310c00320022802d001210402400240200f20076b20022802d8012210490d00200720106a210d20022802b0012105200f21120c010b200720106a220d2007490d04200f4101742212200d2012200d4b1b22124100480d0402400240200f0d00024020120d00410121050c020b201210332205450d070c010b20022802b0012105200f2012460d002005200f201210372205450d060b200220123602b401200220053602b0010b200520076a20042010109d081a2002200d3602b801024020022802d401450d00200410350b201341246a21132012210f200d2107200e415c6a220e0d000b0b200dad42208621082005ad210602402009450d00200941246c210d2011210703400240024020072d0000220f41044b0d00024002400240200f0e050400010204040b2007410c6a280200450d03200741086a28020010350c030b2007410c6a280200450d02200741086a28020010350c020b2007410c6a280200450d01200741086a28020010350c010b200741086a280200450d00200741046a28020010350b200741246a2107200d415c6a220d0d000b0b200820068421080240200241186a2802002207450d00200741246c450d00201110350b20024180026a240020080f0b1045000b103e000b103c000bfc0403027f017e057f230041d0006b2202240041d1c4c700ad4280808080e00084100122032900002104200241086a41086a200341086a290000370300200220043703082003103541e8eec700ad4280808080d00184100122032900002104200241186a41086a200341086a2900003703002002200437031820031035200220013602342002200241346aad4280808080c000841003220329000037033820031035200241cc006a200241386a3602002002200241386a41086a3602442002200241346a3602482002200241386a360240200241286a200241c0006a107b02400240024002402002280230220541206a2206417f4c0d00200228022821070240024020060d0041002101410121030c010b200610332203450d02200621010b024002402001410f4d0d00200121080c010b200141017422084110200841104b1b22084100480d03024020010d002008103322030d010c050b20012008460d0020032001200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821010c010b200841017422014120200141204b1b22014100480d0320082001460d0020032008200110372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200141606a2005490d00200121080c010b200541206a22082005490d03200141017422092008200920084b1b22084100480d0320012008460d0020032001200810372203450d040b200341206a20072005109d081a2000200636020820002008360204200020033602000240200228022c450d00200710350b200241d0006a24000f0b1044000b1045000b103e000b103c000be82709017f017e017f017e017f017e0f7f017e0b7f230041b0056b22022400024002402001450d00200220003602200c010b200241b0b4cc003602200b20022001360224200241186a200241206a10c4010240024020022802180d00200228021c21012002200241206a36029005200241003a00f802200241003602a804200241003602a0042002200136025c200241003602582002200241f8026a360264200220024190056a360260200241d8006a200241a0046a10cd03200241b8036a41086a20022802a8042201360200200220022903a00422033703b80320022d00f8022100200241d8006a41086a22042001360200200220033703582000450d01200241d8006a10a0020b200241ac046a4104360200200241ec006a41023602002002420237025c200241f0b2c300360258200241043602a404200241e8b3c3003602a004200241003602bc03200241b0b4cc003602b8032002200241a0046a3602682002200241b8036a3602a804200241d8006a4180b3c300104c000b200241286a41086a20042802002201360200200220022903582203370328200241386a41086a2001360200200220033703382002410036025020024208370348200241d8006a200241386a10ce0302400240024020022802584101460d00200241d8006a41086a290300210342002105200241f8026a41186a4200370300200241f8026a41106a22064200370300200241f8026a41086a22014200370300200242003703f80241d1efcb00ad42808080809001841001220029000021072001200041086a290000370300200220073703f8022000103541ebc3c400ad4280808080308410012200290000210720024198036a41086a2204200041086a2900003703002002200737039803200010352006200229039803220737030020024190056a41086a200129030037030020024190056a41106a200737030020024190056a41186a2004290300370300200220022903f80237039005200241086a20024190056a10e1022002280208210020022903102107200241c8006a410010a901200228024822082002280250220441c8036c6a220141033602980120014202370368200141a0016a2003200742dc0b7c42dc0b20001b220720032007561b3703002002200441016a22093602504104210a02402002280238220b450d00200228023c210c200b210d0340200d41086a2100200d2f0106220e4103742101410021040240024003402001450d0141f495ca002000410810a008220f450d02200141786a2101200441016a2104200041086a2100200f417f4a0d000b2004417f6a210e0b200c450d02200c417f6a210c200d200e4102746a41e4016a280200210d0c010b0b2002200d2004410c6c6a220141e8006a2802003602a4042002200141e0006a2802003602a004200241d8006a200241a0046a10cf032002280258220a450d02200229025c21050b2005422088a7210e2005a721100c020b200241a8046a200241e4006a2902003703002002200229025c3703a0044184c8c4004128200241a0046a41ecc7c40041acc8c4001046000b4104210a4100210e410021100b200241003602b003200242043703a8030240024002400240024002400240200e450d00200241d8006a41186a220c4200370300200241d8006a41106a22114200370300200241d8006a41086a220f4200370300200242003703584193d1cb00ad4280808080a00184100122012900002103200f200141086a290000370300200220033703582001103541e0caca00ad4280808080e0008410012201290000210320024198036a41086a2200200141086a2900003703002002200337039803200110352011200229039803220337030020024190056a41086a200f29030037030020024190056a41106a200337030020024190056a41186a20002903003703002002200229035837039005200241d8006a20024190056a10b60220022802582201410420011b2112200229025c420020011b2203a721130240024002402003422088a72214450d002012201441c4006c22016a210d200141bc7f6a210420122101034020012d00002100200241d8006a200141016a41c300109d081a20004102460d01200241f8026a41186a200c290000370300200241f8026a41106a2011290000370300200241f8026a41086a200f290000370300200220022900583703f80220004101460d02200441bc7f6a2104200141c4006a2201200d470d000b0b2002410036028003200242013703f8022013450d01201341c4006c450d01201210350c010b20024190056a41086a2200200241f8026a41086a29030037030020024190056a41106a220f200241f8026a41106a29030037030020024190056a41186a220c200241f8026a41186a290300370300200220022903f80222033703b8032002200337039005412010332215450d042015200229039005370000201541186a200c290300370000201541106a200f290300370000201541086a2000290300370000200242818080801037029c03200220153602980302402004450d00200141c4006a2100201441c4006c20126a41bc7f6a211641012114034020002101034020012d00002100200241d8006a200141016a41c300109d081a20004102460d02200241f8026a41186a2204200241d8006a41186a290000370300200241f8026a41106a220f200241d8006a41106a290000370300200241f8026a41086a220c200241d8006a41086a290000370300200220022900583703f802024020004101460d00200141c4006a2201200d470d010c030b0b20024190056a41086a200c290300220337030020024190056a41106a200f290300220537030020024190056a41186a20042903002207370300200220022903f802221737039005200241b8036a41186a220f2007370300200241b8036a41106a220c2005370300200241b8036a41086a22182003370300200220173703b80302402014200228029c03470d0020024198036a20144101108a0120022802980321150b200141c4006a2100201520144105746a220420022903b803370000200441186a200f290300370000200441106a200c290300370000200441086a20182903003700002002201441016a22143602a00320162001470d000b0b02402013450d00201341c4006c450d00201210350b200241f8026a41086a20024198036a41086a28020036020020022002290398033703f8020b200a200e41f0006c6a2115200241a0046a41106a2119200241a0046a41086a211a41d1c4c700ad4280808080e0008421054104211b4104211c4104211d4100211e200a210f0340200f280204210d200f2802002104200241d8006a200f41086a41e800109d081a200f41f0006a210f200d450d02200241b8036a200241d8006a41e800109d081a2002200d3602a404200220043602a004201a200241b8036a41e800109d081a200241d8006a41186a22164200370300200241d8006a41106a22184200370300200241d8006a41086a220c4200370300200242003703582005100122012900002103200c200141086a290000370300200220033703582001103541e7c4c700ad4280808080e0008410012201290000210320024198036a41086a2200200141086a2900003703002002200337039803200110352011200229039803370000201141086a200029030037000020024190056a41086a221f200c29030037030020024190056a41106a2220201829030037030020024190056a41186a222120162903003703002002200229035837039005200220024190056a412010c001200228020021012002280204210020024190056a200241a0046a10d003024002402004417f6a220e2000410020011b22014f0d00200241d8006a200e10d103200241d8006a2019412010a0080d00200441002001417b6a2200200020014b1b490d002002280280032222410574211220024190056a20022802f802220e6b21144100210102400340024020122001470d00410021130c020b4101211320142001460d01200e20016a2100200141206a2101200020024190056a412010a0080d000b0b200241d8006a200410d103200241d8006a20024190056a412010a008210120130d002001450d0020024190056a200241a0046a10d003200241d8006a200241a0046a41f000109d081a0240201e20022802ac03470d00200241a8036a201e410110930120022802b003211e20022802a803221b211c201b211d0b201d201e41f0006c6a200241d8006a41f000109d081a2002201e41016a221e3602b0032016202129030037030020182020290300370300200c201f29030037030020022002290390053703580240202220022802fc02470d00200241f8026a20224101108a0120022802f802210e20022802800321220b200e20224105746a22012002290358370000200141186a2016290300370000200141106a2018290300370000200141086a200c2903003700002002202241016a36028003201e410a470d01410a211e0c040b024020022802ac042201450d00200141246c2100200d210103400240024020012d0000220441044b0d0002400240024020040e050400010204040b2001410c6a280200450d03200141086a28020010350c030b2001410c6a280200450d02200141086a28020010350c020b2001410c6a280200450d01200141086a28020010350c010b200141086a280200450d00200141046a28020010350b200141246a21012000415c6a22000d000b0b20022802a8042201450d00200141246c450d00200d10350b200f2015470d000b2015210f0c010b2010450d01201041f0006c450d01200a10350c010b02402015200f460d000340200f220141046a220010b103200141f0006a210f0240200141086a2802002201450d00200141246c450d00200028020010350b2015200f470d000b0b02402010450d00201041f0006c450d00200a10350b024020022802fc0241ffffff3f71450d0020022802f80210350b0240201e0d0020022802ac032201450d01200141f0006c450d01201b10350c010b201c450d0020022902ac03210302402009200228024c470d00200241c8006a200910a90120022802482108200228025021090b2008200941c8036c6a200241a0046a41e800109d0822014202370368200141a0016a20033703002001419c016a201c3602002001410436029801200120022903b803370370200141f8006a200241c0036a29030037030020014180016a200241c8036a29030037030020014188016a200241d0036a29030037030020014190016a200241d8036a290300370300200141a8016a200241d8006a41a002109d081a2002200941016a22093602500b0240200b450d00200228023c210d0340200b41086a2100200b2f0106220c4103742101410021040240024003402001450d0141fc95ca002000410810a008220f450d02200141786a2101200441016a2104200041086a2100200f417f4a0d000b2004417f6a210c0b200d450d02200d417f6a210d200b200c4102746a41e4016a280200210b0c010b0b200b41e0006a2004410c6c6a22012802084104490d002001280200280000210f200241f8026a41186a22044200370300200241f8026a41106a220d4200370300200241f8026a41086a22014200370300200242003703f80241bee4cb00ad4280808080f001841001220029000021032001200041086a290000370300200220033703f8022000103541b9e0c600ad4280808080b0018410012200290000210320024198036a41086a220c200041086a2900003703002002200337039803200010352006200229039803370000200641086a200c29030037000020024190056a41086a200129030037030020024190056a41106a200d29030037030020024190056a41186a2004290300370300200220022903f80237039005200241d8006a20024190056a10c50220022802582201410420011b2104410021000240200229025c420020011b2203422088a72201450d00200141027420046a417c6a2201450d002001280200200f4721000b0240200342ffffffff0383500d00200410350b2000450d0002402009200228024c470d00200241c8006a200910a90120022802482108200228025021090b2008200941c8036c6a200241a0046a41e800109d0822014202370368200120022903b803370370200141f8006a200241c0036a29030037030020014180016a200241c8036a29030037030020014188016a200241d0036a29030037030020014190016a200241d8036a2903003703002001419c016a200f3602002001410e36029801200141a8016a200241d8006a41a002109d081a2002200941016a22093602500b200228024c2114200241386a10a002200941c8036c4104722201417f4c0d01200110332200450d00200241003602a804200220013602a404200220003602a0042009200241a0046a10770240024020090d0020022802a804210020022802a004210e0c010b200941c8036c211320022802a404210420022802a80421012008210d03402002200d3602b803200241d8006a200241b8036a10b9032002280258211202400240200420016b2002280260220c490d002001200c6a210020022802a004210e2004210f0c010b2001200c6a22002001490d052004410174220f2000200f20004b1b220f4100480d050240024020040d000240200f0d004101210e0c020b200f1033220e0d010c080b20022802a004210e2004200f460d00200e2004200f1037220e450d070b2002200f3602a4042002200e3602a0040b200e20016a2012200c109d081a200220003602a8040240200228025c450d00201210350b200d41c8036a210d200f210420002101201341b87c6a22130d000b0b2000ad4220862103200ead210502402009450d00200941c8036c210020084198016a21010340200110bb02200141c8036a2101200041b87c6a22000d000b0b2003200584210302402014450d00201441c8036c450d00200810350b200241b0056a240020030f0b1045000b1044000b103e000b103c000bd40505067f017e047f017e027f23004180026b22022400024002400240024002402000280200220320002802044f0d00200028020c2104200141086a2105200241a0016a4102722106024003402000200341016a360200200241186a2000280208280200220710ee0220022d00184101460d0120022900192108200241086a200710c40120022802080d012007280204200228020c2203490d012003417f4c0d0302400240024020030d0041002107410121090c010b200310392209450d0820072802042003490d01200920072802002003109d081a2007280204220a2003490d062007200a20036b3602042007200728020020036a360200200321070b20022008370310024002402001280200220b450d002001280204210c0c010b2006410041da00109f081a200241186a4100418401109f081a41e4011033220b450d074100210c200b4100360200200b41046a200241a0016a41dc00109d081a200b41e0006a200241186a418401109d081a200141003602042001200b3602000b2003ad4220862007ad84210d024002400340200b41086a2107200b2f0106220e41037421034100210a024003402003450d01200241106a2007410810a008220f450d03200341786a2103200a41016a210a200741086a2107200f417f4a0d000b200a417f6a210e0b0240200c450d00200c417f6a210c200b200e4102746a41e4016a280200210b0c010b0b2002200837022c200220053602282002200e360224200220013602202002200b36021c200241003602182002200d3702a401200220093602a001200241186a200241a0016a1082030c010b200b200a410c6c6a220341e4006a2207280200210a2007200d370200200341e0006a22072802002103200720093602002003450d00200a450d00200310350b200028020022032000280204490d010c030b0b200910350b200441013a00000b20024180026a24000f0b1044000b2003200a41a4f0cb001059000b103c000b1045000b8c0201067f02400240024020012802002202450d00200128020421030340200241086a210420022f010622054103742101410021060240024003402001450d0141f8eecb002004410810a0082207450d02200141786a2101200641016a2106200441086a21042007417f4a0d000b2006417f6a21050b2003450d022003417f6a2103200220054102746a41e4016a28020021020c010b0b200241e0006a2006410c6c6a22012802084108490d01200041086a2001280200290000370300200041003602000f0b200041003602042000410c6a4128360200200041086a4180efcb003602000c010b200041003602042000410c6a4129360200200041086a41a8efcb003602000b200041013602000bf80303037f017e057f230041e0026b22022400200241086a200110c40102400240024002402002280208450d00200041003602000c010b200228020c2203200128020441f0006e2204200420034b1bad42f0007e2205422088a70d012005a72206417f4c0d010240024020060d00410421070c010b200610332207450d030b4100210420024100360218200220073602102002200641f0006e360214024002402003450d00200241f0016a41086a21080340200241f0016a200110c40320022802f401210620022802f001210920024188016a200841e800109d081a2006450d02200241206a20024188016a41e800109d081a024020042002280214470d00200241106a2004410110930120022802102107200228021821040b2007200441f0006c6a220a2006360204200a2009360200200a41086a200241206a41e800109d081a2002200441016a22043602182003417f6a22030d000b0b20002002290310370200200041086a200241106a41086a2802003602000c010b2000410036020002402004450d00200441f0006c2106200741046a21040340200410b1030240200441046a280200220a450d00200a41246c450d00200428020010350b200441f0006a2104200641907f6a22060d000b0b20022802142204450d00200441f0006c450d00200710350b200241e0026a24000f0b1044000b1045000b9b0902097f037e230041206b220224002002410036020820024201370300024002400240412010332203450d0020032001290010370000200341186a2204200141286a290000370000200341106a2205200141206a290000370000200341086a2206200141186a290000370000412010332207450d02200241203602042002200736020020072003290000370000200741086a2006290000370000200741106a2005290000370000200741186a200429000037000020024120360208200310352001200210e201412010332203450d0020032001290030370000200341186a200141c8006a290000370000200341106a200141c0006a290000370000200341086a200141386a2900003700000240024020022802042208200228020822066b4120490d00200641206a210720022802002104200821050c010b200641206a22072006490d02200841017422042007200420074b1b22054100480d020240024020080d00024020050d00410121040c020b2005103322040d010c050b2002280200210420082005460d0020042008200510372204450d040b20022005360204200220043602000b200420066a22062003290000370000200641186a200341186a290000370000200641106a200341106a290000370000200641086a200341086a2900003700002002200736020820031035412010332203450d0020032001290050370000200341186a200141e8006a290000370000200341106a200141e0006a290000370000200341086a200141d8006a2900003700000240200520076b411f4b0d00200741206a22062007490d02200541017422082006200820064b1b22064100480d020240024020050d00024020060d00410121040c020b200610332204450d050c010b20052006460d0020042005200610372204450d040b20022006360204200220043602000b200420076a22042003290000370000200441186a200341186a290000370000200441106a200341106a290000370000200441086a200341086a2900003700002002200741206a36020820031035200128020421052001410c6a2802002201200210770240024020010d002002280208210320022802042104200228020021080c010b200141246c210920022802042107200228020821010340200241106a200510c0032002280210210a02400240200720016b20022802182206490d00200120066a210320022802002108200721040c010b200120066a22032001490d04200741017422042003200420034b1b22044100480d040240024020070d00024020040d00410121080c020b200410332208450d070c010b2002280200210820072004460d0020082007200410372208450d060b20022004360204200220083602000b200820016a200a2006109d081a2002200336020802402002280214450d00200a10350b200541246a210520042107200321012009415c6a22090d000b0b2003ad4220862008ad8410092201290000210b200141086a290000210c200141106a290000210d200041186a200141186a290000370000200041106a200d370000200041086a200c3700002000200b3700002001103502402004450d00200810350b200241206a24000f0b1045000b103e000b103c000bb90603027f017e057f23004180016b2202240041d1c4c700ad4280808080e00084100122032900002104200241306a41086a200341086a290000370300200220043703302003103541dec4c700ad4280808080900184100122032900002104200241d0006a41086a200341086a2900003703002002200437035020031035200220013602742002200241f4006aad4280808080c000841003220329000037037820031035200241146a200241f8006a3602002002200241f8006a41086a36020c2002200241f4006a3602102002200241f8006a360208200241c0006a200241086a107b02400240024002402002280248220541206a2206417f4c0d00200228024021070240024020060d0041002101410121030c010b200610332203450d02200621010b024002402001410f4d0d00200121080c010b200141017422084110200841104b1b22084100480d03024020010d002008103322030d010c050b20012008460d0020032001200810372203450d040b20032002290330370000200341086a200241306a41086a2903003700000240024020084170714110460d00200821010c010b200841017422014120200141204b1b22014100480d0320082001460d0020032008200110372203450d040b20032002290350370010200341186a200241d0006a41086a29030037000002400240200141606a2005490d00200121080c010b200541206a22082005490d03200141017422092008200920084b1b22084100480d0320012008460d0020032001200810372203450d040b200341206a20072005109d081a02402002280244450d00200710350b200241086a2003200610d501200241d0006a41086a2201200241116a290000370300200241d0006a41106a2206200241196a290000370300200241d0006a41186a2205200241216a290000370300200220022900093703500240024020022d00084101460d0020004200370000200041186a4200370000200041106a4200370000200041086a42003700000c010b20002002290350370000200041186a2005290300370000200041106a2006290300370000200041086a20012903003700000b02402008450d00200310350b20024180016a24000f0b1044000b1045000b103e000b103c000bac2508077f017e0d7f017e017f027e017f037e230041f0026b22022400024002402001450d00200220003602180c010b200241b0b4cc003602180b2002200136021c200241f8006a200241186a10b6030240024002400240024002400240200228027c2203450d00200241f0016a2802002104200241ec016a2802002105200241e8016a2802002106200241f8006a410c6a28020021072002280280012108200241106a200241186a10c4010240024020022802100d00200228021421012002200241186a360250200241003a0020200241003602980220024100360290022002200136027c200241003602782002200241206a360284012002200241d0006a36028001200241f8006a20024190026a10cd03200241e0006a41086a20022802980222013602002002200229039002220937036020022d00202100200241f8006a41086a220a2001360200200220093703782000450d01200241f8006a10a0020b20024190026a410c6a41043602002002418c016a41023602002002420237027c200241f0b2c300360278200241043602940220024184b4c3003602900220024100360264200241b0b4cc00360260200220024190026a360288012002200241e0006a36029802200241f8006a4180b3c300104c000b200241306a41086a200a2802002201360200200220022903782209370330200241c0006a41086a200136020020022009370340200241013b015c2002410036025820024100360250024002402004450d002006200441c8036c6a210b200241d0006a41086a210c200241e0006a410472210d20024190026a410272210e200241f8006a41106a210f200621100340201041e8006a2903004202520d0102400240024002400240201028029801221141034722120d00024002400240024020022802402213450d0020102903a0012109200228024421140340201341086a210020132f0106221541037421014100210a0240024003402001450d01418799cc002000410810a0082216450d02200141786a2101200a41016a210a200041086a21002016417f4a0d000b200a417f6a21150b2014450d022014417f6a2114201320154102746a41e4016a28020021130c010b0b0240201341e0006a200a410c6c6a220128020841074b0d002017428080808070834229842109418f99cc0021140c020b200942b8178020012802002900002217510d034131211841e8c1c30021140c020b201742808080807083421c84210941b899cc0021140b2009a721180b0240024020022d005d450d0041c4c6ca002101413121000c010b200241d0006a10a0022002410036025820024100360250200242e2c289abb68edbb7f40037036020024190026a410272410041da00109f081a200241f8006a4100418401109f081a41e40110332216450d1020164100360200201641046a20024190026a41dc00109d081a201641e0006a200241f8006a418401109d081a200241003602542002201636025020162f010622104103742113417f210041002101024002400340024020132001470d00201021000c020b200241e0006a201620016a41086a410810a008220a450d02200141086a2101200041016a2100200a41004e0d000b0b200242e2c289abb68edbb7f40037028c012002200c3602880120022000360284012002201636027c200241003602782002200241d0006a3602800120024190026a2014201810d303200241f8006a20024190026a10820320024180023b015c200241206a41086a200241d0006a41086a290300370300200220022903503703200c0a0b41f5c6ca002101412d21000b2002200036027c200220013602784181c6ca004122200241f8006a41a4c6ca0041b4c6ca001046000b20120d0020102903a0012109200241f8006a200241c0006a10ce03024002400240024020022802784101460d002002290380012119200241f8006a41186a220a4200370300200f4200370300200241f8006a41086a220142003703002002420037037841d1efcb00ad428080808090018410012200290000211a2001200041086a2900003703002002201a3703782000103541ebc3c400ad4280808080308410012200290000211a200241e0006a41086a2216200041086a2900003703002002201a37036020001035200f2002290360370000200f41086a201629030037000020024190026a41086a200129030037030020024190026a41106a200f29030037030020024190026a41186a200a2903003703002002200229037837039002200220024190026a10e1022009201942b0ea017c560d012009200229030842dc0b7c42dc0b20022802001b22195a0d032019422088211a420021090c020b2002290380012219422088211a200228027c221bad4220864201842109201c4280808080708320023502880184221c211d0c010b201d428080808070832018ad84211d41e9eac400ad21194225211a420121094100211b0b2002201d3703702002201a422086201942ffffffff0f8384221e3703682002201bad422086200942ffffffff0f838437036002400240024020022d005d450d0041c4c6ca002101413121000c010b0240024002402009a722154101470d00200241d0006a10a0022002410036025820024100360250200242f4d2b59bc7ae98b8303703200c010b20022802502113200242f4d2b59bc7ae98b8303703202013450d00200228025421140c010b200e410041da00109f081a200241f8006a4100418401109f081a41e40110332213450d124100211420134100360200201341046a20024190026a41dc00109d081a201341e0006a200241f8006a418401109d081a20024100360254200220133602500b2019a72112201aa7211102400340201341086a210020132f0106221841037421014100210a024003402001450d01200241206a2000410810a0082216450d03200141786a2101200a41016a210a200041086a21002016417f4a0d000b200a417f6a21180b02402014450d002014417f6a2114201320184102746a41e4016a28020021130c010b0b200242f4d2b59bc7ae98b83037028c012002200c3602880120022018360284012002201336027c200241003602782002200241d0006a360280014101103321010240201541014622160d002001450d13200141003a000020014101410910372201450d132001201e3700014109210a410921000c030b2001450d12200141013a000020024190026a200d10b40320022802900221140240024020022802980222130d004101210a201341016a21000c010b201341016a22002013490d1020004102200041024b1b220a4100480d1020014101200a10372201450d130b200141016a20142013109d081a200228029402450d02201410350c020b41f5c6ca002101412d21000b2002200036027c200220013602784181c6ca004122200241f8006a41a4c6ca0041b4c6ca001046000b20022000360298022002200a360294022002200136029002200241f8006a20024190026a108203200220093c005d200241003a005c20160d022015450d00201b450d002011450d00201210350b20102802980121110b20114104470d03201041a4016a280200410b490d032002410d36026820024192c8ca003602642002410036026020022d005d450d0141c4c6ca002101413121000c020b200241206a41086a200241d0006a41086a29030037030020022002290350370320201b450d052011450d05201210350c050b200241d0006a10a0022002410036025820024100360250200242f5dc8de3d6ec9c983037032020024190026a410272410041da00109f081a200241f8006a4100418401109f081a41e40110332216450d0b4100210120164100360200201641046a20024190026a41dc00109d081a201641e0006a200241f8006a418401109d081a200241003602542002201636025020162f010622144103742113417f2100024002400340024020132001470d00201421000c020b200241206a201620016a41086a410810a008220a450d02200141086a2101200041016a2100200a417f4a0d000b0b200242f5dc8de3d6ec9c983037028c012002200c3602880120022000360284012002201636027c200241003602782002200241d0006a36028001410110332201450d0c200141003a000020024190026a200241e0006a10b40320022802900221160240024020022802980222000d0041012113200041016a210a0c010b200041016a220a2000490d0a200a4102200a41024b1b22134100480d0a20014101201310372201450d0d0b200141016a20162000109d081a0240200228029402450d00201610350b2002200a3602880220022013360284022002200136028002200241f8006a20024180026a10820320024180023b015c200241206a41086a200241d0006a41086a290300370300200220022903503703200c050b41f5c6ca002101412d21000b2002200036027c200220013602784181c6ca004122200241f8006a41a4c6ca0041b4c6ca001046000b201041c8036a2210200b470d000b0b200241206a41086a200241d0006a41086a290300370300200220022903503703200b200241c0006a10a00202402007450d00200741246c21002003210103400240024020012d0000220a41044b0d00024002400240200a0e050400010204040b2001410c6a280200450d03200141086a28020010350c030b2001410c6a280200450d02200141086a28020010350c020b2001410c6a280200450d01200141086a28020010350c010b200141086a280200450d00200141046a28020010350b200141246a21012000415c6a22000d000b0b02402008450d00200841246c450d00200310350b02402004450d00200441c8036c210020064198016a21010340200110bb02200141c8036a2101200041b87c6a22000d000b0b02402005450d00200541c8036c450d00200610350b200241003602682002420137036020022d002c2100410110332201450d062002410136026420022001360260200120003a00002002410136026820022d002d210020014101410210372201450d062002410236026420022001360260200120003a00012002410236026820022802282200200241e0006a1077024020022802202201450d00024020022802242216450d002016210a20012113034020132802e4012113200a417f6a220a0d000b2001210a0340200a200a2f01064102746a41e4016a280200210a2016417f6a22160d000b200241f8006a2116201321010c030b200241f8006a21162001210a0c020b410021012002410036027c200241f8006a21160c020b200241ec006a4104360200200241a4026a41023602002002420237029402200241f0b2c300360290022002410436026420024184b4c30036026020024100360254200241b0b4cc003602502002200241e0006a3602a0022002200241d0006a36026820024190026a4180b3c300104c000b2002200a36027c20024184016a200a2f01063602002002410036028001200241003602780b20024190026a41086a201641086a29020022093703002002201629020022173703900220024190016a200937030020024200370380012002200136027c20024100360278200220173703880120022000360298012000450d01034020022000417f6a36029801200241f8006a410020011b2213280200210a20132802082114024002400240201328020c2216201328020422002f01064f0d00200021010c010b0240034020002802002201450d01200a41016a210a20002f0104211620012100201620012f0106490d020c000b0b2014ad2109410021010c010b2016ad4220862014ad8421090b2009422088a7221441016a21162009a7211802400240200a0d00200121000c010b200120164102746a41e4016a280200210041002116200a417f6a220a450d00034020002802e4012100200a417f6a220a0d000b0b2013201636020c2013201836020820132000360204201341003602000240024020022802642216200228026822006b4108490d002002280260210a0c010b200041086a220a2000490d0220164101742213200a2013200a4b1b22134100480d020240024020160d00024020130d004101210a0c020b20131033220a0d010c070b2002280260210a20162013460d00200a201620131037220a450d060b200220133602642002200a3602600b200a20006a200120144103746a41086a2900003700002002200041086a360268200141e0006a2014410c6c6a2201280200211320012802082201200241e0006a10770240024020022802642216200228026822006b2001490d002002280260210a0c010b200020016a220a2000490d0220164101742214200a2014200a4b1b22144100480d020240024020160d00024020140d004101210a0c020b20141033220a450d070c010b2002280260210a20162014460d00200a201620141037220a450d060b200220143602642002200a3602600b200a20006a20132001109d081a2002200020016a22013602682002280298012200450d03200228027c21010c000b0b103e000b200228026821012002280260210a0b200241206a10a002200241f0026a24002001ad422086200aad840f0b103c000bac0401057f024002400240200241046a2203417f4c0d0002400240024002400240024002400240024002402003450d00200310332204450d0b200241c000490d04200241808001490d052002418080808004490d0620030d010b41012103410110332204450d07200441033a0000410521050c010b200441033a000002402003417f6a41034d0d00200321050c020b200341017422064105200641054b1b22054100480d0720032005460d010b20042003200510372204450d050b20042002360001410521060c030b024020030d0041012103410110332204450d040b200420024102743a000041012106200321050c020b02400240200341014d0d00200321050c010b200341017422064102200641024b1b2105024020030d002005103322040d010c040b20032005460d0020042003200510372204450d030b41022106200420024102744101723b00000c010b02400240200341034d0d00200321050c010b200341017422064104200641044b1b22054100480d03024020030d002005103322040d010c030b20032005460d0020042003200510372204450d020b20042002410274410272360000410421060b0240200520066b2002490d00200521030c050b200620026a22032006490d01200541017422072003200720034b1b22034100480d0120052003460d04200420052003103722040d040b103c000b103e000b1044000b1045000b200420066a20012002109d081a2000200620026a36020820002003360204200020043602000bbf0101067f230041206b22022400200241b0b4cc00410010d50302400240412010332203450d0020032002290300370000200341186a2204200241186a290300370000200341106a2205200241106a290300370000200341086a2206200241086a290300370000412010332207450d0120072003290000370000200741186a2004290000370000200741106a2005290000370000200741086a200629000037000020031035200241206a24002007ad42808080808004840f0b1045000b103c000be51b06037f017e077f017e277f027e230041a00d6b220324002003200236020c20032001360208200341206a41186a22044200370300200341206a41106a22024200370300200341206a41086a220142003703002003420037032041d1c4c700ad4280808080e000841001220529000021062001200541086a290000370300200320063703202005103541e7c4c700ad4280808080e00084100122072900002106200341106a41086a2205200741086a2900003703002003200637031020071035200220032903102206370300200341800d6a41086a22082001290300370300200341800d6a41106a22092006370300200341800d6a41186a220a2005290300370300200320032903203703800d2003200341800d6a412010c0012003280204210b2003280200210c200442003703002002420037030020014200370300200342003703204182e9ca00ad42808080808003841001220729000021062001200741086a2900003703002003200637032020071035419ae9ca00ad4280808080e001841001220729000021062005200741086a29000037030020032006370310200710352002200329031022063703002008200129030037030020092006370300200a2005290300370300200320032903203703800d200341206a200341800d6a412010b50220032802202201410120011b210d0240024002402003290224420020011b220e422088a722020d0020004200370000200041186a4200370000200041106a4200370000200041086a42003700000c010b200341206a410041e00c109f081a200b417f6a41d100704130200c1b2101200d41206a210f200d20024105746a21104100211141002112410021134100211441002115410021164100211741002118410021194100211a4100211b4100211c4100211d4100211e4100211f410021204100212141002122410021234100212441002125410021264100212741002128410021294100212a4100212b4100212c4100212d4100212e4100212f4100210b200d21024100213041d1002131024003402030210720022105024002402001450d00200141016a2101200521020340024020102002470d00200d21020b2002220541206a21022001417f6a22010d000b20050d010c030b024020052010460d00200541206a21020c010b200f2102200d21050b0240024002400240200328020c220141056a2204417f4c0d00200328020821320240024020040d00410021044101210c0c010b20041033220c450d020b200341003602182003200c36021020032004360214024020040d0041011033220c450d08200341013602142003200c3602100b200c20073a0000200341013602182001200341106a10770240024020032802142233200328021822306b2001490d00200328021021042033210c0c010b203020016a22042030490d032033410174220c2004200c20044b1b220c4100480d030240024020330d000240200c0d00410121040c020b200c103322040d010c0a0b200328021021042033200c460d0020042033200c10372204450d090b2003200c360214200320043602100b200420306a20322001109d081a2003203020016a2230360218412010332201450d0120012005290000370000200141186a2232200541186a290000370000200141106a2234200541106a290000370000200141086a2235200541086a29000037000002400240200c20306b411f4d0d00200c21330c010b203041206a22052030490d03200c41017422332005203320054b1b22334100480d0302400240200c0d00024020330d00410121040c020b203310332204450d0a0c010b200c2033460d002004200c203310372204450d090b20032033360214200320043602100b200420306a22052001290000370000200541186a2032290000370000200541106a2034290000370000200541086a20352900003700002003203041206a2205360218200110352005ad4220862004ad84100922012900002106200141086a2900002136200141106a2900002137200a200141186a2900003703002009203737030020082036370300200320063703800d2001103502402033450d00200410350b2031417f6a2131200741016a2130200341206a20074103704105746a220120032903800d370000200141186a200a290300370000200141106a2009290300370000200141086a20082903003700004100210503402007200741036e2204417d6c6a4102470d04200341206a20056a220141df006a2d0000220b2001411f6a2d0000220c71200b200c722001413f6a2d000071722128200141de006a2d0000220b2001411e6a2d0000220c71200b200c722001413e6a2d000071722127200141dd006a2d0000220b2001411d6a2d0000220c71200b200c722001413d6a2d000071722126200141dc006a2d0000220b2001411c6a2d0000220c71200b200c722001413c6a2d000071722125200141db006a2d0000220b2001411b6a2d0000220c71200b200c722001413b6a2d000071722124200141da006a2d0000220b2001411a6a2d0000220c71200b200c722001413a6a2d000071722123200141d9006a2d0000220b200141196a2d0000220c71200b200c72200141396a2d000071722122200141d8006a2d0000220b200141186a2d0000220c71200b200c72200141386a2d000071722121200141d7006a2d0000220b200141176a2d0000220c71200b200c72200141376a2d000071722120200141d6006a2d0000220b200141166a2d0000220c71200b200c72200141366a2d00007172211f200141d5006a2d0000220b200141156a2d0000220c71200b200c72200141356a2d00007172211e200141d4006a2d0000220b200141146a2d0000220c71200b200c72200141346a2d00007172211d200141d3006a2d0000220b200141136a2d0000220c71200b200c72200141336a2d00007172211c200141d2006a2d0000220b200141126a2d0000220c71200b200c72200141326a2d00007172211b200141d1006a2d0000220b200141116a2d0000220c71200b200c72200141316a2d00007172211a200141d0006a2d0000220b200141106a2d0000220c71200b200c72200141306a2d000071722119200141cf006a2d0000220b2001410f6a2d0000220c71200b200c722001412f6a2d000071722118200141ce006a2d0000220b2001410e6a2d0000220c71200b200c722001412e6a2d000071722117200141cd006a2d0000220b2001410d6a2d0000220c71200b200c722001412d6a2d000071722116200141cc006a2d0000220b2001410c6a2d0000220c71200b200c722001412c6a2d000071722115200141cb006a2d0000220b2001410b6a2d0000220c71200b200c722001412b6a2d000071722114200141ca006a2d0000220b2001410a6a2d0000220c71200b200c722001412a6a2d000071722113200141c9006a2d0000220b200141096a2d0000220c71200b200c72200141296a2d000071722112200141c8006a2d0000220b200141086a2d0000220c71200b200c72200141286a2d000071722111200141c7006a2d0000220b200141076a2d0000220c71200b200c72200141276a2d000071722129200141c6006a2d0000220b200141066a2d0000220c71200b200c72200141266a2d00007172212a200141c5006a2d0000220b200141056a2d0000220c71200b200c72200141256a2d00007172212b200141c4006a2d0000220b200141046a2d0000220c71200b200c72200141246a2d00007172212c200141c3006a2d0000220b200141036a2d0000220c71200b200c72200141236a2d00007172212d200141c2006a2d0000220b200141026a2d0000220c71200b200c72200141226a2d00007172212e200141c1006a2d0000220b200141016a2d0000220c71200b200c72200141216a2d00007172212f200141c0006a2d0000220b20012d0000220c71200b200c72200141206a2d00007172210b200541800c460d04200341206a20052004410574200741096e41e0006c6b6a6a220141ff006a20283a0000200141fe006a20273a0000200141fd006a20263a0000200141fc006a20253a0000200141fb006a20243a0000200141fa006a20233a0000200141f9006a20223a0000200141f8006a20213a0000200141f7006a20203a0000200141f6006a201f3a0000200141f5006a201e3a0000200141f4006a201d3a0000200141f3006a201c3a0000200141f2006a201b3a0000200141f1006a201a3a0000200141f0006a20193a0000200141ef006a20183a0000200141ee006a20173a0000200141ed006a20163a0000200141ec006a20153a0000200141eb006a20143a0000200141ea006a20133a0000200141e9006a20123a0000200141e8006a20113a0000200141e7006a20293a0000200141e6006a202a3a0000200141e5006a202b3a0000200141e4006a202c3a0000200141e3006a202d3a0000200141e2006a202e3a0000200141e1006a202f3a0000200141e0006a200b3a000020042107200541e0006a220541e00c470d000c040b0b1044000b1045000b103e000b4100210120310d000b0b200020283a001f200020273a001e200020263a001d200020253a001c200020243a001b200020233a001a200020223a0019200020213a0018200020203a00172000201f3a00162000201e3a00152000201d3a00142000201c3a00132000201b3a00122000201a3a0011200020193a0010200020183a000f200020173a000e200020163a000d200020153a000c200020143a000b200020133a000a200020123a0009200020113a0008200020293a00072000202a3a00062000202b3a00052000202c3a00042000202d3a00032000202e3a00022000202f3a00012000200b3a00000b0240200e42ffffff3f83500d00200d10350b200341a00d6a24000f0b103c000b925303097f087e047f230041a0136b220224000240024020010d0020022001360254200241b0b4cc003602500c010b2002200136025420022001417f6a360254200220003602502002200041016a36025020002d0000220341034f0d00200241a80b6a200241d0006a10c80302400240024002400240024002400240024020022903900c4203510d0020024190016a200241a80b6a41c803109d081a200241d8046a20024190016a41c803109d081a2002200241d8046a3602a008200241a80b6a200241a0086a10b90320022802b00b2100024020022802ac0b450d0020022802a80b10350b200241a80b6a200241d8046a41c803109d081a200241a0086a200241a80b6a10d70341012101024020022d00a0084101460d00200241a80b6a200241a0086a41086a2201418003109d081a200241f00e6a200241f80b6a220410d8030240024020022903c80b4202520d00200241800f6a41206a22014200370300200241800f6a41186a22054280808080c000370300200241013a00a80f200242043703900f2002427f3703880f200242003703800f200241a0086a41206a22064200370300200241a0086a41186a22074280808080c000370300200241013a00c808200242043703b0082002427f3703a808200242003703a008200241e0106a200241800f6a200241a0086a10d903200241800f6a41286a2208200241e0106a41286a2903003703002001200241e0106a41206a2903003703002005200241e0106a41186a290300370300200241800f6a41106a2209200241e0106a41106a290300370300200241800f6a41086a220a200241e0106a41086a290300370300200220022903e0103703800f2006420037030020074280808080c000370300200241013a00c808200242043703b0082002427f3703a808200242003703a00820024190116a200241800f6a200241a0086a10d903200820024190116a41286a290300370300200120024190116a41206a290300370300200520024190116a41186a290300370300200920024190116a41106a290300370300200a20024190116a41086a29030037030020022002290390113703800f2006420037030020074280808080c000370300200241013a00c808200242043703b0082002427f3703a808200242003703a008200241c0116a200241800f6a200241a0086a10d9032008200241c0116a41286a2903003703002001200241c0116a41206a2903003703002005200241c0116a41186a2903003703002009200241c0116a41106a290300370300200a200241c0116a41086a290300370300200220022903c0113703800f2006420037030020074280808080c000370300200241013a00c808200242043703b0082002427f3703a808200242003703a008200241f0116a200241800f6a200241a0086a10d9032008200241f0116a41286a2903003703002001200241f0116a41206a2903003703002005200241f0116a41186a2903003703002009200241f0116a41106a290300370300200a200241f0116a41086a290300370300200220022903f0113703800f20022903f00e210b200241d0126a20022d00f80e2201200010da03024002400240024020022903d012220ca741ff01714101460d00200241e00f6a41186a4200370300200241e00f6a41106a22064200370300200241e00f6a41086a22004200370300200242003703e00f41d1c4c700ad4280808080e0008410012205290000210c2000200541086a2900003703002002200c3703e00f200510354184eec700ad4280808080b0028410012205290000210c20024188136a41086a2207200541086a2900003703002002200c37038813200510352006200229038813220c370300200241c00f6a41086a2000290300370300200241c00f6a41106a200c370300200241c00f6a41186a2007290300370300200220022903e00f3703c00f2002200241c00f6a10e102200228020021002002290308210d02400240200141024b0d004280b0def7d32b210c20010e03010004010b4280c0a8ca9a3a210c0b41800c2105200b42c0b2cd3b7c220e200b540d01200d420020001b220d200e7c220e200d540d01200e200c560d014200210c20024181136a21000240024020010e03000105000b200b210c0c040b427f210c0c030b200c420888a721050b20022802900f21060240200241980f6a2802002200450d002000410c6c21012006210003400240200041046a280200450d00200028020010350b2000410c6a2100200141746a22010d000b0b0240200241940f6a2802002200450d002000410c6c450d00200610350b200228029c0f21060240200241a40f6a2802002200450d002000410c6c21012006210003400240200041046a280200450d00200028020010350b2000410c6a2100200141746a22010d000b0b0240200241a00f6a2802002200450d002000410c6c450d00200610350b41010d030c080b4200210c20024181136a21000b200241a0086a41206a22014200370300200241a0086a41186a22054280808080c000370300200220002800003602b80f2002200041036a2800003600bb0f200241cc086a20022800bb0f360000200241013a00c808200242043703b0082002427f3703a8082002200c3703a008200220022802b80f3600c908200241a0126a200241800f6a200241a0086a10d903200241800f6a41286a200241a0126a41286a290300370300200241800f6a41206a200241a0126a41206a290300370300200241800f6a41186a200241a0126a41186a290300370300200241800f6a41106a200241a0126a41106a290300370300200241800f6a41086a200241a0126a41086a290300370300200220022903a0123703800f2001420037030020054280808080c000370300200241013a00c808200242043703b0082002427f3703a808200242003703a008200241d0126a200241800f6a200241a0086a10d903200241bc106a200241d0126a41086a290300370200200220022903d0123702b41041000d01200241e4126a2802002105200241d0126a41186a2802002101200241d0126a41206a2802002106200241f4126a280200210720022802e012210820022802ec12210920022903f812210b0c060b200241800f6a41206a22034200370300200241800f6a41186a22064280808080c000370300200241013a00a80f200242043703900f427f210b2002427f3703880f200242003703800f200241a0086a41206a22074200370300200241a0086a41186a22054280808080c000370300200241013a00c808200242043703b0082002427f3703a808200242003703a00820024180106a200241800f6a200241a0086a10d903200241800f6a41286a220820024180106a41286a290300370300200320024180106a41206a290300370300200620024180106a41186a290300370300200241800f6a41106a220920024180106a41106a290300370300200241800f6a41086a220a20024180106a41086a29030037030020022002290380103703800f2007420037030020054280808080c000370300200241013a00c808200242043703b0082002427f3703a808200242003703a008200241b0106a200241800f6a200241a0086a10d9032008200241b0106a41286a2903003703002003200241b0106a41206a2903003703002006200241b0106a41186a2903003703002009200241b0106a41106a290300370300200a200241b0106a41086a290300370300200220022903b0103703800f20054200370300200241a0086a41106a2206420037030020014200370300200242003703a00841d1c4c700ad4280808080e0008410012203290000210c2001200341086a2900003703002002200c3703a0082003103541e7c4c700ad4280808080e0008410012203290000210c200241a0126a41086a2208200341086a2900003703002002200c3703a01220031035200620022903a012220c370300200241d0126a41086a2001290300370300200241d0126a41106a2201200c370300200241d0126a41186a22032008290300370300200220022903a0083703d012200241c8006a200241d0126a412010c001200228024c410020022802481bad210c024020022903c80b4201520d0020022903d00b220b4200510d04200c200241d80b6a290300220d200d200c541b220e200b7c200e200d7d200b827d210b0b2007420037030020054280808080c000370300200241013a00c808200242043703b008200242003703a00820024200200b200c7d220c200c200b561b3703a808200241e0106a200241800f6a200241a0086a10d903200241d0126a41286a200241e0106a41286a290300370300200241d0126a41206a200241e0106a41206a2903003703002003200241e0106a41186a2903003703002001200241e0106a41106a290300370300200241d0126a41086a200241e0106a41086a290300370300200220022903e0103703d01220022903f00e210b20022802e00b2101200241a0126a200241a80b6a108e02200241a0086a20022802a012220520022802a812108f02200241e8086a280200410020022903a0084201511b2103024020022802a412450d00200510350b024002400240200320014b0d00410c10332206450d0d410410332205450d0b20054104412010372205450d0d200520022903a80b370000200541186a200241a80b6a41186a290300370000200541106a200241a80b6a41106a290300370000200541086a200241a80b6a41086a2903003700002005412041c00010372205450d0d20052001360020200642c0808080c004370204200620053602000240024020032001490d0041002101410421050c010b410c10332205450d0e410410332203450d0c20034104412010372203450d0e200320022903a80b370000200341186a200241a80b6a41186a290300370000200341106a200241a80b6a41106a290300370000200341086a200241a80b6a41086a2903003700002003412041c00010372203450d0e20032001417f6a360020200542c0808080c00437020420052003360200410121010b200241800f6a41206a2203428180808010370300200241800f6a41186a22072001360200200241940f6a2001360200200220022800f0113602e00f2002200241f0116a41036a2800003600e30f200241ac0f6a20022800e30f360000200241013a00a80f2002200636029c0f200220053602900f2002427f3703880f2002200b3703800f200220022802e00f3600a90f20024190116a200241d0126a200241800f6a10d903200241800f6a41286a20024190116a41286a290300370300200320024190116a41206a290300370300200720024190116a41186a290300370300200241800f6a41106a20024190116a41106a290300370300200241800f6a41086a20024190116a41086a29030037030020022002290390113703800f4180122101024020022d00f80e22054102460d00200241d0126a2005200010da03024020022903d012220ca741ff01714101460d00200241e00f6a41186a4200370300200241e00f6a41106a22064200370300200241e00f6a41086a22014200370300200242003703e00f41d1c4c700ad4280808080e0008410012203290000210c2001200341086a2900003703002002200c3703e00f200310354184eec700ad4280808080b0028410012203290000210c20024188136a41086a2207200341086a2900003703002002200c37038813200310352006200229038813220c370300200241c00f6a41086a2001290300370300200241c00f6a41106a200c370300200241c00f6a41186a2007290300370300200220022903e00f3703c00f200241386a200241c00f6a10e1020240200b42c0b2cd3b7c220c200b540d00200229034042002002290338a71b220d200c7c220c200d5a0d040b20022002280081133602b80f200220024184136a2800003600bb0f41800c21010c040b200c420888a721010b20022002280081133602b80f200220024181136a41036a2800003600bb0f0c020b200220022800f0113602e00f2002200241f3116a2800003600e30f200241003a005b20024180063b0059200241013a005820022802e01221050240200241e8126a2802002200450d002000410c6c21012005210003400240200041046a280200450d00200028020010350b2000410c6a2100200141746a22010d000b0b0240200241e4126a2802002200450d002000410c6c450d00200510350b20022802ec1221050240200241f4126a2802002200450d002000410c6c21012005210003400240200041046a280200450d00200028020010350b2000410c6a2100200141746a22010d000b0b200241f0126a2802002200450d082000410c6c450d08200510350c080b20022002280081133602b80f200220024184136a2800003600bb0f41800c2101200c4280c0a8ca9a3a4280b0def7d32b20051b580d050b200241013a0058200220013b0059200220014110763a005b20022802900f21050240200241980f6a2802002200450d002000410c6c21012005210003400240200041046a280200450d00200028020010350b2000410c6a2100200141746a22010d000b0b0240200241940f6a2802002200450d002000410c6c450d00200510350b200228029c0f21050240200241a40f6a2802002200450d002000410c6c21012005210003400240200041046a280200450d00200028020010350b2000410c6a2100200141746a22010d000b0b200241a00f6a2802002200450d062000410c6c450d06200510350c060b200241013a0058200220053b0059200220054110763a005b0c050b200220022d00a3083a005b200220022f00a1083b0059200241013a00580c050b2002419c016a4104360200200241ec046a4102360200200242023702dc04200241f0b2c3003602d80420024104360294012002419cb4c30036029001200241003602a408200241b0b4cc003602a008200220024190016a3602e8042002200241a0086a36029801200241d8046a4180b3c300104c000b41809ccc004119419c9ccc00103f000b200241a0086a41206a4200370300200241a0086a41186a4280808080c000370300200241a0086a412c6a20022800bb0f360000200241013a00c808200242043703b0082002427f3703a8082002427f200b20051b3703a008200220022802b80f3600c908200241c0116a200241800f6a200241a0086a10d903200241a0126a41286a200241c0116a41286a290300370300200241a0126a41206a200241c0116a41206a290300370300200241a0126a41186a200241c0116a41186a290300370300200241a0126a41106a200241c0116a41106a290300370300200241a0126a41086a200241c0116a41086a290300370300200220022903c0113703a012200241286a2000200b20022d00f90e20022903e80b220d200241f00b6a290300220e10db03024002402002290328220b200241286a41086a290300220c84500d0041002100200241003a00b80f2002200c3703e80f2002200b3703e00f200241014111200d200e84501b3a009f132002200241a80b6a360288132002200241a80b6a3602c00f2002200241c00f6a3602b00820022002419f136a3602ac08200220024188136a3602a8082002200241b80f6a3602a4082002200241e00f6a3602a008200241800f6a200241a80b6a200241a0086a10dc030240024020022802800f4101470d004200210e20022903880f210d410121000c010b200241a80f6a290300210e200241a00f6a290300210d20022903880f4201520d00200241800f6a41106a290300210f20022802c00f2101200241d8086a200241800f6a41186a290300370300200241d0086a200f37030041002100200241a0086a41086a41003a0000200241a9086a2001290000370000200241b1086a200141086a290000370000200241b9086a200141106a290000370000200241c1086a200141186a290000370000200241033a00a00841b0b4cc004100200241a0086a10d4010b20000d01200241e00f6a41186a22064200370300200241e00f6a41106a22054200370300200241e00f6a41086a22014200370300200242003703e00f41b6fdc600ad4280808080800184220f10012203290000211020024188136a41086a2200200341086a2900003703002002201037038813200310352001200029030037030020022002290388133703e00f41e489c200ad4280808080d0018422101001220329000021112000200341086a29000037030020022011370388132003103520052002290388132211370300200241c00f6a41086a22072001290300370300200241c00f6a41106a22082011370300200241c00f6a41186a22092000290300370300200220022903e00f3703c00f200241106a200241c00f6a412010d701200241106a41106a29030021112002290318211220022802102103200642003703002005420037030020014200370300200242003703e00f200f10012206290000210f2000200641086a2900003703002002200f37038813200610352001200029030037030020022002290388133703e00f201010012206290000210f2000200641086a2900003703002002200f37038813200610352005200229038813220f370300200720012903003703002008200f37030020092000290300370300200220022903e00f3703c00f200242002011420020031b220f200e7d2012420020031b220e200d54ad7d2210200e200d7d220d200e562010200f562010200f511b22001b3703a80820024200200d20001b3703a008200241c00f6aad4280808080800484200241a0086aad428080808080028410020b200241d0126a41206a4200370300200241d0126a41186a4280808080c000370300200241d0126a412c6a20024184136a280000360000200241013a00f812200242043703e01220022002280081133600f9122002427f3703d8122002200b427f200c501b3703d012200241f0116a200241a0126a200241d0126a10d903200241d8006a41086a20022903f011370300200241d8006a41106a200241f0116a41086a290300370300200241d8006a41186a200241f0116a41106a290300370300200241d8006a41206a200241f0116a41186a290300370300200241d8006a41286a200241f0116a41206a29030037030020024188016a200241f0116a41286a290300370300200241003a00580c020b200241003a005b20024180023b0059200241013a005820022802b01221050240200241b8126a2802002200450d002000410c6c21012005210003400240200041046a280200450d00200028020010350b2000410c6a2100200141746a22010d000b0b0240200241b4126a2802002200450d002000410c6c450d00200510350b20022802bc1221050240200241c4126a2802002200450d002000410c6c21012005210003400240200041046a280200450d00200028020010350b2000410c6a2100200141746a22010d000b0b200241c0126a2802002200450d012000410c6c450d01200510350c010b20024188106a200241b0106a410c6a290200370300200220022902b4103703801002400240024020022802f80b41796a2200410c4b0d000240024020000e0d00020202020202020202020201000b0240200241800c6a2d00004118460d0041002100200241003a00830f200241003b00810f200241013a00800f0c030b024020034102490d0041002100200241003a00830f200241003b00810f200241013a00800f0c030b200241a0086a41286a200241d80d6a220041286a290300370300200241a0086a41206a2203200041206a290300370300200241a0086a41186a220a200041186a290300370300200241a0086a41106a200041106a290300370300200241a0086a41086a200041086a290300370300200220002903003703a00841808eec00210002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200241a0086a20022802d00d10f101411f71417f6a0e1d0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c00010b200241d4086a410f36020020034200370300200a4280808080c000370300200241bdb5c0003602d008200241013a00c808200242043703b0082002427f3703a8082002427f20022903d80d427f200241e00d6a290300501b220c42ffffffffffffffffff007c220d200d200c541b3703a008411710332200450d22200242173702d412200220003602d012410f200241d0126a10770240024020022802d412221320022802d81222146b410f490d002014410f6a210020022802d01221032013210a0c010b2014410f6a22002014490d24201341017422032000200320004b1b220a4100480d240240024020130d000240200a0d00410121030c020b200a103322030d010c270b20022802d01221032013200a460d0020032013200a10372203450d260b2002200a3602d412200220033602d0120b200320146a221441002900bdb540370000201441076a41002900c4b540370000200220003602d81220022802d00d21140240200a20006b41034b0d00200041046a22132000490d24200a41017422152013201520134b1b22134100480d2402400240200a0d00024020130d00410121030c020b201310332203450d270c010b200a2013460d002003200a201310372203450d260b200220133602d412200220033602d0120b200241c9086a210a200320006a2014360000200041046a210320022802d012211420022802d4122113024020022802c408220020022802c008470d00200241bc086a2000410110870120022802c40821000b20022802bc082000410c6c6a220020033602082000201336020420002014360200200241d8126a2200200241a0086a41186a290300370300200220022802c40841016a3602c408200241d0126a41106a2203200241a0086a41206a290300370300200241800f6a41106a4232370300200220022903b0083703d0122002200a2900003703f0112002200a41076a2900003700f711200220022903a0083703880f200241800f6a41186a20022903d012370300200241800f6a41206a2000290300370300200241a80f6a2003290300370300200241b00f6a41003a0000200241b40f6a20022800f311360000200241b10f6a20022802f011360000200241003a00800f0c1f0b41800e21000c1a0b41808e0421000c190b41808e0821000c180b41808e0c21000c170b41808e1021000c160b41808e1421000c150b41808e1821000c140b41808e1c21000c130b41808e2021000c120b41808e2421000c110b41808e2821000c100b41808e2c21000c0f0b41808e3021000c0e0b41808e3421000c0d0b41808e3821000c0c0b41808e3c21000c0b0b41808ec00021000c0a0b41808ec40021000c090b41808ec80021000c080b41808ecc0021000c070b41808ed00021000c060b41808ed40021000c050b41808ed80021000c040b41808edc0021000c030b41808ee00021000c020b41808ee40021000c010b41808ee80021000b200241013a00800f200220003b00810f200220004110763a00830f0c020b200241800f6a200241fc0b6a10dd0320022d00800f4101470d0220022f00810f20022d00830f4110747221000c010b200241003a00830f418102210020024181023b00810f200241013a00800f0b200241013a0058200220003b0059200220004110763a005b02402001450d002001410c6c21012008210003400240200041046a280200450d00200028020010350b2000410c6a2100200141746a22010d000b0b02402005450d002005410c6c450d00200810350b02402007450d002007410c6c21012009210003400240200041046a280200450d00200028020010350b2000410c6a2100200141746a22010d000b0b2006450d012006410c6c450d01200910350c010b200241a0126a41286a2200200241800f6a41306a290300370300200241a0126a41206a2203200241800f6a41286a290300370300200241a0126a41186a220a200241800f6a41206a2214290300370300200241a0126a41106a2213200241800f6a41186a2215290300370300200241a0126a41086a2216200241800f6a41106a290300370300200220022903880f3703a012200241800f6a41086a20024180106a41086a290300370300200241a40f6a20073602002014200636020020152001360200200241940f6a200536020020022002290380103703800f2002200b3703a80f2002200936029c0f200220083602900f200241a0086a41286a2000290300370300200241a0086a41206a2003290300370300200241a0086a41186a200a290300370300200241a0086a41106a2013290300370300200241a0086a41086a2016290300370300200220022903a0123703a008200241d0126a200241800f6a200241a0086a10d903200241d8006a41086a20022903d012370300200241d8006a41106a200241d0126a41086a290300370300200241d8006a41186a200241d0126a41106a290300370300200241d8006a41206a200241d0126a41186a290300370300200241d8006a41286a200241d0126a41206a290300370300200241d8006a41306a200241d0126a41286a290300370300200241003a00580b200410ba0220022d005821010b410110332200450d00200242013702ac0b200220003602a80b02400240200141ff01714101470d00200041013a0000200241013602b00b200241d8006a410172200241a80b6a10c90320022802b00b21000c010b200041003a0000200241013602b00b200241e0006a290300210b024020022802ac0b2201417f6a41074b0d00200141017422054109200541094b1b22054100480d03024020012005460d0020002001200510372200450d050b200220053602ac0b200220003602a80b0b2000200b370001200241093602b00b200241f0006a2802002101200241f8006a2802002200200241a80b6a107702402000450d0020012000410c6c6a2108034020012802002106200141086a2802002200200241a80b6a10770240024020022802ac0b220420022802b00b22056b2000490d0020022802a80b21030c010b200520006a22032005490d05200441017422072003200720034b1b22074100480d050240024020040d00024020070d00410121030c020b200710332203450d080c010b20022802a80b210320042007460d0020032004200710372203450d070b200220073602ac0b200220033602a80b0b200320056a20062000109d081a2002200520006a3602b00b2001410c6a22012008470d000b0b200241fc006a280200210120024184016a2802002200200241a80b6a10770240024020000d0020022802ac0b210620022802b00b21000c010b20012000410c6c6a2108034020012802002107200141086a2802002200200241a80b6a10770240024020022802ac0b220320022802b00b22056b2000490d0020022802a80b2104200321060c010b200520006a22042005490d05200341017422062004200620044b1b22064100480d050240024020030d00024020060d00410121040c020b200610332204450d080c010b20022802a80b210420032006460d0020042003200610372204450d070b200220063602ac0b200220043602a80b0b200420056a20072000109d081a2002200520006a22003602b00b2001410c6a22012008470d000b0b200241e8006a290300210b02400240200620006b4108490d0020022802a80b2105200621010c010b200041086a22012000490d03200641017422052001200520014b1b22014100480d030240024020060d00024020010d00410121050c020b200110332205450d060c010b20022802a80b210520062001460d0020052006200110372205450d050b200220013602ac0b200220053602a80b0b200520006a200b3700002002200041086a22003602b00b20024188016a2d000021030240024020012000460d00200021010c010b200141016a22002001490d03200141017422042000200420004b1b22004100480d030240024020010d0041002101024020000d00410121050c020b200010332205450d060c010b20012000460d0020052001200010372205450d050b200220003602ac0b200220053602a80b0b200520016a20033a00002002200141016a22003602b00b0b2000ad42208620023502a80b84210b024020022d00580d000240200241f8006a2802002201450d00200241f0006a28020021002001410c6c210103400240200041046a280200450d00200028020010350b2000410c6a2100200141746a22010d000b0b0240200241f4006a2802002200450d002000410c6c450d00200228027010350b024020024184016a2802002201450d00200241fc006a28020021002001410c6c210103400240200041046a280200450d00200028020010350b2000410c6a2100200141746a22010d000b0b20024180016a2802002200450d002000410c6c450d00200228027c10350b200241a0136a2400200b0f0b1045000b103e000b103c000b200241e4046a4104360200200241bc0b6a4102360200200242023702ac0b200241f0b2c3003602a80b200241043602dc042002419cb4c3003602d8042002410036029401200241b0b4cc00360290012002200241d8046a3602b80b200220024190016a3602e004200241a80b6a4180b3c300104c000be82307017f027e027f017e077f017e017f230041a0116b22022400420221030240024002400240024002400240024002400240200129036822044202520d00200241186a20014198016a41b002109d081a0c010b20024196036a200141246a41c200109d081a200241d8036a41086a220520014188016a290300370300200241d8036a41106a220620014190016a290300370300200220014180016a2903003703d803200141f8006a29030021032001290370210720024190046a41206a200141206a28020036020020024190046a41186a200141186a29020037030020024190046a41106a200141106a29020037030020024190046a41086a200141086a2902003703002002200129020037039004200241c80a6a20024190046a108b0220024190086a41086a2208200241d10a6a29000037030020024190086a41106a2209200241d90a6a29000037030020024190086a41186a220a200241c80a6a41196a290000370300200220022900c90a3703900820022d00c80a4101460d02200241f0036a41186a200a290300370300200241f0036a41106a2009290300370300200241f0036a41086a200829030037030020022002290390083703f003200241800d6a20014198016a41b002109d081a200241b00f6a41106a2006290300370300200241b00f6a41086a2005290300370300200220022903d8033703b00f4100210520024190116a410010b803200241e8106a200228029011220120022802981110d501200241c8106a41086a200241f4106a290200370300200241c8106a41106a200241fc106a290200370300200241dd106a2206200241e8106a41196a290000370000200220022902ec103703c8100240024020022d00e8104101460d00200241c0106a4200370300200241b8106a4200370300200241b0106a4200370300200242003703a8100c010b20022d00eb10210520022f00e9102108200241b3106a200241d0106a290300370000200241bb106a200241c8106a41106a290300370000200241c0106a2006290000370000200220022903c8103700ab102002200820054110747222053b01a810200220054110763a00aa100b0240200228029411450d00200110350b20024188106a41086a200241b3106a220629000037030020024188106a41106a200241bb106a220829000037030020024188106a41156a200241c0106a2209290000370000200220022900ab1037038810200241c8106a41156a220a4200370000200241c8106a41106a220b4200370300200241c8106a41086a220c4200370300200242003703c81041d1c4c700ad4280808080e00084100122012f0000210d200141026a2d0000210e2002200141086a2900003700ed10200220012900033703e81020011035200220022900ed103700cd10200220022903e8103703c81041e7c4c700ad4280808080e0008410012201290000210f200241e8106a41086a2210200141086a2900003703002002200f3703e81020011035200a2010290300220f3700002009200f370000200220022903e8103700d5102006200c2903003700002008200b2903003700002002200e3a00aa102002200d3b01a810200220022903c8103700ab10200241106a200241a8106a412010c00141002101024020044201520d0020074200510d052002280214410020022802101b2106417f21012006ad220f20032003200f541b220f200f20037d2007827d220f42ffffffff0f560d00200fa721010b200241e8106a200110b803200241086a20022802e810220620022802f01041b0b4cc0041004100108a0220022802082108024020022802ec10450d00200610350b41012106024002400240024020084101470d0020024190116a200110b803200241e8106a200228029011220620022802981110d501200241c8106a41086a2208200241f4106a290200370300200241c8106a41106a2209200241fc106a290200370300200241c8106a41156a220a20024181116a290000370000200220022902ec103703c81020022d00e8104101460d01200241a8106a41156a4200370000200241a8106a41106a4200370300200241a8106a41086a4200370300200242003703a810410021010c020b0c020b20022f00e91020022d00eb10411074722101200241a8106a41156a200a290000370000200241a8106a41106a2009290300370300200241a8106a41086a2008290300370300200220022903c8103703a8100b0240200228029411450d00200610350b200241c8106a41086a200241a8106a41086a290300370300200241c8106a41106a200241a8106a41106a290300370300200241c8106a41156a200241a8106a41156a290000370000200241e8106a41086a20024188106a41086a290300370300200241e8106a41106a20024188106a41106a290300370300200241e8106a41156a20024188106a41156a290000370000200220022903a8103703c81020022002290388103703e810410021060b200241e80f6a41156a2208200241e8106a41156a290000370000200241e80f6a41106a2209200241e8106a41106a290300370300200241e80f6a41086a220a200241e8106a41086a290300370300200241c80f6a41086a220b200241c8106a41086a290300370300200241c80f6a41106a220c200241c8106a41106a290300370300200241c80f6a41156a220d200241c8106a41156a290000370000200220022903e8103703e80f200220022903c8103703c80f20060d01200241d8076a41156a22062008290000370000200241d8076a41106a22082009290300370300200241d8076a41086a2209200a290300370300200241b8076a41086a220a200b290300370300200241b8076a41106a220b200c290300370300200241b8076a41156a220c200d290000370000200220022903e80f3703d807200220022903c80f3703b807200241f8076a41106a220d200241b00f6a41106a290300370300200241f8076a41086a220e200241b00f6a41086a290300370300200220022903b00f3703f807200241c80a6a41046a200241800d6a41b002109d081a20024190086a200241c80a6a41b402109d081a20024190046a20024190086a41046a41b002109d081a200241f6066a20054110763a0000200241f4066a20053b0100200241d0066a2003370300200241c8066a2007370300200241d8066a220520022903f807370300200241e0066a2210200e290300370300200241e8066a200d290300370300200241f7066a20022903d807370000200241ff066a200929030037000020024187076a20082903003700002002418c076a2006290000370000200220043703c006200241f5013602f00620024196076a20014110763a000020024194076a20013b010020024197076a20022903b8073700002002419f076a200a290300370000200241a7076a200b290300370000200241ac076a200c290000370000410410332201450d05200242043702cc0a200220013602c80a20024190046a200241c80a6a10af030240024020022903c0064201520d0020022903d00620022903c8062203420c882204420120044201561b8021040240024020022802cc0a220820022802d00a22016b4102490d0020022802c80a21060c010b200141026a22062001490d09200841017422092006200920064b1b22094100480d090240024020080d00024020090d00410121060c020b2009103322060d010c0d0b20022802c80a210620082009460d0020062008200910372206450d0c20022802d00a21010b200220093602cc0a200220063602c80a0b200620016a2004a741047420037aa7417f6a22064101200641014b1b2206410f2006410f491b723b0000200141026a21010c010b0240024020022802cc0a20022802d00a2201460d0020022802c80a21060c010b200141016a22062001490d08200141017422082006200820064b1b22084100480d080240024020010d0041002101024020080d00410121060c020b200810332206450d0c0c010b20022802c80a210620012008460d0020062001200810372206450d0b20022802d00a21010b200220083602cc0a200220063602c80a0b200620016a41003a0000200141016a21010b200220013602d00a2005200241c80a6a10e201200220103602900820024190086a200241c80a6a10cf0120022802f00621080240024020022802cc0a220620022802d00a22016b4104490d0020022802c80a21050c010b200141046a22052001490d07200641017422092005200920054b1b22094100480d070240024020060d00024020090d00410121050c020b200910332205450d0b0c010b20022802c80a210520062009460d0020052006200910372205450d0a20022802d00a21010b200220093602cc0a200220053602c80a0b200520016a20083600002002200141046a3602d00a412010332201450d052001200241f4066a290200370000200141186a2002418c076a290200370000200141106a20024184076a290200370000200141086a200241fc066a2902003700000240024020022802cc0a220820022802d00a22056b4120490d0020022802c80a21060c010b200541206a22062005490d07200841017422092006200920064b1b22094100480d070240024020080d00024020090d00410121060c020b200910332206450d0b0c010b20022802c80a210620082009460d0020062008200910372206450d0a20022802d00a21050b200220093602cc0a200220063602c80a0b200620056a22062001290000370000200641186a200141186a290000370000200641106a200141106a290000370000200641086a200141086a2900003700002002200541206a3602d00a20011035412010332201450d05200120024194076a290200370000200141186a200241ac076a290200370000200141106a200241a4076a290200370000200141086a2002419c076a2902003700000240024020022802cc0a220820022802d00a22056b4120490d0020022802c80a21060c010b200541206a22062005490d07200841017422092006200920064b1b22094100480d070240024020080d00024020090d00410121060c020b200910332206450d0b0c010b20022802c80a210620082009460d0020062008200910372206450d0a20022802d00a21050b200220093602cc0a200220063602c80a0b200620056a22062001290000370000200641186a200141186a290000370000200641106a200141106a290000370000200641086a200141086a2900003700002002200541206a3602d00a2001103520022802cc0a210620022802c80a21010240024020022802d00a22054180024b0d0020024196036a200241f0036a2001200510f90521050c010b2005ad4220862001ad84100922052900002103200541086a2900002104200541106a2900002107200241a8106a41186a200541186a290000370300200241a8106a41106a2007370300200241a8106a41086a2004370300200220033703a8102005103520024196036a200241f0036a200241a8106a412010f90521050b02402006450d00200110350b2005450d03200241f0026a41086a200241f0036a41086a290300370300200241f0026a41106a200241f0036a41106a290300370300200241f0026a41186a200241f0036a41186a290300370300200241c8026a41086a200241d0066a290300370300200241c8026a41106a200241d8066a290300370300200241c8026a41186a200241e0066a290300370300200241e8026a200241e8066a290300370300200220022903f0033703f0022002200241c8066a2903003703c80220022903c0062103200241186a20024190046a41b002109d081a0b200041086a20022903f002370300200041286a2003370300200041306a20022903c802370300200041206a200241f0026a41186a290300370300200041186a200241f0026a41106a290300370300200041106a200241f0026a41086a290300370300200041386a200241c8026a41086a290300370300200041c0006a200241c8026a41106a290300370300200041c8006a200241c8026a41186a290300370300200041d0006a200241c8026a41206a290300370300200041d8006a200241186a41b002109d081a200041003a00000c060b200241800d6a10ba02200041036a41003a0000200041800a3b0001200041013a00000c050b200041013b0001200041013a0000200041036a41003a000020014198016a10ba020c040b20004180083b0001200041013a0000200041036a41003a000020024190046a10ba020c030b41809ccc004119419c9ccc00103f000b1045000b103e000b200241a0116a24000f0b103c000b841f05017f017e037f027e017f230041d0016b22022400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802000e1c00011302030405060708090a0b0c0d0e0f1011121313131415161713000b420021034100210402400240024002400240024002400240200141086a2802000e0b0001070203030405050506000b200241246a410136020020024201370214200241e8d4ca00360210200241043602a4012002419cd5ca003602a0012002200241a0016a360220200241106a41b0b4cc00104c000b2001410c6a35020042d00f7e21030b410121040c040b41012104428084afdf0021030c030b410121044280dac40921030c020b410121040c010b4101210442c0f0f50b21030b200041003a0009200020043a0008200020033703000c170b0240024002400240024002400240024020012d00040e06000102030405000b200241246a410136020020024201370214200241e8d4ca00360210200241043602a4012002419cd5ca003602a0012002200241a0016a360220200241106a41b0b4cc00104c000b200141086a280200210442c0c3930721030240200141106a280200220541b0026c2206450d00200421010340200241106a200110d803427f427f200320022903107c220720072003541b220342c0843d7c220720072003541b2103200141b0026a2101200641d07d6a22060d000b0b200541b0026c21014101210603402001450d06200141d07d6a2101200241106a200410d803200441b0026a210420022d00184101460d000c050b0b200241106a200141086a280200220110d80320022903102103200241106a200110d803427f200342c08db7017c220720072003541b210320022d001821060c040b200141106a3502002107200241106a200141206a280200220110d80320022903102103200241106a200110d803427f427f427f200342808ece1c7c220820082003541b220320074290a10f7e7c220720072003541b220342c0b2cd3b7c220720072003541b210320022d001821060c030b200141306a35020042c0a9077e42c0c09bd8007c21030c010b200141306a35020042a08d067e42c093b9d3007c21030b410021060b200041003a0009200020063a0008200020033703000c160b200041023b0108200042c0cbe8cb003703000c150b200041023b0108200042003703000c140b200041003b0108200042003703000c130b42c0b2cd3b21074280e89226210302400240024002400240200141086a2802000e050004010203000b200241246a410136020020024201370214200241e8d4ca00360210200241043602a4012002419cd5ca003602a0012002200241a0016a360220200241106a41b0b4cc00104c000b42c09dd81021030c020b4280e59af70021070c010b42808ece1c21030b200041003b01082000200720037c3703000c120b4280cab5ee012103410021040240024002400240024002400240024002400240200141086a2d00000e1900090901010202090902030303030603040909090905060707000b200241246a410136020020024201370214200241e8d4ca00360210200241043602a4012002419cd5ca003602a0012002200241a0016a360220200241106a41b0b4cc00104c000b428088debe0121030c060b4280afd0e50221030c050b42c096b10221030c040b428094ebdc0321030c030b410121040c030b420021030c010b4280d0dbc3f40221030b410021040b200041003a0009200020043a0008200020033703000c110b200041003b010820004280f1a795034280c7bdbf0220012802041b3703000c100b4280e497d0122103410021040240024002400240024002400240024002400240200141086a2d00000e1e000909020201090909020203030404040505060404060604060605050607000b200241246a410136020020024201370214200241e8d4ca00360210200241043602a4012002419cd5ca003602a0012002200241a0016a360220200241106a41b0b4cc00104c000b410121044280cab5ee0121030c070b428084afdf0021030c050b41012104420021030c050b4280c2d72f21030c030b4280cab5ee0121030c020b420021030c010b42c099f9ebc02b21030b410021040b200041003a0009200020043a0008200020033703000c0f0b4280c2d72f2103024002400240024020012d00040e06000303010202000b200241246a410136020020024201370214200241e8d4ca00360210200241043602a4012002419cd5ca003602a0012002200241a0016a360220200241106a41b0b4cc00104c000b4280e497d01221030c010b428084afdf0021030b200041013b0108200020033703000c0e0b4280c2d72f2103024002400240024020012d00040e06000303010202000b200241246a410136020020024201370214200241e8d4ca00360210200241043602a4012002419cd5ca003602a0012002200241a0016a360220200241106a41b0b4cc00104c000b4280e497d01221030c010b428084afdf0021030b200041013b0108200020033703000c0d0b4280c2d72f210341002104024002400240024002400240200141086a2802000e0700050102030404000b200241246a410136020020024201370214200241e8d4ca00360210200241043602a4012002419cd5ca003602a0012002200241a0016a360220200241106a41b0b4cc00104c000b42002103410021040c030b428094ebdc032103410021040c020b4280cab5ee012103410021040c010b410121044280a8d6b90721030b200041003a0009200020043a0008200020033703000c0c0b200041003b010820004280e1eb173703000c0b0b200041023b0108200042003703000c0a0b200041003b0108200042003703000c090b42c090c1a401210341002104024002400240024002400240024002400240200141086a2d00000e09000801020308040506000b200241246a410136020020024201370214200241e8d4ca00360210200241043602a4012002419cd5ca003602a0012002200241a0016a360220200241106a41b0b4cc00104c000b410121044280ae99b50121030c060b410121044280bcded70021030c050b200141346a35020042a01f7e42c0cbf1c5017c21030c030b200141346a35020042a01f7e4280c2d1ae017c21030c020b4280caacf40021030c010b42a0dcc4a20221030b410021040b200041003a0009200020043a0008200020033703000c080b024002400240024002400240200141086a2d00000e06000102030405000b200241246a410136020020024201370214200241e8d4ca00360210200241043602a4012002419cd5ca003602a0012002200241a0016a360220200241106a41b0b4cc00104c000b200041003b0108200042003703000c0b0b200241106a41186a4200370300200241106a41106a22054200370300200241106a41086a220442003703002002420037031041f1d8cb00ad42808080809001841001220629000021032004200641086a290000370300200220033703102006103541e2d8cb00ad4280808080f00184100122062900002103200241c0016a41086a2209200641086a290000370300200220033703c00120061035200520022903c0012203370300200241a0016a41086a2004290300370300200241a0016a41106a2003370300200241a0016a41186a2009290300370300200220022903103703a001200241106a200241a0016a10da02200242a0c21e200229031020022d0098014102461b4200200141146a3502004200108408200041003b01082000427f200229030020022903084200521b3703000c0a0b200041003b01082000200141d0006a2903003703000c090b200041003b01082000200141c8006a2903003703000c080b200041003b0108200042003703000c070b42002103410021040240024002400240024020012802040e0400010402000b200241246a410136020020024201370214200241e8d4ca00360210200241043602a4012002419cd5ca003602a0012002200241a0016a360220200241106a41b0b4cc00104c000b200241106a200141086a280200220110d80320022903102103200241106a200110d803200241106a21010c010b200241106a2001412c6a280200220110d80320022903102103200241106a200110d803200241106a21010b20034290ce007c210320012d000821040b200041003a0009200020043a0008200020033703000c060b200041003b01082000200141286a35020042b0e32d7e2001411c6a35020042809fc9007e7c4280f797f3017c3703000c050b108406000b42c0d4e2cc002103024002400240024002400240024002400240024002400240200141086a2d00000e0c000b0102030405060708090a000b200241246a410136020020024201370214200241e8d4ca00360210200241043602a4012002419cd5ca003602a0012002200241a0016a360220200241106a41b0b4cc00104c000b42808c84a40121030c090b200141146a35020042a0acb9317e42c0b5b6f7267c21030c080b42808ea9da2721030c070b42c0f587ba0121030c060b42c0bda3a90121030c050b42c0ceffc30021030c040b42e0facec40021030c030b4280b4f3c30021030c020b42c0a0e2b30121030c010b42c0febdaf2821030b200041003b0108200020033703000c030b4280e1eb172103024002400240024002400240024002400240200141086a2d00000e0d00080108010203040705060807000b200241246a410136020020024201370214200241e8d4ca00360210200241043602a4012002419cd5ca003602a0012002200241a0016a360220200241106a41b0b4cc00104c000b4280dac40921030c060b428087a70e21030c050b4280dac40921030c040b428087a70e21030c030b4280dac40921030c020b428087a70e21030c010b420021030b200041003b0108200020033703000c020b420021034100210402400240024002400240024020012d00040e0a00010502020202030305000b200241246a410136020020024201370214200241e8d4ca00360210200241043602a4012002419cd5ca003602a0012002200241a0016a360220200241106a41b0b4cc00104c000b200241106a200141286a280200220110d80320022903102103200241106a200110d80320034290ce007c210320022d001821040c030b4280c2d72f21030c010b428087a70e21030b410021040b200041003a0009200020043a0008200020033703000c010b4280e59af700210342808ece1c21070240024002400240200141086a2802000e0400030102000b200241246a410136020020024201370214200241e8d4ca00360210200241043602a4012002419cd5ca003602a0012002200241a0016a360220200241106a41b0b4cc00104c000b42c097e8b20121030c010b42c097e8b201210342c085eb3621070b200041003b01082000200320077c3703000b200241d0016a24000bc10304017f027e067f017e230041206b22032400200229030021042001290300210520022802102106200141106a200141186a2207280200200241186a2208280200220910870120012802102007280200220a410c6c6a20062009410c6c109d081a200841003602002007200a20096a2209360200200341086a200936020020032001290210370300200228021c21082001411c6a200141246a2207280200200241246a220a2802002209108701200128021c2007280200220b410c6c6a20082009410c6c109d081a200a41003602002007200b20096a2209360200200341106a41086a20093602002003200129021c370310427f200520047c220420042005541b2105200229030822042001290308220c200c2004561b21040240024020012d0028450d004101210120022d00280d010b410021010b20002005370300200020032903003702102000200329031037021c200020013a002820002004370308200041186a200341086a280200360200200041246a200341106a41086a2802003602000240200241146a2802002201450d002001410c6c450d00200610350b0240200241206a2802002201450d002001410c6c450d00200810350b200341206a24000b920303047f017e017f230041e0006b22032400200341306a41186a4200370300200341306a41106a22044200370300200341306a41086a220542003703002003420037033041d1c4c700ad4280808080e000841001220629000021072005200641086a290000370300200320073703302006103541b8eec700ad4280808080800284100122062900002107200341d0006a41086a2208200641086a2900003703002003200737035020061035200420032903502207370300200341106a41086a2005290300370300200341106a41106a2007370300200341106a41186a200829030037030020032003290330370310200341086a200341106a412010c0014100210502400240417f200328020c410020032802081b220620026a220220022006491b22064280808080f28ba80942808080c0f588fe06200141ff01711b22072007428094ebdc038022074280ec94a37c7e7c4280cab5ee01562007a76a4b0d00200041046a20063602000c010b200041800c3b0001200041036a41003a0000410121050b200020053a0000200341e0006a24000b8b0a04027f017e017f087e230041b0026b220624000240200341ff01710d00200641b8016a2001ad42004280c8afa025420010840820064180026a41186a420037030020064180026a41106a2207420037030020064180026a41086a22034200370300200642003703800241e3efcb00ad4280808080a002841001220129000021082003200141086a29000037030020062008370380022001103541f5efcb00ad4280808080900284100122012900002108200641a0026a41086a2209200141086a290000370300200620083703a00220011035200720062903a0022208370300200641e0016a41086a2003290300370300200641e0016a41106a2008370300200641e0016a41186a200929030037030020062006290380023703e001200641b8016a41086a29030020062903b801220820024280c0a8ca9a3a20024280c0a8ca9a3a541b7c2202200854ad7c2108200641c8016a200641e0016a10bc020240024020062802c8010d00410021034200210a4200210b0c010b20062903d001220a4200522201200641c8016a41106a290300220b420055200b501b2103200b427f550d00428080808080808080807f4200200b2001ad7c7d200a200b428080808080808080807f85845022011b210b42004200200a7d20011b210a0b200641f8006a2002200842808090bbbad6adf00d4200109808200641a8016a200a200b42808090bbbad6adf00d4200109808200641e8006a2006290378220c200641f8006a41086a290300220d428080f0c4c5a9d28f72427f10840820064198016a20062903a801220b200641a8016a41086a290300220e428080f0c4c5a9d28f72427f108408200642808090bbbad6adf00d370388022006290368210f2006200a2006290398017c220a37038002200641c8006a2002200f7c42ffffffffffffffff0f83420020064180026a200a42808090bbbad6adf00d564103746a29030022104200108408200641386a2006290348220a200641c8006a41086a290300220f42808090bbbad6adf00d4200109808200641286a20062903382211200641386a41086a290300428080f0c4c5a9d28f72427f108408200641d8006a200c200d20104200108408200641186a20084200200b4200108408200641086a200e42002002420010840820064188016a20024200200b4200108408427f427f427f2008427f427f20064188016a41086a290300220b200629031820062903087c7c220c2008420052200e42005271200629032042005272200629031042005272200c200b547222011b220b200641d8006a41086a2903002006290358220e2011427f200f42808090bbbad6adf00d541b200a20062903287c220c428080c89d9deb96f80656200f200641286a41086a2903007c200c200a54ad7c220a420052200a501bad7c7c220a200e54ad7c7c427f20062903880120011b220e200a7c220f200e542201ad7c220a2001200a200b54200a200b511b22011b220e7c2002427f200f20011b220b7c220f2002542201ad7c220a2001200a200854200a2008511b22011b42002008200e7d2002200b54ad7d220a2002200b7d220b200256200a200856200a2008511b22071b20031b220a427f200f20011b4200200b20071b20031b220242c0b2cd3b7c22082002542203ad7c220b2003200b200a54200820025a1b22031b220220057c427f200820031b220820047c22042008542203ad7c22082003200820025420082002511b22031b2105427f200420031b21040b2000200437030020002005370308200641b0026a24000b8e1307077f027e037f0a7e017f037e047f230041d0036b2203240020022802102104200228020c2105200228020821062002280204210720022802002102200341206a2001108e02200341a0016a2003280220220820032802282209108f0220032903a001210a4200210b200342003703a001200341e8016a280200210c20032d00ec01210d02400240200a420151220e0d00200341306a41306a4200370300200341306a41286a4200370300200341306a41206a4200370300200341306a41186a4200370300200341c0006a4200370300200341386a4200370300200342003703304200210f4200211042002111420021120c010b200341d8016a2903002113200341a0016a41306a2903002114200341a0016a41206a290300210f200341a0016a41186a290300210b200341e0016a290300211220032903b001211120032903a8012110200341306a41206a200341a0016a41286a290300370300200341306a41286a2014370300200341306a41306a2013370300200341c0006a200b3703002003200f37034820032010370330200320113703380b02400240024002402010200229030022157d22142010562011200241086a29030022167d2010201554ad7d221320115620132011511b450d00419089c200ad4280808080b00284211141838c0c21040c010b02402010200b7c2217428080e983b1de165441002011200f7c22182017200b54ad7c501b0d002014200b7c220b42ffffe883b1de16562013200f7c200b201454ad7c220b420052200b501b0d0020072d00004101460d0041f588c200ad4280808080900184211141838c1421040c010b2015201684500d0120052d00002105200341e8006a2006280200108e02200341a0026a200328026822062003280270108f0220032903a0024201512107200341d0026a290300210f200341c8026a2903002116200341e0026a290300210b200341d8026a29030021150240200328026c450d00200610350b200b420020071b210b2015420020071b21150240200541ff01714101460d00200f420020071b210f2016420020071b2116024020054101710d0020162115200f210b0c010b200f200b2016201556200f200b56200f200b511b22071b210b2016201520071b21150b2015201458200b201358200b2013511b0d0141a389c200ad4280808080d00284211141838c0421040b20114280807c83210b201142088842ff018321102011a7210e410121020c010b2003201437033020032013370338200241086a290300210f2002290300211520042802002104200341e8006a41186a200341c0006a220241086a290300220b370300200341e8006a41206a2207200241106a29030037030020034190016a2206200241186a29030037030020034198016a2219200241206a2903003703002003201337037020032014370368200320022903002216370378427f20172017201054220220182002ad7c221020115420102011511b22021b427f201020021b8450210502400240427f201420167c2211201120145422022013200b7c2002ad7c221120135420112013511b22021b2210428080e983b1de16544100427f201120021b2211501b0d00200341e8006a41106a29030021102019290300210b2006290300211720072903002116200329037021182003290368211a4201211b200329038001211c0c010b02400240201020118450450d004200211b0c010b4200211b200341a0026a41186a221d4200370300200341a0026a41106a22064200370300200341a0026a41086a22074200370300200342003703a00241b6fdc600ad4280808080800184220b100122192900002117200341c0036a41086a2202201941086a290000370300200320173703c0032019103520072002290300370300200320032903c0033703a00241e489c200ad4280808080d0018422171001221929000021162002201941086a290000370300200320163703c00320191035200620032903c0032216370300200341a0036a41086a221e2007290300370300200341a0036a41106a221f2016370300200341a0036a41186a22202002290300370300200320032903a0023703a003200341086a200341a0036a412010d701200341086a41106a29030021162003290310211820032802082119201d42003703002006420037030020074200370300200342003703a002200b1001221d290000210b2002201d41086a2900003703002003200b3703c003201d103520072002290300370300200320032903c0033703a00220171001221d290000210b2002201d41086a2900003703002003200b3703c003201d1035200620032903c003220b370300201e2007290300370300201f200b37030020202002290300370300200320032903a0023703a003200342002016420020191b220b20117d2018420020191b2217201054ad7d2216201720107d22182017562016200b562016200b511b22021b3703a80220034200201820021b3703a002200341a0036aad4280808080800484200341a0026aad42808080808002841002200341d8026a2011370300200341d0026a2010370300200741013a0000200341a9026a2004290000370000200341b1026a200441086a290000370000200341b9026a200441106a290000370000200341c1026a200441186a290000370000200341033a00a00241b0b4cc004100200341a0026a10d4010b0b2005ad2111200341c8016a2016370300200341d0016a2017370300200341b0016a2018370300200341d8016a200b370300200341b8016a20103703002003201c3703c001200320123703e0012003201a3703a80142012110410021022003200d4100200a42015122041b3a00ec012003200c410020041b3602e8012003201b4201512204ad3703a001024020040d002009ad4220862008ad841007420021104200210b0c010b200320093602a402200320083602a002200341a8016a200341a0026a10e7024200210b0b02402003280224450d00200810350b024002402002450d0020002004360204200041086a2010420886200ead42ff018384200b84370200410121020c010b024002400240200e41ff017122020d0020104200510d004103210e200341a0026a21020c010b2002450d0120104200520d014104210e200341a0016a21020b200241086a200e3a0000200241003a0000200241096a2001290000370000200241116a200141086a290000370000200241196a200141106a290000370000200241216a200141186a29000037000041b0b4cc004100200210d4010b200041286a200f370300200041206a2015370300200041186a2013370300200041106a2014370300200041086a2011370300410021020b20002002360200200341d0036a24000b8f1804057f017e077f017e230041f0006b2202240020012802202103200241086a41186a4200370300200241086a41106a22044200370300200241086a41086a220542003703002002420037030841a3edcb00ad4280808080f000841001220629000021072005200641086a290000370300200220073703082006103541f393ca00ad4280808080a00184100122062900002107200241e0006a41086a2208200641086a2900003703002002200737036020061035200420022903602207370300200241c0006a41086a2005290300370300200241c0006a41106a2007370300200241c0006a41186a200829030037030020022002290308370340200241086a200241c0006a10fe0120022802082205410120051b2106024002400240024002400240024002402003200229020c420020051b2207422088a7490d00200742ffffff3f83500d01200610350c010b2003200620034105746a10b90421030240200742ffffff3f83500d00200610350b20030d010b200241086a41186a22054200370300200241086a41106a22064200370300200241086a41086a220342003703002002420037030841a3edcb00ad4280808080f000841001220829000021072003200841086a290000370300200220073703082008103541a5ebcb00ad4280808080c00184100122082900002107200241e0006a41086a2209200841086a290000370300200220073703602008103520042002290360370000200441086a22082009290300370000200241c0006a41086a220a2003290300370300200241c0006a41106a220b2006290300370300200241c0006a41186a220c2005290300370300200220022903083703402002200241c0006a412010c001200128021c2002280204410020022802001b220d470d01200542003703002006420037030020034200370300200242003703084188e8cb00ad42808080808001841001220e29000021072003200e41086a29000037030020022007370308200e1035418fd1cb00ad4280808080c000841001220e29000021072009200e41086a29000037030020022007370360200e10352004200229036037000020082009290300370000200a2003290300370300200b2006290300370300200c200529030037030020022002290308370340200241086a200241c0006a10d80220022802082204410120041b210c2001280224200229020c420020041b2207422088a72205470d0202402001280220220620054f0d00200c20064105746a220e0d040b20004180083b0001200041013a0000200041036a41003a00000c040b20004180063b0001200041013a0000200041036a41003a00000c040b20004180063b0001200041013a0000200041036a41003a00000c030b200041800e3b0001200041013a0000200041036a410a3a00000c010b2002410036021020024201370308200128020021030240410410332204450d002002410436020c2002200436020820042003360000200241043602102001280204210a2001410c6a2802002204200241086a1077024002400240200228020c2209200228021022036b2004490d00200228020821080c010b200320046a22082003490d012009410174220b2008200b20084b1b220b4100480d010240024020090d000240200b0d00410121080c020b200b103322080d010c040b200228020821082009200b460d0020082009200b10372208450d030b2002200b36020c200220083602080b200820036a200a2004109d081a2002200320046a360210200141106a2802002103200141186a2802002204200241086a10770240024020040d00200228020c210920022802102104200d210b0c010b20032004410c6c6a210b03402003280200210a200341086a2802002204200241086a107702400240200228020c2206200228021022056b2004490d0020022802082108200621090c010b200520046a22082005490d03200641017422092008200920084b1b22094100480d030240024020060d00024020090d00410121080c020b200910332208450d060c010b2002280208210820062009460d0020082006200910372208450d050b2002200936020c200220083602080b200820056a200a2004109d081a2002200520046a22043602102003410c6a2203200b470d000b2001280224210520012802202106200128021c210b0b02400240200920046b4104490d00200441046a2103200228020821082009210a0c010b200441046a22032004490d01200941017422082003200820034b1b220a4100480d010240024020090d000240200a0d00410121080c020b200a10332208450d040c010b200228020821082009200a460d0020082009200a10372208450d030b2002200a36020c200220083602080b200820046a200b360000200220033602100240200a20036b41034b0d00200341046a22042003490d01200a41017422092004200920044b1b22044100480d0102400240200a0d00024020040d00410121080c020b200410332208450d040c010b200a2004460d002008200a200410372208450d030b2002200436020c200220083602080b200820036a20063600002002200341046a220636021002400240200228020c220920066b4104490d0020022802082104200921080c010b200641046a22042006490d01200941017422082004200820044b1b22084100480d010240024020090d00024020080d00410121040c020b200810332204450d040c010b2002280208210420092008460d0020042009200810372204450d030b2002200836020c200220043602080b200420066a2005360000200141286a200341086aad4220862004ad84200e1015210302402008450d00200410350b0240024020034101470d00200241086a41086a427f3703002002413c6a4108360200200241286a4200370300200241206a4280808080c0003703002002427f37030820024188e8cb00360238200241013a003020024204370318411010332204450d0120024210370244200220043602404108200241c0006a10770240024020022802442208200228024822066b4108490d00200641086a210420022802402103200821050c010b200641086a22042006490d03200841017422032004200320044b1b22054100480d030240024020080d00024020050d00410121030c020b200510332203450d060c010b2002280240210320082005460d0020032008200510372203450d050b20022005360244200220033602400b200320066a42c9dabdf2c6ad9ab7e500370000200220043602480240200520046b41034b0d00200441046a22062004490d03200541017422082006200820064b1b22064100480d030240024020050d00024020060d00410121030c020b200610332203450d060c010b20052006460d0020032005200610372203450d050b20022006360244200220033602400b200320046a200d3600002002200441046a2203360248024002402002280244220920036b4120490d00200441246a210820022802402105200921060c010b200341206a22082003490d03200941017422042008200420084b1b22064100480d030240024020090d00024020060d00410121050c020b200610332205450d060c010b2002280240210520092006460d0020052009200610372205450d050b20022006360244200220053602400b200241316a2109200520036a2204200e290000370000200441186a200e41186a290000370000200441106a200e41106a290000370000200441086a200e41086a2900003700000240200228022c22042002280228470d00200241246a20044101108701200228022c21040b20022802242004410c6c6a220420083602082004200636020420042005360200200241c0006a41086a2204200241086a41186a2903003703002002200228022c41016a36022c200241c0006a41106a2203200241086a41206a29030037030020022002290318370340200220092900003703602002200941076a2900003700672002290308210f200041106a42e400370300200041086a200f370300200041306a41013a0000200041186a2002290340370300200041206a2004290300370300200041286a2003290300370300200041003a0000200041316a2002280260360000200041346a2002280063360000200742ffffff3f83500d05200c10350c050b20004180083b0001200041013a0000200041036a41003a00000c030b1045000b103e000b103c000b200742ffffff3f83500d00200c10350b200241f0006a24000bcf3909057f017e057f017e047f017e037f017e0d7f230022022103200241c0046b41607122022400024002402001450d00200220003602400c010b200241b0b4cc003602400b20022001360244200241c0026a200241c0006a10c403024002400240024002400240024020022802c402450d00200241c8006a200241c0026a41f000109d081a200241b8016a200241c8006a10df032002280248200241d8006a20024198016a200241b8016a410010e00341004100280290b54c2201410120011b360290b54c0240200141014b0d000240024020010e020001000b410041fca1c000360298b54c410041b0b4cc00360294b54c41004102360290b54c0c010b03404100280290b54c4101460d000b0b2002410020022802482201417f6a2200200020014b1b22043602c401100d4101470d01200241c0026a41186a22054200370300200241c0026a41106a22004200370300200241c0026a41086a22014200370300200242003703c0024188e8cb00ad42808080808001841001220629000021072001200641086a290000370300200220073703c002200610354194c4c400ad4280808080e00184100122082900002107200241f0016a41086a2206200841086a290000370300200220073703f00120081035200020022903f0012207370300200241e0036a41086a22092001290300370300200241e0036a41106a220a2007370300200241e0036a41186a220b2006290300370300200220022903c0023703e003200241386a200241e0036a412010c001410021080240200228023c410020022802381b220c20044d0d00200241e0036a2100200241c8016a21010c060b200542003703002000420037030020014200370300200242003703c00241a3edcb00ad4280808080f00084220710012208290000210d2001200841086a2900003703002002200d3703c0022008103541a5ebcb00ad4280808080c0018410012208290000210d2006200841086a2900003703002002200d3703f00120081035200020022903f001220d37030020092001290300370300200a200d370300200b2006290300370300200220022903c0023703e003200241306a200241e0036a412010c0012002280234210e2002280230210f200542003703002000420037030020014200370300200242003703c00220071001220829000021072001200841086a290000370300200220073703c0022008103541f393ca00ad4280808080a001841001220829000021072006200841086a290000370300200220073703f00120081035200020022903f001220737030020092001290300370300200a2007370300200b2006290300370300200220022903c0023703e003200241c8016a200241e0036a10fe010240024020022802c80122010d00410021100c010b20022902cc012207422088a72110200742ffffff3f83500d00200110350b200241c0026a41186a22084200370300200241c0026a41106a22054200370300200241c0026a41086a22014200370300200242003703c0024188e8cb00ad42808080808001841001220629000021072001200641086a290000370300200220073703c00220061035418fd1cb00ad4280808080c00084100122062900002107200241f0016a41086a2209200641086a290000370300200220073703f00120061035200020022903f001370000200041086a2009290300370000200241e0036a41086a2001290300370300200241e0036a41106a2005290300370300200241e0036a41186a2008290300370300200220022903c0023703e003200241c0026a200241e0036a10d80220022802c002211120022902c4022112200241c0026a41e9dabdf30610e10320022802c002210820022802c402210902400240024020022802c80222000d004100211341012114410021150c010b02400240024020004105742201410575220641ffffff3f712006470d0020014100480d0020010d01410121140c020b103e000b200110332214450d020b200820016a210a2000410574210520014105762113410021010340200820016a22002900002107200041086a290000210d200041106a2900002116201420016a220641186a200041186a290000370000200641106a2016370000200641086a200d370000200620073700002005200141206a2201470d000b200a20086b41606a41057641016a21150b0240200941ffffff3f71450d00200810350b20154115490d0402404101450d0020154104744160712217417f4c0d000240201710332218450d00200241003602f801200242043703f001201441606a2119201441a07f6a211a41042106410021014100211b2015211c0340201c210b4100211c4101210a0240200b417f6a2205450d00024002400240024002400240201420054105746a200b410574221d20146a41406a412010a0084100480d00200b417e6a2109201a201d6a21004100211c410021080340024020092008470d00200b210a0c080b200841016a2108200041206a2000412010a0082105200041606a21002005417f4a0d000b200841016a210a2008417f73200b6a21050c010b201a201d6a210002400340024020054101470d00410021050c020b2005417f6a2105200041206a2000412010a0082108200041606a210020084100480d000b0b200b2005490d01200b20154b0d02200b20056b220a4101762209450d002019201d6a2100201420054105746a21080340200241e0036a41186a221d200841186a221e290000370300200241e0036a41106a221f200841106a2220290000370300200241e0036a41086a220c200841086a221c290000370300200220082900003703e003200041086a22212900002107200041106a2222290000210d200041186a2223290000211620082000290000370000201e20163700002020200d370000201c20073700002023201d2903003700002022201f2903003700002021200c290300370000200020022903e003370000200041606a2100200841206a21082009417f6a22090d000b0b024020050d002005211c0c050b0240200a41094d0d002005211c0c050b200b20154b0d02200b20056b2109201420054105746a211d0340200b2005417f6a221c490d040240200b201c6b220a4102490d00201420054105746a22002014201c4105746a2205412010a008417f4a0d00200241c0026a41186a220c200541186a2208290000370300200241c0026a41106a2221200541106a221e290000370300200241c0026a41086a2222200541086a221f290000370300200220052900003703c00220052000290000370000201f200041086a290000370000201e200041106a2900003700002008200041186a290000370000410121200240200a4103490d00200541c0006a200241c0026a412010a008417f4a0d0041022108201d210002400340200041186a200041386a290000370000200041106a200041306a290000370000200041086a200041286a2900003700002000200041206a221e29000037000020092008460d01200041c0006a211f20082120201e2100200841016a2108201f200241c0026a412010a008417f4a0d020c000b0b200821200b200520204105746a220020022903c002370000200041186a200c290300370000200041106a2021290300370000200041086a20222903003700000b201c450d05201d41606a211d200941016a2109201c2105200a410a4f0d050c000b0b2005200b41eccfca001059000b200b201541eccfca001058000b200b2005417f6a221c490d00200b201541fccfca001058000b201c200b41fccfca001059000b0240201b20022802f401470d00200241f0016a201b410110900120022802f001210620022802f8012201211b0b2006201b4103746a2200200a3602042000201c3602002002200141016a22013602f8012001211b024020014102490d000240024003400240024002400240024020062001417f6a4103746a2200280200450d00200141037420066a220941746a2802002205200028020422084b0d010b20014103490d022000280204210820062001417d6a221f4103746a28020421000c010b4102211b200141024d0d0620062001417d6a221f4103746a2802042200200820056a4d0d004103211b200141034d0d06200941646a280200200020056a4b0d050b20002008490d010b2001417e6a211f0b02400240024002400240024002402001201f41016a22204d0d002001201f4d0d012006201f41037422216a2201280204222220012802006a22012006202041037422236a2200280200220c490d02200120154b0d032014200c4105746a221d2000280204221e41057422006a2108200141057421062001200c6b2209201e6b2201201e4f0d042018200820014105742200109d08220b20006a2105201e4101480d0520014101480d05201920066a21062008210103402006200141606a2208200541606a220920092008412010a008410048220a1b2200290000370000200641186a200041186a290000370000200641106a200041106a290000370000200641086a200041086a29000037000020052009200a1b21050240201d20082001200a1b2201490d00200b21000c080b200641606a2106200b2100200b2005490d000c070b0b20202001418cd0ca001042000b201f2001419cd0ca001042000b200c200141acd0ca001059000b2001201541acd0ca001058000b2018201d2000109d08220b20006a21050240201e4101480d002009201e4c0d00201420066a210a200b2100201d2101034020012008200020082000412010a00841004822091b2206290000370000200141186a200641186a290000370000200141106a200641106a290000370000200141086a200641086a2900003700002000200041206a20091b2100200141206a2101200841206a200820091b2208200a4f0d03200520004b0d000c030b0b201d2101200b21000c010b20082101200b21000b20012000200520006b416071109d081a024020022802f8012201201f4d0d0020022802f001220620216a22002022201e6a3602042000200c360200200120204d0d02200620236a2200200041086a20012020417f736a410374109e081a20022001417f6a22013602f801200141014b0d010c030b0b201f200141bcd0ca001042000b20202001104e000b2001211b0b201c450d060c000b0b1045000b1044000b103c000b200241ec036a4104360200200241dc006a41023602002002420237024c200241f0b2c300360248200241043602e403200241b8b4c3003602e003200241003602f401200241b0b4cc003602f0012002200241e0036a3602582002200241f0016a3602e803200241c8006a4180b3c300104c000b410028028cb54c4105490d042002410d3602e4032002200241c4016a3602e0034100280298b54c21014100280294b54c21004100280290b54c210620024180036a418003360200200241f8026a42b580808010370300200241f4026a4184cac400360200200241ec026a4210370200200241e8026a41f4c9c400360200200241e0026a4201370300200241d0026a4202370300200241c0026a41086a4108360200200241dc026a200241e0036a360200200241dcc9c4003602cc02200241ecc9c4003602c402200241053602c002200041aca2c000200641024622061b200241c0026a200141c4a2c00020061b2802101102000c040b024020022802f40141ffffffff0171450d00200610350b2017450d01201810350c010b20154102490d0020142015417f6a22004105746a21054101210603400240024002400240201520002201417f6a2200490d00201520006b22094102490d03201420014105746a2201201420004105746a2208412010a008417f4a0d03200241c0026a41186a221e200841186a220a290000370300200241c0026a41106a221f200841106a220b290000370300200241c0026a41086a2220200841086a221d290000370300200220082900003703c00220082001290000370000201d200141086a290000370000200b200141106a290000370000200a200141186a2900003700004101210120094103490d02200841c0006a200241c0026a412010a008417f4a0d0241002109200521010340200141186a200141386a290000370000200141106a200141306a290000370000200141086a200141286a2900003700002001200141206a220b29000037000020062009220a460d02200a417f6a2109200141c0006a211d200b2101201d200241c0026a412010a008417f4a0d020c000b0b2000201541dccfca001059000b4102200a6b21010b200820014105746a220120022903c002370000200141186a201e290300370000200141106a201f290300370000200141086a20202903003700000b200541606a21052006417f6a210620000d000b0b200220103602e801200220043602e4012002200e4100200f1b22013602e001200220153602dc01200220133602d801200220143602d401200241003602d0012002201036028004200220043602fc03200220013602f803200220153602f403200220133602f003200220143602ec03200241003602e80320022011410120111b22083602e003200220083602c801200220082012420020111b2207422088a74105746a22013602e403200220013602cc012007a7210c200241e0036a2100200241c8016a21010b20024198026a41086a2206200141086a29020037030020024198026a41106a220a200141106a29020037030020024198026a41186a220b200141186a29020037030020024198026a41206a221d200141206a280200360200200241f0016a41086a221e200241c0026a41086a2205290200370300200241f0016a41106a221f200241c0026a41106a290200370300200241f0016a41186a2220200241c0026a41186a290200370300200241f0016a41206a221c200241c0026a41206a2902003703002002200129020037039802200220022902c0023703f001200241c8016a41206a2201200241e0036a41206a290200370300200241c8016a41186a2214200241e0036a41186a290200370300200241c8016a41106a2221200241e0036a41106a290200370300200241c8016a41086a2222200241e0036a41086a290200370300200220022902e0033703c8012005200c360200200220083602c402200241013602c002200241cc026a2208200229039802370200200241d4026a22052006290300370200200241dc026a2209200a290300370200200241e4026a220a200b290300370200200241ec026a201d280200360200200241003602f002200241f4026a20022903f001370200200241fc026a201e29030037020020024184036a201f2903003702002002418c036a202029030037020020024194036a201c2903003702002002410036029c03200241c0036a2001290300370300200241b8036a2014290300370300200241b0036a2021290300370300200241a8036a2022290300370300200241a0036a20022903c80137030020024190036a211d200241f8026a21012002419c036a2114200241f0026a212020024180036a211e20024188036a211f410021060340024002402006450d00200241286a202010e3030240200228022822064108460d00200228022c211c0c020b024020022802f0022206450d00024020022802f40241ffffff3f71450d00200610350b20022802880341ffffff3f71450d0020022802840310350b20012000290200370200200141086a200041086a290200370200200141106a200041106a290200370200200141186a200041186a290200370200200141206a200041206a2802003602002002200c3602f402200241003602f0020b2009290200210d200920022903f80337020020052902002116200520022903f00337020020082902002112200820022903e803370200200241d0036a41086a220b200a41086a280200360200200241003602e0032002200a2902003703d00320022902c4022107200220022903e0033702c40202402007a72206450d00201d20022903d00337020020012012370300201e2016370300201d41086a200b280200360200201f200d370300200220073703f0020c020b0240200228029c030d00410821060c010b200241206a201410e3032002280224211c200228022021060b02400240200641796a220b41014b0d000240200b0e020200020b024020022802c002450d0020022802c4022201450d00024020022802c80241ffffff3f71450d00200110350b200241dc026a28020041ffffff3f71450d00200241d8026a28020010350b024020022802f0022201450d00024020022802f40241ffffff3f71450d00200110350b20022802880341ffffff3f71450d0020022802840310350b200228029c032201450d030240200241a0036a28020041ffffff3f71450d00200110350b200241b4036a28020041ffffff3f71450d03200241b0036a28020010350c030b2002201c3602cc03200220063602c803410028028cb54c4104490d002002410e3602dc032002410d3602d4032002200241c8036a3602d8032002200241c4016a3602d0034100280298b54c21064100280294b54c210b4100280290b54c211c200241f7023602a004200242b5808080103703980420024184cac400360294042002421037028c04200241f4c9c400360288042002420237038004200242023703f003200241ccc9c4003602ec03200241083602e803200241ecc9c4003602e403200241043602e003200641c4a2c000201c410246221c1b28021021062002200241d0036a3602fc03200b41aca2c000201c1b200241e0036a20061102000b20022802f00221060c000b0b200241e0036a41186a4200370300200241e0036a41106a22064200370300200241e0036a41086a22014200370300200242003703e00341f7edcb00ad4280808080f000841001220029000021072001200041086a290000370300200220073703e0032000103541b6aac000ad4280808080900284100122002900002107200241f0016a41086a2208200041086a290000370300200220073703f00120001035200620022903f0012207370300200241c0026a41086a2001290300370300200241c0026a41106a2007370300200241c0026a41186a2008290300370300200220022903e0033703c002200241186a200241c0026a10f201024020022802184101470d00200228021c2004470d00200241f0016a410041aeb8c300ad4280808080800384100e10c20102400240024020022802f0012201450d00200241f8016a2802004104490d0041fd93ca002100200420012800002206490d01418294ca002100200641056a20044f0d010b2002200436029802200220043602c801200241e0036a41086a200241f0016a41086a280200360200200220022903f0013703e003200241c0026a200241e0036a10e50320022802c4022101410041aeb8c300ad428080808080038420023502c80242208620022802c0022206ad84200241c8016aad4280808080c00084100f210002402001450d00200610350b024020022802e0032201450d0020022802e403450d00200110350b20004101460d010c020b024020022802f401450d00200110350b20000d010b10e6030b20022802b8012108024020022802c0012201450d00200141246c21002008210103400240024020012d0000220641044b0d0002400240024020060e050400010204040b2001410c6a280200450d03200141086a28020010350c030b2001410c6a280200450d02200141086a28020010350c020b2001410c6a280200450d01200141086a28020010350c010b200141086a280200450d00200141046a28020010350b200141246a21012000415c6a22000d000b0b024020022802bc012201450d00200141246c450d00200810350b0240200241c8006a410c6a2802002200450d00200228024c2101200041246c210003400240024020012d0000220641044b0d0002400240024020060e050400010204040b2001410c6a280200450d03200141086a28020010350c030b2001410c6a280200450d02200141086a28020010350c020b2001410c6a280200450d01200141086a28020010350c010b200141086a280200450d00200141046a28020010350b200141246a21012000415c6a22000d000b0b0240200241d0006a2802002201450d00200141246c450d00200228024c10350b2003240042010b9704010d7f230041c0006b220224002002410036021820024204370310200241086a200141046a10bf0302400240024002400240200228020c41246c2203450d002002280208210141042104410021050340024020012d00004101470d00200141106a2802002206417f4c0d03200141036a2d00002107200141016a2f00002108200141086a2802002109200141046a2d0000210a0240024020060d004100210b4101210c0c010b20061033220c450d052006210b0b02400240200b2006490d00200b210d0c010b200b410174220d2006200d20064b1b220d4100480d060240200b0d00200d1033220c0d010c080b200b200d460d00200c200b200d1037220c450d070b20082007411074722107200c20092006109d08210c200241306a41086a2208200241206a41086a29020037030020022002290220370330200e41807e71200a72210e024020052002280214470d00200241106a20054101108d0120022802102104200228021821050b2004200541246c6a220b2006360210200b200d36020c200b200c360208200b200e360204200b20073b0001200b41013a0000200b41036a20074110763a0000200b2002290330370214200b411c6a20082903003702002002200541016a22053602180b200141246a21012003415c6a22030d000b0b20002002290310370200200041086a200241106a41086a280200360200200241c0006a24000f0b1044000b1045000b103e000b103c000b931107047f017e017f017e037f017e017f230041e0006b2205240020054102360208200541306a41186a22064200370300200541306a41106a22074200370300200541306a41086a220842003703002005420037033041d1c4c700ad4280808080e0008422091001220a290000210b200541d0006a41086a220c200a41086a2900003703002005200b370350200a10352008200c290300370300200520052903503703304188f2c700ad4280808080e001841001220a290000210b200c200a41086a2900003703002005200b370350200a103520072005290350220b370300200541106a41086a220a2008290300370300200541106a41106a220d200b370300200541106a41186a220e200c29030037030020052005290330370310200541203602342005200541106a360230200541086a200541306a10cd042005410036023041c4c3c700ad4280808080800284200541306aad4280808080c00084220f100220064200370300200742003703002008420037030020054200370330200910012210290000210b200c201041086a2900003703002005200b370350201010352008200c2903003703002005200529035037033041e7c4c700ad4280808080e0008410012210290000210b200c201041086a2900003703002005200b3703502010103520072005290350220b370300200a2008290300370300200d200b370300200e200c2903003703002005200529033037031020052000360230200541106aad4280808080800484220b200f100220064200370300200742003703002008420037030020054200370330200910012210290000210f200c201041086a2900003703002005200f370350201010352008200c290300370300200520052903503703304185c5c700ad4280808080e0008410012210290000210f200c201041086a2900003703002005200f3703502010103520072005290350220f370300200a2008290300370300200d200f370300200e200c29030037030020052005290330370310200541203602342005200541106a36023020032802002003280208200541306a109606200642003703002007420037030020084200370300200542003703302009100122062900002109200c200641086a29000037030020052009370350200610352008200c2903003703002005200529035037033041edc4c700ad4280808080a00184100122062900002109200c200641086a2900003703002005200937035020061035200720052903502209370300200a2008290300370300200d2009370300200e200c29030037030020052005290330370310024041201033220c450d00200c2001290000370000200c41186a200141186a290000370000200c41106a200141106a290000370000200c41086a200141086a290000370000200b200cad42808080808004841002200c1035200541306a2000417f6a10b803200535023821092005280230210841201033220c450d00200c2001290000370000200c41186a200141186a290000370000200c41106a200141106a290000370000200c41086a200141086a29000037000020094220862008ad84200cad42808080808004841002200c103502402005280234450d00200810350b200541306a41186a22064200370300200541306a41106a220a4200370300200541306a41086a220842003703002005420037033041d1c4c700ad4280808080e00084100122012900002109200541d0006a41086a220c200141086a29000037030020052009370350200110352008200c2903003703002005200529035037033041f7c4c700ad4280808080e00184100122012900002109200c200141086a290000370300200520093703502001103520072005290350370000200741086a200c290300370000200541106a41086a2008290300370300200541106a41106a200a290300370300200541106a41186a20062903003703002005200529033037031041201033220c450d00200c2002290000370000200c41186a200241186a290000370000200c41106a200241106a290000370000200c41086a200241086a290000370000200b200cad42808080808004841002200c103502402004450d00200541306a41186a22014200370300200541306a41106a22024200370300200541306a41086a220842003703002005420037033041d1c4c700ad4280808080e00084220910012206290000210f200541d0006a41086a220c200641086a2900003703002005200f370350200610352008200c2903003703002005200529035037033041cccfc700ad4280808080e0008410012206290000210f200c200641086a2900003703002005200f3703502006103520072005290350370000200741086a2206200c290300370000200541106a41086a220a2008290300370300200541106a41106a220d2002290300370300200541106a41186a220e200129030037030020052005290330370310200b100720014200370300200242003703002008420037030020054200370330200910012203290000210f200c200341086a2900003703002005200f370350200310352008200c290300370300200520052903503703304198f0c700ad4280808080a0018410012203290000210f200c200341086a2900003703002005200f37035020031035200720052903503700002006200c290300370000200a2008290300370300200d2002290300370300200e200129030037030020052005290330370310200b1007200142003703002002420037030020084200370300200542003703302009100122032900002109200c200341086a29000037030020052009370350200310352008200c2903003703002005200529035037033041d2cfc700ad4280808080b00184100122032900002109200c200341086a2900003703002005200937035020031035200720052903503700002006200c290300370000200a2008290300370300200d2002290300370300200e200129030037030020052005290330370310200b10080b200541e0006a24000f0b1045000bf30505017f017e0a7f017e027f230041e0006b220224002002200136020c0240024002402002410c6a10312203422088a722010d0020004100360208200042013702000c010b2002200136021420022003a722043602102002200241106a10c40120022802000d0102400240024020022802042205200228021422064105762201200120054b1b22014105742207417f4c0d0002400240024020010d00410121080c010b200710332208450d010b2001ad21032005450d024100210903402006210a200241003a0058200941016a2109410021010240024002400340200a2001460d01200241386a20016a200228021022072d00003a00002002200741016a3602102002200141016a22073a00582007210120074120470d000b200241186a41186a220b200241386a41186a290300370300200241186a41106a220c200241386a41106a290300370300200241186a41086a220d200241386a41086a290300370300200220022903383703182003422088220ea722012003a7460d012001210f0c020b200241003602140240200141ff0171450d00200241003a00580b200342ffffff3f83500d08200810350c080b0240024002400240200141016a22062001490d00200ea7220f4101742210200620062010491b220641ffffff3f712006470d00200641057422064100480d00024020010d0020060d02410121080c040b2006200f4105742201460d03024020010d0020060d02410121080c040b20082001200610372208450d020c030b103e000b2006103322080d010b103c000b2006410576ad21030b200a20076b21062008200f4105746a22012002290318370000200141186a200b290300370000200141106a200c290300370000200141086a200d290300370000200342ffffffff0f83200f41016aad42208684210320092005470d000b2002200a20076b3602140c030b1045000b1044000b2008450d020b2000200337020420002008360200200410350b200241e0006a24000f0b41b89acc00412e200241386a41a89acc0041d499cc001046000bb90201037f23004180016b2202240002400240024002400240200128020022034110710d002000280200210420034120710d012004ad41012001105221000c020b20002802002104410021000340200220006a41ff006a2004410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d022001410141d88bc0004102200220006a4180016a410020006b105621000c010b410021000340200220006a41ff006a2004410f712203413072200341376a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d022001410141d88bc0004102200220006a4180016a410020006b105621000b20024180016a240020000f0b200441800141c88bc0001059000b200441800141c88bc0001059000bc023030b7f047e0c7f230041c0066b2202240002400240024020012802082203200128020c2204460d002001200341206a220536020820012802102106200241f8026a41186a200341186a290000370300200241f8026a41106a200341106a290000370300200241f8026a41086a200341086a290000370300200220032900003703f8022001280214210702400240024002402001411c6a280200220841014b0d004100210920080e020201020b2008210a4100210903402009200a410176220b20096a220c2007200c4105746a200241f8026a412010a00841004a1b2109200a200b6b220a41014b0d000b0b200720094105746a200241f8026a412010a0080d002006210c0c010b2001200641016a220c3602104108210920052004460d020240200841014d0d0003402001200541206a2203360208200241f8026a41186a200541186a290000370300200241f8026a41106a200541106a290000370300200241f8026a41086a200541086a290000370300200220052900003703f8022008210a4100210903402009200a410176220520096a220b2007200b4105746a200241f8026a412010a00841004a1b2109200a20056b220a41014b0d000b200720094105746a200241f8026a412010a008450d022001200c41016a220c3602102003210520032004460d030c000b0b0240024020080e020100010b03402001200541206a2209360208200241f8026a41186a200541186a290000370300200241f8026a41106a200541106a290000370300200241f8026a41086a200541086a290000370300200220052900003703f80202402007200241f8026a412010a0080d00410021090c030b2001200c41016a220c3602102009210520042009460d030c000b0b2001200436020820012006200420036b41406a4105766a41026a3602100c020b024002400240024002400240024002400240200820094d0d00200241186a200720094105746a220941186a290000220d370300200241106a200941106a290000220e370300200241086a200941086a290000220f3703002002200929000022103703002001200c41016a360210200141286a2802002111200141206a2802002109200141246a280200210a200241206a41186a200d370300200241206a41106a200e370300200241206a41086a200f370300200220103703202002200a36024c200220093602482002200c360244200241f8026a41186a4200370300200241f8026a41106a22054200370300200241f8026a41086a22094200370300200242003703f80241a3edcb00ad4280808080f000841001220a290000210d2009200a41086a2900003703002002200d3703f802200a103541f393ca00ad4280808080a001841001220a290000210d200241b8026a41086a220b200a41086a2900003703002002200d3703b802200a1035200520022903b802220d370300200241d0006a41086a2009290300370300200241d0006a41106a200d370300200241d0006a41186a200b290300370300200220022903f802370350200241f8026a200241d0006a10fe0120022802f8022209410120091b210a02400240200c20022902fc02420020091b220d422088a7490d000240200d42ffffff3f83500d00200a10350b200228024421010c010b200c200a200c4105746a10b90421050240200d42ffffff3f83500d00200a10350b410221092002280244210120050d0c0b200228024c210520022802482106411b10332209450d01200941176a41002800b7cd44360000200941106a41002900b0cd44370000200941086a41002900a8cd44370000200941002900a0cd4437000041041033220a450d01200a20013600002009411b413610372208450d082008200a28000036001b200a1035200241b8026a41002008ad4280808080f00384220d100e10c2010240024002400240024020022802b8022209450d00200241c0026a280200220a4104490d00200a417c714104460d0041000d0020092800002006470d002009280004220a41036a20054b0d010b410410332209450d0c2009200636000020094104410810372209450d0c20092005360004200241d0006a41086a200241b8026a41086a280200360200200220022903b802370350200241f8026a200241d0006a10e50320022802fc02210a4100200d20023502800342208620022802f8022207ad842009ad4280808080800184100f210b0240200a450d00200710350b02402002280250220a450d002002280254450d00200a10350b2009103541042109200b4101470d01200241f8026a10bb0420022802f8022201450d072002418c036a280200211220024188036a280200211320024184036a280200211420024180036a280200211520022802fc022116200228024c211720022802482118200228024421192002410036028003200242013703f802410410332209450d0c200241043602fc02200220093602f8022009201736000020024104360280032015200241f8026a107720022802fc02220520022802800322096b2015490d0220022802f802210a0c030b024020022802bc02450d00200910350b41012109200a21050b20081035200521010c0d0b200920156a220a2009490d082005410174220b200a200b200a4b1b220b4100480d080240024020050d000240200b0d004101210a0c020b200b1033220a0d010c0b0b20022802f802210a2005200b460d00200a2005200b1037220a450d0a0b2002200b3602fc022002200a3602f8020b200a20096a20012015109d081a2002200920156a360280032012200241f8026a10772012450d0220142012410c6c6a21032014210a0340200a2802002104200a41086a2802002209200241f8026a10770240024020022802fc02220b20022802800322056b2009490d0020022802f8022107200b210c0c010b200520096a22072005490d09200b410174220c2007200c20074b1b220c4100480d0902400240200b0d000240200c0d00410121070c020b200c10332207450d0c0c010b20022802f8022107200b200c460d002007200b200c10372207450d0b0b2002200c3602fc02200220073602f8020b200720056a20042009109d081a2002200520096a220936028003200a410c6a220a2003470d000c050b0b200920084190cdc4001042000b1045000b20022802fc02210c20022802800321090c010b41012109410521170c010b02400240200c20096b4104490d0020022802f802210a200c21050c010b200941046a220a2009490d03200c4101742205200a2005200a4b1b22054100480d0302400240200c0d00024020050d004101210a0c020b20051033220a450d060c010b20022802f802210a200c2005460d00200a200c20051037220a450d050b200220053602fc022002200a3602f8020b200a20096a20183600002002200941046a220b3602800302402005200b6b41034b0d00200b41046a2207200b490d032005410174220c2007200c20074b1b22074100480d030240024020050d00024020070d004101210a0c020b20071033220a450d060c010b20052007460d00200a200520071037220a450d050b200220073602fc022002200a3602f8020b200a200b6a20193600002002200941086a2205360280030240024020022802fc02220b20056b4104490d0020022802f802210a200b21070c010b200541046a220a2005490d03200b4101742207200a2007200a4b1b22074100480d0302400240200b0d00024020070d004101210a0c020b20071033220a450d060c010b20022802f802210a200b2007460d00200a200b20071037220a450d050b200220073602fc022002200a3602f8020b200a20056a2011360000200241f8026a41e9dabdf306200241206a200a2009410c6a10bc04410121090240024020022d00f8024101460d00410321050c010b200241f6026a20022d00fb023a0000200241b8026a41086a2002418c036a290200370300200241c8026a20024194036a290200370300200241d0026a2002419c036a290200370300200241d8026a200241a4036a290200370300200241e0026a200241ac036a290200370300200241e5026a200241b1036a290000370000200220022f00f9023b01f4022002200241f8026a410c6a2902003703b802200241f8026a41086a280200210b4100210920022802fc0221050b200241b4026a41026a220c200241f4026a41026a2d00003a0000200241f8016a41086a2204200241b8026a41086a290300370300200241f8016a41106a2203200241b8026a41106a290300370300200241f8016a41186a221a200241b8026a41186a290300370300200241f8016a41206a221b200241b8026a41206a290300370300200241f8016a41286a221c200241b8026a41286a290300370300200241f8016a41306a200241b8026a41306a290300370300200220022f01f4023b01b402200220022903b8023703f801024020090d00200241f4016a41026a200c2d00003a0000200241f8026a41086a2004290300370300200241f8026a41106a2003290300370300200241f8026a41186a201a290300370300200241f8026a41206a201b290300370300200241f8026a41286a201c290300370300200241f8026a412d6a200241f8016a412d6a290000370000200220022f01b4023b01f401200220022903f8013703f80202402007450d00200a10350b200220022f01f4013b01b8022002200241f6016a2d00003a00ba02410021090c020b02402007450d00200a10350b02402016450d00200110350b02402012450d002012410c6c210a2014210903400240200941046a280200450d00200928020010350b2009410c6a2109200a41746a220a0d000b0b4101210902402013450d002013410c6c450d00201410350b20052117200b21010b0b200241b8016a41086a220a200241f8026a41086a290300370300200241b8016a41106a2207200241f8026a41106a290300370300200241b8016a41186a220c200241f8026a41186a290300370300200241b8016a41206a2204200241f8026a41206a290300370300200241b8016a41286a2203200241f8026a41286a290300370300200241b8016a412d6a221a200241f8026a412d6a290000370000200220022d00ba023a00f201200220022f01b8023b01f001200220022903f8023703b80102400240024020090d00200241d0006a41186a2012360200200241d0006a41146a2013360200200241d0006a41106a2014360200200241d0006a410c6a2015360200200241d0006a41086a2016360200200241fa006a20022d00f2013a0000200241ff006a200b360000200241fb006a200536000020024183016a20022903b8013700002002418b016a200a29030037000020024193016a20072903003700002002419b016a200c290300370000200241a3016a2004290300370000200241ab016a2003290300370000200241b0016a201a29000037000020022011360274200220193602702002201836026c2002200136025420022017360250200220022f01f0013b01780240410028028cb54c4103490d00200241b8026a411c6a410f360200200241b8026a41146a410d360200200241b8026a410c6a410d3602002002410d3602bc022002200241d0006a3602d0022002200241c8006a3602c8022002200241cc006a3602c0022002200241c4006a3602b8024100280298b54c21094100280294b54c210a4100280290b54c2105200241b8036a418104360200200241b0036a42b580808010370300200241ac036a4184cac400360200200241a4036a4210370200200241a0036a41f4c9c40036020020024198036a420437030020024188036a4204370300200241f8026a41086a4108360200200241f8026a411c6a200241b8026a360200200241bccdc40036028403200241ecc9c4003602fc02200241033602f802200a41aca2c000200541024622051b200241f8026a200941c4a2c00020051b2802101102000b2002411336029004200242023703e00320024194046a200241d0006a41e800109d081a2002200241f8026a3602f801200241b8026a200241f8016a10b90320022802b80220022802bc0220022802c00210a004210a20024190046a10ba024107210941062117200a0d010c020b4107210920174107460d010b410410332209450d022009200636000020094104410810372209450d02200941003600044100200d2009ad4280808080800184101620091035201721090b200810350c040b103e000b103c000b410821090b0b2000200136020420002009360200200241c0066a24000bef0401017f230041306b220224000240024002400240024002400240024020002802000e0701020304050600010b2001411c6a2802002100200128021821012002412c6a4100360200200241b0b4cc003602282002420137021c200241e4cac40036021820012000200241186a104321010c060b2002200041046a36020c2002410c3602142001411c6a280200210020022002410c6a360210200128021821012002412c6a41013602002002420137021c200241eccac4003602182002200241106a36022820012000200241186a104321010c050b2002200041046a36020c2002410c3602142001411c6a280200210020022002410c6a360210200128021821012002412c6a41013602002002420237021c200241f4cac4003602182002200241106a36022820012000200241186a104321010c040b2002200028020436020c200241013602142001411c6a280200210020022002410c6a360210200128021821012002412c6a41013602002002420237021c20024184cbc4003602182002200241106a36022820012000200241186a104321010c030b2001411c6a2802002100200128021821012002412c6a4100360200200241b0b4cc003602282002420137021c20024194cbc40036021820012000200241186a104321010c020b2001411c6a2802002100200128021821012002412c6a4100360200200241b0b4cc003602282002420137021c2002419ccbc40036021820012000200241186a104321010c010b2001411c6a2802002100200128021821012002412c6a4100360200200241b0b4cc003602282002420137021c200241a4cbc40036021820012000200241186a104321010b200241306a240020010ba50301067f230041106b22022400024002400240200128020022030d00410121040c010b0240200141086a28020041056a2204417f4c0d0020040d0141002104410121050c020b1044000b2004103322050d001045000b200241003602082002200536020020022004360204024002400240024020030d00024020040d00410110332205450d0420024101360204200220053602000b200541003a0000410121040c010b024020040d00410110332205450d0320024101360204200220053602000b200541013a000020024101360208200141086a2802002204200210770240024020022802042206200228020822056b2004490d00200228020021010c010b200520046a22012005490d02200641017422072001200720014b1b22074100480d020240024020060d00024020070d00410121010c020b2007103322010d010c050b2002280200210120062007460d0020012006200710372201450d040b20022007360204200220013602000b200120056a20032004109d081a200520046a21040b20002002290300370200200041086a2004360200200241106a24000f0b103e000b103c000bde940111027f017e087f017e017f027e037f017e0a7f037e087f027e017f027e037f017e187f230041c0076b22002400200041003602e805200042083703e005200041003602f805200042013703f00541f7edcb00ad4280808080f00084100122012900002102200041f0066a41086a2203200141086a290000370300200020023703f0062001103541f393ca00ad4280808080a00184100122012900002102200041a0076a41086a2204200141086a290000370300200020023703a00720011035024002400240024002400240024002400240412010332201450d00200120002903f006370000200120002903a007370010200141086a2003290300370000200141186a22052004290300370000412010332203450d0020032001290000370000200341186a2005290000370000200341106a200141106a290000370000200341086a200141086a290000370000200041b0066a41026a220420004198026a41026a2d00003a0000200020002f0098023b01b006200041d0066a41106a42a0808080800437030041002106200041003a00e806200020013602dc06200042a080808080043702d406200020033602d006200041eb066a20042d00003a0000200020002f01b0063b00e90620004198026a200041d0066a10c701024002400240024002402000280298024101470d0020004198026a410472210741012108410821094100210a034020004180066a41206a200741206a28020036020020004180066a41186a2201200741186a290200220237030020004180066a41106a2205200741106a290200220b37030020004180066a41086a220c200741086a290200220d37030020002007290200220e37038006200041f0066a41186a220f2002370300200041f0066a41106a2210200b370300200041f0066a41086a2211200d3703002000200e3703f00620004198026a41186a2203200129030037030020004198026a41106a2204200529030037030020004198026a41086a2205200c290300370300200020002903800637039802200041f0066a10c801210241201033220c450d02200c20002903f006370000200c41186a200f290300370000200c41106a2010290300370000200c41086a2011290300370000200041a0076a41086a2005290300220b370300200041a0076a41106a2004290300220d370300200041a0076a41186a2003290300220e370300200020002903980222123703a0072003200e3703002004200d3703002005200b37030020002012370398020240200a20002802e405470d00200041e0056a200a4101108b0120002802e005210920002802e805210a0b2009200a41386c6a22012002370300200529030021022004290300210b2003290300210d200029039802210e2001412c6a4281808080103702002001200c3602282001200e370308200141206a200d370300200141186a200b370300200141106a20023703002000200a41016a220a3602e8052003200f2903003703002004201029030037030020052011290300370300200020002903f006370398020240200620002802f405470d00200041f0056a20064101108a0120002802f005210820002802f80521060b200820064105746a2201200029039802370000200141186a2003290300370000200141106a2004290300370000200141086a20052903003700002000200641016a22063602f80520004198026a200041d0066a10c7012000280298024101460d000b0b024020002802d406450d0020002802d00610350b024020002802e006450d0020002802dc0610350b41f7edcb00ad4280808080f00084100122012900002102200041f0066a41086a2203200141086a290000370300200020023703f0062001103541cca9c000ad4280808080a00184100122012900002102200041a0076a41086a2204200141086a290000370300200020023703a00720011035412010332201450d04200120002903f006370000200120002903a007370010200141086a2003290300370000200141186a22052004290300370000412010332203450d0420032001290000370000200341186a2005290000370000200341106a200141106a290000370000200341086a200141086a29000037000020004188026a41026a220520004198026a41026a2d00003a0000200020002f0098023b01880220004198026a41106a220442a08080808004370300200041003a00b002200020013602a402200042a0808080800437029c022000200336029802200041b3026a20052d00003a0000200020002f0188023b00b102200041e0056a20004198026a10c90120004198026a41186a220642003703002004420037030020004198026a41086a22014200370300200042003703980241f7edcb00ad4280808080f00084220210012205290000210b200041f0066a41086a2203200541086a2900003703002000200b3703f0062005103520012003290300370300200020002903f0063703980241c1edcb00ad4280808080e001841001220c290000210b200041a0076a41086a2205200c41086a2900003703002000200b3703a007200c1035200420002903a007220b37030020004180066a41086a2207200129030037030020004180066a41106a220a200b37030020004180066a41186a220f2005290300370300200020002903980237038006200041b0016a20004180066a412010c00120002802b401211320002802b0012114200642003703002004420037030020014200370300200042003703980220021001220c29000021022003200c41086a290000370300200020023703f006200c103520012003290300370300200020002903f0063703980241cfedcb00ad4280808080d002841001220329000021022005200341086a290000370300200020023703a00720031035200420002903a007220237030020072001290300370300200a2002370300200f2005290300370300200020002903980237038006200041a8016a20004180066a412010c00120002802ac01210520002802a801210c20002802f005211520002802f405211620002802e005211720002802e405211820002802f805210120002802e8052119200041003602d801200041003602d001201920016aad42e0007e2202422088a70d052002a72203417f4c0d054108210402402003450d00200310332204450d050b20054104200c1b221a41014b211b200041003602d806200020043602d0062000200341e0006e3602d406200041003602a807200042083703a007200041a0076a410020014105742205410575109b0120002802a807210902402001450d00200541606a410576211c20002802a007200941d8006c6a210c200041c8026a2103200041c0026a210841002104201521010340200041b0066a41186a2206200141186a2207290000370300200041b0066a41106a220a200141106a220f290000370300200041b0066a41086a2210200141086a2211290000370300200020012900003703b00620004180066a41186a200729000037030020004180066a41106a200f29000037030020004180066a41086a20112900003703002000200129000037038006200041d0016a20004180066a200410840320004198026a41086a420037030020004198026a41106a420037030020004198026a41186a420037030020004198026a41206a420037030020084200370300200341186a2006290300370300200341106a200a290300370300200341086a2010290300370300200320002903b0063703002000420037039802200c20004198026a41d000109d08220c41d0006a41003a0000200c41d8006a210c200141206a2101200441016a2104200541606a22050d000b2009201c6a41016a21090b201a4101201b1b2101200020093602a8070240201641ffffff3f71450d00201510350b200041f0066a41086a200041a0076a41086a2802002203360200200020002903a0073703f0060240024020032001490d00200041d0066a20002802d806201941386c220341386d10a40120002802d006210420002802d8062101200041ac026a200041f0066a3602002000201720036a3602a402200020173602a0022000201836029c0220002017360298022000200041d0016a3602a80220004180066a41086a20013602002000200041d8066a3602840620002004200141e0006c6a3602800620004198026a20004180066a109a042013410020141b2215ad42307e2202422088a70d072002a72203417f4c0d0720002802f80621010240024020030d00410821080c010b200310332208450d070b200041003602980720002008360290072000200341306e360294072015412c6c2203417f4c0d070240024020030d00410421130c010b200310332213450d070b41002117200041003602c001200020153602bc01200020133602b801410021142001201520012015491b221c0d010c040b024020002802f4062201450d00200141d8006c450d0020002802f00610350b024020002802d8062201450d00200141e0006c210320002802d00641346a21010340024020012802002204450d00200441c8006c450d002001417c6a28020010350b200141e0006a2101200341a07f6a22030d000b0b024020002802d4062201450d00200141e0006c450d0020002802d00610350b200041d0016a10b10102402019450d00201941386c21032017412c6a210103400240200128020041ffffff3f71450d002001417c6a28020010350b200141386a2101200341486a22030d000b0b410021082018450d02201841386c450d02201710350c040b20004198026a41186a211a20004198026a41106a210920004198026a41086a211b41002116034020002802f006210402402001450d00200141d8006c21032004210103400240200141d0006a2d00000d0002400240200141206a290300220b200141286a290300220d8450450d0042002102427f210b427f210d0c010b427f210220004198016a427f427f200b200d10980820004198016a41086a290300210d200029039801210b0b2001200b3703002001200d370308200141106a2002370300200141186a20023703000b200141d8006a2101200341a87f6a22030d000b0b0240024020002802d8062201450d0020002802d0062205200141e0006c6a210a0340024020052802382201450d00200141c8006c2104200528023041206a2101034020002802f806220c200128020022034d0d04024020002802f006200341d8006c6a22032d00500d0020032903202202200341286a290300220b84500d0020004198026a2005290310200541186a2903002005290300200541086a2903002002200b109b04200320032903002202427f2002427f20002903a002200028029802410146220c1b220d7c220b200b2002542206200341086a22072903002202427f2009290300200c1b220e7c2006ad7c220b200254200b2002511b220c1b200d200e845022061b37030020072002427f200b200c1b20061b3703000b200141c8006a2101200441b87f6a22040d000b0b200541e0006a2205200a470d000b20002802f00621040b201641016a211620002802f80641d8006c2101200441a87f6a210303402001450d05200141a87f6a2101200341d8006a2103200441d0006a2105200441d8006a220c210420052d00000d000b02402001450d00200341086a2903002102200341186a290300210b200341106a290300210d2003290300210e4100210403400240200c20046a220541d0006a2d00000d00200541086a29030022122002200e2002200d200b2005290300221d2012200541106a290300221e200541186a290300221f109c0441ff017141014622061b2102201d200e20061b210e201f200b20061b210b201e200d20061b210d2005200320061b21030b2001200441d8006a2204470d000b2003450d050b200341013a0050024020002802d8062201450d0020002802d0062204200141e0006c6a21182003410c6a2110200341306a21110340200441e0006a2119024020042802382205450d0020042802302101200541c8006c210503400240024020102001460d00200141246a2011412010a0080d010b200441186a220c290300210e200341086a220629030021022004290310210d2003290300210b20032903102112200141186a200341186a2207290300370300200141106a20123703002001200242002002200e7d200b200d54ad7d2212200b200d7d221d200b56201220025620122002511b220a1b200d200e8450220f1b3703082001200b4200201d200a1b200f1b370300200629030021022007290300210b2003290300210d20042003290310370320200441286a200b3703002004200d370310200c20023703000b200141c8006a2101200541b87f6a22050d000b0b2019210420192018470d000b0b201a200341c8006a2900003703002009200341c0006a290000370300201b200341386a2900003703002000200329003037039802200341286a29030021022003290320210b02402014200028029407470d0020004190076a20144101108801200028029007210820002802980721140b2008201441306c6a2201200029039802370300201b290300210d2009290300210e201a29030021122001200b370320200141286a2002370300200141186a2012370300200141106a200e370300200141086a200d3703002000201441016a2214360298072016201c4f0d0420002802f80621010c010b0b2003200c41f4c4c8001042000b103c000b0c010b024020002802d8062201450d0020002802d0062210200141e0006c6a2115201441306c21192000418c066a221841186a2116201841106a211a201841086a211b4100211703402018201029003c3700002016201041d4006a290000370000201a201041cc006a290000370000201b201041c4006a29000037000020004100360288062000420237038006024020102802382201450d002010280230220a200141c8006c6a2111201041106a2109410021074102210f0340200a220641246a2104200641c8006a210a410021052019210320082101024003402003450d01024020042001460d0020012004412010a008210c200541016a2105200341506a2103200141306a2101200c0d010b0b41ffff032103024020092006109d040d00410021032006290310201029032085200641186a290300201041286a29030085844200520d0020004198026a42ffff0342002006290300200641086a2903002009290300200941086a290300109b04427f20002903a00220002802980241014622011b2202a7417f200242808004544100427f20004198026a41106a29030020011b501b1b21030b20004198026a41186a22042006413c6a29000037030020004198026a41106a2205200641346a29000037030020004198026a41086a220c2006412c6a290000370300200020062900243703980202402007200028028406470d0020004180066a20074101109e01200028028006210f20002802880621070b200f200741226c6a2201200029039802370100200c29030021022005290300210b2004290300210d200120033b0120200141186a200d370100200141106a200b370100200141086a20023701002000200741016a2207360288060b200a2011470d000b0240024002402007450d002007417f200741808004491b210602400240200741226c22040d00410021030c010b200f41206a2101410021030340417f2003411074220320012f01004110746a220520052003491b4110762103200141226a21012004415e6a22040d000b0b200641ffff03712201450d012003417f73220a41ffff0371220320016e210c0240200120034b0d00200f41206a210141002103034020072003460d042001417f20012f01004110742204200c4110746a220520052004491b4110763b0100200141226a21012007200341016a2203470d000b0b0240200a200c20066c6b41ffff03712205450d00410021010340200f200120077041226c6a2203417f20032f01204110742203418080046a220420042003491b4110763b0120200141016a22012005490d000b0b20004198026a41286a220320004180066a41286a28020036020020004198026a41206a220420004180066a41206a29030037030020004198026a41186a220520004180066a41186a29030037030020004198026a41106a220c20004180066a41106a29030037030020004198026a41086a220620004180066a41086a2903003703002000200029038006370398020240201720002802bc01470d00200041b8016a2017410110980120002802b801211320002802c00121170b20132017412c6c6a2201200029039802370200200141286a2003280200360200200141206a2004290300370200200141186a2005290300370200200141106a200c290300370200200141086a20062903003702002000201741016a22173602c0010c030b2000280284062201450d02200141226c450d02200f10350c020b41f0b8c80041194194c5c800103f000b200320074184c5c8001042000b201041e0006a22102015470d000b20002802bc0121150b2000280294072105024020002802f4062201450d00200141d8006c450d0020002802f00610350b024020002802d8062201450d00200141e0006c210320002802d00641346a21010340024020012802002204450d00200441c8006c450d002001417c6a28020010350b200141e0006a2101200341a07f6a22030d000b0b024020002802d4062201450d00200141e0006c450d0020002802d00610350b200041d0016a10b1010b2008450d0820004198026a41186a220c420037030020004198026a41106a2220420037030020004198026a41086a22014200370300200042003703980241f7edcb00ad4280808080f00084220b1001220329000021022001200341086a2900003703002000200237039802200310354192aac000ad4280808080a00284100122042900002102200041a0076a41086a2203200441086a290000370300200020023703a00720041035202020002903a007220237030020004180066a41086a2207200129030037030020004180066a41106a220a200237030020004180066a41186a220f2003290300370300200020002903980237038006200041f0066a20004180066a10fe0120002802f0062206450d07200020002902f406220d3702ec01200020063602e801200c420037030020204200370300200142003703002000420037039802200b1001220429000021022001200441086a29000037030020002002370398022004103541a4aac000ad4280808080a002841001220429000021022003200441086a290000370300200020023703a00720041035202020002903a007370000202041086a200329030037000020072001290300370300200a2020290300370300200f200c290300370300200020002903980237038006200041f0066a20004180066a10fe0120002802f0062201450d06200020002902f4063702fc01200020013602f801200041003602a002200042013703980220004198026a4100201441306c220441306d108a0120002802a002212102402014450d0020002802980220214105746a2101200821030340200341086a2900002102200341106a290000210b2003290000210d200141186a200341186a290000370000200141106a200b370000200141086a20023700002001200d370000202141016a2121200141206a2101200341306a2103200441506a22040d000b0b200020213602a00202402005450d00200541306c450d00200810350b200028029c0221222000280298022123200041003602a807200042043703a007200041a0076a41002017412c6c2203412c6d10980120002802a007210420002802a80721012000201320036a3602a402200020133602a0022000201536029c0220002013360298022000200041f0066a3602a80220004180066a41086a20013602002000200041a0076a41086a36028406200020042001412c6c6a3602800620004198026a20004180066a109d0220004188026a41086a220120002802a807360200200020002903a0073703880220004188026a10ab0220004198026a2023202120002802880222242001280200220110cc01200041e0056a41086a20004198026a41086a220a28020036020020002000290398023703e00510142203280000210420031035024020044106702225450d00410021260340024020010d00410021010c020b20242001412c6c6a212742002128420021290240034002400240202441086a222a28020041306c22030d004200210b420021020c010b202428020041206a21014200210b420021020340427f2002200141086a2903007c200b20012903007c220d200b542204ad7c220b2004200b200254200b2002511b22041b2102427f200d20041b210b200141306a2101200341506a22030d000b0b2000200041e0056a3602a0074200212b4200212c02400240202a28020022014102490d002024280200210802400240200141306c22050d004200210e4200210d0c010b200841206a21014200210e200521034200210d0340427f200d200141086a2903007c200e20012903007c2212200e542204ad7c220e2004200e200d54200e200d511b22041b210d427f201220041b210e200141306a2101200341506a22030d000b0b2024410c6a2106200820056a21112008210f024002400240024002400240024003400240200f220c2011470d004100212d4108212e0c020b200c41306a210f200c41206a290300200c41286a29030084500d0020002802e0052207450d0020002802e40521100340200741086a210320072f010622094105742101410021040240024003402001450d01200c2003412010a0082205450d02200141606a2101200441016a2104200341206a21032005417f4a0d000b2004417f6a21090b2010450d022010417f6a2110200720094102746a41c8056a28020021070c010b0b0b200720044105746a220141f0026a2903002112200141e8026a290300211d41101033222e450d0d202e201d370300202e2012370308200042818080801037029c022000202e360298024101211902400340200f220c2011460d01200c41306a210f200c41206a290300200c41286a29030084500d0020002802a00722012802002207450d00200128020421100340200741086a210320072f010622094105742101410021040240024003402001450d01200c2003412010a0082205450d02200141606a2101200441016a2104200341206a21032005417f4a0d000b2004417f6a21090b2010450d022010417f6a2110200720094102746a41c8056a28020021070c010b0b200720044105746a220141f0026a2903002112200141e8026a290300211d02402019200028029c02470d0020004198026a20194101109a01200028029802212e0b202e20194104746a220120123703082001201d3703002000201941016a22193602a0020c000b0b200028029c02212d20190d010b200b212b2002212c0c010b20194104742203450d01202e2109024020194101460d00202e41106a2101200341706a2103202e21090340200920012009290300200129030056200941086a2903002212200141086a290300221d562012201d511b1b2109200141106a2101200341706a22030d000b2009450d020b20002802a00721180240024003402008220c2011460d01200c41306a210820182802002219450d002019210720182802042217210f0340200741086a210320072f01062210410574210141002104024003402001450d01200c2003412010a0082205450d05200141606a2101200441016a2104200341206a21032005417f4a0d000b2004417f6a21100b200f450d01200f417f6a210f200720104102746a41c8056a28020021070c000b0b0b41acc6c800413241e0c6c8001064000b200720044105746a220141f0026a2903002112200141e8026a290300211d024020082011460d0003402008220c41306a2108201921072017210f02400340200741086a210320072f010622104105742101410021040240024003402001450d01200c2003412010a0082205450d02200141606a2101200441016a2104200341206a21032005417f4a0d000b2004417f6a21100b200f450d02200f417f6a210f200720104102746a41c8056a28020021070c010b0b200720044105746a220141f0026a290300221e2012201d200141e8026a290300221f562012201e562012201e511b22011b2112201f201d20011b211d0b20082011470d000b0b427f4200200941086a290300221e20127d20092903002212201d54ad7d221f2012201d7d221d201256201f201e56201f201e511b22011b221242002002200d7d200b200e54ad7d220d200b200e7d220e200b56200d200256200d2002511b22031b7c4200201d20011b220d4200200e20031b7c220e200d542201ad7c220d2001200d201254200d2012511b22011b212c427f200e20011b212b0b202428020021010240202a280200220341306c2204450d00200120046a211c03402001210c024020002802a00722012802002207450d002001280204210f0340200741086a210320072f010622104105742101410021040240024003402001450d01200c2003412010a0082205450d02200141606a2101200441016a2104200341206a21032005417f4a0d000b2004417f6a21100b200f450d02200f417f6a210f200720104102746a41c8056a28020021070c010b0b200720044105746a220141e8026a220342002003290300220d200c29032022127d220e200e200d56200141f0026a2203290300220e200c41286a2903007d200d201254ad7d220d200e56200d200e511b22041b37030020034200200d20041b37030020014180036a222f2802002207450d00200141f8026a28020021014100210341002104034002400240024020062001460d0020012006412010a008450d0020030d01410021030c020b200341016a21030c010b200420036b220520074f0d0620004198026a41286a220f2001200341506c6a220541286a221029030037030020004198026a41206a2211200541206a220829030037030020004198026a41186a2209200541186a221929030037030020004198026a41106a2217200541106a2218290300370300200a200541086a22152903003703002000200529030037039802200141086a2216290300210d200141106a221a290300210e200141186a221b2903002112200141206a2213290300211d200141286a2214290300211e200520012903003703002010201e3703002008201d370300201920123703002018200e3703002015200d3703002014200f29030037030020132011290300370300201b2009290300370300201a20172903003703002016200a29030037030020012000290398023703000b200141306a21012007200441016a2204470d000b2003450d00202f280200200720036b2201490d00202f20013602000b200c4200370320200c41286a4200370300200c41306a2201201c470d000b202a2802002103202428020021010b2000200041a0076a36028006200020004180066a360298022001200320004198026a410041202003676b109e04202a2802002215417f6a21182024280200220c201541306c22016a2109024020010d004200210d4200210e0c040b20002802a007221728020021194200210d410021084200210e200c2107034002402019450d00201728020421102019210f0340200f41086a2103200f2f010622114105742101410021040240024003402001450d0120072003412010a0082205450d02200141606a2101200441016a2104200341206a21032005417f4a0d000b2004417f6a21110b2010450d022010417f6a2110200f20114102746a41c8056a280200210f0c010b0b200041e8006a200f20044105746a220141f0026a290300223042002008ad2212420010840820004188016a200141e8026a290300221e420020124200108408200041f8006a42004200201e42001084084200427f20002903880120002903702000290380018442005220004188016a41086a2903002212200029036820002903787c7c221d2012547222011b2212200d7d221f201f201256427f201d20011b221d200e7d2012200d54ad7d2212201d562012201d511b22011b200b564200201220011b221220025620122002511b0d04427f200e20307c200d201e7c2212200d542201ad7c220d2001200d200e54200d200e511b22011b210e427f201220011b210d0b200841016a2108200741306a22072009470d000c040b0b41ecc5c8004130419cc6c8001064000b2005200741f485cc001042000b41002008417f6a2201200120084b1b21180b201520184d0d01200041386a200c201841306c6a220141286a290300221e4200201841016a2211ad22124200108408200041d8006a2001290320221d420020124200108408200041c8006a42004200201d42001084084200427f2002200e7c200b200d7c220d200b542201ad7c220b2001200b200254200b2002511b22011b2202427f200041d8006a41086a290300220b200029033820002903487c7c220e2000290340200029035084420052200e200b547222031b7d427f200d20011b220b427f200029035820031b220e54ad7d220d200b200e7d220e200b56200d200256200d2002511b22011b211f4200200e20011b2130024003402009200c460d012011417f6a2111024020002802a00722012802002207450d002001280204210f0340200741086a210320072f010622104105742101410021040240024003402001450d01200c2003412010a0082205450d02200141606a2101200441016a2104200341206a21032005417f4a0d000b2004417f6a21100b200f450d02200f417f6a210f200720104102746a41c8056a28020021070c010b0b200041286a2030201f20124200109808200c41286a220f4200427f200041286a41086a2903002202201e7c2000290328220b201d7c220d200b542201ad7c220b2001200b200254200b2002511b22051b2202200720044105746a220141f0026a22032903007d427f200d20051b220b200141e8026a2204290300220e54ad7d220d200b200e7d220e200b56200d200256200d2002511b22051b220b370300200c4200200e20051b22023703202004427f2004290300220d20027c22022002200d54220520032903002202200b7c2005ad7c220b200254200b2002511b22051b3703002003427f200b20051b370300200041b0066a41186a2207200641186a290000370300200041b0066a41106a2210200641106a290000370300200041b0066a41086a2208200641086a290000370300200020062900003703b006200141f8026a2105200f2903002102200c290320210b024020014180036a22032802002204200141fc026a280200470d00200520044101108801200328020021040b2005280200200441306c6a220120002903b0063703002001200b370320200141186a2007290300370300200141106a2010290300370300200141086a2008290300370300200141286a20023703002003200328020041016a3602000b200c41306a210c20110d000b0b202d41ffffffff0071450d00202e10350b202c2029202b202856202c202956202c2029511b22011b2129202b202820011b21282024412c6a22242027460d020c010b0b2018201541f0c6c8001042000b02400240202641016a222620254f0d0020282029844200520d010b200028029002210120002802880221240c020b200028028802212420002802900221010c000b0b200028028c02212a200041003602f805200042043703f005200041f0056a41002001412c6c2203412c6d109801202420036a211a20002802f805211502400240024020010d002024210f0c010b20002802f0052015412c6c6a2111200041d0066a41186a211b200041d0066a41106a2113200041d0066a41086a21142024210f0340200f2802082104200f2802042116200f2802002118201b200f41246a2902003703002013200f411c6a2902003703002014200f41146a2902003703002000200f29020c3703d006200f412c6a210f2018450d01200041f0066a41186a221c201b290300370300200041f0066a41106a222f2013290300370300200041f0066a41086a222e2014290300370300200020002903d0063703f0062018200441306c22036a21050240024020030d00420021024200210b0c010b201841206a2101420021024200210b0340200141086a290300200b7c2001290300220b20027c2202200b54ad7c210b200141306a2101200341506a22030d000b0b02400240024020052018460d00200441306c2103201821010340200141286a290300210d200141206a290300210e200041b0066a41186a220c200141186a290300370300200041b0066a41106a2206200141106a290300370300200041b0066a41086a2207200141086a290300370300200020012903003703b006200e200d2002200b109f04220441ffff03710d02200141306a2101200341506a22030d000b0b4200210d410021014102211002402016450d00201641306c450d00201810354200210d0b4200211d410021050c010b200041a0076a41086a22052007290300370300200041a0076a41106a220a2006290300370300200041a0076a41186a2208200c290300370300200020002903b006220d370380062000200d3703a007412210332210450d04201020002903a007370100201020043b0120201041186a2008290300370100201041106a200a290300370100201041086a200529030037010020004281808080103702940720002010360290072004ad210d0240024020034130470d00200d42ffff0383210d4200211d410121050c010b200341a07f6a2117200d42ffff0383210e4200211d41012105410021040340200120046a220341d8006a290300210d200341d0006a2903002112200c200341c8006a2903003703002006200341c0006a2903003703002007200341386a2903003703002000200341306a2903003703b006024002402012200d2002200b109f04220a41ffff03710d00200e210d20172004460d030c010b20004180066a41086a2007290300220d37030020004180066a41106a2006290300221237030020004180066a41186a200c290300221e370300200020002903b006221f3703800620004198026a41186a2208201e37030020004198026a41106a2209201237030020004198026a41086a2219200d3703002000201f37039802200e200aad42ffff03837c220d200e54ad210e02402005200028029407470d0020004190076a20054101109e0120002802900721100b201d200e7c211d2010200541226c6a22032000290398023701002019290300210e200929030021122008290300211e2003200a3b0120200341186a201e370100200341106a2012370100200341086a200e3701002000200541016a22053602980720172004460d020b200441306a2104200d210e0c000b0b02402016450d00201641306c450d00201810350b20002802940721010b0240024042ffff03200d7d220b42ffff03564200201d200d42ffff0356ad7c7d220242005220025022031b4101470d00200d4281807c7c2202200d56201d200d42ffff0354ad7d220b201d56200d42feff03561b0d012005450d01200541226c20106a417e6a2203410020032f010041107422032002a7417f200242808004544100200b501b1b4110746b2204200420034b1b4110763b01000c010b2005450d00200541226c20106a417e6a2204417f20042f01004110742204200ba7417f200b4280800454410020031b1b4110746a220320032004491b4110763b01000b20004198026a41186a2203201c29030037030020004198026a41106a2204202f29030037030020004198026a41086a220c202e290300370300200020002903f00637039802201120013602042011200536020820112010360200201120002903980237020c201141146a200c2903003702002011411c6a2004290300370200201141246a2003290300370200201541016a21152011412c6a2111200f201a470d000b200020153602f8050c010b200020153602f805200f201a460d000340200f2201412c6a210f0240200141046a2802002203450d00200341306c450d00200128020010350b201a200f470d000b0b0240202a450d00202a412c6c450d00202410350b2015ad422c7e2202422088a70d012002a72201417f4c0d0120002802f405211720002802f00521090240024020010d00410421030c010b200110332203450d010b200041003602a807200020033602a00720002001412c6e3602a407200041a0076a4100201510980120002802a80721010240024020150d0020002802a00721080c010b20092015412c6c6a211120002802a00722082001412c6c6a210620012015410274417c6a4102766a2119200041a4026a2107200041b0066a41186a210a200041b0066a41106a210f200041b0066a41086a21102009210c0340200a200c41246a290200370300200f200c411c6a2902003703002010200c41146a2902003703002000200c29020c3703b006200c2802082203ad42227e2202422088a70d032002a72204417f4c0d03200c28020021010240024020040d00410221050c010b200410332205450d030b200c412c6a210c200041003602880620002005360280062000200441226e3602840620004180066a41002003109e01200028028806210402402003450d00200341226c2105200028028006200441226c6a21030340200141086a2901002102200141106a290100210b200141186a290100210d2001290100210e200341206a200141206a2f01003b0100200341186a200d370100200341106a200b370100200341086a20023701002003200e370100200341226a2103200441016a2104200141226a21012005415e6a22050d000b0b20004198026a41086a220120043602002000200029038006220237039802200741186a200a290300370200200741106a200f290300370200200741086a2010290300370200200720002903b006370200200641286a20004198026a41286a280200360200200641206a20004198026a41206a290300370200200641186a20004198026a41186a290300370200200641106a20004198026a41106a290300370200200641086a2001290300370200200620023702002006412c6a2106200c2011470d000b201941016a21010b20002802a407210441002103200041003602a807200042043703a007200041a0076a41002001412c6c2205412c6d10980120002802a007210c20002802a80721012000200820056a3602a402200020083602a0022000200436029c0220002008360298022000200041f0066a3602a80220004180066a41086a20013602002000200041a0076a41086a360284062000200c2001412c6c6a3602800620004198026a20004180066a109d0220002802a407211120004198026a2023202120002802a007221920002802a807220810cc0120002802a0022110200028029c02210a024002400240200028029802220f450d000240200a450d00200a2101200f2103034020032802c80521032001417f6a22010d000b200f2101200a21040340200120012f01064102746a41c8056a28020021012004417f6a22040d000b20004198026a21040c020b20004198026a2104200f2103200f21010c010b2000410036029c0220004198026a21040c010b2000200136029c02200041a4026a20012f0106360200200041003602a00220004100360298020b20004180066a41086a200441086a290200220237030020002004290200220b37038006200041b0026a200237030042002112200042003703a0022000200336029c0220004100360298022000200b3703a802200020103602b8020240024020100d00427f211d4200210d4200211e4200211f427f210e0c010b20002010417f6a3602b80220004198026a410020031b220c2802002104200c28020821060240024002400240200c28020c2205200c28020422012f01064f0d00200121030c010b034020012802002203450d02200441016a210420012f0104210520032101200520032f01064f0d000b0b2005ad4220862006ad8421020c010b2006ad2102410021030b2002422088a7220641016a21052002a721070240024020040d00200321010c010b200320054102746a41c8056a2802002101410021052004417f6a2204450d00034020012802c80521012004417f6a22040d000b0b200c200536020c200c2007360208200c2001360204200c4100360200200320064105746a41e8026a2101427f211d427f210e4200211e4200211f420021124200210d0340200041086a200141086a290300220b4200200129030022024200108408200041186a2002420020024200108408427f200d427f200041186a41086a29030022302000290308222c202c7c7c222c200b2000290310222984202984420052202c2030547222011b7c2012427f200029031820011b7c22302012542201ad7c221220012012200d542012200d511b22011b210d427f203020011b2112200b200e2002201d54200b200e54200b200e511b22011b210e2002201d20011b211d200b201f7c2002201e7c221e200254ad7c211f20002802b8022201450d0120002001417f6a3602b80220004198026a4100200028029c021b220c2802002104200c2802082106024002400240200c28020c2205200c28020422012f01064f0d00200121030c010b0240034020012802002203450d01200441016a210420012f0104210520032101200520032f0106490d020c000b0b2006ad2102410021030c010b2005ad4220862006ad8421020b2002422088a7220641016a21052002a721070240024020040d00200321010c010b200320054102746a41c8056a2802002101410021052004417f6a2204450d00034020012802c80521012004417f6a22040d000b0b200c200536020c200c2007360208200c2001360204200c4100360200200320064105746a41e8026a21010c000b0b02400240200f0d0041002110200041ac026a41003602002000410036029c020c010b02400240200a0d00200f21010c010b200a2101200f2103034020032802c80521032001417f6a22010d000b200f21010340200120012f01064102746a41c8056a2802002101200a417f6a220a0d000b2003210f0b200041b4026a20012f0106360200200041b0026a4100360200200041ac026a2001360200200041003602a802200042003703a0022000200f36029c0220004100360298020b200020103602b80220004198026a109e0202402008450d002008412c6c21032019210103400240200141046a2802002204450d00200441306c450d00200128020010350b2001412c6a2101200341546a22030d000b0b02402011450d002011412c6c450d00201910350b20002015360288062000201736028406200020093602800620004198026a20004180066a200041f8016a200041e8016a10fb0120002d0098024101460d03202120216a22012021490d012001417f4c0d01200041d8036a2802002131200041d4036a2802002107200041d0036a2802002127200041cc036a2802002132200041c8036a280200211b200041c4036a280200212f200041c0036a2802002133200041bc036a280200210a200041b8036a280200212d200041b4036a2802002134200041b0036a280200210f200041ac036a2802002126200041a8036a2802002135200041a4036a2802002110200041a0036a28020021252000419c036a280200213620004198036a280200211120004194036a280200213720004190036a28020021382000418c036a280200210820004188036a280200213920004184036a280200213a20004180036a2802002109200041fc026a280200213b200041f8026a280200213c200041f4026a2802002119200041f0026a280200213d200041ec026a280200213e200041e8026a2802002113200041e4026a280200212e200041e0026a280200213f200041dc026a2802002117200041d8026a2802002140200041d4026a2802002141200041d0026a2802002118200041cc026a2802002142200041c8026a2802002143200041c4026a2802002115200041c0026a2802002144200041bc026a2802002145200041b8026a2802002114200041b4026a2802002124200041b0026a2802002146200041ac026a2802002116200041a8026a2802002147200041a4026a2802002148200041a0026a280200211c200028029c02212a0240024020010d00410221060c010b200110332206450d010b4100210c2000410036028806200020063602800620002001410176360284062021450d02202320214105746a212120002802f001221a41057441606a41057641016a2104202321050340200541086a2900002102200541106a290000210b2005290000213020004198026a41186a200541186a29000037030020004198026a41106a200b37030020004198026a41086a20023703002000203037039802201a450d05200541206a21054100210320002802e80121010240034020004198026a2001460d01200120004198026a412010a008450d01200141206a21012004200341016a2203470d000c070b0b200341ffff034b0d050240200c200028028406470d0020004180066a200c4101108e012000280280062106200028028806210c0b2006200c4101746a20033b01002000200c41016a220c3602880620052021470d000c030b0b1045000b1044000b0240202241ffffff3f71450d00202310350b200041de016a20004188066a28020036010020002000290380063701d6010240024020002802e00522050d004100210c200041ac026a41003602002000410036029c020c010b20002802e805210c0240024020002802e40522030d00200521010c010b2003210120052104034020042802c80521042001417f6a22010d000b200521010340200120012f01064102746a41c8056a28020021012003417f6a22030d000b200421050b200041b4026a20012f0106360200200041b0026a4100360200200041ac026a2001360200200041003602a802200042003703a0022000200536029c0220004100360298020b2000200c3602b80220004198026a109e02024020002802fc0141ffffff3f71450d0020002802f80110350b024020002802ec0141ffffff3f71450d0020002802e80110350b200041b8016a41106a200041d0016a41106a2f01003b0100200041b8016a41086a200041d0016a41086a290100370300200020002901d0013703b801200041f0066a41086a2204200041c6016a280100360200200020002901be013703f00620004198026a41186a2205420037030020004198026a41106a220c420037030020004198026a41086a22014200370300200042003703980241f7edcb00ad4280808080f000841001220329000021022001200341086a29000037030020002002370398022003103541e4edcb00ad4280808080a00184100122032900002102200041a0076a41086a2206200341086a290000370300200020023703a00720031035202020002903a007370000202041086a200629030037000020004180066a41086a2203200129030037030020004180066a41106a2201200c29030037030020004180066a41186a220c2005290300370300200020002903980237038006200020004180066a412010c0012000280204210520002802002106200041a3026a2004280200360000200020002903f00637009b0220002000290098023703a007200020004198026a41076a2900003700a707200041b8056a200d370300200041b0056a2012370300200041a8056a201f370300200041a0056a201e37030020004198056a200e37030020004190056a201d370300200041b8036a41183a0000200041c0036a20002900a70737000020004188056a2005410020061b36020020004184056a203136020020004180056a2007360200200041fc046a2027360200200041f8046a2032360200200041f4046a201b360200200041f0046a202f360200200041ec046a2033360200200041e8046a200a360200200041e4046a202d360200200041e0046a2034360200200041dc046a200f360200200041d8046a2026360200200041d4046a2035360200200041d0046a2010360200200041cc046a2025360200200041c8046a2036360200200041c4046a2011360200200041c0046a2037360200200041bc046a2038360200200041b8046a2008360200200041b4046a2039360200200041b0046a203a360200200041ac046a2009360200200041a8046a203b360200200041a4046a203c360200200041a0046a20193602002000419c046a203d36020020004198046a203e36020020004194046a201336020020004190046a202e3602002000418c046a203f36020020004188046a201736020020004184046a204036020020004180046a2041360200200041fc036a2018360200200041f8036a2042360200200041f4036a2043360200200041f0036a2015360200200041ec036a2044360200200041e8036a2045360200200041e4036a2014360200200041e0036a2024360200200041dc036a2046360200200041d8036a2016360200200041d4036a2047360200200041d0036a2048360200200041cc036a201c360200200041c8036a202a360200200041073602b0032000420237038003200020002903a0073700b903200041d8056a200c290300370300200041d0056a2001290300370300200041c8056a2003290300370300200041c0056a200029038006370300200020004198026a3602d00620004180066a200041d0066a10b90320002802800620002802840620002802880610a0041a200041b0036a10ba020c050b0240024020002802e00522050d004100210c200041ac026a41003602002000410036029c020c010b20002802e805210c0240024020002802e40522030d00200521010c010b2003210120052104034020042802c80521042001417f6a22010d000b200521010340200120012f01064102746a41c8056a28020021012003417f6a22030d000b200421050b200041b4026a20012f0106360200200041b0026a4100360200200041ac026a2001360200200041003602a802200042003703a0022000200536029c0220004100360298020b2000200c3602b80220004198026a109e02202241ffffff3f71450d01202310350c010b0240202241ffffff3f71450d00202310350b024020002802840641808080807872418080808078460d00200610350b0240201c41ffffffff0171450d00202a10350b02402016450d002016410c6c450d00204710350b0240201441ffffffff0071450d00202410350b02402015450d00201541146c450d00204410350b02402018450d00201841186c450d00204210350b02402017450d002017411c6c450d00204010350b0240201341ffffff3f71450d00202e10350b02402019450d00201941246c450d00203d10350b02402009450d00200941286c450d00203b10350b02402008450d002008412c6c450d00203910350b02402011450d00201141306c450d00203710350b02402010450d00201041346c450d00202510350b0240200f450d00200f41386c450d00202610350b0240200a450d00200a413c6c450d00202d10350b0240201b41ffffff1f71450d00202f10350b02402007450d00200741c4006c450d00202710350b0240024020002802e00522050d004100210c200041ac026a41003602002000410036029c020c010b20002802e805210c0240024020002802e40522030d00200521010c010b2003210120052104034020042802c80521042001417f6a22010d000b200521010340200120012f01064102746a41c8056a28020021012003417f6a22030d000b200421050b200041b4026a20012f0106360200200041b0026a4100360200200041ac026a2001360200200041003602a802200042003703a0022000200536029c0220004100360298020b2000200c3602b80220004198026a109e020b024020002802fc0141ffffff3f71450d0020002802f80110350b20002802ec0141ffffff3f71450d0220002802e80110350c020b200d42ffffff3f83500d00200610350b02402005450d00200541306c450d00200810350b02402017450d002017412c6c21032013210103400240200141046a2802002204450d00200441226c450d00200128020010350b2001412c6a2101200341546a22030d000b0b2015450d002015412c6c450d00201310350b200041c0076a24000ba50a07027f017e047f017e017f047e027f230041e0006b220224002002411436020c2002419793ca00360208200241106a419793ca00ad4280808080c00284100510c201024002400240024002400240200228021022030d0042002104410821050c010b200228021421062002200241186a2802002207360224200220033602200240024002402007450d0020022007417f6a3602242002200341016a36022020032d00002107200241c8006a200241206a10e80320022802482208450d00200229024c2109200741ff01714101460d012009a72207450d00200741286c450d00200810350b20024100360230200242013703282002410936023c2002200241086a3602382002200241286a36024441012107200241dc006a41013602002002420137024c200241c888c2003602482002200241386a360258200241c4006a41e88ac500200241c8006a10431a200235023042208620023502288410060240200228022c450d00200228022810350b4102210a0c010b4101210a410021070b02402006450d00200310350b4108200820071b21054200200920071b210420070d00200a4101460d0020052802082203ad42287e2209422088a70d012009a72207417f4c0d01200528020021060240024020070d00410821050c010b200710332205450d030b02400240024002400240200741286e220820034f0d002008410174220a2003200a20034b1bad42287e2209422088a70d082009a7220a4100480d08200741274d0d01200841286c2207200a460d022007450d0120052007200a10372205450d090c020b2008ad210b20030d02420021090c030b200a10332205450d070b200a41286ead210b0b200341286c210a42002109410021080340200620086a22032903002104200341086a290300210c200341106a290300210d200341186a290300210e200520086a220741206a200341206a290300370300200741186a200e370300200741106a200d370300200741086a200c3703002007200437030020094280808080107c2109200a200841286a2208470d000b0b200b20098421040b2004422088a7220341286c4104722207417f4c0d00200710332208450d01200241003602502002200736024c200220083602482003200241c8006a10772002280250210702402003450d002005200341286c6a210f200228024c210620052103034002400240200620076b4120490d00200741206a2108200228024821102006210a0c010b200741206a22082007490d052006410174220a2008200a20084b1b220a4100480d050240024020060d000240200a0d00410121100c020b200a10332210450d080c010b200228024821102006200a460d0020102006200a10372210450d070b2002200a36024c200220103602480b201020076a22072003290000370000200741186a200341186a290000370000200741106a200341106a290000370000200741086a200341086a29000037000020022008360250200341206a290300210902400240200a20086b4108490d00200841086a2107200a21060c010b200841086a22072008490d05200a41017422062007200620074b1b22064100480d0502400240200a0d00024020060d00410121100c020b200610332210450d080c010b200a2006460d002010200a200610372210450d070b2002200636024c200220103602480b201020086a200937000020022007360250200f200341286a2203470d000b0b2007ad422086200235024884210902402004a72203450d00200341286c450d00200510350b200241e0006a240020090f0b1044000b1045000b103e000b103c000bbb0504037f017e087f037e23004180016b220224002002200110c40102400240024002402002280200450d00200041003602000c010b20022802042203200128020441286e2204200420034b1bad42287e2205422088a70d012005a72204417f4c0d010240024020040d00410821060c010b200410332206450d030b4100210720024100360210200220063602082002200441286e36020c0240024002402003450d0041002108034041002104200241003a0078200841016a210820012802042109417f210a034020092004460d03200241d8006a20046a2001280200220b2d00003a000020012009200a6a3602042001200b41016a3602002002200441016a220c3a0078200a417f6a210a200c2104200c4120470d000b200241386a41186a2204200241d8006a41186a290300370300200241386a41106a220a200241d8006a41106a290300370300200241386a41086a220d200241d8006a41086a290300370300200220022903583703382009200c6b220c4108490d03200b29000121052001200b41096a3602002001200c41786a360204200241186a41086a220c200d290300370300200241186a41106a2209200a290300370300200241186a41186a220a20042903003703002002200229033837031802402007200228020c470d00200241086a20074101108f0120022802082106200228021021070b2006200741286c6a22042002290318370300200c290300210e2009290300210f200a290300211020042005370320200441186a2010370300200441106a200f370300200441086a200e3703002002200741016a220736021020082003470d000b0b20002002290308370200200041086a200241086a41086a2802003602000c020b200441ff0171450d00200241003a00780b20004100360200200228020c2204450d00200441286c450d00200610350b20024180016a24000f0b1044000b1045000b8c0f05047f017e017f017e077f23004190016b22022400200241c8006a41186a22034200370300200241c8006a41106a22044200370300200241c8006a41086a220542003703002002420037034841a9d1cb00ad4280808080c0008422061001220729000021082005200741086a290000370300200220083703482007103541b7d1cb00ad4280808080b00184100122092900002108200241286a41086a2207200941086a2900003703002002200837032820091035200420022903282208370300200241f0006a41086a220a2005290300370300200241f0006a41106a220b2008370300200241f0006a41186a220c200729030037030020022002290348370370200241c8006a200241f0006a10dd0220022802482109200229024c21082003420037030020044200370300200542003703002002420037034820061001220329000021062005200341086a290000370300200220063703482003103541d8d1cb00ad4280808080a001841001220329000021062007200341086a2900003703002002200637032820031035200420022903282206370300200a2005290300370300200b2006370300200c200729030037030020022002290348370370200241c8006a200241f0006a10b10220022d00482105200c200241e1006a290000370300200b200241d9006a290000370300200a200241d1006a290000370300200220022900493703700240024020054101460d00200241286a41186a4200370300200241286a41106a420037030020074200370300200242003703280c010b200241286a41186a200c290300370300200241286a41106a200b2903003703002007200a290300370300200220022903703703280b200241086a41086a200241286a41086a290300370300200241086a41106a200241286a41106a290300370300200241086a41186a200241286a41186a2903003703002002200229032837030820024100360250200242013703480240410810332205450d002002410836024c20022005360248200542b8173700002002410836025020054108411010372205450d00200542c8013700082002411036024c20022005360248200241103602500240024002404100450d00411021070c010b411041017422074118200741184b1b22074100480d010240024041100d002007103322050d010c040b41102007460d0020054110200710372205450d030b2002200736024c200220053602480b2005420137001020024118360250024020074138714118470d00200741017422044120200441204b1b22044100480d010240024020070d00200410332205450d040c010b20072004460d0020052007200410372205450d030b2002200436024c200220053602480b2009410820091b210d20054204370018200241203602502008420020091b2208422088a72205200241c8006a10772002280250210302402005450d00200d200541286c6a210e410020036b210b200228024c2104410021050340200320056a210c024002402004200b6a4120490d002002280248210a200421090c010b200c41206a2207200c490d03200441017422092007200920074b1b22094100480d030240024020040d00024020090d004101210a0c020b20091033220a450d060c010b2002280248210a20042009460d00200a200420091037220a450d050b2002200936024c2002200a3602480b200a20036a20056a2204200d20056a2207290000370000200441186a200741186a290000370000200441106a200741106a290000370000200441086a200741086a2900003700002002200c41206a2204360250200741206a2903002106024002402009200b6a41606a41074d0d00200921040c010b200441086a220f2004490d0320094101742204200f2004200f4b1b22044100480d030240024020090d00024020040d004101210a0c020b20041033220a450d060c010b20092004460d00200a200920041037220a450d050b2002200436024c2002200a3602480b200a20036a20056a41206a20063700002002200c41286a360250200b41586a210b200541286a2105200e200741286a470d000b200320056a21030b02400240200228024c220420036b4120490d0020022802482107200421050c010b200341206a22052003490d01200441017422072005200720054b1b22054100480d010240024020040d00024020050d00410121070c020b200510332207450d040c010b2002280248210720042005460d0020072004200510372207450d030b2002200536024c200220073602480b200720036a22042002290308370000200441186a200241086a41186a290300370000200441106a200241086a41106a290300370000200441086a200241086a41086a2903003700002002200341206a22043602500240024020052004460d00200421050c010b200541016a22042005490d01200541017422092004200920044b1b22044100480d010240024020050d0041002105024020040d00410121070c020b200410332207450d040c010b20052004460d0020072005200410372207450d030b2002200436024c200220073602480b200720056a41013a0000200541016aad422086200235024884210602402008a72205450d00200541286c450d00200d10350b20024190016a240020060f0b103e000b103c000b8e0406047f017e017f017e047f027e230041f0006b22022400200241c0006a41186a22034200370300200241c0006a41106a22044200370300200241c0006a41086a220542003703002002420037034041a9d1cb00ad4280808080c0008422061001220729000021082005200741086a290000370300200220083703402007103541add1cb00ad4280808080a00184100122092900002108200241e0006a41086a2207200941086a2900003703002002200837036020091035200420022903602208370300200241206a41086a220a2005290300370300200241206a41106a220b2008370300200241206a41186a220c200729030037030020022002290340370320200241106a200241206a10e102200229031821082002290310210d2003420037030020044200370300200542003703002002420037034020061001220929000021062005200941086a290000370300200220063703402009103541c2d1cb00ad4280808080b001841001220929000021062007200941086a2900003703002002200637036020091035200420022903602206370300200a2005290300370300200b2006370300200c2007290300370300200220022903403703202002200241206a10e102200229030821062002290300210e02404108103322050d001045000b200520064200200ea71b200842c8017e4200200da71b7c370000200241f0006a24002005ad42808080808001840baf0b04047f017e0a7f017e230041b0016b2202240020024188016a41186a420037030020024188016a41106a2203420037030020024188016a41086a22044200370300200242003703880141fdd0cb00ad4280808080a00284100122052900002106200241e8006a41086a2207200541086a2900003703002002200637036820051035200420072903003703002002200229036837038801418fd1cb00ad4280808080c000841001220529000021062007200541086a2900003703002002200637036820051035200320022903682206370300200241106a41086a2004290300370300200241106a41106a2006370300200241106a41186a20072903003703002002200229038801370310200241203602342002200241106a360230200241386a200241106aad4280808080800484100510c2010240024002400240200228023822080d00410021030c010b200228023c21092002200241386a41086a28020036024c20022008360248200241086a200241c8006a10c4010240024020022802080d00200228020c220a200228024c220b41057622072007200a4b1b22074105742204417f4c0d040240024020070d00410121030c010b200410332203450d040b4100210c200241003602602002200736025c2002200336025802400240200a450d004100210d0340200b210541002107200241003a00a801200d41016a210d034020052007460d0320024188016a20076a200228024822042d00003a00002002200441016a3602482002200741016a22043a00a8012004210720044120470d000b200241e8006a41186a220e20024188016a41186a290300370300200241e8006a41106a220f20024188016a41106a290300370300200241e8006a41086a221020024188016a41086a29030037030020022002290388013703680240200c200228025c470d00200241d8006a200c4101108a01200228025821032002280260210c0b200520046b210b2003200c4105746a22072002290368370000200741186a200e290300370000200741106a200f290300370000200741086a20102903003700002002200c41016a220c360260200d200a470d000b2002200520046b36024c0b200229025c21062003450d010c020b2002410036024c0240200741ff0171450d00200241003a00a8010b0240200228025c41ffffff3f71450d00200310350b0b4100210320024100360270200242013703682002410936025c2002200241306a3602582002200241e8006a3602542002419c016a41013602002002420137028c01200241c888c200360288012002200241d8006a36029801200241d4006a41e88ac50020024188016a10431a20023502704220862002350268841006200228026c450d00200228026810350b2009450d00200810350b2006420020031b2206422088a7220741057422094104722204417f4c0d01200410332205450d002003410120031b210a20024100360290012002200436028c012002200536028801200720024188016a10770240024020070d002002280290012104200228028801210d0c010b410020022802900122046b2103200228028801210d200228028c012108200a210c0340200c21070240200820036a411f4b0d00024002400240200441206a22052004490d002008410174220c2005200c20054b1b22054100480d000240024020080d00024020050d004101210d0c020b20051033210d0c040b20082005470d020b200521080c030b103e000b200d200820051037210d0b20052108200d0d00103c000b200741206a210c200d20046a22052007290000370000200541186a200741186a290000370000200541106a200741106a290000370000200541086a200741086a290000370000200341606a2103200441206a2104200941606a22090d000b2002200836028c0120022004360290012002200d360288010b2004ad422086200dad8421110240200642ffffff3f83500d00200a10350b200241b0016a240020110f0b1045000b1044000bb70302037f047e23004180016b2202240041002103200241003a0040200041b0b4cc0020011b210402400240034020012003460d01200241206a20036a200420036a2d00003a00002002200341016a22003a00402000210320004120470d000b200241186a200241206a41186a22032903002205370300200241106a200241206a41106a22002903002206370300200241086a200241206a41086a2201290300220737030020022002290320220837030020032005370300200020063703002001200737030020022008370320200241f0006a200241206a10ed03200241206a200228027022032002280278108f0220022903202105200241e8006a280200210002402002280274450d00200310350b4104103322030d011045000b0240200341ff0171450d00200241003a00400b200241346a41023602002002410c6a410436020020024202370224200241f0b2c30036022020024104360204200241d0b4c30036020020024100360274200241b0b4cc00360270200220023602302002200241f0006a360208200241206a4180b3c300104c000b20032000410020054201511b36000020024180016a24002003ad4280808080c000840bc20503027f017e047f230041d0006b2202240041d1c4c700ad4280808080e00084100122032900002104200241086a200341086a290000370300200220043703002003103541d7c4c700ad4280808080f00084100122032900002104200241106a41086a200341086a29000037030020022004370310200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100422012900002104200241306a41086a200141086a2900003703002002200437033020011035200241cc006a200341206a360200200220033602482002200241306a41106a3602442002200241306a360240200241206a200241c0006a107b200310352002280228220541206a2201417f4c0d01200228022021060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290300370000200341086a200241086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290310370010200341186a200241106a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a20002001360208200020083602042000200336020002402002280224450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000bec2d05057f047e067f017e1e7f230041900f6b22022400024020010d0041b0b4cc0021000b200220003602282002200136022c41002103200241003a00f80b2001417f6a210402400240024002400240024002400240024002400240034020012003460d01200241d80b6a20036a200020036a22052d00003a00002002200541016a3602282002200341016a22053a00f80b2002200436022c2004417f6a21042005210320054120470d000b200241306a41086a200241d80b6a41086a290300370300200241306a41106a200241d80b6a41106a290300370300200241306a41186a200241d80b6a41186a290300370300200220022903d80b37033041002103200241003a00f80b200120056b2106200020056a2100417f2101034020062003460d02200241d80b6a20036a200020036a22052d00003a00002002200420036b36022c2002200541016a3602282002200341016a22053a00f80b2001417f6a21012005210320054120470d000b200241d0006a41086a200241d80b6a41086a290300370300200241d0006a41106a200241d80b6a41106a290300370300200241d0006a41186a200241d80b6a41186a290300370300200220022903d80b370350200420056b220441016a4110490d042002200020056a220341106a3602282002200441716a220536022c20054108490d0720032900002107200341086a29000021082002200441696a36022c2002200341186a360228200341106a2900002109200241206a200241286a10c40120022802200d08200228022c220420022802242203490d082003417f4c0d0520030d0241002104410121060c030b0240200341ff0171450d00200241003a00f80b0b200241ec0b6a41023602002002418c096a4104360200200242023702dc0b200241f0b2c3003602d80b2002410436028409200241e8b4c30036028009200241003602cc06200241b0b4cc003602c806200220024180096a3602e80b2002200241c8066a36028809200241d80b6a4180b3c300104c000b0240200341ff0171450d00200241003a00f80b0b200241ec0b6a41023602002002418c096a4104360200200242023702dc0b200241f0b2c3003602d80b2002410436028409200241e8b4c30036028009200241003602cc06200241b0b4cc003602c806200220024180096a3602e80b2002200241c8066a36028809200241d80b6a4180b3c300104c000b200310392206450d032006200228022822052003109d081a2002200420036b36022c2002200520036a360228200321040b2006450d042003ad4220862004ad84210a200241f0006a41186a200241306a41186a290300370300200241f0006a41106a200241306a41106a290300370300200241f0006a41086a200241306a41086a2903003703002002200229033037037020024190016a41186a200241d0006a41186a29030037030020024190016a41106a200241d0006a41106a29030037030020024190016a41086a200241d0006a41086a2903003703002002200229035037039001200220093703b801200220093703b001200241d80b6a41186a4200370300200241d80b6a41106a22044200370300200241d80b6a41086a22034200370300200242003703d80b41f1d8cb00ad42808080809001841001220529000021092003200541086a290000370300200220093703d80b2005103541e2d8cb00ad4280808080f00184100122052900002109200241c8066a41086a2201200541086a290000370300200220093703c80620051035200420022903c806220937030020024180096a41086a200329030037030020024180096a41106a200937030020024180096a41186a2001290300370300200220022903d80b37038009200241d80b6a20024180096a10da0220022d00e00c210320024180096a200241d80b6a418801109d081a2002200241d80b6a418c016a2800003600cb06200220022800e10c3602c8060240024020034102470d002002428080818080043703c0022002428080848080023703b80220024280c2d72f3703a80220024280e1eb173703a002200242a0c21e37039802200242a0c21e37039002200242e0ef972037038802200242e0c9dc2937038002200242e0ef97203703f801200242a0c21e3703f001200242a0c21e3703e801200242a0c21e3703e001200242a0c21e3703d801200242a0c21e3703d001200242a0c21e3703c801200242a0c21e3703c00120024280808080c0003703b002410021030c010b200241c0016a20024180096a418801109d081a200241c0016a418c016a20022800cb06360000200220022802c8063600c9020b200241e8026a4200370300200241d8026a4200370300200220033a00c8022002428080e983b1de163703e0022002428080e983b1de163703d002200242a08080808080103703f0022002200241c0016a3602f8022002200241c0016a3602fc02200241d80b6a41186a22054200370300200241d80b6a41106a22014200370300200241d80b6a41086a22034200370300200242003703d80b41d1efcb00ad42808080809001841001220029000021092003200041086a290000370300200220093703d80b2000103541ebc3c400ad428080808030841001220b2900002109200241c8066a41086a2200200b41086a290000370300200220093703c806200b1035200420022903c806370000200441086a220c200029030037000020024180096a41086a220d200329030037030020024180096a41106a220e200129030037030020024180096a41186a220f2005290300370300200220022903d80b37038009200241106a20024180096a10e1022002290318210920022802102110200542003703002001420037030020034200370300200242003703d80b41d1c4c700ad4280808080e000841001220b29000021112003200b41086a290000370300200220113703d80b200b103541e7c4c700ad4280808080e000841001220b29000021112000200b41086a290000370300200220113703c806200b1035200420022903c806370000200c2000290300370000200d2003290300370300200e2001290300370300200f2005290300370300200220022903d80b37038009200241086a20024180096a412010c001200241b8036a4200370300200241ac036a419494ca00360200200241a8036a41b0b4cc00360200200241a4036a4100360200200241d8036a200241f0006a41086a290300370300200241e0036a200241f0006a41106a290300370300200241e8036a200241f0006a41186a2903003703002002428080808080013703b00320024200370398032002420037038803200220022903703703d00320022802082104200228020c21002002200241fc026a3602c8032002200241f8026a3602c4032002200241c0016a3602c00320022000410020041b3602cc0320022009420020101b37038003200520024190016a41186a290300370300200120024190016a41106a290300370300200320024190016a41086a29030037030020022002290390013703d80b2002200a370284092002200636028009200241f0036a20024180036a200241d80b6a20072008200241b0016a20024180096a10ef0341012112024020022802f00322130d00200241f0036a41106a2d00000d00200241d80b6a41086a200241a0036a29030037030020024180096a41086a200241e40b6a28020036020020022002290398033703d80b200220022902dc0b37038009200241880f6a20024180096a10f003410021120b20022802b403221420022802bc03220341d8026c6a210120022802b80321152014210402402003450d00200241a10c6a2110200241cd086a210e20024187096a2116200241d80b6a41186a210b200241e10b6a2117200241880e6a41116a2118200241880e6a41027221192002419c086a41186a211a200241810c6a211b200241f0086a211c200241970e6a211d2002419c086a41116a210f200241d80b6a410172211e20024180096a41e0006a211f200241d0096a2120201421030240034020032d00002104200241c4066a41026a220d200341036a2d00003a00002002200341016a2f00003b01c406200341046a2802002105200341086a28020021002003410c6a2802002106200241e0056a200341106a41e000109d081a200341f8006a2903002109200341f0006a290300210720034180016a290300210820024190046a20034188016a41d001109d081a20044103460d01200241fc086a41026a220c200d2d00003a0000200220022f01c4063b01fc082002419c086a200241e0056a41e000109d081a200241c8066a20024190046a41d001109d081a024002400240024020040e03010200010b200241c40e6a41026a2204200c2d00003a0000200241b00e6a41086a220d2002419c086a41086a2221290000370300200241b00e6a41106a22222002419c086a41106a22232d00003a0000200220022f01fc083b01c40e2002200229009c083703b00e200241c80e6a41186a2224200f41186a2225290000370300200241c80e6a41106a2226200f41106a2227290000370300200241c80e6a41086a2228200f41086a22292900003703002002200f2900003703c80e200241b00b6a41186a222a200e41186a222b290000370300200241b00b6a41106a222c200e41106a222d290000370300200241b00b6a41086a222e200e41086a222f2900003703002002200e2900003703b00b200220063600930e2002200036008f0e2002200536008b0e2002200c2d00003a008a0e200220022f01fc083b01880e201d200229009c08370000201d41086a2021290000370000201d41106a20232d00003a000020024180096a41186a202529000037030020024180096a41106a202729000037030020024180096a41086a20292900003703002002200f29000037038009200b202b290000370300200241d80b6a41106a202d290000370300200241d80b6a41086a202f2900003703002002200e2900003703d80b200241f80e6a41086a201c41086a2800003602002002201c2900003703f80e200241e80e6a200241880e6a20024180096a200241d80b6a20072009200241f80e6a10f10320022d00e80e210c201720022f01c40e3b0000201741026a20042d00003a0000200b20022903b00e370000200b41086a200d290300370000200b41106a20222d00003a0000200241033a00e00b2002410d3a00d80b200220063602ec0b200220003602e80b200220053602e40b201b20022903c80e370000201b41086a2028290300370000201b41106a2026290300370000201b41186a2024290300370000201041186a202a290300370000201041106a202c290300370000201041086a202e290300370000201020022903b00b370000200241d80b6a41f8006a2009370300200220073703c80c2002200c4104463a00c10c41b0b4cc004100200241d80b6a10d4010c020b20162002419c086a41e000109d081a2002410d3a00d80b201e20024180096a41e700109d081a200241d80b6a41f0006a2009370300200220073703c00c200220083703d00c20052006200241d80b6a10d401200041ffffff3f71450d01200510350c010b200241f80e6a41026a2204200c2d00003a0000200241c80e6a41086a220d2002419c086a41086a2221290000370300200241c80e6a41106a22222002419c086a41106a22232d00003a0000200220022f01fc083b01f80e2002200229009c083703c80e20024180096a201a41c800109d081a20202009370300200220073703c809200220083703d809201f200241c8066a41d001109d081a200241b00e6a20024180096a10d803200241d80b6a20024180096a41b002109d081a201920022f01fc083b0000201941026a200c2d00003a00002018200229009c08370000201841086a2021290000370000201841106a20232d00003a000020024180023b01880e200220063600950e200220003600910e2002200536008d0e200241b00b6a200241d80b6a200241880e6a10ac0342002109024020022903b80b4201520d00420020022903b00e220920022903c00b7d220720072009561b21090b2002427f20022903b801220720097c220920092007541b220920022903b001220720092007561b3703b80120022903b00b2109201720022f01f80e3b0000201741026a20042d00003a0000200b20022903c80e370000200b41086a200d290300370000200b41106a20222d00003a0000200241063a00e00b2002410d3a00d80b200220063602ec0b200220003602e80b200220053602e40b20022009503a00810c41b0b4cc004100200241d80b6a10d4010b200341d8026a22032001470d000b200121040c010b200341d8026a21040b024020012004460d0003402004220341d8026a21040240024020032d0000220541014b0d000240024020050e020001000b0240200341086a28020041ffffff3f71450d00200341046a28020010350b200341106a2d00004107470d02200341386a280200450d02200341346a28020010350c020b200341286a10bb020c010b200341e8006a28020041ffffff3f71450d00200341e4006a28020010350b20012004470d000b0b02402015450d00201541d8026c450d00201410350b20024184046a280200210d200241f0036a41106a2802002106200241fc036a2802002100200241f8036a280200210b20022802f40321010240200228028c032203450d0020024180036a41106a280200450d00200310350b02402012450d0002400240200228029c03220c0d004100210e200241ec0b6a4100360200200241003602dc0b0c010b20022802a403210e02400240200241a0036a28020022040d00200c21030c010b20042103200c2105034020052802880b21052003417f6a22030d000b200c21030340200320032f01064102746a41880b6a28020021032004417f6a22040d000b2005210c0b200241f40b6a20032f0106360200200241f00b6a4100360200200241ec0b6a2003360200200241003602e80b200242003703e00b2002200c3602dc0b200241003602d80b0b2002200e3602f80b200241d80b6a108f030b02402013450d00410021010240200d450d00200610350b0b200241003602e00b200242013703d80b410110332103024002402001450d002003450d08200341003a0000200220033602d80b20024281808080103702dc0b20034101410210372203450d08200320063a0001200220033602d80b20024282808080203702dc0b2000200241d80b6a10770240024020022802dc0b220520022802e00b22046b2000490d0020022802d80b21030c010b200420006a22032004490d08200541017422062003200620034b1b22064100480d080240024020050d00024020060d00410121030c020b2006103322030d010c0b0b20022802d80b210320052006460d0020032005200610372203450d0a0b200220063602dc0b200220033602d80b0b200320046a20012000109d081a200420006aad42208621090c010b2003450d07200341013a0000200241013602dc0b200220033602d80b42808080801021090b20092003ad84210902402001450d00200b450d00200110350b200241900f6a240020090f0b2002418c096a4104360200200241ec0b6a4102360200200242023702dc0b200241f0b2c3003602d80b2002410436028409200241e8b4c30036028009200241003602cc06200241b0b4cc003602c806200220024180096a3602e80b2002200241c8066a36028809200241d80b6a4180b3c300104c000b1044000b1045000b2002418c096a4104360200200241ec0b6a4102360200200242023702dc0b200241f0b2c3003602d80b2002410436028409200241e8b4c30036028009200241003602cc06200241b0b4cc003602c806200220024180096a3602e80b2002200241c8066a36028809200241d80b6a4180b3c300104c000b2002418c096a4104360200200241ec0b6a4102360200200242023702dc0b200241f0b2c3003602d80b2002410436028409200241e8b4c30036028009200241003602cc06200241b0b4cc003602c806200220024180096a3602e80b2002200241c8066a36028809200241d80b6a4180b3c300104c000b103e000b103c000bbf2303027f027e077f23004190056b2207240020072004370310200720033703082007200536021c02400240024002400240024002400240024002400240024002402001280230200128024022082802b001460d002005420020052903082209200841386a2903007d220a200a20095622081b37030820080d03200741f8026a200210f303200741a0016a20072802f802220820072802800310d90220072d00a0012105200741b8046a200741a0016a41017241d700109d081a024020054102460d00200741e0036a200741b8046a41d700109d081a0b024020072802fc02450d00200810350b2005417f6a41ff01714102490d01200741b8046a200741e7036a220b41d000109d081a200741a0016a41186a4200370300200741a0016a41106a220c4200370300200741a0016a41086a22054200370300200742003703a00141d1c4c700ad4280808080e000841001220829000021092005200841086a290000370300200720093703a0012008103541e7c4c700ad4280808080e00084100122082900002109200741b0026a41086a220d200841086a290000370300200720093703b00220081035200c20072903b0022209370300200741f8026a41086a22082005290300370300200741f8026a41106a22052009370300200741f8026a41186a220c200d290300370300200720072903a0013703f8022007200741f8026a412010c001200741b0026a20022007280204410020072802001b220e4100200741b8046a10f603200741a0016a200b41d000109d081a200c200741b0026a41186a2903003703002005200741b0026a41106a2903003703002008200d290300370300200720072903b0023703f802200741206a2002200741a0016a200e200741f8026a10f70320072d002021050c020b200041003a0004200041013602002000410c6a4129360200200041086a41c4baca00360200200041106a2006290200370200200041186a200641086a2802003602000c0b0b200720053a0020200741206a410172200741e0036a41d700109d081a0b200541037122084103460d0220080e03010201010b200041003a0004200041013602002000410c6a4123360200200041086a41edbaca00360200200041106a2006290200370200200041186a200641086a2802003602000c080b200741f8006a41186a200141e8006a29000037030020074188016a200141e0006a290000370300200741f8006a41086a200141d8006a2900003703002007200129005037037841002108024002400240200541ff0171220541024d0d000c010b024020050e03000102000b200741c0006a2802002205417f4c0d032007413c6a280200210e200741206a41186a280200210c0240024020050d004100210d410121080c010b200510332208450d052005210d0b02400240200d2005490d00200d210b0c010b200d410174220b2005200b20054b1b220b4100480d060240200d0d00200b103322080d010c0a0b200d200b460d002008200d200b10372208450d090b2008200c2005109d081a2005ad422086200bad842109200e450d00200c10350b200741086a41086a2903002104200729030821030b200741dc016a4100360200200741cc016a41d8b9ca00360200200741c4016a4100360200200741a0016a41106a2009370300200741f8016a200241086a29000037030020074180026a200241106a29000037030020074188026a200241186a290000370300200720013602a801200741a0016a41286a200141186a220f360200200742083702d401200742003703b801200720083602ac01200720022900003703f001200720012802483602e801200720012903403703e0012007200128023041016a3602d001200129030021092007200128024c3602ec01200720093703a00120074180046a200741f8006a41086a290300370300200741e0036a41286a200741f8006a41106a29030037030020074190046a200741f8006a41186a290300370300200741f4036a200641086a280200360200200720023602e803200720072903783703f803200720062902003702ec0320072007411c6a3602e4032007200741086a3602e003200741e0036a41186a211002400240200320048450450d00410021060c010b200741b8046a200728021c41002010200220032004200741a0016a10bf05024020072d00b8044104460d00200720072900ed033703a0022007200741f4036a2800003600a70220072d00ec03210520072902bc04210320072802b80421060c070b20072802b801210620072802e80321020b200641016a220e41004c0d042007200e3602b801024002400240200741bc016a280200220b450d00200741a0016a41206a280200210c0340200b41086a2105200b2f010622114105742106410021080240024003402006450d0120022005412010a008220d450d02200641606a2106200841016a2108200541206a2105200d417f4a0d000b2008417f6a21110b200c450d02200c417f6a210c200b20114102746a41880b6a280200210b0c010b0b200b200841e0006c6a220541e8026a210602400240200541c5036a2d00000d00200741b8046a41086a2208200641c5006a290000370300200741b8046a41106a220d200641cd006a290000370300200741b8046a41186a220b200641d5006a29000037030020072006413d6a2900003703b8044102210520062d003c4101470d01200741f8026a41186a200b290300370300200741f8026a41106a200d290300370300200741f8026a41086a2008290300370300200720072903b8043703f802410121050c010b20074180036a200641c5006a29000037030020074188036a200641cd006a29000037030020074190036a200641d5006a29000037030020072006413d6a2900003703f80220062d003c21050b200541ff01714102470d010b200741b0026a20072802c801200220072802cc0128021011040020072802b801210e20072d00b00221050c010b200741b9026a20074180036a290300370000200741c1026a20074188036a290300370000200741c9026a20074190036a290300370000200720053a00b002200720072903f8023700b1020b2007200e417f6a3602b8014101210602400240200541ff01714101470d00200741d8026a41186a200741c9026a290000370300200741d8026a41106a200741c1026a290000370300200741d8026a41086a200741b9026a290000370300200720072900b1023703d802200741b8046a200741d8026a20072802e80128020010a306024020072802b8044101470d00200720072900ed033703a0022007200741f4036a2800003600a70220072902bc04210320072d00ec032105410021060c080b200741b0036a41186a2205200741b8046a410472220641186a2802002202360200200741f8026a41106a200641086a290200370300200741f8026a41186a200641106a29020037030020074198036a2002360200200741043602fc02200741fbd5cb003602f802200720062902003703800320072802e40121062005201041186a2900002203370300200741b0036a41106a2202201041106a2900002204370300200741b0036a41086a2208201041086a2900002209370300200741e0046a2009370300200741e8046a2004370300200741f0046a20033703002007201029000022033703b003200720033703d80420072802e003220d41086a29030021032007200741a0016a3602d004200d290300210420072903a001210920072802ec01210d200720033703c004200720043703b8042007200d3602d404200720093703c804200741d0036a41086a200741ec036a220d41086a2802003602002007200d2902003703d003200741b0036a2006200741f8026a200741b8046a200741d0036a20072802e403280200109a05200720072900c1033703a003200720052800003600a7032008290300210320022d0000210520072802b4032106024020072802b0034101470d00200720072800a7033600a702200720072903a0033703a00220074190036a280200450d082007418c036a28020010350c080b200720072d00a2033a00a202200720072f01a0033b01a00220074190036a280200450d012007418c036a28020010350c010b4200210341002105200741f0036a280200450d0020072802ec0310350b200720072903a0022204370390022007419c016a41026a221120072d0092023a0000200720043d019c01200741c0016a280200210220072802dc01210d20072802d801210c20072802d401210820072802c401210e20072802bc01210b024020072802ac012210450d00200741b0016a280200450d00201010350b200741b8046a41026a20112d00003a0000200720072f019c013b01b80402400240200541ff01710d002007200e3602a801200720023602a4012007200b3602a001200f200741a0016a109504200141346a2001413c6a2205280200200d41d8026c220241d8026d220d1095012001280234200528020041d8026c6a20082002109d081a20052005280200200d6a3602000240200c450d00200c41d8026c450d00200810350b20002006360204200020072f01b8043b0011200041106a41003a0000200041086a2003370200200041136a200741ba046a2d00003a00000c010b20002006360204200020072f01b8043b0011200041106a20053a0000200041086a2003370200200041136a200741ba046a2d00003a00000240200d450d00200d41d8026c210d41002106034002400240200820066a22052d0000220141014b0d000240024020010e020001000b0240200541086a28020041ffffff3f71450d00200541046a28020010350b200541106a2d00004107470d02200541386a280200450d02200541346a28020010350c020b200541286a10bb020c010b200541e8006a28020041ffffff3f71450d00200541e4006a28020010350b200d200641d8026a2206470d000b0b0240200c450d00200c41d8026c450d00200810350b02400240200b0d004100210e200741b4016a4100360200200741003602a4010c010b0240024020020d00200b21060c010b20022106200b2105034020052802880b21052006417f6a22060d000b200b21060340200620062f01064102746a41880b6a28020021062002417f6a22020d000b2005210b0b200741bc016a20062f0106360200200741b8016a4100360200200741b4016a2006360200200741003602b001200742003703a8012007200b3602a401200741003602a0010b2007200e3602c001200741a0016a108f030b200041003602000c070b200041003a0004200041013602002000410c6a4119360200200041086a4190bbca00360200200041106a2006290200370200200041186a200641086a280200360200200541ff01710d062007413c6a280200450d06200741386a28020010350c060b1044000b1045000b103e000b41ac96cc004118200741b8046a41d8c1c30041d496cc001046000b200720072903a00237039002200720072800a70236009702200041106a20053a0000200041086a2003370200200020063602042000200729039002370011200041186a20072800970236000020004101360200024020072802ac012200450d00200741a0016a41106a280200450d00200010350b0240024020072802bc0122010d0041002102200741cc046a4100360200200741003602bc040c010b20072802c401210202400240200741c0016a28020022060d00200121000c010b2006210020012105034020052802880b21052000417f6a22000d000b200121000340200020002f01064102746a41880b6a28020021002006417f6a22060d000b200521010b200741d4046a20002f0106360200200741d0046a4100360200200741cc046a2000360200200741003602c804200742003703c004200720013602bc04200741003602b8040b200720023602d804200741b8046a108f03024020072802dc012200450d0020072802d4012101200041d8026c210241002100034002400240200120006a22062d0000220541014b0d000240024020050e020001000b0240200641086a28020041ffffff3f71450d00200641046a28020010350b200641106a2d00004107470d02200641386a280200450d02200641346a28020010350c020b200641286a10bb020c010b200641e8006a28020041ffffff3f71450d00200641e4006a28020010350b2002200041d8026a2200470d000b0b20072802d8012200450d01200041d8026c450d0120072802d40110350c010b103c000b20074190056a24000ba6480d077f017e047f067e047f047e0d7f067e107f027e057f027e0a7f230041b0056b2202240020024190016a42003703002002420037038801200242003703800102400240200128020022030d004100210141002103410021040c010b2001280208210402400240200128020422050d00200321010c010b2005210120032106034020062802880b21062001417f6a22010d000b200321010340200120012f01064102746a41880b6a28020021012005417f6a22050d000b200621030b20012f010621050b20024188016a2107200241b4016a2005360200200241b0016a4100360200200241ac016a2001360200200220043602b801200241003602a801200242003703a0012002200336029c012002410036029801024002400240024002402004450d0020022004417f6a3602b80102402003450d000240024020032f0106450d004100210841002106410021050c010b4100210641002105034002400240200328020022010d002005ad2109410021010c010b200641016a210620033301044220862005ad8421090b200310352009a72105200121032009422088a7220820012f01064f0d000b200121030b20024190056a41186a220a200320084105746a220141206a29000037030020024190056a41106a220b200141186a29000037030020024190056a41086a220c200141106a2900003703002002200141086a290000370390052003200841e0006c6a220141a4036a2d0000210d200141a0036a280200210420014198036a290300210e20014190036a290300210f20014188036a290300211020014180036a2903002111200141f8026a2903002112200141f0026a2903002113200141e8026a290300210920024180046a41186a2214200141bd036a29000037030020024180046a41106a2215200141b5036a29000037030020024180046a41086a2216200141ad036a2900003703002002200141a5036a29000037038004200841016a2108200141c5036a2d0000211702402006450d00200320084102746a41880b6a2802002103410021082006417f6a2201450d00034020032802880b21032001417f6a22010d000b0b200241e0026a41186a200a290300370300200241e0026a41106a200b290300370300200241e0026a41086a200c290300370300200241d0036a41086a2016290300370300200241d0036a41106a2015290300370300200241d0036a41186a201429030037030020022002290390053703e00220022002290380043703d003200220083602a401200220053602a0012002200336029c01200241003602980120094202510d0120024190056aad42808080808004842118200241d0036aad42808080808004842119200241e0026aad4280808080800284211a20024180046aad4280808080800484211b200241b4046a211c20024190056a41106a210820024180046a41106a211d20024189046a211e20024180046a41086a211f20024180046a412c6a2120200241e0026a412c6a2121200241e0026a41106a212220024188036a2123200241b8046a212402400340200241e0016a41186a2203200241e0026a41186a2225290300370300200241e0016a41106a22012022290300370300200241e0016a41086a2205200241e0026a41086a2226290300370300200241c0016a41086a2206200241d0036a41086a220b290300370300200241c0016a41106a220a200241d0036a41106a220c290300370300200241c0016a41186a2215200241d0036a41186a2214290300370300200220022903e0023703e001200220022903d0033703c00120024180026a41186a2216200329030037030020024180026a41106a2227200129030037030020024180026a41086a22282005290300370300200220022903e00137038002200241a0026a41186a22012015290300370300200241a0026a41106a2205200a290300370300200241a0026a41086a220a2006290300370300200220022903c0013703a00202402017ad42ff0183200920095022031b4201520d0020024200201220031b3703d80320024200201320031b3703d003200220024180026a36029005200241e0026a20024180026a200241d0036a20024190056a10880442022109024020022903e00222294202510d0020232903002113200229038003211220022903f802210920294201520d0020022903e802212920242022290300370300201e200229038002370000201e41086a2028290300370000201e41106a2027290300370000201e41186a2016290300370000200220293703b004200241003a008804200241033a00800441b0b4cc00410020024180046a10d4010b42002013200942025122031b21134200201220031b21124200200920031b2109024020030d0020024190056a41186a220642003703002008420037030020024190056a41086a22034200370300200242003703900541b6fdc600ad4280808080800184222910012215290000212a2026201541086a2900003703002002202a3703e0022015103520032026290300370300200220022903e0023703900541e489c200ad4280808080d00184222a10012215290000212b2026201541086a2900003703002002202b3703e00220151035200820022903e002370000200841086a22272026290300370000201f2003290300370300201d200829030037030020024180046a41186a22282006290300370300200220022903900537038004200241e8006a20024180046a412010d701200241e8006a41106a290300212b2002290370212c20022802682115200642003703002008420037030020034200370300200242003703900520291001221629000021292026201641086a290000370300200220293703e0022016103520032026290300370300200220022903e00237039005202a1001221629000021292026201641086a290000370300200220293703e00220161035200820022903e00237000020272026290300370000201f2003290300370300201d2008290300370300202820062903003703002002200229039005370380042002202b420020151b3703e8022002202c420020151b3703e002201b201a10020b200241d0006a20022903800120022903880120024180016a41106a22032903002009201220131091032003200241d0006a41106a290300370300200220022903583703880120022002290350370380010b200e422088210902400240024002400240024002400240024002400240024002400240200d41ff017122154101460d00201741ff01710d0020042011a772450d010b200241d0036a20024180026a10f30320024180046a20022802d003220620022802d80310d9022026201c41086a2900003703002022201c41106a2900003703002025201c41186a2900003703002002201c2900003703e002024020022d00800422034102460d00201d290300212d200229038804212e20022802b004212f20022802ac04213020022802a804213120022802a404213220022802a0042133200228029c042134200228029804213520024190056a41086a20262903003703002008202229030037030020024190056a41186a2025290300370300200220022903e0023703900520022802d40421360b024020022802d403450d00200610350b024002402003410371417f6a220641014b0d0041022137024020060e020002000b20030d0d2034450d0d203510350c0d0b200241c0026a41186a20024190056a41186a290300370300200241c0026a41106a2008290300370300200241c0026a41086a20024190056a41086a29030037030020022002290390053703c00220362138202f2139203021372031213a2032213b2033213c2034213d2035213e202e213f202d21400b4102210641022141024020374102460d00203c417f4c0d0202400240203c0d0041002103410121420c010b203c10332242450d04203c21030b024002402003203c490d00200321430c010b20034101742206203c2006203c4b1b22434100480d05024020030d002043103322420d010c070b20032043460d0020422003204310372242450d060b2042203e203c109d081a20024180046a41186a200241c0026a41186a290300370300201d200241c0026a41106a290300370300201f200241c0026a41086a290300370300200220022903c0023703800420374101462141203c214420372106203b2145203f214620402147203a2148203921490b200241b0036a41186a224a2001290300370300200241b0036a41106a224b2005290300370300200241b0036a41086a224c200a290300370300200b201f290300370300200c201d290300370300201420024180046a41186a2203290300370300200220022903a0023703b00320022002290380043703d003201741ff0171450d060c050b02400240200ea722030d0041002104200241003602940420024100360284040c010b024002402009a722050d00200321010c010b2005210620032101034020012802ec0321012006417f6a22060d000b0340200320032f01064102746a41ec036a28020021032005417f6a22050d000b0b200241003602980420024100360290042002420037038804200220013602840420024100360280042002200336029404200220032f010636029c040b200220043602a00420024180046a1081030c0b0b1044000b1045000b103e000b103c000b20414102460d010240200d4101710d0020024180046a2042204410f4032002350288044220862002280280042203ad8410110240200228028404450d00200310350b20024180046a20024180026a10f3032002350288044220862002280280042203ad8410070240200228028404450d00200310350b02402043450d00204210350b203721060c030b20024180046a2042204410f4032002350288044220862002280280042206ad8410110240200228028404450d00200610350b200241f0036a20024180026a10890420034200370300201d42003703004108211620024180046a41086a22064200370300200242003703800441d1c4c700ad4280808080e000841001221729000021122006201741086a29000037030020022012370380042017103541e7c4c700ad4280808080e0008410012217290000211220024180056a41086a220d201741086a290000370300200220123703800520171035201d200229038005370000201d41086a200d29030037000020024190056a41086a20062903003703002008201d29030037030020024190056a41186a2003290300370300200220022903800437039005200241c8006a20024190056a412010c001200228024c210620022802482117202241086a200241f0036a41086a280200360200202220022903f003370200202120022903b003370100202141086a200241b0036a41086a290300370100202141106a204b290300370100202141186a204a290300370100427f21132002427f3703e8022002427f3703e002200241083602fc0241002141200241003602840320022006410020171b224d36028003024020430d00427f21290c050b20421035427f2113427f21290c040b20414102470d020b200d410171450d00200241f0036a20024180026a10890420034200370300201d42003703004108211620024180046a41086a22064200370300200242003703800441d1c4c700ad4280808080e000841001221729000021122006201741086a29000037030020022012370380042017103541e7c4c700ad4280808080e0008410012217290000211220024180056a41086a220d201741086a290000370300200220123703800520171035201d200229038005370000201d41086a200d29030037000020024190056a41086a20062903003703002008201d29030037030020024190056a41186a2003290300370300200220022903800437039005200241c0006a20024190056a412010c0012002280244210620022802402117202241086a200241f0036a41086a280200360200202220022903f003370200202120022903b003370100202141086a200241b0036a41086a290300370100202141106a204b290300370100202141186a204a290300370100427f21132002427f3703e8022002427f3703e002200241083602fc0241002141200241003602840320022006410020171b224d36028003427f21290c020b20064102460d020240203d0d004100213d0c030b203e10350c020b202120022903d003370200202141086a200b290300370200202141106a200c290300370200202141186a2014290300370200200220463703e002200220493602880320022041360284032002204836028003200220453602fc02200220443602f802200220433602f402200220423602f002200220473703e8022048214d2046211320472129204521160b024020114201520d00200220103703e0022002200f3703e80220102113200f21290b02402015450d00202120022903a002370000202141186a2001290300370000202141106a2005290300370000202141086a200a2903003700000b200ea7210102402004450d0020034200370300201d4200370300201f4200370300200242003703800441d1c4c700ad4280808080e0008410012205290000210e201f200541086a2900003703002002200e370380042005103541e7c4c700ad4280808080e0008410012205290000210e20024180056a41086a2206200541086a2900003703002002200e3703800520051035201d200229038005370000201d41086a200629030037000020024190056a41086a201f2903003703002008201d29030037030020024190056a41186a2003290300370300200220022903800437039005200241386a20024190056a412010c0014101214120024101360284032002200228023c410020022802381b360288030b0240024020010d004100210341002101410021040c010b024002402009a722050d00200121030c010b2005210620012103034020032802ec0321032006417f6a22060d000b0340200120012f01064102746a41ec036a28020021012005417f6a22050d000b0b20012f0106214e0b200220043602a0042002204e36029c0420024100360298042002200136029404200241003602900420024200370388042002200336028404200241003602800402402004450d0020022004417f6a22153602a00402402003450d000240024020032f0106450d004100210d41002106410021050c010b4100210641002105034002400240200328020022010d002005ad2109410021010c010b200641016a210620033301044220862005ad8421090b200310352009a72105200121032009422088a7220d20012f01064f0d000b200121030b20024190056a41186a22172003200d4105746a220141206a2900003703002008200141186a29000037030020024190056a41086a220a200141106a2900003703002002200141086a29000037039005200d41016a21042003200d410c6c6a220141f0026a2802002127200141ec026a280200214f200141e8026a280200210d02402006450d00200320044102746a41ec036a2802002103410021042006417f6a2201450d00034020032802ec0321032001417f6a22010d000b0b20142017290300370300200c2008290300370300200b200a29030037030020022002290390053703d0032002200436028c0420022005360288042002200336028404200241003602800420022802f802212820022802f00221500340204a20142903002209370300204b200c290300220e370300204c200b2903002211370300200220022903d00322123703b00320142009370300200c200e370300200b2011370300200220123703d00320024180056a2050202810f40320191009220141086a2900002109200141106a290000210e200129000021112017200141186a2900003703002008200e370300200a2009370300200220113703900520011035200241f0036a2002350288054220862002280280052201ad842018101010c201024020022802f0032206450d00201620022802f8036b211620022802f403450d00200610350b0240200228028405450d00200110350b02400240200d450d0020024180056a2050202810f40320191009220141086a2900002109200141106a290000210e200129000021112017200141186a2900003703002008200e370300200a20093703002002201137039005200110352002350288054220862002280280052201ad8420182027ad422086200dad8410120240200228028405450d00200110350b201620276a2116204f450d01200d10350c010b20024180056a2050202810f40320191009220141086a2900002109200141106a290000210e200129000021112017200141186a2900003703002008200e370300200a20093703002002201137039005200110352002350288054220862002280280052201ad8420181013200228028405450d00200110350b024020150d00200220163602fc020c030b20022015417f6a22153602a00402402003450d00410021060240200420032f0106490d00034002400240200328020022010d002005ad2109410021010c010b200641016a210620033301044220862005ad8421090b200310352009a72105200121032009422088a7220420012f01064f0d000b200121030b2017200320044105746a220141206a2900003703002008200141186a290000370300200a200141106a2900003703002002200141086a29000037039005200441016a215120032004410c6c6a220141f0026a2802002127200141ec026a280200214f200141e8026a280200210d0240024020060d00205121040c010b200320514102746a41ec036a2802002103410021042006417f6a2201450d00034020032802ec0321032001417f6a22010d000b0b20142017290300370300200c2008290300370300200b200a29030037030020022002290390053703d0032002200436028c042002200536028804200220033602840420024100360280040c010b0b41958dcc00412b41c08dcc00103f000b41958dcc00412b41c08dcc00103f000b20024180046a10810320024190056a41186a2203200241c0026a41186a2903003703002008200241c0026a41106a29030037030020024190056a41086a2201200241c0026a41086a290300370300200220022903c002370390050240024020374102460d002020200229039005370200202041086a2001290300370200202041106a2008290300370200202041186a20032903003702002002203f37038004200220393602a804200220373602a4042002203a3602a0042002203b36029c042002203d360294042002203e36029004200220383602cc0420022040370388042002203c36029804410121030240203c20022802f802470d000240024020022802f0022201203e460d00203e2001203c10a0080d02203b2016470d020c010b203b2016470d010b20202021412010a0080d00203f2013852040202985844200520d00203a204d470d00024020372041470d004100210320374101470d012039200228028803460d010b410121030b0240203d450d00203e10350b20034102460d002003450d010b201f200241e0026a41d000109d081a200241003a00800420024190056a20024180026a10f303200228029005210320022002280298053602d403200220033602d00320024180046a200241d0036a108a040240200228029405450d00200310350b200228029c04450d0220022802980410350c020b20022802f402450d0120022802f00210350c010b02400240200ea722030d0041002104200241003602940420024100360284040c010b024002402009a722050d00200321010c010b2005210620032101034020012802ec0321012006417f6a22060d000b0340200320032f01064102746a41ec036a28020021032005417f6a22050d000b0b200241003602980420024100360290042002420037038804200220013602840420024100360280042002200336029404200220032f010636029c040b200220043602a00420024180046a1081030b024020022802b8012203450d0020022003417f6a3602b801200228029c012203450d0220022802a00121052002280298012106024020022802a401220420032f0106490d00034002400240200328020022010d002005ad2109410021010c010b200641016a210620033301044220862005ad8421090b200310352009a72105200121032009422088a7220420012f01064f0d000b200121030b20024190056a41186a2215200320044105746a220141206a2900003703002008200141186a29000037030020024190056a41086a2216200141106a2900003703002002200141086a29000037039005201f2003200441e0006c6a220141ad036a290000370300201d200141b5036a29000037030020024180046a41186a2227200141bd036a2900003703002002200141a5036a29000037038004200441016a210a20014190036a290300210f20014188036a2903002110200141f8026a2903002112200141f0026a2903002113200141c5036a2d00002117200141a4036a2d0000210d200141a0036a280200210420014198036a290300210e20014180036a2903002111200141e8026a290300210902402006450d002003200a4102746a41880b6a28020021034100210a2006417f6a2201450d00034020032802880b21032001417f6a22010d000b0b202520152903003703002022200829030037030020262016290300370300200b201f290300370300200c201d2903003703002014202729030037030020022002290390053703e00220022002290380043703d0032002200a3602a401200220053602a0012002200336029c01200241003602980120094202520d010b0b200229038001210920024198016a108f0320024180046a2104200950450d040c030b41958dcc00412b41c08dcc00103f000b41958dcc00412b41c08dcc00103f000b20024198016a108f030b024020022903880120024190016a29030084500d0041a1c2c300413341c086cc00103f000b200229038001500d0120024180046aad4280808080800484211b20024180046a21040b200220073602980120024190056a41186a2208420037030020024190056a41106a2205420037030020024190056a41086a22014200370300200242003703900541b6fdc600ad42808080808001842218100122062900002109200241e0026a41086a2203200641086a290000370300200220093703e0022006103520012003290300370300200220022903e0023703900541e489c200ad4280808080d0018422191001220629000021092003200641086a290000370300200220093703e00220061035200520022903e002220937030020024180046a41086a2217200129030037030020024180046a41106a220a200937030020024180046a41186a220b2003290300370300200220022903900537038004200241206a2004412010d701200241206a41106a290300210e200229032821112002280220210620024180016a41106a29030021122002290388012109200842003703002005420037030020014200370300200242003703900520181001220429000021182003200441086a290000370300200220183703e0022004103520012003290300370300200220022903e0023703900520191001220429000021182003200441086a290000370300200220183703e00220041035200520022903e002221837030020172001290300370300200a2018370300200b200329030037030020022002290390053703800420024200200e420020061b221820127d2011420020061b2219200954ad7d220e201920097d2209201956200e201856200e2018511b22031b3703e80220024200200920031b3703e002201b200241e0026aad428080808080028410020c010b200220073602980120024190056a41186a2204420037030020024190056a41106a2205420037030020024190056a41086a22014200370300200242003703900541b6fdc600ad42808080808001842209100122062900002118200241e0026a41086a2203200641086a290000370300200220183703e0022006103520012003290300370300200220022903e0023703900541e489c200ad4280808080d0018422181001220629000021192003200641086a290000370300200220193703e00220061035200520022903e002221937030020024180046a41086a2208200129030037030020024180046a41106a2217201937030020024180046a41186a220a2003290300370300200220022903900537038004200241086a20024180046a412010d701200241086a41106a29030021192002290310210e2002280208210620024180016a41106a29030021112002290388012112200442003703002005420037030020014200370300200242003703900520091001220429000021092003200441086a290000370300200220093703e0022004103520012003290300370300200220022903e0023703900520181001220429000021092003200441086a290000370300200220093703e00220041035200520022903e00222093703002008200129030037030020172009370300200a20032903003703002002200229039005370380042002427f20112019420020061b22097c2012200e420020061b22187c22192018542203ad7c22182003201820095420182009511b22031b3703e8022002427f201920031b3703e00220024180046aad4280808080800484200241e0026aad428080808080028410020b200241b0056a24000b9c3b040f7f017e017f067e230041d0046b2207240020074198026a200110f303200741d0036a200728029802220820072802a00210d902200741f8026a41086a2209200741da036a290100370300200741f8026a410e6a220a200741d0036a41106a290000370100200741a0036a41086a220b20074188046a290300370300200741a0036a41106a220c20074190046a290300370300200741a0036a41186a220d20074198046a290300370300200741a0036a41206a220e200741a0046a290300370300200720072901d2033703f8022007200741f1036a290000370390032007200741f8036a28000036009703200720074180046a2903003703a003200741d0036a41206a2d0000210f200741ec036a2802002110200741d0036a41186a28020021110240024020072d00d00322124102460d00200741fc036a2802002113200741e0026a410e6a200a290100370100200741e0026a41086a2009290300370300200741a8026a41086a200b290300370300200741a8026a41106a200c290300370300200741a8026a41186a200d290300370300200741a8026a41206a200e290300370300200720072903f8023703e00220072007290390033703d00220072007280097033600d702200720072903a0033703a8020240200728029c02450d00200810350b200741f8026a41086a200741e0026a41086a290300370300200741f8026a410e6a2209200741e0026a410e6a290100370100200741a0036a41086a220b200741a8026a41086a290300370300200741a0036a41106a220c200741a8026a41106a290300370300200741a0036a41186a220d200741a8026a41186a290300370300200741a0036a41206a220e200741a8026a41206a290300370300200720072903e0023703f802200720072903d00237039003200720072800d70236009703200720072903a8023703a003410221084102210a024020120d0020074198026a41086a2009290100370300200741d0036a41086a200b290300370300200741d0036a41106a200c290300370300200741d0036a41186a200d290300370300200741d0036a41206a200e290300370300200720072901fe0237039802200720072903900337038802200720072800970336008f02200720072903a0033703d0032013210a0b41012109200a4102460d01200741b6026a20074198026a41086a290300370100200741a0036a41086a200741d0036a41086a290300370300200741a0036a41106a200741d0036a41106a290300370300200741a0036a41186a200741d0036a41186a290300370300200741a0036a41206a200741d0036a41206a29030037030020072007290398023701ae0220072007290388023703f8022007200728008f023600ff02200720072903d0033703a00341002109200a21080c010b0240200728029c02450d00200810350b41012109410221080b200741f0016a41086a200741a8026a41086a220a290100370300200741f0016a410e6a220b200741a8026a410e6a290100370100200741b8016a41086a220c200741a0036a41086a220d290300370300200741b8016a41106a220e200741a0036a41106a2212290300370300200741b8016a41186a2213200741a0036a41186a2214290300370300200741b8016a41206a2215200741a0036a41206a290300370300200720072901a8023703f001200720072903f8023703e001200720072800ff023600e701200720072903a0033703b8010240024002400240024020090d00200741e8006a41186a200f3a0000200741fc006a2010360200200741e8006a41206a20072800e701360000200741e8006a41286a220f20072903b801370300200741e8006a41086a200b290100370300200741e8006a41306a200c290300370300200741e8006a41386a200e290300370300200741e8006a41c0006a2013290300370300200741e8006a41c8006a2015290300370300200720072901f60137036820072011360278200720072903e001370081012007200836028c01200741d0036a41186a4200370300200741d0036a41106a220c4200370300200741d0036a41086a22094200370300200742003703d00341d1c4c700ad4280808080e000841001220b29000021162009200b41086a290000370300200720163703d003200b103541e7c4c700ad4280808080e000841001220b2900002116200a200b41086a290000370300200720163703a802200b1035200c20072903a8022216370300200d2009290300370300201220163703002014200a290300370300200720072903d0033703a003200741e0006a200741a0036a412010c0012007280264410020072802601b210c20084101470d01200f280200200c470d0120004183243b0100200041086a4115360200200041046a41d880c700360200200041026a41053a00000c020b20004183243b0100200041086a4115360200200041046a41fcffc600360200200041026a41023a00000c020b200741f0016a200210f303200741d0036a20072802f001220820072802f80110d902200741f8026a41086a2209200741da036a290100370300200741f8026a410e6a220a200741d0036a41106a290000370100200741a0036a41086a200741d0036a41386a290300370300200741a0036a41106a200741d0036a41c0006a290300370300200741a0036a41186a200741d0036a41c8006a290300370300200741a0036a41206a200741a0046a290300370300200720072901d2033703f8022007200741f1036a290000370390032007200741d0036a41286a280000360097032007200741d0036a41306a2903003703a00302400240024020072d00d003220b4102460d00200741d0036a41206a2d0000210f200741ec036a280200210d200741d0036a41186a280200210e20072d00d1032110200741a8026a410e6a200a290100370100200741a8026a41086a2009290300370300200720072903f8023703a802024020072802f401450d00200810350b200741d0036a410e6a2208200741a8026a410e6a290100370100200741d0036a41086a2209200741a8026a41086a290300370300200720072903a8023703d003200b0d02200d450d01200e10350c010b20072802f401450d00200810350b20004183243b0100200041086a411a360200200041046a419c80c700360200200041026a41033a00000c010b200741e0026a410e6a220a2008290100370100200741e0026a41086a220b2009290300370300200741c1016a200b290300370000200741c7016a200a290100370000200720103a00b801200720072903d0033700b9012007200f3a00d7012007200d3600d3012007200e3600cf01200641086a2802002113200728028c01211520072802900121172007200628020022143602e00220072014201341057422096a3602e4022007200741e8006a3602e802024002400240024002400240024002402013450d002014210803402007200841206a220a3602e002200741d0036a200b200810800620072802d00322080d02200a2108200941606a22090d000b0b4104210d41002109410021110c010b200741a0036a41086a2211200741d0036a410c6a280200360200200720072902d4033703a00341101033220d450d01200d2008360200200d20072903a003370204200d410c6a201128020036020020074281808080103702fc022007200d3602f8022011200741e0026a41086a280200360200200720072903e00222163703a00302402016a7220820072802a4032209470d0041012109410121110c010b200741d0036a410472210f200941606a211241012109024003402007200841206a220a3602a003200741d0036a20112008108006024020072802d003220e0d002012200846210b200a2108200b450d010c020b200741a8026a41086a200f41086a280200220b3602002007200f29020022163703a802200741d0036a41086a2210200b360200200720163703d0030240200920072802fc02470d00200741f8026a20094101108c0120072802f802210d0b200d20094104746a220b200e360200200b20072903d003370204200b410c6a20102802003602002007200941016a2209360280032012200847210b200a2108200b0d000b0b20072802fc0221110b200741a0036a200728027820072802800110f4030240024020073502a80342208620072802a0032212ad8410212216422088a7220f0d00410121100c010b2016a721100b200741003602d803200742013703d0032010200f200741d0036a1097030240024020072802d403220b20072802d80322086b4120490d0020072802d003210a200b210e0c010b200841206a220a2008490d02200b410174220e200a200e200a4b1b220e4100480d0202400240200b0d000240200e0d004101210a0c020b200e1033220a0d010c070b20072802d003210a200b200e460d00200a200b200e1037220a450d060b2007200e3602d4032007200a3602d0030b200a20086a220b2003290000370000200b41186a200341186a290000370000200b41106a200341106a290000370000200b41086a200341086a2900003700002007200841206a22083602d8032008ad422086200aad84100922082900002116200841086a2900002118200841106a2900002119200741a8026a41186a200841186a290000370300200741a8026a41106a2019370300200741a8026a41086a2018370300200720163703a802200810350240200e450d00200a10350b0240200f450d00201010350b024020072802a403450d00201210350b0240200741a8026a200741b8016a412010a0080d000240024020090d004100210a0c010b2009410474210b200d410c6a21084100210a03402008280200200a6a210a200841106a2108200b41706a220b0d000b0b200741e8006a41106a2108200c201720131b210b4101201520131b210e2007200728028401200a6b36028401200741d0036a200110f30320073502d80342208620072802d003220aad841007024020072802d403450d00200a10350b200741d0036a41106a200537030020074180046a200b360200200741fc036a200e360200200741f8036a200c360200200741f4036a200728028401360200200741d0036a41186a2008290300370300200741f0036a200841086a28020036020020074184046a20032900003702002007418c046a200341086a29000037020020074194046a200341106a2900003702002007419c046a200341186a290000370200200720043703d803200741003a00d003200741a0036a200210f30320072802a0032108200720072802a8033602fc02200720083602f802200741d0036a200741f8026a108a04024020072802a403450d00200810350b0240200741ec036a280200450d0020072802e80310350b200741a0036a2001108e02200741d0036a20072802a003220820072802a803108f0220072903d0032105200741e0036a290300211620072903d8032118024020072802a403450d00200810350b200742003703f801200742003703f001200720013602f802200741a0036a2001200741f0016a200741f8026a1088040240024020072903a003221a4202520d00420221040c010b200741c8036a290300211b200741c0036a2903002119200741a0036a41186a2903002104201a4201520d0020072903a803211a20074188046a200741a0036a41106a29030037030020074180046a201a370300200741d0036a41086a41003a0000200741d9036a2001290000370000200741e1036a200141086a290000370000200741e9036a200141106a290000370000200741f1036a200141186a290000370000200741033a00d00341b0b4cc004100200741d0036a10d4010b200542015121014200201b200442025122081b211b4200201920081b21194200200420081b2104024020080d00200741d0036a41186a220e4200370300200741d0036a41106a220b4200370300200741d0036a41086a220a4200370300200742003703d00341b6fdc600ad428080808080018422051001220c290000211a200741e0026a41086a2208200c41086a2900003703002007201a3703e002200c1035200a2008290300370300200720072903e0023703d00341e489c200ad4280808080d00184221a1001220c290000211c2008200c41086a2900003703002007201c3703e002200c1035200b20072903e002221c370300200741a0036a41086a220f200a290300370300200741a0036a41106a2210201c370300200741a0036a41186a22122008290300370300200720072903d0033703a003200741c8006a200741a0036a412010d701200741c8006a41106a290300211c2007290350211d2007280248210c200e4200370300200b4200370300200a4200370300200742003703d00320051001220e29000021052008200e41086a290000370300200720053703e002200e1035200a2008290300370300200720072903e0023703d003201a1001220e29000021052008200e41086a290000370300200720053703e002200e1035200b20072903e0022205370300200f200a2903003703002010200537030020122008290300370300200720072903d0033703a0032007201c4200200c1b3703d8032007201d4200200c1b3703d003200741a0036aad4280808080800484200741d0036aad428080808080028410020b2016420020011b21052018420020011b2116200741f8026a41106a220b201b3703002007201937038003200720043703f802200741f8026a41086a21080240024020044200520d00200720083602f001200741d0036a41186a220e4200370300200741d0036a41106a220a4200370300200741d0036a41086a22014200370300200742003703d00341b6fdc600ad428080808080018422041001220c2900002118200741e0026a41086a2208200c41086a290000370300200720183703e002200c103520012008290300370300200720072903e0023703d00341e489c200ad4280808080d0018422181001220c29000021192008200c41086a290000370300200720193703e002200c1035200a20072903e0022219370300200741a0036a41086a220f2001290300370300200741a0036a41106a22102019370300200741a0036a41186a22122008290300370300200720072903d0033703a003200741186a200741a0036a412010d701200741186a41106a29030021192007290320211b2007280218210c200b290300211a200729038003211c200e4200370300200a420037030020014200370300200742003703d00320041001220b29000021042008200b41086a290000370300200720043703e002200b103520012008290300370300200720072903e0023703d00320181001220b29000021042008200b41086a290000370300200720043703e002200b1035200a20072903e0022204370300200f20012903003703002010200437030020122008290300370300200720072903d0033703a0032007427f201a20194200200c1b22047c201c201b4200200c1b22187c22192018542208ad7c22182008201820045420182004511b22081b3703d8032007427f201920081b3703d003200741a0036aad4280808080800484200741d0036aad428080808080028410020c010b200720083602f001200741d0036a41186a220e4200370300200741d0036a41106a220a4200370300200741d0036a41086a22014200370300200742003703d00341b6fdc600ad428080808080018422181001220c2900002104200741e0026a41086a2208200c41086a290000370300200720043703e002200c103520012008290300370300200720072903e0023703d00341e489c200ad4280808080d0018422191001220c29000021042008200c41086a290000370300200720043703e002200c1035200a20072903e0022204370300200741a0036a41086a220f2001290300370300200741a0036a41106a22102004370300200741a0036a41186a22122008290300370300200720072903d0033703a003200741306a200741a0036a412010d701200741306a41106a290300211b2007290338211a2007280230210c200b290300211c2007290380032104200e4200370300200a420037030020014200370300200742003703d00320181001220b29000021182008200b41086a290000370300200720183703e002200b103520012008290300370300200720072903e0023703d00320191001220b29000021182008200b41086a290000370300200720183703e002200b1035200a20072903e0022218370300200f20012903003703002010201837030020122008290300370300200720072903d0033703a00320074200201b4200200c1b2218201c7d201a4200200c1b2219200454ad7d221b201920047d2204201956201b201856201b2018511b22081b3703d80320074200200420081b3703d003200741a0036aad4280808080800484200741d0036aad428080808080028410020b200720163703f802200720053703800302400240201620058450450d0042002105420021160c010b200720023602e002200741a0036a2002200741f8026a200741e0026a10b002024020072903a0034201520d00200741b0036a290300211620072903a80321050c010b200741c8036a2903002116200741c0036a290300210520072903a8034201520d00200741a0036a41106a290300210420074188046a200741a0036a41186a29030037030020074180046a2004370300200741d0036a41086a41003a0000200741d9036a2002290000370000200741e1036a200241086a290000370000200741e9036a200241106a290000370000200741f1036a200241186a290000370000200741033a00d00341b0b4cc004100200741d0036a10d4010b200741d0036a41186a220c4200370300200741d0036a41106a220a4200370300200741d0036a41086a22014200370300200742003703d00341b6fdc600ad428080808080018422041001220b2900002118200741e0026a41086a2208200b41086a290000370300200720183703e002200b103520012008290300370300200720072903e0023703d00341e489c200ad4280808080d0018422181001220b29000021192008200b41086a290000370300200720193703e002200b1035200a20072903e0022219370300200741a0036a41086a220e2001290300370300200741a0036a41106a220f2019370300200741a0036a41186a22102008290300370300200720072903d0033703a0032007200741a0036a412010d701200741106a29030021192007290308211b2007280200210b200c4200370300200a420037030020014200370300200742003703d00320041001220c29000021042008200c41086a290000370300200720043703e002200c103520012008290300370300200720072903e0023703d00320181001220c29000021042008200c41086a290000370300200720043703e002200c1035200a20072903e0022204370300200e2001290300370300200f200437030020102008290300370300200720072903d0033703a0032007427f20194200200b1b220420167c201b4200200b1b221620057c22182016542208ad7c22052008200520045420052004511b22081b3703d8032007427f201820081b3703d003200741a0036aad4280808080800484200741d0036aad42808080808002841002200041043a000002402009450d0020094104742108200d41046a210003400240200041046a280200450d00200028020010350b200041106a2100200841706a22080d000b0b0240201141ffffffff0071450d00200d10350b200641046a28020041ffffff3f71450d08201410350c080b200d20094104746a210a024020090d00200d21080c030b200741d0036aad42808080808004842119200d210803400240200828020022090d00200841106a21080c040b200841086a280200210b200841046a28020021012008410c6a3502002104200741a0036a200728027820072802800110f4032009ad4280808080800484100922092900002105200941086a2900002116200941106a2900002118200741d0036a41186a200941186a290000370300200741d0036a41106a2018370300200741d0036a41086a2016370300200720053703d0032009103520073502a80342208620072802a0032209ad84201920044220862001ad841012024020072802a403450d00200910350b0240200b450d00200110350b200841106a2208200a470d000c040b0b1045000b103e000b200a2008460d000340200841106a21090240200841086a280200450d00200841046a28020010350b20092108200a2009470d000b0b0240201141ffffffff0071450d00200d10350b20004183243b0100200041086a4110360200200041046a41c080c700360200200041026a41043a00000c010b103c000b200728027c450d00200728027810350b200641046a28020041ffffff3f71450d00200628020010350b200741d0046a24000bd90e03087f037e027f23004180026b2202240041002103200241003a00b801200041b0b4cc0020011b210402400240024002400240034020012003460d0120024198016a20036a200420036a2d00003a00002002200341016a22003a00b8012000210320004120470d000b200241086a41186a20024198016a41186a290300370300200241086a41106a20024198016a41106a290300370300200241086a41086a20024198016a41086a290300370300200220022903980137030841002103200241003a00b801200420006a2104200120006b2101034020012003460d0220024198016a20036a200420036a2d00003a00002002200341016a22003a00b8012000210320004120470d000b200241286a41186a220320024198016a41186a2204290300370300200241286a41106a220020024198016a41106a290300370300200241286a41086a220120024198016a41086a2903003703002002200229039801370328200241c8006a41186a200241086a41186a290300370300200241c8006a41106a200241086a41106a290300370300200241c8006a41086a200241086a41086a29030037030020022002290308370348200241e8006a41186a2003290300370300200241e8006a41106a2000290300370300200241e8006a41086a200129030037030020022002290328370368200241f0016a200241c8006a10f30320024198016a20022802f001220020022802f80110d90220022802f401210320022d00980122014102460d02200241c4016a2802002105200241b8016a2802002106200241b4016a28020021072004280200210802402003450d00200010350b410121092001450d03410121040c040b0240200341ff0171450d00200241003a00b8010b200241ac016a4102360200200241f4006a41043602002002420237029c01200241f0b2c300360298012002410436026c200241f0b4c3003602682002410036024c200241b0b4cc003602482002200241e8006a3602a8012002200241c8006a36027020024198016a4180b3c300104c000b0240200341ff0171450d00200241003a00b8010b200241ac016a4102360200200241f4006a41043602002002420237029c01200241f0b2c300360298012002410436026c200241f0b4c3003602682002410036024c200241b0b4cc003602482002200241e8006a3602a8012002200241c8006a36027020024198016a4180b3c300104c000b02402003450d00200010350b41012104410021090c010b4101210420054102460d00200241f0016a2008200610f403200241e8006aad428080808080048410092203290000210a200341086a290000210b200341106a290000210c20024198016a41186a200341186a29000037030020024198016a41106a200c37030020024198016a41086a200b3703002002200a370398012003103520024188016a20023502f80142208620022802f0012203ad8420024198016aad4280808080800484101010c201024020022802f401450d00200310350b20024188016a41086a280200210d2002280288012101200228028c01210e4100210402402007450d00200810350b0b410121030240024002400240024002400240024020040d00200d41066a410220011b2203417f4c0d0220030d0041002103410121000c010b200310332200450d020b200241003602a00120022000360298012002200336029c0102402004450d00024020030d00410110332200450d052002410136029c0120022000360298010b200041013a0000200241013602a0012002280298012103200228029c0121000240200941ff01714101460d00024020004101470d0020034101410210372203450d062002410236029c0120022003360298010b200341003a0001200241023602a0010c060b024020004101470d0020034101410210372203450d052002410236029c0120022003360298010b200341013a0001200241023602a0010c050b024020030d00410110332200450d042002410136029c0120022000360298010b200041003a0000200241013602a0012002280298012103200228029c0121000240024020010d00024020004101470d0020034101410210372203450d062002410236029c0120022003360298010b200341003a0001200241023602a001428080808020210a0c010b024020004101470d0020034101410210372203450d052002410236029c0120022003360298010b200341013a0001200241023602a001200d20024198016a107702400240200228029c01220420022802a00122006b200d490d0020022802980121030c010b2000200d6a22032000490d04200441017422092003200920034b1b22094100480d040240024020040d00024020090d00410121030c020b2009103322030d010c070b200228029801210320042009460d0020032004200910372203450d060b2002200936029c0120022003360298010b200320006a2001200d109d081a20022000200d6a22003602a0012000ad422086210a0b200a2003ad84210a2001450d05200e450d05200110350c050b1044000b1045000b103e000b103c000b2003ad42808080802084210a0b20024180026a2400200a0bb10503027f017e047f230041d0006b2202240041f1d8cb00ad4280808080900184100122032900002104200241086a41086a200341086a290000370300200220043703082003103541abe0c600ad4280808080e00184100122032900002104200241186a41086a200341086a29000037030020022004370318200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad42808080808004841003220129000037033820011035200241cc006a200341206a360200200220033602482002200241386a41086a3602442002200241386a360240200241286a200241c0006a107b200310352002280230220541206a2201417f4c0d01200228022821060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a2000200136020820002008360204200020033602000240200228022c450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000bb30101037f02400240024002402002417f4c0d000240024020020d0041002103410121040c010b200210332204450d02200221030b0240024020032002490d00200321050c010b200341017422052002200520024b1b22054100480d03024020030d002005103322040d010c050b20032005460d0020042003200510372204450d040b200420012002109d0821032000200236020820002005360204200020033602000f0b1044000b1045000b103e000b103c000ba70c04037f047e047f037e23004190046b2202240041002103200241003a008003200041b0b4cc0020011b210402400240024002400240034020012003460d01200241e0026a20036a200420036a2d00003a00002002200341016a22003a0080032000210320004120470d000b200241386a41186a200241e0026a41186a2903002205370300200241386a41106a200241e0026a41106a2903002206370300200241386a41086a200241e0026a41086a2903002207370300200220022903e0022208370338200241d8006a41186a2005370300200241d8006a41106a2006370300200241d8006a41086a200737030020022008370358200241d0016a200241d8006a10f303200241e0026a20022802d001220020022802d80110d90220022d00e0022103200241b8036a200241e0026a41017241d700109d081a024020034102460d00200241f8006a200241b8036a41d700109d081a0b024020022802d401450d00200010350b410121002003417f6a41ff01714102490d04200241d0016a200241ff006a220941d000109d081a200241e0026a41186a220a4200370300200241e0026a41106a22044200370300200241e0026a41086a22034200370300200242003703e00241d1c4c700ad4280808080e000841001220029000021052003200041086a290000370300200220053703e0022000103541e7c4c700ad4280808080e00084100122002900002105200241c0026a41086a2201200041086a290000370300200220053703c00220001035200420022903c0022205370300200241b8036a41086a2003290300370300200241b8036a41106a220b2005370300200241b8036a41186a2001290300370300200220022903e0023703b803200241306a200241b8036a412010c001200241a0026a200241d8006a2002280234410020022802301b220c4100200241d0016a10f603200241b8036a200941d000109d081a200241c0026a41186a200241a0026a41186a290300370300200241c0026a41106a200241a0026a41106a2903003703002001200241a0026a41086a290300370300200220022903a0023703c002200241e0026a200241d8006a200241b8036a200c200241c0026a10f703410121014101210020022d00e002417f6a41ff01714102490d03200429030021082003290300210d20024184036a2802002103200241fc026a2802002104200a2802002109200241c0026a200241d8006a108e02200241b8036a20022802c002220a20022802c802108f02200b290300420020022903b80342015122001b210620022903c003420020001b2105024020022802c402450d00200a10350b200241206a20052006428080a8ec85afd1b1014200109808200241106a42002003ad22072002290320220e7d220f200f2007564200200241206a41086a2903002007200e54ad7c7d22074200522007501b22031b220e4200200720031b2207428080e983b1de164200108408200e200784500d022005428080d287e2bc2d5441002006501b0d0120022005428080aef89dc3527c2207200d200d200756200820062007200554ad7c427f7c22055620082005511b22031b2005200820031b2002290310200241106a41086a29030010980820022903002205a7417f2005428080808010544100200241086a290300501b1b210302402004450d00200910350b2003200c6a210441002101410021000c040b0240200341ff0171450d00200241003a0080030b200241f4026a4102360200200241c4036a4104360200200242023702e402200241f0b2c3003602e002200241043602bc0320024184b5c3003602b8032002410036027c200241b0b4cc003602782002200241b8036a3602f0022002200241f8006a3602c003200241e0026a4180b3c300104c000b41c780ca00419b0141e481ca001064000b410021002004450d00200910350b0b02400240410110332203450d000240024002402000450d00200341013a000020034101410210372203450d04200341013a00010c010b200341003a000020034101410210372103024020014101460d002003450d04200341003a000120034102410610372203450d04200320043600024280808080e00021050c020b2003450d03200341013a00010b42808080802021050b20024190046a240020052003ad840f0b1045000b103c000bb90504017f017e017f057e23004190016b220524000240024041004100200220036b2203200320024b1b220220042802206b2203200320024b1b22030d00420021060c010b20054180016a2001108e02200541306a2005280280012207200528028801108f0242002106200541c0006a2903004200200529033042015122021b21082005290338420020021b21090240200528028401450d00200710350b200541206a20092008428080a8ec85afd1b101420010980842002004411c6a350200220a2005290320220b7d220c200c200a564200200541286a290300200a200b54ad7c7d220a420052200a501b22021b220b4200200a20021b220a844200510d00420121062009428080d287e2bc2d5441002008501b0d00200541106a2003ad4200200b200a10840820052005290310200541106a41086a290300428080e983b1de164200108408024002402009428080aef89dc3527c22062004290300220a200a200656200441086a290300220a20082006200954ad7c427f7c220656200a2006511b22041b220b2005290300220c200b200c542006200a20041b220a200541086a290300220b54200a200b511b22041b2206200a200b20041b220a8450450d00410121020c010b42002008200a7d2009200654ad7d220b200920067d220c200956200b200856200b2008511b22021b21094200200c20021b210b20054180016a2001108e02200541306a2005280280012203200528028801108f02200541e0006a2903004200200529033042015122021b2108200541d8006a290300420020021b210c0240200528028401450d00200310350b200c200b58200820095820082009511b21020b024020040d002002450d0020002006370308200041106a200a370300420321060c010b200041186a200a370300200041106a200637030020002002ad370308420221060b2000200637030020054190016a24000bbe1d05017f037e057f037e037f230041f0026b220524000240024002400240024002400240024020042802000e0401020300010b200441106a290300210620042903082107200541e0006a2003360200200541386a41186a2002290310370300200541e4006a2002290224370200200541d8006a200241186a290300370300200541386a41346a200229022c370200200541386a413c6a200241346a290200370200200541386a41c4006a2002413c6a29020037020020054184016a200241c4006a290200370200200541386a41106a200241086a29030020067d20022903002208200754ad7d37030041002102200541003a00382005200820077d370340200541e0016a200110f30320052802e0012104200520052802e80136029c012005200436029801200541386a20054198016a10f805024020052802e401450d00200410350b200541003a00df01200541083a009701200520013602d801200520073703e002200520063703e80202400240200720068450450d0042002107420021060c010b200520013602c8012005200541c8016a3602f001200520054197016a3602ec012005200541d8016a3602e8012005200541df016a3602e4012005200541e0026a3602e00120054198016a2001200541e0016a10dc034101210202402005280298014101470d004200210620052903a00121070c010b200541c0016a2903002106200541b8016a29030021074100210220052903a0014201520d0020054198016a41106a290300210820052802c801210120054198026a20054198016a41186a29030037030020054190026a200837030041002102200541e0016a41086a41003a0000200541e9016a2001290000370000200541f1016a200141086a290000370000200541f9016a200141106a29000037000020054181026a200141186a290000370000200541033a00e00141b0b4cc004100200541e0016a10d4010b024020020d00200520073703c801200520063703d0010240024020072006844200520d002005200541c8016a3602d801200541c8016a21030c010b200520063703d001200520073703c8012005200541c8016a3602d801200541c8016a21030b200541e0016a41186a22094200370300200541e0016a41106a22044200370300200541e0016a41086a22014200370300200542003703e00141b6fdc600ad428080808080018422061001220a2900002107200541e0026a41086a2202200a41086a290000370300200520073703e002200a103520012002290300370300200520052903e0023703e00141e489c200ad4280808080d0018422081001220a29000021072002200a41086a290000370300200520073703e002200a1035200420052903e002220737030020054198016a41086a220b200129030037030020054198016a41106a220c200737030020054198016a41186a220d2002290300370300200520052903e00137039801200541206a20054198016a412010d701200541206a41106a290300210e2005290328210f2005280220210a200341086a290300211020032903002107200942003703002004420037030020014200370300200542003703e00120061001220329000021062002200341086a290000370300200520063703e0022003103520012002290300370300200520052903e0023703e00120081001220329000021062002200341086a290000370300200520063703e00220031035200420052903e0022206370300200b2001290300370300200c2006370300200d2002290300370300200520052903e0013703980120054200200e4200200a1b220620107d200f4200200a1b2208200754ad7d220e200820077d2207200856200e200656200e2006511b22021b3703e80120054200200720021b3703e00120054198016aad4280808080800484200541e0016aad428080808080028410020b2000200541386a41d800109d081a0c060b200541e7016a200241d000109d081a200041003a0000200041016a200541e0016a41d700109d081a0c050b200541e0016a200110f30320053502e80142208620052802e0012204ad841007024020052802e401450d00200410350b200541e0016a2002280210220a200241186a28020010f40320053502e80142208620052802e0012204ad841011024020052802e401450d00200410350b200541e0016a41086a41023a000020054189026a41003a0000200541e9016a2001290000370000200541f1016a200141086a290000370000200541f9016a200141106a29000037000020054181026a200141186a2900003700002005410d3a00e00141b0b4cc004100200541e0016a10d401200041023a00000c010b024020042903084201520d00200441106a2903002107200441186a290300210641002104200541003a00d801200541083a00df01200520063703a0012005200737039801200520013602c80102400240200720068450450d0042002107420021060c010b200520013602e0022005200541e0026a3602f0012005200541df016a3602ec012005200541c8016a3602e8012005200541d8016a3602e401200520054198016a3602e001200541386a2001200541e0016a10dc0341012104024020052802384101470d0042002106200529034021070c010b200541e0006a2903002106200541d8006a29030021074100210420052903404201520d00200541386a41106a290300210820052802e002210320054198026a200541386a41186a29030037030020054190026a200837030041002104200541e0016a41086a41003a0000200541e9016a2003290000370000200541f1016a200341086a290000370000200541f9016a200341106a29000037000020054181026a200341186a290000370000200541033a00e00141b0b4cc004100200541e0016a10d4010b20040d00200541e0016a41186a22094200370300200541e0016a41106a22034200370300200541e0016a41086a220a4200370300200542003703e00141b6fdc600ad4280808080800184220f1001220b2900002108200541e0026a41086a2204200b41086a290000370300200520083703e002200b1035200a2004290300370300200520052903e0023703e00141e489c200ad4280808080d0018422101001220b29000021082004200b41086a290000370300200520083703e002200b1035200320052903e002220837030020054198016a41086a220b200a29030037030020054198016a41106a220c200837030020054198016a41186a220d2004290300370300200520052903e00137039801200541086a20054198016a412010d701200541086a41106a2903004200200528020822111b21082005290310420020111b210e024020072006844200520d002009420037030020034200370300200a4200370300200542003703e001200f1001221129000021072004201141086a290000370300200520073703e00220111035200a2004290300370300200520052903e0023703e00120101001221129000021072004201141086a290000370300200520073703e00220111035200320052903e002370000200341086a2004290300370000200b200a290300370300200c2003290300370300200d2009290300370300200520052903e00137039801200520083703e8012005200e3703e00120054198016aad4280808080800484200541e0016aad428080808080028410020c010b2009420037030020034200370300200a4200370300200542003703e001200f10012211290000210f2004201141086a2900003703002005200f3703e00220111035200a2004290300370300200520052903e0023703e001201010012211290000210f2004201141086a2900003703002005200f3703e00220111035200320052903e002370000200341086a2004290300370000200b200a290300370300200c2003290300370300200d2009290300370300200520052903e0013703980120054200200820067d200e200754ad7d2206200e20077d2207200e56200620085620062008511b22041b3703e80120054200200720041b3703e00120054198016aad4280808080800484200541e0016aad428080808080028410020b200541e0016a2002280210220a200241186a280200221210f4030240024020053502e80142208620052802e0012204ad8410212207422088a7220d0d00410121110c010b2007a721110b024020052802e401450d00200410350b200541003602e801200542013703e0012011200d200541e0016a1097030240024020052802e401220b20052802e80122096b4120490d00200941206a210420052802e0012103200b210c0c010b200941206a22042009490d02200b41017422032004200320044b1b220c4100480d0202400240200b0d000240200c0d00410121030c020b200c103322030d010c050b20052802e0012103200b200c460d002003200b200c10372203450d040b2005200c3602e401200520033602e0010b200320096a22092002412c6a220b290000370000200941186a200b41186a290000370000200941106a200b41106a290000370000200941086a200b41086a290000370000200520043602e80120054198016a41186a22092004ad4220862003ad841009220441186a29000037030020054198016a41106a220b200441106a29000037030020054198016a41086a2213200441086a2900003703002005200429000037039801200410350240200c450d00200310350b200541d1006a2009290300370000200541c9006a200b290300370000200541c1006a20132903003700002005200529039801370039200541013a0038200541e0016a200110f30320052802e0012104200520052802e8013602e402200520043602e002200541386a200541e0026a10f805024020052802e401450d00200410350b200541e0016a200a201210f40320053502e80142208620052802e0012204ad841011024020052802e401450d00200410350b200541e0016a41086a41023a000020054189026a41013a0000200541e9016a2001290000370000200541f1016a200141086a290000370000200541f9016a200141106a29000037000020054181026a200141186a2900003700002005410d3a00e00141b0b4cc004100200541e0016a10d4012000200541386a41d800109d081a200d450d00201110350b200241146a280200450d02200a10350c020b103e000b103c000b200541f0026a24000ba50503027f037e027f230041c0076b22022400024002402001450d00200220003602100c010b200241b0b4cc003602100b20022001360214200241e8036a200241106a10c80302400240024020022903d0044203510d00200241186a200241e8036a41c803109d081a200228021422014104490d0120022802102200280000210320022001417c6a3602142002200041046a360210200241e8036a200241186a41c803109d081a200241b0076a20024180056a220110d8032002200320022903b007220420022d00b9074200420010db0341082100200241086a29030021052002290300210620022d00b8072103200110ba02410810332201450d022001200437000002400240200341024d0d00410821030c010b024002400240024020030e03000102000b410021030c020b410121030c010b410221030b200220033a00e8034110210020014108411010372201450d03200120033a0008410921030b200341107221070240200020036b410f4b0d002000200041017422082007200820074b1b2208460d0020012000200810372201450d030b200120036a2200200537000820002006370000200241c0076a24002007ad4220862001ad840f0b200241bc076a41043602002002412c6a41023602002002420237021c200241f0b2c300360218200241043602b4072002419cb5c3003602b007200241003602e403200241b0b4cc003602e0032002200241b0076a3602282002200241e0036a3602b807200241186a4180b3c300104c000b200241bc076a4104360200200241fc036a4102360200200242023702ec03200241f0b2c3003602e803200241043602b4072002419cb5c3003602b007200241003602e403200241b0b4cc003602e0032002200241b0076a3602f8032002200241e0036a3602b807200241e8036a4180b3c300104c000b103c000bd30f04037f017e027f017e230041a0026b220224000240024020010d002002200136020c200241b0b4cc003602080c010b20022001417f6a36020c2002200041016a36020820002d0000220041014b0d004100210102400240024002400240024020000e020100010b2002200241086a10c40120022802000d05200228020c220320022802042200490d052000417f4c0d010240024020000d0041002103410121010c010b200010392201450d032001200228020822042000109d081a2002200320006b36020c2002200420006a360208200021030b2001450d052000ad4220862003ad8421050b410021030240024020010d00410021040c010b2005422088a72200417f4c0d010240024020000d0041002106410121040c010b200010332204450d03200021060b0240024020062000490d00200621070c010b200641017422072000200720004b1b22074100480d04024020060d002007103322040d010c060b20062007460d0020042006200710372204450d050b200420012000109d081a2005428080808070832007ad8421080b200220083702142002200436021020024190016a41e7e485f306200241106a10fa030240024020010d000c010b2005422088a72200417f4c0d010240024020000d0041002104410121030c010b200010332203450d03200021040b0240024020042000490d00200421060c010b200441017422062000200620004b1b22064100480d04024020040d00200610332203450d060c010b20042006460d0020032004200610372203450d050b200320012000109d081a2005428080808070832006ad8421080b2002200837021420022003360210200241b0016a41e2c289ab06200241106a10fb03410021030240024020010d00410021040c010b2005422088a72200417f4c0d010240024020000d0041002106410121040c010b200010332204450d03200021060b0240024020062000490d00200621070c010b200641017422072000200720004b1b22074100480d04024020060d00200710332204450d060c010b20062007460d0020042006200710372204450d050b200420012000109d081a2005428080808070832007ad8421080b2002200837021420022004360210200241d0016a41e9dabdf306200241106a10fb030240024020010d000c010b2005422088a72200417f4c0d010240024020000d0041002104410121030c010b200010332203450d03200021040b0240024020042000490d00200421060c010b200441017422062000200620004b1b22064100480d04024020040d00200610332203450d060c010b20042006460d0020032004200610372203450d050b200320012000109d081a2005428080808070832006ad8421080b20022008370294022002200336029002200241f0016a41e1ea91cb0620024190026a10fb03200241106a41086a220320024190016a41086a290300370300200241106a41106a220420024190016a41106a290300370300200241106a41186a220620024190016a41186a290300370300200241386a200241b0016a41086a290300370300200241c0006a200241b0016a41106a290300370300200241c8006a200241b0016a41186a290300370300200241d8006a200241d0016a41086a290300370300200241e0006a200241d0016a41106a290300370300200241e8006a200241d0016a41186a2903003703002002200229039001370310200220022903b001370330200220022903d00137035020024188016a200241f0016a41186a29030037030020024180016a200241f0016a41106a290300370300200241f8006a200241f0016a41086a290300370300200220022903f001370370412010332200450d0320002002290310370000200041186a2006290300370000200041106a2004290300370000200041086a20032903003700002000412041c00010372200450d032000200241106a41206a2203290000370020200041386a200341186a290000370000200041306a200341106a290000370000200041286a200341086a290000370000200041c00041800110372200450d032000200241106a41c0006a22032900003700402000200241f0006a2204290000370060200041d8006a200341186a290000370000200041d0006a200341106a290000370000200041c8006a200341086a290000370000200041e8006a200441086a290000370000200041f0006a200441106a290000370000200041f8006a200441186a29000037000002402001450d002005a7450d00200110350b41840110332201450d01200242840137021420022001360210418001200241106a10770240024020022802142206200228021822036b418001490d0020034180016a2104200228021021010c010b20034180016a22042003490d03200641017422012004200120044b1b22074100480d030240024020060d00024020070d00410121010c020b200710332201450d060c010b2002280210210120062007460d0020012006200710372201450d050b20022007360214200220013602100b200120036a2000418001109d081a20001035200241a0026a24002004ad4220862001ad840f0b1044000b1045000b103e000b103c000b200241fc016a4104360200200241246a410236020020024202370214200241f0b2c300360210200241043602f401200241b0b5c3003602f001200241003602d401200241b0b4cc003602d0012002200241f0016a3602202002200241d0016a3602f801200241106a4180b3c300104c000bfa0103037f037e037f230041306b220324002003200136020c200341106a200210e503200328021421042003410c6a200335021842208620032802102205ad84102e22012900002106200141086a2900002107200141106a2900002108200341106a41186a2209200141186a290000370300200341106a41106a220a2008370300200341106a41086a220b20073703002003200637031020011035200041186a2009290300370000200041106a200a290300370000200041086a200b2903003700002000200329031037000002402004450d00200510350b024020022802002200450d00200241046a280200450d00200010350b200341306a24000bfa0103037f037e037f230041306b220324002003200136020c200341106a200210e503200328021421042003410c6a200335021842208620032802102205ad84103022012900002106200141086a2900002107200141106a2900002108200341106a41186a2209200141186a290000370300200341106a41106a220a2008370300200341106a41086a220b20073703002003200637031020011035200041186a2009290300370000200041106a200a290300370000200041086a200b2903003700002000200329031037000002402004450d00200510350b024020022802002200450d00200241046a280200450d00200010350b200341306a24000bc50c03037f017e077f230041c0026b22022400024002402001450d00200220003602080c010b200241b0b4cc003602080b2002200136020c2002200241086a10c401024002400240024020022802000d00200228020c220320022802042201490d0002402001417f4c0d000240024020010d0041002103410121000c010b200110392200450d032000200228020822042001109d081a2002200320016b36020c2002200420016a360208200121030b2000450d0120022001ad4220862003ad8422054220883e029c02200220003602980220024190016a20024198026a10c2020240024020022d0090014101470d00410021060c010b200241106a20024190016a410172418001109d081a20024190016a200241106a418001109d081a200241003602a802200242043703a002412010332201450d032001200229039001370000200141186a20024190016a41186a290300370000200141106a20024190016a41106a290300370000200141086a20024190016a41086a290300370000200241a0026a41004101108c0120022802a002220620022802a80222044104746a220341e7e485f30636020c200342a08080808004370204200320013602002002200441016a22013602a802200241b0026a20024190016a41206a10fd030240200120022802a4022207470d00200241a0026a20014101108c0120022802a402210720022802a002210620022802a80221010b200620014104746a220320022903b002370200200341e2c289ab0636020c200341086a200241b0026a41086a2802003602002002200141016a22013602a802200241b0026a200241d0016a10fd03024020012007470d00200241a0026a20074101108c0120022802a402210720022802a002210620022802a80221010b200620014104746a220320022903b002370200200241b0026a41086a22042802002108200341e9dabdf30636020c200341086a20083602002002200141016a22013602a802200241b0026a200241f0016a10fd03024020012007470d00200241a0026a20074101108c0120022802a402210720022802a002210620022802a80221010b200620014104746a220320022903b00237020020042802002104200341e1ea91cb0636020c200341086a2004360200200141016a21090b02402005a7450d00200010350b0240024020060d00410121010c010b20094104744105722201417f4c0d010b200110332200450d022002410036029801200220013602940120022000360290010240024020060d00200041003a00004101210020024101360298010c010b200041013a00002002410136029801200920024190016a1077024020090d0020022802980121000c010b200620094104746a210a2006210103402001280200210b200141086a280200220020024190016a107702400240200228029401220c20022802980122086b2000490d002002280290012103200c21040c010b200820006a22032008490d06200c41017422042003200420034b1b22044100480d0602400240200c0d00024020040d00410121030c020b2004103322030d010c090b2002280290012103200c2004460d002003200c200410372203450d080b200220043602940120022003360290010b200320086a200b2000109d081a2002200820006a2200360298010240200420006b41034b0d00200041046a22082000490d062004410174220c2008200c20084b1b22084100480d060240024020040d00024020080d00410121030c020b200810332203450d090c010b20042008460d0020032004200810372203450d080b200220083602940120022003360290010b200320006a2001410c6a2800003600002002200041046a220036029801200141106a2201200a470d000b0b2000ad42208620023502900184210502402006450d0002402009450d00200941047421002006210103400240200141046a280200450d00200128020010350b200141106a2101200041706a22000d000b0b200741ffffffff0071450d00200610350b200241c0026a240020050f0b1044000b2002411c6a4104360200200241a4016a41023602002002420237029401200241f0b2c3003602900120024104360214200241d0b5c300360210200241003602b402200241b0b4cc003602b0022002200241106a3602a0012002200241b0026a36021820024190016a4180b3c300104c000b1045000b103e000b103c000b5f01017f02404120103322020d001045000b200042a080808080043702042000200236020020022001290000370000200241186a200141186a290000370000200241106a200141106a290000370000200241086a200141086a2900003700000bfc0403027f017e057f230041d0006b2202240041a9d1cb00ad4280808080c00084100122032900002104200241086a41086a200341086a290000370300200220043703082003103541fcd1cb00ad4280808080900284100122032900002104200241186a41086a200341086a2900003703002002200437031820031035200220013602342002200241346aad4280808080c000841003220329000037033820031035200241cc006a200241386a3602002002200241386a41086a3602442002200241346a3602482002200241386a360240200241286a200241c0006a107b02400240024002402002280230220541206a2206417f4c0d00200228022821070240024020060d0041002101410121030c010b200610332203450d02200621010b024002402001410f4d0d00200121080c010b200141017422084110200841104b1b22084100480d03024020010d002008103322030d010c050b20012008460d0020032001200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821010c010b200841017422014120200141204b1b22014100480d0320082001460d0020032008200110372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200141606a2005490d00200121080c010b200541206a22082005490d03200141017422092008200920084b1b22084100480d0320012008460d0020032001200810372203450d040b200341206a20072005109d081a2000200636020820002008360204200020033602000240200228022c450d00200710350b200241d0006a24000f0b1044000b1045000b103e000b103c000bca1d09017f017e047f017e027f037e057f047e017f230041c0046b2200240042002101200041f8016a41186a22024200370300200041f8016a41106a22034200370300200041f8016a41086a22044200370300200042003703f80141a9d1cb00ad4280808080c000841001220529000021062004200541086a290000370300200020063703f8012005103541cde4cb00ad4280808080b00184100122052900002106200041d8036a41086a2207200541086a290000370300200020063703d80320051035200320002903d803220637030020004198046a41086a200429030037030020004198046a41106a200637030020004198046a41186a2007290300370300200020002903f80137039804200041f8016a20004198046a10b70202400240024020002d00f8014102470d00200242003703002003420037030020044200370300200042003703f80141d1c4c700ad4280808080e000841001220529000021062004200541086a290000370300200020063703f801200510354185c5c700ad4280808080e0008410012205290000210620004190016a41086a2207200541086a29000037030020002006370390012005103520032000290390012206370300200041f0026a41086a2004290300370300200041f0026a41106a2006370300200041f0026a41186a2007290300370300200020002903f8013703f002200041f8016a200041f0026a10ce020240024020002802f80122080d0041042108410021040c010b20002902fc012201422088a721040b02400240200441246c2205450d002008210402400340024020042d00004101470d00200441016a2800002107200441086a28020021022000200441106a2802003602f402200020023602f002200741c28289aa04470d00200041f8016a200041f0026a10800420002903f80122064203520d020b200441246a21042005415c6a2205450d020c000b0b2000290380022109200041286a20004188026a41e800109d081a0c010b420321060b02402001422088a72204450d00200441246c21052008210403400240024020042d0000220741044b0d0002400240024020070e050400010204040b2004410c6a280200450d03200441086a28020010350c030b2004410c6a280200450d02200441086a28020010350c020b2004410c6a280200450d01200441086a28020010350c010b200441086a280200450d00200441046a28020010350b200441246a21042005415c6a22050d000b0b02402001a72204450d00200441246c450d00200810350b20004190016a200041286a41e800109d081a0240024020064203520d004100210720004198046a21080c010b200041f0026a20004190016a41e800109d081a200041f8016a41186a22054200370300200041f8016a41106a22074200370300200041f8016a41086a22044200370300200042003703f80141a9d1cb00ad4280808080c00084220a1001220229000021012004200241086a290000370300200020013703f8012002103541c2d1cb00ad4280808080b00184220b100122082900002101200041d8036a41086a2202200841086a290000370300200020013703d80320081035200320002903d803370000200341086a220c200229030037000020004198046a41086a2208200429030037030020004198046a41106a220d200729030037030020004198046a41186a220e2005290300370300200020002903f80137039804200041186a20004198046a10e102024002402000280218450d002000290320500d0020004198046aad4280808080800484210120004198046a21080c010b200542003703002007420037030020044200370300200042003703f801200a1001220f29000021012004200f41086a290000370300200020013703f801200f1035200b1001220f29000021012002200f41086a290000370300200020013703d803200f1035200320002903d803370000200c200229030037000020082004290300370300200d2007290300370300200e2005290300370300200020002903f80137039804200020093703f80120004198046aad42808080808004842201200041f8016aad42808080808001841002200542003703002007420037030020044200370300200042003703f801200a1001220f290000210b2004200f41086a2900003703002000200b3703f801200f103541b7d1cb00ad4280808080b001841001220f290000210b2002200f41086a2900003703002000200b3703d803200f1035200320002903d803370000200c200229030037000020082004290300370300200d2007290300370300200e2005290300370300200020002903f80137039804200041f8016a20004198046a10dd0220002802f801210f20002902fc01210b200542003703002007420037030020044200370300200042003703f801200a10012210290000210a2004201041086a2900003703002000200a3703f8012010103541d8d1cb00ad4280808080a0018410012210290000210a2002201041086a2900003703002000200a3703d80320101035200320002903d803370000200c200229030037000020082004290300370300200d2007290300370300200e2005290300370300200020002903f80137039804200041f8016a20004198046a10b10220002d00f8012105200e20004191026a290000370300200d20004189026a290000370300200820004181026a290000370300200020002900f90137039804200b4200200f1b210a200b428080808070834200200f1b210b200f4108200f1b21040240024020054101460d0020004190046a420037030020004188046a420037030020004180046a4200370300200042003703f8030c010b200041f8036a41186a20004198046a41186a290300370300200041f8036a41106a20004198046a41106a290300370300200041f8036a41086a20004198046a41086a29030037030020002000290398043703f8030b200041d8036a41086a200041f8036a41086a2903002211370300200041d8036a41106a200041f8036a41106a2903002212370300200041d8036a41186a200041f8036a41186a2903002213370300200020002903f80322143703d803200041f8016a41086a200b200a42ffffffff0f8384370300200041f8016a41106a2014370300200041f8016a41186a201137030020004198026a2012370300200041f8016a41286a2013370300200020043602fc01200041003602f80120004198046a200041f8016a10810420004183046a20004198046a41086a28020036000020002000290398043700fb03200041a4046a200041ff036a290000370000200041c28289aa0436009904200041023a009804200020002900f80337009d0420004198046a1082040240200aa72205450d00200541286c450d00200410350b20004198046a21080b200041f8016a41186a22054200370300200041f8016a41106a22074200370300200041f8016a41086a22044200370300200042003703f80141a9d1cb00ad4280808080c00084220a10012202290000210b2004200241086a2900003703002000200b3703f8012002103541cdd1cb00ad4280808080b00184220b1001220d2900002111200041d8036a41086a2202200d41086a290000370300200020113703d803200d1035200320002903d803370000200341086a220d200229030037000020004198046a41086a220e200429030037030020004198046a41106a220c200729030037030020004198046a41186a220f2005290300370300200020002903f80137039804200041086a20004198046a10e1022000280208211520002903102111200542003703002007420037030020044200370300200042003703f801200a1001221029000021122004201041086a290000370300200020123703f801201010354199c2c300ad42808080808001841001221029000021122002201041086a290000370300200020123703d80320101035200320002903d803370000200d2002290300370000200e2004290300370300200c2007290300370300200f2005290300370300200020002903f80137039804200042002009201142017c420120151b7d221120112009561b3e02f8012001200041f8016aad22114280808080c000841002200542003703002007420037030020044200370300200042003703f801200a10012210290000210a2004201041086a2900003703002000200a3703f80120101035200b10012210290000210a2002201041086a2900003703002000200a3703d80320101035200320002903d803370000200d2002290300370000200e2004290300370300200c2007290300370300200f2005290300370300200020002903f80137039804200020093703f80120012011428080808080018410024100210720064200520d00200041f8016a200041f0026a41e800109d081a200041f8036a41186a20004194026a290200370300200041f8036a41106a2000418c026a290200370300200041f8036a41086a20004184026a290200370300200020002902fc013703f803410121070b200041f0026a41186a200041f8036a41186a290300370300200041f0026a41106a200041f8036a41106a290300370300200041f0026a41086a200041f8036a41086a290300370300200020002903f8033703f002200041f8016a41186a22024200370300200041f8016a41106a220d4200370300200041f8016a41086a22044200370300200042003703f80141a9d1cb00ad4280808080c000841001220529000021062004200541086a290000370300200020063703f8012005103541cde4cb00ad4280808080b00184100122052900002106200041d8036a41086a220e200541086a290000370300200020063703d80320051035200320002903d803370000200341086a200e29030037000020004198046a41086a200429030037030020004198046a41106a200d29030037030020004198046a41186a2002290300370300200020002903f80137039804410110332204450d010240024020070d00200441003a000042808080801021060c010b200441013a000020044101412110372204450d03200420002903f002370001200441196a20004188036a290300370000200441116a20004180036a290300370000200441096a200041f8026a2903003700004280808080900421060b2008ad428080808080048420062004ad841002200410350b200041c0046a24000f0b1045000b103c000ba71405067f017e027f057e047f23004190036b22022400024002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a22063602042001200441016a3602002005417f6a220541024b0d0420050e03010203010b200042033703000c050b024020064104490d002004280001210720012003417b6a22053602042001200441056a36020020054108490d00200429000521082001200341736a36020420012004410d6a36020041002105200241003a0028410d20036b2109200341726a2106024002400340200920056a450d01200241086a20056a200420056a220a410d6a2d00003a0000200120063602042001200a410e6a3602002002200541016a220a3a00282006417f6a2106200a2105200a4120470d000b200241b0026a41086a200241086a41086a290300370300200241b0026a41106a200241086a41106a290300370300200241b0026a41186a200241086a41186a290300370300200220022903083703b00241002105200241003a00482004200a6a2109200a20036b410d6a21030340200320056a450d02200241086a20056a200920056a2204410d6a2d00003a00002001200636020420012004410e6a3602002002200541016a22043a00482006417f6a210620042105200441c000470d000b200241d0026a41386a200241086a41386a290300220b370300200241d0026a41306a200241086a41306a290300220c370300200241d0026a41286a200241086a41286a290300220d370300200241d0026a41206a200241086a41206a290300220e370300200241d0026a41186a200241086a41186a290300220f370300200241d0016a41086a2201200241086a41086a290300370300200241d0016a41106a2204200241086a41106a290300370300200241d0016a41186a2205200f370300200241d0016a41206a2206200e370300200241d0016a41286a2203200d370300200241d0016a41306a220a200c370300200241d0016a41386a2209200b370300200220022903083703d00120024190026a41186a2210200241b0026a41186a29030037030020024190026a41106a2211200241b0026a41106a29030037030020024190026a41086a2212200241b0026a41086a290300370300200220022903b00237039002200241b0016a41186a22132010290300370300200241b0016a41106a22102011290300370300200241b0016a41086a2211201229030037030020022002290390023703b001200241f0006a41386a22122009290300370300200241f0006a41306a2209200a290300370300200241f0006a41286a220a2003290300370300200241f0006a41206a22032006290300370300200241f0006a41186a22062005290300370300200241f0006a41106a22052004290300370300200241f0006a41086a22042001290300370300200220022903d001370370200041106a20073602002000200837030820004200370300200020022903b0013702142000411c6a2011290300370200200041246a20102903003702002000412c6a2013290300370200200020022903703702342000413c6a2004290300370200200041c4006a2005290300370200200041cc006a2006290300370200200041d4006a2003290300370200200041dc006a200a290300370200200041e4006a2009290300370200200041ec006a20122903003702000c070b200541ff0171450d01200241003a00280c010b200541ff0171450d00200241003a00480b200042033703000c040b024020064104490d002004280001210620012003417b6a22053602042001200441056a36020020054108490d0020004201370300200429000521082001200341736a36020420012004410d6a360200200041106a200636020020002008370308200041146a200241086a41e400109d081a0c040b200042033703000c030b20064104490d012004280001210720012003417b6a22053602042001200441056a36020020054108490d01200429000521082001200341736a36020420012004410d6a36020041002105200241003a0028410d20036b2109200341726a2106024002400340200920056a450d01200241086a20056a200420056a220a410d6a2d00003a0000200120063602042001200a410e6a3602002002200541016a220a3a00282006417f6a2106200a2105200a4120470d000b200241b0026a41086a200241086a41086a290300370300200241b0026a41106a200241086a41106a290300370300200241b0026a41186a200241086a41186a290300370300200220022903083703b00241002105200241003a00482004200a6a2109200a20036b410d6a21030340200320056a450d02200241086a20056a200920056a2204410d6a2d00003a00002001200636020420012004410e6a3602002002200541016a22043a00482006417f6a210620042105200441c000470d000b200241d0026a41386a200241086a41386a290300220b370300200241d0026a41306a200241086a41306a290300220c370300200241d0026a41286a200241086a41286a290300220d370300200241d0026a41206a200241086a41206a290300220e370300200241d0026a41186a200241086a41186a290300220f370300200241d0016a41086a2201200241086a41086a290300370300200241d0016a41106a2204200241086a41106a290300370300200241d0016a41186a2205200f370300200241d0016a41206a2206200e370300200241d0016a41286a2203200d370300200241d0016a41306a220a200c370300200241d0016a41386a2209200b370300200220022903083703d00120024190026a41186a2210200241b0026a41186a29030037030020024190026a41106a2211200241b0026a41106a29030037030020024190026a41086a2212200241b0026a41086a290300370300200220022903b00237039002200241b0016a41186a22132010290300370300200241b0016a41106a22102011290300370300200241b0016a41086a2211201229030037030020022002290390023703b001200241f0006a41386a22122009290300370300200241f0006a41306a2209200a290300370300200241f0006a41286a220a2003290300370300200241f0006a41206a22032006290300370300200241f0006a41186a22062005290300370300200241f0006a41106a22052004290300370300200241f0006a41086a22042001290300370300200220022903d001370370200041106a20073602002000200837030820004202370300200020022903b0013702142000411c6a2011290300370200200041246a20102903003702002000412c6a2013290300370200200020022903703702342000413c6a2004290300370200200041c4006a2005290300370200200041cc006a2006290300370200200041d4006a2003290300370200200041dc006a200a290300370200200041e4006a2009290300370200200041ec006a20122903003702000c040b200541ff0171450d02200241003a00280c020b200541ff0171450d01200241003a00480c010b200042033703000c010b200042033703000b20024190036a24000bd90a02087f017e230041106b220224002002410036020820024201370300024002402001280200220341024b0d0002400240024002400240024020030e03000102000b410110332203450d062002410136020420022003360200200341013a000020024101360208200128020421032001410c6a2802002204200210770240024020040d00200228020821050c010b2003200441286c6a2106200228020821050340024002402002280204220720056b4120490d00200541206a210420022802002108200721090c010b200541206a22042005490d05200741017422082004200820044b1b22094100480d050240024020070d00024020090d00410121080c020b2009103322080d010c0b0b2002280200210820072009460d0020082007200910372208450d0a0b20022009360204200220083602000b200820056a22052003290000370000200541186a200341186a290000370000200541106a200341106a290000370000200541086a200341086a29000037000020022004360208200341206a290300210a0240200920046b41074b0d00200441086a22052004490d05200941017422072005200720054b1b22054100480d050240024020090d00024020050d00410121080c020b200510332208450d0b0c010b20092005460d0020082009200510372208450d0a0b20022005360204200220083602000b200820046a200a3700002002200441086a22053602082006200341286a2203470d000b0b024002402002280204220420056b4120490d00200228020021030c010b200541206a22032005490d03200441017422082003200820034b1b22084100480d030240024020040d00024020080d00410121030c020b200810332203450d090c010b2002280200210320042008460d0020032004200810372203450d080b20022008360204200220033602000b200320056a2203200141106a2204290000370000200341186a200441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002002200541206a3602080c050b410110332203450d052002410136020420022003360200200341023a000020024101360208200128020421080240024020022802042204417f6a4104490d00200228020021030c010b200441017422034105200341054b1b22054100480d0220022802002103024020042005460d0020032004200510372203450d070b20022005360204200220033602000b20032008360001200241053602080c040b410110332203450d042002410136020420022003360200200341033a00002002410136020820022802002103024020022802044101470d0020034101410210372203450d0520024102360204200220033602000b200341013a0001200241023602082001290308210a0240024020022802042204417e6a4108490d00200228020021030c010b20044101742203410a2003410a4b1b22084100480d0120022802002103024020042008460d0020032004200810372203450d060b20022008360204200220033602000b2003200a3700022002410a3602082001290310210a2002280204220441766a41074b0d01200441017422034112200341124b1b22084100480d0020022802002103024020042008460d0020032004200810372203450d050b2003200a37000a200220083602042002200336020020024112360208200141186a2d000021080c020b103e000b20022802002203200a37000a20024112360208200141186a2d0000210820044112470d0020034112412410372203450d0220024124360204200220033602000b200320083a0012200241133602080b20002002290300370200200041086a200241086a280200360200200241106a24000f0b103c000bd00703047f017e057f230041f0006b22012400200141c8006a41186a4200370300200141c8006a41106a22024200370300200141c8006a41086a220342003703002001420037034841d1c4c700ad4280808080e000841001220429000021052003200441086a29000037030020012005370348200410354185c5c700ad4280808080e00084100122042900002105200141386a41086a2206200441086a2900003703002001200537033820041035200220012903382205370300200141186a41086a2003290300370300200141186a41106a2005370300200141186a41186a200629030037030020012001290348370318200141c8006a200141186a10ce0202400240200128024822020d0041002106200141003602102001420437030841042102410021030c010b2001200129024c220537020c200120023602082005422088a721032005a721060b200141c8006a41206a2207200041206a280200360200200141c8006a41186a2208200041186a290200370300200141c8006a41106a2209200041106a290200370300200141c8006a41086a2204200041086a29020037030020012000290200370348024020032006470d00200141086a20034101108d01200128020c210620012802082102200128021021030b2002200341246c220a6a22002001290348370200200041206a2007280200360200200041186a2008290300370200200041106a2009290300370200200041086a20042903003702002001200341016a22003602102008420037030020094200370300200442003703002001420037034841d1c4c700ad4280808080e000841001220829000021052004200841086a29000037030020012005370348200810354185c5c700ad4280808080e00084100122082900002105200141386a41086a2207200841086a2900003703002001200537033820081035200920012903382205370300200141186a41086a2004290300370300200141186a41106a2005370300200141186a41186a2007290300370300200120012903483703182001412036024c2001200141186a36024820022000200141c8006a109606024020002003490d00200a41246a21032002210003400240024020002d0000220441044b0d0002400240024020040e050400010204040b2000410c6a280200450d03200041086a28020010350c030b2000410c6a280200450d02200041086a28020010350c020b2000410c6a280200450d01200041086a28020010350c010b200041086a280200450d00200041046a28020010350b200041246a21002003415c6a22030d000b0b02402006450d00200641246c450d00200210350b200141f0006a24000b7402027f027e230041e0006b22032400200341d0006a2002108e022003200328025022042003280258108f02200341106a2903004200200329030042015122021b21052003290308420020021b210602402003280254450d00200410350b2000200637030020002005370308200341e0006a24000bca0102017f037e230041306b220524000240024020030d00200041003602000c010b20052003280200200328020810f4032004ad4280808080800484100922032900002106200341086a2900002107200341106a2900002108200541106a41186a200341186a290000370300200541106a41106a2008370300200541106a41086a200737030020052006370310200310352000200535020842208620052802002203ad84200541106aad4280808080800484101010c2012005280204450d00200310350b200541306a24000b8505010a7f230041e0016b2203240020034198016a200210f303200341c0006a200328029801220420032802a00110d902200341a8016a41086a2205200341c0006a41286a290300370300200341a8016a41106a2206200341c0006a41306a290300370300200341a8016a41186a2207200341f8006a290300370300200341a8016a41206a220820034180016a290300370300200341a8016a41286a220920034188016a290300370300200341a8016a41306a220a20034190016a2802003602002003200341c0006a41206a2903003703a801200341dc006a280200210b200341c0006a41186a280200210c024020032d004022024102460d00200341086a41306a200a280200360200200341086a41286a2009290300370300200341086a41206a2008290300370300200341086a41186a2007290300370300200341086a41106a2006290300370300200341086a41086a2005290300370300200320032903a8013703080b0240200328029c01450d00200410350b0240024020024102470d00200041003a00000c010b200341c0006a41306a200341086a41306a280200360200200341c0006a41286a200341086a41286a290300370300200341c0006a41206a200341086a41206a290300370300200341c0006a41186a200341086a41186a290300370300200341c0006a41106a200341086a41106a290300370300200341c0006a41086a200341086a41086a2903003703002003200329030837034002402002450d00200041003a00000c010b20002003290254370001200041013a0000200041196a200341ec006a290200370000200041116a200341e4006a290200370000200041096a200341dc006a290200370000200b450d00200c10350b200341e0016a24000b5601027f230041206b22022400200241106a200110f303200241086a20022802102203200228021841b0b4cc0041004100108a022002280208210102402002280214450d00200310350b200241206a240020014101460bbc0104027f027e027f017e230041f0006b22032400200341e0006a200210f303200341086a20032802602204200328026810d902200341186a2903002105200341106a2903002106200341246a2802002107200341206a280200210820032d0008210202402003280264450d00200410350b420021090240200241ff017122044102460d00200445ad21092007450d00200241ff01710d00200810350b2000200637030820002009370300200041106a2005370300200341f0006a24000b971009037f027e027f077e047f057e017f067e047f230041d0036b2204240020032802002105200441206a2001108e02200441a0016a2004280220220320042802282206108f0220042903a001210742002108200442003703a001200441e8016a280200210920042d00ec01210a0240024020074201510d00200441306a41306a4200370300200441306a41286a4200370300200441306a41206a4200370300200441306a41186a4200370300200441c0006a4200370300200441386a4200370300200442003703304200210b4200210c4200210d4200210e0c010b200441d8016a290300210f200441a0016a41306a2903002110200441a0016a41206a290300210b200441a0016a41186a2903002108200441e0016a290300210e20042903b001210d20042903a801210c200441306a41206a200441a0016a41286a290300370300200441306a41286a2010370300200441306a41306a200f370300200441c0006a20083703002004200b3703482004200c3703302004200d3703380b427f200d200b7c200c20087c2211200c542212ad7c220f2012200f200d54200f200d511b22121b2110427f201120121b2111024002400240427f2002290300220f20087c22082008200f542212200241086a2903002208200b7c2012ad7c220b200854200b2008511b22021b42ffffe883b1de1656427f200b20021b220b420052200b501b0d002011201084500d010b2004200f37033020042008370338200441e8006a41186a200441306a41186a290300220b370300200441e8006a41206a2213200441306a41206a290300370300200441e8006a41286a2214200441306a41286a290300370300200441e8006a41306a2215200441306a41306a290300370300200420083703702004200f370368200420042903402216370378200c200f56200d200856200d2008511b21022008200d7d200f200c54ad7d2117200d20087d200c200f54ad7d2118200f200c7d2119200c200f7d211a201120108450211b02400240427f200f20167c220d200d200f5422122008200b7c2012ad7c220d200854200d2008511b22121b220c428080e983b1de16544100427f200d20121b220d501b0d00200441f8006a29030021162015290300211c2014290300211d2013290300211e2004290370211f200429036821204201211120042903800121210c010b02400240200c200d8450450d00420021110c010b42002111200441a0026a41186a22224200370300200441a0026a41106a22144200370300200441a0026a41086a22134200370300200442003703a00241b6fdc600ad4280808080800184220b100122152900002110200441c0036a41086a2212201541086a290000370300200420103703c0032015103520132012290300370300200420042903c0033703a00241e489c200ad4280808080d0018422101001221529000021162012201541086a290000370300200420163703c00320151035201420042903c0032216370300200441a0036a41086a22232013290300370300200441a0036a41106a22242016370300200441a0036a41186a22252012290300370300200420042903a0023703a003200441086a200441a0036a412010d701200441086a41106a29030021162004290310211c20042802082115202242003703002014420037030020134200370300200442003703a002200b10012222290000210b2012202241086a2900003703002004200b3703c0032022103520132012290300370300200420042903c0033703a002201010012222290000210b2012202241086a2900003703002004200b3703c00320221035201420042903c003220b370300202320132903003703002024200b37030020252012290300370300200420042903a0023703a003200442002016420020151b220b200d7d201c420020151b2210200c54ad7d22162010200c7d221c2010562016200b562016200b511b22121b3703a80220044200201c20121b3703a002200441a0036aad4280808080800484200441a0026aad42808080808002841002200441d8026a200d370300200441d0026a200c370300201341013a0000200441a9026a2005290000370000200441b1026a200541086a290000370000200441b9026a200541106a290000370000200441c1026a200541186a290000370000200441033a00a00241b0b4cc004100200441a0026a10d4010b0b2018201720021b210c201a201920021b210b2002ad2110201bad210d200441c8016a201e370300200441d0016a201d370300200441b0016a201f370300200441d8016a201c370300200441b8016a2016370300200420213703c0012004200e3703e001200420203703a801410021022004200a4100200742015122121b3a00ec0120042009410020121b3602e801200420114201512212ad3703a001024020120d002006ad4220862003ad8410070c020b200420063602a402200420033602a002200441a8016a200441a0026a10e702410121020c010b4202210d0b02402004280224450d00200310350b02400240200d4202520d00200042023703000c010b02400240024020074201510d00200241ff0171450d0041032103200441a0026a21020c010b20074201520d01200241ff01710d0141042103200441a0016a21020b200241086a20033a0000200241003a0000200241096a2001290000370000200241116a200141086a290000370000200241196a200141106a290000370000200241216a200141186a29000037000041b0b4cc004100200210d4010b2000200f3703082000200d370300200041286a200c370300200041206a200b370300200041106a2008370300200041186a20103703000b200441d0036a24000b9c0607047f017e017f017e017f017e047f230041e0006b22022400200241306a41186a22034200370300200241306a41106a22044200370300200241306a41086a220542003703002002420037033041f1d8cb00ad42808080809001842206100122072900002108200241d0006a41086a2209200741086a2900003703002002200837035020071035200520092903003703002002200229035037033041fad8cb00ad4280808080e00184220810012207290000210a2009200741086a2900003703002002200a3703502007103520042002290350220a370300200241106a41086a220b2005290300370300200241106a41106a220c200a370300200241106a41186a220d2009290300370300200220022903303703102002200241106a10e1022002280200210e2002290308210a2003420037030020044200370300200542003703002002420037033020061001220729000021062009200741086a2900003703002002200637035020071035200520092903003703002002200229035037033020081001220729000021062009200741086a2900003703002002200637035020071035200420022903502206370300200b2005290300370300200c2006370300200d2009290300370300200220022903303703102002200a42017c4201200e1b2206370330200241106aad4280808080800484200241306aad4280808080800184100202400240412010332209450d0020092001290000370000200941186a200141186a290000370000200941106a200141106a290000370000200941086a200141086a2900003700002009412041c00010372205450d0020052006370020200241306a41186a22012005ad42808080808005841009220941186a290000370300200241306a41106a2204200941106a290000370300200241306a41086a2207200941086a2900003703002002200929000037033020091035412010332209450d0120092002290330370000200042a0808080800437020420002009360200200941186a2001290300370000200941106a2004290300370000200941086a200729030037000020051035200241e0006a24000f0b103c000b1045000bf10203037f017e037f230041106b22022400200241003602082002420137030020002d00002103410110332104024002400240024020034101460d002004450d02200441003a0000200220043602002002428180808010370204200041086a200210f705200235020842208621052002280204452104200228020021000c010b2004450d01200441013a0000200220043602002002428180808010370204412010332203450d0220032000290001370000200341186a2206200041196a290000370000200341106a2207200041116a290000370000200341086a2208200041096a29000037000020044101412110372200450d0120002003290000370001200041096a2008290000370000200041116a2007290000370000200041196a200629000037000020022000360200200242a1808080900437020420031035410021044280808080900421050b200129020020052000ad841002024020040d00200010350b200241106a24000f0b103c000b1045000b3400200041a9d1cb0036020420004100360200200041146a410a360200200041106a41d4c2c300360200200041086a42043702000b910101057f230041206b22022400200241186a22034200370300200241106a22044200370300200241086a220542003703002002420037030002404120103322060d001045000b20062002290300370000200042a0808080800437020420002006360200200641186a2003290300370000200641106a2004290300370000200641086a2005290300370000200241206a24000b130020004102360204200041c8d7c3003602000b2d01017f02404108103322020d001045000b20004288808080800137020420002002360200200242b8173700000b2d01017f02404108103322020d001045000b20004288808080800137020420002002360200200242c8013700000bee0202097f027e230041206b220324000240200128020041016a220441004c0d00200120043602000240024020012802042205450d00200141086a28020021060340200541086a210720052f0106220841057421094100210a0240024003402009450d0120022007412010a008220b450d02200941606a2109200a41016a210a200741206a2107200b417f4a0d000b200a417f6a21080b2006450d022006417f6a2106200520084102746a41880b6a28020021050c010b0b2005200a41e0006c6a220941c5036a310000200941e8026a290300220c200c5022071ba7450d004200200941f8026a29030020071b210c4200200941f0026a29030020071b210d0c010b200341086a20012802102002200141146a28020028021c110400200341106a290300210c200128020021042003290308210d0b20012004417f6a3602002000200c3703082000200d370300200341206a24000f0b41ac96cc004118200341186a41d8c1c30041d496cc001046000ba60502097f017e230041106b220524000240024002400240024002400240024002400240200128020041016a220641004c0d002001200636020020012802042207450d07200141086a28020021080340200741086a210920072f0106220a41057421064100210b0240024003402006450d0120022009412010a008220c450d02200641606a2106200b41016a210b200941206a2109200c417f4a0d000b200b417f6a210a0b2008450d092008417f6a21082007200a4102746a41880b6a28020021070c010b0b2007200b41e0006c6a220d4198036a22062802002207450d05200628020421080340200741086a210920072f0106220a41057421064100210b0240024003402006450d0120042009412010a008220c450d02200641606a2106200b41016a210b200941206a2109200c417f4a0d000b200b417f6a210a0b2008450d072008417f6a21082007200a4102746a41ec036a28020021070c010b0b0240200741e8026a200b410c6c6a220628020022070d0041012109410021060c070b20062802082209417f4c0d010240024020090d004100210b410121060c010b200910332206450d032009210b0b02400240200b2009490d00200b210c0c010b200b410174220c2009200c20094b1b220c4100480d040240200b0d00200c103322060d010c060b200b200c460d002006200b200c10372206450d050b200620072009109d081a2009ad422086200cad84210e410121090c060b41ac96cc004118200541086a41d8c1c30041d496cc001046000b1044000b1045000b103e000b103c000b410021090b0240200d41e8026a2d005d450d002006410020091b21060c020b20090d010b20002001280210200220032004200141146a28020028020c1105000c010b2000200e370204200020063602000b20012001280200417f6a360200200541106a24000bd10401097f230041c0006b220324000240200128020041016a220441004c0d002001200436020002400240024020012802042205450d00200141086a28020021060340200541086a210720052f0106220841057421094100210a0240024003402009450d0120022007412010a008220b450d02200941606a2109200a41016a210a200741206a2107200b417f4a0d000b200a417f6a21080b2006450d022006417f6a2106200520084102746a41880b6a28020021050c010b0b2005200a41e0006c6a220741e8026a210902400240200741c5036a2d00000d00200341206a41086a220a200941c5006a290000370300200341206a41106a220b200941cd006a290000370300200341206a41186a2205200941d5006a29000037030020032009413d6a2900003703204102210720092d003c4101470d01200341186a2005290300370300200341106a200b290300370300200341086a200a29030037030020032003290320370300410121070c010b200341086a200941c5006a290000370300200341106a200941cd006a290000370300200341186a200941d5006a29000037030020032009413d6a29000037030020092d003c21070b200741ff01714102470d010b200020012802102002200141146a280200280210110400200128020021040c010b200020073a000020002003290300370001200041096a200341086a290300370000200041116a200341106a290300370000200041196a200341186a2903003700000b20012004417f6a360200200341c0006a24000f0b41ac96cc004118200341206a41d8c1c30041d496cc001046000bbe0201097f230041106b220224000240200028020041016a220341004c0d002000200336020002400240024020002802042204450d00200041086a28020021050340200441086a210620042f010622074105742108410021090240024003402008450d0120012006412010a008220a450d02200841606a2108200941016a2109200641206a2106200a417f4a0d000b2009417f6a21070b2005450d022005417f6a2105200420074102746a41880b6a28020021040c010b0b2004200941e0006c6a220841a4036a2d000022064101410220064101461b200841c5036a2d00001b22084102470d010b20002802102001200041146a2802002802181101002108200028020021030c010b200841004721080b20002003417f6a360200200241106a240020080f0b41ac96cc004118200241086a41d8c1c30041d496cc001046000b820302097f037e230041206b220324000240200128020041016a220441004c0d00200120043602000240024020012802042205450d00200141086a28020021060340200541086a210720052f0106220841057421094100210a0240024003402009450d0120022007412010a008220b450d02200941606a2109200a41016a210a200741206a2107200b417f4a0d000b200a417f6a21080b2006450d022006417f6a2106200520084102746a41880b6a28020021050c010b0b2005200a41e0006c6a22094190036a290300210c20094188036a290300210d20094180036a290300210e0240200941c5036a2d00000d00200ea721094201210e2009450d010c020b200e4202520d010b200320012802102002200141146a280200280214110400200341106a290300210c200128020021042003290308210d2003290300210e0b20012004417f6a360200200041106a200c3703002000200d3703082000200e370300200341206a24000f0b41ac96cc004118200341186a41d8c1c30041d496cc001046000bc82107067f017e067f057e107f047e027f230041f00c6b220224000240024002400240024020002802000d002000417f36020002400240200128020022030d004100210141002103410021040c010b2001280208210402400240200128020422050d00200321010c010b2005210120032106034020062802880b21062001417f6a22010d000b200321010340200120012f01064102746a41880b6a28020021012005417f6a22050d000b200621030b20012f010621050b2002411c6a2005360200200241186a4100360200200241146a2001360200200220043602202002410036021020024200370308200220033602042002410036020002402004450d0020022004417f6a3602202003450d020240024020032f0106450d004100210741002106410021050c010b4100210641002105034002400240200328020022010d002005ad2108410021010c010b200641016a210620033301044220862005ad8421080b200310352008a72105200121032008422088a7220720012f01064f0d000b200121030b200241d00c6a41186a2209200320074105746a220141206a290000370300200241d00c6a41106a220a200141186a290000370300200241d00c6a41086a220b200141106a2900003703002002200141086a2900003703d00c2003200741e0006c6a220441a4036a2d0000210c200441a0036a280200210d2004419c036a280200210e20044198036a280200210120044190036a290300210f20044188036a290300211020044180036a2903002111200441f8026a2903002112200441f0026a2903002113200441e8026a2903002108200241d0016a41186a2214200441bd036a290000370300200241d0016a41106a2215200441b5036a290000370300200241d0016a41086a2216200441ad036a2900003703002002200441a5036a2900003703d001200741016a2107200441c6036a2f01002117200441c5036a2d0000211802402006450d00200320074102746a41880b6a2802002103410021072006417f6a2206450d00034020032802880b21032006417f6a22060d000b0b200241f0096a41186a2009290300370300200241f0096a41106a200a290300370300200241f0096a41086a200b29030037030020024188016a41086a201629030037030020024188016a41106a201529030037030020024188016a41186a2014290300370300200220022903d00c3703f009200220022903d001370388012002200736020c20022005360208200220033602042002410036020020084202510d002000410c6a2119200041046a211a200241d0016a41206a2107200241840a6a211b200241d0016a413d6a211c200241d0016a41286a211d0340200241c8006a41186a2203200241f0096a41186a2209290300370300200241c8006a41106a2205200241f0096a41106a220a290300370300200241c8006a41086a2206200241f0096a41086a220b290300370300200241286a41086a220420024188016a41086a221e290300370300200241286a41106a221420024188016a41106a221f290300370300200241286a41186a221520024188016a41186a2220290300370300200220022903f0093703482002200229038801370328200241e8006a41186a22212015290300370300200241e8006a41106a22222014290300370300200241e8006a41086a222320042903003703002002200229032837036820202003290300370300201f2005290300370300201e2006290300370300200220022903483703880102400240201a2802002214450d00200028020821150c010b200241f0096a410041e002109f081a200241d0016a410041a008109f081a41880b10332214450d0541002115201441003b010620144100360200201441086a200241f0096a41e002109d081a201441e8026a200241d0016a41a008109d081a20004100360208200020143602040b024002400340201441086a210520142f01062216410574210341002106024003402003450d0120024188016a2005412010a0082204450d03200341606a2103200641016a2106200541206a21052004417f4a0d000b2006417f6a21160b02402015450d002015417f6a2115201420164102746a41880b6a28020021140c010b0b200241d00c6a41186a20202903002224370300200241d00c6a41106a201f2903002225370300200241d00c6a41086a201e2903002226370300200220022903880122273703d00c201b2027370200201b41086a2026370200201b41106a2025370200201b41186a2024370200200220193602800a200220163602fc092002201a3602f809200220143602f409200241003602f009201d200f370300200241d0016a41106a2012370300200220103703f001200220133703d8012002200c3a008c022002200d360288022002200e360284022002200136028002200220113703e801200220083703d001201c2002290368370000201c41086a2023290300370000201c41106a2022290300370000201c41186a2021290300370000200220173b01ae02200220183a00ad02200241f0096a200241d0016a1080031a0c010b201441e8026a200641e0006c6a2105024020184101710d0020052005290300200820085022031b37030020052005290308201320031b370308200541106a22062006290300201220031b37030020092021290300370300200a2022290300370300200b2023290300370300200220022903683703f00920052d003c2106200241d0016a41186a2218200541d5006a2204290000370300200241d0016a41106a2221200541cd006a2214290000370300200241d0016a41086a2222200541c5006a221529000037030020022005413d6a22162900003703d001201e200241f0096a200241d0016a200c41ff0171410146220c1b220341086a290000370300201f200341106a2900003703002020200341186a2900003703002002200329000037038801200541012006200c1b3a003c20162002290388013700002015201e2903003700002014201f290300370000200420202903003700002005201020052903202011a722031b370320200541286a2206200f200629030020031b37030020052011200529031820031b3703180240024020010d0041002101410021034100210d0c010b02400240200e0d00200121030c010b200e210320012106034020062802ec0321062003417f6a22030d000b200121030340200320032f01064102746a41ec036a2802002103200e417f6a220e0d000b200621010b20032f010621280b2002200d3602a801200220283602a401200241003602a0012002200336029c01200241003602980120024200370390012002200136028c0120024100360288010240200d450d002002200d417f6a22163602a8012001450d08200541306a210c4100210641002105034002400240200620012f01064f0d0020012103410021040c010b41002104034002400240200128020022030d002005ad2108410021030c010b200441016a210420013301044220862005ad8421080b200110352008a72105200321012008422088a7220620032f01064f0d000b0b200241d00c6a41186a2214200320064105746a220141206a290000370300200241d00c6a41106a220e200141186a290000370300200241d00c6a41086a2215200141106a2900003703002002200141086a2900003703d00c200241b0016a41086a220d20032006410c6c6a220141f0026a2802003602002002200141e8026a2902003703b001200641016a21060240024020040d00200321010c010b200320064102746a41ec036a2802002101410021062004417f6a2203450d00034020012802ec0321012003417f6a22030d000b0b200720022903b001370200200741086a2203200d280200360200200b2015290300370300200a200e29030037030020092014290300370300200241f0096a41206a22042007290300370300200241f0096a41286a220d201d280200360200200220022903d00c3703f009200220063602940120022005360290012002200136028c012002410036028801201d200d28020036020020072004290300370300201820092903003703002021200a2903003703002022200b290300370300200220022903f0093703d00120142009290300370300200e200a2903003703002015200b290300370300200220022903f0093703d00c200241c0016a41086a2003280200360200200220072902003703c001200241b0016a200c200241d00c6a200241c0016a108303024020022802b001450d0020022802b4012203450d0020022802b801450d00200310350b2016450d0120022016417f6a22163602a80120010d000b41958dcc00412b41c08dcc00103f000b20024188016a1081030c010b200541386a2116200541306a211502400240200528023022140d0041002129200241003602e401200241003602d4010c010b2005280238212902400240200541346a28020022060d00201421030c010b2006210320142104034020042802ec0321042003417f6a22030d000b201421030340200320032f01064102746a41ec036a28020021032006417f6a22060d000b200421140b200241003602e801200241003602e001200242003703d801200220143602d401200241003602d001200220033602e401200220032f01063602ec010b200220293602f001200241d0016a108103200541286a200f37030020052010370320200541106a20123703002005201337030820052011370318200520083703002015200e360204201520013602002016200d3602002005200c3a003c2005413d6a2002290368370000200541c5006a2023290300370000200541cd006a2022290300370000200541d5006a2021290300370000200520173b015e200520183a005d0b20022802202201450d0120022001417f6a36022020022802042203450d0620022802082105200228020021060240200228020c220420032f0106490d00034002400240200328020022010d002005ad2108410021010c010b200641016a210620033301044220862005ad8421080b200310352008a72105200121032008422088a7220420012f01064f0d000b200121030b200241d00c6a41186a2215200320044105746a220141206a290000370300200241d00c6a41106a2216200141186a290000370300200241d00c6a41086a2221200141106a2900003703002002200141086a2900003703d00c200241d0016a41086a22222003200441e0006c6a221441ad036a290000370300200241d0016a41106a2223201441b5036a290000370300200241d0016a41186a2229201441bd036a2900003703002002201441a5036a2900003703d001200441016a210420144190036a290300210f20144188036a2903002110201441f8026a2903002112201441f0026a2903002113201441c6036a2f01002117201441c5036a2d00002118201441a4036a2d0000210c201441a0036a280200210d2014419c036a280200210e20144198036a280200210120144180036a2903002111201441e8026a290300210802402006450d00200320044102746a41880b6a2802002103410021042006417f6a2206450d00034020032802880b21032006417f6a22060d000b0b20092015290300370300200a2016290300370300200b2021290300370300201e2022290300370300201f202329030037030020202029290300370300200220022903d00c3703f009200220022903d001370388012002200436020c20022005360208200220033602042002410036020020084202520d000b0b2002108f032000200028020041016a360200200241f00c6a24000f0b41a797cc004110200241d0016a41c8c1c30041c897cc001046000b41958dcc00412b41c08dcc00103f000b103c000b41958dcc00412b41c08dcc00103f000b41958dcc00412b41c08dcc00103f000b8b0503027f017e057f230041d0006b2202240041affdc600ad4280808080f00084100122032900002104200241086a200341086a290000370300200220043703002003103541adb6c300ad4280808080800184100122032900002104200241106a41086a200341086a29000037030020022004370310200310352002200136022c2002412c6aad4280808080c00084100422032900002104200241306a41086a200341086a2900003703002002200437033020031035200241cc006a200241306a3602002002200241c0006a36024420022002412c6a3602482002200241306a360240200241206a200241c0006a107b02400240024002402002280228220541206a2206417f4c0d00200228022021070240024020060d0041002101410121030c010b200610332203450d02200621010b024002402001410f4d0d00200121080c010b200141017422084110200841104b1b22084100480d03024020010d002008103322030d010c050b20012008460d0020032001200810372203450d040b20032002290300370000200341086a200241086a2903003700000240024020084170714110460d00200821010c010b200841017422014120200141204b1b22014100480d0320082001460d0020032008200110372203450d040b20032002290310370010200341186a200241106a41086a29030037000002400240200141606a2005490d00200121080c010b200541206a22082005490d03200141017422092008200920084b1b22084100480d0320012008460d0020032001200810372203450d040b200341206a20072005109d081a20002006360208200020083602042000200336020002402002280224450d00200710350b200241d0006a24000f0b1044000b1045000b103e000b103c000bc20503027f017e047f230041d0006b2202240041fafdc600ad4280808080800184100122032900002104200241086a200341086a290000370300200220043703002003103541f5bac300ad4280808080f00084100122032900002104200241106a41086a200341086a29000037030020022004370310200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100422012900002104200241306a41086a200141086a2900003703002002200437033020011035200241cc006a200341206a360200200220033602482002200241306a41106a3602442002200241306a360240200241206a200241c0006a107b200310352002280228220541206a2201417f4c0d01200228022021060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290300370000200341086a200241086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290310370010200341186a200241106a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a20002001360208200020083602042000200336020002402002280224450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000b13002000410436020420004180dec3003602000b3400200041affdc60036020420004100360200200041146a4101360200200041106a4194edc300360200200041086a42073702000baa0b080e7f017e047f017e057f027e067f017e23004180016b22022400200141086a280200210320012802042104200028020421052000280200210602400240024020002802082207200028020c2208460d00200041146a28020021092001280200210a2000280210210b200241086a210c0340200c200741106a290300370300200241106a2201200741186a290300370300200241186a220d200741206a29030037030020022007290308370300200741386a210e02402007280228220f0d00200e21070c020b200741306a2802002100200729030021102007412c6a2802002111200241206a41186a2212200d290300370300200241206a41106a22132001290300370300200241206a41086a2214200c290300370300200220022903003703202000ad42c8007e2215422088a70d032015a72207417f4c0d030240024020070d00410821160c010b200710332216450d030b200741c8006e21170240024020000d00410021180c010b200f20004105746a211941002118200f211a0340201a41086a2900002115201a41106a290000211b201a290000211c200241c0006a41186a221d201a41186a290000370300200241c0006a41106a221e201b370300200241c0006a41086a221f20153703002002201c3703400240200b2802002220450d00200b28020421210340202041086a210020202f010622224105742107410021010240024003402007450d01200241c0006a2000412010a008220d450d02200741606a2107200141016a2101200041206a2100200d417f4a0d000b2001417f6a21220b2021450d022021417f6a2121202020224102746a4194036a28020021200c010b0b0240024002402009280208220d202020014102746a41e8026a220028020022074d0d002009280200200741d8006c6a2207427f2007290320221520107c221b201b2015542201200741286a2207290300221c2001ad7c2223201c54201b20155a1b22011b3703202007427f202320011b370300200241e0006a41186a2201201d290300370300200241e0006a41106a220d201e290300370300200241e0006a41086a2220201f290300370300200220022903403703602000280200210020182017470d02024002400240201841016a22072018490d00201841017422212007202120074b1bad42c8007e2215422088a70d002015a722074100480d00024020180d0020070d02410821160c050b201841c8006c22212007460d04024020210d0020070d02410821160c050b20162021200710372216450d020c040b103e000b2007103322160d020b103c000b2007200d41a4c5ca001042000b200741c8006e21170b2016201841c8006c6a2207420037030020072000360220200741186a4200370300200741106a4200370300200741086a4200370300200720022903603702242007412c6a2020290300370200200741346a200d2903003702002007413c6a2001290300370200201841016a21180b201a41206a221a2019470d000b0b0240201141ffffff3f71450d00200f10350b200241e0006a41186a22072012290300370300200241e0006a41106a22002013290300370300200241e0006a41086a2014290300221537030020022002290320221b370360200a4200370310200a41186a4200370300200a4200370308200a2010370300200a41286a4200370300200a4201370320200a2018360238200a2017360234200a2016360230200a201b37023c200a41c4006a2015370200200a41cc006a2000290300370200200a41d4006a2007290300370200200341016a2103200a41e0006a210a200e2107200e2008470d000b200821070b20042003360200200820076b220041386d210102402000450d00200141386c21002007412c6a210703400240200728020041ffffff3f71450d002007417c6a28020010350b200741386a2107200041486a22000d000b0b02402005450d00200541386c450d00200610350b20024180016a24000f0b1045000b1044000bef3007017f017e017f027e017f027e1c7f23004180036b2207240002400240024002402001200284500d002003200484500d004201210820074198016a200320012003200156200420025620042002511b22091b220a2004200220091b220b20054201200542015620064200522006501b220c1b220520064200200c1b220610980820074188016a200729039801220d20074198016a41086a290300220e200520061084082002200420091b21022001200320091b2104200a20072903880185200b20074188016a41086a290300858450450d01200d210a200e210b420021060c020b20004100360200200041106a4200370300200041086a42003703000c020b200741f8006a2004200220052006109808200741e8006a20072903782201200741f8006a41086a2903002203200520061084084200200620042007290368852002200741e8006a41086a29030085845022091b21064201200520091b21082003200220091b21022001200420091b21040b200741386a200b420020044200108408200741c8006a20024200200a4200108408200741d8006a200a4200200442001084080240024002400240024002400240024002400240024002400240024002400240200b420052200242005271200729034042005272200729035042005272200741d8006a41086a2903002201200729033820072903487c7c2203200154724101470d00411010332209450d0d2007420437029c02200720093602980220074198026a41004104108601200741f0026a41086a220920072802a002220c41046a360200200728029802200c4102746a220c200a3e020c200c200a4220883e0208200c200b3e0204200c200b4220883e020020072007290398023703f002200741f0026a10e607200741a8016a41086a2009280200360200200720072903f0023703a80141101033220c450d0d2007420437029c022007200c3602980220074198026a41004104108601200920072802a002220c41046a360200200728029802200c4102746a220c20043e020c200c20044220883e0208200c20023e0204200c20024220883e020020072007290398023703f002200741f0026a10e607200741b8016a41086a2009280200360200200720072903f0023703b801411010332209450d0d2007420437029c02200720093602980220074198026a41004104108601200741f0026a41086a220c20072802a002220941046a36020020072802980220094102746a22092008a7220f36020c200920084220883e0208200920063e0204200920064220883e020020072007290398023703f002200741f0026a10e607200c280200211020072802f402211120072802f0022112200c200741b8016a41086a280200360200200720072903b8013703f00220074198026a41086a200741a8016a41086a280200360200200720072903a80137039802200741c8016a20074198026a200741f0026a10e807024020072802f40241ffffffff0371450d0020072802f00210350b200741c8016a10e60720104101460d0120072802cc01211320072802c80121142010450d0a2012280200450d0a024020072802d0012215450d002014280200450d0b201520104d0d0b200720103602d401201520106b221641016a22174101201741014b1b221841ffffffff03712018470d0320184102742219417f4c0d0320191039221a450d0e201041ffffffff03712010470d032010410274221b417f4c0d03201b1039221c450d0e4101210f410221092012280200220c67221d211e0240200c41ffffffff034b0d0041022109201d210c4101210f034020094101200c4101711b200f6c210f200c41034b211f200920096c2109200c410176221e210c201f0d000b0b200720153602f802200720133602f402200720143602f0024104211f41041033220c450d0f200c20094101201e4101461b200f6c220f360200200742818080801037029c022007200c36029802200741d8016a200741f0026a20074198026a10e807200c10350240201b450d00201b1033221f450d0f0b200741003602a0022007201b410276222036029c022007201f3602980220074198026a4100201010860120072802980220072802a00222094102746a20122010410274109d081a200741f8026a200920106a36020020072007290398023703f002410410332209450d0f2009200f360200200742818080801037029c022007200936029802200741e8016a200741f0026a20074198026a10e80720091035024020072802d40120176a220920072802e001220c4d0d00200741003602a002200742043703980220074198026a41002009200c6b220c10860120072802a00221090240200c450d0020072802980220094102746a4100200c410274109f081a2009200c6a21090b200741f0026a41086a220c200936020020072007290398023703f00220072802d801211f200741f0026a200920072802e001220f10860120072802f002200c28020022094102746a201f200f410274109d081a200c2009200f6a220936020020074198026a41086a220c2009360200200720072903f00237039802024020072802dc0141ffffffff0371450d0020072802d80110350b200741d8016a41086a200c28020036020020072007290398023703d8010b20194102762121200741e8016a10e607024002400240024002400240024002400240024003402007201622223602f401024020072802e001220920072802d401220c20226a220f417f736a221f2009490d00201f200941ac95cc001042000b0240024002400240024002400240024002400240024002400240024020092009200f6b220f4d0d0020072802f00122092009200c6b220c4d0d0120072802e801200c4102746a35020022024200510d02202220224100476b211620072802d8012209201f4102746a35020021012009200f4102746a3502002104200741003602f80120072004200142208684200280220137038002200741003602880220072004200120027e7d42ffffffff0f83370390022007200741f4016a3602ac022007200741d8016a3602a8022007200741d4016a3602a4022007200741e8016a3602a002200720074188026a36029c022007200741f8016a3602980220074198026a10e9071a034020072802880241016a41004c0d04024020072903900242ffffffff0f560d0020074198026a10e9070d010b0b200729038002210220072802f401210920072802d401210c200741003a00f8022007200c20096a3602f402200720093602f0022007200741d8016a3602fc02200741b0026a200741f0026a10ec0720072802f001220941ffffffff03712009470d1c2009410274220c417f4c0d1c20072802e801210f02400240200c0d004104211f0c010b200c1033221f450d280b200741003602f8022007201f3602f0022007200c4102763602f402200741f0026a4100200910860120072802f00220072802f802221f4102746a200f200c109d081a200741e0026a41086a2223201f20096a360200200720072903f0023703e002410810332209450d2820092002a72224360204200920024220883e020020074282808080203702f402200720093602f002200741c0026a200741e0026a200741f0026a10e8072009103520072802b802221920072802c8022225201920254b1b22144101201441014b1b220c41ffffffff0371200c470d1c200c4102742226417f4c0d1c20072802b402212720072802b00221280240024020260d00410421290c010b202610392229450d280b2014450d062025417f6a221b20254b211520072802c002212a2019417f6a221720194b0d04200c417f6a2109202920266a417c6a211e4100210f4200210203404100211f024020192017200f6b22134d0d004100211f201320174b0d00202820134102746a280200211f0b201fad21044100211f024020150d002025201b200f6b22134d0d002013201b4b0d00202a20134102746a280200211f0b024002402004201fad22037d22012004560d00200120027d220a2001560d00200a42ffffffff0f832104420021020c010b20044280808080108420027d20037d2104420121020b200c20094d0d09201e20043e0200201e417c6a211e2009417f6a2109200f41016a220f2014490d000c060b0b200f200941ac95cc001042000b200c200941ac95cc001042000b419095cc00411941b494cc00103f000b41ac96cc004118200741f0026a41c496cc0041d496cc001046000b200c417f6a2109202920266a417c6a211f4100211e4200210203404100210f024020150d004100210f2025201b201e6b22134d0d004100210f2013201b4b0d00202a20134102746a280200210f0b024002404200200fad22017d22044200520d00200420027d22032004560d00200342ffffffff0f832104420021020c010b428080808010200220017c7d2104420121020b200c20094d0d04201f20043e0200201f417c6a211f2009417f6a2109201e41016a221e2014490d000b0b41012113200250450d010b410021130b0240202741ffffffff0371450d00202810350b20072802d401221f20072802f401220f6a2215201f490d05200f20154f0d01200f417f7321090340200c200c200f6a20096a221e4d0d03200920072802e00122146a220f20094f0d0420072802d801200f4102746a2029201e4102746a2802003602002009417f6a210920072802f401210f201f417f6a221f0d000c050b0b2009200c41bc95cc001042000b201f450d020c030b20252019202520194b1b22074101200741014b1b200f6a20096a200c41ac95cc001042000b200f201441bc95cc001042000b200c200c2015417f7322096a200f6a220f4d0d0220072802e001220c20096a2209200c4f0d0320072802d80120094102746a2029200f4102746a28020036020020072802f401210f0b2018200f417f736a220920184f0d03201a20094102746a202436020002402013450d00201820072802f401417f736a220920184f0d05201a20094102746a22092009280200417f6a36020020072802f401210920072802d401210c200741003a00f8022007200c20096a3602f402200720093602f0022007200741d8016a3602fc02200741d0026a200741f0026a10ec0720072802f001220941ffffffff03712009470d0f2009410274220c417f4c0d0f20072802e801210f02400240200c0d004104211f0c010b200c1033221f450d1b0b200741003602f8022007201f3602f0022007200c4102763602f402200741f0026a4100200910860120072802f00220072802f802221f4102746a200f200c109d081a2023201f20096a360200200720072903f0023703e002200741f0026a200741e0026a200741d0026a10e707024020072802d401220920072802f40122146a220c2009490d00024002402014200c4f0d00200c417f73210920072802f002211320072802f802210f2014211f0340200f200f201f6a20096a221f4d0d0a200920072802e00122156a221e20094f0d0b20072802d801201e4102746a2013201f4102746a280200360200200941016a210920072802f401211f2014200c417f6a220c490d000c020b0b20090d0120072802f802210f2014211f0b201f2014417f7322096a220c200f6a221f200c4f0d0920072802e001220c20096a2209200c4f0d0a20072802d80120094102746a20072802f002201f4102746a2802003602000b024020072802f40241ffffffff0371450d0020072802f00210350b20072802d40241ffffffff0371450d0020072802d00210350b02402026450d00202910350b024020072802c40241ffffffff0371450d0020072802c00210350b20220d000b0240201d0d0020072802e001211020072802dc01212020072802d801210f201c1035410021090c130b4101210920072802d401220c4101460d114100200c6b2114201d411f7121134100201d6b411f7121152010410274201c6a417c6a210c417f210903400240200920072802e001221f6a220f2009490d00200f201f41ac95cc001042000b201f200f417f6a221e4d0d09201020096a221f20104f0d0a200c20072802d801221f201e4102746a280200201574201f200f4102746a28020020137672360200200c417c6a210c20142009417f6a2209460d110c000b0b200f200c41ac95cc001042000b2009200c41bc95cc001042000b2009201841bc95cc001042000b2009201841ac95cc001042000b201f200f41ac95cc001042000b201e201541bc95cc001042000b201f200f41ac95cc001042000b2009200c41bc95cc001042000b200f417f6a201f41ac95cc001042000b201f201041bc95cc001042000b41004100419c96cc001042000b200741286a200729035820032008200610980820004100360200200041106a200741286a41086a290300370300200041086a20072903283703000c0f0b20074198026a41086a200741c8016a41086a280200221f360200200720072903c80137039802201f4101201f41014b1b221e41ffffffff0371201e470d00201e410274221b417f4c0d0002400240201b0d00410421170c010b201b10392217450d0c0b201f450d022017201e410274201f4102746b6a210c201f417f6a2114201e201f6b2113200f4101200f41014b1bad21024200210441002109200728029802210f0340201e201320096a22154d0d02200c2004422086200f35020084220420028022013e020020142009460d03200c41046a210c200f41046a210f2004200120027e7d2104201f200941016a22094b0d000b2009201f41ac95cc001042000b1044000b2015201e41bc95cc001042000b2007201e3602f8022007201b4102763602f402200720173602f002200728029c0241ffffffff0371450d0720072802980210350c070b20072802d40121090b20072802e001220c200c20096b220f4d0d012010201020096b22094d0d02201c20094102746a20072802d801200f4102746a280200201d411f717636020041012109201c210f0b024020072802ec0141ffffffff0371450d0020072802e80110350b2009450d0320072802dc0141ffffffff0371450d0320072802d80110350c030b200f200c41ac95cc001042000b2009201041bc95cc001042000b4100211a0240201341ffffffff0371450d00201410350b0b410410332209450d022009410036020041041033220c450d02200c41003602004101211e02400240201a0d002009211a4101212141012118200c210f41012120410121100c010b20091035200c10350b2007201836028002200720213602fc012007201a3602f801200720103602a0022007202036029c022007200f3602980220074198026a10e607420021020240024020072802a00222094105744180014d0d00421d21040c010b4100211e024020090d00420021040c010b200728029802220c200941027422096a417c6a220f280200211f0240200c200f470d00201fad21040c010b200c41786a210f201fad2104200741206a211f4120210c420021020340200741186a200f20096a3502004200200c41e0007110a308201f29030020027c2007290318220220047c2204200254ad7c2102200c41206a210c2009417c6a22094104470d000b0b0240200728029c0241ffffffff0371450d0020072802980210350b201e0d030240200420084201882006423f8684562002200642018822045620022004511b450d0020074188026a41086a200741f8016a41086a280200360200200720072903f80137038802411010332209450d022007420437029c02200720093602980220074198026a41004104108601200741f0026a41086a220920072802a002220c41046a360200200728029802200c4102746a220c428080808010370208200c420037020020072007290398023703f002200741f0026a10e60720074198026a41086a2009280200360200200720072903f00237039802200741f8016a20074188026a20074198026a10e707200728029c0241ffffffff0371450d0020072802980210350b200741f0026a41086a200741f8016a41086a280200360200200720072903f8013703f0020b200741f0026a10e60720074198026a41086a2209200741f0026a41086a280200360200200720072903f0023703980220074198026a10e6074200210202400240200928020022094105744180014d0d00421d21044101211e0c010b4100211e024020090d00420021040c010b200728029802220c200941027422096a417c6a220f280200211f0240200c200f470d00201fad21040c010b200c41786a210f201fad2104200741106a211f4120210c420021020340200741086a200f20096a3502004200200c41e0007110a308201f29030020027c2007290308220220047c2204200254ad7c2102200c41206a210c2009417c6a22094104470d000b0b0240200728029c0241ffffffff0371450d0020072802980210350b02400240201e450d00200041a898cc00360204200041086a4119360200410121090c010b200041106a2002370300200041086a2004370300410021090b20002009360200201141ffffffff0371450d03201210350c030b1045000b103c000b200720043e029c02200741fc95cc003602980241d897cc00412f20074198026a418898cc00419898cc001046000b20074180036a24000b870701047f230041d0006b2208240002400240024002402002200685200320078584500d00200220038450450d01410121090c020b417f20002004852001200585844200522000200454200120055420012005511b1b21090c010b0240200620078450450d0041ff0121090c010b411010332209450d012008420437024420082009360240200841c0006a41004104108601200841306a41086a22092008280248220a41046a3602002008280240200a4102746a220a20003e020c200a20004220883e0208200a20013e0204200a20014220883e020020082008290340370330200841306a10e607200841106a41086a220b20092802003602002008200829033037031041101033220a450d01200842043702442008200a360240200841c0006a4100410410860120092008280248220a41046a3602002008280240200a4102746a220a20063e020c200a20064220883e0208200a20073e0204200a20074220883e020020082008290340370330200841306a10e607200841206a41086a200928020036020020082008290330370320200841c0006a41086a200b280200360200200820082903103703402008200841c0006a200841206a10e8070240200828022441ffffffff0371450d00200828022010350b411010332209450d012008420437024420082009360240200841c0006a41004104108601200841306a41086a22092008280248220a41046a3602002008280240200a4102746a220a20043e020c200a20044220883e0208200a20053e0204200a20054220883e020020082008290340370330200841306a10e607200841106a41086a220b20092802003602002008200829033037031041101033220a450d01200842043702442008200a360240200841c0006a4100410410860120092008280248220a41046a3602002008280240200a4102746a220a20023e020c200a20024220883e0208200a20033e0204200a20034220883e020020082008290340370330200841306a10e607200841206a41086a200928020036020020082008290330370320200841c0006a41086a200b28020036020020082008290310370340200841306a200841c0006a200841206a10e8070240200828022441ffffffff0371450d00200828022010350b2008200841306a10ea0721090240200828023441ffffffff0371450d00200828023010350b200828020441ffffffff0371450d00200828020010350b200841d0006a240020090f0b1045000bbb0703017f067e017f230041d0006b22022400024002400240200029031022032001290310220485200041186a2903002205200141186a29030022068584500d00200041086a290300210720002903002108411010332200450d022002420437024420022000360240200241c0006a41004104108601200241306a41086a22092002280248220041046a360200200228024020004102746a220020083e020c200020084220883e0208200020073e0204200020074220883e020020022002290340370330200241306a10e607200241106a41086a200928020036020020022002290330370310411010332200450d022002420437024420022000360240200241c0006a41004104108601200241306a41086a22092002280248220041046a360200200228024020004102746a220020043e020c200020044220883e0208200020063e0204200020064220883e020020022002290340370330200241306a10e607200241206a41086a200928020036020020022002290330370320200241c0006a41086a200241106a41086a280200360200200220022903103703402002200241c0006a200241206a10e8070240200228022441ffffffff0371450d00200228022010350b200141086a290300210420012903002106411010332200450d022002420437024420022000360240200241c0006a41004104108601200241306a41086a22002002280248220141046a360200200228024020014102746a220120063e020c200120064220883e0208200120043e0204200120044220883e020020022002290340370330200241306a10e607200241106a41086a2209200028020036020020022002290330370310411010332201450d022002420437024420022001360240200241c0006a4100410410860120002002280248220141046a360200200228024020014102746a220120033e020c200120034220883e0208200120053e0204200120054220883e020020022002290340370330200241306a10e607200241206a41086a200028020036020020022002290330370320200241c0006a41086a200928020036020020022002290310370340200241306a200241c0006a200241206a10e8070240200228022441ffffffff0371450d00200228022010350b2002200241306a10ea0721000240200228023441ffffffff0371450d00200228023010350b200041ff017121000240200228020441ffffffff0371450d00200228020010350b20004521000c010b2000290300200129030085200041086a290300200141086a29030085845021000b200241d0006a240020000f0b1045000bae380b147f017e017f017e017f017e017f017e017f017e0e7f23004180036b220524000240024020014115490d004101210641012107024002400240034020012108200021092006200771410173210a02400240024002400240024003400240024002402004450d00024020064101710d002000200110ff062004417f6a21040b20052002360208200520003602502005200136025420052001410276220b36020c2005200b410174220c3602102005200b41036c220d360214200541003602182005200541186a3602d8012005200541d0006a3602d4012005200541086a3602d0012005200541d0016a36021c024020014132490d002005200b417f6a3602202005200b41016a3602d0022005411c6a200541206a2005410c6a200541d0026a1080072005200c417f6a3602202005200c4101723602d0022005411c6a200541206a200541106a200541d0026a1080072005200d417f6a3602202005200d41016a3602d0022005411c6a200541206a200541146a200541d0026a1080070b2005411c6a2005410c6a200541106a200541146a1080072005280218220b410b4b0d01200b45210b2005280210210e0c020b2000200120021081070c0e0b02402005280254220c410176220d450d002005280250220b200c41306c6a41506a210c0340200541d0026a41286a220f200b41286a2210290300370300200541d0026a41206a2211200b41206a2212290300370300200541d0026a41186a220e200b41186a2213290300370300200541d0026a41106a2214200b41106a2215290300370300200541d0026a41086a2216200b41086a22172903003703002005200b2903003703d002200c41086a22182903002119200c41106a221a290300211b200c41186a221c290300211d200c41206a221e290300211f200c41286a22202903002121200b200c290300370300201020213703002012201f3703002013201d3703002015201b370300201720193703002020200f290300370300201e2011290300370300201c200e290300370300201a201429030037030020182016290300370300200c20052903d002370300200c41506a210c200b41306a210b200d417f6a220d0d000b0b20012005280210417f736a210e4101210b0b0240200b45200a724101710d002000200120021082070d0d0b02402003450d00200e20014f0d030240200228020028020028020022142802002211450d00201428020421122011211002400340201041086a210c20102f01062213410574210b4100210d024002400340200b450d012003200c412010a008220f450d02200b41606a210b200d41016a210d200c41206a210c200f417f4a0d000b200d417f6a21130b024020120d004200211b420021190c030b2012417f6a2112201020134102746a41c8056a28020021100c010b0b2010200d4105746a220b41f0026a2903002119200b41e8026a290300211b0b2011450d002000200e41306c6a2110201428020421120340201141086a210c20112f01062213410574210b4100210d024002400340200b450d012010200c412010a008220f450d02200b41606a210b200d41016a210d200c41206a210c200f417f4a0d000b200d417f6a21130b2012450d022012417f6a2112201120134102746a41c8056a28020021110c010b0b201b2011200d4105746a220b41e8026a290300542019200b41f0026a290300221b542019201b511b450d0020002109200121080c030b200541d0026a41286a221a200041286a2222290300370300200541d0026a41206a221c200041206a2223290300370300200541d0026a41186a221e200041186a2224290300370300200541d0026a41106a2220200041106a2207290300370300200541d0026a41086a2225200041086a2226290300370300200520002903003703d0022000200e41306c6a220b41086a220c2903002119200b41106a220d290300211b200b41186a220f290300211d200b41206a2210290300211f200b41286a221129030021212000200b290300370300202220213703002023201f3703002024201d3703002007201b370300202620193703002011201a2903003703002010201c290300370300200f201e290300370300200d2020290300370300200c2025290300370300200b20052903d002370300200541d0016a41286a22272022290300370300200541d0016a41206a22282023290300370300200541d0016a41186a22292024290300370300200541d0016a41106a222a2007290300370300200541d0016a41086a222b2026290300370300200520002903003703d001200041306a21184100210e200121140340200228020021170240200e2014417f6a22154f0d00201728020028020022162802002113034002402013450d00201628020421112013211002400340201041086a210c20102f01062212410574210b4100210d024002400340200b450d01200541d0016a200c412010a008220f450d02200b41606a210b200d41016a210d200c41206a210c200f417f4a0d000b200d417f6a21120b024020110d004200211b420021190c030b2011417f6a2111201020124102746a41c8056a28020021100c010b0b2010200d4105746a220b41f0026a2903002119200b41e8026a290300211b0b2013450d002018200e41306c6a211020162802042112201321110340201141086a210c20112f01062214410574210b4100210d024002400340200b450d012010200c412010a008220f450d02200b41606a210b200d41016a210d200c41206a210c200f417f4a0d000b200d417f6a21140b2012450d022012417f6a2112201120144102746a41c8056a28020021110c010b0b201b2011200d4105746a220b41e8026a2903005a2019200b41f0026a290300221b5a2019201b511b450d020b200e41016a220e2015470d000b2015210e0b02400340200e201522144f0d010240201728020028020022162802002211450d002014417f6a2115201628020421122011211002400340201041086a210c20102f01062213410574210b4100210d024002400340200b450d01200541d0016a200c412010a008220f450d02200b41606a210b200d41016a210d200c41206a210c200f417f4a0d000b200d417f6a21130b024020120d004200211b420021190c030b2012417f6a2112201020134102746a41c8056a28020021100c010b0b2010200d4105746a220b41f0026a2903002119200b41e8026a290300211b0b2011450d002000201441306c6a2110201628020421120340201141086a210c20112f01062213410574210b4100210d024002400340200b450d012010200c412010a008220f450d02200b41606a210b200d41016a210d200c41206a210c200f417f4a0d000b200d417f6a21130b2012450d022012417f6a2112201120134102746a41c8056a28020021110c010b0b201b2011200d4105746a220b41e8026a290300542019200b41f0026a290300221b542019201b511b0d010b0b201a2018200e41306c6a220b41286a220d290300370300201c200b41206a220f290300370300201e200b41186a22102903003703002020200b41106a22112903003703002025200b41086a22122903003703002005200b2903003703d0022000201441306c6a220c41086a22132903002119200c41106a2215290300211b200c41186a2216290300211d200c41206a2217290300211f200c41286a222c2903002121200b200c290300370300200d2021370300200f201f3703002010201d3703002011201b37030020122019370300202c201a2903003703002017201c2903003703002016201e2903003703002015202029030037030020132025290300370300200c20052903d002370300200e41016a210e0c010b0b200020052903d0013703002022202729030037030020232028290300370300202420292903003703002007202a2903003703002026202b2903003703002001200e41016a220b490d042000200b41306c6a21002001200b6b220141154f0d010c0c0b0b2008450d030b200e20084f0d03200541d0026a41286a2220200941286a2226290300370300200541d0026a41206a2225200941206a2227290300370300200541d0026a41186a222c200941186a2228290300370300200541d0026a41106a2222200941106a2229290300370300200541d0026a41086a2223200941086a222a290300370300200520092903003703d0022009200e41306c6a220b41086a220c2903002119200b41106a220d290300211b200b41186a220f290300211d200b41206a2210290300211f200b41286a221129030021212009200b290300370300202620213703002027201f3703002028201d3703002029201b370300202a20193703002011202029030037030020102025290300370300200f202c290300370300200d2022290300370300200c2023290300370300200b20052903d002370300200541206a41286a222b2026290300370300200541206a41206a22062027290300370300200541206a41186a220a2028290300370300200541206a41106a222d2029290300370300200541206a41086a222e202a29030037030020052009290300370320200941306a21002002280200211602402008417f6a22170d00410021240c050b2016280200280200221428020021134100212403402013450d052000202441306c6a2110201428020421122013211102400340201141086a210c20112f0106220e410574210b4100210d024002400340200b450d012010200c412010a008220f450d02200b41606a210b200d41016a210d200c41206a210c200f417f4a0d000b200d417f6a210e0b024020120d004200211b420021190c030b2012417f6a21122011200e4102746a41c8056a28020021110c010b0b2011200d4105746a220b41f0026a2903002119200b41e8026a290300211b0b2013450d0520142802042111201321100340201041086a210c20102f01062212410574210b4100210d024002400340200b450d01200541206a200c412010a008220f450d02200b41606a210b200d41016a210d200c41206a210c200f417f4a0d000b200d417f6a21120b2011450d072011417f6a2111201020124102746a41c8056a28020021100c010b0b201b2010200d4105746a220b41e8026a290300542019200b41f0026a290300221b542019201b511b450d05202441016a22242017470d000b201721240c040b200e200141d086cc001042000b200b200141e485cc001059000b4100410041f485cc001042000b200e2008418486cc001042000b2017210b02400340200b221420244d22070d010240024002402016280200280200221528020022120d004200211f4200211b0c010b2009201441306c6a21102015280204210e2012211102400340201141086a210c20112f01062213410574210b4100210d024002400340200b450d012010200c412010a008220f450d02200b41606a210b200d41016a210d200c41206a210c200f417f4a0d000b200d417f6a21130b0240200e0d004200211f4200211b0c030b200e417f6a210e201120134102746a41c8056a28020021110c010b0b2011200d4105746a220b41f0026a290300211b200b41e8026a290300211f0b2012450d00201528020421100340201241086a210c20122f01062211410574210b4100210d024002400340200b450d01200541206a200c412010a008220f450d02200b41606a210b200d41016a210d200c41206a210c200f417f4a0d000b200d417f6a21110b2010450d022010417f6a2110201220114102746a41c8056a28020021120c010b0b2012200d4105746a220b41f0026a2903002119200b41e8026a290300211d0c010b4200211d420021190b2014417f6a210b201f201d5a201b20195a201b2019511b0d000b0b20142024490d0320172014490d022000201441306c6a2117418001211c410021154100211a4100211441002118418001211e2000202441306c6a222f21000340201720006b220b41306e210c0240200b41afe0004b22010d00200c41807f6a200c201a2015492018201449220d72220f1b210b0240200f450d00201e200b200d1b211e200b201c200d1b211c0c010b200b200b410176221e6b211c0b024020182014470d000240201e0d00200541d0006a221421180c010b41002113200541d0006a2114200021100340201420133a0000201341016a21130240024002402002280200280200280200221828020022120d004200211d420021190c010b2018280204210e2012211102400340201141086a210c20112f01062216410574210b4100210d024002400340200b450d012010200c412010a008220f450d02200b41606a210b200d41016a210d200c41206a210c200f417f4a0d000b200d417f6a21160b0240200e0d004200211d420021190c030b200e417f6a210e201120164102746a41c8056a28020021110c010b0b2011200d4105746a220b41f0026a2903002119200b41e8026a290300211d0b2012450d00201828020421110340201241086a210c20122f0106220e410574210b4100210d024002400340200b450d01200541206a200c412010a008220f450d02200b41606a210b200d41016a210d200c41206a210c200f417f4a0d000b200d417f6a210e0b2011450d022011417f6a21112012200e4102746a41c8056a28020021120c010b0b2012200d4105746a220b41f0026a290300211b200b41e8026a290300211f0c010b4200211f4200211b0b2014201d201f5a2019201b5a2019201b511b6a2114201041306a21102013201e470d000b200541d0006a21180b0240201a2015470d000240201c0d00200541d0016a2215211a0c010b41002113200541d0016a2115201721100340201520133a0000201041506a2110201341016a21130240024002402002280200280200280200221a28020022120d004200211d420021190c010b201a280204210e2012211102400340201141086a210c20112f01062216410574210b4100210d024002400340200b450d012010200c412010a008220f450d02200b41606a210b200d41016a210d200c41206a210c200f417f4a0d000b200d417f6a21160b0240200e0d004200211d420021190c030b200e417f6a210e201120164102746a41c8056a28020021110c010b0b2011200d4105746a220b41f0026a2903002119200b41e8026a290300211d0b2012450d00201a28020421110340201241086a210c20122f0106220e410574210b4100210d024002400340200b450d01200541206a200c412010a008220f450d02200b41606a210b200d41016a210d200c41206a210c200f417f4a0d000b200d417f6a210e0b2011450d022011417f6a21112012200e4102746a41c8056a28020021120c010b0b2012200d4105746a220b41f0026a290300211b200b41e8026a290300211f0c010b4200211f4200211b0b2015201d201f542019201b542019201b511b6a21152013201c470d000b200541d0016a211a0b02402015201a6b220b201420186b220c200c200b4b1b2211450d002020200020182d000041306c6a220b41286a2903003703002025200b41206a290300370300202c200b41186a2903003703002022200b41106a2903003703002023200b41086a2903003703002005200b2903003703d002200020182d000041306c6a220b2017201a2d0000417f7341306c6a220c290300370300200b41286a200c41286a290300370300200b41206a200c41206a290300370300200b41186a200c41186a290300370300200b41106a200c41106a290300370300200b41086a200c41086a290300370300024020114101460d004100210d03402017201a200d6a220f2d0000417f7341306c6a220b20002018200d6a41016a22102d000041306c6a220c290300370300200b41286a200c41286a290300370300200b41206a200c41206a290300370300200b41186a200c41186a290300370300200b41106a200c41106a290300370300200b41086a200c41086a290300370300200020102d000041306c6a220b2017200f41016a2d0000417f7341306c6a220c290300370300200b41286a200c41286a290300370300200b41206a200c41206a290300370300200b41186a200c41186a290300370300200b41106a200c41106a290300370300200b41086a200c41086a290300370300200d41026a210b200d41016a220c210d200b2011490d000b201a200c6a211a2018200c6a21180b2017201a2d0000417f7341306c6a220b20052903d002370300200b41286a2020290300370300200b41206a2025290300370300200b41186a202c290300370300200b41106a2022290300370300200b41086a2023290300370300201a41016a211a201841016a21180b2000201e41306c6a200020182014461b210020174100201c6b41306c6a2017201a2015461b211720010d000b02400240201820144f0d002017210b0340202020002014417f6a22142d000041306c6a220c41286a220d2903003703002025200c41206a220f290300370300202c200c41186a22102903003703002022200c41106a22112903003703002023200c41086a22122903003703002005200c2903003703d002200b41506a220b41086a220e2903002119200b41106a2213290300211b200b41186a2215290300211d200b41206a2216290300211f200b41286a22172903002121200c200b290300370300200d2021370300200f201f3703002010201d3703002011201b3703002012201937030020172020290300370300201620252903003703002015202c29030037030020132022290300370300200e2023290300370300200b20052903d00237030020182014490d000c020b0b2000210b201a20154f0d0003402015417f6a22152d0000210c2020200b41286a220d2903003703002025200b41206a220f290300370300202c200b41186a22102903003703002022200b41106a22112903003703002023200b41086a22122903003703002005200b2903003703d0022017200c417f7341306c6a220c41086a220e2903002119200c41106a2213290300211b200c41186a2214290300211d200c41206a2216290300211f200c41286a22002903002121200b200c290300370300200d2021370300200f201f3703002010201d3703002011201b3703002012201937030020002020290300370300201620252903003703002014202c29030037030020132022290300370300200e2023290300370300200c20052903d002370300200b41306a210b201a2015490d000b0b200920052903203703002026202b290300370300202720062903003703002028200a2903003703002029202d290300370300202a202e29030037030002402008200b202f6b41306e20246a22014d0d002020202629030037030020252027290300370300202c2028290300370300202220292903003703002023202a290300370300200520092903003703d0022009200141306c6a220b41086a220c2903002119200b41106a220d290300211b200b41186a220f290300211d200b41206a2210290300211f200b41286a221129030021212009200b290300370300202620213703002027201f3703002028201d3703002029201b370300202a20193703002011202029030037030020102025290300370300200f202c290300370300200d2022290300370300200c2023290300370300200b20052903d002370300200820016b220c450d02200c20012001200c4b1b210d2008410376210f200b41306a2100024002402001200c417f6a220c490d002000200c2002200b2004109e04200921000c010b20092001200220032004109e04200b2103200c21010b200d200f4f2106200141154f0d010c050b0b20012008418486cc001042000b41a486cc00411c41c086cc00103f000b20142017419486cc001058000b20242014419486cc001059000b20014102490d004101210b03402000200b41016a220b20021083072001200b470d000b0b20054180036a24000bad0302027f037e230041d0006b22042400200441386a20024201200242015620034200522003501b22051b22022003420020051b220342ffff034200109808200441286a20042903382206200441386a41086a290300220742ffff034200108408200441186a20022003200620022004290328852003200441286a41086a2903008584420052ad7c22084201200842015620072008200654ad7c22064200522006501b22051b22082006420020051b22061098080240024002402004290318220742808004544100200441186a41086a290300501b450d00200441086a200220002002200054200320015420032001511b22051b2003200120051b200820061098082004290308220342808004544100200441086a41086a290300501b450d012007a741ffff037122050d024190edc40041194180efc400103f000b2004411136024c20044190efc40036024841bcedc40041de00200441c8006a41acedc400419ceec4001046000b2004411136024c20044190efc40036024841bcedc40041de00200441c8006a41acedc40041f0eec4001046000b200441d0006a24002003a741ffff037141ffff036c20056e0b810103017f017e027f230041106b220324000240024002402002ad4220862000ad84102a2204428080808010540d00410121022004a722052d0000220641014b0d0020060e020102010b41b89acc00412e200341086a41c09bcc0041e89acc001046000b410021020b2005103502402001450d00200010350b200341106a240020020b13002000410b360204200041c4eec3003602000b3400200041fafdc60036020420004100360200200041146a4104360200200041106a41e8a9c400360200200041086a42083702000b930301027f024020002802082201450d0020002802002202200141c8006c6a21010340024020022d00004101470d00200241086a280200450d00200241046a28020010350b0240200241246a2d00004101470d002002412c6a280200450d00200241286a28020010350b200241c8006a22022001470d000b0b0240200041046a2802002202450d00200241c8006c450d00200028020010350b024020002d000c4101470d00200041146a280200450d00200041106a28020010350b024020002d00304101470d00200041386a280200450d00200041346a28020010350b024020002d00544101470d00200041dc006a280200450d00200041d8006a28020010350b024020002d00784101470d0020004180016a280200450d00200041fc006a28020010350b024020002d009c014101470d00200041a4016a280200450d00200041a0016a28020010350b024020002d00c0014101470d00200041c8016a280200450d00200041c4016a28020010350b024020002d00e4014101470d00200041ec016a280200450d00200041e8016a28020010350b0b13002000410636020420004188b3c4003602000b2c01017f02404104103322020d001045000b20004284808080c00037020420002002360200200241143600000b2d01017f02404104103322020d001045000b20004284808080c00037020420002002360200200241e4003600000b3901017f02404110103322020d001045000b200242003700082002428080d287e2bc2d370000200042908080808002370204200020023602000b3901017f02404110103322020d001045000b2002420037000820024280c0c6c9faeb38370000200042908080808002370204200020023602000b3a01017f02404110103322020d001045000b2002420037000820024280809aa6eaafe301370000200042908080808002370204200020023602000bde0102027f017e230041106b2202240002402000280200220341064b0d00024002400240024002400240024020030e0700010203040506000b200241003a000020012002410110780c060b200241013a00002001200241011078200029030821042002200041106a2903003703082002200437030020012002411010780c050b200241023a000020012002410110780c040b200241033a000020012002410110780c030b200241043a000020012002410110780c020b200241053a000020012002410110780c010b200241063a000020012002410110780b200241106a24000bfa0301047f230041106b2202240020002802002103200028020822042001107702402004450d002003200441c8006c6a210503402002200310ac042001200228020022042002280208107802402002280204450d00200410350b2002200341246a220310ac042001200228020022042002280208107802402002280204450d00200410350b200341246a22032005470d000b0b20022000410c6a10ac042001200228020022032002280208107802402002280204450d00200310350b2002200041306a10ac042001200228020022032002280208107802402002280204450d00200310350b2002200041d4006a10ac042001200228020022032002280208107802402002280204450d00200310350b2002200041f8006a10ac042001200228020022032002280208107802402002280204450d00200310350b20022000419c016a10ac042001200228020022032002280208107802402002280204450d00200310350b0240024020002d0088024101460d00200241003a000020012002410110780c010b200241013a00002001200241011078200120004189026a411410780b2002200041c0016a10ac042001200228020022032002280208107802402002280204450d00200310350b2002200041e4016a10ac042001200228020022032002280208107802402002280204450d00200310350b200241106a24000bd10201057f230041106b22022400024002400240024002400240024002400240024020012d00000e06010203040500010b20024181ca003b01082002200141216a3602042002200141016a3602000c050b410110392201450d062000428180808010370204200020013602000c050b2001410c6a22032802002204412020044120491b220541016a220410332206450d05200620042004109f082106200328020022032005490d06200641016a200141046a2802002005109d081a2000200436020820002004360204200020063602000c040b20024181c4003b01082002200141216a3602042002200141016a3602000c020b20024181c6003b01082002200141216a3602042002200141016a3602000c010b20024181c8003b01082002200141216a3602042002200141016a3602000b2000200210cc070b200241106a24000f0b1045000b2005200341c4e7cb001058000b8611010a7f23004180016b2202240002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a22063602042001200441016a2207360200200541254b0d014100210820050e261301010101010101010101010101010101010101010101010101010101010101010102030405130b200041063a00000c130b02402005417f6a41ff01714121490d00200041063a00000c130b02402005417f6a22090d0020012006360204200120073602004101210a410021094100210b410121080c120b0240024020091039220a450d0020012802042009490d01200a20012802002009109d081a200128020422052009490d062001200520096b3602042001200128020020096a360200410121082009210b0c130b1045000b200041063a0000200a10350c120b41002105200241003a00782003417f6a210a2003417e6a210302400340200a2005460d01200241d8006a20056a200420056a220941016a2d00003a0000200120033602042001200941026a3602002002200541016a22093a00782003417f6a21032009210520094120470d000b200241d6006a20022d005a3a0000200241c8006a200241ef006a290000370300200241d0006a200241f7006a2d00003a0000200220022f01583b0154200220022900673703404100210120022800632109200228005f210b200228005b210a0c100b41012101200541ff01710d040c0e0b41002105200241003a00782003417f6a210a2003417e6a210302400340200a2005460d01200241d8006a20056a200420056a220941016a2d00003a0000200120033602042001200941026a3602002002200541016a22093a00782003417f6a21032009210520094120470d000b200241d6006a20022d005a3a0000200241c8006a200241ef006a290000370300200241d0006a200241f7006a2d00003a0000200220022f01583b0154200220022900673703404100210120022800632109200228005f210b200228005b210a0c0d0b41012101200541ff01710d040c0b0b41002105200241003a00782003417f6a210a2003417e6a210302400340200a2005460d01200241d8006a20056a200420056a220941016a2d00003a0000200120033602042001200941026a3602002002200541016a22093a00782003417f6a21032009210520094120470d000b200241d6006a20022d005a3a0000200241c8006a200241ef006a290000370300200241d0006a200241f7006a2d00003a0000200220022f01583b0154200220022900673703404100210120022800632109200228005f210b200228005b210a0c0a0b41012101200541ff01710d040c080b41002105200241003a00782003417f6a210a2003417e6a210302400340200a2005460d01200241d8006a20056a200420056a220941016a2d00003a0000200120033602042001200941026a3602002002200541016a22093a00782003417f6a21032009210520094120470d000b200241d6006a20022d005a3a0000200241c8006a200241ef006a290000370300200241d0006a200241f7006a2d00003a0000200220022f01583b0154200220022900673703404100210120022800632109200228005f210b200228005b210a0c070b41012101200541ff01710d040c050b2009200541a4f0cb001059000b200241003a00780c090b200241003a00780c060b200241003a00780c030b200241003a00780b0b2002413c6a41026a2205200241d4006a41026a2d00003a0000200241286a41086a2204200241c0006a41086a290300370300200241286a41106a2203200241c0006a41106a2d00003a0000200220022f01543b013c20022002290340370328024020010d00200241246a41026a20052d00003a0000200241106a41086a2004290300370300200241106a41106a20032d00003a0000200220022f013c3b012420022002290328370310410521080c070b200041063a00000c070b0b2002413c6a41026a2205200241d4006a41026a2d00003a0000200241286a41086a2204200241c0006a41086a290300370300200241286a41106a2203200241c0006a41106a2d00003a0000200220022f01543b013c20022002290340370328024020010d00200241246a41026a20052d00003a0000200241106a41086a2004290300370300200241106a41106a20032d00003a0000200220022f013c3b012420022002290328370310410421080c050b200041063a00000c050b0b2002413c6a41026a2205200241d4006a41026a2d00003a0000200241286a41086a2204200241c0006a41086a290300370300200241286a41106a2203200241c0006a41106a2d00003a0000200220022f01543b013c20022002290340370328024020010d00200241246a41026a20052d00003a0000200241106a41086a2004290300370300200241106a41106a20032d00003a0000200220022f013c3b012420022002290328370310410321080c030b200041063a00000c030b0b410221082002413c6a41026a2205200241d4006a41026a2d00003a0000200241286a41086a2204200241c0006a41086a290300370300200241286a41106a2203200241c0006a41106a2d00003a0000200220022f01543b013c20022002290340370328024020010d00200241246a41026a20052d00003a0000200241106a41086a2004290300370300200241106a41106a20032d00003a0000200220022f013c3b0124200220022903283703100c010b200041063a00000c010b200020083a0000200020022f01243b00012000410c6a2009360000200041086a200b360000200041046a200a360000200041106a2002290310370000200041216a20022f000d3b0000200041036a200241246a41026a2d00003a0000200041186a200241106a41086a290300370000200041206a200241106a41106a2d00003a0000200041236a2002410d6a41026a2d00003a00000b20024180016a24000be40701087f230041d00b6b22042400024020002802000d002000417f360200200441206a41186a200141186a290000370300200441206a41106a200141106a290000370300200441206a41086a200141086a2900003703002004200129000037032002400240024020002802042205450d00200041086a28020021060c010b41002106200441f0086a410041e002109f081a200441d0006a410041a008109f081a41880b10332205450d01200541003b010620054100360200200541086a200441f0086a41e002109d081a200541e8026a200441d0006a41a008109d081a200041086a4100360200200020053602040b2004200041046a22073602f808200420053602f408200420063602f008034020052f010622084105742109410021014100210a024002400240034020092001460d010240200441206a200520016a41086a412010a008220b0d00410021012006210b0c030b200141206a2101200a41016a210a200b417f4a0d000b200a417f6a21080b20060d01410121014100210b2008210a0b200441d0006a41106a200a360200200441d0006a410c6a2007360200200441d0006a41086a2005360200200420073602f808200420053602f408200420063602f0082004200b360254200420013602504101210902402001450d00200441186a200441206a41186a290300370300200441106a200441206a41106a290300370300200441086a200441206a41086a29030037030020042004290320370300410021090b0240024020090d002004418c096a200441086a29030037020020044194096a200441106a2903003702002004419c096a200441186a29030037020020042000410c6a360280092004200a3602fc08200420073602f808200420053602f4082004200b3602f0082004200429030037028409200441f0006a2004290340370300200441f8006a200441c0006a41086a29030037030020044188016a41003602002004420037036820044200370350200441003a008c0120044100360280012004418d016a200429002037000020044195016a200441206a41086a2900003700002004419d016a200441206a41106a290000370000200441a5016a200441206a41186a290000370000200441003a00ad01200441f0086a200441d0006a10800321010c010b200441e4006a410036020020044100360270200441003602542005200a41e0006c6a41e8026a2101200441d0006a1081030b200141106a200337030020012002370308200142013703002000200028020041016a360200200441d00b6a24000f0b2006417f6a2106200520084102746a41880b6a28020021050c000b0b103c000b41a797cc004110200441d0006a41c8c1c30041c897cc001046000bef0801087f230041d00b6b22042400024020002802000d002000417f360200200441206a41186a200141186a290000370300200441206a41106a200141106a290000370300200441206a41086a200141086a2900003703002004200129000037032002400240024020002802042205450d00200041086a28020021060c010b41002106200441f0086a410041e002109f081a200441d0006a410041a008109f081a41880b10332205450d01200541003b010620054100360200200541086a200441f0086a41e002109d081a200541e8026a200441d0006a41a008109d081a200041086a4100360200200020053602040b2004200041046a22073602f808200420053602f408200420063602f008034020052f010622084105742109410021014100210a024002400240034020092001460d010240200441206a200520016a41086a412010a008220b0d00410021012006210b0c030b200141206a2101200a41016a210a200b417f4a0d000b200a417f6a21080b20060d01410121014100210b2008210a0b200441d0006a41106a200a360200200441d0006a410c6a2007360200200441d0006a41086a2005360200200420073602f808200420053602f408200420063602f0082004200b360254200420013602504101210902402001450d00200441186a200441206a41186a290300370300200441106a200441206a41106a290300370300200441086a200441206a41086a29030037030020042004290320370300410021090b0240024020090d002004418c096a200441086a29030037020020044194096a200441106a2903003702002004419c096a200441186a29030037020020042000410c6a360280092004200a3602fc08200420073602f808200420053602f4082004200b3602f0082004200429030037028409200441f0006a2004290340370300200441f8006a200441c0006a41086a29030037030020044188016a41003602002004420037036820044200370350200441003a008c0120044100360280012004418d016a200429002037000020044195016a200441206a41086a2900003700002004419d016a200441206a41106a290000370000200441a5016a200441206a41186a290000370000200441003a00ad01200441f0086a200441d0006a10800321010c010b200441e4006a410036020020044100360270200441003602542005200a41e0006c6a41e8026a2101200441d0006a1081030b200441d0006a41186a200241186a290000370300200441d0006a41106a200241106a290000370300200441d0006a41086a200241086a29000037030020042002290000370350200441206a41086a200341086a28020036020020042003290200370320200441f0086a200141306a200441d0006a200441206a108303024020042802f008450d0020042802f4082201450d00200441f8086a280200450d00200110350b2000200028020041016a360200200441d00b6a24000f0b2006417f6a2106200520084102746a41880b6a28020021050c000b0b103c000b41a797cc004110200441d0006a41c8c1c30041c897cc001046000b920402087f027e230041106b22022400200241003602082002420137030020002802102103200041186a2802002204200210770240024002402004450d00200320044105746a21050340200328020021060240024020022802042207200228020822046b4104490d00200228020021080c010b200441046a22082004490d03200741017422092008200920084b1b22094100480d030240024020070d00024020090d00410121080c020b2009103322080d010c060b2002280200210820072009460d0020082007200910372208450d050b20022009360204200220083602000b200820046a20063600002002200441046a360208200341086a200210aa042005200341206a2203470d000b0b200041086a290300210a2000290300210b0240024020022802042207200228020822036b4110490d00200341106a2104200228020021080c010b200341106a22042003490d01200741017422082004200820044b1b22064100480d010240024020070d00024020060d00410121080c020b200610332208450d040c010b2002280200210820072006460d0020082007200610372208450d030b20022006360204200220083602000b200820036a2203200a3700082003200b370000200220043602082000411c6a200210ab04200228020421032001290200200235020842208620022802002204ad84100202402003450d00200410350b200241106a24000f0b103e000b103c000bdf2204137f017e017f087e230041a0026b22032400024002400240024002400240024002400240024002400240024002400240024020012d00000e050001020304000b200341b4016a4101360200200342013702a401200341e8d4ca003602a0012003410436027c2003419cd5ca003602782003200341f8006a3602b001200341a0016a41b0b4cc00104c000b4102210402400240024020022d00000d0020022d00014101470d00200141046a2802002101200241196a2d00002104200241186a2d00002105200241166a2f01002106200241156a2d00002107200241146a2d00002108200241126a2f01002109200241116a2d0000210a200241106a2d0000210b2002410e6a2f0100210c2002410d6a2d0000210d2002410c6a2d0000210e2002410a6a2f0100210f200241096a2d00002110200241086a2d00002111200241066a2f01002112200241056a2d00002113200241046a2d00002114200241026a2f0100211520032002411a6a290100370320200320043a001f200320053a001e200320063b011c200320073a001b200320083a001a200320093b01182003200a3a00172003200b3a00162003200c3b01142003200d3a00132003200e3a00122003200f3b0110200320103a000f200320113a000e200320123b010c200320133a000b200320143a000a200320153b0108200341286a2001109604200341a0016a200328022822052003280230220b10cb02200341f8006a41086a2202200341a0016a41106a290300370300200341f8006a41106a2204200341a0016a41186a290300370300200341f8006a41186a2206200341c0016a290300370300200320032903a8013703780240024020032903a0014201520d00200341386a41186a2006290300370300200341386a41106a2004290300370300200341386a41086a200229030037030020032003290378370338410321044100210241f6b5c300210741052106410221084105210a0c010b200341386a41086a200341086a41086a290300370300200341386a41106a200341086a41106a290300370300200341386a41186a200341086a41186a29030037030020032003290308370338200342003703682003428080e983b1de163703602003200341086a36025c2003200341086a3602742003200341f4006a3602a8012003200341dc006a3602a4012003200341e0006a3602a001200341f8006a200341086a200341a0016a108c030240024020032802784101470d0020032f007d20032d007f41107472220641107621092006410876210820034184016a280200210a200341f8006a41086a280200210720032d007c210c0c010b4104210c0240200341f8006a41086a2903004201520d00200341f8006a41106a290300211620032802742102200341d8016a200341f8006a41186a290300370300200341d0016a2016370300200341a0016a41086a41003a0000200341a9016a2002290000370000200341b1016a200241086a290000370000200341b9016a200241106a290000370000200341c1016a200241186a290000370000200341033a00a00141b0b4cc004100200341a0016a10d4010b0b41042104410021020240200c41ff01714104460d00200c21040c010b200341d0016a4200370300200341c8016a428080e983b1de16370300200341a0016a41106a200341386a41086a290300370300200341a0016a41186a200341386a41106a290300370300200341c0016a200341386a41186a290300370300200342013703a001200320032903383703a8012003200b36027c20032005360278200341a0016a41086a200341f8006a10b204410121020b0240200328022c450d00200510350b20020d02200941ff0171411074200841ff017141087472200641ff0171724108742102200aad4220862007ad8421160c010b410021020b200042003703082000411c6a2016370200200041186a2002200441ff017172360200420121160c0e0b200341c8016a2001360200200341ad016a200341106a290300370000200341b5016a200341186a290300370000200341bd016a200341206a290300370000200341003a00a401200341023a00a001200320032903083700a50141b0b4cc004100200341a0016a10d401420021160c0a0b200141246a2802002105200341386a41186a200141196a290000370300200341386a41106a200141116a290000370300200341386a41086a200141096a29000037030020032001290001370338410221014100210420022d00000d0a20022d00014101470d0a200241196a2d00002101200241186a2d00002106200241166a2f01002107200241156a2d00002108200241146a2d00002109200241126a2f0100210a200241116a2d0000210b200241106a2d0000210c2002410e6a2f0100210d2002410d6a2d0000210e2002410c6a2d0000210f2002410a6a2f01002110200241096a2d00002111200241086a2d00002112200241066a2f01002113200241056a2d00002114200241046a2d00002115200241026a2f0100211720032002411a6a29010037039001200320013a008f01200320063a008e01200320073b018c01200320083a008b01200320093a008a012003200a3b0188012003200b3a0087012003200c3a0086012003200d3b0184012003200e3a0083012003200f3a008201200320103b018001200320113a007f200320123a007e200320133b017c200320143a007b200320153a007a200320173b01780240200341f8006a200341386a412010a0080d0041ebb5c3002102410b21074103210141800a21064180800c21050c0c0b200341e0006a2005109604200341a0016a200328026022042003280268220910cb02410321014105210641002107024020032903a0014201510d004183b6c3002102420b2116410021080c090b200341d0016a2903002118200341c8016a2903002119200341b0016a22022903002116200341a0016a41206a290300211a20032903a801211b2002200341b8016a2903003703002003201a3703b8012003201b3703a001200320163703a801200341a0016a200341f8006a412010a0080d02200341086a200341f8006a200341386a20192018410110ef02200341086a41086a290300211b0240024020032802084101460d004200211642002018200341086a41106a2903007d2019201b54ad7d221a2019201b7d221b201956201a201856201a2018511b22021b21184200201b20021b2119200341386a41106a290300211c2003290340211d2003290338211e2003290350211a4201211b4100210741002108410021060c010b201b4220882116200328020c220141187621072001411076210820014108762106201ba72102200141ff01714104470d094200211b0b200341d0016a2018370300200341c8016a2019370300200341c0016a201a3703002003201b3703a001200341b8016a201c3703002003201e3703a8012003201d3703b00102400240201b4201510d002009ad4220862004ad8410070c010b2003200936020c20032004360208200341a8016a200341086a10b2040b410421010c080b41022104024020022d00000d0020022d00014101470d00200141046a2802002101200241196a2d00002104200241186a2d00002105200241166a2f01002106200241156a2d00002107200241146a2d00002108200241126a2f01002109200241116a2d0000210a200241106a2d0000210b2002410e6a2f0100210c2002410d6a2d0000210d2002410c6a2d0000210e2002410a6a2f0100210f200241096a2d00002110200241086a2d00002111200241066a2f01002112200241056a2d00002113200241046a2d00002114200241026a2f0100211520032002411a6a290100370320200320043a001f200320053a001e200320063b011c200320073a001b200320083a001a200320093b01182003200a3a00172003200b3a00162003200c3b01142003200d3a00132003200e3a00122003200f3b0110200320103a000f200320113a000e200320123b010c200320133a000b200320143a000a200320153b0108200341286a2001109604200341a0016a200328022822052003280230220610cb024103210441800a2102024020032903a0014201510d004280808080b00121164183b6c30021060c060b200341d0016a2903002119200341c8016a290300211b200341a0016a41106a2903002116200341a0016a41206a290300211a20032903a8012118200341386a41106a200341b8016a2903003703002003201a3703502003201837033820032016370340200341386a200341086a412010a0080d032003201b370360200320193703680240201b201984500d002003200341086a360274200341f8006a200341086a200341e0006a200341f4006a10f00220032903784201520d002003290380012116200341d8016a200341f8006a41106a290300370300200341d0016a2016370300200341a0016a41086a41003a0000200341a9016a2003290308370000200341b1016a200341086a41086a290300370000200341b9016a200341086a41106a290300370000200341c1016a200341206a290300370000200341033a00a00141b0b4cc004100200341a0016a10d4010b2006ad4220862005ad84100741042104420021160c050b410021020c050b20022d000120022d0000410047720d02200141116a290000211a200141096a2900002118200141196a29000021192001290001211b200341e0006a200141246a2802002207109604200341a0016a200328026022022003280268220810cb02200341d0016a2101200341c8016a2104200341b8016a2105200341c0016a2106024020032903a0014201520d00200129030021162004290300211c200341a0016a41106a290300211d2006290300211e20032903a801211f200341386a41106a20052903003703002003201e3703502003201f3703382003201d3703402003201c37030820032016370310201c201684500d002003200341386a360228200341f8006a200341386a200341086a200341286a10f00220032903784201520d002003290380012116200341d8016a200341f8006a41106a290300370300200341d0016a2016370300200341a0016a41086a41003a0000200341a9016a2003290338370000200341b1016a200341386a41086a290300370000200341b9016a200341386a41106a290300370000200341c1016a200341d0006a290300370000200341033a00a00141b0b4cc004100200341a0016a10d4010b420021162001420037030020044200370300200620193703002005201a3703002003201b3703a801200342013703a001200320183703b0012003200836027c20032002360278200341a8016a200341f8006a10b20402402003280264450d00200210350b200341ad016a2018370000200341c8016a2007360200200341bd016a2019370000200341b5016a201a3700002003201b3700a501200341003a00a401200341023a00a00141b0b4cc004100200341a0016a10d4010c070b41fbb5c300210242082116410121080c050b41808a04210242808080808001211641fbb5c30021060c010b20004200370308200041186a4102360200420121160c070b0240200328022c450d00200510350b20044104460d0120162006ad8421160b200042003703082000411c6a2016370200200041186a2002200472360200420121160c050b200341a8016a2001360200200341013a00a401200341023a00a00141b0b4cc004100200341a0016a10d401420021160c010b02402003280264450d00200410350b0240200141ff01714104460d002007411874210420064108744180fe037121062008411074418080fc077121052016a721070c030b200341c8016a2005360200200341ad016a200341c0006a290300370000200341b5016a200341c8006a290300370000200341bd016a200341d0006a290300370000200341003a00a401200341023a00a001200320032903383700a50141b0b4cc004100200341a0016a10d401420021160b200020163703080c020b41002105410021060b200041206a20073602002000411c6a200236020020004200370308200041186a2004200572200672200141ff017172360200420121160b20002016370300200341a0026a24000ba90102017f027e02400240411010332202450d0020024110412010372202450d0120022000290000370000200241186a200041186a290000370000200241106a200041106a290000370000200241086a200041086a290000370000200041286a2903002103200029032021042002412041c00010372200450d0120002004370020200041286a200337000020012902002000ad42808080808006841002200010350f0b1045000b103c000b9aa90105037f017e137f077e107f230041f0126b220324000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e0c000102030405060708090a0b000b200341c4106a4101360200200342013702b410200341e8d4ca003602b0102003410436029c0b2003419cd5ca003602980b2003200341980b6a3602c010200341b0106a41b0b4cc00104c000b200241036a2d0000210420022f00012105200141196a2900002106200141186a2d00002107200141176a2d00002108200141156a2f00002109200141146a2d0000210a200141136a2d0000210b200141116a2f0000210c200141106a2d0000210d2001410f6a2d0000210e2001410d6a2f0000210f2001410c6a2d000021102001410b6a2d00002111200141096a2f00002112200141086a2d00002113200141076a2d00002114200141056a2f00002115200141046a2d00002116200141036a2d0000211720012f000121180240024002400240024020022d00002219417f6a220141024b0d00024020010e03000102000b200241086a2802004101742002410c6a2802004d0d00200241046a28020041ff0171450d010b200520044110747220194100477241ff01710d010b41fafdc600ad428080808080018410012202290000211a2002290008211b2002103541e8adc400ad4280808080a0018410012202290000211c2002290008211d200210352003201d3703b00b2003201c3703a80b2003201b3703a00b2003201a3703980b200341b0106a200341980b6a10dc020240024020032802b01022020d0041002105200341003602a00620034208370398064101210141082102410021040c010b200320032902b410221a37029c062003200236029806201a422088a722044114492101201aa721050b200320063703e008200320073a00df08200320083a00de08200320093b01dc082003200a3a00db082003200b3a00da082003200c3b01d8082003200d3a00d7082003200e3a00d6082003200f3b01d408200320103a00d308200320113a00d208200320123b01d008200320133a00cf08200320143a00ce08200320153b01cc08200320163a00cb08200320173a00ca08200320183b01c8082001450d01200341b0106a41186a2207200341c8086a41186a290300370300200341b0106a41106a2208200341c8086a41106a290300370300200341b0106a41086a2209200341c8086a41086a290300370300200320032903c8083703b010024020042005470d0020034198066a2004109401200328029c062105200328029806210220032802a00621040b200220044106746a2201420037030820014201370300200141106a4200370300200141186a4200370300200141206a20032903b010370300200141286a2009290300370300200141306a2008290300370300200141386a20072903003703002003200441016a22073602a00641fafdc600ad42808080808001841001220129000021062001290008211a2001103541e8adc400ad4280808080a0018410012201290000211b2001290008211c200110352003201c3703b00b2003201b3703a80b2003201a3703a00b200320063703980b0240024020020d00200341980b6aad428080808080048410070c010b200341b0106a2002200710b404200341980b6aad428080808080048420033502b81042208620032802b0102201ad841002024020032802b410450d00200110350b200541ffffff1f71450d00200210350b200341bc106a2004360200200341b8106a41063a0000200341113a00b01041b0b4cc004100200341b0106a10d401200041106a2007ad42f0c8217e4280a3c3c7007c37030020004201370308200042003703000c1d0b200341023a00b01020032802b01021010c010b4183b0302101200541ffffff1f71450d00200210350b200041206a41113602002000411c6a41c6b8c300360200200041186a200136020020004200370308200042013703000c1a0b200341c8086a200141046a41a002109d081a410221010240024020022d00000d0020022d00014101470d00200241196a2d00002101200241186a2d00002104200241166a2f01002105200241156a2d00002107200241146a2d00002108200241126a2f01002109200241116a2d0000210a200241106a2d0000210b2002410e6a2f0100210c2002410d6a2d0000210d2002410c6a2d0000210e2002410a6a2f0100210f200241096a2d00002110200241086a2d00002111200241066a2f01002112200241056a2d00002113200241046a2d00002114200241026a2f0100211520032002411a6a2901003703a00e200320013a009f0e200320043a009e0e200320053b019c0e200320073a009b0e200320083a009a0e200320093b01980e2003200a3a00970e2003200b3a00960e2003200c3b01940e2003200d3a00930e2003200e3a00920e2003200f3b01900e200320103a008f0e200320113a008e0e200320123b018c0e200320133a008b0e200320143a008a0e200320153b01880e4103210120032802d008220241e4004b0d0020032002ad221e42004280c0c6c9faeb38420010840820034198066a200341880e6a10b504200341b0106a200328029806220220032802a00610d402200341d0036a200341b0106a41a402109d081a200341b0036a41086a2201200341dd126a290000370300200341b0036a41106a2204200341e5126a290000370300200341b0036a41176a2205200341ec126a280000360000200320032900d5123703b003200341086a290300211f2003290300211c0240024020032d00d41222074102460d0020034188016a200341d0036a41a402109d081a200341e8006a41176a2005280000360000200341e8006a41106a2004290300370300200341e8006a41086a2001290300370300200320032903b0033703680240200328029c06450d00200210350b200341b0106a20034188016a41a402109d081a200341b0106a41a4026a20073a0000200341d5126a2003290368370000200341dd126a200341e8006a41086a290300370000200341e5126a200341e8006a41106a290300370000200341ec126a200341ff006a2800003600000240200341b0106a41186a2802002208450d0020032802c010210241002101410021040340024002400240200241086a2207280200417f6a220541054b0d00024020050e06000101010100000b20010d01410021010c020b200141016a21010c010b200420016b220520084f0d1020034198066a41186a2209200220014105746b220541186a220a29030037030020034198066a41106a220b200541106a220c29030037030020034198066a41086a220d200541086a220e290300370300200320052903003703980620072903002106200241106a220f290300211a200241186a2210290300211b20052002290300370300200a201b370300200c201a370300200e200637030020102009290300370300200f200b2903003703002007200d29030037030020022003290398063703000b200241206a21022008200441016a2204470d000b2001417f6a20084f0d002003200820016b3602c8100b200341cc106a220210a3042002200341c8086a41a002109d081a200341980b6a200341b0106a41c002109d081a200341980b6a41086a290300211b20032903980b211d0c010b0240200328029c06450d00200210350b200341b00b6a41003602004200211d200342003703a00b200342003703980b200342083703a80b200341b40b6a200341c8086a41a002109d081a4200211b0b2003201c4280809aa6eaafe3017c221a3703980b2003201f201a201c54ad7c221c3703a00b0240201a201d58201c201b58201c201b5122041b0d002003201c201b7d201a201d54ad7d22063703d8032003201a201d7d221f3703d0032003200341880e6a360240201f2006844200510d002003200341880e6a36028801200320034188016a3602b8102003200341c0006a3602b4102003200341d0036a3602b01020034198066a200341880e6a200341b0106a108c03024002402003280298064101470d0020032f009d0620032d009f06411074722102200341a0066a290300210620032d009c0621010c010b41042101024020034198066a41086a2903004201520d0020034198066a41106a29030021062003280288012102200341e8106a20034198066a41186a290300370300200341e0106a2006370300200341b0106a41086a41003a0000200341b9106a2002290000370000200341c1106a200241086a290000370000200341c9106a200241106a290000370000200341d1106a200241186a290000370000200341033a00b01041b0b4cc004100200341b0106a10d4010b0b200141ff01714104460d000240200341ac0b6a28020041ffffff3f71450d0020032802a80b10350b200341b40b6a10a3040c020b0240201d201a58201b201c5820041b0d002003201b201c7d201d201a54ad7d22063703d8032003201d201a7d221a3703d003201a200684500d002003200341880e6a3602880120034198066a200341880e6a200341d0036a20034188016a10f0022003290398064201520d0020032903a0062106200341e8106a20034198066a41106a290300370300200341e0106a2006370300200341b0106a41086a41003a0000200341b9106a20032903880e370000200341c1106a200341880e6a41086a290300370000200341c9106a200341880e6a41106a290300370000200341d1106a200341a00e6a290300370000200341033a00b01041b0b4cc004100200341b0106a10d4010b200341b00b6a3502002106200341b0106a200341980b6a41c002109d081a20034198066a200341880e6a10b5042003280298062102200320032802a0063602d403200320023602d003200341b0106a200341d0036a10b0040240200328029c06450d00200210350b0240200341c4106a28020041ffffff3f71450d0020032802c01010350b200341cc106a10a304200341b0106a41086a41003a0000200341b9106a20032903880e370000200341c9106a200341880e6a41106a290300370000200341d1106a200341a00e6a290300370000200341880e6a41086a290300211a200341113a00b010200341b0106a41116a201a37000041b0b4cc004100200341b0106a10d401200041106a201e42e0c6db007e20064280b5187e7c4280c5d8d8007c37030020004201370308200042003703000c1b0b41d7b8c300ad4280808080d001842106200341c8086a10a30441981621020b200020023b00192000200637021c200042003703082000411b6a20024110763a0000200041186a20013a0000200042013703000c190b2001410c6a2802002107200141086a2802002105200141046a28020021084102210920022d00000d1620022d00014101470d16200241196a2d00002101200241186a2d00002104200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241086a2d00002114200241066a2f01002115200241056a2d00002116200241046a2d00002117200241026a2f0100211820032002411a6a2901003703e803200320013a00e703200320043a00e603200320093b01e4032003200a3a00e3032003200b3a00e2032003200c3b01e0032003200d3a00df032003200e3a00de032003200f3b01dc03200320103a00db03200320113a00da03200320123b01d803200320133a00d703200320143a00d603200320153b01d403200320163a00d303200320173a00d203200320183b01d003200341b0106a200341d0036a10b504200341206a20032802b010220120032802b81041b0b4cc0041004100108a0220032802202102024020032802b410450d00200110350b41032109024020024101460d0041d0b9c300ad4280808080800184210641980221040c180b0240200741e4004d0d0041d8b9c300ad4280808080a002842106411821040c180b200341980b6a200341d0036a10b604200341b0106a20032802980b220120032802a00b10cc02200341b0106a41086a290300420020032802c01022021b211a20032903b010420020021b211b20032902c41021060240200328029c0b450d00200110350b2006420020021b211e2002410120021b2119200341106a2007ad4200428080d287e2bc2d42001084080240201b2003290310221f5a201a200341106a41086a290300221d5a201a201d5122021b0d002003201d201a7d201f201b54ad7d22063703d0082003201f201b7d221c3703c8082003200341d0036a3602880e201c2006844200510d002003200341d0036a36029806200320034198066a3602b8102003200341880e6a3602b4102003200341c8086a3602b010200341980b6a200341d0036a200341b0106a108c030240024020032802980b4101470d0020032f009d0b20032d009f0b411074722104200341a00b6a290300210620032d009c0b21090c010b410421090240200341980b6a41086a2903004201520d00200341980b6a41106a29030021062003280298062101200341e8106a200341980b6a41186a290300370300200341e0106a2006370300200341b0106a41086a41003a0000200341b9106a2001290000370000200341c1106a200141086a290000370000200341c9106a200141106a290000370000200341d1106a200141186a290000370000200341033a00b01041b0b4cc004100200341b0106a10d4010b0b200941ff01714104460d00201e42ffffff3f83500d18201910350c180b0240201b201f58201a201d5820021b0d002003201a201d7d201b201f54ad7d22063703d0082003201b201f7d221a3703c808201a200684500d002003200341d0036a36029806200341980b6a200341d0036a200341c8086a20034198066a10f00220032903980b4201520d0020032903a00b2106200341e8106a200341980b6a41106a290300370300200341e0106a2006370300200341b0106a41086a41003a0000200341b9106a20032903d003370000200341c1106a200341d0036a41086a290300370000200341c9106a200341d0036a41106a290300370000200341d1106a200341e8036a290300370000200341033a00b01041b0b4cc004100200341b0106a10d4010b0240201e4220882220a72202450d0020024105742101201921020340200341b0106a200210970420033502b81042208620032802b0102204ad841007024020032802b410450d00200410350b200241206a2102200141606a22010d000b0b200341003602800b200342013703f80a200341f80a6a4100200741c4006c221641c4006d108a0120032802800b210d20032802f80a21180240024002402016450d00200820166a21212018200d4105746a2101200341b0106a41206a2117200341b0106a41216a2104200341980b6a411f6a210e4100210a0340200341880e6a41186a22072008200a6a220241186a290200370300200341880e6a41106a2209200241106a290200370300200341880e6a41086a220b200241086a290200370300200320022902003703880e200341980b6a41086a220c200241296a290000370300200341980b6a41106a220f200241316a290000370300200341980b6a41186a2210200241396a290000370300200e200241c0006a2800003600002003200241216a2900003703980b200241206a2d000022114106460d02200341c8086a41186a22122007290300370300200341c8086a41106a22132009290300370300200341c8086a41086a2214200b290300370300200320032903880e3703c808200341b0106a41186a2207200341d0036a41186a290300370300200341b0106a41106a2209200341d0036a41106a290300370300200341b0106a41086a2215200341d0036a41086a290300370300200320032903d0033703b010200320113a00d010200420032903980b370000200441086a200c290300370000200441106a200f290300370000200441186a20102903003700002004411f6a200e280000360000200341c0006a200341c8086a109704200335024821062003280240210b412010332202450d0d200220032903b010370000200241186a2007290300370000200241106a2009290300370000200241086a201529030037000020034188016a201710ac04200328028801210c0240024020032802900122070d00200741206a21090c010b200741206a22092007490d0f200941c000200941c0004b1b220f4100480d0f20024120200f10372202450d0e0b200241206a200c2007109d081a0240200328028c01450d00200c10350b2006422086200bad842009ad4220862002ad8410022002103502402003280244450d00200b10350b024020032d00d0104101470d0020032802d810450d0020032802d41010350b20034198066a41086a2014290300220637030020034198066a41106a2013290300221a37030020034198066a41186a2012290300221b370300200320032903c808221c37039806200141186a201b370000200141106a201a370000200141086a20063700002001201c370000200d41016a210d200141206a21012016200a41c4006a220a470d000b0b2003200d3602800b0c010b2003200d3602800b200241c4006a2021460d00200241e4006a21022016200a6b41bc7f6a21010340024020022d00004101470d00200241086a280200450d00200241046a28020010350b200241c4006a2102200141bc7f6a22010d000b0b02402005450d00200541c4006c450d00200810350b20032802fc0a2102200dad210602400240200d450d00200341c8106a200d360200200341c4106a20023602002003201f3703b010200320183602c0102003201d3703b810200341980b6a200341d0036a10b60420032802980b2101200320032802a00b3602cc08200320013602c808200341b0106a200341c8086a108d030240200328029c0b450d00200110350b0240200241ffffff3f71450d00201810350b410121010c010b200341b0106a200341d0036a10b60420033502b81042208620032802b0102201ad841007024020032802b410450d00200110350b410021010b202042c0d89e017e200642a0eae1017e7c20204280c2d72f7e7c20064280c2d72f7e7c21060240200241ffffff3f71450d0020010d00201810350b200642c0db89db007c21060240201e42ffffff3f83500d00201910350b20004201370308200041106a2006370300200042003703000c180b41022101024020022d00000d004101210520022d00014101470d00200241196a2d00002101200241186a2d00002104200241166a2f01002107200241156a2d00002108200241146a2d00002109200241126a2f0100210a200241116a2d0000210b200241106a2d0000210c2002410e6a2f0100210d2002410d6a2d0000210e2002410c6a2d0000210f2002410a6a2f01002110200241096a2d00002111200241086a2d00002112200241066a2f01002113200241056a2d00002114200241046a2d00002115200241026a2f0100211620032002411a6a290100370358200320013a0057200320043a0056200320073b0154200320083a0053200320093a00522003200a3b01502003200b3a004f2003200c3a004e2003200d3b014c2003200e3a004b2003200f3a004a200320103b0148200320113a0047200320123a0046200320133b0144200320143a0043200320153a0042200320163b0140200341980b6a200341c0006a10b604200341b0106a20032802980b220220032802a00b220110cc020240024020032802c01022040d004200211b4200211c4200211d0c010b2001ad4220862002ad841007200341b8106a290300211d20032903b010211c20032902c410211b200421050b0240200328029c0b450d00200210350b200341e80d6a200341c0006a10b504200341b0106a20032802e80d220220032802f00d220410d402024020032d00d412220941024622010d002004ad4220862002ad8410070b200341880e6a200341b0106a41a402109d081a200341f80a6a41176a2204200341ec126a280000360000200341f80a6a41106a2207200341e5126a290000370300200341f80a6a41086a2208200341dd126a290000370300200320032900d5123703f80a200341d0036a200341880e6a41a402109d081a200341b0036a41176a220a2004280000360000200341b0036a41106a22042007290300370300200341b0036a41086a22072008290300370300200320032903f80a3703b003024020010d0020034188016a200341d0036a41a402109d081a200341e8006a41176a200a280000360000200341e8006a41106a2004290300370300200341e8006a41086a2007290300370300200320032903b003370368024020032802ec0d450d00200210350b200341c8086a41066a20034188016a41a402109d081a20034198066a200341c8086a41aa02109d081a200341f8056a41176a2202200341e8006a41176a280000360000200341f8056a41106a2201200341e8006a41106a290300370300200341f8056a41086a2204200341e8006a41086a290300370300200320032903683703f805200341980b6a20034198066a41066a41a402109d081a200341980b6a41a4026a20093a0000200341bd0d6a20032903f805370000200341c50d6a2004290300370000200341cd0d6a2001290300370000200341d40d6a2002280000360000200341980b6a41086a290300211e20032903980b211f20032802a80b210702400240200341b00b6a280200220841057422010d00420021064200211a0c010b200741106a2102420021064200211a0340200241086a2903004200200241786a29030042015122041b201a7c2002290300420020041b221a20067c2206201a54ad7c211a200241206a2102200141606a22010d000b0b201e201d7c201f201c7c221c201f54ad7c201a7c201c20067c2206201c54ad7c211a0240201b422088221ca72202450d0020024105742101200521020340200341b0106a200210970420033502b81042208620032802b0102204ad841007024020032802b410450d00200410350b200241206a2102200141606a22010d000b0b20032006370398062003201a3703a00602402006201a84500d002003200341c0006a3602880e200341c8086a200341c0006a20034198066a200341880e6a10f00220032903c8084201520d0020032903d008211d200341e8106a200341c8086a41106a290300370300200341e0106a201d370300200341b0106a41086a41003a0000200341b9106a2003290340370000200341c1106a200341c0006a41086a290300370000200341c9106a200341c0006a41106a290300370000200341d1106a200341d8006a290300370000200341033a00b01041b0b4cc004100200341b0106a10d4010b200341e8106a201a370300200341e0106a2006370300200341b0106a41086a41013a0000200341b9106a2003290340370000200341c9106a200341d0006a290300370000200341d1106a200341d8006a290300370000200341c0006a41086a2903002106200341113a00b010200341b0106a41116a200637000041b0b4cc004100200341b0106a10d401201c42c0d89e017e2008ad42a09c017e7c201c4280c2d72f7e7c200341bc0b6a35020042a0f7367e7c2106200341b40b6a21020240200341ac0b6a28020041ffffff3f71450d00200710350b20064280eaee92017c2106200210a3040240201b42ffffff3f83500d00200510350b20004201370308200041106a2006370300200042003703000c190b024020032802ec0d450d00200210350b41032101201b42ffffff3f83500d00200510350b20004198043b001920004200370308200041206a41083602002000411c6a41c8b9c300360200200041186a20013a0000200042013703000c170b200141106a290300211a200141086a290300211b200141046a28020021012002411a6a2901002106200241196a2d00002105200241186a2d00002107200241166a2f01002108200241156a2d00002109200241146a2d0000210a200241126a2f0100210b200241116a2d0000210c200241106a2d0000210d2002410e6a2f0100210e2002410d6a2d0000210f2002410c6a2d000021102002410a6a2f01002111200241096a2d00002112200241086a2d00002113200241066a2f01002114200241056a2d00002115200241046a2d00002116200241026a2f0100211741012104024020022d00000d0020022d000141014721040b200320063703e008200320053a00df08200320073a00de08200320083b01dc08200320093a00db082003200a3a00da082003200b3b01d8082003200c3a00d7082003200d3a00d6082003200e3b01d4082003200f3a00d308200320103a00d208200320113b01d008200320123a00cf08200320133a00ce08200320143b01cc08200320153a00cb08200320163a00ca08200320173b01c808024020040d00200341880e6a41186a200341c8086a41186a290300370300200341880e6a41106a200341c8086a41106a290300370300200341880e6a41086a200341c8086a41086a290300370300200320032903c8083703880e41fafdc600ad42808080808001841001220229000021062002290008211c2002103541e8adc400ad4280808080a0018410012202290000211d2002290008211f200210352003201f3703b00b2003201d3703a80b2003201c3703a00b200320063703980b200341b0106a200341980b6a10dc0220032802b0102205410820051b210741beb9c300ad4280808080a001842106419806210241032104200120032902b410420020051b221c422088a74f0d13200720014106746a2205450d13024020052903004201510d0041beb9c300ad4280808080a0018421060c140b0240200720014106746a2202290308201b58200241106a2903002206201a582006201a511b0d0041b4b9c300ad4280808080a00184210641980821020c140b200341c0006a200341880e6a10b504200341b0106a20032802402205200328024810d402200341d0036a200341b0106a41a402109d081a200341b0036a41086a200341dd126a290000370300200341b0036a41106a200341e5126a290000370300200341b0036a41176a2208200341ec126a280000360000200320032900d5123703b00302400240024002400240024020032d00d41222094102460d00200241086a210b20034188016a200341d0036a41a402109d081a200341e8006a41176a2008280000360000200341e8006a41106a2202200341b0036a41106a290300370300200341e8006a41086a2204200341b0036a41086a290300370300200320032903b00337036802402003280244450d00200510350b200341c8086a41066a20034188016a41a402109d081a20034198066a200341c8086a41aa02109d081a200341f8056a41176a2205200341e8006a41176a280000360000200341f8056a41106a22082002290300370300200341f8056a41086a22022004290300370300200320032903683703f805200341980b6a20034198066a41066a41a402109d081a200341980b6a41a4026a20093a0000200341bd0d6a20032903f805370000200341c50d6a2002290300370000200341cd0d6a2008290300370000200341d40d6a2005280000360000200b41086a290300211a200b290300211b20032802a80b210941002102200341b00b6a280200220a41014b0d01200a0e020302030b02402003280244450d00200510350b41aab9c300ad4280808080a00184210641980a21020c180b200a2104034020022004410176220520026a2208200920084105746a28020020014b1b2102200420056b220441014b0d000b0b200920024105746a220528020022042001460d01200a200220042001496a2202490d0d0b0240200a200341ac0b6a280200470d00200341980b6a41106a200a410110a10120032802a80b21090b200920024105746a220441206a2004200a20026b410574109e081a200441186a201a370300200441106a201b37030020044201370308200420013602002003200a41016a220a3602b00b0c010b200a20024d0d0c0240200920024105746a2208280208417f6a220c41054b0d00419bb9c300ad4280808080f00184210641980c210241032104200c0e06140000000014140b200841086a420137030020052001360200200841186a201a370300200841106a201b3703000b200b29030021062003200b41086a290300221a3703a00620032006370398062003200341880e6a3602880102402006201a844200510d002003200341880e6a3602d0032003200341d0036a3602b810200320034188016a3602b410200320034198066a3602b010200341c8086a200341880e6a200341b0106a108c030240024020032802c8084101470d0020032f00cd0820032d00cf08411074722102200341d0086a290300210620032d00cc0821040c010b410421040240200341c8086a41086a2903004201520d00200341c8086a41106a290300210620032802d0032102200341e8106a200341c8086a41186a290300370300200341e0106a2006370300200341b0106a41086a41003a0000200341b9106a2002290000370000200341c1106a200241086a290000370000200341c9106a200241106a290000370000200341d1106a200241186a290000370000200341033a00b01041b0b4cc004100200341b0106a10d4010b0b200441ff01714104470d130b200341bc0b6a3502002106200341b0106a200341980b6a41c002109d081a200341c8086a200341880e6a10b50420032802c8082102200320032802d00836029c062003200236029806200341b0106a20034198066a10b004024020032802cc08450d00200210350b200aad211a0240200341c4106a28020041ffffff3f71450d0020032802c01010350b200341cc106a10a304200341b0106a41086a41033a0000200341b9106a20032903880e370000200341c9106a200341880e6a41106a290300370000200341d1106a200341a00e6a290300370000200341dc106a2001360200200341880e6a41086a290300211b200341113a00b010200341b0106a41116a201b37000041b0b4cc004100200341b0106a10d401201a42b0901f7e200642a0e1e7007e7c4280b191e4007c21060240201c42ffffff1f83500d00200710350b20004201370308200041106a2006370300200042003703000c170b410221040c130b02400240024002400240024020022d00000d0020022d00014101470d00200141046a2802002107200241196a2d00002101200241186a2d00002104200241166a2f01002105200241156a2d00002108200241146a2d00002109200241126a2f0100210a200241116a2d0000210b200241106a2d0000210c2002410e6a2f0100210d2002410d6a2d0000210e2002410c6a2d0000210f2002410a6a2f01002110200241096a2d00002111200241086a2d00002112200241066a2f01002113200241056a2d00002114200241046a2d00002115200241026a2f0100211620032002411a6a2901003703a00e200320013a009f0e200320043a009e0e200320053b019c0e200320083a009b0e200320093a009a0e2003200a3b01980e2003200b3a00970e2003200c3a00960e2003200d3b01940e2003200e3a00930e2003200f3a00920e200320103b01900e200320113a008f0e200320123a008e0e200320133b018c0e200320143a008b0e200320153a008a0e200320163b01880e200341e80d6a200341880e6a10b504200341b0106a20032802e80d220220032802f00d10d402200341d0036a200341b0106a41a402109d081a200341b0036a41086a2201200341dd126a290000370300200341b0036a41106a2204200341e5126a290000370300200341b0036a41176a2205200341ec126a280000360000200320032900d5123703b003024020032d00d41222084102460d0020034188016a200341d0036a41a402109d081a200341e8006a41176a2005280000360000200341e8006a41106a2004290300370300200341e8006a41086a2001290300370300200320032903b003370368024020032802ec0d450d00200210350b200341c8086a41066a20034188016a41a402109d081a20034198066a200341c8086a41aa02109d081a200341f8056a41176a2202200341e8006a41176a280000360000200341f8056a41106a2201200341e8006a41106a2903003703004108210a200341f8056a41086a2204200341e8006a41086a290300370300200320032903683703f805200341980b6a20034198066a41066a41a402109d081a200341980b6a41a4026a20083a0000200341bd0d6a20032903f805370000200341c50d6a2004290300370000200341cd0d6a2001290300370000200341d40d6a20022800003600004101210b41d0b9c300210c20032802a80b210841002102200341b00b6a280200220941014b0d0220090e020403040b024020032802ec0d450d00200210350b2003410a360248200341aab9c300360244200341053a004220034183303b01400c040b200341023a00400c030b20092101034020022001410176220420026a2205200820054105746a28020020074b1b2102200120046b220141014b0d000b0b200820024105746a2802002007470d00200920024d0d0d200820024105746a220141186a2903002106200141106a290300211a2001290308211b2001200141206a2002417f7320096a410574109e081a20032009417f6a22023602b00b201b4201510d02418db9c300210c410e210a4107210b0b2003200a3602482003200c3602442003200b3a004220034183303b01400240200341ac0b6a28020041ffffff3f71450d00200810350b200341b40b6a10a3040b200341f80a6a41086a200341c0006a41086a290300220637030020032003290340221a3703f80a20004200370308200041186a201a370300200041206a2006370300200042013703000c160b2003201a37039806200320063703a0060240201a200684500d002003200341880e6a3602d003200341c8086a200341880e6a20034198066a200341d0036a10f00220032903c8084201520d0020032903d0082106200341e8106a200341c8086a41106a290300370300200341e0106a2006370300200341b0106a41086a41003a0000200341b9106a20032903880e370000200341c1106a200341880e6a41086a290300370000200341c9106a200341880e6a41106a290300370000200341d1106a200341a00e6a290300370000200341033a00b01041b0b4cc004100200341b0106a10d4010b200341bc0b6a3502002106200341b0106a200341980b6a41c002109d081a200341c8086a200341880e6a10b50420032802c8082101200320032802d00836029c062003200136029806200341b0106a20034198066a10b004024020032802cc08450d00200110350b2002ad211a0240200341c4106a28020041ffffff3f71450d0020032802c01010350b200341cc106a10a304200341b0106a41086a41043a0000200341b9106a20032903880e370000200341c9106a200341880e6a41106a290300370000200341d1106a200341a00e6a290300370000200341dc106a2007360200200341880e6a41086a290300211b200341113a00b010200341b0106a41116a201b37000041b0b4cc004100200341b0106a10d401200041106a201a42b0901f7e200642a0e1e7007e7c4280b191e4007c37030020004201370308200042003703000c150b200141106a2903002106200141086a290300211a200141046a280200210420032002411a6a2901003703e008410221012003200241026a2901003703c80820032002410a6a2901003703d0082003200241126a2901003703d8080240024020022d00014101470d0020022d000041ff01710d00200341b0106a41186a200341c8086a41186a290300370300200341b0106a41106a200341c8086a41106a290300370300200341b0106a41086a200341c8086a41086a290300370300200320032903c8083703b01041fafdc600ad4280808080800184221b10012202290000211c2002290008211d2002103541e8adc400ad4280808080a00184221f10012202290000211e2002290008212020021035200320203703b00b2003201e3703a80b2003201d3703a00b2003201c3703980b200341c8086a200341980b6a10dc0220032802c8082205410820051b2102410121074183b02421010240200420032902cc08420020051b221d422088a722054f0d00200220044106746a2208450d0020082903004201520d000240200220044106746a220841206a2204200341b0106a460d002004200341b0106a412010a0080d010b200841086a2201201a3703002001200637030841002107200521010b201b1001220429000021062004290008211a20041035201f10012204290000211b2004290008211c200410352003201c3703b00b2003201b3703a80b2003201a3703a00b200320063703980b0240024020020d00200341980b6aad428080808080048410070c010b200341c8086a2002200510b404200341980b6aad428080808080048420033502d00842208620032802c8082204ad841002024020032802cc08450d00200410350b201d42ffffff1f83500d00200210350b2007450d010b20004200370308200041186a20013602002000411c6a41f1b8c300ad4280808080c00184370200200042013703000c150b20004201370308200041106a2001ad42b09f1a7e4280dbf23f7c370300200042003703000c140b410221040240024020022d00000d004101210520022d00014101470d00200141196a290000211d200141186a2d00002118200141176a2d00002119200141156a2f00002121200141146a2d00002122200141136a2d00002123200141116a2f00002124200141106a2d000021252001410f6a2d000021262001410d6a2f000021272001410c6a2d000021282001410b6a2d00002129200141096a2f0000212a200141086a2d0000212b200141076a2d0000212c200141056a2f0000212d200141046a2d0000212e200141036a2d0000212f200141246a280200210820012f00012130200241196a2d00002101200241186a2d00002104200241166a2f01002107200241156a2d00002109200241146a2d0000210a200241126a2f0100210b200241116a2d0000210c200241106a2d0000210d2002410e6a2f0100210e2002410d6a2d0000210f2002410c6a2d000021102002410a6a2f01002111200241096a2d00002112200241086a2d00002113200241066a2f01002114200241056a2d00002115200241046a2d00002116200241026a2f0100211720032002411a6a2901003703c810200320013a00c710200320043a00c610200320073b01c410200320093a00c3102003200a3a00c2102003200b3b01c0102003200c3a00bf102003200d3a00be102003200e3b01bc102003200f3a00bb10200320103a00ba10200320113b01b810200320123a00b710200320133a00b610200320143b01b410200320153a00b310200320163a00b210200320173b01b010200341980b6a41186a22094200370300200341980b6a41106a220a4200370300200341980b6a41086a22024200370300200342003703980b41fafdc600ad4280808080800184220610012201290000211a2002200141086a2900003703002003201a3703980b2001103541e8adc400ad4280808080a00184221a10012201290008211b2001290000211c20011035200341c8086a41106a220b201c370300200341c8086a41186a220c201b370300200341c8086a41086a220d2002290300370300200320032903980b3703c808200341980b6a200341c8086a10dc0220032802980b2207410820071b21014183b024210402402008200329029c0b420020071b221b422088a7220e4f0d00200120084106746a2207450d0020072903004201520d002003201d3703e008200320183a00df08200320193a00de08200320213b01dc08200320223a00db08200320233a00da08200320243b01d808200320253a00d708200320263a00d608200320273b01d408200320283a00d308200320293a00d2082003202a3b01d0082003202b3a00cf082003202c3a00ce082003202d3b01cc082003202e3a00cb082003202f3a00ca08200320303b01c8082003201d3703b00b200320183a00af0b200320193a00ae0b200320213b01ac0b200320223a00ab0b200320233a00aa0b200320243b01a80b200320253a00a70b200320263a00a60b200320273b01a40b200320283a00a30b200320293a00a20b2003202a3b01a00b2003202b3a009f0b2003202c3a009e0b2003202d3b019c0b2003202e3a009b0b2003202f3a009a0b200320303b01980b0240200341b0106a200120084106746a41206a2207460d002007200341b0106a412010a0080d010b200720032903980b370200200741186a200341980b6a41186a290300370200200741106a200341980b6a41106a290300370200200741086a200341980b6a41086a29030037020041002105200e21040b20094200370300200a420037030020024200370300200342003703980b20061001220729000021062002200741086a290000370300200320063703980b20071035201a1001220729000821062007290000211a20071035200b201a370300200c2006370300200d2002290300370300200320032903980b3703c8080240024020010d00200341c8086aad428080808080048410070c010b200341980b6a2001200e10b404200341c8086aad428080808080048420033502a00b42208620032802980b2202ad8410020240200328029c0b450d00200210350b201b42ffffff1f83500d00200110350b2005450d010b20004200370308200041186a20043602002000411c6a41f1b8c300ad4280808080c00184370200200042013703000c140b20004201370308200041106a2004ad42c0ed1a7e42e0ecb5c0007c370300200042003703000c130b200141086a2903002106200141046a280200210420032002411a6a2901003703e008410221012003200241026a2901003703c80820032002410a6a2901003703d0082003200241126a2901003703d8080240024020022d00014101470d0020022d000041ff01710d00200341b0106a41186a200341c8086a41186a290300370300200341b0106a41106a200341c8086a41106a290300370300200341b0106a41086a200341c8086a41086a290300370300200320032903c8083703b01041fafdc600ad4280808080800184221a10012202290000211b2002290008211c2002103541e8adc400ad4280808080a00184221d10012202290000211f2002290008211e200210352003201e3702b00b2003201f3702a80b2003201c3702a00b2003201b3702980b200341c8086a200341980b6a10dc0220032802c8082205410820051b2102410121074183b02421010240200420032902cc08420020051b221f422088a722054f0d00200220044106746a2208450d0020082903004201520d000240200220044106746a220841206a2204200341b0106a460d002004200341b0106a412010a0080d010b2008200637031841002107200521010b201a1001220429000021062004290008211a20041035201d10012204290000211b2004290008211c200410352003201c3702b00b2003201b3702a80b2003201a3702a00b200320063702980b0240024020020d00200341980b6aad428080808080048410070c010b200341c8086a2002200510b404200341980b6aad428080808080048420033502d00842208620032802c8082204ad841002024020032802cc08450d00200410350b201f42ffffff1f83500d00200210350b2007450d010b20004200370308200041186a20013602002000411c6a41f1b8c300ad4280808080c00184370200200042013703000c130b20004201370308200041106a2001ad42a0d1197e4280dbf23f7c370300200042003703000c120b200141c0006a290300211a200141386a290300211b200141306a2903002106200141046a2802002107200341880e6a41206a200141286a280200360200200341880e6a41186a200141206a290200370300200341880e6a41106a200141186a290200370300200341880e6a41086a200141106a2902003703002003200141086a2902003703880e4102210120022d00000d0a20022d00014101470d0a200241196a2d00002101200241186a2d00002104200241166a2f01002105200241156a2d00002108200241146a2d00002109200241126a2f0100210a200241116a2d0000210b200241106a2d0000210c2002410e6a2f0100210d2002410d6a2d0000210e2002410c6a2d0000210f2002410a6a2f01002110200241096a2d00002111200241086a2d00002112200241066a2f01002113200241056a2d00002114200241046a2d00002115200241026a2f0100211620032002411a6a2901003703900b200320013a008f0b200320043a008e0b200320053b018c0b200320083a008b0b200320093a008a0b2003200a3b01880b2003200b3a00870b2003200c3a00860b2003200d3b01840b2003200e3a00830b2003200f3a00820b200320103b01800b200320113a00ff0a200320123a00fe0a200320133b01fc0a200320143a00fb0a200320153a00fa0a200320163b01f80a200341b0106a41206a200341880e6a41206a280200360200200341b0106a41186a200341880e6a41186a29030037030041102102200341b0106a41106a200341880e6a41106a29030037030041082104200341b0106a41086a200341880e6a41086a290300370300200320032903880e3703b010200341980b6a200341b0106a108b02200341c8086a41086a2201200341a10b6a290000370300200341c8086a41106a2205200341a90b6a290000370300200341c8086a41186a2208200341b10b6a290000370300200320032900990b3703c80820032d00980b4101460d09200341c0006a41186a2008290300370300200341c0006a41106a2005290300370300200341c0006a41086a2001290300370300200320032903c8083703404103210141fdb8c300210520064201510d0b41fafdc600ad428080808080018410012202290000211c2002290008211d2002103541e8adc400ad4280808080a0018410012202290000211f2002290008211e200210352003201e3702b00b2003201f3702a80b2003201d3702a00b2003201c3702980b200341b0106a200341980b6a10dc0220032802b0102202410820021b2108024002400240024002400240200720032902b410420020021b221c422088a74f0d00200820074106746a2202450d0020022903004201520d000240200820074106746a41206a2202200341f80a6a460d002002200341f80a6a412010a0080d010b0240201c42ffffff1f83500d00200810350b200341e80d6a200341c0006a10b504200341b0106a20032802e80d220220032802f00d10d402200341d0036a200341b0106a41a402109d081a200341b0036a41086a2204200341dd126a290000370300200341b0036a41106a2205200341e5126a290000370300200341b0036a41176a2208200341ec126a280000360000200320032900d5123703b003024020032d00d41222094102460d0020034188016a200341d0036a41a402109d081a200341e8006a41176a2008280000360000200341e8006a41106a2005290300370300200341e8006a41086a2004290300370300200320032903b003370368024020032802ec0d450d00200210350b200341c8086a41066a20034188016a41a402109d081a20034198066a200341c8086a41aa02109d081a200341f8056a41176a2202200341e8006a41176a280000360000200341f8056a41106a2201200341e8006a41106a290300370300200341f8056a41086a2204200341e8006a41086a290300370300200320032903683703f805200341980b6a20034198066a41066a41a402109d081a200341980b6a41a4026a20093a0000200341bd0d6a20032903f805370000200341c50d6a2004290300370000200341cd0d6a2001290300370000200341d40d6a200228000036000020032802a80b210841002102200341b00b6a280200220941014b0d0220090e020403040b024020032802ec0d450d00200210350b410a210441e4b8c3002105410d21020c110b4109210441f1b8c3002105410c2102201c42ffffff1f83500d10200810350c100b20092101034020022001410176220420026a2205200820054105746a28020020074b1b2102200120046b220141014b0d000b0b200820024105746a220128020022042007460d012009200220042007496a2202490d0a0b02402009200341ac0b6a280200470d00200341980b6a41106a2009410110a10120032802a80b21080b200820024105746a220141206a2001200920026b410574109e081a200141186a201a370300200141106a201b37030020012006370308200120073602002003200941016a22093602b00b0c010b200920024d0d09200820024105746a220241086a2104024020022903084201520d00200341b0106a200341c0006a200341f80a6a200241106a290300200241186a290300410010ef020b2004200637030020012007360200200241186a201a370300200241106a201b3703000b200341bc0b6a3502002106200341b0106a200341980b6a41c002109d081a200341c8086a200341c0006a10b50420032802c8082102200320032802d00836029c062003200236029806200341b0106a20034198066a10b004024020032802cc08450d00200210350b2009ad211a0240200341c4106a28020041ffffff3f71450d0020032802c01010350b200341cc106a10a304200341b0106a41086a41053a0000200341b9106a2003290340370000200341c9106a200341c0006a41106a290300370000200341d1106a200341d8006a290300370000200341dc106a2007360200200341c0006a41086a290300211b200341113a00b010200341b0106a41116a201b37000041b0b4cc004100200341b0106a10d401200041106a201a4280b5187e200642a0e1e7007e7c42c0fff1de007c37030020004201370308200042003703000c110b200341e0006a200141246a280200360200200341d8006a2001411c6a290200370300200341c0006a41106a200141146a290200370300200341c8006a2001410c6a2902003703002003200141046a29020037034041022101200241036a2d0000210520022f000121070240024002400240024002400240024020022d00002208417f6a220441024b0d00024020040e03000102000b200241086a2802004101742002410c6a2802004d0d00200241046a28020041ff0171450d010b200720054110747220084100477241ff01710d010b200341b0106a41206a200341c0006a41206a280200360200200341b0106a41186a200341c0006a41186a290300370300200341b0106a41106a200341c0006a41106a290300370300200341b0106a41086a200341c0006a41086a290300370300200320032903403703b010200341980b6a200341b0106a108b0241012105024020032d00980b4101460d00200341980b6a41086a2d00002102200341a10b6a2f00002101200341a30b6a2d00002104200341a40b6a2d00002107200341a50b6a2f00002108200341a70b6a2d00002109200341980b6a41106a2d0000210a200341a90b6a2f0000210b200341ab0b6a2d0000210c200341ac0b6a2d0000210d200341ad0b6a2f0000210e200341af0b6a2d0000210f200341980b6a41186a2d0000211020032f00990b211120032d009b0b211220032d009c0b211320032f009d0b211420032d009f0b21152003200341b10b6a2900003703900b200320103a008f0b2003200f3a008e0b2003200e3b018c0b2003200d3a008b0b2003200c3a008a0b2003200b3b01880b2003200a3a00870b200320093a00860b200320083b01840b200320073a00830b200320043a00820b200320013b01800b200320023a00ff0a200320153a00fe0a200320143b01fc0a200320133a00fb0a200320123a00fa0a200320113b01f80a200341980b6a200341f80a6a10b604200341b0106a20032802980b220220032802a00b220110cc020240024020032802c01022040d004200211b4200211c4200211d0c010b2001ad4220862002ad841007200341b8106a290300211d20032903b010211c20032902c410211b200421050b0240200328029c0b450d00200210350b200341d80d6a200341f80a6a10b504200341b0106a20032802d80d220220032802e00d220410d402024020032d00d412220941024622010d002004ad4220862002ad8410070b200341880e6a200341b0106a41a402109d081a200341e80d6a41176a2204200341ec126a280000360000200341e80d6a41106a2207200341e5126a290000370300200341e80d6a41086a2208200341dd126a290000370300200320032900d5123703e80d200341d0036a200341880e6a41a402109d081a200341b0036a41176a220a2004280000360000200341b0036a41106a22042007290300370300200341b0036a41086a22072008290300370300200320032903e80d3703b003024020010d0020034188016a200341d0036a41a402109d081a200341e8006a41176a200a280000360000200341e8006a41106a2004290300370300200341e8006a41086a2007290300370300200320032903b003370368024020032802dc0d450d00200210350b200341c8086a41066a20034188016a41a402109d081a20034198066a200341c8086a41aa02109d081a200341f8056a41176a2202200341e8006a41176a280000360000200341f8056a41106a2201200341e8006a41106a290300370300200341f8056a41086a2204200341e8006a41086a290300370300200320032903683703f805200341980b6a20034198066a41066a41a402109d081a200341980b6a41a4026a20093a0000200341bd0d6a20032903f805370000200341c50d6a2004290300370000200341cd0d6a2001290300370000200341d40d6a2002280000360000200341980b6a41086a290300211e20032903980b211f20032802a80b210702400240200341b00b6a280200220841057422010d00420021064200211a0c010b200741106a2102420021064200211a0340200241086a2903004200200241786a29030042015122041b201a7c2002290300420020041b221a20067c2206201a54ad7c211a200241206a2102200141606a22010d000b0b201e201d7c201f201c7c221c201f54ad7c201a7c201c20067c2206201c54ad7c211a0240201b422088221ca72202450d0020024105742101200521020340200341b0106a200210970420033502b81042208620032802b0102204ad841007024020032802b410450d00200410350b200241206a2102200141606a22010d000b0b20032006370398062003201a3703a0062006201a844200520d03200342003703d008200342003703c8080c040b024020032802dc0d450d00200210350b0240201b42ffffff3f83500d00200510350b410321010c010b410121010b20004198043b001920004200370308200041206a41083602002000411c6a41c8b9c300360200200041186a20013a0000420121060c040b2003200341f80a6a3602880e200341c8086a200341f80a6a20034198066a200341880e6a10a802200341e8086a290300211d20032903e008211f024020032903c8084201520d0020032903d008211e200341e8106a200341c8086a41106a290300370300200341e0106a201e370300200341b0106a41086a41003a0000200341b9106a20032903f80a370000200341c1106a200341f80a6a41086a290300370000200341c9106a200341f80a6a41106a290300370000200341d1106a200341900b6a290300370000200341033a00b01041b0b4cc004100200341b0106a10d4010b2003201f3703c8082003201d3703d008201f201d844200520d010b20034198066a41186a220a420037030020034198066a41106a2204420037030020034198066a41086a22014200370300200342003703980641b6fdc600ad4280808080800184221d10012209290000211f200341b0106a41086a2202200941086a2900003703002003201f3703b0102009103520012002290300370300200320032903b0103703980641e489c200ad4280808080d00184221f10012209290000211e2002200941086a2900003703002003201e3703b01020091035200420032903b010221e370300200341880e6a41086a220b2001290300370300200341880e6a41106a220c201e370300200341880e6a41186a220d200229030037030020032003290398063703880e200341286a200341880e6a412010d701200341286a41106a290300211e2003290330212020032802282109200a420037030020044200370300200142003703002003420037039806201d1001220a290000211d2002200a41086a2900003703002003201d3703b010200a103520012002290300370300200320032903b01037039806201f1001220a290000211d2002200a41086a2900003703002003201d3703b010200a1035200420032903b010221d370300200b2001290300370300200c201d370300200d200229030037030020032003290398063703880e2003201e420020091b3703b81020032020420020091b3703b010200341880e6aad4280808080800484200341b0106aad428080808080028410020c010b200342f0f2bda1a7ee9cb9f9003703c808200341b0106a200341c8086a10e001200341b0106a201f201d10df01200341c8106a201d370300200341c0106a201f370300200341b8106a41063a00002003410c3a00b01041b0b4cc004100200341b0106a10d4010b200341e8106a201a370300200341e0106a2006370300200341b0106a41086a41023a0000200341b9106a20032903f80a370000200341f80a6a41086a2903002106200341113a00b010200341b0106a41116a2006370000200341c9106a200341880b6a290300370000200341d1106a200341900b6a29030037000041b0b4cc004100200341b0106a10d401201c42c0d89e017e2008ad42a08d067e7c201c4280c2d72f7e7c200341bc0b6a35020042a0f7367e7c2106200341b40b6a21020240200341ac0b6a28020041ffffff3f71450d00200710350b200642c086a2e7017c2106200210a3040240201b42ffffff3f83500d00200510350b200041106a200637030020004201370308420021060b200020063703000c100b2005200841f485cc001042000b103c000b103e000b2002200a104d000b2002200a41a0bdc4001042000b20022009104e000b20022009104d000b2002200941b0bdc4001042000b410121010b0b200041206a20023602002000411c6a2005360200200020043a001a200041183a0019200041186a20013a000020004200370308200042013703000c050b0240200341ac0b6a28020041ffffff3f71450d00200910350b200341b40b6a10a3040b201c42ffffff1f83500d00200710350b200020023b00192000200637021c200042003703082000411b6a20024110763a0000200041186a20043a0000200042013703000c020b0b02402007450d00200741c4006c2101200841286a210203400240200241786a2d00004101470d002002280200450d002002417c6a28020010350b200241c4006a2102200141bc7f6a22010d000b0b02402005450d00200541c4006c450d00200810350b200020043b00192000200637021c200042003703082000411b6a20044110763a0000200041186a20093a0000200042013703000b200341f0126a24000b950202037f017e230041206b220324000240024020024106744104722204417f4c0d00200410332205450d0120034100360208200320043602042003200536020020022003107702402002450d002002410674210203400240024020012903004201510d00200341003a00102003200341106a410110780c010b200341013a00102003200341106a410110782003200141206a41201078200141086a29030021062003200141106a290300370318200320063703102003200341106a411010782003200141186a2903003703102003200341106a410810780b200141c0006a2101200241406a22020d000b0b20002003290300370200200041086a200341086a280200360200200341206a24000f0b1044000b1045000bb10503027f017e047f230041d0006b2202240041fafdc600ad4280808080800184100122032900002104200241086a41086a200341086a290000370300200220043703082003103541c8acc400ad4280808080a00184100122032900002104200241186a41086a200341086a29000037030020022004370318200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad42808080808004841003220129000037033820011035200241cc006a200341206a360200200220033602482002200241386a41086a3602442002200241386a360240200241286a200241c0006a107b200310352002280230220541206a2201417f4c0d01200228022821060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a2000200136020820002008360204200020033602000240200228022c450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000bb10503027f017e047f230041d0006b2202240041fafdc600ad4280808080800184100122032900002104200241086a41086a200341086a290000370300200220043703082003103541b8adc400ad4280808080e00084100122032900002104200241186a41086a200341086a29000037030020022004370318200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad42808080808004841003220129000037033820011035200241cc006a200341206a360200200220033602482002200241386a41086a3602442002200241386a360240200241286a200241c0006a107b200310352002280230220541206a2201417f4c0d01200228022821060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a2000200136020820002008360204200020033602000240200228022c450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000b13002000410d360204200041c0bdc4003602000b1f0002402000280200450d00200041086a280200450d00200028020410350b0b8c0a03047f017e047f23004190016b22022400200241d8006a41186a4200370300200241d8006a41106a22034200370300200241d8006a41086a220442003703002002420037035841a3edcb00ad4280808080f000841001220529000021062004200541086a290000370300200220063703582005103541a5ebcb00ad4280808080c00184100122052900002106200241f8006a41086a2207200541086a2900003703002002200637037820051035200320022903782206370300200241386a41086a2004290300370300200241386a41106a2006370300200241386a41186a200729030037030020022002290358370338200241106a200241386a412010c001200241d8006a2002280214410020022802101b2203200010ba04200241086a20022802582204200228026041b0b4cc0041004100108a02200228020821050240200228025c450d00200410350b410121040240024002400240024020054101460d004188e8cb00ad4280808080800184100122042900002106200241f8006a41086a200441086a290000370300200220063703782004103541f1c8c400ad4280808080e00184100122042900002106200241386a41086a200441086a2900003703002002200637033820041035200220033602282002200241286aad4280808080c00084100322042900003703880120041035200241e4006a22052002412c6a360200200220024188016a41086a220036025c2002200241286a360260200220024188016a360258200241186a200241d8006a107b412010332204450d0120042001290000370000200441186a200141186a290000370000200441106a200141106a290000370000200441086a200141086a29000037000020022004ad42808080808004841003220129000037038801200110352005200441206a360200200220043602602002200036025c200220024188016a360258200241286a200241d8006a107b200410352002280220220741206a2200200228023022086a2201417f4c0d02200228022821092002280218210a0240024020010d0041002103410121040c010b200110332204450d02200121030b024002402003410f4d0d00200321050c010b200341017422054110200541104b1b22054100480d04024020030d002005103322040d010c060b20032005460d0020042003200510372204450d050b20042002290378370000200441086a200241f8006a41086a2903003700000240024020054170714110460d00200521030c010b200541017422034120200341204b1b22034100480d0420052003460d0020042005200310372204450d050b20042002290338370010200441186a200241386a41086a29030037000002400240200341606a2007490d00200321050c010b2007415f4b0d04200341017422052000200520004b1b22054100480d0420032005460d0020042003200510372204450d050b200441206a200a2007109d081a02400240200520006b2008490d00200521030c010b20012000490d04200541017422032001200320014b1b22034100480d04024020050d00024020030d00410121040c020b200310332204450d060c010b20052003460d0020042005200310372204450d050b200420006a20092008109d081a0240200228022c450d00200910350b0240200228021c450d00200a10350b20022004200110c001200228020421012002280200210502402003450d00200410350b200141004720054100477121040b20024190016a240020040f0b1045000b1044000b103e000b103c000bf60603027f017e077f230041e0006b220324004188e8cb00ad4280808080800184100122042900002105200341086a41086a200441086a29000037030020032005370308200410354190e8cb00ad4280808080a00284100122042900002105200341186a41086a200441086a2900003703002003200537031820041035200320013602382003200341386aad4280808080c000841003220429000037034820041035200341dc006a2204200341386a41046a3602002003200341c8006a41086a22013602542003200341386a3602582003200341c8006a360250200341286a200341d0006a107b200320023602442003200341c4006aad4280808080c0008410032202290000370348200210352004200341c4006a41046a360200200320013602542003200341c4006a3602582003200341c8006a360250200341386a200341d0006a107b02400240024002402003280230220641206a2207200328024022086a2202417f4c0d00200328023821092003280228210a0240024020020d004100210b410121040c010b200210332204450d022002210b0b02400240200b410f4d0d00200b21010c010b200b41017422014110200141104b1b22014100480d030240200b0d002001103322040d010c050b200b2001460d002004200b200110372204450d040b20042003290308370000200441086a200341086a41086a2903003700000240024020014170714110460d002001210b0c010b2001410174220b4120200b41204b1b220b4100480d032001200b460d0020042001200b10372204450d040b20042003290318370010200441186a200341186a41086a29030037000002400240200b41606a2006490d00200b21010c010b200641206a22012006490d03200b410174220c2001200c20014b1b22014100480d03200b2001460d002004200b200110372204450d040b200441206a200a2006109d081a02400240200120076b2008490d002001210b0c010b20022007490d032001410174220b2002200b20024b1b220b4100480d03024020010d000240200b0d00410121040c020b200b10332204450d050c010b2001200b460d0020042001200b10372204450d040b200420076a20092008109d081a200020023602082000200b360204200020043602000240200328023c450d00200910350b0240200328022c450d00200a10350b200341e0006a24000f0b1044000b1045000b103e000b103c000bae0707017f017e067f017e047f017e027f230041306b220124000240024010292202422088a722030d00410121040c010b2002a721040b2001200336022420012004360220024002400240024002402003450d0020042d0000210520012003417f6a3602242001200441016a360220200541014b0d00024020050e020004000b200141186a200141206a10c40120012802180d0020012802242206200128021c2205490d002005417f4c0d020240024020050d0042002102410121070c010b200510392207450d022007200128022022082005109d081a2001200620056b3602242001200820056a3602202005ad21020b2007450d00200141106a200141206a10c4012005ad4220862002842209a7210a024020012802100d002001280214220b2001280224410c6e22052005200b4b1bad420c7e2202422088a70d032002a72205417f4c0d030240024020050d004104210c0c010b20051033220c450d030b2005410c6ead21020240200b450d000340200141086a200141206a10c40102400240024020012802080d0020012802242206200128020c2205490d002005417f4c0d080240024020050d004100210d410121080c010b200510392208450d0820082001280220220d2005109d081a2001200620056b3602242001200d20056a3602202005210d0b2002422088220ea722062002a7470d02024002400240200641016a220f2006490d00200ea74101742210200f200f2010491bad420c7e220e422088a70d00200ea7220f4100480d00024020060d00200f0d024104210c0c050b2006410c6c2206200f460d04024020060d00200f0d024104210c0c050b200c2006200f1037220c450d020c040b103e000b200f1033220c0d020b103c000b02402002422088a72205450d002005410c6c2106200c210503400240200541046a280200450d00200528020010350b2005410c6a2105200641746a22060d000b0b2002a72205450d042005410c6c450d04200c10350c040b2002422088220ea72106200f410c6ead21020b200c2006410c6c6a22062005ad422086200dad8437020420062008360200200e422086200242ffffffff0f83844280808080107c2102200b417f6a220b0d000b0b200c450d002007450d012009422088a721050c050b200a450d00200710350b41b89acc00412e200141286a41c09bcc0041e89acc001046000b1045000b1044000b410021070b2000200a36020420002007360200200041106a20023702002000410c6a200c360200200041086a200536020002402003450d00200410350b200141306a24000b970403017f017e017f23004190016b22052400200520013602040240200541046a20022004ad4220862003ad8410322206422088a72201450d002006a722072d0000220341014b0d004100210202400240024020030e020100010b41002102200541003a008801200741016a21042001417f6a2101034020012002460d02200541c8006a20026a200420026a2d00003a00002005200241016a22033a00880120032102200341c000470d000b200541086a41386a200541c8006a41386a290300370300200541086a41306a200541c8006a41306a290300370300200541086a41286a200541c8006a41286a290300370300200541086a41206a200541c8006a41206a290300370300200541086a41186a200541c8006a41186a290300370300200541086a41106a200541c8006a41106a290300370300200541086a41086a200541c8006a41086a29030037030020052005290348370308410121020b200020023a000020002005290308370001200041096a200541106a290300370000200041116a200541186a290300370000200041196a200541206a290300370000200041216a200541286a290300370000200041296a200541306a290300370000200041316a200541386a290300370000200041396a200541c0006a2903003700002007103520054190016a24000f0b200241ff0171450d00200541003a0088010b41b89acc00412e200541c8006a41c09bcc0041e89acc001046000bac0501077f23004190016b2202240002400240024002402000410c6a2802002203417f4c0d0020002802042104200028020021050240024020030d0041002106410121070c010b200310332207450d02200321060b0240024020062003490d00200621080c010b200641017422082003200820034b1b22084100480d03024020060d002008103322070d010c050b20062008460d0020072006200810372207450d040b200720042003109d082106200241f8006a200041106a10a603200241106a410c6a2003360200200241106a41086a22032008360200200241206a2002290378370300200241286a2208200241f8006a41086a280200360200200241106a41306a200041306a290200370300200241106a41386a200041386a290200370300200241106a41c0006a200041c0006a290200370300200241106a41c8006a200041c8006a290200370300200241106a41d0006a200041d0006a290200370300200241106a41d8006a200041d8006a290200370300200241106a41e0006a200041e0006a2902003703002002200636021420022005360210200220002802243602342002200029021c37022c200220002902283703382002410c6a4110360200200241fcc7c400360200200241043602042001411c6a28020021002002200241106a360208200128021821062002418c016a41023602002002420237027c20024190cec400360278200220023602880120062000200241f8006a1043210602402003280200450d00200228021410350b024020082802002203450d00200228022021002003410c6c210303400240200041046a280200450d00200028020010350b2000410c6a2100200341746a22030d000b0b0240200241246a2802002200450d002000410c6c450d00200228022010350b20024190016a240020060f0b1044000b1045000b103e000b103c000b980201027f230041206b220224002002200128021841b0b4cc0041002001411c6a28020028020c1100003a00102002200136020841012101200241013a00112002410036020c200220003602182002200041286a36021c200241086a200241186a41a0cec400106f2002411c6a41b0cec400106f1a20022d0010210002400240200228020c22030d00200021010c010b0240200041ff01710d00024020034101470d0020022d001141ff0171450d00200228020822002d00004104710d0041012101200028021841d6a0c00041012000411c6a28020028020c1100000d010b2002280208220128021841cca6cc0041012001411c6a28020028020c11000021010b200220013a00100b200241206a2400200141ff01714100470b1c00200128021841ed9dcc00410f2001411c6a28020028020c1100000bed93010a047f017e017f017e077f017e1f7f057e047f017e230041b0066b22002400200041a0056a41186a22014200370300200041a0056a41106a22024200370300200041a0056a41086a22034200370300200042003703a00541a3edcb00ad4280808080f0008422041001220529000021062003200541086a290000370300200020063703a0052005103541a5ebcb00ad4280808080c0018410012205290000210620004180046a41086a2207200541086a29000037030020002006370380042005103520022000290380042206370300200041d0046a41086a22082003290300370300200041d0046a41106a22092006370300200041d0046a41186a220a2007290300370300200020002903a0053703d004200041206a200041d0046a412010c0012000280224210b2000280220210c200142003703002002420037030020034200370300200042003703a0054188e8cb00ad42808080808001841001220529000021062003200541086a290000370300200020063703a00520051035418fd1cb00ad4280808080c000841001220529000021062007200541086a290000370300200020063703800420051035200220002903800422063703002008200329030037030020092006370300200a2007290300370300200020002903a0053703d004200041a0056a200041d0046a10d80220002802a005210d20002902a405210e200142003703002002420037030020034200370300200042003703a00520041001220529000021042003200541086a290000370300200020043703a0052005103541f393ca00ad4280808080a001841001220529000021042007200541086a290000370300200020043703800420051035200220002903800422043703002008200329030037030020092004370300200a2007290300370300200020002903a0053703d004200041a0056a200041d0046a10fe0120002802a0052205410120051b210f20002902a405420020051b2204a72110024002400240024002400240024002402004422088a72205450d00200f200541057422116a211220004194016a2113200041d0046a41206a211420004198036a4104722115200041e0026a41047221164102210541002117034020004180026a41186a200f20176a221841186a221929000037030020004180026a41106a201841106a221a29000037030020004180026a41086a201841086a221b290000370300200020182900003703800220162018290000370000201641086a201b290000370000201641106a201a290000370000201641186a201929000037000020002005417e6a221a3602e002410021190240201a201610b9040d0020004198036a41206a200041e0026a41206a28020036020020004198036a41186a200041e0026a41186a29030037030020004198036a41106a200041e0026a41106a29030037030020004198036a41086a200041e0026a41086a290300370300200020002903e00237039803200041a0026a41186a2219201541186a221a290000370300200041a0026a41106a221b201541106a221c290000370300200041a0026a41086a221d201541086a221e290000370300200020152900003703a002200a201a2900003703002009201c2900003703002008201e290000370300200020152900003703d004200041f0006a200041d0046a108402200041c0026a41186a221a2019290300370300200041c0026a41106a221c201b290300370300200041c0026a41086a221b201d290300370300200020002903a0023703c0022000280290012219450d0020142000290370370300201441186a200041f0006a41186a290300370300201441106a200041f0006a41106a290300370300201441086a200041f0006a41086a290300370300200a201a2903003703002009201c2903003703002008201b290300370300200041a0066a41086a221a201341086a280200360200200020002903c0023703d004200020132902003703a006200041a0056a41386a221b200041d0046a41386a290300370300200041a0056a41306a221c200041d0046a41306a290300370300200041a0056a41286a221d200041d0046a41286a290300370300200041a0056a41206a221e20142903003703002001200a2903003703002002200929030037030020032008290300370300200020002903d0043703a00520004180046a41386a201b29030037030020004180046a41306a201c29030037030020004180046a41286a201d29030037030020004180046a41206a201e29030037030020004180046a41186a200129030037030020004180046a41106a200229030037030020072003290300370300200020002903a00537038004200041386a41086a201a280200360200200020002903a0063703380b200041c0036a41086a2007290300370300200041c0036a41106a20004180046a41106a290300370300200041c0036a41186a20004180046a41186a290300370300200041c0036a41206a20004180046a41206a290300370300200041c0036a41286a20004180046a41286a290300370300200041c0036a41306a20004180046a41306a290300370300200041c0036a41386a20004180046a41386a29030037030020004188036a41086a200041386a41086a28020036020020002000290380043703c003200020002903383703880320190d02200541016a21052011201741206a2217470d000b0b2000410036023020004208370328201041ffffff3f71450d01200f10350c010b200041b0016a41386a2216200041c0036a41386a290300370300200041b0016a41306a2215200041c0036a41306a290300370300200041b0016a41286a221a200041c0036a41286a290300370300200041b0016a41206a221b200041c0036a41206a290300370300200041b0016a41186a2207200041c0036a41186a290300370300200041b0016a41106a2203200041c0036a41106a290300370300200041b0016a41086a2208200041c0036a41086a290300370300200041f0016a41086a220920004188036a41086a280200360200200020002903c0033703b00120002000290388033703f001200041e0006a41086a220a2009280200360200200020002903f001370360200041a0056a41086a22092008290300370300200041a0056a41106a22082003290300370300200041a0056a41186a22032007290300370300200041a0056a41206a221c201b290300370300200041a0056a41286a221b201a290300370300200041a0056a41306a221a2015290300370300200041a0056a41386a22152016290300370300200020002903b0013703a005200041d0046a41086a2216200a280200360200200020002903603703d00441d00010332207450d01200720002903a00537030020072019360240200720002903d004370244200741386a2015290300370300200741306a201a290300370300200741286a201b290300370300200741206a201c290300370300200741186a2003290300370300200741106a2008290300370300200741086a2009290300370300200741cc006a20162802003602002000428180808010370254200020073602500240201141606a2017460d00201841206a2116201120176b41606a211b200041d4016a211c20004198036a4104722115200041e0026a4104722118034020004180026a41186a201641186a221729000037030020004180026a41106a201641106a221929000037030020004180026a41086a201641086a221a290000370300200020162900003703800220162900002104201841186a201729000037000020182004370000201841086a201a290000370000201841106a201929000037000020002005417f6a22193602e0024100211702402019201810b9040d0020004198036a41206a200041e0026a41206a28020036020020004198036a41186a200041e0026a41186a29030037030020004198036a41106a200041e0026a41106a29030037030020004198036a41086a200041e0026a41086a290300370300200020002903e00237039803200041a0026a41186a2217201541186a221a290000370300200041a0026a41106a2208201541106a2203290000370300200041a0026a41086a2209201541086a220a290000370300200020152900003703a002200041d0046a41186a2219201a290000370300200041d0046a41106a221a2003290000370300200041d0046a41086a2203200a290000370300200020152900003703d004200041b0016a200041d0046a108402200041c0026a41186a220a2017290300370300200041c0026a41106a22112008290300370300200041c0026a41086a22082009290300370300200020002903a0023703c00220002802d0012217450d00201420002903b001370300201441186a200041b0016a41186a290300370300201441106a200041b0016a41106a290300370300201441086a200041b0016a41086a2903003703002019200a290300370300201a201129030037030020032008290300370300200041a0066a41086a2208201c41086a280200360200200020002903c0023703d0042000201c2902003703a006200041a0056a41386a2209200041d0046a41386a290300370300200041a0056a41306a220a200041d0046a41306a290300370300200041a0056a41286a2211200041d0046a41286a290300370300200041a0056a41206a221d200041d0046a41206a290300370300200041a0056a41186a221e2019290300370300200041a0056a41106a2219201a290300370300200041a0056a41086a221a2003290300370300200020002903d0043703a00520004180046a41386a200929030037030020004180046a41306a200a29030037030020004180046a41286a201129030037030020004180046a41206a201d29030037030020004180046a41186a201e29030037030020004180046a41106a201929030037030020004180046a41086a201a290300370300200020002903a00537038004200041386a41086a2008280200360200200020002903a0063703380b200041c0036a41086a20004180046a41086a290300370300200041c0036a41106a20004180046a41106a290300370300200041c0036a41186a20004180046a41186a290300370300200041c0036a41206a20004180046a41206a290300370300200041c0036a41286a20004180046a41286a290300370300200041c0036a41306a20004180046a41306a290300370300200041c0036a41386a20004180046a41386a29030037030020004188036a41086a200041386a41086a28020036020020002000290380043703c0032000200029033837038803024020170d00201641206a2116200541016a2105201b41606a221b0d010c020b0b200041f0006a41386a221f200041c0036a41386a2203290300370300200041f0006a41306a2220200041c0036a41306a2208290300370300200041f0006a41286a2221200041c0036a41286a2209290300370300200041f0006a41206a2222200041c0036a41206a220a290300370300200041f0006a41186a2223200041c0036a41186a2211290300370300200041f0006a41106a2224200041c0036a41106a221c290300370300200041f0006a41086a2225200041c0036a41086a221d290300370300200041f0016a41086a222620004188036a41086a221e280200360200200020002903c00337037020002000290388033703f001200041e0006a41086a22272026280200360200200020002903f001370360201641206a2116200041d4016a212820004198036a4104722115200041e0026a410472211841012119410121290340200041b0016a41086a222a2025290300370300200041b0016a41106a222b2024290300370300200041b0016a41186a222c2023290300370300200041b0016a41206a221a2022290300370300200041b0016a41286a221b2021290300370300200041b0016a41306a22012020290300370300200041b0016a41386a2213201f290300370300200020002903703703b001200041a0056a41086a222d2027280200360200200020002903603703a005024020292019470d00200041d0006a2019410110a301200028025021070b2007202941d0006c6a221920002903b001370300202b2903002104202c2903002106201a290300212e201b290300212f2001290300213020132903002131202a290300213220192017360240201941086a2032370300201920002903a005370244201941cc006a202d280200360200201941386a2031370300201941306a2030370300201941286a202f370300201941206a202e370300201941186a2006370300201941106a20043703002000202941016a222936025820162012460d01034020004180026a41186a201641186a221729000037030020004180026a41106a201641106a221929000037030020004180026a41086a201641086a221a2900003703002000201629000037038002200020053602e002201a2900002104201929000021062016290000212e201841186a2017290000370000201841106a2006370000201841086a20043700002018202e3700004100211702402005201810b9040d0020004198036a41206a200041e0026a41206a28020036020020004198036a41186a200041e0026a41186a29030037030020004198036a41106a200041e0026a41106a29030037030020004198036a41086a200041e0026a41086a290300370300200020002903e00237039803200041a0026a41186a2217201541186a221a290000370300200041a0026a41106a2201201541106a221b290000370300200041a0026a41086a2213201541086a2233290000370300200020152900003703a002200041d0046a41186a2219201a290000370300200041d0046a41106a221a201b290000370300200041d0046a41086a221b2033290000370300200020152900003703d004200041b0016a200041d0046a108402200041c0026a41186a22332017290300370300200041c0026a41106a22342001290300370300200041c0026a41086a22012013290300370300200020002903a0023703c00220002802d0012217450d00201420002903b001370300201441186a202c290300370300201441106a202b290300370300201441086a202a29030037030020192033290300370300201a2034290300370300201b2001290300370300200041a0066a41086a2201202841086a280200360200200020002903c0023703d004200020282902003703a006200041a0056a41386a2213200041d0046a41386a290300370300200041a0056a41306a2233200041d0046a41306a290300370300200041a0056a41286a2234200041d0046a41286a290300370300200041a0056a41206a2235200041d0046a41206a290300370300200041a0056a41186a22362019290300370300200041a0056a41106a2219201a290300370300202d201b290300370300200020002903d0043703a00520004180046a41386a201329030037030020004180046a41306a203329030037030020004180046a41286a203429030037030020004180046a41206a203529030037030020004180046a41186a203629030037030020004180046a41106a201929030037030020004180046a41086a202d290300370300200020002903a00537038004200041386a41086a2001280200360200200020002903a0063703380b201d20004180046a41086a290300370300201c20004180046a41106a290300370300201120004180046a41186a290300370300200a20004180046a41206a290300370300200920004180046a41286a290300370300200820004180046a41306a290300370300200320004180046a41386a290300370300201e200041386a41086a28020036020020002000290380043703c0032000200029033837038803024020170d00200541016a21052012201641206a2216470d010c030b0b201f200329030037030020202008290300370300202120092903003703002022200a290300370300202320112903003703002024201c2903003703002025201d2903003703002026201e280200360200200020002903c00337037020002000290388033703f00120272026280200360200200020002903f001370360201641206a2116200541016a2105200028025421190c000b0b0240201041ffffff3f71450d00200f10350b200041286a41086a200041d0006a41086a280200360200200020002903503703280b200041a0056a41186a22174200370300200041a0056a41106a22154200370300200041a0056a41086a22054200370300200042003703a00541a3edcb00ad4280808080f000841001221629000021042005201641086a290000370300200020043703a0052016103541a5ebcb00ad4280808080c0018410012216290000210420004180046a41086a2218201641086a2900003703002000200437038004201610352002200029038004370000200241086a2018290300370000200041d0046a41086a22162005290300370300200041d0046a41106a2015290300370300200041d0046a41186a2017290300370300200020002903a0053703d004200041186a200041d0046a412010c001200028021c2117200028021821154188e8cb00ad42808080808001841001220529000021042018200541086a2900003703002000200437038004200510354190e8cb00ad4280808080a002841001220529000021042016200541086a290000370300200020043703d004200510354100211820002017410020151b3602702000200041f0006aad22044280808080c00084100322052900003703b00120051035200041ac056a200041f4006a3602002000200041b0016a41086a22143602a4052000200041f0006a3602a8052000200041b0016a3602a005200041c0036a200041a0056a107b20002802c803221541206a2216417f4c0d0120002802c00321190240024020160d00410121050c010b201610332205450d01201621180b024002402018410f4d0d00201821170c010b201841017422174110201741104b1b22174100480d03024020180d002017103322050d010c060b20182017460d0020052018201710372205450d050b2005200029038004370000200541086a20004180046a41086a2903003700000240024020174170714110460d00201721180c010b201741017422184120201841204b1b22184100480d0320172018460d0020052017201810372205450d050b200520002903d004370010200541186a200041d0046a41086a29030037000002400240201841606a2015490d00201821170c010b2015415f4b0d03201841017422172016201720164b1b22174100480d0320182017460d0020052018201710372205450d050b200541206a20192015109d081a024020002802c403450d00201910350b2016ad4220862005ad84100802402017450d00200510350b200041a0056a41186a22174200370300200041a0056a41106a22154200370300200041a0056a41086a22054200370300200042003703a00541a3edcb00ad4280808080f000841001221629000021062005201641086a290000370300200020063703a0052016103541a5ebcb00ad4280808080c0018410012216290000210620004180046a41086a2218201641086a2900003703002000200637038004201610352002200029038004370000200241086a2018290300370000200041d0046a41086a22162005290300370300200041d0046a41106a2015290300370300200041d0046a41186a2017290300370300200020002903a0053703d004200041106a200041d0046a412010c00120002802142117200028021021154188e8cb00ad42808080808001841001220529000021062018200541086a29000037030020002006370380042005103541f1c8c400ad4280808080e001841001220529000021062016200541086a290000370300200020063703d004200510354100211820002017410020151b360270200020044280808080c00084100322052900003703b00120051035200041ac056a200041f4006a360200200020143602a4052000200041f0006a3602a8052000200041b0016a3602a005200041c0036a200041a0056a107b20002802c803221541206a2216417f4c0d0120002802c00321190240024020160d00410121050c010b201610332205450d01201621180b024002402018410f4d0d00201821170c010b201841017422174110201741104b1b22174100480d03024020180d00201710332205450d060c010b20182017460d0020052018201710372205450d050b2005200029038004370000200541086a20004180046a41086a2903003700000240024020174170714110460d00201721180c010b201741017422184120201841204b1b22184100480d0320172018460d0020052017201810372205450d050b200520002903d004370010200541186a200041d0046a41086a29030037000002400240201841606a2015490d00201821170c010b2015415f4b0d03201841017422172016201720164b1b22174100480d0320182017460d0020052018201710372205450d050b200541206a20192015109d081a024020002802c403450d00201910350b2016ad4220862005ad84100802402017450d00200510350b200e4200200d1b210e0240024002400240024002400240024002402000280230450d00200041a0056a200041286a10c104200041db046a200041a0056a41086a280200360000200020002903a0053700d304200041ac056a200041d7046a290000370000200041023a00a4052000410f3a00a005200020002900d0043700a50541b0b4cc004100200041a0056a10d401200041c8006a200041286a41086a2802003602002000200e422088a7223536023c2000200b4100200c1b221b3602382000200029032837034020004188036a200041386a41086a10c1042000280290032114200028028c0321102000280288032128410410332205450d092005201b36000020004284808080c000370284042000200536028004200041a0056a10c204200041d0046a20002802a005221620002802a80510e00220002902d404420020002802d00422051b21042005410120051b211a024020002802a405450d00201610350b200020044220883e02c4032000201a3602c003200041086a200041c0036a10c40141002115024020002802080d00200028020c220720002802c403221841246e2205200520074b1bad42247e2206422088a70d0b2006a72205417f4c0d0b0240024020050d00410421150c010b200510332215450d0b0b41002119200041003602d804200020153602d0042000200541246e22053602d4042007450d0041002119410021020240024002400340201822034104490d02200241016a2102200020002802c003221841046a3602c0032018280000210841002105200041003a00c0052003417c6a2117034020172005460d02200041a0056a20056a201820056a221641046a2d00003a00002000201641056a3602c0032000200541016a22163a00c0052016210520164120470d000b200041c0026a41186a2209200041a0056a41186a290300370300200041c0026a41106a220a200041a0056a41106a290300370300200041c0026a41086a220f200041a0056a41086a290300370300200020002903a0053703c0020240201920002802d404470d00200041d0046a20194101108d0120002802d004211520002802d80421190b201720166b21182015201941246c6a22052008360200200520002903c0023702042005410c6a200f290300370200200541146a200a2903003702002005411c6a20092903003702002000201941016a22193602d80420022007470d000b2000200320166b417c6a3602c40320002802d40421050c030b200041003602c403200541ff0171450d01200041003a00c0050c010b200020033602c4030b024020002802d4042205450d00200541246c450d00201510350b410021150b200041a0056a20004180046a10c304200041d0046a20002802a005220720002802a80510b5022019410020151b21162005410020151b211820002902d404420020002802d00422051b21062015410420151b21172005410120051b2105024020002802a405450d00200710350b200041b8036a2016360200200041b4036a2018360200200041a8036a200637030020004198036a41086a20004180046a41086a280200360200200020002903800437039803200020173602b003200020053602a40302402004a7450d00201a10350b2014450d01200041b0036a2134200041a4036a212d2028201441d0006c6a210f200041a0056a41d0006a2133200041a0056a41306a2109200041a0056a41206a210a20004180046a41306a211120004180046a41206a211c20004180046a41c4006a211d41002112202821070340200041a0056a41386a22162007220541386a2903003703002009200541306a290300370300200041a0056a41286a2218200541286a290300370300200a200541206a290300370300200041a0056a41186a2202200541186a290300370300200041a0056a41106a2203200541106a290300370300200041a0056a41086a2208200541086a290300370300200041a0066a41086a2217200541cc006a280200360200200020052903003703a0052000200541c4006a2902003703a006200541d0006a2107200541c0006a2802002205450d03200041c0036a41386a22152016290300370300200041c0036a41306a22162009290300370300200041c0036a41286a22192018290300370300200041c0036a41206a2218200a290300370300200041c0036a41186a22142002290300370300200041c0036a41106a221a2003290300370300200041c0036a41086a221e2008290300370300200041f0016a41086a22012017280200360200200020002903a0053703c003200020002903a0063703f00120004180046a41386a20152903003703002011201629030037030020004180046a41286a2019290300370300201c201829030037030020004180046a41186a2215201429030037030020004180046a41106a2219201a29030037030020004180046a41086a221a201e290300370300200020002903c00337038004200020053602c004201d20002903f001370200201d41086a2001280200360200410410332214450d0a2014201b360000411810332205450d0a200042183702a405200020053602a005200541002902f8be46370000200541086a4100290280bf46370000200041103602a8054104200041a0056a10770240024020002802a405221720002802a80522056b4104490d0020002802a0052116201721180c010b200541046a22162005490d0d201741017422182016201820164b1b22184100480d0d0240024020170d00024020180d00410121160c020b201810332216450d110c010b20002802a005211620172018460d0020162017201810372216450d100b200020183602a405200020163602a0050b201620056a20142800003600002000200541046a22173602a8050240201820176b411f4b0d00201741206a221e2017490d0d20184101742201201e2001201e4b1b221e4100480d0d0240024020180d000240201e0d00410121160c020b201e10332216450d110c010b2018201e460d0020162018201e10372216450d100b2000201e3602a405200020163602a0050b201620176a2216200029038004370000201641186a2015290300370000201641106a2019290300370000201641086a201a2903003700002000200541246a3602a8052000201c3602d004200041d0046a200041a0056a10cf01200020113602d004200041d0046a200041a0056a10cf0120002802c004210520002802c8042216200041a0056a107702402016450d00201641306c211503400240024020002802a405221720002802a80522186b4120490d0020002802a00521160c010b201841206a22162018490d0f201741017422192016201920164b1b22194100480d0f0240024020170d00024020190d00410121160c020b201910332216450d130c010b20002802a005211620172019460d0020162017201910372216450d120b200020193602a405200020163602a0050b201620186a2216200541106a290000370000201641186a200541286a290000370000201641106a200541206a290000370000201641086a200541186a2900003700002000201841206a3602a805200020053602d004200041d0046a200041a0056a10cf01200541306a2105201541506a22150d000b0b20002802a405211620003502a80542208620002802a0052218ad84100922052900002104200541086a2900002106200541106a290000212e200041b0016a41186a221e200541186a290000370300200041b0016a41106a2201202e370300200041b0016a41086a22132006370300200020043703b0012005103502402016450d00201810350b20141035200041a0056a200041b0016a10c404200020002802a005221620002802a80541b0b4cc0041004100108a0220002802002105024020002802a405450d00201610350b024002400240024020054101460d00200041d0046a20004180046a41d000109d081a2000410036027820004201370370200041f0006a41004100108a01200041e0026a41086a22052000280278360200200020002903703703e002200041a0056a200041d0046a41d000109d081a203341086a2005280200360200203320002903e002370200200041f0006a200041b0016a10c4042000350278210420002802702112200041003602d804200042013703d004412010332205450d12200041203602d404200020053602d004200520002903a005370000200541086a2008290300370000200541106a2003290300370000200541186a2002290300370000200041203602d8042000200a3602e002200041e0026a200041d0046a10cf01200020093602e002200041e0026a200041d0046a10cf0120002802e005210520002802e8052216200041d0046a107702402016450d00201641306c211503400240024020002802d404221720002802d80422186b4120490d0020002802d00421160c010b201841206a22162018490d13201741017422192016201920164b1b22194100480d130240024020170d00024020190d00410121160c020b201910332216450d170c010b20002802d004211620172019460d0020162017201910372216450d160b200020193602d404200020163602d0040b201620186a2216200541106a290000370000201641186a200541286a290000370000201641106a200541206a290000370000201641086a200541186a2900003700002000201841206a3602d804200020053602e002200041e0026a200041d0046a10cf01200541306a2105201541506a22150d000b0b20002802f005210520002802f8052216200041d0046a10770240024020160d0020002802d804211620002802d404211420002802d00421190c010b2016410574211a410020002802d80422166b211520002802d4042117034002400240201720156a4120490d0020002802d0042119201721140c010b201641206a22182016490d13201741017422192018201920184b1b22144100480d130240024020170d00024020140d00410121190c020b201410332219450d170c010b20002802d004211920172014460d0020192017201410372219450d160b200020143602d404200020193602d004201421170b201920166a22182005290000370000201841186a200541186a290000370000201841106a200541106a290000370000201841086a200541086a2900003700002000201641206a22163602d804201541606a2115200541206a2105201a41606a221a0d000b0b20044220862012ad842016ad4220862019ad84100202402014450d00201910350b02402000280274450d00201210350b024020002802e4052205450d00200541306c450d0020002802e00510350b024020002802f40541ffffff3f71450d0020002802f00510350b200041d0046a41186a2214201e290300370300200041d0046a41106a221a2001290300370300200041d0046a41086a221e2013290300370300200020002903b0013703d00420002802b003211541002105024020002802b803221941014b0d00024020190e020003000b200220142903003703002003201a2903003703002008201e290300370300200020002903d0043703a005410021050c030b20192116034020052016410176221820056a22172015201741246c6a280200201b4b1b2105201620186b221641014b0d000c020b0b20002802c4042205450d02200541306c450d0220002802c00410350c020b02402015200541246c6a2802002216201b460d0020052016201b496a21050b200220142903003703002003201a2903003703002008201e290300370300200020002903d0043703a005201920054f0d0020052019104d000b0240201920002802b403470d00203420194101108d0120002802b00321150b2015200541246c6a221641246a2016201920056b41246c109e081a2016201b360200201620002903a0053702042016410c6a2008290300370200201641146a20032903003702002016411c6a20022903003702002000201941016a3602b803200220142903003703002003201a2903003703002008201e290300370300200020002903d0043703a005024020002802ac03220520002802a803470d00202d20054101108a0120002802ac0321050b20002802a40320054105746a221620002903a005370000201641186a2002290300370000201641106a2003290300370000201641086a2008290300370000410121122000200541016a3602ac030b2007200f470d000b200f21070c020b200041013a00a4052000410f3a00a00541b0b4cc004100200041a0056a10d401200028022c2205450d07200541d0006c450d07200028022810350c070b2010450d01201041d0006c450d01202810350c010b0240200f2007460d0003402007220541d0006a21070240200541c4006a2802002216450d00201641306c450d00200541c0006a28020010350b200f2007470d000b0b02402010450d00201041d0006c450d00202810350b2012410171450d00024020002802ac032205450d0020002802a4032118200541057441406a2116200041e4056a2105034020004180026a201810c404200041a0056a200028028002221520002802880210d70220004180046a41086a2219200041a0056a41086a29030037030020004180046a41106a2214200041a0056a41106a29030037030020004180046a41186a221a200041a0056a41186a29030037030020004180046a41206a2207200041a0056a41206a29030037030020004180046a41286a2202200041a0056a41286a29030037030020004180046a41306a2203200041a0056a41306a29030037030020004180046a41386a2208200041a0056a41386a290300370300200041e0026a41086a2209200541086a290200370300200041e0026a41106a220a200541106a290200370300200041e0026a41186a220f200541186a280200360200200020002903a00537038004200020052902003703e002024020002802e0052217450d00200041f0006a41386a2008290300370300200041f0006a41306a2003290300370300200041f0006a41286a2002290300370300200041f0006a41206a2007290300370300200041f0006a41186a201a290300370300200041f0006a41106a2014290300370300200041f0006a41086a2019290300370300200041d0046a41086a2009290300370300200041d0046a41106a200a290300370300200041d0046a41186a200f2802003602002000200029038004370370200020002903e0023703d0040b0240200028028402450d00201510350b20170d03201841206a2118201641606a22164140470d000b0b4108210a410021084100210f0c020b0240200028029c03450d0020002802980310350b024020002802a80341ffffff3f71450d0020002802a40310350b20002802b4032205450d02200541246c450d0220002802b00310350c020b200041c0036a41386a2214200041f0006a41386a290300370300200041c0036a41306a221a200041f0006a41306a290300370300200041c0036a41286a2207200041f0006a41286a290300370300200041c0036a41206a2202200041f0006a41206a290300370300200041c0036a41186a2203200041f0006a41186a290300370300200041c0036a41106a2208200041f0006a41106a290300370300200041c0036a41086a2209200041f0006a41086a290300370300200041a0026a41086a220a200041d0046a41086a2205290300370300200041a0026a41106a220f200041d0046a41106a2215290300370300200041a0026a41186a2211200041d0046a41186a2219280200360200200020002903703703c003200020002903d0043703a002200041b0016a41086a221c2009290300370300200041b0016a41106a22092008290300370300200041b0016a41186a22082003290300370300200041b0016a41206a22032002290300370300200041b0016a41286a22022007290300370300200041b0016a41306a2207201a290300370300200041b0016a41386a221a2014290300370300200041c0026a41086a2214200a290300370300200041c0026a41106a220a200f290300370300200041c0026a41186a220f2011280200360200200020002903c0033703b001200020002903a0023703c002200041a0056a41086a2211201c290300370300200041a0056a41106a221c2009290300370300200041a0056a41186a22092008290300370300200041a0056a41206a22082003290300370300200041a0056a41286a22032002290300370300200041a0056a41306a22022007290300370300200041a0056a41386a2207201a290300370300200020002903b0013703a005200520142903003703002015200a2903003703002019200f280200360200200020002903c0023703d00441e0001033220a450d04200a20002903a005370300200a2017360240200a20002903d004370244200a41386a2007290300370300200a41306a2002290300370300200a41286a2003290300370300200a41206a2008290300370300200a41186a2009290300370300200a41106a201c290300370300200a41086a2011290300370300200a41cc006a2005290300370200200a41d4006a2015290300370200200a41dc006a201928020036020020004281808080103702a4062000200a3602a006024020164160470d00410121084101210f0c010b201841206a2117200041a0056a41c4006a211841012108034020004180026a201710c404200041a0056a200028028002220520002802880210d70220004180046a41086a220f200041a0056a41086a221929030037030020004180046a41106a2211200041a0056a41106a221429030037030020004180046a41186a221c200041a0056a41186a221a29030037030020004180046a41206a221d200041a0056a41206a220729030037030020004180046a41286a221e200041a0056a41286a220229030037030020004180046a41306a2201200041a0056a41306a220329030037030020004180046a41386a2213200041a0056a41386a2209290300370300200041e0026a41086a2212201841086a290200370300200041e0026a41106a2233201841106a290200370300200041e0026a41186a2234201841186a280200360200200020002903a00537038004200020182902003703e002024020002802e0052215450d00200041d0046a41386a2013290300370300200041d0046a41306a2001290300370300200041d0046a41286a201e290300370300200041d0046a41206a201d290300370300200041d0046a41186a201c290300370300200041d0046a41106a2011290300370300200041d0046a41086a200f290300370300200041f0006a41086a2012290300370300200041f0006a41106a2033290300370300200041f0006a41186a203428020036020020002000290380043703d004200020002903e0023703700b0240200028028402450d00200510350b02400240024020150d002016450d010c020b200041c0036a41386a2205200041d0046a41386a290300370300200041c0036a41306a221d200041d0046a41306a290300370300200041c0036a41286a221e200041d0046a41286a290300370300200041c0036a41206a2201200041d0046a41206a290300370300200041c0036a41186a2213200041d0046a41186a220f290300370300200041c0036a41106a2212200041d0046a41106a2211290300370300200041c0036a41086a2233200041d0046a41086a221c290300370300200041a0026a41086a2234200041f0006a41086a290300370300200041a0026a41106a222d200041f0006a41106a290300370300200041a0026a41186a2228200041f0006a41186a280200360200200020002903d0043703c003200020002903703703a002200041b0016a41086a22102033290300370300200041b0016a41106a22332012290300370300200041b0016a41186a22122013290300370300200041b0016a41206a22132001290300370300200041b0016a41286a2201201e290300370300200041b0016a41306a221e201d290300370300200041b0016a41386a221d2005290300370300200041c0026a41086a22052034290300370300200041c0026a41106a2234202d290300370300200041c0026a41186a222d2028280200360200200020002903c0033703b001200020002903a0023703c0022019201029030037030020142033290300370300201a201229030037030020072013290300370300200220012903003703002003201e2903003703002009201d290300370300200020002903b0013703a005201c200529030037030020112034290300370300200f202d280200360200200020002903c0023703d0040240200820002802a406470d00200041a0066a2008410110a40120002802a006210a0b200a200841e0006c6a220520002903a005370300200541106a2014290300370300200541086a201929030037030020032903002104200929030021062002290300212e2007290300212f201a2903002130200541c0006a2015360200200541186a2030370300200541206a202f370300200541286a202e370300200541c4006a20002903d004370200200541386a2006370300200541306a2004370300200541cc006a201c290300370200200541d4006a2011290300370200200541dc006a200f2802003602002000200841016a22083602a80620160d010b20002802a406210f0c020b201741206a2117201641606a21160c000b0b200041a0056a41206a20004198036a41206a2802002216360200200041a0056a41106a20004198036a41106a290300370300200041a0056a41086a20004198036a41086a290300370300200041a0056a41186a20004198036a41186a290300220437030020002000290398033703a005201641246c41046a2205417f4c0d040240024020050d0041012118410021050c010b200510332218450d040b200041003602d804200020183602d004200020053602d4042016200041d0046a10770240024020160d0020002802d804211820002802d404211720002802d00421190c010b2004a72205201641246c6a2109410020002802d80422186b211420002802d404211703402005280200211602400240201720146a4104490d0020002802d0042119201721150c010b201841046a22152018490d08201741017422192015201920154b1b22154100480d080240024020170d00024020150d00410121190c020b201510332219450d0c0c010b20002802d004211920172015460d0020192017201510372219450d0b0b200020153602d404200020193602d0040b201920186a20163600002000201841046a22173602d804412010332216450d05201641186a221a2005411c6a290000370000201641106a2207200541146a290000370000201641086a22022005410c6a2900003700002016200541046a29000037000002400240201520146a417c6a411f4d0d00201521170c010b201741206a22032017490d08201541017422172003201720034b1b22174100480d080240024020150d00024020170d00410121190c020b201710332219450d0c0c010b20152017460d0020192015201710372219450d0b0b200020173602d404200020193602d0040b201920186a221541046a20162900003700002015411c6a201a290000370000201541146a20072900003700002015410c6a20022900003700002000201841246a22183602d804201610352014415c6a2114200541246a22052009470d000b0b200041d0046a10c20420002802d0042105200020002802d8043602840420002005360280042019201820004180046a109403024020002802d404450d00200510350b02402017450d00201910350b200041d0046a200041a0056a10c30420002802d0042105200020002802d80436028404200020053602800420002802ac052216200041b4056a28020020004180046a10c504024020002802d404450d00200510350b024020002802a405450d0020002802a00510350b0240200041b0056a28020041ffffff3f71450d00201610350b0240200041bc056a2802002205450d00200541246c450d0020002802b80510350b200a0d010b200028024021170240200041c8006a2802002205450d00200541d0006c2116201741c4006a21050340024020052802002218450d00201841306c450d002005417c6a28020010350b200541d0006a2105201641b07f6a22160d000b0b0240200041c4006a2802002205450d00200541d0006c450d00201710350b41eba3cc00ad4280808080c00184100641dca3cc00ad4280808080f0018410060c010b4100211802402035410a6e417f7320086a221620084b0d0020354101203541014b1b2205418094ebdc036e221820052018418094ebdc036c476a22184101201841014b1b221820054b0d0520002005201641036c221620052016491b20186ead428094ebdc037e200520186ead8042ffffffff0f834280bbb0217e428094ebdc0380a722053602a0052000418094ebdc033602a405200041a0056a2005418094ebdc034b4102746a28020021180b200041003602a805200042043703a005200041a0056a4100200810860120002802a005210720002802a805211a02400240024020080d0020002802a405211141012116200a41002007201a201b10fd010d010c020b2007201a4102746a210520082116034020052018360200200541046a21052016417f6a22160d000b20002802a405211141012116200a20082007201a20086a221a201b10fd01450d010b200041a0026a41186a4200370300200041a0026a41106a22184200370300200041a0026a41086a22054200370300200042003703a00241a2e8cb00ad42808080808001841001221629000021042005201641086a290000370300200020043703a0022016103541e6f2c400ad4280808080800284100122162900002104200041a0056a41086a2217201641086a290000370300200020043703a00520161035201820002903a005220437030020004180026a41086a200529030037030020004180026a41106a200437030020004180026a41186a2017290300370300200020002903a00237038002200041a0056a20004180026a10c6020240024020002802a00522020d0041002109200041003602b801200042043703b00141042102410021030c010b200020002902a40522043702b401200020023602b0012004422088a721032004a721090b2008ad42e0007e2204422088a70d032004a72205417f4c0d030240024020050d00410821160c010b200510332216450d030b200041003602c803200020163602c0032000200541e0006e3602c403200041c0036a4100200810a40120002802c803211c02402008450d00200a200841e0006c6a211420002802c003201c41e0006c6a2105200841057441606a410576211d200041a4056a2118200a21160340200041c0026a41086a2217201641086a290300370300200041c0026a41106a2215201641106a290300370300200041c0026a41186a2219201641186a290300370300200020162903003703c002201641206a2903002104201641286a2903002106201641306a290300212e201641386a290300212f20004180046a201641c0006a10c604200041d0046a201641d0006a10a402201841086a200041d0046a41086a280200360200201820002903d00437020020192903002130201529030021312017290300213220002903c0022137200541386a202f370300200541306a202e370300200541286a2006370300200541206a2004370300200541086a203237030020052037370300200541106a2031370300200541c0006a200029038004370300200541c8006a20004180046a41086a280200360200200541186a2030370300200541cc006a20002902a005370200200541d4006a200041a0056a41086a290200370200200541e0006a2105201641e0006a22162014470d000b201c201d6a41016a211c0b200041a8056a201c360200200020002903c0033703a005201a41ffffffff0371201a470d03201a4102742205417f4c0d030240024020050d00410421160c010b200510332216450d030b200041003602d804200020163602d004200020054102763602d404200041d0046a4100201a10860120002802d00420002802d80422054102746a2007201a410274109d081a20004180046a41086a22182005201a6a2205360200200041b4056a2005360200200020002903d0043702ac05024020032009470d00200041b0016a2009410110f90120002802b401210920002802b001210220002802b80121030b20022003411c6c6a220520002903a005370200200041a0056a41086a22162903002104200041a0056a41106a221729030021062005201b360218200541106a2006370200200541086a20043702002000200341016a22153602b801200041a0056a41186a42003703002017420037030020164200370300200042003703a00541a2e8cb00ad42808080808001841001220529000021042016200541086a290000370300200020043703a0052005103541e6f2c400ad42808080808002841001220529000021042018200541086a29000037030020002004370380042005103520172000290380042204370300200041d0046a41086a2016290300370300200041d0046a41106a2004370300200041d0046a41186a2018290300370300200020002903a0053703d0040240024020020d00200041d0046aad428080808080048410070c010b200041a0056a2002201510c704200041d0046aad428080808080048420003502a80542208620002802a0052205ad841002024020002802a405450d00200510350b2002201510c8022009450d002009411c6c450d00200210350b410021160b410410332205450d012005201b360000200041a8056a4284808080c000370300200041b8056a4100290280bf46370300200041c0056a20163a0000200041103a00a005200041a0056a41106a41002902f8be46370300200020053602a40541b0b4cc004100200041a0056a10d4010240201141ffffffff0371450d00200710350b02402008450d00200841e0006c2116200a41d4006a210503400240200541706a2802002218450d00201841306c450d002005416c6a28020010350b0240200528020041ffffff3f71450d002005417c6a28020010350b200541e0006a2105201641a07f6a22160d000b0b0240200f450d00200f41e0006c450d00200a10350b200028024021170240200041c8006a2802002205450d00200541d0006c2116201741c4006a21050340024020052802002218450d00201841306c450d002005417c6a28020010350b200541d0006a2105201641b07f6a22160d000b0b200041c4006a2802002205450d00200541d0006c450d00201710350b0240200e42ffffff3f83500d00200d4101200d1b10350b200041b0066a24000f0b1045000b1044000b103e000b4190edc40041194180efc400103f000b103c000bfe0304027f017e067f077e230041c0006b220224000240024020012802082203ad42d0007e2204422088a70d002004a72205417f4c0d00200128020021010240024020050d00410821060c010b200510332206450d020b20024100360208200220063602002002200541d0006e36020420024100200310a3012002280208210702402003450d002001200341d0006c6a21082002280200200741d0006c6a2105200341047441706a41047621090340200241206a41086a2203200141086a290300370300200241206a41106a2206200141106a290300370300200241206a41186a220a200141186a29030037030020022001290300370320200141206a2903002104200141286a290300210b200141306a290300210c200141386a290300210d200241106a200141c0006a10c604200a290300210e2006290300210f2003290300211020022903202111200541386a200d370300200541306a200c370300200541286a200b370300200541206a2004370300200541086a201037030020052011370300200541106a200f370300200541186a200e370300200541c0006a2002290310370300200541c8006a200241106a41086a280200360200200541d0006a2105200141d0006a22012008470d000b200720096a41016a21070b20002002290300370200200041086a2007360200200241c0006a24000f0b1044000b1045000b970503027f017e067f230041d0006b2201240041a2e8cb00ad4280808080800184100122022900002103200141086a41086a200241086a290000370300200120033703082002103541aae8cb00ad4280808080a00284100122022900002103200141186a41086a200241086a29000037030020012003370318200210350240024002400240411010332202450d0041002104200241086a4100290280bf46370000200241002902f8be4637000020012002ad42808080808002841003220529000037033820051035200141cc006a200241106a360200200120023602482001200141386a41086a3602442001200141386a360240200141286a200141c0006a107b200210352001280230220641206a2207417f4c0d01200128022821080240024020070d00410121020c010b200710332202450d01200721040b024002402004410f4d0d00200421050c010b200441017422054110200541104b1b22054100480d03024020040d002005103322020d010c050b20042005460d0020022004200510372202450d040b20022001290308370000200241086a200141086a41086a2903003700000240024020054170714110460d00200521040c010b200541017422044120200441204b1b22044100480d0320052004460d0020022005200410372202450d040b20022001290318370010200241186a200141186a41086a29030037000002400240200441606a2006490d00200421050c010b200641206a22052006490d03200441017422092005200920054b1b22054100480d0320042005460d0020022004200510372202450d040b200241206a20082006109d081a2000200736020820002005360204200020023602000240200128022c450d00200810350b200141d0006a24000f0b1045000b1044000b103e000b103c000bbd0603027f017e087f230041d0006b2202240041a2e8cb00ad4280808080800184100122032900002104200241086a41086a200341086a290000370300200220043703082003103541b0a5c500ad4280808080e00284100122032900002104200241186a41086a200341086a29000037030020022004370318200310350240024002400240411010332203450d0041002105200341086a4100290280bf46370000200341002902f8be4637000020022003ad42808080808002841003220629000037033820061035200241cc006a200341106a360200200220033602482002200241386a41086a3602442002200241386a360240200241286a200241c0006a107b20031035200241c0006a200128020020012802081098032002280230220741206a2208200228024822096a2201417f4c0d012002280240210a2002280228210b0240024020010d00410121030c010b200110332203450d01200121050b024002402005410f4d0d002005210c0c010b200541017422064110200641104b1b220c4100480d03024020050d00200c103322030d010c050b2005200c460d0020032005200c10372203450d040b20032002290308370000200341086a200241086a41086a29030037000002400240200c4170714110460d00200c21060c010b200c41017422054120200541204b1b22064100480d03200c2006460d002003200c200610372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200641606a2007490d00200621050c010b200741206a22052007490d032006410174220c2005200c20054b1b22054100480d0320062005460d0020032006200510372203450d040b200341206a200b2007109d081a02400240200520086b2009490d00200521060c010b20012008490d03200541017422062001200620014b1b22064100480d03024020050d00024020060d00410121030c020b200610332203450d050c010b20052006460d0020032005200610372203450d040b200320086a200a2009109d081a20002001360208200020063602042000200336020002402002280244450d00200a10350b0240200228022c450d00200b10350b200241d0006a24000f0b1045000b1044000b103e000b103c000bb10503027f017e047f230041d0006b2202240041a2e8cb00ad4280808080800184100122032900002104200241086a41086a200341086a290000370300200220043703082003103541dff2c400ad4280808080f00084100122032900002104200241186a41086a200341086a29000037030020022004370318200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad42808080808004841003220129000037033820011035200241cc006a200341206a360200200220033602482002200241386a41086a3602442002200241386a360240200241286a200241c0006a107b200310352002280230220541206a2201417f4c0d01200228022821060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a2000200136020820002008360204200020033602000240200228022c450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000be503010a7f230041106b22032400024020014105744104722204417f4c0d000240200410332205450d002003410036020820032004360204200320053602002001200310770240024020010d002003280208210520032802042106200328020021070c010b20014105742108200328020021072003280204210620032802082105034020052104412010332201450d0220012000290000370000200141186a2209200041186a290000370000200141106a220a200041106a290000370000200141086a220b200041086a29000037000002400240200620046b4120490d00200441206a21050c010b024002400240200441206a22052004490d002006410174220c2005200c20054b1b220c4100480d000240024020060d000240200c0d00410121070c020b200c103321070c040b2006200c470d020b200c21060c030b103e000b20072006200c103721070b200c210620070d00103c000b200041206a2100200720046a22042001290000370000200441186a2009290000370000200441106a200a290000370000200441086a200b29000037000020011035200841606a22080d000b2003200636020420032005360208200320073602000b20022902002005ad4220862007ad84100202402006450d00200710350b200341106a24000f0b1045000b1044000bb10203027f017e027f230041106b220224000240024020012802082203ad42307e2204422088a70d002004a72205417f4c0d00200128020021010240024020050d00410821060c010b200510332206450d020b20024100360208200220063602002002200541306e3602042002410020031088012002280208210502402003450d002001200341306c6a21062002280200200541306c6a21030340200320012903003703002003200141086a290300370308200341106a200141106a290300370300200341186a200141186a290300370300200341206a200141206a290300370300200341286a200141286a290300370300200341306a2103200541016a2105200141306a22012006470d000b0b20002002290300370200200041086a2005360200200241106a24000f0b1044000b1045000bfe0301067f230041106b22032400024002402002411c6c41046a2204417f4c0d000240024020040d0041012105410021040c010b200410332205450d020b20034100360208200320053602002003200436020420022003107702402002450d0020012002411c6c6a2106034020012802002105200128020822022003107702402002450d002005200241e0006c6a2107034020032005412010782003200541206a36020c2003410c6a200310cf012003200541306a36020c2003410c6a200310cf0120052802402102200528024822042003107702402004450d00200441306c210403402003200241106a412010782003200236020c200241306a21022003410c6a200310cf01200441506a22040d000b0b200541e0006a210820052802502102200528025822042003107702402004450d002004410574210403402003200241201078200241206a2102200441606a22040d000b0b2008210520082007470d000b0b2001411c6a2105200128020c2102200128021422042003107702402004450d002004410274210403402003200228020036020c20032003410c6a41041078200241046a21022004417c6a22040d000b0b2003200128021836020c20032003410c6a410410782005210120052006470d000b0b20002003290300370200200041086a200341086a280200360200200341106a24000f0b1044000b1045000b960407047f017e017f017e017f017e047f230041e0006b22012400200141306a41186a22024200370300200141306a41106a22034200370300200141306a41086a220442003703002001420037033041d1c4c700ad4280808080e000842205100122062900002107200141d0006a41086a2208200641086a290000370300200120073703502006103520042008290300370300200120012903503703304184eec700ad4280808080b0028422071001220629000021092008200641086a2900003703002001200937035020061035200320012903502209370300200141106a41086a220a2004290300370300200141106a41106a220b2009370300200141106a41186a220c2008290300370300200120012903303703102001200141106a10e102200129030821092001280200210d2002420037030020034200370300200442003703002001420037033020051001220629000021052008200641086a2900003703002001200537035020061035200420082903003703002001200129035037033020071001220629000021052008200641086a2900003703002001200537035020061035200320012903502205370300200a2004290300370300200b2005370300200c2008290300370300200120012903303703102001427f20094200200d1b220520007c220020002005541b370330200141106aad4280808080800484200141306aad42808080808001841002200141e0006a24000bfc0403027f017e057f230041d0006b220224004189fec600ad4280808080900184100122032900002104200241086a41086a200341086a290000370300200220043703082003103541e28cc500ad4280808080e00084100122032900002104200241186a41086a200341086a2900003703002002200437031820031035200220013602342002200241346aad4280808080c000841003220329000037033820031035200241cc006a200241386a3602002002200241386a41086a3602442002200241346a3602482002200241386a360240200241286a200241c0006a107b02400240024002402002280230220541206a2206417f4c0d00200228022821070240024020060d0041002101410121030c010b200610332203450d02200621010b024002402001410f4d0d00200121080c010b200141017422084110200841104b1b22084100480d03024020010d002008103322030d010c050b20012008460d0020032001200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821010c010b200841017422014120200141204b1b22014100480d0320082001460d0020032008200110372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200141606a2005490d00200121080c010b200541206a22082005490d03200141017422092008200920084b1b22084100480d0320012008460d0020032001200810372203450d040b200341206a20072005109d081a2000200636020820002008360204200020033602000240200228022c450d00200710350b200241d0006a24000f0b1044000b1045000b103e000b103c000bea3506207f027e027f057e027f077e230041f0106b220224000240024002400240024002400240200141106a2802002203200141146a280200460d00200241f00a6a41c0026a21042002418d0b6a2105200241e10a6a2106200241a80a6a2107200241f00a6a4105722108200241f8076a4105722109200241a00f6a210a200241c00e6a41c0006a210b200241e00e6a210c200241e8086a210d200241f00a6a410472210e200241f8076a410472210f200241f00a6a41146a2110200241f00a6a41106a2111200241f00a6a410d6a2112200241f00a6a410c6a2113200241f00a6a41086a2114200241c8086a2115200241f8076a41146a2116200241f8076a41106a2117200241f8076a410d6a2118200241a8086a2119200241f8076a410c6a211a200241f8076a41086a211b200241f8076a41c0026a211c200241f8076a41046a211d03402001200341d8026a3602102003280200211e200241186a200341046a41c002109d081a200241086a41086a221f200341d0026a2903003703002002200341c8026a290300370308200341c4026a28020022034102460d0120012802182120200241f8076a200241186a41c002109d081a200241f00a6a201d41bc02109d081a20042002290308370300200441086a2221201f290300370300200220033602ac0d200241b8056a200241f00a6a10d8032001200129030020022903b8057c2222370300200241b8056a200241f00a6a41bc02109d081a200241a8056a41086a221f2021290300370300200220042903003703a8050240024020022802ac0d22034102470d00410321030c010b200241f8076a200241b8056a41bc02109d081a201c41086a2221201f290300370300201c20022903a805370300200220033602b40a0240024020022d00c00a41c000490d002020450d0020222001280220290300560d010b024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020022802f8070e1c00011302030405060708090a0b0c0d0e0f1011121313131415161713000b200241c00e6a201b109d03201441086a200241c00e6a41086a290300370300201420022903c00e370300200241003602f00a0c170b200241c00e6a200f109a03200e41386a200241c00e6a41386a280200360200200e41306a200241c00e6a41306a290300370200200e41286a200241c00e6a41286a290300370200200e41206a200241c00e6a41206a290300370200200e41186a200241c00e6a41186a290300370200200e41106a200241c00e6a41106a290300370200200e41086a200241c00e6a41086a290300370200200e20022903c00e370200200241013602f00a0c160b20022002290380083703f80a200241033602f00a0c150b200241c00e6a200f109e03200e41086a200241c00e6a41086a280200360200200e20022903c00e370200200241043602f00a0c140b024002400240024002400240024020022d00fc07417f6a220341034b0d0020030e0401020304010b41cfa2cc00412841c086cc00103f000b41012103200228028008211f0c040b41022103200241c00d6a41026a200941026a2d00003a0000200241c00e6a41086a201a41086a290200370300200241c00e6a41106a201a41106a290200370300200241c00e6a41186a201a41186a2d00003a0000200220092f00003b01c00d2002201a2902003703c00e0c020b41032103200228028008211f0c020b200241c00d6a41026a200941026a2d00003a0000200241c00e6a41086a201a41086a290200370300200241c00e6a41106a201a41106a290200370300200241c00e6a41186a201a41186a2d00003a0000200220092f00003b01c00d2002201a2902003703c00e410421030b200228028008211f20022802a00821210b200820022f01c00d3b0000201320022903c00e370200200841026a200241c00d6a41026a2d00003a0000201341086a200241c00e6a41086a290300370200201341106a200241c00e6a41106a290300370200201341186a200241c00e6a41186a280200360200200220033a00f40a2002201f3602f80a200220213602980b200241053602f00a0c130b024002400240024002400240200228028008417f6a220341034b0d0020030e0401020304010b41cfa2cc00412841c086cc00103f000b41012103024020022d0084084101460d00200241ec106a41026a201841026a2d00003a0000200241c00e6a41086a201641086a290200370300200241c00e6a41106a201641106a290200370300200241c00e6a41186a201641186a2d00003a0000200220182f00003b01ec10200220162902003703c00e410021030b2002280288082121200241e8106a41026a200241ec106a41026a2d00003a0000200241c00d6a41086a200241c00e6a41086a290300370300200241c00d6a41106a200241c00e6a41106a290300370300200241c00d6a41186a200241c00e6a41186a280200360200200220022f01ec103b01e810200220022903c00e3703c00d20022903a8082223422088a721202023420888a721242023a7211f200241b0086a2903002123410121250c030b41012103024020022d0084084101460d00200241ec106a41026a201841026a2d00003a0000200241c00e6a41086a201641086a290200370300200241c00e6a41106a201641106a290200370300200241c00e6a41186a201641186a2d00003a0000200220182f00003b01ec10200220162902003703c00e410021030b200228028808212141022125200241e8106a41026a200241ec106a41026a2d00003a0000200241c00d6a41086a200241c00e6a41086a290300370300200241c00d6a41106a200241c00e6a41106a290300370300200241c00d6a41186a200241c00e6a41186a280200360200200220022f01ec103b01e810200220022903c00e3703c00d20022903a8082223422088a721202023420888a721242023a7211f200241c0086a2903002126200241b0086a290300212320022903b80821270c020b41012103024020022d0084084101460d00200241ec106a41026a201841026a2d00003a0000200241c00e6a41086a201641086a290200370300200241c00e6a41106a201641106a290200370300200241c00e6a41186a201641186a2d00003a0000200220182f00003b01ec10200220162902003703c00e410021030b20022802880821214101211f0240024020022d00a8084101470d0020022802ac0821202028212320292127202a2126202b21240c010b202c41807e7120022d00c80872212c4100211f20022802ac08212020022903b0082223212820022903b80822272129200241c0086a2903002226212a20022f00a908200241ab086a2d0000411074722224212b0b200241e8106a41026a200241ec106a41026a2d00003a0000200241c00d6a41086a200241c00e6a41086a290300370300200241c00d6a41106a200241c00e6a41106a290300370300200241c00d6a41186a200241c00e6a41186a280200360200200220022f01ec103b01e810200220022903c00e3703c00d202d42808080807083202cad84212d200241d8086a290300212e20022903d008212f410321250c010b41012103024020022d0084084101460d00200241ec106a41026a201841026a2d00003a0000200241c00e6a41086a201641086a290200370300200241c00e6a41106a201641106a290200370300200241c00e6a41186a201641186a2d00003a0000200220182f00003b01ec10200220162902003703c00e410021030b2002280288082121200241e8106a41026a200241ec106a41026a2d00003a0000200241c00d6a41086a200241c00e6a41086a290300370300200241c00d6a41106a200241c00e6a41106a290300370300200241c00d6a41186a200241c00e6a41186a280200360200200220022f01ec103b01e810200220022903c00e3703c00d20022903a8082223422088a721202023420888a721242023a7211f200241b0086a2903002123410421250b201220022f01e8103b0000201241026a200241e8106a41026a2d00003a0000201020022903c00d370200201041086a200241c00d6a41086a290300370200201041106a200241c00d6a41106a290300370200201041186a200241c00d6a41186a280200360200200220033a00fc0a200220253602f80a200220213602800b200241d00b6a202e370300200241b80b6a2026370300200241a80b6a20233703002002202f3703c80b200220273703b00b20022020ad4220862024ad42ffffff078342088684201fad42ff0183843703a00b2002202d3703c00b200241063602f00a0c120b200241c00e6a201b1087022014200241c00e6a418802109d081a200241073602f00a0c110b0240024020022802fc0722240d004100211f0c010b200c2019290000370000200b2015290000370000200241c00e6a41186a201741186a290000370300200241c00e6a41106a201741106a290000370300200241c00e6a41086a201741086a290000370300200c41086a201941086a290000370000200c41106a201941106a290000370000200c41186a201941186a290000370000200b41086a201541086a290000370000200b41106a201541106a290000370000200b41186a201541186a290000370000200220172900003703c00e200a41186a200d41186a290000370000200a41106a200d41106a290000370000200a41086a200d41086a290000370000200a200d2900003700002002280284082203417f4c0d180240024020030d00410021214101211f0c010b20031033221f450d1b200321210b0240024020212003490d00202121200c010b202141017422202003202020034b1b22204100480d1a024020210d0020201033221f0d010c1d0b20212020460d00201f202120201037221f450d1c0b201f20242003109d081a200241c00d6a200241c00e6a418001109d081a2003ad4220862020ad8421300b200220303703f80a2002201f3602f40a2011200241c00d6a418001109d081a200241083602f00a0c100b200241c00e6a201b10a003201441306a200241c00e6a41306a290300370300201441286a200241c00e6a41286a290300370300201441206a200241c00e6a41206a290300370300201441186a200241c00e6a41186a290300370300201441106a200241c00e6a41106a290300370300201441086a200241c00e6a41086a290300370300201420022903c00e370300200241093602f00a0c0f0b200241c00e6a200f10a103200e41286a200241c00e6a41286a290300370200200e41206a200241c00e6a41206a290300370200200e41186a200241c00e6a41186a290300370200200e41106a200241c00e6a41106a290300370200200e41086a200241c00e6a41086a290300370200200e20022903c00e3702002002410a3602f00a0c0e0b200241c00e6a200f10a103200e41286a200241c00e6a41286a290300370200200e41206a200241c00e6a41206a290300370200200e41186a200241c00e6a41186a290300370200200e41106a200241c00e6a41106a290300370200200e41086a200241c00e6a41086a290300370200200e20022903c00e3702002002410b3602f00a0c0d0b200241c00e6a201b108603201441206a200241c00e6a41206a290300370300201441186a200241c00e6a41186a290300370300201441106a200241c00e6a41106a290300370300201441086a200241c00e6a41086a290300370300201420022903c00e3703002002410c3602f00a0c0c0b200241c00e6a200f10a203200e200241c00e6a41c400109d081a2002410d3602f00a0c0b0b200220022802fc073602f40a2002410e3602f00a0c0a0b2002280284082203417f4c0d1020022802fc0721240240024020030d004100211f410121200c010b200310332220450d132003211f0b02400240201f2003490d00201f21210c010b201f41017422212003202120034b1b22214100480d120240201f0d00202110332220450d150c010b201f2021460d002020201f202110372220450d140b202020242003109d08211f200220033602fc0a200220213602f80a2002201f3602f40a2002410f3602f00a0c090b200241c00e6a201b10a303201441386a200241c00e6a41386a290300370300201441306a200241c00e6a41306a290300370300201441286a200241c00e6a41286a290300370300201441206a200241c00e6a41206a290300370300201441186a200241c00e6a41186a290300370300201441086a200241c00e6a41086a290300370300201420022903c00e370300200241103602f00a201441106a200241c00e6a41106a2903003703000c080b200241c00e6a201b10a4032014200241c00e6a419801109d081a200241113602f00a0c070b200241c00e6a200f10a503200e41286a200241c00e6a41286a280200360200200e41206a200241c00e6a41206a290300370200200e41186a200241c00e6a41186a290300370200200e41106a200241c00e6a41106a290300370200200e41086a200241c00e6a41086a290300370200200e20022903c00e370200200241123602f00a0c060b200241c00e6a200f10de04200e200241c00e6a41e800109d081a200241133602f00a0c050b10a703000b200241c00e6a201b10a8032014200241c00e6a41a802109d081a200241173602f00a0c030b200241c00e6a201b10a9032014200241c00e6a41c800109d081a200241183602f00a0c020b200241c00e6a200f10aa03200e200241c00e6a41c400109d081a200241193602f00a0c010b02400240024002400240200228028008417f6a220341024b0d004101212120030e03040102040b41cfa2cc00412841c086cc00103f000b4101211f024020022d0084084101470d00410221212002280288082124200241ec106a2125200241c00e6a21030c020b41022121200241ec106a41026a201841026a2d00003a0000200241c00e6a41086a201641086a290200370300200241c00e6a41106a201641106a290200370300200241c00e6a41186a201641186a2d00003a0000200220182f00003b01ec10200220162902003703c00e4100211f2002280288082124200241ec106a2125200241c00e6a21030c010b4101211f024020022d0084084101460d00200241ec106a41026a201841026a2d00003a0000200241c00e6a41086a201641086a290200370300200241c00e6a41106a201641106a290200370300200241c00e6a41186a201641186a2d00003a0000200220182f00003b01ec10200220162902003703c00e4100211f0b2002280288082124200241c0086a2903002131200241b0086a290300213220022903b808212320022903a80821334103212120022802c8082120200241ec106a2125200241c00e6a21030b200241e8106a41026a202541026a2d00003a0000200241c00d6a41086a200341086a290200370300200241c00d6a41106a200341106a290200370300200241c00d6a41186a200341186a280200360200200220252f00003b01e810200220032902003703c00d0b201220022f01e8103b0000201020022903c00d370200200241b80b6a2031370300200241a80b6a2032370300201241026a200241e8106a41026a2d00003a0000201041086a200241c00d6a41086a290300370200201041106a200241c00d6a41106a290300370200201041186a200241c00d6a41186a280200360200200220233703b00b200220333703a00b2002201f3a00fc0a200220213602f80a200220243602800b200220203602c00b2002411a3602f00a0b4100211f200241003b01c00e200241c80a6a200241f00a6a200241c00e6a10ac030240024020022802a80a22240d000c010b20022802b00a2203417f4c0d070240024020030d00410021214101211f0c010b20031033221f450d0a200321210b0240024020212003490d00202121200c010b202141017422202003202020034b1b22204100480d09024020210d0020201033221f450d0c0c010b20212020460d00201f202120201037221f450d0b0b201f20242003109d081a2003ad4220862020ad8421230b410121030240024020022802b40a4101460d0020022802a80a450d01200241f00a6a200710f00420023502f80a42208620022802f00a2221ad84100720022802f40a450d01202110350c010b20022802b80a21030240024020022802bc0a222141014b0d00200241003602b40a0c010b200241013602b40a20022021417f6a3602bc0a0b200128022428020020036a2103024020022802a80a450d00200241f00a6a200310f30420022802f40a212420022802f00a2125200241f00a6a200710f00420023502f80a213120022802f00a2120410810332221450d0a2021200336000020214100202420254101461b36000420314220862020ad842021ad428080808080018410022021103520022802f40a450d00202010350b200241f00a6a200241f8076a41d002109d081a2003200241f00a6a410110cb04024020022802ac0d4102460d00024020022802a00d2203450d0020022802a40d450d00200310350b200241f00a6a10ba020b410021030b20012802242802002120200220062900003703f00a2002200641076a2800003600f70a0240024020022903c80a4201510d00410421210c010b20022d00e00a212420022903d00a2131200220022800f70a3600c70e200220022903f00a3703c00e4104212120314202510d00200220022800c70e3600f70a200220022903c00e3703f00a202421210b200220022903f00a3703c00d200220022800f70a3600c70d200520022903c00d370000200541076a20022800c70d360000200220213a008c0b200220233702840b2002201f3602800b2002201e3602fc0a200220203602f80a200241013602f40a200241153a00f00a41b0b4cc004100200241f00a6a10d40120012802282022370300024020030d00410421030c020b024020022802a80a2203450d0020022802ac0a450d00200310350b200241f8076a10ba02410421030c010b200241f00a6a200241f8076a41bc02109d081a200241c00e6a41086a221f20212903003703002002201c2903003703c00e024020034103470d00410421030c010b200241f8076a200241f00a6a41bc02109d081a200241c00d6a41086a201f290300370300200220022903c00e3703c00d0b2001200128021841016a360218200241e8026a200241f8076a41bc02109d081a200241d8026a41086a200241c00d6a41086a290300370300200220022903c00d3703d802024020034104470d00200128021022032001280214470d010c020b0b200241f00a6a200241e8026a41bc02109d081a200241f8076a41086a2201200241d8026a41086a290300370300200220022903d8023703f80720034103470d010b200041033602bc020c010b2000200241f00a6a41bc02109d08220420033602bc02200420022903f8073703c002200441c8026a20012903003703000b200241f0106a24000f0b1044000b103e000b1045000b103c000bf41503027f017e087f23004190016b220324004189fec600ad4280808080900184100122042900002105200341c0006a41086a200441086a290000370300200320053703402004103541e28cc500ad4280808080e00084100122042900002105200341d8006a41086a200441086a2900003703002003200537035820041035200320003602082003200341086aad4280808080c00084100322042900003703182004103520034184016a2003410c6a3602002003200341186a41086a36027c2003200341086a360280012003200341186a360278200341286a200341f8006a107b0240024002400240024002400240024002400240024002402003280230220641206a2207417f4c0d00200328022821080240024020070d0041002104410121090c010b200710332209450d02200721040b024002402004410f4d0d002004210a0c010b2004410174220a4110200a41104b1b220a4100480d07024020040d00200a103322090d010c0d0b2004200a460d0020092004200a10372209450d0c0b20092003290340370000200941086a200341c0006a41086a29030037000002400240200a4170714110460d00200a21040c010b200a41017422044120200441204b1b22044100480d07200a2004460d002009200a200410372209450d0c0b20092003290358370010200941186a200341d8006a41086a29030037000002400240200441606a2006490d002004210b0c010b200641206a220a2006490d072004410174220b200a200b200a4b1b220b4100480d072004200b460d0020092004200b10372209450d0c0b200941206a20082006109d081a0240200328022c450d00200810350b200341d8006a2007ad4220862009ad842205100510c2010240024020032802580d00410410332204450d032003420437027c200320043602784100200341f8006a1077200341106a200328028001360200200320032903783703080c010b200341086a41086a200341d8006a41086a280200360200200320032903583703080b200341186a41086a200341086a41086a2802002204360200200320032903083703182001200241d0026c6a210a024002402004450d00200341f8006a20032802182004200210f10420032802784101470d01200328021c450d0b200328021810350c0b0b2002200341186a1077200a2001460d08200241d0026c210720012104034002400240200441bc026a2802004102470d0002400240200328021c2003280220220a460d00200328021821060c010b200a41016a2206200a490d0b200a41017422082006200820064b1b22084100480d0b02400240200a0d004100210a024020080d00410121060c020b200810332206450d120c010b20032802182106200a2008460d002006200a200810372206450d112003280220210a0b2003200836021c200320063602180b2006200a6a41003a00002003200a41016a3602200c010b02400240200328021c2003280220220a460d00200328021821060c010b200a41016a2206200a490d0a200a41017422082006200820064b1b22084100480d0a02400240200a0d004100210a024020080d00410121060c020b200810332206450d110c010b20032802182106200a2008460d002006200a200810372206450d102003280220210a0b2003200836021c200320063602180b2006200a6a41013a00002003200a41016a3602202004200341186a10da040b200441d0026a2104200741b07d6a22070d000c090b0b200328027c2108024020034184016a2802002204200341f8006a41086a2802002207460d002003280220200420076b6a220620024102746a220c417f4c0d0102400240200c0d004100210c4101210d0c010b200c1033220d450d030b2003200d3602282003200c36022c200320063602302003200341286a3602782008200341f8006a200410f20420062004490d03200328023022082006490d04200328022022082007490d052003280228210c2003280218210d2003200620046b22063602382003200820076b220836023c20062008470d06200c20046a200d20076a2006109d081a0240200a2001460d00200241d0026c210720012104034002400240200441bc026a2802004102470d0002400240200328022c2003280230220a460d00200328022821060c010b200a41016a2206200a490d0c200a41017422082006200820064b1b22084100480d0c02400240200a0d004100210a024020080d00410121060c020b200810332206450d130c010b20032802282106200a2008460d002006200a200810372206450d122003280230210a0b2003200836022c200320063602280b2006200a6a41003a00002003200a41016a3602300c010b02400240200328022c2003280230220a460d00200328022821060c010b200a41016a2206200a490d0b200a41017422082006200820064b1b22084100480d0b02400240200a0d004100210a024020080d00410121060c020b200810332206450d120c010b20032802282106200a2008460d002006200a200810372206450d112003280230210a0b2003200836022c200320063602280b2006200a6a41013a00002003200a41016a3602302004200341286a10da040b200441d0026a2104200741b07d6a22070d000b0b2003280230210a200328022c210720032802282104200328021c450d09200328021810350c090b2003200341186a3602782008200341f8006a200710f204200a2001460d07200241d0026c210720012104034002400240200441bc026a2802004102470d0002400240200328021c2003280220220a460d00200328021821060c010b200a41016a2206200a490d0a200a41017422082006200820064b1b22084100480d0a02400240200a0d004100210a024020080d00410121060c020b200810332206450d110c010b20032802182106200a2008460d002006200a200810372206450d102003280220210a0b2003200836021c200320063602180b2006200a6a41003a00002003200a41016a3602200c010b02400240200328021c2003280220220a460d00200328021821060c010b200a41016a2206200a490d09200a41017422082006200820064b1b22084100480d0902400240200a0d004100210a024020080d00410121060c020b200810332206450d100c010b20032802182106200a2008460d002006200a200810372206450d0f2003280220210a0b2003200836021c200320063602180b2006200a6a41013a00002003200a41016a3602202004200341186a10da040b200441d0026a2104200741b07d6a2207450d080c000b0b1044000b1045000b2004200641e88cc5001059000b2006200841e88cc5001058000b2007200841f88cc5001059000b200341d8006a41146a410a360200200341e4006a410c360200200341c0006a41146a41033602002003200341386a36027020032003413c6a360274200341f8006a41146a410036020020034203370244200341a0b3cc003602402003410c36025c200341b0b4cc00360288012003420137027c200341f4b3cc003602782003200341d8006a3602502003200341f8006a3602682003200341f4006a3602602003200341f0006a360258200341c0006a41b0b4cc00104c000b103e000b2003280220210a200328021c2107200328021821040b2004450d002005200aad4220862004ad84100202402007450d00200410350b200b450d01200910350c010b0240200b450d00200910350b200341d8006a200010c9042003280258210420033502602105200341f8006a2001200210d90420054220862004ad842003350280014220862003280278220aad8410020240200328027c450d00200a10350b200328025c450d00200410350b20034190016a24000f0b103c000b81ad010a017f017e017f047e047f027e0b7f067e037f027e230041f00c6b22012400200141003602e003200142013703d803024002400240024020004180ee05700d0041a29bc800ad4280808080f00084220210012203290000210420032900082105200310354189eaca00ad4280808080f00084100122032900002106200329000821072003103520012007370288082001200637028008200120053702f807200120043702f007200141a00a6a200141f0076a10fe0120012902a40a420020012802a00a22031b21042003410120031b2103024020012802dc0341ffffff3f71450d0020012802d80310350b200120043702dc03200120033602d8032001200141d8036a3602e4032002100122032900002102200329000821042003103541ceb8c800ad42808080803084100122032900002105200329000821062003103520012006370288082001200537028008200120043702f807200120023702f007200141c0036a200141f0076a412010d701200141c0036a41106a290300210220012903c803210420012802c0032103200141e8036a41d1b8c800411010d503200141003a00c00a2002420020031b21062004420020031b2107200141e8036a21084120210341002109024002400240024002400340200141003a00f007200141f0076a20082003410047220a109d081a024020030d00200141003a00f0070b2003200a490d01200141a00a6a20096a20012d00f0073a00002001200941016a220b3a00c00a2003200a6b21032008200a6a2108200b2109200b4120470d000b20012903a00a210420012903a80a210520012903b00a210c20012903b80a210d4100210e200141a00a6a4100418002109f081a42002102200141d00c6a4200370300200141c80c6a4200370300200141c00c6a200d370300200141b80c6a200c370300200141b00c6a2005370300200120043703a80c200141c0003602a00c4108210f024020012802e40341086a2802000d004100210a0c050b41a29bc800ad4280808080f00084100122032900002104200329000821052003103541e1b8c800ad4280808080a0018410012203290000210c2003290008210d200310352001200d370288082001200c37028008200120053702f807200120043702f007200141f0056a200141f0076a10be020240024020012802f005220a0d00410021030c010b200141f0076aad4280808080800484100720012902f4052202422088a72103200a210f0b20012802e403220a200a2802082003108a0141d1c4c700ad4280808080e00084100122032900002104200329000821052003103541e7c4c700ad4280808080e0008410012203290000210c2003290008210d200310352001200d370288082001200c37028008200120053702f807200120043702f007200141b8036a200141f0076a412010c00120012802e40341086a28020041f4036a2203450d0120012802bc03210a20012802b8032108200141e4003a00f107200141e40041d0860320036e22036b3a00f007410021102001200141f0076a200341ff017141e4004b6a2d00004180fe126c200a410020081b6a36028c04200141003602980420014201370390042001410036029c04200142003703a804200142003703a004200142003703b804200142003703b004200141e8046a2001418c046a360200200141e4046a200141b0046a360200200141c0046a41206a2001419c046a360200200141dc046a200141a0046a360200200141d8046a20014190046a360200200141d4046a200141a00a6a3602002001200f2002422088a7220341e8006c22086a3602cc042001200f3602c80420012002a722113602c4042001200f3602c0042001200141e4036a3602d0040240024002402003450d00200141f0076a410172210b200141d0046a2112200f210303402001200341e8006a22093602c80420032d0000210a200141f0056a200341016a41e700109d081a200a4102460d012001200a3a00f007200b200141f0056a41e700109d081a20014190076a2012200141f0076a10ae062001290390074201510d0220092103200841987f6a22080d000b0b4108210b02402011450d00201141e8006c450d00200f10350b410021110c010b200141d8066a41306a20014190076a41386a2903002202370300200141d8066a41286a20014190076a41306a2903002204370300200141d8066a41206a20014190076a41286a2903002205370300200141b8056a41086a220b20014190076a41106a290300370300200141b8056a41106a220920014190076a41186a290300370300200141b8056a41186a221220014190076a41206a290300370300200141b8056a41206a22082005370300200141b8056a41286a220a2004370300200141b8056a41306a2203200237030020012001290398073703b80520014180056a41306a220f200329030037030020014180056a41286a2203200a29030037030020014180056a41206a220a200829030037030020014180056a41186a2208201229030037030020014180056a41106a2212200929030037030020014180056a41086a2209200b290300370300200120012903b8053703800541381033220b450d07200b200129038005370300200b41306a200f290300370300200b41286a2003290300370300200b41206a200a290300370300200b41186a2008290300370300200b41106a2012290300370300200b41086a200929030037030020014281808080103702f4042001200b3602f0042009200141c0046a41086a29030022023703002003200141c0046a41286a280200360200200a200141c0046a41206a2903003703002008200141c0046a41186a2903003703002012200141c0046a41106a290300370300200120012903c00437038005024002402002a72203200128028c05220a470d00410121100c010b200a41987f6a210f20014190076a41086a210a200141f0076a41017221114101211003402001200341e8006a22093602880520032d00002108200141f0056a200341016a41e700109d081a20084102460d01200120083a00f0072011200141f0056a41e700109d081a20014190076a2012200141f0076a10ae0602402001290390074201510d00200f2003462108200921032008450d010c020b200141d8066a41306a200a41306a2903002202370300200141d8066a41286a200a41286a2903002204370300200141d8066a41206a200a41206a2903002205370300200141b8056a41086a2208200a41086a290300370300200141b8056a41106a2213200a41106a290300370300200141b8056a41186a2214200a41186a290300370300200141b8056a41206a22152005370300200141b8056a41286a22162004370300200141b8056a41306a221720023703002001200a2903003703b805200141f0076a41306a22182017290300370300200141f0076a41286a22172016290300370300200141f0076a41206a22162015290300370300200141f0076a41186a22152014290300370300200141f0076a41106a22142013290300370300200141f0076a41086a22132008290300370300200120012903b8053703f0070240201020012802f404470d00200141f0046a20104101108b0120012802f004210b0b200b201041386c6a220820012903f007370300200841306a2018290300370300200841286a2017290300370300200841206a2016290300370300200841186a2015290300370300200841106a2014290300370300200841086a20132903003703002001201041016a22103602f804200f20034721082009210320080d000b0b02402001280284052203450d00200341e8006c450d0020012802800510350b20012802f40421110b41a29bc800ad4280808080f00084100122032900002102200329000821042003103541b39bc800ad4280808080d000841001220329000021052003290008210c200310352001200c370288082001200537028008200120043702f807200120023702f007200141f0076aad4280808080800484220c1008024020012903a004200141a0046a41086a29030084500d00024002402001280298042203450d00200128029004210a200141a00a6a2003417f6a10af0622082003490d0120082003419cb9c8001042000b200142f0f2bd99f7edd8b4e5003703f007200141f0056a200141f0076a108106200142f0f2bd99f7edd8b4e50037039007200141f0076a20014190076a10e00120014190076a200141f0056a200141f0076a20012903a004200141a8046a290300410110e6020c010b200a20084105746a200128028c0420012903a004200141a8046a29030010b0060b024020012903b0042202200141b0046a41086a290300220484500d00200142f0f2bd99f7edd8b4e5003703f007200141f0056a200141f0076a10e001200142f0f2bd99f7edd8b4e50037039007200141f0076a20014190076a10810620014190076a200141f0056a200141f0076a20012903b004200141b8046a290300410110e6024200200620047d2007200254ad7d2204200720027d2202200756200420065620042006511b22031b21064200200220031b21070b0240024020100d004100210a0c010b201041386c210a200b41046a2109200141a00a6a200128029c04417f6a10af06210f200b2103034020092108200a450d0402402003290328200341306a29030084500d00200a41486a210a200841386a210920032802002112200341386a21032012200f4d0d010b0b200141f0056a41186a200841186a290000370300200141f0056a41106a200841106a290000370300200141f0056a41086a200841086a290000370300200120082900003703f00541002108200141003602f807200142013703f007200141f0076a4100201041386c221241386d108a0120012802f007220f20012802f80722094105746a21030340200b20086a220a41046a2902002102200a410c6a2902002104200a41146a2902002105200341186a200a411c6a290200370000200341106a2005370000200341086a200437000020032002370000200341206a2103200941016a21092012200841386a2208470d000b200120093602f80702402011450d00201141386c450d00200b10350b20012802f407210a20012802e4032203280200200328020810ac0620012802e403220328020821082003280200211241a29bc800ad4280808080f00084220210012203290000210420032900082105200310354189eaca00ad4280808080f0008410012203290000210d200329000821192003103520012019370288082001200d37028008200120053702f807200120043702f0072001200141f0076a3602900720014120360294072012200820014190076a10a8062002100122032900002102200329000821042003103541f69bc800ad4280808080c000841001220329000021052003290008210d200310352001200d370288082001200537028008200120043702f807200120023702f007412010332203450d07200320012903f005370000200341186a200141f0056a41186a2208290300370000200341106a200141f0056a41106a2212290300370000200341086a200141f0056a41086a2210290300370000200c2003ad4280808080800484100220031035200141f0076a41086a41063a0000200141f9076a20012903f00537000020014181086a201029030037000020014189086a201229030037000020014191086a2008290300370000200141a4086a2009360200200141a0086a200a3602002001419c086a200f360200200141123a00f00741b0b4cc004100200141f0076a10d4014101210a0b200142f0f2bd99f7edd8b4e5003703f007200141f0056a200141f0076a10e00120014190076a200141f0056a108e02200141f0076a2001280290072208200128029807108f0220014180086a290300420020012903f00742015122031b210220012903f807420020031b21040240200128029407450d00200810350b41a29bc800ad4280808080f000841001220329000021052003290008210d2003103541ceb8c800ad428080808030841001220329000021192003290008211a200310352001201a3702880820012019370280082001200d3702f807200120053702f00720014200200420077d22052005200456200220067d2004200754ad7d220420025620042002511b22031b4201884200200420031b2202423f8684220442808094f6c2d7e8d800200442808094f6c2d7e8d80054410020024201882202501b22031b220420077c22073703f00520012002420020031b20067c2007200454ad7c22063703f805200c200141f0056aad42808080808002841002200a201145720d03201141386c450d03200b10350c030b200a200341b89dcc001059000b41f0b8c8004119418cb9c800103f000b41b3b9c80041d700418cbac8001064000b024020012802940441ffffff3f71450d0020012802900410350b20012802e40341086a280200210a0b41a29bc800ad4280808080f000842219100122032900002102200329000821042003103541a99bc800ad4280808080a001841001220329000021052003290008210c200310352001200c370288082001200537028008200120043702f807200120023702f007200141b0036a200141f0076a412010c00102400240410020012802b403410020012802b0031b2203200a6b220a200a20034b1b2203410a2003410a491b22080d0041082111410021130c010b20191001220329000021022003290008210420031035419cbac800ad4280808080c000841001220329000021052003290008210c200310352001200c370288082001200537028008200120043702f807200120023702f007200141f0056a200141f0076a10be020240024020012802f00522180d00410821184200211b4100210a410021030c010b20012902f405221b422088a72103201ba7210a0b200141003602c005200142083703b80502400240024002402003450d000240201b422088a7220b0d00410821114100210e0c030b20032008200820034b1b210f201841286a21034100210e41082111410021174200210242002104410021124100210a4100210802400340024002402012200f4f0d00024002400240200341106a2903002205200341186a290300220c84500d00200220057c220d2007562004200c7c200d200254ad7c220420065620042006511b450d01200d21020c030b201741ff01710d02200141f0076a41186a2209200341386a290000370300200141f0076a41106a2210200341306a290000370300200141f0076a41086a2213200341286a2900003703002001200341206a2900003703f00702400240200341586a2d00004101470d002001200341596a221441036a28000036008305200341086a2903002105200341606a2215290000210c201541086a290000210d201428000021142003290300211a200141c0046a41086a200341706a221541086a2d00003a00002001201436028005200120152900003703c004410121140c010b200341606a2214290300210c201441086a290300210d410021140b200141f0056a41186a22152009290300370300200141f0056a41106a22162010290300370300200141f0056a41086a2210201329030037030020014190076a41086a2213200141c0046a41086a290300370300200120012903f0073703f00520012001280280053602b00420012001280083053600b304200120012903c004370390070240200e20012802bc05470d00200141b8056a200e410110960120012802b805211120012802c005210e0b2011200e41e8006c6a220920143a0000200941106a200d370300200941086a200c370300200920012802b004360001200941046a20012800b304360000200941206a2013290300370300200129039007210c200941c0006a420037030020094200370338200941306a2005370300200941286a201a370300200941186a200c370300200920012903f005370348200941d0006a2010290300370300200941d8006a2016290300370300200941e0006a2015290300370300410121172001200e41016a220e3602c0050c010b200141f0076a41186a2209200341386a290000370300200141f0076a41106a2210200341306a290000370300200141f0076a41086a2213200341286a2900003703002001200341206a2900003703f00702400240200341586a2d00004101470d002001200341596a221441036a28000036008305200341086a2903002102200341606a2215290000211a201541086a290000211c201428000021142003290300211d200141c0046a41086a200341706a221541086a2d00003a00002001201436028005200120152900003703c004410121140c010b200341606a2214290300211a201441086a290300211c410021140b200141d8066a41186a22152009290300370300200141d8066a41106a22162010290300370300200141d8066a41086a2210201329030037030020014190076a41086a2213200141c0046a41086a290300370300200120012903f0073703d80620012001280280053602b00420012001280083053600b304200120012903c004370390070240200e20012802bc05470d00200141b8056a200e410110960120012802b805211120012802c005210e0b2011200e41e8006c6a220920143a0000200941106a201c370300200941086a201a370300200920012802b004360001200941046a20012800b304360000200941206a2013290300370300200129039007211a200941c0006a200c37030020092005370338200941306a2002370300200941286a201d370300200941186a201a370300200920012903d806370348200941d0006a2010290300370300200941d8006a2016290300370300200941e0006a20152903003703002001200e41016a220e3602c005200d21020b200a41016a210a201241016a21120c010b0240200a0d004100210a0c010b2008200a6b2209200b4f0d02200141f0076a2003200a41987f6c6a41586a220941e800109d081a2009200341586a221041e800109e081a2010200141f0076a41e800109d081a0b200341e8006a2103200b200841016a2208460d030c000b0b2009200b41f485cc001042000b410821114100210e410021130c020b0240200a417f6a200b4f0d00201b42ffffffff0f83200b200a6bad42208684211b0b2012450d0041a29bc800ad4280808080f000841001220329000021022003290008210420031035419cbac800ad4280808080c00084100122032900002105200329000821062003103520012006370288082001200537028008200120043702f807200120023702f007200141f0056a2018201b422088a710b106200141f0076aad428080808080048420013502f80542208620012802f005220aad841002201ba72103024020012802f405450d00200a10350b02402003450d00200341e8006c450d00201810350b20012802bc0521130c020b20012802bc052113201ba7210a0b200a450d00200a41e8006c450d00201810350b2019100122032900002102200329000821042003103541e1b8c800ad4280808080a00184100122032900002105200329000821062003103520012006370288082001200537028008200120043702f807200120023702f007200141f0056a2011200e10b106200141f0076aad428080808080048420013502f80542208620012802f0052203ad841002024020012802f405450d00200310350b41002103024020012802e403220b41086a280200220a4102762208450d00410021032008200a460d00410021080340200841026a2103200a200841046a411e71762209450d01200321082009200a470d000b0b4100211203400240201241017422124101722208ad220220027e2202422088a70d00201220082002a7200a2003411f71764b1b21120b02402003450d0041002003417e6a2208200820034b1b21030c010b0b02402012450d0002400240200e450d00200e41e8006c210f201141c8006a21104100210e0c010b2012417f6a21080340200a450d05200141a00a6a200a417f6a10af062203200a4f0d062008450d022008417f6a210820012802e403280208210a0c000b0b0340200a450d04200b2802002108200141a00a6a200a417f6a10af062203200a4f0d05200e41016a210e200820034105746a210b200f21092010210a024002400340200141f0076a200a200b10b20620013502f807210220012802f0072108410110332203450d01200341003a000020024220862008ad842003ad42808080801084100220031035024020012802f407450d00200810350b200a41e8006a210a200941987f6a2209450d020c000b0b103c000b200e2012460d0120012802e403220b280208210a0c000b0b2013450d00201341e8006c450d00201110350b02400240024002400240024002400240024020004180a70c7022180d00024020012802e0030d0041a29bc800ad4280808080f0008410012203290000210220032900082104200310354189eaca00ad4280808080f00084100122032900002105200329000821062003103520012006370288082001200537028008200120043702f807200120023702f007200141a00a6a200141f0076a10fe0120012902a40a420020012802a00a22031b21022003410120031b2103024020012802dc0341ffffff3f71450d0020012802d80310350b200120033602d803200120023702dc032002428080808010540d010b41a29bc800ad4280808080f00084100122032900002102200329000821042003103541ccbac800ad4280808080800184100122032900002105200329000821062003103520012006370288082001200537028008200120043702f807200120023702f007200141a00a6a200141f0076a412010d501024020012d00a00a4101470d00200141a90a6a2800002103200141ad0a6a280000210a200141b10a6a2800002108200141b50a6a2800002109200141b90a6a280000210b20012800a10a211220012800a50a210e2001200141bd0a6a2800003602bc0a2001200b3602b80a200120093602b40a200120083602b00a2001200a3602ac0a200120033602a80a2001200e3602a40a200120123602a00a0240024020012802e003220a450d0020012802d8032103200a410574210a4100210b410021120340200141f0076a200310b30620012802f007220920012802f80710e40241ff01712108024020012802f407450d00200910350b0240024002402008417e6a220841014b0d0020080e020102010b200b41016a210b0c010b201241016a21120b200341206a2103200a41606a220a0d000b2012200b4a0d010b200141a00a6a10b40641a29bc800ad4280808080f0008410012203290000210220032900082104200310354189eaca00ad4280808080f00084100122032900002105200329000821062003103520012006370288082001200537028008200120043702f807200120023702f007200141f0056a200141f0076a10fe0120012902f405420020012802f00522031b21022003410120031b2103024020012802dc0341ffffff3f71450d0020012802d80310350b200120023702dc03200120033602d8030b41a29bc800ad4280808080f00084100122032900002102200329000821042003103541d4bac800ad4280808080d00184100122032900002105200329000821062003103520012006370288082001200537028008200120043702f807200120023702f007200141f0076aad428080808080048410080b024020012802e00341024d0d00200141f0056a41e1bac800411110d503200141003a00c00a200141f0056a210841202103410021090340200141003a00f007200141f0076a20082003410047220a109d081a024020030d00200141003a00f0070b2003200a490d03200141a00a6a20096a20012d00f0073a00002001200941016a220b3a00c00a2003200a6b21032008200a6a2108200b2109200b4120470d000b20012903a00a210220012903a80a210420012903b00a210520012903b80a2106200141a00a6a4100418002109f081a200141d00c6a4200370300200141c80c6a4200370300200141c00c6a2006370300200141b80c6a2005370300200141b00c6a2004370300200120023703a80c200141c0003602a00c20012802e0032203417f6a220a450d032003450d04024002402003417e6a220a450d0020012802d8032108200141a00a6a2003417d6a10af062209200a490d012009200a419cb9c8001042000b41a0bac800411c4184bbc8001064000b41a29bc800ad4280808080f00084100122032900002102200329000821042003103541ccbac800ad4280808080800184100122032900002105200329000821062003103520012006370288082001200537028008200120043702f807200120023702f007412010332203450d0a2003200841206a20094105746a220a290000370000200341186a200a41186a2208290000370000200341106a200a41106a2209290000370000200341086a200a41086a220b290000370000200141f0076aad42808080808004842003ad4280808080800484100220031035200141f0076a41086a410a3a0000200141f9076a200a29000037000020014181086a200b29000037000020014189086a200929000037000020014191086a2008290000370000200141123a00f00741b0b4cc004100200141f0076a10d4010c010b41a29bc800ad4280808080f00084100122032900002102200329000821042003103541ccbac800ad4280808080800184100122032900002105200329000821062003103520012006370288082001200537028008200120043702f807200120023702f007200141f0076aad428080808080048410070b024020012802dc0341ffffff3f71450d0020012802d80310350b200141f0076a41186a22094200370300200141f0076a41106a22034200370300200141f0076a41086a220a4200370300200142003703f00741d1c4c700ad4280808080e00084100122082900002102200a200841086a290000370300200120023703f0072008103541edc4c700ad4280808080a00184100122082900002102200141a00a6a41086a220b200841086a290000370300200120023703a00a20081035200320012903a00a2202370300200141f0056a41086a200a290300370300200141f0056a41106a2002370300200141f0056a41186a200b290300370300200120012903f0073703f005200141a00a6a200141f0056a412010d50120012d00a00a21082009200141b90a6a2900003703002003200141b10a6a290000370300200a200141a90a6a290000370300200120012900a10a3703f0070240024020084101460d0020014190076a41186a420037030020014190076a41106a420037030020014190076a41086a420037030020014200370390070c010b20014190076a41186a200929030037030020014190076a41106a200329030037030020014190076a41086a200a290300370300200120012903f007370390070b200141f0076a41186a22094200370300200141f0076a41106a220b4200370300200141f0076a41086a22084200370300200142003703f0074182e9ca00ad42808080808003841001220a29000021022008200a41086a290000370300200120023703f007200a1035419ae9ca00ad4280808080e001841001220a2900002102200141a00a6a41086a2212200a41086a290000370300200120023703a00a200a1035200320012903a00a370000200341086a2012290300370000200141f0056a41086a2008290300370300200141f0056a41106a200b290300370300200141f0056a41186a2009290300370300200120012903f0073703f005200141d8066a200141f0056a412010b502024002400240024020012802d806220a0d0041002103200141003602c005200142013703b805200920014190076a41186a290300370300200b20014190076a41106a290300370300200820014190076a41086a29030037030020012001290390073703f007200141f0076a21080c010b200120012902dc0622023702bc052001200a3602b8052002a7210b02402002422088a7220341d100490d00200141a00a6a41186a220920014190076a41186a290300370300200141a00a6a41106a221220014190076a41106a290300370300200141a00a6a41086a220e20014190076a41086a29030037030020012001290390073703a00a2000417f6a41d10070220820034f0d07200a20084105746a220820012903a00a370000200841186a2009290300370000200841106a2012290300370000200841086a200e2903003700000c030b200141f0076a41186a20014190076a41186a290300370300200141f0076a41106a20014190076a41106a290300370300200141f0076a41086a20014190076a41086a29030037030020012001290390073703f007200141f0076a21082003200b470d010b200141b8056a20034101108a0120012802bc05210b20012802b805210a20012802c00521030b200a20034105746a22092008290000370000200941186a200841186a290000370000200941106a200841106a290000370000200941086a200841086a2900003700002001200341016a22033602c0050b200141a00a6a41186a4200370300200141a00a6a41106a22124200370300200141a00a6a41086a22084200370300200142003703a00a4182e9ca00ad42808080808003841001220929000021022008200941086a290000370300200120023703a00a20091035419ae9ca00ad4280808080e00184100122092900002102200141f0056a41086a220e200941086a290000370300200120023703f00520091035201220012903f0052202370300200141f0076a41086a2008290300370300200141f0076a41106a2002370300200141f0076a41186a200e290300370300200120012903a00a3703f00702400240200a0d00200141f0076aad428080808080048410070c010b200141203602a40a2001200141f0076a3602a00a200a2003200141a00a6a10c504200b41ffffff3f71450d00200a10350b4200211e200141a00a6a41186a220b4200370300200141a00a6a41106a220a4200370300200141a00a6a41086a22034200370300200142003703a00a41f7edcb00ad4280808080f000841001220829000021022003200841086a290000370300200120023703a00a2008103541b6aac000ad4280808080900284100122082900002102200141f0056a41086a2209200841086a290000370300200120023703f00520081035200a20012903f0052202370300200141f0076a41086a22082003290300370300200141f0076a41106a22122002370300200141f0076a41186a220e2009290300370300200120012903a00a3703f007200141a8036a200141f0076a10f20120012802a803417d710d07200b4200370300200a420037030020034200370300200142003703a00a41a2e8cb00ad428080808080018422061001220f29000021022003200f41086a290000370300200120023703a00a200f103541e6f2c400ad428080808080028422071001220f29000021022009200f41086a290000370300200120023703f005200f1035200a20012903f005370000200a41086a2009290300370000200820032903003703002012200a290300370300200e200b290300370300200120012903a00a3703f007200141a00a6a200141f0076a10c602200120012802a00a2203410420031b221f3602900720012902a40a420020031b2205422088a7220e450d064100210a201f21034100210803400240024002402003280200200341086a22092802002003410c6a280200200341146a280200200341186a220b28020010fd01450d00200a0d014100210a0c020b200a41016a210a0c010b2008200a6b2212200e4f0d06200141a00a6a41186a220f2003200a41646c6a221241186a2210280200360200200141a00a6a41106a2211201241106a2213290200370300200141a00a6a41086a2214201241086a2215290200370300200120122902003703a00a20092902002102200341106a22162902002104200b280200211720122003290200370200201020173602002013200437020020152002370200200b200f2802003602002016201129030037020020092014290300370200200320012903a00a3702000b2003411c6a2103200e200841016a2208460d060c000b0b200a200341b89dcc001059000b4101410041f4bac8001059000b200a410041f4bac8001058000b2008200341f0e9ca001042000b2012200e41f485cc001042000b200a450d00200e200a490d00201f200e200a6b220e411c6c6a200a10c802200542ffffffff0f8321050b2001280290072103200141a00a6a41186a4200370300200141a00a6a41106a22094200370300200141a00a6a41086a220a4200370300200142003703a00a2006100122082900002102200a200841086a290000370300200120023703a00a200810352007100122082900002102200141f0056a41086a220b200841086a290000370300200120023703f00520081035200920012903f0052202370300200141f0076a41086a200a290300370300200141f0076a41106a2002370300200141f0076a41186a200b290300370300200120012903a00a3703f007024020030d00200141f0076aad428080808080048410070c010b2005a7210a200141a00a6a2003200e10c704200141f0076aad428080808080048420013502a80a42208620012802a00a2208ad841002024020012802a40a450d00200810350b2003200e10c802200a450d00200a411c6c450d00200310350b024020004180e101700d00200142f0f2bda1a7ee9cb9f9003703a00a200141f0076a200141a00a6a10e001200141f0056a200141f0076a108e02200141a00a6a20012802f005220a20012802f805108f02200141a00a6a41106a2217290300420020012903a00a42015122031b210420012903a80a420020031b2102024020012802f405450d00200a10350b2001420020042002428080e983b1de1654ad7d2205200242808097fccea1697c22062002562005200456200242ffffe883b1de16561b22031b22023703880520014200200620031b220437038005200141a00a6a41186a221f200237030020172004370300200141a00a6a41086a220f41013a00002001410c3a00a00a41b0b4cc004100200141a00a6a10d401200141003a00a004200142003703c005200142003703b805201f420037030020174200370300200f4200370300200142003703a00a4186f0cb00ad4280808080800184221a100122032900002102200141f0056a41086a2214200341086a290000370300200120023703f00520031035200f2014290300370300200120012903f0053703a00a419bf0cb00ad4280808080900184221c1001220329000021022014200341086a290000370300200120023703f00520031035201720012903f0052202370300200141f0076a41086a2211200f290300370300200141f0076a41106a2002370300200141f0076a41186a22162014290300370300200120012903a00a3703f007200141a00a6a200141f0076a10c50220012802a00a2203410420031b2120024020012902a40a420020031b2219422088220da72210450d00200141a90a6a210b200141b0086a211220014190086a2113200141d80a6a2115200141b8076a2121202021034100210a410021080240034020014190076a2003280200220e10b506200141a00a6a200128029007220920012802980710df0220012903a00a2104200141f0076a200f41e000109d081a42002102024020044201520d00200141f0056a200141f0076a41e000109d081a420121020b0240200128029407450d00200910350b024002400240200250450d00200a41016a210a0c010b200141f0076a200141f0056a41e000109d081a0240200129038005220520012903f007220654220920014180056a41086a2903002202201129030022045420022004511b0d002001200520067d370380052001200220047d2009ad7d37038805200141a00a6a200e10b50620013502a80a42208620012802a00a2209ad841007024020012802a40a450d00200910350b20012903800821022001201629030022043703e006200120023703d80602402002200484500d00200120133602c00420014190076a2013200141d8066a200141c0046a10f0022001290390074201520d002001290398072102201520014190076a41106a290300370300200b2013290000370000200b41086a201341086a290000370000200b41106a201341106a290000370000200b41186a201341186a290000370000200120023703d00a200141003a00a80a200141033a00a00a41b0b4cc004100200141a00a6a10d4010b20012903f00721022001201129030022043703e006200120023703d80602400240200220048450450d00420021054200210642002104420021070c010b200120123602c00420014190076a2012200141d8066a200141c0046a10b002024002402001290390074201520d0020014190076a41106a290300210720012903980721040c010b2021290300210720012903b00721042001290398074201520d0020012903a0072102201520014190076a41186a290300370300200b2012290000370000200b41086a201241086a290000370000200b41106a201241106a290000370000200b41186a201241186a290000370000200120023703d00a200141003a00a80a200141033a00a00a41b0b4cc004100200141a00a6a10d4010b2011290300210620012903f00721050b200141b8056a41086a2209427f2009290300220220077c20012903b805220720047c220c2007542209ad7c22042009200420025420042002511b22091b3703002001427f200c20091b3703b80520152006370300200b2012290000370000200b41086a201241086a290000370000200b41106a201241106a290000370000200b41186a201241186a290000370000200120053703d00a200141023a00a80a2001410c3a00a00a2001200e3602cc0a41b0b4cc004100200141a00a6a10d401200a41016a210a0c010b200141013a00a0040240200a0d004100210a0c010b2008200a6b220920104f0d012003200a4102746b2209280200210e200920032802003602002003200e3602000b200341046a21032010200841016a2208460d020c010b0b2009201041f485cc001042000b200a417f6a20104f0d00201942ffffffff0f8321192010200a6b21100b201f4200370300200141a00a6a41106a220a4200370300200f4200370300200142003703a00a201a1001220329000021022014200341086a290000370300200120023703f00520031035200f2014290300370300200120012903f0053703a00a201c1001220329000021022014200341086a290000370300200120023703f00520031035201720012903f005370000201741086a20142903003700002011200f290300370300200141f0076a41106a200a2903003703002016201f290300370300200120012903a00a3703f007200141203602a40a2001200141f0076a3602a00a20202010200141a00a6a1095030240201942ffffffff0383500d00202010350b024020012d00a0040d004200210720014198036a200129038005220220014180056a41086a2203290300220442c0843d420010980820014188036a200129039803220520014198036a41086a290300220642c0fb42427f108408200141f8026a2005200642a0c21e4200108408200320042004200141f8026a41086a29030020012903f802220520022001290388037c2206420188220ca7417f200642a0c21e7e2206428080808080c8d007541b2006200c42c0fb427e7c42a0c21e566aad7c2206200554ad7c22052006200256200520045620052004511b220a1b22057d200220022006200a1b220454ad7d3703002001200220047d3703800502400240200420058450450d004200210c0c010b200141f0076a41186a22124200370300200141f0076a41106a220a4200370300200141f0076a41086a22034200370300200142003703f00741b6fdc600ad4280808080800184220210012209290000210620014190076a41086a2208200941086a2900003703002001200637039007200910352003200829030037030020012001290390073703f00741e489c200ad4280808080d0018422061001220b2900002107200141c0046a41086a2209200b41086a290000370300200120073703c004200b1035200a20012903c0042207370300200141d8066a41086a220e2003290300370300200141d8066a41106a220f2007370300200141d8066a41186a22102009290300370300200120012903f0073703d806200141e0026a200141d8066a412010d701200141e0026a41106a290300210720012903e802210c20012802e002210b20124200370300200a420037030020034200370300200142003703f00720021001221229000021022008201241086a2900003703002001200237039007201210352003200829030037030020012001290390073703f00720061001220829000021022009200841086a290000370300200120023703c00420081035200a20012903c0042202370300200e2003290300370300200f200237030020102009290300370300200120012903f0073703d8062001420020074200200b1b220220057d200c4200200b1b2206200454ad7d2207200620047d220c200656200720025620072002511b22031b3703a80a20014200200c20031b3703a00a200141d8066aad4280808080800484200141a00a6aad428080808080028410022002200520031b210c2006200420031b21070b200141b8056a41086a2203427f20032903002202200c7c20012903b805220620077c22072006542203ad7c22062003200620025420062002511b22031b3703002001427f200720031b3703b805200141b80a6a2005370300200141b00a6a2004370300200141a00a6a41086a41043a00002001410c3a00a00a41b0b4cc004100200141a00a6a10d4010b200142f0f2bda1a7ee9cb9f9003703a00a200141f0056a200141a00a6a10e001200141c0056a290300210420012903b805210241002103200141003a00e803200141023a00b004200120043703980720012002370390072001200141f0056a3602c00402400240200220048450450d0042002105420021060c010b2001200141f0056a3602d8062001200141d8066a3602b00a2001200141b0046a3602ac0a2001200141c0046a3602a80a2001200141e8036a3602a40a200120014190076a3602a00a200141f0076a200141f0056a200141a00a6a10dc0341012103024020012802f0074101470d004200210620012903f80721050c010b20014198086a290300210620014190086a29030021054100210320012903f8074201520d00200141f0076a41106a290300210720012802d806210a200141d80a6a200141f0076a41186a290300370300200141d00a6a200737030041002103200141a00a6a41086a41003a0000200141a90a6a200a290000370000200141b10a6a200a41086a290000370000200141b90a6a200a41106a290000370000200141c10a6a200a41186a290000370000200141033a00a00a41b0b4cc004100200141a00a6a10d4010b024002400240024020030d00200141f0076a41186a220b4200370300200141f0076a41106a22034200370300200141f0076a41086a220a4200370300200142003703f00741b6fdc600ad4280808080800184221a10012209290000210720014190076a41086a2208200941086a290000370300200120073703900720091035200a200829030037030020012001290390073703f00741e489c200ad4280808080d00184221c100122122900002107200141c0046a41086a2209201241086a290000370300200120073703c00420121035200320012903c0042207370300200141d8066a41086a2212200a290300370300200141d8066a41106a220e2007370300200141d8066a41186a220f2009290300370300200120012903f0073703d806200141b0026a200141d8066a412010d701200420067d2002200554ad7d200620047d2005200254ad7d20052002582006200458200620045122101b22111b211d200220057d200520027d20111b2119200141b0026a41106a290300420020012802b00222111b210720012903b802420020111b210c2005200256200620045620101b0d01200b420037030020034200370300200a4200370300200142003703f007201a1001221029000021022008201041086a290000370300200120023703900720101035200a200829030037030020012001290390073703f007201c1001220829000021022009200841086a290000370300200120023703c00420081035200320012903c004370000200341086a20092903003700002012200a290300370300200e2003290300370300200f200b290300370300200120012903f0073703d8062001427f2007201d7c200c20197c2204200c542203ad7c22022003200220075420022007511b22031b3703a80a2001427f200420031b3703a00a200141a00a6a21030c020b4184b8c800ad4280808080a009841006200141f0076a41186a22124200370300200141f0076a41106a220a4200370300200141f0076a41086a22034200370300200142003703f00741b6fdc600ad4280808080800184220510012209290000210620014190076a41086a2208200941086a2900003703002001200637039007200910352003200829030037030020012001290390073703f00741e489c200ad4280808080d0018422061001220b2900002107200141c0046a41086a2209200b41086a290000370300200120073703c004200b1035200a20012903c0042207370300200141d8066a41086a220e2003290300370300200141d8066a41106a220f2007370300200141d8066a41186a22102009290300370300200120012903f0073703d806200141c8026a200141d8066a412010d701200141c8026a41106a290300210720012903d002210c20012802c802210b20124200370300200a420037030020034200370300200142003703f00720051001221229000021052008201241086a2900003703002001200537039007201210352003200829030037030020012001290390073703f00720061001220829000021052009200841086a290000370300200120053703c00420081035200a20012903c0042205370300200e2003290300370300200f200537030020102009290300370300200120012903f0073703d8062001427f20074200200b1b220520047c200c4200200b1b220420027c22062004542203ad7c22022003200220055420022005511b22031b3703a80a2001427f200620031b3703a00a200141d8066aad4280808080800484200141a00a6aad428080808080028410020c020b200b420037030020034200370300200a4200370300200142003703f007201a1001221029000021022008201041086a290000370300200120023703900720101035200a200829030037030020012001290390073703f007201c1001220829000021022009200841086a290000370300200120023703c00420081035200320012903c004370000200341086a20092903003700002012200a290300370300200e2003290300370300200f200b290300370300200120012903f0073703d806200142002007201d7d200c201954ad7d2202200c20197d2204200c56200220075620022007511b22031b3703a80a20014200200420031b3703a00a200141a00a6a21030b200141d8066aad42808080808004842003ad428080808080028410020b2001290380052102200141b80a6a20014180056a41086a290300370300200141b00a6a2002370300200141a00a6a41086a41053a00002001410c3a00a00a41b0b4cc004100200141a00a6a10d401200d42c097e8b2017e200d4280bfdf80017e7c4280e59af7007c211e0b024020180d0010a1020b02400240200041809c3170450d00200141a00a6a21090c010b200141f0056a41186a4200370300200141f0056a41106a22094200370300200141f0056a41086a220a4200370300200142003703f00541d9e3cb00ad428080808090018410012208290000210220014190076a41086a2203200841086a290000370300200120023703900720081035200a200329030037030020012001290390073703f00541efe3cb00ad4280808080d002841001220829000021022003200841086a29000037030020012002370390072008103520092001290390072202370300200141a00a6a41086a200a290300370300200141a00a6a41106a2002370300200141a00a6a41186a2003290300370300200120012903f0053703a00a024002400240024002400240200141a00a6a10bd02220341ff01714102460d00200141a00a6aad4280808080800484100720034101710d010b200141a00a6a200010e70420012d00a00a4104460d02200141f0076a200010ea040c010b200141a00a6a200010ea0420012d00a00a4104460d01200141f0076a200010e7040b20012d00f0074104460d01200141a00a6a411610e8040c020b200141043a00f0070b200141043a00a00a0b200141a00a6a21090b200120003602b805200141f0056a41186a22124200370300200141f0056a41106a2208420037030041082113200141f0056a41086a220a4200370300200142003703f00541d9e3cb00ad428080808090018422021001220b290000210420014190076a41086a2203200b41086a2900003703002001200437039007200b1035200a200329030037030020012001290390073703f00541e2e3cb00ad4280808080d001841001220b29000021042003200b41086a2900003703002001200437039007200b103520082001290390072204370300200141a00a6a41086a220e200a290300370300200141a00a6a41106a220f2004370300200141a00a6a41186a22102003290300370300200120012903f0053703a00a200141a8026a2009412010c00120012802ac02211120012802a80221142012420037030020084200370300200a4200370300200142003703f00520021001220b29000021022003200b41086a2900003703002001200237039007200b1035200a200329030037030020012001290390073703f00541cae3cb00ad4280808080f001841001220b29000021022003200b41086a2900003703002001200237039007200b103520082001290390072202370300200e200a290300370300200f200237030020102003290300370300200120012903f0053703a00a200141a0026a2009412010c0014100210e200120012802a402410020012802a0021b3602dc0620012011410020141b3602d8062001200141b8056a3602e006200141a00a6a200141d8066a200141d8066a41086a10b6060240024020012d00800b220a4103460d00200141f0076a200141a00a6a41e000109d081a2001200141a00a6a41e4006a2800003600b304200120012800810b3602b00441e80010332213450d022013200141f0076a41e000109d082203200a3a0060200320012802b004360061200341e4006a20012800b3043600002001428180808010370294072001200336029007200141f0056a41086a220b200141d8066a41086a280200360200200120012903d8063703f005200141a00a6a200141f0056a200b10b606024020012d00800b22094103470d004101210a4101210e0c020b41c9012108200141810b6a221241036a210f4101210e4101210a0340200141f0076a200141a00a6a41e000109d081a2001200f2800003600b304200120122800003602b004200141a00a6a200141f0076a41e000109d081a200120012800b30436008305200120012802b004360280050240200a200e470d0020014190076a200e410110960120012802900721130b201320086a2203419f7f6a200141a00a6a41e000109d081a2003417f6a20093a00002003200128028005360000200341036a2001280083053600002001200a41016a220a36029807200141a00a6a200141f0056a200b10b606200841e8006a2108200128029407210e20012d00800b22094103470d000c020b0b4100210a0b0240200a450d002013200a41e8006c6a2115200141f0076a41096a2118200141f0076a41106a2109200141a8066a2114200141a00a6a41086a2120200141a00a6a410172211f200141c9066a210f20014190076a41046a211641b6fdc600ad4280808080800184212220014198066a21172013210803402008280200210b200141a00a6a200841046a41dc00109d081a2001200841e1006a2800003602f0072001200841e4006a2800003600f307200841e0006a2d000022124103460d0120014190076a200141a00a6a41dc00109d081a200120012800f3073600eb03200120012802f0073602e803200141f0056a201641d800109d081a200f20012802e803360000200f41036a20012800eb03360000200120123a00c806200141f0076a41186a2210420037030020094200370300200141f0076a41086a22034200370300200142003703f00720221001220a29000021022003200a41086a290000370300200120023703f007200a103541e489c200ad4280808080d001841001220a2900002102200141c0046a41086a2211200a41086a290000370300200120023703c004200a1035200920012903c004370000200941086a2011290300370000200141d8066a41086a2003290300370300200141d8066a41106a2009290300370300200141d8066a41186a2010290300370300200120012903f0073703d80620014188026a200141d8066a412010d70120014188026a41106a2903002105200128028802210a2001290390022106200141f0056a41186a2903002123200141f0056a41086a290300211b41002103200129038006211d20012903f005211c0240200129039006220d4202882017290300220c423e86842202200c420288220484500d002002200d852004200c8584500d00410021030340200141f8016a200d200c200341046a41fe007110a408200341026a210320012903f8012202200141f8016a41086a290300220484500d012002200d852004200c85844200520d000b0b200841e8006a210820054200200a1b211920064200200a1b211a42002106420021040340200141d8016a20044201862006423f8884220442002006420186220642018422024200108408200141e8016a20024200200242001084080240200420012903e001220584200584420052200141e8016a41086a290300220520012903d801220720077c7c2207200554720d0020012903e8012105200141c8016a200d200c200341ff007110a40820042004200520012903c801562007200141c8016a41086a29030022055620072005511b220a1b210420062002200a1b21060b02402003450d0041002003417e6a220a200a20034b1b21030c010b0b410021030240201a4202882019423e868422022019420288220584500d002002201a85200520198584500d00410021030340200141b8016a201a2019200341046a41fe007110a408200341026a210320012903b8012202200141b8016a41086a290300220584500d012002201a852005201985844200520d000b0b4200210542002102034020014198016a20024201862005423f8884220242002005420186220542018422074200108408200141a8016a20074200200742001084080240200220012903a001220c84200c84420052200141a8016a41086a290300220c200129039801220d200d7c7c220d200c54720d0020012903a801210c20014188016a201a2019200341ff007110a40820022002200c20012903880156200d20014188016a41086a290300220c56200d200c511b220a1b210220052007200a1b21050b02402003450d0041002003417e6a220a200a20034b1b21030c010b0b024002400240024002402006200484500d0002400240024020120e03000102000b0340200141386a201d2023200620041098082005220c2002220d844200510d04200141386a41086a290300210220012903382105200141286a201c201b200c200d109808200520012903282219542002200141286a41086a290300220754200220075122031b0d062019200554200720025420031b0d03200141186a2005200220062004108408200141086a20192007200c200d108408201c200129030822027d2207201b200141086a41086a2903007d201c200254ad7d220284500d032023200141186a41086a2903007d2119201d20012903182205542103201d20057d21052006211c2004211b2007210620022104200c211d200d2123200520192003ad7d22028450450d000c060b0b0340200421072006210c20052002844200510d04200141e8006a201c201b200c2007109808200141f8006a201d2023200520021098082001290378220d2001290368221954200141f8006a41086a2903002204200141e8006a41086a290300220654200420065122031b0d052019200d54200620045420031b0d02200141d8006a200d200420052002108408200141c8006a20192006200c2007108408201c200129034822047d220d201b200141c8006a41086a2903007d201c200454ad7d220484500d022023200141d8006a41086a2903007d2119201d20012903582206542103201d20067d21062005211c2002211b200d210520042102200c211d20072123200620192003ad7d22048450450d000c050b0b201c201d56201b202356201b2023511b0d030b2001200b3602ac0a200141053a00a80a200141063a00a00a4100210341b0b4cc004100200141a00a6a10d4010c030b41d0c7c40041194194c5c800103f000b41d0c7c40041194194c5c800103f000b2001200b3602ac0a200141043a00a80a200141063a00a00a41b0b4cc004100200141a00a6a10d401024002400240024020012802a4062203450d00200141d8066a201410ee04200141a00a6a20012802d806221220012802e006221010d202200320006a210a024020012d00a00a2203410371222141034622110d00024020030e03000100000b0240024020110d0020210e03010001010b20012802c80a450d0020012802c40a10350b201f20012f00b8053b0000201f41026a200141b8056a41026a2d00003a000041002103200141003a00a00a2001200a3602a40a2020200141f0076a41c800109d081a0c020b2001200a3602d80a200141013602d40a20034102470d012010ad4220862012ad8410070c020b200141a00a6a41186a201441186a290000370300200141a00a6a41106a201441106a2900003703002020201441086a290000370300200120142900003703a00a200141f0076a200141a00a6a200b10f4040c020b200141003602f807200142013703f007200141a00a6a200141f0076a10ef0420012802f40721112010ad4220862012ad8420013502f80742208620012802f0072210ad84100202402011450d00201010350b0240200341037122034103460d0020030e03010001010b20012802c80a450d0020012802c40a10350b024020012802dc06450d00201210350b20182014290000370000201841086a201441086a290000370000201841106a201441106a290000370000201841186a201441186a2900003700002001411d3a00f8072001200b36029c08200141093602f007410c10332203450d042003200b360008200342e4cab5fbb6ccdcb0e3003700002001428c808080c0013702dc06200120033602d806200141a00a6a200141d8066a10f004200120012802a00a221020012802a80a41b0b4cc0041004100108a0220012802002112024020012802a40a450d00201010350b024020124101460d00410c10332212450d0520122003290000370000201241086a200341086a280000360000200141a00a6a200141f0076a41b002109d081a2001413f3a00e80c200141003602dc0c2001428c808080c0013702d40c200120123602d00c200a200141a00a6a410110cb04024020012802dc0c4102460d00024020012802d00c2203450d0020012802d40c450d00200310350b200141a00a6a10ba020b200141a00a6a200a10f3042001410020012802a40a417f6a20012802a00a4101461b360284052001200a36028005200141a00a6a200141d8066a10f00420012802a00a2103200120012802a80a3602bc05200120033602b80520014180056a200141b8056a10db01024020012802a40a450d00200310350b20012802dc06450d0120012802d80610350c010b20031035200141f0076a10ba0241b08cc500ad4280808080a0068410060b410121030b200120003602a40a200120033a00a10a200141013a00a00a200141f0076a200b10f50420012802f0072103200120012802f8073602f405200120033602f005200141a00a6a200141f0056a10f604024020012802f407450d00200310350b20082015470d000b0b0240200e450d00200e41e8006c450d00201310350b200010b7062102200141f00c6a2400427f201e20027c22022002201e541b0f0b1045000b41a0bac800411c41bcbac8001064000b2003200a419cb9c8001042000bc30103017f017e027f0240024002402000280200220241024d0d004101210042002103410121020c010b024002400240024020020e03000102000b410110332204450d0441002102200441003a00002000280204210520044101410510372200450d04200020053600014280808080d00021030c030b410110332200450d03200041013a00000c010b410110332200450d02200041023a00000b4100210242808080801021030b200129020020032000ad841002024020020d00200010350b0f0b103c000bd10707017f017e027f017e017f027e037f230041e0006b22032400200341306a2001200210da03024002400240024020032903302204a7220241ff01714101460d00200341306a41186a4200370300200341306a41106a22054200370300200341306a41086a220242003703002003420037033041d1c4c700ad4280808080e000841001220629000021072002200641086a29000037030020032007370330200610354184eec700ad4280808080b00284100122062900002107200341d0006a41086a2208200641086a2900003703002003200737035020061035200520032903502207370300200341106a41086a2002290300370300200341106a41106a2007370300200341106a41186a2008290300370300200320032903303703102003200341106a10e1022003290308420020032802001b210702400240200141ff0171220141024b0d004280b0def7d32b210920010e03010003010b4280c0a8ca9a3a21090b4100210141800c2102200042c0b2cd3b7c220a2000540d032007200a7c22002007540d0320002009560d030c020b200241087641ff017121012004421088a741087421020c020b427f2007427f200042c0b2cd3b7c220920092000541b7c220020002007541b21000b200341306a41186a22084200370300200341306a41106a22064200370300200341306a41086a220242003703002003420037033041d1c4c700ad4280808080e000842207100122052900002109200341d0006a41086a2201200541086a2900003703002003200937035020051035200220012903003703002003200329035037033041b8eec700ad42808080808002841001220529000021092001200541086a2900003703002003200937035020051035200620032903502209370300200341106a41086a220b2002290300370300200341106a41106a220c2009370300200341106a41186a220d20012903003703002003200329033037031020032004422088a7360230200341106aad42808080808004842204200341306aad22094280808080c0008410022008420037030020064200370300200242003703002003420037033020071001220529000021072001200541086a290000370300200320073703502005103520022001290300370300200320032903503703304184eec700ad4280808080b002841001220529000021072001200541086a2900003703002003200737035020051035200620032903502207370300200b2002290300370300200c2007370300200d20012903003703002003200329033037031020032000370330200420094280808080800184100241022101410021020b200341e0006a240020022001720bac0604047f017e017f047e230041d0016b22022400200241a0016a41186a4200370300200241a0016a41106a22034200370300200241a0016a41086a22044200370300200242003703a00141e3efcb00ad4280808080a002841001220529000021062004200541086a290000370300200220063703a0012005103541f5efcb00ad4280808080900284100122052900002106200241c0016a41086a2207200541086a290000370300200220063703c00120051035200320022903c001220637030020024180016a41086a200429030037030020024180016a41106a200637030020024180016a41186a2007290300370300200220022903a0013703800120014280c0a8ca9a3a20014280c0a8ca9a3a541b2101200241e8006a20024180016a10bc020240024020022802680d004100210442002108420021060c010b200229037022084200522205200241e8006a41106a29030022064200552006501b21042006427f550d00428080808080808080807f420020062005ad7c7d20082006428080808080808080807f85845022051b21064200420020087d20051b21080b200241d8006a2008200642808090bbbad6adf00d4200109808200241c8006a20022903582209200241d8006a41086a290300220a428080f0c4c5a9d28f72427f108408200242808090bbbad6adf00d3703a8012002200820022903487c22063703a001200241286a200241a0016a200642808090bbbad6adf00d564103746a290300420020014200108408200241186a20022903282206200241286a41086a290300220842808090bbbad6adf00d4200109808200241086a2002290318220b200241186a41086a290300428080f0c4c5a9d28f72427f108408200241386a2009200a200142001084082000200241386a41086a29030020022903382209200b200620022903087c220a428080c89d9deb96f806562008200241086a41086a2903007c200a200654ad7c22064200522006501bad7c7c2206200954ad7c2208200620017c2209200654ad7c4200420020082001200654ad7c7d2208200120067d220620015620084200522008501b22051b20041b370308200020094200200620051b20041b370300200241d0016a24000b910f05017f017e047f017e067f230041f0016b2201240042002102200141d8006a41186a22034200370300200141d8006a41106a22044200370300200141d8006a41086a22054200370300200142003703584193d1cb00ad4280808080a00184100122062900002107200141c8006a41086a2208200641086a2900003703002001200737034820061035200520082903003703002001200129034837035841d8c7ca00ad4280808080e000841001220629000021072008200641086a2900003703002001200737034820061035200420012903482207370300200141286a41086a22062005290300370300200141286a41106a2007370300200141286a41186a200829030037030020012001290358370328200141f8006a200141286a412010d50120012d00782108200320014191016a290000370300200420014189016a290000370300200520014181016a290000370300200120012900793703580240024020084101470d0020002001290358370000200041186a2003290300370000200041106a2004290300370000200041086a20052903003700000c010b200141f8006a41186a4200370300200141f8006a41106a22094200370300200141f8006a41086a220842003703002001420037037841d1c4c700ad4280808080e000841001220a29000021072008200a41086a29000037030020012007370378200a10354185c5c700ad4280808080e000841001220a29000021072006200a41086a29000037030020012007370328200a103520092001290328220737030020052008290300370300200420073703002003200629030037030020012001290378370358200141f8006a200141d8006a10ce02024002402001280278220a0d004104210a410021050c010b200129027c2202422088a721050b02400240200541246c2205450d002005415c6a2108200a210503400240024020052d00004101460d002008450d030c010b200541016a2800002103200541086a28020021062001200541106a28020036025c200120063602580240200341c28289aa04460d0020080d010c030b200141f8006a200141d8006a10800420012903784203510d02200141f8006a41106a22052802002106200141f8006a41186a420037030020054200370300200141f8006a41086a220842003703002001420037037841a3edcb00ad4280808080f000841001220329000021072008200341086a290000370300200120073703782003103541f393ca00ad4280808080a00184100122032900002107200141286a41086a2209200341086a2900003703002001200737032820031035200520012903282207370300200141d8006a41086a2008290300370300200141d8006a41106a2007370300200141d8006a41186a200929030037030020012001290378370358200141f8006a200141d8006a10fe0120012802782205410120051b21034100210802402006200129027c420020051b2207422088a74f0d00200320064105746a2205450d00200141086a41186a200541186a290000370300200141086a41106a200541106a290000370300200141086a41086a200541086a29000037030020012005290000370308410121080b0240200742ffffff3f83500d00200310350b2008450d02200141f8006a41186a2208200141086a41186a290300370300200141f8006a41106a2203200141086a41106a290300370300200141f8006a41086a2206200141086a41086a29030037030020012001290308370378200141d8006a41186a220b4200370300200141d8006a41106a220c4200370300200141d8006a41086a22094200370300200142003703584193d1cb00ad4280808080a001841001220d2900002107200141c8006a41086a2205200d41086a29000037030020012007370348200d1035200920052903003703002001200129034837035841d8c7ca00ad4280808080e000841001220d29000021072005200d41086a29000037030020012007370348200d103520042001290348370000200441086a2005290300370000200141286a41086a2009290300370300200141286a41106a200c290300370300200141286a41186a200b290300370300200120012903583703280240412010332205450d0020052001290378370000200541186a2008290300370000200541106a2003290300370000200541086a2006290300370000200141286aad42808080808004842005ad4280808080800484100220051035200041186a2008290300370000200041106a2003290300370000200041086a2006290300370000200020012903783700000c040b1045000b200541246a21052008415c6a21080c000b0b20004200370000200041186a4200370000200041106a4200370000200041086a42003700000b02402002422088a72205450d00200541246c2108200a210503400240024020052d0000220341044b0d0002400240024020030e050400010204040b2005410c6a280200450d03200541086a28020010350c030b2005410c6a280200450d02200541086a28020010350c020b2005410c6a280200450d01200541086a28020010350c010b200541086a280200450d00200541046a28020010350b200541246a21052008415c6a22080d000b0b2002a72205450d00200541246c450d00200a10350b200141f0016a24000b8b0101017f41e09dcc00ad4280808080d001841006024002400240024020002d00000e0400010203000b200041046a29020010060f0b41d29dcc00ad4280808080e0018410060f0b41c89dcc00ad4280808080a0018410060f0b20003100011026200041026a31000010260240200041046a2802002201450d00200041086a3502004220862001ad8410060b0b130020004101360204200041a8d0c4003602000b850a03057f017e047f230041a0016b22012400200141e8006a41186a22024200370300200141e8006a41106a22034200370300200141e8006a41086a220442003703002001420037036841a3edcb00ad4280808080f000841001220529000021062004200541086a290000370300200120063703682005103541a5ebcb00ad4280808080c0018410012205290000210620014188016a41086a2207200541086a29000037030020012006370388012005103520032001290388012206370300200141c8006a41086a2004290300370300200141c8006a41106a2006370300200141c8006a41186a200729030037030020012001290368370348200141106a200141c8006a412010c00120012802142105200128021021082002200041186a2900003703002003200041106a2900003703002004200041086a290000370300200120002900003703684188e8cb00ad4280808080800184100122002900002106200141186a41086a200041086a290000370300200120063703182000103541f1c8c400ad4280808080e001841001220029000021062007200041086a29000037030020012006370388012000103520012005410020081b3602382001200141386aad4280808080c00084100322002900003703980120001035200141d4006a22052001413c6a360200200120014198016a41086a220736024c2001200141386a360250200120014198016a360248200141286a200141c8006a107b0240024002400240412010332200450d0020002001290368370000200041186a2002290300370000200041106a2003290300370000200041086a200429030037000020012000ad42808080808004841003220429000037039801200410352005200041206a360200200120003602502001200736024c200120014198016a360248200141386a200141c8006a107b200010352001280230220741206a2202200128024022086a2204417f4c0d01200128023821092001280228210a0240024020040d0041002105410121000c010b200410332200450d01200421050b024002402005410f4d0d00200521030c010b200541017422034110200341104b1b22034100480d03024020050d002003103322000d010c050b20052003460d0020002005200310372200450d040b20002001290318370000200041086a200141186a41086a2903003700000240024020034170714110460d00200321050c010b200341017422054120200541204b1b22054100480d0320032005460d0020002003200510372200450d040b2000200129038801370010200041186a20014188016a41086a29030037000002400240200541606a2007490d00200521030c010b2007415f4b0d03200541017422032002200320024b1b22034100480d0320052003460d0020002005200310372200450d040b200041206a200a2007109d081a02400240200320026b2008490d00200321050c010b20042002490d03200341017422052004200520044b1b22054100480d03024020030d00024020050d00410121000c020b200510332200450d050c010b20032005460d0020002003200510372200450d040b200020026a20092008109d081a0240200128023c450d00200910350b0240200128022c450d00200a10350b200141086a2000200410c0012001200128020c41016a410120012802081b3602682004ad4220862000ad84200141e8006aad4280808080c00084100202402005450d00200010350b200141a0016a24000f0b1045000b1044000b103e000b103c000b340020004188e8cb0036020420004100360200200041146a4104360200200041106a41f4d4c400360200200041086a42083702000b130020004101360204200041d8ddc4003602000b3400200041d1efcb0036020420004100360200200041146a4102360200200041106a4188e5c400360200200041086a42093702000b130020004101360204200041c8e7c4003602000b2d01017f02404108103322020d001045000b20004288808080800137020420002002360200200242dc0b3700000bd50101037f230041106b2203240002400240200241d0026c4104722204417f4c0d00200410332205450d0120034100360208200320043602042003200536020020022003107702402002450d00200241d0026c2102034002400240200141bc026a2802004102470d00200341003a000f20032003410f6a410110780c010b200341013a000f20032003410f6a410110782001200310da040b200141d0026a2101200241b07d6a22020d000b0b20002003290300370200200041086a200341086a280200360200200341106a24000f0b1044000b1045000bec0101037f230041106b220224000240024020002802b00222030d00200241003a00072001200241076a41011078200241076a21030c010b200241013a00072001200241076a41011078200041b8026a2802002204200110772001200320041078200241076a21030b200220002d00c8023a000720012003410110782000200110af030240024020002802bc024101460d00200241003a000720012003410110780c010b200241013a000720012003410110782002200041c0026a2802003602082001200241086a410410782002200041c4026a28020036020c20012002410c6a410410780b200241106a24000b6401037f024041094101200128020022024101461b220310332204450d000240024020020d00200441003a0000410121010c010b200441013a000020042001290204370001410921010b2000200136020820002003360204200020043602000f0b1045000bc90202027f017e23004180016b220224002000280200210002400240024002400240200128020022034110710d002000290300210420034120710d01200441012001105221000c020b20002903002104410021000340200220006a41ff006a2004a7410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200442048822044200520d000b20004180016a22034181014f0d022001410141d88bc0004102200220006a4180016a410020006b105621000c010b410021000340200220006a41ff006a2004a7410f712203413072200341376a2003410a491b3a00002000417f6a2100200442048822044200520d000b20004180016a22034181014f0d022001410141d88bc0004102200220006a4180016a410020006b105621000b20024180016a240020000f0b200341800141c88bc0001059000b200341800141c88bc0001059000b8b0605027f027e017f027e027f230041a0016b220224002000280200210002400240024002400240024002400240200128020022034110710d00200041086a29030021042000290300210520034120710d0220054290ce005441002004501b450d012005a72103412721000c060b200041086a2903002105200029030021044180012100024003402000450d01200241206a20006a417f6a2004a7410f712203413072200341d7006a2003410a491b3a00002000417f6a210020044204882005423c8684220420054204882205844200520d000b0b20004181014f0d022001410141d88bc0004102200241206a20006a41800120006b105621000c060b41272100200241186a21060340200241106a200520044290ce0042001098082002200229031022072006290300220842f0b17f427f108408200241206a20006a2203417c6a200520022903007ca7220941ffff037141e4006e220a410174419a87c0006a2f00003b00002003417e6a200a419c7f6c20096a41ffff0371410174419a87c0006a2f00003b0000200542ffc1d72f56210320044200522109200450210a2000417c6a2100200721052008210420032009200a1b0d000c040b0b4180012100024003402000450d01200241206a20006a417f6a2005a7410f712203413072200341376a2003410a491b3a00002000417f6a210020054204882004423c8684220520044204882204844200520d000b0b20004181014f0d012001410141d88bc0004102200241206a20006a41800120006b105621000c040b200041800141c88bc0001059000b200041800141c88bc0001059000b2007a721030b02400240200341e3004a0d00200321090c010b200241206a2000417e6a22006a2003200341ffff037141e4006e2209419c7f6c6a41ffff0371410174419a87c0006a2f00003b00000b024002402009410a480d00200241206a2000417e6a22006a2009410174419a87c0006a2f00003b00000c010b200241206a2000417f6a22006a200941306a3a00000b2001410141b0b4cc004100200241206a20006a412720006b105621000b200241a0016a240020000ba50301077f230041106b2202240002400240024002402001410c6a2802002203417f4c0d0020012802042104200128020021050240024020030d0041002106410121070c010b200310332207450d02200321060b0240024020062003490d00200621080c010b200641017422082003200820034b1b22084100480d03024020060d002008103322070d010c050b20062008460d0020072006200810372207450d040b200720042003109d0821062002200141106a10a6032000410c6a2003360200200041086a20083602002000200636020420002005360200200041106a2002290300370200200041186a200241086a280200360200200020012802243602242000200129021c37021c20002001290228370228200041306a200141306a290200370200200041386a200141386a290200370200200041c0006a200141c0006a290200370200200041c8006a200141c8006a290200370200200041d0006a200141d0006a290200370200200041d8006a200141d8006a290200370200200041e0006a200141e0006a290200370200200241106a24000f0b1044000b1045000b103e000b103c000b1300200041023602042000418cecc4003602000b0f00200028020020012002107f41000bfe0101017f230041106b22022400200028020021002002410036020c02400240024002402001418001490d002001418010490d012001418080044f0d0220022001413f71418001723a000e20022001410676413f71418001723a000d20022001410c76410f7141e001723a000c410321010c030b200220013a000c410121010c020b20022001413f71418001723a000d20022001410676411f7141c001723a000c410221010c010b20022001413f71418001723a000f2002200141127641f001723a000c20022001410676413f71418001723a000e20022001410c76413f71418001723a000d410421010b20002002410c6a2001107f200241106a240041000b6301017f230041206b2202240020022000280200360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a41e88ac500200241086a10432101200241206a240020010ba50502067f017e230041d0006b220424002004200136020c2004200041b0b4cc0020011b3602082004200441086a10c40102400240024002400240024020042802000d0020042802042205200428020c4104762201200120054b1b22004104742201417f4c0d030240024020000d00410821060c010b200110332206450d050b41002101200441003602182004200036021420042006360210024002402005450d00200441306a4104722107410021010340200441306a200441086a10e404200441c0006a41086a2200200741086a28020036020020042007290200370340200428023022084104460d02200441206a41086a2209200028020036020020042004290340370320024020012004280214470d00200441106a20014101109a0120042802102106200428021821010b200620014104746a22002008360200200020042903203702042000410c6a20092802003602002004200141016a22013602182005417f6a22050d000b200428021421000b2006450d01200441306a200220062001200311060020042802302105410110332201450d054201210a200442013702442004200136024020054105470d02200141013a0000200441013602480c030b200428021441ffffffff0071450d00200610350b41b08bc50041f000200441306a41908bc50041a08cc5001046000b200141003a00002004410136024820014101410210372101024020054104470d002001450d04200141003a00012004200136024020044282808080203702444202210a0c010b2001450d03200141013a0001200420013602402004428280808020370244200441306a200441c0006a10e5042004350248210a200428024021010b2001ad422086200a84210a0240200041ffffffff0071450d00200610350b200441d0006a2400200a0f0b1044000b1045000b103c000bd90202047f017e02400240024002400240024020012802042202450d00200128020022032d0000210420012002417f6a22053602042001200341016a360200200441034b0d0520040e0401020304010b200041043602000f0b024020054104490d00200041003602002003280001210420012002417b6a3602042001200341056a360200200020043602040f0b200041043602000f0b024020054108490d0020004101360200200329000121062001200241776a3602042001200341096a360200200041086a20063703000f0b200041043602000f0b024020054104490d00200041023602002003280001210420012002417b6a3602042001200341056a360200200020043602040f0b200041043602000f0b024020054108490d0020004103360200200329000121062001200241776a3602042001200341096a360200200041086a20063703000f0b200041043602000f0b200041043602000bd70101017f230041106b220224000240024002400240024020002802000e0400010203000b200241003a00082001200241086a41011078200220002802043602082001200241086a410410780c030b200241013a00082001200241086a410110782002200041086a2903003703082001200241086a410810780c020b200241023a00082001200241086a41011078200220002802043602082001200241086a410410780c010b200241033a00082001200241086a410110782002200041086a2903003703082001200241086a410810780b200241106a24000bec0201047f230041306b22042400200441a58ecc00410310500240024002400240024020020d0041002105410121060c010b200210332206450d01200221050b0240024020052002490d00200521070c010b200541017422072002200720024b1b22074100480d02024020050d002007103322060d010c040b20052007460d0020062005200710372206450d030b200620012002109d082105200441146a2002360200200441106a220220073602002004200536020c200441186a41106a22052002290300370300200441186a41086a2207200441086a29030037030020042004290300370318024020002802082202200041046a280200470d00200020024101109101200028020821020b200028020020024105746a22024100360218200220042903183702002002411c6a2003360200200241106a2005290300370200200241086a20072903003702002000200028020841016a360208200441306a24000f0b1045000b103e000b103c000bdd0505047f017e017f017e0a7f230041e0016b22022400200241c0006a41186a22034200370300200241c0006a41106a22044200370300200241c0006a41086a220542003703002002420037034041d9e3cb00ad42808080809001842206100122072900002108200241e0006a41086a2209200741086a29000037030020022008370360200710352005200929030037030020022002290360370340419c8dc500ad4280808080c001841001220729000021082009200741086a2900003703002002200837036020071035200420022903602208370300200241206a41086a22072005290300370300200241206a41106a220a2008370300200241206a41186a220b200929030037030020022002290340370320200241e0006a200241206a10c0020240024020022d008001220c4103470d002000411610e8040c010b200241206aad428080808080048422081007200241086a220d2009290300370300200241106a220e200241e0006a41106a220f290300370300200241186a2210200241e0006a41186a2211290300370300200220022903603703002003420037030020044200370300200542003703002002420037034020061001221229000021062009201241086a2900003703002002200637036020121035200520092903003703002002200229036037034041efe3cb00ad4280808080d002841001221229000021062009201241086a290000370300200220063703602012103520042002290360370000200441086a200929030037000020072005290300370300200a2004290300370300200b200329030037030020022002290340370320200241013a00602008200241e0006aad428080808010841002200941023a0000200241063a006041b0b4cc004100200241e0006a10d40120112010290300370300200f200e2903003703002009200d29030037030020022002290300370360200141809c316a200241e0006a200c4180de3410e904200041043a00000b200241e0016a24000b8e0701047f230041c0006b2202240041f6f2c4002103412421044108210502400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200141ff01710e26000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425000b200241146a410136020020024201370204200241e8d4ca003602002002410436021c200241f0d5ca003602182002200241186a360210200241b0b4cc00104c000b41eaf5c400210341002104410821050c230b41d2dfca002103410f2105410121040c220b41e2f5c400210341022104410821050c210b41daf5c400210341032104410821050c200b41cbf5c4002103410f2105410421040c1f0b41e1dfca00210341112105410521040c1e0b41b8f5c400210341132105410621040c1d0b41a7f5c400210341112105410721040c1c0b419cf5c4002103410b2105410821040c1b0b4192f5c4002103410a2105410921040c1a0b4185f5c4002103410d2105410a21040c190b419bd6ca002103410c2105410b21040c180b41fbf4c4002103410a2105410c21040c170b41eff4c4002103410c2105410d21040c160b41def4c400210341112105410e21040c150b41d3f4c4002103410b2105410f21040c140b41a1dfca00210341102104410821050c130b41cbf4c400210341112104410821050c120b41bcf4c4002103410f2105411221040c110b41abf4c400210341112105411321040c100b419cf4c4002103410f2105411421040c0f0b4191f4c4002103410b2105411521040c0e0b4188f4c400210341092105411621040c0d0b41fef3c4002103410a2105411721040c0c0b41f7f3c400210341072105411821040c0b0b41eef3c400210341092105411921040c0a0b41e5f3c400210341092105411a21040c090b41ddf3c4002103411b2104410821050c080b41d1f3c4002103410c2105411c21040c070b41c0f3c400210341112105411d21040c060b41a7d6ca002103411e2104410821050c050b41b7f3c400210341092105411f21040c040b41a6f3c400210341112105412021040c030b4199f3c4002103410d2105412121040c020b418ff3c4002103410a2105412221040c010b41fef2c400210341112105412321040b20004183143b0100200041086a2005360200200041046a2003360200200041026a20043a0000200241c0006a24000b900707047f017e017f017e017f017e047f230041e0016b22042400200441d8006a41186a22054200370300200441d8006a41106a22064200370300200441d8006a41086a220742003703002004420037035841d9e3cb00ad4280808080900184220810012209290000210a200441c8006a41086a220b200941086a2900003703002004200a370348200910352007200b2903003703002004200429034837035841cae3cb00ad4280808080f00184220a10012209290000210c200b200941086a2900003703002004200c3703482009103520062004290348220c370300200441106a41086a22092007290300370300200441106a41106a220d200c370300200441106a41186a220e200b29030037030020042004290358370310200441086a200441106a412010c001200428020c210f20042802082110200542003703002006420037030020074200370300200442003703582008100122052900002108200b200541086a29000037030020042008370348200510352007200b29030037030020042004290348370358200a100122052900002108200b200541086a290000370300200420083703482005103520062004290348220837030020092007290300370300200d2008370300200e200b290300370300200420042903583703102004200f410020101b220b41016a360258200441106aad4280808080800484200441d8006aad4280808080c0008410022004413f6a4200370000200441376a42003700002004412f6a4200370000200441276a42003700002004411f6a420037000020044200370017200441e1006a22062009290000370000200441e9006a200d290000370000200441f1006a200e290000370000200441f9006a200441106a41206a29000037000020044181016a200441386a29000037000020044188016a420037000020044194016a200336020020044190016a200036020020044198016a2001290000370300200441a0016a200141086a290000370300200441a8016a200141106a290000370300200441b0016a200141186a290000370300200441003a005820042004290010370059200441b8016a20023a0000200441c8006a200b10f50420042802482101200420042802503602dc01200420013602d801200441d8006a200441d8016a10f6040240200428024c450d00200110350b200441e4006a200b360200200620023a0000200741033a0000200441063a005841b0b4cc004100200441d8006a10d401200441e0016a24000bcd1a06057f017e017f017e117f097e23002202210320024180046b4160712202240020024180016a41186a420037030020024180016a41106a2204420037030020024180016a41086a22054200370300200242003703800141d9e3cb00ad4280808080900184100122062900002107200241d8006a41086a2208200641086a290000370300200220073703582006103520052008290300370300200220022903583703800141918dc500ad4280808080b001841001220629000021072008200641086a2900003703002002200737035820061035200420022903582207370300200241386a41086a2005290300370300200241386a41106a2007370300200241386a41186a2008290300370300200220022903800137033820024120360294022002200241386a3602900220024198026a200241386aad42808080808004842209100510c20102400240024002400240200228029802220a0d004100210b0c010b200228029c02210c200220024198026a41086a2802003602ac022002200a3602a802200241306a200241a8026a10c4010240024020022802300d002002280234220d20022802ac02220e41c4006e22082008200d4b1bad42c4007e2207422088a70d042007a72208417f4c0d040240024020080d004104210b0c010b20081033220b450d040b200241003602b8022002200b3602b0022002200841c4006e3602b40202400240200d450d004100210f41002110034002400240200e4104490d00200220022802a802221141046a3602a8022011280000211241002108200241003a00a001200e417c6a21060240024002400240034020062008460d0120024180016a20086a201120086a220541046a2d00003a00002002200541056a3602a8022002200841016a22053a00a0012005210820054120470d000b200241d8006a41186a221320024180016a41186a2214290300370300200241d8006a41106a221520024180016a41106a2216290300370300200241d8006a41086a221720024180016a41086a2218290300370300200220022903800137035841002108200241003a00a001201120056a21192005200e6b41046a210e0340200e20086a450d0220024180016a20086a201920086a221141046a2d00003a00002002201141056a3602a8022002200841016a22113a00a0012006417f6a21062011210820114120470d000b200241c0036a41186a2014290300370300200241c0036a41106a2016290300370300200241c0036a41086a2018290300370300200241e0036a41086a2017290300370300200241e0036a41106a2015290300370300200241e0036a41186a201329030037030020022002290380013703c003200220022903583703e003200620056b210e410021082012211a0c050b200841ff0171450d020c010b200841ff0171450d010b200241003a00a0010b4100210e0b410121080b200241a0036a41186a2205200241e0036a41186a290300370300200241a0036a41106a2206200241e0036a41106a290300370300200241a0036a41086a2211200241e0036a41086a29030037030020024180036a41086a2219200241c0036a41086a29030037030020024180036a41106a2212200241c0036a41106a29030037030020024180036a41186a2213200241c0036a41186a290300370300200220022903e0033703a003200220022903c0033703800320080d02201041016a2110200241e0026a41186a22142005290300370300200241e0026a41106a22052006290300370300200241e0026a41086a22062011290300370300200241c0026a41086a22112019290300370300200241c0026a41106a22192012290300370300200241c0026a41186a22122013290300370300200220022903a0033703e00220022002290380033703c0020240200f20022802b402470d00200241b0026a200f4101109f0120022802b002210b20022802b802210f0b200b200f41c4006c6a2208201a360200200820022903e0023702042008410c6a2006290300370200200841146a20052903003702002008411c6a2014290300370200200820022903c0023702242008412c6a2011290300370200200841346a20192903003702002008413c6a20122903003702002002200f41016a220f3602b8022010200d470d000b2002200e3602ac020b20022902b4022107200b450d010c020b2002200e3602ac02024020022802b4022208450d00200841c4006c450d00200b10350b0b4100210b2002410036026020024201370358200241093602e403200220024190026a3602e0032002200241d8006a3602c00320024194016a41013602002002420137028401200241c888c200360280012002200241e0036a36029001200241c0036a41e88ac50020024180016a10431a20023502604220862002350258841006200228025c450d00200228025810350b200c450d00200a10350b200b4104200b1b2110024020074200200b1b221b422088a7220b450d00200241186a201028020010eb04200241186a41106a2903004200200228021822081b21072002290320420020081b211c0240200b4101470d002002201c3703800141002111200241003602900120022007370388010c040b201041c4006a2108200b41c4006c41bc7f6a210e41002111200241106a21192010210f4101210603402002200828020010eb04200720192903004200200228020022051b221d201c2002290308420020051b221e562007201d562007201d511b22051b2107201c201e20051b211c200f200820051b210f2011200620051b2111200641016a2106200841c4006a2108200e41bc7f6a220e0d000b2002201c3703800120022011360290012002200737038801200f0d030b2000411610e8040240201ba72202450d00200241c4006c450d00201010350b200324000f0b1045000b1044000b02402011200b4f0d002010201141c4006c6a220841186a2206290200211c2010200b417f6a221141c4006c6a220541c0006a280200210f200541206a290200211d200541286a290200211e200541306a290200211f200541386a29020021202005290200212120052902082107200529021021222006200541186a290200370200200829021021232008202237021020082902082122200820073702082008290200210720082021370200200841386a2020370200200841306a201f370200200841286a201e370200200841206a2205280200210b2005201d370200200841c0006a200f3602002002202337039001200220223703880120022007370380012002201c37039801200241e0036a41186a200228029c01360200200241e0036a41106a200229029401370300200241e0036a41086a200229028c0137030020022002290284013703e00320024180016a41186a220f420037030020024180016a41106a220e420037030020024180016a41086a22054200370300200242003703800141d9e3cb00ad428080808090018410012206290000211c200241d8006a41086a2208200641086a2900003703002002201c3703582006103520052008290300370300200220022903583703800141918dc500ad4280808080b0018410012206290000211c2008200641086a2900003703002002201c3703582006103520042002290358370000200441086a2008290300370000200241386a41086a2005290300370300200241386a41106a200e290300370300200241386a41186a200f290300370300200220022903800137033820024180016a2010201110ec0420092002350288014220862002280280012208ad8410020240200228028401450d00200810350b2007a7210e0240201ba72208450d00200841c4006c450d00201010350b200241d8006a200e10ed0420024180016a200228025822082002280260220510cc020240200228029001220f450d002005ad4220862008ad8410070b20024188016a290300210720024198016a2802002119200229038001211c20022802940121100240200228025c450d00200810350b0240200f450d0002402019410574450d00201c200784500d0020024189016a210520194105742106200241b8016a2111200f210803402002201c3703c003200220073703c803200220083602a003200241d8006a2008200241c0036a200241a0036a10f002024020022903584201520d002002290360211d200841186a290000211e200841106a290000211b200841086a29000021092008290000211f2011200241d8006a41106a2903003703002005201f370000200541086a2009370000200541106a201b370000200541186a201e370000200241003a008801200241033a0080012002201d3703b00141b0b4cc00410020024180016a10d4010b200841206a2108200641606a22060d000b0b200241a8016a2007370300200241a0016a201c37030020024180016a41186a2208201936020020024194016a201036020020024180016a41106a2205200f3602002002418c016a200e36020020024180016a41086a220641013a0000200241063a00800141b0b4cc00410020024180016a10d4012008200241e0036a41186a2802003602002005200241e0036a41106a2903003703002006200241e0036a41086a290300370300200220022903e003370380012002200b36029c01200141809c316a20024180016a41004180de3410e9040b200041043a0000200324000f0b2011200b104a000bcf0102037f047e230041c0006b22022400200241306a200110ed04200241106a20022802302203200228023810cc02200228023421010240024020022802202204450d00200241186a2903002105200229031021062002290224210702402001450d00200310350b20022006200520074220884200108408200241086a29030021054201210620022903002108200742ffffff3f83500d01200410350c010b02402001450d00200310350b420021060b2000200837030820002006370300200041106a2005370300200241c0006a24000bc006010a7f230041106b220324000240024002400240200241c4006c41046a2204417f4c0d000240024020040d0041012105410021040c010b200410332205450d020b20034100360208200320053602002003200436020420022003107702402002450d002001200241c4006c6a2106200328020421022003280208210403402001280200210702400240200220046b4104490d0020032802002105200221080c010b200441046a22052004490d05200241017422082005200820054b1b22084100480d050240024020020d00024020080d00410121050c020b2008103322050d010c080b2003280200210520022008460d0020052002200810372205450d070b20032008360204200320053602000b200520046a20073600002003200441046a2209360208412010332202450d03200241186a220a2001411c6a290000370000200241106a220b200141146a290000370000200241086a220c2001410c6a2900003700002002200141046a29000037000002400240200820096b4120490d00200441246a2104200821070c010b200941206a22042009490d05200841017422072004200720044b1b22074100480d050240024020080d00024020070d00410121050c020b200710332205450d080c010b20082007460d0020052008200710372205450d070b20032007360204200320053602000b200520096a22082002290000370000200841186a200a290000370000200841106a200b290000370000200841086a200c290000370000200320043602082002103502400240200720046b411f4d0d00200721020c010b200441206a22022004490d05200741017422082002200820024b1b22024100480d050240024020070d00024020020d00410121050c020b200210332205450d080c010b20072002460d0020052007200210372205450d070b20032002360204200320053602000b200520046a2205200141246a290000370000200541186a2001413c6a290000370000200541106a200141346a290000370000200541086a2001412c6a2900003700002003200441206a2204360208200141c4006a22012006470d000b0b20002003290300370200200041086a200341086a280200360200200341106a24000f0b1044000b1045000b103e000b103c000bfc0403027f017e057f230041d0006b2202240041d9e3cb00ad4280808080900184100122032900002104200241086a41086a200341086a290000370300200220043703082003103541f2f8c400ad4280808080900184100122032900002104200241186a41086a200341086a2900003703002002200437031820031035200220013602342002200241346aad4280808080c000841003220329000037033820031035200241cc006a200241386a3602002002200241386a41086a3602442002200241346a3602482002200241386a360240200241286a200241c0006a107b02400240024002402002280230220541206a2206417f4c0d00200228022821070240024020060d0041002101410121030c010b200610332203450d02200621010b024002402001410f4d0d00200121080c010b200141017422084110200841104b1b22084100480d03024020010d002008103322030d010c050b20012008460d0020032001200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821010c010b200841017422014120200141204b1b22014100480d0320082001460d0020032008200110372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200141606a2005490d00200121080c010b200541206a22082005490d03200141017422092008200920084b1b22084100480d0320012008460d0020032001200810372203450d040b200341206a20072005109d081a2000200636020820002008360204200020033602000240200228022c450d00200710350b200241d0006a24000f0b1044000b1045000b103e000b103c000b9f0303027f017e027f230041206b2202240041d9e3cb00ad4280808080900184100122032900002104200241086a200341086a290000370300200220043703002003103541888dc500ad4280808080900184100122032900002104200241106a41086a200341086a29000037030020022004370310200310350240412010332203450d0020032001290000370000200341186a2205200141186a290000370000200341106a2206200141106a290000370000200341086a200141086a290000370000412010332201450d0020012003290000370000200141186a2005290000370000200141106a2006290000370000200141086a2205200341086a2900003700002003103541c00010332203450d002003200229031037001020032002290300370000200341086a200241086a290300370000200341186a200241106a41086a290300370000200042c080808080083702042000200336020020032001290000370020200341286a2005290000370000200341306a200141106a290000370000200341386a200141186a29000037000020011035200241206a24000f0b1045000b880202037f017e230041106b220224000240024020002d00004101460d00200241003a000020012002410110782002200041046a28020036020020012002410410780c010b200241013a00002001200241011078200041246a28020021032000412c6a28020022042001107720012003200410782001200041016a41201078200041c0006a29030021052002200041c8006a2903003703082002200537030020012002411010782002200041306a28020036020020012002410410780240200041346a2802004101460d00200241003a000020012002410110780c010b200241013a000020012002410110782002200041386a28020036020020012002410410780b200241106a24000ba50403027f017e057f230041306b220224004189fec600ad4280808080900184100122032900002104200241086a200341086a290000370300200220043703002003103541b489c500ad4280808080e00084100122032900002104200241106a41086a200341086a2900003703002002200437031020031035200241206a2001280200200128020810980302400240024002402002280228220541206a2206417f4c0d00200228022021070240024020060d0041002103410121010c010b200610332201450d02200621030b024002402003410f4d0d00200321080c010b200341017422084110200841104b1b22084100480d03024020030d002008103322010d010c050b20032008460d0020012003200810372201450d040b20012002290300370000200141086a200241086a2903003700000240024020084170714110460d00200821030c010b200841017422034120200341204b1b22034100480d0320082003460d0020012008200310372201450d040b20012002290310370010200141186a200241106a41086a29030037000002400240200341606a2005490d00200321080c010b200541206a22082005490d03200341017422092008200920084b1b22084100480d0320032008460d0020012003200810372201450d040b200141206a20072005109d081a20002006360208200020083602042000200136020002402002280224450d00200710350b200241306a24000f0b1044000b1045000b103e000b103c000bd60201027f024002402002450d002002417f6a21040240024020012d0000220241037122054103460d0002400240024020050e03000102000b200241027621020c030b2004450d0320012d0001410874200272220241ffff0371418002490d03200241fcff037141027621020c020b20044103490d0220012f0001200141036a2d000041107472410874200272220241808004490d02200241027621020c010b200241034b0d0120044104490d0120012800012202418080808004490d010b200220036a22012002490d0141012103410121050240200241c000490d0041022105200241808001490d00410441052002418080808004491b21050b0240200141c000490d0041022103200141808001490d00410441052001418080808004491b21030b20002001360204200041003602002000410c6a2003360200200041086a20053602000f0b200041013602000f0b200041013602000ba40301027f230041e0006b22032400200341003a00050240024002400240200041c000490d00200041808001490d012000418080808004490d0241052104200341053a0005200341033a0000200320003600010c030b41012104200341013a0005200320004102743a00000c020b41022104200341023a0005200320004102744101723b01000c010b41042104200341043a0005200320004102744102723602000b024002402001280200220028020822012002490d0020002802002100200320023602082003200436020c20042002470d01200020032002109d081a200341e0006a24000f0b2002200141ccc8ca001058000b200341286a41146a410a360200200341346a410c360200200341106a41146a41033602002003200341086a36024020032003410c6a360244200341c8006a41146a410036020020034203370214200341a0b3cc003602102003410c36022c200341b0b4cc003602582003420137024c200341f4b3cc003602482003200341286a3602202003200341c8006a3602382003200341c4006a3602302003200341c0006a360228200341106a41b0b4cc00104c000bad0301087f230041c0006b22022400200241106a200110c904200241206a200235021842208620022802102203ad84100510c20102400240200228022022040d002002410036023820024208370330200241306a4100410010a701200228023841d0026c220141d0026d2105200228023421062002280230210702402001450d00200541d0026c21082007210103400240200141bc026a2802004102460d000240200141b0026a2802002209450d00200141b4026a280200450d00200910350b200110bb020b200141d0026a2101200841b07d6a22080d000b0b02402006450d00200641d0026c450d00200710350b4100210120004100360200200020053602040c010b200228022421082002200241206a41086a28020036023420022004360230200241086a200241306a10c401024002402002280208450d00200041b0b4cc00360204200041086a4100360200410121010c010b2000200228020c360204410021010b20002001360200410121012008450d00200410350b02402002280214450d00200310350b02402004410047200141017371450d002002280224450d00200410350b200241c0006a24000bd71203077f057e057f230041d0086b22032400200341e0006a200110ee04200341f0056a200328026022042003280268220510d20241022106024020032d00f005220741024622080d002005ad4220862004ad8410070b20034198036a411f6a220520034190066a28000036000020034198036a41186a220920034189066a29000037030020034198036a41106a20034181066a290000220a37030020034198036a41086a200341f9056a290000220b370300200320032900f105220c37039803200341b8066a290300210d200341b0066a290300210e20034194066a280200210f20034198066a28020021102003419c066a2802002111200341f0056a411f6a22122005280000360000200341f0056a41186a22052009290300370300200341f0056a41106a2209200a370300200341f0056a41086a2213200b3703002003200c3703f005024020080d00200341186a411f6a2012280000360000200341186a41186a2005290300370300200341186a41106a2009290300370300200341186a41086a2013290300370300200320032903f005370318200721060b02402003280264450d00200410350b0240024002400240200641037122064103460d0020060e03010001010b200341c0006a41186a200341186a41186a290300370300200341c0006a41106a200341186a41106a290300370300200341c0006a41086a200341186a41086a2903003703002003200329031837034020032011360294032003200f36029003200341e0006a20034190036a10b90202402003280260411b460d0020034198036a200341e0006a41b002109d081a2003200e3703c8052003200d3703d0050240200e200d84500d002003200341c0006a3602a408200341a8086a200341c0006a200341c8056a200341a4086a10f00220032903a8084201520d0020032903b008210a200341a8066a200341a8086a41106a290300370300200341a0066a200a370300200341f0056a41086a41003a0000200341f9056a200329034037000020034181066a200341c0006a41086a29030037000020034189066a200341c0006a41106a29030037000020034191066a200341d8006a290300370000200341033a00f00541b0b4cc004100200341f0056a10d4010b200341f0056a41086a2206410c3a000020034199066a2003290340370000200341f9056a2207200129000037000020034181066a200141086a29000037000020034189066a200141106a29000037000020034191066a200141186a290000370000200341a1066a200341c0006a41086a290300370000200341a9066a200341c0006a41106a290300370000200341b1066a200341c0006a41186a290300370000200341063a00f005200341c8066a200d370300200341c0066a200e37030041b0b4cc004100200341f0056a10d401200341f0056a20034198036a41b002109d081a200341003b01a808200341c8056a200341f0056a200341a8086a10ac0320032903c805210a200341f0056a410c6a20023602002007200a503a0000200641073a0000200341063a00f00541b0b4cc004100200341f0056a10d401200041043a000020100d020c030b2003200e3703a8082003200d3703b0080240024002400240200e200d844200520d00200342003703d005200342003703c8050c010b2003200341c0006a3602c80520034198036a200341c0006a200341a8086a200341c8056a10a802200341b8036a290300210a20032903b003210b02402003290398034201520d0020032903a003210c200341a8066a20034198036a41106a290300370300200341a0066a200c370300200341f0056a41086a41003a0000200341f9056a200329034037000020034181066a200341c0006a41086a29030037000020034189066a200341c0006a41106a29030037000020034191066a200341d8006a290300370000200341033a00f00541b0b4cc004100200341f0056a10d4010b2003200b3703c8052003200a3703d005200b200a844200520d010b200341f0056a41186a22054200370300200341f0056a41106a22044200370300200341f0056a41086a22074200370300200342003703f00541b6fdc600ad4280808080800184220a10012208290000210b200341a8086a41086a2206200841086a2900003703002003200b3703a8082008103520072006290300370300200320032903a8083703f00541e489c200ad4280808080d00184220b10012208290000210c2006200841086a2900003703002003200c3703a80820081035200420032903a808220c37030020034198036a41086a2209200729030037030020034198036a41106a2212200c37030020034198036a41186a22132006290300370300200320032903f00537039803200320034198036a412010d701200341106a290300210c2003290308210d20032802002108200542003703002004420037030020074200370300200342003703f005200a10012205290000210a2006200541086a2900003703002003200a3703a8082005103520072006290300370300200320032903a8083703f005200b10012205290000210a2006200541086a2900003703002003200a3703a80820051035200420032903a808220a370300200920072903003703002012200a37030020132006290300370300200320032903f005370398032003200c420020081b3703f8052003200d420020081b3703f00520034198036aad4280808080800484200341f0056aad428080808080028410020c010b200342f0f2bda1a7ee9cb9f90037039803200341f0056a20034198036a10e001200341f0056a200b200a10df0120034188066a200a37030020034180066a200b370300200341f8056a41063a00002003410c3a00f00541b0b4cc004100200341f0056a10d4010b200341f0056a41086a410d3a0000200341f9056a20012900003700002003419c066a200236020020034181066a200141086a29000037000020034189066a200141106a29000037000020034191066a200141186a290000370000200341063a00f00541b0b4cc004100200341f0056a10d4012000411510e80420100d010c020b200341f0056a41086a410e3a0000200341f9056a20012900003700002003419c066a200236020020034181066a200141086a29000037000020034189066a200141106a29000037000020034191066a200141186a290000370000200341063a00f00541b0b4cc004100200341f0056a10d4012000411310e8040240200741037122014103460d0020010e03020002020b2010450d010b200f10350b200341d0086a24000bfc0403027f017e057f230041d0006b2202240041d9e3cb00ad4280808080900184100122032900002104200241086a41086a200341086a290000370300200220043703082003103541fbf8c400ad4280808080800284100122032900002104200241186a41086a200341086a2900003703002002200437031820031035200220013602342002200241346aad4280808080c000841003220329000037033820031035200241cc006a200241386a3602002002200241386a41086a3602442002200241346a3602482002200241386a360240200241286a200241c0006a107b02400240024002402002280230220541206a2206417f4c0d00200228022821070240024020060d0041002101410121030c010b200610332203450d02200621010b024002402001410f4d0d00200121080c010b200141017422084110200841104b1b22084100480d03024020010d002008103322030d010c050b20012008460d0020032001200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821010c010b200841017422014120200141204b1b22014100480d0320082001460d0020032008200110372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200141606a2005490d00200121080c010b200541206a22082005490d03200141017422092008200920084b1b22084100480d0320012008460d0020032001200810372203450d040b200341206a20072005109d081a2000200636020820002008360204200020033602000240200228022c450d00200710350b200241d0006a24000f0b1044000b1045000b103e000b103c000ba60203027f017e017f230041106b22022400200241003602082002420137030002400240024020002d00004101460d00410110332203450d02200341003a0000200220033602002002428180808010370204200041086a200210a406200235020842208621042002280204452103200228020021000c010b410110332203450d01200341013a000020022003360200200242818080801037020420002d0001210520034101410210372203450d01200320053a00012002200336020020024282808080203702042000280204210520034102410610372200450d01200020053600022002200036020020024286808080e000370204410021034280808080e00021040b200129020020042000ad841002024020030d00200010350b200241106a24000f0b103c000b130020004103360204200041a88dc5003602000b340020004182fec60036020420004100360200200041146a4101360200200041106a41849fc500360200200041086a42073702000b130020004101360204200041aca0c5003602000b3a01017f02404110103322020d001045000b20024200370008200242808084fea6dee111370000200042908080808002370204200020023602000b3400200041a2e8cb0036020420004100360200200041146a4104360200200041106a41c8a1c500360200200041086a42083702000b13002000411d360204200041d8aac5003602000b3400200041d9e3cb0036020420004100360200200041146a410e360200200041106a418c95c600360200200041086a42093702000b4d01027f230041106b220224000240410110332203450d00200341003a0000200041086a4101360200200241013602042002200336020020002002290300370200200241106a24000f0b1045000b7c01017f230041f0006b22022400200241106a4200370300200241186a4200370300200241206a4200370300200241286a4200370300200241306a4200370300200241386a4200370300200241c0006a410036020020024108360204200241086a4200370300200241003a000020002002108005200241f0006a24000b8d1802097f027e230041206b220224002002410036020820024201370300024002400240024020012d00004101460d00410110332203450d032002410136020420022003360200200341003a000020024101360208200141046a28020021042001410c6a2802002203200210770240024020030d0020022802042105200228020821060c010b2004200341306c6a2107200228020421052002280208210603402004280200210802400240200520066b4104490d00200641046a2103200228020021090c010b200641046a22032006490d05200541017422092003200920034b1b220a4100480d050240024020050d000240200a0d00410121090c020b200a103322090d010c080b200228020021092005200a460d0020092005200a10372209450d070b2002200a360204200220093602000b200920066a20083600002002200336020802400240200441086a2d00004101460d00200241003a00100240024020022802042003460d00200228020021050c010b200341016a22052003490d07200341017422062005200620054b1b22064100480d070240024020030d0041002103024020060d00410121050c020b200610332205450d0a0c010b2002280200210520032006460d0020052003200610372205450d090b20022006360204200220053602000b200520036a41003a00002002200341016a22033602082002200441096a2d00004100474107742004410a6a2d00007222063a00100240024020022802042003460d00200228020021050c010b200341016a22052003490d07200341017422092005200920054b1b22094100480d070240024020030d0041002103024020090d00410121050c020b200910332205450d0a0c010b2002280200210520032009460d0020052003200910372205450d090b20022009360204200220053602000b200520036a20063a00002002200341016a2203360208200441106a290300210b2002200441186a2903003703182002200b370310200241106a2109200228020421060c010b200241013a00100240024020022802042003460d00200228020021050c010b200341016a22052003490d06200341017422062005200620054b1b22064100480d060240024020030d0041002103024020060d00410121050c020b200610332205450d090c010b2002280200210520032006460d0020052003200610372205450d080b20022006360204200220053602000b200520036a41013a00002002200341016a2205360208200441186a290300210b200441106a290300210c024002402002280204220920056b4110490d00200341116a210320022802002108200921060c010b200541106a22032005490d06200941017422062003200620034b1b22064100480d060240024020090d00024020060d00410121080c020b200610332208450d090c010b2002280200210820092006460d0020082009200610372208450d080b20022006360204200220083602000b200820056a2205200b3700082005200c37000020022003360208200441206a290300210b2002200441286a2903003703182002200b370310200241106a21090b02400240200620036b4110490d0020022802002108200621050c010b200341106a22052003490d05200641017422082005200820054b1b22054100480d050240024020060d00024020050d00410121080c020b200510332208450d080c010b2002280200210820062005460d0020082006200510372208450d070b20022005360204200220083602000b200820036a22062009290000370000200641086a200941086a2900003700002002200341106a22063602082007200441306a2204470d000b0b200141186a290300210b2001290310210c02400240200520066b4110490d0020022802002103200521040c010b200641106a22032006490d03200541017422042003200420034b1b22044100480d030240024020050d00024020040d00410121030c020b200410332203450d060c010b2002280200210320052004460d0020032005200410372203450d050b20022004360204200220033602000b200320066a2205200b3700082005200c3700002002200641106a2209360208200141286a290300210b200141206a290300210c02400240200420096b410f4d0d00200421050c010b200941106a22052009490d03200441017422082005200820054b1b22054100480d030240024020040d00024020050d00410121030c020b200510332203450d060c010b20042005460d0020032004200510372203450d050b20022005360204200220033602000b200320096a2204200b3700082004200c3700002002200641206a2204360208200141c0006a28020021090240200520046b41034b0d00200441046a22082004490d032005410174220a2008200a20084b1b22084100480d030240024020050d00024020080d00410121030c020b200810332203450d060c010b20052008460d0020032005200810372203450d050b20022008360204200220033602000b200320046a20093600002002200641246a22033602082001290330210b2002200141386a2903003703182002200b370310200241106a21040c010b410110332203450d022002410136020420022003360200200341013a000020024101360208200141306a290300210b200141286a290300210c0240024020022802042205417f6a4110490d0020022802002103200521040c010b200541017422034111200341114b1b22044100480d0220022802002103024020052004460d0020032005200410372203450d040b20022004360204200220033602000b2003200c370001200341096a200b37000020024111360208024002402004416f6a411f4d0d00200421050c010b200441017422054131200541314b1b22054100480d02024020042005460d0020032004200510372203450d040b20022005360204200220033602000b20032001290001370011200341296a200141196a290000370000200341216a200141116a290000370000200341196a200141096a2900003700004131210420024131360208024020012d0021220641064b0d000240024002400240024002400240024020060e0700010203040506000b410021040c060b410121040c050b410221040c040b410321040c030b410421040c020b410521040c010b410621040b200220043a0010024020054131470d002003413141e20010372203450d04200241e200360204200220033602000b200320043a00314132210420024132360208200228020421050b200141c0006a290300210b2001290338210c02400240200520046b4110490d0020022802002103200521060c010b20054101742203200441106a2206200320064b1b22064100480d020240024020050d00200610332203450d050c010b2002280200210320052006460d0020032005200610372203450d040b20022006360204200220033602000b200320046a2205200b3700082005200c3700002002200441106a2209360208200141d0006a290300210b200141c8006a290300210c02400240200620096b410f4d0d00200621050c010b20064101742205200441206a2208200520084b1b22054100480d020240024020060d00200510332203450d050c010b20062005460d0020032006200510372203450d040b20022005360204200220033602000b200320096a2206200b3700082006200c3700002002200441206a2206360208200141e8006a28020021090240200520066b41034b0d0020054101742208200441246a220a2008200a4b1b22084100480d020240024020050d00200810332203450d050c010b20052008460d0020032005200810372203450d040b20022008360204200220033602000b200320066a20093600002002200441246a22033602082001290358210b2002200141e0006a2903003703182002200b370310200241106a21040b024002402002280204220620036b4110490d00200228020021050c010b200341106a22052003490d01200641017422092005200920054b1b22094100480d010240024020060d00024020090d00410121050c020b200910332205450d040c010b2002280200210520062009460d0020052006200910372205450d030b20022009360204200220053602000b200520036a22052004290000370000200541086a200441086a2900003700002002200341106a2203360208200041086a200336020020002002290300370200200241206a24000f0b103e000b103c000b4d01027f230041106b2202240002404104103322030d001045000b2002420437020420022003360200410020021077200041086a200228020836020020002002290300370200200241106a24000b130020004107360204200041ccb0c6003602000b3801017f02404110103322020d001045000b2002420037000820024280a094a58d1d370000200042908080808002370204200020023602000b2e01017f02404104103322020d001045000b20004284808080c00037020420002002360200200241809c313600000b2e01017f02404104103322020d001045000b20004284808080c0003702042000200236020020024180a3053600000b2e01017f02404104103322020d001045000b20004284808080c0003702042000200236020020024180de343600000b340020004189fec60036020420004100360200200041146a4102360200200041106a41acbbc600360200200041086a42093702000bfc0f030b7f017e017f230041106b2202240020024100360208200242013703000240024002402001280200220341044b0d000240024002400240024020030e050001020304000b410110332203450d062002410136020420022003360200200341013a000020024101360208200128020421042001410c6a2802002203200210770240024020030d00200228020821030c010b2004200341286c6a21054100200228020822066b2107410021030340200620036a2108024002402007200228020422096a4120490d002002280200210a2009210b0c010b200841206a220a2008490d082009410174220b200a200b200a4b1b220b4100480d080240024020090d000240200b0d004101210a0c020b200b1033220a0d010c0b0b2002280200210a2009200b460d00200a2009200b1037220a450d0a0b2002200b3602042002200a3602000b200a20066a20036a220c200420036a2209290000370000200c41186a200941186a290000370000200c41106a200941106a290000370000200c41086a200941086a2900003700002002200841206a220c360208200941206a290300210d0240200b20076a41606a41074b0d00200c41086a220e200c490d08200b410174220c200e200c200e4b1b220c4100480d0802400240200b0d000240200c0d004101210a0c020b200c1033220a450d0b0c010b200b200c460d00200a200b200c1037220a450d0a0b2002200c3602042002200a3602000b200a20066a20036a41206a200d3700002002200841286a360208200741586a2107200341286a21032005200941286a470d000b200620036a21030b200141106a280200210b024002402002280204220a20036b4104490d00200228020021090c010b200341046a22092003490d06200a41017422072009200720094b1b22074100480d0602400240200a0d00024020070d00410121090c020b200710332209450d090c010b20022802002109200a2007460d002009200a200710372209450d080b20022007360204200220093602000b200920036a200b3600002002200341046a3602080c040b410110332203450d052002410136020420022003360200200341023a0000200241013602082001280204210a0240024020022802042209417f6a4104490d00200228020021030c010b200941017422034105200341054b1b220b4100480d052002280200210302402009200b460d0020032009200b10372203450d070b2002200b360204200220033602000b2003200a3600012002410536020820012802082103200141106a2802002209200210770240024020090d002002280208210b0c010b2003200941286c6a210c2002280208210b03400240024020022802042208200b6b4120490d00200b41206a21092002280200210a200821070c010b200b41206a2209200b490d072008410174220a2009200a20094b1b22074100480d070240024020080d00024020070d004101210a0c020b20071033220a450d0a0c010b2002280200210a20082007460d00200a200820071037220a450d090b200220073602042002200a3602000b200a200b6a220b2003290000370000200b41186a200341186a290000370000200b41106a200341106a290000370000200b41086a200341086a29000037000020022009360208200341206a290300210d0240200720096b41074b0d00200941086a220b2009490d0720074101742208200b2008200b4b1b220b4100480d070240024020070d000240200b0d004101210a0c020b200b1033220a450d0a0c010b2007200b460d00200a2007200b1037220a450d090b2002200b3602042002200a3602000b200a20096a200d3700002002200941086a220b360208200c200341286a2203470d000b0b200141146a280200210a0240024020022802042209200b6b4104490d00200228020021030c010b200b41046a2203200b490d05200941017422072003200720034b1b22074100480d050240024020090d00024020070d00410121030c020b200710332203450d080c010b2002280200210320092007460d0020032009200710372203450d070b20022007360204200220033602000b2003200b6a200a3600002002200b41046a3602080c030b410110332203450d042002410136020420022003360200200341033a000020024101360208200141086a290300210d0240024020022802042209417f6a4108490d00200228020021030c010b200941017422034109200341094b1b220a4100480d042002280200210302402009200a460d0020032009200a10372203450d060b2002200a360204200220033602000b2003200d370001200241093602080c020b410110332203450d032002410136020420022003360200200341043a0000200241013602082001280204210a0240024020022802042209417f6a4104490d00200228020021030c010b200941017422034105200341054b1b220b4100480d032002280200210302402009200b460d0020032009200b10372203450d050b2002200b360204200220033602000b2003200a360001200241053602080c010b410110332203450d022002410136020420022003360200200341053a0000200241013602082001280204210a0240024020022802042209417f6a4104490d00200228020021030c010b200941017422034105200341054b1b220b4100480d022002280200210302402009200b460d0020032009200b10372203450d040b2002200b360204200220033602000b2003200a360001200241053602080b20002002290300370200200041086a200241086a280200360200200241106a24000f0b103e000b103c000bb70905037f017e027f047e017f230041a0026b22022400200241c8006a2001108a052002280248210320022002280250220436028c022002200336028802200241f8006a2004ad4220862003ad84100510c20102400240200228027822040d00420021050c010b200228027c2106024002400240200241f8006a41086a28020022074110490d0020074170714110460d002007417c714120470d010b20024100360260200242013703582002410936029402200220024188026a360290022002200241d8006a36029c022002419c016a41013602002002420137028c01200241c888c20036028801200220024190026a360298012002419c026a41e88ac50020024188016a10431a200235026042208620023502588410060240200228025c450d00200228025810350b420021050c010b200441086a290000210820042900002109200441186a290000210a2004290010210b20042800202107420121050b2006450d00200410350b0240200228024c450d00200310350b02400240024002402005500d0020024188016a41186a420037030020024188016a41106a2206420037030020024188016a41086a22034200370300200242003703880141d1c4c700ad4280808080e000841001220429000021052003200441086a29000037030020022005370388012004103541e7c4c700ad4280808080e00084100122042900002105200241f8006a41086a220c200441086a2900003703002002200537037820041035200620022903782205370300200241d8006a41086a2003290300370300200241d8006a41106a2005370300200241d8006a41186a200c2903003703002002200229038801370358200241306a200241d8006a412010c001200241106a200a420041002002280234410020022802301b220320076b2204200420034b1bad22054200108408200241206a20054200200b4200108408200242004200200b42001084082002290308200229031884420052200241206a41086a2903002205200229030020022903107c7c220b200554720d0142002009200229032022057d220a200a2009562008200b7d2009200554ad7d220520085620052008511b22031b220b4200200520031b220584500d01200242f6cacda397cddbb320370340200241c0006a2001200b20054106109002200241c0016a2005370300200241b8016a200b37030020024188016a41086a41003a000020024191016a200129000037000020024199016a200141086a290000370000200241a1016a200141106a290000370000200241a9016a200141186a290000370000200241143a00880120024188016a21010c020b20004183363b0100200041086a410a360200200041046a41c1efc400360200200041026a41003a00000c020b200242f6cacda397cddbb320370338200241386a200110920220024188016a2001108a052002350290014220862002280288012203ad8410070240200228028c01450d00200310350b20024188016a41086a41013a000020024191016a200129000037000020024199016a200141086a290000370000200241a1016a200141106a290000370000200241a9016a200141186a290000370000200241143a00880120024188016a21010b41b0b4cc004100200110d401200041043a00000b200241a0026a24000bbc0505017f017e017f017e047f230041d0006b220224004182fec600ad4280808080f000842203100122042900002105200241086a200441086a29000037030020022005370300200410352003100122042900002103200241106a41086a200441086a29000037030020022003370310200410350240024002400240412010332204450d0020042001290000370000200441186a200141186a290000370000200441106a200141106a290000370000200441086a200141086a2900003700002004ad4280808080800484100422012900002103200241306a41086a200141086a2900003703002002200337033020011035200241cc006a200441206a360200200220043602482002200241306a41106a3602442002200241306a360240200241206a200241c0006a107b200410352002280228220641206a2201417f4c0d01200228022021070240024020010d0041002108410121040c010b200110332204450d01200121080b024002402008410f4d0d00200821090c010b200841017422094110200941104b1b22094100480d03024020080d002009103322040d010c050b20082009460d0020042008200910372204450d040b20042002290300370000200441086a200241086a2903003700000240024020094170714110460d00200921080c010b200941017422084120200841204b1b22084100480d0320092008460d0020042009200810372204450d040b20042002290310370010200441186a200241106a41086a29030037000002400240200841606a2006490d00200821090c010b2006415f4b0d03200841017422092001200920014b1b22094100480d0320082009460d0020042008200910372204450d040b200441206a20072006109d081a20002001360208200020093602042000200436020002402002280224450d00200710350b200241d0006a24000f0b1045000b1044000b103e000b103c000be9800205027f037e117f057e0c7f23002203210420034180086b4160712203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e1e000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d000b20034194036a41013602002003420137028403200341e8d4ca0036028003200341043602c4052003419cd5ca003602c0052003200341c0056a3602900320034180036a41b0b4cc00104c000b200141306a2903002105200141286a290300210620034180026a41186a200141196a29000037030020034180026a41106a200141116a29000037030020034180026a41086a200141096a29000037030020032001290001370380022002411a6a2901002107200241196a2d00002101200241186a2d00002108200241166a2f01002109024020022d0000450d00200320073702e407200320013a00e307200320083a00e207200320093b01e0070c500b200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241086a2d00002114200241066a2f01002115200241056a2d00002116200241046a2d00002117200241026a2f0100211820022d00012102200320073703e007200241ff01714101470d4f200320073703e006200320013a00df06200320083a00de06200320093b01dc062003200a3a00db062003200b3a00da062003200c3b01d8062003200d3a00d7062003200e3a00d6062003200f3b01d406200320103a00d306200320113a00d206200320123b01d006200320133a00cf06200320143a00ce06200320153b01cc06200320163a00cb06200320173a00ca06200320183b01c8060240200642808084fea6dee1115441002005501b0d00200320063703c001200320053703c8012003200341c8066a3602e0072003200341c8066a36028801200320034188016a360288032003200341e0076a360284032003200341c0016a36028003200341c0056a200341c8066a20034180036a108c030240024020032802c0054101470d0020032f00c50520032d00c705411074722101200341c8056a290300210720032d00c40521020c010b410421020240200341c0056a41086a2903004201520d00200341c0056a41106a29030021072003280288012101200341b8036a200341c0056a41186a290300370300200341b0036a200737030020034180036a41086a41003a000020034189036a200129000037000020034191036a200141086a29000037000020034199036a200141106a290000370000200341a1036a200141186a290000370000200341033a00800341b0b4cc00410020034180036a10d4010b0b0240200241ff01714104470d0041d9e3cb00ad428080808090018422071001220229000021192002290008211a2002103541bbe3cb00ad4280808080f00184221b10012202290000211c2002290008211d200210352003201d3701d8012003201c3701d0012003201a3701c801200320193701c001200341106a200341c0016a412010c001200328021421012003280210210820071001220229000021072002290008211920021035201b10012202290000211a2002290008211b200210352003201b3701d8012003201a3701d001200320193701c801200320073701c00120032001410020081b220841016a36028003200341c0016aad4280808080800484220720034180036aad4280808080c0008410022003200341c8066a3602c001200341c0056a200810ed0420033502c805211920032802c005210c411810332202450d4f2002200637000020022005370008200342988080808002370284032003200236028003410120034180036a107720032802c0012102200328028003210102400240200328028403220a20032802880322096b411f4d0d00200a210b0c010b200941206a220b2009490d3f200a410174220d200b200d200b4b1b220b4100480d3f0240200a0d000240200b0d00410121010c020b200b103322010d010c520b200a200b460d002001200a200b10372201450d510b200120096a220a2002290000370000200a41186a200241186a290000370000200a41106a200241106a290000370000200a41086a200241086a2900003700002019422086200cad84200941206aad4220862001ad8410020240200b450d00200110350b024020032802c405450d00200c10350b200341cc056a20034180026a41086a290300370200200341d4056a20034180026a41106a290300370200200341dc056a20034180026a41186a290300370200200341ec056a200341c8066a41086a290300370200200341f4056a200341c8066a41106a290300370200200341fc056a200341c8066a41186a290300370200200320083602c00520032003290380023702c405200320032903c8063702e4052003200341c0056a3602ac0141d9e3cb00ad42808080809001841001220229000021192002290008211a2002103541918dc500ad4280808080b0018410012202290000211b2002290008211c200210352003201c3701d8012003201b3701d0012003201a3701c801200320193701c00120034188016a2007100510c201024002402003280288010d00410410332202450d5120034204370284032003200236028003410020034180036a1077200341b8016a20032802880336020020032003290380033703b0010c010b200341b0016a41086a20034188016a41086a28020036020020032003290388013703b0010b200341b8076a41086a200341b0016a41086a2802002202360200200320032903b0013703b807024002402002450d0020034180036a20032802b80722012002410110f1042003280280034101470d0120032802bc07450d4e200110350c4e0b4101200341b8076a107720032802ac01200341b8076a108c050c4b0b200328028403210a02402003418c036a280200220120034180036a41086a2802002209460d002002200120096b6a220241046a220b417f4c0d4002400240200b0d004100210b4101210c0c010b200b1033220c450d510b2003200c3602c8072003200b3602cc07200320023602d0072003200341c8076a36028003200a20034180036a200110f20420022001490d1f20032802d007220a2002490d2020032802c007220a2009490d2120032802c807210b20032802b807210c2003200220016b22023602d8072003200a20096b220a3602dc072002200a470d22200b20016a200c20096a2002109d081a20032802ac01200341c8076a108c0520032802d007210120032802cc07210920032802c807210220032802bc07450d4c20032802b80710350c4c0b2003200341b8076a36028003200a20034180036a200910f20420032802ac01200341b8076a108c050c4a0b2003200737027c200320023a0078200320013b0079200320014110763a007b0c510b200341f8006a410110e80420032d00784104460d4c200329027c21070c500b200141046a280200211e2002411a6a2901002107200241196a2d00002101200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241086a2d00002114200241066a2f01002115200241056a2d00002116200241046a2d00002117200241026a2f010021180240024020022d0000450d00200320073702e407200320013a00e307200320083a00e207200320093b01e007410121020c010b20022d00012102200320073703e007200241ff017141014721020b200320073701d801200320013a00d701200320083a00d601200320093b01d4012003200a3a00d3012003200b3a00d2012003200c3b01d0012003200d3a00cf012003200e3a00ce012003200f3b01cc01200320103a00cb01200320113a00ca01200320123b01c801200320133a00c701200320143a00c601200320153b01c401200320163a00c301200320173a00c201200320183b01c001024002400240024020020d0020034180026a41186a200341c0016a41186a29010037030020034180026a41106a200341c0016a41106a29010037030020034180026a41086a200341c0016a41086a290100370300200320032901c00137038002200341c0016a201e10ed0420034180036a20032802c001220120032802c80110cc02200341c0056a41086a22082003419c036a28020036020020032003290294033703c00502402003280290032202450d0020034180036a41086a2903002107200329038003210520034188016a41086a2008280200360200200320032903c00537038801024020032802c401450d00200110350b200341dc066a200329038801370200200341e4066a20034190016a280200360200200320053703c806200320023602d806200320073703d006200320073703c801200320053703c001200320034180026a3602e007024020052007844200510d00200320034180026a36028801200320034188016a360288032003200341e0076a360284032003200341c0016a36028003200341c0056a20034180026a20034180036a108c030240024020032802c0054101470d0020032f00c50520032d00c705411074722108200341c8056a290300210720032d00c40521010c010b410421010240200341c0056a41086a2903004201520d00200341c0056a41106a29030021072003280288012108200341b8036a200341c0056a41186a290300370300200341b0036a200737030020034180036a41086a41003a000020034189036a200829000037000020034191036a200841086a29000037000020034199036a200841106a290000370000200341a1036a200841186a290000370000200341033a00800341b0b4cc00410020034180036a10d4010b0b200141ff01714104470d030b200329039802210720032d009702210820032d009602210920032f019402210a20032d009302210b20032d009202210c20032f019002210d20032d008f02210e20032d008e02210f20032f018c02211020032d008b02211120032d008a02211220032f018802211320032d008702211420032d008602211520032f018402211620032d008302211720032d008202211820032f018002211f0240200341c8066a41186a280200220120032802dc06470d00200341d8066a20014101108a0120032802d806210220032802e00621010b200220014105746a22022007370018200220083a0017200220093a00162002200a3b00142002200b3a00132002200c3a00122002200d3b00102002200e3a000f2002200f3a000e200220103b000c200220113a000b200220123a000a200220133b0008200220143a0007200220153a0006200220163b0004200220173a0003200220183a00022002201f3b00002003200141016a3602e00620034180036a41186a20032903e00637030020034180036a41106a200341c8066a41106a29030037030020034180036a41086a200341c8066a41086a290300370300200320032903c80637038003200341c0056a201e10ed0420032802c0052102200320032802c8053602c401200320023602c00120034180036a200341c0016a108d03024020032802c405450d00200210350b024020034194036a28020041ffffff3f71450d0020032802900310350b200341043a00c8070c500b024020032802c401450d00200110350b200341c8076a410210e80420032d00c8074104460d4f0c020b200341023a00c8070c020b200320073702cc07200320013a00c807200320083b00c907200320084110763a00cb0720032802dc0641ffffff3f71450d00200210350b20032902cc0721070b20032802c80721032000411c6a2007370200200041186a200336020020004200370308420121070c500b200141046a2802002108200341c0056a41206a200141286a290300370300200341c0056a41186a200141206a290300370300200341c0056a41106a200141186a290300370300200341c0056a41086a200141106a2903003703002003200141086a2903003703c0050240024002400240024020022d00000d0020022d000141ff01714101460d010b200341023a0080020c010b200241196a2d00002101200241186a2d00002109200241166a2f0100210a200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241086a2d00002115200241066a2f01002116200241056a2d00002117200241046a2d00002118200241026a2f0100211e20032002411a6a2901003703e006200320013a00df06200320093a00de062003200a3b01dc062003200b3a00db062003200c3a00da062003200d3b01d8062003200e3a00d7062003200f3a00d606200320103b01d406200320113a00d306200320123a00d206200320133b01d006200320143a00cf06200320153a00ce06200320163b01cc06200320173a00cb06200320183a00ca062003201e3b01c80620034180036a41206a200341c0056a41206a29030037030020034180036a41186a200341c0056a41186a29030037030020034180036a41106a200341c0056a41106a29030037030020034180036a41086a200341c0056a41086a290300370300200320032903c0053703800320034180026a200341c8066a200820034180036a108d0520032d0080024104460d0120032902840221070b20032802800221032000411c6a2007370200200041186a2003360200420121070c010b420021070b200042003703080c4f0b200141046a2802002108200341c0056a41206a200141286a290300370300200341c0056a41186a200141206a290300370300200341c0056a41106a200141186a290300370300200341c0056a41086a200141106a2903003703002003200141086a2903003703c00520022d00000d1d20022d000141ff01714101470d1d2002411a6a2901002107200241196a2d00002101200241186a2d00002109200241166a2f0100210a200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241086a2d00002114200241066a2f01002115200241056a2d00002116200241046a2d00002117200241026a2f010021182003200241096a2d00003a00c701200320143a00c601200320153b01c401200320163a00c301200320173a00c201200320183b01c0012003200e3a00cf012003200f3a00ce01200320103b01cc01200320113a00cb01200320123a00ca01200320133b01c801200320013a00d701200320093a00d6012003200a3b01d4012003200b3a00d3012003200c3a00d2012003200d3b01d001200320073701d801200341c8066a41186a2007370300200341c8066a41106a20032901d001370300200341c8066a41086a20032901c801370300200320032901c0013703c80620034180036a200341c8066a108e050240024020032d00800322024102460d0020024101470d0020034180036a41186a2d0000210220034197036a2d0000210120034195036a2f0000210920034194036a2d0000210a20034193036a2d0000210b20034191036a2f0000210c20034180036a41106a2d0000210d2003418f036a2d0000210e2003418d036a2f0000210f2003418c036a2d000021102003418b036a2d0000211120034189036a2f0000211220034180036a41086a2d0000211320032d008703211420032f008503211520032d008403211620032d008303211720032d008203211820032d008103211e200320034199036a29000037039802200320023a009702200320013a009602200320093b0194022003200a3a0093022003200b3a0092022003200c3b0190022003200d3a008f022003200e3a008e022003200f3b018c02200320103a008b02200320113a008a02200320123b018802200320133a008702200320143a008602200320153b018402200320163a008302200320173a008202200320183a0081022003201e3a00800220034180036a41206a200341c0056a41206a29030037030020034180036a41186a200341c0056a41186a29030037030020034180036a41106a200341c0056a41106a29030037030020034180036a41086a200341c0056a41086a290300370300200320032903c0053703800320034188016a20034180026a200820034180036a108d050c010b20034188016a410310e8040b024020032d0088014104460d00200329028c0121070c440b420021070c440b0240024020022d0000417f6a220841024b0d00200141046a2802002101024020080e03000102000b200241046a2d00000d00200241086a28020041036c2002410c6a2802004101744f0d010b200341023a00e0070c420b20034188016a200110f50420034180036a200328028801220820032802900110b30220032d0080032102200341c0056a20034180036a41017241e700109d081a0240024020024102460d00200341c8066a200341c0056a41e700109d081a0240200328028c01450d00200810350b20034180036a200341c8066a41e700109d081a2002450d0120034180026a411410e8040c410b0240200328028c01450d00200810350b20034180026a411410e8040c400b20034184026a20034187036a41e000109d081a20032f01bc02210220032d00be02210820032d00bf02210920032f01c002210a20032d00c202210b20032d00c302210c20032f01c402210d20032d00c602210e20032d00c702210f20032f01c802211020032d00ca02211120032d00cb02211220032f01cc02211320032d00ce02211420032d00cf02211520032f01d002211620032d00d202211720032d00d3022118200320032902d402220737039803200320183a009703200320173a009603200320163b019403200320153a009303200320143a009203200320133b019003200320123a008f03200320113a008e03200320103b018c032003200f3a008b032003200e3a008a032003200d3b0188032003200c3a0087032003200b3a0086032003200a3b018403200320093a008303200320083a008203200320023b018003200341c0056a20034180036a108f05200341186a20032802c005221f20032802c80541b0b4cc0041004100108a022003280218211e024020032802c405450d00201f10350b0240201e4101460d002003200737039803200320183a009703200320173a009603200320163b019403200320153a009303200320143a009203200320133b019003200320123a008f03200320113a008e03200320103b018c032003200f3a008b032003200e3a008a032003200d3b0188032003200c3a0087032003200b3a0086032003200a3b018403200320093a008303200320083a008203200320023b018003200341c0056a20034180036a108f0520032802c005210220033502c8052107200341013a00800320074220862002ad8420034180036aad428080808010841002024020032802c405450d00200210350b2003418c036a200136020020034188036a41063a0000200341063a00800341b0b4cc00410020034180036a10d40120034180036a200110f5042003350288034220862003280280032202ad8410070240200328028403450d00200210350b200341043a00e0070c490b200341e0076a410510e8040c400b200341d8056a200141196a290000370300200341d0056a200141116a290000370300200341c8056a200141096a290000370300200320012900013703c00502400240024020022d0000417f6a220141024b0d00024020010e03000102000b200241086a2802004101742002410c6a280200490d00200241046a28020041ff0171450d010b200341023a0080020c010b41d9e3cb00ad4280808080900184221a1001220229000021072002290008210520021035419c8dc500ad4280808080c001841001220229000021062002290008211920021035200320193701d801200320063701d001200320053701c801200320073701c001200341286a200341c0016a412041b0b4cc0041004100108a020240024020032802284101460d0020034180036a41186a2201200341c0056a41186a29030037030020034180036a41106a2208200341c0056a41106a29030037030020034180036a41086a2209200341c0056a41086a290300370300200320032903c00537038003201a100122022d000f210a20022d000e210b20022f000c210c20022d000b210d20022d000a210e20022f0008210f20022d0007211020022d0006211120022f0004211220022d0003211320022d0002211420022f000021152002103541b8a3c600ad428080808090018410012202290008210720022d0007211620022d0006211720022f0004211820022d0003211e20022d0002211f20022f0000212020021035412010332202450d4b2002200329038003370000200241186a2001290300370000200241106a2008290300370000200241086a2009290300370000412010332201450d4b20012002290000370000200141186a2208200241186a290000370000200141106a2209200241106a290000370000200141086a2221200241086a2900003700002002103541c00010332202450d4b20022007370018200220163a0017200220173a0016200220183b00142002201e3a00132002201f3a0012200220203b00102002200a3a000f2002200b3a000e2002200c3b000c2002200d3a000b2002200e3a000a2002200f3b0008200220103a0007200220113a0006200220123b0004200220133a0003200220143a0002200220153b0000200241386a2008290000370000200241306a2009290000370000200241286a2021290000370000200220012900003700202001103520034180036a200241c00010cd022003280280032109200329038803210720032802840321012002103502402001450d0020034180036a41186a420037030020034180036a41106a220a420037030020034180036a41086a22024200370300200342003703800341d1c4c700ad4280808080e000841001220829000021052002200841086a29000037030020032005370380032008103541e7c4c700ad4280808080e00084100122082900002105200341e0076a41086a220b200841086a290000370300200320053703e00720081035200a20032903e0072205370300200341c8066a41086a2002290300370300200341c8066a41106a2005370300200341c8066a41186a200b29030037030020032003290380033703c806200341206a200341c8066a412010c00102402003280224410020032802201b20094f0d0020034180026a410710e804200742ffffff3f83500d03200110350c030b200742ffffff3f83500d00200110350b20034180036a41186a200341c0056a41186a29030037030020034180036a41106a200341c0056a41106a29030037030020034180036a41086a200341c0056a41086a290300370300200320032903c00537038003200341003a00a00341d9e3cb00ad42808080809001841001220229000021072002290008210520021035419c8dc500ad4280808080c001841001220229000021062002290008211920021035200320193701d801200320063701d001200320053701c801200320073701c001200341203602cc062003200341c0016a3602c80620034180036a200341c8066a109005200341043a0080020c4a0b20034180026a410610e8040b20032d0080024104460d4820032902840221070b20032802800221032000411c6a2007370200200041186a200336020020004200370308420121070c4c0b200341c0056a41186a200141196a290000370300200341d0056a200141116a290000370300200341c0056a41086a200141096a290000370300200320012900013703c0050240024020022d0000417f6a220141024b0d00024020010e03000102000b200241046a2d00000d00200241086a2802004102742002410c6a28020041036c4f0d010b20004200370308200041186a4102360200420121070c4c0b20034180036a41186a200341c0056a41186a29030037030020034180036a41106a200341c0056a41106a29030037030020034180036a41086a200341c0056a41086a290300370300200320032903c00537038003200341023a00a00341d9e3cb00ad42808080809001841001220229000021072002290008210520021035419c8dc500ad4280808080c001841001220229000021062002290008211920021035200320193701d801200320063701d001200320053701c801200320073701c001200341203602cc062003200341c0016a3602c80620034180036a200341c8066a1090050c460b200341c0056a41186a200141196a290000370300200341d0056a200141116a290000370300200341c8056a200141096a290000370300200320012900013703c0050240024020022d0000417f6a220141024b0d00024020010e03000102000b200241086a2802002002410c6a280200490d00200241046a28020041ff0171450d010b20004200370308200041186a4102360200420121070c4b0b20034180036a41186a200341c0056a41186a29030037030020034180036a41106a200341c0056a41106a29030037030020034180036a41086a200341c0056a41086a290300370300200320032903c00537038003200341013a00a00341d9e3cb00ad42808080809001841001220229000021072002290008210520021035419c8dc500ad4280808080c001841001220229000021062002290008211920021035200320193701d801200320063701d001200320053701c801200320073701c001200341203602cc062003200341c0016a3602c80620034180036a200341c8066a1090050c450b200141286a280200210d200141246a280200210820034188016a41086a220a2002411c6a2800003602002003200241146a290000370388012002410c6a280000210b200241086a280000210c200241046a280000210920022d0000210220034198026a200141196a29000037030020034190026a200141116a29000037030020034180026a41086a200141096a29000037030020032001290001370380020240024020084180a305490d00200341e0076a41086a200a28020036020020032003290388013703e00720024102470d01200941ff01710d3941002109200c41036c200b4101744f0d3a0c380b2002417e6a220241014b0d3820020e023739370b20024103470d370c380b20034198026a200141196a29000037030020034180026a41106a200141116a29000037030020034180026a41086a200141096a290000370300200320012900013703800220022d00004102470d18200241236a2d00002108200241216a2f000021092002411f6a2d0000210a2002411d6a2f0000210b2002410f6a2d0000210c2002410d6a2f0000210d2002410b6a2d0000210e200241096a2f0000210f200241076a2d00002110200241056a2f00002111200241246a2802002112200241206a2d00002113200241116a2900002107200241106a2d000021142002410c6a2d00002115200241086a2d00002116200241046a2d000021012003200241196a2800003602e807200320073703e00720014101470d182003200920084110747222023b01dc05200341de056a20024110763a00002003200b200a4110747222023b01d805200341da056a20024110763a00002003200d200c4110747222023b01c805200341c0056a410a6a20024110763a000020032007a722023b01cc05200341ce056a20024110763a0000200320123a00df05200320133a00db05200320032902e4073703d005200320143a00cb05200320153a00c705200320163a00c305200320074218883c00cf052003200f200e4110747222023b01c405200320024110763a00c6052003201120104110747222023b01c005200320024110763a00c20541d9e3cb00ad42808080809001841001220229000021072002290008210520021035419c8dc500ad4280808080c001841001220229000021062002290008211920021035200320193701d801200320063701d001200320053701c801200320073701c00120034180036a200341c0016a10c00202400240024020032d00a0034103460d0020032903800321072003290388032105200329039003210620032003290398033703980320032006370390032003200537038803200320073703800320034180026a20034180036a412010a008450d01200341c8076a410210e8040c020b200341c8076a410a10e8040c010b200341c8066a20034180026a10910520034180036a20032802c806220220032802d00610cd022003290388032107200328028403210e024020032802cc06450d00200210350b0240200e0d004100210f200341003602900120034201370388014101210e0c330b2003200e360288012003200737028c012007a7210f41002102024002402007422088a7220a41014b0d00200a0e023401340b200a210103402001410176220820026a22092002200e20094105746a200341c0056a412010a0084101481b2102200120086b220141014b0d000b0b0240200e20024105746a200341c0056a412010a0082201450d0020034180036a41186a200341c0056a41186a29030037030020034180036a41106a200341c0056a41106a29030037030020034180036a41086a200341c0056a41086a290300370300200320032903c005370380032001411f7620026a2208200a4b0d1b20034180036a21010c340b200341c8076a410b10e804200f41ffffff3f71450d00200e10350b20032d00c8074104460d4320032902cc0721070c300b20022d000120022d0000410047720d192003418c036a200141046a280200220236020020034188036a41063a0000200341063a00800341b0b4cc00410020034180036a10d40120034180036a200210f5042003350288034220862003280280032202ad841007200328028403450d42200210350c420b20022d000120022d0000410047720d19200141046a2802002102410c10332201450d4220012002360008200142e4cab5fbb6ccdcb0e3003700004189fec600ad4280808080900184100122022900002107200341c8066a41086a200241086a290000370300200320073703c8062002103541b489c500ad4280808080e00084100122022900002107200341c0056a41086a200241086a290000370300200320073703c00520021035411010332202450d4220034210370284032003200236028003410c20034180036a107702400240200328028403220a20032802880322086b410c490d002003280280032102200a21090c010b2008410c6a22022008490d32200a41017422092002200920024b1b22094100480d3202400240200a0d00024020090d00410121020c020b200910332202450d460c010b2003280280032102200a2009460d002002200a200910372202450d450b200320093602840320032002360280030b200220086a220a2001290000370000200a41086a200141086a28000036000020032008410c6a2208ad4220862002ad841003220a29000037038801200a103520034180036a410c6a200220086a3602002003200236028803200320034188016a41086a36028403200320034188016a3602800320034180026a20034180036a107b02402009450d00200210350b200328028802220b41206a2208417f4c0d32200328028002210c0240024020080d0041002109410121020c010b200810332202450d43200821090b024002402009410f4d0d002009210a0c010b2009410174220a4110200a41104b1b220a4100480d32024020090d00200a10332202450d450c010b2009200a460d0020022009200a10372202450d440b200220032903c806370000200241086a200341c8066a41086a29030037000002400240200a4170714110460d00200a21090c010b200a41017422094120200941204b1b22094100480d32200a2009460d002002200a200910372202450d440b200220032903c005370010200241186a200341c0056a41086a29030037000002400240200941606a200b490d002009210a0c010b200b415f4b0d322009410174220a2008200a20084b1b220a4100480d322009200a460d0020022009200a10372202450d440b200241206a200c200b109d081a0240200328028402450d00200c10350b20034180036a2002200810da0141012109024002402003280280034101460d00410021090c010b2008ad4220862002ad84100720032902840321070b0240200a450d00200210350b2001103502402009450d00200341c8066a2007a710c90420034180036a20032802c806220a20032802d006220110b8022003280280032202410820021b210902402007422088a72208200329028403420020021b2207422088a722024f0d002009200841d0026c6a220b450d002009200841d0026c6a220141bc026a210a024020012802bc024102460d00024020012802b002220c450d002009200841d0026c6a41b4026a280200450d00200c10350b200b10ba020b200b20034180036a41bc02109d081a200a4102360200200141c8026a200341c8056a290300370300200120032903c0053703c00220032802d006210120032802c806210a0b0240024020090d002001ad422086200aad8410070c010b20034180036a2009200210d9042001ad422086200aad842003350288034220862003280280032201ad8410020240200328028403450d00200110350b02402002450d00200241d0026c21012009210203400240200241bc026a2802004102460d000240200241b0026a2802002208450d00200241b4026a280200450d00200810350b200210bb020b200241d0026a2102200141b07d6a22010d000b0b2007a72202450d00200241d0026c450d00200910350b024020032802cc06450d00200a10350b200341043a00c0010c420b200341c0016a410210e80420032d00c0014104460d4120032902c40121070c2d0b20034188016a41186a200141196a29000037030020034188016a41106a200141116a29000037030020034188016a41086a200141096a29000037030020032001290001370388012002411a6a2901002107200241196a2d00002101200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241086a2d00002114200241066a2f01002115200241056a2d00002116200241046a2d00002117200241026a2f010021180240024020022d0000450d00200320073702e407200320013a00e307200320083a00e207200320093b01e007410121020c010b20022d00012102200320073703e007200241ff017141014721020b200320073701d801200320013a00d701200320083a00d601200320093b01d4012003200a3a00d3012003200b3a00d2012003200c3b01d0012003200d3a00cf012003200e3a00ce012003200f3b01cc01200320103a00cb01200320113a00ca01200320123b01c801200320133a00c701200320143a00c601200320153b01c401200320163a00c301200320173a00c201200320183b01c00120020d19200341c0016a20034188016a10920520034180036a20032802c001221e20032802c801222010c402200341a0036a2d000021020240024020032d008003221f4102470d00200341023a0080020c010b200320032d0083033a008302200320032f0081033b0081022003200329028403370284022003201f3a008002200320034198036a2903003703980220032003418c036a29020037028c02200320034194036a280200360294020b200320013a00df06200320083a00de06200320093b01dc062003200a3a00db062003200b3a00da062003200c3b01d8062003200d3a00d7062003200e3a00d6062003200f3b01d406200320103a00d306200320113a00d206200320123b01d006200320133a00cf06200320143a00ce06200320153b01cc06200320163a00cb06200320173a00ca06200320183b01c806200320073703e00620034198036a20032903980237030020034180036a41206a20023a0000200341023a00c0052003200329039002370390032003200329038802370388032003200329038002220537038003200320032903d80537039802200320032903d00537039002200320032903c80537038802200320032903c00537038002024002402005a7410371417f6a220141014b0d0041192102024020010e020002000b410c21020c010b411a210220034180036a410172200341c8066a412010a0080d00200320032903c80637008102200341013a0080022003200341df066a290000370098022003200341d8066a290300370091022003200341d0066a290300370089022003200329039802370398032003200329039002370390032003200329038802370388032003200329038002220537038003024002402005a7220241ff01714102470d002020ad422086201ead8410070c010b410110332201450d44200120023a000020014101412110372202450d44200220032900810337000120022007423888a73a0020200241186a200329009803370000200241116a200329009103370000200241096a2003290089033700002020ad422086201ead842002ad42808080809004841002200210350b412621020b024020032802c401450d00201e10350b024020024126470d00200341043a00c8070c410b200341c8076a200210e80420032d00c8074104460d4020032902cc0721070c2b0b20022d00000d1920022d000141ff01714101470d19200241196a2d00002101200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241086a2d00002114200241066a2f01002115200241056a2d00002116200241046a2d00002117200241026a2f0100211820032002411a6a2901003703d805200320013a00d705200320083a00d605200320093b01d4052003200a3a00d3052003200b3a00d2052003200c3b01d0052003200d3a00cf052003200e3a00ce052003200f3b01cc05200320103a00cb05200320113a00ca05200320123b01c805200320133a00c705200320143a00c605200320153b01c405200320163a00c305200320173a00c205200320183b01c005200341c8066a200341c0056a10920520034180036a20032802c806220220032802d006220110c402024020032d0080034102460d00200341c0056a1099020b2001ad4220862002ad84100720032802cc06450d3f200210350c3f0b20034188016a41186a200141196a29000037030020034188016a41106a200141116a29000037030020034188016a41086a200141096a29000037030020032001290001370388012002411a6a2901002107200241196a2d00002101200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241086a2d00002114200241066a2f01002115200241056a2d00002116200241046a2d00002117200241026a2f010021180240024020022d0000450d00200320073702e407200320013a00e307200320083a00e207200320093b01e007410121020c010b20022d00012102200320073703e007200241ff017141014721020b200320073701d801200320013a00d701200320083a00d601200320093b01d4012003200a3a00d3012003200b3a00d2012003200c3b01d0012003200d3a00cf012003200e3a00ce012003200f3b01cc01200320103a00cb01200320113a00ca01200320123b01c801200320133a00c701200320143a00c601200320153b01c401200320163a00c301200320173a00c201200320183b01c00120020d19200341c0016a20034188016a10920520034180036a20032802c001221e20032802c801222010c402200341a0036a2d000021020240024020032d008003221f4102470d00200341023a0080020c010b200320032d0083033a008302200320032f0081033b0081022003200329028403370284022003201f3a008002200320034198036a2903003703980220032003418c036a29020037028c02200320034194036a280200360294020b200320013a00df06200320083a00de06200320093b01dc062003200a3a00db062003200b3a00da062003200c3b01d8062003200d3a00d7062003200e3a00d6062003200f3b01d406200320103a00d306200320113a00d206200320123b01d006200320133a00cf06200320143a00ce06200320153b01cc06200320163a00cb06200320173a00ca06200320183b01c806200320073703e00620034198036a20032903980237030020034180036a41206a20023a0000200341023a00c0052003200329039002370390032003200329038802370388032003200329038002220537038003200320032903d80537039802200320032903d00537039002200320032903c80537038802200320032903c00537038002411b210202402005a741ff01714101470d00410d210220034180036a410172200341c8066a412010a0080d00200320032903c80637008102200341003a0080022003200341df066a290000370098022003200341d8066a290300370091022003200341d0066a290300370089022003200329039802370398032003200329039002370390032003200329038802370388032003200329038002220537038003024002402005a7220241ff01714102470d002020ad422086201ead8410070c010b410110332201450d42200120023a000020014101412110372202450d42200220032900810337000120022007423888a73a0020200241186a200329009803370000200241116a200329009103370000200241096a2003290089033700002020ad422086201ead842002ad42808080809004841002200210350b412621020b024020032802c401450d00201e10350b024020024126470d00200341043a00c8070c3f0b200341c8076a200210e80420032d00c8074104460d3e20032902cc0721070c280b200141306a2903002107200141286a2903002105200141216a2d00002108200341c8066a41186a200141196a290000370300200341c8066a41106a200141116a290000370300200341c8066a41086a200141096a290000370300200320012900013703c8060240024020022d00000d0020022d000141ff01714101470d002002411a6a2901002106200241196a2d00002101200241186a2d00002109200241166a2f0100210a200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241086a2d00002114200241066a2f01002115200241056a2d00002116200241046a2d00002117200241026a2f010021182003200241096a2d00003a00c701200320143a00c601200320153b01c401200320163a00c301200320173a00c201200320183b01c0012003200e3a00cf012003200f3a00ce01200320103b01cc01200320113a00cb01200320123a00ca01200320133b01c801200320013a00d701200320093a00d6012003200a3b01d4012003200b3a00d3012003200c3a00d2012003200d3b01d001200320063701d801200341c0056a41186a2006370300200341c0056a41106a20032901d001370300200341c0056a41086a20032901c801370300200320032901c0013703c00520034180036a41186a200341c8066a41186a29030037030020034180036a41106a200341c8066a41106a29030037030020034180036a41086a200341c8066a41086a290300370300200320032903c8063703800320034180026a200341c0056a20034180036a20082005200710930520032d00800222024104460d3f20032f00810220032d00830241107472210120032902840221070c010b410221020b200042003703082000411c6a2007370200200041186a2001410874200272360200420121070c420b0240024020022d00000d0020022d000141ff01714101470d002002411a6a2901002107200241196a2d00002101200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241086a2d00002113200241066a2f01002114200241056a2d00002115200241046a2d00002116200241026a2f010021172003200241096a2d00003a00c701200320133a00c601200320143b01c401200320153a00c301200320163a00c201200320173b01c0012003200d3a00cf012003200e3a00ce012003200f3b01cc01200320103a00cb01200320113a00ca01200320123b01c801200320013a00d701200320083a00d601200320093b01d4012003200a3a00d3012003200b3a00d2012003200c3b01d001200320073701d80120034198036a200737030020034180036a41106a20032901d00137030020034188036a20032901c801370300200320032901c00137038003200341c0056a20034180036a10940520032d00c00522024104460d3e20032f00c10520032d00c30541107472210120032902c40521070c010b410221020b200042003703082000411c6a2007370200200041186a2001410874200272360200420121070c410b024020022d000120022d000041004772450d0020004200370308200041186a4102360200420121070c410b41d9e3cb00ad4280808080900184100122022900002107200229000821052002103541918dc500ad4280808080b001841001220229000021062002290008211920021035200320193701d801200320063701d001200320053701c801200320073701c001200341c0016aad428080808080048410070c3b0b200141086a2802002108200141046a280200210920022d00000d1620022d000141ff01714101470d162001410c6a2802002101200241196a2d0000210a200241186a2d0000210b200241166a2f0100210c200241156a2d0000210d200241146a2d0000210e200241126a2f0100210f200241116a2d00002110200241106a2d000021112002410e6a2f010021122002410d6a2d000021132002410c6a2d000021142002410a6a2f01002115200241096a2d00002116200241086a2d00002117200241066a2f01002118200241056a2d0000211e200241046a2d0000211f200241026a2f0100212020032002411a6a2901003703d8012003200a3a00d7012003200b3a00d6012003200c3b01d4012003200d3a00d3012003200e3a00d2012003200f3b01d001200320103a00cf01200320113a00ce01200320123b01cc01200320133a00cb01200320143a00ca01200320153b01c801200320163a00c701200320173a00c601200320183b01c4012003201e3a00c3012003201f3a00c201200320203b01c0012001ad22194220862009ad84100922022900002107200241086a2900002105200241106a290000210620034180026a41186a200241186a29000037030020034180026a41106a200637030020034180026a41086a200537030020032007370380022002103520034180036a20034180026a10ee04200341d8006a200328028003220a20032802880341b0b4cc0041004100108a02200328025821020240200328028403450d00200a10350b20024101460d17200341c8006a201942004280a094a58d1d42001084082003200341d0006a29030022073703d0062003200329034822053703c8062003200341c0016a3602c807024002402001450d002003200341c0016a3602e0072003200341e0076a360288032003200341c8076a360284032003200341c8066a36028003200341c0056a200341c0016a20034180036a108c030240024020032802c0054101470d0020032f00c50520032d00c70541107472210a200341c8056a290300210620032d00c40521020c010b410421020240200341c0056a41086a2903004201520d00200341c0056a41106a290300210620032802e007210a200341b8036a200341c0056a41186a290300370300200341b0036a200637030020034180036a41086a41003a000020034189036a200a29000037000020034191036a200a41086a29000037000020034199036a200a41106a290000370000200341a1036a200a41186a290000370000200341033a00800341b0b4cc00410020034180036a10d4010b0b200241ff01714104470d010b20034180036a41186a420037030020034180036a41106a220b420037030020034180036a41086a22024200370300200342003703800341d1c4c700ad4280808080e000841001220a29000021062002200a41086a2900003703002003200637038003200a103541e7c4c700ad4280808080e000841001220a2900002106200341e0076a41086a220c200a41086a290000370300200320063703e007200a1035200b20032903e0072206370300200341c8066a41086a2002290300370300200341c8066a41106a2006370300200341c8066a41186a200c29030037030020032003290380033703c806200341c0006a200341c8066a412010c0012003280244210a2003280240210b200341c0056a41186a20034180026a41186a220c290300370300200341c0056a41106a20034180026a41106a220d290300370300200341c0056a41086a20034180026a41086a220e29030037030020032003290380023703c005200341c8036a2007370300200341c0036a200537030020034189036a220f200341c0016a41086a221029030037000020034191036a2211200341c0016a41106a221229030037000020034199036a2213200341c0016a41186a2214290300370000200341b4036a4100360200200341b0036a200a4100200b1b360200200341ac036a2001360200200341a8036a2008360200200341a4036a2009360200200341013a008003200320032903c00137008103200341c0056a20034180036a109505200341d8036a2007370300200341d0036a20053703002002410b3a0000200f2003290380023700002011200e2903003700002013200d290300370000200341a1036a200c290300370000200341a9036a20032903c001370000200341b1036a2010290300370000200341b9036a2012290300370000200341c1036a2014290300370000200341063a00800341b0b4cc00410020034180036a10d401200341043a0088010c3b0b2003200637028c01200320023a0088012003200a3b0089012003200a4110763a008b010c230b200141086a2802002108200141046a280200210902400240024020022d00000d0020022d000141ff01714101470d002001410c6a2802002101200241196a2d0000210a200241186a2d0000210b200241166a2f0100210c200241156a2d0000210d200241146a2d0000210e200241126a2f0100210f200241116a2d00002110200241106a2d000021112002410e6a2f010021122002410d6a2d000021132002410c6a2d000021142002410a6a2f01002115200241096a2d00002116200241086a2d00002117200241066a2f01002118200241056a2d0000211e200241046a2d0000211f200241026a2f0100212020032002411a6a2901003701d8012003200a3a00d7012003200b3a00d6012003200c3b01d4012003200d3a00d3012003200e3a00d2012003200f3b01d001200320103a00cf01200320113a00ce01200320123b01cc01200320133a00cb01200320143a00ca01200320153b01c801200320163a00c701200320173a00c601200320183b01c4012003201e3a00c3012003201f3a00c201200320203b01c0012001ad4220862009ad84100922022900002107200241086a2900002105200241106a290000210620034180026a41186a200241186a29000037030020034180026a41106a200637030020034180026a41086a2005370300200320073703800220021035200341c0056a20034180026a10ee0420034180036a20032802c005220a20032802c80510d20220032802c4052102024002400240024020032d008003220b4102460d00200341a8036a280200210c200341a4036a280200210d200335028403210702402002450d00200a10350b200b450d014201210542801e2107200c450d02200d10350c020b02402002450d00200a10350b411021020c020b200742208642801e842107420021050b410f21022005200784a741ff01714101470d030b20034188016a200210e8040c010b200341023a0088010b02402008450d00200910350b20032d0088014104460d3a20032802880121022000411c6a200329028c01370200200041186a200236020020004200370308420121070c3f0b20034180036a41186a420037030020034180036a41106a220b420037030020034180036a41086a22024200370300200342003703800341d1c4c700ad4280808080e000841001220a29000021052002200a41086a2900003703002003200537038003200a103541e7c4c700ad4280808080e000841001220a2900002105200341e0076a41086a220c200a41086a290000370300200320053703e007200a1035200b20032903e0072205370300200341c8066a41086a2002290300370300200341c8066a41106a2005370300200341c8066a41186a200c29030037030020032003290380033703c806200341e0006a200341c8066a412010c0012003280264210a2003280260210b200341c0056a41186a20034180026a41186a220c290300370300200341c0056a41106a20034180026a41106a220d290300370300200341c0056a41086a20034180026a41086a220e29030037030020032003290380023703c005200341c8036a4200370300200341c0036a420037030020034189036a220f200341c0016a41086a221029010037000020034191036a2211200341c0016a41106a221229010037000020034199036a2213200341c0016a41186a2214290100370000200341b8036a20074220883e0200200341b4036a4101360200200341b0036a200a4100200b1b360200200341ac036a2001360200200341a8036a2008360200200341a4036a2009360200200341013a008003200320032901c00137008103200341c0056a20034180036a109505200341d8036a4200370300200341d0036a42003703002002410b3a0000200f2003290380023700002011200e2903003700002013200d290300370000200341a1036a200c290300370000200341a9036a20032901c001370000200341b1036a2010290100370000200341b9036a2012290100370000200341c1036a2014290100370000200341063a00800341b0b4cc00410020034180036a10d401200341043a0088010c390b20034188016a41186a200141196a29000037030020034188016a41106a200141116a29000037030020034188016a41086a200141096a29000037030020032001290001370388012002411a6a2901002107200241196a2d00002101200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241086a2d00002114200241066a2f01002115200241056a2d00002116200241046a2d00002117200241026a2f010021180240024020022d0000450d00200320073702e407200320013a00e307200320083a00e207200320093b01e007410121020c010b20022d00012102200320073703e007200241ff017141014721020b200320073701d801200320013a00d701200320083a00d601200320093b01d4012003200a3a00d3012003200b3a00d2012003200c3b01d0012003200d3a00cf012003200e3a00ce012003200f3b01cc01200320103a00cb01200320113a00ca01200320123b01c801200320133a00c701200320143a00c601200320153b01c401200320163a00c301200320173a00c201200320183b01c0010240024020020d0020034180026a41186a200341c0016a41186a29010037030020034180026a41106a200341c0016a41106a29010037030020034180026a41086a200341c0016a41086a290100370300200320032901c00137038002200341c0056a20034188016a10ee0420034180036a20032802c005220120032802c80510d20220032802c40521020240024020032d00800322084102460d00200341c8036a2903002105200341c0036a2903002106200341b8036a2802002122200341b4036a2802002121200341b0036a280200210a200341a8036a280200210b200341a4036a280200212020034199036a290000210720034180036a41186a2d0000210c20034197036a2d0000210d20034195036a2f0000210e20034194036a2d0000210f20034193036a2d0000211020034191036a2f0000211120034180036a41106a2d000021122003418f036a2d000021132003418d036a2f000021142003418c036a2d000021152003418b036a2d0000211620034189036a2f0000211720034180036a41086a2d00002118200328028403210920032d008303211e20032f008103211f02402002450d00200110350b2008450d0120094118762102200941087621010240200b450d00202010350b200320073703d8052003200c3a00d7052003200d3a00d6052003200e3b01d4052003200f3a00d305200320103a00d205200320113b01d005200320123a00cf05200320133a00ce05200320143b01cc05200320153a00cb05200320163a00ca05200320173b01c805200320183a00c705200320023a00c605200320013b01c405200320093a00c3052003201e3a00c2052003201f3b01c00520034180036a41186a420037030020034180036a41106a2208420037030020034180036a41086a22024200370300200342003703800341d1c4c700ad4280808080e000841001220129000021072002200141086a29000037030020032007370380032001103541e7c4c700ad4280808080e00084100122012900002107200341e0076a41086a2209200141086a290000370300200320073703e00720011035200820032903e0072207370300200341c8066a41086a2002290300370300200341c8066a41106a2007370300200341c8066a41186a200929030037030020032003290380033703c806200341e8006a200341c8066a412010c001411121020240200328026c410020032802681b2201200a4180de34410020034180026a200341c0056a412010a0081b6a41809c316a490d002021450d0441122102200120224b0d040b200341c8076a200210e8040c230b2002450d00200110350b200341c8076a411310e8040c210b200341023a00c8070c210b20034180036a200341c0056a20034180026a20062005410010ef0220034180036a20034188016a10ee042003350288034220862003280280032202ad8410070240200328028403450d00200210350b20034180036a41086a410f3a000020034189036a200329038801370000200341a9036a20032903c00537000020034191036a20034188016a41086a29030037000020034199036a20034188016a41106a290300370000200341a1036a20034188016a41186a290300370000200341b1036a200341c0056a41086a290300370000200341b9036a200341c0056a41106a290300370000200341c1036a200341c0056a41186a290300370000200341063a008003200341f0036a2006370300200341f8036a2005370300200341e1036a20034180026a41186a290300370000200341d9036a20034180026a41106a290300370000200341d1036a20034180026a41086a290300370000200341c9036a20032903800237000041b0b4cc00410020034180036a10d401200341043a00c8070c380b20034180026a41186a200141196a29000037030020034190026a200141116a29000037030020034188026a200141096a29000037030020032001290001370380022002411a6a2901002107024020022d0000450d00200241166a2f01002101200241186a2d00002108200241196a2d00002102200320073702e407200320023a00e307200320083a00e207200320013b01e0070c1e0b20022d00012102200320073703e007200241ff01714101470d1d200341c0016a20034180026a10960520034180036a20032802c001220920032802c801220a10c90220032d0080032102200341c8066a20034180036a41017241ef00109d081a0240024020024102470d00200341d0056a4200370300200341d8056a4200370300200341e0056a4200370300200341e8056a4200370300200341f0056a4200370300200341f8056a42003703004100210220034180066a4100360200200341083602c405200341c0056a41086a4200370300200341003a00c0050c010b200320023a00c005200341c0056a410172200341c8066a41ef00109d081a200241014621020b20034180036a41186a420037030020034180036a41106a220b420037030020034180036a41086a22014200370300200342003703800341d1c4c700ad4280808080e000841001220829000021072001200841086a29000037030020032007370380032008103541e7c4c700ad4280808080e00084100122082900002107200341e0076a41086a220c200841086a290000370300200320073703e00720081035200b20032903e0072207370300200341c8066a41086a2001290300370300200341c8066a41106a2007370300200341c8066a41186a200c29030037030020032003290380033703c806200341f0006a200341c8066a412010c001024020034198066a200341f0056a20021b22012802102003280274410020032802701b4b0d0020014200370300200141106a4100360200200141086a42003703000b024002402002450d00200341f0056a2903002106200341e8056a29030021190c010b200341f8056a290300210620032903f0052119200341cc056a28020041306c2201450d0020032802c40541206a21020340200241706a22082903002105200841086a29030021070240200241686a2d00004101470d00427f2007200241086a2903007c200520022903007c221a2005542208ad7c22052008200520075420052007511b22081b2107427f201a20081b21050b200620072005201954200720065420072006511b22081b21062019200520081b2119200241306a2102200141506a22010d000b0b20034180036a200341c0056a41f000109d081a0240024020032d00800322024102470d00200aad4220862009ad8410070c010b200341c8066a20034180036a108005200aad4220862009ad8420033502d00642208620032802c8062201ad841002024020032802cc06450d00200110350b20020d0020034188036a2802002202450d00200241306c450d0020032802840310350b024020032802c401450d00200910350b02402019200684500d00200342e4cab5fbb6ccdcb0e3003703800320034180036a20034180026a2019200641021090020c380b200342e4cab5fbb6ccdcb0e3003703800320034180036a20034180026a1092020c370b20022d00000d1420022d000141ff01714101470d14200141196a2900002105200141186a2d00002109200141176a2d0000210a200141156a2f0000210b200141146a2d0000210c200141136a2d0000210d200141116a2f0000210e200141106a2d0000210f2001410f6a2d000021102001410d6a2f000021112001410c6a2d000021122001410b6a2d00002113200141096a2f00002114200141086a2d00002115200141076a2d00002116200141056a2f00002117200141046a2d00002118200141036a2d0000211e20012f00012101200241196a3100002106200241186a3100002119200241166a330100211a200241156a310000211b200241146a310000211c200241126a330100211d200241116a2d00002108200241106a2d0000211f2002410e6a2f010021202002410d6a2d000021212002410c6a2d000021222002410a6a2f01002123200241096a2d00002124200241086a2d00002125200241066a2f01002126200241056a2d00002127200241046a2d00002128200241026a2f01002129200341de056a2002411a6a29010022074230883c0000200341ce056a201f3a0000200341ca056a20223a000020032007a722023b01d805200341da056a20024110763a0000200320203b01cc05200320233b01c805200320253a00c605200320263b01c405200320283a00c205200320293b01c005200320083a00cf05200320213a00cb05200320243a00c705200320273a00c305200320074220883d01dc05200320074238883c00df05200320074218883c00db052003201d201c42108684201b42188684201a422086842019423086842006423886843703d005200341c8066a200341c0056a10920520034180036a20032802c806220820032802d006221f10c4020240024020032d0080034102460d0020032003290081033701c001200320034199036a2900003701d801200320034189036a2900003701c801200320034191036a2900003701d00120014180fe037141087621020c010b20014180fe03714108762102200341c0056a108d020b200320153a00c701200320163a00c601200320173b01c401200320183a00c3012003201e3a00c20120032002410874200141ff0171723b01c0012003200f3a00cf01200320103a00ce01200320113b01cc01200320123a00cb01200320133a00ca01200320143b01c801200320093a00d7012003200a3a00d6012003200b3b01d4012003200c3a00d3012003200d3a00d2012003200e3b01d001200320053701d80120034198036a200537030020034190036a20032901d00137030020034180036a41086a20032901c801370300200320032901c00137038003410110332202450d38200241003a000020024101412110372202450d382002200329038003370001200241196a20034198036a290300370000200241116a20034190036a290300370000200241096a20034188036a290300370000201fad4220862008ad842002ad428080808090048410022002103520032802cc06450d36200810350c360b0240024002400240024020022d00000d0020022d000141ff01714101460d010b200341023a00c0050c010b200141046a2802002101200241196a2d00002108200241186a2d00002109200241166a2f0100210a200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241086a2d00002115200241066a2f01002116200241056a2d00002117200241046a2d00002118200241026a2f0100211e20032002411a6a29010037039803200320083a009703200320093a0096032003200a3b0194032003200b3a0093032003200c3a0092032003200d3b0190032003200e3a008f032003200f3a008e03200320103b018c03200320113a008b03200320123a008a03200320133b018803200320143a008703200320153a008603200320163b018403200320173a008303200320183a0082032003201e3b018003200341c0056a20034180036a2001410010970520032d00c0054104460d0120032902c40521070b20032802c00521032000411c6a2007370200200041186a2003360200420121070c010b420021070b200042003703080c3a0b200141246a2802002108200341c0056a41186a200141196a290000370300200341c0056a41106a200141116a290000370300200341c0056a41086a200141096a290000370300200320012900013703c0050240024020022d00000d0020022d000141ff01714101470d00200241196a2d00002101200241186a2d00002109200241166a2f0100210a200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241086a2d00002115200241066a2f01002116200241056a2d00002117200241046a2d00002118200241026a2f0100211e20032002411a6a29010037039803200320013a009703200320093a0096032003200a3b0194032003200b3a0093032003200c3a0092032003200d3b0190032003200e3a008f032003200f3a008e03200320103b018c03200320113a008b03200320123a008a03200320133b018803200320143a008703200320153a008603200320163b018403200320173a008303200320183a0082032003201e3b018003200341c8066a200341c0056a2008200341c0056a20034180036a412010a00841004710970520032d00c80622024104460d3620032f00c90620032d00cb0641107472210120032902cc0621070c010b410221020b200042003703082000411c6a2007370200200041186a2001410874200272360200420121070c390b200141306a2903002107200141286a2903002105200141216a2d00002108200341c8066a41186a200141196a290000370300200341c8066a41106a200141116a290000370300200341c8066a41086a200141096a290000370300200320012900013703c80620022d00000d1220022d000141ff01714101470d122002411a6a2901002106200241196a2d00002101200241186a2d00002109200241166a2f0100210a200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241086a2d00002114200241066a2f01002115200241056a2d00002116200241046a2d00002117200241026a2f010021182003200241096a2d00003a00c701200320143a00c601200320153b01c401200320163a00c301200320173a00c201200320183b01c0012003200e3a00cf012003200f3a00ce01200320103b01cc01200320113a00cb01200320123a00ca01200320133b01c801200320013a00d701200320093a00d6012003200a3b01d4012003200b3a00d3012003200c3a00d2012003200d3b01d001200320063701d801200341c0056a41186a2006370300200341c0056a41106a20032901d001370300200341c0056a41086a20032901c801370300200320032901c0013703c00520034180036a200341c0056a108e05024020032d00800322024102460d0020024101470d0020034180036a41186a2d0000210220034197036a2d0000210120034195036a2f0000210920034194036a2d0000210a20034193036a2d0000210b20034191036a2f0000210c20034180036a41106a2d0000210d2003418f036a2d0000210e2003418d036a2f0000210f2003418c036a2d000021102003418b036a2d0000211120034189036a2f0000211220034180036a41086a2d0000211320032d008703211420032f008503211520032d008403211620032d008303211720032d008203211820032d008103211e200320034199036a2900003703d805200320023a00d705200320013a00d605200320093b01d4052003200a3a00d3052003200b3a00d2052003200c3b01d0052003200d3a00cf052003200e3a00ce052003200f3b01cc05200320103a00cb05200320113a00ca05200320123b01c805200320133a00c705200320143a00c605200320153b01c405200320163a00c305200320173a00c205200320183a00c1052003201e3a00c00520034180036a41186a200341c8066a41186a29030037030020034180036a41106a200341c8066a41106a29030037030020034180036a41086a200341c8066a41086a290300370300200320032903c8063703800320034180026a200341c0056a20034180036a200820052007109305024020032d00800222024104470d00200341043a0088010c350b20032d008302210120032f00810221082003200329028402220737028c01200320023a0088012003200820014110747222023b008901200320024110763a008b010c190b20034188016a410310e80420032d0088014104460d33200329028c0121070c180b20022d00000d1220022d000141ff01714101470d122002411a6a2901002107200241196a2d00002101200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241086a2d00002113200241066a2f01002114200241056a2d00002115200241046a2d00002116200241026a2f010021172003200241096a2d00003a00c701200320133a00c601200320143b01c401200320153a00c301200320163a00c201200320173b01c0012003200d3a00cf012003200e3a00ce012003200f3b01cc01200320103a00cb01200320113a00ca01200320123b01c801200320013a00d701200320083a00d601200320093b01d4012003200a3a00d3012003200b3a00d2012003200c3b01d001200320073701d801200341c0056a41186a2007370300200341c0056a41106a20032901d001370300200341c0056a41086a20032901c801370300200320032901c0013703c00520034180036a200341c0056a108e05024020032d00800322024102460d0020024101470d0020034180036a41186a2d0000210220034197036a2d0000210120034195036a2f0000210820034194036a2d0000210920034193036a2d0000210a20034191036a2f0000210b20034180036a41106a2d0000210c2003418f036a2d0000210d2003418d036a2f0000210e2003418c036a2d0000210f2003418b036a2d0000211020034189036a2f0000211120034180036a41086a2d0000211220032d008703211320032f008503211420032d008403211520032d008303211620032d008203211720032d0081032118200320034199036a29000037039803200320023a009703200320013a009603200320083b019403200320093a0093032003200a3a0092032003200b3b0190032003200c3a008f032003200d3a008e032003200e3b018c032003200f3a008b03200320103a008a03200320113b018803200320123a008703200320133a008603200320143b018403200320153a008303200320163a008203200320173a008103200320183a008003200341c0056a20034180036a109405024020032d00c00522024104470d00200341043a00c8060c340b20032d00c305210120032f00c1052108200320032902c40522073702cc06200320023a00c8062003200820014110747222023b00c906200320024110763a00cb060c170b200341c8066a410310e80420032d00c8064104460d3220032902cc0621070c160b20022d00000d1220022d000141ff01714101470d12200141046a28020021182002411a6a2901002107200241196a2d00002101200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241086a2d00002113200241066a2f01002114200241056a2d00002115200241046a2d00002116200241026a2f010021172003200241096a2d00003a00c701200320133a00c601200320143b01c401200320153a00c301200320163a00c201200320173b01c0012003200d3a00cf012003200e3a00ce012003200f3b01cc01200320103a00cb01200320113a00ca01200320123b01c801200320013a00d701200320083a00d601200320093b01d4012003200a3a00d3012003200b3a00d2012003200c3b01d001200320073701d801200341c0056a41186a2007370300200341c0056a41106a20032901d001370300200341c0056a41086a20032901c801370300200320032901c0013703c00520034180036a200341c0056a108e050240024020032d00800322024102460d0020024101470d0020034180036a41186a2d0000210220034197036a2d0000210120034195036a2f0000210820034194036a2d0000210920034193036a2d0000210a20034191036a2f0000210b20034180036a41106a2d0000210c2003418f036a2d0000210d2003418d036a2f0000210e2003418c036a2d0000210f2003418b036a2d0000211020034189036a2f0000211120034180036a41086a2d0000211220032d008703211320032f008503211420032d008403211520032d008303211620032d008203211720032d008103211e200320034199036a2900003703e006200320023a00df06200320013a00de06200320083b01dc06200320093a00db062003200a3a00da062003200b3b01d8062003200c3a00d7062003200d3a00d6062003200e3b01d4062003200f3a00d306200320103a00d206200320113b01d006200320123a00cf06200320133a00ce06200320143b01cc06200320153a00cb06200320163a00ca06200320173a00c9062003201e3a00c80620034180026a200341c8066a201841001097050c010b20034180026a410310e8040b024020032d0080024104460d0020032902840221070c140b420021070c140b200141246a2802002108200341c0056a41186a2209200141196a290000370300200341c0056a41106a220a200141116a290000370300200341c0056a41086a220b200141096a290000370300200320012900013703c005024002400240024020022d000120022d000041004772450d00200341023a00c8060c010b20034180036a41186a200929030037030020034180036a41106a200a29030037030020034180036a41086a200b290300370300200320032903c00537038003200341c8066a20034180036a200810f40420032d00c8064104460d0120032902cc0621070b20032802c80621032000411c6a2007370200200041186a2003360200420121070c010b420021070b200042003703080c350b2001200241e88cc5001059000b2002200a41e88cc5001058000b2009200a41f88cc5001059000b20034188016a41146a410a36020020034194016a410c360200200341e0076a41146a41033602002003200341d8076a3602f8072003200341dc076a3602fc0720034180036a41146a4100360200200342033702e407200341a0b3cc003602e0072003410c36028c01200341b0b4cc00360290032003420137028403200341f4b3cc0036028003200320034188016a3602f007200320034180036a360298012003200341fc076a360290012003200341f8076a36028801200341e0076a41b0b4cc00104c000b200341023a0088010c250b200341023a00c8070c170b2008200a104d000b20004200370308200041186a4102360200420121070c2d0b200341023a00c0010c130b200341023a00c8070c110b20004200370308200041186a4102360200420121070c2a0b200341023a00c8070c0e0b200341023a0088010c0c0b20034188016a410f10e8040c0b0b20004200370308200041186a4102360200420121070c260b200341023a0088010c050b200341023a00c8060c030b200341023a0080020b20032802800221032000411c6a2007370200200041186a2003360200420121070b200042003703080c210b20032802c80621032000411c6a2007370200200041186a200336020020004200370308420121070c200b20032802880121032000411c6a2007370200200041186a200336020020004200370308420121070c1f0b200041186a410236020020004200370308420121070c1e0b20032d00c8074104460d1820032902cc0721070b20032802c80721032000411c6a2007370200200041186a200336020020004200370308420121070c1c0b02402008450d00200910350b20032d0088014104460d1620032802880121022000411c6a200329028c01370200200041186a200236020020004200370308420121070c1b0b20032802c80721032000411c6a2007370200200041186a200336020020004200370308420121070c1a0b20032802c80721032000411c6a2007370200200041186a200336020020004200370308420121070c190b20032802c00121032000411c6a2007370200200041186a200336020020004200370308420121070c180b20032802c80721032000411c6a2007370200200041186a200336020020004200370308420121070c170b20034180036a41186a200341c0056a41186a29030037030020034180036a41106a200341c0056a41106a29030037030020034180036a41086a200341c0056a41086a290300370300200320032903c005370380034100210a20034180036a2101410021080b0240200a200f470d0020034188016a200a4101108a01200328028c01210f200328028801210e0b200e20084105746a220241206a2002200a20086b410574109e081a20022001290000370000200241186a200141186a290000370000200241106a200141106a290000370000200241086a200141086a2900003700002003200a41016a22023602900120034180036a41186a420037030020034180036a41106a2209420037030020034180036a41086a22014200370300200342003703800341d1c4c700ad4280808080e000841001220829000021072001200841086a29000037030020032007370380032008103541e7c4c700ad4280808080e00084100122082900002107200341e0076a41086a220a200841086a290000370300200320073703e00720081035200920032903e0072207370300200341c8066a41086a2001290300370300200341c8066a41106a2007370300200341c8066a41186a200a29030037030020032003290380033703c806200341386a200341c8066a412010c001200328023c21092003280238210a200341c8066a20034180026a1091052002410574220b41047241046a2201417f4c0d0120033502d006210720032802c8062110200110332208450d112008200941809c316a41809c31200a1b2211360000200341043602880320032001360284032003200836028003200220034180036a10770240024020020d0020032802880321012003280284032109200328028003210d0c010b410020032802880322016b210a200328028003210d2003280284032109200e210c0340200c210202402009200a6a411f4b0d00200141206a22082001490d032009410174220c2008200c20084b1b22084100480d03024002400240024020090d00024020080d004101210d0c020b20081033210d0c030b20092008470d010b200821090c020b200d200920081037210d0b20082109200d450d150b200241206a210c200d20016a22082002290000370000200841186a200241186a290000370000200841106a200241106a290000370000200841086a200241086a290000370000200a41606a210a200141206a2101200b41606a220b0d000b200320093602840320032001360288032003200d360280030b20074220862010ad842001ad422086200dad84100202402009450d00200d10350b024020032802cc06450d00201010350b0240200f41ffffff3f71450d00200e10350b20034180036a41086a410a3a000020034189036a20032903c005370000200341a9036a20032903800237000020034191036a200341c0056a41086a29030037000020034199036a200341c0056a41106a290300370000200341a1036a200341c0056a41186a290300370000200341b1036a20034180026a41086a290300370000200341b9036a20034180026a41106a290300370000200341c1036a20034180026a41186a290300370000200341063a008003200341cc036a201136020041b0b4cc00410020034180036a10d40141d9e3cb00ad42808080809001841001220229000021072002290008210520021035419c8dc500ad4280808080c001841001220229000021062002290008211920021035200320193701d801200320063701d001200320053701c801200320073701c001200341c0016aad42808080808004841007200341043a00c8070c100b103e000b1044000b200941ff01710d00200c200b4f0d010b200341023a00c8070c010b41d9e3cb00ad42808080809001841001220229000021072002290008210520021035419c8dc500ad4280808080c001841001220229000021062002290008211920021035200320193701d801200320063701d001200320053701c801200320073701c00120034180036a200341c0016a10c0020240024020032d00a00322024103460d0020032f018003210120032d008203210920032d008303210a20032f018403210b20032d008603210c20032d008703210e20032f018803210f20032d008a03211020032d008b03211120032f018c03211220032d008e03211320032d008f03211420032f019003211520032d009203211620032d009303211720032f019403211820032d009603211e20032d009703211f20032003290398033703d8052003201f3a00d7052003201e3a00d605200320183b01d405200320173a00d305200320163a00d205200320153b01d005200320143a00cf05200320133a00ce05200320123b01cc05200320113a00cb05200320103a00ca052003200f3b01c8052003200e3a00c7052003200c3a00c6052003200b3b01c4052003200a3a00c305200320093a00c205200320013a00c00541082109200320014108763a00c10502402002450d004109210920034180026a200341c0056a412010a008450d040b200341c8076a200910e8040c010b200341c8076a410210e8040b20032d00c8074104460d0b20032902cc0721070b20032802c80721032000411c6a2007370200200041186a200336020020004200370308420121070c0f0b41d9e3cb00ad42808080809001841001220129000021072001290008210520011035419c8dc500ad4280808080c001841001220129000021062001290008211920011035200320193701d801200320063701d001200320053701c801200320073701c001200341c0016aad4280808080800484100720034180036a41186a220b420037030020034180036a41106a2209420037030020034180036a41086a22014200370300200342003703800341d1c4c700ad4280808080e000841001220a29000021072001200a41086a2900003703002003200737038003200a103541e7c4c700ad4280808080e000841001220a2900002107200341e0076a41086a220c200a41086a290000370300200320073703e007200a1035200920032903e0072207370300200341c8066a41086a2001290300370300200341c8066a41106a2007370300200341c8066a41186a200c29030037030020032003290380033703c806200341306a200341c8066a412010c0012003280234210a2003280230210c200b20034180026a41186a290300370300200920034180026a41106a290300370300200120034180026a41086a290300370300200320032903800237038003200a4100200c1b20086a20034180036a2002200d10e904200341043a00c8070c090b200341c0016a41086a20034180026a41086a2902002207370300200341c0016a41106a20034180026a41106a290200370300200341c0016a41186a20034180026a41186a290200370300200341c0016a41206a20034180026a41206a290200370300200341c0016a41286a20034180026a41286a290200370300200341c0016a41306a20034180026a41306a290200370300200341c0016a41386a20034180026a41386a280200360200200320032902800222053703c001200341e0076a41086a20073e0200200320053703e0070b20032d00e0074104460d0720032902e40721070b20032802e00721032000411c6a2007370200200041186a200336020020004200370308420121070c0b0b20032802880121032000411c6a2007370200200041186a2003360200420121070b200042003703080c090b20032802c007210120032802bc07210920032802b80721020b2002450d0020072001ad4220862002ad8410022009450d01200210350c010b41d9e3cb00ad42808080809001841001220229000021192002290008211a2002103541918dc500ad4280808080b0018410012202290000211b2002290008211c200210352003201c3701d8012003201b3701d0012003201a3701c801200320193701c001410810332202450d0220034208370284032003200236028003410120034180036a107720032802ac0120034180036a108c05200328028403210220072003350288034220862003280280032201ad8410022002450d00200110350b20034198036a200537030020034190036a20063703002003418c036a200836020020034188036a41003a0000200341063a00800341b0b4cc00410020034180036a10d401200341043a00780b42002107200042003703080c040b1045000b103c000b200341023a00780b200328027821032000411c6a2007370200200041186a200336020020004200370308420121070b20002007370300200424000b880101027f230041106b220224002002200028020036020c20012002410c6a4104107802404120103322030d001045000b20032000290004370000200341186a2000411c6a290000370000200341106a200041146a290000370000200341086a2000410c6a2900003700002001200341201078200310352001200041246a41201078200241106a24000bb91e06037f0d7e027f017e057f047e230041b0066b22042400200441d0036a200210f504200441d0046a20042802d003220520042802d80310b30220042d00d0042106200441e0036a200441d0046a41017241e700109d081a024002400240024020064102460d00200441c0056a200441e0036a41e700109d081a024020042802d403450d00200510350b200441e8026a200441c0056a41e700109d081a200441d0046a200441e8026a41e700109d081a2006450d01200441f8016a411410e8040c020b024020042802d403450d00200510350b200441f8016a411410e8040c010b200441fc016a200441d7046a41e000109d081a200441c8016a41206a200441cc026a2902002207370300200441c8016a41186a200441c4026a2902002208370300200441c8016a41106a200441bc026a2902002209370300200441c8016a41086a200441b4026a290200220a370300200441c8016a41286a2206200441d4026a290200370300200420042902ac02220b3703c80120044184026a290200210c20044194026a290200210d200441a4026a290200210e20042902fc01210f200429028c022110200429029c022111200441e8026a41086a200a370300200441e8026a41106a2009370300200441e8026a41186a2008370300200441e8026a41206a2007370300200441e8026a41286a20062903003703002004200b3703e802200341186a2903002112200341086a2903002108200341206a2903002113200341106a290300210720032d00002114200441e0036a2001108e02200441d0046a20042802e003221520042802e803108f02427f200720137c200820127c220a2008542206ad7c22092006200920075420092007511b22061b2007201441014622051b2109427f200a20061b200820051b210b200441d0046a41106a290300420020042903d00442015122061b210a20042903d804420020061b2116024020042802e403450d00201510350b0240024002400240024002400240024002400240200b2016562009200a562009200a511b0d00200441c8016a2001109605200441d0046a20042802c801221720042802d001221810c90220042d00d0042106200441c0056a200441d0046a41017241ef00109d081a0240024020064102470d00200441f0036a4200370300200441f8036a420037030020044180046a420037030020044188046a420037030020044190046a420037030020044198046a420037030041002106200441a0046a4100360200200441083602e403200441e0036a41086a4200370300200441003a00e0030c010b200420063a00e003200441e0036a410172200441c0056a41ef00109d081a0b411e210520060d0420042802e403211941002106024002400240024002400240200441ec036a280200221a41014b0d00201a0e020201020b201a2105034020062005410176221520066a221b2019201b41306c6a28020020024b1b2106200520156b220541014b0d000b0b2019200641306c6a28020022052002460d01200620052002496a21060b200441f4046a200341206a290200370200200441ec046a200341186a290200370200200441e4046a200341106a290200370200200441dc046a200341086a290200370200200420032902003702d404201a2006490d010240201a200441e0036a41086a280200470d00200441e0036a410472201a410110880120042802e40321190b2019200641306c6a220541306a2005201a20066b41306c109e081a20052002360200200520042902d0043702042005410c6a200441d8046a290200370200200541146a200441e0046a2902003702002005411c6a200441e8046a290200370200200541246a200441f0046a2902003702002005412c6a200441f8046a2802003602002004201a41016a3602ec030c060b201a20064d0d012019200641306c6a220641186a290300211c200641106a290300210a0240024020062d000822154101470d0041202105200441e8006a200641206a290300221d200641286a290300221e420a4200109808200441f8006a200a201c420a42001098082011200a7d221f201156200e201c7d2011200a54ad7d221c200e56201c200e511b0d08201f201d7d2216201f56201c201e7d201f201d54ad7d220a201c56200a201c511b0d08200f2004290378220e7d221f200f56200c200441f8006a41086a2903007d200f200e54ad7d221c200c56201c200c511b0d0920102004290368220e7d220f201056200d200441e8006a41086a2903007d2010200e54ad7d220c200d56200c200d511b450d010c0a0b200641096a2d0000211b024002402006410a6a2d0000220541ff0171450d00200441a8016a201c42002005ad42ff018322164200108408200441b8016a200a42002016420010840820044198016a42004200200a4200108408427f200441c0016a290300221620042903a8012004290398017c7c221f20042903b00120042903a00184420052201f2016547222051b211d427f20042903b80120051b211f0c010b20044188016a200a201c420a420010980820044190016a290300211d200429038801211f0b412021052011200a7d2216201156200e201c7d2011200a54ad7d220a200e56200a200e511b0d070240201b41ff01710d002010201f7d2211201056200d201d7d2010201f54ad7d220e200d56200e200d511b0d0920112110200e210d200f211e200c211c0c050b200f201f7d221e200f56200c201d7d200f201f54ad7d221c200c56201c200c511b450d040c080b20162111200a210e200f2110200c210d201f210f201c210c0c040b2006201a104d000b2006201a41ecc0c6001042000b2000412110e8040c0a0b0240024020150d00201b41ff01714102460d004200200a20044188046a2903007d201620044180046a290300221154ad7d220e201620117d2211201656200e200a56200e200a511b22051b210e4200201120051b2111200441f8036a290300211620042903f003210a0240201b4101710d004200200d20167d2010200a54ad7d22162010200a7d220a2010562016200d562016200d511b22051b210d4200200a20051b21100c020b4200201c20167d201e200a54ad7d2216201e200a7d220a201e562016201c562016201c511b22051b210c4200200a20051b210f0c020b20162111200a210e0b201e210f201c210c0b200641086a22062003290300370300200641206a200341206a290300370300200641186a200341186a290300370300200641106a200341106a290300370300200641086a200341086a2903003703000b0240024020144101470d00200441086a20122013420a4200109808200441186a20082007420a4200109808411f2105201120087c22082011542206200e20077c2006ad7c2207200e542007200e511b0d02200820127c22162008542206200720137c2006ad7c220a200754200a2007511b0d02200f20042903187c221f200f542206200c200441186a41086a2903007c2006ad7c221c200c54201c200c511b0d03201020042903087c22082010542206200d200441086a41086a2903007c2006ad7c2207200d542007200d511b0d040c010b20032d0001211502400240200341026a2d0000220641ff0171450d00200441c8006a200742002006ad42ff0183220a4200108408200441d8006a20084200200a4200108408200441386a4200420020084200108408427f200441e0006a290300220a200429034820042903387c7c221220042903502004290340844200522012200a547222061b2112427f200429035820061b21130c010b200441286a20082007420a4200109808200441306a2903002112200429032821130b411f2105201120087c22162011542206200e20077c2006ad7c220a200e54200a200e511b0d0102400240201541ff01710d00201020137c22082010542206200d20127c2006ad7c2207200d542007200d511b0d04200821102007210d200f211f200c211c0c010b200f20137c221f200f542206200c20127c2006ad7c221c200c54201c200c511b0d030b024020140d00201541ff01714102460d00427f200a20044188046a2903007c201620044180046a2903007c22082016542206ad7c220720062007200a542007200a511b22061b210a427f200820061b2116200441f8036a290300210720042903f0032108024020154101710d00427f200d20077c201020087c22082010542206ad7c220720062007200d542007200d511b22061b2107427f200820061b21080c020b427f201c20077c201f20087c2208201f542206ad7c220720062007201c542007201c511b22061b211c427f200820061b211f0b20102108200d21070b200441043a00f8010c040b20112116200e210a0b20102108200d2107200f211f200c211c0c010b20102108200d21070b200441f8016a200510e80420042d00f80122064104460d00200420042900f9013703c0052004200441f8016a41086a2800003600c70520042d00e0030d01200441e0036a41086a2802002203450d01200341306c450d0120042802e40310350c010b200441d0046a200441e0036a41f000109d081a0240024020042d00d00422064102470d002018ad4220862017ad8410070c010b200441c0056a200441d0046a1080052018ad4220862017ad8420043502c80542208620042802c0052203ad841002024020042802c405450d00200310350b20060d00200441d8046a2802002206450d00200641306c450d0020042802d40410350b200420042900f9013703c005200420044180026a2800003600c705410421060b024020042802cc01450d00201710350b200420042903c0053703d003200420042800c7053600d703024020064104470d00200442e4cab5fbb6ccdcb0e3003703e002200441e0026a2001200b200910ea0220044180056a200a370300200441d0046a41286a2016370300200441d0046a41206a2007370300200441d0046a41186a2008370300200441d0046a41106a201c37030020044188056a20042903e80237030020044190056a200441f0026a29030037030020044198056a200441e8026a41106a290300370300200441a0056a200441e8026a41186a290300370300200441a8056a200441e8026a41206a290300370300200441b0056a200441e8026a41286a2903003703002004201f3703d804200441003a00d004200441e0036a200210f50420042802e0032106200420042802e8033602c405200420063602c005200441d0046a200441c0056a10f604024020042802e403450d00200610350b200041043a00000c020b200020063a0000200020042903d003370001200041086a20042800d7033600000c010b20042802f8012106200041046a20042902fc01370200200020063602000b200441b0066a24000b810703047f017e027f23004180016b22022400200241186a2203200141186a290000370300200241106a2204200141106a290000370300200241086a2205200141086a2900003703002002200129000037030041d9e3cb00ad4280808080900184100122012900002106200241286a41086a200141086a290000370300200220063703282001103541e4a6cb00ad4280808080d00084100122012900002106200241386a41086a200141086a29000037030020022006370338200110350240024002400240412010332201450d0020012002290300370000200141186a2003290300370000200141106a2004290300370000200141086a200529030037000020022001ad42808080808004841003220329000037037820031035200241e4006a200141206a360200200220013602602002200241f8006a41086a36025c2002200241f8006a360258200241c8006a200241d8006a107b200110352002280250220741206a2203417f4c0d01200228024821080240024020030d0041002104410121010c010b200310332201450d01200321040b024002402004410f4d0d00200421050c010b200441017422054110200541104b1b22054100480d03024020040d002005103322010d010c050b20042005460d0020012004200510372201450d040b20012002290328370000200141086a200241286a41086a2903003700000240024020054170714110460d00200521040c010b200541017422044120200441204b1b22044100480d0320052004460d0020012005200410372201450d040b20012002290338370010200141186a200241386a41086a29030037000002400240200441606a2007490d00200421050c010b2007415f4b0d03200441017422052003200520034b1b22054100480d0320042005460d0020012004200510372201450d040b200141206a20082007109d081a0240200228024c450d00200810350b20022001200310c402200241e0006a2203200241096a290000370300200241e8006a2204200241116a290000370300200241f0006a2207200241196a290000370300200220022900013703580240024020022d000022084102470d00200041023a00000c010b200020083a000020002002290358370001200041096a2003290300370000200041116a2004290300370000200041196a20072903003700000b02402005450d00200110350b20024180016a24000f0b1045000b1044000b103e000b103c000b9f0303027f017e027f230041206b2202240041d9e3cb00ad4280808080900184100122032900002104200241086a200341086a29000037030020022004370300200310354184a4c600ad4280808080d00184100122032900002104200241106a41086a200341086a29000037030020022004370310200310350240412010332203450d0020032001290000370000200341186a2205200141186a290000370000200341106a2206200141106a290000370000200341086a200141086a290000370000412010332201450d0020012003290000370000200141186a2005290000370000200141106a2006290000370000200141086a2205200341086a2900003700002003103541c00010332203450d002003200229031037001020032002290300370000200341086a200241086a290300370000200341186a200241106a41086a290300370000200042c080808080083702042000200336020020032001290000370020200341286a2005290000370000200341306a200141106a290000370000200341386a200141186a29000037000020011035200241206a24000f0b1045000ba10202067f017e230041106b2202240002400240412010332203450d0020032000290000370000200341186a2204200041186a290000370000200341106a2205200041106a290000370000200341086a2206200041086a290000370000412010332207450d0120072003290000370000200741186a2004290000370000200741106a2005290000370000200741086a2006290000370000200310350240024020002d0020220341024d0d004280808080800421080c010b024002400240024020030e03000102000b410021030c020b410121030c010b410221030b200220033a000f2007412041c00010372207450d02200720033a00204280808080900421080b200129020020082007ad84100220071035200241106a24000f0b1045000b103c000b9f0303027f017e027f230041206b2202240041d9e3cb00ad4280808080900184100122032900002104200241086a200341086a290000370300200220043703002003103541b8a3c600ad4280808080900184100122032900002104200241106a41086a200341086a29000037030020022004370310200310350240412010332203450d0020032001290000370000200341186a2205200141186a290000370000200341106a2206200141106a290000370000200341086a200141086a290000370000412010332201450d0020012003290000370000200141186a2005290000370000200141106a2006290000370000200141086a2205200341086a2900003700002003103541c00010332203450d002003200229031037001020032002290300370000200341086a200241086a290300370000200341186a200241106a41086a290300370000200042c080808080083702042000200336020020032001290000370020200341286a2005290000370000200341306a200141106a290000370000200341386a200141186a29000037000020011035200241206a24000f0b1045000bb10503027f017e047f230041d0006b2202240041d9e3cb00ad4280808080900184100122032900002104200241086a41086a200341086a290000370300200220043703082003103541e4a6cb00ad4280808080d00084100122032900002104200241186a41086a200341086a29000037030020022004370318200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad42808080808004841003220129000037033820011035200241cc006a200341206a360200200220033602482002200241386a41086a3602442002200241386a360240200241286a200241c0006a107b200310352002280230220541206a2201417f4c0d01200228022821060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a2000200136020820002008360204200020033602000240200228022c450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000bfe2208047f027e047f077e037f087e157f017e23002206210720064180056b416071220624000240024020012002460d0020012002412010a008450d00200641a0016a2001108e0220064180046a20062802a001220820062802a801108f0220064190046a290300420020062903800442015122091b210a200629038804420020091b210b024020062802a401450d00200810350b200b200454200a200554200a2005511b450d012000412110e804200724000f0b2000412510e804200724000f0b20064190016a200110960520064180046a200628029001220c200628029801220d10c90220064190036a41026a220920062d0083043a0000200641c8036a41086a220820064180046a41e0006a290300370300200641c8036a41106a220e20064180046a41e8006a290300370300200620062f0081043b019003200620064180046a41d8006a2903003703c8030240024020062d008004220f4102470d00200641a0016a41c0006a220941003602004200210b200641a0016a41106a4200370300200641a0016a41186a4200370300200641a0016a41206a4200370300200641a0016a41286a4200370300200641a0016a41306a4200370300200641a0016a41386a4200370300200641083602a401200641a0016a41086a4200370300200641003a00a001200641a0016a41d0006a2903002110200641a0016a41c8006a2903002111200929030021124200210a42002113420021140c010b20064180046a41d0006a290300211020064180046a41c8006a290300211120064180046a41386a290300211420064180046a41286a290300210a20064180046a41206a290300210b20064180046a41186a290300211520064180046a41106a290300211620064180046a41306a290300211320064180046a410c6a280200211720064180046a41086a28020021182006280284042119200641a0016a41c0006a20064180046a41c0006a2903002212370300200641a0016a41386a2014370300200641a0016a41286a200a370300200641a0016a41206a200b370300200641a0016a41186a2015370300200641a0016a41106a2016370300200641a0016a41d0006a2010370300200641a0016a41c8006a2011370300200641a0016a41306a2013370300200641a0016a410c6a2017360200200641a0016a41086a2018360200200641a0016a41d8006a20062903c803370300200641a0016a41e0006a2008290300370300200641a0016a41e8006a200e2903003703002006200f3a00a001200620062f0190033b00a101200620193602a401200620092d00003a00a3010b2006200241106a2900003700b1022006200241176a2900003700b8022006200241086a2900003700a902200620022900003700a10220062903b802211a2006200641b8016a2209290300221b3703b80220062903b002211c200620062903b001221d3703b00220062903a802211e200620062903a801221f3703a802200641013a00a00220062903a0022116200620062903a00122153703a002200231001f2120200641d8016a4200370300200641d0016a2005370300200641c8016a20043703002009201a370300200620202003ad222142ff0183420886843703c0012006201c3703b0012006201e3703a801200620163703a001200641f8016a2209290300211a20094200370300200641f0016a4200370300200641e8016a4200370300200642003703e00120064188026a2208280200210f20064180026a220e290300211c20084100360200200e420037030002400240024002400240024002402015a741ff01714101460d002015422088a7210f201fa72108201f422088a70d02200641d8016a200641b0016a2016a741ff017141014622171b220e201b370308200e201d370300200e200b370310200e41186a200a3703002009200641a0016a41306a20171b22092012a736021020092014370308200920133703002008450d01200841306c450d01200f10350c010b20064180046a41176a200641a0026a410172220841176a29000037000020064180046a41106a200841106a29000037030020064180046a41086a200841086a2900003703002006200b3c009f04200620082900003703800402400240200b420888200a42388684220ba741ff0171450d00200641e0006a20134200200b42ff0183220b4200108408200641f0006a200a4200200b4200108408200641d0006a42004200200a4200108408427f200641f8006a290300220b200629036020062903507c7c221520062903682006290358844200522015200b547222081b210b427f200629037020081b21150c010b200641c0006a200a2013420a4200109808200641c8006a290300210b200629034021150b20064180046a2015200b200a2013109805200641d8016a200641b0016a20062d00a001410146220e1b2208201137031020082012370308200841186a2010370300200820143703002009200641d0016a200e1b2209201a3703002009201c3703082009200f3602100b02400240200341ff0171450d00200641206a20054200202142ff0183220a4200108408200641306a20044200200a4200108408200641106a4200420020044200108408427f200641386a290300220a200629032020062903107c7c220b2006290328200629031884420052200b200a547222031b2121427f200629033020031b211b0c010b200620042005420a4200109808200641086a29030021212006290300211b0b200641d0026a200210960520064180046a20062802d002222220062802d802222310c90220064190036a41026a220320062d0083043a000041082124200641c8036a41086a200641e0046a290300370300200641c8036a41106a2209200641e8046a290300370300200620062f0081043b0190032006200641d8046a2903003703c803200641d0046a290300211a200641c8046a290300211f0240024020062d00800422254102470d004200211041002126410021274200211c420021114200211e4200211d4200211242002120410021250c010b200641c0046a2903002120200641b8046a2903002112200641a8046a290300211e200641a0046a290300211120064198046a290300211c20064180046a41106a2903002110200641b0046a290300211d2006418c046a280200212720064180046a41086a28020021262006280284042124200641fc026a41026a20032d00003a0000200641e0026a41086a200641c8036a41086a290300370300200641e0026a41106a2009290300370300200620062f0190033b01fc02200620062903c8033703e0020b20254101460d01427f201e20057c201120047c220b2011542203ad7c220a2003200a201e54200a201e511b22031b211e427f200b20031b2111427f201c20217c2010201b7c220b2010542203ad7c220a2003200a201c54200a201c511b22031b211c427f200b20031b2110202741306c2203450d02202420036a2119200641b8046a210920064180046a410172222841036a2129202421030340200341306a21080240200341086a2d00004101710d00200341096a2d0000212a20064180036a200328020010f50420064180046a2006280280032203200628028803222b10b302200641c8036a41086a222c200941086a222d290000370300200641c8036a41106a222e200941106a222f290000370300200641c8036a41186a2230200941186a2231290000370300200641c8036a41206a2232200941206a2233290000370300200641c8036a41286a2234200941286a2235290000370300200620282800003602f803200620292800003600fb03200620092900003703c80320064180046a41306a210e20064180046a41206a210f20064180046a41106a2117024020062d00800422184102472236450d00200e290300210a200f29030021152017290300211320062903a804210b2006290398042114200629038804211620064190036a41086a202c29030037030020064190036a41106a202e29030037030020064190036a41186a203029030037030020064190036a41206a203229030037030020064190036a41286a2034290300370300200620062800fb033600c303200620062802f8033602c003200620062903c8033703900320180d00427f200a20057c200b20047c2237200b54222cad7c220b202c200b200a54200b200a511b222c1b210a427f2037202c1b210b0240202a4101710d00427f201520217c2014201b7c2237201454222cad7c2214202c201420155420142015511b222c1b2115427f2037202c1b21140c010b427f201320217c2016201b7c2237201654222cad7c2216202c201620135420162013511b222c1b2113427f2037202c1b21160b202820062802c0033600002009200629039003370300200e200a370300200f201537030020172013370300202920062800c303360000202d20064190036a41086a290300370300202f20064190036a41106a290300370300203120064190036a41186a290300370300203320064190036a41206a290300370300203520064190036a41286a2903003703002006200b3703a80420062014370398042006201637038804200620183a0080040240024020360d00202bad4220862003ad8410070c010b2006202b3602cc03200620033602c80320064180046a200641c8036a1099050b200628028403450d00200310350b2008210320192008470d000c030b0b20064190026a412310e80402402008450d00200841306c450d00200f10350b20062d00900222034104460d0220062006290091023703c803200620064190026a41086a2800003600cf0320062d00a0010d03200641a0016a41086a2802002209450d03200941306c450d0320062802a40110350c030b427f201a20057c201f20047c220b201f542203ad7c220a2003200a201a54200a201a511b22031b211a427f200b20031b211f427f202020217c2012201b7c220b2012542203ad7c220a2003200a202054200a2020511b22031b2120427f200b20031b21120b200641d0046a201a370300200641c8046a201f370300200641c0046a2020370300200641b8046a2012370300200641a8046a201e370300200641a0046a201137030020064198046a201c37030020064180046a41106a2010370300200641b0046a201d3703002006418c046a202736020020064180046a41086a2026360200200641d8046a20062903e002370300200641e0046a200641e0026a41086a290300370300200641e8046a200641e0026a41106a290300370300200620062f01fc023b00810420062024360284042006200641fc026a41026a2d00003a008304200620253a0080040240024020254102470d002023ad4220862022ad8410070c010b200641c8036a20064180046a1080052023ad4220862022ad8420063502d00342208620062802c8032203ad841002024020062802cc03450d00200310350b20250d002026450d00202641306c450d00202410350b024020062802d402450d00202210350b200642e4cab5fbb6ccdcb0e3003703c802200641c8026a20012004200510ea02200641043a0090020b20064180046a200641a0016a41f000109d081a0240024020062d00800422034102470d00200dad422086200cad8410070c010b200641c8036a20064180046a108005200dad422086200cad8420063502d00342208620062802c8032209ad841002024020062802cc03450d00200910350b20030d0020064188046a2802002203450d00200341306c450d0020062802840410350b20062006290091023703c803200620064198026a2800003600cf03410421030b0240200628029401450d00200c10350b200620062903c80337038001200620062800cf0336008701024020034104470d0020064180046a41086a41083a000020064189046a200129000037000020064191046a200141086a29000037000020064199046a200141106a290000370000200641a1046a200141186a290000370000200641a9046a2002290000370000200641b1046a200241086a290000370000200641b9046a200241106a290000370000200641c1046a200241186a290000370000200641063a00800441b0b4cc00410020064180046a10d401200041043a0000200724000f0b200020033a00002000200629038001370001200041086a200628008701360000200724000bc90e0b057f017e017f057e027f057e017f027e017f037e017f230022022103200241e0046b41607122022400200241e0006a2001109605200241d0036a200228026022042002280268220510c90220022d00d0032106200241f0016a200241d0036a41017241ef00109d081a0240024020064102470d004200210720024180016a420037030020024188016a420037030020024190016a420037030020024198016a4200370300200241a0016a4200370300200241a8016a420037030041002108200241b0016a410036020020024108360274200241f0006a41086a4200370300200241003a007042002109410021064200210a4200210b4200210c0c010b200220063a0070200241f0006a410172200241f0016a41ef00109d081a20024190016a290300220d420888a72106200241d0016a2903002109200241a0016a290300210b20024198016a290300210a200241a8016a290300210c200241d8016a280200210e200da72108420021070b200241a8016a4200370300200241f0006a41306a420037030020024198016a420037030020024188016a220f290300210d200f42003703002002410836028403200241003a008003200241003602e00220022903800121102002420037038001200229037821112002420037037820024200370390012002200d370398032002201037039003200220113703880320022903f80221122002200241c8016a220f29030022133703f80220022903f00221142002200241c0016a221529030022163703f00220022903e80221172002200241b8016a221829030022193703e802200229038003210d200220022903702210370380032002200d37037020022903e002211a200220022903b001221b3703e002200f201237030020152014370300201820173703002002201a3703b001200da7210f0240024002402010a741ff017122154101460d00200241e0016a412210e804024020150d002011a72206450d00200641306c450d002010422088a710350b20022d00e00122064104460d01200220022900e1013703f0012002200241e8016a2800003600f701200f41ff01710d0241010d0241010d02200d422088a710350c020b200241c7036a200229009803370000200241c0036a200229009103370300200241b0036a41086a20022900890337030020022002290081033703b003200220083a00cf0302400240200641ff0171450d00200241306a200b42002006ad42ff0183220d4200108408200241c0006a200a4200200d4200108408200241206a42004200200a4200108408427f200241c8006a290300220d200229033020022903207c7c221120022903382002290328844200522011200d547222151b210d427f200229034020151b21110c010b200241106a200a200b420a4200109808200241186a290300210d200229031021110b200241b0036a2011200d200a200b109805200241d0036a41186a4200370300200241d0036a41106a22084200370300200241d0036a41086a22154200370300200242003703d00341d1c4c700ad4280808080e0008410012218290000210d2015201841086a2900003703002002200d3703d0032018103541e7c4c700ad4280808080e0008410012218290000210d200241d0046a41086a221c201841086a2900003703002002200d3703d00420181035200820022903d004220d370300200241f0016a41086a2015290300370300200241f0016a41106a200d370300200241f0016a41186a201c290300370300200220022903d0033703f001200241086a200241f0016a412010c001200228020c211520022802082118200241a8016a200241f0006a41106a200f41ff017141014622081b220f41186a2016370300200f2019370310200f201b370308200f200c370300200241c8016a200241a0016a20081b220f2007201384220d200a200d200a562009200b562009200b511b22081b370300200f2009200b20081b370308200f200e20064118744118754102744184e4cb006a2802004180de346c2015410020181b6a2206200e20064b1b360210200241043a00e0010b200241d0036a200241f0006a41f000109d081a0240024020022d00d00322064102470d002005ad4220862004ad8410070c010b200241f0016a200241d0036a1080052005ad4220862004ad8420023502f80142208620022802f001220fad841002024020022802f401450d00200f10350b20060d00200241d8036a2802002206450d00200641306c450d0020022802d40310350b200220022900e1013703f0012002200241e8016a2800003600f701410421060b02402002280264450d00200410350b200220022903f001370350200220022800f7013600570240024020064104470d00200241d0036a41086a41093a0000200241d0036a41096a2001290000370000200241e1036a200141086a290000370000200241e9036a200141106a290000370000200241f1036a200141186a290000370000200241063a00d00341b0b4cc004100200241d0036a10d4010c010b20002002290350370001200041086a20022800573600000b200020063a0000200324000bb50403047f017e017f230041c0006b22022400200241186a2203200041186a290000370300200241106a2204200041106a290000370300200241086a2205200041086a2900003703002002200029000037030041d9e3cb00ad4280808080900184100122002900002106200241206a41086a200041086a290000370300200220063703202000103541888dc500ad4280808080900184100122002900002106200241306a41086a200041086a29000037030020022006370330200010350240412010332200450d0020002002290300370000200041186a2003290300370000200041106a2004290300370000200041086a2005290300370000412010332203450d0020032000290000370000200341186a2204200041186a290000370000200341106a2205200041106a290000370000200341086a2207200041086a2900003700002000103541c00010332200450d002000200229033037001020002002290320370000200041086a200241206a41086a290300370000200041186a200241306a41086a29030037000020002003290000370020200041286a2007290000370000200041306a2005290000370000200041386a20042900003700002003103520024100360208200242013703002001200210ef04200228020421032000ad4280808080800884200235020842208620022802002204ad84100202402003450d00200410350b20001035024020012d0000450d00200141286a280200450d00200141246a28020010350b200241c0006a24000f0b1045000bb10503027f017e047f230041d0006b2202240041d9e3cb00ad4280808080900184100122032900002104200241086a41086a200341086a290000370300200220043703082003103541a4a1c600ad4280808080800184100122032900002104200241186a41086a200341086a29000037030020022004370318200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad42808080808004841003220129000037033820011035200241cc006a200341206a360200200220033602482002200241386a41086a3602442002200241386a360240200241286a200241c0006a107b200310352002280230220541206a2201417f4c0d01200228022821060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a2000200136020820002008360204200020033602000240200228022c450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000bca1c08077f067e0a7f017e017f057e017f067e23004180046b2204240020044198026a200210f504200441c8026a200428029802220520042802a00210b302200441b8036a41086a220620044188036a290300370300200441b8036a41106a220720044190036a290300370300200441b8036a41186a220820044198036a290300370300200441b8036a41206a2209200441a0036a290300370300200441b8036a41286a220a200441a8036a290300370300200420044180036a2903003703b803200441f8026a290300210b200441c8026a41286a290300210c200441c8026a41206a290300210d200441c8026a41186a290300210e200441c8026a41106a290300210f200441c8026a41086a290300211020042802cc02211120042d00c9022112024020042d00c80222134102460d00200441e8006a41286a200a290300370300200441e8006a41206a2009290300370300200441e8006a41186a2008290300370300200441e8006a41106a2007290300370300200441e8006a41086a2006290300370300200420042903b8033703680b0240200428029c02450d00200510350b20044198016a41286a2205200441e8006a41286a29030037030020044198016a41206a2206200441e8006a41206a29030037030020044198016a41186a2207200441e8006a41186a29030037030020044198016a41106a2214200441e8006a41106a29030037030020044198016a41086a2215200441e8006a41086a2903003703002004200429036837039801200441c8016a2001109605200441c8026a20042802c801221620042802d00110c90220044198026a41026a220120042d00cb023a0000200441b8036a41086a20044194036a290200370300200441b8036a41106a22172004419c036a290200370300200441b8036a41186a2218200441a4036a290200370300200441b8036a41206a2219200441ac036a290200370300200441b8036a41286a221a200441b4036a280200360200200420042f00c9023b01980220042004418c036a2902003703b8030240024020042d00c80222094102470d004200211b4100210a4100211c4200211d4200211e4200211f42002120420021214100212241082108410021090c010b20044180036a2903002121200441f8026a2903002120200441c8026a41286a290300211f200441c8026a41206a290300211e200441c8026a41186a290300211d200441c8026a41106a290300211b20044188036a2802002122200441d4026a280200211c200441c8026a41086a280200210a20042802cc02210820044184026a41026a20012d00003a0000200441d8016a41086a200441b8036a41086a290300370300200441d8016a41106a2017290300370300200441d8016a41186a2018290300370300200441d8016a41206a2019290300370300200441d8016a41286a201a280200360200200420042f0198023b018402200420042903b8033703d8010b20044198026a41286a200529030037030020044198026a41206a200629030037030020044198026a41186a200729030037030020044198026a41106a201429030037030020044198026a41086a2015290300370300200420042903980137039802024002400240024020090d00410021010240024002400240024002400240024002400240201c41014b0d00201c0e020201020b201c2105034020012005410176220620016a22072008200741306c6a28020020024b1b2101200520066b220541014b0d000b0b2008200141306c6a2802002002470d00024002402013410371417f6a220541014b0d0020050e020109010b200441b8036a41286a20044198026a41286a290300370300200441b8036a41206a20044198026a41206a290300370300200441b8036a41186a20044198026a41186a290300370300200441b8036a41106a20044198026a41106a290300370300200441b8036a41086a20044198026a41086a29030037030020042004290398023703b803411d2106024020030d00201c20014d0d032008200141306c6a220541186a2903002123200541106a2903002124024020052d000822074101470d00412021062004200541206a2903002225200541286a2903002226420a4200109808200441106a20242023420a4200109808200c20247d2227200c56200b20237d200c202454ad7d2224200b562024200b511b0d01202720257d2228202756202420267d2027202554ad7d220c202456200c2024511b0d0120102004290310220b7d2224201056200f200441106a41086a2903007d2010200b54ad7d220b200f56200b200f511b0d01200e2004290300220f7d2210200e56200d200441086a2903007d200e200f54ad7d220f200d56200f200d511b0d010c090b200541096a2d00002114024002402005410a6a2d0000220541ff0171450d00200441c0006a202342002005ad42ff018322274200108408200441d0006a2024420020274200108408200441306a4200420020244200108408427f200441d8006a2903002227200429034020042903307c7c2228200429034820042903388442005220282027547222051b2125427f200429035020051b21270c010b200441206a20242023420a4200109808200441286a2903002125200429032021270b41202106200c20247d2228200c56200b20237d200c202454ad7d220c200b56200c200b511b0d000240201441ff01710d00200e20277d2226200e56200d20257d200e202754ad7d2223200d562023200d511b0d0120102124200f210b2026210e2023210d0c080b201020277d2224201056200f20257d2010202754ad7d220b200f56200b200f511b450d070b20044188026a200610e8040c050b201c20014d0d022008200141306c6a22052d00080d07201241ff0171410047200541096a2d00004573450d07200541186a290300210c200541106a290300210f2008200141306c6a410a6a2c00002107200441c8026a41186a4200370300200441c8026a41106a22024200370300200441c8026a41086a22054200370300200442003703c80241d1c4c700ad4280808080e0008410012206290000210b2005200641086a2900003703002004200b3703c8022006103541e7c4c700ad4280808080e0008410012206290000210b200441e8036a41086a2214200641086a2900003703002004200b3703e80320061035200220042903e803220b370300200441b8036a41086a2005290300370300200441b8036a41106a200b370300200441b8036a41186a2014290300370300200420042903c8023703b803200441e0006a200441b8036a412010c0012004280264410020042802601b20074102744184e4cb006a2802004180de346c20116a22054f0d0720030d032021200c2020200f562021200c562021200c511b22061b21212020200f20061b212020222005202220054b1b21220c070b20044188026a411c10e8040c030b2001201c4194c0c6001042000b2001201c41a4c0c6001042000b20044188026a411d10e8040b20042d00880222014104460d0420042004290089023703b803200420044190026a2800003600bf03200a450d05200a41306c450d05200810350c050b024020070d00201441ff01714102460d004200200c201f7d2028201e54ad7d220f2028201e7d2210202856200f200c56200f200c511b22051b210c4200201020051b2128024020144101710d004200200d201d7d200e201b54ad7d220f200e201b7d2210200e56200f200d56200f200d511b22051b210f4200201020051b21100c020b4200200b201d7d2024201b54ad7d220f2024201b7d2210202456200f200b56200f200b511b22051b210b4200201020051b21240b200e2110200d210f0b200441f8026a200c370300200441c8026a41286a2028370300200441c8026a41206a200f370300200441c8026a41186a2010370300200441c8026a41106a200b37030020044180036a20042903b80337030020044188036a200441c0036a29030037030020044190036a200441b8036a41106a29030037030020044198036a200441b8036a41186a290300370300200441a0036a200441b8036a41206a290300370300200441a8036a200441b8036a41286a290300370300200420243703d002200441003a00c802200441e8036a200210f50420042802e8032105200420042802f0033602fc03200420053602f803200441c8026a200441f8036a10f60420042802ec03450d00200510350b201c20014d0d032008200141306c6a2205200541306a201c2001417f736a41306c109e081a201c417f6a211c0b200441043a0088020b20044180036a2021370300200441f8026a2020370300200441c8026a41286a201f370300200441c8026a41206a201e370300200441c8026a41186a201d370300200441c8026a41106a201b37030020044188036a2022360200200441d4026a201c360200200441c8026a41086a200a3602002004418c036a20042903d80137020020044194036a200441d8016a41086a2903003702002004419c036a200441d8016a41106a290300370200200441a4036a200441d8016a41186a290300370200200441ac036a200441d8016a41206a290300370200200441b4036a200441d8016a41286a280200360200200420042f0184023b00c902200420083602cc02200420044184026a41026a2d00003a00cb02200420093a00c8020240024020094102470d0020043502d00142208620042802c8012216ad8410070c010b20043502d001212120042802c8012116200441b8036a200441c8026a10800520214220862016ad8420043502c00342208620042802b8032201ad84100220042802bc03450d00200110350b0240200a450d0020090d00200a41306c450d00200810350b20042004290089023703b803200420044190026a2800003600bf03410421010b024020042802cc01450d00201610350b200420042903b8033703c802200420042800bf033600cf02024020014104460d00200020042903c802370001200041086a20042800cf023600000b200020013a000020044180046a24000f0b2001201c104e000bdb0e08057f027e017f017e027f087e157f067e230041a0026b2205240020052000109605200541306a200528020022062005280208220710c902200541b0016a41026a220020052d00333a000041082108200541e8016a41086a20054190016a290300370300200541e8016a41106a220920054198016a290300370300200520052f00313b01b001200520054188016a2903003703e80120054180016a290300210a200541f8006a290300210b0240024020052d0030220c4102470d004200210d4100210e4100210f4200211042002111420021124200211342002114420021154100210c0c010b200541f0006a2903002115200541e8006a2903002114200541d8006a2903002112200541d0006a2903002111200541c8006a2903002110200541306a41106a290300210d200541e0006a29030021132005413c6a280200210f200541306a41086a280200210e200528023421082005412c6a41026a20002d00003a0000200541106a41086a200541e8016a41086a290300370300200541106a41106a2009290300370300200520052f01b0013b012c200520052903e8013703100b02400240200c4101460d004200201220047d2011200354ad7d2216201120037d2217201156201620125620162012511b22001b21124200201720001b21114200201020027d200d200154ad7d2216200d20017d2217200d56201620105620162010511b22001b21104200201720001b210d200f41306c2200450d01200820006a2118200541e8006a2109200541306a410172221941036a211a200821000340200041306a211b0240200041086a2d00004101710d00200041096a2d0000211c200541a0016a200028020010f504200541306a20052802a001220020052802a801221d10b302200541e8016a41086a221e200941086a221f290000370300200541e8016a41106a2220200941106a2221290000370300200541e8016a41186a2222200941186a2223290000370300200541e8016a41206a2224200941206a2225290000370300200541e8016a41286a2226200941286a222729000037030020052019280000360298022005201a28000036009b02200520092900003703e801200541306a41306a2128200541306a41206a2129200541306a41106a212a024020052d0030222b410247222c450d00202829030021172029290300212d202a290300212e200529035821162005290348212f20052903382130200541b0016a41086a201e290300370300200541b0016a41106a2020290300370300200541b0016a41186a2022290300370300200541b0016a41206a2024290300370300200541b0016a41286a20262903003703002005200528009b023600e30120052005280298023602e001200520052903e8013703b001202b0d004200201720047d2016200354ad7d2231201620037d2232201656203120175620312017511b221e1b211742002032201e1b21160240201c4101710d004200202d20027d202f200154ad7d2231202f20017d2232202f562031202d562031202d511b221e1b212d42002032201e1b212f0c010b4200202e20027d2030200154ad7d2231203020017d22322030562031202e562031202e511b221e1b212e42002032201e1b21300b201920052802e001360000200920052903b001370300202820173703002029202d370300202a202e370300201a20052800e301360000201f200541b0016a41086a2903003703002021200541b0016a41106a2903003703002023200541b0016a41186a2903003703002025200541b0016a41206a2903003703002027200541b0016a41286a290300370300200520163703582005202f370348200520303703382005202b3a003002400240202c0d00201dad4220862000ad8410070c010b2005201d3602ec01200520003602e801200541306a200541e8016a1099050b20052802a401450d00200010350b201b21002018201b470d000c020b0b4200200a20047d200b200354ad7d2216200b20037d2217200b562016200a562016200a511b22001b210a4200201720001b210b4200201520027d2014200154ad7d2216201420017d2217201456201620155620162015511b22001b21154200201720001b21140b20054180016a200a370300200541f8006a200b370300200541f0006a2015370300200541e8006a2014370300200541d8006a2012370300200541d0006a2011370300200541c8006a2010370300200541306a41106a200d370300200541e0006a20133703002005413c6a200f360200200541306a41086a200e36020020054188016a200529031037030020054190016a200541106a41086a29030037030020054198016a200541106a41106a290300370300200520052f012c3b00312005200836023420052005412c6a41026a2d00003a00332005200c3a003002400240200c4102470d002007ad4220862006ad8410070c010b200541e8016a200541306a1080052007ad4220862006ad8420053502f00142208620052802e8012200ad841002024020052802ec01450d00200010350b200c0d00200e450d00200e41306c450d00200810350b02402005280204450d00200610350b200541a0026a24000ba60203027f017e017f230041106b22022400200241003602082002420137030002400240024020002d00004101460d00410110332203450d02200341003a0000200220033602002002428180808010370204200041086a200210a406200235020842208621042002280204452103200228020021000c010b410110332203450d01200341013a000020024281808080103702042002200336020020002d0001210520034101410210372203450d01200320053a00012002428280808020370204200220033602002000280204210520034102410610372200450d01200020053600022002200036020020024286808080e000370204410021034280808080e00021040b200129020020042000ad841002024020030d00200010350b200241106a24000f0b103c000bd21f04067f027e027f017e230041f0006b220624000240024002402002410c6a280200200241106a28020010172207417f460d00410c103322080d010c020b109b05000b200820073602082008428180808010370200200641186a420037030020064280808080c000370310200642043703080240024002400240024002402008280200220741016a220941014d0d00200820093602002007417e460d002008200741026a3602000240200628021c22072006280218470d00200641146a20074101108601200628021c21070b200628021420074102746a20083602002006200628021c41016a36021c2008280208210a200641d0006a41a58ecc0041031050200641206a41a9bbca0041061050200641e4006a200641206a41086a22092802003602002006200629032037025c200641206a41106a220b200641d0006a41106a2903003703002009200641d0006a41086a29030037030020062006290350370320024020062802102207200628020c470d00200641086a20074101109101200628021021070b200628020820074105746a22074101360218200720062903203702002007411c6a200a360200200741106a200b290300370200200741086a20092903003702002006200628021041016a36021020082008280200417f6a2207360200024020070d002008280208101820082008280204417f6a220736020420070d00200810350b200641086a41a88ecc004103411110e604200641086a41c6dfcb00410f411210e604200641086a41d5dfcb004111411310e604200641086a41e6dfcb00410f411410e604200641086a41f5dfcb00410c411510e604200641086a4181e0cb004108411610e604200641086a4189e0cb00410f411710e604200641086a4198e0cb00410d411810e604200641086a41a5e0cb00410a411910e604200641086a41afe0cb00410a411a10e604200641086a41b9e0cb00410b411b10e604200641086a41c4e0cb00410d411c10e604200641086a41d1e0cb00410c411d10e604200641086a41dde0cb00410b411e10e604200641086a41e8e0cb004115411f10e604200641086a41fde0cb00410a412010e604200641086a4187e1cb004107412110e604200641086a418ee1cb004113412210e604200641086a41a1e1cb004115412310e604200641086a41b6e1cb004111412410e604200641086a41c7e1cb00410e412510e604200641086a41d5e1cb004110412610e604200641086a41e5e1cb004110412710e604200641086a41f5e1cb004111412810e604200641086a4186e2cb004111412910e604200641086a4197e2cb004116412a10e604200641086a41ade2cb004112412b10e604200641086a41bfe2cb00410b412c10e604200641086a41cae2cb004110412d10e604200641086a41dae2cb004117412e10e604200641086a41f1e2cb004111412f10e604200641086a4182e3cb004113413010e604200641086a4195e3cb004113413110e604200641086a41a8e3cb004113413210e604200641206a410c6a200441086a280200360200200620033602202006410336023c20062005360238200620083602342006200429020037022420062001280200360230200628021022084105744104722204417f4c0d01200241146a350200210c2002411c6a350200210d20062802082107200410332209450d022006410036025820062004360254200620093602502008200641d0006a10770240024020080d002006280258210820062802542103200628025021090c010b200720084105746a210a034020072802002103200741086a2802002208200641d0006a10770240024020062802542201200628025822046b2008490d00200628025021090c010b200420086a22092004490d06200141017422052009200520094b1b22054100480d060240024020010d00024020050d00410121090c020b200510332209450d0b0c010b2006280250210920012005460d0020092001200510372209450d0a0b20062005360254200620093602500b200920046a20032008109d081a2006200420086a3602582007410c6a2802002105200741146a2802002209200641d0006a10770240024020062802542203200628025822016b2009490d0020062802502104200321080c010b200120096a22082001490d06200341017422042008200420084b1b22084100480d060240024020030d00024020080d00410121040c020b200810332204450d0b0c010b2006280250210420032008460d0020042003200810372204450d0a0b20062008360254200620043602500b200420016a20052009109d081a2006200120096a220936025802400240200741186a2802004101460d000240024020082009460d00200921080c010b200841016a22092008490d08200841017422012009200120094b1b22094100480d080240024020080d0041002108024020090d00410121040c020b200910332204450d0d0c010b20082009460d0020042008200910372204450d0c0b20062009360254200620043602500b200420086a41013a00002006200841016a220836025820062007411c6a2802002201360268200641e8006a21050c010b0240024020082009460d00200921080c010b200841016a22092008490d07200841017422012009200120094b1b22094100480d070240024020080d0041002108024020090d00410121040c020b200910332204450d0c0c010b20082009460d0020042008200910372204450d0b0b20062009360254200620043602500b200420086a41023a00002006200841016a220836025820062007411c6a2802002201360268200641e8006a21050b024002402006280254220420086b4104490d0020062802502109200421030c010b200841046a22092008490d06200441017422012009200120094b1b22034100480d060240024020040d00024020030d00410121090c020b200310332209450d0b0c010b2006280250210920042003460d0020092004200310372209450d0a0b2006200336025420062009360250200528020021010b200920086a20013600002006200841046a2208360258200741206a2207200a470d000b0b02400240024002400240024002404133200d422086200c842008ad4220862009ad84200641206a1019220b41036a220841024b0d004100210120080e03010002010b200628021c220741ffffffff03712007470d0720074102742204417f4c0d07200628021421080240024020040d00410421010c010b200410332201450d090b200641003602582006200136025020062004410276360254200641d0006a410020071086012006280250210e2006280258210102402007450d0020074102742105200e20014102746a210703402008280200220428020041016a220a41014d0d08200841046a21082004200a36020020072004360200200141016a2101200741046a21072005417c6a22050d000b0b2006280254210f02402003450d00200910350b2002350204210c2002350200210d2006410036025820064208370350200641d0006a41004100109a01200628025822084104744104722207417f4c0d072006280254210920062802502104200710332203450d082006410036025820062007360254200620033602502008200641d0006a107702402008450d00200841047421072004210803402008200641d0006a10e504200841106a2108200741706a22070d000b0b2006350258211020062802542103200628025021070240200941ffffffff0071450d00200410350b410a10392208450d08200b200c422086200d8420104220862007ad842008410a200641206a101a41036a220441034b0d024101210520040e0404020203040b410221010b410121054100210a02402003450d00200910350b0c090b41cfa2cc00412841c086cc00103f000b2006410936026c410121052006200841016a36026820082d0000220441014b0d01410421090240024020040e020100010b200641d0006a200641e8006a10e404200628025022094104460d022006280254210a0b410021050b200810352003450d05200710350c050b20081035024020030d000c050b200710350c040b00000b1044000b1045000b103e000b200b101b02402001450d0020014102742107200e21080340200828020022042004280200417f6a3602000240200828020022042802000d0020042802081018200828020022042004280204417f6a360204200828020022042802040d00200410350b200841046a21082007417c6a22070d000b0b0240200f41ffffffff0371450d00200e10350b410221010b200641206a410c6a290200210c200641206a41086a280200210720062802342108200628022421040240024002400240024002400240024002400240200628023c0e0403020001030b20004101360204200041086a4200370200200041106a41003a00000c030b2005450d04200041003a0004200ca72109024020010d00200041b5c1c60036020820004101360200200041186a2009360200200041146a2007360200200041106a20043602002000410c6a41103602000c060b200041c5c1c60036020820004101360200200041186a2009360200200041146a2007360200200041106a20043602002000410c6a41213602000c050b200041003a000420004101360200200041186a200c3e0200200041146a2007360200200041106a20043602002000410c6a4128360200200041086a41fcc0c6003602000c020b200041106a41003a00002000410c6a200641c8006a2802003602002000200641c0006a2903003702040b200041003602002007450d00200410350b20082008280200417f6a220736020020070d032008280208101820082008280204417f6a220736020420070d030c020b0240200941044b0d000240024020090e050102020200010b2000200436020420004100360200200041106a41003a00002000410c6a4100360200200041086a20073602000c020b2000200436020420004100360200200041106a200a3a00002000410c6a200c3e0200200041086a20073602000c010b200041003a000420004101360200200041186a200c3e0200200041146a2007360200200041106a20043602002000410c6a4111360200200041086a41a4c1c6003602000b20082008280200417f6a220736020020070d012008280208101820082008280204417f6a220736020420070d010b200810350b024020062802102207450d00200628020821082007410574210703400240200841046a280200450d00200828020010350b0240200841106a280200450d002008410c6a28020010350b200841206a2108200741606a22070d000b0b0240200628020c41ffffff3f71450d00200628020810350b0240200628021c2207450d0020062802142108200741027421070340200828020022042004280200417f6a3602000240200828020022042802000d0020042802081018200828020022042004280204417f6a360204200828020022042802040d00200410350b200841046a21082007417c6a22070d000b0b0240200628021841ffffffff0371450d00200628021410350b200641f0006a24000f0b103c000b120041b1c6c60041fc0041c086cc00103f000b7201027f230041106b22042400024002402003450d002002280200450d010b41e6c1c60041f40341dcc5c6001064000b2001280210210320012802182105200228020421022004410036020020042002360204200041054104200520032001411c6a200410be051b360200200441106a24000bcb0501067f230041f0006b22042400024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d02410521030240200241246a280200220520012802002802182802402802b4014b0d0020022802042106200241146a2802002107200441186a4200370300200441106a4200370300200441086a420037030020044200370300200128021821022001280210210820044281808080800437034041052103200220082001411c6a2209200441c0006a10be050d00024002402001280214280208200620044120101c41026a220241024b0d0020020e03020001020b41cfa2cc00412841f8a2cc00103f000b20012802102102200128021821082004410136024020042005360244200820022009200441c0006a10be050d002005417f4c0d040240024020050d0041002108410121020c010b200510392202450d06200521080b0240024002402001280214280208200720022005101c41026a220641024b0d0020060e03010002010b41cfa2cc00412841f8a2cc00103f000b2008450d01200210350c010b20012802002101200441206a41186a2206200441186a290300370300200441206a41106a2209200441106a290300370300200441206a41086a2207200441086a290300370300200420042903003703200240200128021822012802402802b40120054f0d002008450d01200210350c010b200441c0006a41186a2006290300370300200441c0006a41106a2009290300370300200441c0006a41086a20072903003703002004200429032037034020042005ad4220862008ad8437026420042002360260200141186a200141d0006a200441c0006a200441e0006a10af04410421030b20002003360200200441f0006a24000f0b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b1044000b1045000b860302037f047e230041f0006b2204240002402003450d0020022802000d0020022802042105200441186a4200370300200441106a4200370300200441086a4200370300200442003703002001280218210320012802102106200442818080808004370340410521020240200320062001411c6a200441c0006a10be050d00024002402001280214280208200520044120101c41026a220341024b0d0020030e03020001020b41cfa2cc00412841f8a2cc00103f000b20012802002101200441206a41186a200441186a2903002207370300200441206a41106a200441106a2903002208370300200441206a41086a200441086a290300220937030020042004290300220a37032020012802182101200441c0006a41186a2007370300200441c0006a41106a2008370300200441c0006a41086a20093703002004200a37034020044100360260200141186a200141d0006a200441c0006a200441e0006a10af04410421020b20002002360200200441f0006a24000f0b41e6c1c60041f40341dcc5c6001064000be60201027f230041306b2204240002402003450d0020022802000d0020022802042105200441186a4200370300200441106a4200370300200441086a420037030020044200370300200128021821022001280210210320044281808080800437032002400240200220032001411c6a200441206a10be050d00024002402001280214280208200520044120101c41026a220241024b0d0020020e03020001020b41cfa2cc00412841f8a2cc00103f000b200441206a2001280200280218220241186a200241d0006a2002410c6a4100200228020c1b2004109104024002402004280220450d00200141046a21020240200141086a280200450d00200228020010350b20022004290320370200200241086a200441206a41086a280200360200410021010c010b2001410c6a4100360200410121010b20004100360200200020013602040c010b200041053602000b200441306a24000f0b41e6c1c60041f40341dcc5c6001064000bdc0802087f027e23004190016b22042400024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d0220034103460d0320022802300d0320022802042105200241146a2802002106200241246a2802002107200241346a28020021082001280210210220012802182103200441013602482004200636024c02400240200320022001411c6a2209200441c8006a10be050d002006417f4c0d060240024002400240024002400240024020060d004100210a4101210b02402001280214280208200541014100101c41026a220241024b0d00200141146a210520020e03090002090b41cfa2cc00412841f8a2cc00103f000b20061039220b450d04024020012802142802082005200b2006101c41026a220241024b0d00200141146a21052006210a20020e03020001020b41cfa2cc00412841f8a2cc00103f000b41002102200441003a00680240034020062002460d01200441c8006a20026a200b20026a2d00003a00002004200241016a22033a00682003210220034120470d000b200441f0006a41186a2202200441c8006a41186a290300370300200441f0006a41106a2203200441c8006a41106a290300370300200441f0006a41086a2206200441c8006a41086a290300370300200420042903483703700240200a450d00200b10350b200441086a41086a2006290300370300200441086a41106a2003290300370300200441086a41186a2002290300370300200420042903703703082001280210210220012802182103200441013602482004200836024c200320022009200441c8006a10be050d072008417f4c0d0d20080d032005280200280208200741014100101c41026a220241024b0d0220020e03070207070b0240200241ff0171450d00200441003a00680b200a450d060b200b10350c050b41cfa2cc00412841f8a2cc00103f000b200810392202450d0002402005280200280208200720022008101c41026a220341024b0d0020030e03030002030b41cfa2cc00412841f8a2cc00103f000b1045000b2008410f4d0d00200241086a290000210c2002290000210d200210352001280218210320012802002802182102200441f0006a41186a200441086a41186a290300370300200441f0006a41106a200441086a41106a290300370300200441f0006a41086a200441086a41086a29030037030020042004290308370370200441c8006a41186a200241e8006a290000370300200441c8006a41106a200241e0006a290000370300200441c8006a41086a200241d8006a29000037030020042002290050370348200441286a20034100200441c8006a200441f0006a200d200c200210bf0520042d0028210220004100360200200020024104473602040c020b200210350b200041053602000b20044190016a24000f0b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b1044000bfb0e04037f017e077f047e230041a0016b2204240002400240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802204101470d0220034103460d0320022802300d0320034104460d0420022802400d0420034105460d0520022802500d0520034106460d0620022802600d0620022802042105200241146a2802002106200241286a2903002107200241346a2802002108200241c4006a2802002109200241d4006a280200210a200241e4006a280200210b2001280210210220012802182103200441013602682004200636026c02400240200320022001411c6a220c200441e8006a10be050d002006417f4c0d090240024002400240024002400240024020060d004100210d4101210e02402001280214280208200541014100101c41026a220241024b0d00200141146a210520020e03090002090b41cfa2cc00412841f8a2cc00103f000b20061039220e450d04024020012802142802082005200e2006101c41026a220241024b0d00200141146a21052006210d20020e03020001020b41cfa2cc00412841f8a2cc00103f000b41002102200441003a0088010240034020062002460d01200441e8006a20026a200e20026a2d00003a00002004200241016a22033a0088012003210220034120470d000b200441c8006a41186a2202200441e8006a41186a290300370300200441c8006a41106a2203200441e8006a41106a290300370300200441c8006a41086a2206200441e8006a41086a290300370300200420042903683703480240200d450d00200e10350b200441086a41086a2006290300370300200441086a41106a2003290300370300200441086a41186a2002290300370300200420042903483703082001280210210220012802182103200441013602682004200936026c20032002200c200441e8006a10be050d072009417f4c0d1020090d032005280200280208200841014100101c41026a220241024b0d0220020e03070207070b0240200241ff0171450d00200441003a0088010b200d450d060b200e10350c050b41cfa2cc00412841f8a2cc00103f000b200910392202450d0002402005280200280208200820022009101c41026a220341024b0d0020030e03030002030b41cfa2cc00412841f8a2cc00103f000b1045000b2009410f4d0d00200241086a290000210f20022900002110200210352001280210210220012802182103200441013602682004200b36026c20032002200c200441e8006a10be050d0102400240200b2001410c6a220628020022034b0d00200b21020c010b02400240200141086a280200220220036b200b20036b2205490d002001280204210e200321020c010b200320056a220e2003490d0d20024101742209200e2009200e4b1b22094100480d0d0240024020020d00024020090d004101210e0c020b20091033220e0d010c100b2001280204210e20022009460d00200e200220091037220e450d0f0b2001200e360204200141086a20093602002001410c6a28020021020b200e20026a21090240024020054102490d0020094100200b2003417f7322036a2205109f081a200e200b20026a20036a6a2109200520026a21020c010b2005450d010b200941003a0000200241016a21020b20062002360200024002402001280214280208200a20012802042002101c41026a220241024b0d0020020e03030001030b41cfa2cc00412841f8a2cc00103f000b2001410c6a220228020021094100210520024100360200200141086a280200210220012802042103200142013702042001280218220629030822112112024002402007500d00418002210e2007211220112007540d010b2006201120127d3703082004201237033020042012370328200128020041186a280200210e200441e8006a41186a200441086a41186a290300370300200441e8006a41106a200441086a41106a290300370300200441e8006a41086a200441086a41086a29030037030020042004290308370368200420093602980120042002360294012004200336029001200441c8006a200e200441e8006a2010200f200441286a20044190016a10ef03410121090240024020042802484101470d00200441c8006a41186a280200210c200441dc006a2802002102200441c8006a41106a28020021034100210e0c010b200441c8006a41106a2d0000210e200441d4006a280200210c200441d0006a280200210241002109200428024c21030b2006200429033020062903087c370308200141086a280200210602402009450d00418002210e2006450d01200128020410350c010b02402006450d00200128020410350b200c21050b200120033602042001410c6a2005360200200141086a2002360200200041003602002000200e3602040c020b200210350b200041053602000b200441a0016a24000f0b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b1044000b103e000b103c000b8a1004037f017e077f047e230041b0016b2204240002400240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802204101470d0220034103460d0320022802300d0320034104460d0420022802400d0420034105460d0520022802500d0520034106460d0620022802600d0620022802042105200241146a2802002106200241286a2903002107200241346a2802002108200241c4006a2802002109200241d4006a280200210a200241e4006a280200210b2001280210210220012802182103200441013602782004200636027c02400240200320022001411c6a220c200441f8006a10be050d002006417f4c0d090240024002400240024002400240024020060d004100210d4101210e02402001280214280208200541014100101c41026a220241024b0d00200141146a210520020e03090002090b41cfa2cc00412841f8a2cc00103f000b20061039220e450d04024020012802142802082005200e2006101c41026a220241024b0d00200141146a21052006210d20020e03020001020b41cfa2cc00412841f8a2cc00103f000b41002102200441003a0098010240034020062002460d01200441f8006a20026a200e20026a2d00003a00002004200241016a22033a0098012003210220034120470d000b200441c8006a41186a2202200441f8006a41186a290300370300200441c8006a41106a2203200441f8006a41106a290300370300200441c8006a41086a2206200441f8006a41086a290300370300200420042903783703480240200d450d00200e10350b200441086a41086a2006290300370300200441086a41106a2003290300370300200441086a41186a2002290300370300200420042903483703082001280210210220012802182103200441013602782004200936027c20032002200c200441f8006a10be050d072009417f4c0d1020090d032005280200280208200841014100101c41026a220241024b0d0220020e03070207070b0240200241ff0171450d00200441003a0098010b200d450d060b200e10350c050b41cfa2cc00412841f8a2cc00103f000b200910392202450d0002402005280200280208200820022009101c41026a220341024b0d0020030e03030002030b41cfa2cc00412841f8a2cc00103f000b1045000b2009410f4d0d00200241086a290000210f20022900002110200210352001280210210220012802182103200441013602782004200b36027c20032002200c200441f8006a10be050d01200141046a210e02400240200b2001410c6a220628020022034b0d00200b21020c010b02400240200141086a280200220220036b200b20036b2209490d00200e2802002105200321020c010b200320096a22052003490d0d2002410174220c2005200c20054b1b220c4100480d0d0240024020020d000240200c0d00410121050c020b200c103322050d010c100b200e28020021052002200c460d0020052002200c10372205450d0f0b20012005360204200141086a200c3602002001410c6a28020021020b200520026a210c0240024020094102490d00200c4100200b2003417f7322036a2209109f081a2005200b20026a20036a6a210c200920026a21020c010b2009450d010b200c41003a0000200241016a21020b20062002360200024002402001280214280208200a20012802042002101c41026a220241024b0d0020020e03030001030b41cfa2cc00412841f8a2cc00103f000b2001410c6a2202280200210520024100360200200141086a28020021022001280204210320014201370204200128021822062903082211211202400240024002402007500d002007211220112007540d010b2006201120127d3703082004201237037020042012370368200128020041186a2802002109200420053602502004200236024c20042003360248200441f8006a20092010200f200441e8006a200441086a200441c8006a10c005410121050240024020042802784101470d00200441f8006a41186a28020021092004418c016a280200210220044188016a28020021030c010b200441c8006a41086a200441f8006a41186a290300370300200441c8006a41106a20044198016a2802003602002004200441f8006a41106a290300370348200441a8016a2d0000210c2004419c016a290200210720044184016a2802002109200441f8006a41086a280200210241002105200428027c21030b2006200429037020062903087c370308200441286a41086a2206200441c8006a41086a290300370300200441286a41106a2208200441c8006a41106a280200360200200420042903483703282005450d01200141086a280200450d00200e28020010350b200120033602042001410c6a4100360200200141086a200236020041800221020c010b2004418c016a200629030037020020044194016a200828020036020020042009360280012004200236027c2004200336027820042004290328370284010240200141086a280200450d00200e28020010350b200120073702042001410c6a4100360200200c41ff017122020d00200e200441f8006a412010780b20004100360200200020023602040c020b200210350b200041053602000b200441b0016a24000f0b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b1044000b103e000b103c000bf113020b7f047e230022042105200441e00c6b41607122042400024002402003450d0020022802000d00024020034101460d0020022802100d0020022802042106200241146a28020021072001280210210220012802182103200441013602e001200420073602e401200320022001411c6a200441e0016a10be050d0202402007417f4c0d00024002400240024002400240024020070d00410021084101210902402001280214280208200641014100101c41026a220241024b0d0020020e030b00020b0b41cfa2cc00412841f8a2cc00103f000b0240200710392209450d0002402001280214280208200620092007101c41026a220241024b0d002007210820020e03030002030b41cfa2cc00412841f8a2cc00103f000b1045000b41002102200441003a0080020240034020072002460d01200441e0016a20026a200920026a2d00003a00002004200241016a22033a0080022003210220034120470d000b200441800a6a41186a2202200441e0016a41186a290300370300200441800a6a41106a2203200441e0016a41106a290300370300200441800a6a41086a2207200441e0016a41086a290300370300200420042903e0013703800a02402008450d00200910350b200441206a41086a2007290300370300200441206a41106a2003290300370300200441206a41186a2002290300370300200420042903800a3703202001280218210a200441c0006a41186a2001280200280218220641e8006a290000370300200441c0006a41106a200641e0006a290000370300200441c0006a41086a200641d8006a29000037030020042006290050370340200628021841016a220b41004c0d052006200b3602182006411c6a220c2802002208450d03200641206a280200210d0340200841086a210320082f0106220e410574210241002107024003402002450d01200441c0006a2003412010a0082209450d05200241606a2102200741016a2107200341206a21032009417f4a0d000b2007417f6a210e0b200d450d04200d417f6a210d2008200e4102746a41880b6a28020021080c000b0b0240200241ff0171450d00200441003a0080020b2008450d080b200910350c070b2008200741e0006c6a220241c5036a310000200241e8026a290300220f200f5022031ba7450d004200200241f8026a29030020031b210f4200200241f0026a29030020031b21100c010b200441106a200641286a280200200441c0006a2006412c6a28020028021c110400200441186a290300210f2006280218210b200429031021100b2006200b417f6a360218024020062802082202450d00200241d0006a2203200441c0006a460d052003200441c0006a412010a008450d05034020022802082202450d01200441c0006a200241d0006a2203460d062003200441c0006a412010a0080d000c060b0b200441e0016a200a4102200441c0006a200441206a2010200f200610bf0520042d00e0014104470d04024020062802180d002006417f360218200441003a009c0120044100360298012004410036029001200441013a007d200441c0016a41186a200441c0006a41186a290300370300200441c0016a41106a200441c0006a41106a290300370300200441c0016a41086a200441c0006a41086a290300370300200420042903403703c001024002400240200628021c2209450d00200641206a280200210d0c010b200441800a6a410041e002109f081a200441e0016a410041a008109f081a41880b10332209450d014100210d200941003b010620094100360200200941086a200441800a6a41e002109d081a200941e8026a200441e0016a41a008109d081a200641206a41003602002006200936021c0b2004200c3602880a200420093602840a2004200d3602800a034020092f0106220b41057421084100210241002103024002400240034020082002460d010240200441c0016a200920026a41086a412010a00822070d0041002102200d21070c030b200241206a2102200341016a21032007417f4a0d000b2003417f6a210b0b200d0d014101210241002107200b21030b200441e0016a41106a2003360200200441ec016a200c360200200441e0016a41086a20093602002004200c3602880a200420093602840a2004200d3602800a200420073602e401200420023602e001024002402002450d00200441a0016a41186a200441c0016a41186a290300220f370300200441a0016a41106a200441c0016a41106a2903002210370300200441a0016a41086a200441c0016a41086a2903002211370300200420042903c00122123703a0012004419c0a6a2011370200200441800a6a41246a2010370200200441ac0a6a200f3702002004200641246a3602900a2004200336028c0a2004200c3602880a200420093602840a200420073602800a200420123702940a200441e0016a41186a4200370300200442003703e00120044198026a20042903980137030020044190026a20042903900137030020044188026a20042903880137030020044180026a200429038001370300200441b8026a2004290378370300200441b0026a2004290370370300200441a8026a2004290368370300200441a0026a2004290360370300200441800a6a200441e0016a1080031a4202210f0c010b2009200341e0006c6a22024190036a20042903880137030020024188036a200429038001370300200241c0036a2004290378370000200241b8036a2004290370370000200241b0036a2004290368370000200241a8036a200429036037000020024180036a4200370300200241e8026a2203290300210f20034200370300200241a0036a22032802002108200320042903980137030020024198036a2202290300211020022004290390013703002010a721092010422088a721030b0240200f4202510d000240024020090d0041002108200441f4016a4100360200200441003602e4010c010b0240024020030d00200921020c010b2003210220092107034020072802ec0321072002417f6a22020d000b200921020340200220022f01064102746a41ec036a28020021022003417f6a22030d000b200721090b200441fc016a20022f0106360200200441f8016a4100360200200441f4016a2002360200200441003602f001200442003703e801200420093602e401200441003602e0010b2004200836028002200441e0016a1081030b2006200628021841016a3602180240200128021c0d00200141246a280200450d00200141206a28020010350b2001410236021c200141206a20042902e001370200200141286a200441e8016a2802003602000c080b200d417f6a210d2009200b4102746a41880b6a28020021090c000b0b103c000b41a797cc004110200441e0016a41c8c1c30041c897cc001046000b41ac96cc004118200441e0016a41d8c1c30041d496cc001046000b1044000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b20004105360200200524000b940501077f230041106b2204240002400240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200241146a2802002102200128021021032001280218210620044103360200200420023602040240200620032001411c6a2207200410be050d0020012802102103200128021821062004410136020020042002360204200620032007200410be050d000240024020022001410c6a220728020022064b0d00200221030c010b02400240200141086a280200220320066b200220066b2208490d0020012802042109200621030c010b200620086a22092006490d052003410174220a2009200a20094b1b220a4100480d050240024020030d000240200a0d00410121090c020b200a103322090d010c080b200128020421092003200a460d0020092003200a10372209450d070b20012009360204200141086a200a3602002001410c6a28020021030b200920036a210a0240024020084102490d00200a410020022006417f7322066a2208109f081a2009200220036a20066a6a210a200820036a21030c010b2008450d010b200a41003a0000200341016a21030b20072003360200024002402001280214280208200520012802042003101c41026a220241024b0d0020020e03020001020b41cfa2cc00412841f8a2cc00103f000b2001410c6a2202280200210320024100360200200141086a280200210220012802042106200142013702040240200128021c0d00200141246a280200450d00200141206a28020010350b2001410036021c200141286a2003360200200141246a2002360200200141206a20063602000b20004105360200200441106a24000f0b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b103e000b103c000b24002001410c6a4100360200200141046a200128020041206a41201078200041043602000b28002001410c6a4100360200200141046a200128020028021841d0006a41201078200041043602000b5702017f017e230041206b220424002001410c6a41003602002004420110cf04200429030021052004200441086a29030037031820042005370310200141046a200441106a4110107820004104360200200441206a24000b4001017f230041106b220424002001410c6a410036020020042001280218290308370308200141046a200441086a4108107820004104360200200441106a24000ba403020b7f027e230041206b220424002001410c6a410036020002402001280200280218220528021841016a220641004c0d00200141046a2107200541d0006a210820052006360218024002402005411c6a2802002209450d00200541206a280200210a0340200941086a210b20092f0106220c41057421014100210d0240024003402001450d012008200b412010a008220e450d02200141606a2101200d41016a210d200b41206a210b200e417f4a0d000b200d417f6a210c0b200a450d02200a417f6a210a2009200c4102746a41880b6a28020021090c010b0b2009200d41e0006c6a220141c5036a310000200141e8026a290300220f200f50220b1ba7450d004200200141f8026a290300200b1b210f4200200141f0026a290300200b1b21100c010b2004200541286a28020020082005412c6a28020028021c110400200441086a290300210f20052802182106200429030021100b20052006417f6a3602182004200f370318200420103703102007200441106a4110107820004104360200200441206a24000f0b41ac96cc004118200441106a41d8c1c30041d496cc001046000b5202027f017e230041106b220424002001410c6a41003602002001280200220529030021062004200541086a29030037030820042006370300200141046a20044110107820004104360200200441106a24000bb60301057f230041206b2204240002400240024002402003450d0020022802000d0020034101460d0120022802100d01410521050240200241146a280200220320012802102206280284014b0d0020022802042107200128021821022004410136020020042003360204200220062001411c6a200410be050d002003417f4c0d0302400240024020030d00410021084101210602402001280214280208200741014100101c41026a220241024b0d0020020e03040002040b41cfa2cc00412841f8a2cc00103f000b200310392206450d0602402001280214280208200720062003101c41026a220241024b0d002003210820020e03020001020b41cfa2cc00412841f8a2cc00103f000b2001410c6a410036020020042006200310d503412010332202450d0520022004290300370000200241186a200441186a290300370000200241106a200441106a290300370000200241086a200441086a29030037000041042105200141046a200241201078200210352008450d010b200610350b20002005360200200441206a24000f0b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b1044000b1045000b4001017f230041106b220424002001410c6a410036020020042001280200290310370308200141046a200441086a4108107820004104360200200441106a24000b5a02027f017e230041106b220424002001410c6a410036020020012802002802182802402205290390012106200420054198016a29030037030820042006370300200141046a20044110107820004104360200200441106a24000b5a02027f017e230041106b220424002001410c6a4100360200200128020028021828024022052903a00121062004200541a8016a29030037030820042006370300200141046a20044110107820004104360200200441106a24000bb00601047f230041e0096b220424000240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200241146a28020021022001280210210320012802182106200441013602a807200420023602ac07024002400240200620032001411c6a2207200441a8076a10be050d002002417f4c0d0502400240024020020d00410021064101210302402001280214280208200541014100101c41026a220541024b0d0020050e03040002040b41cfa2cc00412841f8a2cc00103f000b0240200210392203450d0002402001280214280208200520032002101c41026a220541024b0d002002210620050e03030002030b41cfa2cc00412841f8a2cc00103f000b1045000b2004200236020c20042003360208200441a8076a200441086a10b902024020042802a8072202411b460d00200441f8046a200441a8076a41047241ac02109d081a02402006450d00200310350b200441b8026a200441f8046a41ac02109d081a20042002360208200441086a410472200441b8026a41ac02109d081a200441e8046a200441086a10d8032001280210210220012802182103200420042903e8043703b007200441043602a807200320022007200441a8076a10be05450d03200441086a10ba02410521020c040b2006450d010b200310350b410521020c010b20012802002102200441f8046a200441086a41b002109d081a200441c0026a22032002280218220241d8006a290000370300200441c8026a2206200241e0006a290000370300200441d0026a2205200241e8006a290000370300200420022900503703b802200441af076a200441f8046a41b002109d081a02402002413c6a2802002201200241386a280200470d00200241346a20014101109501200228023c21010b2002280234200141d8026c6a220141013a0000200120042903b802370001200141096a2003290300370000200141116a2006290300370000200141196a2005290300370000200141216a200441a8076a41b702109d081a2002200228023c41016a36023c410421020b20002002360200200441e0096a24000f0b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b1044000b9315020c7f027e230041b0036b220424000240024002400240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d0220034103460d0320022802300d0320034104460d0420022802400d0420034105460d0520022802500d0520034106460d0620022802600d0620034107460d0720022802700d0720022802042105200241146a2802002106200241246a2802002107200241346a2802002108200241c4006a2802002109200241d4006a280200210a200241e4006a280200210b200241f4006a280200210c2001280210210220012802182103200441013602b801200420063602bc010240024002400240024002400240200320022001411c6a220d200441b8016a10be050d002006417f4c0d0f02400240024020060d004100210e4101210f02402001280214280208200541014100101c41026a220241024b0d00200141146a210520020e03040002040b41cfa2cc00412841f8a2cc00103f000b20061039220f450d06024020012802142802082005200f2006101c41026a220241024b0d00200141146a21052006210e20020e03020001020b41cfa2cc00412841f8a2cc00103f000b41002102200441003a00d8010240034020062002460d01200441b8016a20026a200f20026a2d00003a00002004200241016a22033a00d8012003210220034120470d000b20044190036a41086a2202200441b8016a41086a29030037030020044190036a41106a2203200441b8016a41106a29030037030020044190036a41186a2206200441b8016a41186a290300370300200420042903b801370390030240200e450d00200f10350b200441086a41086a2002290300370300200441086a41106a2003290300370300200441086a41186a200629030037030020042004290390033703082001280210210220012802182103200441013602b801200420083602bc0120032002200d200441b8016a10be050d132008417f4c0d1120080d044100210f410121062005280200280208200741014100101c41026a220241024b0d0320020e03130305130b0240200241ff0171450d00200441003a00d8010b200e450d010b200f10350b200441c8006a41186a20044190036a41186a290300370300200441c8006a41106a20044190036a41106a290300370300200441c8006a41086a20044190036a41086a2903003703002004200429039003370348410521020c110b41cfa2cc00412841f8a2cc00103f000b200810392206450d0102402005280200280208200720062008101c41026a220241024b0d002008210f20020e030e00010e0b41cfa2cc00412841f8a2cc00103f000b41002102200441003a00d801024002400240034020082002460d01200441b8016a20026a200620026a2d00003a00002004200241016a22033a00d8012003210220034120470d000b20044190036a41086a2202200441b8016a41086a29030037030020044190036a41106a2203200441b8016a41106a29030037030020044190036a41186a2208200441b8016a41186a290300370300200420042903b801370390030240200f450d00200610350b200441286a41086a2002290300370300200441286a41106a2003290300370300200441286a41186a200829030037030020042004290390033703282001280210210320012802182106200441013602b8012004200a3602bc014105210220062003200d200441b8016a10be050d11200a417f4c0d0e200a0d022005280200280208200941014100101c41026a220341024b0d0120030e03110111110b0240200241ff0171450d00200441003a00d8010b200f0d0e0c0f0b41cfa2cc00412841f8a2cc00103f000b200a10392203450d000240200528020028020820092003200a101c41026a220641024b0d0020060e03020003020b41cfa2cc00412841f8a2cc00103f000b1045000b200310350c0c0b0240200a410f4b0d00200310350c0c0b200341086a2900002110200329000021112003103541002102200441003602a00120044201370398010240200c450d0020044190036a41186a210320044190036a41106a210620044190036a41086a210f4101210a03402003420037030020064200370300200f4200370300200442003703900320012802182108200128021021072004428180808080043703b8010240024020082007200d200441b8016a10be050d00024002402005280200280208200b20044190036a4120101c41026a220841024b0d0020080e03020001020b41cfa2cc00412841f8a2cc00103f000b200441b8016a41186a22072003290300370300200441b8016a41106a22092006290300370300200441b8016a41086a220e200f29030037030020042004290390033703b80102402002200428029c01470d0020044198016a20024101108a01200428029801210a20042802a00121020b200a20024105746a220820042903b801370000200841186a2007290300370000200841106a2009290300370000200841086a200e2903003700002004200241016a22023602a001200b41206a2208200b4f0d010b0240200428029c0141ffffff3f71450d00200a10350b410521020c0e0b2008210b200c417f6a220c0d000b0b200441e8006a41086a220220044198016a41086a2206280200360200200420042903980137036820062001280200280218220341d8006a29000037030020044198016a41106a2206200341e0006a29000037030020044198016a41186a2201200341e8006a2900003703002004200329005037039801200441f8006a41086a200441086a41086a290300370300200441f8006a41106a220f200441086a41106a290300370300200441f8006a41186a2208200441086a41186a2903003703002004200429030837037820044190036a41186a2205200441286a41186a29030037030020044190036a41106a220d200441286a41106a29030037030020044190036a41086a200441286a41086a2903003703002004200429032837039003200441d3006a20022802003600002004200429036837004b02402003413c6a2802002202200341386a280200470d00200341346a20024101109501200328023c21020b2003280234200241d8026c6a220241023a0000200220042903980137000120022004290378370021200241096a20044198016a41086a290300370000200241116a2006290300370000200241196a2001290300370000200241296a200441f8006a41086a290300370000200241316a200f290300370000200241396a200829030037000020022011370370200241f8006a20103703002002200429039003370041200241c9006a20044190036a41086a290300370000200241d1006a200d290300370000200241d9006a200529030037000020022004290048370061200241e8006a200441cf006a29000037000020024180016a200441b8016a41d801109d081a2003200328023c41016a36023c410421020c0b0b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b1044000b200610350b410521020b20002002360200200441b0036a24000b16002000410036020020002001410c6a2802003602040ba50201067f230041106b220424000240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d024105210302402001410c6a2802002205200241146a2802002206490d00200520066b200241246a2802002205470d00200228020421072001280204210820012802182102200128021021092004410236020020042005360204200220092001411c6a200410be050d000240024020012802142802082007200820066a2005101d41026a220241024b0d0020020e03020001020b41cfa2cc00412841cca3cc00103f000b410421030b20002003360200200441106a24000f0b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b820401087f230041106b2204240002400240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200241146a280200210220012802102103200128021821062004410136020020042002360204410521070240200620032001411c6a200410be050d000240024020022001410c6a220828020022064b0d00200221030c010b02400240200141086a280200220320066b200220066b2209490d002001280204210a200621030c010b200620096a220a2006490d052003410174220b200a200b200a4b1b220b4100480d050240024020030d000240200b0d004101210a0c020b200b1033220a0d010c080b2001280204210a2003200b460d00200a2003200b1037220a450d070b2001200a360204200141086a200b3602002001410c6a28020021030b200a20036a210b0240024020094102490d00200b410020022006417f7322066a2209109f081a200a200220036a20066a6a210b200920036a21030c010b2009450d010b200b41003a0000200341016a21030b20082003360200024002402001280214280208200520012802042003101c41026a220141024b0d0020010e03020001020b41cfa2cc00412841f8a2cc00103f000b410421070b20002007360200200441106a24000f0b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b103e000b103c000bf90803077f017e017f230041d0026b22042400024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d0220034103460d0320022802300d03200241246a2802002105200241346a2802002106024002400240200241146a2802002203450d00200228020421072001280210210820012802182109200441013602082004200336020c41052102200920082001411c6a200441086a10be050d0a2003417f4c0d07200310392208450d08024002402001280214280208200720082003101c41026a220941024b0d0020090e03010003010b41cfa2cc00412841f8a2cc00103f000b200810350c0a0b41012107410021094100210a0c010b200420033602dc01200420083602d801200441086a200441d8016a10c301200441106a2802002109200429020c210b200428020c210a20042802082107200810352007450d082001280210280274200b422088a7490d070b20072009410041202009676b10c105024020094102490d00200721022009210303402002200241206a2208412010a008450d08200821022003417f6a220341024f0d000b0b2001280210210220012802182103200441013602082004200636020c200320022001411c6a2208200441086a10be050d062006417f4c0d040240024020060d0041002102410121030c010b200610392203450d06200621020b0240024002402001280214280208200520032006101c41026a220541024b0d0020050e03010002010b41cfa2cc00412841f8a2cc00103f000b2002450d07200310350c070b200128021021052001280218210c200441086a41086a20063602002004200936020c200441053602080240200c20052008200441086a10be05450d002002450d07200310350c070b2006ad4220862002ad84210b200441a8026a41086a2001280200280218220841d8006a290000370300200441b8026a2201200841e0006a290000370300200441c0026a2206200841e8006a290000370300200420082900503703a80202402008413c6a2802002202200841386a280200470d00200841346a20024101109501200828023c21020b2008280234200241d8026c6a220241003a0000200220042f00cd023b0001200241073a00102002200936000c2002200a36000820022007360004200220042903a802370011200241036a200441cd026a41026a2d00003a0000200241196a200441b0026a290300370000200241216a2001290300370000200241296a2006290300370000200220033600342002200b370038200220042f00a5023b0031200241336a200441a5026a41026a2d00003a0000200241c0006a200441d8016a41c800109d081a20024188016a200441086a41d001109d081a2008200828023c41016a36023c410421020c070b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b1044000b1045000b41052102200a41ffffff3f71450d00200710350b20002002360200200441d0026a24000bbd0a03047f027e037f230041d00b6b22042400024002402003450d0020022802000d00024020034101460d0020022802100d0020022802042105200241146a28020021022001280210210620012802182107200441013602502004200236025441052103200720062001411c6a200441d0006a10be050d0202402002417f4c0d00024020020d0002402001280214280208200541014100101c41026a220241024b0d0020020e03050005050b41cfa2cc00412841f8a2cc00103f000b024002400240200210392206450d0002402001280214280208200520062002101c41026a220741024b0d0020070e03020003020b41cfa2cc00412841f8a2cc00103f000b1045000b200610350c040b02402002410f4b0d00200610350c040b200641086a290000210820062900002109200610350240200128020028021822052802180d002005417f360218200441386a200541e8006a290000370300200441306a200541e0006a290000370300200441206a41086a200541d8006a290000370300200420052900503703200240024002402005411c6a220a2802002206450d00200541206a280200210b0c010b4100210b200441f0086a410041e002109f081a200441d0006a410041a008109f081a41880b10332206450d01200641003b010620064100360200200641086a200441f0086a41e002109d081a200641e8026a200441d0006a41a008109d081a200541206a41003602002005200636021c0b2004200a3602f808200420063602f4082004200b3602f008034020062f0106220c41057421074100210241002101024002400240034020072002460d010240200441206a200620026a41086a412010a00822030d0041002102200b21070c030b200241206a2102200141016a21012003417f4a0d000b2001417f6a210c0b200b0d014101210241002107200c21010b200441d0006a41106a2001360200200441dc006a200a360200200441d0006a41086a20063602002004200a3602f808200420063602f4082004200b3602f00820042007360254200420023602504101210302402002450d00200441186a200441206a41186a290300370300200441106a200441206a41106a290300370300200441086a200441206a41086a29030037030020042004290320370300410021030b0240024020030d002004418c096a200441086a29030037020020044194096a200441106a2903003702002004419c096a200441186a2903003702002004200541246a36028009200420013602fc082004200a3602f808200420063602f408200420073602f0082004200429030037028409200441f0006a2004290340370300200441f8006a200441c0006a41086a29030037030020044188016a41003602002004420037036820044200370350200441003a008c0120044100360280012004418d016a200429002037000020044195016a200441206a41086a2900003700002004419d016a200441206a41106a290000370000200441a5016a200441206a41186a290000370000200441003a00ad01200441f0086a200441d0006a10800321020c010b200441e4006a410036020020044100360270200441003602542006200141e0006c6a41e8026a2102200441d0006a1081030b200241286a2008370300200241206a2009370300200242013703182005200528021841016a360218410421030c070b200b417f6a210b2006200c4102746a41880b6a28020021060c000b0b103c000b41a797cc004110200441d0006a41c8c1c30041c897cc001046000b1044000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b20002003360200200441d00b6a24000b7d02027f017e230041306b220424002001410c6a4100360200200441086a2001280200280218220541186a200541d0006a109404200429031021062004200441086a41106a290300427f200428020822051b37032820042006427f20051b370320200141046a200441206a4110107820004104360200200441306a24000be30201047f230041106b220424000240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200241146a280200210220012802102106200128021821072004410136020020042002360204410521030240200720062001411c6a200410be050d002002417f4c0d0302400240024020020d00410021074101210602402001280214280208200541014100101c41026a220141024b0d0020010e03040002040b41cfa2cc00412841f8a2cc00103f000b0240200210392206450d0002402001280214280208200520062002101c41026a220141024b0d002002210720010e03030002030b41cfa2cc00412841f8a2cc00103f000b1045000b2004200620021074024020042802000d00200429020410060b410421032007450d010b200610350b20002003360200200441106a24000f0b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b1044000b4001017f230041106b220424002001410c6a41003602002004200128020028021c36020c200141046a2004410c6a4104107820004104360200200441106a24000bce0502087f017e230041106b2204240002400240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200241146a28020021022001280210210320012802182106200441013602002004200236020402400240200620032001411c6a200410be050d00200141046a21070240024020022001410c6a220828020022064b0d00200221030c010b02400240200141086a280200220320066b200220066b2209490d002007280200210a200621030c010b200620096a220a2006490d062003410174220b200a200b200a4b1b220b4100480d060240024020030d000240200b0d004101210a0c020b200b1033220a0d010c090b2007280200210a2003200b460d00200a2003200b1037220a450d080b2001200a360204200141086a200b3602002001410c6a28020021030b200a20036a210b0240024020094102490d00200b410020022006417f7322066a2209109f081a200a200220036a20066a6a210b200920036a21030c010b2009450d010b200b41003a0000200341016a21030b20082003360200024002402001280214280208200520012802042003101c41026a220241024b0d0020020e03020001020b41cfa2cc00412841f8a2cc00103f000b2001410c6a2202350200210c20024100360200200141086a2203280200210620012802042102200142013702042004200c4220862002ad84100510c20120032802002103024002402004280200450d0002402003450d00200728020010350b20072004290300370200200741086a200441086a280200360200410021012006450d01200210350c010b02402003450d00200728020010350b200120023602042001410c6a4100360200200141086a2006360200410121010b20004100360200200020013602040c010b200041053602000b200441106a24000f0b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b103e000b103c000bc70402077f037e230041306b2204240002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d0220022802042105200241146a2802002103200241246a280200210620012802102107200128021821082004410136020020042003360204410521020240200820072001411c6a2209200410be050d002003417f4c0d0402400240024020030d00410021084101210702402001280214280208200541014100101c41026a220a41024b0d00200141146a2105200a0e03040002040b41cfa2cc00412841f8a2cc00103f000b0240200310392207450d0002402001280214280208200520072003101c41026a220a41024b0d00200141146a210520032108200a0e03030002030b41cfa2cc00412841f8a2cc00103f000b1045000b2003ad4220862007ad84101e2203290000210b200341086a290000210c200341106a290000210d200441186a200341186a290000370300200441106a200d370300200441086a200c3703002004200b37030020031035200128021821032001280210210120044282808080800437032002400240200320012009200441206a10be050d0002402005280200280208200620044120101d41026a220141024b0d0020010e03010002010b41cfa2cc00412841cca3cc00103f000b20080d010c020b410421022008450d010b200710350b20002002360200200441306a24000f0b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b1044000bc70402077f037e230041306b2204240002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d0220022802042105200241146a2802002103200241246a280200210620012802102107200128021821082004410136020020042003360204410521020240200820072001411c6a2209200410be050d002003417f4c0d0402400240024020030d00410021084101210702402001280214280208200541014100101c41026a220a41024b0d00200141146a2105200a0e03040002040b41cfa2cc00412841f8a2cc00103f000b0240200310392207450d0002402001280214280208200520072003101c41026a220a41024b0d00200141146a210520032108200a0e03030002030b41cfa2cc00412841f8a2cc00103f000b1045000b2003ad4220862007ad84101f2203290000210b200341086a290000210c200341106a290000210d200441186a200341186a290000370300200441106a200d370300200441086a200c3703002004200b37030020031035200128021821032001280210210120044282808080800437032002400240200320012009200441206a10be050d0002402005280200280208200620044120101d41026a220141024b0d0020010e03010002010b41cfa2cc00412841cca3cc00103f000b20080d010c020b410421022008450d010b200710350b20002002360200200441306a24000f0b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b1044000bc70402077f037e230041306b2204240002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d0220022802042105200241146a2802002103200241246a280200210620012802102107200128021821082004410136020020042003360204410521020240200820072001411c6a2209200410be050d002003417f4c0d0402400240024020030d00410021084101210702402001280214280208200541014100101c41026a220a41024b0d00200141146a2105200a0e03040002040b41cfa2cc00412841f8a2cc00103f000b0240200310392207450d0002402001280214280208200520072003101c41026a220a41024b0d00200141146a210520032108200a0e03030002030b41cfa2cc00412841f8a2cc00103f000b1045000b2003ad4220862007ad8410092203290000210b200341086a290000210c200341106a290000210d200441186a200341186a290000370300200441106a200d370300200441086a200c3703002004200b37030020031035200128021821032001280210210120044282808080800437032002400240200320012009200441206a10be050d0002402005280200280208200620044120101d41026a220141024b0d0020010e03010002010b41cfa2cc00412841cca3cc00103f000b20080d010c020b410421022008450d010b200710350b20002002360200200441306a24000f0b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b1044000ba20402077f017e230041206b2204240002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d0220022802042105200241146a2802002103200241246a280200210620012802102107200128021821082004410136021020042003360214410521020240200820072001411c6a2209200441106a10be050d002003417f4c0d0402400240024020030d00410021084101210702402001280214280208200541014100101c41026a220a41024b0d00200141146a2105200a0e03040002040b41cfa2cc00412841f8a2cc00103f000b0240200310392207450d0002402001280214280208200520072003101c41026a220a41024b0d00200141146a210520032108200a0e03030002030b41cfa2cc00412841f8a2cc00103f000b1045000b2003ad4220862007ad8410042203290000210b200441086a200341086a2900003703002004200b37030020031035200128021821032001280210210120044282808080800237031002400240200320012009200441106a10be050d0002402005280200280208200620044110101d41026a220141024b0d0020010e03010002010b41cfa2cc00412841cca3cc00103f000b20080d010c020b410421022008450d010b200710350b20002002360200200441206a24000f0b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b41e6c1c60041f40341dcc5c6001064000b1044000bc60304017f017e017f027e230041e0006b22042400200341086a2903002105200328020421060240024002400240024002400240024020032802000e06010203040005010b427f2107200520012903487c220820055a0d050c060b2006ad21080c040b2004200129035042002006ad4200108408427f210720042903084200520d04200429030021080c030b200441106a200129035842002006ad4200108408427f210720042903184200520d03200429031021080c020b200441206a200129031842002006ad4200108408427f210720042903284200520d02200429032021080c010b200441306a200129032842002006ad4200108408200441c0006a20012903204200200542ffffffff0f834200108408427f210720042903484200520d0120042903384200520d012004290340220820042903307c22052008540d01200520012903307c22082005540d010b200821070b200042002000290308220520077d220720072005561b37030841002103024020072005580d00024020022802000d00200241086a280200450d00200228020410350b4101210320024101360200200220042902543702042002410c6a200441dc006a2802003602000b200441e0006a240020030bd30e06017f017e017f017e077f067e230041e0026b2208240020014200200129030822092007280240220a41e8006a200a41e0006a200241ff01714101461b2903007d220b200b2009561b37030802400240200b2009580d00200041003a0000200041086a4122360200200041046a418496ca003602000c010b0240024002400240200728021841016a220c41004c0d00200741186a210d2007200c360218024002402007411c6a280200220e450d00200741206a280200210f0340200e41086a210a200e2f010622104105742101410021110240024003402001450d012003200a412010a0082212450d02200141606a2101201141016a2111200a41206a210a2012417f4a0d000b2011417f6a21100b200f450d02200f417f6a210f200e20104102746a41880b6a280200210e0c010b0b200e201141e0006c6a220141c5036a310000200141e8026a2903002209200950220a1ba7450d004200200141f8026a290300200a1b21094200200141f0026a290300200a1b210b0c010b200841106a200741286a28020020032007412c6a28020028021c110400200841186a29030021092007280218210c2008290310210b0b200d200c417f6a220f3602000240200b20057d2213200b56200920067d200b200554ad7d220b200956200b2009511b4101470d00200041003a0000200041086a411d360200200041046a41a696ca003602000c050b200c41004c0d012007200c36021802400240200728021c220e450d00200741206a280200210c0340200e41086a210a200e2f010622104105742101410021110240024003402001450d012004200a412010a0082212450d02200141606a2101201141016a2111200a41206a210a2012417f4a0d000b2011417f6a21100b200c450d02200c417f6a210c200e20104102746a41880b6a280200210e0c010b0b200e201141e0006c6a220141c5036a310000200141e8026a2903002209200950220a1ba7450d004200200141f8026a290300200a1b21144200200141f0026a290300200a1b21150c010b2008200741286a28020020042007412c6a28020028021c1104002007280218417f6a210f200841086a2903002114200829030021150b200d200f36020042002109024020152014844200520d00200728024022012903900120055820014198016a290300221620065820162006511b0d00200041003a0000200041086a411f360200200041046a41c396ca003602000c050b420021160240200241ff01714102460d00200728024022014198016a290300211620012903900121090b201320097d2217201356200b20167d2013200954ad7d2209200b562009200b511b0d0202402005200684500d00200841b8026a2003108e02200841206a20082802b802220a20082802c002108f02200841d0006a2903004200200829032042015122011b2116200841c8006a290300420020011b2118024020082802bc02450d00200a10350b2018201756201620095620162009511b0d040b0240201520057c22162015542201201420067c2001ad7c220920145420092014511b450d00200041003a0000200041086a412d360200200041046a418997ca003602000c050b024020032004460d0020032004412010a008450d00200d20032013200b10ae04200d20042016200910ae04200841b8026a41086a220a200341086a290000370300200841b8026a41106a2211200341106a290000370300200841b8026a41186a2212200341186a29000037030020084198026a41086a220e200441086a29000037030020084198026a41106a220c200441106a29000037030020084198026a41186a2202200441186a290000370300200820032900003703b802200820042900003703980202402007413c6a2802002201200741386a280200470d00200741346a20014101109501200728023c21010b2007280234200141d8026c6a220141003a0000200120082f00dd023b00012001420037000820014101360004200120082903b8023700112001200829039802370031200141036a200841df026a2d00003a0000200141106a41003a0000200141196a200a290300370000200141216a2011290300370000200141296a2012290300370000200141396a200e290300370000200141c1006a200c290300370000200141c9006a200229030037000020012005370358200141e0006a2006370300200141d4006a20084191026a41036a2800003600002001200828009102360051200120082903f001370368200141f0006a200841f0016a41086a290300370300200141f8006a200841f0016a41106a29030037030020014180016a200841f0016a41186a29030037030020014188016a200841206a41d001109d081a2007200728023c41016a36023c0b200041043a00000c040b41ac96cc004118200841206a41d8c1c30041d496cc001046000b41ac96cc004118200841206a41d8c1c30041d496cc001046000b200041003a0000200041086a4127360200200041046a41e296ca003602000c010b200041830c3b0100200041086a4115360000200041046a41a389c200360000200041026a41013a00000b200841e0026a24000b812f05027f027e087f037e017f230041f00d6b22072400024002400240024002400240024002402001280230200128024022082802b001460d002004420020042903082209200841c0006a2903007d220a200a20095622081b37030820080d02200741106a41186a200141e8006a290000370300200741106a41106a200141e0006a290000370300200741106a41086a200141d8006a29000037030020072001290050370310200741900b6a41186a20063502084220862006350200841009220841186a290000370300200741900b6a41106a200841106a290000370300200741900b6a41086a200841086a290000370300200720082900003703900b200810354120103322080d010c070b200041003a0004200041013602002000410c6a4129360200200041086a41aeb9ca00360200200041106a2006290200370200200041186a200641086a2802003602000c050b20082005290000370000200841186a200541186a290000370000200841106a200541106a290000370000200841086a200541086a2900003700002008412041c00010372208450d05200820072903900b370020200841386a200741900b6a41186a290300370000200841306a200741900b6a41106a290300370000200841286a200741900b6a41086a290300370000200841c00041800110372208450d0520082007290310370040200841d8006a200741106a41186a290300370000200841d0006a200741106a41106a290300370000200841c8006a200741106a41086a290300370000200741f0026a41186a220b2008ad4280808080800c841009220c41186a290000370300200741f0026a41106a220d200c41106a290000370300200741f0026a41086a220e200c41086a2900003703002007200c2900003703f002200c1035200741306a41186a220c200b290300370300200741306a41106a220b200d290300370300200741306a41086a220d200e290300370300200720072903f00237033020081035200741f0006a41d8006a200d290300370300200741d0016a200b290300370300200741d8016a200c2903003703004100210d200741ac016a41003602002007419c016a41d8b9ca0036020020074194016a410036020020072001360278200741f0006a41286a200141186a220f360200200720072903303703c001200742083702a40120074200370388012007410036027c200720012802483602b801200720012903403703b0012007200128023041016a3602a001200129030021092007200128024c3602bc0120072009370370200741f4016a41026a2208200641036a2d00003a0000200720062f00013b01f40120062d0000211020062902042109200741a8026a41186a200541186a290000370300200741a8026a41106a200541106a290000370300200741a8026a41086a200541086a290000370300200720052900003703a8022007410136028801200f200741306a10930421062007200728028801417f6a220c3602880120060d010240200c0d002007417f36028801200741f8016a41186a200741306a41186a290300370300200741f8016a41106a200741306a41106a290300370300200741f8016a41086a200741306a41086a290300370300200720072903303703f80102400240200728028c01220d450d0020074190016a280200210e0c010b4100210e200741900b6a410041e002109f081a200741f0026a410041a008109f081a41880b1033220d450d07200d41003b0106200d4100360200200d41086a200741900b6a41e002109d081a200d41e8026a200741f0026a41a008109d081a20074190016a41003602002007200d36028c010b20072007418c016a22113602980b2007200d3602940b2007200e3602900b0340200d41086a2108200d2f0106221241057421064100210c024002400240024003402006450d010240200741f8016a2008412010a008220b0d0041002106200e21080c030b200641606a2106200c41016a210c200841206a2108200b417f4a0d000b200c417f6a21120b200e0d0141012106410021082012210c0b200741f0026a41106a200c360200200741fc026a2011360200200741f0026a41086a200d360200200720113602980b2007200d3602940b2007200e3602900b200720083602f402200720063602f002024002402006450d00200741d0026a41186a200741f8016a41186a290300220a370300200741d0026a41106a200741f8016a41106a2903002213370300200741d0026a41086a200741f8016a41086a2903002214370300200720072903f80122153703d002200741ac0b6a2014370200200741900b6a41246a2013370200200741bc0b6a200a3702002007200741f0006a41246a3602a00b2007200c36029c0b200720113602980b2007200d3602940b200720083602900b200720153702a40b200741a8036a4100360200200741003a00ac03200742003703f002200741003a00cd03200741003602a0032007420037038803200741900b6a200741f0026a10800321060c010b200d200c41e0006c6a41e8026a21060b200741c0026a290300210a20064201370318200641013a003c200641286a427f370300200641206a427f3703002006413d6a20072903a802370000200641c5006a200741a8026a41086a290300370000200641cd006a200741b8026a290300370000200641d5006a200a370000200720072802880141016a36028801200741f0026a20044101200741106a200741306a20022003200741f0006a10bf05024020072d00f002220d4104460d00200741f0016a41026a20072d00f3023a0000200741ec016a41026a200741f4016a41026a2d00003a0000200720072f00f1023b01f001200720072f01f4013b01ec012009422088a72106200741f0026a41086a280200210420072802f40221052009a721010c080b200741f0026a200520072802b80128020010a306024020072802f0024101470d00200741ec016a41026a200741f4016a41026a2d00003a0000200720072f01f4013b01ec012009422088a72106200741f8026a280200210420072802f40221052009a721014100210d0c080b200741900b6a41186a200741f0026a410472220641186a2802002208360200200741f8016a41106a200641086a290200370300200741f8016a41186a200641106a29020037030020074198026a2008360200200741063602fc01200741ffd5cb003602f801200720062902003703800220072802b40121062007200741f0006a360288032007290370210a20072802bc01210820074198036a200741106a41086a290300370300200741a0036a200741106a41106a290300370300200741a8036a200741106a41186a290300370300200720033703f802200720023703f0022007200836028c032007200a370380032007200729031037039003200720103a00d002200720093702d402200720072f01f4013b00d1022007200741f4016a41026a2d00003a00d302200741900b6a2006200741f8016a200741f0026a200741d0026a2004109a05200741a8026a41026a220620072d00970b3a0000200741cc026a41026a2208200741a30b6a2d00003a0000200720072f00950b3b01a802200720072f00a10b3b01cc02200741900b6a41086a28020021052007419c0b6a280200210e200741900b6a41106a2d0000211020072d00940b2112024002400240024020072802900b4101460d00200741a4026a41026a20062d00003a0000200741a0026a41026a20082d00003a0000200720072f01a8023b01a402200720072f01cc023b01a00220072802880141016a221141004c0d05200720113602880102400240200728028c012204450d00200741f0006a41206a280200210d0340200441086a210820042f0106221641057421064100210c0240024003402006450d01200741306a2008412010a008220b450d02200641606a2106200c41016a210c200841206a2108200b417f4a0d000b200c417f6a21160b200d450d02200d417f6a210d200420164102746a41880b6a28020021040c010b0b2004200c41e0006c6a220641c5036a310000200641e8026a290300220220025022081ba7450d004200200641f8026a29030020081b21024200200641f0026a29030020081b21030c010b2007200728029801200741306a200728029c0128021c110400200741086a29030021022007290300210320072802880121110b20072011417f6a36028801200320072802b00122062903900154200220064198016a29030022035420022003511b0d01200741d0026a41086a2208200741106a41086a290300370300200741d0026a41106a220c200741106a41106a290300370300200741d0026a41186a220b200741106a41186a290300370300200741a8026a41086a2204200741306a41086a290300370300200741a8026a41106a220d200741306a41106a290300370300200741a8026a41186a2211200741306a41186a290300370300200720072903103703d002200720072903303703a802024020072802ac01220620072802a801470d00200741a4016a2006410110950120072802ac0121060b20072802a401200641d8026c6a220641003a0000200620072f00cc023b0001200641013a00102006410036000c20064201370004200620072903d002370011200620072903a802370031200641036a200741cc026a41026a2d00003a0000200641196a2008290300370000200641216a200c290300370000200641296a200b290300370000200641396a2004290300370000200641c1006a200d290300370000200641c9006a201129030037000020064180016a200741bf0b6a290000370000200641f9006a200741b80b6a290000370000200641f1006a200741900b6a41206a290000370000200641e9006a200741900b6a41186a290000370000200641e1006a200741900b6a41106a290000370000200641d9006a200741900b6a41086a290000370000200620072900900b37005120064188016a200741f0026a41d001109d081a200741f0016a41026a2208200741a4026a41026a2d00003a0000200741ec016a41026a220c200741a0026a41026a2d00003a0000200720072802ac0141016a22063602ac01200720072f01a4023b01f001200720072f01a0023b01ec010240200741f8016a41186a280200450d002007418c026a280200103520072802ac0121060b200741ec006a41026a20082d00003a0000200741e8006a41026a200c2d00003a0000200720072f01f0013b016c200720072f01ec013b0168200741f0006a41206a280200210b20072802a801211120072802a40121042007280294012116200728028c01210d0240200728027c2208450d0020074180016a280200450d00200810350b200741900b6a41026a2208200741ec006a41026a2d00003a0000200741f0006a41026a220c200741e8006a41026a2d00003a0000200720072f016c3b01900b200720072f01683b0170201041ff01710d02200720163602f8022007200b3602f4022007200d3602f002200f200741f0026a109504200141346a2001413c6a2208280200200641d8026c220641d8026d220c1095012001280234200828020041d8026c6a20042006109d081a20082008280200200c6a36020002402011450d00201141d8026c450d00200410350b200741e4006a41026a200741900b6a41026a2d00003a0000200741e0006a41026a200741f0006a41026a2d00003a0000200720072f01900b3b0164200720072f01703b01600c030b200741a40b6a2902002102200741f0016a41026a20062d00003a0000200741ec016a41026a20082d00003a0000200720072f01a8023b01f001200720072f01cc023b01ec012002422088a721062002a72101200e21042012210d0c090b200741ec016a41026a200741a4026a41026a2d00003a0000200720072f01a4023b01ec014100210d411e21042005210141fcb9ca00210520122110200e21060c080b200741e4006a41026a20082d00003a0000200741e0006a41026a200c2d00003a0000200720072f01900b3b0164200720072f01703b016002402006450d00200641d8026c210141002106034002400240200420066a22082d0000220c41014b0d0002400240200c0e020001000b0240200841086a28020041ffffff3f71450d00200841046a28020010350b200841106a2d00004107470d02200841386a280200450d02200841346a28020010350c020b200841286a10bb020c010b200841e8006a28020041ffffff3f71450d00200841e4006a28020010350b2001200641d8026a2206470d000b0b02402011450d00201141d8026c450d00200410350b02400240200d0d004100211620074184036a4100360200200741003602f4020c010b02400240200b0d00200d21060c010b200b2106200d2108034020082802880b21082006417f6a22060d000b200d21060340200620062f01064102746a41880b6a2802002106200b417f6a220b0d000b2008210d0b2007418c036a20062f010636020020074188036a410036020020074184036a20063602002007410036028003200742003703f8022007200d3602f402200741003602f0020b2007201636029003200741f0026a108f030b200741d4006a41026a2206200741e4006a41026a2d00003a0000200741d0006a41026a2208200741e0006a41026a2d00003a0000200720072f0164220c3b015c200720072f0160220b3b01582007200c3b01542007200b3b0150200041246a20123a00002000411c6a200741c8006a290300370000200041146a200741c0006a2903003700002000410c6a200741386a29030037000020002007290330370004200041306a20103a00002000412c6a200e360200200041286a2005360200200020072f01543b0025200041276a20062d00003a0000200020072f01503b0031200041336a20082d00003a0000200041003602000c080b200e417f6a210e200d20124102746a41880b6a280200210d0c010b0b41ac96cc004118200741f0026a41d8c1c30041d496cc001046000b41a797cc004110200741f0026a41c8c1c30041c897cc001046000b200041003a0004200041013602002000410c6a412a360200200041086a419abaca00360200200041106a2006290200370200200041186a200641086a2802003602000c030b200741ec016a41026a20082d00003a0000200720072f01f4013b01ec012009422088a721062009a72101419cc1c3002105412a21040c010b20074190026a280200450d002007418c026a28020010350b200741e4006a41026a200741f0016a41026a2d00003a0000200741e0006a41026a200741ec016a41026a2d00003a0000200720072f01f0013b0164200720072f01ec013b01600240200728027c2208450d0020074180016a280200450d00200810350b2006ad210202400240200728028c01220b0d004100210e20074184036a4100360200200741003602f4020c010b200728029401210e0240024020074190016a28020022080d00200b21060c010b20082106200b210c0340200c2802880b210c2006417f6a22060d000b200b21060340200620062f01064102746a41880b6a28020021062008417f6a22080d000b200c210b0b2007418c036a20062f010636020020074188036a410036020020074184036a20063602002007410036028003200742003703f8022007200b3602f402200741003602f0020b200242208621022001ad21032007200e36029003200741f0026a108f03024020072802ac012206450d0020072802a401210b200641d8026c210141002106034002400240200b20066a22082d0000220c41014b0d0002400240200c0e020001000b0240200841086a28020041ffffff3f71450d00200841046a28020010350b200841106a2d00004107470d02200841386a280200450d02200841346a28020010350c020b200841286a10bb020c010b200841e8006a28020041ffffff3f71450d00200841e4006a28020010350b2001200641d8026a2206470d000b0b20022003842102024020072802a8012206450d00200641d8026c450d0020072802a40110350b200741dc006a41026a200741e4006a41026a2d000022063a0000200741d8006a41026a2208200741e0006a41026a2d00003a0000200720072f0164220c3b015c200720072f01603b01582000200d3a00042000200c3b0005200041076a20063a0000200041106a20103a00002000410c6a2004360200200041086a2005360200200041146a200237020020004101360200200020072f01583b0011200041136a20082d00003a00000b200741f00d6a24000f0b103c000bf42003167f037e067f230041c0026b220424000240024020014115490d0041012105410121060240024002400340200121072000210820052006714101732109024002400240024002400240034002400240024002402003450d00024020054101710d002000200110fc062003417f6a21030b2001410276220a41036c210b200a410174210c4100210d024020014132490d00200a200a417f6a220d2000200a4105746a2000200d4105746a412010a008220e410048220f1b2210200a41016a2211200d200a200f1b220a200020114105746a2000200a4105746a412010a00841004822111b220a2000200a4105746a200020104105746a412010a00822104100481b210a200c200c417f6a220d2000200c4105746a2000200d4105746a412010a008221241004822131b2214200c4101722215200d200c20131b220c200020154105746a2000200c4105746a412010a00822134100481b220c2000200c4105746a200020144105746a412010a00822144100481b210c200b200b417f6a220d2000200b4105746a2000200d4105746a412010a008221541004822161b2217200b41016a2218200d200b20161b220b200020184105746a2000200b4105746a412010a008220d4100481b220b2000200b4105746a200020174105746a412010a00822164100481b210b41024101200f1b200e411f7620111b2010411f766a2012411f766a2013411f766a2014411f766a2015411f766a200d411f766a2016411f766a210d0b2000200c4105746a2000200a4105746a412010a008220f411f76200d6a2000200b4105746a2000200a200c200f410048220f1b220e4105746a412010a0082210411f766a210d2000200b200e20104100481b220b4105746a2000200c200a200f1b22194105746a412010a008417f4c0d01200b21190c020b2000200110fd060c0f0b200d41016a220d410c490d0002402001410176220b450d00200020014105746a41606a210a2000210c0340200441206a41186a220d200c41186a220f290000370300200441206a41106a220e200c41106a2210290000370300200441206a41086a2211200c41086a22122900003703002004200c290000370320200a41086a2213290000211a200a41106a2214290000211b200a41186a2215290000211c200c200a290000370000200f201c3700002010201b3700002012201a3700002015200d2903003700002014200e29030037000020132011290300370000200a2004290320370000200a41606a210a200c41206a210c200b417f6a220b0d000b0b20012019417f736a21194101210a0c010b200d45210a0b0240200a452009724101710d002000200110fe060d0d0b2002450d02201920014f0d0102402002200020194105746a220a412010a00841004e0d0020002108200121070c040b200441206a41186a2212200041186a220e290000370300200441206a41106a2213200041106a2210290000370300200441206a41086a2214200041086a221129000037030020042000290000370320200a41086a220c290000211a200a41106a220b290000211b200a41186a220d290000211c2000200a290000370000200e201c3700002010201b3700002011201a370000200d2012290300370000200b2013290300370000200c2014290300370000200a2004290320370000200441c0016a41186a2217200e290000370300200441c0016a41106a22182010290000370300200441c0016a41086a22192011290000370300200420002900003703c001200041606a2115200041206a21164100210c2001210b03400240200c200b417f6a220d4f0d002016200c4105746a210a0340200441c0016a200a412010a008417f4c0d01200a41206a210a200d200c41016a220c470d000b200d210c0b2015200b4105746a210a02400340200c200b417f6a220b4f0d01200441c0016a200a412010a008210d200a41606a220f210a200d4100480d000b20122016200c4105746a220a41186a220d2900003703002013200a41106a221d2900003703002014200a41086a22062900003703002004200a290000370320200f41286a221e290000211a200f41306a221f290000211b200f41386a2220290000211c200a200f41206a220f290000370000200d201c370000201d201b3700002006201a37000020202012290300370000201f2013290300370000201e2014290300370000200f2004290320370000200c41016a210c0c010b0b200020042903c001370000200e2017290300370000201020182903003700002011201929030037000002402001200c41016a220a490d002000200a4105746a21002001200a6b220141154f0d010c0c0b0b200a200141e485cc001059000b2019200141d086cc001042000b2007450d010b201920074f0d01200441206a41186a2216200841186a221e290000370300200441206a41106a2217200841106a221f290000370300200441206a41086a2218200841086a222029000037030020042008290000370320200820194105746a220a41086a220c290000211a200a41106a220b290000211b200a41186a220d290000211c2008200a290000370000201e201c370000201f201b3700002020201a370000200d2016290300370000200b2017290300370000200c2018290300370000200a2004290320370000200441186a2205201e290000370300200441106a2209201f290000370300200441086a2221202029000037030020042008290000370300200841206a21014100211d2007417f6a220d450d022001210a0340200a2004412010a00841004e0d03200a41206a210a200d201d41016a221d470d000b200d211d0c020b4100410041f485cc001042000b20192007418486cc001042000b200820074105746a210c200d210b02400340200c2100200b220a201d4d22060d01200a417f6a210b200041606a220c2004412010a008417f4a0d000b0b0240200a201d490d00200d200a490d0241800121144100210f410021124100210d4100211141800121152001201d4105746a2222210103400240200020016b220a419fc0004b22190d00200a410576220a41807f6a200a2012200f492011200d49220c72220b1b210a0240200b450d002015200a200c1b2115200a2014200c1b21140c010b200a200a41017622156b21140b02402011200d470d00024020150d00200441c0006a220d21110c010b4100210a200441c0006a2211210d2001210c0340200d200a3a0000200d200c2004412010a008417f73411f766a210d200c41206a210c2015200a41016a220a470d000b0b02402012200f470d00024020140d00200441c0016a220f21120c010b200041606a210a4100210c200441c0016a2212210f0340200f200c3a0000200f200a2004412010a008411f766a210f200a41606a210a2014200c41016a220c470d000b0b0240200f20126b220a200d20116b220c200c200a4b1b2213450d002016200120112d00004105746a220a41186a2900003703002017200a41106a2900003703002018200a41086a2900003703002004200a290000370320200120112d00004105746a220a200020122d0000417f734105746a220c290000370000200a41186a200c41186a290000370000200a41106a200c41106a290000370000200a41086a200c41086a290000370000024020134101460d004100210a034020002012200a6a220e2d0000417f734105746a220c20012011200a6a41016a22102d00004105746a220b290000370000200c41186a200b41186a290000370000200c41106a200b41106a290000370000200c41086a200b41086a290000370000200120102d00004105746a220c2000200e41016a2d0000417f734105746a220b290000370000200c41186a200b41186a290000370000200c41106a200b41106a290000370000200c41086a200b41086a290000370000200a41026a210c200a41016a220b210a200c2013490d000b2012200b6a21122011200b6a21110b200020122d0000417f734105746a220a2004290320370000200a41186a2016290300370000200a41106a2017290300370000200a41086a2018290300370000201241016a2112201141016a21110b200020144105746b20002012200f461b2100200120154105746a20012011200d461b210120190d000b024002402011200d4f0d002000210a034020162001200d417f6a220d2d00004105746a220c41186a220b2900003703002017200c41106a220f2900003703002018200c41086a22002900003703002004200c290000370320200a41606a220a41086a220e290000211a200a41106a2210290000211b200a41186a2212290000211c200c200a290000370000200b201c370000200f201b3700002000201a3700002012201629030037000020102017290300370000200e2018290300370000200a20042903203700002011200d490d000c020b0b2001210a2012200f4f0d000340200f417f6a220f2d0000210c2016200a41186a220b2900003703002017200a41106a220d2900003703002018200a41086a22012900003703002004200a2900003703202000200c417f734105746a220c41086a220e290000211a200c41106a2210290000211b200c41186a2211290000211c200a200c290000370000200b201c370000200d201b3700002001201a3700002011201629030037000020102017290300370000200e2018290300370000200c2004290320370000200a41206a210a2012200f490d000b0b20082004290300370000201e2005290300370000201f2009290300370000202020212903003700002007200a20226b410576201d6a22014d0d032016201e2900003703002017201f2900003703002018202029000037030020042008290000370320200820014105746a220a41086a220c290000211a200a41106a220b290000211b200a41186a220d290000211c2008200a290000370000201e201c370000201f201b3700002020201a370000200d2016290300370000200b2017290300370000200c2018290300370000200a2004290320370000200720016b220c450d04200c20012001200c4b1b210b2007410376210d200a41206a2100024002402001200c417f6a220c490d002000200c200a200310c105200821000c010b200820012002200310c105200a2102200c21010b200b200d4f2105200141154f0d010c050b0b201d200a419486cc001059000b200a200d419486cc001058000b20012007418486cc001042000b41a486cc00411c41c086cc00103f000b20014102490d00200041606a210f4101210b0340200b410574210a200b417f6a210c200b41016a210b02402000200a6a220a2000200c4105746a220d412010a008417f4a0d00200441c0016a41186a220e200a41186a2210290000370300200441c0016a41106a2211200a41106a2212290000370300200441c0016a41086a2213200a41086a22142900003703002004200a2900003703c001200a200d2900003700002014200d41086a2900003700002012200d41106a2900003700002010200d41186a2900003700004100210d0240200c450d00200f210a03400240200441c0016a200a412010a0084100480d00200c210d0c020b200a41206a200a290000370000200a41386a200a41186a290000370000200a41306a200a41106a290000370000200a41286a200a41086a290000370000200a41606a210a200c417f6a220c0d000b0b2000200d4105746a220a20042903c001370000200a41186a200e290300370000200a41106a2011290300370000200a41086a20132903003700000b200f41206a210f200b2001470d000b0b200441c0026a24000b130020004103360204200041b0c7c6003602000b130020004125360204200041d8c9c6003602000b9e0303077f017e017f230041106b220224000240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a22063602042001200441016a3602002006450d0020042d0001210720012003417e6a22063602042001200441026a3602002006450d0020042d0002210820012003417d6a22063602042001200441036a36020020060d010b200041003602040c010b20042d0003210620012003417c6a3602042001200441046a360200200241086a200110c401024020022802080d002001280204200228020c2204490d002004417f4c0d02024002400240024020040d0042002109410121030c010b200410392203450d0120012802042004490d02200320012802002004109d081a2001280204220a2004490d062001200a20046b3602042001200128020020046a3602002004ad21090b2003450d02200020092004ad4220868437020820002003360204200020074108742005722008411074722006411874723602000c030b1045000b200310350b200041003602040b200241106a24000f0b1044000b2004200a41a4f0cb001059000bc20101047f230041106b220224002000280200220028020821032000280200210041012104200128021841d9a0c00041012001411c6a28020028020c1100002105200241003a0005200220053a00042002200136020002402003450d0003402002200036020c20022002410c6a41accfc70010701a200041016a21002003417f6a22030d000b20022d000421050b0240200541ff01710d002002280200220028021841d8a0c00041012000411c6a28020028020c11000021040b200241106a240020040bb70204027f017e027f037e230041106b220224000240024020012802082203ad42287e2204422088a70d002004a72205417f4c0d00200128020021010240024020050d00410821060c010b200510332206450d020b20024100360208200220063602002002200541286e360204200241002003108f012002280208210502402003450d00200341286c21062002280200200541286c6a21030340200141086a2903002104200141106a2903002107200141186a290300210820012903002109200341206a200141206a290300370300200341186a2008370300200341106a2007370300200341086a200437030020032009370300200341286a2103200541016a2105200141286a2101200641586a22060d000b0b20002002290300370200200041086a2005360200200241106a24000f0b1044000b1045000bbc0201057f024002400240200041046a2802002202200041086a28020022036b20012802042204200128020022056b22064f0d00200320066a22052003490d01200241017422042005200420054b1b22054100480d010240024020020d00024020050d00410121040c020b2005103322040d010c040b2000280200210420022005460d0020042002200510372204450d03200041086a28020021030b20002004360200200041046a200536020020012802002105200128020421040b024020052004460d00200028020021042001200541016a360200200420036a20052d00003a0000200341016a2103200128020022052001280204460d0003402001200541016a360200200420036a20052d00003a0000200341016a2103200128020022052001280204470d000b0b200041086a20033602000f0b103e000b103c000bc60303037f017e047f230041a0076b220224002002200110c40102400240024002402002280200450d00200041003602000c010b20022802042203200128020441b0026e2204200420034b1bad42b0027e2205422088a70d012005a72206417f4c0d010240024020060d00410821070c010b200610332207450d030b4100210420024100360210200220073602082002200641b0026e36020c024002402003450d00200241f0046a41047221080340200241f0046a200110b90220022802f0042106200241c4026a200841ac02109d081a2006411b460d02200241186a200241c4026a41ac02109d081a02402004200228020c470d00200241086a2004410110920120022802082107200228021021040b2007200441b0026c6a22092006360200200941046a200241186a41ac02109d081a2002200441016a22043602102003417f6a22030d000b0b20002002290308370200200041086a200241086a41086a2802003602000c010b2000410036020002402004450d00200441b0026c2106200721040340200410bb02200441b0026a2104200641d07d6a22060d000b0b200228020c2204450d00200441b0026c450d00200710350b200241a0076a24000f0b1044000b1045000ba90603067f017e047f230041f0006b22022400200241286a200141146a350200422086200135020c84102710c2010240024020022802282203450d00200241086a2104200141106a2105034002400240200141086a22062802002207200229022c2208422088a722094b0d002001280200220a2003460d01200a2003200710a008450d010b2008a7450d02200310350c020b02402005280200450d00200128020c10350b2001200336020c20052008370200200220032009109c020240024020022d00104102460d00200241186a41086a200441086a280200360200200220042902003703182002280204210b2002280200210c024020012d0018450d002001350214422086200135020c8410070b2001280214220920062802002203490d0102400240200920036b22094108490d00200941786a2107200128020c20036a41086a210a0c010b410021070240410028028cb54c0d0041b0b4cc00210a0c010b410021074100280298b54c21034100280294b54c21094100280290b54c2106200241e500360268200242b48080801037036020024187a1c00036025c20024213370254200241f4a0c0003602502002420037034841b0b4cc00210a200241b0b4cc0036024420024201370338200241eca0c00036023420024113360230200241f4a0c00036022c20024101360228200941aca2c000200641024622061b200241286a200341c4a2c00020061b2802101102000b41002103200241003a00480240034020072003460d01200241286a20036a200a20036a2d00003a00002002200341016a22093a00482009210320094120470d000b20002002290328370000200041186a200241286a41186a290300370000200041106a200241286a41106a290300370000200041086a200241286a41086a2903003700002000200b3602242000200c36022020002002290318370228200041306a200241186a41086a2802003602000c050b0240200341ff0171450d00200241003a00480b200b41ffffff3f71450d00200c10350b200241286a2001350214422086200135020c84102710c201200228022822030d010c020b0b2003200941889aca001059000b200041023a00300b200241f0006a24000bf707040c7f017e047f037e23004190016b220224000240024002400240200141086a220328020022042001410c6a2802002205460d002001280210220628020021072006280208220841014b210903402003200441206a220a360200200241f0006a41186a200441186a290000370300200241f0006a41106a200441106a290000370300200241f0006a41086a200441086a29000037030020022004290000370370410021040240024020090d0020080e020401040b2008210b0340200b410176220c20046a220d20042007200d4105746a200241f0006a412010a0084101481b2104200b200c6b220b41014b0d000b0b200720044105746a200241f0006a412010a0080d02200a2104200a2005470d000b0b2000410036020820004201370200200128020441ffffff3f71450d01200128020010350c010b200241d0006a41086a2204200241f0006a41086a290300370300200241d0006a41106a220b200241f0006a41106a290300370300200241d0006a41186a220c200241f0006a41186a29030037030020022002290370220e3703102002200e37035041201033220f450d01200f2002290350370000200f41186a200c290300370000200f41106a200b290300370000200f41086a200429030037000020024281808080103702042002200f36020020012802042110200128020021110240200a2005460d00410121120340200628020821032006280200210702400340200241f0006a41186a2208200a41186a290000370300200241f0006a41106a2209200a41106a290000370300200241f0006a41086a2201200a41086a2900003703002002200a290000370370200a41206a210a4100210402400240200341014b0d0020030e020301030b2003210b0340200b410176220c20046a220d20042007200d4105746a200241f0006a412010a0084101481b2104200b200c6b220b41014b0d000b0b200720044105746a200241f0006a412010a0080d01200a2005470d000c030b0b200241d0006a41086a2001290300220e370300200241d0006a41106a20092903002213370300200241d0006a41186a20082903002214370300200220022903702215370350200241106a41186a220b2014370300200241106a41106a220c2013370300200241106a41086a220d200e37030020022015370310024020122002280204470d00200220124101108a012002280200210f0b200f20124105746a22042002290310370000200441186a200b290300370000200441106a200c290300370000200441086a200d2903003700002002201241016a2212360208200a2005470d000b0b0240201041ffffff3f71450d00201110350b20002002290300370200200041086a200241086a2802003602000b20024190016a24000f0b1045000baa0704057f017e0a7f027e23004180016b22032400200341306a2001200228020c220411020002400240024002402003280230450d00200341d8006a41106a200341306a41106a290300370300200341d8006a41086a200341306a41086a290300370300200341d8006a41186a200341306a41186a290300370300200341d8006a41206a200341306a41206a280200360200200341106a41086a200341e4006a290200370300200341106a41106a200341ec006a290200370300200341106a41186a200341f4006a290200370300200320032903303703582003200329025c370310200341d8006a200120022802102205110200417f2003280258220641016a220720072006491bad42287e2208422088a70d022008a72206417f4c0d02200610332209450d032009200329031037030020094201370320200941186a200341106a41186a220a290300370300200941106a200341106a41106a220b290300370300200941086a200341106a41086a220c29030037030020034101360208200320093602002003200641286e2207360204200341306a2001200411020002402003280230450d00200341d8006a41047221064102210d41c800210e0340200341d8006a41206a200341306a41206a280200360200200341d8006a41186a220f200341306a41186a290300370300200341d8006a41106a2210200341306a41106a290300370300200341d8006a41086a2211200341306a41086a29030037030020032003290330370358200c200641086a290200370300200b200641106a290200370300200a200641186a29020037030020032006290200370310200f200a2903003703002010200b2903003703002011200c290300370300200320032903103703580240200d417f6a2007470d00200341306a2001200511020020032007417f2003280230221241016a220920092012491b108f01200328020021090b2009200e6a221241606a220720032903583703002011290300210820102903002113200f290300211420124201370300200741186a2014370300200741106a2013370300200741086a20083703002003200d360208200341306a200120041102002003280230450d01200e41286a210e200d41016a210d200328020421070c000b0b2001200228020011030002402002280204450d00200110350b20002003290300370200200041086a200341086a2802003602000c010b2000410036020820004208370200200120022802001103002002280204450d00200110350b20034180016a24000f0b1044000b1045000b1300200041053602042000418cc5c7003602000b130020004106360204200041f0f2c2003602000b130020004102360204200041b8b6c3003602000b130020004105360204200041f489c2003602000b3400200041e3efcb0036020420004100360200200041146a4101360200200041106a4198bfc700360200200041086a42123702000b130020004101360204200041f0bdc7003602000b130020004108360204200041c8aac0003602000b130020004101360204200041d0ebcb003602000b1300200041113602042000418cf9c4003602000b130020004107360204200041a0e0ca003602000b130020004105360204200041d890c2003602000b130020004106360204200041ccc9c7003602000b1300200041013602042000419cbcc7003602000b130020004102360204200041d0b9c7003602000b13002000410236020420004198b8c7003602000b130020004103360204200041d8e4cb003602000b13002000410b360204200041d4aec8003602000b3400200041f1d8cb0036020420004100360200200041146a4105360200200041106a41b8b1c700360200200041086a42093702000b130020004105360204200041a89fc7003602000b1300200041083602042000419492c7003602000b130020004108360204200041c083c7003602000b13002000410636020420004194fec6003602000b130020004103360204200041fc98c8003602000b130020004103360204200041a4c4c4003602000b130020004101360204200041bce8cb003602000b130020004107360204200041fcbac3003602000b13002000410f360204200041dc9dc8003602000b130020004106360204200041dcd8ca003602000b130020004102360204200041e8efc4003602000b130020004102360204200041bc89c5003602000b2e01017f02404104103322020d001045000b20004284808080c000370204200020023602002002418080013600000b2c01017f02404104103322020d001045000b20004284808080c00037020420002002360200200241203600000b3a01017f02404110103322020d001045000b20024200370008200242808086bdbacdd21a370000200042908080808002370204200020023602000b3b01017f02404110103322020d001045000b200242003700082002428080a8ec85afd1b101370000200042908080808002370204200020023602000b3901017f02404110103322020d001045000b200242003700082002428080e983b1de16370000200042908080808002370204200020023602000b2c01017f02404104103322020d001045000b20004284808080c00037020420002002360200200241083600000b2c01017f02404104103322020d001045000b20004284808080c00037020420002002360200200241023600000b2201017f230041106b22022400200241003602002000200210e503200241106a24000bff0101017f230041a0016b22022400200241003a0088012002418080013602800120024280808480800237037820024280c2d72f37036820024280e1eb17370360200242a0c21e370358200242a0c21e370350200242e0ef9720370348200242e0c9dc29370340200242e0ef9720370338200242a0c21e370330200242a0c21e370328200242a0c21e370320200242a0c21e370318200242a0c21e370310200242a0c21e370308200242a0c21e37030020024280808080c000370370200241203602840120024100360298012002420137039001200220024190016a10f305200041086a2002280298013602002000200229039001370200200241a0016a24000bd00301017f230041106b22022400200220002802703602082001200241086a41041078200220002903003703082001200241086a41081078200220002903083703082001200241086a41081078200220002903103703082001200241086a41081078200220002903183703082001200241086a41081078200220002903203703082001200241086a41081078200220002903283703082001200241086a41081078200220002903303703082001200241086a41081078200220002903383703082001200241086a41081078200220002903403703082001200241086a41081078200220002903483703082001200241086a41081078200220002903503703082001200241086a41081078200220002903583703082001200241086a41081078200220002903603703082001200241086a41081078200220002903683703082001200241086a41081078200220002802743602082001200241086a41041078200220002802783602082001200241086a410410782002200028027c3602082001200241086a4104107820022000280280013602082001200241086a41041078200220002d0088013a00082001200241086a4101107820022000280284013602082001200241086a41041078200241106a24000b2d01017f02404104103322020d001045000b20004284808080c00037020420002002360200200241e8073600000b2d01017f02404104103322020d001045000b20004284808080c00037020420002002360200200241e5003600000b3701017f02404110103322020d001045000b2002420037000820024280c8afa025370000200042908080808002370204200020023602000b960202037f017e230041106b2202240020002802102103200041186a28020022042001107720012003200410782002200028021c36020020012002410410780240412010332203450d002003200029002c370000200341186a200041c4006a290000370000200341106a2000413c6a290000370000200341086a200041346a290000370000200120034120107820031035200029030021052002200041086a2903003703082002200537030020012002411010782002200028022036020020012002410410780240024020002802244101460d00200241003a000020012002410110780c010b200241013a000020012002410110782002200041286a28020036020020012002410410780b200241106a24000f0b1045000bf10203037f017e037f230041106b22022400200241003602082002420137030020002d00002103410110332104024002400240024020034101460d002004450d02200441003a0000200220043602002002428180808010370204200041086a200210f705200235020842208621052002280204452104200228020021000c010b2004450d01200441013a0000200220043602002002428180808010370204412010332203450d0220032000290001370000200341186a2206200041196a290000370000200341106a2207200041116a290000370000200341086a2208200041096a29000037000020044101412110372200450d0120002003290000370001200041096a2008290000370000200041116a2007290000370000200041196a200629000037000020022000360200200242a1808080900437020420031035410021044280808080900421050b200129020020052000ad841002024020040d00200010350b200241106a24000f0b103c000b1045000bc90402017f037e23004190016b22042400024002400240024020002d00000e03000102000b200441206a41186a200141186a290000370300200441206a41106a200141106a290000370300200441206a41086a200141086a29000037030020042001290000370320200041016a2003ad4220862002ad84200441206a102041014621000c020b200441206a41186a200141186a290000370300200441206a41106a200141106a290000370300200441206a41086a200141086a29000037030020042001290000370320200041016a2003ad4220862002ad84200441206a101541014621000c010b2003ad4220862002ad84100922022900002105200241086a2900002106200241106a2900002107200441186a200241186a290000370300200441106a2007370300200441086a2006370300200420053703002002103541012102200441206a200041016a200410fa054100210020042d00200d00200441c8006a41206a200441c1006a2d00003a0000200441c8006a41186a200441396a290000370300200441c8006a41106a200441316a290000370300200441c8006a41086a200441296a29000037030020042004290021370348200441c8006aad4280808080900484100922002900002105200041086a2900002106200041106a2900002107200441f0006a41186a200041186a290000370300200441f0006a41106a2007370300200441f0006a41086a200637030020042005370370200010350240200441f0006a2001460d00200441f0006a2001412010a0084521020b200221000b20044190016a240020000bcf0303017f017e037f230041d0006b22032400024020012002102f2204422088a72201450d002004a722052d0000220241014b0d002001417f6a210602400240024020020e020001000b41002101200341003a0049200541016a21070240034020062001460d01200341286a20016a200720016a2d00003a00002003200141016a22023a00492002210120024121470d000b200341106a200341316a290000370300200341186a200341396a290000370300200341206a200341c1006a2900003703002003200329002937030820032d0028210241002106200341086a21010c020b200141ff0171450d02200341003a00490c020b2006450d0120052d0001220241034f0d01200341086a41186a200341286a41186a290000370300200341086a41106a200341286a41106a290000370300200341086a41086a200341286a41086a2900003703002003200329002837030841012106200341086a21010b200020023a0001200020063a0000200041026a20012900003700002000410a6a200141086a290000370000200041126a200141106a2900003700002000411a6a200141186a29000037000020051035200341d0006a24000f0b41b89acc00412e200341286a41c09bcc0041e89acc001046000bd40303017f017e027f230041e0006b22022400024002402000290300220342c000540d00024002400240200342808001540d002003428080808004540d014108200379a741037622046b4104490d022002411320044102746b3a00482001200241c8006a41011078200220002903002203370308200441786a21000340200220033c00482001200241c8006a4101107820034208882103200041016a22042000492105200421002005450d000b200220033703082003500d04200241286a41146a410a360200200241346a4134360200200241106a41146a41033602002002200241086a36024020024180caca00360244200241c8006a41146a410036020020024203370214200241a0b3cc003602102002413436022c200241b0b4cc003602582002420137024c20024188caca003602482002200241286a3602202002200241c8006a3602382002200241c4006a3602302002200241c0006a360228200241106a41b0b4cc00104c000b20022003a74102744101723b01482001200241c8006a410210780c030b20022003a74102744102723602482001200241c8006a410410780c020b41c6c9ca00413641c086cc00103f000b20022003a74102743a00482001200241c8006a410110780b200241e0006a24000bc30101017f230041106b2202240002400240024020002d00004101470d00200041046a280200220041ffff034b0d010240200041ef014b0d00200220003a000b20012002410b6a410110780c030b200241fc013a000b20012002410b6a41011078200220003b01082001200241086a410210780c020b200241ff013a000b20012002410b6a410110782001200041016a412010780c010b200241fd013a000b20012002410b6a410110782002200036020c20012002410c6a410410780b200241106a24000bcb0102017f017e230041106b220224000240024020002d00004101460d00200241003a00002001200241011078200220002d0001410047410774200041026a2d0000723a00002001200241011078200029030821032002200041106a290300370308200220033703000c010b200241013a00002001200241011078200029030821032002200041106a290300370308200220033703002001200241101078200041186a29030021032002200041206a290300370308200220033703000b2001200241101078200241106a24000b960401037f230041106b220224000240024020002d0000417f6a220341044b0d000240024002400240024020030e050001020304000b200241003a000f20012002410f6a41011078200041246a28020021032000412c6a28020022042001107702402004450d002004410574210403402001200341201078200341206a2103200441606a22040d000b0b024020002d00014101460d00200241003a000f20012002410f6a410110780c050b200241013a000f20012002410f6a410110782001200041026a412010780c040b200241013a000f20012002410f6a41011078200041046a280200200110af030c030b200241023a000f20012002410f6a41011078200041046a200110e201200041086a280200200110af030c020b200241033a000f20012002410f6a41011078412010332203450d0220032000290001370000200341186a200041196a290000370000200341106a200041116a290000370000200341086a200041096a290000370000200120034120107820031035200041246a200110e2012002200041216a2d00003a000f20012002410f6a410110780c010b200241043a000f20012002410f6a41011078412010332203450d0120032000290001370000200341186a200041196a290000370000200341106a200041116a290000370000200341086a200041096a290000370000200120034120107820031035200041246a200110e2010b200241106a24000f0b1045000b4a01037f230041106b220124002001410036020820014201370300200110ff05200128020421022000200128020022032001280208107802402002450d00200310350b200141106a24000ba50303027f047e017f230041f0006b22032400200341106a20012802002204280210200441186a28020010f4032002ad42808080808004842205100922042900002106200441086a2900002107200441106a2900002108200341206a41186a200441186a290000370300200341206a41106a2008370300200341206a41086a200737030020032006370320200410352003200335021842208620032802102209ad84200341206aad4280808080800484101010c2010240024020032802000d00200041003602000c010b200341c0006a20012802002204280210200428021810f40320051009220441086a2900002106200441106a290000210720042900002108200341d0006a41186a200441186a290000370300200341d0006a41106a2007370300200341d0006a41086a20063703002003200837035020041035200335024842208620032802402204ad84200341d0006aad4280808080800484101302402003280244450d00200410350b20002002360200200020032903003702042000410c6a200341086a2802003602000b02402003280214450d00200910350b200341f0006a24000bf80201067f230041d0006b22022400024002400240410b10332203450d00200341edde91e3063600002003410b411610372204450d0120042001290000370004200441002800acb94836000c2004410f6a41002800afb948360000200241003a00484113210320042105410021060340200241003a0008200241086a200520034100472201109d081a024020030d00200241003a00080b20032001490d03200241286a20066a20022d00083a00002002200641016a22073a0048200320016b2103200520016a21052007210620074120470d000b200241086a41186a2203200241286a41186a290300370300200241086a41106a2201200241286a41106a290300370300200241086a41086a2205200241286a41086a2903003703002002200229032837030820041035200041186a2003290300370000200041106a2001290300370000200041086a200529030037000020002002290308370000200241d0006a24000f0b1045000b103c000b2001200341b89dcc001059000b964603027f017e027f230041106b220224000240024020002d0000220341154b0d00024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020030e16000102030405060708090a0b0c0d0e0f101112131415000b200241003a00002001200241011078200041086a2d0000220341044b0d150240024002400240024020030e050001020304000b200241003a000020012002410110782002200041106a29030037030020012002410810780240200041186a2d0000220341024b0d00024002400240024020030e03000102000b200241003a00000c020b200241013a00000c010b200241023a00000b20012002410110780b2002200041196a2d00003a000020012002410110780c190b200241013a00002001200241011078024002400240024002402000410c6a2d00000e0400010203000b200241003a00000c030b200241013a00000c020b200241023a00000c010b200241033a0000200120024101107820022000410d6a2d00003a0000200120024101107820022000410e6a2d00003a00000b20012002410110782002200029031837030020012002410810780240200041206a2d0000220341024b0d00024002400240024020030e03000102000b200241003a00000c020b200241013a00000c010b200241023a00000b20012002410110780b2002200041216a2d00003a000020012002410110780c180b200241023a000020012002410110780c170b200241033a000020012002410110782001200041096a412010780c160b200241043a000020012002410110782001200041096a412010780c150b200241013a00002001200241011078200041046a2d0000220341054b0d1402400240024002400240024020030e06000102030405000b200241003a000020012002410110782002200041086a2802003602002001200241041078024002400240024002402000410c6a2d00000e0400010203000b200241003a00000c030b200241013a00000c020b200241023a00000c010b200241033a0000200120024101107820022000410d6a2d00003a0000200120024101107820022000410e6a2d00003a00000b20012002410110780c190b200241013a000020012002410110780c180b200241023a000020012002410110782001200041056a412010782001200041256a412010782001200041c5006a412010780c170b200241033a000020012002410110782001200041056a412010782002200041e8006a28020036020020012002410410782002200041ec006a28020036020020012002410410782001200041256a412010782001200041c5006a412010780c160b200241043a000020012002410110782001200041056a412010782002200041e8006a28020036020020012002410410782002200041ec006a28020036020020012002410410782001200041256a412010782001200041c5006a412010780240200041f0006a2d00004104460d00200241013a000020012002410110780240024002400240024020002d00700e0400010203000b200241003a00000c030b200241013a00000c020b200241023a00000c010b200241033a000020012002410110782002200041f1006a2d00003a000020012002410110782002200041f2006a2d00003a00000b20012002410110780c160b200241003a000020012002410110780c150b200241053a000020012002410110782001200041056a412010782002200041e8006a28020036020020012002410410782002200041ec006a28020036020020012002410410782001200041256a412010782001200041c5006a412010780c140b200241023a000020012002410110780240200041046a2d00004101460d00200241003a000020012002410110782001200041056a412010782002200041286a28020036020020012002410410780c140b200241013a000020012002410110782002200041086a28020036020020012002410410780c130b200241033a00002001200241011078200041086a2d0000220341044b0d1202400240024002400240024020030e050001020304000b200241003a000020012002410110782001200041096a41201078200041306a29030021042002200041386a290300370308200220043703000c040b200241013a000020012002410110782001200041096a41201078200041306a29030021042002200041386a290300370308200220043703000c030b200241023a000020012002410110782001200041096a412010782001200041296a41201078200041d0006a29030021042002200041d8006a290300370308200220043703000c020b200241033a000020012002410110782001200041096a41201078200041306a29030021042002200041386a290300370308200220043703002001200241101078200041c0006a29030021042002200041c8006a290300370308200220043703000c010b200241043a000020012002410110782001200041096a41201078200041306a29030021042002200041386a290300370308200220043703000b20012002411010780c120b200241043a0000200120024101107802400240024002400240024002400240200041086a2d00000e080001020304050607000b200241003a0000200120024101107820022000410c6a2802003602002001200241041078200041106a29030021042002200041186a290300370308200220043703002001200241101078200041206a29030021042002200041286a2903003703082002200437030020012002411010780c180b200241013a000020012002410110782001200041096a41201078200041306a29030021042002200041386a2903003703082002200437030020012002411010780c170b200241023a000020012002410110782001200041096a41201078200041306a29030021042002200041386a2903003703082002200437030020012002411010780c160b200241033a0000200120024101107820022000410c6a28020036020020012002410410780c150b200241043a00002001200241011078200041096a2d0000220041024b0d1402400240024020000e03000102000b200241003a000020012002410110780c160b200241013a000020012002410110780c150b200241023a000020012002410110780c140b200241053a000020012002410110782001200041096a41201078200041306a29030021042002200041386a2903003703082002200437030020012002411010780c130b200241063a000020012002410110782001200041096a41201078200041306a29030021042002200041386a2903003703082002200437030020012002411010780c120b200241073a000020012002410110782001200041096a41201078200041306a29030021042002200041386a2903003703082002200437030020012002411010780c110b200241053a00002001200241011078200241003a000020012002410110782002200041046a28020036020020012002410410780c100b200241063a00002001200241011078200041086a2d0000220341104b0d0f0240024002400240024002400240024002400240024002400240024002400240024020030e11000102030405060708090a0b0c0d0e0f10000b200241003a0000200120024101107820022000410c6a2802003602002001200241041078200041106a29030021042002200041186a2903003703082002200437030020012002411010780c1f0b200241013a0000200120024101107820022000410c6a2802003602002001200241041078200041206a29030021042002200041286a290300370308200220043703002001200241101078200041106a2802002103200041186a2802002200200110772000450d1e2000410574210003402001200341201078200341206a2103200041606a22000d000c1f0b0b200241023a000020012002410110780c1d0b200241033a0000200120024101107820022000410c6a2802003602002001200241041078200041096a2d0000220041024b0d1c02400240024020000e03000102000b200241003a000020012002410110780c1e0b200241013a000020012002410110780c1d0b200241023a000020012002410110780c1c0b200241043a0000200120024101107820022000410c6a28020036020020012002410410780c1b0b200241053a0000200120024101107820022000410c6a28020036020020012002410410780c1a0b200241063a0000200120024101107820022000410c6a28020036020020012002410410780c190b200241073a0000200120024101107820022000410c6a28020036020020012002410410782002200041096a2d00003a000020012002410110780c180b200241083a000020012002410110782001200041096a412010782001200041296a412010780c170b200241093a000020012002410110782001200041096a412010780c160b2002410a3a000020012002410110782001200041096a41201078412010332203450d16200341186a200041c1006a290000370000200341106a200041396a290000370000200341086a200041316a2900003700002003200041296a2900003700002001200341201078200310352002200041cc006a28020036020020012002410410780c150b2002410b3a00002001200241011078412010332203450d15200341186a200041216a290000370000200341106a200041196a290000370000200341086a200041116a2900003700002003200041096a2900003700002001200341201078200310352001200041296a41201078200041d0006a29030021042002200041d8006a2903003703082002200437030020012002411010780c140b2002410c3a00002001200241011078412010332203450d14200341186a200041216a290000370000200341106a200041196a290000370000200341086a200041116a2900003700002003200041096a2900003700002001200341201078200310352001200041296a41201078200041d0006a29030021042002200041d8006a2903003703082002200437030020012002411010780c130b2002410d3a00002001200241011078412010332203450d13200341186a200041216a290000370000200341106a200041196a290000370000200341086a200041116a2900003700002003200041096a29000037000020012003412010782003103520022000412c6a28020036020020012002410410780c120b2002410e3a00002001200241011078412010332203450d12200341186a200041216a290000370000200341106a200041196a290000370000200341086a200041116a2900003700002003200041096a29000037000020012003412010782003103520022000412c6a28020036020020012002410410780c110b2002410f3a00002001200241011078412010332203450d11200341186a200041216a290000370000200341106a200041196a290000370000200341086a200041116a2900003700002003200041096a2900003700002001200341201078200310352001200041296a41201078200041f0006a29030021042002200041f8006a2903003703082002200437030020012002411010782001200041c9006a412010780c100b200241103a000020012002410110782001200041096a412010780c0f0b200241073a00002001200241011078200041046a20011083060c0e0b200241083a00002001200241011078200041046a20011083060c0d0b200241093a00002001200241011078200041046a2d0000220341044b0d0c0240024002400240024020030e050001020304000b200241003a00002001200241011078200041086a2802002103200041106a2802002200200110772000450d102003200041306c6a210003402001200341201078200341206a29030021042002200341286a2903003703082002200437030020012002411010782000200341306a2203470d000c110b0b200241013a000020012002410110780c0f0b200241023a000020012002410110782001200041056a412010780c0e0b200241033a000020012002410110782001200041056a412010780c0d0b200241043a000020012002410110782001200041056a412010782001200041256a412010782002200041c5006a2d00003a000020012002410110780c0c0b2002410a3a0000200120024101107820002d0001220041054b0d0b024002400240024002400240024020000e06000102030405000b200241003a00000c050b200241013a00000c040b200241023a00000c030b200241033a00000c020b200241043a00000c010b200241053a00000b20012002410110780c0b0b2002410b3a00002001200241011078200041046a280200220341024b0d0a02400240024020030e03000102000b200241003a00002001200241011078200041086a2802002103200041106a2802002200200110772000450d0c2003200041286c6a2100034020012003412010782002200341206a29030037030020012002410810782000200341286a2203470d000c0d0b0b200241013a000020012002410110780c0b0b200241023a000020012002410110780c0a0b2002410c3a00002001200241011078200041086a2d00002203410a4b0d090240024002400240024002400240024002400240024020030e0b000102030405060708090a000b200241003a0000200120024101107820022000410c6a28020036020020012002410410780c130b200241013a00002001200241011078200041106a29030021042002200041186a2903003703082002200437030020012002411010780c120b200241023a0000200120024101107820022000412c6a2802003602002001200241041078200041306a29030021042002200041386a2903003703082002200437030020012002411010782001200041096a412010780c110b200241033a0000200120024101107820022000410c6a2802003602002001200241041078200041106a29030021042002200041186a2903003703082002200437030020012002411010780c100b200241043a00002001200241011078200041106a29030021042002200041186a2903003703082002200437030020012002411010780c0f0b200241053a00002001200241011078200041106a29030021042002200041186a2903003703082002200437030020012002411010780c0e0b200241063a00002001200241011078200041106a29030021042002200041186a2903003703082002200437030020012002411010780c0d0b200241073a00002001200241011078412010332203450d0d200341186a200041216a290000370000200341106a200041196a290000370000200341086a200041116a2900003700002003200041096a2900003700002001200341201078200310350c0c0b200241083a00002001200241011078412010332203450d0c200341186a200041216a290000370000200341106a200041196a290000370000200341086a200041116a2900003700002003200041096a2900003700002001200341201078200310350c0b0b200241093a00002001200241011078412010332203450d0b200341186a200041216a290000370000200341106a200041196a290000370000200341086a200041116a2900003700002003200041096a2900003700002001200341201078200310352001200041296a41201078200041d0006a29030021042002200041d8006a2903003703082002200437030020012002411010780c0a0b2002410a3a00002001200241011078412010332203450d0a200341186a200041216a290000370000200341106a200041196a290000370000200341086a200041116a2900003700002003200041096a2900003700002001200341201078200310350c090b2002410d3a0000200120024101107802400240024002400240024002400240200041086a2d00000e080001020304050607000b200241003a000020012002410110782001200041096a412010782001200041296a41201078200041d0006a29030021042002200041d8006a2903003703082002200437030020012002411010780c0f0b200241013a000020012002410110782001200041096a412010782001200041296a412010780c0e0b200241023a000020012002410110782001200041096a412010782002200041296a2d00003a000020012002410110780c0d0b200241033a000020012002410110782001200041096a412010782001200041296a41201078412010332203450d0d200341186a200041e1006a290000370000200341106a200041d9006a290000370000200341086a200041d1006a2900003700002003200041c9006a290000370000200120034120107820031035200041f0006a29030021042002200041f8006a2903003703082002200437030020012002411010782002200041e9006a2d00003a000020012002410110780c0c0b200241043a00002001200241011078412010332203450d0c200341186a200041216a290000370000200341106a200041196a290000370000200341086a200041116a2900003700002003200041096a2900003700002001200341201078200310350c0b0b200241053a0000200120024101107820022000410c6a28020036020020012002410410780c0a0b200241063a000020012002410110782001200041096a412010782002200041296a2d00003a000020012002410110780c090b200241073a000020012002410110782001200041096a412010782000412c6a2802002103200041346a28020022002001107720012003200010780c080b2002410e3a00002001200241011078200041046a2d0000220341024b0d0702400240024020030e03000102000b200241003a000020012002410110780240200041086a2d000022034104460d00200241013a000020012002410110780240024002400240024020030e0400010203000b200241003a00000c030b200241013a00000c020b200241023a00000c010b200241033a000020012002410110782002200041096a2d00003a0000200120024101107820022000410a6a2d00003a00000b20012002410110780c0a0b200241003a000020012002410110780c090b200241013a000020012002410110782001200041056a412010780c080b200241023a000020012002410110782002200041056a2d00003a000020012002410110780c070b2002410f3a00002001200241011078200041046a2d0000220341024b0d0602400240024020030e03000102000b200241003a000020012002410110782001200041056a412010780c080b200241013a000020012002410110780c070b200241023a00002001200241011078200041086a2802002105200041106a2802002200200110772000450d062005200041d0006c6a2106034020012005412010782002200541206a3602002002200110cf012002200541306a3602002002200110cf01200528024021002005280248220320011077200541d0006a210502402003450d00200341306c210303402001200041106a41201078200220003602002002200110cf01200041306a2100200341506a22030d000b0b20062005470d000c070b0b200241103a00002001200241011078200241003a000020012002410110782001200041106a41101078200041046a28020021032000410c6a28020022052001107720012003200510782002200041206a2d00003a000020012002410110780c050b200241113a00002001200241011078200041086a2d0000220341064b0d04024002400240024002400240024020030e0700010203040506000b200241003a000020012002410110782001200041096a412010780c0a0b200241013a000020012002410110782001200041096a41201078200041306a29030021042002200041386a2903003703082002200437030020012002411010780c090b200241023a000020012002410110782001200041096a41201078200041306a29030021042002200041386a2903003703082002200437030020012002411010780c080b200241033a000020012002410110782001200041096a4120107820022000412c6a28020036020020012002410410780c070b200241043a000020012002410110782001200041096a4120107820022000412c6a28020036020020012002410410780c060b200241053a000020012002410110782001200041096a4120107820022000412c6a28020036020020012002410410780c050b200241063a0000200120024101107820022000410c6a28020036020020012002410410780c040b200241123a00002001200241011078200041086a2d00002203410e4b0d0302400240024002400240024002400240024002400240024002400240024020030e0f000102030405060708090a0b0c0d0e000b200241003a000020012002410110782001200041096a412010780c110b200241013a000020012002410110782001200041096a41201078200041306a29030021042002200041386a2903003703082002200437030020012002411010780c100b200241023a000020012002410110782001200041096a41201078200041d0006a29030021042002200041d8006a2903003703082002200437030020012002411010782001200041296a412010780c0f0b200241033a000020012002410110782001200041096a412010780c0e0b200241043a000020012002410110782001200041096a412010780c0d0b200241053a000020012002410110782001200041096a412010780c0c0b200241063a000020012002410110782001200041096a412010782000412c6a2802002103200041346a2802002200200110772000450d0b2000410574210003402001200341201078200341206a2103200041606a22000d000c0c0b0b200241073a000020012002410110782001200041096a412010782002200041296a2d00003a000020012002410110780c0a0b200241083a000020012002410110782001200041096a412010780c090b200241093a000020012002410110782001200041096a412010780c080b2002410a3a000020012002410110782001200041096a412010780c070b2002410b3a000020012002410110782001200041096a412010782001200041296a412010782002200041c9006a2d00003a000020012002410110780c060b2002410c3a000020012002410110782001200041096a412010782002200041296a2d00003a000020012002410110780c050b2002410d3a0000200120024101107820022000410c6a28020036020020012002410410780c040b2002410e3a000020012002410110782001200041096a412010780c030b200241133a0000200120024101107820002d0001220341054b0d02024002400240024002400240024020030e06000102030405000b200241003a00002001200241011078200041026a21000c050b200241013a000020012002410110782001200041026a41201078200041226a21000c040b200241023a000020012002410110782001200041026a412010782001200041226a41201078200041c2006a21000c030b200241033a000020012002410110782001200041026a41201078200041226a21000c020b200241043a000020012002410110782001200041026a41201078200041226a21000c010b200241053a00002001200241011078200041026a21000b20012000412010780c020b200241143a00002001200241011078200041096a21030240200041086a2d00004101460d00200241003a000020012002410110782001200341201078200041306a29030021042002200041386a2903003703082002200437030020012002411010780c020b200241013a0000200120024101107820012003412010780c010b200241153a000020012002410110780240200041046a2802004101460d00200241003a000020012002410110782002200041086a28020036020020012002410410780c010b200241013a000020012002410110782002200041086a280200360200200120024104107820022000410c6a280200360200200120024104107802400240200041106a28020022030d00200241003a000020012002410110780c010b200241013a00002001200241011078200041186a28020022052001107720012003200510780b024020002d001c22034104460d00200241013a000020012002410110780240024002400240024020030e0400010203000b200241003a00000c030b200241013a00000c020b200241023a00000c010b200241033a0000200120024101107820022000411d6a2d00003a0000200120024101107820022000411e6a2d00003a00000b20012002410110780c010b200241003a000020012002410110780b200241106a24000f0b1045000bf70701027f230041106b220224000240024020002d0000220341064b0d00024002400240024002400240024020030e0700010203040506000b200241003a000c20012002410c6a410110782001200041016a412010782002200041c4006a28020036020c20012002410c6a41041078412010332203450d07200341186a200041396a290000370000200341106a200041316a290000370000200341086a200041296a2900003700002003200041216a2900003700002001200341201078200310352002200041c8006a28020036020c20012002410c6a410410780c060b200241013a000c20012002410c6a410110782001200041016a41201078412010332203450d06200341186a200041396a290000370000200341106a200041316a290000370000200341086a200041296a2900003700002003200041216a2900003700002001200341201078200310352002200041c1006a2d00003a000c20012002410c6a410110782002200041c4006a28020036020c20012002410c6a410410782002200041c8006a28020036020c20012002410c6a410410780c050b200241023a000c20012002410c6a41011078412010332203450d0520032000290001370000200341186a200041196a290000370000200341106a200041116a290000370000200341086a200041096a2900003700002001200341201078200310350c040b200241033a000c20012002410c6a41011078412010332203450d0420032000290001370000200341186a200041196a290000370000200341106a200041116a290000370000200341086a200041096a2900003700002001200341201078200310350c030b200241043a000c20012002410c6a41011078412010332203450d0320032000290001370000200341186a200041196a290000370000200341106a200041116a290000370000200341086a200041096a2900003700002001200341201078200310352002200041216a2d00003a000c20012002410c6a410110780c020b200241053a000c20012002410c6a41011078412010332203450d0220032000290001370000200341186a200041196a290000370000200341106a200041116a290000370000200341086a200041096a2900003700002001200341201078200310352002200041216a2d00003a000c20012002410c6a410110780c010b200241063a000c20012002410c6a41011078412010332203450d0120032000290001370000200341186a200041196a290000370000200341106a200041116a290000370000200341086a200041096a2900003700002001200341201078200310352002200041246a28020036020c20012002410c6a410410782002200041286a28020036020c20012002410c6a410410780b200241106a24000f0b1045000b4d01017f230041206b22002400200041146a410136020020004201370204200041e8d4ca003602002000410436021c2000419cd5ca003602182000200041186a360210200041b0b4cc00104c000bec220a017f017e037f017e037f017e047f017e077f047e230041e0016b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402001280200417f6a0e0a00010203040506070809000b420021042000420037030820022d000120022d000041004772450d18200041186a41023602000c170b200141086a280200210520012802042101024020022d00000d0020022d000141ff01714101470d002005450d09200110350c090b02402005450d00200110350b20004200370308200041186a41023602000c160b024020022d000120022d0000410047720d00200141086a2903002104410810332201450d0b2001200437000041de92c800ad4280808080a001842001ad42808080808001841002200110350c080b20004200370308200041186a41023602000c150b200141086a280200210520012802042106024020022d000120022d000041004772450d00410221070c140b200341b0016a2001410c6a280200ad22044220862006ad220884102510c20120032802b0012201450d1220032802b40121022003200341b8016a2802003602ac01200320013602a801200341186a200341a8016a10c40120032802180d1120032802ac012209200328021c220a490d11200a417f4c0d0a02400240200a0d0041002109410121070c010b200a10392207450d0a200720032802a801220b200a109d081a20032009200a6b3602ac012003200b200a6a3602a801200a21090b2007450d11200341106a200341a8016a10c401200aad4220862009ad84220ca7210920032802100d0f20032802ac01220a2003280214220b490d0f200b417f4c0d0a02400240200b0d004100210b4101210d0c010b200b1039220d450d0a200d20032802a801220e200b109d081a2003200a200b6b220a3602ac012003200e200b6a3602a8010b200d450d0f02400240024002400240200a4104490d00200320032802a801220e41046a3602a8012003200a417c6a220f3602ac01200f4104490d012003200e41086a3602a801200e28000421102003200a41786a220f3602ac01200f4104490d032003200a41746a3602ac012003200e410c6a3602a801200341086a200341a8016a10c4012003280208450d020c130b0240200b450d00200d10350b20090d140c150b0240200b450d00200d10350b20090d130c140b200328020c220e20032802ac01410c6e220a200a200e4b1bad420c7e2211422088a70d0c2011a7220f417f4c0d0c02400240200f0d00410421120c010b200f10332212450d0c0b4100210a20034100360228200320123602202003200f410c6e36022402400240200e450d000340200341d0016a200341a8016a10ee0220032d00d0014101460d0220032802ac01220f4104490d0220032900d101211120032802a801221328000021142003200f417c6a3602ac012003201341046a3602a8010240200a2003280224470d00200341206a200a4101108701200328022021122003280228210a0b2012200a410c6c6a220f2014360208200f20113702002003200a41016a220a360228200e417f6a220e0d000b0b2012450d112003290224a7210e20032802ac0141044f0d020240200e450d00200e410c6c450d00201210350b0240200b450d00200d10350b2009450d140c130b2003280224220a450d10200a410c6c450d10201210350c100b0240200b450d00200d10350b20090d110c120b200c422088a7210f02402002450d00200110350b41b5c3c700210a410f210241002101200f4104470d0d024020074190e1c600460d00200728000041eede91ab06470d0e0b0240201041f6014f0d00419bc3c700210a411a2102410121010c0e0b02402009450d00200710350b0240200b450d00200d10350b0240200e450d00200e410c6c450d00201210350b41e892c800ad4280808080d0008420044220862008841002200341286a41023a0000200341003a002041b0b4cc004100200341206a10d4012005450d06200610350c060b200141086a280200210520012802042106024020022d000120022d0000410047720d0041e892c800ad4280808080d000842001410c6a3502004220862006ad841002200341206a41086a41023a0000200341003a002041b0b4cc004100200341206a10d4012005450d06200610350c060b02402005450d00200610350b20004200370308200041186a41023602000c130b20022d000120022d0000410047720d0a2001410c6a2802002105200141086a280200210702400240200128020422094101460d0041ed92c800ad4280808080d0018410070c010b410410332201450d0a2001200736000020014104410810372201450d0a2001200536000441ed92c800ad4280808080d001842001ad42808080808001841002200110350b200341206a41186a4200370300200341206a41106a22064200370300200341206a41086a220142003703002003420037032041d1c4c700ad4280808080e000841001220229000021042001200241086a29000037030020032004370320200210354185c5c700ad4280808080e00084100122022900002104200341d0016a41086a220a200241086a290000370300200320043703d00120021035200620032903d0012204370300200341b0016a41086a2001290300370300200341b0016a41106a2004370300200341b0016a41186a200a290300370300200320032903203703b001200341206a200341b0016a10ce0202400240200328022022060d004100210a200341003602d801200342043703d00141042106410021020c010b2003200329022422043702d401200320063602d0012004422088a721022004a7210a0b200341a8016a41026a220b200341a5016a41026a2d00003a0000200341206a41086a220d200341b0016a41086a290200370300200341206a41106a220e200341b0016a41106a280200360200200320032f00a5013b01a801200320032902b00137032002402002200a470d00200341d0016a200a4101108d0120032802d401210a20032802d001210620032802d80121020b2006200241246c220f6a220141043a00002001200536020c2001200736020820012009360204200141036a200b2d00003a0000200120032f01a8013b000120012003290320370210200141186a200d290300370200200141206a200e2802003602002003200241016a22013602d80141d1c4c700ad4280808080e0008410012205290000210420052900082108200510354185c5c700ad4280808080e0008410012205290000210c2005290008211120051035200320113701382003200c3701302003200837012820032004370120200341203602ac012003200341206a3602a80120062001200341a8016a109606024020012002490d00200f41246a21022006210103400240024020012d0000220541044b0d0002400240024020050e050400010204040b2001410c6a280200450d03200141086a28020010350c030b2001410c6a280200450d02200141086a28020010350c020b2001410c6a280200450d01200141086a28020010350c010b200141086a280200450d00200141046a28020010350b200141246a21012002415c6a22020d000b0b200a450d04200a41246c450d04200610350c040b2001410c6a2802002105200141086a28020021062001280204210a024020022d000120022d0000410047720d000240200541186c2201450d00200a20016a2102200a21010340200141086a350200422086200135020084200141146a3502004220862001410c6a350200841002200141186a22012002470d000b0b02402005450d00200541186c2102200a210103400240200141046a280200450d00200128020010350b0240200141106a280200450d002001410c6a28020010350b200141186a2101200241686a22020d000b0b2006450d04200641186c450d04200a10350c040b02402005450d00200541186c2102200a210103400240200141046a280200450d00200128020010350b0240200141106a280200450d002001410c6a28020010350b200141186a2101200241686a22020d000b0b02402006450d00200641186c450d00200a10350b20004200370308200041186a41023602000c110b2001410c6a2802002105200141086a28020021062001280204210a024020022d000120022d0000410047720d0002402005410c6c2201450d00200a20016a2102200a21010340200141086a35020042208620013502008410072001410c6a22012002470d000b0b02402005450d002005410c6c2102200a210103400240200141046a280200450d00200128020010350b2001410c6a2101200241746a22020d000b0b2006450d032006410c6c450d03200a10350c030b02402005450d002005410c6c2102200a210103400240200141046a280200450d00200128020010350b2001410c6a2101200241746a22020d000b0b02402006450d002006410c6c450d00200a10350b20004200370308200041186a41023602000c100b200141086a280200210520012802042106024020022d000120022d0000410047720d002001410c6a3502004220862006ad8410082005450d02200610350c020b02402005450d00200610350b20004200370308200041186a41023602000c0f0b4102210120022d00000d014101210520022d00014101470d012002411a6a2901002104200241196a2d00002101200241186a2d00002106200241166a2f0100210a200241156a2d00002107200241146a2d00002109200241126a2f0100210b200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021132002410c6a2d000021142002410a6a2f01002112200241086a2d00002110200241066a2f01002115200241056a2d00002116200241046a2d00002117200241026a2f010021182003200241096a2d00003a0027200320103a0026200320153b0124200320163a0023200320173a0022200320183b01202003200d3a002f2003200e3a002e2003200f3b012c200320133a002b200320143a002a200320123b0128200320013a0037200320063a00362003200a3b0134200320073a0033200320093a00322003200b3b013020032004370138200341b0016a41186a2004370300200341b0016a41106a2003290130370300200341b8016a2003290128370300200320032901203703b001200341d0016a200341b0016a108e02200341206a20032802d001220120032802d801108f0242002104420021084200210c42002111420021194200211a4200211b4200211c024020032903204201520d0020032d006c452105200341206a41106a290300211c200341c0006a2903002108200341206a41186a2903002104200341d0006a2903002111200341c8006a290300210c200341e0006a290300211a200341d8006a29030021192003290328211b0b024020032802d401450d00200110350b024020050d0041dcc2c7002102410f2105418080102106410321010c030b0240200c200484201984201b842011200884201a84201c8484500d0041ebc2c7002102411321054180800c2106410321010c030b200341206a41186a200341b0016a41186a290300370300200341206a41106a200341b0016a41106a290300370300200341206a41086a200341b0016a41086a290300370300200320032903b001370320200341d0016a200341206a10ed0320033502d80142208620032802d0012201ad84100720032802d401450d00200110350b42002104200042003703080c0e0b410021060b20004200370308200041206a20053602002000411c6a2002360200200041186a20064180801c712001723602000c0b0b1045000b1044000b103c000b20004200370308200041186a41023602000c070b02402009450d00200710350b0240200b450d00200d10350b41032107200e450d05200e410c6c450d05201210350c050b200b450d00200d10350b2009450d010b200710350b2002450d00200110350b4103210741fec2c700210a411d2102410221010b200141ff0171411074210102402005450d00200610350b20004200370308200041206a20023602002000411c6a200a360200200041186a20012007723602000b420121040b20002004370300200341e0016a24000b971f03077f037e127f230041a0036b22042400200128020821052001280204210620012802002107410221080240024002400240024002400240200241ff01710d00200341ff01714102470d002005410a4b0d0120044188016a41186a2209420037030020044188016a41106a220a420037030020044188016a41086a2202420037030020044200370388014193d1cb00ad4280808080a00184220b10012203290000210c20044180036a41086a2201200341086a2900003703002004200c370380032003103520022001290300370300200420042903800337038801419dd1cb00ad4280808080c00184220d10012203290000210c2001200341086a2900003703002004200c3703800320031035200a200429038003220c370300200441206a41086a220e2002290300370300200441206a41106a220f200c370300200441206a41186a221020012903003703002004200429038801370320200441206a10bd02220341ff01714102460d02410321082003410171450d020b419fc8ca0021114110210f410121122005450d030c020b4192c8ca002111410d210f41032108410221120c010b20094200370300200a4200370300200242003703002004420037038801200b10012203290000210c2001200341086a2900003703002004200c370380032003103520022001290300370300200420042903800337038801200d10012203290000210c2001200341086a2900003703002004200c3703800320031035200a200429038003370000200a41086a2001290300370000200e2002290300370300200f200a290300370300201020092903003703002004200429038801370320200441013a008801200441206aad4280808080800484220d20044188016aad42808080801084100220044180036a41186a2208420037030020044180036a41106a2213420037030020014200370300200442003703800341d1c4c700ad4280808080e0008410012202290000210c2001200241086a2900003703002004200c370380032002103541e7c4c700ad4280808080e0008410012203290000210c200441f0026a41086a2202200341086a2900003703002004200c3703f00220031035201320042903f002220c370300200441d0026a41086a22092001290300370300200441d0026a41106a220e200c370300200441d0026a41186a220f200229030037030020042004290380033703d002200441086a200441d0026a412010c001200428020c2110200428020821142008420037030020134200370300200142003703002004420037038003200b10012203290000210b2001200341086a2900003703002004200b370380032003103541e0caca00ad4280808080e0008410012203290000210b2002200341086a2900003703002004200b3703f00220031035201320042903f002220b37030020092001290300370300200e200b370300200f200229030037030020042004290380033703d00220044188016a200441d0026a10b6020240024020042802880122150d0020044100360218200442043703104104211541002102410021010c010b2004200429028c01220b37021420042015360210200b422088a72102200ba721010b2010410020141b2103024020022001470d00200441106a20024101109f0120042802102115200428021821020b2015200241c4006c6a220141003a000020012003360204200141036a200441206a41026a2d00003a0000200120042f00203b00012001200429028801370208200141106a20044188016a41086a2216290200370200200141186a20044188016a41106a2217290200370200200141206a20044188016a41186a290200370200200141286a20044188016a41206a290200370200200141306a20044188016a41286a290200370200200141386a20044188016a41306a290200370200200141c0006a20044188016a41386a2802003602002004200241016a22183602182007200541f0006c22016a211902400240024020050d00200721080c010b200741f4006a2109200141907f6a210e41d1c4c700ad4280808080e00084210c20072108024003402008280204211a2008280200210320044188016a200841086a41e800109d081a200841f0006a2108201a450d02200441206a20044188016a41e800109d081a2004201a36028c0120042003360288012016200441206a41e800109d081a20044180036a41186a221b420037030020044180036a41106a221c420037030020044180036a41086a221042003703002004420037038003200c10012201290000210b2010200141086a2900003703002004200b370380032001103541e7c4c700ad4280808080e0008410012201290000210b200441f0026a41086a2202200141086a2900003703002004200b3703f00220011035201320042903f002370000201341086a2002290300370000200441d0026a41086a221d2010290300370300200441d0026a41106a221e201c290300370300200441d0026a41186a221f201b29030037030020042004290380033703d0022004200441d0026a412010c0012004280200210120042802042102200441d0026a20044188016a10d003410c210f024020030d00410321124186c8ca0021110c020b024020032002410020011b22014d0d004104211241fac7ca0021110c020b20044180036a2003417f6a10d103024020044180036a2017412010a008450d004100211241afc8ca0021114112210f0c020b0240200341002001417b6a2202200220014b1b4f0d004106211241dec7ca0021114108210f0c020b0240024020152015201841c4006c22026a460d00201541016a2101034002402001417f6a2d00004101470d0041012114200441d0026a2001460d032001200441d0026a412010a008450d030b200141c4006a2101200241bc7f6a22020d000b0b410021140b20044180036a200310d10320044180036a200441d0026a412010a00821014105211241e6c7ca0021114114210f20140d012001450d01200441f8016a41086a220f200441b0026a41086a2202290200370300200441f8016a41106a2214200441b0026a41106a22032f01003b0100200420042f018e023b018c02200420042902b0023703f80120044190026a20044188016a10d003200441b0026a41186a221142003703002003420037030020024200370300200442003703b002201f4200370300201e4200370300201d4200370300200442003703d002024041c80010332201450d0020044180036a10d004200141186a201b290300370200200141106a201c290300370200200141086a201029030037020020012004290380033702002001410236022020014101360244200120042903d0023700242001412c6a201d290300370000200141346a201e2903003700002001413c6a201f290300370000200420013602f00220044282808080203702f402200441f0026a10ab01201b2011290300370300201c200329030037030020102002290300370300200420042903b0023703800320044180036a10d304201020044190026a41086a290300370300201c20044190026a41106a290300370300201b20044190026a41186a290300370300201d200f290300370300201e20142f01003b0100200420042903900237038003200420042f018c023b01b002200420042903f8013703d002024020182004280214470d00200441106a20184101109f01200428021821180b20042802102215201841c4006c6a220141013a00002001200429038003370001200141003a0021200120042f01b0023b0022200120042903d002370030200141096a2010290300370000200141116a201c290300370000200141196a201b290300370000200141386a201d290300370000200141c0006a201e2f01003b00002004201841016a221836021802402004280294012201450d00200141246c2102201a210103400240024020012d0000220341044b0d0002400240024020030e050400010204040b2001410c6a280200450d03200141086a28020010350c030b2001410c6a280200450d02200141086a28020010350c020b2001410c6a280200450d01200141086a28020010350c010b200141086a280200450d00200141046a28020010350b200141246a21012002415c6a22020d000b0b02402004280290012201450d00200141246c450d00201a10350b200e41907f6a210e200941f0006a210920082019470d010c040b0b103c000b02402004280294012201450d00200141246c2102201a210103400240024020012d0000220341044b0d0002400240024020030e050400010204040b2001410c6a280200450d03200141086a28020010350c030b2001410c6a280200450d02200141086a28020010350c020b2001410c6a280200450d01200141086a28020010350c010b200141086a280200450d00200141046a28020010350b200141246a21012002415c6a22020d000b0b02402004280290012201450d00200141246c450d00201a10350b024020192008460d000340200910b1030240200941046a2802002201450d00200141246c450d00200928020010350b200941f0006a2109200e41907f6a220e0d000b0b02402006450d00200641f0006c450d00200710350b024020042802142201450d00200141c4006c450d00201510350b410321080c040b20192008460d002007200541f0006c6a210303402008220141046a220210b103200141f0006a21080240200141086a2802002201450d00200141246c450d00200228020010350b20032008470d000b0b02402006450d00200641f0006c450d00200710350b20044188016a41186a2208420037030020044188016a41106a2209420037030020044188016a41086a2202420037030020044200370388014193d1cb00ad4280808080a0018410012203290000210b20044180036a41086a2201200341086a2900003703002004200b37038003200310352002200129030037030020042004290380033703880141e0caca00ad4280808080e0008410012203290000210b2001200341086a2900003703002004200b3703800320031035200a200429038003370000200a41086a2001290300370000200441206a41086a2002290300370300200441206a41106a2009290300370300200441206a41186a2008290300370300200420042903880137032020044188016a2015201810e006200d2004350290014220862004280288012201ad8410020240200428028c01450d00200110350b024020042802142201450d00200141c4006c450d00201510350b4200210b0c030b200541f0006c2102200741046a21010340200110b1030240200141046a2802002203450d00200341246c450d00200128020010350b200141f0006a2101200241907f6a22020d000b0b2006450d00200641f0006c450d00200710350b200041206a200f3602002000411c6a2011360200200041186a2012411074200872418008723602004201210b0b2000200b37030020004200370308200441a0036a24000be81c041c7f017e067f017e230041e0066b220324000240024002400240024002400240024002400240024020012802002204450d0020032001410c6a418001109d0821052001280204210602400240024020022d00000d0020022d00014101460d010b02402006450d00200410350b41022105410021020c010b200241196a2d00002101200241186a2d00002107200241166a2f01002108200241156a2d00002109200241146a2d0000210a200241126a2f0100210b200241116a2d0000210c200241106a2d0000210d2002410e6a2f0100210e2002410d6a2d0000210f2002410c6a2d000021102002410a6a2f01002111200241096a2d00002112200241086a2d00002113200241066a2f01002114200241056a2d00002115200241046a2d00002116200241026a2f0100211720052002411a6a29010037039801200520013a009701200520073a009601200520083b019401200520093a0093012005200a3a0092012005200b3b0190012005200c3a008f012005200d3a008e012005200e3b018c012005200f3a008b01200520103a008a01200520113b018801200520123a008701200520133a008601200520143b018401200520153a008301200520163a008201200520173b018001200541a0016a2005418001109d081a200541c0036a41186a200529039801370300200541c0036a41106a200529039001370300200541c8036a20052903880137030020052005290380013703c003200541d8056a200541c0036a10fc010240024020052d00d8054101470d00200541ef046a2202200541f1056a290000370000200541d8046a41106a2201200541ea056a290100370300200541a9026a200541e2056a290100370000200541b1026a2001290300370000200541a0026a41186a2002290000370000200520052d00d9053a00a002200520052901da053700a102200541c0026a200541a0016a418001109d081a200541c8046a200541a0026a10dd06200541d8056a20052802c804220120052802d00410c10220052d00d8052102200541d8046a200541d8056a410172418001109d081a0240024020024101460d00200541003a00c0030c010b200541013a00c003200541c0036a410172200541d8046a418001109d081a0b024020052802cc04450d00200110350b200541c0026a41206a211820054180036a2119200541a0036a211a200541e1036a211b20054181046a211c200541a1046a211d200541c0036a410172211e4170210803404100210141b0b4cc0021070240024002400240200841c4e2c6006a280000220241e6e485f3064a220b0d00200241e2c289ab06460d01200241e1ea91cb06470d0341202101201a21070c030b200241e9dabdf306460d01200241e7e485f306470d0241202101200541c0026a21070c020b41202101201821070c010b41202101201921070b200520013602e005200520073602dc05200520023602d805200541d8046a200541d8056a10f706200541d8056a20052802d804220a20052802e00410d50120052802dc0421090240024020052d00d8054101470d0020052900f105211f20052d00f005210c20052d00ef05210d20052f00ed05210e20052d00ec05210f20052d00eb05211020052f00e905211120052d00e805211220052d00e705211320052f00e505211420052d00e405211520052d00e305211620052f00e105211720052d00e005212020052d00df05212120052f00dd05212220052d00dc05212320052d00db05212420052f00d905212502402009450d00200a10350b2005201f3703f0052005200c3a00ef052005200d3a00ee052005200e3b01ec052005200f3a00eb05200520103a00ea05200520113b01e805200520123a00e705200520133a00e605200520143b01e405200520153a00e305200520163a00e205200520173b01e005200520203a00df05200520213a00de05200520223b01dc05200520233a00db05200520243a00da05200520253b01d805200541d8056a200541a0026a412010a008450d0141b193ca00ad211f4280808080d00121264180800821050c040b2009450d00200a10350b0240024020052d00c0034101470d004100210941b0b4cc00210a0240024002400240200b0d00200241e2c289ab06460d01200241e1ea91cb06470d0341202109201d210a0c030b200241e9dabdf306460d01200241e7e485f306470d0241202109201e210a0c020b41202109201b210a0c010b41202109201c210a0b024020012009470d002007200a460d022007200a200110a008450d020b200520093602e0052005200a3602dc05200520023602d805200541d8046a200541d8056a10f70620053502e00442208620052802d8042209ad84100720052802dc04450d00200910350b200520013602e005200520073602dc05200520023602d805200541d8046a200541d8056a10f70620052802d804210120053502e004211f412010332202450d0e200220052903a002370000200241186a200541a0026a41186a290300370000200241106a200541a0026a41106a290300370000200241086a200541a0026a41086a290300370000201f4220862001ad842002ad428080808080048410022002103520052802dc04450d00200110350b200841046a22080d000b200541d8056a200541a0026a10dd0620053502e005211f20052802d8052101412010332202450d0d200220052903c002370000200241186a200541c0026a41186a290300370000200241106a200541c0026a41106a290300370000200241086a200541c0026a41086a2903003700002002412041c00010372202450d0d200220052903e002370020200241386a200541c0026a41386a290300370000200241306a200541c0026a41306a290300370000200241286a200541c0026a41286a290300370000200241c00041800110372202450d0d2002200529038003370040200241d8006a200541c0026a41d8006a290300370000200241d0006a200541c0026a41d0006a290300370000200241c8006a200541c0026a41c8006a290300370000200220052903a003370060200241e8006a200541c0026a41e8006a290300370000200241f0006a200541c0026a41f0006a290300370000200241f8006a200541c0026a41f8006a290300370000201f4220862001ad842002ad4280808080801084100220021035024020052802dc05450d00200110350b024020052d00c0030d0020054180016a108d020b2006450d04200410350c040b41be93ca00ad211f4280808080f00221264180800421050b201f42ffffffff0f83211f20054180800c71210502402006450d00200410350b2026201f84211f2005418012722102410321050b200042003703082000411c6a201f370200200041186a20022005723602000c070b4102210520022d00000d0420022d00014101470d042002411a6a290100211f200241196a2d00002105200241186a2d00002101200241166a2f01002107200241156a2d00002108200241146a2d00002109200241126a2f0100210a200241116a2d0000210b200241106a2d000021042002410e6a2f0100210c2002410d6a2d0000210d2002410c6a2d0000210e2002410a6a2f0100210f200241086a2d00002110200241066a2f01002111200241056a2d00002112200241046a2d00002113200241026a2f010021142003200241096a2d00003a0007200320103a0006200320113b0104200320123a0003200320133a0002200320143b01002003200b3a000f200320043a000e2003200c3b010c2003200d3a000b2003200e3a000a2003200f3b0108200320053a0017200320013a0016200320073b0114200320083a0013200320093a00122003200a3b01102003201f370318200341c0036a41186a201f370300200341c0036a41106a2003290310370300200341c8036a2003290308370300200320032903003703c003200341d8056a200341c0036a10fc0120032d00d8054101470d02200341ef046a2205200341f1056a290000370000200341d8046a41106a2202200341ea056a290100370300200341a9016a200341e2056a290100370000200341b1016a2002290300370000200341a0016a41186a2005290000370000200320032d00d9053a00a001200320032901da053700a101200341a0026a200341a0016a10dd06200341d8056a20032802a002220520032802a802220110c102024020032d00d8052202450d002001ad4220862005ad8410070b20032d00d9052101200341d8046a200341d8056a41027241ff00109d081a200341d8056a200341d8046a41ff00109d081a20024101470d01200341c0026a200341d8056a41ff00109d081a024020032802a402450d00200510350b200320013a00c003200341c0036a410172200341c0026a41ff00109d081a200341e0056a4120360200200341e7e485f3063602d8052003200341c0036a3602dc05200341d8046a200341d8056a10f70620033502e00442208620032802d8042205ad841007024020032802dc04450d00200510350b200341e2c289ab063602d805200341203602e0052003200341c0036a41206a3602dc05200341d8046a200341d8056a10f70620033502e00442208620032802d8042205ad841007024020032802dc04450d00200510350b200341203602e005200320034180046a3602dc05200341e9dabdf3063602d805200341d8046a200341d8056a10f70620033502e00442208620032802d8042205ad841007024020032802dc04450d00200510350b200341203602e0052003200341a0046a3602dc05200341e1ea91cb063602d805200341d8046a200341d8056a10f70620033502e00442208620032802d8042205ad841007024020032802dc04450d00200510350b20031099020b4200211f200042003703080c060b024020032802a402450d00200510350b4180920c21024280808080e000211f41ab93ca0021050c010b4180920421024280808080f002211f41be93ca0021050b201f2005ad84211f410321050c010b410021020b200042003703082000411c6a201f370200200041186a20022005723602000b4201211f0b2000201f370300200341e0066a24000f0b1045000b103c000bf75d06067f017e027f017e0d7f047e230041a0046b2203240002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e06000102030405000b200341e4016a4101360200200342013702d401200341e8d4ca003602d001200341043602ac012003419cd5ca003602a8012003200341a8016a3602e001200341d0016a41b0b4cc00104c000b2001412c6a2802002104200141286a2802002105200141246a280200210620012d00012107200341e0006a41186a2001411a6a290000370300200341e0006a41106a200141126a290000370300200341e0006a41086a2001410a6a2900003703002003200141026a290000370360024020022d000120022d0000410047720d002006200410ac06200341d0016a41186a4200370300200341d0016a41106a22024200370300200341d0016a41086a22014200370300200342003703d00141dad5ca00ad4280808080b002841001220829000021092001200841086a290000370300200320093703d001200810354189eaca00ad4280808080f00084100122082900002109200341306a41086a220a200841086a290000370300200320093703302008103520022003290330220937030020034180016a41086a200129030037030020034180016a41106a200937030020034180016a41186a200a290300370300200320032903d00137038001200341d0016a20034180016a10fe01200341d0016a2006200420032802d0012201410120011b220820032902d401420020011b2209422088a710a6022002280200210220032802d401210120032802d001210a20032802dc01220b200341e4016a2802002006200410a7020240200241ffffff3f71450d00200b10350b0240200141ffffff3f71450d00200a10350b20034180046a41186a2202200341e0006a41186a29030037030020034180046a41106a2201200341e0006a41106a29030037030020034180046a41086a2204200341e0006a41086a290300370300200320032903603703800402400240200741ff01710d0020034180016a41186a420037030020034180016a41106a2207420037030020034180016a41086a22014200370300200342003703800141dad5ca00ad4280808080b0028410012204290000210c200341d0006a41086a2202200441086a2900003703002003200c37035020041035200120022903003703002003200329035037038001419cdfca00ad4280808080d0008410012204290000210c2002200441086a2900003703002003200c3703502004103520072003290350220c370300200341a8016a41086a2001290300370300200341a8016a41106a200c370300200341a8016a41186a200229030037030020032003290380013703a801200341a8016aad428080808080048410070c010b200341a8016a41186a2002290300370300200341a8016a41106a2001290300370300200341a8016a41086a200429030037030020032003290380043703a801200341306a41186a4200370300200341306a41106a22074200370300200341306a41086a220242003703002003420037033041dad5ca00ad4280808080b0028410012201290000210c200341d0016a41086a2204200141086a2900003703002003200c3703d0012001103520022004290300370300200320032903d001370330419cdfca00ad4280808080d0008410012201290000210c20034180016a41086a220a200141086a2900003703002003200c37038001200110352007200329038001220c37030020042002290300370300200341d0016a41106a200c370300200341d0016a41186a200a290300370300200320032903303703d001412010332202450d06200220032903a801370000200241186a200341a8016a41186a290300370000200241106a200341a8016a41106a290300370000200241086a200341a8016a41086a290300370000200341d0016aad42808080808004842002ad42808080808004841002200210350b0240200942ffffff3f83500d00200810350b200541ffffff3f71450d0f200610350c0f0b0240200541ffffff3f71450d00200610350b20004200370308200041186a4102360200420121090c0f0b200141046a280200210520032002411a6a290100370398012003200241026a2901003703800120032002410a6a290100370388012003200241126a290100370390010240024020022d00014101470d0020022d000041ff01710d00200341e0006a41186a20034180016a41186a2206290300370300200341e0006a41106a20034180016a41106a2204290300370300200341e0006a41086a20034180016a41086a22072903003703002003200329038001370360200341d0016a41186a4200370300200341d0016a41106a22084200370300200341d0016a41086a22024200370300200342003703d00141dad5ca00ad4280808080b002841001220129000021092002200141086a290000370300200320093703d001200110354189eaca00ad4280808080f00084100122012900002109200341306a41086a220a200141086a290000370300200320093703302001103520082003290330220937030020072002290300370300200420093703002006200a290300370300200320032903d00137038001200341d0016a20034180016a10fe0120032902d401420020032802d00122021b2209422088a741057421012002410120021b2207210202400340024020010d00410021040c020b41012104200341e0006a2002460d01200141606a21012002200341e0006a412010a0082106200241206a210220060d000b0b0240200942ffffff3f83500d00200710350b41831621022004450d01200341003602d801200342013703d0012005200341d0016a10af0320032802d401210120034180046a41186a220620033502d80142208620032802d0012208ad841009220241186a29000037030020034180046a41106a2204200241106a29000037030020034180046a41086a2207200241086a29000037030020032002290000370380042002103502402001450d00200810350b200341d0016a200541b002109d081a200341a8016a410d6a200341e0006a41086a290300370000200341a8016a41156a200341e0006a41106a290300370000200341a8016a411d6a200341e0006a41186a290300370000200341013a00ac01200320032903603700ad01200341013a00a80120034180016a200341d0016a200341a8016a10ac032003290380012109200341d0016a410d6a2007290300370000200341d0016a41156a2004290300370000200341d0016a411d6a2006290300370000200341f5016a2009503a0000200341053a00d401200341073a00d00120032003290380043700d50141b0b4cc004100200341d0016a10d401200510350c0f0b41821621020b200510ba0220051035200041206a41093602002000411c6a41f2dfca00360200200041186a200236020020004200370308420121090c0e0b200141086a2802002105200141046a280200210d2002411a6a2901002109200241196a2d00002106200241186a2d00002104200241166a2f01002107200241156a2d00002108200241146a2d0000210a200241126a2f0100210b200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241086a2d00002115200241066a2f01002116200241056a2d00002117200241046a2d00002118200241026a2f0100211941012101024020022d00000d0020022d000141014721010b200320093703c001200320063a00bf01200320043a00be01200320073b01bc01200320083a00bb012003200a3a00ba012003200b3b01b8012003200e3a00b7012003200f3a00b601200320103b01b401200320113a00b301200320123a00b201200320133b01b001200320143a00af01200320153a00ae01200320163b01ac01200320173a00ab01200320183a00aa01200320193b01a801024020010d00200341e0006a41186a200341a8016a41186a290300370300200341e0006a41106a200341a8016a41106a290300370300200341e0006a41086a200341a8016a41086a290300370300200320032903a801370360200341d0016a41186a4200370300200341d0016a41106a22074200370300200341d0016a41086a22024200370300200342003703d00141dad5ca00ad4280808080b002841001220129000021092002200141086a290000370300200320093703d001200110354189eaca00ad4280808080f00084100122012900002109200341306a41086a2206200141086a290000370300200320093703302001103520072003290330220937030020034180016a41086a200229030037030020034180016a41106a200937030020034180016a41186a2006290300370300200320032903d00137038001200341d0016a20034180016a10fe0120032902d401420020032802d00122021b2209422088a741057421012002410120021b2208210202400340024020010d00410021040c020b41012104200341e0006a2002460d01200141606a21012002200341e0006a412010a0082106200241206a210220060d000b0b0240200942ffffff3f83500d00200810350b41032102024020040d0041f2dfca0021014109210641801621040c0c0b200341003602d801200342013703d0012005200341d0016a10af0320032802d401210620034180046a41186a220420033502d80142208620032802d001220bad841009220141186a29000037030020034180046a41106a2208200141106a29000037030020034180046a41086a220a200141086a29000037030020032001290000370380042001103502402006450d00200b10350b200341d0016a41186a2004290300370300200341d0016a41106a2008290300370300200341d0016a41086a200a29030037030020032003290380043703d001200341a8016a200341d0016a109907200341206a20032802a801220620032802b00141b0b4cc0041004100108a0220032802202101024020032802ac01450d00200610350b20014101460d040240200d4102490d0020034180016a41186a2208420037030020034180016a41106a2206420037030020034180016a41086a22014200370300200342003703800141dad5ca00ad4280808080b00284220910012204290000210c200341d0006a41086a2202200441086a2900003703002003200c37035020041035200120022903003703002003200329035037038001418ef0cb00ad4280808080d00184220c10012204290000211a2002200441086a2900003703002003201a3703502004103520062003290350221a370300200341306a41086a22042001290300370300200341306a41106a220a201a370300200341306a41186a220b20022903003703002003200329038001370330200341186a200341306a412010c001200328021c210f20032802182110200842003703002006420037030020014200370300200342003703800120091001220e290000211a2002200e41086a2900003703002003201a370350200e1035200120022903003703002003200329035037038001200c1001220e290000211a2002200e41086a2900003703002003201a370350200e103520062003290350221a37030020042001290300370300200a201a370300200b20022903003703002003200329038001370330200341106a200341306a412010c0012003280210211120032802142112200842003703002006420037030020014200370300200342003703800120091001220e290000211a2002200e41086a2900003703002003201a370350200e1035200120022903003703002003200329035037038001200c1001220e290000210c2002200e41086a2900003703002003200c370350200e103520062003290350220c37030020042001290300370300200a200c370300200b20022903003703002003200329038001370330410121022003201241016a410120111b3602d001200341306aad4280808080800484200341d0016aad4280808080c000841002200341d0016a41186a220e4200370300200341d0016a41106a22114200370300200341d0016a41086a220a4200370300200342003703d00120091001220b2900002109200a200b41086a290000370300200320093703d001200b10354180eaca00ad42808080809001841001220b29000021092004200b41086a29000037030020032009370330200b103520072003290330370000200741086a20042903003700002001200a290300370300200620112903003703002008200e290300370300200320032903d00137038001200341d0016a20034180016a412010b5020240024020032802d00122010d00200341003602b001200342013703a8014100210a410021060c010b200320032902d40122093702ac01200320013602a8012009422088a721062009a7210a200121020b200341306a41186a220b20034180046a41186a290300370300200341306a41106a220420034180046a41106a290300370300200341306a41086a220120034180046a41086a290300370300200320032903800437033002402006200a470d00200341a8016a200a4101108a0120032802ac01210a20032802a801210220032802b00121060b200220064105746a22082003290330370000200841186a200b290300370000200841106a2004290300370000200841086a20012903003700002003200641016a220e3602b001200b420037030020044200370300200142003703002003420037033041dad5ca00ad4280808080b00284100122082900002109200341d0006a41086a2206200841086a290000370300200320093703502008103520012006290300370300200320032903503703304180eaca00ad42808080809001841001220829000021092006200841086a290000370300200320093703502008103520042003290350220937030020034180016a41086a200129030037030020034180016a41106a200937030020034180016a41186a200629030037030020032003290330370380010240024020020d0020034180016aad428080808080048410070c010b200341203602d401200320034180016a3602d0012002200e200341d0016a10c504200a41ffffff3f71450d00200210350b200341d0016a200541b002109d081a200341a8016a41186a20034180046a41186a290300370300200341a8016a41106a20034180046a41106a290300370300200341a8016a41086a20034180046a41086a29030037030020032003290380043703a80120034180016a200341a8016a10990720032802800121022003350288012109200341003602b001200342013703a801200341d0016a200341a8016a10af0320032802ac01210120094220862002ad8420033502b00142208620032802a8012206ad84100202402001450d00200610350b0240200328028401450d00200210350b200341d0016a10ba02200341d0016a41186a22064200370300200341d0016a41106a22044200370300200341d0016a41086a22024200370300200342003703d00141d1c4c700ad4280808080e000841001220129000021092002200141086a290000370300200320093703d0012001103541e7c4c700ad4280808080e00084100122012900002109200341306a41086a2208200141086a290000370300200320093703302001103520072003290330370000200741086a200829030037000020034180016a41086a200229030037030020034180016a41106a200429030037030020034180016a41186a2006290300370300200320032903d00137038001200341086a20034180016a412010c001200328020c210120032802082106412010332202450d0620022003290360370000200241186a200341e0006a41186a290300370000200241106a200341e0006a41106a290300370000200241086a200341e0006a41086a290300370000200341ec016a4100360200200341dc016a428180808010370200200320014180e5086a4180e50820061b3602f001200342013702e401200320023602d8012003200d3602d4012003200f410020101b22063602d001200341a8016a41186a20034180046a41186a290300370300200341a8016a41106a20034180046a41106a290300370300200341a8016a41086a20034180046a41086a29030037030020032003290380043703a80120034180016a200341a8016a108c07200328028001210120032003280288013602ac01200320013602a801200341d0016a200341a8016a1092070240200328028401450d00200110350b20021035200341dd016a200341e0006a41086a290300370000200341e5016a200341e0006a41106a290300370000200341ed016a200341e0006a41186a290300370000200341f5016a200329038004370000200341fd016a20034180046a41086a29030037000020034185026a20034180046a41106a2903003700002003418d026a20034180046a41186a2903003700002003419c026a200d36020020034198026a2006360200200341003a00d401200341073a00d001200320032903603700d501200341d0016a21020c0d0b200341d0016a41186a22064200370300200341d0016a41106a22044200370300200341d0016a41086a22024200370300200342003703d00141dad5ca00ad4280808080b002841001220129000021092002200141086a290000370300200320093703d001200110354189eaca00ad4280808080f00084100122012900002109200341306a41086a2208200141086a290000370300200320093703302001103520072003290330370000200741086a200829030037000020034180016a41086a200229030037030020034180016a41106a200429030037030020034180016a41186a2006290300370300200320032903d00137038001200341a8016a20034180016a10fe010240024020032802a80122010d00410021020c010b20032902ac012209422088a72102200942ffffff3f83500d00200110350b200341d0016a200541b002109d081a200341b4016a2002360200200341a8016a41086a4101360200200341003a00ac01200341013a00a80120034180016a200341d0016a200341a8016a10ac032003290380012109200341dd016a20034180046a41086a290300370000200341e5016a20034190046a290300370000200341ed016a20034198046a290300370000200341f5016a2009503a0000200341043a00d401200341073a00d00120032003290380043700d501200341d0016a21020c0c0b4102210241801621040c0a0b200141216a2d0000210d200141246a2802002119200341e0006a41186a200141196a290000370300200341e0006a41106a200141116a290000370300200341e0006a41086a200141096a290000370300200320012900013703602002411a6a2901002109200241196a2d00002106200241186a2d00002104200241166a2f01002105200241156a2d00002107200241146a2d00002108200241126a2f0100210a200241116a2d0000210b200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241086a2d00002114200241066a2f01002115200241056a2d00002116200241046a2d00002117200241026a2f0100211841012101024020022d00000d0020022d000141014721010b200320093703c001200320063a00bf01200320043a00be01200320053b01bc01200320073a00bb01200320083a00ba012003200a3b01b8012003200b3a00b7012003200e3a00b6012003200f3b01b401200320103a00b301200320113a00b201200320123b01b001200320133a00af01200320143a00ae01200320153b01ac01200320163a00ab01200320173a00aa01200320183b01a801024020010d0020034180046a41186a200341a8016a41186a29030037030020034180046a41106a200341a8016a41106a29030037030020034180046a41086a200341a8016a41086a290300370300200320032903a80137038004200341d0016a41186a4200370300200341d0016a41106a22054200370300200341d0016a41086a22024200370300200342003703d00141dad5ca00ad4280808080b002841001220129000021092002200141086a290000370300200320093703d001200110354189eaca00ad4280808080f00084100122012900002109200341306a41086a2206200141086a290000370300200320093703302001103520052003290330220937030020034180016a41086a200229030037030020034180016a41106a200937030020034180016a41186a2006290300370300200320032903d00137038001200341d0016a20034180016a10fe0120032902d401420020032802d00122021b2209422088a741057421012002410120021b2207210202400340024020010d00410021040c020b4101210420034180046a2002460d01200141606a2101200220034180046a412010a0082106200241206a210220060d000b0b0240200942ffffff3f83500d00200710350b41032102024020040d004100210141f2dfca002106410921040c0a0b20034180016a200341e0006a109a07200341d0016a200328028001220620032802880110de0220032802840121010240024020032802d8012208450d00200341f0016a2802002102200341ec016a280200210b200341e8016a2802002110200341e4016a280200210f200341e0016a280200210a20032802dc01210e20032903d001210902402001450d00200610350b200341c4016a200b360200200341c0016a2010360200200341b8016a200a360200200341b4016a200e360200200320023602c8012003200f3602bc01200320083602b001200320093703a80120192009a7460d0141c8dfca002106410a21044180800c21010c0a0b02402001450d00200610350b41808008210141d2dfca002106410f21040c0a0b4100210141002106410021110240200a450d00200a410574210441002106200821020240034020034180046a2002460d012006200220034180046a412010a00822074100476a21062007450d01200241206a2102200441606a22040d000b410021110c010b410121110b410021020240200b450d00200b410574210441002101200f21020240034020034180046a2002460d012001200220034180046a412010a00822074100476a21012007450d01200241206a2102200441606a22040d000b410021020c010b410121020b024002400240200d41ff01710d002002450d010c0a0b20110d09200341306a41186a220420034180046a41186a290300370300200341306a41106a220720034180046a41106a290300370300200341306a41086a220b20034180046a41086a29030037030020032003290380043703300240200a200e470d00200341b0016a200e4101108a0120032802b801210a20032802b00121080b2008200a4105746a22062003290330370000200641186a2004290300370000200641106a2007290300370000200641086a200b2903003700002003200a41016a22073602b80120032802c40121042002450d01200420014d0d0720032802bc0122062004417f6a22044105746a220229000021092002290008210c2002290010211a200241186a290000211b200320043602c401200620014105746a220241186a201b3700002002201a3700102002200c370008200220093700000c010b20034180016a41186a220120034180046a41186a29030037030020034180016a41106a220420034180046a41106a29030037030020034180016a41086a220720034180046a41086a2903003703002003200329038004370380010240200b2010470d00200341bc016a20104101108a0120032802c401210b20032802bc01210f0b200f200b4105746a2202200329038001370000200241186a2001290300370000200241106a2004290300370000200241086a2007290300370000200320032802c40141016a22043602c40120032802b80121072011450d00200720064d0d0720032802b00122012007417f6a22074105746a220229000021092002290008210c2002290010211a200241186a290000211b200320073602b801200120064105746a220241186a201b3700002002201a3700102002200c370008200220093700000b200341f5016a2003290360370000200341dd016a20034180046a41086a290300370000200341e5016a20034180046a41106a290300370000200341ed016a20034180046a41186a290300370000200341fd016a200341e0006a41086a29030037000020034185026a200341e0006a41106a2903003700002003418d026a200341e0006a41186a290300370000200341013a00d401200341073a00d00120032003290380043700d5012003419c026a200436020020034198026a200736020020034195026a200d3a00004100210241b0b4cc004100200341d0016a10d401200341d0016a41186a22084200370300200341d0016a41106a220a4200370300200341d0016a41086a22014200370300200342003703d00141dad5ca00ad4280808080b002841001220629000021092001200641086a290000370300200320093703d001200610354189eaca00ad4280808080f00084100122062900002109200341306a41086a220b200641086a290000370300200320093703302006103520052003290330370000200541086a200b29030037000020034180016a41086a200129030037030020034180016a41106a200a29030037030020034180016a41186a2008290300370300200320032903d00137038001200341d0006a20034180016a10fe01024020032802502201450d0020032902542209422088a72102200942ffffff3f83500d00200110350b0240200720032802ac0122014f22060d004100200220046b2204200420024b1b2001490d00200341d0016a41206a200341a8016a41206a280200360200200341d0016a41186a200341a8016a41186a290300370300200341d0016a41106a200341a8016a41106a290300370300200341d0016a41086a200341a8016a41086a290300370300200320032903a8013703d00120034180016a200341e0006a109a072003280280012102200320032802880136023420032002360230200341d0016a200341306a1092070240200328028401450d00200210350b0240200341dc016a28020041ffffff3f71450d0020032802d80110350b200341e8016a28020041ffffff3f71450d0d20032802e40110350c0d0b200341d0016a41206a200341a8016a41206a280200360200200341d0016a41186a200341a8016a41186a290300370300200341d0016a41106a200341a8016a41106a290300370300200341d0016a41086a200341a8016a41086a290300370300200320032903a8013703d00120034180016a41186a200341e0006a41186a29030037030020034180016a41106a200341e0006a41106a29030037030020034180016a41086a200341e0006a41086a290300370300200320032903603703800120062002200341d0016a20034180016a109b070c0c0b41002101410221020c080b200141246a280200210620034198046a200141196a29000037030020034190046a200141116a29000037030020034188046a200141096a2900003703002003200129000137038004410221010240024002400240024020022d00000d0020022d00014101470d00200341a8016a20034180046a109a07200341d0016a20032802a801220120032802b00110de0220032802ac012102024020032802d8012205450d00200341f0016a280200210b200341ec016a280200210e200341e8016a2802002107200341e4016a280200210f200341e0016a280200210a20032802dc01210820032903d001210902402002450d00200110350b20062009a7460d0241c8dfca002106410a21024180800c21040c030b02402002450d00200110350b410321010b418080082104410f210241d2dfca0021060c020b200341d0016a41186a4200370300200341d0016a41106a2210420037030041082102200341d0016a41086a22014200370300200342003703d00141d1c4c700ad4280808080e0008410012206290000210c2001200641086a2900003703002003200c3703d0012006103541e7c4c700ad4280808080e0008410012206290000210c200341306a41086a2204200641086a2900003703002003200c3703302006103520102003290330220c37030020034180016a41086a200129030037030020034180016a41106a2201200c37030020034180016a41186a22062004290300370300200320032903d00137038001200341286a20034180016a412010c001200328022c410020032802281b200b4f0d0241a1dfca0021064180801821040b0240200841ffffff3f71450d00200510350b0240200741ffffff3f71450d00200f10350b410321010b20004200370308200041206a20023602002000411c6a2006360200200041186a20044180801c7120017241801672360200420121090c0c0b2009422088210c200642003703002001420037030020034180016a41086a22024200370300200342003703800141dad5ca00ad4280808080b0028410012211290000211a200341d0006a41086a2204201141086a2900003703002003201a37035020111035200220042903003703002003200329035037038001419cdfca00ad4280808080d0008410012211290000211a2004201141086a2900003703002003201a3703502011103520012003290350221a370300200341306a41086a2002290300370300200341306a41106a201a370300200341306a41186a20042903003703002003200329038001370330200341d0016a200341306a412010d50120032d00d00121042006200341e9016a2900003703002001200341e1016a2900003703002002200341d9016a290000370300200320032900d101370380010240024020044101460d00410021040c010b200341a8016a41186a20034180016a41186a290300221a370300200341a8016a41106a20034180016a41106a290300221b370300200341a8016a41086a2002290300221c3703002003200329038001221d3703a801200341d0016a41186a201a370300200341d0016a41106a201b370300200341d0016a41086a201c3703002003201d3703d001200a4105742101200521020340024020010d00410021040c020b41012104200341d0016a2002460d01200141606a21012002200341d0016a412010a0082106200241206a210220060d000b0b200ca72106200341d0016a41186a22114200370300200341d0016a41106a22124200370300200341d0016a41086a22024200370300200342003703d00141dad5ca00ad4280808080b0028410012201290000210c2002200141086a2900003703002003200c3703d001200110354189eaca00ad4280808080f0008410012201290000210c200341306a41086a2213200141086a2900003703002003200c3703302001103520102003290330370000201041086a201329030037000020034180016a41086a200229030037030020034180016a41106a201229030037030020034180016a41186a2011290300370300200320032903d00137038001200341a8016a20034180016a10fe010240024020032802a80122010d00410021020c010b20032902ac01220c422088a72102200c42ffffff3f83500d00200110350b200341dd016a20034180046a41086a2201290300370000200341e5016a20034180046a41106a2210290300370000200341ed016a20034180046a41186a2211290300370000200341fc016a41002002200e200a6a6b221220041b200e6a360200200341f8016a2012410020041b200a6a2204360200200341063a00d401200341073a00d00120032003290380043700d50141b0b4cc004100200341d0016a10d401200341ec016a200e360200200341d0016a41186a2007360200200341d0016a41106a200a360200200341dc016a20083602002003200b3602f0012003200f3602e401200320053602d801200320093703d001200341a8016a41186a2011290300370300200341a8016a41106a2010290300370300200341a8016a41086a200129030037030020032003290380043703a801200420064f2002200341d0016a200341a8016a109b070c0a0b1045000b41e1dfca002101411121064180960421040c060b103c000b20012004104a000b20062007104a000b41bbdfca002106410d21044180801021010b0240200e41ffffff3f71450d00200810350b0240201041ffffff3f71450d00200f10350b410321020b20004200370308200041206a20043602002000411c6a2006360200200041186a20014180801c7120027241801672360200420121090c030b200510ba0220051035200041206a20063602002000411c6a2001360200200041186a200420027236020020004200370308420121090c020b41b0b4cc004100200210d401200510350b42002109200042003703080b20002009370300200341a0046a24000bf55c04097f027e0c7f047e230041a0046b2203240002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e06000102030405000b200341e4016a4101360200200342013702d401200341e8d4ca003602d001200341043602ac012003419cd5ca003602a8012003200341a8016a3602e001200341d0016a41b0b4cc00104c000b2001412c6a2802002104200141286a2802002105200141246a280200210620012d00012107200341e0006a41186a22082001411a6a290000370300200341e0006a41106a2209200141126a290000370300200341e0006a41086a220a2001410a6a2900003703002003200141026a290000370360024020022d000120022d0000410047720d002006200410ac06200341d0016a41186a4200370300200341d0016a41106a220b4200370300200341d0016a41086a22024200370300200342003703d00141c7d5ca00ad4280808080b00284220c10012201290000210d2002200141086a2900003703002003200d3703d001200110354189eaca00ad4280808080f0008410012201290000210d200341306a41086a220e200141086a2900003703002003200d37033020011035200b2003290330220d37030020034180016a41086a200229030037030020034180016a41106a200d37030020034180016a41186a200e290300370300200320032903d00137038001200341d0016a20034180016a10fe012006200420032802d0012202410120021b220b20032902d401420020021b220d422088a710ad0620034180046a41186a200829030037030020034180046a41106a200929030037030020034180046a41086a200a290300370300200320032903603703800402400240200741ff01710d0020034180016a41186a420037030020034180016a41106a2207420037030020034180016a41086a220142003703002003420037038001200c10012204290000210c200341d0006a41086a2202200441086a2900003703002003200c37035020041035200120022903003703002003200329035037038001419cdfca00ad4280808080d0008410012204290000210c2002200441086a2900003703002003200c3703502004103520072003290350220c370300200341a8016a41086a2001290300370300200341a8016a41106a200c370300200341a8016a41186a200229030037030020032003290380013703a801200341a8016aad428080808080048410070c010b200341a8016a41186a220720034180046a41186a290300370300200341a8016a41106a220820034180046a41106a290300370300200341a8016a41086a220920034180046a41086a29030037030020032003290380043703a801200341306a41186a4200370300200341306a41106a220a4200370300200341306a41086a2202420037030020034200370330200c10012201290000210c200341d0016a41086a2204200141086a2900003703002003200c3703d0012001103520022004290300370300200320032903d001370330419cdfca00ad4280808080d0008410012201290000210c20034180016a41086a220e200141086a2900003703002003200c3703800120011035200a200329038001220c37030020042002290300370300200341d0016a41106a200c370300200341d0016a41186a200e290300370300200320032903303703d001412010332202450d06200220032903a801370000200241186a2007290300370000200241106a2008290300370000200241086a2009290300370000200341d0016aad42808080808004842002ad42808080808004841002200210350b0240200d42ffffff3f83500d00200b10350b200541ffffff3f71450d0f200610350c0f0b0240200541ffffff3f71450d00200610350b20004200370308200041186a41023602004201210c0c0f0b200141046a280200210420032002411a6a290100370398012003200241026a2901003703800120032002410a6a290100370388012003200241126a290100370390010240024020022d00014101470d0020022d000041ff01710d00200341e0006a41186a20034180016a41186a2206290300370300200341e0006a41106a20034180016a41106a2205290300370300200341e0006a41086a20034180016a41086a22072903003703002003200329038001370360200341d0016a41186a4200370300200341d0016a41106a22084200370300200341d0016a41086a22024200370300200342003703d00141c7d5ca00ad4280808080b0028410012201290000210c2002200141086a2900003703002003200c3703d001200110354189eaca00ad4280808080f0008410012201290000210c200341306a41086a2209200141086a2900003703002003200c3703302001103520082003290330220c370300200720022903003703002005200c37030020062009290300370300200320032903d00137038001200341d0016a20034180016a10fe0120032902d401420020032802d00122021b220c422088a741057421012002410120021b2207210202400340024020010d00410021050c020b41012105200341e0006a2002460d01200141606a21012002200341e0006a412010a0082106200241206a210220060d000b0b0240200c42ffffff3f83500d00200710350b41831821022005450d01200341003602d801200342013703d0012004200341d0016a10af0320032802d401210120034180046a41186a220620033502d80142208620032802d0012208ad841009220241186a29000037030020034180046a41106a2205200241106a29000037030020034180046a41086a2207200241086a29000037030020032002290000370380042002103502402001450d00200810350b200341d0016a200441b002109d081a200341a8016a410d6a200341e0006a41086a290300370000200341a8016a41156a200341e0006a41106a290300370000200341a8016a411d6a200341e0006a41186a290300370000200341013a00ac01200320032903603700ad01200341023a00a80120034180016a200341d0016a200341a8016a10ac03200329038001210c200341d0016a410d6a2007290300370000200341d0016a41156a2005290300370000200341d0016a411d6a2006290300370000200341f5016a200c503a0000200341053a00d401200341083a00d00120032003290380043700d50141b0b4cc004100200341d0016a10d401200410350c0f0b41821821020b200410ba0220041035200041206a41093602002000411c6a41f2dfca00360200200041186a2002360200200042003703084201210c0c0e0b200141086a2802002104200141046a280200210f2002411a6a290100210c200241196a2d00002106200241186a2d00002105200241166a2f01002107200241156a2d00002108200241146a2d00002109200241126a2f0100210a200241116a2d0000210b200241106a2d0000210e2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241086a2d00002115200241066a2f01002116200241056a2d00002117200241046a2d00002118200241026a2f0100211941012101024020022d00000d0020022d000141014721010b2003200c3703c001200320063a00bf01200320053a00be01200320073b01bc01200320083a00bb01200320093a00ba012003200a3b01b8012003200b3a00b7012003200e3a00b601200320103b01b401200320113a00b301200320123a00b201200320133b01b001200320143a00af01200320153a00ae01200320163b01ac01200320173a00ab01200320183a00aa01200320193b01a801024020010d00200341e0006a41186a200341a8016a41186a290300370300200341e0006a41106a200341a8016a41106a290300370300200341e0006a41086a200341a8016a41086a290300370300200320032903a801370360200341d0016a41186a4200370300200341d0016a41106a22074200370300200341d0016a41086a22024200370300200342003703d00141c7d5ca00ad4280808080b0028410012201290000210c2002200141086a2900003703002003200c3703d001200110354189eaca00ad4280808080f0008410012201290000210c200341306a41086a2206200141086a2900003703002003200c3703302001103520072003290330220c37030020034180016a41086a200229030037030020034180016a41106a200c37030020034180016a41186a2006290300370300200320032903d00137038001200341d0016a20034180016a10fe0120032902d401420020032802d00122021b220c422088a741057421012002410120021b2208210202400340024020010d00410021050c020b41012105200341e0006a2002460d01200141606a21012002200341e0006a412010a0082106200241206a210220060d000b0b0240200c42ffffff3f83500d00200810350b41032102024020050d0041f2dfca0021014109210641801821050c0c0b200341003602d801200342013703d0012004200341d0016a10af0320032802d401210620034180046a41186a220520033502d80142208620032802d001220aad841009220141186a29000037030020034180046a41106a2208200141106a29000037030020034180046a41086a2209200141086a29000037030020032001290000370380042001103502402006450d00200a10350b200341d0016a41186a2005290300370300200341d0016a41106a2008290300370300200341d0016a41086a200929030037030020032003290380043703d001200341a8016a200341d0016a109d07200341206a20032802a801220620032802b00141b0b4cc0041004100108a0220032802202101024020032802ac01450d00200610350b20014101460d040240200f4102490d0020034180016a41186a2208420037030020034180016a41106a2206420037030020034180016a41086a22014200370300200342003703800141c7d5ca00ad4280808080b00284220c10012205290000210d200341d0006a41086a2202200541086a2900003703002003200d37035020051035200120022903003703002003200329035037038001418ef0cb00ad4280808080d00184220d10012205290000211a2002200541086a2900003703002003201a3703502005103520062003290350221a370300200341306a41086a22052001290300370300200341306a41106a2209201a370300200341306a41186a220a20022903003703002003200329038001370330200341186a200341306a412010c001200328021c210e200328021821102008420037030020064200370300200142003703002003420037038001200c1001220b290000211a2002200b41086a2900003703002003201a370350200b1035200120022903003703002003200329035037038001200d1001220b290000211a2002200b41086a2900003703002003201a370350200b103520062003290350221a370300200520012903003703002009201a370300200a20022903003703002003200329038001370330200341106a200341306a412010c00120032802102111200328021421122008420037030020064200370300200142003703002003420037038001200c1001220b290000211a2002200b41086a2900003703002003201a370350200b1035200120022903003703002003200329035037038001200d1001220b290000210d2002200b41086a2900003703002003200d370350200b103520062003290350220d370300200520012903003703002009200d370300200a20022903003703002003200329038001370330410121022003201241016a410120111b3602d001200341306aad4280808080800484200341d0016aad4280808080c000841002200341d0016a41186a220b4200370300200341d0016a41106a22114200370300200341d0016a41086a22094200370300200342003703d001200c1001220a290000210c2009200a41086a2900003703002003200c3703d001200a10354180eaca00ad42808080809001841001220a290000210c2005200a41086a2900003703002003200c370330200a103520072003290330370000200741086a200529030037000020012009290300370300200620112903003703002008200b290300370300200320032903d00137038001200341d0016a20034180016a412010b5020240024020032802d00122010d00200341003602b001200342013703a80141002109410021060c010b200320032902d401220c3702ac01200320013602a801200c422088a72106200ca72109200121020b200341306a41186a220a20034180046a41186a290300370300200341306a41106a220520034180046a41106a290300370300200341306a41086a220120034180046a41086a2903003703002003200329038004370330024020062009470d00200341a8016a20094101108a0120032802ac01210920032802a801210220032802b00121060b200220064105746a22082003290330370000200841186a200a290300370000200841106a2005290300370000200841086a20012903003700002003200641016a220b3602b001200a420037030020054200370300200142003703002003420037033041c7d5ca00ad4280808080b0028410012208290000210c200341d0006a41086a2206200841086a2900003703002003200c3703502008103520012006290300370300200320032903503703304180eaca00ad428080808090018410012208290000210c2006200841086a2900003703002003200c3703502008103520052003290350220c37030020034180016a41086a200129030037030020034180016a41106a200c37030020034180016a41186a200629030037030020032003290330370380010240024020020d0020034180016aad428080808080048410070c010b200341203602d401200320034180016a3602d0012002200b200341d0016a10c504200941ffffff3f71450d00200210350b200341d0016a200441b002109d081a200341a8016a41186a20034180046a41186a290300370300200341a8016a41106a20034180046a41106a290300370300200341a8016a41086a20034180046a41086a29030037030020032003290380043703a80120034180016a200341a8016a109d072003280280012102200335028801210c200341003602b001200342013703a801200341d0016a200341a8016a10af0320032802ac012101200c4220862002ad8420033502b00142208620032802a8012206ad84100202402001450d00200610350b0240200328028401450d00200210350b200341d0016a10ba02200341d0016a41186a22064200370300200341d0016a41106a22054200370300200341d0016a41086a22024200370300200342003703d00141d1c4c700ad4280808080e0008410012201290000210c2002200141086a2900003703002003200c3703d0012001103541e7c4c700ad4280808080e0008410012201290000210c200341306a41086a2208200141086a2900003703002003200c3703302001103520072003290330370000200741086a200829030037000020034180016a41086a200229030037030020034180016a41106a200529030037030020034180016a41186a2006290300370300200320032903d00137038001200341086a20034180016a412010c001200328020c210120032802082106412010332202450d0620022003290360370000200241186a200341e0006a41186a290300370000200241106a200341e0006a41106a290300370000200241086a200341e0006a41086a290300370000200341ec016a4100360200200341dc016a428180808010370200200320014180e5086a4180e50820061b3602f001200342013702e401200320023602d8012003200f3602d4012003200e410020101b22063602d001200341a8016a41186a20034180046a41186a290300370300200341a8016a41106a20034180046a41106a290300370300200341a8016a41086a20034180046a41086a29030037030020032003290380043703a80120034180016a200341a8016a108a07200328028001210120032003280288013602ac01200320013602a801200341d0016a200341a8016a1092070240200328028401450d00200110350b20021035200341e5016a200341e0006a41106a290300370000200341ed016a200341e0006a41186a290300370000200341f5016a20032903800437000020034185026a20034180046a41106a2903003700002003418d026a20034180046a41186a2903003700002003419c026a200f36020020034198026a2006360200200341083a00d001200341dd016a200341e0006a41086a290300370000200341fd016a20034180046a41086a290300370000200341003a00d401200320032903603700d501200341d0016a21020c0d0b200341d0016a41186a22064200370300200341d0016a41106a22054200370300200341d0016a41086a22024200370300200342003703d00141c7d5ca00ad4280808080b0028410012201290000210c2002200141086a2900003703002003200c3703d001200110354189eaca00ad4280808080f0008410012201290000210c200341306a41086a2208200141086a2900003703002003200c3703302001103520072003290330370000200741086a200829030037000020034180016a41086a200229030037030020034180016a41106a200529030037030020034180016a41186a2006290300370300200320032903d00137038001200341a8016a20034180016a10fe010240024020032802a80122010d00410021020c010b20032902ac01220c422088a72102200c42ffffff3f83500d00200110350b200341d0016a200441b002109d081a200341b4016a2002360200200341a8016a41086a4101360200200341003a00ac01200341023a00a80120034180016a200341d0016a200341a8016a10ac03200329038001210c200341dd016a20034180046a41086a290300370000200341e5016a20034190046a290300370000200341ed016a20034198046a290300370000200341f5016a200c503a0000200341043a00d401200341083a00d00120032003290380043700d501200341d0016a21020c0c0b4102210241801821050c0a0b200141216a2d0000210f200141246a2802002119200341e0006a41186a200141196a290000370300200341e0006a41106a200141116a290000370300200341e0006a41086a200141096a290000370300200320012900013703602002411a6a290100210c200241196a2d00002106200241186a2d00002105200241166a2f01002104200241156a2d00002107200241146a2d00002108200241126a2f01002109200241116a2d0000210a200241106a2d0000210b2002410e6a2f0100210e2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241086a2d00002114200241066a2f01002115200241056a2d00002116200241046a2d00002117200241026a2f0100211841012101024020022d00000d0020022d000141014721010b2003200c3703c001200320063a00bf01200320053a00be01200320043b01bc01200320073a00bb01200320083a00ba01200320093b01b8012003200a3a00b7012003200b3a00b6012003200e3b01b401200320103a00b301200320113a00b201200320123b01b001200320133a00af01200320143a00ae01200320153b01ac01200320163a00ab01200320173a00aa01200320183b01a801024020010d0020034180046a41186a200341a8016a41186a29030037030020034180046a41106a200341a8016a41106a29030037030020034180046a41086a200341a8016a41086a290300370300200320032903a80137038004200341d0016a41186a4200370300200341d0016a41106a22044200370300200341d0016a41086a22024200370300200342003703d00141c7d5ca00ad4280808080b0028410012201290000210c2002200141086a2900003703002003200c3703d001200110354189eaca00ad4280808080f0008410012201290000210c200341306a41086a2206200141086a2900003703002003200c3703302001103520042003290330220c37030020034180016a41086a200229030037030020034180016a41106a200c37030020034180016a41186a2006290300370300200320032903d00137038001200341d0016a20034180016a10fe0120032902d401420020032802d00122021b220c422088a741057421012002410120021b2207210202400340024020010d00410021050c020b4101210520034180046a2002460d01200141606a2101200220034180046a412010a0082106200241206a210220060d000b0b0240200c42ffffff3f83500d00200710350b41032102024020050d004100210141f2dfca002106410921050c0a0b20034180016a200341e0006a109e07200341d0016a200328028001220620032802880110de0220032802840121010240024020032802d8012208450d00200341f0016a2802002102200341ec016a280200210a200341e8016a2802002110200341e4016a280200210e200341e0016a280200210920032802dc01210b20032903d001210c02402001450d00200610350b200341c4016a200a360200200341c0016a2010360200200341b8016a2009360200200341b4016a200b360200200320023602c8012003200e3602bc01200320083602b0012003200c3703a8012019200ca7460d0141c8dfca002106410a21054180800c21010c0a0b02402001450d00200610350b41808008210141d2dfca002106410f21050c0a0b41002101410021064100211102402009450d002009410574210541002106200821020240034020034180046a2002460d012006200220034180046a412010a00822074100476a21062007450d01200241206a2102200541606a22050d000b410021110c010b410121110b410021020240200a450d00200a410574210541002101200e21020240034020034180046a2002460d012001200220034180046a412010a00822074100476a21012007450d01200241206a2102200541606a22050d000b410021020c010b410121020b024002400240200f41ff01710d002002450d010c0a0b20110d09200341306a41186a220520034180046a41186a290300370300200341306a41106a220720034180046a41106a290300370300200341306a41086a220a20034180046a41086a290300370300200320032903800437033002402009200b470d00200341b0016a200b4101108a0120032802b801210920032802b00121080b200820094105746a22062003290330370000200641186a2005290300370000200641106a2007290300370000200641086a200a2903003700002003200941016a22073602b80120032802c40121052002450d01200520014d0d0720032802bc0122062005417f6a22054105746a2202290000210c2002290008210d2002290010211a200241186a290000211b200320053602c401200620014105746a220241186a201b3700002002201a3700102002200d3700082002200c3700000c010b20034180016a41186a220120034180046a41186a29030037030020034180016a41106a220520034180046a41106a29030037030020034180016a41086a220720034180046a41086a2903003703002003200329038004370380010240200a2010470d00200341bc016a20104101108a0120032802c401210a20032802bc01210e0b200e200a4105746a2202200329038001370000200241186a2001290300370000200241106a2005290300370000200241086a2007290300370000200320032802c40141016a22053602c40120032802b80121072011450d00200720064d0d0720032802b00122012007417f6a22074105746a2202290000210c2002290008210d2002290010211a200241186a290000211b200320073602b801200120064105746a220241186a201b3700002002201a3700102002200d3700082002200c3700000b200341f5016a2003290360370000200341e5016a20034180046a41106a290300370000200341ed016a20034180046a41186a29030037000020034185026a200341e0006a41106a2903003700002003418d026a200341e0006a41186a290300370000200341083a00d001200341dd016a20034180046a41086a290300370000200341fd016a200341e0006a41086a290300370000200341013a00d40120032003290380043700d5012003419c026a200536020020034198026a200736020020034195026a200f3a00004100210241b0b4cc004100200341d0016a10d401200341d0016a41186a22084200370300200341d0016a41106a22094200370300200341d0016a41086a22014200370300200342003703d00141c7d5ca00ad4280808080b0028410012206290000210c2001200641086a2900003703002003200c3703d001200610354189eaca00ad4280808080f0008410012206290000210c200341306a41086a220a200641086a2900003703002003200c3703302006103520042003290330370000200441086a200a29030037000020034180016a41086a200129030037030020034180016a41106a200929030037030020034180016a41186a2008290300370300200320032903d00137038001200341d0006a20034180016a10fe01024020032802502201450d002003290254220c422088a72102200c42ffffff3f83500d00200110350b0240200720032802ac0122014f22060d004100200220056b2205200520024b1b2001490d00200341d0016a41206a200341a8016a41206a280200360200200341d0016a41186a200341a8016a41186a290300370300200341d0016a41106a200341a8016a41106a290300370300200341d0016a41086a200341a8016a41086a290300370300200320032903a8013703d00120034180016a200341e0006a109e072003280280012102200320032802880136023420032002360230200341d0016a200341306a1092070240200328028401450d00200210350b0240200341dc016a28020041ffffff3f71450d0020032802d80110350b200341e8016a28020041ffffff3f71450d0d20032802e40110350c0d0b200341d0016a41206a200341a8016a41206a280200360200200341d0016a41186a200341a8016a41186a290300370300200341d0016a41106a200341a8016a41106a290300370300200341d0016a41086a200341a8016a41086a290300370300200320032903a8013703d00120034180016a41186a200341e0006a41186a29030037030020034180016a41106a200341e0006a41106a29030037030020034180016a41086a200341e0006a41086a290300370300200320032903603703800120062002200341d0016a20034180016a109f070c0c0b41002101410221020c080b200141246a280200210620034198046a200141196a29000037030020034190046a200141116a29000037030020034188046a200141096a2900003703002003200129000137038004410221010240024002400240024020022d00000d0020022d00014101470d00200341a8016a20034180046a109e07200341d0016a20032802a801220120032802b00110de0220032802ac012102024020032802d8012204450d00200341f0016a280200210a200341ec016a280200210b200341e8016a2802002107200341e4016a280200210e200341e0016a280200210920032802dc01210820032903d001210c02402002450d00200110350b2006200ca7460d0241c8dfca002106410a21024180800c21050c030b02402002450d00200110350b410321010b418080082105410f210241d2dfca0021060c020b200341d0016a41186a4200370300200341d0016a41106a2210420037030041082102200341d0016a41086a22014200370300200342003703d00141d1c4c700ad4280808080e0008410012206290000210d2001200641086a2900003703002003200d3703d0012006103541e7c4c700ad4280808080e0008410012206290000210d200341306a41086a2205200641086a2900003703002003200d3703302006103520102003290330220d37030020034180016a41086a200129030037030020034180016a41106a2201200d37030020034180016a41186a22062005290300370300200320032903d00137038001200341286a20034180016a412010c001200328022c410020032802281b200a4f0d0241a1dfca0021064180801821050b0240200841ffffff3f71450d00200410350b0240200741ffffff3f71450d00200e10350b410321010b20004200370308200041206a20023602002000411c6a2006360200200041186a20054180801c71200172418018723602004201210c0c0c0b200c422088210d200642003703002001420037030020034180016a41086a22024200370300200342003703800141c7d5ca00ad4280808080b0028410012211290000211a200341d0006a41086a2205201141086a2900003703002003201a37035020111035200220052903003703002003200329035037038001419cdfca00ad4280808080d0008410012211290000211a2005201141086a2900003703002003201a3703502011103520012003290350221a370300200341306a41086a2002290300370300200341306a41106a201a370300200341306a41186a20052903003703002003200329038001370330200341d0016a200341306a412010d50120032d00d00121052006200341e9016a2900003703002001200341e1016a2900003703002002200341d9016a290000370300200320032900d101370380010240024020054101460d00410021050c010b200341a8016a41186a20034180016a41186a290300221a370300200341a8016a41106a20034180016a41106a290300221b370300200341a8016a41086a2002290300221c3703002003200329038001221d3703a801200341d0016a41186a201a370300200341d0016a41106a201b370300200341d0016a41086a201c3703002003201d3703d00120094105742101200421020340024020010d00410021050c020b41012105200341d0016a2002460d01200141606a21012002200341d0016a412010a0082106200241206a210220060d000b0b200da72106200341d0016a41186a22114200370300200341d0016a41106a22124200370300200341d0016a41086a22024200370300200342003703d00141c7d5ca00ad4280808080b0028410012201290000210d2002200141086a2900003703002003200d3703d001200110354189eaca00ad4280808080f0008410012201290000210d200341306a41086a2213200141086a2900003703002003200d3703302001103520102003290330370000201041086a201329030037000020034180016a41086a200229030037030020034180016a41106a201229030037030020034180016a41186a2011290300370300200320032903d00137038001200341a8016a20034180016a10fe010240024020032802a80122010d00410021020c010b20032902ac01220d422088a72102200d42ffffff3f83500d00200110350b200341e5016a20034180046a41106a2201290300370000200341ed016a20034180046a41186a2210290300370000200341083a00d001200341dd016a20034180046a41086a2211290300370000200341fc016a41002002200b20096a6b221220051b200b6a360200200341f8016a2012410020051b20096a2205360200200341063a00d40120032003290380043700d50141b0b4cc004100200341d0016a10d401200341ec016a200b360200200341d0016a41186a2007360200200341d0016a41106a2009360200200341dc016a20083602002003200a3602f0012003200e3602e401200320043602d8012003200c3703d001200341a8016a41186a2010290300370300200341a8016a41106a2001290300370300200341a8016a41086a201129030037030020032003290380043703a801200520064f2002200341d0016a200341a8016a109f070c0a0b1045000b41e1dfca002101411121064180980421050c060b103c000b20012005104a000b20062007104a000b41bbdfca002106410d21054180801021010b0240200b41ffffff3f71450d00200810350b0240201041ffffff3f71450d00200e10350b410321020b20004200370308200041206a20053602002000411c6a2006360200200041186a20014180801c71200272418018723602004201210c0c030b200410ba0220041035200041206a20063602002000411c6a2001360200200041186a2005200272360200200042003703084201210c0c020b41b0b4cc004100200210d401200410350b4200210c200042003703080b2000200c370300200341a0046a24000bb65d07047f017e037f027e017f027e097f23004180036b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e080001020304050607000b20034194026a41013602002003420137028402200341e8d4ca0036028002200341043602dc012003419cd5ca003602d8012003200341d8016a3602900220034180026a41b0b4cc00104c000b200341d0016a200141196a290000370300200341b8016a41106a200141116a290000370300200341c0016a200141096a290000370300200320012900013703b801200241036a2d0000210420022f000121050240024020022d00002206417f6a220141024b0d00024020010e03000102000b200241086a2802004101742002410c6a2802004d0d00200241046a28020041ff0171450d010b200641004720052004411074727241ff01710d070b20034180026a41186a420037030020034180026a41106a2204420037030020034180026a41086a22014200370300200342003703800241fb8fc800ad4280808080b002841001220229000021072001200241086a2900003703002003200737038002200210354189eaca00ad4280808080f0008410012202290000210720034198016a41086a2205200241086a29000037030020032007370398012002103520042003290398012207370300200341d8016a41086a2001290300370300200341d8016a41106a2007370300200341d8016a41186a200529030037030020032003290380023703d801200341f8006a200341d8016a10fe010240200328027822060d00410021082003410036023020034201370328410121060c170b2003200329027c220737022c200320063602282007a7210841002101024002402007422088a7220941014b0d0020090e021801180b2009210203402002410176220420016a22052001200620054105746a200341b8016a412010a0084101481b2101200220046b220241014b0d000b0b0240200620014105746a200341b8016a412010a0082202450d0020034180026a41186a200341b8016a41186a29030037030020034180026a41106a200341b8016a41106a29030037030020034180026a41086a200341b8016a41086a290300370300200320032903b801370380022002411f7620016a220420094b0d0820034180026a21020c180b02402008450d00200841ffffff3f71450d00200610350b41831c21010c150b200341c0006a200141196a290000370300200341286a41106a200141116a290000370300200341306a200141096a2900003703002003200129000137032841022101200241036a2d0000210520022f0001210602400240024020022d00002209417f6a220441024b0d00024020040e03000102000b200241086a2802004101742002410c6a2802004d0d00200241046a28020041ff0171450d010b200941004720062005411074727241ff01710d010b20034180026a41186a420037030020034180026a41106a2204420037030020034180026a41086a22014200370300200342003703800241fb8fc800ad4280808080b002841001220229000021072001200241086a2900003703002003200737038002200210354189eaca00ad4280808080f0008410012202290000210720034198016a41086a2205200241086a29000037030020032007370398012002103520042003290398012207370300200341d8016a41086a2001290300370300200341d8016a41106a2007370300200341d8016a41186a200529030037030020032003290380023703d80120034180026a200341d8016a10fe012003280280022202410120021b210641002101024002400240200329028402420020021b2207422088a7220941014b0d0020090e020201020b2009210203402002410176220420016a22052001200620054105746a200341286a412010a0084101481b2101200220046b220241014b0d000b0b200620014105746a200341286a412010a0080d00200120094f0d09200620014105746a2202200241206a2001417f7320096a410574109e081a20034180026a41186a220a420037030020034180026a41106a2208420037030020034180026a41086a22054200370300200342003703800241fb8fc800ad4280808080b00284220b10012201290000210c20034198016a41086a2202200141086a2900003703002003200c3703980120011035200520022903003703002003200329039801370380024189eaca00ad4280808080f0008410012201290000210c2002200141086a2900003703002003200c37039801200110352008200329039801220c370300200341b8016a41086a22042005290300370300200341b8016a41106a200c370300200341b8016a41186a200229030037030020032003290380023703b80120034120360284022003200341b8016a3602800220062009417f6a220120034180026a109802200a200341286a41186a2903003703002008200341286a41106a2903003703002005200341286a41086a290300370300200320032903283703800220034180026a41012006200110aa06200341d8016a41186a220d4200370300200341d8016a41106a22084200370300200341d8016a41086a22054200370300200342003703d801200b1001220a290000210b2004200a41086a2900003703002003200b3703b801200a103520052004290300370300200320032903b8013703d801419cdfca00ad4280808080d000841001220a290000210b2004200a41086a2900003703002003200b3703b801200a1035200820032903b801220b3703002002200529030037030020034198016a41106a200b37030020034198016a41186a2004290300370300200320032903d8013703980120034180026a20034198016a412010d50120032d0080022102200d20034199026a290000370300200820034191026a290000370300200520034189026a29000037030020032003290081023703d801024020024101470d00200341f8006a41186a200d290300220b370300200341f8006a41106a2008290300220c370300200341f8006a41086a2005290300220e370300200320032903d801220f370378200d200b3703002008200c3703002005200e3703002003200f3703d8014100210202400240024002402009417f6a220441014b0d0020040e020201020b03402001410176220420026a22052002200620054105746a200341d8016a412010a0084101481b2102200120046b220141014b0d000b0b200620024105746a200341d8016a412010a008450d010b20034198016a41186a420037030020034198016a41106a2205420037030020034198016a41086a22024200370300200342003703980141fb8fc800ad4280808080b0028410012204290000210b200341e8006a41086a2201200441086a2900003703002003200b37036820041035200220012903003703002003200329036837039801419cdfca00ad4280808080d0008410012204290000210b2001200441086a2900003703002003200b3703682004103520052003290368220b370300200341c8006a41086a2002290300370300200341c8006a41106a200b370300200341c8006a41186a20012903003703002003200329039801370348200341c8006aad428080808080048410070c010b20034199026a200341f0016a29030037000020034191026a200341e8016a29030037000020034189026a200341e0016a290300370000200320032903d80137008102200341013a00800220034180026a10ab060b2003418a023b01800241b0b4cc00410020034180026a10d401200742ffffff3f83500d15200610350c150b02402007a72201450d00200141ffffff3f71450d00200610350b410321010b20004200370308200041206a41093602002000411c6a41f2dfca00360200200041186a200141809c0472360200420121070c180b200341086a41186a200141196a290000370300200341086a41106a200141116a290000370300200341086a41086a200141096a29000037030020032001290001370308200341286a41186a200141396a290000370300200341286a41106a200141316a290000370300200341286a41086a200141296a2900003703002003200141216a29000037032841022101200241036a2d0000210520022f000121060240024020022d00002209417f6a220441024b0d00024020040e03000102000b200241086a2802004101742002410c6a2802004d0d00200241046a28020041ff0171450d010b200941004720062005411074727241ff0171450d000c110b200341086a200341286a412010a008450d1220034180026a41186a420037030020034180026a41106a2204420037030020034180026a41086a22014200370300200342003703800241fb8fc800ad4280808080b002841001220229000021072001200241086a2900003703002003200737038002200210354189eaca00ad4280808080f0008410012202290000210720034198016a41086a2205200241086a29000037030020032007370398012002103520042003290398012207370300200341d8016a41086a2001290300370300200341d8016a41106a2007370300200341d8016a41186a200529030037030020032003290380023703d80120034180026a200341d8016a10fe014101210d2003280280022202410120021b210641f2dfca0021084109210a4100210102400240200329028402420020021b2207422088a7220941014b0d0020090e021101110b2009210203402002410176220420016a22052001200620054105746a200341086a412010a0084101481b2101200220046b220241014b0d000b0b200620014105746a2210200341086a412010a0080d0f410021020240200941014b0d0020090e02120f120b2009210403402004410176220520026a22082002200620084105746a200341286a412010a0084101481b2102200420056b220441014b0d000c0f0b0b200241036a2d0000210520022f000121062001410c6a2802002109200141086a280200210d200141046a280200210402400240024020022d00002208417f6a220141024b0d00024020010e03000102000b200241086a2802004101742002410c6a2802004d0d00200241046a28020041ff0171450d010b200841004720062005411074727241ff01710d010b2004200910ac0620034180026a41186a420037030020034180026a41106a2205420037030020034180026a41086a22024200370300200342003703800241fb8fc800ad4280808080b00284220710012201290000210b2002200141086a2900003703002003200b37038002200110354189eaca00ad4280808080f0008410012201290000210b20034198016a41086a2208200141086a2900003703002003200b37039801200110352005200329039801220b370300200341d8016a41086a22012002290300370300200341d8016a41106a2202200b370300200341d8016a41186a2205200829030037030020032003290380023703d80120034180026a200341d8016a10fe01200420092003280280022206410120061b2210200329028402420020061b220b422088a710ad06200542003703002002420037030020014200370300200342003703d80120071001220a2900002107200341b8016a41086a2206200a41086a290000370300200320073703b801200a103520012006290300370300200320032903b8013703d801419cdfca00ad4280808080d000841001220a29000021072006200a41086a290000370300200320073703b801200a1035200220032903b80122073703002008200129030037030020034198016a41106a200737030020034198016a41186a2006290300370300200320032903d8013703980120034180026a20034198016a412010d50120032d0080022106200520034199026a290000370300200220034191026a290000370300200120034189026a29000037030020032003290081023703d801024020064101470d00200341f8006a41186a20052903002207370300200341f8006a41106a2002290300220c370300200341f8006a41086a2001290300220e370300200320032903d801220f370378200520073703002002200c3703002001200e3703002003200f3703d801410021010240024002400240200941014b0d0020090e020201020b2009210203402002410176220520016a22062001200420064105746a200341d8016a412010a0084101481b2101200220056b220241014b0d000b0b200420014105746a200341d8016a412010a008450d010b20034198016a41186a420037030020034198016a41106a2206420037030020034198016a41086a22024200370300200342003703980141fb8fc800ad4280808080b00284100122052900002107200341e8006a41086a2201200541086a2900003703002003200737036820051035200220012903003703002003200329036837039801419cdfca00ad4280808080d000841001220529000021072001200541086a2900003703002003200737036820051035200620032903682207370300200341c8006a41086a2002290300370300200341c8006a41106a2007370300200341c8006a41186a20012903003703002003200329039801370348200341c8006aad428080808080048410070c010b20034199026a200341f0016a29030037000020034191026a200341e8016a29030037000020034189026a200341e0016a290300370000200320032903d80137008102200341013a00800220034180026a10ab060b0240200b42ffffff3f83500d00201010350b4200210720034198016a41186a420037030020034198016a41106a2206420037030020034198016a41086a22024200370300200342003703980141fb8fc800ad4280808080b0028410012205290000210b200341e8006a41086a2201200541086a2900003703002003200b370368200510352002200129030037030020032003290368370398014189eaca00ad4280808080f0008410012205290000210b2001200541086a2900003703002003200b3703682005103520062003290368220b370300200341c8006a41086a2002290300370300200341c8006a41106a200b370300200341c8006a41186a2001290300370300200320032903980137034820034120360284022003200341c8006a360280022004200920034180026a1098020240200d41ffffff3f71450d00200410350b2003418a063b01800241b0b4cc00410020034180026a10d4010c160b0240200d41ffffff3f71450d00200410350b20004200370308200041186a4102360200420121070c160b200341286a41186a200141196a290000370300200341286a41106a200141116a290000370300200341286a41086a200141096a2900003703002003200129000137032841022101024020022d00000d0020022d00014101470d002002411a6a2901002107200241196a2d00002101200241186a2d00002104200241166a2f01002105200241156a2d00002106200241146a2d00002109200241126a2f01002108200241116a2d0000210a200241106a2d0000210d2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241086a2d00002114200241066a2f01002115200241056a2d00002116200241046a2d00002117200241026a2f010021182003200241096a2d00003a009f01200320143a009e01200320153b019c01200320163a009b01200320173a009a01200320183b0198012003200a3a00a7012003200d3a00a601200320103b01a401200320113a00a301200320123a00a201200320133b01a001200320013a00af01200320043a00ae01200320053b01ac01200320063a00ab01200320093a00aa01200320083b01a801200320073701b001200341f8006a41186a22012007370300200341f8006a41106a220220032901a801370300200341f8006a41086a220420032901a0013703002003200329019801370378200341b8016a41186a2001290300370300200341b8016a41106a2002290300370300200341b8016a41086a2004290300370300200320032903783703b801200341b8016a200341286a412010a008450d0920034180026a41186a420037030020034180026a41106a2204420037030020034180026a41086a22014200370300200342003703800241fb8fc800ad4280808080b002841001220229000021072001200241086a2900003703002003200737038002200210354189eaca00ad4280808080f0008410012202290000210720034198016a41086a2205200241086a29000037030020032007370398012002103520042003290398012207370300200341d8016a41086a2001290300370300200341d8016a41106a2007370300200341d8016a41186a200529030037030020032003290380023703d80120034180026a200341d8016a10fe01410121092003280280022202410120021b210641f2dfca0021084109210a4100210102400240200329028402420020021b2207422088a7220d41014b0d00200d0e020901090b200d210203402002410176220420016a22052001200620054105746a200341b8016a412010a0084101481b2101200220046b220241014b0d000b0b200620014105746a2210200341b8016a412010a0080d07410021020240200d41014b0d00200d0e020907090b200d210403402004410176220520026a22092002200620094105746a200341286a412010a0084101481b2102200420056b220441014b0d000c070b0b0c090b200341d0016a200141196a290000370300200341b8016a41106a200141116a290000370300200341c0016a200141096a290000370300200320012900013703b80141022101200241036a2d0000210520022f0001210602400240024020022d00002209417f6a220441024b0d00024020040e03000102000b200241086a2802004101742002410c6a2802004d0d00200241046a28020041ff0171450d010b200941004720062005411074727241ff01710d010b20034180026a41186a420037030020034180026a41106a2204420037030020034180026a41086a22014200370300200342003703800241fb8fc800ad4280808080b002841001220229000021072001200241086a2900003703002003200737038002200210354189eaca00ad4280808080f0008410012202290000210720034198016a41086a2205200241086a29000037030020032007370398012002103520042003290398012207370300200341d8016a41086a2001290300370300200341d8016a41106a2007370300200341d8016a41186a200529030037030020032003290380023703d80120034180026a200341d8016a10fe012003280280022202410120021b210641002101024002400240200329028402420020021b2207422088a7220241014b0d0020020e020201020b03402002410176220420016a22052001200620054105746a200341b8016a412010a0084101481b2101200220046b220241014b0d000b0b200620014105746a200341b8016a412010a0080d000240200742ffffff3f83500d00200610350b4200210720034198016a41186a420037030020034198016a41106a2205420037030020034198016a41086a22024200370300200342003703980141fb8fc800ad4280808080b0028410012204290000210b200341e8006a41086a2201200441086a2900003703002003200b37036820041035200220012903003703002003200329036837039801419cdfca00ad4280808080d0008410012204290000210b2001200441086a2900003703002003200b3703682004103520052003290368220b370300200341c8006a41086a2002290300370300200341c8006a41106a200b370300200341c8006a41186a20012903003703002003200329039801370348412010332201450d0c200120032903b801370000200141186a200341b8016a41186a2202290300370000200141106a200341b8016a41106a2204290300370000200141086a200341b8016a41086a2205290300370000200341c8006aad42808080808004842001ad428080808080048410022001103520034199026a200229030037000020034191026a200429030037000020034189026a2005290300370000200320032903b80137008102200341013a00800220034180026a10ab060c150b02402007a72201450d00200141ffffff3f71450d00200610350b410321010b20004200370308200041206a41093602002000411c6a41f2dfca00360200200041186a200141809c0472360200420121070c140b200241036a2d0000210420022f000121050240024020022d00002206417f6a220141024b0d00024020010e03000102000b200241086a2802004101742002410c6a2802004d0d00200241046a28020041ff0171450d010b200641004720052004411074727241ff0171450d0020004200370308200041186a4102360200420121070c140b4200210720034198016a41186a420037030020034198016a41106a2205420037030020034198016a41086a22024200370300200342003703980141fb8fc800ad4280808080b0028410012204290000210b200341e8006a41086a2201200441086a2900003703002003200b37036820041035200220012903003703002003200329036837039801419cdfca00ad4280808080d0008410012204290000210b2001200441086a2900003703002003200b3703682004103520052003290368220b370300200341c8006a41086a2002290300370300200341c8006a41106a200b370300200341c8006a41186a20012903003703002003200329039801370348200341c8006aad42808080808004841007200341003a00800220034180026a10ab060c120b41821c21010c0e0b20042009104d000b20012009104e000b200620024105746a200341286a412010a0080d0141ce9cc8002108410d210a410021090b02402007a722010d00410321010c030b0240200141ffffff3f71450d00200610350b410321010c020b200341d8016a41186a2202200341286a41186a290300370300200341d8016a41106a2204200341286a41106a290300370300200341d8016a41086a2205200341286a41086a290300370300200320032903283703d8012001200d4f0d02201020032903d801370000201041186a2002290300370000201041106a2004290300370000201041086a20052903003700002006200d10ac0620034198016a41186a2205420037030020034198016a41106a2204420037030020034198016a41086a22024200370300200342003703980141fb8fc800ad4280808080b00284220b10012209290000210c200341e8006a41086a2201200941086a2900003703002003200c370368200910352002200129030037030020032003290368370398014189eaca00ad4280808080f0008410012209290000210c2001200941086a2900003703002003200c3703682009103520042003290368220c370300200341c8006a41086a220a2002290300370300200341c8006a41106a2210200c370300200341c8006a41186a22112001290300370300200320032903980137034820034120360284022003200341c8006a360280022006200d20034180026a10980220034180026a41186a200341b8016a41186a29030037030020034180026a41106a200341b8016a41106a29030037030020034180026a41086a200341b8016a41086a290300370300200320032903b801370380024101210820034180026a41012006200d10aa062005420037030020044200370300200242003703002003420037039801200b10012209290000210b2001200941086a2900003703002003200b37036820091035200220012903003703002003200329036837039801419cdfca00ad4280808080d0008410012209290000210b2001200941086a2900003703002003200b3703682009103520042003290368220b370300200a20022903003703002010200b37030020112001290300370300200320032903980137034820034180026a200341c8006a412010d50120032d0080022101200520034180026a41196a290000370300200420034180026a41116a290000370300200220034180026a41096a2900003703002003200329008102370398010240024020014101460d0041002108200341003a00d8010c010b200341d8016a41096a200341a0016a290300370000200341d8016a41116a200341a8016a290300370000200341d8016a41196a200341b0016a290300370000200341013a00d80120032003290398013700d9010b20034199026a200341d0016a29030037000020034191026a200341c8016a29030037000020034189026a200341c0016a290300370000200320032903b80137008102200341013a00800202402008450d00200341d8016a41017220034180026a410172412010a0080d0020034198016a41186a2209420037030020034198016a41106a2208420037030020034198016a41086a22024200370300200342003703980141fb8fc800ad4280808080b0028410012205290000210b200341e8006a41086a2201200541086a2900003703002003200b37036820051035200220012903003703002003200329036837039801419cdfca00ad4280808080d0008410012205290000210b2001200541086a2900003703002003200b3703682005103520042003290368370000200441086a2001290300370000200341c8006a41086a2002290300370300200341c8006a41106a2008290300370300200341c8006a41186a20092903003703002003200329039801370348412010332201450d0420012003290328370000200141186a200341286a41186a2202290300370000200141106a200341286a41106a2204290300370000200141086a200341286a41086a2205290300370000200341c8006aad42808080808004842001ad428080808080048410022001103520034199026a200229030037000020034191026a200429030037000020034189026a20052903003700002003200329032837008102200341013a00800220034180026a10ab060b200742ffffff3f83500d00200610350b2003418a083b01800241b0b4cc00410020034180026a10d401420021070c0b0b20004200370308200041206a200a3602002000411c6a2008360200200041186a200941ff017141107420017241801c72360200420121070c0b0b2001200d419898c8001042000b1045000b200620024105746a200341286a412010a0080d0241ce9cc8002108410d210a4100210d0b02402007a72201450d00200141ffffff3f71450d00200610350b410321010b20004200370308200041206a200a3602002000411c6a2008360200200041186a200d41ff017141107420017241801c72360200420121070c060b20034180026a41186a2205200341286a41186a29030037030020034180026a41106a2208200341286a41106a29030037030020034180026a41086a220a200341286a41086a29030037030020032003290328370380020240200120094f0d002010200329038002370000201041186a2005290300370000201041106a2008290300370000201041086a200a2903003700002006200910ac06200341d8016a41186a4200370300200341d8016a41106a220d4200370300200341d8016a41086a22044200370300200342003703d80141fb8fc800ad4280808080b00284220b10012201290000210c200341b8016a41086a2202200141086a2900003703002003200c3703b8012001103520042002290300370300200320032903b8013703d8014189eaca00ad4280808080f0008410012201290000210c2002200141086a2900003703002003200c3703b80120011035200d20032903b801220c37030020034198016a41086a2201200429030037030020034198016a41106a2204200c37030020034198016a41186a220d2002290300370300200320032903d801370398012003412036028402200320034198016a360280022006200920034180026a1098022005200341086a41186a2903003703002008200341086a41106a290300370300200a200341086a41086a290300370300200320032903083703800220034180026a41012006200910aa06200d420037030020044200370300200142003703002003420037039801200b10012205290000210b200341e8006a41086a2202200541086a2900003703002003200b37036820051035200120022903003703002003200329036837039801419cdfca00ad4280808080d0008410012205290000210b2002200541086a2900003703002003200b3703682005103520042003290368220b370300200341c8006a41086a2001290300370300200341c8006a41106a200b370300200341c8006a41186a2002290300370300200320032903980137034820034180026a200341c8006a412010d50120032d0080022102200d20034199026a290000370300200420034191026a290000370300200120034189026a290000370300200320032900810237039801024020024101470d00200341b8016a41186a20034198016a41186a290300220b370300200341b8016a41106a20034198016a41106a290300220c370300200341b8016a41086a20034198016a41086a290300220e3703002003200329039801220f3703b801200341d8016a41186a200b370300200341d8016a41106a200c370300200341d8016a41086a200e3703002003200f3703d80141002101024020094101460d004100210103402009410176220220016a22042001200620044105746a200341d8016a412010a0084101481b2101200920026b220941014b0d000b0b0240200620014105746a200341d8016a412010a008450d00200341f8006a41186a4200370300200341f8006a41106a22054200370300200341f8006a41086a220242003703002003420037037841fb8fc800ad4280808080b0028410012204290000210b20034198016a41086a2201200441086a2900003703002003200b3703980120041035200220012903003703002003200329039801370378419cdfca00ad4280808080d0008410012204290000210b2001200441086a2900003703002003200b37039801200410352005200329039801220b37030020034180026a41086a200229030037030020034180026a41106a200b37030020034180026a41186a2001290300370300200320032903783703800220034180026aad428080808080048410070c010b20034199026a200341f0016a29030037000020034191026a200341e8016a29030037000020034189026a200341e0016a290300370000200320032903d80137008102200341013a00800220034180026a10ab060b2003418a043b01800241b0b4cc00410020034180026a10d401200742ffffff3f83500d0120061035420021070c050b20012009418898c8001042000b420021070c030b20004200370308200041206a410d3602002000411c6a41ce9cc800360200200041186a2001360200420121070c030b20034180026a41186a200341b8016a41186a29030037030020034180026a41106a200341b8016a41106a29030037030020034180026a41086a200341b8016a41086a290300370300200320032903b801370380024100210920034180026a2102410021040b024020092008470d00200341286a20094101108a01200328022c2108200328022821060b200620044105746a220141206a2001200920046b410574109e081a20012002290000370000200141186a200241186a290000370000200141106a200241106a290000370000200141086a200241086a2900003700002003200941016a3602304200210720034198016a41186a420037030020034198016a41106a2205420037030020034198016a41086a22024200370300200342003703980141fb8fc800ad4280808080b0028410012204290000210b200341e8006a41086a2201200441086a2900003703002003200b370368200410352002200129030037030020032003290368370398014189eaca00ad4280808080f0008410012204290000210b2001200441086a2900003703002003200b3703682004103520052003290368220b370300200341c8006a41086a2002290300370300200341c8006a41106a200b370300200341c8006a41186a2001290300370300200320032903980137034820034120360284022003200341c8006a360280022003280228200328023020034180026a10980220034180026a41186a200341b8016a41186a29030037030020034180026a41106a200341b8016a41106a29030037030020034180026a41086a200341b8016a41086a290300370300200320032903b8013703800241b0b4cc00410020032802282201200328023010aa062003410a3b01800241b0b4cc00410020034180026a10d401200841ffffff3f71450d00200110350b200020073703080b2000200737030020034180036a24000b8b970107017f027e117f017e027f087e1d7f230041d0086b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e0900010203040506070a000b200341d4076a4101360200200342013702c407200341e8d4ca003602c007200341043602b4062003419cd5ca003602b0062003200341b0066a3602d007200341c0076a41b0b4cc00104c000b200141306a2903002104200141286a2903002105200341b0066a41206a200141246a280200360200200341b0066a41186a2001411c6a290200370300200341b0066a41106a200141146a290200370300200341b0066a41086a2001410c6a2902003703002003200141046a2902003703b006418222210102400240024020022d00000d0020022d00014101470d00200241196a2d00002101200241186a2d00002106200241166a2f01002107200241156a2d00002108200241146a2d00002109200241126a2f0100210a200241116a2d0000210b200241106a2d0000210c2002410e6a2f0100210d2002410d6a2d0000210e2002410c6a2d0000210f2002410a6a2f01002110200241096a2d00002111200241086a2d00002112200241066a2f01002113200241056a2d00002114200241046a2d00002115200241026a2f0100211620032002411a6a29010037038804200320013a008704200320063a008604200320073b018404200320083a008304200320093a0082042003200a3b0180042003200b3a00ff032003200c3a00fe032003200d3b01fc032003200e3a00fb032003200f3a00fa03200320103b01f803200320113a00f703200320123a00f603200320133b01f403200320143a00f303200320153a00f203200320163b01f003200341c0076a41206a200341b0066a41206a280200360200200341c0076a41186a200341b0066a41186a290300370300200341c0076a41106a200341b0066a41106a290300370300200341c0076a41086a200341b0066a41086a290300370300200320032903b0063703c007200341f8046a200341c0076a108b02418122210120032d00f8044101460d00200341f8046a41086a2d0000210720034181056a2f0000210820034183056a2d0000210920034184056a2d0000210a20034185056a2f0000210b20034187056a2d0000210c200341f8046a41106a2d0000210d20034189056a2f0000210e2003418b056a2d0000210f2003418c056a2d000021102003418d056a2f000021112003418f056a2d00002112200341f8046a41186a2d0000211320034191056a290000211720032f00f904211420032d00fb04211520032d00fc04211620032f00fd04211820032d00ff042119200341286a2005200442c0843d4200109808200341186a2003290328221a200341286a41086a290300221b42c0fb42427f108408200341086a201a201b42d0860342001084082003200341086a41086a2903002003290308221b200520032903187c221a421480221ca7417f201a42d086037e221a428080808080c8d007541b201a201c42c0fb427e7c42a0c21e566aad7c221a201b54ad7c221b4200201a428080e983b1de1656201b420052201b501b22011b221b3703f0022003201a428080e983b1de1620011b221a3703e8022003200341f0036a360280062003200341f0036a3602e0012003200341e0016a3602c807200320034180066a3602c4072003200341e8026a3602c007200341f8046a200341f0036a200341c0076a108c0320032802f8044101470d01418322210120032d00fc044104460d020b200041206a411c3602002000411c6a41e3adc800360200200041186a200136020020004200370308420121050c160b200341f8046a41086a2903004201520d00200341f8046a41106a290300211c20032802e0012101200341f8076a200341f8046a41186a290300370300200341f0076a201c370300200341c0076a41086a41003a0000200341c9076a2001290000370000200341d1076a200141086a290000370000200341d9076a200141106a290000370000200341e1076a200141186a290000370000200341033a00c00741b0b4cc004100200341c0076a10d4010b4186f0cb00ad4280808080800184221c10012201290000211d2001290008211e20011035418ef0cb00ad4280808080d00184221f1001220129000021202001290008212120011035200320213703900520032020370388052003201e370380052003201d3703f8042003200341f8046a412010c0012003280204210220032802002106201c10012201290000211c2001290008211d20011035201f10012201290000211e2001290008211f200110352003201f370390052003201e370388052003201d370380052003201c3703f80420032002410020061b220241016a3602c007200341f8046aad4280808080800484200341c0076aad4280808080c000841002200341c0076a41186a2222200341f0036a41186a290300370300200341c0076a41106a2223200341f0036a41106a290300370300200341c0076a41086a2224200341f0036a41086a290300370300200320032903f0033703c007200341f8046a200210b506200335028005211c20032802f8042106412010332201450d15200120032903c007370000200141186a2022290300370000200141106a2023290300370000200141086a20242903003700002001412041c00010372201450d1520012005370020200141286a2004370000200141c00041800110372201450d152001201a37005020012017370048200120133a0047200120123a0046200120113b0044200120103a00432001200f3a00422001200e3b00402001200d3a003f2001200c3a003e2001200b3b003c2001200a3a003b200120093a003a200120083b0038200120073a0037200120193a0036200120183b0034200120163a0033200120153a0032200120143b0030200141d8006a201b370000201c4220862006ad842001ad4280808080800c84100220011035024020032802fc04450d00200610350b200341c8076a41003a00002003410c3a00c007200341c0076a410c6a200236020041b0b4cc004100200341c0076a10d4010c120b200241036a2d0000210620022f00012107200141046a28020021090240024002400240024020022d00002208417f6a220141024b0d00024020010e03000102000b200241086a2802004102490d00200241046a28020041ff0171450d010b4182a2042101200720064110747220084100477241ff01710d010b4186f0cb00ad4280808080800184100122012d000f210b20012d000e210c20012f000c210d20012d000b210e20012d000a210f20012f0008211020012d0007211120012d0006211220012f0004211320012d0003211420012d0002211520012f00002116200110354180eaca00ad428080808090018410012201290008210520012d0007211820012d0006211920012f0004212220012d0003212320012d0002212420012f0000212520011035200320093602c0012003200341c0016aad4280808080c00084100322012900003703800620011035200341cc076a200341c4016a360200200320034188066a3602c4072003200341c0016a3602c807200320034180066a3602c007200341f0036a200341c0076a107b20032802f803220841206a2202417f4c0d0c20032802f003210a0240024020020d0041002106410121010c010b200210332201450d0c200221060b024002402006410f4d0d00200621070c010b200641017422074110200741104b1b22074100480d0a024020060d002007103322010d010c190b20062007460d0020012006200710372201450d180b2001200b3a000f2001200c3a000e2001200d3b000c2001200e3a000b2001200f3a000a200120103b0008200120113a0007200120123a0006200120133b0004200120143a0003200120153a0002200120163b00000240024020074170714110460d00200721060c010b200741017422064120200641204b1b22064100480d0a20072006460d0020012007200610372201450d180b20012005370018200120183a0017200120193a0016200120223b0014200120233a0013200120243a0012200120253b001002400240200641606a2008490d00200621070c010b2008415f4b0d0a200641017422072002200720024b1b22074100480d0a20062007460d0020012006200710372201450d180b200141206a200a2008109d081a024020032802f403450d00200a10350b200341c0076a2001200210df02024020032903c00742015222060d002002ad4220862001ad8410070b200341f0036a200341c8076a41e000109d081a200341c0076a200341f0036a41e000109d081a024020060d00200341e8026a200341c0076a41e000109d081a02402007450d00200110350b200341b0066a41066a200341e8026a41e000109d081a200341f8046a200341b0066a41e600109d081a200341e0016a200341f8046a41066a41e000109d081a20032903f00121042003200341f8016a290300221a37038005200320043703f804024002402004201a844200520d00200342003703f803200342003703f0030c010b2003200341e0016a41206a22013602f003200341b0066a2001200341f8046a200341f0036a10a802200341b0066a41206a290300210520032903c806211b024020032903b0064201520d0020032903b806211c200341f8076a200341b0066a41106a290300370300200341f0076a201c370300200341c0076a41086a41003a0000200341c9076a2001290000370000200341d1076a200141086a290000370000200341d9076a200141106a290000370000200341e1076a200141186a290000370000200341033a00c00741b0b4cc004100200341c0076a10d4010b2003201b3703f003200320053703f803201b2005844200520d030b2003200341f0036a36028006200341f0036a21080c030b02402007450d00200110350b4183a20421010b20004200370308200041206a41143602002000411c6a41cfadc800360200200041186a2001360200420121050c150b200320053703f8032003201b3703f0032003200341f0036a36028006200341f0036a21080b42002105200341f8046a41186a220e4200370300200341f8046a41106a22024200370300200341f8046a41086a22014200370300200342003703f80441b6fdc600ad4280808080800184221c10012207290000211b200341b0066a41086a2206200741086a2900003703002003201b3703b0062007103520012006290300370300200320032903b0063703f80441e489c200ad4280808080d0018422171001220a290000211b200341e8026a41086a2207200a41086a2900003703002003201b3703e802200a1035200220032903e802221b370300200341c0076a41086a220a2001290300370300200341c0076a41106a220b201b370300200341c0076a41186a220c2007290300370300200320032903f8043703c007200341386a200341c0076a412010d701200341386a41106a290300211d2003290340211e2003280238210d200841086a290300211f2008290300211b200e42003703002002420037030020014200370300200342003703f804201c10012208290000211c2006200841086a2900003703002003201c3703b0062008103520012006290300370300200320032903b0063703f804201710012206290000211c2007200641086a2900003703002003201c3703e80220061035200220032903e802221c370300200a2001290300370300200b201c370300200c2007290300370300200320032903f8043703c00720034200201d4200200d1b221c201f7d201e4200200d1b2217201b54ad7d221d2017201b7d221b201756201d201c56201d201c511b22011b3703b80620034200201b20011b3703b006200341c0076aad4280808080800484200341b0066aad42808080808002841002200c201a370300200b2004370300200a41033a00002003410c3a00c007200341c0076a410c6a200936020041b0b4cc004100200341c0076a10d4010c120b200241036a2d0000210720022f00012108200141046a28020021010240024020022d00002209417f6a220641024b0d00024020060e03000102000b200241086a2802004104490d00200241046a28020041ff0171450d010b4182a2042102200820074110747220094100477241ff01710d050b200341c0076a200110b506200341d0006a20032802c007220220032802c80741b0b4cc0041004100108a0220032802502106024020032802c407450d00200210350b4183a204210220064101470d044186f0cb00ad42808080808001841001220229000021052002290008210420021035419bf0cb00ad428080808090018410012202290000211a2002290008211b200210352003201b370390052003201a370388052003200437038005200320053703f804200341c0076a200341f8046a10c50202400240024020032802c00722020d0041002107200341003602b806200342043703b0060c010b20032902c4072105200320023602b006200320053702b4062005422088a722062005a72207470d010b200341b0066a2007410110860120032802b406210720032802b006210220032802b80621060b200220064102746a20013602002003200641016a22063602b8064186f0cb00ad42808080808001841001220129000021052001290008210420011035419bf0cb00ad428080808090018410012201290000211a2001290008211b200110352003201b370390052003201a370388052003200437038005200320053703f804024020020d00200341f8046aad428080808080048410070c110b200341203602c4072003200341f8046a3602c00720022006200341c0076a109503200741ffffffff0371450d10200210350c100b2001412c6a280200210c200141286a2802002106200141246a280200210b200341e0016a41186a200141196a290000370300200341e0016a41106a200141116a290000370300200341e0016a41086a200141096a290000370300200320012900013703e0014102210120022d00000d0d20022d00014101470d0d200241196a2d00002101200241186a2d00002107200241166a2f01002108200241156a2d00002109200241146a2d0000210a200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241086a2d00002115200241066a2f01002116200241056a2d00002118200241046a2d00002119200241026a2f0100212220032002411a6a29010037038003200320013a00ff02200320073a00fe02200320083b01fc02200320093a00fb022003200a3a00fa022003200d3b01f8022003200e3a00f7022003200f3a00f602200320103b01f402200320113a00f302200320123a00f202200320133b01f002200320143a00ef02200320153a00ee02200320163b01ec02200320183a00eb02200320193a00ea02200320223b01e8020240200c41818001490d0041c3adc800210a410c21094103210141112108410221070c0f0b200cad221b422086200bad84100922012900002105200141086a2900002104200141106a290000211a200341f0036a41186a200141186a290000370300200341f0036a41106a201a370300200341f0036a41086a2004370300200320053703f00320011035200341c0076a200341f0036a10d206200341f0006a20032802c007220220032802c80741b0b4cc0041004100108a0220032802702101024020032802c407450d00200210350b20014101460d0c2003200341e0016a3602c4072003200341f0036a3602c007200341f8046a200341c0076a10a706200341c0076a200341f8046a10d306200341e8006a20032802c007220220032802c80741b0b4cc0041004100108a0220032802682101024020032802c407450d00200210350b20014101460d0c200341d8006a201b42004280a094a58d1d4200108408200320032903582204428080e983b1de167c2205370380062003200341d8006a41086a2903002005200454ad7c2204370388062003200341e8026a3602a0062003200341e8026a3602c0012003200341c0016a3602c8072003200341a0066a3602c407200320034180066a3602c007200341b0066a200341e8026a200341c0076a108c030240024020032802b0064101470d00200341bc066a2802002109200341b0066a41086a280200210a20032d00b706210220032d00b606210720032d00b506210820032d00b40621010c010b410421010240200341b0066a41086a2903004201520d00200341b0066a41106a290300211a20032802c0012102200341f8076a200341b0066a41186a290300370300200341f0076a201a370300200341c0076a41086a41003a0000200341c9076a2002290000370000200341d1076a200241086a290000370000200341d9076a200241106a290000370000200341e1076a200241186a290000370000200341033a00c00741b0b4cc004100200341c0076a10d4010b0b200141ff01714104470d0e200341c0076a200341f0036a10d20620032802c0072101200320032802c8073602b406200320013602b006200b200c200341b0066a109403024020032802c407450d00200110350b200341f0076a2004370300200341e8076a200537030020034188086a4100360200200341c0076a41106a200341e8026a41086a290300370300200341c0076a41186a200341e8026a41106a290300370300200341e0076a200341e8026a41186a29030037030020034194086a200341f0036a41086a2903003702002003419c086a200341f0036a41106a290300370200200341a4086a200341f0036a41186a290300370200200342013703c007200320032903e8023703c8072003420837038008200341003602f807200320032903f00337028c08200341c4086a200341e0016a41186a290300370200200341bc086a200341e0016a41106a290300370200200341b4086a200341e0016a41086a290300370200200320032903e0013702ac08200341b0066a200341f8046a10d30620032802b0062101200320032802b806360284062003200136028006200341c0076a20034180066a10cd06024020032802b406450d00200110350b200341c0076a41086a41073a0000200341c9076a20032903f804370000200341d1076a200341f8046a41086a290300370000200341d9076a200341f8046a41106a290300370000200341e1076a200341f8046a41186a2903003700002003410c3a00c00741b0b4cc004100200341c0076a10d4012006450d0f200b10350c0f0b200341c0016a41186a200141196a290000370300200341c0016a41106a200141116a290000370300200341c0016a41086a200141096a290000370300200320012900013703c00141022101024002400240024020022d00000d0020022d00014101470d00200241196a2d00002101200241186a2d00002106200241166a2f01002107200241156a2d00002108200241146a2d00002109200241126a2f0100210a200241116a2d0000210b200241106a2d0000210c2002410e6a2f0100210d2002410d6a2d0000210e2002410c6a2d0000210f2002410a6a2f01002110200241096a2d00002111200241086a2d00002112200241066a2f01002113200241056a2d00002114200241046a2d00002115200241026a2f0100211620032002411a6a29010037039806200320013a009706200320063a009606200320073b019406200320083a009306200320093a0092062003200a3b0190062003200b3a008f062003200c3a008e062003200d3b018c062003200e3a008b062003200f3a008a06200320103b018806200320113a008706200320123a008606200320133b018406200320143a008306200320153a008206200320163b018006200341a0066a200341c0016a10d306200341c0076a20032802a006220120032802a80610b20220032903c0072105200341f8046a200341c8076a418801109d081a024020054202510d00200341f0036a200341f8046a418801109d081a024020032802a406450d00200110350b200341e8026a200341f0036a418801109d081a200341e0016a200341e8026a418801109d081a200320053703b006200341b0066a41086a200341e0016a418801109d081a200341f0036a41186a2201200341b0066a41206a290300370300200341f0036a41106a2202200341b0066a41186a290300370300200341f0036a41086a2206200341b0066a41106a290300370300200320032903b8063703f00320054201520d02200341e0066a2903002104200341d8066a290300211a200341c0076a410e6a2006290300370100200341c0076a41166a2002290300370100200341c0076a411e6a20012903002205370100200341f8046a411e6a22072005370100200320032903f0033701c607200341f8046a41086a200341c0076a41086a290100370300200341f8046a41106a200341c0076a41106a290100370300200341f8046a41186a200341c0076a41186a290100370300200320032901c0073703f804200120072901003703002002200341f8046a41166a2901003703002006200341f8046a410e6a290100370300200320032901fe043703f003200341f0036a20034180066a412010a0080d02200341c0076a200341fc066a10d20620033502c80742208620032802c0072201ad841007024020032802c407450d00200110350b200341c0076a200341c0016a10d30620033502c80742208620032802c0072201ad841007024020032802c407450d00200110350b2003201a3703e802200320043703f0020240201a200484500d00200320034180066a3602e001200341f8046a20034180066a200341e8026a200341e0016a10f00220032903f8044201520d002003290380052105200341f8076a200341f8046a41106a290300370300200341f0076a2005370300200341c0076a41086a41003a0000200341c9076a200329038006370000200341d1076a20034180066a41086a290300370000200341d9076a20034180066a41106a290300370000200341e1076a20034198066a290300370000200341033a00c00741b0b4cc004100200341c0076a10d4010b200341c0076a41086a410a3a0000200341c9076a20032903c001370000200341d1076a200341c0016a41086a290300370000200341d9076a200341d0016a290300370000200341e1076a200341d8016a2903003700002003410c3a00c00741b0b4cc004100200341c0076a10d401200341f4066a2802002201450d13200141306c450d1320032802f00610350c130b024020032802a406450d00200110350b41adadc8002102410a21064180801021070c020b410021070c020b41a4adc800210241092106418080142107200341f4066a2802002201450d00200141306c450d0020032802f00610350b410321010b20004200370308200041206a20063602002000411c6a2002360200200041186a20074180801c7120017241802272360200420121050c100b200141386a2903002105200141306a29030021042001412c6a2802002108200141286a2802002106200141246a280200210720034180036a200141196a290000370300200341f8026a200141116a290000370300200341f0026a200141096a290000370300200320012900013703e80220032002411a6a290100370390052003200241026a2901003703f80420032002410a6a290100370380052003200241126a290100370388050240024020022d00014101470d0020022d000041ff01710d00200341f0036a41186a200341f8046a41186a2202290300370300200341f0036a41106a200341f8046a41106a2209290300370300200341f0036a41086a200341f8046a41086a220a290300370300200320032903f8043703f0034182a20c2101200341f0036a10e902450d0b2008ad4220862007ad8410092201290000211a200141086a290000211b200141106a290000211c2002200141186a2900003703002009201c370300200a201b3703002003201a3703f80420011035200341c0076a200341f8046a10d206200341f8006a20032802c007220220032802c80741b0b4cc0041004100108a0220032802782101024020032802c407450d00200210350b20014101460d012003200341e8026a3602c4072003200341f8046a3602c007200341b0066a200341c0076a10a706200341c0076a200341f8046a10d20620032802c0072101200320032802c8073602e401200320013602e00120072008200341e0016a109403024020032802c407450d00200110350b20032903b006211a20032903b806211b20032903c006211c200341e1076a20032903c806370000200341d9076a201c370000200341d1076a201b370000200341c9076a201a370000200341c0076a41086a41073a00002003410c3a00c00741b0b4cc004100200341c0076a10d401413010332201450d1220012004370320200120032903f003370000200141286a2005370300200141186a200341f0036a41186a290300370000200141106a200341f0036a41106a290300370000200141086a200341f0036a41086a29030037000020034184086a42818080801037020020034194086a200341f8046a41086a2903003702002003419c086a200341f8046a41106a290300370200200341a4086a200341f8046a41186a2903003702002003200136028008200341003602f807200342003703c007200320032903f80437028c08200341b4086a200341e8026a41086a290300370200200341bc086a200341e8026a41106a290300370200200341c4086a200341e8026a41186a290300370200200320032903e8023702ac08200341e0016a200341b0066a10d30620032802e0012102200320032802e801360284062003200236028006200341c0076a20034180066a10cd06024020032802e401450d00200210350b200110352006450d0f200710350c0f0b4182a20c21010c0a0b4183a20c21010c090b200141306a2903002105200141286a2903002104200341c0016a41186a200141196a290000370300200341c0016a41106a200141116a290000370300200341c0016a41086a200141096a290000370300200320012900013703c0014182a21021010240024002400240024002400240024020022d00000d0020022d00014101470d00200241196a2d00002106200241186a2d00002107200241166a2f01002108200241156a2d00002109200241146a2d0000210a200241126a2f0100210b200241116a2d0000210c200241106a2d0000210d2002410e6a2f0100210e2002410d6a2d0000210f2002410c6a2d000021102002410a6a2f01002111200241096a2d00002112200241086a2d00002113200241066a2f01002114200241056a2d00002115200241046a2d00002116200241026a2f0100211820032002411a6a29010037039806200320063a009706200320073a009606200320083b019406200320093a0093062003200a3a0092062003200b3b0190062003200c3a008f062003200d3a008e062003200e3b018c062003200f3a008b06200320103a008a06200320113b018806200320123a008706200320133a008606200320143b018406200320153a008306200320163a008206200320183b01800620034180066a10e902450d00200341f8046a41186a200341c0016a41186a290300370300200341f8046a41106a200341c0016a41106a290300370300200341f8046a41086a200341c0016a41086a290300370300200320032903c0013703f804200341a0066a200341f8046a10d406200341c0076a20032802a006220120032802a80610b20220032903c007211a200341f8046a200341c0076a41086a418801109d081a0240201a4202510d00200341f0036a200341f8046a418801109d081a024020032802a406450d00200110350b200341e8026a200341f0036a418801109d081a200341e0016a200341e8026a418801109d081a2003201a3703b006200341b0066a41086a200341e0016a418801109d081a200341f0036a41186a20034180066a41186a290300370300200341f0036a41106a20034180066a41106a290300370300200341f0036a41086a20034180066a41086a29030037030020032003290380063703f00320032802f006210841002101200341f8066a280200220d41014b0d020240200d0e020004000b200341c0076a41186a200341f0036a41186a290300370300200341c0076a41106a200341f0036a41106a290300370300200341c0076a41086a200341f0036a41086a290300370300200320032903f0033703c00741002106200341c0076a21020c040b024020032802a406450d00200110350b4183a21021010b200041206a410a3602002000411c6a41adadc800360200200041186a200136020020004200370308420121050c150b200d210203402002410176220620016a220720012008200741306c6a200341f0036a412010a0084101481b2101200220066b220241014b0d000b0b2008200141306c6a2202200341f0036a412010a0082206450d01200341c0076a41186a200341f0036a41186a290300370300200341c0076a41106a200341f0036a41106a290300370300200341c0076a41086a200341f0036a41086a290300370300200320032903f0033703c007200341c0076a2102200d2006411f7620016a2206490d040b0240200d200341f4066a280200470d00200341f0066a200d410110880120032802f00621080b2008200641306c6a220141306a2001200d20066b41306c109e081a200141286a200537030020012004370320200141186a200241186a290300370300200141106a200241106a290300370300200141086a200241086a290300370300200120022903003703002003200d41016a220d3602f8060c010b200d20014d0d0120032901f203211a20032901fa03211b200328018204210620032f0186042107200329038804211c200220032f01f0033b01002008200141306c6a220120043703202001201c370318200120073b0116200120063601122001201b37010a2001201a370102200141286a20053703000b200341c0076a10e80220032802c00721250240200d450d00202520032802c80722014105746a210920032802f006210e2025410020011b2102202541206a202520011b21014100210c4100210a0340200a220b41016a210a200e200b41306c6a2108024002400340024020020d00410021020c020b20022008412010a008220641004a0d0141002001200120094622071b21022001200141206a20071b2207210120064100480d000b024002400240200c0d004100210c0c010b200b200c6b2201200d4f0d01200341f8046a41286a2206200e200141306c6a220141286a220b290300370300200341f8046a41206a220f200141206a2210290300370300200341f8046a41186a2211200141186a2212290300370300200341f8046a41106a2213200141106a2214290300370300200341f8046a41086a2215200141086a2216290300370300200320012903003703f804200841086a22182903002105200841106a22192903002104200841186a2222290300211a200841206a2223290300211b2008290300211c200b200841286a22242903003703002010201b3703002012201a37030020142004370300201620053703002001201c370300202420062903003703002023200f290300370300202220112903003703002019201329030037030020182015290300370300200820032903f8043703000b200721010c020b2001200d41f485cc001042000b200c41016a210c0b200a200d470d000b200c417f6a200d4f0d002003200d200c6b3602f8060b024020032802c40741ffffff3f71450d00202510350b200341f8046a41186a4200370300200341f8046a41106a22064200370300200341f8046a41086a22014200370300200342003703f80441a0e4cb00ad42808080808002841001220229000021052001200241086a290000370300200320053703f804200210354189eaca00ad4280808080f00084100122022900002105200341e8026a41086a2207200241086a290000370300200320053703e80220021035200620032903e8022205370300200341c0076a41086a2001290300370300200341c0076a41106a2005370300200341c0076a41186a2007290300370300200320032903f8043703c007200341f8046a200341c0076a10a20220032802f804210120032902fc042105200341003602c807200342013703c007200341c0076a41002005420020011b2205422088a7220241306c220741306d108a012005a721082001410820011b210920032802c807210602402002450d0020032802c00720064105746a2101200921020340200241086a2900002105200241106a29000021042002290000211a200141186a200241186a290000370000200141106a2004370000200141086a20053700002001201a370000200641016a2106200141206a2101200241306a2102200741506a22070d000b0b200320063602c80702402008450d00200841306c450d00200910350b024020032802c40741ffffff3f71450d0020032802c00710350b024020032802f806200641016a410176490d0020032802e8064101460d00200341c0076a41186a4200370300200341c0076a41106a22064200370300200341c0076a41086a22014200370300200342003703c00741d1c4c700ad4280808080e000841001220229000021052001200241086a290000370300200320053703c0072002103541e7c4c700ad4280808080e00084100122022900002105200341e8026a41086a2207200241086a290000370300200320053703e80220021035200620032903e8022205370300200341f8046a41086a22022001290300370300200341f8046a41106a22062005370300200341f8046a41186a22082007290300370300200320032903c0073703f80420034180016a200341f8046a412010c001200341ec066a2003280284014180e1016a4180e1012003280280011b360200200341013602e8062008200341c0016a41186a22072903003703002006200341c0016a41106a22082903003703002002200341c0016a41086a2206290300370300200320032903c0013703f804200141083a00002003410c3a00c007200341c9076a20032903c001370000200341d1076a2006290300370000200341d9076a2008290300370000200341e1076a200729030037000041b0b4cc004100200341c0076a10d4010b200341c0076a200341b0066a419001109d081a200341f8046a200341c0016a10d30620032802f804210120032003280280053602f403200320013602f003200341c0076a200341f0036a10cd06024020032802fc04450d00200110350b20034184086a2802002201450d0e200141306c450d0e20032802800810350c0e0b2001200d41bc82ca001042000b2006200d104d000b20004200370308200041206a41143602002000411c6a41cfadc800360200200041186a2002360200420121050c0d0b103e000b4104210741adadc8002108410a2109410221060240024020022d00000d0020022d00014101470d00200141186a2d00002126200141176a2d00002127200141156a2f00002128200141146a2d00002129200141136a2d0000212a200141116a2f0000212b200141106a2d0000212c2001410f6a2d0000212d2001410d6a2f0000212e2001410c6a2d0000212f2001410b6a2d00002130200141096a2f00002131200141086a2d00002132200141076a2d00002133200141056a2f00002134200141046a2d00002135200141036a2d0000213620012f000121372003200141196a290000221737039005200320263a008f05200320273a008e05200320283b018c05200320293a008b052003202a3a008a052003202b3b0188052003202c3a0087052003202d3a0086052003202e3b0184052003202f3a008305200320303a008205200320313b018005200320323a00ff04200320333a00fe04200320343b01fc04200320353a00fb04200320363a00fa04200320373b01f80420034180066a200341f8046a10d406200341c0076a200328028006220120032802880610b20220032903c0072105200341f8046a200341c8076a418801109d081a024002400240024020054202510d00200341f0036a200341f8046a418801109d081a0240200328028406450d00200110350b200341e8026a200341f0036a418801109d081a200341e0016a200341e8026a418801109d081a200320053703b006200341b0066a41086a200341e0016a418801109d081a20032802e8064101460d01419badc8002108410621070c020b200328028406450d02200110350c020b200341c0076a41186a4200370300200341c0076a41106a22064200370300200341c0076a41086a22014200370300200342003703c00741d1c4c700ad4280808080e000841001220229000021052001200241086a290000370300200320053703c0072002103541e7c4c700ad4280808080e00084100122022900002105200341e8026a41086a2207200241086a290000370300200320053703e80220021035200620032903e8022205370300200341f8046a41086a2001290300370300200341f8046a41106a2005370300200341f8046a41186a2007290300370300200320032903c0073703f804200341b8016a200341f8046a412010c00120032802bc01410020032802b8011b200341ec066a2802004f0d034192adc8002108410721070b0240200341f4066a2802002201450d00200141306c450d0020032802f00610350b410921090b410321060b20004200370308200041206a20093602002000411c6a2008360200200041186a200741107420067241802272360200420121050c0c0b200341c0076a200341fc066a10d20620033502c80742208620032802c0072201ad841007024020032802c407450d00200110350b200320173703d807200320263a00d707200320273a00d607200320283b01d407200320293a00d3072003202a3a00d2072003202b3b01d0072003202c3a00cf072003202d3a00ce072003202e3b01cc072003202f3a00cb07200320303a00ca07200320313b01c807200320323a00c707200320333a00c607200320343b01c407200320353a00c307200320363a00c207200320373b01c007200341f8046a200341c0076a10d40620033502800542208620032802f8042201ad841007024020032802fc04450d00200110350b200341c0076a200341b0066a419001109d081a20034188086a280200211620034184086a28020021382003280280082112200341f0036a10e80220032802f00321250240024020160d00410021160c010b202520032802f80322014105746a21092025410020011b2102202541206a202520011b21014100210c4100210a0340200a220b41016a210a2012200b41306c6a2108024002400340024020020d00410021020c020b20022008412010a008220641004a0d0141002001200120094622071b21022001200141206a20071b2207210120064100480d000b024002400240200c0d004100210c0c010b200b200c6b220120164f0d01200341f8046a41286a22062012200141306c6a220141286a220b290300370300200341f8046a41206a220d200141206a220e290300370300200341f8046a41186a220f200141186a2210290300370300200341f8046a41106a2211200141106a2213290300370300200341f8046a41086a2214200141086a2215290300370300200320012903003703f804200841086a22182903002105200841106a22192903002104200841186a2222290300211a200841206a2223290300211b2008290300211c200b200841286a2224290300370300200e201b3703002010201a37030020132004370300201520053703002001201c370300202420062903003703002023200d2903003703002022200f2903003703002019201129030037030020182014290300370300200820032903f8043703000b200721010c020b2001201641f485cc001042000b200c41016a210c0b200a2016470d000b200c450d0020162016200c6b220120162001491b21160b024020032802f40341ffffff3f71450d00202510350b20164115490d032016410176ad42307e2205422088a70d012005a72239417f4c0d0120391033223a450d0041002102200341003602f803200342043703f003201241506a213b201241907f6a213c410421064100213d20162111034020112109410021114101210a02402009417f6a223e450d000240024002400240024002402012203e41306c6a220141206a290300200941306c220820126a41406a2207290300220454200141286a290300221a200741086a290300220554201a2005511b0d002009417e6a210c203c20086a2101410021114100210703400240200c2007470d002009210a0c080b20042001290300221b5a21082005200141086a290300221a51210a2005201a5a210b200141506a2101200741016a2107201b2104201a21052008200b200a1b0d000b200741016a210a2007417f7320096a21080c010b203c200941066c410374220c6a2101203e210802400340024020084101470d00410021080c020b20042001290300221b5421072005200141086a290300221a51210a2005201a54210b200141506a21012008417f6a2108201b2104201a21052007200b200a1b0d000b0b20092008490d02200920164b0d01200920086b220a410176220b450d00203b200c6a21012012200841306c6a21070340200341f8046a41286a220c200741286a220d290300370300200341f8046a41206a220e200741206a220f290300370300200341f8046a41186a2210200741186a2211290300370300200341f8046a41106a2213200741106a2214290300370300200341f8046a41086a2215200741086a2218290300370300200320072903003703f804200141086a22192903002105200141106a22222903002104200141186a2223290300211a200141206a2224290300211b200141286a2225290300211c20072001290300370300200d201c370300200f201b3703002011201a37030020142004370300201820053703002025200c2903003703002024200e290300370300202320102903003703002022201329030037030020192015290300370300200120032903f804370300200141506a2101200741306a2107200b417f6a220b0d000b0b024020080d00200821110c050b0240200a41094d0d00200821110c050b200920164b0d022012200841306c6a210d034020092008417f6a2211490d040240200920116b220a4102490d002012200841306c6a220141206a220b2903002012201141306c6a220741206a220c290300221a5a200141286a220e2903002204200741286a220f29030022055a20042005511b0d002007290300210420072001290300370300200341f8046a41186a2210200741186a2213290300370300200341f8046a41106a2214200741106a2215290300370300200341f8046a41086a2218200741086a22192903003703002019200141086a2903003703002015200141106a2903003703002013200141186a290300370300200c200b290300370300200f200e290300370300200320043703f8040240200a4103490d00203e210b200d210c20074180016a290300201a5a20074188016a290300220420055a20042005511b0d0002400340200c220141286a200141d8006a290300370300200141206a200141d0006a290300370300200141186a200141c8006a290300370300200141106a200141c0006a290300370300200141086a200141386a2903003703002001200141306a220c2903003703002008200b417f6a220b460d0120014180016a290300201a5a20014188016a290300220420055a20042005511b450d000b0b200141306a21010b2001201a370320200120032903f804370300200141286a2005370300200141186a2010290300370300200141106a2014290300370300200141086a20182903003703000b2011450d05200d41506a210d20112108200a410a4f0d050c000b0b2009201641eccfca001058000b2008200941eccfca001059000b20092008417f6a2211490d002009201641fccfca001058000b2011200941fccfca001059000b0240203d20032802f403470d00200341f0036a203d410110900120032802f003210620032802f8032202213d0b2006203d4103746a2201200a360204200120113602002003200241016a22023602f8032002213d024020024102490d000240024003400240024002400240024020062002417f6a4103746a2201280200450d00200241037420066a220941746a2802002208200128020422074b0d010b20024103490d022001280204210720062002417d6a220e4103746a28020421010c010b4102213d200241024d0d0620062002417d6a220e4103746a2802042201200720086a4d0d004103213d200241034d0d06200941646a280200200120086a4b0d050b20012007490d010b2002417e6a210e0b02400240024002400240024002402002200e41016a220f4d0d002002200e4d0d012006200e41037422136a2201280204221420012802006a22012006200f41037422156a22022802002210490d02200120164b0d032012201041306c6a220c2002280204220d41306c22026a2107200141306c2106200120106b2209200d6b2201200d4f0d04203a2007200141306c2202109d08220920026a2108200d4101480d0520014101480d05203b20066a21062007210103402006200141506a220a200841506a220b200841706a2202290300200141706a220729030054200241086a2903002205200741086a29030022045420052004511b22071b2202290300370300200641086a200241086a290300370300200641106a200241106a290300370300200641186a200241186a290300370300200641206a200241206a290300370300200641286a200241286a2903003703002008200b20071b21080240200c200a200120071b2201490d00200921020c080b200641506a21062009210220092008490d000c070b0b200f2002418cd0ca001042000b200e2002419cd0ca001042000b2010200141acd0ca001059000b2001201641acd0ca001058000b203a200c2002109d08220b20026a21080240200d4101480d002009200d4c0d00201220066a210a200b2102200c21010340200120072002200741206a290300200241206a29030054200741286a2903002205200241286a29030022045420052004511b22091b2206290300370300200141086a200641086a290300370300200141106a200641106a290300370300200141186a200641186a290300370300200141206a200641206a290300370300200141286a200641286a2903003703002002200241306a20091b2102200141306a2101200741306a200720091b2207200a4f0d03200820024b0d000c030b0b200c2101200b21020c010b20072101200921020b20012002200820026b220620064130706b109d081a024020032802f8032201200e4d0d0020032802f003220620136a22022014200d6a360204200220103602002001200f4d0d02200620156a2202200241086a2001200f417f736a410374109e081a20032001417f6a22023602f803200241014b0d010c030b0b200e200141bcd0ca001042000b200f2001104e000b2002213d0b2011450d030c000b0b1045000b1044000b024020032802f40341ffffffff0171450d00200610350b2039413070210120394130490d0120392001460d01203a10350c010b20164102490d002016417f6a21062012201641306c6a2108410021090340024002400240201620062201417f6a2206490d00201620066b22074102490d022012200141306c6a220141206a220a2903002012200641306c6a220241206a220b290300221a5a200141286a220c2903002204200241286a220d29030022055a20042005511b0d022002290300210420022001290300370300200341f8046a41186a220e200241186a220f290300370300200341f8046a41106a2210200241106a2211290300370300200341f8046a41086a2213200241086a22142903003703002014200141086a2903003703002011200141106a290300370300200f200141186a290300370300200b200a290300370300200d200c290300370300200320043703f80420074103490d01200921072008210a20024180016a290300201a5a20024188016a290300220420055a20042005511b0d010340200a220141506a22022001290300370300200241286a200141286a290300370300200241206a200141206a290300370300200241186a200141186a290300370300200241106a200141106a290300370300200241086a200141086a2903003703002007417f6a2207450d02200141306a210a200141d0006a290300201a5a200141d8006a290300220420055a20042005511b0d020c000b0b2006201641dccfca001059000b2001201a370320200120032903f804370300200141286a2005370300200141186a200e290300370300200141106a2010290300370300200141086a20132903003703000b200941016a2109200841506a210820060d000b0b200342f0f2bda1a7ee9cb9f9003703f804200341e0016a200341f8046a10e001200342f0f2bda1a7ee9cb9f9003703f804200341f0036a200341f8046a10e001200341e8026a200341f0036a108e02200341f8046a20032802e802220120032802f002108f0220032903f804210520034188056a2903002104200329038005211a024020032802ec02450d00200110350b02402016201641017622014d0d00420020044200200542015122021b2204201a420020021b2205428080e983b1de1654ad7d221a200542808097fccea1697c221b200556201a200456200542ffffe883b1de16561b22021b22052012200141306c6a220141286a29030022042001290320221a4200201b20021b221b56200420055620042005511b22011b2104201b201a20011b2105024020032903c0074201520d00200341e8026a41186a200341c0076a41206a290300370300200341e8026a41106a200341c0076a41186a290300370300200341f0026a200341c0076a41106a290300370300200320032903c8073703e802200341c0076a41286a290300211a2003200341c0076a41306a290300221b370388062003201a370380060240201a201b84500d002003200341e8026a3602c001200341f0036a200341e8026a20034180066a200341c0016a10f00220032903f0034201520d0020032903f803211a200341b0056a200341f0036a41106a290300370300200341a8056a201a370300200341f8046a41086a41003a000020034181056a20032903e80237000020034189056a200341e8026a41086a29030037000020034191056a200341e8026a41106a29030037000020034199056a20034180036a290300370000200341033a00f80441b0b4cc004100200341f8046a10d4010b200341e8026a200341ac086a412010a008450d00200341a8016a2005200442e400420010980820034198016a20032903a801221a200341a8016a41086a290300221b429c7f427f10840820034188016a201a201b42144200108408200341f8046a200341e0016a200341e8026a200329038801221b20052003290398017ca741ff0071220141056e2202200141146c2002419c7f6c6a41fcff037141324b6aad7c221a20034188016a41086a290300201a201b54ad7c221b410010e6022004201b7d2005201a54ad7d21042005201a7d21050b200341f8046a200341e0016a200341ac086a20052004410010e60220034199056a201737000020034198056a20263a000020034197056a20273a000020034195056a20283b000020034194056a20293a000020034193056a202a3a000020034191056a202b3b000020034190056a202c3a00002003418f056a202d3a00002003418d056a202e3b00002003418c056a202f3a00002003418b056a20303a000020034189056a20313b000020034188056a20323a000020034187056a20333a000020034185056a20343b000020034183056a20363a0000200341f8046a41096a20373b000020034180056a41093a00002003410c3a00f804200341f8046a410c6a20353a0000200341c8056a2005370300200341d0056a2004370300200341b9056a200341c4086a290200370000200341b1056a200341bc086a290200370000200341a9056a200341b4086a290200370000200341a1056a20032902ac0837000041b0b4cc004100200341f8046a10d4012038450d05203841306c450d05201210350c050b2001201641cc82ca001042000b02402006450d00200710350b20004200370308200041206a410c3602002000411c6a41b7adc800360200200041186a2001360200420121050c050b41b7adc800210a410c21094111210841032107410321010c010b0b02402006450d00200b10350b20004200370308200041206a20093602002000411c6a200a360200200041186a2002411874200741ff017141107472200841ff017141087472200141ff017172360200420121050c020b420021050b200020053703080b20002005370300200341d0086a24000f0b103c000bbd930106147f027e0c7f017e027f017e230041e0046b22042400200441c0036a20012002200310ed06200441c0036a41086a280200210520042802c40321060240024002400240024020042802c0034101460d00200441d4036a280200220741306c2108200441d8036a2802002109200441d0036a280200210a200441cc036a280200210b4100210c4100210102400340024020082001470d000c020b200b20016a2102200141306a220d210120022d00004102470d000b200441d8006a200b200d6a41546a10bf032004280258210c200428025c21010b4100210e20014100200c1b210f200741306c2108200c41b0b4cc00200c1b21104100210102400340024020082001470d000c020b200b20016a2102200141306a220d210120022d00004108470d000b200441d0006a200b200d6a41546a10bf032004280250210e200428025421010b4100211120014100200e1b2112200741306c2108200e41b0b4cc00200e1b210c4100210102400340024020082001470d000c020b200b20016a2102200141306a220d210120022d00004104470d000b200441c8006a200b200d6a41546a10bf0320042802482111200428024c21010b4100210e2001410020111b2113200741306c2108201141b0b4cc0020111b21114100210102400340024020082001470d000c020b200b20016a2102200141306a220d210120022d00004103470d000b200441c0006a200b200d6a41546a10bf032004280240210e200428024421010b41002102024020014100200e1b2201450d00200141286c2108200e41b0b4cc00200e1b41186a2101410021020340200220012d0000456a2102200141286a2101200841586a22080d000b0b024020120d00411e210120004185d6cb003602040c030b200c201241146c6a211241002114410021150240034041a3d6cb00210841382101200c41086a280200417c6a220e41024b0d01200c280200210d024002400240200e0e03000401000b41012115200d41fbd5cb00460d01200d28000041e3c2b1e306460d010c030b41012114200d41ffd5cb00460d00200d41ffd5cb00410610a0080d020b0240200c410c6a280200450d0041132101200041a1d7cb003602040c050b0240200c41106a280200220120026b220d20014d0d00412a2101200041b4d7cb003602040c050b41fbd6cb002108412621012013200d4d0d012011200d4102746a220d450d0141dbd6cb00210841202101200f200d280200220d4d0d012010200d4104746a220d450d0141ded7cb002108411f2101200d2802080d01200d2d000d220d41077141044b0d010240200d0e050002020200000b200c41146a220c2012470d000b20142015714101710d02411c411e201441017122021b2101200041fdd7cb004185d6cb0020021b3602040c030b200020083602040c020b2000200636020420004101360200200041086a20053602000c030b200741306c2108410021010240024002400240034020082001460d01200b20016a2102200141306a220d210120022d00004106470d000b200441386a200b200d6a41546a10bf03200428023c0d010b200741306c2108200328028001210c410021010240034020082001460d01200b20016a2102200141306a220d210120022d00004105470d000b200441306a200b200d6a41546a220110bf030240200428023441014d0d0041182101200041e8d3cb003602040c050b200441286a200110bf03200428022c450d0020042802282201450d002001280200200c4d0d004122210120004180d4cb003602040c040b200741306c2108410021010240034020082001460d01200b20016a2102200141306a220d210120022d00004107470d000b200441206a200b200d6a41546a10bf032004280220220120042802244104746a2108034020012008460d012001450d012001410c6a2102200141106a210120022d0000410271450d000b413221012000418cd5cb003602040c040b200741306c2108410021010240034020082001460d01200b20016a2102200141306a220d210120022d0000410c470d000b200b200d6a2201415c6a2802002202450d00200141546a280200220d200241186c6a210c0340200d220241186a210d2002280208410374210120022802002102024003402001450d01200141786a210120022d00042108200241086a21022008410271450d000b41312101200041dbd4cb003602040c060b200d200c470d000b0b200741306c2108410021010240034020082001460d01200b20016a2102200141306a220d210120022d00004102470d000b200441186a200b200d6a41546a10bf03200428021c2201450d002004280218220220014104746a210e03402002450d01200241106a210c200420022d000d22083a00c0032002280200220120022802086a210d4100200441c0036a20084104461b210802400340024002402001450d00200d2001460d0020012102200141016a21010c010b2008450d024100210120082102410021080b20022d0000410271450d000b41392101200041a2d4cb003602040c060b200c2102200c200e470d000b0b200741306c21084100210c4100210102400340024020082001470d000c020b200b20016a2102200141306a220d210120022d00004102470d000b200441106a200b200d6a41546a10bf032004280210210c200428021421010b4100210e20014100200c1b2110200741306c2108200c41b0b4cc00200c1b21124100210102400340024020082001470d000c020b200b20016a2102200141306a220d210120022d00004103470d000b200441086a200b200d6a41546a10bf032004280208210e200428020c21010b200e41b0b4cc00200e1b220220014100200e1b41286c6a210d41002113034002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402002200d460d00412d210141ecbcca00210820022802084103470d0902402002280200220c41a58ecc00460d00200c41a58ecc00410310a0080d0a0b200241286a21114115210c41e5bbca00210e4114210141d8bcca0021080240024020022d00180e04010b0022010b412f21014199bdca00210820022802144106470d0a0240200228020c220c41a9bbca00460d00200c41a9bbca00410610a0080d0b0b2013450d02411f2101200041c8bdca003602040c270b4136210c41afbbca00210e2010200228021c22014d0d20201220014104746a220f450d202002280214210c200228020c2102024020092d0088010d00200c410b470d004138210141a0bcca002108200241bfe2cb00460d0a200241bfe2cb00410b10a008450d0a0c200b4126210141fabbca002108200c417d6a220c41144b0d09024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200c0e15003030301208300d46060b160118031f1430101d21000b200241a88ecc00460d2f200241a88ecc00410310a008450d2f41a88ecc002002410310a0080d2f41011033220e0d010c4d0b200241c6dfcb00460d0241c6dfcb002002410f10a008450d02200241e6dfcb00460d0541e6dfcb002002410f10a008450d05024020024189e0cb00460d004189e0cb002002410f10a0080d2f0b41071033220e450d4c200e4100360003200e41013a0002200e41003b0000200f2d000c41e000460d0a0c430b200e41003a0000200f2d000c41e000470d41200f2802084101470d410240200f2802002214200e460d0041002102034020024101460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d430c000b0b200f2d000d4104470d41200e1035201121020c460b200241d5dfcb00460d0141d5dfcb002002411110a008450d01200241b6e1cb00460d1341b6e1cb002002411110a008450d13200241f5e1cb00460d1841f5e1cb002002411110a008450d1820024186e2cb00460d1a4186e2cb002002411110a008450d1a0240200241f1e2cb00460d0041f1e2cb002002411110a0080d2d0b41031033220e450d4a200e41003a0002200e41003b0000200f2d000c41e000460d1f0c3f0b41031033220e450d49200e41003a0002200e41003b0000200f2d000c41e000470d3d200f2802084103470d3d0240200f2802002214200e460d0041002102034020024103460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d3f0c000b0b200f2d000d4104470d3d200e1035201121020c440b41011033220e450d48200e41003a0000200f2d000c41e000470d3b200f2802084101470d3b0240200f2802002214200e460d0041002102034020024101460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d3d0c000b0b200f2d000d4104470d3b200e1035201121020c430b200241f5dfcb00460d0241f5dfcb002002410c10a008450d020240200241d1e0cb00460d0041d1e0cb002002410c10a0080d2a0b4126210c41fabbca00210e200f2d000c41e000470d40200f2802080d4020112102200f2d000d4104460d420c400b41011033220e450d46200e41003a0000200f2d000c41e000470d38200f2802084101470d38200f2802002214200e460d3741002102034020024101460d38200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d390c000b0b024020024181e0cb00460d00200229000042e5f0d1fbb5ac98b6ec00520d280b41071033220e450d45200e4100360003200e41013a0002200e41003b0000200f2d000c41e000460d010c350b41041033220e450d44200e4100360000200f2d000c41e000470d33200f2802084104470d33200f2802002214200e460d3241002102034020024104460d33200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d340c000b0b200f2802084107470d33200f2802002214200e460d3041002102034020024107460d31200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d340c000b0b20024198e0cb00460d024198e0cb002002410d10a008450d020240200241c4e0cb00460d0041c4e0cb002002410d10a0080d250b4126210c41fabbca00210e200f2d000c41e000470d3b200f2802080d3b20112102200f2d000d4104460d3d0c3b0b200f2802084107470d38200f2802002214200e460d2d41002102034020024107460d2e200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d390c000b0b200241a5e0cb00460d0141a5e0cb002002410a10a008450d010240200241afe0cb00460d0041afe0cb002002410a10a0080d040b4126210c41fabbca00210e200f2d000c41e000470d39200f2802080d3920112102200f2d000d4104460d3b0c390b41021033220e450d3f200e41003b0000200f2d000c41e000470d2a200f2802084102470d2a0240200f2802002214200e460d0041002102034020024102460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d2c0c000b0b200f2d000d4104470d2a200e1035201121020c3a0b41021033220e450d3e200e41003b0000200f2d000c41e000470d28200f2802084102470d280240200f2802002214200e460d0041002102034020024102460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d2a0c000b0b200f2d000d4104470d28200e1035201121020c390b0240200241e8e0cb00460d0041e8e0cb002002411510a0080d050b4126210c41fabbca00210e200f2d000c41e000470d36200f2802080d3620112102200f2d000d4104460d380c360b0240200241fde0cb00460d0041fde0cb002002410a10a0080d1f0b41021033220e450d3c200e41003b0000200f2d000c41e000460d010c250b024020024187e1cb00460d004187e1cb002002410710a0080d1e0b4126210c41fabbca00210e200f2d000c41e000470d34200f2802080d3420112102200f2d000d4104460d360c340b200f2802084102470d230240200f2802002214200e460d0041002102034020024102460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d250c000b0b200f2d000d4104470d23200e1035201121020c350b02402002418ee1cb00460d00418ee1cb002002411310a0080d0e0b4126210c41fabbca00210e200f2d000c41e000470d32200f2802080d3220112102200f2d000d4104460d340c320b0240200241a1e1cb00460d0041a1e1cb002002411510a0080d1b0b4126210c41fabbca00210e200f2d000c41e000470d31200f2802080d3120112102200f2d000d4104460d330c310b0240200241c7e1cb00460d0041c7e1cb002002410e10a0080d1a0b41081033220e450d37200e4200370000200f2d000c41e000460d020c1f0b41021033220e450d36200e41003b0000200f2d000c41e000470d1d200f2802084102470d1d0240200f2802002214200e460d0041002102034020024102460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d1f0c000b0b200f2d000d4104470d1d200e1035201121020c310b200241d5e1cb00460d0141d5e1cb002002411010a008450d01200241e5e1cb00460d0241e5e1cb002002411010a008450d020240200241cae2cb00460d0041cae2cb002002411010a0080d180b4126210c41fabbca00210e200f2d000c41e000470d2e200f2802080d2e20112102200f2d000d4104460d300c2e0b200f2802084108470d1c0240200f2802002214200e460d0041002102034020024108460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d1e0c000b0b200f2d000d4104470d1c200e1035201121020c2f0b4126210c41fabbca00210e200f2d000c41e000470d2c200f2802080d2c200f2d000d22014104460d2c20112102200141fb0171450d2e0c2c0b41031033220e450d32200e41003a0002200e41003b0000200f2d000c41e000470d18200f2802084103470d180240200f2802002214200e460d0041002102034020024103460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d1a0c000b0b200f2d000d4104470d18200e1035201121020c2d0b41021033220e450d31200e41003b0000200f2d000c41e000470d16200f2802084102470d160240200f2802002214200e460d0041002102034020024102460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d180c000b0b200f2d000d4104470d16200e1035201121020c2c0b024020024197e2cb00460d004197e2cb002002411610a0080d130b41021033220e450d30200e41003b0000200f2d000c41e000460d020c140b41041033220e450d2f200e4100360000200f2d000c41e000470d12200f2802084104470d120240200f2802002214200e460d0041002102034020024104460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d140c000b0b200f2d000d4104470d12200e1035201121020c2a0b0240200241ade2cb00460d0041ade2cb002002411210a0080d110b4126210c41fabbca00210e200f2d000c41e000470d27200f2802080d2720112102200f2d000d4104460d290c270b200f2802084102470d110240200f2802002214200e460d0041002102034020024102460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d130c000b0b200f2d000d4104470d11200e1035201121020c280b0240200241dae2cb00460d0041dae2cb002002411710a0080d0f0b410210332214450d2c201441003b0000200f2d000c41e000470d0d200f2802084102470d0d200f28020022152014460d0c41002102034020024102460d0d201420026a210c201520026a210e200241016a2102200e2d0000200c2d0000470d0e0c000b0b20024182e3cb00460d014182e3cb002002411310a008450d0120024195e3cb00460d024195e3cb002002411310a008450d020240200241a8e3cb00460d0041a8e3cb002002411310a0080d0e0b41031033220e450d2b200e41003a0002200e41003b0000200f2d000c41e000460d030c0a0b200f2802084103470d1f0240200f2802002214200e460d0041002102034020024103460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d210c000b0b200f2d000d4104470d1f200e1035201121020c250b41031033220e450d29200e41003a0002200e41003b0000200f2d000c41e000470d07200f2802084103470d070240200f2802002214200e460d0041002102034020024103460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d090c000b0b200f2d000d4104470d07200e1035201121020c240b41031033220e450d28200e41003a0002200e41003b0000200f2d000c41e000470d05200f2802084103470d050240200f2802002214200e460d0041002102034020024103460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d070c000b0b200f2d000d4104470d05200e1035201121020c230b200f2802084103470d060240200f2802002214200e460d0041002102034020024103460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d080c000b0b200f2d000d4104470d06200e1035201121020c220b410021164100211720130d010c020b2002411c6a2113201121020c200b024020132802040d00200041e7bdca00360204413221010c240b024020132802002216201341086a28020022174d0d0020004199beca0036020441c90021010c240b2017200328027c4d0d00200041e2beca0036020441c10021010c230b20092903082118200441c0036a410c6a22024100360200200441003602c4032009290310211920042018a7417f2018428080808010541b3602d00320042019a7417f2019428080808010541b3602c003200441c0036a4104722201410d10ee062001410c10ee062001410710ee062001410f10ee06200420042802c003360264200441c8036a220828020021122002280200211a20042802c403211320042802d003211b200441d0036a220d20073602002002200a3602002004200b3602c803200420053602c403200420063602c003200441e8006a200441c0036a10ef06410110332201450d23200141003a0000200420042f01c00322023b019002200d41e0083b01002008428180808010370300200420013602c403200441013602c003200420023b01d203200441e8006a200441c0036a10f006210c02400240410310332202450d00200241026a41002d00a78e4c3a0000200241002f00a58e4c3b0000410310332208450d00200841026a41002d00aa8e4c3a0000200841002f00a88e4c3b000020044190026a41026a200441c0036a41026a220b2d000022073a0000200420042f00c003220e3b019002200441fc006a280200210d200441e8006a41106a2802002101200b20073a00002004200e3b01c00302400240200d2001470d00200141016a220d2001490d012001410174220b200d200b200d4b1bad42287e2218422088a70d012018a7220d4100480d0102400240024020010d00200d0d014104210b0c020b2004280274210b200141286c2201200d460d01024020010d00200d0d014104210b0c020b200b2001200d1037220b450d290c010b200d1033220b450d280b2004200b3602742004200d41286e360278200428027c210d0b2004280274200d41286c6a220141003a00182001200836020c200142838080803037020420012002360200200141106a428380808030370200200141196a20042f01c0033b00002001411b6a200441c2036a2d00003a00002001411c6a200c3602002004200428027c41016a36027c200441c0036a200441e8006a418c01109d081a200441f8016a200441c0036a10f106200441f8016a41106a280200220e41306c2101200428028002220b41546a210202400340410021082001450d01200141506a21012002412c6a210d200241306a220c2102200d2d00004103470d000b200c41086a2802002201450d00200141286c2102200c28020041186a2101410021080340200820012d0000456a2108200141286a2101200241586a22020d000b0b200e41306c2101200b41546a21022008417f6a210d02400340410021082001450d01200141506a21012002412c6a210c200241306a22072102200c2d00004103470d000b200741086a2802002201450d00200141286c2102200728020041186a2101410021080340200820012d0000456a2108200141286a2101200241586a22020d000b0b200e41306c2101200b415c6a21020240034041002111024020010d00410021010c020b200141506a2101200241246a210c200241306a22072102200c2d00004104470d000b200728020021010b0240024002400240200e450d00200120086a211c200b200e41306c6a2115200441a0036a410c6a211d200441bc036a41046a211e200441a0036a41146a211f410021204100212103400240200b2d000041786a220141044b0d000240024002400240024020010e050301020500030b200b28020c2201450d04200b280204220c200141186c6a2122202021010340200121200240200c22082802144104742202450d00200828020c21010340024020012d0000410b470d00200141046a220c2802002207200d490d00200c200741016a3602000b200141106a2101200241706a22020d000b0b2008410c6a2106200442003703b00320044280808080c0003703a803200442043703a003200441a0036a41004101108c0120042802a00320042802a8034104746a22014200370200200141056a4200370000200420042802a80341016a3602a8030240024002400240024020082802142201450d002001ad21194200211803402018a721140240024002400240024002400240024020182001ad5a0d004110210202400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402006280200222320144104746a2d000022240eac010001020202020202020202020202020303030404050506060707080809090a0a0b0b0c0d0d0e0e0f0f1010111213131414151516161717181819191a1a1b1b1c1c1d1d1e1e1f1f2020212122222323242425252627272828292a2a2b2b2c2d2d2e2e2f2f303031313232333434353536363737383839393a3a3b3b3c3c3d3d3e3e3f3f40404141424243434444454546464747484a4a4a4a49494a4a4a4a4a4a4a4a4a4a4a4a4a4a4b4b4b4b000b411121020c4a0b411221020c490b410a21020c480b410821020c470b410821020c460b410421020c450b410421020c440b410421020c430b410421020c420b410421020c410b410421020c400b410421020c3f0b410521020c3e0b410521020c3d0b410521020c3c0b410521020c3b0b410521020c3a0b411321020c390b411421020c380b410621020c370b410721020c360b410b21020c350b410b21020c340b410b21020c330b410b21020c320b410b21020c310b410b21020c300b410b21020c2f0b410b21020c2e0b410b21020c2d0b410b21020c2c0b410b21020c2b0b410c21020c2a0b410c21020c290b410c21020c280b410c21020c270b410c21020c260b410c21020c250b410021020c240b410021020c230b410121020c220b410221020c210b410321020c200b410321020c1f0b410021020c1e0b410021020c1d0b410021020c1c0b410021020c1b0b410021020c1a0b410021020c190b410121020c180b410221020c170b410321020c160b410321020c150b410021020c140b410021020c130b410021020c120b410021020c110b410d21020c100b410d21020c0f0b410d21020c0e0b410d21020c0d0b410d21020c0c0b410d21020c0b0b410d21020c0a0b410d21020c090b410d21020c080b410d21020c070b410d21020c060b410d21020c050b410d21020c040b410d21020c030b410e21020c020b410e21020c010b410f21020b200441e4006a212502402013450d0020132107201221050340200741086a211020072f010621114100210c4100210102400240034020112001460d01201020016a210f200c41086a210c200141016a210102404100417f4101200f2d0000220f20024b1b200f2002461b41016a0e03000301000b0b2001417f6a21110b2005450d022005417f6a2105200720114102746a41ec006a28020021070c010b0b02402007200c6a2201410c6a2802000e0401140001010b200141106a21250b201842017c2118202528020021020240024002400240024002400240024002402024417e6a220141084b0d0020010e09010302050406060708010b20042802a8032201450d1a200141047420042802a0036a41786a220c280200220120026a22022001490d1a200c20023602000c0f0b20042802a8032201450d19200141047420042802a0036a41786a220c280200220120026a22022001490d19200c200236020020042802a8032202450d19200241047420042802a00322016a41746a28020021072002210c0240200220042802a403470d00200441a0036a20024101108c0120042802a803210c20042802a00321010b2001200c4104746a2201200e3b000d200141003a000c20012007360204200120023602002001410f6a200e4110763a0000200141086a4100360200200420042802a80341016a3602a8030c0e0b20042802a8032201450d18200141047420042802a0036a41786a220c280200220120026a22022001490d18200c200236020020042802a803220221010240200220042802a403470d00200441a0036a20024101108c0120042802a80321010b20042802a00320014104746a2201200e3b000d200141003a000c200120183e0204200120023602002001410f6a200e4110763a0000200141086a4100360200200420042802a80341016a3602a8030c0d0b20042802a8032201450d17200141047420042802a0036a41786a220c280200220120026a22022001490d17200c200236020020042802a803220221010240200220042802a403470d00200441a0036a20024101108c0120042802a80321010b20042802a00320014104746a2201200e3b000d200141013a000c200120183e0204200120023602002001410f6a200e4110763a0000200141086a4100360200200420042802a80341016a3602a8030c0c0b20042802a8032201450d16200141047420042802a0036a41746a22012902002126200120183702002026a7210c2026422088a7210202400240024020042802a80322014101460d002001450d0820042802a0032001417e6a4104746a2207280204200c470d00200741086a21010c010b2002450d01024020042802b403220120042802b003470d00201d2001410110900120042802b40321010b20042802ac0320014103746a220120023602042001200c36020041012102201f21010b2001200128020020026a36020020042802a8032201450d170b20042001417f6a22023602a80320042802a003220c20024104746a22072d000c4102460d162002450d0b2001410474200c6a41606a220c20072802002201200c280200220c200c20014b1b360200200120024f0d0b20042802a8032201450d16200141047420042802a0036a41746a22012902002126200120183702002026a7210c2026422088a72101024020042802a80322024101460d002002450d0720042802a0032002417e6a4104746a2202280204200c470d002002200228020820016a3602080c0c0b2001450d0b024020042802b403220220042802b003470d00201d2002410110900120042802b40321020b20042802ac0320024103746a220220013602042002200c360200200420042802b40341016a3602b4030c0b0b20042802a8032201450d15200141047420042802a0036a41746a22012902002126200120183702002026a7210c2026422088a72101024020042802a80322024101460d002002450d0720042802a0032002417e6a4104746a2202280204200c470d002002200228020820016a3602080c0b0b2001450d0a024020042802b403220220042802b003470d00201d2002410110900120042802b40321020b20042802ac0320024103746a220220013602042002200c360200200420042802b40341016a3602b4030c0a0b20042802a8032201450d14200141047420042802a0036a41786a220c280200220120026a22022001490d14202320144104746a41046a2802002107200c200236020020042802a8032201417f6a220c20014b0d14200c20076b2202200c4b0d14200141047420042802a0036a41746a22012902002126200120183702002026a721072026422088a7210c02400240024020042802a80322014101460d002001450d0920042802a0032001417e6a4104746a22112802042007470d00201141086a21010c010b200c450d01024020042802b403220120042802b003470d00201d2001410110900120042802b40321010b20042802ac0320014103746a2201200c360204200120073602004101210c201f21010b20012001280200200c6a36020020042802a80321010b200120024d0d1420042802a003220c20024104746a2d000c0d092001410474200c6a41706a2201200220012802002201200120024b1b3602000c090b20042802a8032201450d13200141047420042802a0036a41786a220c280200220120026a22022001490d13200c200236020020042802a8032202417f6a220120024b0d13200420013602b8032004202320144104746a41046a2202280200280208220c3602bc0320022802002207280200210220072802042107200441003a00cf042004200220074102746a36029c0220042002360298022004201e360294022004200441bc036a360290022004200441bc036a41046a360290022004200441cf046a3602a4022004200441b8036a3602a00202402001200c6b220220014d0d00200441013a00cf040c140b410410332201450d1b2001200236020020044281808080103702d404200420013602d004200441c0036a41106a20044190026a41106a290300370300200441c0036a41086a20044190026a41086a290300370300200420042903900222263703c00320042802d4032102024002402026a72201450d00024020042802c4032001460d002004200141046a3602c00320042802d003280200220720012802006b220c20074d0d02200241013a00000c0a0b200441003602c0030b20042802c8032201450d0820042802cc032001460d082004200141046a3602c80341012107024020042802d003280200221120012802006b220c20114d0d00200241013a0000410021070b2007417d71450d080b4101210220042802cc03211020042802d003211120042802c403210f20042802d4032105410121010340024020012002470d00200441d0046a200241011086010b20042802d00420014102746a200c3602002004200141016a3602d8040240024020042802c0032201450d000240200f2001460d002004200141046a3602c0032011280200220220012802006b220c20024d0d02200541013a00000c0b0b200441003602c0030b20042802c8032201450d0920102001460d092004200141046a3602c8034101210202402011280200220720012802006b220c20074d0d00200541013a0000410021020b2002417d71450d090b20042802d404210220042802d80421010c000b0b20042802a8032201450d12200141047420042802a0036a41786a220c280200220120026a22022001490d12200c200236020020042802a8032201450d12200141047420042802a0036a41746a22012902002126200120183702002026a7210c2026422088a7210102400240024020042802a80322024101460d002002450d0820042802a0032002417e6a4104746a2207280204200c470d00200741086a21020c010b2001450d01024020042802b403220220042802b003470d00201d2002410110900120042802b40321020b20042802ac0320024103746a220220013602042002200c36020041012101201f21020b2002200228020020016a36020020042802a8032202450d130b20042802a00322012d000c0d07200241047420016a41706a41003602000c070b2014200141fc8ecc001042000b41ab8ecc00413f41ec8ecc001064000b41ab8ecc00413f41ec8ecc001064000b41ab8ecc00413f41ec8ecc001064000b41ab8ecc00413f41ec8ecc001064000b41ab8ecc00413f41ec8ecc001064000b20042802d004210f20042802d4042105024020042d00cf04450d00200541ffffffff0371450d0c200f10350c0c0b200f450d0b0240024020042802a80322010d00410121100c010b20042802d8042102200141047420042802a0036a41746a22012902002126200120183702002026a721072026422088a7210102400240024020042802a803220c4101460d00200c450d0720042802a003200c417e6a4104746a220c2802042007470d00200c41086a210c0c010b2001450d01024020042802b403220c20042802b003470d00201d200c410110900120042802b403210c0b20042802ac03200c4103746a220c2001360204200c200736020041012101201f210c0b200c200c28020020016a3602000b410021102002450d002002410274210c200f21010340024020042802a8032207200128020022024b0d00410121100c020b024020042802a003221120024104746a2d000c0d00200741047420116a41706a2207200220072802002207200720024b1b3602000b200141046a2101200c417c6a220c0d000b0b0240200541ffffffff0371450d00200f10350b20100d0b0b20182019510d01200828021421010c000b0b20042802ac0320042802b4032201410041202001676b10f20620042903b003212620042802ac032124024020042802a40341ffffffff0071450d0020042802a00310350b024020240d00410121210c0a0b200828021422012026422088a7220c4101746a220241ffffffff00712002470d0120024104742202417f4c0d010240024020020d00410821070c010b200210332207450d11200828021421010b20084100360214200828020c21232008200736020c200841106a220f2802002127200f2002410476360200202320014104746a21112024200c4103746a212541022107024020010d0020242114202321010c030b41002102202421144100210c202321010340200141016a2f0000200141036a2d000041107472210e024020012d0000221041ac01470d00200141106a21010c040b200141086a2900002118200141046a28000021050240024020074102470d00024020142025470d0041002107202521140c020b20142902002219422088a721282019a7210a41012107201441086a21140b20074101470d00200c200a470d0002402002200f280200470d00200620024101109a01200828021421020b200828020c20024104746a220220042f00c0033b00012002412d3a000020022028360204200241036a200441c0036a41026a2d00003a00002008200828021441016a220236021402402002200f280200470d00200620024101109a01200828021421020b200828020c20024104746a220220042f00c0033b00012002410b3a00002002200d36020441022107200241036a200441c0036a41026a2d00003a00002008200828021441016a2202360214200c210a0b02402002200f280200470d00200620024101109a01200828021421020b200c41016a210c200828020c20024104746a22022018370308200220053602042002200e3b0001200220103a0000200241036a200e4110763a00002008200828021441016a2202360214200141106a22012011470d000c040b0b41ab8ecc00413f41ec8ecc001064000b1044000b20112001460d000340200141106a2102024020012d00004109470d000240200141046a220c280200220128020441ffffffff0371450d0020012802001035200c28020021010b200110350b2002210120112002470d000b0b0240202741ffffffff0071450d00202310350b2014202547200720074102461b21010240202642ffffffff0183500d00202410350b024020014101470d00410121210c060b200841186a210c02400240201b450d0020082802142202450d00200828020c210120024104742102410021080340024020012d0000412c470d002001410b3a0000200141046a201c360200200841016a21080b200141106a2101200241706a22020d000b4101210120080d010b202021010b200c2022470d000b200121200c040b200b2802042201200d490d03200b200141016a3602040c030b200b28020c2201450d02200b280204220c2001411c6c6a21070340200c2201411c6a210c024020012802182202450d0020012802102101200241027421020340024020012802002208200d490d002001200841016a3602000b200141046a21012002417c6a22020d000b0b200c2007460d030c000b0b200b28020c2201450d01200141146c2102200b28020441106a2101034002402001417c6a2802000d0020012802002208200d490d002001200841016a3602000b200141146a21012002416c6a22020d000c020b0b024020042802a40341ffffffff0071450d0020042802a00310350b024020042802b00341ffffffff0171450d0020042802ac0310350b410121210b200b41306a220b2015470d000b4101210f20214101710d0220204101710d012004280288022111200428028002210b0b20044184026a280200211020042802fc01210520042802f80121064100210f0c020b200441c0036a41106a200441f8016a41106a280200360200200441c0036a41086a200441f8016a41086a290300370300200420042903f8013703c00320044190026a200441c0036a10ef06411010332202450d28200241063a0000410110332201450d28200141003a000041011033220c450d28200c20012d00003a000020011035411010332208450d28200841063a000041f00010332201450d28200141063a00602001412c3b01502001200d3602442001410b3a0040200141d8003a00302001201b3602242001412d3a0020200141003602142001410f3a0010200141003602042001410f3a0000024020082d00004109470d0002402008280204220d28020441ffffffff0371450d00200d28020010352008280204210d0b200d10350b20081035024020022d00004109470d0002402002280204220828020441ffffffff0371450d0020082802001035200228020421080b200810350b20021035200441e4036a4287808080f000370200200441e0036a2001360200200441dc036a4100360200200441c0036a410c6a4281808080800c370200200441c8036a4101360200200441003602ec03200442043702d4032004200c3602c403200441013602c00320044190026a200441c0036a10f306200441c0036a20044190026a418c01109d081a200441a0036a200441c0036a10f106200441a0036a410c6a2802002110200441b0036a280200211120042802a003210620042802a403210520042802a803210b4100210f0c010b20044184026a2802002110200428028002220b200428028802221110f406411a210541bed5cb00210602402010450d00201041306c450d00200b10350b0b41002108410021014100210c02402013450d0002402012450d000340201328026c21132012417f6a22120d000b0b20132101201a210c0b024002400340200c450d012001450d024100210d02400240200820012f01064f0d00200121020c010b4100210d034002400240200128020022020d0041002108410021020c010b200d41016a210d20012f010421080b2001103520022101200820022f01064f0d000b0b200841016a2107200220084103746a41146a280200210e02400240200d0d0020022101200721080c010b200220074102746a41ec006a280200210141002108200d417f6a2202450d000340200128026c21012002417f6a22020d000b0b200c417f6a210c200e4103470d000b0b02402001450d0020012802002102200110352002450d00034020022802002101200210352001210220010d000b0b02400240200f0d0020044190026a41106a201136020020044190026a410c6a20103602002004200b3602980220042005360294022004200636029002200441c0036a20044190026a200928027810f50620042802c0034101470d010240200441c0036a41086a280200450d0020042802c40310350b200041d8d5cb0036020420004101360200200041086a41233602000c2a0b2000200636020420004101360200200041086a20053602000c290b200441d4036a2802002102200441c0036a41106a2802002110200441c0036a410c6a280200210f200441c8036a280200210c20042802c403210820032802702105200441003602a803200442013703a003410410332201450d27200441043602a403200420013602a00320012008360000200441043602a8030240024020042802a403220d417c714104460d004104210120042802a00321080c010b200d41017422014108200141084b1b220b4100480d0202400240200d0d0041042101200b10332208450d2a0c010b4104210120042802a0032108200d200b460d002008200d200b10372208450d2920042802a80321010b2004200b3602a403200420083602a0030b200820016a200c3600002004200141046a3602a803200f200241306c6a2113024020020d00200f21010c040b200441c0036a4101722102200441c0036a41276a210d200441c0036a41206a210c200441c0036a41186a210b200441c0036a41086a2107200f21010240034020012d00002108200d200141286a290000370000200c200141216a290000370300200b200141196a290000370300200441c0036a41106a220e200141116a2900003703002007200141096a2900003703002004200141016a2900003703c003024020084110470d00200141306a21010c060b20044190026a41276a2211200d29000037000020044190026a41206a2203200c29030037030020044190026a41186a200b290300221837030020044190026a41106a200e290300221937030020044190026a41086a20072903002226370300200420042903c00322293703900220022029370000200241086a2026370000200241106a2019370000200241186a2018370000200241206a2003290300370000200241276a2011290000370000200420083a00c003200441e8006a200441c0036a200441a0036a10f60620042d00682208411f470d01200141306a22012013470d000b201321010c040b200428026c210d20042802702102200141306a2201201320016b41306d10f40602402010450d00201041306c450d00200f10350b024020042802a403450d0020042802a00310350b024020084105470d002002450d00200d10350b20004199d8cb0036020420004101360200200041086a41253602000c280b41958dcc00412b41c08dcc00103f000b103e000b1045000b2001201320016b41306d10f40602402010450d00201041306c450d00200f10350b20042802a003210120042902a40321182000411c6a41003a0000200041146a2018370200200041106a20013602002000410c6a2017360200200041086a2016360200200020053602042000411d6a20042f00f8013b0000200041003602002000411f6a200441fa016a2d00003a00000c240b200e1035200041fabbca003602040c210b200e1035200041fabbca003602040c200b200e1035200041fabbca003602040c1f0b200f2d000d22024104460d00200241fb01710d0020141035201121020c1a0b201410350b200020083602040c1c0b200e1035200041fabbca003602040c1b0b200e1035200041fabbca003602040c1a0b200e1035200041fabbca003602040c190b200e1035200041fabbca003602040c180b200e1035200041fabbca003602040c170b200e1035200041fabbca003602040c160b200e1035200041fabbca003602040c150b200e1035200041fabbca003602040c140b200e1035200041fabbca003602040c130b200f2d000d22024104460d0a200241fb01710d0a200e1035201121020c0e0b200f2d000d22024104460d02200241fb01710d02200e1035201121020c0d0b200f2d000d22024104460d00200241fb01710d00200e1035201121020c0c0b200e1035200041fabbca003602040c0f0b200e1035200041fabbca003602040c0e0b200f2d000d22024104460d00200241fb01710d00200e1035201121020c090b200e1035200041fabbca003602040c0c0b200e1035200041fabbca003602040c0b0b200e1035200041fabbca003602040c0a0b200e1035200041fabbca003602040c090b200e1035200041fabbca003602040c080b200e1035200041fabbca003602040c070b02400240200241b9e0cb00460d0041b9e0cb002002410b10a0080d010b4126210c41fabbca00210e200f2d000c41e000470d01200f2802080d0120112102200f2d000d4104460d030c010b0240200241dde0cb00460d0041dde0cb002002410b10a0080d020b4126210c41fabbca00210e200f2d000c41e000470d00200f2802080d0020112102200f2d000d4104460d020b200c21012000200e3602040c050b0240200241bfe2cb00460d0041bfe2cb002002410b10a0080d040b41021033220c450d05200c41003b0000200f2d000c41e000470d02200f2802084102470d020240200f280200220e200c460d0041002101034020014102460d01200c20016a2102200e20016a2108200141016a210120082d000020022d0000470d040c000b0b200f2d000d4104470d02200c1035201121020c000b0b200041c9d3cb00360204411f21010c020b200c10350b41262101200041fabbca003602040b20004101360200200041086a200136020002402007450d00200b200741306c6a2111200b210703402007220041306a21070240024020002d00002201410e4b0d00024002400240024002400240024002400240024002400240024020010e0f0001020304050607080e090e0a0b0c000b200041086a280200450d0d200041046a28020010350c0d0b0240200041086a280200450d00200041046a28020010350b200041146a280200450d0c200041106a28020010350c0c0b02402000410c6a2802002202450d00200041046a28020021012002410474210203400240200141046a280200450d00200128020010350b200141106a2101200241706a22020d000b0b200041086a28020041ffffffff0071450d0b200028020410350c0b0b02402000410c6a2802002202450d00200041046a2802002101200241286c210203400240200141046a280200450d00200128020010350b0240200141106a280200450d002001410c6a28020010350b200141286a2101200241586a22020d000b0b200041086a2802002201450d0a200141286c450d0a200028020410350c0a0b200041086a28020041ffffffff0371450d09200041046a28020010350c090b200041086a2802002201450d082001410c6c450d08200041046a28020010350c080b200041086a2802002201450d072001410c6c450d07200041046a28020010350c070b02402000410c6a2802002201450d00200041046a280200220c20014104746a210e03400240200c2802082202450d00200c2802002101200241047421020340024020012d00004109470d000240200141046a220d280200220828020441ffffffff0371450d0020082802001035200d28020021080b200810350b200141106a2101200241706a22020d000b0b200c41106a21010240200c41046a28020041ffffffff0071450d00200c28020010350b2001210c2001200e470d000b0b200041086a28020041ffffffff0071450d06200028020410350c060b02402000410c6a2802002202450d00200041046a2802002101200241146c210203400240200141046a280200450d00200128020010350b200141146a21012002416c6a22020d000b0b200041086a2802002201450d05200141146c450d05200028020410350c050b02402000410c6a2802002201450d00200041046a280200220c2001411c6c6a210e03400240200c2802042201450d000240200c410c6a2802002202450d00200241047421020340024020012d00004109470d000240200141046a220d280200220828020441ffffffff0371450d0020082802001035200d28020021080b200810350b200141106a2101200241706a22020d000b0b200c41086a28020041ffffffff0071450d00200c28020410350b200c411c6a21010240200c41146a28020041ffffffff0371450d00200c28021010350b2001210c2001200e470d000b0b200041086a2802002201450d042001411c6c450d04200028020410350c040b02402000410c6a2802002201450d00200041046a280200220c200141186c6a210e03400240200c41046a28020041ffffffff0171450d00200c28020010350b0240200c41146a2802002202450d00200c28020c2101200241047421020340024020012d00004109470d000240200141046a220d280200220828020441ffffffff0371450d0020082802001035200d28020021080b200810350b200141106a2101200241706a22020d000b0b200c41186a21010240200c41106a28020041ffffffff0071450d00200c28020c10350b2001210c2001200e470d000b0b200041086a2802002201450d03200141186c450d03200028020410350c030b02402000410c6a2802002201450d00200041046a280200220c2001411c6c6a210e03400240200c2802042201450d000240200c410c6a2802002202450d00200241047421020340024020012d00004109470d000240200141046a220d280200220828020441ffffffff0371450d0020082802001035200d28020021080b200810350b200141106a2101200241706a22020d000b0b200c41086a28020041ffffffff0071450d00200c28020410350b200c411c6a21010240200c41146a280200450d00200c28021010350b2001210c2001200e470d000b0b200041086a2802002201450d022001411c6c450d02200028020410350c020b0240200041046a2802002201450d00200041086a280200450d00200110350b0240200041146a2802002201450d0002402000411c6a2802002202450d002002410c6c21020340024020012802002208450d00200141046a280200450d00200810350b2001410c6a2101200241746a22020d000b0b200041186a2802002201450d002001410c6c450d00200028021410350b200041246a280200220c450d0102402000412c6a2802002201450d00200c20014104746a210e0340200c220d41106a210c0240200d2802042201450d000240200d410c6a2802002202450d002002410c6c21020340024020012802002208450d00200141046a280200450d00200810350b2001410c6a2101200241746a22020d000b0b200d41086a2802002201450d002001410c6c450d00200d28020410350b200c200e470d000b0b200041286a28020041ffffffff0071450d01200028022410350c010b0240200041086a280200450d00200041046a28020010350b0240200041146a2802002201450d00200041186a280200450d00200110350b200041246a28020041ffffffff0071450d00200041206a28020010350b20072011470d000b0b200a450d01200a41306c450d01200b10350c010b103c000b200441e0046a24000bf70a02147f027e23004190066b22022400024002400240024020012d00000e03010200010b200241b0056a41186a2203200141196a2200290000370300200241b0056a41106a2204200141116a2205290000370300200241b0056a41086a2206200141096a2207290000370300200220012900013703b005200241d0056a41186a2208200141396a2209290000370300200241d0056a41106a220a200141316a220b290000370300200241d0056a41086a220c200141296a220d2900003703002002200141216a220e2900003703d005200241b0026a41186a220f200141d9006a2210290000370300200241b0026a41106a2211200141d1006a2212290000370300200241b0026a41086a2213200141c9006a22142900003703002002200141c1006a22152900003703b002200141f8006a2903002116200141f0006a290300211720024188056a41186a200029000037030020024188056a41106a200529000037030020024188056a41086a20072900003703002002200129000137038805200241186a2009290000370300200241106a200b290000370300200241086a200d2900003703002002200e290000370300200241d8026a41186a2010290000370300200241d8026a41106a2012290000370300200241d8026a41086a22002014290000370300200220152900003703d80220024180066a41086a200141ec006a2802003602002002200141e4006a29020037038006200241f0056a20024188056a2002200241d8026a2017201620024180066a10f10320022d00f0052101200041033a0000200241d8026a41096a20022903b005370000200241d8026a41116a2006290300370000200241d8026a41196a2004290300370000200241d8026a41216a2003290300370000200241d8026a41296a20022903d005370000200241d8026a41316a200c290300370000200241d8026a41396a200a290300370000200241d8026a41c1006a20082903003700002002410d3a00d802200241d8026a41f8006a2016370300200241d8026a41f0006a2017370300200241c1036a20014104463a0000200241b9036a200f290300370000200241d8026a41d9006a2011290300370000200241d8026a41d1006a2013290300370000200241d8026a41c9006a20022903b00237000041b0b4cc004100200241d8026a10d4010c020b200141086a28020021002001410c6a2802002104200141046a2802002103200241076a200141106a41f800109d081a2002410d3a00d802200241d8026a410172200241ff00109d081a20032004200241d8026a10d401200041ffffff3f71450d01200310350c010b200241e8056a2204200141196a2205290000370300200241d0056a41106a2206200141116a2207290000370300200241d0056a41086a2208200141096a2209290000370300200220012900013703d0052002200141286a41b002109d08220341b0056a200310d803200341d8026a200341b002109d081a20034192056a20092900003701002003419a056a2007290000370100200341a2056a200529000037010020034180023b0188052003200129000137018a05200341b0026a200341d8026a20034188056a10ac032000280200280200210142002116024020032903b8024201520d00420020032903b0052216200341b0026a41106a2903007d221720172016561b21160b2001427f2001290308221720167c221620162017541b22162001290300221720162017561b37030820032903b0022116200341d8026a41086a41063a0000200341d8026a41096a20032903d005370000200341d8026a41116a2008290300370000200341d8026a41196a2006290300370000200341f9026a200429030037000020034181036a2016503a00002003410d3a00d80241b0b4cc004100200341d8026a10d4010b20024190066a24000bb22402137f067e23004190046b22032400024002400240024002400240024002400240024002400240024020012802000e0400010203000b200341cc016a4101360200200342013702bc01200341e8d4ca003602b801200341043602ec032003419cd5ca003602e8032003200341e8036a3602c801200341b8016a41b0b4cc00104c000b20012802042101418226210420022d00000d0420022d00014101470d04200241196a2d00002104200241186a2d00002105200241166a2f01002106200241156a2d00002107200241146a2d00002108200241126a2f01002109200241116a2d0000210a200241106a2d0000210b2002410e6a2f0100210c2002410d6a2d0000210d2002410c6a2d0000210e2002410a6a2f0100210f200241096a2d00002110200241086a2d00002111200241066a2f01002112200241056a2d00002113200241046a2d00002114200241026a2f0100211520032002411a6a290100370320200320043a001f200320053a001e200320063b011c200320073a001b200320083a001a200320093b01182003200a3a00172003200b3a00162003200c3b01142003200d3a00132003200e3a00122003200f3b0110200320103a000f200320113a000e200320123b010c200320133a000b200320143a000a200320153b010841d5c3c800ad4280808080c00084100122022900002116200229000821172002103541b4c4c800ad428080808030841001220229000021182002290008211920021035200320193701a801200320183701a00120032017370198012003201637019001200341b8016a20034190016a412010d5010240024020032d00b8014101460d0020034180046a4200370300200341f8036a4200370300200341f0036a4200370300200342003703e8030c010b200320032900b9013703e8032003200341d1016a290000370380042003200341c1016a2900003703f0032003200341c9016a2900003703f8030b4183262104200341086a200341e8036a412010a0080d04200341b8016a200141b002109d081a200341003b01e80320034190016a200341b8016a200341e8036a10ac03200320032900a9013703b801200320034190016a41206a2800003600bf01024002402003290390014201510d00410421020c010b200341a8016a2d000021042003290398012116200320032800bf013600ef03200320032903b8013703e8034104210220164202510d00200320032800ef033600bf01200320032903e8033703b801200421020b200320032903b801370370200320032800bf01360077200341b8016a41086a20023a0000200341c1016a2003290370370000200341b8016a41106a2003280077360000200341003a00bc012003410e3a00b801200320032f00503b00bd012003200341d2006a2d00003a00bf01200341cc016a20032902e803370200200341d4016a200341e8036a41086a290200370200200341dc016a200341e8036a41106a28020036020041b0b4cc004100200341b8016a10d401200110350c020b200341e8036a41206a200141246a280200360200200341e8036a41186a2001411c6a290200370300200341e8036a41106a200141146a290200370300200341e8036a41086a2001410c6a290200370300200320012902043703e8034182262101024020022d00000d0020022d00014101470d00200241196a2d00002101200241186a2d00002104200241166a2f01002105200241156a2d00002106200241146a2d00002107200241126a2f01002108200241116a2d00002109200241106a2d0000210a2002410e6a2f0100210b2002410d6a2d0000210c2002410c6a2d0000210d2002410a6a2f0100210e200241096a2d0000210f200241086a2d00002110200241066a2f01002111200241056a2d00002112200241046a2d00002113200241026a2f0100211420032002411a6a290100370348200320013a0047200320043a0046200320053b0144200320063a0043200320073a0042200320083b0140200320093a003f2003200a3a003e2003200b3b013c2003200c3a003b2003200d3a003a2003200e3b01382003200f3a0037200320103a0036200320113b0134200320123a0033200320133a0032200320143b013041d5c3c800ad4280808080c00084100122012900002116200129000821172001103541b4c4c800ad428080808030841001220129000021182001290008211920011035200320193701a801200320183701a00120032017370198012003201637019001200341b8016a20034190016a412010d5010240024020032d00b8014101460d00200341a8016a4200370300200341a0016a420037030020034198016a420037030020034200370390010c010b200320032900b901370390012003200341d1016a2900003703a8012003200341c1016a290000370398012003200341c9016a2900003703a0010b4183262101200341306a20034190016a412010a0080d00200341b8016a41206a200341e8036a41206a280200360200200341b8016a41186a200341e8036a41186a290300370300200341b8016a41106a200341e8036a41106a290300370300200341b8016a41086a200341e8036a41086a290300370300200320032903e8033703b80120034190016a200341b8016a108b02200341086a41086a220120034199016a290000370300200341086a41106a2202200341a1016a290000370300200341086a41186a2204200341a9016a2900003703002003200329009101370308024020032d0090014101460d00200341f0006a41186a2004290300370300200341f0006a41106a2002290300370300200341f0006a41086a20012903003703002003200329030837037041d5c3c800ad4280808080c000842216100122012900002117200129000821182001103541b4c4c800ad42808080803084221910012201290000211a2001290008211b200110352003201b3701a8012003201a3701a00120032018370198012003201737019001200341b8016a20034190016a412010d5010240024020032d00b8014101460d004200211741002101410021024100210441002105410021064100210741002108410021094100210a4100210b4100210c4100210d4100210e4100210f410021104100211141002112410021130c010b200341c0016a2d0000210e200341c1016a2f0000210d200341c3016a2d0000210c200341c4016a2d0000210b200341c5016a2f0000210a200341c7016a2d00002109200341c8016a2d00002108200341c9016a2f00002107200341cb016a2d00002106200341cc016a2d00002105200341cd016a2f00002104200341cf016a2d00002102200341d0016a2d00002101200341d1016a290000211720032f00b901211320032d00bb01211220032d00bc01211120032f00bd01211020032d00bf01210f0b200341d5016a2017370000200341d4016a20013a0000200341d3016a20023a0000200341d1016a20043b0000200341b8016a41186a220220053a0000200341cf016a20063a0000200341cd016a20073b0000200341cc016a20083a0000200341cb016a20093a0000200341c9016a200a3b0000200341b8016a41106a2204200b3a0000200341c7016a200c3a0000200341c5016a200d3b0000200341c4016a200e3a0000200341c3016a200f3a0000200341c1016a20103b0000200341b8016a41086a220520113a0000200320123a00bf01200320133b00bd01200341013a00bc012003410e3a00b80141b0b4cc004100200341b8016a10d4012002200341f0006a41186a2903003703002004200341f0006a41106a2903003703002005200341f0006a41086a290300370300200320032903703703b801201610012201290000211620012900082117200110352019100122012900002118200129000821192001103520032019370168200320183701602003201737015820032016370150412010332201450d06200120032903b801370000200141186a2002290300370000200141106a2004290300370000200141086a2005290300370000200341d0006aad42808080808004842001ad42808080808004841002200110350c030b41812621010b200041206a410b3602002000411c6a41de98c800360200200041186a2001360200200042003703080c080b200141286a2802002104200341286a200141246a280200360200200341086a41186a2001411c6a290200370300200341086a41106a200141146a290200370300200341086a41086a2001410c6a290200370300200320012902043703084102210120022d00000d0420022d00014101470d04200241196a2d00002101200241186a2d00002105200241166a2f01002106200241156a2d00002107200241146a2d00002108200241126a2f01002109200241116a2d0000210a200241106a2d0000210b2002410e6a2f0100210c2002410d6a2d0000210d2002410c6a2d0000210e2002410a6a2f0100210f200241096a2d00002110200241086a2d00002111200241066a2f01002112200241056a2d00002113200241046a2d00002114200241026a2f0100211520032002411a6a29010037038801200320013a008701200320053a008601200320063b018401200320073a008301200320083a008201200320093b0180012003200a3a007f2003200b3a007e2003200c3b017c2003200d3a007b2003200e3a007a2003200f3b0178200320103a0077200320113a0076200320123b0174200320133a0073200320143a0072200320153b017041d5c3c800ad4280808080c00084100122012900002116200129000821172001103541b4c4c800ad428080808030841001220129000021182001290008211920011035200320193701a801200320183701a00120032017370198012003201637019001200341b8016a20034190016a412010d5010240024020032d00b8014101460d0020034180046a4200370300200341f8036a4200370300200341f0036a4200370300200342003703e8030c010b200320032900b9013703e8032003200341d1016a290000370380042003200341c1016a2900003703f0032003200341c9016a2900003703f8030b200341f0006a200341e8036a412010a0080d05200341b8016a41206a200341086a41206a280200360200200341b8016a41186a200341086a41186a290300370300200341b8016a41106a200341086a41106a290300370300200341b8016a41086a200341086a41086a290300370300200320032903083703b801200341e8036a200341b8016a108b024101210120032d00e8034101460d01200341e8036a41086a2d00002102200341f1036a2f00002105200341f3036a2d00002106200341f4036a2d00002107200341f5036a2f00002108200341f7036a2d00002109200341e8036a41106a2d0000210a200341f9036a2f0000210b200341fb036a2d0000210c200341fc036a2d0000210d200341fd036a2f0000210e200341ff036a2d0000210f200341e8036a41186a2d0000211020032f00e903211120032d00eb03211220032d00ec03211320032f00ed03211420032d00ef032115200320034181046a290000370168200320103a00672003200f3a00662003200e3b01642003200d3a00632003200c3a00622003200b3b01602003200a3a005f200320093a005e200320083b015c200320073a005b200320063a005a200320053b0158200320023a0057200320153a0056200320143b0154200320133a0053200320123a0052200320113b0150200341b8016a200441b002109d081a200341f2036a2003290158370100200341fa036a200329016037010020034182046a200329016837010020034180023b01e803200320032901503701ea0320034190016a200341b8016a200341e8036a10ac0302402003290390014201520d00200341b8016a41186a200341b0016a290300370300200341b8016a41106a220120034190016a41186a290300370300200341c0016a20034190016a41106a29030037030020032003290398013703b801200110d10441c4e0c600ad4280808080a001841006419ea2c000ad4280808080e0018410060240024020032903b8014201510d004194a2c000ad4280808080a0018410060c010b20032903c00110260b410021010b200320013a00bd01200341023a00bc012003410e3a00b80141b0b4cc004100200341b8016a10d401200410350b42002116200042003703080c070b200410ba0220041035410121010c040b200110ba0220011035200041206a410b3602002000411c6a41de98c800360200200041186a2004360200200042003703080c040b1045000b200410ba02200410350c010b200410ba0220041035410321010b20004200370308200041206a410b3602002000411c6a41de98c800360200200041186a2001418026723602000b420121160b2000201637030020034190046a24000bb8c20105017f037e127f087e087f23004180046b220324000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e0d00011a13120c0b0a0605040302000b20034184036a4101360200200342013702f402200341e8d4ca003602f002200341043602b4012003419cd5ca003602b0012003200341b0016a36028003200341f0026a41b0b4cc00104c000b200141106a2903002104200141086a29030021052002411a6a2901002106200241196a2d00002107200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241086a2d00002114200241066a2f01002115200241056a2d00002116200241046a2d00002117200241026a2f0100211841012101024020022d00000d0020022d000141014721010b2003200637038001200320073a007f200320083a007e200320093b017c2003200a3a007b2003200b3a007a2003200c3b01782003200d3a00772003200e3a00762003200f3b0174200320103a0073200320113a0072200320123b0170200320133a006f200320143a006e200320153b016c200320163a006b200320173a006a200320183b016820010d1920034188016a41186a200341e8006a41186a29030037030020034188016a41106a200341e8006a41106a29030037030020034188016a41086a200341e8006a41086a2903003703002003200329036837038801200341f0026a20034188016a10cf06200341106a20032802f002220120032802f80241b0b4cc0041004100108a0220032802102102024020032802f402450d00200110350b4103210720024101460d1a200341f0026a20034188016a10b906200341086a20032802f002220120032802f80241b0b4cc0041004100108a0220032802082102024020032802f402450d00200110350b20024101460d1a200341f0026a41186a4200370300200341f0026a41106a220e4200370300200341f0026a41086a22024200370300200342003703f00241a29bc800ad4280808080f000841001220129000021062002200141086a290000370300200320063703f00220011035419cbac800ad4280808080c00084100122012900002106200341e8006a41086a2207200141086a2900003703002003200637036820011035200e20032903682206370300200341c8026a41086a2002290300370300200341c8026a41106a2006370300200341c8026a41186a2007290300370300200320032903f0023703c802200341f0026a200341c8026a10be0220032802f0022202410820021b220f20032902f402420020021b2206422088a741e8006c6a210d200f210202400340024002402002200d460d0041e59bc8002108410a2109410321074119210a410c210b20034188016a200241c8006a2201470d010c030b200341f0026a41186a22074200370300200341f0026a41106a22084200370300200341f0026a41086a22024200370300200342003703f00241a29bc800ad4280808080f000841001220129000021192002200141086a290000370300200320193703f0022001103541e1b8c800ad4280808080a00184100122012900002119200341e8006a41086a2209200141086a2900003703002003201937036820011035200e2003290368370000200e41086a2009290300370000200341c8026a41086a2002290300370300200341c8026a41106a2008290300370300200341c8026a41186a2007290300370300200320032903f0023703c802200341f0026a200341c8026a10be0220032802f0022202410820021b221020032902f402420020021b2219422088a741e8006c6a210d20102102024002400240024002400340024002402002200d460d0041d59bc800210841102109410321074119210a410d210b20034188016a200241c8006a2201470d010c070b200341f0026a41186a22074200370300200341f0026a41106a22084200370300200341f0026a41086a22024200370300200342003703f00241a29bc800ad4280808080f0008410012201290000211a2002200141086a2900003703002003201a3703f002200110354189eaca00ad4280808080f0008410012201290000211a200341e8006a41086a2209200141086a2900003703002003201a37036820011035200e2003290368370000200e41086a2009290300370000200341c8026a41086a2002290300370300200341c8026a41106a2008290300370300200341c8026a41186a2007290300370300200320032903f0023703c802200341f0026a200341c8026a10fe0120032802f0022201410120011b210d41002102024020032902f402420020011b221a422088a7220141014b0d0020010e020403040b03402001410176220720026a22082002200d20084105746a20034188016a412010a0084101481b2102200120076b220141014b0d000c030b0b200141206a2102200120034188016a412010a0080d000c050b0b200d20024105746a20034188016a412010a0080d0041ce9cc8002108410d2109410321074119210a4102210b0c010b200342003703d00220034280809aa6eaafe3013703c802200320034188016a360268200320034188016a36028002200320034180026a3602f8022003200341e8006a3602f4022003200341c8026a3602f002200341b0016a20034188016a200341f0026a108c030240024020032802b0014101470d00200341bc016a2802002109200341b8016a280200210820032d00b701210c20032d00b601210b20032d00b501210a20032d00b40121070c010b410421070240200341b0016a41086a2903004201520d00200341b0016a41106a290300211b2003280280022102200341a8036a200341b0016a41186a290300370300200341a0036a201b370300200341f0026a41086a41003a0000200341f9026a200229000037000020034181036a200241086a29000037000020034189036a200241106a29000037000020034191036a200241186a290000370000200341033a00f00241b0b4cc004100200341f0026a10d4010b0b200741ff01714104460d010b201a42ffffff3f83500d01200d10350c010b200320063702b4012003200f3602b001200341f0026a41106a4200370300200341f0026a41086a22024280809aa6eaafe301370300200341003a00f002200341b0016a20034188016a20052004200341f0026a10d606200341a8036a2004370300200341a0036a2005370300200241013a0000200341f9026a20032903880137000020034181036a20034188016a41086a29030037000020034189036a20034188016a41106a29030037000020034191036a200341a0016a290300370000200341123a00f00241b0b4cc004100200341f0026a10d4010240201a42ffffff3f83500d00200d10350b02402019a72202450d00200241e8006c450d00201010350b420021060c200b2019a72202450d02200241e8006c450d02201010350c020b200141206a2102200120034188016a412010a0080d000b0b2006a72202450d1b200241e8006c450d1b200f10350c1b0b4182b23c21070240024020022d000120022d0000410047720d004183b23c2107200141046a280200220241014b0d010b20004200370308200041206a410a3602002000411c6a41a99bc800360200200041186a2007360200420121060c1d0b42002106200341e8006a41186a4200370300200341e8006a41106a22094200370300200341e8006a41086a220742003703002003420037036841a29bc800ad4280808080f0008410012208290000210420034180026a41086a2201200841086a29000037030020032004370380022008103520072001290300370300200320032903800237036841a99bc800ad4280808080a001841001220829000021042001200841086a29000037030020032004370380022008103520092003290380022204370300200341c8026a41086a2007290300370300200341c8026a41106a2004370300200341c8026a41186a2001290300370300200320032903683703c802200320023602f002200341c8026aad4280808080800484200341f0026aad4280808080c000841002200341fc026a2002360200200341f0026a41086a410d3a0000200341123a00f00241b0b4cc004100200341f0026a10d4010c0b0b200141216a2d0000210820034188016a41186a200141196a29000037030020034188016a41106a200141116a29000037030020034188016a41086a200141096a2900003703002003200129000137038801200341f0026a41206a200241206a290200370300200341f0026a41186a200241186a290200370300200341f0026a41106a200241106a290200370300200341f0026a41086a200241086a290200370300200320022902003703f002200341b0016a200341f0026a10d70602400240024020032d00b0014101460d00200341e8006a20034188016a10cf06200328026821022003200328027022013602bc02200320023602b802200341c8026a2001ad4220862002ad84100510c2010240024020032802c80222070d00410221010c010b20032802cc0221092003200341c8026a41086a280200220136028402200320073602800202400240024020014110490d002003200141706a360284022003200741106a36028002200741086a290000210620072900002104200341f0026a20034180026a10bf0220032d00f00222014102470d010b200341003602b801200342013703b001200341093602f4032003200341b8026a3602f0032003200341b0016a3602fc0320034184036a4101360200200342013702f402200341c888c2003602f0022003200341f0036a36028003200341fc036a41e88ac500200341f0026a10431a20033502b80142208620033502b001841006024020032802b401450d0020032802b00110350b410221010c010b200341b0016a41086a20034190036a290300370300200320032800f4023600f303200320032800f1023602f003200320034188036a2903003703b00120034180036a2903002119200341f0026a41086a2903002105200341a0036a290300211a20034198036a290300211b0b2009450d00200710350b20034180026a41086a2207200341b0016a41086a290300370300200320032802f0033602f002200320032800f3033600f302200320032903b00137038002024020014102460d00200341a0026a41086a2007290300370300200320032800f3023600b302200320032802f0023602b00220032003290380023703a0020b0240200328026c450d00200210350b20014102470d0141b99cc8002101410c21074103210241192108410421090c020b410221020c010b200341b8026a41086a2207200341a0026a41086a290300370300200320032802b0023602f003200320032800b3023600f303200320032903a0023703b80241032102024002400240024002400240024020084103710e03000201000b200341f0026a41186a220a4200370300200341f0026a41106a22084200370300200341f0026a41086a22024200370300200342003703f00241a29bc800ad4280808080f0008410012209290000211c2002200941086a2900003703002003201c3703f00220091035419cbac800ad4280808080c0008410012209290000211c200341e8006a41086a220b200941086a2900003703002003201c3703682009103520082003290368221c370300200341c8026a41086a2002290300370300200341c8026a41106a201c370300200341c8026a41186a200b290300370300200320032903f0023703c802200341f0026a200341c8026a10be02200320032902f402420020032802f00222091b3702b40120032009410820091b3602b0012008201937030020022005370300200341a0036a201a37030020034198036a201b370300200a20032903b80237030020034190036a2007290300370300200320013a00f002200320032802f0033600f102200320032800f3033600f402200341b0016a20034188016a20042006200341f0026a10d6060c020b200341e8006a41186a4200370300200341e8006a41106a4200370300200341e8006a41086a220742003703002003420037036841a29bc800ad4280808080f0008410012208290000211c20034180026a41086a2209200841086a2900003703002003201c370380022008103520072009290300370300200320032903800237036841ceb8c800ad428080808030841001220841086a290000211c2008290000211d20081035200341c8026a41106a201d370300200341c8026a41186a201c370300200341c8026a41086a2007290300370300200320032903683703c802200341d0006a200341c8026a412010d701024020032903584200200328025022071b221d2004542208200341d0006a41106a290300420020071b221c200654201c2006511b450d0041949cc8002101410f210741192108410721090c060b200341f0026a20034188016a10d806200341f0026a41086a2107024020032d00f00222024104460d002007280200210720032802f402210120032d00f302210a20032d00f202210920032d00f10221080c060b200341e8006a41186a4200370300200341e8006a41106a4200370300200341e8006a41086a220242003703002003420037036841a29bc800ad4280808080f00084221e10012209290000211f20034180026a41086a220a200941086a2900003703002003201f37038002200910352002200a290300370300200320032903800237036841ceb8c800ad428080808030841001220941086a290000211f2009290000212020091035200341c8026a41106a22092020370300200341c8026a41186a220a201f370300200341c8026a41086a220b2002290300370300200320032903683703c8022003201c20067d2008ad7d3703f8022003201d20047d3703f002200341c8026aad4280808080800484200341f0026aad42808080808002841002200341f0026a41186a220d4200370300200341f0026a41106a2208420037030020074200370300200342003703f00241d1c4c700ad4280808080e000841001220c290000211c2007200c41086a2900003703002003201c3703f002200c103541e7c4c700ad4280808080e000841001220c290000211c2002200c41086a2900003703002003201c370368200c103520082003290368221c370300200b20072903003703002009201c370300200a2002290300370300200320032903f0023703c802200341c8006a200341c8026a412010c001200328024c210e2003280248210f200d42003703002008420037030020074200370300200342003703f002201e1001220c290000211c2007200c41086a2900003703002003201c3703f002200c10354189eaca00ad4280808080f000841001220c290000211c2002200c41086a2900003703002003201c370368200c103520082003290368221c370300200b20072903003703002009201c370300200a2002290300370300200320032903f0023703c802200341f0026a200341c8026a10fe0120032902f402420020032802f00222021b221c422088a741f4036a2207450d02200341e4003a00f102200341e40041d0860320076e22076b3a00f002200e4100200f1b2108200341f0026a200741ff017141e4004b6a2d00004180fe126c21070240201c42ffffff3f83500d002002410120021b10350b200720086a210220034180026a41086a2207200341b8026a41086a290300370300200320032802f003360268200320032800f30336006b200320032903b802370380020240024020014101470d00200341ff026a20193700002003418f036a20072d00003a0000200320053700f7022003200328006b3600f302200320032802683602f002200320032903800237008703200341b0016a200341f0026a10d006024020032802b001220120032802b801220810d10241ff017122074102460d002008ad4220862001ad8410070b024020032802b401450d00200110350b20070d01200341f0026a20022004201b2004201b5422012006201a542006201a511b22071b2006201a20071b10b00642002006201a7d2001ad7d22052004201b7d2219200456200520065620052006511b22011b21064200201920011b21040c010b200320053703c802200320193703d0022005201984500d00200320034188016a3602fc03200341b0016a20034188016a200341c8026a200341fc036a10f00220032903b0014201520d0020032903b8012105200341a8036a200341b0016a41106a290300370300200341a0036a2005370300200341f0026a41086a41003a0000200341f9026a20032903880137000020034181036a20034188016a41086a29030037000020034189036a20034188016a41106a29030037000020034191036a200341a0016a290300370000200341033a00f00241b0b4cc004100200341f0026a10d4010b20034188016a20022004200610b0060c010b02402001410171450d00200341ff026a20193700002003418f036a200341c0026a2d00003a0000200320053700f702200320032800f3033600f302200320032802f0033602f002200320032903b80237008703200341b0016a200341f0026a10d00620033502b801210620032802b0012101410110332202450d16200241013a000020064220862001ad842002ad4280808080108410022002103520032802b401450d01200110350c010b200342f0f2bd99f7edd8b4e5003703b001200341f0026a200341b0016a10e001200341b0016a20034188016a200341f0026a20052019410010ef020b200341f0026a41186a220120034188016a41186a290300370300200341f0026a41106a220720034188016a41106a290300370300200341f0026a41086a220820034188016a41086a29030037030020032003290388013703f00241a29bc800ad4280808080f0008410012202290000210620034180026a41086a200241086a29000037030020032006370380022002103541e0aec900ad4280808080b00284100122022900002106200241086a290000210420021035412010332202450d07200220032903f002370000200241186a2001290300370000200241106a2007290300370000200241086a200829030037000020032002ad42808080808004841003220129000037036820011035200341bc016a200241206a360200200320023602b8012003200341e8006a41086a3602b4012003200341e8006a3602b001200341c8026a200341b0016a107b2002103520032802d002220941206a2201417f4c0d0120032802c802210a0240024020010d0041002107410121020c010b200110332202450d08200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322020d010c160b20072008460d0020022007200810372202450d150b2002200329038002370000200241086a20034180026a41086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020022008200710372202450d150b20022006370010200241186a200437000002400240200741606a2009490d00200721080c010b2009415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020022007200810372202450d150b200241206a200a2009109d081a024020032802cc02450d00200a10350b2001ad4220862002ad8410072008450d0d20021035420021060c0e0b41f0b8c8004119418cb9c800103f000b1044000b103e000b20004200370308200041206a20073602002000411c6a2001360200200041186a200a411874200941ff017141107472200841ff017141087472200272360200420121060c1b0b200141216a2d0000210720034188016a41186a200141196a29000037030020034188016a41106a200141116a29000037030020034188016a41086a200141096a2900003703002003200129000137038801200341f0026a41206a200241206a290200370300200341f0026a41186a200241186a290200370300200341f0026a41106a200241106a290200370300200341f0026a41086a200241086a290200370300200320022902003703f002200341b0016a200341f0026a10d706410221020240024020032d00b0014101460d00200341f0026a20034188016a10b906200341c0006a20032802f002220220032802f80241b0b4cc0041004100108a0220032802402101024020032802f402450d00200210350b4103210220014101470d000240024002400240200741ff01710d00200341f0026a20034188016a10b80620033502f80242208620032802f0022202ad841007024020032802f402450d00200210350b200341f0026a20034188016a10ba0620033502f80242208620032802f0022202ad841007024020032802f402450d00200210350b200341f0026a20034188016a10d006024020032802f002220220032802f802220810d10241ff017122014102460d002008ad4220862002ad8410070b024020032802f402450d00200210350b20010d03200341f0026a41186a4200370300200341f0026a41106a22084200370300200341f0026a41086a22024200370300200342003703f00241a29bc800ad4280808080f0008422041001220129000021062002200141086a290000370300200320063703f00220011035419cbac800ad4280808080c000842205100122012900002106200341e8006a41086a220d200141086a2900003703002003200637036820011035200820032903682206370300200341c8026a41086a220c2002290300370300200341c8026a41106a220e2006370300200341c8026a41186a220f200d290300370300200320032903f0023703c802200341f0026a200341c8026a10be0220032802f0022202410820021b210920032902f402420020021b2206422088a72210450d02201041037441786a41037641016a210a2009417f7320034188016a6a210b410021024100210103400240200920026a22082d0000450d00200b2002460d03200841016a20034188016a412010a008450d030b200241e8006a2102200a200141016a2201470d000c030b0b200341f0026a20034188016a10d80620032d00f00222024104460d02200341f0026a41086a280200210120032802f402210720032d00f102410874210820032d00f202411074210920032d00f302411874210a0c040b200341f0026a200841e800109d081a2008200841e8006a201041e8006c20026b41987f6a109e081a200341e0026a200341d0036a2903002219370300200341d8026a200341c8036a290300221a370300200341c8026a41086a200341c0036a290300221b370300200320032903b803221c3703c802200341f0026a41086a41053a0000200341f9026a201c37000020034181036a201b37000020034189036a201a37000020034191036a2019370000200341123a00f00241b0b4cc004100200341f0026a10d40120064280808080707c21060b200f4200370300200e4200370300200c4200370300200342003703c802200410012201290000210420034180026a41086a2202200141086a290000370300200320043703800220011035200c200229030037030020032003290380023703c80220051001220129000021042002200141086a290000370300200320043703800220011035200e2003290380022204370300200d200c290300370300200341e8006a41106a2004370300200341e8006a41186a2002290300370300200320032903c802370368024020090d00200341e8006aad428080808080048410070c010b200341f0026a20092006422088a710b106200341e8006aad428080808080048420033502f80242208620032802f0022202ad841002024020032802f402450d00200210350b2006a72202450d00200241e8006c450d00200910350b200341f0026a20034188016a10b90620033502f80242208620032802f0022202ad841007024020032802f402450d00200210350b200341f0026a41086a41073a0000200341f9026a20032903880137000020034199036a20073a000020034181036a20034188016a41086a29030037000020034189036a20034198016a29030037000020034191036a200341a0016a290300370000200341123a00f00241b0b4cc004100200341f0026a10d401420021060c0b0b41b99cc8002107410c210141803221084180801021094100210a0b20004200370308200041206a20013602002000411c6a2007360200200041186a200a200972200872200272360200420121060c1a0b4102210141803221070240024020022d00000d0020022d00014101470d002002411a6a2901002104200241196a2d0000210a200241186a2d0000210b200241166a2f0100210c200241156a2d0000210d200241146a2d0000210e200241126a2f0100210f200241116a2d00002110200241106a2d000021112002410e6a2f010021122002410d6a2d000021132002410c6a2d000021142002410a6a2f01002115200241096a2d00002116200241086a2d00002117200241066a2f01002118200241056a2d00002121200241046a2d00002122200241026a2f01002123200341e8006a41186a22094200370300200341e8006a41106a22074200370300200341e8006a41086a220242003703002003420037036841a29bc800ad4280808080f0008410012208290000210620034180026a41086a2201200841086a29000037030020032006370380022008103520022001290300370300200320032903800237036841ef9bc800ad4280808080f000841001220829000021062001200841086a29000037030020032006370380022008103520072003290380022206370300200341c8026a41086a2002290300370300200341c8026a41106a2006370300200341c8026a41186a2001290300370300200320032903683703c802200341f0026a200341c8026a412010d50120032d00f00221012009200341f0026a41196a2900003703002007200341f0026a41116a2900003703002002200341f0026a41096a290000370300200320032900f1023703680240024020014101460d0041002102200341003a00b0010c010b200341b0016a41096a2002290300370000200341b0016a41116a2007290300370000200341b0016a41196a200929030037000041012102200341013a00b001200320032903683700b1010b20034189036a200437000020034188036a200a3a000020034187036a200b3a000020034185036a200c3b000020034184036a200d3a000020034183036a200e3a000020034181036a200f3b000020034180036a20103a0000200341ff026a20113a0000200341fd026a20123b0000200341fc026a20133a0000200341fb026a20143a0000200341f9026a20153b0000200341f8026a20163a0000200320173a00f702200320183b00f502200320213a00f402200320223a00f302200320233b00f102200341013a00f002024020020d0041bf9bc8002108410a2102410321014180b2c00021070c020b410321010240200341b0016a410172200341f0026a410172412010a008450d0041bf9bc8002108410a21024180b2c00021070c020b200341e8006a41186a22094200370300200341e8006a41106a22244200370300200341e8006a41086a220242003703002003420037036841a29bc800ad4280808080f0008410012225290000210620034180026a41086a2208202541086a29000037030020032006370380022025103520022008290300370300200320032903800237036841f69bc800ad4280808080c000841001222529000021062008202541086a2900003703002003200637038002202510352007200329038002370000200741086a2008290300370000200341c8026a41086a2002290300370300200341c8026a41106a2024290300370300200341c8026a41186a2009290300370300200320032903683703c802200341f0026a200341c8026a412010d50120032d00f00221252009200341f0026a41196a2900003703002024200341f0026a41116a2900003703002002200341f0026a41096a290000370300200320032900f102370368410121080240024020254101460d0041002108200341003a00b0010c010b200341b0016a41096a2002290300370000200341b0016a41116a2024290300370000200341b0016a41196a2009290300370000200341013a00b001200320032903683700b1010b20034189036a200437000020034188036a200a3a000020034187036a200b3a000020034185036a200c3b000020034184036a200d3a000020034183036a200e3a000020034181036a200f3b000020034180036a20103a0000200341ff026a20113a0000200341fd026a20123b0000200341fc026a20133a0000200341fb026a20143a0000200341f9026a20153b0000200341f8026a20163a0000200320173a00f702200320183b00f502200320213a00f402200320223a00f302200320233b00f102200341013a00f002024002402008450d00200341b0016a410172200341f0026a410172412010a008450d010b41b89bc8002108410721024180b2c40021070c020b42002106200341e8006a41186a22084200370300200341e8006a41106a22094200370300200341e8006a41086a220142003703002003420037036841a29bc800ad4280808080f00084220510012224290000211920034180026a41086a2202202441086a2900003703002003201937038002202410352001200229030037030020032003290380023703684189eaca00ad4280808080f000841001222429000021192002202441086a2900003703002003201937038002202410352007200329038002370000200741086a22242002290300370000200341c8026a41086a22252001290300370300200341c8026a41106a22262009290300370300200341c8026a41186a22272008290300370300200320032903683703c802200341c8026aad42808080808004842219100720084200370300200942003703002001420037030020034200370368200510012228290000211a2002202841086a2900003703002003201a370380022028103520012002290300370300200320032903800237036841f69bc800ad4280808080c0008410012228290000211a2002202841086a2900003703002003201a3703800220281035200720032903800237000020242002290300370000202520012903003703002026200929030037030020272008290300370300200320032903683703c8022019100720084200370300200942003703002001420037030020034200370368200510012228290000211a2002202841086a2900003703002003201a370380022028103520012002290300370300200320032903800237036841ef9bc800ad4280808080f0008410012228290000211a2002202841086a2900003703002003201a3703800220281035200720032903800237000020242002290300370000202520012903003703002026200929030037030020272008290300370300200320032903683703c8022019100720084200370300200942003703002001420037030020034200370368200510012228290000211a2002202841086a2900003703002003201a37038002202810352001200229030037030020032003290380023703684188aec900ad4280808080d0008410012228290000211a2002202841086a2900003703002003201a3703800220281035200720032903800237000020242002290300370000202520012903003703002026200929030037030020272008290300370300200320032903683703c8022019100720084200370300200942003703002001420037030020034200370368200510012228290000211a2002202841086a2900003703002003201a370380022028103520012002290300370300200320032903800237036841e1b8c800ad4280808080a0018410012228290000211a2002202841086a2900003703002003201a3703800220281035200720032903800237000020242002290300370000202520012903003703002026200929030037030020272008290300370300200320032903683703c802201910072008420037030020094200370300200142003703002003420037036820051001222829000021052002202841086a29000037030020032005370380022028103520012002290300370300200320032903800237036841e0aec900ad4280808080b002841001222829000021052002202841086a290000370300200320053703800220281035200720032903800237000020242002290300370000202520012903003703002026200929030037030020272008290300370300200320032903683703c8022019100820034191036a2004370000200341f0026a41206a200a3a00002003418f036a200b3a00002003418d036a200c3b00002003418c036a200d3a00002003418b036a200e3a000020034189036a200f3b0000200341f0026a41186a20103a000020034187036a20113a000020034185036a20123b000020034184036a20133a000020034183036a20143a000020034181036a20153b0000200341f0026a41106a20163a0000200341ff026a20173a0000200341fd026a20183b0000200341fc026a20213a0000200341fb026a20223a0000200341f9026a20233b0000200341f0026a41086a410e3a0000200341123a00f00241b0b4cc004100200341f0026a10d4010c0a0b0b20004200370308200041206a20023602002000411c6a2008360200200041186a2007200172360200420121060c190b200141246a280200210f200341c8016a200141196a290000370300200341c0016a200141116a290000370300200341b8016a200141096a290000370300200320012900013703b0014102210a2001412c6a280200210c200141286a280200210e4100210b20022d0000417f6a220d41024b0d01200141306a3502002104410021094100210102400240200d0e03000401000b200241086a2802004101742002410c6a2802004d0d024100210941002101200241046a28020041ff01710d030b200341e8006a41186a4200370300200341e8006a41106a22074200370300200341e8006a41086a220142003703002003420037036841a29bc800ad4280808080f0008410012208290000210620034180026a41086a2202200841086a29000037030020032006370380022008103520012002290300370300200320032903800237036841f69bc800ad4280808080c000841001220829000021062002200841086a29000037030020032006370380022008103520072003290380022206370300200341c8026a41086a2001290300370300200341c8026a41106a2006370300200341c8026a41186a2002290300370300200320032903683703c8024100210b200341386a200341c8026a412041b0b4cc0041004100108a024103210a4180322101024020032802384101470d0041a39cc8002108410e21074180801821090c030b0240200f41024f0d0041a99bc8002108410a21074180803c21090c030b200341e8006a41186a22084200370300200341e8006a41106a22094200370300200341e8006a41086a220142003703002003420037036841a29bc800ad4280808080f0008422051001220a290000210620034180026a41086a2202200a41086a2900003703002003200637038002200a103520012002290300370300200320032903800237036841a99bc800ad4280808080a001841001220a29000021062002200a41086a2900003703002003200637038002200a10352007200329038002370000200741086a220b2002290300370000200341c8026a41086a220d2001290300370300200341c8026a41106a22102009290300370300200341c8026a41186a22112008290300370300200320032903683703c8022003200f3602f002200341c8026aad42808080808004842206200341f0026aad4280808080c000841002200341f0026a200341b0016a10d806024020032d00f002220a4104470d002008420037030020094200370300200142003703002003420037036820051001220a29000021052002200a41086a2900003703002003200537038002200a103520012002290300370300200320032903800237036841f69bc800ad4280808080c000841001220a29000021052002200a41086a2900003703002003200537038002200a10352007200329038002370000200b2002290300370000200d20012903003703002010200929030037030020112008290300370300200320032903683703c802412010332202450d01200220032903b001370000200241186a200341b0016a41186a220b290300370000200241106a200341b0016a41106a220d290300370000200241086a200341b0016a41086a220f29030037000020062002ad4280808080800484100220021035200341e8006a41186a22094200370300200341e8006a41106a220a4200370300200341e8006a41086a220842003703002003420037036841a29bc800ad4280808080f00084220510012201290000211920034180026a41086a2202200141086a29000037030020032019370380022001103520082002290300370300200320032903800237036841ef9bc800ad4280808080f000841001220129000021192002200141086a2900003703002003201937038002200110352007200329038002370000200741086a22102002290300370000200341c8026a41086a22112008290300370300200341c8026a41106a2212200a290300370300200341c8026a41186a22132009290300370300200320032903683703c802412010332201450d01200120032903b001370000200141186a200b290300370000200141106a200d290300370000200141086a200f29030037000020062001ad4280808080800484100220011035200341f0026a41186a2004422086200ead841009220141186a290000370300200341f0026a41106a200141106a290000370300200341f0026a41086a200141086a290000370300200320012900003703f0022001103520094200370300200a4200370300200842003703002003420037036820051001220129000021042002200141086a2900003703002003200437038002200110352008200229030037030020032003290380023703684188aec900ad4280808080d000841001220129000021042002200141086a290000370300200320043703800220011035200720032903800237000020102002290300370000201120082903003703002012200a29030037030020132009290300370300200320032903683703c802412010332202450d01200220032903f002370000200241186a200341f0026a41186a290300370000200241106a200341f0026a41106a290300370000200241086a200341f0026a41086a220129030037000020062002ad4280808080800484100220021035200141003a0000200341f9026a20032903b00137000020034181036a200341b0016a41086a29030037000020034189036a200341b0016a41106a29030037000020034191036a200341b0016a41186a290300370000200341123a00f00241b0b4cc004100200341f0026a10d401200c450d07200e1035420021060c080b200341f0026a41086a280200210720032802f402210820032d00f102410874210120032d00f202411074210920032d00f302411874210b0c020b1045000b41002109410021010b0240200c450d00200e10350b20004200370308200041206a20073602002000411c6a2008360200200041186a200b200972200172200a72360200420121060c150b20032002411a6a290100370380014102210a2003200241026a29010037036820032002410a6a2901003703702003200241126a2901003703784101210b410021010240024002400240024020022d000041004720022d0001410147720d00200341b0016a41186a200341e8006a41186a290300370300200341b0016a41106a200341e8006a41106a290300370300200341b0016a41086a200341e8006a41086a2202290300370300200320032903683703b001200341f0026a41186a4200370300200341f0026a41106a220f4200370300200341f0026a41086a22074200370300200342003703f00241a29bc800ad4280808080f000841001220829000021062007200841086a290000370300200320063703f002200810354189eaca00ad4280808080f000841001220829000021062002200841086a2900003703002003200637036820081035200f20032903682206370300200341c8026a41086a2007290300370300200341c8026a41106a2006370300200341c8026a41186a2002290300370300200320032903f0023703c802200341f0026a200341c8026a10fe0120032802f0022202410120021b210941f2dfca00210c4109210d4103210a4119210e0240024020032902f402420020021b2206422088a7220241014b0d0020020e020401040b4100210103402002410176220720016a22082001200920084105746a200341b0016a412010a0084101481b2101200220076b220241014b0d000b0b200920014105746a200341b0016a412010a0080d02200341f0026a200341b0016a10b806200341c8026a20032802f002220720032802f80210b40220032902cc02210420032802c8022201410820011b2102024020032802f402450d00200710350b2004420020011b210402402002450d002004422088a72210450d00200341f0026a41186a22084200370300200341f0026a41106a220a4200370300200341f0026a41086a22014200370300200342003703f00241d1c4c700ad4280808080e000841001220729000021052001200741086a290000370300200320053703f0022007103541e7c4c700ad4280808080e00084100122072900002105200341e8006a41086a220b200741086a2900003703002003200537036820071035200f2003290368370000200f41086a200b290300370000200341c8026a41086a22072001290300370300200341c8026a41106a200a290300370300200341c8026a41186a2008290300370300200320032903f0023703c802200341306a200341c8026a412010c00120022802002003280234410020032802301b4b0d00200342f0f2bd99f7edd8b4e5003703c802200341f0026a200341c8026a108106200341c8026a200341f0026a200341b0016a2002290308200241106a290300410110e6022007280200210d20032802cc02210c20032d00cb02210720032d00ca02210b20032d00c902210e024020032d00c802220a4104470d002002200241186a2010417f6a220141186c109e08210802402001450d00200341f0026a200341b0016a10b80620032802f0022102200320032802f8023602cc02200320023602c80220082001200341c8026a109603024020032802f402450d00200210350b4104210a2004a72202450d04200241186c450d04200810350c040b200341f0026a200341b0016a10b80620033502f80242208620032802f0022201ad841007024020032802f402450d00200110350b200442ffffffff0f8321044104210a0b2004a72201450d03200141186c450d03200210350c030b02402004a72201450d00200141186c450d00200210350b0240200642ffffff3f83500d00200910350b41b19cc800210c4108210d4103210a4119210e4105210b0c030b0c020b0b0240200642ffffff3f83500d00200910350b42002106200a4104460d010b200041206a200d3602002000411c6a200c360200200041186a2007411874200b41ff017141107472200e41ff017141087472200a72360200420121060b200042003703080c140b20012d0001210a20032002411a6a29010037038001410221012003200241026a29010037036820032002410a6a2901003703702003200241126a29010037037802400240024020022d00014101470d0020022d000041ff01710d00200341b0016a41186a200341e8006a41186a290300370300200341b0016a41106a200341e8006a41106a290300370300200341b0016a41086a200341e8006a41086a2202290300370300200320032903683703b001200341f0026a41186a4200370300200341f0026a41106a22084200370300200341f0026a41086a22014200370300200342003703f00241a29bc800ad4280808080f000841001220729000021062001200741086a290000370300200320063703f002200710354189eaca00ad4280808080f000841001220729000021062002200741086a2900003703002003200637036820071035200820032903682206370300200341c8026a41086a2001290300370300200341c8026a41106a2006370300200341c8026a41186a2002290300370300200320032903f0023703c802200341f0026a200341c8026a10fe0120032802f0022201410120011b21094100210202400240024020032902f402420020011b2206422088a7220141014b0d0020010e020201020b03402001410176220720026a22082002200920084105746a200341b0016a412010a0084101481b2102200120076b220141014b0d000b0b200920024105746a200341b0016a412010a0080d00200a41ff01710d02200341013a00c802200341f0026a200341b0016a10b30620033502f802210420032802f0022101410110332202450d0c200241013a000020044220862001ad842002ad4280808080108410022002103520032802f402450d03200110350c030b02402006a72202450d00200241ffffff3f71450d00200910350b410321010b20004200370308200041206a41093602002000411c6a41f2dfca00360200200041186a20014180b20472360200420121060c150b200341023a00c802200341f0026a200341b0016a10b30620033502f802210420032802f0022101410110332202450d09200241023a000020044220862001ad842002ad4280808080108410022002103520032802f402450d00200110350b200341f0026a41086a410c3a0000200341f9026a20032903b00137000020034181036a200341b0016a41086a29030037000020034189036a200341c0016a29030037000020034191036a200341c8016a29030037000020034199036a200a3a0000200341123a00f00241b0b4cc004100200341f0026a10d401200642ffffff3f83500d0120091035420021060c020b20012d0001210c200341b0016a41206a2208200141246a280200360200200341b0016a41186a22092001411c6a290200370300200341b0016a41106a220a200141146a290200370300200341b0016a41086a220b2001410c6a2902003703002003200141046a2902003703b00120032002411a6a2901003703e002410221012003200241026a2901003703c80220032002410a6a2901003703d0022003200241126a2901003703d80241002107024020022d000041004720022d000141014772450d000c050b20034180026a41186a200341c8026a41186a29030037030020034180026a41106a200341c8026a41106a29030037030020034180026a41086a200341c8026a41086a290300370300200320032903c80237038002200341f0026a41206a2008280200360200200341f0026a41186a2009290300370300200341f0026a41106a200a290300370300200341f0026a41086a200b290300370300200320032903b0013703f002200341c8026a200341f0026a108b02200341e8006a41086a200341d1026a290000370300200341e8006a41106a200341d9026a290000370300200341e8006a41186a200341e1026a290000370300200320032900c90237036820032d00c8024101460d0220034188016a41186a200341e8006a41186a29030037030020034188016a41106a200341e8006a41106a29030037030020034188016a41086a200341e8006a41086a22022903003703002003200329036837038801200341f0026a41186a4200370300200341f0026a41106a22084200370300200341f0026a41086a22014200370300200342003703f00241a29bc800ad4280808080f000841001220729000021062001200741086a290000370300200320063703f0022007103541e1b8c800ad4280808080a001841001220729000021062002200741086a2900003703002003200637036820071035200820032903682206370300200341c8026a41086a2001290300370300200341c8026a41106a2006370300200341c8026a41186a2002290300370300200320032903f0023703c802200341f0026a200341c8026a10be0220032802f0022202410820021b220a20032902f402420020021b2206422088a741e8006c6a2107200a21020340024020022007470d0041c99bc8002108410c21024180803821070c050b024020034188016a200241c8006a2201460d00200141206a2102200120034188016a412010a0080d010b0b200341f0026a41186a22074200370300200341f0026a41106a22094200370300200341f0026a41086a22024200370300200342003703f00241a29bc800ad4280808080f000841001220129000021042002200141086a290000370300200320043703f002200110354189eaca00ad4280808080f00084100122012900002104200341e8006a41086a220b200141086a290000370300200320043703682001103520082003290368370000200841086a200b290300370000200341c8026a41086a2002290300370300200341c8026a41106a2009290300370300200341c8026a41186a2007290300370300200320032903f0023703c802200341f0026a200341c8026a10fe0120032802f0022201410120011b2109410021020240024002400240024020032902f402420020011b2204422088a7220141014b0d0020010e020201020b03402001410176220720026a22082002200920084105746a20034180026a412010a0084101481b2102200120076b220141014b0d000b0b200920024105746a20034180026a412010a0080d00200c41ff01710d01200341013a00c802200341f0026a20034188016a20034180026a10b20620033502f802210520032802f0022101410110332202450d0a200241013a000020054220862001ad842002ad4280808080108410022002103520032802f402450d02200110350c020b41f2dfca00210841092102418080042107200442ffffff3f83500d05200910350c050b200341023a00c802200341f0026a20034188016a20034180026a10b20620033502f802210520032802f0022101410110332202450d08200241023a000020054220862001ad842002ad4280808080108410022002103520032802f402450d00200110350b200341f0026a41086a410b3a0000200341f9026a20032903880137000020034181036a20034188016a41086a29030037000020034189036a20034188016a41106a29030037000020034191036a20034188016a41186a29030037000020034199036a200329038002370000200341a1036a20034180026a41086a290300370000200341a9036a20034180026a41106a290300370000200341b1036a20034180026a41186a290300370000200341123a00f002200341b9036a200c3a000041b0b4cc004100200341f0026a10d4010240200442ffffff3f83500d00200910350b2006a72202450d00200241e8006c450d00200a10350b420021060b200020063703080c100b410121010c010b410321012006a72209450d00200941e8006c450d00200a10350b200041206a20023602002000411c6a2008360200200041186a20074180803c712001724180327236020020004200370308420121060c0d0b4102210702400240024020022d00000d0020022d00014101470d00200141046a2802002118200241196a2d00002101200241186a2d00002107200241166a2f01002108200241156a2d00002109200241146a2d0000210a200241126a2f0100210b200241116a2d0000210c200241106a2d0000210d2002410e6a2f0100210e2002410d6a2d0000210f2002410c6a2d000021102002410a6a2f01002111200241096a2d00002112200241086a2d00002113200241066a2f01002114200241056a2d00002115200241046a2d00002116200241026a2f0100211720032002411a6a2901003703c801200320013a00c701200320073a00c601200320083b01c401200320093a00c3012003200a3a00c2012003200b3b01c0012003200c3a00bf012003200d3a00be012003200e3b01bc012003200f3a00bb01200320103a00ba01200320113b01b801200320123a00b701200320133a00b601200320143b01b401200320153a00b301200320163a00b201200320173b01b001200341f0026a200341b0016a10d00620032802f002220120032802f80210d10241ff01712102024020032802f402450d00200110350b4103210720020d00200341f0026a41186a4200370300200341f0026a41106a22074200370300200341f0026a41086a22024200370300200342003703f00241a29bc800ad4280808080f0008422041001220129000021062002200141086a290000370300200320063703f00220011035419cbac800ad4280808080c000842205100122012900002106200341e8006a41086a220b200141086a2900003703002003200637036820011035200720032903682206370300200341c8026a41086a22082002290300370300200341c8026a41106a220c2006370300200341c8026a41186a2209200b290300370300200320032903f0023703c802200341f0026a200341c8026a10be0220032802f0022201410820011b210a410b210202400240201820032902f402420020011b2206422088a72201490d0041db9cc800210141833221070c010b41803221070240200a201841e8006c6a220d2d00000d0041e683ca0021010c010b0240200341b0016a200d41016a2202460d002002200341b0016a412010a008450d0041d483ca002101411221020c010b200341f0026a200341b0016a10d00620033502f80242208620032802f0022202ad841007024020032802f402450d00200210350b200341f0026a200a201841e8006c6a220241e800109d081a2002200241e8006a20012018417f736a41e8006c109e081a200341e0026a200341d0036a2903002219370300200341d8026a200341c8036a290300221a370300200341c8026a41086a200341c0036a290300221b370300200320032903b803221c3703c802200341f0026a41086a41053a0000200341f9026a201c37000020034181036a201b37000020034189036a201a37000020034191036a2019370000200341123a00f00241b0b4cc004100200341f0026a10d40120064280808080707c210641843221070b20094200370300200c420037030020084200370300200342003703c80220041001220d290000210420034180026a41086a2209200d41086a2900003703002003200437038002200d10352008200929030037030020032003290380023703c80220051001220d29000021042009200d41086a2900003703002003200437038002200d1035200c2003290380022204370300200b2008290300370300200341e8006a41106a2004370300200341e8006a41186a2009290300370300200320032903c80237036802400240200a0d00200341e8006aad428080808080048410070c010b200341f0026a200a2006422088a710b106200341e8006aad428080808080048420033502f80242208620032802f0022208ad841002024020032802f402450d00200810350b2006a72208450d00200841e8006c450d00200a10350b4180322108420021062007418432460d020c010b41fa9bc8002101410b21024180b22421080b200041206a20023602002000411c6a2001360200200041186a2008200741ff017172360200420121060b200042003703080c0c0b200141c0006a2903002119200141386a290300211a200141306a2903002104200141286a290300210520034188016a41186a200141196a29000037030020034188016a41106a200141116a29000037030020034188016a41086a200141096a29000037030020032001290001370388012002411a6a2901002106200241196a2d00002107200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241086a2d00002114200241066a2f01002115200241056a2d00002116200241046a2d00002117200241026a2f0100211841012101024020022d00000d0020022d000141014721010b2003200637038001200320073a007f200320083a007e200320093b017c2003200a3a007b2003200b3a007a2003200c3b01782003200d3a00772003200e3a00762003200f3b0174200320103a0073200320113a0072200320123b0170200320133a006f200320143a006e200320153b016c200320163a006b200320173a006a200320183b016802400240024020010d00200341b0016a41186a200341e8006a41186a290300370300200341b0016a41106a200341e8006a41106a290300370300200341b0016a41086a200341e8006a41086a290300370300200320032903683703b001200341f0026a20034188016a10cf06200341286a20032802f002220220032802f80241b0b4cc0041004100108a0220032802282101024020032802f402450d00200210350b4103210220014101460d01200341f0026a20034188016a10b906200341206a20032802f002220720032802f80241b0b4cc0041004100108a0220032802202101024020032802f402450d00200710350b20014101460d01200341f0026a41186a4200370300200341f0026a41106a220b4200370300200341f0026a41086a22024200370300200342003703f00241a29bc800ad4280808080f000841001220129000021062002200141086a290000370300200320063703f00220011035419cbac800ad4280808080c00084100122012900002106200341e8006a41086a2207200141086a2900003703002003200637036820011035200b20032903682206370300200341c8026a41086a2002290300370300200341c8026a41106a2006370300200341c8026a41186a2007290300370300200320032903f0023703c802200341f0026a200341c8026a10be0220032802f0022202410820021b220c20032902f402420020021b2206422088a741e8006c6a210a200c2102024003402002200a460d0141e59bc8002108410a2109410c210720034188016a200241c8006a2201460d08200141206a2102200120034188016a412010a0080d000c080b0b200341f0026a41186a22074200370300200341f0026a41106a22084200370300200341f0026a41086a22024200370300200342003703f00241a29bc800ad4280808080f0008410012201290000211b2002200141086a2900003703002003201b3703f0022001103541e1b8c800ad4280808080a0018410012201290000211b200341e8006a41086a2209200141086a2900003703002003201b37036820011035200b2003290368370000200b41086a2009290300370000200341c8026a41086a2002290300370300200341c8026a41106a2008290300370300200341c8026a41186a2007290300370300200320032903f0023703c802200341f0026a200341c8026a10be0220032802f0022202410820021b220e20032902f402420020021b221b422088a741e8006c6a210a200e2102024003402002200a460d0141d59bc800210841102109410d210720034188016a200241c8006a2201460d07200141206a2102200120034188016a412010a0080d000c070b0b200341f0026a41186a22074200370300200341f0026a41106a22084200370300200341f0026a41086a22024200370300200342003703f00241a29bc800ad4280808080f0008410012201290000211c2002200141086a2900003703002003201c3703f002200110354189eaca00ad4280808080f0008410012201290000211c200341e8006a41086a2209200141086a2900003703002003201c37036820011035200b2003290368370000200b41086a2009290300370000200341c8026a41086a2002290300370300200341c8026a41106a2008290300370300200341c8026a41186a2007290300370300200320032903f0023703c802200341f0026a200341c8026a10fe014101210720032802f0022201410120011b210b41f2dfca0021084109210941002102024020032902f402420020011b221c422088a7220d41014b0d00200d0e020503050b200d210103402001410176220720026a220a2002200b200a4105746a20034188016a412010a0084101481b2102200120076b220141014b0d000c030b0b410221020b41c59cc800210841092109410321070c050b0240200b20024105746a20034188016a412010a0080d0041ce9cc8002108410d2109410221070c020b410121074100210202400240200d41014b0d00200d0e020301030b0340200d410176220120026a220a2002200b200a4105746a200341b0016a412010a0084101481b2102200d20016b220d41014b0d000b0b200b20024105746a200341b0016a412010a0080d01200341f0026a200341b0016a10d006200341186a20032802f002220120032802f80241b0b4cc0041004100108a0220032802182102024020032802f402450d00200110350b024020024101470d0041859cc8002108410f2109410821070c020b200341f0026a200341b0016a10d00620033502f802211d20032802f0022101410110332202450d00200241003a0000201d4220862001ad842002ad42808080801084100220021035024020032802f402450d00200110350b200320063702cc022003200c3602c802200341a0036a201937030020034189036a2202200341b0016a41186a220129030037000020034181036a2207200341b0016a41106a2208290300370000200341f9026a2209200341b0016a41086a220a2903003700002003201a37039803200320032903b0013700f102200341013a00f002200341c8026a20034188016a20052004200341f0026a10d606200341c8036a2004370300200341c0036a2005370300200341f0026a41086a41023a00002009200329038801370000200720034188016a41086a290300370000200220034188016a41106a29030037000020034191036a20034188016a41186a29030037000020034199036a20032903b001370000200341a1036a200a290300370000200341a9036a2008290300370000200341b1036a2001290300370000200341123a00f00241b0b4cc004100200341f0026a10d4010240201c42ffffff3f83500d00200b10350b0240201ba72202450d00200241e8006c450d00200e10350b420021060c050b103c000b201c42ffffff3f83500d00200b10350b201ba72202450d00200241e8006c450d00200e10350b02402006a72202450d00200241e8006c450d00200c10350b410321020b200041206a20093602002000411c6a2008360200200041186a200741107420027241803272360200420121060b200042003703080c050b410221070240024020022d00000d0020022d00014101470d002002411a6a2901002106200241196a2d00002108200241186a2d0000210a200241166a2f0100210b200241156a2d0000210c200241146a2d0000210d200241126a2f0100210e200241116a2d0000210f200241106a2d000021102002410e6a2f010021112002410d6a2d000021122002410c6a2d000021132002410a6a2f01002114200241096a2d00002115200241086a2d00002116200241066a2f01002117200241056a2d00002118200241046a2d00002121200241026a2f010021222003200141046a28020022093602a002200341f0026a41186a4200370300200341f0026a41106a22234200370300200341f0026a41086a22014200370300200342003703f00241a29bc800ad4280808080f0008422041001220229000021052001200241086a290000370300200320053703f00220021035419cbac800ad4280808080c000842205100122072900002119200341e8006a41086a2202200741086a2900003703002003201937036820071035202320032903682219370300200341c8026a41086a22232001290300370300200341c8026a41106a22242019370300200341c8026a41186a22252002290300370300200320032903f0023703c802200341f0026a200341c8026a10be0220032802f002210120032902f4022119200341a4016a2006370200200341a3016a20083a0000200341a2016a200a3a000020034188016a41186a200b3b01002003419f016a200c3a00002003419e016a200d3a00002003419c016a200e3b01002003419b016a200f3a00002003419a016a20103a000020034188016a41106a20113b010020034197016a20123a000020034196016a20133a000020034194016a20143b010020034193016a20153a000020034192016a20163a000020034188016a41086a20173b0100200320183a008f01200320213a008e01200320223b018c012001410820011b21082003200341a0026a360288014183322107024020092019420020011b2206422088a7220a4f0d0002402008200941e8006c6a220141c8006a220c20034188016a410472220b460d00200c200b412010a0080d010b20012d00002107200320012800013602682003200141046a28000036006b200141106a2903002119200141086a290300211a200341b0016a200141186a41d000109d081a2001200141e8006a2009417f73200a6a41e8006c109e081a0240024020074101470d00200341ff026a20193700002003418f036a200341b0016a41086a2d00003a00002003201a3700f7022003200328006b3600f302200320032802683602f002200320032903b00137008703200341c8026a200341f0026a10d00620033502d00242208620032802c8022201ad84100720032802cc02450d01200110350c010b2003201a370380022003201937038802201a201984500d002003200b3602b802200341c8026a200b20034180026a200341b8026a10f00220032903c8024201520d0020032903d0022119200341a8036a200341c8026a41106a290300370300200341a0036a2019370300200341f0026a41086a41003a0000200341f9026a200b29000037000020034181036a200b41086a29000037000020034189036a200b41106a29000037000020034191036a200b41186a290000370000200341033a00f00241b0b4cc004100200341f0026a10d4010b20064280808080707c2106200341f8026a41043a0000200341f9026a200329028c0137000020034181036a20034194016a29020037000020034189036a2003419c016a29020037000020034191036a200341a4016a290200370000200341123a00f00241b0b4cc004100200341f0026a10d40141843221070b200341e8006a41186a4200370300200341e8006a41106a220a42003703002002420037030020034200370368200410012209290000210420034180026a41086a2201200941086a29000037030020032004370380022009103520022001290300370300200320032903800237036820051001220929000021042001200941086a290000370300200320043703800220091035200a2003290380022204370300202320022903003703002024200437030020252001290300370300200320032903683703c8020240024020080d00200341c8026aad428080808080048410070c010b200341f0026a20082006422088a710b106200341c8026aad428080808080048420033502f80242208620032802f0022202ad841002024020032802f402450d00200210350b2006a72202450d00200241e8006c450d00200810350b420021062007418432460d010b2000411c6a41db9cc800ad4280808080b00184370200200041186a200741ff017141803272360200420121060b200042003703080c040b410221070b41c59cc8002108410921094119210a4103210b0b200041206a20093602002000411c6a2008360200200041186a200c411874200b41ff017141107472200a41ff017141087472200741ff017172360200420121060b200042003703080b2000200637030020034180046a24000bbb6504147f017e037f027e230041c0046b220324000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e0a00010203040506070809000b200341e4016a4101360200200342013702d401200341e8d4ca003602d00120034104360284042003419cd5ca0036028004200320034180046a3602e001200341d0016a41b0b4cc00104c000b200141246a2802002104200341c8006a41186a200141196a290000370300200341c8006a41106a200141116a290000370300200341c8006a41086a200141096a29000037030020032001290001370348410a2105410221010240024020022d00000d0020022d00014101470d00200241196a2d00002101200241186a2d00002106200241166a2f01002107200241156a2d00002108200241146a2d00002109200241126a2f0100210a200241116a2d0000210b200241106a2d0000210c2002410e6a2f0100210d2002410d6a2d0000210e2002410c6a2d0000210f2002410a6a2f01002110200241096a2d00002111200241086a2d00002112200241066a2f01002113200241056a2d00002114200241046a2d00002115200241026a2f0100211620032002411a6a29010037038001200320013a007f200320063a007e200320073b017c200320083a007b200320093a007a2003200a3b01782003200b3a00772003200c3a00762003200d3b01742003200e3a00732003200f3a0072200320103b0170200320113a006f200320123a006e200320133b016c200320143a006b200320153a006a200320163b0168200341a8046a200341e8006a109507200341d0016a20032802a804220120032802b00410d50120034180046a41086a2202200341da016a29010037030020034180046a41106a2206200341e2016a29010037030020034180046a41176a2207200341e9016a290000370000200320032901d201370380040240024020032d00d0014101470d0020032d00d1012108200341a8016a41176a2007290000370000200341a8016a41106a2006290300370300200341a8016a41086a200229030037030020032003290380043703a801024020032802ac04450d00200110350b20034191016a200341a8016a41086a29030037000020034199016a200341a8016a41106a29030037000020034188016a41186a200341bf016a290000370000200320083a008801200320032903a8013700890120034188016a200341c8006a412010a0080d01200341d0016a200441b002109d081a2003418a046a200341c8006a41086a29030037010020034192046a200341c8006a41106a2903003701002003419a046a200341c8006a41186a29030037010020034180023b0180042003200329034837018204200341a8016a200341d0016a20034180046a10ac0320032903a8014201510d030c250b20032802ac04450d00200110350b410321010b200410ba0241cdd7ca002108418034210741002102410021060c230b20032903b0014202510d21200341c8016a2802002105200341c4016a2802002108200341c0016a2802002201418080807871210220014180807c712106200141807e7121070c220b200341a8016a41186a200141196a290000370300200341a8016a41106a200141116a290000370300200341a8016a41086a200141096a290000370300200320012900013703a80120034180046a41186a200141396a29000037030020034180046a41106a200141316a29000037030020034180046a41086a200141296a2900003703002003200141216a2900003703800420022d000120022d0000410047720d08200341d0016a20034180046a10950720033502d801211720032802d0012102412010332201450d07200120032903a801370000200141186a200341a8016a41186a2204290300370000200141106a200341a8016a41106a2205290300370000200141086a200341a8016a41086a220629030037000020174220862002ad842001ad4280808080800484100220011035024020032802d401450d00200210350b200341f2016a200329038004370100200341da016a2006290300370100200341e2016a2005290300370100200341ea016a2004290300370100200341fa016a20034180046a41086a29030037010020034182026a20034180046a41106a2903003701002003418a026a20034180046a41186a29030037010020034193083b01d001200320032903a8013701d20141b0b4cc004100200341d0016a10d4010c150b200141086a2802002107200141046a28020021094102210520022d00000d1d20022d00014101470d1d2001410c6a2802002118200141106a2802002119200141026a2f0100211a200241196a2d00002101200241186a2d00002104200241166a2f01002105200241156a2d00002106200241146a2d00002108200241126a2f0100210a200241116a2d0000210b200241106a2d0000210c2002410e6a2f0100210d2002410d6a2d0000210e2002410c6a2d0000210f2002410a6a2f01002110200241096a2d00002111200241086a2d00002112200241066a2f01002113200241056a2d00002114200241046a2d00002115200241026a2f0100211620032002411a6a2901003703c001200320013a00bf01200320043a00be01200320053b01bc01200320063a00bb01200320083a00ba012003200a3b01b8012003200b3a00b7012003200c3a00b6012003200d3b01b4012003200e3a00b3012003200f3a00b201200320103b01b001200320113a00af01200320123a00ae01200320133b01ac01200320143a00ab01200320153a00aa01200320163b01a801200341d0016a200341a8016a109607200341186a20032802d001220120032802d80141b0b4cc0041004100108a0220032802182102024020032802d401450d00200110350b4101210141032105411a2106024020024101470d0041fdd6ca00210441122102410621010c1f0b0240201a0d0041c0d7ca002104410d21020c1f0b41b0d7ca0021044110210241022101024020180d000c1f0b02402018201a4f0d000c1f0b410321050240201841094d0d0041a6d7ca002104410a2102410321010c1f0b201841016a210a2009210802400340200a417f6a220a4102490d012008200841206a220b412010a008210c419dd7ca0021044109210241042101200b2108200c4100480d000b0c1f0b200341086a2018ad42004280c0f4c198af0b420010840820032003290308221b4280808d93f5d7f1007c2217370388012003200341086a41086a2903002017201b54ad7c221b370390012003200341a8016a3602482003200341a8016a3602682003200341e8006a3602d8012003200341c8006a3602d401200320034188016a3602d00120034180046a200341a8016a200341d0016a108c03024002402003280280044101470d002003418c046a280200210220034180046a41086a280200210420032d008704210820032d008604210120032d008504210620032d00840421050c010b41042105024020034180046a41086a2903004201520d0020034180046a41106a290300211c2003280268210120034188026a20034180046a41186a29030037030020034180026a201c370300200341d0016a41086a41003a0000200341d9016a2001290000370000200341e1016a200141086a290000370000200341e9016a200141106a290000370000200341f1016a200141186a290000370000200341033a00d00141b0b4cc004100200341d0016a10d4010b0b200541ff01714104470d1e20034180046a200341a8016a109607200335028804211c200328028004210e200341003602d801200342013703d001410410332201450d1c200341043602d401200320013602d00120012019360000200341043602d80120014104411410372201450d1c200120173700042001410c6a201b370000200320013602d00120034294808080c0023702d4012018200341d0016a10772018410574210c410020032802d801220b6b210d20032802d401210541002106410021010340200b20016a210802400240200d20056a20066a4120490d0020032802d00121022005210a0c010b200841206a22022008490d0b200541017422042002200420024b1b220a4100480d0b0240024020050d000240200a0d00410121020c020b200a103322020d010c200b20032802d00121022005200a460d0020022005200a10372202450d1f0b2003200a3602d401200320023602d001200a21050b2002200b6a20016a2202200920016a2204290000370000200241186a200441186a290000370000200241106a200441106a290000370000200241086a200441086a2900003700002003200841206a3602d801200641606a2106200c200141206a2201470d000b200b20016a210502400240200a200b6b20016b4102490d0020032802d0012102200a21040c010b200541026a22022005490d0a200a41017422042002200420024b1b22044100480d0a02400240200a0d00024020040d00410121020c020b200410332202450d1f0c010b20032802d0012102200a2004460d002002200a200410372202450d1e0b200320043602d401200320023602d0010b2002200b6a20016a201a3b0000201c422086200ead84200541026aad4220862002ad84100202402004450d00200210350b0240200328028404450d00200e10350b0240200741ffffff3f71450d00200910350b200341da016a200341b0016a290300370100200341e2016a200341b8016a290300370100200341ea016a200341c0016a290300370100200341133b01d001200320032903a8013701d20141b0b4cc004100200341d0016a10d4010c140b20034188016a41186a200141196a29000037030020034188016a41106a200141116a29000037030020034188016a41086a200141096a29000037030020032001290001370388014102210120022d00000d1920022d00014101470d19200241196a2d00002101200241186a2d00002104200241166a2f01002105200241156a2d00002106200241146a2d00002107200241126a2f01002108200241116a2d00002109200241106a2d0000210a2002410e6a2f0100210b2002410d6a2d0000210c2002410c6a2d0000210d2002410a6a2f0100210e200241096a2d0000210f200241086a2d00002110200241066a2f01002111200241056a2d00002112200241046a2d00002113200241026a2f0100211420032002411a6a2901003703c001200320013a00bf01200320043a00be01200320053b01bc01200320063a00bb01200320073a00ba01200320083b01b801200320093a00b7012003200a3a00b6012003200b3b01b4012003200c3a00b3012003200d3a00b2012003200e3b01b0012003200f3a00af01200320103a00ae01200320113b01ac01200320123a00ab01200320133a00aa01200320143b01a801200341d0016a20034188016a109607200341306a20032802d001220120032802d80141b0b4cc0041004100108a0220032802302105024020032802d401450d00200110350b410e210441032101411a2102024020054101460d00418fd7ca002107410521060c1b0b200341d0016a20034188016a200341a8016a109707200341286a20032802d001220620032802d80141b0b4cc0041004100108a0220032802282105024020032802d401450d00200610350b024020054101470d0041efd6ca002107410721060c1b0b2003420037037020034280808d93f5d7f1003703682003200341a8016a3602a8042003200341a8016a3602482003200341c8006a3602d8012003200341a8046a3602d4012003200341e8006a3602d00120034180046a200341a8016a200341d0016a108c03024002402003280280044101470d002003418c046a280200210420034188046a280200210720032d008704210520032d008604210620032d008504210220032d00840421010c010b41042101024020034180046a41086a2903004201520d0020034180046a41106a29030021172003280248210220034188026a20034180046a41186a29030037030020034180026a2017370300200341d0016a41086a41003a0000200341d9016a2002290000370000200341e1016a200241086a290000370000200341e9016a200241106a290000370000200341f1016a200241186a290000370000200341033a00d00141b0b4cc004100200341d0016a10d4010b0b200141ff01714104470d1a42002117200341d0016a41186a4200370300200341d0016a41106a22044200370300200341d0016a41086a22014200370300200342003703d00141d1c4c700ad4280808080e0008410012202290000211b2001200241086a2900003703002003201b3703d0012002103541e7c4c700ad4280808080e0008410012202290000211b200341e8006a41086a2205200241086a2900003703002003201b3703682002103520042003290368221b37030020034180046a41086a200129030037030020034180046a41106a201b37030020034180046a41186a2005290300370300200320032903d00137038004200341206a20034180046a412010c0012003280224210120032802202102200341ec016a4100360200200342003703d80120034280808d93f5d7f1003703d001200342013702e40120032001410020021b3602e00120034180046a20034188016a200341a8016a1097072003280280042101200320032802880436026c20032001360268200341d0016a200341e8006a1094070240200328028404450d00200110350b200341da016a20034188016a41086a290300370100200341e2016a20034188016a41106a290300370100200341ea016a20034188016a41186a290300370100200341f2016a20032903a801370100200341fa016a200341a8016a41086a29030037010020034182026a200341a8016a41106a2903003701002003418a026a200341a8016a41186a29030037010020034193023b01d00120032003290388013701d20141b0b4cc004100200341d0016a10d4010c140b200341e8006a41186a200141196a290000370300200341e8006a41106a200141116a290000370300200341e8006a41086a200141096a2900003703002003200129000137036820034188016a41186a200141396a29000037030020034188016a41106a200141316a29000037030020034188016a41086a200141296a2900003703002003200141216a290000370388014102210120022d00000d1620022d00014101470d16200241196a2d00002101200241186a2d00002104200241166a2f01002105200241156a2d00002106200241146a2d00002107200241126a2f01002108200241116a2d00002109200241106a2d0000210a2002410e6a2f0100210b2002410d6a2d0000210c2002410c6a2d0000210d2002410a6a2f0100210e200241096a2d0000210f200241086a2d00002110200241066a2f01002111200241056a2d00002112200241046a2d00002113200241026a2f0100211420032002411a6a2901003703c001200320013a00bf01200320043a00be01200320053b01bc01200320063a00bb01200320073a00ba01200320083b01b801200320093a00b7012003200a3a00b6012003200b3b01b4012003200c3a00b3012003200d3a00b2012003200e3b01b0012003200f3a00af01200320103a00ae01200320113b01ac01200320123a00ab01200320133a00aa01200320143b01a80120034180046a200341e8006a109607200341d0016a200328028004220420032802880410e20220032802840421020240024020032802e4012207450d00200341ec016a280200210120032802e801210902402002450d00200410350b200341c8006a200341e8006a20034188016a109707200341d0016a20032802482202200328025010d00241082104200341d0016a41086a290300211b20032903d001211c20032903e801211720032802e401210820032802e00121050240200328024c450d00200210350b20080d0141e5d6ca002106410a21050c170b02402002450d00200410350b418fd7ca002106410e210541032101410521040c180b20034198046a20173703002003201c37038004200320083602940420032005360290042003201b370388042017a7210a41dcd6ca0021064100210202400240200141014b0d00410921044109210520010e021101110b03402001410176220420026a22052002200720054105746a200341a8016a412010a0084101481b2102200120046b220141014b0d000b0b4109210441092105200720024105746a200341a8016a412010a0080d0f4100210102402017422088a7220641014b0d00024020060e020010000b200341d0016a41186a200341a8016a41186a290300370300200341d0016a41106a200341a8016a41106a290300370300200341d0016a41086a200341a8016a41086a290300370300200320032903a8013703d00141002104200341d0016a21020c120b2006210203402002410176220420016a22052001200820054105746a200341a8016a412010a0084101481b2101200220046b220241014b0d000c0f0b0b20034188016a41186a200141196a29000037030020034188016a41106a200141116a29000037030020034188016a41086a200141096a2900003703002003200129000137038801410e210441052105410221010240024020022d00000d0020022d00014101470d00200241196a2d00002101200241186a2d00002106200241166a2f01002107200241156a2d00002108200241146a2d00002109200241126a2f0100210a200241116a2d0000210b200241106a2d0000210c2002410e6a2f0100210d2002410d6a2d0000210e2002410c6a2d0000210f2002410a6a2f01002110200241096a2d00002111200241086a2d00002112200241066a2f01002113200241056a2d00002114200241046a2d00002115200241026a2f0100211620032002411a6a2901003703c001200320013a00bf01200320063a00be01200320073b01bc01200320083a00bb01200320093a00ba012003200a3b01b8012003200b3a00b7012003200c3a00b6012003200d3b01b4012003200e3a00b3012003200f3a00b201200320103b01b001200320113a00af01200320123a00ae01200320133b01ac01200320143a00ab01200320153a00aa01200320163b01a80120034180046a20034188016a109607200341d0016a200328028004220220032802880410e2022003280284042101024020032802e4012206450d00200341f0016a2f0100210920032802e801210720032802e001210802402001450d00200210350b20034180046a20034188016a200341a8016a109707200341d0016a200328028004220220032802880410d00220032903e801211720032802e401210120032802e00121050240200328028404450d00200210350b20010d0241e5d6ca002102410a2104410821050c0e0b02402001450d00200210350b410321010b418fd7ca0021020c0d0b200341d0016a200341a8016a109507200341c0006a20032802d001220420032802d80141b0b4cc0041004100108a0220032802402102024020032802d401450d00200410350b024020024101470d00419bd6ca002102410c2104410f21050c0b0b200341d0016a41186a4200370300200341d0016a41106a220b420037030041082104200341d0016a41086a22024200370300200342003703d00141d1c4c700ad4280808080e000841001220a290000211b2002200a41086a2900003703002003201b3703d001200a103541e7c4c700ad4280808080e000841001220a290000211b200341e8006a41086a220c200a41086a2900003703002003201b370368200a1035200b2003290368221b37030020034180046a41086a200229030037030020034180046a41106a201b37030020034180046a41186a200c290300370300200320032903d00137038004200341386a20034180046a412010c0010240200520086a220220054f0d0041a7d6ca002102410e21050c0b0b02402002200328023c410020032802381b4d0d0041d1d6ca002102410b2104410a21050c0b0b02402017422088a720094f0d0041bad6ca00210241092104410c21050c0b0b200341d0016a200341a8016a10950720033502d801211b20032802d0012104412010332202450d032002200329038801370000200241186a20034188016a41186a2205290300370000200241106a20034188016a41106a2208290300370000200241086a20034188016a41086a2209290300370000201b4220862004ad842002ad4280808080800484100220021035024020032802d401450d00200410350b200341a8016a108d02200341da016a2009290300370100200341e2016a2008290300370100200341ea016a2005290300370100200341f2016a20032903a801370100200341fa016a200341a8016a41086a29030037010020034182026a200341a8016a41106a2903003701002003418a026a200341a8016a41186a29030037010020034193083b01d00120032003290388013701d20141b0b4cc004100200341d0016a10d4010240201742ffffff3f83500d00200110350b200741ffffff3f71450d11200610350c110b200341a8016a41186a200141196a290000370300200341a8016a41106a200141116a290000370300200341a8016a41086a200141096a290000370300200320012900013703a8014182b4202101024020022d00000d0020022d00014101470d00200241196a2d00002101200241186a2d00002104200241166a2f01002105200241156a2d00002106200241146a2d00002107200241126a2f01002108200241116a2d00002109200241106a2d0000210a2002410e6a2f0100210b2002410d6a2d0000210c2002410c6a2d0000210d2002410a6a2f0100210e200241096a2d0000210f200241086a2d00002110200241066a2f01002111200241056a2d00002112200241046a2d00002113200241026a2f0100211420032002411a6a29010037039804200320013a009704200320043a009604200320053b019404200320063a009304200320073a009204200320083b019004200320093a008f042003200a3a008e042003200b3b018c042003200c3a008b042003200d3a008a042003200e3b0188042003200f3a008704200320103a008604200320113b018404200320123a008304200320133a008204200320143b01800420034188016a20034180046a200341a8016a109707200341d0016a2003280288012201200328029001220210d002024020032802e4012204450d002002ad4220862001ad841007200341d0016a41086a290300211720032903d001211b20032903e801211c0240200328028c01450d00200110350b200341d0016a200341a8016a20034180046a201b2017410010ef02200341da016a20034180046a41086a290300370100200341e2016a20034180046a41106a290300370100200341ea016a20034180046a41186a290300370100200341f2016a20032903a801370100200341fa016a200341a8016a41086a29030037010020034182026a200341a8016a41106a2903003701002003418a026a200341a8016a41186a29030037010020034193063b01d00120032003290380043701d20141b0b4cc004100200341d0016a10d401201c42ffffff3f83500d12200410350c120b0240200328028c01450d00200110350b4183b42021010b200041206a410a3602002000411c6a41e5d6ca00360200200041186a200136020020004200370308420121170c1d0b4102210120022d00000d0520022d00014101470d05200241196a2d00002101200241186a2d00002104200241166a2f01002105200241156a2d00002106200241146a2d00002107200241126a2f01002108200241116a2d00002109200241106a2d0000210a2002410e6a2f0100210b2002410d6a2d0000210c2002410c6a2d0000210d2002410a6a2f0100210e200241096a2d0000210f200241086a2d00002110200241066a2f01002111200241056a2d00002112200241046a2d00002113200241026a2f0100211420032002411a6a2901003703c001200320013a00bf01200320043a00be01200320053b01bc01200320063a00bb01200320073a00ba01200320083b01b801200320093a00b7012003200a3a00b6012003200b3b01b4012003200c3a00b3012003200d3a00b2012003200e3b01b0012003200f3a00af01200320103a00ae01200320113b01ac01200320123a00ab01200320133a00aa01200320143b01a80141f8a2cb00ad428080808080018410012201290000211720034180046a41086a200141086a29000037030020032017370380042001103541e8a5cb00ad428080808080028410012201280004210820012800002109200341ac046a2001410e6a2f00003b01002003200128000a3602a80420012f0008210a20011035412010332201450d01200120032903a801370000200141186a200341a8016a41186a290300370000200141106a200341a8016a41106a290300370000200141086a200341a8016a41086a29030037000020032001ad42808080808004841003220229000037034820021035200341dc016a200141206a360200200320013602d8012003200341c8006a41086a3602d4012003200341c8006a3602d001200341e8006a200341d0016a107b200110352003280270220641206a2202417f4c0d03200328026821070240024020020d0041002104410121010c010b200210332201450d02200221040b024002402004410f4d0d00200421050c010b200441017422054110200541104b1b22054100480d05024020040d00200510332201450d190c010b20042005460d0020012004200510372201450d180b2001200329038004370000200141086a20034180046a41086a2903003700000240024020054170714110460d00200521040c010b200541017422044120200441204b1b22044100480d0520052004460d0020012005200410372201450d180b2001200a3b00182001200836001420012009360010200120032802a80436001a2001411e6a200341ac046a2f01003b000002400240200441606a2006490d00200421050c010b2006415f4b0d05200441017422052002200520024b1b22054100480d0520042005460d0020012004200510372201450d180b200141206a20072006109d081a0240200328026c450d00200710350b0240024020020d0041002104410121070c010b200210332207450d02200221040b0240024020042002490d00200421060c010b200441017422062002200620024b1b22064100480d05024020040d00200610332207450d190c010b20042006460d0020072004200610372207450d180b200720012002109d0821042003419c016a200236020020034198016a2005360200200320013602940120032002360290012003200636028c012003200436028801200341d0016a2002ad4220862001ad84102710c20102400240024020032802d0012201450d0020032802d401210202400240200341d8016a28020022042003280290012205490d0020032802880122062001460d0120062001200510a008450d010b2002450d01200110350c010b20034194016a2105200320043602b004200320023602ac04200320013602a804200341d0016a2001200410d002024020032802e40122010d002003410036025020034201370348200341f4006a4135360200200320053602b4042003413536026c2003200341b8046a3602702003200341b4046a3602682003200341a8046a3602b8042003200341c8006a3602bc0420034194046a4102360200200342023702840420034180c9c400360280042003200341e8006a36029004200341bc046a41e88ac50020034180046a10431a20033502504220862003350248841006200328024c450d00200328024810350b20034180046a41086a2202200341a8046a41086a280200360200200320032903a804370380040240200328029801450d0020032802940110350b2005200329038004370200200541086a200228020036020020010d010b20034180046a200341a8016a109607200341d0016a2003280280042202200328028804220410e202024020032802e4012201450d002004ad4220862002ad8410070b200328028404210402402001450d00200341d8016a290300211720032903d001211b20032802e801210502402004450d00200210350b2003201b370368200320173703700240201b201784500d002003200341a8016a36024820034180046a200341a8016a200341e8006a200341c8006a10f0022003290380044201520d00200329038804211720034188026a20034180046a41106a29030037030020034180026a2017370300200341d0016a41086a41003a0000200341d9016a20032903a801370000200341e1016a200341a8016a41086a290300370000200341e9016a200341a8016a41106a290300370000200341f1016a200341c0016a290300370000200341033a00d00141b0b4cc004100200341d0016a10d4010b200341da016a200341b0016a290300370100200341e2016a200341b8016a290300370100200341ea016a200341c0016a290300370100200341930a3b01d001200320032903a8013701d20141b0b4cc004100200341d0016a10d4010240200541ffffff3f71450d00200110350b0240200328028c01450d0020032802880110350b200328029801450d1220032802940110350c120b02402004450d00200210350b418fd7ca002102410e21044180801421050c010b41afd6ca002102410b210441808034210520032802e80141ffffff3f71450d00200110350b0240200328028c01450d0020032802880110350b0240200328029801450d0020032802940110350b410321010c070b20034188016a41186a200141196a29000037030020034188016a41106a200141116a29000037030020034188016a41086a200141096a2900003703002003200129000137038801418234210120022d00000d0520022d00014101470d05200241196a2d00002101200241186a2d00002104200241166a2f01002105200241156a2d00002106200241146a2d00002107200241126a2f01002108200241116a2d00002109200241106a2d0000210a2002410e6a2f0100210b2002410d6a2d0000210c2002410c6a2d0000210d2002410a6a2f0100210e200241096a2d0000210f200241086a2d00002110200241066a2f01002111200241056a2d00002112200241046a2d00002113200241026a2f0100211420032002411a6a2901003703c001200320013a00bf01200320043a00be01200320053b01bc01200320063a00bb01200320073a00ba01200320083b01b801200320093a00b7012003200a3a00b6012003200b3b01b4012003200c3a00b3012003200d3a00b2012003200e3b01b0012003200f3a00af01200320103a00ae01200320113b01ac01200320123a00ab01200320133a00aa01200320143b01a801200341e8006a200341a8016a109507200341d0016a20032802682202200328027010d5010240024020032d00d0014101460d0041002101200341003a0080040c010b20034180046a41196a200341d0016a41196a29000037000020034180046a41096a200341d0016a41096a29000037000020034180046a41116a200341d0016a41116a29000037000041012101200341013a008004200320032900d101370081040b0240200328026c450d00200210350b200341e9016a200341a0016a290300370000200341e1016a20034198016a290300370000200341d9016a20034190016a29030037000020032003290388013700d101200341013a00d001024020010d0041833421010c060b418334210120034180046a410172200341d0016a410172412010a0080d05200341d0016a200341a8016a10950720033502d80142208620032802d0012201ad841007024020032802d401450d00200110350b200341a8016a1099020c0e0b1045000b200041186a410236020020004200370308420121170c190b1044000b103e000b410021050c010b200041206a410a3602002000411c6a41cdd7ca00360200200041186a200136020020004200370308420121170c150b20004200370308200041206a20043602002000411c6a2002360200200041186a20054180803c7120017241803472360200420121170c140b201742ffffff3f83500d00200110350b0240200741ffffff3f71450d00200610350b410321010b20004200370308200041206a20043602002000411c6a2002360200200041186a200541107420017241803472360200420121170c110b200820014105746a200341a8016a412010a00822040d0141c3d6ca002106410e2105410b21040b200a41ffffff3f71450d05200810350c050b200341d0016a41186a200341a8016a41186a290300370300200341d0016a41106a200341a8016a41106a290300370300200341d0016a41086a200341a8016a41086a290300370300200320032903a8013703d001200341d0016a21022004411f7620016a220420064b0d030b02402006200a470d0020034194046a20064101108a0120032802940421080b200820044105746a220141206a2001200620046b410574109e081a200141186a200241186a290000370000200141106a200241106a290000370000200141086a200241086a290000370000200120022900003700002003200641016a36029c04200341d0016a41186a220220034180046a41186a290300370300200341d0016a41106a20034180046a41106a290300370300200341d0016a41086a20034180046a41086a29030037030020032003290380043703d001200341c8006a200341e8006a20034188016a10970720032802482101200320032802503602ac04200320013602a804200341d0016a200341a8046a1094070240200328024c450d00200110350b0240200228020041ffffff3f71450d0020032802e40110350b200341f2016a200329038801370100200341da016a200341e8006a41086a290300370100200341e2016a200341e8006a41106a290300370100200341ea016a200341e8006a41186a290300370100200341fa016a20034188016a41086a29030037010020034182026a20034188016a41106a2903003701002003418a026a20034188016a41186a29030037010020034193043b01d001200320032903683701d201200341aa026a200341a8016a41186a290300370100200341a2026a200341a8016a41106a2903003701002003419a026a200341a8016a41086a29030037010020034192026a20032903a80137010041b0b4cc004100200341d0016a10d401200941ffffff3f71450d00200710350b420021170b200020173703080c0b0b20042006104d000b41032101200941ffffff3f71450d01200710350c010b0b200041206a20053602002000411c6a200636020020004200370308200041186a200441ff017141107420017241803472360200420121170c070b0b200041206a20043602002000411c6a200736020020004200370308200041186a2005411874200641ff017141107472200241ff017141087472200141ff017172360200420121170c050b103c000b0b0240200741ffffff3f71450d00200910350b20004200370308200041206a20023602002000411c6a2004360200200041186a2008411874200141ff017141107472200641ff017141087472200541ff017172360200420121170c020b410421014100210241002106410021070b20041035420021170240200141ff017122014104460d00200041206a20053602002000411c6a2008360200200041186a20022006418080fc07717220074180fe037172200172360200420121170b200042003703080b20002017370300200341c0046a24000bb50404057f017e017f017e0240024020012802042202450d00200128020022032d0000210420012002417f6a22053602042001200341016a3602000240200441037122064103460d00024002400240024020060e03000102000b2004410276ad21070c020b41012106024020050d000c050b20032d0001210520012002417e6a3602042001200341026a3602002005410874200472220141ffff0371418002490d04200141fcff0371410276ad21070c010b410121060240200541034f0d000c040b200341036a2d0000210520032f0001210820012002417c6a3602042001200341046a3602002008200541107472410874200472220141808004490d032001410276ad21070b410021060c020b02402004410276220841044b0d000240024020080e050002020201000b20054104490d022003350001210720012002417b6a3602042001200341056a36020020074280808080045421060c030b20054108490d01200329000121072001200241776a3602042001200341096a3602002007428080808080808080015421060c020b200841046a220541084b0d002002417e6a2102200341026a2103410021044200210741012106034002402002417f470d000c030b2003417f6a310000210920012002360204200120033602002002417f6a2102200341016a210320092004410374413871ad862007842107200441016a220441ff01712005490d000b2007427f412820084103746b413871ad885821060c010b410121060b2000200737030820002006ad3703000bf30601067f230041f0006b2102024002400240024002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a2206360204410121072001200441016a360200200541f001490d06200541847e6a220541034b0d0120050e0402030405020b200041023a00000f0b200041023a00000f0b20064102490d0420042f0001210520012003417d6a3602042001200441036a3602000240200541ef014d0d00410121070c040b200041023a00000f0b20064104490d042004280001210520012003417b6a3602042001200441056a36020041012107200541ffff034b0d02200041023a00000f0b024020064104490d00200041023a000020012003417b6a3602042001200441056a3602000f0b200041023a00000f0b41002105200241003a00682003417f6a21062003417e6a210302400240034020062005460d01200241c8006a20056a200420056a220741016a2d00003a0000200120033602042001200741026a3602002002200541016a22073a00682003417f6a21032007210520074120470d000b200241c6006a20022d004a3a0000200241306a200241d7006a290000370300200241386a200241df006a290000370300200241c0006a200241e7006a2d00003a0000200220022f01483b01442002200229004f370328200228004b2105410021010c010b0240200541ff0171450d00200241003a00680b410121010b200241246a41026a2203200241c4006a41026a2d00003a0000200241086a41086a2207200241286a41086a290300370300200241086a41106a2204200241286a41106a290300370300200241086a41186a2206200241286a41186a2d00003a0000200220022f01443b01242002200229032837030820010d03200241286a41026a20032d00003a0000200241c8006a41086a2007290300370300200241c8006a41106a2004290300370300200241c8006a41186a20062d00003a0000200220022f01243b012820022002290308370348410021070b200020073a0000200020022f01283b0001200041046a2005360200200041086a2002290348370200200041036a2002412a6a2d00003a0000200041106a200241c8006a41086a290300370200200041186a200241c8006a41106a290300370200200041206a200241c8006a41186a2802003602000f0b200041023a00000f0b200041023a00000f0b200041023a00000b9f1002097f047e230041d0056b220224000240024002400240024002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a3602042001200441016a360200200541044b0d0620050e050102030405010b200041063a00000c090b200241a0036a200110c301024020022802a0032206450d0020022802a4032107024020012802042203450d00200241a8036a2802002108200128020022042d0000210520012003417f6a3602042001200441016a360200200541014b0d004100210902400240024020050e020100010b41002105200241003a00c0032003417f6a210a2003417e6a21030340200a2005460d02200241a0036a20056a200420056a220941016a2d00003a0000200120033602042001200941026a3602002002200541016a22093a00c0032003417f6a21032009210520094120470d000b200241f0006a41186a200241a0036a41186a290300370300200241f0006a41106a200241a0036a41106a290300370300200241f0006a41086a200241a0036a41086a290300370300200220022903a003370370410121090b200241206a41186a200241f0006a41186a290300220b370300200241206a41106a200241f0006a41106a290300220c370300200241206a41086a200241f0006a41086a290300220d37030020022002290370220e370320200020093a0001200041013a0000200041026a200e3700002000410a6a200d370000200041126a200c3700002000411a6a200b3700002000412c6a2008360100200041286a2007360100200041246a20063601000c0b0b200541ff0171450d00200241003a00c0030b200041063a0000200741ffffff3f71450d09200610350c090b200041063a00000c080b200241a0036a200110b90220022802a0032101200241f0006a200241a0036a41047241ac02109d081a024002402001411b460d00200241a0036a200241f0006a41ac02109d081a41b002103322050d010c080b200041063a00000c080b20052001360200200541046a200241a0036a41ac02109d081a200041023a0000200020022f00503b0001200041036a200241d0006a41026a2d00003a0000200041046a2005360200200041086a2002290220370200200041106a200241206a41086a290200370200200041186a200241206a41106a290200370200200041206a200241206a41186a290200370200200041286a200241206a41206a2902003702000c070b200241086a200110c401024020022802080d00200228020c2103200241a0036a200110b90220022802a0032101200241f0006a200241a0036a41047241ac02109d081a2001411b460d00200241a0036a200241f0006a41ac02109d081a41b00210332205450d0620052001360200200541046a200241a0036a41ac02109d081a200041033a0000200020022f00503b0001200041036a200241d2006a2d00003a0000200041086a2005360200200041046a20033602002000410c6a2002290220370200200041146a200241206a41086a2902003702002000411c6a200241306a290200370200200041246a200241386a2902003702002000412c6a200241c0006a2802003602000c070b200041063a00000c060b41002105200241003a00c0032003417f6a210a2003417e6a210302400240024002400340200a2005460d01200241a0036a20056a200420056a220941016a2d00003a0000200120033602042001200941026a3602002002200541016a22093a00c0032003417f6a21032009210520094120470d000b200241206a41086a200241a0036a41086a290300370300200241206a41106a200241a0036a41106a290300370300200241206a41186a200241a0036a41186a290300370300200220022903a003370320200241106a200110c40120022802100d0120012802042203450d0120022802142104200128020022092d0000210520012003417f6a3602042001200941016a360200200541014b0d014100210120050e020302030b200541ff0171450d00200241003a00c0030b200041063a00000c070b410121010b200241d0006a41186a200241206a41186a290300220b370300200241d0006a41106a200241206a41106a290300220c370300200241d0006a41086a200241206a41086a290300220d37030020022002290320220e370350200041043a00002000200e370001200041096a200d370000200041116a200c370000200041196a200b370000200041246a2004360200200041216a20013a00000c050b41002105200241003a00c0032003417f6a210a2003417e6a210302400340200a2005460d01200241a0036a20056a200420056a220941016a2d00003a0000200120033602042001200941026a3602002002200541016a22093a00c0032003417f6a21032009210520094120470d000b200241206a41086a2205200241a0036a41086a290300370300200241206a41106a2203200241a0036a41106a290300370300200241206a41186a2209200241a0036a41186a290300370300200220022903a003370320200241186a200110c4012002280218450d020c030b200541ff0171450d02200241003a00c0030c020b200041063a00000c030b200228021c2101200241d0006a41186a2009290300220b370300200241d0006a41106a2003290300220c370300200241d0006a41086a2005290300220d37030020022002290320220e370350200041053a00002000200e370001200041096a200d370000200041116a200c370000200041196a200b370000200041216a20022f004d3b0000200041236a200241cf006a2d00003a0000200041246a20013602000c020b200041063a00000c010b103c000b200241d0056a24000bc60702047f047e230041b0056b22022400024002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a3602042001200441016a360200200541024b0d0320050e03010204010b200041043602000c050b20024180036a200110b9022002280280032101200241d0006a20024180036a41047241ac02109d081a024002402001411b460d0020024180036a200241d0006a41ac02109d081a41b002103322050d010c050b200041043602000c050b20052001360200200541046a20024180036a41ac02109d081a2000200536020420004101360200200041086a2002290228370200200041106a200241286a41086a290200370200200041186a200241286a41106a290200370200200041206a200241286a41186a290200370200200041286a200241286a41206a2802003602000c040b20024180036a2001109206024020022d0080034102460d00200241d0006a41206a20024180036a41206a2802002201360200200241d0006a41186a20024180036a41186a2903002206370300200241d0006a41106a20024180036a41106a2903002207370300200241d0006a41086a20024180036a41086a29030022083703002002200229038003220937035020004102360200200020093702042000410c6a2008370200200041146a20073702002000411c6a2006370200200041246a20013602000c040b200041043602000c030b200041043602000c020b20024180036a2001109206024020022d0080034102470d00200041043602000c020b200241286a41206a20024180036a41206a280200360200200241286a41186a20024180036a41186a290300370300200241286a41106a20024180036a41106a290300370300200241286a41086a20024180036a41086a290300370300200220022903800337032820024180036a200110b9022002280280032101200241d0006a20024180036a41047241ac02109d081a02402001411b460d0020024180036a200241d0006a41ac02109d081a41b00210332205450d0120052001360200200541046a20024180036a41ac02109d081a200241206a200241286a41206a2802002201360200200241186a200241286a41186a2903002206370300200241106a200241286a41106a2903002207370300200241086a200241286a41086a290300220837030020022002290328220937030020004103360200200020093702042000410c6a2008370200200041146a20073702002000411c6a2006370200200041246a2001360200200041286a20053602000c020b200041043602000c010b103c000b200241b0056a24000bbc1e03077f047e017f230041e0056b2202240002400240024002400240024002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a3602042001200441016a360200200541084b0d0a20050e09010203040506070809010b2000410a3a00000c0a0b41002105200241003a00d0032003417f6a21062003417e6a2107024002400240034020062005460d01200241b0036a20056a200420056a220841016a2d00003a0000200120073602042001200841026a3602002002200541016a22083a00d0032007417f6a21072008210520084120470d000b200241c0006a41086a200241b0036a41086a290300370300200241c0006a41106a200241b0036a41106a290300370300200241c0006a41186a200241b0036a41186a290300370300200220022903b003370340200241b0036a200110b90220022802b003210120024180016a200241b0036a41047241ac02109d081a2001411b460d01200241b0036a20024180016a41ac02109d081a41b002103322040d02103c000b200541ff0171450d00200241003a00d0030b2000410a3a00000c0a0b20042001360200200441046a200241b0036a41ac02109d081a200241206a41186a200241c0006a41186a2903002209370300200241206a41106a200241c0006a41106a290300220a370300200241206a41086a200241c0006a41086a290300220b37030020022002290340220c370320200041013a00002000200c370001200041096a200b370000200041116a200a370000200041196a2009370000200041216a20022f001d3b0000200041236a2002411f6a2d00003a0000200041246a2004360200200041286a2002290200370200200041306a200241086a290200370200200041386a200241106a290200370200200041c0006a200241186a2802003602000c090b41002105200241003a00d003410120036b21062003417e6a21070240024002400340200620056a450d01200241b0036a20056a200420056a220841016a2d00003a0000200120073602042001200841026a3602002002200541016a22083a00d0032007417f6a21072008210520084120470d000b20024180016a41086a200241b0036a41086a29030037030020024180016a41106a200241b0036a41106a29030037030020024180016a41186a200241b0036a41186a290300370300200220022903b0033703800141002105200241003a00d003200420086a2106200820036b41016a21080340200820056a450d02200241b0036a20056a200620056a220441016a2d00003a0000200120073602042001200441026a3602002002200541016a22043a00d0032007417f6a21072004210520044120470d000b200241206a41086a2201200241b0036a41086a290300370300200241206a41106a2204200241b0036a41106a290300370300200241206a41186a2205200241b0036a41186a290300370300200241c0006a41086a220720024180016a41086a290300370300200241c0006a41106a220820024180016a41106a290300370300200241c0006a41186a220320024180016a41186a290300370300200220022903b0033703202002200229038001370340200041023a000020002002290340370001200041096a2007290300370000200041116a2008290300370000200041196a2003290300370000200041216a2002290320370000200041296a2001290300370000200041316a2004290300370000200041396a2005290300370000200041c1006a20022f00003b0000200041c3006a200241026a2d00003a00000c0b0b200541ff0171450d01200241003a00d0030c010b200541ff0171450d00200241003a00d0030b2000410a3a00000c080b20024180016a200110c3010240024002402002280280012204450d002002280284012105200128020422074102490d0120024188016a2802002106200128020022082f0000210d20012007417e6a22033602042001200841026a36020020034104490d022008280002210320012007417a6a3602042001200841066a360200200041106a20033602002000410c6a2006360200200041086a2005360200200041046a2004360200200041026a200d3b0100200041033a0000200041146a20022902b0033702002000411c6a200241b0036a41086a290200370200200041246a200241b0036a41106a2902003702002000412c6a200241c8036a290200370200200041346a200241d0036a2902003702002000413c6a200241d8036a2902003702000c0a0b2000410a3a00000c090b2000410a3a0000200541ffffff3f71450d08200410350c080b2000410a3a0000200541ffffff3f71450d07200410350c070b41002105200241003a00a0012003417f6a21062003417e6a21070240034020062005460d0120024180016a20056a200420056a220841016a2d00003a0000200120073602042001200841026a3602002002200541016a22083a00a0012007417f6a21072008210520084120470d000b200241c0006a41086a20024180016a41086a2903002209370300200241c0006a41106a20024180016a41106a290300220a370300200241c0006a41186a20024180016a41186a290300220b3703002002200229038001220c370340200041043a00002000200c370001200041096a2009370000200041116a200a370000200041196a200b370000200041216a20022900b003370000200041296a200241b0036a41086a290000370000200041316a200241b0036a41106a290000370000200041396a200241b0036a41186a290000370000200041c0006a200241cf036a2800003600000c070b0240200541ff0171450d00200241003a00a0010b2000410a3a00000c060b41002105200241003a00d003410120036b21062003417e6a21070240024002400340200620056a450d01200241b0036a20056a200420056a220841016a2d00003a0000200120073602042001200841026a3602002002200541016a22083a00d0032007417f6a21072008210520084120470d000b20024180016a41086a200241b0036a41086a29030037030020024180016a41106a200241b0036a41106a29030037030020024180016a41186a200241b0036a41186a290300370300200220022903b0033703800141002105200241003a00d003200420086a2106200820036b41016a21080340200820056a450d02200241b0036a20056a200620056a220441016a2d00003a0000200120073602042001200441026a3602002002200541016a22043a00d0032007417f6a21072004210520044120470d000b200241206a41086a2201200241b0036a41086a290300370300200241206a41106a2204200241b0036a41106a290300370300200241206a41186a2205200241b0036a41186a290300370300200241c0006a41086a220720024180016a41086a290300370300200241c0006a41106a220820024180016a41106a290300370300200241c0006a41186a220320024180016a41186a290300370300200220022903b0033703202002200229038001370340200041053a000020002002290340370001200041096a2007290300370000200041116a2008290300370000200041196a2003290300370000200041216a2002290320370000200041296a2001290300370000200041316a2004290300370000200041396a2005290300370000200041c1006a20022f00003b0000200041c3006a200241026a2d00003a00000c080b200541ff0171450d01200241003a00d0030c010b200541ff0171450d00200241003a00d0030b2000410a3a00000c050b41002105200241003a00a0012003417f6a21062003417e6a21070240034020062005460d0120024180016a20056a200420056a220841016a2d00003a0000200120073602042001200841026a3602002002200541016a22083a00a0012007417f6a21072008210520084120470d000b200241c0006a41086a20024180016a41086a2903002209370300200241c0006a41106a20024180016a41106a290300220a370300200241c0006a41186a20024180016a41186a290300220b3703002002200229038001220c370340200041063a00002000200c370001200041096a2009370000200041116a200a370000200041196a200b370000200041216a20022900b003370000200041296a200241b0036a41086a290000370000200041316a200241b0036a41106a290000370000200041396a200241b0036a41186a290000370000200041c0006a200241cf036a2800003600000c050b0240200541ff0171450d00200241003a00a0010b2000410a3a00000c040b41002105200241003a00a0012003417f6a21062003417e6a21070240034020062005460d0120024180016a20056a200420056a220841016a2d00003a0000200120073602042001200841026a3602002002200541016a22083a00a0012007417f6a21072008210520084120470d000b200241c0006a41086a20024180016a41086a2903002209370300200241c0006a41106a20024180016a41106a290300220a370300200241c0006a41186a20024180016a41186a290300220b3703002002200229038001220c370340200041073a00002000200c370001200041096a2009370000200041116a200a370000200041196a200b370000200041216a20022900b003370000200041296a200241b0036a41086a290000370000200041316a200241b0036a41106a290000370000200041396a200241b0036a41186a290000370000200041c0006a200241cf036a2800003600000c040b0240200541ff0171450d00200241003a00a0010b2000410a3a00000c030b200041083a00000c020b41002105200241003a00a0012003417f6a21062003417e6a21070240034020062005460d0120024180016a20056a200420056a220841016a2d00003a0000200120073602042001200841026a3602002002200541016a22083a00a0012007417f6a21072008210520084120470d000b200241c0006a41086a20024180016a41086a2903002209370300200241c0006a41106a20024180016a41106a290300220a370300200241c0006a41186a20024180016a41186a290300220b3703002002200229038001220c370340200041093a00002000200c370001200041096a2009370000200041116a200a370000200041196a200b370000200041216a20022900b003370000200041296a200241b0036a41086a290000370000200041316a200241b0036a41106a290000370000200041396a200241b0036a41186a290000370000200041c0006a200241cf036a2800003600000c020b0240200541ff0171450d00200241003a00a0010b2000410a3a00000c010b2000410a3a00000b200241e0056a24000bab0301087f230041206b220324000240024002400240200141246c41046a2204417f4c0d000240024020040d0041012105410021040c010b200410332205450d020b2003410036020820032005360200200320043602042001200310770240024020010d002003280208210420032802042106200328020021070c010b200141246c210820032802042105200328020821010340200341106a200010c0032003280210210902400240200520016b2003280218220a490d002001200a6a210420032802002107200521060c010b2001200a6a22042001490d05200541017422062004200620044b1b22064100480d050240024020050d00024020060d00410121070c020b2006103322070d010c080b2003280200210720052006460d0020072005200610372207450d070b20032006360204200320073602000b200720016a2009200a109d081a2003200436020802402003280214450d00200910350b200041246a210020062105200421012008415c6a22080d000b0b20022902002004ad4220862007ad84100202402006450d00200710350b200341206a24000f0b1044000b1045000b103e000b103c000bd20301037f0240024020002d0000220141144b0d00024002400240024002400240024020010e15080808080808000808010802080308040508060808080b200041086a2d00004101470d07200041146a28020041ffffff3f71450d07200041106a28020010350f0b200041046a2d00000d062000410c6a2802002201450d06200141306c450d06200041086a28020010350f0b200041046a2802000d052000410c6a2802002201450d05200141286c450d05200041086a28020010350f0b200041086a2d00004107470d04200041306a280200450d042000412c6a28020010350f0b200041046a2d00004102490d030240200041106a2802002201450d00200141d0006c2102200041086a28020041c4006a21010340024020012802002203450d00200341306c450d002001417c6a28020010350b200141d0006a2101200241b07f6a22020d000b0b2000410c6a2802002201450d03200141d0006c450d03200028020810350f0b200041086a280200450d02200041046a28020010350f0b200041086a2d00004106470d01200041306a28020041ffffff3f71450d012000412c6a28020010350c010b200041046a280200450d00200041106a2802002201450d00200041146a280200450d00200110350f0b0b13002000410a360204200041e0cfc7003602000b3400200041d1c4c70036020420004100360200200041146a410f360200200041106a4184e3c700360200200041086a42063702000b2b01017f02404101103322020d001045000b200042818080801037020420002002360200200241003a00000be00101057f230041206b22022400200241186a22034200370300200241106a22044200370300200241086a220542003703002002420037030002400240412010332206450d0020062002290300370000200641186a2003290300370000200641106a2004290300370000200641086a2005290300370000412010332203450d0120032006290000370000200341186a200641186a290000370000200341106a200641106a290000370000200341086a200641086a29000037000020061035200042a0808080800437020420002003360200200241206a24000f0b1045000b103c000bae0101017f0240410410332202450d002002410036000020024104410810372202450d00200241003a000420024108411510372202450d00200242003700052002410d6a420037000020024115412a10372202450d00200242003700152002411d6a42003700002002412a41d40010372202450d002002420037003520024200370025200042d4808080d008370204200020023602002002413d6a42003700002002412d6a42003700000f0b103c000b13002000410536020420004184fdc7003602000b2f01017f02404104103322020d001045000b20004284808080c000370204200020023602002002418080c0023600000b2f01017f02404108103322020d001045000b20004288808080800137020420002002360200200242c0b2cd3b3700000b3001017f02404108103322020d001045000b2000428880808080013702042000200236020020024280e497d0123700000b4801017f0240410810332202450d00200242c0f0f50b37000020024108411010372202450d002000429080808080023702042000200236020020024280c2d72f3700080f0b103c000b3101017f02404108103322020d001045000b2000428880808080013702042000200236020020024280c0a8ca9a3a3700000b861603027f017e0a7f230041b0016b2203240041f1d8cb00ad4280808080900184100122042900002105200341c8006a41086a200441086a290000370300200320053703482004103541a0e0c600ad4280808080b00184100122042900002105200341e8006a41086a200441086a29000037030020032005370368200410350240024002400240024002400240412010332204450d0020042001290000370000200441186a2206200141186a290000370000200441106a2207200141106a290000370000200441086a200141086a290000370000412010332208450d0020082004290000370000200841186a2006290000370000200841106a2007290000370000200841086a2206200441086a2900003700002004103541c00010332204450d002004200329036837001020042003290348370000200441086a200341c8006a41086a290300370000200441186a200341e8006a41086a29030037000020042008290000370020200441286a2006290000370000200441306a200841106a290000370000200441386a200841186a29000037000020081035200341c000360294012003200436029001200341206a2004ad4280808080800884100510c20102400240200328022022070d00410221080c010b200328022421092003200341286a28020036029c012003200736029801200341186a20034198016a10c40102400240024020032802180d00200328021c2106200341106a20034198016a10c40120032802100d002003280214210a200341086a20034198016a10c40120032802080d00200328029c012208450d00200328020c210b20032008417f6a36029c012003200328029801220841016a3602980120082d0000220c41014b0d004100210802400240200c0e020100010b410121080b200320034198016a10c40120032802000d00200328029c01220d2003280204220e490d00200e417f4c0d0502400240200e0d004100210d4101210c0c010b200e1039220c450d05200c200328029801220f200e109d081a2003200d200e6b36029c012003200f200e6a36029801200e210d0b200c0d010b2003410036025020034201370348200341093602a401200320034190016a3602a0012003200341c8006a3602ac01200341fc006a41013602002003420137026c200341c888c2003602682003200341a0016a360278200341ac016a41e88ac500200341e8006a10431a200335025042208620033502488410060240200328024c450d00200328024810350b410221080c010b200ead422086200dad8421052003418c016a41026a200341e8006a41026a2d00003a0000200320032f00683b018c010b2009450d00200710350b200341e8006a41026a2003418c016a41026a2d00003a0000200320032f018c013b01680240024020084102460d00200341c4006a41026a2207200341e8006a41026a2d00003a0000200320032f01683b014420041035200341c0006a41026a20072d000022043a0000200341306a220920053703002003413b6a20043a0000200320032f014422043b0140200320083a00382003200c36022c2003200b3602282003200a360224200320043b003920032006360220200341206a41086a2107200228027020064b0d010c070b20041035200041086a4111360200200041ef84c800360204200041013602000c070b41f1d8cb00ad4280808080900184100122042900002105200341c8006a41086a200441086a29000037030020032005370348200410354194e0c600ad4280808080c00184100122042900002105200341e8006a41086a200441086a2900003703002003200537036820041035412010332204450d0020042001290000370000200441186a2206200141186a290000370000200441106a220a200141106a290000370000200441086a220b200141086a290000370000412010332208450d0020082004290000370000200841186a2006290000370000200841106a200a290000370000200841086a200b2900003700002004103541c00010332204450d002004200329036837001020042003290348370000200441086a200341c8006a41086a290300370000200441186a200341e8006a41086a29030037000020042008290000370020200441286a200841086a290000370000200441306a200841106a290000370000200441386a200841186a29000037000020081035200341e8006a200441c00010e002200329026c2105200328026821062004103502400240024002402006450d00200341e8006a20062005422088a72002108c062005a7210220032802684101460d03200341c8006a41186a220a200341e8006a410472220441186a280200360200200341c8006a41106a220b200441106a290200370300200341c8006a41086a2208200441086a2902003703002003200429020037034802402003280230450d00200328022c10350b200341206a41186a200a280200360200200341206a41106a200b290300370300200341206a41086a20082903003703002003200329034837032041f1d8cb00ad42808080809001841001220429000021052008200441086a290000370300200320053703482004103541a0e0c600ad4280808080b00184100122042900002105200341e8006a41086a200441086a2900003703002003200537036820041035412010332204450d0420042001290000370000200441186a220a200141186a290000370000200441106a220b200141106a290000370000200441086a220c200141086a290000370000412010332208450d0420082004290000370000200841186a200a290000370000200841106a200b290000370000200841086a200c2900003700002004103541c00010332204450d042004200329036837001020042003290348370000200441086a200341c8006a41086a290300370000200441186a200341e8006a41086a29030037000020042008290000370020200441286a200841086a290000370000200441306a200841106a290000370000200441386a200841186a290000370000200810352003410036027020034201370368200341206a200341e8006a10e201200341206a410472200341e8006a10e2012007200341e8006a10e20120032d0038210a200328026c20032802702208460d01200328026821010c020b2000418085c80036020420004101360200200041086a411a3602000c070b200841016a22012008490d042008410174220b2001200b20014b1b220b4100480d040240024020080d00410021080240200b0d00410121010c020b200b103322010d010c070b200328026821012008200b460d0020012008200b10372201450d060b2003200b36026c200320013602680b200120086a200a3a00002003200841016a360270200328022c210e200341346a2802002208200341e8006a107702400240200328026c220c2003280270220a6b2008490d0020032802682101200c210b0c010b200a20086a2201200a490d04200c410174220b2001200b20014b1b220b4100480d0402400240200c0d000240200b0d00410121010c020b200b10332201450d070c010b20032802682101200c200b460d002001200c200b10372201450d060b2003200b36026c200320013602680b2001200a6a200e2008109d081a2004ad4280808080800884200a20086aad4220862001ad8410020240200b450d00200110350b200410352002450d06200610350c060b2000200329026c370204200041013602002002450d04200610350c040b1045000b1044000b103e000b103c000b2003280230450d01200328022c10350c010b20002003290320370204200041003602002000411c6a200341386a280200360200200041146a20092903003702002000410c6a20072903003702000b200341b0016a24000bc00202027f017e230041106b220224002002200028023036020020012002410410780240412010332203450d0020032000290038370000200341186a200041d0006a290000370000200341106a200041c8006a290000370000200341086a200041c0006a290000370000200120034120107820031035024020002d0058220341024b0d00024002400240024020030e03000102000b200241003a00000c020b200241013a00000c010b200241023a00000b20012002410110780b200220002802343602002001200241041078200029030021042002200041086a290300370308200220043703002001200241101078200029031021042002200041186a290300370308200220043703002001200241101078200029032021042002200041286a290300370308200220043703002001200241101078200241106a24000f0b1045000b1300200041073602042000419c85c8003602000b3400200041fb8fc80036020420004100360200200041146a4102360200200041106a419090c800360200200041086a42133702000bcb0202057f037e2001280200210202400240412010332203450d0020032002290000370000200341186a2204200241186a290000370000200341106a2205200241106a290000370000200341086a2206200241086a290000370000412010332202450d0120022003290000370000200241186a2004290000370000200241106a2005290000370000200241086a200629000037000020031035200128020421012002412041c00010372203450d0120032001290000370020200341386a200141186a290000370000200341306a200141106a290000370000200341286a200141086a2900003700002003ad4280808080800884100922022900002107200241086a2900002108200241106a2900002109200041186a200241186a290000370000200041106a2009370000200041086a20083700002000200737000020021035200310350f0b1045000b103c000ba30301067f230041106b22032400024020014105744104722204417f4c0d000240200410332205450d002003410036020820032004360204200320053602002001200310770240024020010d002003280208210520032802042106200328020021070c010b20014105742108200328020021072003280204210620032802082105034020002101024002402006200522046b4120490d00200441206a21050c010b024002400240200441206a22052004490d00200641017422002005200020054b1b22004100480d000240024020060d00024020000d00410121070c020b2000103321070c040b20062000470d020b200021060c030b103e000b200720062000103721070b2000210620070d00103c000b200141206a2100200720046a22042001290000370000200441186a200141186a290000370000200441106a200141106a290000370000200441086a200141086a290000370000200841606a22080d000b2003200636020420032005360208200320073602000b20022902002005ad4220862007ad84100202402006450d00200710350b200341106a24000f0b1045000b1044000b130020004105360204200041fc92c8003602000be80f06087f017e047f017e057f077e230022042105200441a0016b41607122042400024002400240200141ffffff3f712001470d0020014105742206417f4c0d000240024020060d00410121070c010b200610332207450d020b41002108200441003602282004200736022020042006410576360224200441206a41002001108a012004280228210902402001450d002001410574210a200428022020094105746a210b0340200b20086a2206200020086a2207290000370000200641186a200741186a290000370000200641106a200741106a290000370000200641086a200741086a290000370000200a200841206a2208470d000b200141057441606a41057620096a41016a21090b200441086a200936020020042004290320220c370300200ca72009410041202009676b10c105200441206a41186a22014200370300200441206a41106a220d4200370300200441206a41086a220e42003703002004420037032041c7d5ca00ad4280808080b0028410012208290000210c200e200841086a2900003703002004200c370320200810354180eaca00ad428080808090018410012208290000210c200441e8006a41086a220f200841086a2900003703002004200c37036820081035200d2004290368220c37030020044180016a41086a200e29030037030020044180016a41106a200c37030020044180016a41186a200f2903003703002004200429032037038001200441206a20044180016a412010b50220042802202208410120081b21102004290224420020081b2211422088a72208450d022008410574210920044180016a410c722112200441206a410c6a2100200441206a4114722113200441206a41087221142010210803402001200841186a290000370300200d200841106a290000370300200e200841086a29000037030020042008290000370320200441106a200441206a108a07200441206a2004280210220b2004280218221510de02200f200041086a290200370300200441e8006a41106a220a200041106a2802003602002004200029020037036820042802402106024020042802282207450d002004290320210c20122004290368370200201241086a200f290300370200201241106a200a2802003602002004200c37038001200621160b200420073602880120044100360228200429039801211720042004290338221837039801200429039001211920042004290330221a37039001200429038001211b20042004290320221c37038001200429038801210c20042004290328221d37038801201da7210702400240200ca7220a0d00201d210c201a211920182117201621060c010b2004201b3703202004200c37032820042019370330200420173703382004200a2019a74105746a3602742004200a3602702004200c422088a736026c2004200a36026820042004360278200441d8006a200441e8006a10ca05201441086a200441d8006a41086a22162802003602002014200429035837020020042019422088a7220a2017422088a74105746a3602742004200a36027020042017a736026c2004200a36026820042004360278200441d8006a200441e8006a10ca05201341086a2016280200360200201320042903583702002004290328210c2004290320211c200429033821172004290330211902402007450d002018a7210a0240201d422088a741ffffff3f71450d00200710350b200a41ffffff3f71450d00201a422088a710350b2004201c370380012004200c3703880120042019370390012004201737039801200ca721070b2004200c37032820042019370330200120173703002004201c37032020042006360240200ca7210a0240024020070d002015ad422086200bad8410070c010b2004201536026c2004200b360268200441206a200441e8006a108b070b0240200a450d002017a721070240200c422088a741ffffff3f71450d00200a10350b200741ffffff3f71450d002019422088a710350b02402004280214450d00200b10350b200841206a210820062116200941606a22090d000c030b0b1044000b1045000b0240201142ffffff3f83500d00201010350b200441206a41186a220a4200370300200441206a41106a22074200370300200441206a41086a220642003703002004420037032041c7d5ca00ad4280808080b00284220c10012200290000211c200441e8006a41086a2208200041086a2900003703002004201c3703682000103520062008290300370300200420042903683703204189eaca00ad4280808080f0008410012200290000211c2008200041086a2900003703002004201c3703682000103520072004290368221c37030020044180016a41086a220b200629030037030020044180016a41106a2201201c37030020044180016a41186a22092008290300370300200420042903203703800120044120360224200420044180016a36022020022003200441206a10a806200a4200370300200742003703002006420037030020044200370320200c10012200290000210c2008200041086a2900003703002004200c370368200010352006200829030037030020042004290368370320419cdfca00ad4280808080d0008410012200290000210c2008200041086a2900003703002004200c3703682000103520072004290368220c370300200b20062903003703002001200c37030020092008290300370300200420042903203703800120044180016aad428080808080048410070240200428020441ffffff3f71450d00200428020010350b200524000bec0502057f017e23004190016b2201240020002d00002102200141186a2203200041196a290000370300200141106a2204200041116a290000370300200141086a2205200041096a2900003703002001200029000137030002400240024020020d00200141f0006a41186a4200370300200141f0006a41106a22034200370300200141f0006a41086a220042003703002001420037037041c7d5ca00ad4280808080b002841001220229000021062000200241086a2900003703002001200637037020021035419cdfca00ad4280808080d00084100122022900002106200141206a41086a2204200241086a2900003703002001200637032020021035200320012903202206370300200141c0006a41086a2000290300370300200141c0006a41106a2006370300200141c0006a41186a200429030037030020012001290370370340200141c0006aad428080808080048410070c010b200141206a41186a2003290300370300200141206a41106a2004290300370300200141206a41086a200529030037030020012001290300370320200141f0006a41186a4200370300200141f0006a41106a22034200370300200141f0006a41086a220042003703002001420037037041c7d5ca00ad4280808080b002841001220229000021062000200241086a2900003703002001200637037020021035419cdfca00ad4280808080d00084100122022900002106200141e0006a41086a2204200241086a2900003703002001200637036020021035200320012903602206370300200141c0006a41086a2000290300370300200141c0006a41106a2006370300200141c0006a41186a200429030037030020012001290370370340412010332200450d0120002001290320370000200041186a200141206a41186a290300370000200041106a200141206a41106a290300370000200041086a200141206a41086a290300370000200141c0006aad42808080808004842000ad42808080808004841002200010350b20014190016a24000f0b1045000bf61407157f017e017f017e017f017e017f230041306b220224000240024020014115490d00024002402001410176220341ffffff3f712003470d0020034105742204417f4c0d000240200410332205450d002002410036020820024204370300200041606a2106200041a07f6a210741042108410021094100210a2001210b0340200b210c4100210b4101210d0240200c417f6a220e450d000240024002400240024002402000200e4105746a200c410574220f20006a41406a412010a0084100480d004102200c6b210e2007200f6a21034101210d03400240200e200d6a4101470d004100210b200c210d0c080b200d41016a210d200341206a2003412010a0082110200341606a21032010417f4a0d000b200c200d6b210e0c010b2007200f6a2103024003400240200e4101470d004100210e0c020b200e417f6a210e200341206a2003412010a0082110200341606a210320104100480d000b0b200c200e490d01200c20014b0d02200c200e6b220d4101762211450d002006200f6a21032000200e4105746a21100340200241106a41186a220f201041186a2212290000370300200241106a41106a2213201041106a2214290000370300200241106a41086a2215201041086a221629000037030020022010290000370310200341086a220b2900002117200341106a22182900002119200341186a221a290000211b201020032900003700002012201b3700002014201937000020162017370000201a200f29030037000020182013290300370000200b201529030037000020032002290310370000200341606a2103201041206a21102011417f6a22110d000b0b0240200e0d00200e210b0c050b0240200d41094d0d00200e210b0c050b200c20014b0d02200c200e6b21112000200e4105746a210f0340200c200e417f6a220b490d040240200c200b6b220d4102490d002000200e4105746a22032000200b4105746a220e412010a008417f4a0d00200e2900002117200e2003290000370000200241106a41186a2215200e41186a2210290000370300200241106a41106a2216200e41106a2212290000370300200241106a41086a2218200e41086a22132900003703002013200341086a2900003700002012200341106a2900003700002010200341186a29000037000020022017370310410121140240200d4103490d00200e41c0006a200241106a412010a008417f4a0d0041022110200f210302400340200341186a200341386a290000370000200341106a200341306a290000370000200341086a200341286a2900003700002003200341206a221229000037000020112010460d01200341c0006a21132010211420122103201041016a21102013200241106a412010a008417f4a0d020c000b0b201021140b200e20144105746a22032002290310370000200341186a2015290300370000200341106a2016290300370000200341086a20182903003700000b200b450d05200f41606a210f201141016a2111200b210e200d410a4f0d050c000b0b200e200c41eccfca001059000b200c200141eccfca001058000b200c200e417f6a220b490d00200c200141fccfca001058000b200b200c41fccfca001059000b0240200a2002280204470d002002200a41011090012002280200210820022802082209210a0b2008200a4103746a2203200d3602042003200b3602002002200941016a22093602082009210a024020094102490d00034002400240024002400240200820092214417f6a22094103746a2203280200450d00201441037420086a221141746a280200220d200328020422104b0d010b20144103490d022003280204211020082014417d6a22034103746a280204210e0c010b4102210a0240201441024b0d0020142109200b450d090c060b20082014417d6a22034103746a280204220e2010200d6a4d0d004103210a0240201441034b0d0020142109200b450d090c060b201141646a280200200e200d6a4d0d00201421092014210a0c040b200e2010490d010b2014417e6a21030b02400240024002400240024002402014200341016a22184d0d00201420034d0d0120082003410374221a6a2203280204220a20032802006a220320082018410374221c6a22102802002216490d02200320014b0d03200020164105746a22132010280204221541057422106a210d2003410574210e200320166b220c20156b220320154f0d042005200d20034105742210109d08221220106a211120154101480d0520034101480d052006200e6a210e200d21030340200e200341606a220d201141606a220c200c200d412010a008410048220f1b2210290000370000200e41186a201041186a290000370000200e41106a201041106a290000370000200e41086a201041086a2900003700002011200c200f1b211102402013200d2003200f1b2203490d00201221100c080b200e41606a210e2012211020122011490d000c070b0b20182014418cd0ca001042000b20032014419cd0ca001042000b2016200341acd0ca001059000b2003200141acd0ca001058000b200520132010109d08221220106a2111024020154101480d00200c20154c0d002000200e6a210f201221102013210303402003200d2010200d2010412010a008410048220c1b220e290000370000200341186a200e41186a290000370000200341106a200e41106a290000370000200341086a200e41086a2900003700002010201041206a200c1b2110200341206a2103200d41206a200d200c1b220d200f4f0d03201120104b0d000c030b0b20132103201221100c010b200d2103201221100b20032010201120106b416071109d081a2008201a6a2203200a20156a360204200320163602002008201c6a2203200341086a20142018417f736a410374109e081a20022009360208200941014b0d000b2009210a200b450d040c010b200b450d030c000b0b1045000b1044000b0240200228020441ffffffff0171450d00200810350b2004450d01200510350c010b20014102490d002001417f6a2110200141057420006a41206a210f410121110340024002400240024020102203417f6a221020014b0d00200120106b220e4102490d03200020034105746a2203200020104105746a220c412010a008417f4a0d03200c2900002117200c2003290000370000200241106a41186a2213200c41186a220d290000370300200241106a41106a2214200c41106a2212290000370300200241106a41086a2208200c41086a22152900003703002015200341086a2900003700002012200341106a290000370000200d200341186a2900003700002002201737031041012103200e4103490d02200c41c0006a200241106a412010a008417f4a0d0241002112200f21030340200341406a220e200341606a220d290000370000200e41186a200d41186a290000370000200e41106a200d41106a290000370000200e41086a200d41086a29000037000020112012220e460d02200e417f6a21122003200241106a412010a008210d200341206a2103200d417f4a0d020c000b0b2010200141dccfca001059000b4102200e6b21030b200c20034105746a22032002290310370000200341186a2013290300370000200341106a2014290300370000200341086a20082903003700000b200f41606a210f2011417f6a211120100d000b0b200241306a24000bfc0701137f230041c0006b22042400200441003602082004420137030020044100360218200442013703102002410020031b21052000410020011b2106200241206a200220031b2107200041206a200020011b2108200020014105746a2109200220034105746a210a4101210b4101210c4100210d4101210e4101210f410021100340200b2111200e2112201021132007210320052102024002400340024020020d00410021052006450d020c030b02402006450d000240024020022006460d0020022006412010a00822140d010b2003200341206a2003200a4622021b210741002008200820094622141b21064100200320021b21052011210b2012210e201321102008200841206a20141b21080c050b02402014417f4c0d00200221050c040b200441206a41186a2214200241186a290000370300200441206a41106a2215200241106a290000370300200441206a41086a2216200241086a29000037030020042002290000370320024020132004280214470d00200441106a20134101108a01200428021821132004280210221121122011210f0b200f20134105746a22022004290320370000200241186a2014290300370000200241106a2015290300370000200241086a20162903003700002004201341016a2213360218410020032003200a4622141b21022003200341206a20141b21030c010b0b200441206a41186a2203200541186a290000370300200441206a41106a2213200541106a290000370300200441206a41086a2206200541086a29000037030020042005290000370320024020102004280214470d00200441106a20104101108a01200428021821102004280210220b210e0b200e20104105746a22022004290320370000200241186a2003290300370000200241106a2013290300370000200241086a20062903003700002004201041016a221036021841002106410020072007200a4622021b2105200e210f2007200741206a20021b21070c020b2004280204210220042802142103201120132000200110aa060240200341ffffff3f71450d00201110350b0240200241ffffff3f71450d00200c10350b200441c0006a24000f0b200441206a41186a2214200641186a290000370300200441206a41106a2215200641106a290000370300200441206a41086a2216200641086a290000370300200420062900003703200240200d2004280204470d002004200d4101108a012004280200210c2004280208210d0b200c200d4105746a22022004290320370000200241186a2014290300370000200241106a2015290300370000200241086a20162903003700002004200d41016a220d36020841002008200820094622021b21062011210b2012210e201321102008200841206a20021b2108200321070c000b0bee1604017f067e0e7f027e230041d0026b22032400200241c0006a2903002104200241306a2903002105200241286a2903002106200241106a2903002107200241086a29030021082002290338210920022d0000210a200341086a41186a200241e0006a290000370300200341086a41106a200241d8006a290000370300200341086a41086a200241d0006a29000037030020032002290048370308200341286a41086a200241206a290300370300200320022800013602382003200241046a28000036003b2003200241186a29030037032820012802002802002202280208220b410574210c2002280200210d024002400240200b0d0041032102200d210e0c010b200c210f200d210202400340200341a8016a200341086a2002220b10b20620032802a801220e20032802b00110e40241ff01712102024020032802ac01450d00200e10350b024020024103470d00200b41206a2102200f41606a220f450d020c010b0b200b41206a210e0c020b200b41206a210e410321020b0b4101211002400240024002400240024002400240200241ff0171417e6a220f41014b0d000240200f0e020200020b4100210f410421114100210b410021100c020b410021100b410810332211450d03200d200c6a210c2011200b360204201120023a000020034281808080103702840120032011360280014101210b034002400240200c200e2202470d002002210e4103210f0c010b200341a8016a200341086a200210b20620032802a801220e20032802b00110e40241ff0171210f024020032802ac01450d00200e10350b200241206a210e200f4103460d010b024002400240200f41ff0171220d4102470d00201041016a21100c010b200d4103460d010b0240200b200328028401470d0020034180016a200b410110900120032802800121110b2011200b4103746a220d2002360204200d200f3a00002003200b41016a220b360288010c010b0b200328028401210f200b450d002001280204200b417f6a10af062202200b4f0d04201120024103746a2d000022024103470d010b410121024100210d0c010b410241012002410246220d1b21020b200320023a003f2001280208210e200341c0026a200128020c360200200341bc026a200341c8026a36020020032011200b4103746a22023602b402200320113602b0022003200f3602ac02200320113602a80220032003413f6a3602b8022003200341b8026a220b3602a8010240034020112002460d012003201141086a3602b0022011280200220241ff01714103460d010240200b2002201128020410ce0622020d0020032802b402210220032802b00221110c010b0b20034180016a41086a2211200241086a29000037030020034180016a41106a220c200241106a29000037030020034180016a41186a2212200241186a2900003703002003200229000037038001200e41046a21130340200341a8016a41186a22142012290300370300200341a8016a41106a2215200c290300370300200341a8016a41086a2216201129030037030020032003290380013703a8010240200e41086a2217280200220f2013280200470d00200e200f4101108a010b200e280200200f4105746a220220032903a801370000200241186a2014290300370000200241106a2015290300370000200241086a20162903003700002017200f41016a3602002003200b3602a801034020032802b002220220032802b402460d022003200241086a3602b0022002280200220f41ff01714103460d02200b200f200228020410ce062202450d000b2011200241086a290000370300200c200241106a2900003703002012200241186a29000037030020032002290000370380010c000b0b024020032802ac0241ffffffff0171450d0020032802a80210350b02400240200d0d0020034180016a41086a200341286a41086a290300370300200320032802383602402003200328003b3600432003200329032837038001200341a8026a200341086a10cf0620033502b002211820032802a8022111411010332202450d0220022009370000200220043700082002411041201037210202400240200a41ff01714101460d002002450d06200241003a0010200320073703b001200320083703a801200341a8016a210e4111210b4120210f0c010b2002450d05200241013a001041c000210f2002412041c00010372202450d0520022008370018200220032802403600112002200329038001370028200241206a2007370000200241146a2003280043360000200241306a20034188016a2d00003a0000200320053703b001200320063703a801200341a8016a210e4131210b0b0240200f200b6b410f470d00200f200f410174220d200b41106a220c200d200c4b1b220d460d002002200f200d10372202450d050b2002200b6a220f200e290000370000200f41086a200e41086a29000037000020184220862011ad84200b41106aad4220862002ad84100220021035024020032802ac02450d00201110350b200341a8016a41086a41083a0000200341b1016a2003290308370000200341b9016a200341086a41086a290300370000200341c1016a200341086a41106a290300370000200341c9016a200341206a290300370000200341123a00a80141b0b4cc004100200341a8016a10d401200042003703000c010b20012802102202200228020020106a360200200128021422022002290300221820097c2219370300200241086a2202200229030020047c2019201854ad7c37030020012802002802002102200341a8016a41186a220f200341086a41186a290300370300200341a8016a41106a220e200341086a41106a290300370300200341a8016a41086a2211200341086a41086a290300370300200320032903083703a80102402002280208220b200241046a280200470d002002200b4101108a012002280208210b0b2002280200200b4105746a220b20032903a801370000200b41186a200f290300370000200b41106a200e290300370000200b41086a20112903003700002002200228020841016a360208200320032802383602502003200328003b360053200341c0006a41086a200341286a41086a290300370300200320032903283703402001280218280200210202400240200a41ff01714101470d00200341b7016a2007370000200341c7016a200341c8006a2d00003a0000200320083700af01200320032800533600ab01200320032802503602a801200320032903403700bf0120034180016a200341a8016a10d0060240200328028001220b200328028801220e10d10241ff0171220f4102460d00200ead422086200bad8410070b0240200328028401450d00200b10350b2009210720042108200f0d01200341a8016a2002200920062009200654220b200420055420042005511b220f1b20042005200f1b10b0064200200420057d200bad7d2207200920067d2205200956200720045620072004511b220b1b210842002005200b1b21070c010b200320083703a802200320073703b00202402008200784500d002003200341086a36027c20034180016a200341086a200341a8026a200341fc006a10f0022003290380014201520d002003290388012107200341e0016a20034180016a41106a290300370300200341d8016a2007370300200341a8016a41086a41003a0000200341b1016a2003290308370000200341b9016a200341086a41086a290300370000200341c1016a200341086a41106a290300370000200341c9016a200341206a290300370000200341033a00a80141b0b4cc004100200341a8016a10d4010b20092107200421080b200341086a20022007200810b006200041386a2004370300200041306a20093703002000410c6a2003290308370200200041146a200341106a2903003702002000411c6a200341186a290300370200200041246a200341206a29030037020020004201370300200020012802102802003602080b200341d0026a24000f0b1045000b2002200b419cb9c8001042000b103c000b992209027f017e027f017e2f7f017e1e7f077e017f0240200028028002220241c000490d00200041a0026a22032903002204a7210520004198026a22062903002207a721082004422088a721092007422088a7210a41e5f0c18b06210b41eec8819903210c41b2da88cb07210d41f4ca81d906210e410a21022006280200220f21102000419c026a28020022112112200328020022132114200041a4026a28020022152116200f211720112118201321192015211a200f211b2011211c2013211d2015211e20004194026a280200221f210320004190026a280200222021062000418c026a2802002221212220002802880222232124201f2125202021262021212720232128201f21292020212a2021212b2023212c201f212d2020212e2021212f20232130200041b0026a2903002204422088a7223121322004a722332134200041ac026a2802002235ad422086200041a8026a2802002236ad84223742037c2204422088a7223821392004a7223a213b2031213c2033213d203742027c2204422088a7223e213f2004a7224021412031214220332143203742017c2204422088a7224421452004a722462147203121482033214941f4ca81d906214a41b2da88cb07214b41eec8819903214c41e5f0c18b06214d41f4ca81d906214e41b2da88cb07214f41eec8819903215041e5f0c18b06215141f4ca81d906215241e5f0c18b06215341eec8819903215441b2da88cb0721550340200c20226a220cad422086200b20246a220bad842039ad422086203bad84852204a74110772239201b6a221bad2004422088a7411077223b201c6a221cad422086842022ad4220862024ad84852204a7410c772222200b6a2224ad2004422088a7410c77220b200c6a220cad422086842039ad203bad42208684852204a7410877223b201b6a221bad2004422088a74108772239201c6a221cad422086842022ad200bad42208684852204a74107772222200d20066a220bad200e20036a220dad422086842034ad2032ad42208684852207a7411077220e201d6a221dad2007422088a74110772232201e6a221ead422086842006ad2003ad42208684852207422088a7410c772203200d6a22066a2234ad4220862007a7410c77220d200b6a220bad2006ad42208684200ead2032ad42208684852207a74108772206201d6a221dad2007422088a74108772232201e6a221ead42208684200dad2003ad42208684852207422088a74107772203200b6a220bad842039ad2006ad42208684852256a74110772206201b6a221bad2056422088a74110772239201c6a221cad422086842022ad4220862003ad84852256a7410c772203200b6a220dad2056422088a7410c77222220346a220ead422086842006ad2039ad42208684852256a74108772239201b6a221bad2056422088a74108772234201c6a221cad422086842003ad2022ad42208684852256a741077721032004422088a7410777220620246a2222ad2007a74107772224200c6a220cad42208684203bad4220862032ad84852204a74110772232201d6a221dad2004422088a7411077223b201e6a221ead422086842006ad2024ad42208684852204a7410c77220620226a220bad2004422088a7410c772222200c6a220cad422086842032ad203bad42208684852204a74108772232201d6a221dad2004422088a7410877223b201e6a221ead422086842006ad2022ad42208684852204a74107772122204c20276a2206ad422086204d20286a2224ad84203fad4220862041ad84852207a7411077223f20176a2217ad2007422088a7411077224120186a2218ad422086842027ad4220862028ad84852207a7410c77222720246a2224ad2007422088a7410c77222820066a2206ad42208684203fad2041ad42208684852207a7410877224120176a2217ad2007422088a7410877223f20186a2218ad422086842027ad2028ad42208684852207a74107772227204b20266a2228ad204a20256a224aad42208684203dad203cad42208684852257a7411077223c20196a2219ad2057422088a7411077223d201a6a221aad422086842026ad2025ad42208684852257422088a7410c772225204a6a22266a224aad4220862057a7410c77224b20286a2228ad2026ad42208684203cad203dad42208684852257a7410877222620196a2219ad2057422088a7410877223c201a6a221aad42208684204bad2025ad42208684852257422088a7410777222520286a2228ad84203fad2026ad42208684852258a7411077222620176a2217ad2058422088a7411077223d20186a2218ad422086842027ad4220862025ad84852258a7410c77222520286a224bad2058422088a7410c772227204a6a224aad422086842026ad203dad42208684852258a7410877223f20176a2217ad2058422088a7410877223d20186a2218ad422086842025ad2027ad42208684852258a741077721252007422088a7410777222620246a2224ad2057a7410777222720066a2206ad422086842041ad422086203cad84852207a7411077222820196a2219ad2007422088a7411077223c201a6a221aad422086842026ad2027ad42208684852207a7410c77222620246a224dad2007422088a7410c77222420066a224cad422086842028ad203cad42208684852207a7410877223c20196a2219ad2007422088a74108772241201a6a221aad422086842026ad2024ad42208684852207a741077721272050202b6a2206ad4220862051202c6a2224ad842045ad4220862047ad84852257a7411077222620106a2228ad2057422088a7411077221020126a2212ad42208684202bad422086202cad84852257a7410c77222b20246a2224ad2057422088a7410c77222c20066a2206ad422086842026ad2010ad42208684852257a7410877222620286a2228ad2057422088a7410877221020126a2212ad42208684202bad202cad42208684852257a7410777222b204f202a6a222cad204e20296a2245ad422086842043ad2042ad42208684852259a7411077224220146a2214ad2059422088a7411077224320166a2216ad42208684202aad2029ad42208684852259422088a7410c77222920456a222a6a2245ad4220862059a7410c772247202c6a222cad202aad422086842042ad2043ad42208684852259a7410877222a20146a2214ad2059422088a7410877224220166a2216ad422086842047ad2029ad42208684852259422088a74107772229202c6a222cad842010ad202aad4220868485225aa7411077222a20286a2228ad205a422088a7411077221020126a2212ad42208684202bad4220862029ad8485225aa7410c772229202c6a224fad205a422088a7410c77222b20456a224ead42208684202aad2010ad4220868485225aa7410877224520286a2210ad205a422088a7410877224320126a2212ad422086842029ad202bad4220868485225aa741077721292057422088a7410777222820246a2224ad2059a7410777222a20066a2206ad422086842026ad4220862042ad84852257a7411077222620146a222bad2057422088a7411077222c20166a2216ad422086842028ad202aad42208684852257a7410c77222820246a2251ad2057422088a7410c77222420066a2250ad422086842026ad202cad42208684852257a74108772242202b6a2214ad2057422088a7410877224720166a2216ad422086842028ad2024ad42208684852257a7410777212b205320306a2206ad2054202f6a2224ad422086842035ad4220862036ad84852259a7411077222620086a2228ad2059422088a7411077222a200a6a222cad42208684202fad4220862030ad84852259a7410c77222f20066a2206ad2059422088a7410c77223020246a2224ad422086842026ad202aad42208684852259a7410877222620286a2228ad2059422088a7410877222a202c6a222cad42208684202fad2030ad42208684852259a7410777222f2052202d6a2230ad4220862055202e6a2208ad842049ad2048ad4220868485225ba7411077220a20056a2205ad205b422088a7411077223520096a2209ad42208684202ead202dad4220868485225b422088a7410c77222d20306a222e6a2230ad422086205ba7410c77223620086a2208ad202ead42208684200aad2035ad4220868485225ba7410877222e20056a2205ad205b422088a7410877224820096a2209ad422086842036ad202dad4220868485225b422088a7410777222d20086a2208ad84202aad202ead4220868485225ca7411077222a20286a2228ad205c422088a7411077222e202c6a222cad42208684202fad422086202dad8485225ca7410c77222d20086a2255ad205c422088a7410c77222f20306a2252ad42208684202aad202ead4220868485225ca7410877223520286a2208ad205c422088a74108772249202c6a220aad42208684202dad202fad4220868485225ca7410777212d2059422088a7410777222820066a2206ad205ba7410777222a20246a2224ad422086842026ad4220862048ad84852259a7411077222620056a222cad2059422088a7411077222e20096a222fad422086842028ad202aad42208684852259a7410c77222820066a2253ad2059422088a7410c77220620246a2254ad422086842026ad202ead42208684852259a74108772248202c6a2205ad2059422088a74108772236202f6a2209ad422086842028ad2006ad42208684852259a7410777212f2056422088a741077721242004422088a741077721062058422088a741077721282007422088a74107772126205a422088a7410777212c2057422088a7410777212a205c422088a741077721302059422088a7410777212e2002417f6a22020d000b41002102200041003602800220002802a802215d2000203742047c22043e02a8022000203220316a3602fc012000203420336a3602f8012000203920386a3602f4012000203b203a6a3602f0012000201e20156a3602ec012000201d20136a3602e8012000201c20116a3602e4012000201b200f6a3602e00120002003201f6a3602dc012000200620206a3602d8012000202220216a3602d4012000202420236a3602d0012000200e41f4ca81d9066a3602cc012000200d41b2da88cb076a3602c8012000200c41eec88199036a3602c4012000200b41e5f0c18b066a3602c0012000203c20316a3602bc012000203d20336a3602b8012000203f203e6a3602b4012000204120406a3602b0012000201a20156a3602ac012000201920136a3602a8012000201820116a3602a40120002017200f6a3602a00120002025201f6a36029c012000202620206a360298012000202720216a360294012000202820236a360290012000204a41f4ca81d9066a36028c012000204b41b2da88cb076a360288012000204c41eec88199036a360284012000204d41e5f0c18b066a360280012000204220316a36027c2000204320336a3602782000204520446a3602742000204720466a3602702000201620156a36026c2000201420136a3602682000201220116a36026420002010200f6a36026020002029201f6a36025c2000202a20206a3602582000202b20216a3602542000202c20236a3602502000204e41f4ca81d9066a36024c2000204f41b2da88cb076a3602482000205041eec88199036a3602442000205141e5f0c18b066a3602402000200920156a36022c2000200520136a3602282000200a20116a36022420002008200f6a3602202000202d201f6a36021c2000202e20206a3602182000202f20216a3602142000203020236a3602102000205241f4ca81d9066a36020c2000205541b2da88cb076a3602082000205441eec88199036a3602042000205341e5f0c18b066a36020020002802ac022103200020044220883e02ac02200020002802b40220486a36023c200020002802b00220496a3602382000200320356a3602342000205d20366a3602300b200020024102746a28020021032000200241016a360280020240200141016a220620014f0d004180bcc800413941bcbcc800103f000b20032006700bfb0303057f017e047f230041306b220424000240024002402002200384500d002004200010b806200441206a200428020022052004280208220610b402024002400240024002400240200428022022070d00410021002004410036021820044208370310410021080c010b200420042902242209370214200420073602102009a7210a410021000240024002402009422088a7220841014b0d0020080e020201020b2008210b03402000200b410176220c20006a220d2007200d41186c6a28020020014b1b2100200b200c6b220b41014b0d000b0b2007200041186c6a280200220b2001460d032000200b2001496a220020084b0d070b2008200a470d010b200441106a20084101109c012004280214210a200428021021070b2007200041186c6a220b41186a200b200820006b41186c109e081a200b41106a2003370300200b2002370308200b20013602002004200841016a220836021820070d012006ad4220862005ad8410070c020b200020084f0d042007200041186c6a22002000290308220920027c2202370308200041106a2200200029030020037c2002200954ad7c3703000b200420063602242004200536022020072008200441206a109603200a450d00200a41186c450d00200710350b2004280204450d00200510350b200441306a24000f0b20002008104d000b2000200841e0bbc8001042000be30202047f017e230041206b2203240002400240200241e8006c4104722204417f4c0d00200410332205450d0120034100360208200320043602042003200536020020022003107702402002450d00200241e8006c21064100210403402003200120046a220241c8006a412010780240024020022d00004101460d00200341003a00102003200341106a41011078200241086a29030021072003200241106a29030037031820032007370310200341106a21050c010b200341013a00102003200341106a410110782003200241016a41201078200241286a29030021072003200241306a29030037031820032007370310200341106a21050b2003200541101078200241386a29030021072003200241c0006a290300370318200320073703102003200341106a411010782006200441e8006a2204470d000b0b20002003290300370200200041086a200341086a280200360200200341206a24000f0b1044000b1045000bdc0703027f017e067f230041e0006b2203240041a29bc800ad4280808080f00084100122042900002105200341086a41086a200441086a290000370300200320053703082004103541b39bc800ad4280808080d00084100122042900002105200341186a41086a200441086a29000037030020032005370318200410350240024002400240412010332204450d0020042001290000370000200441186a200141186a290000370000200441106a200141106a290000370000200441086a200141086a29000037000020032004ad42808080808004841003220129000037034820011035200341dc006a2201200441206a360200200320043602582003200341c8006a41086a22063602542003200341c8006a360250200341286a200341d0006a107b20041035412010332204450d0020042002290000370000200441186a200241186a290000370000200441106a200241106a290000370000200441086a200241086a29000037000020032004ad428080808080048410032202290000370348200210352001200441206a36020020032004360258200320063602542003200341c8006a360250200341386a200341d0006a107b200410352003280230220741206a2206200328024022086a2201417f4c0d01200328023821092003280228210a0240024020010d004100210b410121040c010b200110332204450d012001210b0b02400240200b410f4d0d00200b21020c010b200b41017422024110200241104b1b22024100480d030240200b0d002002103322040d010c050b200b2002460d002004200b200210372204450d040b20042003290308370000200441086a200341086a41086a2903003700000240024020024170714110460d002002210b0c010b2002410174220b4120200b41204b1b220b4100480d032002200b460d0020042002200b10372204450d040b20042003290318370010200441186a200341186a41086a29030037000002400240200b41606a2007490d00200b21020c010b2007415f4b0d03200b41017422022006200220064b1b22024100480d03200b2002460d002004200b200210372204450d040b200441206a200a2007109d081a02400240200220066b2008490d002002210b0c010b20012006490d032002410174220b2001200b20014b1b220b4100480d03024020020d000240200b0d00410121040c020b200b10332204450d050c010b2002200b460d0020042002200b10372204450d040b200420066a20092008109d081a200020013602082000200b360204200020043602000240200328023c450d00200910350b0240200328022c450d00200a10350b200341e0006a24000f0b1045000b1044000b103e000b103c000bb10503027f017e047f230041d0006b2202240041a29bc800ad4280808080f00084100122032900002104200241086a41086a200341086a290000370300200220043703082003103541d4bac800ad4280808080d00184100122032900002104200241186a41086a200341086a29000037030020022004370318200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad42808080808004841003220129000037033820011035200241cc006a200341206a360200200220033602482002200241386a41086a3602442002200241386a360240200241286a200241c0006a107b200310352002280230220541206a2201417f4c0d01200228022821060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a2000200136020820002008360204200020033602000240200228022c450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000b8c1004057f017e047f017e230041f0016b22012400200141d0006a41186a22024200370300200141d0006a41106a22034200370300200141d0006a41086a220442003703002001420037035041a29bc800ad4280808080f00084100122052900002106200141f0006a41086a2207200541086a2900003703002001200637037020051035200420072903003703002001200129037037035041f69bc800ad4280808080c000841001220529000021062007200541086a2900003703002001200637037020051035200320012903702206370300200141306a41086a2004290300370300200141306a41106a2006370300200141306a41186a200729030037030020012001290350370330200141f0006a200141306a412010d50120012d007021052002200141f0006a41196a2900003703002003200141f0006a41116a2900003703002004200141f0006a41096a29000037030020012001290071370350410121070240024020054101460d0041002107200141003a00080c010b200141086a41096a2004290300370000200141086a41116a2003290300370000200141086a41196a2002290300370000200141013a0008200120012903503700090b20014189016a200041186a29000037000020014181016a200041106a290000370000200141f9006a200041086a29000037000020012000290000370071200141013a00700240024002402007450d00200141086a410172200141f0006a410172412010a008450d010b200141d0006a41186a22054200370300200141d0006a41106a22024200370300200141d0006a41086a220442003703002001420037035041a29bc800ad4280808080f00084100122082900002106200141f0006a41086a2207200841086a2900003703002001200637037020081035200420072903003703002001200129037037035041ef9bc800ad4280808080f000841001220829000021062007200841086a290000370300200120063703702008103520032001290370370000200341086a2007290300370000200141306a41086a2004290300370300200141306a41106a2002290300370300200141306a41186a200529030037030020012001290350370330200141f0006a200141306a412010d50120012d007021082005200141f0006a41196a2900003703002002200141f0006a41116a2900003703002004200141f0006a41096a29000037030020012001290071370350410121070240024020084101460d0041002107200141003a00080c010b200141086a41096a2004290300370000200141086a41116a2002290300370000200141086a41196a2005290300370000200141013a0008200120012903503700090b20014189016a200041186a29000037000020014181016a200041106a290000370000200141f9006a200041086a29000037000020012000290000370071200141013a007002402007450d00200141086a410172200141f0006a410172412010a008450d010b200141f0006a41186a4200370300200141f0006a41106a22054200370300200141f0006a41086a220442003703002001420037037041a29bc800ad4280808080f000841001220729000021062004200741086a29000037030020012006370370200710354189eaca00ad4280808080f00084100122072900002106200141d0006a41086a2202200741086a2900003703002001200637035020071035200520012903502206370300200141086a41086a2004290300370300200141086a41106a2006370300200141086a41186a200229030037030020012001290370370308200141f0006a200141086a10fe0120012802702207410120071b21084100210402400240024002402001290274420020071b2206422088a7220941014b0d0020090e020201020b2009210703402007410176220520046a22022004200820024105746a2000412010a0084101481b2104200720056b220741014b0d000b0b200820044105746a2000412010a008450d010b200642ffffff3f83500d01200810350c010b200420094f0d01200820044105746a2207200741206a2004417f7320096a410574109e081a200141d0006a41186a22024200370300200141d0006a41106a220a4200370300200141d0006a41086a220742003703002001420037035041a29bc800ad4280808080f0008410012205290000210b200141f0006a41086a2204200541086a2900003703002001200b3703702005103520072004290300370300200120012903703703504189eaca00ad4280808080f0008410012205290000210b2004200541086a2900003703002001200b3703702005103520032001290370370000200341086a2004290300370000200141306a41086a2007290300370300200141306a41106a200a290300370300200141306a41186a200229030037030020012001290350370330200141203602742001200141306a36027020082009417f6a200141f0006a1098020240200642ffffff3f83500d00200810350b200141f0006a200010b9062001280270210420013502782106200141013a000820064220862004ad84200141086aad42808080801084100202402001280274450d00200410350b200141f0006a200010ba06200135027842208620012802702204ad84100702402001280274450d00200410350b200141f0006a41086a41093a0000200141f0006a41096a200029000037000020014181016a200041086a29000037000020014189016a200041106a29000037000020014191016a200041186a290000370000200141123a007041b0b4cc004100200141f0006a10d4010b200141f0016a24000f0b20042009104e000bfc0403027f017e057f230041d0006b220224004186f0cb00ad4280808080800184100122032900002104200241086a41086a200341086a29000037030020022004370308200310354180eaca00ad4280808080900184100122032900002104200241186a41086a200341086a2900003703002002200437031820031035200220013602342002200241346aad4280808080c000841003220329000037033820031035200241cc006a200241386a3602002002200241386a41086a3602442002200241346a3602482002200241386a360240200241286a200241c0006a107b02400240024002402002280230220541206a2206417f4c0d00200228022821070240024020060d0041002101410121030c010b200610332203450d02200621010b024002402001410f4d0d00200121080c010b200141017422084110200841104b1b22084100480d03024020010d002008103322030d010c050b20012008460d0020032001200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821010c010b200841017422014120200141204b1b22014100480d0320082001460d0020032008200110372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200141606a2005490d00200121080c010b200541206a22082005490d03200141017422092008200920084b1b22084100480d0320012008460d0020032001200810372203450d040b200341206a20072005109d081a2000200636020820002008360204200020033602000240200228022c450d00200710350b200241d0006a24000f0b1044000b1045000b103e000b103c000bf21201277f230041f0046b220324000240024002402001280200220420012802044f0d00200341d7036a210520034184026a21062003418c046a2107200341d0036a4101722108200341b1046a220941036a210a03402001200441016a360200200341c0026a200410f504200341d0036a20032802c002220b20032802c80210b302200341b8046a41086a220c200841086a290000370300200341b8046a41106a220d200841106a290000370300200341b8046a41186a220e200841186a290000370300200341b8046a41206a220f200841206a290000370300200341b8046a41286a2210200841286a290000370300200341b8046a412f6a22112008412f6a290000370000200341e8026a41086a2212200741086a290000370300200341e8026a41106a2213200741106a290000370300200341e8026a41186a2214200741186a290000370300200341e8026a41206a2215200741206a280000360200200320082900003703b804200320072900003703e802200328028804211620032d00d0032117200320092800003602d8012003200a2800003600db010240201741024622180d0020032d00b004211920034180026a412f6a201129000037000020034180026a41286a201029030037030020034180026a41206a200f29030037030020034180026a41186a200e29030037030020034180026a41106a200d29030037030020034180026a41086a200c290300370300200341a8036a41086a2012290300370300200341a8036a41106a2013290300370300200341a8036a41186a2014290300370300200341a8036a41206a2015280200360200200320032903b80437038002200320032903e8023703a803200320032800db013600a303200320032802d8013602a0032016211a0b024020032802c402450d00200b10350b200c20034180026a41086a221b290300370300200d20034180026a41106a221c290300370300200e20034180026a41186a221d290300370300200f20034180026a41206a221e290300370300201020034180026a41286a221f290300370300201120034180026a412f6a290000370000200341d8016a41086a2220200341a8036a41086a220b290300370300200341d8016a41106a2221200341a8036a41106a2216290300370300200341d8016a41186a2222200341a8036a41186a2223290300370300200341d8016a41206a2224200341a8036a41206a222528020036020020032003290380023703b804200320032903a8033703d801200320032800a3033600d301200320032802a0033602d001200341d0036a41086a2226200c290300370300200341d0036a41106a2227200d290300370300200341d0036a41186a220d200e290300370300200341d0036a41206a220e200f290300370300200341d0036a41286a220f2010290300370300200341d0036a412f6a2011290000370000200320032903b8043703d003200b2020290300370300201620212903003703002023202229030037030020252024280200360200200320032903d8013703a803200320032800d3013600a303200320032802d0013602a00302400240024020180d002017410171450d010b4103210c0c010b20062005290000370000200641286a200541286a290000370000200641206a200541206a290000370000200641186a200541186a290000370000200641106a200541106a290000370000200641086a200541086a290000370000200341c0026a41086a2210200b290300370300200341c0026a41106a22112016290300370300200341c0026a41186a22172023290300370300200341c0026a41206a220b2025280200360200200320032903a8033703c0022012201b2902003703002013201c2902003703002014201d2902003703002015201e290200370300200341e8026a41286a2216201f290200370300200341e8026a41306a222320034180026a41306a280200360200200320032800a3033600bb02200320032802a0033602b80220032003290280023703e8024103210c201941ff01714103460d002026201229030037030020272013290300370300200d2014290300370300200e2015290300370300200f2016290300370300200341d0036a41306a22162023280200360200201b2010290300370300201c2011290300370300201d2017290300370300201e200b280200360200200320032903e8023703d003200320032903c00237038002200320032800bb023600ab03200320032802b8023602a8034103210c201a2002280200280200470d0020034198016a41306a201628020036020020034198016a41286a200f29030037030020034198016a41206a200e29030037030020034198016a41186a200d29030037030020034198016a41106a202729030037030020034198016a41086a2026290300370300200341f0006a41086a201b290300370300200341f0006a41106a201c290300370300200341f0006a41186a201d290300370300200341f0006a41206a201e280200360200200320032903d003370398012003200329038002370370200320032800ab0336006b200320032802a80336026820042128201a21292019210c0b200c41ff01714103470d02200128020022042001280204490d000b0b200041033a00600c010b200341306a41306a220820034198016a41306a280200360200200341306a41286a220720034198016a41286a290300370300200341306a41206a220d20034198016a41206a290300370300200341306a41186a220e20034198016a41186a290300370300200341306a41106a220f20034198016a41106a290300370300200341306a41086a221020034198016a41086a290300370300200341086a41086a2211200341f0006a41086a290300370300200341086a41106a2201200341f0006a41106a290300370300200341086a41186a2204200341f0006a41186a290300370300200341086a41206a2205200341f0006a41206a2802003602002003200329039801370330200320032903703703082003200328006b3600032003200328026836020020002028360200200020032903303702042000410c6a2010290300370200200041146a200f2903003702002000411c6a200e290300370200200041246a200d2903003702002000412c6a2007290300370200200041346a2008280200360200200020293602382000200329030837023c200041c4006a2011290300370200200041cc006a2001290300370200200041d4006a2004290300370200200041dc006a20052802003602002000200c3a0060200041e4006a2003280003360000200020032802003600610b200341f0046a24000b81fc010d017f017e037f017e017f017e027f017e057f017e067f067e0b7f230041f00b6b2201240010ff0342d0a1f10221020240024002400240024002400240024020004101460d00200141c8056a41186a22034200370300200141c8056a41106a22044200370300200141c8056a41086a22054200370300200142003703c80541a9d1cb00ad4280808080c0008422061001220729000021082005200741086a290000370300200120083703c8052007103541cdd1cb00ad4280808080b0018410012207290000210820014198076a41086a2209200741086a29000037030020012008370398072007103520042001290398072208370300200141a8056a41086a2005290300370300200141a8056a41106a2008370300200141a8056a41186a2009290300370300200120012903c8053703a80520014188056a200141a8056a10e1022001290390052108200128028805210a200342003703002004420037030020054200370300200142003703c805200610012207290000210b2005200741086a2900003703002001200b3703c8052007103541add1cb00ad4280808080a001841001220c290000210b200141e8056a41086a2207200c41086a2900003703002001200b3703e805200c1035200420012903e805220b370300200141a0096a41086a220c2005290300370300200141a0096a41106a220d200b370300200141a0096a41186a220e2007290300370300200120012903c8053703a009200141f8046a200141a0096a10e10220012802f804210f200129038005210b200342003703002004420037030020054200370300200142003703c80520061001220329000021062005200341086a290000370300200120063703c8052003103541c2d1cb00ad4280808080b001841001220329000021062007200341086a290000370300200120063703e80520031035200420012903e8052206370300200c2005290300370300200d2006370300200e2007290300370300200120012903c8053703a009200141e8046a200141a0096a10e102420020084200200a1b220620012903f004420020012802e8041b200b42c8017e4200200f1b7c7d220820082006561b42c801540d00200141a00a6a41186a220a4200370300200141a00a6a41106a22104200370300200141a00a6a41086a22074200370300200142003703a00a41a3edcb00ad4280808080f000842211100122032900002102200141f8056a41086a2205200341086a290000370300200120023703f8052003103520072005290300370300200120012903f8053703a00a41a5ebcb00ad4280808080c001841001220329000021022005200341086a290000370300200120023703f80520031035201020012903f8052202370300200c2007290300370300200d2002370300200e2005290300370300200120012903a00a3703a009200141e0046a200141a0096a412010c00120012802e404210f20012802e0042112200a42003703002010420037030020074200370300200142003703a00a20111001220329000021022005200341086a290000370300200120023703f8052003103520072005290300370300200120012903f8053703a00a41b1ebcb00ad4280808080d001841001220329000021022005200341086a290000370300200120023703f80520031035201020012903f8052202370300200c2007290300370300200d2002370300200e2005290300370300200120012903a00a3703a009200141a0096a10bd02210310c00420014198076a41186a420037030020014198076a41106a2213420037030020094200370300200142003703980741f7edcb00ad4280808080f000841001220729000021022009200741086a29000037030020012002370398072007103541eeedcb00ad4280808080900184100122072900002102200c200741086a290000370300200120023703a00920071035201320012903a009220237030020052009290300370300200141f8056a41106a2002370300200141f8056a41186a200c29030037030020012001290398073703f8054100210c200f410020121b210f200141a00a6a200141f8056a10ac01024020012903a00a22024202510d0020012903a80a2106200141a00a6a2010280200220d41016a10b801200141d8046a20012802a00a220720012802a80a10c00120012802dc04210920012802d8042105024020012802a40a450d00200710350b20054101470d002009200f41016a470d0020024201520d00200141c8056a41186a22074200370300200141c8056a41106a22094200370300200141c8056a41086a22054200370300200142003703c80541d1efcb00ad42808080809001841001220e29000021022005200e41086a290000370300200120023703c805200e103541ebc3c400ad428080808030841001220a2900002102200141f8056a41086a220e200a41086a290000370300200120023703f805200a1035200420012903f805370000200441086a2212200e290300370000200141a8056a41086a22142005290300370300200141a8056a41106a22152009290300370300200141a8056a41186a22162007290300370300200120012903c8053703a805200141c8046a200141a8056a10e102200141a0046a20012903d004420020012802c8041b220242e807802208420042e8074200108408200141a00a6a200d10bd01200141b0046a20012802a00a221720012802a80a10d70120012903a004220b200220084298787e7c42ff07837c2202427f200141a0046a41086a2903002002200b54ad7c501b20067d2118200141b0046a41106a290300420020012802b004220a1b210220012903b8044200200a1b210b024020012802a40a450d00201710350b200742003703002009420037030020054200370300200142003703c80541b6fdc600ad42808080808001841001220a29000021062005200a41086a290000370300200120063703c805200a103541e489c200ad4280808080d001841001220a2900002106200e200a41086a290000370300200120063703f805200a1035200420012903f8053700002012200e290300370000201420052903003703002015200929030037030020162007290300370300200120012903c8053703a80520014188046a200141a8056a412010d701200141f8036a200129039004420020012802880422051b220620014188046a41106a290300420020051b2208428094ebdc034200109808200141e8036a20012903f8032219200141f8036a41086a290300221a4280ec94a37c427f10840820082002200b200656200220085620022008511b22051b21022006200b20051b210b20012903e80320067c211b2018428086ebc7f5002018428086ebc7f500541b42058842ffffffff0f83428094ebdc037e4298ac9fd60380211c4100210741d87d2105024002400340200141d8036a2019201a200541ece4c6006a350200220642001084082007200b20012903d80322082006201b7e2206428094ebdc03802218a7417f2006428080808080c0b2cd3b541b200620184280ec94a37c7e7c4280cab5ee01566aad7c22065a2002200141d8036a41086a2903002006200854ad7c22085a200220085122091b6a2107200b200654200220085420091b0d01200541086a22050d000b200141c8036a2019201a42e8aafa0b4200108408200141d0036a29030020012903c8032206201b42e8aafa0b7e2202428094ebdc03802208a7417f2002428080808080c0b2cd3b541b200220084280ec94a37c7e7c4280cab5ee01566aad7c2202200654ad7c21060c010b02402007417f6a220520074d0d00200141c8026a2019201a42c0f0f50b4200108408200141d0026a29030020012903c8022206201b4228802202a7417f201b42c0f0f50b7e2208428080808080c0b2cd3b541b200820024280ec94a37c7e7c4280cab5ee01566aad7c2202200654ad7c21060c010b02400240200541244b0d00200141b8036a2019201a2005410374220941c4e2c6006a280200220ead2206420010840820014198036a200b20012903b80322082006201b7e2206428094ebdc03802218a7417f2006428080808080c0b2cd3b541b200620184280ec94a37c7e7c4280cab5ee01566aad7c2206200b2006562002200141b8036a41086a2903002006200854ad7c22085620022008511b22051b22182006200b20051b22067d220b2002200820051b2008200220051b7d2018200654ad7d41002007410374220a41c4e2c6006a2802002207200e6b220e200e20074b1b22074101200741014b1bad2202420010980820014188036a200129039803220620014198036a41086a290300221820024200108408200141a8036a2019201a200941c8e2c6006a2802002207ad221d4200108408200141d8026a20184200200a41c8e2c6006a28020022092007200920074b220e1b20072009200e1b6bad22084200108408200141f8026a2006420020084200108408200141e8026a4200420020064200108408427f427f200141f8026a41086a290300220620012903d80220012903e8027c7c221820012903e00220012903f00284420052201820065472220e1b2218427f20012903f802200e1b2206200b2001290388037d20087e2002807c2202200654220ead7c2208200e2008201854200220065a1b220e1b210b427f2002200e1b2108200141a8036a41086a29030020012903a8032218201d201b7e2202428094ebdc03802206a7417f2002428080808080c0b2cd3b541b200220064280ec94a37c7e7c4280cab5ee01566aad7c2206201854ad7c2102200920074d2005730d0142002002200b7d2006200854ad7d220b200620087d2208200656200b200256200b2002511b22051b21064200200820051b21020c020b2005412541e4b8ca001042000b427f2002200b7c200620087c22082006542205ad7c22062005200620025420062002511b22051b2106427f200820051b21020b20014188026a2019201a4280c2d72f4200108408200141b8026a20022006428094ebdc034200109808200141f8016a2001290388022208201b420a802206a7417f201b4280c2d72f7e220b428080808080c0b2cd3b541b200b20064280ec94a37c7e7c4280cab5ee01566aad7c220620014188026a41086a2903002006200854ad7c428094ebdc034200109808200141a8026a20012903b8022208200141b8026a41086a290300220b4280ec94a37c427f10840820014198026a2008200b201c4200108408200141e8016a20012903f8012208200141f8016a41086a290300220b4280ec94a37c427f108408200141d8016a2008200b201c4200108408200141ac0a6a200d360200200141a00a6a41086a41003a0000200141b00a6a2001290398022208201c200220012903a8027c7e2202428094ebdc0380220ba7417f2002428080808080c0b2cd3b541b2002200b4280ec94a37c7e7c4280cab5ee01566aad7c2202370300200141b80a6a20014198026a41086a2903002002200854ad7c220b370300200141c80a6a4200200141d8016a41086a29030020012903d8012208201c200620012903e8017c7e2206428094ebdc03802218a7417f2006428080808080c0b2cd3b541b200620184280ec94a37c7e7c4280cab5ee01566aad7c2206200854ad7c2208200b7d2006200254ad7d2218200620027d221b200656201820085620182008511b22051b2206370300200141c00a6a4200201b20051b2208370300200141043a00a00a41b0b4cc004100200141a00a6a10d401200141f8056a200d10be0120012802f805210520013502800621182001200b3703a80a200120023703a00a20184220862005ad84200141a00a6aad220b42808080808002841002024020012802fc05450d00200510350b02400240024020082006844200520d002001420037038006200142003703f805200141a0096aad428080808080048421180c010b200141c8056a41186a22074200370300200141c8056a41106a22094200370300200141c8056a41086a22054200370300200142003703c80541b6fdc600ad428080808080018422021001220e290000211820014198076a41086a220d200e41086a2900003703002001201837039807200e10352005200d29030037030020012001290398073703c80541e489c200ad4280808080d0018422181001220a290000211b200141e8056a41086a220e200a41086a2900003703002001201b3703e805200a1035200420012903e805370000200441086a2214200e290300370000200141a0096a41086a22152005290300370300200141a0096a41106a22162009290300370300200141a0096a41186a22172007290300370300200120012903c8053703a009200141c0016a200141a0096a412010d701200141c0016a41106a290300211b20012903c801211920012802c001210a200742003703002009420037030020054200370300200142003703c8052002100122122900002102200d201241086a2900003703002001200237039807201210352005200d29030037030020012001290398073703c80520181001220d2900002102200e200d41086a290000370300200120023703e805200d1035200420012903e8053700002014200e290300370000201520052903003703002016200929030037030020172007290300370300200120012903c8053703a0092001427f201b4200200a1b220220067c20194200200a1b221b20087c2219201b542205ad7c22182005201820025420182002511b22051b3703a80a2001427f201920051b3703a00a200141a0096aad42808080808004842218200b42808080808002841002024020050d00200120083703f80520012006370380060c020b2001201b427f8522083703f80520012002427f85220637038006201b200283427f520d010b200141c8056a41186a22074200370300200141c8056a41106a22094200370300200141c8056a41086a22054200370300200142003703c80541b6fdc600ad428080808080018422021001220e290000210620014198076a41086a220d200e41086a2900003703002001200637039807200e10352005200d29030037030020012001290398073703c80541e489c200ad4280808080d0018422061001220a2900002108200141e8056a41086a220e200a41086a290000370300200120083703e805200a1035200420012903e805370000200441086a2214200e290300370000200141a0096a41086a22152005290300370300200141a0096a41106a22162009290300370300200141a0096a41186a22172007290300370300200120012903c8053703a009200141a8016a200141a0096a412010d701200141a8016a41106a290300210820012903b001211b20012802a801210a200742003703002009420037030020054200370300200142003703c8052002100122122900002102200d201241086a2900003703002001200237039807201210352005200d29030037030020012001290398073703c80520061001220d2900002102200e200d41086a290000370300200120023703e805200d1035200420012903e8053700002014200e290300370000201520052903003703002016200929030037030020172007290300370300200120012903c8053703a009200120084200200a1b3703a80a2001201b4200200a1b3703a00a2018200b428080808080028410020c010b200142f0f2bda1a7ee9cb9f9003703f805200141a00a6a200141f8056a10e001200141a00a6a2008200610df01200141b80a6a2006370300200141b00a6a2008370300200141a80a6a41063a00002001410c3a00a00a41b0b4cc004100200141a00a6a10d4010b200141a00a6a41186a220d4200370300200141a00a6a41106a220e4200370300200141a00a6a41086a22074200370300200142003703a00a2011100122092900002102200141f8056a41086a2205200941086a290000370300200120023703f8052009103520072005290300370300200120012903f8053703a00a41c897ca00ad4280808080a001841001220929000021022005200941086a290000370300200120023703f80520091035201020012903f805370000201041086a2005290300370000200141a0096a41086a2007290300370300200141a0096a41106a200e290300370300200141a0096a41186a200d290300370300200120012903a00a3703a009200141203602e40b2001200141a0096a3602e00b200141a8056a200141a0096aad221b42808080808004842211100510c2010240024020012802a805220d0d000c010b20012802ac05210e2001200141a8056a41086a2802003602ec052001200d3602e805200141a0016a200141e8056a10c4010240024020012802a0010d0020012802a401220a20012802ec05220941a0016e22052005200a4b1bad42a0017e2202422088a70d072002a72205417f4c0d070240024020050d004101210c0c010b20051033220c450d090b200141003602a8082001200c3602a0082001200541a0016e3602a4080240200a450d00200141a00a6a41206a211520014198076a410172211641002114410021120240034041002105200141003a00b807201241016a211202400340200141003a00d00b20092005460d0120014198076a20056a20012802e80522072d00003a00002001200741016a3602e8052001200541016a22073a00b8072007210520074120470d000b200141c8056a41086a220520014198076a41086a290300370300200141c8056a41106a221720014198076a41106a290300370300200141c8056a41186a221e20014198076a41186a29030037030020012001290398073703c8052001200920076b3602ec0520014198076a200141e8056a10c20220012d0098074101460d02200141a00a6a41186a201e290300370300200141a00a6a41106a2017290300370300200141a00a6a41086a2005290300370300200120012903c8053703a00a20152016418001109d081a200141f8056a200141a00a6a41a001109d081a0240201420012802a408470d00200141a0086a2014410110a00120012802a008210c20012802a80821140b200c201441a0016c6a200141f8056a41a001109d081a2001201441016a22143602a8082012200a460d0320012802ec0521090c010b0b200141003602ec05200541ff0171450d00200141003a00b8070b024020012802a4082205450d00200541a0016c450d00200c10350b0c010b20012902a4082102200c0d010b4100210c2001410036028006200142013703f8052001410936029c072001200141e00b6a360298072001200141f8056a3602a008200141b40a6a4101360200200142013702a40a200141c888c2003602a00a200120014198076a3602b00a200141a0086a41e88ac500200141a00a6a10431a20013502800642208620013502f80584100620012802fc05450d0020012802f80510350b200e450d00200d10350b2003200341ff017141024771211f200141003602a80a200142013703a00a200141a00a6a410020024200200c1b2219422088a7222041a0016c221241a0016e108a01200c4101200c1b211620012802a80a210c20012802a00a212102402020450d002021200c4105746a21052012210920162107034020052007290000370000200541186a200741186a290000370000200541106a200741106a290000370000200541086a200741086a290000370000200c41016a210c200541206a2105200741a0016a2107200941e07e6a22090d000b0b20012802a40a2122200141a00a6a41186a22034200370300200141a00a6a41106a22094200370300200141a00a6a41086a22074200370300200142003703a00a41a3edcb00ad4280808080f0008422021001220d2900002106200141f8056a41086a2205200d41086a290000370300200120063703f805200d103520072005290300370300200120012903f8053703a00a41f393ca00ad4280808080a001841001220d29000021062005200d41086a290000370300200120063703f805200d1035201020012903f805370000201041086a22142005290300370000200141a0096a41086a220d2007290300370300200141a0096a41106a220e2009290300370300200141a0096a41186a220a2003290300370300200120012903a00a3703a009200141203602a40a2001200141a0096a3602a00a2021200c200141a00a6a1098020240201f450d00200342003703002009420037030020074200370300200142003703a00a20021001220c29000021062005200c41086a290000370300200120063703f805200c103520072005290300370300200120012903f8053703a00a41beebcb00ad4280808080a002841001220c29000021062005200c41086a290000370300200120063703f805200c1035201020012903f80537000020142005290300370000200d2007290300370300200e2009290300370300200a2003290300370300200120012903a00a3703a009200141a00a6a200141a0096a10c50220012802a00a220c450d002011100720012902a40a42ffffffff0383500d00200c10350b200342003703002009420037030020074200370300200142003703a00a20021001220c29000021022005200c41086a290000370300200120023703f805200c103520072005290300370300200120012903f8053703a00a41a5ebcb00ad4280808080c001841001220c29000021022005200c41086a290000370300200120023703f805200c1035201020012903f80537000020142005290300370000200d2007290300370300200e2009290300370300200a2003290300370300200120012903a00a3703a0092001200f41016a22153602a00a2011200141a00a6aad22184280808080c000841002200141c8056a41186a220c4200370300200141c8056a41106a22034200370300200141c8056a41086a22054200370300200142003703c80541f7edcb00ad4280808080f000841001220729000021022005200741086a290000370300200120023703c8052007103541eeedcb00ad4280808080900184100122072900002102200141e8056a41086a2214200741086a290000370300200120023703e80520071035200420012903e805370000200441086a2014290300370000200d2005290300370300200e2003290300370300200a200c290300370300200120012903c8053703a009200141a00a6a200141a0096a10ac01200141a00a6a4100200928020041016a20012903a00a4202511b10b80120014198016a20012802a00a220c20012802a80a10c001200128029c0121072001280298012105024020012802a40a450d00200c10350b024020054101470d00024020072015460d00200720154f0d0141c3a6c000ad428080808080068410060b201510d8010b200141c8056a41186a220c4200370300200141c8056a41106a22094200370300200141c8056a41086a22054200370300200142003703c80541f7edcb00ad4280808080f0008410012207290000210220014198076a41086a2203200741086a2900003703002001200237039807200710352005200329030037030020012001290398073703c80541e4edcb00ad4280808080a00184100122072900002102200141e8056a41086a2203200741086a290000370300200120023703e80520071035200420012903e805370000200441086a2003290300370000200141a0096a41086a2005290300370300200141a0096a41106a2009290300370300200141a0096a41186a200c290300370300200120012903c8053703a00920014190016a200141a0096a412010c001200f41026a2105024002402001280290014101460d0020014198056a200510bf010c010b200141a00a6a20012802940110b80120014188016a20012802a00a220c20012802a80a10c001200128028c0121092001280288012107024020012802a40a450d00200c10350b024020070d0041fdb5c000ad4280808080e006841006410021090b200141c8056a41186a22034200370300200141c8056a41106a220d4200370300200141c8056a41086a22074200370300200142003703c80541f7edcb00ad4280808080f000841001220c290000210220014198076a41086a220e200c41086a2900003703002001200237039807200c10352007200e29030037030020012001290398073703c8054193eecb00ad42808080808001841001220c2900002102200141e8056a41086a220e200c41086a290000370300200120023703e805200c1035200420012903e805370000200441086a200e290300370000200141a0096a41086a2007290300370300200141a0096a41106a200d290300370300200141a0096a41186a2003290300370300200120012903c8053703a0094100200520096b2207200720054b1b210c0240024002404100200141a0096a10e5012207200741ff01714104461b41ff0171220741034b0d00024020070e0400020103000b200c41064f0d020b0240200c41016a4106490d00200141c8056a41186a220c4200370300200141c8056a41106a22094200370300200141c8056a41086a22054200370300200142003703c80541f7edcb00ad4280808080f0008410012207290000210220014198076a41086a2203200741086a2900003703002001200237039807200710352005200329030037030020012001290398073703c80541d9eecb00ad4280808080d00284100122072900002102200141e8056a41086a2203200741086a290000370300200120023703e80520071035200420012903e805370000200441086a2003290300370000200141a0096a41086a2005290300370300200141a0096a41106a2009290300370300200141a0096a41186a200c290300370300200120012903c8053703a009200141013a00d00b201b4280808080800484200141d00b6aad4280808080108410020b20014100360298050c020b200141c8056a41186a22094200370300200141c8056a41106a22034200370300200141c8056a41086a22074200370300200142003703c80541f7edcb00ad4280808080f000841001220c290000210220014198076a41086a220d200c41086a2900003703002001200237039807200c10352007200d29030037030020012001290398073703c8054193eecb00ad42808080808001841001220c2900002102200141e8056a41086a220d200c41086a290000370300200120023703e805200c1035200420012903e805370000200441086a200d290300370000200141a0096a41086a2007290300370300200141a0096a41106a2003290300370300200141a0096a41186a2009290300370300200120012903c8053703a009201b428080808080048410070b200141c8056a41186a22094200370300200141c8056a41106a22034200370300200141c8056a41086a22074200370300200142003703c80541f7edcb00ad4280808080f000841001220c290000210220014198076a41086a220d200c41086a2900003703002001200237039807200c10352007200d29030037030020012001290398073703c80541d9eecb00ad4280808080d002841001220c2900002102200141e8056a41086a220d200c41086a290000370300200120023703e805200c1035200420012903e805370000200441086a200d290300370000200141a0096a41086a2007290300370300200141a0096a41106a2003290300370300200141a0096a41186a2009290300370300200120012903c8053703a009200141003a00d00b201b4280808080800484200141d00b6aad42808080801084100220014198056a200510bf010b201620126a211e0240024020012802980522230d00200141a00a6a41186a4200370300200141a00a6a41106a220c4200370300200141a00a6a41086a22054200370300200142003703a00a41a3edcb00ad4280808080f000841001220729000021022005200741086a290000370300200120023703a00a2007103541f393ca00ad4280808080a0018410012207290000210220014198076a41086a2209200741086a290000370300200120023703980720071035200c2001290398072202370300200141f8056a41086a2005290300370300200141f8056a41106a2002370300200141f8056a41186a2009290300370300200120012903a00a3703f805200141a00a6a200141f8056a10fe0120012902a40a420020012802a00a22051b21022005410120051b2124410021250c010b41012125200129029c052102202321240b200120253a00c00b2001201e3602d40b200120163602d00b2001200141d00b6a3602e40b2001200141c00b6a3602e00b200141003602f005200142013703e805200141e8056a41002002422088a72205410574220741057510a00120012802f005211420012802e805211702402005450d002017201441a0016c6a210c2014200741606a4105766a2126200141a00a6a41206a210a200141a0086a41e0006a2127200141a0086a41c0006a2114200141a0086a41206a2112200141f8056a410172210f202421050340200141c8056a41186a2209200541186a290000370300200141c8056a41106a2204200541106a290000370300200141c8056a41086a2203200541086a290000370300200120052900003703c805200141a8056a200141c8056a10dd06200141f8056a20012802a805220e20012802b00510c10220012d00f805210d20014198076a200f418001109d081a02400240200d4101470d00200141a0096a20014198076a418001109d081a024020012802ac05450d00200e10350b200141a0086a200141a0096a418001109d081a0c010b024020012802ac05450d00200e10350b200141a0086a4100418001109f081a0b024020012802e00b2d00000d0020012802e40b220e280200220d200e280204460d00200e200d41a0016a36020002400240200141a0086a200d41206a220e460d00200e200141a0086a412010a0080d010b02402012200d41c0006a220e460d00200e2012412010a0080d010b02402014200d41e0006a220e460d00200e2014412010a0080d010b2027200d4180016a220d460d01200d2027412010a008450d010b20012802e00b41013a00000b200541206a2105200141a00a6a41186a2009290300370300200141a00a6a41106a2004290300370300200141a00a6a41086a2003290300370300200120012903c8053703a00a200a200141a0086a418001109d081a200c200141a00a6a41a001109d0841a0016a210c200741606a22070d000b202641016a21140b200120143602f0050240200242ffffff3f83500d00202410350b2014ad42a0017e2202422088a70d042002a72205417f4c0d0420012802ec05212820012d00c00b21240240024020050d00410121070c010b200510332207450d060b2001410036028006200120073602f8052001200541a0016e3602fc05200141f8056a4100201410a00120012802800621030240024020140d0020012802f805210f0c010b2017201441a0016c6a210e20012802f805220f200341a0016c6a210d200141a00a6a4180016a2107200141a00a6a41e0006a210c200141a00a6a41c0006a2109200141a00a6a41206a2104201721050340200141a00a6a41186a200541186a290000370300200141a00a6a41106a200541106a290000370300200141a00a6a41086a200541086a290000370300200120052900003703a00a200441186a200541386a290000370000200441106a200541306a290000370000200441086a200541286a2900003700002004200541206a2900003700002009200541c0006a290000370000200941086a200541c8006a290000370000200941106a200541d0006a290000370000200941186a200541d8006a290000370000200c200541e0006a290000370000200c41086a200541e8006a290000370000200c41106a200541f0006a290000370000200c41186a200541f8006a290000370000200720054180016a290000370000200741086a20054188016a290000370000200741106a20054190016a290000370000200741186a20054198016a290000370000200341016a2103200d200141a00a6a41a001109d0841a0016a210d200541a0016a2205200e470d000b0b20012802fc052127200141a00a6a41186a22094200370300200141a00a6a41106a22044200370300200141a00a6a41086a22074200370300200142003703a00a41a3edcb00ad4280808080f000841001220c2900002102200141f8056a41086a2205200c41086a290000370300200120023703f805200c103520072005290300370300200120012903f8053703a00a41c897ca00ad4280808080a001841001220c29000021022005200c41086a290000370300200120023703f805200c1035201020012903f805370000201041086a2005290300370000200141a0096a41086a2007290300370300200141a0096a41106a2004290300370300200141a0096a41186a2009290300370300200120012903a00a3703a009200341a0016c4104722205417f4c0d04200510332207450d05200141003602a80a200120053602a40a200120073602a00a2003200141a00a6a10770240024020030d0020012802a80a210520012802a40a210d20012802a00a21070c010b200f200341a0016c6a2112410020012802a80a22036b210920012802a40a210d4100210c03402003200c6a210402400240200d20096a4120490d0020012802a00a2107200d210e0c010b200441206a22052004490d04200d41017422072005200720054b1b220e4100480d0402400240200d0d000240200e0d00410121070c020b200e103322070d010c0c0b20012802a00a2107200d200e460d002007200d200e10372207450d0b0b2001200e3602a40a200120073602a00a0b200720036a200c6a220d200f200c6a2205290000370000200d41186a200541186a290000370000200d41106a200541106a290000370000200d41086a200541086a2900003700002001200441206a220d3602a80a02400240200e20096a41606a411f4d0d00200e210d0c010b200d41206a220a200d490d04200e410174220d200a200d200a4b1b220d4100480d0402400240200e0d000240200d0d00410121070c020b200d10332207450d0c0c010b200e200d460d002007200e200d10372207450d0b0b2001200d3602a40a200120073602a00a0b200720036a200c6a220e41206a200541206a290000370000200e41386a200541386a290000370000200e41306a200541306a290000370000200e41286a200541286a2900003700002001200441c0006a220e3602a80a02400240200d20096a41406a411f4d0d00200d210e0c010b200e41206a220a200e490d04200d410174220e200a200e200a4b1b220e4100480d0402400240200d0d000240200e0d00410121070c020b200e10332207450d0c0c010b200d200e460d002007200d200e10372207450d0b0b2001200e3602a40a200120073602a00a0b200720036a200c6a220d41c0006a200541c0006a290000370000200d41d8006a200541d8006a290000370000200d41d0006a200541d0006a290000370000200d41c8006a200541c8006a2900003700002001200441e0006a220d3602a80a02400240200e20096a41a07f6a411f4d0d00200e210a0c010b200d41206a220a200d490d04200e410174220d200a200d200a4b1b220a4100480d0402400240200e0d000240200a0d00410121070c020b200a10332207450d0c0c010b200e200a460d002007200e200a10372207450d0b0b2001200a3602a40a200120073602a00a0b200720036a200c6a220d41e0006a200541e0006a290000370000200d41f8006a200541f8006a290000370000200d41f0006a200541f0006a290000370000200d41e8006a200541e8006a290000370000200120044180016a220d3602a80a02400240200a20096a41807f6a411f4d0d00200a210d0c010b200d41206a220e200d490d04200a410174220d200e200d200e4b1b220d4100480d0402400240200a0d000240200d0d00410121070c020b200d10332207450d0c0c010b200a200d460d002007200a200d10372207450d0b0b2001200d3602a40a200120073602a00a0b200720036a200c6a220e4180016a20054180016a290000370000200e4198016a20054198016a290000370000200e4190016a20054190016a290000370000200e4188016a20054188016a2900003700002001200441a0016a3602a80a200941e07e6a2109200c41a0016a210c200541a0016a2012470d000b2003200c6a21050b20112005ad4220862007ad8410020240200d450d00200710350b02402027450d00202741a0016c450d00200f10350b200141a00a6a41186a22094200370300200141a00a6a41106a22044200370300200141a00a6a41086a22074200370300200142003703a00a41a3edcb00ad4280808080f000841001220c2900002102200141f8056a41086a2205200c41086a290000370300200120023703f805200c103520072005290300370300200120012903f8053703a00a41b1ebcb00ad4280808080d001841001220c29000021022005200c41086a290000370300200120023703f805200c1035201020012903f805370000201041086a2005290300370000200141a0096a41086a2007290300370300200141a0096a41106a2004290300370300200141a0096a41186a2009290300370300200120012903a00a3703a009200120243a00a00a20112018428080808010841002200120153602a40a200141053a00a00a41b0b4cc004100200141a00a6a10d40141081033220c450d07200c201e360204200c201636020002400240201f0d00200141a00a6a41186a22094200370300200141a00a6a41106a22044200370300200141a00a6a41086a22074200370300200142003703a00a41a8e7cb00ad4280808080f00184100122032900002102200141f8056a41086a2205200341086a290000370300200120023703f8052003103520072005290300370300200120012903f8053703a00a419ce7cb00ad4280808080c001841001220329000021022005200341086a290000370300200120023703f80520031035201020012903f805370000201041086a220d2005290300370000200141a0096a41086a220e2007290300370300200141a0096a41106a220a2004290300370300200141a0096a41186a220f2009290300370300200120012903a00a3703a009200141f8006a200141a0096a10e102200129038001210220012802782112200942003703002004420037030020074200370300200142003703a00a41a3edcb00ad4280808080f000841001220329000021062005200341086a290000370300200120063703f8052003103520072005290300370300200120012903f8053703a00a41a5ebcb00ad4280808080c001841001220329000021062005200341086a290000370300200120063703f80520031035201020012903f805370000200d2005290300370000200e2007290300370300200a2004290300370300200f2009290300370300200120012903a00a3703a009200141f0006a200141a0096a412010c0012002420020121b2001280274410020012802701b10de06200c10350c010b0240024002402020450d00200c201641a0016a360200200141003a00c00a201641206a2107410021050340200141003a00d00b200141a00a6a20056a200720056a2d00003a00002001200541016a22053a00c00a20054120470d000b200141f8056a41086a2205200141a00a6a41086a290300370300200141f8056a41106a2207200141a00a6a41106a290300370300200141f8056a41186a2209200141a00a6a41186a290300370300200120012903a00a22023703a009200120023703f8052016450d0020014198076a41186a200929030037030020014198076a41106a200729030037030020014198076a41086a2005290300370300200120012903f80537039807200c280204200c2802006b41a0016e41286c41286a2205417f4c0d08200510332204450d09200420012903980737030020044201370320200441186a20014198076a41186a290300370300200441106a20014198076a41106a290300370300200441086a20014198076a41086a29030037030041012109200141013602a808200120043602a0082001200541286e22073602a408200c2802002205200c280204460d01200c200541a0016a360200200141003a00c00a200541206a2109410021050340200141003a00d00b200141a00a6a20056a200920056a2d00003a00002001200541016a22053a00c00a20054120470d000b200141a0096a41086a2215200141a00a6a41086a22272903002202370300200141f8056a41186a2203200141a00a6a41186a2220290300370300200141f8056a41106a220d200141a00a6a41106a2224290300370300200141f8056a41086a220e2002370300200120012903a00a22023703a009200120023703f80541012109034020014198076a41186a2003290300220237030020014198076a41106a200d290300220637030020014198076a41086a200e2903002208370300200120012903f805220b37039807200141c8056a41186a220a2002370300200141c8056a41106a220f2006370300200141c8056a41086a221220083703002001200b3703c805024020092007470d00200141a0086a2007200c280204200c2802006b41a0016e41016a108f0120012802a00821040b2004200941286c6a220520012903c80537030020122903002102200f2903002106200a290300210820054201370320200541186a2008370300200541106a2006370300200541086a20023703002001200941016a22093602a8080240200c2802002207200c280204470d0020012802a40821070c030b200c200741a0016a36020041002105200141003a00c00a200741206a21070340200141003a00d00b200141a00a6a20056a200720056a2d00003a00002001200541016a22053a00c00a20054120470d000b20152027290300220237030020032020290300370300200d2024290300370300200e2002370300200120012903a00a22023703a009200120023703f80520012802a40821070c000b0b200c10354108210441002109410021070c010b200c10350b200141a00a6a41186a220d4200370300200141a00a6a41106a220e4200370300200141a00a6a41086a220c4200370300200142003703a00a41a8e7cb00ad4280808080f00184100122032900002102200141f8056a41086a2205200341086a290000370300200120023703f80520031035200c2005290300370300200120012903f8053703a00a41d297ca00ad4280808080f000841001220329000021022005200341086a290000370300200120023703f80520031035201020012903f805370000201041086a2005290300370000200141a0096a41086a200c290300370300200141a0096a41106a200e290300370300200141a0096a41186a200d290300370300200120012903a00a3703a009200141a00a6a200141a0096a412010da010240024020012802a00a4101460d00200120093602a80a200120073602a40a200120043602a00a200141f8056a200141a00a6a41004100200110df060c010b2011100720012902a40a2102200120093602a80a200120073602a40a200120043602a00a200141f8056a200141a00a6a2002a741012002422088a710df060b200141a00a6a41186a220c4200370300200141a00a6a41106a22094200370300200141a00a6a41086a22074200370300200142003703a00a41a8e7cb00ad4280808080f001842202100122042900002106200141f8056a41086a2205200441086a290000370300200120063703f8052004103520072005290300370300200120012903f8053703a00a419ce7cb00ad4280808080c0018422061001220429000021082005200441086a290000370300200120083703f80520041035201020012903f805370000201041086a22042005290300370000200141a0096a41086a22032007290300370300200141a0096a41106a220d2009290300370300200141a0096a41186a220e200c290300370300200120012903a00a3703a009200141e0006a200141a0096a10e1022001280260210f20012903682108200c42003703002009420037030020074200370300200142003703a00a20021001220a29000021022005200a41086a290000370300200120023703f805200a103520072005290300370300200120012903f8053703a00a20061001220a29000021022005200a41086a290000370300200120023703f805200a1035201020012903f8053700002004200529030037000020032007290300370300200d2009290300370300200e200c290300370300200120012903a00a3703a0092001200842017c4201200f1b22023703a00a2011201842808080808001841002200c42003703002009420037030020074200370300200142003703a00a41a3edcb00ad4280808080f000841001220a29000021062005200a41086a290000370300200120063703f805200a103520072005290300370300200120012903f8053703a00a41a5ebcb00ad4280808080c001841001220a29000021062005200a41086a290000370300200120063703f805200a1035201020012903f8053700002004200529030037000020032007290300370300200d2009290300370300200e200c290300370300200120012903a00a3703a009200141d8006a200141a0096a412010c0012002200128025c410020012802581b10de060b410810332205450d072005201e36020420052016360200410810332207450d0720072017201441a0016c6a222436020420072017360200200141c00b6a200541dc97ca0010cb05200141d00b6a200741dc97ca0010cb0520012802c80b210420012802c40b211220012802c00b2110200141e00b6a41086a200141d00b6a41086a280200360200200120012903d00b3703e00b20014198076a41186a2207420037030020014198076a41106a220c420037030020014198076a41086a22054200370300200142003703980741a9d1cb00ad4280808080c0008422021001220929000021062005200941086a29000037030020012006370398072009103541add1cb00ad4280808080a001842206100122032900002108200141e8056a41086a2209200341086a290000370300200120083703e80520031035201320012903e805370000201341086a22032009290300370000200141f8056a41086a220d2005290300370300200141f8056a41106a220e200c290300370300200141f8056a41186a220a200729030037030020012001290398073703f805200141c8006a200141f8056a10e10202400240024002402001290350420020012802481b220b42017c2208200b540d0020074200370300200c420037030020054200370300200142003703980720021001220f290000210b2005200f41086a2900003703002001200b37039807200f103520061001220f29000021062009200f41086a290000370300200120063703e805200f1035201320012903e80537000020032009290300370000200d2005290300370300200e200c290300370300200a200729030037030020012001290398073703f805200120083703a00a200141f8056aad4280808080800484220620184280808080800184100220074200370300200c420037030020054200370300200142003703980720021001220f29000021022005200f41086a2900003703002001200237039807200f103541b7d1cb00ad4280808080b001841001220f29000021022009200f41086a290000370300200120023703e805200f1035201320012903e80537000020032009290300370000200d2005290300370300200e200c290300370300200a200729030037030020012001290398073703f805200441286c4104722205417f4c0d08200510332207450d09200141003602a80a200120053602a40a200120073602a00a2004200141a00a6a10770240024020040d0020012802a80a210520012802a00a21040c010b2010200441286c6a210d20012802a40a210c20012802a80a210520102107034002400240200c20056b4120490d0020012802a00a2104200c21090c010b200541206a22092005490d08200c41017422042009200420094b1b22094100480d0802400240200c0d00024020090d00410121040c020b200910332204450d100c010b20012802a00a2104200c2009460d002004200c200910372204450d0f0b200120093602a40a200120043602a00a0b200420056a220c2007290000370000200c41186a200741186a290000370000200c41106a200741106a290000370000200c41086a200741086a2900003700002001200541206a22033602a80a200741206a290300210202400240200920036b4108490d00200541286a21052009210c0c010b200341086a22052003490d082009410174220c2005200c20054b1b220c4100480d080240024020090d000240200c0d00410121040c020b200c10332204450d100c010b2009200c460d0020042009200c10372204450d0f0b2001200c3602a40a200120043602a00a0b200420036a2002370000200120053602a80a200d200741286a2207470d000b0b20012802a40a210720062005ad4220862004ad84100202402007450d00200410350b02402012450d00201241286c450d00201010350b200842017c22022008540d0120014198076a41186a220c420037030020014198076a41106a2209420037030020014198076a41086a22054200370300200142003703980741a9d1cb00ad4280808080c000841001220729000021082005200741086a29000037030020012008370398072007103541e2d1cb00ad4280808080e00184100122072900002108200141e8056a41086a2204200741086a290000370300200120083703e80520071035201320012903e805370000201341086a2004290300370000200141f8056a41086a2005290300370300200141f8056a41106a2009290300370300200141f8056a41186a200c29030037030020012001290398073703f805200141a00a6a200141f8056a10b10220012d00a00a2105200141c8056a41186a2207200141b90a6a290000370300200141c8056a41106a220c200141b10a6a290000370300200141c8056a41086a2209200141a90a6a290000370300200120012900a10a3703c8050240024020054101460d00200141a8056a41186a4200370300200141a8056a41106a4200370300200141a8056a41086a4200370300200142003703a8050c010b200141a8056a41186a2007290300370300200141a8056a41106a200c290300370300200141a8056a41086a2009290300370300200120012903c8053703a8050b20014198076a41186a2207420037030020014198076a41106a220c420037030020014198076a41086a22054200370300200142003703980741a9d1cb00ad4280808080c00084220810012209290000210b2005200941086a2900003703002001200b370398072009103541f0d1cb00ad4280808080c00184220b100122042900002111200141e8056a41086a2209200441086a290000370300200120113703e80520041035201320012903e805370000201341086a22032009290300370000200141f8056a41086a220d2005290300370300200141f8056a41106a220e200c290300370300200141f8056a41186a220a200729030037030020012001290398073703f805200141c0006a200141f8056a412010c0012001280244210f2001280240211220074200370300200c420037030020054200370300200142003703980720081001220429000021082005200441086a290000370300200120083703980720041035200b1001220429000021082009200441086a290000370300200120083703e80520041035201320012903e80537000020032009290300370000200d2005290300370300200e200c290300370300200a200729030037030020012001290398073703f805200141003602a00a200620184280808080c000841002200141a0096a41186a200141a8056a41186a290300370300200141a0096a41106a200141a8056a41106a290300370300200141a0096a41086a200141a8056a41086a290300370300200120012903a8053703a009417f200f410020121b220341016a220520052003491b410d74412872220a417f4c0d08200a1033220d450d09200d20012903a009370000200d2002370020200d41186a200141a0096a41186a290300370000200d41106a200141a0096a41106a290300370000200d41086a200141a0096a41086a2903003700004128210e410021074100210502400340024002402005450d00200c2009470d01200441ffffff3f71450d00200510350b200720034f0d02200141e8056a200710fe03200141a00a6a20012802e805220c20012802f005220910c302024020012802a00a2205450d002009ad422086200cad8410070b20012902a40a420020051b21022005410120051b2105024020012802ec05450d00200c10350b200741016a210720052002422088a74105746a21092002a721042005210c0c010b20014198076a41186a200c41186a220f29000037030020014198076a41106a200c41106a221229000037030020014198076a41086a200c41086a22102900003703002001200c290000370398072010290000210220122900002108200c290000210b200141f8056a41186a2212200f290000370300200141f8056a41106a220f2008370300200141f8056a41086a221020023703002001200b3703f805200141a00a6a41186a22142012290300370300200141a00a6a41106a2212200f290300370300200141a00a6a41086a22152010290300370300200120012903f8053703a00a0240200a200e6b411f4b0d00200e41206a220f200e490d08200a4101742210200f2010200f4b1b220f4100480d0802400240200a0d000240200f0d004101210d0c020b200f1033220d450d100c010b200a200f460d00200d200a200f1037220d450d0f0b200f210a0b200c41206a210c200d200e6a220f20012903a00a370000200f41186a2014290300370000200f41106a2012290300370000200f41086a2015290300370000200e41206a210e0c000b0b200ead422086200dad84100922052900002102200541086a2900002108200541106a290000210b200141c8056a41186a200541186a290000370300200141c8056a41106a200b370300200141c8056a41086a2008370300200120023703c805200510350240200a450d00200d10350b20014198076a41186a220c420037030020014198076a41106a2209420037030020014198076a41086a22054200370300200142003703980741a9d1cb00ad4280808080c0008422021001220729000021082005200741086a29000037030020012008370398072007103541e2d1cb00ad4280808080e00184100122072900002108200141e8056a41086a2204200741086a290000370300200120083703e80520071035201320012903e805370000201341086a2004290300370000200141f8056a41086a2005290300370300200141f8056a41106a2009290300370300200141f8056a41186a200c29030037030020012001290398073703f805412010332205450d09200520012903c805370000200541186a200141c8056a41186a2203290300370000200541106a200141c8056a41106a220d290300370000200541086a200141c8056a41086a220e29030037000020062005ad4280808080800484100220051035200141a0086a41186a200141a8056a41186a2903002208370300200141a0086a41106a200141a8056a41106a290300220b370300200141a0086a41086a200141a8056a41086a2903002211370300200120012903a805221a3703a008200141a00a6a41186a220a2008370300200141a00a6a41106a220f200b370300200141a00a6a41086a221220113703002001201a3703a00a20014198076a41186a220c420037030020014198076a41106a2209420037030020014198076a41086a22074200370300200142003703980720021001220529000021022007200541086a29000037030020012002370398072005103541d8d1cb00ad4280808080a00184100122052900002102200141e8056a41086a2204200541086a290000370300200120023703e80520051035201320012903e805370000201341086a22102004290300370000200141f8056a41086a22142007290300370300200141f8056a41106a22152009290300370300200141f8056a41186a2227200c29030037030020012001290398073703f805412010332205450d09200520012903a00a370000200541186a200a290300370000200541106a200f290300370000200541086a201229030037000020062005ad4280808080800484100220051035200c42003703002009420037030020074200370300200142003703980741a9d1cb00ad4280808080c000841001220529000021022007200541086a29000037030020012002370398072005103541e2d1cb00ad4280808080e001841001220529000021022004200541086a290000370300200120023703e80520051035201320012903e8053700002010200429030037000020142007290300370300201520092903003703002027200c29030037030020012001290398073703f805200141a00a6a200141f8056a10b10220012d00a00a21052003200141b90a6a290000370300200d200141b10a6a290000370300200e200141a90a6a290000370300200120012900a10a3703c8050240024020054101460d00200141b8096a4200370300200141b0096a4200370300200141a8096a4200370300200142003703a0090c010b200141a0096a41186a200141c8056a41186a290300370300200141a0096a41106a200141c8056a41106a290300370300200141a0096a41086a200141c8056a41086a290300370300200120012903c8053703a0090b200141f8056a41086a2205200141e00b6a41086a280200360200200141f8056a41246a200141a0096a41186a290300370200200141f8056a411c6a200141a0096a41106a290300370200200141f8056a41146a200141a0096a41086a290300370200200120012903e00b22023703f805200120012903a00937028406200141cc0a6a200141f8056a41286a280200360200200141a00a6a41246a20014198066a290300370200200141a00a6a411c6a200141f8056a41186a290300370200200141a00a6a41146a200141f8056a41106a290300370200200141a00a6a410c6a2005290300370200200120023702a40a200141003602a00a20014198076a200141a00a6a108104200141d3056a20014198076a41086a28020036000020012001290398073700cb0520014198076a410c6a200141cf056a290000370000200141c28289aa0436009907200141023a009807200120012900c80537009d0720014198076a1082040240200141a00a6a41086a2802002205450d00200541286c450d0020012802a40a10350b41081033220c450d0b200c201e360204200c2016360200410810332227450d0b2027202436020420272017360200200141f8056a41186a4200370300200141f8056a41106a22264200370300200141f8056a41086a22054200370300200142003703f80541d1c4c700ad4280808080e000841001220729000021022005200741086a290000370300200120023703f8052007103541e7c4c700ad4280808080e00084100122072900002102200141e8056a41086a2209200741086a290000370300200120023703e80520071035202620012903e8052202370300200141a0096a41086a2005290300370300200141a0096a41106a2002370300200141a0096a41186a2009290300370300200120012903f8053703a009200141386a200141a0096a412010c00120012802382104200128023c2103200141a00a6a41186a4200370300200141a00a6a41106a22204200370300200141a00a6a41086a22074200370300200142003703a00a4188e8cb00ad42808080808001841001220929000021022005200941086a290000370300200120023703f8052009103520072005290300370300200120012903f8053703a00a4194c4c400ad4280808080e0018410012205290000210220014198076a41086a2209200541086a29000037030020012002370398072005103520202001290398072202370300200141a0086a41086a2007290300370300200141a0086a41106a2002370300200141a0086a41186a2009290300370300200120012903a00a3703a0082001200341e4006a41e40020041b3602a00a200141a0086aad4280808080800484221120184280808080c0008410020240200c2802002205200c280204460d00200c200541a0016a360200200141003a00c00a200541e0006a2107410021050340200141003a00d00b200141a00a6a20056a200720056a2d00003a00002001200541016a22053a00c00a20054120470d000b200141f8056a41086a200141a00a6a41086a290300220237030020014198076a41186a2205200141a00a6a41186a29030037030020014198076a41106a2207200141a00a6a41106a29030037030020014198076a41086a22092002370300200120012903a00a22023703f8052001200237039807200c280204200c2802006b41a0016e41057441206a220410332212450d0a2012200129039807370000201241186a2005290300370000201241106a2007290300370000201241086a200929030037000041012109200141013602a808200120123602a00820012004410576220a3602a408200c2802002205200c280204460d03200c200541a0016a360200200141003a00c00a200541e0006a2107410021050340200141003a00d00b200141a00a6a20056a200720056a2d00003a00002001200541016a22053a00c00a20054120470d000b200141a0096a41086a2210200141a00a6a41086a22132903002202370300200141f8056a41186a2204200141a00a6a41186a2214290300370300200141f8056a41106a2203200141a00a6a41106a2215290300370300200141f8056a41086a220d2002370300200120012903a00a22023703a009200120023703f805410121090340200141a8056a41186a20042903002202370300200141a8056a41106a20032903002206370300200141a8056a41086a200d2903002208370300200120012903f805220b3703a805200141c8056a41186a22072002370300200141c8056a41106a220e2006370300200141c8056a41086a220f20083703002001200b3703c80502402009200a470d00200141a0086a200a200c280204200c2802006b41a0016e41016a108a0120012802a00821120b201220094105746a220520012903c805370000200541186a2007290300370000200541106a200e290300370000200541086a200f2903003700002001200941016a22093602a8080240200c2802002207200c280204470d0020012802a408210a0c050b200c200741a0016a36020041002105200141003a00c00a200741e0006a21070340200141003a00d00b200141a00a6a20056a200720056a2d00003a00002001200541016a22053a00c00a20054120470d000b2010201329030022023703002004201429030037030020032015290300370300200d2002370300200120012903a00a22023703a009200120023703f80520012802a408210a0c000b0b200c10354100210a41012112410021090c030b41e6dcc30041c90041b0ddc3001064000b41e6dcc30041c90041c0ddc3001064000b200c10350b200141a00a6a41186a220c4200370300200141a00a6a41106a22044200370300200141a00a6a41086a22054200370300200142003703a00a4188e8cb00ad4280808080800184100122072900002102200141f8056a41086a2203200741086a290000370300200120023703f8052007103520052003290300370300200120012903f8053703a00a418fd1cb00ad4280808080c0008410012207290000210220014198076a41086a2203200741086a2900003703002001200237039807200710352020200129039807370000202041086a2003290300370000200141a0086a41086a2005290300370300200141a0086a41106a2004290300370300200141a0086a41186a200c290300370300200120012903a00a3703a008200941057422034104722205417f4c0d04200510332207450d05200141003602a80a200120053602a40a200120073602a00a2009200141a00a6a10770240024020090d0020012802a80a210720012802a40a210920012802a00a210e0c010b410020012802a80a22076b210420012802a00a210e20012802a40a21092012210d0340200d21050240200920046a411f4b0d00200741206a220c2007490d042009410174220d200c200d200c4b1b220c4100480d04024002400240024020090d000240200c0d004101210e0c020b200c1033210e0c030b2009200c470d010b200c21090c020b200e2009200c1037210e0b200c2109200e450d0a0b200541206a210d200e20076a220c2005290000370000200c41186a200541186a290000370000200c41106a200541106a290000370000200c41086a200541086a290000370000200441606a2104200741206a2107200341606a22030d000b200120093602a40a200120073602a80a2001200e3602a00a0b20112007ad422086200ead84100202402009450d00200e10350b0240200a41ffffff3f71450d00201210350b2027103541081033220c450d07200c201e360204200c201636020041081033221e450d07201e2024360204201e20173602000240024002400240201f450d000240200c2802002205200c280204460d00200c200541a0016a360200200141003a00c00a20054180016a2107410021050340200141003a00d00b200141a00a6a20056a200720056a2d00003a00002001200541016a22053a00c00a20054120470d000b200141f8056a41086a200141a00a6a41086a290300220237030020014198076a41186a2205200141a00a6a41186a29030037030020014198076a41106a2207200141a00a6a41106a29030037030020014198076a41086a22092002370300200120012903a00a22023703f8052001200237039807200c280204200c2802006b41a0016e41057441206a220410332212450d0a2012200129039807370000201241186a2005290300370000201241106a2007290300370000201241086a200929030037000041012109200141013602a808200120123602a00820012004410576220a3602a408200c2802002205200c280204460d02200c200541a0016a360200200141003a00c00a20054180016a2107410021050340200141003a00d00b200141a00a6a20056a200720056a2d00003a00002001200541016a22053a00c00a20054120470d000b200141a0096a41086a2210200141a00a6a41086a22132903002202370300200141f8056a41186a2204200141a00a6a41186a2214290300370300200141f8056a41106a2203200141a00a6a41106a2215290300370300200141f8056a41086a220d2002370300200120012903a00a22023703a009200120023703f805410121090340200141a8056a41186a20042903002202370300200141a8056a41106a20032903002206370300200141a8056a41086a200d2903002208370300200120012903f805220b3703a805200141c8056a41186a22072002370300200141c8056a41106a220e2006370300200141c8056a41086a220f20083703002001200b3703c80502402009200a470d00200141a0086a200a200c280204200c2802006b41a0016e41016a108a0120012802a00821120b201220094105746a220520012903c805370000200541186a2007290300370000200541106a200e290300370000200541086a200f2903003700002001200941016a22093602a8080240200c2802002207200c280204470d0020012802a408210a0c040b200c200741a0016a36020041002105200141003a00c00a20074180016a21070340200141003a00d00b200141a00a6a20056a200720056a2d00003a00002001200541016a22053a00c00a20054120470d000b2010201329030022023703002004201429030037030020032015290300370300200d2002370300200120012903a00a22023703a009200120023703f80520012802a408210a0c000b0b200c10354100210a41012112410021090c020b201e1035200c10350c020b200c10350b200141f8056a41186a220c4200370300200141f8056a41106a22044200370300200141f8056a41086a22054200370300200142003703f80541fdd0cb00ad4280808080a002841001220729000021022005200741086a290000370300200120023703f80520071035418fd1cb00ad4280808080c00084100122072900002102200141e8056a41086a2203200741086a290000370300200120023703e80520071035202620012903e805370000202641086a2003290300370000200141a0096a41086a2005290300370300200141a0096a41106a2004290300370300200141a0096a41186a200c290300370300200120012903f8053703a009200941057422034104722205417f4c0d05200510332207450d06200141003602a80a200120053602a40a200120073602a00a2009200141a00a6a10770240024020090d0020012802a80a210720012802a40a210920012802a00a210e0c010b410020012802a80a22076b210420012802a00a210e20012802a40a21092012210d0340200d21050240200920046a411f4b0d00200741206a220c2007490d052009410174220d200c200d200c4b1b220c4100480d05024002400240024020090d000240200c0d004101210e0c020b200c1033210e0c030b2009200c470d010b200c21090c020b200e2009200c1037210e0b200c2109200e450d0b0b200541206a210d200e20076a220c2005290000370000200c41186a200541186a290000370000200c41106a200541106a290000370000200c41086a200541086a290000370000200441606a2104200741206a2107200341606a22030d000b200120093602a40a200120073602a80a2001200e3602a00a0b201b42808080808004842007ad422086200ead84100202402009450d00200e10350b0240200a41ffffff3f71450d00201210350b201e10350b02402028450d00202841a0016c450d00201710350b02402025202345720d00200128029c0541ffffff3f71450d00202310350b0240202241ffffff3f71450d00202110350b42d0e199cd9a3a21022019a72205450d00200541a0016c450d00201610350b20014198076a41186a2203420037030020014198076a41106a2207420037030020014198076a41086a22054200370300200142003703980741f7edcb00ad4280808080f0008422081001220c2900002106200141a00a6a41086a2209200c41086a290000370300200120063703a00a200c103520052009290300370300200120012903a00a3703980741b6aac000ad42808080809002841001220c2900002106200141a0096a41086a2204200c41086a290000370300200120063703a009200c1035200720012903a0092206370300200141f8056a41086a220c2005290300370300200141f8056a41106a220d2006370300200141f8056a41186a220e200429030037030020012001290398073703f805200141306a200141f8056a10f2012001280230417d710d02200342003703002007420037030020054200370300200142003703980720081001220a29000021062009200a41086a290000370300200120063703a00a200a103520052009290300370300200120012903a00a3703980741d9eecb00ad4280808080d002841001220929000021062004200941086a290000370300200120063703a00920091035200720012903a009370000200741086a2004290300370000200c2005290300370300200d2007290300370300200e200329030037030020012001290398073703f8050240200141f8056a10bd02220541ff01714102460d0020054101710d020b20014198076a41186a2209420037030020014198076a41106a2204420037030020014198076a41086a22054200370300200142003703980741f7edcb00ad4280808080f000841001220c2900002106200141a00a6a41086a2203200c41086a290000370300200120063703a00a200c103520052003290300370300200120012903a00a370398074193eecb00ad42808080808001841001220c2900002106200141a0096a41086a2203200c41086a290000370300200120063703a009200c1035200720012903a009370000200741086a2003290300370000200141f8056a41086a2005290300370300200141f8056a41106a2004290300370300200141f8056a41186a200929030037030020012001290398073703f8054100200141f8056a10e5012205200541ff01714104461b41ff01710e0402010201020b103e000b200141c8056a41186a22044200370300200141c8056a41106a220c4200370300200141c8056a41086a22054200370300200142003703c80541a9d1cb00ad4280808080c0008422061001220929000021082005200941086a290000370300200120083703c8052009103541add1cb00ad4280808080a0018410012203290000210820014198076a41086a2209200341086a290000370300200120083703980720031035200c2001290398072208370300200141a0096a41086a220d2005290300370300200141a0096a41106a220e2008370300200141a0096a41186a220a2009290300370300200120012903c8053703a009200141206a200141a0096a10e1022001280220210f2001290328210820044200370300200c420037030020054200370300200142003703c805200610012203290000210b2005200341086a2900003703002001200b3703c8052003103541c2d1cb00ad4280808080b0018410012203290000210b2009200341086a2900003703002001200b3703980720031035200c200129039807220b370300200d2005290300370300200e200b370300200a2009290300370300200120012903c8053703a009200141106a200141a0096a10e1022001290318210b2001280210210320044200370300200c420037030020054200370300200142003703c80520061001220929000021062005200941086a290000370300200120063703c8052009103541cdd1cb00ad4280808080b00184100122092900002106200141f8056a41086a2204200941086a290000370300200120063703f80520091035200c20012903f8052206370300200141a8056a41086a2005290300370300200141a8056a41106a2006370300200141a8056a41186a2004290300370300200120012903c8053703a8052001200141a8056a10e102427f200b420020031b200842c8017e4200200f1b7c220642c8017c220820082006541b22062001290308420020012802001b7d22082006560d00417f20002008a7417f2008428080808010541b6a220520052000491b220520006b220c20054b0d00200c417f6a41314b0d0041f7edcb00ad4280808080f00084100122052900002106200141a00a6a41086a220c200541086a290000370300200120063703a00a2005103541f393ca00ad4280808080a00184100122052900002106200141a0096a41086a2209200541086a290000370300200120063703a00920051035412010332205450d02200520012903a00a370000200520012903a009370010200541086a200c290300370000200541186a2204200929030037000041201033220c450d02200c2005290000370000200c41186a2004290000370000200c41106a200541106a290000370000200c41086a200541086a290000370000200141a8056a41026a2209200141a00a6a41026a2d00003a0000200120012f00a00a3b01a80520014198076a41106a42a08080808004370300200141003a00b007200120053602a407200142a0808080800437029c072001200c36029807200141b3076a20092d00003a0000200120012f01a8053b00b107200141a00a6a20014198076a10c7010240024020012802a00a4101470d00200141c8056a41186a2205200141bc0a6a290200370300200141c8056a41106a200141b40a6a290200370300200141c8056a41086a200141ac0a6a290200370300200120012902a40a3703c805412010332203450d04200320012903c805370000200341186a2005290300370000200341106a200141c8056a41106a220d290300370000200341086a200141c8056a41086a220e29030037000020014281808080103702a408200120033602a008200141f8056a41186a20014198076a41186a280200360200200141f8056a41106a20014198076a41106a290300370300200141f8056a41086a20014198076a41086a29030037030020012001290398073703f805200141a00a6a200141f8056a10c70141012109024020012802a00a4101470d00200141a00a6a410472210541022109412021044101210c0340200141a0096a41186a200541186a2902002206370300200141a0096a41106a200541106a2902002208370300200141a0096a41086a200541086a290200220b3703002001200529020022183703a009200141c8056a41186a220a2006370300200d2008370300200e200b370300200120183703c80502402009417f6a200c470d00200141a0086a200c4101108a0120012802a00821030b200320046a220c20012903c805370000200c41186a200a290300370000200c41106a200d290300370000200c41086a200e290300370000200120093602a808200141a00a6a200141f8056a10c70120012802a00a4101470d01200441206a2104200941016a210920012802a408210c0c000b0b024020012802fc05450d0020012802f80510350b024020014188066a280200450d0020012802840610350b20012802a40841ffffff3f7121130c010b0240200128029c07450d0020012802980710350b4100211341012103024020012802a807450d0020012802a40710350b410021090b41f7edcb00ad4280808080f00084100122052900002106200141a00a6a41086a220c200541086a290000370300200120063703a00a2005103541cca9c000ad4280808080a00184100122052900002106200141a0096a41086a2204200541086a290000370300200120063703a00920051035412010332205450d02200520012903a00a370000200520012903a009370010200541086a200c290300370000200541186a220d200429030037000041201033220c450d02200c2005290000370000200c41186a200d290000370000200c41106a200541106a290000370000200c41086a200541086a290000370000200141e8056a41026a2204200141a00a6a41026a2d00003a0000200120012f00a00a3b01e80520014198076a41106a42a08080808004370300200141003a00b007200120053602a407200142a0808080800437029c072001200c36029807200141b3076a20042d00003a0000200120012f01e8053b00b107200141a00a6a20014198076a10c9050240024020012d00d00a4102460d00200141c8056a41186a200141a00a6a41186a290300370300200141c8056a41106a200141a00a6a41106a290300370300200141c8056a41086a200141a00a6a41086a290300370300200120012903a00a3703c805024020012802c40a41ffffff3f71450d0020012802c00a10350b412010332210450d04201020012903c805370000201041186a200141c8056a41186a220d290300370000201041106a200141c8056a41106a220e290300370000201041086a200141c8056a41086a220a29030037000020014281808080103702a408200120103602a008200141f8056a41186a20014198076a41186a280200360200200141f8056a41106a20014198076a41106a290300370300200141f8056a41086a20014198076a41086a29030037030020012001290398073703f805200141a00a6a200141f8056a10c905024020012d00d00a4102460d00412021044101210c0340200141a0096a41186a2205200141a00a6a41186a290300370300200141a0096a41106a220f200141a00a6a41106a290300370300200141a0096a41086a2212200141a00a6a41086a290300370300200120012903a00a3703a009024020012802c40a41ffffff3f71450d0020012802c00a10350b200d2005290300370300200e200f290300370300200a2012290300370300200120012903a0093703c8050240200c20012802a408470d00200141a0086a200c4101108a0120012802a00821100b201020046a220520012903c805370000200541186a200d290300370000200541106a200e290300370000200541086a200a2903003700002001200c41016a220c3602a808200441206a2104200141a00a6a200141f8056a10c90520012d00d00a4102470d000b0b024020012802fc05450d0020012802f80510350b024020014188066a280200450d0020012802840610350b200141a8056a41086a200141a0086a41086a280200360200200120012903a0083703a8050c010b200141003602b005200142013703a8050240200128029c07450d0020012802980710350b20012802a807450d0020012802a40710350b0240200941808004490d00024020012802ac0541ffffff3f71450d0020012802a80510350b2013450d01200310350c010b20094105742205417f4c0d010240024020090d00200141003602a80a200142013703a00a200141a00a6a41004100108a0120012802a80a210c20012802a00a210d0c010b200510332205450d03200141003602a80a200120093602a40a200120053602a00a200141a00a6a41002009108a012009410574210420012802a00a220d20012802a80a220e4105746a21052003210c03402005200c290000370000200541186a200c41186a290000370000200541106a200c41106a290000370000200541086a200c41086a290000370000200541206a2105200c41206a210c200441606a22040d000b2001200941057441606a410576200e6a41016a220c3602a80a0b20012802a40a2105200141a8056a20012802b005200c410574220c4105752204108a0120012802a805220f20012802b005220e4105746a200d200c109d081a2001200e20046a22123602b0050240200541ffffff3f71450d00200d10350b20014198076a41186a220c420037030020014198076a41106a2204420037030020014198076a41086a22054200370300200142003703980741f7edcb00ad4280808080f0008422061001220e2900002108200141a00a6a41086a220d200e41086a290000370300200120083703a00a200e10352005200d290300370300200120012903a00a370398074192aac000ad4280808080a002841001220a2900002108200141a0096a41086a220e200a41086a290000370300200120083703a009200a1035200720012903a009370000200741086a220a200e290300370000200141f8056a41086a22102005290300370300200141f8056a41106a22142004290300370300200141f8056a41186a2215200c29030037030020012001290398073703f805200141203602a40a2001200141f8056a3602a00a20032009200141a00a6a10980202402013450d00200310350b20012802ac052103200c4200370300200442003703002005420037030020014200370398072006100122092900002106200d200941086a290000370300200120063703a00a200910352005200d290300370300200120012903a00a3703980741a4aac000ad4280808080a00284100122092900002106200e200941086a290000370300200120063703a00920091035200720012903a009370000200a200e29030037000020102005290300370300201420042903003703002015200c29030037030020012001290398073703f805200141203602a40a2001200141f8056a3602a00a200f2012200141a00a6a1098020240200341ffffff3f71450d00200f10350b20014198076a41186a2209420037030020014198076a41106a2204420037030020014198076a41086a22054200370300200142003703980741f7edcb00ad4280808080f000841001220c2900002106200141a00a6a41086a2203200c41086a290000370300200120063703a00a200c103520052003290300370300200120012903a00a3703980741b6aac000ad42808080809002841001220c2900002106200141a0096a41086a2203200c41086a290000370300200120063703a009200c1035200720012903a009370000200741086a2003290300370000200141f8056a41086a2005290300370300200141f8056a41106a2004290300370300200141f8056a41186a200929030037030020012001290398073703f805410110332205450d04200541013a000020054101410510372205450d0420052000360001200141f8056aad42808080808004842005ad4280808080d000841002200510350b02400240200041044b0d00200141a8056a21030c010b200141c8056a41186a4200370300200141c8056a41106a220c4200370300200141c8056a41086a22054200370300200142003703c8054193d1cb00ad4280808080a001841001220729000021062005200741086a290000370300200120063703c8052007103541e0caca00ad4280808080e0008410012207290000210620014198076a41086a2209200741086a290000370300200120063703980720071035200c2001290398072206370300200141a0096a41086a2005290300370300200141a0096a41106a2006370300200141a0096a41186a2009290300370300200120012903c8053703a009200141a00a6a200141a0096a10b60220012802a00a2205410420051b210d0240024020012902a40a420020051b2206422088a7220941c4006c22050d00410021040c010b2000417b6a210c200d20056a210741002104200d210502400340024020052d00004101460d00200541046a280200200c4f0d020b200441016a21042007200541c4006a2205470d000b0b200420094b0d040b200920046b210e200642ffffffff0f832106200d200441c4006c22076a2103200d210c02400340024020070d00200321050c020b200741bc7f6a2107200c2d00002109200c41c4006a2205210c20094102470d000b0b0240034020032005460d0120052d00002107200541c4006a210520074102470d000b0b0240200e450d0002402004450d00200d200d200441c4006c6a200e41c4006c109e081a0b200ead42208620068421060b200141c8056a41186a4200370300200141c8056a41106a220c4200370300200141c8056a41086a22054200370300200142003703c8054193d1cb00ad4280808080a00184100122072900002108200141e8056a41086a2209200741086a290000370300200120083703e8052007103520052009290300370300200120012903e8053703c80541e0caca00ad4280808080e00084100122072900002108200141f8056a41086a2209200741086a290000370300200120083703f80520071035200c20012903f8052208370300200141a8056a41086a2005290300370300200141a8056a41106a2008370300200141a8056a41186a2009290300370300200120012903c8053703a805200141a00a6a200d2006422088a710e006200141a8056aad428080808080048420013502a80a42208620012802a00a2207ad8410022006a72105024020012802a40a450d00200710350b200141a8056a21032005450d00200541c4006c450d00200d10350b200141c8056a41186a22044200370300200141c8056a41106a220c4200370300200141c8056a41086a22074200370300200142003703c8054193d1cb00ad4280808080a00184100122052900002106200141e8056a41086a2209200541086a290000370300200120063703e8052005103520072009290300370300200120012903e8053703c805419dd1cb00ad4280808080c00184100122052900002106200141f8056a41086a2209200541086a290000370300200120063703f80520051035200c20012903f8052206370300200141a8056a41086a2007290300370300200141a8056a41106a2006370300200141a8056a41186a2009290300370300200120012903c8053703a805200141003a00d00b2003ad4280808080800484200141d00b6aad428080808010841002200141f8056a10d0042004200141f8056a41186a2203290300370300200c200141f8056a41106a220d29030037030020072009290300370300200120012903f8053703c805412410332205450d03200520012903c80537000020054114360220200541186a2004290300370000200541106a200c290300370000200541086a200729030037000020014281808080103702a40a200120053602a00a200141a00a6a10ab01200141a00a6a41186a2003290300370300200141a00a6a41106a200d290300370300200141a00a6a41086a2009290300370300200120012903f8053703a00a200141a00a6a10d30410ff03200141f00b6a240020020f0b1044000b1045000b20042009104f000b103c000bb10503027f017e047f230041d0006b2202240041a29bc800ad4280808080f00084100122032900002104200241086a41086a200341086a290000370300200220043703082003103541f0bbc800ad4280808080f00084100122032900002104200241186a41086a200341086a29000037030020022004370318200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad42808080808004841003220129000037033820011035200241cc006a200341206a360200200220033602482002200241386a41086a3602442002200241386a360240200241286a200241c0006a107b200310352002280230220541206a2201417f4c0d01200228022821060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a2000200136020820002008360204200020033602000240200228022c450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000bb10503027f017e047f230041d0006b2202240041a29bc800ad4280808080f00084100122032900002104200241086a41086a200341086a290000370300200220043703082003103541cebbc800ad4280808080800284100122032900002104200241186a41086a200341086a29000037030020022004370318200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad42808080808004841003220129000037033820011035200241cc006a200341206a360200200220033602482002200241386a41086a3602442002200241386a360240200241286a200241c0006a107b200310352002280230220541206a2201417f4c0d01200228022821060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a2000200136020820002008360204200020033602000240200228022c450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000bb10503027f017e047f230041d0006b2202240041a29bc800ad4280808080f00084100122032900002104200241086a41086a200341086a290000370300200220043703082003103541c7bbc800ad4280808080f00084100122032900002104200241186a41086a200341086a29000037030020022004370318200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad42808080808004841003220129000037033820011035200241cc006a200341206a360200200220033602482002200241386a41086a3602442002200241386a360240200241286a200241c0006a107b200310352002280230220541206a2201417f4c0d01200228022821060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a2000200136020820002008360204200020033602000240200228022c450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000b130020004103360204200041ccbcc8003602000b3400200041d5c3c80036020420004100360200200041146a4101360200200041106a41dcc3c800360200200041086a42043702000b910101057f230041206b22022400200241186a22034200370300200241106a22044200370300200241086a220542003703002002420037030002404120103322060d001045000b20062002290300370000200042a0808080800437020420002006360200200641186a2003290300370000200641106a2004290300370000200641086a2005290300370000200241206a24000b13002000410c36020420004180c7c8003602000b3400200041a29bc80036020420004100360200200041146a4110360200200041106a4180a3c900360200200041086a42073702000b130020004107360204200041c8b8c9003602000b3501017f02404108103322020d001045000b20004288808080800137020420002002360200200242f0f2bd99f7edd8b4e5003700000b2e01017f02404104103322020d001045000b20004284808080c0003702042000200236020020024180ee053600000b3b01017f02404110103322020d001045000b20024200370008200242808094f6c2d7e8d800370000200042908080808002370204200020023602000b2c01017f02404104103322020d001045000b20004284808080c000370204200020023602002002410a3600000b13002000410836020420004188c2c9003602000b340020004186f0cb0036020420004100360200200041146a4105360200200041106a41a0ebc900360200200041086a42083702000b130020004109360204200041e0f4c9003602000b3501017f02404108103322020d001045000b20004288808080800137020420002002360200200242f0f2bda1a7ee9cb9f9003700000b2b01017f02404101103322020d001045000b200042818080801037020420002002360200200241143a00000b2e01017f02404104103322020d001045000b20004284808080c0003702042000200236020020024180e1013600000b2e01017f02404104103322020d001045000b20004284808080c00037020420002002360200200241a0c21e3600000b2e01017f02404104103322020d001045000b20004284808080c00037020420002002360200200241d086033600000b900a030a7f027e017f230041106b220224002002410036020820024201370300024002400240412010332203450d002003200029004c370000200341186a2204200041e4006a290000370000200341106a2205200041dc006a290000370000200341086a2206200041d4006a290000370000412010332207450d02200241203602042002200736020020072003290000370000200741086a2006290000370000200741106a2005290000370000200741186a200429000037000020024120360208200310352007412041c00010372203450d022003200029006c370020200341286a200041f4006a290000370000200341306a200041fc006a290000370000200341386a20004184016a29000037000020022003360200200242c080808080083702040240024020002903004201510d00200341c00041800110372203450d04200341003a004020024180013602042002200336020041c10021070c010b200341c00041800110372203450d03200341013a00402003200041086a2207290000370041200341e9006a200041306a2903003700002003200041286a290300370061200341c9006a200741086a290000370000200341d1006a200741106a290000370000200341d9006a200741186a2900003700002002200336020020024280818080900c37020441f10021070b200220073602080240024020002802384101460d00200320076a41003a0000200741016a21030c010b200320076a41013a00002002200741016a22033602082000413c6a2802002106024002402002280204220520036b4104490d00200228020021040c010b41000d0320054101742204200341046a2208200420084b1b22084100480d030240024020050d002008103322040d010c060b2002280200210420052008460d0020042005200810372204450d050b20022008360204200220043602000b200420036a2006360000200741056a21030b2002200336020820002802402109200041c8006a2802002200200210770240024020000d002002280208210020022802042107200228020021050c010b2009200041306c6a210a41002002280208220b6b210620022802042107410021030340200b20036a210802400240200720066a4120490d0020022802002105200721040c010b200841206a22002008490d04200741017422042000200420004b1b22044100480d040240024020070d00024020040d00410121050c020b200410332205450d070c010b2002280200210520072004460d0020052007200410372205450d060b20022004360204200220053602000b2005200b6a20036a2207200920036a2200290000370000200741186a200041186a290000370000200741106a200041106a290000370000200741086a200041086a2900003700002002200841206a2207360208200041286a290300210c200041206a290300210d02400240200420066a41606a410f4d0d00200421070c010b200741106a220e2007490d0420044101742207200e2007200e4b1b22074100480d040240024020040d00024020070d00410121050c020b200710332205450d070c010b20042007460d0020052004200710372205450d060b20022007360204200220053602000b2005200b6a20036a220441286a200c370000200441206a200d3700002002200841306a360208200641506a2106200341306a2103200a200041306a470d000b200b20036a21000b20012902002000ad4220862005ad84100202402007450d00200510350b200241106a24000f0b1045000b103e000b103c000b990907027f027e017f017e027f047e047f230041306b2203240002400240024002400240024020002802002d0000200141ff0171460d0020002802082104200341206a200210b806200341106a20032802202201200328022810b4024200210520032902144200200328021022001b210602402003280224450d00200110350b2000410820001b2107428080d287e2bc2d210802402006422088a72209450d0002400240200941186c22000d0042002105428080d287e2bc2d2108410021010c010b200720006a210a4200210b428080d287e2bc2d210c4100210120072100024003400240200c200041086a290300220d7d2208200c56200b200041106a290300220e7d200c200d54ad7d2205200b562005200b511b450d00200041086a200d200c7d370300200041106a200e200b7d200d200c54ad7d37030042002108420021050c020b200141016a21012008210c2005210b200a200041186a2200470d000b0b200120094b0d030b200341106a200210b806200920016b220a41186c4104722200417f4c0d032003350218210d2003280210210f200010332210450d04200341003602282003200036022420032010360220200a200341206a10770240024020012009470d002003280228210020032802242101200328022021090c010b2007200141186c6a21102007200941186c6a2111200328022421012003280228210003402010280200211202400240200120006b4104490d00200328022021092001210a0c010b200041046a220a2000490d0820014101742209200a2009200a4b1b220a4100480d080240024020010d000240200a0d00410121090c020b200a103322090d010c0b0b200328022021092001200a460d0020092001200a10372209450d0a0b2003200a360224200320093602200b200920006a20123600002003200041046a2212360228201041106a290300210c201041086a290300210b02400240200a20126b4110490d00200041146a2100200a21010c010b201241106a22002012490d08200a41017422012000200120004b1b22014100480d0802400240200a0d00024020010d00410121090c020b200110332209450d0b0c010b200a2001460d002009200a200110372209450d0a0b20032001360224200320093602200b200920126a220a200c370008200a200b37000020032000360228201041186a22102011470d000b0b200d422086200fad842000ad4220862009ad84100202402001450d00200910350b2003280214450d00200f10350b2008428080d287e2bc2d56ad210c02402006a72200450d00200041186c450d00200710350b2005200c7c210b200341206a200210ba06200341086a200328022022002003280228220110c0012003200328020c41016a410120032802081b220a3602102001ad4220862000ad84200341106aad4280808080c00084100202402003280224450d00200010350b428080d287e2bc2d20087d210c4200200b7d210b0240200a410a490d00200210b4060b2004200c20042903007c2205370300200441086a2200200b20002903007c2005200c54ad7c370300410021020b200341306a240020020f0b2001200941ac82ca001059000b1044000b1045000b103e000b103c000bb10503027f017e047f230041d0006b2202240041a29bc800ad4280808080f00084100122032900002104200241086a41086a200341086a290000370300200220043703082003103541e0aec900ad4280808080b00284100122032900002104200241186a41086a200341086a29000037030020022004370318200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad42808080808004841003220129000037033820011035200241cc006a200341206a360200200220033602482002200241386a41086a3602442002200241386a360240200241286a200241c0006a107b200310352002280230220541206a2201417f4c0d01200228022821060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a2000200136020820002008360204200020033602000240200228022c450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000bb10503027f017e047f230041d0006b2202240041a29bc800ad4280808080f00084100122032900002104200241086a41086a200341086a290000370300200220043703082003103541acb0c900ad4280808080800184100122032900002104200241186a41086a200341086a29000037030020022004370318200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad42808080808004841003220129000037033820011035200241cc006a200341206a360200200220033602482002200241386a41086a3602442002200241386a360240200241286a200241c0006a107b200310352002280230220541206a2201417f4c0d01200228022821060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a2000200136020820002008360204200020033602000240200228022c450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000b802304057f017e037f037e230041c0036b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802000e1c00011302030405060708090a0b0c0d0e0f1011121313131415161713000b20024180016a200141086a109d0320004100360200200041106a20024180016a41086a290300370300200041086a2002290380013703000c170b20024180016a200141046a109a03200041013602002000413c6a200241b8016a280200360200200041346a200241b0016a2903003702002000412c6a200241a8016a290300370200200041246a200241a0016a2903003702002000411c6a20024198016a290300370200200041146a20024190016a2903003702002000410c6a20024188016a29030037020020002002290380013702040c160b20004103360200200041086a200141086a2903003703000c150b20024180016a200141046a109e03200041043602002000410c6a20024188016a28020036020020002002290380013702040c140b02400240024002400240024020012d0004417f6a220341034b0d00200141046a210420030e0401020304010b41cfa2cc00412841c086cc00103f000b200141086a2802002103410121050c030b41022105200241026a200441036a2d00003a000020024180016a41086a200141146a29020037030020024190016a2001411c6a29020037030020024198016a200141246a2d00003a0000200220042f00013b010020022001410c6a29020037038001200141086a2802002103200141286a28020021010c020b200141086a2802002103410321050c010b200241026a200441036a2d00003a000020024180016a41086a200141146a29020037030020024190016a2001411c6a29020037030020024198016a200141246a2d00003a0000200220042f00013b010020022001410c6a29020037038001200141086a2802002103200141286a2802002101410421050b200020053a0004200020022f01003b000520004105360200200041086a20033602002000410c6a200229038001370200200041286a2001360200200041076a200241026a2d00003a0000200041146a20024180016a41086a2903003702002000411c6a20024190016a290300370200200041246a20024198016a2802003602000c130b20024180016a200141086a108503200041086a20024180016a41e000109d081a200041063602000c120b20024180016a200141086a108702200041086a20024180016a418802109d081a200041073602000c110b02400240200128020422060d00410021030c010b20024180016a41186a200141286a29000037030020024180016a41106a200141206a29000037030020024188016a200141186a29000037030020024180016a41286a200141386a29000037030020024180016a41306a200141c0006a29000037030020024180016a41386a200141c8006a29000037030020024180016a41c8006a200141d8006a29000037030020024180016a41d0006a200141e0006a29000037030020024180016a41d8006a200141e8006a2900003703002002200141106a290000370380012002200141306a2900003703a0012002200141d0006a2900003703c00120024180016a41f8006a20014188016a29000037030020024180016a41f0006a20014180016a29000037030020024180016a41e8006a200141f8006a2900003703002002200141f0006a2900003703e0012001410c6a2802002201417f4c0d120240024020010d0041002105410121030c010b200110332203450d14200121050b0240024020052001490d00200521040c010b200541017422042001200420014b1b22044100480d15024020050d002004103322030d010c170b20052004460d0020032005200410372203450d160b200320062001109d081a200220024180016a418001109d081a2001ad4220862004ad8421070b20002003360204200041086a2007370200200041106a2002418001109d081a200041083602000c100b20024180016a200141086a10a00320004109360200200041386a20024180016a41306a290300370300200041306a20024180016a41286a290300370300200041286a20024180016a41206a290300370300200041206a20024180016a41186a290300370300200041186a20024180016a41106a290300370300200041106a20024180016a41086a290300370300200041086a2002290380013703000c0f0b20024180016a200141046a10a1032000410a3602002000412c6a200241a8016a290300370200200041246a200241a0016a2903003702002000411c6a20024198016a290300370200200041146a20024190016a2903003702002000410c6a20024188016a29030037020020002002290380013702040c0e0b20024180016a200141046a10a1032000410b3602002000412c6a200241a8016a290300370200200041246a200241a0016a2903003702002000411c6a20024198016a290300370200200041146a20024190016a2903003702002000410c6a20024188016a29030037020020002002290380013702040c0d0b20024180016a200141086a1086032000410c360200200041286a20024180016a41206a290300370300200041206a20024180016a41186a290300370300200041186a20024180016a41106a290300370300200041106a20024180016a41086a290300370300200041086a2002290380013703000c0c0b0240024002400240024002400240024020012d0004417f6a220441064b0d00200141046a21034107210520040e0701020304050607010b41cfa2cc00412841c086cc00103f000b20024198016a200341196a29000037030020024190016a200341116a29000037030020024188016a200341096a2900003703002002200329000137038001410121050c050b20024198016a200341196a29000037030020024190016a200341116a29000037030020024188016a200341096a2900003703002002200329000137038001410221050c040b20024180016a41186a200341196a29000037030020024180016a41106a200341116a29000037030020024180016a41086a200341096a290000370300200241086a200341296a290000370300200241106a200341316a290000370300200241186a200341396a29000037030020022003290001370380012002200341216a290000370300410321050c030b200141106a280200220841ffffff3f712008470d0f20084105742203417f4c0d0f200141086a28020021040240024020030d00410121050c010b200310332205450d110b41002101200241003602082002200536020020022003410576360204200241002008108a012002280208210902402008450d0020084105742106200228020020094105746a210a0340200a20016a2203200420016a2205290000370000200341186a200541186a290000370000200341106a200541106a290000370000200341086a200541086a2900003700002006200141206a2201470d000b200841057441606a41057620096a41016a21090b2002418b016a20093600002002200229030037008301410421050c020b20024198016a200341196a29000037030020024190016a200341116a29000037030020024188016a200341096a2900003703002002200329000137038001410521050c010b20024198016a200341196a29000037030020024190016a200341116a29000037030020024188016a200341096a2900003703002002200329000137038001410621050b200020053a0004200020022903800137000520002002290300370025200020022f00bc033b00452000410d6a20024180016a41086a290300370000200041156a20024180016a41106a2903003700002000411d6a20024180016a41186a2903003700002000412d6a200241086a290300370000200041356a200241106a2903003700002000413d6a200241186a290300370000200041c7006a200241be036a2d00003a00002000410d3602000c0b0b2000410e360200200020012802043602040c0a0b2001410c6a2802002203417f4c0d0a200128020421060240024020030d0041002101410121040c010b200310332204450d0c200321010b0240024020012003490d00200121050c010b200141017422052003200520034b1b22054100480d0d024020010d00200510332204450d0f0c010b20012005460d0020042001200510372204450d0e0b200420062003109d0821012000410c6a2003360200200041086a2005360200200020013602042000410f3602000c090b20024180016a200141086a10a30320004110360200200041c0006a20024180016a41386a290300370300200041386a20024180016a41306a290300370300200041306a20024180016a41286a290300370300200041286a20024180016a41206a290300370300200041206a20024180016a41186a290300370300200041186a20024180016a41106a290300370300200041106a20024180016a41086a290300370300200041086a2002290380013703000c080b20024180016a200141086a10a403200041086a20024180016a419801109d081a200041113602000c070b20024180016a200141046a10a503200041123602002000412c6a200241a8016a280200360200200041246a200241a0016a2903003702002000411c6a20024198016a290300370200200041146a20024190016a2903003702002000410c6a20024188016a29030037020020002002290380013702040c060b20024180016a200141046a10de04200041046a20024180016a41e800109d081a200041133602000c050b10a703000b20024180016a200141086a10a803200041086a20024180016a41a802109d081a200041173602000c030b20024180016a200141086a10a903200041086a20024180016a41c800109d081a200041183602000c020b20024180016a200141046a10aa03200041046a20024180016a41c400109d081a200041193602000c010b0240024002400240200141086a280200417f6a220a41024b0d0041012105200a0e03030102030b41cfa2cc00412841c086cc00103f000b41012103024002402001410c6a22052d00004101470d00200141106a28020021060c010b200241be036a200541036a2d00003a000020024188016a2001411c6a29020037030020024180016a41106a200141246a29020037030020024198016a2001412c6a2d00003a0000200220052f00013b01bc032002200141146a29020037038001200141106a2802002106410021030b41022105200241ac036a41026a200241bc036a41026a2d00003a0000200241086a20024180016a41086a290300370300200241106a20024180016a41106a290300370300200241186a20024180016a41186a280200360200200220022f01bc033b01ac0320022002290380013703000c010b41012103024002402001410c6a22052d00004101470d00200141106a28020021060c010b200241be036a200541036a2d00003a000020024188016a2001411c6a29020037030020024180016a41106a200141246a29020037030020024198016a2001412c6a2d00003a0000200220052f00013b01bc032002200141146a29020037038001200141106a2802002106410021030b200241ac036a41026a200241bc036a41026a2d00003a0000200241086a20024180016a41086a290300370300200241106a20024180016a41106a290300370300200241186a20024180016a41186a280200360200200220022f01bc033b01ac032002200229038001370300200141c8006a290300210b200141c0006a2903002107200141386a290300210c200141d0006a28020021042001290330210d410321050b200020022f01ac033b000d200041c8006a200b370300200041c0006a2007370300200041386a200c370300200041306a200d3703002000410c6a20033a0000200041086a2005360200200041106a2006360200200041146a2002290300370200200041d0006a20043602002000410f6a200241ae036a2d00003a00002000411c6a200241086a290300370200200041246a200241106a2903003702002000412c6a200241186a2802003602002000411a3602000b200241c0036a24000f0b1044000b1045000b103e000b103c000b9f0303027f017e027f230041206b220224004186f0cb00ad4280808080800184100122032900002104200241086a200341086a290000370300200220043703002003103541c0f0c900ad4280808080f00084100122032900002104200241106a41086a200341086a29000037030020022004370310200310350240412010332203450d0020032001290000370000200341186a2205200141186a290000370000200341106a2206200141106a290000370000200341086a200141086a290000370000412010332201450d0020012003290000370000200141186a2005290000370000200141106a2006290000370000200141086a2205200341086a2900003700002003103541c00010332203450d002003200229031037001020032002290300370000200341086a200241086a290300370000200341186a200241106a41086a290300370000200042c080808080083702042000200336020020032001290000370020200341286a2005290000370000200341306a200141106a290000370000200341386a200141186a29000037000020011035200241206a24000f0b1045000bb10503027f017e047f230041d0006b220224004186f0cb00ad4280808080800184100122032900002104200241086a41086a200341086a290000370300200220043703082003103541d8efc900ad4280808080c00084100122032900002104200241186a41086a200341086a29000037030020022004370318200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad42808080808004841003220129000037033820011035200241cc006a200341206a360200200220033602482002200241386a41086a3602442002200241386a360240200241286a200241c0006a107b200310352002280230220541206a2201417f4c0d01200228022821060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a2000200136020820002008360204200020033602000240200228022c450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000bb10503027f017e047f230041d0006b220224004186f0cb00ad4280808080800184100122032900002104200241086a41086a200341086a290000370300200220043703082003103541d8efc900ad4280808080c00084100122032900002104200241186a41086a200341086a29000037030020022004370318200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad42808080808004841003220129000037033820011035200241cc006a200341206a360200200220033602482002200241386a41086a3602442002200241386a360240200241286a200241c0006a107b200310352002280230220541206a2201417f4c0d01200228022821060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a2000200136020820002008360204200020033602000240200228022c450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000b1300200041013602042000419083ca003602000bb31903077f027e067f230041a0026b22052400200028020021064100210702400240024002400240024002400240200041086a280200220841014b0d0020080e020201020b20082109034020072009410176220a20076a220b2006200b41e8006c6a220b41386a290300200256200b41c0006a290300220c200356200c2003511b1b21072009200a6b220941014b0d000b0b2006200741e8006c6a220941386a290300220d200285200941c0006a290300220c20038584500d012007200d200254200c200354200c2003511b6a21070b200541a0016a41086a200441086a290300370300200541a0016a41106a200441106a290300370300200541a0016a41186a200441186a290300370300200541a0016a41206a200441206a290300370300200541a0016a41286a200441286a290300370300200541a0016a41306a200441306a290300370300200541286a41086a200141086a290000370300200541286a41106a200141106a290000370300200541286a41186a200141186a290000370300200520042903003703a0012005200129000037032820082007490d0302402008200041046a280200470d00200020084101109601200028020021060b2006200741e8006c6a220941e8006a2009200820076b41e8006c109e081a200941c0006a200337030020092002370338200941306a200541a0016a41306a290300370300200941286a200541a0016a41286a290300370300200941206a200541a0016a41206a290300370300200941186a200541a0016a41186a290300370300200941106a200541a0016a41106a290300370300200941086a200541a0016a41086a290300370300200920052903a00137030020092005290328370348200941d0006a200541286a41086a290300370300200941d8006a200541286a41106a290300370300200941e0006a200541286a41186a290300370300200041086a200841016a22093602000c010b0240024002400240024020070d002006210a0c010b20082007417f6a22094d0d012006200941e8006c6a41e8006a210a0b200a2006200841e8006c6a460d00200820074d0d04200a290338200256200a41c0006a290300220c200356200c2003511b0d01200a41e8006a2109200841e8006c20066a200a6b41987f6a210a0340200a450d01200741016a21072009290338210c200941c0006a210b200a41987f6a210a200941e8006a2109200c200256200b290300220c200356200c2003511b0d020c000b0b200541286a41186a2209200141186a290000370300200541286a41106a220a200141106a290000370300200541286a41086a220b200141086a290000370300200541a0016a41086a220e200441086a290300370300200541a0016a41106a220f200441106a290300370300200541a0016a41186a2210200441186a290300370300200541a0016a41206a2211200441206a290300370300200541a0016a41286a2212200441286a290300370300200541a0016a41306a2213200441306a29030037030020052001290000370328200520042903003703a00102402008200041046a280200470d00200020084101109601200041086a2802002108200028020021060b2006200841e8006c6a22072002370338200720052903a00137030020072005290328370348200741c0006a2003370300200741306a2013290300370300200741286a2012290300370300200741206a2011290300370300200741186a2010290300370300200741106a200f290300370300200741086a200e290300370300200741d0006a200b290300370300200741d8006a200a290300370300200741e0006a20092903003703000c010b200541a0016a41086a200441086a290300370300200541a0016a41106a200441106a290300370300200541a0016a41186a200441186a290300370300200541a0016a41206a200441206a290300370300200541a0016a41286a200441286a290300370300200541a0016a41306a200441306a290300370300200541286a41086a200141086a290000370300200541286a41106a200141106a290000370300200541286a41186a200141186a290000370300200520042903003703a0012005200129000037032820082007490d0302402008200041046a280200470d00200020084101109601200028020021060b2006200741e8006c6a220941e8006a2009200820076b41e8006c109e081a200941c0006a200337030020092002370338200941306a200541a0016a41306a290300370300200941286a200541a0016a41286a290300370300200941206a200541a0016a41206a290300370300200941186a200541a0016a41186a290300370300200941106a200541a0016a41106a290300370300200941086a200541a0016a41086a290300370300200920052903a00137030020092005290328370348200941d0006a200541286a41086a290300370300200941d8006a200541286a41106a290300370300200941e0006a200541286a41186a2903003703000b200041086a200841016a22093602000b0240200941e907490d00200041086a2009417f6a22093602002006200941e8006c6a220741106a2903002103200741086a290300210c20072d0000210a20072800012101200741046a280000210e20054180016a41186a220b200741306a29030037030020054180016a41106a2204200741286a29030037030020054180016a41086a2208200741206a290300370300200741186a2903002102200541a0016a41286a220f200741e0006a290300370300200541a0016a41206a2210200741d8006a2903003703002005200237038001200541a0016a41186a2211200741d0006a290300370300200541a0016a41106a2212200741c8006a290300370300200541a0016a41086a2213200741c0006a2903003703002005200e36000320052001360200200520072903383703a001200a4102460d03200541d8006a41086a22072008290300370300200541d8006a41106a22012004290300370300200541d8006a41186a220e200b290300370300200541286a41086a2013290300370300200541286a41106a22132012290300370300200541286a41186a22122011290300370300200541286a41206a22112010290300370300200541286a41286a2210200f2903003703002005200528000336007b200520052802003602782005200529038001370358200520052903a001370328200541186a2010290300370300200541106a2011290300370300200541086a201229030037030020052013290300370300200520052802783602202005200528007b3600232008200729030037030020042001290300370300200b200e290300370300200520052903583703800102400240200a410171450d00200541af016a2003370000200541bf016a20054188016a2d00003a00002005200c3700a701200520052800233600a301200520052802203602a00120052005290380013700b701200541286a200541a0016a10d006200535023042208620052802282207ad841007200528022c450d01200710350c010b2005200c37035820052003370360200c200384500d0020052005360278200541286a2005200541d8006a200541f8006a10f00220052903284201520d0020052903302103200541d8016a200541286a41106a290300370300200541d0016a2003370300200541a0016a41086a41003a0000200541a9016a2005290300370000200541b1016a200541086a290300370000200541b9016a200541106a290300370000200541c1016a200541186a290300370000200541033a00a00141b0b4cc004100200541a0016a10d4010b200541a0016a41086a41033a0000200541a9016a2005290300370000200541b1016a200541086a290300370000200541b9016a200541106a290300370000200541c1016a200541186a290300370000200541123a00a00141b0b4cc004100200541a0016a10d4010b2000280204210b200541a0016a41186a4200370300200541a0016a41106a22044200370300200541a0016a41086a22074200370300200542003703a00141a29bc800ad4280808080f000841001220a29000021032007200a41086a290000370300200520033703a001200a1035419cbac800ad4280808080c000841001220a290000210320054180016a41086a2200200a41086a2900003703002005200337038001200a103520042005290380012203370300200541286a41086a2007290300370300200541286a41106a2003370300200541286a41186a2000290300370300200520052903a001370328200541a0016a2006200910b106200541286aad428080808080048420053502a80142208620052802a0012207ad841002024020052802a401450d00200710350b0240200b450d00200b41e8006c450d00200610350b200541a0026a24000f0b2007200841f483ca001042000b20072008104d000b418484ca004113419884ca001064000b810b031d7f017e017f230041b0016b2202240041012103024020012d00000d002001411d6a2d000021042001411c6a2d000021052001411a6a2f00002106200141196a2d00002107200141186a2d00002108200141166a2f00002109200141156a2d0000210a200141146a2d0000210b200141126a2f0000210c200141116a2d0000210d200141106a2d0000210e2001410e6a2f0000210f2001410d6a2d000021102001410c6a2d000021112001410a6a2f00002112200141096a2d00002113200141086a2d00002114200141066a2f00002115200141056a2d00002116200141046a2d00002117200141026a2f0000211820012d00012103200141206a2d00002119200141216a2d0000211a2001411e6a2f0000211b20024190016a41186a221c420037030020024190016a41106a221d420037030020024190016a41086a22014200370300200242003703900141a29bc800ad4280808080f000841001221e290000211f2001201e41086a2900003703002002201f37039001201e103541ef9bc800ad4280808080f000841001221e290000211f200241c8006a41086a2220201e41086a2900003703002002201f370348201e1035201d2002290348221f370300200241f0006a41086a2001290300370300200241f0006a41106a201f370300200241f0006a41186a20202903003703002002200229039001370370200241c8006a200241f0006a412010d50120022d0048211e201c200241c8006a41196a290000370300201d200241c8006a41116a2900003703002001200241c8006a41096a2900003703002002200229004937039001410021010240201e4101470d00200241f0006a41186a20024190016a41186a290300370300200241f0006a41106a20024190016a41106a290300370300200241f0006a41086a20024190016a41086a2903003703002002200229039001370370410121010b200241206a201a3a00002002411f6a20193a00002002411d6a201b3b00002002411c6a20043a00002002411b6a20053a0000200241196a20063b0000200241186a20073a0000200241176a20083a0000200241156a20093b0000200241146a200a3a0000200241136a200b3a0000200241116a200c3b0000200241106a200d3a00002002410f6a200e3a00002002410d6a200f3b00002002410c6a20103a00002002410b6a20113a0000200241096a20123b0000200241086a20133a0000200220013a0021200220143a0007200220153b0005200220163a0004200220173a0003200220183b0001200220033a00002002413a6a200241f0006a41186a290300370100200241326a200241f0006a41106a2903003701002002412a6a200241f0006a41086a290300370100200241226a221d20022903703701000240200341ff01714101470d002001450d0020024101722201201d412010a0080d00200241c8006a41026a200141026a2d000022033a0000200220012f000022013b01482002410a6a2f0100211d2002410e6a2f0100211e200241126a2f01002105200241166a2f010021082002411a6a2f0100210b2002411e6a2f0100210e20022f01062111200041036a20033a0000200020013b0001200041206a201a3a00002000411e6a200e3b00002000411d6a201b3a00002000411c6a20043a00002000411a6a200b3b0000200041196a20063a0000200041186a20073a0000200041166a20083b0000200041156a20093a0000200041146a200a3a0000200041126a20053b0000200041116a200c3a0000200041106a200d3a00002000410e6a201e3b00002000410d6a200f3a00002000410c6a20103a00002000410a6a201d3b0000200041096a20123a0000200041086a20133a0000200041066a20113b0000200041056a20153a0000200041046a20163a0000410021030c010b410121030b200020033a0000200241b0016a24000bba0a03047f017e057f230041f0006b22022400200241c0006a41186a4200370300200241c0006a41106a22034200370300200241c0006a41086a220442003703002002420037034041a29bc800ad4280808080f000841001220529000021062004200541086a29000037030020022006370340200510354189eaca00ad4280808080f00084100122052900002106200241e0006a41086a2207200541086a2900003703002002200637036020051035200320022903602206370300200241206a41086a2004290300370300200241206a41106a2006370300200241206a41186a200729030037030020022002290340370320200241c0006a200241206a10fe0102400240200228024022080d00410021092002410036021820024201370310410121084100210a0c010b200220022902442206370214200220083602102006422088a7210a2006a721090b200241c0006a41186a4200370300200241c0006a41106a220b4200370300200241c0006a41086a220542003703002002420037034041a29bc800ad4280808080f00084100122032900002106200241e0006a41086a2204200341086a2900003703002002200637036020031035200520042903003703002002200229036037034041a99bc800ad4280808080a001841001220329000021062004200341086a2900003703002002200637036020031035200b20022903602206370300200241206a41086a2005290300370300200241206a41106a2006370300200241206a41186a200429030037030020022002290340370320200241086a200241206a412010c00141002104024002400240024002400240200a200228020c410020022802081b4f0d00024002400240200a41014b0d00200a0e020201020b41002104200a210503402005410176220320046a22072004200820074105746a2001412010a0084101481b2104200520036b220541014b0d000b0b200820044105746a2001412010a0082205450d022005411f7620046a21040b200241c0006a41186a200141186a290000370300200241c0006a41106a200141106a290000370300200241c0006a41086a200141086a29000037030020022001290000370340200a2004490d040240200a2009470d00200241106a20094101108a0120022802142109200228021021080b200820044105746a220541206a2005200a20046b410574109e081a20052002290340370000200541186a200241c0006a41186a2203290300370000200541106a200241c0006a41106a2207290300370000200541086a200241c0006a41086a22042903003700002002200a41016a220a3602182003420037030020074200370300200442003703002002420037034041a29bc800ad4280808080f00084100122012900002106200241e0006a41086a2205200141086a290000370300200220063703602001103520042005290300370300200220022903603703404189eaca00ad4280808080f000841001220129000021062005200141086a2900003703002002200637036020011035200b2002290360370000200b41086a2005290300370000200241206a41086a2004290300370300200241206a41106a2007290300370300200241206a41186a200329030037030020022002290340370320200241203602442002200241206a3602402008200a200241c0006a109802200941ffffff3f710d020c030b20004183323b0100200041086a410a360200200041046a41a99bc800360200200041026a410f3a0000200941ffffff3f71450d04200810350c040b200941ffffff3f71450d010b200810350b200041043a00000c010b2004200a104d000b200241f0006a24000b130020004108360204200041a884ca003602000b130020004112360204200041c089ca003602000b8c0201037f024002400240024002400240024020012802000e0400010203000b41012102410110332201450d05200141003a0000410121030c040b410110332202450d04200241013a00002001280204210320024101410510372202450d042002200336000120012802082104410a210320024105410a10372201450d04200120043600050c020b41012102410110332201450d03200141023a0000410121030c020b410110332202450d02200241033a00002001280204210320024101410510372202450d022002200336000120012802082104410a210320024105410a10372201450d02200120043600050b410921020b2000200236020820002003360204200020013602000f0b103c000bf33010017f017e017f027e097f017e027f017e037f057e017f017e017f047e017f027e230041d0046b22052400200541d8016a4201427f420020032004844200521b2206200342005220044200552004501b22071b4200200620071b4201427f420020012002844200521b2206200142005220024200552002501b22071b4200200620071b108408200541d8016a41086a290300210820052903d801210902402002427f550d00200541003602d401200541c0016a20012002427f427f200541d4016a10850842ffffffffffffffffff00200541c0016a41086a29030020052802d40122071b2102427f20052903c00120071b21010b02402004427f550d00200541003602bc01200541a8016a20032004427f427f200541bc016a10850842ffffffffffffffffff00200541b0016a29030020052802bc0122071b2104427f20052903a80120071b21030b0240024002400240024002400240024002400240024002402002427f570d002004427f570d01200541f8006a2003420020014200108408200541e8006a200342002002420010840820054198016a200442002001420010840820054188016a20044200200242001084082005290388012204200529039801220220052903682203200541f8006a41086a2903007c22017c2206200254ad20054198016a41086a2903007c22022001200354ad200541e8006a41086a2903007c7c22037c2201200454ad20054188016a41086a2903007c22042003200254ad7c22022004540d0a2005290378210320054198026a4200370300200541a0026a42003703002005420037039002200542808090bbbad6adf00d37038802410021070340200741086a220a4128460d0b20054188026a20076a210b200a2107200b290300500d000b200520023703c002200520013703b802200520063703b002200520033703a802200541c8026a41186a20054188026a41186a290300370300200541c8026a41106a20054188026a41106a290300370300200541c8026a41086a20054188026a41086a29030037030020052005290388023703c802200541a8026a41186a2107200541a8026a41086a210c41c002210a024003400240200a41406a220a41c000470d002003210441c000210a0c020b20072903002104200741786a21072004500d000b0b200a200479a76b210b200541e0026a210741c002210a024002400340200a41406a220a41c000460d0120072903002104200741786a21072004500d000c020b0b41c000210a20052903c80221040b200a200479a76b2207450d02200b2007490d030240200741c100490d00200541e8026a41106a200c41106a290300370300200541e8026a41086a200c41086a2903003703002005200c2903003703e80220054180036a41186a220a200541c8026a41186a29030037030020054180036a41106a220c200541c8026a41106a29030037030020054180036a41086a220d200541c8026a41086a290300370300200520052903c802370380032007417f6a220e410676210f02400240024002400240200e41ff014b0d00200b417f6a4106762210200f6b210b200f41016a211120054180036a200f4103746a22122903002104200541a0036a41186a200a290300370300200541a0036a41106a200c290300370300200541a0036a41086a200d29030037030020052005290380033703a003200541e8036a41106a4200370300200541e8036a41186a4200370300200542003703f003200520047922133703e8032013a72114200541e8036a41086a210d4100210702400340200741086a220a4120460d01200d20076a210c200a2107200c290300500d000b418b80cc00412641dc80cc00103f000b200541a8046a4200370300200541a0046a420037030020054190046a41086a420037030020054200370390042014410676220d41037421072014413f71220cad2104200541a0036a210a034020054190046a20076a200a290300200486370300200a41086a210a200741086a22074120470d000b0240200c450d00200d4103742107420020137d423f83210420054190046a41086a210d200541a0036a210a0340200d20076a220c200c290300200a2903002004887c370300200a41086a210a200741086a22074118470d000b0b20054180036a41186a20054190046a41186a29030037030020054180036a41106a20054190046a41106a29030037030020054180036a41086a20054190046a41086a290300370300200520052903900437038003200541b0046a41106a200541e8026a41086a290300370300200541b0046a41186a200541e8026a41106a290300370300200520052903e8023703b804200520033703b004200541e8036a41106a4200370300200541e8036a41186a4200370300200542003703f003200541c00020146b2215ad22013703e80320032013423f832216862102200541e8036a41086a210d4100210702400340200741086a220a4120460d01200d20076a210c200a2107200c290300500d000b418b80cc00412641dc80cc00103f000b200541a8046a4200370300200541a0046a420037030020054190046a41086a420037030020054200370390042015413f71210c2015410676210d0240201541ff014b0d00200d4103742107200cad210420054190046a210a0340200a200541b0046a20076a290300200488370300200a41086a210a200741086a22074120470d000b0b0240200c450d00200d41016a41034b0d00200d410374210a420020017d423f832104200541b0046a41086a210c20054190046a2107034020072007290300200c200a6a2903002004867c370300200741086a2107200a41086a220a4118470d000b0b200520052903a8043703c003200520052903a0043703b80320052005290398043703b00320052005290390043703a803200520023703a003200541e0036a4200370300200541c8036a41106a4200370300200541c8036a41086a4200370300200542003703c803200f417f6a220741034b0d01200f41026a2117200541a0036a2010200f6b4103746a221841086a21192012290300221a201a792204423f83221b86221c42ffffffff0f83211d201c422088210120054180036a20074103746a290300211e41c0002004a76b221f413f71ad2120200541e8036a41106a21212005290398032122200529039003212320052903880321242005290380032125200e4180024921260340200b221520116a220741054f0d03427f21020240200541a0036a20074103746a22122903002204201a5a0d002015200f6a220a41044b0d052001500d0c200541a0036a200a4103746a2903002202201b86220342ffffffff0f8321062003422088210342002002202088201f413f4b1b2004201b868422272027200180220220017e7d2104024003400240200242ffffffff0f560d002002201d7e2004422086200384580d020b2002427f7c2102200420017c2204428080808010540d000b0b20274220862003842002201c7e7d22272027200180220320017e7d2104024003400240200342ffffffff0f560d002003201d7e2004422086200684580d020b2003427f7c2103200420017c220442ffffffff0f580d000b0b2007417e6a220741044b0d0d20274220862006842003201c7e7d201b882104200320024220867c2102200541a0036a20074103746a29030021060340200541d8006a20024200201e4200108408200620052903585a2004200541d8006a41086a29030022035a20042003511b0d012002427f7c21022004201a7c22032004542107200321042007450d000b0b200541c8006a2025420020024200108408200541386a2024420020024200108408200541286a2023420020024200108408200541186a20224200200242001084082005200529034822283703e803200520052903382203200541c8006a41086a2903007c22043703f003200520052903282206200541386a41086a2903002004200354ad7c7c22033703f803200520052903182227200541286a41086a2903002003200654ad7c7c2203370380042005200541186a41086a2903002003202754ad7c37038804201541064f0d0d2026450d0e024020174128201541037422106b410376220e200e20174b1b220d450d00200541a0036a20106a22072007290300220320287d22063703002006200356210c0240200d4101460d004102210a2021210b2019210703402007200729030022032004200cad4201837c22067d22273703002006200454202720035672210c200a200d4f0d01200a41016a210a200741086a2107200b2903002104200b41086a210b0c000b0b200c450d004100210b02402011200e200e20114b1b220d450d0020054180036a210a201821074100210c0340200720072903002204200a2903002203200bad42ff01837c22067c22273703002006200354202720045472210b200741086a2107200a41086a210a200c41016a220c200d490d000b0b2002427f7c210220122012290300200bad7c3703000b201541034b0d05201520154100476b210b200541c8036a20106a2002370300201841786a2118201941786a21192015450d0f0c000b0b200f410441dc80cc001042000b2007410441dc80cc001042000b2007410541dc80cc001042000b200a410541dc80cc001042000b2015410441dc80cc001042000b200541e8036a41186a200541a8026a41186a290300370300200541e8036a41106a200541a8026a41106a290300370300200541e8036a41086a200541a8026a41086a290300370300200520052903a8023703e80302400240024020052903c80222042004792203423f83221e86221a4220882204500d00201a42ffffffff0f832102200529038004210641c0002003a76b220741c000490d012004422086211d2006201e86220342ffffffff0f8321282003422088211b42002103420021064200212742002101024003400240200142ffffffff0f560d0020032006201b84580d020b200320027d21032006201d7c21062001427f7c2101202720047c2227428080808010540d000b0b201b2001201a7e7d22272027200480220320047e7d2106024003400240200342ffffffff0f560d00200320027e2006422086202884580d020b2003427f7c2103200620047c2206428080808010540d000b0b2005200320014220867c37038004427f201e8620274220862028842003201a7e7d83221d201d200480220320047e7d210120052903f803201e86220642ffffffff0f83212720064220882106024003400240200342ffffffff0f560d00200320027e2001422086200684580d020b2003427f7c2103200120047c2201428080808010540d000b0b2006201d422086842003201a7e7d221d201d200480220120047e7d2106024003400240200142ffffffff0f560d00200120027e2006422086202784580d020b2001427f7c2101200620047c2206428080808010540d000b0b2005200120034220867c3703f803427f201e86201d4220862027842001201a7e7d83221d201d200480220320047e7d210120052903f003201e86220642ffffffff0f83212720064220882106024003400240200342ffffffff0f560d00200320027e2001422086200684580d020b2003427f7c2103200120047c2201428080808010540d000b0b2006201d422086842003201a7e7d221d201d200480220120047e7d2106024003400240200142ffffffff0f560d00200120027e2006422086202784580d020b2001427f7c2101200620047c2206428080808010540d000b0b2005200120034220867c3703f003427f201e86201d4220862027842001201a7e7d83221d201d200480220320047e7d210120052903e803201e86220642ffffffff0f83212720064220882106024003400240200342ffffffff0f560d00200320027e2001422086200684580d020b2003427f7c2103200120047c2201428080808010540d000b0b2006201d422086842003201a7e7d22012001200480220120047e7d2106024003400240200142ffffffff0f560d00200120027e2006422086202784580d020b2001427f7c2101200620047c2206428080808010540d000b0b2005200120034220867c3703e8030c020b41d0fecb00411941dc80cc00103f000b20062007413f71ad221d8822282028200480220320047e7d21012006201e86220642ffffffff0f83212720064220882106024003400240200342ffffffff0f560d00200320027e2001422086200684580d020b2003427f7c2103200120047c2201428080808010540d000b0b20284220862006842003201a7e7d22282028200480220120047e7d2106024003400240200142ffffffff0f560d00200120027e2006422086202784580d020b2001427f7c2101200620047c2206428080808010540d000b0b2005200120034220867c3703800420052903f8032206201d88427f201e8620284220862027842001201a7e7d838422282028200480220320047e7d21012006201e86220642ffffffff0f83212720064220882106024003400240200342ffffffff0f560d00200320027e2001422086200684580d020b2003427f7c2103200120047c2201428080808010540d000b0b20284220862006842003201a7e7d22282028200480220120047e7d2106024003400240200142ffffffff0f560d00200120027e2006422086202784580d020b2001427f7c2101200620047c2206428080808010540d000b0b2005200120034220867c3703f80320052903f0032206201d88427f201e8620284220862027842001201a7e7d838422282028200480220320047e7d21012006201e86220642ffffffff0f83212720064220882106024003400240200342ffffffff0f560d00200320027e2001422086200684580d020b2003427f7c2103200120047c2201428080808010540d000b0b20284220862006842003201a7e7d22282028200480220120047e7d2106024003400240200142ffffffff0f560d00200120027e2006422086202784580d020b2001427f7c2101200620047c2206428080808010540d000b0b2005200120034220867c3703f00320052903e8032206201d88427f201e8620284220862027842001201a7e7d8384221d201d200480220320047e7d21012006201e86220642ffffffff0f83212720064220882106024003400240200342ffffffff0f560d00200320027e2001422086200684580d020b2003427f7c2103200120047c2201428080808010540d000b0b201d4220862006842003201a7e7d22012001200480220120047e7d2106024003400240200142ffffffff0f560d00200120027e2006422086202784580d020b2001427f7c2101200620047c2206428080808010540d000b0b2005200120034220867c3703e8030b20054190046a41186a200541e8036a41186a29030037030020054190046a41106a200541e8036a41106a29030037030020054190046a41086a200541e8036a41086a290300370300200520052903e803370390040c090b41e9fecb00413541dc80cc00103f000b41e9fecb00413541dc80cc00103f000b41fbffcb00411041dc80cc00103f000b200541a8046a4200370300200541a0046a420037030020054198046a420037030020054200370390040c050b41c080cc00411941dc80cc00103f000b2007410541dc80cc001042000b2015410541dc80cc001059000b2017410541dc80cc001058000b200541e8036a41206a200541a0036a41206a290300370300200541e8036a41186a200541a0036a41186a2903002204370300200541e8036a41106a200541a0036a41106a2903002202370300200541e8036a41086a200541a0036a41086a2903002203370300200520052903a00322013703e803200520012016883703b004200520032016883703b804200520022016883703c004200520042016883703c804024002402014450d00420020137d423f8321044101210703402007417f6a220a41034b0d02200541b0046a200a4103746a220a200a290300200541e8036a20074103746a29030020048684370300200720074104496a220a41044b0d01200741034b210b200a2107200b450d000b0b20054190046a41086a200541c8036a41086a29030037030020054190046a41106a200541c8036a41106a29030037030020054190046a41186a200541c8036a41186a290300370300200520052903c803370390040c010b200a410441dc80cc001042000b200541e8016a41086a20054190046a41086a2903002204370300200541e8016a41106a20054190046a41106a2903002202370300200541e8016a41186a20054190046a41186a2903002203370300200520052903900422013703e801200541e8036a41186a2003370300200541e8036a41106a220c2002370300200541e8036a41086a2004370300200520013703e8034100210702400340200741086a220a4118460d01200c20076a210b200a2107200b290300500d000c020b0b200541086a20092008422520052903e80320052903f003220442005322071b4200200420071b1084082004427f570d00200541106a2903002104200529030821020c010b428080808080808080807f42ffffffffffffffffff00200842005322071b21044200427f20071b21020b2000200237030020002004370308200541d0046a24000bb10503027f017e047f230041d0006b2202240041a3edcb00ad4280808080f00084100122032900002104200241086a41086a200341086a290000370300200220043703082003103541fe99ca00ad4280808080800184100122032900002104200241186a41086a200341086a29000037030020022004370318200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad42808080808004841003220129000037033820011035200241cc006a200341206a360200200220033602482002200241386a41086a3602442002200241386a360240200241286a200241c0006a107b200310352002280230220541206a2201417f4c0d01200228022821060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a2000200136020820002008360204200020033602000240200228022c450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000b920503027f017e067f230041d0006b2202240041a8e7cb00ad4280808080f00184100122032900002104200241086a200341086a290000370300200220043703002003103541b7e7cb00ad4280808080c00184100122032900002104200241106a41086a200341086a2900003703002002200437031020031035200220003703302002200241306aad42808080808001841003220329000037033820031035200241cc006a200241306a41086a3602002002200241386a41086a3602442002200241306a3602482002200241386a360240200241206a200241c0006a107b02400240024002402002280228220541206a2206417f4c0d00200228022021070240024020060d0041002108410121030c010b200610332203450d02200621080b024002402008410f4d0d00200821090c010b200841017422094110200941104b1b22094100480d03024020080d002009103322030d010c050b20082009460d0020032008200910372203450d040b20032002290300370000200341086a200241086a2903003700000240024020094170714110460d00200921080c010b200941017422084120200841204b1b22084100480d0320092008460d0020032009200810372203450d040b20032002290310370010200341186a200241106a41086a29030037000002400240200841606a2005490d00200821090c010b200541206a22092005490d032008410174220a2009200a20094b1b22094100480d0320082009460d0020032008200910372203450d040b200341206a20072005109d081a02402002280224450d00200710350b200220013602402006ad4220862003ad84200241c0006aad4280808080c00084100202402009450d00200310350b200241d0006a24000f0b1044000b1045000b103e000b103c000be91305057f017e047f027e037f230041f0006b22052400200541c0006a41186a22064200370300200541c0006a41106a22074200370300200541c0006a41086a220842003703002005420037034041a8e7cb00ad4280808080f0018410012209290000210a200541e0006a41086a220b200941086a2900003703002005200a370360200910352008200b2903003703002005200529036037034041b697ca00ad4280808080d0018410012209290000210a200b200941086a2900003703002005200a3703602009103520072005290360220a370300200541206a41086a22092008290300370300200541206a41106a220c200a370300200541206a41186a220d200b29030037030020052005290340370320200541186a200541206a412041b0b4cc0041004100108a02024002400240024002400240024020052802184101470d0041e192ca00210b410d2108410221070c010b2006420037030020074200370300200842003703002005420037034041d1c4c700ad4280808080e0008410012206290000210a2008200641086a2900003703002005200a3703402006103541e7c4c700ad4280808080e0008410012206290000210a200b200641086a2900003703002005200a3703602006103520072005290360220a37030020092008290300370300200c200a370300200d200b29030037030020052005290340370320200541106a200541206a412010c0012005280214410020052802101b2109024020034101460d00200541206a210e0c030b200541c0006a41186a22064200370300200541c0006a41106a220c4200370300200541c0006a41086a220842003703002005420037034041a8e7cb00ad4280808080f00184220f1001220d290000210a200541e0006a41086a220b200d41086a2900003703002005200a370360200d10352008200b2903003703002005200529036037034041f499ca00ad4280808080a0018422101001220d290000210a200b200d41086a2900003703002005200a370360200d103520072005290360370000200741086a220d200b290300370000200541206a41086a220e2008290300370300200541206a41106a2211200c290300370300200541206a41186a2212200629030037030020052005290340370320200541086a200541206a412010c0012005280208450d01200528020c20094d0d0141da92ca00210b41072108410321070b20004183203b0100200041086a2008360200200041046a200b360200200041026a20073a0000200141046a280200220b450d02200b41286c450d02200128020010350c020b20064200370300200c42003703002008420037030020054200370340200f10012213290000210a200b201341086a2900003703002005200a370360201310352008200b29030037030020052005290360370340201010012213290000210a200b201341086a2900003703002005200a3703602013103520072005290360370000200d200b290300370000200e20082903003703002011200c29030037030020122006290300370300200520052903403703202005200920024101746a360240200541206aad4280808080800484200541c0006aad4280808080c000841002200541206a210e0b200128020821082001280204210c2001280200210d200541c0006a41186a22114200370300200541c0006a41106a22124200370300200541c0006a41086a220142003703002005420037034041a8e7cb00ad4280808080f0018410012206290000210a200541e0006a41086a220b200641086a2900003703002005200a370360200610352001200b2903003703002005200529036037034041b697ca00ad4280808080d0018410012206290000210a200b200641086a2900003703002005200a3703602006103520072005290360370000200741086a200b290300370000200541206a41086a2001290300370300200541206a41106a2012290300370300200541206a41186a201129030037030020052005290340370320200541003602482005420137034041041033220b450d02200541043602442005200b360240200b200936000020054104360248200b410441081037220b450d0220054108360244200b20023600042005200b360240200541083602482008200541c0006a10772005280248210702402008450d00200d200841286c6a2106200d210b0340024002402005280244220220076b4120490d00200741206a210820052802402101200221090c010b200741206a22082007490d04200241017422012008200120084b1b22094100480d040240024020020d00024020090d00410121010c020b2009103322010d010c070b2005280240210120022009460d0020012002200910372201450d060b20052009360244200520013602400b200120076a2207200b290000370000200741186a200b41186a290000370000200741106a200b41106a290000370000200741086a200b41086a29000037000020052008360248200b41206a290300210a0240200920086b41074b0d00200841086a22072008490d04200941017422022007200220074b1b22074100480d040240024020090d00024020070d00410121010c020b200710332201450d070c010b20092007460d0020012009200710372201450d060b20052007360244200520013602400b200120086a200a3700002005200841086a22073602482006200b41286a220b470d000b0b2005280244210b0240024020034101460d0002400240200b2007460d00200528024021080c010b200741016a220b2007490d0420074101742208200b2008200b4b1b220b4100480d040240024020070d00410021070240200b0d00410121080c020b200b10332208450d070c010b200528024021082007200b460d0020082007200b10372208450d060b2005200b360244200520083602400b200820076a41003a00002005200741016a22073602480c010b02400240200b2007460d00200528024021080c010b200741016a220b2007490d0320074101742208200b2008200b4b1b220b4100480d030240024020070d00410021070240200b0d00410121080c020b200b10332208450d060c010b200528024021082007200b460d0020082007200b10372208450d050b2005200b360244200520083602400b200820076a41013a00002005200741016a22013602480240200b20016b41034b0d00200141046a22092001490d03200b41017422022009200220094b1b22094100480d0302400240200b0d00024020090d00410121080c020b200910332208450d060c010b200b2009460d002008200b200910372208450d050b20052009360244200520083602400b200820016a20043600002005200741056a22073602482005280244210b200528024021080b200ead42808080808004842007ad4220862008ad8410020240200b450d00200810350b0240200c450d00200c41286c450d00200d10350b200041043a00000b200541f0006a24000f0b103e000b103c000bff0201037f230041206b2203240002400240200241c4006c41046a2204417f4c0d000240024020040d0041012105410021040c010b200410332205450d020b20034100360208200320053602002003200436020420022003107702402002450d00200241c4006c210203400240024020012d00004101460d00200341003a00102003200341106a410110782003200141046a2802003602102003200341106a410410780c010b200341013a00102003200341106a41011078412010332204450d042003422037021420032004360210200341106a200141016a41201078200328021421042003200328021022052003280218107802402004450d00200510350b0240200141216a2d00004101460d00200341003a00102003200341106a410110780c010b200341013a00102003200341106a410110782003200141226a412010780b200141c4006a2101200241bc7f6a22020d000b0b20002003290300370200200041086a200341086a280200360200200341206a24000f0b1044000b1045000b290020004101360204200041086a200128020420012802006b41a0016e2201360200200020013602000ba50201057f230041d0006b21020240200128020022032001280204470d00200041003602000f0b2001200341a0016a3602002002200329004237012a2002200329004a370132200241086a41086a220120022903303703002002200329005237013a200241086a41106a220420022903383703002002200328005a360142200220032f005e3b0146200241086a41186a22052002290340370300200220032f00403b012820022002290328370308200241286a41186a22062005290300370300200241286a41106a22052004290300370300200241286a41086a220420012903003703002002200229030837032820002003360200200020022903283702042000410c6a2004290300370200200041146a20052903003702002000411c6a20062903003702000bf30801087f230041f0006b2103024002402001280200220420012802042205460d00200241016a210603402001200441a0016a2202360200200341003a0068200441c0006a2d00002107200341013a0068200320073a0048200441c1006a2d00002107200341023a0068200320073a0049200441c2006a2d00002107200341033a0068200320073a004a200441c3006a2d00002107200341043a0068200320073a004b200441c4006a2d00002107200341053a0068200320073a004c200441c5006a2d00002107200341063a0068200320073a004d200441c6006a2d00002107200341073a0068200320073a004e2003200441c7006a2d00003a004f200341083a0068200441c8006a2d00002107200341093a0068200320073a0050200441c9006a2d000021072003410a3a0068200320073a0051200441ca006a2d000021072003410b3a0068200320073a0052200441cb006a2d000021072003410c3a0068200320073a0053200441cc006a2d000021072003410d3a0068200320073a0054200441cd006a2d000021072003410e3a0068200320073a0055200441ce006a2d000021072003410f3a0068200320073a00562003200441cf006a2d00003a0057200341103a0068200441d0006a2d00002107200341113a0068200320073a0058200441d1006a2d00002107200341123a0068200320073a0059200441d2006a2d00002107200341133a0068200320073a005a200441d3006a2d00002107200341143a0068200320073a005b200441d4006a2d00002107200341153a0068200320073a005c200441d5006a2d00002107200341163a0068200320073a005d200441d6006a2d00002107200341173a0068200320073a005e2003200441d7006a2d00003a005f200341183a0068200441d8006a2d00002107200341193a0068200320073a0060200441d9006a2d000021072003411a3a0068200320073a0061200441da006a2d000021072003411b3a0068200320073a0062200441db006a2d000021072003411c3a0068200320073a0063200441dc006a2d000021072003411d3a0068200320073a0064200441dd006a2d000021072003411e3a0068200320073a0065200441de006a2d000021072003411f3a0068200320073a0066200441df006a2d00002107200341203a0068200320073a0067200341286a41086a22072003290350370300200341286a41106a22082003290358370300200341286a41186a2209200329036037030020032003290348370328200341086a41086a220a2007290300370300200341086a41106a22072008290300370300200341086a41186a2208200929030037030020032003290328370308200341c8006a41186a2008290300370300200341c8006a41106a2007290300370300200341c8006a41086a200a290300370300200320032903083703482006417f6a2206450d022002210420052002470d000b0b200041003602000f0b20002004360200200020032903483702042000410c6a200341d0006a290300370200200041146a200341d8006a2903003702002000411c6a200341e0006a2903003702000b130020004101360204200041e09aca003602000b3400200041a8e7cb0036020420004100360200200041146a4106360200200041106a41d49bca00360200200041086a420f3702000b2c01017f02404108103322020d001045000b20004288808080800137020420002002360200200242003700000b2201017f230041106b22022400200241003602002000200210db04200241106a24000b2201017f230041106b22022400200241003602002000200210db06200241106a24000b130020004102360204200041eca4ca003602000b3400200041a3edcb0036020420004100360200200041146a4107360200200041106a41b8adca00360200200041086a42073702000b2c01017f02404104103322020d001045000b20004284808080c00037020420002002360200200241003600000bec0101057f230041306b2201240002400240200028020422020d00410021032001411c6a41003602002001410036020c0c010b2000410c6a280200210302400240200041086a28020022040d00200221000c010b2004210020022105034020052802880b21052000417f6a22000d000b200221000340200020002f01064102746a41880b6a28020021002004417f6a22040d000b200521020b200141246a20002f0106360200200141206a41003602002001411c6a200036020020014100360218200142003703102001200236020c200141003602080b20012003360228200141086a108f03200141306a24000bd564030d7f017e0c7f230041d0036b220424004100210520044100360280012004200236027c200420013602784104210602400240024002400240024002400240024002400240024002400240024002400240024002400240024020024104490d00200441043602800120012800004180c2cdeb06460d0141012101410021070c030b200441013a00b801200441a4036a41013602002004420137029403200441acfdcb0036029003200441363602ec022004200441e8026a3602a0032004200441b8016a3602e80220044180026a20044190036a10410c010b4104210602400240024002402002417c714104460d00200241074d0d0220044108360280010240200128000422084101460d004102210141042106410021070c060b20044190036a200441f8006a10b107410421062004280290034101470d0141002105410021070c030b200441013a00b801200441a4036a41013602002004420137029403200441acfdcb0036029003200441363602ec022004200441e8026a3602a0032004200441b8016a3602e80220044180026a20044190036a10410c030b20044190036a4104722101410021094100210a41002105410021074100210b0340200441b8016a41286a220c200141286a290200370300200441b8016a41206a220d200141206a290200370300200441b8016a41186a220e200141186a290200370300200441b8016a41106a220f200141106a290200370300200441b8016a41086a2210200141086a2902003703002004200129020022113703b80102402011a741ff01712212417e6a410c4f0d0041002108024002400240024002400240024002400240024002400240024020120e100c0c000102030405060708090a0b0c0c0c0b410121080c0b0b410221080c0a0b410321080c090b410421080c080b410521080c070b410621080c060b410721080c050b410821080c040b410921080c030b410a21080c020b410b21080c010b410c21080b024002400240200b41ff0171221320084d0d00411321010c010b41002108024002400240024002400240024002400240024002400240024020120e100c0c000102030405060708090a0b0c0c0c0b410121080c0b0b410221080c0a0b410321080c090b410421080c080b410521080c070b410621080c060b410721080c050b410821080c040b410921080c030b410a21080c020b410b21080c010b410c21080b20132008470d01411421010b024002402012410e4b0d00024002400240024002400240024002400240024002400240024020120e0f0001020304050607080e090e0a0b0c000b200441c0016a280200450d0d20042802bc0110350c140b0240200441c0016a280200450d0020042802bc0110350b200441cc016a280200450d0c200441c8016a28020010350c130b20042802bc0121090240200441c4016a2802002212450d002012410474210a2009211203400240201241046a280200450d00201228020010350b201241106a2112200a41706a220a0d000b0b200441c0016a28020041ffffffff0071450d0b200910350c120b20042802bc0121090240200441b8016a410c6a2802002212450d00201241286c210a2009211203400240201241046a280200450d00201228020010350b0240201241106a280200450d002012410c6a28020010350b201241286a2112200a41586a220a0d000b0b200441c0016a2802002212450d0a201241286c450d0a200910350c110b200441c0016a28020041ffffffff0371450d0920042802bc0110350c100b200441c0016a2802002212450d082012410c6c450d0820042802bc0110350c0f0b200441c0016a2802002212450d072012410c6c450d0720042802bc0110350c0e0b20042802bc01210f0240200441c4016a2802002212450d00200f20124104746a210e200f210d03400240200d280208220a450d00200d2802002112200a410474210a0340024020122d00004109470d000240201241046a220c280200220928020441ffffffff0371450d0020092802001035200c28020021090b200910350b201241106a2112200a41706a220a0d000b0b200d41106a21120240200d41046a28020041ffffffff0071450d00200d28020010350b2012210d2012200e470d000b0b200441c0016a28020041ffffffff0071450d06200f10350c0d0b20042802bc0121090240200441c4016a2802002212450d00201241146c210a2009211203400240201241046a280200450d00201228020010350b201241146a2112200a416c6a220a0d000b0b200441c0016a2802002212450d05201241146c450d05200910350c0c0b200441b8016a41047210b207200441c0016a2802002212450d042012411c6c450d0420042802bc0110350c0b0b200441b8016a41047210b307200441c0016a2802002212450d03201241186c450d0320042802bc0110350c0a0b200441b8016a41047210b407200441c0016a2802002212450d022012411c6c450d0220042802bc0110350c090b024020042802bc012212450d00200441c0016a280200450d00201210350b0240200441cc016a280200220c450d000240200441d4016a2802002212450d002012410c6c210a200c21120340024020122802002209450d00201241046a280200450d00200910350b2012410c6a2112200a41746a220a0d000b0b200441d0016a2802002212450d002012410c6c450d00200c10350b200441dc016a280200220f450d010240200441e4016a2802002212450d00200f20124104746a210e200f210d0340200d220c41106a210d0240200c2802042212450d000240200c410c6a280200220a450d00200a410c6c210a0340024020122802002209450d00201241046a280200450d00200910350b2012410c6a2112200a41746a220a0d000b0b200c41086a2802002212450d002012410c6c450d00200c28020410350b200d200e470d000b0b200441e0016a28020041ffffffff0071450d01200f10350c080b0240200441c0016a280200450d0020042802bc0110350b0240200441cc016a2802002212450d00200441d0016a280200450d00201210350b200441dc016a28020041ffffffff0071450d00200441d8016a28020010350b0c060b4100210b02400240024002400240024002400240024002400240024020120e100c0c000102030405060708090a0b0c0c0c0b4101210b0c0b0b4102210b0c0a0b4103210b0c090b4104210b0c080b4105210b0c070b4106210b0c060b4107210b0c050b4108210b0c040b4109210b0c030b410a210b0c020b410b210b0c010b410c210b0b20044180026a41286a2208200c29030037030020044180026a41206a220c200d29030037030020044180026a41186a220d200e29030037030020044180026a41106a220e200f29030037030020044180026a41086a220f2010290300370300200420042903b80137038002024020052007470d00200541016a22122005490d0720092012200920124b1bad42307e2211422088a70d072011a722124100480d0702400240024020050d0020120d01410421060c020b200a2012460d010240200a0d0020120d01410421060c020b2006200a201210372206450d180c010b201210332206450d170b201241306e21070b2006200a6a2212200429038002370200201241286a2008290300370200201241206a200c290300370200201241186a200d290300370200201241106a200e290300370200201241086a200f290300370200200941026a2109200a41306a210a200541016a210520044190036a200441f8006a10b1072004280290034101460d020c000b0b4108200241c0fdcb001058000b0240024020042d0094030d002006200541306c6a210b20062101024003400240200b2001470d00410021090c020b20012d00002112200141306a220a21012012410c470d000b200a415c6a28020021090b2006200541306c6a210b20062101024003400240200b2001470d00410021010c020b20012d00002112200141306a220a210120124104470d000b200441f0006a200a41546a10bf03200428027421010b024020092001470d00410021014101210841e100210b41f3da01210a410021120c050b2006200510f40641012112411a21012007450d01200741306c450d01200610350c040b2004280294032201411076210a2001410876210b20044190036a41106a28020021092004419c036a280200210c20044190036a41086a28020021080c020b0c020b2004280280022108200428028402210c20042802880221094105210141002105410021074100210a4100210b0b2006200510f4064101211202402007450d00200741306c450d00200610350b20092107200c21060b200a411074200b41ff017141087472200141ff01717221100240024002402012450d00200621020c010b2004280280012002460d01200441003a00b801200441a4036a41013602002004420137029403200441acfdcb0036029003200441363602ec022004200441e8026a3602a0032004200441b8016a3602e80220044180026a20044190036a1041200428028002210820042802840221022006200510f406410521102007450d00200741306c450d00200610350b02402002450d00201041ff01714105470d00200810350b200041a0d3cb0036020420004101360200200041086a41163602000c0f0b4100210a200441b0016a4100360200200441a0016a420037030020044198016a4280808080c00037030020044188016a4200370300200442043703a801200442013703900120044280808080c0003703800120044204370378200541306c211241002102024002400340024020122002470d00410421124100210b0c020b200620026a2101200241306a220b210220012d00004102470d000b200441e8006a2006200b6a41546a10bf032004280268210b200428026c21012004410036029803200442043703900320044190036a41002001108c012004280290032102200428029803210c02402001450d002001410474210d2002200c4104746a21020340200b221241086a2802002201417f4c0d032012410c6a2d0000210e2012280200210f0240024020010d004100210b410121090c010b200110332209450d082001210b0b02400240200b2001490d00200b210a0c010b200b410174220a2001200a20014b1b220a4100480d050240200b0d00200a10332209450d150c010b0240200b200a470d00200b210a0c010b2009200b200a10372209450d140b201241106a210b2009200f2001109d0821092002410d6a2012410d6a2d00003a00002002410c6a200e3a0000200241086a2001360200200241046a200a360200200220093602002002410e6a20042f0180023b0100200241106a2102200c41016a210c200d41706a220d0d000b20042802900321020b200428029403410020021b210b200c410020021b210a2002410420021b21120b024020042802a4012201450d00200428029c0121022001410474210103400240200241046a280200450d00200228020010350b200241106a2102200141706a22010d000b0b024020042802a00141ffffffff0071450d00200428029c0110350b2004200a3602a4012004200b3602a0012004201236029c01200541306c2112410021094100210203404101210b20122002460d03200620026a2101200241306a220a210220012d00004103470d000b200441e0006a2006200a6a41546a10bf0320042802602202450d024100210f20042802642201450d03200141286c21012002411c6a2102200441f8006a410c6a2113410021094100210f4101210b034002400240024002400240024002402002417c6a2d00000e0401020300010b200441f8006a2002417d6a22122d00002002417e6a220a2d000041017110b507200a2d0000210a20122d0000210c2009200f470d04200941016a22122009490d082009410174220d2012200d20124b1b220e200e6a2212200e490d0820124100480d080240024020090d0020120d014101210b0c050b200d2012460d040240200d0d0020120d014101210b0c050b200b200d20121037220b450d180c040b20121033220b450d170c030b200441f8006a200228020010b6070c040b20044190036a41086a220a200241086a28020036020020042002290200370390030240200428028c012212200428028801470d00201320124101108701200428028c0121120b2004280284012012410c6c6a2212200429039003370200201241086a200a2802003602002004200428028c0141016a36028c010c030b20044190036a41086a220a200241086a280200360200200420022902003703900302402004280280012212200428027c470d00200441f8006a2012410110870120042802800121120b20042802782012410c6c6a2212200429039003370200201241086a200a280200360200200420042802800141016a360280010c020b2012410176210f0b200b20094101746a2212200a4101713a00012012200c3a0000200941016a21090b200241286a2102200141586a2201450d040c000b0b1044000b103e000b4100210f0b200541306c2112410021020240034020122002460d01200620026a2101200241306a220a210220012d00004104470d000b200441d8006a2006200a6a41546a10bf03200428025c2201450d0020042802582102200141027421010340200441f8006a200228020010b607200241046a21022001417c6a22010d000b0b200541306c2112410021020240034020122002460d01200620026a2101200241306a220a210220012d00004105470d000b200441d0006a2006200a6a41546a10bf032004280254410c6c2212450d0020042802502102200441f8006a410c6a210d0340200241086a2101024002400240200241046a2802004101470d0020042001280200220a3602e8022002280200220c200a4b0d010b200441003602b8010c010b200441023602a4032004420237029403200441d0aacc00360290032004410136028c0220044101360284022004200c3602f802200420044180026a3602a0032004200441f8026a360288022004200441e8026a36028002200441b8016a20044190036a104120042802b801450d00200441b8016a21020c0b0b2002290200211120044190036a41086a220a200128020036020020042011370390030240200428028c012201200428028801470d00200d20014101108701200428028c0121010b2002410c6a21022004280284012001410c6c6a2201200429039003370200200141086a200a2802003602002004200428028c0141016a36028c01201241746a22120d000b0b200541306c2102200641546a2101024003402002450d01200241506a21022001412c6a2112200141306a220a210120122d00004106470d000b200441c8006a200a10bf03200428024c2201450d00200428024821022001410c6c2112034020044190036a200210b7070240200428029003450d0020044190036a21020c0b0b2002290200211120044190036a41086a220a200241086a280200360200200420113703900302402004280280012201200428027c470d00200441f8006a2001410110870120042802800121010b2002410c6a210220042802782001410c6c6a2201200429039003370200200141086a200a280200360200200420042802800141016a36028001201241746a22120d000b0b200541306c2102200641546a2101024003402002450d01200241506a21022001412c6a2112200141306a220a210120122d00004107470d000b200441c0006a200a10bf0320042802442201450d002004280240220220014104746a210a20044190036a4104722112034020044190036a2002200b200910b80702400240024020042d0090034101460d00200420042d00910322013a00e802024020012002410c6a2d0000220c470d00200441003602b8010c030b200441023602a4032004420237029403200441e4abcc00360290032004413736028c0220044137360284022004200c3a00f802200420044180026a3602a0032004200441e8026a360288022004200441f8026a36028002200441b8016a20044190036a10410c010b200441b8016a41086a201241086a280200360200200420122902003703b8010b024020042802b801450d00200441b8016a21020c0c0b2002410c6a2d000021010b200441f8006a20012002410d6a2d000041017110b507200241106a2202200a470d000b0b20044190036a41386a2202200441f8006a41386a28020036020020044190036a41306a2201200441f8006a41306a29030037030020044190036a41286a200441f8006a41286a29030037030020044190036a41206a2212200441f8006a41206a29030037030020044190036a41186a220a200441f8006a41186a29030037030020044190036a41106a200441f8006a41106a29030037030020044190036a41086a200441f8006a41086a22092903003703002004200429037837039003200441b8016a41086a2009280200360200200420042903783703b801200441b8016a41146a20044190036a41146a2802003602002004200429029c033702c401200441b8016a41206a20122802003602002004200a2903003703d001200441b8016a412c6a20044190036a412c6a280200360200200420042902b4033702dc01200441b8016a41386a2002280200360200200420012903003703e801200541306c2102200641546a210102400340024020020d00410021090c020b200241506a21022001412c6a2112200141306a220a210120122d00004104470d000b200441386a200a10bf03200428023c21090b200420093602f401200541306c21022006415c6a210102400340024020020d00410021020c020b200241506a2102200141246a2112200141306a220a210120122d0000410c470d000b200a28020021020b200420023602f80120092002470d050240024002400240024002402009450d00200541306c2102200641546a210103402002450d04200241506a21022001412c6a2112200141306a220a210120122d00004104470d000b200541306c2102200641546a210103402002450d03200241506a21022001412c6a2112200141306a220c210120122d0000410c470d000b200441306a200a10bf0320042802342202450d002004280230220e20024102746a211420044190036a41286a2115200c41086a2113200441b0026a2116200441b8026a21174100210d03402004200d3602fc0120132802002102200c2802002101200442013702940320044198dbcb0036029003200441013602fc02200441013602a4032004200441f8026a3602a0032004200441fc016a3602f80220044180026a20044190036a1041200428028002211220042902840221112002200d4d0d0e02402011a7450d00201210350b2004200e28020022023602e802024002400240024020042802e40120024d0d000240024002402001200d41186c6a22012802142218450d0020042802dc0120024104746a22122d000d21192012280200211a200128020c21022001280200211b2012280208221c210a024002402001280208221d450d00201d4103742109201c2101201b21120340200120122802006a220a2001490d02201241086a2112200a2101200941786a22090d000b0b200420193a00c803200442808080808080103703c003200442043703b803200442808080808080103703b003200442013703a8032004201a360294032004200aad422086201dad843703a0032004201bad422086201cad84370398032004200441b8016a36029003410021012015410010ba0720042802b80320042802c00322124103746a2019ad42ff018342288637020020044180026a41086a20042903980337030020044180026a41106a20042903a00337030020044180026a41186a20042903a80337030020044180026a41206a20042903b00337030020044180026a41286a20042903b8033703002004201241016a3602c003201620042903c003370300201720042802c803360200200420042903900337038002201841047421120340200420013602c002200420023602c402200441c8026a20044180026a200210bb07024020042802c802450d00200441e8026a41086a200441c8026a41086a280200360200200420042903c8023703e8022004410336028c03200442033702fc02200441c4d2cb003602f802200441383602a4032004410136029c032004413936029403200420044190036a360288032004200441e8026a3602a0032004200441c0026a360298032004200441c4026a36029003200441d8026a200441f8026a1041024020042802ec02450d0020042802e80210350b20042802d802220a0d040b200241106a2102200141016a2101201241706a22120d000b20042802b0020d030240200428029c02450d0020042802980210350b20042802ac0241ffffffff0171450d0720042802a80210350c070b41201033220a450d0e200a41186a41002900c0b24c370000200a41106a41002900b8b24c370000200a41086a41002900b0b24c370000200a41002900a8b24c37000042a0808080800421110c040b41201033220a450d0d200a41186a41002900bad24b370000200a41106a41002900b2d24b370000200a41086a41002900aad24b370000200a41002900a2d24b37000042a0808080800421110c030b20042902dc0221110240200428029c02450d0020042802980210350b20042802ac0241ffffffff0171450d0320042802a80210350c030b41dcd2cb00413041c086cc00103f000b200441013602a4032004420237029403200441f0aecc0036029003200441013602fc022004200441f8026a3602a0032004200441e8026a3602f80220044180026a20044190036a1041200428028002210a20042902840221110b200a450d010b200420113702fc022004200a3602f8022004200441f8026a3602d802200441023602a4032004420237029403200441a0dbcb00360290032004413a36028c022004410136028402200420044180026a3602a0032004200441d8026a360288022004200441fc016a36028002200441e8026a20044190036a1041024020042802fc02450d0020042802f80210350b20042802e80222120d030b200d41016a210d200e41046a220e2014470d000b0b200541306c2102200641546a2101024003402002450d01200241506a21022001412c6a2112200141306a220a210120122d00004109470d000b2004200a28020022023602d80202400240200441f0016a28020020024d0d00200420042802e80120024102746a28020022023602e802200441e4016a28020020024b0d01200441a4036a41013602002004420237029403200441f0aecc0036029003200441013602fc022004200441f8026a3602a0032004200441e8026a3602f80220044180026a20044190036a10410c090b200441a4036a41013602002004420237029403200441ccaecc0036029003200441013602fc022004200441f8026a3602a0032004200441d8026a3602f80220044180026a20044190036a10410c080b20042802dc0120024104746a220231000d4220862002350208844280808080c000510d00412d10332212450d06201241256a41002900d5db4b370000201241206a41002900d0db4b370000201241186a41002900c8db4b370000201241106a41002900c0db4b370000201241086a41002900b8db4b370000201241002900b0db4b37000042ad808080d00521110c0d0b200541306c2102200641546a210103402002450d05200241506a21022001412c6a2112200141306a220a210120122d00004108470d000b200441286a200a10bf0320042802282102200428022c21122004410036029803200442043703900320044190036a41002012109001200428029803210c200428029003210e02402012450d002002201241146c6a2109200e200c4103746a21012012410274417c6a410276210d034020022802002112200141046a200241086a28020036020020012012360200200141086a2101200241146a22022009470d000b200c200d6a41016a210c0b2004280294032113200e200c20044190036a41004120200c676b10be070240200c450d00200e200c4103746a210941012112200e2102200e21010340024002402012450d00200920026b41037620124d0d03200220124103746a21020c010b20092002460d020b200420013602e8020240200141046a2802002212200241046a280200470d002001280200220c2002280200220d460d0a200c200d201210a008450d0a0b200241086a210241002112200141086a22012009470d000b0b200441206a200a10bf0320042802242202450d03200241146c2101200428022041106a210203400240024002400240024002402002417c6a2802000e0400030201000b2004200228020022123602d802024020042802f00120124d0d00200420042802e80120124102746a28020022123602e80220042802e40120124b0d05200441013602a4032004420237029403200441f0aecc0036029003200441013602fc022004200441f8026a3602a0032004200441e8026a3602f80220044180026a20044190036a10410c0f0b200441a4036a41013602002004420237029403200441ccaecc0036029003200441013602fc022004200441f8026a3602a0032004200441d8026a3602f80220044180026a20044190036a10410c0e0b2004200228020022123602d80220042802d80120124d0d0220042802d00120124101746a2d0001450d03200441a4036a41013602002004420237029403200441b0afcc0036029003200441013602fc022004200441f8026a3602a0032004200441d8026a3602f80220044180026a20044190036a10410c0d0b2004200228020022123602e80220042802c00120124b0d02200441013602a4032004420237029403200441fcadcc0036029003200441013602fc022004200441f8026a3602a0032004200441e8026a3602f80220044180026a20044190036a104120042802800222120d0d0c020b2004200228020022123602e80220042802cc0120124b0d01200441a4036a41013602002004420237029403200441acaecc0036029003200441013602fc022004200441f8026a3602a0032004200441e8026a3602f80220044180026a20044190036a10410c0b0b200441a4036a4101360200200442023702940320044190afcc0036029003200441013602fc022004200441f8026a3602a0032004200441d8026a3602f80220044180026a20044190036a10410c0a0b200241146a21022001416c6a22010d000c040b0b20042902ec0221110c0b0b41c0dacb0041c8004188dbcb001064000b4190dacb00411e41b0dacb001064000b201341ffffffff0171450d00200e10350b200541306c2102200641546a2101024003402002450d01200241506a21022001412c6a2112200141306a220a210120122d00004103470d000b200441186a200a10bf03200428021c2202450d002004280218210a200241286c210941002102034002400240024002400240200a20026a220141186a2d00000e0401000302010b200141206a2802004101470d032001411c6a28020021122004200141246a28020022013602d802201220014d0d03200441023602a4032004420237029403200441d0aacc00360290032004410136028c022004410136028402200420123602e802200420044180026a3602a0032004200441e8026a360288022004200441d8026a36028002200441f8026a20044190036a104120042802f80222120d0c0c030b20042001411c6a28020022013602e80220042802e40120014b0d02200441a4036a41013602002004420237029403200441f0aecc0036029003200441013602fc022004200441f8026a3602a0032004200441e8026a3602f80220044180026a20044190036a10410c060b2001411a6a2d0000450d012001410c6a2802002102200141146a280200210120044190036a41146a4101360200200420013602fc02200420023602f802200441043602ec022004420137029403200441e8dbcb00360290032004200441f8026a3602e8022004200441e8026a3602a00320044180026a20044190036a10410c050b20044190036a2001411c6a10b7072004280290032212450d0020042902940321110c0a0b2009200241286a2202470d000b0b024002400240200441b8016a41146a280200220241014b0d0020042802c001220241014b0d01200541306c2102200641546a2101024003402002450d01200241506a21022001412c6a2112200141306a220a210120122d0000410d470d000b200441106a200a10bf03200428021022022004280214411c6c6a210a0240024003402002200a460d032004200228020022013602e802024020042802c00120014b0d00200441013602a4032004420237029403200441fcadcc0036029003200441013602fc022004200441f8026a3602a0032004200441e8026a3602f80220044180026a20044190036a10412004280280022212450d0020042902840221110c0f0b200241046a2202280200450d0120044190036a200220042802d00120042802d80110b80720042d0090034101460d02200241186a210220042d009103450d000b412010332212450d06201241186a41002900c1dc4b370000201241106a41002900b9dc4b370000201241086a41002900b1dc4b370000201241002900a9dc4b37000042a0808080800421110c0d0b412910332212450d05201241286a41002d00a8dc4b3a0000201241206a41002900a0dc4b370000201241186a4100290098dc4b370000201241106a4100290090dc4b370000201241086a4100290088dc4b37000020124100290080dc4b37000042a9808080900521110c0c0b20044198036a290300211120042802940321120c0b0b200541306c2102200641546a2101024003402002450d01200241506a21022001412c6a2112200141306a220a210120122d0000410a470d000b200441086a200a10bf03200428020c2202450d00200428020822092002411c6c6a210c024002400240024003402009450d052004200928020022023602e80220042802cc0120024d0d082009280204450d0120044190036a200941046a20042802d00120042802d80110b80720042d0090034101460d0220042d0091030d032004200910bf070240024020042802042202450d00200428020021012002410274211220042802f001210a03402004200128020022023602d802200a20024d0d07200420042802e80120024102746a28020022023602e80220042802e40120024d0d02200141046a21012012417c6a22120d000b0b2009411c6a2209200c460d060c010b0b200441013602a4032004420237029403200441f0aecc0036029003200441013602fc022004200441f8026a3602a0032004200441e8026a3602f80220044180026a20044190036a10410c090b412a10332212450d07201241286a41002f00f1dc4b3b0000201241206a41002900e9dc4b370000201241186a41002900e1dc4b370000201241106a41002900d9dc4b370000201241086a41002900d1dc4b370000201241002900c9dc4b37000042aa808080a00521110c0e0b20044198036a290300211120042802940321120c0d0b412010332212450d05201241186a41002900c1dc4b370000201241106a41002900b9dc4b370000201241086a41002900b1dc4b370000201241002900a9dc4b37000042a0808080800421110c0c0b200441a4036a41013602002004420237029403200441ccaecc0036029003200441013602fc022004200441f8026a3602a0032004200441d8026a3602f80220044180026a20044190036a10410c050b024020042802bc012202450d002002410c6c450d0020042802b80110350b0240200441c8016a2802002202450d002002410c6c450d0020042802c40110350b0240200441d4016a28020041808080807872418080808078460d0020042802d00110350b0240200441e4016a2802002201450d0020042802dc0121022001410474210103400240200241046a280200450d00200228020010350b200241106a2102200141706a22010d000b0b0240200441e0016a28020041ffffffff0071450d0020042802dc0110350b0240200441ec016a28020041ffffffff0371450d0020042802e80110350b200f41808080807872418080808078460d0d200b10350c0d0b20044190036a41146a41013602002004420137029403200441f0dbcb0036029003200441013602fc02200420023602e8022004200441f8026a3602a0032004200441e8026a3602f80220044180026a20044190036a10410c030b200441a4036a41013602002004420137029403200441f8dbcb0036029003200441013602fc02200420023602e8022004200441f8026a3602a0032004200441e8026a3602f80220044180026a20044190036a10410c020b200441a4036a41013602002004420237029403200441acaecc0036029003200441013602fc022004200441f8026a3602a0032004200441e8026a3602f80220044180026a20044190036a10410c010b1045000b200428028002211220042902840221110c050b200441a4036a41013602002004420137029403200441e0dbcb00360290032004413b3602fc022004200441f8026a3602a0032004200441e8026a3602f80220044180026a20044190036a10410b20042802800221120b2004290284022111201341ffffffff0171450d02200e10350c020b200441a4036a41023602002004418c026a4101360200200442023702940320044180dacb00360290032004410136028402200420044180026a3602a0032004200441f8016a360288022004200441f4016a36028002200441f8026a20044190036a104120042802f80221120b20042902fc0221110b024020042802bc012202450d002002410c6c450d0020042802b80110350b0240200441c8016a2802002202450d002002410c6c450d0020042802c40110350b0240200441d4016a28020041808080807872418080808078460d0020042802d00110350b0240200441e4016a2802002201450d0020042802dc0121022001410474210103400240200241046a280200450d00200228020010350b200241106a2102200141706a22010d000b0b0240200441e0016a28020041ffffffff0071450d0020042802dc0110350b0240200441ec016a28020041ffffffff0371450d0020042802e80110350b200f41808080807872418080808078460d01200b10350c010b20022902042111200228020021120240200f41808080807872418080808078460d00200b10350b0240200428027c2202450d002002410c6c450d00200428027810350b02402004280288012202450d002002410c6c450d0020042802840110350b024020042802940141808080807872418080808078460d0020042802900110350b024020042802a4012201450d00200428029c0121022001410474210103400240200241046a280200450d00200228020010350b200241106a2102200141706a22010d000b0b024020042802a00141ffffffff0071450d00200428029c0110350b20042802ac0141ffffffff0371450d0020042802a80110350b2012450d0002402011a7450d00201210350b200041b6d3cb0036020420004101360200200041086a41133602002006200510f4062007450d01200741306c450d01200610350c010b2000201036020420004100360200200041186a2003360200200041146a2005360200200041106a20073602002000410c6a2006360200200041086a20083602000b200441d0036a24000f0b103c000bc31401187f23004190026b220224000240024002400240024020002802002203450d00200028020421040c010b41002104200241216a410041d800109f081a200241076a220542003700002002420037010241ec0010332203450d0120034100360200200320022902003702042003410b6a2005290000370000200341136a200241206a41d900109d081a20004100360204200020033602000b200220003602282002200336022420022004360220200141ff017121060240024002400340200341066a210720032f01062108410c2109410021050240034020082005460d01200320056a210a200941086a2109200541016a210502404100417f4101200a41086a2d0000220a20064b1b200a2006461b41016a0e03000401000b0b2005417f6a21080b02402004450d002004417f6a2104200320084102746a41ec006a28020021030c010b0b200241c0016a2008360200200241bc016a2000360200200241b0016a41086a20033602002002200036022820022003360224200241003602b4012000200028020841016a36020802400240024020032f01062205410b490d00200241206a41016a410041d800109f081a200241003a001141ec0010332206450d06200641003602002006410036000f20064200370007200620022f01103b0005200641136a200241206a41d900109d081a2003410e6a2d0000210b2003280248210c2003280244210d200641086a2003410f6a20032f010641796a2205109d082109200641146a200341cc006a2005410374109d082104200341063b0106200620053b010620084107490d0120092008417a6a220a6a2009200841796a22086a2209200541ffff037120086b109e081a200920013a00002004200a4103746a200420084103746a2205200641066a22072f010020086b410374109e081a2005410136020020072f010021050c020b200341086a2209200841016a22066a200920086a2209200520086b2200109e081a200920013a0000200341146a220920064103746a200920084103746a22092000410374109e081a200941013602002003200541016a3b01060c040b200341086a2205200841016a22096a200520086a220420072f0100220520086b220a109e081a200420013a0000200341146a220420094103746a200420084103746a2209200a410374109e081a200941013602000b2007200541016a3b01000240200328020022050d00410021010c020b200241206a41016a210e200241a8016a210f200241a0016a211020024198016a211120024190016a211220024180016a41086a211341002101034020062114200c2115200d2116200b211720032f01042104024002400240200522032f01062205410b490d00200e410041d800109f081a200241003a0011200220022f01103b0100200241b0016a200241206a41d900109d081a200f4200370300201042003703002011420037030020124200370300201342003703002002420037038001419c0110332206450d07200641003602002006410036000f20064200370007200620022f01003b0005200641136a200241b0016a41d900109d081a20064194016a200f2903003702002006418c016a201029030037020020064184016a2011290300370200200641fc006a2012290300370200200641f4006a2013290300370200200620022903800137026c2003410e6a2d0000210b2003280248210c2003280244210d200641086a2003410f6a20032f0106220941796a2205109d082118200641146a200341cc006a2005410374109d082119200641ec006a20034188016a2009417a6a220a410274109d082107200341063b0106200620053b01060240200a450d00410021052007210903402009280200220820053b010420082006360200200941046a2109200a200541016a2205470d000b0b20044107490d0120182004417a6a22096a2018200441796a22056a220820062f010620056b109e081a200820173a0000201920094103746a201920054103746a220820062f010620056b410374109e081a2008201636020020082015360204200620062f010641016a22083b01062004410274221520076a416c6a200720094102746a220a200841ffff0371220420096b410274109e081a200a201436020020042009490d02200620156a41d4006a2109034020092802002208200541016a22053b010420082006360200200941046a210920052004490d000c030b0b200341086a2206200441016a22096a200620046a2206200520046b2208109e081a200620173a0000200341146a220620094103746a200620044103746a22062008410374109e081a20062016360200200620153602042003200541016a22053b01062004410274200341ec006a22066a41086a200620094102746a2206200541ffff0371220820096b410274109e081a20062014360200200420084f0d0520032009417f6a22054102746a41f0006a2109034020092802002206200541016a22053b010420062003360200200941046a210920052008490d000c060b0b200341086a2209200441016a22056a200920046a220920032f0106220820046b220a109e081a200920173a0000200341146a220920054103746a200920044103746a2209200a410374109e081a20092016360200200920153602042003200841016a22093b010620044102742207200341ec006a22086a41086a200820054102746a220a200941ffff0371220820056b410274109e081a200a2014360200200420084f0d00200320076a41f0006a2105034020052802002209200441016a22043b010420092003360200200541046a210520082004470d000b0b200141016a210120032802002205450d020c000b0b200241c0016a2005417f6a360200200241bc016a2000360200200241b8016a20033602002002200036022820022003360224200220043602b401200320096a42013702000c010b200241206a41016a410041d800109f081a200241076a22034200370000200242003701022002200229020037031020022003290000370017200241b0016a200241206a41d900109d081a200241a8016a22054200370300200241a0016a2209420037030020024198016a2208420037030020024190016a2204420037030020024188016a220a42003703002002420037038001419c0110332203450d0120034100360200200320022903103702042003410b6a2002290017370000200341136a200241b0016a41d900109d081a20034194016a20052903003702002003418c016a200929030037020020034184016a2008290300370200200341fc006a2004290300370200200341f4006a200a290300370200200320022903800137026c20032000280200220536026c2000200336020020002000280204220941016a360204200541003b01042005200336020020092001470d0220032f01062205410a4b0d03200320054103746a220941186a200c360200200941146a200d360200200320056a41086a200b3a00002003200541016a22054102746a41ec006a2006360200200320053b0106200620053b0104200620033602000b20024190026a24000f0b103c000b41ff83cc00413041c086cc00103f000b41af84cc00412741c086cc00103f000bf42a11017f017e097f017e017f017e037f017e017f017e017f017e017f017e0c7f037e017f230041b0026b220224004200210320024184016a4200370200200241fc006a4280808080c000370200200241ec006a4200370200200241e4006a4280808080c000370200200241d0006a4200370300200241c0006a4200370300200241386a4280808080c000370300200241286a4200370300200241206a4280808080c000370300200241106a4200370300200242043702742002420437025c20024204370348200242043703302002420437031820024280808080c00037030820024204370300200141106a28020021042001410c6a280200210520012802082106410021072002410036029001200241003602a001200241003602b0010240024020040d004104210841002101410021094100210a4100210b4104210c4200210d4104210e4200210f41042110410021114100210441042112420021134104211442002115410421164200211741042118420021190c010b200241f0016a410172211a200241f0016a410472211b200241c0016a41086a2109200241c0016a41186a210a200241c0016a41206a210b200241c0016a41276a211c4100211d4100211e4100211f4100212041002121410021224100211102400340200920062004417f6a220441306c6a220141096a290000370300200241c0016a41106a2223200141116a290000370300200a200141196a290000370300200b200141216a290000370300201c200141286a290000370000200220012900013703c00120012d000022014110460d01201a20022903c001370000201a41086a2009290300370000201a41106a2023290300370000201a41186a200a290300370000201a41206a200b290300370000201a41276a201c290000370000200220013a00f001410121160240024002400240024002400240024002402001417e6a2214410b4d0d00410121120c010b410121124101210e410121104101210c410121244101210141012123410121084101212502400240024002400240024002400240024002400240024002400240024002400240024020140e0c000102030405060a07190809000b20022903f801211520022802f40121082022450d1002402026422088a72201450d00200141047421232022210103400240200141046a280200450d00200128020010350b200141106a2101202341706a22230d000b0b202642ffffffff0083500d10202210350c100b4100212520022903f801211520022802f40121082021450d0e02402027422088a72201450d00200141286c21232021210103400240200141046a280200450d00200128020010350b0240200141106a280200450d002001410c6a28020010350b200141286a2101202341586a22230d000b0b2027a72201450d0e200141286c450d0e202110350c0e0b4100211220022903f801211520022802f40121012020450d0c200f42ffffffff0383500d0c202010350c0c0b4100210e20022903f801211520022802f4012101201f450d0a2013a72223450d0a2023410c6c450d0a201f10350c0a0b4100211020022903f801211520022802f4012101201e450d08200da72223450d082023410c6c450d08201e10350c080b4100210c20022903f801211520022802f4012110201d450d0602402028422088a72201450d00201d20014104746a210e201d21240340024020242802082223450d0020242802002101202341047421230340024020012d00004109470d000240200141046a2225280200220828020441ffffffff0371450d0020082802001035202528020021080b200810350b200141106a2101202341706a22230d000b0b202441106a21010240202441046a28020041ffffffff0071450d00202428020010350b200121242001200e470d000b0b202842ffffffff0083500d06201d10350c060b4100212420022903f801211520022802f40121082007450d0402402003422088a72201450d00200141146c21232007210103400240200141046a280200450d00200128020010350b200141146a21012023416c6a22230d000b0b2003a72201450d04200141146c450d04200710350c040b200241a0026a41086a2201201b41086a2802003602002002201b2902003703a00202402002280290012223450d0020024190016a10b2072002280294012208450d002008411c6c450d00202310350b20024190016a41086a2001280200360200200220022903a0023703900141002101410121124101210e410121104101210c410121240c0f0b200241a0026a41086a2201201b41086a2802003602002002201b2902003703a002024020022802a0012223450d00200241a0016a10b30720022802a4012208450d00200841186c450d00202310350b200241a0016a41086a2001280200360200200220022903a0023703a00141002123410121124101210e410121104101210c41012124410121010c0f0b200241a0026a41086a2201201b41086a2802003602002002201b2902003703a002024020022802b0012223450d00200241b0016a10b40720022802b4012208450d002008411c6c450d00202310350b200241b0016a41086a2001280200360200200220022903a0023703b00141002108410121124101210e410121104101210c410121244101210141012123410121250c0f0b4101211220022802f40121294101210e410121104101210c410121244101210141012123410121084101212541012116410121110c0e0b2015210320082107410121124101210e410121104101210c0c0a0b201521282010211d410121124101210e410121100c080b2015210d2001211e410121124101210e0c060b201521132001211f410121120c040b2015210f200121200c020b2015212720082121410121124101210e410121104101210c410121244101210141012123410121080c080b2015212620082122410121124101210e410121104101210c4101212441012101410121234101210841012125410021160c070b4101210e0b410121100b4101210c0b410121240b410121010b410121230b41012108410121250b02400240024002400240024002400240024002400240024020022d00f0012218417e6a2214410b4b0d0020140e0c0a09080706050400030002010a0b02402018410e4b0d00024002400240024002400240024002400240024002400240024020180e0f0001020304050607081809180a0b0c000b20022802f801450d1720022802f40110350c170b024020022802f801450d0020022802f40110350b200228028402450d1620022802800210350c160b20022802f4012108024020022802fc012201450d00200141047421232008210103400240200141046a280200450d00200128020010350b200141106a2101202341706a22230d000b0b20022802f80141ffffffff0071450d15200810350c150b20022802f4012108024020022802fc012201450d00200141286c21232008210103400240200141046a280200450d00200128020010350b0240200141106a280200450d002001410c6a28020010350b200141286a2101202341586a22230d000b0b20022802f8012201450d14200141286c450d14200810350c140b20022802f80141ffffffff0371450d1320022802f40110350c130b20022802f8012201450d122001410c6c450d1220022802f40110350c120b20022802f8012201450d112001410c6c450d1120022802f40110350c110b20022802f401210e024020022802fc012201450d00200e20014104746a210c200e21240340024020242802082223450d0020242802002101202341047421230340024020012d00004109470d000240200141046a2225280200220828020441ffffffff0371450d0020082802001035202528020021080b200810350b200141106a2101202341706a22230d000b0b202441106a21010240202441046a28020041ffffffff0071450d00202428020010350b200121242001200c470d000b0b20022802f80141ffffffff0071450d10200e10350c100b20022802f4012108024020022802fc012201450d00200141146c21232008210103400240200141046a280200450d00200128020010350b200141146a21012023416c6a22230d000b0b20022802f8012201450d0f200141146c450d0f200810350c0f0b201b10b20720022802f8012201450d0e2001411c6c450d0e20022802f40110350c0e0b201b10b30720022802f8012201450d0d200141186c450d0d20022802f40110350c0d0b201b10b40720022802f8012201450d0c2001411c6c450d0c20022802f40110350c0c0b024020022802f4012201450d0020022802f801450d00200110350b02402002280284022225450d000240200228028c022201450d002001410c6c2123202521010340024020012802002208450d00200141046a280200450d00200810350b2001410c6a2101202341746a22230d000b0b2002280288022201450d002001410c6c450d00202510350b200228029402220e450d0b0240200228029c022201450d00200e20014104746a210c200e212403402024222541106a2124024020252802042201450d0002402025410c6a2802002223450d002023410c6c21230340024020012802002208450d00200141046a280200450d00200810350b2001410c6a2101202341746a22230d000b0b202541086a2802002201450d002001410c6c450d00202528020410350b2024200c470d000b0b20022802980241ffffffff0071450d0b200e10350c0b0b024020022802f801450d0020022802f40110350b02402002280284022201450d00200228028802450d00200110350b20022802940241ffffffff0071450d0a20022802900210350c0a0b2008450d09201b10b40720022802f8012201450d092001411c6c450d0920022802f40110350c090b2023450d08201b10b30720022802f8012201450d08200141186c450d0820022802f40110350c080b2001450d07201b10b20720022802f8012201450d072001411c6c450d0720022802f40110350c070b2024450d0620022802f4012108024020022802fc012201450d00200141146c21232008210103400240200141046a280200450d00200128020010350b200141146a21012023416c6a22230d000b0b20022802f8012201450d06200141146c450d06200810350c060b200c450d0520022802f401210e024020022802fc012201450d00200e20014104746a210c200e21240340024020242802082223450d0020242802002101202341047421230340024020012d00004109470d000240200141046a2225280200220828020441ffffffff0371450d0020082802001035202528020021080b200810350b200141106a2101202341706a22230d000b0b202441106a21010240202441046a28020041ffffffff0071450d00202428020010350b200121242001200c470d000b0b20022802f80141ffffffff0071450d05200e10350c050b2010450d0420022802f8012201450d042001410c6c450d0420022802f40110350c040b200e450d0320022802f8012201450d032001410c6c450d0320022802f40110350c030b2012450d0220022802f80141ffffffff0371450d0220022802f40110350c020b2025450d0120022802f4012108024020022802fc012201450d00200141286c21232008210103400240200141046a280200450d00200128020010350b0240200141106a280200450d002001410c6a28020010350b200141286a2101202341586a22230d000b0b20022802f8012201450d01200141286c450d01200810350c010b2016450d0020022802f4012108024020022802fc012201450d00200141047421232008210103400240200141046a280200450d00200128020010350b200141106a2101202341706a22230d000b0b20022802f80141ffffffff0071450d00200810350b20040d000b410021040b2003420020071b211920284200201d1b2103200d4200201e1b211720134200201f1b210d200f420020201b21152027420020211b210f2026420020221b21132007410420071b2118201d4104201d1b210c201e4104201e1b2116201f4104201f1b210e2020410420201b21142021410420211b21102022410420221b2112200228020821012002280200210820022902b401212820022802b001210920022902a401212720022802a001210a2002290294012126200228029001210b0b02402001450d00200141047421232008210103400240200141046a280200450d00200128020010350b200141106a2101202341706a22230d000b0b0240200228020441ffffffff0071450d00200810350b200228020c2108024020022802142201450d00200141286c21232008210103400240200141046a280200450d00200128020010350b0240200141106a280200450d002001410c6a28020010350b200141286a2101202341586a22230d000b0b024020022802102201450d00200141286c450d00200810350b0240200228021c41ffffffff0371450d00200228021810350b024020022802282201450d002001410c6c450d00200228022410350b024020022802342201450d002001410c6c450d00200228023010350b200228023c211c024020022802442201450d00201c20014104746a2124201c211a03400240201a2802082223450d00201a2802002101202341047421230340024020012d00004109470d000240200141046a2225280200220828020441ffffffff0371450d0020082802001035202528020021080b200810350b200141106a2101202341706a22230d000b0b201a41106a21010240201a41046a28020041ffffffff0071450d00201a28020010350b2001211a20012024470d000b0b0240200228024041ffffffff0071450d00201c10350b20022802482108024020022802502201450d00200141146c21232008210103400240200141046a280200450d00200128020010350b200141146a21012023416c6a22230d000b0b0240200228024c2201450d00200141146c450d00200810350b200241dc006a10b207024020022802602201450d002001411c6c450d00200228025c10350b200241e8006a10b3070240200228026c2201450d00200141186c450d00200228026810350b200241f4006a10b407024020022802782201450d002001411c6c450d00200228027410350b2028420020091b212820274200200a1b212720264200200b1b21262009410420091b2101200a4104200a1b2123200b4104200b1b2108200228028001221a20022802880110f40602402002280284012225450d00202541306c450d00201a10350b200241d8006a202936020020022004360288012002200536028401200220063602800120022028370378200220013602742002202737026c20022023360268200220263703602002200836025c200220113602542002201937024c20022018360248200220033703402002200c36023c20022017370234200220163602302002200d3703282002200e3602242002201537021c200220143602182002200f3703102002201036020c200220133702042002201236020020002002418c01109d081a200241b0026a24000bd60401107f230041106b220224000240024020012802004101460d00200128020421030c010b200141106a2d000021042001410c6a2802002105200141086a280200210620012f0112210720012d0011210820012802042109200241086a200010bf0302400240200228020c220a450d0020022802082101200a41047441706a410476210b0240200841ff0171220c4104460d004100210a200441ff0171210d0340200a2103024020012d000c200d470d0020012802082005470d0002402001280200220a2009460d002005210e2009210f0340200e450d01200e417f6a210e200f2d00002110200a2d00002111200f41016a210f200a41016a210a20112010460d000c020b0b20012d000d220a200c470d00200a4104470d040b200141106a2101200341016a210a2003200b470d000c020b0b4100210a200441ff0171210d0340200a2103024020012d000c200d470d0020012802082005470d0002402001280200220a2009460d002005210e2009210f0340200e450d01200e417f6a210e200f2d00002110200a2d00002111200f41016a210f200a41016a210a20112010460d000c020b0b20012d000d4104460d030b200141106a2101200341016a210a2003200b470d000b0b024020002802082201200041046a280200470d00200020014101108c01200028020821010b200028020020014104746a220120073b010e200120083a000d200120043a000c2001200536020820012006360204200120093602002000200028020841016a3602082002200010bf032002280204417f6a21030c010b2006450d00200910350b200241106a240020030b9d1901217f23004180016b2202240041002103200241003602102002420437030820012802042104200128020021054101210641012107024020012802082208450d0041002107200241086a410041011089012002280208200228021041306c6a2203200836000c2003200436000820032005360004200341023a00002002200228021041016a22033602100b200141106a2802002109200128020c210a0240200141146a280200220b450d0002402003200228020c470d00200241086a20034101108901200228021021030b2002280208200341306c6a220320022f00713b0001200341033a00002003200b36000c200320093600082003200a36000420032002290218370210200341036a200241f3006a2d00003a0000200341186a200241206a290200370200200341206a200241286a290200370200200341286a200241186a41186a2902003702002002200228021041016a2203360210410021060b2001411c6a280200210c2001280218210d4100210e02400240200141206a280200220f0d00410021100c010b02402003200228020c470d00200241086a20034101108901200228021021030b2002280208200341306c6a220320022f00713b0001200341043a00002003200f36000c2003200c3600082003200d36000420032002290218370210200341036a200241f3006a2d00003a0000200341186a200241206a290200370200200341206a200241286a290200370200200341286a200241186a41186a290200370200410121102002200228021041016a22033602100b200141286a28020021112001280224211202402001412c6a280200220f450d0002402003200228020c470d00200241086a20034101108901200228021021030b2002280208200341306c6a220320022f00713b0001200341053a00002003200f36000c200320113600082003201236000420032002290218370210200341036a200241f3006a2d00003a0000200341186a200241206a290200370200200341206a200241286a290200370200200341286a200241186a41186a2902003702004101210e2002200228021041016a22033602100b200141346a28020021132001280230211402400240200141386a280200220f0d00410021150c010b02402003200228020c470d00200241086a20034101108901200228021021030b2002280208200341306c6a220320022f00713b0001200341063a00002003200f36000c200320133600082003201436000420032002290218370210200341036a200241f3006a2d00003a0000200341186a200241206a290200370200200341206a200241286a290200370200200341286a200241186a41186a290200370200410121152002200228021041016a22033602100b200141c0006a2802002116200128023c21174101211802400240200141c4006a28020022190d004101211a0c010b02402003200228020c470d00200241086a20034101108901200228021021030b2002280208200341306c6a220320022f00713b0001200341073a00002003201936000c200320163600082003201736000420032002290218370210200341036a200241f3006a2d00003a0000200341186a200241206a290200370200200341206a200241286a290200370200200341286a200241186a41186a2902003702002002200228021041016a22033602104100211a0b200141cc006a280200211b2001280248211c0240200141d0006a280200221d450d0002402003200228020c470d00200241086a20034101108901200228021021030b2002280208200341306c6a220320022f00713b0001200341083a00002003201d36000c2003201b3600082003201c36000420032002290218370210200341036a200241f3006a2d00003a0000200341186a200241186a41086a290200370200200341206a200241286a290200370200200341286a200241186a41186a2902003702002002200228021041016a2203360210410021180b4101211e024020012802544101470d00200141d8006a280200210f02402003200228020c470d00200241086a20034101108901200228021021030b2002280208200341306c6a220320022f00713b0001200341093a00002003200f36020420032002290218370208200341036a200241f3006a2d00003a0000200341106a200241206a290200370200200341186a200241186a41106a290200370200200341206a200241186a41186a290200370200200341286a200241186a41206a2902003702002002200228021041016a22033602100b200241c0006a41086a221f200141e4006a280200220f3602002002200129025c3703400240200f450d00200241fc006a201f2802003600002002200229034037007402402003200228020c470d00200241086a20034101108901200228021021030b2002280208200341306c6a220320022900713700012003410a3a000020032002290218370210200341086a200241f8006a290000370000200341186a200241186a41086a290200370200200341206a200241286a290200370200200341286a200241186a41186a2902003702002002200228021041016a22033602104100211e0b200241d0006a41086a200141f0006a280200220f3602002002200129026837035002400240200f0d00410121200c010b200241fc006a200241d0006a41086a2802003600002002200229035037007402402003200228020c470d00200241086a20034101108901200228021021030b2002280208200341306c6a220320022900713700012003410c3a000020032002290218370210200341086a200241f8006a290000370000200341186a200241186a41086a290200370200200341206a200241286a290200370200200341286a200241186a41186a2902003702002002200228021041016a2203360210410021200b200241e8006a221f200141fc006a280200220f3602002002200129027437036002400240200f0d00410121210c010b200241fc006a201f2802003600002002200229036037007402402003200228020c470d00200241086a20034101108901200228021021030b2002280208200341306c6a220320022900713700012003410d3a000020032002290218370210200341086a200241f8006a290000370000200341186a200241186a41086a290200370200200341206a200241286a290200370200200341286a200241186a41186a2902003702002002200228021041016a2203360210410021210b20014184016a280200210f200128028001211f200241086a200320014188016a28020041306c220141306d222210890120022802082002280210220341306c6a201f2001109d081a2002200320226a3602100240200f450d00200f41306c450d00201f10350b200241186a41086a2201200241086a41086a280200360200200220022903083703180240024041800610332203450d0020004280c2cdeb1637020020002002290318370208200041106a2001280200360200200310352021450d01200241e0006a10b40720022802642201450d012001411c6c450d01200228026010350c010b1045000b02402020450d00200241d0006a10b30720022802542201450d00200141186c450d00200228025010350b0240201e450d00200241c0006a10b20720022802442201450d002001411c6c450d00200228024010350b02402018450d000240201d450d00201d41146c2103201c210103400240200141046a280200450d00200128020010350b200141146a21012003416c6a22030d000b0b201b450d00201b41146c450d00201c10350b0240201a450d0002402019450d00201720194104746a211e201721180340024020182802082203450d0020182802002101200341047421030340024020012d00004109470d000240200141046a220f280200220028020441ffffffff0371450d0020002802001035200f28020021000b200010350b200141106a2101200341706a22030d000b0b201841106a21010240201841046a28020041ffffffff0071450d00201828020010350b200121182001201e470d000b0b201641ffffffff0071450d00201710350b02402013452015720d002013410c6c450d00201410350b0240201145200e720d002011410c6c450d00201210350b0240200c41ffffffff0371410047201041017371450d00200d10350b02402006450d000240200b450d00200b41286c2103200a210103400240200141046a280200450d00200128020010350b0240200141106a280200450d002001410c6a28020010350b200141286a2101200341586a22030d000b0b2009450d00200941286c450d00200a10350b02402007450d0002402008450d00200841047421032005210103400240200141046a280200450d00200128020010350b200141106a2101200341706a22030d000b0b200441ffffffff0071450d00200510350b20024180016a24000ba01302147f027e23004180026b220424000240024020014115490d0041012105410121060240024002400340200121072000210820052006714101732109024002400240024002400240034002400240024002402003450d00024020054101710d002000200110c8072003417f6a21030b2001410276220a41036c210b200a410174210c4100210d024020014132490d00200b200b417f6a220d2000200b4103746a280200220e2000200d4103746a280200220f4922101b2211200b41016a2212200d200b20101b200020124103746a280200220b200f200e20101b220d49220f1b200b200d200f1b200020114103746a2802004922131b210b200c200c417f6a220d2000200c4103746a28020022112000200d4103746a280200221249220e1b2214200c4101722206200d200c200e1b200020064103746a280200220c20122011200e1b220d4922111b200c200d20111b200020144103746a2802004922141b210c200a200a417f6a22122000200a4103746a2802002206200020124103746a280200221549220d1b2216200a41016a22172012200a200d1b200020174103746a280200220a20152006200d1b22064922121b200a200620121b200020164103746a2802004922061b210a41024101200d1b200d20121b20066a200e6a20116a20146a20106a200f6a20136a210d0b200d2000200c4103746a280200220e2000200a4103746a280200220f4922106a2000200b4103746a280200220d200f200e20101b221149220f6a210e200d2011200f1b2000200c200a20101b220d4103746a280200490d01200b200a200c20101b200f1b210d0c020b2000200110d9070c0f0b200e41016a220e410c490d0002402001410176220b450d00200020014103746a41786a210a2000210c0340200c2902002118200c200a290200370200200a2018370200200c41086a210c200a41786a210a200b417f6a220b0d000b0b2001200d417f736a210d4101210a0c010b200e45210a0b0240200a452009724101710d002000200110da070d0d0b2002450d02200d20014f0d01024020022802002000200d4103746a220a2802004f0d0020002108200121070c040b200029020021182000200a290200370200200a2018370200200041786a210f200041086a211120002902002218a721104100210c2001210b03400240200c200b417f6a220d4f0d002011200c4103746a210a0340200a28020020104b0d01200a41086a210a200d200c41016a220c470d000b200d210c0b200f200b4103746a210a02400340200c200b417f6a220b4f0d01200a280200210d200a41786a220e210a200d20104b0d000b2011200c4103746a220a2902002119200a200e41086a220d290200370200200d2019370200200c41016a210c0c010b0b2000201837020002402001200c41016a220a490d002000200a4103746a21002001200a6b220141154f0d010c0c0b0b200a200141e485cc001059000b200d200141d086cc001042000b2007450d010b200d20074f0d012008290200211820082008200d4103746a220a290200370200200a2018370200200841086a210e20082902002219a72111410021142007417f6a2210450d02200e210a0340200a28020020114f0d03200a41086a210a2010201441016a2214470d000b201021140c020b4100410041f485cc001042000b200d2007418486cc001042000b200820074103746a210c2010210b02400340200c210d200b220a20144d22060d01200a417f6a210b200d41786a220c28020020114f0d000b0b0240200a2014490d002010200a490d0241800121054100210b410021014100210c4100210f4180012109200e20144103746a2215211003400240200d20106b220a4187104b22130d00200a410376220a41807f6a200a2001200b49200f200c49220e7222001b210a02402000450d002009200a200e1b2109200a2005200e1b21050c010b200a200a41017622096b21050b0240200f200c470d00024020090d002004220c210f0c010b4100210a2004220f210c2010210e0340200c200a3a0000200c200e28020020114f6a210c200e41086a210e2009200a41016a220a470d000b0b02402001200b470d00024020050d0020044180016a220b21010c010b200d41786a210a4100210e20044180016a2201210b0340200b200e3a0000200b200a2802002011496a210b200a41786a210a2005200e41016a220e470d000b0b0240200b20016b220a200c200f6b220e200e200a4b1b2212450d002010200f2d00004103746a220a2902002118200a200d20012d0000417f734103746a290200370200024020124101460d004100210a0340200d2001200a6a220e2d0000417f734103746a2010200f200a6a41016a22002d00004103746a290200370200201020002d00004103746a200d200e41016a2d0000417f734103746a290200370200200a41026a210e200a41016a2200210a200e2012490d000b200120006a2101200f20006a210f0b200d20012d0000417f734103746a2018370200200141016a2101200f41016a210f0b200d20054103746b200d2001200b461b210d201020094103746a2010200f200c461b211020130d000b02400240200f200c4f0d00200d210a03402010200c417f6a220c2d00004103746a220b2902002118200b200a41786a220a290200370200200a2018370200200f200c490d000c020b0b2010210a2001200b4f0d000340200a2902002118200a200d200b417f6a220b2d0000417f734103746a220c290200370200200c2018370200200a41086a210a2001200b490d000b0b200820193702002007200a20156b41037620146a22014d0d032008200820014103746a220a290200370200200a2019370200200720016b220c450d04200c20012001200c4b1b210b2007410376210d200a41086a2100024002402001200c417f6a220c490d002000200c200a200310f206200821000c010b200820012002200310f206200a2102200c21010b200b200d4f2105200141154f0d010c050b0b2014200a419486cc001059000b200a2010419486cc001058000b20012007418486cc001042000b41a486cc00411c41c086cc00103f000b20014102490d00200041786a21104100210e4101210b0340200b410374210c200b417f6a210a200b41016a210b02402000200c6a220d2802002000200a4103746a220f2802004f0d00200d2902002118200d200f2902003702000240200a450d00200e210c2010210a200d41706a2802002018a7220d4d0d00024002400340200a41086a200a290200370200200c4101460d01200c417f6a210c200a41786a220a280200200d4b0d000c020b0b4100210c0b2000200c4103746a210f0b200f20183702000b200e41016a210e201041086a2110200b2001470d000b0b20044180026a24000b9c0402077f017e230041306b22022400200241106a2203200141246a290200370300200241086a22042001411c6a29020037030020022001290214370300200241186a41106a2205200141106a280200360200200241186a41086a2206200141086a290200370300200220012902003703182000200241186a10f00621070240200041206a28020022082000411c6a280200470d00200041186a20084101108601200028022021080b200028021820084102746a20073602002000200028022041016a3602202005200329030037030020062004290300370300200220022903003703180240200041f0006a22032802002208200041ec006a280200470d000240024002400240200841016a22042008490d00200841017422052004200520044b1bad42187e2209422088a70d002009a722044100480d00024020080d0020040d02410421050c040b20002802682105200841186c22082004460d03024020080d0020040d02410421050c040b20052008200410372205450d020c030b103e000b2004103322050d010b103c000b20002005360268200041ec006a200441186e360200200041f0006a28020021080b2000280268200841186c6a22082002290318370200200841106a200241186a41106a290300370200200841086a200241186a41086a29030037020020032003280200220841016a360200024020012d002c450d0020004101360254200041d8006a20083602000b200241306a24000bcf0f01077f02402001450d002000200141306c6a210203402000220341306a21000240024020032d00002201410e4b0d00024002400240024002400240024002400240024002400240024020010e0f0001020304050607080e090e0a0b0c000b200341086a280200450d0d200341046a28020010350c0d0b0240200341086a280200450d00200341046a28020010350b200341146a280200450d0c200341106a28020010350c0c0b02402003410c6a2802002204450d00200341046a28020021012004410474210403400240200141046a280200450d00200128020010350b200141106a2101200441706a22040d000b0b200341086a28020041ffffffff0071450d0b200328020410350c0b0b02402003410c6a2802002204450d00200341046a2802002101200441286c210403400240200141046a280200450d00200128020010350b0240200141106a280200450d002001410c6a28020010350b200141286a2101200441586a22040d000b0b200341086a2802002201450d0a200141286c450d0a200328020410350c0a0b200341086a28020041ffffffff0371450d09200341046a28020010350c090b200341086a2802002201450d082001410c6c450d08200341046a28020010350c080b200341086a2802002201450d072001410c6c450d07200341046a28020010350c070b02402003410c6a2802002201450d00200341046a280200220520014104746a21060340024020052802082204450d0020052802002101200441047421040340024020012d00004109470d000240200141046a2207280200220828020441ffffffff0371450d0020082802001035200728020021080b200810350b200141106a2101200441706a22040d000b0b200541106a21010240200541046a28020041ffffffff0071450d00200528020010350b2001210520012006470d000b0b200341086a28020041ffffffff0071450d06200328020410350c060b02402003410c6a2802002204450d00200341046a2802002101200441146c210403400240200141046a280200450d00200128020010350b200141146a21012004416c6a22040d000b0b200341086a2802002201450d05200141146c450d05200328020410350c050b02402003410c6a2802002201450d00200341046a28020022052001411c6c6a21060340024020052802042201450d0002402005410c6a2802002204450d00200441047421040340024020012d00004109470d000240200141046a2207280200220828020441ffffffff0371450d0020082802001035200728020021080b200810350b200141106a2101200441706a22040d000b0b200541086a28020041ffffffff0071450d00200528020410350b2005411c6a21010240200541146a28020041ffffffff0371450d00200528021010350b2001210520012006470d000b0b200341086a2802002201450d042001411c6c450d04200328020410350c040b02402003410c6a2802002201450d00200341046a2802002205200141186c6a210603400240200541046a28020041ffffffff0171450d00200528020010350b0240200541146a2802002204450d00200528020c2101200441047421040340024020012d00004109470d000240200141046a2207280200220828020441ffffffff0371450d0020082802001035200728020021080b200810350b200141106a2101200441706a22040d000b0b200541186a21010240200541106a28020041ffffffff0071450d00200528020c10350b2001210520012006470d000b0b200341086a2802002201450d03200141186c450d03200328020410350c030b02402003410c6a2802002201450d00200341046a28020022052001411c6c6a21060340024020052802042201450d0002402005410c6a2802002204450d00200441047421040340024020012d00004109470d000240200141046a2207280200220828020441ffffffff0371450d0020082802001035200728020021080b200810350b200141106a2101200441706a22040d000b0b200541086a28020041ffffffff0071450d00200528020410350b2005411c6a21010240200541146a280200450d00200528021010350b2001210520012006470d000b0b200341086a2802002201450d022001411c6c450d02200328020410350c020b0240200341046a2802002201450d00200341086a280200450d00200110350b0240200341146a2802002201450d0002402003411c6a2802002204450d002004410c6c21040340024020012802002208450d00200141046a280200450d00200810350b2001410c6a2101200441746a22040d000b0b200341186a2802002201450d002001410c6c450d00200328021410350b200341246a2802002205450d0102402003412c6a2802002201450d00200520014104746a210603402005220741106a2105024020072802042201450d0002402007410c6a2802002204450d002004410c6c21040340024020012802002208450d00200141046a280200450d00200810350b2001410c6a2101200441746a22040d000b0b200741086a2802002201450d002001410c6c450d00200728020410350b20052006470d000b0b200341286a28020041ffffffff0071450d01200328022410350c010b0240200341086a280200450d00200341046a28020010350b0240200341146a2802002201450d00200341186a280200450d00200110350b200341246a28020041ffffffff0071450d00200341206a28020010350b20002002470d000b0b0b8f7205077f017e277f047e077f23002203210420034180096b416071220324000240411010332205450d00200541063a0000412010332206450d00200641063a001020064100360204200620032f00e0043b00012006412d3a0000200641036a200341e2046a2d00003a0000024020052d00004109470d0002402005280204220728020441ffffffff0371450d0020072802001035200528020421070b200710350b20051035200141106a28020041306c2105200128020841546a21070240024002400240024002400240024002400340024020050d00411010332207450d0b20074180023b010c200742828080802037020420072006360200200720032f01d0033b010e200128021022052001410c6a280200470d03200541016a22082005490d05200541017422092008200920084b1bad42307e220a422088a70d05200aa722084100480d050240024020050d0020080d01410421090c040b20012802082109200541306c22052008460d03024020050d0020080d01410421090c040b20092005200810372209450d0c0c030b2008103322090d020c0b0b200541506a21052007412c6a2108200741306a2209210720082d00004107470d000b200320032f01d0033b01e0040240200941086a22072802002205200941046a280200470d00200920054101108c01200728020021050b200928020020054104746a22054180023b010c200542828080802037020420052006360200200520032f01e0043b010e2007200728020041016a360200200341306a200910bf032003280234417f6a210b2001280210210c0c020b200120093602082001410c6a200841306e360200200128021021050b2001280208200541306c6a220520032f00f0073b0001200541073a0000200542818080801037000820052007360004200520032902e004370210200541036a200341f2076a2d00003a0000200541186a200341e8046a290200370200200541206a200341f0046a290200370200200541286a200341e0046a41186a2902003702002001200128021041016a220c3602104100210b0b200c41306c21052001280208220d41546a210702400340410021082005450d01200541506a21052007412c6a2109200741306a2206210720092d00004103470d000b200641086a2802002205450d00200541286c2107200628020041186a2105410021080340200820052d0000456a2108200541286a2105200741586a22070d000b0b200c41306c2105200d41546a210702400340410021092005450d01200541506a21052007412c6a2106200741306a220e210720062d00004103470d000b200e41086a2802002205450d00200541286c2107200e28020041186a2105410021090340200920052d0000456a2109200541286a2105200741586a22070d000b0b200c41306c2105200d415c6a210702400340024020050d00410021050c020b200541506a2105200741246a2106200741306a220e210720062d00004104470d000b200e28020021050b200341003602d00302400240200520096a220d0d004104210f41002110410021110c010b0240024002402008450d00200342003703e004410021050c010b200341e0046a4100200110e40720032802e404210520032802e0044101470d00200341e8046a290300210a024020032802d0032207450d0020032802d403450d00200710350b2003200a3702d403200320053602d003410021114104210f410021100c010b41041033220c450d07200c200536020020034281808080103702f4072003200c3602f0070240200d4102490d0002400240024020084102490d00200342003703e0044100210e0c010b200341e0046a4101200110e40720032802e404210e20032802e0044101470d00200341e8046a290300210a024020032802d003450d0020032802d403450d0020032802d00310350b2003200a3702d4030c010b4104210941012106410121070340200741016a2105024020072006470d00200341f0076a2006410110860120032802f007210c0b200c20096a200e360200200320053602f8072005200d4f0d0202400240200820054d0d00200342003703e0044100210e0c010b200341e0046a2005200110e40720032802e404210e20032802e0044101470d0020032903e804210a024020032802d003450d0020032802d403450d0020032802d00310350b2003200a3702d4030c020b200941046a210920032802f4072106200521070c000b0b2003200e3602d0030b20032802d003210520032802f807211020032802f407211120032802f007210f0b2005450d0020032902d403210a0240201141ffffffff0371450d00200f10350b2000200536020420004101360200200041086a200a3702000c040b024020012802102205450d0020012802082212200541306c6a2113200341e0046a41106a2114200341d0066a210e20034184056a211520034194056a2116200341a4056a2117200341b4056a2118200341c4056a2119200341d4056a211a200341e4056a211b200341f4056a211c20034184066a211d20034194066a211e200341a4066a211f200341b4066a2120200341c4066a21210340024020122d0000410c470d00201228020c2205450d0020122802042206200541186c6a212203400240200641146a22232802002205450d002006410c6a21244100210c034002400240024002400240200c20054f0d00410121052024280200200c410474220d6a22072d0000410b470d042003200741046a22073602c0022007280200220720104f0d01200f20074102746a2802002208450d042003200b3602c406200341133a00c006200341d7003a00b006200320083602a4062003412d3a00a0062003200b36029406200341123a00900620032007360284062003410b3a008006200341063a00f005200341003a00e00520034184083b01d005200341373a00c005200320023602b4052003412d3a00b0052003200b3602a405200341123a00a0052003200b36029405200341133a009005200341d6003a008005200320083602f4042003412d3a00f0042003200b3602e404200341123a00e004200c41016a212520232802002226200c4d0d022023200c360200200628020c2205202541047422276a2108024002402005200d6a22282d0000220941ac01470d00202841106a21090c010b4100210502400340202820056a21070240200941ff01714109470d000240200741046a280200220928020441ffffffff0371450d00200928020010350b200910350b2005450d01200541106a2105200741106a2d0000220941ac01470d000b202820056a41106a21090c010b200741106a21090b202620256b212920082107024020092008460d0002400340200922052d0000220741ac01460d01024020074109470d000240200541046a280200220728020441ffffffff0371450d00200728020010350b200710350b200541106a22092008470d000b0b200541106a21070b02400240024002402029450d00200341e0046a21050240202520062802142209460d00200d200941047422056b41106a210d200628020c20056a2109200341e0046a21050340200341f0076a41002005200e200546222a1b10e30720032d00f00741ac01460d052005200541106a202a1b2105200920032903f007370300200941086a200341f0076a41086a2903003703002006200628021441016a360214200941106a2109200d41706a220d0d000b0b200e20056b220d41047621090240200d450d00202420262009109a01200628020c222a202520096a22254104746a202a20276a2029410474109e081a20252006280214222a460d00200c200d4104766a410474202a41047422096b41106a210d200628020c20096a21090340200341f0076a41002005200e200546222a1b10e30720032d00f00741ac01460d052005200541106a202a1b2105200920032903f007370300200941086a200341f0076a41086a2903003703002006200628021441016a360214200941106a2109200d41706a220d0d000b200e20056b41047621090b200341003602d803200342083703d003200341d0036a41002009109a0120032802d803210d20032802d003212b200341f0076a41002005200e20054622091b10e307024020032d00f00741ac01460d002005200541106a20091b2105202b200d4104746a21090340200920032903f007370300200941086a200341f0076a41086a290300370300200341f0076a41002005200e200546222a1b10e3072005200541106a202a1b2105200d41016a210d200941106a210920032d00f00741ac01470d000b0b202b200d41047422266a212a20032802d403212c200d0d01202b21050c020b20242023280200410f109a012023280200210d200628020c2105200341f0076a200341e0046a10e307024020032d00f00741ac01460d002005200d4104746a2109201421050340200920032903f007370300200941086a200341f0076a41086a290300370300200341f0076a41002005200e200546222a1b10e3072005200541106a202a1b2105200d41016a210d200941106a210920032d00f00741ac01470d000b0b2023200d3602000c020b2024202920256a20264104752205109a0120254104742109200628020c220d202520056a222541047422056a200d20096a2029410474109e081a0240202520062802142209470d00202b21050c010b200628020c220d20056a212d200d20094104746a210d202b21090340024020260d00202a21050c020b200341f0076a41026a2205200941036a2d00003a0000200320092f00013b01f007024020092d0000222741ac01470d00200941106a21050c020b200941046a280200212e200941086a290300210a200d20273a0000200d41086a200a370300200d41046a202e36020020032f01f0072127200d41036a20052d00003a0000200d41016a20273b00002006200628021441016a360214202641706a2126200941106a22052109200d41106a220d202d470d000b0b0240202a2005460d000340200541106a2109024020052d00004109470d000240200541046a220d280200220528020441ffffffff0371450d0020052802001035200d28020021050b200510350b20092105202a2009470d000b0b202c41ffffffff0071450d00202b10350b20072008460d0303400240024020072d000022054109460d00200541ac01470d0120282007460d06200741106a2105034020052d0000220741ac01460d07024020074109470d000240200541046a280200220728020441ffffffff0371450d00200728020010350b200710350b200541106a22052008470d000c070b0b0240200741046a280200220528020441ffffffff0371450d00200528020010350b200510350b200741106a22072008470d000c040b0b200c2005418490cc001042000b200341013602f404200342013702e4042003419490cc003602e0042003413c3602d4032003200341d0036a3602f0042003200341c0026a3602d003200341f0076a200341e0046a104120032802f0072205450d0420032902f407210a2000200536020420004101360200200041086a200a370200201141ffffffff0371450d0c200f10350c0c0b20252026104f000b02402029450d000240202520232802002205460d002024280200220720054104746a200720254104746a2029410474109e081a0b2023202920056a3602000b024020032d00e0044109470d00024020032802e404220528020441ffffffff0371450d002005280200103520032802e40421050b200510350b024020032d00f0044109470d000240200341e0046a41146a280200220528020441ffffffff0371450d002005280200103520032802f40421050b200510350b024020032d0080054109470d0002402015280200220528020441ffffffff0371450d002005280200103520032802840521050b200510350b024020032d0090054109470d0002402016280200220528020441ffffffff0371450d002005280200103520032802940521050b200510350b024020032d00a0054109470d0002402017280200220528020441ffffffff0371450d002005280200103520032802a40521050b200510350b024020032d00b0054109470d0002402018280200220528020441ffffffff0371450d002005280200103520032802b40521050b200510350b024020032d00c0054109470d0002402019280200220528020441ffffffff0371450d002005280200103520032802c40521050b200510350b024020032d00d0054109470d000240201a280200220528020441ffffffff0371450d002005280200103520032802d40521050b200510350b024020032d00e0054109470d000240201b280200220528020441ffffffff0371450d002005280200103520032802e40521050b200510350b024020032d00f0054109470d000240201c280200220528020441ffffffff0371450d002005280200103520032802f40521050b200510350b024020032d0080064109470d000240201d280200220528020441ffffffff0371450d002005280200103520032802840621050b200510350b024020032d0090064109470d000240201e280200220528020441ffffffff0371450d002005280200103520032802940621050b200510350b024020032d00a0064109470d000240201f280200220528020441ffffffff0371450d002005280200103520032802a40621050b200510350b024020032d00b0064109470d0002402020280200220528020441ffffffff0371450d002005280200103520032802b40621050b200510350b024020032d00c0064109470d0002402021280200220528020441ffffffff0371450d002005280200103520032802c40621050b200510350b410f21050b2005200c6a220c20232802002205490d000b0b200641186a22062022470d000b0b201241306a22122013470d000b0b200341386a41106a200141106a280200220c360200200341386a41086a200141086a290200220a37030020032001290200370338410021062003410036025820034204370350200c41306c2105200aa7220d41546a210702400340024020050d000c020b200541506a21052007412c6a2108200741306a2209210720082d00004108470d000b200341286a200910bf0320032802282106200328022c21050b4100210e2005410020061b212a200c41306c2105200d41546a2108200641b0b4cc0020061b210702400340024020050d000c020b200541506a21052008412c6a2109200841306a2206210820092d0000410a470d000b200341206a200610bf032003280220210e200328022421050b20054100200e1b2128200c41306c2105200d41546a2109200e41b0b4cc00200e1b210802400340024020050d004200210a0c020b200541506a21052009412c6a2106200941306a220e210920062d00004109470d000b200e28020021054201210a0b20034100360278200341003602702007202a41146c6a212520082028411c6c6a21242005ad422086200a84210a200341f0076a410272221541266a2116201541206a2117201541186a2118201541106a2119201541086a211a200341f0076a41286a211b4100212a410121260240024003400240024002400240024020264102460d000240024002402007450d0020252007460d000340200741146a21092007410c6a280200450d022009210720252009470d000b0b4100210720264101470d02202a2105034002402005450d004100212a20052028460d00200541046a212a410121264100210720050d030c040b20242008460d03200341186a200810bf072008411c6a210820032802182205450d032005200328021c4102746a21282005212a0c000b0b200741106a2105200921070b200528020021050c010b0240200aa722054102460d002005450d00200a422088a721054200210a410221260c010b200341e0006a41086a200341f0006a41086a280200360200200320032903703703602003280248220e41306c21052003280240220c41546a210702400340410021082005450d01200541506a21052007412c6a2109200741306a2206210720092d00004103470d000b200641086a2802002205450d00200541286c2107200628020041186a2105410021080340200820052d0000456a2108200541286a2105200741586a22070d000b0b200e41306c2105200c415c6a210702400340024020050d00410021050c020b200541506a2105200741246a2109200741306a2206210720092d00004104470d000b200628020021050b200341e0046a41106a2229200341386a41106a280200360200200341e0046a41086a200341386a41086a290300370300200320032903383703e004200341b0016a200341e0046a10ef062003280250212f20032802542130024020032802582207450d00202f20074102746a2124200520086a212a200341e0046a41e0016a2126200341e0046a41d0016a2127200341e0046a41c0016a212e200341e0046a41b0016a2110200341e0046a41a0016a212b200341e0046a4190016a212d200341e0046a4180016a212c200341e0046a41f0006a2115200341e0046a41e0006a2116200341e0046a41d0006a2117200341e0046a41c0006a2118200341e0046a41306a2119200341e0046a41206a211a200341f7076a211b20034194056a211c200341a4056a211d200341b4056a211e200341c4056a211f200341d4056a2120200341e4056a2121200341f4056a212220034184066a211420034194066a2112200341a4066a2101200341b4066a2113200341c4066a2131202f21050240034020032802602207450d01200541046a2123200528020021062003280264210d034020072f01062225410274210c41002109417f210841002105024003400240200c2005470d00202521080c020b200720056a210e200841016a2108200941206a2109200541046a21050240417f200e41086a280200220e200647200e20064b1b41016a0e03020001020b0b200720096a220e412c6a2802002107200e41306a28020021052003200b3602c406200341133a00c006200341d7003a00b006200320053602a4062003412d3a00a0062003200b36029406200341123a00900620032007360284062003410b3a008006200341063a00f005200341003a00e00520034184083b01d005200341373a00c005200320023602b4052003412d3a00b0052003200b3602a405200341123a00a0052003200b36029405200341133a009005200341d6003a008005200320053602f4042003412d3a00f0042003200b3602e404200341123a00e004200e411c6a220c280200220841106a220541ffffffff00712005470d0620054104742207417f4c0d060240024020070d00410821090c010b200710332209450d12200c28020021080b41002105200341003602880120032009360280012003200741047622073602840102402008450d002008417f6a210641002105410021080340024020052007470d0020034180016a20074101109a01200328028001210920032802880121050b200920054104746a2207410f3a000020072008360204200720032f01f0073b0001200741036a200341f0076a41026a2d00003a00002003200541016a22053602880120062008460d01200841016a210820032802840121070c000b0b20034180016a2005410f109a0120032802880121092003280280012108200341f0076a200341e0046a10d707200820094104746a220541086a200341f0076a41086a2207290300370300200520032903f007370300200341f0076a202910d707200541186a2007290300370300200520032903f007370310200341f0076a201a10d707200541286a2007290300370300200541206a20032903f007370300200341f0076a201910d707200541386a2007290300370300200541306a20032903f007370300200341f0076a201810d707200541c8006a2007290300370300200541c0006a20032903f007370300200341f0076a201710d707200541d8006a2007290300370300200541d0006a20032903f007370300200341f0076a201610d707200541e8006a2007290300370300200541e0006a20032903f007370300200341f0076a201510d707200541f8006a2007290300370300200541f0006a20032903f007370300200341f0076a202c10d70720054188016a200729030037030020054180016a20032903f007370300200341f0076a202d10d70720054198016a200729030037030020054190016a20032903f007370300200341f0076a202b10d707200541a8016a2007290300370300200541a0016a20032903f007370300200341f0076a201010d707200541b8016a2007290300370300200541b0016a20032903f007370300200341f0076a202e10d707200541c8016a2007290300370300200541c0016a20032903f007370300200341f0076a202710d707200541d8016a2007290300370300200541d0016a20032903f007370300200341f0076a202610d707200541e0016a20032903f007370300200541e8016a200729030037030020032009410f6a22053602880102402005200328028401470d0020034180016a20054101109a01200328028001210820032802880121050b200820054104746a220720032900f007370001200741063a0000200741086a201b2900003700002003200541016a36028801200341f0076a200341b0016a418c01109d081a411010332207450d12200741063a0000200341d0036a200341f0076a418c01109d081a200c2802002205417f4c0d06200e41146a280200210c0240024020050d0041002108410121060c010b200510332206450d12200521080b0240024020082005490d00200821090c010b200841017422092005200920054b1b22094100480d0d024020080d00200910332206450d140c010b20082009460d0020062008200910372206450d130b2006200c2005109d0821080240024020050d00410021064101210c0c010b20051033220c450d13200521060b200c20082005109d08210c02402009450d00200810350b200341c0026a200341d0036a418c01109d081a200e41216a3100002132200341f0076a200341c0026a418c01109d081a200341d0036a200341f0076a418c01109d081a411010332208450d12202841807e712128200a428080808080804083220a2005ad842032422886844280808080800c842132200841063a000020032802880121052003280284012109200328028001210d20081035200341c0026a200341d0036a418c01109d081a200341f0076a200341c0026a418c01109d081a024020072d00004109470d0002402007280204220828020441ffffffff0371450d0020082802001035200728020421080b200810350b20071035200341d0036a200341f0076a418c01109d081a200341f0076a200341d0036a418c01109d081a200320283602ec02200320053602e802200320093602e4022003200d3602e002200341003602dc02200342043702d402200320323702cc02200320063602c8022003200c3602c402200341013602c002200341f0076a200341c0026a10f306200341b0016a200341f0076a418c01109d081a200e41286a202a360200200e41246a4101360200024020032d00e0044109470d00024020032802e404220528020441ffffffff0371450d002005280200103520032802e40421050b200510350b024020032d00f0044109470d000240200341e0046a41146a280200220528020441ffffffff0371450d002005280200103520032802f40421050b200510350b024020032d0080054109470d000240200341e0046a41246a280200220528020441ffffffff0371450d002005280200103520032802840521050b200510350b024020032d0090054109470d000240201c280200220528020441ffffffff0371450d002005280200103520032802940521050b200510350b024020032d00a0054109470d000240201d280200220528020441ffffffff0371450d002005280200103520032802a40521050b200510350b024020032d00b0054109470d000240201e280200220528020441ffffffff0371450d002005280200103520032802b40521050b200510350b024020032d00c0054109470d000240201f280200220528020441ffffffff0371450d002005280200103520032802c40521050b200510350b024020032d00d0054109470d0002402020280200220528020441ffffffff0371450d002005280200103520032802d40521050b200510350b024020032d00e0054109470d0002402021280200220528020441ffffffff0371450d002005280200103520032802e40521050b200510350b024020032d00f0054109470d0002402022280200220528020441ffffffff0371450d002005280200103520032802f40521050b200510350b024020032d0080064109470d0002402014280200220528020441ffffffff0371450d002005280200103520032802840621050b200510350b024020032d0090064109470d0002402012280200220528020441ffffffff0371450d002005280200103520032802940621050b200510350b024020032d00a0064109470d0002402001280200220528020441ffffffff0371450d002005280200103520032802a40621050b200510350b024020032d00b0064109470d0002402013280200220528020441ffffffff0371450d002005280200103520032802b40621050b200510350b024020032d00c0064109470d0002402031280200220528020441ffffffff0371450d002005280200103520032802c40621050b200510350b200a4280808080808c0184210a202a41016a212a2023210520232024470d020c040b200d450d02200d417f6a210d200720084102746a4194036a28020021070c000b0b0b41a081cc0041800141a082cc001064000b0240203041ffffffff0371450d00202f10350b200341e0046a200341b0016a418c01109d081a200341f0076a200341e0046a10f106024020034180086a2802002205450d0020032802f8072226200541306c6a21272003280264210b200328026021280340024020262d000041786a220541024b0d0002400240024020050e03000102000b202628020c2207450d0220262802042205200741146c6a212a03400240200528020c0d002028450d002005280210210d20282106200b21230340200641286a2109200641086a210820062f010622254102742107417f210e02400340024020070d002025210e0c020b2008280200210c200e41016a210e200941206a21092007417c6a2107200841046a21080240417f200c200d47200c200d4b1b41016a0e03020001020b0b02402009417c6a280200450d00200520092802003602100c030b41b082cc00413541e882cc001064000b2023450d012023417f6a21232006200e4102746a4194036a28020021060c000b0b200541146a2205202a470d000c030b0b2028450d012026280204210c20282109200b210d0340200941286a2108200941086a210720092f0106222a4102742105417f210602400340024020050d00202a21060c020b2007280200210e200641016a2106200841206a21082005417c6a2105200741046a21070240417f200e200c47200e200c4b1b41016a0e03020001020b0b02402008417c6a280200450d00202620082802003602040c040b41b082cc00413541e882cc001064000b200d450d02200d417f6a210d200920064102746a4194036a28020021090c000b0b202628020c2205450d00202628020422292005411c6c6a21240340024020292802182205450d002029280210220d20054102746a2125034002402028450d00200d280200210c20282109200b212a0340200941286a2108200941086a210720092f010622234102742105417f210602400340024020050d00202321060c020b2007280200210e200641016a2106200841206a21082005417c6a2105200741046a21070240417f200e200c47200e200c4b1b41016a0e03020001020b0b02402008417c6a280200450d00200d20082802003602000c030b41b082cc00413541e882cc001064000b202a450d01202a417f6a212a200920064102746a4194036a28020021090c000b0b200d41046a220d2025470d000b0b2029411c6a22292024470d000b0b202641306a22262027470d000b0b20032902f4072232422088a72105200341fc076a290200210a20032802f0072129200341e0006a10e1072032a7212b410021070c090b2003200536027c0240024002400240200520104f0d00200f20054102746a280200220e450d070240200328025822092003280254470d00200341d0006a20094101108601200328025821090b200328025020094102746a20053602002003200941016a360258200341e0046a200328027c2223200341386a10e00720032802e804212b20032802e404212920032802e004222c4101460d0320292802082205417f4c0d042029280200210d20292d000c212720050d01410021094101210c0c020b200341013602f404200342023702e4042003419081cc003602e004200341013602d4032003200341d0036a3602f0042003200341fc006a3602d003200341f0076a200341e0046a104120032902f407220a422088a7210520032802f0072129200aa7212b0c0a0b20051033220c450d0d200521090b0240024020092005490d00200921060c010b200941017422062005200620054b1b22064100480d08024020090d0020061033220c450d0f0c010b024020092006470d00200921060c010b200c200920061037220c450d0e0b200c200d2005109d082109200320273a008c01200320053602880120032006360284012003200936028001200320292d000d3a008d012003200e36029c012003200328027c360298012003410036029001200320032f01f0073b018e010240024020032802702205450d00200328027421270c010b20164200370100201742003701002018420037010020194200370100201a420037010020154200370100200341e0046a410041e002109f081a41940310332205450d0e4100212720054100360200200520032903f0073702042005410c6a200341f0076a41086a290300370200200541146a200341f0076a41106a2903003702002005411c6a200341f0076a41186a290300370200200541246a200341f0076a41206a2903003702002005412c6a201b290300370200200541346a200341e0046a41e002109d081a20034100360274200320053602700b0340200541146a2109200541086a210e200541066a212d20052f0106222e4102742106417f210c02400340024020060d00202e210c0c020b200e280200210d200c41016a210c200941206a21092006417c6a2106200e41046a210e0240417f200d202347200d20234b1b41016a0e03020001020b0b200929020021322009200329038001370200200941186a200329039801370200200941106a220529020021332005200329039001370200200941086a200329038801370200203342ffffffff0f83420285500d05203242808080807083500d052032a710350c050b02402027450d002027417f6a21272005200c4102746a4194036a28020021050c010b0b2003200328027841016a36027820032903980121322003290390012133200329038801213420032903800121350240202d2f01002206410b490d0020164200370100201742003701002018420037010020194200370100201a420037010020154200370100200341e0046a410041e002109f081a41940310332209450d0e20094100360200200920032903f0073702042009410c6a200341f0076a41086a221e290300370200200941146a200341f0076a41106a221f2903003702002009411c6a200341f0076a41186a2220290300370200200941246a200341f0076a41206a22362903003702002009412c6a201b290300370200200941346a200341e0046a41e002109d08210e200341e0046a41086a2227200541fc016a290200370300200341e0046a41106a222e20054184026a290200370300200341e0046a41186a221c2005418c026a290200370300200320052902f4013703e00420052802202112200941086a200541246a20052f010641796a2206410274109d08210d200e20054194026a2006410574109d08210e200541063b0106200920063b01062020201c290300370300201f202e290300370300201e2027290300370300200320032903e0043703f00702400240200c4107490d00200d200c417a6a222d4102746a200d200c41796a220c4102746a220d200641ffff0371200c6b410274109e081a200d2023360200200e202d4105746a200e200c4105746a2206200941066a222d2f0100200c6b410574109e081a200641186a2032370200200620333702102006203437020820062035370200202d2f0100210e0c010b200541086a2206200c41016a220d4102746a2006200c4102746a2206202d2f0100220e200c6b221d410274109e081a20062023360200200541346a2206200d4105746a2006200c4105746a2206201d410574109e081a200641186a20323702002006203337021020062034370208200620353702000b202d200e41016a3b0100200341d0036a41186a222120202903002232370300200341d0036a41106a2222201f2903002233370300200341d0036a41086a2214201e2903002234370300200341b0016a41186a22012032370300200341b0016a41106a22132033370300200341b0016a41086a22312034370300200320032903f00722323703d003200320323703b00102402005280200220d0d004100212f200921060c040b20052f0104212d4100212f200921300340200341c0026a41186a22372001290300370300200341c0026a41106a22382013290300370300200341c0026a41086a22392031290300370300200320032903b0013703c002202d41ffff0371210c024002400240200d2f01062205410b490d0020164200370100201742003701002018420037010020194200370100201a4200370100201542003701002014201e2903003703002022201f29030037030020212020290300370300200341d0036a41206a22052036290300370300200341d0036a41286a2209201b290300370300200320032903f0073703d003200341e0046a4100419003109f081a41c40310332206450d1220064100360200200620032903d0033702042006410c6a2014290300370200200641146a20222903003702002006411c6a2021290300370200200641246a20052903003702002006412c6a2009290300370200200641346a200341e0046a419003109d082109200d280220213a201c200d418c026a290200370300202e200d4184026a2902003703002027200d41fc016a2902003703002003200d2902f4013703e004200641086a200d41246a200d2f0106220e41796a2205410274109d08213b2009200d4194026a2005410574109d08213c20064194036a200d41b0036a200e417a6a2223410274109d08211d200d41063b0106200620053b010602402023450d0041002105201d210903402009280200220e20053b0104200e2006360200200941046a21092023200541016a2205470d000b0b2020201c2903002232370300201f202e2903002233370300201e20272903002234370300200320032903e00422353703f007201c2032370300202e203337030020272034370300200320353703e004202d41ffff037122094107490d01203b200c417a6a220e41027422236a203b200c41796a22054102746a220920062f010620056b410274109e081a20092012360200203c200e4105746a203c20054105746a220920062f010620056b410574109e081a200941186a2037290300370200200941106a2038290300370200200941086a2039290300370200200920032903c002370200200620062f010641016a22093b0106200c410274222d201d6a416c6a201d20236a2223200941ffff0371220c200e6b410274109e081a20232030360200200c200e490d022006202d6a41fc026a210903402009280200220e200541016a22053b0104200e2006360200200941046a21092005200c490d000c030b0b200d41086a2209200c41016a2206410274220e6a2009200c41027422236a22092005200c6b2227410274109e081a20092012360200200d41346a220920064105746a2009200c4105746a22092027410574109e081a200941186a2037290300370200200941106a2038290300370200200941086a2039290300370200200920032903c002370200200d200541016a22053b01062023200d4194036a22096a41086a2009200e6a2209200541ffff0371220e20066b410274109e081a20092030360200200c200e4f0d07200d2006417f6a22054102746a4198036a2109034020092802002206200541016a22053b01042006200d360200200941046a21092005200e490d000c080b0b200d41086a2205200c41016a2223410274220e6a2005200c410274222d6a2205200d2f0106221d200c6b223b410274109e081a20052012360200200d41346a220520234105746a2005200c4105746a2205203b410574109e081a200541186a2037290300370200200541106a2038290300370200200541086a2039290300370200200520032903c002370200200d201d41016a22053b0106202d200d4194036a221d6a41086a201d200e6a221d200541ffff0371220e20236b410274109e081a201d20303602002009200e4f0d00200d202d6a4198036a2105034020052802002209200c41016a220c3b01042009200d360200200541046a2105200e200c470d000b0b202f41016a212f2001201c2903003703002013202e29030037030020312027290300370300200320032903e0043703b0010240200d28020022050d00203a21120c050b200d2f0104212d2005210d203a2112200621300c000b0b200541086a2209200c41016a220e4102746a2009200c4102746a22092006200c6b220d410274109e081a20092023360200200541346a2209200e4105746a2009200c4105746a2209200d410574109e081a200941186a20323702002009203337021020092034370208200920353702002005200641016a3b01060c030b20032802ec0421050c070b1044000b20164200370100201742003701002018420037010020194200370100201a4200370100201542003701002014201e2903003703002022201f29030037030020212020290300370300200341d0036a41206a22092036290300370300200341d0036a41286a220e201b290300370300200320032903f0073703d003200341e0046a4100419003109f081a41c40310332205450d0a20054100360200200520032903d0033702042005410c6a2014290300370200200541146a20222903003702002005411c6a2021290300370200200541246a20092903003702002005412c6a200e290300370200200541346a200341e0046a419003109d08210e2005200328027022093602940320032003280274220c41016a360274200941003b01042003200536027020092005360200201c2001290300370300202e201329030037030020272031290300370300200320032903b0013703e004200c202f470d0220052f01062209410a4b0d03200e20094105746a220e20032903e004370200200e41086a2027290300370200200e41106a202e290300370200200e41186a201c290300370200200520094102746a41086a20123602002005200941016a22094102746a4194036a2006360200200520093b0106200620093b0104200620053602000b202c450d00202b450d00202910350c000b0b41ff83cc00413041c086cc00103f000b41af84cc00412741c086cc00103f000b103e000b200341f0006a10e1070240200328025441ffffffff0371450d00200328025010350b20032802402208200328024810f406410121070240200341c4006a2802002203450d00200341306c450d00200810350b0b20002029360204200041086a2005ad422086202bad843702000240024020070d0020004100360200200041106a200a370200201141ffffffff03710d010c030b20004101360200201141ffffffff0371450d020b200f10350c010b2001280208200128021010f4062001410c6a2802002203450d00200341306c450d0020012802081035200424000f0b200424000f0b1045000b103c000bf6c70103017f037e1b7f230041e0006b220324000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e10010002161514131211100e0f0d0c0403010b200141046a29020021042001410c6a2902002105200141146a2902002106200341003a00002002200341011078200341106a20063703002003200537030820032004370300200341d0006a2003200210c10720032d0050411f460d1c20002003290350370200200041086a200341d0006a41086a2903003702000c1d0b200141086a28020021072001410c6a2802002108200141046a2802002109200320012d00013a0000200220034101107820022009200810782007450d1b200910350c1b0b200141086a280200210a200141046a280200210b2001410c6a280200210c200341013a00002002200341011078200b200c4104746a210d41002107410021094101210e200c210803400240024020072009460d00200921010c010b200941016a22012009490d162009410174220f2001200f20014b1b22014100480d160240024020090d00024020010d004101210e0c020b20011033220e0d010c200b20092001460d00200e200920011037220e450d1f0b200121090b200e20076a200841807f72200841ff00712008410776220f1b3a0000200741016a2107200f2108200f0d000b0240200c0d00200b21100c190b200b21090340200941106a211020092d000d22114105460d1920092d000c2108200928020821122009280204211320092802002114024020012007470d00200741016a22012007490d16200741017422092001200920014b1b22014100480d16024020070d00024020010d004101210e0c020b20011033220e450d1f0c010b20072001460d00200e200720011037220e450d1e0b200e20076a20083a0000200741016a2109200741017441046a21152012210703402015210c0240024020092001460d002001210f0c010b200141016a22082001490d172001410174220f2008200f20084b1b220f4100480d170240024020010d000240200f0d004101210e0c020b200f1033220e450d210c010b2001200f460d00200e2001200f1037220e450d200b200f21010b200e20096a200741807f72200741ff0071200741077622081b3a0000200c41026a2115200941016a21092008210720080d000b0240024020120d00200921070c010b410021010340200920016a210741fc0021080240024002400240201420016a2d00000e050200010305020b41fe0021080c020b41fd0021080c010b41ff0021080b200320083a000002402007200f470d00200741016a220f2007490d18200c200f200c200f4b1b220f4100480d18024020070d000240200f0d004101210e0c020b200f1033220e450d210c010b2007200f460d00200e2007200f1037220e450d200b200e20096a20016a20083a0000200c41026a210c2012200141016a2201470d000b200920016a21070b02402013450d00201410350b41002109024020114104460d000240200f2007470d00200741016a22012007490d17200741017422092001200920014b1b220f4100480d17024020070d000240200f0d004101210e0c020b200f1033220e450d200c010b2007200f460d00200e2007200f1037220e450d1f0b200e20076a41013a0000200741016a2107201141077141ff007321090b02400240200f2007460d00200f21010c010b200741016a22012007490d16200741017422082001200820014b1b22014100480d16024020070d00024020010d004101210e0c020b20011033220e450d1f0c010b20072001460d00200e200720011037220e450d1e0b200e20076a20093a0000200741016a2107201021092010200d470d000c1a0b0b200141286a2802002112200141246a280200210a200141206a280200210d2001411c6a2802002114200141186a2802002113200141146a2802002110200141086a280200210b200141046a28020021112001410c6a2902002104200341003a00002002200341011078200341d0006a410c6a410036020020034201370254200320023602502004a7221541017441026a21092004422088a7210f41002107410021012015210803400240024020012007460d002003280254210c0c010b200741016a220c2007490d032007410174220e200c200e200c4b1b220e4100480d030240024020070d000240200e0d004101210c0c020b200e1033220c450d0b0c010b2003280254210c2007200e460d00200c2007200e1037220c450d0a0b2003200e3602582003200c3602540b200c20016a200841807f72200841ff00712008410776220c1b3a00002003200141016a220136025c200941026a210920032802582107200c2108200c0d000b02400240200720016b2015490d002003280254210c200721080c010b200120156a22082001490d022007410174220c2008200c20084b1b22084100480d020240024020070d00024020080d004101210c0c020b20081033220c450d0a0c010b2003280254210c20072008460d00200c200720081037220c450d090b200320083602582003200c3602540b200c20016a20112015109d081a2003201520016a36025c0240200b450d00201110350b034002400240201520016a220c2008460d00200328025421070c010b200841016a22072008490d032008410174220e2007200e20074b1b220e4100480d030240024020080d000240200e0d00410121070c020b200e10332207450d0b0c010b200328025421072008200e460d0020072008200e10372207450d0a0b2003200e360258200320073602540b200720156a20016a200f41807f72200f41ff0071200f41077622071b3a00002003200c41016a36025c02402007450d00200941026a2109200141016a2101200328025821082007210f0c010b0b0240024020100d00200c41016a2101410121020c010b2015417f732102201541016a210c20142107034002400240200c20016a22082003280258460d002003280254210f0c010b200841016a220f2008490d042009200f2009200f4b1b220e4100480d040240024020022001470d000240200e0d004101210f0c020b200e1033220f450d0c0c010b2003280254210f2008200e460d00200f2008200e1037220f450d0b0b2003200e3602582003200f3602540b200f200c6a20016a200741807f72200741ff00712007410776220f1b3a00002003200841016a36025c200941026a2109200141016a2101200f2107200f0d000b024002402001417f732003280258220720156b6a2014490d00200328025421090c010b201520016a41016a220820146a22092008490d03200741017422082009200820094b1b22084100480d030240024020070d00024020080d00410121090c020b200810332209450d0b0c010b2003280254210920072008460d0020092007200810372209450d0a0b20032008360258200320093602540b201520096a20016a41016a20102014109d081a2003201420156a20016a41016a220136025c410021022013450d00201010350b20014101742107200d20124104746a210e2012210903400240024020012003280258460d00200328025421080c010b200141016a22082001490d0320072008200720084b1b220f4100480d030240024020010d000240200f0d00410121080c020b200f10332208450d0b0c010b200328025421082001200f460d0020082001200f10372208450d0a0b2003200f360258200320083602540b200820016a200941807f72200941ff0071200941077622081b3a00002003200141016a220136025c200741026a21072008210920080d000b024002402012450d00200d210c0340200c410c6a2802002115200c41086a2802002101200c28020421090240024002400240024002400240024002400240200c2802000e0900010203040506070b000b200341003a0000024002402003280258200328025c2207460d004100210f200328025421080c010b200741016a22082007490d0e2007410174220f2008200f20084b1b220f4100480d0e0240024020070d000240200f0d00410121080c020b200f10332208450d160c010b200328025421082007200f460d0020082007200f10372208450d150b2003200f3602582003200836025420032d0000210f200328025c21070b200820076a200f3a00002003200741016a220736025c200341003a000003402003200941807f72200941ff0071200941077622081b220f3a00000240024020032802582007460d00200328025421090c010b200741016a22092007490d0f2007410174220f2009200f20094b1b220f4100480d0f0240024020070d000240200f0d00410121090c020b200f10332209450d170c010b200328025421092007200f460d0020092007200f10372209450d160b2003200f3602582003200936025420032d0000210f200328025c21070b200920076a200f3a00002003200741016a220736025c2008210920080d000b200341003a000003402003200141807f72200141ff0071200141077622091b22083a00000240024020032802582007460d00200328025421010c010b200741016a22012007490d0f200741017422082001200820014b1b22084100480d0f0240024020070d00024020080d00410121010c020b200810332201450d170c010b2003280254210120072008460d0020012007200810372201450d160b200320083602582003200136025420032d00002108200328025c21070b200120076a20083a00002003200741016a220736025c2009210120090d000c090b0b200341013a0000024002402003280258200328025c2207460d004101210f200328025421080c010b200741016a22082007490d0d2007410174220f2008200f20084b1b220f4100480d0d0240024020070d000240200f0d00410121080c020b200f10332208450d150c010b200328025421082007200f460d0020082007200f10372208450d140b2003200f3602582003200836025420032d0000210f200328025c21070b200820076a200f3a00002003200741016a220736025c200341003a000003402003200941807f72200941ff0071200941077622081b220f3a00000240024020032802582007460d00200328025421090c010b200741016a22092007490d0e2007410174220f2009200f20094b1b220f4100480d0e0240024020070d000240200f0d00410121090c020b200f10332209450d160c010b200328025421092007200f460d0020092007200f10372209450d150b2003200f3602582003200936025420032d0000210f200328025c21070b200920076a200f3a00002003200741016a220736025c2008210920080d000b200341003a000003402003200141807f72200141ff0071200141077622091b22083a00000240024020032802582007460d00200328025421010c010b200741016a22012007490d0e200741017422082001200820014b1b22084100480d0e0240024020070d00024020080d00410121010c020b200810332201450d160c010b2003280254210120072008460d0020012007200810372201450d150b200320083602582003200136025420032d00002108200328025c21070b200120076a20083a00002003200741016a220736025c200921012009450d080c000b0b200341023a0000024002402003280258200328025c2207460d004102210f200328025421080c010b200741016a22082007490d0c2007410174220f2008200f20084b1b220f4100480d0c0240024020070d000240200f0d00410121080c020b200f10332208450d140c010b200328025421082007200f460d0020082007200f10372208450d130b2003200f3602582003200836025420032d0000210f200328025c21070b200820076a200f3a00002003200741016a220736025c200341003a000003402003200941807f72200941ff0071200941077622081b220f3a00000240024020032802582007460d00200328025421090c010b200741016a22092007490d0d2007410174220f2009200f20094b1b220f4100480d0d0240024020070d000240200f0d00410121090c020b200f10332209450d150c010b200328025421092007200f460d0020092007200f10372209450d140b2003200f3602582003200936025420032d0000210f200328025c21070b200920076a200f3a00002003200741016a220736025c2008210920080d000b200341003a000003402003200141807f72200141ff0071200141077622091b22083a00000240024020032802582007460d00200328025421010c010b200741016a22012007490d0d200741017422082001200820014b1b22084100480d0d0240024020070d00024020080d00410121010c020b200810332201450d150c010b2003280254210120072008460d0020012007200810372201450d140b200320083602582003200136025420032d00002108200328025c21070b200120076a20083a00002003200741016a220736025c200921012009450d070c000b0b200341033a0000024002402003280258200328025c2207460d004103210f200328025421080c010b200741016a22082007490d0b2007410174220f2008200f20084b1b220f4100480d0b0240024020070d000240200f0d00410121080c020b200f10332208450d130c010b200328025421082007200f460d0020082007200f10372208450d120b2003200f3602582003200836025420032d0000210f200328025c21070b200820076a200f3a00002003200741016a220736025c200341003a000003402003200941807f72200941ff0071200941077622081b220f3a00000240024020032802582007460d00200328025421090c010b200741016a22092007490d0c2007410174220f2009200f20094b1b220f4100480d0c0240024020070d000240200f0d00410121090c020b200f10332209450d140c010b200328025421092007200f460d0020092007200f10372209450d130b2003200f3602582003200936025420032d0000210f200328025c21070b200920076a200f3a00002003200741016a220736025c2008210920080d000b200341003a000003402003200141807f72200141ff0071200141077622091b22083a00000240024020032802582007460d00200328025421010c010b200741016a22012007490d0c200741017422082001200820014b1b22084100480d0c0240024020070d00024020080d00410121010c020b200810332201450d140c010b2003280254210120072008460d0020012007200810372201450d130b200320083602582003200136025420032d00002108200328025c21070b200120076a20083a00002003200741016a220736025c2009210120090d000b20032015200341d0006a10a50720032d00002201411f460d0520032f000120032d00034110747221090c040b200341043a0000024002402003280258200328025c2207460d004104210f200328025421080c010b200741016a22082007490d0a2007410174220f2008200f20084b1b220f4100480d0a0240024020070d000240200f0d00410121080c020b200f10332208450d120c010b200328025421082007200f460d0020082007200f10372208450d110b2003200f3602582003200836025420032d0000210f200328025c21070b200820076a200f3a00002003200741016a220736025c200341003a000003402003200941807f72200941ff0071200941077622081b220f3a00000240024020032802582007460d00200328025421090c010b200741016a22092007490d0b2007410174220f2009200f20094b1b220f4100480d0b0240024020070d000240200f0d00410121090c020b200f10332209450d130c010b200328025421092007200f460d0020092007200f10372209450d120b2003200f3602582003200936025420032d0000210f200328025c21070b200920076a200f3a00002003200741016a220736025c2008210920080d000b200341003a000003402003200141807f72200141ff0071200141077622091b22083a00000240024020032802582007460d00200328025421010c010b200741016a22012007490d0b200741017422082001200820014b1b22084100480d0b0240024020070d00024020080d00410121010c020b200810332201450d130c010b2003280254210120072008460d0020012007200810372201450d120b200320083602582003200136025420032d00002108200328025c21070b200120076a20083a00002003200741016a220736025c2009210120090d000b20032015200341d0006a10a50720032d00002201411f460d0420032f000120032d00034110747221090c030b200341053a0000024002402003280258200328025c2207460d004105210f200328025421080c010b200741016a22082007490d092007410174220f2008200f20084b1b220f4100480d090240024020070d000240200f0d00410121080c020b200f10332208450d110c010b200328025421082007200f460d0020082007200f10372208450d100b2003200f3602582003200836025420032d0000210f200328025c21070b200820076a200f3a00002003200741016a220736025c200341003a000003402003200941807f72200941ff0071200941077622081b220f3a00000240024020032802582007460d00200328025421090c010b200741016a22092007490d0a2007410174220f2009200f20094b1b220f4100480d0a0240024020070d000240200f0d00410121090c020b200f10332209450d120c010b200328025421092007200f460d0020092007200f10372209450d110b2003200f3602582003200936025420032d0000210f200328025c21070b200920076a200f3a00002003200741016a220736025c2008210920080d000b200341003a000003402003200141807f72200141ff0071200141077622091b22083a00000240024020032802582007460d00200328025421010c010b200741016a22012007490d0a200741017422082001200820014b1b22084100480d0a0240024020070d00024020080d00410121010c020b200810332201450d120c010b2003280254210120072008460d0020012007200810372201450d110b200320083602582003200136025420032d00002108200328025c21070b200120076a20083a00002003200741016a220736025c2009210120090d000b20032015200341d0006a10a50720032d00002201411f460d0320032f000120032d00034110747221090c020b200341063a0000024002402003280258200328025c2207460d004106210f200328025421080c010b200741016a22082007490d082007410174220f2008200f20084b1b220f4100480d080240024020070d000240200f0d00410121080c020b200f10332208450d100c010b200328025421082007200f460d0020082007200f10372208450d0f0b2003200f3602582003200836025420032d0000210f200328025c21070b200820076a200f3a00002003200741016a220736025c200341003a000003402003200941807f72200941ff0071200941077622081b220f3a00000240024020032802582007460d00200328025421090c010b200741016a22092007490d092007410174220f2009200f20094b1b220f4100480d090240024020070d000240200f0d00410121090c020b200f10332209450d110c010b200328025421092007200f460d0020092007200f10372209450d100b2003200f3602582003200936025420032d0000210f200328025c21070b200920076a200f3a00002003200741016a220736025c2008210920080d000b200341003a000003402003200141807f72200141ff0071200141077622091b22083a00000240024020032802582007460d00200328025421010c010b200741016a22012007490d09200741017422082001200820014b1b22084100480d090240024020070d00024020080d00410121010c020b200810332201450d110c010b2003280254210120072008460d0020012007200810372201450d100b200320083602582003200136025420032d00002108200328025c21070b200120076a20083a00002003200741016a220736025c200921012009450d030c000b0b200341073a0000024002402003280258200328025c2207460d004107210f200328025421080c010b200741016a22082007490d072007410174220f2008200f20084b1b220f4100480d070240024020070d000240200f0d00410121080c020b200f10332208450d0f0c010b200328025421082007200f460d0020082007200f10372208450d0e0b2003200f3602582003200836025420032d0000210f200328025c21070b200820076a200f3a00002003200741016a220736025c200341003a000003402003200941807f72200941ff0071200941077622081b220f3a00000240024020032802582007460d00200328025421090c010b200741016a22092007490d082007410174220f2009200f20094b1b220f4100480d080240024020070d000240200f0d00410121090c020b200f10332209450d100c010b200328025421092007200f460d0020092007200f10372209450d0f0b2003200f3602582003200936025420032d0000210f200328025c21070b200920076a200f3a00002003200741016a220736025c2008210920080d000b200341003a000003402003200141807f72200141ff0071200141077622091b22083a00000240024020032802582007460d00200328025421010c010b200741016a22012007490d08200741017422082001200820014b1b22084100480d080240024020070d00024020080d00410121010c020b200810332201450d100c010b2003280254210120072008460d0020012007200810372201450d0f0b200320083602582003200136025420032d00002108200328025c21070b200120076a20083a00002003200741016a220736025c200921012009450d020c000b0b200328020c210f20032802082108200328020421070240200a41ffffffff0071450d00200d10350b2003280258450d03200328025410350c030b200c41106a220c200e470d000b0b0240200a41ffffffff0071450d00200d10350b200328025c21082003280258210c2003280254210f20032802502107200341003a00002008210103402003200141800172200141ff0071200141077622091b3a000020072003410110782009210120090d000b2007200f200810780240200c450d00200f10350b2010450d1a2002450d1a2013450d1a201010350c1a0b02402010450d002002450d002013450d00201010350b200020093b0001200020013a0000200041036a20094110763a00002000410c6a200f360000200041086a2008360000200041046a20073600000c1a0b2001412c6a2802002116200141286a2802002117200141246a280200210d200141206a28020021182001411c6a2802002119200141186a280200211a200141146a280200210b2001410c6a2902002104200141086a280200211b200141046a280200211341002112200341003a000041012108200220034101107802400240024041041033220a450d00200a41eec2b5ab06360000024020130d00410021114100211c0c030b200341003a00004101210c41002101410021092004a72215210703402003200741807f72200741ff0071200741077622081b22073a00000240024020012009460d002001210f0c010b200141016a22092001490d172001410174220f2009200f20094b1b220f4100480d170240024020010d00410021090240200f0d004101210c0c020b200f1033220c450d210c010b02402001200f470d00200121090c010b20012109200c2001200f1037220c450d200b200f21010b200c20096a20073a0000200941016a21092008210720080d000b02400240200f20096b2015490d00200f21100c010b200920156a22012009490d04200f41017422072001200720014b1b22104100480d040240200f0d00024020100d004101210c0c020b20101033220c450d1f0c010b200f2010460d00200c200f20101037220c450d0a0b200c20096a20132015109d081a0240201b450d00201310350b200341003a0000410110332208450d09200841003a0000200341003a0000410121014101210f200920156a220e210903402003200941807f72200941ff0071200941077622071b22093a00000240200f2001470d00200141016a220f2001490d0520014101742215200f2015200f4b1b220f4100480d05024020010d00410021010240200f0d00410121080c020b200f103322080d010c0c0b2001200f460d0020082001200f10372208450d0b0b200820016a20093a0000200141016a21012007210920070d000b0240200f20016b200e490d00200f21110c020b2001200e6a22092001490d03200f41017422072009200720094b1b22114100480d030240200f0d00024020110d00410121080c030b201110332208450d0a0c020b200f2011460d012008200f201110372208450d090c010b1045000b200820016a200c200e109d081a2001200e6a21124101211c2010450d00200c10350b02400240200b0d004101211d0c010b4100211d20034100360240200342013703382003410c6a2019360200200341086a201a3602002003200b360204200320044220883e0200200341d0006a2003200341386a10c20720032d0050411f470d04200341013a00000240024020112012460d002011210f0c010b201241016a22012012490d02201241017422092001200920014b1b220f4100480d02024020120d00410021120240200f0d00410121080c020b200f10332208450d090c010b2012200f460d0020082012200f10372208450d080b200820126a41013a000020032802402115200341003a0000201241016a21012015210903402003200941807f72200941ff0071200941077622071b22093a00000240200f2001470d00200141016a220f2001490d032001410174220c200f200c200f4b1b220f4100480d03024020010d00410021010240200f0d00410121080c020b200f10332208450d0a0c010b2001200f460d0020082001200f10372208450d090b200820016a20093a0000200141016a21012007210920070d000b2003280238210902400240200f20016b2015490d00200f21110c010b200120156a22072001490d02200f410174220c2007200c20074b1b22114100480d020240200f0d00024020110d00410121080c020b201110332208450d090c010b200f2011460d002008200f201110372208450d080b200820016a20092015109d081a0240200328023c450d00200910350b200120156a21124100211d0b0240200d0d004100210f0c030b2003410036024020034201370338200341003a00004101210c41002109410021012018210703402003200741807f72200741ff00712007410776220f1b22153a0000024020092001470d00200941016a22012009490d02200941017422072001200720014b1b22074100480d020240024020090d0041002101024020070d004101210c0c020b20071033220c450d0a0c010b024020092007470d00200921010c010b20092101200c200920071037220c450d090b2003200736023c2003200c360238200721090b200c20016a20153a00002003200141016a2201360240200f2107200f0d000b200d20164104746a211002400240024020160d00200d210c0c010b200d210c2018450d00201041706a211e41002101200d211f02400340201f210f02400340200f41046a28020022140d01200141016a21012010200f41106a220f470d000c050b0b200f41086a2902002104200f2802002120200341003a0000200f41106a211f200141016a21212018417f6a2118200328023c21072003280240210903402003200141807f72200141ff00712001410776220c1b220e3a00000240024020072009460d00200328023821010c010b200741016a22012007490d06200741017422092001200920014b1b22154100480d060240024020070d0041002109024020150d00410121010c020b201510332201450d0e0c010b20032802382101024020072015470d00200721090c010b2007210920012007201510372201450d0d0b2003201536023c20032001360238201521070b200120096a200e3a00002003200941016a2209360240200c2101200c0d000b200320043703082003201436020420032020360200200341d0006a2003200341386a10c207024020032d0050220e411f470d00201e200f460d022021210120180d010c020b0b20032d0053211520032f005121202003280254211f20032802582118200328025c21140240201041706a200f460d00200f41106a210c0340200c220f41106a210c0240200f2802042201450d000240200f410c6a2802002209450d002009410c6c21090340024020012802002207450d00200141046a280200450d00200710350b2001410c6a2101200941746a22090d000b0b200f41086a2802002201450d002001410c6c450d00200f28020410350b200c2010470d000b0b201541107421010240201741ffffffff0071450d00200d10350b202020017221104101210f200328023c450d07200328023810350c070b200f41106a210c0b2010200c460d000340200c220f41106a210c0240200f2802042201450d000240200f410c6a2802002209450d002009410c6c21090340024020012802002207450d00200141046a280200450d00200710350b2001410c6a2101200941746a22090d000b0b200f41086a2802002201450d002001410c6c450d00200f28020410350b200c2010470d000b0b0240201741ffffffff0071450d00200d10350b200341023a00000240024020112012460d002011210f0c010b201241016a22012012490d01201241017422092001200920014b1b220f4100480d01024020120d00410021120240200f0d00410121080c020b200f10332208450d080c010b2012200f460d0020082012200f10372208450d070b200820126a41023a000020032802402115200341003a0000201241016a21012015210903402003200941807f72200941ff0071200941077622071b22093a00000240200f2001470d00200141016a220f2001490d022001410174220c200f200c200f4b1b220f4100480d02024020010d00410021010240200f0d00410121080c020b200f10332208450d090c010b2001200f460d0020082001200f10372208450d080b200820016a20093a0000200141016a21012007210920070d000b200328023821090240200f20016b2015490d00200f21110c020b200120156a22072001490d00200f410174220c2007200c20074b1b22114100480d000240200f0d00024020110d00410121080c030b201110332208450d070c020b200f2011460d012008200f201110372208450d060c010b103e000b200820016a20092015109d081a0240200328023c450d00200910350b200120156a21124101210f0b0240201345201c720d00201b450d00201310350b0240200b450d00201d4101730d0002402019450d002019410c6c2109200b21010340024020012802002207450d00200141046a280200450d00200710350b2001410c6a2101200941746a22090d000b0b201a450d00201a410c6c450d00200b10350b200d45200f720d0202402016450d00200d20164104746a2115200d210c0340200c220f41106a210c0240200f2802042201450d000240200f410c6a2802002209450d002009410c6c21090340024020012802002207450d00200141046a280200450d00200710350b2001410c6a2101200941746a22090d000b0b200f41086a2802002201450d002001410c6c450d00200f28020410350b200c2015470d000b0b201741ffffffff0071450d02200d10350c020b2003280250220e4108762110200341d0006a410c6a2802002114200341d0006a41086a28020021182003280254211f0240200328023c450d00200328023810350b4100210f0b0240201c201345720d00201b450d00201310350b0240200b450d00201d4101730d0002402019450d002019410c6c2109200b21010340024020012802002207450d00200141046a280200450d00200710350b2001410c6a2101200941746a22090d000b0b201a450d00201a410c6c450d00200b10350b0240200d45200f720d0002402016450d00200d20164104746a2115200d210c0340200c220f41106a210c0240200f2802042201450d000240200f410c6a2802002209450d002009410c6c21090340024020012802002207450d00200141046a280200450d00200710350b2001410c6a2101200941746a22090d000b0b200f41086a2802002201450d002001410c6c450d00200f28020410350b200c2015470d000b0b201741ffffffff0071450d00200d10350b200e41ff01712201411f460d002010410874200172210102402011450d00200810350b200020013602002000410c6a2014360200200041086a2018360200200041046a201f360200200a10350c140b200341146a2012360200200341106a20113602002003200836020c20034284808080c0003702042003200a360200200341d0006a2003200210c10720032d0050411f460d1220002003290350370200200041086a200341d0006a41086a2903003702000c130b103c000b200141086a280200210e200141046a28020021152001410c6a280200210c2003410b3a00002002200341011078200341386a410c6a41003602002003420137023c200320023602382015200c411c6c6a210d4100210141002109200c210703400240024020092001460d00200328023c21080c010b200141016a22082001490d0c2001410174220f2008200f20084b1b220f4100480d0c0240024020010d000240200f0d00410121080c020b200f10332208450d160c010b200328023c21082001200f460d0020082001200f10372208450d150b2003200f3602402003200836023c0b200820096a200741807f72200741ff0071200741077622071b3a00002003200941016a220936024402402007450d0020032802402101200721070c010b0b2003200d36025c200320153602582003200e360254200320153602500240200c450d000340200320152201411c6a22153602582001280210220e450d012001410c6a2802002102200141086a28020021102001280204210c200141146a290200210420012802002109200341003a00002003280244210103402003200941807f72200941ff0071200941077622071b22083a00000240024020032802402001460d00200328023c21090c010b200141016a22092001490d0e200141017422082009200820094b1b22084100480d0e0240024020010d00024020080d00410121090c020b200810332209450d180c010b200328023c210920012008460d0020092001200810372209450d170b200320083602402003200936023c20032d00002108200328024421010b200920016a20083a00002003200141016a22013602442007210920070d000b024002400240200c0d00410121140c010b200320023602302003201036022c2003200c3602282003200341286a200341386a10a20720032d00002201411f470d0141002114200328024421010b200341003a00002004a721122004422088a7220f210903402003200941807f72200941ff0071200941077622071b22083a00000240024020032802402001460d00200328023c21090c010b200141016a22092001490d0f200141017422082009200820094b1b22084100480d0f0240024020010d00024020080d00410121090c020b200810332209450d190c010b200328023c210920012008460d0020092001200810372209450d180b200320083602402003200936023c20032d00002108200328024421010b200920016a20083a00002003200141016a22013602442007210920070d000b024002402003280240220720016b200f490d00200328023c21090c010b2001200f6a22092001490d0e200741017422012009200120094b1b22014100480d0e0240024020070d00024020010d00410121090c020b200110332209450d180c010b200328023c210920072001460d0020092007200110372209450d170b200320013602402003200936023c200328024421010b200920016a200e200f109d081a20032001200f6a36024402402012450d00200e10350b0240200c450d002014450d0002402002450d0020024104742109200c21010340024020012d00004109470d000240200141046a2208280200220728020441ffffffff0371450d0020072802001035200828020021070b200710350b200141106a2101200941706a22090d000b0b201041ffffffff0071450d00200c10350b2015200d470d010c020b0b20032d0003411074210920032f00012107200328020c21082003280208210f2003280204210c02402004a7450d00200e10350b20072009722109200341d0006a10c30702402003280240450d00200328023c10350b200020093b0001200020013a0000200041036a20094110763a00002000410c6a2008360000200041086a200f360000200041046a200c3600000c120b200341d0006a10c30720032802382107200328023c210f2003280240210c20032802442108200341003a00002008210103402003200141800172200141ff0071200141077622091b3a000020072003410110782009210120090d000b2007200f20081078200c450d10200f10350c100b200141086a280200210e200141046a280200210f2001410c6a28020021152003410a3a00002002200341011078200341186a410c6a41003602002003420137021c20032002360218200f201541186c6a210b41002101410021092015210703400240024020092001460d00200328021c21080c010b200141016a22082001490d0b2001410174220c2008200c20084b1b220c4100480d0b0240024020010d000240200c0d00410121080c020b200c10332208450d150c010b200328021c21082001200c460d0020082001200c10372208450d140b2003200c3602202003200836021c0b200820096a200741807f72200741ff0071200741077622071b3a00002003200941016a220936022402402007450d0020032802202101200721070c010b0b2003200b3602342003200f3602302003200e36022c2003200f36022802402015450d0020034101722102200341026a210e03402003200f41186a2214360230200f2802002210450d01200f41146a280200210d200f41106a2802002111200f28020c2112200f2802082107200f280204211341002109200341003602442003420137023c201020074103746a21152003200341186a3602384100210103400240024020092001460d00200328023c21080c010b200941016a22012009490d0d200941017422082001200820014b1b22014100480d0d0240024020090d00024020010d00410121080c020b200110332208450d170c010b200328023c210820092001460d0020082009200110372208450d160b200320013602402003200836023c200328024421010b200820016a200741807f72200741ff0071200741077622071b3a00002003200141016a220136024402402007450d0020032802402109200721070c010b0b024020152010460d002010210f0340200f2902002204422088a7220941ff01714104460d01200f41086a210f2009411874411875210c200341003a00002004a7210903402003200941807f72200941ff0071200941077622071b22083a00000240024020032802402001460d00200328023c21090c010b200141016a22092001490d0f200141017422082009200820094b1b22084100480d0f0240024020010d00024020080d00410121090c020b200810332209450d190c010b200328023c210920012008460d0020092001200810372209450d180b200320083602402003200936023c20032d00002108200328024421010b200920016a20083a00002003200141016a22013602442007210920070d000b2003200c417f732209413f7141c000722009200c417f4a1b22073a00000240024020032802402001460d00200328023c21090c010b200141016a22092001490d0e200141017422072009200720094b1b22074100480d0e0240024020010d00024020070d00410121090c020b200710332209450d180c010b200328023c210920012007460d0020092001200710372209450d170b200320073602402003200936023c20032d00002107200328024421010b200920016a20073a00002003200141016a2201360244200f2015470d000b0b0240201341ffffffff0171450d00201010350b2012200d41047422016a21070240024002400240200d0d00201221010c010b200141706a210820122101034020012d00002109200e200141036a2d00003a00002003200141016a2f00003b01000240200941ac01470d00200141106a21010c020b200341cc006a41026a200e2d0000220f3a0000200320032f0100220c3b014c200141046a2802002115200141086a29030021042002200c3b0000200241026a200f3a0000200320093a00002003200437030820032015360204200341d0006a2003200341386a10ac07024020032d0050220c411f47220f0d00200841706a2108200141106a22012007470d010c030b0b20032d0053211020032f0051210d200328025421132003280258210a200328025c211602402008450d004100210903400240200120096a220741106a2d00004109470d000240200741146a2215280200220728020441ffffffff0371450d0020072802001035201528020021070b200710350b2008200941106a2209470d000b0b0240201141ffffffff0071450d00201210350b02402003280240450d00200328023c10350b200f450d02200d2010411074722101200341286a10c40702402003280220450d00200328021c10350b200020013b00012000200c3a0000200041036a20014110763a00002000410c6a2016360000200041086a200a360000200041046a20133600000c150b20072001460d000340200141106a2109024020012d00004109470d000240200141046a2208280200220128020441ffffffff0371450d0020012802001035200828020021010b200110350b2009210120072009470d000b0b0240201141ffffffff0071450d00201210350b200328024421102003280240210d200328023c21122003280238210f200341003a0000200f410c6a220c28020021012010210903402003200941807f72200941ff0071200941077622071b22083a000002400240200f41086a22152802002001460d00200f28020421090c010b200141016a22092001490d0e200141017422082009200820094b1b22084100480d0e0240024020010d00024020080d00410121090c020b200810332209450d180c010b200f280204210920012008460d0020092001200810372209450d170b200f200936020420152008360200200c280200210120032d000021080b200920016a20083a0000200c200141016a22013602002007210920070d000b024002402015280200220720016b2010490d00200f28020421090c010b200120106a22092001490d0d200741017422012009200120094b1b22014100480d0d0240024020070d00024020010d00410121090c020b200110332209450d170c010b200f280204210920072001460d0020092007200110372209450d160b200f200936020420152001360200200c28020021010b200920016a20122010109d081a200c200120106a360200200d450d00201210350b2014210f2014200b470d000b0b200341286a10c40720032802182107200328021c210f2003280220210c20032802242108200341003a00002008210103402003200141800172200141ff0071200141077622091b3a000020072003410110782009210120090d000b2007200f20081078200c450d0f200f10350c0f0b200141086a2802002115200141046a28020021102001410c6a280200210c200341093a00002002200341011078200341386a410c6a41003602002003420137023c200320023602382010200c411c6c6a210d4100210141002109200c210703400240024020092001460d00200328023c21080c010b200141016a22082001490d0a2001410174220f2008200f20084b1b220f4100480d0a0240024020010d000240200f0d00410121080c020b200f10332208450d140c010b200328023c21082001200f460d0020082001200f10372208450d130b2003200f3602402003200836023c0b200820096a200741807f72200741ff0071200741077622071b3a00002003200941016a220936024402402007450d0020032802402101200721070c010b0b2003200d36025c2003201036025820032015360254200320103602500240200c450d000340200320102201411c6a221036025820012802102215450d012001410c6a2802002102200141086a28020021122001280204210e200141146a2902002104200128020021092003280244210103400240024020032802402001460d00200328023c21070c010b200141016a22072001490d0c200141017422082007200820074b1b22084100480d0c0240024020010d00024020080d00410121070c020b200810332207450d160c010b200328023c210720012008460d0020072001200810372207450d150b200320083602402003200736023c200328024421010b200720016a200941807f72200941ff0071200941077622071b3a00002003200141016a22013602442007210920070d000b024002400240200e0d00410121140c010b200320023602302003201236022c2003200e3602282003200341286a200341386a10a20720032d00002201411f470d0141002114200328024421010b200341003a000020152004422088a722094102746a210c03402003200941807f72200941ff0071200941077622071b22083a00000240024020032802402001460d00200328023c21090c010b200141016a22092001490d0d200141017422082009200820094b1b22084100480d0d0240024020010d00024020080d00410121090c020b200810332209450d170c010b200328023c210920012008460d0020092001200810372209450d160b200320083602402003200936023c20032d00002108200328024421010b200920016a20083a00002003200141016a22013602442007210920070d000b0240200c2015460d002015210f0340200f2802002109200341003a000003402003200941807f72200941ff0071200941077622071b22083a00000240024020032802402001460d00200328023c21090c010b200141016a22092001490d0f200141017422082009200820094b1b22084100480d0f0240024020010d00024020080d00410121090c020b200810332209450d190c010b200328023c210920012008460d0020092001200810372209450d180b200320083602402003200936023c20032d00002108200328024421010b200920016a20083a00002003200141016a22013602442007210920070d000b200f41046a220f200c470d000b0b0240200442ffffffff0383500d00201510350b0240200e450d002014450d0002402002450d0020024104742109200e21010340024020012d00004109470d000240200141046a2208280200220728020441ffffffff0371450d0020072802001035200828020021070b200710350b200141106a2101200941706a22090d000b0b201241ffffffff0071450d00200e10350b2010200d470d010c020b0b20032d0003411074210920032f00012107200328020c21082003280208210f2003280204210c0240200442ffffffff0383500d00201510350b20072009722109200341d0006a10c50702402003280240450d00200328023c10350b200020093b0001200020013a0000200041036a20094110763a00002000410c6a2008360000200041086a200f360000200041046a200c3600000c100b200341d0006a10c50720032802382107200328023c210f2003280240210c20032802442108200341003a00002008210103402003200141800172200141ff0071200141077622091b3a000020072003410110782009210120090d000b2007200f20081078200c450d0e200f10350c0e0b200141046a28020021072003410c3a00002002200341011078200341003a000041002109410021014101210c03402003200741807f72200741ff0071200741077622081b22073a00000240024020092001460d002001210f0c010b200141016a220f2001490d0920014101742215200f2015200f4b1b220f4100480d090240024020010d000240200f0d004101210c0c020b200f1033220c450d130c010b2001200f460d00200c2001200f1037220c450d120b200f21010b200c20096a20073a0000200941016a21092008210720080d000b200341003a00002009210103402003200141800172200141ff0071200141077622071b3a000020022003410110782007210120070d000b2002200c20091078200f450d0d200c10350c0d0b200141046a2802002107200341083a00002002200341011078200341003a000041002109410021014101210c03402003200741807f72200741ff0071200741077622081b22073a00000240024020092001460d002001210f0c010b200141016a220f2001490d0820014101742215200f2015200f4b1b220f4100480d080240024020010d000240200f0d004101210c0c020b200f1033220c450d120c010b2001200f460d00200c2001200f1037220c450d110b200f21010b200c20096a20073a0000200941016a21092008210720080d000b200341003a00002009210103402003200141800172200141ff0071200141077622071b3a000020022003410110782007210120070d000b2002200c20091078200f450d0c200c10350c0c0b200141086a280200210b200141046a28020021132001410c6a280200210e200341073a00002002200341011078200341003a00002013200e41146c6a211441002101410021074101210f200e210803402003200841807f72200841ff00712008410776220c1b22083a00000240024020012007460d00200721090c010b200741016a22092007490d07200741017422152009201520094b1b22094100480d070240024020070d00024020090d004101210f0c020b20091033220f450d110c010b20072009460d00200f200720091037220f450d100b200921070b200f20016a20083a0000200141016a2101200c2108200c0d000b024002400240200e0d002013210e0c010b201321070340200741146a210e200728020c220d4104460d0120072802042111200741106a28020021082007280200211220072802082210210703400240024020012009460d00200921150c010b200941016a220c2009490d0a20094101742215200c2015200c4b1b22154100480d0a0240024020090d00024020150d004101210f0c020b20151033220f450d140c010b20092015460d00200f200920151037220f450d130b201521090b200f20016a200741807f72200741ff00712007410776220c1b3a0000200141016a2101200c2107200c0d000b02400240201520016b2010490d00201521090c010b200120106a22092001490d09201541017422072009200720094b1b22094100480d09024020150d00024020090d004101210f0c020b20091033220f450d120c010b20152009460d00200f201520091037220f450d110b200f20016a20122010109d081a201020096b20016a210702402011450d00201210350b024002402007450d00200921070c010b200941016a22072009490d092009410174220c2007200c20074b1b22074100480d09024020090d00024020070d004101210f0c020b20071033220f450d120c010b20092007460d00200f200920071037220f450d110b200f20106a20016a200d3a0000201020016a41016a210103400240024020012007460d00200721090c010b200741016a22092007490d0a2007410174220c2009200c20094b1b22094100480d0a0240024020070d00024020090d004101210f0c020b20091033220f450d140c010b20072009460d00200f200720091037220f450d130b200921070b200f20016a200841807f72200841ff00712008410776220c1b3a0000200141016a2101200c2108200c0d000b200e2107200e2014470d000c020b0b2014200e460d000340200e41146a21070240200e41046a280200450d00200e28020010350b2007210e20142007470d000b0b0240200b450d00200b41146c450d00201310350b200341003a00002001210703402003200741800172200741ff0071200741077622081b3a000020022003410110782008210720080d000b2002200f200110782009450d0b200f10350c0b0b200141086a280200210e200141046a280200210c2001410c6a2802002115200341063a00002002200341011078200341386a410c6a41003602002003420137023c20032002360238200c20154104746a210241002101410021092015210703400240024020092001460d00200328023c21080c010b200141016a22082001490d062001410174220f2008200f20084b1b220f4100480d060240024020010d000240200f0d00410121080c020b200f10332208450d100c010b200328023c21082001200f460d0020082001200f10372208450d0f0b2003200f3602402003200836023c0b200820096a200741807f72200741ff0071200741077622071b3a00002003200941016a220936024402402007450d0020032802402101200721070c010b0b2003200236025c2003200c3602582003200e3602542003200c36025002402015450d00024003400240200c410d6a2d000022094102470d00200c41106a21020c020b200c41086a280200210f200c41046a2802002115200c280200210e2003200c410c6a2d000041ff007322083a000002400240200328024020032802442201460d00200328023c21070c010b200141016a22072001490d08200141017422082007200820074b1b22084100480d080240024020010d00024020080d00410121070c020b200810332207450d120c010b200328023c210720012008460d0020072001200810372207450d110b200320083602402003200736023c20032d00002108200328024421010b200720016a20083a00002003200141016a2201360244200320093a00000240024020032802402001460d00200328023c21070c010b200141016a22092001490d08200141017422072009200720094b1b22094100480d080240024020010d00024020090d00410121070c020b200910332207450d120c010b200328023c210720012009460d0020072001200910372207450d110b200320093602402003200736023c20032d00002109200328024421010b200720016a20093a00002003200141016a3602442003200f3602302003201536022c2003200e3602282003200341286a200341386a10a207024020032d00002201411f470d00200c41106a220c2002470d010c020b0b20032f000120032d00034110747221092003280204210720032802082108200328020c210f2003200c41106a360258200341d0006a10c60702402003280240450d00200328023c10350b200020093b0001200020013a0000200041036a20094110763a00002000410c6a200f360000200041086a2008360000200041046a20073600000c0d0b200320023602580b200341d0006a10c60720032802382107200328023c210f2003280240210c20032802442108200341003a00002008210103402003200141800172200141ff0071200141077622091b3a000020072003410110782009210120090d000b2007200f20081078200c450d0a200f10350c0a0b2001410c6a2802002110200141086a2802002112200141046a280200210e200341053a00002002200341011078200341d0006a410c6a41003602002003420137025420032002360250200341003a0000410021014101210f4100210920102107034020032007220741807f72200741ff0071200741077622071b22083a0000024020012009470d00200941016a220c2009490d0520094101742215200c2015200c4b1b220c4100480d05024002400240024020090d000240200c0d004101210f0c020b200c1033210f0c030b2009200c470d010b200c21090c020b200f2009200c1037210f0b200c2109200f450d0d0b200f20016a20083a0000200141016a210120070d000b2003200136025c2003200f36025420032009360258024002402010450d002010410c6c2108410021010340200e20016a220941046a28020022074102460d01200320092802002007200941086a280200200341d0006a10af0720032d00002209411f470d0220082001410c6a2201470d000b0b02402012450d002012410c6c450d00200e10350b200328025c21082003280258210c2003280254210f20032802502107200341003a00002008210103402003200141800172200141ff0071200141077622091b3a000020072003410110782009210120090d000b2007200f20081078200c450d0a200f10350c0a0b20032d0003411074210120032f00012107200328020c21082003280208210f2003280204210c02402012450d002012410c6c450d00200e10350b2007200172210102402003280258450d00200328025410350b200020013b0001200020093a0000200041036a20014110763a00002000410c6a2008360000200041086a200f360000200041046a200c3600000c0a0b2001410c6a2802002115200141086a2802002110200141046a280200210e200341043a00002002200341011078200341d0006a410c6a4100360200200342013702542003200236025041002101410121084100210920152107034020072107024020012009470d00200941016a220f2009490d042009410174220c200f200c200f4b1b220f4100480d04024002400240024020090d000240200f0d00410121080c020b200f103321080c030b2009200f470d010b200f21090c020b20082009200f103721080b200f21092008450d0c0b200820016a200741807f72200741ff0071200741077622071b3a0000200141016a210120070d000b2003200136025c2003200836025420032009360258024002402015450d002015410c6c2102410021090340200e20096a220141046a28020022084102460d012001280200210f200141086a280200210c200341f0003a0000024002402003280258200328025c2201460d0041f0002115200328025421070c010b200141016a22072001490d06200141017422152007201520074b1b22154100480d060240024020010d00024020150d00410121070c020b201510332207450d100c010b2003280254210720012015460d0020072001201510372207450d0f0b200320153602582003200736025420032d000021150b200720016a20153a00002003200141016a36025c2003200f2008200c200341d0006a10af0720032d00002201411f470d0220022009410c6a2209470d000b0b02402010450d002010410c6c450d00200e10350b200328025c21082003280258210c2003280254210f20032802502107200341003a00002008210103402003200141800172200141ff0071200141077622091b3a000020072003410110782009210120090d000b2007200f20081078200c450d09200f10350c090b20032d0003411074210920032f00012107200328020c21082003280208210f2003280204210c02402010450d002010410c6c450d00200e10350b2007200972210902402003280258450d00200328025410350b200020093b0001200020013a0000200041036a20094110763a00002000410c6a2008360000200041086a200f360000200041046a200c3600000c090b200141086a2802002114200141046a28020021122001410c6a280200210e200341033a00002002200341011078200341003a00002012200e4102746a211041002109410021074101210c200e210803402003200841807f72200841ff00712008410776220f1b22083a00000240024020092007460d00200721010c010b200741016a22012007490d03200741017422152001201520014b1b22014100480d030240024020070d00024020010d004101210c0c020b20011033220c450d0d0c010b20072001460d00200c200720011037220c450d0c0b200121070b200c20096a20083a0000200941016a2109200f2108200f0d000b02400240200e0d002001210f0c010b2012210e0340200e2802002107200341003a000003402003200741807f72200741ff0071200741077622081b22073a00000240024020092001460d002001210f0c010b200141016a220f2001490d0520014101742215200f2015200f4b1b220f4100480d050240024020010d000240200f0d004101210c0c020b200f1033220c450d0f0c010b2001200f460d00200c2001200f1037220c450d0e0b200f21010b200c20096a20073a0000200941016a21092008210720080d000b200f2101200e41046a220e2010470d000b0b0240201441ffffffff0371450d00201210350b200341003a00002009210103402003200141800172200141ff0071200141077622071b3a000020022003410110782007210120070d000b2002200c20091078200f450d07200c10350c070b200141086a280200211a200141046a28020021162001410c6a2802002115200341023a00002002200341011078200341d0006a410c6a410036020020034201370254200320023602502016201541286c6a210241002101410021092015210703400240024020092001460d00200328025421080c010b200141016a22082001490d022001410174220f2008200f20084b1b220f4100480d020240024020010d000240200f0d00410121080c020b200f10332208450d0c0c010b200328025421082001200f460d0020082001200f10372208450d0b0b2003200f360258200320083602540b200820096a200741807f72200741ff0071200741077622071b3a00002003200941016a220936025c02402007450d0020032802582101200721070c010b0b2016210c2015450d02201541286c41586a21102016210c0340200c220941286a210c20092d0018220d4104460d03200941206a29000021042009411c6a280000210f2009411a6a2d0000210a200941196a2c0000210b200941146a2802002115200941106a2802002111200928020c21122009280204211320092802002114200328025c21012009280208220e210903400240024020032802582001460d00200328025421070c010b200141016a22072001490d03200141017422082007200820074b1b22084100480d030240024020010d00024020080d00410121070c020b200810332207450d0d0c010b2003280254210720012008460d0020072001200810372207450d0c0b2003200836025820032007360254200328025c21010b200720016a200941807f72200941ff0071200941077622071b3a00002003200141016a220136025c2007210920070d000b024002402003280258220720016b200e490d00200328025421090c010b2001200e6a22092001490d02200741017422012009200120094b1b22014100480d020240024020070d00024020010d00410121090c020b200110332209450d0c0c010b2003280254210920072001460d0020092007200110372209450d0b0b2003200136025820032009360254200328025c21010b200920016a2014200e109d081a20032001200e6a220136025c02402013450d0020141035200328025c21010b2015210903400240024020032802582001460d00200328025421070c010b200141016a22072001490d03200141017422082007200820074b1b22084100480d030240024020010d00024020080d00410121070c020b200810332207450d0d0c010b2003280254210720012008460d0020072001200810372207450d0c0b2003200836025820032007360254200328025c21010b200720016a200941807f72200941ff0071200941077622071b3a00002003200141016a220136025c2007210920070d000b024002402003280258220720016b2015490d00200328025421090c010b200120156a22092001490d02200741017422012009200120094b1b22014100480d020240024020070d00024020010d00410121090c020b200110332209450d0c0c010b2003280254210920072001460d0020092007200110372209450d0b0b2003200136025820032009360254200328025c21010b200920016a20122015109d081a2003200120156a36025c02402011450d00201210350b02400240024002400240200d0e0400010203000b200341003a0000024002402003280258200328025c2201460d0041002107200328025421090c010b200141016a22092001490d06200141017422072009200720094b1b22074100480d060240024020010d00024020070d00410121090c020b200710332209450d100c010b2003280254210920012007460d0020092001200710372209450d0f0b200320073602582003200936025420032d00002107200328025c21010b200920016a20073a00002003200141016a220136025c200341003a000003402003200f41807f72200f41ff0071200f41077622091b22083a00000240024020032802582001460d00200328025421070c010b200141016a22072001490d07200141017422082007200820074b1b22084100480d070240024020010d00024020080d00410121070c020b200810332207450d110c010b2003280254210720012008460d0020072001200810372207450d100b200320083602582003200736025420032d00002108200328025c21010b200720016a20083a00002003200141016a220136025c2009210f20090d000c040b0b200341013a0000024002402003280258200328025c2201460d0041012107200328025421090c010b200141016a22092001490d05200141017422072009200720094b1b22074100480d050240024020010d00024020070d00410121090c020b200710332209450d0f0c010b2003280254210920012007460d0020092001200710372209450d0e0b200320073602582003200936025420032d00002107200328025c21010b200920016a20073a00002003200141016a220136025c200341f0003a00000240024020032802582001460d0041f0002107200328025421090c010b200141016a22092001490d05200141017422072009200720094b1b22074100480d050240024020010d00024020070d00410121090c020b200710332209450d0f0c010b2003280254210920012007460d0020092001200710372209450d0e0b200320073602582003200936025420032d00002107200328025c21010b200920016a20073a00002003200141016a36025c2003200f2004a72004422088a7200341d0006a10af0720032d00002201411f460d0220032f000120032d00034110747221090c050b200341023a0000024002402003280258200328025c2201460d0041022107200328025421090c010b200141016a22092001490d04200141017422072009200720094b1b22074100480d040240024020010d00024020070d00410121090c020b200710332209450d0e0c010b2003280254210920012007460d0020092001200710372209450d0d0b200320073602582003200936025420032d00002107200328025c21010b200920016a20073a00002003200141016a36025c2003200f2004a72004422088a7200341d0006a10af0720032d00002201411f460d0120032f000120032d00034110747221090c040b200341033a0000024002402003280258200328025c2201460d0041032107200328025421090c010b200141016a22092001490d03200141017422072009200720094b1b22074100480d030240024020010d00024020070d00410121090c020b200710332209450d0d0c010b2003280254210920012007460d0020092001200710372209450d0c0b200320073602582003200936025420032d00002107200328025c21010b200920016a20073a00002003200141016a220136025c2003200b417f732209413f7141c000722009200b417f4a1b22073a00000240024020032802582001460d00200328025421090c010b200141016a22092001490d03200141017422072009200720094b1b22074100480d030240024020010d00024020070d00410121090c020b200710332209450d0d0c010b2003280254210920012007460d0020092001200710372209450d0c0b200320073602582003200936025420032d00002107200328025c21010b200920016a20073a00002003200141016a220136025c2003200a41ff017141004722073a00000240024020032802582001460d00200328025421090c010b200141016a22092001490d03200141017422072009200720094b1b22074100480d030240024020010d00024020070d00410121090c020b200710332209450d0d0c010b2003280254210920012007460d0020092001200710372209450d0c0b200320073602582003200936025420032d00002107200328025c21010b200920016a20073a00002003200141016a36025c0b201041586a2110200c2002470d000c040b0b103e000b200328020c2107200328020821082003280204210f02402002200c460d0003400240200c41046a280200450d00200c28020010350b0240200c41106a280200450d00200c410c6a28020010350b200c41286a210c201041586a22100d000b0b0240201a450d00201a41286c450d00201610350b02402003280258450d00200328025410350b200020093b0001200020013a0000200041036a20094110763a00002000410c6a2007360000200041086a2008360000200041046a200f3600000c050b2002200c460d0003400240200c41046a280200450d00200c28020010350b200c41286a21010240200c41106a280200450d00200c410c6a28020010350b2001210c20022001470d000b0b0240201a450d00201a41286c450d00201610350b200328025c21082003280258210c2003280254210f20032802502107200341003a00002008210103402003200141800172200141ff0071200141077622091b3a000020072003410110782009210120090d000b2007200f20081078200c450d02200f10350c020b200d2010460d000340201041106a21090240201041046a280200450d00201028020010350b20092110200d2009470d000b0b0240200a41ffffffff0071450d00200b10350b200341003a00002007210903402003200941800172200941ff0071200941077622081b3a000020022003410110782008210920080d000b2002200e200710782001450d00200e10350b2000411f3a00000b200341e0006a24000f0b103c000be60703027f017e057f230041d0006b2202240041a3edcb00ad4280808080f00084100122032900002104200241086a41086a200341086a2900003703002002200437030820031035419cb4ca00ad4280808080800184100122032900002104200241186a41086a200341086a29000037030020022004370318200310350240024002400240200141086a28020041046a2203417f4c0d000240024020030d0041012105410021030c010b200310332205450d020b2002410036024820022005360240200220033602440240200341034b0d00200341017422064104200641044b1b22064100480d030240024020030d002006103322050d010c060b20032006460d0020052003200610372205450d050b20022006360244200220053602400b2005200128000036000020024104360248200141046a2802002107200141086a2802002201200241c0006a10770240024020022802442208200228024822056b2001490d0020022802402103200821060c010b200520016a22032005490d03200841017422062003200620034b1b22064100480d030240024020080d00024020060d00410121030c020b200610332203450d060c010b2002280240210320082006460d0020032008200610372203450d050b20022006360244200220033602400b200320056a20072001109d081a2002200520016a2201ad4220862003ad841003220529000037033820051035200241cc006a200320016a360200200220033602482002200241c0006a3602442002200241386a360240200241286a200241c0006a107b02402006450d00200310350b2002280230220841206a2206417f4c0d00200228022821070240024020060d0041002101410121030c010b200610332203450d02200621010b024002402001410f4d0d00200121050c010b200141017422054110200541104b1b22054100480d03024020010d00200510332203450d050c010b20012005460d0020032001200510372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020054170714110460d00200521010c010b200541017422014120200141204b1b22014100480d0320052001460d0020032005200110372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200141606a2008490d00200121050c010b200841206a22052008490d03200141017422092005200920054b1b22054100480d0320012005460d0020032001200510372203450d040b200341206a20072008109d081a2000200636020820002005360204200020033602000240200228022c450d00200710350b200241d0006a24000f0b1044000b1045000b103e000b103c000b130020004104360204200041a4bfca003602000b1300200041043602042000418cc3ca003602000b130020004101360204200041e8caca003602000b340020004193d1cb0036020420004100360200200041146a4103360200200041106a41e8cbca00360200200041086a420a3702000beb050a067f017e017f017e017f017e017f017e017f017e230041206b2202240002400240024020014108490d00200141017641feffffff07712203417f6a220420014f0d022001410d74200173220541117620057322054105742005732206417f2001417f6a677622077122054100200120052001491b6b220520014f0d01200020044105746a22042900002108200020054105746a220541086a2209290000210a200541106a220b290000210c200541186a220d290000210e20042005290000370000200441186a220f2900002110200f200e370000200441106a220f290000210e200f200c370000200441086a2204290000210c2004200a370000200d2010370000200b200e3700002009200c37000020052008370000024020032001490d00200321040c030b2006410d7420067322054111762005732205410574200573220620077122054100200120052001491b6b220520014f0d01200020034105746a22042900002108200020054105746a220541086a2209290000210a200541106a220b290000210c200541186a220d290000210e20042005290000370000200441186a220f2900002110200f200e370000200441106a220f290000210e200f200c370000200441086a2204290000210c2004200a370000200d2010370000200b200e3700002009200c370000200520083700002003410172220420014f0d022006410d742006732205411176200573220541057420057320077122054100200120052001491b6b220520014f0d01200020044105746a22012900002108200020054105746a220041086a2205290000210a200041106a2204290000210c200041186a2203290000210e20012000290000370000200141186a220629000021102006200e370000200141106a2206290000210e2006200c370000200141086a2201290000210c2001200a370000200320103700002004200e3700002005200c370000200020083700000b200241206a24000f0b20052001418486cc001042000b2004200141f485cc001042000be90609067f017e017f017e017f027e017f017e027f230041206b22022400024020014101762203450d0003402003417f6a2203210402400240024003402004410174220541017221060240200541026a220520014f0d00200620014f0d0220052006200020064105746a200020054105746a412010a0084100481b21060b200620014f0d03200420014f0d02200020044105746a2204200020064105746a2205412010a00841004e0d03200541086a22072900002108200541106a2209290000210a200541186a220b290000210c2004290000210d20042005290000370000200441186a220e290000210f200e200c370000200441106a220e290000210c200e200a370000200441086a2204290000210a20042008370000200b200f3700002009200c3700002007200a3700002005200d370000200621040c000b0b2006200141f487cc001042000b20042001418488cc001042000b20030d000b0b0240024020014102490d002001210703402007417f6a220720014f0d02200241186a2209200041186a2204290000370300200241106a220b200041106a2205290000370300200241086a220e200041086a2203290000370300200020074105746a220641086a2900002108200641106a290000210a200641186a290000210c2000290000210d200020062900003700002004200c3700002005200a370000200320083700002002200d37030041002105024002400240034020062002290300370000200641186a2009290300370000200641106a200b290300370000200641086a200e2903003700002005410174220641017221040240200641026a220620074f0d00200420074f0d0220062004200020044105746a200020064105746a412010a0084100481b21040b200420074f0d03200520074f0d02200020054105746a2205200020044105746a2206412010a00841004e0d032009200541186a2203290000370300200b200541106a2210290000370300200e200541086a2211290000370300200641086a2900002108200641106a290000210a200641186a290000210c2005290000210d200520062900003700002003200c3700002010200a370000201120083700002002200d370300200421050c000b0b2004200741f487cc001042000b20052007418488cc001042000b200741014b0d000b0b200241206a24000f0b20072001418486cc001042000bdb08030a7f017e0a7f230041c0006b22022400200041a07f6a21032001417f6a2104200141324921054101210641002107024003400240024020062001490d00410021080c010b41012108200020064105746a2209200941606a412010a0084100480d0003404101210a20042006460d03200641016a2106200941206a220a2009412010a0082108200a21092008417f4a0d000b200620014921080b2006200146210a20050d0120062001460d0102400240024002402006417f6a220920014f0d002008450d0120002006410574220b6a220a290000210c200a200020094105746a22092900003700002009200c370000200a41086a220d290000210c200d200941086a220e290000370000200e200c370000200a41106a220f290000210c200f200941106a22102900003700002010200c370000200a41186a2211290000210c2011200941186a22122900003700002012200c37000020064102490d03200920002006417e6a22084105746a2213412010a008417f4a0d032009290000210c20092013290000370000200241206a41186a22142012290000370300200241206a41106a22152010290000370300200241206a41086a2216200e290000370300200e201341086a2900003700002010201341106a2900003700002012201341186a2900003700002002200c3703204100210e2008450d022003200b6a210903400240200241206a2009412010a0084100480d002008210e0c040b200941206a2009290000370000200941386a200941186a290000370000200941306a200941106a290000370000200941286a200941086a290000370000200941606a21092008417f6a22080d000c030b0b2009200141f485cc001042000b20062001418486cc001042000b2000200e4105746a22092002290320370000200941186a2014290300370000200941106a2015290300370000200941086a20162903003700000b200741016a21070240200120066b22104102490d00200a41206a2209200a412010a008417f4a0d00200a290000210c200a2009290000370000200241206a41186a22122011290000370300200241206a41106a2213200f290000370300200241206a41086a220b200d290000370300200d200941086a290000370000200f200941106a2900003700002011200941186a2900003700002002200c3703204101210d024020104103490d00200a41c0006a200241206a412010a008417f4a0d00410321084102210e0340200a200e4105746a220941606a220d2009290000370000200d41186a200941186a290000370000200d41106a200941106a290000370000200d41086a200941086a290000370000024020082010490d00200e210d0c020b20084105742109200e210d2008210e200841016a2108200a20096a200241206a412010a0084100480d000b0b200a200d4105746a22092002290320370000200941186a2012290300370000200941106a2013290300370000200941086a200b2903003700000b20074105470d000b4100210a0b200241c0006a2400200a0b88090b107f017e017f017e017f017e017f017e017f017e017f230041306b2202240002400240024020014108490d00200141017641feffffff07712203417f6a220420014f0d022001410d74200173220541117620057322054105742005732206417f2001417f6a677622077122054100200120052001491b6b220520014f0d01200241286a22082000200441306c6a220441286a2209290300370300200241206a220a200441206a220b290300370300200241186a220c200441186a220d290300370300200241106a220e200441106a220f290300370300200241086a2210200441086a2211290300370300200220042903003703002000200541306c6a22052903002112200541086a22132903002114200541106a22152903002116200541186a22172903002118200541206a2219290300211a2009200541286a221b290300370300200b201a370300200d2018370300200f20163703002011201437030020042012370300201b20082903003703002019200a2903003703002017200c2903003703002015200e2903003703002013201029030037030020052002290300370300024020032001490d00200321040c030b2006410d7420067322044111762004732204410574200473220620077122044100200120042001491b6b220520014f0d01200241286a22082000200341306c6a220441286a2209290300370300200241206a220a200441206a220b290300370300200241186a220c200441186a220d290300370300200241106a220e200441106a220f290300370300200241086a2210200441086a2211290300370300200220042903003703002000200541306c6a22052903002112200541086a22132903002114200541106a22152903002116200541186a22172903002118200541206a2219290300211a2009200541286a221b290300370300200b201a370300200d2018370300200f20163703002011201437030020042012370300201b20082903003703002019200a2903003703002017200c2903003703002015200e29030037030020132010290300370300200520022903003703002003410172220420014f0d022006410d742006732205411176200573220541057420057320077122054100200120052001491b6b220520014f0d01200241286a22032000200441306c6a220141286a2204290300370300200241206a2206200141206a2207290300370300200241186a2208200141186a2209290300370300200241106a220a200141106a220b290300370300200241086a220c200141086a220d290300370300200220012903003703002000200541306c6a22002903002112200041086a22052903002114200041106a220e2903002116200041186a220f2903002118200041206a2210290300211a2004200041286a22112903003703002007201a37030020092018370300200b2016370300200d2014370300200120123703002011200329030037030020102006290300370300200f2008290300370300200e200a2903003703002005200c290300370300200020022903003703000b200241306a24000f0b20052001418486cc001042000b2004200141f485cc001042000bf30a020e7f027e02402000280200220428020028020028020028020028020022052802002206450d0020012802002107200428020428020022082002280200220941306c6a210a2005280204210b2006210c02400340200c41086a210d200c2f0106220e410574210f41002110024002400340200f450d01200a200d412010a0082211450d02200f41606a210f201041016a2110200d41206a210d2011417f4a0d000b2010417f6a210e0b0240200b0d0042002112420021130c030b200b417f6a210b200c200e4102746a41c8056a280200210c0c010b0b200c20104105746a220f41f0026a2903002113200f41e8026a29030021120b2006450d002008200741306c6a210a2005280204210b2006210c02400340200c41086a210d200c2f0106220e410574210f41002110024002400340200f450d01200a200d412010a0082211450d02200f41606a210f201041016a2110200d41206a210d2011417f4a0d000b2010417f6a210e0b200b450d02200b417f6a210b200c200e4102746a41c8056a280200210c0c010b0b2012200c20104105746a220f41e8026a2903005a2013200f41f0026a29030022125a20132012511b0d0020012009360200200220073602002004280208220f200f28020041016a360200200228020021092000280200220428020428020021082004280200280200280200280200280200220528020021060b2006450d0020082003280200220741306c6a210a2005280204210b2006210c02400340200c41086a210d200c2f0106220e410574210f41002110024002400340200f450d01200a200d412010a0082211450d02200f41606a210f201041016a2110200d41206a210d2011417f4a0d000b2010417f6a210e0b0240200b0d0042002112420021130c030b200b417f6a210b200c200e4102746a41c8056a280200210c0c010b0b200c20104105746a220f41f0026a2903002113200f41e8026a29030021120b2006450d002008200941306c6a210a2005280204210b2006210c02400340200c41086a210d200c2f0106220e410574210f41002110024002400340200f450d01200a200d412010a0082211450d02200f41606a210f201041016a2110200d41206a210d2011417f4a0d000b2010417f6a210e0b200b450d02200b417f6a210b200c200e4102746a41c8056a280200210c0c010b0b2012200c20104105746a220f41e8026a2903005a2013200f41f0026a29030022125a20132012511b0d0020022007360200200320093602002004280208220f200f28020041016a360200200228020021092000280200220428020428020021082004280200280200280200280200280200220528020021060b2006450d00200128020021002008200941306c6a210a2005280204210b2006210c02400340200c41086a210d200c2f0106220e410574210f41002110024002400340200f450d01200a200d412010a0082211450d02200f41606a210f201041016a2110200d41206a210d2011417f4a0d000b2010417f6a210e0b0240200b0d0042002112420021130c030b200b417f6a210b200c200e4102746a41c8056a280200210c0c010b0b200c20104105746a220f41f0026a2903002113200f41e8026a29030021120b2006450d002008200041306c6a210a2005280204210c0340200641086a210d20062f0106220b410574210f41002110024002400340200f450d01200a200d412010a0082211450d02200f41606a210f201041016a2110200d41206a210d2011417f4a0d000b2010417f6a210b0b200c450d02200c417f6a210c2006200b4102746a41c8056a28020021060c010b0b2012200620104105746a220f41e8026a2903005a2013200f41f0026a29030022125a20132012511b0d0020012009360200200220003602002004280208220f200f28020041016a3602000b0bfe030a0d7f017e017f017e017f017e017f017e017f017e230041c0006b22032400200320023602082003200341086a36020c024020014101762202450d002003410c6a200020012002417f6a1084072002417e6a210203402002417f460d012003410c6a2000200120021084072002417f6a21020c000b0b0240024020014102490d00200141306c20006a41506a21022001210403402004417f6a220520014f0d02200341106a41286a2204200041286a2206290300370300200341106a41206a2207200041206a2208290300370300200341106a41186a2209200041186a220a290300370300200341106a41106a220b200041106a220c290300370300200341106a41086a220d200041086a220e29030037030020032000290300370310200241086a220f2903002110200241106a22112903002112200241186a22132903002114200241206a22152903002116200241286a22172903002118200020022903003703002006201837030020082016370300200a2014370300200c2012370300200e20103703002017200429030037030020152007290300370300201320092903003703002011200b290300370300200f200d290300370300200220032903103703002003410c6a200020054100108407200241506a210220052104200541014b0d000b0b200341c0006a24000f0b2004417f6a2001418486cc001042000bf20f03107f027e0a7f230041306b22032400410021042001413249210541012106024003400240024020062001490d00410021070c010b20022802002802002802002208280200210941012107034002402009450d002006417f6a210a2000200641306c6a210b2008280204210c2009210d02400340200d41086a210e200d2f0106220f4105742110410021110240024003402010450d01200b200e412010a0082212450d02201041606a2110201141016a2111200e41206a210e2012417f4a0d000b2011417f6a210f0b0240200c0d0042002113420021140c030b200c417f6a210c200d200f4102746a41c8056a280200210d0c010b0b200d20114105746a221041f0026a2903002114201041e8026a29030021130b2009450d002000200a41306c6a210b2008280204210c2009210d0340200d41086a210e200d2f0106220f4105742110410021110240024003402010450d01200b200e412010a0082212450d02201041606a2110201141016a2111200e41206a210e2012417f4a0d000b2011417f6a210f0b200c450d02200c417f6a210c200d200f4102746a41c8056a280200210d0c010b0b2013200d20114105746a221041e8026a2903005a2014201041f0026a29030022135a20142013511b450d020b41012110200641016a2206200149210720062001470d000c030b0b2006200146211020050d0120062001460d0102400240024002402006417f6a221020014f0d002007410171450d01200441016a21042000201041306c6a2210290300211420102000200641306c6a220b290300370300200341286a2209201041286a220e290300370300200341206a2207201041206a2211290300370300200341186a2208201041186a2212290300370300200341106a220a201041106a220d290300370300200341086a2215201041086a22102903003703002010200b41086a2216290300370300200d200b41106a22172903003703002012200b41186a22182903003703002011200b41206a2219290300370300200e200b41286a221a29030037030020032014370300200b2003290300370300201a200929030037030020192007290300370300201820082903003703002017200a29030037030020162015290300370300200020062002108307200120066b221b4102490d032002280200280200280200221c280200220f450d03200b41306a210d201c280204211d200f210c02400340200c41086a210e200c2f0106221e4105742110410021110240024003402010450d01200d200e412010a0082212450d02201041606a2110201141016a2111200e41206a210e2012417f4a0d000b2011417f6a211e0b0240201d0d0042002113420021140c030b201d417f6a211d200c201e4102746a41c8056a280200210c0c010b0b200c20114105746a221041f0026a2903002114201041e8026a29030021130b200f450d03201c280204210c0340200f41086a210e200f2f0106221d4105742110410021110240024003402010450d01200b200e412010a0082212450d02201041606a2110201141016a2111200e41206a210e2012417f4a0d000b2011417f6a211d0b200c450d05200c417f6a210c200f201d4102746a41c8056a280200210f0c010b0b2013200f20114105746a221041e8026a2903005a2014201041f0026a29030022135a20142013511b0d03200b2903002114200b200d2903003703002009201a2903003703002007201929030037030020082018290300370300200a2017290300370300201520162903003703002016200d41086a2903003703002017200d41106a2903003703002018200d41186a2903003703002019200d41206a290300370300201a200d41286a290300370300200320143703004101211e201b4103490d02410321184102211a4101211e034020022802002802002802002219280200220c450d03200b201a41306c6a210d2018211d20192802042116200c210f02400340200f41086a210e200f2f010622174105742110410021110240024003402010450d01200d200e412010a0082212450d02201041606a2110201141016a2111200e41206a210e2012417f4a0d000b2011417f6a21170b024020160d0042002113420021140c030b2016417f6a2116200f20174102746a41c8056a280200210f0c010b0b200f20114105746a221041f0026a2903002114201041e8026a29030021130b200c450d032019280204210f0340200c41086a210e200c2f010622164105742110410021110240024003402010450d012003200e412010a0082212450d02201041606a2110201141016a2111200e41206a210e2012417f4a0d000b2011417f6a21160b200f450d05200f417f6a210f200c20164102746a41c8056a280200210c0c010b0b2013200c20114105746a221041e8026a290300542014201041f0026a29030022135420142013511b450d03200d41506a2210200d290300370300201041286a200d41286a290300370300201041206a200d41206a290300370300201041186a200d41186a290300370300201041106a200d41106a290300370300201041086a200d41086a29030037030002402018201b4f0d00201841016a2118201a211e201d211a0c010b0b201a211e0c020b2010200141f485cc001042000b20062001418486cc001042000b200b201e41306c6a22102003290300370300201041286a2009290300370300201041206a2007290300370300201041186a2008290300370300201041106a200a290300370300201041086a20152903003703000b20044105470d000b410021100b200341306a240020100bc709030c7f027e057f230041306b22032400024020014102490d00200228020028020028020022042802002205450d002001417e6a2106200141306c20006a220141a07f6a2107200141506a2108200428020421092005210a02400340200a41086a210b200a2f0106220c41057421014100210d0240024003402001450d012008200b412010a008220e450d02200141606a2101200d41016a210d200b41206a210b200e417f4a0d000b200d417f6a210c0b024020090d004200210f420021100c030b2009417f6a2109200a200c4102746a41c8056a280200210a0c010b0b200a200d4105746a220141f0026a2903002110200141e8026a290300210f0b2005450d002004280204210a0340200541086a210b20052f0106220941057421014100210d0240024003402001450d012007200b412010a008220e450d02200141606a2101200d41016a210d200b41206a210b200e417f4a0d000b200d417f6a21090b200a450d02200a417f6a210a200520094102746a41c8056a28020021050c010b0b200f2005200d4105746a220141e8026a2903005a2010200141f0026a290300220f5a2010200f511b0d002008290300211020082007290300370300200341286a2211200841286a2201290300370300200341206a2212200841206a220b290300370300200341186a2213200841186a220d290300370300200341106a2214200841106a220e290300370300200341086a2215200841086a22082903003703002008200741086a290300370300200e200741106a290300370300200d200741186a290300370300200b200741206a2903003703002001200741286a290300370300200320103703000240024020060d00410021060c010b03402002280200280200280200220c2802002207450d0120002006417f6a220441306c6a2108200c28020421052007210a02400340200a41086a210b200a2f0106220941057421014100210d0240024003402001450d012003200b412010a008220e450d02200141606a2101200d41016a210d200b41206a210b200e417f4a0d000b200d417f6a21090b024020050d004200210f420021100c030b2005417f6a2105200a20094102746a41c8056a280200210a0c010b0b200a200d4105746a220141f0026a2903002110200141e8026a290300210f0b2007450d01200c280204210a0340200741086a210b20072f0106220541057421014100210d0240024003402001450d012008200b412010a008220e450d02200141606a2101200d41016a210d200b41206a210b200e417f4a0d000b200d417f6a21050b200a450d03200a417f6a210a200720054102746a41c8056a28020021070c010b0b200f2007200d4105746a220141e8026a290300542010200141f0026a290300220f542010200f511b450d012000200641306c6a22012008290300370300200141286a200841286a290300370300200141206a200841206a290300370300200141186a200841186a290300370300200141106a200841106a290300370300200141086a200841086a2903003703002004210620040d000b410021060b2000200641306c6a22012003290300370300200141286a2011290300370300200141206a2012290300370300200141186a2013290300370300200141106a2014290300370300200141086a20152903003703000b200341306a24000bd20907067f027e077f027e047f017e017f230041306b2204240003402003410174220541017221060240200541026a220720024f0d00024002400240200620024f0d0002402000280200280200280200280200280200220828020022090d004200210a4200210b0c020b2001200641306c6a210c2008280204210d2009210e02400340200e41086a210f200e2f010622104105742105410021110240024003402005450d01200c200f412010a0082212450d02200541606a2105201141016a2111200f41206a210f2012417f4a0d000b2011417f6a21100b0240200d0d004200210a4200210b0c030b200d417f6a210d200e20104102746a41c8056a280200210e0c010b0b200e20114105746a220541f0026a290300210b200541e8026a290300210a0b2009450d012001200741306c6a210c2008280204210e0340200941086a210f20092f0106220d4105742105410021110240024003402005450d01200c200f412010a0082212450d02200541606a2105201141016a2111200f41206a210f2012417f4a0d000b2011417f6a210d0b200e450d03200e417f6a210e2009200d4102746a41c8056a28020021090c010b0b200920114105746a220541f0026a2903002113200541e8026a29030021140c020b2006200241f487cc001042000b42002114420021130b20072006200a201454200b201354200b2013511b1b21060b024002400240200620024f0d00200320024f0d0120002802002802002802002802002802002210280200220e450d002001200341306c6a210c20102802042109200e210302400340200341086a210f20032f0106220d4105742105410021110240024003402005450d01200c200f412010a0082212450d02200541606a2105201141016a2111200f41206a210f2012417f4a0d000b2011417f6a210d0b024020090d00420021134200210b0c030b2009417f6a21092003200d4102746a41c8056a28020021030c010b0b200320114105746a220541f0026a290300210b200541e8026a29030021130b200e450d002001200641306c6a2103201028020421090340200e41086a210f200e2f0106220d4105742105410021110240024003402005450d012003200f412010a0082212450d02200541606a2105201141016a2111200f41206a210f2012417f4a0d000b2011417f6a210d0b2009450d022009417f6a2109200e200d4102746a41c8056a280200210e0c010b0b2013200e20114105746a220541e8026a29030054200b200541f0026a290300221354200b2013511b0d020b200441306a24000f0b20032002418488cc001042000b200441286a2205200c41286a220f290300370300200441206a2211200c41206a2212290300370300200441186a220e200c41186a2209290300370300200441106a220d200c41106a2210290300370300200441086a2207200c41086a22082903003703002004200c2903003703002003290300210b200341086a22152903002113200341106a2216290300210a200341186a22172903002114200341206a22182903002119200f200341286a221a29030037030020122019370300200920143703002010200a37030020082013370300200c200b370300201a2005290300370300201820112903003703002017200e2903003703002016200d2903003703002015200729030037030020032004290300370300200621030c000b0b88090b107f017e017f017e017f017e017f017e017f017e017f230041306b2202240002400240024020014108490d00200141017641feffffff07712203417f6a220420014f0d022001410d74200173220541117620057322054105742005732206417f2001417f6a677622077122054100200120052001491b6b220520014f0d01200241286a22082000200441306c6a220441286a2209290300370300200241206a220a200441206a220b290300370300200241186a220c200441186a220d290300370300200241106a220e200441106a220f290300370300200241086a2210200441086a2211290300370300200220042903003703002000200541306c6a22052903002112200541086a22132903002114200541106a22152903002116200541186a22172903002118200541206a2219290300211a2009200541286a221b290300370300200b201a370300200d2018370300200f20163703002011201437030020042012370300201b20082903003703002019200a2903003703002017200c2903003703002015200e2903003703002013201029030037030020052002290300370300024020032001490d00200321040c030b2006410d7420067322044111762004732204410574200473220620077122044100200120042001491b6b220520014f0d01200241286a22082000200341306c6a220441286a2209290300370300200241206a220a200441206a220b290300370300200241186a220c200441186a220d290300370300200241106a220e200441106a220f290300370300200241086a2210200441086a2211290300370300200220042903003703002000200541306c6a22052903002112200541086a22132903002114200541106a22152903002116200541186a22172903002118200541206a2219290300211a2009200541286a221b290300370300200b201a370300200d2018370300200f20163703002011201437030020042012370300201b20082903003703002019200a2903003703002017200c2903003703002015200e29030037030020132010290300370300200520022903003703002003410172220420014f0d022006410d742006732205411176200573220541057420057320077122054100200120052001491b6b220520014f0d01200241286a22032000200441306c6a220141286a2204290300370300200241206a2206200141206a2207290300370300200241186a2208200141186a2209290300370300200241106a220a200141106a220b290300370300200241086a220c200141086a220d290300370300200220012903003703002000200541306c6a22002903002112200041086a22052903002114200041106a220e2903002116200041186a220f2903002118200041206a2210290300211a2004200041286a22112903003703002007201a37030020092018370300200b2016370300200d2014370300200120123703002011200329030037030020102006290300370300200f2008290300370300200e200a2903003703002005200c290300370300200020022903003703000b200241306a24000f0b20052001418486cc001042000b2004200141f485cc001042000bf20907077f027e0b7f017e017f027e017f230041306b22022400024020014101762203450d0003402003417f6a2203210402400240024003402004410174220541017221060240200541026a220520014f0d00200620014f0d02200520062000200641306c6a22072903002000200541306c6a220829030056200741086a2903002209200841086a290300220a562009200a511b1b21060b200620014f0d03200420014f0d022000200441306c6a22042903002000200641306c6a220529030056200441086a22072903002209200541086a2208290300220a562009200a511b450d03200241286a220b200441286a220c290300370300200241206a220d200441206a220e290300370300200241186a220f200441186a2210290300370300200241106a2211200441106a2212290300370300200241086a221320072903003703002002200429030037030020082903002109200541106a2214290300210a200541186a22152903002116200541206a2217290300211820052903002119200c200541286a221a290300370300200e2018370300201020163703002012200a3703002007200937030020042019370300201a200b2903003703002017200d2903003703002015200f290300370300201420112903003703002008201329030037030020052002290300370300200621040c000b0b2006200141f487cc001042000b20042001418488cc001042000b20030d000b0b0240024020014102490d002001210703402007417f6a220720014f0d02200241286a220b200041286a2205290300370300200241206a220c200041206a2206290300370300200241186a220d200041186a2208290300370300200241106a220e200041106a2210290300370300200241086a220f200041086a2211290300370300200220002903003703002000200741306c6a22042903002109200441086a290300210a200441106a2903002116200441186a2903002118200441206a29030021192005200441286a2903003703002006201937030020082018370300201020163703002011200a3703002000200937030041002105024002400240034020042002290300370300200441286a200b290300370300200441206a200c290300370300200441186a200d290300370300200441106a200e290300370300200441086a200f2903003703002005410174220441017221060240200441026a220420074f0d00200620074f0d02200420062000200641306c6a22082903002000200441306c6a221029030056200841086a2903002209201041086a290300220a562009200a511b1b21060b200620074f0d03200520074f0d022000200541306c6a22052903002000200641306c6a220429030056200541086a22082903002209200441086a2210290300220a562009200a511b450d03200b200541286a2211290300370300200c200541206a2212290300370300200d200541186a2213290300370300200e200541106a2214290300370300200f20082903003703002002200529030037030020102903002109200441106a290300210a200441186a2903002116200441206a2903002118200429030021192011200441286a29030037030020122018370300201320163703002014200a3703002008200937030020052019370300200621050c000b0b2006200741f487cc001042000b20052007418488cc001042000b200741014b0d000b0b200241306a24000f0b20072001418486cc001042000bb80c050a7f017e017f037e0f7f230041306b22022400200041c07e6a21032001417f6a2104200041306a2105410021062001413249210741012108024003400240024020082001490d00410021090c010b410121092000200841306c220a6a220b290300220c200b41506a220d29030056200b41086a290300220e200d41086a290300220f56200e200f511b0d002005200a6a210903404101210b20042008460d03200841016a210820092903002210200c58210b200941086a290300220f200e51210d200f200e58210a200941306a21092010210c200f210e200b200a200d1b0d000b200820014921090b2008200146210b20070d0120082001460d010240024002400240024002402008417f6a220b20014f0d002009450d012000200b41306c6a2209290300210e20092000200841306c22116a220b290300370300200241286a220a200941286a2212290300370300200241206a2213200941206a2214290300370300200241186a2215200941186a2216290300370300200241106a2217200941106a2218290300370300200241086a2219200941086a220d290300370300200d200b41086a221a2903003703002018200b41106a221b2903003703002016200b41186a221c2903003703002014200b41206a221d2903003703002012200b41286a221e2903003703002002200e370300200b2002290300370300201e200a290300370300201d2013290300370300201c2015290300370300201b2017290300370300201a201929030037030020084102490d052009290300220c20002008417e6a221341306c6a220a29030058200d290300220e200a41086a221f290300220f58200e200f511b0d052009200a290300370300200d201f2903003703002009290310210f2018200a41106a2903003703002015201229030037030020172014290300370300201920162903003703002016200a41186a2903003703002014200a41206a2903003703002012200a41286a2903003703002002200f370300024020130d00410021130c050b200c20002008417d6a220d41306c6a220929030058200e200941086a290300220f58200e200f511b0d04200320116a2109034020094188016a200941d8006a29030037030020094180016a200941d0006a290300370300200941f8006a200941c8006a290300370300200941f0006a200941c0006a290300370300200941e8006a200941386a290300370300200941e0006a200941306a290300370300200d450d032009290300210f200941086a210a200941506a2109200d417f6a210d200c200f56200e200a290300220f56200e200f511b0d000b200d41016a21130c030b200b200141f485cc001042000b20082001418486cc001042000b410021130b2000201341306c6a210a0b200a200c370300200a200e3703082000201341306c6a22092002290300370310200941286a2015290300370300200941206a2017290300370300200941186a20192903003703000b200641016a21060240200120086b22144102490d00200b290330200b290300220c58200b41386a290300220f201a290300220e58200f200e511b0d00200b200b41306a2212290300370300201a201241086a290300370300200b290310210f201b201241106a2903003703002015201e2903003703002017201d2903003703002019201c290300370300201c201241186a290300370300201d201241206a290300370300201e201241286a2903003703002002200f3703004101211a024020144103490d00200b290360200c58200b41e8006a290300220f200e58200f200e511b0d00200b41e0006a21094103210a4102210d0340200d221a41306c200b6a221241506a220d2009290300370300200d41286a200941286a290300370300200d41206a200941206a290300370300200d41186a200941186a290300370300200d41106a200941106a290300370300200d41086a200941086a290300370300200a20144f0d01200a41306c2109200a210d200a41016a210a200b20096a2209290300200c56200941086a290300220f200e56200f200e511b0d000b0b2012200c3703002012200e370308200b201a41306c6a22092002290300370310200941286a2015290300370300200941206a2017290300370300200941186a20192903003703000b20064105470d000b4100210b0b200241306a2400200b0b13002000410736020420004194d1ca003602000b130020004100360204200041b0b4cc003602000b9f0303027f017e027f230041206b2202240041c7d5ca00ad4280808080b00284100122032900002104200241086a200341086a29000037030020022004370300200310354190eaca00ad4280808080e00084100122032900002104200241106a41086a200341086a29000037030020022004370310200310350240412010332203450d0020032001290000370000200341186a2205200141186a290000370000200341106a2206200141106a290000370000200341086a200141086a290000370000412010332201450d0020012003290000370000200141186a2005290000370000200141106a2006290000370000200141086a2205200341086a2900003700002003103541c00010332203450d002003200229031037001020032002290300370000200341086a200241086a290300370000200341186a200241106a41086a290300370000200042c080808080083702042000200336020020032001290000370020200341286a2005290000370000200341306a200141106a290000370000200341386a200141186a29000037000020011035200241206a24000f0b1045000ba10701087f230041106b220224002002410036020820024201370300200028020021030240410410332204450d00200241043602042002200436020020042003360000200241043602082000280204210320044104410810372204450d002002410836020420042003360004200220043602002002410836020820002802082104200041106a280200220320021077024002402003450d00200341057421052002280204210620022802082103034002400240200620036b4120490d00200341206a2107200228020021080c010b200341206a22072003490d03200641017422082007200820074b1b22094100480d030240024020060d00024020090d00410121080c020b2009103322080d010c060b2002280200210820062009460d0020082006200910372208450d050b2002200936020420022008360200200921060b200820036a22032004290000370000200341186a200441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002002200736020820072103200441206a2104200541606a22050d000b0b200028021421042000411c6a2802002203200210770240024020030d0020022802042109200228020821030c010b200341057421054100200228020822036b210820022802042106034002400240200620086a4120490d0020022802002107200621090c010b200341206a22072003490d03200641017422092007200920074b1b22094100480d030240024020060d00024020090d00410121070c020b200910332207450d060c010b2002280200210720062009460d0020072006200910372207450d050b2002200936020420022007360200200921060b200720036a22072004290000370000200741186a200441186a290000370000200741106a200441106a290000370000200741086a200441086a2900003700002002200341206a2203360208200841606a2108200441206a2104200541606a22050d000b0b2000280220210602400240200920036b4104490d0020022802002104200921070c010b200341046a22042003490d01200941017422072004200720044b1b22074100480d010240024020090d00024020070d00410121040c020b200710332204450d040c010b2002280200210420092007460d0020042009200710372204450d030b20022007360204200220043602000b200420036a20063600002001290200200341046aad4220862004ad84100202402007450d00200410350b200241106a24000f0b103e000b103c000b9f0303027f017e027f230041206b2202240041dad5ca00ad4280808080b00284100122032900002104200241086a200341086a29000037030020022004370300200310354190eaca00ad4280808080e00084100122032900002104200241106a41086a200341086a29000037030020022004370310200310350240412010332203450d0020032001290000370000200341186a2205200141186a290000370000200341106a2206200141106a290000370000200341086a200141086a290000370000412010332201450d0020012003290000370000200141186a2005290000370000200141106a2006290000370000200141086a2205200341086a2900003700002003103541c00010332203450d002003200229031037001020032002290300370000200341086a200241086a290300370000200341186a200241106a41086a290300370000200042c080808080083702042000200336020020032001290000370020200341286a2005290000370000200341306a200141106a290000370000200341386a200141186a29000037000020011035200241206a24000f0b1045000b130020004109360204200041a8eaca003602000b3400200041f8a2cb0036020420004100360200200041146a4103360200200041106a4180a3cb00360200200041086a42083702000b130020004105360204200041b4a9cb003602000b3400200041c7d5ca0036020420004100360200200041146a4106360200200041106a41f8bbcb00360200200041086a42133702000b3400200041dad5ca0036020420004100360200200041146a4106360200200041106a41f8bbcb00360200200041086a42133702000ba10701087f230041106b220224002002410036020820024201370300200028020021030240410410332204450d00200241043602042002200436020020042003360000200241043602082000280204210320044104410810372204450d002002410836020420042003360004200220043602002002410836020820002802082104200041106a280200220320021077024002402003450d00200341057421052002280204210620022802082103034002400240200620036b4120490d00200341206a2107200228020021080c010b200341206a22072003490d03200641017422082007200820074b1b22094100480d030240024020060d00024020090d00410121080c020b2009103322080d010c060b2002280200210820062009460d0020082006200910372208450d050b2002200936020420022008360200200921060b200820036a22032004290000370000200341186a200441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002002200736020820072103200441206a2104200541606a22050d000b0b200028021421042000411c6a2802002203200210770240024020030d0020022802042109200228020821030c010b200341057421054100200228020822036b210820022802042106034002400240200620086a4120490d0020022802002107200621090c010b200341206a22072003490d03200641017422092007200920074b1b22094100480d030240024020060d00024020090d00410121070c020b200910332207450d060c010b2002280200210720062009460d0020072006200910372207450d050b2002200936020420022007360200200921060b200720036a22072004290000370000200741186a200441186a290000370000200741106a200441106a290000370000200741086a200441086a2900003700002002200341206a2203360208200841606a2108200441206a2104200541606a22050d000b0b2000280220210602400240200920036b4104490d0020022802002104200921070c010b200341046a22042003490d01200941017422072004200720044b1b22074100480d010240024020090d00024020070d00410121040c020b200710332204450d040c010b2002280200210420092007460d0020042009200710372204450d030b20022007360204200220043602000b200420036a20063600002001290200200341046aad4220862004ad84100202402007450d00200410350b200241106a24000f0b103e000b103c000b340020004182e9ca0036020420004100360200200041146a4101360200200041106a41b8c0cb00360200200041086a42183702000bfd0303037f027e047f230041106b220224002002410036020820024201370300200028021021030240410410332204450d0020024104360204200220043602002004200336000020024104360208200041086a29030021052000290300210620044104411410372204450d00200420063700042004410c6a200537000020024294808080c00237020420022004360200200028021421072000411c6a2802002200200210770240024020000d002002280208210320022802042108200228020021090c010b2000410574210a200228020021092002280204210820022802082103034020072100024002402008200322046b4120490d00200441206a21030c010b024002400240200441206a22032004490d00200841017422072003200720034b1b22074100480d000240024020080d00024020070d00410121090c020b2007103321090c040b20082007470d020b200721080c030b103e000b200920082007103721090b200721082009450d030b200041206a2107200920046a22042000290000370000200441186a200041186a290000370000200441106a200041106a290000370000200441086a200041086a290000370000200a41606a220a0d000b2002200836020420022003360208200220093602000b20012902002003ad4220862009ad84100202402008450d00200910350b200241106a24000f0b103c000bc20503027f017e047f230041d0006b2202240041f8a2cb00ad4280808080800184100122032900002104200241086a200341086a290000370300200220043703002003103541e4a6cb00ad4280808080d00084100122032900002104200241106a41086a200341086a29000037030020022004370310200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003ad4280808080800484100422012900002104200241306a41086a200141086a2900003703002002200437033020011035200241cc006a200341206a360200200220033602482002200241306a41106a3602442002200241306a360240200241206a200241c0006a107b200310352002280228220541206a2201417f4c0d01200228022021060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290300370000200341086a200241086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290310370010200341186a200241106a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a20002001360208200020083602042000200336020002402002280224450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000bb10503027f017e047f230041d0006b2202240041f8a2cb00ad4280808080800184100122032900002104200241086a41086a200341086a29000037030020022004370308200310354188a5cb00ad4280808080b00184100122032900002104200241186a41086a200341086a29000037030020022004370318200310350240024002400240412010332203450d0020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a29000037000020022003ad42808080808004841003220129000037033820011035200241cc006a200341206a360200200220033602482002200241386a41086a3602442002200241386a360240200241286a200241c0006a107b200310352002280230220541206a2201417f4c0d01200228022821060240024020010d0041002107410121030c010b200110332203450d01200121070b024002402007410f4d0d00200721080c010b200741017422084110200841104b1b22084100480d03024020070d002008103322030d010c050b20072008460d0020032007200810372203450d040b20032002290308370000200341086a200241086a41086a2903003700000240024020084170714110460d00200821070c010b200841017422074120200741204b1b22074100480d0320082007460d0020032008200710372203450d040b20032002290318370010200341186a200241186a41086a29030037000002400240200741606a2005490d00200721080c010b2005415f4b0d03200741017422082001200820014b1b22084100480d0320072008460d0020032007200810372203450d040b200341206a20062005109d081a2000200136020820002008360204200020033602000240200228022c450d00200610350b200241d0006a24000f0b1045000b1044000b103e000b103c000bdc0703027f017e067f230041e0006b2203240041f8a2cb00ad4280808080800184100122042900002105200341086a41086a200441086a290000370300200320053703082004103541e8a5cb00ad4280808080800284100122042900002105200341186a41086a200441086a29000037030020032005370318200410350240024002400240412010332204450d0020042001290000370000200441186a200141186a290000370000200441106a200141106a290000370000200441086a200141086a29000037000020032004ad42808080808004841003220129000037034820011035200341dc006a2201200441206a360200200320043602582003200341c8006a41086a22063602542003200341c8006a360250200341286a200341d0006a107b20041035412010332204450d0020042002290000370000200441186a200241186a290000370000200441106a200241106a290000370000200441086a200241086a29000037000020032004ad428080808080048410032202290000370348200210352001200441206a36020020032004360258200320063602542003200341c8006a360250200341386a200341d0006a107b200410352003280230220741206a2206200328024022086a2201417f4c0d01200328023821092003280228210a0240024020010d004100210b410121040c010b200110332204450d012001210b0b02400240200b410f4d0d00200b21020c010b200b41017422024110200241104b1b22024100480d030240200b0d002002103322040d010c050b200b2002460d002004200b200210372204450d040b20042003290308370000200441086a200341086a41086a2903003700000240024020024170714110460d002002210b0c010b2002410174220b4120200b41204b1b220b4100480d032002200b460d0020042002200b10372204450d040b20042003290318370010200441186a200341186a41086a29030037000002400240200b41606a2007490d00200b21020c010b2007415f4b0d03200b41017422022006200220064b1b22024100480d03200b2002460d002004200b200210372204450d040b200441206a200a2007109d081a02400240200220066b2008490d002002210b0c010b20012006490d032002410174220b2001200b20014b1b220b4100480d03024020020d000240200b0d00410121040c020b200b10332204450d050c010b2002200b460d0020042002200b10372204450d040b200420066a20092008109d081a200020013602082000200b360204200020043602000240200328023c450d00200910350b0240200328022c450d00200a10350b200341e0006a24000f0b1045000b1044000b103e000b103c000b130020004110360204200041fcc2cb003602000b9f0303027f017e027f230041206b2202240041dad5ca00ad4280808080b00284100122032900002104200241086a200341086a29000037030020022004370300200310354188b8cb00ad4280808080a00184100122032900002104200241106a41086a200341086a29000037030020022004370310200310350240412010332203450d0020032001290000370000200341186a2205200141186a290000370000200341106a2206200141106a290000370000200341086a200141086a290000370000412010332201450d0020012003290000370000200141186a2005290000370000200141106a2006290000370000200141086a2205200341086a2900003700002003103541c00010332203450d002003200229031037001020032002290300370000200341086a200241086a290300370000200341186a200241106a41086a290300370000200042c080808080083702042000200336020020032001290000370020200341286a2005290000370000200341306a200141106a290000370000200341386a200141186a29000037000020011035200241206a24000f0b1045000b9f0303027f017e027f230041206b2202240041dad5ca00ad4280808080b00284100122032900002104200241086a200341086a29000037030020022004370300200310354190eaca00ad4280808080e00084100122032900002104200241106a41086a200341086a29000037030020022004370310200310350240412010332203450d0020032001290000370000200341186a2205200141186a290000370000200341106a2206200141106a290000370000200341086a200141086a290000370000412010332201450d0020012003290000370000200141186a2005290000370000200141106a2006290000370000200141086a2205200341086a2900003700002003103541c00010332203450d002003200229031037001020032002290300370000200341086a200241086a290300370000200341186a200241106a41086a290300370000200042c080808080083702042000200336020020032001290000370020200341286a2005290000370000200341306a200141106a290000370000200341386a200141186a29000037000020011035200241206a24000f0b1045000b9b0c08057f037e057f017e077f017e017f017e230041c0076b220424000240024020000d00200441e0026a2003109c0720043502e80242208620042802e0022200ad841007024020042802e402450d00200010350b200441ed026a200341086a290000370000200441f5026a200341106a290000370000200441fd026a200341186a290000370000200441033a00e402200441073a00e002200420032900003700e50241b0b4cc004100200441e0026a10d4010c010b200441ed026a200341086a290000370000200441f5026a200341106a290000370000200441fd026a200341186a290000370000200441023a00e402200441073a00e002200420032900003700e50241b0b4cc004100200441e0026a10d401200441b8026a2003109c07200441e0026a20042802b802220520042802c00210e30220042802e002210020044190056a200441e0026a41047241ac02109d081a02402000411b470d0020042802bc02450d01200510350c010b200441086a20044190056a41ac02109d081a024020042802bc02450d00200510350b20022802042105200420003602e002200441e0026a410472200441086a41ac02109d081a2004419c056a200136020020044190056a41086a2005360200200441003a009405200441013a009005200441b8026a200441e0026a20044190056a10ac0320044185036a20042903b802503a0000200441ed026a200341086a290000370000200441f5026a200341106a290000370000200441fd026a200341186a290000370000200441043a00e402200441073a00e002200420032900003700e50241b0b4cc004100200441e0026a10d4010b200441e0026a2003109a0720043502e80242208620042802e0022200ad841007024020042802e402450d00200010350b20044190056a41186a2206420037030020044190056a41106a2207420037030020044190056a41086a22084200370300200442003703900541dad5ca00ad4280808080b00284220910012200290000210a2008200041086a2900003703002004200a37039005200010354180eaca00ad4280808080900184220b10012200290000210a200441086a41086a220c200041086a2900003703002004200a3703082000103520072004290308220a370300200441e0026a41086a220d2008290300370300200441e0026a41106a220e200a370300200441e0026a41186a220f200c29030037030020042004290390053703e00220044190056a200441e0026a412010b5022004280290052200410120001b21100240200429029405420020001b2211422088a72212450d0041002101201021004100210502400240034002400240024020032000460d0020002003412010a008450d0020010d01410021010c020b200141016a21010c010b200520016b221320124f0d022006200020014105746b221341186a22142900003703002007201341106a22152900003703002008201341086a22162900003703002004201329000037039005200041086a2217290000210a200041106a22182900002119200041186a221a290000211b201320002900003700002014201b370000201520193700002016200a370000201a2006290300370000201820072903003700002017200829030037000020002004290390053700000b200041206a21002012200541016a2205460d020c000b0b2013201241f485cc001042000b2001417f6a20124f0d00201220016bad422086201142ffffffff0f838421110b200f4200370300200e4200370300200d4200370300200442003703e002200910012200290000210a200d200041086a2900003703002004200a3703e00220001035200b10012200290000210a200c200041086a2900003703002004200a37030820001035200e2004290308220a3703002008200d2903003703002007200a3703002006200c290300370300200420042903e002370390050240024020100d0020044190056aad428080808080048410070c010b200441203602e402200420044190056a3602e00220102011422088a7200441e0026a10c504201142ffffff3f83500d00201010350b02402002410c6a28020041ffffff3f71450d00200228020810350b0240200241186a28020041ffffff3f71450d00200228021410350b200441c0076a24000b9f0303027f017e027f230041206b2202240041dad5ca00ad4280808080b00284100122032900002104200241086a200341086a29000037030020022004370300200310354188b8cb00ad4280808080a00184100122032900002104200241106a41086a200341086a29000037030020022004370310200310350240412010332203450d0020032001290000370000200341186a2205200141186a290000370000200341106a2206200141106a290000370000200341086a200141086a290000370000412010332201450d0020012003290000370000200141186a2005290000370000200141106a2006290000370000200141086a2205200341086a2900003700002003103541c00010332203450d002003200229031037001020032002290300370000200341086a200241086a290300370000200341186a200241106a41086a290300370000200042c080808080083702042000200336020020032001290000370020200341286a2005290000370000200341306a200141106a290000370000200341386a200141186a29000037000020011035200241206a24000f0b1045000b9f0303027f017e027f230041206b2202240041c7d5ca00ad4280808080b00284100122032900002104200241086a200341086a29000037030020022004370300200310354188b8cb00ad4280808080a00184100122032900002104200241106a41086a200341086a29000037030020022004370310200310350240412010332203450d0020032001290000370000200341186a2205200141186a290000370000200341106a2206200141106a290000370000200341086a200141086a290000370000412010332201450d0020012003290000370000200141186a2005290000370000200141106a2006290000370000200141086a2205200341086a2900003700002003103541c00010332203450d002003200229031037001020032002290300370000200341086a200241086a290300370000200341186a200241106a41086a290300370000200042c080808080083702042000200336020020032001290000370020200341286a2005290000370000200341306a200141106a290000370000200341386a200141186a29000037000020011035200241206a24000f0b1045000b9f0303027f017e027f230041206b2202240041c7d5ca00ad4280808080b00284100122032900002104200241086a200341086a29000037030020022004370300200310354190eaca00ad4280808080e00084100122032900002104200241106a41086a200341086a29000037030020022004370310200310350240412010332203450d0020032001290000370000200341186a2205200141186a290000370000200341106a2206200141106a290000370000200341086a200141086a290000370000412010332201450d0020012003290000370000200141186a2005290000370000200141106a2006290000370000200141086a2205200341086a2900003700002003103541c00010332203450d002003200229031037001020032002290300370000200341086a200241086a290300370000200341186a200241106a41086a290300370000200042c080808080083702042000200336020020032001290000370020200341286a2005290000370000200341306a200141106a290000370000200341386a200141186a29000037000020011035200241206a24000f0b1045000b9b0c08057f037e057f017e077f017e017f017e230041c0076b220424000240024020000d00200441e0026a200310a00720043502e80242208620042802e0022200ad841007024020042802e402450d00200010350b200441f5026a200341106a290000370000200441fd026a200341186a290000370000200441083a00e002200441ed026a200341086a290000370000200441033a00e402200420032900003700e50241b0b4cc004100200441e0026a10d4010c010b200441f5026a200341106a290000370000200441fd026a200341186a290000370000200441083a00e002200441ed026a200341086a290000370000200441023a00e402200420032900003700e50241b0b4cc004100200441e0026a10d401200441b8026a200310a007200441e0026a20042802b802220520042802c00210e30220042802e002210020044190056a200441e0026a41047241ac02109d081a02402000411b470d0020042802bc02450d01200510350c010b200441086a20044190056a41ac02109d081a024020042802bc02450d00200510350b20022802042105200420003602e002200441e0026a410472200441086a41ac02109d081a2004419c056a200136020020044190056a41086a2005360200200441003a009405200441023a009005200441b8026a200441e0026a20044190056a10ac0320044185036a20042903b802503a0000200441ed026a200341086a290000370000200441f5026a200341106a290000370000200441fd026a200341186a290000370000200441043a00e402200441083a00e002200420032900003700e50241b0b4cc004100200441e0026a10d4010b200441e0026a2003109e0720043502e80242208620042802e0022200ad841007024020042802e402450d00200010350b20044190056a41186a2206420037030020044190056a41106a2207420037030020044190056a41086a22084200370300200442003703900541c7d5ca00ad4280808080b00284220910012200290000210a2008200041086a2900003703002004200a37039005200010354180eaca00ad4280808080900184220b10012200290000210a200441086a41086a220c200041086a2900003703002004200a3703082000103520072004290308220a370300200441e0026a41086a220d2008290300370300200441e0026a41106a220e200a370300200441e0026a41186a220f200c29030037030020042004290390053703e00220044190056a200441e0026a412010b5022004280290052200410120001b21100240200429029405420020001b2211422088a72212450d0041002101201021004100210502400240034002400240024020032000460d0020002003412010a008450d0020010d01410021010c020b200141016a21010c010b200520016b221320124f0d022006200020014105746b221341186a22142900003703002007201341106a22152900003703002008201341086a22162900003703002004201329000037039005200041086a2217290000210a200041106a22182900002119200041186a221a290000211b201320002900003700002014201b370000201520193700002016200a370000201a2006290300370000201820072903003700002017200829030037000020002004290390053700000b200041206a21002012200541016a2205460d020c000b0b2013201241f485cc001042000b2001417f6a20124f0d00201220016bad422086201142ffffffff0f838421110b200f4200370300200e4200370300200d4200370300200442003703e002200910012200290000210a200d200041086a2900003703002004200a3703e00220001035200b10012200290000210a200c200041086a2900003703002004200a37030820001035200e2004290308220a3703002008200d2903003703002007200a3703002006200c290300370300200420042903e002370390050240024020100d0020044190056aad428080808080048410070c010b200441203602e402200420044190056a3602e00220102011422088a7200441e0026a10c504201142ffffff3f83500d00201010350b02402002410c6a28020041ffffff3f71450d00200228020810350b0240200241186a28020041ffffff3f71450d00200228021410350b200441c0076a24000b9f0303027f017e027f230041206b2202240041c7d5ca00ad4280808080b00284100122032900002104200241086a200341086a29000037030020022004370300200310354188b8cb00ad4280808080a00184100122032900002104200241106a41086a200341086a29000037030020022004370310200310350240412010332203450d0020032001290000370000200341186a2205200141186a290000370000200341106a2206200141106a290000370000200341086a200141086a290000370000412010332201450d0020012003290000370000200141186a2005290000370000200141106a2006290000370000200141086a2205200341086a2900003700002003103541c00010332203450d002003200229031037001020032002290300370000200341086a200241086a290300370000200341186a200241106a41086a290300370000200042c080808080083702042000200336020020032001290000370020200341286a2005290000370000200341306a200141106a290000370000200341386a200141186a29000037000020011035200241206a24000f0b1045000b130020004107360204200041accdcb003602000bcc04020d7f017e230041c0006b22032400200128020822044104742105200128020421062001280200220721010240024002402004450d00200341306a410172210841002104200341306a41026a2109200341206a410172220a41076a210b03402009200720046a220141036a2d00003a00002003200141016a2f00003b0130024020012d0000220c41ac01470d00200141106a21010c020b2003410c6a41026a20092d0000220d3a0000200320032f0130220e3b010c200141046a280200210f200141086a29030021102008200e3b0000200841026a200d3a00002003200c3a0030200320103703382003200f360234200341206a200341306a200210a3072003200a2900003703102003200b290000370017024020032d0020220c411f470d002005200441106a2204470d010c030b0b2000200c3a000020002003290310370001200041086a20032900173700000240200541706a2004460d00200141146a2101200520046b41706a2104034002402001417c6a2d00004109470d0002402001280200220928020441ffffffff0371450d0020092802001035200128020021090b200910350b200141106a2101200441706a22040d000b0b200641ffffffff0071450d02200710350c020b200720056a22092001460d000340200141106a2104024020012d00004109470d000240200141046a2208280200220128020441ffffffff0371450d0020012802001035200828020021010b200110350b2004210120092004470d000b0b0240200641ffffffff0071450d00200710350b2000411f3a00000b200341c0006a24000b9bee0202097f017e230041106b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000eac01000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa01ab01000b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dad01200441017422062005200620054b1b22064100480dad010240024020040d00024020060d00410121050c020b2006103322050d010cb9010b2002280204210520042006460d0020052004200610372205450db8010b20022005360204200241086a20063602002002410c6a28020021040b200520046a41003a00002002410c6a200441016a3602000cab010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dac01200441017422062005200620054b1b22064100480dac010240024020040d00024020060d00410121050c020b200610332205450db8010c010b2002280204210520042006460d0020052004200610372205450db7010b20022005360204200241086a20063602002002410c6a28020021040b200520046a41013a00002002410c6a200441016a3602000caa010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490dab01200441017422082005200820054b1b22084100480dab010240024020040d00024020080d00410121050c020b200810332205450db7010c010b2006280200210520042008460d0020052004200810372205450db6010b20022005360204200241086a20083602002002410c6a28020021040b200520046a41023a00002002410c6a200441016a220436020002400240200241086a2802002004460d00200628020021050c010b200441016a22052004490dab01200441017422082005200820054b1b22084100480dab010240024020040d00024020080d00410121050c020b200810332205450db7010c010b2006280200210520042008460d0020052004200810372205450db6010b20022005360204200241086a20083602002002410c6a28020021040b200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00002002410c6a200441016a3602000ca9010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490daa01200441017422082005200820054b1b22084100480daa010240024020040d00024020080d00410121050c020b200810332205450db6010c010b2006280200210520042008460d0020052004200810372205450db5010b20022005360204200241086a20083602002002410c6a28020021040b200520046a41033a00002002410c6a200441016a220436020002400240200241086a2802002004460d00200628020021050c010b200441016a22052004490daa01200441017422082005200820054b1b22084100480daa010240024020040d00024020080d00410121050c020b200810332205450db6010c010b2006280200210520042008460d0020052004200810372205450db5010b20022005360204200241086a20083602002002410c6a28020021040b200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00002002410c6a200441016a3602000ca8010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490da901200441017422082005200820054b1b22084100480da9010240024020040d00024020080d00410121050c020b200810332205450db5010c010b2006280200210520042008460d0020052004200810372205450db4010b20022005360204200241086a20083602002002410c6a28020021040b200520046a41043a00002002410c6a200441016a220436020002400240200241086a2802002004460d00200628020021050c010b200441016a22052004490da901200441017422082005200820054b1b22084100480da9010240024020040d00024020080d00410121050c020b200810332205450db5010c010b2006280200210520042008460d0020052004200810372205450db4010b20022005360204200241086a20083602002002410c6a28020021040b200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00002002410c6a200441016a3602000ca7010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da801200441017422062005200620054b1b22064100480da8010240024020040d00024020060d00410121050c020b200610332205450db4010c010b2002280204210520042006460d0020052004200610372205450db3010b20022005360204200241086a20063602002002410c6a28020021040b200520046a41053a00002002410c6a200441016a3602000ca6010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da701200441017422062005200620054b1b22064100480da7010240024020040d00024020060d00410121050c020b200610332205450db3010c010b2002280204210520042006460d0020052004200610372205450db2010b20022005360204200241086a20063602002002410c6a28020021040b200520046a410b3a00002002410c6a200441016a3602000ca5010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490da601200441017422072006200720064b1b22074100480da6010240024020040d00024020070d00410121060c020b200710332206450db2010c010b2009280200210620042007460d0020062004200710372206450db1010b20022006360204200241086a20073602002002410c6a28020021040b200620046a410c3a00002002410c6a2208200441016a2204360200200241086a210a034002400240200a2802002004460d00200928020021060c010b200441016a22062004490da701200441017422072006200720064b1b22074100480da7010240024020040d00024020070d00410121060c020b200710332206450db3010c010b2009280200210620042007460d0020062004200710372206450db2010b20022006360204200a2007360200200828020021040b200620046a200541807f72200541ff0071200541077622061b3a00002008200441016a22043602002006210520060d000ca5010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490da501200441017422072006200720064b1b22074100480da5010240024020040d00024020070d00410121060c020b200710332206450db1010c010b2009280200210620042007460d0020062004200710372206450db0010b20022006360204200241086a20073602002002410c6a28020021040b200620046a410d3a00002002410c6a2208200441016a2204360200200241086a210a034002400240200a2802002004460d00200928020021060c010b200441016a22062004490da601200441017422072006200720064b1b22074100480da6010240024020040d00024020070d00410121060c020b200710332206450db2010c010b2009280200210620042007460d0020062004200710372206450db1010b20022006360204200a2007360200200828020021040b200620046a200541807f72200541ff0071200541077622061b3a00002008200441016a22043602002006210520060d000ca4010b0b200241046a210902400240200241086a2802002002410c6a2802002204460d00200928020021050c010b200441016a22052004490da401200441017422062005200620054b1b22064100480da4010240024020040d00024020060d00410121050c020b200610332205450db0010c010b2009280200210520042006460d0020052004200610372205450daf010b20022005360204200241086a20063602002002410c6a28020021040b200520046a410e3a00002002410c6a2208200441016a360200200320012802042204280204220520042802002204200420054102746a200210a4072003210420032d0000411f470dab012008280200210420012802042802082105200241086a210a034002400240200a2802002004460d00200928020021060c010b200441016a22062004490da501200441017422072006200720064b1b22074100480da5010240024020040d00024020070d00410121060c020b200710332206450db1010c010b2009280200210620042007460d0020062004200710372206450db0010b20022006360204200a2007360200200828020021040b200620046a200541807f72200541ff0071200541077622061b3a00002008200441016a22043602002006210520060d000ca3010b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da301200441017422062005200620054b1b22064100480da3010240024020040d00024020060d00410121050c020b200610332205450daf010c010b2002280204210520042006460d0020052004200610372205450dae010b20022005360204200241086a20063602002002410c6a28020021040b200520046a410f3a00002002410c6a200441016a3602000ca1010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490da201200441017422072006200720064b1b22074100480da2010240024020040d00024020070d00410121060c020b200710332206450dae010c010b2009280200210620042007460d0020062004200710372206450dad010b20022006360204200241086a20073602002002410c6a28020021040b200620046a41103a00002002410c6a2208200441016a2204360200200241086a210a034002400240200a2802002004460d00200928020021060c010b200441016a22062004490da301200441017422072006200720064b1b22074100480da3010240024020040d00024020070d00410121060c020b200710332206450daf010c010b2009280200210620042007460d0020062004200710372206450dae010b20022006360204200a2007360200200828020021040b200620046a200541807f72200541ff0071200541077622061b3a00002008200441016a22043602002006210520060d000ca1010b0b200241046a2109200141046a280200210520012d0001210b02400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490da101200441017422072006200720064b1b22074100480da1010240024020040d00024020070d00410121060c020b200710332206450dad010c010b2009280200210620042007460d0020062004200710372206450dac010b20022006360204200241086a20073602002002410c6a28020021040b200620046a41113a00002002410c6a2208200441016a2204360200200241086a210a034002400240200a2802002004460d00200928020021060c010b200441016a22062004490da201200441017422072006200720064b1b22074100480da2010240024020040d00024020070d00410121060c020b200710332206450dae010c010b2009280200210620042007460d0020062004200710372206450dad010b20022006360204200a2007360200200828020021040b200620046a200541807f72200541ff0071200541077622061b3a00002008200441016a22043602002006210520060d000b02400240200241086a2802002004460d00200928020021050c010b200441016a22052004490da101200441017422062005200620054b1b22064100480da1010240024020040d00024020060d00410121050c020b200610332205450dad010c010b2009280200210520042006460d0020052004200610372205450dac010b20022005360204200241086a20063602002002410c6a28020021040b200520046a200b3a00002002410c6a200441016a3602000c9f010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da001200441017422062005200620054b1b22064100480da0010240024020040d00024020060d00410121050c020b200610332205450dac010c010b2002280204210520042006460d0020052004200610372205450dab010b20022005360204200241086a20063602002002410c6a28020021040b200520046a411a3a00002002410c6a200441016a3602000c9e010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9f01200441017422062005200620054b1b22064100480d9f010240024020040d00024020060d00410121050c020b200610332205450dab010c010b2002280204210520042006460d0020052004200610372205450daa010b20022005360204200241086a20063602002002410c6a28020021040b200520046a411b3a00002002410c6a200441016a3602000c9d010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9e01200441017422072006200720064b1b22074100480d9e010240024020040d00024020070d00410121060c020b200710332206450daa010c010b2009280200210620042007460d0020062004200710372206450da9010b20022006360204200241086a20073602002002410c6a28020021040b200620046a41203a00002002410c6a2208200441016a2204360200200241086a210a034002400240200a2802002004460d00200928020021060c010b200441016a22062004490d9f01200441017422072006200720064b1b22074100480d9f010240024020040d00024020070d00410121060c020b200710332206450dab010c010b2009280200210620042007460d0020062004200710372206450daa010b20022006360204200a2007360200200828020021040b200620046a200541807f72200541ff0071200541077622061b3a00002008200441016a22043602002006210520060d000c9d010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9d01200441017422072006200720064b1b22074100480d9d010240024020040d00024020070d00410121060c020b200710332206450da9010c010b2009280200210620042007460d0020062004200710372206450da8010b20022006360204200241086a20073602002002410c6a28020021040b200620046a41213a00002002410c6a2208200441016a2204360200200241086a210a034002400240200a2802002004460d00200928020021060c010b200441016a22062004490d9e01200441017422072006200720064b1b22074100480d9e010240024020040d00024020070d00410121060c020b200710332206450daa010c010b2009280200210620042007460d0020062004200710372206450da9010b20022006360204200a2007360200200828020021040b200620046a200541807f72200541ff0071200541077622061b3a00002008200441016a22043602002006210520060d000c9c010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9c01200441017422072006200720064b1b22074100480d9c010240024020040d00024020070d00410121060c020b200710332206450da8010c010b2009280200210620042007460d0020062004200710372206450da7010b20022006360204200241086a20073602002002410c6a28020021040b200620046a41223a00002002410c6a2208200441016a2204360200200241086a210a034002400240200a2802002004460d00200928020021060c010b200441016a22062004490d9d01200441017422072006200720064b1b22074100480d9d010240024020040d00024020070d00410121060c020b200710332206450da9010c010b2009280200210620042007460d0020062004200710372206450da8010b20022006360204200a2007360200200828020021040b200620046a200541807f72200541ff0071200541077622061b3a00002008200441016a22043602002006210520060d000c9b010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9b01200441017422072006200720064b1b22074100480d9b010240024020040d00024020070d00410121060c020b200710332206450da7010c010b2009280200210620042007460d0020062004200710372206450da6010b20022006360204200241086a20073602002002410c6a28020021040b200620046a41233a00002002410c6a2208200441016a2204360200200241086a210a034002400240200a2802002004460d00200928020021060c010b200441016a22062004490d9c01200441017422072006200720064b1b22074100480d9c010240024020040d00024020070d00410121060c020b200710332206450da8010c010b2009280200210620042007460d0020062004200710372206450da7010b20022006360204200a2007360200200828020021040b200620046a200541807f72200541ff0071200541077622061b3a00002008200441016a22043602002006210520060d000c9a010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9a01200441017422072006200720064b1b22074100480d9a010240024020040d00024020070d00410121060c020b200710332206450da6010c010b2009280200210620042007460d0020062004200710372206450da5010b20022006360204200241086a20073602002002410c6a28020021040b200620046a41243a00002002410c6a2208200441016a2204360200200241086a210a034002400240200a2802002004460d00200928020021060c010b200441016a22062004490d9b01200441017422072006200720064b1b22074100480d9b010240024020040d00024020070d00410121060c020b200710332206450da7010c010b2009280200210620042007460d0020062004200710372206450da6010b20022006360204200a2007360200200828020021040b200620046a200541807f72200541ff0071200541077622061b3a00002008200441016a22043602002006210520060d000c99010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9901200441017422082007200820074b1b22084100480d99010240024020040d00024020080d00410121070c020b200810332207450da5010c010b200a280200210720042008460d0020072004200810372207450da4010b20022007360204200241086a20083602002002410c6a28020021040b200720046a41283a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d9a01200441017422082007200820074b1b22084100480d9a010240024020040d00024020080d00410121070c020b200810332207450da6010c010b200a280200210720042008460d0020072004200810372207450da5010b20022007360204200b2008360200200928020021040b200720046a200541807f72200541ff0071200541077622071b3a00002009200441016a22043602002007210520070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021050c010b200441016a22052004490d9a01200441017422072005200720054b1b22074100480d9a010240024020040d00024020070d00410121050c020b200710332205450da6010c010b200a280200210520042007460d0020052004200710372205450da5010b2002200536020420082007360200200928020021040b200520046a200641807f72200641ff0071200641077622051b3a00002009200441016a22043602002005210620050d000c98010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9801200441017422082007200820074b1b22084100480d98010240024020040d00024020080d00410121070c020b200810332207450da4010c010b200a280200210720042008460d0020072004200810372207450da3010b20022007360204200241086a20083602002002410c6a28020021040b200720046a41293a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d9901200441017422082007200820074b1b22084100480d99010240024020040d00024020080d00410121070c020b200810332207450da5010c010b200a280200210720042008460d0020072004200810372207450da4010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d9901200441017422072006200720064b1b22074100480d99010240024020040d00024020070d00410121060c020b200710332206450da5010c010b200a280200210620042007460d0020062004200710372206450da4010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c97010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9701200441017422082007200820074b1b22084100480d97010240024020040d00024020080d00410121070c020b200810332207450da3010c010b200a280200210720042008460d0020072004200810372207450da2010b20022007360204200241086a20083602002002410c6a28020021040b200720046a412a3a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d9801200441017422082007200820074b1b22084100480d98010240024020040d00024020080d00410121070c020b200810332207450da4010c010b200a280200210720042008460d0020072004200810372207450da3010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d9801200441017422072006200720064b1b22074100480d98010240024020040d00024020070d00410121060c020b200710332206450da4010c010b200a280200210620042007460d0020062004200710372206450da3010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c96010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9601200441017422082007200820074b1b22084100480d96010240024020040d00024020080d00410121070c020b200810332207450da2010c010b200a280200210720042008460d0020072004200810372207450da1010b20022007360204200241086a20083602002002410c6a28020021040b200720046a412b3a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d9701200441017422082007200820074b1b22084100480d97010240024020040d00024020080d00410121070c020b200810332207450da3010c010b200a280200210720042008460d0020072004200810372207450da2010b20022007360204200b2008360200200928020021040b200720046a200541807f72200541ff0071200541077622071b3a00002009200441016a22043602002007210520070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021050c010b200441016a22052004490d9701200441017422072005200720054b1b22074100480d97010240024020040d00024020070d00410121050c020b200710332205450da3010c010b200a280200210520042007460d0020052004200710372205450da2010b2002200536020420082007360200200928020021040b200520046a200641807f72200641ff0071200641077622051b3a00002009200441016a22043602002005210620050d000c95010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9501200441017422082007200820074b1b22084100480d95010240024020040d00024020080d00410121070c020b200810332207450da1010c010b200a280200210720042008460d0020072004200810372207450da0010b20022007360204200241086a20083602002002410c6a28020021040b200720046a412c3a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d9601200441017422082007200820074b1b22084100480d96010240024020040d00024020080d00410121070c020b200810332207450da2010c010b200a280200210720042008460d0020072004200810372207450da1010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d9601200441017422072006200720064b1b22074100480d96010240024020040d00024020070d00410121060c020b200710332206450da2010c010b200a280200210620042007460d0020062004200710372206450da1010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c94010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9501200441017422082007200820074b1b22084100480d95010240024020040d00024020080d00410121070c020b200810332207450da0010c010b200a280200210720042008460d0020072004200810372207450d9f010b20022007360204200241086a20083602002002410c6a28020021040b200720046a412d3a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d9601200441017422082007200820074b1b22084100480d96010240024020040d00024020080d00410121070c020b2008103322070d010c9e010b200a280200210720042008460d0020072004200810372207450d9c010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d9601200441017422072006200720064b1b22074100480d96010240024020040d00024020070d00410121060c020b2007103322060d010c9e010b200a280200210620042007460d0020062004200710372206450d9c010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c93010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9401200441017422082007200820074b1b22084100480d94010240024020040d00024020080d00410121070c020b2008103322070d010c9c010b200a280200210720042008460d0020072004200810372207450d9a010b20022007360204200241086a20083602002002410c6a28020021040b200720046a412e3a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d9501200441017422082007200820074b1b22084100480d95010240024020040d00024020080d00410121070c020b2008103322070d010c9d010b200a280200210720042008460d0020072004200810372207450d9b010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d9501200441017422072006200720064b1b22074100480d95010240024020040d00024020070d00410121060c020b2007103322060d010c9d010b200a280200210620042007460d0020062004200710372206450d9b010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c92010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9301200441017422082007200820074b1b22084100480d93010240024020040d00024020080d00410121070c020b2008103322070d010c9b010b200a280200210720042008460d0020072004200810372207450d99010b20022007360204200241086a20083602002002410c6a28020021040b200720046a412f3a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d9401200441017422082007200820074b1b22084100480d94010240024020040d00024020080d00410121070c020b2008103322070d010c9c010b200a280200210720042008460d0020072004200810372207450d9a010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d9401200441017422072006200720064b1b22074100480d94010240024020040d00024020070d00410121060c020b2007103322060d010c9c010b200a280200210620042007460d0020062004200710372206450d9a010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c91010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9201200441017422082007200820074b1b22084100480d92010240024020040d00024020080d00410121070c020b2008103322070d010c9a010b200a280200210720042008460d0020072004200810372207450d98010b20022007360204200241086a20083602002002410c6a28020021040b200720046a41303a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d9301200441017422082007200820074b1b22084100480d93010240024020040d00024020080d00410121070c020b2008103322070d010c9b010b200a280200210720042008460d0020072004200810372207450d99010b20022007360204200b2008360200200928020021040b200720046a200541807f72200541ff0071200541077622071b3a00002009200441016a22043602002007210520070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021050c010b200441016a22052004490d9301200441017422072005200720054b1b22074100480d93010240024020040d00024020070d00410121050c020b2007103322050d010c9b010b200a280200210520042007460d0020052004200710372205450d99010b2002200536020420082007360200200928020021040b200520046a200641807f72200641ff0071200641077622051b3a00002009200441016a22043602002005210620050d000c90010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9101200441017422082007200820074b1b22084100480d91010240024020040d00024020080d00410121070c020b2008103322070d010c99010b200a280200210720042008460d0020072004200810372207450d97010b20022007360204200241086a20083602002002410c6a28020021040b200720046a41313a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d9201200441017422082007200820074b1b22084100480d92010240024020040d00024020080d00410121070c020b2008103322070d010c9a010b200a280200210720042008460d0020072004200810372207450d98010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d9201200441017422072006200720064b1b22074100480d92010240024020040d00024020070d00410121060c020b2007103322060d010c9a010b200a280200210620042007460d0020062004200710372206450d98010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c8f010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9001200441017422082007200820074b1b22084100480d90010240024020040d00024020080d00410121070c020b2008103322070d010c98010b200a280200210720042008460d0020072004200810372207450d96010b20022007360204200241086a20083602002002410c6a28020021040b200720046a41323a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d9101200441017422082007200820074b1b22084100480d91010240024020040d00024020080d00410121070c020b2008103322070d010c99010b200a280200210720042008460d0020072004200810372207450d97010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d9101200441017422072006200720064b1b22074100480d91010240024020040d00024020070d00410121060c020b2007103322060d010c99010b200a280200210620042007460d0020062004200710372206450d97010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c8e010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8f01200441017422082007200820074b1b22084100480d8f010240024020040d00024020080d00410121070c020b2008103322070d010c97010b200a280200210720042008460d0020072004200810372207450d95010b20022007360204200241086a20083602002002410c6a28020021040b200720046a41333a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d9001200441017422082007200820074b1b22084100480d90010240024020040d00024020080d00410121070c020b2008103322070d010c98010b200a280200210720042008460d0020072004200810372207450d96010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d9001200441017422072006200720064b1b22074100480d90010240024020040d00024020070d00410121060c020b2007103322060d010c98010b200a280200210620042007460d0020062004200710372206450d96010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c8d010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8e01200441017422082007200820074b1b22084100480d8e010240024020040d00024020080d00410121070c020b2008103322070d010c96010b200a280200210720042008460d0020072004200810372207450d94010b20022007360204200241086a20083602002002410c6a28020021040b200720046a41343a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d8f01200441017422082007200820074b1b22084100480d8f010240024020040d00024020080d00410121070c020b2008103322070d010c97010b200a280200210720042008460d0020072004200810372207450d95010b20022007360204200b2008360200200928020021040b200720046a200541807f72200541ff0071200541077622071b3a00002009200441016a22043602002007210520070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021050c010b200441016a22052004490d8f01200441017422072005200720054b1b22074100480d8f010240024020040d00024020070d00410121050c020b2007103322050d010c97010b200a280200210520042007460d0020052004200710372205450d95010b2002200536020420082007360200200928020021040b200520046a200641807f72200641ff0071200641077622051b3a00002009200441016a22043602002005210620050d000c8c010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8d01200441017422082007200820074b1b22084100480d8d010240024020040d00024020080d00410121070c020b2008103322070d010c95010b200a280200210720042008460d0020072004200810372207450d93010b20022007360204200241086a20083602002002410c6a28020021040b200720046a41353a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d8e01200441017422082007200820074b1b22084100480d8e010240024020040d00024020080d00410121070c020b2008103322070d010c96010b200a280200210720042008460d0020072004200810372207450d94010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d8e01200441017422072006200720064b1b22074100480d8e010240024020040d00024020070d00410121060c020b2007103322060d010c96010b200a280200210620042007460d0020062004200710372206450d94010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c8b010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8c01200441017422082007200820074b1b22084100480d8c010240024020040d00024020080d00410121070c020b2008103322070d010c94010b200a280200210720042008460d0020072004200810372207450d92010b20022007360204200241086a20083602002002410c6a28020021040b200720046a41363a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d8d01200441017422082007200820074b1b22084100480d8d010240024020040d00024020080d00410121070c020b2008103322070d010c95010b200a280200210720042008460d0020072004200810372207450d93010b20022007360204200b2008360200200928020021040b200720046a200541807f72200541ff0071200541077622071b3a00002009200441016a22043602002007210520070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021050c010b200441016a22052004490d8d01200441017422072005200720054b1b22074100480d8d010240024020040d00024020070d00410121050c020b2007103322050d010c95010b200a280200210520042007460d0020052004200710372205450d93010b2002200536020420082007360200200928020021040b200520046a200641807f72200641ff0071200641077622051b3a00002009200441016a22043602002005210620050d000c8a010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8b01200441017422082007200820074b1b22084100480d8b010240024020040d00024020080d00410121070c020b2008103322070d010c93010b200a280200210720042008460d0020072004200810372207450d91010b20022007360204200241086a20083602002002410c6a28020021040b200720046a41373a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d8c01200441017422082007200820074b1b22084100480d8c010240024020040d00024020080d00410121070c020b2008103322070d010c94010b200a280200210720042008460d0020072004200810372207450d92010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d8c01200441017422072006200720064b1b22074100480d8c010240024020040d00024020070d00410121060c020b2007103322060d010c94010b200a280200210620042007460d0020062004200710372206450d92010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c89010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8a01200441017422082007200820074b1b22084100480d8a010240024020040d00024020080d00410121070c020b2008103322070d010c92010b200a280200210720042008460d0020072004200810372207450d90010b20022007360204200241086a20083602002002410c6a28020021040b200720046a41383a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d8b01200441017422082007200820074b1b22084100480d8b010240024020040d00024020080d00410121070c020b2008103322070d010c93010b200a280200210720042008460d0020072004200810372207450d91010b20022007360204200b2008360200200928020021040b200720046a200541807f72200541ff0071200541077622071b3a00002009200441016a22043602002007210520070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021050c010b200441016a22052004490d8b01200441017422072005200720054b1b22074100480d8b010240024020040d00024020070d00410121050c020b2007103322050d010c93010b200a280200210520042007460d0020052004200710372205450d91010b2002200536020420082007360200200928020021040b200520046a200641807f72200641ff0071200641077622051b3a00002009200441016a22043602002005210620050d000c88010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8901200441017422082007200820074b1b22084100480d89010240024020040d00024020080d00410121070c020b2008103322070d010c91010b200a280200210720042008460d0020072004200810372207450d8f010b20022007360204200241086a20083602002002410c6a28020021040b200720046a41393a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d8a01200441017422082007200820074b1b22084100480d8a010240024020040d00024020080d00410121070c020b2008103322070d010c92010b200a280200210720042008460d0020072004200810372207450d90010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d8a01200441017422072006200720064b1b22074100480d8a010240024020040d00024020070d00410121060c020b2007103322060d010c92010b200a280200210620042007460d0020062004200710372206450d90010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c87010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8801200441017422082007200820074b1b22084100480d88010240024020040d00024020080d00410121070c020b2008103322070d010c90010b200a280200210720042008460d0020072004200810372207450d8e010b20022007360204200241086a20083602002002410c6a28020021040b200720046a413a3a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d8901200441017422082007200820074b1b22084100480d89010240024020040d00024020080d00410121070c020b2008103322070d010c91010b200a280200210720042008460d0020072004200810372207450d8f010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d8901200441017422072006200720064b1b22074100480d89010240024020040d00024020070d00410121060c020b2007103322060d010c91010b200a280200210620042007460d0020062004200710372206450d8f010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c86010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8701200441017422082007200820074b1b22084100480d87010240024020040d00024020080d00410121070c020b2008103322070d010c8f010b200a280200210720042008460d0020072004200810372207450d8d010b20022007360204200241086a20083602002002410c6a28020021040b200720046a413b3a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d8801200441017422082007200820074b1b22084100480d88010240024020040d00024020080d00410121070c020b2008103322070d010c90010b200a280200210720042008460d0020072004200810372207450d8e010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d8801200441017422072006200720064b1b22074100480d88010240024020040d00024020070d00410121060c020b2007103322060d010c90010b200a280200210620042007460d0020062004200710372206450d8e010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c85010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8601200441017422082007200820074b1b22084100480d86010240024020040d00024020080d00410121070c020b2008103322070d010c8e010b200a280200210720042008460d0020072004200810372207450d8c010b20022007360204200241086a20083602002002410c6a28020021040b200720046a413c3a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d8701200441017422082007200820074b1b22084100480d87010240024020040d00024020080d00410121070c020b2008103322070d010c8f010b200a280200210720042008460d0020072004200810372207450d8d010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d8701200441017422072006200720064b1b22074100480d87010240024020040d00024020070d00410121060c020b2007103322060d010c8f010b200a280200210620042007460d0020062004200710372206450d8d010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c84010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8501200441017422082007200820074b1b22084100480d85010240024020040d00024020080d00410121070c020b2008103322070d010c8d010b200a280200210720042008460d0020072004200810372207450d8b010b20022007360204200241086a20083602002002410c6a28020021040b200720046a413d3a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d8601200441017422082007200820074b1b22084100480d86010240024020040d00024020080d00410121070c020b2008103322070d010c8e010b200a280200210720042008460d0020072004200810372207450d8c010b20022007360204200b2008360200200928020021040b200720046a200541807f72200541ff0071200541077622071b3a00002009200441016a22043602002007210520070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021050c010b200441016a22052004490d8601200441017422072005200720054b1b22074100480d86010240024020040d00024020070d00410121050c020b2007103322050d010c8e010b200a280200210520042007460d0020052004200710372205450d8c010b2002200536020420082007360200200928020021040b200520046a200641807f72200641ff0071200641077622051b3a00002009200441016a22043602002005210620050d000c83010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8401200441017422082007200820074b1b22084100480d84010240024020040d00024020080d00410121070c020b2008103322070d010c8c010b200a280200210720042008460d0020072004200810372207450d8a010b20022007360204200241086a20083602002002410c6a28020021040b200720046a413e3a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d8501200441017422082007200820074b1b22084100480d85010240024020040d00024020080d00410121070c020b2008103322070d010c8d010b200a280200210720042008460d0020072004200810372207450d8b010b20022007360204200b2008360200200928020021040b200720046a200541807f72200541ff0071200541077622071b3a00002009200441016a22043602002007210520070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021050c010b200441016a22052004490d8501200441017422072005200720054b1b22074100480d85010240024020040d00024020070d00410121050c020b2007103322050d010c8d010b200a280200210520042007460d0020052004200710372205450d8b010b2002200536020420082007360200200928020021040b200520046a200641807f72200641ff0071200641077622051b3a00002009200441016a22043602002005210620050d000c82010b0b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d8301200441017422082005200820054b1b22084100480d83010240024020040d00024020080d00410121050c020b2008103322050d010c8b010b2006280200210520042008460d0020052004200810372205450d89010b20022005360204200241086a20083602002002410c6a28020021040b200520046a413f3a00002002410c6a200441016a220436020002400240200241086a2802002004460d00200628020021050c010b200441016a22052004490d8301200441017422082005200820054b1b22084100480d83010240024020040d00024020080d00410121050c020b2008103322050d010c8b010b2006280200210520042008460d0020052004200810372205450d89010b20022005360204200241086a20083602002002410c6a28020021040b200520046a20073a00002002410c6a200441016a3602000c80010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d8201200441017422082005200820054b1b22084100480d82010240024020040d00024020080d00410121050c020b2008103322050d010c8a010b2006280200210520042008460d0020052004200810372205450d88010b20022005360204200241086a20083602002002410c6a28020021040b200520046a41c0003a00002002410c6a200441016a220436020002400240200241086a2802002004460d00200628020021050c010b200441016a22052004490d8301200441017422082005200820054b1b22084100480d83010240024020040d00024020080d00410121050c020b2008103322050d010c8a010b2006280200210520042008460d0020052004200810372205450d88010b20022005360204200241086a20083602002002410c6a28020021040b200520046a20073a00002002410c6a200441016a3602000c7f0b200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8201200441017422072005200720054b1b22074100480d82010240024020040d00024020070d00410121050c020b2007103322050d010c89010b2002280204210520042007460d0020052004200710372205450d84010b20022005360204200241086a20073602002002410c6a28020021040b200520046a41c1003a00002002410c6a200441016a36020020032006200210a5072003210420032d0000411f470d87010c7e0b200141086a290300210c02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8101200441017422062005200620054b1b22064100480d81010240024020040d00024020060d00410121050c020b2006103322050d010c88010b2002280204210520042006460d0020052004200610372205450d83010b20022005360204200241086a20063602002002410c6a28020021040b200520046a41c2003a00002002410c6a200441016a3602002003200c200210a6072003210420032d0000411f470d86010c7d0b200241046a2106200141046a280200210802400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d8001200441017422072005200720054b1b22074100480d80010240024020040d00024020070d00410121050c020b2007103322050d010c87010b2006280200210520042007460d0020052004200710372205450d82010b20022005360204200241086a20073602002002410c6a28020021040b200520046a41c3003a00002002410c6a200441016a220436020002400240200241086a280200220720046b4104490d00200628020021050c010b200441046a22052004490d8001200741017422042005200420054b1b22044100480d80010240024020070d00024020040d00410121050c020b2004103322050d010c87010b2006280200210520072004460d0020052007200410372205450d82010b20022005360204200241086a20043602002002410c6a28020021040b200520046a20083600002002410c6a200441046a3602000c7c0b200241046a2106200141086a290300210c02400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d7f200441017422072005200720054b1b22074100480d7f0240024020040d00024020070d00410121050c020b2007103322050d010c86010b2006280200210520042007460d0020052004200710372205450d81010b20022005360204200241086a20073602002002410c6a28020021040b200520046a41c4003a00002002410c6a200441016a220436020002400240200241086a280200220720046b4108490d00200628020021050c010b200441086a22052004490d7f200741017422042005200420054b1b22044100480d7f0240024020070d00024020040d00410121050c020b2004103322050d010c86010b2006280200210520072004460d0020052007200410372205450d81010b20022005360204200241086a20043602002002410c6a28020021040b200520046a200c3700002002410c6a200441086a3602000c7b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7e200441017422062005200620054b1b22064100480d7e0240024020040d00024020060d00410121050c020b2006103322050d010c85010b2002280204210520042006460d0020052004200610372205450d80010b20022005360204200241086a20063602002002410c6a28020021040b200520046a41c5003a00002002410c6a200441016a3602000c7a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7d200441017422062005200620054b1b22064100480d7d0240024020040d00024020060d00410121050c020b2006103322050d010c84010b2002280204210520042006460d0020052004200610372205450d7f0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41c6003a00002002410c6a200441016a3602000c790b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7c200441017422062005200620054b1b22064100480d7c0240024020040d00024020060d00410121050c020b2006103322050d010c83010b2002280204210520042006460d0020052004200610372205450d7e0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41c7003a00002002410c6a200441016a3602000c780b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7b200441017422062005200620054b1b22064100480d7b0240024020040d00024020060d00410121050c020b2006103322050d010c82010b2002280204210520042006460d0020052004200610372205450d7d0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41c8003a00002002410c6a200441016a3602000c770b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7a200441017422062005200620054b1b22064100480d7a0240024020040d00024020060d00410121050c020b2006103322050d010c81010b2002280204210520042006460d0020052004200610372205450d7c0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41c9003a00002002410c6a200441016a3602000c760b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d79200441017422062005200620054b1b22064100480d790240024020040d00024020060d00410121050c020b2006103322050d010c80010b2002280204210520042006460d0020052004200610372205450d7b0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ca003a00002002410c6a200441016a3602000c750b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d78200441017422062005200620054b1b22064100480d780240024020040d00024020060d00410121050c020b2006103322050d010c7f0b2002280204210520042006460d0020052004200610372205450d7a0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41cb003a00002002410c6a200441016a3602000c740b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d77200441017422062005200620054b1b22064100480d770240024020040d00024020060d00410121050c020b2006103322050d010c7e0b2002280204210520042006460d0020052004200610372205450d790b20022005360204200241086a20063602002002410c6a28020021040b200520046a41cc003a00002002410c6a200441016a3602000c730b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d76200441017422062005200620054b1b22064100480d760240024020040d00024020060d00410121050c020b2006103322050d010c7d0b2002280204210520042006460d0020052004200610372205450d780b20022005360204200241086a20063602002002410c6a28020021040b200520046a41cd003a00002002410c6a200441016a3602000c720b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d75200441017422062005200620054b1b22064100480d750240024020040d00024020060d00410121050c020b2006103322050d010c7c0b2002280204210520042006460d0020052004200610372205450d770b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ce003a00002002410c6a200441016a3602000c710b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d74200441017422062005200620054b1b22064100480d740240024020040d00024020060d00410121050c020b2006103322050d010c7b0b2002280204210520042006460d0020052004200610372205450d760b20022005360204200241086a20063602002002410c6a28020021040b200520046a41cf003a00002002410c6a200441016a3602000c700b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d73200441017422062005200620054b1b22064100480d730240024020040d00024020060d00410121050c020b2006103322050d010c7a0b2002280204210520042006460d0020052004200610372205450d750b20022005360204200241086a20063602002002410c6a28020021040b200520046a41d0003a00002002410c6a200441016a3602000c6f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d72200441017422062005200620054b1b22064100480d720240024020040d00024020060d00410121050c020b2006103322050d010c790b2002280204210520042006460d0020052004200610372205450d740b20022005360204200241086a20063602002002410c6a28020021040b200520046a41d1003a00002002410c6a200441016a3602000c6e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d71200441017422062005200620054b1b22064100480d710240024020040d00024020060d00410121050c020b2006103322050d010c780b2002280204210520042006460d0020052004200610372205450d730b20022005360204200241086a20063602002002410c6a28020021040b200520046a41d2003a00002002410c6a200441016a3602000c6d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d70200441017422062005200620054b1b22064100480d700240024020040d00024020060d00410121050c020b2006103322050d010c770b2002280204210520042006460d0020052004200610372205450d720b20022005360204200241086a20063602002002410c6a28020021040b200520046a41d3003a00002002410c6a200441016a3602000c6c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6f200441017422062005200620054b1b22064100480d6f0240024020040d00024020060d00410121050c020b2006103322050d010c760b2002280204210520042006460d0020052004200610372205450d710b20022005360204200241086a20063602002002410c6a28020021040b200520046a41d4003a00002002410c6a200441016a3602000c6b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6e200441017422062005200620054b1b22064100480d6e0240024020040d00024020060d00410121050c020b2006103322050d010c750b2002280204210520042006460d0020052004200610372205450d700b20022005360204200241086a20063602002002410c6a28020021040b200520046a41d5003a00002002410c6a200441016a3602000c6a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6d200441017422062005200620054b1b22064100480d6d0240024020040d00024020060d00410121050c020b2006103322050d010c740b2002280204210520042006460d0020052004200610372205450d6f0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41d6003a00002002410c6a200441016a3602000c690b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6c200441017422062005200620054b1b22064100480d6c0240024020040d00024020060d00410121050c020b2006103322050d010c730b2002280204210520042006460d0020052004200610372205450d6e0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41d7003a00002002410c6a200441016a3602000c680b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6b200441017422062005200620054b1b22064100480d6b0240024020040d00024020060d00410121050c020b2006103322050d010c720b2002280204210520042006460d0020052004200610372205450d6d0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41d8003a00002002410c6a200441016a3602000c670b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6a200441017422062005200620054b1b22064100480d6a0240024020040d00024020060d00410121050c020b2006103322050d010c710b2002280204210520042006460d0020052004200610372205450d6c0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41d9003a00002002410c6a200441016a3602000c660b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d69200441017422062005200620054b1b22064100480d690240024020040d00024020060d00410121050c020b2006103322050d010c700b2002280204210520042006460d0020052004200610372205450d6b0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41da003a00002002410c6a200441016a3602000c650b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d68200441017422062005200620054b1b22064100480d680240024020040d00024020060d00410121050c020b2006103322050d010c6f0b2002280204210520042006460d0020052004200610372205450d6a0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41db003a00002002410c6a200441016a3602000c640b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d67200441017422062005200620054b1b22064100480d670240024020040d00024020060d00410121050c020b2006103322050d010c6e0b2002280204210520042006460d0020052004200610372205450d690b20022005360204200241086a20063602002002410c6a28020021040b200520046a41dc003a00002002410c6a200441016a3602000c630b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d66200441017422062005200620054b1b22064100480d660240024020040d00024020060d00410121050c020b2006103322050d010c6d0b2002280204210520042006460d0020052004200610372205450d680b20022005360204200241086a20063602002002410c6a28020021040b200520046a41dd003a00002002410c6a200441016a3602000c620b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d65200441017422062005200620054b1b22064100480d650240024020040d00024020060d00410121050c020b2006103322050d010c6c0b2002280204210520042006460d0020052004200610372205450d670b20022005360204200241086a20063602002002410c6a28020021040b200520046a41de003a00002002410c6a200441016a3602000c610b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d64200441017422062005200620054b1b22064100480d640240024020040d00024020060d00410121050c020b2006103322050d010c6b0b2002280204210520042006460d0020052004200610372205450d660b20022005360204200241086a20063602002002410c6a28020021040b200520046a41df003a00002002410c6a200441016a3602000c600b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d63200441017422062005200620054b1b22064100480d630240024020040d00024020060d00410121050c020b2006103322050d010c6a0b2002280204210520042006460d0020052004200610372205450d650b20022005360204200241086a20063602002002410c6a28020021040b200520046a41e0003a00002002410c6a200441016a3602000c5f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d62200441017422062005200620054b1b22064100480d620240024020040d00024020060d00410121050c020b2006103322050d010c690b2002280204210520042006460d0020052004200610372205450d640b20022005360204200241086a20063602002002410c6a28020021040b200520046a41e1003a00002002410c6a200441016a3602000c5e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d61200441017422062005200620054b1b22064100480d610240024020040d00024020060d00410121050c020b2006103322050d010c680b2002280204210520042006460d0020052004200610372205450d630b20022005360204200241086a20063602002002410c6a28020021040b200520046a41e2003a00002002410c6a200441016a3602000c5d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d60200441017422062005200620054b1b22064100480d600240024020040d00024020060d00410121050c020b2006103322050d010c670b2002280204210520042006460d0020052004200610372205450d620b20022005360204200241086a20063602002002410c6a28020021040b200520046a41e3003a00002002410c6a200441016a3602000c5c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5f200441017422062005200620054b1b22064100480d5f0240024020040d00024020060d00410121050c020b2006103322050d010c660b2002280204210520042006460d0020052004200610372205450d610b20022005360204200241086a20063602002002410c6a28020021040b200520046a41e4003a00002002410c6a200441016a3602000c5b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5e200441017422062005200620054b1b22064100480d5e0240024020040d00024020060d00410121050c020b2006103322050d010c650b2002280204210520042006460d0020052004200610372205450d600b20022005360204200241086a20063602002002410c6a28020021040b200520046a41e5003a00002002410c6a200441016a3602000c5a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5d200441017422062005200620054b1b22064100480d5d0240024020040d00024020060d00410121050c020b2006103322050d010c640b2002280204210520042006460d0020052004200610372205450d5f0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41e6003a00002002410c6a200441016a3602000c590b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5c200441017422062005200620054b1b22064100480d5c0240024020040d00024020060d00410121050c020b2006103322050d010c630b2002280204210520042006460d0020052004200610372205450d5e0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41e7003a00002002410c6a200441016a3602000c580b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5b200441017422062005200620054b1b22064100480d5b0240024020040d00024020060d00410121050c020b2006103322050d010c620b2002280204210520042006460d0020052004200610372205450d5d0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41e8003a00002002410c6a200441016a3602000c570b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5a200441017422062005200620054b1b22064100480d5a0240024020040d00024020060d00410121050c020b2006103322050d010c610b2002280204210520042006460d0020052004200610372205450d5c0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41e9003a00002002410c6a200441016a3602000c560b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d59200441017422062005200620054b1b22064100480d590240024020040d00024020060d00410121050c020b2006103322050d010c600b2002280204210520042006460d0020052004200610372205450d5b0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ea003a00002002410c6a200441016a3602000c550b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d58200441017422062005200620054b1b22064100480d580240024020040d00024020060d00410121050c020b2006103322050d010c5f0b2002280204210520042006460d0020052004200610372205450d5a0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41eb003a00002002410c6a200441016a3602000c540b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d57200441017422062005200620054b1b22064100480d570240024020040d00024020060d00410121050c020b2006103322050d010c5e0b2002280204210520042006460d0020052004200610372205450d590b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ec003a00002002410c6a200441016a3602000c530b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d56200441017422062005200620054b1b22064100480d560240024020040d00024020060d00410121050c020b2006103322050d010c5d0b2002280204210520042006460d0020052004200610372205450d580b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ed003a00002002410c6a200441016a3602000c520b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d55200441017422062005200620054b1b22064100480d550240024020040d00024020060d00410121050c020b2006103322050d010c5c0b2002280204210520042006460d0020052004200610372205450d570b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ee003a00002002410c6a200441016a3602000c510b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d54200441017422062005200620054b1b22064100480d540240024020040d00024020060d00410121050c020b2006103322050d010c5b0b2002280204210520042006460d0020052004200610372205450d560b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ef003a00002002410c6a200441016a3602000c500b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d53200441017422062005200620054b1b22064100480d530240024020040d00024020060d00410121050c020b2006103322050d010c5a0b2002280204210520042006460d0020052004200610372205450d550b20022005360204200241086a20063602002002410c6a28020021040b200520046a41f0003a00002002410c6a200441016a3602000c4f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d52200441017422062005200620054b1b22064100480d520240024020040d00024020060d00410121050c020b2006103322050d010c590b2002280204210520042006460d0020052004200610372205450d540b20022005360204200241086a20063602002002410c6a28020021040b200520046a41f1003a00002002410c6a200441016a3602000c4e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d51200441017422062005200620054b1b22064100480d510240024020040d00024020060d00410121050c020b2006103322050d010c580b2002280204210520042006460d0020052004200610372205450d530b20022005360204200241086a20063602002002410c6a28020021040b200520046a41f2003a00002002410c6a200441016a3602000c4d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d50200441017422062005200620054b1b22064100480d500240024020040d00024020060d00410121050c020b2006103322050d010c570b2002280204210520042006460d0020052004200610372205450d520b20022005360204200241086a20063602002002410c6a28020021040b200520046a41f3003a00002002410c6a200441016a3602000c4c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4f200441017422062005200620054b1b22064100480d4f0240024020040d00024020060d00410121050c020b2006103322050d010c560b2002280204210520042006460d0020052004200610372205450d510b20022005360204200241086a20063602002002410c6a28020021040b200520046a41f4003a00002002410c6a200441016a3602000c4b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4e200441017422062005200620054b1b22064100480d4e0240024020040d00024020060d00410121050c020b2006103322050d010c550b2002280204210520042006460d0020052004200610372205450d500b20022005360204200241086a20063602002002410c6a28020021040b200520046a41f5003a00002002410c6a200441016a3602000c4a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4d200441017422062005200620054b1b22064100480d4d0240024020040d00024020060d00410121050c020b2006103322050d010c540b2002280204210520042006460d0020052004200610372205450d4f0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41f6003a00002002410c6a200441016a3602000c490b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4c200441017422062005200620054b1b22064100480d4c0240024020040d00024020060d00410121050c020b2006103322050d010c530b2002280204210520042006460d0020052004200610372205450d4e0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41f7003a00002002410c6a200441016a3602000c480b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4b200441017422062005200620054b1b22064100480d4b0240024020040d00024020060d00410121050c020b2006103322050d010c520b2002280204210520042006460d0020052004200610372205450d4d0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41f8003a00002002410c6a200441016a3602000c470b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4a200441017422062005200620054b1b22064100480d4a0240024020040d00024020060d00410121050c020b2006103322050d010c510b2002280204210520042006460d0020052004200610372205450d4c0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41f9003a00002002410c6a200441016a3602000c460b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d49200441017422062005200620054b1b22064100480d490240024020040d00024020060d00410121050c020b2006103322050d010c500b2002280204210520042006460d0020052004200610372205450d4b0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41fa003a00002002410c6a200441016a3602000c450b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d48200441017422062005200620054b1b22064100480d480240024020040d00024020060d00410121050c020b2006103322050d010c4f0b2002280204210520042006460d0020052004200610372205450d4a0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41fb003a00002002410c6a200441016a3602000c440b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d47200441017422062005200620054b1b22064100480d470240024020040d00024020060d00410121050c020b2006103322050d010c4e0b2002280204210520042006460d0020052004200610372205450d490b20022005360204200241086a20063602002002410c6a28020021040b200520046a41fc003a00002002410c6a200441016a3602000c430b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d46200441017422062005200620054b1b22064100480d460240024020040d00024020060d00410121050c020b2006103322050d010c4d0b2002280204210520042006460d0020052004200610372205450d480b20022005360204200241086a20063602002002410c6a28020021040b200520046a41fd003a00002002410c6a200441016a3602000c420b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d45200441017422062005200620054b1b22064100480d450240024020040d00024020060d00410121050c020b2006103322050d010c4c0b2002280204210520042006460d0020052004200610372205450d470b20022005360204200241086a20063602002002410c6a28020021040b200520046a41fe003a00002002410c6a200441016a3602000c410b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d44200441017422062005200620054b1b22064100480d440240024020040d00024020060d00410121050c020b2006103322050d010c4b0b2002280204210520042006460d0020052004200610372205450d460b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ff003a00002002410c6a200441016a3602000c400b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d43200441017422062005200620054b1b22064100480d430240024020040d00024020060d00410121050c020b2006103322050d010c4a0b2002280204210520042006460d0020052004200610372205450d450b20022005360204200241086a20063602002002410c6a28020021040b200520046a4180013a00002002410c6a200441016a3602000c3f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d42200441017422062005200620054b1b22064100480d420240024020040d00024020060d00410121050c020b2006103322050d010c490b2002280204210520042006460d0020052004200610372205450d440b20022005360204200241086a20063602002002410c6a28020021040b200520046a4181013a00002002410c6a200441016a3602000c3e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d41200441017422062005200620054b1b22064100480d410240024020040d00024020060d00410121050c020b2006103322050d010c480b2002280204210520042006460d0020052004200610372205450d430b20022005360204200241086a20063602002002410c6a28020021040b200520046a4182013a00002002410c6a200441016a3602000c3d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d40200441017422062005200620054b1b22064100480d400240024020040d00024020060d00410121050c020b2006103322050d010c470b2002280204210520042006460d0020052004200610372205450d420b20022005360204200241086a20063602002002410c6a28020021040b200520046a4183013a00002002410c6a200441016a3602000c3c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3f200441017422062005200620054b1b22064100480d3f0240024020040d00024020060d00410121050c020b2006103322050d010c460b2002280204210520042006460d0020052004200610372205450d410b20022005360204200241086a20063602002002410c6a28020021040b200520046a4184013a00002002410c6a200441016a3602000c3b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3e200441017422062005200620054b1b22064100480d3e0240024020040d00024020060d00410121050c020b2006103322050d010c450b2002280204210520042006460d0020052004200610372205450d400b20022005360204200241086a20063602002002410c6a28020021040b200520046a4185013a00002002410c6a200441016a3602000c3a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3d200441017422062005200620054b1b22064100480d3d0240024020040d00024020060d00410121050c020b2006103322050d010c440b2002280204210520042006460d0020052004200610372205450d3f0b20022005360204200241086a20063602002002410c6a28020021040b200520046a4186013a00002002410c6a200441016a3602000c390b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3c200441017422062005200620054b1b22064100480d3c0240024020040d00024020060d00410121050c020b2006103322050d010c430b2002280204210520042006460d0020052004200610372205450d3e0b20022005360204200241086a20063602002002410c6a28020021040b200520046a4187013a00002002410c6a200441016a3602000c380b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3b200441017422062005200620054b1b22064100480d3b0240024020040d00024020060d00410121050c020b2006103322050d010c420b2002280204210520042006460d0020052004200610372205450d3d0b20022005360204200241086a20063602002002410c6a28020021040b200520046a4188013a00002002410c6a200441016a3602000c370b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3d200441017422062005200620054b1b22064100480d3d0240024020040d00024020060d00410121050c020b2006103322050d010c410b2002280204210520042006460d0020052004200610372205450d3c0b20022005360204200241086a20063602002002410c6a28020021040b200520046a4189013a00002002410c6a200441016a3602000c360b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3c200441017422062005200620054b1b22064100480d3c0240024020040d00024020060d00410121050c020b2006103322050d010c400b2002280204210520042006460d0020052004200610372205450d3c0b20022005360204200241086a20063602002002410c6a28020021040b200520046a418a013a00002002410c6a200441016a3602000c350b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3b200441017422062005200620054b1b22064100480d3b0240024020040d00024020060d00410121050c020b2006103322050d010c3f0b2002280204210520042006460d0020052004200610372205450d3b0b20022005360204200241086a20063602002002410c6a28020021040b200520046a418b013a00002002410c6a200441016a3602000c340b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3a200441017422062005200620054b1b22064100480d3a0240024020040d00024020060d00410121050c020b2006103322050d010c3e0b2002280204210520042006460d0020052004200610372205450d3a0b20022005360204200241086a20063602002002410c6a28020021040b200520046a418c013a00002002410c6a200441016a3602000c330b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d39200441017422062005200620054b1b22064100480d390240024020040d00024020060d00410121050c020b2006103322050d010c3d0b2002280204210520042006460d0020052004200610372205450d390b20022005360204200241086a20063602002002410c6a28020021040b200520046a418d013a00002002410c6a200441016a3602000c320b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d38200441017422062005200620054b1b22064100480d380240024020040d00024020060d00410121050c020b2006103322050d010c3c0b2002280204210520042006460d0020052004200610372205450d380b20022005360204200241086a20063602002002410c6a28020021040b200520046a418e013a00002002410c6a200441016a3602000c310b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d37200441017422062005200620054b1b22064100480d370240024020040d00024020060d00410121050c020b2006103322050d010c3b0b2002280204210520042006460d0020052004200610372205450d370b20022005360204200241086a20063602002002410c6a28020021040b200520046a418f013a00002002410c6a200441016a3602000c300b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d36200441017422062005200620054b1b22064100480d360240024020040d00024020060d00410121050c020b2006103322050d010c3a0b2002280204210520042006460d0020052004200610372205450d360b20022005360204200241086a20063602002002410c6a28020021040b200520046a4190013a00002002410c6a200441016a3602000c2f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d35200441017422062005200620054b1b22064100480d350240024020040d00024020060d00410121050c020b2006103322050d010c390b2002280204210520042006460d0020052004200610372205450d350b20022005360204200241086a20063602002002410c6a28020021040b200520046a4191013a00002002410c6a200441016a3602000c2e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d34200441017422062005200620054b1b22064100480d340240024020040d00024020060d00410121050c020b2006103322050d010c380b2002280204210520042006460d0020052004200610372205450d340b20022005360204200241086a20063602002002410c6a28020021040b200520046a4192013a00002002410c6a200441016a3602000c2d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d33200441017422062005200620054b1b22064100480d330240024020040d00024020060d00410121050c020b2006103322050d010c370b2002280204210520042006460d0020052004200610372205450d330b20022005360204200241086a20063602002002410c6a28020021040b200520046a4193013a00002002410c6a200441016a3602000c2c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d32200441017422062005200620054b1b22064100480d320240024020040d00024020060d00410121050c020b2006103322050d010c360b2002280204210520042006460d0020052004200610372205450d320b20022005360204200241086a20063602002002410c6a28020021040b200520046a4194013a00002002410c6a200441016a3602000c2b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d31200441017422062005200620054b1b22064100480d310240024020040d00024020060d00410121050c020b2006103322050d010c350b2002280204210520042006460d0020052004200610372205450d310b20022005360204200241086a20063602002002410c6a28020021040b200520046a4195013a00002002410c6a200441016a3602000c2a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d30200441017422062005200620054b1b22064100480d300240024020040d00024020060d00410121050c020b2006103322050d010c340b2002280204210520042006460d0020052004200610372205450d300b20022005360204200241086a20063602002002410c6a28020021040b200520046a4196013a00002002410c6a200441016a3602000c290b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2f200441017422062005200620054b1b22064100480d2f0240024020040d00024020060d00410121050c020b2006103322050d010c330b2002280204210520042006460d0020052004200610372205450d2f0b20022005360204200241086a20063602002002410c6a28020021040b200520046a4197013a00002002410c6a200441016a3602000c280b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2e200441017422062005200620054b1b22064100480d2e0240024020040d00024020060d00410121050c020b2006103322050d010c320b2002280204210520042006460d0020052004200610372205450d2e0b20022005360204200241086a20063602002002410c6a28020021040b200520046a4198013a00002002410c6a200441016a3602000c270b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2d200441017422062005200620054b1b22064100480d2d0240024020040d00024020060d00410121050c020b2006103322050d010c310b2002280204210520042006460d0020052004200610372205450d2d0b20022005360204200241086a20063602002002410c6a28020021040b200520046a4199013a00002002410c6a200441016a3602000c260b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2c200441017422062005200620054b1b22064100480d2c0240024020040d00024020060d00410121050c020b2006103322050d010c300b2002280204210520042006460d0020052004200610372205450d2c0b20022005360204200241086a20063602002002410c6a28020021040b200520046a419a013a00002002410c6a200441016a3602000c250b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2b200441017422062005200620054b1b22064100480d2b0240024020040d00024020060d00410121050c020b2006103322050d010c2f0b2002280204210520042006460d0020052004200610372205450d2b0b20022005360204200241086a20063602002002410c6a28020021040b200520046a419b013a00002002410c6a200441016a3602000c240b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2a200441017422062005200620054b1b22064100480d2a0240024020040d00024020060d00410121050c020b2006103322050d010c2d0b2002280204210520042006460d0020052004200610372205450d2a0b20022005360204200241086a20063602002002410c6a28020021040b200520046a419c013a00002002410c6a200441016a3602000c230b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d29200441017422062005200620054b1b22064100480d290240024020040d00024020060d00410121050c020b200610332205450d2c0c010b2002280204210520042006460d0020052004200610372205450d290b20022005360204200241086a20063602002002410c6a28020021040b200520046a419d013a00002002410c6a200441016a3602000c220b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d28200441017422062005200620054b1b22064100480d280240024020040d00024020060d00410121050c020b200610332205450d2b0c010b2002280204210520042006460d0020052004200610372205450d280b20022005360204200241086a20063602002002410c6a28020021040b200520046a419e013a00002002410c6a200441016a3602000c210b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d27200441017422062005200620054b1b22064100480d270240024020040d00024020060d00410121050c020b200610332205450d2a0c010b2002280204210520042006460d0020052004200610372205450d270b20022005360204200241086a20063602002002410c6a28020021040b200520046a419f013a00002002410c6a200441016a3602000c200b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d26200441017422062005200620054b1b22064100480d260240024020040d00024020060d00410121050c020b200610332205450d290c010b2002280204210520042006460d0020052004200610372205450d260b20022005360204200241086a20063602002002410c6a28020021040b200520046a41a0013a00002002410c6a200441016a3602000c1f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d25200441017422062005200620054b1b22064100480d250240024020040d00024020060d00410121050c020b200610332205450d280c010b2002280204210520042006460d0020052004200610372205450d250b20022005360204200241086a20063602002002410c6a28020021040b200520046a41a1013a00002002410c6a200441016a3602000c1e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d24200441017422062005200620054b1b22064100480d240240024020040d00024020060d00410121050c020b200610332205450d270c010b2002280204210520042006460d0020052004200610372205450d240b20022005360204200241086a20063602002002410c6a28020021040b200520046a41a2013a00002002410c6a200441016a3602000c1d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d23200441017422062005200620054b1b22064100480d230240024020040d00024020060d00410121050c020b200610332205450d260c010b2002280204210520042006460d0020052004200610372205450d230b20022005360204200241086a20063602002002410c6a28020021040b200520046a41a3013a00002002410c6a200441016a3602000c1c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d22200441017422062005200620054b1b22064100480d220240024020040d00024020060d00410121050c020b200610332205450d250c010b2002280204210520042006460d0020052004200610372205450d220b20022005360204200241086a20063602002002410c6a28020021040b200520046a41a4013a00002002410c6a200441016a3602000c1b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d00024020060d00410121050c020b200610332205450d240c010b2002280204210520042006460d0020052004200610372205450d210b20022005360204200241086a20063602002002410c6a28020021040b200520046a41a5013a00002002410c6a200441016a3602000c1a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d20200441017422062005200620054b1b22064100480d200240024020040d00024020060d00410121050c020b200610332205450d230c010b2002280204210520042006460d0020052004200610372205450d200b20022005360204200241086a20063602002002410c6a28020021040b200520046a41a6013a00002002410c6a200441016a3602000c190b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1f200441017422062005200620054b1b22064100480d1f0240024020040d00024020060d00410121050c020b200610332205450d220c010b2002280204210520042006460d0020052004200610372205450d1f0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41a7013a00002002410c6a200441016a3602000c180b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1e200441017422062005200620054b1b22064100480d1e0240024020040d00024020060d00410121050c020b200610332205450d210c010b2002280204210520042006460d0020052004200610372205450d1e0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41a8013a00002002410c6a200441016a3602000c170b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1d200441017422062005200620054b1b22064100480d1d0240024020040d00024020060d00410121050c020b200610332205450d200c010b2002280204210520042006460d0020052004200610372205450d1d0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41a9013a00002002410c6a200441016a3602000c160b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1c200441017422062005200620054b1b22064100480d1c0240024020040d00024020060d00410121050c020b200610332205450d1f0c010b2002280204210520042006460d0020052004200610372205450d1c0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41aa013a00002002410c6a200441016a3602000c150b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1b200441017422062005200620054b1b22064100480d1b0240024020040d00024020060d00410121050c020b200610332205450d1e0c010b2002280204210520042006460d0020052004200610372205450d1b0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ab013a00002002410c6a200441016a3602000c140b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1a200441017422062005200620054b1b22064100480d1a0240024020040d00024020060d00410121050c020b200610332205450d1d0c010b2002280204210520042006460d0020052004200610372205450d1a0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ac013a00002002410c6a200441016a3602000c130b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d19200441017422062005200620054b1b22064100480d190240024020040d00024020060d00410121050c020b200610332205450d1c0c010b2002280204210520042006460d0020052004200610372205450d190b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ad013a00002002410c6a200441016a3602000c120b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d18200441017422062005200620054b1b22064100480d180240024020040d00024020060d00410121050c020b200610332205450d1b0c010b2002280204210520042006460d0020052004200610372205450d180b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ae013a00002002410c6a200441016a3602000c110b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d17200441017422062005200620054b1b22064100480d170240024020040d00024020060d00410121050c020b200610332205450d1a0c010b2002280204210520042006460d0020052004200610372205450d170b20022005360204200241086a20063602002002410c6a28020021040b200520046a41af013a00002002410c6a200441016a3602000c100b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d16200441017422062005200620054b1b22064100480d160240024020040d00024020060d00410121050c020b200610332205450d190c010b2002280204210520042006460d0020052004200610372205450d160b20022005360204200241086a20063602002002410c6a28020021040b200520046a41b0013a00002002410c6a200441016a3602000c0f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d15200441017422062005200620054b1b22064100480d150240024020040d00024020060d00410121050c020b200610332205450d180c010b2002280204210520042006460d0020052004200610372205450d150b20022005360204200241086a20063602002002410c6a28020021040b200520046a41b1013a00002002410c6a200441016a3602000c0e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d14200441017422062005200620054b1b22064100480d140240024020040d00024020060d00410121050c020b200610332205450d170c010b2002280204210520042006460d0020052004200610372205450d140b20022005360204200241086a20063602002002410c6a28020021040b200520046a41b2013a00002002410c6a200441016a3602000c0d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d13200441017422062005200620054b1b22064100480d130240024020040d00024020060d00410121050c020b200610332205450d160c010b2002280204210520042006460d0020052004200610372205450d130b20022005360204200241086a20063602002002410c6a28020021040b200520046a41b3013a00002002410c6a200441016a3602000c0c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d12200441017422062005200620054b1b22064100480d120240024020040d00024020060d00410121050c020b200610332205450d150c010b2002280204210520042006460d0020052004200610372205450d120b20022005360204200241086a20063602002002410c6a28020021040b200520046a41b4013a00002002410c6a200441016a3602000c0b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d11200441017422062005200620054b1b22064100480d110240024020040d00024020060d00410121050c020b200610332205450d140c010b2002280204210520042006460d0020052004200610372205450d110b20022005360204200241086a20063602002002410c6a28020021040b200520046a41b5013a00002002410c6a200441016a3602000c0a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d10200441017422062005200620054b1b22064100480d100240024020040d00024020060d00410121050c020b200610332205450d130c010b2002280204210520042006460d0020052004200610372205450d100b20022005360204200241086a20063602002002410c6a28020021040b200520046a41b6013a00002002410c6a200441016a3602000c090b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0f200441017422062005200620054b1b22064100480d0f0240024020040d00024020060d00410121050c020b200610332205450d120c010b2002280204210520042006460d0020052004200610372205450d0f0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41b7013a00002002410c6a200441016a3602000c080b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0e200441017422062005200620054b1b22064100480d0e0240024020040d00024020060d00410121050c020b200610332205450d110c010b2002280204210520042006460d0020052004200610372205450d0e0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41b8013a00002002410c6a200441016a3602000c070b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0d200441017422062005200620054b1b22064100480d0d0240024020040d00024020060d00410121050c020b200610332205450d100c010b2002280204210520042006460d0020052004200610372205450d0d0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41b9013a00002002410c6a200441016a3602000c060b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0c200441017422062005200620054b1b22064100480d0c0240024020040d00024020060d00410121050c020b200610332205450d0f0c010b2002280204210520042006460d0020052004200610372205450d0c0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ba013a00002002410c6a200441016a3602000c050b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0b200441017422062005200620054b1b22064100480d0b0240024020040d00024020060d00410121050c020b200610332205450d0e0c010b2002280204210520042006460d0020052004200610372205450d0b0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41bb013a00002002410c6a200441016a3602000c040b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0a200441017422062005200620054b1b22064100480d0a0240024020040d00024020060d00410121050c020b200610332205450d0d0c010b2002280204210520042006460d0020052004200610372205450d0a0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41bc013a00002002410c6a200441016a3602000c030b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d09200441017422062005200620054b1b22064100480d090240024020040d00024020060d00410121050c020b200610332205450d0c0c010b2002280204210520042006460d0020052004200610372205450d090b20022005360204200241086a20063602002002410c6a28020021040b200520046a41bd013a00002002410c6a200441016a3602000c020b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d08200441017422062005200620054b1b22064100480d080240024020040d00024020060d00410121050c020b200610332205450d0b0c010b2002280204210520042006460d0020052004200610372205450d080b20022005360204200241086a20063602002002410c6a28020021040b200520046a41be013a00002002410c6a200441016a3602000c010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d07200441017422062005200620054b1b22064100480d070240024020040d00024020060d00410121050c020b200610332205450d0a0c010b2002280204210520042006460d0020052004200610372205450d070b20022005360204200241086a20063602002002410c6a28020021040b200520046a41bf013a00002002410c6a200441016a3602000b2000411f3a000020012d00004109470d090240200141046a280200220228020441ffffffff0371450d0020022802001035200128020421020b200210350c090b103e000b103e000b103e000b103c000b103c000b103e000b103c000b103c000b20002004290200370200200041086a200441086a29020037020020012d00004109470d000240200141046a280200220228020441ffffffff0371450d0020022802001035200128020421020b200210350b200341106a24000f0b103c000bd80301057f2004410c6a22052802002106200441086a21070240024003400240024020072802002006460d00200428020421080c010b200641016a22082006490d02200641017422092008200920084b1b22094100480d020240024020060d00024020090d00410121080c020b2009103322080d010c050b2004280204210820062009460d0020082006200910372208450d040b2004200836020420072009360200200528020021060b200820066a200141807f72200141ff0071200141077622081b3a00002005200641016a22063602002008210120080d000b024020022003460d00200441086a21052004410c6a210703402002280200210103400240024020052802002006460d00200428020421080c010b200641016a22082006490d04200641017422092008200920084b1b22094100480d040240024020060d00024020090d00410121080c020b200910332208450d070c010b2004280204210820062009460d0020082006200910372208450d060b2004200836020420052009360200200728020021060b200820066a200141807f72200141ff0071200141077622081b3a00002007200641016a22063602002008210120080d000b200241046a22022003470d000b0b2000411f3a00000f0b103e000b103c000bdb0301067f024002400240024020014107752203200141c00071220472452003417f4720044572470d002002410c6a28020021040c010b2002410c6a22052802002104200241086a210603400240024020062802002004460d00200228020421070c010b200441016a22072004490d03200441017422082007200820074b1b22084100480d030240024020040d00024020080d00410121070c020b2008103322070d010c060b2002280204210720042008460d0020072004200810372207450d050b2002200736020420062008360200200528020021040b200720046a200141807f723a00002005200441016a2204360200200341c000712107200321012003410775220821032008200772452008417f4720074572470d000b0b02400240200241086a2802002004460d00200228020421030c010b200441016a22032004490d01200441017422072003200720034b1b22074100480d010240024020040d00024020070d00410121030c020b200710332203450d040c010b2002280204210320042007460d0020032004200710372203450d030b20022003360204200241086a20073602002002410c6a28020021040b200320046a200141ff00713a00002000411f3a00002002410c6a200441016a3602000f0b103e000b103c000bdf0302017e067f024002400240024020014207872203502001a7220441c00071452205712003427f52200572470d002002410c6a28020021050c010b2002410c6a22062802002105200241086a210703400240024020072802002005460d00200228020421080c010b200541016a22082005490d03200541017422092008200920084b1b22094100480d030240024020050d00024020090d00410121080c020b2009103322080d010c060b2002280204210820052009460d0020082005200910372208450d050b2002200836020420072009360200200628020021050b200820056a200441807f723a00002006200541016a22053602002003a72104200342078722012103200150200441c00071452208712001427f52200872470d000b0b02400240200241086a2802002005460d00200228020421080c010b200541016a22082005490d01200541017422092008200920084b1b22094100480d010240024020050d00024020090d00410121080c020b200910332208450d040c010b2002280204210820052009460d0020082005200910372208450d030b20022008360204200241086a20093602002002410c6a28020021050b200820056a200441ff00713a00002000411f3a00002002410c6a200541016a3602000f0b103e000b103c000bc40301077f230041d0006b22022400410021032002410036021020024208370308200241c1006a220441076a210541082106024002400340200241386a200110a807200220042900003703282002200529000037002f20022d0040210720022802384101460d012002200229002f37001f200220022903283703182002200229001f37003f2002200229031837033802402003200228020c470d00200241086a200310a90720022802082106200228021021030b200620034104746a220820073a000020082002290338370001200841086a200229003f3700002002200341016a2203360210200741ff01714106470d000b20002002290308370204200041003602002000410c6a200241106a2802003602000c010b2000200228023c3602042000200229032837000920004101360200200041086a20073a0000200041106a200228002f36000002402003450d0020034104742107200621030340024020032d00004109470d000240200341046a2201280200220828020441ffffffff0371450d0020082802001035200128020021080b200810350b200341106a2103200741706a22070d000b0b200228020c41ffffffff0071450d00200610350b200241d0006a24000bc1ba0102097f017e230041f0006b2202240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802082203200128020c2204460d00200441016a22052004490dab0120032005490dac012001280200220620046a2d000021072001410c6a22082005360200200741bf014b0d0120070ec001b402b402020304b402010101010105060708090a0b01010101010101010c0d010101010e0f101112010101131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa01b4020b200241013a0048200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241c8006a360238200241086a200241d8006a1041200241336a200241106a2802003600002002200229030837002b2002200229002837031820022002412f6a29000037001f200041053a0004200020022903183700052000410c6a200229001f370000200041013602000cb6020b2000410b3a000420004101360200200041056a20073a00000cb5020b024002400240024002400240024020032005460d00200441026a21092005417f460db10120032009490db201200620056a2c00002101200820093602004100210a0240200141004e0d00411921090c020b0240200141017441807f71200172220141ff0171220541847e6a220941034d0d0041062109200541c001470d034104210a410221070cb9020b20090e0405040306050b200241013a0047200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241c7006a360238200241c8006a200241d8006a1041200241326a200241d0006a2802003601002002200229034837012a2002200229012837031820022002412e6a29010037011e410521090b2002200229011e37010e200220022903183703080b200020013a0005200020093a000420002002290308370106200041013602002000410c6a200229010e3701000cb8020b4101210a410221070cb4020b4102210a410221070cb3020b4103210a0b410221070cb1020b024002400240024002400240024020032005460d00200441026a21092005417f460db20120032009490db301200620056a2c00002101200820093602004100210a0240200141004e0d00411921090c020b0240200141017441807f71200172220141ff0171220541847e6a220941034d0d0041062109200541c001470d034104210a410321070cb8020b20090e0405040306050b200241013a0047200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241c7006a360238200241c8006a200241d8006a1041200241326a200241d0006a2802003601002002200229034837012a2002200229012837031820022002412e6a29010037011e410521090b2002200229011e37010e200220022903183703080b200020013a0005200020093a000420002002290308370106200041013602002000410c6a200229010e3701000cb7020b4101210a410321070cb3020b4102210a410321070cb2020b4103210a0b410321070cb0020b024002400240024002400240024020032005460d00200441026a21092005417f460db30120032009490db401200620056a2c00002101200820093602004100210a0240200141004e0d00411921090c020b0240200141017441807f71200172220141ff0171220541847e6a220941034d0d0041062109200541c001470d034104210a410421070cb7020b20090e0405040306050b200241013a0047200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241c7006a360238200241c8006a200241d8006a1041200241326a200241d0006a2802003601002002200229034837012a2002200229012837031820022002412e6a29010037011e410521090b2002200229011e37010e200220022903183703080b200020013a0005200020093a000420002002290308370106200041013602002000410c6a200229010e3701000cb6020b4101210a410421070cb2020b4102210a410421070cb1020b4103210a0b410421070caf020b410621070cae020b410021014100210902400240034002402001411f4d0d00410f21010c030b20032005460d012005417f460daf012003200541016a2207490df701200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b024020014120490d00410d21012004410f4b0d020b410721070caf020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000cb0020b410021014100210902400240034002402001411f4d0d00410f21010c030b20032005460d012005417f460daf012003200541016a2207490df701200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b024020014120490d00410d21012004410f4b0d020b410821070cae020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000caf020b200241d8006a200110ab07200241d8006a410c6a2802002109200241d8006a41086a2802002107200228025c210420022802584101460daf012002410036026020024204370358200241d8006a4100200941027422034102751086012002280260210602402009450d002003417c6a410276210a200228025820064102746a210920042105034020092005280200360200200941046a2109200541046a21052003417c6a22030d000b2006200a6a41016a21060b200220063602600240200741ffffffff0371450d00200410350b2002280258210a0240200228025c22092006460d0020092006490dad012009450d002009410274220520064102742209460d00024020090d00024020050d004104210a0c020b200a10354104210a0c010b200a200520091037220a450dae010b410021094100210402400240034002402009411f4d0d00410f21010c030b20012802082207200128020c2205460d01200541016a22032005490db10120072003490df701200128020020056a2d0000210520082003360200200541ff00712009411f71742004722104200941076a21092005418001710d000b024020094120490d00410d21012005410f4b0d020b410c10332209450daf0120092004360208200920063602042009200a360200410921070cad020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a280200360200200641ffffffff0371450dae02200a10350cae020b410a21070caa020b410021014100210902400240034002402001411f4d0d00410f21010c030b20032005460d012005417f460db1012003200541016a2207490df601200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b024020014120490d00410d21012004410f4b0d020b410b21070cab020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000cac020b410021014100210902400240024002400240034002402001411f4d0d00410f21010c030b20032005460d012005417f460db4012003200541016a2204490df901200620056a2d0000210720082004360200200741ff00712001411f71742009722109200141076a2101200421052007418001710d000b024020014120490d00410d21012007410f4b0d020b20032004460d03200441016a22012004490db401200320014f0d022001200341c0fdcb001058000b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000cae020b200620046a2d000021052008200136020020050d01410c21074100210a0caa020b200241013a0048200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241c8006a360238200241086a200241d8006a1041200241336a200241106a2802003600002002200229030837002b2002200229002837031820022002412f6a29000037001f200041053a0004200020022903183700052000410c6a200229001f370000200041013602000cac020b200041163a000420004101360200200041056a20053a00000cab020b410d21070ca7020b410e21070ca6020b410021014100210902400240034002402001411f4d0d00410f21010c030b20032005460d012005417f460db0012003200541016a2207490df401200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b024020014120490d00410d21012004410f4b0d020b410f21070ca7020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000ca8020b410021014100210902400240034002402001411f4d0d00410f21010c030b20032005460d012005417f460db0012003200541016a2207490df401200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b024020014120490d00410d21012004410f4b0d020b411021070ca6020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000ca7020b410021014100210902400240034002402001411f4d0d00410f21010c030b20032005460d012005417f460db0012003200541016a2207490df401200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b024020014120490d00410d21012004410f4b0d020b411121070ca5020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000ca6020b410021014100210902400240034002402001411f4d0d00410f21010c030b20032005460d012005417f460db0012003200541016a2207490df401200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b024020014120490d00410d21012004410f4b0d020b411221070ca4020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000ca5020b410021014100210902400240034002402001411f4d0d00410f21010c030b20032005460d012005417f460db0012003200541016a2207490df401200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b024020014120490d00410d21012004410f4b0d020b411321070ca3020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000ca4020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450db20120032001490df601200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460db3012003200141016a2207490df701200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210b411421070ca4020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a104120022802282103200228022c210520022802302109410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a20033602000ca5020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000ca3020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450db30120032001490df701200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460db4012003200141016a2207490df801200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210b411521070ca3020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a104120022802282103200228022c210520022802302109410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a20033602000ca4020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000ca2020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450db40120032001490df801200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460db5012003200141016a2207490df901200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210b411621070ca2020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a104120022802282103200228022c210520022802302109410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a20033602000ca3020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000ca1020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450db50120032001490df901200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460db6012003200141016a2207490dfa01200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210b411721070ca1020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a104120022802282103200228022c210520022802302109410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a20033602000ca2020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000ca0020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450db60120032001490dfa01200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460db7012003200141016a2207490dfb01200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210b411821070ca0020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a104120022802282103200228022c210520022802302109410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a20033602000ca1020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c9f020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450db70120032001490dfb01200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460db8012003200141016a2207490dfc01200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210b411921070c9f020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a104120022802282103200228022c210520022802302109410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a20033602000ca0020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c9e020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450db80120032001490dfc01200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460db9012003200141016a2207490dfd01200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210b411a21070c9e020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a104120022802282103200228022c210520022802302109410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a20033602000c9f020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c9d020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450db90120032001490dfd01200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dba012003200141016a2207490dfe01200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210b411b21070c9d020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a104120022802282103200228022c210520022802302109410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a20033602000c9e020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c9c020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dba0120032001490dfe01200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dbb012003200141016a2207490dff01200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210b411c21070c9c020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a104120022802282103200228022c210520022802302109410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a20033602000c9d020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c9b020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dbb0120032001490dff01200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dbc012003200141016a2207490d8002200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210b411d21070c9b020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a104120022802282103200228022c210520022802302109410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a20033602000c9c020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c9a020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dbc0120032001490d8002200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dbd012003200141016a2207490d8102200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210b411e21070c9a020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a104120022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9b020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c99020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dbd0120032001490d8102200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dbe012003200141016a2207490d8202200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210b411f21070c99020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a104120022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9a020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c98020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dbe0120032001490d8202200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dbf012003200141016a2207490d8302200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b41202107024020054120490d00410d21012004410f4b0d040b200aad210b0c98020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a104120022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c99020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c97020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dbf0120032001490d8302200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dc0012003200141016a2207490d8402200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210b412121070c97020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a104120022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c98020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c96020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dc00120032001490d8402200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dc1012003200141016a2207490d8502200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210b412221070c96020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a104120022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c97020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c95020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dc10120032001490d8502200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dc2012003200141016a2207490d8602200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210b412321070c95020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a104120022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c96020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c94020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dc20120032001490d8602200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dc3012003200141016a2207490d8702200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210b412421070c94020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a104120022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c95020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c93020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dc30120032001490d8702200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dc4012003200141016a2207490d8802200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210b412521070c93020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a104120022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c94020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c92020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dc40120032001490d8802200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dc5012003200141016a2207490d8902200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210b412621070c92020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a104120022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c93020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c91020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dc50120032001490d8902200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dc6012003200141016a2207490d8a02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210b412721070c91020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a104120022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c92020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c90020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dc60120032001490d8a02200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dc7012003200141016a2207490d8b02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210b412821070c90020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a104120022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c91020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c8f020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dc70120032001490d8b02200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dc8012003200141016a2207490d8c02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210b412921070c8f020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a104120022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c90020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c8e020b410120036b2107200441026a210141002105410021090240024002400240034002402005411f4d0d00410f21010c030b200720016a4102460d012001450dc80120032001490d8c02200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b024020054120490d002004410f4d0d00410d21010c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c050b20032001460d032001417f460dc9012003200141016a2207490d8d02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d040b200aad210b412a21070c8e020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a104120022802282109200228022c210520022802302103410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c8f020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1041410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c8d020b0240024020032005460d00200441026a21012005417f460dc60120032001490dc701200620056a2d000021092008200136020020090d01412b21074100210a0c8b020b200241013a0048200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241c8006a360238200241086a200241d8006a1041200241336a200241106a2802003600002002200229030837002b2002200229002837031820022002412f6a29000037001f200041053a0004200020022903183700052000410c6a200229001f370000200041013602000c8d020b200041153a000420004101360200200041056a20093a00000c8c020b0240024020032005460d00200441026a21012005417f460dc70120032001490dc801200620056a2d000021092008200136020020090d01412c21074100210a0c8a020b200241013a0048200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241c8006a360238200241086a200241d8006a1041200241336a200241106a2802003600002002200229030837002b2002200229002837031820022002412f6a29000037001f200041053a0004200020022903183700052000410c6a200229001f370000200041013602000c8c020b200041153a000420004101360200200041056a20093a00000c8b020b4100210141002109024002400340410d210a2001411f4b0d0220032005460d012005417f460dc9012003200541016a2207490d8902200620056a2c0000210420082007360200200441ff00712001411f71742009722109200141076a21012007210520044100480d000b200441c00071210502402001411f4b0d0020050dca010b02400240024020014120490d0020050d010b200441ff01714108490d0120014120490d0120050d010c030b20044180017241ff017141f801490d020b412d21070c89020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a10414105210a0b2000200a36020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c8a020b4200210b4100210102400340410e21072001413f4b0d890220032005460d012005417f460dc9012003200541016a2209490dca01200620056a2d0000210420082009360200200441ff0071220aad2001413f71ad86200b84210b200141076a21012009210520044118744118752209417f4c0d000b200941c0007121050240024002402001413f4b0d0020050d010b02400240200141c000490d0020050d010b200141c000490d022009450d020c8b020b200a41ff00470d8a020c010b200b428080808080808080807f427f2001413f712201ad862001413f461b84210b0b412e21070c87020b200241013a0008200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241086a360238200241286a200241d8006a10412002290328210b20022802302101410521070c88020b0240200320056b4104490d00200441056a21012005417b4b0dc90120032001490dca01200620056a280000210920082001360200412f21070c86020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a104120004281808080d000370300200041086a2002290328370200200041106a200241286a41086a2802003602000c88020b0240200320056b4108490d00200441096a2101200541774b0dca0120032001490dcb01200620056a290000210b20082001360200413021070c85020b200241013a0018200241ec006a41013602002002420137025c200241acfdcb003602582002413636023c2002200241386a3602682002200241186a360238200241286a200241d8006a10412002290328210b200041106a2002280230360200200041086a200b37020020004281808080d0003703000c87020b413121070c83020b413221070c82020b413321070c81020b413421070c80020b413521070cff010b413621070cfe010b413721070cfd010b413821070cfc010b413921070cfb010b413a21070cfa010b413b21070cf9010b413c21070cf8010b413d21070cf7010b413e21070cf6010b413f21070cf5010b41c00021070cf4010b41c10021070cf3010b41c20021070cf2010b41c30021070cf1010b41c40021070cf0010b41c50021070cef010b41c60021070cee010b41c70021070ced010b41c80021070cec010b41c90021070ceb010b41ca0021070cea010b41cb0021070ce9010b41cc0021070ce8010b41cd0021070ce7010b41ce0021070ce6010b41cf0021070ce5010b41d00021070ce4010b41d10021070ce3010b41d20021070ce2010b41d30021070ce1010b41d40021070ce0010b41d50021070cdf010b41d60021070cde010b41d70021070cdd010b41d80021070cdc010b41d90021070cdb010b41da0021070cda010b41db0021070cd9010b41dc0021070cd8010b41dd0021070cd7010b41de0021070cd6010b41df0021070cd5010b41e00021070cd4010b41e10021070cd3010b41e20021070cd2010b41e30021070cd1010b41e40021070cd0010b41e50021070ccf010b41e60021070cce010b41e70021070ccd010b41e80021070ccc010b41e90021070ccb010b41ea0021070cca010b41eb0021070cc9010b41ec0021070cc8010b41ed0021070cc7010b41ee0021070cc6010b41ef0021070cc5010b41f00021070cc4010b41f10021070cc3010b41f20021070cc2010b41f30021070cc1010b41f40021070cc0010b41f50021070cbf010b41f60021070cbe010b41f70021070cbd010b41f80021070cbc010b41f90021070cbb010b41fa0021070cba010b41fb0021070cb9010b41fc0021070cb8010b41fd0021070cb7010b41fe0021070cb6010b41ff0021070cb5010b41800121070cb4010b41810121070cb3010b41820121070cb2010b41830121070cb1010b41840121070cb0010b41850121070caf010b41860121070cae010b41870121070cad010b41880121070cac010b41890121070cab010b418a0121070caa010b418b0121070ca9010b418c0121070ca8010b418d0121070ca7010b418e0121070ca6010b418f0121070ca5010b41900121070ca4010b41910121070ca3010b41920121070ca2010b41930121070ca1010b41940121070ca0010b41950121070c9f010b41960121070c9e010b41970121070c9d010b41980121070c9c010b41990121070c9b010b419a0121070c9a010b419b0121070c99010b419c0121070c98010b419d0121070c97010b419e0121070c96010b419f0121070c95010b41a00121070c94010b41a10121070c93010b41a20121070c92010b41a30121070c91010b41a40121070c90010b41a50121070c8f010b41a60121070c8e010b41a70121070c8d010b41a80121070c8c010b41a90121070c8b010b41aa0121070c8a010b41ab0121070c89010b417f200541c0fdcb001059000b2005200341c0fdcb001058000b417f200941c0fdcb001059000b2009200341c0fdcb001058000b417f200941c0fdcb001059000b2009200341c0fdcb001058000b417f200941c0fdcb001059000b2009200341c0fdcb001058000b417f200541016a41c0fdcb001059000b417f200541016a41c0fdcb001059000b41ec80cc00412441c086cc00103f000b103c000b417f200341c0fdcb001059000b200241d8006a41106a28020021012000200436020420004101360200200041106a20013602002000410c6a2009360200200041086a20073602000c7e0b417f200541016a41c0fdcb001059000b417f200541016a41c0fdcb001059000b417f200141c0fdcb001059000b417f200541016a41c0fdcb001059000b417f200541016a41c0fdcb001059000b417f200541016a41c0fdcb001059000b417f200541016a41c0fdcb001059000b417f200541016a41c0fdcb001059000b417f200141c0fdcb001059000b417f200141016a41c0fdcb001059000b417f200141c0fdcb001059000b417f200141016a41c0fdcb001059000b417f200141c0fdcb001059000b417f200141016a41c0fdcb001059000b417f200141c0fdcb001059000b417f200141016a41c0fdcb001059000b417f200141c0fdcb001059000b417f200141016a41c0fdcb001059000b417f200141c0fdcb001059000b417f200141016a41c0fdcb001059000b417f200141c0fdcb001059000b417f200141016a41c0fdcb001059000b417f200141c0fdcb001059000b417f200141016a41c0fdcb001059000b417f200141c0fdcb001059000b417f200141016a41c0fdcb001059000b417f200141c0fdcb001059000b417f200141016a41c0fdcb001059000b417f200141c0fdcb001059000b417f200141016a41c0fdcb001059000b417f200141c0fdcb001059000b417f200141016a41c0fdcb001059000b417f200141c0fdcb001059000b417f200141016a41c0fdcb001059000b417f200141c0fdcb001059000b417f200141016a41c0fdcb001059000b417f200141c0fdcb001059000b417f200141016a41c0fdcb001059000b417f200141c0fdcb001059000b417f200141016a41c0fdcb001059000b417f200141c0fdcb001059000b417f200141016a41c0fdcb001059000b417f200141c0fdcb001059000b417f200141016a41c0fdcb001059000b417f200141c0fdcb001059000b417f200141016a41c0fdcb001059000b417f200141c0fdcb001059000b417f200141016a41c0fdcb001059000b417f200141c0fdcb001059000b417f200141016a41c0fdcb001059000b417f200141c0fdcb001059000b417f200141016a41c0fdcb001059000b417f200141c0fdcb001059000b417f200141016a41c0fdcb001059000b417f200141c0fdcb001059000b2001200341c0fdcb001058000b417f200141c0fdcb001059000b2001200341c0fdcb001058000b417f200541016a41c0fdcb001059000b2009417f2001411f7174722109412d21070c3f0b417f200541016a41c0fdcb001059000b200541016a200341c0fdcb001058000b2005200141c0fdcb001059000b2001200341c0fdcb001058000b2005200141c0fdcb001059000b2001200341c0fdcb001058000b200541016a200341c0fdcb001058000b200541016a200341c0fdcb001058000b2003200741c0fdcb001058000b200541016a200341c0fdcb001058000b200541016a200341c0fdcb001058000b200541016a200341c0fdcb001058000b200541016a200341c0fdcb001058000b200541016a200341c0fdcb001058000b200541016a200341c0fdcb001058000b200541016a200341c0fdcb001058000b2001200341c0fdcb001058000b200141016a200341c0fdcb001058000b2001200341c0fdcb001058000b200141016a200341c0fdcb001058000b2001200341c0fdcb001058000b200141016a200341c0fdcb001058000b2001200341c0fdcb001058000b200141016a200341c0fdcb001058000b2001200341c0fdcb001058000b200141016a200341c0fdcb001058000b2001200341c0fdcb001058000b200141016a200341c0fdcb001058000b2001200341c0fdcb001058000b200141016a200341c0fdcb001058000b2001200341c0fdcb001058000b200141016a200341c0fdcb001058000b2001200341c0fdcb001058000b200141016a200341c0fdcb001058000b2001200341c0fdcb001058000b200141016a200341c0fdcb001058000b2001200341c0fdcb001058000b200141016a200341c0fdcb001058000b2001200341c0fdcb001058000b200141016a200341c0fdcb001058000b2001200341c0fdcb001058000b200141016a200341c0fdcb001058000b2001200341c0fdcb001058000b200141016a200341c0fdcb001058000b2001200341c0fdcb001058000b200141016a200341c0fdcb001058000b2001200341c0fdcb001058000b200141016a200341c0fdcb001058000b2001200341c0fdcb001058000b200141016a200341c0fdcb001058000b2001200341c0fdcb001058000b200141016a200341c0fdcb001058000b2001200341c0fdcb001058000b200141016a200341c0fdcb001058000b2001200341c0fdcb001058000b200141016a200341c0fdcb001058000b2001200341c0fdcb001058000b200141016a200341c0fdcb001058000b2001200341c0fdcb001058000b200141016a200341c0fdcb001058000b2001200341c0fdcb001058000b200141016a200341c0fdcb001058000b200541016a200341c0fdcb001058000b20004100360200200041106a200b3703002000410c6a2009360200200041096a200a3a0000200041086a20073a00000c020b0b200020073a0004200020022f00183b000520004101360200200041106a2001360200200041086a200b370200200041076a2002411a6a2d00003a00000b200241f0006a24000bbb0101027f0240200041046a2802002001470d000240024002400240200141016a22022001490d00200141017422032002200320024b1b220241ffffffff00712002470d00200241047422024100480d00024020010d0020020d02410821030c040b20002802002103200141047422012002460d03024020010d0020020d02410821030c040b20032001200210372203450d020c030b103e000b2002103322030d010b103c000b20002003360200200041046a20024104763602000b0bd30101017f230041106b22022400024002400240024020002d00000e03010200010b2002200128021841a9fecb00410b2001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c020b2002200128021841b4fecb00410c2001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c010b2002200128021841c0fecb00410d2001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040b200241106a240020000bff06020c7f017e230041e0006b220224004100210341002104024002400240024002400240034002402003411f4d0d00410f21030c060b20012802082205200128020c2206460d04200641016a22072006490d0120052007490d03200128020020066a2d000021062001200736020c200641ff00712003411f71742004722104200341076a21032006418001710d000b024020034120490d00410d21032006410f4b0d050b410021082002410036021020024204370308024002402004450d00410421094100210a0340200a41016a210a4100210341002105024003404101210b02402003411f4d0d00410f21030c020b024002402001280208220c200128020c2206460d00200641016a22072006490d08200c20074f0d012007200c41c0fdcb001058000b4101210b200241013a00472002410136025c2002420137024c200241acfdcb003602482002413636023c2002200241386a3602582002200241c7006a360238200241286a200241c8006a10414100210d410521030c020b200128020020066a2d000021062001200736020c200641ff00712003411f71742005722105200341076a21032006418001710d000b024020034120490d00410d21032006410f4b0d010b2005410876210d4100210b200521030b200241186a41086a200241286a41086a28020036020020022002290328370318200d410874200341ff0171722103200b0d0202402008200228020c470d00200241086a2008410110860120022802082109200228021021080b200920084102746a20033602002002200841016a2208360210200a2004470d000b0b20002002290308370204200041003602002000410c6a200241106a2802003602000c060b2000200336020420004101360200200041086a2002290318370200200041106a200241186a41086a280200360200200228020c41ffffffff0371450d05200910350c050b417f200741c0fdcb001059000b417f200741c0fdcb001059000b2007200541c0fdcb001058000b200241013a0008200241dc006a41013602002002420137024c200241acfdcb003602482002413636023c2002200241386a3602582002200241086a360238200241286a200241c8006a1041410521030b200241186a41086a200241286a41086a280200220136020020022002290328220e37031820002003360204200041086a200e370200200041106a2001360200200041013602000b200241e0006a24000b9bee0202097f017e230041106b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000eac01000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa01ab01000b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dad01200441017422062005200620054b1b22064100480dad010240024020040d00024020060d00410121050c020b2006103322050d010cb9010b2002280204210520042006460d0020052004200610372205450db8010b20022005360204200241086a20063602002002410c6a28020021040b200520046a41003a00002002410c6a200441016a3602000cab010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dac01200441017422062005200620054b1b22064100480dac010240024020040d00024020060d00410121050c020b200610332205450db8010c010b2002280204210520042006460d0020052004200610372205450db7010b20022005360204200241086a20063602002002410c6a28020021040b200520046a41013a00002002410c6a200441016a3602000caa010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490dab01200441017422082005200820054b1b22084100480dab010240024020040d00024020080d00410121050c020b200810332205450db7010c010b2006280200210520042008460d0020052004200810372205450db6010b20022005360204200241086a20083602002002410c6a28020021040b200520046a41023a00002002410c6a200441016a220436020002400240200241086a2802002004460d00200628020021050c010b200441016a22052004490dab01200441017422082005200820054b1b22084100480dab010240024020040d00024020080d00410121050c020b200810332205450db7010c010b2006280200210520042008460d0020052004200810372205450db6010b20022005360204200241086a20083602002002410c6a28020021040b200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00002002410c6a200441016a3602000ca9010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490daa01200441017422082005200820054b1b22084100480daa010240024020040d00024020080d00410121050c020b200810332205450db6010c010b2006280200210520042008460d0020052004200810372205450db5010b20022005360204200241086a20083602002002410c6a28020021040b200520046a41033a00002002410c6a200441016a220436020002400240200241086a2802002004460d00200628020021050c010b200441016a22052004490daa01200441017422082005200820054b1b22084100480daa010240024020040d00024020080d00410121050c020b200810332205450db6010c010b2006280200210520042008460d0020052004200810372205450db5010b20022005360204200241086a20083602002002410c6a28020021040b200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00002002410c6a200441016a3602000ca8010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490da901200441017422082005200820054b1b22084100480da9010240024020040d00024020080d00410121050c020b200810332205450db5010c010b2006280200210520042008460d0020052004200810372205450db4010b20022005360204200241086a20083602002002410c6a28020021040b200520046a41043a00002002410c6a200441016a220436020002400240200241086a2802002004460d00200628020021050c010b200441016a22052004490da901200441017422082005200820054b1b22084100480da9010240024020040d00024020080d00410121050c020b200810332205450db5010c010b2006280200210520042008460d0020052004200810372205450db4010b20022005360204200241086a20083602002002410c6a28020021040b200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00002002410c6a200441016a3602000ca7010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da801200441017422062005200620054b1b22064100480da8010240024020040d00024020060d00410121050c020b200610332205450db4010c010b2002280204210520042006460d0020052004200610372205450db3010b20022005360204200241086a20063602002002410c6a28020021040b200520046a41053a00002002410c6a200441016a3602000ca6010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da701200441017422062005200620054b1b22064100480da7010240024020040d00024020060d00410121050c020b200610332205450db3010c010b2002280204210520042006460d0020052004200610372205450db2010b20022005360204200241086a20063602002002410c6a28020021040b200520046a410b3a00002002410c6a200441016a3602000ca5010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490da601200441017422072006200720064b1b22074100480da6010240024020040d00024020070d00410121060c020b200710332206450db2010c010b2009280200210620042007460d0020062004200710372206450db1010b20022006360204200241086a20073602002002410c6a28020021040b200620046a410c3a00002002410c6a2208200441016a2204360200200241086a210a034002400240200a2802002004460d00200928020021060c010b200441016a22062004490da701200441017422072006200720064b1b22074100480da7010240024020040d00024020070d00410121060c020b200710332206450db3010c010b2009280200210620042007460d0020062004200710372206450db2010b20022006360204200a2007360200200828020021040b200620046a200541807f72200541ff0071200541077622061b3a00002008200441016a22043602002006210520060d000ca5010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490da501200441017422072006200720064b1b22074100480da5010240024020040d00024020070d00410121060c020b200710332206450db1010c010b2009280200210620042007460d0020062004200710372206450db0010b20022006360204200241086a20073602002002410c6a28020021040b200620046a410d3a00002002410c6a2208200441016a2204360200200241086a210a034002400240200a2802002004460d00200928020021060c010b200441016a22062004490da601200441017422072006200720064b1b22074100480da6010240024020040d00024020070d00410121060c020b200710332206450db2010c010b2009280200210620042007460d0020062004200710372206450db1010b20022006360204200a2007360200200828020021040b200620046a200541807f72200541ff0071200541077622061b3a00002008200441016a22043602002006210520060d000ca4010b0b200241046a210902400240200241086a2802002002410c6a2802002204460d00200928020021050c010b200441016a22052004490da401200441017422062005200620054b1b22064100480da4010240024020040d00024020060d00410121050c020b200610332205450db0010c010b2009280200210520042006460d0020052004200610372205450daf010b20022005360204200241086a20063602002002410c6a28020021040b200520046a410e3a00002002410c6a2208200441016a360200200320012802042204280204220520042802002204200420054102746a200210a4072003210420032d0000411f470dab012008280200210420012802042802082105200241086a210a034002400240200a2802002004460d00200928020021060c010b200441016a22062004490da501200441017422072006200720064b1b22074100480da5010240024020040d00024020070d00410121060c020b200710332206450db1010c010b2009280200210620042007460d0020062004200710372206450db0010b20022006360204200a2007360200200828020021040b200620046a200541807f72200541ff0071200541077622061b3a00002008200441016a22043602002006210520060d000ca3010b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da301200441017422062005200620054b1b22064100480da3010240024020040d00024020060d00410121050c020b200610332205450daf010c010b2002280204210520042006460d0020052004200610372205450dae010b20022005360204200241086a20063602002002410c6a28020021040b200520046a410f3a00002002410c6a200441016a3602000ca1010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490da201200441017422072006200720064b1b22074100480da2010240024020040d00024020070d00410121060c020b200710332206450dae010c010b2009280200210620042007460d0020062004200710372206450dad010b20022006360204200241086a20073602002002410c6a28020021040b200620046a41103a00002002410c6a2208200441016a2204360200200241086a210a034002400240200a2802002004460d00200928020021060c010b200441016a22062004490da301200441017422072006200720064b1b22074100480da3010240024020040d00024020070d00410121060c020b200710332206450daf010c010b2009280200210620042007460d0020062004200710372206450dae010b20022006360204200a2007360200200828020021040b200620046a200541807f72200541ff0071200541077622061b3a00002008200441016a22043602002006210520060d000ca1010b0b200241046a2109200141046a280200210520012d0001210b02400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490da101200441017422072006200720064b1b22074100480da1010240024020040d00024020070d00410121060c020b200710332206450dad010c010b2009280200210620042007460d0020062004200710372206450dac010b20022006360204200241086a20073602002002410c6a28020021040b200620046a41113a00002002410c6a2208200441016a2204360200200241086a210a034002400240200a2802002004460d00200928020021060c010b200441016a22062004490da201200441017422072006200720064b1b22074100480da2010240024020040d00024020070d00410121060c020b200710332206450dae010c010b2009280200210620042007460d0020062004200710372206450dad010b20022006360204200a2007360200200828020021040b200620046a200541807f72200541ff0071200541077622061b3a00002008200441016a22043602002006210520060d000b02400240200241086a2802002004460d00200928020021050c010b200441016a22052004490da101200441017422062005200620054b1b22064100480da1010240024020040d00024020060d00410121050c020b200610332205450dad010c010b2009280200210520042006460d0020052004200610372205450dac010b20022005360204200241086a20063602002002410c6a28020021040b200520046a200b3a00002002410c6a200441016a3602000c9f010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da001200441017422062005200620054b1b22064100480da0010240024020040d00024020060d00410121050c020b200610332205450dac010c010b2002280204210520042006460d0020052004200610372205450dab010b20022005360204200241086a20063602002002410c6a28020021040b200520046a411a3a00002002410c6a200441016a3602000c9e010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9f01200441017422062005200620054b1b22064100480d9f010240024020040d00024020060d00410121050c020b200610332205450dab010c010b2002280204210520042006460d0020052004200610372205450daa010b20022005360204200241086a20063602002002410c6a28020021040b200520046a411b3a00002002410c6a200441016a3602000c9d010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9e01200441017422072006200720064b1b22074100480d9e010240024020040d00024020070d00410121060c020b200710332206450daa010c010b2009280200210620042007460d0020062004200710372206450da9010b20022006360204200241086a20073602002002410c6a28020021040b200620046a41203a00002002410c6a2208200441016a2204360200200241086a210a034002400240200a2802002004460d00200928020021060c010b200441016a22062004490d9f01200441017422072006200720064b1b22074100480d9f010240024020040d00024020070d00410121060c020b200710332206450dab010c010b2009280200210620042007460d0020062004200710372206450daa010b20022006360204200a2007360200200828020021040b200620046a200541807f72200541ff0071200541077622061b3a00002008200441016a22043602002006210520060d000c9d010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9d01200441017422072006200720064b1b22074100480d9d010240024020040d00024020070d00410121060c020b200710332206450da9010c010b2009280200210620042007460d0020062004200710372206450da8010b20022006360204200241086a20073602002002410c6a28020021040b200620046a41213a00002002410c6a2208200441016a2204360200200241086a210a034002400240200a2802002004460d00200928020021060c010b200441016a22062004490d9e01200441017422072006200720064b1b22074100480d9e010240024020040d00024020070d00410121060c020b200710332206450daa010c010b2009280200210620042007460d0020062004200710372206450da9010b20022006360204200a2007360200200828020021040b200620046a200541807f72200541ff0071200541077622061b3a00002008200441016a22043602002006210520060d000c9c010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9c01200441017422072006200720064b1b22074100480d9c010240024020040d00024020070d00410121060c020b200710332206450da8010c010b2009280200210620042007460d0020062004200710372206450da7010b20022006360204200241086a20073602002002410c6a28020021040b200620046a41223a00002002410c6a2208200441016a2204360200200241086a210a034002400240200a2802002004460d00200928020021060c010b200441016a22062004490d9d01200441017422072006200720064b1b22074100480d9d010240024020040d00024020070d00410121060c020b200710332206450da9010c010b2009280200210620042007460d0020062004200710372206450da8010b20022006360204200a2007360200200828020021040b200620046a200541807f72200541ff0071200541077622061b3a00002008200441016a22043602002006210520060d000c9b010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9b01200441017422072006200720064b1b22074100480d9b010240024020040d00024020070d00410121060c020b200710332206450da7010c010b2009280200210620042007460d0020062004200710372206450da6010b20022006360204200241086a20073602002002410c6a28020021040b200620046a41233a00002002410c6a2208200441016a2204360200200241086a210a034002400240200a2802002004460d00200928020021060c010b200441016a22062004490d9c01200441017422072006200720064b1b22074100480d9c010240024020040d00024020070d00410121060c020b200710332206450da8010c010b2009280200210620042007460d0020062004200710372206450da7010b20022006360204200a2007360200200828020021040b200620046a200541807f72200541ff0071200541077622061b3a00002008200441016a22043602002006210520060d000c9a010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9a01200441017422072006200720064b1b22074100480d9a010240024020040d00024020070d00410121060c020b200710332206450da6010c010b2009280200210620042007460d0020062004200710372206450da5010b20022006360204200241086a20073602002002410c6a28020021040b200620046a41243a00002002410c6a2208200441016a2204360200200241086a210a034002400240200a2802002004460d00200928020021060c010b200441016a22062004490d9b01200441017422072006200720064b1b22074100480d9b010240024020040d00024020070d00410121060c020b200710332206450da7010c010b2009280200210620042007460d0020062004200710372206450da6010b20022006360204200a2007360200200828020021040b200620046a200541807f72200541ff0071200541077622061b3a00002008200441016a22043602002006210520060d000c99010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9901200441017422082007200820074b1b22084100480d99010240024020040d00024020080d00410121070c020b200810332207450da5010c010b200a280200210720042008460d0020072004200810372207450da4010b20022007360204200241086a20083602002002410c6a28020021040b200720046a41283a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d9a01200441017422082007200820074b1b22084100480d9a010240024020040d00024020080d00410121070c020b200810332207450da6010c010b200a280200210720042008460d0020072004200810372207450da5010b20022007360204200b2008360200200928020021040b200720046a200541807f72200541ff0071200541077622071b3a00002009200441016a22043602002007210520070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021050c010b200441016a22052004490d9a01200441017422072005200720054b1b22074100480d9a010240024020040d00024020070d00410121050c020b200710332205450da6010c010b200a280200210520042007460d0020052004200710372205450da5010b2002200536020420082007360200200928020021040b200520046a200641807f72200641ff0071200641077622051b3a00002009200441016a22043602002005210620050d000c98010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9801200441017422082007200820074b1b22084100480d98010240024020040d00024020080d00410121070c020b200810332207450da4010c010b200a280200210720042008460d0020072004200810372207450da3010b20022007360204200241086a20083602002002410c6a28020021040b200720046a41293a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d9901200441017422082007200820074b1b22084100480d99010240024020040d00024020080d00410121070c020b200810332207450da5010c010b200a280200210720042008460d0020072004200810372207450da4010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d9901200441017422072006200720064b1b22074100480d99010240024020040d00024020070d00410121060c020b200710332206450da5010c010b200a280200210620042007460d0020062004200710372206450da4010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c97010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9701200441017422082007200820074b1b22084100480d97010240024020040d00024020080d00410121070c020b200810332207450da3010c010b200a280200210720042008460d0020072004200810372207450da2010b20022007360204200241086a20083602002002410c6a28020021040b200720046a412a3a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d9801200441017422082007200820074b1b22084100480d98010240024020040d00024020080d00410121070c020b200810332207450da4010c010b200a280200210720042008460d0020072004200810372207450da3010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d9801200441017422072006200720064b1b22074100480d98010240024020040d00024020070d00410121060c020b200710332206450da4010c010b200a280200210620042007460d0020062004200710372206450da3010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c96010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9601200441017422082007200820074b1b22084100480d96010240024020040d00024020080d00410121070c020b200810332207450da2010c010b200a280200210720042008460d0020072004200810372207450da1010b20022007360204200241086a20083602002002410c6a28020021040b200720046a412b3a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d9701200441017422082007200820074b1b22084100480d97010240024020040d00024020080d00410121070c020b200810332207450da3010c010b200a280200210720042008460d0020072004200810372207450da2010b20022007360204200b2008360200200928020021040b200720046a200541807f72200541ff0071200541077622071b3a00002009200441016a22043602002007210520070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021050c010b200441016a22052004490d9701200441017422072005200720054b1b22074100480d97010240024020040d00024020070d00410121050c020b200710332205450da3010c010b200a280200210520042007460d0020052004200710372205450da2010b2002200536020420082007360200200928020021040b200520046a200641807f72200641ff0071200641077622051b3a00002009200441016a22043602002005210620050d000c95010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9501200441017422082007200820074b1b22084100480d95010240024020040d00024020080d00410121070c020b200810332207450da1010c010b200a280200210720042008460d0020072004200810372207450da0010b20022007360204200241086a20083602002002410c6a28020021040b200720046a412c3a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d9601200441017422082007200820074b1b22084100480d96010240024020040d00024020080d00410121070c020b200810332207450da2010c010b200a280200210720042008460d0020072004200810372207450da1010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d9601200441017422072006200720064b1b22074100480d96010240024020040d00024020070d00410121060c020b200710332206450da2010c010b200a280200210620042007460d0020062004200710372206450da1010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c94010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9501200441017422082007200820074b1b22084100480d95010240024020040d00024020080d00410121070c020b200810332207450da0010c010b200a280200210720042008460d0020072004200810372207450d9f010b20022007360204200241086a20083602002002410c6a28020021040b200720046a412d3a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d9601200441017422082007200820074b1b22084100480d96010240024020040d00024020080d00410121070c020b2008103322070d010c9e010b200a280200210720042008460d0020072004200810372207450d9c010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d9601200441017422072006200720064b1b22074100480d96010240024020040d00024020070d00410121060c020b2007103322060d010c9e010b200a280200210620042007460d0020062004200710372206450d9c010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c93010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9401200441017422082007200820074b1b22084100480d94010240024020040d00024020080d00410121070c020b2008103322070d010c9c010b200a280200210720042008460d0020072004200810372207450d9a010b20022007360204200241086a20083602002002410c6a28020021040b200720046a412e3a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d9501200441017422082007200820074b1b22084100480d95010240024020040d00024020080d00410121070c020b2008103322070d010c9d010b200a280200210720042008460d0020072004200810372207450d9b010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d9501200441017422072006200720064b1b22074100480d95010240024020040d00024020070d00410121060c020b2007103322060d010c9d010b200a280200210620042007460d0020062004200710372206450d9b010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c92010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9301200441017422082007200820074b1b22084100480d93010240024020040d00024020080d00410121070c020b2008103322070d010c9b010b200a280200210720042008460d0020072004200810372207450d99010b20022007360204200241086a20083602002002410c6a28020021040b200720046a412f3a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d9401200441017422082007200820074b1b22084100480d94010240024020040d00024020080d00410121070c020b2008103322070d010c9c010b200a280200210720042008460d0020072004200810372207450d9a010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d9401200441017422072006200720064b1b22074100480d94010240024020040d00024020070d00410121060c020b2007103322060d010c9c010b200a280200210620042007460d0020062004200710372206450d9a010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c91010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9201200441017422082007200820074b1b22084100480d92010240024020040d00024020080d00410121070c020b2008103322070d010c9a010b200a280200210720042008460d0020072004200810372207450d98010b20022007360204200241086a20083602002002410c6a28020021040b200720046a41303a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d9301200441017422082007200820074b1b22084100480d93010240024020040d00024020080d00410121070c020b2008103322070d010c9b010b200a280200210720042008460d0020072004200810372207450d99010b20022007360204200b2008360200200928020021040b200720046a200541807f72200541ff0071200541077622071b3a00002009200441016a22043602002007210520070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021050c010b200441016a22052004490d9301200441017422072005200720054b1b22074100480d93010240024020040d00024020070d00410121050c020b2007103322050d010c9b010b200a280200210520042007460d0020052004200710372205450d99010b2002200536020420082007360200200928020021040b200520046a200641807f72200641ff0071200641077622051b3a00002009200441016a22043602002005210620050d000c90010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9101200441017422082007200820074b1b22084100480d91010240024020040d00024020080d00410121070c020b2008103322070d010c99010b200a280200210720042008460d0020072004200810372207450d97010b20022007360204200241086a20083602002002410c6a28020021040b200720046a41313a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d9201200441017422082007200820074b1b22084100480d92010240024020040d00024020080d00410121070c020b2008103322070d010c9a010b200a280200210720042008460d0020072004200810372207450d98010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d9201200441017422072006200720064b1b22074100480d92010240024020040d00024020070d00410121060c020b2007103322060d010c9a010b200a280200210620042007460d0020062004200710372206450d98010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c8f010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9001200441017422082007200820074b1b22084100480d90010240024020040d00024020080d00410121070c020b2008103322070d010c98010b200a280200210720042008460d0020072004200810372207450d96010b20022007360204200241086a20083602002002410c6a28020021040b200720046a41323a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d9101200441017422082007200820074b1b22084100480d91010240024020040d00024020080d00410121070c020b2008103322070d010c99010b200a280200210720042008460d0020072004200810372207450d97010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d9101200441017422072006200720064b1b22074100480d91010240024020040d00024020070d00410121060c020b2007103322060d010c99010b200a280200210620042007460d0020062004200710372206450d97010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c8e010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8f01200441017422082007200820074b1b22084100480d8f010240024020040d00024020080d00410121070c020b2008103322070d010c97010b200a280200210720042008460d0020072004200810372207450d95010b20022007360204200241086a20083602002002410c6a28020021040b200720046a41333a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d9001200441017422082007200820074b1b22084100480d90010240024020040d00024020080d00410121070c020b2008103322070d010c98010b200a280200210720042008460d0020072004200810372207450d96010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d9001200441017422072006200720064b1b22074100480d90010240024020040d00024020070d00410121060c020b2007103322060d010c98010b200a280200210620042007460d0020062004200710372206450d96010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c8d010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8e01200441017422082007200820074b1b22084100480d8e010240024020040d00024020080d00410121070c020b2008103322070d010c96010b200a280200210720042008460d0020072004200810372207450d94010b20022007360204200241086a20083602002002410c6a28020021040b200720046a41343a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d8f01200441017422082007200820074b1b22084100480d8f010240024020040d00024020080d00410121070c020b2008103322070d010c97010b200a280200210720042008460d0020072004200810372207450d95010b20022007360204200b2008360200200928020021040b200720046a200541807f72200541ff0071200541077622071b3a00002009200441016a22043602002007210520070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021050c010b200441016a22052004490d8f01200441017422072005200720054b1b22074100480d8f010240024020040d00024020070d00410121050c020b2007103322050d010c97010b200a280200210520042007460d0020052004200710372205450d95010b2002200536020420082007360200200928020021040b200520046a200641807f72200641ff0071200641077622051b3a00002009200441016a22043602002005210620050d000c8c010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8d01200441017422082007200820074b1b22084100480d8d010240024020040d00024020080d00410121070c020b2008103322070d010c95010b200a280200210720042008460d0020072004200810372207450d93010b20022007360204200241086a20083602002002410c6a28020021040b200720046a41353a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d8e01200441017422082007200820074b1b22084100480d8e010240024020040d00024020080d00410121070c020b2008103322070d010c96010b200a280200210720042008460d0020072004200810372207450d94010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d8e01200441017422072006200720064b1b22074100480d8e010240024020040d00024020070d00410121060c020b2007103322060d010c96010b200a280200210620042007460d0020062004200710372206450d94010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c8b010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8c01200441017422082007200820074b1b22084100480d8c010240024020040d00024020080d00410121070c020b2008103322070d010c94010b200a280200210720042008460d0020072004200810372207450d92010b20022007360204200241086a20083602002002410c6a28020021040b200720046a41363a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d8d01200441017422082007200820074b1b22084100480d8d010240024020040d00024020080d00410121070c020b2008103322070d010c95010b200a280200210720042008460d0020072004200810372207450d93010b20022007360204200b2008360200200928020021040b200720046a200541807f72200541ff0071200541077622071b3a00002009200441016a22043602002007210520070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021050c010b200441016a22052004490d8d01200441017422072005200720054b1b22074100480d8d010240024020040d00024020070d00410121050c020b2007103322050d010c95010b200a280200210520042007460d0020052004200710372205450d93010b2002200536020420082007360200200928020021040b200520046a200641807f72200641ff0071200641077622051b3a00002009200441016a22043602002005210620050d000c8a010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8b01200441017422082007200820074b1b22084100480d8b010240024020040d00024020080d00410121070c020b2008103322070d010c93010b200a280200210720042008460d0020072004200810372207450d91010b20022007360204200241086a20083602002002410c6a28020021040b200720046a41373a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d8c01200441017422082007200820074b1b22084100480d8c010240024020040d00024020080d00410121070c020b2008103322070d010c94010b200a280200210720042008460d0020072004200810372207450d92010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d8c01200441017422072006200720064b1b22074100480d8c010240024020040d00024020070d00410121060c020b2007103322060d010c94010b200a280200210620042007460d0020062004200710372206450d92010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c89010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8a01200441017422082007200820074b1b22084100480d8a010240024020040d00024020080d00410121070c020b2008103322070d010c92010b200a280200210720042008460d0020072004200810372207450d90010b20022007360204200241086a20083602002002410c6a28020021040b200720046a41383a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d8b01200441017422082007200820074b1b22084100480d8b010240024020040d00024020080d00410121070c020b2008103322070d010c93010b200a280200210720042008460d0020072004200810372207450d91010b20022007360204200b2008360200200928020021040b200720046a200541807f72200541ff0071200541077622071b3a00002009200441016a22043602002007210520070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021050c010b200441016a22052004490d8b01200441017422072005200720054b1b22074100480d8b010240024020040d00024020070d00410121050c020b2007103322050d010c93010b200a280200210520042007460d0020052004200710372205450d91010b2002200536020420082007360200200928020021040b200520046a200641807f72200641ff0071200641077622051b3a00002009200441016a22043602002005210620050d000c88010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8901200441017422082007200820074b1b22084100480d89010240024020040d00024020080d00410121070c020b2008103322070d010c91010b200a280200210720042008460d0020072004200810372207450d8f010b20022007360204200241086a20083602002002410c6a28020021040b200720046a41393a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d8a01200441017422082007200820074b1b22084100480d8a010240024020040d00024020080d00410121070c020b2008103322070d010c92010b200a280200210720042008460d0020072004200810372207450d90010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d8a01200441017422072006200720064b1b22074100480d8a010240024020040d00024020070d00410121060c020b2007103322060d010c92010b200a280200210620042007460d0020062004200710372206450d90010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c87010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8801200441017422082007200820074b1b22084100480d88010240024020040d00024020080d00410121070c020b2008103322070d010c90010b200a280200210720042008460d0020072004200810372207450d8e010b20022007360204200241086a20083602002002410c6a28020021040b200720046a413a3a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d8901200441017422082007200820074b1b22084100480d89010240024020040d00024020080d00410121070c020b2008103322070d010c91010b200a280200210720042008460d0020072004200810372207450d8f010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d8901200441017422072006200720064b1b22074100480d89010240024020040d00024020070d00410121060c020b2007103322060d010c91010b200a280200210620042007460d0020062004200710372206450d8f010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c86010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8701200441017422082007200820074b1b22084100480d87010240024020040d00024020080d00410121070c020b2008103322070d010c8f010b200a280200210720042008460d0020072004200810372207450d8d010b20022007360204200241086a20083602002002410c6a28020021040b200720046a413b3a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d8801200441017422082007200820074b1b22084100480d88010240024020040d00024020080d00410121070c020b2008103322070d010c90010b200a280200210720042008460d0020072004200810372207450d8e010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d8801200441017422072006200720064b1b22074100480d88010240024020040d00024020070d00410121060c020b2007103322060d010c90010b200a280200210620042007460d0020062004200710372206450d8e010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c85010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8601200441017422082007200820074b1b22084100480d86010240024020040d00024020080d00410121070c020b2008103322070d010c8e010b200a280200210720042008460d0020072004200810372207450d8c010b20022007360204200241086a20083602002002410c6a28020021040b200720046a413c3a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d8701200441017422082007200820074b1b22084100480d87010240024020040d00024020080d00410121070c020b2008103322070d010c8f010b200a280200210720042008460d0020072004200810372207450d8d010b20022007360204200b2008360200200928020021040b200720046a200641807f72200641ff0071200641077622071b3a00002009200441016a22043602002007210620070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021060c010b200441016a22062004490d8701200441017422072006200720064b1b22074100480d87010240024020040d00024020070d00410121060c020b2007103322060d010c8f010b200a280200210620042007460d0020062004200710372206450d8d010b2002200636020420082007360200200928020021040b200620046a200541807f72200541ff0071200541077622061b3a00002009200441016a22043602002006210520060d000c84010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8501200441017422082007200820074b1b22084100480d85010240024020040d00024020080d00410121070c020b2008103322070d010c8d010b200a280200210720042008460d0020072004200810372207450d8b010b20022007360204200241086a20083602002002410c6a28020021040b200720046a413d3a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d8601200441017422082007200820074b1b22084100480d86010240024020040d00024020080d00410121070c020b2008103322070d010c8e010b200a280200210720042008460d0020072004200810372207450d8c010b20022007360204200b2008360200200928020021040b200720046a200541807f72200541ff0071200541077622071b3a00002009200441016a22043602002007210520070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021050c010b200441016a22052004490d8601200441017422072005200720054b1b22074100480d86010240024020040d00024020070d00410121050c020b2007103322050d010c8e010b200a280200210520042007460d0020052004200710372205450d8c010b2002200536020420082007360200200928020021040b200520046a200641807f72200641ff0071200641077622051b3a00002009200441016a22043602002005210620050d000c83010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8401200441017422082007200820074b1b22084100480d84010240024020040d00024020080d00410121070c020b2008103322070d010c8c010b200a280200210720042008460d0020072004200810372207450d8a010b20022007360204200241086a20083602002002410c6a28020021040b200720046a413e3a00002002410c6a2209200441016a2204360200200241086a210b034002400240200b2802002004460d00200a28020021070c010b200441016a22072004490d8501200441017422082007200820074b1b22084100480d85010240024020040d00024020080d00410121070c020b2008103322070d010c8d010b200a280200210720042008460d0020072004200810372207450d8b010b20022007360204200b2008360200200928020021040b200720046a200541807f72200541ff0071200541077622071b3a00002009200441016a22043602002007210520070d000b200241086a21082002410c6a210903400240024020082802002004460d00200a28020021050c010b200441016a22052004490d8501200441017422072005200720054b1b22074100480d85010240024020040d00024020070d00410121050c020b2007103322050d010c8d010b200a280200210520042007460d0020052004200710372205450d8b010b2002200536020420082007360200200928020021040b200520046a200641807f72200641ff0071200641077622051b3a00002009200441016a22043602002005210620050d000c82010b0b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d8301200441017422082005200820054b1b22084100480d83010240024020040d00024020080d00410121050c020b2008103322050d010c8b010b2006280200210520042008460d0020052004200810372205450d89010b20022005360204200241086a20083602002002410c6a28020021040b200520046a413f3a00002002410c6a200441016a220436020002400240200241086a2802002004460d00200628020021050c010b200441016a22052004490d8301200441017422082005200820054b1b22084100480d83010240024020040d00024020080d00410121050c020b2008103322050d010c8b010b2006280200210520042008460d0020052004200810372205450d89010b20022005360204200241086a20083602002002410c6a28020021040b200520046a20073a00002002410c6a200441016a3602000c80010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d8201200441017422082005200820054b1b22084100480d82010240024020040d00024020080d00410121050c020b2008103322050d010c8a010b2006280200210520042008460d0020052004200810372205450d88010b20022005360204200241086a20083602002002410c6a28020021040b200520046a41c0003a00002002410c6a200441016a220436020002400240200241086a2802002004460d00200628020021050c010b200441016a22052004490d8301200441017422082005200820054b1b22084100480d83010240024020040d00024020080d00410121050c020b2008103322050d010c8a010b2006280200210520042008460d0020052004200810372205450d88010b20022005360204200241086a20083602002002410c6a28020021040b200520046a20073a00002002410c6a200441016a3602000c7f0b200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8201200441017422072005200720054b1b22074100480d82010240024020040d00024020070d00410121050c020b2007103322050d010c89010b2002280204210520042007460d0020052004200710372205450d84010b20022005360204200241086a20073602002002410c6a28020021040b200520046a41c1003a00002002410c6a200441016a36020020032006200210a5072003210420032d0000411f470d87010c7e0b200141086a290300210c02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8101200441017422062005200620054b1b22064100480d81010240024020040d00024020060d00410121050c020b2006103322050d010c88010b2002280204210520042006460d0020052004200610372205450d83010b20022005360204200241086a20063602002002410c6a28020021040b200520046a41c2003a00002002410c6a200441016a3602002003200c200210a6072003210420032d0000411f470d86010c7d0b200241046a2106200141046a280200210802400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d8001200441017422072005200720054b1b22074100480d80010240024020040d00024020070d00410121050c020b2007103322050d010c87010b2006280200210520042007460d0020052004200710372205450d82010b20022005360204200241086a20073602002002410c6a28020021040b200520046a41c3003a00002002410c6a200441016a220436020002400240200241086a280200220720046b4104490d00200628020021050c010b200441046a22052004490d8001200741017422042005200420054b1b22044100480d80010240024020070d00024020040d00410121050c020b2004103322050d010c87010b2006280200210520072004460d0020052007200410372205450d82010b20022005360204200241086a20043602002002410c6a28020021040b200520046a20083600002002410c6a200441046a3602000c7c0b200241046a2106200141086a290300210c02400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d7f200441017422072005200720054b1b22074100480d7f0240024020040d00024020070d00410121050c020b2007103322050d010c86010b2006280200210520042007460d0020052004200710372205450d81010b20022005360204200241086a20073602002002410c6a28020021040b200520046a41c4003a00002002410c6a200441016a220436020002400240200241086a280200220720046b4108490d00200628020021050c010b200441086a22052004490d7f200741017422042005200420054b1b22044100480d7f0240024020070d00024020040d00410121050c020b2004103322050d010c86010b2006280200210520072004460d0020052007200410372205450d81010b20022005360204200241086a20043602002002410c6a28020021040b200520046a200c3700002002410c6a200441086a3602000c7b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7e200441017422062005200620054b1b22064100480d7e0240024020040d00024020060d00410121050c020b2006103322050d010c85010b2002280204210520042006460d0020052004200610372205450d80010b20022005360204200241086a20063602002002410c6a28020021040b200520046a41c5003a00002002410c6a200441016a3602000c7a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7d200441017422062005200620054b1b22064100480d7d0240024020040d00024020060d00410121050c020b2006103322050d010c84010b2002280204210520042006460d0020052004200610372205450d7f0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41c6003a00002002410c6a200441016a3602000c790b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7c200441017422062005200620054b1b22064100480d7c0240024020040d00024020060d00410121050c020b2006103322050d010c83010b2002280204210520042006460d0020052004200610372205450d7e0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41c7003a00002002410c6a200441016a3602000c780b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7b200441017422062005200620054b1b22064100480d7b0240024020040d00024020060d00410121050c020b2006103322050d010c82010b2002280204210520042006460d0020052004200610372205450d7d0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41c8003a00002002410c6a200441016a3602000c770b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7a200441017422062005200620054b1b22064100480d7a0240024020040d00024020060d00410121050c020b2006103322050d010c81010b2002280204210520042006460d0020052004200610372205450d7c0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41c9003a00002002410c6a200441016a3602000c760b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d79200441017422062005200620054b1b22064100480d790240024020040d00024020060d00410121050c020b2006103322050d010c80010b2002280204210520042006460d0020052004200610372205450d7b0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ca003a00002002410c6a200441016a3602000c750b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d78200441017422062005200620054b1b22064100480d780240024020040d00024020060d00410121050c020b2006103322050d010c7f0b2002280204210520042006460d0020052004200610372205450d7a0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41cb003a00002002410c6a200441016a3602000c740b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d77200441017422062005200620054b1b22064100480d770240024020040d00024020060d00410121050c020b2006103322050d010c7e0b2002280204210520042006460d0020052004200610372205450d790b20022005360204200241086a20063602002002410c6a28020021040b200520046a41cc003a00002002410c6a200441016a3602000c730b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d76200441017422062005200620054b1b22064100480d760240024020040d00024020060d00410121050c020b2006103322050d010c7d0b2002280204210520042006460d0020052004200610372205450d780b20022005360204200241086a20063602002002410c6a28020021040b200520046a41cd003a00002002410c6a200441016a3602000c720b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d75200441017422062005200620054b1b22064100480d750240024020040d00024020060d00410121050c020b2006103322050d010c7c0b2002280204210520042006460d0020052004200610372205450d770b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ce003a00002002410c6a200441016a3602000c710b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d74200441017422062005200620054b1b22064100480d740240024020040d00024020060d00410121050c020b2006103322050d010c7b0b2002280204210520042006460d0020052004200610372205450d760b20022005360204200241086a20063602002002410c6a28020021040b200520046a41cf003a00002002410c6a200441016a3602000c700b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d73200441017422062005200620054b1b22064100480d730240024020040d00024020060d00410121050c020b2006103322050d010c7a0b2002280204210520042006460d0020052004200610372205450d750b20022005360204200241086a20063602002002410c6a28020021040b200520046a41d0003a00002002410c6a200441016a3602000c6f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d72200441017422062005200620054b1b22064100480d720240024020040d00024020060d00410121050c020b2006103322050d010c790b2002280204210520042006460d0020052004200610372205450d740b20022005360204200241086a20063602002002410c6a28020021040b200520046a41d1003a00002002410c6a200441016a3602000c6e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d71200441017422062005200620054b1b22064100480d710240024020040d00024020060d00410121050c020b2006103322050d010c780b2002280204210520042006460d0020052004200610372205450d730b20022005360204200241086a20063602002002410c6a28020021040b200520046a41d2003a00002002410c6a200441016a3602000c6d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d70200441017422062005200620054b1b22064100480d700240024020040d00024020060d00410121050c020b2006103322050d010c770b2002280204210520042006460d0020052004200610372205450d720b20022005360204200241086a20063602002002410c6a28020021040b200520046a41d3003a00002002410c6a200441016a3602000c6c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6f200441017422062005200620054b1b22064100480d6f0240024020040d00024020060d00410121050c020b2006103322050d010c760b2002280204210520042006460d0020052004200610372205450d710b20022005360204200241086a20063602002002410c6a28020021040b200520046a41d4003a00002002410c6a200441016a3602000c6b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6e200441017422062005200620054b1b22064100480d6e0240024020040d00024020060d00410121050c020b2006103322050d010c750b2002280204210520042006460d0020052004200610372205450d700b20022005360204200241086a20063602002002410c6a28020021040b200520046a41d5003a00002002410c6a200441016a3602000c6a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6d200441017422062005200620054b1b22064100480d6d0240024020040d00024020060d00410121050c020b2006103322050d010c740b2002280204210520042006460d0020052004200610372205450d6f0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41d6003a00002002410c6a200441016a3602000c690b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6c200441017422062005200620054b1b22064100480d6c0240024020040d00024020060d00410121050c020b2006103322050d010c730b2002280204210520042006460d0020052004200610372205450d6e0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41d7003a00002002410c6a200441016a3602000c680b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6b200441017422062005200620054b1b22064100480d6b0240024020040d00024020060d00410121050c020b2006103322050d010c720b2002280204210520042006460d0020052004200610372205450d6d0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41d8003a00002002410c6a200441016a3602000c670b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6a200441017422062005200620054b1b22064100480d6a0240024020040d00024020060d00410121050c020b2006103322050d010c710b2002280204210520042006460d0020052004200610372205450d6c0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41d9003a00002002410c6a200441016a3602000c660b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d69200441017422062005200620054b1b22064100480d690240024020040d00024020060d00410121050c020b2006103322050d010c700b2002280204210520042006460d0020052004200610372205450d6b0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41da003a00002002410c6a200441016a3602000c650b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d68200441017422062005200620054b1b22064100480d680240024020040d00024020060d00410121050c020b2006103322050d010c6f0b2002280204210520042006460d0020052004200610372205450d6a0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41db003a00002002410c6a200441016a3602000c640b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d67200441017422062005200620054b1b22064100480d670240024020040d00024020060d00410121050c020b2006103322050d010c6e0b2002280204210520042006460d0020052004200610372205450d690b20022005360204200241086a20063602002002410c6a28020021040b200520046a41dc003a00002002410c6a200441016a3602000c630b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d66200441017422062005200620054b1b22064100480d660240024020040d00024020060d00410121050c020b2006103322050d010c6d0b2002280204210520042006460d0020052004200610372205450d680b20022005360204200241086a20063602002002410c6a28020021040b200520046a41dd003a00002002410c6a200441016a3602000c620b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d65200441017422062005200620054b1b22064100480d650240024020040d00024020060d00410121050c020b2006103322050d010c6c0b2002280204210520042006460d0020052004200610372205450d670b20022005360204200241086a20063602002002410c6a28020021040b200520046a41de003a00002002410c6a200441016a3602000c610b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d64200441017422062005200620054b1b22064100480d640240024020040d00024020060d00410121050c020b2006103322050d010c6b0b2002280204210520042006460d0020052004200610372205450d660b20022005360204200241086a20063602002002410c6a28020021040b200520046a41df003a00002002410c6a200441016a3602000c600b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d63200441017422062005200620054b1b22064100480d630240024020040d00024020060d00410121050c020b2006103322050d010c6a0b2002280204210520042006460d0020052004200610372205450d650b20022005360204200241086a20063602002002410c6a28020021040b200520046a41e0003a00002002410c6a200441016a3602000c5f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d62200441017422062005200620054b1b22064100480d620240024020040d00024020060d00410121050c020b2006103322050d010c690b2002280204210520042006460d0020052004200610372205450d640b20022005360204200241086a20063602002002410c6a28020021040b200520046a41e1003a00002002410c6a200441016a3602000c5e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d61200441017422062005200620054b1b22064100480d610240024020040d00024020060d00410121050c020b2006103322050d010c680b2002280204210520042006460d0020052004200610372205450d630b20022005360204200241086a20063602002002410c6a28020021040b200520046a41e2003a00002002410c6a200441016a3602000c5d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d60200441017422062005200620054b1b22064100480d600240024020040d00024020060d00410121050c020b2006103322050d010c670b2002280204210520042006460d0020052004200610372205450d620b20022005360204200241086a20063602002002410c6a28020021040b200520046a41e3003a00002002410c6a200441016a3602000c5c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5f200441017422062005200620054b1b22064100480d5f0240024020040d00024020060d00410121050c020b2006103322050d010c660b2002280204210520042006460d0020052004200610372205450d610b20022005360204200241086a20063602002002410c6a28020021040b200520046a41e4003a00002002410c6a200441016a3602000c5b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5e200441017422062005200620054b1b22064100480d5e0240024020040d00024020060d00410121050c020b2006103322050d010c650b2002280204210520042006460d0020052004200610372205450d600b20022005360204200241086a20063602002002410c6a28020021040b200520046a41e5003a00002002410c6a200441016a3602000c5a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5d200441017422062005200620054b1b22064100480d5d0240024020040d00024020060d00410121050c020b2006103322050d010c640b2002280204210520042006460d0020052004200610372205450d5f0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41e6003a00002002410c6a200441016a3602000c590b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5c200441017422062005200620054b1b22064100480d5c0240024020040d00024020060d00410121050c020b2006103322050d010c630b2002280204210520042006460d0020052004200610372205450d5e0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41e7003a00002002410c6a200441016a3602000c580b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5b200441017422062005200620054b1b22064100480d5b0240024020040d00024020060d00410121050c020b2006103322050d010c620b2002280204210520042006460d0020052004200610372205450d5d0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41e8003a00002002410c6a200441016a3602000c570b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5a200441017422062005200620054b1b22064100480d5a0240024020040d00024020060d00410121050c020b2006103322050d010c610b2002280204210520042006460d0020052004200610372205450d5c0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41e9003a00002002410c6a200441016a3602000c560b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d59200441017422062005200620054b1b22064100480d590240024020040d00024020060d00410121050c020b2006103322050d010c600b2002280204210520042006460d0020052004200610372205450d5b0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ea003a00002002410c6a200441016a3602000c550b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d58200441017422062005200620054b1b22064100480d580240024020040d00024020060d00410121050c020b2006103322050d010c5f0b2002280204210520042006460d0020052004200610372205450d5a0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41eb003a00002002410c6a200441016a3602000c540b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d57200441017422062005200620054b1b22064100480d570240024020040d00024020060d00410121050c020b2006103322050d010c5e0b2002280204210520042006460d0020052004200610372205450d590b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ec003a00002002410c6a200441016a3602000c530b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d56200441017422062005200620054b1b22064100480d560240024020040d00024020060d00410121050c020b2006103322050d010c5d0b2002280204210520042006460d0020052004200610372205450d580b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ed003a00002002410c6a200441016a3602000c520b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d55200441017422062005200620054b1b22064100480d550240024020040d00024020060d00410121050c020b2006103322050d010c5c0b2002280204210520042006460d0020052004200610372205450d570b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ee003a00002002410c6a200441016a3602000c510b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d54200441017422062005200620054b1b22064100480d540240024020040d00024020060d00410121050c020b2006103322050d010c5b0b2002280204210520042006460d0020052004200610372205450d560b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ef003a00002002410c6a200441016a3602000c500b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d53200441017422062005200620054b1b22064100480d530240024020040d00024020060d00410121050c020b2006103322050d010c5a0b2002280204210520042006460d0020052004200610372205450d550b20022005360204200241086a20063602002002410c6a28020021040b200520046a41f0003a00002002410c6a200441016a3602000c4f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d52200441017422062005200620054b1b22064100480d520240024020040d00024020060d00410121050c020b2006103322050d010c590b2002280204210520042006460d0020052004200610372205450d540b20022005360204200241086a20063602002002410c6a28020021040b200520046a41f1003a00002002410c6a200441016a3602000c4e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d51200441017422062005200620054b1b22064100480d510240024020040d00024020060d00410121050c020b2006103322050d010c580b2002280204210520042006460d0020052004200610372205450d530b20022005360204200241086a20063602002002410c6a28020021040b200520046a41f2003a00002002410c6a200441016a3602000c4d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d50200441017422062005200620054b1b22064100480d500240024020040d00024020060d00410121050c020b2006103322050d010c570b2002280204210520042006460d0020052004200610372205450d520b20022005360204200241086a20063602002002410c6a28020021040b200520046a41f3003a00002002410c6a200441016a3602000c4c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4f200441017422062005200620054b1b22064100480d4f0240024020040d00024020060d00410121050c020b2006103322050d010c560b2002280204210520042006460d0020052004200610372205450d510b20022005360204200241086a20063602002002410c6a28020021040b200520046a41f4003a00002002410c6a200441016a3602000c4b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4e200441017422062005200620054b1b22064100480d4e0240024020040d00024020060d00410121050c020b2006103322050d010c550b2002280204210520042006460d0020052004200610372205450d500b20022005360204200241086a20063602002002410c6a28020021040b200520046a41f5003a00002002410c6a200441016a3602000c4a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4d200441017422062005200620054b1b22064100480d4d0240024020040d00024020060d00410121050c020b2006103322050d010c540b2002280204210520042006460d0020052004200610372205450d4f0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41f6003a00002002410c6a200441016a3602000c490b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4c200441017422062005200620054b1b22064100480d4c0240024020040d00024020060d00410121050c020b2006103322050d010c530b2002280204210520042006460d0020052004200610372205450d4e0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41f7003a00002002410c6a200441016a3602000c480b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4b200441017422062005200620054b1b22064100480d4b0240024020040d00024020060d00410121050c020b2006103322050d010c520b2002280204210520042006460d0020052004200610372205450d4d0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41f8003a00002002410c6a200441016a3602000c470b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4a200441017422062005200620054b1b22064100480d4a0240024020040d00024020060d00410121050c020b2006103322050d010c510b2002280204210520042006460d0020052004200610372205450d4c0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41f9003a00002002410c6a200441016a3602000c460b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d49200441017422062005200620054b1b22064100480d490240024020040d00024020060d00410121050c020b2006103322050d010c500b2002280204210520042006460d0020052004200610372205450d4b0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41fa003a00002002410c6a200441016a3602000c450b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d48200441017422062005200620054b1b22064100480d480240024020040d00024020060d00410121050c020b2006103322050d010c4f0b2002280204210520042006460d0020052004200610372205450d4a0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41fb003a00002002410c6a200441016a3602000c440b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d47200441017422062005200620054b1b22064100480d470240024020040d00024020060d00410121050c020b2006103322050d010c4e0b2002280204210520042006460d0020052004200610372205450d490b20022005360204200241086a20063602002002410c6a28020021040b200520046a41fc003a00002002410c6a200441016a3602000c430b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d46200441017422062005200620054b1b22064100480d460240024020040d00024020060d00410121050c020b2006103322050d010c4d0b2002280204210520042006460d0020052004200610372205450d480b20022005360204200241086a20063602002002410c6a28020021040b200520046a41fd003a00002002410c6a200441016a3602000c420b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d45200441017422062005200620054b1b22064100480d450240024020040d00024020060d00410121050c020b2006103322050d010c4c0b2002280204210520042006460d0020052004200610372205450d470b20022005360204200241086a20063602002002410c6a28020021040b200520046a41fe003a00002002410c6a200441016a3602000c410b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d44200441017422062005200620054b1b22064100480d440240024020040d00024020060d00410121050c020b2006103322050d010c4b0b2002280204210520042006460d0020052004200610372205450d460b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ff003a00002002410c6a200441016a3602000c400b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d43200441017422062005200620054b1b22064100480d430240024020040d00024020060d00410121050c020b2006103322050d010c4a0b2002280204210520042006460d0020052004200610372205450d450b20022005360204200241086a20063602002002410c6a28020021040b200520046a4180013a00002002410c6a200441016a3602000c3f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d42200441017422062005200620054b1b22064100480d420240024020040d00024020060d00410121050c020b2006103322050d010c490b2002280204210520042006460d0020052004200610372205450d440b20022005360204200241086a20063602002002410c6a28020021040b200520046a4181013a00002002410c6a200441016a3602000c3e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d41200441017422062005200620054b1b22064100480d410240024020040d00024020060d00410121050c020b2006103322050d010c480b2002280204210520042006460d0020052004200610372205450d430b20022005360204200241086a20063602002002410c6a28020021040b200520046a4182013a00002002410c6a200441016a3602000c3d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d40200441017422062005200620054b1b22064100480d400240024020040d00024020060d00410121050c020b2006103322050d010c470b2002280204210520042006460d0020052004200610372205450d420b20022005360204200241086a20063602002002410c6a28020021040b200520046a4183013a00002002410c6a200441016a3602000c3c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3f200441017422062005200620054b1b22064100480d3f0240024020040d00024020060d00410121050c020b2006103322050d010c460b2002280204210520042006460d0020052004200610372205450d410b20022005360204200241086a20063602002002410c6a28020021040b200520046a4184013a00002002410c6a200441016a3602000c3b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3e200441017422062005200620054b1b22064100480d3e0240024020040d00024020060d00410121050c020b2006103322050d010c450b2002280204210520042006460d0020052004200610372205450d400b20022005360204200241086a20063602002002410c6a28020021040b200520046a4185013a00002002410c6a200441016a3602000c3a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3d200441017422062005200620054b1b22064100480d3d0240024020040d00024020060d00410121050c020b2006103322050d010c440b2002280204210520042006460d0020052004200610372205450d3f0b20022005360204200241086a20063602002002410c6a28020021040b200520046a4186013a00002002410c6a200441016a3602000c390b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3c200441017422062005200620054b1b22064100480d3c0240024020040d00024020060d00410121050c020b2006103322050d010c430b2002280204210520042006460d0020052004200610372205450d3e0b20022005360204200241086a20063602002002410c6a28020021040b200520046a4187013a00002002410c6a200441016a3602000c380b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3b200441017422062005200620054b1b22064100480d3b0240024020040d00024020060d00410121050c020b2006103322050d010c420b2002280204210520042006460d0020052004200610372205450d3d0b20022005360204200241086a20063602002002410c6a28020021040b200520046a4188013a00002002410c6a200441016a3602000c370b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3d200441017422062005200620054b1b22064100480d3d0240024020040d00024020060d00410121050c020b2006103322050d010c410b2002280204210520042006460d0020052004200610372205450d3c0b20022005360204200241086a20063602002002410c6a28020021040b200520046a4189013a00002002410c6a200441016a3602000c360b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3c200441017422062005200620054b1b22064100480d3c0240024020040d00024020060d00410121050c020b2006103322050d010c400b2002280204210520042006460d0020052004200610372205450d3c0b20022005360204200241086a20063602002002410c6a28020021040b200520046a418a013a00002002410c6a200441016a3602000c350b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3b200441017422062005200620054b1b22064100480d3b0240024020040d00024020060d00410121050c020b2006103322050d010c3f0b2002280204210520042006460d0020052004200610372205450d3b0b20022005360204200241086a20063602002002410c6a28020021040b200520046a418b013a00002002410c6a200441016a3602000c340b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3a200441017422062005200620054b1b22064100480d3a0240024020040d00024020060d00410121050c020b2006103322050d010c3e0b2002280204210520042006460d0020052004200610372205450d3a0b20022005360204200241086a20063602002002410c6a28020021040b200520046a418c013a00002002410c6a200441016a3602000c330b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d39200441017422062005200620054b1b22064100480d390240024020040d00024020060d00410121050c020b2006103322050d010c3d0b2002280204210520042006460d0020052004200610372205450d390b20022005360204200241086a20063602002002410c6a28020021040b200520046a418d013a00002002410c6a200441016a3602000c320b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d38200441017422062005200620054b1b22064100480d380240024020040d00024020060d00410121050c020b2006103322050d010c3c0b2002280204210520042006460d0020052004200610372205450d380b20022005360204200241086a20063602002002410c6a28020021040b200520046a418e013a00002002410c6a200441016a3602000c310b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d37200441017422062005200620054b1b22064100480d370240024020040d00024020060d00410121050c020b2006103322050d010c3b0b2002280204210520042006460d0020052004200610372205450d370b20022005360204200241086a20063602002002410c6a28020021040b200520046a418f013a00002002410c6a200441016a3602000c300b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d36200441017422062005200620054b1b22064100480d360240024020040d00024020060d00410121050c020b2006103322050d010c3a0b2002280204210520042006460d0020052004200610372205450d360b20022005360204200241086a20063602002002410c6a28020021040b200520046a4190013a00002002410c6a200441016a3602000c2f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d35200441017422062005200620054b1b22064100480d350240024020040d00024020060d00410121050c020b2006103322050d010c390b2002280204210520042006460d0020052004200610372205450d350b20022005360204200241086a20063602002002410c6a28020021040b200520046a4191013a00002002410c6a200441016a3602000c2e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d34200441017422062005200620054b1b22064100480d340240024020040d00024020060d00410121050c020b2006103322050d010c380b2002280204210520042006460d0020052004200610372205450d340b20022005360204200241086a20063602002002410c6a28020021040b200520046a4192013a00002002410c6a200441016a3602000c2d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d33200441017422062005200620054b1b22064100480d330240024020040d00024020060d00410121050c020b2006103322050d010c370b2002280204210520042006460d0020052004200610372205450d330b20022005360204200241086a20063602002002410c6a28020021040b200520046a4193013a00002002410c6a200441016a3602000c2c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d32200441017422062005200620054b1b22064100480d320240024020040d00024020060d00410121050c020b2006103322050d010c360b2002280204210520042006460d0020052004200610372205450d320b20022005360204200241086a20063602002002410c6a28020021040b200520046a4194013a00002002410c6a200441016a3602000c2b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d31200441017422062005200620054b1b22064100480d310240024020040d00024020060d00410121050c020b2006103322050d010c350b2002280204210520042006460d0020052004200610372205450d310b20022005360204200241086a20063602002002410c6a28020021040b200520046a4195013a00002002410c6a200441016a3602000c2a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d30200441017422062005200620054b1b22064100480d300240024020040d00024020060d00410121050c020b2006103322050d010c340b2002280204210520042006460d0020052004200610372205450d300b20022005360204200241086a20063602002002410c6a28020021040b200520046a4196013a00002002410c6a200441016a3602000c290b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2f200441017422062005200620054b1b22064100480d2f0240024020040d00024020060d00410121050c020b2006103322050d010c330b2002280204210520042006460d0020052004200610372205450d2f0b20022005360204200241086a20063602002002410c6a28020021040b200520046a4197013a00002002410c6a200441016a3602000c280b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2e200441017422062005200620054b1b22064100480d2e0240024020040d00024020060d00410121050c020b2006103322050d010c320b2002280204210520042006460d0020052004200610372205450d2e0b20022005360204200241086a20063602002002410c6a28020021040b200520046a4198013a00002002410c6a200441016a3602000c270b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2d200441017422062005200620054b1b22064100480d2d0240024020040d00024020060d00410121050c020b2006103322050d010c310b2002280204210520042006460d0020052004200610372205450d2d0b20022005360204200241086a20063602002002410c6a28020021040b200520046a4199013a00002002410c6a200441016a3602000c260b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2c200441017422062005200620054b1b22064100480d2c0240024020040d00024020060d00410121050c020b2006103322050d010c300b2002280204210520042006460d0020052004200610372205450d2c0b20022005360204200241086a20063602002002410c6a28020021040b200520046a419a013a00002002410c6a200441016a3602000c250b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2b200441017422062005200620054b1b22064100480d2b0240024020040d00024020060d00410121050c020b2006103322050d010c2f0b2002280204210520042006460d0020052004200610372205450d2b0b20022005360204200241086a20063602002002410c6a28020021040b200520046a419b013a00002002410c6a200441016a3602000c240b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2a200441017422062005200620054b1b22064100480d2a0240024020040d00024020060d00410121050c020b2006103322050d010c2d0b2002280204210520042006460d0020052004200610372205450d2a0b20022005360204200241086a20063602002002410c6a28020021040b200520046a419c013a00002002410c6a200441016a3602000c230b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d29200441017422062005200620054b1b22064100480d290240024020040d00024020060d00410121050c020b200610332205450d2c0c010b2002280204210520042006460d0020052004200610372205450d290b20022005360204200241086a20063602002002410c6a28020021040b200520046a419d013a00002002410c6a200441016a3602000c220b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d28200441017422062005200620054b1b22064100480d280240024020040d00024020060d00410121050c020b200610332205450d2b0c010b2002280204210520042006460d0020052004200610372205450d280b20022005360204200241086a20063602002002410c6a28020021040b200520046a419e013a00002002410c6a200441016a3602000c210b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d27200441017422062005200620054b1b22064100480d270240024020040d00024020060d00410121050c020b200610332205450d2a0c010b2002280204210520042006460d0020052004200610372205450d270b20022005360204200241086a20063602002002410c6a28020021040b200520046a419f013a00002002410c6a200441016a3602000c200b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d26200441017422062005200620054b1b22064100480d260240024020040d00024020060d00410121050c020b200610332205450d290c010b2002280204210520042006460d0020052004200610372205450d260b20022005360204200241086a20063602002002410c6a28020021040b200520046a41a0013a00002002410c6a200441016a3602000c1f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d25200441017422062005200620054b1b22064100480d250240024020040d00024020060d00410121050c020b200610332205450d280c010b2002280204210520042006460d0020052004200610372205450d250b20022005360204200241086a20063602002002410c6a28020021040b200520046a41a1013a00002002410c6a200441016a3602000c1e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d24200441017422062005200620054b1b22064100480d240240024020040d00024020060d00410121050c020b200610332205450d270c010b2002280204210520042006460d0020052004200610372205450d240b20022005360204200241086a20063602002002410c6a28020021040b200520046a41a2013a00002002410c6a200441016a3602000c1d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d23200441017422062005200620054b1b22064100480d230240024020040d00024020060d00410121050c020b200610332205450d260c010b2002280204210520042006460d0020052004200610372205450d230b20022005360204200241086a20063602002002410c6a28020021040b200520046a41a3013a00002002410c6a200441016a3602000c1c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d22200441017422062005200620054b1b22064100480d220240024020040d00024020060d00410121050c020b200610332205450d250c010b2002280204210520042006460d0020052004200610372205450d220b20022005360204200241086a20063602002002410c6a28020021040b200520046a41a4013a00002002410c6a200441016a3602000c1b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d00024020060d00410121050c020b200610332205450d240c010b2002280204210520042006460d0020052004200610372205450d210b20022005360204200241086a20063602002002410c6a28020021040b200520046a41a5013a00002002410c6a200441016a3602000c1a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d20200441017422062005200620054b1b22064100480d200240024020040d00024020060d00410121050c020b200610332205450d230c010b2002280204210520042006460d0020052004200610372205450d200b20022005360204200241086a20063602002002410c6a28020021040b200520046a41a6013a00002002410c6a200441016a3602000c190b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1f200441017422062005200620054b1b22064100480d1f0240024020040d00024020060d00410121050c020b200610332205450d220c010b2002280204210520042006460d0020052004200610372205450d1f0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41a7013a00002002410c6a200441016a3602000c180b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1e200441017422062005200620054b1b22064100480d1e0240024020040d00024020060d00410121050c020b200610332205450d210c010b2002280204210520042006460d0020052004200610372205450d1e0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41a8013a00002002410c6a200441016a3602000c170b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1d200441017422062005200620054b1b22064100480d1d0240024020040d00024020060d00410121050c020b200610332205450d200c010b2002280204210520042006460d0020052004200610372205450d1d0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41a9013a00002002410c6a200441016a3602000c160b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1c200441017422062005200620054b1b22064100480d1c0240024020040d00024020060d00410121050c020b200610332205450d1f0c010b2002280204210520042006460d0020052004200610372205450d1c0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41aa013a00002002410c6a200441016a3602000c150b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1b200441017422062005200620054b1b22064100480d1b0240024020040d00024020060d00410121050c020b200610332205450d1e0c010b2002280204210520042006460d0020052004200610372205450d1b0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ab013a00002002410c6a200441016a3602000c140b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1a200441017422062005200620054b1b22064100480d1a0240024020040d00024020060d00410121050c020b200610332205450d1d0c010b2002280204210520042006460d0020052004200610372205450d1a0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ac013a00002002410c6a200441016a3602000c130b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d19200441017422062005200620054b1b22064100480d190240024020040d00024020060d00410121050c020b200610332205450d1c0c010b2002280204210520042006460d0020052004200610372205450d190b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ad013a00002002410c6a200441016a3602000c120b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d18200441017422062005200620054b1b22064100480d180240024020040d00024020060d00410121050c020b200610332205450d1b0c010b2002280204210520042006460d0020052004200610372205450d180b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ae013a00002002410c6a200441016a3602000c110b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d17200441017422062005200620054b1b22064100480d170240024020040d00024020060d00410121050c020b200610332205450d1a0c010b2002280204210520042006460d0020052004200610372205450d170b20022005360204200241086a20063602002002410c6a28020021040b200520046a41af013a00002002410c6a200441016a3602000c100b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d16200441017422062005200620054b1b22064100480d160240024020040d00024020060d00410121050c020b200610332205450d190c010b2002280204210520042006460d0020052004200610372205450d160b20022005360204200241086a20063602002002410c6a28020021040b200520046a41b0013a00002002410c6a200441016a3602000c0f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d15200441017422062005200620054b1b22064100480d150240024020040d00024020060d00410121050c020b200610332205450d180c010b2002280204210520042006460d0020052004200610372205450d150b20022005360204200241086a20063602002002410c6a28020021040b200520046a41b1013a00002002410c6a200441016a3602000c0e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d14200441017422062005200620054b1b22064100480d140240024020040d00024020060d00410121050c020b200610332205450d170c010b2002280204210520042006460d0020052004200610372205450d140b20022005360204200241086a20063602002002410c6a28020021040b200520046a41b2013a00002002410c6a200441016a3602000c0d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d13200441017422062005200620054b1b22064100480d130240024020040d00024020060d00410121050c020b200610332205450d160c010b2002280204210520042006460d0020052004200610372205450d130b20022005360204200241086a20063602002002410c6a28020021040b200520046a41b3013a00002002410c6a200441016a3602000c0c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d12200441017422062005200620054b1b22064100480d120240024020040d00024020060d00410121050c020b200610332205450d150c010b2002280204210520042006460d0020052004200610372205450d120b20022005360204200241086a20063602002002410c6a28020021040b200520046a41b4013a00002002410c6a200441016a3602000c0b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d11200441017422062005200620054b1b22064100480d110240024020040d00024020060d00410121050c020b200610332205450d140c010b2002280204210520042006460d0020052004200610372205450d110b20022005360204200241086a20063602002002410c6a28020021040b200520046a41b5013a00002002410c6a200441016a3602000c0a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d10200441017422062005200620054b1b22064100480d100240024020040d00024020060d00410121050c020b200610332205450d130c010b2002280204210520042006460d0020052004200610372205450d100b20022005360204200241086a20063602002002410c6a28020021040b200520046a41b6013a00002002410c6a200441016a3602000c090b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0f200441017422062005200620054b1b22064100480d0f0240024020040d00024020060d00410121050c020b200610332205450d120c010b2002280204210520042006460d0020052004200610372205450d0f0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41b7013a00002002410c6a200441016a3602000c080b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0e200441017422062005200620054b1b22064100480d0e0240024020040d00024020060d00410121050c020b200610332205450d110c010b2002280204210520042006460d0020052004200610372205450d0e0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41b8013a00002002410c6a200441016a3602000c070b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0d200441017422062005200620054b1b22064100480d0d0240024020040d00024020060d00410121050c020b200610332205450d100c010b2002280204210520042006460d0020052004200610372205450d0d0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41b9013a00002002410c6a200441016a3602000c060b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0c200441017422062005200620054b1b22064100480d0c0240024020040d00024020060d00410121050c020b200610332205450d0f0c010b2002280204210520042006460d0020052004200610372205450d0c0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41ba013a00002002410c6a200441016a3602000c050b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0b200441017422062005200620054b1b22064100480d0b0240024020040d00024020060d00410121050c020b200610332205450d0e0c010b2002280204210520042006460d0020052004200610372205450d0b0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41bb013a00002002410c6a200441016a3602000c040b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0a200441017422062005200620054b1b22064100480d0a0240024020040d00024020060d00410121050c020b200610332205450d0d0c010b2002280204210520042006460d0020052004200610372205450d0a0b20022005360204200241086a20063602002002410c6a28020021040b200520046a41bc013a00002002410c6a200441016a3602000c030b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d09200441017422062005200620054b1b22064100480d090240024020040d00024020060d00410121050c020b200610332205450d0c0c010b2002280204210520042006460d0020052004200610372205450d090b20022005360204200241086a20063602002002410c6a28020021040b200520046a41bd013a00002002410c6a200441016a3602000c020b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d08200441017422062005200620054b1b22064100480d080240024020040d00024020060d00410121050c020b200610332205450d0b0c010b2002280204210520042006460d0020052004200610372205450d080b20022005360204200241086a20063602002002410c6a28020021040b200520046a41be013a00002002410c6a200441016a3602000c010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d07200441017422062005200620054b1b22064100480d070240024020040d00024020060d00410121050c020b200610332205450d0a0c010b2002280204210520042006460d0020052004200610372205450d070b20022005360204200241086a20063602002002410c6a28020021040b200520046a41bf013a00002002410c6a200441016a3602000b2000411f3a000020012d00004109470d090240200141046a280200220228020441ffffffff0371450d0020022802001035200128020421020b200210350c090b103e000b103e000b103e000b103c000b103c000b103e000b103c000b103c000b20002004290200370200200041086a200441086a29020037020020012d00004109470d000240200141046a280200220228020441ffffffff0371450d0020022802001035200128020421020b200210350b200341106a24000f0b103c000ba907010c7f230041d0086b22022400410021034100210402400240024002400240024002400240024002400240034002402003411f4d0d00410f21030c030b20012802082205200128020c2206460d01200641016a22072006490d0420052007490d082001280200220820066a2d000021062001200736020c200641ff00712003411f71742004722104200341076a21032006418001710d000b024020034120490d00410d21032006410f4b0d020b20040d022000428080808010370200200041086a42003702000c0a0b200241013a0089082002411c6a41013602002002420137020c200241acfdcb003602082002413636029c08200220024198086a360218200220024189086a36029808200241b8086a200241086a1041410521030b2000200336020420004101360200200041086a20022903b808370200200041106a200241b8086a41086a2802003602000c080b200241086a4100418008109f081a41002106410021094101210a4100210b02400340200520076b2004200b6b22034180082003418008491b2203490d01200720036a220c2007490d032005200c490d04200241086a200820076a2003109d081a2001200c36020c02400240200920066b2003490d00200620036a210c2009210d0c010b200620036a220c2006490d0620094101742207200c2007200c4b1b220d4100480d06024020090d000240200d0d004101210a0c020b200d1033220a0d010c090b2009200d460d00200a2009200d1037220a450d080b200a20066a200241086a2003109d081a20042003200b6a220b4d0d08200128020c21072001280208210520012802002108200c2106200d21090c000b0b200241013a00a708200241cc086a4101360200200242013702bc08200241acfdcb003602b8082002413636029c08200220024198086a3602c8082002200241a7086a36029808200241a8086a200241b8086a104120024194086a200241b0086a280200360000200220022903a80837008c08200041053a000420002002290089083700052000410c6a20024190086a290000370000200041013602002009450d07200a10350c070b417f200741c0fdcb001059000b2007200c41c0fdcb001059000b200c200541c0fdcb001058000b103e000b2007200541c0fdcb001058000b103c000b200241086a200a200c1074024020022802084101470d000240200d450d00200a10350b200041083a0004200041013602000c010b2000200a3602042000410c6a200c360200200041086a200d360200200041003602000b200241d0086a24000b15002001200028020022002802002000280208105a0bf90401067f200441046a21050240024002400240200441086a2802002004410c6a2802002206460d00200528020021070c010b200641016a22072006490d01200641017422082007200820074b1b22084100480d010240024020060d00024020080d00410121070c020b2008103322070d010c040b2005280200210720062008460d0020072006200810372207450d030b20042007360204200441086a20083602002004410c6a28020021060b200720066a20024101463a00002004410c6a2209200641016a2206360200200441086a210a034002400240200a2802002006460d00200528020021070c010b200641016a22072006490d02200641017422082007200820074b1b22084100480d020240024020060d00024020080d00410121070c020b200810332207450d050c010b2005280200210720062008460d0020072006200810372207450d040b20042007360204200a2008360200200928020021060b200720066a200141807f72200141ff0071200141077622071b3a00002009200641016a22063602002007210120070d000b024020024101470d00200441086a21082004410c6a210903400240024020082802002006460d00200528020021010c010b200641016a22012006490d03200641017422072001200720014b1b22074100480d030240024020060d00024020070d00410121010c020b200710332201450d060c010b2005280200210120062007460d0020012006200710372201450d050b2004200136020420082007360200200928020021060b200120066a200341807f72200341ff0071200341077622011b3a00002009200641016a22063602002001210320010d000b0b2000411f3a00000f0b103e000b103c000bc807010a7f230041d0006b220224000240024002400240024002400240024002400240024020012802082203200128020c2204460d00200441016a22052004490d0220032005490d032001280200220620046a2d000021072001200536020c20074102490d01200041173a000420004101360200200041056a20073a00000c0a0b200241013a001f200241cc006a41013602002002420137023c200241acfdcb00360238200241363602342002200241306a36024820022002411f6a360230200241206a200241386a10412002411b6a200241286a28020036000020022002290320370013200220022900103703002002200241176a290000370007200041053a0004200020022903003700052000410c6a2002290007370000200041013602000c090b410120036b2108200441026a21044100210541002109034002402005411f4d0d00410f21050c090b200820046a4102460d072004450d0320032004490d05200620046a417f6a2d0000210a2001200436020c200a41ff00712005411f71742009722109200441016a2104200541076a2105200a418001710d000b024020054120490d00410d2105200a410f4b0d080b410021050240024002402007410171450d002004417f6a2104410021054100210b034002402005411f4d0d00410f21040c040b20032004460d022004417f460d072003200441016a2208490d09200620046a2d0000210a2001200836020c200a41ff00712005411f7174200b72210b200541076a210520082104200a418001710d000b024020054120490d00410d2104200a410f4b0d030b410121050b20002009360204200041003602002000410c6a200b360200200041086a20053602000c0a0b200241013a0000200241cc006a41013602002002420137023c200241acfdcb00360238200241363602342002200241306a36024820022002360230200241106a200241386a1041410521040b2000200436020420004101360200200041086a2002290310370200200041106a200241106a41086a2802003602000c080b417f200541c0fdcb001059000b2005200341c0fdcb001058000b417f200441c0fdcb001059000b417f200441016a41c0fdcb001059000b2004200341c0fdcb001058000b200441016a200341c0fdcb001058000b200241013a0000200241cc006a41013602002002420137023c200241acfdcb00360238200241363602342002200241306a36024820022002360230200241106a200241386a1041410521050b2000200536020420004101360200200041086a2002290310370200200041106a200241106a41086a2802003602000b200241d0006a24000bc4c901040b7f027e147f017e230041e081046b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402001280204220320012802082204460d00200441016a22052004490d0720032005490d06200128020020046a2d00002104200120053602082004410c4b0d0120040e0d02031211100f0e0d0c0b0a0908020b200241013a0060200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241e0006a360228200241c881046a200241b8016a104120022802c88104210420022802cc8104210120004101360200200041003a00042001450d1c200410350c1c0b200041123a000420004101360200200041056a20043a00000c1b0b200241b8016a200110c0074101210620022802bc012107024020022802b8014101460d0041002108200241b8016a410041808001109f081a41002103410021092007450d13410021054100210a410121064100210b024003402001280204220c200128020822036b2007200b6b220441808001200441808001491b2204490d01200320046a22092003490d05200c2009490d04200241b8016a200128020020036a2004109d081a2001200936020802400240200a20056b2004490d00200520046a2103200a21090c010b200520046a22032005490d19200a41017422092003200920034b1b22094100480d1902400240200a0d00024020090d00410121060c020b200910332206450d1f0c010b200a2009460d002006200a200910372206450d1e0b2009210a0b200620056a200241b8016a2004109d081a2003210520072004200b6a220b4b0d000c150b0b200241013a00b88104200241dc81046a4101360200200242013702cc8104200241acfdcb003602c881042002413636022c2002200241286a3602d881042002200241b881046a360228200241e0006a200241c881046a10412002290360210d2002280268210141052107200a450d15200610350c150b200241c8016a2802002101200241c0016a290300210d0c140b200241b8016a200110c707200241b8016a41086a290300220d422088210e200241c8016a280200210120022802bc01210a20022802b8014101460d0f200ea72103200241cc016a280200210f200da72110410021044100210b024002400240024002400240024002400240034002402004411f4d0d00410f21090c030b20032001460d012001417f460d09200141016a220820034b0d08200a20016a2d0000220541ff00712004411f7174200b72210b200441076a2104200821012005418001710d000b024020044120490d00410d21092005410f4b0d020b200241003602c08104200242043703b88104200b0d02410421040c030b200241013a00c88104200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241c881046a36022820024198016a200241b8016a1041410521090b20024188016a41086a20024198016a41086a28020022013602002002200229039801220d370388010c030b410020036b21114104210441002112410021130340024002400240024002400240024002400240024002400240024020082003460d00200841016a22052008490d01200520034b0d020240200a20086a2d0000220741e000460d004118211441002115200521080c0c0b200841036a2107410021084100210602400240024003402007210902402008411f4d0d00410f21140c030b20032005460d012005417f460d07200541016a220c20034b0d09200a20056a2d0000221641ff00712008411f71742006722106200941016a2107200841076a2108200c21052016418001710d000b024020084120490d00410d21142016410f4d0d00200c21050c020b41002117200241003602682002420137036020060d02410121144100211841002116200c21050c0c0b200241013a0060200241013602cc01200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241e0006a360228200241c881046a200241b8016a1041200241306a41086a200241c881046a41086a280200360200200220022903c8810437033041052114200321050b200241c0006a41086a200241306a41086a280200221936020020022002290330220d370340200da72116410021074101211720022802442118410021150c0b0b200a200c6a211a2011200c6a211b410021164101211441002115410021180240034020162108201b201822056a450d012009450d060240200920034d0d002009200341c0fdcb001058000b0240201a20056a2c0000220741004e0d004119211c201d2116201e2118201f21190c0a0b4106211c200741c00071450d08200741807f72220741ff017141fc01490d080240024020052015460d00200821160c010b024020082015460d0020082116200821150c010b200841016a22162008490d2b200841017422182016201820164b1b22164100480d2b0240024020080d00024020160d00410121140c020b201610332214450d310c010b20082016460d0020142008201610372214450d300b2002201636026420022014360260201621150b201420056a2007417f733a00002002200541016a2218360268200941016a210920062018460d0a0c000b0b200241013a00a801200241013602cc01200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241a8016a360228200241c881046a200241b8016a10414105211c20022802c881042216211d20022802cc81042218211e20022802d081042219211f200321090c070b200241013a0060200241013602cc01200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241e0006a360228200241c881046a200241b8016a104120022802c88104211620022802cc8104211820022d00d08104210920022d00d18104210620022f01d2810421014105211441002115200321080c0a0b417f200541c0fdcb001059000b2005200341c0fdcb001058000b417f200541016a41c0fdcb001059000b417f200941c0fdcb001059000b200541016a200341c0fdcb001058000b2020211620212118202221190b410021154101211702402008450d00201410350b201c2114201621202018212120192122200921050c020b200c20186a21050b20144110762115201441087621070b0240024002400240024002400240024020170d002015411074200741ff017141087472201441ff017172211b410021174100210941002106034002402009411f4d0d00410f21140c080b0240024020032005460d002005417f460d05200541016a220820034d0d01200541016a200341c0fdcb001058000b200241013a0060200241013602cc01200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241e0006a360228200241c881046a200241b8016a104120022802c88104210720022802cc8104211820022d00d08104210920022d00d18104210620022f01d28104210141052114200321050c090b200a20056a2d0000220c41ff00712009411f71742006722106200941076a210920082105200c418001710d000b20094120490d01200c410f4d0d0120082105410d21140c060b201941107621012019410876210620052108201921090c070b024002400240200641014b0d00024020060e020002000b410421090c020b4104211441bed8cb00210741242118200821050c060b0240024020032008460d00200841016a22052008490d04200520034b0d05200a20086a2c0000221741004e0d01411921140c070b200241013a0060200241013602cc01200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241e0006a360228200241c881046a200241b8016a104120022802c88104210720022802cc8104211820022d00d08104210920022d00d18104210620022f01d28104210141052114200321050c070b201741c00071450d04201741807f72221741ff017141fc01490d042017417f732109200521080b20014180807c71200941ff01714108747241e000722101410021050c070b417f200541016a41c0fdcb001059000b417f200841016a41c0fdcb001059000b200841016a200341c0fdcb001058000b410621140b0b4100211502402016450d00201b10350b2005210820072116201721070b200641ff0171410874200941ff0171722001411074722101410121050b2015411074200741ff017141087472201441ff01717221092018ad4220862016ad84210d20050d02201341016a21130240201220022802bc8104470d00200241b881046a20124101108c0120022802b88104210420022802c0810421120b200420124104746a2205200136020c2005200d370204200520093602002002201241016a22123602c081042013200b470d000b0b2008200f46210120022902bc8104212302402010450d00200a10350b410221032001450d020c170b02402012450d00201241047421052004210303400240200341046a280200450d00200328020010350b200341106a2103200541706a22050d000b0b20022802bc810441ffffffff0071450d00200410350b200d422088210e20094108762103024020100d002009210a0c140b200a10352009210a0c130b20024103410220011b3a0060200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241e0006a360228200241c881046a200241b8016a104120022903c88104210d20022802d08104210102402023422088a72203450d00200341047421052004210303400240200341046a280200450d00200328020010350b200341106a2103200541706a22050d000b0b200d422088210e4105210a41002103202342ffffffff0083500d12200410350c120b200141016a200341c0fdcb001058000b417f200141016a41c0fdcb001059000b2009200c41c0fdcb001058000b2003200941c0fdcb001059000b2005200341c0fdcb001058000b417f200541c0fdcb001059000b200241b8016a200110c707200241b8016a41106a2802002101200241b8016a410c6a2802002105200241b8016a41086a280200210920022802bc01210b0240024020022802b8014101460d00200241cc016a280200210641002103410021040240024002400240034002402003411f4d0d00410f21010c030b20052001460d012001417f460d042005200141016a220a490d06200b20016a2d0000220841ff00712003411f71742004722104200341076a2103200a21012008418001710d000b024020034120490d00410d21012008410f4b0d020b2006200a46210102402009450d00200b10350b2001450d02410b21030c130b200241013a0060200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241e0006a360228200241c881046a200241b8016a1041410521010b2000200136020420004101360200200041086a20022903c88104370200200041106a200241c881046a41086a2802003602002009450d18200b10350c180b20024103410220011b3a00b88104200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241b881046a360228200241e0006a200241b8016a1041200241d381046a200241e8006a280200360000200220022903603700cb8104200041053a0004200020022900c881043700052000410c6a200241cf81046a290000370000200041013602000c170b417f200141016a41c0fdcb001059000b2000200b36020420004101360200200041106a20013602002000410c6a2005360200200041086a20093602000c150b200141016a200541c0fdcb001058000b200241b8016a200110c707200241c8016a2802002101200241b8016a41086a290300210d20022802bc01210b024002400240024020022802b8014101460d002002200241cc016a2802003602702002200136026c2002200b3602602002200d370264200d422088a72108410021044100210a02400240024002400240034002402004411f4d0d00410f210b0c030b20082001460d012001417f460d05200141016a220520084b0d04200b20016a2d000021032002200536026c200341ff00712004411f7174200a72210a200441076a2104200521012003418001710d000b024020044120490d00410d210b2003410f4b0d020b200241003602800120024204370378200a0d02410421040c070b200241013a00c88104200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241c881046a36022820024198016a200241b8016a10414105210b0b20024188016a41086a20024198016a41086a28020022013602002002200229039801220d370388010c040b410021070340200741016a21074100210141002105024002400240024002400240024002400240034002402001411f4d0d00410f210b0c030b20022802682208200228026c2204460d01200441016a22032004490d0520082003490d06200228026020046a2d000021042002200336026c200441ff00712001411f71742005722105200141076a21012004418001710d000b20014120490d022004410f4d0d02410d210b0c010b200241013a00b88104200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241b881046a360228200241c881046a200241b8016a1041200241c0006a41086a200241c881046a41086a280200360200200220022903c88104220d370340200da7210a4105210b0b20022802482101200228024421090c010b200241b8016a200241e0006a10a70720022802c401211820022802c001211520022802bc01211420022802b8014101470d0320022802c80121012014210b2015210a201821090b200241d0006a41086a20024198016a41086a28020036020020022002290398013703500c030b417f200341c0fdcb001059000b2003200841c0fdcb001058000b410021044100210b02400240024002400240024002400240034002402004411f4d0d00410f210b0c030b20022802682208200228026c2203460d01200341016a22012003490d0420082001490d072002280260220920036a2d000021032002200136026c200341ff00712004411f7174200b72210b200441076a21042003418001710d000b024020044120490d002003410f4d0d00410d210b0c020b41002112200241b8016a410041808004109f081a200b0d02410121134100210c0c090b200241013a00b88104200241013602cc01200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241b881046a360228200241c881046a200241b8016a1041200241306a41086a200241c881046a41086a280200360200200220022903c88104220d370330200da7210a4105210b0b20022802382101200228023421090c050b4100210641012113410021034100211602400340200820016b200b20166b220441808004200441808004491b2204490d01200120046a220c2001490d032008200c490d04200241b8016a200920016a2004109d081a2002200c36026c02400240200620036b2004490d00200320046a210c200621120c010b200320046a220c2003490d1f20064101742201200c2001200c4b1b22124100480d1f024020060d00024020120d00410121130c020b201210332213450d240c010b20062012460d0020132006201210372213450d230b201320036a200241b8016a2004109d081a200b200420166a22164d0d08200228026c2101200228026821082002280260210920122106200c21030c000b0b200241013a0040200241013602dc8104200242013702cc8104200241acfdcb003602c881042002413636022c2002200241286a3602d881042002200241c0006a360228200241b881046a200241c881046a104120022802b88104210a20022802bc8104210920022802c0810421014105210b2006450d04201310350c040b417f200141c0fdcb001059000b2001200c41c0fdcb001059000b200c200841c0fdcb001058000b2001200841c0fdcb001058000b02402018450d0020184104742103201421040340024020042d00004109470d000240200441046a2208280200220528020441ffffffff0371450d0020052802001035200828020021050b200510350b200441106a2104200341706a22030d000b0b0240201541ffffffff0071450d00201410350b200241d0006a41086a20024198016a41086a28020036020020022002290398013703500b2009ad422086200aad84210d200241f8006a10b407200228027c2204450d052004411c6c450d05200228027810350c050b200241d0006a41086a200c36020020024188016a41086a2208200c360200200220123602ac01200220133602a801200220022903a801220d3703502002200d370388012015ad4220862014ad84210d02402002280280012203200228027c470d00200241f8006a2003410110f90120022802800121030b200228027822042003411c6c6a2201200d3702042001200536020020012002290388013702102001410c6a2018360200200141186a20082802003602002002200341016a360280012007200a460d050c000b0b200141016a200841c0fdcb001058000b417f200141016a41c0fdcb001059000b200d422088210e200b41087621040c020b200d422088210e200b41087621042002280264450d01200228026010350c010b2002200229027c222337021c20022004360218200228026c200228027046210102402002280264450d00200228026010350b024020010d0020024103410220011b3a00b88104200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241b881046a360228200241c881046a200241b8016a104120022903c88104210d20022802d081042101200241186a10b40702402023a72203450d002003411c6c450d00200410350b200d422088210e4105210b410021040c010b410d21030c0d0b20004101360200200041106a2001360200200041086a200e422086200d42ffffffff0f838437020020002004410874200b41ff0171723602040c130b200241b8016a200110c707200241c8016a2802002101200241b8016a41086a290300210d20022802bc01210b0240024002400240024002400240024002400240024002400240024020022802b8014101460d00200241cc016a2802002112200d422088a72105200da72106410021044100210802400240024002400240034002402004411f4d0d00410f21090c030b20052001460d012001417f460d05200141016a220320054b0d04200b20016a2d0000220a41ff00712004411f71742008722108200441076a210420032101200a418001710d000b024020044120490d00410d2109200a410f4b0d020b200241003602b001200242043703a80120080d02410421040c110b200241013a00b88104200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241b881046a360228200241c881046a200241b8016a1041410521090b200241e0006a41086a200241c881046a41086a2802002201360200200220022903c88104220d3703600c0e0b410021150340201541016a2115410021014100210a024002400240024002400240024002400240024002400240024002400240034002402001411f4d0d00410f210920022802a00121010c1d0b20052003460d012003417f460d04200341016a220420054b0d0b200b20036a2d0000220941ff00712001411f7174200a72210a200141076a2101200421032009418001710d000b024020014120490d002009410f4d0d00410d210920022802a00121010c1c0b4100210c200241b8016a410041808001109f081a200a0d01410121182004210341002114410021090c020b200241013a00c88104200241013602cc01200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241c881046a36022820024198016a200241b8016a104141052109200229039801210d20022802a00121010c1a0b410021164101211841002107410021130340200520046b200a20136b220141808001200141808001491b2201490d19200420016a22032004490d03200320054b0d04200241b8016a200b20046a2001109d081a02400240201620076b2001490d00200720016a2109201621140c010b200720016a22092007490d2d201641017422042009200420094b1b22144100480d2d0240024020160d00024020140d00410121180c020b201410332218450d330c010b20162014460d0020182016201410372218450d320b201421160b201820076a200241b8016a2001109d081a2003210420092107200a200120136a22134b0d000b0b200220093602702002410036026c2002201836026020022009ad4220862014ad84370264410021014100210702400240024002400240024002400240034002402001411f4d0d00410f21090c030b2009200c460d01200c417f460d0c200c41016a220a20094b0d112018200c6a2d000021042002200a36026c200441ff00712001411f71742007722107200141076a2101200a210c2004418001710d000b024020014120490d002004410f4d0d00410d21090c020b4100210c200241003602c08104200242043703b8810420070d024104211441002110410021180c030b200241013a00b88104200241013602cc01200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241b881046a360228200241c881046a200241b8016a1041200241306a41086a200241c881046a41086a280200360200200220022903c88104370330410521090b200241c0006a41086a200241306a41086a280200220136020020022002290330220d370340200da722044108762105200228024421030c1b0b4100211041042114410021190340201941016a21194100210141002116034002402001411f4d0d00410f21090c050b20022802682213200228026c2204460d03200441016a220a2004490d0b2013200a490d102002280260221820046a2d000021092002200a36026c200941ff00712001411f71742016722116200141076a21012009418001710d000b024020014120490d002009410f4d0d00410d21090c040b2013200a460d04200441026a2101200a417f460d0b20132001490d0c2018200a6a2c0000210a2002200136026c0240200a41004e0d00411921090c1a0b41062109200a41c00071450d18200a41807f72220a41ff017141fb014d0d18200a417f7321010240201020022802bc8104470d00200241b881046a2010410110900120022802b88104211420022802c0810421100b201420104103746a220420013a0004200420163602002002201041016a22103602c0810420192007470d000b20022802bc810421180b201420104103746a210920142101034020092001460d04200c20012802006a2204200c49210a200141086a21012004210c200a450d000b200229038801220d422088a7210320024190016a2802002101200da72104411c21090c150b200241013a00c88104200241013602cc01200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241c881046a36022820024198016a200241b8016a10414105210920022802980121040b2004410876210520022802a0012101200228029c0121034100210a0c160b200241013a009801200241013602cc01200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c801200220024198016a360228200241c881046a200241b8016a104120022802c88104210420022802cc8104210320022802d081042101410521090c140b4100210a200241003602d08104200242083703c881044101210c410821130340200241b8016a200241e0006a10a80720022802c001210420022903c801210d20022802c4012116024002400240024020022802b8014101460d00200441ff017122014106460d022001417e6a41034f0d03200c41016a2201200c4f21092001210c20090d03200441ff0171210141152103418dd2cb0021044104210920014109460d010c150b20022802bc012109200da72101201621030c140b0240201628020441ffffffff0371450d00201628020010350b201610350c130b200c417f6a210c0b2004410876210702400240200a20022802cc8104460d00200a21090c010b200241c881046a200a10a90720022802c88104211320022802d0810421090b201320094104746a2201200d37030820012016360204200120073b0001200120043a0000200141036a20074110763a00002002200941016a220a3602d08104200c0d000b200228026c200228027046210120022802cc8104210702402002280264450d00200228026010350b024020010d0020024103410220011b3a00b88104200241013602cc01200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241b881046a360228200241c881046a200241b8016a104120022903c88104210d20022802d0810421010240200a450d00200941047441106a2103201321040340024020042d00004109470d000240200441046a2208280200220528020441ffffffff0371450d0020052802001035200828020021050b200510350b200441106a2104200341706a22030d000b0b200d422088210e0240200741ffffffff0071450d00201310350b200ea72103200da7210441052109201841ffffffff0171450d1a201410350c1a0b20022802b001220120022802ac01470d0b200141016a22042001490d2a200141017422092004200920044b1bad42187e220d422088a70d2a200da722044100480d2a0240024020010d0020040d01410421090c0c0b20022802a8012109200141186c220c2004460d0b0240200c0d0020040d01410421090c0c0b2009200c200410372209450d2f0c0b0b200410332209450d2e0c0a0b417f200341016a41c0fdcb001059000b2004200341c0fdcb001059000b2003200541c0fdcb001058000b417f200c41016a41c0fdcb001059000b417f200a41c0fdcb001059000b417f200141c0fdcb001059000b2001201341c0fdcb001058000b200341016a200541c0fdcb001058000b200c41016a200941c0fdcb001058000b200a201341c0fdcb001058000b200220093602a8012002200441186e3602ac010b20022802a8012204200141186c6a2209201336020c20092010ad4220862018ad8437020420092014360200200941106a200aad4220862007ad843702002002200141016a3602b00120152008460d0f0c000b0b200141016a200541c0fdcb001058000b417f200141016a41c0fdcb001059000b200d422088210e200b41087621040c0c0b0240200a450d00200a4104742108201321050340024020052d00004109470d000240200541046a2207280200220a28020441ffffffff0371450d00200a28020010352007280200210a0b200a10350b200541106a2105200841706a22080d000b0b20022802cc810441ffffffff0071450d00201310350b201841ffffffff0171450d04201410350c040b0b200441087621050b200a41ff0171410874200972210920022802bc810441ffffffff0171450d00201410350b2005410874200441ff01717221040b2002280264450d02200228026010350c020b200241013a009801200241013602dc8104200242013702cc8104200241acfdcb003602c881042002413636022c2002200241286a3602d88104200220024198016a360228200241b881046a200241c881046a104120022903b88104210d20022802c081042101410521092016450d00201810350b200d422088a72103200da721040b200241a8016a10b3072003ad4220862004ad84210d20022802ac012204450d00200441186c450d0020022802a80110350b200d422088210e20094108762104024020060d002009210b0c020b200b10352009210b0c010b200220022902ac01222337027c200220043602782003201246210102402006450d00200b10350b024020010d0020024103410220011b3a0060200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241e0006a360228200241c881046a200241b8016a104120022903c88104210d20022802d081042101200241f8006a10b30702402023a72203450d00200341186c450d00200410350b200d422088210e4105210b410021040c010b410c21030c0c0b20004101360200200041106a2001360200200041086a200e422086200d42ffffffff0f838437020020002004410874200b41ff0171723602040c120b200241b8016a200110c707200241c8016a2802002101200241b8016a41086a290300210d20022802bc01210b02400240024020022802b8014101460d002002200241cc016a2802003602d88104200220013602d481042002200b3602c881042002200d3702cc8104200d422088a72108410021044100210a024002400240024002400240034002402004411f4d0d00410f210b0c030b20082001460d012001417f460d06200141016a220520084b0d05200b20016a2d00002103200220053602d48104200341ff00712004411f7174200a72210a200441076a2104200521012003418001710d000b024020044120490d00410d210b2003410f4b0d020b200241003602a0012002420437039801200a0d02410421040c030b200241013a00b88104200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241b881046a360228200241e0006a200241b8016a1041200241c0006a41086a200241e0006a41086a280200360200200220022903603703404105210b0b20024198016a41086a200241c0006a41086a280200220136020020022002290340220d370398010c050b41042104410021090340200941016a21094100210141002108024002400240024002400240024002400240034002402001411f4d0d00410f210b0c030b20022802d08104220b20022802d481042203460d01200341016a22052003490d07200b2005490d0820022802c8810420036a2d00002103200220053602d48104200341ff00712001411f71742008722108200141076a21012003418001710d000b20014120490d022003410f4d0d02410d210b0c010b200241013a0078200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241f8006a360228200241e0006a200241b8016a1041200241306a41086a200241e0006a41086a28020036020020022002290360220d370330200da721064105210b0b20022802382101200228023421030c010b200241b8016a200241c881046a10a70720022802c401210c20022802c001211220022802bc01211620022802b8014101470d0120022802c80121012016210b20122106200c21030b200241d0006a41086a200241b881046a41086a280200360200200220022903b881043703500c010b200241b8016a200241c881046a10ab0720022802c401210320022802c001210620022802bc01210b20022802b8014101470d0320022802c80121010240200c450d00200c4104742108201621050340024020052d00004109470d000240200541046a2209280200220a28020441ffffffff0371450d00200a28020010352009280200210a0b200a10350b200541106a2105200841706a22080d000b0b0240201241ffffffff0071450d00201610350b200241d0006a41086a200241b881046a41086a280200360200200220022903b881043703500b2003ad4220862006ad84210d20024198016a10b207200228029c012203450d082003411c6c450d08200410350c080b417f200541c0fdcb001059000b2005200b41c0fdcb001058000b200241003602c001200242043703b801200241b8016a41002003410274220541027510860120022802c001210702402003450d002005417c6a410276211320022802b80120074102746a2101200b2103034020012003280200360200200141046a2101200341046a21032005417c6a22050d000b200720136a41016a21070b200220073602c0010240200641ffffffff0371450d00200b10350b200241d0006a41086a200241b8016a41086a2802002201360200200241a8016a41086a22052001360200200220022903b801220d3703502002200d3703a8012012ad4220862016ad84210d024020022802a0012203200228029c01470d0020024198016a2003410110f901200228029801210420022802a00121030b20042003411c6c6a2201200d370204200120083602002001410c6a200c360200200120022903a801370210200141186a20052802003602002002200341016a3602a0012009200a470d000b0b2002200229029c01222337028c01200220043602880120022802d4810420022802d88104462101024020022802cc8104450d0020022802c8810410350b024020010d0020024103410220011b3a00b88104200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241b881046a360228200241e0006a200241b8016a10412002290360210d2002280268210120024188016a10b20702402023a72203450d002003411c6c450d00200410350b200d422088210e4105210b410021040c050b410a21030c0f0b200141016a200841c0fdcb001058000b417f200141016a41c0fdcb001059000b200d422088210e200b41087621040c010b200d422088210e200b410876210420022802cc8104450d0020022802c8810410350b20004101360200200041106a2001360200200041086a200e422086200d42ffffffff0f838437020020002004410874200b41ff0171723602040c110b200241b8016a200110c707200241b8016a41106a2802002101200241b8016a410c6a2802002105200241b8016a41086a280200210920022802bc01210b0240024020022802b8014101460d00200241cc016a280200210641002103410021040240024002400240034002402003411f4d0d00410f21010c030b20052001460d012001417f460d042005200141016a220a490d06200b20016a2d0000220841ff00712003411f71742004722104200341076a2103200a21012008418001710d000b024020034120490d00410d21012008410f4b0d020b2006200a46210102402009450d00200b10350b2001450d02410921030c0f0b200241013a0060200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241e0006a360228200241c881046a200241b8016a1041410521010b2000200136020420004101360200200041086a20022903c88104370200200041106a200241c881046a41086a2802003602002009450d14200b10350c140b20024103410220011b3a00b88104200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241b881046a360228200241e0006a200241b8016a1041200241d381046a200241e8006a280200360000200220022903603700cb8104200041053a0004200020022900c881043700052000410c6a200241cf81046a290000370000200041013602000c130b417f200141016a41c0fdcb001059000b2000200b36020420004101360200200041106a20013602002000410c6a2005360200200041086a20093602000c110b200141016a200541c0fdcb001058000b200241b8016a200110c707200241c8016a2802002101200241b8016a41086a290300210d20022802bc01210b02400240024002400240024002400240024020022802b8014101460d002002200241cc016a2802003602d88104200220013602d481042002200b3602c881042002200d3702cc8104200d422088a72108410021044100210a024002400240024002400240034002402004411f4d0d00410f210b0c030b20082001460d012001417f460d06200141016a220520084b0d05200b20016a2d00002103200220053602d48104200341ff00712004411f7174200a72210a200441076a2104200521012003418001710d000b024020044120490d00410d210b2003410f4b0d020b200241003602b001200242043703a801200a0d02410421040c030b200241013a00b88104200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241b881046a360228200241e0006a200241b8016a1041200241306a41086a200241e0006a41086a280200360200200220022903603703304105210b0b200241c0006a41086a200241306a41086a280200220136020020022002290330220d3703400c0b0b410021070340200241b8016a200241c881046a10ad0720022802c401211620022802c001210c20022802bc01210b0240024002400240024002400240024002400240024020022802b8014101460d0002400240024002400240024020022802d08104220420022802d481042203460d00200341016a22012003490d0920042001490d0a20022802c88104220520036a2d00002103200220013602d48104200341034b0d0720030e0401020304010b200220073602b001200241013a009801200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c801200220024198016a360228200241e0006a200241b8016a10410c180b410021084100210303402008411f4b0d150240024020042001460d002001417f460d0c2004200141016a22064f0d01200141016a200441c0fdcb001058000b200220073602b001200241013a009801200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c801200220024198016a360228200241e0006a200241b8016a10410c190b200520016a2d00002109200220063602d48104200941ff00712008411f71742003722103200841076a2108200621012009418001710d000b4100210420084120490d032009410f4d0d030c150b410021084100210303402008411f4b0d140240024020042001460d002001417f460d0c2004200141016a22064f0d01200141016a200441c0fdcb001058000b200220073602b001200241013a009801200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c801200220024198016a360228200241e0006a200241b8016a10410c180b200520016a2d00002109200220063602d48104200941ff00712008411f71742003722103200841076a2108200621012009418001710d000b4101210420084120490d022009410f4b0d140c020b410021084100210303402008411f4b0d130240024020042001460d002001417f460d0c2004200141016a22064f0d01200141016a200441c0fdcb001058000b200220073602b001200241013a009801200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c801200220024198016a360228200241e0006a200241b8016a10410c170b200520016a2d00002109200220063602d48104200941ff00712008411f71742003722103200841076a2108200621012009418001710d000b4102210420084120490d012009410f4b0d130c010b410021084100210303402008411f4b0d120240024020042001460d002001417f460d0c2004200141016a22064f0d01200141016a200441c0fdcb001058000b200220073602b001200241013a009801200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c801200220024198016a360228200241e0006a200241b8016a10410c160b200520016a2d00002109200220063602d48104200941ff00712008411f71742003722103200841076a2108200621012009418001710d000b4103210420084120490d002009410f4b0d120b200220163602bc81042002200c3602b8810420022903b88104210d200720022802ac01470d0a20074101742201200741016a2205200120054b1bad42147e220e422088a70d22200ea7220141004e0d020c220b200220022802c80122013602c08104200220163602bc81042002200c3602b88104200220073602b0010c140b200220073602b00120034108742103410a21040c100b0240024020070d0020010d01410421050c080b20022802a8012105200741146c22082001460d07024020080d0020010d01410421050c080b20052008200110372205450d240c070b200110332205450d230c060b417f200141c0fdcb001059000b2001200441c0fdcb001058000b417f200141016a41c0fdcb001059000b417f200141016a41c0fdcb001059000b417f200141016a41c0fdcb001059000b417f200141016a41c0fdcb001059000b200220053602a8012002200141146e3602ac010b20022802a801200741146c6a2201200436020c2001200d3702042001200b360200200141106a2003360200200741016a220121072001200a470d000b200220013602b00120022802a80121040b20022802d4810420022802d8810446210120022902ac012123024020022802cc8104450d0020022802c8810410350b024020010d002023a7210820024103410220011b3a00b88104200241b8016a41146a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241b881046a360228200241e0006a200241b8016a10412002290360210d2002280268210102402023422088a72203450d00200341146c21052004210303400240200341046a280200450d00200328020010350b200341146a21032005416c6a22050d000b0b200d422088210e4105210b410021032008450d0b200841146c450d0b200410350c0b0b410821030c130b200141016a200841c0fdcb001058000b417f200141016a41c0fdcb001059000b200d422088210e200b41087621030c070b200220073602b001410f2104410021030c010b200220073602b001410d2104410021030b0c010b200228026021012002290264210d41052104410021030b200220013602b881042002200d3702bc8104200d422088210d0240200c450d00200b10350b2004200372210b200da7210120022802b00121070b20022903b88104210d02402007450d0020022802a8012104200741146c210303400240200441046a280200450d00200428020010350b200441146a21042003416c6a22030d000b0b20022802ac012204450d00200441146c450d0020022802a80110350b200d422088210e200b410876210320022802cc8104450d0020022802c8810410350b20004101360200200041106a2001360200200041086a200e422086200d42ffffffff0f838437020020002003410874200b41ff0171723602040c0f0b200241b8016a200110c707200241c8016a2802002101200241b8016a41086a290300210d20022802bc01210b0240024002400240024002400240024002400240024002400240024020022802b8014101460d002002200241cc016a2802003602d88104200220013602d481042002200b3602c881042002200d3702cc8104200d422088a72108410021044100210a024002400240034002402004411f4d0d00410f21040c030b20082001460d012001417f460d05200141016a220320084b0d0a200b20016a2d00002105200220033602d48104200541ff00712004411f7174200a72210a200441076a2104200321012005418001710d000b024020044120490d00410d21042005410f4b0d020b200241003602b001200242043703a801200a0d02410421040c0f0b200241013a0060200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241e0006a36022820024188016a200241b8016a1041410521040b200241b881046a41086a20024188016a41086a28020022013602002002200229038801220d3703b881040c0c0b200a417f6a2106200241b8016a410472210741042104410421124104210a4100210903400240024020082003460d00200341016a22052003490d0520082005490d06200b20036a2c00002101200220053602d48104200141004e0d01411921160c0a0b200241013a008801200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c801200220024188016a360228200241e0006a200241b8016a10410c0a0b41062116200141c00071450d080240200141807f72220c41ff017141fc014f0d00200c21010c090b02400240024020082005460d00200341026a21032005417f460d0820082003490d09200b20056a2d00002101200220033602d481040240200141014d0d00410c21160c0c0b4100210320010e020201020b200241013a008801200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c801200220024188016a360228200241e0006a200241b8016a10410c0b0b410121030b200241b8016a200241c881046a10a707200241306a41086a200741086a2802002201360200200241c0006a41086a2205200136020020022007290200370340024020022802b8014101470d0020022d00c801210420022d00c901210320022f01ca0121010c0c0b200c417f73210820024198016a41086a20052802002201360200200241b881046a41086a2205200136020020022002290340220d370398012002200d3703b881040240200920022802ac01470d00200241a8016a20094101108c0120022802b001210920022802a801220421122004210a0b2005280200210520022903b88104210d200a20094104746a220120083a000c2001200d3702002001410d6a20033a0000200141086a20053602002002200941016a22093602b0012006450d0d2006417f6a210620022802d48104210320022802d08104210820022802c88104210b0c000b0b200d422088210e200b41087621030c0c0b417f200141016a41c0fdcb001059000b417f200541c0fdcb001059000b2005200841c0fdcb001058000b417f200341c0fdcb001059000b2003200841c0fdcb001058000b200141016a200841c0fdcb001058000b0c010b200228026021032002280264210520022802682104410521160b2002200536024820022003360244200220013a0041200220163a004020044110762101200441087621030b20024198016a41086a200241c0006a41086a28020036020020022002290340220e37039801200341ff0171410874200441ff017172210b20014110742106200229029c01210d02402009450d00200a20094104746a210803400240200a2802082204450d00200a2802002101200441047421040340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d0020032802001035200528020021030b200310350b200141106a2101200441706a22040d000b0b200a41106a21010240200a41046a28020041ffffffff0071450d00200a28020010350b2001210a20012008470d000b0b200b2006722101200ea7210420022802ac0141ffffffff0071450d00201210350b200d422088210e20044108762103024020022802cc81040d002004210b0c020b20022802c8810410352004210b0c010b20022802d4810420022802d8810446210120022902ac012123024020022802cc8104450d0020022802c8810410350b024020010d0020024103410220011b3a00b88104200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241b881046a360228200241e0006a200241b8016a10412002290360210d2002280268210102402023422088a72203450d00200420034104746a21092004210b03400240200b2802082205450d00200b2802002103200541047421050340024020032d00004109470d000240200341046a220a280200220828020441ffffffff0371450d0020082802001035200a28020021080b200810350b200341106a2103200541706a22050d000b0b200b41106a21030240200b41046a28020041ffffffff0071450d00200b28020010350b2003210b20032009470d000b0b200d422088210e4105210b41002103202342ffffffff0083500d01200410350c010b410721030c080b20004101360200200041106a2001360200200041086a200e422086200d42ffffffff0f838437020020002003410874200b41ff0171723602040c0e0b200241b8016a200110c707200241c8016a2802002101200241b8016a41086a290300210d20022802bc01210802400240024020022802b8014101460d002002200241cc016a2802003602d88104200220013602d48104200220083602c881042002200d3702cc8104200d422088a7210541002104410021030240024002400240024003402004411f4b0d010240024020052001460d002001417f460d0a200141016a220a20054d0d01200141016a200541c0fdcb001058000b200220053602d48104200241013a00b88104200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241b881046a360228200241e0006a200241b8016a1041200241306a41086a200241e0006a41086a28020036020020022002290360370330410521080c030b200820016a2d0000220b41ff00712004411f71742003722103200441076a2104200a2101200b418001710d000b2002200a3602d48104024020044120490d00410d2108200b410f4b0d020b4100210120024100360268200242043703604104210402402003450d000340200241b8016a200241c881046a10b00720022903c001210d20022802bc01210820022802b8014101460d04024020012002280264470d00200241e0006a2001410110870120022802602104200228026821010b20042001410c6c6a2205200d370204200520083602002002200141016a22013602682003417f6a22030d000b0b20022802d4810420022802d8810446210120022902642123024020022802cc8104450d0020022802c8810410350b20010d0420024103410220011b3a00b88104200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241b881046a360228200241e0006a200241b8016a10412002290360220d422088210e2002280268210141052108410021032023a72205450d062005410c6c450d06200410350c060b200220013602d48104410f21080b200241c0006a41086a200241306a41086a280200220136020020022002290330220d3703400c010b200241c8016a280200210120022802642203450d002003410c6c450d00200410350b200d422088210e2008410876210320022802cc8104450d0220022802c8810410350c020b410621030c090b200d422088210e200841087621030b20004101360200200041106a2001360200200041086a200e422086200d42ffffffff0f838437020020002003410874200841ff0171723602040c0e0b417f200141016a41c0fdcb001059000b200241b8016a200110c707200241c8016a2802002101200241b8016a41086a290300210d20022802bc01210b02400240024002400240024020022802b8014101460d002002200241cc016a2802003602d88104200220013602d481042002200b3602c881042002200d3702cc8104200d422088a721034100210441002108024002400240024003402004411f4b0d010240024020032001460d002001417f460d08200141016a220520034d0d01200141016a200341c0fdcb001058000b200220033602d48104200241013a00b88104200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241b881046a360228200241e0006a200241b8016a1041200241306a41086a200241e0006a41086a28020036020020022002290360370330410521090c030b200b20016a2d0000220a41ff00712004411f71742008722108200441076a210420052101200a418001710d000b200220053602d48104024020044120490d00410d2109200a410f4b0d020b4100210a200241003602c08104200242043703b8810420080d02410421040c080b200220013602d48104410f21090b200241c0006a41086a200241306a41086a280200220136020020022002290330220d3703400c010b2008417f6a21084104210402400240034020032005460d01200541016a22012005490d0620032001490d07200b20056a2c00002103200220013602d48104410021090240200341004e0d00411921060c030b410721060240200341c000710d000c030b200341807f7222034170470d02200241b8016a200241c881046a10b00720022802bc012101024020022802b8014101470d00200141ff0171210620014180807c7121092001410876210320022903c001220d422088a7210b200241c8016a2802002101200da721050c030b20022903c001210d0240200a20022802bc8104470d00200241b881046a200a410110870120022802b88104210420022802c08104210a0b2004200a410c6c6a2203200d370204200320013602002002200a41016a220a3602c081042008450d082008417f6a210820022802d48104210520022802d08104210320022802c88104210b0c000b0b200241013a00a801200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241a8016a360228200241e0006a200241b8016a1041200228026021052002280264210b2002280268210141002109410521060b200bad4220862005ad84210d2009200341ff017141087472200672210920022802bc81042203450d002003410c6c450d00200410350b200d422088210e20094108762103024020022802cc81040d002009210b0c060b20022802c8810410352009210b0c050b200d422088210e200b41087621030c040b417f200141016a41c0fdcb001059000b417f200141c0fdcb001059000b2001200341c0fdcb001058000b20022802d4810420022802d8810446210120022902bc81042123024020022802cc8104450d0020022802c8810410350b024020010d0020024103410220011b3a00b88104200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241b881046a360228200241e0006a200241b8016a10412002290360220d422088210e200228026821014105210b410021032023a72205450d012005410c6c450d01200410350c010b410521030c060b20004101360200200041106a2001360200200041086a200e422086200d42ffffffff0f838437020020002003410874200b41ff0171723602040c0c0b200241b8016a200110c707200241c8016a2802002101200241b8016a41086a290300210d20022802bc01210b024002400240024002400240024002400240024020022802b8014101460d00200241cc016a280200210c200d422088a72103200da721074100210441002108034002402004411f4d0d00410f21090c090b20032001460d072001417f460d03200141016a220520034b0d05200b20016a2d0000220a41ff00712004411f71742008722108200441076a210420052101200a418001710d000b024020044120490d00410d2109200a410f4b0d080b410021122002410036026820024204370360410421040240024002402008450d00410021160340201641016a21164100210a200521014100210903400240200a411f4d0d00410f21090c050b20032001460d032001417f460d08200141016a220520034b0d0a200b20016a2d0000220641ff0071200a411f71742009722109200a41076a210a200521012006418001710d000b0240200a4120490d002006410f4d0d00410d21090c040b20024198016a41086a200241c0006a41086a2802003602002002200229034037039801024020122002280264470d00200241e0006a2012410110860120022802602104200228026821120b200420124102746a20093602002002201241016a221236026820162008470d000b0b2005200c4621012002290264212302402007450d00200b10350b2001450d03410421030c100b200241013a00b88104200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241b881046a360228200241c881046a200241b8016a1041200241306a41086a200241c881046a41086a280200360200200220022903c88104370330410521090b200241386a28020021012002290330210d200228026441ffffffff0371450d08200410350c080b200d422088210e200b41087621030c080b20024103410220011b3a0060200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241e0006a360228200241c881046a200241b8016a104120022903c88104220d422088210e20022802d0810421014105210b41002103202342ffffffff0383500d07200410350c070b417f200141016a41c0fdcb001059000b417f200141016a41c0fdcb001059000b200141016a200341c0fdcb001058000b200141016a200341c0fdcb001058000b200241013a00c88104200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241c881046a36022820024188016a200241b8016a1041410521090b200241b881046a41086a20024188016a41086a28020022013602002002200229038801220d3703b881040b200d422088210e41002103024020070d002009210b0c010b200b10352009210b0b20004101360200200041106a2001360200200041086a200e422086200d42ffffffff0f838437020020002003410874200b41ff0171723602040c0b0b200241b8016a200110c707200241c8016a2802002101200241b8016a41086a290300210d20022802bc01210b024002400240024002400240024020022802b8014101460d002002200241cc016a2802003602d88104200220013602d481042002200b3602c881042002200d3702cc8104200d422088a7210a4100210441002108024002400240024002400240034002402004411f4d0d00410f210b0c030b200a2001460d012001417f460d06200141016a2205200a4b0d05200b20016a2d00002103200220053602d48104200341ff00712004411f71742008722108200441076a2104200521012003418001710d000b024020044120490d00410d210b2003410f4b0d020b200241003602b001200242043703a80120080d02410421040c030b200241013a00b88104200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241b881046a360228200241e0006a200241b8016a1041200241306a41086a200241e0006a41086a280200360200200220022903603703304105210b0b200241c0006a41086a200241306a41086a280200220136020020022002290330220d3703400c090b20022802ac01210620022802b001210c410021150340200241b8016a200241c881046a10ad0720022802c401211420022802c001211320022802bc01210b024002400240024002400240024002400240024002400240024002400240024002400240024020022802b8014101460d00200241b8016a200241c881046a10ad0720022802c401211020022802c001211820022802bc012116024002400240024020022802b8014101460d000240024002400240024020022802d08104220320022802d481042205460d00200541016a22012005490d0a20032001490d0b20022802c88104220720056a2d00002104200220013602d481040240200441034d0d00410921090c230b20040e0401020304010b200241013a009801200241013602cc01200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c801200220024198016a360228200241e0006a200241b8016a10410c200b410021124100210441002109034002402004411f4d0d00410f2109410021040c080b20032001460d062001417f460d0b2003200141016a220a490d12200720016a2d000021052002200a3602d48104200541ff00712004411f71742009722109200441076a2104200a21012005418001710d000b4100211220044120490d172005410f4d0d17410d2109410021040c060b0240024020032001460d00200541026a21042001417f460d0c20032004490d0d200720016a2c00002101200220043602d4810402402001417f4a0d00411921030c160b200141c00071450d14200141807f7222014170470d14200241b8016a200241c881046a10b00720022903c001210d20022802bc01210920022802b8014101470d0120022802c80121040c160b200241013a009801200241013602cc01200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c801200220024198016a360228200241e0006a200241b8016a10412002290360210d20022802682104410521030c140b410121120c180b200241b8016a200241c881046a10b00720022903c001210d20022802bc012109024020022802b8014101460d00410221120c180b200220022802c8013602c0012009411876210320094110762112200941087621040c140b0240024020032001460d00200541026a210a2001417f460d0c2003200a490d0d200720016a2c000021042002200a3602d481040240200441004e0d0041192109410021030c200b200441c000710d010c110b200241013a009801200241013602cc01200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c801200220024198016a360228200241e0006a200241b8016a1041410521092002290264210e20022802602101410021030c1e0b200441807f72220441ff017141fb014d0d0f02402003200a460d00200541036a2101200a417f460d0d20032001490d0e2007200a6a2d00002105200220013602d481040240200541014d0d00410c2109200521040c1f0b2004417f73210a410321124100210320050e021702170b200241013a009801200241013602cc01200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c801200220024198016a360228200241e0006a200241b8016a10410c1c0b200220022802c80122013602c08104200220103602bc8104200220183602b881042016411876210320164110762112201641087621040c1d0b410121030c130b200241013a009801200241013602cc01200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c801200220024198016a360228200241e0006a200241b8016a1041200228026021012002290264210e41052109410021040b410021030c190b20022802c8012101200220143602bc8104200220133602b88104200220063602ac012002200c3602b0010c1a0b417f200141c0fdcb001059000b2001200341c0fdcb001058000b417f200141016a41c0fdcb001059000b417f200441c0fdcb001059000b2004200341c0fdcb001058000b417f200a41c0fdcb001059000b200a200341c0fdcb001058000b417f200141c0fdcb001059000b2001200341c0fdcb001058000b200141016a200341c0fdcb001058000b410621090c0d0b410721030b200141ff017141087420037221090b200220043602c0012009411876210320094110762112200941087621040b2002200d3703b80120022902bc01210e200da721010c090b0b0b200220143602bc8104200220133602b8810420022903b88104210e02400240200c2006460d0020062105200c21060c010b200641016a22012006490d11200641017422042001200420014b1bad42287e2223422088a70d112023a722014100480d1102400240024020060d0020010d01410421040c020b20022802a8012104200641286c22052001460d01024020050d0020010d01410421040c020b20042005200110372204450d170c010b200110332204450d160b200220043602a801200141286e21050b20022802a8012204200641286c6a220120123a00182001201636020c2001200e3702042001200b360200200141206a200d3702002001411c6a20093602002001411a6a20033a0000200141196a200a3a0000200141146a2010360200200141106a2018360200200641016a210c20052106201541016a22152008470d000b200220053602ac012002200c3602b0010b20022802d4810420022802d8810446210120022902ac012123024020022802cc8104450d0020022802c8810410350b024020010d002023a7210820024103410220011b3a00b88104200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241b881046a360228200241e0006a200241b8016a10412002290360210d2002280268210102402023422088a72203450d00200341286c21052004210303400240200341046a280200450d00200328020010350b0240200341106a280200450d002003410c6a28020010350b200341286a2103200541586a22050d000b0b200d422088210e4105210b410021032008450d09200841286c450d09200410350c090b410321030c0c0b200141016a200a41c0fdcb001058000b417f200141016a41c0fdcb001059000b200d422088210e200b41087621030c050b200228026021012002290264210e410521090b200220013602b881042002200e3702bc8104200e422088a72101024020180d00200921160c010b20161035200921160b02402013450d00200b10350b2002200c3602b001200220063602ac012003411874201241ff017141107472200441ff017141087472201641ff017172210b0b20022903b88104210d20022802a80121050240200c450d00200c41286c21032005210403400240200441046a280200450d00200428020010350b0240200441106a280200450d002004410c6a28020010350b200441286a2104200341586a22030d000b0b2006450d00200641286c450d00200510350b200d422088210e200b410876210320022802cc8104450d0020022802c8810410350b20004101360200200041106a2001360200200041086a200e422086200d42ffffffff0f838437020020002003410874200b41ff0171723602040c0a0b200a41087621030b20004101360200200041106a2001360200200041086a200e422086200d42ffffffff0f838437020020002003410874200a41ff0171723602040c080b4100210141002104024002400240024002400240024002400340024020084105470d00410f21070c030b20032008460d01200320084d0d04200620086a2d0000220541ff00712001411f71742004722104200141076a2101200841016a220a21082005418001710d000b024020014120490d002005410f4d0d00410d21070c020b20040d024101211641002107410021054100210b0c070b200241013a0060200241cc016a4101360200200242013702bc01200241acfdcb003602b8012002413636022c2002200241286a3602c8012002200241e0006a360228200241c881046a200241b8016a1041200241306a41086a200241c881046a41086a280200360200200220022903c88104220d370330410521070b200d422088a7210520022802382101200da7210b0c030b200241b8016a4100418008109f081a4100210541002108410121164100210702400240024003402003200a6b200420076b22014180082001418008491b2201490d01200a20016a220c200a490d022003200c490d03200241b8016a2006200a6a2001109d081a02400240200820056b2001490d002008210b0c010b200520016a220a2005490d0c2008410174220b200a200b200a4b1b220b4100480d0c0240024020080d000240200b0d00410121160c020b200b103322160d010c120b2008200b460d0020162008200b10372216450d110b200b21080b201620056a200241b8016a2001109d081a200520016a2105200c210a2004200120076a22074d0d050c000b0b200241013a00b88104200241dc81046a4101360200200242013702cc8104200241acfdcb003602c881042002413636022c2002200241286a3602d881042002200241b881046a360228200241e0006a200241c881046a10412002290360220d422088a7210520022802682101200da7210b410521072008450d04201610350c040b200a200c41c0fdcb001059000b200c200341c0fdcb001058000b200841016a200341c0fdcb001058000b200241b8016a20162005107420022802b8014101470d01410821070240200b450d00201610350b0b2005ad422086200bad84210d2009450d03200610350c030b201641807e712107200c210a0b2003200a490d052003200a6b2203417f4c0d030240024020030d0041002104410121010c010b200310332201450d05200321040b0240024020042003490d00200421080c010b200441017422082003200820034b1b22084100480d03024020040d00200810332201450d080c010b20042008460d0020012004200810372201450d070b2007201641ff01717221042005ad422086200bad84212320012006200a6a2003109d081a2003ad4220862008ad84210d410121032009450d00200610350b200020033a000420004100360200200041056a20022f00153b0000200041186a200d370200200041146a20013602002000410c6a2023370200200041086a2004360200200041206a2002290200370200200041076a200241176a2d00003a0000200041286a200241086a290200370200200041306a200241106a2802003602000c060b2000200736020420004101360200200041106a2001360200200041086a200d3702000c050b103e000b1044000b1045000b200a20034188d9cb001059000b103c000b200241e081046a24000bdc0101057f024020002802082201450d00200028020022022001411c6c6a21030340024020022802042200450d0002402002410c6a2802002201450d00200141047421010340024020002d00004109470d000240200041046a2204280200220528020441ffffffff0371450d0020052802001035200428020021050b200510350b200041106a2100200141706a22010d000b0b200241086a28020041ffffffff0071450d00200228020410350b2002411c6a21000240200241146a28020041ffffffff0371450d00200228021010350b2000210220002003470d000b0b0bd90101057f024020002802082201450d0020002802002202200141186c6a210303400240200241046a28020041ffffffff0171450d00200228020010350b0240200241146a2802002201450d00200228020c2100200141047421010340024020002d00004109470d000240200041046a2204280200220528020441ffffffff0371450d0020052802001035200428020021050b200510350b200041106a2100200141706a22010d000b0b200241186a21000240200241106a28020041ffffffff0071450d00200228020c10350b2000210220002003470d000b0b0bd50101057f024020002802082201450d00200028020022022001411c6c6a21030340024020022802042200450d0002402002410c6a2802002201450d00200141047421010340024020002d00004109470d000240200041046a2204280200220528020441ffffffff0371450d0020052802001035200428020021050b200510350b200041106a2100200141706a22010d000b0b200241086a28020041ffffffff0071450d00200228020410350b2002411c6a21000240200241146a280200450d00200228021010350b2000210220002003470d000b0b0be40101047f0240200041206a28020022032000411c6a280200470d000240024002400240200341016a22042003490d00200341017422052004200520044b1b220620066a22042006490d0020044100480d00024020030d0020040d02410121030c040b2000280218210320052004460d03024020050d0020040d02410121030c040b20032005200410372203450d020c030b103e000b2004103322030d010b103c000b200020033602182000411c6a2004410176360200200028022021030b200028021820034101746a220320023a0001200320013a00002000200028022041016a3602200be70101037f0240200041386a2802002202200041346a280200470d000240024002400240200241016a22032002490d00200241017422042003200420034b1b220341ffffffff03712003470d00200341027422034100480d00024020020d0020030d02410421040c040b20002802302104200241027422022003460d03024020020d0020030d02410421040c040b20042002200310372204450d020c030b103e000b2003103322040d010b103c000b20002004360230200041346a2003410276360200200028023821020b200028023020024102746a20013602002000200028023841016a3602380b8d0302037f017e230041c0006b22022400200141086a28020021032001280204210420022001280200220136020002400240024002402001418080044b0d002004450d022002200336020402400240200120034b0d002003418080044d0d042002413c6a41013602002002420237022c200241e0aacc003602282002410136020c200241bcaacc003602082002200241086a360238200241186a200241286a1041200241186a21010c010b2002413c6a4102360200200241246a41013602002002420237022c200241d0aacc003602282002410136021c2002200241186a360238200220023602202002200241046a360218200241086a200241286a1041200241086a21010b20012902042105200128020021010c010b2002413c6a41013602002002420237022c200241c0aacc003602282002410136020c200241bcaacc003602082002200241086a360238200241186a200241286a104120022802182101200229021c21050b2001450d0020002005370204200020013602000c010b200041003602000b200241c0006a24000be00501037f230041f0006b2204240002400240024020012802084102460d00412e10332201450d01200041013a0000200141266a41002900d4ac4c370000200141206a41002900ceac4c370000200141186a41002900c6ac4c370000200141106a41002900beac4c370000200141086a41002900b6ac4c370000200141002900aeac4c370000200041086a42ae808080e005370200200041046a20013602000c020b0240024002400240024002400240200128020022052d0000416e6a2201411e4b0d004100210620010e1f03000000000000000000000000000000000000000000000000000006040102030b412010332201450d06200041013a0000200141186a41002900f4ac4c370000200141106a41002900ecac4c370000200141086a41002900e4ac4c370000200141002900dcac4c370000200041086a42a08080808004370200200041046a20013602000c070b410221060c040b410321060c030b20042005280204220136020c0240024020012003490d0041fcaccc002105200441e8006a2103200441d0006a2101200441c0006a21020c010b200220014101746a22012d0001450d02418cadcc002105200441386a2103200441206a2101200441106a21020b20034101360204200141146a410136020020012003360210200142023702042001200536020020032004410c6a360200200220011041200041013a00002000410c6a200241086a280200360200200041046a20022902003702000c040b410121060c010b20012d000021060b0240200541106a2d00004106470d00200041003a0000200020063a00010c020b412910332201450d00200041013a0000200141286a41002d00c4ad4c3a0000200141206a41002900bcad4c370000200141186a41002900b4ad4c370000200141106a41002900acad4c370000200141086a41002900a4ad4c3700002001410029009cad4c370000200041086a42a98080809005370200200041046a20013602000c010b1045000b200441f0006a24000b8f0201017f230041106b220224000240024002400240024020002d00000e0401020300010b200220012802184180fdcb0041032001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c030b200220012802184183fdcb0041032001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c020b200220012802184186fdcb0041032001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c010b200220012802184189fdcb0041032001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040b200241106a240020000bbb0101027f0240200041046a2802002001470d000240024002400240200141016a22022001490d00200141017422032002200320024b1b220241ffffffff01712002470d00200241037422024100480d00024020010d0020020d02410421030c040b20002802002103200141037422012002460d03024020010d0020020d02410421030c040b20032001200210372203450d020c030b103e000b2002103322030d010b103c000b20002003360200200041046a20024103763602000b0bbbcb0203047f017e057f230041a0016b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020022d00000eac0101cc0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa0100010b20034188016a200141186a2204200141286a410110f207024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490dcb01200241017422062005200620054b1b22054100480dcb010240024020020d002005103322040d010cd2010b2004280200210420022005460d0020042002200510372204450dd1010b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000ccd010b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450dcc012003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b2001450dcc010ccb010b200328028c012201450dcb0120034190016a29030021070cca010b200141306a2802002202450da90102400240200241037420012802286a41786a22052802002204200141206a220628020022024b0d00200421010c010b024002402001411c6a280200220820026b200420026b2209490d002001280218210a200221010c010b200220096a220a2002490dc9012008410174220b200a200b200a4b1b220b4100480dc9010240024020080d000240200b0d004101210a0c020b200b1033220a450dd0010c010b2001280218210a2008200b460d00200a2008200b1037220a450dcf010b2001200a3602182001411c6a200b360200200141206a28020021010b200a20016a21080240024020094102490d002008410420042002417f736a2202109f081a200a200220016a22016a21080c010b2009450d010b200841043a0000200141016a21010b20062001360200200541013a00060cca010b0240200141306a2802002204200141346a22052802004f0d002002310001422886200141206a350200842107024020042001412c6a280200470d00200141286a200410ba07200141306a28020021040b200128022820044103746a2007370200200141306a2201200128020041016a3602000cca010b2003419c016a220141013602002003420137028c01200341e8b1cc003602880120034101360234200320053602302003200341306a36029801200341c0006a20034188016a104120032802402202450dc9012003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b2001450dc90120002007370204200020013602000cca010b0240200141306a2802002204200141346a22052802004f0d002002310001422886200141206a35020084428080808030842107024020042001412c6a280200470d00200141286a200410ba07200141306a28020021040b200128022820044103746a2007370200200141306a2201200128020041016a3602000cc9010b2003419c016a220141013602002003420137028c01200341e8b1cc003602880120034101360234200320053602302003200341306a36029801200341c0006a20034188016a104120032802402202450dc8012003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b2001450dc80120002007370204200020013602000cc9010b2002310001210720034188016a200141186a200141286a2204410010f20720032d0088014101460da7010240200141306a2802002202200141346a22052802004f0d002007422886200141206a35020084428080808010842107024020022001412c6a280200470d002004200210ba07200141306a28020021020b200128022820024103746a2007370200200141306a2201200128020041016a3602000cc8010b2003419c016a220141013602002003420137028c01200341e8b1cc003602880120034101360234200320053602302003200341306a36029801200341c0006a20034188016a104120032802402202450dc7012003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b2001450dc70120002007370204200020013602000cc8010b200141306a2802002202450da70102400240200141286a22042802002002417f6a4103746a22022d00044101470d002002310005210720034188016a200141186a200410f307200328028801450d012000200329038801370200200041086a20034188016a41086a2802003602000cc9010b411a10332201450da901200141186a41002f00b0a54c3b0000200141106a41002900a8a54c370000200141086a41002900a0a54c37000020014100290098a54c3700002000429a808080a003370204200020013602000cc8010b0240200141306a2802002202200141346a22052802004f0d002007422886200141206a35020084428080808020842107024020022001412c6a280200470d002004200210ba07200141306a28020021020b200128022820024103746a2007370200200141306a2201200128020041016a3602000cc7010b2003419c016a220141013602002003420137028c01200341e8b1cc003602880120034101360234200320053602302003200341306a36029801200341c0006a20034188016a104120032802402202450dc6012003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b2001450dc60120002007370204200020013602000cc7010b200141306a2802002202450da8012002410374200141286a22062802006a2204417d6a220a2d0000210502402004417c6a2d00004101470d00200541ff01714104470daa010b02400240024002400240024020024101460d0020034188016a200141186a2202200610f3072003280288010d01200541ff01714104460dcb01200141206a2802002204200141246a22062802004f0d0520042001411c6a280200470d04200441016a22062004490dc8012004410174220a2006200a20064b1b22064100480dc80120040d02200610332202450dcd010c030b024020012d003822024104460d0020034188016a200141186a2006200210f407200328028801450d002000200329038801370200200041086a20034188016a41086a2802003602000ccc010b20034188016a200141186a200610f307200328028801450dca012000200329038801370200200041086a20034188016a41086a2802003602000ccb010b2000200329038801370200200041086a20034188016a41086a2802003602000cca010b2002280200210220042006460d0020022004200610372202450dca010b200120023602182001411c6a2006360200200141206a28020021040b200128021820046a20053a0000200141206a2201200128020041016a3602000cc6010b2003419c016a220141013602002003420137028c01200341e8b1cc003602880120034101360234200320063602302003200341306a36029801200341c0006a20034188016a104120032802402202450dc5012003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b2001450dc50120002007370204200020013602000cc6010b2003200241046a2802002202360278024002400240200141306a280200220420024d0d0020042002417f736a220220044f0dac01200141286a220428020020024103746a22022d00044103460d0220022d0005220241ff01714104460d0220034188016a200141186a2004200210f4072003280288012202450d02200329028c0121070c010b2003419c016a22024102360200200341cc006a41013602002003420237028c0120034198b0cc003602880120034101360244200320043602302003200341c0006a360298012003200341306a3602482003200341f8006a360240200341e8006a20034188016a1041200328026821042003200329026c37026c20032004360268200241013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402102200329024421070240200328026c450d00200328026810350b2002450d010b20002007370204200020023602000cc6010b200141306a2802002202450daa0102400240200241037420012802286a41786a22052802002204200141206a220628020022024b0d00200421010c010b024002402001411c6a280200220820026b200420026b2209490d002001280218210a200221010c010b200220096a220a2002490dc3012008410174220b200a200b200a4b1b220b4100480dc3010240024020080d000240200b0d004101210a0c020b200b1033220a450dca010c010b2001280218210a2008200b460d00200a2008200b1037220a450dc9010b2001200a3602182001411c6a200b360200200141206a28020021010b200a20016a21080240024020094102490d002008410420042002417f736a2202109f081a200a200220016a22016a21080c010b2009450d010b200841043a0000200141016a21010b20062001360200200541013a00060cc4010b200241046a280200210220034188016a200141186a2205200141286a2204410010f20702400240024020032d0088014101460d00200141306a2802002101200320023602780240200120024d0d0020012002417f736a220220014f0db401200428020020024103746a22012d00044103460dc70120012d0005220141ff01714104460dc70120034188016a20052004200110f4072003280288012201450dc701200329028c0121070c030b2003419c016a22024102360200200341cc006a41013602002003420237028c0120034198b0cc003602880120034101360244200320013602302003200341c0006a360298012003200341306a3602482003200341f8006a360240200341e8006a20034188016a1041200328026821012003200329026c37026c20032001360268200241013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a10412003280240210120032902442107200328026c450d01200328026810350c010b20034190016a2903002107200328028c0121010b2001450dc4010b20002007370204200020013602000cc4010b200241046a2802002202280204210620022802002104200320022802082205360278200141306a280200220220054d0dbd0120022005417f736a220520024f0da901410421080240200141286a220c280200220a20054103746a22052d00044103460d0020052d000521080b200320083a00602006450db701200841ff0171220b4104460db601200641027421060340200320042802002205360278200220054d0db90120022005417f736a220520024f0dc101200a20054103746a22052d00044103460dba0120052d000522094104460dba01200b2009470dba01200441046a21042006417c6a22060d000cb8010b0b024020012d003822024104460d0020034188016a200141186a200141286a200210f407200328028801450d002000200329038801370200200041086a20034188016a41086a2802003602000cc3010b200141306a2802002202450da90102400240200241037420012802286a41786a22052802002204200141206a220628020022024b0d00200421010c010b024002402001411c6a280200220820026b200420026b2209490d002001280218210a200221010c010b200220096a220a2002490dc0012008410174220b200a200b200a4b1b220b4100480dc0010240024020080d000240200b0d004101210a0c020b200b1033220a450dc7010c010b2001280218210a2008200b460d00200a2008200b1037220a450dc6010b2001200a3602182001411c6a200b360200200141206a28020021010b200a20016a21080240024020094102490d002008410420042002417f736a2202109f081a200a200220016a22016a21080c010b2009450d010b200841043a0000200141016a21010b20062001360200200541013a00060cc1010b200128020021042003200241046a280200220236028401024002400240024002400240024002400240200441386a28020020024d0d002003200428023020024102746a2802002202360230024002402004412c6a28020020024d0d00200341cc006a200428022420024104746a22042d000d220a3a0000200341c8006a2004280208220236020020042802002104410021050c010b410121052003419c016a41013602002003420237028c01200341f0aecc00360288012003410136027c2003200341f8006a360298012003200341306a360278200341e8006a20034188016a1041200341c8006a200329026c22073703002007422088a7210a200328026821042007a721020b200320053602402003200436024420050d0102402002450d002004417f6a2104200141286a2105200141186a2106034020034188016a20062005200420026a2d000010f20720032d0088014101460d082002417f6a22020d000b0b200a41ff01714104460dc901200141206a2802002202200141246a22042802004f0d0520022001411c6a280200470d04200241016a22042002490dc601200241017422052004200520044b1b22044100480dc60120020d02200410332205450dcb010c030b2003419c016a41013602002003420237028c01200341ccaecc0036028801200341013602642003200341e0006a36029801200320034184016a360260200341e8006a20034188016a1041200341c8006a200329026c370300200341013602402003200328026822043602440b200341c8006a21010c050b2001280218210520022004460d0020052002200410372205450dc8010b200120053602182001411c6a2004360200200141206a28020021020b200128021820026a200a3a0000200141206a2201200128020041016a3602000cc4010b2003419c016a220141013602002003420137028c01200341e8b1cc003602880120034101360234200320043602302003200341306a36029801200341c0006a20034188016a104120032802402202450dc3012003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402104200329024421070240200328026c450d00200328026810350b20040d020cc3010b20034190016a2101200328028c0121040b2004450dc101200129020021070b20002007370204200020043602000cc1010b200241046a28020021062001280200210220034100360268200241146a280200450da80120034188016a200141186a2204200141286a2205410010f20720032d0088014101460da9012001280200220a412c6a28020021022003200636026802400240024002400240200220064d0d00200a28022420064104746a22062d000d210a024020062802082202450d002006280200417f6a2106034020034188016a20042005200620026a2d000010f20720032d0088014101460db1012002417f6a22020d000b0b200a41ff01714104460dc401200141206a2802002202200141246a22052802004f0d0420022001411c6a280200470d03200241016a22052002490dc101200241017422062005200620054b1b22054100480dc10120020d01200510332204450dc6010c020b2003419c016a41013602002003420237028c01200341f0aecc0036028801200341013602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a10410cb5010b2004280200210420022005460d0020042002200510372204450dc4010b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a200a3a0000200141206a2201200128020041016a3602000cc0010b2003419c016a220141013602002003420137028c01200341e8b1cc003602880120034101360234200320053602302003200341306a36029801200341c0006a20034188016a104120032802402202450dbf012003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a10412003280240210120032902442107200328026c450db201200328026810350cb2010b20034188016a200141186a200141286a410410f20720032d0088014101470dbe01200328028c012201450dbe01200020034190016a290300370204200020013602000cbf010b20034188016a200141186a2204200141286a2205410010f20720034188016a21020240024020032d0088014101460d0020034188016a20042005410410f20720034188016a210220032d0088014101460d0020034188016a2004200520032d008901220610f20720034188016a210220032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490dbe012002410174220a2005200a20054b1b22054100480dbe010240024020020d00200510332204450dc5010c010b2004280200210420022005460d0020042002200510372204450dc4010b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a20063a0000200141206a2201200128020041016a3602000cc0010b2003419c016a220141013602002003420137028c01200341e8b1cc003602880120034101360234200320053602302003200341306a36029801200341c0006a20034188016a104120032802402202450dbf012003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010cbf010b200241046a2802002201450dbe01200241086a29020021070b20002007370204200020013602000cbe010b20034188016a200141046a200241046a28020010f5070240024020032d0088014101460d000240200141206a2802002202200141246a22042802004f0d0020032d0089012104024020022001411c6a280200470d00200241016a22052002490dbd01200241017422062005200620054b1b22054100480dbd010240024020020d00200510332206450dc4010c010b2001280218210620022005460d0020062002200510372206450dc3010b200120063602182001411c6a2005360200200141206a28020021020b200128021820026a20043a0000200141206a2201200128020041016a3602000cbf010b2003419c016a220141013602002003420137028c01200341e8b1cc003602880120034101360234200320043602302003200341306a36029801200341c0006a20034188016a104120032802402202450dbe012003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010cbe010b200328028c012201450dbd0120034190016a29030021070b20002007370204200020013602000cbd010b2003200241046a280200220236023020034188016a200141046a200210f5070240024020032d0088014101460d00200320032d00890122023a006020034188016a200141186a200141286a410410f2070240024020032d0088014101460d00200320032d00890122013a007820014104460dbf01200241ff01712001460dbf01200341c0006a41146a413d360200200341cc006a413736020020034188016a41146a41033602002003420337028c01200341d4a5cc0036028801200341013602442003200341c0006a360298012003200341f8006a3602502003200341e0006a3602482003200341306a360240200341e8006a20034188016a10410c010b200341f0006a20034194016a2802003602002003200329028c013703680b200329026c2107200328026821010c010b2003200328028c012201360268200320034190016a290300220737026c0b2001450dbb0120002007370204200020013602000cbc010b20034188016a200141046a200241046a28020010f5070240024020032d0088014101460d0020034188016a200141186a200141286a20032d00890110f4072003280288012201450dbc01200329028c0121070c010b200328028c012201450dbb0120034190016a29030021070b20002007370204200020013602000cbb010b200128020021042003200241046a280200220236026802400240200441206a28020020024d0d000240200141206a2802002205200141246a22062802004f0d00200428021820024101746a2d00002102024020052001411c6a280200470d00200541016a22042005490dba01200541017422062004200620044b1b22044100480dba010240024020050d00200410332206450dc1010c010b2001280218210620052004460d0020062005200410372206450dc0010b200120063602182001411c6a2004360200200141206a28020021050b200128021820056a20023a0000200141206a2201200128020041016a3602000cbc010b2003419c016a220141013602002003420137028c01200341e8b1cc003602880120034101360234200320063602302003200341306a36029801200341c0006a20034188016a104120032802402202450dbb012003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010cbb010b2003419c016a41013602002003420237028c0120034190afcc00360288012003410136027c2003200341f8006a360298012003200341e8006a360278200341c0006a20034188016a104120032802402201450dba01200329024421070b20002007370204200020013602000cba010b2003200241046a2802002202360258200128020021042003200236028401024002400240200441206a28020020024d0d00200428021820024101746a22022d00010d022003419c016a41013602002003420237028c01200341a0afcc0036028801200341013602342003200341306a36029801200320034184016a360230200341c0006a20034188016a10410c010b2003419c016a41013602002003420237028c0120034190afcc00360288012003410136027c2003200341f8006a36029801200320034184016a360278200341c0006a20034188016a10410b2003280240210120032003290244220737026c200320013602680caa010b200320022d000022023a005f20034188016a200141186a200141286a410410f20720032d0088014101470da701200341f0006a20034194016a2802003602002003200329028c013703680ca8010b20034188016a2001200241046a2802004104410010f707200328028801450db7012000200329038801370200200041086a20034188016a41086a2802003602000cb8010b20034188016a2001200241046a2802004108410110f707200328028801450db6012000200329038801370200200041086a20034188016a41086a2802003602000cb7010b20034188016a2001200241046a2802004104410210f707200328028801450db5012000200329038801370200200041086a20034188016a41086a2802003602000cb6010b20034188016a2001200241046a2802004108410310f707200328028801450db4012000200329038801370200200041086a20034188016a41086a2802003602000cb5010b20034188016a2001200241046a2802004101410010f707200328028801450db3012000200329038801370200200041086a20034188016a41086a2802003602000cb4010b20034188016a2001200241046a2802004101410010f707200328028801450db2012000200329038801370200200041086a20034188016a41086a2802003602000cb3010b20034188016a2001200241046a2802004102410010f707200328028801450db1012000200329038801370200200041086a20034188016a41086a2802003602000cb2010b20034188016a2001200241046a2802004102410010f707200328028801450db0012000200329038801370200200041086a20034188016a41086a2802003602000cb1010b20034188016a2001200241046a2802004101410110f707200328028801450daf012000200329038801370200200041086a20034188016a41086a2802003602000cb0010b20034188016a2001200241046a2802004101410110f707200328028801450dae012000200329038801370200200041086a20034188016a41086a2802003602000caf010b20034188016a2001200241046a2802004102410110f707200328028801450dad012000200329038801370200200041086a20034188016a41086a2802003602000cae010b20034188016a2001200241046a2802004102410110f707200328028801450dac012000200329038801370200200041086a20034188016a41086a2802003602000cad010b20034188016a2001200241046a2802004104410110f707200328028801450dab012000200329038801370200200041086a20034188016a41086a2802003602000cac010b20034188016a2001200241046a2802004104410110f707200328028801450daa012000200329038801370200200041086a20034188016a41086a2802003602000cab010b20034188016a2001200241046a2802004104410010f807200328028801450da9012000200329038801370200200041086a20034188016a41086a2802003602000caa010b20034188016a2001200241046a2802004108410110f807200328028801450da8012000200329038801370200200041086a20034188016a41086a2802003602000ca9010b20034188016a2001200241046a2802004104410210f807200328028801450da7012000200329038801370200200041086a20034188016a41086a2802003602000ca8010b20034188016a2001200241046a2802004108410310f807200328028801450da6012000200329038801370200200041086a20034188016a41086a2802003602000ca7010b20034188016a2001200241046a2802004101410010f807200328028801450da5012000200329038801370200200041086a20034188016a41086a2802003602000ca6010b20034188016a2001200241046a2802004102410010f807200328028801450da4012000200329038801370200200041086a20034188016a41086a2802003602000ca5010b20034188016a2001200241046a2802004101410110f807200328028801450da3012000200329038801370200200041086a20034188016a41086a2802003602000ca4010b20034188016a2001200241046a2802004102410110f807200328028801450da2012000200329038801370200200041086a20034188016a41086a2802003602000ca3010b20034188016a2001200241046a2802004104410110f807200328028801450da1012000200329038801370200200041086a20034188016a41086a2802003602000ca2010b20012802002102200341003602680240024020022802080d002003419c016a41013602002003420237028c01200341fcadcc0036028801200341013602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402202450d00200329024421070c010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490da001200241017422052004200520044b1b22044100480da0010240024020020d00200410332205450da7010c010b2001280218210520022004460d0020052002200410372205450da6010b200120053602182001411c6a2004360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000ca2010b2003419c016a220141013602002003420137028c01200341e8b1cc003602880120034101360234200320043602302003200341306a36029801200341c0006a20034188016a104120032802402202450da1012003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402102200329024421070240200328026c450d00200328026810350b2002450da1010b20002007370204200020023602000ca1010b20012802002102200341003602680240024020022802080d002003419c016a41013602002003420237028c01200341fcadcc0036028801200341013602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402202450d00200329024421070c010b20034188016a200141186a2204200141286a410010f207024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490da001200241017422062005200620054b1b22054100480da0010240024020020d00200510332204450da7010c010b2004280200210420022005460d0020042002200510372204450da6010b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000ca2010b2003419c016a220141013602002003420137028c01200341e8b1cc003602880120034101360234200320053602302003200341306a36029801200341c0006a20034188016a104120032802402202450da1012003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402102200329024421070240200328026c450d00200328026810350b20020d010ca1010b200328028c012202450da00120034190016a29030021070b20002007370204200020023602000ca0010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490d9d01200241017422052004200520044b1b22044100480d9d010240024020020d00200410332205450da4010c010b2001280218210520022004460d0020052002200410372205450da3010b200120053602182001411c6a2004360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c9f010b2003419c016a220141013602002003420137028c01200341e8b1cc003602880120034101360234200320043602302003200341306a36029801200341c0006a20034188016a104120032802402202450d9e012003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b2001450d9e0120002007370204200020013602000c9f010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490d9c01200241017422052004200520044b1b22044100480d9c010240024020020d00200410332205450da3010c010b2001280218210520022004460d0020052002200410372205450da2010b200120053602182001411c6a2004360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000c9e010b2003419c016a220141013602002003420137028c01200341e8b1cc003602880120034101360234200320043602302003200341306a36029801200341c0006a20034188016a104120032802402202450d9d012003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b2001450d9d0120002007370204200020013602000c9e010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490d9b01200241017422052004200520044b1b22044100480d9b010240024020020d00200410332205450da2010c010b2001280218210520022004460d0020052002200410372205450da1010b200120053602182001411c6a2004360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c9d010b2003419c016a220141013602002003420137028c01200341e8b1cc003602880120034101360234200320043602302003200341306a36029801200341c0006a20034188016a104120032802402202450d9c012003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b2001450d9c0120002007370204200020013602000c9d010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490d9a01200241017422052004200520044b1b22044100480d9a010240024020020d00200410332205450da1010c010b2001280218210520022004460d0020052002200410372205450da0010b200120053602182001411c6a2004360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c9c010b2003419c016a220141013602002003420137028c01200341e8b1cc003602880120034101360234200320043602302003200341306a36029801200341c0006a20034188016a104120032802402202450d9b012003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b2001450d9b0120002007370204200020013602000c9c010b20034188016a200141186a2204200141286a410010f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d9b01200241017422062005200620054b1b22054100480d9b010240024020020d00200510332204450da2010c010b2004280200210420022005460d0020042002200510372204450da1010b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c9d010b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d9c012003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c9c010b200328028c012201450d9b0120034190016a29030021070b20002007370204200020013602000c9b010b20034188016a2001410010f907200328028801450d99012000200329038801370200200041086a20034188016a41086a2802003602000c9a010b20034188016a2001410010f907200328028801450d98012000200329038801370200200041086a20034188016a41086a2802003602000c99010b20034188016a2001410010f907200328028801450d97012000200329038801370200200041086a20034188016a41086a2802003602000c98010b20034188016a2001410010f907200328028801450d96012000200329038801370200200041086a20034188016a41086a2802003602000c97010b20034188016a2001410010f907200328028801450d95012000200329038801370200200041086a20034188016a41086a2802003602000c96010b20034188016a2001410010f907200328028801450d94012000200329038801370200200041086a20034188016a41086a2802003602000c95010b20034188016a2001410010f907200328028801450d93012000200329038801370200200041086a20034188016a41086a2802003602000c94010b20034188016a2001410010f907200328028801450d92012000200329038801370200200041086a20034188016a41086a2802003602000c93010b20034188016a2001410010f907200328028801450d91012000200329038801370200200041086a20034188016a41086a2802003602000c92010b20034188016a2001410010f907200328028801450d90012000200329038801370200200041086a20034188016a41086a2802003602000c91010b20034188016a200141186a2204200141286a410110f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d9001200241017422062005200620054b1b22054100480d90010240024020020d00200510332204450d97010c010b2004280200210420022005460d0020042002200510372204450d96010b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c92010b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d91012003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c91010b200328028c012201450d900120034190016a29030021070b20002007370204200020013602000c90010b20034188016a2001410110f907200328028801450d8e012000200329038801370200200041086a20034188016a41086a2802003602000c8f010b20034188016a2001410110f907200328028801450d8d012000200329038801370200200041086a20034188016a41086a2802003602000c8e010b20034188016a2001410110f907200328028801450d8c012000200329038801370200200041086a20034188016a41086a2802003602000c8d010b20034188016a2001410110f907200328028801450d8b012000200329038801370200200041086a20034188016a41086a2802003602000c8c010b20034188016a2001410110f907200328028801450d8a012000200329038801370200200041086a20034188016a41086a2802003602000c8b010b20034188016a2001410110f907200328028801450d89012000200329038801370200200041086a20034188016a41086a2802003602000c8a010b20034188016a2001410110f907200328028801450d88012000200329038801370200200041086a20034188016a41086a2802003602000c89010b20034188016a2001410110f907200328028801450d87012000200329038801370200200041086a20034188016a41086a2802003602000c88010b20034188016a2001410110f907200328028801450d86012000200329038801370200200041086a20034188016a41086a2802003602000c87010b20034188016a2001410110f907200328028801450d85012000200329038801370200200041086a20034188016a41086a2802003602000c86010b20034188016a2001410210f907200328028801450d84012000200329038801370200200041086a20034188016a41086a2802003602000c85010b20034188016a2001410210f907200328028801450d83012000200329038801370200200041086a20034188016a41086a2802003602000c84010b20034188016a2001410210f907200328028801450d82012000200329038801370200200041086a20034188016a41086a2802003602000c83010b20034188016a2001410210f907200328028801450d81012000200329038801370200200041086a20034188016a41086a2802003602000c82010b20034188016a2001410210f907200328028801450d80012000200329038801370200200041086a20034188016a41086a2802003602000c81010b20034188016a2001410210f907200328028801450d7f2000200329038801370200200041086a20034188016a41086a2802003602000c80010b20034188016a2001410310f907200328028801450d7e2000200329038801370200200041086a20034188016a41086a2802003602000c7f0b20034188016a2001410310f907200328028801450d7d2000200329038801370200200041086a20034188016a41086a2802003602000c7e0b20034188016a2001410310f907200328028801450d7c2000200329038801370200200041086a20034188016a41086a2802003602000c7d0b20034188016a2001410310f907200328028801450d7b2000200329038801370200200041086a20034188016a41086a2802003602000c7c0b20034188016a2001410310f907200328028801450d7a2000200329038801370200200041086a20034188016a41086a2802003602000c7b0b20034188016a2001410310f907200328028801450d792000200329038801370200200041086a20034188016a41086a2802003602000c7a0b20034188016a200141186a2204200141286a410010f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d79200241017422062005200620054b1b22054100480d790240024020020d00200510332204450d80010c010b2004280200210420022005460d0020042002200510372204450d7f0b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c7b0b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d7a2003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c7a0b200328028c012201450d7920034190016a29030021070b20002007370204200020013602000c790b20034188016a200141186a2204200141286a410010f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d78200241017422062005200620054b1b22054100480d780240024020020d00200510332204450d7f0c010b2004280200210420022005460d0020042002200510372204450d7e0b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c7a0b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d792003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c790b200328028c012201450d7820034190016a29030021070b20002007370204200020013602000c780b20034188016a200141186a2204200141286a410010f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d77200241017422062005200620054b1b22054100480d770240024020020d00200510332204450d7e0c010b2004280200210420022005460d0020042002200510372204450d7d0b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c790b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d782003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c780b200328028c012201450d7720034190016a29030021070b20002007370204200020013602000c770b20034188016a2001410010fa07200328028801450d752000200329038801370200200041086a20034188016a41086a2802003602000c760b20034188016a2001410010fa07200328028801450d742000200329038801370200200041086a20034188016a41086a2802003602000c750b20034188016a2001410010fa07200328028801450d732000200329038801370200200041086a20034188016a41086a2802003602000c740b20034188016a2001410010fa07200328028801450d722000200329038801370200200041086a20034188016a41086a2802003602000c730b20034188016a2001410010fa07200328028801450d712000200329038801370200200041086a20034188016a41086a2802003602000c720b20034188016a2001410010fa07200328028801450d702000200329038801370200200041086a20034188016a41086a2802003602000c710b20034188016a2001410010fa07200328028801450d6f2000200329038801370200200041086a20034188016a41086a2802003602000c700b20034188016a2001410010fa07200328028801450d6e2000200329038801370200200041086a20034188016a41086a2802003602000c6f0b20034188016a2001410010fa07200328028801450d6d2000200329038801370200200041086a20034188016a41086a2802003602000c6e0b20034188016a2001410010fa07200328028801450d6c2000200329038801370200200041086a20034188016a41086a2802003602000c6d0b20034188016a2001410010fa07200328028801450d6b2000200329038801370200200041086a20034188016a41086a2802003602000c6c0b20034188016a2001410010fa07200328028801450d6a2000200329038801370200200041086a20034188016a41086a2802003602000c6b0b20034188016a2001410010fa07200328028801450d692000200329038801370200200041086a20034188016a41086a2802003602000c6a0b20034188016a2001410010fa07200328028801450d682000200329038801370200200041086a20034188016a41086a2802003602000c690b20034188016a2001410010fa07200328028801450d672000200329038801370200200041086a20034188016a41086a2802003602000c680b20034188016a200141186a2204200141286a410110f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d67200241017422062005200620054b1b22054100480d670240024020020d00200510332204450d6e0c010b2004280200210420022005460d0020042002200510372204450d6d0b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000c690b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d682003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c680b200328028c012201450d6720034190016a29030021070b20002007370204200020013602000c670b20034188016a200141186a2204200141286a410110f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d66200241017422062005200620054b1b22054100480d660240024020020d00200510332204450d6d0c010b2004280200210420022005460d0020042002200510372204450d6c0b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000c680b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d672003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c670b200328028c012201450d6620034190016a29030021070b20002007370204200020013602000c660b20034188016a200141186a2204200141286a410110f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d65200241017422062005200620054b1b22054100480d650240024020020d00200510332204450d6c0c010b2004280200210420022005460d0020042002200510372204450d6b0b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000c670b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d662003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c660b200328028c012201450d6520034190016a29030021070b20002007370204200020013602000c650b20034188016a2001410110fa07200328028801450d632000200329038801370200200041086a20034188016a41086a2802003602000c640b20034188016a2001410110fa07200328028801450d622000200329038801370200200041086a20034188016a41086a2802003602000c630b20034188016a2001410110fa07200328028801450d612000200329038801370200200041086a20034188016a41086a2802003602000c620b20034188016a2001410110fa07200328028801450d602000200329038801370200200041086a20034188016a41086a2802003602000c610b20034188016a2001410110fa07200328028801450d5f2000200329038801370200200041086a20034188016a41086a2802003602000c600b20034188016a2001410110fa07200328028801450d5e2000200329038801370200200041086a20034188016a41086a2802003602000c5f0b20034188016a2001410110fa07200328028801450d5d2000200329038801370200200041086a20034188016a41086a2802003602000c5e0b20034188016a2001410110fa07200328028801450d5c2000200329038801370200200041086a20034188016a41086a2802003602000c5d0b20034188016a2001410110fa07200328028801450d5b2000200329038801370200200041086a20034188016a41086a2802003602000c5c0b20034188016a2001410110fa07200328028801450d5a2000200329038801370200200041086a20034188016a41086a2802003602000c5b0b20034188016a2001410110fa07200328028801450d592000200329038801370200200041086a20034188016a41086a2802003602000c5a0b20034188016a2001410110fa07200328028801450d582000200329038801370200200041086a20034188016a41086a2802003602000c590b20034188016a2001410110fa07200328028801450d572000200329038801370200200041086a20034188016a41086a2802003602000c580b20034188016a2001410110fa07200328028801450d562000200329038801370200200041086a20034188016a41086a2802003602000c570b20034188016a2001410110fa07200328028801450d552000200329038801370200200041086a20034188016a41086a2802003602000c560b20034188016a200141186a2204200141286a410210f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d55200241017422062005200620054b1b22054100480d550240024020020d00200510332204450d5c0c010b2004280200210420022005460d0020042002200510372204450d5b0b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c570b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d562003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c560b200328028c012201450d5520034190016a29030021070b20002007370204200020013602000c550b20034188016a200141186a2204200141286a410210f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d54200241017422062005200620054b1b22054100480d540240024020020d00200510332204450d5b0c010b2004280200210420022005460d0020042002200510372204450d5a0b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c560b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d552003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c550b200328028c012201450d5420034190016a29030021070b20002007370204200020013602000c540b20034188016a200141186a2204200141286a410210f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d53200241017422062005200620054b1b22054100480d530240024020020d00200510332204450d5a0c010b2004280200210420022005460d0020042002200510372204450d590b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c550b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d542003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c540b200328028c012201450d5320034190016a29030021070b20002007370204200020013602000c530b20034188016a200141186a2204200141286a410210f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d52200241017422062005200620054b1b22054100480d520240024020020d00200510332204450d590c010b2004280200210420022005460d0020042002200510372204450d580b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c540b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d532003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c530b200328028c012201450d5220034190016a29030021070b20002007370204200020013602000c520b20034188016a200141186a2204200141286a410210f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d51200241017422062005200620054b1b22054100480d510240024020020d00200510332204450d580c010b2004280200210420022005460d0020042002200510372204450d570b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c530b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d522003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c520b200328028c012201450d5120034190016a29030021070b20002007370204200020013602000c510b20034188016a200141186a2204200141286a410210f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d50200241017422062005200620054b1b22054100480d500240024020020d00200510332204450d570c010b2004280200210420022005460d0020042002200510372204450d560b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c520b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d512003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c510b200328028c012201450d5020034190016a29030021070b20002007370204200020013602000c500b20034188016a200141186a2204200141286a410210f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d4f200241017422062005200620054b1b22054100480d4f0240024020020d00200510332204450d560c010b2004280200210420022005460d0020042002200510372204450d550b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c510b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d502003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c500b200328028c012201450d4f20034190016a29030021070b20002007370204200020013602000c4f0b20034188016a2001410210fa07200328028801450d4d2000200329038801370200200041086a20034188016a41086a2802003602000c4e0b20034188016a2001410210fa07200328028801450d4c2000200329038801370200200041086a20034188016a41086a2802003602000c4d0b20034188016a2001410210fa07200328028801450d4b2000200329038801370200200041086a20034188016a41086a2802003602000c4c0b20034188016a2001410210fa07200328028801450d4a2000200329038801370200200041086a20034188016a41086a2802003602000c4b0b20034188016a2001410210fa07200328028801450d492000200329038801370200200041086a20034188016a41086a2802003602000c4a0b20034188016a2001410210fa07200328028801450d482000200329038801370200200041086a20034188016a41086a2802003602000c490b20034188016a2001410210fa07200328028801450d472000200329038801370200200041086a20034188016a41086a2802003602000c480b20034188016a200141186a2204200141286a410310f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d47200241017422062005200620054b1b22054100480d470240024020020d00200510332204450d4e0c010b2004280200210420022005460d0020042002200510372204450d4d0b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c490b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d482003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c480b200328028c012201450d4720034190016a29030021070b20002007370204200020013602000c470b20034188016a200141186a2204200141286a410310f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d46200241017422062005200620054b1b22054100480d460240024020020d00200510332204450d4d0c010b2004280200210420022005460d0020042002200510372204450d4c0b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c480b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d472003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c470b200328028c012201450d4620034190016a29030021070b20002007370204200020013602000c460b20034188016a200141186a2204200141286a410310f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d45200241017422062005200620054b1b22054100480d450240024020020d00200510332204450d4c0c010b2004280200210420022005460d0020042002200510372204450d4b0b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c470b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d462003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c460b200328028c012201450d4520034190016a29030021070b20002007370204200020013602000c450b20034188016a200141186a2204200141286a410310f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d44200241017422062005200620054b1b22054100480d440240024020020d00200510332204450d4b0c010b2004280200210420022005460d0020042002200510372204450d4a0b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c460b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d452003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c450b200328028c012201450d4420034190016a29030021070b20002007370204200020013602000c440b20034188016a200141186a2204200141286a410310f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d43200241017422062005200620054b1b22054100480d430240024020020d00200510332204450d4a0c010b2004280200210420022005460d0020042002200510372204450d490b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c450b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d442003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c440b200328028c012201450d4320034190016a29030021070b20002007370204200020013602000c430b20034188016a200141186a2204200141286a410310f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d42200241017422062005200620054b1b22054100480d420240024020020d00200510332204450d490c010b2004280200210420022005460d0020042002200510372204450d480b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c440b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d432003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c430b200328028c012201450d4220034190016a29030021070b20002007370204200020013602000c420b20034188016a200141186a2204200141286a410310f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d41200241017422062005200620054b1b22054100480d410240024020020d00200510332204450d480c010b2004280200210420022005460d0020042002200510372204450d470b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c430b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d422003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c420b200328028c012201450d4120034190016a29030021070b20002007370204200020013602000c410b20034188016a2001410310fa07200328028801450d3f2000200329038801370200200041086a20034188016a41086a2802003602000c400b20034188016a2001410310fa07200328028801450d3e2000200329038801370200200041086a20034188016a41086a2802003602000c3f0b20034188016a2001410310fa07200328028801450d3d2000200329038801370200200041086a20034188016a41086a2802003602000c3e0b20034188016a2001410310fa07200328028801450d3c2000200329038801370200200041086a20034188016a41086a2802003602000c3d0b20034188016a2001410310fa07200328028801450d3b2000200329038801370200200041086a20034188016a41086a2802003602000c3c0b20034188016a2001410310fa07200328028801450d3a2000200329038801370200200041086a20034188016a41086a2802003602000c3b0b20034188016a2001410310fa07200328028801450d392000200329038801370200200041086a20034188016a41086a2802003602000c3a0b20034188016a200141186a2204200141286a410110f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d39200241017422062005200620054b1b22054100480d390240024020020d00200510332204450d400c010b2004280200210420022005460d0020042002200510372204450d3f0b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c3b0b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d3a2003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c3a0b200328028c012201450d3920034190016a29030021070b20002007370204200020013602000c390b20034188016a200141186a2204200141286a410210f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d38200241017422062005200620054b1b22054100480d380240024020020d00200510332204450d3f0c010b2004280200210420022005460d0020042002200510372204450d3e0b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c3a0b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d392003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c390b200328028c012201450d3820034190016a29030021070b20002007370204200020013602000c380b20034188016a200141186a2204200141286a410210f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d37200241017422062005200620054b1b22054100480d370240024020020d00200510332204450d3e0c010b2004280200210420022005460d0020042002200510372204450d3d0b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c390b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d382003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c380b200328028c012201450d3720034190016a29030021070b20002007370204200020013602000c370b20034188016a200141186a2204200141286a410310f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d36200241017422062005200620054b1b22054100480d360240024020020d00200510332204450d3d0c010b2004280200210420022005460d0020042002200510372204450d3c0b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c380b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d372003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c370b200328028c012201450d3620034190016a29030021070b20002007370204200020013602000c360b20034188016a200141186a2204200141286a410310f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d35200241017422062005200620054b1b22054100480d350240024020020d00200510332204450d3c0c010b2004280200210420022005460d0020042002200510372204450d3b0b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c370b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d362003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c360b200328028c012201450d3520034190016a29030021070b20002007370204200020013602000c350b20034188016a200141186a2204200141286a410010f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d34200241017422062005200620054b1b22054100480d340240024020020d00200510332204450d3b0c010b2004280200210420022005460d0020042002200510372204450d3a0b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000c360b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d352003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c350b200328028c012201450d3420034190016a29030021070b20002007370204200020013602000c340b20034188016a200141186a2204200141286a410010f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d33200241017422062005200620054b1b22054100480d330240024020020d00200510332204450d3a0c010b2004280200210420022005460d0020042002200510372204450d390b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000c350b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d342003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c340b200328028c012201450d3320034190016a29030021070b20002007370204200020013602000c330b20034188016a200141186a2204200141286a410210f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d21200241017422062005200620054b1b22054100480d210240024020020d002005103322040d010c250b2004280200210420022005460d0020042002200510372204450d240b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000c340b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d332003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c330b200328028c012201450d3220034190016a29030021070b20002007370204200020013602000c320b20034188016a200141186a2204200141286a410210f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d20200241017422062005200620054b1b22054100480d200240024020020d00200510332204450d240c010b2004280200210420022005460d0020042002200510372204450d230b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000c330b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d322003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c320b200328028c012201450d3120034190016a29030021070b20002007370204200020013602000c310b20034188016a200141186a2204200141286a410310f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d1f200241017422062005200620054b1b22054100480d1f0240024020020d00200510332204450d230c010b2004280200210420022005460d0020042002200510372204450d220b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000c320b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d312003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c310b200328028c012201450d3020034190016a29030021070b20002007370204200020013602000c300b20034188016a200141186a2204200141286a410310f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d1e200241017422062005200620054b1b22054100480d1e0240024020020d00200510332204450d220c010b2004280200210420022005460d0020042002200510372204450d210b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000c310b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d302003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c300b200328028c012201450d2f20034190016a29030021070b20002007370204200020013602000c2f0b20034188016a200141186a2204200141286a410010f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d1d200241017422062005200620054b1b22054100480d1d0240024020020d00200510332204450d210c010b2004280200210420022005460d0020042002200510372204450d200b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c300b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d2f2003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c2f0b200328028c012201450d2e20034190016a29030021070b20002007370204200020013602000c2e0b20034188016a200141186a2204200141286a410010f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d1c200241017422062005200620054b1b22054100480d1c0240024020020d00200510332204450d200c010b2004280200210420022005460d0020042002200510372204450d1f0b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c2f0b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d2e2003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c2e0b200328028c012201450d2d20034190016a29030021070b20002007370204200020013602000c2d0b20034188016a200141186a2204200141286a410110f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d1b200241017422062005200620054b1b22054100480d1b0240024020020d00200510332204450d1f0c010b2004280200210420022005460d0020042002200510372204450d1e0b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c2e0b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d2d2003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c2d0b200328028c012201450d2c20034190016a29030021070b20002007370204200020013602000c2c0b20034188016a200141186a2204200141286a410110f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d1a200241017422062005200620054b1b22054100480d1a0240024020020d00200510332204450d1e0c010b2004280200210420022005460d0020042002200510372204450d1d0b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c2d0b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d2c2003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c2c0b200328028c012201450d2b20034190016a29030021070b20002007370204200020013602000c2b0b20034188016a200141186a2204200141286a410310f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d19200241017422062005200620054b1b22054100480d190240024020020d00200510332204450d1d0c010b2004280200210420022005460d0020042002200510372204450d1c0b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c2c0b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d2b2003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c2b0b200328028c012201450d2a20034190016a29030021070b20002007370204200020013602000c2a0b20034188016a200141186a2204200141286a410010f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d18200241017422062005200620054b1b22054100480d180240024020020d00200510332204450d1c0c010b2004280200210420022005460d0020042002200510372204450d1b0b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c2b0b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d2a2003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c2a0b200328028c012201450d2920034190016a29030021070b20002007370204200020013602000c290b20034188016a200141186a2204200141286a410010f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d17200241017422062005200620054b1b22054100480d170240024020020d00200510332204450d1b0c010b2004280200210420022005460d0020042002200510372204450d1a0b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c2a0b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d292003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c290b200328028c012201450d2820034190016a29030021070b20002007370204200020013602000c280b20034188016a200141186a2204200141286a410110f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d16200241017422062005200620054b1b22054100480d160240024020020d00200510332204450d1a0c010b2004280200210420022005460d0020042002200510372204450d190b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c290b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d282003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c280b200328028c012201450d2720034190016a29030021070b20002007370204200020013602000c270b20034188016a200141186a2204200141286a410110f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d15200241017422062005200620054b1b22054100480d150240024020020d00200510332204450d190c010b2004280200210420022005460d0020042002200510372204450d180b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c280b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d272003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c270b200328028c012201450d2620034190016a29030021070b20002007370204200020013602000c260b20034188016a200141186a2204200141286a410210f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d14200241017422062005200620054b1b22054100480d140240024020020d00200510332204450d180c010b2004280200210420022005460d0020042002200510372204450d170b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c270b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d262003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c260b200328028c012201450d2520034190016a29030021070b20002007370204200020013602000c250b20034188016a200141186a2204200141286a410210f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d13200241017422062005200620054b1b22054100480d130240024020020d00200510332204450d170c010b2004280200210420022005460d0020042002200510372204450d160b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c260b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d252003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c250b200328028c012201450d2420034190016a29030021070b20002007370204200020013602000c240b20034188016a200141186a2204200141286a410310f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d12200241017422062005200620054b1b22054100480d120240024020020d00200510332204450d160c010b2004280200210420022005460d0020042002200510372204450d150b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000c250b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d242003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c240b200328028c012201450d2320034190016a29030021070b20002007370204200020013602000c230b20034188016a200141186a2204200141286a410010f2070240024020032d0088014101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d11200241017422062005200620054b1b22054100480d110240024020020d00200510332204450d150c010b2004280200210420022005460d0020042002200510372204450d140b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c240b2003419c016a220141013602002003420137028c01200341e8b1cc00360288012003410136026c200320053602682003200341e8006a36029801200341c0006a20034188016a104120032802402202450d232003200329024437026c20032002360268200141013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402101200329024421070240200328026c450d00200328026810350b20010d010c230b200328028c012201450d2220034190016a29030021070b20002007370204200020013602000c220b2003411810fb072003410036029001200320032903003703880120034188016a4100411810fc07200328028801220120032802900122006a411841feafcc00411810fd072003200041186a360290012003200329028c0137028c01200320013602880141f7a3cc00413b20034188016a41b4a4cc0041c4a4cc001046000b2000200329028c01370200200041086a20034194016a2802003602000c200b200341086a411810fb072003410036029001200320032903083703880120034188016a4100411810fc07200328028801220120032802900122006a411841feafcc00411810fd072003200041186a360290012003200329028c0137028c01200320013602880141d4a4cc00413420034188016a41b4a4cc004188a5cc001046000b1045000b200341106a411810fb072003410036029001200320032903103703880120034188016a4100411810fc07200328028801220120032802900122006a411841feafcc00411810fd072003200041186a360290012003200329028c0137028c01200320013602880141d4a4cc00413420034188016a41b4a4cc004188a5cc001046000b2003419c016a41013602002003420237028c01200341b4a5cc00360288012003413e36026c2003200a3602682003200341e8006a36029801200341c0006a20034188016a1041200041086a200341c0006a41086a280200360200200020032903403702000c1c0b41dab0cc00411d41f8b0cc001064000b200341186a411810fb072003410036029001200320032903183703880120034188016a4100411810fc07200328028801220120032802900122006a411841feafcc00411810fd072003200041186a360290012003200329028c0137028c01200320013602880141f7a3cc00413b20034188016a41b4a4cc0041c4a4cc001046000b41dab0cc00411d41f8b0cc001064000b200341286a411810fb072003410036029001200320032903283703880120034188016a4100411810fc07200328028801220120032802900122006a411841feafcc00411810fd072003200041186a360290012003200329028c0137028c01200320013602880141f7a3cc00413b20034188016a41b4a4cc0041c4a4cc001046000b20034188016a41146a41013602002003420237028c01200341acaecc0036028801200341013602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a10410c080b20034190016a2903002107200328028c0121010c080b20034190016a2903002107200328028c0121010c070b103e000b41dab0cc00411d41f8b0cc001064000b103c000b200320032d00890122013a00302001200241ff0171460d1020014104460d10200341c0006a41146a413d360200200341cc006a413d36020020034188016a41146a41033602002003420337028c01200341eca5cc0036028801200341013602442003200341c0006a360298012003200341306a3602502003200341df006a3602482003200341d8006a360240200341e8006a20034188016a10410b200329026c2107200328026821010b2001450d0e20002007370204200020013602000c0f0b20032802402101200329024421070b2001450d0c20002007370204200020013602000c0d0b200641027421060340200320042802002205360278200220054d0d0220022005417f736a220520024f0d0a0240200a20054103746a22052d00044103460d0020052d00054104470d040b200441046a21042006417c6a22060d000b410421080b20034188016a200141186a2202200c410010f20720032d0088014101460d02200841ff01714104470d030c040b2003419c016a22044102360200200341cc006a41013602002003420237028c0120034198b0cc003602880120034101360244200320023602302003200341c0006a360298012003200341306a3602482003200341f8006a360240200341e8006a20034188016a1041200328026821022003200329026c37026c20032002360268200441013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402102200329024421070240200328026c450d00200328026810350b20032007370234200320023602300c050b200341cc006a413e3602002003419c016a41023602002003420237028c01200341c4a5cc00360288012003200541056a3602482003413e3602442003200341c0006a360298012003200341e0006a360240200341306a20034188016a10410c040b200341386a20034194016a2802003602002003200329028c013703300c030b20034188016a2002200c200810f407200328028801450d00200341306a41086a20034188016a41086a28020036020020032003290388013703300c020b200341003602300c010b2003419c016a22044102360200200341cc006a41013602002003420237028c0120034198b0cc003602880120034101360244200320023602302003200341c0006a360298012003200341306a3602482003200341f8006a360240200341e8006a20034188016a1041200328026821022003200329026c37026c20032002360268200441013602002003420137028c01200341acaacc0036028801200341383602342003200341306a360298012003200341e8006a360230200341c0006a20034188016a104120032802402102200329024421070240200328026c450d00200328026810350b20032007370234200320023602300b02400240200328023022020d00200141306a2802002202450d0102400240200241037420012802286a41786a22052802002204200141206a220628020022024b0d00200421010c010b024002402001411c6a280200220820026b200420026b2209490d002001280218210a200221010c010b200220096a220a2002490d042008410174220b200a200b200a4b1b220b4100480d040240024020080d000240200b0d004101210a0c020b200b1033220a450d0b0c010b2001280218210a2008200b460d00200a2008200b1037220a450d0a0b2001200a3602182001411c6a200b360200200141206a28020021010b200a20016a21080240024020094102490d002008410420042002417f736a2202109f081a200a200220016a22016a21080c010b2009450d010b200841043a0000200141016a21010b20062001360200200541013a00060c050b20002003290234370204200020023602000c050b200341206a411810fb072003410036029001200320032903203703880120034188016a4100411810fc07200328028801220120032802900122006a411841feafcc00411810fd072003200041186a360290012003200329028c0137028c01200320013602880141f7a3cc00413b20034188016a41b4a4cc0041c4a4cc001046000b103e000b41dab0cc00411d41f8b0cc001064000b20002007370204200020013602000c010b200041003602000b200341a0016a24000f0b103c000b6401017f230041206b220224002002413f360204200220003602002001411c6a2802002100200128021821012002411c6a41013602002002420137020c20024188b2cc003602082002200236021820012000200241086a10432101200241206a240020010b0c002000280200200110cd070b8f1f03127f017e037f23004180026b220524000240024020014115490d00410121064101210702400240034020012108200021092006200771410173210a024002400240034002400240024002402004450d00024020064101710d002000200110c8072004417f6a21040b2001410276220741036c210b2007410174210c4100210d20014132490d03200741016a210e200020074103746a220f28020020002007417f6a220d4103746a2210280200201041046a2802002210200f41046a280200220f200f20104b1b10a0082211450d01417f410120114100481b21100c020b2000200110c9070c0b0b417f200f201047200f2010491b21100b2007200d2010417f4622101b210f024002402000200e4103746a22112802002000200d200720101b22124103746a2207280200200741046a2802002207201141046a280200220d200d20074b1b10a0082211450d00417f410120114100481b21070c010b417f200d200747200d2007491b21070b4102410120101b20102007417f4622071b210d024002402000200e201220071b22114103746a22102802002000200f4103746a2207280200200741046a2802002207201041046a2802002210201020074b1b10a008220e450d00417f4101200e4100481b21100c010b417f201020074720102007491b21100b200c4101722107200d2010417f4622126a2113024002402000200c4103746a220d2802002000200c417f6a22104103746a220e280200200e41046a280200220e200d41046a280200220d200d200e4b1b10a0082214450d00417f410120144100481b210e0c010b417f200d200e47200d200e491b210e0b200c2010200e417f46220e1b210d2013200e6a211302400240200020074103746a221428020020002010200c200e1b220e4103746a220c280200200c41046a280200220c201441046a28020022102010200c4b1b10a0082214450d00417f410120144100481b210c0c010b417f2010200c472010200c491b210c0b2013200c417f46220c6a21100240024020002007200e200c1b22134103746a220c2802002000200d4103746a2207280200200741046a2802002207200c41046a280200220c200c20074b1b10a008220e450d00417f4101200e4100481b210c0c010b417f200c200747200c2007491b210c0b200b41016a21072010200c417f4622146a2115024002402000200b4103746a220e2802002000200b417f6a220c4103746a2210280200201041046a2802002210200e41046a280200220e200e20104b1b10a0082216450d00417f410120164100481b21100c010b417f200e201047200e2010491b21100b200b200c2010417f4622101b210e201520106a211502400240200020074103746a22162802002000200c200b20101b22104103746a220c280200200c41046a280200220c201641046a280200220b200b200c4b1b10a0082216450d00417f410120164100481b210c0c010b417f200b200c47200b200c491b210c0b2015200c417f46220c6a211502400240200020072010200c1b220b4103746a220c2802002000200e4103746a2207280200200741046a2802002207200c41046a280200220c200c20074b1b10a0082210450d00417f410120104100481b21100c010b417f200c200747200c2007491b21100b200f201120121b2107200d201320141b210c200e200b2010417f4622101b210b201520106a210d0b024002402000200c4103746a220e280200200020074103746a2210280200201041046a2802002210200e41046a280200220e200e20104b1b10a008220f450d00417f4101200f4100481b21100c010b417f200e201047200e2010491b21100b200c20072010417f46220e1b2110200d200e6a210d024002402000200b4103746a220f28020020002007200c200e1b220e4103746a2207280200200741046a2802002207200f41046a280200220c200c20074b1b10a008220f450d00417f4101200f4100481b21070c010b417f200c200747200c2007491b21070b200d2007417f46220c6a2107024002400240024002402000200b200e200c1b220d4103746a220b280200200020104103746a220c280200200c41046a280200220c200b41046a280200220b200b200c4b1b10a008220e450d00200e4100480d010c020b200b200c4f0d010b200741016a2207410c490d0102402001410176220b450d00200020014103746a41786a21072000210c0340200c2902002117200c200729020037020020072017370200200c41086a210c200741786a2107200b417f6a220b0d000b0b20012010417f736a2110410121070c020b200d21100b20074521070b0240200745200a724101710d002000200110ca070d090b2003450d010240201020014f0d00024002402003280200200020104103746a2207280200200741046a280200220c200341046a280200220b200b200c4b1b10a008220e450d00200e41004e0d010c050b200b200c490d040b200029020021172000200729020037020020072017370200200041786a21122000410c6a2113200041086a2114200028020421072000280200210d4100210b2001210e0340024002400240200b200e417f6a22114f0d002013200b4103746a210c034002400240200d200c417c6a280200200c28020022102007200720104b1b10a008220f450d00200f4100480d030c010b20072010490d020b200c41086a210c2011200b41016a220b470d000c020b0b0240200b20114f0d002012200e4103746a210c2011210e034002400240200d200c280200200c41046a28020022102007200720104b1b10a008220f450d00200f4100480d010c050b200720104f0d040b200c41786a210c200b200e417f6a220e490d000b0b200b21110b200020073602042000200d36020002402001201141016a2207490d00200020074103746a2100200120076b220141154f0d040c0b0b2007200141e485cc001059000b2014200b4103746a221029020021172010200c290200370200200c2017370200200b41016a210b0c000b0b0b2010200141d086cc001042000b20080d014100410041f485cc001042000b20002109200121080b201020084f0d02200929020021172009200920104103746a2207290200370200200720173702002009280204210c200928020021124100210e410021184100211902402008417f6a2200450d002009410c6a21074100211803400240024002402007417c6a2802002012200c2007280200220b200b200c4b1b10a0082210450d00201041004e0d010c020b200b200c490d010b200021190240200020184d0d00200920084103746a41786a21072000211903400240024020072802002012200c200741046a280200220b200b200c4b1b10a0082210450d00201041004e0d010c030b200b200c490d020b200741786a21072019417f6a221920184b0d000b0b0240024020192018490d0020002019490d010c040b20182019419486cc001059000b20192000419486cc001058000b200741086a21072000201841016a2218470d000b20002118200021190b200941086a220720194103746a210041800121144100211141002110410021014180012106200720184103746a221a210d034002402000200d6b22074187104b220a0d002007410376220741807f6a20072011200e492001201049220b72220f1b21070240200f450d0020062007200b1b210620072014200b1b21140c010b2007200741017622066b21140b024020012010470d00024020060d002005221021010c010b4100210720052110200d210b0340201020073a0000200741016a210702400240200b2802002012200c200b41046a280200220f200f200c4b1b10a0082201450d00417f410120014100481b210f0c010b417f200f200c47200f200c491b210f0b200b41086a210b2010200f417f476a211020062007470d000b200521010b02402011200e470d00024020140d0020054180016a220e21110c010b200041786a21074100210b20054180016a210e0340200e200b3a0000200b41016a210b0240024020072802002012200c200741046a280200220f200f200c4b1b10a0082211450d00417f410120114100481b210f0c010b417f200f200c47200f200c491b210f0b200741786a2107200e200f417f466a210e2014200b470d000b20054180016a21110b0240200e20116b2207201020016b220b200b20074b1b2213450d00200d20012d00004103746a22072802042115200728020021162007200020112d0000417f734103746a290200370200024020134101460d004100210703402000201120076a220b2d0000417f734103746a200d200120076a41016a220f2d00004103746a290200370200200d200f2d00004103746a2000200b41016a2d0000417f734103746a290200370200200741026a210b200741016a220f2107200b2013490d000b2011200f6a21112001200f6a21010b200020112d0000417f734103746a2207201536020420072016360200201141016a2111200141016a21010b200020144103746b20002011200e461b2100200d20064103746a200d20012010461b210d200a0d000b02400240200120104f0d00200021070340200d2010417f6a22102d00004103746a220b2902002117200b200741786a22072902003702002007201737020020012010490d000c020b0b200d21072011200e4f0d0003402007290200211720072000200e417f6a220e2d0000417f734103746a220b290200370200200b2017370200200741086a21072011200e490d000b0b2009200c36020420092012360200024020082007201a6b41037620186a22014d0d00200929020021172009200920014103746a220729020037020020072017370200200820016b220c450d02200c20012001200c4b1b210b20084103762110200741086a2100024002402001200c417f6a220c490d002000200c20022007200410be07200921000c010b2009200120022003200410be0720072103200c21010b200b20104f2106201920184d2107200141154f0d010c040b0b20012008418486cc001042000b41a486cc00411c41c086cc00103f000b20102008418486cc001042000b20014102490d00200041786a2111410021124101210f0340200f4103742107200f417f6a210c200f41016a210f024002400240200020076a2210280200220d2000200c4103746a2207280200200741046a280200220e201041046a280200220b200b200e4b1b10a0082213450d0020134100480d010c020b200b200e4f0d010b201020072902003702000240200c450d002012210c201121070240034002400240200d2007280200200741046a2802002210200b200b20104b1b10a008220e450d00200e41004e0d030c010b200b20104f0d020b200741086a2007290200370200200741786a2107200c41016a2210200c49210e2010210c200e450d000b0b200741086a21070b2007200d3602002007200b3602040b2012417f6a2112201141086a2111200f2001470d000b0b20054180026a24000b19002000200141186a280200360204200020012802103602000bf80201067f230041c0006b2202240041002103410021040240024003400240024002402003411f4b0d002001280204220520012802082206460d01200641016a22072006490d04200520074f0d022007200541c0fdcb001058000b200041013602002000410f3a00040c040b200241013a000f200241346a410136020020024201370224200241acfdcb003602202002413636023c2002200241386a36023020022002410f6a360238200241106a200241206a10412002410b6a200241186a28020036000020022002290310370003200041053a0004200020022900003700052000410c6a200241076a290000370000200041013602000c030b200128020020066a2d0000210620012007360208200641ff00712003411f71742004722104200341076a21032006418001710d000b0240024020034120490d002006410f4b0d010b20004100360200200020043602040c020b200041013602002000410d3a00040c010b417f200741c0fdcb001059000b200241c0006a24000be704010a7f230041106b22032400200128020421042001280200210541002106410121074100210820012802082209210a0240024003400240024020082006460d002006210b0c010b200641016a220c2006490d022006410174220b200c200b200c4b1b220b4100480d020240024020060d000240200b0d00410121070c020b200b103322070d010c050b2006200b460d0020072006200b10372207450d040b200b21060b200720086a200a41807f72200a41ff0071200a410776220c1b3a0000200841016a2108200c210a200c0d000b02400240200b20086b2009490d00200b21060c010b200820096a22062008490d01200b410174220a2006200a20064b1b22064100480d010240200b0d00024020060d00410121070c020b200610332207450d030c010b200b2006460d002007200b200610372207450d020b200720086a20052009109d081a02402004450d00200510350b200128020c210502400240200620096b20086b200141146a280200220c490d002009200c6a20086a210a2006210b0c010b200920086a220b200c6a220a200b490d012006410174220b200a200b200a4b1b220b4100480d01024020060d000240200b0d00410121070c020b200b10332207450d030c010b2006200b460d0020072006200b10372207450d020b200720096a20086a2005200c109d081a200341003a000f200a210603402003200641800172200641ff0071200641077622081b3a000f20022003410f6a410110782008210620080d000b20022007200a10780240200b450d00200710350b2000411f3a00000240200141106a280200450d00200510350b200341106a24000f0b103e000b103c000bde03030a7f017e027f230041106b2203240020012802002104200341003a000e2004210503402003200541800172200541ff0071200541077622061b3a000e20022003410e6a410110782006210520060d000b200128020422072001410c6a2802002206410c6c6a2108200141086a280200210920072105024002402006450d00200721052004450d00200841746a210a410021052007210b0340200b2106024003402006280200220c0d01200541016a210520082006410c6a2206470d000c040b0b200641046a290200210d200341003a000e2006410c6a210b200541016a210e03402003200541800172200541ff0071200541077622011b3a000e20022003410e6a410110782001210520010d000b200341003a000f200d422088a7220f210503402003200541800172200541ff0071200541077622011b3a000f20022003410f6a410110782001210520010d000b2002200c200f10780240200da7450d00200c10350b0240200a2006460d00200e21052004417f6a22040d010b0b2006410c6a21050b20082005460d00034020052206410c6a2105024020062802002202450d00200641046a280200450d00200210350b20082005470d000b0b02402009450d002009410c6c450d00200710350b2000411f3a0000200341106a24000bfe0101067f2000410c6a280200200028020822016b2202411c6d210302402002450d0020012003411c6c6a21040340024020012802042202450d0002402001410c6a2802002203450d00200341047421030340024020022d00004109470d000240200241046a2205280200220628020441ffffffff0371450d0020062802001035200528020021060b200610350b200241106a2102200341706a22030d000b0b200141086a28020041ffffffff0071450d00200128020410350b2001411c6a21020240200141146a280200450d00200128021010350b2002210120022004470d000b0b024020002802042202450d002002411c6c450d00200028020010350b0b820201067f2000410c6a280200200028020822016b220241186d210302402002450d002001200341186c6a210403400240200141046a28020041ffffffff0171450d00200128020010350b0240200141146a2802002203450d00200128020c2102200341047421030340024020022d00004109470d000240200241046a2205280200220628020441ffffffff0371450d0020062802001035200528020021060b200610350b200241106a2102200341706a22030d000b0b200141186a21020240200141106a28020041ffffffff0071450d00200128020c10350b2002210120022004470d000b0b024020002802042202450d00200241186c450d00200028020010350b0b850201067f2000410c6a280200200028020822016b2202411c6d210302402002450d0020012003411c6c6a21040340024020012802042202450d0002402001410c6a2802002203450d00200341047421030340024020022d00004109470d000240200241046a2205280200220628020441ffffffff0371450d0020062802001035200528020021060b200610350b200241106a2102200341706a22030d000b0b200141086a28020041ffffffff0071450d00200128020410350b2001411c6a21020240200141146a28020041ffffffff0371450d00200128021010350b2002210120022004470d000b0b024020002802042202450d002002411c6c450d00200028020010350b0bcf0101067f02402000410c6a2802002201200028020822026b450d000340024020022802082203450d0020022802002104200341047421030340024020042d00004109470d000240200441046a2205280200220628020441ffffffff0371450d0020062802001035200528020021060b200610350b200441106a2104200341706a22030d000b0b200241106a21040240200241046a28020041ffffffff0071450d00200228020010350b2004210220042001470d000b0b0240200028020441ffffffff0071450d00200028020010350b0b8f05010b7f230041c080016b220224002002200110c007410121030240024020022802004101460d00200228020421042002410041808001109f08210541002106410021070240024002400240024002402004450d004100210841002109410121034100210a03402001280204220b200128020822076b2004200a6b220c41808001200c41808001491b220c490d022007200c6a22062007490d03200b2006490d042005200128020020076a200c109d08210b2001200636020802400240200920086b200c490d002008200c6a2107200921060c010b2008200c6a22072008490d06200941017422062007200620074b1b22064100480d060240024020090d00024020060d00410121030c020b2006103322030d010c090b20092006460d0020032009200610372203450d080b200621090b200320086a200b200c109d081a200721082004200c200a6a220a4b0d000b0b2000200336020420004100360200200041146a2007360200200041106a41003602002000410c6a2007360200200041086a20063602000c060b200541013a008f8001200541b480016a4101360200200542013702a48001200541acfdcb003602a08001200541363602bc80012005200541b880016a3602b0800120052005418f80016a3602b880012005419080016a200541a080016a10412005418b80016a2005419880016a2802003600002005200529039080013700838001200041053a00042000200529008080013700052000410c6a2005418780016a290000370000200041013602002009450d05200310350c050b2007200641c0fdcb001059000b2006200b41c0fdcb001058000b103e000b103c000b20002002290204370204200041013602002000410c6a2002410c6a2902003702000b200241c080016a24000bf50202057f017e02400240024020014108490d00200141017641feffffff07712202417f6a220320014f0d022001410d74200173220441117620047322044105742004732205417f2001417f6a677622067122044100200120042001491b6b220420014f0d01200020034103746a220329020021072003200020044103746a220429020037020020042007370200024020022001490d00200221030c030b2005410d7420057322044111762004732204410574200473220520067122044100200120042001491b6b220420014f0d01200020024103746a220329020021072003200020044103746a2204290200370200200420073702002002410172220320014f0d022005410d742005732204411176200473220441057420047320067122044100200120042001491b6b220420014f0d01200020034103746a220129020021072001200020044103746a2200290200370200200020073702000b0f0b20042001418486cc001042000b2003200141f485cc001042000bb20102037f017e024020014101762202450d00200020012002417f6a10cb072002417e6a210203402002417f460d0120002001200210cb072002417f6a21020c000b0b0240024020014102490d00200141037420006a41786a21022001210303402003417f6a220420014f0d0220002902002105200020022902003702002002200537020020002004410010cb07200241786a210220042103200441014b0d000b0b0f0b2003417f6a2001418486cc001042000b8f06050a7f017e017f017e037f200041686a2102200041786a210320014132492104410121054100210602400240024003400240024020052001490d00410021070c010b200320054103746a210841012107034002400240200841086a22092802002008280200200841046a280200220a2008410c6a28020022082008200a4b1b10a008220b450d00200b4100480d030c010b2008200a490d020b4101210a200541016a220520014921072009210820012005470d000c030b0b2005200146210a20040d0120052001460d012005417f6a220820014f0d032007410171450d02200020084103746a2208290200210c200820002005410374220d6a2209290200220e3702002009200c370200024020054102490d0002400240200ea7220f20002005417e6a22074103746a220b280200200b41046a2802002210200841046a280200220a200a20104b1b10a0082211450d0020114100480d010c020b200a20104f0d010b2008200b29020037020002402007450d002002200d6a21080240034002400240200f2008280200200841046a280200220b200a200a200b4b1b10a0082210450d00201041004e0d030c010b200a200b4f0d020b200841086a2008290200370200200841786a21082007417f6a22070d000b0b200841086a210b0b200b200f360200200b200a3602040b200641016a21060240200120056b220f4102490d000240024020092802082009280200220d200941046a280200220b2009410c6a28020022082008200b4b1b10a008220a450d00200a4100480d010c020b2008200b4f0d010b200941086a2111200920092902083702000240200f4103490d004103210a41022107034002400240200920074103746a2208280200200d200b200841046a28020022072007200b4b1b10a0082210450d00201041004e0d030c010b2007200b4f0d020b200841786a20082902003702000240200a200f4f0d00200a2107200a41016a210a200821110c010b0b200821110b2011200d3602002011200b3602040b20064105470d000b4100210a0b200a0f0b20052001418486cc001042000b2008200141f485cc001042000bb60202057f017e03402002410174220341017221040240024002400240200341026a220320014f0d00200420014f0d0102400240200020044103746a2205280200200020034103746a2206280200200641046a2802002206200541046a2802002205200520064b1b10a0082207450d00417f410120074100481b21060c010b417f200520064720052006491b21060b200320042006417f461b21040b0240200420014f0d00200220014f0d020240200020024103746a2202280200200020044103746a2203280200200341046a2802002206200241046a2802002205200520064b1b10a0082207450d00200741004e0d010c040b20052006490d030b0f0b2004200141f487cc001042000b20022001418488cc001042000b200229020021082002200329020037020020032008370200200421020c000b0b830401097f200141096a2d0000210220012802042103200128020021040240024002400240024002400240024020012d000822014102470d0020040d010c050b20014101462105024020040d00200521060c020b2005200320046b6a220620054f0d01410021074100210541002106410121080340024002400240200141ff01714102470d00200221090c010b410021092001410171450d00410021010c010b2004450d0820042003460d0820042d0000210241022101200441016a21040b024020052006470d002005417f200320046b410020041b220641016a220a200a2006491b6a22062005490d0420072006200720064b1b22064100480d04024020050d00024020060d00410121080c020b2006103322080d010c060b20052006460d0020082005200610372208450d050b200820056a20023a0000200741026a2107200541016a2105200921020c000b0b200320046b21060b2006450d0220064100480d00200610332208450d010c030b103e000b103c000b41012108410021060b02400240200141037122074103460d00410021052008210120070e03010001010b200820023a000041012105200841016a21010b2004450d0020032004460d00200421020340200120022d00003a0000200141016a21012003200241016a2202470d000b2003200520046b6a21050b2000200536020820002006360204200020083602000bc76501037f230041206b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020002d00000eac010102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa01ab0100010b2002200128021841cff1cb0041112001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000cab010b2002200128021841e0f1cb00410b2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000caa010b2002200128021841ebf1cb0041032001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000ca9010b2002200128021841eef1cb0041052001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a41f4f1cb00106f21000ca8010b200220012802184184f2cb0041042001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a41f4f1cb00106f21000ca7010b200220012802184188f2cb0041022001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a41f4f1cb00106f21000ca6010b20022001280218418af2cb0041042001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000ca5010b20022001280218418ef2cb0041032001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000ca4010b200220012802184191f2cb0041022001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21000ca3010b200220012802184193f2cb0041042001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21000ca2010b200220012802184197f2cb0041072001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a0f2cb00106f21000ca1010b2002200128021841b0f2cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000ca0010b2002200128021841b6f2cb0041042001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21000c9f010b2002200128021841baf2cb00410c2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21012002200041016a36020c20012002410c6a41c8f2cb00106f21000c9e010b2002200128021841d8f2cb0041042001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c9d010b2002200128021841dcf2cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c9c010b2002200128021841e2f2cb0041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21000c9b010b2002200128021841eaf2cb0041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21000c9a010b2002200128021841f2f2cb0041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21000c99010b2002200128021841faf2cb0041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21000c98010b200220012802184183f3cb0041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21000c97010b20022001280218418cf3cb0041072001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21012002200041086a36020c20012002410c6a4198f1cb00106f21000c96010b200220012802184193f3cb0041072001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21012002200041086a36020c20012002410c6a4198f1cb00106f21000c95010b20022001280218419af3cb0041072001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21012002200041086a36020c20012002410c6a4198f1cb00106f21000c94010b2002200128021841a1f3cb0041072001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21012002200041086a36020c20012002410c6a4198f1cb00106f21000c93010b2002200128021841a8f3cb0041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21012002200041086a36020c20012002410c6a4198f1cb00106f21000c92010b2002200128021841b1f3cb0041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21012002200041086a36020c20012002410c6a4198f1cb00106f21000c91010b2002200128021841baf3cb00410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21012002200041086a36020c20012002410c6a4198f1cb00106f21000c90010b2002200128021841c4f3cb00410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21012002200041086a36020c20012002410c6a4198f1cb00106f21000c8f010b2002200128021841cef3cb0041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21012002200041086a36020c20012002410c6a4198f1cb00106f21000c8e010b2002200128021841d7f3cb0041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21012002200041086a36020c20012002410c6a4198f1cb00106f21000c8d010b2002200128021841e0f3cb00410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21012002200041086a36020c20012002410c6a4198f1cb00106f21000c8c010b2002200128021841eaf3cb00410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21012002200041086a36020c20012002410c6a4198f1cb00106f21000c8b010b2002200128021841f4f3cb00410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21012002200041086a36020c20012002410c6a4198f1cb00106f21000c8a010b2002200128021841fef3cb00410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21012002200041086a36020c20012002410c6a4198f1cb00106f21000c89010b200220012802184188f4cb0041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21012002200041086a36020c20012002410c6a4198f1cb00106f21000c88010b200220012802184190f4cb0041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21012002200041086a36020c20012002410c6a4198f1cb00106f21000c87010b200220012802184198f4cb0041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21012002200041086a36020c20012002410c6a4198f1cb00106f21000c86010b2002200128021841a0f4cb0041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21012002200041086a36020c20012002410c6a4198f1cb00106f21000c85010b2002200128021841a8f4cb0041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21012002200041086a36020c20012002410c6a4198f1cb00106f21000c84010b2002200128021841b1f4cb00410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21012002200041086a36020c20012002410c6a4198f1cb00106f21000c83010b2002200128021841bbf4cb0041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21012002200041086a36020c20012002410c6a4198f1cb00106f21000c82010b2002200128021841c4f4cb00410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21012002200041086a36020c20012002410c6a4198f1cb00106f21000c81010b2002200128021841cef4cb00410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21012002200041086a36020c20012002410c6a4198f1cb00106f21000c80010b2002200128021841d8f4cb00410d2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a41c8f2cb00106f21000c7f0b2002200128021841e5f4cb00410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a41c8f2cb00106f21000c7e0b2002200128021841eff4cb0041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41f8f4cb00106f21000c7d0b200220012802184188f5cb0041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041086a36020c200241106a2002410c6a4190f5cb00106f21000c7c0b2002200128021841a0f5cb0041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4198f1cb00106f21000c7b0b2002200128021841a8f5cb0041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041086a36020c200241106a2002410c6a41b0f5cb00106f21000c7a0b2002200128021841c0f5cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c790b2002200128021841c6f5cb0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c780b2002200128021841cbf5cb0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c770b2002200128021841d0f5cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c760b2002200128021841d6f5cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c750b2002200128021841dcf5cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c740b2002200128021841e2f5cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c730b2002200128021841e8f5cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c720b2002200128021841eef5cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c710b2002200128021841f4f5cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c700b2002200128021841faf5cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6f0b200220012802184180f6cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6e0b200220012802184186f6cb0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6d0b20022001280218418bf6cb0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6c0b200220012802184190f6cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6b0b200220012802184196f6cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6a0b20022001280218419cf6cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c690b2002200128021841a2f6cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c680b2002200128021841a8f6cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c670b2002200128021841aef6cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c660b2002200128021841b4f6cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c650b2002200128021841baf6cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c640b2002200128021841c0f6cb0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c630b2002200128021841c5f6cb0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c620b2002200128021841caf6cb0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c610b2002200128021841cff6cb0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c600b2002200128021841d4f6cb0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5f0b2002200128021841d9f6cb0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5e0b2002200128021841def6cb0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5d0b2002200128021841e3f6cb0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5c0b2002200128021841e8f6cb0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5b0b2002200128021841edf6cb0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5a0b2002200128021841f2f6cb0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c590b2002200128021841f7f6cb0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c580b2002200128021841fcf6cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c570b200220012802184182f7cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c560b200220012802184188f7cb0041092001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c550b200220012802184191f7cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c540b200220012802184197f7cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c530b20022001280218419df7cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c520b2002200128021841a3f7cb0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c510b2002200128021841aaf7cb0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c500b2002200128021841b1f7cb0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4f0b2002200128021841b8f7cb0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4e0b2002200128021841bff7cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4d0b2002200128021841c5f7cb0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4c0b2002200128021841caf7cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4b0b2002200128021841d0f7cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4a0b2002200128021841d6f7cb0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c490b2002200128021841ddf7cb0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c480b2002200128021841e4f7cb0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c470b2002200128021841ebf7cb0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c460b2002200128021841f2f7cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c450b2002200128021841f8f7cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c440b2002200128021841fef7cb0041092001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c430b200220012802184187f8cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c420b20022001280218418df8cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c410b200220012802184193f8cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c400b200220012802184199f8cb0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3f0b2002200128021841a0f8cb0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3e0b2002200128021841a7f8cb0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3d0b2002200128021841aef8cb0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3c0b2002200128021841b5f8cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3b0b2002200128021841bbf8cb0041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3a0b2002200128021841c0f8cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c390b2002200128021841c6f8cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c380b2002200128021841ccf8cb0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c370b2002200128021841d3f8cb0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c360b2002200128021841daf8cb0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c350b2002200128021841e1f8cb0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c340b2002200128021841e8f8cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c330b2002200128021841eef8cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c320b2002200128021841f4f8cb0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c310b2002200128021841fbf8cb0041082001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c300b200220012802184183f9cb0041082001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2f0b20022001280218418bf9cb00410a2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2e0b200220012802184195f9cb0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2d0b20022001280218419cf9cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2c0b2002200128021841a2f9cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2b0b2002200128021841a8f9cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2a0b2002200128021841aef9cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c290b2002200128021841b4f9cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c280b2002200128021841baf9cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c270b2002200128021841c0f9cb00410b2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c260b2002200128021841cbf9cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c250b2002200128021841d1f9cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c240b2002200128021841d7f9cb0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c230b2002200128021841def9cb0041082001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c220b2002200128021841e6f9cb0041082001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c210b2002200128021841eef9cb00410a2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c200b2002200128021841f8f9cb0041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1f0b2002200128021841fff9cb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1e0b200220012802184185facb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1d0b20022001280218418bfacb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1c0b200220012802184191facb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1b0b200220012802184197facb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1a0b20022001280218419dfacb0041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c190b2002200128021841a3facb00410b2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c180b2002200128021841aefacb00410a2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c170b2002200128021841b8facb00410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c160b2002200128021841c4facb00410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c150b2002200128021841d0facb00410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c140b2002200128021841dcfacb00410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c130b2002200128021841e8facb00410d2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c120b2002200128021841f5facb00410d2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c110b200220012802184182fbcb00410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c100b20022001280218418efbcb00410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0f0b20022001280218419afbcb00410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0e0b2002200128021841a6fbcb00410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0d0b2002200128021841b2fbcb00410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0c0b2002200128021841c0fbcb00410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0b0b2002200128021841cefbcb00410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0a0b2002200128021841dcfbcb00410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c090b2002200128021841eafbcb00410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c080b2002200128021841f6fbcb00410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c070b200220012802184184fccb00410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c060b200220012802184192fccb00410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c050b2002200128021841a0fccb00410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c040b2002200128021841aefccb00410d2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c030b2002200128021841bbfccb0041112001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c020b2002200128021841ccfccb0041112001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c010b2002200128021841ddfccb0041112001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000b20002d00082101024020002802042203450d00200141ff0171210441012101024020040d00024020034101470d0020002d0009450d00200028020022042d00004104710d0041012101200428021841d6a0c00041012004411c6a28020028020c1100000d010b2000280200220128021841cca6cc0041012001411c6a28020028020c11000021010b200020013a00080b200241206a2400200141ff01714100470bcc0101047f230041106b220224002000280200220041046a28020021032000280200210041012104200128021841d9a0c00041012001411c6a28020028020c1100002105200241003a0005200220053a00042002200136020002402003450d002003410274210103402002200036020c20022002410c6a41f0fccb0010701a200041046a21002001417c6a22010d000b20022d000421050b0240200541ff01710d002002280200220028021841d8a0c00041012000411c6a28020028020c11000021040b200241106a240020040b8a0201027f230041106b2202240020002802002802002100200128021841a8f1cb00410b2001411c6a28020028020c1100002103200241003a0005200220033a0004200220013602002002200036020c200241b3f1cb0041052002410c6a41b8f1cb00106921012002200041086a36020c200141c8f1cb0041072002410c6a4198f1cb0010691a20022d00042101024020022d0005450d00200141ff0171210041012101024020000d0020022802002201411c6a28020028020c210020012802182103024020012d00004104710d00200341d0a0c0004102200011000021010c010b200341d2a0c0004101200011000021010b200220013a00040b200241106a2400200141ff01714100470b0c002000280200200110b9070bc50201037f230041206b2202240002400240200028020022002d00004104470d0020022001280218419cfdcb0041082001411c6a28020028020c11000022003a001820022001360210200241003a0019200241003602140c010b2002200128021841a4fdcb0041052001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200036020c200241106a2002410c6a418cfdcb00106f210120022d0018210020022802142203450d00200041ff0171210441012100024020040d00024020034101470d0020012d0009450d00200128020022042d00004104710d0041012100200428021841d6a0c00041012004411c6a28020028020c1100000d010b2001280200220028021841cca6cc0041012000411c6a28020028020c11000021000b200120003a00080b200241206a2400200041ff01714100470bc00201037f230041206b220224000240024020002d00004104470d0020022001280218419cfdcb0041082001411c6a28020028020c11000022003a001820022001360210200241003a0019200241003602140c010b2002200128021841a4fdcb0041052001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200036020c200241106a2002410c6a418cfdcb00106f210120022d0018210020022802142203450d00200041ff0171210441012100024020040d00024020034101470d0020012d0009450d00200128020022042d00004104710d0041012100200428021841d6a0c00041012004411c6a28020028020c1100000d010b2001280200220028021841cca6cc0041012000411c6a28020028020c11000021000b200120003a00080b200241206a2400200041ff01714100470bd70203027f017e017f23004180016b220224002000280200210002400240024002400240200128020022034110710d002000280200210020034120710d012000ac22042004423f8722047c2004852000417f73411f762001105221000c020b20002802002103410021000340200220006a41ff006a2003410f712205413072200541d7006a2005410a491b3a00002000417f6a2100200341047622030d000b20004180016a22034181014f0d022001410141d88bc0004102200220006a4180016a410020006b105621000c010b410021030340200220036a41ff006a2000410f712205413072200541376a2005410a491b3a00002003417f6a2103200041047622000d000b20034180016a22004181014f0d022001410141d88bc0004102200220036a4180016a410020036b105621000b20024180016a240020000f0b200341800141c88bc0001059000b200041800141c88bc0001059000bca0201037f23004180016b220224002000280200210002400240024002400240200128020022034110710d0020002d0000210420034120710d012004ad42ff018341012001105221000c020b20002d00002104410021000340200220006a41ff006a2004410f712203413072200341d7006a2003410a491b3a00002000417f6a21002004410476410f7122040d000b20004180016a22044181014f0d022001410141d88bc0004102200220006a4180016a410020006b105621000c010b410021000340200220006a41ff006a2004410f712203413072200341376a2003410a491b3a00002000417f6a21002004410476410f7122040d000b20004180016a22044181014f0d022001410141d88bc0004102200220006a4180016a410020006b105621000b20024180016a240020000f0b200441800141c88bc0001059000b200441800141c88bc0001059000bd70202027f027e23004180016b220224002000280200210002400240024002400240200128020022034110710d002000290300210420034120710d0120042004423f8722057c2005852004427f552001105221000c020b20002903002104410021000340200220006a41ff006a2004a7410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200442048822044200520d000b20004180016a22034181014f0d022001410141d88bc0004102200220006a4180016a410020006b105621000c010b410021000340200220006a41ff006a2004a7410f712203413072200341376a2003410a491b3a00002000417f6a2100200442048822044200520d000b20004180016a22034181014f0d022001410141d88bc0004102200220006a4180016a410020006b105621000b20024180016a240020000f0b200341800141c88bc0001059000b200341800141c88bc0001059000b940201047f230041106b220324000240024002400240200241ffffffff03712002470d0020024102742204417f4c0d000240024020040d00410421050c010b200410332205450d020b20034100360208200320053602002003200441027636020420034100200210860120032802002205200328020822064102746a20012002410274109d081a024020032802042204200620026a2202460d0020042002490d032004450d002004410274220120024102742204460d00024020040d00024020010d00410421050c020b20051035410421050c010b20052001200410372205450d040b2000200236020420002005360200200341106a24000f0b1044000b1045000b41ec80cc00412441c086cc00103f000b103c000bab0902027f017e230041106b220224000240024020012d00002203414f6a41fb00490d0002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020030e312a2a0001022a2a0304052a06072a2a08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a0b200020012d00013a0001410221030c290b200020012d00013a0001410321030c280b200020012d00013a0001410421030c270b200041046a200141046a280200360200410721030c260b200041046a200141046a280200360200410821030c250b200141046a2802002103410c10332201450d25200241086a2003280200200341046a28020010d607200229030821042001200328020836020820012004370200200041046a2001360200410921030c240b200041046a200141046a280200360200410b21030c230b200020012d00013a0001200041046a200141046a280200360200410c21030c220b200041046a200141046a280200360200410f21030c210b200041046a200141046a280200360200411021030c200b200041046a200141046a280200360200411121030c1f0b200041046a200141046a280200360200411221030c1e0b200041046a200141046a280200360200411321030c1d0b200041046a200141046a290200370200411421030c1c0b200041046a200141046a290200370200411521030c1b0b200041046a200141046a290200370200411621030c1a0b200041046a200141046a290200370200411721030c190b200041046a200141046a290200370200411821030c180b200041046a200141046a290200370200411921030c170b200041046a200141046a290200370200411a21030c160b200041046a200141046a290200370200411b21030c150b200041046a200141046a290200370200411c21030c140b200041046a200141046a290200370200411d21030c130b200041046a200141046a290200370200411e21030c120b200041046a200141046a290200370200411f21030c110b200041046a200141046a290200370200412021030c100b200041046a200141046a290200370200412121030c0f0b200041046a200141046a290200370200412221030c0e0b200041046a200141046a290200370200412321030c0d0b200041046a200141046a290200370200412421030c0c0b200041046a200141046a290200370200412521030c0b0b200041046a200141046a290200370200412621030c0a0b200041046a200141046a290200370200412721030c090b200041046a200141046a290200370200412821030c080b200041046a200141046a290200370200412921030c070b200041046a200141046a290200370200412a21030c060b200020012d00013a0001412b21030c050b200020012d00013a0001412c21030c040b200041046a200141046a280200360200412d21030c030b200041086a200141086a290300370300412e21030c020b200041046a200141046a280200360200412f21030c010b200041086a200141086a290300370300413021030b200020033a0000200241106a24000f0b103c000bcc0201027f230041106b22022400200028020028020021002001280218418b85cc0041052001411c6a28020028020c1100002103200241003a0005200220033a00042002200136020020022000410c6a36020c2002419085cc00410e2002410c6a41a085cc00106921012002200036020c200141b085cc0041092002410c6a41bc85cc00106921012002200041046a36020c200141cc85cc00410c2002410c6a41bc85cc00106921012002200041086a36020c200141d885cc00410c2002410c6a41bc85cc0010691a20022d00042100024020022d0005450d00200041ff0171210141012100024020010d0020022802002200411c6a28020028020c210120002802182103024020002d00004104710d00200341d0a0c0004102200111000021000c010b200341d2a0c0004101200111000021000b200220003a00040b200241106a2400200041ff01714100470bd50302047f017e024020014101762202450d0003402002417f6a2202210302400240024003402003410174220441017221050240200441026a220420014f0d00200520014f0d0220042005200020054103746a280200200020044103746a280200491b21050b200520014f0d03200320014f0d02200020034103746a2203280200200020054103746a22042802004f0d03200329020021062003200429020037020020042006370200200521030c000b0b2005200141f487cc001042000b20032001418488cc001042000b20020d000b0b0240024020014102490d002001210403402004417f6a220420014f0d02200029020021062000200020044103746a2205290200370200200520063702004100210302400240024003402003410174220241017221050240200241026a220220044f0d00200520044f0d0220022005200020054103746a280200200020024103746a280200491b21050b200520044f0d03200320044f0d02200020034103746a2203280200200020054103746a22022802004f0d03200329020021062003200229020037020020022006370200200521030c000b0b2005200441f487cc001042000b20032004418488cc001042000b200441014b0d000b0b0f0b20042001418486cc001042000bea04050a7f017e017f017e027f200041686a21022001417f6a2103200041086a2104410021052001413249210641012107024003400240024020072001490d00410021080c010b410121082000200741037422096a220a280200220b200a41786a280200490d00200420096a210803404101210a20032007460d03200741016a21072008280200220a200b4f2109200841086a2108200a210b20090d000b200720014921080b2007200146210a20060d0120072001460d010240024002400240024002402007417f6a220b20014f0d002008450d012000200b4103746a220b290200210c200b20002007410374220d6a2208290200220e3702002008200c37020020074102490d0520002007417e6a220a4103746a220f280200200ea722094d0d05200b200f290200370200200a450d0420002007417d6a220a4103746a28020020094d0d042002200d6a210b0340200b41086a200b290200370200200a450d03200a417f6a210a200b41786a220b28020020094b0d000b200a41016a210b0c030b200b200141f485cc001042000b20072001418486cc001042000b4100210b0b2000200b4103746a210f0b200f200e3702000b200541016a21050240200120076b220a4102490d00200828020820082802004f0d002008290200210c20082008290208370200200841086a210f0240200a4103490d002008280210200ca722104f0d00200841106a21094103210b4102210d0340200d41037420086a220f41786a2009290200370200200b200a4f0d01200b4103742109200b210d200b41016a210b200820096a22092802002010490d000b0b200f200c3702000b20054105470d000b4100210a0b200a0bcc5e010c7f230041a0016b22032400200320013602242002280208220441546a2105200241106a280200220641306c21010240024002400240024002400240024002400240024003402001450d01200141506a21012005412c6a2107200541306a2208210520072d00004104470d000b200641306c2101200441546a210503402001450d02200141506a21012005412c6a2107200541306a2209210520072d0000410c470d000b200641306c2101200441546a210503402001450d03200141506a21012005412c6a2107200541306a2204210520072d00004102470d000b0240410028028cb54c4105490d00200341013602442003200341246a3602404100280298b54c21014100280294b54c21054100280290b54c210720034198016a41980136020020034190016a42ee808080103703002003418c016a41b88acc0036020020034184016a422537020020034180016a41ee8bcc00360200200341f8006a4201370300200341e8006a4201370300200341e0006a410a360200200341f4006a200341c0006a360200200341c888cc00360264200341e48bcc0036025c20034105360258200541aca2c000200741024622071b200341d8006a200141c4a2c00020071b2802101102000b200341186a200810bf03200328021c200328022422014d0d03200328021820014102746a2201450d03200341106a200410bf032003280214200128020022014d0d04200328021020014104746a2201450d04200941086a280200200328022422054d0d0820092802002109200341286a41086a420037030020034280808080c00037032820012d000d2101410021072003410036024820032001410447220a3602442003200a360240200341003a004c410028028cb54c41044b0d05200341d8006a41086a200341c0006a41086a29030037030020032003290340370358200341286a410472210b200341d8006a21010c060b411310332201450d082001410f6a41002800a3884c360000200141086a410029009c884c37000020014100290094884c370000200041086a4293808080b00237020020002001360204200041013602000c090b410f10332201450d07200141076a41002900ae884c370000200141002900a7884c370000200041086a428f808080f00137020020002001360204200041013602000c080b410f10332201450d06200141076a41002900bd884c370000200141002900b6884c370000200041086a428f808080f00137020020002001360204200041013602000c070b412510332201450d052001411d6a41002900ed884c370000200141186a41002900e8884c370000200141106a41002900e0884c370000200141086a41002900d8884c370000200141002900d0884c370000200041086a42a5808080d00437020020002001360204200041013602000c060b412510332201450d042001411d6a41002900ed884c370000200141186a41002900e8884c370000200141106a41002900e0884c370000200141086a41002900d8884c370000200141002900d0884c370000200041086a42a5808080d00437020020002001360204200041013602000c050b200341c0003602542003200341c0006a3602504100280298b54c21014100280294b54c21074100280290b54c210820034198016a41cb0036020020034190016a42ee808080103703002003418c016a41b88acc0036020020034184016a422537020020034180016a41ee8bcc00360200200341f8006a4201370300200341e8006a4201370300200341d8006a41086a2206410a360200200341f4006a200341d0006a360200200341f888cc00360264200341e48bcc0036025c20034105360258200741aca2c000200841024622081b200341d8006a200141c4a2c00020081b28021011020020032802342108200328023021072006200341c0006a41086a29030037030020032003290340370358200341286a410472210b200341d8006a210120082007470d010b200b20074101108c01200328023421080b200b28020020084104746a22072001290200370200200741086a200141086a2902003702002003200328023441016a3602344100210702402009200541186c6a2201280214450d002009200541186c6a410c6a2109200141146a2108200341d8006a410472210c41002107410021010240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240034002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200328022820074d0d00200341d8006a200341286a410010dd0720032802584101460d0120072003280228200328025c2d000c1b21070b2001200828020022054f0d1e2003200928020020014104746a220536023c0240410028028cb54c4105490d002003413936024420032003413c6a3602404100280298b54c21054100280294b54c21064100280290b54c210d200341c90136029801200342ee8080801037039001200341b88acc0036028c012003422537028401200341ee8bcc0036028001200342013703782003420137036820034188b2cc003602642003410a360260200341e48bcc0036025c20034105360258200541c4a2c000200d410246220d1b28021021052003200341c0006a360274200641aca2c000200d1b200341d8006a2005110200200328023c21050b20052d000022060eac01031b0101011b020405060708090a0b0c0d0e0f10111111111111111111111111111112121212121212121213141515151516171717171717171717171617171717171717171717171717171717171717171717181818191919191919191919191919191919181818191919191919191919191919191919181818181818181919191919191918181818181818191919191919191a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a030b200041013602002000200c2902003702042000410c6a200c41086a2802003602000c340b20052d000121052003200328022836024820032005410447220536024020032006410347200571360244200341003a004c0240410028028cb54c4105490d00200341c0003602542003200341c0006a3602504100280298b54c21054100280294b54c21064100280290b54c210d200341cb0036029801200342ee8080801037039001200341b88acc0036028c012003422537028401200341ee8bcc00360280012003420137037820034201370368200341f888cc003602642003410a360260200341e48bcc0036025c20034105360258200541c4a2c000200d410246220d1b28021021052003200341d0006a360274200641aca2c000200d1b200341d8006a20051102000b200341d8006a41086a2206200341c0006a41086a290300370300200320032903403703580240200328023422052003280230470d00200b20054101108c01200328023421050b200b28020020054104746a22052003290358370200200541086a20062903003702002003200328023441016a3602340c190b0240410028028cb54c4105490d00200b2802002105200341c10036025420032005200328023422064104746a41706a410020061b3602402003200341c0006a3602504100280298b54c21054100280294b54c21064100280290b54c210d200341d30036029801200342ee8080801037039001200341b88acc0036028c012003422537028401200341ee8bcc00360280012003420137037820034201370368200341a889cc003602642003410a360260200341e48bcc0036025c20034105360258200541c4a2c000200d410246220d1b28021021052003200341d0006a360274200641aca2c000200d1b200341d8006a20051102000b024020032802342205450d0020032005417f6a2205360234200b28020020054104746a22052d000c4102460d00200528020021062003200528020822053602400240410028028cb54c4105490d00200341013602542003200341c0006a3602504100280298b54c21054100280294b54c210d4100280290b54c210e200341db0036029801200342ee8080801037039001200341b88acc0036028c012003422537028401200341ee8bcc00360280012003420137037820034201370368200341b089cc003602642003410a360260200341e48bcc0036025c20034105360258200541c4a2c000200e410246220e1b28021021052003200341d0006a360274200d41aca2c000200e1b200341d8006a2005110200200328024021050b20032005360228200320063602500240410028028cb54c4105490d00200341013602442003200341d0006a3602404100280298b54c21054100280294b54c21064100280290b54c210d200341e30036029801200342ee8080801037039001200341b88acc0036028c012003422537028401200341ee8bcc00360280012003420137037820034201370368200341b889cc003602642003410a360260200341e48bcc0036025c20034105360258200541c4a2c000200d410246220d1b28021021052003200341c0006a360274200641aca2c000200d1b200341d8006a200511020020032802282105200328025021060b0240200520066a22062005490d00200320063602280c1a0b410e10332201450d36200141066a41002900c6894c370000200141002900c0894c370000200041086a428e808080e00137020020002001360204200041013602000c330b411710332201450d352001410f6a41002900dd894c370000200141086a41002900d6894c370000200141002900ce894c370000200041086a4297808080f00237020020002001360204200041013602000c320b0240410028028cb54c4105490d004100280298b54c21054100280294b54c21064100280290b54c210d200341c10036029801200342ee8080801037039001200341b88acc0036028c012003422537028401200341ee8bcc003602800120034200370378200341b0b4cc0036027420034201370368200341e889cc003602642003410a360260200341e48bcc0036025c20034105360258200641aca2c000200d410246220d1b200341d8006a200541c4a2c000200d1b2802101102000b024020032802342205450d002005410474200b2802006a417c6a41013a00000c180b411710332201450d342001410f6a41002900dd894c370000200141086a41002900d6894c370000200141002900ce894c370000200041086a4297808080f00237020020002001360204200041013602000c310b200341d8006a200341286a200541046a28020010dd0720032802584101460d1a200341d8006a200341286a200328025c28020410df0720032802580d1b0240410028028cb54c4105490d004100280298b54c21054100280294b54c21064100280290b54c210d200341c10036029801200342ee8080801037039001200341b88acc0036028c012003422537028401200341ee8bcc003602800120034200370378200341b0b4cc0036027420034201370368200341e889cc003602642003410a360260200341e48bcc0036025c20034105360258200641aca2c000200d410246220d1b200341d8006a200541c4a2c000200d1b2802101102000b024020032802342205450d002005410474200b2802006a417c6a41013a00000c170b411710332201450d332001410f6a41002900dd894c370000200141086a41002900d6894c370000200141002900ce894c370000200041086a4297808080f00237020020002001360204200041013602000c300b200341d8006a200341286a200541046a28020010dd0720032802584101460d1b200341d8006a200341286a200328025c280204220510df0720032802580d1c200341d8006a200341286a410110df0720032802580d1d200320053602500240410028028cb54c4105490d00200341013602442003200341d0006a3602404100280298b54c21054100280294b54c21064100280290b54c210d200341e30036029801200342ee8080801037039001200341b88acc0036028c012003422537028401200341ee8bcc00360280012003420137037820034201370368200341b889cc003602642003410a360260200341e48bcc0036025c20034105360258200541c4a2c000200d410246220d1b28021021052003200341c0006a360274200641aca2c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c160b410e10332201450d32200141066a41002900c6894c370000200141002900c0894c370000200041086a428e808080e00137020020002001360204200041013602000c2f0b200341d8006a200341286a200541046a28020028020810dd0720032802584101460d1d200328025c280204210d2005280204220628020441027421052006280200210602400340024020050d00200341d8006a200341286a200d10df0720032802580d220240410028028cb54c4105490d004100280298b54c21054100280294b54c21064100280290b54c210d200341c10036029801200342ee8080801037039001200341b88acc0036028c012003422537028401200341ee8bcc003602800120034200370378200341b0b4cc0036027420034201370368200341e889cc003602642003410a360260200341e48bcc0036025c20034105360258200641aca2c000200d410246220d1b200341d8006a200541c4a2c000200d1b2802101102000b20032802342205450d022005410474200b2802006a417c6a41013a00000c170b200341d8006a200341286a200628020010dd0720032802584101460d202005417c6a2105200641046a2106200328025c280204200d460d000b412710332201450d322001411f6a410029008f8a4c370000200141186a41002900888a4c370000200141106a41002900808a4c370000200141086a41002900f8894c370000200141002900f0894c370000200041086a42a7808080f00437020020002001360204200041013602000c2f0b411710332201450d312001410f6a41002900dd894c370000200141086a41002900d6894c370000200141002900ce894c370000200041086a4297808080f00237020020002001360204200041013602000c2e0b200341d8006a200341286a200a10df0720032802580d1f0240410028028cb54c4105490d004100280298b54c21054100280294b54c21064100280290b54c210d200341c10036029801200342ee8080801037039001200341b88acc0036028c012003422537028401200341ee8bcc003602800120034200370378200341b0b4cc0036027420034201370368200341e889cc003602642003410a360260200341e48bcc0036025c20034105360258200641aca2c000200d410246220d1b200341d8006a200541c4a2c000200d1b2802101102000b024020032802342205450d002005410474200b2802006a417c6a41013a00000c140b411710332201450d302001410f6a41002900dd894c370000200141086a41002900d6894c370000200141002900ce894c370000200041086a4297808080f00237020020002001360204200041013602000c2d0b200341d8006a200541046a280200200210e00720032802584101460d1f200341d8006a200341286a200328025c220528020810df0720032802580d20200320052d000d41044722053602500240410028028cb54c4105490d00200341013602442003200341d0006a3602404100280298b54c21054100280294b54c21064100280290b54c210d200341e30036029801200342ee8080801037039001200341b88acc0036028c012003422537028401200341ee8bcc00360280012003420137037820034201370368200341b889cc003602642003410a360260200341e48bcc0036025c20034105360258200541c4a2c000200d410246220d1b28021021052003200341c0006a360274200641aca2c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c130b410e10332201450d2f200141066a41002900c6894c370000200141002900c0894c370000200041086a428e808080e00137020020002001360204200041013602000c2c0b200341086a200410bf0302400240200328020c200541046a28020022054d0d002003280208220620054104746a220d450d00200341d8006a200341286a200620054104746a28020810df0720032802580d222003200d2d000d41044722053602500240410028028cb54c4105490d00200341013602442003200341d0006a3602404100280298b54c21054100280294b54c21064100280290b54c210d200341e30036029801200342ee8080801037039001200341b88acc0036028c012003422537028401200341ee8bcc00360280012003420137037820034201370368200341b889cc003602642003410a360260200341e48bcc0036025c20034105360258200541c4a2c000200d410246220d1b28021021052003200341c0006a360274200641aca2c000200d1b200341d8006a2005110200200328025021050b2003280228220620056a22052006490d01200320053602280c130b410e10332201450d2f200141066a410029009d8a4c370000200141002900978a4c370000200041086a428e808080e00137020020002001360204200041013602000c2c0b410e10332201450d2e200141066a41002900c6894c370000200141002900c0894c370000200041086a428e808080e00137020020002001360204200041013602000c2b0b200341d8006a200341286a410110df072003280258450d1020002003290358370204200041013602002000410c6a200341e0006a2802003602000c2a0b200341d8006a200341286a410210df0720032802580d1f41012105200341d8006a200341286a410110df0720032802580d20200341013602500240410028028cb54c4105490d00200341013602442003200341d0006a3602404100280298b54c21054100280294b54c21064100280290b54c210d200341e30036029801200342ee8080801037039001200341b88acc0036028c012003422537028401200341ee8bcc00360280012003420137037820034201370368200341b889cc003602642003410a360260200341e48bcc0036025c20034105360258200541c4a2c000200d410246220d1b28021021052003200341c0006a360274200641aca2c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c100b410e10332201450d2c200141066a41002900c6894c370000200141002900c0894c370000200041086a428e808080e00137020020002001360204200041013602000c290b41012105200341013602500240410028028cb54c4105490d00200341013602442003200341d0006a3602404100280298b54c21054100280294b54c21064100280290b54c210d200341e30036029801200342ee8080801037039001200341b88acc0036028c012003422537028401200341ee8bcc00360280012003420137037820034201370368200341b889cc003602642003410a360260200341e48bcc0036025c20034105360258200541c4a2c000200d410246220d1b28021021052003200341c0006a360274200641aca2c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c0f0b410e10332201450d2b200141066a41002900c6894c370000200141002900c0894c370000200041086a428e808080e00137020020002001360204200041013602000c280b200341d8006a200341286a410110df072003280258450d0d20002003290358370204200041013602002000410c6a200341e0006a2802003602000c270b41012105200341d8006a200341286a410110df0720032802580d1e200341013602500240410028028cb54c4105490d00200341013602442003200341d0006a3602404100280298b54c21054100280294b54c21064100280290b54c210d200341e30036029801200342ee8080801037039001200341b88acc0036028c012003422537028401200341ee8bcc00360280012003420137037820034201370368200341b889cc003602642003410a360260200341e48bcc0036025c20034105360258200541c4a2c000200d410246220d1b28021021052003200341c0006a360274200641aca2c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c0d0b410e10332201450d29200141066a41002900c6894c370000200141002900c0894c370000200041086a428e808080e00137020020002001360204200041013602000c260b41012105200341013602500240410028028cb54c4105490d00200341013602442003200341d0006a3602404100280298b54c21054100280294b54c21064100280290b54c210d200341e30036029801200342ee8080801037039001200341b88acc0036028c012003422537028401200341ee8bcc00360280012003420137037820034201370368200341b889cc003602642003410a360260200341e48bcc0036025c20034105360258200541c4a2c000200d410246220d1b28021021052003200341c0006a360274200641aca2c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c0c0b410e10332201450d28200141066a41002900c6894c370000200141002900c0894c370000200041086a428e808080e00137020020002001360204200041013602000c250b200341d8006a200341286a410110df072003280258450d0a20002003290358370204200041013602002000410c6a200341e0006a2802003602000c240b41012105200341d8006a200341286a410110df0720032802580d1c200341013602500240410028028cb54c4105490d00200341013602442003200341d0006a3602404100280298b54c21054100280294b54c21064100280290b54c210d200341e30036029801200342ee8080801037039001200341b88acc0036028c012003422537028401200341ee8bcc00360280012003420137037820034201370368200341b889cc003602642003410a360260200341e48bcc0036025c20034105360258200541c4a2c000200d410246220d1b28021021052003200341c0006a360274200641aca2c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c0a0b410e10332201450d26200141066a41002900c6894c370000200141002900c0894c370000200041086a428e808080e00137020020002001360204200041013602000c230b200341d8006a200341286a410210df072003280258450d0820002003290358370204200041013602002000410c6a200341e0006a2802003602000c220b41012105200341013602500240410028028cb54c4105490d00200341013602442003200341d0006a3602404100280298b54c21054100280294b54c21064100280290b54c210d200341e30036029801200342ee8080801037039001200341b88acc0036028c012003422537028401200341ee8bcc00360280012003420137037820034201370368200341b889cc003602642003410a360260200341e48bcc0036025c20034105360258200541c4a2c000200d410246220d1b28021021052003200341c0006a360274200641aca2c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c080b410e10332201450d24200141066a41002900c6894c370000200141002900c0894c370000200041086a428e808080e00137020020002001360204200041013602000c210b41012105200341d8006a200341286a410110df0720032802580d1a200341013602500240410028028cb54c4105490d00200341013602442003200341d0006a3602404100280298b54c21054100280294b54c21064100280290b54c210d200341e30036029801200342ee8080801037039001200341b88acc0036028c012003422537028401200341ee8bcc00360280012003420137037820034201370368200341b889cc003602642003410a360260200341e48bcc0036025c20034105360258200541c4a2c000200d410246220d1b28021021052003200341c0006a360274200641aca2c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c070b410e10332201450d23200141066a41002900c6894c370000200141002900c0894c370000200041086a428e808080e00137020020002001360204200041013602000c200b41012105200341013602500240410028028cb54c4105490d00200341013602442003200341d0006a3602404100280298b54c21054100280294b54c21064100280290b54c210d200341e30036029801200342ee8080801037039001200341b88acc0036028c012003422537028401200341ee8bcc00360280012003420137037820034201370368200341b889cc003602642003410a360260200341e48bcc0036025c20034105360258200541c4a2c000200d410246220d1b28021021052003200341c0006a360274200641aca2c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c060b410e10332201450d22200141066a41002900c6894c370000200141002900c0894c370000200041086a428e808080e00137020020002001360204200041013602000c1f0b41012105200341d8006a200341286a410110df0720032802580d19200341013602500240410028028cb54c4105490d00200341013602442003200341d0006a3602404100280298b54c21054100280294b54c21064100280290b54c210d200341e30036029801200342ee8080801037039001200341b88acc0036028c012003422537028401200341ee8bcc00360280012003420137037820034201370368200341b889cc003602642003410a360260200341e48bcc0036025c20034105360258200541c4a2c000200d410246220d1b28021021052003200341c0006a360274200641aca2c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c050b410e10332201450d21200141066a41002900c6894c370000200141002900c0894c370000200041086a428e808080e00137020020002001360204200041013602000c1e0b200341d8006a200341286a410210df0720032802580d1941012105200341013602500240410028028cb54c4105490d00200341013602442003200341d0006a3602404100280298b54c21054100280294b54c21064100280290b54c210d200341e30036029801200342ee8080801037039001200341b88acc0036028c012003422537028401200341ee8bcc00360280012003420137037820034201370368200341b889cc003602642003410a360260200341e48bcc0036025c20034105360258200541c4a2c000200d410246220d1b28021021052003200341c0006a360274200641aca2c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c040b410e10332201450d20200141066a41002900c6894c370000200141002900c0894c370000200041086a428e808080e00137020020002001360204200041013602000c1d0b41012105200341d8006a200341286a410110df0720032802580d19200341013602500240410028028cb54c4105490d00200341013602442003200341d0006a3602404100280298b54c21054100280294b54c21064100280290b54c210d200341e30036029801200342ee8080801037039001200341b88acc0036028c012003422537028401200341ee8bcc00360280012003420137037820034201370368200341b889cc003602642003410a360260200341e48bcc0036025c20034105360258200541c4a2c000200d410246220d1b28021021052003200341c0006a360274200641aca2c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c030b410e10332201450d1f200141066a41002900c6894c370000200141002900c0894c370000200041086a428e808080e00137020020002001360204200041013602000c1c0b200341d8006a200341286a410210df0720032802580d1941012105200341013602500240410028028cb54c4105490d00200341013602442003200341d0006a3602404100280298b54c21054100280294b54c21064100280290b54c210d200341e30036029801200342ee8080801037039001200341b88acc0036028c012003422537028401200341ee8bcc00360280012003420137037820034201370368200341b889cc003602642003410a360260200341e48bcc0036025c20034105360258200541c4a2c000200d410246220d1b28021021052003200341c0006a360274200641aca2c000200d1b200341d8006a2005110200200328025021050b02402003280228220620056a22052006490d00200320053602280c020b410e10332201450d1e200141066a41002900c6894c370000200141002900c0894c370000200041086a428e808080e00137020020002001360204200041013602000c1b0b41012105200341d8006a200341286a410110df0720032802580d19200341013602500240410028028cb54c4105490d00200341013602442003200341d0006a3602404100280298b54c21054100280294b54c21064100280290b54c210d200341e30036029801200342ee8080801037039001200341b88acc0036028c012003422537028401200341ee8bcc00360280012003420137037820034201370368200341b889cc003602642003410a360260200341e48bcc0036025c20034105360258200541c4a2c000200d410246220d1b28021021052003200341c0006a360274200641aca2c000200d1b200341d8006a2005110200200328025021050b2003280228220620056a22052006490d02200320053602280b200141016a22012008280200490d000c1a0b0b410e10332201450d1a200141066a41002900c6894c370000200141002900c0894c370000200041086a428e808080e00137020020002001360204200041013602000c170b2001200541a88acc001042000b200041013602002000200c2902003702042000410c6a200c41086a2802003602000c150b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c140b200041013602002000200c2902003702042000410c6a200c41086a2802003602000c130b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c120b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c110b200041013602002000200c2902003702042000410c6a200c41086a2802003602000c100b200041013602002000200c2902003702042000410c6a200c41086a2802003602000c0f0b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c0e0b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c0d0b200041013602002000200c2902003702042000410c6a200c41086a2802003602000c0c0b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c0b0b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c0a0b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c090b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c080b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c070b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c060b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c050b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c040b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c030b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c020b20002003290358370204200041013602002000410c6a200341e0006a2802003602000c010b20002003290358370204200041013602002000410c6a200341e0006a2802003602000b200328023041ffffffff0071450d03200b28020010350c030b2000410036020020002007360204200328023041ffffffff0071450d02200b28020010350c020b412710332201450d002001411f6a410029009f894c370000200141186a4100290098894c370000200141106a4100290090894c370000200141086a4100290088894c37000020014100290080894c370000200041086a42a7808080f00437020020002001360204200041013602000c010b1045000b200341a0016a24000bc20201027f230041106b220224002001280218418b85cc0041052001411c6a28020028020c1100002103200241003a0005200220033a00042002200136020020022000410c6a36020c2002419085cc00410e2002410c6a41a085cc00106921012002200036020c200141b085cc0041092002410c6a41bc85cc00106921012002200041046a36020c200141cc85cc00410c2002410c6a41bc85cc00106921012002200041086a36020c200141d885cc00410c2002410c6a41bc85cc0010691a20022d00042100024020022d0005450d00200041ff0171210141012100024020010d0020022802002200411c6a28020028020c210120002802182103024020002d00004104710d00200341d0a0c0004102200111000021000c010b200341d2a0c0004101200111000021000b200220003a00040b200241106a2400200041ff01714100470b8d0201027f024002400240024002402001410c6a2802002203417f6a220420034b0d00200420026b220220044b0d01200320024d0d032000200128020420024104746a360204200041003602000f0b411610332201450d01200020013602042001410e6a41002900c98c4c370000200141086a41002900c38c4c370000200141002900bb8c4c370000200041086a4296808080e0023702000c030b411b10332201450d0020002001360204200141176a41002800fb8c4c360000200141106a41002900f48c4c370000200141086a41002900ec8c4c370000200141002900e48c4c370000200041086a429b808080b0033702000c020b1045000b2002200341d48ccc001042000b200041013602000bba0201037f230041106b220224000240024020002802000d002002200128021841ee8fcc0041042001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c010b2002200128021841ea8fcc0041042001411c6a28020028020c1100003a000820022001360200200241003a0009200241003602042002200036020c20022002410c6a41f48fcc00106f210120022d0008210020022802042203450d00200041ff0171210441012100024020040d00024020034101470d0020012d0009450d00200128020022042d00004104710d0041012100200428021841d6a0c00041012004411c6a28020028020c1100000d010b2001280200220028021841cca6cc0041012000411c6a28020028020c11000021000b200120003a00080b200241106a2400200041ff01714100470bcd0401037f230041e0006b220324002003200236020c0240410028028cb54c4105490d002003410136021420032003410c6a3602104100280298b54c21024100280294b54c21044100280290b54c2105200341d8006a41ef00360200200341d0006a42ee80808010370300200341cc006a41b88acc00360200200341c4006a4225370200200341c0006a41ee8bcc00360200200341386a4201370300200341286a4201370300200341206a410a360200200341346a200341106a360200200341a88bcc00360224200341e48bcc0036021c20034105360218200441aca2c000200541024622051b200341186a200241c4a2c00020051b280210110200200328020c21020b0240024002400240024002402002450d00200341186a2001410010dd0720032802184101460d0120012802002202200328021c2204280208460d022002200328020c6b220420024b0d0320004100360200200120043602000c050b200041003602000c040b2000200341186a4104722202290200370200200041086a200241086a2802003602000c030b024020042d000c0d00412510332202450d02200042a5808080d004370204200020023602002002411d6a41002900cd8b4c370000200241186a41002900c88b4c370000200241106a41002900c08b4c370000200241086a41002900b88b4c370000200241002900b08b4c3700000c030b200041003602000c020b410f10332202450d002000428f808080f00137020420002002360200200241076a41002900dc8b4c370000200241002900d58b4c3700000c010b1045000b200341e0006a24000bb107010a7f230041e0006b22032400200320013602202002280208220441546a2105200241106a280200220641306c210202400340024020020d00410021070c020b200241506a21022005412c6a2107200541306a2208210520072d00004102470d000b200341186a200810bf0320032802182107200328021c21020b2002410020071b2109200641306c2102200441546a2105200741b0b4cc0020071b210a02400340024020020d004100210b0c020b200241506a21022005412c6a2107200541306a2208210520072d00004104470d000b200341106a200810bf032003280210210b2003280214210c0b200641306c2102200441546a210502400240024002400240024002400240024003402002450d01200241506a21022005412c6a2107200541306a2208210520072d00004103470d000b200841086a2802002202450d00200241286c2107200828020041186a2102410021050340200520022d0000456a2105200241286a2102200741586a22070d000b200520014d0d01200641306c2102200441546a210503402002450d07200241506a21022005412c6a2107200541306a2208210520072d00004103470d000b200341086a200810bf03200328020c220441286c210520032802082206210703402005450d08200541586a2105200741186a2108200741286a2202210720082d00000d000b20010d02200241586a21020c030b410021050b0240200c4100200b1b200120056b22024d0d00200b41b0b4cc00200b1b20024102746a22020d030b200341dc006a41013602002003420237024c200341d093cc003602482003410136022c2003200341286a3602582003200341206a360228200341386a200341c8006a1041200341386a21020c030b2006200441286c6a210803402001417f6a2101034020082002460d06200241186a2105200241286a2207210220052d00000d000b2007210220010d000b200741586a21020b2002411c6a21020b2003200228020022023602240240200920024d0d00200a20024104746a2202450d0020002002360204410021020c040b200341dc006a4102360200200341c4006a41013602002003420337024c200341e093cc003602482003410136023c2003200341386a3602582003200341206a3602402003200341246a360238200341286a200341c8006a1041200341286a21020b20022802002105200041086a200229020437020020002005360204410121020c020b419e92cc0041c20041e092cc001064000b41f092cc0041dd0041e092cc001064000b20002002360200200341e0006a24000bec0201087f024020002802002201450d0020002802082102024020002802042200450d00034020012802940321012000417f6a22000d000b0b02402002450d0041002103024003402001450d01410021040240200320012f0106490d00034002400240200128020022000d0041002103410021000c010b200441016a210420012f010421030b2001103520002101200320002f01064f0d000b200021010b200341016a2105200120034105746a220041c4006a2802002106200041386a2802002107200041346a28020021080240024020040d00200521030c010b200120054102746a4194036a2802002101410021032004417f6a2200450d00034020012802940321012000417f6a22000d000b0b20064102460d022002417f6a210202402007450d00200810350b20020d000c020b0b41958dcc00412b41c08dcc00103f000b2001450d0020012802002100200110352000450d00034020002802002101200010352001210020010d000b0b0b2600024020002802002d00000d002001419d9fc0004105105a0f0b200141a29fc0004104105a0b8c0902047f017e230041106b2202240002400240024020010d00200041ac013a00000c010b024002400240024020012d00002203414f6a41fb004f0d000c010b02400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020030e312c2c0001022c2c0304052c06072c2c08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292c0b20012d00012104410221030c2b0b20012d00012104410321030c2a0b20012d00012104410421030c290b200141046a2802002105410721030c270b200141046a2802002105410821030c260b200141046a2802002101410c10332205450d28200241086a2001280200200141046a28020010d607200229030821062005200128020836020820052006370200410921030c250b200141046a2802002105410b21030c240b200141046a280200210520012d00012104410c21030c240b200141046a2802002105410f21030c220b200141046a2802002105411021030c210b200141046a2802002105411121030c200b200141046a2802002105411221030c1f0b200141046a2802002105411321030c1e0b200141046a280200210520013502082106411421030c1d0b200141046a280200210520013502082106411521030c1c0b200141046a280200210520013502082106411621030c1b0b200141046a280200210520013502082106411721030c1a0b200141046a280200210520013502082106411821030c190b200141046a280200210520013502082106411921030c180b200141046a280200210520013502082106411a21030c170b200141046a280200210520013502082106411b21030c160b200141046a280200210520013502082106411c21030c150b200141046a280200210520013502082106411d21030c140b200141046a280200210520013502082106411e21030c130b200141046a280200210520013502082106411f21030c120b200141046a280200210520013502082106412021030c110b200141046a280200210520013502082106412121030c100b200141046a280200210520013502082106412221030c0f0b200141046a280200210520013502082106412321030c0e0b200141046a280200210520013502082106412421030c0d0b200141046a280200210520013502082106412521030c0c0b200141046a280200210520013502082106412621030c0b0b200141046a280200210520013502082106412721030c0a0b200141046a280200210520013502082106412821030c090b200141046a280200210520013502082106412921030c080b200141046a280200210520013502082106412a21030c070b20012d00012104412b21030c070b20012d00012104412c21030c060b200141046a2802002105412d21030c040b20012903082106412e21030c020b200141046a2802002105412f21030c020b20012903082106413021030b0b0b200020043a0001200020033a0000200041086a2006370300200041046a20053602000b200241106a24000f0b103c000bc60501087f230041106b220324002002280208220441546a2105200241106a280200220641306c210702400340410021082007450d01200741506a21072005412c6a2109200541306a220a210520092d00004103470d000b200a41086a2802002207450d00200741286c2105200a28020041186a2107410021080340200820072d0000456a2108200741286a2107200541586a22050d000b0b024002400240024002400240200120086b220a20014b0d00200641306c2107200441546a210503402007450d02200741506a21072005412c6a2108200541306a2209210520082d0000410c470d000b200941086a280200200a4b0d03411e10332207450d052000200736020420004101360200200741166a4100290096924c370000200741106a4100290090924c370000200741086a4100290088924c37000020074100290080924c370000200041086a429e808080e0033702000c040b412c103322070d010c040b412c10332207450d032000200736020420004101360200200741286a41002800fc914c360000200741206a41002900f4914c370000200741186a41002900ec914c370000200741106a41002900e4914c370000200741086a41002900dc914c370000200741002900d4914c370000200041086a42ac808080c0053702000c020b2000200736020420004101360200200741286a41002800d0914c360000200741206a41002900c8914c370000200741186a41002900c0914c370000200741106a41002900b8914c370000200741086a41002900b0914c370000200741002900a8914c370000200041086a42ac808080c0053702000c010b2009280200200a41186c6a28020821072003200a200210db07024020032802004101470d0020002003290204370204200041013602002000410c6a2003410c6a2802003602000c010b20032802042105200041003602002000200520076a3602040b200341106a24000f0b1045000b100020002802003502004101200110520b8903010a7f230041206b220124000240024002400240200041086a2802002202450d00410020024102746b2103417f210420002802002205210603402003450d01200441016a2104200341046a210320062802002107200641046a21062007450d000b4100200741004741016a41017122066b2004460d002002200620046a2208490d012002200741004741016a4101716b20046b220641ffffffff03712006470d0220064102742209417f4c0d024104210a02402009450d0020091033220a450d040b200141003602182001200a36021020012009410276360214200141106a410020061086012001280210200128021822064102746a200520084102746a4104200741004741016a410171220741027420036a6b109d081a200141086a22032002200620076b6a20046b360200200120012903103703000240200041046a28020041ffffffff0371450d00200028020010350b20002001290300370200200041086a20032802003602000b200141206a24000f0b2008200241cc95cc001059000b1044000b1045000bb90403077f017e097f02400240024002400240200141086a2802002203200241086a2802002204200320044b1b220541016a22064101200641014b1b220741ffffffff03712007470d0020074102742208417f4c0d00200810392209450d01024020050d004200210a0c040b2004417f6a220b20044b210c2002280200210d2003417f6a220e20034b0d022001280200210f2007417f6a2102200820096a417c6a2110410021064200210a03404100211102402003200e20066b22124d0d00410021112012200e4b0d00200f20124102746a28020021110b410021120240200c0d002004200b20066b22134d0d002013200b4b0d00200d20134102746a28020021120b200720024d0d052010200a2011ad7c2012ad7c220a3e02002010417c6a21102002417f6a2102200a422088210a200641016a22062005490d000c040b0b1044000b1045000b2007417f6a2102200820096a417c6a2111410021104200210a0340410021060240200c0d00410021062004200b20106b22124d0d00410021062012200b4b0d00200d20124102746a28020021060b200720024d0d022011200a2006ad7c220a3e02002011417c6a21112002417f6a2102200a422088210a201041016a22102005490d000b0b024020072005417f736a220220074f0d00200020073602082000200841027636020420002009360200200920024102746a200a3e02000240200141046a28020041ffffffff0371450d00200128020010350b0f0b2002200741bc95cc001042000b2002200741bc95cc001042000bb404030e7f017e017f02400240200241086a2802002203200141086a28020022046a22054101200541014b1b220641ffffffff03712006470d0020064102742207417f4c0d000240200710392208450d002004450d022001280200210902400240024020030d002006417f6a2105200720086a417c6a210a20092004417f6a22024102746a21030340200420024d0d0302402003280200450d00200620054d0d03200a41003602000b2003417c6a2103200a417c6a210a2005417f6a21052002417f6a2202417f470d000c060b0b200720086a417c6a210b200341027420022802006a417c6a210c4100210d2006210e03402004200d417f736a220220044f0d020240200920024102746a220f2802002210450d0042002111417f2102200b2105200c210a024003402006200e20026a22124d0d012005200a3502002010ad7e20117c20053502007c22113e0200201142208821110240200320026a0d002006200d20036a417f736a220520064f0d05200820054102746a20113e02000c030b2005417c6a2105200a417c6a210a200f280200211020032002417f6a22026a22122003490d000b2012200341ac95cc001042000b2012200641ac95cc001042000b200b417c6a210b200e417f6a210e200d41016a220d2004460d050c000b0b2005200641bc95cc001042000b2002200441ac95cc001042000b1045000b1044000b2000200636020820002007410276360204200020083602000240200141046a28020041ffffffff0371450d00200128020010350b0bca0302097f017e230041106b2201240002400240024002400240024002402000280200220228020041016a41004c0d002000280204220328020041016a41004c0d012000280208220441086a28020022054101200028020c22062802006b22076a220820054f0d02200720002802142802006b22052000280210220741086a28020022006a220920054f0d03024002402002290308220a42ffffffff0f560d0041002100200a200428020020084102746a3502007e2003290308422086200728020020094102746a35020084580d010b20022802000d052002410036020020022002290308427f7c370308200441086a2802002200200020062802006b22024d0d0620032802000d07200428020020024102746a350200210a200341003602002003200a20032903087c370308410121000b200141106a240020000f0b41ac96cc004118200141086a41c496cc0041d496cc001046000b41ac96cc004118200141086a41c496cc0041d496cc001046000b2008200541ac95cc001042000b2009200041ac95cc001042000b41a797cc004110200141086a41b897cc0041c897cc001046000b2002200041ac95cc001042000b41a797cc004110200141086a41b897cc0041c897cc001046000ba80301087f200028020822024102742103410021042000280200220521000240024003402003450d012004417f6a21042003417c6a210320002802002106200041046a21002006450d000b410121072004417f73200641004741016a4101716a21080c010b41002107410020046b21080b200128020822094102742103410021042001280200220121000240024003402003450d012004417f6a21042003417c6a210320002802002106200041046a21002006450d000b410021032004417f73200641004741016a4101716a21000c010b410020046b2100410121030b024020070d00410020034101736b0f0b4101210402400240024020030d0020022008490d0120092000490d02417f200220086b2203200920006b22064720032006491b22040d0020062003200320064b1b2107200120004102746a2103200520084102746a2100417f210103400240200141016a22012007490d0041000f0b2003280200210420002802002106200341046a2103200041046a2100417f200620044720062004491b2204450d000b0b20040f0b2008200241dc95cc001059000b2000200941ec95cc001059000b100020002802002000280204200110720bcd04010a7f230041106b220224002002410036020820024204370300200128000c2103410021040240024002400240024002400240024020012802042205200128020022064920012d00084100477222010d004100200520066b2204200420054b1b220741016a220420074f0d00200341086a21084100210441042109410021010340200828020022072005417f736a220a20074f0d02200620054f2107200520062005496b21052003280200200a4102746a280200210a024020012002280204470d0020022001417f41004100417f4100200520066b2209200920054b1b220941016a220b200b2009491b20071b20052006491b220941016a220b200b2009491b108601200228020021090b200920046a200a3602002002200141016a2201360208200441046a21042005200649200772450d000c070b0b2002410020041086012002280208210b20010d042002280200200b4102746a2104200520064d0d012005417f732101200341086a21092005210703402001200928020022086a220a20014f0d0320042003280200200a4102746a280200360200200141016a2101200441046a210420062007417f6a2207490d000b200520066b200b6a210b0c030b200a200741ac95cc001042000b20052006460d010c020b200a200841ac95cc001042000b200341086a28020022052006417f736a220620054f0d022004200328020020064102746a280200360200200b41016a210b0b2002200b3602080b20002002290300370200200041086a200241086a280200360200200241106a24000f0b2006200541ac95cc001042000b1c00200128021841ed9dcc00410f2001411c6a28020028020c1100000bb00301047f230041c0006b2202240020002802002103410121000240200128021841e29ec000410c2001411c6a28020028020c1100000d0002400240200328020822000d0020032802002200200328020428020c11070042e4aec285979ba58811520d012002200036020c2002413b36021420022002410c6a36021020012802182104200128021c2105410121002002413c6a41013602002002420237022c200241f09ec0003602282002200241106a36023820042005200241286a10430d020c010b2002200036020c2002410836021420022002410c6a36021020012802182104200128021c2105410121002002413c6a41013602002002420237022c200241f09ec0003602282002200241106a36023820042005200241286a10430d010b200328020c2100200241106a41146a4101360200200241106a410c6a410136020020022000410c6a3602202002200041086a360218200241043602142002200036021020012802182100200128021c2101200241286a41146a41033602002002420337022c200241809fc0003602282002200241106a36023820002001200241286a104321000b200241c0006a240020000b21002000417f6a41ff01712002ad4220862001ad842004ad4220862003ad8410000b1c00200128021841ed9dcc00410f2001411c6a28020028020c1100000b1c00200128021841ed9dcc00410f2001411c6a28020028020c1100000b9a0601037f230041d0006b22042400200420033a000f02400240024020022802082205450d00200141086a2802002106200541037420022802006a41786a220528020021020240024020052d0006450d0020062002460d010b024002400240200620024d0d00200141086a2006417f6a2202360200200128020020026a2d00002201417c6a220241014b0d0220020e020301030b412b10332202450d04200041013a0000200241276a41002800e5a94c360000200241206a41002900dea94c370000200241186a41002900d6a94c370000200241106a41002900cea94c370000200241086a41002900c6a94c370000200241002900bea94c370000200041086a42ab808080b005370200200041046a20023602000c050b411810332202450d03200241106a410029008eb04c370000200241086a4100290086b04c370000200241002900feaf4c37000020044298808080800337022420042002360220200441c4006a410136020020044201370234200441acaacc003602302004413836024c2004200441c8006a3602402004200441206a360248200441106a200441306a104102402004280224450d00200428022010350b200041013a0000200041046a20042903103702002000410c6a200441106a41086a2802003602000c040b02400240200341ff017122024104460d0020012002470d010b200041003a0000200020013a00010c040b200420013a0048200441c4006a4102360200200441206a410c6a413d36020020044202370234200441eca9cc003602302004413d3602242004200441206a3602402004200441c8006a36022820042004410f6a360220200441106a200441306a10412000410c6a200441186a280200360200200041046a2004290310370200200041013a00000c030b20004180083b01000c020b2004411810fb072004410036023820042004290300370330200441306a4100411810fc0720042802302202200428023822006a411841feafcc00411810fd072004200041186a360238200420042902343702342004200236023041d4a4cc004134200441306a41b4a4cc004188a5cc001046000b1045000b200441d0006a24000be40502047f017e230041d0006b220324000240024002400240024002400240200241086a2802002204450d00200228020022052004417f6a22044103746a2d000522064104460d02200341386a20012002200610f20720032d00384101470d012000200329023c370200200041086a200341c4006a2802003602000c060b411810332202450d04200241106a410029008eb04c370000200241086a4100290086b04c370000200241002900feaf4c37000020034298808080800337021420032002360210200341cc006a41013602002003420137023c200341acaacc00360238200341383602342003200341306a3602482003200341106a360230200341206a200341386a1041200041086a200341206a41086a280200360200200020032903203702002003280214450d05200328021010350c050b200241086a2802002204450d012004417f6a2104200228020021050b200241086a2004360200200520044103746a290200220742808080808080c0ff0083428080808080808001510d00200141086a28020021022003200737030820022007a7470d01200041003602000c030b411810332202450d01200241106a410029008eb04c370000200241086a4100290086b04c370000200241002900feaf4c37000020034298808080800337021420032002360210200341cc006a41013602002003420137023c200341acaacc00360238200341383602342003200341306a3602482003200341106a360230200341206a200341386a1041200041086a200341206a41086a280200360200200020032903203702002003280214450d02200328021010350c020b200341cc006a41023602002003412c6a41013602002003420237023c200341aca8cc0036023820034101360224200320023602302003200341206a3602482003200341086a3602282003200341306a360220200341106a200341386a1041200041086a200341106a41086a280200360200200020032903103702000c010b1045000b200341d0006a24000bef0302037f017e230041c0006b22042400200441286a20012002200310f2070240024002400240024020042d00284101460d0002400240200141086a2802002202200128020c4f0d0002402002200141046a280200470d00200241016a22052002490d05200241017422062005200620054b1b22054100480d050240024020020d002005103322060d010c090b2001280200210620022005460d0020062002200510372206450d080b20012006360200200141046a2005360200200141086a28020021020b200128020020026a20033a0000200141086a2201200128020041016a3602000c010b2004413c6a220341013602002004420137022c200441e8b1cc003602282004410136021420042001410c6a3602102004200441106a360238200441186a200441286a104120042802182201450d002004200429021c37020420042001360200200341013602002004420137022c200441acaacc00360228200441383602142004200441106a36023820042004360210200441186a200441286a104120042802182101200429021c210702402004280204450d00200428020010350b20010d020b200041003602000c030b2000200429022c370200200041086a200441346a2802003602000c020b20002007370204200020013602000c010b103e000b200441c0006a24000f0b103c000ba80301057f230041c0006b2203240020032002360200024002402001280204220420024b0d002001280208417c6a21052001410c6a280200410374210102400340024020010d00200320043602042003412c6a4102360200200341306a410c6a41013602002003420337021c200341c8b2cc00360218200341013602342003200341306a3602282003200341046a36023820032003360230200341086a200341186a10412000410c6a200341106a280200360200200041046a2003290308370200200041013a00000c040b2004200541046a2802006a22062004490d01200141786a2101200541086a2105200420024b21072006210420070d0020062104200620024d0d000b20052d00002104200041003a0000200020043a00010c020b0240412010332204450d00200041013a0000200441186a41002900c0b24c370000200441106a41002900b8b24c370000200441086a41002900b0b24c370000200441002900a8b24c370000200041086a42a08080808004370200200041046a20043602000c020b1045000b200041003a00002000200128020020026a2d00003a00010b200341c0006a24000bbd0201037f230041106b220224000240024020002d00004104470d002002200128021841a0a7cc0041032001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c010b200220012802184185a7cc0041082001411c6a28020028020c1100003a000820022001360200200241003a0009200241003602042002200036020c20022002410c6a4190a7cc00106f210120022d0008210020022802042203450d00200041ff0171210441012100024020040d00024020034101470d0020012d0009450d00200128020022042d00004104710d0041012100200428021841d6a0c00041012004411c6a28020028020c1100000d010b2001280200220028021841cca6cc0041012000411c6a28020028020c11000021000b200120003a00080b200241106a2400200041ff01714100470b930602037f017e230041d0006b22052400200520023602082005200336020c024002400240417f41012002411f71742002411f4b1b20034b0d00200541386a200141186a2203200141286a410010f20720052d00384101470d012000200529023c370200200041086a200541c4006a2802003602000c020b200541cc006a41023602002005411c6a41013602002005420337023c20054184a6cc00360238200541013602142005200541106a36024820052005410c6a3602182005200541086a360210200541206a200541386a1041200041086a200541206a41086a280200360200200020052903203702000c010b200128020021022005410036022002400240024020022802080d00200541cc006a41013602002005420237023c200541fcadcc00360238200541013602342005200541306a3602482005200541206a360230200541106a200541386a1041200528021022020d010b0240024002400240200141206a2802002202200141246a22062802004f0d00024020022001411c6a280200470d00200241016a22062002490d04200241017422072006200720064b1b22064100480d040240024020020d002006103322030d010c080b2003280200210320022006460d0020032002200610372203450d070b200120033602182001411c6a2006360200200141206a28020021020b200128021820026a20043a0000200141206a2202200228020041016a3602000c010b200541cc006a220241013602002005420137023c200541e8b1cc0036023820054101360234200520063602302005200541306a360248200541106a200541386a104120052802102201450d002005200529021437022420052001360220200241013602002005420137023c200541acaacc00360238200541383602342005200541306a3602482005200541206a360230200541106a200541386a1041200528021021022005290214210802402005280224450d00200528022010350b20020d010b200041003602000c040b20002008370204200020023602000c030b103e000b20002005290214370204200020023602000c010b103c000b200541d0006a24000bb00301017f230041d0006b22052400200520023602082005200336020c02400240024002400240417f41012002411f71742002411f4b1b20034b0d002001280200210220054100360234024020022802080d00200541cc006a41013602002005420237023c200541fcadcc00360238200541013602142005200541106a3602482005200541346a360210200541206a200541386a1041200528022022020d020b200541386a200141186a2202200141286a2203200410f20720052d00384101460d02200541386a20022003410010f20720052d00384101460d03200041003602000c040b200541cc006a41023602002005412c6a41013602002005420337023c20054184a6cc00360238200541013602242005200541206a36024820052005410c6a3602282005200541086a360220200541106a200541386a1041200041086a200541106a41086a280200360200200020052903103702000c030b20002005290224370204200020023602000c020b2000200529023c370200200041086a200541c4006a2802003602000c010b2000200529023c370200200041086a200541c4006a2802003602000b200541d0006a24000bb10402047f017e230041c0006b22032400200341286a200141186a2204200141286a2205200210f20702400240024020032d00284101460d00200341286a20042005200210f20720032d00284101470d012000200329022c370200200041086a200341346a2802003602000c020b2000200329022c370200200041086a200341346a2802003602000c010b02400240024002400240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d04200241017422062005200620054b1b22054100480d040240024020020d002005103322040d010c070b2004280200210420022005460d0020042002200510372204450d060b200120043602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c010b2003413c6a220141013602002003420137022c200341e8b1cc0036022820034101360214200320053602102003200341106a360238200341186a200341286a104120032802182202450d002003200329021c37020420032002360200200141013602002003420137022c200341acaacc00360228200341383602142003200341106a36023820032003360210200341186a200341286a104120032802182101200329021c210702402003280204450d00200328020010350b20010d010b200041003602000c030b20002007370204200020013602000c020b103e000b103c000b200341c0006a24000bb10402057f017e230041c0006b22032400200341286a200141186a2204200141286a2205200210f20702400240024020032d00284101460d00200341286a20042005200210f20720032d00284101470d012000200329022c370200200041086a200341346a2802003602000c020b2000200329022c370200200041086a200341346a2802003602000c010b02400240024002400240200141206a2802002205200141246a22062802004f0d00024020052001411c6a280200470d00200541016a22062005490d04200541017422072006200720064b1b22064100480d040240024020050d002006103322040d010c070b2004280200210420052006460d0020042005200610372204450d060b200120043602182001411c6a2006360200200141206a28020021050b200128021820056a20023a0000200141206a2201200128020041016a3602000c010b2003413c6a220141013602002003420137022c200341e8b1cc0036022820034101360214200320063602102003200341106a360238200341186a200341286a104120032802182202450d002003200329021c37020420032002360200200141013602002003420137022c200341acaacc00360228200341383602142003200341106a36023820032003360210200341186a200341286a104120032802182101200329021c210802402003280204450d00200328020010350b20010d010b200041003602000c030b20002008370204200020013602000c020b103e000b103c000b200341c0006a24000b3101017f0240024020010d0041002101410121020c010b2001103322020d001045000b20002002360200200020013602040b950101017f024002400240200041046a280200220320016b20024f0d00200120026a22022001490d01200341017422012002200120024b1b22014100480d010240024020030d00024020010d00410121020c020b2001103322020d010c040b2000280200210220032001460d0020022003200110372202450d030b20002002360200200041046a20013602000b0f0b103e000b103c000bea0101017f230041e0006b22042400200420013602082004200336020c024020012003470d00200020022001109d081a200441e0006a24000f0b200441286a41146a410a360200200441346a410c360200200441106a41146a41033602002004200441086a36024020042004410c6a360244200441c8006a41146a410036020020044203370214200441a0b3cc003602102004410c36022c200441b0b4cc003602582004420137024c200441f4b3cc003602482004200441286a3602202004200441c8006a3602382004200441c4006a3602302004200441c0006a360228200441106a41b0b4cc00104c000b17000240200041046a280200450d00200028020010350b0b1500200028020022002802002000280208200110720b1000200120002802002000280208105a0bfb0101027f230041106b22022400200220012802184190b2cc0041052001411c6a28020028020c1100003a000820022001360200200241003a0009200241003602042002200036020c20022002410c6a4198b2cc00106f1a20022d00082101024020022802042203450d00200141ff0171210041012101024020000d00024020034101470d0020022d000941ff0171450d00200228020022002d00004104710d0041012101200028021841d6a0c00041012000411c6a28020028020c1100000d010b2002280200220128021841cca6cc0041012001411c6a28020028020c11000021010b200220013a00080b200241106a2400200141ff01714100470b8a0202017f037e230041106b220524002001200210950842ffffffff0f832003200410950842ffffffff0f83108d082106200120021095084220882003200410950842ffffffff0f83108d0820064220887c220742208810890821082005200320041095084220882001200210950842ffffffff0f83108d08200742ffffffff0f837c2207422086200642ffffffff0f8384200820074220881089087c2001200210950842208820032004109508422088108d081089087c2001200210960820032004109508108908108d08108c082001200210950810890820032004109608108d08108c08109708200529030021032000200541086a29030037030820002003370300200541106a24000bdc0302017f057e230041f0006b2206240020054100360200200641e0006a2001200220032004109208200641e0006a41086a290300210720062903602108200641d0006a10910802400240024002402006290350200185200641d0006a41086a29030020028584500d00200641c0006a1091082006290340200385200641c0006a41086a29030020048584500d012002423f872209200185220120097d220a420254200920028520097d2001200954ad7d22014200532001501b0d032004423f872202200385220320027d220b420254200220048520027d2003200254ad7d22044200532004501b0d0320092002852202200284500d02200641306a109108200641206a2006290330200641306a41086a2903004200200b7d42002004200b420052ad7c7d109408200a2006290320562001200641206a41086a29030022025520012002511b450d03200541013602000c030b200342025441002004501b0d02200541013602000c020b200142025441002002501b0d01200541013602000c010b200641106a10900820062006290310200641106a41086a290300200b2004109408200a2006290300582001200641086a29030022025720012002511b0d00200541013602000b2000200837030020002007370308200641f0006a24000b3c01017f230041106b2205240020052001200220032004108208200529030021012000200541086a29030037030820002001370300200541106a24000b3e01017f230041106b22062400200620012002200320042005108308200629030021012000200641086a29030037030820002001370300200641106a24000b3c01017f230041106b2205240020052001200220032004109b08200529030021012000200541086a29030037030820002001370300200541106a24000b040000000b8c0202017f027e230041e0006b22052400200541d0006a2002423f872206200185200620028520062006109308200541d0006a41086a290300210120052903502107200541c0006a2004423f872202200385200220048520022002109308200541c0006a41086a290300210420052903402103200541306a20072001108e08200541306a41086a290300210120052903302107200541206a20032004108e08200541106a200720012005290320200541206a41086a290300108f0820052005290310200541106a41086a290300108e08200541086a2903002104200020052903002002200685220685220220067d3703002000200420068520067d2002200654ad7d370308200541e0006a24000b040020000b1500024020014200520d00108708000b20002001800b1500024020014200520d00108708000b20002001820b0700200120007c0b0700200120007e0b100020002002370308200020013703000b4901017f230041106b22052400024020032004844200520d00108708000b200520012002200320041098082000200541086a29030037030820002005290300370300200541106a24000b1900200042ffffffffffffffffff003703082000427f3703000b19002000428080808080808080807f370308200042003703000b3801017f230041106b22052400200520032004200120021084082000200541086a29030037030820002005290300370300200541106a24000b1d002000200120037d3703002000200220047d2001200354ad7d3703080b6a01017f230041106b22052400024002402003200484500d0020012002428080808080808080807f85844200520d012003200483427f520d010b108708000b20052001200220032004109c082000200541086a29030037030820002005290300370300200541106a24000b040020000b040020010b100020002002370308200020013703000b3c01017f230041106b2205240020052001200220032004109908200529030021012000200541086a29030037030820002001370300200541106a24000b3e01017f230041106b22052400200520012002200320044100109a08200529030021012000200541086a29030037030820002001370300200541106a24000bc00704017f027e027f047e230041d0006b22062400024002400240024002400240024002400240024020012002109608500d002003200410950821072003200410960821082007500d012008500d022003200410960879a72001200210960879a76b2209413f4b0d0341ff0020096b210a200941016a21090c080b024020032004109608500d0020050d040c060b02402005450d002001200210950820032004109508108b08210720054200370308200520073703000b2001200210950820032004109508108a0821010c060b2008500d0302400240024020012002109508500d00200320041096087b4201510d012003200410960879a72001200210960879a76b2209413e4b0d0241ff0020096b210a200941016a21090c090b02402005450d00200642002001200210960820032004109608108b08109708200629030021072005200641086a290300370308200520073703000b2001200210960820032004109608108a0821010c070b02402005450d00200641106a200120021095082001200210960820032004109608427f7c83109708200629031021072005200641186a290300370308200520073703000b20012002109608200320041096087a423f838821010c060b2005450d040c020b0240200320041095087b4201510d0041bf7f2003200410950879a72001200210960879a76b22096b210a200941c1006a21090c060b02402005450d0020012002109508210720032004109508210820054200370308200520072008427f7c833703000b200320041095084201510d06200641c0006a20012002200320041095087aa710a408200641c8006a2903002102200629034021010c060b2005450d020b2005200137030020052002370308420021010c020b108708000b420021010b420021020c010b200641206a20012002200a41ff007110a308200641306a20012002200941ff007110a408200641206a41086a2903002102200641306a41086a290300210b20062903202101200629033021070240024020090d00420021084200210c0c010b4200210c4200210d0340200b4201862007423f888422082008427f8520047c20074201862002423f88842207427f85220820037c200854ad7c423f8722082004837d20072008200383220e54ad7d210b2007200e7d2107420020024201862001423f8884842102200d200142018684210120084201832208210d2009417f6a22090d000b0b02402005450d00200520073703002005200b3703080b200c20024201862001423f8884842102200820014201868421010b2000200137030020002002370308200641d0006a24000b4c01017f230041206b22052400200542003703182005420037031020052001200220032004200541106a109a08200529031021012000200529031837030820002001370300200541206a24000b3c01017f230041106b2205240020052001200220032004108808200529030021012000200541086a29030037030820002001370300200541106a24000b3601017f02402002450d00200021030340200320012d00003a0000200341016a2103200141016a21012002417f6a22020d000b0b20000b7101017f0240024020012000490d002002450d01200021030340200320012d00003a0000200141016a2101200341016a21032002417f6a22020d000c020b0b2002450d002001417f6a21012000417f6a21030340200320026a200120026a2d00003a00002002417f6a22020d000b0b20000b2c01017f02402002450d00200021030340200320013a0000200341016a21032002417f6a22020d000b0b20000b4a01037f4100210302402002450d000240034020002d0000220420012d00002205470d01200041016a2100200141016a21012002417f6a2202450d020c000b0b200420056b21030b20030bac0102017f037e230041206b2204240002400240200341c000710d002003450d01200120021095082105200120021096082106200420052003413f71ad22078620012002109508410020036b413f71ad88200620078684109708200441086a2903002102200429030021010c010b200441106a4200200120021095082003413f71ad86109708200441186a2903002102200429031021010b2000200137030020002002370308200441206a24000b9e0102017f027e230041106b22042400024002400240200341c000710d002003450d02200120021096082105200120021095082003413f71ad2206882005410020036b413f71ad868421052001200210960820068821010c010b200120021096082003413f71ad882105420021010b200420052001109708200441086a2903002102200429030021010b2000200137030020002002370308200441106a24000b3a01017f230041106b22042400200420012002200310a108200429030021012000200441086a29030037030820002001370300200441106a24000b3a01017f230041106b22042400200420012002200310a208200429030021012000200441086a29030037030820002001370300200441106a24000b0bb4b50c0300418080c0000b89b50c6361706163697479206f766572666c6f7700000024001000170000006e020000050000007372632f6c6962616c6c6f632f7261775f7665632e727300cb0010004600000068010000130000004200000004000000040000004300000044000000450000006120666f726d617474696e6720747261697420696d706c656d656e746174696f6e2072657475726e656420616e206572726f720042000000000000000100000046000000b8001000130000004a020000050000007372632f6c6962616c6c6f632f666d742e72732f72757374632f666135316638313065356239323534393034623932363630653732383062376436613436663131322f7372632f6c6962636f72652f666d742f6d6f642e72730000004f0110001600000065011000160000004c131300010000003c01100013000000ca0300000d0000007372632f6c6962616c6c6f632f7665632e7273737761705f72656d6f766520696e6465782028697320292073686f756c64206265203c206c656e202869732000a401100014000000b8011000170000004c131300010000003c01100013000000f10300000d000000696e73657274696f6e20696e6465782028697320292073686f756c64206265203c3d206c656e202869732000f80110001200000065011000160000004c131300010000003c01100013000000210400000d00000072656d6f76616c20696e646578202869732000003402100014000000b8011000170000004c131300010000003c01100013000000330500000d000000656e6420647261696e20696e6465782028697320010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002020202020202020202020202020202020202020202020202020202020203030303030303030303030303030303040404040400000000000000000000006803100020000000880310001200000042000000000000000100000047000000696e646578206f7574206f6620626f756e64733a20746865206c656e20697320206275742074686520696e646578206973203030303130323033303430353036303730383039313031313132313331343135313631373138313932303231323232333234323532363237323832393330333133323333333433353336333733383339343034313432343334343435343634373438343935303531353235333534353535363537353835393630363136323633363436353636363736383639373037313732373337343735373637373738373938303831383238333834383538363837383838393930393139323933393439353936393739383939000074041000060000007a04100022000000696e64657820206f7574206f662072616e676520666f7220736c696365206f66206c656e67746820ac04100016000000c20410000d000000736c69636520696e64657820737461727473206174202062757420656e64732061742000330f100016000000040800002f0000005b2e2e2e5d000000480510000b0000001d0f1000160000008705100001000000fb0e10000e000000090f1000040000000d0f1000100000008705100001000000480510000b00000053051000260000007905100008000000810510000600000087051000010000006279746520696e64657820206973206e6f742061206368617220626f756e646172793b20697420697320696e7369646520202862797465732029206f66206060c605100002000000b0051000160000005604000024000000b0051000160000004c040000110000007372632f6c6962636f72652f666d742f6d6f642e72732e2eda05100016000000540000001400000030787372632f6c6962636f72652f666d742f6e756d2e727300010305050606030706080809110a1c0b190c140d100e0d0f0410031212130916011705180219031a071c021d011f1620032b032c022d0b2e01300331023201a702a902aa04ab08fa02fb05fd04fe03ff09ad78798b8da23057588b8c901c1ddd0e0f4b4cfbfc2e2f3f5c5d5fb5e2848d8e9192a9b1babbc5c6c9cadee4e5ff00041112293134373a3b3d494a5d848e92a9b1b4babbc6cacecfe4e500040d0e11122931343a3b4546494a5e646584919b9dc9cecf0d112945495764658d91a9b4babbc5c9dfe4e5f00d11454964658084b2bcbebfd5d7f0f183858ba4a6bebfc5c7cecfdadb4898bdcdc6cecf494e4f57595e5f898e8fb1b6b7bfc1c6c7d71116175b5cf6f7feff800d6d71dedf0e0f1f6e6f1c1d5f7d7eaeafbbbcfa16171e1f46474e4f585a5c5e7e7fb5c5d4d5dcf0f1f572738f7475962f5f262e2fa7afb7bfc7cfd7df9a409798308f1fc0c1ceff4e4f5a5b07080f10272feeef6e6f373d3f42459091feff536775c8c9d0d1d8d9e7feff00205f2282df048244081b04061181ac0e80ab35280b80e003190801042f043404070301070607110a500f1207550703041c0a090308030703020303030c0405030b06010e15053a0311070605100757070207150d500443032d03010411060f0c3a041d255f206d046a2580c80582b0031a0682fd035907150b1709140c140c6a060a061a0659072b05460a2c040c040103310b2c041a060b0380ac060a06213f4c042d0374083c030f033c0738082b0582ff1118082f112d032010210f808c048297190b158894052f053b07020e180980b32d740c80d61a0c0580ff0580df0cee0d03848d033709815c1480b80880cb2a38030a06380846080c06740b1e035a0459098083181c0a16094c04808a06aba40c170431a10481da26070c050580a511816d1078282a064c04808d0480be031b030f0d0006010103010402080809020a050b020e041001110212051311140115021702190d1c051d0824016a036b02bc02d102d40cd509d602d702da01e005e102e802ee20f004f802f902fa02fb010c273b3e4e4f8f9e9e9f060709363d3e56f3d0d1041418363756577faaaeafbd35e01287898e9e040d0e11122931343a4546494a4e4f64655cb6b71b1c07080a0b141736393aa8a9d8d909379091a8070a3b3e66698f926f5feeef5a629a9b2728559da0a1a3a4a7a8adbabcc4060b0c151d3a3f4551a6a7cccda007191a22253e3fc5c604202325262833383a484a4c50535556585a5c5e606365666b73787d7f8aa4aaafb0c0d0aeaf79cc6e6f935e227b0503042d036603012f2e80821d03310f1c0424091e052b0544040e2a80aa06240424042808340b018090813709160a088098390363080930160521031b05014038044b052f040a070907402027040c0936033a051a07040c07504937330d33072e080a8126524e28082a561c1417094e041e0f430e19070a0648082709750b3f412a063b050a0651060105100305808b621e48080a80a65e22450b0a060d1339070a362c041080c03c64530c48090a46451b4808531d398107460a1d03474937030e080a0639070a81361980b7010f320d839b66750b80c48abc842f8fd18247a1b98239072a040260260a460a28051382b05b654b0439071140050b020e97f80884d62a09a2f7811f3103110408818c89046b050d03090710936080f60a73086e1746809a140c570919808781470385420f1585502b80d52d031a040281703a0501850080d7294c040a04028311444c3d80c23c06010455051b3402810e2c04640c560a80ae381d0d2c040907020e06809a83d8080d030d03740c59070c140c0438080a062808224e81540c15030305070919070709030d072980cb250a840600580b1000200000000a0000001c000000580b1000200000001a000000280000007372632f6c6962636f72652f756e69636f64652f7072696e7461626c652e72730003000083042000910560005d13a0001217a01e0c20e01eef2c202b2a30a02b6fa6602c02a8e02c1efbe02d00fea0359effe035fd016136010aa136240d6137ab0ee1382f182139301c6146f31ea14af06a614e4f6fa14e9dbc214f65d1e14f00da215000e0e15130e16153ece2a154d0e8e15420002e55f001bf55d80e100023000000520000003e00000000700007002d0101010201020101480b30151001650702060202010423011e1b5b0b3a09090118040109010301052b03770f0120370101010408040103070a021d013a0101010204080109010a021a010202390104020402020303011e0203010b0239010405010204011402160601013a0101020104080107030a021e013b0101010c0109012801030139030503010407020b021d013a01020102010301050207020b021c02390201010204080109010a021d0148010401020301010801510102070c08620102090b064a021b0101010101370e01050102050b0124090166040106010202021902040310040d01020206010f01000300031d031d021e02400201070801020b09012d03770222017603040209010603db0202013a010107010101010208060a020130113f0430070101050128090c0220040202010338010102030101033a0802029803010d0107040106010302c63a01050001c32100038d016020000669020004010a200250020001030104011902050197021a120d012608190b2e0330010204020227014306020202020c0108012f01330101030202050201012a020801ee010201040100010010101000020001e201950500030102050428030401a50200040002990bb001360f3803310402024503240501083e010c0234090a0402015f03020101020601a0010308150239020101010116010e070305c308020301011701510102060101020101020102eb010204060201021b025508020101026a0101010206010165030204010500090102f5010a0201010401900402020401200a280602040801090602032e0d010200070106010152160207010201027a060301010201070101480203010101000200053b0700013f0451010002000101030405080802071e0494030037043208010e011605010f000701110207010201050007000400076d07006080f000000000d80e1000230000004b00000028000000d80e10002300000057000000160000007372632f6c6962636f72652f756e69636f64652f756e69636f64655f646174612e7273626567696e203c3d20656e642028203c3d2029207768656e20736c6963696e672060206973206f7574206f6620626f756e6473206f6620607372632f6c6962636f72652f7374722f6d6f642e7273426f72726f774572726f72426f72726f774d75744572726f7270616e69636b6564206174200000990f1000010000009a0f100003000000301a130000000000980f100001000000980f1000010000003a27272c2066616c736574727565202020200000cc0f10001a0000008b01000026000000330f100016000000c30700002f0000007372632f6c6962636f72652f7374722f7061747465726e2e72730000f80f10001b00000052000000050000007372632f6c6962636f72652f736c6963652f6d656d6368722e7273207b202c20207b0a00420000000c0000000400000048000000490000004a0000002c0a00004200000004000000040000004b0000004c0000004d000000207d7d28280a2c0a5d5b0000330f100016000000800700002f000000bb101000260000006672616d655f737570706f72743a3a686173682f686f6d652f6461766964642f6465762f7375627374726174652f6672616d652f737570706f72742f7372632f686173682e7273496e76616c696420726576657273653a2068617368206c656e67746820746f6f2073686f72740000004200000004000000040000004e0000004f000000500000004200000000000000010000005100000052000000530000006d61782d77656967687461637475616c5f7765696768743d42000000000000000100000054000000550000005300000042000000000000000100000054000000550000005300000043616c6c4e6f74416c6c6f77656450687261676d656e426f67757353636f726550687261676d656e426f6775734564676550687261676d656e426f67757353656c66566f746550687261676d656e536c61736865644e6f6d696e6174696f6e50687261676d656e426f6775734e6f6d696e6174696f6e50687261676d656e426f6775734e6f6d696e61746f7250687261676d656e426f677573436f6d7061637450687261676d656e426f67757357696e6e657250687261676d656e426f67757357696e6e6572436f756e74536e617073686f74556e617661696c61626c6550687261676d656e5765616b5375626d697373696f6e50687261676d656e4561726c795375626d697373696f6e416c7265616479436c61696d65644e6f74536f72746564416e64556e69717565496e76616c69644e756d6265724f664e6f6d696e6174696f6e73496e76616c6964457261546f52657761726446756e6465645461726765744e6f556e6c6f636b4368756e6b4e6f4d6f72654368756e6b73496e73756666696369656e7456616c7565496e76616c6964536c617368496e6465784475706c6963617465496e646578456d70747954617267657473416c7265616479506169726564416c7265616479426f6e6465644e6f7453746173684e6f74436f6e74726f6c6c65725761726e696e673a20412073657373696f6e206170706561727320746f2068617665206265656e20736b69707065642e626f6e64626f6e645f6578747261756e626f6e6477697468647261775f756e626f6e64656476616c69646174656e6f6d696e6174656368696c6c7365745f70617965657365745f636f6e74726f6c6c65727365745f76616c696461746f725f636f756e74666f7263655f6e6f5f65726173666f7263655f6e65775f6572617365745f696e76756c6e657261626c6573666f7263655f756e7374616b65666f7263655f6e65775f6572615f616c7761797363616e63656c5f64656665727265645f736c6173687061796f75745f6e6f6d696e61746f727061796f75745f76616c696461746f727061796f75745f7374616b6572737265626f6e647365745f686973746f72795f6465707468726561705f73746173687375626d69745f656c656374696f6e5f736f6c7574696f6e7375626d69745f656c656374696f6e5f736f6c7574696f6e5f756e7369676e6564426f6e6465644c65646765724e6f6d696e61746f727356616c696461746f72536c617368496e4572614e6f6d696e61746f72536c617368496e457261536c617368696e675370616e735370616e536c617368536e617073686f7456616c696461746f7273536e617073686f744e6f6d696e61746f7273457261456c656374696f6e5374617475730000000000a81610000900000000000000b4161000030000000000000000000000cc161000020000000000000000000000dc161000060000000000000084111200020000000000000000000000e4161000010000000000000000000000ec161000050000000000000084111200020000000000000000000000f4161000010000000000000000000000fc1610001a0000000000000008f6120001000000000000000000000018171000020000000000000000000000281710000f000000000000003817100001000000000000000000000040171000010000000000000000000000c0141000060000000000000084111200020000000000000000000000481710000400000000000000000000006817100008000000000000008411120002000000000000000000000070171000010000000000000000000000781710000900000000000000841112000200000000000000000000008417100002000000000000004572615061796f7574000000b51a100008000000f615120007000000f6151200070000002e1a100056000000841a1000310000005265776172640000df1910004f000000536c61736800000096191000490000004f6c64536c617368696e675265706f727444697363617264656400003d1910004700000084191000120000005374616b696e67456c656374696f6e002e1910000f000000ea181000440000002a18100023000000301a1300000000004d18100054000000a118100049000000556e626f6e646564051810002500000057697468647261776e0000009417100057000000eb1710001a00000020416e206163636f756e74206861732063616c6c6564206077697468647261775f756e626f6e6465646020616e642072656d6f76656420756e626f6e64696e67206368756e6b7320776f727468206042616c616e6365602066726f6d2074686520756e6c6f636b696e672071756575652e20416e206163636f756e742068617320756e626f6e646564207468697320616d6f756e742e20416e206163636f756e742068617320626f6e646564207468697320616d6f756e742e204e4f54453a2054686973206576656e74206973206f6e6c7920656d6974746564207768656e2066756e64732061726520626f6e64656420766961206120646973706174636861626c652e204e6f7461626c792c2069742077696c6c206e6f7420626520656d697474656420666f72207374616b696e672072657761726473207768656e20746865792061726520616464656420746f207374616b652e2041206e657720736574206f66207374616b6572732077617320656c656374656420776974682074686520676976656e20636f6d7075746174696f6e206d6574686f642e456c656374696f6e436f6d7075746520416e206f6c6420736c617368696e67207265706f72742066726f6d2061207072696f72206572612077617320646973636172646564206265636175736520697420636f756c64206e6f742062652070726f6365737365642e204f6e652076616c696461746f722028616e6420697473206e6f6d696e61746f72732920686173206265656e20736c61736865642062792074686520676976656e20616d6f756e742e20546865207374616b657220686173206265656e207265776172646564206279207468697320616d6f756e742e20604163636f756e7449646020697320746865207374617368206163636f756e742e2054686520657261207061796f757420686173206265656e207365743b207468652066697273742062616c616e6365206973207468652076616c696461746f722d7061796f75743b20746865207365636f6e64206973207468652072656d61696e6465722066726f6d20746865206d6178696d756d20616d6f756e74206f66207265776172642e457261496e6465785374616b696e674f6666636861696e45726173526577617264506f696e74734572617356616c696461746f7252657761726445726173546f74616c5374616b654572726f723a2073746172745f73657373696f6e5f696e646578206d7573742062652073657420666f722063757272656e745f657261517565756564456c65637465644572617356616c696461746f725072656673457261735374616b657273436c6970706564457261735374616b657273556e6170706c696564536c61736865730000000000731310000400000000000000a01f1000030000000000000000000000e81f1000110000000000000000000000771310000a00000000000000702010000100000000000000000000008820100011000000000000000000000081131000060000000000000010211000010000000000000000000000282110001b0000000000000000000000871310001100000000000000301a13000000000000000000000000000022100013000000000000000000000098131000080000000000000098221000010000000000000000000000b02210000c0000000000000000000000a0131000080000000000000010231000010000000000000000000000282310000d0000000000000000000000a81310000500000000000000301a1300000000000000000000000000902310000c0000000000000000000000ad1310000900000000000000f0231000010000000000000000000000082410000b0000000000000000000000b61310000e0000000000000060241000010000000000000000000000782410000b0000000000000000000000c41310001300000000000000d0241000010000000000000000000000e8241000010000000000000000000000d71310000d00000000000000301a1300000000000000000000000000f0241000050000000000000000000000e41310000d00000000000000301a130000000000000000000000000018251000060000000000000000000000f113100011000000000000004825100001000000000000000000000060251000010000000000000000000000021410000d0000000000000068251000010000000000000000000000802510000100000000000000000000000f1410001400000000000000301a130000000000000000000000000088251000050000000000000000000000231410001500000000000000b0251000020000000000000000000000e025100007000000000000000000000038141000100000000000000018261000020000000000000000000000482610001e00000000000000000000004814100010000000000000003827100001000000000000000000000050271000130000000000000000000000581410000e00000000000000e8271000020000000000000000000000182810000f000000000000000000000066141000060000000000000010211000010000000000000000000000902810000900000000000000000000006c1410001100000000000000d8281000010000000000000000000000f02810000300000000000000000000007d1410000a00000000000000682510000100000000000000000000000829100007000000000000000000000087141000180000000000000040291000040000000000000000000000a02910004a00000000000000000000009f141000210000000000000040291000040000000000000000000000f02b1000050000000000000000000000674810000a00000000000000f32012002300000000000000aa4d12000500000000000000807512001500000000000000f44810000500000000000000f94810001100000038531000590000009153100021000000301a130000000000b25310004c000000301a130000000000fe53100049000000301a1300000000001a53100010000000301a130000000000f5bd12000b000000475410003500000085201200080000007c5410001a000000301a1300000000009654100054000000ea5410005000000044be12000c000000000000002a5310000e0000000000000080751200150000005e51100059000000b75110000d000000301a130000000000c45110005400000018521000590000007152100013000000301a1300000000008452100058000000dc5210003e000000301a1300000000001a53100010000000301a130000000000f5bd12000b000000d54710003a0000008520120008000000ee8811001000000044be12000c00000000000000aa4d1200050000000000000080751200150000006f4d100055000000c44d100040000000044e100049000000301a1300000000004d4e1000520000009f4e100030000000301a130000000000cf4e10004f0000001e4f10004f0000006d4f10003f000000301a1300000000009f481000550000003c49100043000000301a130000000000ac4f100012000000301a130000000000be4f100026000000301a130000000000f5bd12000b000000e44f1000500000000f4810002600000034501000590000008d5010005c000000e9501000540000003d51100017000000ee88110010000000545110000a000000554b10004b000000301a130000000000a04b10004d000000ed4b100013000000301a1300000000009f481000550000003c49100043000000301a130000000000004c100013000000301a130000000000134c10001b000000301a130000000000f5bd12000b0000002e4c100055000000834c100051000000d44c10003d000000114d10005e000000354810003200000044be12000c00000000000000424b10000500000000000000474b10000e000000084b10003a000000301a1300000000004947100037000000301a1300000000009f481000550000003c49100043000000301a130000000000f5bd12000b000000d54710003a0000000f48100026000000354810003200000044be12000c00000000000000d94a10000700000000000000e04a1000280000009449100044000000301a130000000000d849100054000000233b100023000000301a1300000000009f481000550000003c49100043000000301a130000000000f5bd12000b0000002c4a100049000000754a10002e000000a34a10003600000044be12000c0000000a49100032000000301a1300000000004947100037000000301a1300000000009f481000550000003c49100043000000301a130000000000f5bd12000b000000d54710003a0000007f49100015000000354810003200000044be12000c00000000000000f44810000500000000000000f948100011000000714810002e000000301a1300000000004947100037000000301a1300000000009f48100055000000301a130000000000f5bd12000b000000d54710003a0000000f48100026000000354810003200000044be12000c00000000000000674810000a00000000000000f3201200230000002547100024000000301a1300000000004947100037000000301a1300000000008047100055000000301a130000000000f5bd12000b000000d54710003a0000000f48100026000000354810003200000044be12000c00000000000000842112000300000000000000194710000c000000f946100020000000cd4610002c000000301a130000000000f5bd12000b000000bd4610001000000044be12000c00000042461000530000009546100028000000301a130000000000f5bd12000b000000bd4610001000000044be12000c00000000000000804410000a00000000000000ddce1200110000000f46100033000000000000000a46100005000000000000007ac312000c000000c7451000430000007245100041000000301a130000000000f5bd12000b000000b34510001400000044be12000c00000000000000093910000300000000000000b51a10000800000000000000654510000d00000000000000c499120008000000a244100051000000f34410001c0000000f45100041000000301a130000000000f5bd12000b000000504510001500000044be12000c00000000000000093910000300000000000000b51a10000800000000000000804410000a000000000000008a44100018000000f03d100058000000483e1000570000009f3e100031000000301a130000000000ac40100029000000301a130000000000d54010003f000000383f100059000000913f10004c00000014411000560000006a41100049000000b341100022000000d54110004200000017421000480000005f42100028000000301a130000000000dd3f100057000000344010000e000000301a1300000000004240100051000000301a130000000000f5bd12000b0000008742100057000000de42100027000000054310004e00000053431000370000008a43100050000000da431000520000002c4410005400000044be12000c00000000000000093910000300000000000000b51a100008000000f03d100058000000483e1000570000009f3e100031000000301a130000000000d03e100029000000301a130000000000f93e10003f000000383f100059000000913f10004c000000301a130000000000dd3f100057000000344010000e000000301a1300000000004240100051000000301a130000000000f5bd12000b00000093401000190000009f9510003100000044be12000c00000000000000e13d10000f000000000000007ac312000c00000000000000093910000300000000000000b51a100008000000bf3b100044000000301a130000000000033c100053000000563c10004a000000a03c10004d000000301a130000000000ed3c100056000000433d10001e000000301a130000000000613d100040000000301a130000000000f5bd12000b000000a13d1000400000009f9510003100000044be12000c000000963a100038000000301a130000000000ce3a100055000000233b100023000000301a130000000000f5bd12000b000000463b10003c000000823b10003d00000044be12000c00000000000000743a10001100000000000000853a100011000000463a100019000000301a1300000000005f3a1000150000000c3910004e0000005a39100058000000b239100030000000301a130000000000e239100024000000301a130000000000063a10004000000000000000b83810000700000000000000bf3810001300000000000000d23810001300000000000000e53810001200000000000000f73810000500000000000000fc3810000d00000000000000093910000300000000000000b51a100008000000112d100038000000301a130000000000492d10000d000000562d100045000000301a1300000000009b2d100021000000301a130000000000bc2d10002b000000301a130000000000e72d10003d000000242e100054000000782e10000c000000301a130000000000842e10004a000000301a130000000000ce2e10002a000000301a130000000000f82e100032000000301a1300000000002a2f1000530000007d2f100047000000c42f10004c00000010301000540000006430100058000000bc30100026000000301a130000000000e230100018000000301a130000000000fa30100039000000333110003e000000713110002b0000009c31100055000000f131100057000000483210001000000058321000430000009b3210001b000000301a130000000000b632100030000000301a130000000000e6321000590000003f331000590000009833100050000000e833100027000000301a130000000000f5bd12000b0000000f341000590000006834100039000000301a130000000000a134100059000000fa34100052000000301a1300000000004c35100038000000301a1300000000008435100027000000ab35100026000000d135100027000000f835100037000000301a1300000000002f36100045000000743610003f000000b336100042000000f536100045000000301a1300000000003a3710004f000000893710005a000000301a130000000000e3371000230000000638100022000000301a130000000000283810002b0000005338100027000000301a1300000000007a3810003e00000044be12000c000000182c100030000000301a130000000000482c1000570000009f2c100058000000f72c10001a00000020556e7369676e65642076657273696f6e206f6620607375626d69745f656c656374696f6e5f736f6c7574696f6e602e204e6f746520746861742074686973206d757374207061737320746865205b6056616c6964617465556e7369676e6564605d20636865636b207768696368206f6e6c7920616c6c6f7773207472616e73616374696f6e732066726f6d20746865206c6f63616c206e6f646520746f20626520696e636c756465642e20496e206f7468657220776f7264732c206f6e6c792074686520626c6f636b20617574686f722063616e20696e636c7564652061207472616e73616374696f6e20696e2074686520626c6f636b2e205375626d697420612070687261676d656e20726573756c7420746f2074686520636861696e2e2049662074686520736f6c7574696f6e3a20312e2069732076616c69642e20322e206861732061206265747465722073636f7265207468616e206120706f74656e7469616c6c79206578697374696e6720736f6c7574696f6e206f6e20636861696e2e207468656e2c2069742077696c6c206265205f7075745f206f6e20636861696e2e204120736f6c7574696f6e20636f6e7369737473206f662074776f20706965636573206f6620646174613a20312e206077696e6e657273603a206120666c617420766563746f72206f6620616c6c207468652077696e6e657273206f662074686520726f756e642e20322e206061737369676e6d656e7473603a2074686520636f6d706163742076657273696f6e206f6620616e2061737369676e6d656e7420766563746f72207468617420656e636f64657320746865206564676520202020776569676874732e20426f7468206f66207768696368206d617920626520636f6d7075746564207573696e67205b6070687261676d656e605d2c206f7220616e79206f7468657220616c676f726974686d2e204164646974696f6e616c6c792c20746865207375626d6974746572206d7573742070726f766964653a202d20546865206073636f7265602074686174207468657920636c61696d20746865697220736f6c7574696f6e206861732e20426f74682076616c696461746f727320616e64206e6f6d696e61746f72732077696c6c20626520726570726573656e74656420627920696e646963657320696e2074686520736f6c7574696f6e2e2054686520696e64696365732073686f756c6420726573706563742074686520636f72726573706f6e64696e6720747970657320285b6056616c696461746f72496e646578605d20616e64205b604e6f6d696e61746f72496e646578605d292e204d6f72656f7665722c20746865792073686f756c642062652076616c6964207768656e207573656420746f20696e64657820696e746f205b60536e617073686f7456616c696461746f7273605d20616e64205b60536e617073686f744e6f6d696e61746f7273605d2e20416e7920696e76616c696420696e6465782077696c6c2063617573652074686520736f6c7574696f6e20746f2062652072656a65637465642e2054686573652074776f2073746f72616765206974656d73206172652073657420647572696e672074686520656c656374696f6e2077696e646f7720616e64206d6179206265207573656420746f2064657465726d696e652074686520696e64696365732e204120736f6c7574696f6e2069732076616c69642069663a20302e204974206973207375626d6974746564207768656e205b60457261456c656374696f6e537461747573605d20697320604f70656e602e20312e2049747320636c61696d65642073636f726520697320657175616c20746f207468652073636f726520636f6d7075746564206f6e2d636861696e2e20322e2050726573656e74732074686520636f7272656374206e756d626572206f662077696e6e6572732e20332e20416c6c20696e6465786573206d7573742062652076616c7565206163636f7264696e6720746f2074686520736e617073686f7420766563746f72732e20416c6c20656467652076616c756573206d75737420202020616c736f20626520636f727265637420616e642073686f756c64206e6f74206f766572666c6f7720746865206772616e756c6172697479206f662074686520726174696f20747970652028692e652e20323536202020206f722062696c6c696f6e292e20342e20466f72206561636820656467652c20616c6c2074617267657473206172652061637475616c6c79206e6f6d696e617465642062792074686520766f7465722e20352e2048617320636f72726563742073656c662d766f7465732e204120736f6c7574696f6e732073636f726520697320636f6e736973746564206f66203320706172616d65746572733a20312e20606d696e207b20737570706f72742e746f74616c207d6020666f72206561636820737570706f7274206f6620612077696e6e65722e20546869732076616c75652073686f756c64206265206d6178696d697a65642e20322e206073756d207b20737570706f72742e746f74616c207d6020666f72206561636820737570706f7274206f6620612077696e6e65722e20546869732076616c75652073686f756c64206265206d696e696d697a65642e20332e206073756d207b20737570706f72742e746f74616c5e32207d6020666f72206561636820737570706f7274206f6620612077696e6e65722e20546869732076616c75652073686f756c64206265202020206d696e696d697a65642028746f20656e73757265206c6573732076617269616e63652920453a206e756d626572206f662065646765732e206d3a2073697a65206f662077696e6e657220636f6d6d69747465652e206e3a206e756d626572206f66206e6f6d696e61746f72732e20643a2065646765206465677265652028313620666f72206e6f772920763a206e756d626572206f66206f6e2d636861696e2076616c696461746f722063616e646964617465732e204e4f54453a20676976656e206120736f6c7574696f6e20776869636820697320726564756365642c2077652063616e20656e61626c652061206e657720636865636b2074686520656e7375726520607c457c203c206e202b206d602e20576520646f6e277420646f2074686973205f7965745f2c20627574206f7572206f6666636861696e20776f726b657220636f6465206578656375746573206974206e6f6e657468656c6573732e206d616a6f722073746570732028616c6c20646f6e6520696e2060636865636b5f616e645f7265706c6163655f736f6c7574696f6e60293a202d2053746f726167653a204f28312920726561642060456c656374696f6e537461747573602e202d2053746f726167653a204f2831292072656164206050687261676d656e53636f7265602e202d2053746f726167653a204f2831292072656164206056616c696461746f72436f756e74602e202d2053746f726167653a204f283129206c656e67746820726561642066726f6d2060536e617073686f7456616c696461746f7273602e202d2053746f726167653a204f287629207265616473206f6620604163636f756e7449646020746f2066657463682060736e617073686f745f76616c696461746f7273602e202d204d656d6f72793a204f286d2920697465726174696f6e7320746f206d61702077696e6e657220696e64657820746f2076616c696461746f722069642e202d2053746f726167653a204f286e2920726561647320604163636f756e7449646020746f2066657463682060736e617073686f745f6e6f6d696e61746f7273602e202d204d656d6f72793a204f286e202b206d2920726561647320746f206d617020696e64657820746f20604163636f756e7449646020666f7220756e2d636f6d706163742e202d2053746f726167653a204f286529206163636f756e7469642072656164732066726f6d20604e6f6d696e6174696f6e6020746f207265616420636f7272656374206e6f6d696e6174696f6e732e202d2053746f726167653a204f2865292063616c6c7320696e746f2060736c61736861626c655f62616c616e63655f6f665f766f74655f7765696768746020746f20636f6e7665727420726174696f20746f207374616b65642e202d204d656d6f72793a206275696c645f737570706f72745f6d61702e204f2865292e202d204d656d6f72793a206576616c756174655f737570706f72743a204f2845292e202d2053746f726167653a204f2865292077726974657320746f2060517565756564456c6563746564602e202d2053746f726167653a204f28312920777269746520746f206051756575656453636f7265602054686520776569676874206f6620746869732063616c6c20697320312f31307468206f662074686520626c6f636b7320746f74616c207765696768742e77696e6e6572735665633c56616c696461746f72496e6465783e636f6d706163745f61737369676e6d656e7473436f6d7061637441737369676e6d656e747373636f726550687261676d656e53636f72656572612052656d6f766520616c6c20646174612073747275637475726520636f6e6365726e696e672061207374616b65722f7374617368206f6e6365206974732062616c616e6365206973207a65726f2e205468697320697320657373656e7469616c6c79206571756976616c656e7420746f206077697468647261775f756e626f6e64656460206578636570742069742063616e2062652063616c6c656420627920616e796f6e6520616e6420746865207461726765742060737461736860206d7573742068617665206e6f2066756e6473206c6566742e20546869732063616e2062652063616c6c65642066726f6d20616e79206f726967696e2e202d20607374617368603a20546865207374617368206163636f756e7420746f20726561702e204974732062616c616e6365206d757374206265207a65726f2e2053657420686973746f72795f64657074682076616c75652e204f726967696e206d75737420626520726f6f742e6e65775f686973746f72795f6465707468436f6d706163743c457261496e6465783e205265626f6e64206120706f7274696f6e206f6620746865207374617368207363686564756c656420746f20626520756e6c6f636b65642e20546865206469737061746368206f726967696e206d757374206265207369676e65642062792074686520636f6e74726f6c6c65722c20616e642069742063616e206265206f6e6c792063616c6c6564207768656e205b60457261456c656374696f6e537461747573605d2069732060436c6f736564602e202d2054696d6520636f6d706c65786974793a204f2831292e20426f756e64656420627920604d41585f554e4c4f434b494e475f4348554e4b53602e202d2053746f72616765206368616e6765733a2043616e277420696e6372656173652073746f726167652c206f6e6c792064656372656173652069742e20506179206f757420616c6c20746865207374616b65727320626568696e6420612073696e676c652076616c696461746f7220666f7220612073696e676c65206572612e202d206076616c696461746f725f73746173686020697320746865207374617368206163636f756e74206f66207468652076616c696461746f722e205468656972206e6f6d696e61746f72732c20757020746f20202060543a3a4d61784e6f6d696e61746f72526577617264656450657256616c696461746f72602c2077696c6c20616c736f207265636569766520746865697220726577617264732e202d206065726160206d617920626520616e7920657261206265747765656e20605b63757272656e745f657261202d20686973746f72795f64657074683b2063757272656e745f6572615d602e20546865206f726967696e206f6620746869732063616c6c206d757374206265205f5369676e65645f2e20416e79206163636f756e742063616e2063616c6c20746869732066756e6374696f6e2c206576656e206966206974206973206e6f74206f6e65206f6620746865207374616b6572732e20546869732063616e206f6e6c792062652063616c6c6564207768656e205b60457261456c656374696f6e537461747573605d2069732060436c6f736564602e202d2054696d6520636f6d706c65786974793a206174206d6f7374204f284d61784e6f6d696e61746f72526577617264656450657256616c696461746f72292e76616c696461746f725f7374617368202a2a546869732065787472696e7369632077696c6c2062652072656d6f76656420616674657220604d6967726174696f6e457261202b20486973746f727944657074686020686173207061737365642c20676976696e67206f70706f7274756e69747920666f7220757365727320746f20636c61696d20616c6c2072657761726473206265666f7265206d6f76696e6720746f2053696d706c65205061796f7574732e20416674657220746869732074696d652c20796f752073686f756c642075736520607061796f75745f7374616b6572736020696e73746561642e2a2a204d616b65206f6e652076616c696461746f722773207061796f757420666f72206f6e65206572612e202d206077686f602069732074686520636f6e74726f6c6c6572206163636f756e74206f66207468652076616c696461746f7220746f20706179206f75742e202d206065726160206d6179206e6f74206265206c6f776572207468616e206f6e6520666f6c6c6f77696e6720746865206d6f737420726563656e746c792070616964206572612e204966206974206973206869676865722c2020207468656e20697420696e6469636174657320616e20696e737472756374696f6e20746f20736b697020746865207061796f7574206f6620616c6c2070726576696f757320657261732e205741524e494e473a206f6e636520616e2065726120697320706179656420666f7220612076616c696461746f7220737563682076616c696461746f722063616e277420636c61696d20746865207061796f7574206f662070726576696f7573206572612e205741524e494e473a20496e636f727265637420617267756d656e747320686572652063616e20726573756c7420696e206c6f7373206f66207061796f75742e2042652076657279206361726566756c2e202d2054696d6520636f6d706c65786974793a204f2831292e204d616b65206f6e65206e6f6d696e61746f722773207061796f757420666f72206f6e65206572612e202d206077686f602069732074686520636f6e74726f6c6c6572206163636f756e74206f6620746865206e6f6d696e61746f7220746f20706179206f75742e202d206076616c696461746f72736020697320746865206c697374206f6620616c6c2076616c696461746f72732074686174206077686f6020686164206578706f7375726520746f20647572696e672060657261602c202020616c6f6e67736964652074686520696e646578206f66206077686f6020696e2074686520636c6970706564206578706f73757265206f66207468652076616c696461746f722e202020492e652e206561636820656c656d656e742069732061207475706c65206f66202020602876616c696461746f722c20696e646578206f66206077686f6020696e20636c6970706564206578706f73757265206f662076616c696461746f7229602e202020496620697420697320696e636f6d706c6574652c207468656e206c657373207468616e207468652066756c6c207265776172642077696c6c2062652070616964206f75742e2020204974206d757374206e6f742065786365656420604d41585f4e4f4d494e4154494f4e53602e202d204e756d626572206f662073746f726167652072656164206f6620604f2876616c696461746f727329603b206076616c696461746f7273602069732074686520617267756d656e74206f66207468652063616c6c2c202020616e6420697320626f756e64656420627920604d41585f4e4f4d494e4154494f4e53602e202d20456163682073746f72616765207265616420697320604f284e29602073697a6520616e64206465636f646520636f6d706c65786974793b20604e602069732074686520206d6178696d756d2020206e6f6d696e6174696f6e7320746861742063616e20626520676976656e20746f20612073696e676c652076616c696461746f722e202d20436f6d7075746174696f6e20636f6d706c65786974793a20604f284d41585f4e4f4d494e4154494f4e53202a206c6f674e29603b20604d41585f4e4f4d494e4154494f4e5360206973207468652020206d6178696d756d206e756d626572206f662076616c696461746f72732074686174206d6179206265206e6f6d696e6174656420627920612073696e676c65206e6f6d696e61746f722c206974206973202020626f756e646564206f6e6c792065636f6e6f6d6963616c6c792028616c6c206e6f6d696e61746f72732061726520726571756972656420746f20706c6163652061206d696e696d756d207374616b65292e76616c696461746f72735665633c28543a3a4163636f756e7449642c20753332293e2043616e63656c20656e6163746d656e74206f66206120646566657272656420736c6173682e2043616e2062652063616c6c6564206279206569746865722074686520726f6f74206f726967696e206f72207468652060543a3a536c61736843616e63656c4f726967696e602e2070617373696e67207468652065726120616e6420696e6469636573206f662074686520736c617368657320666f7220746861742065726120746f206b696c6c2e202d204f6e652073746f726167652077726974652e736c6173685f696e646963657320466f72636520746865726520746f2062652061206e6577206572612061742074686520656e64206f662073657373696f6e7320696e646566696e6974656c792e202d204f6e652073746f7261676520777269746520466f72636520612063757272656e74207374616b657220746f206265636f6d6520636f6d706c6574656c7920756e7374616b65642c20696d6d6564696174656c792e737461736820536574207468652076616c696461746f72732077686f2063616e6e6f7420626520736c61736865642028696620616e79292e20466f72636520746865726520746f2062652061206e6577206572612061742074686520656e64206f6620746865206e6578742073657373696f6e2e20416674657220746869732c2069742077696c6c20626520726573657420746f206e6f726d616c20286e6f6e2d666f7263656429206265686176696f75722e202d204e6f20617267756d656e74732e20466f72636520746865726520746f206265206e6f206e6577206572617320696e646566696e6974656c792e2054686520696465616c206e756d626572206f662076616c696461746f72732e436f6d706163743c7533323e202852652d297365742074686520636f6e74726f6c6c6572206f6620612073746173682e20456666656374732077696c6c2062652066656c742061742074686520626567696e6e696e67206f6620746865206e657874206572612e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f206279207468652073746173682c206e6f742074686520636f6e74726f6c6c65722e202d20496e646570656e64656e74206f662074686520617267756d656e74732e20496e7369676e69666963616e7420636f6d706c65786974792e202d20436f6e7461696e732061206c696d69746564206e756d626572206f662072656164732e202d2057726974657320617265206c696d6974656420746f2074686520606f726967696e60206163636f756e74206b65792e636f6e74726f6c6c6572202852652d2973657420746865207061796d656e742074617267657420666f72206120636f6e74726f6c6c65722e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f2062792074686520636f6e74726f6c6c65722c206e6f74207468652073746173682e706179656552657761726444657374696e6174696f6e204465636c617265206e6f2064657369726520746f206569746865722076616c6964617465206f72206e6f6d696e6174652e20416e642c2069742063616e206265206f6e6c792063616c6c6564207768656e205b60457261456c656374696f6e537461747573605d2069732060436c6f736564602e202d20436f6e7461696e73206f6e6520726561642e204465636c617265207468652064657369726520746f206e6f6d696e6174652060746172676574736020666f7220746865206f726967696e20636f6e74726f6c6c65722e20456666656374732077696c6c2062652066656c742061742074686520626567696e6e696e67206f6620746865206e657874206572612e20546869732063616e206f6e6c792062652063616c6c6564207768656e202d20546865207472616e73616374696f6e277320636f6d706c65786974792069732070726f706f7274696f6e616c20746f207468652073697a65206f66206074617267657473602c2077686963682069732063617070656420617420436f6d7061637441737369676e6d656e74733a3a4c494d49542e202d20426f74682074686520726561647320616e642077726974657320666f6c6c6f7720612073696d696c6172207061747465726e2e746172676574735665633c3c543a3a4c6f6f6b7570206173205374617469634c6f6f6b75703e3a3a536f757263653e204465636c617265207468652064657369726520746f2076616c696461746520666f7220746865206f726967696e20636f6e74726f6c6c65722e707265667356616c696461746f7250726566732052656d6f766520616e7920756e6c6f636b6564206368756e6b732066726f6d207468652060756e6c6f636b696e67602071756575652066726f6d206f7572206d616e6167656d656e742e205468697320657373656e7469616c6c7920667265657320757020746861742062616c616e636520746f206265207573656420627920746865207374617368206163636f756e7420746f20646f2077686174657665722069742077616e74732e20456d697473206057697468647261776e602e2053656520616c736f205b6043616c6c3a3a756e626f6e64605d2e202d20436f756c6420626520646570656e64656e74206f6e2074686520606f726967696e6020617267756d656e7420616e6420686f77206d7563682060756e6c6f636b696e6760206368756e6b732065786973742e2020497420696d706c6965732060636f6e736f6c69646174655f756e6c6f636b656460207768696368206c6f6f7073206f76657220604c65646765722e756e6c6f636b696e67602c2077686963682069732020696e6469726563746c7920757365722d636f6e74726f6c6c65642e20536565205b60756e626f6e64605d20666f72206d6f72652064657461696c2e202d20436f6e7461696e732061206c696d69746564206e756d626572206f662072656164732c20796574207468652073697a65206f6620776869636820636f756c64206265206c61726765206261736564206f6e20606c6564676572602e205363686564756c65206120706f7274696f6e206f662074686520737461736820746f20626520756e6c6f636b656420726561647920666f72207472616e73666572206f75742061667465722074686520626f6e6420706572696f6420656e64732e2049662074686973206c656176657320616e20616d6f756e74206163746976656c7920626f6e646564206c657373207468616e20543a3a43757272656e63793a3a6d696e696d756d5f62616c616e636528292c207468656e20697420697320696e6372656173656420746f207468652066756c6c20616d6f756e742e204f6e63652074686520756e6c6f636b20706572696f6420697320646f6e652c20796f752063616e2063616c6c206077697468647261775f756e626f6e6465646020746f2061637475616c6c79206d6f7665207468652066756e6473206f7574206f66206d616e6167656d656e7420726561647920666f72207472616e736665722e204e6f206d6f7265207468616e2061206c696d69746564206e756d626572206f6620756e6c6f636b696e67206368756e6b73202873656520604d41585f554e4c4f434b494e475f4348554e4b5360292063616e20636f2d657869737473206174207468652073616d652074696d652e20496e207468617420636173652c205b6043616c6c3a3a77697468647261775f756e626f6e646564605d206e65656420746f2062652063616c6c656420666972737420746f2072656d6f766520736f6d65206f6620746865206368756e6b732028696620706f737369626c65292e20456d6974732060556e626f6e646564602e2053656520616c736f205b6043616c6c3a3a77697468647261775f756e626f6e646564605d2e202d20496e646570656e64656e74206f662074686520617267756d656e74732e204c696d697465642062757420706f74656e7469616c6c79206578706c6f697461626c6520636f6d706c65786974792e202d20456163682063616c6c20287265717569726573207468652072656d61696e646572206f662074686520626f6e6465642062616c616e636520746f2062652061626f766520606d696e696d756d5f62616c616e6365602920202077696c6c2063617573652061206e657720656e74727920746f20626520696e73657274656420696e746f206120766563746f722028604c65646765722e756e6c6f636b696e676029206b65707420696e2073746f726167652e202020546865206f6e6c792077617920746f20636c65616e207468652061666f72656d656e74696f6e65642073746f72616765206974656d20697320616c736f20757365722d636f6e74726f6c6c6564207669612020206077697468647261775f756e626f6e646564602e203c2f7765696768743e2041646420736f6d6520657874726120616d6f756e742074686174206861766520617070656172656420696e207468652073746173682060667265655f62616c616e63656020696e746f207468652062616c616e636520757020666f72207374616b696e672e20557365207468697320696620746865726520617265206164646974696f6e616c2066756e647320696e20796f7572207374617368206163636f756e74207468617420796f75207769736820746f20626f6e642e20556e6c696b65205b60626f6e64605d206f72205b60756e626f6e64605d20746869732066756e6374696f6e20646f6573206e6f7420696d706f736520616e79206c696d69746174696f6e206f6e2074686520616d6f756e7420746861742063616e2062652061646465642e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f206279207468652073746173682c206e6f742074686520636f6e74726f6c6c657220616e642069742063616e206265206f6e6c792063616c6c6564207768656e205b60457261456c656374696f6e537461747573605d2069732060436c6f736564602e20456d6974732060426f6e646564602e6d61785f6164646974696f6e616c2054616b6520746865206f726967696e206163636f756e74206173206120737461736820616e64206c6f636b207570206076616c756560206f66206974732062616c616e63652e2060636f6e74726f6c6c6572602077696c6c20626520746865206163636f756e74207468617420636f6e74726f6c732069742e206076616c756560206d757374206265206d6f7265207468616e2074686520606d696e696d756d5f62616c616e636560207370656369666965642062792060543a3a43757272656e6379602e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20627920746865207374617368206163636f756e742e202d20496e646570656e64656e74206f662074686520617267756d656e74732e204d6f64657261746520636f6d706c65786974792e202d20546872656520657874726120444220656e74726965732e204e4f54453a2054776f206f66207468652073746f726167652077726974657320286053656c663a3a626f6e646564602c206053656c663a3a7061796565602920617265205f6e657665725f20636c65616e656420756e6c6573732074686520606f726967696e602066616c6c732062656c6f77205f6578697374656e7469616c206465706f7369745f20616e6420676574732072656d6f76656420617320647573742e000000000000b5f612000c000000000000000000000060dc12000300000000000000000000000000000000000000000000000000000000000000301a13009c6110000000000000000000ac61100007000000000000000100000000000000c1f612000e000000000000000000000060dc12000300000000000000000000000000000000000000000000000000000000000000301a1300e46110000000000000000000f461100001000000000000000100000000000000cff6120015000000000000000000000060dc12000300000000000000000000000000000000000000000000000000000000000000301a1300fc61100000000000000000000c62100001000000000000000100000000000000146210000d0000000000000000000000ddce12001100000000000000000000000000000000000000000000000000000000000000301a13002462100000000000000000003462100003000000000000000100000000000000c01410000600000001050000000000007ac312000c000000000000007ac312000c00000000000000000000000000000000000000301a13002067100000000000000000004c62100001000000000000000000000000000000c61410000600000001020000000000007ac312000c00000000000000546210002900000000000000000000000000000000000000301a13002067100000000000000000008062100001000000000000000000000000000000886210000500000001050000000000007ac312000c00000000000000f94810001100000000000000000000000000000000000000301a1300906210000000000000000000a062100001000000000000000100000000000000f38912000a00000001050000000000007ac312000c00000000000000474b10000e00000000000000000000000000000000000000301a1300086410000000000000000000a862100001000000000000000100000000000000cc1410000a00000001050000000000007ac312000c00000000000000b06210001900000000000000000000000000000000000000301a1300cc6210000000000000000000dc62100001000000000000000000000000000000e4f612000a0000000000000000000000b51a10000800000000000000000000000000000000000000000000000000000000000000301a1300c86710000000000000000000e462100004000000000000000000000000000000eef61200090000000000000000000000046310000d00000000000000000000000000000000000000000000000000000000000000301a13001463100000000000000000002463100004000000000000000000000000000000fef61200150000000105000000000000b51a1000080000000000000097f612000c00000000000000000000000000000000000000301a1300c867100000000000000000004463100001000000000000000000000000000000641b10000b0000000205050000000000b51a100008000000000000007ac312000c000000000000004c6310002400000000000000301a1300a063100000000000000000007063100006000000000000000100000000000000521b1000120000000205050000000000b51a100008000000000000007ac312000c000000000000004c6310002400000000000000301a1300a06310000000000000000000b06310000b000000000000000100000000000000401b1000120000000205050000000000b51a100008000000000000007ac312000c00000000000000474b10000e00000000000000301a13000864100000000000000000001864100005000000000000000100000000000000dc1a1000130000000105000000000000b51a10000800000000000000b66c12000c00000000000000000000000000000000000000301a1300f465100000000000000000004064100003000000000000000000000000000000cc1a1000100000000105000000000000b51a10000800000000000000586410001d00000000000000000000000000000000000000301a13007864100000000000000000008864100002000000000000000100000000000000ef1a10000e0000000105000000000000b51a10000800000000000000b66c12000c00000000000000000000000000000000000000301a1300046510000000000000000000986410000200000000000000010000000000000013f71200080000000000000000000000a86410000700000000000000000000000000000000000000000000000000000000000000301a1300b06410000000000000000000c0641000010000000000000001000000000000001bf712001300000000000000000000007df111000700000000000000000000000000000000000000000000000000000000000000301a1300c86410000000000000000000d864100003000000000000000100000000000000f0641000130000000000000000000000b66c12000c00000000000000000000000000000000000000000000000000000000000000301a130004651000000000000000000014651000020000000000000001000000000000006f1b1000100000000105000000000000b51a10000800000000000000246510002f00000000000000000000000000000000000000301a130054651000000000000000000064651000010000000000000001000000000000002ef712000a00000000000000000000006c6510001d00000000000000000000000000000000000000000000000000000000000000301a13008c65100000000000000000009c65100004000000000000000100000000000000d6141000130000000205050000000000b51a100008000000000000007ac312000c00000000000000bc6510001700000000000000301a1300d46510000000000000000000e465100002000000000000000000000000000000e9141000130000000205050000000000b51a100008000000000000007ac312000c00000000000000b66c12000c00000000000000301a1300f465100000000000000000000466100001000000000000000000000000000000fc1410000d00000001050000000000007ac312000c000000000000000c6610001700000000000000000000000000000000000000301a13002466100000000000000000003466100001000000000000000000000000000000091510000900000001050000000000003c66100023000000000000005f6610002200000000000000000000000000000000000000301a1300846610000000000000000000946610000200000000000000010000000000000038f71200160000000000000000000000b51a10000800000000000000000000000000000000000000000000000000000000000000301a1300c86710000000000000000000a46610000100000000000000000000000000000012151000120000000000000000000000ddce12001100000000000000000000000000000000000000000000000000000000000000301a1300bc6610000000000000000000ac6610000200000000000000000000000000000024151000120000000000000000000000ddce12001100000000000000000000000000000000000000000000000000000000000000301a1300bc6610000000000000000000cc66100002000000000000000000000000000000331b10000d0000000000000000000000dc6610002a00000000000000000000000000000000000000000000000000000000000000301a130020671000000000000000000008671000030000000000000000000000000000004ef712000b0000000000000000000000fc3810000d00000000000000000000000000000000000000000000000000000000000000301a1300206710000000000000000000306710000100000000000000000000000000000036151000110000000000000000000000386710001e00000000000000000000000000000000000000000000000000000000000000301a1300586710000000000000000000686710000200000000000000010000000000000059f71200150000000000000000000000a1f512000400000000000000000000000000000000000000000000000000000000000000301a130078671000000000000000000088671000020000000000000001000000000000005c9d10000e00000000000000000000006a9d10000800000000000000000000000000000000000000000000000000000000000000301a1300986710000000000000000000a8671000040000000000000001000000000000006ef712000a0000000000000000000000b51a10000800000000000000000000000000000000000000000000000000000000000000301a1300c86710000000000000000000d8671000010000000000000000000000420000000000000001000000560000004b77100023000000301a1300000000006e7710004e000000301a130000000000bc77100043000000ff7710002b0000002a7810004400000042000000000000000100000057000000217710002a00000042000000000000000100000058000000d176100050000000496e76756c6e657261626c657300000042000000000000000100000059000000fd751000560000005376100053000000a67610002b000000bd751000400000005374616b696e674c65646765723c543a3a4163636f756e7449642c2042616c616e63654f663c543e3e0000006c7510005100000050617965650000004200000000000000010000005a0000003375100039000000e2741000510000004e6f6d696e6174696f6e733c543a3a4163636f756e7449643e0000004200000000000000010000005b0000008974100059000000f973100017000000301a13000000000010741000590000006974100020000000416374697665457261496e666f0000004200000000000000010000005b0000004a73100036000000301a130000000000807310002e000000ae7310004b000000fe7210004c0000004578706f737572653c543a3a4163636f756e7449642c2042616c616e63654f663c543e3ee07210001e000000301a1300000000008070100058000000301a130000000000d87010002a00000090721000500000004200000000000000010000005c0000000271100026000000301a13000000000028711000560000007e71100037000000b571100047000000fc7110003d000000301a1300000000003972100057000000301a130000000000d87010002a00000090721000500000004200000000000000010000005d0000003c70100044000000301a1300000000008070100058000000301a130000000000d87010002a000000b26f100042000000301a130000000000f46f100048000000457261526577617264506f696e74733c543a3a4163636f756e7449643e0000004200000000000000010000005e0000003e6f10002b000000696f100049000000bc6e10003b000000f76e100047000000466f7263696e67004200000000000000010000005a000000a76e10001500000042000000000000000100000057000000306e10003e000000301a1300000000006e6e10003900000043616e63656c6564536c6173685061796f7574004200000000000000010000005f000000b06d100045000000f56d10003b0000005665633c556e6170706c696564536c6173683c543a3a4163636f756e7449642c2042616c616e63654f663c543e3e3e00420000000000000001000000590000007f6d1000310000005665633c28457261496e6465782c2053657373696f6e496e646578293e00000042000000000000000100000059000000d56c100049000000301a1300000000001e6d100032000000506d10002f0000002850657262696c6c2c2042616c616e63654f663c543e29004200000000000000010000005b000000686c100051000000b96c10001c0000004200000000000000010000005b000000106c100058000000736c617368696e673a3a536c617368696e675370616e73004200000000000000010000005b000000ed6b10002300000028543a3a4163636f756e7449642c20736c617368696e673a3a5370616e496e64657829736c617368696e673a3a5370616e5265636f72643c42616c616e63654f663c543e3e00000042000000000000000100000060000000706b10004f000000bf6b10002e000000316b10003f000000d86a100059000000926a1000460000004200000000000000010000005b000000396a100059000000926a100046000000456c656374696f6e526573756c743c543a3a4163636f756e7449642c2042616c616e63654f663c543e3e00007b69100059000000d4691000580000002c6a10000d0000004200000000000000010000005b0000004f6910002c000000456c656374696f6e5374617475733c543a3a426c6f636b4e756d6265723e00004200000000000000010000005a000000e268100052000000346910001b0000004200000000000000010000005b0000007968100053000000cc68100016000000420000000000000001000000610000001e681000330000009c9d10001f000000301a13000000000051681000280000004200000000000000010000005b000000e06710003e0000002054686520657261207768657265207765206d696772617465642066726f6d204c617a79205061796f75747320746f2053696d706c65205061796f7574732054727565206966206e6574776f726b20686173206265656e20757067726164656420746f20746869732076657273696f6e2e20546869732069732073657420746f2076332e302e3020666f72206e6577206e6574776f726b732e2054727565206966207468652063757272656e74202a2a706c616e6e65642a2a2073657373696f6e2069732066696e616c2e204e6f74652074686174207468697320646f6573206e6f742074616b652065726120666f7263696e6720696e746f206163636f756e742e20466c616720746f20636f6e74726f6c2074686520657865637574696f6e206f6620746865206f6666636861696e20656c656374696f6e2e205768656e20604f70656e285f29602c2077652061636365707420736f6c7574696f6e7320746f206265207375626d69747465642e205468652073636f7265206f66207468652063757272656e74205b60517565756564456c6563746564605d2e20546865206e6578742076616c696461746f72207365742e2041742074686520656e64206f6620616e206572612c206966207468697320697320617661696c61626c652028706f74656e7469616c6c792066726f6d2074686520726573756c74206f6620616e206f6666636861696e20776f726b6572292c20697420697320696d6d6564696174656c7920757365642e204f74686572776973652c20746865206f6e2d636861696e20656c656374696f6e2069732065786563757465642e20536e617073686f74206f66206e6f6d696e61746f72732061742074686520626567696e6e696e67206f66207468652063757272656e7420656c656374696f6e2077696e646f772e20546869732073686f756c64206f6e6c79206861766520612076616c7565207768656e205b60457261456c656374696f6e537461747573605d203d3d2060456c656374696f6e5374617475733a3a4f70656e285f29602e20536e617073686f74206f662076616c696461746f72732061742074686520626567696e6e696e67206f66207468652063757272656e7420656c656374696f6e2077696e646f772e20546869732073686f756c64206f6e6c7920546865206561726c696573742065726120666f72207768696368207765206861766520612070656e64696e672c20756e6170706c69656420736c6173682e205265636f72647320696e666f726d6174696f6e2061626f757420746865206d6178696d756d20736c617368206f6620612073746173682077697468696e206120736c617368696e67207370616e2c2061732077656c6c20617320686f77206d7563682072657761726420686173206265656e2070616964206f75742e20536c617368696e67207370616e7320666f72207374617368206163636f756e74732e20416c6c20736c617368696e67206576656e7473206f6e206e6f6d696e61746f72732c206d61707065642062792065726120746f20746865206869676865737420736c6173682076616c7565206f6620746865206572612e20416c6c20736c617368696e67206576656e7473206f6e2076616c696461746f72732c206d61707065642062792065726120746f20746865206869676865737420736c6173682070726f706f7274696f6e20616e6420736c6173682076616c7565206f6620746865206572612e2041206d617070696e672066726f6d207374696c6c2d626f6e646564206572617320746f207468652066697273742073657373696f6e20696e646578206f662074686174206572612e204d75737420636f6e7461696e7320696e666f726d6174696f6e20666f72206572617320666f72207468652072616e67653a20605b6163746976655f657261202d20626f756e64696e675f6475726174696f6e3b206163746976655f6572615d6020416c6c20756e6170706c69656420736c61736865732074686174206172652071756575656420666f72206c617465722e2054686520616d6f756e74206f662063757272656e637920676976656e20746f207265706f7274657273206f66206120736c617368206576656e74207768696368207761732063616e63656c65642062792065787472616f7264696e6172792063697263756d7374616e6365732028652e672e20676f7665726e616e6365292e205468652070657263656e74616765206f662074686520736c617368207468617420697320646973747269627574656420746f207265706f72746572732e205468652072657374206f662074686520736c61736865642076616c75652069732068616e646c6564206279207468652060536c617368602e204d6f6465206f662065726120666f7263696e672e2054686520746f74616c20616d6f756e74207374616b656420666f7220746865206c6173742060484953544f52595f44455054486020657261732e20496620746f74616c206861736e2774206265656e20736574206f7220686173206265656e2072656d6f766564207468656e2030207374616b652069732072657475726e65642e205265776172647320666f7220746865206c6173742060484953544f52595f44455054486020657261732e20496620726577617264206861736e2774206265656e20736574206f7220686173206265656e2072656d6f766564207468656e2030207265776172642069732072657475726e65642e2054686520746f74616c2076616c696461746f7220657261207061796f757420666f7220746865206c6173742060484953544f52595f44455054486020657261732e2045726173207468617420686176656e27742066696e697368656420796574206f7220686173206265656e2072656d6f76656420646f65736e27742068617665207265776172642e2053696d696c617220746f2060457261735374616b657273602c207468697320686f6c64732074686520707265666572656e636573206f662076616c696461746f72732e2054686973206973206b65796564206669727374206279207468652065726120696e64657820746f20616c6c6f772062756c6b2064656c6574696f6e20616e64207468656e20746865207374617368206163636f756e742e2049732069742072656d6f7665642061667465722060484953544f52595f44455054486020657261732e20436c6970706564204578706f73757265206f662076616c696461746f72206174206572612e20546869732069732073696d696c617220746f205b60457261735374616b657273605d20627574206e756d626572206f66206e6f6d696e61746f7273206578706f736564206973207265647563656420746f207468652060543a3a4d61784e6f6d696e61746f72526577617264656450657256616c696461746f72602062696767657374207374616b6572732e20284e6f74653a20746865206669656c642060746f74616c6020616e6420606f776e60206f6620746865206578706f737572652072656d61696e7320756e6368616e676564292e2054686973206973207573656420746f206c696d69742074686520692f6f20636f737420666f7220746865206e6f6d696e61746f72207061796f75742e2054686973206973206b657965642066697374206279207468652065726120696e64657820746f20616c6c6f772062756c6b2064656c6574696f6e20616e64207468656e20746865207374617368206163636f756e742e204966207374616b657273206861736e2774206265656e20736574206f7220686173206265656e2072656d6f766564207468656e20656d707479206578706f737572652069732072657475726e65642e204578706f73757265206f662076616c696461746f72206174206572612e205468652073657373696f6e20696e646578206174207768696368207468652065726120737461727420666f7220746865206c6173742060484953544f52595f44455054486020657261732e20546865206163746976652065726120696e666f726d6174696f6e2c20697420686f6c647320696e64657820616e642073746172742e20546865206163746976652065726120697320746865206572612063757272656e746c792072657761726465642e2056616c696461746f7220736574206f66207468697320657261206d75737420626520657175616c20746f206053657373696f6e496e746572666163653a3a76616c696461746f7273602e205468652063757272656e742065726120696e6465782e205468697320697320746865206c617465737420706c616e6e6564206572612c20646570656e64696e67206f6e20686f77207468652053657373696f6e2070616c6c657420717565756573207468652076616c696461746f72207365742c206974206d6967687420626520616374697665206f72206e6f742e20546865206d61702066726f6d206e6f6d696e61746f72207374617368206b657920746f2074686520736574206f66207374617368206b657973206f6620616c6c2076616c696461746f727320746f206e6f6d696e6174652e20546865206d61702066726f6d202877616e6e616265292076616c696461746f72207374617368206b657920746f2074686520707265666572656e636573206f6620746861742076616c696461746f722e2057686572652074686520726577617264207061796d656e742073686f756c64206265206d6164652e204b657965642062792073746173682e204d61702066726f6d20616c6c2028756e6c6f636b6564292022636f6e74726f6c6c657222206163636f756e747320746f2074686520696e666f20726567617264696e6720746865207374616b696e672e204d61702066726f6d20616c6c206c6f636b65642022737461736822206163636f756e747320746f2074686520636f6e74726f6c6c6572206163636f756e742e20416e792076616c696461746f72732074686174206d6179206e6576657220626520736c6173686564206f7220666f726369626c79206b69636b65642e20497427732061205665632073696e63652074686579277265206561737920746f20696e697469616c697a6520616e642074686520706572666f726d616e636520686974206973206d696e696d616c2028776520657870656374206e6f206d6f7265207468616e20666f757220696e76756c6e657261626c65732920616e64207265737472696374656420746f20746573746e6574732e204d696e696d756d206e756d626572206f66207374616b696e67207061727469636970616e7473206265666f726520656d657267656e637920636f6e646974696f6e732061726520696d706f7365642e2054686520696465616c206e756d626572206f66207374616b696e67207061727469636970616e74732e204e756d626572206f66206572617320746f206b65657020696e20686973746f72792e20496e666f726d6174696f6e206973206b65707420666f72206572617320696e20605b63757272656e745f657261202d20686973746f72795f64657074683b2063757272656e745f6572615d602e204d757374206265206d6f7265207468616e20746865206e756d626572206f6620657261732064656c617965642062792073657373696f6e206f74686572776973652e20492e652e2061637469766520657261206d75737420616c7761797320626520696e20686973746f72792e20492e652e20606163746976655f657261203e2063757272656e745f657261202d20686973746f72795f646570746860206d7573742062652067756172616e746565642e000000000000e07810000e0000000000000097f612000c00000000000000301a1300f0781000000000000000000000791000010000000000000000000000087910000f00000000000000b51a10000800000000000000301a130018791000000000000000000028791000010000000000000053657373696f6e73506572457261000042000000000000000100000062000000697910001c000000426f6e64696e674475726174696f6e00420000000000000001000000630000003079100039000000204e756d626572206f6620657261732074686174207374616b65642066756e6473206d7573742072656d61696e20626f6e64656420666f722e204e756d626572206f662073657373696f6e7320706572206572612e65786163746c79206f6e65206f6620606d617962655f76616c696461746f726020616e6420606d617962655f6e6f6d696e6174696f6e2e69735f736f6d656020697320747275652e2069735f76616c696461746f722069732066616c73653b206d617962655f6e6f6d696e6174696f6e20697320736f6d653b207165640000147a1000330000005c090000220000002f686f6d652f6461766964642f6465762f7375627374726174652f6672616d652f7374616b696e672f7372632f6c69622e72730000000000361310000d00000000000000587d10000100000000000000000000002e1310000800000000000000607d1000010000000000000000000000211310000d00000000000000687d1000010000000000000000000000141310000d00000000000000707d1000010000000000000000000000081310000c00000000000000787d1000010000000000000000000000fa1210000e00000000000000807d1000010000000000000000000000e91210001100000000000000887d1000010000000000000000000000d81210001100000000000000907d1000010000000000000000000000cc1210000c00000000000000987d1000010000000000000000000000bf1210000d00000000000000a07d1000010000000000000000000000b31210000c00000000000000a87d1000010000000000000000000000a11210001200000000000000b07d1000010000000000000000000000871210001a00000000000000b87d1000010000000000000000000000751210001200000000000000c07d1000010000000000000000000000671210000e00000000000000c87d1000010000000000000000000000501210001700000000000000d07d10000100000000000000000000003a1210001600000000000000d87d1000010000000000000000000000271210001300000000000000e07d10000100000000000000000000000f1210001800000000000000e87d1000010000000000000000000000fc1110001300000000000000f07d1000020000000000000000000000e81110001400000000000000007e1000020000000000000000000000d21110001600000000000000107e1000010000000000000000000000bb1110001700000000000000187e1000010000000000000000000000a21110001900000000000000207e10000200000000000000000000008d1110001500000000000000307e10000100000000000000000000007c1110001100000000000000387e10000100000000000000000000006a1110001200000000000000407e10000100000000000000000000005c1110000e00000000000000487e100001000000000000002d8410001a0000001884100015000000ff83100019000000e18310001e000000c883100019000000b783100011000000958310002200000062831000330000003d831000250000001483100029000000e182100033000000ca82100017000000ab8210001f0000008a8210002100000047821000430000000e82100039000000ce811000400000009a811000340000006e8110002c0000000881100058000000608110000e0000008780100057000000de8010002a0000004280100045000000ef7f100053000000827f100058000000da7f100015000000397f100049000000e87e100051000000a27e100046000000507e100052000000205468652063616c6c206973206e6f7420616c6c6f7765642061742074686520676976656e2074696d652064756520746f207265737472696374696f6e73206f6620656c656374696f6e20706572696f642e2054686520636c61696d65642073636f726520646f6573206e6f74206d61746368207769746820746865206f6e6520636f6d70757465642066726f6d2074686520646174612e20546865207375626d697474656420726573756c742068617320756e6b6e6f776e206564676573207468617420617265206e6f7420616d6f6e67207468652070726573656e7465642077696e6e6572732e20412073656c6620766f7465206d757374206f6e6c79206265206f726967696e617465642066726f6d20612076616c696461746f7220746f204f4e4c59207468656d73656c7665732e204f6e65206f6620746865207375626d6974746564206e6f6d696e61746f72732068617320616e2065646765207768696368206973207375626d6974746564206265666f726520746865206c617374206e6f6e2d7a65726f20736c617368206f6620746865207461726765742e204f6e65206f6620746865207375626d6974746564206e6f6d696e61746f72732068617320616e206564676520746f20776869636820746865792068617665206e6f7420766f746564206f6e20636861696e2e204f6e65206f6620746865207375626d6974746564206e6f6d696e61746f7273206973206e6f7420616e20616374697665206e6f6d696e61746f72206f6e20636861696e2e204572726f72207768696c65206275696c64696e67207468652061737369676e6d656e7420747970652066726f6d2074686520636f6d706163742e20546869732063616e2068617070656e20696620616e20696e64657820697320696e76616c69642c206f72206966207468652077656967687473205f6f766572666c6f775f2e204f6e65206f6620746865207375626d69747465642077696e6e657273206973206e6f7420616e206163746976652063616e646964617465206f6e20636861696e2028696e646578206973206f7574206f662072616e676520696e20736e617073686f74292e20496e636f7272656374206e756d626572206f662077696e6e65727320776572652070726573656e7465642e2054686520736e617073686f742064617461206f66207468652063757272656e742077696e646f77206973206d697373696e672e20546865207375626d697474656420726573756c74206973206e6f7420617320676f6f6420617320746865206f6e652073746f726564206f6e20636861696e2e20546865207375626d697474656420726573756c74206973207265636569766564206f7574206f6620746865206f70656e2077696e646f772e205265776172647320666f72207468697320657261206861766520616c7265616479206265656e20636c61696d656420666f7220746869732076616c696461746f722e204974656d7320617265206e6f7420736f7274656420616e6420756e697175652e20496e76616c6964206e756d626572206f66206e6f6d696e6174696f6e732e20496e76616c69642065726120746f207265776172642e20417474656d7074696e6720746f2074617267657420612073746173682074686174207374696c6c206861732066756e64732e2043616e206e6f74207265626f6e6420776974686f757420756e6c6f636b696e67206368756e6b732e2043616e206e6f74207363686564756c65206d6f726520756e6c6f636b206368756e6b732e2043616e206e6f7420626f6e6420776974682076616c7565206c657373207468616e206d696e696d756d2062616c616e63652e20536c617368207265636f726420696e646578206f7574206f6620626f756e64732e204475706c696361746520696e6465782e20546172676574732063616e6e6f7420626520656d7074792e20436f6e74726f6c6c657220697320616c7265616479207061697265642e20537461736820697320616c726561647920626f6e6465642e204e6f742061207374617368206163636f756e742e204e6f74206120636f6e74726f6c6c6572206163636f756e742e00508410001a0000004552524f523a20436f7272757074656420737461746520617420446561644163636f756e744b656570416c6976654578697374656e7469616c4465706f736974496e73756666696369656e7442616c616e63654c69717569646974795265737472696374696f6e7356657374696e6742616c616e63657365745f62616c616e63657472616e736665725f6b6565705f616c697665546f74616c49737375616e636500000000000000d0851000070000000000000084111200020000000000000000000000d8851000010000000000000000000000e0851000080000000000000084111200020000000000000000000000e885100002000000000000000000000074ca110008000000000000007cca1100030000000000000000000000f8851000010000000000000000000000008610000a000000000000000c86100003000000000000000000000024861000010000000000000000000000c81912000700000000000000841112000200000000000000000000002c8610000100000000000000456e646f77656400318710002f000000447573744c6f7374c286100050000000128710001f0000009c8610002600000042616c616e6365536574000020af120009000000f615120007000000f6151200070000006b86100031000000348610003700000020536f6d6520616d6f756e7420776173206465706f73697465642028652e672e20666f72207472616e73616374696f6e2066656573292e20412062616c616e6365207761732073657420627920726f6f74202877686f2c20667265652c207265736572766564292e205472616e7366657220737563636565646564202866726f6d2c20746f2c2076616c7565292e20416e206163636f756e74207761732072656d6f7665642077686f73652062616c616e636520776173206e6f6e2d7a65726f206275742062656c6f77204578697374656e7469616c4465706f7369742c20726573756c74696e6720696e20616e206f75747269676874206c6f73732e20416e206163636f756e74207761732063726561746564207769746820736f6d6520667265652062616c616e63652e496e76616c69644f726967696e496e73756666696369656e7443616e64696461746546756e647352756e6e65725375626d69744d656d6265725375626d69744475706c69636174656443616e6469646174655265706f727453656c664d7573744265566f746572556e61626c65546f506179426f6e644c6f7742616c616e63654d6178696d756d566f7465734578636565646564546f6f4d616e79566f7465734e6f566f746573556e61626c65546f566f746572656d6f76655f766f7465727265706f72745f646566756e63745f766f7465727375626d69745f63616e64696461637972656e6f756e63655f63616e646964616379000000000000003489100007000000000000003c89100001000000000000000000000044891000040000000000000000000000648910000900000000000000301a130000000000000000000000000070891000020000000000000000000000808910000c0000000000000074ad12000100000000000000000000008c8910000200000000000000000000009c8910000f0000000000000074ad1200010000000000000000000000ac891000010000000000000000000000b48910000d00000000000000ac121200030000000000000000000000c489100002000000000000004e65775465726d00ad8c100019000000538b100056000000a98b100056000000ff8b100058000000578c100056000000456d7074795465726d000000d58a10004d000000228b1000310000004d656d6265724b69636b6564778a100051000000c88a10000d0000004d656d62657252656e6f756e636564004f8a100028000000566f7465725265706f72746564000000d4891000580000002c8a100023000000204120766f7465722028666972737420656c656d656e742920776173207265706f72746564202862797420746865207365636f6e6420656c656d656e742920776974682074686520746865207265706f7274206265696e67207375636365737366756c206f72206e6f742028746869726420656c656d656e74292e2041206d656d626572206861732072656e6f756e6365642074686569722063616e6469646163792e2041206d656d62657220686173206265656e2072656d6f7665642e20546869732073686f756c6420616c7761797320626520666f6c6c6f7765642062792065697468657220604e65775465726d60206f742060456d7074795465726d602e204e6f20286f72206e6f7420656e6f756768292063616e64696461746573206578697374656420666f72207468697320726f756e642e205468697320697320646966666572656e742066726f6d20604e65775465726d285b5d29602e2053656520746865206465736372697074696f6e206f6620604e65775465726d602e2041206e6577207465726d2077697468206e6577206d656d626572732e205468697320696e64696361746573207468617420656e6f7567682063616e64696461746573206578697374656420746f2072756e2074686520656c656374696f6e2c206e6f74207468617420656e6f756768206861766520686173206265656e20656c65637465642e2054686520696e6e65722076616c7565206d757374206265206578616d696e656420666f72207468697320707572706f73652e204120604e65775465726d285b5d296020696e64696361746573207468617420736f6d652063616e6469646174657320676f7420746865697220626f6e6420736c617368656420616e64206e6f6e65207765726520656c65637465642c207768696c73742060456d7074795465726d60206d65616e732074686174206e6f2063616e64696461746573206578697374656420746f20626567696e20776974682e5665633c284163636f756e7449642c2042616c616e6365293e52756e6e657273557000a48a12003e00000003030000190000003c8e10003c00000071000000130000003c8e10003c00000088000000180000003c8e10003c000000b4000000190000003c8e10003c000000ff000000420000003c8e10003c00000013010000420000004475706c696361746520766f74657220286f72206f7468657220636f727275707420696e707574292e0000003c8e10003c00000057010000150000003c8e10003c0000005c0100001e000000420000000000000001000000640000003c8e10003c0000005f0000001a0000003c8e10003c0000005f0000002c0000003c8e10003c000000cc010000240000003c8e10003c000000cd010000240000003c8e10003c000000f3010000240000003c8e10003c00000020020000240000003c8e10003c00000043020000350000003c8e10003c000000580200002b0000003c8e10003c00000059020000280000003c8e10003c000000630200002b0000003c8e10003c00000064020000280000002f686f6d652f6461766964642f6465762f7375627374726174652f7072696d6974697665732f70687261676d656e2f7372632f7265647563652e72730000000013db10000800000000000000288f1000020000000000000000000000588f10001b0000000000000000000000c68410000b0000000000000030901000030000000000000000000000789010001000000000000000000000001fdb10000e00000000000000f890100003000000000000000000000040911000060000000000000000000000d18410001300000000000000288f1000020000000000000000000000709110000b0000000000000000000000b2d311000400000000000000f32012002300000000000000aa4d120005000000000000000a941000130000003896100036000000301a1300000000006e96100042000000b096100048000000f8961000450000003d9710002d000000301a1300000000006a97100046000000301a130000000000f5bd12000b000000b09710004c000000fc971000330000002f9810005a000000301a1300000000008998100013000000301a1300000000009c98100054000000f09810004b0000003b991000350000007099100058000000c8991000520000001a9a10003e000000589a1000220000007a9a10004e000000c89a100037000000ff9a10004500000044be12000c00000000000000f02012000300000000000000f320120023000000000000002496100008000000000000000a94100013000000000000002c9610000c000000000000000a941000130000001d94100025000000301a13000000000042941000480000008a94100042000000cc941000460000001295100040000000301a130000000000529510002d000000301a130000000000f5bd12000b0000007f951000200000009f95100031000000d095100016000000e695100018000000fe9510002600000044be12000c00000000000000049410000600000000000000f32012002300000000000000b2d311000400000000000000f32012002300000000000000aa4d120005000000000000000a941000130000003193100054000000859310000b000000f5bd12000b0000009093100050000000e09310002400000044be12000c000000c8911000540000001c92100010000000301a1300000000002c9210002f000000301a1300000000005b92100031000000f5bd12000b0000008c9210003a000000c692100019000000df92100047000000269310000b0000002053616d6520617320746865205b607472616e73666572605d2063616c6c2c206275742077697468206120636865636b207468617420746865207472616e736665722077696c6c206e6f74206b696c6c20746865206f726967696e206163636f756e742e20393925206f66207468652074696d6520796f752077616e74205b607472616e73666572605d20696e73746561642e205b607472616e73666572605d3a207374727563742e4d6f64756c652e68746d6c236d6574686f642e7472616e73666572202d2043686561706572207468616e207472616e736665722062656361757365206163636f756e742063616e6e6f74206265206b696c6c65642e202d2042617365205765696768743a2035372e333620c2b573202d204442205765696768743a2031205265616420616e64203120577269746520746f2064657374202873656e64657220697320696e206f7665726c617920616c72656164792920233c2f7765696768743e2045786163746c7920617320607472616e73666572602c2065786365707420746865206f726967696e206d75737420626520726f6f7420616e642074686520736f75726365206163636f756e74206d6179206265207370656369666965642e202d2053616d65206173207472616e736665722c20627574206164646974696f6e616c207265616420616e6420777269746520626563617573652074686520736f75726365206163636f756e742069732020206e6f7420617373756d656420746f20626520696e20746865206f7665726c61792e736f75726365436f6d706163743c543a3a42616c616e63653e20536574207468652062616c616e636573206f66206120676976656e206163636f756e742e20546869732077696c6c20616c74657220604672656542616c616e63656020616e642060526573657276656442616c616e63656020696e2073746f726167652e2069742077696c6c20616c736f2064656372656173652074686520746f74616c2069737375616e6365206f66207468652073797374656d202860546f74616c49737375616e636560292e20496620746865206e65772066726565206f722072657365727665642062616c616e63652069732062656c6f7720746865206578697374656e7469616c206465706f7369742c2069742077696c6c20726573657420746865206163636f756e74206e6f6e63652028606672616d655f73797374656d3a3a4163636f756e744e6f6e636560292e20546865206469737061746368206f726967696e20666f7220746869732063616c6c2069732060726f6f74602e202d20496e646570656e64656e74206f662074686520617267756d656e74732e202d20436f6e7461696e732061206c696d69746564206e756d626572206f6620726561647320616e64207772697465732e202d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d202d2042617365205765696768743a2033322e3620c2b573202d204442205765696768743a203120526561642c203120577269746520746f206077686f606e65775f667265656e65775f7265736572766564205472616e7366657220736f6d65206c697175696420667265652062616c616e636520746f20616e6f74686572206163636f756e742e20607472616e73666572602077696c6c207365742074686520604672656542616c616e636560206f66207468652073656e64657220616e642072656365697665722e2049742077696c6c2064656372656173652074686520746f74616c2069737375616e6365206f66207468652073797374656d2062792074686520605472616e73666572466565602e204966207468652073656e6465722773206163636f756e742069732062656c6f7720746865206578697374656e7469616c206465706f736974206173206120726573756c74206f6620746865207472616e736665722c20746865206163636f756e742077696c6c206265207265617065642e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d75737420626520605369676e65646020627920746865207472616e736163746f722e202d20446570656e64656e74206f6e20617267756d656e747320627574206e6f7420637269746963616c2c20676976656e2070726f70657220696d706c656d656e746174696f6e7320666f72202020696e70757420636f6e6669672074797065732e205365652072656c617465642066756e6374696f6e732062656c6f772e202d20497420636f6e7461696e732061206c696d69746564206e756d626572206f6620726561647320616e642077726974657320696e7465726e616c6c7920616e64206e6f20636f6d706c657820636f6d7075746174696f6e2e2052656c617465642066756e6374696f6e733a2020202d2060656e737572655f63616e5f77697468647261776020697320616c776179732063616c6c656420696e7465726e616c6c792062757420686173206120626f756e64656420636f6d706c65786974792e2020202d205472616e7366657272696e672062616c616e63657320746f206163636f756e7473207468617420646964206e6f74206578697374206265666f72652077696c6c20636175736520202020202060543a3a4f6e4e65774163636f756e743a3a6f6e5f6e65775f6163636f756e746020746f2062652063616c6c65642e2020202d2052656d6f76696e6720656e6f7567682066756e64732066726f6d20616e206163636f756e742077696c6c20747269676765722060543a3a4475737452656d6f76616c3a3a6f6e5f756e62616c616e636564602e2020202d20607472616e736665725f6b6565705f616c6976656020776f726b73207468652073616d652077617920617320607472616e73666572602c206275742068617320616e206164646974696f6e616c2020202020636865636b207468617420746865207472616e736665722077696c6c206e6f74206b696c6c20746865206f726967696e206163636f756e742e202d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d202d2042617365205765696768743a20383020c2b5732c20776f7273742063617365207363656e6172696f20286163636f756e7420637265617465642c206163636f756e742072656d6f76656429202d204442205765696768743a2031205265616420616e64203120577269746520746f2064657374696e6174696f6e206163636f756e74202d204f726967696e206163636f756e7420697320616c726561647920696e206d656d6f72792c20736f206e6f204442206f7065726174696f6e7320666f72207468656d2e00000000e48410000d0000000000000000000000a49c10000a00000000000000000000000000000000000000000000000000000000000000301a1300b09c10000000000000000000c09c10000100000000000000010000000000000057e211000700000001020000000000007ac312000c00000000000000c89c10001700000000000000000000000000000000000000301a1300e09c10000000000000000000f09c100006000000000000000100000000000000389111000500000001020000000000007ac312000c00000000000000209d10001c00000000000000000000000000000000000000301a13003c9d100000000000000000004c9d1000020000000000000001000000000000005c9d10000e00000000000000000000006a9d10000800000000000000000000000000000000000000000000000000000000000000301a1300749d10000000000000000000849d1000030000000000000001000000543a3a42616c616e636500004200000000000000010000005f0000004b9f1000260000004163636f756e74446174613c543a3a42616c616e63653e00420000000000000001000000650000005a9e10001b000000301a130000000000759e100056000000cb9e100030000000301a130000000000fb9e1000500000005665633c42616c616e63654c6f636b3c543a3a42616c616e63653e3e42000000000000000100000059000000e39d10002e000000119e10004900000053746f7261676556657273696f6e52656c656173657300004200000000000000010000005a0000009c9d10001f000000301a130000000000bb9d1000280000002053746f726167652076657273696f6e206f66207468652070616c6c65742e20546869732069732073657420746f2076322e302e3020666f72206e6577206e6574776f726b732e20416e79206c6971756964697479206c6f636b73206f6e20736f6d65206163636f756e742062616c616e6365732e204e4f54453a2053686f756c64206f6e6c79206265206163636573736564207768656e2073657474696e672c206368616e67696e6720616e642066726565696e672061206c6f636b2e205468652062616c616e6365206f6620616e206163636f756e742e204e4f54453a2054484953204d4159204e4556455220424520494e204558495354454e434520414e4420594554204841564520412060746f74616c28292e69735f7a65726f2829602e2049662074686520746f74616c2069732065766572207a65726f2c207468656e2074686520656e747279202a4d5553542a2062652072656d6f7665642e204e4f54453a2054686973206973206f6e6c79207573656420696e20746865206361736520746861742074686973206d6f64756c65206973207573656420746f2073746f72652062616c616e6365732e2054686520746f74616c20756e6974732069737375656420696e207468652073797374656d2e000000000000007e8410001200000000000000a49c10000a00000000000000301a1300d4b110000000000000000000ac9f10000100000000000000b49f10003500000020546865206d696e696d756d20616d6f756e7420726571756972656420746f206b65657020616e206163636f756e74206f70656e2e0000000000000014b012000400000000000000f4a0100002000000000000000000000024a110000f0000000000000000000000138810000c00000000000000301a13000000000000000000000000009ca110000700000000000000000000001f8810001400000000000000b4471100010000000000000000000000d4a110000d0000000000000000000000338810001000000000000000301a13000000000000000000000000003ca210000d0000000000000000000000438810001200000000000000301a1300000000000000000000000000a4a2100009000000000000000000000087e411000d00000000000000eca2100001000000000000000000000004a310000d000000000000000000000052ac10000500000000000000ddce12001100000000000000aa4d120005000000000000008075120015000000b8aa100041000000301a130000000000f9aa1000140000000dab1000120000001fab10002b000000301a1300000000004aab100057000000a1ab100057000000f8ab100028000000301a130000000000f5bd12000b000000c7a410000b000000acaa10000c00000020ac10003200000044be12000c00000064aa100048000000301a130000000000f5bd12000b000000c7a410000b000000acaa10000c000000aba810000d00000044be12000c000000b8a81000570000000fa910005700000066a9100017000000301a1300000000007da91000220000009fa9100053000000f2a910002d000000301a130000000000f5bd12000b000000c7a410000b0000001faa100045000000aba810000d00000044be12000c00000069a710001e000000301a13000000000087a7100019000000a0a710003b000000dba710004b00000026a81000550000007ba810000d000000301a130000000000f5bd12000b000000c7a410000b00000088a8100023000000aba810000d00000044be12000c000000ffa410005400000053a510001000000063a5100050000000b3a510003d000000f0a510005600000046a610002100000067a6100053000000baa610005600000010a710005900000000000000f02012000300000000000000f3201200230000006ca3100057000000c3a3100020000000301a130000000000e3a310005600000039a410003d000000301a13000000000076a4100051000000301a130000000000f5bd12000b000000c7a410000b000000d2a4100016000000e8a410001700000044be12000c0000002052656d6f7665206120706172746963756c6172206d656d6265722066726f6d20746865207365742e20546869732069732065666665637469766520696d6d6564696174656c7920616e642074686520626f6e64206f6620746865206f7574676f696e67206d656d62657220697320736c61736865642e20496620612072756e6e65722d757020697320617661696c61626c652c207468656e2074686520626573742072756e6e65722d75702077696c6c2062652072656d6f76656420616e64207265706c6163657320746865206f7574676f696e67206d656d6265722e204f74686572776973652c2061206e65772070687261676d656e20726f756e6420697320737461727465642e204e6f74652074686174207468697320646f6573206e6f7420616666656374207468652064657369676e6174656420626c6f636b206e756d626572206f6620746865206e65787420656c656374696f6e2e20232323232053746174652052656164733a204f28646f5f70687261676d656e29205772697465733a204f28646f5f70687261676d656e292052656e6f756e6365206f6e65277320696e74656e74696f6e20746f20626520612063616e64696461746520666f7220746865206e65787420656c656374696f6e20726f756e642e203320706f74656e7469616c206f7574636f6d65732065786973743a202d20606f726967696e6020697320612063616e64696461746520616e64206e6f7420656c656374656420696e20616e79207365742e20496e207468697320636173652c2074686520626f6e64206973202020756e72657365727665642c2072657475726e656420616e64206f726967696e2069732072656d6f76656420617320612063616e6469646174652e202d20606f726967696e6020697320612063757272656e742072756e6e65722075702e20496e207468697320636173652c2074686520626f6e6420697320756e72657365727665642c2072657475726e656420616e642020206f726967696e2069732072656d6f76656420617320612072756e6e65722e202d20606f726967696e6020697320612063757272656e74206d656d6265722e20496e207468697320636173652c2074686520626f6e6420697320756e726573657276656420616e64206f726967696e20697320202072656d6f7665642061732061206d656d6265722c20636f6e73657175656e746c79206e6f74206265696e6720612063616e64696461746520666f7220746865206e65787420726f756e6420616e796d6f72652e20202053696d696c617220746f205b6072656d6f76655f766f746572605d2c206966207265706c6163656d656e742072756e6e657273206578697374732c20746865792061726520696d6d6564696174656c7920757365642e205375626d6974206f6e6573656c6620666f722063616e6469646163792e20412063616e6469646174652077696c6c206569746865723a2020202d204c6f73652061742074686520656e64206f6620746865207465726d20616e6420666f7266656974207468656972206465706f7369742e2020202d2057696e20616e64206265636f6d652061206d656d6265722e204d656d626572732077696c6c206576656e7475616c6c7920676574207468656972207374617368206261636b2e2020202d204265636f6d6520612072756e6e65722d75702e2052756e6e6572732d75707320617265207265736572766564206d656d6265727320696e2063617365206f6e65206765747320666f72636566756c6c79202020202072656d6f7665642e2052656164733a204f284c6f674e2920476976656e204e2063616e646964617465732e205772697465733a204f283129205265706f727420607461726765746020666f72206265696e6720616e20646566756e637420766f7465722e20496e2063617365206f6620612076616c6964207265706f72742c20746865207265706f727465722069732072657761726465642062792074686520626f6e6420616d6f756e74206f662060746172676574602e204f74686572776973652c20746865207265706f7274657220697473656c662069732072656d6f76656420616e6420746865697220626f6e6420697320736c61736865642e204120646566756e637420766f74657220697320646566696e656420746f2062653a2020202d206120766f7465722077686f73652063757272656e74207375626d697474656420766f7465732061726520616c6c20696e76616c69642e20692e652e20616c6c206f66207468656d20617265206e6f20202020206c6f6e67657220612063616e646964617465206e6f7220616e20616374697665206d656d6265722e2052656164733a204f284e4c6f674d2920676976656e204d2063757272656e742063616e6469646174657320616e64204e20766f74657320666f722060746172676574602e2052656d6f766520606f726967696e60206173206120766f7465722e20546869732072656d6f76657320746865206c6f636b20616e642072657475726e732074686520626f6e642e2052656164733a204f28312920566f746520666f72206120736574206f662063616e6469646174657320666f7220746865207570636f6d696e6720726f756e64206f6620656c656374696f6e2e205468652060766f746573602073686f756c643a2020202d206e6f7420626520656d7074792e2020202d206265206c657373207468616e20746865206e756d626572206f662063616e646964617465732e2055706f6e20766f74696e672c206076616c75656020756e697473206f66206077686f6027732062616c616e6365206973206c6f636b656420616e64206120626f6e6420616d6f756e742069732072657365727665642e2049742069732074686520726573706f6e736962696c697479206f66207468652063616c6c657220746f206e6f7420706c61636520616c6c206f662074686569722062616c616e636520696e746f20746865206c6f636b20616e64206b65657020736f6d6520666f722066757274686572207472616e73616374696f6e732e205772697465733a204f28562920676976656e2060566020766f7465732e205620697320626f756e6465642062792031362e766f746573000000000009b5120007000000000000000000000010ae10002100000000000000000000000000000000000000000000000000000000000000301a13003cae1000000000000000000034ae100001000000000000000100000000000000c68c100009000000000000000000000010ae10002100000000000000000000000000000000000000000000000000000000000000301a13003cae100000000000000000004cae10000100000000000000010000000000000030f212000e000000000000000000000060dc12000300000000000000000000000000000000000000000000000000000000000000301a130054ae1000000000000000000064ae10000100000000000000010000000000000010b512000600000001050000000000007ac312000c00000000000000a48f11002100000000000000000000000000000000000000301a13006cae100000000000000000007cae100001000000000000000100000000000000611c12000a0000000000000000000000ddce12001100000000000000000000000000000000000000000000000000000000000000301a130084ae1000000000000000000094ae10000200000000000000010000005665633c28543a3a4163636f756e7449642c2042616c616e63654f663c543e293e0000001ab010003c00000042000000000000000100000059000000c8af1000520000004200000000000000010000005700000078af100050000000420000000000000001000000660000004aaf10002e00000042000000000000000100000059000000a4ae100056000000faae100050000000205468652070726573656e742063616e646964617465206c6973742e20536f72746564206261736564206f6e206163636f756e742d69642e20412063757272656e74206d656d626572206f722072756e6e65722d75702063616e206e6576657220656e746572207468697320766563746f7220616e6420697320616c7761797320696d706c696369746c7920617373756d656420746f20626520612063616e6469646174652e20566f74657320616e64206c6f636b6564207374616b65206f66206120706172746963756c617220766f7465722e2054686520746f74616c206e756d626572206f6620766f746520726f756e6473207468617420686176652068617070656e65642c206578636c7564696e6720746865207570636f6d696e67206f6e652e205468652063757272656e742072756e6e6572735f75702e20536f72746564206261736564206f6e206c6f7720746f2068696768206d657269742028776f72736520746f20626573742072756e6e6572292e205468652063757272656e7420656c6563746564206d656d626572736869702e20536f72746564206261736564206f6e206163636f756e742069642e000000000000a8b110000d00000000000000b66c12000c00000000000000301a1300b8b110000000000000000000301a1300000000000000000000000000c8b110000a00000000000000b66c12000c00000000000000301a1300d4b110000000000000000000301a1300000000000000000000000000e4b110000e0000000000000060dc12000300000000000000301a1300f4b110000000000000000000301a130000000000000000000000000004b21000100000000000000060dc12000300000000000000301a130014b210000000000000000000301a130000000000000000000000000024b210000c0000000000000006cf12000e00000000000000301a130030b210000000000000000000301a1300000000000000000000000000cc5e1200080000000000000040b210000e00000000000000301a130050b210000000000000000000301a1300000000000000000043616e646964616379426f6e6400000042000000000000000100000067000000566f74696e67426f6e64000042000000000000000100000068000000446573697265644d656d626572730000420000000000000001000000690000004465736972656452756e6e65727355704200000000000000010000006a0000005465726d4475726174696f6e4200000000000000010000006b0000004c6f636b4964656e74696669657200004200000000000000010000006c00000000000000b88410000e0000000000000040b31000010000000000000000000000a3841000150000000000000048b3100001000000000000000000000027ab1200080000000000000050b3100001000000000000000000000090841000130000000000000058b310000100000000000000000000007e841000120000000000000060b3100001000000000000000000000075841000090000000000000068b31000010000000000000000000000aa371100170000000000000070b310000100000000000000000000006a8410000b0000000000000078b310000100000000000000a2b410002700000070b410003200000053b410001d00000035b410001e000000fab310003b000000d6b3100024000000a3b310003300000080b31000230000002042656e6566696369617279206163636f756e74206d757374207072652d657869737420412076657374696e67207363686564756c6520616c72656164792065786973747320666f722074686973206163636f756e74205472616e736665722f7061796d656e7420776f756c64206b696c6c206163636f756e742056616c756520746f6f206c6f7720746f20637265617465206163636f756e742064756520746f206578697374656e7469616c206465706f7369742042616c616e636520746f6f206c6f7720746f2073656e642076616c756520476f7420616e206f766572666c6f7720616674657220616464696e67204163636f756e74206c6971756964697479207265737472696374696f6e732070726576656e74207769746864726177616c2056657374696e672062616c616e636520746f6f206869676820746f2073656e642076616c756500000000000000078810000c0000000000000054b610000100000000000000000000000088100007000000000000005cb61000010000000000000000000000f48710000c0000000000000064b61000010000000000000000000000e087100014000000000000006cb61000010000000000000000000000d68710000a0000000000000074b61000010000000000000000000000c78710000f000000000000007cb61000010000000000000000000000bc8710000b0000000000000084b61000010000000000000000000000b28710000a000000000000008cb610000100000000000000000000009f871000130000000000000094b61000010000000000000000000000938710000c000000000000009cb61000010000000000000000000000878710000c00000000000000a4b610000100000000000000000000006d8710001a00000000000000acb61000010000000000000000000000608710000d00000000000000b4b61000010000000000000000000000f2af12000900000000000000bcb61000010000000000000076b810003100000050b81000260000002eb810002200000007b8100027000000d5b7100032000000b6b710001f000000a5b710001100000091b710001400000070b71000210000004db71000230000002ab710002300000004b7100026000000d2b6100032000000c4b610000e000000204e6f742061206d656d6265722e204f726967696e206973206e6f7420612063616e6469646174652c206d656d626572206f7220612072756e6e65722075702e2043616e64696461746520646f6573206e6f74206861766520656e6f7567682066756e64732e2052756e6e65722063616e6e6f742072652d7375626d69742063616e6469646163792e204d656d6265722063616e6e6f742072652d7375626d69742063616e6469646163792e204475706c6963617465642063616e646964617465207375626d697373696f6e2e2043616e6e6f74207265706f72742073656c662e204d757374206265206120766f7465722e20566f7465722063616e206e6f742070617920766f74696e6720626f6e642e2043616e6e6f7420766f74652077697468207374616b65206c657373207468616e206d696e696d756d2062616c616e63652e2043616e6e6f7420766f7465206d6f7265207468616e206d6178696d756d20616c6c6f7765642e2043616e6e6f7420766f7465206d6f7265207468616e2063616e646964617465732e204d75737420766f746520666f72206174206c65617374206f6e652063616e6469646174652e2043616e6e6f7420766f7465207768656e206e6f2063616e64696461746573206f72206d656d626572732065786973742e556e657870656374656454696d65706f696e7457726f6e6754696d65706f696e744e6f54696d65706f696e7453656e646572496e5369676e61746f726965735369676e61746f726965734f75744f664f72646572546f6f4d616e795369676e61746f72696573546f6f4665775369676e61746f726965734e6f417070726f76616c734e6565646564416c7265616479417070726f766564626174636861735f73756261735f6d756c7469617070726f76655f61735f6d756c746963616e63656c5f61735f6d756c74690000000078ba1000100000000000000088ba100002000000000000000000000098ba1000020000000000000000000000a8ba10000e00000000000000301a1300000000000000000000000000b8ba1000010000000000000000000000c0ba10000b00000000000000ccba1000030000000000000000000000e4ba1000020000000000000000000000f4ba1000100000000000000004bb100004000000000000000000000024bb100002000000000000000000000034bb1000100000000000000044bb10000500000000000000000000006cbb10000200000000000000000000007cbb1000110000000000000004bb100004000000000000000000000090bb100002000000000000004261746368496e74657272757074656460dc120003000000e00e13000d0000004dbe100056000000a3be1000130000004261746368436f6d706c6574656400001abe1000330000004e65774d756c74697369670020af12000900000020af120009000000e9bc1000080000008dbd100052000000dfbd10003b0000004d756c7469736967417070726f76616c20af120009000000d3bc10001600000020af120009000000e9bc100008000000f1bc10005600000047bd1000460000004d756c7469736967457865637574656420af120009000000d3bc10001600000020af120009000000e9bc100008000000940d12000e00000033bc10004b0000007ebc1000550000004d756c746973696743616e63656c6c6564000000a0bb10004c000000ecbb1000470000002041206d756c7469736967206f7065726174696f6e20686173206265656e2063616e63656c6c65642e20466972737420706172616d20697320746865206163636f756e7420746861742069732063616e63656c6c696e672c20746869726420697320746865206d756c7469736967206163636f756e742c20666f757274682069732068617368206f66207468652063616c6c2e2041206d756c7469736967206f7065726174696f6e20686173206265656e2065786563757465642e20466972737420706172616d20697320746865206163636f756e74207468617420697320617070726f76696e672c20746869726420697320746865206d756c7469736967206163636f756e742c20666f757274682069732068617368206f66207468652063616c6c20746f2062652065786563757465642e54696d65706f696e743c426c6f636b4e756d6265723e43616c6c486173682041206d756c7469736967206f7065726174696f6e20686173206265656e20617070726f76656420627920736f6d656f6e652e20466972737420706172616d20697320746865206163636f756e74207468617420697320617070726f76696e672c20746869726420697320746865206d756c7469736967206163636f756e742c20666f757274682069732068617368206f66207468652063616c6c2e2041206e6577206d756c7469736967206f7065726174696f6e2068617320626567756e2e20466972737420706172616d20697320746865206163636f756e74207468617420697320617070726f76696e672c207365636f6e6420697320746865206d756c7469736967206163636f756e742c2074686972642069732068617368206f66207468652063616c6c2e204261746368206f66206469737061746368657320636f6d706c657465642066756c6c792077697468206e6f206572726f722e204261746368206f66206469737061746368657320646964206e6f7420636f6d706c6574652066756c6c792e20496e646578206f66206669727374206661696c696e6720646973706174636820676976656e2c2061732077656c6c20617320746865206572726f722e0000000000003eb91000050000000000000094bf1000010000000000000000000000acbf100013000000000000000000000043b91000060000000000000044c0100002000000000000000000000074c0100008000000000000000000000049b910000800000000000000b4c0100004000000000000000000000014c1100032000000000000000000000051b910001000000000000000a4c2100004000000000000000000000004c3100027000000000000000000000061b910000f000000000000003cc410000400000000000000000000009cc410001b00000000000000000000000bd41000050000000000000010d410001700000071d1100020000000301a13000000000091d110003b000000301a130000000000ccd110001f000000301a130000000000ebd110003c000000301a130000000000f5bd12000b00000027d21000240000004bd210002e00000079d210003100000044be12000c000000301a130000000000aad210005600000000d310004d0000004dd3100056000000a3d3100054000000f7d31000140000000000000098d912000500000000000000f7ce12000300000000000000fbea1200040000000000000061d112001700000000d1100038000000301a13000000000098c9120034000000301a130000000000f5bd12000b00000038d110001900000051d110002000000044be12000c00000000000000eece12000900000000000000f7ce120003000000000000005ec910001100000000000000ddce1200110000000000000092cd10000f00000000000000a1cd10002100000000000000fbea1200040000000000000061d1120017000000a2c9100056000000f8c910003f000000301a130000000000c2cd10002d000000301a13000000000037ca1000540000008bca100058000000e3ca10000e000000301a13000000000098c9120034000000301a130000000000fcc510005600000052c6100051000000a3c610001c000000f1ca10005700000048cb1000550000009dcb100036000000efcd100023000000301a13000000000012ce1000480000005ace100047000000301a130000000000a1ce100057000000f8ce1000560000004ecf100038000000301a130000000000f5bd12000b00000086cf1000150000006ac71000340000009ec7100050000000eec71000520000009bcf10004900000040c810003000000021cc10003600000057cc10003f0000002bc112000d000000e4cf10001c00000096cc10004c000000e2cc10002400000006cd10003d00000000d010002000000043cd10000f00000020d010002300000043d010002400000067d0100025000000f2c810000d0000008cd0100030000000bcd0100031000000edd010001300000044be12000c00000000000000eece12000900000000000000f7ce120003000000000000005ec910001100000000000000ddce1200110000000000000092cd10000f00000000000000a1cd1000210000000000000091c9100009000000000000009ac9100008000000a2c9100056000000f8c910003f000000301a13000000000037ca1000540000008bca100058000000e3ca10000e000000301a13000000000098c9120034000000301a130000000000fcc510005600000052c6100051000000a3c610001c000000f1ca10005700000048cb1000550000009dcb10003600000036c7100034000000301a130000000000d3cb10004e000000301a130000000000f5bd12000b000000af8811000a0000006ac71000340000009ec7100050000000eec710005200000040c810003000000021cc10003600000057cc10003f0000002bc112000d00000096cc10004c000000e2cc10002400000006cd10003d000000afc810002300000043cd10000f00000052cd10001f00000071cd100021000000f2c810000d000000ffc810002f0000002ec910003000000044be12000c00000000000000eece12000900000000000000f7ce120003000000000000005ec910001100000000000000ddce120011000000000000006fc91000090000000000000078c91000190000000000000091c9100009000000000000009ac910000800000074c5100056000000cac5100032000000301a13000000000098c9120034000000301a130000000000fcc510005600000052c6100051000000a3c610001c000000bfc610005800000017c710001f00000036c7100034000000301a130000000000f5bd12000b000000af8811000a0000006ac71000340000009ec7100050000000eec710005200000040c81000300000002bc112000d00000070c810002200000092c810001d000000afc8100023000000d2c8100020000000f2c810000d000000ffc810002f0000002ec910003000000044be12000c0000002043616e63656c2061207072652d6578697374696e672c206f6e2d676f696e67206d756c7469736967207472616e73616374696f6e2e20416e79206465706f7369742072657365727665642070726576696f75736c7920666f722074686973206f7065726174696f6e2077696c6c20626520756e7265736572766564206f6e20737563636573732e202d20607468726573686f6c64603a2054686520746f74616c206e756d626572206f6620617070726f76616c7320666f722074686973206469737061746368206265666f72652069742069732065786563757465642e202d20606f746865725f7369676e61746f72696573603a20546865206163636f756e747320286f74686572207468616e207468652073656e646572292077686f2063616e20617070726f766520746869732064697370617463682e204d6179206e6f7420626520656d7074792e202d206074696d65706f696e74603a205468652074696d65706f696e742028626c6f636b206e756d62657220616e64207472616e73616374696f6e20696e64657829206f662074686520666972737420617070726f76616c207472616e73616374696f6e20666f7220746869732064697370617463682e202d206063616c6c5f68617368603a205468652068617368206f66207468652063616c6c20746f2062652065786563757465642e202d20557020746f206f6e652062616c616e63652d72657365727665206f7220756e72657365727665206f7065726174696f6e2e202d204f6e6520706173737468726f756768206f7065726174696f6e2c206f6e6520696e736572742c20626f746820604f285329602077686572652060536020697320746865206e756d626572206f662020207369676e61746f726965732e206053602069732063617070656420627920604d61785369676e61746f72696573602c207769746820776569676874206265696e672070726f706f7274696f6e616c2e202d204f6e6520656e636f6465202620686173682c20626f7468206f6620636f6d706c657869747920604f285329602e202d20492f4f3a2031207265616420604f285329602c206f6e652072656d6f76652e202d2053746f726167653a2072656d6f766573206f6e65206974656d2e202d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d202d2042617365205765696768743a2034362e3731202b20302e3039202a2053202d204442205765696768743a20202020202d20526561643a204d756c74697369672053746f726167652c205b43616c6c6572204163636f756e745d20202020202d2057726974653a204d756c74697369672053746f726167652c205b43616c6c6572204163636f756e745d6f746865725f7369676e61746f7269657374696d65706f696e7454696d65706f696e743c543a3a426c6f636b4e756d6265723e63616c6c5f686173685b75383b2033325d20526567697374657220617070726f76616c20666f72206120646973706174636820746f206265206d6164652066726f6d20612064657465726d696e697374696320636f6d706f73697465206163636f756e7420696620617070726f766564206279206120746f74616c206f6620607468726573686f6c64202d203160206f6620606f746865725f7369676e61746f72696573602e205061796d656e743a20604d756c74697369674465706f73697442617365602077696c6c20626520726573657276656420696620746869732069732074686520666972737420617070726f76616c2c20706c757320607468726573686f6c64602074696d657320604d756c74697369674465706f736974466163746f72602e2049742069732072657475726e6564206f6e636520746869732064697370617463682068617070656e73206f722069732063616e63656c6c65642e202d20606d617962655f74696d65706f696e74603a20496620746869732069732074686520666972737420617070726f76616c2c207468656e2074686973206d75737420626520604e6f6e65602e204966206974206973206e6f742074686520666972737420617070726f76616c2c207468656e206974206d7573742062652060536f6d65602c2077697468207468652074696d65706f696e742028626c6f636b206e756d62657220616e64207472616e73616374696f6e20696e64657829206f662074686520666972737420617070726f76616c207472616e73616374696f6e2e204e4f54453a2049662074686973206973207468652066696e616c20617070726f76616c2c20796f752077696c6c2077616e7420746f20757365206061735f6d756c74696020696e73746561642e202d20557020746f206f6e652062696e6172792073656172636820616e6420696e736572742028604f286c6f6753202b20532960292e202d20492f4f3a2031207265616420604f285329602c20757020746f2031206d757461746520604f285329602e20557020746f206f6e652072656d6f76652e202d2053746f726167653a20696e7365727473206f6e65206974656d2c2076616c75652073697a6520626f756e64656420627920604d61785369676e61746f72696573602c207769746820612020206465706f7369742074616b656e20666f7220697473206c69666574696d65206f66202020604d756c74697369674465706f73697442617365202b207468726573686f6c64202a204d756c74697369674465706f736974466163746f72602e202d2042617365205765696768743a20202020202d204372656174653a2035362e33202b20302e313037202a205320202020202d20417070726f76653a2033392e3235202b20302e313231202a20536d617962655f74696d65706f696e744f7074696f6e3c54696d65706f696e743c543a3a426c6f636b4e756d6265723e3e2049662074686572652061726520656e6f7567682c207468656e206469737061746368207468652063616c6c2e202d206063616c6c603a205468652063616c6c20746f2062652065786563757465642e204e4f54453a20556e6c6573732074686973206973207468652066696e616c20617070726f76616c2c20796f752077696c6c2067656e6572616c6c792077616e7420746f207573652060617070726f76655f61735f6d756c74696020696e73746561642c2073696e6365206974206f6e6c7920726571756972657320612068617368206f66207468652063616c6c2e20526573756c74206973206571756976616c656e7420746f20746865206469737061746368656420726573756c7420696620607468726573686f6c64602069732065786163746c79206031602e204f7468657277697365206f6e20737563636573732c20726573756c7420697320604f6b6020616e642074686520726573756c742066726f6d2074686520696e746572696f722063616c6c2c206966206974207761732065786563757465642c206d617920626520666f756e6420696e20746865206465706f736974656420604d756c7469736967457865637574656460206576656e742e202d20604f2853202b205a202b2043616c6c29602e202d204f6e652063616c6c20656e636f6465202620686173682c20626f7468206f6620636f6d706c657869747920604f285a296020776865726520605a602069732074782d6c656e2e202d2054686520776569676874206f6620746865206063616c6c602e202d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d20202020202d204372656174653a2035392e32202b20302e303936202a205320c2b57320202020202d20417070726f76653a2034322e3237202b202e313136202a205320c2b57320202020202d20436f6d706c6574653a2035302e3931202b202e323332202a205320c2b57320202020202d2052656164733a204d756c74697369672053746f726167652c205b43616c6c6572204163636f756e745d20202020202d205772697465733a204d756c74697369672053746f726167652c205b43616c6c6572204163636f756e745d202d20506c75732043616c6c205765696768742053656e6420612063616c6c207468726f75676820616e20696e64657865642070736575646f6e796d206f66207468652073656e6465722e202d2042617365207765696768743a20322e38363320c2b573202d20506c75732074686520776569676874206f6620746865206063616c6c602053656e642061206261746368206f662064697370617463682063616c6c732e20546869732077696c6c206578656375746520756e74696c20746865206669727374206f6e65206661696c7320616e64207468656e2073746f702e204d61792062652063616c6c65642066726f6d20616e79206f726967696e2e202d206063616c6c73603a205468652063616c6c7320746f20626520646973706174636865642066726f6d207468652073616d65206f726967696e2e202d2042617365207765696768743a2031352e3634202b202e393837202a206320c2b573202d20506c7573207468652073756d206f66207468652077656967687473206f6620746865206063616c6c73602e202d20506c7573206f6e65206164646974696f6e616c206576656e742e202872657065617420726561642f77726974652920546869732077696c6c2072657475726e20604f6b6020696e20616c6c2063697263756d7374616e6365732e20546f2064657465726d696e65207468652073756363657373206f66207468652062617463682c20616e206576656e74206973206465706f73697465642e20496620612063616c6c206661696c656420616e64207468652062617463682077617320696e7465727275707465642c207468656e2074686520604261746368496e74657272757074656460206576656e74206973206465706f73697465642c20616c6f6e67207769746820746865206e756d626572206f66207375636365737366756c2063616c6c73206d61646520616e6420746865206572726f72206f6620746865206661696c65642063616c6c2e20496620616c6c2077657265207375636365737366756c2c207468656e2074686520604261746368436f6d706c6574656460206576656e74206973206465706f73697465642e63616c6c735665633c3c542061732054726169743e3a3a43616c6c3e000000000080d410000900000002050200000000007ac312000c000000000000009ac91000080000000000000089d410003400000000000000301a1300c0d410000000000000000000d0d410000100000000000000000000004d756c7469736967734d756c74697369673c543a3a426c6f636b4e756d6265722c2042616c616e63654f663c543e2c20543a3a4163636f756e7449643e0000004200000000000000010000005b000000d8d41000250000002054686520736574206f66206f70656e206d756c7469736967206f7065726174696f6e732e6d6f646c70792f7574696c697375626100000000000000c0ab12000d0000000000000060d610000100000000000000000000002fb910000f0000000000000068d610000100000000000000000000001eb91000110000000000000070d610000100000000000000000000000db91000110000000000000078d61000010000000000000000000000fbb81000120000000000000080d61000010000000000000000000000e6b81000150000000000000088d61000010000000000000000000000d3b81000130000000000000090d61000010000000000000000000000d0dc1000080000000000000098d61000010000000000000000000000fbda10000800000000000000a0d61000010000000000000000000000c8b810000b00000000000000a8d61000010000000000000000000000bab810000e00000000000000b0d61000010000000000000000000000a7b810001300000000000000b8d61000010000000000000049d910001d0000001dd910002c000000f5d8100028000000cad810002b0000009ed810002c0000005ad810004400000016d8100044000000ded710003800000092d710004c0000004ad7100048000000fed610004c000000c0d610003e00000020412074696d65706f696e742077617320676976656e2c20796574206e6f206d756c7469736967206f7065726174696f6e20697320756e6465727761792e204120646966666572656e742074696d65706f696e742077617320676976656e20746f20746865206d756c7469736967206f7065726174696f6e207468617420697320756e6465727761792e204e6f2074696d65706f696e742077617320676976656e2c2079657420746865206d756c7469736967206f7065726174696f6e20697320616c726561647920756e6465727761792e204f6e6c7920746865206163636f756e742074686174206f726967696e616c6c79206372656174656420746865206d756c74697369672069732061626c6520746f2063616e63656c2069742e204d756c7469736967206f7065726174696f6e206e6f7420666f756e64207768656e20617474656d7074696e6720746f2063616e63656c2e205468652073656e6465722077617320636f6e7461696e656420696e20746865206f74686572207369676e61746f726965733b2069742073686f756c646e27742062652e20546865207369676e61746f7269657320776572652070726f7669646564206f7574206f66206f726465723b20746865792073686f756c64206265206f7264657265642e2054686572652061726520746f6f206d616e79207369676e61746f7269657320696e20746865206c6973742e2054686572652061726520746f6f20666577207369676e61746f7269657320696e20746865206c6973742e2043616c6c20646f65736e2774206e65656420616e7920286d6f72652920617070726f76616c732e2043616c6c20697320616c726561647920617070726f7665642062792074686973207369676e61746f72792e205468726573686f6c6420697320746f6f206c6f7720287a65726f292e0000abd910000d00000090d910001b0000005c09120002000000a2a3120036000000e20200000100000042616420696e70757420646174612070726f766964656420746f20657865637574655f626c6f636bc0d9100010000000696e697469616c697a655f626c6f636bd8d910000f0000006170706c795f65787472696e73696300f0d9100013000000696e686572656e745f65787472696e73696373000cda10000f000000636865636b5f696e686572656e74730024da10001400000076616c69646174655f7472616e73616374696f6e40da10000f0000006f6666636861696e5f776f726b65720058da10000d0000006163636f756e745f6e6f6e6365000000fbea12000400000078da10000b0000006765745f73746f72616765008cda10000f00000072656e745f70726f6a656374696f6e00a4da10000a00000071756572795f696e666f0000b8da10001500000067656e65726174655f73657373696f6e5f6b657973000000d8da1000130000006465636f64655f73657373696f6e5f6b6579734e6f745472616e73666572496e5573654e6f744f776e65724e6f7441737369676e6564636c61696d7472616e7366657266726565666f7263655f7472616e736665724163636f756e74730000000000000090db10000d00000000000000a0db1000020000000000000000000000b0db1000010000000000000000000000b8db10000a00000000000000c4db1000010000000000000000000000ccdb10000100000000000000496e64657841737369676e656400000020af12000900000004dc10000c00000010dc10001e000000496e6465784672656564000004dc10000c000000d4db1000300000002041206163636f756e7420696e64657820686173206265656e2066726565642075702028756e61737369676e6564292e4163636f756e74496e6465782041206163636f756e7420696e646578207761732061737369676e65642e7061726974792f7374616b696e672d656c656374696f6e2f546f6f4d616e7952656769737472617273546f6f4d616e794669656c6473496e76616c6964546172676574496e76616c6964496e646578496e76616c69644a756467656d656e744a756467656d656e74476976656e537469636b794a756467656d656e744e6f4964656e746974794665654368616e676564456d707479496e6465784e6f744e616d65644e6f74466f756e64546f6f4d616e795375624163636f756e74736164645f7265676973747261727365745f6964656e746974797365745f73756273636c6561725f6964656e74697479726571756573745f6a756467656d656e7463616e63656c5f726571756573747365745f6665657365745f6163636f756e745f69647365745f6669656c647370726f766964655f6a756467656d656e746b696c6c5f6964656e7469747953757065724f6600000000b0de10000b0000000000000074ad1200010000000000000000000000bcde1000010000000000000000000000c4de10000f0000000000000084111200020000000000000000000000d4de1000010000000000000000000000dcde10000e0000000000000084111200020000000000000000000000ecde1000010000000000000000000000f4de1000120000000000000008df100002000000000000000000000018df100001000000000000000000000020df1000140000000000000008df100002000000000000000000000034df10000100000000000000000000008ddc10000e0000000000000008df10000200000000000000000000003cdf100001000000000000000000000044df10000e0000000000000054df10000100000000000000000000005cdf100001000000000000004964656e746974795365740060e010003c0000004964656e74697479436c6561726564002ce01000340000004964656e746974794b696c6c65640000fadf1000320000004a756467656d656e74526571756573746564000020af1200090000007bdf10000e000000d2df1000280000004a756467656d656e74556e726571756573746564afdf10002300000089df100026000000526567697374726172416464656400007bdf10000e00000064df100017000000204120726567697374726172207761732061646465642e526567697374726172496e6465782041206a756467656d656e742077617320676976656e2062792061207265676973747261722e2041206a756467656d656e74207265717565737420776173207265747261637465642e2041206a756467656d656e74207761732061736b65642066726f6d2061207265676973747261722e2041206e616d65207761732072656d6f76656420616e642074686520676976656e2062616c616e636520736c61736865642e2041206e616d652077617320636c65617265642c20616e642074686520676976656e2062616c616e63652072657475726e65642e2041206e616d652077617320736574206f72207265736574202877686963682077696c6c2072656d6f766520616c6c206a756467656d656e7473292e416c69766520636f6e7472616374206f7220746f6d6273746f6e6520616c72656164792065786973747300004200000000000000010000006d0000004200000000000000010000006400000074696d657374616d702073657420696e20626c6f636b20646f65736e2774206d6174636820736c6f7420696e207365616c4c6174656e657373636f6e74726163742073756273797374656d20726573756c74696e6720696e20706f73697469766520696d62616c616e63652100000000ade812000a000000000000000000000010f111000300000000000000000000000000000000000000000000000000000000000000301a13001ce510000000000000000000c4e4100001000000000000000100000000000000b7e812000b0000000000000000000000cce410002700000000000000000000000000000000000000000000000000000000000000301a1300f4e41000000000000000000004e5100001000000000000000100000000000000c2e812000b000000000000000000000010f111000300000000000000000000000000000000000000000000000000000000000000301a13001ce5100000000000000000000ce5100002000000000000000100000000000000cde812000b000000000000000000000010f111000300000000000000000000000000000000000000000000000000000000000000301a13001ce5100000000000000000002ce5100001000000000000000100000000000000d8e812000a000000000000000000000034e510001600000000000000000000000000000000000000000000000000000000000000301a13009ce5100000000000000000004ce510000a000000000000000100000000000000e2e812000e000000000000000000000034e510001600000000000000000000000000000000000000000000000000000000000000301a13009ce510000000000000000000ace5100001000000000000000100000000000000f0e812000c000000000000000000000060dc12000300000000000000000000000000000000000000000000000000000000000000301a130054e610000000000000000000b4e5100009000000000000000100000000000000fce8120011000000010500000000000060dc12000300000000000000fce510001d00000000000000000000000000000000000000301a13001ce610000000000000000000301a1300000000000000000001000000000000004df212000b00000000000000000000002ce610000800000000000000000000000000000000000000000000000000000000000000301a130034e61000000000000000000044e610000200000000000000000000000000000019e1100008000000000000000000000006cf12000e00000000000000000000000000000000000000000000000000000000000000301a130054e61000000000000000000064e61000050000000000000001000000b2eb1000150000005665633c28417574686f7269747949642c2042616265417574686f72697479576569676874293e004200000000000000010000005900000097eb10001b00000035eb10003e00000073eb1000240000004200000000000000010000006e00000020eb1000150000007363686e6f72726b656c3a3a52616e646f6d6e65737300005ae910002e000000301a13000000000088e910000b000000301a13000000000093e9100041000000d4e910003e00000012ea10004500000057ea1000450000009cea100041000000ddea1000430000004200000000000000010000006f00000043e9100017000000fee710001f000000301a1300000000001de810003d0000005ae81000400000009ae8100025000000301a130000000000bfe810003b000000fae81000420000003ce91000070000005665633c7363686e6f72726b656c3a3a5261775652464f75747075743e000000420000000000000001000000590000004d617962655672664200000000000000010000005b00000077e7100040000000b7e7100047000000420000000000000001000000570000008ce6100036000000301a130000000000c2e610004500000007e71000440000004be710002c00000020486f77206c617465207468652063757272656e7420626c6f636b20697320636f6d706172656420746f2069747320706172656e742e205468697320656e74727920697320706f70756c617465642061732070617274206f6620626c6f636b20657865637574696f6e20616e6420697320636c65616e6564207570206f6e20626c6f636b2066696e616c697a6174696f6e2e205175657279696e6720746869732073746f7261676520656e747279206f757473696465206f6620626c6f636b20657865637574696f6e20636f6e746578742073686f756c6420616c77617973207969656c64207a65726f2e2054656d706f726172792076616c75652028636c656172656420617420626c6f636b2066696e616c697a6174696f6e292077686963682069732060536f6d6560206966207065722d626c6f636b20696e697469616c697a6174696f6e2068617320616c7265616479206265656e2063616c6c656420666f722063757272656e7420626c6f636b2e2052616e646f6d6e65737320756e64657220636f6e737472756374696f6e2e205765206d616b6520612074726164656f6666206265747765656e2073746f7261676520616363657373657320616e64206c697374206c656e6774682e2057652073746f72652074686520756e6465722d636f6e737472756374696f6e2072616e646f6d6e65737320696e207365676d656e7473206f6620757020746f2060554e4445525f434f4e535452554354494f4e5f5345474d454e545f4c454e475448602e204f6e63652061207365676d656e7420726561636865732074686973206c656e6774682c20776520626567696e20746865206e657874206f6e652e20576520726573657420616c6c207365676d656e747320616e642072657475726e20746f206030602061742074686520626567696e6e696e67206f662065766572792065706f63682e204e6578742065706f63682072616e646f6d6e6573732e205468652065706f63682072616e646f6d6e65737320666f7220746865202a63757272656e742a2065706f63682e20232053656375726974792054686973204d555354204e4f54206265207573656420666f722067616d626c696e672c2061732069742063616e20626520696e666c75656e6365642062792061206d616c6963696f75732076616c696461746f7220696e207468652073686f7274207465726d2e204974204d4159206265207573656420696e206d616e792063727970746f677261706869632070726f746f636f6c732c20686f77657665722c20736f206c6f6e67206173206f6e652072656d656d626572732074686174207468697320286c696b652065766572797468696e6720656c7365206f6e2d636861696e29206974206973207075626c69632e20466f72206578616d706c652c2069742063616e20626520757365642077686572652061206e756d626572206973206e656564656420746861742063616e6e6f742068617665206265656e2063686f73656e20627920616e206164766572736172792c20666f7220707572706f7365732073756368206173207075626c69632d636f696e207a65726f2d6b6e6f776c656467652070726f6f66732e2043757272656e7420736c6f74206e756d6265722e2054686520736c6f74206174207768696368207468652066697273742065706f63682061637475616c6c7920737461727465642e2054686973206973203020756e74696c2074686520666972737420626c6f636b206f662074686520636861696e2e2043757272656e742065706f636820617574686f7269746965732e2043757272656e742065706f636820696e6465782e000000000038ec10000d0000000000000010f111000300000000000000301a130048ec1000000000000000000058ec100002000000000000000000000068ec10001100000000000000383311000900000000000000301a13007cec100000000000000000008cec1000050000000000000045706f63684475726174696f6e00000042000000000000000100000070000000e4ed10004300000027ee10003f0000004578706563746564426c6f636b54696d6500000042000000000000000100000071000000b4ec100041000000f5ec10004400000039ed1000410000007aed100042000000bced10002800000020546865206578706563746564206176657261676520626c6f636b2074696d6520617420776869636820424142452073686f756c64206265206372656174696e6720626c6f636b732e2053696e636520424142452069732070726f626162696c6973746963206974206973206e6f74207472697669616c20746f20666967757265206f7574207768617420746865206578706563746564206176657261676520626c6f636b2074696d652073686f756c64206265206261736564206f6e2074686520736c6f74206475726174696f6e20616e642074686520736563757269747920706172616d657465722060636020287768657265206031202d20636020726570726573656e7473207468652070726f626162696c697479206f66206120736c6f74206265696e6720656d707479292e20546865206e756d626572206f66202a2a736c6f74732a2a207468617420616e2065706f63682074616b65732e20576520636f75706c652073657373696f6e7320746f2065706f6368732c20692e652e2077652073746172742061206e65772073657373696f6e206f6e636520746865206e65772065706f636820626567696e732e65706f636820696e64696365732077696c6c206e6576657220726561636820325e3634206265666f726520746865206465617468206f662074686520756e6976657273653b2071656400d0ee100030000000790100001b000000d0ee10003000000081010000200000002f686f6d652f6461766964642f6465762f7375627374726174652f6672616d652f626162652f7372632f6c69622e7273000000000edb10000500000000000000b0ef1000010000000000000000000000c8ef100010000000000000000000000013db1000080000000000000048f0100002000000000000000000000078f010001000000000000000000000001bdb10000400000000000000b0ef1000010000000000000000000000f8f010001000000000000000000000001fdb10000e0000000000000048f0100002000000000000000000000078f1100010000000000000000000000098d912000500000000000000e6f510000f000000f5f5100027000000301a1300000000001cf6100038000000301a13000000000098c9120034000000301a13000000000054f610003d000000301a1300000000003df3100025000000301a130000000000f5bd12000b000000184a11000a00000062f3100027000000e2f41000190000002bc112000d00000044be12000c000000000000008421120003000000000000007ac312000c0000000000000098d912000500000000000000e6f510000f000000fbf410005800000053f510002f000000301a13000000000098c9120034000000301a13000000000082f510004a000000e5f2100058000000301a1300000000003df3100025000000301a130000000000f5bd12000b000000184a11000a00000062f3100027000000ccf510001a0000002bc112000d00000044be12000c000000a8f3100026000000301a130000000000cef3100058000000301a13000000000026f4100056000000301a1300000000007cf4100044000000301a130000000000c0f4100022000000301a130000000000f5bd12000b000000184a11000a00000062f3100027000000e2f41000190000002bc112000d00000044be12000c000000f8f11000560000004ef210003b000000301a13000000000089f2100032000000301a130000000000bbf210002a000000e5f2100058000000301a1300000000003df3100025000000301a130000000000f5bd12000b000000184a11000a00000062f310002700000089f310001f0000002bc112000d00000044be12000c00000020466f72636520616e20696e64657820746f20616e206163636f756e742e205468697320646f65736e277420726571756972652061206465706f7369742e2049662074686520696e64657820697320616c72656164792068656c642c207468656e20616e79206465706f736974206973207265696d62757273656420746f206974732063757272656e74206f776e65722e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f526f6f745f2e202d2060696e646578603a2074686520696e64657820746f206265202872652d2961737369676e65642e202d20606e6577603a20746865206e6577206f776e6572206f662074686520696e6465782e20546869732066756e6374696f6e2069732061206e6f2d6f7020696620697420697320657175616c20746f2073656e6465722e20456d6974732060496e64657841737369676e656460206966207375636365737366756c2e202d204f6e652073746f72616765206d75746174696f6e2028636f64656320604f28312960292e202d20557020746f206f6e652072657365727665206f7065726174696f6e2e204672656520757020616e20696e646578206f776e6564206279207468652073656e6465722e205061796d656e743a20416e792070726576696f7573206465706f73697420706c6163656420666f722074686520696e64657820697320756e726573657276656420696e207468652073656e646572206163636f756e742e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e64207468652073656e646572206d757374206f776e2074686520696e6465782e202d2060696e646578603a2074686520696e64657820746f2062652066726565642e2054686973206d757374206265206f776e6564206279207468652073656e6465722e20456d6974732060496e646578467265656460206966207375636365737366756c2e202d204f6e652072657365727665206f7065726174696f6e2e2041737369676e20616e20696e64657820616c7265616479206f776e6564206279207468652073656e64657220746f20616e6f74686572206163636f756e742e205468652062616c616e6365207265736572766174696f6e206973206566666563746976656c79207472616e7366657272656420746f20746865206e6577206163636f756e742e202d2060696e646578603a2074686520696e64657820746f2062652072652d61737369676e65642e2054686973206d757374206265206f776e6564206279207468652073656e6465722e202d204f6e65207472616e73666572206f7065726174696f6e2e543a3a4163636f756e74496e6465782041737369676e20616e2070726576696f75736c7920756e61737369676e656420696e6465782e205061796d656e743a20604465706f736974602069732072657365727665642066726f6d207468652073656e646572206163636f756e742e202d2060696e646578603a2074686520696e64657820746f20626520636c61696d65642e2054686973206d757374206e6f7420626520696e207573652e000000000000002ddb1000080000000102000000000000e6f510000f00000000000000ecf610001c00000000000000000000000000000000000000301a130008f71000000000000000000018f7100001000000000000000000000028543a3a4163636f756e7449642c2042616c616e63654f663c543e294200000000000000010000005b00000020f710002200000020546865206c6f6f6b75702066726f6d20696e64657820746f206163636f756e742e000000000000eadc10000d0000000000000004b9120001000000000000000000000028f910000e0000000000000000000000f7dc10000c0000000000000098f91000010000000000000000000000b0f9100014000000000000000000000003dd1000080000000000000050fa100001000000000000000000000068fa10001600000000000000000000000bdd10000e00000000000000301a130000000000000000000000000018fb100015000000000000000000000019dd10001100000000000000c0fb1000020000000000000000000000f0fb10001800000000000000000000002add10000e00000000000000b0fc1000010000000000000000000000c8fc100012000000000000000000000038dd1000070000000000000058fd100002000000000000000000000088fd10000d00000000000000000000003fdd10000e00000000000000f0fd100002000000000000000000000020fe10000d00000000000000000000004ddd10000a0000000000000088fe1000020000000000000000000000b8fe10000d000000000000000000000057dd1000110000000000000020ff100003000000000000000000000068ff100014000000000000000000000068dd10000d00000000000000b4471100010000000000000000000000080011001400000000000000841311001f000000301a130000000000a313110047000000301a130000000000ea1311002b000000301a1300000000001514110026000000301a130000000000f5bd12000b0000003b1411004a00000085141100270000002bc112000d000000ac1411003900000044be12000c00000000000000741311000400000000000000781311000c000000341111004b000000301a1300000000007f11110056000000d511110015000000301a13000000000098c9120034000000301a130000000000ea11110024000000301a1300000000000e12110023000000301a130000000000f5bd12000b000000311211001200000043121100480000008b12110039000000c412110021000000e5121100490000002bc112000d0000002e1311004600000044be12000c000000000000001711110004000000000000001b11110019000000a10e110024000000301a130000000000c50e1100560000001b0f11004c000000301a1300000000005b0c110059000000b40c11000a000000301a130000000000670f11002d000000301a130000000000f5bd12000b000000940f11000d000000a10f11003a0000002a0d110036000000db0f110022000000fd0f11000600000003101100380000003b101100300000006b101100310000009c10110035000000d11011004600000044be12000c000000d00b11004f000000301a1300000000001f0c11003c000000301a1300000000005b0c110059000000b40c11000a000000301a130000000000be0c110027000000301a130000000000f5bd12000b000000e50c110011000000f60c1100340000002a0d110036000000600d110049000000a90d110023000000cc0d1100330000002bc112000d000000ff0d11000e0000000d0e11004b000000580e11004900000044be12000c000000000000008c0511000900000000000000950511001700000000000000c90b110007000000000000008075120015000000cb09110026000000301a130000000000f109110056000000470a110007000000301a130000000000810811004e000000cf08110015000000301a1300000000004e0a110048000000960a110056000000301a130000000000ec0a11000d000000f90a11002f000000280b110004000000301a1300000000002c0b11002a000000301a130000000000f5bd12000b000000c10411000e000000bd02110021000000560b11002f0000002bc112000d000000850b11004400000044be12000c000000000000008c05110009000000000000007bdf10000e000000270811001b000000301a130000000000420811003f000000301a130000000000810811004e000000cf08110015000000301a130000000000e408110052000000301a130000000000360911002c000000301a130000000000f5bd12000b000000c10411000e000000bd0211002100000062091100230000002bc112000d000000850911004600000044be12000c0000000000000098d91200050000000000000095051100170000000000000024081100030000000000000080751200150000008d07110047000000301a1300000000007c03110056000000ee05110029000000301a130000000000170611003e000000d407110016000000301a130000000000f5bd12000b0000006c8711000a000000990611001f000000ea0711003a00000044be12000c0000000000000098d9120005000000000000009505110017000000000000008421120003000000000000007ac312000c0000000607110030000000301a1300000000007c03110056000000ee05110029000000301a130000000000170611003e000000360711001d000000301a130000000000f5bd12000b0000006c8711000a000000990611001f000000530711003a00000044be12000c0000000000000098d912000500000000000000950511001700000000000000f20611000600000000000000f80611000e000000c30511002b000000301a1300000000007c03110056000000ee05110029000000301a130000000000170611003e0000005506110044000000301a130000000000f5bd12000b0000006c8711000a000000990611001f000000b80611003a00000044be12000c000000000000008c0511000900000000000000950511001700000000000000834b11000600000000000000f320120023000000000000004e3712000900000000000000ac051100170000004d0311002f000000301a1300000000007c03110056000000d20311002d000000301a130000000000ff031100490000001102110056000000670211001e0000004804110053000000301a1300000000009b04110026000000301a130000000000f5bd12000b000000c10411000e000000cf04110022000000f104110026000000170511002f0000002bc112000d000000460511004600000044be12000c000000a800110051000000301a130000000000f9001100590000005201110052000000a401110021000000301a130000000000c50111004c000000301a1300000000001102110056000000670211001e000000301a1300000000008502110026000000301a130000000000f5bd12000b000000ab02110012000000bd02110021000000de0211001d0000002bc112000d000000fb0211005200000044be12000c0000002052656d6f766520616e206163636f756e742773206964656e7469747920616e64207375622d6163636f756e7420696e666f726d6174696f6e20616e6420736c61736820746865206465706f736974732e205061796d656e743a2052657365727665642062616c616e6365732066726f6d20607365745f737562736020616e6420607365745f6964656e74697479602061726520736c617368656420616e642068616e646c65642062792060536c617368602e20566572696669636174696f6e2072657175657374206465706f7369747320617265206e6f742072657475726e65643b20746865792073686f756c642062652063616e63656c6c6564206d616e75616c6c79207573696e67206063616e63656c5f72657175657374602e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f526f6f745f206f72206d617463682060543a3a466f7263654f726967696e602e202d2060746172676574603a20746865206163636f756e742077686f7365206964656e7469747920746865206a756467656d656e742069732075706f6e2e2054686973206d75737420626520616e206163636f756e742020207769746820612072656769737465726564206964656e746974792e20456d69747320604964656e746974794b696c6c656460206966207375636365737366756c2e202d20604f2852202b2053202b205829602e202d204f6e652062616c616e63652d72657365727665206f7065726174696f6e2e202d206053202b2032602073746f72616765206d75746174696f6e732e202d2042656e63686d61726b3a203130312e39202b2052202a20302e303931202b2053202a20322e353839202b2058202a20302e38373120c2b57320286d696e207371756172657320616e616c79736973292050726f766964652061206a756467656d656e7420666f7220616e206163636f756e742773206964656e746974792e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e64207468652073656e646572206d75737420626520746865206163636f756e74206f6620746865207265676973747261722077686f736520696e64657820697320607265675f696e646578602e202d20607265675f696e646578603a2074686520696e646578206f6620746865207265676973747261722077686f7365206a756467656d656e74206973206265696e67206d6164652e202d20606a756467656d656e74603a20746865206a756467656d656e74206f662074686520726567697374726172206f6620696e64657820607265675f696e646578602061626f75742060746172676574602e20456d69747320604a756467656d656e74476976656e60206966207375636365737366756c2e202d20604f2852202b205829602e202d204f6e652062616c616e63652d7472616e73666572206f7065726174696f6e2e202d20557020746f206f6e65206163636f756e742d6c6f6f6b7570206f7065726174696f6e2e202d2053746f726167653a2031207265616420604f285229602c2031206d757461746520604f2852202b205829602e202d2042656e63686d61726b3a2034372e3737202b2052202a20302e333336202b2058202a20312e36363420c2b57320286d696e207371756172657320616e616c79736973297265675f696e646578436f6d706163743c526567697374726172496e6465783e4a756467656d656e743c42616c616e63654f663c543e3e2053657420746865206669656c6420696e666f726d6174696f6e20666f722061207265676973747261722e206f6620746865207265676973747261722077686f736520696e6465782069732060696e646578602e202d2060696e646578603a2074686520696e646578206f6620746865207265676973747261722077686f73652066656520697320746f206265207365742e202d20606669656c6473603a20746865206669656c64732074686174207468652072656769737472617220636f6e6365726e73207468656d73656c76657320776974682e202d204f6e652073746f72616765206d75746174696f6e20604f285229602e202d2042656e63686d61726b3a20382e393835202b2052202a20302e34313320c2b57320286d696e207371756172657320616e616c79736973296669656c64734964656e746974794669656c6473204368616e676520746865206163636f756e74206173736f63696174656420776974682061207265676973747261722e202d20606e6577603a20746865206e6577206163636f756e742049442e202d2042656e63686d61726b3a2031302e3035202b2052202a20302e34333820c2b57320286d696e207371756172657320616e616c797369732920536574207468652066656520726571756972656420666f722061206a756467656d656e7420746f206265207265717565737465642066726f6d2061207265676973747261722e202d2060666565603a20746865206e6577206665652e202d2042656e63686d61726b3a20382e383438202b2052202a20302e34323520c2b57320286d696e207371756172657320616e616c79736973296665652043616e63656c20612070726576696f757320726571756573742e205061796d656e743a20412070726576696f75736c79207265736572766564206465706f7369742069732072657475726e6564206f6e20737563636573732e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e64207468652073656e646572206d757374206861766520612072656769737465726564206964656e746974792e202d20607265675f696e646578603a2054686520696e646578206f6620746865207265676973747261722077686f7365206a756467656d656e74206973206e6f206c6f6e676572207265717565737465642e20456d69747320604a756467656d656e74556e72657175657374656460206966207375636365737366756c2e202d204f6e652073746f72616765206d75746174696f6e20604f2852202b205829602e202d2042656e63686d61726b3a2035302e3035202b2052202a20302e333231202b2058202a20312e36383820c2b57320286d696e207371756172657320616e616c797369732920526571756573742061206a756467656d656e742066726f6d2061207265676973747261722e205061796d656e743a204174206d6f737420606d61785f666565602077696c6c20626520726573657276656420666f72207061796d656e7420746f2074686520726567697374726172206966206a756467656d656e7420676976656e2e202d20607265675f696e646578603a2054686520696e646578206f6620746865207265676973747261722077686f7365206a756467656d656e74206973207265717565737465642e202d20606d61785f666565603a20546865206d6178696d756d206665652074686174206d617920626520706169642e20546869732073686f756c64206a757374206265206175746f2d706f70756c617465642061733a206060606e6f636f6d70696c652053656c663a3a7265676973747261727328292e676574287265675f696e646578292e756e7772617028292e6665652060606020456d69747320604a756467656d656e7452657175657374656460206966207375636365737366756c2e202d2053746f726167653a2031207265616420604f285229602c2031206d757461746520604f2858202b205229602e202d2042656e63686d61726b3a2035392e3032202b2052202a20302e343838202b2058202a20312e3720c2b57320286d696e207371756172657320616e616c79736973296d61785f66656520436c65617220616e206163636f756e742773206964656e7469747920696e666f20616e6420616c6c207375622d6163636f756e747320616e642072657475726e20616c6c206465706f736974732e205061796d656e743a20416c6c2072657365727665642062616c616e636573206f6e20746865206163636f756e74206172652072657475726e65642e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e64207468652073656e646572206d757374206861766520612072656769737465726564206964656e746974792e20456d69747320604964656e74697479436c656172656460206966207375636365737366756c2e202d20604f2852202b2053202b205829602020202d20776865726520605260207265676973747261722d636f756e742028676f7665726e616e63652d626f756e646564292e2020202d2077686572652060536020737562732d636f756e742028686172642d20616e64206465706f7369742d626f756e646564292e2020202d20776865726520605860206164646974696f6e616c2d6669656c642d636f756e7420286465706f7369742d626f756e64656420616e6420636f64652d626f756e646564292e202d204f6e652062616c616e63652d756e72657365727665206f7065726174696f6e2e202d206032602073746f7261676520726561647320616e64206053202b2032602073746f726167652064656c6574696f6e732e202d2042656e63686d61726b733a2020202d2035372e3336202b2052202a20302e303139202b2053202a20322e353737202b2058202a20302e38373420c2b57320286d656469616e20736c6f70657320616e616c79736973292020202d2035372e3036202b2052202a20302e303036202b2053202a20322e353739202b2058202a20302e38373820c2b57320286d696e207371756172657320616e616c79736973292053657420746865207375622d6163636f756e7473206f66207468652073656e6465722e205061796d656e743a20416e79206167677265676174652062616c616e63652072657365727665642062792070726576696f757320607365745f73756273602063616c6c732077696c6c2062652072657475726e656420616e6420616e20616d6f756e7420605375624163636f756e744465706f736974602077696c6c20626520726573657276656420666f722065616368206974656d20696e206073756273602e202d206073756273603a20546865206964656e74697479277320286e657729207375622d6163636f756e74732e202d20604f2850202b205329602020202d20776865726520605060206f6c642d737562732d636f756e742028686172642d20616e64206465706f7369742d626f756e646564292e202d204174206d6f7374206f6e652062616c616e6365206f7065726174696f6e732e202d2044423a2020202d206050202b2053602073746f72616765206d75746174696f6e732028636f64656320636f6d706c657869747920604f28312960292020202d204f6e652073746f7261676520726561642028636f64656320636f6d706c657869747920604f28502960292e2020202d204f6e652073746f726167652077726974652028636f64656320636f6d706c657869747920604f28532960292e2020202d204f6e652073746f726167652d6578697374732028604964656e746974794f663a3a636f6e7461696e735f6b657960292e202d2042656e63686d61726b3a2033392e3433202b2050202a20322e353232202b2053202a20332e36393820c2b57320286d696e207371756172657320616e616c7973697329737562735665633c28543a3a4163636f756e7449642c2044617461293e2053657420616e206163636f756e742773206964656e7469747920696e666f726d6174696f6e20616e6420726573657276652074686520617070726f707269617465206465706f7369742e20496620746865206163636f756e7420616c726561647920686173206964656e7469747920696e666f726d6174696f6e2c20746865206465706f7369742069732074616b656e2061732070617274207061796d656e7420666f7220746865206e6577206465706f7369742e202d2060696e666f603a20546865206964656e7469747920696e666f726d6174696f6e2e20456d69747320604964656e7469747953657460206966207375636365737366756c2e202d20604f2858202b205827202b205229602020202d20776865726520605860206164646974696f6e616c2d6669656c642d636f756e7420286465706f7369742d626f756e64656420616e6420636f64652d626f756e646564292020202d20776865726520605260206a756467656d656e74732d636f756e7420287265676973747261722d636f756e742d626f756e64656429202d204f6e652062616c616e63652072657365727665206f7065726174696f6e2e202d204f6e652073746f72616765206d75746174696f6e2028636f6465632d7265616420604f285827202b205229602c20636f6465632d777269746520604f2858202b20522960292e202d2042656e63686d61726b3a2035392e3434202b2052202a20302e333839202b2058202a20312e34333420c2b57320286d696e207371756172657320616e616c7973697329696e666f4964656e74697479496e666f2041646420612072656769737472617220746f207468652073797374656d2e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d75737420626520605265676973747261724f726967696e60206f722060526f6f74602e202d20606163636f756e74603a20746865206163636f756e74206f6620746865207265676973747261722e20456d6974732060526567697374726172416464656460206966207375636365737366756c2e202d20604f2852296020776865726520605260207265676973747261722d636f756e742028676f7665726e616e63652d626f756e64656420616e6420636f64652d626f756e646564292e202d204f6e652073746f72616765206d75746174696f6e2028636f64656320604f28522960292e202d2042656e63686d61726b3a2032342e3633202b2052202a20302e353320c2b57320286d696e207371756172657320616e616c797369732900000000000000481611000a00000001050000000000007ac312000c00000000000000521611001a00000000000000000000000000000000000000301a13006c16110000000000000000007c1611000100000000000000000000000000000075dd10000700000001020000000000007ac312000c00000000000000841611001400000000000000000000000000000000000000301a1300981611000000000000000000a816110002000000000000000000000000000000b81611000600000001050000000000007ac312000c00000000000000a48f11002100000000000000000000000000000000000000301a1300c01611000000000000000000d016110003000000000000000100000000000000e81611000a0000000000000000000000f21611003600000000000000000000000000000000000000000000000000000000000000301a1300281711000000000000000000381711000400000000000000010000004964656e746974794f66526567697374726174696f6e3c42616c616e63654f663c543e3e4200000000000000010000005b000000401911004800000028543a3a4163636f756e7449642c2044617461294200000000000000010000005b0000009418110058000000ec18110054000000537562734f660000420000000000000001000000660000001f1811002e000000301a1300000000004d18110047000000526567697374726172735665633c4f7074696f6e3c526567697374726172496e666f3c42616c616e63654f663c543e2c20543a3a4163636f756e7449643e3e3e420000000000000001000000590000005817110053000000ab1711002a000000301a130000000000d51711004a0000002054686520736574206f6620726567697374726172732e204e6f7420657870656374656420746f206765742076657279206269672061732063616e206f6e6c79206265206164646564207468726f7567682061207370656369616c206f726967696e20286c696b656c79206120636f756e63696c206d6f74696f6e292e2054686520696e64657820696e746f20746869732063616e206265206361737420746f2060526567697374726172496e6465786020746f2067657420612076616c69642076616c75652e20416c7465726e6174697665202273756222206964656e746974696573206f662074686973206163636f756e742e20546865206669727374206974656d20697320746865206465706f7369742c20746865207365636f6e64206973206120766563746f72206f6620746865206163636f756e74732e205468652073757065722d6964656e74697479206f6620616e20616c7465726e6174697665202273756222206964656e7469747920746f676574686572207769746820697473206e616d652c2077697468696e207468617420636f6e746578742e20496620746865206163636f756e74206973206e6f7420736f6d65206f74686572206163636f756e742773207375622d6964656e746974792c207468656e206a75737420604e6f6e65602e20496e666f726d6174696f6e20746861742069732070657274696e656e7420746f206964656e746966792074686520656e7469747920626568696e6420616e206163636f756e742e00000000d81a11000c00000000000000b66c12000c00000000000000301a1300e41a11000000000000000000f41a1100010000000000000000000000fc1a11000c00000000000000b66c12000c00000000000000301a1300081b11000000000000000000181b1100010000000000000000000000201b11001100000000000000b66c12000c00000000000000301a1300341b11000000000000000000441b11000300000000000000000000005c1b11000e0000000000000060dc12000300000000000000301a1300881b110000000000000000006c1b1100010000000000000000000000741b1100130000000000000060dc12000300000000000000301a1300881b11000000000000000000981b1100020000000000000000000000a81b11000d0000000000000060dc12000300000000000000301a1300b81b11000000000000000000c81b1100020000000000000042617369634465706f73697442000000000000000100000067000000691e1100360000004669656c644465706f736974420000000000000001000000720000001e1e11004b0000005375624163636f756e744465706f736974000000420000000000000001000000730000001f1d110059000000781d11005c000000d41d11004a0000004d61785375624163636f756e74730000dc1c1100430000004d61784164646974696f6e616c4669656c647300420000000000000001000000740000004b1c110059000000a41c1100380000004d61785265676973747261727300000042000000000000000100000075000000d81b1100540000002c1c11001f000000204d61786d696d756d206e756d626572206f66207265676973747261727320616c6c6f77656420696e207468652073797374656d2e204e656564656420746f20626f756e642074686520636f6d706c6578697479206f662c20652e672e2c207570646174696e67206a756467656d656e74732e204d6178696d756d206e756d626572206f66206164646974696f6e616c206669656c64732074686174206d61792062652073746f72656420696e20616e2049442e204e656564656420746f20626f756e642074686520492f4f20726571756972656420746f2061636365737320616e206964656e746974792c206275742063616e2062652070726574747920686967682e20546865206d6178696d756d206e756d626572206f66207375622d6163636f756e747320616c6c6f77656420706572206964656e746966696564206163636f756e742e2054686520616d6f756e742068656c64206f6e206465706f73697420666f7220612072656769737465726564207375626163636f756e742e20546869732073686f756c64206163636f756e7420666f722074686520666163742074686174206f6e652073746f72616765206974656d27732076616c75652077696c6c20696e637265617365206279207468652073697a65206f6620616e206163636f756e742049442c20616e642074686572652077696c6c20626520616e6f746865722074726965206974656d2077686f73652076616c7565206973207468652073697a65206f6620616e206163636f756e7420494420706c75732033322062797465732e2054686520616d6f756e742068656c64206f6e206465706f73697420706572206164646974696f6e616c206669656c6420666f7220612072656769737465726564206964656e746974792e2054686520616d6f756e742068656c64206f6e206465706f73697420666f7220612072656769737465726564206964656e746974792e00d4f31200340000004a0300001d000000d4f31200340000001e0400003600000000000000d8dc100012000000000000002c201100010000000000000000000000d0dc1000080000000000000034201100010000000000000000000000c8dc100008000000000000003c201100010000000000000000000000bedc10000a0000000000000044201100010000000000000000000000b4dc10000a000000000000004c201100010000000000000000000000aadc10000a00000000000000542011000100000000000000000000009bdc10000f000000000000005c2011000100000000000000000000008ddc10000e00000000000000642011000100000000000000000000007ddc100010000000000000006c20110001000000000000000000000071dc10000c000000000000007420110001000000000000000000000064dc10000d000000000000007c20110001000000000000000000000057dc10000d000000000000008420110001000000000000000000000046dc100011000000000000008c2011000100000000000000a82111001800000093211100150000007e21110015000000712111000d00000061211100100000004e211100130000003c211100120000002b2111001100000018211100130000000221110016000000eb20110017000000cf2011001c000000942011003b000000204d6178696d756d20616d6f756e74206f66207265676973747261727320726561636865642e2043616e6e6f742061646420616e79206d6f72652e20546f6f206d616e79206164646974696f6e616c206669656c64732e205468652074617267657420697320696e76616c69642e2054686520696e64657820697320696e76616c69642e20496e76616c6964206a756467656d656e742e204a756467656d656e7420676976656e2e20537469636b79206a756467656d656e742e204e6f206964656e7469747920666f756e642e20466565206973206368616e6765642e20456d70747920696e6465782e204163636f756e742069736e2774206e616d65642e204163636f756e742069736e277420666f756e642e20546f6f206d616e7920737562732d6163636f756e74732e54696d657374616d70206d7573742062652075706461746564206f6e636520696e2074686520626c6f636b4e6f774475706c696361746564486561727462656174496e76616c69644b65796865617274626561744865617274626561744166746572000000000000a82211001100000000000000bc221100010000000000000000000000c4221100010000000000000000000000cc2211000700000000000000301a1300000000000000000000000000d4221100010000000000000000000000dc2211000b00000000000000e8221100010000000000000000000000f022110001000000000000004865617274626561745265636569766564000000c12311000b0000009123110030000000416c6c476f6f64005c23110035000000536f6d654f66666c696e65004423110018000000f82211004c0000002041742074686520656e64206f66207468652073657373696f6e2c206174206c65617374206f6e63652076616c696461746f722077617320666f756e6420746f206265206f66666c696e652e5665633c4964656e74696669636174696f6e5475706c653e2041742074686520656e64206f66207468652073657373696f6e2c206e6f206f6666656e63652077617320636f6d6d69747465642e2041206e657720686561727462656174207761732072656365697665642066726f6d2060417574686f72697479496460417574686f72697479496473657400617474656d707420746f20646976696465206279207a65726f000000760000001000000004000000770000000b221100090000004765747320616e64206465636f6465732074696d657374616d7020696e686572656e7420646174613c24110035000000e80000001f0000002f686f6d652f6461766964642f6465762f7375627374726174652f6672616d652f74696d657374616d702f7372632f6c69622e7273417574686f726564426c6f636b7300902411002e000000be2411000d0000004552524f523a2072657475726e6564206e6578745f6b657920686173206e6f2076616c75653a0a6b6579206973200a6e6578745f6b6579206973200039251100160000005c0912000200000039251100160000004f25110012000000696d6f6e6c696e6570616c6c65745f696d5f6f6e6c696e652f686f6d652f6461766964642f6465762f7375627374726174652f6672616d652f696d2d6f6e6c696e652f7372632f6c69622e7273536b697070696e6720686561727462656174206174202e204e6f7420612076616c696461746f722e000000732611001c000000452611002e000000132611001a0000002d26110018000000f72511000a0000000126110012000000df25110018000000c925110016000000ac2511001d0000004661696c656420746f206665746368206e6574776f726b2073746174654661696c656420746f2061637175697265206c6f636b4661696c656420746f207369676e20686561727462656174417574686f726974792020697320616c7265616479206f6e6c696e6548656172746265617420616c72656164792073656e74206174202e2057616974696e6720666f7220696e636c7573696f6e2e546f6f206561726c7920746f2073656e64206865617274626561742c206e657874206578706563746564206174204661696c656420746f207375626d6974207472616e73616374696f6e00042511003500000026020000340000007061726974792f696d2d6f6e6c696e652d6865617274626561742f00dc26110008000000e426110020000000042711000b0000009de91200030000005b696e6465783a205d205265706f7274696e6720696d2d6f6e6c696e6520617420626c6f636b3a20202873657373696f6e3a2000301a130000000000301a1300000000004200000004000000040000007800000042000000040000000400000078000000506172656e7420686173682073686f756c642062652076616c69642e5472616e73616374696f6e207472696520726f6f74206d7573742062652076616c69642ef527110032000000446967657374206974656d206d757374206d6174636820746861742063616c63756c617465642e53746f7261676520726f6f74206d757374206d6174636820746861742063616c63756c617465642e5369676e617475726520766572696669636174696f6e206661696c65642e4e756d626572206f6620646967657374206974656d73206d757374206d6174636820746861742063616c63756c617465642e00000000000b221100090000000000000054281100020000000000000000000000842811000a00000000000000000000000b22110009000000000000001f2a11001900000000000000382a11000a00000000000000422a11002f000000f5bd12000b000000d4281100480000001c2911002d000000301a13000000000049291100230000006c2911002c000000982911004f000000e729110017000000fe2911002100000044be12000c000000202d20436f6d706c65786974793a20604f284b202b20452960207768657265204b206973206c656e677468206f6620604b6579736020616e642045206973206c656e677468206f66202020604865617274626561742e6e6574776f726b5f73746174652e65787465726e616c5f61646472657373602020202d20604f284b29603a206465636f64696e67206f66206c656e67746820604b602020202d20604f284529603a206465636f64696e672f656e636f64696e67206f66206c656e67746820604560202d20446252656164733a2070616c6c65745f73657373696f6e206056616c696461746f7273602c2070616c6c65745f73657373696f6e206043757272656e74496e646578602c20604b657973602c2020206052656365697665644865617274626561747360202d2044625772697465733a2060526563656976656448656172746265617473604865617274626561743c543a3a426c6f636b4e756d6265723e5f7369676e61747572653c543a3a417574686f7269747949642061732052756e74696d654170705075626c69633e3a3a5369676e617475726500000000000000142211000e000000000000000000000006cf12000e00000000000000000000000000000000000000000000000000000000000000301a13005c2c11000000000000000000d42b1100060000000000000001000000000000008fe81200040000000000000000000000042c11001300000000000000000000000000000000000000000000000000000000000000301a1300182c11000000000000000000282c11000100000000000000010000000000000010f4120012000000020505000000000097f612000c00000000000000302c11000900000000000000cc8d12000700000000000000301a13003c2c110000000000000000004c2c110002000000000000000000000000000000712411000e000000020505000000000097f612000c00000000000000f49912000e0000000000000060dc12000300000000000000301a13005c2c110000000000000000006c2c1100020000000000000001000000832d11004c000000301a130000000000cf2d110044000000132e110034000000472e110040000000872e11004e0000005665633c543a3a417574686f7269747949643e00420000000000000001000000590000004f2d11003400000041757468496e6465780000004200000000000000010000005b000000f32c11003c0000002f2d110020000000420000000000000001000000570000007c2c110045000000c12c11003200000020466f7220656163682073657373696f6e20696e6465782c207765206b6565702061206d617070696e67206f662060543a3a56616c696461746f7249646020746f20746865206e756d626572206f6620626c6f636b7320617574686f7265642062792074686520676976656e20617574686f726974792e20466f7220656163682073657373696f6e20696e6465782c207765206b6565702061206d617070696e67206f66206041757468496e6465786020746f20606f6666636861696e3a3a4f70617175654e6574776f726b5374617465602e205468652063757272656e7420736574206f66206b6579732074686174206d61792069737375652061206865617274626561742e2054686520626c6f636b206e756d6265722061667465722077686963682069742773206f6b20746f2073656e64206865617274626561747320696e2063757272656e742073657373696f6e2e2041742074686520626567696e6e696e67206f6620656163682073657373696f6e20776520736574207468697320746f20612076616c756520746861742073686f756c642066616c6c20726f7567686c7920696e20746865206d6964646c65206f66207468652073657373696f6e206475726174696f6e2e20546865206964656120697320746f206669727374207761697420666f72207468652076616c696461746f727320746f2070726f64756365206120626c6f636b20696e207468652063757272656e742073657373696f6e2c20736f20746861742074686520686561727462656174206c61746572206f6e2077696c6c206e6f74206265206e65636573736172792e00000000000000cc2311000300000000000000042f11000100000000000000000000001c2f11001200000000000000000000007232110003000000000000007532110012000000ac2f110016000000301a130000000000c22f1100560000001830110036000000301a1300000000004e301100510000009f30110011000000301a130000000000b030110036000000301a130000000000f5bd12000b000000e6301100340000001a31110068000000823111002d000000af3111002a000000d931110060000000393211003900000044be12000c00000020536574207468652063757272656e742074696d652e20546869732063616c6c2073686f756c6420626520696e766f6b65642065786163746c79206f6e63652070657220626c6f636b2e2049742077696c6c2070616e6963206174207468652066696e616c697a6174696f6e2070686173652c20696620746869732063616c6c206861736e2774206265656e20696e766f6b656420627920746861742074696d652e205468652074696d657374616d702073686f756c642062652067726561746572207468616e207468652070726576696f7573206f6e652062792074686520616d6f756e742073706563696669656420627920604d696e696d756d506572696f64602e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d7573742062652060496e686572656e74602e202d20604f285429602077686572652060546020636f6d706c6578697479206f6620606f6e5f74696d657374616d705f73657460202d20312073746f72616765207265616420616e6420312073746f72616765206d75746174696f6e2028636f64656320604f28312960292e202862656361757365206f6620604469645570646174653a3a74616b656020696e20606f6e5f66696e616c697a656029202d2031206576656e742068616e646c657220606f6e5f74696d657374616d705f7365746020604f285429602e202d2042656e63686d61726b3a20382e35323320286d696e207371756172657320616e616c79736973292020202d204e4f54453a20546869732062656e63686d61726b2077617320646f6e6520666f7220612072756e74696d65207769746820696e7369676e69666963616e7420606f6e5f74696d657374616d705f736574602068616e646c6572732e20202020204e65772062656e63686d61726b696e67206973206e6565646564207768656e20616464696e67206e65772068616e646c6572732e6e6f77436f6d706163743c543a3a4d6f6d656e743e0000000000eb211100030000000000000000000000383311000900000000000000000000000000000000000000000000000000000000000000301a13004433110000000000000000005433110001000000000000000100000000000000daf71200090000000000000000000000a1f512000400000000000000000000000000000000000000000000000000000000000000301a13005c33110000000000000000006c331100010000000000000001000000543a3a4d6f6d656e740000004200000000000000010000006e000000a1331100240000004200000000000000010000005b000000743311002d00000020446964207468652074696d657374616d7020676574207570646174656420696e207468697320626c6f636b3f2043757272656e742074696d6520666f72207468652063757272656e7420626c6f636b2e00000000000000003411000d00000000000000383311000900000000000000301a13001034110000000000000000002034110004000000000000004d696e696d756d506572696f6400000042000000000000000100000079000000403411005a0000009a3411005a000000f4341100590000004d3511001c00000020546865206d696e696d756d20706572696f64206265747765656e20626c6f636b732e204265776172652074686174207468697320697320646966666572656e7420746f20746865202a65787065637465642a20706572696f6420746861742074686520626c6f636b2070726f64756374696f6e206170706172617475732070726f76696465732e20596f75722063686f73656e20636f6e73656e7375732073797374656d2077696c6c2067656e6572616c6c7920776f726b2077697468207468697320746f2064657465726d696e6520612073656e7369626c6520626c6f636b2074696d652e20652e672e20466f7220417572612c2069742077696c6c20626520646f75626c65207468697320706572696f64206f6e2064656661756c742073657474696e67732e54696d657374616d7020746f6f2066617220696e2066757475726520746f2061636365707454696d657374616d70206d7573742062652075706461746564206f6e6c79206f6e636520696e2074686520626c6f636b54696d657374616d70206d75737420696e6372656d656e74206279206174206c65617374203c4d696e696d756d506572696f643e206265747765656e2073657175656e7469616c20626c6f636b7300000000012211000a0000000000000044361100010000000000000000000000ee21110013000000000000004c36110001000000000000006a361100190000005436110016000000204475706c696361746564206865617274626561742e204e6f6e206578697374656e74207075626c6963206b65792e00000000000000000000000000617474656d707420746f20646976696465206279207a65726f0000004200000008000000040000007a00000071202f206365696c28712f246d617829203c20246d61782e204d6163726f2070726576656e747320616e792074797065206265696e672063726561746564207468617420646f6573206e6f74207361746973667920746869733b2071656400002c3711004200000064010000270000002f686f6d652f6461766964642f6465762f7375627374726174652f7072696d6974697665732f61726974686d657469632f7372632f7065725f7468696e67732e727300002c371100420000006b010000270000002c3711004200000076010000210000004661696c656420746f20636f6e76657274416d6f756e744c6f774578697374696e6756657374696e675363686564756c654e6f7456657374696e6776657374766573745f6f746865727665737465645f7472616e7366657200000000403811000e00000000000000841112000200000000000000000000005038110002000000000000000000000060381100100000000000000074ad120001000000000000000000000070381100010000000000000056657374696e67557064617465640000c338110056000000193911004600000056657374696e67436f6d706c65746564783811004b00000020416e206163636f756e742028676976656e2920686173206265636f6d652066756c6c79207665737465642e204e6f20667572746865722076657374696e672063616e2068617070656e2e2054686520616d6f756e742076657374656420686173206265656e20757064617465642e205468697320636f756c6420696e646963617465206d6f72652066756e64732061726520617661696c61626c652e205468652062616c616e636520676976656e2069732074686520616d6f756e74207768696368206973206c65667420756e7665737465642028616e642074687573206c6f636b6564292e5265706f72747344656665727265644f6666656e6365734e6f6e73656e7365496e7374616e744e6f74416c6c6f776564566f74657345786973744e6f7444656c65676174696e67496e73756666696369656e7446756e6473556e646572666c6f77416c726561647944656c65676174696e674e6f5065726d697373696f6e4e6f74566f7465724e6f7441637469766557726f6e674f70656e4e6f744f70656e4e6f74457870697265644e6f744c6f636b65644e6f6e6557616974696e67507265696d616765496e76616c69645265666572656e64756d496e76616c6964507265696d6167654d697373696e67496d6d696e656e744e6f74496d6d696e656e744475706c6963617465507265696d6167654e6f7444656c65676174656457726f6e6750726f7879416c72656164795665746f65644e6f50726f706f73616c496e76616c6964486173684e6f7453696d706c654d616a6f7269747950726f706f73616c426c61636b6c6973746564416c726561647943616e63656c6564426164496e6465784e6f7450726f787956616c75654c6f777365636f6e6470726f78795f766f7465656d657267656e63795f63616e63656c65787465726e616c5f70726f706f736565787465726e616c5f70726f706f73655f6d616a6f7269747965787465726e616c5f70726f706f73655f64656661756c74666173745f747261636b7665746f5f65787465726e616c63616e63656c5f7265666572656e64756d63616e63656c5f71756575656461637469766174655f70726f7879636c6f73655f70726f7879646561637469766174655f70726f787964656c6567617465756e64656c6567617465636c6561725f7075626c69635f70726f706f73616c736e6f74655f707265696d6167656e6f74655f696d6d696e656e745f707265696d616765726561705f707265696d616765756e6c6f636b6f70656e5f70726f787972656d6f76655f766f746572656d6f76655f6f746865725f766f746570726f78795f64656c656761746570726f78795f756e64656c656761746570726f78795f72656d6f76655f766f7465656e6163745f70726f706f73616c4465706f7369744f665265666572656e64756d496e666f4f66000000000054b112000800000000000000783f1100020000000000000000000000883f1100010000000000000000000000903f11000600000000000000983f1100030000000000000000000000b03f1100010000000000000000000000b83f11000e00000000000000301a1300000000000000000000000000c83f1100010000000000000000000000d03f11000700000000000000d83f1100020000000000000000000000e83f1100010000000000000000000000f03f11000600000000000000f83f110001000000000000000000000000401100010000000000000000000000084011000900000000000000f83f1100010000000000000000000000144011000100000000000000000000001c4011000900000000000000f83f110001000000000000000000000028401100010000000000000000000000f8b112000800000000000000304011000200000000000000000000004040110001000000000000000000000048401100090000000000000098ad1200020000000000000000000000544011000100000000000000000000005c4011000b0000000000000074ad1200010000000000000000000000684011000100000000000000000000007040110006000000000000007840110003000000000000000000000090401100010000000000000000000000984011000d00000000000000081a1200030000000000000000000000a8401100010000000000000000000000b04011000c00000000000000081a1200030000000000000000000000bc4011000100000000000000000000001c3a11000f00000000000000c4401100020000000000000000000000d44011000100000000000000000000003c3a11000f00000000000000c4401100020000000000000000000000dc401100010000000000000000000000e44011000e00000000000000f4401100040000000000000000000000144111000100000000000000000000001c411100080000000000000074ad12000100000000000000000000002441110001000000000000007b44110009000000f61512000700000084441100300000005461626c656400007b44110009000000f615120007000000a81412000e000000444411003700000045787465726e616c5461626c656400001e441100260000005374617274656400344211000f000000114411000d000000f9431100180000005061737365640000344211000f000000cd4311002c0000004e6f74506173736564000000a14311002c00000043616e63656c6c65640000008043110021000000344211000f000000a1f5120004000000634311001d00000044656c6567617465640000002b43110038000000556e64656c65676174656400f14211003a0000005665746f6564000020af12000900000089b2120004000000e64211000b000000c042110026000000507265696d6167654e6f7465640000008842110038000000507265696d61676555736564434211004500000089b2120004000000344211000f000000f141110043000000ae41110043000000507265696d616765526561706564000089b212000400000020af120009000000f61512000700000020af1200090000005741110057000000556e6c6f636b65642c4111002b00000020416e206163636f756e7420686173206265656e20756e6c6f636b6564207375636365737366756c6c792e2041207265676973746572656420707265696d616765207761732072656d6f76656420616e6420746865206465706f73697420636f6c6c6563746564206279207468652072656170657220286c617374206974656d292e20412070726f706f73616c20636f756c64206e6f7420626520657865637574656420626563617573652069747320707265696d61676520776173206d697373696e672e20412070726f706f73616c20636f756c64206e6f7420626520657865637574656420626563617573652069747320707265696d6167652077617320696e76616c69642e5265666572656e64756d496e64657820412070726f706f73616c20707265696d616765207761732072656d6f76656420616e6420757365642028746865206465706f736974207761732072657475726e6564292e20412070726f706f73616c277320707265696d61676520776173206e6f7465642c20616e6420746865206465706f7369742074616b656e2e20416e2065787465726e616c2070726f706f73616c20686173206265656e207665746f65642e426c6f636b4e756d62657220416e206163636f756e74206861732063616e63656c6c656420612070726576696f75732064656c65676174696f6e206f7065726174696f6e2e20416e206163636f756e74206861732064656c65676174656420746865697220766f746520746f20616e6f74686572206163636f756e742e20412070726f706f73616c20686173206265656e20656e61637465642e2041207265666572656e64756d20686173206265656e2063616e63656c6c65642e20412070726f706f73616c20686173206265656e2072656a6563746564206279207265666572656e64756d2e20412070726f706f73616c20686173206265656e20617070726f766564206279207265666572656e64756d2e2041207265666572656e64756d2068617320626567756e2e566f74655468726573686f6c6420416e2065787465726e616c2070726f706f73616c20686173206265656e207461626c65642e2041207075626c69632070726f706f73616c20686173206265656e207461626c656420666f72207265666572656e64756d20766f74652e50726f70496e6465782041206d6f74696f6e20686173206265656e2070726f706f7365642062792061207075626c6963206163636f756e742e4c6f6f6b757000000000000014451100090000000000000020451100010000000000000000000000301a13000000000000000000000000008ccb11000a0000000000000028451100030000000000000000000000301a130000000000000000005363686564756c6564000000e64211000b0000004045110018000000584511000f000000940d12000e0000005461736b416464726573733c426c6f636b4e756d6265723e4f7074696f6e3c5665633c75383e3e004200000004000000040000007b0000007c0000007d00000042000000000000000100000064000000420000000000000001000000460000004200000000000000010000006d00000073657269616c697a656420617267732073686f756c642062652070726f7669646564206279207468652072756e74696d653b0a090909636f72726563746c792073657269616c697a656420646174612073686f756c6420626520646573657269616c697a61626c653b0a0909097165648811130043000000ba000000100000004c4f474943204552524f523a2062616b655f7265666572656e64756d2f7363686564756c655f6e616d6564206661696c65644167656e64615ca412006a000000a7000000090000005ca412006a000000a700000035000000507265696d616765735075626c696350726f70734e65787445787465726e616c00000000cb3711000400000000000000301a13000000000000000000000000002c471100110000000000000000000000cf3711000a00000000000000b4471100010000000000000000000000cc471100130000000000000000000000d93711000f0000000000000064481100020000000000000000000000944811001200000000000000ec4d11002f000000301a1300000000001b4e110058000000364c11001a000000301a130000000000504c110035000000301a130000000000f5bd12000b000000184a11000a000000734e11001e000000914e11003f000000d04e110040000000004d11000d000000104f11003a0000004a4f110039000000814d11006b00000044be12000c00000000000000834b11000600000000000000f320120023000000b24b11002f000000301a13000000000098c9120034000000301a130000000000e14b110055000000364c11001a000000301a130000000000504c110035000000301a130000000000f5bd12000b000000184a11000a000000224a11001e000000854c11003d000000c24c11003e000000004d11000d0000000d4d11003b000000484d110039000000814d11006b00000044be12000c00000000000000834b11000600000000000000f32012002300000000000000a8d811000800000000000000894b110029000000244911001a000000301a13000000000098c9120034000000301a1300000000003e491100450000008349110040000000c34911003d000000301a130000000000004a110018000000301a130000000000f5bd12000b000000184a11000a000000224a11001e000000404a11004f0000008f4a110050000000df4a110038000000174b11006c00000044be12000c00000020437265617465206120766573746564207472616e736665722e202d2060746172676574603a20546865206163636f756e7420746861742073686f756c64206265207472616e7366657272656420746865207665737465642066756e64732e202d2060616d6f756e74603a2054686520616d6f756e74206f662066756e647320746f207472616e7366657220616e642077696c6c206265207665737465642e202d20607363686564756c65603a205468652076657374696e67207363686564756c6520617474616368656420746f20746865207472616e736665722e20456d697473206056657374696e6743726561746564602e202d20604f283129602e202d2044625765696768743a20332052656164732c20332057726974657320202020202d2052656164733a2056657374696e672053746f726167652c2042616c616e636573204c6f636b732c20546172676574204163636f756e742c205b53656e646572204163636f756e745d20202020202d205772697465733a2056657374696e672053746f726167652c2042616c616e636573204c6f636b732c20546172676574204163636f756e742c205b53656e646572204163636f756e745d202d2042656e63686d61726b3a203131312e34202b202e333435202a206c20c2b57320286d696e2073717561726520616e616c7973697329202d205573696e672031313520c2b5732066697865642e20417373756d696e67206c657373207468616e203530206c6f636b73206f6e20616e7920757365722c20656c7365207765206d61792077616e7420666163746f7220696e206e756d626572206f66206c6f636b732e74617267657456657374696e67496e666f3c42616c616e63654f663c543e2c20543a3a426c6f636b4e756d6265723e20556e6c6f636b20616e79207665737465642066756e6473206f662061206074617267657460206163636f756e742e202d2060746172676574603a20546865206163636f756e742077686f7365207665737465642066756e64732073686f756c6420626520756e6c6f636b65642e204d75737420686176652066756e6473207374696c6c206c6f636b656420756e6465722074686973206d6f64756c652e20456d69747320656974686572206056657374696e67436f6d706c6574656460206f72206056657374696e6755706461746564602e20202020202d2052656164733a2056657374696e672053746f726167652c2042616c616e636573204c6f636b732c20546172676574204163636f756e7420202020202d205772697465733a2056657374696e672053746f726167652c2042616c616e636573204c6f636b732c20546172676574204163636f756e74202d2042656e63686d61726b3a20202020202d20556e6c6f636b65643a2035382e3039202b202e313034202a206c20c2b57320286d696e2073717561726520616e616c797369732920202020202d204c6f636b65643a2035352e3335202b202e323535202a206c20c2b57320286d696e2073717561726520616e616c7973697329202d205573696e6720363020c2b5732066697865642e20417373756d696e67206c657373207468616e203530206c6f636b73206f6e20616e7920757365722c20656c7365207765206d61792077616e7420666163746f7220696e206e756d626572206f66206c6f636b732e20556e6c6f636b20616e79207665737465642066756e6473206f66207468652073656e646572206163636f756e742e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e64207468652073656e646572206d75737420686176652066756e6473207374696c6c202d2044625765696768743a20322052656164732c20322057726974657320202020202d2052656164733a2056657374696e672053746f726167652c2042616c616e636573204c6f636b732c205b53656e646572204163636f756e745d20202020202d205772697465733a2056657374696e672053746f726167652c2042616c616e636573204c6f636b732c205b53656e646572204163636f756e745d20202020202d20556e6c6f636b65643a2035362e31202b202e303938202a206c20c2b57320286d696e2073717561726520616e616c797369732920202020202d204c6f636b65643a2035342e3337202b202e323534202a206c20c2b57320286d696e2073717561726520616e616c7973697329000000000002bf11000700000001020000000000007ac312000c00000000000000894b11002900000000000000000000000000000000000000301a1300dc4f11000000000000000000ec4f11000100000000000000000000004200000000000000010000005b000000f44f11003600000020496e666f726d6174696f6e20726567617264696e67207468652076657374696e67206f66206120676976656e206163636f756e742e000000000000645011001100000000000000b66c12000c00000000000000301a1300549a110000000000000000007850110001000000000000004d696e5665737465645472616e73666572000000805011004700000020546865206d696e696d756d20616d6f756e7420746f206265207472616e7366657272656420746f206372656174652061206e65772076657374696e67207363686564756c652e00000000005f391100070000000105000000000000285211000d00000000000000355211003400000000000000000000000000000000000000301a13008891110000000000000000006c5211000100000000000000000000000000000066391100100000000000000000000000745211001900000000000000000000000000000000000000000000000000000000000000301a1300905211000000000000000000a052110002000000000000000100000000000000b05211001600000002050500000000008ff51200040000000000000093f512000e00000000000000c65211001200000000000000301a1300d85211000000000000000000e8521100010000000000000001000000000000002af412001200000001050000000000008ff512000400000000000000cc8d12000700000000000000000000000000000000000000301a1300f05211000000000000000000005311000600000000000000010000005265706f727449644f663c543e4f6666656e636544657461696c733c543a3a4163636f756e7449642c20543a3a4964656e74696669636174696f6e5475706c653e00000003551100520000005665633c44656665727265644f6666656e63654f663c543e3e000000420000000000000001000000590000009954110059000000f254110011000000436f6e63757272656e745265706f727473496e6465785665633c5265706f727449644f663c543e3e420000000000000001000000590000004f5411004a000000420000000000000001000000590000003053110044000000301a130000000000745311002f000000301a130000000000a353110052000000f55311005a00000020456e756d65726174657320616c6c207265706f727473206f662061206b696e6420616c6f6e672077697468207468652074696d6520746865792068617070656e65642e20416c6c207265706f7274732061726520736f72746564206279207468652074696d65206f66206f6666656e63652e204e6f74652074686174207468652061637475616c2074797065206f662074686973206d617070696e6720697320605665633c75383e602c207468697320697320626563617573652076616c756573206f6620646966666572656e7420747970657320617265206e6f7420737570706f7274656420617420746865206d6f6d656e7420736f2077652061726520646f696e6720746865206d616e75616c2073657269616c697a6174696f6e2e204120766563746f72206f66207265706f727473206f66207468652073616d65206b696e6420746861742068617070656e6564206174207468652073616d652074696d6520736c6f742e204465666572726564207265706f72747320746861742068617665206265656e2072656a656374656420627920746865206f6666656e63652068616e646c657220616e64206e65656420746f206265207375626d69747465642061742061206c617465722074696d652e20546865207072696d61727920737472756374757265207468617420686f6c647320616c6c206f6666656e6365207265636f726473206b65796564206279207265706f7274206964656e746966696572732e000000000000000db012000700000000000000545a1100020000000000000000000000845a11000f0000000000000000000000f23a11000600000000000000fc5a1100010000000000000000000000145b11000c000000000000000000000014b012000400000000000000745b1100020000000000000000000000a45b11000d0000000000000000000000f83a11000a00000000000000745b11000200000000000000000000000c5c11000c0000000000000000000000023b110010000000000000006c5c1100010000000000000000000000845c11000a0000000000000000000000123b11001000000000000000d45c1100010000000000000000000000ec5c11000b0000000000000000000000223b11001900000000000000d45c1100010000000000000000000000445d11000e00000000000000000000003b3b11001800000000000000d45c1100010000000000000000000000b45d11000e0000000000000000000000533b11000a00000000000000245e11000300000000000000000000006c5e11001300000000000000000000005d3b11000d00000000000000d45c1100010000000000000000000000045f11000f00000000000000000000006a3b110011000000000000007c5f1100010000000000000000000000945f11000900000000000000000000007b3b11000d00000000000000dc5f1100010000000000000000000000f45f11000a0000000000000000000000883b11000e00000000000000446011000100000000000000000000005c6011000b0000000000000000000000963b11000b00000000000000301a1300000000000000000000000000b4601100090000000000000000000000a13b1100100000000000000044601100010000000000000000000000fc6011000d0000000000000000000000b13b1100080000000000000064611100030000000000000000000000ac611100140000000000000000000000b93b11000a00000000000000301a13000000000000000000000000004c6211000d0000000000000000000000c33b11001600000000000000301a1300000000000000000000000000b4621100080000000000000000000000d93b11000d00000000000000f46211000100000000000000000000000c6311000d0000000000000000000000e63b11001600000000000000f4621100010000000000000000000000746311000c0000000000000000000000fc3b11000d00000000000000d45c1100010000000000000000000000d46311000f0000000000000000000000093c110006000000000000004c641100010000000000000000000000646411000900000000000000000000000f3c11000a000000000000004c641100010000000000000000000000ac6411000d0000000000000000000000193c11000b00000000000000146511000100000000000000000000002c6511001c0000000000000000000000243c110011000000000000000c6611000200000000000000000000003c661100100000000000000000000000353c11000e0000000000000064611100030000000000000000000000bc661100170000000000000000000000433c11001000000000000000301a1300000000000000000000000000746711000d0000000000000000000000533c1100110000000000000014651100010000000000000000000000dc6711000d0000000000000000000000643c11000e000000000000004468110002000000000000000000000074681100010000000000000000000000d06811000d0000000000000091d912000700000000000000aa4d1200050000000000000080751200150000001089110028000000301a13000000000038891100460000007e89110021000000301a1300000000009f89110036000000d589110046000000301a1300000000001b8a110012000000301a130000000000f5bd12000b0000002d8a110009000000368a1100360000006c8a11002000000044be12000c0000000000000089d912000800000000000000fe88110012000000c88711002e000000301a130000000000f6871100410000003788110045000000301a1300000000007c88110033000000301a130000000000f5bd12000b000000af8811000a000000b988110035000000ee8811001000000044be12000c000000000000004f7e11000900000000000000587e1100180000000000000014b012000400000000000000af87110019000000b88611004d000000058711002f000000301a130000000000f370110033000000301a13000000000034871100380000007786110022000000301a130000000000f5bd12000b0000006c8711000a0000007687110039000000998611001f00000044be12000c000000a885110054000000fc8511003d000000301a130000000000f370110033000000301a130000000000398611003e0000007786110022000000301a130000000000f5bd12000b000000184a11000a000000998611001f00000044be12000c000000000000004f7e11000900000000000000344211000f000000e084110054000000998411000c000000301a130000000000348511003f000000301a1300000000007385110035000000301a130000000000f5bd12000b000000184a11000a00000044be12000c00000000000000d06811000d0000000000000091d91200070000004d8411004c000000998411000c000000301a130000000000a58411003b000000301a130000000000f382110036000000301a130000000000f5bd12000b000000184a11000a000000732112001100000044be12000c000000a383110056000000f983110018000000301a130000000000118411003c000000301a130000000000f382110036000000301a13000000000029831100530000007c83110027000000301a130000000000f5bd12000b000000184a11000a000000732112001100000044be12000c00000045821100520000009782110021000000301a130000000000b88211003b000000301a130000000000f382110036000000301a13000000000029831100530000007c83110027000000301a130000000000f5bd12000b000000184a11000a000000732112001100000044be12000c00000000000000d06811000d0000000000000091d912000700000000000000338211000d0000000000000006cf12000e0000000000000040821100050000000000000006cf12000e000000c57f1100540000001980110059000000728011003b000000301a130000000000ad80110035000000301a130000000000e28011003e000000208111005800000078811100260000009e81110055000000f38111002f000000301a1300000000002282110011000000301a130000000000f5bd12000b000000db7711001000000073211200110000000d7611001600000044be12000c000000707e11002f000000301a1300000000009f7e110037000000301a130000000000d67e11004c000000301a130000000000227f110010000000301a130000000000f5bd12000b000000327f110012000000db77110010000000447f110042000000867f110011000000977f11002e00000044be12000c000000000000004f7e11000900000000000000587e110018000000047e110015000000301a130000000000217a110031000000301a130000000000197e110036000000301a130000000000f5bd12000b000000184a11000a00000044be12000c00000000000000ff7d11000500000000000000344211000f000000727d110028000000301a130000000000217a110031000000301a1300000000009a7d110032000000301a130000000000f5bd12000b0000007321120011000000cc7d11003300000044be12000c000000000000006d7d110005000000000000007ac312000c000000cf7c110041000000301a130000000000107d110025000000301a130000000000f370110033000000301a130000000000357d110038000000301a130000000000f5bd12000b0000000d7611001600000044be12000c000000817c110026000000301a130000000000a77c110028000000301a130000000000f370110033000000301a130000000000f5bd12000b000000db7711001000000044be12000c000000b27b11004b000000301a130000000000fd7b110022000000301a1300000000001f7c110028000000301a130000000000f370110033000000301a130000000000477c11003a000000301a130000000000f5bd12000b000000db7711001000000044be12000c00000000000000957b110002000000000000007ac312000c00000000000000977b11000a00000000000000a17b11000a00000000000000ab7b11000700000000000000b66c12000c000000ee7a11004f000000301a1300000000000a6c110056000000606c110033000000301a1300000000003d7b110058000000886d11001e000000a66d110057000000fd6d110026000000301a130000000000236e110052000000756e110056000000cb6e1100510000001c6f110055000000716f110032000000301a130000000000a36f110013000000301a130000000000f5bd12000b00000044be12000c000000527a110034000000301a130000000000dc6a110058000000346b110038000000301a130000000000867a110052000000d87a110016000000301a130000000000a86b110015000000301a130000000000f5bd12000b000000852012000800000044be12000c000000047a11001d000000301a130000000000217a110031000000301a130000000000f5bd12000b000000184a11000a000000db7711001000000044be12000c00000000000000f47911001000000000000000cc8d120007000000fe781100580000005679110049000000301a130000000000f370110033000000301a1300000000006978110032000000301a1300000000009b78110017000000301a130000000000f5bd12000b0000009f79110041000000e07911001400000044be12000c000000eb771100510000003c7811002d000000301a130000000000f370110033000000301a1300000000006978110032000000301a1300000000009b78110017000000301a130000000000f5bd12000b000000b27811004c00000044be12000c0000007b7611003d000000301a130000000000f370110033000000301a130000000000b876110034000000301a130000000000ec761100540000004077110057000000977711002c000000301a130000000000c377110018000000301a130000000000f5bd12000b000000db7711001000000044be12000c00000000000000834b110006000000000000007ac312000c0000002376110029000000301a130000000000f370110033000000301a1300000000004c7611002f000000301a130000000000f5bd12000b000000184a11000a00000044be12000c0000003075110010000000301a1300000000004075110037000000301a1300000000007775110019000000301a130000000000907511003b000000301a130000000000cb75110042000000301a130000000000f5bd12000b0000000d7611001600000044be12000c0000000000000098d912000500000000000000344211000f000000b66f110020000000301a13000000000090711100040000009471110023000000b771110020000000d771110025000000fc711100400000003c7211003600000072721100220000009472110058000000ec72110017000000301a130000000000037311002b0000002e7311003c0000006a73110038000000a273110030000000d2731100570000002974110057000000807411003a000000301a130000000000ba741100530000000d75110023000000301a1300000000001c6a11003e000000301a130000000000f5bd12000b0000005a6a11005000000044be12000c00000000000000834b110006000000000000007ac312000c0000000000000098d912000500000000000000344211000f000000b66f110020000000301a130000000000d66f1100540000002a7011004c0000007670110056000000cc70110027000000301a130000000000f370110033000000301a13000000000026711100540000007a711100160000001c6a11003e000000301a130000000000f5bd12000b0000005a6a11005000000044be12000c000000bd6b11004d000000301a1300000000000a6c110056000000606c110033000000301a130000000000936c110055000000e86c11002c000000301a130000000000146d1100580000006c6d11001c000000886d11001e000000a66d110057000000fd6d110026000000236e110052000000756e110056000000cb6e1100510000001c6f110055000000716f110032000000301a130000000000a36f110013000000301a130000000000f5bd12000b00000044be12000c000000aa6a110032000000301a130000000000dc6a110058000000346b110038000000301a13000000000070691100540000006c6b11003c000000301a130000000000a86b110015000000301a130000000000f5bd12000b000000852012000800000044be12000c000000dd68110028000000301a13000000000005691100540000005969110017000000301a1300000000007069110054000000c469110058000000301a1300000000001c6a11003e000000301a130000000000f5bd12000b0000005a6a11005000000044be12000c00000000000000d06811000d0000000000000091d91200070000000000000098d912000500000000000000344211000f0000007c6811005400000020456e61637420612070726f706f73616c2066726f6d2061207265666572656e64756d2e20466f72206e6f77207765206a757374206d616b65207468652077656967687420626520746865206d6178696d756d2e70726f706f73616c5f686173682052656d6f766520612070726f7869656420766f746520666f722061207265666572656e64756d2e2045786163746c79206571756976616c656e7420746f206072656d6f76655f766f746560206578636570742074686174206974206f70657261746573206f6e20746865206163636f756e742074686174207468652073656e64657220697320612070726f787920666f722e20546865206469737061746368206f726967696e206f6620746869732063616c6c206d757374206265205f5369676e65645f20616e6420746865207369676e696e67206163636f756e74206d75737420626520612070726f787920666f7220736f6d65206f74686572206163636f756e74207768696368206861732061207265676973746572656420766f746520666f7220746865207265666572656e64756d206f662060696e646578602e202d2060696e646578603a2054686520696e646578206f66207265666572656e64756d206f662074686520766f746520746f2062652072656d6f7665642e202d20604f2852202b206c6f6720522960207768657265205220697320746865206e756d626572206f66207265666572656e646120746861742060746172676574602068617320766f746564206f6e2e20556e64656c65676174652074686520766f74696e6720706f776572206f6620612070726f78696564206163636f756e742e20546f6b656e73206d617920626520756e6c6f636b656420666f6c6c6f77696e67206f6e636520616e20616d6f756e74206f662074696d6520636f6e73697374656e74207769746820746865206c6f636b20706572696f64206f662074686520636f6e76696374696f6e2077697468207768696368207468652064656c65676174696f6e20776173206973737565642e2070726f787920666f7220736f6d65206f74686572206163636f756e742077686963682069732063757272656e746c792064656c65676174696e672e20456d6974732060556e64656c656761746564602e2044656c65676174652074686520766f74696e6720706f77657220287769746820736f6d6520676976656e20636f6e76696374696f6e29206f6620612070726f78696564206163636f756e742e205468652062616c616e63652064656c656761746564206973206c6f636b656420666f72206173206c6f6e6720617320697427732064656c6567617465642c20616e64207468657265616674657220666f72207468652074696d6520617070726f70726961746520666f722074686520636f6e76696374696f6e2773206c6f636b20706572696f642e20546865206469737061746368206f726967696e206f6620746869732063616c6c206d757374206265205f5369676e65645f2c20616e6420746865207369676e696e67206163636f756e74206d7573742068617665206265656e20736574206173207468652070726f7879206163636f756e7420666f722060746172676574602e202d2060746172676574603a20546865206163636f756e742077686f6c6520766f74696e6720706f776572207368616c6c2062652064656c65676174656420616e642077686f73652062616c616e6365206c6f636b65642e20202054686973206163636f756e74206d757374206569746865723a2020202d2062652064656c65676174696e6720616c72656164793b206f722020202d2068617665206e6f20766f74696e67206163746976697479202869662074686572652069732c207468656e2069742077696c6c206e65656420746f2062652072656d6f7665642f636f6e736f6c69646174656420202020207468726f7567682060726561705f766f746560206f722060756e766f746560292e202d2060746f603a20546865206163636f756e742077686f736520766f74696e6720746865206074617267657460206163636f756e74277320766f74696e6720706f7765722077696c6c20666f6c6c6f772e202d2060636f6e76696374696f6e603a2054686520636f6e76696374696f6e20746861742077696c6c20626520617474616368656420746f207468652064656c65676174656420766f7465732e205768656e207468652020206163636f756e7420697320756e64656c6567617465642c207468652066756e64732077696c6c206265206c6f636b656420666f722074686520636f72726573706f6e64696e6720706572696f642e202d206062616c616e6365603a2054686520616d6f756e74206f6620746865206163636f756e7427732062616c616e636520746f206265207573656420696e2064656c65676174696e672e2054686973206d7573742020206e6f74206265206d6f7265207468616e20746865206163636f756e7427732063757272656e742062616c616e63652e20456d697473206044656c656761746564602e2052656d6f7665206120766f746520666f722061207265666572656e64756d2e2049662074686520607461726765746020697320657175616c20746f20746865207369676e65722c207468656e20746869732066756e6374696f6e2069732065786163746c79206571756976616c656e7420746f206072656d6f76655f766f7465602e204966206e6f7420657175616c20746f20746865207369676e65722c207468656e2074686520766f7465206d757374206861766520657870697265642c20656974686572206265636175736520746865207265666572656e64756d207761732063616e63656c6c65642c20626563617573652074686520766f746572206c6f737420746865207265666572656e64756d206f7220626563617573652074686520636f6e76696374696f6e20706572696f64206973206f7665722e20546865206469737061746368206f726967696e206f6620746869732063616c6c206d757374206265205f5369676e65645f2e202d2060746172676574603a20546865206163636f756e74206f662074686520766f746520746f2062652072656d6f7665643b2074686973206163636f756e74206d757374206861766520766f74656420666f722020207265666572656e64756d2060696e646578602e2049663a202d20746865207265666572656e64756d207761732063616e63656c6c65642c206f72202d20746865207265666572656e64756d206973206f6e676f696e672c206f72202d20746865207265666572656e64756d2068617320656e646564207375636820746861742020202d2074686520766f7465206f6620746865206163636f756e742077617320696e206f70706f736974696f6e20746f2074686520726573756c743b206f722020202d20746865726520776173206e6f20636f6e76696374696f6e20746f20746865206163636f756e74277320766f74653b206f722020202d20746865206163636f756e74206d61646520612073706c697420766f7465202e2e2e7468656e2074686520766f74652069732072656d6f76656420636c65616e6c7920616e64206120666f6c6c6f77696e672063616c6c20746f2060756e6c6f636b60206d617920726573756c7420696e206d6f72652066756e6473206265696e6720617661696c61626c652e2049662c20686f77657665722c20746865207265666572656e64756d2068617320656e64656420616e643a202d2069742066696e697368656420636f72726573706f6e64696e6720746f2074686520766f7465206f6620746865206163636f756e742c20616e64202d20746865206163636f756e74206d6164652061207374616e6461726420766f7465207769746820636f6e76696374696f6e2c20616e64202d20746865206c6f636b20706572696f64206f662074686520636f6e76696374696f6e206973206e6f74206f766572202e2e2e7468656e20746865206c6f636b2077696c6c206265206167677265676174656420696e746f20746865206f766572616c6c206163636f756e742773206c6f636b2c207768696368206d617920696e766f6c7665202a6f7665726c6f636b696e672a20287768657265207468652074776f206c6f636b732061726520636f6d62696e656420696e746f20612073696e676c65206c6f636b207468617420697320746865206d6178696d756d206f6620626f74682074686520616d6f756e74206c6f636b656420616e64207468652074696d65206973206974206c6f636b656420666f72292e20546865206469737061746368206f726967696e206f6620746869732063616c6c206d757374206265205f5369676e65645f2c20616e6420746865207369676e6572206d7573742068617665206120766f7465207265676973746572656420666f72207265666572656e64756d2060696e646578602e204265636f6d6520612070726f78792e2054686973206d7573742062652063616c6c6564207072696f7220746f2061206c61746572206061637469766174655f70726f7879602e204f726967696e206d7573742062652061205369676e65642e202d2060746172676574603a20546865206163636f756e742077686f736520766f7465732077696c6c206c617465722062652070726f786965642e2060636c6f73655f70726f787960206d7573742062652063616c6c6564206265666f726520746865206163636f756e742063616e2062652064657374726f7965642e202d204f6e6520657874726120444220656e7472792e20556e6c6f636b20746f6b656e732074686174206861766520616e2065787069726564206c6f636b2e202d2060746172676574603a20546865206163636f756e7420746f2072656d6f766520746865206c6f636b206f6e2e2052656d6f766520616e20657870697265642070726f706f73616c20707265696d61676520616e6420636f6c6c65637420746865206465706f7369742e202d206070726f706f73616c5f68617368603a2054686520707265696d6167652068617368206f6620612070726f706f73616c2e20546869732077696c6c206f6e6c7920776f726b2061667465722060566f74696e67506572696f646020626c6f636b732066726f6d207468652074696d6520746861742074686520707265696d61676520776173206e6f7465642c2069662069742773207468652073616d65206163636f756e7420646f696e672069742e2049662069742773206120646966666572656e74206163636f756e742c207468656e206974276c6c206f6e6c7920776f726b20616e206164646974696f6e616c2060456e6163746d656e74506572696f6460206c617465722e20456d6974732060507265696d616765526561706564602e202d204f6e6520444220636c6561722e2052656769737465722074686520707265696d61676520666f7220616e207570636f6d696e672070726f706f73616c2e2054686973207265717569726573207468652070726f706f73616c20746f20626520696e207468652064697370617463682071756575652e204e6f206465706f736974206973206e65656465642e202d2060656e636f6465645f70726f706f73616c603a2054686520707265696d616765206f6620612070726f706f73616c2e20456d6974732060507265696d6167654e6f746564602e202d20446570656e64656e74206f6e207468652073697a65206f662060656e636f6465645f70726f706f73616c6020616e64206c656e677468206f662064697370617463682071756575652e2052656769737465722074686520707265696d61676520666f7220616e207570636f6d696e672070726f706f73616c2e205468697320646f65736e27742072657175697265207468652070726f706f73616c20746f20626520696e207468652064697370617463682071756575652062757420646f657320726571756972652061206465706f7369742c2072657475726e6564206f6e636520656e61637465642e202d20446570656e64656e74206f6e207468652073697a65206f662060656e636f6465645f70726f706f73616c60206275742070726f74656374656420627920612020207265717569726564206465706f7369742e656e636f6465645f70726f706f73616c20436c6561727320616c6c207075626c69632070726f706f73616c732e20546865206469737061746368206f726967696e206f6620746869732063616c6c206d757374206265205f526f6f745f2e20556e64656c65676174652074686520766f74696e6720706f776572206f66207468652073656e64696e67206163636f756e742e20546865206469737061746368206f726967696e206f6620746869732063616c6c206d757374206265205f5369676e65645f20616e6420746865207369676e696e67206163636f756e74206d7573742062652063757272656e746c792064656c65676174696e672e2044656c65676174652074686520766f74696e6720706f77657220287769746820736f6d6520676976656e20636f6e76696374696f6e29206f66207468652073656e64696e67206163636f756e742e20546865206469737061746368206f726967696e206f6620746869732063616c6c206d757374206265205f5369676e65645f2c20616e6420746865207369676e696e67206163636f756e74206d757374206569746865723a746f636f6e76696374696f6e436f6e76696374696f6e62616c616e63652044656163746976617465207468652070726f78792c20627574206c65617665206f70656e20746f2074686973206163636f756e742e2043616c6c6564206279207468652073746173682e205468652070726f7879206d75737420616c7265616479206265206163746976652e204e4f54453a205573656420746f2062652063616c6c6564206072656d6f76655f70726f7879602e202d206070726f7879603a20546865206163636f756e7420746861742077696c6c2062652064656163746976617465642061732070726f78792e20436c656172207468652070726f78792e2043616c6c6564206279207468652070726f78792e204e4f54453a205573656420746f2062652063616c6c6564206072657369676e5f70726f7879602e205370656369667920612070726f7879207468617420697320616c7265616479206f70656e20746f2075732e2043616c6c6564206279207468652073746173682e204e4f54453a205573656420746f2062652063616c6c656420607365745f70726f7879602e202d206070726f7879603a20546865206163636f756e7420746861742077696c6c206265206163746976617465642061732070726f78792e70726f78792043616e63656c20612070726f706f73616c2071756575656420666f7220656e6163746d656e742e202d20607768696368603a2054686520696e646578206f6620746865207265666572656e64756d20746f2063616e63656c2e202d204f286429207768657265206420697320746865206974656d7320696e207468652064697370617463682071756575652e77686963682052656d6f76652061207265666572656e64756d2e202d20607265665f696e646578603a2054686520696e646578206f6620746865207265666572656e64756d20746f2063616e63656c2e7265665f696e646578436f6d706163743c5265666572656e64756d496e6465783e205665746f20616e6420626c61636b6c697374207468652065787465726e616c2070726f706f73616c20686173682e20546865206469737061746368206f726967696e206f6620746869732063616c6c206d75737420626520605665746f4f726967696e602e202d206070726f706f73616c5f68617368603a2054686520707265696d6167652068617368206f66207468652070726f706f73616c20746f207665746f20616e6420626c61636b6c6973742e20456d69747320605665746f6564602e202d2054776f20444220656e74726965732e202d20506572666f726d7320612062696e61727920736561726368206f6e20606578697374696e675f7665746f657273602077686963682073686f756c64206e6f7420202062652076657279206c617267652e202d204f286c6f672076292c2076206973206e756d626572206f6620606578697374696e675f7665746f65727360205363686564756c65207468652063757272656e746c792065787465726e616c6c792d70726f706f736564206d616a6f726974792d63617272696573207265666572656e64756d20746f206265207461626c656420696d6d6564696174656c792e204966207468657265206973206e6f2065787465726e616c6c792d70726f706f736564207265666572656e64756d2063757272656e746c792c206f72206966207468657265206973206f6e6520627574206974206973206e6f742061206d616a6f726974792d63617272696573207265666572656e64756d207468656e206974206661696c732e20546865206469737061746368206f6620746869732063616c6c206d757374206265206046617374547261636b4f726967696e602e202d206070726f706f73616c5f68617368603a205468652068617368206f66207468652063757272656e742065787465726e616c2070726f706f73616c2e202d2060766f74696e675f706572696f64603a2054686520706572696f64207468617420697320616c6c6f77656420666f7220766f74696e67206f6e20746869732070726f706f73616c2e20496e6372656173656420746f2020206046617374547261636b566f74696e67506572696f646020696620746f6f206c6f772e202d206064656c6179603a20546865206e756d626572206f6620626c6f636b20616674657220766f74696e672068617320656e64656420696e20617070726f76616c20616e6420746869732073686f756c64206265202020656e61637465642e205468697320646f65736e277420686176652061206d696e696d756d20616d6f756e742e20456d697473206053746172746564602e766f74696e675f706572696f6464656c6179205363686564756c652061206e656761746976652d7475726e6f75742d62696173207265666572656e64756d20746f206265207461626c6564206e657874206f6e6365206974206973206c6567616c20746f207363686564756c6520616e2065787465726e616c207265666572656e64756d2e20546865206469737061746368206f6620746869732063616c6c206d757374206265206045787465726e616c44656661756c744f726967696e602e202d206070726f706f73616c5f68617368603a2054686520707265696d6167652068617368206f66207468652070726f706f73616c2e20556e6c696b65206065787465726e616c5f70726f706f7365602c20626c61636b6c697374696e6720686173206e6f20656666656374206f6e207468697320616e64206974206d6179207265706c6163652061207072652d7363686564756c6564206065787465726e616c5f70726f706f7365602063616c6c2e205363686564756c652061206d616a6f726974792d63617272696573207265666572656e64756d20746f206265207461626c6564206e657874206f6e6365206974206973206c6567616c20746f207363686564756c6520616e2065787465726e616c207265666572656e64756d2e20546865206469737061746368206f6620746869732063616c6c206d757374206265206045787465726e616c4d616a6f726974794f726967696e602e205363686564756c652061207265666572656e64756d20746f206265207461626c6564206f6e6365206974206973206c6567616c20746f207363686564756c6520616e2065787465726e616c207265666572656e64756d2e20546865206469737061746368206f726967696e206f6620746869732063616c6c206d757374206265206045787465726e616c4f726967696e602e205363686564756c6520616e20656d657267656e63792063616e63656c6c6174696f6e206f662061207265666572656e64756d2e2043616e6e6f742068617070656e20747769636520746f207468652073616d6520546865206469737061746368206f726967696e206f6620746869732063616c6c206d757374206265206043616e63656c6c6174696f6e4f726967696e602e202d607265665f696e646578603a2054686520696e646578206f6620746865207265666572656e64756d20746f2063616e63656c2e20566f746520696e2061207265666572656e64756d206f6e20626568616c66206f6620612073746173682e2049662060766f74652e69735f6179652829602c2074686520766f746520697320746f20656e616374207468652070726f706f73616c3b206f7468657277697365206974206973206120766f746520746f206b65657020746865207374617475732071756f2e202d20607265665f696e646578603a2054686520696e646578206f6620746865207265666572656e64756d20746f2070726f787920766f746520666f722e202d2060766f7465603a2054686520766f746520636f6e66696775726174696f6e2e202d204f6e65204442206368616e67652c206f6e6520444220656e7472792e20566f746520696e2061207265666572656e64756d2e2049662060766f74652e69735f6179652829602c2074686520766f746520697320746f20656e616374207468652070726f706f73616c3b206f7468657277697365206974206973206120766f746520746f206b65657020746865207374617475732071756f2e202d20607265665f696e646578603a2054686520696e646578206f6620746865207265666572656e64756d20746f20766f746520666f722e202d20604f285229602e202d205220697320746865206e756d626572206f66207265666572656e64756d732074686520766f7465722068617320766f746564206f6e2e4163636f756e74566f74653c42616c616e63654f663c543e3e205369676e616c732061677265656d656e742077697468206120706172746963756c61722070726f706f73616c2e20546865206469737061746368206f726967696e206f6620746869732063616c6c206d757374206265205f5369676e65645f20616e64207468652073656e646572206d75737420686176652066756e647320746f20636f76657220746865206465706f7369742c20657175616c20746f20746865206f726967696e616c206465706f7369742e202d206070726f706f73616c603a2054686520696e646578206f66207468652070726f706f73616c20746f207365636f6e642e202d20604f285329602e202d205320697320746865206e756d626572206f66207365636f6e647320612070726f706f73616c20616c7265616479206861732e202d204f6e6520444220656e7472792e436f6d706163743c50726f70496e6465783e2050726f706f736520612073656e73697469766520616374696f6e20746f2062652074616b656e2e20546865206469737061746368206f726967696e206f6620746869732063616c6c206d757374206265205f5369676e65645f20616e64207468652073656e646572206d75737420686176652066756e647320746f20636f76657220746865206465706f7369742e202d206070726f706f73616c5f68617368603a205468652068617368206f66207468652070726f706f73616c20707265696d6167652e202d206076616c7565603a2054686520616d6f756e74206f66206465706f73697420286d757374206265206174206c6561737420604d696e696d756d4465706f73697460292e20456d697473206050726f706f736564602e202d20604f28502960202d205020697320746865206e756d6265722070726f706f73616c7320696e2074686520605075626c696350726f707360207665632e202d2054776f204442206368616e6765732c206f6e6520444220656e7472792e00000000bbf112000f00000000000000000000007b4411000900000000000000000000000000000000000000000000000000000000000000301a13003490110000000000000000005c8f110001000000000000000100000000000000914611000b0000000000000000000000648f11002700000000000000000000000000000000000000000000000000000000000000301a13008c8f110000000000000000009c8f110001000000000000000100000000000000723c11000900000001050000000000007b4411000900000000000000a48f11002100000000000000000000000000000000000000301a1300c88f11000000000000000000d88f1100010000000000000000000000000000008846110009000000010600000000000091d912000700000000000000e08f11003a00000000000000000000000000000000000000301a13008891110000000000000000001c90110002000000000000000000000000000000caf112000f0000000000000000000000344211000f00000000000000000000000000000000000000000000000000000000000000301a13003490110000000000000000002c90110001000000000000000100000000000000e2f112000d0000000000000000000000344211000f00000000000000000000000000000000000000000000000000000000000000301a130034901100000000000000000044901100020000000000000001000000000000007b3c1100100000000105000000000000344211000f00000000000000549011003500000000000000000000000000000000000000301a13008c90110000000000000000009c90110001000000000000000000000000000000a49011000800000001050000000000007ac312000c00000000000000ac9011003200000000000000000000000000000000000000301a1300e09011000000000000000000f09011000200000000000000010000000000000064d312000500000001050000000000007ac312000c00000000000000009111001800000000000000000000000000000000000000301a13001891110000000000000000002891110002000000000000000000000000000000389111000500000001050000000000007ac312000c0000000000000006cf12000e00000000000000000000000000000000000000301a13004091110000000000000000005091110002000000000000000000000000000000eff11200150000000000000000000000a1f512000400000000000000000000000000000000000000000000000000000000000000301a130014921100000000000000000060911100020000000000000001000000000000009c4611000c0000000000000000000000709111001800000000000000000000000000000000000000000000000000000000000000301a13008891110000000000000000009891110004000000000000000000000000000000b891110009000000010600000000000091d912000700000000000000c19111002300000000000000000000000000000000000000301a1300e49111000000000000000000f491110002000000000000000000000000000000049211000d000000010600000000000091d912000700000000000000a1f512000400000000000000000000000000000000000000301a1300149211000000000000000000249211000100000000000000010000000c9811003d0000005665633c2850726f70496e6465782c20543a3a486173682c20543a3a4163636f756e744964293e0042000000000000000100000059000000c4971100480000002842616c616e63654f663c543e2c205665633c543a3a4163636f756e7449643e290000004200000000000000010000007e000000a397110021000000507265696d6167655374617475733c543a3a4163636f756e7449642c2042616c616e63654f663c543e2c20543a3a426c6f636b4e756d6265723e000012971100580000006a97110039000000c69611004c0000004200000000000000010000005700000046961100490000008f961100370000005265666572656e64756d496e666f3c543a3a426c6f636b4e756d6265722c20543a3a486173682c2042616c616e63654f663c543e3e0000004200000000000000010000005b000000199611002d000000566f74696e674f66566f74696e673c42616c616e63654f663c543e2c20543a3a4163636f756e7449642c20543a3a426c6f636b4e756d6265723e00004200000000000000010000007f0000006b95110057000000c29511005700000050726f787953746174653c543a3a4163636f756e7449643e4200000000000000010000005b000000fd9411004c00000049951100220000004c6f636b730000004200000000000000010000005b0000005294110057000000a994110054000000f293110056000000489411000a00000028543a3a486173682c20566f74655468726573686f6c64294200000000000000010000005b00000004931100560000005a93110055000000af93110029000000d89311001a000000426c61636b6c69737428543a3a426c6f636b4e756d6265722c205665633c543a3a4163636f756e7449643e294200000000000000010000007e0000007692110054000000ca9211003a00000043616e63656c6c6174696f6e730000004200000000000000010000005b0000002c9211004a000000205265636f7264206f6620616c6c2070726f706f73616c7320746861742068617665206265656e207375626a65637420746f20656d657267656e63792063616e63656c6c6174696f6e2e2041207265636f7264206f662077686f207665746f656420776861742e204d6170732070726f706f73616c206861736820746f206120706f737369626c65206578697374656e7420626c6f636b206e756d6265722028756e74696c207768656e206974206d6179206e6f742062652072657375626d69747465642920616e642077686f207665746f65642069742e20546865207265666572656e64756d20746f206265207461626c6564207768656e6576657220697420776f756c642062652076616c696420746f207461626c6520616e2065787465726e616c2070726f706f73616c2e20546869732068617070656e73207768656e2061207265666572656e64756d206e6565647320746f206265207461626c656420616e64206f6e65206f662074776f20636f6e646974696f6e7320617265206d65743a202d20604c6173745461626c656457617345787465726e616c60206973206066616c7365603b206f72202d20605075626c696350726f70736020697320656d7074792e205472756520696620746865206c617374207265666572656e64756d207461626c656420776173207375626d69747465642065787465726e616c6c792e2046616c7365206966206974207761732061207075626c69632070726f706f73616c2e204163636f756e747320666f7220776869636820746865726520617265206c6f636b7320696e20616374696f6e207768696368206d61792062652072656d6f76656420617420736f6d6520706f696e7420696e20746865206675747572652e205468652076616c75652069732074686520626c6f636b206e756d62657220617420776869636820746865206c6f636b206578706972657320616e64206d61792062652072656d6f7665642e2057686f2069732061626c6520746f20766f746520666f722077686f6d2e2056616c7565206973207468652066756e642d686f6c64696e67206163636f756e742c206b65792069732074686520766f74652d7472616e73616374696f6e2d73656e64696e67206163636f756e742e20416c6c20766f74657320666f72206120706172746963756c617220766f7465722e2057652073746f7265207468652062616c616e636520666f7220746865206e756d626572206f6620766f74657320746861742077652068617665207265636f726465642e20546865207365636f6e64206974656d2069732074686520746f74616c20616d6f756e74206f662064656c65676174696f6e732c20746861742077696c6c2062652061646465642e20496e666f726d6174696f6e20636f6e6365726e696e6720616e7920676976656e207265666572656e64756d2e20546865206c6f77657374207265666572656e64756d20696e64657820726570726573656e74696e6720616e20756e62616b6564207265666572656e64756d2e20457175616c20746f20605265666572656e64756d436f756e74602069662074686572652069736e2774206120756e62616b6564207265666572656e64756d2e20546865206e6578742066726565207265666572656e64756d20696e6465782c20616b6120746865206e756d626572206f66207265666572656e6461207374617274656420736f206661722e204d6170206f662068617368657320746f207468652070726f706f73616c20707265696d6167652c20616c6f6e6720776974682077686f207265676973746572656420697420616e64207468656972206465706f7369742e2054686520626c6f636b206e756d6265722069732074686520626c6f636b20617420776869636820697420776173206465706f73697465642e2054686f73652077686f2068617665206c6f636b65642061206465706f7369742e20546865207075626c69632070726f706f73616c732e20556e736f727465642e20546865207365636f6e64206974656d206973207468652070726f706f73616c277320686173682e20546865206e756d626572206f6620287075626c6963292070726f706f73616c7320746861742068617665206265656e206d61646520736f206661722e00000000000000d49911000f0000000000000006cf12000e00000000000000301a1300e49911000000000000000000f49911000500000000000000000000001c9a11000c0000000000000006cf12000e00000000000000301a1300ac9a11000000000000000000289a1100010000000000000000000000309a11000c0000000000000006cf12000e00000000000000301a1300ac9a110000000000000000003c9a1100010000000000000000000000449a11000e00000000000000b66c12000c00000000000000301a1300549a11000000000000000000649a11000100000000000000000000006c9a1100150000000000000006cf12000e00000000000000301a1300849a11000000000000000000949a11000100000000000000000000009c9a11000d0000000000000006cf12000e00000000000000301a1300ac9a11000000000000000000bc9a1100010000000000000000000000c49a11001300000000000000b66c12000c00000000000000301a1300d89a11000000000000000000e89a11000100000000000000456e6163746d656e74506572696f640042000000000000000100000080000000819c11005c000000301a130000000000dd9c11004c000000299d11005a000000839d1100270000004c61756e6368506572696f64489c110039000000566f74696e67506572696f641a9c11002e0000004d696e696d756d4465706f736974000042000000000000000100000081000000cd9b11004d00000046617374547261636b566f74696e67506572696f6400000042000000000000000100000082000000929b11003b000000436f6f6c6f6666506572696f64000000420000000000000001000000830000003a9b110058000000507265696d616765427974654465706f7369740042000000000000000100000084000000f09a11004a0000002054686520616d6f756e74206f662062616c616e63652074686174206d757374206265206465706f7369746564207065722062797465206f6620707265696d6167652073746f7265642e20506572696f6420696e20626c6f636b7320776865726520616e2065787465726e616c2070726f706f73616c206d6179206e6f742062652072652d7375626d6974746564206166746572206265696e67207665746f65642e204d696e696d756d20766f74696e6720706572696f6420616c6c6f77656420666f7220616e20656d657267656e6379207265666572656e64756d2e20546865206d696e696d756d20616d6f756e7420746f20626520757365642061732061206465706f73697420666f722061207075626c6963207265666572656e64756d2070726f706f73616c2e20486f77206f6674656e2028696e20626c6f636b732920746f20636865636b20666f72206e657720766f7465732e20486f77206f6674656e2028696e20626c6f636b7329206e6577207075626c6963207265666572656e646120617265206c61756e636865642e20546865206d696e696d756d20706572696f64206f66206c6f636b696e6720616e642074686520706572696f64206265747765656e20612070726f706f73616c206265696e6720617070726f76656420616e6420656e61637465642e2049742073686f756c642067656e6572616c6c792062652061206c6974746c65206d6f7265207468616e2074686520756e7374616b6520706572696f6420746f20656e73757265207468617420766f74696e67207374616b657273206861766520616e206f70706f7274756e69747920746f2072656d6f7665207468656d73656c7665732066726f6d207468652073797374656d20696e207468652063617365207768657265207468657920617265206f6e20746865206c6f73696e672073696465206f66206120766f74652e0000000000006246110006000000010500000000000006cf12000e000000000000005c9e11003a00000000000000000000000000000000000000301a1300989e11000000000000000000a89e110001000000000000000100000000000000b4441100060000000105000000000000cc8d12000700000000000000b09e11001b00000000000000000000000000000000000000301a1300cc9e11000000000000000000dc9e11000100000000000000000000005665633c4f7074696f6e3c5363686564756c65643c3c542061732054726169743e3a3a43616c6c2c20543a3a426c6f636b4e756d6265723e3e3e000042000000000000000100000059000000249f1100530000005461736b416464726573733c543a3a426c6f636b4e756d6265723e0042000000000000000100000085000000e49e110040000000204c6f6f6b75702066726f6d206964656e7469747920746f2074686520626c6f636b206e756d62657220616e6420696e646578206f6620746865207461736b2e204974656d7320746f2062652065786563757465642c20696e64657865642062792074686520626c6f636b206e756d626572207468617420746865792073686f756c64206265206578656375746564206f6e2e00696d2d6f6e6c696e653a6f66666c696e7573657220646f6573206e6f74206861766520616e206578697374696e672076657374696e67207363686564756c653b20712e652e642e00420000000c0000000400000086000000e09f110033000000080100000d0000002f686f6d652f6461766964642f6465762f7375627374726174652f6672616d652f76657374696e672f7372632f6c69622e72730034a0110035000000730500002d00000034a01100350000007a050000400000002f686f6d652f6461766964642f6465762f7375627374726174652f6672616d652f64656d6f63726163792f7372632f6c69622e727300000034a0110035000000460500002d00000072616e206f7574206f662067617320647572696e6720636f6e747261637420657865637574696f6e72657475726e2074797065206572726f7276616c69646174696f6e206572726f72636f6e7472616374207472617070656420647572696e6720657865637574696f6e707265636f6e646974696f6e3a20616c6c20696d706f7274732073686f756c6420626520636865636b656420616761696e737420746865207369676e617475726573206f6620636f72726573706f6e64696e670a09090909090966756e6374696f6e7320646566696e65642062792060646566696e655f656e762160206d6163726f206279207468652075736572206f6620746865206d6163726f3b0a0909090909097369676e617475726573206f662074686573652066756e6374696f6e7320646566696e6564206279206024706172616d73603b0a09090909090963616c6c7320616c77617973206d616465207769746820617267756d656e7473207479706573206f662077686963682061726520646566696e65642062792074686520636f72726573706f6e64696e6720696d706f7274733b0a09090909090974687573207479706573206f6620617267756d656e74732073686f756c6420626520657175616c20746f2074797065206c69737420696e206024706172616d736020616e640a0909090909096c656e677468206f6620617267756d656e74206c69737420616e642024706172616d732073686f756c6420626520657175616c3b0a0909090909097468757320746869732063616e206e6576657220626520604e6f6e65603b0a0909090909097165643b0a0909090909090000eca211004500000046000000110000002f686f6d652f6461766964642f6465762f7375627374726174652f6672616d652f636f6e7472616374732f7372632f7761736d2f656e765f6465662f6d6163726f732e7273657865632e7072656661625f6d6f64756c652e696e697469616c2063616e27742062652067726561746572207468616e20657865632e7072656661625f6d6f64756c652e6d6178696d756d3b0a09090909090974687573204d656d6f72793a3a6e6577206d757374206e6f74206661696c3b0a09090909090971656400000000000000c13711000a0000000000000004a41100010000000000000000000000aa37110017000000000000000ca41100010000000000000000000000a1371100090000000000000014a411000100000000000000b5a41100220000005ea41100570000001ca411004200000020416d6f756e74206265696e67207472616e7366657272656420697320746f6f206c6f7720746f2063726561746520612076657374696e67207363686564756c652e20416e206578697374696e672076657374696e67207363686564756c6520616c72656164792065786973747320666f722074686973206163636f756e7420746861742063616e6e6f7420626520636c6f6262657265642e20546865206163636f756e7420676976656e206973206e6f742076657374696e672e0000000000ea3a11000800000000000000e4a81100010000000000000000000000d2af12000f00000000000000eca81100010000000000000000000000e23a11000800000000000000f4a81100010000000000000000000000da3a11000800000000000000fca81100010000000000000000000000cb3a11000f0000000000000004a91100010000000000000000000000e1af120011000000000000000ca91100010000000000000000000000b83a1100130000000000000014a91100010000000000000000000000a73a110011000000000000001ca911000100000000000000000000009c3a11000b0000000000000024a91100010000000000000000000000923a11000a000000000000002ca91100010000000000000000000000853a11000d0000000000000034a911000100000000000000000000001bab12000c000000000000003ca911000100000000000000000000007b3a11000a0000000000000044a911000100000000000000000000006f3a11000c000000000000004ca911000100000000000000000000005e3a1100110000000000000054a91100010000000000000000000000533a11000b000000000000005ca91100010000000000000000000000a1af1200080000000000000064a911000100000000000000000000004b3a110008000000000000006ca911000100000000000000000000003c3a11000f0000000000000074a911000100000000000000000000002b3a110011000000000000007ca911000100000000000000000000001c3a11000f0000000000000084a91100010000000000000000000000113a11000b000000000000008ca91100010000000000000000000000083a1100090000000000000094a91100010000000000000000000000fe3911000a000000000000009ca91100010000000000000000000000f73911000700000000000000a4a91100010000000000000000000000ee3911000900000000000000aca91100010000000000000000000000e53911000900000000000000b4a91100010000000000000000000000dd3911000800000000000000bca91100010000000000000000000000d13911000c00000000000000c4a91100010000000000000000000000c03911001100000000000000cca9110001000000000000000000000027ab12000800000000000000d4a91100010000000000000000000000b73911000900000000000000dca91100010000000000000000000000a63911001100000000000000e4a91100010000000000000000000000993911000d00000000000000eca911000100000000000000000000008f3911000a00000000000000f4a911000200000000000000000000007e391100110000000000000004aa11000100000000000000000000007639110008000000000000000caa1100010000000000000035af11000e0000001daf11001800000011af11000c00000003af11000e000000ddae110026000000c7ae110016000000acae11001b00000081ae11002b00000074ae11000d0000005fae11001500000038ae11002700000028ae1100100000001cae11000c0000000eae11000e000000f7ad110017000000eaad11000d000000e0ad11000a000000d7ad110009000000c4ad110013000000a2ad11002200000091ad1100110000007cad11001500000053ad11002900000017ad11003c000000d8ac11003f0000008aac11004e00000046ac11004400000014ac110032000000e1ab110033000000beab11002300000095ab1100290000006bab11002a0000002bab11004000000002ab11002900000071aa110056000000c7aa11003b0000003aaa11003700000014aa1100260000002044656c65676174696f6e20746f206f6e6573656c66206d616b6573206e6f2073656e73652e2054686520696e7374616e74207265666572656e64756d206f726967696e2069732063757272656e746c7920646973616c6c6f7765642e20546865206163636f756e742063757272656e746c792068617320766f74657320617474616368656420746f20697420616e6420746865206f7065726174696f6e2063616e6e6f74207375636365656420756e74696c207468657365206172652072656d6f7665642c20656974686572207468726f7567682060756e766f746560206f722060726561705f766f7465602e20546865206163636f756e74206973206e6f742063757272656e746c792064656c65676174696e672e20546f6f206869676820612062616c616e6365207761732070726f7669646564207468617420746865206163636f756e742063616e6e6f74206166666f72642e20416e20756e657870656374656420696e746567657220756e646572666c6f77206f636375727265642e20416e20756e657870656374656420696e7465676572206f766572666c6f77206f636375727265642e20546865206163636f756e7420697320616c72656164792064656c65676174696e672e20546865206163746f7220686173206e6f207065726d697373696f6e20746f20636f6e647563742074686520616374696f6e2e2054686520676976656e206163636f756e7420646964206e6f7420766f7465206f6e20746865207265666572656e64756d2e20412070726f78792d64652d70616972696e672077617320617474656d7074656420746f20616e206163636f756e74207468617420776173206e6f74206163746976652e20412070726f78792d70616972696e672077617320617474656d7074656420746f20616e206163636f756e74207468617420776173206f70656e20746f20616e6f74686572206163636f756e742e20412070726f78792d70616972696e672077617320617474656d7074656420746f20616e206163636f756e74207468617420776173206e6f74206f70656e2e20546865206c6f636b206f6e20746865206163636f756e7420746f20626520756e6c6f636b656420686173206e6f742079657420657870697265642e2054686520746172676574206163636f756e7420646f6573206e6f7420686176652061206c6f636b2e204e6f2070726f706f73616c732077616974696e6720496e76616c696420707265696d61676520566f746520676976656e20666f7220696e76616c6964207265666572656e64756d20507265696d616765206e6f7420666f756e6420496d6d696e656e7420546f6f206561726c79204e6f7420696d6d696e656e7420507265696d61676520616c7265616479206e6f746564204e6f742064656c6567617465642057726f6e672070726f787920416c726561647920612070726f7879204964656e74697479206d6179206e6f74207665746f20612070726f706f73616c207477696365204e6f2065787465726e616c2070726f706f73616c20496e76616c69642068617368204e6578742065787465726e616c2070726f706f73616c206e6f742073696d706c65206d616a6f726974792050726f706f73616c207374696c6c20626c61636b6c69737465642050726f706f73616c20616c7265616479206d6164652043616e6e6f742063616e63656c207468652073616d652070726f706f73616c20747769636520556e6b6e6f776e20696e646578204e6f7420612070726f78792050726f706f73616c20646f6573206e6f742065786973742056616c756520746f6f206c6f77617373657274696f6e206661696c65643a2073656c662e686569676874203e2030617373657274696f6e206661696c65643a2073656c662e6c656e2829203e203094af110056000000a5040000520000002f72757374632f666135316638313065356239323534393034623932363630653732383062376436613436663131322f7372632f6c6962616c6c6f632f636f6c6c656374696f6e732f62747265652f6e6f64652e7273000094af110056000000b60400004c0000004368617267655472616e73616374696f6e5061796d656e745072697374696e65436f6465436f646553746f72616765436f6e7472616374496e666f4f66526563656e7448696e7473506f7374496e666f3a2000000000000090b0110004000000000000000000000094b011000e000000000000000a000000f50000000300000000000000a4b011000c00000000000000010000006e6f64657375627374726174652d6e6f64650000df6acb689907609b0300000037e397fc7c91f5e40100000040fe3ad401f8959a04000000d2bc9897eed08f1502000000f78b278be53f454c02000000ed99c5acb25eedf502000000cbca25e39f14238702000000687ad44ad37f03c201000000bc9d89904f5b923f0100000068b66ba122c93fa70100000037c8bb1350a9a2a801000000ab3c0572291feb8b010000006772616e62616265696d6f6e617564690000000040787d010065cd1d00e1f505d85aae1ec0542205b0508f1f38e4750488467020d853e903603c5121d0bf760338323222a8591903402013236039cd02480ef423a82a8f0268f8d42470955c02b8dab525c05a3302d8c4962648bd1102e0b27727a855f601e8a05828e8fedf0180773929c0cacd01586d1a2af8f1be019053fb2a50d8b201d00edc2be0fca80138edbc2c48f2a001e06d9d2d80669a01c80d7e2e500f9501c0575e2f08b6900140323f30e0278d0148202031b0418a0108a3ff3120e8870120bedf32f0fb85013856c03398698401f0fda03478218301b8d87f35d8178201d8c26036183d8101b8223e37508d800188d21c38c8fc7f0168b5f93898877f01a829d139d8297f0120d6ab3ab8db7e0168ae803b389d7e0100ca9a3b68957e010000000051e211000600000000000000870000000000000000000000000000000000000000000000000000000000000088000000000000000000000000000000890000000000000000000000000000008a0000000000000000000000000000008b000000000000000000000000000000a8be110007000000000000008c000000000000000000000000000000000000000000000000000000000000008d0000000000000000000000000000008e0000000000000000000000000000008f00000000000000000000000000000090000000000000000000000000000000a9e81200040000000000000091000000000000000000000000000000000000000000000000000000000000008f00000000000000000000000200000000000000000000000000000000000000920000000000000000000000000000008f000000000000000000000000000000d1f71200090000000000000093000000000000000000000000000000000000000000000000000000000000009400000000000000000000000200000000000000000000000000000000000000950000000000000000000000000000008f00000000000000000000000000000093e812000a00000000000000960000000000000000000000000000000000000000000000000000000000000097000000000000000000000002000000000000000000000000000000000000008f00000000000000000000000000000098000000000000000000000000000000afbe1100070000000000000099000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000009b0000000000000000000000000000008f0000000000000000000000000000008f000000000000000000000000000000b6be110008000000000000009c000000000000000000000000000000000000000000000000000000000000009d0000000000000000000000000000009e0000000000000000000000000000009f000000000000000000000000000000a0000000000000000000000000000000e3f712001200000000000000a1000000000000000000000000000000000000000000000000000000020000000000000000000000000000000200000000000000000000000000000000000000a20000000000000000000000000000008f000000000000000000000000000000f7f612000700000000000000a300000000000000000000000000000000000000000000000000000000000000a4000000000000000000000000000000a5000000000000000000000000000000a6000000000000000000000000000000a7000000000000000000000000000000a3f612000700000000000000a800000000000000000000000000000000000000000000000000000000000000a9000000000000000000000000000000aa0000000000000000000000000000008f000000000000000000000000000000ab000000000000000000000000000000d9f112000900000000000000ac00000000000000000000000000000000000000000000000000000000000000ad000000000000000000000000000000ae000000000000000000000000000000af000000000000000000000000000000b0000000000000000000000000000000bebe11000700000000000000b100000000000000000000000000000000000000000000000000000000000000b2000000000000000000000000000000b30000000000000000000000000000008f000000000000000000000000000000b4000000000000000000000000000000c5be11001200000000000000b500000000000000000000000000000000000000000000000000000000000000b2000000000000000000000000000000b30000000000000000000000000000008f000000000000000000000000000000b4000000000000000000000000000000d7be11000900000000000000b600000000000000000000000000000000000000000000000000000000000000b7000000000000000000000000000000b8000000000000000000000000000000b9000000000000000000000000000000ba000000000000000000000000000000e0be11001300000000000000bb00000000000000000000000000000000000000000000000000000000000000bc000000000000000000000000000000bd0000000000000000000000000000008f0000000000000000000000000000008f0000000000000000000000000000003ef212000f000000020000000000000000000000000000000000000000000000000000000000000000000000be00000000000000000000000200000000000000000000000000000000000000bf000000000000000000000000000000c0000000000000000000000000000000f3be11000700000000000000c100000000000000000000000000000000000000000000000000000000000000c2000000000000000000000000000000c30000000000000000000000000000008f000000000000000000000000000000c400000000000000000000000000000006f812000800000000000000c500000000000000000000000000000000000000000000000000000000000000c6000000000000000000000000000000c7000000000000000000000000000000c8000000000000000000000000000000c900000000000000000000000000000071ec12000900000000000000ca00000000000000000000000000000000000000000000000000000000000000cb000000000000000000000000000000cc000000000000000000000000000000cd000000000000000000000000000000ce000000000000000000000000000000d52112000400000000000000cf00000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000d10000000000000000000000000000008f000000000000000000000000000000d200000000000000000000000000000008f412000800000000000000d300000000000000000000000000000000000000000000000000000000000000d4000000000000000000000000000000d50000000000000000000000000000008f000000000000000000000000000000d60000000000000000000000000000007de81200120000000200000000000000000000000000000000000000000000000000000000000000000000008f000000000000000000000002000000000000000000000000000000000000008f0000000000000000000000000000008f00000000000000000000000000000022f412000800000000000000d7000000000000000000000000000000000000000000000000000000000000008f000000000000000000000000000000d80000000000000000000000000000008f0000000000000000000000000000008f00000000000000000000000000000082b412001800000000000000d9000000000000000000000000000000000000000000000000000000000000008f000000000000000000000002000000000000000000000000000000000000008f0000000000000000000000000000008f000000000000000000000000000000fabe11000800000000000000da00000000000000000000000000000000000000000000000000000000000000db000000000000000000000000000000dc000000000000000000000000000000dd000000000000000000000000000000de000000000000000000000000000000a20d12000700000000000000df00000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000e1000000000000000000000000000000e2000000000000000000000000000000e300000000000000000000000000000078d112000800000000000000e400000000000000000000000000000000000000000000000000000000000000e5000000000000000000000000000000e60000000000000000000000000000008f000000000000000000000000000000e700000000000000000000000000000002bf11000700000000000000e800000000000000000000000000000000000000000000000000000000000000e9000000000000000000000000000000ea000000000000000000000000000000eb000000000000000000000000000000ec00000000000000000000000000000009bf11000900000000000000ed000000000000000000000000000000000000000000000000000000000000008f000000000000000000000000000000ee0000000000000000000000000000008f0000000000000000000000000000008f00000000000000000000005574696c697479496e646963657342616c616e636573436f756e63696c546563686e6963616c436f6d6d6974746565456c656374696f6e73546563686e6963616c4d656d626572736869704772616e6470614964656e7469747956657374696e675363686564756c6572000000000000bcbf11001600000000000000d4bf1100010000000000000000000000dcbf11001500000000000000f4bf1100010000000000000000000000fcbf1100150000000000000014c011000100000000000000000000001cc011001a0000000000000038c0110001000000000000000000000040c01100100000000000000050c0110001000000000000000000000058c01100150000000000000070c011000100000000000000496e76616c69645363686564756c6556657273696f6e00007cc1110041000000496e76616c6964537572636861726765436c61696d00000027c1110055000000496e76616c6964536f75726365436f6e7472616374000000f0c0110037000000496e76616c696444657374696e6174696f6e436f6e74726163740000bfc0110031000000496e76616c6964546f6d6273746f6e65a7c0110018000000496e76616c6964436f6e74726163744f726967696e00000078c011002f00000020416e206f726967696e20547269654964207772697474656e20696e207468652063757272656e7420626c6f636b2e20546f6d6273746f6e657320646f6e2774206d617463682e2043616e6e6f7420726573746f726520746f206e6f6e6578697374696e67206f7220616c69766520636f6e74726163742e2043616e6e6f7420726573746f72652066726f6d206e6f6e6578697374696e67206f7220746f6d6273746f6e6520636f6e74726163742e20416e206f726967696e206d757374206265207369676e6564206f7220696e686572656e7420616e6420617578696c696172792073656e646572206f6e6c792070726f7669646564206f6e20696e686572656e742e2041206e6577207363686564756c65206d7573742068617665206120677265617465722076657273696f6e207468616e207468652063757272656e74206f6e652e0000000000000080c31100130000000000000006cf12000e00000000000000301a130094c311000000000000000000a4c31100040000000000000000000000c4c311001000000000000000b66c12000c00000000000000301a13001cc411000000000000000000d4c31100010000000000000000000000dcc31100110000000000000060dc12000300000000000000301a1300f0c31100000000000000000000c4110002000000000000000000000010c411000b00000000000000b66c12000c00000000000000301a13001cc4110000000000000000002cc4110001000000000000000000000034c411001100000000000000b66c12000c00000000000000301a130048c41100000000000000000058c4110007000000000000000000000090c411000f00000000000000b66c12000c00000000000000301a1300a0c411000000000000000000b0c41100020000000000000000000000c0c41100080000000000000060dc12000300000000000000301a1300c8c411000000000000000000d8c41100020000000000000000000000e8c411000c0000000000000060dc12000300000000000000301a1300f4c41100000000000000000004c5110001000000000000005369676e6564436c61696d48616e646963617000420000000000000001000000ef0000007fc8110038000000301a130000000000b7c8110043000000fac811001a000000546f6d6273746f6e654465706f7369744ac811003500000053746f7261676553697a654f6666736574000000420000000000000001000000f0000000ccc711005500000021c811002900000052656e744279746546656500420000000000000001000000680000007fc711004d00000052656e744465706f7369744f6666736574000000420000000000000001000000f100000007c611004100000048c6110016000000301a1300000000005ec611005a000000b8c61100560000000ec711005300000061c711001e00000053757263686172676552657761726400420000000000000001000000f2000000b4c5110039000000edc511001a0000004d61784465707468420000000000000001000000f30000005ac511004c000000a6c511000e0000004d617856616c756553697a65420000000000000001000000f40000000cc511004e00000020546865206d6178696d756d2073697a65206f6620612073746f726167652076616c756520696e2062797465732e204120726561736f6e61626c652064656661756c74206973203136204b69422e20546865206d6178696d756d206e657374696e67206c6576656c206f6620612063616c6c2f696e7374616e746961746520737461636b2e204120726561736f6e61626c652064656661756c742076616c7565206973203130302e205265776172642074686174206973207265636569766564206279207468652070617274792077686f736520746f75636820686173206c656420746f2072656d6f76616c206f66206120636f6e74726163742e2054686520616d6f756e74206f662066756e6473206120636f6e74726163742073686f756c64206465706f73697420696e206f7264657220746f206f66667365742074686520636f7374206f66206f6e6520627974652e204c6574277320737570706f736520746865206465706f73697420697320312c303030204255202862616c616e636520756e697473292f6279746520616e64207468652072656e7420697320312042552f627974652f6461792c207468656e206120636f6e7472616374207769746820312c3030302c3030302042552074686174207573657320312c303030206279746573206f662073746f7261676520776f756c6420706179206e6f2072656e742e20427574206966207468652062616c616e6365207265647563656420746f203530302c30303020425520616e64207468652073746f7261676520737461796564207468652073616d6520617420312c3030302c207468656e20697420776f756c6420706179203530302042552f6461792e205072696365206f6620612062797465206f662073746f7261676520706572206f6e6520626c6f636b20696e74657276616c2e2053686f756c642062652067726561746572207468616e20302e2053697a65206f66206120636f6e7472616374206174207468652074696d65206f6620696e7374616e74696174696f6e2e205468697320697320612073696d706c652077617920746f20656e73757265207468617420656d70747920636f6e747261637473206576656e7475616c6c7920676574732064656c657465642e20546865206d696e696d756d20616d6f756e7420726571756972656420746f2067656e6572617465206120746f6d6273746f6e652e204e756d626572206f6620626c6f636b2064656c617920616e2065787472696e73696320636c61696d20737572636861726765206861732e205768656e20636c61696d207375726368617267652069732063616c6c656420627920616e2065787472696e736963207468652072656e7420697320636865636b656420666f722063757272656e745f626c6f636b202d2064656c61790000000074ca110008000000000000007cca110003000000000000000000000094ca11000100000000000000000000009cca11000c0000000000000098ad1200020000000000000000000000a8ca1100010000000000000000000000b0ca1100070000000000000048121200020000000000000000000000b8ca1100060000000000000000000000e8ca11000800000000000000f0ca110005000000000000000000000018cb110009000000000000000000000060cb11000a00000000000000d4b112000100000000000000000000006ccb110001000000000000000000000074cb11000f00000000000000f012120001000000000000000000000084cb11000100000000000000000000008ccb11000a000000000000004812120002000000000000000000000098cb1100020000000000000000000000a8cb11001100000000000000bccb1100020000000000000000000000cccb110001000000000000005472616e7366657220af12000900000020af120009000000f6151200070000004bcf11005a000000496e7374616e74696174656414cf11003700000045766963746564004bce110039000000301a1300000000000ecd110009000000301a13000000000084ce110043000000c7ce11004d000000526573746f72656420af12000900000020af12000900000089b2120004000000f615120007000000a1f5120004000000dfcc11002f000000301a1300000000000ecd110009000000301a13000000000017cd11003d00000054cd11003b0000008fcd11003a000000c9cd1100460000000fce11003c000000436f646553746f7265640000b1cc11002e0000005363686564756c65557064617465640081cc11003000000044697370617463686564000016cc11004e00000064cc11001d000000436f6e7472616374457865637574696f6e00000020af120009000000cc8d120007000000d4cb11004200000020416e206576656e74206465706f73697465642075706f6e20657865637574696f6e206f66206120636f6e74726163742066726f6d20746865206163636f756e742e20412063616c6c2077617320646973706174636865642066726f6d2074686520676976656e206163636f756e742e2054686520626f6f6c207369676e616c73207768657468657220697420776173207375636365737366756c20657865637574696f6e206f72206e6f742e20547269676765726564207768656e207468652063757272656e74207363686564756c6520697320757064617465642e20436f646520776974682074686520737065636966696564206861736820686173206265656e2073746f7265642e20526573746f726174696f6e20666f72206120636f6e747261637420686173206265656e20696e697469617465642e202320506172616d73202d2060646f6e6f72603a20604163636f756e744964603a204163636f756e74204944206f662074686520726573746f72696e6720636f6e7472616374202d206064657374603a20604163636f756e744964603a204163636f756e74204944206f662074686520726573746f72656420636f6e7472616374202d2060636f64655f68617368603a206048617368603a20436f64652068617368206f662074686520726573746f72656420636f6e7472616374202d206072656e745f616c6c6f77616e63653a206042616c616e6365603a2052656e7420616c6c6f77616e6365206f662074686520726573746f72656420636f6e7472616374202d206073756363657373603a2060626f6f6c603a20547275652069662074686520726573746f726174696f6e20776173207375636365737366756c20436f6e747261637420686173206265656e206576696374656420616e64206973206e6f7720696e20746f6d6273746f6e652073746174652e202d2060636f6e7472616374603a20604163636f756e744964603a20546865206163636f756e74204944206f6620746865206576696374656420636f6e74726163742e202d2060746f6d6273746f6e65603a2060626f6f6c603a205472756520696620746865206576696374656420636f6e7472616374206c65667420626568696e64206120746f6d6273746f6e652e20436f6e7472616374206465706c6f7965642062792061646472657373206174207468652073706563696669656420616464726573732e205472616e736665722068617070656e6564206066726f6d6020746f2060746f60207769746820676976656e206076616c7565602061732070617274206f662061206063616c6c60206f722060696e7374616e7469617465602e0000000000000084d011000f0000000000000094d01100010000000000000000000000acd01100030000000000000000000000c4d01100080000000000000040ea1100010000000000000000000000ccd01100020000000000000000000000fbea12000400000000000000dcd011000400000000000000000000003cd1110007000000000000000000000074d111000b0000000000000080d11100040000000000000000000000e0d111000a000000000000000000000030d211000f0000000000000040d2110002000000000000000000000070d2110005000000000000007570646174655f7363686564756c650000000000a8d811000800000000000000b0d811000800000038d811002d000000301a13000000000065d81100430000007075745f636f6465acd711005700000003d811003500000000000000b2d311000400000000000000f32012002300000000000000aa4d12000500000000000000807512001500000000000000ead511000900000000000000f3d511000c0000000000000013d611000400000000000000cc8d12000700000017d6110042000000301a13000000000059d611004a000000a3d611002c000000cfd611004600000015d711005200000067d7110045000000696e7374616e74696174650000000000e1d511000900000000000000807512001500000000000000ead511000900000000000000f3d511000c00000000000000ffd51100090000000000000008d611000b0000000000000013d611000400000000000000cc8d120007000000c0d311006f000000301a1300000000002fd4110026000000301a13000000000055d4110050000000a5d4110041000000e6d411005b00000041d511005700000098d511002a000000c2d511001f000000636c61696d5f7375726368617267650000000000b2d3110004000000000000007ac312000c00000000000000b6d311000a00000000000000dddb12001400000098d211005c000000f4d2110045000000301a13000000000039d311004e00000087d311002b00000020416c6c6f777320626c6f636b2070726f64756365727320746f20636c61696d206120736d616c6c2072657761726420666f72206576696374696e67206120636f6e74726163742e204966206120626c6f636b2070726f6475636572206661696c7320746f20646f20736f2c206120726567756c61722075736572732077696c6c20626520616c6c6f77656420746f20636c61696d20746865207265776172642e20496620636f6e7472616374206973206e6f742065766963746564206173206120726573756c74206f6620746869732063616c6c2c206e6f20616374696f6e73206172652074616b656e20616e64207468652073656e646572206973206e6f7420656c696769626c6520666f7220746865207265776172642e646573746175785f73656e64657220496e7374616e7469617465732061206e657720636f6e74726163742066726f6d207468652060636f646568617368602067656e65726174656420627920607075745f636f6465602c206f7074696f6e616c6c79207472616e7366657272696e6720736f6d652062616c616e63652e20496e7374616e74696174696f6e20697320657865637574656420617320666f6c6c6f77733a202d205468652064657374696e6174696f6e206164647265737320697320636f6d7075746564206261736564206f6e207468652073656e64657220616e642068617368206f662074686520636f64652e202d2054686520736d6172742d636f6e7472616374206163636f756e7420697320637265617465642061742074686520636f6d707574656420616464726573732e202d20546865206063746f725f636f64656020697320657865637574656420696e2074686520636f6e74657874206f6620746865206e65776c792d63726561746564206163636f756e742e204275666665722072657475726e656420202061667465722074686520657865637574696f6e206973207361766564206173207468652060636f646560206f6620746865206163636f756e742e205468617420636f64652077696c6c20626520696e766f6b656420202075706f6e20616e792063616c6c2072656365697665642062792074686973206163636f756e742e202d2054686520636f6e747261637420697320696e697469616c697a65642e656e646f776d656e746761735f6c696d6974436f6d706163743c4761733e636f64655f68617368436f6465486173683c543e64617461204d616b657320612063616c6c20746f20616e206163636f756e742c206f7074696f6e616c6c79207472616e7366657272696e6720736f6d652062616c616e63652e202a20496620746865206163636f756e74206973206120736d6172742d636f6e7472616374206163636f756e742c20746865206173736f63696174656420636f64652077696c6c20626520657865637574656420616e6420616e792076616c75652077696c6c206265207472616e736665727265642e202a20496620746865206163636f756e74206973206120726567756c6172206163636f756e742c20616e792076616c75652077696c6c206265207472616e736665727265642e202a204966206e6f206163636f756e742065786973747320616e64207468652063616c6c2076616c7565206973206e6f74206c657373207468616e20606578697374656e7469616c5f6465706f736974602c206120726567756c6172206163636f756e742077696c6c206265206372656174656420616e6420616e792076616c75652077696c6c206265207472616e736665727265642e2053746f7265732074686520676976656e2062696e617279205761736d20636f646520696e746f2074686520636861696e27732073746f7261676520616e642072657475726e73206974732060636f646568617368602e20596f752063616e20696e7374616e746961746520636f6e747261637473206f6e6c7920776974682073746f72656420636f64652e205570646174657320746865207363686564756c6520666f72206d65746572696e6720636f6e7472616374732e20546865207363686564756c65206d7573742068617665206120677265617465722076657273696f6e207468616e207468652073746f726564207363686564756c652e7363686564756c655363686564756c650000000062ec12000f0000000000000000000000b0d811000800000000000000000000000000000000000000000000000000000000000000301a130070da1100000000000000000080da11000100000000000000010000000000000014b011000c000000010600000000000008d611000b00000000000000cc8d12000700000000000000000000000000000000000000301a130088da1100000000000000000098da11000100000000000000000000000000000020b011000b000000010600000000000008d611000b00000000000000a0da11001600000000000000000000000000000000000000301a1300e8da11000000000000000000b8da1100010000000000000000000000000000007aec12000e000000000000000000000010f111000300000000000000000000000000000000000000000000000000000000000000301a1300c0da11000000000000000000d0da1100010000000000000001000000000000002bb011000e00000001050000000000007ac312000c00000000000000d8da11000f00000000000000000000000000000000000000301a1300e8da11000000000000000000f8da1100010000000000000000000000420000000000000001000000f5000000f1db110025000000420000000000000001000000f600000098db1100590000007761736d3a3a5072656661625761736d4d6f64756c6500003fdb1100590000004200000000000000010000006e0000002adb110015000000436f6e7472616374496e666f3c543e004200000000000000010000005b00000000db11002a0000002054686520636f6465206173736f6369617465642077697468206120676976656e206163636f756e742e20546865207375627472696520636f756e7465722e2041206d617070696e67206265747765656e20616e206f726967696e616c20636f6465206861736820616e6420696e737472756d656e746564207761736d20636f64652c20726561647920666f7220657865637574696f6e2e2041206d617070696e672066726f6d20616e206f726967696e616c20636f6465206861736820746f20746865206f726967696e616c20636f64652c20756e746f756368656420627920696e737472756d656e746174696f6e2e2043757272656e7420636f7374207363686564756c6520666f7220636f6e7472616374732e00000000000050dc11000e0000000000000060dc110001000000000000000000000068dc1100070000000000000070dc11000100000000000000416c72656164795570646174656400009cdc11003200000042616448696e740078dc1100240000002046696e616c697a6564206865696768742061626f766520626c6f636b206e756d6265722046696e616c2068696e74206d7573742062652075706461746564206f6e6c79206f6e636520696e2074686520626c6f636b00000000000040dd11000a0000000000000006cf12000e00000000000000301a13004cdd110000000000000000005cdd110001000000000000000000000064dd11000d0000000000000006cf12000e00000000000000301a130074dd1100000000000000000084dd1100010000000000000057696e646f7753697a650000420000000000000001000000f7000000d3dd1100460000005265706f72744c6174656e6379000000420000000000000001000000f80000008cdd110047000000205468652064656c617920616674657220776869636820706f696e74207468696e6773206265636f6d6520737573706963696f75732e2044656661756c7420697320313030302e20546865206e756d626572206f6620726563656e742073616d706c657320746f206b6565702066726f6d207468697320636861696e2e2044656661756c74206973203130312e0000000000000048de11000a0000000000000054de11000100000000000000000000006cde1100020000000000000066696e616c5f68696e74000000000000d4de11000400000000000000d8de1100170000007cde11003d000000b9de11001b0000002048696e7420746861742074686520617574686f72206f66207468697320626c6f636b207468696e6b732074686520626573742066696e616c697a656420626c6f636b2069732074686520676976656e206e756d6265722e68696e74436f6d706163743c543a3a426c6f636b4e756d6265723e000000000028df11001200000000000000b66c12000c00000000000000301a13003cdf110000000000000000004cdf110001000000000000005472616e73616374696f6e427974654665650000420000000000000001000000f900000054df110043000000205468652066656520746f206265207061696420666f72206d616b696e672061207472616e73616374696f6e3b20746865207065722d6279746520706f7274696f6e2e0000000000f5f71200110000000000000000000000f0df11000a00000000000000000000000000000000000000000000000000000000000000301a1300fcdf11000000000000000000301a13000000000000000000010000004d756c7469706c69657200004200000000000000010000005f0000005570646174654f72646572656448696e74734d656469616e616c77617973206174206c65617374206f6e6520726563656e742073616d706c653b20716564000020e111003c0000006f0000002b000000726563656e7420616e64206f72646572656420636f6e7461696e207468652073616d65206974656d733b2071656400004200000004000000040000000d00000020e111003c0000007a0000001b0000007072756e696e672064696374617465642062792077696e646f775f73697a6520776869636820697320616c776179732073617475726174656420617420313b207165640020e111003c000000950000001100000020e111003c0000008f0000001900000020e111003c00000090000000190000002f686f6d652f6461766964642f6465762f7375627374726174652f6672616d652f66696e616c6974792d747261636b65722f7372632f6c69622e72734e6f6e5a65726f526566436f756e744e6f6e44656661756c74436f6d706f736974654661696c6564546f4578747261637452756e74696d6556657273696f6e5370656356657273696f6e4e65656473546f496e637265617365496e76616c6964537065634e616d653a65787472696e7369635f696e64657866696c6c5f626c6f636b72656d61726b7365745f686561705f70616765737365745f636f64657365745f636f64655f776974686f75745f636865636b737365745f6368616e6765735f747269655f636f6e6669677365745f73746f726167656b696c6c5f73746f726167656b696c6c5f7072656669787375696369646553797374656d4163636f756e74426c6f636b486173684e756d626572506172656e744861736845787472696e73696373526f6f74446967657374000000000068e31100100000000000000078e3110001000000000000000000000080e3110001000000000000000000000088e311000f0000000000000098e31100020000000000000000000000a8e31100010000000000000000000000b0e311000b00000000000000301a1300000000000000000000000000bce31100010000000000000000000000c4e311000a0000000000000074ad1200010000000000000000000000d0e31100010000000000000000000000d8e311000d0000000000000074ad1200010000000000000000000000e8e31100010000000000000045787472696e736963537563636573734ce411000c00000058e411002500000045787472696e7369634661696c656400e00e13000d0000004ce411000c00000037e4110015000000436f6465557064617465640022e41100150000004e65774163636f756e74000007e411001b0000004b696c6c65644163636f756e74000000f0e311001700000020416e206163636f756e7420776173207265617065642e2041206e6577206163636f756e742077617320637265617465642e20603a636f6465602077617320757064617465642e20416e2065787472696e736963206661696c65642e4469737061746368496e666f20416e2065787472696e73696320636f6d706c65746564207375636365737366756c6c792e6164645f6d656d62657272656d6f76655f6d656d626572737761705f6d656d62657272657365745f6d656d626572736368616e67655f6b65797365745f7072696d65636c6561725f7072696d65000000000000d4e511000b00000000000000301a1300000000000000000000000000e0e51100010000000000000000000000e8e511000d00000000000000301a1300000000000000000000000000f8e5110001000000000000000000000000e611000e00000000000000301a130000000000000000000000000010e6110001000000000000000000000018e611000c00000000000000301a130000000000000000000000000024e61100010000000000000000000000180d12000a00000000000000301a13000000000000000000000000002ce6110001000000000000000000000034e6110005000000000000003ce6110001000000000000000000000044e6110001000000000000004d656d62657241646465640071e71100390000004d656d62657252656d6f76656400000036e711003b0000004d656d62657273537761707065640000ffe61100370000004d656d626572735265736574b9e611004600000097e611002200000044756d6d7900000068e611002f0000004ce611001c000000205068616e746f6d206d656d6265722c206e6576657220757365642e73705f7374643a3a6d61726b65723a3a5068616e746f6d446174613c284163636f756e7449642c204576656e74293e204f6e65206f6620746865206d656d6265727327206b657973206368616e6765642e20546865206d656d62657273686970207761732072657365743b2073656520746865207472616e73616374696f6e20666f722077686f20746865206e6577207365742069732e2054776f206d656d62657273207765726520737761707065643b2073656520746865207472616e73616374696f6e20666f722077686f2e2054686520676976656e206d656d626572207761732072656d6f7665643b2073656520746865207472616e73616374696f6e20666f722077686f2e2054686520676976656e206d656d626572207761732061646465643b2073656520746865207472616e73616374696f6e20666f722077686f2e0000420000000400000004000000fa000000420000000000000001000000460000004576656e74734576656e74546f7069637300000000000000d4e111000a0000000000000098e91100010000000000000000000000b0e91100010000000000000000000000dee111000600000000000000b8e91100010000000000000000000000d0e91100050000000000000000000000e4e111000e00000000000000f8e9110001000000000000000000000010ea1100060000000000000000000000f2e11100080000000000000040ea110001000000000000000000000058ea1100080000000000000000000000fae11100170000000000000040ea110001000000000000000000000098ea110007000000000000000000000011e211001700000000000000d0ea1100010000000000000000000000e8ea110007000000000000000000000028e211000b0000000000000020eb110001000000000000000000000038eb110006000000000000000000000033e211000c0000000000000068eb110001000000000000000000000080eb11000600000000000000000000003fe211000b00000000000000b0eb1100010000000000000000000000c8eb11000600000000000000000000004ae211000700000000000000301a1300000000000000000000000000f8eb110007000000000000000000000077f1110006000000000000007df111000700000035f1110042000000000000002ef111000700000000000000cc8d12000700000013f111001b000000301a130000000000f5bd12000b000000adec11000900000044be12000c000000000000000bf11100050000000000000010f1110003000000b9f011003f000000301a130000000000f5bd12000b000000adec110009000000f8f011001300000044be12000c00000000000000b5f011000400000000000000cc8d120007000000f0ef11001a000000301a130000000000f5bd12000b0000000af011004d000000c3ef11002200000057f011005e000000e5ef11000b00000044be12000c00000058ef110047000000301a130000000000f5bd12000b0000009fef110024000000c3ef110022000000e5ef11000b00000044be12000c0000000000000025ef1100130000000000000038ef1100200000005fee110028000000301a130000000000f5bd12000b00000087ee110026000000adee11002c000000d9ee11004c00000044be12000c000000000000004dee1100050000000000000052ee11000d000000eeed11001b000000301a130000000000f5bd12000b00000009ee1100250000002eee11001f00000044be12000c00000000000000a79612000400000000000000e6ed11000800000070ed11001e000000301a130000000000f5bd12000b0000008eed11003f000000cded11001900000044be12000c000000000000006aed110006000000000000003422120003000000d5ec110045000000301a130000000000f5bd12000b0000001aed11003700000051ed11001900000044be12000c00000030ec11005900000089ec110024000000301a130000000000f5bd12000b000000adec110009000000b6ec11001f00000044be12000c000000204b696c6c207468652073656e64696e67206163636f756e742c20617373756d696e6720746865726520617265206e6f207265666572656e636573206f75747374616e64696e6720616e642074686520636f6d706f73697465206461746120697320657175616c20746f206974732064656661756c742076616c75652e202d20604f28312960202d20312073746f72616765207265616420616e642064656c6574696f6e2e204b696c6c20616c6c2073746f72616765206974656d7320776974682061206b657920746861742073746172747320776974682074686520676976656e207072656669782e202d20604f285029602077686572652060506020616d6f756e74206f66206b657973207769746820707265666978206070726566697860202d206050602073746f726167652064656c6574696f6e732e707265666978204b696c6c20736f6d65206974656d732066726f6d2073746f726167652e202d20604f28564b296020776865726520605660206c656e677468206f6620606b6579736020616e6420604b60206c656e677468206f66206f6e65206b6579202d206056602073746f726167652064656c6574696f6e732e5665633c4b65793e2053657420736f6d65206974656d73206f662073746f726167652e202d20604f2849296020776865726520604960206c656e677468206f6620606974656d7360202d206049602073746f72616765207772697465732028604f28312960292e6974656d735665633c4b657956616c75653e2053657420746865206e6577206368616e676573207472696520636f6e66696775726174696f6e2e202d20604f2844296020776865726520604460206c656e677468206f66206044696765737460202d20312073746f72616765207772697465206f722064656c6574652028636f64656320604f28312960292e202d20312063616c6c20746f20606465706f7369745f6c6f67603a20604f284429602028776869636820646570656e6473206f6e20746865206c656e677468206f66206044696765737460296368616e6765735f747269655f636f6e6669674f7074696f6e3c4368616e67657354726965436f6e66696775726174696f6e3e2053657420746865206e65772072756e74696d6520636f646520776974686f757420646f696e6720616e7920636865636b73206f662074686520676976656e2060636f6465602e202d20604f2843296020776865726520604360206c656e677468206f662060636f646560202d20312073746f726167652077726974652028636f64656320604f28432960292e202d2031206576656e742e2053657420746865206e65772072756e74696d6520636f64652e202d20604f2843202b2053296020776865726520604360206c656e677468206f662060636f64656020616e642060536020636f6d706c6578697479206f66206063616e5f7365745f636f646560202d20312063616c6c20746f206063616e5f7365745f636f6465603a20604f28532960202863616c6c73206073705f696f3a3a6d6973633a3a72756e74696d655f76657273696f6e6020776869636820697320657870656e73697665292e636f64652053657420746865206e756d626572206f6620706167657320696e2074686520576562417373656d626c7920656e7669726f6e6d656e74277320686561702e202d20312073746f726167652077726974652e7061676573753634204d616b6520736f6d65206f6e2d636861696e2072656d61726b2e5f72656d61726b204120646973706174636820746861742077696c6c2066696c6c2074686520626c6f636b2077656967687420757020746f2074686520676976656e20726174696f2e5f726174696f50657262696c6c0000000057e211000700000001020000000000007ac312000c00000000000000acf611002500000000000000000000000000000000000000301a1300d4f611000000000000000000e4f6110001000000000000000100000000000000ecf611000e000000000000000000000060dc12000300000000000000000000000000000000000000000000000000000000000000301a130048f711000000000000000000fcf611000100000000000000000000000000000004f7110013000000000000000000000017f711000600000000000000000000000000000000000000000000000000000000000000301a130020f71100000000000000000030f711000100000000000000000000000000000038f7110010000000000000000000000060dc12000300000000000000000000000000000000000000000000000000000000000000301a130048f71100000000000000000058f71100010000000000000000000000000000005ee2110009000000010500000000000006cf12000e0000000000000091d912000700000000000000000000000000000000000000301a1300a0f71100000000000000000060f711000100000000000000010000000000000068f711000d000000010500000000000060dc12000300000000000000cc8d12000700000000000000000000000000000000000000301a130078f71100000000000000000088f711000100000000000000010000000000000067e2110006000000000000000000000006cf12000e00000000000000000000000000000000000000000000000000000000000000301a13002cf81100000000000000000090f71100010000000000000001000000000000006de211000a000000000000000000000091d912000700000000000000000000000000000000000000000000000000000000000000301a1300a0f71100000000000000000098f711000100000000000000010000000000000077e211000e000000000000000000000091d912000700000000000000000000000000000000000000000000000000000000000000301a1300a0f711000000000000000000b0f711000100000000000000010000000000000085e21100060000000000000000000000b8f711000b00000000000000000000000000000000000000000000000000000000000000301a1300c4f711000000000000000000d4f7110001000000000000000100000000000000cce71100060000000000000000000000dcf711002300000000000000000000000000000000000000000000000000000000000000301a130000f81100000000000000000010f811000100000000000000010000000000000018f811000a000000000000000000000022f811000a00000000000000000000000000000000000000000000000000000000000000301a13002cf8110000000000000000003cf8110001000000000000000100000000000000d2e711000b000000010200000000000091d91200070000000000000044f811002100000000000000000000000000000000000000301a130068f81100000000000000000078f811000a000000000000000100000000000000c8f81100120000000000000000000000daf811001600000000000000000000000000000000000000000000000000000000000000301a1300f0f81100000000000000000000f911000100000000000000000000000000000008f911000e000000000000000000000016f911000500000000000000000000000000000000000000000000000000000000000000301a13001cf9110000000000000000002cf911000100000000000000000000004163636f756e74496e666f3c543a3a496e6465782c20543a3a4163636f756e74446174613e000000420000000000000001000000fb0000004afe11003a00000045787472696e736963436f756e7400001cfe11002e000000416c6c45787472696e736963735765696768745765696768740000004200000000000000010000005b000000d7fd110045000000416c6c45787472696e736963734c656e4200000000000000010000005b00000087fd11005000000061fd11002600000045787472696e736963446174610000004200000000000000010000005900000012fd11004f000000d0fc110042000000b4fc11001c000000420000000000000001000000fc0000006ffc1100450000004469676573744f663c543e004200000000000000010000005900000033fc11003c0000005665633c4576656e745265636f72643c543a3a4576656e742c20543a3a486173683e3e00420000000000000001000000590000000bfc1100280000004576656e74436f756e744576656e74496e64657842000000000000000100000057000000ddfb11002e0000005665633c28543a3a426c6f636b4e756d6265722c204576656e74496e646578293e00000042000000000000000100000059000000abf9110049000000f4f9110025000000301a13000000000019fa1100540000006dfa110051000000befa110039000000301a130000000000f7fa1100530000004afb1100530000009dfb1100400000004c61737452756e74696d65557067726164654c61737452756e74696d6555706772616465496e666f4200000000000000010000005b00000056f9110055000000457865637574696f6e50686173655068617365004200000000000000010000005b00000034f91100220000002054686520657865637574696f6e207068617365206f662074686520626c6f636b2e2053746f726573207468652060737065635f76657273696f6e6020616e642060737065635f6e616d6560206f66207768656e20746865206c6173742072756e74696d6520757067726164652068617070656e65642e204d617070696e67206265747765656e206120746f7069632028726570726573656e74656420627920543a3a486173682920616e64206120766563746f72206f6620696e6465786573206f66206576656e747320696e2074686520603c4576656e74733c543e3e60206c6973742e20416c6c20746f70696320766563746f727320686176652064657465726d696e69737469632073746f72616765206c6f636174696f6e7320646570656e64696e67206f6e2074686520746f7069632e205468697320616c6c6f7773206c696768742d636c69656e747320746f206c6576657261676520746865206368616e67657320747269652073746f7261676520747261636b696e67206d656368616e69736d20616e6420696e2063617365206f66206368616e67657320666574636820746865206c697374206f66206576656e7473206f6620696e7465726573742e205468652076616c756520686173207468652074797065206028543a3a426c6f636b4e756d6265722c204576656e74496e646578296020626563617573652069662077652075736564206f6e6c79206a7573742074686520604576656e74496e64657860207468656e20696e20636173652069662074686520746f70696320686173207468652073616d6520636f6e74656e7473206f6e20746865206e65787420626c6f636b206e6f206e6f74696669636174696f6e2077696c6c20626520747269676765726564207468757320746865206576656e74206d69676874206265206c6f73742e20546865206e756d626572206f66206576656e747320696e2074686520604576656e74733c543e60206c6973742e204576656e7473206465706f736974656420666f72207468652063757272656e7420626c6f636b2e20446967657374206f66207468652063757272656e7420626c6f636b2c20616c736f2070617274206f662074686520626c6f636b206865616465722e2045787472696e7369637320726f6f74206f66207468652063757272656e7420626c6f636b2c20616c736f2070617274206f662074686520626c6f636b206865616465722e2048617368206f66207468652070726576696f757320626c6f636b2e205468652063757272656e7420626c6f636b206e756d626572206265696e672070726f6365737365642e205365742062792060657865637574655f626c6f636b602e2045787472696e73696373206461746120666f72207468652063757272656e7420626c6f636b20286d61707320616e2065787472696e736963277320696e64657820746f206974732064617461292e204d6170206f6620626c6f636b206e756d6265727320746f20626c6f636b206861736865732e20546f74616c206c656e6774682028696e2062797465732920666f7220616c6c2065787472696e736963732070757420746f6765746865722c20666f72207468652063757272656e7420626c6f636b2e20546f74616c2077656967687420666f7220616c6c2065787472696e736963732070757420746f6765746865722c20666f72207468652063757272656e7420626c6f636b2e20546f74616c2065787472696e7369637320636f756e7420666f72207468652063757272656e7420626c6f636b2e205468652066756c6c206163636f756e7420696e666f726d6174696f6e20666f72206120706172746963756c6172206163636f756e742049442e000000009cff1100120000000000000017f711000600000000000000301a1300b0ff11000000000000000000c0ff1100010000000000000000000000c8ff11000800000000000000d0ff11000f00000000000000301a1300e0ff11000000000000000000f0ff1100010000000000000000000000f8ff1100140000000000000017f711000600000000000000301a13000c00120000000000000000001c00120001000000000000000000000024001200130000000000000017f711000600000000000000301a13003800120000000000000000004800120001000000000000000000000050001200120000000000000060dc12000300000000000000301a13006400120000000000000000007400120001000000000000004d6178696d756d426c6f636b5765696768740000420000000000000001000000fd0000009a0112001f000000446257656967687452756e74696d65446257656967687400420000000000000001000000fe0000005801120042000000426c6f636b457865637574696f6e576569676874420000000000000001000000ff000000040112005400000045787472696e736963426173655765696768740042000000000000000100000000010000a60012005e0000004d6178696d756d426c6f636b4c656e6774680000420000000000000001000000010100007c0012002a00000020546865206d6178696d756d206c656e677468206f66206120626c6f636b2028696e206279746573292e20546865206261736520776569676874206f6620616e2045787472696e73696320696e2074686520626c6f636b2c20696e646570656e64656e74206f6620746865206f662065787472696e736963206265696e672065786563757465642e20546865206261736520776569676874206f6620657865637574696e67206120626c6f636b2c20696e646570656e64656e74206f6620746865207472616e73616374696f6e7320696e2074686520626c6f636b2e2054686520776569676874206f662072756e74696d65206461746162617365206f7065726174696f6e73207468652072756e74696d652063616e20696e766f6b652e20546865206d6178696d756d20776569676874206f66206120626c6f636b2e4e6f646520697320636f6e6669677572656420746f20757365207468652073616d6520686173683b207165640000000802120032000000ce0300001c0000000802120032000000d6030000110000002f686f6d652f6461766964642f6465762f7375627374726174652f6672616d652f73797374656d2f7372632f6c69622e7273436865636b56657273696f6e436865636b47656e65736973436865636b457261436865636b4e6f6e6365436865636b576569676874636f6465206973206e6f7420666f756e647072697374696e6520636f6465206973206e6f7420666f756e640000000000007de411000a00000000000000d0031200010000000000000000000000e803120003000000000000000000000087e411000d00000000000000d00312000100000000000000000000000004120003000000000000000000000094e411000b0000000000000018041200020000000000000000000000480412000500000000000000000000009fe411000d000000000000007004120001000000000000000000000088041200040000000000000000000000ace411000a00000000000000a8041200010000000000000000000000c0041200050000000000000000000000b6e411000900000000000000d0031200010000000000000000000000e8041200010000000000000000000000bfe411000b00000000000000301a1300000000000000000000000000f0041200010000000000000000000000f020120003000000000000007ac312000c000000af0712001f000000301a130000000000ce0712002d0000005b07120024000000301a1300000000007f07120030000000000000005207120006000000000000007ac312000c000000000000005807120003000000000000007ac312000c000000b006120030000000301a130000000000e00612002e000000301a1300000000000e0712004400000000000000a90612000700000000000000ddce12001100000009061200560000005f0612001b000000301a1300000000007a0612002f000000000000008421120003000000000000007ac312000c0000004e05120036000000301a130000000000840512003d000000301a130000000000c1051200480000001e05120030000000f8041200260000002052656d6f766520746865207072696d65206d656d626572206966206974206578697374732e2053657420746865207072696d65206d656d6265722e204d75737420626520612063757272656e74206d656d6265722e2053776170206f7574207468652073656e64696e67206d656d62657220666f7220736f6d65206f74686572206b657920606e6577602e204d6179206f6e6c792062652063616c6c65642066726f6d20605369676e656460206f726967696e206f6620612063757272656e74206d656d6265722e205072696d65206d656d62657273686970206973207061737365642066726f6d20746865206f726967696e206163636f756e7420746f20606e6577602c20696620657874616e742e204368616e676520746865206d656d6265727368697020746f2061206e6577207365742c20646973726567617264696e6720746865206578697374696e67206d656d626572736869702e204265206e69636520616e64207061737320606d656d6265727360207072652d736f727465642e204d6179206f6e6c792062652063616c6c65642066726f6d206052657365744f726967696e60206f7220726f6f742e6d656d626572732053776170206f7574206f6e65206d656d626572206072656d6f76656020666f7220616e6f746865722060616464602e204d6179206f6e6c792062652063616c6c65642066726f6d2060537761704f726967696e60206f7220726f6f742e205072696d65206d656d62657273686970206973202a6e6f742a207061737365642066726f6d206072656d6f76656020746f2060616464602c20696620657874616e742e72656d6f76656164642052656d6f76652061206d656d626572206077686f602066726f6d20746865207365742e204d6179206f6e6c792062652063616c6c65642066726f6d206052656d6f76654f726967696e60206f7220726f6f742e204164642061206d656d626572206077686f6020746f20746865207365742e204d6179206f6e6c792062652063616c6c65642066726f6d20604164644f726967696e60206f7220726f6f742e496e7374616e6365314d656d6265727368697000000000000009b51200070000000000000000000000ddce12001100000000000000000000000000000000000000000000000000000000000000301a1300c00812000000000000000000d0081200010000000000000001000000000000009caf12000500000000000000000000007ac312000c00000000000000000000000000000000000000000000000000000000000000301a1300d80812000000000000000000e80812000100000000000000000000004200000000000000010000005900000019091200320000004200000000000000010000005b000000f008120029000000205468652063757272656e74207072696d65206d656d6265722c206966206f6e65206578697374732e205468652063757272656e74206d656d626572736869702c2073746f72656420617320616e206f726465726564205665632e00301a1300000000005c091200020000003a203a6865617070616765733a636f64653a6368616e6765735f74726965000000000000b5e111000f00000000000000080a12000200000000000000000000009be111001a00000000000000180a12000200000000000000000000007ee111001d00000000000000280a12000300000000000000000000006be111001300000000000000400a12000100000000000000000000005ce111000f00000000000000480a12000100000000000000c30b120045000000ae0b1200150000005d0b120051000000ae0b120015000000de0a12003c000000301a1300000000001a0b1200430000009e0a120040000000500a12004e0000002054686572652069732061206e6f6e2d7a65726f207265666572656e636520636f756e742070726576656e74696e6720746865206163636f756e742066726f6d206265696e67207075726765642e20537569636964652063616c6c6564207768656e20746865206163636f756e7420686173206e6f6e2d64656661756c7420636f6d706f7369746520646174612e204661696c656420746f2065787472616374207468652072756e74696d652076657273696f6e2066726f6d20746865206e65772072756e74696d652e204569746865722063616c6c696e672060436f72655f76657273696f6e60206f72206465636f64696e67206052756e74696d6556657273696f6e60206661696c65642e205468652073706563696669636174696f6e2076657273696f6e206973206e6f7420616c6c6f77656420746f206465637265617365206265747765656e207468652063757272656e742072756e74696d6520616e6420746865206e65772072756e74696d652e20546865206e616d65206f662073706563696669636174696f6e20646f6573206e6f74206d61746368206265747765656e207468652063757272656e742072756e74696d65280c120036000000ac0000000d000000280c120036000000dd000000110000002f686f6d652f6461766964642f6465762f7375627374726174652f6672616d652f6d656d626572736869702f7372632f6c69622e7273526571756972655375646f7375646f7365745f6b65797375646f5f61730000000000000d12000500000000000000080d1200010000000000000000000000100d1200010000000000000000000000180d12000a0000000000000074ad1200010000000000000000000000240d12000100000000000000000000002c0d12000a00000000000000380d1200010000000000000000000000100d120001000000000000005375646964000000940d12000e0000007c0d1200180000004b65794368616e6765640000400d12003c0000005375646f4173446f6e650000a1f512000400000020546865207375646f6572206a757374207377697463686564206964656e746974793b20746865206f6c64206b657920697320737570706c6965642e2041207375646f206a75737420746f6f6b20706c6163652e4469737061746368526573756c74536f63696574794d61784d656d62657273566f7465734e6f74486561644e6f74466f756e6465724e6f7443616e646964617465416c726561647943616e646964617465416c7265616479426964466f756e646572486561644e6f74566f756368696e67416c7265616479566f756368696e67496e73756666696369656e74506f74416c7265616479466f756e6465644e6f5061796f75744e6f7453757370656e64656453757370656e646564416c72656164794d656d626572426164506f736974696f6e626964756e626964766f756368746970756e766f756368646566656e6465725f766f74657061796f7574666f756e64756e666f756e646a756467655f73757370656e6465645f6d656d6265726a756467655f73757370656e6465645f63616e6469646174657365745f6d61785f6d656d6265727300000000000070111200070000000000000074ad1200010000000000000000000000781112000100000000000000000000008011120003000000000000008411120002000000000000000000000094111200020000000000000000000000a41112000500000000000000ac111200030000000000000000000000c4111200020000000000000000000000d4111200090000000000000074ad1200010000000000000000000000e0111200010000000000000000000000e8111200050000000000000074ad1200010000000000000000000000f0111200010000000000000000000000f8111200070000000000000074ad1200010000000000000000000000001212000100000000000000000000000812120008000000000000001012120002000000000000000000000020121200020000000000000000000000301212001800000000000000481212000200000000000000000000005812120001000000000000000000000060121200120000000000000074ad1200010000000000000000000000741212000100000000000000000000007c1212000f0000000000000074ad12000100000000000000000000008c121200010000000000000000000000941212000a0000000000000074ad1200010000000000000000000000a0121200010000000000000000000000a81212000400000000000000ac121200030000000000000000000000c4121200010000000000000000000000cc1212000c0000000000000048121200020000000000000000000000d8121200010000000000000000000000e01212000d00000000000000f0121200010000000000000000000000f812120001000000000000000000000000131200090000000000000074ad12000100000000000000000000000c1312000100000000000000466f756e64656400641612002e0000004269640020af120009000000f615120007000000fd15120058000000551612000f000000566f75636800000020af120009000000f61512000700000020af1200090000006215120058000000ba1512003c0000004175746f556e6269640000002015120042000000556e626964000000f41412002c000000556e766f75636800b61412003e000000496e64756374656420af120009000000a81412000e00000035141200560000008b1412001d00000053757370656e6465644d656d6265724a756467656d656e7420af120009000000a1f5120004000000121412002300000043616e64696461746553757370656e6465640000f31312001f0000004d656d62657253757370656e64656400d71312001c0000004368616c6c656e6765640000ba1312001d000000566f746520af12000900000020af120009000000a1f51200040000008a13120030000000446566656e646572566f74654e1312003c0000004e65774d61784d656d6265727300000060dc1200030000002a13120024000000556e666f756e646564000000141312001600000020536f636965747920697320756e666f756e6465642e2041206e6577206d6178206d656d62657220636f756e7420686173206265656e20736574204120766f746520686173206265656e20706c6163656420666f72206120646566656e64696e67206d656d6265722028766f7465722c20766f746529204120766f746520686173206265656e20706c61636564202863616e6469646174652c20766f7465722c20766f7465292041206d656d62657220686173206265656e206368616c6c656e6765642041206d656d62657220686173206265656e2073757370656e64656420412063616e64696461746520686173206265656e2073757370656e64656420412073757370656e646564206d656d62657220686173206265656e206a756467656420412067726f7570206f662063616e646964617465732068617665206265656e20696e6475637465642e205468652062617463682773207072696d617279206973207468652066697273742076616c75652c2074686520626174636820696e2066756c6c20697320746865207365636f6e642e5665633c4163636f756e7449643e20412063616e646964617465207761732064726f70706564202862792072657175657374206f662077686f20766f756368656420666f72207468656d292e20412063616e646964617465207761732064726f70706564202862792074686569722072657175657374292e20412063616e646964617465207761732064726f70706564202864756520746f20616e20657863657373206f66206269647320696e207468652073797374656d292e2041206d656d6265727368697020626964206a7573742068617070656e656420627920766f756368696e672e2054686520676976656e206163636f756e74206973207468652063616e646964617465277320494420616e64207468656972206f6666657220697320746865207365636f6e642e2054686520766f756368696e67207061727479206973207468652074686972642e42616c616e63652041206d656d6265727368697020626964206a7573742068617070656e65642e2054686520676976656e206163636f756e74206973207468652063616e646964617465277320494420616e64207468656972206f6666657220697320746865207365636f6e642e2054686520736f636965747920697320666f756e6465642062792074686520676976656e206964656e746974792e5072656d61747572655374696c6c4f70656e4e6f7446696e646572556e6b6e6f776e546970416c72656164794b6e6f776e526561736f6e546f6f426967496e76616c696450726f706f73616c496e646578496e73756666696369656e7450726f706f7365727342616c616e636570726f706f73655f7370656e6472656a6563745f70726f706f73616c617070726f76655f70726f706f73616c7265706f72745f617765736f6d65726574726163745f7469707469705f6e6577636c6f73655f7469700000000054b11200080000000000000038191200010000000000000000000000401912000100000000000000000000004819120008000000000000005019120001000000000000000000000058191200010000000000000000000000601912000700000000000000681912000300000000000000000000008019120001000000000000000000000088191200080000000000000090191200020000000000000000000000a0191200010000000000000000000000a8191200050000000000000050191200010000000000000000000000b0191200010000000000000000000000b8191200080000000000000050191200010000000000000000000000c0191200010000000000000000000000c8191200070000000000000050191200010000000000000000000000d0191200010000000000000000000000d81912000600000000000000d4b11200010000000000000000000000e0191200010000000000000000000000e81912000a00000000000000d4b11200010000000000000000000000f4191200010000000000000000000000fc1912000900000000000000081a1200030000000000000000000000201a1200010000000000000000000000281a12000c00000000000000d4b11200010000000000000000000000341a1200010000000000000075b412000d000000f61b12000e0000005370656e64696e67f615120007000000bc1b12003a000000417761726465640075b412000d000000f61512000700000020af1200090000009c1b12002000000052656a656374656475b412000d000000f6151200070000006f1b12002d0000004275726e740000004c1b120023000000526f6c6c6f766572001b12004c0000004465706f73697400e01a1200200000004e65775469700000ba1a120026000000546970436c6f73696e670000831a120037000000546970436c6f73656400000089b212000400000020af120009000000f615120007000000611a1200220000005469705265747261637465643c1a1200250000002041207469702073756767657374696f6e20686173206265656e207265747261637465642e2041207469702073756767657374696f6e20686173206265656e20636c6f7365642e2041207469702073756767657374696f6e206861732072656163686564207468726573686f6c6420616e6420697320636c6f73696e672e2041206e6577207469702073756767657374696f6e20686173206265656e206f70656e65642e20536f6d652066756e64732068617665206265656e206465706f73697465642e205370656e64696e67206861732066696e69736865643b20746869732069732074686520616d6f756e74207468617420726f6c6c73206f76657220756e74696c206e657874207370656e642e20536f6d65206f66206f75722066756e64732068617665206265656e206275726e742e20412070726f706f73616c207761732072656a65637465643b2066756e6473207765726520736c61736865642e20536f6d652066756e64732068617665206265656e20616c6c6f63617465642e205765206861766520656e6465642061207370656e6420706572696f6420616e642077696c6c206e6f7720616c6c6f636174652066756e64732e204e65772070726f706f73616c2e496e636f6e73697374656e74207374617465202d20636f756c646e277420736574746c6520696d62616c616e636520666f722066756e6473207370656e74206279207472656173757279506f74736f63696574795f726f746174696f6e43616e646964617465730000000000617474656d707420746f20646976696465206279207a65726f000000941d120033000000390600001d000000941d1200330000008d0400000f0000007061796f757473652e31206f662066696e616c206974656d203d3d20746f74616c5f617070726f76616c733b20776f72737420636173652066696e642077696c6c20616c776179732072657475726e2074686174206974656d3b207165640000941d120033000000840500001f00000042696473657869746564206966206d656d6265727320656d7074793b20716564941d120033000000a30500001f000000446566656e646572446566656e646572566f746573736f63696574795f6368616c6c656e67650000941d1200330000001a06000033000000941d1200330000001a0600001e0000002f686f6d652f6461766964642f6465762f7375627374726174652f6672616d652f736f63696574792f7372632f6c69622e7273537472696b657353757370656e6465644d656d626572730000941d120033000000c60500001e0000005061796f757473000000000000000000617474656d707420746f2063616c63756c617465207468652072656d61696e646572207769746820612064697669736f72206f66207a65726f000000941d120033000000940400000500000000000000690c12000400000000000000d01e1200010000000000000000000000e81e12000a00000000000000000000006d0c12000700000000000000381f1200010000000000000000000000501f1200090000000000000000000000740c12000700000000000000981f1200020000000000000000000000c81f12000b0000000000000000000000fbea1200040000000000000061d1120017000000872112004e000000301a13000000000098c9120034000000301a130000000000f5bd12000b00000085201200080000008d20120019000000a620120018000000be2012003200000044be12000c00000000000000842112000300000000000000f320120023000000162112005d000000301a13000000000098c9120034000000301a130000000000f5bd12000b00000085201200080000008d20120019000000732112001100000044be12000c00000000000000f02012000300000000000000f32012002300000000000000fbea1200040000000000000061d112001700000020201200540000007420120011000000301a13000000000098c9120034000000301a130000000000f5bd12000b00000085201200080000008d20120019000000a620120018000000be2012003200000044be12000c0000002041757468656e7469636174657320746865207375646f206b657920616e64206469737061746368657320612066756e6374696f6e2063616c6c207769746820605369676e656460206f726967696e2066726f6d206120676976656e206163636f756e742e202d204f2831292e202d204c696d697465642073746f726167652072656164732e202d204f6e6520444220777269746520286576656e74292e202d20576569676874206f662064657269766174697665206063616c6c6020657865637574696f6e202b2031302c3030302e77686f3c543a3a4c6f6f6b7570206173205374617469634c6f6f6b75703e3a3a536f757263652041757468656e74696361746573207468652063757272656e74207375646f206b657920616e6420736574732074686520676976656e204163636f756e7449642028606e6577602920617320746865206e6577207375646f206b65792e202d204f6e65204442206368616e67652e6e65772041757468656e7469636174657320746865207375646f206b657920616e64206469737061746368657320612066756e6374696f6e2063616c6c20776974682060526f6f7460206f726967696e2e5375646f00000000000000342212000300000000000000000000007ac312000c00000000000000000000000000000000000000000000000000000000000000301a1300382212000000000000000000482212000100000000000000010000004b6579004200000000000000010000000201000050221200210000002054686520604163636f756e74496460206f6620746865207375646f206b65792e000000b4a21200390000009d0100001e000000b4a2120039000000fb01000029000000a422120048000000bb0100002d0000002f72757374632f666135316638313065356239323534393034623932363630653732383062376436613436663131322f7372632f6c6962636f72652f6f70732f61726974682e7273766563746f72207769746820706f736974697665206c656e6774682077696c6c20686176652061206d61783b20716564b4a2120039000000c5020000190000006974657261746f72207769746820706f736974697665206c656e6774682077696c6c20686176652061206d696e3b207165640000b4a2120039000000c902000019000000b4a2120039000000f40200001600000000000000660e1200030000000000000090251200010000000000000000000000a8251200210000000000000000000000690e12000500000000000000b0261200010000000000000000000000c82612001300000000000000000000006e0e1200050000000000000060271200030000000000000000000000a82712002c0000000000000000000000760e12000700000000000000b02612000100000000000000000000000829120011000000000000000000000014b01200040000000000000090291200020000000000000000000000c02912001300000000000000000000007d0e12000d00000000000000582a1200010000000000000000000000702a12001000000000000000000000008a0e12000600000000000000301a1300000000000000000000000000f02a1200140000000000000000000000900e12000500000000000000902b1200030000000000000000000000d82b1200130000000000000000000000950e12000700000000000000301a1300000000000000000000000000702c12000d00000000000000000000009c0e12001600000000000000d82c1200020000000000000000000000082d12001b0000000000000000000000b20e12001900000000000000e02d1200020000000000000000000000102e1200280000000000000000000000cb0e12000f00000000000000502f1200010000000000000000000000682f12000e0000000000000000000000aa4d12000500000000000000af4d12000f000000f94f120038000000301a130000000000315012004e0000007f5012003c000000301a13000000000098c9120034000000301a130000000000a3bd12000c000000bb50120056000000301a130000000000f5bd12000b00000011511200550000006749120011000000ec4912003b000000274a1200380000005f4a120037000000964a12003d0000007849120032000000d34a120012000000284b120060000000884b120040000000c84b1200170000000f4c12004b0000005a4c1200310000008b4c12001e000000a94c120027000000d04c120048000000184d12000a000000665112001a0000003a4d12003f000000301a130000000000794d12003100000044be12000c00000000000000f64f1200030000000000000060dc120003000000be4d120036000000f44d120040000000344e120021000000301a130000000000554e12003f000000301a130000000000944e120041000000301a130000000000a3bd12000c000000d54e120046000000301a130000000000f5bd12000b0000001b4f12002c000000474f1200430000008a4f1200510000002bc112000d000000301a130000000000db4f12001b00000044be12000c00000000000000f020120003000000000000007ac312000c00000000000000aa4d12000500000000000000af4d12000f00000000000000730e12000300000000000000af4d12000f000000f945120051000000301a1300000000004a461200550000009f46120057000000f646120050000000301a13000000000046471200560000009c47120054000000301a1300000000007b41120041000000301a130000000000a3bd12000c000000f047120033000000234812005400000077481200190000009048120052000000e248120045000000301a130000000000f5bd12000b000000274912004000000067491200110000007849120032000000aa49120042000000ec4912003b000000274a1200380000005f4a120037000000964a12003d000000d34a120012000000e54a120043000000284b120060000000884b120040000000c84b120017000000df4b1200300000000f4c12004b0000005a4c1200310000008b4c12001e000000a94c120027000000d04c120048000000184d12000a000000224d1200180000003a4d12003f000000301a130000000000794d12003100000044be12000c000000264412004b0000007144120025000000301a130000000000964412004a000000301a130000000000a3bd12000c000000e04412004b000000301a130000000000f5bd12000b0000002b451200150000004045120042000000824512003b000000bd451200250000002bc112000d000000301a130000000000e24512001700000044be12000c000000000000001d4412000900000000000000f320120023000000000000002bda12000700000000000000a1f5120004000000d042120022000000301a1300000000007b41120041000000301a130000000000a3bd12000c000000f242120043000000bc4112003d0000003543120036000000301a130000000000f5bd12000b0000006b4312002f0000003c421200470000009a43120016000000b04312004b000000834212002f0000002bc112000d000000301a130000000000fb4312002200000044be12000c000000000000002bda12000700000000000000a1f51200040000005841120023000000301a1300000000007b41120041000000301a130000000000a3bd12000c000000bc4112003d000000f941120029000000301a130000000000f5bd12000b000000224212001a0000003c42120047000000834212002f0000002bc112000d000000301a130000000000b24212001e00000044be12000c000000603e120051000000301a130000000000b13e12005a000000301a1300000000000b3f120048000000533f12001e000000301a130000000000713f120045000000b63f120013000000301a130000000000f5bd12000b000000c93f120047000000104012004900000059401200390000009240120039000000cb40120023000000ee40120044000000301a130000000000324112002600000044be12000c00000000000000493e120007000000000000007ac312000c00000000000000503e12000b0000000000000060dc120003000000000000005b3e12000500000000000000cc8d120007000000303c120013000000301a130000000000433c12003c0000007f3c120046000000301a130000000000c53c120047000000301a130000000000a3bd12000c0000000c3d120046000000523d120045000000973d12003d000000301a130000000000f5bd12000b000000d43d1200380000000c3e12003d0000002bc112000d000000301a130000000000e83012001700000044be12000c000000203b120023000000301a130000000000433b1200570000009a3b120056000000f03b120008000000301a130000000000f5bd12000b000000f83b12001a000000123c12001e0000002bc112000d000000301a130000000000e83012001700000044be12000c00000000000000f020120003000000000000007ac312000c00000000000000193b12000700000000000000a1f5120004000000603712004b000000301a130000000000ab371200560000000138120033000000301a13000000000034381200520000008638120040000000301a130000000000d832120050000000301a130000000000a3bd12000c000000c63812002d000000f33812004d0000004039120049000000301a130000000000f5bd12000b0000008939120029000000b23912003e000000f03912005c0000004c3a12003e0000008a3a120051000000bd36120035000000db3a12001c000000093712001f000000301a130000000000f73a12002200000044be12000c00000000000000f020120003000000000000007ac312000c000000000000004e37120009000000000000005737120009000000023112004d000000301a1300000000004f31120057000000a63112001d000000301a130000000000c3311200550000001832120044000000301a1300000000005c32120057000000b332120025000000301a130000000000d832120050000000301a130000000000a3bd12000c00000028331200300000005833120031000000301a130000000000f5bd12000b000000893312003d000000c63312003c0000000234120032000000343412001000000044341200450000008934120037000000c03412003a000000fa3412002d00000027351200280000004f3512002c0000007b35120053000000ce3512000f000000dd35120037000000143612004b0000005f3612000e0000006d36120050000000bd36120035000000f236120017000000093712001f000000301a130000000000283712002600000044be12000c00000000000000ff301200030000000000000060dc120003000000d82f1200470000001f3012002d000000301a1300000000004c30120037000000301a130000000000a3bd12000c0000008330120039000000301a130000000000f5bd12000b000000bc3012002c0000002bc112000d000000301a130000000000e83012001700000044be12000c00000020416c6c6f777320726f6f74206f726967696e20746f206368616e676520746865206d6178696d756d206e756d626572206f66206d656d6265727320696e20736f63696574792e204d6178206d656d6265727368697020636f756e74206d7573742062652067726561746572207468616e20312e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d7573742062652066726f6d205f524f4f545f2e202d20606d617860202d20546865206d6178696d756d206e756d626572206f66206d656d6265727320666f722074686520736f63696574792e202d204f6e652073746f7261676520777269746520746f2075706461746520746865206d61782e204f28312920546f74616c20436f6d706c65786974793a204f2831296d617820416c6c6f772073757370656e646564206a756467656d656e74206f726967696e20746f206d616b65206a756467656d656e74206f6e20612073757370656e6465642063616e6469646174652e20496620746865206a756467656d656e742069732060417070726f7665602c20776520616464207468656d20746f20736f63696574792061732061206d656d62657220776974682074686520617070726f707269617465207061796d656e7420666f72206a6f696e696e6720736f63696574792e20496620746865206a756467656d656e74206973206052656a656374602c2077652065697468657220736c61736820746865206465706f736974206f6620746865206269642c20676976696e67206974206261636b20746f2074686520736f63696574792074726561737572792c206f722077652062616e2074686520766f75636865722066726f6d20766f756368696e6720616761696e2e20496620746865206a756467656d656e7420697320605265626964602c20776520707574207468652063616e646964617465206261636b20696e207468652062696420706f6f6c20616e64206c6574207468656d20676f207468726f7567682074686520696e64756374696f6e2070726f6365737320616761696e2e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d7573742062652066726f6d20746865205f53757370656e73696f6e4a756467656d656e744f726967696e5f2e202d206077686f60202d205468652073757370656e6465642063616e64696461746520746f206265206a75646765642e202d20606a756467656d656e7460202d2060417070726f7665602c206052656a656374602c206f7220605265626964602e204b65793a204220286c656e206f662062696473292c204d20286c656e206f66206d656d62657273292c2058202862616c616e636520616374696f6e29202d204f6e652073746f72616765207265616420746f20636865636b206077686f6020697320612073757370656e6465642063616e6469646174652e202d204f6e652073746f726167652072656d6f76616c206f66207468652073757370656e6465642063616e6469646174652e202d20417070726f7665204c6f67696320092d204f6e652073746f72616765207265616420746f206765742074686520617661696c61626c6520706f7420746f2070617920757365727320776974682e204f28312920092d204f6e652073746f7261676520777269746520746f207570646174652074686520617661696c61626c6520706f742e204f28312920092d204f6e652073746f72616765207265616420746f20676574207468652063757272656e7420626c6f636b206e756d6265722e204f28312920092d204f6e652073746f72616765207265616420746f2067657420616c6c206d656d626572732e204f284d2920092d20557020746f206f6e6520756e726573657276652063757272656e637920616374696f6e2e20092d20557020746f2074776f206e65772073746f726167652077726974657320746f207061796f7574732e20092d20557020746f206f6e652073746f726167652077726974652077697468204f286c6f67204d292062696e6172792073656172636820746f206164642061206d656d62657220746f20736f63696574792e202d2052656a656374204c6f67696320092d20557020746f206f6e6520726570617472696174652072657365727665642063757272656e637920616374696f6e2e204f28582920092d20557020746f206f6e652073746f7261676520777269746520746f2062616e2074686520766f756368696e67206d656d6265722066726f6d20766f756368696e6720616761696e2e202d205265626964204c6f67696320092d2053746f72616765206d75746174652077697468204f286c6f672042292062696e6172792073656172636820746f20706c616365207468652075736572206261636b20696e746f20626964732e202d20557020746f206f6e65206164646974696f6e616c206576656e7420696620756e766f7563682074616b657320706c6163652e202d204f6e652073746f726167652072656d6f76616c2e202d204f6e65206576656e7420666f7220746865206a756467656d656e742e20546f74616c20436f6d706c65786974793a204f284d202b206c6f674d202b2042202b2058296a756467656d656e744a756467656d656e7420416c6c6f772073757370656e73696f6e206a756467656d656e74206f726967696e20746f206d616b65206a756467656d656e74206f6e20612073757370656e646564206d656d6265722e20496620612073757370656e646564206d656d62657220697320666f72676976656e2c2077652073696d706c7920616464207468656d206261636b2061732061206d656d6265722c206e6f7420616666656374696e6720616e79206f6620746865206578697374696e672073746f72616765206974656d7320666f722074686174206d656d6265722e20496620612073757370656e646564206d656d6265722069732072656a65637465642c2072656d6f766520616c6c206173736f6369617465642073746f72616765206974656d732c20696e636c7564696e67207468656972207061796f7574732c20616e642072656d6f766520616e7920766f7563686564206269647320746865792063757272656e746c7920686176652e202d206077686f60202d205468652073757370656e646564206d656d62657220746f206265206a75646765642e202d2060666f726769766560202d204120626f6f6c65616e20726570726573656e74696e672077686574686572207468652073757370656e73696f6e206a756467656d656e74206f726967696e202020202020202020202020202020666f726769766573202860747275656029206f722072656a6563747320286066616c7365602920612073757370656e646564206d656d6265722e204b65793a204220286c656e206f662062696473292c204d20286c656e206f66206d656d6265727329202d204f6e652073746f72616765207265616420746f20636865636b206077686f6020697320612073757370656e646564206d656d6265722e204f283129202d20557020746f206f6e652073746f72616765207772697465204f284d292077697468204f286c6f67204d292062696e6172792073656172636820746f206164642061206d656d626572206261636b20746f20736f63696574792e202d20557020746f20332073746f726167652072656d6f76616c73204f28312920746f20636c65616e20757020612072656d6f766564206d656d6265722e202d20557020746f206f6e652073746f72616765207772697465204f2842292077697468204f2842292073656172636820746f2072656d6f766520766f7563686564206269642066726f6d20626964732e202d204f6e652073746f726167652072656d6f76616c2e204f28312920546f74616c20436f6d706c65786974793a204f284d202b206c6f674d202b204229666f726769766520416e6e756c2074686520666f756e64696e67206f662074686520736f63696574792e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205369676e65642c20616e6420746865207369676e696e67206163636f756e74206d75737420626520626f7468207468652060466f756e6465726020616e6420746865206048656164602e205468697320696d706c6965732074686174206974206d6179206f6e6c7920626520646f6e65207768656e207468657265206973206f6e65206d656d6265722e202d2054776f2073746f72616765207265616473204f2831292e202d20466f75722073746f726167652072656d6f76616c73204f2831292e20466f756e642074686520736f63696574792e205468697320697320646f6e65206173206120646973637265746520616374696f6e20696e206f7264657220746f20616c6c6f7720666f7220746865206d6f64756c6520746f20626520696e636c7564656420696e746f20612072756e6e696e6720636861696e20616e642063616e206f6e6c7920626520646f6e65206f6e63652e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d7573742062652066726f6d20746865205f466f756e6465725365744f726967696e5f2e202d2060666f756e64657260202d20546865206669727374206d656d62657220616e642068656164206f6620746865206e65776c7920666f756e64656420736f63696574792e202d20606d61785f6d656d6265727360202d2054686520696e697469616c206d6178206e756d626572206f66206d656d6265727320666f722074686520736f63696574792e202d206072756c657360202d205468652072756c6573206f66207468697320736f636965747920636f6e6365726e696e67206d656d626572736869702e202d2054776f2073746f72616765206d75746174657320746f207365742060486561646020616e642060466f756e646572602e204f283129202d204f6e652073746f7261676520777269746520746f2061646420746865206669727374206d656d62657220746f20736f63696574792e204f283129666f756e6465726d61785f6d656d6265727372756c6573205472616e7366657220746865206669727374206d617475726564207061796f757420666f72207468652073656e64657220616e642072656d6f76652069742066726f6d20746865207265636f7264732e204e4f54453a20546869732065787472696e736963206e6565647320746f2062652063616c6c6564206d756c7469706c652074696d657320746f20636c61696d206d756c7469706c65206d617475726564207061796f7574732e205061796d656e743a20546865206d656d6265722077696c6c20726563656976652061207061796d656e7420657175616c20746f207468656972206669727374206d617475726564207061796f757420746f20746865697220667265652062616c616e63652e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e642061206d656d6265722077697468207061796f7574732072656d61696e696e672e204b65793a204d20286c656e206f66206d656d62657273292c205020286e756d626572206f66207061796f75747320666f72206120706172746963756c6172206d656d62657229202d204f6e652073746f726167652072656164204f284d2920616e64204f286c6f67204d292073656172636820746f20636865636b207369676e65722069732061206d656d6265722e202d204f6e652073746f726167652072656164204f28502920746f2067657420616c6c207061796f75747320666f722061206d656d6265722e202d204f6e652073746f726167652072656164204f28312920746f20676574207468652063757272656e7420626c6f636b206e756d6265722e202d204f6e652063757272656e6379207472616e736665722063616c6c2e204f285829202d204f6e652073746f72616765207772697465206f722072656d6f76616c20746f2075706461746520746865206d656d6265722773207061796f7574732e204f28502920546f74616c20436f6d706c65786974793a204f284d202b206c6f674d202b2050202b2058292041732061206d656d6265722c20766f7465206f6e2074686520646566656e6465722e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e642061206d656d6265722e202d2060617070726f7665603a204120626f6f6c65616e2077686963682073617973206966207468652063616e6469646174652073686f756c6420626520617070726f766564202860747275656029206f722072656a656374656420286066616c736560292e202d204b65793a204d20286c656e206f66206d656d6265727329202d204f6e652073746f726167652072656164204f284d2920616e64204f286c6f67204d292073656172636820746f20636865636b20757365722069732061206d656d6265722e202d204f6e652073746f7261676520777269746520746f2061646420766f746520746f20766f7465732e204f28312920546f74616c20436f6d706c65786974793a204f284d202b206c6f674d292041732061206d656d6265722c20766f7465206f6e20612063616e6469646174652e202d206063616e646964617465603a205468652063616e646964617465207468617420746865206d656d62657220776f756c64206c696b6520746f20626964206f6e2e2020202020202020202020202020617070726f766564202860747275656029206f722072656a656374656420286066616c736560292e204b65793a204320286c656e206f662063616e64696461746573292c204d20286c656e206f66206d656d6265727329202d204f6e65206163636f756e74206c6f6f6b75702e202d204f6e652073746f726167652072656164204f28432920616e64204f2843292073656172636820746f20636865636b2074686174207573657220697320612063616e6469646174652e20546f74616c20436f6d706c65786974793a204f284d202b206c6f674d202b20432963616e646964617465204173206120766f756368696e67206d656d6265722c20756e766f7563682061206269642e2054686973206f6e6c7920776f726b73207768696c6520766f75636865642075736572206973206f6e6c792061206269646465722028616e64206e6f7420612063616e646964617465292e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e64206120766f756368696e67206d656d6265722e202d2060706f73603a20506f736974696f6e20696e207468652060426964736020766563746f72206f6620746865206269642077686f2073686f756c6420626520756e766f75636865642e204b65793a204220286c656e206f66206269647329202d204f6e652073746f726167652072656164204f28312920746f20636865636b20746865207369676e6572206973206120766f756368696e67206d656d6265722e202d204f6e652073746f72616765206d757461746520746f20726574726965766520616e64207570646174652074686520626964732e204f284229202d204f6e6520766f756368696e672073746f726167652072656d6f76616c2e204f28312920546f74616c20436f6d706c65786974793a204f2842292041732061206d656d6265722c20766f75636820666f7220736f6d656f6e6520746f206a6f696e20736f636965747920627920706c6163696e67206120626964206f6e20746865697220626568616c662e205468657265206973206e6f206465706f73697420726571756972656420746f20766f75636820666f722061206e6577206269642c206275742061206d656d6265722063616e206f6e6c7920766f75636820666f72206f6e652062696420617420612074696d652e2049662074686520626964206265636f6d657320612073757370656e6465642063616e64696461746520616e6420756c74696d6174656c792072656a6563746564206279207468652073757370656e73696f6e206a756467656d656e74206f726967696e2c20746865206d656d6265722077696c6c2062652062616e6e65642066726f6d20766f756368696e6720616761696e2e204173206120766f756368696e67206d656d6265722c20796f752063616e20636c61696d206120746970206966207468652063616e6469646174652069732061636365707465642e2054686973207469702077696c6c2062652070616964206173206120706f7274696f6e206f66207468652072657761726420746865206d656d6265722077696c6c207265636569766520666f72206a6f696e696e672074686520736f63696574792e202d206077686f603a2054686520757365722077686f20796f7520776f756c64206c696b6520746f20766f75636820666f722e202d206076616c7565603a2054686520746f74616c2072657761726420746f2062652070616964206265747765656e20796f7520616e64207468652063616e6469646174652069662074686579206265636f6d652061206d656d62657220696e2074686520736f63696574792e202d2060746970603a20596f757220637574206f662074686520746f74616c206076616c756560207061796f7574207768656e207468652063616e64696461746520697320696e64756374656420696e746f2074686520736f63696574792e2054697073206c6172676572207468616e206076616c7565602077696c6c206265207361747572617465642075706f6e207061796f75742e204b65793a204220286c656e206f662062696473292c204320286c656e206f662063616e64696461746573292c204d20286c656e206f66206d656d6265727329202d2053746f726167652052656164733a20092d204f6e652073746f72616765207265616420746f20726574726965766520616c6c206d656d626572732e204f284d2920092d204f6e652073746f72616765207265616420746f20636865636b206d656d626572206973206e6f7420616c726561647920766f756368696e672e204f28312920092d204f6e652073746f72616765207265616420746f20636865636b20666f722073757370656e6465642063616e6469646174652e204f28312920092d204f6e652073746f72616765207265616420746f20636865636b20666f722073757370656e646564206d656d6265722e204f28312920092d204f6e652073746f72616765207265616420746f20726574726965766520616c6c2063757272656e7420626964732e204f28422920092d204f6e652073746f72616765207265616420746f20726574726965766520616c6c2063757272656e742063616e646964617465732e204f284329202d2053746f72616765205772697465733a20092d204f6e652073746f7261676520777269746520746f20696e7365727420766f756368696e672073746174757320746f20746865206d656d6265722e204f28312920092d204f6e652073746f72616765206d757461746520746f206164642061206e65772062696420746f2074686520766563746f72204f2842292028544f444f3a20706f737369626c65206f7074696d697a6174696f6e20772f20726561642920092d20557020746f206f6e652073746f726167652072656d6f76616c206966206269642e6c656e2829203e204d41585f4249445f434f554e542e204f283129202d204e6f7461626c6520436f6d7075746174696f6e3a20092d204f286c6f67204d292073656172636820746f20636865636b2073656e6465722069732061206d656d6265722e20092d204f2842202b2043202b206c6f67204d292073656172636820746f20636865636b2075736572206973206e6f7420616c726561647920612070617274206f6620736f63696574792e20092d204f286c6f672042292073656172636820746f20696e7365727420746865206e65772062696420736f727465642e202d2045787465726e616c204d6f64756c65204f7065726174696f6e733a20092d204f6e652062616c616e63652072657365727665206f7065726174696f6e2e204f28582920092d20557020746f206f6e652062616c616e636520756e72657365727665206f7065726174696f6e20696620626964732e6c656e2829203e204d41585f4249445f434f554e542e202d204576656e74733a20092d204f6e65206576656e7420666f7220766f7563682e20092d20557020746f206f6e65206576656e7420666f72204175746f556e626964206966206269642e6c656e2829203e204d41585f4249445f434f554e542e20546f74616c20436f6d706c65786974793a204f284d202b2042202b2043202b206c6f674d202b206c6f6742202b20582976616c756542616c616e63654f663c542c20493e2041206269646465722063616e2072656d6f76652074686569722062696420666f7220656e74727920696e746f20736f63696574792e20427920646f696e6720736f2c20746865792077696c6c20686176652074686569722063616e646964617465206465706f7369742072657475726e6564206f7220746865792077696c6c20756e766f75636820746865697220766f75636865722e205061796d656e743a2054686520626964206465706f73697420697320756e7265736572766564206966207468652075736572206d6164652061206269642e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e642061206269646465722e202d2060706f73603a20506f736974696f6e20696e207468652060426964736020766563746f72206f6620746865206269642077686f2077616e747320746f20756e6269642e204b65793a204220286c656e206f662062696473292c2058202862616c616e636520756e7265736572766529202d204f6e652073746f72616765207265616420616e6420777269746520746f20726574726965766520616e64207570646174652074686520626964732e204f284229202d20456974686572206f6e6520756e726573657276652062616c616e636520616374696f6e204f285829206f72206f6e6520766f756368696e672073746f726167652072656d6f76616c2e204f28312920546f74616c20436f6d706c65786974793a204f2842202b205829706f7320412075736572206f757473696465206f662074686520736f63696574792063616e206d616b6520612062696420666f7220656e7472792e205061796d656e743a206043616e6469646174654465706f736974602077696c6c20626520726573657276656420666f72206d616b696e672061206269642e2049742069732072657475726e6564207768656e2074686520626964206265636f6d65732061206d656d6265722c206f7220696620746865206269642063616c6c732060756e626964602e202d206076616c7565603a2041206f6e652074696d65207061796d656e74207468652062696420776f756c64206c696b6520746f2072656365697665207768656e206a6f696e696e672074686520736f63696574792e204b65793a204220286c656e206f662062696473292c204320286c656e206f662063616e64696461746573292c204d20286c656e206f66206d656d62657273292c2058202862616c616e636520726573657276652920092d204f6e65206576656e7420666f72206e6577206269642e00000000ef0d12000700000000000000000000007ac312000c00000000000000000000000000000000000000000000000000000000000000301a130018781200000000000000000000571200010000000000000000000000000000000857120005000000000000000000000091d912000700000000000000000000000000000000000000000000000000000000000000301a13001057120000000000000000002057120002000000000000000000000000000000611c12000a0000000000000000000000305712002700000000000000000000000000000000000000000000000000000000000000301a13001458120000000000000000005857120001000000000000000100000000000000605712001300000001050000000000007ac312000c00000000000000735712003900000000000000000000000000000000000000301a1300ac5712000000000000000000bc571200010000000000000000000000000000004e1c1200030000000000000000000000af4d12000f00000000000000000000000000000000000000000000000000000000000000301a1300c45712000000000000000000d457120001000000000000000100000000000000f60d12000400000000000000000000007ac312000c00000000000000000000000000000000000000000000000000000000000000301a1300187812000000000000000000dc5712000100000000000000000000000000000009b51200070000000000000000000000ddce12001100000000000000000000000000000000000000000000000000000000000000301a1300e45712000000000000000000f457120001000000000000000100000000000000ce1d12001000000001050000000000007ac312000c00000000000000a1f512000400000000000000000000000000000000000000301a1300fc57120000000000000000000c581200010000000000000001000000000000001c1d1200040000000000000000000000305712002700000000000000000000000000000000000000000000000000000000000000301a130014581200000000000000000024581200010000000000000001000000000000002c5812000800000001050000000000007ac312000c00000000000000345812000e00000000000000000000000000000000000000301a13004458120000000000000000005458120001000000000000000000000000000000f01d12000700000001050000000000007ac312000c000000000000005c5812002600000000000000000000000000000000000000301a13008458120000000000000000009458120001000000000000000100000000000000c71d12000700000001050000000000007ac312000c000000000000009c5812000b00000000000000000000000000000000000000301a1300587712000000000000000000a858120001000000000000000100000000000000b30d12000500000002050500000000007ac312000c000000000000007ac312000c00000000000000a81212000400000000000000301a1300c05812000000000000000000b0581200010000000000000000000000000000004c1d12000800000000000000000000007ac312000c00000000000000000000000000000000000000000000000000000000000000301a1300187812000000000000000000b858120001000000000000000000000000000000541d12000d00000001050000000000007ac312000c00000000000000a81212000400000000000000000000000000000000000000301a1300c05812000000000000000000d058120001000000000000000000000000000000a90d12000a000000000000000000000060dc12000300000000000000000000000000000000000000000000000000000000000000301a1300587712000000000000000000d8581200010000000000000001000000365c12001200000052756c65730000004200000000000000010000005b000000cd5b120054000000215c1200150000005665633c4269643c543a3a4163636f756e7449642c2042616c616e63654f663c542c20493e3e3e007f5b12004e00000053757370656e64656443616e646964617465732842616c616e63654f663c542c20493e2c204269644b696e643c543a3a4163636f756e7449642c2042616c616e63654f663c542c20493e3e294200000000000000010000005b0000005e5b1200210000004200000000000000010000005f0000000e5b120050000000d45a12003a00000042000000000000000100000059000000af5a1200250000004200000000000000010000005b000000915a12001e00000042000000000000000100000059000000575a12003a000000566f756368696e67566f756368696e6753746174757300004200000000000000010000005b0000001e5a1200390000005665633c28543a3a426c6f636b4e756d6265722c2042616c616e63654f663c542c20493e293e000042000000000000000100000059000000cb59120053000000537472696b65436f756e7400945912003700000060591200340000002f591200310000004200000000000000010000005b0000001759120018000000e05812003700000020546865206d6178206e756d626572206f66206d656d6265727320666f722074686520736f6369657479206174206f6e652074696d652e20566f74657320666f722074686520646566656e6465722e2054686520646566656e64696e67206d656d6265722063757272656e746c79206265696e67206368616c6c656e6765642e20446f75626c65206d61702066726f6d2043616e646964617465202d3e20566f746572202d3e20284d617962652920566f74652e20546865206f6e676f696e67206e756d626572206f66206c6f73696e6720766f746573206361737420627920746865206d656d6265722e2050656e64696e67207061796f7574733b206f72646572656420627920626c6f636b206e756d6265722c20776974682074686520616d6f756e7420746861742073686f756c642062652070616964206f75742e204d656d626572732063757272656e746c7920766f756368696e67206f722062616e6e65642066726f6d20766f756368696e6720616761696e205468652063757272656e7420626964732c2073746f726564206f726465726564206279207468652076616c7565206f6620746865206269642e2054686520736574206f662073757370656e646564206d656d626572732e205468652063757272656e7420736574206f66206d656d626572732c206f7264657265642e20546865206d6f7374207072696d6172792066726f6d20746865206d6f737420726563656e746c7920617070726f766564206d656d626572732e20416d6f756e74206f66206f7572206163636f756e742062616c616e63652074686174206973207370656369666963616c6c7920666f7220746865206e65787420726f756e642773206269642873292e2054686520736574206f662073757370656e6465642063616e646964617465732e205468652063757272656e7420736574206f662063616e646964617465733b206269646465727320746861742061726520617474656d7074696e6720746f206265636f6d65206d656d626572732e20412068617368206f66207468652072756c6573206f66207468697320736f636965747920636f6e6365726e696e67206d656d626572736869702e2043616e206f6e6c7920626520736574206f6e636520616e64206f6e6c792062792074686520666f756e6465722e20546865206669727374206d656d6265722e00000000d05d12001000000000000000af4d12000f00000000000000301a1300e05d12000000000000000000f05d1200010000000000000000000000f85d12001200000000000000af4d12000f00000000000000301a13000c5e120000000000000000001c5e12000200000000000000000000002c5e12000a0000000000000060dc12000300000000000000301a1300385e12000000000000000000485e1200020000000000000000000000585e12000b00000000000000af4d12000f00000000000000301a1300645e12000000000000000000745e12000100000000000000000000007c5e12000e0000000000000006cf12000e00000000000000301a13008c5e120000000000000000009c5e1200010000000000000000000000a45e12000f0000000000000006cf12000e00000000000000301a1300b45e12000000000000000000c45e1200010000000000000000000000cc5e12000800000000000000cc5e12000800000000000000301a1300d45e12000000000000000000e45e1200010000000000000043616e6469646174654465706f73697442000000000000000100000067000000c96012003f00000057726f6e6753696465446564756374696f6e000042000000000000000100000073000000446012005500000099601200300000004d6178537472696b6573000042000000000000000100000003010000c95f12005d000000266012001e000000506572696f645370656e6400420000000000000001000000040100007e5f12004b000000526f746174696f6e506572696f640000420000000000000001000000050100003a5f1200440000004368616c6c656e6765506572696f64004200000000000000010000006b000000065f1200340000004d6f64756c65496442000000000000000100000006010000ec5e12001a0000002054686520736f636965746965732773206d6f64756c6520696420546865206e756d626572206f6620626c6f636b73206265747765656e206d656d62657273686970206368616c6c656e6765732e20546865206e756d626572206f6620626c6f636b73206265747765656e2063616e6469646174652f6d656d6265727368697020726f746174696f6e20706572696f64732e2054686520616d6f756e74206f6620696e63656e7469766520706169642077697468696e206561636820706572696f642e20446f65736e277420696e636c75646520566f7465725469702e20546865206e756d626572206f662074696d65732061206d656d626572206d617920766f7465207468652077726f6e672077617920286f72206e6f7420617420616c6c2c207768656e207468657920617265206120736b657074696329206265666f72652074686579206265636f6d652073757370656e6465642e2054686520616d6f756e74206f662074686520756e70616964207265776172642074686174206765747320646564756374656420696e207468652063617365207468617420656974686572206120736b657074696320646f65736e277420766f7465206f7220736f6d656f6e6520766f74657320696e207468652077726f6e67207761792e20546865206d696e696d756d20616d6f756e74206f662061206465706f73697420726571756972656420666f7220612062696420746f206265206d6164652e00000000ff1612000d0000000000000068621200020000000000000000000000986212000900000000000000000000000c1712000f00000000000000e0621200010000000000000000000000f86212000700000000000000000000001b1712001000000000000000e0621200010000000000000000000000306312000800000000000000000000002b1712000e0000000000000070631200020000000000000000000000a0631200130000000000000000000000391712000b000000000000003864120001000000000000000000000050641200130000000000000000000000441712000700000000000000e864120003000000000000000000000030651200160000000000000000000000730e12000300000000000000e0651200020000000000000000000000106612001900000000000000000000004b171200090000000000000038641200010000000000000000000000d8661200110000000000000000000000aa4d12000500000000000000807512001500000000000000957512000b00000000000000f3201200230000006b7412004b000000b67412004d0000000375120015000000301a130000000000f5bd12000b000000e473120013000000187512002d000000457512003b00000044be12000c00000000000000607412000b000000000000009dd9120016000000a57312003f000000301a130000000000f5bd12000b000000e473120013000000f7731200340000002b7412003500000044be12000c000000d4721200570000002b7312002b000000301a130000000000f5bd12000b00000056731200140000006a731200240000008e7312001700000044be12000c00000000000000486f12000600000000000000cc8d12000700000000000000f020120003000000000000007ac312000c0000004371120057000000301a13000000000098c9120034000000301a1300000000009a71120055000000ef71120035000000301a130000000000ff6c120058000000576d1200170000006e6d12003b000000301a130000000000a96d12001e000000301a130000000000f5bd12000b000000247212003300000057721200250000007c72120031000000ad7212002700000044be12000c00000000000000a96c1200040000000000000091d91200070000004e6f120055000000301a130000000000a36f120038000000301a130000000000db6f1200540000002f701200510000008070120014000000301a130000000000be671200590000001768120058000000301a1300000000009470120024000000301a130000000000f5bd12000b000000ea95120015000000b870120037000000ef70120024000000137112003000000044be12000c00000000000000486f12000600000000000000cc8d12000700000000000000f020120003000000000000007ac312000c00000000000000ad6c12000900000000000000b66c12000c000000c26c12003d000000301a130000000000df69120055000000346a12001d000000301a130000000000ff6c120058000000576d1200170000006e6d12003b000000b76a1200540000000b6b120036000000301a130000000000a96d12001e000000301a130000000000f5bd12000b000000c76d1200550000001c6e1200300000004c6e1200420000008e6e120043000000d16e1200390000000a6f1200200000002a6f12001e00000044be12000c00000000000000a96c1200040000000000000091d912000700000000000000ad6c12000900000000000000b66c12000c000000b26912002d000000301a130000000000df69120055000000346a12001d000000301a130000000000be67120059000000516a120058000000a96a12000e000000b76a1200540000000b6b120036000000301a130000000000416b1200590000009a6b12000d000000301a130000000000f5bd12000b0000006f68120039000000a76b120045000000cf681200400000000f69120041000000301a130000000000ec6b120058000000446c120035000000796c12001d000000966c12001300000044be12000c0000006067120018000000301a13000000000098c9120034000000301a1300000000007867120046000000301a130000000000be671200590000001768120058000000301a130000000000f5bd12000b0000006f68120039000000a868120027000000cf681200400000000f69120041000000506912002b0000007b6912003700000044be12000c00000020436c6f736520616e64207061796f75742061207469702e2054686520746970206964656e74696669656420627920606861736860206d75737420686176652066696e69736865642069747320636f756e74646f776e20706572696f642e202d206068617368603a20546865206964656e74697479206f6620746865206f70656e2074697020666f722077686963682061207469702076616c7565206973206465636c617265642e205468697320697320666f726d65642020206173207468652068617368206f6620746865207475706c65206f6620746865206f726967696e616c207469702060726561736f6e6020616e64207468652062656e6566696369617279206163636f756e742049442e202d20436f6d706c65786974793a20604f285429602077686572652060546020697320746865206e756d626572206f6620746970706572732e2020206465636f64696e6720605469707065726020766563206f66206c656e677468206054602e202020605460206973206368617267656420617320757070657220626f756e6420676976656e2062792060436f6e7461696e734c656e677468426f756e64602e2020205468652061637475616c20636f737420646570656e6473206f6e2074686520696d706c656d656e746174696f6e206f662060543a3a54697070657273602e202d20446252656164733a206054697073602c206054697070657273602c20607469702066696e64657260202d2044625772697465733a2060526561736f6e73602c206054697073602c206054697070657273602c20607469702066696e64657260204465636c6172652061207469702076616c756520666f7220616e20616c72656164792d6f70656e207469702e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e6420746865207369676e696e67206163636f756e74206d7573742062652061206d656d626572206f662074686520605469707065727360207365742e2020206173207468652068617368206f6620746865207475706c65206f66207468652068617368206f6620746865206f726967696e616c207469702060726561736f6e6020616e64207468652062656e65666963696172792020206163636f756e742049442e202d20607469705f76616c7565603a2054686520616d6f756e74206f66207469702074686174207468652073656e64657220776f756c64206c696b6520746f20676976652e20546865206d656469616e2074697020202076616c7565206f662061637469766520746970706572732077696c6c20626520676976656e20746f20746865206077686f602e20456d6974732060546970436c6f73696e676020696620746865207468726573686f6c64206f66207469707065727320686173206265656e207265616368656420616e642074686520636f756e74646f776e20706572696f642068617320737461727465642e2020206465636f64696e6720605469707065726020766563206f66206c656e677468206054602c20696e736572742074697020616e6420636865636b20636c6f73696e672c20202041637475616c6c792077656967687420636f756c64206265206c6f77657220617320697420646570656e6473206f6e20686f77206d616e7920746970732061726520696e20604f70656e5469706020627574206974202020697320776569676874656420617320696620616c6d6f73742066756c6c20692e65206f66206c656e6774682060542d31602e202d20446252656164733a206054697070657273602c20605469707360202d2044625772697465733a20605469707360686173687469705f76616c756542616c616e63654f663c543e204769766520612074697020666f7220736f6d657468696e67206e65773b206e6f2066696e6465722773206665652077696c6c2062652074616b656e2e202d2060726561736f6e603a2054686520726561736f6e20666f722c206f7220746865207468696e6720746861742064657365727665732c20746865207469703b2067656e6572616c6c7920746869732077696c6c20626520202061205554462d382d656e636f6465642055524c2e202d206077686f603a20546865206163636f756e742077686963682073686f756c6420626520637265646974656420666f7220746865207469702e20456d69747320604e657754697060206966207375636365737366756c2e202d20436f6d706c65786974793a20604f2852202b2054296020776865726520605260206c656e677468206f662060726561736f6e602c2060546020697320746865206e756d626572206f6620746970706572732e2020202d20604f285429603a206465636f64696e6720605469707065726020766563206f66206c656e677468206054602020202020605460206973206368617267656420617320757070657220626f756e6420676976656e2062792060436f6e7461696e734c656e677468426f756e64602e20202020205468652061637475616c20636f737420646570656e6473206f6e2074686520696d706c656d656e746174696f6e206f662060543a3a54697070657273602e2020202d20604f285229603a2068617368696e6720616e6420656e636f64696e67206f6620726561736f6e206f66206c656e67746820605260202d20446252656164733a206054697070657273602c2060526561736f6e7360202d2044625772697465733a2060526561736f6e73602c20605469707360726561736f6e20526574726163742061207072696f72207469702d7265706f72742066726f6d20607265706f72745f617765736f6d65602c20616e642063616e63656c207468652070726f63657373206f662074697070696e672e204966207375636365737366756c2c20746865206f726967696e616c206465706f7369742077696c6c20626520756e72657365727665642e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e642074686520746970206964656e74696669656420627920606861736860206d7573742068617665206265656e207265706f7274656420627920746865207369676e696e67206163636f756e74207468726f75676820607265706f72745f617765736f6d65602028616e64206e6f74207468726f75676820607469705f6e657760292e20456d697473206054697052657472616374656460206966207375636365737366756c2e2020202d20446570656e6473206f6e20746865206c656e677468206f662060543a3a48617368602077686963682069732066697865642e202d20446252656164733a206054697073602c20606f726967696e206163636f756e7460202d2044625772697465733a2060526561736f6e73602c206054697073602c20606f726967696e206163636f756e7460205265706f727420736f6d657468696e672060726561736f6e60207468617420646573657276657320612074697020616e6420636c61696d20616e79206576656e7475616c207468652066696e6465722773206665652e205061796d656e743a20605469705265706f72744465706f73697442617365602077696c6c2062652072657365727665642066726f6d20746865206f726967696e206163636f756e742c2061732077656c6c20617320605469705265706f72744465706f736974506572427974656020666f722065616368206279746520696e2060726561736f6e602e202d20436f6d706c65786974793a20604f2852296020776865726520605260206c656e677468206f662060726561736f6e602e2020202d20656e636f64696e6720616e642068617368696e67206f662027726561736f6e27202d20446252656164733a2060526561736f6e73602c206054697073602c206077686f206163636f756e74206461746160202d2044625772697465733a206054697073602c206077686f206163636f756e7420646174616020417070726f766520612070726f706f73616c2e2041742061206c617465722074696d652c207468652070726f706f73616c2077696c6c20626520616c6c6f636174656420746f207468652062656e656669636961727920616e6420746865206f726967696e616c206465706f7369742077696c6c2062652072657475726e65642e202d20436f6d706c65786974793a204f2831292e202d20446252656164733a206050726f706f73616c73602c2060417070726f76616c7360202d20446257726974653a2060417070726f76616c73602052656a65637420612070726f706f736564207370656e642e20546865206f726967696e616c206465706f7369742077696c6c20626520736c61736865642e202d20436f6d706c65786974793a204f283129202d20446252656164733a206050726f706f73616c73602c206072656a65637465642070726f706f736572206163636f756e7460202d2044625772697465733a206050726f706f73616c73602c206072656a65637465642070726f706f736572206163636f756e746070726f706f73616c5f69642050757420666f727761726420612073756767657374696f6e20666f72207370656e64696e672e2041206465706f7369742070726f706f7274696f6e616c20746f207468652076616c756520697320726573657276656420616e6420736c6173686564206966207468652070726f706f73616c2069732072656a65637465642e2049742069732072657475726e6564206f6e6365207468652070726f706f73616c20697320617761726465642e202d20446252656164733a206050726f706f73616c436f756e74602c20606f726967696e206163636f756e7460202d2044625772697465733a206050726f706f73616c436f756e74602c206050726f706f73616c73602c20606f726967696e206163636f756e7460436f6d706163743c42616c616e63654f663c543e3e62656e6566696369617279000000000ef812000d000000000000000000000075b412000d00000000000000000000000000000000000000000000000000000000000000301a1300587712000000000000000000687712000100000000000000010000000000000000b5120009000000010500000000000075b412000d00000000000000707712002400000000000000000000000000000000000000301a1300947712000000000000000000a4771200010000000000000000000000000000001bf81200090000000000000000000000ac7712001200000000000000000000000000000000000000000000000000000000000000301a1300c07712000000000000000000d077120001000000000000000100000000000000d877120004000000010500000000000091d912000700000000000000dc7712003c00000000000000000000000000000000000000301a130018781200000000000000000028781200030000000000000000000000000000004078120007000000010600000000000091d912000700000000000000cc8d12000700000000000000000000000000000000000000301a13004878120000000000000000005878120002000000000000000000000042000000000000000100000057000000347a12002900000050726f706f73616c3c543a3a4163636f756e7449642c2042616c616e63654f663c543e3e4200000000000000010000005b000000157a12001f0000005665633c50726f706f73616c496e6465783e000042000000000000000100000059000000d77912003e000000546970734f70656e5469703c543a3a4163636f756e7449642c2042616c616e63654f663c543e2c20543a3a426c6f636b4e756d6265722c20543a3a486173683e4200000000000000010000005b0000001279120056000000687912004f000000b779120020000000526561736f6e7300420000000000000001000000f60000006878120052000000ba781200580000002053696d706c6520707265696d616765206c6f6f6b75702066726f6d2074686520726561736f6e2773206861736820746f20746865206f726967696e616c20646174612e20416761696e2c2068617320616e20696e73656375726520656e756d657261626c6520686173682073696e636520746865206b65792069732067756172616e7465656420746f2062652074686520726573756c74206f6620612073656375726520686173682e2054697073207468617420617265206e6f742079657420636f6d706c657465642e204b65796564206279207468652068617368206f66206028726561736f6e2c2077686f29602066726f6d207468652076616c75652e2054686973206861732074686520696e73656375726520656e756d657261626c6520686173682066756e6374696f6e2073696e636520746865206b657920697473656c6620697320616c72656164792067756172616e7465656420746f20626520612073656375726520686173682e2050726f706f73616c20696e646963657320746861742068617665206265656e20617070726f76656420627574206e6f742079657420617761726465642e2050726f706f73616c7320746861742068617665206265656e206d6164652e204e756d626572206f662070726f706f73616c7320746861742068617665206265656e206d6164652e00000000000000587c12000c00000000000000647c12000700000000000000301a13006c7c120000000000000000007c7c12000200000000000000000000008c7c12001300000000000000b66c12000c00000000000000301a13003c7d12000000000000000000a07c1200010000000000000000000000a87c12000b0000000000000006cf12000e00000000000000301a1300e47c12000000000000000000b47c1200010000000000000000000000bc7c12000400000000000000647c12000700000000000000301a1300c07c12000000000000000000d07c1200010000000000000000000000d87c12000c0000000000000006cf12000e00000000000000301a1300e47c12000000000000000000f47c1200010000000000000000000000fc7c12000d00000000000000097d12000700000000000000301a1300107d12000000000000000000207d1200010000000000000000000000287d12001400000000000000b66c12000c00000000000000301a13003c7d120000000000000000004c7d1200010000000000000000000000547d12001700000000000000b66c12000c00000000000000301a13006c7d120000000000000000007c7d1200010000000000000000000000cc5e12000800000000000000cc5e12000800000000000000301a1300847d12000000000000000000947d1200010000000000000050726f706f73616c426f6e645065726d696c6c0042000000000000000100000007010000ae7f120055000000038012004400000050726f706f73616c426f6e644d696e696d756d005c7f1200520000005370656e64506572696f64003a7f1200220000004275726e42000000000000000100000008010000f67e120044000000546970436f756e74646f776e42000000000000000100000009010000a57e12005100000054697046696e6465727346656550657263656e744200000000000000010000000a010000597e12004c0000005469705265706f72744465706f7369744261736542000000000000000100000068000000247e1200350000005469705265706f72744465706f736974506572427974650042000000000000000100000084000000e27d1200420000004200000000000000010000000b0100009c7d120046000000205468652074726561737572792773206d6f64756c652069642c207573656420666f72206465726976696e672069747320736f7665726569676e206163636f756e742049442e2054686520616d6f756e742068656c64206f6e206465706f7369742070657220627974652077697468696e2074686520746970207265706f727420726561736f6e2e2054686520616d6f756e742068656c64206f6e206465706f73697420666f7220706c6163696e67206120746970207265706f72742e2054686520616d6f756e74206f66207468652066696e616c2074697020776869636820676f657320746f20746865206f726967696e616c207265706f72746572206f6620746865207469702e2054686520706572696f6420666f722077686963682061207469702072656d61696e73206f70656e20616674657220697320686173206163686965766564207468726573686f6c6420746970706572732e2050657263656e74616765206f662073706172652066756e64732028696620616e7929207468617420617265206275726e7420706572207370656e6420706572696f642e20506572696f64206265747765656e2073756363657373697665207370656e64732e204d696e696d756d20616d6f756e74206f662066756e647320746861742073686f756c6420626520706c6163656420696e2061206465706f73697420666f72206d616b696e6720612070726f706f73616c2e204672616374696f6e206f6620612070726f706f73616c27732076616c756520746861742073686f756c6420626520626f6e64656420696e206f7264657220746f20706c616365207468652070726f706f73616c2e20416e2061636365707465642070726f706f73616c2067657473207468657365206261636b2e20412072656a65637465642070726f706f73616c20646f6573206e6f742e74686520636f6e74726163742065786973747320616e6420696e2074686520616c6976652073746174653b0a090974686520757064617465642062616c616e6365206d7573742062652067726561746572207468616e2073756273697374656e6365206465706f7369743b0a0909746869732066756e6374696f6e20646f65736e27742072657475726e20604e6f6e65603b0a09097165640a09090000f48012003600000074010000170000002f686f6d652f6461766964642f6465762f7375627374726174652f6672616d652f636f6e7472616374732f7372632f72656e742e72730000941d120033000000bd0500002b0000005c8112003400000070020000180000005c811200340000009c0200001a0000002f686f6d652f6461766964642f6465762f7375627374726174652f6672616d652f74726561737572792f7372632f6c69622e7273000000005e0c12000b00000000000000ac8112000100000000000000b4811200200000002053656e646572206d75737420626520746865205375646f206163636f756e74696e636f7272656374206964656e746974796e6f7420766f7563686564000000941d120033000000ac04000035000000622e6c656e2829203e20313030303b2071656400941d120033000000c80400003100000000000000e31612001c0000000000000008831200010000000000000000000000cf161200140000000000000010831200010000000000000000000000c31612000c0000000000000018831200010000000000000000000000b71612000c0000000000000020831200010000000000000000000000ad1612000a0000000000000028831200010000000000000000000000a41612000900000000000000308312000100000000000000000000009b161200090000000000000038831200010000000000000000000000921612000900000000000000408312000100000000000000a18412001f000000868412001b000000648412002200000041841200230000002884120019000000e083120048000000958312004b000000488312004d00000020546865207469702063616e6e6f7420626520636c61696d65642f636c6f73656420626563617573652069742773207374696c6c20696e2074686520636f756e74646f776e20706572696f642e20546865207469702063616e6e6f7420626520636c61696d65642f636c6f736564206265636175736520746865726520617265206e6f7420656e6f7567682074697070657273207965742e20546865206163636f756e7420617474656d7074696e6720746f20726574726163742074686520746970206973206e6f74207468652066696e646572206f6620746865207469702e2054686520746970206861736820697320756e6b6e6f776e2e20546865207469702077617320616c726561647920666f756e642f737461727465642e2054686520726561736f6e20676976656e206973206a75737420746f6f206269672e204e6f2070726f706f73616c206174207468617420696e6465782e2050726f706f73657227732062616c616e636520697320746f6f206c6f772e000000005b0e12000b00000000000000b8861200010000000000000000000000f2af12000900000000000000c08612000100000000000000000000004e0e12000d00000000000000c8861200010000000000000000000000450e12000900000000000000d0861200010000000000000000000000390e12000c00000000000000d8861200010000000000000000000000310e12000800000000000000e0861200010000000000000000000000230e12000e00000000000000e8861200010000000000000000000000140e12000f00000000000000f0861200010000000000000000000000050e12000f00000000000000f8861200010000000000000000000000fa0d12000b0000000000000000871200010000000000000000000000f60d1200040000000000000008871200010000000000000000000000ef0d1200070000000000000010871200010000000000000000000000e50d12000a0000000000000018871200010000000000000000000000d50d1200100000000000000020871200010000000000000000000000c90d12000c0000000000000028871200010000000000000000000000a90d12000a0000000000000030871200010000000000000000000000bf0d12000a0000000000000038871200010000000000000000000000b80d1200070000000000000040871200010000000000000036891200240000002089120016000000068912001a000000f388120013000000dc88120017000000c988120013000000b08812001900000089881200270000004f8812003a00000037881200180000001288120025000000f78712001b000000da8712001d000000bd8712001d000000a4871200190000008387120021000000648712001f000000488712001c000000205468652063616c6c6572206973206e6f742074686520686561642e205468652063616c6c6572206973206e6f742074686520666f756e6465722e20546f6f206d616e79206d656d6265727320696e2074686520736f63696574792e2055736572206973206e6f7420612063616e6469646174652e205573657220697320616c726561647920612063616e6469646174652e20557365722068617320616c7265616479206d6164652061206269642e2043616e6e6f742072656d6f76652074686520666f756e6465722e2043616e6e6f742072656d6f7665207468652068656164206f662074686520636861696e2e204d656d626572206973206e6f7420766f756368696e672e204d656d62657220697320616c726561647920766f756368696e67206f722062616e6e65642066726f6d20766f756368696e6720616761696e2e204e6f7420656e6f75676820696e20706f7420746f206163636570742063616e6469646174652e20536f636965747920616c726561647920666f756e6465642e204e6f7468696e6720746f207061796f75742e2055736572206973206e6f742073757370656e6465642e20557365722069732073757370656e6465642e205573657220697320616c72656164792061206d656d6265722e2055736572206973206e6f742061206d656d6265722e20416e20696e636f727265637420706f736974696f6e207761732070726f76696465642e546f6f536f6f6e4368616e676550656e64696e67526573756d654661696c656450617573654661696c65647265706f72745f6d69736265686176696f723a6772616e6470615f617574686f7269746965734e6f4b6579734475706c6963617465644b65794e6f4173736f63696174656456616c696461746f724964496e76616c696450726f6f667365745f6b65797370757267655f6b65797356616c696461746f7273666f726b2e726563656e746c792065786563757465642e4200000000000000010000000c0100000d0100000e0100000f0100001001000011010000656e74697265206e65775f7365742077617320676976656e20746f206275696c645f737570706f72745f6d61703b20656e20656e747279206d757374206265206372656174656420666f722065616368206974656d3b207165640000a48a12003e000000eb020000230000002f686f6d652f6461766964642f6465762f7375627374726174652f6672616d652f656c656374696f6e732d70687261676d656e2f7372632f6c69622e7273000042000000000000000100000064000000756e636c6573303066696e616c6e756d6e6f7420656e6f7567682067617320746f20706179207472616e736665722066656562616c616e636520746f6f206c6f7720746f2073656e642076616c756576616c756520746f6f206c6f7720746f20637265617465206163636f756e746272696e67732073656e6465722062656c6f77206578697374656e7469616c206465706f73697464657374696e6174696f6e2062616c616e636520746f6f206869676820746f20726563656976652076616c756550656e64696e674368616e676553746174655175657565644b6579735374616c6c6564000000420000000800000004000000120100001301000000000000000000001401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004e657874466f726365644e6578744b6579730000188d12004500000075000000450000002f686f6d652f6461766964642f6465762f7375627374726174652f6672616d652f737570706f72742f7372632f73746f726167652f67656e657261746f722f6d61702e7273000000000000008589120012000000000000008c8d1200010000000000000000000000a48d1200010000000000000000000000c58d12000700000000000000cc8d120007000000ac8d120019000000205265706f727420736f6d65206d69736265686176696f722e5f7265706f72745665633c75383e0000000000c38b1200050000000000000000000000e48f12001b00000000000000000000000000000000000000000000000000000000000000301a13000090120000000000000000001090120001000000000000000100000000000000b68b12000d0000000000000000000000189012002300000000000000000000000000000000000000000000000000000000000000301a1300389a120000000000000000003c90120001000000000000000000000000000000f48c12000a000000000000000000000006cf12000e00000000000000000000000000000000000000000000000000000000000000301a1300ac90120000000000000000004490120001000000000000000000000000000000d28b12000700000000000000000000004c9012002000000000000000000000000000000000000000000000000000000000000000301a13006c90120000000000000000007c901200010000000000000000000000000000009cf312000c0000000000000000000000849012000500000000000000000000000000000000000000000000000000000000000000301a13008c90120000000000000000009c90120002000000000000000100000000000000b7f312000c000000010500000000000084901200050000000000000097f612000c00000000000000000000000000000000000000301a1300ac9012000000000000000000bc90120002000000000000000000000053746f72656453746174653c543a3a426c6f636b4e756d6265723e0042000000000000000100000015010000489212002400000053746f72656450656e64696e674368616e67653c543a3a426c6f636b4e756d6265723e001792120031000000e89112002f00000028543a3a426c6f636b4e756d6265722c20543a3a426c6f636b4e756d6265722942000000000000000100000085000000c49112002400000053657449640000004200000000000000010000006e0000003c9112005700000093911200310000004200000000000000010000005b000000cc90120056000000229112001a0000002041206d617070696e672066726f6d206772616e6470612073657420494420746f2074686520696e646578206f6620746865202a6d6f737420726563656e742a2073657373696f6e20666f7220776869636820697473206d656d62657273207765726520726573706f6e7369626c652e20546865206e756d626572206f66206368616e6765732028626f746820696e207465726d73206f66206b65797320616e6420756e6465726c79696e672065636f6e6f6d696320726573706f6e736962696c69746965732920696e20746865202273657422206f66204772616e6470612076616c696461746f72732066726f6d2067656e657369732e20607472756560206966207765206172652063757272656e746c79207374616c6c65642e206e65787420626c6f636b206e756d6265722077686572652077652063616e20666f7263652061206368616e67652e2050656e64696e67206368616e67653a20287369676e616c65642061742c207363686564756c6564206368616e6765292e205374617465206f66207468652063757272656e7420617574686f72697479207365742e00000000e18912000800000000000000c4921200020000000000000000000000f49212000e0000000000000000000000e98912000a00000000000000301a1300000000000000000000000000649312000c0000000000000000000000a79612000400000000000000ab9612000700000000000000b29612000500000000000000cc8d120007000000689512003a000000a295120048000000f793120031000000301a1300000000002894120035000000301a130000000000f5bd12000b000000ea951200150000008a94120056000000ff9512003c0000003b961200290000006496120021000000859612002200000044be12000c000000c493120033000000f793120031000000301a1300000000002894120035000000301a130000000000f5bd12000b0000005d9412002d0000008a94120056000000e09412003c0000001c95120029000000459512002300000044be12000c0000002052656d6f76657320616e792073657373696f6e206b6579287329206f66207468652066756e6374696f6e2063616c6c65722e205468697320646f65736e27742074616b652065666665637420756e74696c20746865206e6578742073657373696f6e2e20546865206469737061746368206f726967696e206f6620746869732066756e6374696f6e206d757374206265207369676e65642e202d20436f6d706c65786974793a20604f2831296020696e206e756d626572206f66206b65792074797065732e20202041637475616c20636f737420646570656e6473206f6e20746865206e756d626572206f66206c656e677468206f662060543a3a4b6579733a3a6b65795f6964732829602077686963682069732066697865642e202d20446252656164733a2060543a3a56616c696461746f7249644f66602c20604e6578744b657973602c20606f726967696e206163636f756e7460202d2044625772697465733a20604e6578744b657973602c20606f726967696e206163636f756e7460202d20446257726974657320706572206b65792069643a20604b65794f776e646572602053657473207468652073657373696f6e206b6579287329206f66207468652066756e6374696f6e2063616c6c657220746f20606b657973602e20416c6c6f777320616e206163636f756e7420746f20736574206974732073657373696f6e206b6579207072696f7220746f206265636f6d696e6720612076616c696461746f722e202d20436f6d706c65786974793a20604f28312960202d20446252656164733a20606f726967696e206163636f756e74602c2060543a3a56616c696461746f7249644f66602c20604e6578744b65797360202d2044625772697465733a20606f726967696e206163636f756e74602c20604e6578744b65797360202d204462526561647320706572206b65792069643a20604b65794f776e657260202d20446257726974657320706572206b65792069643a20604b65794f776e6572606b657973543a3a4b65797370726f6f660000000000f38912000a0000000000000000000000209912001300000000000000000000000000000000000000000000000000000000000000301a13003499120000000000000000004499120001000000000000000100000000000000a5f512000c000000000000000000000097f612000c00000000000000000000000000000000000000000000000000000000000000301a13004c99120000000000000000005c99120001000000000000000100000000000000b1f512000d0000000000000000000000a1f512000400000000000000000000000000000000000000000000000000000000000000301a13006499120000000000000000007499120002000000000000000100000000000000c88b12000a0000000000000000000000849912001e00000000000000000000000000000000000000000000000000000000000000301a1300a49912000000000000000000b499120002000000000000000100000000000000bef51200120000000000000000000000c49912000800000000000000000000000000000000000000000000000000000000000000301a1300cc9912000000000000000000dc99120003000000000000000100000000000000fe8c1200080000000105000000000000f49912000e00000000000000ab9612000700000000000000000000000000000000000000301a1300049a12000000000000000000149a1200010000000000000000000000000000001c9a1200080000000105000000000000249a12001400000000000000f49912000e00000000000000000000000000000000000000301a1300389a12000000000000000000489a12000100000000000000000000005665633c543a3a56616c696461746f7249643e0042000000000000000100000059000000429c12001f00000042000000000000000100000057000000249c12001e0000004200000000000000010000005b000000ad9b12004e000000fb9b1200290000005665633c28543a3a56616c696461746f7249642c20543a3a4b657973293e000042000000000000000100000059000000269b12004f000000759b1200380000005665633c7533323e42000000000000000100000059000000b99a120020000000301a130000000000d99a12004d000000543a3a56616c696461746f72496400004200000000000000010000005b000000929a1200270000004b65794f776e6572284b65795479706549642c205665633c75383e294200000000000000010000005b000000509a12004200000020546865206f776e6572206f662061206b65792e20546865206b65792069732074686520604b657954797065496460202b2074686520656e636f646564206b65792e20546865206e6578742073657373696f6e206b65797320666f7220612076616c696461746f722e20496e6469636573206f662064697361626c65642076616c696461746f72732e205468652073657420697320636c6561726564207768656e20606f6e5f73657373696f6e5f656e64696e67602072657475726e732061206e657720736574206f66206964656e7469746965732e2054686520717565756564206b65797320666f7220746865206e6578742073657373696f6e2e205768656e20746865206e6578742073657373696f6e20626567696e732c207468657365206b6579732077696c6c206265207573656420746f2064657465726d696e65207468652076616c696461746f7227732073657373696f6e206b6579732e20547275652069662074686520756e6465726c79696e672065636f6e6f6d6963206964656e746974696573206f7220776569676874696e6720626568696e64207468652076616c696461746f727320686173206368616e67656420696e20746865207175657565642076616c696461746f72207365742e2043757272656e7420696e646578206f66207468652073657373696f6e2e205468652063757272656e7420736574206f662076616c696461746f72732e000000749c12003a00000033000000120000002f686f6d652f6461766964642f6465762f7375627374726174652f7072696d6974697665732f72756e74696d652f7372632f63757276652e727372656163686564206d6178696d756d2064657074682c2063616e6e6f7420696e7374616e7469617465001601000018000000040000001701000018010000190100001a0100001b0100001c010000696e73756666696369656e742072656d61696e696e672062616c616e63656e6f7420656e6f7567682067617320746f20706179206261736520696e7374616e74696174652066656572656163686564206d6178696d756d2064657074682c2063616e6e6f74206d616b6520612063616c6c6e6f7420656e6f7567682067617320746f2070617920626173652063616c6c20666565636f6e747261637420686173206265656e20657669637465646d656d6f727976616c69646174696f6e3a20696d706f727420656e74727920706f696e747320746f2061206e6f6e2d6578697374656e74207479706543616e6e6f7420696d706f727420676c6f62616c736d6f64756c6520696d706f7274732061206e6f6e2d6578697374656e742066756e6374696f6e6d6f64756c6520696d706f72747320606578745f7072696e746c6e60206275742064656275672066656174757265732064697361626c656443616e6e6f7420696d706f7274207461626c65736d6f64756c652068617320696d706f7274732066726f6d2061206e6f6e2d27656e7627206e616d6573706163654d656d6f727920696d706f7274206d757374206861766520746865206669656c64206e616d6520276d656d6f7279274d756c7469706c65206d656d6f727920696d706f72747320646566696e65644d6178696d756d206e756d626572206f662070616765732073686f756c6420626520616c77617973206465636c617265642e52657175657374656420696e697469616c206e756d626572206f662070616765732073686f756c64206e6f74206578636565642074686520726571756573746564206d6178696d756d4d6178696d756d206e756d626572206f662070616765732073686f756c64206e6f74206578636565642074686520636f6e66696775726564206d6178696d756d2e00000000007a8912000b0000000000000014a012000200000000000000000000006e8912000c0000000000000024a01200020000000000000000000000618912000d0000000000000034a012000100000000000000000000005a89120007000000000000003ca0120001000000000000001da11200420000005fa112002a000000afa0120045000000f4a012002900000074a012003b00000044a01200300000002043616e6e6f74207369676e616c20666f72636564206368616e676520736f20736f6f6e206166746572206c6173742e20417474656d707420746f207369676e616c204752414e445041206368616e67652077697468206f6e6520616c72656164792070656e64696e672e20417474656d707420746f207369676e616c204752414e44504120726573756d65207768656e2074686520617574686f72697479207365742069736e2774207061757365642028656974686572206c697665206f7220616c72656164792070656e64696e6720726573756d65292e20417474656d707420746f207369676e616c204752414e445041207061757365207768656e2074686520617574686f72697479207365742069736e2774206c697665202865697468657220706175736564206f7220616c72656164792070656e64696e67207061757365292e00000000000000d58912000c00000000000000fca11200010000000000000000000000be891200170000000000000004a21200010000000000000000000000b18912000d000000000000000ca21200010000000000000000000000ab891200060000000000000014a21200010000000000000088a212001900000060a212002800000046a212001a0000001ca212002a000000204e6f206b65797320617265206173736f63696174656420776974682074686973206163636f756e742e2052656769737465726564206475706c6963617465206b65792e204e6f206173736f6369617465642076616c696461746f7220494420666f72206163636f756e742e20496e76616c6964206f776e6572736869702070726f6f662e000000b4a212003900000077010000330000002f686f6d652f6461766964642f6465762f7375627374726174652f7072696d6974697665732f70687261676d656e2f7372632f6c69622e72734469676573744974656d206e6f7420657175616c5468657265206973206f6e6c79206f6e6520666174616c206572726f723b20716564004200000008000000040000001d010000a2a3120036000000a0020000010000004e6f206f74686572206572726f72732061726520616363657074656420616674657220616e2068617264206572726f7221496e686572656e7420776974682073616d65206964656e74696669657220616c726561647920657869737473212f686f6d652f6461766964642f6465762f7375627374726174652f62696e2f6e6f64652f72756e74696d652f7372632f6c69622e7273417574686f724f6c64556e636c65556e636c65416c7265616479496e636c75646564546f6f48696768556e636c6547656e65736973556e636c65546f6f4d616e79556e636c6573556e636c6573416c7265616479536574496e76616c6964556e636c65506172656e747365745f756e636c6573005ca412006a000000910000000d0000002f686f6d652f6461766964642f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f7061726974792d7363616c652d636f6465632d312e332e302f7372632f656e636f64655f617070656e642e727350726576696f7573206d617463682061726d206d61746368657320616e7974696e67206c657373207468616e20325e33303b2071656400000000000000000000000010a512003d000000736869667465642073756666696369656e74206269747320726967687420746f206c656164206f6e6c79206c656164696e67207a65726f733b2071656400000000000000000000000000000000000000556e636c657300000000000041a412000a0000000000000094a51200010000000000000000000000aca51200010000000000000000000000cda512000a00000000000000d7a512000e000000b4a51200190000002050726f76696465206120736574206f6620756e636c65732e6e65775f756e636c65735665633c543a3a4865616465723e0000000000000060a51200060000000000000000000000f0a612003a00000000000000000000000000000000000000000000000000000000000000301a13002ca7120000000000000000003ca7120001000000000000000100000000000000d8a312000600000000000000000000007ac312000c00000000000000000000000000000000000000000000000000000000000000301a130044a71200000000000000000054a71200010000000000000000000000000000009de812000c0000000000000000000000a1f512000400000000000000000000000000000000000000000000000000000000000000301a13005ca7120000000000000000006ca712000100000000000000010000005665633c556e636c65456e7472794974656d3c543a3a426c6f636b4e756d6265722c20543a3a486173682c20543a3a4163636f756e7449643e3e000042000000000000000100000059000000bca71200070000004200000000000000010000005b000000a3a71200190000004200000000000000010000005b00000074a712002f000000205768657468657220756e636c6573207765726520616c72656164792073657420696e207468697320626c6f636b2e20417574686f72206f662063757272656e7420626c6f636b2e20556e636c6573000100000001000000000000000000000000000000010000004ca8120045000000c1030000220000004ca8120045000000dd030000150000004ca8120045000000eb0300001e0000004ca8120045000000f4030000180000004ca8120045000000f5030000190000004ca8120045000000f80300001a0000004ca8120045000000fe0300000d0000002f72757374632f666135316638313065356239323534393034623932363630653732383062376436613436663131322f7372632f6c6962616c6c6f632f736c6963652e7273000000000000002fa41200120000000000000058a912000100000000000000000000001fa41200100000000000000060a9120001000000000000000000000012a412000d0000000000000068a9120001000000000000000000000006a412000c0000000000000070a91200010000000000000000000000faa312000c0000000000000078a91200010000000000000000000000e6a31200140000000000000080a91200010000000000000000000000dea31200080000000000000088a91200010000000000000045aa12002300000024aa12002100000013aa120011000000fda9120016000000dda9120020000000bea912001f00000090a912002e0000002054686520756e636c652069736e277420726563656e7420656e6f75676820746f20626520696e636c756465642e2054686520756e636c6520697320616c726561647920696e636c756465642e2054686520756e636c6520697320746f6f206869676820696e20636861696e2e2054686520756e636c652069732067656e657369732e20546f6f206d616e7920756e636c65732e20556e636c657320616c72656164792073657420696e2074686520626c6f636b2e2054686520756e636c6520706172656e74206e6f7420696e2074686520636861696e2e70aa12002a000000696e7465726e616c206572726f723a20656e746572656420756e726561636861626c6520636f64653a200000a4aa1200230000005f5f5068616e746f6d4974656d2073686f756c64206e6576657220626520757365642e496e7374616e636532436f6c6c656374697665496e7374616e636531436f6c6c656374697665000000f8aa120023000000605f5f49676e6f7265602063616e206e6576657220626520636f6e7374727563746564416c726561647950726f78794f766572666c6f775374696c6c4163746976655468726573686f6c64416c7265616479566f756368656444656c6179506572696f644e6f74467269656e644e6f7453746172746564416c726561647953746172746564416c72656164795265636f76657261626c654e6f745265636f76657261626c654e6f74536f727465644d6178467269656e64734e6f74456e6f756768467269656e64735a65726f5468726573686f6c644e6f74416c6c6f77656461735f7265636f76657265647365745f7265636f76657265646372656174655f7265636f76657279696e6974696174655f7265636f76657279766f7563685f7265636f76657279636c61696d5f7265636f76657279636c6f73655f7265636f7665727972656d6f76655f7265636f7665727963616e63656c5f7265636f76657265640000000000000064ad12000f0000000000000074ad12000100000000000000000000007cad120001000000000000000000000084ad1200110000000000000098ad1200020000000000000000000000a8ad1200010000000000000000000000b0ad12000f00000000000000c0ad1200030000000000000000000000d8ad1200010000000000000000000000e0ad12000e0000000000000098ad1200020000000000000000000000f0ad1200010000000000000000000000f8ad1200100000000000000098ad120002000000000000000000000008ae120001000000000000000000000010ae12000f0000000000000074ad120001000000000000000000000020ae120001000000000000005265636f76657279437265617465640020af1200090000006aaf1200320000005265636f76657279496e6974696174656400000020af12000900000020af12000900000029af1200410000005265636f76657279566f75636865640020af12000900000020af12000900000020af120009000000d0ae1200500000005265636f76657279436c6f736564000092ae12003e0000004163636f756e745265636f76657265645bae1200370000005265636f7665727952656d6f7665640028ae1200330000002041207265636f766572792070726f6365737320686173206265656e2072656d6f76656420666f7220616e206163636f756e74204163636f756e745f3120686173206265656e207375636365737366756c6c79207265636f7665726564206279206163636f756e745f322041207265636f766572792070726f6365737320666f72206163636f756e745f31206279206163636f756e745f3220686173206265656e20636c6f7365642041207265636f766572792070726f6365737320666f72206163636f756e745f31206279206163636f756e745f3220686173206265656e20766f756368656420666f72206279206163636f756e745f334163636f756e7449642041207265636f766572792070726f6365737320686173206265656e20696e6974696174656420666f72206163636f756e745f31206279206163636f756e745f322041207265636f766572792070726f6365737320686173206265656e2073657420757020666f7220616e206163636f756e745072696d65546f6f4561726c79416c7265616479496e697469616c697a65644475706c6963617465566f746557726f6e67496e64657850726f706f73616c4d697373696e674475706c696361746550726f706f73616c4e6f744d656d6265727365745f6d656d626572736578656375746570726f706f7365766f7465636c6f73650000000000000054b1120008000000000000005cb112000400000000000000000000007cb112000200000000000000000000008cb11200050000000000000094b11200050000000000000000000000bcb11200020000000000000000000000ccb112000800000000000000d4b11200010000000000000000000000dcb11200010000000000000000000000e4b112000b00000000000000d4b11200010000000000000000000000f0b11200010000000000000000000000f8b11200080000000000000000b2120002000000000000000000000010b2120001000000000000000000000018b212000e0000000000000000b2120002000000000000000000000028b2120001000000000000000000000030b21200060000000000000038b2120003000000000000000000000050b21200010000000000000050726f706f73656420af12000900000075b412000d00000089b21200040000008db212000b00000012b412005300000065b4120010000000566f74656400000020af12000900000089b2120004000000a1f51200040000008db212000b0000008db212000b0000008ab3120042000000ccb3120046000000417070726f76656489b212000400000059b3120031000000446973617070726f7665640024b3120035000000457865637574656489b2120004000000a1f5120004000000e3b21200410000004d656d6265724578656375746564000098b212004b000000436c6f736564000089b21200040000008db212000b0000008db212000b00000058b212003100000020412070726f706f73616c2077617320636c6f73656420616674657220697473206475726174696f6e207761732075702e486173684d656d626572436f756e7420412073696e676c65206d656d6265722064696420736f6d6520616374696f6e3b2060626f6f6c6020697320747275652069662072657475726e656420776974686f7574206572726f722e2041206d6f74696f6e207761732065786563757465643b2060626f6f6c6020697320747275652069662072657475726e656420776974686f7574206572726f722e2041206d6f74696f6e20776173206e6f7420617070726f76656420627920746865207265717569726564207468726573686f6c642e2041206d6f74696f6e2077617320617070726f76656420627920746865207265717569726564207468726573686f6c642e2041206d6f74696f6e2028676976656e20686173682920686173206265656e20766f746564206f6e20627920676976656e206163636f756e742c206c656176696e6720612074616c6c79202879657320766f74657320616e64206e6f20766f74657320676976656e20726573706563746976656c7920617320604d656d626572436f756e7460292e2041206d6f74696f6e2028676976656e20686173682920686173206265656e2070726f706f7365642028627920676976656e206163636f756e742920776974682061207468726573686f6c642028676976656e20604d656d626572436f756e7460292e50726f706f73616c496e64657852616e646f6d6e657373436f6c6c656374697665466c697052616e646f6d4d6174657269616c2f686f6d652f6461766964642f6465762f7375627374726174652f6672616d652f72616e646f6d6e6573732d636f6c6c6563746976652d666c69702f7372632f6c69622e72730000a8b4120046000000540000001100000050726f706f73616c734d656d62657273566f74696e67486973746f726963616c53657373696f6e7300000000d7ab12000c00000000000000b4b61200020000000000000000000000e4b612000d0000000000000000000000e3ab12000d000000000000004cb712000200000000000000000000007cb712000d0000000000000000000000f0ab12000f00000000000000e4b712000300000000000000000000002cb812001b0000000000000000000000ffab1200110000000000000004b912000100000000000000000000001cb9120016000000000000000000000010ac12000e000000000000004cb71200020000000000000000000000ccb912001900000000000000000000001eac12000e0000000000000004b9120001000000000000000000000094ba12001400000000000000000000002cac12000e0000000000000034bb12000100000000000000000000004cbb12001400000000000000000000003aac12000f00000000000000301a1300000000000000000000000000ecbb120015000000000000000000000049ac1200100000000000000004b9120001000000000000000000000094bc12000b000000000000000000000025cb120007000000000000007ac312000c00000000000000fbea1200040000000000000061d112001700000048d0120029000000301a13000000000024bd12004500000069bd12003a000000301a130000000000a3bd12000c00000071d0120049000000bad0120040000000301a130000000000f5bd12000b000000fad01200250000001fd112004200000044be12000c0000000000000044d0120004000000000000007ac312000c0000000000000073c3120007000000000000007ac312000c00000014cf1200470000005bcf12001d000000301a13000000000078cf120032000000301a130000000000a3bd12000c000000aacf12002e000000d8cf120047000000301a130000000000f5bd12000b0000001fd012001900000038d012000c00000044be12000c00000000000000d6ce12000700000000000000ddce12001100000000000000eece12000900000000000000f7ce12000300000000000000face12000c0000000000000006cf12000e0000002ccb120057000000301a13000000000083cb12004c000000cfcb12005200000021cc12002f000000301a13000000000098c9120034000000301a130000000000a3bd12000c00000050cc12004900000099cc120035000000cecc12004c0000001acd12004700000061cd12002500000086cd12004f000000d5cd12003a000000301a130000000000f5bd12000b0000000fce12001a00000029ce12004b00000074ce12003b000000e3ca120027000000afce1200270000002bc112000d000000301a13000000000038c112001b00000044be12000c0000000000000025cb120007000000000000007ac312000c0000009fc812003b000000301a130000000000dac812004700000021c91200490000006ac912002e000000301a13000000000098c9120034000000301a130000000000a3bd12000c000000ccc912004500000011ca120040000000301a130000000000f5bd12000b00000051ca12003e0000008fca120054000000e3ca120027000000cec51200390000000acb12001b0000002bc112000d000000301a13000000000038c112001b00000044be12000c00000049c612004a00000093c612001a000000301a130000000000adc612004a000000f7c612001d000000301a130000000000a3bd12000c00000014c712003500000049c71200440000008dc7120015000000301a130000000000a2c7120049000000ebc7120009000000301a130000000000f5bd12000b00000000c512003f0000003fc512004700000086c5120048000000f4c712003b0000002fc812004700000007c61200270000002bc112000d000000301a13000000000076c812002900000044be12000c00000086c312003d000000301a130000000000c3c312004b0000000ec412004700000055c412004c000000301a130000000000a3bd12000c000000a1c412004b000000ecc4120014000000301a130000000000f5bd12000b00000000c512003f0000003fc512004700000086c5120048000000cec512003900000007c61200270000002bc112000d000000301a1300000000002ec612001b00000044be12000c0000000000000073c3120007000000000000007ac312000c00000053c112004500000098c112001a000000301a130000000000b2c1120048000000fac112003e000000301a130000000000dabf12004100000038c212003c000000301a130000000000a3bd12000c00000074c2120044000000301a130000000000f5bd12000b000000b8c2120021000000d9c212004f00000028c31200300000002bc112000d000000301a13000000000058c312001b00000044be12000c00000050be120057000000301a130000000000a7be120045000000ecbe120042000000301a1300000000002ebf12004900000077bf1200260000009dbf12003d000000301a130000000000dabf1200410000001bc0120039000000301a130000000000f5bd12000b00000054c01200180000006cc012004a000000b6c012004e00000004c11200270000002bc112000d000000301a13000000000038c112001b00000044be12000c000000ecbc120038000000301a13000000000024bd12004500000069bd12003a000000301a130000000000a3bd12000c000000afbd120046000000301a130000000000f5bd12000b00000000be12004400000044be12000c0000002043616e63656c20746865206162696c69747920746f20757365206061735f7265636f76657265646020666f7220606163636f756e74602e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e64207265676973746572656420746f2062652061626c6520746f206d616b652063616c6c73206f6e20626568616c66206f6620746865207265636f7665726564206163636f756e742e20506172616d65746572733a202d20606163636f756e74603a20546865207265636f7665726564206163636f756e7420796f75206172652061626c6520746f2063616c6c206f6e2d626568616c662d6f662e2023203c7765696768743e202d204f6e652073746f72616765206d75746174696f6e20746f20636865636b206163636f756e74206973207265636f7665726564206279206077686f602e204f2831292023203c2f7765696768743e2052656d6f766520746865207265636f766572792070726f6365737320666f7220796f7572206163636f756e742e205265636f7665726564206163636f756e747320617265207374696c6c2061636365737369626c652e204e4f54453a205468652075736572206d757374206d616b65207375726520746f2063616c6c2060636c6f73655f7265636f7665727960206f6e20616c6c20616374697665207265636f7665727920617474656d707473206265666f72652063616c6c696e6720746869732066756e6374696f6e20656c73652069742077696c6c206661696c2e205061796d656e743a2042792063616c6c696e6720746869732066756e6374696f6e20746865207265636f76657261626c65206163636f756e742077696c6c20756e72657365727665207468656972207265636f7665727920636f6e66696775726174696f6e206465706f7369742e202860436f6e6669674465706f7369744261736560202b2060467269656e644465706f736974466163746f7260202a20235f6f665f667269656e64732920546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e64206d7573742062652061207265636f76657261626c65206163636f756e742028692e652e206861732061207265636f7665727920636f6e66696775726174696f6e292e204b65793a204620286c656e206f6620667269656e647329202d204f6e652073746f72616765207265616420746f206765742074686520707265666978206974657261746f7220666f7220616374697665207265636f7665726965732e204f283129202d204f6e652073746f7261676520726561642f72656d6f766520746f2067657420746865207265636f7665727920636f6e66696775726174696f6e2e204f2831292c20436f646563204f284629202d204f6e652062616c616e63652063616c6c20746f20756e72657365727665642e204f285829202d204f6e65206576656e742e20546f74616c20436f6d706c65786974793a204f2846202b2058292041732074686520636f6e74726f6c6c6572206f662061207265636f76657261626c65206163636f756e742c20636c6f736520616e20616374697665207265636f766572792070726f6365737320666f7220796f7572206163636f756e742e205061796d656e743a2042792063616c6c696e6720746869732066756e6374696f6e2c20746865207265636f76657261626c65206163636f756e742077696c6c207265636569766520746865207265636f76657279206465706f73697420605265636f766572794465706f7369746020706c616365642062792074686520726573637565722e207265636f76657261626c65206163636f756e74207769746820616e20616374697665207265636f766572792070726f6365737320666f722069742e202d206072657363756572603a20546865206163636f756e7420747279696e6720746f207265736375652074686973207265636f76657261626c65206163636f756e742e204b65793a205620286c656e206f6620766f756368696e6720667269656e647329202d204f6e652073746f7261676520726561642f72656d6f766520746f206765742074686520616374697665207265636f766572792070726f636573732e204f2831292c20436f646563204f285629202d204f6e652062616c616e63652063616c6c20746f20726570617472696174652072657365727665642e204f28582920546f74616c20436f6d706c65786974793a204f2856202b20582972657363756572543a3a4163636f756e74496420416c6c6f772061207375636365737366756c207265736375657220746f20636c61696d207468656972207265636f7665726564206163636f756e742e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e64206d7573742062652061202272657363756572222077686f20686173207375636365737366756c6c7920636f6d706c6574656420746865206163636f756e74207265636f766572792070726f636573733a20636f6c6c656374656420607468726573686f6c6460206f72206d6f726520766f75636865732c20776169746564206064656c61795f706572696f646020626c6f636b732073696e636520696e6974696174696f6e2e202d20606163636f756e74603a20546865206c6f7374206163636f756e74207468617420796f752077616e7420746f20636c61696d20686173206265656e207375636365737366756c6c792020207265636f766572656420627920796f752e204b65793a204620286c656e206f6620667269656e647320696e20636f6e666967292c205620286c656e206f6620766f756368696e6720667269656e647329202d204f6e652073746f72616765207265616420746f2067657420746865207265636f7665727920636f6e66696775726174696f6e2e204f2831292c20436f646563204f284629202d204f6e652073746f72616765207265616420746f206765742074686520616374697665207265636f766572792070726f636573732e204f2831292c20436f646563204f285629202d204f6e652073746f72616765207265616420746f20676574207468652063757272656e7420626c6f636b206e756d6265722e204f283129202d204f6e652073746f726167652077726974652e204f2831292c20436f646563204f2856292e20546f74616c20436f6d706c65786974793a204f2846202b20562920416c6c6f7720612022667269656e6422206f662061207265636f76657261626c65206163636f756e7420746f20766f75636820666f7220616e20616374697665207265636f766572792070726f6365737320666f722074686174206163636f756e742e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20616e64206d75737420626520612022667269656e642220666f7220746865207265636f76657261626c65206163636f756e742e202d20606c6f7374603a20546865206c6f7374206163636f756e74207468617420796f752077616e7420746f207265636f7665722e202d206072657363756572603a20546865206163636f756e7420747279696e6720746f2072657363756520746865206c6f7374206163636f756e74207468617420796f7520202077616e7420746f20766f75636820666f722e2054686520636f6d62696e6174696f6e206f662074686573652074776f20706172616d6574657273206d75737420706f696e7420746f20616e20616374697665207265636f766572792070726f636573732e202d204f6e652062696e6172792073656172636820746f20636f6e6669726d2063616c6c6572206973206120667269656e642e204f286c6f674629202d204f6e652062696e6172792073656172636820746f20636f6e6669726d2063616c6c657220686173206e6f7420616c726561647920766f75636865642e204f286c6f67562920546f74616c20436f6d706c65786974793a204f2846202b206c6f6746202b2056202b206c6f67562920496e697469617465207468652070726f6365737320666f72207265636f766572696e672061207265636f76657261626c65206163636f756e742e205061796d656e743a20605265636f766572794465706f736974602062616c616e63652077696c6c20626520726573657276656420666f7220696e6974696174696e6720746865207265636f766572792070726f636573732e2054686973206465706f7369742077696c6c20616c7761797320626520726570617472696174656420746f20746865206163636f756e7420747279696e6720746f206265207265636f76657265642e205365652060636c6f73655f7265636f76657279602e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f2e202d20606163636f756e74603a20546865206c6f7374206163636f756e74207468617420796f752077616e7420746f207265636f7665722e2054686973206163636f756e742020206e6565647320746f206265207265636f76657261626c652028692e652e20686176652061207265636f7665727920636f6e66696775726174696f6e292e202d204f6e652073746f72616765207265616420746f20636865636b2074686174206163636f756e74206973207265636f76657261626c652e204f284629202d204f6e652073746f72616765207265616420746f20636865636b20746861742074686973207265636f766572792070726f63657373206861736e277420616c726561647920737461727465642e204f283129202d204f6e652063757272656e63792072657365727665206f7065726174696f6e2e204f285829202d204f6e652073746f726167652077726974652e204f2831292e6163636f756e74204372656174652061207265636f7665727920636f6e66696775726174696f6e20666f7220796f7572206163636f756e742e2054686973206d616b657320796f7572206163636f756e74207265636f76657261626c652e205061796d656e743a2060436f6e6669674465706f7369744261736560202b2060467269656e644465706f736974466163746f7260202a20235f6f665f667269656e64732062616c616e63652077696c6c20626520726573657276656420666f722073746f72696e6720746865207265636f7665727920636f6e66696775726174696f6e2e2054686973206465706f7369742069732072657475726e656420696e2066756c6c207768656e2074686520757365722063616c6c73206072656d6f76655f7265636f76657279602e202d2060667269656e6473603a2041206c697374206f6620667269656e647320796f7520747275737420746f20766f75636820666f72207265636f7665727920617474656d7074732e20202053686f756c64206265206f72646572656420616e6420636f6e7461696e206e6f206475706c69636174652076616c7565732e202d20607468726573686f6c64603a20546865206e756d626572206f6620667269656e64732074686174206d75737420766f75636820666f722061207265636f7665727920617474656d70742020206265666f726520746865206163636f756e742063616e206265207265636f76657265642e2053686f756c64206265206c657373207468616e206f7220657175616c20746f202020746865206c656e677468206f6620746865206c697374206f6620667269656e64732e202d206064656c61795f706572696f64603a20546865206e756d626572206f6620626c6f636b732061667465722061207265636f7665727920617474656d707420697320696e697469616c697a656420202074686174206e6565647320746f2070617373206265666f726520746865206163636f756e742063616e206265207265636f76657265642e202d204b65793a204620286c656e206f6620667269656e647329202d204f6e652073746f72616765207265616420746f20636865636b2074686174206163636f756e74206973206e6f7420616c7265616479207265636f76657261626c652e204f2831292e202d204120636865636b20746861742074686520667269656e6473206c69737420697320736f7274656420616e6420756e697175652e204f284629202d204f6e652073746f726167652077726974652e204f2831292e20436f646563204f2846292e667269656e64735665633c543a3a4163636f756e7449643e7468726573686f6c6475313664656c61795f706572696f64543a3a426c6f636b4e756d62657220416c6c6f7720524f4f5420746f2062797061737320746865207265636f766572792070726f6365737320616e642073657420616e20612072657363756572206163636f756e7420666f722061206c6f7374206163636f756e74206469726563746c792e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f524f4f545f2e202d20606c6f7374603a2054686520226c6f7374206163636f756e742220746f206265207265636f76657265642e202d206072657363756572603a20546865202272657363756572206163636f756e74222077686963682063616e2063616c6c20617320746865206c6f7374206163636f756e742e202d204f6e652073746f72616765207772697465204f283129202d204f6e65206576656e746c6f73742053656e6420612063616c6c207468726f7567682061207265636f7665726564206163636f756e742e202d20606163636f756e74603a20546865207265636f7665726564206163636f756e7420796f752077616e7420746f206d616b6520612063616c6c206f6e2d626568616c662d6f662e202d206063616c6c603a205468652063616c6c20796f752077616e7420746f206d616b65207769746820746865207265636f7665726564206163636f756e742e202d2054686520776569676874206f6620746865206063616c6c60202b2031302c3030302e202d204f6e652073746f72616765206c6f6f6b757020746f20636865636b206163636f756e74206973207265636f7665726564206279206077686f602e204f283129426f783c3c542061732054726169743e3a3a43616c6c3e5265636f766572790000000088d212000b00000001050000000000007ac312000c0000000000000093d212003a00000000000000000000000000000000000000301a1300d0d212000000000000000000e0d2120001000000000000000000000000000000e8d212001000000002050500000000007ac312000c000000000000007ac312000c00000000000000f8d212003a00000000000000301a130034d31200000000000000000044d312000400000000000000000000000000000064d312000500000001020000000000007ac312000c000000000000007ac312000c00000000000000000000000000000000000000301a130028e0120000000000000000006cd312000300000000000000000000005265636f76657261626c655265636f76657279436f6e6669673c543a3a426c6f636b4e756d6265722c2042616c616e63654f663c543e2c20543a3a4163636f756e7449643e0000004200000000000000010000005b00000070d41200420000004163746976655265636f7665726965734163746976655265636f766572793c543a3a426c6f636b4e756d6265722c2042616c616e63654f663c543e2c20543a3a4163636f756e7449643e00004200000000000000010000005b000000e6d312001a000000301a13000000000000d412004500000045d412002b00000050726f787900000084d3120024000000301a130000000000a8d312003e00000020546865206c697374206f6620616c6c6f7765642070726f7879206163636f756e74732e204d61702066726f6d2074686520757365722077686f2063616e2061636365737320697420746f20746865207265636f7665726564206163636f756e742e20416374697665207265636f7665727920617474656d7074732e204669727374206163636f756e7420697320746865206163636f756e7420746f206265207265636f76657265642c20616e6420746865207365636f6e64206163636f756e7420697320746865207573657220747279696e6720746f207265636f76657220746865206163636f756e742e2054686520736574206f66207265636f76657261626c65206163636f756e747320616e64207468656972207265636f7665727920636f6e66696775726174696f6e2e000000000000fbaf12000b0000000000000090d51200020000000000000000000000c0d5120006000000000000000000000006b012000700000000000000f0d5120001000000000000000000000008d612000300000000000000000000000db01200070000000000000020d6120002000000000000000000000050d6120004000000000000000000000014b01200040000000000000070d61200030000000000000000000000b8d6120004000000000000000000000018b012000500000000000000d8d6120002000000000000000000000008d712000d0000000000000000000000cddb12000b00000000000000ddce12001100000000000000d8db12000500000000000000dddb1200140000001edb120021000000301a1300000000003fdb12003f0000007edb120039000000301a130000000000b7db1200160000000000000089d91200080000000000000098da12001e000000b6da12003d000000301a130000000000f3da12002b00000000000000eece1200090000000000000084da1200140000000000000089d91200080000000000000098da12001e000000f5bd12000b00000032da12002400000056da12002e00000044be12000c0000000000000089d91200080000000000000091d91200070000000000000098d9120005000000000000009dd9120016000000000000002bda12000700000000000000a1f5120004000000f5bd12000b000000b3d9120023000000d6d912005500000044be12000c0000000000000089d91200080000000000000091d91200070000000000000098d9120005000000000000009dd912001600000070d7120054000000c4d7120026000000301a130000000000ead712005700000041d8120019000000301a1300000000005ad81200250000007fd81200200000009fd8120043000000e2d812002c0000000ed912001e0000002cd912002700000053d9120036000000204d61792062652063616c6c656420627920616e79207369676e6564206163636f756e742061667465722074686520766f74696e67206475726174696f6e2068617320656e64656420696e206f7264657220746f2066696e69736820766f74696e6720616e6420636c6f7365207468652070726f706f73616c2e2041627374656e74696f6e732061726520636f756e7465642061732072656a656374696f6e7320756e6c6573732074686572652069732061207072696d65206d656d6265722073657420616e6420746865207072696d65206d656d626572206361737420616e20617070726f76616c2e202d2074686520776569676874206f66206070726f706f73616c6020707265696d6167652e202d20757020746f207468726565206576656e7473206465706f73697465642e202d206f6e6520726561642c2074776f2072656d6f76616c732c206f6e65206d75746174696f6e2e2028706c7573207468726565207374617469632072656164732e29202d20636f6d7075746174696f6e20616e6420692f6f20604f2850202b204c202b204d29602077686572653a2020202d20604d60206973206e756d626572206f66206d656d626572732c2020202d20605060206973206e756d626572206f66206163746976652070726f706f73616c732c2020202d20604c602069732074686520656e636f646564206c656e677468206f66206070726f706f73616c6020707265696d6167652e70726f706f73616c543a3a48617368696e646578436f6d706163743c50726f706f73616c496e6465783e202d20426f756e6465642073746f72616765207265616420616e64207772697465732e202d2057696c6c20626520736c696768746c792068656176696572206966207468652070726f706f73616c20697320617070726f766564202f20646973617070726f7665642061667465722074686520766f74652e617070726f7665202d20426f756e6465642073746f7261676520726561647320616e64207772697465732e202d20417267756d656e7420607468726573686f6c6460206861732062656172696e67206f6e207765696768742e436f6d706163743c4d656d626572436f756e743e426f783c3c542061732054726169743c493e3e3a3a50726f706f73616c3e20446973706174636820612070726f706f73616c2066726f6d2061206d656d626572207573696e672074686520604d656d62657260206f726967696e2e204f726967696e206d7573742062652061206d656d626572206f662074686520636f6c6c6563746976652e205365742074686520636f6c6c6563746976652773206d656d626572736869702e202d20606e65775f6d656d62657273603a20546865206e6577206d656d626572206c6973742e204265206e69636520746f2074686520636861696e20616e64202d20607072696d65603a20546865207072696d65206d656d6265722077686f736520766f74652073657473207468652064656661756c742e20526571756972657320726f6f74206f726967696e2e6e65775f6d656d626572737072696d654f7074696f6e3c543a3a4163636f756e7449643e5665633c543a3a486173683e000000d4dd12002400000050726f706f73616c4f663c542061732054726169743c493e3e3a3a50726f706f73616c00a1dd120033000000566f7465733c543a3a4163636f756e7449642c20543a3a426c6f636b4e756d6265723e0074dd12002d0000007533320062dd12001200000014dd12004e00000084dc120057000000dbdc12003900000020546865206d656d6265722077686f2070726f7669646573207468652064656661756c7420766f746520666f7220616e79206f74686572206d656d62657273207468617420646f206e6f7420766f7465206265666f7265207468652074696d656f75742e204966204e6f6e652c207468656e206e6f206d656d6265722068617320746861742070726976696c6567652e205468652063757272656e74206d656d62657273206f662074686520636f6c6c6563746976652e20546869732069732073746f72656420736f7274656420286a7573742062792076616c7565292e2050726f706f73616c7320736f206661722e20566f746573206f6e206120676976656e2070726f706f73616c2c206966206974206973206f6e676f696e672e2041637475616c2070726f706f73616c20666f72206120676976656e20686173682c20696620697427732063757272656e742e2054686520686173686573206f6620746865206163746976652070726f706f73616c732e0000000000b51200090000000000000000000000f1db12000c00000000000000000000000000000000000000000000000000000000000000301a130090e01200000000000000000000dc12000100000000000000010000000000000008dc12000a000000010600000000000091d91200070000000000000012dc12001900000000000000000000000000000000000000301a130028e0120000000000000000002cdc12000100000000000000000000000000000010b5120006000000010600000000000091d91200070000000000000034dc12002300000000000000000000000000000000000000301a130028e01200000000000000000058dc1200010000000000000000000000000000000ef812000d000000000000000000000060dc12000300000000000000000000000000000000000000000000000000000000000000301a130008e01200000000000000000064dc12000100000000000000010000000000000009b51200070000000000000000000000ddce12001100000000000000000000000000000000000000000000000000000000000000301a130018e0120000000000000000006cdc1200010000000000000001000000000000009caf12000500000000000000000000007ac312000c00000000000000000000000000000000000000000000000000000000000000301a130028e01200000000000000000074dc120002000000000000000000000042000000000000000100000057000000420000000000000001000000590000004200000000000000010000005b000000000000009ab412000e0000000000000000000000f1db12000c00000000000000000000000000000000000000000000000000000000000000301a130090e012000000000000000000a0e0120003000000000000000100000042000000000000000100000059000000b8e012005800000010e112005800000068e112001100000020536572696573206f6620626c6f636b20686561646572732066726f6d20746865206c61737420383120626c6f636b73207468617420616374732061732072616e646f6d2073656564206d6174657269616c2e205468697320697320617272616e67656420617320612072696e672062756666657220776974682060626c6f636b5f6e756d626572202520383160206265696e672074686520696e64657820696e746f20746865206056656360206f6620746865206f6c6465737420686173682e00000000000000cdab12000a000000000000003ce31200010000000000000000000000c0ab12000d0000000000000044e31200010000000000000000000000b0ab120010000000000000004ce31200010000000000000000000000a6ab12000a0000000000000054e312000100000000000000000000009dab120009000000000000005ce312000100000000000000000000008fab12000e0000000000000064e312000100000000000000000000007dab120012000000000000006ce312000100000000000000000000006fab12000e0000000000000074e3120001000000000000000000000065ab12000a000000000000007ce312000100000000000000000000005cab1200090000000000000084e3120001000000000000000000000051ab12000b000000000000008ce3120001000000000000000000000043ab12000e0000000000000094e312000100000000000000000000003aab120009000000000000009ce312000100000000000000000000002fab12000b00000000000000a4e3120001000000000000000000000027ab12000800000000000000ace312000100000000000000000000001bab12000c000000000000006ce3120001000000000000006fe612003d0000004be612002400000016e6120035000000ebe512002b000000b8e512003300000090e512002800000064e512002c0000002ce5120038000000f8e4120034000000cde412002b00000086e412004700000056e41200300000001be412003b000000dbe3120040000000b4e31200270000002054686572652077617320616e206f766572666c6f7720696e20612063616c63756c6174696f6e20546865726520617265207374696c6c20616374697665207265636f7665727920617474656d7074732074686174206e65656420746f20626520636c6f73656420546865207468726573686f6c6420666f72207265636f766572696e672074686973206163636f756e7420686173206e6f74206265656e206d6574205468697320757365722068617320616c726561647920766f756368656420666f722074686973207265636f766572792054686520667269656e64206d757374207761697420756e74696c207468652064656c617920706572696f6420746f20766f75636820666f722074686973207265636f766572792054686973206163636f756e74206973206e6f74206120667269656e642077686f2063616e20766f7563682041207265636f766572792070726f6365737320686173206e6f74207374617274656420666f72207468697320726573637565722041207265636f766572792070726f636573732068617320616c7265616479207374617274656420666f722074686973206163636f756e742054686973206163636f756e7420697320616c72656164792073657420757020666f72207265636f766572792054686973206163636f756e74206973206e6f742073657420757020666f72207265636f7665727920467269656e6473206c697374206d75737420626520736f7274656420616e642066726565206f66206475706c69636174657320467269656e6473206c697374206d757374206265206c657373207468616e206d617820667269656e647320467269656e6473206c697374206d7573742062652067726561746572207468616e207a65726f20616e64207468726573686f6c64205468726573686f6c64206d7573742062652067726561746572207468616e207a65726f2055736572206973206e6f7420616c6c6f77656420746f206d616b6520612063616c6c206f6e20626568616c66206f662074686973206163636f756e7400000000f2af1200090000000000000070e71200010000000000000000000000e1af1200110000000000000078e71200010000000000000000000000d2af12000f0000000000000080e71200010000000000000000000000c8af12000a0000000000000088e71200010000000000000000000000bbaf12000d0000000000000090e71200010000000000000000000000a9af1200120000000000000098e71200010000000000000000000000a1af12000800000000000000a0e71200010000000000000065e812001800000045e812002000000031e812001400000020e812001100000009e8120017000000e8e7120021000000a8e71200400000002054686520636c6f73652063616c6c206973206d61646520746f6f206561726c792c206265666f72652074686520656e64206f662074686520766f74696e672e204d656d626572732061726520616c726561647920696e697469616c697a656421204475706c696361746520766f74652069676e6f726564204d69736d61746368656420696e6465782050726f706f73616c206d757374206578697374204475706c69636174652070726f706f73616c73206e6f7420616c6c6f776564204163636f756e74206973206e6f742061206d656d626572417574686f72697479446973636f766572794b657973417574686f7273686970446964536574556e636c65734261626545706f6368496e646578417574686f72697469657347656e65736973536c6f7443757272656e74536c6f7452616e646f6d6e6573734e65787452616e646f6d6e6573735365676d656e74496e646578556e646572436f6e737472756374696f6e746f6f206d616e7920696e737472756374696f6e734e6f6e2d656d7074792066756e6374696f6e20626f647920657870656374656400008ce912000f0000009be91200020000009de9120003000000617373657274696f6e206661696c65643a20636f6e746578742e6672616d655f737461636b2e69735f656d7074792829417420696e737472756374696f6e202840293a2043616e2774206465636f6465207761736d20636f64654d6f64756c65206973206e6f742076616c69646d6f64756c65206465636c6172657320696e7465726e616c206d656d6f72796d756c7469706c65207461626c6573206465636c617265647461626c652065786365656473206d6178696d756d2073697a6520616c6c6f776564757365206f6620666c6f6174696e6720706f696e74207479706520696e2066756e6374696f6e20747970657320697320666f7262696464656e757365206f6620666c6f6174696e6720706f696e74207479706520696e206c6f63616c7320697320666f7262696464656e757365206f6620666c6f6174696e6720706f696e74207479706520696e20676c6f62616c7320697320666f7262696464656e67617320696e737472756d656e746174696f6e206661696c6564737461636b2068656967687420696e737472756d656e746174696f6e206661696c656463616c6c6465706c6f796465706c6f792066756e6374696f6e2069736e2774206578706f72746564756e6b6e6f776e206578706f72743a20657870656374696e67206f6e6c79206465706c6f7920616e642063616c6c2066756e6374696f6e7366756e6374696f6e206861732061206e6f6e2d6578697374656e7420747970656578706f72742072656665727320746f206e6f6e2d6578697374656e742066756e6374696f6e657870656374656420612066756e6374696f6e656e74727920706f696e7420706f696e747320746f20616e20696d706f727465642066756e6374696f6e656e74727920706f696e74206861732077726f6e67207369676e617475726563616c6c2066756e6374696f6e2069736e2774206578706f727465646572726f722073657269616c697a696e6720696e737472756d656e746564206d6f64756c6552657475726e207479706573206c656e6774682073686f756c642062652030206f72203143757272656e745363686564756c65436f6e7472616374734163636f756e74436f756e74657298ec12006700000051010000170000002f686f6d652f6461766964642f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f7061726974792d7761736d2d302e34312e302f7372632f656c656d656e74732f73656374696f6e2e72730089ef12001e000000a7ef12001f00000066756e6374696f6e5f73656374696f6e5f6c656e20213d20303b2071656400002bef12005e000000d10000002000000066756e6374696f6e5f73656374696f6e5f6c656e20213d20303b2066756e6374696f6e5f73656374696f6e5f6c656e203d3d20636f64655f73656374696f6e5f6c656e3b207165642bef12005e000000d40000001c00000011ef12001a000000ecee12000a000000f6ee12001b00000073746172742066756e6374696f6e20657870656374656420746f20686176652074797065205b5d202d3e205b5d000000dbee120011000000bbee1200200000009bee12002000000073ee12002800000070617373697665206d656d6f7279207365676d656e747320617265206e6f7420737570706f727465647365676d656e74206f66667365742073686f756c642072657475726e204933327061737369766520656c656d656e74207365676d656e747320617265206e6f7420737570706f72746564746f6f206d616e79206d656d6f727920726567696f6e7320696e20696e6465782073706163653a20746f6f206d616e79207461626c657320696e20696e6465782073706163653a20747279696e6720746f20696d706f7274206d757461626c6520676c6f62616c206475706c6963617465206578706f72742046756e6374696f6e20232072656164696e672f76616c69646174696f6e206572726f723a204d697373696e6720626f647920666f722066756e6374696f6e202f686f6d652f6461766964642f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f7761736d692d76616c69646174696f6e2d302e332e302f7372632f6c69622e72736c656e677468206f662066756e6374696f6e2073656374696f6e206973202c207768696c65206c656e206f6620636f64652073656374696f6e206973206578745f7365745f73746f726167656578745f636c6561725f73746f726167656578745f6765745f73746f726167656578745f7472616e736665726578745f63616c6c6578745f696e7374616e74696174656578745f7465726d696e6174656578745f72657475726e6578745f63616c6c65726578745f616464726573736578745f6761735f70726963656578745f6761735f6c6566746578745f62616c616e63656578745f76616c75655f7472616e736665727265646578745f72616e646f6d6578745f6e6f776578745f6d696e696d756d5f62616c616e63656578745f746f6d6273746f6e655f6465706f7369746578745f64697370617463685f63616c6c6578745f726573746f72655f746f6578745f736372617463685f73697a656578745f736372617463685f726561646578745f736372617463685f77726974656578745f6465706f7369745f6576656e746578745f7365745f72656e745f616c6c6f77616e63656578745f72656e745f616c6c6f77616e63656578745f7072696e746c6e6578745f626c6f636b5f6e756d6265726578745f6765745f72756e74696d655f73746f726167656578745f686173685f736861325f3235366578745f686173685f6b656363616b5f3235366578745f686173685f626c616b65325f3235366578745f686173685f626c616b65325f3132385075626c696350726f70436f756e745265666572656e64756d436f756e7444656d6f63726163794c6f77657374556e62616b65644c6173745461626c656457617345787465726e616c0000000001000000020000000400000008000000100000002000000050687261676d656e456c656374696f6e456c656374696f6e526f756e647346696e616c697479547261636b6572496e697469616c697a656400000000dcf212000e00000000000000ecf21200010000000000000000000000f4f21200010000000000000000000000fcf212000600000000000000301a130000000000000000000000000004f312000100000000000000000000000cf312000700000000000000301a130000000000000000000000000014f3120001000000000000004e6577417574686f72697469657300008ff312000d0000006bf3120024000000506175736564000044f3120027000000526573756d6564001cf31200280000002043757272656e7420617574686f726974792073657420686173206265656e20726573756d65642e2043757272656e7420617574686f726974792073657420686173206265656e207061757365642e204e657720617574686f726974792073657420686173206265656e206170706c6965642e417574686f726974794c69737443757272656e7453657449644772616e64706146696e616c697479536574496453657373696f6e00d4f3120034000000b00000002e0000002f686f6d652f6461766964642f6465762f7375627374726174652f6672616d652f6964656e746974792f7372632f6c69622e7273496d4f6e6c696e655265636569766564486561727462656174734f6666656e6365735265706f72747342794b696e64496e6465780000000068f41200070000000000000070f4120003000000000000000000000088f4120003000000000000004f6666656e6365008ff512000400000093f512000e000000a1f5120004000000a0f4120055000000f5f412005300000048f512004700000020546865726520697320616e206f6666656e6365207265706f72746564206f662074686520676976656e20606b696e64602068617070656e656420617420746865206073657373696f6e5f696e6465786020616e6420286b696e642d7370656369666963292074696d6520736c6f742e2054686973206576656e74206973206e6f74206465706f736974656420666f72206475706c696361746520736c61736865732e206c61737420656c656d656e7420696e64696361746573206f6620746865206f6666656e636520776173206170706c69656420287472756529206f7220717565756564202866616c7365292e4b696e644f706171756554696d65536c6f74626f6f6c43757272656e74496e6465785175657565644368616e67656444697361626c656456616c696461746f727300000000fcf512000a0000000000000008f6120001000000000000000000000010f6120002000000000000004e657753657373696f6e000097f612000c00000020f612005500000075f6120022000000204e65772073657373696f6e206861732068617070656e65642e204e6f746520746861742074686520617267756d656e74206973207468652073657373696f6e20696e6465782c206e6f742074686520626c6f636b206e756d626572206173207468652074797065206d6967687420737567676573742e53657373696f6e496e64657853657373696f6e53746f72656452616e6765486973746f7279446570746856616c696461746f72436f756e744d696e696d756d56616c696461746f72436f756e7443757272656e744572614163746976654572615374616b696e6745726173537461727453657373696f6e496e646578466f726365457261536c6173685265776172644672616374696f6e426f6e646564457261734561726c69657374556e6170706c696564536c61736851756575656453636f7265497343757272656e7453657373696f6e46696e616c4d69677261746545726174696d737461703054696d657374616d7020696e686572656e742064617461206973206e6f742070726f76696465642e496e76616c69642074696d657374616d7020696e686572656e74206461746120656e636f64696e672e54696d657374616d704469645570646174655472616e73616374696f6e5061796d656e744e6578744665654d756c7469706c696572547265617375727950726f706f73616c436f756e74417070726f76616c7334f812006200000088000000120000002f686f6d652f6461766964642f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f7061726974792d7363616c652d636f6465632d312e332e302f7372632f636f6465632e727300004200000004000000040000000c00000042725461626c65446174617461626c654200000004000000040000001e01000064656661756c744636345265696e74657270726574493634556e726561636861626c654e6f70426c6f636b004200000004000000040000001f0100004c6f6f704966456c7365456e6442724272496642725461626c6500004200000004000000040000002001000052657475726e43616c6c43616c6c496e6469726563740000420000000400000004000000fa00000044726f7053656c6563744765744c6f63616c5365744c6f63616c5465654c6f63616c476574476c6f62616c536574476c6f62616c4933324c6f61644936344c6f61644633324c6f61644636344c6f61644933324c6f616438534933324c6f616438554933324c6f61643136534933324c6f61643136554936344c6f616438534936344c6f616438554936344c6f61643136534936344c6f61643136554936344c6f61643332534936344c6f616433325549333253746f726549363453746f726546333253746f726546363453746f726549333253746f72653849333253746f7265313649363453746f72653849363453746f7265313649363453746f7265333243757272656e744d656d6f727947726f774d656d6f7279493332436f6e73740042000000040000000400000021010000493634436f6e737442000000040000000400000022010000463332436f6e7374463634436f6e73744200000004000000040000003400000049333245717a49333245714933324e654933324c74534933324c74554933324774534933324774554933324c65534933324c655549333247655349333247655549363445717a49363445714936344e654936344c74534936344c74554936344774534936344774554936344c65534936344c655549363447655349363447655546333245714633324e654633324c7446333247744633324c65463332476546363445714636344e654636344c7446363447744636344c654636344765493332436c7a49333243747a493332506f70636e744933324164644933325375624933324d756c493332446976534933324469765549333252656d5349333252656d55493332416e644933324f72493332586f7249333253686c4933325368725349333253687255493332526f746c493332526f7472493634436c7a49363443747a493634506f70636e744936344164644936345375624936344d756c493634446976534936344469765549363452656d5349363452656d55493634416e644936344f72493634586f7249363453686c4936345368725349363453687255493634526f746c493634526f74724633324162734633324e65674633324365696c463332466c6f6f724633325472756e634633324e656172657374463332537172744633324164644633325375624633324d756c4633324469764633324d696e4633324d6178463332436f70797369676e4636344162734636344e65674636344365696c463634466c6f6f724636345472756e634636344e656172657374463634537172744636344164644636345375624636344d756c4636344469764636344d696e4636344d6178463634436f70797369676e493332577261704936344933325472756e63534633324933325472756e63554633324933325472756e63534636344933325472756e6355463634493634457874656e6453493332493634457874656e64554933324936345472756e63534633324936345472756e63554633324936345472756e63534636344936345472756e6355463634463332436f6e7665727453493332463332436f6e7665727455493332463332436f6e7665727453493634463332436f6e766572745549363446333244656d6f7465463634463634436f6e7665727453493332463634436f6e7665727455493332463634436f6e7665727453493634463634436f6e766572745549363446363450726f6d6f74654633324933325265696e746572707265744633324936345265696e746572707265744636344633325265696e7465727072657449333200004200000004000000040000000c000000463634493332493634463332420000000400000004000000230100004e6f526573756c7456616c7565000000b4fe12000b000000492f4f204572726f723a2000d0fe120059000000450000001e0000002f686f6d652f6461766964642f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f7061726974792d7761736d2d302e34312e302f7372632f696f2e7273496e76616c696444617461547261696c696e6744617461556e6578706563746564456f66000000617474656d707420746f20646976696465206279207a65726f556e7369676e656420696e74656765722063616e277420626520637265617465642066726f6d206e656761746976652076616c75652f686f6d652f6461766964642f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f7072696d69746976652d74797065732d302e372e302f7372632f6c69622e72736469766973696f6e206279207a65726f496e7465676572206f766572666c6f77207768656e2063617374696e6720746f207573697a65000000000000000000000000000000617474656d707420746f20646976696465206279207a65726f0000009eff12005d0000002000000001000000547269656420746f20736872696e6b20746f2061206c6172676572206361706163697479e101130012000000f30113000c0000006066756e635f696478602073686f756c6420636f6d652066726f6d20606e6565645f7468756e6b73603b0a09090909606e6565645f7468756e6b736020697320706f70756c617465642077697468207468652073616d65206974656d73207468617420696e20607265706c6163656d656e745f6d6170603b0a09090909716564780113006900000050000000190000004174207468697320706f696e7420616e20696e646578206d7573742062652061737369676e656420746f2065616368207468756e6b0000007801130069000000890000001d0000002f686f6d652f6461766964642f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e31322e302f7372632f737461636b5f6865696768742f7468756e6b2e727366756e6374696f6e207769746820696478202069736e277420666f756e64617373657274696f6e206661696c65643a20656467652e686569676874203d3d2073656c662e686569676874202d2031617373657274696f6e206661696c65643a2073656c662e6c656e2829203c204341504143495459617373657274696f6e206661696c65643a20656467652e686569676874203d3d2073656c662e6e6f64652e686569676874202d20314672616d6569735f706f6c796d6f7270686963000042000000040000000400000024010000656e645f61726974790000004200000004000000040000000c0000006272616e63685f617269747973746172745f6865696768746003130049000000920200001a000000a9031300480000000002000023000000a90313004800000001020000230000006003130049000000a301000027000000617373657274696f6e206661696c65643a206d6964203c3d206c656e401a1300490000000a0000000900000060031300490000008e0200001d0000002f72757374632f666135316638313065356239323534393034623932363630653732383062376436613436663131322f7372632f6c6962636f72652f736c6963652f736f72742e72732f72757374632f666135316638313065356239323534393034623932363630653732383062376436613436663131322f7372632f6c6962636f72652f736c6963652f6d6f642e72730000006003130049000000a1000000300000006003130049000000a4000000300000004e6f2066756e6374696f6e2073656374696f6e4e6f20636f64652073656374696f6e4e6f20747970652073656374696f6e0000008b0613000a00000046756e6374696f6e206973206e6f7420666f756e6420696e2066756e632073656374696f6e0000007f0613000c00000046756e6374696f6e20626f647920666f722074686520696e6465782069736e277420666f756e6400300613000b00000029061300070000002306130006000000737461636b206f766572666c6f77737461636b206d757374206265206e6f6e2d656d707479000000180613000b0000004172697479206f6620616c6c206a756d702d74617267657473206d75737420626520657175616c54797065206e6f7420666f756e64000000380513006e000000c8000000170000002f686f6d652f6461766964642f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e31322e302f7372632f737461636b5f6865696768742f6d61785f6865696768742e727300001306130005000000747279696e6720746f20706f70206d6f72652076616c756573207468616e20707573686564737461636b20756e646572666c6f776d61785f686569676874707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f686569676874706f703a20756e726561636861626c65707573683a207472756e633a20706f705f6672616d653a20636f6e74726f6c20737461636b20697320656d707479000000380513006e0000003a0000000d000000636f6e74726f6c20737461636b206f75742d6f662d626f756e6473707573685f6672616d653a2066756e635f6964783a2063616c6c656420604f7074696f6e3a3a756e77726170282960206f6e206120604e6f6e65602076616c7565d006130055000000480600001b0000002f72757374632f666135316638313065356239323534393034623932363630653732383062376436613436663131322f7372632f6c6962616c6c6f632f636f6c6c656374696f6e732f62747265652f6d61702e7273656e766761736c6173745f696e6465782069732067726561746572207468616e20303b206c6173745f696e64657820697320737461636b2073697a65202d20313b2071656400008c0713005e000000a6000000260000008c0713005e000000120100001c0000002f686f6d652f6461766964642f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e31322e302f7372632f6761732f6d6f642e7273536f6d654e6f6e65000042000000040000000400000025010000410813006700000010010000200000001c0813002500000043616c6c20746f2066756e6374696f6e2074686174206f75742d6f662d626f756e64733a202f686f6d652f6461766964642f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e31322e302f7372632f737461636b5f6865696768742f6d6f642e7273546869732073686f756c64206265206120696e646578206f66206120646566696e65642066756e6374696f6e44756520746f2076616c69646174696f6e20636f64652073656374696f6e2073686f756c642065786973747346756e6374696f6e20626f6479206973206f7574206f6620626f756e647366756e6374696f6e20696d706f727420636f756e74206973206e6f74207a65726f3b20696d706f72742073656374696f6e206d757374206578697374733b207165644108130067000000590100000900000066756e635f696478206973206c657373207468616e2066756e6374696f6e20696d706f72747320636f756e743b0a090909096e74682066756e6374696f6e20696d706f7274206d7573742062652060536f6d65603b0a090909097165640000005c17130012000000250a13000f000000f80913000a000000020a130014000000160a13000f0000005369676e61747572652020287370656369666965642062792066756e6320292069736e277420646566696e6564206973206e6f7420646566696e6564440a13003f000000440000000d0000002f686f6d652f6461766964642f6465762f7375627374726174652f7072696d6974697665732f61726974686d657469632f7372632f62696775696e742e727300000000000000000000000000617474656d707420746f20646976696465206279207a65726f000000440a13003f0000006d00000009000000440a13003f0000007e00000009000000440a13003f0000009c0000001b000000440a13003f000000d40100001c000000440a13003f000000d50100001c00000063616e6e6f74206669742061206e756d62657220696e746f2075313238000000440a13003f0000009000000009000000616c7265616479206d757461626c7920626f72726f77656442000000000000000100000064000000640b1300430000001e030000090000002f72757374632f666135316638313065356239323534393034623932363630653732383062376436613436663131322f7372632f6c6962636f72652f63656c6c2e7273616c726561647920626f72726f776564004200000000000000010000006d000000640b1300430000006e0300000900000072656d696e646572206f6620646976206279206320697320616c77617973206c657373207468616e20633b20716564004200000008000000040000007a000000410c130046000000680000001b000000726573756c742063616e6e6f742066697420696e20753132382f686f6d652f6461766964642f6465762f7375627374726174652f7072696d6974697665732f61726974686d657469632f7372632f68656c706572735f3132386269742e727362616265736c6f74436f756c64206e6f74206465636f64652072657175657374656420696e686572656e742074797065214241424520696e686572656e742064617461206e6f7420666f756e64e40c130044000000cd0000000d0000002f686f6d652f6461766964642f6465762f7375627374726174652f7072696d6974697665732f72756e74696d652d696e746572666163652f7372632f696d706c732e727342000000000000000100000046000000486f737420746f207761736d2076616c7565732061726520656e636f64656420636f72726563746c793b207165640000780d13004600000008010000090000002f686f6d652f6461766964642f6465762f7375627374726174652f7072696d6974697665732f72756e74696d652d696e746572666163652f7372632f706173735f62792e727300004200000000000000010000004600000072756e74696d6552756e74696d65206d656d6f7279206578686175737465642e2041626f7274696e6700000000000000617474656d707420746f20646976696465206279207a65726f0000002c0e1300400000005f0000002b0000002f686f6d652f6461766964642f6465762f7375627374726174652f7072696d6974697665732f72756e74696d652f7372632f67656e657269632f6572612e727348617368206e6f7420657175616c2f686f6d652f6461766964642f6465762f7375627374726174652f7072696d6974697665732f72756e74696d652f7372632f7472616974732e72730000007a0e13003b0000000504000013000000426164206f726967696e43616e206e6f74206c6f6f6b757044697370617463684572726f723c7761736d3a73747269707065643e5472616e616374696f6e206469737061746368206973206d616e6461746f72793b207472616e73616374696f6e73206d6179206e6f742068617665206d616e6461746f727920646973706174636865732e412063616c6c20776173206c6162656c6c6564206173206d616e6461746f72792c2062757420726573756c74656420696e20616e204572726f722e5472616e73616374696f6e20776f756c642065786861757374732074686520626c6f636b206c696d6974735472616e73616374696f6e2068617320616e20616e6369656e7420626972746820626c6f636b5472616e73616374696f6e20686173206120626164207369676e61747572655472616e73616374696f6e206973206f757464617465645472616e73616374696f6e2077696c6c2062652076616c696420696e2074686520667574757265496e6162696c69747920746f2070617920736f6d6520666565732028652e672e206163636f756e742062616c616e636520746f6f206c6f77295472616e73616374696f6e2063616c6c206973206e6f74206578706563746564496e76616c69645472616e73616374696f6e20637573746f6d206572726f72436f756c64206e6f742066696e6420616e20756e7369676e65642076616c696461746f7220666f722074686520756e7369676e6564207472616e73616374696f6e436f756c64206e6f74206c6f6f6b757020696e666f726d6174696f6e20726571756972656420746f2076616c696461746520746865207472616e73616374696f6e556e6b6e6f776e5472616e73616374696f6e20637573746f6d206572726f72696e7465726e616c206572726f723a20656e746572656420756e726561636861626c6520636f64650088111300430000005a000000120000002f686f6d652f6461766964642f6465762f7375627374726174652f7072696d6974697665732f73616e64626f782f7372632f2e2e2f776974686f75745f7374642e727300881113004300000068000000120000004475706c69636174655265706f72744f6666656e63654572726f726d616b655f746f705f6672616d655f706f6c796d6f72706869632069732063616c6c6564207769746820656d707479206672616d6520737461636b0000260100000c00000004000000270100005f1413005f0000004204000011000000746869732066756e6374696f6e2063616e27742062652063616c6c6564207769746820656d707479206672616d6520737461636b5f1413005f000000b2040000050000004d6973706c6163656420656c736520696e737472756374696f6e0000df131300470000002614130005000000a313130037000000da131300050000006e1313001700000065131300090000001a161300140000004d1313001800000065131300090000001a161300140000001c1313001d00000039131300130000004c13130001000000546f6f206c61726765206d656d6f727920616c69676e6d656e7420325e20286578706563746564206174206d6f73742029547279696e6720746f2075706461746520676c6f62616c20206f66207479706520547279696e6720746f20757064617465206c6f63616c20537065636966696300000042000000040000000400000023010000416e794c6162656c7320696e2062725f7461626c6520706f696e747320746f20626c6f636b206f6620646966666572656e742074797065733a2020616e6420496620626c6f636b20776974686f757420656c736520726571756972656420746f2068617665204e6f526573756c7420626c6f636b20747970652e2042757420697420686173202074797065003c14130018000000541413000b000000556e657870656374656420737461636b20686569676874202c206578706563746564202f686f6d652f6461766964642f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f7761736d692d76616c69646174696f6e2d302e332e302f7372632f66756e632e7273547279696e6720746f2061636365737320706172656e74206672616d6520737461636b2076616c7565732e000000fc14130017000000131513001600000045787065637465642076616c7565206f66207479706520206f6e20746f70206f6620737461636b2e20476f74200000003415130007000000537461636b3a200000000100be1513002400000094151300060000009a1513000e000000a815130016000000701513002400000094151300060000006d6178696d756d206d656d6f72792073697a65206d757374206265206174206d6f7374202070616765736d6178696d756d206c696d697420206973206c657373207468616e206d696e696d756d20696e697469616c206d656d6f72792073697a65206d757374206265206174206d6f7374200000f4151300260000001a16130014000000547279696e6720746f20696e697469616c697a65207661726961626c65206f6620747970652020776974682076616c7565206f66207479706520496e69742065787072657373696f6e2073686f756c6420616c776179732062652077697468206c656e67746820324e6f6e20636f6e7374616e74206f70636f646520696e20696e69742065787072c516130007000000d716130022000000c516130007000000cc1613000b00000045787072657373696f6e20646f65736e277420656e647320776974682060656e6460206f70636f6465476c6f62616c20206973206d757461626c6520646f65736e277420657869737473206f72206e6f742079657420646566696e65640000000c171300100000001c1713000f0000004d656d6f727920617420696e6465782020646f65736e277420657869737473003c1713000f0000001c1713000f0000005461626c6520617420696e64657820005c171300120000001c1713000f00000046756e6374696f6e20617420696e646578200000801713000e0000001c1713000f0000005479706520617420696e646578200000ee171300100000001c1713000f000000c017130010000000e01713000e000000c017130010000000d017130010000000457870656374656420676c6f62616c2020746f20626520696d6d757461626c6520746f206265206d757461626c65476c6f62616c20617420696e646578206e6f6e2d656d70747920737461636b206578706563746564000028181300200000004818130012000000747279696e6720746f206765742076616c756520617420706f736974696f6e20206f6e20737461636b206f662073697a6520636865636b656420636f75706c65206f66206c696e65732061626f76650088181300600000004b0000000c0000002f686f6d652f6461766964642f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f7761736d692d76616c69646174696f6e2d302e332e302f7372632f737461636b2e7273f018130015000000657863656564656420737461636b206c696d697420000000301a1300000000004572726f72000000420000000400000004000000280100004c6f63616c732072616e6765206e6f7420696e2033322d6269742072616e6765601913002200000082191300150000009719130007000000547279696e6720746f20616363657373206c6f63616c207769746820696e64657820207768656e20746865726520617265206f6e6c7920206c6f63616c730000b81913002d000000e51913000c000000f119130003000000617373657274696f6e206661696c65643a2060286c656674203d3d20726967687429600a20206c6566743a2060602c0a2072696768743a2060603a20fc1913003400000064657374696e6174696f6e20616e6420736f7572636520736c69636573206861766520646966666572656e74206c656e67746873401a13004900000010000000090000002f72757374632f666135316638313065356239323534393034623932363630653732383062376436613436663131322f7372632f6c6962636f72652f6d6163726f732f6d6f642e727300418cb5cc000b080000000000000000004194b5cc000b082c1110002c11100000e1b605046e616d6501d8b605a50800196578745f6c6f6767696e675f6c6f675f76657273696f6e5f31011e6578745f68617368696e675f74776f785f3132385f76657273696f6e5f3102196578745f73746f726167655f7365745f76657273696f6e5f31031d6578745f68617368696e675f74776f785f36345f76657273696f6e5f3104206578745f68617368696e675f626c616b65325f3132385f76657273696f6e5f3105196578745f73746f726167655f6765745f76657273696f6e5f31061d6578745f6d6973635f7072696e745f757466385f76657273696f6e5f31071b6578745f73746f726167655f636c6561725f76657273696f6e5f3108226578745f73746f726167655f636c6561725f7072656669785f76657273696f6e5f3109206578745f68617368696e675f626c616b65325f3235365f76657273696f6e5f310a1c6578745f6d6973635f7072696e745f6865785f76657273696f6e5f310b276578745f63727970746f5f73746172745f62617463685f7665726966795f76657273696f6e5f310c286578745f63727970746f5f66696e6973685f62617463685f7665726966795f76657273696f6e5f310d236578745f6f6666636861696e5f69735f76616c696461746f725f76657273696f6e5f310e286578745f6f6666636861696e5f6c6f63616c5f73746f726167655f6765745f76657273696f6e5f310f346578745f6f6666636861696e5f6c6f63616c5f73746f726167655f636f6d706172655f616e645f7365745f76657273696f6e5f3110276578745f64656661756c745f6368696c645f73746f726167655f6765745f76657273696f6e5f3111306578745f64656661756c745f6368696c645f73746f726167655f73746f726167655f6b696c6c5f76657273696f6e5f3112276578745f64656661756c745f6368696c645f73746f726167655f7365745f76657273696f6e5f3113296578745f64656661756c745f6368696c645f73746f726167655f636c6561725f76657273696f6e5f3114226578745f6f6666636861696e5f72616e646f6d5f736565645f76657273696f6e5f3115236578745f63727970746f5f737232353531395f7665726966795f76657273696f6e5f3216286578745f6f6666636861696e5f6c6f63616c5f73746f726167655f7365745f76657273696f6e5f3117206578745f73616e64626f785f6d656d6f72795f6e65775f76657273696f6e5f3118256578745f73616e64626f785f6d656d6f72795f74656172646f776e5f76657273696f6e5f3119216578745f73616e64626f785f696e7374616e74696174655f76657273696f6e5f311a1c6578745f73616e64626f785f696e766f6b655f76657273696f6e5f311b276578745f73616e64626f785f696e7374616e63655f74656172646f776e5f76657273696f6e5f311c206578745f73616e64626f785f6d656d6f72795f6765745f76657273696f6e5f311d206578745f73616e64626f785f6d656d6f72795f7365745f76657273696f6e5f311e1e6578745f68617368696e675f736861325f3235365f76657273696f6e5f311f206578745f68617368696e675f6b656363616b5f3235365f76657273696f6e5f3120236578745f63727970746f5f656432353531395f7665726966795f76657273696f6e5f3121286578745f64656661756c745f6368696c645f73746f726167655f726f6f745f76657273696f6e5f31221c6578745f73746f726167655f617070656e645f76657273696f6e5f31231a6578745f73746f726167655f726f6f745f76657273696f6e5f3124226578745f73746f726167655f6368616e6765735f726f6f745f76657273696f6e5f3125226578745f6d6973635f72756e74696d655f76657273696f6e5f76657273696f6e5f31261c6578745f6d6973635f7072696e745f6e756d5f76657273696f6e5f31271e6578745f73746f726167655f6e6578745f6b65795f76657273696f6e5f31282a6578745f747269655f626c616b65325f3235365f6f7264657265645f726f6f745f76657273696f6e5f3129246578745f6f6666636861696e5f6e6574776f726b5f73746174655f76657273696f6e5f312a296578745f6f6666636861696e5f7375626d69745f7472616e73616374696f6e5f76657273696f6e5f312b1a6578745f73746f726167655f726561645f76657273696f6e5f312c1e6578745f616c6c6f6361746f725f6d616c6c6f635f76657273696f6e5f312d1c6578745f616c6c6f6361746f725f667265655f76657273696f6e5f312e256578745f63727970746f5f656432353531395f67656e65726174655f76657273696f6e5f312f376578745f63727970746f5f736563703235366b315f65636473615f7265636f7665725f636f6d707265737365645f76657273696f6e5f3130256578745f63727970746f5f737232353531395f67656e65726174655f76657273696f6e5f3131286578745f63727970746f5f737232353531395f7075626c69635f6b6579735f76657273696f6e5f3132216578745f63727970746f5f737232353531395f7369676e5f76657273696f6e5f31330c5f5f727573745f616c6c6f63340a5f5f72675f616c6c6f63350e5f5f727573745f6465616c6c6f63360c5f5f72675f6465616c6c6f63370e5f5f727573745f7265616c6c6f63380c5f5f72675f7265616c6c6f6339135f5f727573745f616c6c6f635f7a65726f65643a115f5f72675f616c6c6f635f7a65726f65643b09686173685f746573743c33616c6c6f633a3a616c6c6f633a3a68616e646c655f616c6c6f635f6572726f723a3a68353163623932333763613366353463663d08727573745f6f6f6d3e34616c6c6f633a3a7261775f7665633a3a63617061636974795f6f766572666c6f773a3a68636633313064393836323166623433303f29636f72653a3a70616e69636b696e673a3a70616e69633a3a683030363437306536303862656439353040673c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c26542c636f72653a3a736c6963653a3a497465723c543e3e3e3a3a737065635f657874656e643a3a68663630333566303732643235353538394125616c6c6f633a3a666d743a3a666f726d61743a3a68353162646564663733633836333235354236636f72653a3a70616e69636b696e673a3a70616e69635f626f756e64735f636865636b3a3a68393562303464643938363539313862364323636f72653a3a666d743a3a77726974653a3a68303831356161306566383061653962354448616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68303037343834663462386361636666364548616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68303135633362643336363064376362304633636f72653a3a6f7074696f6e3a3a6578706563745f6e6f6e655f6661696c65643a3a6836383432633035363039613131616134473a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a6862356535663530653539386135316130483b3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f636861723a3a6834383533323037383764313363643164493a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f666d743a3a68323565373337646265363866313463314a41616c6c6f633a3a7665633a3a5665633c543e3a3a737761705f72656d6f76653a3a6173736572745f6661696c65643a3a68633031623332663963663337653963314b4e636f72653a3a666d743a3a6e756d3a3a696d703a3a3c696d706c20636f72653a3a666d743a3a446973706c617920666f72207533323e3a3a666d743a3a68663135303861353562323463646664644c2d636f72653a3a70616e69636b696e673a3a70616e69635f666d743a3a68313231656364656237656134313664664d3c616c6c6f633a3a7665633a3a5665633c543e3a3a696e736572743a3a6173736572745f6661696c65643a3a68613934373131623037663536363065634e3c616c6c6f633a3a7665633a3a5665633c543e3a3a72656d6f76653a3a6173736572745f6661696c65643a3a68303739623034626265643466336234324f3f616c6c6f633a3a7665633a3a5665633c543e3a3a647261696e3a3a656e645f6173736572745f6661696c65643a3a6835643131373130356238363638376435504b3c616c6c6f633a3a7665633a3a5665633c75383e20617320636f72653a3a636f6e766572743a3a46726f6d3c267374723e3e3a3a66726f6d3a3a68386463303336393566373236363031305139636f72653a3a6f70733a3a66756e6374696f6e3a3a466e4f6e63653a3a63616c6c5f6f6e63653a3a6862393936313139646531313231346565522f636f72653a3a666d743a3a6e756d3a3a696d703a3a666d745f7536343a3a68366533616365353734346466643033645311727573745f626567696e5f756e77696e64542b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a683031343036616161383432343565306555313c5420617320636f72653a3a616e793a3a416e793e3a3a747970655f69643a3a68303661353130333961616237383235345635636f72653a3a666d743a3a466f726d61747465723a3a7061645f696e74656772616c3a3a68653932373262646363616336306465615743636f72653a3a666d743a3a466f726d61747465723a3a7061645f696e74656772616c3a3a77726974655f7072656669783a3a68643738323237356538303230633037345834636f72653a3a736c6963653a3a736c6963655f696e6465785f6c656e5f6661696c3a3a68313938373562666436383834646638635936636f72653a3a736c6963653a3a736c6963655f696e6465785f6f726465725f6661696c3a3a68316465333637626133373764636538645a2c636f72653a3a666d743a3a466f726d61747465723a3a7061643a3a68313636656363363539373163643363635b2e636f72653a3a7374723a3a736c6963655f6572726f725f6661696c3a3a68623233363366646233303032316536665c323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a68383435353735636630376666363164325d4a3c636f72653a3a6f70733a3a72616e67653a3a52616e67653c4964783e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68353536393033316138643865383531325e323c6368617220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68376161336631343238396430386261365f47636f72653a3a756e69636f64653a3a756e69636f64655f646174613a3a6772617068656d655f657874656e643a3a6c6f6f6b75703a3a68613835323132396535396333363565616032636f72653a3a756e69636f64653a3a7072696e7461626c653a3a636865636b3a3a68393165333839386434396631656236396149636f72653a3a666d743a3a6e756d3a3a3c696d706c20636f72653a3a666d743a3a446562756720666f72207573697a653e3a3a666d743a3a683236383537666231363037623539353362453c636f72653a3a63656c6c3a3a426f72726f774572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a683065623838643135356633303964303763483c636f72653a3a63656c6c3a3a426f72726f774d75744572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6862333335646536383631323063633233642e636f72653a3a6f7074696f6e3a3a6578706563745f6661696c65643a3a683633646465376666396462376438623465303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a686230333265336361626166646339613166323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a683061643362663132396338323533363767533c636f72653a3a666d743a3a6275696c646572733a3a5061644164617074657220617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a6836306236656363373161626162353536682e636f72653a3a736c6963653a3a6d656d6368723a3a6d656d6368723a3a6832336130393365346464623739333531693a636f72653a3a666d743a3a6275696c646572733a3a44656275675374727563743a3a6669656c643a3a68663330616534613631356331363839626a2f636f72653a3a666d743a3a57726974653a3a77726974655f636861723a3a68356261336366363138313565373762666b2e636f72653a3a666d743a3a57726974653a3a77726974655f666d743a3a68663435363732306637616333343265356c3a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a68383834636237333035363965623265616d3b3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f636861723a3a68656433643766613065316262373331326e3a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f666d743a3a68666434323965346239656338393933366f39636f72653a3a666d743a3a6275696c646572733a3a44656275675475706c653a3a6669656c643a3a68613533333665666163353734656238627037636f72653a3a666d743a3a6275696c646572733a3a44656275675365743a3a656e7472793a3a686637353538653961373662616632373071443c636f72653a3a666d743a3a417267756d656e747320617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a683362303935626162663933396632636272313c73747220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6862306565323536613538376662373638738001636f72653a3a7374723a3a7472616974733a3a3c696d706c20636f72653a3a736c6963653a3a536c696365496e6465783c7374723e20666f7220636f72653a3a6f70733a3a72616e67653a3a52616e67653c7573697a653e3e3a3a696e6465783a3a7b7b636c6f737572657d7d3a3a68376438313835366161663932613237397427636f72653a3a7374723a3a66726f6d5f757466383a3a6830613066313562666632633634383831753e3c636f72653a3a666d743a3a4572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a686130313939333562376233613364346576693c6672616d655f6d657461646174613a3a4465636f6465446966666572656e743c422c4f3e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6836633839313338393962326465613731776c3c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a683131636162386431306239626630303878493c616c6c6f633a3a7665633a3a5665633c75383e206173207061726974795f7761736d3a3a696f3a3a57726974653e3a3a77726974653a3a686538303463366336346431303063636479693c6672616d655f6d657461646174613a3a4465636f6465446966666572656e743c422c4f3e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68326335306536343564623663653564667a483c5b545d206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68633561613262653264646332633533397b513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a68366331646231303461373464363865327c3a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a68336662333236333863616364353236377d3b3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f636861723a3a68363239653634316237613866396631307e3a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f666d743a3a68653539373662636463313735623361617f503c6672616d655f737570706f72743a3a64656275673a3a57726974657220617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a683864616337306630633162323838346580014d3c6672616d655f737570706f72743a3a64656275673a3a52756e74696d654c6f67676572206173206c6f673a3a4c6f673e3a3a656e61626c65643a3a68386236316431323364646263636566388101493c6672616d655f737570706f72743a3a64656275673a3a52756e74696d654c6f67676572206173206c6f673a3a4c6f673e3a3a6c6f673a3a68353338633737353131616136353964338201323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a68333439613737636530353865613237308301383c6c6f673a3a4e6f704c6f67676572206173206c6f673a3a4c6f673e3a3a656e61626c65643a3a68633239643832333162626531343461648401343c6c6f673a3a4e6f704c6f67676572206173206c6f673a3a4c6f673e3a3a6c6f673a3a68373561656236636535666332353064388501363c6c6f673a3a4e6f704c6f67676572206173206c6f673a3a4c6f673e3a3a666c7573683a3a6832333664393961633239333539356465860137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6830306233616230316365303566353762870137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6830313138336261353330663735376166880137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6830313539356333616532386461336132890137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a68303938313666656635363836373464348a0137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a68306130376261626533643332346335328b0137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a68306233646536613136313166646435308c0137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a68306265633839663034633230333335368d0137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a68306565346266623164666664633131398e0137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a68313833636462623733303532343237358f0137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6831633138383230343530626239653433900137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6831636632633661666363653535343962910137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6831643436663636626232336533383666920137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6832303637333966373536346132336662930137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6832346536633636363337653535393631940137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6832616634616331623438646438396664950137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6832653933356538333434386234303034960137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6833383237316431623266633831663666970137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6834303333643664613139306665626463980137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6834383232383630643736613163353732990137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a68346362313561313938626162373534339a0137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a68353937376632376461343466386164359b0137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a68356561396138313961356231613439619c0137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a68363439363836303666353664613035669d0137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a68373535626135646537663936313539659e0137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a68383365633066633261353739653164329f0137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6838363836623239313566613066333130a00137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6839353032353630636139636166623661a10137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6839383265313132666366646234303661a20137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6862363539333836366361323837653837a30137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6862383861646232303966323232656231a40137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6864616238346263393430363538613437a50137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6865623161653131333435316565643934a60137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6865663038666639336337353237303066a70137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6866303862623863643834643632396636a80137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6866306631373136336237626238303865a90137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6866363864656237353365313461663162aa0137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6866663363303663636265343764333434ab013b70616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a7265776172645f62795f6964733a3a6864636139643036343738323164633830ac01386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6834313139373062343437616531373362ad015c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6833333833633533663066646563643133ae01386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6862353832613638383661383164353732af014b616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a566163616e74456e7472793c4b2c563e3a3a696e736572743a3a6839663061363539663838363338616262b001723c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6865323164343931373636326632646637b101613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6861356134346131616263636163636231b201706672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a6863663737636432363464396364633937b301706672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a6866346136633935396164626166363165b4015c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6831653164393839653161396135636530b5015c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6831666665373833303935306535353935b6015c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6832366334363936643039313539383762b7015c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6839396664303737346630666363383262b8015c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6862363264353235666237303932376562b9015c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6864376231326534373839353535313930ba015c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6864643435393335393231646238356666bb01746672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a6765743a3a6866303330336532366636323661626533bc01386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6864616163323265636339303261363938bd015c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6831343835353666343531396234366532be015c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6863366366353362303065386236633237bf013570616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a6e65775f6572613a3a6838363865613135646461396139356263c001386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6831663165396231656266303064373036c1014370616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a636c6561725f6572615f696e666f726d6174696f6e3a3a6864633566356431343030633634663137c2017c3c73705f72756e74696d655f696e746572666163653a3a706173735f62793a3a436f6465633c543e2061732073705f72756e74696d655f696e746572666163653a3a706173735f62793a3a506173734279496d706c3c543e3e3a3a66726f6d5f6666695f76616c75653a3a6838333637393936366666373735343431c301543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6833643235366261663161383635393630c4016b3c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c7533323e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6835626539633733323632656564623437c501860170616c6c65745f7374616b696e673a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722070616c6c65745f7374616b696e673a3a4578706f737572653c4163636f756e7449642c42616c616e63653e3e3a3a6465636f64653a3a6862373263363130643764383364653562c601303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6830356263646666653963363038383638c7018b013c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61704974657261746f723c4b2c562c4861736865723e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6835343634353665383630663135313332c8014e70616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a736c61736861626c655f62616c616e63655f6f665f766f74655f7765696768743a3a6834313166656532323136366431613466c901533c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a737065635f657874656e643a3a6837623066653764653564346663623934ca012573705f70687261676d656e3a3a656c6563743a3a6866333332326333306366633538383839cb014473705f70687261676d656e3a3a41737369676e6d656e743c4163636f756e7449642c543e3a3a696e746f5f7374616b65643a3a6830373431333861393335346132663361cc013173705f70687261676d656e3a3a6275696c645f737570706f72745f6d61703a3a6861333435313631653635393138303863cd01513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a6839353934343839393133303633336265ce01706672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a6832353738303831353236383565323662cf01723c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163745265663c753132383e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6833386432653937633831393637393337d0012d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a6865623630613835366464666230666437d101706672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a6834613934623137323135656561356361d201386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6833386539373537643037376334383863d301706672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a6837316633396462396563613464666338d401416672616d655f73797374656d3a3a4d6f64756c653c543e3a3a6465706f7369745f6576656e745f696e64657865643a3a6835346130353631613439363261623365d501386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6830306464643131313032633630666435d601386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6839393762383537626662636237363433d701386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6862333265356161663330663030663162d8013770616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a73746172745f6572613a3a6862363233363862303235626162646133d901386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6839303237343363373866363065363637da01386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6862303837626538313962323139383562db014a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6865363264373431313561666261666230dc015c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6833316130313665656135376230336162dd01386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6863373031383135303633303237353534de013570616c6c65745f7374616b696e673a3a736c617368696e673a3a646f5f736c6173683a3a6839316164393039633461386266393130df01446672616d655f737570706f72743a3a7472616974733a3a43757272656e63793a3a7265736f6c76655f6372656174696e673a3a6837366665613630346362386236313466e0014873705f72756e74696d653a3a7472616974733a3a4163636f756e744964436f6e76657273696f6e3a3a696e746f5f6163636f756e743a3a6830633633383531633435626139366235e1014a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6833653833343163646234376638656165e201713c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163745265663c7533323e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6837303032646133353961356264666234e3013c70616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6834643530636536383061383537613339e4013c70616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a656e737572655f6e65775f6572613a3a6830393732666433646632643436643261e501386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6831356536346137356531373461323034e6013e70616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6863363264663833376135313732656632e701723c70616c6c65745f7374616b696e673a3a5f5f4765744279746553747275637453746f7261676556657273696f6e3c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6833336135666263633530626133303430e801753c70616c6c65745f7374616b696e673a3a5f5f47657442797465537472756374457261456c656374696f6e5374617475733c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6862333831326230663835386563666334e9016d3c70616c6c65745f7374616b696e673a3a5f5f476574427974655374727563745370616e536c6173683c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6865346430383431333761653038643161ea013c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6866383035616566303437346163313730eb01723c70616c6c65745f7374616b696e673a3a5f5f4765744279746553747275637445726173546f74616c5374616b653c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6835326435363136643765613563383631ec01743c70616c6c65745f7374616b696e673a3a5f5f4765744279746553747275637445726173526577617264506f696e74733c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6836653530663432343764373132653937ed01763c70616c6c65745f7374616b696e673a3a5f5f476574427974655374727563744572617356616c696461746f7250726566733c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6835323234373938363964373462356662ee01763c70616c6c65745f7374616b696e673a3a5f5f47657442797465537472756374457261735374616b657273436c69707065643c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6863303930616637366532613763363534ef01793c70616c6c65745f7374616b696e673a3a5f5f476574427974655374727563744d696e696d756d56616c696461746f72436f756e743c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6862343734326261636139373865353332f001703c70616c6c65745f7374616b696e673a3a5f5f47657442797465537472756374486973746f727944657074683c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6834376231663234316131333837383530f1014170616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a7072655f64697370617463685f636865636b733a3a6830376139616237313539316231303132f201386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6861653030333130303931663063613330f3014770616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6866333435643531316437306262313931f4019b013c70616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a426f6e64696e674475726174696f6e44656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6862333038356136333062623933653730f5019a013c70616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a53657373696f6e7350657245726144656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6861303430396462303330346461356163f6016c3c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c753132383e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6864363635653835623335616132663537f7018e0170616c6c65745f7374616b696e673a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722070616c6c65745f7374616b696e673a3a47656e65726963436f6d7061637441737369676e6d656e74733c562c542c573e3e3a3a656e636f64655f746f3a3a6837313136666235333362323266656661f8018b0170616c6c65745f7374616b696e673a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722070616c6c65745f7374616b696e673a3a47656e65726963436f6d7061637441737369676e6d656e74733c562c542c573e3e3a3a6465636f64653a3a6863353762383663653866656635353130f90137616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6831353437633033383734353136373230fa012b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a6830343835653435366166613339343432fb015b70616c6c65745f7374616b696e673a3a47656e65726963436f6d7061637441737369676e6d656e74733c562c542c41636375726163793e3a3a66726f6d5f61737369676e6d656e743a3a6838383732373863613233333934396261fc01ba013c70616c6c65745f7374616b696e673a3a53746173684f663c543e2061732073705f72756e74696d653a3a7472616974733a3a436f6e766572743c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449642c636f72653a3a6f7074696f6e3a3a4f7074696f6e3c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3e3a3a636f6e766572743a3a6830616638363432323131623162326637fd01f3013c70616c6c65745f7374616b696e673a3a4d6f64756c653c543e2061732073705f7374616b696e673a3a6f6666656e63653a3a4f6e4f6666656e636548616e646c65723c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449642c283c542061732070616c6c65745f73657373696f6e3a3a54726169743e3a3a56616c696461746f7249642c3c542061732070616c6c65745f73657373696f6e3a3a686973746f726963616c3a3a54726169743e3a3a46756c6c4964656e74696669636174696f6e293e3e3a3a6f6e5f6f6666656e63653a3a6832656633633339663131363538393637fe01386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6863346231663334366631316233376163ff014a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a683330303135333935663033353664653280024970616c6c65745f7374616b696e673a3a736c617368696e673a3a496e7370656374696e675370616e733c543e3a3a6572615f7370616e3a3a686637666534373739663439626634366481024470616c6c65745f7374616b696e673a3a736c617368696e673a3a536c617368696e675370616e733a3a656e645f7370616e3a3a686131613338303033663362343434323582023570616c6c65745f73657373696f6e3a3a4d6f64756c653c543e3a3a64697361626c653a3a683662663838313764666333626235666183025e70616c6c65745f7374616b696e673a3a736c617368696e673a3a496e7370656374696e675370616e733c543e3a3a636f6d706172655f616e645f7570646174655f7370616e5f736c6173683a3a68356662646462613166316638626462648402d3023c70616c6c65745f7374616b696e673a3a4578706f737572654f663c543e2061732073705f72756e74696d653a3a7472616974733a3a436f6e766572743c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449642c636f72653a3a6f7074696f6e3a3a4f7074696f6e3c70616c6c65745f7374616b696e673a3a4578706f737572653c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449642c3c3c542061732070616c6c65745f7374616b696e673a3a54726169743e3a3a43757272656e6379206173206672616d655f737570706f72743a3a7472616974733a3a43757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a42616c616e63653e3e3e3e3a3a636f6e766572743a3a68366165633732636137343538356537328502386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a686561373263643463313939383833653786026a636f72653a3a6f70733a3a66756e6374696f6e3a3a696d706c733a3a3c696d706c20636f72653a3a6f70733a3a66756e6374696f6e3a3a466e4f6e63653c413e20666f7220266d757420463e3a3a63616c6c5f6f6e63653a3a68646461313137386666616564376263308702493c70616c6c65745f7374616b696e673a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a68643538653432356363326333303736388802623c70616c6c65745f7374616b696e673a3a47656e65726963436f6d7061637441737369676e6d656e74733c562c542c573e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a686230643338376132663535346235633589025a3c70616c6c65745f7374616b696e673a3a43616c6c3c543e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a68376139646535393235356236623761378a024373705f696f3a3a73746f726167653a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a726561643a3a68356631316666663034633234346237368b025a3c70616c6c65745f696e64696365733a3a4d6f64756c653c543e2061732073705f72756e74696d653a3a7472616974733a3a5374617469634c6f6f6b75703e3a3a6c6f6f6b75703a3a68363637616632356366663931613162338c025c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a68383836343239393966323134653135358d02336672616d655f73797374656d3a3a4d6f64756c653c543e3a3a696e635f7265663a3a68306235396665366132366334643530398e025c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a68643639653335623838326465313837368f02386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a683133333464633934343966353631313390028d013c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a4c6f636b61626c6543757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a7365745f6c6f636b3a3a683337623739646161613263303430633691023870616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a6b696c6c5f73746173683a3a6864326365663735666432363461363533920290013c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a4c6f636b61626c6543757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a72656d6f76655f6c6f636b3a3a683739616636313835633566656230373793024870616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a636865636b5f616e645f7265706c6163655f736f6c7574696f6e3a3a68303831346461353136633534306661369402746672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a6765743a3a683132666433336539326564633833363395025273705f61726974686d657469633a3a7065725f7468696e67733a3a50657262696c6c3a3a66726f6d5f726174696f6e616c5f617070726f78696d6174696f6e3a3a686630666536323262646132323831626696023970616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a6d616b655f7061796f75743a3a68303632316136623964616133663734649702386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68383837653464393332303634306330329802437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a68373261376638666436643338303831359902336672616d655f73797374656d3a3a4d6f64756c653c543e3a3a6465635f7265663a3a68373363386664363463323763653433389a02b2013c6672616d655f73797374656d3a3a4d6f64756c653c543e206173206672616d655f737570706f72743a3a7472616974733a3a53746f7265644d61703c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449642c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e74446174613e3e3a3a7472795f6d75746174655f6578697374733a3a68343864623564623262323538663163329b025b70616c6c65745f7374616b696e673a3a47656e65726963436f6d7061637441737369676e6d656e74733c562c542c41636375726163793e3a3a696e746f5f61737369676e6d656e743a3a68633432613962666466633334363131399c02386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68363663616538386266323333613932329d02633c636f72653a3a697465723a3a61646170746572733a3a4d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a666f6c643a3a68663239656236333235643336633234649e02613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a68623532636466636630306166373430639f025f3c70616c6c65745f7374616b696e673a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6831316434303430363132373532383830a002613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6839396432663639626232396434363662a1024470616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a646f5f70687261676d656e3a3a6832313836663665366438613036636565a202386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6865363430383138323931386434353163a3028b013c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61704974657261746f723c4b2c562c4861736865723e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6839343366613839663730633763623066a402443c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6830646335343235663931366265336535a502633c636f72653a3a697465723a3a61646170746572733a3a4d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a666f6c643a3a6838363764336163343130306534396663a6024d6672616d655f737570706f72743a3a7472616974733a3a4368616e67654d656d626572733a3a636f6d707574655f6d656d626572735f646966663a3a6839353666666563636639663165616533a70299013c70616c6c65745f636f6c6c6563746976653a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a4368616e67654d656d626572733c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6368616e67655f6d656d626572735f736f727465643a3a6834656335643432313562353635623333a802b2013c6672616d655f73797374656d3a3a4d6f64756c653c543e206173206672616d655f737570706f72743a3a7472616974733a3a53746f7265644d61703c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449642c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e74446174613e3e3a3a7472795f6d75746174655f6578697374733a3a6831373338623865633332343562373765a902437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6830396535326137613665323663643336aa02543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6831663262353933303961386238636532ab022e73705f70687261676d656e3a3a7265647563653a3a7265647563653a3a6866613839333933386335633064303363ac0248616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a456e7472793c4b2c563e3a3a6f725f696e736572743a3a6832363936366166363363626338383663ad023373705f70687261676d656e3a3a6e6f64653a3a4e6f64653c413e3a3a726f6f743a3a6832313162326230633165643831393031ae022b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a6837646430346163656532393739306635af023b73705f70687261676d656e3a3a6e6f64653a3a4e6f64653c413e3a3a69735f706172656e745f6f663a3a6838656537333833373639333435636461b002b2013c6672616d655f73797374656d3a3a4d6f64756c653c543e206173206672616d655f737570706f72743a3a7472616974733a3a53746f7265644d61703c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449642c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e74446174613e3e3a3a7472795f6d75746174655f6578697374733a3a6866633538393636646663356335623934b102386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6830303663376135636264323163623164b202386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6830346365656166336533313736373839b302386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6830396164366265643431623365333866b402386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6831326238663365323232373534313765b502386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6831353138626163323830343836383939b602386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6831626530663065356638343261306131b702386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6831666234306230623362313530353464b802386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6832383436613537373538383536313062b9026b6e6f64655f72756e74696d653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f72206e6f64655f72756e74696d653a3a43616c6c3e3a3a6465636f64653a3a6833303331316332393734623531313537ba022b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a6837626530343537633261323562366639bb022b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a6837626530343537633261323562366639bc02386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6832653466383037646162323536646363bd02386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6833326362393833393534356432663763be02386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6833353064666630323434646466666339bf02850170616c6c65745f736f63696574793a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722070616c6c65745f736f63696574793a3a4269644b696e643c4163636f756e7449642c42616c616e63653e3e3a3a6465636f64653a3a6866313235363563313165623962613634c002386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6833626365633832626135653635626530c102386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6833666539333037396566343139363235c202726e6f64655f72756e74696d653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f72206e6f64655f72756e74696d653a3a53657373696f6e4b6579733e3a3a6465636f64653a3a6839353939313966326534633236316632c302386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6834336466636238346637343730653239c402386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6834623236373432613535373633633038c502386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6835343638336563333961313639613737c602386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6835346432346363353461363437383562c702960173705f7374616b696e673a3a6f6666656e63653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722073705f7374616b696e673a3a6f6666656e63653a3a4f6666656e636544657461696c733c5265706f727465722c4f6666656e6465723e3e3a3a6465636f64653a3a6831653765323661336635613461383461c8022b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a6836646335333530646333613065383137c902386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6836353263323130333635656163303636ca028f0170616c6c65745f64656d6f63726163793a3a766f74653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722070616c6c65745f64656d6f63726163793a3a766f74653a3a4163636f756e74566f74653c42616c616e63653e3e3a3a6465636f64653a3a6861633539363439666333356636393939cb02386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6836363464646364623162396564333038cc02386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6836623833306538313430383264633566cd02386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6837363362306534326565313733363539ce02386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6838316166653732346534303035396535cf02543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6866306166393161396338646231373539d002386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6838336538616661363836613730363065d102386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6838613564366633633165316665663834d202386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6839313063323861313964653537386663d302386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6839396663356535633130633832633832d402386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6861393462353839616266346234666435d5026b3c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c7533323e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6833336365616132373739326638656135d602573c70616c6c65745f6964656e746974793a3a44617461206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6861333165363237333335636235633762d702386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6862373538343730653262376463373837d802386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6862373632303636666338356631393438d902386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6863303639643361393036623066636437da02386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6863306130653734346233653862646133db027770616c6c65745f636f6e7472616374733a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722070616c6c65745f636f6e7472616374733a3a5363686564756c653e3a3a6465636f64653a3a6863336630356437396561363133623233dc02386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6863373162373832383237366363303838dd02386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6863376530396264636637353036363634de02386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6863643332333865303439386236333131df02386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6864323832313030306333376432366536e002386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6864613738363534623466316330353965e102386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6864626232653333663964366537343837e202386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6866633435643532643461343937393632e302396672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a74616b653a3a6832386461633638616133626338393631e402396672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a74616b653a3a6835343632383862373566316635383163e5025c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6839323562306339353930386331613735e60285013c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a43757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a7472616e736665723a3a6864343663333266353861633533633431e7024a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6835343932373162623464663939613461e80293013c70616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e206173206672616d655f737570706f72743a3a7472616974733a3a436f6e7461696e733c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a736f727465645f6d656d626572733a3a6838383335633266313832663030666466e9024270616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a69735f6d656d6265723a3a6838643735333232303465643539303231ea0290013c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a4c6f636b61626c6543757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a657874656e645f6c6f636b3a3a6834623132343665623938396134326233eb023670616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e3a3a6c6f636b733a3a6862303366643032636131623430623863ec023d70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e3a3a7570646174655f6c6f636b733a3a6836613463346231616439316536393666ed025c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6864303533343130383539663065303032ee02483c5b543b20385d206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6832666363313466303830323838336630ef029a013c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a52657365727661626c6543757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a726570617472696174655f72657365727665643a3a6863333161396136356539393537383538f002b2013c6672616d655f73797374656d3a3a4d6f64756c653c543e206173206672616d655f737570706f72743a3a7472616974733a3a53746f7265644d61703c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449642c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e74446174613e3e3a3a7472795f6d75746174655f6578697374733a3a6862616238343766663637326630623339f1023f70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e3a3a63616c6c5f66756e6374696f6e733a3a6866326461336234333831366166653936f2024170616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e3a3a73746f726167655f6d657461646174613a3a6837646666346166316365353262303238f3026e3c70616c6c65745f62616c616e6365733a3a5f5f476574427974655374727563744163636f756e743c542c493e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6836323038326136323863393464373639f4024a70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6863343165313633613436316538663061f5024770616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6835346438633035363837303735643862f6024970616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6836396330346162666638316161386364f702753c70616c6c65745f656c656374696f6e735f70687261676d656e3a3a5f5f47657442797465537472756374566f74696e673c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6865626363316535343431303637353433f8023c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6837383031373637633031366335316135f9025270616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6838313061353662383030333963326362fa029f013c70616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d6f64756c65496444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6865303833336237356336313633386666fb02a3013c70616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5465726d4475726174696f6e44656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6864326263376435386134663365643564fc02a7013c70616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4465736972656452756e6e657273557044656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6866343038326364626630333661633336fd02a5013c70616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a446573697265644d656d6265727344656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6830313564663038333234636630656564fe02fa01616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6e6f64653a3a48616e646c653c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6e6f64653a3a4e6f64655265663c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6e6f64653a3a6d61726b65723a3a4d75742c4b2c562c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6e6f64653a3a6d61726b65723a3a4c6561663e2c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6e6f64653a3a6d61726b65723a3a456467653e3a3a696e736572743a3a6862306530653564613066326339353763ff02fe01616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6e6f64653a3a48616e646c653c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6e6f64653a3a4e6f64655265663c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6e6f64653a3a6d61726b65723a3a4d75742c4b2c562c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6e6f64653a3a6d61726b65723a3a496e7465726e616c3e2c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6e6f64653a3a6d61726b65723a3a456467653e3a3a696e736572743a3a683566643663326365336639623734356380034b616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a566163616e74456e7472793c4b2c563e3a3a696e736572743a3a68393330616266633430343738623461348103613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a686462393761386332663332663562333282034b616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a566163616e74456e7472793c4b2c563e3a3a696e736572743a3a6837653937333561643437646535376431830348616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e3a3a696e736572743a3a6836643136353039383966373231353561840348616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e3a3a696e736572743a3a686632643433303933666533653030626385034c3c70616c6c65745f62616c616e6365733a3a43616c6c3c542c493e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a68386130383931393238383833643463618603543c70616c6c65745f656c656374696f6e735f70687261676d656e3a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a686139666231633135666162666562653987035d3c70616c6c65745f62616c616e6365733a3a43616c6c3c542c493e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a68613035613537306163393530303263358803623c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a68626136396533323639643933633430328903653c70616c6c65745f656c656374696f6e735f70687261676d656e3a3a43616c6c3c543e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a68356432326632396564343834633936378a03393c54206173206672616d655f737570706f72743a3a7472616974733a3a4c656e3e3a3a6c656e3a3a68396633306466656136386663646331328b03393c54206173206672616d655f737570706f72743a3a7472616974733a3a4c656e3e3a3a6c656e3a3a68613034306564333636643737613766338c03b2013c6672616d655f73797374656d3a3a4d6f64756c653c543e206173206672616d655f737570706f72743a3a7472616974733a3a53746f7265644d61703c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449642c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e74446174613e3e3a3a7472795f6d75746174655f6578697374733a3a68303235326339343361363263386331338d03437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a68353335303433356532306162393531398e035270616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a72656d6f76655f616e645f7265706c6163655f6d656d6265723a3a68323036303636626432356466343566348f03613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a683236656435323766326637666531656590036a3c70616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a68343737393833333664393536623737639103456672616d655f737570706f72743a3a7472616974733a3a5369676e6564496d62616c616e63653c422c503e3a3a6d657267653a3a683565373432613166323763623765333592033c70616c6c65745f7574696c6974793a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a683165373139393235373033613539363593033e70616c6c65745f7574696c6974793a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a68366264613134316162616566633165619403437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a68303962653065306334356236326338349503437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a68313632316364613131363533373363309603437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a68326333323665666639333932303766349703437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a68383731393832336466356432353338329803437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a686131346166366162663430333231363999034a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a68366631633135393734643031633335389a03493c70616c6c65745f7574696c6974793a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a68663462306134316331353163626234619b03493c6e6f64655f72756e74696d653a3a43616c6c20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a68333736613635376637383866316639642e323036329c03443c6e6f64655f72756e74696d653a3a43616c6c20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a68333736613635376637383866316639649d03473c6672616d655f73797374656d3a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a68663532646138393065373263323462399e03443c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a68633634343962653363613331313336399f03443c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6864323032313031353031396634303934a0034b3c70616c6c65745f64656d6f63726163793a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6838666336653532613337343966636361a1034e3c70616c6c65745f636f6c6c6563746976653a3a43616c6c3c542c493e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6861623763636361336138303334346538a2034e3c70616c6c65745f6d656d626572736869703a3a43616c6c3c542c493e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6832636337346331373936626566666335a3034a3c70616c6c65745f74726561737572793a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6863623639343032643235386531626236a4034b3c70616c6c65745f636f6e7472616374733a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6834346537393330616533373636613663a503463c70616c6c65745f7375646f3a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6864353065613531666464656538623564a603443c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6836306663313039343964343862333534a703463c70616c6c65745f626162653a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6836623738656336353333316431343666a8034a3c70616c6c65745f6964656e746974793a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6836623362396564656461313531303039a9034b3c70616c6c65745f736f63696574793a3a43616c6c3c542c493e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6831633536343162356636303762326231aa034a3c70616c6c65745f7265636f766572793a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6836336537623530653866326531366634ab035a3c70616c6c65745f7574696c6974793a3a43616c6c3c543e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6832653138653265666336356565663837ac03553c6e6f64655f72756e74696d653a3a43616c6c2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6830386530613933623532393731393261ad034670616c6c65745f7574696c6974793a3a4d6f64756c653c543e3a3a656e737572655f736f727465645f616e645f696e736572743a3a6835383039313964346538363430666266ae03437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6861613162323539663533333232333564af036e6e6f64655f72756e74696d653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f72206e6f64655f72756e74696d653a3a43616c6c3e3a3a656e636f64655f746f3a3a6839326661326535376432653361363236b003706672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a6834353039326334313066366132323361b103463c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6832353936316464316532343531396566b2035f3c70616c6c65745f7574696c6974793a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6863653832363264636461653031313665b3030c436f72655f76657273696f6eb4036b3c73705f72756e74696d653a3a72756e74696d655f737472696e673a3a52756e74696d65537472696e67206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64653a3a6830353936316638653965663866343037b50312436f72655f657865637574655f626c6f636bb6039a0173705f72756e74696d653a3a67656e657269633a3a626c6f636b3a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722073705f72756e74696d653a3a67656e657269633a3a626c6f636b3a3a426c6f636b3c4865616465722c45787472696e7369633e3e3a3a6465636f64653a3a6836633664366533643238323565383166b70384016672616d655f6578656375746976653a3a4578656375746976653c53797374656d2c426c6f636b2c436f6e746578742c556e7369676e656456616c696461746f722c416c6c4d6f64756c65732c434f6e52756e74696d65557067726164653e3a3a696e697469616c697a655f626c6f636b3a3a6838393534336262666334333534303062b8035c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6838636465383435303864653034626362b9033e73705f72756e74696d653a3a67656e657269633a3a656e636f64655f776974685f7665635f7072656669783a3a6836616639306563633236343262396566ba035373705f696f3a3a747269653a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a626c616b65325f3235365f6f7264657265645f726f6f743a3a6838626166303166646138346239643638bb038c016672616d655f6578656375746976653a3a4578656375746976653c53797374656d2c426c6f636b2c436f6e746578742c556e7369676e656456616c696461746f722c416c6c4d6f64756c65732c434f6e52756e74696d65557067726164653e3a3a6170706c795f65787472696e7369635f776974685f6c656e3a3a6837626533313430336232346436353961bc03446672616d655f73797374656d3a3a4d6f64756c653c543e3a3a6e6f74655f66696e69736865645f65787472696e736963733a3a6834663565633735623365366462643935bd03713c285475706c65456c656d656e74302c5475706c65456c656d656e743129206173206672616d655f737570706f72743a3a7472616974733a3a4f6e46696e616c697a653c426c6f636b4e756d6265723e3e3a3a6f6e5f66696e616c697a653a3a6837356431383837323432663037626232be03346672616d655f73797374656d3a3a4d6f64756c653c543e3a3a66696e616c697a653a3a6834306363643339316338633733393866bf03467061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a436f646553656374696f6e3a3a626f646965733a3a6865666236393637346665636463336532c0036f3c73705f72756e74696d653a3a67656e657269633a3a6469676573743a3a4469676573744974656d3c486173683e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64653a3a6861653631333134316431633734656430c103363c5420617320636f72653a3a636f6e766572743a3a496e746f3c553e3e3a3a696e746f3a3a6831653531663063306165653439623266c203303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6832333239626366396430636261636135c30315436f72655f696e697469616c697a655f626c6f636bc403723c73705f72756e74696d653a3a67656e657269633a3a6865616465723a3a4865616465723c4e756d6265722c486173683e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6836353732656635373330626338323535c503114d657461646174615f6d65746164617461c603d9053c6e6f64655f72756e74696d653a3a52756e74696d652061732073705f6170693a3a72756e74696d655f6465636c5f666f725f4d657461646174613a3a4d657461646174613c73705f72756e74696d653a3a67656e657269633a3a626c6f636b3a3a426c6f636b3c73705f72756e74696d653a3a67656e657269633a3a6865616465723a3a4865616465723c7533322c73705f72756e74696d653a3a7472616974733a3a426c616b6554776f3235363e2c73705f72756e74696d653a3a67656e657269633a3a756e636865636b65645f65787472696e7369633a3a556e636865636b656445787472696e7369633c3c70616c6c65745f696e64696365733a3a4d6f64756c653c6e6f64655f72756e74696d653a3a52756e74696d653e2061732073705f72756e74696d653a3a7472616974733a3a5374617469634c6f6f6b75703e3a3a536f757263652c6e6f64655f72756e74696d653a3a43616c6c2c73705f72756e74696d653a3a4d756c74695369676e61747572652c286672616d655f73797374656d3a3a436865636b56657273696f6e3c6e6f64655f72756e74696d653a3a52756e74696d653e2c6672616d655f73797374656d3a3a436865636b47656e657369733c6e6f64655f72756e74696d653a3a52756e74696d653e2c6672616d655f73797374656d3a3a436865636b4572613c6e6f64655f72756e74696d653a3a52756e74696d653e2c6672616d655f73797374656d3a3a436865636b4e6f6e63653c6e6f64655f72756e74696d653a3a52756e74696d653e2c6672616d655f73797374656d3a3a436865636b5765696768743c6e6f64655f72756e74696d653a3a52756e74696d653e2c70616c6c65745f7472616e73616374696f6e5f7061796d656e743a3a4368617267655472616e73616374696f6e5061796d656e743c6e6f64655f72756e74696d653a3a52756e74696d653e293e3e3e3e3a3a6d657461646174613a3a6839373832303465333938323838636637c7031c426c6f636b4275696c6465725f6170706c795f65787472696e736963c8039c013c73705f72756e74696d653a3a67656e657269633a3a756e636865636b65645f65787472696e7369633a3a556e636865636b656445787472696e7369633c416464726573732c43616c6c2c5369676e61747572652c45787472613e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6838633366316637643336313964326631c903aa0173705f72756e74696d653a3a7472616e73616374696f6e5f76616c69646974793a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722073705f72756e74696d653a3a7472616e73616374696f6e5f76616c69646974793a3a5472616e73616374696f6e56616c69646974794572726f723e3a3a656e636f64655f746f3a3a6837616630643436316630373732653336ca031b426c6f636b4275696c6465725f66696e616c697a655f626c6f636bcb035c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6864666365313231316532383232373936cc0320426c6f636b4275696c6465725f696e686572656e745f65787472696e73696373cd036f3c636f72653a3a697465723a3a61646170746572733a3a526573756c745368756e743c492c453e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a7472795f666f6c643a3a6837383030326161646637346638343330ce033a70616c6c65745f74696d657374616d703a3a657874726163745f696e686572656e745f646174613a3a6831316537336434343339363134626430cf03543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6837393561656339316661343637336666d003437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6862316366653033333662363463663133d103366672616d655f73797374656d3a3a4d6f64756c653c543e3a3a626c6f636b5f686173683a3a6834616266626433393131633436333032d2031c426c6f636b4275696c6465725f636865636b5f696e686572656e7473d303453c737472206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64653a3a6866613461623063393161366331636337d40318426c6f636b4275696c6465725f72616e646f6d5f73656564d50390013c70616c6c65745f72616e646f6d6e6573735f636f6c6c6563746976655f666c69703a3a4d6f64756c653c543e206173206672616d655f737570706f72743a3a7472616974733a3a52616e646f6d6e6573733c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a486173683e3e3a3a72616e646f6d3a3a6830663032613736303538393733646663d6032b5461676765645472616e73616374696f6e51756575655f76616c69646174655f7472616e73616374696f6ed7039f013c73705f72756e74696d653a3a67656e657269633a3a756e636865636b65645f65787472696e7369633a3a556e636865636b656445787472696e7369633c416464726573732c43616c6c2c5369676e61747572652c45787472613e2061732073705f72756e74696d653a3a7472616974733a3a436865636b61626c653c4c6f6f6b75703e3e3a3a636865636b3a3a6832323837393033373663643437333663d803653c6e6f64655f72756e74696d653a3a43616c6c206173206672616d655f737570706f72743a3a776569676874733a3a4765744469737061746368496e666f3e3a3a6765745f64697370617463685f696e666f3a3a6834646464643866306463633231393133d9035373705f72756e74696d653a3a7472616e73616374696f6e5f76616c69646974793a3a56616c69645472616e73616374696f6e3a3a636f6d62696e655f776974683a3a6835303633363533356261326534313839da03436672616d655f73797374656d3a3a436865636b5765696768743c543e3a3a636865636b5f626c6f636b5f6c656e6774683a3a6839616436343133613033373137376362db034570616c6c65745f7472616e73616374696f6e5f7061796d656e743a3a4d6f64756c653c543e3a3a636f6d707574655f6665653a3a6866373362323964633264663765616638dc03b2013c6672616d655f73797374656d3a3a4d6f64756c653c543e206173206672616d655f737570706f72743a3a7472616974733a3a53746f7265644d61703c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449642c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e74446174613e3e3a3a7472795f6d75746174655f6578697374733a3a6863313236303339373534623933336233dd036b3c70616c6c65745f696d5f6f6e6c696e653a3a4d6f64756c653c543e2061732073705f72756e74696d653a3a7472616974733a3a56616c6964617465556e7369676e65643e3a3a76616c69646174655f756e7369676e65643a3a6837336534646664383430316138633162de03214f6666636861696e576f726b65724170695f6f6666636861696e5f776f726b6572df0386016672616d655f6578656375746976653a3a4578656375746976653c53797374656d2c426c6f636b2c436f6e746578742c556e7369676e656456616c696461746f722c416c6c4d6f64756c65732c434f6e52756e74696d65557067726164653e3a3a657874726163745f7072655f6469676573743a3a6833633036653934333837323364316438e003366672616d655f73797374656d3a3a4d6f64756c653c543e3a3a696e697469616c697a653a3a6862353039623233376562656265333134e1035173705f696f3a3a63727970746f3a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a737232353531395f7075626c69635f6b6579733a3a6836343533373533326262646661653531e20347636f72653a3a666d743a3a6e756d3a3a3c696d706c20636f72653a3a666d743a3a446562756720666f72207533323e3a3a666d743a3a6831633835623037353066633565353230e303633c636f72653a3a697465723a3a61646170746572733a3a4d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6862353438336361646236356530656662e403583c70616c6c65745f696d5f6f6e6c696e653a3a4f6666636861696e4572723c426c6f636b4e756d6265723e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6863623733323834383634623336613164e5033c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6830336530383365663037633565323135e6034f70616c6c65745f7374616b696e673a3a6f6666636861696e5f656c656374696f6e3a3a636f6d707574655f6f6666636861696e5f656c656374696f6e3a3a6837366430386564363432653765616166e7031e4772616e6470614170695f6772616e6470615f617574686f726974696573e803543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6838616534643735326134636663633836e90315426162654170695f636f6e66696775726174696f6eea031b426162654170695f63757272656e745f65706f63685f7374617274eb0321417574686f72697479446973636f766572794170695f617574686f726974696573ec031d4163636f756e744e6f6e63654170695f6163636f756e745f6e6f6e6365ed035c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6838333634626337663438643432626536ee0311436f6e7472616374734170695f63616c6cef034870616c6c65745f636f6e7472616374733a3a657865633a3a457865637574696f6e436f6e746578743c542c562c4c3e3a3a63616c6c3a3a6830366364393161376464663131303334f003783c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6d6d69743a3a6865373930646264376132643939306532f1033a70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a726573746f72655f746f3a3a6835323066363264363537326337656139f20318436f6e7472616374734170695f6765745f73746f72616765f3035c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6837346439313964636132303135343433f4033470616c6c65745f636f6e7472616374733a3a6368696c645f747269655f696e666f3a3a6832613034653636333861626539363636f5031c436f6e7472616374734170695f72656e745f70726f6a656374696f6ef6033870616c6c65745f636f6e7472616374733a3a72656e743a3a636f6e73696465725f636173653a3a6830303562333937373330646164633432f7033870616c6c65745f636f6e7472616374733a3a72656e743a3a656e6163745f766572646963743a3a6864643361303261343738326136646332f803205472616e73616374696f6e5061796d656e744170695f71756572795f696e666ff9032153657373696f6e4b6579735f67656e65726174655f73657373696f6e5f6b657973fa034e73705f696f3a3a63727970746f3a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a656432353531395f67656e65726174653a3a6861663766653465303739306335326632fb034e73705f696f3a3a63727970746f3a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a737232353531395f67656e65726174653a3a6864343036646464383438353830636663fc031f53657373696f6e4b6579735f6465636f64655f73657373696f6e5f6b657973fd038f0173705f6170706c69636174696f6e5f63727970746f3a3a737232353531393a3a3c696d706c2073705f6170706c69636174696f6e5f63727970746f3a3a7472616974733a3a52756e74696d655075626c696320666f722073705f636f72653a3a737232353531393a3a5075626c69633e3a3a746f5f7261775f7665633a3a6834313030303530383533656362626532fe035c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6831393936653735363032656131383631ff033870616c6c65745f626162653a3a4d6f64756c653c543e3a3a646f5f696e697469616c697a653a3a68633338386661663832363234383361628004a30173705f636f6e73656e7375735f626162653a3a646967657374733a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722073705f636f6e73656e7375735f626162653a3a646967657374733a3a5261775072654469676573743c5652464f75747075742c56524650726f6f663e3e3a3a6465636f64653a3a686130646632326430623236643163656481043c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a68313165336635633266343039316364398204376672616d655f73797374656d3a3a4d6f64756c653c543e3a3a6465706f7369745f6c6f673a3a686630363362653331366338626237333883047d3c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f62616c616e63653a3a686564363866316535633066653734663984047d3c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f73746f726167653a3a683938306661326366633937353864356285047f3c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f636f64655f686173683a3a6833613766373162343832633964306361860481013c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6e74726163745f6578697374733a3a6864313439303833363664313538303233870484013c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f72656e745f616c6c6f77616e63653a3a68623766623738363236663665613963358804b2013c6672616d655f73797374656d3a3a4d6f64756c653c543e206173206672616d655f737570706f72743a3a7472616974733a3a53746f7265644d61703c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449642c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e74446174613e3e3a3a7472795f6d75746174655f6578697374733a3a6865333236306265366637666530353662890496013c70616c6c65745f636f6e7472616374733a3a54726965496446726f6d506172656e74436f756e7465723c543e2061732070616c6c65745f636f6e7472616374733a3a54726965496447656e657261746f723c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a747269655f69643a3a68306430306531353533613839656338638a04437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a68663833616235613935626232353935328b043b70616c6c65745f626162653a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a68373736396466303265633361353862368c046b3c70616c6c65745f626162653a3a5f5f4765744279746553747275637452616e646f6d6e6573733c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68643037353937653665626139643666318d044470616c6c65745f626162653a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a68613465636330363035336538613934648e049a013c70616c6c65745f626162653a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4578706563746564426c6f636b54696d6544656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68663132623135316637333065646564318f0496013c70616c6c65745f626162653a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a45706f63684475726174696f6e44656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6864303939323866636538356432363165900481013c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f62616c616e63653a3a6835346134663936366639613335613333910481013c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f73746f726167653a3a6831333761343332373762393038393930920483013c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f636f64655f686173683a3a6863363330343066363363346238383664930485013c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6e74726163745f6578697374733a3a6861613235386264623031366636323334940488013c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f72656e745f616c6c6f77616e63653a3a683465633732623862343635643365356195047c3c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6d6d69743a3a686139353036663666623136363539363896045c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a683232353165633664623062396134326397045c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a683763613265633161393362616636613198043c70616c6c65745f696e64696365733a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a683730393262316634353134333762346199043e70616c6c65745f696e64696365733a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a68663735376536623033353530613163659a04633c636f72653a3a697465723a3a61646170746572733a3a4d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a666f6c643a3a68333033316564326565666233343036329b044673705f61726974686d657469633a3a68656c706572735f3132386269743a3a6d756c7469706c795f62795f726174696f6e616c3a3a68393031626331333565356638666566329c04533c73705f61726974686d657469633a3a726174696f6e616c3132383a3a526174696f6e616c31323820617320636f72653a3a636d703a3a4f72643e3a3a636d703a3a68616362613234623435383430376330329d04583c73705f61726974686d657469633a3a726174696f6e616c3132383a3a526174696f6e616c31323820617320636f72653a3a636d703a3a5061727469616c45713e3a3a65713a3a68343232666636626366653836633466619e042d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a68396534323465363362383761366161669f047a3c73705f61726974686d657469633a3a7065725f7468696e67733a3a5065725531362061732073705f61726974686d657469633a3a7065725f7468696e67733a3a5065725468696e673e3a3a66726f6d5f726174696f6e616c5f617070726f78696d6174696f6e3a3a6861383037316235323863656163643538a0045273705f696f3a3a6f6666636861696e3a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a7375626d69745f7472616e73616374696f6e3a3a6834363464333661636234303335376461a1043d70616c6c65745f6964656e746974793a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6861396537356666336265643832313831a2043f70616c6c65745f6964656e746974793a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6865616338323362343237373934623033a3042b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a6832393232323238633938316134356636a4044870616c6c65745f6964656e746974793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6839326137653733326333633064323064a5049a013c70616c6c65745f6964656e746974793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d61785265676973747261727344656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6861326337656361656162356462383565a6049b013c70616c6c65745f6964656e746974793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d61785375624163636f756e747344656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6838666537313832346431326331663036a7049e013c70616c6c65745f6964656e746974793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5375624163636f756e744465706f73697444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6838633039343264643061663732613163a80499013c70616c6c65745f6964656e746974793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4669656c644465706f73697444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6863663461663934613235356665303065a90499013c70616c6c65745f6964656e746974793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a42617369634465706f73697444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6864333333633633656637633635306135aa04820170616c6c65745f6964656e746974793a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722070616c6c65745f6964656e746974793a3a4a756467656d656e743c42616c616e63653e3e3a3a656e636f64655f746f3a3a6862343963306633303230306635653635ab047c70616c6c65745f6964656e746974793a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722070616c6c65745f6964656e746974793a3a4964656e74697479496e666f3e3a3a656e636f64655f746f3a3a6832323837376662666234346564353236ac04573c70616c6c65745f6964656e746974793a3a44617461206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64653a3a6837616237303239366439623865346535ad04573c70616c6c65745f6964656e746974793a3a44617461206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6836373039623532623961643239646633ae045170616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e3a3a7365745f62616c616e63653a3a6863386335363437633837386434663335af045170616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e3a3a7365745f73746f726167653a3a6834343931643963656639383037386463b004437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6839646263306437626664393831653038b1045a3c70616c6c65745f696e64696365733a3a43616c6c3c543e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6830326163366530316334613661303063b2044a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6832326565616262356163633664323730b3045b3c70616c6c65745f6964656e746974793a3a43616c6c3c543e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6866633337643032386261626630633739b4043c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6837383037623265343638316565666461b5045c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6865343462623363643664396463353034b6045c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6862313338636132333030313665643536b704603c70616c6c65745f6964656e746974793a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6835383261646132356362633639623135b8042b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a6837356239656266393732333739373237b9043d70616c6c65745f696d5f6f6e6c696e653a3a4d6f64756c653c543e3a3a69735f6f6e6c696e655f6175783a3a6833633636653065386335386366303261ba04706672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a6865393964373537383363333162663138bb044d73705f696f3a3a6f6666636861696e3a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a6e6574776f726b5f73746174653a3a6864363436393861636139303262366232bc044a73705f696f3a3a63727970746f3a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a737232353531395f7369676e3a3a6838643263316630613033363163383862bd04473c70616c6c65745f696d5f6f6e6c696e653a3a43616c6c3c543e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6839636435616364366236316564356130be04373c285431302c5431312920617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6833323134383937343237336366333637bf04303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6830363734343637326239636663623838c00496013c70616c6c65745f696d5f6f6e6c696e653a3a4d6f64756c653c543e2061732070616c6c65745f73657373696f6e3a3a4f6e6553657373696f6e48616e646c65723c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6f6e5f6265666f72655f73657373696f6e5f656e64696e673a3a6862396661323234346664313931633363c104443c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6865653039373465616162386365386134c2045c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6834316463613531376539363937633637c304706672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a6864666564653639646361353935623239c4045c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6833383837656164613662646236373964c504437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6865376337336564626436393965356639c604443c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6835643031373934636661633266383865c7043c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6833333966366463656630356665663331c8044b6672616d655f73797374656d3a3a4d6f64756c653c543e3a3a72656769737465725f65787472615f7765696768745f756e636865636b65643a3a6830363637653030653263383333383865c9045c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6833303063393962386634303565353535ca04693c636f72653a3a697465723a3a61646170746572733a3a46696c7465724d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6866343130663637613761373036356665cb0481016672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a617070656e645f6f725f696e736572743a3a6831343462303635666137353430356262cc04753c285475706c65456c656d656e74302c5475706c65456c656d656e743129206173206672616d655f737570706f72743a3a7472616974733a3a4f6e496e697469616c697a653c426c6f636b4e756d6265723e3e3a3a6f6e5f696e697469616c697a653a3a6865353261323135343036663731653664cd04437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6830363561373534326135373733623533ce04406672616d655f73797374656d3a3a436865636b5765696768743c543e3a3a646f5f7072655f64697370617463683a3a6863646164363235623432616530386333cf045770616c6c65745f7472616e73616374696f6e5f7061796d656e743a3a4d6f64756c653c543e3a3a7765696768745f746f5f6665655f776974685f61646a7573746d656e743a3a6864313735373932323233353063623536d0043770616c6c65745f617574686f72736869703a3a4d6f64756c653c543e3a3a617574686f723a3a6866393463636564386561313039646364d104563c73705f72756e74696d653a3a44697370617463684572726f722061732073705f72756e74696d653a3a7472616974733a3a5072696e7461626c653e3a3a7072696e743a3a6863346566383637626639386531386236d2043e70616c6c65745f696d5f6f6e6c696e653a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6837626466653761376130393937323932d3043f70616c6c65745f696d5f6f6e6c696e653a3a4d6f64756c653c543e3a3a6e6f74655f617574686f72736869703a3a6836383334633136353461333264623062d4044070616c6c65745f696d5f6f6e6c696e653a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6861653831363333396361316265383064d5043e70616c6c65745f74696d657374616d703a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6835393730656335653436363337613935d6044070616c6c65745f74696d657374616d703a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6865353864396564363730396166666565d7044970616c6c65745f74696d657374616d703a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6862336631393833396163353133663035d8049b013c70616c6c65745f74696d657374616d703a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d696e696d756d506572696f6444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6833616533613339373230373764306237d9043c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6834643932316134343239626133323166da048d0170616c6c65745f7363686564756c65723a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722070616c6c65745f7363686564756c65723a3a5363686564756c65643c43616c6c2c426c6f636b4e756d6265723e3e3a3a656e636f64655f746f3a3a6863646237646465323139356636646462db043c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6831306436353761386661656266653430dc04303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6831643133313534366161663930316465dd04303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6832356635323932333764633036323530de044b3c70616c6c65745f696d5f6f6e6c696e653a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6832303562383065666232313537653534df04613c70616c6c65745f696d5f6f6e6c696e653a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6866356637323433663232336634336536e0043a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a6831616635653663383338626233653235e1043b3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f636861723a3a6861643534346239663235663461656264e2043a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f666d743a3a6835366534336430616634633936666337e3043273705f73616e64626f783a3a696d703a3a64697370617463685f7468756e6b3a3a6866376564613431343138656534343638e4047673705f7761736d5f696e746572666163653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722073705f7761736d5f696e746572666163653a3a56616c75653e3a3a6465636f64653a3a6835393366313463636336656639626339e5047973705f7761736d5f696e746572666163653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722073705f7761736d5f696e746572666163653a3a56616c75653e3a3a656e636f64655f746f3a3a6839313534646335623637376664313034e6045273705f73616e64626f783a3a696d703a3a456e7669726f6e6d656e74446566696e6974696f6e4275696c6465723c543e3a3a6164645f686f73745f66756e633a3a6838373336363164663163303463316637e7043f70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a6c61756e63685f65787465726e616c3a3a6836643536353630643663653737303936e8047f70616c6c65745f64656d6f63726163793a3a3c696d706c20636f72653a3a636f6e766572743a3a46726f6d3c70616c6c65745f64656d6f63726163793a3a4572726f723c543e3e20666f722073705f72756e74696d653a3a44697370617463684572726f723e3a3a66726f6d3a3a6835326237626330383633613465643362e9044170616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a696e6a6563745f7265666572656e64756d3a3a6834623037666463353162383939383938ea043d70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a6c61756e63685f7075626c69633a3a6833633034346631383532336235666139eb043b70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a6261636b696e675f666f723a3a6864386130376463356365613739663666ec043c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6863373565363961353434643862303132ed045c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6830353866623530366539396665336136ee045c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6836323630376138623937616561333436ef049f0170616c6c65745f64656d6f63726163793a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722070616c6c65745f64656d6f63726163793a3a507265696d6167655374617475733c4163636f756e7449642c42616c616e63652c426c6f636b4e756d6265723e3e3a3a656e636f64655f746f3a3a6833643935623264323734656539306466f0045c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6865353132616361303662316134313330f104497061726974795f7363616c655f636f6465633a3a656e636f64655f617070656e643a3a657874726163745f6c656e6774685f646174613a3a6831623937383962616439613065656536f204703c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6830626465626632353966633031623962f3047b6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a6465636f64655f6c656e3a3a6833336433396564623631626530643738f4044170616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a646f5f656e6163745f70726f706f73616c3a3a6864633334633535663465646232656166f5045c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6837653263386666386330663931376132f604437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6830313931363539336464323665303865f7043c70616c6c65745f76657374696e673a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6838663561313062313565616238386461f8043e70616c6c65745f76657374696e673a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6839613731373863376632353762646634f9044770616c6c65745f76657374696e673a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6864363630313832323364363538663163fa049c013c70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d696e696d756d4465706f73697444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6839653936343061373563363536663035fb043f70616c6c65745f6f6666656e6365733a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6833306633643931663932353732613065fc043e70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6830343063663230333563633164666362fd044070616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6831663536323832656232656537376239fe046f3c70616c6c65745f64656d6f63726163793a3a5f5f47657442797465537472756374426c61636b6c6973743c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6864306132616435366164656331653433ff046e3c70616c6c65745f64656d6f63726163793a3a5f5f47657442797465537472756374566f74696e674f663c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a686333323734333335646336633331373180053c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a68396131393765386363666230363339338105713c70616c6c65745f64656d6f63726163793a3a5f5f476574427974655374727563745075626c696350726f70733c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a683033343339626338313964326538326282054970616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a68393236393765383731653465663431618305a1013c70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a507265696d616765427974654465706f73697444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a686132326330646635646132663032313884059a013c70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4c61756e6368506572696f6444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68393231633964636166666239653732398505a3013c70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a46617374547261636b566f74696e67506572696f6444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a683639393965326138316466656531623586059d013c70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a456e6163746d656e74506572696f6444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a683965633966363866326532613463643387054070616c6c65745f7363686564756c65723a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a683931643066343566313138646535643488053c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a683165633030613065306137323031356189053970616c6c65745f76657374696e673a3a4d6f64756c653c543e3a3a7570646174655f6c6f636b3a3a68306237323332303437353837333333328a055c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a68353736613565353061386434623762368b055c3c70616c6c65745f64656d6f63726163793a3a43616c6c3c543e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a68303234626133366332633361613636348c0582017061726974795f7363616c655f636f6465633a3a636f6465633a3a696e6e65725f7475706c655f696d706c3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f72202850302c51302c5230293e3a3a656e636f64655f746f3a3a68393135336435643966623834353661618d053870616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a7472795f766f74653a3a68313064326433636461376361613330618e053570616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a70726f78793a3a68323739353238313538613963653139648f055c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a68376562323737656265643432336362659005437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a683433656363366261643662646365333291055c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a683635663434326137303864373762616592055c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a686131373466313939383037313862396593053c70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a7472795f64656c65676174653a3a683038363531333431346631363130326194053e70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a7472795f756e64656c65676174653a3a68306339343637393337616166396437329505776672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a686335346231616266633734653139383896055c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a683638323938316364336131643631353897053f70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a7472795f72656d6f76655f766f74653a3a686565663931356636626466383631656198054a70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a7265647563655f757073747265616d5f64656c65676174696f6e3a3a683064643061373065313139336239386499054a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a68363162616132623433303539393361669a055d3c70616c6c65745f636f6e7472616374733a3a7761736d3a3a5761736d566d2061732070616c6c65745f636f6e7472616374733a3a657865633a3a566d3c543e3e3a3a657865637574653a3a68376233376537336562663732363061359b056a3c70616c6c65745f636f6e7472616374733a3a7761736d3a3a5761736d566d2061732070616c6c65745f636f6e7472616374733a3a657865633a3a566d3c543e3e3a3a657865637574653a3a7b7b636c6f737572657d7d3a3a68383534646339396665386631643930339c0581013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6761733a3a68303335303838633964666332303034319d058d013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f7365745f73746f726167653a3a68656662643636666432363932376636379e058f013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f636c6561725f73746f726167653a3a68626363646632316562636235653533399f058d013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6765745f73746f726167653a3a6837356265373535653466313263373765a0058a013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f7472616e736665723a3a6830643733383935356564303664316230a10586013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f63616c6c3a3a6862313262663739333865353762393637a2058d013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f696e7374616e74696174653a3a6839656562636264333262376438373839a3058b013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f7465726d696e6174653a3a6830373334386163386135373838386364a40588013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f72657475726e3a3a6863363638623230373537623538373562a50588013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f63616c6c65723a3a6865386461323932333434376432393864a60589013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f616464726573733a3a6834373335333764656535303064663730a7058b013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6761735f70726963653a3a6836616461373632366133643864306266a8058a013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6761735f6c6566743a3a6833666430316438366336393639306664a90589013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f62616c616e63653a3a6830336533383862613463396637636132aa0593013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f76616c75655f7472616e736665727265643a3a6834646462653665616561396438313866ab0588013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f72616e646f6d3a3a6835303266313663336230376132646362ac0585013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6e6f773a3a6863353638323331646463336533373936ad0591013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6d696e696d756d5f62616c616e63653a3a6839326561396436653266353635663632ae0593013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f746f6d6273746f6e655f6465706f7369743a3a6839653962666535396261383662303930af058f013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f64697370617463685f63616c6c3a3a6863643336353634643830633133376164b0058c013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f726573746f72655f746f3a3a6838386534336132646530336464623934b1058e013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f736372617463685f73697a653a3a6837303139636333623961353864393633b2058e013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f736372617463685f726561643a3a6835343832623336393563373937303134b3058f013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f736372617463685f77726974653a3a6839633461373430343739393032623836b4058f013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6465706f7369745f6576656e743a3a6866333961343935306630386338323034b50594013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f7365745f72656e745f616c6c6f77616e63653a3a6864306636613538623864636264666338b60590013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f72656e745f616c6c6f77616e63653a3a6838353134653630343839393530346161b70589013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f7072696e746c6e3a3a6862303738623262643435383035343662b8058e013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f626c6f636b5f6e756d6265723a3a6861356662313538373065386461313535b90595013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6765745f72756e74696d655f73746f726167653a3a6830623930616465383335616464646463ba058f013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f686173685f736861325f3235363a3a6866356635646634623262393263656439bb0591013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f686173685f6b656363616b5f3235363a3a6837666539323932666233353837643334bc0591013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f686173685f626c616b65325f3235363a3a6832366432373238613734623064663831bd0591013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f686173685f626c616b65325f3132383a3a6836353664656638373130303166336330be053e70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a6368617267655f6761733a3a6833343264326238626337633764303261bf053370616c6c65745f636f6e7472616374733a3a657865633a3a7472616e736665723a3a6839353065616664303466613631633736c0054f70616c6c65745f636f6e7472616374733a3a657865633a3a457865637574696f6e436f6e746578743c542c562c4c3e3a3a696e7374616e74696174653a3a6837326333393439373130303337383537c1052d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a6833303639646365353332316537326664c2055f3c70616c6c65745f76657374696e673a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6836396637383763643730633564646231c305613c70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6863343035386338336531623237393362c4057c7061726974795f7363616c655f636f6465633a3a636f6465633a3a696e6e65725f7475706c655f696d706c3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f72202851302c5230293e3a3a6465636f64653a3a6837613662633666663530623563616432c505303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6838363134356262326635306231306634c605443c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6866643934383032333264636662306439c705533c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a737065635f657874656e643a3a6863653938353838666331663533653265c805543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6861643939656561356336613366313236c9058b013c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61704974657261746f723c4b2c562c4861736865723e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6835333064343834303262373132633962ca05513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a6830316233366132363737356365623639cb05513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a6864316636633833373835616238313737cc05466e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f6672616d655f73797374656d3a3a6865623161613639353762323132663936cd05486e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f7574696c6974793a3a6863616530373132333564336166616335ce05486e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f696e64696365733a3a6865323739323066323238376263366633cf05496e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f62616c616e6365733a3a6863383661383130666332396536643662d0054a70616c6c65745f7472616e73616374696f6e5f7061796d656e743a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6834666639316130643838646266343337d1055370616c6c65745f7472616e73616374696f6e5f7061796d656e743a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6839333563346561333134323263623932d205486e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f7374616b696e673a3a6864316365643130336365643636363531d305486e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f73657373696f6e3a3a6839333339383162343430633764326435d4054a6e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f64656d6f63726163793a3a6839656639373339613833636639623831d505556e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f636f6c6c6563746976655f496e7374616e6365313a3a6833643664373237376330363634393766d605536e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f656c656374696f6e735f70687261676d656e3a3a6834336130633465666138323766343239d705556e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f6d656d626572736869705f496e7374616e6365313a3a6834656264313639383432376235313532d8054570616c6c65745f66696e616c6974795f747261636b65723a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6866656531656332393265316135633063d9055070616c6c65745f66696e616c6974795f747261636b65723a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6836393634623035643963626363323166da05683c70616c6c65745f66696e616c6974795f747261636b65723a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6835323637386639303932326239343030db05486e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f6772616e6470613a3a6830656631386162363435316532383066dc05496e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f74726561737572793a3a6838386238326464633734636436303838dd054070616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6863363536326163326638616465363566de053e70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6832646562663438626638656135663734df054a6e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f636f6e7472616374733a3a6830643036326139336330303036323732e0054970616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6861376639386461353463316338356335e105613c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6832323661383965343737646336663631e205456e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f7375646f3a3a6865376131336161623435313138323466e3054a6e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f696d5f6f6e6c696e653a3a6864623130613939343133383966393236e405496e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f6f6666656e6365733a3a6861333137626439666532363932363063e505496e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f6964656e746974793a3a6831633965636538353139383065633563e605486e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f736f63696574793a3a6837366239313665353030366435376633e705496e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f7265636f766572793a3a6831396435633835636466346536663032e805486e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f76657374696e673a3a6836303936386161396662336636653962e9054a6e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f7363686564756c65723a3a6863346264306238656532396239353963ea059a013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d617856616c756553697a6544656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6863393438343731653466633666303030eb0596013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d6178446570746844656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6830333864356532323234303632323362ec059d013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a53757263686172676552657761726444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6836343830653436366165336364303937ed059f013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a52656e744465706f7369744f666673657444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6839626530363830656562376135663336ee0599013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a52656e744279746546656544656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6836663961393366386466613437636564ef059f013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a53746f7261676553697a654f666673657444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6838643633303139303332616634633336f005a1013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5369676e6564436c61696d48616e646963617044656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6863346466383466376635316164343366f105723c70616c6c65745f636f6e7472616374733a3a5f5f476574427974655374727563745072697374696e65436f64653c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6839393763623030653134396439313736f205753c70616c6c65745f636f6e7472616374733a3a5f5f4765744279746553747275637443757272656e745363686564756c653c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6866393832333137383262633461326433f3057a70616c6c65745f636f6e7472616374733a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722070616c6c65745f636f6e7472616374733a3a5363686564756c653e3a3a656e636f64655f746f3a3a6832376466393964366137383130313132f405a2013c70616c6c65745f66696e616c6974795f747261636b65723a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5265706f72744c6174656e637944656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6833393932333966643833396664313862f5059f013c70616c6c65745f66696e616c6974795f747261636b65723a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a57696e646f7753697a6544656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6862306365323463633437653563363365f605aa013c70616c6c65745f7472616e73616374696f6e5f7061796d656e743a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5472616e73616374696f6e4279746546656544656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6862656437356130663137626439343838f705a40170616c6c65745f636f6e7472616374733a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722070616c6c65745f636f6e7472616374733a3a526177416c697665436f6e7472616374496e666f3c436f6465486173682c42616c616e63652c426c6f636b4e756d6265723e3e3a3a656e636f64655f746f3a3a6834393036313261313163303935356662f8054a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6830343339333663613334336566363630f905ac013c73705f72756e74696d653a3a67656e657269633a3a756e636865636b65645f65787472696e7369633a3a556e636865636b656445787472696e7369633c416464726573732c43616c6c2c5369676e61747572652c45787472613e2061732073705f72756e74696d653a3a7472616974733a3a436865636b61626c653c4c6f6f6b75703e3e3a3a636865636b3a3a7b7b636c6f737572657d7d3a3a6835313732306465363738346439346362fa056073705f696f3a3a63727970746f3a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a736563703235366b315f65636473615f7265636f7665725f636f6d707265737365643a3a6830303331353463306265636239363333fb05713c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163745265663c7536343e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6834343239616463383933393563666663fc057d3c70616c6c65745f696e64696365733a3a616464726573733a3a416464726573733c4163636f756e7449642c4163636f756e74496e6465783e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6863303838393935643661633831383431fd05920170616c6c65745f64656d6f63726163793a3a766f74653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722070616c6c65745f64656d6f63726163793a3a766f74653a3a4163636f756e74566f74653c42616c616e63653e3e3a3a656e636f64655f746f3a3a6865666438373135663161313033393764fe057d70616c6c65745f636f6c6c6563746976653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722070616c6c65745f636f6c6c6563746976653a3a43616c6c3c542c493e3e3a3a656e636f64655f746f3a3a6833383035363664353437343365656365ff053f7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64655f746f3a3a6831303138393062613431346139333432800668636f72653a3a6f70733a3a66756e6374696f6e3a3a696d706c733a3a3c696d706c20636f72653a3a6f70733a3a66756e6374696f6e3a3a466e4d75743c413e20666f7220266d757420463e3a3a63616c6c5f6d75743a3a68616431343631393831616133613130348106573c49642061732073705f72756e74696d653a3a7472616974733a3a4163636f756e744964436f6e76657273696f6e3c543e3e3a3a696e746f5f7375625f6163636f756e743a3a686563316364626431313036666232653882066f6e6f64655f72756e74696d653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f72206e6f64655f72756e74696d653a3a4576656e743e3a3a656e636f64655f746f3a3a686636653666393138643662376334356183068e0170616c6c65745f636f6c6c6563746976653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722070616c6c65745f636f6c6c6563746976653a3a5261774576656e743c486173682c4163636f756e7449642c493e3e3a3a656e636f64655f746f3a3a68326331303235313933333662396166628406763c70616c6c65745f617574686f726974795f646973636f766572793a3a43616c6c3c543e206173206672616d655f737570706f72743a3a776569676874733a3a4765744469737061746368496e666f3e3a3a6765745f64697370617463685f696e666f3a3a68376239316539663635616365623730398506583c6672616d655f73797374656d3a3a43616c6c3c543e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a686631356263383935616364623033363486065d3c70616c6c65745f617574686f72736869703a3a43616c6c3c543e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a683365336433353465333864363733333187065a3c70616c6c65745f73657373696f6e3a3a43616c6c3c543e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a683361336639313562353663343735356388065f3c70616c6c65745f636f6c6c6563746976653a3a43616c6c3c542c493e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a683131393766356464313431393763363989065f3c70616c6c65745f636f6c6c6563746976653a3a43616c6c3c542c493e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a68363561363031306463626432333664398a065f3c70616c6c65745f6d656d626572736869703a3a43616c6c3c542c493e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a68333831376537613764316438393663348b065b3c70616c6c65745f74726561737572793a3a43616c6c3c543e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a68646136656437623533653762383937338c064470616c6c65745f636f6e7472616374733a3a7761736d3a3a707265706172653a3a707265706172655f636f6e74726163743a3a68306562636136353464356463346135368d064970616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a657865637574655f7761736d3a3a7b7b636c6f737572657d7d3a3a68613037633433343761656339663165378e06573c70616c6c65745f7375646f3a3a43616c6c3c543e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a68656235333666653835313961623535398f065c3c70616c6c65745f736f63696574793a3a43616c6c3c542c493e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a683837643638326638366266643433353990065b3c70616c6c65745f7265636f766572793a3a43616c6c3c543e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a683737626163353439376530613934346491066b3c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c7536343e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a686435323433616462323264653362616692067a3c70616c6c65745f696e64696365733a3a616464726573733a3a416464726573733c4163636f756e7449642c4163636f756e74496e6465783e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a683334613364393661333031323938636293067a70616c6c65745f636f6c6c6563746976653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722070616c6c65745f636f6c6c6563746976653a3a43616c6c3c542c493e3e3a3a6465636f64653a3a686464386233316238633161316437383894066c70616c6c65745f7375646f3a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722070616c6c65745f7375646f3a3a43616c6c3c543e3e3a3a6465636f64653a3a686665366230643061623361653539363295067470616c6c65745f7265636f766572793a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722070616c6c65745f7265636f766572793a3a43616c6c3c543e3e3a3a6465636f64653a3a68343130636536643031343038393037649606437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6830383438343261386137346565316564970630636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a68646563306531626466306138343965312e3130373098063a6672616d655f73797374656d3a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a683831376537383834613661633166386599063c6672616d655f73797374656d3a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a68336531316630613964306364333663369a06703c6672616d655f73797374656d3a3a5f5f47657442797465537472756374457865637574696f6e50686173653c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68323138303262393830623333346530639b06703c6672616d655f73797374656d3a3a5f5f4765744279746553747275637445787472696e73696373526f6f743c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68333131373865326139303164306635309c06693c6672616d655f73797374656d3a3a5f5f476574427974655374727563744163636f756e743c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68386561313265336264626535636137369d06456672616d655f73797374656d3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a68626466626630333830376631616636319e069c013c6672616d655f73797374656d3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d6178696d756d426c6f636b4c656e67746844656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68303265663366653630333561346535669f069d013c6672616d655f73797374656d3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a45787472696e7369634261736557656967687444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6835623934353064346537323130363635a0069e013c6672616d655f73797374656d3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a426c6f636b457865637574696f6e57656967687444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6839613765386561316361323764343865a10692013c6672616d655f73797374656d3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a446257656967687444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6866653034303734613637623134663162a2069c013c6672616d655f73797374656d3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d6178696d756d426c6f636b57656967687444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6832663333303361336535396365363436a3063b70616c6c65745f636f6e7472616374733a3a7761736d3a3a636f64655f63616368653a3a6c6f61643a3a6831393939343334323732646361353233a406aa0170616c6c65745f64656d6f63726163793a3a74797065733a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722070616c6c65745f64656d6f63726163793a3a74797065733a3a5265666572656e64756d5374617475733c426c6f636b4e756d6265722c486173682c42616c616e63653e3e3a3a656e636f64655f746f3a3a6862393137323034313462313038366635a5064170616c6c65745f6d656d626572736869703a3a4d6f64756c653c542c493e3a3a63616c6c5f66756e6374696f6e733a3a6866323964663330623038633836633037a6064370616c6c65745f6d656d626572736869703a3a4d6f64756c653c542c493e3a3a73746f726167655f6d657461646174613a3a6835646331333063393561653063356366a706437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6836633466633039653364333864663661a8064a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6835613261613431373162653338663437a9065d3c6672616d655f73797374656d3a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6833643662316337306335303231333962aa0699013c70616c6c65745f636f6c6c6563746976653a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a4368616e67654d656d626572733c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6368616e67655f6d656d626572735f736f727465643a3a6830353935366365616662323934356336ab068d013c70616c6c65745f636f6c6c6563746976653a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a4368616e67654d656d626572733c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a7365745f7072696d653a3a6838336566366439663836303137343563ac062b616c6c6f633a3a736c6963653a3a6d657267655f736f72743a3a6833636639313337393965633965353439ad064b6672616d655f737570706f72743a3a7472616974733a3a4368616e67654d656d626572733a3a7365745f6d656d626572735f736f727465643a3a6839383135333962646438623262626161ae0668636f72653a3a6f70733a3a66756e6374696f6e3a3a696d706c733a3a3c696d706c20636f72653a3a6f70733a3a66756e6374696f6e3a3a466e4d75743c413e20666f7220266d757420463e3a3a63616c6c5f6d75743a3a6862356630623138363637326365383565af062d70616c6c65745f736f63696574793a3a7069636b5f7573697a653a3a6837343739633461336232356230643737b0063b70616c6c65745f736f63696574793a3a4d6f64756c653c542c493e3a3a62756d705f7061796f75743a3a6839386439353436356264363863616235b1063c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6866373338333839346538386334323162b206706672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a6838363237653065643430373430393730b3065c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6863353830363663306264623464396537b4063e70616c6c65745f736f63696574793a3a4d6f64756c653c542c493e3a3a73757370656e645f6d656d6265723a3a6866616665343765383366306564653932b5065c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6831346538303361656533666439616162b606673c636f72653a3a697465723a3a61646170746572733a3a4d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a7472795f666f6c643a3a6832316461383965366161383535393933b706753c285475706c65456c656d656e74302c5475706c65456c656d656e743129206173206672616d655f737570706f72743a3a7472616974733a3a4f6e496e697469616c697a653c426c6f636b4e756d6265723e3e3a3a6f6e5f696e697469616c697a653a3a6830333761643364346366353234343365b8065c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6863346639373934393861633137303563b9065c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6834373166333530323666396361386231ba065c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6837313634653061663836396463356234bb063970616c6c65745f7375646f3a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6862643838643265303762666533626239bc063b70616c6c65745f7375646f3a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6866323765373566346433356638666136bd06643c70616c6c65745f7375646f3a3a5f5f476574427974655374727563744b65793c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6835666533643339363864366535653732be063e70616c6c65745f736f63696574793a3a4d6f64756c653c542c493e3a3a63616c6c5f66756e6374696f6e733a3a6838626439623466356662663865626466bf064070616c6c65745f736f63696574793a3a4d6f64756c653c542c493e3a3a73746f726167655f6d657461646174613a3a6831396166623964653934306131636366c0064970616c6c65745f736f63696574793a3a4d6f64756c653c542c493e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6833323064366162653830343462633962c10698013c70616c6c65745f736f63696574793a3a4d6f64756c653c542c493e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d6f64756c65496444656661756c74427974654765747465723c542c493e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6834346566393263616134313163623830c2069e013c70616c6c65745f736f63696574793a3a4d6f64756c653c542c493e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a526f746174696f6e506572696f6444656661756c74427974654765747465723c542c493e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6837353731653665353963383161313438c3069b013c70616c6c65745f736f63696574793a3a4d6f64756c653c542c493e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a506572696f645370656e6444656661756c74427974654765747465723c542c493e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6839616536316237323166633131323063c4069a013c70616c6c65745f736f63696574793a3a4d6f64756c653c542c493e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d6178537472696b657344656661756c74427974654765747465723c542c493e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6831626131666433373163303130343862c5063d70616c6c65745f74726561737572793a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6834316666376337643464373064633863c6063f70616c6c65745f74726561737572793a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6835623335363464653439663666616133c7064870616c6c65745f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6831303639633234303865653738333566c80695013c70616c6c65745f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d6f64756c65496444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6839363964343463333261636534356236c9069a013c70616c6c65745f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a54697046696e6465727346656544656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6863383661336631343061643137663666ca0698013c70616c6c65745f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5370656e64506572696f6444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6838343566613030653932383065336130cb0691013c70616c6c65745f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4275726e44656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6837313762333438363361383631316565cc0699013c70616c6c65745f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a50726f706f73616c426f6e6444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6862373065636235383833306666313033cd06437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6835383338386439623264613665653565ce0668636f72653a3a6f70733a3a66756e6374696f6e3a3a696d706c733a3a3c696d706c20636f72653a3a6f70733a3a66756e6374696f6e3a3a466e4d75743c413e20666f7220266d757420463e3a3a63616c6c5f6d75743a3a6837326264323932386338376534363531cf065c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6833373163313531376437393539666637d0065c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6832323739653231343262613366333463d106493c6e6f64655f72756e74696d653a3a43616c6c20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a68333736613635376637383866316639642e31353034d2065c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6865653138306264333033636130313663d3065c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6866616135386431363235396463666462d4065c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6866306235363637663762346264343139d5065c3c70616c6c65745f7375646f3a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6831376166616136333265626637393833d6063770616c6c65745f736f63696574793a3a4d6f64756c653c542c493e3a3a7075745f6269643a3a6831643330373763313363393765653438d706456672616d655f737570706f72743a3a7472616974733a3a456e737572654f726967696e3a3a656e737572655f6f726967696e3a3a6831663836393939653965313464616335d8063a70616c6c65745f736f63696574793a3a4d6f64756c653c542c493e3a3a6164645f6d656d6265723a3a6861333839393863343961623430386131d906603c70616c6c65745f74726561737572793a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6864336431366161363130356134326138da06613c70616c6c65745f736f63696574793a3a4d6f64756c653c542c493e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6864363964616136336130306665386264db063c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6834653362623736613863613666363331dc066b3c73705f61726974686d657469633a3a66697865643132383a3a46697865643132382061732073705f61726974686d657469633a3a7472616974733a3a53617475726174696e673e3a3a73617475726174696e675f6d756c3a3a6831613530653032346332353132376262dd065c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6832613534656366653262383037666630de06776672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a6837346164333837356264353232303437df063d70616c6c65745f6772616e6470613a3a4d6f64756c653c543e3a3a7363686564756c655f6368616e67653a3a6866646636343030336636613135643862e0063c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6862616535666330343739363465313432e106683c636f72653a3a697465723a3a61646170746572733a3a4d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a73697a655f68696e743a3a6831396666356430383165346638376231e206633c636f72653a3a697465723a3a61646170746572733a3a4d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6835383638636236336632353930666135e3063e636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723a3a6e74683a3a6835326166653137346365323438663833e4063c70616c6c65745f6772616e6470613a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6832306435616365333761663234623235e5063e70616c6c65745f6772616e6470613a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6832396166353464643230343034646563e606703c70616c6c65745f6772616e6470613a3a5f5f4765744279746553747275637443757272656e7453657449643c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6838376431323432303135393731343235e7066b3c70616c6c65745f6772616e6470613a3a5f5f476574427974655374727563745374616c6c65643c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6831376438303138616533323166373233e806693c70616c6c65745f6772616e6470613a3a5f5f4765744279746553747275637453746174653c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6832363230386139336637396338633139e9063c70616c6c65745f73657373696f6e3a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6863656665363931333838306262303962ea063e70616c6c65745f73657373696f6e3a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6830373865323861366264386533333737eb06703c70616c6c65745f73657373696f6e3a3a5f5f4765744279746553747275637443757272656e74496e6465783c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6865336438313432316530386163313232ec062b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a6839343863336665383135653764663132ed064770616c6c65745f636f6e7472616374733a3a7761736d3a3a707265706172653a3a436f6e74726163744d6f64756c653a3a6e65773a3a6861623435626538366235333337643233ee0648616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e3a3a696e736572743a3a6866623430333137376534626538373836ef063c7061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a66726f6d5f6d6f64756c653a3a6866333834373962663335336136613366f006537061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a4d6f64756c654275696c6465723c463e3a3a7265736f6c76655f747970655f7265663a3a6834633266623438353162383736646366f106a9017061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a3c696d706c20636f72653a3a636f6e766572743a3a46726f6d3c7061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a4d6f64756c6553636166666f6c643e20666f72207061726974795f7761736d3a3a656c656d656e74733a3a6d6f64756c653a3a4d6f64756c653e3a3a66726f6d3a3a6835306361373739666538313464623463f2062d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a6834313530386166653865623432633038f306507061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a4d6f64756c654275696c6465723c463e3a3a707573685f66756e6374696f6e3a3a6866363462363133383937383334613137f4062b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a6833616534653964353339636535333539f5063c707761736d5f7574696c733a3a737461636b5f6865696768743a3a696e6a6563745f6c696d697465723a3a6839636130333231656531386331363338f6066b3c7061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a53656374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6862313134326534323564636135643531f7065c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6865326666353434643965303731393036f8065f3c70616c6c65745f6772616e6470613a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6837663863363935396266643331333939f9065f3c70616c6c65745f73657373696f6e3a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6835373864323439636139613137316632fa063f70616c6c65745f617574686f72736869703a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6832363535616164383839393866646332fb064170616c6c65745f617574686f72736869703a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6862366162333363643165613139343731fc0634636f72653a3a736c6963653a3a736f72743a3a627265616b5f7061747465726e733a3a6835363762363965366331393861366138fd062e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a6862383736626461613861633862333565fe063c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a6832393836656661313337343830313433ff0634636f72653a3a736c6963653a3a736f72743a3a627265616b5f7061747465726e733a3a686138323232383231313635343238376680073f636f72653a3a736c6963653a3a736f72743a3a63686f6f73655f7069766f743a3a7b7b636c6f737572657d7d3a3a683738333761396232663631653834326481072e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a686362653437326364636564643931663782073c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a6831643439353266326632616633653931830730636f72653a3a736c6963653a3a736f72743a3a73686966745f7461696c3a3a686562373833323164356566366339326284073b636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a7b7b636c6f737572657d7d3a3a6839663264373835626337393261303131850734636f72653a3a736c6963653a3a736f72743a3a627265616b5f7061747465726e733a3a683566333032363664303130323665396486072e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a683263353261363266333433633333343987073c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a68373133646261306637393639363532668807623c70616c6c65745f617574686f72736869703a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a68616432623466393161303466386438658907753c70616c6c65745f72616e646f6d6e6573735f636f6c6c6563746976655f666c69703a3a43616c6c3c543e206173206672616d655f737570706f72743a3a7472616974733a3a47657443616c6c4e616d653e3a3a6765745f63616c6c5f6e616d65733a3a68323961313231653735316234333562318a075c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a68643034313164373637326466303531658b074a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a68383632383539636661633837343062328c075c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a68613735376630303463336164346130378d073d70616c6c65745f7265636f766572793a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a68623832396330383263663265353362628e073f70616c6c65745f7265636f766572793a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a68303165333565646537383863616465628f074170616c6c65745f636f6c6c6563746976653a3a4d6f64756c653c542c493e3a3a63616c6c5f66756e6374696f6e733a3a683464613663376338666466336334666290074370616c6c65745f636f6c6c6563746976653a3a4d6f64756c653c542c493e3a3a73746f726167655f6d657461646174613a3a683033613166343366313736636537356691074370616c6c65745f636f6c6c6563746976653a3a4d6f64756c653c542c493e3a3a73746f726167655f6d657461646174613a3a68663934633434326563663936303038619207437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a683536663833303332356336626564383693075170616c6c65745f72616e646f6d6e6573735f636f6c6c6563746976655f666c69703a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a683535303335613465326161353865656494074a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a683534323939643736623963323661616595075c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a686263376264306561336335376635623796075c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a68626236373865393432336631613237339707706672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a68613234653662393932343462623763629807603c70616c6c65745f7265636f766572793a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a683533643035366435643235326332366399075c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a68623435343038346265653437316436649a075c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a68643535393733393936323038653838659b074470616c6c65745f636f6c6c6563746976653a3a4d6f64756c653c542c493e3a3a66696e616c697a655f70726f706f73616c3a3a68616436343066333133306630313965359c075c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a68663838336661643664393038326338389d075c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a68356535616238393063626561343132399e075c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a68626662363364353833396563376539619f074470616c6c65745f636f6c6c6563746976653a3a4d6f64756c653c542c493e3a3a66696e616c697a655f70726f706f73616c3a3a6866643633623434313664643633303236a0075c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6861663736336438386137366332316438a107643c70616c6c65745f636f6c6c6563746976653a3a4d6f64756c653c542c493e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6831343061333461373132356364386363a207683c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e697445787072206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6834633439393331653735616331303138a3076b3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6864356135626266333165343636323863a4077d3c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a436f756e7465644c6973745772697465723c492c543e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6831666265366561303230383136373939a5076f3c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a566172496e743332206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6862386538363632373939653530373036a6076f3c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a566172496e743634206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6831363563383135396232653962303266a7076c3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e697445787072206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6837303733363332303830643532303037a8076f3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6863656638303132636264353065663931a90737616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6865643330346464376366633233646363aa07443c7061726974795f7761736d3a3a696f3a3a4572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6830363338666230393435646262316335ab07793c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a436f756e7465644c6973743c543e206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6862363633343636326632653739666337ac076b3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6833326532316261643239303066363766ad0786017061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a3c696d706c207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a6520666f7220616c6c6f633a3a737472696e673a3a537472696e673e3a3a646573657269616c697a653a3a6863353961393931616461356430623731ae07323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6834666334636132316331623933643033af07783c7061726974795f7761736d3a3a656c656d656e74733a3a696d706f72745f656e7472793a3a526573697a61626c654c696d697473206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6832643663653261356166653563383933b0077c3c7061726974795f7761736d3a3a656c656d656e74733a3a696d706f72745f656e7472793a3a526573697a61626c654c696d697473206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6838626232643362346332336531633565b1076f3c7061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a53656374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6837663765346430383832396631323139b207463c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6833376132336136316462616631363131b307463c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6863643738643132376462383834626331b407463c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6834663939323932346130383535613964b5074f7761736d695f76616c69646174696f6e3a3a636f6e746578743a3a4d6f64756c65436f6e746578744275696c6465723a3a707573685f676c6f62616c3a3a6862636338656463363736323264336163b607587761736d695f76616c69646174696f6e3a3a636f6e746578743a3a4d6f64756c65436f6e746578744275696c6465723a3a707573685f66756e635f747970655f696e6465783a3a6861356466303736306130303135376138b707397761736d695f76616c69646174696f6e3a3a76616c69646174655f6d656d6f72795f747970653a3a6831383633306138366563393738353763b807347761736d695f76616c69646174696f6e3a3a657870725f636f6e73745f747970653a3a6833613736663931623637613733323066b907553c7061726974795f7761736d3a3a656c656d656e74733a3a74797065733a3a56616c75655479706520617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6861643864386337663861313638323138ba0737616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6839613162383130373666393532313831bb074a7761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a737465703a3a6837376339326138323465313365383937bc07473c7761736d695f76616c69646174696f6e3a3a4572726f7220617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6864656161653436366361623262613537bd07303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6830613238336532663738663661326566be072d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a6831363439613438666466323361333234bf07457061726974795f7761736d3a3a656c656d656e74733a3a7365676d656e743a3a446174615365676d656e743a3a76616c75653a3a6866626639333864636633313437393639c007743c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a56617255696e743332206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6833623230373765376464326631363864c107713c7061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a437573746f6d53656374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6864663763623061633039343731666132c207713c7061726974795f7761736d3a3a656c656d656e74733a3a696e6465785f6d61703a3a496e6465784d61703c543e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6864666232373762626563613239623830c3074b3c616c6c6f633a3a7665633a3a496e746f497465723c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6865633837386535616238626531386461c4074b3c616c6c6f633a3a7665633a3a496e746f497465723c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6865656338373534646334383636656137c5074b3c616c6c6f633a3a7665633a3a496e746f497465723c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6839313737336537633930356339383138c6074b3c616c6c6f633a3a7665633a3a496e746f497465723c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6833333565616231613531386161623564c707457061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a53656374696f6e5265616465723a3a6e65773a3a6832623264323232373937343937323061c80734636f72653a3a736c6963653a3a736f72743a3a627265616b5f7061747465726e733a3a6836343538633738383030373433303233c9072e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a6831306338313934323835623434626230ca073c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a6864613432613230353866666131383664cb073b636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a7b7b636c6f737572657d7d3a3a6835383437313839323762303531653533cc07513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a6832663135653939656239653139333630cd07553c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6832303532316635393734663134313935ce07303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6863383639356162343734343836336363cf07303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6864613136343061353937346565313763d007303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6830353832373464653465663439383937d107303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6865396662333236613732333063383332d207553c7061726974795f7761736d3a3a656c656d656e74733a3a74797065733a3a426c6f636b5479706520617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6837323362653966316562343863383163d307303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6835366339366664633833326565393861d407303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6835666561393361383663313330373437d507303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6866636266616465653635666130653233d607483c616c6c6f633a3a626f7865643a3a426f783c5b545d3e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6863633537623165633463306466373734d707593c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6831323935353262336336633161383561d807303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6863373464613163386662353263386639d9072e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a6863663136636133313038386537343636da073c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a6831313032373164326234386463616666db0741707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a636f6d707574653a3a6837656330646464396561363763366134dc075a3c707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a4672616d6520617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6831643937376433336462393035613166dd0746707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a537461636b3a3a6672616d653a3a6831636263656662616631333631356230de07453c636f72653a3a6f7074696f6e3a3a4f7074696f6e3c543e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6864626634366461626130636234616438df074b707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a537461636b3a3a706f705f76616c7565733a3a6863356261643934666164326137633337e0073f707761736d5f7574696c733a3a737461636b5f6865696768743a3a7265736f6c76655f66756e635f747970653a3a6835623034396663666265376561646530e107613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6835373163636462353465633063306339e207303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6834373738326234376365343162386331e30733636f72653a3a6f7074696f6e3a3a4f7074696f6e3c26543e3a3a636c6f6e65643a3a6833623861386631386663366664343632e40740707761736d5f7574696c733a3a737461636b5f6865696768743a3a636f6d707574655f737461636b5f636f73743a3a6861323533626530386134336531623837e507323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6837613135656265343936356665396133e6073a73705f61726974686d657469633a3a62696775696e743a3a42696755696e743a3a6c73747269703a3a6836646436653963623432323733363663e7073773705f61726974686d657469633a3a62696775696e743a3a42696755696e743a3a6164643a3a6830316434306537663531376362383139e8073773705f61726974686d657469633a3a62696775696e743a3a42696755696e743a3a6d756c3a3a6866643130333939633138306330393161e9074473705f61726974686d657469633a3a62696775696e743a3a42696755696e743a3a6469763a3a7b7b636c6f737572657d7d3a3a6866383462626664386539613033646631ea074b3c73705f61726974686d657469633a3a62696775696e743a3a42696755696e7420617320636f72653a3a636d703a3a4f72643e3a3a636d703a3a6834343461643533633863373732383630eb07303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6837333938323135383866653231386330ec07513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a6861616431376235343262386136333034ed07413c73705f696e686572656e74733a3a4572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6866646363643030363831623962623332ee07323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6834386262343837633064373131326537ef074273705f696f3a3a6c6f6767696e673a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a6c6f673a3a6866343962313237633262386461396133f007573c73705f72756e74696d653a3a72756e74696d655f737472696e673a3a52756e74696d65537472696e6720617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6839343732383631363335666331333066f107473c73705f72756e74696d653a3a44697370617463684572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6839393631343466363366333061303337f207347761736d695f76616c69646174696f6e3a3a66756e633a3a706f705f76616c75653a3a6838613630623536373166386263396664f307347761736d695f76616c69646174696f6e3a3a66756e633a3a706f705f6c6162656c3a3a6865333162373732616530303563363736f407347761736d695f76616c69646174696f6e3a3a66756e633a3a7465655f76616c75653a3a6837646138326332343962306562633331f507407761736d695f76616c69646174696f6e3a3a7574696c3a3a4c6f63616c733a3a747970655f6f665f6c6f63616c3a3a6838636138323766646134356339313330f607543c7761736d695f76616c69646174696f6e3a3a66756e633a3a537461636b56616c75655479706520617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6835353532326133316636303964363937f707537761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f6c6f61643a3a6830376132393432636464306365343338f807547761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f73746f72653a3a6831323764353062613862376333643439f907547761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f72656c6f703a3a6861343966626334643365306136373739fa07547761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f62696e6f703a3a6838656230653936636235643135343234fb073b616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a616c6c6f636174655f696e3a3a6831363031666261373561616639383461fc0737616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6830313230663136306336333962303561fd073b636f72653a3a736c6963653a3a3c696d706c205b545d3e3a3a636f70795f66726f6d5f736c6963653a3a6862656366363865633237636235336665fe072b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a6861626461346364333962343639396563ff07303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68323235343564613034363464666239398008453c616c6c6f633a3a737472696e673a3a537472696e6720617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a683430363536353032386339373630633381084c3c7761736d695f76616c69646174696f6e3a3a737461636b3a3a4572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6861313263303261643833303862306162820838636f6d70696c65725f6275696c74696e733a3a696e743a3a6d756c3a3a5f5f6d756c7469333a3a6839373632626331636361303166383364830839636f6d70696c65725f6275696c74696e733a3a696e743a3a6d756c3a3a5f5f6d756c6f7469343a3a68323735656632666138626166616237318408085f5f6d756c7469338508095f5f6d756c6f7469348608095f5f756d6f6474693387082b636f6d70696c65725f6275696c74696e733a3a61626f72743a3a6837373662356362633663393964313163880839636f6d70696c65725f6275696c74696e733a3a696e743a3a736469763a3a5f5f6469767469333a3a68353431303861623133616630373236328908463c69363420617320636f6d70696c65725f6275696c74696e733a3a696e743a3a496e743e3a3a66726f6d5f756e7369676e65643a3a68623233353336366166363766393733388a08453c75363420617320636f6d70696c65725f6275696c74696e733a3a696e743a3a496e743e3a3a61626f7274696e675f6469763a3a68353339326136663336363336656339308b08453c75363420617320636f6d70696c65725f6275696c74696e733a3a696e743a3a496e743e3a3a61626f7274696e675f72656d3a3a68636165613162386434353561363334398c08453c69363420617320636f6d70696c65725f6275696c74696e733a3a696e743a3a496e743e3a3a7772617070696e675f6164643a3a68356438303838653933313037343366398d08453c69363420617320636f6d70696c65725f6275696c74696e733a3a696e743a3a496e743e3a3a7772617070696e675f6d756c3a3a68616366346631393365666533333565668e08473c6931323820617320636f6d70696c65725f6275696c74696e733a3a696e743a3a496e743e3a3a66726f6d5f756e7369676e65643a3a68396361396438643435306530333130398f08463c7531323820617320636f6d70696c65725f6275696c74696e733a3a696e743a3a496e743e3a3a61626f7274696e675f6469763a3a68646461633866376335323365633534389008433c6931323820617320636f6d70696c65725f6275696c74696e733a3a696e743a3a496e743e3a3a6d61785f76616c75653a3a68313965366462646366643839343564339108433c6931323820617320636f6d70696c65725f6275696c74696e733a3a696e743a3a496e743e3a3a6d696e5f76616c75653a3a68396138626366656461353838656165339208463c6931323820617320636f6d70696c65725f6275696c74696e733a3a696e743a3a496e743e3a3a7772617070696e675f6d756c3a3a68663762643232353766633537633430369308463c6931323820617320636f6d70696c65725f6275696c74696e733a3a696e743a3a496e743e3a3a7772617070696e675f7375623a3a68323165393061666464326361353338329408463c6931323820617320636f6d70696c65725f6275696c74696e733a3a696e743a3a496e743e3a3a61626f7274696e675f6469763a3a68313361346530633765653064303163399508423c6931323820617320636f6d70696c65725f6275696c74696e733a3a696e743a3a4c61726765496e743e3a3a6c6f773a3a68633539396133336534633865356161339608433c6931323820617320636f6d70696c65725f6275696c74696e733a3a696e743a3a4c61726765496e743e3a3a686967683a3a68666365633135386664353336366161629708493c6931323820617320636f6d70696c65725f6275696c74696e733a3a696e743a3a4c61726765496e743e3a3a66726f6d5f70617274733a3a68646135326234366661633734663438379808095f5f7564697674693399083a636f6d70696c65725f6275696c74696e733a3a696e743a3a756469763a3a5f5f756469767469333a3a68316538396139356663646439323031339a083d636f6d70696c65725f6275696c74696e733a3a696e743a3a756469763a3a5f5f756469766d6f647469343a3a68633262343431643430303733343161669b083a636f6d70696c65725f6275696c74696e733a3a696e743a3a756469763a3a5f5f756d6f647469333a3a68653963366462306266373836386263319c08085f5f6469767469339d08066d656d6370799e08076d656d6d6f76659f08066d656d736574a0080462636d70a1083b636f6d70696c65725f6275696c74696e733a3a696e743a3a73686966743a3a5f5f6173686c7469333a3a6838656231636163626365343565313733a2083b636f6d70696c65725f6275696c74696e733a3a696e743a3a73686966743a3a5f5f6c7368727469333a3a6861613765666137333665663233346637a308095f5f6173686c746933a408095f5f6c73687274693300550970726f64756365727302086c616e6775616765010452757374000c70726f6365737365642d62790105727573746325312e34352e302d6e696768746c79202866613531663831306520323032302d30342d323929", + "0x5f3e4907f716ac89b6347d15ececedcaa141c4fe67c2d11f4a10c6aca7a79a04b4def25cfda6ef3a00000000": "0xd8ff03bfc91b8e000000000000000000", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950d49dd691c4fe7bf66772616e803919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef": "0xf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", + "0x5f3e4907f716ac89b6347d15ececedca682db92dde20a10d96d00ff0e9e221c0b4def25cfda6ef3a000000007441588f5c9a91b3f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663": "0x00", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195081918b9c078ba64f696d6f6e8000299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378": "0xf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", + "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb3c90f9b6dd26886b468655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78": "0x7932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950f05c8ba6ac2a99ca6175646980482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a": "0x547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65", + "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc47bd1e6299d2e71c4c848a957ae243d7b9e42241d7cd91d001773b0b616d523dd80e13c6c2cab860b1234ef1b9ffc1526": "0x547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d650f0000c16ff286230f0000c16ff286230000", + "0x5f3e4907f716ac89b6347d15ececedca8bde0a0ea8864605e3b68ed9cb2da01bb4def25cfda6ef3a0000000079091c57296b2634547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65": "0x0ff6ffc06ff286230ff6ffc06ff2862300", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195090ae3b675fd0a89f6175646980482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e": "0x68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78", + "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc469a5ec1b3cb6032ce536e31d5679de28c8dc79e36b29395413399edaec3e20fcca7205fb19776ed8ddb25d6f427ec40e": "0x68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde780f0000c16ff286230f0000c16ff286230000", + "0xe2e62dd81c48a88f73b6f6463555fd8e71cd3068e6118bfb392b798317f63a89d28ebd9aad2de6179ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809": "0x0000c16ff28623000000000000000000049ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809", + "0x5f3e4907f716ac89b6347d15ececedcae1791577e4efcb083fdc3cb21e85b2e4": "0x00", "0x1cb6f36e027abb2091cfb5110ab5087f66e8f035c8adbe7f1547b43c51e6f8a4": "0x00000000", - "0x26aa394eea5630e07c48ae0c9558cef7a44704b568d21667356a5a050c11874611da6d1f761ddf9bdb4c9d6e5303ebd41f61858d0a5647a1a7bfe089bf921be9": "0x4545454545454545454545454545454545454545454545454545454545454545", - "0x5f3e4907f716ac89b6347d15ececedcaad811cd65a470ddc5f1d628ff055098211da6d1f761ddf9bdb4c9d6e5303ebd41f61858d0a5647a1a7bfe089bf921be9": "0x00000000", + "0xe2e62dd81c48a88f73b6f6463555fd8eba7fb8745735dc3be2a2c61a72c39e78": "0x049ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e3180973474718090000c16ff28623000000000000000000", + "0x2099d7f109d6e535fb000bba623fd4409f99a2ce711f3a31b2fc05604c93f179": "0x106e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f910600299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e", + "0x5f3e4907f716ac89b6347d15ececedca42982b9d6c7acc99faa9094c912372c2b4def25cfda6ef3a0000000079091c57296b2634547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65": "0x0ff6ffc06ff286230ff6ffc06ff2862300", + "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade987441588f5c9a91b3f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663": "0x00", + "0x2371e21684d2fae99bcb4d579242f74a8a2d09463effcc78a22d75b9cb87dffc": "0x0000000000000000", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9b2a4e124620611833d1b252494468c2a68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78": "0x00000000030000c16ff28623000000000000000000000000000000000000000000000000000000c16ff286230000000000000000000000c16ff28623000000000000000000", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950606e9687c0a4d75f696d6f6e80482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e": "0x68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78", + "0x26aa394eea5630e07c48ae0c9558cef7f9cce9c888469bb1a0dceaa129672ef8": "0xd503106e6f6465", + "0x5f3e4907f716ac89b6347d15ececedcaea07de2b8f010516dca3f7ef52f7ac5a": "0x040000000000000000", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195003e77b7332307fb461756469806e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106": "0x9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195050b3bd0c839f9eac6772616e807932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f": "0x68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78", + "0x5f3e4907f716ac89b6347d15ececedca682db92dde20a10d96d00ff0e9e221c0b4def25cfda6ef3a0000000079091c57296b2634547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65": "0x00", + "0xcec5070d609dd3497f72bde07fc96ba088dcde934c658227ee1dfafcd6e16903": "0x109c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d6568655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78", + "0x26aa394eea5630e07c48ae0c9558cef78a42f33323cb5ced3b44dd825fda9fcc": "0x4545454545454545454545454545454545454545454545454545454545454545", + "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe7054352b71083d945a9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12": "0x781ead1e2fa9ccb74b44c19d29cb2a7a4b5be3972927ae98cd3877523976a276", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9a8d6d78917f3d243ed0a3d1dfb3878099c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12": "0x00000000030000c16ff28623000000000000000000000000000000000000000000000000000000c16ff286230000000000000000000000c16ff28623000000000000000000", + "0x5f3e4907f716ac89b6347d15ececedca42982b9d6c7acc99faa9094c912372c2b4def25cfda6ef3a0000000054352b71083d945a9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12": "0x0ff6ffc06ff286230ff6ffc06ff2862300", "0x5f3e4907f716ac89b6347d15ececedcab49a2738eeb30896aacb8b3fb46471bd": "0x04000000", - "0xcec5070d609dd3497f72bde07fc96ba088dcde934c658227ee1dfafcd6e16903": "0x10f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d6568655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde789c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", - "0x5f3e4907f716ac89b6347d15ececedca8bde0a0ea8864605e3b68ed9cb2da01bb4def25cfda6ef3a0000000079091c57296b2634547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65": "0x0ff6ffc06ff286230ff6ffc06ff2862300", - "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc401278c742b3436b1fdc6f422f6166f4cf5078209e15c31f4947506f71744409a": "0x547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d650f0000c16ff286230f0000c16ff286230000", + "0x5f3e4907f716ac89b6347d15ececedca308ce9615de0775a82f8a94dc3d285a1": "0x02", + "0x1cb6f36e027abb2091cfb5110ab5087f5e0621c4869aa60c02be9adcc98a0d1d": "0x106e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106010000000000000000299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f43780100000000000000482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a0100000000000000482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e0100000000000000", + "0x5c0d1176a568c1f92944340dbfed9e9c530ebca703c85910e7164cb7d1c9e47b": "0x9ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809", + "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe70c90f9b6dd26886b468655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78": "0xc8dc79e36b29395413399edaec3e20fcca7205fb19776ed8ddb25d6f427ec40e", + "0x3a6772616e6470615f617574686f726974696573": "0x01109becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe969933201000000000000003919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef01000000000000005633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce44001000000000000007932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f0100000000000000", + "0x5f3e4907f716ac89b6347d15ececedca682db92dde20a10d96d00ff0e9e221c0b4def25cfda6ef3a0000000054352b71083d945a9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12": "0x00", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195088c3e18f0a370f936772616e809becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe9699332": "0x9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", + "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc49c1d737e05234a5ad3f96cf385e1f17b781ead1e2fa9ccb74b44c19d29cb2a7a4b5be3972927ae98cd3877523976a276": "0x9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d120f0000c16ff286230f0000c16ff286230000", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da95018afb0daf0c8654bf248b8e9f3ca3cf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663": "0x00000000030000c16ff28623000000000000000000000000000000000000000000000000000000c16ff286230000000000000000000000c16ff28623000000000000000000", + "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe7079091c57296b2634547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65": "0x9e42241d7cd91d001773b0b616d523dd80e13c6c2cab860b1234ef1b9ffc1526", "0x5f3e4907f716ac89b6347d15ececedca42982b9d6c7acc99faa9094c912372c2b4def25cfda6ef3a00000000c90f9b6dd26886b468655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78": "0x0ff6ffc06ff286230ff6ffc06ff2862300", - "0x5f3e4907f716ac89b6347d15ececedca0b6a45321efae92aea15e0740ec7afe7": "0x00000000", - "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade98e54094c2d5af8ae10b91e1288f4f59f2946d7738f2c509b7effd909e5e9ba0ad": "0x00" + "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e1690354352b71083d945a9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12": "0x00", + "0x3a65787472696e7369635f696e646578": "0x00000000", + "0x426e15054d267946093858132eb537f1a47a9ff5cd5bf4d848a80a0b1a947dc3": "0x00000000000000000000000000000000", + "0x8985776095addd4789fccbce8ca77b23ba7fb8745735dc3be2a2c61a72c39e78": "0x049ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809", + "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc65018afb0daf0c8654bf248b8e9f3ca3cf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663": "0x047374616b696e67200000c16ff2862300000000000000000002", + "0x426e15054d267946093858132eb537f1ba7fb8745735dc3be2a2c61a72c39e78": "0x049ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809", + "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc6b2a4e124620611833d1b252494468c2a68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78": "0x047374616b696e67200000c16ff2862300000000000000000002", + "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb37441588f5c9a91b3f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663": "0x3919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f437800299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f437800299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378", + "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc6bed2903186223711a06d85784e730efd547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65": "0x047374616b696e67200000c16ff2862300000000000000000002", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950279056c0dd3fd147696d6f6e806e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106": "0x9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", + "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e16903c90f9b6dd26886b468655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78": "0x00", + "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade9879091c57296b2634547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65": "0x00", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950a7c05e469443baab617564698000299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378": "0xf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", + "0x5f3e4907f716ac89b6347d15ececedca42982b9d6c7acc99faa9094c912372c2b4def25cfda6ef3a000000007441588f5c9a91b3f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663": "0x0ff6ffc06ff286230ff6ffc06ff2862300", + "0x426e15054d267946093858132eb537f1d0b4a3f7631f0c0e761898fe198211de": "0xe7030000", + "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade98c90f9b6dd26886b468655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78": "0x00", + "0x5f3e4907f716ac89b6347d15ececedca487df464e44a534ba6b0cbb32407b587": "0x0000000000", + "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc6a8d6d78917f3d243ed0a3d1dfb3878099c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12": "0x047374616b696e67200000c16ff2862300000000000000000002", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9a831cc69a96025a90c389ecb19a25ff29ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809": "0x000000000100405f2954c5c535360000000000000000c040b571e8030000000000000000000000c16ff2862300000000000000000000000000000000000000000000000000", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195018823a93d5cac7d062616265806e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106": "0x9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195082216e38506cc6f7626162658000299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378": "0xf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da95ecffd7b6c0f78751baa9d281e0bfa3a6d6f646c70792f74727372790000000000000000000000000000000000000000": "0x000000000000407a10f35a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "0x26aa394eea5630e07c48ae0c9558cef7a44704b568d21667356a5a050c118746b4def25cfda6ef3a00000000": "0x4545454545454545454545454545454545454545454545454545454545454545", + "0x5f3e4907f716ac89b6347d15ececedca8bde0a0ea8864605e3b68ed9cb2da01bb4def25cfda6ef3a00000000c90f9b6dd26886b468655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78": "0x0ff6ffc06ff286230ff6ffc06ff2862300", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950414ee903f38cbde66772616e805633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440": "0x547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195057479bdad16c7a386261626580482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e": "0x68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78", + "0xf2794c22e353e9a839f12faab03a911be2f6cb0456905c189bcb0458f9440f13": "0x00000000", + "0x5f3e4907f716ac89b6347d15ececedca28dccb559b95c40168a1b2696581b5a7": "0x00000000000000000000000000000000", + "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc6a831cc69a96025a90c389ecb19a25ff29ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809": "0x04706872656c6563740000c16ff2862300000000000000000001", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950dd81945454d561f36261626580482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a": "0x547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65" }, - "children": {} + "childrenDefault": {} } } } diff --git a/bin/node/cli/src/browser.rs b/bin/node/cli/src/browser.rs index e7dd1e78b4fb250eb6e1ead9932290ddab6fb0e9..3aec486c103700f9e7fd9e9c9a8218b78cf555ab 100644 --- a/bin/node/cli/src/browser.rs +++ b/bin/node/cli/src/browser.rs @@ -1,23 +1,24 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use crate::chain_spec::ChainSpec; use log::info; use wasm_bindgen::prelude::*; -use sc_service::Configuration; use browser_utils::{ Client, browser_configuration, set_console_error_panic_hook, init_console_log, @@ -26,30 +27,35 @@ use std::str::FromStr; /// Starts the client. #[wasm_bindgen] -pub async fn start_client(chain_spec: String, log_level: String) -> Result { +pub async fn start_client(chain_spec: Option, log_level: String) -> Result { start_inner(chain_spec, log_level) .await .map_err(|err| JsValue::from_str(&err.to_string())) } -async fn start_inner(chain_spec: String, log_level: String) -> Result> { +async fn start_inner(chain_spec: Option, log_level: String) -> Result> { set_console_error_panic_hook(); init_console_log(log::Level::from_str(&log_level)?)?; - let chain_spec = ChainSpec::from_json_bytes(chain_spec.as_bytes().to_vec()) - .map_err(|e| format!("{:?}", e))?; + let chain_spec = match chain_spec { + Some(chain_spec) => ChainSpec::from_json_bytes(chain_spec.as_bytes().to_vec()) + .map_err(|e| format!("{:?}", e))?, + None => crate::chain_spec::development_config(), + }; let config = browser_configuration(chain_spec).await?; info!("Substrate browser node"); - info!("✌️ version {}", config.full_version()); + info!("✌️ version {}", config.impl_version); info!("❤️ by Parity Technologies, 2017-2020"); - info!("📋 Chain specification: {}", config.expect_chain_spec().name()); - info!("🏷 Node name: {}", config.name); + info!("📋 Chain specification: {}", config.chain_spec.name()); + info!("🏷 Node name: {}", config.network.node_name); info!("👤 Role: {:?}", config.role); // Create the service. This is the most heavy initialization step. - let service = crate::service::new_light(config) - .map_err(|e| format!("{:?}", e))?; + let (task_manager, rpc_handlers) = + crate::service::new_light_base(config) + .map(|(components, rpc_handlers, _, _, _)| (components, rpc_handlers)) + .map_err(|e| format!("{:?}", e))?; - Ok(browser_utils::start_client(service)) + Ok(browser_utils::start_client(task_manager, rpc_handlers)) } diff --git a/bin/node/cli/src/chain_spec.rs b/bin/node/cli/src/chain_spec.rs index 700556206d46072b778fc371a89fa60777e42e4f..8617024255f2842107bdbf0fb28dd4f8dcb050cf 100644 --- a/bin/node/cli/src/chain_spec.rs +++ b/bin/node/cli/src/chain_spec.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Substrate chain configurations. @@ -27,7 +29,7 @@ use node_runtime::{ }; use node_runtime::Block; use node_runtime::constants::currency::*; -use sc_service; +use sc_service::ChainType; use hex_literal::hex; use sc_telemetry::TelemetryEndpoints; use grandpa_primitives::{AuthorityId as GrandpaId}; @@ -51,9 +53,9 @@ const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; #[serde(rename_all = "camelCase")] pub struct Extensions { /// Block numbers with known hashes. - pub fork_blocks: sc_client::ForkBlocks, + pub fork_blocks: sc_client_api::ForkBlocks, /// Known bad block hashes. - pub bad_blocks: sc_client::BadBlocks, + pub bad_blocks: sc_client_api::BadBlocks, } /// Specialized `ChainSpec`. @@ -158,6 +160,7 @@ pub fn staging_testnet_config() -> ChainSpec { ChainSpec::from_genesis( "Staging Testnet", "staging_testnet", + ChainType::Live, staging_testnet_config_genesis, boot_nodes, Some(TelemetryEndpoints::new(vec![(STAGING_TELEMETRY_URL.to_string(), 0)]) @@ -183,7 +186,7 @@ pub fn get_account_id_from_seed(seed: &str) -> AccountId where } /// Helper function to generate stash, controller and session key from seed -pub fn get_authority_keys_from_seed(seed: &str) -> ( +pub fn authority_keys_from_seed(seed: &str) -> ( AccountId, AccountId, GrandpaId, @@ -291,7 +294,6 @@ pub fn testnet_genesis( enable_println, // this should only be enabled on development chains ..Default::default() }, - gas_price: 1 * MILLICENTS, }), pallet_sudo: Some(SudoConfig { key: root_key, @@ -325,7 +327,7 @@ pub fn testnet_genesis( fn development_config_genesis() -> GenesisConfig { testnet_genesis( vec![ - get_authority_keys_from_seed("Alice"), + authority_keys_from_seed("Alice"), ], get_account_id_from_seed::("Alice"), None, @@ -338,6 +340,7 @@ pub fn development_config() -> ChainSpec { ChainSpec::from_genesis( "Development", "dev", + ChainType::Development, development_config_genesis, vec![], None, @@ -350,8 +353,8 @@ pub fn development_config() -> ChainSpec { fn local_testnet_genesis() -> GenesisConfig { testnet_genesis( vec![ - get_authority_keys_from_seed("Alice"), - get_authority_keys_from_seed("Bob"), + authority_keys_from_seed("Alice"), + authority_keys_from_seed("Bob"), ], get_account_id_from_seed::("Alice"), None, @@ -364,6 +367,7 @@ pub fn local_testnet_config() -> ChainSpec { ChainSpec::from_genesis( "Local Testnet", "local_testnet", + ChainType::Local, local_testnet_genesis, vec![], None, @@ -376,14 +380,14 @@ pub fn local_testnet_config() -> ChainSpec { #[cfg(test)] pub(crate) mod tests { use super::*; - use crate::service::{new_full, new_light}; + use crate::service::{new_full_base, new_light_base}; use sc_service_test; use sp_runtime::BuildStorage; fn local_testnet_genesis_instant_single() -> GenesisConfig { testnet_genesis( vec![ - get_authority_keys_from_seed("Alice"), + authority_keys_from_seed("Alice"), ], get_account_id_from_seed::("Alice"), None, @@ -396,6 +400,7 @@ pub(crate) mod tests { ChainSpec::from_genesis( "Integration Test", "test", + ChainType::Development, local_testnet_genesis_instant_single, vec![], None, @@ -410,6 +415,7 @@ pub(crate) mod tests { ChainSpec::from_genesis( "Integration Test", "test", + ChainType::Development, local_testnet_genesis, vec![], None, @@ -424,8 +430,14 @@ pub(crate) mod tests { fn test_connectivity() { sc_service_test::connectivity( integration_test_config_with_two_authorities(), - |config| new_full(config), - |config| new_light(config), + |config| { + let (keep_alive, _, client, network, transaction_pool) = new_full_base(config,|_, _| ())?; + Ok(sc_service_test::TestNetComponents::new(keep_alive, client, network, transaction_pool)) + }, + |config| { + let (keep_alive, _, client, network, transaction_pool) = new_light_base(config)?; + Ok(sc_service_test::TestNetComponents::new(keep_alive, client, network, transaction_pool)) + } ); } diff --git a/bin/node/cli/src/cli.rs b/bin/node/cli/src/cli.rs index b6db9c3deb7e31f8f8da62d30b6971bf572b30d1..29e916fe0180ec2c8ffde4cacdfba361b24cf86c 100644 --- a/bin/node/cli/src/cli.rs +++ b/bin/node/cli/src/cli.rs @@ -1,24 +1,26 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . -use sc_cli::{SharedParams, ImportParams, RunCmd}; +use sc_cli::RunCmd; use structopt::StructOpt; /// An overarching CLI command definition. -#[derive(Clone, Debug, StructOpt)] +#[derive(Debug, StructOpt)] pub struct Cli { /// Possible subcommand with parameters. #[structopt(subcommand)] @@ -29,18 +31,11 @@ pub struct Cli { } /// Possible subcommands of the main binary. -#[derive(Clone, Debug, StructOpt)] +#[derive(Debug, StructOpt)] pub enum Subcommand { /// A set of base subcommands handled by `sc_cli`. #[structopt(flatten)] Base(sc_cli::Subcommand), - /// 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), /// The custom inspect subcommmand for decoding blocks and extrinsics. #[structopt( @@ -50,30 +45,6 @@ pub enum Subcommand { Inspect(node_inspect::cli::InspectCmd), /// The custom benchmark subcommmand benchmarking runtime pallets. - #[structopt( - name = "benchmark", - about = "Benchmark runtime pallets." - )] + #[structopt(name = "benchmark", about = "Benchmark runtime pallets.")] Benchmark(frame_benchmarking_cli::BenchmarkCmd), } - -/// 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 { - /// Number of blocks to generate. - #[structopt(long="blocks", default_value = "1")] - pub blocks: u32, - - /// Number of transactions to push per block. - #[structopt(long="transactions", default_value = "8")] - pub transactions: u32, - - #[allow(missing_docs)] - #[structopt(flatten)] - pub shared_params: SharedParams, - - #[allow(missing_docs)] - #[structopt(flatten)] - pub import_params: ImportParams, -} diff --git a/bin/node/cli/src/command.rs b/bin/node/cli/src/command.rs index 84d680b6f8024b94e9941620c1f6f676f1d2a7da..91bec64edd63f11b8ceaced9445cccebb7ce2d97 100644 --- a/bin/node/cli/src/command.rs +++ b/bin/node/cli/src/command.rs @@ -1,117 +1,102 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . -use sc_cli::VersionInfo; -use sc_service::{Role as ServiceRole}; -use node_transaction_factory::RuntimeAdapter; -use crate::{Cli, service, ChainSpec, load_spec, Subcommand, factory_impl::FactoryState}; +use crate::{chain_spec, service, Cli, Subcommand}; +use node_executor::Executor; +use node_runtime::{Block, RuntimeApi}; +use sc_cli::{Result, SubstrateCli, RuntimeVersion, Role, ChainSpec}; -/// Parse command line arguments into service configuration. -pub fn run(args: I, version: VersionInfo) -> sc_cli::Result<()> -where - I: Iterator, - T: Into + Clone, -{ - sc_cli::reset_signal_pipe_handler()?; +impl SubstrateCli for Cli { + fn impl_name() -> String { + "Substrate Node".into() + } + + fn impl_version() -> String { + env!("SUBSTRATE_CLI_IMPL_VERSION").into() + } + + fn description() -> String { + env!("CARGO_PKG_DESCRIPTION").into() + } + + fn author() -> String { + env!("CARGO_PKG_AUTHORS").into() + } + + fn support_url() -> String { + "https://github.com/paritytech/substrate/issues/new".into() + } - let args: Vec<_> = args.collect(); - let opt = sc_cli::from_iter::(args.clone(), &version); + fn copyright_start_year() -> i32 { + 2017 + } + + fn load_spec(&self, id: &str) -> std::result::Result, String> { + Ok(match id { + "dev" => Box::new(chain_spec::development_config()), + "local" => Box::new(chain_spec::local_testnet_config()), + "" | "fir" | "flaming-fir" => Box::new(chain_spec::flaming_fir_config()?), + "staging" => Box::new(chain_spec::staging_testnet_config()), + path => Box::new(chain_spec::ChainSpec::from_json_file( + std::path::PathBuf::from(path), + )?), + }) + } - let mut config = sc_service::Configuration::from_version(&version); + fn native_runtime_version(_: &Box) -> &'static RuntimeVersion { + &node_runtime::VERSION + } +} - match opt.subcommand { +/// Parse command line arguments into service configuration. +pub fn run() -> Result<()> { + let cli = Cli::from_args(); + + match &cli.subcommand { None => { - opt.run.init(&version)?; - opt.run.update_config(&mut config, load_spec, &version)?; - opt.run.run( - config, - service::new_light, - service::new_full, - &version, - ) - }, + let runner = cli.create_runner(&cli.run)?; + runner.run_node_until_exit(|config| match config.role { + Role::Light => service::new_light(config), + _ => service::new_full(config), + }) + } Some(Subcommand::Inspect(cmd)) => { - cmd.init(&version)?; - cmd.update_config(&mut config, load_spec, &version)?; - - let client = sc_service::new_full_client::< - node_runtime::Block, node_runtime::RuntimeApi, node_executor::Executor, - >(&config)?; - let inspect = node_inspect::Inspector::::new(client); + let runner = cli.create_runner(cmd)?; - cmd.run(inspect) - }, + runner.sync_run(|config| cmd.run::(config)) + } Some(Subcommand::Benchmark(cmd)) => { - cmd.init(&version)?; - cmd.update_config(&mut config, load_spec, &version)?; - - cmd.run::(config) - }, - Some(Subcommand::Factory(cli_args)) => { - cli_args.shared_params.init(&version)?; - cli_args.shared_params.update_config(&mut config, load_spec, &version)?; - cli_args.import_params.update_config( - &mut config, - &ServiceRole::Full, - cli_args.shared_params.dev, - )?; - - config.use_in_memory_keystore()?; - - match ChainSpec::from(config.expect_chain_spec().id()) { - Some(ref c) if c == &ChainSpec::Development || c == &ChainSpec::LocalTestnet => {}, - _ => return Err( - "Factory is only supported for development and local testnet.".into() - ), + if cfg!(feature = "runtime-benchmarks") { + let runner = cli.create_runner(cmd)?; + + runner.sync_run(|config| cmd.run::(config)) + } else { + println!("Benchmarking wasn't enabled when building the node. \ + You can enable it with `--features runtime-benchmarks`."); + Ok(()) } - - // Setup tracing. - if let Some(tracing_targets) = cli_args.import_params.tracing_targets.as_ref() { - let subscriber = sc_tracing::ProfilingSubscriber::new( - cli_args.import_params.tracing_receiver.into(), tracing_targets - ); - if let Err(e) = tracing::subscriber::set_global_default(subscriber) { - return Err( - format!("Unable to set global default subscriber {}", e).into() - ); - } - } - - let factory_state = FactoryState::new( - cli_args.blocks, - cli_args.transactions, - ); - - let service_builder = new_full_start!(config).0; - node_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(()) - }, + } Some(Subcommand::Base(subcommand)) => { - subcommand.init(&version)?; - subcommand.update_config(&mut config, load_spec, &version)?; - subcommand.run( - config, - |config: sc_service::Configuration| Ok(new_full_start!(config).0), - ) - }, + let runner = cli.create_runner(subcommand)?; + runner.run_subcommand(subcommand, |config| { + let (builder, _, _, _) = new_full_start!(config); + Ok(builder.to_chain_ops_parts()) + }) + } } } diff --git a/bin/node/cli/src/factory_impl.rs b/bin/node/cli/src/factory_impl.rs deleted file mode 100644 index cd7e3022e0b9a66e510707245118dbc123edee0d..0000000000000000000000000000000000000000 --- a/bin/node/cli/src/factory_impl.rs +++ /dev/null @@ -1,205 +0,0 @@ -// Copyright 2019-2020 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 transaction factory trait, which enables -//! using the cli to manufacture transactions and distribute them -//! to accounts. - -use rand::{Rng, SeedableRng}; -use rand::rngs::StdRng; - -use codec::{Encode, Decode}; -use sp_keyring::sr25519::Keyring; -use node_runtime::{ - Call, CheckedExtrinsic, UncheckedExtrinsic, SignedExtra, BalancesCall, ExistentialDeposit, - MinimumPeriod -}; -use node_primitives::Signature; -use sp_core::{sr25519, crypto::Pair}; -use sp_runtime::{ - generic::Era, traits::{Block as BlockT, Header as HeaderT, SignedExtension, Verify, IdentifyAccount} -}; -use node_transaction_factory::RuntimeAdapter; -use sp_inherents::InherentData; -use sp_timestamp; -use sp_finality_tracker; - -type AccountPublic = ::Signer; - -pub struct FactoryState { - blocks: u32, - transactions: u32, - block_number: N, - index: u32, -} - -type Number = <::Header as HeaderT>::Number; - -impl FactoryState { - fn build_extra(index: node_primitives::Index, phase: u64) -> node_runtime::SignedExtra { - ( - frame_system::CheckVersion::new(), - frame_system::CheckGenesis::new(), - frame_system::CheckEra::from(Era::mortal(256, phase)), - frame_system::CheckNonce::from(index), - frame_system::CheckWeight::new(), - pallet_transaction_payment::ChargeTransactionPayment::from(0), - Default::default(), - Default::default(), - ) - } -} - -impl RuntimeAdapter for FactoryState { - type AccountId = node_primitives::AccountId; - type Balance = node_primitives::Balance; - type Block = node_primitives::Block; - type Phase = sp_runtime::generic::Phase; - type Secret = sr25519::Pair; - type Index = node_primitives::Index; - - type Number = Number; - - fn new( - blocks: u32, - transactions: u32, - ) -> FactoryState { - FactoryState { - blocks, - transactions, - block_number: 0, - index: 0, - } - } - - fn block_number(&self) -> u32 { - self.block_number - } - - fn blocks(&self) -> u32 { - self.blocks - } - - fn transactions(&self) -> u32 { - self.transactions - } - - fn set_block_number(&mut self, value: u32) { - self.block_number = value; - } - - fn transfer_extrinsic( - &mut self, - sender: &Self::AccountId, - key: &Self::Secret, - destination: &Self::AccountId, - amount: &Self::Balance, - version: u32, - genesis_hash: &::Hash, - prior_block_hash: &::Hash, - ) -> ::Extrinsic { - let phase = self.block_number() as Self::Phase; - let extra = Self::build_extra(self.index, phase); - self.index += 1; - - sign::(CheckedExtrinsic { - signed: Some((sender.clone(), extra)), - function: Call::Balances( - BalancesCall::transfer( - pallet_indices::address::Address::Id(destination.clone().into()), - (*amount).into() - ) - ) - }, key, (version, genesis_hash.clone(), prior_block_hash.clone(), (), (), (), (), ())) - } - - fn inherent_extrinsics(&self) -> InherentData { - let timestamp = (self.block_number as u64 + 1) * MinimumPeriod::get(); - - let mut inherent = InherentData::new(); - inherent.put_data(sp_timestamp::INHERENT_IDENTIFIER, ×tamp) - .expect("Failed putting timestamp inherent"); - inherent.put_data(sp_finality_tracker::INHERENT_IDENTIFIER, &self.block_number) - .expect("Failed putting finalized number inherent"); - inherent - } - - fn minimum_balance() -> Self::Balance { - ExistentialDeposit::get() - } - - fn master_account_id() -> Self::AccountId { - Keyring::Alice.to_account_id() - } - - fn master_account_secret() -> Self::Secret { - Keyring::Alice.pair() - } - - /// Generates a random `AccountId` from `seed`. - fn gen_random_account_id(seed: u32) -> Self::AccountId { - let pair: sr25519::Pair = sr25519::Pair::from_seed(&gen_seed_bytes(seed)); - AccountPublic::from(pair.public()).into_account() - } - - /// Generates a random `Secret` from `seed`. - fn gen_random_account_secret(seed: u32) -> Self::Secret { - let pair: sr25519::Pair = sr25519::Pair::from_seed(&gen_seed_bytes(seed)); - pair - } -} - -fn gen_seed_bytes(seed: u32) -> [u8; 32] { - let mut rng: StdRng = SeedableRng::seed_from_u64(seed as u64); - - let mut seed_bytes = [0u8; 32]; - for i in 0..32 { - seed_bytes[i] = rng.gen::(); - } - seed_bytes -} - -/// Creates an `UncheckedExtrinsic` containing the appropriate signature for -/// a `CheckedExtrinsics`. -fn sign( - xt: CheckedExtrinsic, - key: &sr25519::Pair, - additional_signed: ::AdditionalSigned, -) -> ::Extrinsic { - let s = match xt.signed { - Some((signed, extra)) => { - let payload = (xt.function, extra.clone(), additional_signed); - let signature = payload.using_encoded(|b| { - if b.len() > 256 { - key.sign(&sp_io::hashing::blake2_256(b)) - } else { - key.sign(b) - } - }).into(); - UncheckedExtrinsic { - signature: Some((pallet_indices::address::Address::Id(signed), signature, extra)), - function: payload.0, - } - } - None => UncheckedExtrinsic { - signature: None, - function: xt.function, - }, - }; - - let e = Encode::encode(&s); - Decode::decode(&mut &e[..]).expect("Failed to decode signed unchecked extrinsic") -} diff --git a/bin/node/cli/src/lib.rs b/bin/node/cli/src/lib.rs index 6b3644856c6b027172ad62b132c65fcb92d05146..bd2298514a7a2f1ed57fa008615b11ac0947d20b 100644 --- a/bin/node/cli/src/lib.rs +++ b/bin/node/cli/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Substrate CLI library. //! @@ -37,8 +39,6 @@ mod browser; #[cfg(feature = "cli")] mod cli; #[cfg(feature = "cli")] -mod factory_impl; -#[cfg(feature = "cli")] mod command; #[cfg(feature = "browser")] @@ -47,45 +47,3 @@ pub use browser::*; pub use cli::*; #[cfg(feature = "cli")] pub use command::*; - -/// The chain specification option. -#[derive(Clone, Debug, PartialEq)] -pub enum ChainSpec { - /// Whatever the current runtime is, with just Alice as an auth. - Development, - /// Whatever the current runtime is, with simple Alice/Bob auths. - LocalTestnet, - /// The Flaming Fir testnet. - FlamingFir, - /// Whatever the current runtime is with the "global testnet" defaults. - StagingTestnet, -} - -/// Get a chain config from a spec setting. -impl ChainSpec { - pub(crate) fn load(self) -> Result { - Ok(match self { - ChainSpec::FlamingFir => chain_spec::flaming_fir_config()?, - ChainSpec::Development => chain_spec::development_config(), - ChainSpec::LocalTestnet => chain_spec::local_testnet_config(), - ChainSpec::StagingTestnet => chain_spec::staging_testnet_config(), - }) - } - - pub(crate) fn from(s: &str) -> Option { - match s { - "dev" => Some(ChainSpec::Development), - "local" => Some(ChainSpec::LocalTestnet), - "" | "fir" | "flaming-fir" => Some(ChainSpec::FlamingFir), - "staging" => Some(ChainSpec::StagingTestnet), - _ => None, - } - } -} - -fn load_spec(id: &str) -> Result, String> { - Ok(match ChainSpec::from(id) { - Some(spec) => Box::new(spec.load()?), - None => Box::new(chain_spec::ChainSpec::from_json_file(std::path::PathBuf::from(id))?), - }) -} diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index 3e09802ccd8f653585d2c34cbe1e62d9ec7fafba..521c5bb078662a2b10dfb1c4fc187346382999d4 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -1,43 +1,44 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . #![warn(unused_extern_crates)] //! Service implementation. Specialized wrapper over substrate service. use std::sync::Arc; - use sc_consensus_babe; -use sc_client::{self, LongestChain}; -use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider, StorageAndProofProvider}; +use grandpa::{ + self, FinalityProofProvider as GrandpaFinalityProofProvider, StorageAndProofProvider, +}; use node_executor; use node_primitives::Block; use node_runtime::RuntimeApi; use sc_service::{ - AbstractService, ServiceBuilder, config::Configuration, error::{Error as ServiceError}, + ServiceBuilder, config::{Role, Configuration}, error::{Error as ServiceError}, + RpcHandlers, ServiceComponents, TaskManager, }; use sp_inherents::InherentDataProviders; - -use sc_service::{Service, NetworkStatus}; -use sc_client::{Client, LocalCallExecutor}; -use sc_client_db::Backend; +use sc_consensus::LongestChain; +use sc_network::{Event, NetworkService}; use sp_runtime::traits::Block as BlockT; -use node_executor::NativeExecutor; -use sc_network::NetworkService; -use sc_offchain::OffchainWorkers; +use futures::prelude::*; +use sc_client_api::ExecutorProvider; +use sp_core::traits::BareCryptoStorePtr; /// Starts a `ServiceBuilder` for a full service. /// @@ -46,27 +47,44 @@ use sc_offchain::OffchainWorkers; macro_rules! new_full_start { ($config:expr) => {{ use std::sync::Arc; - type RpcExtension = jsonrpc_core::IoHandler; + let mut import_setup = None; + let mut rpc_setup = None; let inherent_data_providers = sp_inherents::InherentDataProviders::new(); let builder = sc_service::ServiceBuilder::new_full::< node_primitives::Block, node_runtime::RuntimeApi, node_executor::Executor >($config)? .with_select_chain(|_config, backend| { - Ok(sc_client::LongestChain::new(backend.clone())) + Ok(sc_consensus::LongestChain::new(backend.clone())) })? - .with_transaction_pool(|config, client, _fetcher| { - let pool_api = sc_transaction_pool::FullChainApi::new(client.clone()); - Ok(sc_transaction_pool::BasicPool::new(config, std::sync::Arc::new(pool_api))) + .with_transaction_pool(|builder| { + let pool_api = sc_transaction_pool::FullChainApi::new( + builder.client().clone(), + builder.prometheus_registry(), + ); + Ok(sc_transaction_pool::BasicPool::new_full( + builder.config().transaction_pool.clone(), + std::sync::Arc::new(pool_api), + builder.prometheus_registry(), + builder.spawn_handle(), + builder.client().clone(), + )) })? - .with_import_queue(|_config, client, mut select_chain, _transaction_pool| { + .with_import_queue(| + _config, + client, + mut select_chain, + _transaction_pool, + spawn_task_handle, + prometheus_registry, + | { let select_chain = select_chain.take() .ok_or_else(|| sc_service::Error::SelectChainRequired)?; let (grandpa_block_import, grandpa_link) = grandpa::block_import( client.clone(), &(client.clone() as Arc<_>), - select_chain, + select_chain.clone(), )?; let justification_import = grandpa_block_import.clone(); @@ -82,232 +100,287 @@ macro_rules! new_full_start { Some(Box::new(justification_import)), None, client, + select_chain, inherent_data_providers.clone(), + spawn_task_handle, + prometheus_registry, )?; import_setup = Some((block_import, grandpa_link, babe_link)); Ok(import_queue) })? - .with_rpc_extensions(|builder| -> Result { + .with_rpc_extensions_builder(|builder| { + let grandpa_link = import_setup.as_ref().map(|s| &s.1) + .expect("GRANDPA LinkHalf is present for full services or set up failed; qed."); + + let shared_authority_set = grandpa_link.shared_authority_set().clone(); + let shared_voter_state = grandpa::SharedVoterState::empty(); + + rpc_setup = Some((shared_voter_state.clone())); + let babe_link = import_setup.as_ref().map(|s| &s.2) .expect("BabeLink is present for full services or set up failed; qed."); - let deps = node_rpc::FullDeps { - client: builder.client().clone(), - pool: builder.pool(), - select_chain: builder.select_chain().cloned() - .expect("SelectChain is present for full services or set up failed; qed."), - babe: node_rpc::BabeDeps { - keystore: builder.keystore(), - babe_config: sc_consensus_babe::BabeLink::config(babe_link).clone(), - shared_epoch_changes: sc_consensus_babe::BabeLink::epoch_changes(babe_link).clone() - } - }; - Ok(node_rpc::create_full(deps)) + + let babe_config = babe_link.config().clone(); + let shared_epoch_changes = babe_link.epoch_changes().clone(); + + let client = builder.client().clone(); + let pool = builder.pool().clone(); + let select_chain = builder.select_chain().cloned() + .expect("SelectChain is present for full services or set up failed; qed."); + let keystore = builder.keystore().clone(); + + Ok(move |deny_unsafe| { + let deps = node_rpc::FullDeps { + client: client.clone(), + pool: pool.clone(), + select_chain: select_chain.clone(), + deny_unsafe, + babe: node_rpc::BabeDeps { + babe_config: babe_config.clone(), + shared_epoch_changes: shared_epoch_changes.clone(), + keystore: keystore.clone(), + }, + grandpa: node_rpc::GrandpaDeps { + shared_voter_state: shared_voter_state.clone(), + shared_authority_set: shared_authority_set.clone(), + }, + }; + + node_rpc::create_full(deps) + }) })?; - (builder, import_setup, inherent_data_providers) + (builder, import_setup, inherent_data_providers, rpc_setup) }} } +type FullClient = sc_service::TFullClient; +type FullBackend = sc_service::TFullBackend; +type GrandpaBlockImport = grandpa::GrandpaBlockImport< + FullBackend, Block, FullClient, sc_consensus::LongestChain +>; +type BabeBlockImport = sc_consensus_babe::BabeBlockImport; + /// 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::prelude::*; - use sc_network::Event; - use sc_client_api::ExecutorProvider; - - let ( - role, - force_authoring, - name, - disable_grandpa, - ) = ( - $config.role.clone(), - $config.force_authoring, - $config.name.clone(), - $config.disable_grandpa, - ); +pub fn new_full_base( + config: Configuration, + with_startup_data: impl FnOnce(&BabeBlockImport, &sc_consensus_babe::BabeLink) +) -> Result<( + TaskManager, + InherentDataProviders, + Arc, Arc::Hash>>, + Arc, Block>> +), ServiceError> { + let ( + role, + force_authoring, + name, + disable_grandpa, + ) = ( + config.role.clone(), + config.force_authoring, + config.network.node_name.clone(), + config.disable_grandpa, + ); + + let (builder, mut import_setup, inherent_data_providers, mut rpc_setup) = + new_full_start!(config); + + let ServiceComponents { + client, transaction_pool, task_manager, keystore, network, select_chain, + prometheus_registry, telemetry_on_connect_sinks, .. + } = builder + .with_finality_proof_provider(|client, backend| { + // GenesisAuthoritySetProvider is implemented for StorageAndProofProvider + let provider = client as Arc>; + Ok(Arc::new(grandpa::FinalityProofProvider::new(backend, provider)) as _) + })? + .build_full()?; - let (builder, mut import_setup, inherent_data_providers) = new_full_start!($config); + 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"); - let service = builder - .with_finality_proof_provider(|client, backend| { - // GenesisAuthoritySetProvider is implemented for StorageAndProofProvider - let provider = client as Arc>; - Ok(Arc::new(grandpa::FinalityProofProvider::new(backend, provider)) as _) - })? - .build()?; + let shared_voter_state = rpc_setup.take() + .expect("The SharedVoterState is present for Full Services or setup failed before. qed"); - 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); - ($with_startup_data)(&block_import, &babe_link); + if let sc_service::config::Role::Authority { .. } = &role { + let proposer = sc_basic_authorship::ProposerFactory::new( + client.clone(), + transaction_pool.clone(), + prometheus_registry.as_ref(), + ); - if let sc_service::config::Role::Authority { sentry_nodes } = &role { - let proposer = sc_basic_authorship::ProposerFactory::new( - service.client(), - service.transaction_pool() - ); + let select_chain = select_chain + .ok_or(sc_service::Error::SelectChainRequired)?; - let client = service.client(); - let select_chain = service.select_chain() - .ok_or(sc_service::Error::SelectChainRequired)?; + let can_author_with = + sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); - let can_author_with = - sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); + let babe_config = sc_consensus_babe::BabeParams { + keystore: keystore.clone(), + client: client.clone(), + select_chain, + env: proposer, + block_import, + sync_oracle: network.clone(), + inherent_data_providers: inherent_data_providers.clone(), + force_authoring, + babe_link, + can_author_with, + }; - let babe_config = sc_consensus_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, - can_author_with, - }; + let babe = sc_consensus_babe::start_babe(babe_config)?; + task_manager.spawn_essential_handle().spawn_blocking("babe-proposer", babe); + } - let babe = sc_consensus_babe::start_babe(babe_config)?; - service.spawn_essential_task("babe-proposer", babe); + // Spawn authority discovery module. + if matches!(role, Role::Authority{..} | Role::Sentry {..}) { + let (sentries, authority_discovery_role) = match role { + sc_service::config::Role::Authority { ref sentry_nodes } => ( + sentry_nodes.clone(), + sc_authority_discovery::Role::Authority ( + keystore.clone(), + ), + ), + sc_service::config::Role::Sentry {..} => ( + vec![], + sc_authority_discovery::Role::Sentry, + ), + _ => unreachable!("Due to outer matches! constraint; qed.") + }; - let network = service.network(); - let dht_event_stream = network.event_stream().filter_map(|e| async move { match e { + let dht_event_stream = network.event_stream("authority-discovery") + .filter_map(|e| async move { match e { Event::Dht(e) => Some(e), _ => None, }}).boxed(); - let authority_discovery = sc_authority_discovery::AuthorityDiscovery::new( - service.client(), - network, - sentry_nodes.clone(), - service.keystore(), - dht_event_stream, - service.prometheus_registry(), - ); + let authority_discovery = sc_authority_discovery::AuthorityDiscovery::new( + client.clone(), + network.clone(), + sentries, + dht_event_stream, + authority_discovery_role, + prometheus_registry.clone(), + ); - service.spawn_task("authority-discovery", authority_discovery); - } + task_manager.spawn_handle().spawn("authority-discovery", authority_discovery); + } - // 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 role.is_authority() { - Some(service.keystore()) - } else { - None - }; + // 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 role.is_authority() { + Some(keystore.clone() as BareCryptoStorePtr) + } 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: false, - keystore, - is_authority: role.is_network_authority(), - }; + 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: false, + keystore, + is_authority: role.is_network_authority(), + }; - let enable_grandpa = !disable_grandpa; - if enable_grandpa { - // start the full GRANDPA voter - // NOTE: non-authorities could run the GRANDPA observer protocol, but at - // this point the full voter should provide better guarantees of block - // and vote data availability than the observer. The observer has not - // been tested extensively yet and having most nodes in a network run it - // could lead to finality stalls. - let grandpa_config = grandpa::GrandpaParams { - config, - link: grandpa_link, - network: service.network(), - inherent_data_providers: inherent_data_providers.clone(), - telemetry_on_connect: Some(service.telemetry_on_connect_stream()), - voting_rule: grandpa::VotingRulesBuilder::default().build(), - prometheus_registry: service.prometheus_registry(), - }; + let enable_grandpa = !disable_grandpa; + if enable_grandpa { + // start the full GRANDPA voter + // NOTE: non-authorities could run the GRANDPA observer protocol, but at + // this point the full voter should provide better guarantees of block + // and vote data availability than the observer. The observer has not + // been tested extensively yet and having most nodes in a network run it + // could lead to finality stalls. + let grandpa_config = grandpa::GrandpaParams { + config, + link: grandpa_link, + network: network.clone(), + inherent_data_providers: inherent_data_providers.clone(), + telemetry_on_connect: Some(telemetry_on_connect_sinks.on_connect_stream()), + voting_rule: grandpa::VotingRulesBuilder::default().build(), + prometheus_registry: prometheus_registry.clone(), + shared_voter_state, + }; - // the GRANDPA voter task is considered infallible, i.e. - // if it fails we take down the service with it. - service.spawn_essential_task( - "grandpa-voter", - grandpa::run_grandpa_voter(grandpa_config)? - ); - } else { - grandpa::setup_disabled_grandpa( - service.client(), - &inherent_data_providers, - service.network(), - )?; - } + // the GRANDPA voter task is considered infallible, i.e. + // if it fails we take down the service with it. + task_manager.spawn_essential_handle().spawn_blocking( + "grandpa-voter", + grandpa::run_grandpa_voter(grandpa_config)? + ); + } else { + grandpa::setup_disabled_grandpa( + client.clone(), + &inherent_data_providers, + network.clone(), + )?; + } - Ok((service, inherent_data_providers)) - }}; - ($config:expr) => {{ - new_full!($config, |_, _| {}) - }} + Ok((task_manager, inherent_data_providers, client, network, transaction_pool)) } -type ConcreteBlock = node_primitives::Block; -type ConcreteClient = - Client< - Backend, - LocalCallExecutor, NativeExecutor>, - ConcreteBlock, - node_runtime::RuntimeApi - >; -type ConcreteBackend = Backend; -type ConcreteTransactionPool = sc_transaction_pool::BasicPool< - sc_transaction_pool::FullChainApi, - ConcreteBlock ->; - /// Builds a new service for a full client. pub fn new_full(config: Configuration) --> Result< - Service< - ConcreteBlock, - ConcreteClient, - LongestChain, - NetworkStatus, - NetworkService::Hash>, - ConcreteTransactionPool, - OffchainWorkers< - ConcreteClient, - >::OffchainStorage, - ConcreteBlock, - > - >, - ServiceError, -> -{ - new_full!(config).map(|(service, _)| service) +-> Result { + new_full_base(config, |_, _| ()).map(|(task_manager, _, _, _, _)| { + task_manager + }) } -/// Builds a new service for a light client. -pub fn new_light(config: Configuration) --> Result { - type RpcExtension = jsonrpc_core::IoHandler; +type LightClient = sc_service::TLightClient; +type LightFetcher = sc_network::config::OnDemand; + +pub fn new_light_base(config: Configuration) -> Result<( + TaskManager, Arc, Arc, + Arc::Hash>>, + Arc, Block + >> +), ServiceError> { let inherent_data_providers = InherentDataProviders::new(); - let service = ServiceBuilder::new_light::(config)? + let ServiceComponents { + task_manager, rpc_handlers, client, network, transaction_pool, .. + } = ServiceBuilder::new_light::(config)? .with_select_chain(|_config, backend| { Ok(LongestChain::new(backend.clone())) })? - .with_transaction_pool(|config, client, fetcher| { - let fetcher = fetcher + .with_transaction_pool(|builder| { + let fetcher = builder.fetcher() .ok_or_else(|| "Trying to start light transaction pool without active fetcher")?; - let pool_api = sc_transaction_pool::LightChainApi::new(client.clone(), fetcher.clone()); - let pool = sc_transaction_pool::BasicPool::with_revalidation_type( - config, Arc::new(pool_api), sc_transaction_pool::RevalidationType::Light, + let pool_api = sc_transaction_pool::LightChainApi::new( + builder.client().clone(), + fetcher, ); + let pool = Arc::new(sc_transaction_pool::BasicPool::new_light( + builder.config().transaction_pool.clone(), + Arc::new(pool_api), + builder.prometheus_registry(), + builder.spawn_handle(), + )); Ok(pool) })? - .with_import_queue_and_fprb(|_config, client, backend, fetcher, _select_chain, _tx_pool| { + .with_import_queue_and_fprb(| + _config, + client, + backend, + fetcher, + mut select_chain, + _tx_pool, + spawn_task_handle, + registry, + | { + let select_chain = select_chain.take() + .ok_or_else(|| sc_service::Error::SelectChainRequired)?; + 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( client.clone(), backend, @@ -331,7 +404,10 @@ pub fn new_light(config: Configuration) None, Some(Box::new(finality_proof_import)), client.clone(), + select_chain, inherent_data_providers.clone(), + spawn_task_handle, + registry, )?; Ok((import_queue, finality_proof_request_builder)) @@ -341,9 +417,7 @@ pub fn new_light(config: Configuration) let provider = client as Arc>; Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, provider)) as _) })? - .with_rpc_extensions(|builder,| -> - Result - { + .with_rpc_extensions(|builder| { let fetcher = builder.fetcher() .ok_or_else(|| "Trying to start node RPC without active fetcher")?; let remote_blockchain = builder.remote_backend() @@ -355,19 +429,25 @@ pub fn new_light(config: Configuration) client: builder.client().clone(), pool: builder.pool(), }; + Ok(node_rpc::create_light(light_deps)) })? - .build()?; + .build_light()?; + + Ok((task_manager, rpc_handlers, client, network, transaction_pool)) +} - Ok(service) +/// Builds a new service for a light client. +pub fn new_light(config: Configuration) -> Result { + new_light_base(config).map(|(task_manager, _, _, _, _)| { + task_manager + }) } #[cfg(test)] mod tests { use std::{sync::Arc, borrow::Cow, any::Any}; - use sc_consensus_babe::{ - CompatibleDigestItem, BabeIntermediate, INTERMEDIATE_KEY - }; + use sc_consensus_babe::{CompatibleDigestItem, BabeIntermediate, INTERMEDIATE_KEY}; use sc_consensus_epochs::descendent_query; use sp_consensus::{ Environment, Proposer, BlockImportParams, BlockOrigin, ForkChoiceStrategy, BlockImport, @@ -376,101 +456,24 @@ mod tests { 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 codec::Encode; use sp_core::{crypto::Pair as CryptoPair, H256}; use sp_runtime::{ generic::{BlockId, Era, Digest, SignedPayload}, traits::{Block as BlockT, Header as HeaderT}, traits::Verify, - OpaqueExtrinsic, }; use sp_timestamp; use sp_finality_tracker; use sp_keyring::AccountKeyring; - use sc_service::AbstractService; - use crate::service::{new_full, new_light}; + use sc_service_test::TestNetNode; + use crate::service::{new_full_base, new_light_base}; use sp_runtime::traits::IdentifyAccount; use sp_transaction_pool::{MaintainedTransactionPool, ChainEvent}; + use sc_client_api::BlockBackend; type AccountPublic = ::Signer; - #[cfg(feature = "rhd")] - fn test_sync() { - use sp_core::ed25519::Pair; - - use {service_test, Factory}; - use sc_client::{BlockImportParams, BlockOrigin}; - - let alice: Arc = Arc::new(Keyring::Alice.into()); - let bob: Arc = Arc::new(Keyring::Bob.into()); - let validators = vec![alice.public().0.into(), bob.public().0.into()]; - let keys: Vec<&ed25519::Pair> = vec![&*alice, &*bob]; - let dummy_runtime = ::tokio::runtime::Runtime::new().unwrap(); - let block_factory = |service: &::FullService| { - let block_id = BlockId::number(service.client().chain_info().best_number); - let parent_header = service.client().best_header(&block_id) - .expect("db error") - .expect("best block should exist"); - - futures::executor::block_on( - service.transaction_pool().maintain( - ChainEvent::NewBlock { - is_new_best: true, - id: block_id.clone(), - retracted: vec![], - header: parent_header, - }, - ) - ); - - let consensus_net = ConsensusNetwork::new(service.network(), service.client().clone()); - let proposer_factory = consensus::ProposerFactory { - client: service.client().clone(), - transaction_pool: service.transaction_pool().clone(), - network: consensus_net, - force_delay: 0, - handle: dummy_runtime.executor(), - }; - let (proposer, _, _) = proposer_factory.init(&parent_header, &validators, alice.clone()).unwrap(); - let block = proposer.propose().expect("Error making test block"); - BlockImportParams { - origin: BlockOrigin::File, - justification: Vec::new(), - internal_justification: Vec::new(), - finalized: false, - body: Some(block.extrinsics), - storage_changes: None, - header: block.header, - auxiliary: Vec::new(), - } - }; - let extrinsic_factory = - |service: &SyncService<::FullService>| - { - let payload = ( - 0, - Call::Balances(BalancesCall::transfer(RawAddress::Id(bob.public().0.into()), 69.into())), - Era::immortal(), - service.client().genesis_hash() - ); - let signature = alice.sign(&payload.encode()).into(); - let id = alice.public().0.into(); - let xt = UncheckedExtrinsic { - signature: Some((RawAddress::Id(id), signature, payload.0, Era::immortal())), - function: payload.1, - }.encode(); - let v: Vec = Decode::decode(&mut xt.as_slice()).unwrap(); - OpaqueExtrinsic(v) - }; - sc_service_test::sync( - sc_chain_spec::integration_test_config(), - |config| new_full(config), - |mut config| new_light(config), - block_factory, - extrinsic_factory, - ); - } - #[test] // It is "ignored", but the node-cli ignored tests are running on the CI. // This can be run locally with `cargo test --release -p node-cli test_sync -- --ignored`. @@ -496,14 +499,25 @@ mod tests { chain_spec, |config| { let mut setup_handles = None; - new_full!(config, | - block_import: &sc_consensus_babe::BabeBlockImport, - babe_link: &sc_consensus_babe::BabeLink, - | { - setup_handles = Some((block_import.clone(), babe_link.clone())); - }).map(move |(node, x)| (node, (x, setup_handles.unwrap()))) + let (keep_alive, inherent_data_providers, client, network, transaction_pool) = + new_full_base(config, + | + block_import: &sc_consensus_babe::BabeBlockImport, + babe_link: &sc_consensus_babe::BabeLink, + | { + setup_handles = Some((block_import.clone(), babe_link.clone())); + } + )?; + + let node = sc_service_test::TestNetComponents::new( + keep_alive, client, network, transaction_pool + ); + Ok((node, (inherent_data_providers, setup_handles.unwrap()))) + }, + |config| { + let (keep_alive, _, client, network, transaction_pool) = new_light_base(config)?; + Ok(sc_service_test::TestNetComponents::new(keep_alive, client, network, transaction_pool)) }, - |config| new_light(config), |service, &mut (ref inherent_data_providers, (ref mut block_import, ref babe_link))| { let mut inherent_data = inherent_data_providers .create_inherent_data() @@ -519,8 +533,8 @@ mod tests { service.transaction_pool().maintain( ChainEvent::NewBlock { is_new_best: true, - id: parent_id.clone(), - retracted: vec![], + hash: parent_header.hash(), + tree_route: None, header: parent_header.clone(), }, ) @@ -528,7 +542,8 @@ mod tests { let mut proposer_factory = sc_basic_authorship::ProposerFactory::new( service.client(), - service.transaction_pool() + service.transaction_pool(), + None, ); let epoch_descriptor = babe_link.epoch_changes().lock().epoch_descriptor_for_child_of( @@ -598,46 +613,48 @@ mod tests { 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().chain_info().best_number); - let version = service.client().runtime_version_at(&best_block_id).unwrap().spec_version; + let (spec_version, transaction_version) = { + let version = service.client().runtime_version_at(&best_block_id).unwrap(); + (version.spec_version, version.transaction_version) + }; let signer = charlie.clone(); let function = Call::Balances(BalancesCall::transfer(to.into(), amount)); - let check_version = frame_system::CheckVersion::new(); + let check_spec_version = frame_system::CheckSpecVersion::new(); + let check_tx_version = frame_system::CheckTxVersion::new(); let check_genesis = frame_system::CheckGenesis::new(); let check_era = frame_system::CheckEra::from(Era::Immortal); let check_nonce = frame_system::CheckNonce::from(index); let check_weight = frame_system::CheckWeight::new(); let payment = pallet_transaction_payment::ChargeTransactionPayment::from(0); + let validate_grandpa_equivocation = pallet_grandpa::ValidateEquivocationReport::new(); let extra = ( - check_version, + check_spec_version, + check_tx_version, check_genesis, check_era, check_nonce, check_weight, payment, - Default::default(), - Default::default(), + validate_grandpa_equivocation, ); let raw_payload = SignedPayload::from_raw( function, extra, - (version, genesis_hash, genesis_hash, (), (), (), (), ()) + (spec_version, transaction_version, genesis_hash, genesis_hash, (), (), (), ()) ); let signature = raw_payload.using_encoded(|payload| { signer.sign(payload) }); let (function, extra, _) = raw_payload.deconstruct(); - let xt = UncheckedExtrinsic::new_signed( + index += 1; + UncheckedExtrinsic::new_signed( function, from.into(), signature.into(), extra, - ).encode(); - let v: Vec = Decode::decode(&mut xt.as_slice()).unwrap(); - - index += 1; - OpaqueExtrinsic(v) + ).into() }, ); } @@ -647,8 +664,14 @@ mod tests { fn test_consensus() { sc_service_test::consensus( crate::chain_spec::tests::integration_test_config_with_two_authorities(), - |config| new_full(config), - |config| new_light(config), + |config| { + let (keep_alive, _, client, network, transaction_pool) = new_full_base(config, |_, _| ())?; + Ok(sc_service_test::TestNetComponents::new(keep_alive, client, network, transaction_pool)) + }, + |config| { + let (keep_alive, _, client, network, transaction_pool) = new_light_base(config)?; + Ok(sc_service_test::TestNetComponents::new(keep_alive, client, network, transaction_pool)) + }, vec![ "//Alice".into(), "//Bob".into(), diff --git a/bin/node/cli/tests/build_spec_works.rs b/bin/node/cli/tests/build_spec_works.rs index 2eca71a5b5978de1e1de20873b6584a7d5c703b0..800a4a8c51e6175e2eb8fbfb1e5ddf375d30c264 100644 --- a/bin/node/cli/tests/build_spec_works.rs +++ b/bin/node/cli/tests/build_spec_works.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use assert_cmd::cargo::cargo_bin; use std::process::Command; diff --git a/bin/node/cli/tests/check_block_works.rs b/bin/node/cli/tests/check_block_works.rs index 6bfb82a8bfafb84c1b041b87dc093e2481193ec5..34078b08cf074f218865df548ee20b3b94f19d74 100644 --- a/bin/node/cli/tests/check_block_works.rs +++ b/bin/node/cli/tests/check_block_works.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . #![cfg(unix)] @@ -20,7 +22,7 @@ use assert_cmd::cargo::cargo_bin; use std::process::Command; use tempfile::tempdir; -mod common; +pub mod common; #[test] fn check_block_works() { diff --git a/bin/node/cli/tests/common.rs b/bin/node/cli/tests/common.rs index 34e371195c16b20e216a9426f238ce6b78bcd257..61a07dd1ca877c8814169f2babdfccd3a506ec76 100644 --- a/bin/node/cli/tests/common.rs +++ b/bin/node/cli/tests/common.rs @@ -1,21 +1,22 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . #![cfg(unix)] -#![allow(dead_code)] use std::{process::{Child, ExitStatus}, thread, time::Duration, path::Path}; use assert_cmd::cargo::cargo_bin; diff --git a/bin/node/cli/tests/export_import_flow.rs b/bin/node/cli/tests/export_import_flow.rs new file mode 100644 index 0000000000000000000000000000000000000000..557e722ddb7b505a13fa8daa8361838dcfd93c45 --- /dev/null +++ b/bin/node/cli/tests/export_import_flow.rs @@ -0,0 +1,212 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#![cfg(unix)] + +use assert_cmd::cargo::cargo_bin; +use std::{process::Command, fs, path::PathBuf}; +use tempfile::{tempdir, TempDir}; +use regex::Regex; + +pub mod common; + +fn contains_error(logged_output: &str) -> bool { + logged_output.contains("Error") +} + +/// Helper struct to execute the export/import/revert tests. +/// The fields are paths to a temporary directory +struct ExportImportRevertExecutor<'a> { + base_path: &'a TempDir, + exported_blocks_file: &'a PathBuf, + db_path: &'a PathBuf, + num_exported_blocks: Option, +} + +/// Format options for export / import commands. +enum FormatOpt { + Json, + Binary, +} + +/// Command corresponding to the different commands we would like to run. +enum SubCommand { + ExportBlocks, + ImportBlocks, +} + +impl ToString for SubCommand { + fn to_string(&self) -> String { + match self { + SubCommand::ExportBlocks => String::from("export-blocks"), + SubCommand::ImportBlocks => String::from("import-blocks"), + } + } +} + +impl<'a> ExportImportRevertExecutor<'a> { + fn new( + base_path: &'a TempDir, + exported_blocks_file: &'a PathBuf, + db_path: &'a PathBuf + ) -> Self { + Self { + base_path, + exported_blocks_file, + db_path, + num_exported_blocks: None, + } + } + + /// Helper method to run a command. Returns a string corresponding to what has been logged. + fn run_block_command(&self, + sub_command: SubCommand, + format_opt: FormatOpt, + expected_to_fail: bool + ) -> String { + let sub_command_str = sub_command.to_string(); + // Adding "--binary" if need be. + let arguments: Vec<&str> = match format_opt { + FormatOpt::Binary => vec![&sub_command_str, "--dev", "--pruning", "archive", "--binary", "-d"], + FormatOpt::Json => vec![&sub_command_str, "--dev", "--pruning", "archive", "-d"], + }; + + let tmp: TempDir; + // Setting base_path to be a temporary folder if we are importing blocks. + // This allows us to make sure we are importing from scratch. + let base_path = match sub_command { + SubCommand::ExportBlocks => &self.base_path.path(), + SubCommand::ImportBlocks => { + tmp = tempdir().unwrap(); + tmp.path() + } + }; + + // Running the command and capturing the output. + let output = Command::new(cargo_bin("substrate")) + .args(&arguments) + .arg(&base_path) + .arg(&self.exported_blocks_file) + .output() + .unwrap(); + + let logged_output = String::from_utf8_lossy(&output.stderr).to_string(); + + if expected_to_fail { + // Checking that we did indeed find an error. + assert!(contains_error(&logged_output), "expected to error but did not error!"); + assert!(!output.status.success()); + } else { + // Making sure no error were logged. + assert!(!contains_error(&logged_output), "expected not to error but error'd!"); + assert!(output.status.success()); + } + + logged_output + } + + /// Runs the `export-blocks` command. + fn run_export(&mut self, fmt_opt: FormatOpt) { + let log = self.run_block_command(SubCommand::ExportBlocks, fmt_opt, false); + + // Using regex to find out how many block we exported. + let re = Regex::new(r"Exporting blocks from #\d* to #(?P\d*)").unwrap(); + let caps = re.captures(&log).unwrap(); + // Saving the number of blocks we've exported for further use. + self.num_exported_blocks = Some(caps["exported_blocks"].parse::().unwrap()); + + let metadata = fs::metadata(&self.exported_blocks_file).unwrap(); + assert!(metadata.len() > 0, "file exported_blocks should not be empty"); + + let _ = fs::remove_dir_all(&self.db_path); + } + + /// Runs the `import-blocks` command, asserting that an error was found or + /// not depending on `expected_to_fail`. + fn run_import(&mut self, fmt_opt: FormatOpt, expected_to_fail: bool) { + let log = self.run_block_command(SubCommand::ImportBlocks, fmt_opt, expected_to_fail); + + if !expected_to_fail { + // Using regex to find out how much block we imported, + // and what's the best current block. + let re = Regex::new(r"Imported (?P\d*) blocks. Best: #(?P\d*)").unwrap(); + let caps = re.captures(&log).expect("capture should have succeeded"); + let imported = caps["imported"].parse::().unwrap(); + let best = caps["best"].parse::().unwrap(); + + assert_eq!( + imported, + best, + "numbers of blocks imported and best number differs" + ); + assert_eq!( + best, + self.num_exported_blocks.expect("number of exported blocks cannot be None; qed"), + "best block number and number of expected blocks should not differ" + ); + } + self.num_exported_blocks = None; + } + + /// Runs the `revert` command. + fn run_revert(&self) { + let output = Command::new(cargo_bin("substrate")) + .args(&["revert", "--dev", "--pruning", "archive", "-d"]) + .arg(&self.base_path.path()) + .output() + .unwrap(); + + let logged_output = String::from_utf8_lossy(&output.stderr).to_string(); + + // Reverting should not log any error. + assert!(!contains_error(&logged_output)); + // Command should never fail. + assert!(output.status.success()); + } + + /// Helper function that runs the whole export / import / revert flow and checks for errors. + fn run(&mut self, export_fmt: FormatOpt, import_fmt: FormatOpt, expected_to_fail: bool) { + self.run_export(export_fmt); + self.run_import(import_fmt, expected_to_fail); + self.run_revert(); + } +} + +#[test] +fn export_import_revert() { + let base_path = tempdir().expect("could not create a temp dir"); + let exported_blocks_file = base_path.path().join("exported_blocks"); + let db_path = base_path.path().join("db"); + + common::run_dev_node_for_a_while(base_path.path()); + + let mut executor = ExportImportRevertExecutor::new( + &base_path, + &exported_blocks_file, + &db_path, + ); + + // Binary and binary should work. + executor.run(FormatOpt::Binary, FormatOpt::Binary, false); + // Binary and JSON should fail. + executor.run(FormatOpt::Binary, FormatOpt::Json, true); + // JSON and JSON should work. + executor.run(FormatOpt::Json, FormatOpt::Json, false); + // JSON and binary should fail. + executor.run(FormatOpt::Json, FormatOpt::Binary, true); +} diff --git a/bin/node/cli/tests/import_export_and_revert_work.rs b/bin/node/cli/tests/import_export_and_revert_work.rs deleted file mode 100644 index 131265e3b4ab9bd868b9728bca6cda558d2982f2..0000000000000000000000000000000000000000 --- a/bin/node/cli/tests/import_export_and_revert_work.rs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2020 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(unix)] - -use assert_cmd::cargo::cargo_bin; -use std::{process::Command, fs}; -use tempfile::tempdir; - -mod common; - -#[test] -fn import_export_and_revert_work() { - let base_path = tempdir().expect("could not create a temp dir"); - let exported_blocks = base_path.path().join("exported_blocks"); - - common::run_dev_node_for_a_while(base_path.path()); - - let status = Command::new(cargo_bin("substrate")) - .args(&["export-blocks", "--dev", "--pruning", "archive", "-d"]) - .arg(base_path.path()) - .arg(&exported_blocks) - .status() - .unwrap(); - assert!(status.success()); - - let metadata = fs::metadata(&exported_blocks).unwrap(); - assert!(metadata.len() > 0, "file exported_blocks should not be empty"); - - let _ = fs::remove_dir_all(base_path.path().join("db")); - - let status = Command::new(cargo_bin("substrate")) - .args(&["import-blocks", "--dev", "--pruning", "archive", "-d"]) - .arg(base_path.path()) - .arg(&exported_blocks) - .status() - .unwrap(); - assert!(status.success()); - - let status = Command::new(cargo_bin("substrate")) - .args(&["revert", "--dev", "--pruning", "archive", "-d"]) - .arg(base_path.path()) - .status() - .unwrap(); - assert!(status.success()); -} diff --git a/bin/node/cli/tests/inspect_works.rs b/bin/node/cli/tests/inspect_works.rs index 441b08ccf46da1b1ef70ec49a7a46015d94f3c4c..aa9653acadba5a1db8ccd295da9d802967604a77 100644 --- a/bin/node/cli/tests/inspect_works.rs +++ b/bin/node/cli/tests/inspect_works.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . #![cfg(unix)] @@ -20,7 +22,7 @@ use assert_cmd::cargo::cargo_bin; use std::process::Command; use tempfile::tempdir; -mod common; +pub mod common; #[test] fn inspect_works() { diff --git a/bin/node/cli/tests/purge_chain_works.rs b/bin/node/cli/tests/purge_chain_works.rs index 020259d0c595a57a01b8a9b113522d826e1de912..001bed8b136f5d2349f83fe86c557466f0b7a7ca 100644 --- a/bin/node/cli/tests/purge_chain_works.rs +++ b/bin/node/cli/tests/purge_chain_works.rs @@ -1,24 +1,26 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use assert_cmd::cargo::cargo_bin; use std::process::Command; use tempfile::tempdir; -mod common; +pub mod common; #[test] #[cfg(unix)] diff --git a/bin/node/cli/tests/running_the_node_and_interrupt.rs b/bin/node/cli/tests/running_the_node_and_interrupt.rs index 67efedccbe771a65e892b5dbe94bac702d3c01ce..bd79dcd77a49a9e6a81b28ae360ef90b3174b565 100644 --- a/bin/node/cli/tests/running_the_node_and_interrupt.rs +++ b/bin/node/cli/tests/running_the_node_and_interrupt.rs @@ -1,24 +1,26 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use assert_cmd::cargo::cargo_bin; use std::{convert::TryInto, process::Command, thread, time::Duration}; use tempfile::tempdir; -mod common; +pub mod common; #[test] #[cfg(unix)] diff --git a/bin/node/cli/tests/temp_base_path_works.rs b/bin/node/cli/tests/temp_base_path_works.rs new file mode 100644 index 0000000000000000000000000000000000000000..9351568d87955b130bdde3d9f82f5ce977bc2b20 --- /dev/null +++ b/bin/node/cli/tests/temp_base_path_works.rs @@ -0,0 +1,72 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#![cfg(unix)] + +use assert_cmd::cargo::cargo_bin; +use nix::sys::signal::{kill, Signal::SIGINT}; +use nix::unistd::Pid; +use regex::Regex; +use std::convert::TryInto; +use std::io::Read; +use std::path::PathBuf; +use std::process::{Command, Stdio}; +use std::thread; +use std::time::Duration; + +pub mod common; + +#[test] +fn temp_base_path_works() { + let mut cmd = Command::new(cargo_bin("substrate")); + + let mut cmd = cmd + .args(&["--dev", "--tmp"]) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .unwrap(); + + // Let it produce some blocks. + thread::sleep(Duration::from_secs(30)); + assert!( + cmd.try_wait().unwrap().is_none(), + "the process should still be running" + ); + + // Stop the process + kill(Pid::from_raw(cmd.id().try_into().unwrap()), SIGINT).unwrap(); + assert!(common::wait_for(&mut cmd, 40) + .map(|x| x.success()) + .unwrap_or_default()); + + // Ensure the database has been deleted + let mut stderr = String::new(); + cmd.stderr.unwrap().read_to_string(&mut stderr).unwrap(); + let re = Regex::new(r"Database: .+ at (\S+)").unwrap(); + let db_path = PathBuf::from( + re.captures(stderr.as_str()) + .unwrap() + .get(1) + .unwrap() + .as_str() + .to_string(), + ); + + assert!(!db_path.exists()); +} diff --git a/bin/node/cli/tests/version.rs b/bin/node/cli/tests/version.rs new file mode 100644 index 0000000000000000000000000000000000000000..c5240257f16dea779fa78f75fafd77df75cce08e --- /dev/null +++ b/bin/node/cli/tests/version.rs @@ -0,0 +1,85 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use assert_cmd::cargo::cargo_bin; +use platforms::*; +use regex::Regex; +use std::process::Command; + +fn expected_regex() -> Regex { + Regex::new(r"^substrate (\d+\.\d+\.\d+(?:-.+?)?)-([a-f\d]+|unknown-commit)-(.+?)-(.+?)(?:-(.+))?$").unwrap() +} + +#[test] +fn version_is_full() { + let expected = expected_regex(); + let output = Command::new(cargo_bin("substrate")) + .args(&["--version"]) + .output() + .unwrap(); + + assert!( + output.status.success(), + "command returned with non-success exit code" + ); + + let output = String::from_utf8_lossy(&output.stdout).trim().to_owned(); + let captures = expected + .captures(output.as_str()) + .expect("could not parse version in output"); + + assert_eq!(&captures[1], env!("CARGO_PKG_VERSION")); + assert_eq!(&captures[3], TARGET_ARCH.as_str()); + assert_eq!(&captures[4], TARGET_OS.as_str()); + assert_eq!( + captures.get(5).map(|x| x.as_str()), + TARGET_ENV.map(|x| x.as_str()) + ); +} + +#[test] +fn test_regex_matches_properly() { + let expected = expected_regex(); + + let captures = expected + .captures("substrate 2.0.0-da487d19d-x86_64-linux-gnu") + .unwrap(); + assert_eq!(&captures[1], "2.0.0"); + assert_eq!(&captures[2], "da487d19d"); + assert_eq!(&captures[3], "x86_64"); + assert_eq!(&captures[4], "linux"); + assert_eq!(captures.get(5).map(|x| x.as_str()), Some("gnu")); + + let captures = expected + .captures("substrate 2.0.0-alpha.5-da487d19d-x86_64-linux-gnu") + .unwrap(); + assert_eq!(&captures[1], "2.0.0-alpha.5"); + assert_eq!(&captures[2], "da487d19d"); + assert_eq!(&captures[3], "x86_64"); + assert_eq!(&captures[4], "linux"); + assert_eq!(captures.get(5).map(|x| x.as_str()), Some("gnu")); + + let captures = expected + .captures("substrate 2.0.0-alpha.5-da487d19d-x86_64-linux") + .unwrap(); + assert_eq!(&captures[1], "2.0.0-alpha.5"); + assert_eq!(&captures[2], "da487d19d"); + assert_eq!(&captures[3], "x86_64"); + assert_eq!(&captures[4], "linux"); + assert_eq!(captures.get(5).map(|x| x.as_str()), None); +} diff --git a/bin/node/executor/Cargo.toml b/bin/node/executor/Cargo.toml index 2f1060a99884505ba94f1692f493bf8cdb01f43a..900f0cad4327ee8cd015b581b8bcba600dfba28e 100644 --- a/bin/node/executor/Cargo.toml +++ b/bin/node/executor/Cargo.toml @@ -1,43 +1,46 @@ [package] name = "node-executor" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] description = "Substrate node implementation in Rust." edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0" } -node-primitives = { version = "2.0.0-alpha.5", path = "../primitives" } -node-runtime = { version = "2.0.0-alpha.5", path = "../runtime" } -sc-executor = { version = "0.8.0-alpha.5", path = "../../../client/executor" } -sp-core = { version = "2.0.0-alpha.5", path = "../../../primitives/core" } -sp-io = { version = "2.0.0-alpha.5", path = "../../../primitives/io" } -sp-state-machine = { version = "0.8.0-alpha.5", path = "../../../primitives/state-machine" } -sp-trie = { version = "2.0.0-alpha.5", path = "../../../primitives/trie" } +codec = { package = "parity-scale-codec", version = "1.3.1" } +node-primitives = { version = "2.0.0-rc4", path = "../primitives" } +node-runtime = { version = "2.0.0-rc4", path = "../runtime" } +sc-executor = { version = "0.8.0-rc4", path = "../../../client/executor" } +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } +sp-io = { version = "2.0.0-rc4", path = "../../../primitives/io" } +sp-state-machine = { version = "0.8.0-rc4", path = "../../../primitives/state-machine" } +sp-trie = { version = "2.0.0-rc4", path = "../../../primitives/trie" } trie-root = "0.16.0" -frame-benchmarking = { version = "2.0.0-alpha.5", path = "../../../frame/benchmarking" } +frame-benchmarking = { version = "2.0.0-rc4", path = "../../../frame/benchmarking" } [dev-dependencies] criterion = "0.3.0" -frame-support = { version = "2.0.0-alpha.5", path = "../../../frame/support" } -frame-system = { version = "2.0.0-alpha.5", path = "../../../frame/system" } -node-testing = { version = "2.0.0-alpha.5", path = "../testing" } -pallet-balances = { version = "2.0.0-alpha.5", path = "../../../frame/balances" } -pallet-contracts = { version = "2.0.0-alpha.5", path = "../../../frame/contracts" } -pallet-grandpa = { version = "2.0.0-alpha.5", path = "../../../frame/grandpa" } -pallet-im-online = { version = "2.0.0-alpha.5", path = "../../../frame/im-online" } -pallet-indices = { version = "2.0.0-alpha.5", path = "../../../frame/indices" } -pallet-session = { version = "2.0.0-alpha.5", path = "../../../frame/session" } -pallet-timestamp = { version = "2.0.0-alpha.5", path = "../../../frame/timestamp" } -pallet-transaction-payment = { version = "2.0.0-alpha.5", path = "../../../frame/transaction-payment" } -pallet-treasury = { version = "2.0.0-alpha.5", path = "../../../frame/treasury" } -sp-application-crypto = { version = "2.0.0-alpha.5", path = "../../../primitives/application-crypto" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime" } -sp-externalities = { version = "0.8.0-alpha.5", path = "../../../primitives/externalities" } -substrate-test-client = { version = "2.0.0-dev", path = "../../../test-utils/client" } +frame-support = { version = "2.0.0-rc4", path = "../../../frame/support" } +frame-system = { version = "2.0.0-rc4", path = "../../../frame/system" } +node-testing = { version = "2.0.0-rc4", path = "../testing" } +pallet-balances = { version = "2.0.0-rc4", path = "../../../frame/balances" } +pallet-contracts = { version = "2.0.0-rc4", path = "../../../frame/contracts" } +pallet-grandpa = { version = "2.0.0-rc4", path = "../../../frame/grandpa" } +pallet-im-online = { version = "2.0.0-rc4", path = "../../../frame/im-online" } +pallet-indices = { version = "2.0.0-rc4", path = "../../../frame/indices" } +pallet-session = { version = "2.0.0-rc4", path = "../../../frame/session" } +pallet-timestamp = { version = "2.0.0-rc4", path = "../../../frame/timestamp" } +pallet-transaction-payment = { version = "2.0.0-rc4", path = "../../../frame/transaction-payment" } +pallet-treasury = { version = "2.0.0-rc4", path = "../../../frame/treasury" } +sp-application-crypto = { version = "2.0.0-rc4", path = "../../../primitives/application-crypto" } +sp-runtime = { version = "2.0.0-rc4", path = "../../../primitives/runtime" } +sp-externalities = { version = "0.8.0-rc4", path = "../../../primitives/externalities" } +substrate-test-client = { version = "2.0.0-rc4", path = "../../../test-utils/client" } wabt = "0.9.2" [features] @@ -52,6 +55,3 @@ stress-test = [] [[bench]] name = "bench" harness = false - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/bin/node/executor/benches/bench.rs b/bin/node/executor/benches/bench.rs index 4f335df90d1ba3b1eba376601c899ec77b0909b6..ad735c87661ca2aeb33a1ec889e983537ef30f63 100644 --- a/bin/node/executor/benches/bench.rs +++ b/bin/node/executor/benches/bench.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use codec::{Decode, Encode}; use criterion::{BatchSize, Criterion, criterion_group, criterion_main}; @@ -39,7 +40,9 @@ const COMPACT_CODE: &[u8] = node_runtime::WASM_BINARY; const GENESIS_HASH: [u8; 32] = [69u8; 32]; -const VERSION: u32 = node_runtime::VERSION.spec_version; +const TRANSACTION_VERSION: u32 = node_runtime::VERSION.transaction_version; + +const SPEC_VERSION: u32 = node_runtime::VERSION.spec_version; const HEAP_PAGES: u64 = 20; @@ -52,7 +55,7 @@ enum ExecutionMethod { } fn sign(xt: CheckedExtrinsic) -> UncheckedExtrinsic { - node_testing::keyring::sign(xt, VERSION, GENESIS_HASH) + node_testing::keyring::sign(xt, SPEC_VERSION, TRANSACTION_VERSION, GENESIS_HASH) } fn new_test_ext(genesis_config: &GenesisConfig) -> TestExternalities { diff --git a/bin/node/executor/src/lib.rs b/bin/node/executor/src/lib.rs index bcc7f48507398cd0ea15319460f8d13e6058f2ec..4c3b82bc7d3b538234d470a5560ca61db28976b7 100644 --- a/bin/node/executor/src/lib.rs +++ b/bin/node/executor/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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. +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! A `CodeExecutor` specialization which uses natively compiled runtime when the wasm to be //! executed is equivalent to the natively compiled code. diff --git a/bin/node/executor/tests/basic.rs b/bin/node/executor/tests/basic.rs index 1ee0a17c81120ca32a7a9af2d704ce97699ee454..9ee7824e519826a3c0259517a6364047decd0c62 100644 --- a/bin/node/executor/tests/basic.rs +++ b/bin/node/executor/tests/basic.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use codec::{Encode, Decode, Joiner}; use frame_support::{ @@ -20,12 +21,10 @@ use frame_support::{ traits::Currency, weights::{GetDispatchInfo, DispatchInfo, DispatchClass}, }; -use sp_core::{ - NeverNativeValue, map, traits::Externalities, storage::{well_known_keys, Storage}, -}; +use sp_core::{NeverNativeValue, traits::Externalities, storage::well_known_keys}; use sp_runtime::{ - ApplyExtrinsicResult, Fixed64, - traits::{Hash as HashT, Convert, BlakeTwo256}, + ApplyExtrinsicResult, + traits::Hash as HashT, transaction_validity::InvalidTransaction, }; use pallet_contracts::ContractAddressFor; @@ -33,7 +32,7 @@ use frame_system::{self, EventRecord, Phase}; use node_runtime::{ Header, Block, UncheckedExtrinsic, CheckedExtrinsic, Call, Runtime, Balances, - System, TransactionPayment, Event, TransactionBaseFee, TransactionByteFee, + System, TransactionPayment, Event, constants::currency::*, }; use node_primitives::{Balance, Hash}; @@ -50,16 +49,17 @@ use self::common::{*, sign}; /// test code paths that differ between native and wasm versions. pub const BLOATY_CODE: &[u8] = node_runtime::WASM_BINARY_BLOATY; -/// Default transfer fee -fn transfer_fee(extrinsic: &E, fee_multiplier: Fixed64) -> Balance { - let length_fee = TransactionByteFee::get() * (extrinsic.encode().len() as Balance); - - let weight = default_transfer_call().get_dispatch_info().weight; - let weight_fee = - ::WeightToFee::convert(weight); - - let base_fee = TransactionBaseFee::get(); - base_fee + fee_multiplier.saturated_multiply_accumulate(length_fee + weight_fee) +/// Default transfer fee. This will use the same logic that is implemented in transaction-payment module. +/// +/// Note that reads the multiplier from storage directly, hence to get the fee of `extrinsic` +/// at block `n`, it must be called prior to executing block `n` to do the calculation with the +/// correct multiplier. +fn transfer_fee(extrinsic: &E) -> Balance { + TransactionPayment::compute_fee( + extrinsic.encode().len() as u32, + &default_transfer_call().get_dispatch_info(), + 0, + ) } fn xt() -> UncheckedExtrinsic { @@ -158,20 +158,13 @@ fn block_with_size(time: u64, nonce: u32, size: usize) -> (Vec, Hash) { #[test] fn panic_execution_with_foreign_code_gives_error() { - let mut t = TestExternalities::::new_with_code(BLOATY_CODE, Storage { - top: map![ - >::hashed_key_for(alice()) => { - (69u128, 0u8, 0u128, 0u128, 0u128).encode() - }, - >::hashed_key().to_vec() => { - 69_u128.encode() - }, - >::hashed_key_for(0) => { - vec![0u8; 32] - } - ], - children: map![], - }); + let mut t = new_test_ext(BLOATY_CODE, false); + t.insert( + >::hashed_key_for(alice()), + (69u128, 0u8, 0u128, 0u128, 0u128).encode() + ); + t.insert(>::hashed_key().to_vec(), 69_u128.encode()); + t.insert(>::hashed_key_for(0), vec![0u8; 32]); let r = executor_call:: _>( &mut t, @@ -194,20 +187,13 @@ fn panic_execution_with_foreign_code_gives_error() { #[test] fn bad_extrinsic_with_native_equivalent_code_gives_error() { - let mut t = TestExternalities::::new_with_code(COMPACT_CODE, Storage { - top: map![ - >::hashed_key_for(alice()) => { - (0u32, 0u8, 69u128, 0u128, 0u128, 0u128).encode() - }, - >::hashed_key().to_vec() => { - 69_u128.encode() - }, - >::hashed_key_for(0) => { - vec![0u8; 32] - } - ], - children: map![], - }); + let mut t = new_test_ext(COMPACT_CODE, false); + t.insert( + >::hashed_key_for(alice()), + (0u32, 0u8, 69u128, 0u128, 0u128, 0u128).encode() + ); + t.insert(>::hashed_key().to_vec(), 69_u128.encode()); + t.insert(>::hashed_key_for(0), vec![0u8; 32]); let r = executor_call:: _>( &mut t, @@ -230,18 +216,20 @@ fn bad_extrinsic_with_native_equivalent_code_gives_error() { #[test] fn successful_execution_with_native_equivalent_code_gives_ok() { - let mut t = TestExternalities::::new_with_code(COMPACT_CODE, Storage { - top: map![ - >::hashed_key_for(alice()) => { - (0u32, 0u8, 111 * DOLLARS, 0u128, 0u128, 0u128).encode() - }, - >::hashed_key().to_vec() => { - (111 * DOLLARS).encode() - }, - >::hashed_key_for(0) => vec![0u8; 32] - ], - children: map![], - }); + let mut t = new_test_ext(COMPACT_CODE, false); + t.insert( + >::hashed_key_for(alice()), + (0u32, 0u8, 111 * DOLLARS, 0u128, 0u128, 0u128).encode() + ); + t.insert( + >::hashed_key_for(bob()), + (0u32, 0u8, 0 * DOLLARS, 0u128, 0u128, 0u128).encode() + ); + t.insert( + >::hashed_key().to_vec(), + (111 * DOLLARS).encode() + ); + t.insert(>::hashed_key_for(0), vec![0u8; 32]); let r = executor_call:: _>( &mut t, @@ -252,7 +240,7 @@ fn successful_execution_with_native_equivalent_code_gives_ok() { ).0; assert!(r.is_ok()); - let fm = t.execute_with(TransactionPayment::next_fee_multiplier); + let fees = t.execute_with(|| transfer_fee(&xt())); let r = executor_call:: _>( &mut t, @@ -264,7 +252,6 @@ fn successful_execution_with_native_equivalent_code_gives_ok() { assert!(r.is_ok()); t.execute_with(|| { - let fees = transfer_fee(&xt(), fm); assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - fees); assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS); }); @@ -272,18 +259,20 @@ fn successful_execution_with_native_equivalent_code_gives_ok() { #[test] fn successful_execution_with_foreign_code_gives_ok() { - let mut t = TestExternalities::::new_with_code(BLOATY_CODE, Storage { - top: map![ - >::hashed_key_for(alice()) => { - (0u32, 0u8, 111 * DOLLARS, 0u128, 0u128, 0u128).encode() - }, - >::hashed_key().to_vec() => { - (111 * DOLLARS).encode() - }, - >::hashed_key_for(0) => vec![0u8; 32] - ], - children: map![], - }); + let mut t = new_test_ext(BLOATY_CODE, false); + t.insert( + >::hashed_key_for(alice()), + (0u32, 0u8, 111 * DOLLARS, 0u128, 0u128, 0u128).encode() + ); + t.insert( + >::hashed_key_for(bob()), + (0u32, 0u8, 0 * DOLLARS, 0u128, 0u128, 0u128).encode() + ); + t.insert( + >::hashed_key().to_vec(), + (111 * DOLLARS).encode() + ); + t.insert(>::hashed_key_for(0), vec![0u8; 32]); let r = executor_call:: _>( &mut t, @@ -294,7 +283,7 @@ fn successful_execution_with_foreign_code_gives_ok() { ).0; assert!(r.is_ok()); - let fm = t.execute_with(TransactionPayment::next_fee_multiplier); + let fees = t.execute_with(|| transfer_fee(&xt())); let r = executor_call:: _>( &mut t, @@ -306,7 +295,6 @@ fn successful_execution_with_foreign_code_gives_ok() { assert!(r.is_ok()); t.execute_with(|| { - let fees = transfer_fee(&xt(), fm); assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - fees); assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS); }); @@ -319,7 +307,7 @@ fn full_native_block_import_works() { let (block1, block2) = blocks(); let mut alice_last_known_balance: Balance = Default::default(); - let mut fm = t.execute_with(TransactionPayment::next_fee_multiplier); + let mut fees = t.execute_with(|| transfer_fee(&xt())); executor_call:: _>( &mut t, @@ -330,23 +318,18 @@ fn full_native_block_import_works() { ).0.unwrap(); t.execute_with(|| { - let fees = transfer_fee(&xt(), fm); assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - fees); assert_eq!(Balances::total_balance(&bob()), 169 * DOLLARS); alice_last_known_balance = Balances::total_balance(&alice()); let events = vec![ EventRecord { phase: Phase::ApplyExtrinsic(0), + // timestamp set call with weight 8_000_000 + 2 read + 1 write event: Event::frame_system(frame_system::RawEvent::ExtrinsicSuccess( - DispatchInfo { weight: 10000, class: DispatchClass::Operational, pays_fee: true } + DispatchInfo { weight: 8_000_000 + 2 * 25_000_000 + 1 * 100_000_000, class: DispatchClass::Mandatory, ..Default::default() } )), topics: vec![], }, - EventRecord { - phase: Phase::ApplyExtrinsic(1), - event: Event::pallet_treasury(pallet_treasury::RawEvent::Deposit(fees * 8 / 10)), - topics: vec![], - }, EventRecord { phase: Phase::ApplyExtrinsic(1), event: Event::pallet_balances(pallet_balances::RawEvent::Transfer( @@ -358,8 +341,14 @@ fn full_native_block_import_works() { }, EventRecord { phase: Phase::ApplyExtrinsic(1), + event: Event::pallet_treasury(pallet_treasury::RawEvent::Deposit(fees * 8 / 10)), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(1), + // Balance Transfer 70_000_000 + 1 Read + 1 Write event: Event::frame_system(frame_system::RawEvent::ExtrinsicSuccess( - DispatchInfo { weight: 1000000, class: DispatchClass::Normal, pays_fee: true } + DispatchInfo { weight: 70_000_000 + 25_000_000 + 100_000_000, ..Default::default() } )), topics: vec![], }, @@ -367,7 +356,7 @@ fn full_native_block_import_works() { assert_eq!(System::events(), events); }); - fm = t.execute_with(TransactionPayment::next_fee_multiplier); + fees = t.execute_with(|| transfer_fee(&xt())); executor_call:: _>( &mut t, @@ -378,7 +367,6 @@ fn full_native_block_import_works() { ).0.unwrap(); t.execute_with(|| { - let fees = transfer_fee(&xt(), fm); assert_eq!( Balances::total_balance(&alice()), alice_last_known_balance - 10 * DOLLARS - fees, @@ -390,16 +378,12 @@ fn full_native_block_import_works() { let events = vec![ EventRecord { phase: Phase::ApplyExtrinsic(0), + // timestamp set call with weight 8_000_000 + 2 read + 1 write event: Event::frame_system(frame_system::RawEvent::ExtrinsicSuccess( - DispatchInfo { weight: 10000, class: DispatchClass::Operational, pays_fee: true } + DispatchInfo { weight: 8_000_000 + 2 * 25_000_000 + 1 * 100_000_000, class: DispatchClass::Mandatory, ..Default::default() } )), topics: vec![], }, - EventRecord { - phase: Phase::ApplyExtrinsic(1), - event: Event::pallet_treasury(pallet_treasury::RawEvent::Deposit(fees * 8 / 10)), - topics: vec![], - }, EventRecord { phase: Phase::ApplyExtrinsic(1), event: Event::pallet_balances( @@ -413,14 +397,15 @@ fn full_native_block_import_works() { }, EventRecord { phase: Phase::ApplyExtrinsic(1), - event: Event::frame_system(frame_system::RawEvent::ExtrinsicSuccess( - DispatchInfo { weight: 1000000, class: DispatchClass::Normal, pays_fee: true } - )), + event: Event::pallet_treasury(pallet_treasury::RawEvent::Deposit(fees * 8 / 10)), topics: vec![], }, EventRecord { - phase: Phase::ApplyExtrinsic(2), - event: Event::pallet_treasury(pallet_treasury::RawEvent::Deposit(fees * 8 / 10)), + phase: Phase::ApplyExtrinsic(1), + // Balance Transfer 70_000_000 + 1 Read + 1 Write + event: Event::frame_system(frame_system::RawEvent::ExtrinsicSuccess( + DispatchInfo { weight: 70_000_000 + 25_000_000 + 100_000_000, ..Default::default() } + )), topics: vec![], }, EventRecord { @@ -436,8 +421,14 @@ fn full_native_block_import_works() { }, EventRecord { phase: Phase::ApplyExtrinsic(2), + event: Event::pallet_treasury(pallet_treasury::RawEvent::Deposit(fees * 8 / 10)), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(2), + // Balance Transfer 70_000_000 + 1 Read + 1 Write event: Event::frame_system(frame_system::RawEvent::ExtrinsicSuccess( - DispatchInfo { weight: 1000000, class: DispatchClass::Normal, pays_fee: true } + DispatchInfo { weight: 70_000_000 + 25_000_000 + 100_000_000, ..Default::default() } )), topics: vec![], }, @@ -453,7 +444,7 @@ fn full_wasm_block_import_works() { let (block1, block2) = blocks(); let mut alice_last_known_balance: Balance = Default::default(); - let mut fm = t.execute_with(TransactionPayment::next_fee_multiplier); + let mut fees = t.execute_with(|| transfer_fee(&xt())); executor_call:: _>( &mut t, @@ -464,12 +455,12 @@ fn full_wasm_block_import_works() { ).0.unwrap(); t.execute_with(|| { - assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt(), fm)); + assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - fees); assert_eq!(Balances::total_balance(&bob()), 169 * DOLLARS); alice_last_known_balance = Balances::total_balance(&alice()); }); - fm = t.execute_with(TransactionPayment::next_fee_multiplier); + fees = t.execute_with(|| transfer_fee(&xt())); executor_call:: _>( &mut t, @@ -482,11 +473,11 @@ fn full_wasm_block_import_works() { t.execute_with(|| { assert_eq!( Balances::total_balance(&alice()), - alice_last_known_balance - 10 * DOLLARS - transfer_fee(&xt(), fm), + alice_last_known_balance - 10 * DOLLARS - fees, ); assert_eq!( Balances::total_balance(&bob()), - 179 * DOLLARS - 1 * transfer_fee(&xt(), fm), + 179 * DOLLARS - 1 * fees, ); }); } @@ -500,32 +491,31 @@ const CODE_TRANSFER: &str = r#" ;; value_ptr: u32, ;; value_len: u32, ;; input_data_ptr: u32, -;; input_data_len: u32 +;; input_data_len: u32, +;; output_ptr: u32, +;; output_len_ptr: u32 ;; ) -> u32 -(import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32))) -(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_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32))) +(import "env" "ext_input" (func $ext_input (param i32 i32))) (import "env" "memory" (memory 1 1)) (func (export "deploy") ) (func (export "call") (block $fail - ;; load and check the input data (which is stored in the scratch buffer). + ;; Load input data to contract memory + (call $ext_input + (i32.const 0) + (i32.const 52) + ) + ;; fail if the input size is not != 4 (br_if $fail (i32.ne (i32.const 4) - (call $ext_scratch_size) + (i32.load (i32.const 52)) ) ) - (call $ext_scratch_read - (i32.const 0) - (i32.const 0) - (i32.const 4) - ) - - (br_if $fail (i32.ne (i32.load8_u (i32.const 0)) @@ -560,6 +550,8 @@ const CODE_TRANSFER: &str = r#" (i32.const 16) ;; 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 4294967295) ;; u32 max value is the sentinel value: do not copy output + (i32.const 0) ;; Length is ignored in this case ) ) @@ -580,6 +572,8 @@ const CODE_TRANSFER: &str = r#" "\06\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00" "\00\00" ) +;; Length of the input buffer +(data (i32.const 52) "\04") ) "#; @@ -606,13 +600,18 @@ fn deploying_wasm_contract_should_work() { CheckedExtrinsic { signed: Some((charlie(), signed_extra(0, 0))), function: Call::Contracts( - pallet_contracts::Call::put_code::(10_000, transfer_code) + pallet_contracts::Call::put_code::(transfer_code) ), }, CheckedExtrinsic { signed: Some((charlie(), signed_extra(1, 0))), function: Call::Contracts( - pallet_contracts::Call::instantiate::(1 * DOLLARS, 10_000, transfer_ch, Vec::new()) + pallet_contracts::Call::instantiate::( + 1 * DOLLARS, + 500_000_000, + transfer_ch, + Vec::new() + ) ), }, CheckedExtrinsic { @@ -621,7 +620,7 @@ fn deploying_wasm_contract_should_work() { pallet_contracts::Call::call::( pallet_indices::address::Address::Id(addr.clone()), 10, - 10_000, + 500_000_000, vec![0x00, 0x01, 0x02, 0x03] ) ), @@ -697,15 +696,13 @@ fn native_big_block_import_fails_on_fallback() { #[test] fn panic_execution_gives_error() { - let mut t = TestExternalities::::new_with_code(BLOATY_CODE, Storage { - top: map![ - >::hashed_key().to_vec() => { - 0_u128.encode() - }, - >::hashed_key_for(0) => vec![0u8; 32] - ], - children: map![], - }); + let mut t = new_test_ext(BLOATY_CODE, false); + t.insert( + >::hashed_key_for(alice()), + (0u32, 0u8, 0 * DOLLARS, 0u128, 0u128, 0u128).encode() + ); + t.insert(>::hashed_key().to_vec(), 0_u128.encode()); + t.insert(>::hashed_key_for(0), vec![0u8; 32]); let r = executor_call:: _>( &mut t, @@ -728,18 +725,20 @@ fn panic_execution_gives_error() { #[test] fn successful_execution_gives_ok() { - let mut t = TestExternalities::::new_with_code(COMPACT_CODE, Storage { - top: map![ - >::hashed_key_for(alice()) => { - (0u32, 0u8, 111 * DOLLARS, 0u128, 0u128, 0u128).encode() - }, - >::hashed_key().to_vec() => { - (111 * DOLLARS).encode() - }, - >::hashed_key_for(0) => vec![0u8; 32] - ], - children: map![], - }); + let mut t = new_test_ext(COMPACT_CODE, false); + t.insert( + >::hashed_key_for(alice()), + (0u32, 0u8, 111 * DOLLARS, 0u128, 0u128, 0u128).encode() + ); + t.insert( + >::hashed_key_for(bob()), + (0u32, 0u8, 0 * DOLLARS, 0u128, 0u128, 0u128).encode() + ); + t.insert( + >::hashed_key().to_vec(), + (111 * DOLLARS).encode() + ); + t.insert(>::hashed_key_for(0), vec![0u8; 32]); let r = executor_call:: _>( &mut t, @@ -749,7 +748,12 @@ fn successful_execution_gives_ok() { None, ).0; assert!(r.is_ok()); - let fm = t.execute_with(TransactionPayment::next_fee_multiplier); + t.execute_with(|| { + assert_eq!(Balances::total_balance(&alice()), 111 * DOLLARS); + }); + + let fees = t.execute_with(|| transfer_fee(&xt())); + let r = executor_call:: _>( &mut t, "BlockBuilder_apply_extrinsic", @@ -763,7 +767,6 @@ fn successful_execution_gives_ok() { .expect("Extrinsic failed"); t.execute_with(|| { - let fees = transfer_fee(&xt(), fm); assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - fees); assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS); }); @@ -817,5 +820,3 @@ fn should_import_block_with_test_client() { client.import(BlockOrigin::Own, block).unwrap(); } - - diff --git a/bin/node/executor/tests/common.rs b/bin/node/executor/tests/common.rs index 6b6ef272f8a35bac1140e77ed1411adc52f0e8cf..9f4d9f71e72dd657fc328da40f48a267b9cde303 100644 --- a/bin/node/executor/tests/common.rs +++ b/bin/node/executor/tests/common.rs @@ -1,24 +1,36 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use codec::{Encode, Decode}; +use frame_system::offchain::AppCrypto; use frame_support::Hashable; use sp_state_machine::TestExternalities as CoreTestExternalities; -use sp_core::{NeverNativeValue, NativeOrEncoded, traits::{CodeExecutor, RuntimeCode}}; -use sp_runtime::{ApplyExtrinsicResult, traits::{Header as HeaderT, BlakeTwo256}}; +use sp_core::{ + NeverNativeValue, NativeOrEncoded, + crypto::KeyTypeId, + sr25519::Signature, + traits::{CodeExecutor, RuntimeCode}, +}; +use sp_runtime::{ + ApplyExtrinsicResult, + MultiSigner, + MultiSignature, + traits::{Header as HeaderT, BlakeTwo256}, +}; use sc_executor::{NativeExecutor, WasmExecutionMethod}; use sc_executor::error::Result; @@ -31,6 +43,25 @@ use node_primitives::{Hash, BlockNumber}; use node_testing::keyring::*; use sp_externalities::Externalities; +pub const TEST_KEY_TYPE_ID: KeyTypeId = KeyTypeId(*b"test"); + +pub mod sr25519 { + mod app_sr25519 { + use sp_application_crypto::{app_crypto, sr25519}; + use super::super::TEST_KEY_TYPE_ID; + app_crypto!(sr25519, TEST_KEY_TYPE_ID); + } + + pub type AuthorityId = app_sr25519::Public; +} + +pub struct TestAuthorityId; +impl AppCrypto for TestAuthorityId { + type RuntimeAppPublic = sr25519::AuthorityId; + type GenericSignature = Signature; + type GenericPublic = sp_core::sr25519::Public; +} + /// The wasm runtime code. /// /// `compact` since it is after post-processing with wasm-gc which performs tree-shaking thus @@ -41,12 +72,14 @@ pub const COMPACT_CODE: &[u8] = node_runtime::WASM_BINARY; pub const GENESIS_HASH: [u8; 32] = [69u8; 32]; -pub const VERSION: u32 = node_runtime::VERSION.spec_version; +pub const SPEC_VERSION: u32 = node_runtime::VERSION.spec_version; + +pub const TRANSACTION_VERSION: u32 = node_runtime::VERSION.transaction_version; pub type TestExternalities = CoreTestExternalities; pub fn sign(xt: CheckedExtrinsic) -> UncheckedExtrinsic { - node_testing::keyring::sign(xt, VERSION, GENESIS_HASH) + node_testing::keyring::sign(xt, SPEC_VERSION, TRANSACTION_VERSION, GENESIS_HASH) } pub fn default_transfer_call() -> pallet_balances::Call { diff --git a/bin/node/executor/tests/fees.rs b/bin/node/executor/tests/fees.rs index ea9d740a05ef86e77fa923c8863d55a984cdbca7..8f828263c5bdb5b17532caca29cebd935c8a7b3e 100644 --- a/bin/node/executor/tests/fees.rs +++ b/bin/node/executor/tests/fees.rs @@ -1,33 +1,33 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use codec::{Encode, Joiner}; use frame_support::{ StorageValue, StorageMap, traits::Currency, - weights::GetDispatchInfo, + weights::{GetDispatchInfo, constants::ExtrinsicBaseWeight, IdentityFee, WeightToFeePolynomial}, }; -use sp_core::{NeverNativeValue, map, storage::Storage}; -use sp_runtime::{Fixed64, Perbill, traits::{Convert, BlakeTwo256}}; +use sp_core::NeverNativeValue; +use sp_runtime::{Perbill, FixedPointNumber}; use node_runtime::{ - CheckedExtrinsic, Call, Runtime, Balances, TransactionPayment, TransactionBaseFee, - TransactionByteFee, WeightFeeCoefficient, + CheckedExtrinsic, Call, Runtime, Balances, TransactionPayment, Multiplier, + TransactionByteFee, constants::currency::*, }; -use node_runtime::impls::LinearWeightToFee; use node_primitives::Balance; use node_testing::keyring::*; @@ -38,8 +38,8 @@ use self::common::{*, sign}; fn fee_multiplier_increases_and_decreases_on_big_weight() { let mut t = new_test_ext(COMPACT_CODE, false); - // initial fee multiplier must be zero - let mut prev_multiplier = Fixed64::from_parts(0); + // initial fee multiplier must be one. + let mut prev_multiplier = Multiplier::one(); t.execute_with(|| { assert_eq!(TransactionPayment::next_fee_multiplier(), prev_multiplier); @@ -59,7 +59,7 @@ fn fee_multiplier_increases_and_decreases_on_big_weight() { }, CheckedExtrinsic { signed: Some((charlie(), signed_extra(0, 0))), - function: Call::System(frame_system::Call::fill_block(Perbill::from_percent(90))), + function: Call::System(frame_system::Call::fill_block(Perbill::from_percent(60))), } ] ); @@ -122,7 +122,7 @@ fn fee_multiplier_increases_and_decreases_on_big_weight() { } #[test] -fn transaction_fee_is_correct_ultimate() { +fn transaction_fee_is_correct() { // This uses the exact values of substrate-node. // // weight of transfer call as of now: 1_000_000 @@ -130,21 +130,20 @@ fn transaction_fee_is_correct_ultimate() { // - 1 MILLICENTS in substrate node. // - 1 milli-dot based on current polkadot runtime. // (this baed on assigning 0.1 CENT to the cheapest tx with `weight = 100`) - let mut t = TestExternalities::::new_with_code(COMPACT_CODE, Storage { - top: map![ - >::hashed_key_for(alice()) => { - (0u32, 0u8, 100 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS).encode() - }, - >::hashed_key_for(bob()) => { - (0u32, 0u8, 10 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS).encode() - }, - >::hashed_key().to_vec() => { - (110 * DOLLARS).encode() - }, - >::hashed_key_for(0) => vec![0u8; 32] - ], - children: map![], - }); + let mut t = new_test_ext(COMPACT_CODE, false); + t.insert( + >::hashed_key_for(alice()), + (0u32, 0u8, 100 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS).encode() + ); + t.insert( + >::hashed_key_for(bob()), + (0u32, 0u8, 10 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS).encode() + ); + t.insert( + >::hashed_key().to_vec(), + (110 * DOLLARS).encode() + ); + t.insert(>::hashed_key_for(0), vec![0u8; 32]); let tip = 1_000_000; let xt = sign(CheckedExtrinsic { @@ -173,22 +172,27 @@ fn transaction_fee_is_correct_ultimate() { t.execute_with(|| { assert_eq!(Balances::total_balance(&bob()), (10 + 69) * DOLLARS); // Components deducted from alice's balances: + // - Base fee // - Weight fee // - Length fee // - Tip // - Creation-fee of bob's account. let mut balance_alice = (100 - 69) * DOLLARS; - let length_fee = TransactionBaseFee::get() + - TransactionByteFee::get() * - (xt.clone().encode().len() as Balance); + let base_weight = ExtrinsicBaseWeight::get(); + let base_fee = IdentityFee::::calc(&base_weight); + + let length_fee = TransactionByteFee::get() * (xt.clone().encode().len() as Balance); balance_alice -= length_fee; let weight = default_transfer_call().get_dispatch_info().weight; - let weight_fee = LinearWeightToFee::::convert(weight); + let weight_fee = IdentityFee::::calc(&weight); // we know that weight to fee multiplier is effect-less in block 1. - assert_eq!(weight_fee as Balance, MILLICENTS); + // current weight of transfer = 200_000_000 + // Linear weight to fee is 1:1 right now (1 weight = 1 unit of balance) + assert_eq!(weight_fee, weight as Balance); + balance_alice -= base_fee; balance_alice -= weight_fee; balance_alice -= tip; diff --git a/bin/node/executor/tests/submit_transaction.rs b/bin/node/executor/tests/submit_transaction.rs index 536cf486e38ae28e0df13fadd65ac9b5c20e99a0..b3fc25e6cd8fccaadf7dafbf9b03835d4f7224a1 100644 --- a/bin/node/executor/tests/submit_transaction.rs +++ b/bin/node/executor/tests/submit_transaction.rs @@ -1,38 +1,44 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use node_runtime::{ - Call, Executive, Indices, Runtime, TransactionSubmitterOf, UncheckedExtrinsic, + Executive, Indices, Runtime, UncheckedExtrinsic, }; use sp_application_crypto::AppKey; use sp_core::testing::KeyStore; -use sp_core::traits::KeystoreExt; -use sp_core::offchain::{ - TransactionPoolExt, - testing::TestTransactionPoolExt, +use sp_core::{ + offchain::{ + TransactionPoolExt, + testing::TestTransactionPoolExt, + }, + traits::KeystoreExt, +}; +use frame_system::{ + offchain::{ + Signer, + SubmitTransaction, + SendSignedTransaction, + } }; -use frame_system::offchain::{SubmitSignedTransaction, SubmitUnsignedTransaction}; -use pallet_im_online::sr25519::AuthorityPair as Key; use codec::Decode; pub mod common; use self::common::*; -type SubmitTransaction = TransactionSubmitterOf; - #[test] fn should_submit_unsigned_transaction() { let mut t = new_test_ext(COMPACT_CODE, false); @@ -46,11 +52,11 @@ fn should_submit_unsigned_transaction() { network_state: Default::default(), session_index: 1, authority_index: 0, + validators_len: 0, }; let call = pallet_im_online::Call::heartbeat(heartbeat_data, signature); - > - ::submit_unsigned(call) + SubmitTransaction::>::submit_unsigned_transaction(call.into()) .unwrap(); assert_eq!(state.read().transactions.len(), 1) @@ -66,23 +72,16 @@ fn should_submit_signed_transaction() { t.register_extension(TransactionPoolExt::new(pool)); let keystore = KeyStore::new(); - keystore.write().sr25519_generate_new(Key::ID, Some(&format!("{}/hunter1", PHRASE))).unwrap(); - keystore.write().sr25519_generate_new(Key::ID, Some(&format!("{}/hunter2", PHRASE))).unwrap(); - keystore.write().sr25519_generate_new(Key::ID, Some(&format!("{}/hunter3", PHRASE))).unwrap(); + keystore.write().sr25519_generate_new(sr25519::AuthorityId::ID, Some(&format!("{}/hunter1", PHRASE))).unwrap(); + keystore.write().sr25519_generate_new(sr25519::AuthorityId::ID, Some(&format!("{}/hunter2", PHRASE))).unwrap(); + keystore.write().sr25519_generate_new(sr25519::AuthorityId::ID, Some(&format!("{}/hunter3", PHRASE))).unwrap(); t.register_extension(KeystoreExt(keystore)); t.execute_with(|| { - let keys = > - ::find_all_local_keys(); - assert_eq!(keys.len(), 3, "Missing keys: {:?}", keys); - - let can_sign = > - ::can_sign(); - assert!(can_sign, "Since there are keys, `can_sign` should return true"); - - let call = pallet_balances::Call::transfer(Default::default(), Default::default()); - let results = - >::submit_signed(call); + let results = Signer::::all_accounts() + .send_signed_transaction(|_| { + pallet_balances::Call::transfer(Default::default(), Default::default()) + }); let len = results.len(); assert_eq!(len, 3); @@ -98,34 +97,33 @@ fn should_submit_signed_twice_from_the_same_account() { t.register_extension(TransactionPoolExt::new(pool)); let keystore = KeyStore::new(); - keystore.write().sr25519_generate_new(Key::ID, Some(&format!("{}/hunter1", PHRASE))).unwrap(); + keystore.write().sr25519_generate_new(sr25519::AuthorityId::ID, Some(&format!("{}/hunter1", PHRASE))).unwrap(); + keystore.write().sr25519_generate_new(sr25519::AuthorityId::ID, Some(&format!("{}/hunter2", PHRASE))).unwrap(); t.register_extension(KeystoreExt(keystore)); t.execute_with(|| { - let call = pallet_balances::Call::transfer(Default::default(), Default::default()); - let results = - >::submit_signed(call); + let result = Signer::::any_account() + .send_signed_transaction(|_| { + pallet_balances::Call::transfer(Default::default(), Default::default()) + }); - let len = results.len(); - assert_eq!(len, 1); - assert_eq!(results.into_iter().filter_map(|x| x.1.ok()).count(), len); + assert!(result.is_some()); assert_eq!(state.read().transactions.len(), 1); // submit another one from the same account. The nonce should be incremented. - let call = pallet_balances::Call::transfer(Default::default(), Default::default()); - let results = - >::submit_signed(call); + let result = Signer::::any_account() + .send_signed_transaction(|_| { + pallet_balances::Call::transfer(Default::default(), Default::default()) + }); - let len = results.len(); - assert_eq!(len, 1); - assert_eq!(results.into_iter().filter_map(|x| x.1.ok()).count(), len); + assert!(result.is_some()); assert_eq!(state.read().transactions.len(), 2); // now check that the transaction nonces are not equal let s = state.read(); fn nonce(tx: UncheckedExtrinsic) -> frame_system::CheckNonce { let extra = tx.signature.unwrap().2; - extra.3 + extra.4 } let nonce1 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[0]).unwrap()); let nonce2 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[1]).unwrap()); @@ -136,6 +134,60 @@ fn should_submit_signed_twice_from_the_same_account() { }); } +#[test] +fn should_submit_signed_twice_from_all_accounts() { + let mut t = new_test_ext(COMPACT_CODE, false); + let (pool, state) = TestTransactionPoolExt::new(); + t.register_extension(TransactionPoolExt::new(pool)); + + let keystore = KeyStore::new(); + keystore.write().sr25519_generate_new(sr25519::AuthorityId::ID, Some(&format!("{}/hunter1", PHRASE))).unwrap(); + keystore.write().sr25519_generate_new(sr25519::AuthorityId::ID, Some(&format!("{}/hunter2", PHRASE))).unwrap(); + t.register_extension(KeystoreExt(keystore)); + + t.execute_with(|| { + let results = Signer::::all_accounts() + .send_signed_transaction(|_| { + pallet_balances::Call::transfer(Default::default(), Default::default()) + }); + + let len = results.len(); + assert_eq!(len, 2); + assert_eq!(results.into_iter().filter_map(|x| x.1.ok()).count(), len); + assert_eq!(state.read().transactions.len(), 2); + + // submit another one from the same account. The nonce should be incremented. + let results = Signer::::all_accounts() + .send_signed_transaction(|_| { + pallet_balances::Call::transfer(Default::default(), Default::default()) + }); + + let len = results.len(); + assert_eq!(len, 2); + assert_eq!(results.into_iter().filter_map(|x| x.1.ok()).count(), len); + assert_eq!(state.read().transactions.len(), 4); + + // now check that the transaction nonces are not equal + let s = state.read(); + fn nonce(tx: UncheckedExtrinsic) -> frame_system::CheckNonce { + let extra = tx.signature.unwrap().2; + extra.4 + } + let nonce1 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[0]).unwrap()); + let nonce2 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[1]).unwrap()); + let nonce3 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[2]).unwrap()); + let nonce4 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[3]).unwrap()); + assert!( + nonce1 != nonce3, + "Transactions should have different nonces. Got: 1st tx nonce: {:?}, 2nd nonce: {:?}", nonce1, nonce3 + ); + assert!( + nonce2 != nonce4, + "Transactions should have different nonces. Got: 1st tx nonce: {:?}, 2nd tx nonce: {:?}", nonce2, nonce4 + ); + }); +} + #[test] fn submitted_transaction_should_be_valid() { use codec::Encode; @@ -148,13 +200,14 @@ fn submitted_transaction_should_be_valid() { t.register_extension(TransactionPoolExt::new(pool)); let keystore = KeyStore::new(); - keystore.write().sr25519_generate_new(Key::ID, Some(&format!("{}/hunter1", PHRASE))).unwrap(); + keystore.write().sr25519_generate_new(sr25519::AuthorityId::ID, Some(&format!("{}/hunter1", PHRASE))).unwrap(); t.register_extension(KeystoreExt(keystore)); t.execute_with(|| { - let call = pallet_balances::Call::transfer(Default::default(), Default::default()); - let results = - >::submit_signed(call); + let results = Signer::::all_accounts() + .send_signed_transaction(|_| { + pallet_balances::Call::transfer(Default::default(), Default::default()) + }); let len = results.len(); assert_eq!(len, 1); assert_eq!(results.into_iter().filter_map(|x| x.1.ok()).count(), len); @@ -178,10 +231,10 @@ fn submitted_transaction_should_be_valid() { let res = Executive::validate_transaction(source, extrinsic); assert_eq!(res.unwrap(), ValidTransaction { - priority: 2_411_002_000_000, + priority: 1_410_710_000_000, requires: vec![], provides: vec![(address, 0).encode()], - longevity: 128, + longevity: 2048, propagate: true, }); }); diff --git a/bin/node/inspect/Cargo.toml b/bin/node/inspect/Cargo.toml index 9e94fe74d68469d9570fe76292d004e9106ef049..e76f215a998142516e52d2996300a073a02cdf59 100644 --- a/bin/node/inspect/Cargo.toml +++ b/bin/node/inspect/Cargo.toml @@ -1,23 +1,23 @@ [package] name = "node-inspect" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0" } +codec = { package = "parity-scale-codec", version = "1.3.1" } derive_more = "0.99" log = "0.4.8" -sc-cli = { version = "0.8.0-alpha.5", path = "../../../client/cli" } -sc-client-api = { version = "2.0.0-alpha.5", path = "../../../client/api" } -sc-service = { version = "0.8.0-alpha.5", default-features = false, path = "../../../client/service" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../../primitives/blockchain" } -sp-core = { version = "2.0.0-alpha.5", path = "../../../primitives/core" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime" } +sc-cli = { version = "0.8.0-rc4", path = "../../../client/cli" } +sc-client-api = { version = "2.0.0-rc4", path = "../../../client/api" } +sc-service = { version = "0.8.0-rc4", default-features = false, path = "../../../client/service" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../../primitives/blockchain" } +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } +sp-runtime = { version = "2.0.0-rc4", path = "../../../primitives/runtime" } structopt = "0.3.8" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/bin/node/inspect/src/cli.rs b/bin/node/inspect/src/cli.rs index 5d51bd5848f17d308933fdcb69d429504fa8445e..d66644bab52fa78788098e3713ceae1576f25b6c 100644 --- a/bin/node/inspect/src/cli.rs +++ b/bin/node/inspect/src/cli.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Structs to easily compose inspect sub-command for CLI. @@ -21,7 +23,7 @@ use sc_cli::{ImportParams, SharedParams}; use structopt::StructOpt; /// The `inspect` command used to print decoded chain data. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, StructOpt)] pub struct InspectCmd { #[allow(missing_docs)] #[structopt(flatten)] @@ -37,7 +39,7 @@ pub struct InspectCmd { } /// A possible inspect sub-commands. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, StructOpt)] pub enum InspectSubCmd { /// Decode block with native version of runtime and print out the details. Block { diff --git a/bin/node/inspect/src/command.rs b/bin/node/inspect/src/command.rs index 335b6c85319a23c2c8e5ffd17d52b593f9602cd7..fae6c10c7fe7846dc63e990dcf03254655467705 100644 --- a/bin/node/inspect/src/command.rs +++ b/bin/node/inspect/src/command.rs @@ -1,201 +1,65 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Command ran by the CLI -use std::{ - fmt::Debug, - str::FromStr, -}; - use crate::cli::{InspectCmd, InspectSubCmd}; -use crate::{Inspector, PrettyPrinter}; +use crate::Inspector; +use sc_cli::{CliConfiguration, ImportParams, Result, SharedParams}; +use sc_service::{new_full_client, Configuration, NativeExecutionDispatch}; +use sp_runtime::traits::Block; +use std::str::FromStr; impl InspectCmd { - /// Initialize - pub fn init(&self, version: &sc_cli::VersionInfo) -> sc_cli::Result<()> { - self.shared_params.init(version) - } - - /// Parse CLI arguments and initialize given config. - pub fn update_config( - &self, - mut config: &mut sc_service::config::Configuration, - spec_factory: impl FnOnce(&str) -> Result, String>, - version: &sc_cli::VersionInfo, - ) -> sc_cli::Result<()> { - self.shared_params.update_config(config, spec_factory, version)?; - - // make sure to configure keystore - config.use_in_memory_keystore()?; - - // and all import params (especially pruning that has to match db meta) - self.import_params.update_config( - &mut config, - &sc_service::Role::Full, - self.shared_params.dev, - )?; - - Ok(()) - } - /// Run the inspect command, passing the inspector. - pub fn run( - self, - inspect: Inspector, - ) -> sc_cli::Result<()> where - B: sp_runtime::traits::Block, + pub fn run(&self, config: Configuration) -> Result<()> + where + B: Block, B::Hash: FromStr, - P: PrettyPrinter, + RA: Send + Sync + 'static, + EX: NativeExecutionDispatch + 'static, { - match self.command { + let client = new_full_client::(&config)?; + let inspect = Inspector::::new(client); + + match &self.command { InspectSubCmd::Block { input } => { let input = input.parse()?; - let res = inspect.block(input) - .map_err(|e| format!("{}", e))?; + let res = inspect.block(input).map_err(|e| format!("{}", e))?; println!("{}", res); Ok(()) - }, + } InspectSubCmd::Extrinsic { input } => { let input = input.parse()?; - let res = inspect.extrinsic(input) - .map_err(|e| format!("{}", e))?; + let res = inspect.extrinsic(input).map_err(|e| format!("{}", e))?; println!("{}", res); Ok(()) - }, + } } } } -/// A block to retrieve. -#[derive(Debug, Clone, PartialEq)] -pub enum BlockAddress { - /// Get block by hash. - Hash(Hash), - /// Get block by number. - Number(Number), - /// Raw SCALE-encoded bytes. - Bytes(Vec), -} - -impl FromStr for BlockAddress { - type Err = String; - - fn from_str(s: &str) -> Result { - // try to parse hash first - if let Ok(hash) = s.parse() { - return Ok(Self::Hash(hash)) - } - - // then number - if let Ok(number) = s.parse() { - return Ok(Self::Number(number)) - } - - // then assume it's bytes (hex-encoded) - sp_core::bytes::from_hex(s) - .map(Self::Bytes) - .map_err(|e| format!( - "Given string does not look like hash or number. It could not be parsed as bytes either: {}", - e - )) +impl CliConfiguration for InspectCmd { + fn shared_params(&self) -> &SharedParams { + &self.shared_params } -} - -/// An extrinsic address to decode and print out. -#[derive(Debug, Clone, PartialEq)] -pub enum ExtrinsicAddress { - /// Extrinsic as part of existing block. - Block(BlockAddress, usize), - /// Raw SCALE-encoded extrinsic bytes. - Bytes(Vec), -} - -impl FromStr for ExtrinsicAddress { - type Err = String; - - fn from_str(s: &str) -> Result { - // first try raw bytes - if let Ok(bytes) = sp_core::bytes::from_hex(s).map(Self::Bytes) { - return Ok(bytes) - } - - // split by a bunch of different characters - let mut it = s.split(|c| c == '.' || c == ':' || c == ' '); - let block = it.next() - .expect("First element of split iterator is never empty; qed") - .parse()?; - - let index = it.next() - .ok_or_else(|| format!("Extrinsic index missing: example \"5:0\""))? - .parse() - .map_err(|e| format!("Invalid index format: {}", e))?; - - Ok(Self::Block(block, index)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use sp_core::hash::H160 as Hash; - - #[test] - fn should_parse_block_strings() { - type BlockAddress = super::BlockAddress; - - let b0 = BlockAddress::from_str("3BfC20f0B9aFcAcE800D73D2191166FF16540258"); - let b1 = BlockAddress::from_str("1234"); - let b2 = BlockAddress::from_str("0"); - let b3 = BlockAddress::from_str("0x0012345f"); - - - assert_eq!(b0, Ok(BlockAddress::Hash( - "3BfC20f0B9aFcAcE800D73D2191166FF16540258".parse().unwrap() - ))); - assert_eq!(b1, Ok(BlockAddress::Number(1234))); - assert_eq!(b2, Ok(BlockAddress::Number(0))); - assert_eq!(b3, Ok(BlockAddress::Bytes(vec![0, 0x12, 0x34, 0x5f]))); - } - - #[test] - fn should_parse_extrinsic_address() { - type BlockAddress = super::BlockAddress; - type ExtrinsicAddress = super::ExtrinsicAddress; - - let e0 = ExtrinsicAddress::from_str("1234"); - let b0 = ExtrinsicAddress::from_str("3BfC20f0B9aFcAcE800D73D2191166FF16540258:5"); - let b1 = ExtrinsicAddress::from_str("1234:0"); - let b2 = ExtrinsicAddress::from_str("0 0"); - let b3 = ExtrinsicAddress::from_str("0x0012345f"); - - assert_eq!(e0, Err("Extrinsic index missing: example \"5:0\"".into())); - assert_eq!(b0, Ok(ExtrinsicAddress::Block( - BlockAddress::Hash("3BfC20f0B9aFcAcE800D73D2191166FF16540258".parse().unwrap()), - 5 - ))); - assert_eq!(b1, Ok(ExtrinsicAddress::Block( - BlockAddress::Number(1234), - 0 - ))); - assert_eq!(b2, Ok(ExtrinsicAddress::Block( - BlockAddress::Number(0), - 0 - ))); - assert_eq!(b3, Ok(ExtrinsicAddress::Bytes(vec![0, 0x12, 0x34, 0x5f]))); + fn import_params(&self) -> Option<&ImportParams> { + Some(&self.import_params) } } diff --git a/bin/node/inspect/src/lib.rs b/bin/node/inspect/src/lib.rs index c82682d6021dbbac42f51c0367343d1dec8dcb65..02f5614b81a78044d1418d9d23f87322da2c298c 100644 --- a/bin/node/inspect/src/lib.rs +++ b/bin/node/inspect/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify +// +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 +// +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, +// +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! A CLI extension for substrate node, adding sub-command to pretty print debug info //! about blocks and extrinsics. @@ -27,7 +29,9 @@ pub mod command; use std::{ fmt, - marker::PhantomData + fmt::Debug, + marker::PhantomData, + str::FromStr, }; use codec::{Encode, Decode}; use sc_client_api::BlockBackend; @@ -38,8 +42,6 @@ use sp_runtime::{ traits::{Block, HashFor, NumberFor, Hash} }; -use command::{BlockAddress, ExtrinsicAddress}; - /// A helper type for a generic block input. pub type BlockAddressFor = BlockAddress< as Hash>::Output, @@ -205,3 +207,123 @@ impl> Inspector Ok(format!("{}", ExtrinsicPrinter(ext, &self.printer))) } } + +/// A block to retrieve. +#[derive(Debug, Clone, PartialEq)] +pub enum BlockAddress { + /// Get block by hash. + Hash(Hash), + /// Get block by number. + Number(Number), + /// Raw SCALE-encoded bytes. + Bytes(Vec), +} + +impl FromStr for BlockAddress { + type Err = String; + + fn from_str(s: &str) -> Result { + // try to parse hash first + if let Ok(hash) = s.parse() { + return Ok(Self::Hash(hash)) + } + + // then number + if let Ok(number) = s.parse() { + return Ok(Self::Number(number)) + } + + // then assume it's bytes (hex-encoded) + sp_core::bytes::from_hex(s) + .map(Self::Bytes) + .map_err(|e| format!( + "Given string does not look like hash or number. It could not be parsed as bytes either: {}", + e + )) + } +} + +/// An extrinsic address to decode and print out. +#[derive(Debug, Clone, PartialEq)] +pub enum ExtrinsicAddress { + /// Extrinsic as part of existing block. + Block(BlockAddress, usize), + /// Raw SCALE-encoded extrinsic bytes. + Bytes(Vec), +} + +impl FromStr for ExtrinsicAddress { + type Err = String; + + fn from_str(s: &str) -> Result { + // first try raw bytes + if let Ok(bytes) = sp_core::bytes::from_hex(s).map(Self::Bytes) { + return Ok(bytes) + } + + // split by a bunch of different characters + let mut it = s.split(|c| c == '.' || c == ':' || c == ' '); + let block = it.next() + .expect("First element of split iterator is never empty; qed") + .parse()?; + + let index = it.next() + .ok_or_else(|| format!("Extrinsic index missing: example \"5:0\""))? + .parse() + .map_err(|e| format!("Invalid index format: {}", e))?; + + Ok(Self::Block(block, index)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use sp_core::hash::H160 as Hash; + + #[test] + fn should_parse_block_strings() { + type BlockAddress = super::BlockAddress; + + let b0 = BlockAddress::from_str("3BfC20f0B9aFcAcE800D73D2191166FF16540258"); + let b1 = BlockAddress::from_str("1234"); + let b2 = BlockAddress::from_str("0"); + let b3 = BlockAddress::from_str("0x0012345f"); + + + assert_eq!(b0, Ok(BlockAddress::Hash( + "3BfC20f0B9aFcAcE800D73D2191166FF16540258".parse().unwrap() + ))); + assert_eq!(b1, Ok(BlockAddress::Number(1234))); + assert_eq!(b2, Ok(BlockAddress::Number(0))); + assert_eq!(b3, Ok(BlockAddress::Bytes(vec![0, 0x12, 0x34, 0x5f]))); + } + + #[test] + fn should_parse_extrinsic_address() { + type BlockAddress = super::BlockAddress; + type ExtrinsicAddress = super::ExtrinsicAddress; + + let e0 = ExtrinsicAddress::from_str("1234"); + let b0 = ExtrinsicAddress::from_str("3BfC20f0B9aFcAcE800D73D2191166FF16540258:5"); + let b1 = ExtrinsicAddress::from_str("1234:0"); + let b2 = ExtrinsicAddress::from_str("0 0"); + let b3 = ExtrinsicAddress::from_str("0x0012345f"); + + + assert_eq!(e0, Err("Extrinsic index missing: example \"5:0\"".into())); + assert_eq!(b0, Ok(ExtrinsicAddress::Block( + BlockAddress::Hash("3BfC20f0B9aFcAcE800D73D2191166FF16540258".parse().unwrap()), + 5 + ))); + assert_eq!(b1, Ok(ExtrinsicAddress::Block( + BlockAddress::Number(1234), + 0 + ))); + assert_eq!(b2, Ok(ExtrinsicAddress::Block( + BlockAddress::Number(0), + 0 + ))); + assert_eq!(b3, Ok(ExtrinsicAddress::Bytes(vec![0, 0x12, 0x34, 0x5f]))); + } +} diff --git a/bin/node/primitives/Cargo.toml b/bin/node/primitives/Cargo.toml index 81c5009f394d57332d5c9ef65ed8c6bb2cb6f120..0a66336046caafc81ef7dd9a4d9da1e122617407 100644 --- a/bin/node/primitives/Cargo.toml +++ b/bin/node/primitives/Cargo.toml @@ -1,26 +1,32 @@ [package] name = "node-primitives" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/core" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/runtime" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/system" } +sp-application-crypto = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/application-crypto" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/core" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/runtime" } [dev-dependencies] -sp-serializer = { version = "2.0.0-alpha.5", path = "../../../primitives/serializer" } +sp-serializer = { version = "2.0.0-rc4", path = "../../../primitives/serializer" } pretty_assertions = "0.6.1" [features] default = ["std"] std = [ + "codec/std", + "frame-system/std", + "sp-application-crypto/std", "sp-core/std", "sp-runtime/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/bin/node/primitives/src/lib.rs b/bin/node/primitives/src/lib.rs index 97e8f50c2714562b68ce324fad94df0295758357..137fb1d94c778aafa6b2f45713d4954070caa1d5 100644 --- a/bin/node/primitives/src/lib.rs +++ b/bin/node/primitives/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Low-level types used throughout the Substrate code. @@ -62,3 +63,34 @@ pub type Header = generic::Header; pub type Block = generic::Block; /// Block ID. pub type BlockId = generic::BlockId; + +/// App-specific crypto used for reporting equivocation/misbehavior in BABE and +/// GRANDPA. Any rewards for misbehavior reporting will be paid out to this +/// account. +pub mod report { + use super::{Signature, Verify}; + use frame_system::offchain::AppCrypto; + use sp_core::crypto::{key_types, KeyTypeId}; + + /// Key type for the reporting module. Used for reporting BABE and GRANDPA + /// equivocations. + pub const KEY_TYPE: KeyTypeId = key_types::REPORTING; + + mod app { + use sp_application_crypto::{app_crypto, sr25519}; + app_crypto!(sr25519, super::KEY_TYPE); + } + + /// Identity of the equivocation/misbehavior reporter. + pub type ReporterId = app::Public; + + /// An `AppCrypto` type to allow submitting signed transactions using the reporting + /// application key as signer. + pub struct ReporterAppCrypto; + + impl AppCrypto<::Signer, Signature> for ReporterAppCrypto { + type RuntimeAppPublic = ReporterId; + type GenericSignature = sp_core::sr25519::Signature; + type GenericPublic = sp_core::sr25519::Public; + } +} diff --git a/bin/node/rpc-client/Cargo.toml b/bin/node/rpc-client/Cargo.toml index df095bc5bb10d2574a01790f3ed32ea9c8585ebe..2d21746f2aeb275b7db28037e59e9aa02a3c9c14 100644 --- a/bin/node/rpc-client/Cargo.toml +++ b/bin/node/rpc-client/Cargo.toml @@ -1,20 +1,20 @@ [package] name = "node-rpc-client" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] env_logger = "0.7.0" futures = "0.1.29" hyper = "0.12.35" -jsonrpc-core-client = { version = "14.0.5", default-features = false, features = ["http"] } +jsonrpc-core-client = { version = "14.2.0", default-features = false, features = ["http"] } log = "0.4.8" -node-primitives = { version = "2.0.0-alpha.5", path = "../primitives" } -sc-rpc = { version = "2.0.0-alpha.5", path = "../../../client/rpc" } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +node-primitives = { version = "2.0.0-rc4", path = "../primitives" } +sc-rpc = { version = "2.0.0-rc4", path = "../../../client/rpc" } diff --git a/bin/node/rpc-client/src/main.rs b/bin/node/rpc-client/src/main.rs index c547d30002d795b07ffc9468027bf1c06f17b877..eadd1c8d472476b6db57570d08a0233d36bea45d 100644 --- a/bin/node/rpc-client/src/main.rs +++ b/bin/node/rpc-client/src/main.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. #![warn(missing_docs)] diff --git a/bin/node/rpc/Cargo.toml b/bin/node/rpc/Cargo.toml index f1d230af90dc5e9e65da0ba4284355fa5292435a..95d55fab6402c9a0dff73bbbb8c19bd6fd8823ef 100644 --- a/bin/node/rpc/Cargo.toml +++ b/bin/node/rpc/Cargo.toml @@ -1,30 +1,34 @@ [package] name = "node-rpc" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" -[dependencies] -sc-client = { version = "0.8.0-alpha.5", path = "../../../client/" } -jsonrpc-core = "14.0.3" -node-primitives = { version = "2.0.0-alpha.5", path = "../primitives" } -node-runtime = { version = "2.0.0-alpha.5", path = "../runtime" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime" } -sp-api = { version = "2.0.0-alpha.5", path = "../../../primitives/api" } -pallet-contracts-rpc = { version = "0.8.0-alpha.5", path = "../../../frame/contracts/rpc/" } -pallet-transaction-payment-rpc = { version = "2.0.0-alpha.5", path = "../../../frame/transaction-payment/rpc/" } -substrate-frame-rpc-system = { version = "2.0.0-alpha.5", path = "../../../utils/frame/rpc/system" } -sp-transaction-pool = { version = "2.0.0-alpha.5", path = "../../../primitives/transaction-pool" } -sc-consensus-babe = { version = "0.8.0-alpha.5", path = "../../../client/consensus/babe" } -sc-consensus-babe-rpc = { version = "0.8.0-alpha.5", path = "../../../client/consensus/babe/rpc" } -sp-consensus-babe = { version = "0.8.0-alpha.5", path = "../../../primitives/consensus/babe" } -sc-keystore = { version = "2.0.0-alpha.5", path = "../../../client/keystore" } -sc-consensus-epochs = { version = "0.8.0-alpha.5", path = "../../../client/consensus/epochs" } -sp-consensus = { version = "0.8.0-alpha.5", path = "../../../primitives/consensus/common" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../../primitives/blockchain" } - [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +sc-client-api = { version = "2.0.0-rc4", path = "../../../client/api" } +jsonrpc-core = "14.2.0" +node-primitives = { version = "2.0.0-rc4", path = "../primitives" } +node-runtime = { version = "2.0.0-rc4", path = "../runtime" } +sp-runtime = { version = "2.0.0-rc4", path = "../../../primitives/runtime" } +sp-api = { version = "2.0.0-rc4", path = "../../../primitives/api" } +pallet-contracts-rpc = { version = "0.8.0-rc4", path = "../../../frame/contracts/rpc/" } +pallet-transaction-payment-rpc = { version = "2.0.0-rc4", path = "../../../frame/transaction-payment/rpc/" } +substrate-frame-rpc-system = { version = "2.0.0-rc4", path = "../../../utils/frame/rpc/system" } +sp-transaction-pool = { version = "2.0.0-rc4", path = "../../../primitives/transaction-pool" } +sc-consensus-babe = { version = "0.8.0-rc4", path = "../../../client/consensus/babe" } +sc-consensus-babe-rpc = { version = "0.8.0-rc4", path = "../../../client/consensus/babe/rpc" } +sp-consensus-babe = { version = "0.8.0-rc4", path = "../../../primitives/consensus/babe" } +sc-keystore = { version = "2.0.0-rc4", path = "../../../client/keystore" } +sc-consensus-epochs = { version = "0.8.0-rc4", path = "../../../client/consensus/epochs" } +sp-consensus = { version = "0.8.0-rc4", path = "../../../primitives/consensus/common" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../../primitives/blockchain" } +sc-finality-grandpa = { version = "0.8.0-rc4", path = "../../../client/finality-grandpa" } +sc-finality-grandpa-rpc = { version = "0.8.0-rc4", path = "../../../client/finality-grandpa/rpc" } +sc-rpc-api = { version = "0.8.0-rc4", path = "../../../client/rpc-api" } +sp-block-builder = { version = "2.0.0-rc4", path = "../../../primitives/block-builder" } diff --git a/bin/node/rpc/src/lib.rs b/bin/node/rpc/src/lib.rs index 4e1cfa56733a7bbbbb50fd944241410465d488c1..9b6b5991748f96e60ff0ea20d126faaa315637fb 100644 --- a/bin/node/rpc/src/lib.rs +++ b/bin/node/rpc/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! A collection of node-specific RPC methods. //! @@ -29,9 +30,9 @@ #![warn(missing_docs)] -use std::{sync::Arc, fmt}; +use std::sync::Arc; -use node_primitives::{Block, BlockNumber, AccountId, Index, Balance}; +use node_primitives::{Block, BlockNumber, AccountId, Index, Balance, Hash}; use node_runtime::UncheckedExtrinsic; use sp_api::ProvideRuntimeApi; use sp_transaction_pool::TransactionPool; @@ -41,7 +42,11 @@ use sc_keystore::KeyStorePtr; use sp_consensus_babe::BabeApi; use sc_consensus_epochs::SharedEpochChanges; use sc_consensus_babe::{Config, Epoch}; -use sc_consensus_babe_rpc::BabeRPCHandler; +use sc_consensus_babe_rpc::BabeRpcHandler; +use sc_finality_grandpa::{SharedVoterState, SharedAuthoritySet}; +use sc_finality_grandpa_rpc::GrandpaRpcHandler; +use sc_rpc_api::DenyUnsafe; +use sp_block_builder::BlockBuilder; /// Light client extra dependencies. pub struct LightDeps { @@ -50,7 +55,7 @@ pub struct LightDeps { /// Transaction pool instance. pub pool: Arc

, /// Remote access to the blockchain (async). - pub remote_blockchain: Arc>, + pub remote_blockchain: Arc>, /// Fetcher instance. pub fetcher: Arc, } @@ -65,6 +70,14 @@ pub struct BabeDeps { pub keystore: KeyStorePtr, } +/// Extra dependencies for GRANDPA +pub struct GrandpaDeps { + /// Voting round info. + pub shared_voter_state: SharedVoterState, + /// Authority set info. + pub shared_authority_set: SharedAuthoritySet, +} + /// Full client dependencies. pub struct FullDeps { /// The client instance to use. @@ -73,8 +86,12 @@ pub struct FullDeps { pub pool: Arc

, /// The SelectChain Strategy pub select_chain: SC, + /// Whether to deny unsafe calls + pub deny_unsafe: DenyUnsafe, /// BABE specific dependencies. pub babe: BabeDeps, + /// GRANDPA specific dependencies. + pub grandpa: GrandpaDeps, } /// Instantiate all Full RPC extensions. @@ -88,7 +105,7 @@ pub fn create_full( C::Api: pallet_contracts_rpc::ContractsRuntimeApi, C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi, C::Api: BabeApi, - ::Error: fmt::Debug, + C::Api: BlockBuilder, P: TransactionPool + 'static, M: jsonrpc_core::Metadata + Default, SC: SelectChain +'static, @@ -102,16 +119,22 @@ pub fn create_full( client, pool, select_chain, - babe + deny_unsafe, + babe, + grandpa, } = deps; let BabeDeps { keystore, babe_config, shared_epoch_changes, } = babe; + let GrandpaDeps { + shared_voter_state, + shared_authority_set, + } = grandpa; io.extend_with( - SystemApi::to_delegate(FullSystem::new(client.clone(), pool)) + SystemApi::to_delegate(FullSystem::new(client.clone(), pool, deny_unsafe)) ); // Making synchronous calls in light client freezes the browser currently, // more context: https://github.com/paritytech/substrate/pull/3480 @@ -124,7 +147,19 @@ pub fn create_full( ); io.extend_with( sc_consensus_babe_rpc::BabeApi::to_delegate( - BabeRPCHandler::new(client, shared_epoch_changes, keystore, babe_config, select_chain) + BabeRpcHandler::new( + client, + shared_epoch_changes, + keystore, + babe_config, + select_chain, + deny_unsafe, + ), + ) + ); + io.extend_with( + sc_finality_grandpa_rpc::GrandpaApi::to_delegate( + GrandpaRpcHandler::new(shared_authority_set, shared_voter_state) ) ); @@ -135,9 +170,9 @@ pub fn create_full( pub fn create_light( deps: LightDeps, ) -> jsonrpc_core::IoHandler where - C: sc_client::blockchain::HeaderBackend, + C: sp_blockchain::HeaderBackend, C: Send + Sync + 'static, - F: sc_client::light::fetcher::Fetcher + 'static, + F: sc_client_api::light::Fetcher + 'static, P: TransactionPool + 'static, M: jsonrpc_core::Metadata + Default, { @@ -151,7 +186,7 @@ pub fn create_light( } = deps; let mut io = jsonrpc_core::IoHandler::default(); io.extend_with( - SystemApi::::to_delegate(LightSystem::new(client, remote_blockchain, fetcher, pool)) + SystemApi::::to_delegate(LightSystem::new(client, remote_blockchain, fetcher, pool)) ); io diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 67e50e53f69e6755481de5c5fe615d968a67d2d5..1d29a592c414c65c825ebe4272ba283a9a16158e 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -1,81 +1,90 @@ [package] name = "node-runtime" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" build = "build.rs" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] # third-party dependencies -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } integer-sqrt = { version = "0.1.2" } serde = { version = "1.0.102", optional = true } +static_assertions = "1.1.0" +hex-literal = { version = "0.2.1", optional = true } # primitives -sp-authority-discovery = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/authority-discovery" } -sp-consensus-babe = { version = "0.8.0-alpha.5", default-features = false, path = "../../../primitives/consensus/babe" } -sp-block-builder = { path = "../../../primitives/block-builder", default-features = false, version = "2.0.0-alpha.5"} -sp-inherents = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/inherents" } -node-primitives = { version = "2.0.0-alpha.5", default-features = false, path = "../primitives" } -sp-offchain = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/offchain" } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/core" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/std" } -sp-api = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/api" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/runtime" } -sp-staking = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/staking" } -sp-keyring = { version = "2.0.0-alpha.5", optional = true, path = "../../../primitives/keyring" } -sp-session = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/session" } -sp-transaction-pool = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/transaction-pool" } -sp-version = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/version" } +sp-authority-discovery = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/authority-discovery" } +sp-consensus-babe = { version = "0.8.0-rc4", default-features = false, path = "../../../primitives/consensus/babe" } +sp-block-builder = { path = "../../../primitives/block-builder", default-features = false, version = "2.0.0-rc4"} +sp-inherents = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/inherents" } +node-primitives = { version = "2.0.0-rc4", default-features = false, path = "../primitives" } +sp-offchain = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/offchain" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/core" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/std" } +sp-api = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/api" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/runtime" } +sp-staking = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/staking" } +sp-keyring = { version = "2.0.0-rc4", optional = true, path = "../../../primitives/keyring" } +sp-session = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/session" } +sp-transaction-pool = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/transaction-pool" } +sp-version = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/version" } # frame dependencies -frame-executive = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/executive" } -frame-benchmarking = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/benchmarking", optional = true } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/system" } -frame-system-rpc-runtime-api = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/system/rpc/runtime-api/" } -pallet-authority-discovery = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/authority-discovery" } -pallet-authorship = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/authorship" } -pallet-babe = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/babe" } -pallet-balances = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/balances" } -pallet-collective = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/collective" } -pallet-contracts = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/contracts" } -pallet-contracts-primitives = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/contracts/common/" } -pallet-contracts-rpc-runtime-api = { version = "0.8.0-alpha.5", default-features = false, path = "../../../frame/contracts/rpc/runtime-api/" } -pallet-democracy = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/democracy" } -pallet-elections-phragmen = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/elections-phragmen" } -pallet-finality-tracker = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/finality-tracker" } -pallet-grandpa = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/grandpa" } -pallet-im-online = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/im-online" } -pallet-indices = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/indices" } -pallet-identity = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/identity" } -pallet-membership = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/membership" } -pallet-offences = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/offences" } -pallet-randomness-collective-flip = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/randomness-collective-flip" } -pallet-recovery = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/recovery" } -pallet-session = { version = "2.0.0-alpha.5", features = ["historical"], path = "../../../frame/session", default-features = false } -pallet-session-benchmarking = { version = "2.0.0-alpha.5", path = "../../../frame/session/benchmarking", default-features = false, optional = true } -pallet-staking = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/staking" } -pallet-staking-reward-curve = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/staking/reward-curve" } -pallet-scheduler = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/scheduler" } -pallet-society = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/society" } -pallet-sudo = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/sudo" } -pallet-timestamp = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/timestamp" } -pallet-treasury = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/treasury" } -pallet-utility = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/utility" } -pallet-transaction-payment = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/transaction-payment" } -pallet-transaction-payment-rpc-runtime-api = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/transaction-payment/rpc/runtime-api/" } -pallet-vesting = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/vesting" } +frame-executive = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/executive" } +frame-benchmarking = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/benchmarking", optional = true } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/system" } +frame-system-benchmarking = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/system/benchmarking", optional = true } +frame-system-rpc-runtime-api = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/system/rpc/runtime-api/" } +pallet-authority-discovery = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/authority-discovery" } +pallet-authorship = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/authorship" } +pallet-babe = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/babe" } +pallet-balances = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/balances" } +pallet-collective = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/collective" } +pallet-contracts = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/contracts" } +pallet-contracts-primitives = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/contracts/common/" } +pallet-contracts-rpc-runtime-api = { version = "0.8.0-rc4", default-features = false, path = "../../../frame/contracts/rpc/runtime-api/" } +pallet-democracy = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/democracy" } +pallet-elections-phragmen = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/elections-phragmen" } +pallet-finality-tracker = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/finality-tracker" } +pallet-grandpa = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/grandpa" } +pallet-im-online = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/im-online" } +pallet-indices = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/indices" } +pallet-identity = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/identity" } +pallet-membership = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/membership" } +pallet-multisig = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/multisig" } +pallet-offences = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/offences" } +pallet-offences-benchmarking = { version = "2.0.0-rc4", path = "../../../frame/offences/benchmarking", default-features = false, optional = true } +pallet-proxy = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/proxy" } +pallet-randomness-collective-flip = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/randomness-collective-flip" } +pallet-recovery = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/recovery" } +pallet-session = { version = "2.0.0-rc4", features = ["historical"], path = "../../../frame/session", default-features = false } +pallet-session-benchmarking = { version = "2.0.0-rc4", path = "../../../frame/session/benchmarking", default-features = false, optional = true } +pallet-staking = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/staking" } +pallet-staking-reward-curve = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/staking/reward-curve" } +pallet-scheduler = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/scheduler" } +pallet-society = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/society" } +pallet-sudo = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/sudo" } +pallet-timestamp = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/timestamp" } +pallet-treasury = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/treasury" } +pallet-utility = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/utility" } +pallet-transaction-payment = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/transaction-payment" } +pallet-transaction-payment-rpc-runtime-api = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/transaction-payment/rpc/runtime-api/" } +pallet-vesting = { version = "2.0.0-rc4", default-features = false, path = "../../../frame/vesting" } [build-dependencies] wasm-builder-runner = { version = "1.0.5", package = "substrate-wasm-builder-runner", path = "../../../utils/wasm-builder-runner" } [dev-dependencies] -sp-io = { version = "2.0.0-alpha.5", path = "../../../primitives/io" } +sp-io = { version = "2.0.0-rc4", path = "../../../primitives/io" } [features] default = ["std"] @@ -101,10 +110,13 @@ std = [ "pallet-indices/std", "sp-inherents/std", "pallet-membership/std", + "pallet-multisig/std", "pallet-identity/std", + "pallet-scheduler/std", "node-primitives/std", "sp-offchain/std", "pallet-offences/std", + "pallet-proxy/std", "sp-core/std", "pallet-randomness-collective-flip/std", "sp-std/std", @@ -137,21 +149,25 @@ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "sp-runtime/runtime-benchmarks", + "pallet-babe/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-collective/runtime-benchmarks", "pallet-democracy/runtime-benchmarks", "pallet-elections-phragmen/runtime-benchmarks", "pallet-identity/runtime-benchmarks", "pallet-im-online/runtime-benchmarks", + "pallet-indices/runtime-benchmarks", + "pallet-multisig/runtime-benchmarks", + "pallet-proxy/runtime-benchmarks", + "pallet-scheduler/runtime-benchmarks", "pallet-society/runtime-benchmarks", "pallet-staking/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", "pallet-treasury/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-vesting/runtime-benchmarks", - "pallet-collective/runtime-benchmarks", + "pallet-offences-benchmarking", "pallet-session-benchmarking", + "frame-system-benchmarking", + "hex-literal", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/bin/node/runtime/build.rs b/bin/node/runtime/build.rs index 647b4768141d2203155bf5325f9ff87f7d9c2446..a4f323566006cf7c003cec2e413e1d23ecffead1 100644 --- a/bin/node/runtime/build.rs +++ b/bin/node/runtime/build.rs @@ -1,25 +1,26 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use wasm_builder_runner::WasmBuilder; fn main() { WasmBuilder::new() .with_current_project() - .with_wasm_builder_from_crates_or_path("1.0.9", "../../../utils/wasm-builder") + .with_wasm_builder_from_crates_or_path("1.0.11", "../../../utils/wasm-builder") .export_heap_base() .import_memory() .build() diff --git a/bin/node/runtime/src/constants.rs b/bin/node/runtime/src/constants.rs index bf12492f8db029dc22b519dd52af74adcad99a7f..8e87d61c1e6b597ccb0eb114351befe969264ddf 100644 --- a/bin/node/runtime/src/constants.rs +++ b/bin/node/runtime/src/constants.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! A set of constant values used in substrate runtime. @@ -23,6 +24,10 @@ pub mod currency { pub const MILLICENTS: Balance = 1_000_000_000; pub const CENTS: Balance = 1_000 * MILLICENTS; // assume this is worth about a cent. pub const DOLLARS: Balance = 100 * CENTS; + + pub const fn deposit(items: u32, bytes: u32) -> Balance { + items as Balance * 15 * CENTS + (bytes as Balance) * 6 * CENTS + } } /// Time. diff --git a/bin/node/runtime/src/impls.rs b/bin/node/runtime/src/impls.rs index 646dc24f578de221339d08d27393b5457e7fda88..039093ddee69700594b70200595a39b07f7e7fa4 100644 --- a/bin/node/runtime/src/impls.rs +++ b/bin/node/runtime/src/impls.rs @@ -1,26 +1,26 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Some configurable implementations as associated type for the substrate runtime. use node_primitives::Balance; -use sp_runtime::traits::{Convert, Saturating}; -use sp_runtime::{Fixed64, Perbill}; -use frame_support::{traits::{OnUnbalanced, Currency, Get}, weights::Weight}; -use crate::{Balances, System, Authorship, MaximumBlockWeight, NegativeImbalance}; +use sp_runtime::traits::Convert; +use frame_support::traits::{OnUnbalanced, Currency}; +use crate::{Balances, Authorship, NegativeImbalance}; pub struct Author; impl OnUnbalanced for Author { @@ -45,108 +45,63 @@ impl Convert for CurrencyToVoteHandler { fn convert(x: u128) -> Balance { x * Self::factor() } } -/// 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(sp_std::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: - let coefficient = C::get(); - Balance::from(w).saturating_mul(coefficient) - } -} - -/// Update the given multiplier based on the following formula -/// -/// 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 TargetedFeeAdjustment(sp_std::marker::PhantomData); - -impl> Convert for TargetedFeeAdjustment { - fn convert(multiplier: Fixed64) -> Fixed64 { - let block_weight = System::all_extrinsics_weight(); - let max_weight = MaximumBlockWeight::get(); - let target_weight = (T::get() * max_weight) as u128; - let block_weight = block_weight as u128; - - // determines if the first_term is positive - let positive = block_weight >= target_weight; - let diff_abs = block_weight.max(target_weight) - block_weight.min(target_weight); - // diff is within u32, safe. - let diff = Fixed64::from_rational(diff_abs as i64, max_weight as u64); - let diff_squared = diff.saturating_mul(diff); - - // 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. - let v_squared_2 = Fixed64::from_rational(1, 1_000_000_000); - - let first_term = v.saturating_mul(diff); - // It is very unlikely that this will exist (in our poor perbill estimate) but we are giving - // it a shot. - let second_term = v_squared_2.saturating_mul(diff_squared); - - if positive { - // 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(excess) - } else { - // Proof: first_term > second_term. Safe subtraction. - let negative = first_term - second_term; - 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(Fixed64::from_rational(-1, 1)) - } - } -} - #[cfg(test)] -mod tests { +mod multiplier_tests { use super::*; - use sp_runtime::assert_eq_error_rate; - use crate::{MaximumBlockWeight, AvailableBlockRatio, Runtime}; - use crate::{constants::currency::*, TransactionPayment, TargetBlockFullness}; - use frame_support::weights::Weight; + use sp_runtime::{assert_eq_error_rate, FixedPointNumber}; + use pallet_transaction_payment::{Multiplier, TargetedFeeAdjustment}; + + use crate::{ + constants::{currency::*, time::*}, + TransactionPayment, MaximumBlockWeight, AvailableBlockRatio, Runtime, TargetBlockFullness, + AdjustmentVariable, System, MinimumMultiplier, + }; + use frame_support::weights::{Weight, WeightToFeePolynomial}; fn max() -> Weight { - MaximumBlockWeight::get() + AvailableBlockRatio::get() * MaximumBlockWeight::get() + } + + fn min_multiplier() -> Multiplier { + MinimumMultiplier::get() } fn target() -> Weight { TargetBlockFullness::get() * max() } - // poc reference implementation. - fn fee_multiplier_update(block_weight: Weight, previous: Fixed64) -> Fixed64 { - let block_weight = block_weight as f32; - let v: f32 = 0.00004; + // update based on runtime impl. + fn runtime_multiplier_update(fm: Multiplier) -> Multiplier { + TargetedFeeAdjustment::< + Runtime, + TargetBlockFullness, + AdjustmentVariable, + MinimumMultiplier, + >::convert(fm) + } + + // update based on reference impl. + fn truth_value_update(block_weight: Weight, previous: Multiplier) -> Multiplier { + let accuracy = Multiplier::accuracy() as f64; + let previous_float = previous.into_inner() as f64 / accuracy; + // bump if it is zero. + let previous_float = previous_float.max(min_multiplier().into_inner() as f64 / accuracy); // maximum tx weight - let m = max() as f32; + let m = max() as f64; + // block weight always truncated to max weight + let block_weight = (block_weight as f64).min(m); + let v: f64 = AdjustmentVariable::get().to_fraction(); + // Ideal saturation in terms of weight - let ss = target() as f32; + let ss = target() as f64; // Current saturation in terms of weight let s = block_weight; - 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) + let t1 = v * (s/m - ss/m); + let t2 = v.powi(2) * (s/m - ss/m).powi(2) / 2.0; + let next_float = previous_float * (1.0 + t1 + t2); + Multiplier::from_fraction(next_float) } fn run_with_system_weight(w: Weight, assertions: F) where F: Fn() -> () { @@ -159,11 +114,12 @@ mod tests { } #[test] - fn fee_multiplier_update_poc_works() { - let fm = Fixed64::from_rational(0, 1); + fn truth_value_update_poc_works() { + let fm = Multiplier::saturating_from_rational(1, 2); let test_set = vec![ (0, fm.clone()), (100, fm.clone()), + (1000, fm.clone()), (target(), fm.clone()), (max() / 2, fm.clone()), (max(), fm.clone()), @@ -171,36 +127,71 @@ mod tests { 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, + truth_value_update(w, fm), + runtime_multiplier_update(fm), + // Error is only 1 in 100^18 + Multiplier::from_inner(100), ); }) }) } #[test] - fn empty_chain_simulation() { - // just a few txs per_block. - let block_weight = 0; - run_with_system_weight(block_weight, || { - let mut fm = Fixed64::default(); + fn multiplier_can_grow_from_zero() { + // if the min is too small, then this will not change, and we are doomed forever. + // the weight is 1/100th bigger than target. + run_with_system_weight(target() * 101 / 100, || { + let next = runtime_multiplier_update(min_multiplier()); + assert!(next > min_multiplier(), "{:?} !>= {:?}", next, min_multiplier()); + }) + } + + #[test] + fn multiplier_cannot_go_below_limit() { + // will not go any further below even if block is empty. + run_with_system_weight(0, || { + let next = runtime_multiplier_update(min_multiplier()); + assert_eq!(next, min_multiplier()); + }) + } + + #[test] + fn time_to_reach_zero() { + // blocks per 24h in substrate-node: 28,800 (k) + // s* = 0.1875 + // The bound from the research in an empty chain is: + // v <~ (p / k(0 - s*)) + // p > v * k * -0.1875 + // to get p == -1 we'd need + // -1 > 0.00001 * k * -0.1875 + // 1 < 0.00001 * k * 0.1875 + // 10^9 / 1875 < k + // k > 533_333 ~ 18,5 days. + run_with_system_weight(0, || { + // start from 1, the default. + let mut fm = Multiplier::one(); let mut iterations: u64 = 0; loop { - let next = TargetedFeeAdjustment::::convert(fm); + let next = runtime_multiplier_update(fm); fm = next; - if fm == Fixed64::from_rational(-1, 1) { break; } + if fm == min_multiplier() { 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, - ); + assert!(iterations > 533_333); + }) + } + + #[test] + fn min_change_per_day() { + run_with_system_weight(max(), || { + let mut fm = Multiplier::one(); + // See the example in the doc of `TargetedFeeAdjustment`. are at least 0.234, hence + // `fm > 1.234`. + for _ in 0..DAYS { + let next = runtime_multiplier_update(fm); + fm = next; + } + assert!(fm > Multiplier::saturating_from_rational(1234, 1000)); }) } @@ -212,23 +203,24 @@ mod tests { // almost full. The entire quota of normal transactions is taken. let block_weight = AvailableBlockRatio::get() * max() - 100; - // Default substrate minimum. - let tx_weight = 10_000; + // Default substrate weight. + let tx_weight = frame_support::weights::constants::ExtrinsicBaseWeight::get(); run_with_system_weight(block_weight, || { // initial value configured on module - let mut fm = Fixed64::default(); + let mut fm = Multiplier::one(); assert_eq!(fm, TransactionPayment::next_fee_multiplier()); let mut iterations: u64 = 0; loop { - let next = TargetedFeeAdjustment::::convert(fm); + let next = runtime_multiplier_update(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); + let fee = + ::WeightToFee::calc(&tx_weight); + let adjusted_fee = fm.saturating_mul_acc_int(fee); println!( "iteration {}, new fm = {:?}. Fee at this point is: {} units / {} millicents, \ {} cents, {} dollars", @@ -245,80 +237,86 @@ mod tests { #[test] fn stateless_weight_mul() { + let fm = Multiplier::saturating_from_rational(1, 2); run_with_system_weight(target() / 4, || { - // Light block. Fee is reduced a little. - assert_eq!( - TargetedFeeAdjustment::::convert(Fixed64::default()), - feemul(-7500), + let next = runtime_multiplier_update(fm); + assert_eq_error_rate!( + next, + truth_value_update(target() / 4 , fm), + Multiplier::from_inner(100), ); + + // Light block. Multiplier is reduced a little. + assert!(next < fm); }); + 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), + let next = runtime_multiplier_update(fm); + assert_eq_error_rate!( + next, + truth_value_update(target() / 2 , fm), + Multiplier::from_inner(100), ); + // Light block. Multiplier is reduced a little. + assert!(next < fm); }); run_with_system_weight(target(), || { - // ideal. Original fee. No changes. - assert_eq!( - TargetedFeeAdjustment::::convert(Fixed64::default()), - feemul(0), + let next = runtime_multiplier_update(fm); + assert_eq_error_rate!( + next, + truth_value_update(target(), fm), + Multiplier::from_inner(100), ); + // ideal. No changes. + assert_eq!(next, fm) }); run_with_system_weight(target() * 2, || { - // // More than ideal. Fee is increased. - assert_eq!( - TargetedFeeAdjustment::::convert(Fixed64::default()), - feemul(10000), + // More than ideal. Fee is increased. + let next = runtime_multiplier_update(fm); + assert_eq_error_rate!( + next, + truth_value_update(target() * 2 , fm), + Multiplier::from_inner(100), ); + + // Heavy block. Fee is increased a little. + assert!(next > fm); }); } #[test] - fn stateful_weight_mul_grow_to_infinity() { + fn weight_mul_grow_on_big_block() { 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) - ); + let mut original = Multiplier::zero(); + let mut next = Multiplier::default(); + + (0..1_000).for_each(|_| { + next = runtime_multiplier_update(original); + assert_eq_error_rate!( + next, + truth_value_update(target() * 2, original), + Multiplier::from_inner(100), + ); + // must always increase + assert!(next > original, "{:?} !>= {:?}", next, original); + original = next; + }); }); } #[test] - fn stateful_weight_mil_collapse_to_minus_one() { - 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) - ); + fn weight_mul_decrease_on_small_block() { + run_with_system_weight(target() / 2, || { + let mut original = Multiplier::saturating_from_rational(1, 2); + let mut next; + + for _ in 0..100 { + // decreases + next = runtime_multiplier_update(original); + assert!(next < original, "{:?} !<= {:?}", next, original); + original = next; + } }) } @@ -326,7 +324,7 @@ mod tests { fn weight_to_fee_should_not_overflow_on_large_weights() { let kb = 1024 as Weight; let mb = kb * kb; - let max_fm = Fixed64::from_natural(i64::max_value()); + let max_fm = Multiplier::saturating_from_integer(i128::max_value()); // check that for all values it can compute, correctly. vec![ @@ -339,13 +337,17 @@ mod tests { 100 * kb, mb, 10 * mb, + 2147483647, + 4294967295, + MaximumBlockWeight::get() / 2, + MaximumBlockWeight::get(), 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); + let next = runtime_multiplier_update(Multiplier::one()); + let truth = truth_value_update(i, Multiplier::one()); + assert_eq_error_rate!(truth, next, Multiplier::from_inner(50_000_000)); }); }); @@ -355,7 +357,7 @@ mod tests { .into_iter() .for_each(|i| { run_with_system_weight(i, || { - let fm = TargetedFeeAdjustment::::convert(max_fm); + let fm = runtime_multiplier_update(max_fm); // won't grow. The convert saturates everything. assert_eq!(fm, max_fm); }) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 309f4ed0245e4b6e3006dd6b87613aff69ec1159..6e5a67387c601d175d133af55dc1be39044d2d75 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! The Substrate runtime. This can be compiled with ``#[no_std]`, ready for Wasm. @@ -21,49 +23,62 @@ #![recursion_limit="256"] use sp_std::prelude::*; + use frame_support::{ - construct_runtime, parameter_types, debug, - weights::Weight, - traits::{Currency, Randomness, OnUnbalanced, Imbalance}, + construct_runtime, parameter_types, debug, RuntimeDebug, + weights::{ + Weight, IdentityFee, + constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, + }, + traits::{Currency, Imbalance, KeyOwnerProofSystem, OnUnbalanced, Randomness, LockIdentifier}, +}; +use frame_system::{EnsureRoot, EnsureOneOf}; +use frame_support::traits::InstanceFilter; +use codec::{Encode, Decode}; +use sp_core::{ + crypto::KeyTypeId, + u32_trait::{_1, _2, _3, _4}, + OpaqueMetadata, }; -use sp_core::u32_trait::{_1, _2, _3, _4}; pub use node_primitives::{AccountId, Signature}; use node_primitives::{AccountIndex, Balance, BlockNumber, Hash, Index, Moment}; use sp_api::impl_runtime_apis; use sp_runtime::{ - Permill, Perbill, Percent, ApplyExtrinsicResult, - impl_opaque_keys, generic, create_runtime_str, + Permill, Perbill, Perquintill, Percent, ApplyExtrinsicResult, + impl_opaque_keys, generic, create_runtime_str, ModuleId, FixedPointNumber, }; use sp_runtime::curve::PiecewiseLinear; -use sp_runtime::transaction_validity::{TransactionValidity, TransactionSource}; +use sp_runtime::transaction_validity::{TransactionValidity, TransactionSource, TransactionPriority}; use sp_runtime::traits::{ self, BlakeTwo256, Block as BlockT, StaticLookup, SaturatedConversion, - ConvertInto, OpaqueKeys, + ConvertInto, OpaqueKeys, NumberFor, Saturating, }; use sp_version::RuntimeVersion; #[cfg(any(feature = "std", test))] use sp_version::NativeVersion; -use sp_core::OpaqueMetadata; -use pallet_grandpa::AuthorityList as GrandpaAuthorityList; +use pallet_grandpa::{AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; use pallet_grandpa::fg_primitives; -use pallet_im_online::sr25519::{AuthorityId as ImOnlineId}; +use pallet_im_online::sr25519::AuthorityId as ImOnlineId; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo; +pub use pallet_transaction_payment::{Multiplier, TargetedFeeAdjustment}; use pallet_contracts_rpc_runtime_api::ContractExecResult; -use frame_system::offchain::TransactionSubmitter; +use pallet_session::{historical as pallet_session_historical}; use sp_inherents::{InherentData, CheckInherentsResult}; +use static_assertions::const_assert; #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; -pub use pallet_timestamp::Call as TimestampCall; +#[cfg(any(feature = "std", test))] pub use pallet_balances::Call as BalancesCall; -pub use pallet_contracts::Gas; -pub use frame_support::StorageValue; -pub use pallet_staking::{StakerStatus, LockStakingStatus}; +#[cfg(any(feature = "std", test))] +pub use frame_system::Call as SystemCall; +#[cfg(any(feature = "std", test))] +pub use pallet_staking::StakerStatus; /// Implementations of some helper traits passed into runtime modules as associated types. pub mod impls; -use impls::{CurrencyToVoteHandler, Author, LinearWeightToFee, TargetedFeeAdjustment}; +use impls::{CurrencyToVoteHandler, Author}; /// Constant values used within the runtime. pub mod constants; @@ -73,52 +88,6 @@ use constants::{time::*, currency::*}; #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -/// A transaction submitter with the given key type. -pub type TransactionSubmitterOf = TransactionSubmitter; - -/// Submits transaction with the node's public and signature type. Adheres to the signed extension -/// format of the chain. -impl frame_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)> { - // take the biggest period possible. - let period = BlockHashCount::get() - .checked_next_power_of_two() - .map(|c| c / 2) - .unwrap_or(2) as u64; - let current_block = System::block_number() - .saturated_into::() - // The `System::block_number` is initialized with `n+1`, - // so the actual block number is `n`. - .saturating_sub(1); - let tip = 0; - let extra: SignedExtra = ( - frame_system::CheckVersion::::new(), - frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(generic::Era::mortal(period, current_block)), - frame_system::CheckNonce::::from(index), - frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(tip), - Default::default(), - Default::default(), - ); - let raw_payload = SignedPayload::new(call, extra).map_err(|e| { - debug::warn!("Unable to create signed payload: {:?}", e); - }).ok()?; - let signature = TSigner::sign(public, &raw_payload)?; - let address = Indices::unlookup(account); - let (call, extra, _) = raw_payload.deconstruct(); - Some((call, (address, signature, extra))) - } -} - /// Runtime version. pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("node"), @@ -128,9 +97,10 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // and set impl_version to 0. If only runtime // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. - spec_version: 240, + spec_version: 255, impl_version: 1, apis: RUNTIME_API_VERSIONS, + transaction_version: 1, }; /// Native version. @@ -160,15 +130,24 @@ impl OnUnbalanced for DealWithFees { } } +const AVERAGE_ON_INITIALIZE_WEIGHT: Perbill = Perbill::from_percent(10); parameter_types! { - pub const BlockHashCount: BlockNumber = 250; - pub const MaximumBlockWeight: Weight = 1_000_000_000; + pub const BlockHashCount: BlockNumber = 2400; + /// We allow for 2 seconds of compute with a 6 second average block time. + pub const MaximumBlockWeight: Weight = 2 * WEIGHT_PER_SECOND; + pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); + /// Assume 10% of weight for average on_initialize calls. + pub MaximumExtrinsicWeight: Weight = + AvailableBlockRatio::get().saturating_sub(AVERAGE_ON_INITIALIZE_WEIGHT) + * MaximumBlockWeight::get(); pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; pub const Version: RuntimeVersion = VERSION; - pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); } +const_assert!(AvailableBlockRatio::get().deconstruct() >= AVERAGE_ON_INITIALIZE_WEIGHT.deconstruct()); + impl frame_system::Trait for Runtime { + type BaseCallFilter = (); type Origin = Origin; type Call = Call; type Index = Index; @@ -181,6 +160,10 @@ impl frame_system::Trait for Runtime { type Event = Event; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = RocksDbWeight; + type BlockExecutionWeight = BlockExecutionWeight; + type ExtrinsicBaseWeight = ExtrinsicBaseWeight; + type MaximumExtrinsicWeight = MaximumExtrinsicWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = Version; @@ -188,34 +171,99 @@ impl frame_system::Trait for Runtime { type AccountData = pallet_balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); +} + +impl pallet_utility::Trait for Runtime { + type Event = Event; + type Call = Call; + type WeightInfo = (); } parameter_types! { - // One storage item; value is size 4+4+16+32 bytes = 56 bytes. - pub const MultisigDepositBase: Balance = 30 * CENTS; + // One storage item; key size is 32; value is size 4+4+16+32 bytes = 56 bytes. + pub const DepositBase: Balance = deposit(1, 88); // Additional storage item size of 32 bytes. - pub const MultisigDepositFactor: Balance = 5 * CENTS; + pub const DepositFactor: Balance = deposit(0, 32); pub const MaxSignatories: u16 = 100; } -impl pallet_utility::Trait for Runtime { +impl pallet_multisig::Trait for Runtime { type Event = Event; type Call = Call; type Currency = Balances; - type MultisigDepositBase = MultisigDepositBase; - type MultisigDepositFactor = MultisigDepositFactor; + type DepositBase = DepositBase; + type DepositFactor = DepositFactor; type MaxSignatories = MaxSignatories; + type WeightInfo = (); +} + +parameter_types! { + // One storage item; key size 32, value size 8; . + pub const ProxyDepositBase: Balance = deposit(1, 8); + // Additional storage item size of 33 bytes. + pub const ProxyDepositFactor: Balance = deposit(0, 33); + pub const MaxProxies: u16 = 32; +} + +/// The type used to represent the kinds of proxying allowed. +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug)] +pub enum ProxyType { + Any, + NonTransfer, + Governance, + Staking, +} +impl Default for ProxyType { fn default() -> Self { Self::Any } } +impl InstanceFilter for ProxyType { + fn filter(&self, c: &Call) -> bool { + match self { + ProxyType::Any => true, + ProxyType::NonTransfer => !matches!(c, + Call::Balances(..) | Call::Vesting(pallet_vesting::Call::vested_transfer(..)) + | Call::Indices(pallet_indices::Call::transfer(..)) + ), + ProxyType::Governance => matches!(c, + Call::Democracy(..) | Call::Council(..) | Call::Society(..) + | Call::TechnicalCommittee(..) | Call::Elections(..) | Call::Treasury(..) + ), + ProxyType::Staking => matches!(c, Call::Staking(..)), + } + } + fn is_superset(&self, o: &Self) -> bool { + match (self, o) { + (x, y) if x == y => true, + (ProxyType::Any, _) => true, + (_, ProxyType::Any) => false, + (ProxyType::NonTransfer, _) => true, + _ => false, + } + } +} + +impl pallet_proxy::Trait for Runtime { + type Event = Event; + type Call = Call; + type Currency = Balances; + type ProxyType = ProxyType; + type ProxyDepositBase = ProxyDepositBase; + type ProxyDepositFactor = ProxyDepositFactor; + type MaxProxies = MaxProxies; + type WeightInfo = (); } parameter_types! { - pub const MaximumWeight: Weight = 2_000_000; + pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * MaximumBlockWeight::get(); } impl pallet_scheduler::Trait for Runtime { type Event = Event; type Origin = Origin; + type PalletsOrigin = OriginCaller; type Call = Call; - type MaximumWeight = MaximumWeight; + type MaximumWeight = MaximumSchedulerWeight; + type ScheduleOrigin = EnsureRoot; + type WeightInfo = (); } parameter_types! { @@ -227,6 +275,21 @@ impl pallet_babe::Trait for Runtime { type EpochDuration = EpochDuration; type ExpectedBlockTime = ExpectedBlockTime; type EpochChangeTrigger = pallet_babe::ExternalTrigger; + + type KeyOwnerProofSystem = Historical; + + type KeyOwnerProof = >::Proof; + + type KeyOwnerIdentification = >::IdentificationTuple; + + type HandleEquivocation = + pallet_babe::EquivocationHandler; } parameter_types! { @@ -235,9 +298,10 @@ parameter_types! { impl pallet_indices::Trait for Runtime { type AccountIndex = AccountIndex; - type Event = Event; type Currency = Balances; type Deposit = IndexDeposit; + type Event = Event; + type WeightInfo = (); } parameter_types! { @@ -250,24 +314,23 @@ impl pallet_balances::Trait for Runtime { type Event = Event; type ExistentialDeposit = ExistentialDeposit; type AccountStore = frame_system::Module; + type WeightInfo = (); } 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); + pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25); + pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(1, 100_000); + pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 1_000_000_000u128); } impl pallet_transaction_payment::Trait for Runtime { type Currency = Balances; type OnTransactionPayment = DealWithFees; - type TransactionBaseFee = TransactionBaseFee; type TransactionByteFee = TransactionByteFee; - type WeightToFee = LinearWeightToFee; - type FeeMultiplierUpdate = TargetedFeeAdjustment; + type WeightToFee = IdentityFee; + type FeeMultiplierUpdate = + TargetedFeeAdjustment; } parameter_types! { @@ -278,6 +341,7 @@ impl pallet_timestamp::Trait for Runtime { type Moment = Moment; type OnTimestampSet = Babe; type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); } parameter_types! { @@ -309,11 +373,12 @@ impl pallet_session::Trait for Runtime { type ValidatorId = ::AccountId; type ValidatorIdOf = pallet_staking::StashOf; type ShouldEndSession = Babe; - type SessionManager = Staking; + type NextSessionRotation = Babe; + type SessionManager = pallet_session::historical::NoteHistoricalRoot; type SessionHandler = ::KeyTypeIdProviders; type Keys = SessionKeys; type DisabledValidatorsThreshold = DisabledValidatorsThreshold; - type NextSessionRotation = Babe; + type WeightInfo = (); } impl pallet_session::historical::Trait for Runtime { @@ -337,8 +402,11 @@ parameter_types! { pub const BondingDuration: pallet_staking::EraIndex = 24 * 28; pub const SlashDeferDuration: pallet_staking::EraIndex = 24 * 7; // 1/4 the bonding duration. pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE; - pub const ElectionLookahead: BlockNumber = 25; // 10 minutes per session => 100 block. pub const MaxNominatorRewardedPerValidator: u32 = 64; + pub const ElectionLookahead: BlockNumber = EPOCH_DURATION_IN_BLOCKS / 4; + pub const MaxIterations: u32 = 10; + // 0.05%. The higher the value, the more strict solution acceptance becomes. + pub MinSolutionScoreBump: Perbill = Perbill::from_rational_approximation(5u32, 10_000); } impl pallet_staking::Trait for Runtime { @@ -353,14 +421,21 @@ impl pallet_staking::Trait for Runtime { type BondingDuration = BondingDuration; type SlashDeferDuration = SlashDeferDuration; /// A super-majority of the council can cancel the slash. - type SlashCancelOrigin = pallet_collective::EnsureProportionAtLeast<_3, _4, AccountId, CouncilCollective>; + type SlashCancelOrigin = EnsureOneOf< + AccountId, + EnsureRoot, + pallet_collective::EnsureProportionAtLeast<_3, _4, AccountId, CouncilCollective> + >; type SessionInterface = Self; type RewardCurve = RewardCurve; type NextNewSession = Session; type ElectionLookahead = ElectionLookahead; type Call = Call; - type SubmitTransaction = TransactionSubmitterOf<()>; + type MaxIterations = MaxIterations; + type MinSolutionScoreBump = MinSolutionScoreBump; type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; + type UnsignedPriority = StakingUnsignedPriority; + type WeightInfo = (); } parameter_types! { @@ -373,6 +448,7 @@ parameter_types! { pub const CooloffPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; // One cent: $10,000 / MB pub const PreimageByteDeposit: Balance = 1 * CENTS; + pub const MaxVotes: u32 = 100; } impl pallet_democracy::Trait for Runtime { @@ -403,12 +479,17 @@ impl pallet_democracy::Trait for Runtime { type VetoOrigin = pallet_collective::EnsureMember; type CooloffPeriod = CooloffPeriod; type PreimageByteDeposit = PreimageByteDeposit; + type OperationalPreimageOrigin = pallet_collective::EnsureMember; type Slash = Treasury; type Scheduler = Scheduler; + type PalletsOrigin = OriginCaller; + type MaxVotes = MaxVotes; + type WeightInfo = (); } parameter_types! { pub const CouncilMotionDuration: BlockNumber = 5 * DAYS; + pub const CouncilMaxProposals: u32 = 100; } type CouncilCollective = pallet_collective::Instance1; @@ -417,6 +498,8 @@ impl pallet_collective::Trait for Runtime { type Proposal = Call; type Event = Event; type MotionDuration = CouncilMotionDuration; + type MaxProposals = CouncilMaxProposals; + type WeightInfo = (); } parameter_types! { @@ -425,10 +508,15 @@ parameter_types! { pub const TermDuration: BlockNumber = 7 * DAYS; pub const DesiredMembers: u32 = 13; pub const DesiredRunnersUp: u32 = 7; + pub const ElectionsPhragmenModuleId: LockIdentifier = *b"phrelect"; } +// Make sure that there are no more than `MAX_MEMBERS` members elected via elections-phragmen. +const_assert!(DesiredMembers::get() <= pallet_collective::MAX_MEMBERS); + impl pallet_elections_phragmen::Trait for Runtime { type Event = Event; + type ModuleId = ElectionsPhragmenModuleId; type Currency = Balances; type ChangeMembers = Council; // NOTE: this implies that council's genesis members cannot be set directly and must come from @@ -443,10 +531,12 @@ impl pallet_elections_phragmen::Trait for Runtime { type DesiredMembers = DesiredMembers; type DesiredRunnersUp = DesiredRunnersUp; type TermDuration = TermDuration; + type WeightInfo = (); } parameter_types! { pub const TechnicalMotionDuration: BlockNumber = 5 * DAYS; + pub const TechnicalMaxProposals: u32 = 100; } type TechnicalCollective = pallet_collective::Instance2; @@ -455,15 +545,22 @@ impl pallet_collective::Trait for Runtime { type Proposal = Call; type Event = Event; type MotionDuration = TechnicalMotionDuration; + type MaxProposals = TechnicalMaxProposals; + type WeightInfo = (); } +type EnsureRootOrHalfCouncil = EnsureOneOf< + AccountId, + EnsureRoot, + pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective> +>; impl pallet_membership::Trait for Runtime { type Event = Event; - type AddOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; - type RemoveOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; - type SwapOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; - type ResetOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; - type PrimeOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; + type AddOrigin = EnsureRootOrHalfCouncil; + type RemoveOrigin = EnsureRootOrHalfCouncil; + type SwapOrigin = EnsureRootOrHalfCouncil; + type ResetOrigin = EnsureRootOrHalfCouncil; + type PrimeOrigin = EnsureRootOrHalfCouncil; type MembershipInitialized = TechnicalCommittee; type MembershipChanged = TechnicalCommittee; } @@ -477,12 +574,22 @@ parameter_types! { pub const TipFindersFee: Percent = Percent::from_percent(20); pub const TipReportDepositBase: Balance = 1 * DOLLARS; pub const TipReportDepositPerByte: Balance = 1 * CENTS; + pub const TreasuryModuleId: ModuleId = ModuleId(*b"py/trsry"); } impl pallet_treasury::Trait for Runtime { + type ModuleId = TreasuryModuleId; type Currency = Balances; - type ApproveOrigin = pallet_collective::EnsureMembers<_4, AccountId, CouncilCollective>; - type RejectOrigin = pallet_collective::EnsureMembers<_2, AccountId, CouncilCollective>; + type ApproveOrigin = EnsureOneOf< + AccountId, + EnsureRoot, + pallet_collective::EnsureMembers<_4, AccountId, CouncilCollective> + >; + type RejectOrigin = EnsureOneOf< + AccountId, + EnsureRoot, + pallet_collective::EnsureMembers<_2, AccountId, CouncilCollective> + >; type Tippers = Elections; type TipCountdown = TipCountdown; type TipFindersFee = TipFindersFee; @@ -494,28 +601,23 @@ impl pallet_treasury::Trait for Runtime { type ProposalBondMinimum = ProposalBondMinimum; type SpendPeriod = SpendPeriod; type Burn = Burn; + type WeightInfo = (); } 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; + pub const TombstoneDeposit: Balance = 16 * MILLICENTS; + pub const RentByteFee: Balance = 4 * MILLICENTS; + pub const RentDepositOffset: Balance = 1000 * MILLICENTS; + pub const SurchargeReward: Balance = 150 * MILLICENTS; } impl pallet_contracts::Trait for Runtime { - type Currency = Balances; type Time = Timestamp; type Randomness = RandomnessCollectiveFlip; - type Call = Call; + type Currency = Balances; type Event = Event; type DetermineContractAddress = pallet_contracts::SimpleAddressDeterminer; - type ComputeDispatchFee = pallet_contracts::DefaultDispatchFeeComputor; type TrieIdGenerator = pallet_contracts::TrieIdFromParentCounter; - type GasPayment = (); type RentPayment = (); type SignedClaimHandicap = pallet_contracts::DefaultSignedClaimHandicap; type TombstoneDeposit = TombstoneDeposit; @@ -523,14 +625,9 @@ impl pallet_contracts::Trait for Runtime { type RentByteFee = RentByteFee; type RentDepositOffset = RentDepositOffset; type SurchargeReward = SurchargeReward; - type TransactionBaseFee = ContractTransactionBaseFee; - type TransactionByteFee = ContractTransactionByteFee; - type ContractFee = ContractFee; - type CallBaseFee = pallet_contracts::DefaultCallBaseFee; - type InstantiateBaseFee = pallet_contracts::DefaultInstantiateBaseFee; type MaxDepth = pallet_contracts::DefaultMaxDepth; type MaxValueSize = pallet_contracts::DefaultMaxValueSize; - type BlockGasLimit = pallet_contracts::DefaultBlockGasLimit; + type WeightPrice = pallet_transaction_payment::Module; } impl pallet_sudo::Trait for Runtime { @@ -540,27 +637,109 @@ impl pallet_sudo::Trait for Runtime { parameter_types! { pub const SessionDuration: BlockNumber = EPOCH_DURATION_IN_SLOTS as _; + pub const ImOnlineUnsignedPriority: TransactionPriority = TransactionPriority::max_value(); + /// We prioritize im-online heartbeats over election solution submission. + pub const StakingUnsignedPriority: TransactionPriority = TransactionPriority::max_value() / 2; +} + + +impl frame_system::offchain::CreateSignedTransaction for Runtime where + Call: From, +{ + fn create_transaction>( + call: Call, + public: ::Signer, + account: AccountId, + nonce: Index, + ) -> Option<(Call, ::SignaturePayload)> { + // take the biggest period possible. + let period = BlockHashCount::get() + .checked_next_power_of_two() + .map(|c| c / 2) + .unwrap_or(2) as u64; + let current_block = System::block_number() + .saturated_into::() + // The `System::block_number` is initialized with `n+1`, + // so the actual block number is `n`. + .saturating_sub(1); + let tip = 0; + let extra: SignedExtra = ( + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(generic::Era::mortal(period, current_block)), + frame_system::CheckNonce::::from(nonce), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(tip), + pallet_grandpa::ValidateEquivocationReport::::new(), + ); + let raw_payload = SignedPayload::new(call, extra).map_err(|e| { + debug::warn!("Unable to create signed payload: {:?}", e); + }).ok()?; + let signature = raw_payload.using_encoded(|payload| { + C::sign(payload, public) + })?; + let address = Indices::unlookup(account); + let (call, extra, _) = raw_payload.deconstruct(); + Some((call, (address, signature.into(), extra))) + } +} + +impl frame_system::offchain::SigningTypes for Runtime { + type Public = ::Signer; + type Signature = Signature; +} + +impl frame_system::offchain::SendTransactionTypes for Runtime where + Call: From, +{ + type Extrinsic = UncheckedExtrinsic; + type OverarchingCall = Call; } impl pallet_im_online::Trait for Runtime { type AuthorityId = ImOnlineId; type Event = Event; - type Call = Call; - type SubmitTransaction = TransactionSubmitterOf; type SessionDuration = SessionDuration; type ReportUnresponsiveness = Offences; + type UnsignedPriority = ImOnlineUnsignedPriority; + type WeightInfo = (); +} + +parameter_types! { + pub OffencesWeightSoftLimit: Weight = Perbill::from_percent(60) * MaximumBlockWeight::get(); } impl pallet_offences::Trait for Runtime { type Event = Event; type IdentificationTuple = pallet_session::historical::IdentificationTuple; type OnOffenceHandler = Staking; + type WeightSoftLimit = OffencesWeightSoftLimit; + type WeightInfo = (); } impl pallet_authority_discovery::Trait for Runtime {} impl pallet_grandpa::Trait for Runtime { type Event = Event; + type Call = Call; + + type KeyOwnerProofSystem = Historical; + + type KeyOwnerProof = + >::Proof; + + type KeyOwnerIdentification = >::IdentificationTuple; + + type HandleEquivocation = pallet_grandpa::EquivocationHandler< + Self::KeyOwnerIdentification, + node_primitives::report::ReporterAppCrypto, + Runtime, + Offences, + >; } parameter_types! { @@ -580,6 +759,7 @@ parameter_types! { pub const SubAccountDeposit: Balance = 2 * DOLLARS; // 53 bytes on-chain pub const MaxSubAccounts: u32 = 100; pub const MaxAdditionalFields: u32 = 100; + pub const MaxRegistrars: u32 = 20; } impl pallet_identity::Trait for Runtime { @@ -590,9 +770,11 @@ impl pallet_identity::Trait for Runtime { type SubAccountDeposit = SubAccountDeposit; type MaxSubAccounts = MaxSubAccounts; type MaxAdditionalFields = MaxAdditionalFields; + type MaxRegistrars = MaxRegistrars; type Slashed = Treasury; - type ForceOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; - type RegistrarOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; + type ForceOrigin = EnsureRootOrHalfCouncil; + type RegistrarOrigin = EnsureRootOrHalfCouncil; + type WeightInfo = (); } parameter_types! { @@ -620,10 +802,12 @@ parameter_types! { pub const PeriodSpend: Balance = 500 * DOLLARS; pub const MaxLockDuration: BlockNumber = 36 * 30 * DAYS; pub const ChallengePeriod: BlockNumber = 7 * DAYS; + pub const SocietyModuleId: ModuleId = ModuleId(*b"py/socie"); } impl pallet_society::Trait for Runtime { type Event = Event; + type ModuleId = SocietyModuleId; type Currency = Balances; type Randomness = RandomnessCollectiveFlip; type CandidateDeposit = CandidateDeposit; @@ -647,6 +831,7 @@ impl pallet_vesting::Trait for Runtime { type Currency = Balances; type BlockNumberToBalance = ConvertInto; type MinVestedTransfer = MinVestedTransfer; + type WeightInfo = (); } construct_runtime!( @@ -656,8 +841,8 @@ construct_runtime!( UncheckedExtrinsic = UncheckedExtrinsic { System: frame_system::{Module, Call, Config, Storage, Event}, - Utility: pallet_utility::{Module, Call, Storage, Event}, - Babe: pallet_babe::{Module, Call, Storage, Config, Inherent(Timestamp)}, + Utility: pallet_utility::{Module, Call, Event}, + Babe: pallet_babe::{Module, Call, Storage, Config, Inherent, ValidateUnsigned}, Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, Authorship: pallet_authorship::{Module, Call, Storage, Inherent}, Indices: pallet_indices::{Module, Call, Storage, Config, Event}, @@ -673,17 +858,20 @@ construct_runtime!( FinalityTracker: pallet_finality_tracker::{Module, Call, Inherent}, Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event}, Treasury: pallet_treasury::{Module, Call, Storage, Config, Event}, - Contracts: pallet_contracts::{Module, Call, Config, Storage, Event}, + Contracts: pallet_contracts::{Module, Call, Config, Storage, Event}, Sudo: pallet_sudo::{Module, Call, Config, Storage, Event}, ImOnline: pallet_im_online::{Module, Call, Storage, Event, ValidateUnsigned, Config}, AuthorityDiscovery: pallet_authority_discovery::{Module, Call, Config}, Offences: pallet_offences::{Module, Call, Storage, Event}, + Historical: pallet_session_historical::{Module}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, Identity: pallet_identity::{Module, Call, Storage, Event}, Society: pallet_society::{Module, Call, Storage, Event, Config}, Recovery: pallet_recovery::{Module, Call, Storage, Event}, Vesting: pallet_vesting::{Module, Call, Storage, Event, Config}, Scheduler: pallet_scheduler::{Module, Call, Storage, Event}, + Proxy: pallet_proxy::{Module, Call, Storage, Event}, + Multisig: pallet_multisig::{Module, Call, Storage, Event}, } ); @@ -698,15 +886,19 @@ pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; /// The SignedExtension to the basic transaction logic. +/// +/// When you change this, you **MUST** modify [`sign`] in `bin/node/testing/src/keyring.rs`! +/// +/// [`sign`]: <../../testing/src/keyring.rs.html> pub type SignedExtra = ( - frame_system::CheckVersion, + frame_system::CheckSpecVersion, + frame_system::CheckTxVersion, frame_system::CheckGenesis, frame_system::CheckEra, frame_system::CheckNonce, frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment, - pallet_contracts::CheckBlockGasLimit, - pallet_staking::LockStakingStatus, + pallet_grandpa::ValidateEquivocationReport, ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; @@ -779,28 +971,77 @@ impl_runtime_apis! { fn grandpa_authorities() -> GrandpaAuthorityList { Grandpa::grandpa_authorities() } + + fn submit_report_equivocation_extrinsic( + equivocation_proof: fg_primitives::EquivocationProof< + ::Hash, + NumberFor, + >, + key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof, + ) -> Option<()> { + let key_owner_proof = key_owner_proof.decode()?; + + Grandpa::submit_report_equivocation_extrinsic( + equivocation_proof, + key_owner_proof, + ) + } + + fn generate_key_ownership_proof( + _set_id: fg_primitives::SetId, + authority_id: GrandpaId, + ) -> Option { + use codec::Encode; + + Historical::prove((fg_primitives::KEY_TYPE, authority_id)) + .map(|p| p.encode()) + .map(fg_primitives::OpaqueKeyOwnershipProof::new) + } } impl sp_consensus_babe::BabeApi for Runtime { - fn configuration() -> sp_consensus_babe::BabeConfiguration { + fn configuration() -> sp_consensus_babe::BabeGenesisConfiguration { // 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. // - sp_consensus_babe::BabeConfiguration { + sp_consensus_babe::BabeGenesisConfiguration { slot_duration: Babe::slot_duration(), epoch_length: EpochDuration::get(), c: PRIMARY_PROBABILITY, genesis_authorities: Babe::authorities(), randomness: Babe::randomness(), - secondary_slots: true, + allowed_slots: sp_consensus_babe::AllowedSlots::PrimaryAndSecondaryPlainSlots, } } fn current_epoch_start() -> sp_consensus_babe::SlotNumber { Babe::current_epoch_start() } + + fn generate_key_ownership_proof( + _slot_number: sp_consensus_babe::SlotNumber, + authority_id: sp_consensus_babe::AuthorityId, + ) -> Option { + use codec::Encode; + + Historical::prove((sp_consensus_babe::KEY_TYPE, authority_id)) + .map(|p| p.encode()) + .map(sp_consensus_babe::OpaqueKeyOwnershipProof::new) + } + + fn submit_report_equivocation_unsigned_extrinsic( + equivocation_proof: sp_consensus_babe::EquivocationProof<::Header>, + key_owner_proof: sp_consensus_babe::OpaqueKeyOwnershipProof, + ) -> Option<()> { + let key_owner_proof = key_owner_proof.decode()?; + + Babe::submit_unsigned_equivocation_report( + equivocation_proof, + key_owner_proof, + ) + } } impl sp_authority_discovery::AuthorityDiscoveryApi for Runtime { @@ -825,12 +1066,13 @@ impl_runtime_apis! { gas_limit: u64, input_data: Vec, ) -> ContractExecResult { - let exec_result = + let (exec_result, gas_consumed) = Contracts::bare_call(origin, dest.into(), value, gas_limit, input_data); match exec_result { Ok(v) => ContractExecResult::Success { - status: v.status, + flags: v.flags.bits(), data: v.data, + gas_consumed: gas_consumed, }, Err(_) => ContractExecResult::Error, } @@ -867,7 +1109,7 @@ impl_runtime_apis! { fn decode_session_keys( encoded: Vec, - ) -> Option, sp_core::crypto::KeyTypeId)>> { + ) -> Option, KeyTypeId)>> { SessionKeys::decode_into_raw_public_keys(&encoded) } } @@ -887,21 +1129,53 @@ impl_runtime_apis! { // To get around that, we separated the Session benchmarks into its own crate, which is why // we need these two lines below. use pallet_session_benchmarking::Module as SessionBench; + use pallet_offences_benchmarking::Module as OffencesBench; + use frame_system_benchmarking::Module as SystemBench; + impl pallet_session_benchmarking::Trait for Runtime {} + impl pallet_offences_benchmarking::Trait for Runtime {} + impl frame_system_benchmarking::Trait for Runtime {} + + let whitelist: Vec> = vec![ + // Block Number + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec(), + // Total Issuance + hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec(), + // Execution Phase + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec(), + // Event Count + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec(), + // System Events + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec(), + // Caller 0 Account + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da946c154ffd9992e395af90b5b13cc6f295c77033fce8a9045824a6690bbf99c6db269502f0a8d1d2a008542d5690a0749").to_vec(), + // Treasury Account + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da95ecffd7b6c0f78751baa9d281e0bfa3a6d6f646c70792f74727372790000000000000000000000000000000000000000").to_vec(), + ]; let mut batches = Vec::::new(); - let params = (&pallet, &benchmark, &lowest_range_values, &highest_range_values, &steps, repeat); - add_benchmark!(params, batches, b"balances", Balances); - add_benchmark!(params, batches, b"collective", Council); - add_benchmark!(params, batches, b"democracy", Democracy); - add_benchmark!(params, batches, b"identity", Identity); - add_benchmark!(params, batches, b"im-online", ImOnline); - add_benchmark!(params, batches, b"session", SessionBench::); - add_benchmark!(params, batches, b"staking", Staking); - add_benchmark!(params, batches, b"timestamp", Timestamp); - add_benchmark!(params, batches, b"treasury", Treasury); - add_benchmark!(params, batches, b"utility", Utility); - add_benchmark!(params, batches, b"vesting", Vesting); + let params = (&pallet, &benchmark, &lowest_range_values, &highest_range_values, &steps, repeat, &whitelist); + + add_benchmark!(params, batches, pallet_babe, Babe); + add_benchmark!(params, batches, pallet_balances, Balances); + add_benchmark!(params, batches, pallet_collective, Council); + add_benchmark!(params, batches, pallet_democracy, Democracy); + add_benchmark!(params, batches, pallet_elections_phragmen, Elections); + add_benchmark!(params, batches, pallet_identity, Identity); + add_benchmark!(params, batches, pallet_im_online, ImOnline); + add_benchmark!(params, batches, pallet_indices, Indices); + add_benchmark!(params, batches, pallet_multisig, Multisig); + add_benchmark!(params, batches, pallet_offences, OffencesBench::); + add_benchmark!(params, batches, pallet_proxy, Proxy); + add_benchmark!(params, batches, pallet_scheduler, Scheduler); + add_benchmark!(params, batches, pallet_session, SessionBench::); + add_benchmark!(params, batches, pallet_staking, Staking); + add_benchmark!(params, batches, frame_system, SystemBench::); + add_benchmark!(params, batches, pallet_timestamp, Timestamp); + add_benchmark!(params, batches, pallet_treasury, Treasury); + add_benchmark!(params, batches, pallet_utility, Utility); + add_benchmark!(params, batches, pallet_vesting, Vesting); + if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } Ok(batches) } @@ -911,28 +1185,14 @@ impl_runtime_apis! { #[cfg(test)] mod tests { use super::*; - use frame_system::offchain::{SignAndSubmitTransaction, SubmitSignedTransaction}; + use frame_system::offchain::CreateSignedTransaction; #[test] fn validate_transaction_submitter_bounds() { fn is_submit_signed_transaction() where - T: SubmitSignedTransaction< - Runtime, - Call, - >, - {} - - fn is_sign_and_submit_transaction() where - T: SignAndSubmitTransaction< - Runtime, - Call, - Extrinsic=UncheckedExtrinsic, - CreateTransaction=Runtime, - Signer=ImOnlineId, - >, + T: CreateSignedTransaction, {} - is_submit_signed_transaction::>(); - is_sign_and_submit_transaction::>(); + is_submit_signed_transaction::(); } } diff --git a/bin/node/testing/Cargo.toml b/bin/node/testing/Cargo.toml index df73e20070d2cedca064206d6b6dfc9b796272f2..fbf369cc3b4e4cfd60303afea26a8380a25ece18 100644 --- a/bin/node/testing/Cargo.toml +++ b/bin/node/testing/Cargo.toml @@ -1,57 +1,57 @@ [package] name = "node-testing" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] description = "Test utilities for Substrate node." edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" publish = true +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -pallet-balances = { version = "2.0.0-alpha.5", path = "../../../frame/balances" } -sc-client = { version = "0.8.0-alpha.5", path = "../../../client/" } -sc-client-db = { version = "0.8.0-alpha.5", path = "../../../client/db/", features = ["kvdb-rocksdb"] } -sc-client-api = { version = "2.0.0-alpha.5", path = "../../../client/api/" } -codec = { package = "parity-scale-codec", version = "1.3.0" } -pallet-contracts = { version = "2.0.0-alpha.5", path = "../../../frame/contracts" } -pallet-grandpa = { version = "2.0.0-alpha.5", path = "../../../frame/grandpa" } -pallet-indices = { version = "2.0.0-alpha.5", path = "../../../frame/indices" } -sp-keyring = { version = "2.0.0-alpha.5", path = "../../../primitives/keyring" } -node-executor = { version = "2.0.0-alpha.5", path = "../executor" } -node-primitives = { version = "2.0.0-alpha.5", path = "../primitives" } -node-runtime = { version = "2.0.0-alpha.5", path = "../runtime" } -sp-core = { version = "2.0.0-alpha.5", path = "../../../primitives/core" } -sp-io = { version = "2.0.0-alpha.5", path = "../../../primitives/io" } -frame-support = { version = "2.0.0-alpha.5", path = "../../../frame/support" } -pallet-session = { version = "2.0.0-alpha.5", path = "../../../frame/session" } -pallet-society = { version = "2.0.0-alpha.5", path = "../../../frame/society" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime" } -pallet-staking = { version = "2.0.0-alpha.5", path = "../../../frame/staking" } -sc-executor = { version = "0.8.0-alpha.5", path = "../../../client/executor", features = ["wasmtime"] } -sp-consensus = { version = "0.8.0-alpha.5", path = "../../../primitives/consensus/common" } -frame-system = { version = "2.0.0-alpha.5", path = "../../../frame/system" } -substrate-test-client = { version = "2.0.0-dev", path = "../../../test-utils/client" } -pallet-timestamp = { version = "2.0.0-alpha.5", path = "../../../frame/timestamp" } -pallet-transaction-payment = { version = "2.0.0-alpha.5", path = "../../../frame/transaction-payment" } -pallet-treasury = { version = "2.0.0-alpha.5", path = "../../../frame/treasury" } +pallet-balances = { version = "2.0.0-rc4", path = "../../../frame/balances" } +sc-service = { version = "0.8.0-rc4", features = ["test-helpers", "db"], path = "../../../client/service" } +sc-client-db = { version = "0.8.0-rc4", path = "../../../client/db/", features = ["kvdb-rocksdb", "parity-db"] } +sc-client-api = { version = "2.0.0-rc4", path = "../../../client/api/" } +codec = { package = "parity-scale-codec", version = "1.3.1" } +pallet-contracts = { version = "2.0.0-rc4", path = "../../../frame/contracts" } +pallet-grandpa = { version = "2.0.0-rc4", path = "../../../frame/grandpa" } +pallet-indices = { version = "2.0.0-rc4", path = "../../../frame/indices" } +sp-keyring = { version = "2.0.0-rc4", path = "../../../primitives/keyring" } +node-executor = { version = "2.0.0-rc4", path = "../executor" } +node-primitives = { version = "2.0.0-rc4", path = "../primitives" } +node-runtime = { version = "2.0.0-rc4", path = "../runtime" } +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } +sp-io = { version = "2.0.0-rc4", path = "../../../primitives/io" } +frame-support = { version = "2.0.0-rc4", path = "../../../frame/support" } +pallet-session = { version = "2.0.0-rc4", path = "../../../frame/session" } +pallet-society = { version = "2.0.0-rc4", path = "../../../frame/society" } +sp-runtime = { version = "2.0.0-rc4", path = "../../../primitives/runtime" } +pallet-staking = { version = "2.0.0-rc4", path = "../../../frame/staking" } +sc-executor = { version = "0.8.0-rc4", path = "../../../client/executor", features = ["wasmtime"] } +sp-consensus = { version = "0.8.0-rc4", path = "../../../primitives/consensus/common" } +frame-system = { version = "2.0.0-rc4", path = "../../../frame/system" } +substrate-test-client = { version = "2.0.0-rc4", path = "../../../test-utils/client" } +pallet-timestamp = { version = "2.0.0-rc4", path = "../../../frame/timestamp" } +pallet-transaction-payment = { version = "2.0.0-rc4", path = "../../../frame/transaction-payment" } +pallet-treasury = { version = "2.0.0-rc4", path = "../../../frame/treasury" } wabt = "0.9.2" -sp-api = { version = "2.0.0-alpha.5", path = "../../../primitives/api" } -sp-finality-tracker = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/finality-tracker" } -sp-timestamp = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/timestamp" } -sp-block-builder = { version = "2.0.0-alpha.5", path = "../../../primitives/block-builder" } -sc-block-builder = { version = "0.8.0-alpha.5", path = "../../../client/block-builder" } -sp-inherents = { version = "2.0.0-alpha.5", path = "../../../primitives/inherents" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../../primitives/blockchain" } +sp-api = { version = "2.0.0-rc4", path = "../../../primitives/api" } +sp-finality-tracker = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/finality-tracker" } +sp-timestamp = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/timestamp" } +sp-block-builder = { version = "2.0.0-rc4", path = "../../../primitives/block-builder" } +sc-block-builder = { version = "0.8.0-rc4", path = "../../../client/block-builder" } +sp-inherents = { version = "2.0.0-rc4", path = "../../../primitives/inherents" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../../primitives/blockchain" } log = "0.4.8" tempfile = "3.1.0" fs_extra = "1" +futures = "0.3.1" [dev-dependencies] criterion = "0.3.0" -sc-cli = { version = "0.8.0-alpha.5", path = "../../../client/cli" } -sc-service = { version = "0.8.0-alpha.5", path = "../../../client/service", features = ["rocksdb"] } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +sc-cli = { version = "0.8.0-rc4", path = "../../../client/cli" } diff --git a/bin/node/testing/src/bench.rs b/bin/node/testing/src/bench.rs index 3bc8d483ea2afe4c7cadc0ad9a74e746b14121ea..507d3420d835470e41fd1f1bb71fef9eaee9ad60 100644 --- a/bin/node/testing/src/bench.rs +++ b/bin/node/testing/src/bench.rs @@ -1,18 +1,20 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Benchmarking module. //! @@ -20,7 +22,7 @@ //! can pregenerate seed database and `clone` it for every iteration of your benchmarks //! or tests to get consistent, smooth benchmark experience! -use std::{sync::Arc, path::Path, collections::BTreeMap}; +use std::{sync::Arc, path::{Path, PathBuf}, collections::BTreeMap}; use node_primitives::Block; use crate::client::{Client, Backend}; @@ -43,20 +45,22 @@ use node_runtime::{ constants::currency::DOLLARS, UncheckedExtrinsic, MinimumPeriod, + SystemCall, BalancesCall, AccountId, Signature, }; -use sp_core::{ExecutionContext, blake2_256}; +use sp_core::{ExecutionContext, blake2_256, traits::CloneableSpawn}; use sp_api::ProvideRuntimeApi; use sp_block_builder::BlockBuilder; use sp_inherents::InherentData; use sc_client_api::{ - ExecutionStrategy, + ExecutionStrategy, BlockBackend, execution_extensions::{ExecutionExtensions, ExecutionStrategies}, }; use sp_core::{Pair, Public, sr25519, ed25519}; use sc_block_builder::BlockBuilderProvider; +use futures::{executor, task}; /// Keyring full of accounts for benching. /// @@ -92,11 +96,13 @@ impl BenchPair { pub struct BenchDb { keyring: BenchKeyring, directory_guard: Guard, + database_type: DatabaseType, } impl Clone for BenchDb { fn clone(&self) -> Self { let keyring = self.keyring.clone(); + let database_type = self.database_type; let dir = tempfile::tempdir().expect("temp dir creation failed"); let seed_dir = self.directory_guard.0.path(); @@ -120,7 +126,7 @@ impl Clone for BenchDb { &fs_extra::dir::CopyOptions::new(), ).expect("Copy of seed database is ok"); - BenchDb { keyring, directory_guard: Guard(dir) } + BenchDb { keyring, directory_guard: Guard(dir), database_type } } } @@ -128,26 +134,180 @@ impl Clone for BenchDb { #[derive(Debug, PartialEq, Clone, Copy)] pub enum BlockType { /// Bunch of random transfers. - RandomTransfers(usize), + RandomTransfersKeepAlive, /// Bunch of random transfers that drain all of the source balance. - RandomTransfersReaping(usize), + RandomTransfersReaping, + /// Bunch of "no-op" calls. + Noop, } impl BlockType { - /// Number of transactions for this block type. - pub fn transactions(&self) -> usize { + /// Create block content description with specified number of transactions. + pub fn to_content(self, size: Option) -> BlockContent { + BlockContent { + block_type: self, + size: size, + } + } +} + +/// Content of the generated block. +#[derive(Clone, Debug)] +pub struct BlockContent { + block_type: BlockType, + size: Option, +} + +/// Type of backend database. +#[derive(Debug, PartialEq, Clone, Copy)] +pub enum DatabaseType { + /// RocksDb backend. + RocksDb, + /// Parity DB backend. + ParityDb, +} + +impl DatabaseType { + fn into_settings(self, path: PathBuf) -> sc_client_db::DatabaseSettingsSrc { match self { - Self::RandomTransfers(v) | Self::RandomTransfersReaping(v) => *v, + Self::RocksDb => sc_client_db::DatabaseSettingsSrc::RocksDb { + path, + cache_size: 512, + }, + Self::ParityDb => sc_client_db::DatabaseSettingsSrc::ParityDb { + path, + } + } + } +} + +/// Benchmarking task executor. +/// +/// Uses multiple threads as the regular executable. +#[derive(Debug, Clone)] +pub struct TaskExecutor { + pool: executor::ThreadPool, +} + +impl TaskExecutor { + fn new() -> Self { + Self { + pool: executor::ThreadPool::new() + .expect("Failed to create task executor") + } + } +} + +impl task::Spawn for TaskExecutor { + fn spawn_obj(&self, future: task::FutureObj<'static, ()>) + -> Result<(), task::SpawnError> { + self.pool.spawn_obj(future) + } +} + +impl CloneableSpawn for TaskExecutor { + fn clone(&self) -> Box { + Box::new(Clone::clone(self)) + } +} + +/// Iterator for block content. +pub struct BlockContentIterator<'a> { + iteration: usize, + content: BlockContent, + runtime_version: sc_executor::RuntimeVersion, + genesis_hash: node_primitives::Hash, + keyring: &'a BenchKeyring, +} + +impl<'a> BlockContentIterator<'a> { + fn new(content: BlockContent, keyring: &'a BenchKeyring, client: &Client) -> Self { + let runtime_version = client.runtime_version_at(&BlockId::number(0)) + .expect("There should be runtime version at 0"); + + let genesis_hash = client.block_hash(Zero::zero()) + .expect("Database error?") + .expect("Genesis block always exists; qed") + .into(); + + BlockContentIterator { + iteration: 0, + content, + keyring, + runtime_version, + genesis_hash, } } } +impl<'a> Iterator for BlockContentIterator<'a> { + type Item = OpaqueExtrinsic; + + fn next(&mut self) -> Option { + if self.content.size.map(|size| size <= self.iteration).unwrap_or(false) { + return None; + } + + let sender = self.keyring.at(self.iteration); + let receiver = get_account_id_from_seed::( + &format!("random-user//{}", self.iteration) + ); + + let signed = self.keyring.sign( + CheckedExtrinsic { + signed: Some((sender, signed_extra(0, node_runtime::ExistentialDeposit::get() + 1))), + function: match self.content.block_type { + BlockType::RandomTransfersKeepAlive => { + Call::Balances( + BalancesCall::transfer_keep_alive( + pallet_indices::address::Address::Id(receiver), + node_runtime::ExistentialDeposit::get() + 1, + ) + ) + }, + BlockType::RandomTransfersReaping => { + Call::Balances( + BalancesCall::transfer( + pallet_indices::address::Address::Id(receiver), + // Transfer so that ending balance would be 1 less than existential deposit + // so that we kill the sender account. + 100*DOLLARS - (node_runtime::ExistentialDeposit::get() - 1), + ) + ) + }, + BlockType::Noop => { + Call::System( + SystemCall::remark(Vec::new()) + ) + }, + }, + }, + self.runtime_version.spec_version, + self.runtime_version.transaction_version, + self.genesis_hash.into(), + ); + + let encoded = Encode::encode(&signed); + + let opaque = OpaqueExtrinsic::decode(&mut &encoded[..]) + .expect("Failed to decode opaque"); + + self.iteration += 1; + + Some(opaque) + } +} + impl BenchDb { /// New immutable benchmarking database. /// - /// See [`new`] method documentation for more information about the purpose + /// See [`BenchDb::new`] method documentation for more information about the purpose /// of this structure. - pub fn with_key_types(keyring_length: usize, key_types: KeyTypes) -> Self { + pub fn with_key_types( + database_type: DatabaseType, + keyring_length: usize, + key_types: KeyTypes, + ) -> Self { let keyring = BenchKeyring::new(keyring_length, key_types); let dir = tempfile::tempdir().expect("temp dir creation failed"); @@ -156,10 +316,10 @@ impl BenchDb { "Created seed db at {}", dir.path().to_string_lossy(), ); - let (_client, _backend) = Self::bench_client(dir.path(), Profile::Native, &keyring); + let (_client, _backend) = Self::bench_client(database_type, dir.path(), Profile::Native, &keyring); let directory_guard = Guard(dir); - BenchDb { keyring, directory_guard } + BenchDb { keyring, directory_guard, database_type } } /// New immutable benchmarking database. @@ -168,10 +328,10 @@ impl BenchDb { /// and keep it there until struct is dropped. /// /// You can `clone` this database or you can `create_context` from it - /// (which also do `clone`) to run actual operation against new database - /// which will be identical to this. - pub fn new(keyring_length: usize) -> Self { - Self::with_key_types(keyring_length, KeyTypes::Sr25519) + /// (which also does `clone`) to run actual operation against new database + /// which will be identical to the original. + pub fn new(database_type: DatabaseType, keyring_length: usize) -> Self { + Self::with_key_types(database_type, keyring_length, KeyTypes::Sr25519) } // This should return client that is doing everything that full node @@ -179,101 +339,85 @@ impl BenchDb { // // - This client should use best wasm execution method. // - This client should work with real database only. - fn bench_client(dir: &std::path::Path, profile: Profile, keyring: &BenchKeyring) -> (Client, std::sync::Arc) { + fn bench_client( + database_type: DatabaseType, + dir: &std::path::Path, + profile: Profile, + keyring: &BenchKeyring, + ) -> (Client, std::sync::Arc) { let db_config = sc_client_db::DatabaseSettings { state_cache_size: 16*1024*1024, state_cache_child_ratio: Some((0, 100)), pruning: PruningMode::ArchiveAll, - source: sc_client_db::DatabaseSettingsSrc::Path { - path: dir.into(), - cache_size: None, - }, + source: database_type.into_settings(dir.into()), }; - let (client, backend) = sc_client_db::new_client( + let (client, backend) = sc_service::new_client( db_config, NativeExecutor::new(WasmExecutionMethod::Compiled, None, 8), &keyring.generate_genesis(), None, None, ExecutionExtensions::new(profile.into_execution_strategies(), None), - sp_core::tasks::executor(), + Box::new(TaskExecutor::new()), None, + Default::default(), ).expect("Should not fail"); (client, backend) } - /// Generate new block using this database. - pub fn generate_block(&mut self, block_type: BlockType) -> Block { - let (client, _backend) = Self::bench_client( - self.directory_guard.path(), - Profile::Wasm, - &self.keyring, - ); - - let version = client.runtime_version_at(&BlockId::number(0)) - .expect("There should be runtime version at 0") - .spec_version; - - let genesis_hash = client.block_hash(Zero::zero()) - .expect("Database error?") - .expect("Genesis block always exists; qed") - .into(); - - let mut block = client - .new_block(Default::default()) - .expect("Block creation failed"); - + /// Generate list of required inherents. + /// + /// Uses already instantiated Client. + pub fn generate_inherents(&mut self, client: &Client) -> Vec { + let mut inherent_data = InherentData::new(); let timestamp = 1 * MinimumPeriod::get(); - let mut inherent_data = InherentData::new(); inherent_data.put_data(sp_timestamp::INHERENT_IDENTIFIER, ×tamp) .expect("Put timestamp failed"); inherent_data.put_data(sp_finality_tracker::INHERENT_IDENTIFIER, &0) .expect("Put finality tracker failed"); - for extrinsic in client.runtime_api() + client.runtime_api() .inherent_extrinsics_with_context( &BlockId::number(0), ExecutionContext::BlockConstruction, inherent_data, ).expect("Get inherents failed") - { - block.push(extrinsic).expect("Push inherent failed"); - } + } - let mut iteration = 0; - let start = std::time::Instant::now(); - for _ in 0..block_type.transactions() { - - let sender = self.keyring.at(iteration); - let receiver = get_account_id_from_seed::( - &format!("random-user//{}", iteration) - ); - - let signed = self.keyring.sign( - CheckedExtrinsic { - signed: Some((sender, signed_extra(0, node_runtime::ExistentialDeposit::get() + 1))), - function: Call::Balances( - BalancesCall::transfer( - pallet_indices::address::Address::Id(receiver), - match block_type { - BlockType::RandomTransfers(_) => node_runtime::ExistentialDeposit::get() + 1, - BlockType::RandomTransfersReaping(_) => 100*DOLLARS - node_runtime::ExistentialDeposit::get() - 1, - } - ) - ), - }, - version, - genesis_hash, - ); + /// Iterate over some block content with transaction signed using this database keyring. + pub fn block_content(&self, content: BlockContent, client: &Client) -> BlockContentIterator { + BlockContentIterator::new(content, &self.keyring, client) + } - let encoded = Encode::encode(&signed); + /// Get cliet for this database operations. + pub fn client(&mut self) -> Client { + let (client, _backend) = Self::bench_client( + self.database_type, + self.directory_guard.path(), + Profile::Wasm, + &self.keyring, + ); - let opaque = OpaqueExtrinsic::decode(&mut &encoded[..]) - .expect("Failed to decode opaque"); + client + } + + /// Generate new block using this database. + pub fn generate_block(&mut self, content: BlockContent) -> Block { + let client = self.client(); + let mut block = client + .new_block(Default::default()) + .expect("Block creation failed"); + + for extrinsic in self.generate_inherents(&client) { + block.push(extrinsic).expect("Push inherent failed"); + } + + let start = std::time::Instant::now(); + for opaque in self.block_content(content, &client) { match block.push(opaque) { Err(sp_blockchain::Error::ApplyExtrinsicFailed( sp_blockchain::ApplyExtrinsicFailed::Validity(e) @@ -283,8 +427,8 @@ impl BenchDb { Err(err) => panic!("Error pushing transaction: {:?}", err), Ok(_) => {}, } - iteration += 1; - } + }; + let block = block.build().expect("Block build failed").block; log::info!( @@ -303,11 +447,16 @@ impl BenchDb { /// Clone this database and create context for testing/benchmarking. pub fn create_context(&self, profile: Profile) -> BenchContext { - let BenchDb { directory_guard, keyring } = self.clone(); - let (client, backend) = Self::bench_client(directory_guard.path(), profile, &keyring); + let BenchDb { directory_guard, keyring, database_type } = self.clone(); + let (client, backend) = Self::bench_client( + database_type, + directory_guard.path(), + profile, + &keyring + ); BenchContext { - client, backend, db_guard: directory_guard, + client: Arc::new(client), backend, db_guard: directory_guard, } } } @@ -358,10 +507,16 @@ impl BenchKeyring { } /// Sign transaction with keypair from this keyring. - pub fn sign(&self, xt: CheckedExtrinsic, version: u32, genesis_hash: [u8; 32]) -> UncheckedExtrinsic { + pub fn sign( + &self, + xt: CheckedExtrinsic, + spec_version: u32, + tx_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 payload = (xt.function, extra.clone(), spec_version, tx_version, genesis_hash, genesis_hash); let key = self.accounts.get(&signed).expect("Account id not found in keyring"); let signature = payload.using_encoded(|b| { if b.len() > 256 { @@ -433,7 +588,7 @@ impl Guard { /// Benchmarking/test context holding instantiated client and backend references. pub struct BenchContext { /// Node client. - pub client: Client, + pub client: Arc, /// Node backend. pub backend: Arc, diff --git a/bin/node/testing/src/client.rs b/bin/node/testing/src/client.rs index 963bac7041b7d8ac25686e8e872b72d9210fb23b..f44747b26b7a6eb6409e76063b23914f3fb43f66 100644 --- a/bin/node/testing/src/client.rs +++ b/bin/node/testing/src/client.rs @@ -1,23 +1,25 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Utilities to build a `TestClient` for `node-runtime`. use sp_runtime::BuildStorage; - +use sc_service::client; /// Re-export test-client utilities. pub use substrate_test_client::*; @@ -28,9 +30,9 @@ pub type Executor = sc_executor::NativeExecutor; pub type Backend = sc_client_db::Backend; /// Test client type. -pub type Client = sc_client::Client< +pub type Client = client::Client< Backend, - sc_client::LocalCallExecutor, + client::LocalCallExecutor, node_primitives::Block, node_runtime::RuntimeApi, >; @@ -61,7 +63,7 @@ pub trait TestClientBuilderExt: Sized { impl TestClientBuilderExt for substrate_test_client::TestClientBuilder< node_primitives::Block, - sc_client::LocalCallExecutor, + client::LocalCallExecutor, Backend, GenesisParameters, > { diff --git a/bin/node/testing/src/genesis.rs b/bin/node/testing/src/genesis.rs index 8a57010770f3dedf9795e0da462455943fb6f74d..2bbae96cf4332f08c24469857388d72877877653 100644 --- a/bin/node/testing/src/genesis.rs +++ b/bin/node/testing/src/genesis.rs @@ -1,18 +1,20 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Genesis Configuration. @@ -21,7 +23,7 @@ use sp_keyring::{Ed25519Keyring, Sr25519Keyring}; use node_runtime::{ GenesisConfig, BalancesConfig, SessionConfig, StakingConfig, SystemConfig, GrandpaConfig, IndicesConfig, ContractsConfig, SocietyConfig, WASM_BINARY, - AccountId, + AccountId, StakerStatus, }; use node_runtime::constants::currency::*; use sp_core::ChangesTrieConfiguration; @@ -85,9 +87,9 @@ pub fn config_endowed( }), pallet_staking: Some(StakingConfig { stakers: vec![ - (dave(), alice(), 111 * DOLLARS, pallet_staking::StakerStatus::Validator), - (eve(), bob(), 100 * DOLLARS, pallet_staking::StakerStatus::Validator), - (ferdie(), charlie(), 100 * DOLLARS, pallet_staking::StakerStatus::Validator) + (dave(), alice(), 111 * DOLLARS, StakerStatus::Validator), + (eve(), bob(), 100 * DOLLARS, StakerStatus::Validator), + (ferdie(), charlie(), 100 * DOLLARS, StakerStatus::Validator) ], validator_count: 3, minimum_validator_count: 0, @@ -97,7 +99,6 @@ pub fn config_endowed( }), pallet_contracts: Some(ContractsConfig { current_schedule: Default::default(), - gas_price: 1 * MILLICENTS, }), pallet_babe: Some(Default::default()), pallet_grandpa: Some(GrandpaConfig { diff --git a/bin/node/testing/src/keyring.rs b/bin/node/testing/src/keyring.rs index 5fa1e48b0321813d3c9bec039ec3212c5be4216a..efa47a59821945caa16a271b81bc7dcd344b5292 100644 --- a/bin/node/testing/src/keyring.rs +++ b/bin/node/testing/src/keyring.rs @@ -1,18 +1,20 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Test accounts. @@ -68,22 +70,22 @@ pub fn to_session_keys( /// Returns transaction extra. pub fn signed_extra(nonce: Index, extra_fee: Balance) -> SignedExtra { ( - frame_system::CheckVersion::new(), + frame_system::CheckSpecVersion::new(), + frame_system::CheckTxVersion::new(), frame_system::CheckGenesis::new(), frame_system::CheckEra::from(Era::mortal(256, 0)), frame_system::CheckNonce::from(nonce), frame_system::CheckWeight::new(), pallet_transaction_payment::ChargeTransactionPayment::from(extra_fee), - Default::default(), - Default::default(), + pallet_grandpa::ValidateEquivocationReport::new(), ) } /// Sign given `CheckedExtrinsic`. -pub fn sign(xt: CheckedExtrinsic, version: u32, genesis_hash: [u8; 32]) -> UncheckedExtrinsic { +pub fn sign(xt: CheckedExtrinsic, spec_version: u32, tx_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 payload = (xt.function, extra.clone(), spec_version, tx_version, genesis_hash, genesis_hash); let key = AccountKeyring::from_account_id(&signed).unwrap(); let signature = payload.using_encoded(|b| { if b.len() > 256 { diff --git a/bin/node/testing/src/lib.rs b/bin/node/testing/src/lib.rs index 6a06d318016f290fd96d6a33fbe7c2e2163ce988..d682347e40019dd4a7ff74a8716929130623f31e 100644 --- a/bin/node/testing/src/lib.rs +++ b/bin/node/testing/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! A set of testing utilities for Substrate Node. diff --git a/bin/node/transaction-factory/Cargo.toml b/bin/node/transaction-factory/Cargo.toml deleted file mode 100644 index 33ebeb767ae37e75c04309c958e3de79096bee67..0000000000000000000000000000000000000000 --- a/bin/node/transaction-factory/Cargo.toml +++ /dev/null @@ -1,26 +0,0 @@ -[package] -name = "node-transaction-factory" -version = "0.8.0-alpha.5" -authors = ["Parity Technologies "] -edition = "2018" -license = "GPL-3.0" -homepage = "https://substrate.dev" -repository = "https://github.com/paritytech/substrate/" - -[dependencies] -sp-block-builder = { version = "2.0.0-alpha.5", path = "../../../primitives/block-builder" } -sc-cli = { version = "0.8.0-alpha.5", path = "../../../client/cli" } -sc-client-api = { version = "2.0.0-alpha.5", path = "../../../client/api" } -sc-block-builder = { version = "0.8.0-alpha.5", path = "../../../client/block-builder" } -sc-client = { version = "0.8.0-alpha.5", path = "../../../client" } -codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive"] } -sp-consensus = { version = "0.8.0-alpha.5", path = "../../../primitives/consensus/common" } -log = "0.4.8" -sp-core = { version = "2.0.0-alpha.5", path = "../../../primitives/core" } -sp-api = { version = "2.0.0-alpha.5", path = "../../../primitives/api" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime" } -sc-service = { version = "0.8.0-alpha.5", default-features = false, path = "../../../client/service" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../../primitives/blockchain" } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/bin/node/transaction-factory/src/lib.rs b/bin/node/transaction-factory/src/lib.rs deleted file mode 100644 index 44cb178be15ae3d8d73a49db5ef8c2717c8c1855..0000000000000000000000000000000000000000 --- a/bin/node/transaction-factory/src/lib.rs +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2019-2020 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 . - -//! Simple transaction factory which distributes tokens from a master -//! account to a specified number of newly created accounts. -//! -//! The factory currently only works on an empty database! - -use std::collections::HashMap; -use std::sync::Arc; -use std::cmp::PartialOrd; -use std::fmt::Display; - -use log::info; - -use sp_block_builder::BlockBuilder; -use sc_block_builder::BlockBuilderProvider; -use sp_api::{ProvideRuntimeApi, ApiExt, CallApiAt, TransactionFor}; -use sp_consensus::{ - BlockOrigin, BlockImportParams, InherentData, - ForkChoiceStrategy, SelectChain -}; -use sp_consensus::block_import::BlockImport; -use codec::{Decode, Encode}; -use sp_runtime::generic::BlockId; -use sp_runtime::traits::{ - Block as BlockT, Header as HeaderT, AtLeast32Bit, One, Zero, -}; -use sp_blockchain::HeaderBackend; - -pub trait RuntimeAdapter { - type AccountId: Display; - type Balance: Display + AtLeast32Bit + From; - type Block: BlockT; - type Index: Copy; - type Number: Display + PartialOrd + AtLeast32Bit + Zero + One; - type Phase: Copy; - type Secret; - - fn new(blocks: u32, transactions: u32) -> Self; - - fn blocks(&self) -> u32; - fn transactions(&self) -> u32; - - fn block_number(&self) -> u32; - fn set_block_number(&mut self, value: u32); - - fn transfer_extrinsic( - &mut self, - sender: &Self::AccountId, - key: &Self::Secret, - destination: &Self::AccountId, - amount: &Self::Balance, - version: u32, - genesis_hash: &::Hash, - prior_block_hash: &::Hash, - ) -> ::Extrinsic; - - fn inherent_extrinsics(&self) -> InherentData; - - fn minimum_balance() -> Self::Balance; - fn master_account_id() -> Self::AccountId; - fn master_account_secret() -> Self::Secret; - - fn gen_random_account_id(seed: u32) -> Self::AccountId; - fn gen_random_account_secret(seed: u32) -> Self::Secret; -} - -/// Manufactures transactions. The exact amount depends on `num` and `rounds`. -pub fn factory( - mut factory_state: RA, - client: &Arc, - select_chain: &Sc, -) -> sc_cli::Result<()> - where - Backend: sc_client_api::backend::Backend + Send, - Block: BlockT, - Client: BlockBuilderProvider + CallApiAt - + ProvideRuntimeApi + HeaderBackend, - Client::Api: BlockBuilder + ApiExt, - Sc: SelectChain, - RA: RuntimeAdapter, - Block::Hash: From, - for<'a> &'a Client: BlockImport>, -{ - let best_header: Result<::Header, sc_cli::Error> = - select_chain.best_chain().map_err(|e| format!("{:?}", e).into()); - let mut best_hash = best_header?.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.hash(Zero::zero())? - .expect("Genesis block always exists; qed").into(); - - while factory_state.block_number() < factory_state.blocks() { - let from = (RA::master_account_id(), RA::master_account_secret()); - let amount = RA::minimum_balance(); - - let inherents = RA::inherent_extrinsics(&factory_state); - let inherents = client.runtime_api().inherent_extrinsics(&best_block_id, inherents) - .expect("Failed to create inherent extrinsics"); - - let tx_per_block = factory_state.transactions(); - - let mut block = client.new_block(Default::default()).expect("Failed to create new block"); - - for tx_num in 0..tx_per_block { - let seed = tx_num * (factory_state.block_number() + 1); - let to = RA::gen_random_account_id(seed); - - let transfer = factory_state.transfer_extrinsic( - &from.0, - &from.1, - &to, - &amount, - version, - &genesis_hash, - &best_hash, - ); - - info!("Pushing transfer {}/{} to {} into block.", tx_num + 1, tx_per_block, to); - - block.push( - Decode::decode(&mut &transfer.encode()[..]) - .expect("Failed to decode transfer extrinsic") - ).expect("Failed to push transfer extrinsic into block"); - } - - for inherent in inherents { - block.push(inherent).expect("Failed ..."); - } - - let block = block.build().expect("Failed to bake block").block; - - factory_state.set_block_number(factory_state.block_number() + 1); - - info!( - "Created block {} with hash {}.", - factory_state.block_number(), - best_hash, - ); - - best_hash = block.header().hash(); - best_block_id = BlockId::::hash(best_hash); - - let mut import = BlockImportParams::new(BlockOrigin::File, block.header().clone()); - import.body = Some(block.extrinsics().to_vec()); - import.fork_choice = Some(ForkChoiceStrategy::LongestChain); - (&**client).import_block(import, HashMap::new()).expect("Failed to import block"); - - info!("Imported block at {}", factory_state.block_number()); - } - - Ok(()) -} diff --git a/bin/utils/chain-spec-builder/Cargo.toml b/bin/utils/chain-spec-builder/Cargo.toml index 9b03dd17b76de499094287fc126a0607c866a3a3..b633ffa96634e19aadbe082d3bafc971cf812654 100644 --- a/bin/utils/chain-spec-builder/Cargo.toml +++ b/bin/utils/chain-spec-builder/Cargo.toml @@ -1,20 +1,21 @@ [package] name = "chain-spec-builder" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" build = "build.rs" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] ansi_term = "0.12.1" -sc-keystore = { version = "2.0.0-alpha.5", path = "../../../client/keystore" } -node-cli = { version = "2.0.0-alpha.5", path = "../../node/cli" } -sp-core = { version = "2.0.0-alpha.5", path = "../../../primitives/core" } +sc-keystore = { version = "2.0.0-rc4", path = "../../../client/keystore" } +sc-chain-spec = { version = "2.0.0-rc4", path = "../../../client/chain-spec" } +node-cli = { version = "2.0.0-rc4", path = "../../node/cli" } +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } rand = "0.7.2" structopt = "0.3.8" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/bin/utils/chain-spec-builder/build.rs b/bin/utils/chain-spec-builder/build.rs index 513cc234d4363a854961db1efdea1cbc7007ce56..8d5aac1a08742486a9b0e5d55aaf7959941abd77 100644 --- a/bin/utils/chain-spec-builder/build.rs +++ b/bin/utils/chain-spec-builder/build.rs @@ -1,18 +1,20 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use std::env; diff --git a/bin/utils/chain-spec-builder/src/main.rs b/bin/utils/chain-spec-builder/src/main.rs index 3673909706cdb765508e4e72230d66c0ffc46635..4fbcc1e850723982de125067c931f27110f82ec9 100644 --- a/bin/utils/chain-spec-builder/src/main.rs +++ b/bin/utils/chain-spec-builder/src/main.rs @@ -1,18 +1,20 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use std::{fs, path::{Path, PathBuf}}; @@ -87,7 +89,7 @@ fn genesis_constructor( let authorities = authority_seeds .iter() .map(AsRef::as_ref) - .map(chain_spec::get_authority_keys_from_seed) + .map(chain_spec::authority_keys_from_seed) .collect::>(); let enable_println = true; @@ -120,6 +122,7 @@ fn generate_chain_spec( let chain_spec = chain_spec::ChainSpec::from_genesis( "Custom", "custom", + sc_chain_spec::ChainType::Live, move || genesis_constructor(&authority_seeds, &endowed_accounts, &sudo_account), vec![], None, @@ -142,7 +145,7 @@ fn generate_authority_keys_and_store( ).map_err(|err| err.to_string())?; let (_, _, grandpa, babe, im_online, authority_discovery) = - chain_spec::get_authority_keys_from_seed(seed); + chain_spec::authority_keys_from_seed(seed); let insert_key = |key_type, public| { keystore.write().insert_unknown( diff --git a/bin/utils/subkey/Cargo.toml b/bin/utils/subkey/Cargo.toml index 9bf20146a990d8dd876495caa867812d331949a5..2713ccdbf12fd14bbfee266a836f487a8146b911 100644 --- a/bin/utils/subkey/Cargo.toml +++ b/bin/utils/subkey/Cargo.toml @@ -1,39 +1,40 @@ [package] name = "subkey" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] futures = "0.1.29" -sp-core = { version = "2.0.0-alpha.5", path = "../../../primitives/core" } -node-runtime = { version = "2.0.0-alpha.5", path = "../../node/runtime" } -node-primitives = { version = "2.0.0-alpha.5", path = "../../node/primitives" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime" } +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } +node-runtime = { version = "2.0.0-rc4", path = "../../node/runtime" } +node-primitives = { version = "2.0.0-rc4", path = "../../node/primitives" } +sp-runtime = { version = "2.0.0-rc4", path = "../../../primitives/runtime" } rand = "0.7.2" clap = "2.33.0" tiny-bip39 = "0.7" substrate-bip39 = "0.4.1" hex = "0.4.0" hex-literal = "0.2.1" -codec = { package = "parity-scale-codec", version = "1.3.0" } -frame-system = { version = "2.0.0-alpha.5", path = "../../../frame/system" } -pallet-balances = { version = "2.0.0-alpha.5", path = "../../../frame/balances" } -pallet-transaction-payment = { version = "2.0.0-alpha.5", path = "../../../frame/transaction-payment" } +codec = { package = "parity-scale-codec", version = "1.3.1" } +frame-system = { version = "2.0.0-rc4", path = "../../../frame/system" } +pallet-balances = { version = "2.0.0-rc4", path = "../../../frame/balances" } +pallet-transaction-payment = { version = "2.0.0-rc4", path = "../../../frame/transaction-payment" } +pallet-grandpa = { version = "2.0.0-rc4", path = "../../../frame/grandpa" } rpassword = "4.0.1" itertools = "0.8.2" derive_more = { version = "0.99.2" } -sc-rpc = { version = "2.0.0-alpha.5", path = "../../../client/rpc" } -jsonrpc-core-client = { version = "14.0.3", features = ["http"] } +sc-rpc = { version = "2.0.0-rc4", path = "../../../client/rpc" } +jsonrpc-core-client = { version = "14.2.0", features = ["http"] } hyper = "0.12.35" -libp2p = "0.16.2" +libp2p = { version = "0.21.1", default-features = false } serde_json = "1.0" [features] bench = [] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/bin/utils/subkey/README.adoc b/bin/utils/subkey/README.adoc index 07533a002f80ef1f1912b352829c147be81bad88..1fa0753312f0cd6dc1f9a94c42866326bdf4f59d 100644 --- a/bin/utils/subkey/README.adoc +++ b/bin/utils/subkey/README.adoc @@ -68,3 +68,16 @@ subkey sign-transaction \ ``` Will output a signed and encoded `UncheckedMortalCompactExtrinsic` as hex. + +=== Inspecting a module ID + +```bash +subkey --network kusama moduleid "py/trsry" + +OUTPUT: +Public Key URI `F3opxRbN5ZbjJNU511Kj2TLuzFcDq9BGduA9TgiECafpg29` is account: + Network ID/version: kusama + Public key (hex): 0x6d6f646c70792f74727372790000000000000000000000000000000000000000 + Account ID: 0x6d6f646c70792f74727372790000000000000000000000000000000000000000 + SS58 Address: F3opxRbN5ZbjJNU511Kj2TLuzFcDq9BGduA9TgiECafpg29 +``` \ No newline at end of file diff --git a/bin/utils/subkey/src/main.rs b/bin/utils/subkey/src/main.rs index 237cc68df2f4657808152d493d2e26ac9866231f..4153e769c97f57ce65e3f6eb2c36c1991c586224 100644 --- a/bin/utils/subkey/src/main.rs +++ b/bin/utils/subkey/src/main.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . #![cfg_attr(feature = "bench", feature(test))] #[cfg(feature = "bench")] @@ -31,7 +33,7 @@ use sp_core::{ crypto::{set_default_ss58_version, Ss58AddressFormat, Ss58Codec}, ed25519, sr25519, ecdsa, Pair, Public, H256, hexdisplay::HexDisplay, }; -use sp_runtime::{traits::{IdentifyAccount, Verify}, generic::Era}; +use sp_runtime::{traits::{AccountIdConversion, IdentifyAccount, Verify}, generic::Era, ModuleId}; use std::{ convert::{TryInto, TryFrom}, io::{stdin, Read}, str::FromStr, path::PathBuf, fs, fmt, }; @@ -265,6 +267,9 @@ fn get_app<'a, 'b>(usage: &'a str) -> App<'a, 'b> { If the value is a file, the file content is used as URI. \ If not given, you will be prompted for the URI.' "), + SubCommand::with_name("inspect-node-key") + .about("Print the peer ID corresponding to the node key in the given file") + .args_from_usage("[file] 'Name of file to read the secret key from'"), SubCommand::with_name("sign") .about("Sign a message, provided on STDIN, with a given (secret) key") .args_from_usage(" @@ -318,6 +323,11 @@ fn get_app<'a, 'b>(usage: &'a str) -> App<'a, 'b> { 'Key type, examples: \"gran\", or \"imon\" ' [node-url] 'Node JSON-RPC endpoint, default \"http:://localhost:9933\"' "), + SubCommand::with_name("moduleid") + .about("Inspect a module ID address") + .args_from_usage(" + 'The module ID used to derive the account' + ") ]) } @@ -432,6 +442,17 @@ where ("inspect", Some(matches)) => { C::print_from_uri(&get_uri("uri", &matches)?, password, maybe_network, output); } + ("inspect-node-key", Some(matches)) => { + let file = matches.value_of("file").ok_or(Error::Static("Input file name is required"))?; + + let mut file_content = fs::read(file)?; + let secret = libp2p_ed25519::SecretKey::from_bytes(&mut file_content) + .map_err(|_| Error::Static("Bad node key file"))?; + let keypair = libp2p_ed25519::Keypair::from(secret); + let peer_id = PublicKey::Ed25519(keypair.public()).into_peer_id(); + + println!("{}", peer_id); + } ("sign", Some(matches)) => { let suri = get_uri("suri", &matches)?; let should_decode = matches.is_present("hex"); @@ -507,6 +528,20 @@ where sp_core::Bytes(pair.public().as_ref().to_vec()), ); } + ("moduleid", Some(matches)) => { + let id = get_uri("id", &matches)?; + if id.len() != 8 { + Err("a module id must be a string of 8 characters")? + } + + let id_fixed_array: [u8; 8] = id.as_bytes().try_into() + .map_err(|_| Error::Static("Cannot convert argument to moduleid: argument should be 8-character string"))?; + + let account_id: AccountId = ModuleId(id_fixed_array).into_account(); + let v = maybe_network.unwrap_or(Ss58AddressFormat::SubstrateAccount); + + C::print_from_uri(&account_id.to_ss58check_with_version(v), password, maybe_network, output); + } _ => print_usage(&matches), } @@ -683,28 +718,28 @@ fn create_extrinsic( { let extra = |i: Index, f: Balance| { ( - frame_system::CheckVersion::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), frame_system::CheckEra::::from(Era::Immortal), frame_system::CheckNonce::::from(i), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(f), - Default::default(), - Default::default(), + pallet_grandpa::ValidateEquivocationReport::::new(), ) }; let raw_payload = SignedPayload::from_raw( function, extra(index, 0), ( - VERSION.spec_version as u32, + VERSION.spec_version, + VERSION.transaction_version, genesis_hash, genesis_hash, (), (), (), (), - (), ), ); let signature = raw_payload.using_encoded(|payload| signer.sign(payload)).into_runtime(); diff --git a/bin/utils/subkey/src/rpc.rs b/bin/utils/subkey/src/rpc.rs index e08ccc19a22b8de89088ffade2809f7418eb7d25..e24cf50dc45026615891782cc2440a3eda5749a0 100644 --- a/bin/utils/subkey/src/rpc.rs +++ b/bin/utils/subkey/src/rpc.rs @@ -1,18 +1,20 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Helper to run commands against current node RPC diff --git a/bin/utils/subkey/src/vanity.rs b/bin/utils/subkey/src/vanity.rs index f921470946ec04732654091922711808f8aa6ad7..d09aeeef25a47a79ff434035a4d43a20d88c53a6 100644 --- a/bin/utils/subkey/src/vanity.rs +++ b/bin/utils/subkey/src/vanity.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use super::{PublicOf, PublicT, Crypto}; use sp_core::Pair; diff --git a/client/Cargo.toml b/client/Cargo.toml deleted file mode 100644 index 5d4b5927111ea220c33256c50c8250fe198ec840..0000000000000000000000000000000000000000 --- a/client/Cargo.toml +++ /dev/null @@ -1,49 +0,0 @@ -[package] -name = "sc-client" -version = "0.8.0-alpha.5" -authors = ["Parity Technologies "] -edition = "2018" -license = "GPL-3.0" -homepage = "https://substrate.dev" -repository = "https://github.com/paritytech/substrate/" -description = "Substrate Client and associated logic." - -[dependencies] -sc-block-builder = { version = "0.8.0-alpha.5", path = "block-builder" } -sc-client-api = { version = "2.0.0-alpha.5", path = "api" } -codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive"] } -sp-consensus = { version = "0.8.0-alpha.5", path = "../primitives/consensus/common" } -derive_more = { version = "0.99.2" } -sc-executor = { version = "0.8.0-alpha.5", path = "executor" } -sp-externalities = { version = "0.8.0-alpha.5", path = "../primitives/externalities" } -fnv = { version = "1.0.6" } -futures = { version = "0.3.1", features = ["compat"] } -hash-db = { version = "0.15.2" } -hex-literal = { version = "0.2.1" } -sp-inherents = { version = "2.0.0-alpha.5", path = "../primitives/inherents" } -sp-keyring = { version = "2.0.0-alpha.5", path = "../primitives/keyring" } -kvdb = "0.5.0" -log = { version = "0.4.8" } -parking_lot = "0.10.0" -sp-core = { version = "2.0.0-alpha.5", path = "../primitives/core" } -sp-std = { version = "2.0.0-alpha.5", path = "../primitives/std" } -sp-version = { version = "2.0.0-alpha.5", path = "../primitives/version" } -sp-api = { version = "2.0.0-alpha.5", path = "../primitives/api" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../primitives/runtime" } -sp-utils = { version = "2.0.0-alpha.5", path = "../primitives/utils" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../primitives/blockchain" } -sp-state-machine = { version = "0.8.0-alpha.5", path = "../primitives/state-machine" } -sc-telemetry = { version = "2.0.0-alpha.5", path = "telemetry" } -sp-trie = { version = "2.0.0-alpha.5", path = "../primitives/trie" } -prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.8.0-alpha.5", path = "../utils/prometheus" } -tracing = "0.1.10" - -[dev-dependencies] -env_logger = "0.7.0" -tempfile = "3.1.0" -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../test-utils/runtime/client" } -kvdb-memorydb = "0.5.0" -sp-panic-handler = { version = "2.0.0-alpha.5", path = "../primitives/panic-handler" } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/client/api/Cargo.toml b/client/api/Cargo.toml index dbe6afe9c7cae00c99abca8464dd4acd4c4f8a3c..8147d620345cb8a5b7b2b52e60137ef309414b8a 100644 --- a/client/api/Cargo.toml +++ b/client/api/Cargo.toml @@ -1,46 +1,49 @@ [package] name = "sc-client-api" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate client interfaces." documentation = "https://docs.rs/sc-client-api" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-consensus = { version = "0.8.0-alpha.5", path = "../../primitives/consensus/common" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-consensus = { version = "0.8.0-rc4", path = "../../primitives/consensus/common" } derive_more = { version = "0.99.2" } -sc-executor = { version = "0.8.0-alpha.5", path = "../executor" } -sp-externalities = { version = "0.8.0-alpha.5", path = "../../primitives/externalities" } +sc-executor = { version = "0.8.0-rc4", path = "../executor" } +sp-externalities = { version = "0.8.0-rc4", path = "../../primitives/externalities" } fnv = { version = "1.0.6" } futures = { version = "0.3.1" } hash-db = { version = "0.15.2", default-features = false } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../primitives/blockchain" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../primitives/blockchain" } hex-literal = { version = "0.2.1" } -sp-inherents = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/inherents" } -sp-keyring = { version = "2.0.0-alpha.5", path = "../../primitives/keyring" } -kvdb = "0.5.0" +sp-inherents = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/inherents" } +sp-keyring = { version = "2.0.0-rc4", path = "../../primitives/keyring" } +kvdb = "0.7.0" log = { version = "0.4.8" } parking_lot = "0.10.0" lazy_static = "1.4.0" -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/core" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-version = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/version" } -sp-api = { version = "2.0.0-alpha.5", path = "../../primitives/api" } -sp-utils = { version = "2.0.0-alpha.5", path = "../../primitives/utils" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -sp-state-machine = { version = "0.8.0-alpha.5", path = "../../primitives/state-machine" } -sc-telemetry = { version = "2.0.0-alpha.5", path = "../telemetry" } -sp-trie = { version = "2.0.0-alpha.5", path = "../../primitives/trie" } -sp-storage = { version = "2.0.0-alpha.5", path = "../../primitives/storage" } -sp-transaction-pool = { version = "2.0.0-alpha.5", path = "../../primitives/transaction-pool" } +sp-database = { version = "2.0.0-rc4", path = "../../primitives/database" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/core" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-version = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/version" } +sp-api = { version = "2.0.0-rc4", path = "../../primitives/api" } +sp-utils = { version = "2.0.0-rc4", path = "../../primitives/utils" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +sp-state-machine = { version = "0.8.0-rc4", path = "../../primitives/state-machine" } +sc-telemetry = { version = "2.0.0-rc4", path = "../telemetry" } +sp-trie = { version = "2.0.0-rc4", path = "../../primitives/trie" } +sp-storage = { version = "2.0.0-rc4", path = "../../primitives/storage" } +sp-transaction-pool = { version = "2.0.0-rc4", path = "../../primitives/transaction-pool" } +prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.8.0-rc4", path = "../../utils/prometheus" } [dev-dependencies] -sp-test-primitives = { version = "2.0.0-dev", path = "../../primitives/test-primitives" } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +kvdb-memorydb = "0.6.0" +sp-test-primitives = { version = "2.0.0-rc4", path = "../../primitives/test-primitives" } +substrate-test-runtime = { version = "2.0.0-rc4", path = "../../test-utils/runtime" } diff --git a/client/api/src/backend.rs b/client/api/src/backend.rs index d10e62cc54920e56509ddbb06a51f38296b417c1..9482a6118d71a21415c74f7410d27ead150e06c3 100644 --- a/client/api/src/backend.rs +++ b/client/api/src/backend.rs @@ -1,32 +1,34 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Substrate Client data backend use std::sync::Arc; use std::collections::HashMap; use sp_core::ChangesTrieConfigurationRange; -use sp_core::offchain::OffchainStorage; +use sp_core::offchain::{OffchainStorage,storage::OffchainOverlayedChanges}; use sp_runtime::{generic::BlockId, Justification, Storage}; use sp_runtime::traits::{Block as BlockT, NumberFor, HashFor}; use sp_state_machine::{ ChangesTrieState, ChangesTrieStorage as StateChangesTrieStorage, ChangesTrieTransaction, StorageCollection, ChildStorageCollection, }; -use sp_storage::{StorageData, StorageKey, ChildInfo}; +use sp_storage::{StorageData, StorageKey, PrefixedStorageKey, ChildInfo}; use crate::{ blockchain::{ Backend as BlockchainBackend, well_known_cache_keys @@ -65,8 +67,10 @@ pub struct ImportSummary { pub is_new_best: bool, /// Optional storage changes. pub storage_changes: Option<(StorageCollection, ChildStorageCollection)>, - /// Blocks that got retracted because of this one got imported. - pub retracted: Vec, + /// Tree route from old best to new best. + /// + /// If `None`, there was no re-org while importing. + pub tree_route: Option>, } /// Import operation wrapper @@ -79,6 +83,25 @@ pub struct ClientImportOperation> { pub notify_finalized: Vec, } +/// Helper function to apply auxiliary data insertion into an operation. +pub fn apply_aux<'a, 'b: 'a, 'c: 'a, B, Block, D, I>( + operation: &mut ClientImportOperation, + insert: I, + delete: D, +) -> sp_blockchain::Result<()> + where + Block: BlockT, + B: 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))) + ) +} + /// State of a new block. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum NewBlockState { @@ -148,6 +171,14 @@ pub trait BlockImportOperation { child_update: ChildStorageCollection, ) -> sp_blockchain::Result<()>; + /// Write offchain storage changes to the database. + fn update_offchain_storage( + &mut self, + _offchain_update: OffchainOverlayedChanges, + ) -> sp_blockchain::Result<()> { + Ok(()) + } + /// Inject changes trie data into the database. fn update_changes_trie( &mut self, @@ -280,6 +311,7 @@ impl<'a, State, Block> Iterator for KeyIterator<'a, State, Block> where Some(StorageKey(next_key)) } } + /// Provides acess to storage primitives pub trait StorageProvider> { /// Given a `BlockId` and a key, return the value under the key in that block. @@ -310,8 +342,7 @@ pub trait StorageProvider> { fn child_storage( &self, id: &BlockId, - storage_key: &StorageKey, - child_info: ChildInfo, + child_info: &ChildInfo, key: &StorageKey ) -> sp_blockchain::Result>; @@ -319,8 +350,7 @@ pub trait StorageProvider> { fn child_storage_keys( &self, id: &BlockId, - child_storage_key: &StorageKey, - child_info: ChildInfo, + child_info: &ChildInfo, key_prefix: &StorageKey ) -> sp_blockchain::Result>; @@ -328,8 +358,7 @@ pub trait StorageProvider> { fn child_storage_hash( &self, id: &BlockId, - storage_key: &StorageKey, - child_info: ChildInfo, + child_info: &ChildInfo, key: &StorageKey ) -> sp_blockchain::Result>; @@ -351,7 +380,7 @@ pub trait StorageProvider> { &self, first: NumberFor, last: BlockId, - storage_key: Option<&StorageKey>, + storage_key: Option<&PrefixedStorageKey>, key: &StorageKey ) -> sp_blockchain::Result, u32)>>; } diff --git a/client/api/src/call_executor.rs b/client/api/src/call_executor.rs index 3afd29be8d49c7404bde565b300376ef6a953ee8..d9d43900dfc94f2732db7be0051401a832bf8c5b 100644 --- a/client/api/src/call_executor.rs +++ b/client/api/src/call_executor.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! A method call executor interface. @@ -26,7 +28,7 @@ use sp_state_machine::{ }; use sc_executor::{RuntimeVersion, NativeVersion}; use sp_externalities::Extensions; -use sp_core::NativeOrEncoded; +use sp_core::{NativeOrEncoded,offchain::storage::OffchainOverlayedChanges}; use sp_api::{ProofRecorder, InitializeBlock, StorageTransactionCache}; use crate::execution_extensions::ExecutionExtensions; @@ -84,6 +86,7 @@ pub trait CallExecutor { method: &str, call_data: &[u8], changes: &RefCell, + offchain_changes: &RefCell, storage_transaction_cache: Option<&RefCell< StorageTransactionCache>::State>, >>, diff --git a/client/src/cht.rs b/client/api/src/cht.rs similarity index 95% rename from client/src/cht.rs rename to client/api/src/cht.rs index de67280632302395e2363f6d309b2fecbf75d9ad..30cfd3a1b671b8f159d40bdcb499137de8fe5a69 100644 --- a/client/src/cht.rs +++ b/client/api/src/cht.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Canonical hash trie definitions and helper functions. //! @@ -232,7 +234,7 @@ pub fn for_each_cht_group( functor_param = functor( functor_param, current_cht_num, - ::std::mem::replace(&mut current_cht_blocks, Vec::new()), + std::mem::take(&mut current_cht_blocks), )?; } @@ -244,7 +246,7 @@ pub fn for_each_cht_group( functor( functor_param, current_cht_num, - ::std::mem::replace(&mut current_cht_blocks, Vec::new()), + std::mem::take(&mut current_cht_blocks), )?; } @@ -331,9 +333,10 @@ pub fn decode_cht_value(value: &[u8]) -> Option { #[cfg(test)] mod tests { - use substrate_test_runtime_client::runtime::Header; - use sp_runtime::traits::BlakeTwo256; use super::*; + use sp_runtime::{generic, traits::BlakeTwo256}; + + type Header = generic::Header; #[test] fn is_build_required_works() { diff --git a/client/api/src/client.rs b/client/api/src/client.rs index c855cd3a0832883c3a66b5c986871909aece048a..35d40965e6425096790e6e88c37045724b2b5578 100644 --- a/client/api/src/client.rs +++ b/client/api/src/client.rs @@ -16,7 +16,7 @@ //! A set of APIs supported by the client along with their primitives. -use std::{fmt, collections::HashSet}; +use std::{fmt, collections::HashSet, sync::Arc}; use sp_core::storage::StorageKey; use sp_runtime::{ traits::{Block as BlockT, NumberFor}, @@ -90,6 +90,9 @@ pub trait BlockBackend { /// Get block justification set by id. fn justification(&self, id: &BlockId) -> sp_blockchain::Result>; + + /// Get block hash by number. + fn block_hash(&self, number: NumberFor) -> sp_blockchain::Result>; } /// Provide a list of potential uncle headers for a given block. @@ -234,8 +237,10 @@ 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, + /// Tree route from old best to new best parent. + /// + /// If `None`, there was no re-org while importing. + pub tree_route: Option>>, } /// Summary of a finalized block. @@ -246,3 +251,22 @@ pub struct FinalityNotification { /// Imported block header. pub header: Block::Header, } + +impl From> for sp_transaction_pool::ChainEvent { + fn from(n: BlockImportNotification) -> Self { + Self::NewBlock { + is_new_best: n.is_new_best, + hash: n.hash, + header: n.header, + tree_route: n.tree_route, + } + } +} + +impl From> for sp_transaction_pool::ChainEvent { + fn from(n: FinalityNotification) -> Self { + Self::Finalized { + hash: n.hash, + } + } +} diff --git a/client/api/src/execution_extensions.rs b/client/api/src/execution_extensions.rs index 10d33c20e679c6eeddb4368da3c18d429d2ade6b..4f2ddb77e6653a056fcfd1647cfacdf6afbbec54 100644 --- a/client/api/src/execution_extensions.rs +++ b/client/api/src/execution_extensions.rs @@ -84,6 +84,10 @@ pub struct ExecutionExtensions { keystore: Option, // FIXME: these two are only RwLock because of https://github.com/paritytech/substrate/issues/4587 // remove when fixed. + // To break retain cycle between `Client` and `TransactionPool` we require this + // extension to be a `Weak` reference. + // That's also the reason why it's being registered lazily instead of + // during initialization. transaction_pool: RwLock>>>, extensions_factory: RwLock>, } @@ -121,13 +125,10 @@ impl ExecutionExtensions { } /// Register transaction pool extension. - /// - /// To break retain cycle between `Client` and `TransactionPool` we require this - /// extension to be a `Weak` reference. - /// That's also the reason why it's being registered lazily instead of - /// during initialization. - pub fn register_transaction_pool(&self, pool: Weak>) { - *self.transaction_pool.write() = Some(pool); + pub fn register_transaction_pool(&self, pool: &Arc) + where T: sp_transaction_pool::OffchainSubmitTransaction + 'static + { + *self.transaction_pool.write() = Some(Arc::downgrade(&pool) as _); } /// Create `ExecutionManager` and `Extensions` for given offchain call. @@ -177,7 +178,7 @@ impl ExecutionExtensions { if let ExecutionContext::OffchainCall(Some(ext)) = context { extensions.register( OffchainExt::new(offchain::LimitedExternalities::new(capabilities, ext.0)) - ) + ); } (manager, extensions) diff --git a/client/src/in_mem.rs b/client/api/src/in_mem.rs similarity index 87% rename from client/src/in_mem.rs rename to client/api/src/in_mem.rs index 3672da1822df1b30f377f64a3bf1d8c8d85dd8d7..9bfdcdd4d5aea75e4b7e1e9bd49da3c120e87e3c 100644 --- a/client/src/in_mem.rs +++ b/client/api/src/in_mem.rs @@ -1,27 +1,29 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! In memory client backend use std::collections::HashMap; +use std::ptr; use std::sync::Arc; use parking_lot::RwLock; -use sp_core::storage::well_known_keys; -use sp_core::offchain::storage::{ - InMemOffchainStorage as OffchainStorage +use sp_core::{ + storage::well_known_keys, offchain::storage::InMemOffchainStorage as OffchainStorage, }; use sp_runtime::generic::BlockId; use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Zero, NumberFor, HashFor}; @@ -32,14 +34,15 @@ use sp_state_machine::{ }; use sp_blockchain::{CachedHeaderMetadata, HeaderMetadata}; -use sc_client_api::{ +use crate::{ backend::{self, NewBlockState}, blockchain::{ self, BlockStatus, HeaderBackend, well_known_cache_keys::Id as CacheKeyId }, UsageInfo, + light, + leaves::LeafSet, }; -use crate::leaves::LeafSet; struct PendingBlock { block: StoredBlock, @@ -111,6 +114,12 @@ pub struct Blockchain { storage: Arc>>, } +impl Default for Blockchain { + fn default() -> Self { + Self::new() + } +} + impl Clone for Blockchain { fn clone(&self) -> Self { let storage = Arc::new(RwLock::new(self.storage.read().clone())); @@ -189,11 +198,19 @@ impl Blockchain { /// Compare this blockchain with another in-mem blockchain pub fn equals_to(&self, other: &Self) -> bool { + // Check ptr equality first to avoid double read locks. + if ptr::eq(self, other) { + return true; + } self.canon_equals_to(other) && self.storage.read().blocks == other.storage.read().blocks } /// Compare canonical chain to other canonical chain. pub fn canon_equals_to(&self, other: &Self) -> bool { + // Check ptr equality first to avoid double read locks. + if ptr::eq(self, other) { + return true; + } let this = self.storage.read(); let other = other.storage.read(); this.hashes == other.hashes @@ -400,7 +417,7 @@ impl backend::AuxStore for Blockchain { } } -impl sc_client_api::light::Storage for Blockchain +impl light::Storage for Blockchain where Block::Hash: From<[u8; 32]>, { @@ -454,7 +471,7 @@ impl sc_client_api::light::Storage for Blockchain None } - fn usage_info(&self) -> Option { + fn usage_info(&self) -> Option { None } } @@ -464,7 +481,7 @@ pub struct BlockImportOperation { pending_block: Option>, pending_cache: HashMap>, old_state: InMemoryBackend>, - new_state: Option>>, + new_state: Option<> as StateBackend>>::Transaction>, aux: Vec<(Vec, Option>)>, finalized_blocks: Vec<(BlockId, Option)>, set_head: Option>, @@ -502,7 +519,7 @@ impl backend::BlockImportOperation for BlockImportOperatio &mut self, update: > as StateBackend>>::Transaction, ) -> sp_blockchain::Result<()> { - self.new_state = Some(self.old_state.update(update)); + self.new_state = Some(update); Ok(()) } @@ -516,16 +533,20 @@ impl backend::BlockImportOperation for BlockImportOperatio fn reset_storage(&mut self, storage: Storage) -> sp_blockchain::Result { check_genesis_storage(&storage)?; - let child_delta = storage.children.into_iter() - .map(|(storage_key, child_content)| - (storage_key, child_content.data.into_iter().map(|(k, v)| (k, Some(v))), child_content.child_info)); + let child_delta = storage.children_default.iter() + .map(|(_storage_key, child_content)| + ( + &child_content.child_info, + child_content.data.iter().map(|(k, v)| (k.as_ref(), Some(v.as_ref()))) + ) + ); let (root, transaction) = self.old_state.full_storage_root( - storage.top.into_iter().map(|(k, v)| (k, Some(v))), - child_delta + storage.top.iter().map(|(k, v)| (k.as_ref(), Some(v.as_ref()))), + child_delta, ); - self.new_state = Some(InMemoryBackend::from(transaction)); + self.new_state = Some(transaction); Ok(root) } @@ -638,7 +659,12 @@ impl backend::Backend for Backend where Block::Hash let hash = header.hash(); - self.states.write().insert(hash, operation.new_state.unwrap_or_else(|| old_state.clone())); + let new_state = match operation.new_state { + Some(state) => old_state.update_backend(*header.state_root(), state), + None => old_state.clone(), + }; + + self.states.write().insert(hash, new_state); self.blockchain.insert(hash, header, justification, body, pending_block.state)?; } @@ -714,7 +740,7 @@ impl backend::RemoteBackend for Backend where Block .unwrap_or(false) } - fn remote_blockchain(&self) -> Arc> { + fn remote_blockchain(&self) -> Arc> { unimplemented!() } } @@ -725,52 +751,10 @@ pub fn check_genesis_storage(storage: &Storage) -> sp_blockchain::Result<()> { return Err(sp_blockchain::Error::GenesisInvalid.into()); } - if storage.children.keys().any(|child_key| !well_known_keys::is_child_storage_key(&child_key)) { - return Err(sp_blockchain::Error::GenesisInvalid.into()); + if storage.children_default.keys() + .any(|child_key| !well_known_keys::is_child_storage_key(&child_key)) { + return Err(sp_blockchain::Error::GenesisInvalid.into()); } Ok(()) } - -#[cfg(test)] -mod tests { - use sp_core::offchain::{OffchainStorage, storage::InMemOffchainStorage}; - use std::sync::Arc; - - type TestBackend = substrate_test_runtime_client::sc_client::in_mem::Backend; - - #[test] - fn test_leaves_with_complex_block_tree() { - let backend = Arc::new(TestBackend::new()); - - substrate_test_runtime_client::trait_tests::test_leaves_for_backend(backend); - } - - #[test] - fn test_blockchain_query_by_number_gets_canonical() { - let backend = Arc::new(TestBackend::new()); - - substrate_test_runtime_client::trait_tests::test_blockchain_query_by_number_gets_canonical(backend); - } - - #[test] - fn in_memory_offchain_storage() { - - let mut storage = InMemOffchainStorage::default(); - assert_eq!(storage.get(b"A", b"B"), None); - assert_eq!(storage.get(b"B", b"A"), None); - - storage.set(b"A", b"B", b"C"); - assert_eq!(storage.get(b"A", b"B"), Some(b"C".to_vec())); - assert_eq!(storage.get(b"B", b"A"), None); - - storage.compare_and_set(b"A", b"B", Some(b"X"), b"D"); - assert_eq!(storage.get(b"A", b"B"), Some(b"C".to_vec())); - storage.compare_and_set(b"A", b"B", Some(b"C"), b"D"); - assert_eq!(storage.get(b"A", b"B"), Some(b"D".to_vec())); - - assert!(!storage.compare_and_set(b"B", b"A", Some(b""), b"Y")); - assert!(storage.compare_and_set(b"B", b"A", None, b"X")); - assert_eq!(storage.get(b"B", b"A"), Some(b"X".to_vec())); - } -} diff --git a/client/src/leaves.rs b/client/api/src/leaves.rs similarity index 81% rename from client/src/leaves.rs rename to client/api/src/leaves.rs index 7c169488ddcf4ef2031fd4d45a1e121afb3f622e..d10fa7ac0e565347803999d7a63a6aa2a0536fb5 100644 --- a/client/src/leaves.rs +++ b/client/api/src/leaves.rs @@ -1,28 +1,32 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Helper for managing the set of available leaves in the chain for DB implementations. use std::collections::BTreeMap; use std::cmp::Reverse; -use kvdb::{KeyValueDB, DBTransaction}; +use sp_database::{Database, Transaction}; use sp_runtime::traits::AtLeast32Bit; use codec::{Encode, Decode}; use sp_blockchain::{Error, Result}; +type DbHash = [u8; 32]; + #[derive(Debug, Clone, PartialEq, Eq)] struct LeafSetItem { hash: H, @@ -59,7 +63,7 @@ impl FinalizationDisplaced { #[derive(Debug, Clone, PartialEq, Eq)] pub struct LeafSet { storage: BTreeMap, Vec>, - pending_added: Vec>, + pending_added: Vec<(H, N)>, pending_removed: Vec, } @@ -77,21 +81,20 @@ impl LeafSet where } /// Read the leaf list from the DB, using given prefix for keys. - pub fn read_from_db(db: &dyn KeyValueDB, column: u32, prefix: &[u8]) -> Result { + pub fn read_from_db(db: &dyn Database, column: u32, prefix: &[u8]) -> Result { let mut storage = BTreeMap::new(); - for (key, value) in db.iter_from_prefix(column, prefix) { - if !key.starts_with(prefix) { break } - let raw_hash = &mut &key[prefix.len()..]; - let hash = match Decode::decode(raw_hash) { - Ok(hash) => hash, - Err(_) => return Err(Error::Backend("Error decoding hash".into())), - }; - let number = match Decode::decode(&mut &value[..]) { - Ok(number) => number, - Err(_) => return Err(Error::Backend("Error decoding number".into())), - }; - storage.entry(Reverse(number)).or_insert_with(Vec::new).push(hash); + match db.get(column, prefix) { + Some(leaves) => { + let vals: Vec<_> = match Decode::decode(&mut leaves.as_ref()) { + Ok(vals) => vals, + Err(_) => return Err(Error::Backend("Error decoding leaves".into())), + }; + for (number, hashes) in vals.into_iter() { + storage.insert(Reverse(number), hashes); + } + } + None => {}, } Ok(Self { storage, @@ -124,7 +127,7 @@ impl LeafSet where }; self.insert_leaf(Reverse(number.clone()), hash.clone()); - self.pending_added.push(LeafSetItem { hash, number: Reverse(number) }); + self.pending_added.push((hash, number)); displaced } @@ -185,7 +188,7 @@ impl LeafSet where // this is an invariant of regular block import. if !leaves_contains_best { self.insert_leaf(best_number.clone(), best_hash.clone()); - self.pending_added.push(LeafSetItem { hash: best_hash, number: best_number }); + self.pending_added.push((best_hash, best_number.0)); } } @@ -201,18 +204,11 @@ impl LeafSet where } /// Write the leaf list to the database transaction. - pub fn prepare_transaction(&mut self, tx: &mut DBTransaction, column: u32, prefix: &[u8]) { - let mut buf = prefix.to_vec(); - for LeafSetItem { hash, number } in self.pending_added.drain(..) { - hash.using_encoded(|s| buf.extend(s)); - tx.put_vec(column, &buf[..], number.0.encode()); - buf.truncate(prefix.len()); // reuse allocation. - } - for hash in self.pending_removed.drain(..) { - hash.using_encoded(|s| buf.extend(s)); - tx.delete(column, &buf[..]); - buf.truncate(prefix.len()); // reuse allocation. - } + pub fn prepare_transaction(&mut self, tx: &mut Transaction, column: u32, prefix: &[u8]) { + let leaves: Vec<_> = self.storage.iter().map(|(n, h)| (n.0.clone(), h.clone())).collect(); + tx.set_from_vec(column, prefix, leaves.encode()); + self.pending_added.clear(); + self.pending_removed.clear(); } #[cfg(test)] @@ -281,6 +277,7 @@ impl<'a, H: 'a, N: 'a> Drop for Undo<'a, H, N> { #[cfg(test)] mod tests { use super::*; + use std::sync::Arc; #[test] fn it_works() { @@ -305,7 +302,7 @@ mod tests { #[test] fn flush_to_disk() { const PREFIX: &[u8] = b"abcdefg"; - let db = ::kvdb_memorydb::create(1); + let db = Arc::new(sp_database::MemDb::default()); let mut set = LeafSet::new(); set.import(0u32, 0u32, 0u32); @@ -314,12 +311,12 @@ mod tests { set.import(2_1, 2, 1_1); set.import(3_1, 3, 2_1); - let mut tx = DBTransaction::new(); + let mut tx = Transaction::new(); set.prepare_transaction(&mut tx, 0, PREFIX); - db.write(tx).unwrap(); + db.commit(tx).unwrap(); - let set2 = LeafSet::read_from_db(&db, 0, PREFIX).unwrap(); + let set2 = LeafSet::read_from_db(&*db, 0, PREFIX).unwrap(); assert_eq!(set, set2); } @@ -339,7 +336,7 @@ mod tests { #[test] fn finalization_consistent_with_disk() { const PREFIX: &[u8] = b"prefix"; - let db = ::kvdb_memorydb::create(1); + let db = Arc::new(sp_database::MemDb::default()); let mut set = LeafSet::new(); set.import(10_1u32, 10u32, 0u32); @@ -349,21 +346,21 @@ mod tests { assert!(set.contains(10, 10_1)); - let mut tx = DBTransaction::new(); + let mut tx = Transaction::new(); set.prepare_transaction(&mut tx, 0, PREFIX); - db.write(tx).unwrap(); + db.commit(tx).unwrap(); let _ = set.finalize_height(11); - let mut tx = DBTransaction::new(); + let mut tx = Transaction::new(); set.prepare_transaction(&mut tx, 0, PREFIX); - db.write(tx).unwrap(); + db.commit(tx).unwrap(); assert!(set.contains(11, 11_1)); assert!(set.contains(11, 11_2)); assert!(set.contains(12, 12_1)); assert!(!set.contains(10, 10_1)); - let set2 = LeafSet::read_from_db(&db, 0, PREFIX).unwrap(); + let set2 = LeafSet::read_from_db(&*db, 0, PREFIX).unwrap(); assert_eq!(set, set2); } diff --git a/client/api/src/lib.rs b/client/api/src/lib.rs index e4080323c188eb5ded7f85ab14e229e9beae117a..bad61f7687a63293175da3e29a4c2b21049deff4 100644 --- a/client/api/src/lib.rs +++ b/client/api/src/lib.rs @@ -20,8 +20,11 @@ pub mod backend; pub mod call_executor; pub mod client; +pub mod cht; pub mod execution_extensions; +pub mod in_mem; pub mod light; +pub mod leaves; pub mod notifications; pub mod proof_provider; @@ -36,6 +39,13 @@ pub use proof_provider::*; pub use sp_state_machine::{StorageProof, ExecutionStrategy, CloneableSpawn}; +/// Usage Information Provider interface +/// +pub trait UsageProvider { + /// Get usage info about current client. + fn usage_info(&self) -> ClientInfo; +} + /// Utility methods for the client. pub mod utils { use sp_blockchain::{HeaderBackend, HeaderMetadata, Error}; diff --git a/client/api/src/light.rs b/client/api/src/light.rs index c0bebc1740a8a0047e1f1d93c259cb3d237994d3..b359c1149eea645e27f584122dfaf328c168ac47 100644 --- a/client/api/src/light.rs +++ b/client/api/src/light.rs @@ -26,7 +26,7 @@ use sp_runtime::{ }, generic::BlockId }; -use sp_core::ChangesTrieConfigurationRange; +use sp_core::{ChangesTrieConfigurationRange, storage::PrefixedStorageKey}; use sp_state_machine::StorageProof; use sp_blockchain::{ HeaderMetadata, well_known_cache_keys, HeaderBackend, Cache as BlockchainCache, @@ -81,12 +81,7 @@ pub struct RemoteReadChildRequest { /// Header of block at which read is performed. pub header: Header, /// Storage key for child. - pub storage_key: Vec, - /// Child trie source information. - pub child_info: Vec, - /// Child type, its required to resolve `child_info` - /// content and choose child implementation. - pub child_type: u32, + pub storage_key: PrefixedStorageKey, /// Child storage key to read. pub keys: Vec>, /// Number of times to retry request. None means that default RETRY_COUNT is used. @@ -110,7 +105,7 @@ pub struct RemoteChangesRequest { /// 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>, + 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. @@ -301,7 +296,25 @@ pub trait RemoteBlockchain: Send + Sync { >>; } - +/// Returns future that resolves header either locally, or remotely. +pub fn future_header>( + blockchain: &dyn RemoteBlockchain, + fetcher: &F, + id: BlockId, +) -> impl Future, ClientError>> { + use futures::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 { diff --git a/client/api/src/notifications.rs b/client/api/src/notifications.rs index f154eade44d5e37cd76a3bad97e21d46e3ed779d..ec63c372c7e5969b28e5dfdbd54afae0b757b1b6 100644 --- a/client/api/src/notifications.rs +++ b/client/api/src/notifications.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Storage notifications @@ -25,6 +27,7 @@ use fnv::{FnvHashSet, FnvHashMap}; use sp_core::storage::{StorageKey, StorageData}; use sp_runtime::traits::Block as BlockT; use sp_utils::mpsc::{TracingUnboundedSender, TracingUnboundedReceiver, tracing_unbounded}; +use prometheus_endpoint::{Registry, CounterVec, Opts, U64, register}; /// Storage change set #[derive(Debug)] @@ -71,9 +74,12 @@ pub type StorageEventStream = TracingUnboundedReceiver<(H, StorageChangeSet)> type SubscriberId = u64; +type SubscribersGauge = CounterVec; + /// Manages storage listeners. #[derive(Debug)] pub struct StorageNotifications { + metrics: Option, next_id: SubscriberId, wildcard_listeners: FnvHashSet, listeners: HashMap>, @@ -90,7 +96,8 @@ pub struct StorageNotifications { impl Default for StorageNotifications { fn default() -> Self { - StorageNotifications { + Self { + metrics: Default::default(), next_id: Default::default(), wildcard_listeners: Default::default(), listeners: Default::default(), @@ -101,6 +108,29 @@ impl Default for StorageNotifications { } impl StorageNotifications { + /// Initialize a new StorageNotifications + /// optionally pass a prometheus registry to send subscriber metrics to + pub fn new(prometheus_registry: Option) -> Self { + let metrics = prometheus_registry.and_then(|r| + CounterVec::new( + Opts::new( + "storage_notification_subscribers", + "Number of subscribers in storage notification sytem" + ), + &["action"], //added | removed + ).and_then(|g| register(g, &r)) + .ok() + ); + + StorageNotifications { + metrics, + next_id: Default::default(), + wildcard_listeners: Default::default(), + listeners: Default::default(), + child_listeners: Default::default(), + sinks: Default::default(), + } + } /// Trigger notification to all listeners. /// /// Note the changes are going to be filtered by listener's filter key. @@ -113,6 +143,7 @@ impl StorageNotifications { Item=(Vec, impl Iterator, Option>)>) >, ) { + let has_wildcard = !self.wildcard_listeners.is_empty(); // early exit if no listeners @@ -169,21 +200,32 @@ impl StorageNotifications { let changes = Arc::new(changes); let child_changes = Arc::new(child_changes); // Trigger the events - for subscriber in subscribers { - let should_remove = { - let &(ref sink, ref filter, ref child_filters) = self.sinks.get(&subscriber) - .expect("subscribers returned from self.listeners are always in self.sinks; qed"); - sink.unbounded_send((hash.clone(), StorageChangeSet { - changes: changes.clone(), - child_changes: child_changes.clone(), - filter: filter.clone(), - child_filters: child_filters.clone(), - })).is_err() - }; - - if should_remove { - self.remove_subscriber(subscriber); - } + + let to_remove = self.sinks + .iter() + .filter_map(|(subscriber, &(ref sink, ref filter, ref child_filters))| { + let should_remove = { + if subscribers.contains(subscriber) { + sink.unbounded_send((hash.clone(), StorageChangeSet { + changes: changes.clone(), + child_changes: child_changes.clone(), + filter: filter.clone(), + child_filters: child_filters.clone(), + })).is_err() + } else { + sink.is_closed() + } + }; + + if should_remove { + Some(subscriber.clone()) + } else { + None + } + }).collect::>(); + + for sub_id in to_remove { + self.remove_subscriber(sub_id); } } @@ -241,6 +283,9 @@ impl StorageNotifications { } } } + if let Some(m) = self.metrics.as_ref() { + m.with_label_values(&[&"removed"]).inc(); + } } } @@ -301,6 +346,11 @@ impl StorageNotifications { // insert sink let (tx, rx) = tracing_unbounded("mpsc_storage_notification_items"); self.sinks.insert(current_id, (tx, keys, child_keys)); + + if let Some(m) = self.metrics.as_ref() { + m.with_label_values(&[&"added"]).inc(); + } + rx } } diff --git a/client/api/src/proof_provider.rs b/client/api/src/proof_provider.rs index 2d9876f7ad278dd7067199f9090122d5c9c073ab..5749ae0576fc38799d8c2eeb9b2aeaccd49b2bca 100644 --- a/client/api/src/proof_provider.rs +++ b/client/api/src/proof_provider.rs @@ -1,25 +1,28 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . + //! Proof utilities use sp_runtime::{ generic::BlockId, traits::{Block as BlockT}, }; use crate::{StorageProof, ChangesProof}; -use sp_storage::{ChildInfo, StorageKey}; +use sp_storage::{ChildInfo, StorageKey, PrefixedStorageKey}; /// Interface for providing block proving utilities. pub trait ProofProvider { @@ -35,8 +38,7 @@ pub trait ProofProvider { fn read_child_proof( &self, id: &BlockId, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, keys: &mut dyn Iterator, ) -> sp_blockchain::Result; @@ -65,7 +67,7 @@ pub trait ProofProvider { last: Block::Hash, min: Block::Hash, max: Block::Hash, - storage_key: Option<&StorageKey>, + storage_key: Option<&PrefixedStorageKey>, key: &StorageKey, ) -> sp_blockchain::Result>; } diff --git a/client/authority-discovery/Cargo.toml b/client/authority-discovery/Cargo.toml index 3fe4de13e33b9daa1e37083dcfd9b53bb69ade84..75cb30646b06d02f4978580d66cac73378980c24 100644 --- a/client/authority-discovery/Cargo.toml +++ b/client/authority-discovery/Cargo.toml @@ -1,43 +1,43 @@ [package] name = "sc-authority-discovery" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] edition = "2018" build = "build.rs" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate authority discovery." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [build-dependencies] prost-build = "0.6.1" [dependencies] bytes = "0.5.0" -codec = { package = "parity-scale-codec", default-features = false, version = "1.3.0" } +codec = { package = "parity-scale-codec", default-features = false, version = "1.3.1" } derive_more = "0.99.2" futures = "0.3.4" futures-timer = "3.0.1" -libp2p = { version = "0.16.2", default-features = false, features = ["secp256k1", "libp2p-websocket"] } +libp2p = { version = "0.21.1", default-features = false, features = ["kad"] } log = "0.4.8" -prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.8.0-alpha.5"} +prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.8.0-rc4"} prost = "0.6.1" rand = "0.7.2" -sc-client-api = { version = "2.0.0-alpha.5", path = "../api" } -sc-keystore = { version = "2.0.0-alpha.5", path = "../keystore" } -sc-network = { version = "0.8.0-alpha.5", path = "../network" } +sc-client-api = { version = "2.0.0-rc4", path = "../api" } +sc-keystore = { version = "2.0.0-rc4", path = "../keystore" } +sc-network = { version = "0.8.0-rc4", path = "../network" } serde_json = "1.0.41" -sp-authority-discovery = { version = "2.0.0-alpha.5", path = "../../primitives/authority-discovery" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../primitives/blockchain" } -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../primitives/runtime" } -sp-api = { version = "2.0.0-alpha.5", path = "../../primitives/api" } +sp-authority-discovery = { version = "2.0.0-rc4", path = "../../primitives/authority-discovery" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../primitives/blockchain" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +sp-runtime = { version = "2.0.0-rc4", path = "../../primitives/runtime" } +sp-api = { version = "2.0.0-rc4", path = "../../primitives/api" } [dev-dependencies] env_logger = "0.7.0" quickcheck = "0.9.0" -sc-peerset = { version = "2.0.0-alpha.5", path = "../peerset" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../test-utils/runtime/client"} - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +sc-peerset = { version = "2.0.0-rc4", path = "../peerset" } +substrate-test-runtime-client = { version = "2.0.0-rc4", path = "../../test-utils/runtime/client"} diff --git a/client/authority-discovery/src/addr_cache.rs b/client/authority-discovery/src/addr_cache.rs index 96f589c5d3c020c1dacefdb3db74a7f01c6393f1..0a27c1c44363a89731e89034d19198295402c6ad 100644 --- a/client/authority-discovery/src/addr_cache.rs +++ b/client/authority-discovery/src/addr_cache.rs @@ -68,6 +68,11 @@ where self.cache.insert(id, addresses); } + /// Returns the number of authority IDs in the cache. + pub fn num_ids(&self) -> usize { + self.cache.len() + } + // Each node should connect to a subset of all authorities. In order to prevent hot spots, this // selection is based on randomness. Selecting randomly each time we alter the address cache // would result in connection churn. To reduce this churn a node generates a seed on startup and diff --git a/client/authority-discovery/src/error.rs b/client/authority-discovery/src/error.rs index 216f8c26bf07e397a80612c17ca8ea82cd2275da..b1358485c37eeb25edd77d1c5273a8f1316dcaf2 100644 --- a/client/authority-discovery/src/error.rs +++ b/client/authority-discovery/src/error.rs @@ -44,13 +44,13 @@ pub enum Error { EncodingProto(prost::EncodeError), /// Failed to decode a protobuf payload. DecodingProto(prost::DecodeError), - /// Failed to encode or decode scale payload + /// Failed to encode or decode scale payload. EncodingDecodingScale(codec::Error), /// Failed to parse a libp2p multi address. ParsingMultiaddress(libp2p::core::multiaddr::Error), - /// Failed to sign using a specific public key + /// Failed to sign using a specific public key. MissingSignature(CryptoTypePublicPair), - /// Failed to sign using all public keys + /// Failed to sign using all public keys. Signing, /// Failed to register Prometheus metric. Prometheus(prometheus_endpoint::PrometheusError), diff --git a/client/authority-discovery/src/lib.rs b/client/authority-discovery/src/lib.rs index 176e8b2e81dcd2e53bb13ed906e54a78a68f85d3..1a4473d665ce09d053cf9ca81ed51aa240429e47 100644 --- a/client/authority-discovery/src/lib.rs +++ b/client/authority-discovery/src/lib.rs @@ -25,13 +25,11 @@ //! //! 1. **Makes itself discoverable** //! -//! 1. Retrieves its external addresses. +//! 1. Retrieves its external addresses (including peer id) or the ones of its sentry nodes. //! -//! 2. Adds its network peer id to the addresses. +//! 2. Signs the above. //! -//! 3. Signs the above. -//! -//! 4. Puts the signature and the addresses on the libp2p Kademlia DHT. +//! 3. Puts the signature and the addresses on the libp2p Kademlia DHT. //! //! //! 2. **Discovers other authorities** @@ -43,6 +41,12 @@ //! 3. Validates the signatures of the retrieved key value pairs. //! //! 4. Adds the retrieved external addresses as priority nodes to the peerset. +//! +//! When run as a sentry node, the authority discovery module does not +//! publish any addresses to the DHT but still discovers validators and +//! sentry nodes of validators, i.e. only step 2 (Discovers other authorities) +//! is executed. + use std::collections::{HashMap, HashSet}; use std::convert::TryInto; use std::marker::PhantomData; @@ -51,22 +55,30 @@ use std::sync::Arc; use std::time::{Duration, Instant}; use futures::task::{Context, Poll}; -use futures::{Future, FutureExt, Stream, StreamExt}; +use futures::{Future, FutureExt, ready, Stream, StreamExt}; use futures_timer::Delay; -use codec::{Decode, Encode}; +use addr_cache::AddrCache; +use codec::Decode; use error::{Error, Result}; -use log::{debug, error, log_enabled, warn}; +use libp2p::core::multiaddr; +use log::{debug, error, log_enabled}; use prometheus_endpoint::{Counter, CounterVec, Gauge, Opts, U64, register}; use prost::Message; use sc_client_api::blockchain::HeaderBackend; -use sc_network::{Multiaddr, config::MultiaddrWithPeerId, DhtEvent, ExHashT, NetworkStateInfo}; +use sc_network::{ + config::MultiaddrWithPeerId, + DhtEvent, + ExHashT, + Multiaddr, + NetworkStateInfo, + PeerId, +}; use sp_authority_discovery::{AuthorityDiscoveryApi, AuthorityId, AuthoritySignature, AuthorityPair}; -use sp_core::crypto::{key_types, CryptoTypePublicPair, Pair}; +use sp_core::crypto::{key_types, Pair}; use sp_core::traits::BareCryptoStorePtr; use sp_runtime::{traits::Block as BlockT, generic::BlockId}; use sp_api::ProvideRuntimeApi; -use addr_cache::AddrCache; #[cfg(test)] mod tests; @@ -80,6 +92,8 @@ mod schema { type Interval = Box + Unpin + Send + Sync>; +const LOG_TARGET: &'static str = "sub-authority-discovery"; + /// Upper bound estimation on how long one should wait before accessing the Kademlia DHT. const LIBP2P_KADEMLIA_BOOTSTRAP_TIME: Duration = Duration::from_secs(30); @@ -87,51 +101,15 @@ const LIBP2P_KADEMLIA_BOOTSTRAP_TIME: Duration = Duration::from_secs(30); /// discovery module. const AUTHORITIES_PRIORITY_GROUP_NAME: &'static str = "authorities"; -/// Prometheus metrics for an `AuthorityDiscovery`. -#[derive(Clone)] -pub(crate) struct Metrics { - publish: Counter, - amount_last_published: Gauge, - request: Counter, - dht_event_received: CounterVec, -} - -impl Metrics { - pub(crate) fn register(registry: &prometheus_endpoint::Registry) -> Result { - Ok(Self { - publish: register( - Counter::new( - "authority_discovery_times_published_total", - "Number of times authority discovery has published external addresses." - )?, - registry, - )?, - amount_last_published: register( - Gauge::new( - "authority_discovery_amount_external_addresses_last_published", - "Number of external addresses published when authority discovery last published addresses ." - )?, - registry, - )?, - request: register( - Counter::new( - "authority_discovery_times_requested_total", - "Number of times authority discovery has requested external addresses." - )?, - registry, - )?, - dht_event_received: register( - CounterVec::new( - Opts::new( - "authority_discovery_dht_event_received", - "Number of dht events received by authority discovery." - ), - &["name"], - )?, - registry, - )?, - }) - } +/// Role an authority discovery module can run as. +pub enum Role { + /// Actual authority as well as a reference to its key store. + Authority(BareCryptoStorePtr), + /// Sentry node that guards an authority. + /// + /// No reference to its key store needed, as sentry nodes don't have an identity to sign + /// addresses with in the first place. + Sentry, } /// An `AuthorityDiscovery` makes a given authority discoverable and discovers other authorities. @@ -156,8 +134,6 @@ where /// Channel we receive Dht events on. dht_event_rx: Pin + Send>>, - key_store: BareCryptoStorePtr, - /// Interval to be proactive, publishing own addresses. publish_interval: Interval, /// Interval on which to query for addresses of other authorities. @@ -167,6 +143,8 @@ where metrics: Option, + role: Role, + phantom: PhantomData, } @@ -187,8 +165,8 @@ where client: Arc, network: Arc, sentry_nodes: Vec, - key_store: BareCryptoStorePtr, dht_event_rx: Pin + Send>>, + role: Role, prometheus_registry: Option, ) -> Self { // Kademlia's default time-to-live for Dht records is 36h, republishing records every 24h. @@ -221,7 +199,7 @@ where match Metrics::register(®istry) { Ok(metrics) => Some(metrics), Err(e) => { - error!(target: "sub-authority-discovery", "Failed to register metrics: {:?}", e); + error!(target: LOG_TARGET, "Failed to register metrics: {:?}", e); None }, } @@ -234,10 +212,10 @@ where network, sentry_nodes, dht_event_rx, - key_store, publish_interval, query_interval, addr_cache, + role, metrics, phantom: PhantomData, } @@ -245,6 +223,14 @@ where /// Publish either our own or if specified the public addresses of our sentry nodes. fn publish_ext_addresses(&mut self) -> Result<()> { + let key_store = match &self.role { + Role::Authority(key_store) => key_store, + // Only authority nodes can put addresses (their own or the ones of their sentry nodes) + // on the Dht. Sentry nodes don't have a known identity to authenticate such addresses, + // thus `publish_ext_addresses` becomes a no-op. + Role::Sentry => return Ok(()), + }; + if let Some(metrics) = &self.metrics { metrics.publish.inc() } @@ -255,7 +241,7 @@ where .collect(), None => self.network.external_addresses() .into_iter() - .map(|a| a.with(libp2p::core::multiaddr::Protocol::P2p( + .map(|a| a.with(multiaddr::Protocol::P2p( self.network.local_peer_id().into(), ))) .map(|a| a.to_vec()) @@ -271,13 +257,12 @@ where .encode(&mut serialized_addresses) .map_err(Error::EncodingProto)?; - let keys: Vec = self.get_own_public_keys_within_authority_set()? - .into_iter() - .map(Into::into) - .collect(); + let keys = AuthorityDiscovery::get_own_public_keys_within_authority_set( + &key_store, + &self.client, + )?.into_iter().map(Into::into).collect::>(); - let signatures = self.key_store - .read() + let signatures = key_store.read() .sign_with_all( key_types::AUTHORITY_DISCOVERY, keys.clone(), @@ -285,22 +270,22 @@ where ) .map_err(|_| Error::Signing)?; - for (sign_result, key) in signatures.iter().zip(keys) { + for (sign_result, key) in signatures.into_iter().zip(keys) { let mut signed_addresses = vec![]; // sign_with_all returns Result signature // is generated for a public key that is supported. // Verify that all signatures exist for all provided keys. - let signature = sign_result.as_ref().map_err(|_| Error::MissingSignature(key.clone()))?; + let signature = sign_result.map_err(|_| Error::MissingSignature(key.clone()))?; schema::SignedAuthorityAddresses { addresses: serialized_addresses.clone(), - signature: Encode::encode(&signature), + signature, } .encode(&mut signed_addresses) .map_err(Error::EncodingProto)?; self.network.put_value( - hash_authority_id(key.1.as_ref())?, + hash_authority_id(key.1.as_ref()), signed_addresses, ); } @@ -309,10 +294,6 @@ where } fn request_addresses_of_others(&mut self) -> Result<()> { - if let Some(metrics) = &self.metrics { - metrics.request.inc(); - } - let id = BlockId::hash(self.client.info().best_hash); let authorities = self @@ -321,18 +302,40 @@ where .authorities(&id) .map_err(Error::CallingRuntime)?; + let local_keys = match &self.role { + Role::Authority(key_store) => { + key_store.read() + .sr25519_public_keys(key_types::AUTHORITY_DISCOVERY) + .into_iter() + .collect::>() + }, + Role::Sentry => HashSet::new(), + }; + for authority_id in authorities.iter() { - self.network - .get_value(&hash_authority_id(authority_id.as_ref())?); + // Make sure we don't look up our own keys. + if !local_keys.contains(authority_id.as_ref()) { + if let Some(metrics) = &self.metrics { + metrics.request.inc(); + } + + self.network + .get_value(&hash_authority_id(authority_id.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) => { + /// Handle incoming Dht events. + /// + /// Returns either: + /// - Poll::Pending when there are no more events to handle or + /// - Poll::Ready(()) when the dht event stream terminated. + fn handle_dht_events(&mut self, cx: &mut Context) -> Poll<()>{ + loop { + match ready!(self.dht_event_rx.poll_next_unpin(cx)) { + Some(DhtEvent::ValueFound(v)) => { if let Some(metrics) = &self.metrics { metrics.dht_event_received.with_label_values(&["value_found"]).inc(); } @@ -340,47 +343,58 @@ where if log_enabled!(log::Level::Debug) { let hashes = v.iter().map(|(hash, _value)| hash.clone()); debug!( - target: "sub-authority-discovery", + target: LOG_TARGET, "Value for hash '{:?}' found on Dht.", hashes, ); } - self.handle_dht_value_found_event(v)?; + if let Err(e) = self.handle_dht_value_found_event(v) { + if let Some(metrics) = &self.metrics { + metrics.handle_value_found_event_failure.inc(); + } + + debug!( + target: LOG_TARGET, + "Failed to handle Dht value found event: {:?}", e, + ); + } } - DhtEvent::ValueNotFound(hash) => { + Some(DhtEvent::ValueNotFound(hash)) => { if let Some(metrics) = &self.metrics { metrics.dht_event_received.with_label_values(&["value_not_found"]).inc(); } debug!( - target: "sub-authority-discovery", + target: LOG_TARGET, "Value for hash '{:?}' not found on Dht.", hash ) }, - DhtEvent::ValuePut(hash) => { + Some(DhtEvent::ValuePut(hash)) => { if let Some(metrics) = &self.metrics { metrics.dht_event_received.with_label_values(&["value_put"]).inc(); } debug!( - target: "sub-authority-discovery", + target: LOG_TARGET, "Successfully put hash '{:?}' on Dht.", hash, ) }, - DhtEvent::ValuePutFailed(hash) => { + Some(DhtEvent::ValuePutFailed(hash)) => { if let Some(metrics) = &self.metrics { metrics.dht_event_received.with_label_values(&["value_put_failed"]).inc(); } - warn!( - target: "sub-authority-discovery", + debug!( + target: LOG_TARGET, "Failed to put hash '{:?}' on Dht.", hash ) }, + None => { + debug!(target: LOG_TARGET, "Dht event stream terminated."); + return Poll::Ready(()); + }, } } - - Ok(()) } fn handle_dht_value_found_event( @@ -408,8 +422,8 @@ where self.addr_cache.retain_ids(&authorities); authorities .into_iter() - .map(|id| hash_authority_id(id.as_ref()).map(|h| (h, id))) - .collect::>>()? + .map(|id| (hash_authority_id(id.as_ref()), id)) + .collect::>() }; // Check if the event origins from an authority in the current authority set. @@ -417,6 +431,8 @@ where .get(&remote_key) .ok_or(Error::MatchingHashedAuthorityIdWithAuthorityId)?; + let local_peer_id = self.network.local_peer_id(); + let remote_addresses: Vec = values.into_iter() .map(|(_k, v)| { let schema::SignedAuthorityAddresses { signature, addresses } = @@ -441,10 +457,35 @@ where Ok(addresses) }) .collect::>>>()? - .into_iter().flatten().collect(); + .into_iter() + .flatten() + // Ignore own addresses. + .filter(|addr| !addr.iter().any(|protocol| { + // Parse to PeerId first as Multihashes of old and new PeerId + // representation don't equal. + // + // See https://github.com/libp2p/rust-libp2p/issues/555 for + // details. + if let multiaddr::Protocol::P2p(hash) = protocol { + let peer_id = match PeerId::from_multihash(hash) { + Ok(peer_id) => peer_id, + Err(_) => return true, // Discard address. + }; + + return peer_id == local_peer_id; + } + + false // Multiaddr does not contain a PeerId. + })) + .collect(); if !remote_addresses.is_empty() { self.addr_cache.insert(authority_id.clone(), remote_addresses); + if let Some(metrics) = &self.metrics { + metrics.known_authorities_count.set( + self.addr_cache.num_ids().try_into().unwrap_or(std::u64::MAX) + ); + } self.update_peer_set_priority_group()?; } @@ -457,17 +498,17 @@ where // one for the upcoming session. In addition it could be participating in the current authority // set with two keys. The function does not return all of the local authority discovery public // keys, but only the ones intersecting with the current authority set. - fn get_own_public_keys_within_authority_set(&mut self) -> Result> { - let local_pub_keys = self.key_store - .read() + fn get_own_public_keys_within_authority_set( + key_store: &BareCryptoStorePtr, + client: &Client, + ) -> Result> { + let local_pub_keys = key_store.read() .sr25519_public_keys(key_types::AUTHORITY_DISCOVERY) .into_iter() .collect::>(); - let id = BlockId::hash(self.client.info().best_hash); - let current_authorities = self - .client - .runtime_api() + let id = BlockId::hash(client.info().best_hash); + let current_authorities = client.runtime_api() .authorities(&id) .map_err(Error::CallingRuntime)? .into_iter() @@ -483,16 +524,22 @@ where } /// Update the peer set 'authority' priority group. - // fn update_peer_set_priority_group(&self) -> Result<()> { let addresses = self.addr_cache.get_subset(); + if let Some(metrics) = &self.metrics { + metrics.priority_group_size.set(addresses.len().try_into().unwrap_or(std::u64::MAX)); + } + debug!( - target: "sub-authority-discovery", + target: LOG_TARGET, "Applying priority group {:?} to peerset.", addresses, ); self.network - .set_priority_group(AUTHORITIES_PRIORITY_GROUP_NAME.to_string(), addresses.into_iter().collect()) + .set_priority_group( + AUTHORITIES_PRIORITY_GROUP_NAME.to_string(), + addresses.into_iter().collect(), + ) .map_err(Error::SettingPeersetPriorityGroup)?; Ok(()) @@ -510,40 +557,41 @@ where 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_ext_addresses()?; - } + // Process incoming events. + if let Poll::Ready(()) = self.handle_dht_events(cx) { + // `handle_dht_events` returns `Poll::Ready(())` when the Dht event stream terminated. + // Termination of the Dht event stream implies that the underlying network terminated, + // thus authority discovery should terminate as well. + return Poll::Ready(()); + } + - 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) {} + // Publish own addresses. + if let Poll::Ready(_) = self.publish_interval.poll_next_unpin(cx) { + // Register waker of underlying task for next interval. + while let Poll::Ready(_) = self.publish_interval.poll_next_unpin(cx) {} - self.request_addresses_of_others()?; + if let Err(e) = self.publish_ext_addresses() { + error!( + target: LOG_TARGET, + "Failed to publish external addresses: {:?}", e, + ); } + } - Ok(()) - }; + // Request addresses of authorities. + if let Poll::Ready(_) = self.query_interval.poll_next_unpin(cx) { + // Register waker of underlying task for next interval. + while let Poll::Ready(_) = self.query_interval.poll_next_unpin(cx) {} - match inner() { - Ok(()) => {} - Err(e) => error!(target: "sub-authority-discovery", "Poll failure: {:?}", e), - }; + if let Err(e) = self.request_addresses_of_others() { + error!( + target: LOG_TARGET, + "Failed to request addresses of authorities: {:?}", e, + ); + } + } - // Make sure to always return NotReady as this is a long running task with the same lifetime - // as the node itself. Poll::Pending } } @@ -586,10 +634,8 @@ where } } -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) +fn hash_authority_id(id: &[u8]) -> libp2p::kad::record::Key { + libp2p::kad::record::Key::new(&libp2p::multihash::Sha2_256::digest(id)) } fn interval_at(start: Instant, duration: Duration) -> Interval { @@ -601,3 +647,76 @@ fn interval_at(start: Instant, duration: Duration) -> Interval { Box::new(stream) } + +/// Prometheus metrics for an `AuthorityDiscovery`. +#[derive(Clone)] +pub(crate) struct Metrics { + publish: Counter, + amount_last_published: Gauge, + request: Counter, + dht_event_received: CounterVec, + handle_value_found_event_failure: Counter, + known_authorities_count: Gauge, + priority_group_size: Gauge, +} + +impl Metrics { + pub(crate) fn register(registry: &prometheus_endpoint::Registry) -> Result { + Ok(Self { + publish: register( + Counter::new( + "authority_discovery_times_published_total", + "Number of times authority discovery has published external addresses." + )?, + registry, + )?, + amount_last_published: register( + Gauge::new( + "authority_discovery_amount_external_addresses_last_published", + "Number of external addresses published when authority discovery last \ + published addresses." + )?, + registry, + )?, + request: register( + Counter::new( + "authority_discovery_authority_addresses_requested_total", + "Number of times authority discovery has requested external addresses of a \ + single authority." + )?, + registry, + )?, + dht_event_received: register( + CounterVec::new( + Opts::new( + "authority_discovery_dht_event_received", + "Number of dht events received by authority discovery." + ), + &["name"], + )?, + registry, + )?, + handle_value_found_event_failure: register( + Counter::new( + "authority_discovery_handle_value_found_event_failure", + "Number of times handling a dht value found event failed." + )?, + registry, + )?, + known_authorities_count: register( + Gauge::new( + "authority_discovery_known_authorities_count", + "Number of authorities known by authority discovery." + )?, + registry, + )?, + priority_group_size: register( + Gauge::new( + "authority_discovery_priority_group_size", + "Number of addresses passed to the peer set as a priority group." + )?, + registry, + )?, + }) + } +} diff --git a/client/authority-discovery/src/tests.rs b/client/authority-discovery/src/tests.rs index d23836d6fac9cc3b0c677dafbae4da048159ddf6..09a65fd138c11ad7178fe91237a644e1d6e71a1b 100644 --- a/client/authority-discovery/src/tests.rs +++ b/client/authority-discovery/src/tests.rs @@ -1,28 +1,33 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use std::{iter::FromIterator, sync::{Arc, Mutex}}; use futures::channel::mpsc::channel; -use futures::executor::block_on; -use futures::future::poll_fn; -use libp2p::{kad, PeerId}; +use futures::executor::{block_on, LocalPool}; +use futures::future::{poll_fn, FutureExt}; +use futures::sink::SinkExt; +use futures::task::LocalSpawn; +use futures::poll; +use libp2p::{kad, core::multiaddr, PeerId}; use sp_api::{ProvideRuntimeApi, ApiRef}; -use sp_core::testing::KeyStore; +use sp_core::{crypto::Public, testing::KeyStore}; use sp_runtime::traits::{Zero, Block as BlockT, NumberFor}; use substrate_test_runtime_client::runtime::Block; @@ -159,8 +164,8 @@ sp_api::mock_impl_runtime_apis! { } } -#[derive(Default)] struct TestNetwork { + peer_id: PeerId, // Whenever functions on `TestNetwork` are called, the function arguments are added to the // vectors below. pub put_value_call: Arc)>>>, @@ -168,6 +173,17 @@ struct TestNetwork { pub set_priority_group_call: Arc)>>>, } +impl Default for TestNetwork { + fn default() -> Self { + TestNetwork { + peer_id: PeerId::random(), + put_value_call: Default::default(), + get_value_call: Default::default(), + set_priority_group_call: Default::default(), + } + } +} + impl NetworkProvider for TestNetwork { fn set_priority_group( &self, @@ -190,11 +206,11 @@ impl NetworkProvider for TestNetwork { impl NetworkStateInfo for TestNetwork { fn local_peer_id(&self) -> PeerId { - PeerId::random() + self.peer_id.clone() } fn external_addresses(&self) -> Vec { - vec![] + vec!["/ip6/2001:db8::/tcp/30333".parse().unwrap()] } } @@ -213,8 +229,8 @@ fn new_registers_metrics() { test_api, network.clone(), vec![], - key_store, dht_event_rx.boxed(), + Role::Authority(key_store), Some(registry.clone()), ); @@ -222,73 +238,88 @@ fn new_registers_metrics() { } #[test] -fn publish_ext_addresses_puts_record_on_dht() { +fn request_addresses_of_others_triggers_dht_get_query() { + let _ = ::env_logger::try_init(); let (_dht_event_tx, dht_event_rx) = channel(1000); - let network: Arc = Arc::new(Default::default()); - let key_store = KeyStore::new(); - let public = key_store - .write() - .sr25519_generate_new(key_types::AUTHORITY_DISCOVERY, None) - .unwrap(); + + // Generate authority keys + let authority_1_key_pair = AuthorityPair::from_seed_slice(&[1; 32]).unwrap(); + let authority_2_key_pair = AuthorityPair::from_seed_slice(&[2; 32]).unwrap(); + let test_api = Arc::new(TestApi { - authorities: vec![public.into()], + authorities: vec![authority_1_key_pair.public(), authority_2_key_pair.public()], }); + let network: Arc = Arc::new(Default::default()); + let key_store = KeyStore::new(); + let mut authority_discovery = AuthorityDiscovery::new( test_api, network.clone(), vec![], - key_store, dht_event_rx.boxed(), + Role::Authority(key_store), None, ); - authority_discovery.publish_ext_addresses().unwrap(); + authority_discovery.request_addresses_of_others().unwrap(); - // Expect authority discovery to put a new record onto the dht. - assert_eq!(network.put_value_call.lock().unwrap().len(), 1); + // Expect authority discovery to request new records from the dht. + assert_eq!(network.get_value_call.lock().unwrap().len(), 2); } #[test] -fn request_addresses_of_others_triggers_dht_get_query() { +fn publish_discover_cycle() { let _ = ::env_logger::try_init(); - let (_dht_event_tx, dht_event_rx) = channel(1000); - // Generate authority keys - let authority_1_key_pair = AuthorityPair::from_seed_slice(&[1; 32]).unwrap(); - let authority_2_key_pair = AuthorityPair::from_seed_slice(&[2; 32]).unwrap(); + // Node A publishing its address. - let test_api = Arc::new(TestApi { - authorities: vec![authority_1_key_pair.public(), authority_2_key_pair.public()], - }); + let (_dht_event_tx, dht_event_rx) = channel(1000); let network: Arc = Arc::new(Default::default()); + let node_a_multiaddr = { + let peer_id = network.local_peer_id(); + let address = network.external_addresses().pop().unwrap(); + + address.with(multiaddr::Protocol::P2p( + peer_id.into(), + )) + }; + let key_store = KeyStore::new(); + let node_a_public = key_store + .write() + .sr25519_generate_new(key_types::AUTHORITY_DISCOVERY, None) + .unwrap(); + let test_api = Arc::new(TestApi { + authorities: vec![node_a_public.into()], + }); let mut authority_discovery = AuthorityDiscovery::new( test_api, network.clone(), vec![], - key_store, dht_event_rx.boxed(), + Role::Authority(key_store), None, ); - authority_discovery.request_addresses_of_others().unwrap(); + authority_discovery.publish_ext_addresses().unwrap(); - // Expect authority discovery to request new records from the dht. - assert_eq!(network.get_value_call.lock().unwrap().len(), 2); -} + // Expect authority discovery to put a new record onto the dht. + assert_eq!(network.put_value_call.lock().unwrap().len(), 1); -#[test] -fn handle_dht_events_with_value_found_should_call_set_priority_group() { - let _ = ::env_logger::try_init(); - // Create authority discovery. + let dht_event = { + let (key, value) = network.put_value_call.lock().unwrap().pop().unwrap(); + sc_network::DhtEvent::ValueFound(vec![(key, value)]) + }; + + // Node B discovering node A's address. let (mut dht_event_tx, dht_event_rx) = channel(1000); - let key_pair = AuthorityPair::from_seed_slice(&[1; 32]).unwrap(); let test_api = Arc::new(TestApi { - authorities: vec![key_pair.public()], + // Make sure node B identifies node A as an authority. + authorities: vec![node_a_public.into()], }); let network: Arc = Arc::new(Default::default()); let key_store = KeyStore::new(); @@ -297,38 +328,18 @@ fn handle_dht_events_with_value_found_should_call_set_priority_group() { test_api, network.clone(), vec![], - key_store, dht_event_rx.boxed(), + Role::Authority(key_store), None, ); - // Create sample dht event. - - let authority_id_1 = hash_authority_id(key_pair.public().as_ref()).unwrap(); - let address_1: 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 signature = key_pair.sign(serialized_addresses.as_ref()).encode(); - let mut signed_addresses = vec![]; - schema::SignedAuthorityAddresses { - addresses: serialized_addresses, - signature: signature, - } - .encode(&mut signed_addresses) - .unwrap(); - - let dht_event = sc_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(); + // Make authority discovery handle the event. + if let Poll::Ready(e) = authority_discovery.handle_dht_events(cx) { + panic!("Unexpected error: {:?}", e); + } // Expect authority discovery to set the priority set. assert_eq!(network.set_priority_group_call.lock().unwrap().len(), 1); @@ -337,7 +348,7 @@ fn handle_dht_events_with_value_found_should_call_set_priority_group() { network.set_priority_group_call.lock().unwrap()[0], ( "authorities".to_string(), - HashSet::from_iter(vec![address_1.clone()].into_iter()) + HashSet::from_iter(vec![node_a_multiaddr.clone()].into_iter()) ) ); @@ -346,3 +357,206 @@ fn handle_dht_events_with_value_found_should_call_set_priority_group() { let _ = block_on(poll_fn(f)); } + +#[test] +fn terminate_when_event_stream_terminates() { + let (dht_event_tx, dht_event_rx) = channel(1000); + let network: Arc = Arc::new(Default::default()); + let key_store = KeyStore::new(); + let test_api = Arc::new(TestApi { + authorities: vec![], + }); + + let mut authority_discovery = AuthorityDiscovery::new( + test_api, + network.clone(), + vec![], + dht_event_rx.boxed(), + Role::Authority(key_store), + None, + ); + + block_on(async { + assert_eq!(Poll::Pending, poll!(&mut authority_discovery)); + + // Simulate termination of the network through dropping the sender side of the dht event + // channel. + drop(dht_event_tx); + + assert_eq!( + Poll::Ready(()), poll!(&mut authority_discovery), + "Expect the authority discovery module to terminate once the sending side of the dht \ + event channel is terminated.", + ); + }); +} + +#[test] +fn dont_stop_polling_when_error_is_returned() { + #[derive(PartialEq, Debug)] + enum Event { + Processed, + End, + }; + + let (mut dht_event_tx, dht_event_rx) = channel(1000); + let (mut discovery_update_tx, mut discovery_update_rx) = channel(1000); + let network: Arc = Arc::new(Default::default()); + let key_store = KeyStore::new(); + let test_api = Arc::new(TestApi { + authorities: vec![], + }); + let mut pool = LocalPool::new(); + + let mut authority_discovery = AuthorityDiscovery::new( + test_api, + network.clone(), + vec![], + dht_event_rx.boxed(), + Role::Authority(key_store), + None, + ); + + // Spawn the authority discovery to make sure it is polled independently. + // + // As this is a local pool, only one future at a time will have the CPU and + // can make progress until the future returns `Pending`. + pool.spawner().spawn_local_obj( + futures::future::poll_fn(move |ctx| { + match std::pin::Pin::new(&mut authority_discovery).poll(ctx) { + Poll::Ready(()) => {}, + Poll::Pending => { + discovery_update_tx.send(Event::Processed).now_or_never(); + return Poll::Pending; + }, + } + let _ = discovery_update_tx.send(Event::End).now_or_never().unwrap(); + Poll::Ready(()) + }).boxed_local().into(), + ).expect("Spawns authority discovery"); + + pool.run_until( + // The future that drives the event stream + async { + // Send an event that should generate an error + let _ = dht_event_tx.send(DhtEvent::ValueFound(Default::default())).now_or_never(); + // Send the same event again to make sure that the event stream needs to be polled twice + // to be woken up again. + let _ = dht_event_tx.send(DhtEvent::ValueFound(Default::default())).now_or_never(); + + // Now we call `await` and give the control to the authority discovery future. + assert_eq!(Some(Event::Processed), discovery_update_rx.next().await); + + // Drop the event rx to stop the authority discovery. If it was polled correctly, it + // should end properly. + drop(dht_event_tx); + + assert!( + discovery_update_rx.collect::>() + .await + .into_iter() + .any(|evt| evt == Event::End), + "The authority discovery should have ended", + ); + } + ); +} + +/// In the scenario of a validator publishing the address of its sentry node to +/// the DHT, said sentry node should not add its own Multiaddr to the +/// peerset "authority" priority group. +#[test] +fn never_add_own_address_to_priority_group() { + let validator_key_store = KeyStore::new(); + let validator_public = validator_key_store + .write() + .sr25519_generate_new(key_types::AUTHORITY_DISCOVERY, None) + .unwrap(); + + let sentry_network: Arc = Arc::new(Default::default()); + + let sentry_multiaddr = { + let peer_id = sentry_network.local_peer_id(); + let address: Multiaddr = "/ip6/2001:db8:0:0:0:0:0:2/tcp/30333".parse().unwrap(); + + address.with(multiaddr::Protocol::P2p( + peer_id.into(), + )) + }; + + // Address of some other sentry node of `validator`. + let random_multiaddr = { + let peer_id = PeerId::random(); + let address: Multiaddr = "/ip6/2001:db8:0:0:0:0:0:1/tcp/30333".parse().unwrap(); + + address.with(multiaddr::Protocol::P2p( + peer_id.into(), + )) + }; + + let dht_event = { + let addresses = vec![ + sentry_multiaddr.to_vec(), + random_multiaddr.to_vec(), + ]; + + let mut serialized_addresses = vec![]; + schema::AuthorityAddresses { addresses } + .encode(&mut serialized_addresses) + .map_err(Error::EncodingProto) + .unwrap(); + + let signature = validator_key_store.read() + .sign_with( + key_types::AUTHORITY_DISCOVERY, + &validator_public.clone().into(), + serialized_addresses.as_slice(), + ) + .map_err(|_| Error::Signing) + .unwrap(); + + let mut signed_addresses = vec![]; + schema::SignedAuthorityAddresses { + addresses: serialized_addresses.clone(), + signature, + } + .encode(&mut signed_addresses) + .map_err(Error::EncodingProto) + .unwrap(); + + let key = hash_authority_id(&validator_public.to_raw_vec()); + let value = signed_addresses; + (key, value) + }; + + let (_dht_event_tx, dht_event_rx) = channel(1); + let sentry_test_api = Arc::new(TestApi { + // Make sure the sentry node identifies its validator as an authority. + authorities: vec![validator_public.into()], + }); + + let mut sentry_authority_discovery = AuthorityDiscovery::new( + sentry_test_api, + sentry_network.clone(), + vec![], + dht_event_rx.boxed(), + Role::Sentry, + None, + ); + + sentry_authority_discovery.handle_dht_value_found_event(vec![dht_event]).unwrap(); + + assert_eq!( + sentry_network.set_priority_group_call.lock().unwrap().len(), 1, + "Expect authority discovery to set the priority set.", + ); + + assert_eq!( + sentry_network.set_priority_group_call.lock().unwrap()[0], + ( + "authorities".to_string(), + HashSet::from_iter(vec![random_multiaddr.clone()].into_iter(),) + ), + "Expect authority discovery to only add `random_multiaddr`." + ); +} diff --git a/client/basic-authorship/Cargo.toml b/client/basic-authorship/Cargo.toml index 040370ac491cf09932ef1e7467ebeb96847b5af8..b6a853a1a14ef05dfe176e4da8cd48ed78596f82 100644 --- a/client/basic-authorship/Cargo.toml +++ b/client/basic-authorship/Cargo.toml @@ -1,34 +1,36 @@ [package] name = "sc-basic-authorship" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Basic implementation of block-authoring logic." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -log = "0.4.8" +codec = { package = "parity-scale-codec", version = "1.3.1" } futures = "0.3.4" -codec = { package = "parity-scale-codec", version = "1.3.0" } -sp-api = { version = "2.0.0-alpha.5", path = "../../primitives/api" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../primitives/runtime" } -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../primitives/blockchain" } -sc-client-api = { version = "2.0.0-alpha.5", path = "../api" } -sp-consensus = { version = "0.8.0-alpha.5", path = "../../primitives/consensus/common" } -sp-inherents = { version = "2.0.0-alpha.5", path = "../../primitives/inherents" } -sc-telemetry = { version = "2.0.0-alpha.5", path = "../telemetry" } -sp-transaction-pool = { version = "2.0.0-alpha.5", path = "../../primitives/transaction-pool" } -sc-block-builder = { version = "0.8.0-alpha.5", path = "../block-builder" } -tokio-executor = { version = "0.2.0-alpha.6", features = ["blocking"] } futures-timer = "3.0.1" +log = "0.4.8" +prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.8.0-rc4"} +sp-api = { version = "2.0.0-rc4", path = "../../primitives/api" } +sp-runtime = { version = "2.0.0-rc4", path = "../../primitives/runtime" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../primitives/blockchain" } +sc-client-api = { version = "2.0.0-rc4", path = "../api" } +sp-consensus = { version = "0.8.0-rc4", path = "../../primitives/consensus/common" } +sp-inherents = { version = "2.0.0-rc4", path = "../../primitives/inherents" } +sc-telemetry = { version = "2.0.0-rc4", path = "../telemetry" } +sp-transaction-pool = { version = "2.0.0-rc4", path = "../../primitives/transaction-pool" } +sc-block-builder = { version = "0.8.0-rc4", path = "../block-builder" } +sc-proposer-metrics = { version = "0.8.0-rc4", path = "../proposer-metrics" } +tokio-executor = { version = "0.2.0-alpha.6", features = ["blocking"] } [dev-dependencies] -sc-transaction-pool = { version = "2.0.0-alpha.5", path = "../../client/transaction-pool" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../test-utils/runtime/client" } +sc-transaction-pool = { version = "2.0.0-rc4", path = "../../client/transaction-pool" } +substrate-test-runtime-client = { version = "2.0.0-rc4", path = "../../test-utils/runtime/client" } parking_lot = "0.10.0" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index b3bf486aae7b780163c7500c8a46c3a85a68efbf..dd01f8893d27d5d3a4444bf45be825a878c40696 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! A consensus proposer for "basic" chains which use the primitive inherent-data. @@ -23,8 +25,7 @@ use sc_client_api::backend; use codec::Decode; use sp_consensus::{evaluation, Proposal, RecordProof}; use sp_inherents::InherentData; -use log::{error, info, debug, trace}; -use sp_core::ExecutionContext; +use log::{error, info, debug, trace, warn}; use sp_runtime::{ generic::BlockId, traits::{Block as BlockT, Hash as HashT, Header as HeaderT, DigestFor, BlakeTwo256}, @@ -34,24 +35,34 @@ use sc_telemetry::{telemetry, CONSENSUS_INFO}; use sc_block_builder::{BlockBuilderApi, BlockBuilderProvider}; use sp_api::{ProvideRuntimeApi, ApiExt}; use futures::{executor, future, future::Either}; -use sp_blockchain::{HeaderBackend, ApplyExtrinsicFailed}; +use sp_blockchain::{HeaderBackend, ApplyExtrinsicFailed::Validity, Error::ApplyExtrinsicFailed}; use std::marker::PhantomData; +use prometheus_endpoint::Registry as PrometheusRegistry; +use sc_proposer_metrics::MetricsLink as PrometheusMetrics; + /// Proposer factory. pub struct ProposerFactory { /// The client instance. client: Arc, /// The transaction pool. transaction_pool: Arc, + /// Prometheus Link, + metrics: PrometheusMetrics, /// phantom member to pin the `Backend` type. _phantom: PhantomData, } impl ProposerFactory { - pub fn new(client: Arc, transaction_pool: Arc) -> Self { + pub fn new( + client: Arc, + transaction_pool: Arc, + prometheus: Option<&PrometheusRegistry>, + ) -> Self { ProposerFactory { client, transaction_pool, + metrics: PrometheusMetrics::new(prometheus), _phantom: PhantomData, } } @@ -79,15 +90,14 @@ impl ProposerFactory info!("🙌 Starting consensus session on top of parent {:?}", parent_hash); let proposer = Proposer { - inner: Arc::new(ProposerInner { - client: self.client.clone(), - parent_hash, - parent_id: id, - parent_number: *parent_header.number(), - transaction_pool: self.transaction_pool.clone(), - now, - _phantom: PhantomData, - }), + client: self.client.clone(), + parent_hash, + parent_id: id, + parent_number: *parent_header.number(), + transaction_pool: self.transaction_pool.clone(), + now, + metrics: self.metrics.clone(), + _phantom: PhantomData, }; proposer @@ -119,17 +129,13 @@ impl sp_consensus::Environment for /// The proposer logic. pub struct Proposer { - inner: Arc>, -} - -/// Proposer inner, to wrap parameters under Arc. -struct ProposerInner { client: Arc, parent_hash: ::Hash, parent_id: BlockId, parent_number: <::Header as HeaderT>::Number, transaction_pool: Arc, now: Box time::Instant + Send + Sync>, + metrics: PrometheusMetrics, _phantom: PhantomData, } @@ -151,22 +157,21 @@ impl sp_consensus::Proposer for type Error = sp_blockchain::Error; fn propose( - &mut self, + self, inherent_data: InherentData, inherent_digests: DigestFor, max_duration: time::Duration, record_proof: RecordProof, ) -> Self::Proposal { - let inner = self.inner.clone(); tokio_executor::blocking::run(move || { // leave some time for evaluation and block finalization (33%) - let deadline = (inner.now)() + max_duration - max_duration / 3; - inner.propose_with(inherent_data, inherent_digests, deadline, record_proof) + let deadline = (self.now)() + max_duration - max_duration / 3; + self.propose_with(inherent_data, inherent_digests, deadline, record_proof) }) } } -impl ProposerInner +impl Proposer where A: TransactionPool, B: backend::Backend + Send + Sync + 'static, @@ -177,7 +182,7 @@ impl ProposerInner + BlockBuilderApi, { fn propose_with( - &self, + self, inherent_data: InherentData, inherent_digests: DigestFor, deadline: time::Instant, @@ -194,20 +199,23 @@ impl ProposerInner record_proof, )?; - // We don't check the API versions any further here since the dispatch compatibility - // check should be enough. - for extrinsic in self.client.runtime_api() - .inherent_extrinsics_with_context( - &self.parent_id, - ExecutionContext::BlockConstruction, - inherent_data - )? - { - block_builder.push(extrinsic)?; + for inherent in block_builder.create_inherents(inherent_data)? { + match block_builder.push(inherent) { + Err(ApplyExtrinsicFailed(Validity(e))) if e.exhausted_resources() => + warn!("⚠️ Dropping non-mandatory inherent from overweight block."), + Err(ApplyExtrinsicFailed(Validity(e))) if e.was_mandatory() => { + error!("❌️ Mandatory inherent extrinsic returned error. Block cannot be produced."); + Err(ApplyExtrinsicFailed(Validity(e)))? + } + Err(e) => { + warn!("❗️ Inherent extrinsic returned unexpected error: {}. Dropping.", e); + } + Ok(_) => {} + } } // proceed with transactions - let mut is_first = true; + let block_timer = time::Instant::now(); let mut skipped = 0; let mut unqueue_invalid = Vec::new(); let pending_iterator = match executor::block_on(future::select( @@ -217,7 +225,8 @@ impl ProposerInner Either::Left((iterator, _)) => iterator, Either::Right(_) => { log::warn!( - "Timeout fired waiting for transaction pool to be ready. Proceeding to block production anyway.", + "Timeout fired waiting for transaction pool at block #{}. Proceeding with production.", + self.parent_number, ); self.transaction_pool.ready() } @@ -241,12 +250,9 @@ impl ProposerInner Ok(()) => { debug!("[{:?}] Pushed to the block.", pending_tx_hash); } - Err(sp_blockchain::Error::ApplyExtrinsicFailed(ApplyExtrinsicFailed::Validity(e))) + Err(ApplyExtrinsicFailed(Validity(e))) if e.exhausted_resources() => { - if is_first { - debug!("[{:?}] Invalid transaction: FullBlock on empty block", pending_tx_hash); - unqueue_invalid.push(pending_tx_hash); - } else if skipped < MAX_SKIPPED_TRANSACTIONS { + if skipped < MAX_SKIPPED_TRANSACTIONS { skipped += 1; debug!( "Block seems full, but will try {} more transactions before quitting.", @@ -269,14 +275,19 @@ impl ProposerInner unqueue_invalid.push(pending_tx_hash); } } - - is_first = false; } self.transaction_pool.remove_invalid(&unqueue_invalid); let (block, storage_changes, proof) = block_builder.build()?.into_inner(); + self.metrics.report( + |metrics| { + metrics.number_of_transactions.set(block.extrinsics().len() as u64); + metrics.block_constructed.observe(block_timer.elapsed().as_secs_f64()); + } + ); + info!("🎁 Prepared block for proposing at {} [hash: {:?}; parent_hash: {}; extrinsics ({}): [{}]]", block.header().number(), ::Hash::from(block.header().hash()), @@ -312,15 +323,14 @@ mod tests { use parking_lot::Mutex; use sp_consensus::{BlockOrigin, Proposer}; use substrate_test_runtime_client::{ - prelude::*, - runtime::{Extrinsic, Transfer}, + prelude::*, TestClientBuilder, runtime::{Extrinsic, Transfer}, TestClientBuilderExt, }; use sp_transaction_pool::{ChainEvent, MaintainedTransactionPool, TransactionSource}; use sc_transaction_pool::{BasicPool, FullChainApi}; use sp_api::Core; - use backend::Backend; use sp_blockchain::HeaderBackend; use sp_runtime::traits::NumberFor; + use sc_client_api::Backend; const SOURCE: TransactionSource = TransactionSource::External; @@ -333,12 +343,12 @@ mod tests { }.into_signed_tx() } - fn chain_event(block_number: u64, header: B::Header) -> ChainEvent + fn chain_event(header: B::Header) -> ChainEvent where NumberFor: From { ChainEvent::NewBlock { - id: BlockId::Number(block_number.into()), - retracted: vec![], + hash: header.hash(), + tree_route: None, is_new_best: true, header, } @@ -348,8 +358,13 @@ mod tests { fn should_cease_building_block_when_deadline_is_reached() { // given let client = Arc::new(substrate_test_runtime_client::new()); - let txpool = Arc::new( - BasicPool::new(Default::default(), Arc::new(FullChainApi::new(client.clone()))).0 + let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let txpool = BasicPool::new_full( + Default::default(), + Arc::new(FullChainApi::new(client.clone(), None)), + None, + spawner, + client.clone(), ); futures::executor::block_on( @@ -358,15 +373,16 @@ mod tests { futures::executor::block_on( txpool.maintain(chain_event( - 0, - client.header(&BlockId::Number(0u64)).expect("header get error").expect("there should be header") + client.header(&BlockId::Number(0u64)) + .expect("header get error") + .expect("there should be header") )) ); - let mut proposer_factory = ProposerFactory::new(client.clone(), txpool.clone()); + let mut proposer_factory = ProposerFactory::new(client.clone(), txpool.clone(), None); let cell = Mutex::new((false, time::Instant::now())); - let mut proposer = proposer_factory.init_with_now( + let proposer = proposer_factory.init_with_now( &client.header(&BlockId::number(0)).unwrap().unwrap(), Box::new(move || { let mut value = cell.lock(); @@ -396,14 +412,19 @@ mod tests { #[test] fn should_not_panic_when_deadline_is_reached() { let client = Arc::new(substrate_test_runtime_client::new()); - let txpool = Arc::new( - BasicPool::new(Default::default(), Arc::new(FullChainApi::new(client.clone()))).0 + let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let txpool = BasicPool::new_full( + Default::default(), + Arc::new(FullChainApi::new(client.clone(), None)), + None, + spawner, + client.clone(), ); - let mut proposer_factory = ProposerFactory::new(client.clone(), txpool.clone()); + let mut proposer_factory = ProposerFactory::new(client.clone(), txpool.clone(), None); let cell = Mutex::new((false, time::Instant::now())); - let mut proposer = proposer_factory.init_with_now( + let proposer = proposer_factory.init_with_now( &client.header(&BlockId::number(0)).unwrap().unwrap(), Box::new(move || { let mut value = cell.lock(); @@ -425,12 +446,17 @@ mod tests { #[test] fn proposed_storage_changes_should_match_execute_block_storage_changes() { - let (client, backend) = substrate_test_runtime_client::TestClientBuilder::new() - .build_with_backend(); + let (client, backend) = TestClientBuilder::new().build_with_backend(); let client = Arc::new(client); - let txpool = Arc::new( - BasicPool::new(Default::default(), Arc::new(FullChainApi::new(client.clone()))).0 + let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let txpool = BasicPool::new_full( + Default::default(), + Arc::new(FullChainApi::new(client.clone(), None)), + None, + spawner, + client.clone(), ); + let genesis_hash = client.info().best_hash; let block_id = BlockId::Hash(genesis_hash); @@ -440,14 +466,15 @@ mod tests { futures::executor::block_on( txpool.maintain(chain_event( - 0, - client.header(&BlockId::Number(0u64)).expect("header get error").expect("there should be header") + client.header(&BlockId::Number(0u64)) + .expect("header get error") + .expect("there should be header"), )) ); - let mut proposer_factory = ProposerFactory::new(client.clone(), txpool.clone()); + let mut proposer_factory = ProposerFactory::new(client.clone(), txpool.clone(), None); - let mut proposer = proposer_factory.init_with_now( + let proposer = proposer_factory.init_with_now( &client.header(&block_id).unwrap().unwrap(), Box::new(move || time::Instant::now()), ); @@ -468,8 +495,11 @@ mod tests { backend.changes_trie_storage(), ).unwrap(); - let storage_changes = api.into_storage_changes(&state, changes_trie_state.as_ref(), genesis_hash) - .unwrap(); + let storage_changes = api.into_storage_changes( + &state, + changes_trie_state.as_ref(), + genesis_hash, + ).unwrap(); assert_eq!( proposal.storage_changes.transaction_storage_root, @@ -481,8 +511,13 @@ mod tests { fn should_not_remove_invalid_transactions_when_skipping() { // given let mut client = Arc::new(substrate_test_runtime_client::new()); - let txpool = Arc::new( - BasicPool::new(Default::default(), Arc::new(FullChainApi::new(client.clone()))).0 + let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let txpool = BasicPool::new_full( + Default::default(), + Arc::new(FullChainApi::new(client.clone(), None)), + None, + spawner, + client.clone(), ); futures::executor::block_on( @@ -507,14 +542,14 @@ mod tests { ]) ).unwrap(); - let mut proposer_factory = ProposerFactory::new(client.clone(), txpool.clone()); + let mut proposer_factory = ProposerFactory::new(client.clone(), txpool.clone(), None); let mut propose_block = | client: &TestClient, number, expected_block_extrinsics, expected_pool_transactions, | { - let mut proposer = proposer_factory.init_with_now( + let proposer = proposer_factory.init_with_now( &client.header(&BlockId::number(number)).unwrap().unwrap(), Box::new(move || time::Instant::now()), ); @@ -535,8 +570,9 @@ mod tests { futures::executor::block_on( txpool.maintain(chain_event( - 0, - client.header(&BlockId::Number(0u64)).expect("header get error").expect("there should be header") + client.header(&BlockId::Number(0u64)) + .expect("header get error") + .expect("there should be header") )) ); @@ -546,8 +582,9 @@ mod tests { futures::executor::block_on( txpool.maintain(chain_event( - 1, - client.header(&BlockId::Number(1)).expect("header get error").expect("there should be header") + client.header(&BlockId::Number(1)) + .expect("header get error") + .expect("there should be header") )) ); diff --git a/client/basic-authorship/src/lib.rs b/client/basic-authorship/src/lib.rs index 5ec0bc6f9a520c5d8292ce21cc219b5a8a658bab..68356d0a28ff804f11e6fdff234c9db77eea5cc9 100644 --- a/client/basic-authorship/src/lib.rs +++ b/client/basic-authorship/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Basic implementation of block-authoring logic. //! @@ -23,12 +25,22 @@ //! # use sp_consensus::{Environment, Proposer, RecordProof}; //! # use sp_runtime::generic::BlockId; //! # use std::{sync::Arc, time::Duration}; -//! # use substrate_test_runtime_client::{self, runtime::{Extrinsic, Transfer}, AccountKeyring}; +//! # use substrate_test_runtime_client::{ +//! # runtime::{Extrinsic, Transfer}, AccountKeyring, +//! # DefaultTestClientBuilderExt, TestClientBuilderExt, +//! # }; //! # use sc_transaction_pool::{BasicPool, FullChainApi}; //! # let client = Arc::new(substrate_test_runtime_client::new()); -//! # let txpool = Arc::new(BasicPool::new(Default::default(), Arc::new(FullChainApi::new(client.clone()))).0); +//! # let spawner = sp_core::testing::SpawnBlockingExecutor::new(); +//! # let txpool = BasicPool::new_full( +//! # Default::default(), +//! # Arc::new(FullChainApi::new(client.clone(), None)), +//! # None, +//! # spawner, +//! # client.clone(), +//! # ); //! // The first step is to create a `ProposerFactory`. -//! let mut proposer_factory = ProposerFactory::new(client.clone(), txpool.clone()); +//! let mut proposer_factory = ProposerFactory::new(client.clone(), txpool.clone(), None); //! //! // From this factory, we create a `Proposer`. //! let proposer = proposer_factory.init( @@ -36,7 +48,7 @@ //! ); //! //! // The proposer is created asynchronously. -//! let mut proposer = futures::executor::block_on(proposer).unwrap(); +//! let proposer = futures::executor::block_on(proposer).unwrap(); //! //! // This `Proposer` allows us to create a block proposition. //! // The proposer will grab transactions from the transaction pool, and put them into the block. diff --git a/client/block-builder/Cargo.toml b/client/block-builder/Cargo.toml index 5f9ef7c75e8591baaada2b2ff1a46fbebc72f231..a56ff61cd0f536ded60fd898b9298eb682e68274 100644 --- a/client/block-builder/Cargo.toml +++ b/client/block-builder/Cargo.toml @@ -1,28 +1,29 @@ [package] name = "sc-block-builder" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate block builder" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-state-machine = { version = "0.8.0-alpha.5", path = "../../primitives/state-machine" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../primitives/runtime" } -sp-api = { version = "2.0.0-alpha.5", path = "../../primitives/api" } -sp-consensus = { version = "0.8.0-alpha.5", path = "../../primitives/consensus/common" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../primitives/blockchain" } -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -sp-block-builder = { version = "2.0.0-alpha.5", path = "../../primitives/block-builder" } -sc-client-api = { version = "2.0.0-alpha.5", path = "../api" } -codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive"] } +sp-state-machine = { version = "0.8.0-rc4", path = "../../primitives/state-machine" } +sp-runtime = { version = "2.0.0-rc4", path = "../../primitives/runtime" } +sp-api = { version = "2.0.0-rc4", path = "../../primitives/api" } +sp-consensus = { version = "0.8.0-rc4", path = "../../primitives/consensus/common" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../primitives/blockchain" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +sp-block-builder = { version = "2.0.0-rc4", path = "../../primitives/block-builder" } +sp-inherents = { version = "2.0.0-rc4", path = "../../primitives/inherents" } +sc-client-api = { version = "2.0.0-rc4", path = "../api" } +codec = { package = "parity-scale-codec", version = "1.3.1", features = ["derive"] } [dev-dependencies] substrate-test-runtime-client = { path = "../../test-utils/runtime/client" } -sp-trie = { version = "2.0.0-alpha.5", path = "../../primitives/trie" } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +sp-trie = { version = "2.0.0-rc4", path = "../../primitives/trie" } diff --git a/client/block-builder/src/lib.rs b/client/block-builder/src/lib.rs index 480a759e30d706941049bff06392478c4411537a..904667b1afc6e99d3cf63f09d7f88890e631f041 100644 --- a/client/block-builder/src/lib.rs +++ b/client/block-builder/src/lib.rs @@ -1,23 +1,25 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Substrate block builder //! //! This crate provides the [`BlockBuilder`] utility and the corresponding runtime api -//! [`BlockBuilder`](api::BlockBuilder).Error +//! [`BlockBuilder`](sp_block_builder::BlockBuilder).Error //! //! The block builder utility is used in the node as an abstraction over the runtime api to //! initialize a block, to push extrinsics and to finalize a block. @@ -32,7 +34,10 @@ use sp_runtime::{ }; use sp_blockchain::{ApplyExtrinsicFailed, Error}; use sp_core::ExecutionContext; -use sp_api::{Core, ApiExt, ApiErrorFor, ApiRef, ProvideRuntimeApi, StorageChanges, StorageProof}; +use sp_api::{ + Core, ApiExt, ApiErrorFor, ApiRef, ProvideRuntimeApi, StorageChanges, StorageProof, + TransactionOutcome, +}; use sp_consensus::RecordProof; pub use sp_block_builder::BlockBuilder as BlockBuilderApi; @@ -154,17 +159,22 @@ where let block_id = &self.block_id; let extrinsics = &mut self.extrinsics; - self.api.map_api_result(|api| { + self.api.execute_in_transaction(|api| { match api.apply_extrinsic_with_context( block_id, ExecutionContext::BlockConstruction, xt.clone(), - )? { - Ok(_) => { + ) { + Ok(Ok(_)) => { extrinsics.push(xt); - Ok(()) + TransactionOutcome::Commit(Ok(())) } - Err(tx_validity) => Err(ApplyExtrinsicFailed::Validity(tx_validity).into()), + Ok(Err(tx_validity)) => { + TransactionOutcome::Rollback( + Err(ApplyExtrinsicFailed::Validity(tx_validity).into()), + ) + }, + Err(e) => TransactionOutcome::Rollback(Err(e)), } }) } @@ -210,6 +220,25 @@ where proof, }) } + + /// Create the inherents for the block. + /// + /// Returns the inherents created by the runtime or an error if something failed. + pub fn create_inherents( + &mut self, + inherent_data: sp_inherents::InherentData, + ) -> Result, ApiErrorFor> { + let block_id = self.block_id; + self.api.execute_in_transaction(move |api| { + // `create_inherents` should not change any state, to ensure this we always rollback + // the transaction. + TransactionOutcome::Rollback(api.inherent_extrinsics_with_context( + &block_id, + ExecutionContext::BlockConstruction, + inherent_data + )) + }) + } } #[cfg(test)] diff --git a/client/chain-spec/Cargo.toml b/client/chain-spec/Cargo.toml index 5d65cbd842b5430064ae2249fe63f9f0b4cf2b8c..a3176deee5ed7666f650df8a2bd6024d4704580b 100644 --- a/client/chain-spec/Cargo.toml +++ b/client/chain-spec/Cargo.toml @@ -1,22 +1,23 @@ [package] name = "sc-chain-spec" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate chain configurations." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sc-chain-spec-derive = { version = "2.0.0-alpha.5", path = "./derive" } +sc-chain-spec-derive = { version = "2.0.0-rc4", path = "./derive" } impl-trait-for-tuples = "0.1.3" -sc-network = { version = "0.8.0-alpha.5", path = "../network" } -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } +sc-network = { version = "0.8.0-rc4", path = "../network" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } serde = { version = "1.0.101", features = ["derive"] } serde_json = "1.0.41" -sp-runtime = { version = "2.0.0-alpha.5", path = "../../primitives/runtime" } -sc-telemetry = { version = "2.0.0-alpha.5", path = "../telemetry" } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +sp-runtime = { version = "2.0.0-rc4", path = "../../primitives/runtime" } +sp-chain-spec = { version = "2.0.0-rc4", path = "../../primitives/chain-spec" } +sc-telemetry = { version = "2.0.0-rc4", path = "../telemetry" } diff --git a/client/chain-spec/derive/Cargo.toml b/client/chain-spec/derive/Cargo.toml index 9343c9a6de1c95919abe695b4918bd576117efbf..75a290dc98332178df5290616b9fd1bb81755bee 100644 --- a/client/chain-spec/derive/Cargo.toml +++ b/client/chain-spec/derive/Cargo.toml @@ -1,13 +1,16 @@ [package] name = "sc-chain-spec-derive" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Macros to derive chain spec extension traits implementation." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [lib] proc-macro = true @@ -18,6 +21,3 @@ quote = "1.0.3" syn = "1.0.7" [dev-dependencies] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/client/chain-spec/derive/src/impls.rs b/client/chain-spec/derive/src/impls.rs index 1b22f16581a79c25920cc8733469b12dd2ba7e94..ded961a6da8159d8cc5f1db8c3c7fe80dc94d77c 100644 --- a/client/chain-spec/derive/src/impls.rs +++ b/client/chain-spec/derive/src/impls.rs @@ -64,7 +64,6 @@ pub fn extension_derive(ast: &DeriveInput) -> proc_macro::TokenStream { }) } - /// 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| { @@ -75,9 +74,27 @@ pub fn group_derive(ast: &DeriveInput) -> proc_macro::TokenStream { 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); + let serde_crate_name = match proc_macro_crate::crate_name("serde") { + Ok(name) => Ident::new(&name.replace("-", "_"), Span::call_site()), + Err(e) => { + let err = Error::new( + Span::call_site(), + &format!("Could not find `serde` crate: {}", e), + ).to_compile_error(); + + return quote!( #err ).into(); + } + }; quote! { - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecExtension)] + #[derive( + Debug, + Clone, + PartialEq, + #serde_crate_name::Serialize, + #serde_crate_name::Deserialize, + ChainSpecExtension, + )] pub struct #fork_name #ty_generics #where_clause { #fork_fields } diff --git a/client/chain-spec/src/chain_spec.rs b/client/chain-spec/src/chain_spec.rs index a7cf1d8aac4143ff758ec67b39e32c39eb6cc379..52414f8687c96ed97f56e84e1345d3c0f8423ecc 100644 --- a/client/chain-spec/src/chain_spec.rs +++ b/client/chain-spec/src/chain_spec.rs @@ -1,32 +1,29 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Substrate chain configurations. -use std::borrow::Cow; -use std::collections::HashMap; -use std::fs::File; -use std::path::PathBuf; -use std::sync::Arc; +use std::{borrow::Cow, fs::File, path::PathBuf, sync::Arc, collections::HashMap}; use serde::{Serialize, Deserialize}; use sp_core::storage::{StorageKey, StorageData, ChildInfo, Storage, StorageChild}; use sp_runtime::BuildStorage; use serde_json as json; -use crate::RuntimeGenesis; -use crate::extension::GetExtension; +use crate::{RuntimeGenesis, ChainType, extension::GetExtension, Properties}; use sc_network::config::MultiaddrWithPeerId; use sc_telemetry::TelemetryEndpoints; @@ -34,14 +31,16 @@ enum GenesisSource { File(PathBuf), Binary(Cow<'static, [u8]>), Factory(Arc G + Send + Sync>), + Storage(Storage), } impl Clone for GenesisSource { fn clone(&self) -> Self { match *self { - GenesisSource::File(ref path) => GenesisSource::File(path.clone()), - GenesisSource::Binary(ref d) => GenesisSource::Binary(d.clone()), - GenesisSource::Factory(ref f) => GenesisSource::Factory(f.clone()), + Self::File(ref path) => Self::File(path.clone()), + Self::Binary(ref d) => Self::Binary(d.clone()), + Self::Factory(ref f) => Self::Factory(f.clone()), + Self::Storage(ref s) => Self::Storage(s.clone()), } } } @@ -54,19 +53,40 @@ impl GenesisSource { } match self { - GenesisSource::File(path) => { + Self::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))?; Ok(genesis.genesis) }, - GenesisSource::Binary(buf) => { + Self::Binary(buf) => { 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())), + Self::Factory(f) => Ok(Genesis::Runtime(f())), + Self::Storage(storage) => { + let top = storage.top + .iter() + .map(|(k, v)| (StorageKey(k.clone()), StorageData(v.clone()))) + .collect(); + + let children_default = storage.children_default + .iter() + .map(|(k, child)| + ( + StorageKey(k.clone()), + child.data + .iter() + .map(|(k, v)| (StorageKey(k.clone()), StorageData(v.clone()))) + .collect() + ) + ) + .collect(); + + Ok(Genesis::Raw(RawGenesis { top, children_default })) + }, } } } @@ -75,17 +95,14 @@ impl BuildStorage for ChainSpec { fn build_storage(&self) -> Result { match self.genesis.resolve()? { Genesis::Runtime(gc) => gc.build_storage(), - Genesis::Raw(RawGenesis { top: map, children: children_map }) => Ok(Storage { + Genesis::Raw(RawGenesis { top: map, children_default: children_map }) => Ok(Storage { top: map.into_iter().map(|(k, v)| (k.0, v.0)).collect(), - children: children_map.into_iter().map(|(sk, child_content)| { - let child_info = ChildInfo::resolve_child_info( - child_content.child_type, - child_content.child_info.as_slice(), - ).expect("chain spec contains correct content").to_owned(); + children_default: children_map.into_iter().map(|(storage_key, child_content)| { + let child_info = ChildInfo::new_default(storage_key.0.as_slice()); ( - sk.0, + storage_key.0, StorageChild { - data: child_content.data.into_iter().map(|(k, v)| (k.0, v.0)).collect(), + data: child_content.into_iter().map(|(k, v)| (k.0, v.0)).collect(), child_info, }, ) @@ -102,24 +119,15 @@ impl BuildStorage for ChainSpec { } } -type GenesisStorage = HashMap; +pub type GenesisStorage = HashMap; +/// Raw storage content for genesis block. #[derive(Serialize, Deserialize)] #[serde(rename_all = "camelCase")] #[serde(deny_unknown_fields)] -struct ChildRawStorage { - data: GenesisStorage, - child_info: Vec, - child_type: u32, -} - -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -#[serde(deny_unknown_fields)] -/// Storage content for genesis block. -struct RawGenesis { - top: GenesisStorage, - children: HashMap, +pub struct RawGenesis { + pub top: GenesisStorage, + pub children_default: HashMap, } #[derive(Serialize, Deserialize)] @@ -137,6 +145,8 @@ enum Genesis { struct ClientSpec { name: String, id: String, + #[serde(default)] + chain_type: ChainType, boot_nodes: Vec, telemetry_endpoints: Option, protocol_id: Option, @@ -149,9 +159,6 @@ struct ClientSpec { 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. @@ -219,6 +226,7 @@ impl ChainSpec { pub fn from_genesis G + 'static + Send + Sync>( name: &str, id: &str, + chain_type: ChainType, constructor: F, boot_nodes: Vec, telemetry_endpoints: Option, @@ -229,6 +237,7 @@ impl ChainSpec { let client_spec = ClientSpec { name: name.to_owned(), id: id.to_owned(), + chain_type, boot_nodes, telemetry_endpoints, protocol_id: protocol_id.map(str::to_owned), @@ -243,6 +252,11 @@ impl ChainSpec { genesis: GenesisSource::Factory(Arc::new(constructor)), } } + + /// Type of the chain. + fn chain_type(&self) -> ChainType { + self.client_spec.chain_type.clone() + } } impl ChainSpec { @@ -270,7 +284,7 @@ impl ChainSpec { } } -impl ChainSpec { +impl ChainSpec { /// Dump to json string. pub fn as_json(&self, raw: bool) -> Result { #[derive(Serialize, Deserialize)] @@ -286,23 +300,16 @@ impl ChainSpec { let top = storage.top.into_iter() .map(|(k, v)| (StorageKey(k), StorageData(v))) .collect(); - let children = storage.children.into_iter() - .map(|(sk, child)| { - let info = child.child_info.as_ref(); - let (info, ci_type) = info.info(); - ( - StorageKey(sk), - ChildRawStorage { - data: child.data.into_iter() - .map(|(k, v)| (StorageKey(k), StorageData(v))) - .collect(), - child_info: info.to_vec(), - child_type: ci_type, - }, - )}) + let children_default = storage.children_default.into_iter() + .map(|(sk, child)| ( + StorageKey(sk), + child.data.into_iter() + .map(|(k, v)| (StorageKey(k), StorageData(v))) + .collect(), + )) .collect(); - Genesis::Raw(RawGenesis { top, children }) + Genesis::Raw(RawGenesis { top, children_default }) }, (_, genesis) => genesis, }; @@ -317,8 +324,8 @@ impl ChainSpec { impl crate::ChainSpec for ChainSpec where - G: RuntimeGenesis, - E: GetExtension + serde::Serialize + Clone + Send, + G: RuntimeGenesis + 'static, + E: GetExtension + serde::Serialize + Clone + Send + 'static, { fn boot_nodes(&self) -> &[MultiaddrWithPeerId] { ChainSpec::boot_nodes(self) @@ -332,6 +339,10 @@ where ChainSpec::id(self) } + fn chain_type(&self) -> ChainType { + ChainSpec::chain_type(self) + } + fn telemetry_endpoints(&self) -> &Option { ChainSpec::telemetry_endpoints(self) } @@ -359,6 +370,14 @@ where fn as_storage_builder(&self) -> &dyn BuildStorage { self } + + fn cloned_box(&self) -> Box { + Box::new(self.clone()) + } + + fn set_storage(&mut self, storage: Storage) { + self.genesis = GenesisSource::Storage(storage); + } } #[cfg(test)] @@ -392,6 +411,7 @@ mod tests { ).unwrap(); assert_eq!(spec1.as_json(false), spec2.as_json(false)); + assert_eq!(spec2.chain_type(), ChainType::Live) } #[derive(Debug, Serialize, Deserialize)] diff --git a/client/chain-spec/src/lib.rs b/client/chain-spec/src/lib.rs index b7875fdbb4670ee97fb9ccd14971d3b0e3c3d95a..8901a9a682224991a3679f6e160ac0a0c36f8237 100644 --- a/client/chain-spec/src/lib.rs +++ b/client/chain-spec/src/lib.rs @@ -29,10 +29,9 @@ //! //! ```rust //! use std::collections::HashMap; -//! use serde::{Serialize, Deserialize}; //! use sc_chain_spec::{GenericChainSpec, ChainSpecExtension}; //! -//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecExtension)] +//! #[derive(Clone, Debug, serde::Serialize, serde::Deserialize, ChainSpecExtension)] //! pub struct MyExtension { //! pub known_blocks: HashMap, //! } @@ -48,21 +47,20 @@ //! block number. //! //! ```rust -//! use serde::{Serialize, Deserialize}; //! use sc_chain_spec::{Forks, ChainSpecGroup, ChainSpecExtension, GenericChainSpec}; //! -//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup)] +//! #[derive(Clone, Debug, serde::Serialize, serde::Deserialize, ChainSpecGroup)] //! pub struct ClientParams { //! max_block_size: usize, //! max_extrinsic_size: usize, //! } //! -//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup)] +//! #[derive(Clone, Debug, serde::Serialize, serde::Deserialize, ChainSpecGroup)] //! pub struct PoolParams { //! max_transaction_size: usize, //! } //! -//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)] +//! #[derive(Clone, Debug, serde::Serialize, serde::Deserialize, ChainSpecGroup, ChainSpecExtension)] //! pub struct Extension { //! pub client: ClientParams, //! pub pool: PoolParams, @@ -107,29 +105,32 @@ //! pub type MyChainSpec = GenericChainSpec; //! ``` - mod chain_spec; mod extension; -pub use chain_spec::{ChainSpec as GenericChainSpec, Properties, NoExtension}; +pub use chain_spec::{ChainSpec as GenericChainSpec, NoExtension}; pub use extension::{Group, Fork, Forks, Extension, GetExtension, get_extension}; pub use sc_chain_spec_derive::{ChainSpecExtension, ChainSpecGroup}; +pub use sp_chain_spec::{Properties, ChainType}; use serde::{Serialize, de::DeserializeOwned}; use sp_runtime::BuildStorage; use sc_network::config::MultiaddrWithPeerId; use sc_telemetry::TelemetryEndpoints; +use sp_core::storage::Storage; /// A set of traits for the runtime genesis config. pub trait RuntimeGenesis: Serialize + DeserializeOwned + BuildStorage {} impl RuntimeGenesis for T {} -/// Common interface to `GenericChainSpec` +/// Common interface of a chain specification. pub trait ChainSpec: BuildStorage + Send { /// Spec name. fn name(&self) -> &str; /// Spec id. fn id(&self) -> &str; + /// Type of the chain. + fn chain_type(&self) -> ChainType; /// A list of bootnode addresses. fn boot_nodes(&self) -> &[MultiaddrWithPeerId]; /// Telemetry endpoints (if any) @@ -148,4 +149,16 @@ pub trait ChainSpec: BuildStorage + Send { fn as_json(&self, raw: bool) -> Result; /// Return StorageBuilder for this spec. fn as_storage_builder(&self) -> &dyn BuildStorage; + /// Returns a cloned `Box`. + fn cloned_box(&self) -> Box; + /// Set the storage that should be used by this chain spec. + /// + /// This will be used as storage at genesis. + fn set_storage(&mut self, storage: Storage); +} + +impl std::fmt::Debug for dyn ChainSpec { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "ChainSpec(name = {:?}, id = {:?})", self.name(), self.id()) + } } diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 89247cf016d100792a6ca49e3882529c165472c4..3bf480f0b1eee76dbb13e9e05e36469d1a4e443b 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -1,15 +1,17 @@ [package] name = "sc-cli" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] description = "Substrate CLI interface." edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -clap = "2.33.0" derive_more = "0.99.2" env_logger = "0.7.0" log = "0.4.8" @@ -18,29 +20,30 @@ regex = "1.3.1" time = "0.1.42" ansi_term = "0.12.1" lazy_static = "1.4.0" -app_dirs = "1.2.1" tokio = { version = "0.2.9", features = [ "signal", "rt-core", "rt-threaded" ] } futures = "0.3.4" fdlimit = "0.1.4" serde_json = "1.0.41" -sc-informant = { version = "0.8.0-alpha.5", path = "../informant" } -sp-panic-handler = { version = "2.0.0-alpha.5", path = "../../primitives/panic-handler" } -sc-client-api = { version = "2.0.0-alpha.5", path = "../api" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../primitives/blockchain" } -sc-network = { version = "0.8.0-alpha.5", path = "../network" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../primitives/runtime" } -sp-utils = { version = "2.0.0-alpha.5", path = "../../primitives/utils" } -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -sc-service = { version = "0.8.0-alpha.5", default-features = false, path = "../service" } -sp-state-machine = { version = "0.8.0-alpha.5", path = "../../primitives/state-machine" } -sc-telemetry = { version = "2.0.0-alpha.5", path = "../telemetry" } -substrate-prometheus-endpoint = { path = "../../utils/prometheus" , version = "0.8.0-alpha.5"} -sp-keyring = { version = "2.0.0-alpha.5", path = "../../primitives/keyring" } +sc-informant = { version = "0.8.0-rc4", path = "../informant" } +sp-panic-handler = { version = "2.0.0-rc4", path = "../../primitives/panic-handler" } +sc-client-api = { version = "2.0.0-rc4", path = "../api" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../primitives/blockchain" } +sc-network = { version = "0.8.0-rc4", path = "../network" } +sp-runtime = { version = "2.0.0-rc4", path = "../../primitives/runtime" } +sp-utils = { version = "2.0.0-rc4", path = "../../primitives/utils" } +sp-version = { version = "2.0.0-rc4", path = "../../primitives/version" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +sc-service = { version = "0.8.0-rc4", default-features = false, path = "../service" } +sp-state-machine = { version = "0.8.0-rc4", path = "../../primitives/state-machine" } +sc-telemetry = { version = "2.0.0-rc4", path = "../telemetry" } +substrate-prometheus-endpoint = { path = "../../utils/prometheus" , version = "0.8.0-rc4"} +sp-keyring = { version = "2.0.0-rc4", path = "../../primitives/keyring" } names = "0.11.0" structopt = "0.3.8" -sc-tracing = { version = "2.0.0-alpha.5", path = "../tracing" } +sc-tracing = { version = "2.0.0-rc4", path = "../tracing" } chrono = "0.4.10" -parity-util-mem = { version = "0.6.0", default-features = false, features = ["primitive-types"] } +parity-util-mem = { version = "0.7.0", default-features = false, features = ["primitive-types"] } +serde = "1.0.111" [target.'cfg(not(target_os = "unknown"))'.dependencies] rpassword = "4.0.1" @@ -55,6 +58,3 @@ tempfile = "3.1.0" wasmtime = [ "sc-service/wasmtime", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/client/cli/src/arg_enums.rs b/client/cli/src/arg_enums.rs index 384087bec0dbe4538c7227e36a6dbce7d789586b..db13fff76148e6acbfc74212e0c4a4cacc53e525 100644 --- a/client/cli/src/arg_enums.rs +++ b/client/cli/src/arg_enums.rs @@ -1,19 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . - +// along with this program. If not, see . // NOTE: we allow missing docs here because arg_enum! creates the function variants without doc #![allow(missing_docs)] @@ -45,7 +46,9 @@ impl WasmExecutionMethod { impl Into for WasmExecutionMethod { fn into(self) -> sc_service::config::WasmExecutionMethod { match self { - WasmExecutionMethod::Interpreted => sc_service::config::WasmExecutionMethod::Interpreted, + WasmExecutionMethod::Interpreted => { + sc_service::config::WasmExecutionMethod::Interpreted + } #[cfg(feature = "wasmtime")] WasmExecutionMethod::Compiled => sc_service::config::WasmExecutionMethod::Compiled, #[cfg(not(feature = "wasmtime"))] @@ -120,10 +123,63 @@ impl ExecutionStrategy { } } +arg_enum! { + /// Available RPC methods. + #[allow(missing_docs)] + #[derive(Debug, Copy, Clone, PartialEq)] + pub enum RpcMethods { + // Expose every RPC method only when RPC is listening on `localhost`, + // otherwise serve only safe RPC methods. + Auto, + // Allow only a safe subset of RPC methods. + Safe, + // Expose every RPC method (even potentially unsafe ones). + Unsafe, + } +} + +impl Into for RpcMethods { + fn into(self) -> sc_service::config::RpcMethods { + match self { + RpcMethods::Auto => sc_service::config::RpcMethods::Auto, + RpcMethods::Safe => sc_service::config::RpcMethods::Safe, + RpcMethods::Unsafe => sc_service::config::RpcMethods::Unsafe, + } + } +} + +arg_enum! { + /// Database backend + #[allow(missing_docs)] + #[derive(Debug, Clone, Copy)] + pub enum Database { + // Facebooks RocksDB + RocksDb, + // Subdb. https://github.com/paritytech/subdb/ + SubDb, + // ParityDb. https://github.com/paritytech/parity-db/ + ParityDb, + } +} + + +arg_enum! { + /// Whether off-chain workers are enabled. + #[allow(missing_docs)] + #[derive(Debug, Clone)] + pub enum OffchainWorkerEnabled { + Always, + Never, + WhenValidating, + } +} + /// Default value for the `--execution-syncing` parameter. pub const DEFAULT_EXECUTION_SYNCING: ExecutionStrategy = ExecutionStrategy::NativeElseWasm; /// Default value for the `--execution-import-block` parameter. pub const DEFAULT_EXECUTION_IMPORT_BLOCK: ExecutionStrategy = ExecutionStrategy::NativeElseWasm; +/// Default value for the `--execution-import-block` parameter when the node is a validator. +pub const DEFAULT_EXECUTION_IMPORT_BLOCK_VALIDATOR: ExecutionStrategy = ExecutionStrategy::Wasm; /// Default value for the `--execution-block-construction` parameter. pub const DEFAULT_EXECUTION_BLOCK_CONSTRUCTION: ExecutionStrategy = ExecutionStrategy::Wasm; /// Default value for the `--execution-offchain-worker` parameter. diff --git a/client/cli/src/commands/build_spec_cmd.rs b/client/cli/src/commands/build_spec_cmd.rs index 67aaf998fca6f5d6c198fcc44c5120e5c587660c..616c5139f64f0d370373bda2b221bacea8700b6c 100644 --- a/client/cli/src/commands/build_spec_cmd.rs +++ b/client/cli/src/commands/build_spec_cmd.rs @@ -1,31 +1,33 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 structopt::StructOpt; -use log::info; -use sc_network::config::{build_multiaddr, MultiaddrWithPeerId}; -use sc_service::{Configuration, ChainSpec}; +// along with this program. If not, see . use crate::error; -use crate::VersionInfo; -use crate::params::SharedParams; use crate::params::NodeKeyParams; +use crate::params::SharedParams; +use crate::CliConfiguration; +use log::info; +use sc_network::config::build_multiaddr; +use sc_service::{config::{MultiaddrWithPeerId, NetworkConfiguration}, ChainSpec}; +use structopt::StructOpt; +use std::io::Write; /// The `build-spec` command used to build a specification. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, StructOpt)] pub struct BuildSpecCmd { /// Force raw genesis storage output. #[structopt(long = "raw")] @@ -50,15 +52,15 @@ pub struct BuildSpecCmd { impl BuildSpecCmd { /// Run the build-spec command pub fn run( - self, - config: Configuration, + &self, + mut spec: Box, + network_config: NetworkConfiguration, ) -> error::Result<()> { info!("Building chain spec"); - let mut spec = config.chain_spec.expect("`chain_spec` is set to `Some` in `update_config`"); let raw_output = self.raw; if spec.boot_nodes().is_empty() && !self.disable_default_bootnode { - let keys = config.network.node_key.into_keypair()?; + let keys = network_config.node_key.into_keypair()?; let peer_id = keys.public().into_peer_id(); let addr = MultiaddrWithPeerId { multiaddr: build_multiaddr![Ip4([127, 0, 0, 1]), Tcp(30333u16)], @@ -68,30 +70,19 @@ impl BuildSpecCmd { } let json = sc_service::chain_ops::build_spec(&*spec, raw_output)?; - - print!("{}", json); - + if std::io::stdout().write_all(json.as_bytes()).is_err() { + let _ = std::io::stderr().write_all(b"Error writing to stdout\n"); + } Ok(()) } +} - /// Update and prepare a `Configuration` with command line parameters - pub fn update_config( - &self, - mut config: &mut Configuration, - spec_factory: F, - version: &VersionInfo, - ) -> error::Result<()> where - F: FnOnce(&str) -> Result, String>, - { - self.shared_params.update_config(&mut config, spec_factory, version)?; - - let net_config_path = config - .in_chain_config_dir(crate::commands::DEFAULT_NETWORK_CONFIG_PATH) - .expect("We provided a base_path"); - - self.node_key_params.update_config(&mut config, Some(&net_config_path))?; +impl CliConfiguration for BuildSpecCmd { + fn shared_params(&self) -> &SharedParams { + &self.shared_params + } - Ok(()) + fn node_key_params(&self) -> Option<&NodeKeyParams> { + Some(&self.node_key_params) } } - diff --git a/client/cli/src/commands/check_block_cmd.rs b/client/cli/src/commands/check_block_cmd.rs index ba267bbf4bbc54489229a15dde20103a7e1e382a..b536d4f26bb6c875745e0ee180eca07a31158b68 100644 --- a/client/cli/src/commands/check_block_cmd.rs +++ b/client/cli/src/commands/check_block_cmd.rs @@ -1,40 +1,35 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . -use std::fmt::Debug; -use std::str::FromStr; -use structopt::StructOpt; -use sc_service::{ - Configuration, ServiceBuilderCommand, Role, ChainSpec, +use crate::{ + CliConfiguration, error, params::{ImportParams, SharedParams, BlockNumberOrHash}, }; +use sc_client_api::{BlockBackend, UsageProvider}; use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; -use sp_runtime::generic::BlockId; - -use crate::error; -use crate::VersionInfo; -use crate::runtime::run_until_exit; -use crate::params::SharedParams; -use crate::params::ImportParams; +use std::{fmt::Debug, str::FromStr, sync::Arc}; +use structopt::StructOpt; /// The `check-block` command used to validate blocks. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, StructOpt)] pub struct CheckBlockCmd { /// Block hash or number #[structopt(value_name = "HASH or NUMBER")] - pub input: String, + pub input: BlockNumberOrHash, /// The default number of 64KB pages to ever allocate for Wasm execution. /// @@ -53,49 +48,33 @@ pub struct CheckBlockCmd { impl CheckBlockCmd { /// Run the check-block command - pub fn run( - self, - config: Configuration, - builder: B, + pub async fn run( + &self, + client: Arc, + import_queue: IQ, ) -> error::Result<()> where - B: FnOnce(Configuration) -> Result, - BC: ServiceBuilderCommand + Unpin, - BB: sp_runtime::traits::Block + Debug, - <<::Header as HeaderT>::Number as std::str::FromStr>::Err: std::fmt::Debug, - ::Hash: std::str::FromStr, + B: BlockT + for<'de> serde::Deserialize<'de>, + C: BlockBackend + UsageProvider + Send + Sync + 'static, + IQ: sc_service::ImportQueue + 'static, + B::Hash: FromStr, + ::Err: Debug, + <::Number as FromStr>::Err: Debug, { - let input = if self.input.starts_with("0x") { &self.input[2..] } else { &self.input[..] }; - let block_id = match FromStr::from_str(input) { - Ok(hash) => BlockId::hash(hash), - Err(_) => match self.input.parse::() { - Ok(n) => BlockId::number((n as u32).into()), - Err(_) => return Err(error::Error::Input("Invalid hash or number specified".into())), - } - }; - let start = std::time::Instant::now(); - run_until_exit(config, |config| { - Ok(builder(config)?.check_block(block_id)) - })?; + sc_service::chain_ops::check_block(client, import_queue, self.input.parse()?).await?; println!("Completed in {} ms.", start.elapsed().as_millis()); Ok(()) } +} - /// Update and prepare a `Configuration` with command line parameters - pub fn update_config( - &self, - mut config: &mut Configuration, - spec_factory: F, - version: &VersionInfo, - ) -> error::Result<()> where - F: FnOnce(&str) -> Result, String>, - { - self.shared_params.update_config(&mut config, spec_factory, version)?; - self.import_params.update_config(&mut config, &Role::Full, self.shared_params.dev)?; - config.use_in_memory_keystore()?; +impl CliConfiguration for CheckBlockCmd { + fn shared_params(&self) -> &SharedParams { + &self.shared_params + } - Ok(()) + fn import_params(&self) -> Option<&ImportParams> { + Some(&self.import_params) } } diff --git a/client/cli/src/commands/export_blocks_cmd.rs b/client/cli/src/commands/export_blocks_cmd.rs index 26cfcf61bfabe909320121d5c63a2cfffe40b8a7..118832a79d29d96ba255b0df8b92ea04b1091301 100644 --- a/client/cli/src/commands/export_blocks_cmd.rs +++ b/client/cli/src/commands/export_blocks_cmd.rs @@ -1,38 +1,40 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . -use std::io; -use std::fs; -use std::path::PathBuf; -use std::fmt::Debug; +use crate::error; +use crate::params::{BlockNumber, DatabaseParams, PruningParams, SharedParams}; +use crate::CliConfiguration; use log::info; -use structopt::StructOpt; use sc_service::{ - Configuration, ServiceBuilderCommand, ChainSpec, - config::DatabaseConfig, Role, + config::DatabaseConfig, chain_ops::export_blocks, }; +use sc_client_api::{BlockBackend, UsageProvider}; use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; - -use crate::error; -use crate::VersionInfo; -use crate::runtime::run_until_exit; -use crate::params::{SharedParams, BlockNumber, PruningParams}; +use std::fmt::Debug; +use std::fs; +use std::io; +use std::path::PathBuf; +use std::str::FromStr; +use std::sync::Arc; +use structopt::StructOpt; /// The `export-blocks` command used to export blocks. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, StructOpt)] pub struct ExportBlocksCmd { /// Output file name or stdout if unspecified. #[structopt(parse(from_os_str))] @@ -51,7 +53,7 @@ pub struct ExportBlocksCmd { pub to: Option, /// Use binary output rather than JSON. - #[structopt(long = "binary", value_name = "BOOL", parse(try_from_str), default_value("false"))] + #[structopt(long)] pub binary: bool, #[allow(missing_docs)] @@ -61,25 +63,28 @@ pub struct ExportBlocksCmd { #[allow(missing_docs)] #[structopt(flatten)] pub pruning_params: PruningParams, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub database_params: DatabaseParams, } impl ExportBlocksCmd { /// Run the export-blocks command - pub fn run( - self, - config: Configuration, - builder: B, + pub async fn run( + &self, + client: Arc, + database_config: DatabaseConfig, ) -> error::Result<()> where - B: FnOnce(Configuration) -> Result, - BC: ServiceBuilderCommand + Unpin, - BB: sp_runtime::traits::Block + Debug, - <<::Header as HeaderT>::Number as std::str::FromStr>::Err: std::fmt::Debug, - ::Hash: std::str::FromStr, + B: BlockT, + C: BlockBackend + UsageProvider + 'static, + <::Number as FromStr>::Err: Debug, { - if let DatabaseConfig::Path { ref path, .. } = config.expect_database() { + if let DatabaseConfig::RocksDb { ref path, .. } = database_config { info!("DB path: {}", path.display()); } + let from = self.from.as_ref().and_then(|f| f.parse().ok()).unwrap_or(1); let to = self.to.as_ref().and_then(|t| t.parse().ok()); @@ -90,24 +95,22 @@ impl ExportBlocksCmd { None => Box::new(io::stdout()), }; - run_until_exit(config, |config| { - Ok(builder(config)?.export_blocks(file, from.into(), to, binary)) - }) + export_blocks(client, file, from.into(), to, binary) + .await + .map_err(Into::into) } +} - /// Update and prepare a `Configuration` with command line parameters - pub fn update_config( - &self, - mut config: &mut Configuration, - spec_factory: F, - version: &VersionInfo, - ) -> error::Result<()> where - F: FnOnce(&str) -> Result, String>, - { - self.shared_params.update_config(&mut config, spec_factory, version)?; - self.pruning_params.update_config(&mut config, &Role::Full, true)?; - config.use_in_memory_keystore()?; +impl CliConfiguration for ExportBlocksCmd { + fn shared_params(&self) -> &SharedParams { + &self.shared_params + } + + fn pruning_params(&self) -> Option<&PruningParams> { + Some(&self.pruning_params) + } - Ok(()) + fn database_params(&self) -> Option<&DatabaseParams> { + Some(&self.database_params) } } diff --git a/client/cli/src/commands/export_state_cmd.rs b/client/cli/src/commands/export_state_cmd.rs new file mode 100644 index 0000000000000000000000000000000000000000..c078db0d8aea922e23ddfda88112e22f5979bbbe --- /dev/null +++ b/client/cli/src/commands/export_state_cmd.rs @@ -0,0 +1,82 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use crate::{ + CliConfiguration, error, params::{PruningParams, SharedParams, BlockNumberOrHash}, +}; +use log::info; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; +use std::{fmt::Debug, str::FromStr, io::Write, sync::Arc}; +use structopt::StructOpt; +use sc_client_api::{StorageProvider, UsageProvider}; + +/// The `export-state` command used to export the state of a given block into +/// a chain spec. +#[derive(Debug, StructOpt)] +pub struct ExportStateCmd { + /// Block hash or number. + #[structopt(value_name = "HASH or NUMBER")] + pub input: Option, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub shared_params: SharedParams, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub pruning_params: PruningParams, +} + +impl ExportStateCmd { + /// Run the `export-state` command + pub async fn run( + &self, + client: Arc, + mut input_spec: Box, + ) -> error::Result<()> + where + B: BlockT, + C: UsageProvider + StorageProvider, + BA: sc_client_api::backend::Backend, + B::Hash: FromStr, + ::Err: Debug, + <::Number as FromStr>::Err: Debug, + { + info!("Exporting raw state..."); + let block_id = self.input.as_ref().map(|b| b.parse()).transpose()?; + let raw_state = sc_service::chain_ops::export_raw_state(client, block_id)?; + input_spec.set_storage(raw_state); + + info!("Generating new chain spec..."); + let json = sc_service::chain_ops::build_spec(&*input_spec, true)?; + if std::io::stdout().write_all(json.as_bytes()).is_err() { + let _ = std::io::stderr().write_all(b"Error writing to stdout\n"); + } + Ok(()) + } +} + +impl CliConfiguration for ExportStateCmd { + fn shared_params(&self) -> &SharedParams { + &self.shared_params + } + + fn pruning_params(&self) -> Option<&PruningParams> { + Some(&self.pruning_params) + } +} diff --git a/client/cli/src/commands/import_blocks_cmd.rs b/client/cli/src/commands/import_blocks_cmd.rs index 5dc8debe064f3435479849463eef9daaf87f9fd9..00f8ec43b02fe937b26db243ab930adf793e75bc 100644 --- a/client/cli/src/commands/import_blocks_cmd.rs +++ b/client/cli/src/commands/import_blocks_cmd.rs @@ -1,37 +1,37 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . +use crate::error; +use crate::params::ImportParams; +use crate::params::SharedParams; +use crate::CliConfiguration; +use sc_service::chain_ops::import_blocks; +use sp_runtime::traits::Block as BlockT; use std::fmt::Debug; -use std::io::{Read, Seek, self}; use std::fs; +use std::io::{self, Read, Seek}; use std::path::PathBuf; +use std::sync::Arc; use structopt::StructOpt; -use sc_service::{ - Configuration, ServiceBuilderCommand, ChainSpec, Role, -}; -use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; - -use crate::error; -use crate::VersionInfo; -use crate::runtime::run_until_exit; -use crate::params::SharedParams; -use crate::params::ImportParams; +use sc_client_api::UsageProvider; /// The `import-blocks` command used to import blocks. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, StructOpt)] pub struct ImportBlocksCmd { /// Input file or stdin if unspecified. #[structopt(parse(from_os_str))] @@ -43,6 +43,10 @@ pub struct ImportBlocksCmd { #[structopt(long = "default-heap-pages", value_name = "COUNT")] pub default_heap_pages: Option, + /// Try importing blocks from binary format rather than JSON. + #[structopt(long)] + pub binary: bool, + #[allow(missing_docs)] #[structopt(flatten)] pub shared_params: SharedParams, @@ -59,17 +63,15 @@ impl ReadPlusSeek for T {} impl ImportBlocksCmd { /// Run the import-blocks command - pub fn run( - self, - config: Configuration, - builder: B, + pub async fn run( + &self, + client: Arc, + import_queue: IQ, ) -> error::Result<()> where - B: FnOnce(Configuration) -> Result, - BC: ServiceBuilderCommand + Unpin, - BB: sp_runtime::traits::Block + Debug, - <<::Header as HeaderT>::Number as std::str::FromStr>::Err: std::fmt::Debug, - ::Hash: std::str::FromStr, + C: UsageProvider + Send + Sync + 'static, + B: BlockT + for<'de> serde::Deserialize<'de>, + IQ: sc_service::ImportQueue + 'static, { let file: Box = match &self.input { Some(filename) => Box::new(fs::File::open(filename)?), @@ -77,27 +79,21 @@ impl ImportBlocksCmd { let mut buffer = Vec::new(); io::stdin().read_to_end(&mut buffer)?; Box::new(io::Cursor::new(buffer)) - }, + } }; - run_until_exit(config, |config| { - Ok(builder(config)?.import_blocks(file, false)) - }) + import_blocks(client, import_queue, file, false, self.binary) + .await + .map_err(Into::into) } +} - /// Update and prepare a `Configuration` with command line parameters - pub fn update_config( - &self, - mut config: &mut Configuration, - spec_factory: F, - version: &VersionInfo, - ) -> error::Result<()> where - F: FnOnce(&str) -> Result, String>, - { - self.shared_params.update_config(&mut config, spec_factory, version)?; - self.import_params.update_config(&mut config, &Role::Full, self.shared_params.dev)?; - config.use_in_memory_keystore()?; +impl CliConfiguration for ImportBlocksCmd { + fn shared_params(&self) -> &SharedParams { + &self.shared_params + } - Ok(()) + fn import_params(&self) -> Option<&ImportParams> { + Some(&self.import_params) } } diff --git a/client/cli/src/commands/mod.rs b/client/cli/src/commands/mod.rs index d87b08f7f49828ef48bb469c016d2ac65e507906..04cce66bef80d231a2b9d63509d1133914c7e5a1 100644 --- a/client/cli/src/commands/mod.rs +++ b/client/cli/src/commands/mod.rs @@ -1,139 +1,417 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 runcmd; -mod export_blocks_cmd; +// along with this program. If not, see . mod build_spec_cmd; -mod import_blocks_cmd; mod check_block_cmd; -mod revert_cmd; +mod export_blocks_cmd; +mod export_state_cmd; +mod import_blocks_cmd; mod purge_chain_cmd; +mod revert_cmd; +mod run_cmd; +pub use self::build_spec_cmd::BuildSpecCmd; +pub use self::check_block_cmd::CheckBlockCmd; +pub use self::export_blocks_cmd::ExportBlocksCmd; +pub use self::export_state_cmd::ExportStateCmd; +pub use self::import_blocks_cmd::ImportBlocksCmd; +pub use self::purge_chain_cmd::PurgeChainCmd; +pub use self::revert_cmd::RevertCmd; +pub use self::run_cmd::RunCmd; use std::fmt::Debug; use structopt::StructOpt; -use sc_service::{ Configuration, ServiceBuilderCommand, ChainSpec }; -use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; - -use crate::error; -use crate::VersionInfo; -use crate::params::SharedParams; - -pub use crate::commands::runcmd::RunCmd; -pub use crate::commands::export_blocks_cmd::ExportBlocksCmd; -pub use crate::commands::build_spec_cmd::BuildSpecCmd; -pub use crate::commands::import_blocks_cmd::ImportBlocksCmd; -pub use crate::commands::check_block_cmd::CheckBlockCmd; -pub use crate::commands::revert_cmd::RevertCmd; -pub use crate::commands::purge_chain_cmd::PurgeChainCmd; - -/// default sub directory to store network config -const DEFAULT_NETWORK_CONFIG_PATH : &'static str = "network"; - /// All core commands that are provided by default. /// /// The core commands are split into multiple subcommands and `Run` is the default subcommand. From /// the CLI user perspective, it is not visible that `Run` is a subcommand. So, all parameters of /// `Run` are exported as main executable parameters. -#[derive(Debug, Clone, StructOpt)] +#[derive(Debug, StructOpt)] pub enum Subcommand { /// Build a spec.json file, outputs to stdout. - BuildSpec(build_spec_cmd::BuildSpecCmd), + BuildSpec(BuildSpecCmd), /// Export blocks to a file. - ExportBlocks(export_blocks_cmd::ExportBlocksCmd), + ExportBlocks(ExportBlocksCmd), /// Import blocks from file. - ImportBlocks(import_blocks_cmd::ImportBlocksCmd), + ImportBlocks(ImportBlocksCmd), /// Validate a single block. - CheckBlock(check_block_cmd::CheckBlockCmd), + CheckBlock(CheckBlockCmd), /// Revert chain to the previous state. - Revert(revert_cmd::RevertCmd), + Revert(RevertCmd), /// Remove the whole chain data. - PurgeChain(purge_chain_cmd::PurgeChainCmd), + PurgeChain(PurgeChainCmd), + + /// Export state as raw chain spec. + ExportState(ExportStateCmd), } -impl Subcommand { - /// Get the shared parameters of a `CoreParams` command. - pub fn get_shared_params(&self) -> &SharedParams { - use Subcommand::*; - - match self { - BuildSpec(params) => ¶ms.shared_params, - ExportBlocks(params) => ¶ms.shared_params, - ImportBlocks(params) => ¶ms.shared_params, - CheckBlock(params) => ¶ms.shared_params, - Revert(params) => ¶ms.shared_params, - PurgeChain(params) => ¶ms.shared_params, - } - } +// TODO: move to config.rs? +/// Macro that helps implement CliConfiguration on an enum of subcommand automatically +/// +/// # Example +/// +/// ``` +/// # #[macro_use] extern crate sc_cli; +/// +/// # struct EmptyVariant {} +/// +/// # impl sc_cli::CliConfiguration for EmptyVariant { +/// # fn shared_params(&self) -> &sc_cli::SharedParams { unimplemented!() } +/// # fn chain_id(&self, _: bool) -> sc_cli::Result { Ok("test-chain-id".to_string()) } +/// # } +/// +/// # fn main() { +/// enum Subcommand { +/// Variant1(EmptyVariant), +/// Variant2(EmptyVariant), +/// } +/// +/// substrate_cli_subcommands!( +/// Subcommand => Variant1, Variant2 +/// ); +/// +/// # use sc_cli::CliConfiguration; +/// # assert_eq!(Subcommand::Variant1(EmptyVariant {}).chain_id(false).unwrap(), "test-chain-id"); +/// +/// # } +/// ``` +/// +/// Which will expand to: +/// +/// ```ignore +/// impl CliConfiguration for Subcommand { +/// fn base_path(&self) -> Result> { +/// match self { +/// Subcommand::Variant1(cmd) => cmd.base_path(), +/// Subcommand::Variant2(cmd) => cmd.base_path(), +/// } +/// } +/// +/// fn is_dev(&self) -> Result { +/// match self { +/// Subcommand::Variant1(cmd) => cmd.is_dev(), +/// Subcommand::Variant2(cmd) => cmd.is_dev(), +/// } +/// } +/// +/// // ... +/// } +/// ``` +#[macro_export] +macro_rules! substrate_cli_subcommands { + ($enum:ident => $($variant:ident),*) => { + impl $crate::CliConfiguration for $enum { + fn shared_params(&self) -> &$crate::SharedParams { + match self { + $($enum::$variant(cmd) => cmd.shared_params()),* + } + } - /// Run any `CoreParams` command. - pub fn run( - self, - config: Configuration, - builder: B, - ) -> error::Result<()> - where - B: FnOnce(Configuration) -> Result, - BC: ServiceBuilderCommand + Unpin, - BB: sp_runtime::traits::Block + Debug, - <<::Header as HeaderT>::Number as std::str::FromStr>::Err: std::fmt::Debug, - ::Hash: std::str::FromStr, - { - match self { - Subcommand::BuildSpec(cmd) => cmd.run(config), - Subcommand::ExportBlocks(cmd) => cmd.run(config, builder), - Subcommand::ImportBlocks(cmd) => cmd.run(config, builder), - Subcommand::CheckBlock(cmd) => cmd.run(config, builder), - Subcommand::PurgeChain(cmd) => cmd.run(config), - Subcommand::Revert(cmd) => cmd.run(config, builder), - } - } + fn import_params(&self) -> Option<&$crate::ImportParams> { + match self { + $($enum::$variant(cmd) => cmd.import_params()),* + } + } - /// Update and prepare a `Configuration` with command line parameters. - pub fn update_config( - &self, - mut config: &mut Configuration, - spec_factory: F, - version: &VersionInfo, - ) -> error::Result<()> where - F: FnOnce(&str) -> Result, String>, - { - match self { - Subcommand::BuildSpec(cmd) => cmd.update_config(&mut config, spec_factory, version), - Subcommand::ExportBlocks(cmd) => cmd.update_config(&mut config, spec_factory, version), - Subcommand::ImportBlocks(cmd) => cmd.update_config(&mut config, spec_factory, version), - Subcommand::CheckBlock(cmd) => cmd.update_config(&mut config, spec_factory, version), - Subcommand::PurgeChain(cmd) => cmd.update_config(&mut config, spec_factory, version), - Subcommand::Revert(cmd) => cmd.update_config(&mut config, spec_factory, version), - } - } + fn pruning_params(&self) -> Option<&$crate::PruningParams> { + match self { + $($enum::$variant(cmd) => cmd.pruning_params()),* + } + } + + fn keystore_params(&self) -> Option<&$crate::KeystoreParams> { + match self { + $($enum::$variant(cmd) => cmd.keystore_params()),* + } + } + + fn network_params(&self) -> Option<&$crate::NetworkParams> { + match self { + $($enum::$variant(cmd) => cmd.network_params()),* + } + } + + fn offchain_worker_params(&self) -> Option<&$crate::OffchainWorkerParams> { + match self { + $($enum::$variant(cmd) => cmd.offchain_worker_params()),* + } + } + + fn database_params(&self) -> Option<&$crate::DatabaseParams> { + match self { + $($enum::$variant(cmd) => cmd.database_params()),* + } + } + + fn base_path(&self) -> $crate::Result<::std::option::Option> { + match self { + $($enum::$variant(cmd) => cmd.base_path()),* + } + } - /// Initialize substrate. This must be done only once. - /// - /// This method: - /// - /// 1. Set the panic handler - /// 2. Raise the FD limit - /// 3. Initialize the logger - pub fn init(&self, version: &VersionInfo) -> error::Result<()> { - self.get_shared_params().init(version) + fn is_dev(&self) -> $crate::Result { + match self { + $($enum::$variant(cmd) => cmd.is_dev()),* + } + } + + fn role(&self, is_dev: bool) -> $crate::Result<::sc_service::Role> { + match self { + $($enum::$variant(cmd) => cmd.role(is_dev)),* + } + } + + fn transaction_pool(&self) + -> $crate::Result<::sc_service::config::TransactionPoolOptions> { + match self { + $($enum::$variant(cmd) => cmd.transaction_pool()),* + } + } + + fn network_config( + &self, + chain_spec: &::std::boxed::Box, + is_dev: bool, + net_config_dir: ::std::path::PathBuf, + client_id: &str, + node_name: &str, + node_key: ::sc_service::config::NodeKeyConfig, + ) -> $crate::Result<::sc_service::config::NetworkConfiguration> { + match self { + $( + $enum::$variant(cmd) => cmd.network_config( + chain_spec, is_dev, net_config_dir, client_id, node_name, node_key + ) + ),* + } + } + + fn keystore_config(&self, base_path: &::std::path::PathBuf) + -> $crate::Result<::sc_service::config::KeystoreConfig> { + match self { + $($enum::$variant(cmd) => cmd.keystore_config(base_path)),* + } + } + + fn database_cache_size(&self) -> $crate::Result<::std::option::Option> { + match self { + $($enum::$variant(cmd) => cmd.database_cache_size()),* + } + } + + fn database_config( + &self, + base_path: &::std::path::PathBuf, + cache_size: usize, + database: $crate::Database, + ) -> $crate::Result<::sc_service::config::DatabaseConfig> { + match self { + $($enum::$variant(cmd) => cmd.database_config(base_path, cache_size, database)),* + } + } + + fn database(&self) -> $crate::Result<::std::option::Option<$crate::Database>> { + match self { + $($enum::$variant(cmd) => cmd.database()),* + } + } + + fn state_cache_size(&self) -> $crate::Result { + match self { + $($enum::$variant(cmd) => cmd.state_cache_size()),* + } + } + + fn state_cache_child_ratio(&self) -> $crate::Result<::std::option::Option> { + match self { + $($enum::$variant(cmd) => cmd.state_cache_child_ratio()),* + } + } + + fn pruning(&self, unsafe_pruning: bool, role: &::sc_service::Role) + -> $crate::Result<::sc_service::config::PruningMode> { + match self { + $($enum::$variant(cmd) => cmd.pruning(unsafe_pruning, role)),* + } + } + + fn chain_id(&self, is_dev: bool) -> $crate::Result { + match self { + $($enum::$variant(cmd) => cmd.chain_id(is_dev)),* + } + } + + fn init(&self) -> $crate::Result<()> { + match self { + $($enum::$variant(cmd) => cmd.init::()),* + } + } + + fn node_name(&self) -> $crate::Result { + match self { + $($enum::$variant(cmd) => cmd.node_name()),* + } + } + + fn wasm_method(&self) -> $crate::Result<::sc_service::config::WasmExecutionMethod> { + match self { + $($enum::$variant(cmd) => cmd.wasm_method()),* + } + } + + fn execution_strategies(&self, is_dev: bool, is_validator: bool) + -> $crate::Result<::sc_client_api::execution_extensions::ExecutionStrategies> { + match self { + $($enum::$variant(cmd) => cmd.execution_strategies(is_dev, is_validator)),* + } + } + + fn rpc_ipc(&self) -> $crate::Result<::std::option::Option<::std::string::String>> { + match self { + $($enum::$variant(cmd) => cmd.rpc_ipc()),* + } + } + + fn rpc_http(&self) -> $crate::Result<::std::option::Option<::std::net::SocketAddr>> { + match self { + $($enum::$variant(cmd) => cmd.rpc_http()),* + } + } + + fn rpc_ws(&self) -> $crate::Result<::std::option::Option<::std::net::SocketAddr>> { + match self { + $($enum::$variant(cmd) => cmd.rpc_ws()),* + } + } + + fn rpc_methods(&self) -> $crate::Result { + match self { + $($enum::$variant(cmd) => cmd.rpc_methods()),* + } + } + + fn rpc_ws_max_connections(&self) -> $crate::Result<::std::option::Option> { + match self { + $($enum::$variant(cmd) => cmd.rpc_ws_max_connections()),* + } + } + + fn rpc_cors(&self, is_dev: bool) + -> $crate::Result<::std::option::Option<::std::vec::Vec>> { + match self { + $($enum::$variant(cmd) => cmd.rpc_cors(is_dev)),* + } + } + + fn prometheus_config(&self) + -> $crate::Result<::std::option::Option<::sc_service::config::PrometheusConfig>> { + match self { + $($enum::$variant(cmd) => cmd.prometheus_config()),* + } + } + + fn telemetry_endpoints( + &self, + chain_spec: &Box, + ) -> $crate::Result<::std::option::Option<::sc_service::config::TelemetryEndpoints>> { + match self { + $($enum::$variant(cmd) => cmd.telemetry_endpoints(chain_spec)),* + } + } + + fn telemetry_external_transport(&self) + -> $crate::Result<::std::option::Option<::sc_service::config::ExtTransport>> { + match self { + $($enum::$variant(cmd) => cmd.telemetry_external_transport()),* + } + } + + fn default_heap_pages(&self) -> $crate::Result<::std::option::Option> { + match self { + $($enum::$variant(cmd) => cmd.default_heap_pages()),* + } + } + + fn offchain_worker( + &self, + role: &::sc_service::Role, + ) -> $crate::Result<::sc_service::config::OffchainWorkerConfig> { + match self { + $($enum::$variant(cmd) => cmd.offchain_worker(role)),* + } + } + + fn force_authoring(&self) -> $crate::Result { + match self { + $($enum::$variant(cmd) => cmd.force_authoring()),* + } + } + + fn disable_grandpa(&self) -> $crate::Result { + match self { + $($enum::$variant(cmd) => cmd.disable_grandpa()),* + } + } + + fn dev_key_seed(&self, is_dev: bool) -> $crate::Result<::std::option::Option> { + match self { + $($enum::$variant(cmd) => cmd.dev_key_seed(is_dev)),* + } + } + + fn tracing_targets(&self) -> $crate::Result<::std::option::Option> { + match self { + $($enum::$variant(cmd) => cmd.tracing_targets()),* + } + } + + fn tracing_receiver(&self) -> $crate::Result<::sc_service::TracingReceiver> { + match self { + $($enum::$variant(cmd) => cmd.tracing_receiver()),* + } + } + + fn node_key(&self, net_config_dir: &::std::path::PathBuf) + -> $crate::Result<::sc_service::config::NodeKeyConfig> { + match self { + $($enum::$variant(cmd) => cmd.node_key(net_config_dir)),* + } + } + + fn max_runtime_instances(&self) -> $crate::Result<::std::option::Option> { + match self { + $($enum::$variant(cmd) => cmd.max_runtime_instances()),* + } + } + + fn log_filters(&self) -> $crate::Result { + match self { + $($enum::$variant(cmd) => cmd.log_filters()),* + } + } + } } } + +substrate_cli_subcommands!( + Subcommand => BuildSpec, ExportBlocks, ImportBlocks, CheckBlock, Revert, PurgeChain, ExportState +); diff --git a/client/cli/src/commands/purge_chain_cmd.rs b/client/cli/src/commands/purge_chain_cmd.rs index e12a50bf24f174ccfcc868fa4099bdf11fb45292..9c9c6e91fb2416c56e8a6e9a3894a8a7aeb31c10 100644 --- a/client/cli/src/commands/purge_chain_cmd.rs +++ b/client/cli/src/commands/purge_chain_cmd.rs @@ -1,31 +1,32 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . +use crate::error; +use crate::params::{DatabaseParams, SharedParams}; +use crate::CliConfiguration; +use sc_service::DatabaseConfig; use std::fmt::Debug; -use std::io::{Write, self}; use std::fs; +use std::io::{self, Write}; use structopt::StructOpt; -use sc_service::{ Configuration, ChainSpec, config::{DatabaseConfig} }; - -use crate::error; -use crate::VersionInfo; -use crate::params::SharedParams; /// The `purge-chain` command used to remove the whole chain. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, StructOpt)] pub struct PurgeChainCmd { /// Skip interactive prompt by answering yes automatically. #[structopt(short = "y")] @@ -34,21 +35,19 @@ pub struct PurgeChainCmd { #[allow(missing_docs)] #[structopt(flatten)] pub shared_params: SharedParams, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub database_params: DatabaseParams, } impl PurgeChainCmd { /// Run the purge command - pub fn run( - self, - config: Configuration, - ) -> error::Result<()> { - let db_path = match config.expect_database() { - DatabaseConfig::Path { path, .. } => path, - _ => { - eprintln!("Cannot purge custom database implementation"); - return Ok(()); - } - }; + pub fn run(&self, database_config: DatabaseConfig) -> error::Result<()> { + let db_path = database_config.path() + .ok_or_else(|| + error::Error::Input("Cannot purge custom database implementation".into()) + )?; if !self.yes { print!("Are you sure to remove {:?}? [y/N]: ", &db_path); @@ -76,22 +75,17 @@ impl PurgeChainCmd { eprintln!("{:?} did not exist.", &db_path); Ok(()) }, - Err(err) => Result::Err(err.into()) + Err(err) => Result::Err(err.into()), } } +} - /// Update and prepare a `Configuration` with command line parameters - pub fn update_config( - &self, - mut config: &mut Configuration, - spec_factory: F, - version: &VersionInfo, - ) -> error::Result<()> where - F: FnOnce(&str) -> Result, String>, - { - self.shared_params.update_config(&mut config, spec_factory, version)?; - config.use_in_memory_keystore()?; +impl CliConfiguration for PurgeChainCmd { + fn shared_params(&self) -> &SharedParams { + &self.shared_params + } - Ok(()) + fn database_params(&self) -> Option<&DatabaseParams> { + Some(&self.database_params) } } diff --git a/client/cli/src/commands/revert_cmd.rs b/client/cli/src/commands/revert_cmd.rs index 9617f8eda40f3446a5f082a403a50da2d918ee5b..bbfb0d2ff99a73b20571a724181744d78c9edeb3 100644 --- a/client/cli/src/commands/revert_cmd.rs +++ b/client/cli/src/commands/revert_cmd.rs @@ -1,32 +1,34 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . +use crate::error; +use crate::params::{BlockNumber, PruningParams, SharedParams}; +use crate::CliConfiguration; +use sc_service::chain_ops::revert_chain; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; use std::fmt::Debug; +use std::str::FromStr; +use std::sync::Arc; use structopt::StructOpt; -use sc_service::{ - Configuration, ServiceBuilderCommand, ChainSpec, Role, -}; -use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; - -use crate::error; -use crate::VersionInfo; -use crate::params::{BlockNumber, SharedParams, PruningParams}; +use sc_client_api::{Backend, UsageProvider}; /// The `revert` command used revert the chain to a previous state. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, StructOpt)] pub struct RevertCmd { /// Number of blocks to revert. #[structopt(default_value = "256")] @@ -43,37 +45,30 @@ pub struct RevertCmd { impl RevertCmd { /// Run the revert command - pub fn run( - self, - config: Configuration, - builder: B, + pub async fn run( + &self, + client: Arc, + backend: Arc, ) -> error::Result<()> where - B: FnOnce(Configuration) -> Result, - BC: ServiceBuilderCommand + Unpin, - BB: sp_runtime::traits::Block + Debug, - <<::Header as HeaderT>::Number as std::str::FromStr>::Err: std::fmt::Debug, - ::Hash: std::str::FromStr, + B: BlockT, + BA: Backend, + C: UsageProvider, + <<::Header as HeaderT>::Number as FromStr>::Err: Debug, { let blocks = self.num.parse()?; - builder(config)?.revert_chain(blocks)?; + revert_chain(client, backend, blocks)?; Ok(()) } +} - /// Update and prepare a `Configuration` with command line parameters - pub fn update_config( - &self, - mut config: &mut Configuration, - spec_factory: F, - version: &VersionInfo, - ) -> error::Result<()> where - F: FnOnce(&str) -> Result, String>, - { - self.shared_params.update_config(&mut config, spec_factory, version)?; - self.pruning_params.update_config(&mut config, &Role::Full, true)?; - config.use_in_memory_keystore()?; +impl CliConfiguration for RevertCmd { + fn shared_params(&self) -> &SharedParams { + &self.shared_params + } - Ok(()) + fn pruning_params(&self) -> Option<&PruningParams> { + Some(&self.pruning_params) } } diff --git a/client/cli/src/commands/run_cmd.rs b/client/cli/src/commands/run_cmd.rs new file mode 100644 index 0000000000000000000000000000000000000000..de5589196f27fa0ecb6d2fa9b749f7e367f0cf66 --- /dev/null +++ b/client/cli/src/commands/run_cmd.rs @@ -0,0 +1,622 @@ +// This file is part of Substrate. + +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use crate::arg_enums::RpcMethods; +use crate::error::{Error, Result}; +use crate::params::ImportParams; +use crate::params::KeystoreParams; +use crate::params::NetworkParams; +use crate::params::OffchainWorkerParams; +use crate::params::SharedParams; +use crate::params::TransactionPoolParams; +use crate::CliConfiguration; +use regex::Regex; +use sc_service::{ + config::{BasePath, MultiaddrWithPeerId, PrometheusConfig, TransactionPoolOptions}, + ChainSpec, Role, +}; +use sc_telemetry::TelemetryEndpoints; +use std::net::{IpAddr, Ipv4Addr, SocketAddr}; +use structopt::StructOpt; + +/// The `run` command used to run a node. +#[derive(Debug, StructOpt)] +pub struct RunCmd { + /// 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, + + /// 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", "light" ], + parse(try_from_str) + )] + pub sentry: Vec, + + /// Disable GRANDPA voter when running in validator mode, otherwise disable the GRANDPA observer. + #[structopt(long)] + pub no_grandpa: bool, + + /// Experimental: Run in light client mode. + #[structopt(long = "light", conflicts_with = "sentry")] + pub light: bool, + + /// Listen to all RPC interfaces. + /// + /// Default is local. Note: not all RPC methods are safe to be exposed publicly. Use an RPC proxy + /// server to filter out dangerous methods. More details: https://github.com/paritytech/substrate/wiki/Public-RPC. + /// Use `--unsafe-rpc-external` to suppress the warning if you understand the risks. + #[structopt(long = "rpc-external")] + pub rpc_external: bool, + + /// Listen to all RPC interfaces. + /// + /// Same as `--rpc-external`. + #[structopt(long)] + pub unsafe_rpc_external: bool, + + /// RPC methods to expose. + /// + /// - `Unsafe`: Exposes every RPC method. + /// - `Safe`: Exposes only a safe subset of RPC methods, denying unsafe RPC methods. + /// - `Auto`: Acts as `Safe` if RPC is served externally, e.g. when `--{rpc,ws}-external` is passed, + /// otherwise acts as `Unsafe`. + #[structopt( + long, + value_name = "METHOD SET", + possible_values = &RpcMethods::variants(), + case_insensitive = true, + default_value = "Auto", + verbatim_doc_comment + )] + pub rpc_methods: RpcMethods, + + /// Listen to all Websocket interfaces. + /// + /// Default is local. Note: not all RPC methods are safe to be exposed publicly. Use an RPC proxy + /// server to filter out dangerous methods. More details: https://github.com/paritytech/substrate/wiki/Public-RPC. + /// Use `--unsafe-ws-external` to suppress the warning if you understand the risks. + #[structopt(long = "ws-external")] + pub ws_external: bool, + + /// Listen to all Websocket interfaces. + /// + /// Same as `--ws-external` but doesn't warn you about it. + #[structopt(long = "unsafe-ws-external")] + pub unsafe_ws_external: bool, + + /// Listen to all Prometheus data source interfaces. + /// + /// Default is local. + #[structopt(long = "prometheus-external")] + pub prometheus_external: bool, + + /// Specify IPC RPC server path + #[structopt(long = "ipc-path", value_name = "PATH")] + pub ipc_path: Option, + + /// Specify HTTP RPC server TCP port. + #[structopt(long = "rpc-port", value_name = "PORT")] + pub rpc_port: Option, + + /// Specify WebSockets RPC server TCP port. + #[structopt(long = "ws-port", value_name = "PORT")] + pub ws_port: Option, + + /// Maximum number of WS RPC server connections. + #[structopt(long = "ws-max-connections", value_name = "COUNT")] + pub ws_max_connections: Option, + + /// Specify browser Origins allowed to access the HTTP & WS RPC servers. + /// + /// A comma-separated list of origins (protocol://domain or special `null` + /// value). Value of `all` will disable origin validation. Default is to + /// allow localhost and https://polkadot.js.org 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 Prometheus data source server TCP Port. + #[structopt(long = "prometheus-port", value_name = "PORT")] + pub prometheus_port: Option, + + /// Do not expose a Prometheus metric endpoint. + /// + /// Prometheus metric endpoint is enabled by default. + #[structopt(long = "no-prometheus")] + pub no_prometheus: 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. + #[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 means to specify multiple + /// telemetry endpoints. Verbosity levels range from 0-9, with 0 denoting + /// the least verbosity. + /// Expected format is 'URL VERBOSITY', e.g. `--telemetry-url 'wss://foo/bar 0'`. + #[structopt(long = "telemetry-url", value_name = "URL VERBOSITY", parse(try_from_str = parse_telemetry_endpoints))] + pub telemetry_endpoints: Vec<(String, u8)>, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub offchain_worker_params: OffchainWorkerParams, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub shared_params: SharedParams, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub import_params: ImportParams, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub network_params: NetworkParams, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub pool_config: TransactionPoolParams, + + /// Shortcut for `--name Alice --validator` with session keys for `Alice` added to keystore. + #[structopt(long, conflicts_with_all = &["bob", "charlie", "dave", "eve", "ferdie", "one", "two"])] + pub alice: bool, + + /// Shortcut for `--name Bob --validator` with session keys for `Bob` added to keystore. + #[structopt(long, conflicts_with_all = &["alice", "charlie", "dave", "eve", "ferdie", "one", "two"])] + pub bob: bool, + + /// Shortcut for `--name Charlie --validator` with session keys for `Charlie` added to keystore. + #[structopt(long, conflicts_with_all = &["alice", "bob", "dave", "eve", "ferdie", "one", "two"])] + pub charlie: bool, + + /// Shortcut for `--name Dave --validator` with session keys for `Dave` added to keystore. + #[structopt(long, conflicts_with_all = &["alice", "bob", "charlie", "eve", "ferdie", "one", "two"])] + pub dave: bool, + + /// Shortcut for `--name Eve --validator` with session keys for `Eve` added to keystore. + #[structopt(long, conflicts_with_all = &["alice", "bob", "charlie", "dave", "ferdie", "one", "two"])] + pub eve: bool, + + /// Shortcut for `--name Ferdie --validator` with session keys for `Ferdie` added to keystore. + #[structopt(long, conflicts_with_all = &["alice", "bob", "charlie", "dave", "eve", "one", "two"])] + pub ferdie: bool, + + /// Shortcut for `--name One --validator` with session keys for `One` added to keystore. + #[structopt(long, conflicts_with_all = &["alice", "bob", "charlie", "dave", "eve", "ferdie", "two"])] + pub one: bool, + + /// Shortcut for `--name Two --validator` with session keys for `Two` added to keystore. + #[structopt(long, conflicts_with_all = &["alice", "bob", "charlie", "dave", "eve", "ferdie", "one"])] + pub two: bool, + + /// Enable authoring even when offline. + #[structopt(long = "force-authoring")] + pub force_authoring: bool, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub keystore_params: KeystoreParams, + + /// The size of the instances cache for each runtime. + /// + /// The default value is 8 and the values higher than 256 are ignored. + #[structopt(long)] + pub max_runtime_instances: Option, + + /// Specify a list of sentry node public addresses. + /// + /// Can't be used with --public-addr as the sentry node would take precedence over the public address + /// specified there. + #[structopt( + long = "sentry-nodes", + value_name = "ADDR", + conflicts_with_all = &[ "sentry", "public-addr" ] + )] + pub sentry_nodes: Vec, + + /// Run a temporary node. + /// + /// A temporary directory will be created to store the configuration and will be deleted + /// at the end of the process. + /// + /// Note: the directory is random per process execution. This directory is used as base path + /// which includes: database, node key and keystore. + #[structopt(long, conflicts_with = "base-path")] + pub tmp: bool, +} + +impl RunCmd { + /// Get the `Sr25519Keyring` matching one of the flag. + pub fn get_keyring(&self) -> Option { + use sp_keyring::Sr25519Keyring::*; + + if self.alice { + Some(Alice) + } else if self.bob { + Some(Bob) + } else if self.charlie { + Some(Charlie) + } else if self.dave { + Some(Dave) + } else if self.eve { + Some(Eve) + } else if self.ferdie { + Some(Ferdie) + } else if self.one { + Some(One) + } else if self.two { + Some(Two) + } else { + None + } + } +} + +impl CliConfiguration for RunCmd { + fn shared_params(&self) -> &SharedParams { + &self.shared_params + } + + fn import_params(&self) -> Option<&ImportParams> { + Some(&self.import_params) + } + + fn network_params(&self) -> Option<&NetworkParams> { + Some(&self.network_params) + } + + fn keystore_params(&self) -> Option<&KeystoreParams> { + Some(&self.keystore_params) + } + + fn offchain_worker_params(&self) -> Option<&OffchainWorkerParams> { + Some(&self.offchain_worker_params) + } + + fn node_name(&self) -> Result { + let name: String = match (self.name.as_ref(), self.get_keyring()) { + (Some(name), _) => name.to_string(), + (_, Some(keyring)) => keyring.to_string(), + (None, None) => crate::generate_node_name(), + }; + + is_node_name_valid(&name).map_err(|msg| { + Error::Input(format!( + "Invalid node name '{}'. Reason: {}. If unsure, use none.", + name, msg + )) + })?; + + Ok(name) + } + + fn dev_key_seed(&self, is_dev: bool) -> Result> { + Ok(self.get_keyring().map(|a| format!("//{}", a)).or_else(|| { + if is_dev && !self.light { + Some("//Alice".into()) + } else { + None + } + })) + } + + fn telemetry_endpoints( + &self, + chain_spec: &Box, + ) -> Result> { + Ok(if self.no_telemetry { + None + } else if !self.telemetry_endpoints.is_empty() { + Some( + TelemetryEndpoints::new(self.telemetry_endpoints.clone()) + .map_err(|e| e.to_string())?, + ) + } else { + chain_spec.telemetry_endpoints().clone() + }) + } + + fn role(&self, is_dev: bool) -> Result { + let keyring = self.get_keyring(); + let is_light = self.light; + let is_authority = (self.validator || is_dev || keyring.is_some()) && !is_light; + + Ok(if is_light { + sc_service::Role::Light + } else if is_authority { + sc_service::Role::Authority { + sentry_nodes: self.sentry_nodes.clone(), + } + } else if !self.sentry.is_empty() { + sc_service::Role::Sentry { + validators: self.sentry.clone(), + } + } else { + sc_service::Role::Full + }) + } + + fn force_authoring(&self) -> Result { + // Imply forced authoring on --dev + Ok(self.shared_params.dev || self.force_authoring) + } + + fn prometheus_config(&self) -> Result> { + Ok(if self.no_prometheus { + None + } else { + let interface = if self.prometheus_external { + Ipv4Addr::UNSPECIFIED + } else { + Ipv4Addr::LOCALHOST + }; + + Some(PrometheusConfig::new_with_default_registry( + SocketAddr::new(interface.into(), self.prometheus_port.unwrap_or(9615)) + )) + }) + } + + fn disable_grandpa(&self) -> Result { + Ok(self.no_grandpa) + } + + fn rpc_ws_max_connections(&self) -> Result> { + Ok(self.ws_max_connections) + } + + fn rpc_cors(&self, is_dev: bool) -> Result>> { + Ok(self + .rpc_cors + .clone() + .unwrap_or_else(|| { + if is_dev { + log::warn!("Running in --dev mode, RPC CORS has been disabled."); + Cors::All + } else { + Cors::List(vec![ + "http://localhost:*".into(), + "http://127.0.0.1:*".into(), + "https://localhost:*".into(), + "https://127.0.0.1:*".into(), + "https://polkadot.js.org".into(), + ]) + } + }) + .into()) + } + + fn rpc_http(&self) -> Result> { + let interface = rpc_interface( + self.rpc_external, + self.unsafe_rpc_external, + self.rpc_methods, + self.validator + )?; + + Ok(Some(SocketAddr::new(interface, self.rpc_port.unwrap_or(9933)))) + } + + fn rpc_ipc(&self) -> Result> { + Ok(self.ipc_path.clone()) + } + + fn rpc_ws(&self) -> Result> { + let interface = rpc_interface( + self.ws_external, + self.unsafe_ws_external, + self.rpc_methods, + self.validator + )?; + + Ok(Some(SocketAddr::new(interface, self.ws_port.unwrap_or(9944)))) + } + + fn rpc_methods(&self) -> Result { + Ok(self.rpc_methods.into()) + } + + fn transaction_pool(&self) -> Result { + Ok(self.pool_config.transaction_pool()) + } + + fn max_runtime_instances(&self) -> Result> { + Ok(self.max_runtime_instances.map(|x| x.min(256))) + } + + fn base_path(&self) -> Result> { + Ok(if self.tmp { + Some(BasePath::new_temp_dir()?) + } else { + self.shared_params().base_path() + }) + } +} + +/// Check whether a node name is considered as valid. +pub fn is_node_name_valid(_name: &str) -> std::result::Result<(), &str> { + let name = _name.to_string(); + if name.chars().count() >= crate::NODE_NAME_MAX_LENGTH { + return Err("Node name too long"); + } + + let invalid_chars = r"[\\.@]"; + let re = Regex::new(invalid_chars).unwrap(); + if re.is_match(&name) { + return Err("Node name should not contain invalid chars such as '.' and '@'"); + } + + let invalid_patterns = r"(https?:\\/+)?(www)+"; + let re = Regex::new(invalid_patterns).unwrap(); + if re.is_match(&name) { + return Err("Node name should not contain urls"); + } + + Ok(()) +} + +fn rpc_interface( + is_external: bool, + is_unsafe_external: bool, + rpc_methods: RpcMethods, + is_validator: bool, +) -> Result { + if is_external && is_validator && rpc_methods != RpcMethods::Unsafe { + return Err(Error::Input( + "--rpc-external and --ws-external options shouldn't be \ + used if the node is running as a validator. Use `--unsafe-rpc-external` \ + or `--rpc-methods=unsafe` if you understand the risks. See the options \ + description for more information." + .to_owned(), + )); + } + + if is_external || is_unsafe_external { + if rpc_methods == RpcMethods::Unsafe { + log::warn!( + "It isn't safe to expose RPC publicly without a proxy server that filters \ + available set of RPC methods." + ); + } + + Ok(Ipv4Addr::UNSPECIFIED.into()) + } else { + Ok(Ipv4Addr::LOCALHOST.into()) + } +} + +#[derive(Debug)] +enum TelemetryParsingError { + MissingVerbosity, + VerbosityParsingError(std::num::ParseIntError), +} + +impl std::error::Error for TelemetryParsingError {} + +impl std::fmt::Display for TelemetryParsingError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match &*self { + TelemetryParsingError::MissingVerbosity => write!(f, "Verbosity level missing"), + TelemetryParsingError::VerbosityParsingError(e) => write!(f, "{}", e), + } + } +} + +fn parse_telemetry_endpoints(s: &str) -> std::result::Result<(String, u8), TelemetryParsingError> { + let pos = s.find(' '); + match pos { + None => Err(TelemetryParsingError::MissingVerbosity), + Some(pos_) => { + let url = s[..pos_].to_string(); + let verbosity = s[pos_ + 1..] + .parse() + .map_err(TelemetryParsingError::VerbosityParsingError)?; + Ok((url, verbosity)) + } + } +} + +/// CORS setting +/// +/// The type is introduced to overcome `Option>` +/// handling of `structopt`. +#[derive(Clone, Debug)] +pub enum Cors { + /// All hosts allowed. + All, + /// Only hosts on the list are allowed. + List(Vec), +} + +impl From for Option> { + fn from(cors: Cors) -> Self { + match cors { + Cors::All => None, + Cors::List(list) => Some(list), + } + } +} + +/// Parse cors origins. +fn parse_cors(s: &str) -> std::result::Result> { + let mut is_all = false; + let mut origins = Vec::new(); + for part in s.split(',') { + match part { + "all" | "*" => { + is_all = true; + break; + } + other => origins.push(other.to_owned()), + } + } + + Ok(if is_all { + Cors::All + } else { + Cors::List(origins) + }) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn tests_node_name_good() { + assert!(is_node_name_valid("short name").is_ok()); + } + + #[test] + fn tests_node_name_bad() { + assert!(is_node_name_valid( + "very very long names are really not very cool for the ui at all, really they're not" + ).is_err()); + assert!(is_node_name_valid("Dots.not.Ok").is_err()); + assert!(is_node_name_valid("http://visit.me").is_err()); + assert!(is_node_name_valid("https://visit.me").is_err()); + assert!(is_node_name_valid("www.visit.me").is_err()); + assert!(is_node_name_valid("email@domain").is_err()); + } +} diff --git a/client/cli/src/commands/runcmd.rs b/client/cli/src/commands/runcmd.rs deleted file mode 100644 index bdc57a38c3d15130a8a45fe610de6c009af96e47..0000000000000000000000000000000000000000 --- a/client/cli/src/commands/runcmd.rs +++ /dev/null @@ -1,741 +0,0 @@ -// Copyright 2018-2020 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::path::PathBuf; -use std::net::SocketAddr; -use std::fs; -use log::info; -use structopt::{StructOpt, clap::arg_enum}; -use names::{Generator, Name}; -use regex::Regex; -use chrono::prelude::*; -use sc_service::{ - AbstractService, Configuration, ChainSpec, Role, - config::{MultiaddrWithPeerId, KeystoreConfig, PrometheusConfig}, -}; -use sc_telemetry::TelemetryEndpoints; - -use crate::VersionInfo; -use crate::error; -use crate::params::ImportParams; -use crate::params::SharedParams; -use crate::params::NetworkConfigurationParams; -use crate::params::TransactionPoolParams; -use crate::runtime::run_service_until_exit; - -/// The maximum number of characters for a node name. -const NODE_NAME_MAX_LENGTH: usize = 32; - -/// default sub directory for the key store -const DEFAULT_KEYSTORE_CONFIG_PATH : &'static str = "keystore"; - -arg_enum! { - /// Whether off-chain workers are enabled. - #[allow(missing_docs)] - #[derive(Debug, Clone)] - pub enum OffchainWorkerEnabled { - Always, - Never, - WhenValidating, - } -} - -/// The `run` command used to run a node. -#[derive(Debug, StructOpt, Clone)] -pub struct RunCmd { - /// 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, - - /// 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", "light" ], - parse(try_from_str) - )] - pub sentry: Vec, - - /// Disable GRANDPA voter when running in validator mode, otherwise disable the GRANDPA observer. - #[structopt(long = "no-grandpa")] - pub no_grandpa: bool, - - /// Experimental: Run in light client mode. - #[structopt(long = "light", conflicts_with = "sentry")] - pub light: bool, - - /// Listen to all RPC interfaces. - /// - /// Default is local. Note: not all RPC methods are safe to be exposed publicly. Use an RPC proxy - /// server to filter out dangerous methods. More details: https://github.com/paritytech/substrate/wiki/Public-RPC. - /// Use `--unsafe-rpc-external` to suppress the warning if you understand the risks. - #[structopt(long = "rpc-external")] - pub rpc_external: bool, - - /// Listen to all RPC interfaces. - /// - /// Same as `--rpc-external`. - #[structopt(long = "unsafe-rpc-external")] - pub unsafe_rpc_external: bool, - - /// Listen to all Websocket interfaces. - /// - /// Default is local. Note: not all RPC methods are safe to be exposed publicly. Use an RPC proxy - /// server to filter out dangerous methods. More details: https://github.com/paritytech/substrate/wiki/Public-RPC. - /// Use `--unsafe-ws-external` to suppress the warning if you understand the risks. - #[structopt(long = "ws-external")] - pub ws_external: bool, - - /// Listen to all Websocket interfaces. - /// - /// Same as `--ws-external` but doesn't warn you about it. - #[structopt(long = "unsafe-ws-external")] - pub unsafe_ws_external: bool, - - /// Listen to all Prometheus data source interfaces. - /// - /// Default is local. - #[structopt(long = "prometheus-external")] - pub prometheus_external: bool, - - /// Specify HTTP RPC server TCP port. - #[structopt(long = "rpc-port", value_name = "PORT")] - pub rpc_port: Option, - - /// Specify WebSockets RPC server TCP port. - #[structopt(long = "ws-port", value_name = "PORT")] - pub ws_port: Option, - - /// Maximum number of WS RPC server connections. - #[structopt(long = "ws-max-connections", value_name = "COUNT")] - pub ws_max_connections: Option, - - /// Specify browser Origins allowed to access the HTTP & WS RPC servers. - /// - /// A comma-separated list of origins (protocol://domain or special `null` - /// value). Value of `all` will disable origin validation. Default is to - /// allow localhost and https://polkadot.js.org 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 Prometheus data source server TCP Port. - #[structopt(long = "prometheus-port", value_name = "PORT")] - pub prometheus_port: Option, - - /// Do not expose a Prometheus metric endpoint. - /// - /// Prometheus metric endpoint is enabled by default. - #[structopt(long = "no-prometheus")] - pub no_prometheus: 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. - #[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 means 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. - #[structopt( - long = "offchain-worker", - value_name = "ENABLED", - possible_values = &OffchainWorkerEnabled::variants(), - case_insensitive = true, - default_value = "WhenValidating" - )] - pub offchain_worker: OffchainWorkerEnabled, - - #[allow(missing_docs)] - #[structopt(flatten)] - pub shared_params: SharedParams, - - #[allow(missing_docs)] - #[structopt(flatten)] - pub import_params: ImportParams, - - #[allow(missing_docs)] - #[structopt(flatten)] - pub network_config: NetworkConfigurationParams, - - #[allow(missing_docs)] - #[structopt(flatten)] - pub pool_config: TransactionPoolParams, - - /// Shortcut for `--name Alice --validator` with session keys for `Alice` added to keystore. - #[structopt(long, conflicts_with_all = &["bob", "charlie", "dave", "eve", "ferdie", "one", "two"])] - pub alice: bool, - - /// Shortcut for `--name Bob --validator` with session keys for `Bob` added to keystore. - #[structopt(long, conflicts_with_all = &["alice", "charlie", "dave", "eve", "ferdie", "one", "two"])] - pub bob: bool, - - /// Shortcut for `--name Charlie --validator` with session keys for `Charlie` added to keystore. - #[structopt(long, conflicts_with_all = &["alice", "bob", "dave", "eve", "ferdie", "one", "two"])] - pub charlie: bool, - - /// Shortcut for `--name Dave --validator` with session keys for `Dave` added to keystore. - #[structopt(long, conflicts_with_all = &["alice", "bob", "charlie", "eve", "ferdie", "one", "two"])] - pub dave: bool, - - /// Shortcut for `--name Eve --validator` with session keys for `Eve` added to keystore. - #[structopt(long, conflicts_with_all = &["alice", "bob", "charlie", "dave", "ferdie", "one", "two"])] - pub eve: bool, - - /// Shortcut for `--name Ferdie --validator` with session keys for `Ferdie` added to keystore. - #[structopt(long, conflicts_with_all = &["alice", "bob", "charlie", "dave", "eve", "one", "two"])] - pub ferdie: bool, - - /// Shortcut for `--name One --validator` with session keys for `One` added to keystore. - #[structopt(long, conflicts_with_all = &["alice", "bob", "charlie", "dave", "eve", "ferdie", "two"])] - pub one: bool, - - /// Shortcut for `--name Two --validator` with session keys for `Two` added to keystore. - #[structopt(long, conflicts_with_all = &["alice", "bob", "charlie", "dave", "eve", "ferdie", "one"])] - pub two: bool, - - /// Enable authoring even when offline. - #[structopt(long = "force-authoring")] - pub force_authoring: bool, - - /// Specify custom keystore path. - #[structopt(long = "keystore-path", value_name = "PATH", parse(from_os_str))] - pub keystore_path: Option, - - /// Use interactive shell for entering the password used by the keystore. - #[structopt( - long = "password-interactive", - conflicts_with_all = &[ "password", "password-filename" ] - )] - pub password_interactive: bool, - - /// Password used by the keystore. - #[structopt( - long = "password", - conflicts_with_all = &[ "password-interactive", "password-filename" ] - )] - pub password: Option, - - /// File that contains the password used by the keystore. - #[structopt( - long = "password-filename", - value_name = "PATH", - parse(from_os_str), - conflicts_with_all = &[ "password-interactive", "password" ] - )] - pub password_filename: Option, - - /// The size of the instances cache for each runtime. - /// - /// The default value is 8 and the values higher than 256 are ignored. - #[structopt(long = "max-runtime-instances", default_value = "8")] - pub max_runtime_instances: usize, -} - -impl RunCmd { - /// Get the `Sr25519Keyring` matching one of the flag. - pub fn get_keyring(&self) -> Option { - use sp_keyring::Sr25519Keyring::*; - - if self.alice { Some(Alice) } - else if self.bob { Some(Bob) } - else if self.charlie { Some(Charlie) } - else if self.dave { Some(Dave) } - else if self.eve { Some(Eve) } - else if self.ferdie { Some(Ferdie) } - else if self.one { Some(One) } - else if self.two { Some(Two) } - else { None } - } - - /// Update and prepare a `Configuration` with command line parameters of `RunCmd` and `VersionInfo`. - pub fn update_config( - &self, - mut config: &mut Configuration, - spec_factory: F, - version: &VersionInfo, - ) -> error::Result<()> - where - F: FnOnce(&str) -> Result, String>, - { - self.shared_params.update_config(&mut config, spec_factory, version)?; - - let password = if self.password_interactive { - #[cfg(not(target_os = "unknown"))] - { - Some(input_keystore_password()?.into()) - } - #[cfg(target_os = "unknown")] - None - } else if let Some(ref file) = self.password_filename { - Some(fs::read_to_string(file).map_err(|e| format!("{}", e))?.into()) - } else if let Some(ref password) = self.password { - Some(password.clone().into()) - } else { - None - }; - - let path = self.keystore_path.clone().or( - config.in_chain_config_dir(DEFAULT_KEYSTORE_CONFIG_PATH) - ); - - config.keystore = KeystoreConfig::Path { - path: path.ok_or_else(|| "No `base_path` provided to create keystore path!".to_string())?, - password, - }; - - let keyring = self.get_keyring(); - let is_dev = self.shared_params.dev; - let is_light = self.light; - let is_authority = (self.validator || is_dev || keyring.is_some()) - && !is_light; - let role = - if is_light { - sc_service::Role::Light - } else if is_authority { - sc_service::Role::Authority { sentry_nodes: self.network_config.sentry_nodes.clone() } - } else if !self.sentry.is_empty() { - sc_service::Role::Sentry { validators: self.sentry.clone() } - } else { - sc_service::Role::Full - }; - - self.import_params.update_config(&mut config, &role, is_dev)?; - - config.name = match (self.name.as_ref(), keyring) { - (Some(name), _) => name.to_string(), - (_, Some(keyring)) => keyring.to_string(), - (None, None) => generate_node_name(), - }; - if let Err(msg) = is_node_name_valid(&config.name) { - return Err(error::Error::Input( - format!("Invalid node name '{}'. Reason: {}. If unsure, use none.", - config.name, - msg, - ) - )); - } - - config.offchain_worker = match (&self.offchain_worker, &role) { - (OffchainWorkerEnabled::WhenValidating, sc_service::Role::Authority { .. }) => true, - (OffchainWorkerEnabled::Always, _) => true, - (OffchainWorkerEnabled::Never, _) => false, - (OffchainWorkerEnabled::WhenValidating, _) => false, - }; - - config.role = role; - config.disable_grandpa = self.no_grandpa; - - let client_id = config.client_id(); - let network_path = config - .in_chain_config_dir(crate::commands::DEFAULT_NETWORK_CONFIG_PATH) - .expect("We provided a basepath"); - self.network_config.update_config( - &mut config, - network_path, - client_id, - is_dev, - )?; - - self.pool_config.update_config(&mut config)?; - - config.dev_key_seed = keyring - .map(|a| format!("//{}", a)).or_else(|| { - if is_dev && !is_light { - Some("//Alice".into()) - } else { - None - } - }); - - if config.rpc_http.is_none() || self.rpc_port.is_some() { - let rpc_interface: &str = interface_str(self.rpc_external, self.unsafe_rpc_external, self.validator)?; - config.rpc_http = Some(parse_address(&format!("{}:{}", rpc_interface, 9933), self.rpc_port)?); - } - if config.rpc_ws.is_none() || self.ws_port.is_some() { - let ws_interface: &str = interface_str(self.ws_external, self.unsafe_ws_external, self.validator)?; - config.rpc_ws = Some(parse_address(&format!("{}:{}", ws_interface, 9944), self.ws_port)?); - } - - config.rpc_ws_max_connections = self.ws_max_connections; - config.rpc_cors = self.rpc_cors.clone().unwrap_or_else(|| if is_dev { - log::warn!("Running in --dev mode, RPC CORS has been disabled."); - Cors::All - } else { - Cors::List(vec![ - "http://localhost:*".into(), - "http://127.0.0.1:*".into(), - "https://localhost:*".into(), - "https://127.0.0.1:*".into(), - "https://polkadot.js.org".into(), - ]) - }).into(); - - // Override telemetry - if self.no_telemetry { - config.telemetry_endpoints = None; - } else if !self.telemetry_endpoints.is_empty() { - config.telemetry_endpoints = Some( - TelemetryEndpoints::new(self.telemetry_endpoints.clone()).map_err(|e| e.to_string())? - ); - } - - // Override prometheus - if self.no_prometheus { - config.prometheus_config = None; - } else if config.prometheus_config.is_none() { - let prometheus_interface: &str = if self.prometheus_external { "0.0.0.0" } else { "127.0.0.1" }; - config.prometheus_config = Some(PrometheusConfig::new_with_default_registry( - parse_address(&format!("{}:{}", prometheus_interface, 9615), self.prometheus_port)?, - )); - } - - config.tracing_targets = self.import_params.tracing_targets.clone().into(); - config.tracing_receiver = self.import_params.tracing_receiver.clone().into(); - - // Imply forced authoring on --dev - config.force_authoring = self.shared_params.dev || self.force_authoring; - - config.max_runtime_instances = self.max_runtime_instances.min(256); - - Ok(()) - } - - /// Run the command that runs the node. - pub fn run( - self, - config: Configuration, - new_light: FNL, - new_full: FNF, - version: &VersionInfo, - ) -> error::Result<()> - where - FNL: FnOnce(Configuration) -> Result, - FNF: FnOnce(Configuration) -> Result, - SL: AbstractService + Unpin, - SF: AbstractService + Unpin, - { - info!("{}", version.name); - info!("✌️ version {}", config.full_version()); - info!("❤️ by {}, {}-{}", version.author, version.copyright_start_year, Local::today().year()); - info!("📋 Chain specification: {}", config.expect_chain_spec().name()); - info!("🏷 Node name: {}", config.name); - info!("👤 Role: {}", config.display_role()); - - match config.role { - Role::Light => run_service_until_exit( - config, - new_light, - ), - _ => run_service_until_exit( - config, - new_full, - ), - } - } - - /// Initialize substrate. This must be done only once. - /// - /// This method: - /// - /// 1. Set the panic handler - /// 2. Raise the FD limit - /// 3. Initialize the logger - pub fn init(&self, version: &VersionInfo) -> error::Result<()> { - self.shared_params.init(version) - } -} - -/// Check whether a node name is considered as valid. -pub fn is_node_name_valid(_name: &str) -> Result<(), &str> { - let name = _name.to_string(); - if name.chars().count() >= NODE_NAME_MAX_LENGTH { - return Err("Node name too long"); - } - - let invalid_chars = r"[\\.@]"; - let re = Regex::new(invalid_chars).unwrap(); - if re.is_match(&name) { - return Err("Node name should not contain invalid chars such as '.' and '@'"); - } - - let invalid_patterns = r"(https?:\\/+)?(www)+"; - let re = Regex::new(invalid_patterns).unwrap(); - if re.is_match(&name) { - return Err("Node name should not contain urls"); - } - - Ok(()) -} - -#[cfg(not(target_os = "unknown"))] -fn input_keystore_password() -> Result { - rpassword::read_password_from_tty(Some("Keystore password: ")) - .map_err(|e| format!("{:?}", e)) -} - -fn generate_node_name() -> String { - let result = loop { - let node_name = Generator::with_naming(Name::Numbered).next().unwrap(); - let count = node_name.chars().count(); - - if count < NODE_NAME_MAX_LENGTH { - break node_name - } - }; - - result -} - -fn parse_address( - address: &str, - port: Option, -) -> Result { - let mut address: SocketAddr = address.parse().map_err( - |_| format!("Invalid address: {}", address) - )?; - if let Some(port) = port { - address.set_port(port); - } - - Ok(address) -} - -fn interface_str( - is_external: bool, - is_unsafe_external: bool, - is_validator: bool, -) -> Result<&'static str, error::Error> { - if is_external && is_validator { - return Err(error::Error::Input("--rpc-external and --ws-external options shouldn't be \ - used if the node is running as a validator. Use `--unsafe-rpc-external` if you understand \ - the risks. See the options description for more information.".to_owned())); - } - - if is_external || is_unsafe_external { - log::warn!("It isn't safe to expose RPC publicly without a proxy server that filters \ - available set of RPC methods."); - - Ok("0.0.0.0") - } else { - Ok("127.0.0.1") - } -} - -/// Default to verbosity level 0, if none is provided. -fn parse_telemetry_endpoints(s: &str) -> Result<(String, u8), Box> { - let pos = s.find(' '); - match pos { - None => { - Ok((s.to_owned(), 0)) - }, - Some(pos_) => { - let verbosity = s[pos_ + 1..].parse()?; - let url = s[..pos_].parse()?; - Ok((url, verbosity)) - } - } -} - -/// CORS setting -/// -/// The type is introduced to overcome `Option>` -/// handling of `structopt`. -#[derive(Clone, Debug)] -pub enum Cors { - /// All hosts allowed. - All, - /// Only hosts on the list are allowed. - List(Vec), -} - -impl From for Option> { - fn from(cors: Cors) -> Self { - match cors { - Cors::All => None, - Cors::List(list) => Some(list), - } - } -} - -/// Parse cors origins. -fn parse_cors(s: &str) -> Result> { - let mut is_all = false; - let mut origins = Vec::new(); - for part in s.split(',') { - match part { - "all" | "*" => { - is_all = true; - break; - }, - other => origins.push(other.to_owned()), - } - } - - Ok(if is_all { Cors::All } else { Cors::List(origins) }) -} - -#[cfg(test)] -mod tests { - use super::*; - use sc_service::{GenericChainSpec, config::DatabaseConfig}; - - const TEST_VERSION_INFO: &'static VersionInfo = &VersionInfo { - name: "node-test", - version: "0.1.0", - commit: "some_commit", - executable_name: "node-test", - description: "description", - author: "author", - support_url: "http://example.org", - copyright_start_year: 2020, - }; - - #[test] - fn tests_node_name_good() { - assert!(is_node_name_valid("short name").is_ok()); - } - - #[test] - fn tests_node_name_bad() { - assert!(is_node_name_valid("long names are not very cool for the ui").is_err()); - assert!(is_node_name_valid("Dots.not.Ok").is_err()); - assert!(is_node_name_valid("http://visit.me").is_err()); - assert!(is_node_name_valid("https://visit.me").is_err()); - assert!(is_node_name_valid("www.visit.me").is_err()); - assert!(is_node_name_valid("email@domain").is_err()); - } - - #[test] - fn keystore_path_is_generated_correctly() { - let chain_spec = GenericChainSpec::from_genesis( - "test", - "test-id", - || (), - Vec::new(), - None, - None, - None, - None::<()>, - ); - - for keystore_path in vec![None, Some("/keystore/path")] { - let args: Vec<&str> = vec![]; - let mut cli = RunCmd::from_iter(args); - cli.keystore_path = keystore_path.clone().map(PathBuf::from); - - let mut config = Configuration::default(); - config.config_dir = Some(PathBuf::from("/test/path")); - config.chain_spec = Some(Box::new(chain_spec.clone())); - let chain_spec = chain_spec.clone(); - cli.update_config(&mut config, move |_| Ok(Box::new(chain_spec)), TEST_VERSION_INFO).unwrap(); - - let expected_path = match keystore_path { - Some(path) => PathBuf::from(path), - None => PathBuf::from("/test/path/chains/test-id/keystore"), - }; - - assert_eq!(expected_path, config.keystore.path().unwrap().to_owned()); - } - } - - #[test] - fn ensure_load_spec_provide_defaults() { - let chain_spec = GenericChainSpec::from_genesis( - "test", - "test-id", - || (), - vec!["/ip4/127.0.0.1/tcp/30333/p2p/QmdSHZLmwEL5Axz5JvWNE2mmxU7qyd7xHBFpyUfktgAdg7".parse().unwrap()], - Some(TelemetryEndpoints::new(vec![("wss://foo/bar".to_string(), 42)]) - .expect("provided url should be valid")), - None, - None, - None::<()>, - ); - - let args: Vec<&str> = vec![]; - let cli = RunCmd::from_iter(args); - - let mut config = Configuration::from_version(TEST_VERSION_INFO); - cli.update_config(&mut config, |_| Ok(Box::new(chain_spec)), TEST_VERSION_INFO).unwrap(); - - assert!(config.chain_spec.is_some()); - assert!(!config.network.boot_nodes.is_empty()); - assert!(config.telemetry_endpoints.is_some()); - } - - #[test] - fn ensure_update_config_for_running_node_provides_defaults() { - let chain_spec = GenericChainSpec::from_genesis( - "test", - "test-id", - || (), - vec![], - None, - None, - None, - None::<()>, - ); - - let args: Vec<&str> = vec![]; - let cli = RunCmd::from_iter(args); - - let mut config = Configuration::from_version(TEST_VERSION_INFO); - cli.init(&TEST_VERSION_INFO).unwrap(); - cli.update_config(&mut config, |_| Ok(Box::new(chain_spec)), TEST_VERSION_INFO).unwrap(); - - assert!(config.config_dir.is_some()); - assert!(config.database.is_some()); - if let Some(DatabaseConfig::Path { ref cache_size, .. }) = config.database { - assert!(cache_size.is_some()); - } else { - panic!("invalid config.database variant"); - } - assert!(!config.name.is_empty()); - assert!(config.network.config_path.is_some()); - assert!(!config.network.listen_addresses.is_empty()); - } -} diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs new file mode 100644 index 0000000000000000000000000000000000000000..fa3f09116c3142c780684e377276063c859bf8e5 --- /dev/null +++ b/client/cli/src/config.rs @@ -0,0 +1,522 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Configuration trait for a CLI based on substrate + +use crate::arg_enums::Database; +use crate::error::Result; +use crate::{ + init_logger, DatabaseParams, ImportParams, KeystoreParams, NetworkParams, NodeKeyParams, + OffchainWorkerParams, PruningParams, SharedParams, SubstrateCli, +}; +use names::{Generator, Name}; +use sc_client_api::execution_extensions::ExecutionStrategies; +use sc_service::config::{ + BasePath, Configuration, DatabaseConfig, ExtTransport, KeystoreConfig, NetworkConfiguration, + NodeKeyConfig, OffchainWorkerConfig, PrometheusConfig, PruningMode, Role, RpcMethods, + TaskExecutor, TelemetryEndpoints, TransactionPoolOptions, WasmExecutionMethod, +}; +use sc_service::{ChainSpec, TracingReceiver}; +use std::net::SocketAddr; +use std::path::PathBuf; + +/// The maximum number of characters for a node name. +pub(crate) const NODE_NAME_MAX_LENGTH: usize = 64; + +/// default sub directory to store network config +pub(crate) const DEFAULT_NETWORK_CONFIG_PATH: &'static str = "network"; + +/// A trait that allows converting an object to a Configuration +pub trait CliConfiguration: Sized { + /// Get the SharedParams for this object + fn shared_params(&self) -> &SharedParams; + + /// Get the ImportParams for this object + fn import_params(&self) -> Option<&ImportParams> { + None + } + + /// Get the PruningParams for this object + fn pruning_params(&self) -> Option<&PruningParams> { + self.import_params().map(|x| &x.pruning_params) + } + + /// Get the KeystoreParams for this object + fn keystore_params(&self) -> Option<&KeystoreParams> { + None + } + + /// Get the NetworkParams for this object + fn network_params(&self) -> Option<&NetworkParams> { + None + } + + /// Get a reference to `OffchainWorkerParams` for this object. + fn offchain_worker_params(&self) -> Option<&OffchainWorkerParams> { + None + } + + /// Get the NodeKeyParams for this object + fn node_key_params(&self) -> Option<&NodeKeyParams> { + self.network_params().map(|x| &x.node_key_params) + } + + /// Get the DatabaseParams for this object + fn database_params(&self) -> Option<&DatabaseParams> { + self.import_params().map(|x| &x.database_params) + } + + /// Get the base path of the configuration (if any) + /// + /// By default this is retrieved from `SharedParams`. + fn base_path(&self) -> Result> { + Ok(self.shared_params().base_path()) + } + + /// Returns `true` if the node is for development or not + /// + /// By default this is retrieved from `SharedParams`. + fn is_dev(&self) -> Result { + Ok(self.shared_params().is_dev()) + } + + /// Gets the role + /// + /// By default this is `Role::Full`. + fn role(&self, _is_dev: bool) -> Result { + Ok(Role::Full) + } + + /// Get the transaction pool options + /// + /// By default this is `TransactionPoolOptions::default()`. + fn transaction_pool(&self) -> Result { + Ok(Default::default()) + } + + /// Get the network configuration + /// + /// By default this is retrieved from `NetworkParams` if it is available otherwise it creates + /// a default `NetworkConfiguration` based on `node_name`, `client_id`, `node_key` and + /// `net_config_dir`. + fn network_config( + &self, + chain_spec: &Box, + is_dev: bool, + net_config_dir: PathBuf, + client_id: &str, + node_name: &str, + node_key: NodeKeyConfig, + ) -> Result { + Ok(if let Some(network_params) = self.network_params() { + network_params.network_config( + chain_spec, + is_dev, + Some(net_config_dir), + client_id, + node_name, + node_key, + ) + } else { + NetworkConfiguration::new( + node_name, + client_id, + node_key, + Some(net_config_dir), + ) + }) + } + + /// Get the keystore configuration. + /// + /// Bu default this is retrieved from `KeystoreParams` if it is available. Otherwise it uses + /// `KeystoreConfig::InMemory`. + fn keystore_config(&self, base_path: &PathBuf) -> Result { + self.keystore_params() + .map(|x| x.keystore_config(base_path)) + .unwrap_or(Ok(KeystoreConfig::InMemory)) + } + + /// Get the database cache size. + /// + /// By default this is retrieved from `DatabaseParams` if it is available. Otherwise its `None`. + fn database_cache_size(&self) -> Result> { + Ok(self.database_params() + .map(|x| x.database_cache_size()) + .unwrap_or(Default::default())) + } + + /// Get the database backend variant. + /// + /// By default this is retrieved from `DatabaseParams` if it is available. Otherwise its `None`. + fn database(&self) -> Result> { + Ok(self.database_params().and_then(|x| x.database())) + } + + /// Get the database configuration object for the parameters provided + fn database_config( + &self, + base_path: &PathBuf, + cache_size: usize, + database: Database, + ) -> Result { + Ok(match database { + Database::RocksDb => DatabaseConfig::RocksDb { + path: base_path.join("db"), + cache_size, + }, + Database::SubDb => DatabaseConfig::SubDb { + path: base_path.join("subdb"), + }, + Database::ParityDb => DatabaseConfig::ParityDb { + path: base_path.join("paritydb"), + }, + }) + } + + /// Get the state cache size. + /// + /// By default this is retrieved from `ImportParams` if it is available. Otherwise its `0`. + fn state_cache_size(&self) -> Result { + Ok(self.import_params() + .map(|x| x.state_cache_size()) + .unwrap_or(Default::default())) + } + + /// Get the state cache child ratio (if any). + /// + /// By default this is `None`. + fn state_cache_child_ratio(&self) -> Result> { + Ok(Default::default()) + } + + /// Get the pruning mode. + /// + /// By default this is retrieved from `PruningMode` if it is available. Otherwise its + /// `PruningMode::default()`. + fn pruning(&self, unsafe_pruning: bool, role: &Role) -> Result { + self.pruning_params() + .map(|x| x.pruning(unsafe_pruning, role)) + .unwrap_or(Ok(Default::default())) + } + + /// Get the chain ID (string). + /// + /// By default this is retrieved from `SharedParams`. + fn chain_id(&self, is_dev: bool) -> Result { + Ok(self.shared_params().chain_id(is_dev)) + } + + /// Get the name of the node. + /// + /// By default a random name is generated. + fn node_name(&self) -> Result { + Ok(generate_node_name()) + } + + /// Get the WASM execution method. + /// + /// By default this is retrieved from `ImportParams` if it is available. Otherwise its + /// `WasmExecutionMethod::default()`. + fn wasm_method(&self) -> Result { + Ok(self.import_params() + .map(|x| x.wasm_method()) + .unwrap_or(Default::default())) + } + + /// Get the execution strategies. + /// + /// By default this is retrieved from `ImportParams` if it is available. Otherwise its + /// `ExecutionStrategies::default()`. + fn execution_strategies( + &self, + is_dev: bool, + is_validator: bool, + ) -> Result { + Ok(self + .import_params() + .map(|x| x.execution_strategies(is_dev, is_validator)) + .unwrap_or(Default::default())) + } + + /// Get the RPC HTTP address (`None` if disabled). + /// + /// By default this is `None`. + fn rpc_http(&self) -> Result> { + Ok(Default::default()) + } + + /// Get the RPC IPC path (`None` if disabled). + /// + /// By default this is `None`. + fn rpc_ipc(&self) -> Result> { + Ok(Default::default()) + } + + /// Get the RPC websocket address (`None` if disabled). + /// + /// By default this is `None`. + fn rpc_ws(&self) -> Result> { + Ok(Default::default()) + } + + /// Returns the RPC method set to expose. + /// + /// By default this is `RpcMethods::Auto` (unsafe RPCs are denied iff + /// `{rpc,ws}_external` returns true, respectively). + fn rpc_methods(&self) -> Result { + Ok(Default::default()) + } + + /// Get the RPC websockets maximum connections (`None` if unlimited). + /// + /// By default this is `None`. + fn rpc_ws_max_connections(&self) -> Result> { + Ok(Default::default()) + } + + /// Get the RPC cors (`None` if disabled) + /// + /// By default this is `None`. + fn rpc_cors(&self, _is_dev: bool) -> Result>> { + Ok(Some(Vec::new())) + } + + /// Get the prometheus configuration (`None` if disabled) + /// + /// By default this is `None`. + fn prometheus_config(&self) -> Result> { + Ok(Default::default()) + } + + /// Get the telemetry endpoints (if any) + /// + /// By default this is retrieved from the chain spec loaded by `load_spec`. + fn telemetry_endpoints( + &self, + chain_spec: &Box, + ) -> Result> { + Ok(chain_spec.telemetry_endpoints().clone()) + } + + /// Get the telemetry external transport + /// + /// By default this is `None`. + fn telemetry_external_transport(&self) -> Result> { + Ok(Default::default()) + } + + /// Get the default value for heap pages + /// + /// By default this is `None`. + fn default_heap_pages(&self) -> Result> { + Ok(Default::default()) + } + + /// Returns an offchain worker config wrapped in `Ok(_)` + /// + /// By default offchain workers are disabled. + fn offchain_worker(&self, role: &Role) -> Result { + self.offchain_worker_params() + .map(|x| x.offchain_worker(role)) + .unwrap_or_else(|| Ok(OffchainWorkerConfig::default())) + } + + /// Returns `Ok(true)` if authoring should be forced + /// + /// By default this is `false`. + fn force_authoring(&self) -> Result { + Ok(Default::default()) + } + + /// Returns `Ok(true)` if grandpa should be disabled + /// + /// By default this is `false`. + fn disable_grandpa(&self) -> Result { + Ok(Default::default()) + } + + /// Get the development key seed from the current object + /// + /// By default this is `None`. + fn dev_key_seed(&self, _is_dev: bool) -> Result> { + Ok(Default::default()) + } + + /// Get the tracing targets from the current object (if any) + /// + /// By default this is retrieved from `ImportParams` if it is available. Otherwise its + /// `None`. + fn tracing_targets(&self) -> Result> { + Ok(self.import_params() + .map(|x| x.tracing_targets()) + .unwrap_or(Default::default())) + } + + /// Get the TracingReceiver value from the current object + /// + /// By default this is retrieved from `ImportParams` if it is available. Otherwise its + /// `TracingReceiver::default()`. + fn tracing_receiver(&self) -> Result { + Ok(self.import_params() + .map(|x| x.tracing_receiver()) + .unwrap_or(Default::default())) + } + + /// Get the node key from the current object + /// + /// By default this is retrieved from `NodeKeyParams` if it is available. Otherwise its + /// `NodeKeyConfig::default()`. + fn node_key(&self, net_config_dir: &PathBuf) -> Result { + self.node_key_params() + .map(|x| x.node_key(net_config_dir)) + .unwrap_or(Ok(Default::default())) + } + + /// Get maximum runtime instances + /// + /// By default this is `None`. + fn max_runtime_instances(&self) -> Result> { + Ok(Default::default()) + } + + /// Activate or not the automatic announcing of blocks after import + /// + /// By default this is `false`. + fn announce_block(&self) -> Result { + Ok(true) + } + + /// Create a Configuration object from the current object + fn create_configuration( + &self, + cli: &C, + task_executor: TaskExecutor, + ) -> Result { + let is_dev = self.is_dev()?; + let chain_id = self.chain_id(is_dev)?; + let chain_spec = cli.load_spec(chain_id.as_str())?; + let base_path = self + .base_path()? + .unwrap_or_else(|| BasePath::from_project("", "", &C::executable_name())); + let config_dir = base_path + .path() + .to_path_buf() + .join("chains") + .join(chain_spec.id()); + let net_config_dir = config_dir.join(DEFAULT_NETWORK_CONFIG_PATH); + let client_id = C::client_id(); + let database_cache_size = self.database_cache_size()?.unwrap_or(128); + let database = self.database()?.unwrap_or(Database::RocksDb); + let node_key = self.node_key(&net_config_dir)?; + let role = self.role(is_dev)?; + let max_runtime_instances = self.max_runtime_instances()?.unwrap_or(8); + let is_validator = role.is_network_authority(); + + let unsafe_pruning = self + .import_params() + .map(|p| p.unsafe_pruning) + .unwrap_or(false); + + Ok(Configuration { + impl_name: C::impl_name(), + impl_version: C::impl_version(), + task_executor, + transaction_pool: self.transaction_pool()?, + network: self.network_config( + &chain_spec, + is_dev, + net_config_dir, + client_id.as_str(), + self.node_name()?.as_str(), + node_key, + )?, + keystore: self.keystore_config(&config_dir)?, + database: self.database_config(&config_dir, database_cache_size, database)?, + state_cache_size: self.state_cache_size()?, + state_cache_child_ratio: self.state_cache_child_ratio()?, + pruning: self.pruning(unsafe_pruning, &role)?, + wasm_method: self.wasm_method()?, + execution_strategies: self.execution_strategies(is_dev, is_validator)?, + rpc_http: self.rpc_http()?, + rpc_ws: self.rpc_ws()?, + rpc_ipc: self.rpc_ipc()?, + rpc_methods: self.rpc_methods()?, + rpc_ws_max_connections: self.rpc_ws_max_connections()?, + rpc_cors: self.rpc_cors(is_dev)?, + prometheus_config: self.prometheus_config()?, + telemetry_endpoints: self.telemetry_endpoints(&chain_spec)?, + telemetry_external_transport: self.telemetry_external_transport()?, + default_heap_pages: self.default_heap_pages()?, + offchain_worker: self.offchain_worker(&role)?, + force_authoring: self.force_authoring()?, + disable_grandpa: self.disable_grandpa()?, + dev_key_seed: self.dev_key_seed(is_dev)?, + tracing_targets: self.tracing_targets()?, + tracing_receiver: self.tracing_receiver()?, + chain_spec, + max_runtime_instances, + announce_block: self.announce_block()?, + role, + base_path: Some(base_path), + informant_output_format: Default::default(), + }) + } + + /// Get the filters for the logging. + /// + /// This should be a list of comma-separated values. + /// Example: `foo=trace,bar=debug,baz=info` + /// + /// By default this is retrieved from `SharedParams`. + fn log_filters(&self) -> Result { + Ok(self.shared_params().log_filters().join(",")) + } + + /// Initialize substrate. This must be done only once. + /// + /// This method: + /// + /// 1. Set the panic handler + /// 2. Raise the FD limit + /// 3. Initialize the logger + fn init(&self) -> Result<()> { + let logger_pattern = self.log_filters()?; + + sp_panic_handler::set(&C::support_url(), &C::impl_version()); + + fdlimit::raise_fd_limit(); + init_logger(&logger_pattern); + + Ok(()) + } +} + +/// Generate a valid random name for the node +pub fn generate_node_name() -> String { + loop { + let node_name = Generator::with_naming(Name::Numbered) + .next() + .expect("RNG is available on all supported platforms; qed"); + let count = node_name.chars().count(); + + if count < NODE_NAME_MAX_LENGTH { + return node_name; + } + } +} diff --git a/client/cli/src/error.rs b/client/cli/src/error.rs index edc1adecc762c5f70c11958d1b6f9b0b93863904..f091354be154bbd62856143ed9c23e8c2444c82c 100644 --- a/client/cli/src/error.rs +++ b/client/cli/src/error.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Initialization errors. @@ -25,7 +27,7 @@ pub enum Error { /// Io error Io(std::io::Error), /// Cli error - Cli(clap::Error), + Cli(structopt::clap::Error), /// Service error Service(sc_service::Error), /// Client error @@ -35,6 +37,7 @@ pub enum Error { Input(String), /// Invalid listen multiaddress #[display(fmt="Invalid listen multiaddress")] + #[from(ignore)] InvalidListenMultiaddress, /// Other uncategorized error. #[from(ignore)] diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index ba59b94c8287a97f338b6bf7d8d21e347a05ae35..c7f48d27214681349ef1be7283cdcf9db6ef63d8 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -1,155 +1,231 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Substrate CLI library. #![warn(missing_docs)] #![warn(unused_extern_crates)] -mod params; mod arg_enums; -mod error; -mod runtime; mod commands; +mod config; +mod error; +mod params; +mod runner; -pub use sc_service::config::VersionInfo; - -use std::io::Write; - -use regex::Regex; -use structopt::{StructOpt, clap::{self, AppSettings}}; -pub use structopt; -pub use params::*; -pub use commands::*; pub use arg_enums::*; +pub use commands::*; +pub use config::*; pub use error::*; -use log::info; use lazy_static::lazy_static; -pub use crate::runtime::{run_until_exit, run_service_until_exit}; +use log::info; +pub use params::*; +use regex::Regex; +pub use runner::*; +use sc_service::{Configuration, TaskExecutor}; +pub use sc_service::{ChainSpec, Role}; +pub use sp_version::RuntimeVersion; +use std::io::Write; +pub use structopt; +use structopt::{ + clap::{self, AppSettings}, + StructOpt, +}; -/// Helper function used to parse the command line arguments. This is the equivalent of -/// `structopt`'s `from_iter()` except that it takes a `VersionInfo` argument to provide the name of -/// the application, author, "about" and version. It will also set `AppSettings::GlobalVersion`. +/// Substrate client CLI /// -/// To allow running the node without subcommand, tt also sets a few more settings: -/// `AppSettings::ArgsNegateSubcommands` and `AppSettings::SubcommandsNegateReqs`. +/// This trait needs to be defined on the root structopt of the application. It will provide the +/// implementation name, version, executable name, description, author, support_url, copyright start +/// year and most importantly: how to load the chain spec. /// -/// Gets the struct from the command line arguments. Print the -/// error message and quit the program in case of failure. -pub fn from_args(version: &VersionInfo) -> T -where - T: StructOpt + Sized, -{ - from_iter::(&mut std::env::args_os(), version) -} +/// StructOpt must not be in scope to use from_args (or the similar methods). This trait provides +/// its own implementation that will fill the necessary field based on the trait's functions. +pub trait SubstrateCli: Sized { + /// Implementation name. + fn impl_name() -> String; + + /// Implementation version. + /// + /// By default this will look like this: 2.0.0-b950f731c-x86_64-linux-gnu where the hash is the + /// short commit hash of the commit of in the Git repository. + fn impl_version() -> String; + + /// Executable file name. + /// + /// Extracts the file name from `std::env::current_exe()`. + /// Resorts to the env var `CARGO_PKG_NAME` in case of Error. + fn executable_name() -> String { + std::env::current_exe().ok() + .and_then(|e| e.file_name().map(|s| s.to_os_string())) + .and_then(|w| w.into_string().ok()) + .unwrap_or_else(|| env!("CARGO_PKG_NAME").into()) + } -/// Helper function used to parse the command line arguments. This is the equivalent of -/// `structopt`'s `from_iter()` except that it takes a `VersionInfo` argument to provide the name of -/// the application, author, "about" and version. It will also set `AppSettings::GlobalVersion`. -/// -/// To allow running the node without subcommand, tt also sets a few more settings: -/// `AppSettings::ArgsNegateSubcommands` and `AppSettings::SubcommandsNegateReqs`. -/// -/// Gets the struct from any iterator such as a `Vec` of your making. -/// Print the error message and quit the program in case of failure. -pub fn from_iter(iter: I, version: &VersionInfo) -> T -where - T: StructOpt + Sized, - I: IntoIterator, - I::Item: Into + Clone, -{ - let app = T::clap(); - - let mut full_version = sc_service::config::full_version_from_strs( - version.version, - version.commit - ); - full_version.push_str("\n"); - - let app = app - .name(version.executable_name) - .author(version.author) - .about(version.description) - .version(full_version.as_str()) - .settings(&[ - AppSettings::GlobalVersion, - AppSettings::ArgsNegateSubcommands, - AppSettings::SubcommandsNegateReqs, - ]); - - T::from_clap(&app.get_matches_from(iter)) -} + /// Executable file description. + fn description() -> String; + + /// Executable file author. + fn author() -> String; + + /// Support URL. + fn support_url() -> String; + + /// Copyright starting year (x-current year) + fn copyright_start_year() -> i32; + + /// Chain spec factory + fn load_spec(&self, id: &str) -> std::result::Result, String>; + + /// Helper function used to parse the command line arguments. This is the equivalent of + /// `structopt`'s `from_iter()` except that it takes a `VersionInfo` argument to provide the name of + /// the application, author, "about" and version. It will also set `AppSettings::GlobalVersion`. + /// + /// To allow running the node without subcommand, tt also sets a few more settings: + /// `AppSettings::ArgsNegateSubcommands` and `AppSettings::SubcommandsNegateReqs`. + /// + /// Gets the struct from the command line arguments. Print the + /// error message and quit the program in case of failure. + fn from_args() -> Self + where + Self: StructOpt + Sized, + { + ::from_iter(&mut std::env::args_os()) + } -/// Helper function used to parse the command line arguments. This is the equivalent of -/// `structopt`'s `from_iter()` except that it takes a `VersionInfo` argument to provide the name of -/// the application, author, "about" and version. It will also set `AppSettings::GlobalVersion`. -/// -/// To allow running the node without subcommand, tt also sets a few more settings: -/// `AppSettings::ArgsNegateSubcommands` and `AppSettings::SubcommandsNegateReqs`. -/// -/// Gets the struct from any iterator such as a `Vec` of your making. -/// Print the error message and quit the program in case of failure. -/// -/// **NOTE:** This method WILL NOT exit when `--help` or `--version` (or short versions) are -/// used. It will return a [`clap::Error`], where the [`kind`] is a -/// [`ErrorKind::HelpDisplayed`] or [`ErrorKind::VersionDisplayed`] respectively. You must call -/// [`Error::exit`] or perform a [`std::process::exit`]. -pub fn try_from_iter(iter: I, version: &VersionInfo) -> clap::Result -where - T: StructOpt + Sized, - I: IntoIterator, - I::Item: Into + Clone, -{ - let app = T::clap(); - - let mut full_version = sc_service::config::full_version_from_strs( - version.version, - version.commit, - ); - full_version.push_str("\n"); - - let app = app - .name(version.executable_name) - .author(version.author) - .about(version.description) - .version(full_version.as_str()); - - let matches = app.get_matches_from_safe(iter)?; - - Ok(T::from_clap(&matches)) -} + /// Helper function used to parse the command line arguments. This is the equivalent of + /// `structopt`'s `from_iter()` except that it takes a `VersionInfo` argument to provide the name of + /// the application, author, "about" and version. It will also set `AppSettings::GlobalVersion`. + /// + /// To allow running the node without subcommand, it also sets a few more settings: + /// `AppSettings::ArgsNegateSubcommands` and `AppSettings::SubcommandsNegateReqs`. + /// + /// Gets the struct from any iterator such as a `Vec` of your making. + /// Print the error message and quit the program in case of failure. + fn from_iter(iter: I) -> Self + where + Self: StructOpt + Sized, + I: IntoIterator, + I::Item: Into + Clone, + { + let app = ::clap(); + + let mut full_version = Self::impl_version(); + full_version.push_str("\n"); + + let name = Self::executable_name(); + let author = Self::author(); + let about = Self::description(); + let app = app + .name(name) + .author(author.as_str()) + .about(about.as_str()) + .version(full_version.as_str()) + .settings(&[ + AppSettings::GlobalVersion, + AppSettings::ArgsNegateSubcommands, + AppSettings::SubcommandsNegateReqs, + ]); + + let matches = match app.get_matches_from_safe(iter) { + Ok(matches) => matches, + Err(mut e) => { + // To support pipes, we can not use `writeln!` as any error + // results in a "broken pipe" error. + // + // Instead we write directly to `stdout` and ignore any error + // as we exit afterwards anyway. + e.message.extend("\n".chars()); + + if e.use_stderr() { + let _ = std::io::stderr().write_all(e.message.as_bytes()); + std::process::exit(1); + } else { + let _ = std::io::stdout().write_all(e.message.as_bytes()); + std::process::exit(0); + } + }, + }; -/// Initialize substrate. This must be done only once. -/// -/// This method: -/// -/// 1. Set the panic handler -/// 2. Raise the FD limit -/// 3. Initialize the logger -pub fn init(logger_pattern: &str, version: &VersionInfo) -> error::Result<()> { - let full_version = sc_service::config::full_version_from_strs( - version.version, - version.commit - ); - sp_panic_handler::set(version.support_url, &full_version); - - fdlimit::raise_fd_limit(); - init_logger(logger_pattern); - - Ok(()) + ::from_clap(&matches) + } + + /// Helper function used to parse the command line arguments. This is the equivalent of + /// `structopt`'s `from_iter()` except that it takes a `VersionInfo` argument to provide the name of + /// the application, author, "about" and version. It will also set `AppSettings::GlobalVersion`. + /// + /// To allow running the node without subcommand, it also sets a few more settings: + /// `AppSettings::ArgsNegateSubcommands` and `AppSettings::SubcommandsNegateReqs`. + /// + /// Gets the struct from any iterator such as a `Vec` of your making. + /// Print the error message and quit the program in case of failure. + /// + /// **NOTE:** This method WILL NOT exit when `--help` or `--version` (or short versions) are + /// used. It will return a [`clap::Error`], where the [`clap::Error::kind`] is a + /// [`clap::ErrorKind::HelpDisplayed`] or [`clap::ErrorKind::VersionDisplayed`] respectively. + /// You must call [`clap::Error::exit`] or perform a [`std::process::exit`]. + fn try_from_iter(iter: I) -> clap::Result + where + Self: StructOpt + Sized, + I: IntoIterator, + I::Item: Into + Clone, + { + let app = ::clap(); + + let mut full_version = Self::impl_version(); + full_version.push_str("\n"); + + let name = Self::executable_name(); + let author = Self::author(); + let about = Self::description(); + let app = app + .name(name) + .author(author.as_str()) + .about(about.as_str()) + .version(full_version.as_str()); + + let matches = app.get_matches_from_safe(iter)?; + + Ok(::from_clap(&matches)) + } + + /// Returns the client ID: `{impl_name}/v{impl_version}` + fn client_id() -> String { + format!("{}/v{}", Self::impl_name(), Self::impl_version()) + } + + /// Only create a Configuration for the command provided in argument + fn create_configuration( + &self, + command: &T, + task_executor: TaskExecutor, + ) -> error::Result { + command.create_configuration(self, task_executor) + } + + /// Create a runner for the command provided in argument. This will create a Configuration and + /// a tokio runtime + fn create_runner(&self, command: &T) -> error::Result> { + command.init::()?; + Runner::new(self, command) + } + + /// Native runtime version. + fn native_runtime_version(chain_spec: &Box) -> &'static RuntimeVersion; } /// Initialize the logger @@ -159,6 +235,7 @@ pub fn init_logger(pattern: &str) { let mut builder = env_logger::Builder::new(); // Disable info logging by default for some modules: builder.filter(Some("ws"), log::LevelFilter::Off); + builder.filter(Some("yamux"), log::LevelFilter::Off); builder.filter(Some("hyper"), log::LevelFilter::Warn); builder.filter(Some("cranelift_wasm"), log::LevelFilter::Warn); // Always log the special target `sc_tracing`, overrides global level @@ -177,17 +254,22 @@ pub fn init_logger(pattern: &str) { builder.format(move |buf, record| { let now = time::now(); let timestamp = - time::strftime("%Y-%m-%d %H:%M:%S", &now) - .expect("Error formatting log timestamp"); + time::strftime("%Y-%m-%d %H:%M:%S", &now).expect("Error formatting log timestamp"); let mut output = if log::max_level() <= log::LevelFilter::Info { - format!("{} {}", Colour::Black.bold().paint(timestamp), record.args()) + format!( + "{} {}", + Colour::Black.bold().paint(timestamp), + record.args(), + ) } else { let name = ::std::thread::current() .name() - .map_or_else(Default::default, |x| format!("{}", Colour::Blue.bold().paint(x))); + .map_or_else(Default::default, |x| { + format!("{}", Colour::Blue.bold().paint(x)) + }); let millis = (now.tm_nsec as f32 / 1000000.0).floor() as usize; - let timestamp = format!("{}.{}", timestamp, millis); + let timestamp = format!("{}.{:03}", timestamp, millis); format!( "{} {} {} {} {}", Colour::Black.bold().paint(timestamp), @@ -221,21 +303,3 @@ fn kill_color(s: &str) -> String { } RE.replace_all(s, "").to_string() } - -/// Reset the signal pipe (`SIGPIPE`) handler to the default one provided by the system. -/// This will end the program on `SIGPIPE` instead of panicking. -/// -/// This should be called before calling any cli method or printing any output. -pub fn reset_signal_pipe_handler() -> Result<()> { - #[cfg(target_family = "unix")] - { - use nix::sys::signal; - - unsafe { - signal::signal(signal::Signal::SIGPIPE, signal::SigHandler::SigDfl) - .map_err(|e| Error::Other(e.to_string()))?; - } - } - - Ok(()) -} diff --git a/client/cli/src/logger.rs b/client/cli/src/logger.rs new file mode 100644 index 0000000000000000000000000000000000000000..10e44098f0f16389c332d207d9f13ac0c82ba3b1 --- /dev/null +++ b/client/cli/src/logger.rs @@ -0,0 +1,272 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use ansi_term::Colour; +use flexi_logger::{ + DeferredNow, Duplicate, LogSpecBuilder, + LogSpecification, LogTarget, Logger, Criterion, Naming, Cleanup, Age, +}; +use lazy_static::lazy_static; +use regex::Regex; +use std::path::PathBuf; +use structopt::StructOpt; +use crate::error::{Error, Result}; + +type IoResult = std::result::Result<(), std::io::Error>; + +/// Default size used for rotation. Basically unlimited. +const DEFAULT_ROTATION_SIZE: u64 = u64::MAX; + +/// Options for log rotation. +#[derive(Debug, StructOpt, Default, Clone)] +pub struct LogRotationOpt { + /// Specify the path of the directory which will contain the log files. + /// Defaults to never rotating logs. + #[structopt(long, parse(from_os_str))] + log_directory: Option, + + /// Rotate the log file when the local clock has started a new day/hour/minute/second + /// since the current file has been created. + #[structopt(long, + conflicts_with("log-size"), + possible_values(&["day", "hour", "minute", "second"]), + parse(from_str = age_from_str)) + ] + log_age: Option, + + /// Rotate the log file when it exceeds this size (in bytes). + #[structopt(long, conflicts_with("log-age"))] + log_size: Option, +} + +/// Utility for parsing an Age from a &str. +fn age_from_str(s: &str) -> Age { + match s { + "day" => Age::Day, + "hour" => Age::Hour, + "minute" => Age::Minute, + "second" => Age::Second, + _ => unreachable!(), + } +} + +/// Format used when writing to a tty. Colors the output. +fn colored_fmt( + w: &mut dyn std::io::Write, + _now: &mut DeferredNow, + record: &log::Record, +) -> IoResult { + let now = time::now(); + let timestamp = + time::strftime("%Y-%m-%d %H:%M:%S", &now).expect("Error formatting log timestamp"); + + let output = if log::max_level() <= log::LevelFilter::Info { + format!( + "{} {}", + Colour::Black.bold().paint(timestamp), + record.args(), + ) + } else { + let name = ::std::thread::current() + .name() + .map_or_else(Default::default, |x| { + format!("{}", Colour::Blue.bold().paint(x)) + }); + let millis = (now.tm_nsec as f32 / 1000000.0).floor() as usize; + let timestamp = format!("{}.{:03}", timestamp, millis); + format!( + "{} {} {} {} {}", + Colour::Black.bold().paint(timestamp), + name, + record.level(), + record.target(), + record.args() + ) + }; + + write!(w, "{}", output) +} + +/// Format used when logging to files. Does not add any colors. +fn file_fmt( + w: &mut dyn std::io::Write, + _now: &mut DeferredNow, + record: &log::Record, +) -> IoResult { + let now = time::now(); + let timestamp = + time::strftime("%Y-%m-%d %H:%M:%S", &now).expect("Error formatting log timestamp"); + + let output = if log::max_level() <= log::LevelFilter::Info { + format!("{} {}", timestamp, record.args(),) + } else { + let name = std::thread::current() + .name() + .map_or_else(Default::default, |x| format!("{}", x)); + let millis = (now.tm_nsec as f32 / 1000000.0).floor() as usize; + let timestamp = format!("{}.{:03}", timestamp, millis); + format!( + "{} {} {} {} {}", + timestamp, + name, + record.level(), + record.target(), + record.args() + ) + }; + + // Required because substrate sometimes sends strings that are colored. + // Doing this ensures no colors are ever printed to files. + let output = kill_color(&output); + + write!(w, "{}", output) +} + +/// Initialize the logger +pub fn init_logger( + pattern: &str, + log_rotation_opt: Option, +) -> Result<()> { + let mut builder = LogSpecBuilder::new(); + // Disable info logging by default for some modules: + builder.module("ws", log::LevelFilter::Off); + builder.module("yamux", log::LevelFilter::Off); + builder.module("hyper", log::LevelFilter::Warn); + builder.module("cranelift_wasm", log::LevelFilter::Warn); + // Always log the special target `sc_tracing`, overrides global level + builder.module("sc_tracing", log::LevelFilter::Info); + // Enable info for others. + builder.default(log::LevelFilter::Info); + + // Add filters defined by RUST_LOG. + builder.insert_modules_from(LogSpecification::env()?); + + // Add filters passed in as argument. + builder.insert_modules_from(LogSpecification::parse(pattern)?); + + // Build the LogSpec. + let spec = builder.build(); + + // Use timestamps to differentiate logs. + let naming = Naming::Timestamps; + // Never cleanup old logs; let the end-user take care of that. + let cleanup = Cleanup::Never; + + let log_rotation_opt = log_rotation_opt.unwrap_or_default(); + let age = log_rotation_opt.log_age; + let size = log_rotation_opt.log_size; + + // Build a Criterion from the options. + let criterion = match (age, size) { + (Some(a), None) => Criterion::Age(a), + (None, Some(s)) => Criterion::Size(s), + // Default to rotating with a size of `DEFAULT_ROTATION_SIZE`. + (None, None) => Criterion::Size(DEFAULT_ROTATION_SIZE), + _ => return Err(Error::Input("Only one of Age or Size should be defined".into())) + }; + + let isatty_stderr = atty::is(atty::Stream::Stderr); + let isatty_stdout = atty::is(atty::Stream::Stdout); + let logger = Logger::with(spec) + .format(file_fmt) + .format_for_stderr(colored_fmt) + .format_for_stdout(colored_fmt) + .rotate(criterion, naming, cleanup); // Won't get used if log_directory has not been specified. + + + let logger = match (log_rotation_opt.log_directory.as_ref(), isatty_stderr) { + // Only log to stderr using colored format; nothing to file, nothing to stdout. + (None, true) => { + logger.log_target(LogTarget::StdErr) + } + // Log to stderr using file format, log to stdout using colored format. + (None, false) => { + let logger = logger + .log_target(LogTarget::DevNull) + .format_for_stderr(file_fmt) + .duplicate_to_stderr(Duplicate::All); + + // Write to stdout only if it's a tty. + if isatty_stdout { + logger.duplicate_to_stdout(Duplicate::Info) + } else { + logger + } + } + // Log to stderr with colored format, log to file with file format. Nothing to stdout. + (Some(file), true) => { + logger + .log_target(LogTarget::File) + .duplicate_to_stderr(Duplicate::All) + .directory(file) + } + // Log to stderr with file format, log to file with file format, log to stdout with colored format. + (Some(file), false) => { + let logger = logger + .log_target(LogTarget::File) + .format_for_stderr(file_fmt) + .duplicate_to_stderr(Duplicate::All) + .directory(file); + + // Write to stdout only if it's a tty. + if isatty_stdout { + logger.duplicate_to_stdout(Duplicate::Info) + } else { + logger + } + } + }; + + logger.start().map(|_| ()).map_err(|e| e.into()) +} + +fn kill_color(s: &str) -> String { + lazy_static! { + static ref RE: Regex = Regex::new("\x1b\\[[^m]+m").expect("Error initializing color regex"); + } + RE.replace_all(s, "").to_string() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn logger_default() { + let pattern = ""; + let log_rotation_opt = LogRotationOpt { + log_directory: None, + log_age: None, + log_size: None, + }; + + assert!(init_logger(pattern, Some(log_rotation_opt)).is_ok()); + } + + #[test] + fn logger_conflicting_opt() { + let pattern = ""; + let log_rotation_opt = LogRotationOpt { + log_directory: None, + log_age: Some(Age::Day), + log_size: Some(1337), + }; + + assert!(init_logger(pattern, Some(log_rotation_opt)).is_err()); + } +} diff --git a/client/cli/src/params/database_params.rs b/client/cli/src/params/database_params.rs new file mode 100644 index 0000000000000000000000000000000000000000..24b23f6076a02302071c76a6da614c8e5c11e6a0 --- /dev/null +++ b/client/cli/src/params/database_params.rs @@ -0,0 +1,49 @@ +// This file is part of Substrate. + +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use crate::arg_enums::Database; +use structopt::StructOpt; + +/// Parameters for block import. +#[derive(Debug, StructOpt)] +pub struct DatabaseParams { + /// Select database backend to use. + #[structopt( + long, + alias = "db", + value_name = "DB", + case_insensitive = true, + )] + pub database: Option, + + /// Limit the memory the database cache can use. + #[structopt(long = "db-cache", value_name = "MiB")] + pub database_cache_size: Option, +} + +impl DatabaseParams { + /// Limit the memory the database cache can use. + pub fn database(&self) -> Option { + self.database + } + + /// Limit the memory the database cache can use. + pub fn database_cache_size(&self) -> Option { + self.database_cache_size + } +} diff --git a/client/cli/src/params/import_params.rs b/client/cli/src/params/import_params.rs index 8d34b706f570246d02d4adcd40cf6dba39796f54..c2fb34f90e6fc84c247d535d9323679e5608dc1c 100644 --- a/client/cli/src/params/import_params.rs +++ b/client/cli/src/params/import_params.rs @@ -1,37 +1,42 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 structopt::StructOpt; -use sc_service::{Configuration, config::DatabaseConfig}; +// along with this program. If not, see . -use crate::error; use crate::arg_enums::{ - WasmExecutionMethod, TracingReceiver, ExecutionStrategy, DEFAULT_EXECUTION_BLOCK_CONSTRUCTION, - DEFAULT_EXECUTION_IMPORT_BLOCK, DEFAULT_EXECUTION_OFFCHAIN_WORKER, DEFAULT_EXECUTION_OTHER, - DEFAULT_EXECUTION_SYNCING + ExecutionStrategy, TracingReceiver, WasmExecutionMethod, DEFAULT_EXECUTION_BLOCK_CONSTRUCTION, + DEFAULT_EXECUTION_IMPORT_BLOCK, DEFAULT_EXECUTION_IMPORT_BLOCK_VALIDATOR, + DEFAULT_EXECUTION_OFFCHAIN_WORKER, DEFAULT_EXECUTION_OTHER, DEFAULT_EXECUTION_SYNCING, }; +use crate::params::DatabaseParams; use crate::params::PruningParams; +use sc_client_api::execution_extensions::ExecutionStrategies; +use structopt::StructOpt; /// Parameters for block import. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, StructOpt)] pub struct ImportParams { #[allow(missing_docs)] #[structopt(flatten)] pub pruning_params: PruningParams, + #[allow(missing_docs)] + #[structopt(flatten)] + pub database_params: DatabaseParams, + /// Force start with unsafe pruning settings. /// /// When running as a validator it is highly recommended to disable state @@ -52,14 +57,14 @@ pub struct ImportParams { #[allow(missing_docs)] #[structopt(flatten)] - pub execution_strategies: ExecutionStrategies, - - /// Limit the memory the database cache can use. - #[structopt(long = "db-cache", value_name = "MiB", default_value = "128")] - pub database_cache_size: u32, + pub execution_strategies: ExecutionStrategiesParams, /// Specify the state cache size. - #[structopt(long = "state-cache-size", value_name = "Bytes", default_value = "67108864")] + #[structopt( + long = "state-cache-size", + value_name = "Bytes", + default_value = "67108864" + )] pub state_cache_size: usize, /// Comma separated list of targets for tracing. @@ -78,70 +83,79 @@ pub struct ImportParams { } impl ImportParams { - /// Put block import CLI params into `config` object. - pub fn update_config( - &self, - mut config: &mut Configuration, - role: &sc_service::Role, - is_dev: bool, - ) -> error::Result<()> { - use sc_client_api::execution_extensions::ExecutionStrategies; - - if let Some(DatabaseConfig::Path { ref mut cache_size, .. }) = config.database { - *cache_size = Some(self.database_cache_size); - } + /// Receiver to process tracing messages. + pub fn tracing_receiver(&self) -> sc_service::TracingReceiver { + self.tracing_receiver.clone().into() + } - config.state_cache_size = self.state_cache_size; + /// Comma separated list of targets for tracing. + pub fn tracing_targets(&self) -> Option { + self.tracing_targets.clone() + } - self.pruning_params.update_config(&mut config, role, self.unsafe_pruning)?; + /// Specify the state cache size. + pub fn state_cache_size(&self) -> usize { + self.state_cache_size + } - config.wasm_method = self.wasm_method.into(); + /// Get the WASM execution method from the parameters + pub fn wasm_method(&self) -> sc_service::config::WasmExecutionMethod { + self.wasm_method.into() + } + /// Get execution strategies for the parameters + pub fn execution_strategies(&self, is_dev: bool, is_validator: bool) -> ExecutionStrategies { let exec = &self.execution_strategies; - let exec_all_or = |strat: ExecutionStrategy, default: ExecutionStrategy| { - exec.execution.unwrap_or(if strat == default && is_dev { + let exec_all_or = |strat: Option, default: ExecutionStrategy| { + let default = if is_dev { ExecutionStrategy::Native } else { - strat - }).into() + default + }; + + exec.execution.unwrap_or(strat.unwrap_or(default)).into() + }; + + let default_execution_import_block = if is_validator { + DEFAULT_EXECUTION_IMPORT_BLOCK_VALIDATOR + } else { + DEFAULT_EXECUTION_IMPORT_BLOCK }; - config.execution_strategies = ExecutionStrategies { + ExecutionStrategies { syncing: exec_all_or(exec.execution_syncing, DEFAULT_EXECUTION_SYNCING), - importing: exec_all_or(exec.execution_import_block, DEFAULT_EXECUTION_IMPORT_BLOCK), + importing: exec_all_or(exec.execution_import_block, default_execution_import_block), block_construction: exec_all_or(exec.execution_block_construction, DEFAULT_EXECUTION_BLOCK_CONSTRUCTION), offchain_worker: exec_all_or(exec.execution_offchain_worker, DEFAULT_EXECUTION_OFFCHAIN_WORKER), other: exec_all_or(exec.execution_other, DEFAULT_EXECUTION_OTHER), - }; - - Ok(()) + } } } /// Execution strategies parameters. -#[derive(Debug, StructOpt, Clone)] -pub struct ExecutionStrategies { - /// The means of execution used when calling into the runtime while syncing blocks. +#[derive(Debug, StructOpt)] +pub struct ExecutionStrategiesParams { + /// The means of execution used when calling into the runtime for importing blocks as + /// part of an initial sync. #[structopt( long = "execution-syncing", value_name = "STRATEGY", possible_values = &ExecutionStrategy::variants(), case_insensitive = true, - default_value = DEFAULT_EXECUTION_SYNCING.as_str(), )] - pub execution_syncing: ExecutionStrategy, + pub execution_syncing: Option, - /// The means of execution used when calling into the runtime while importing blocks. + /// The means of execution used when calling into the runtime for general block import + /// (including locally authored blocks). #[structopt( long = "execution-import-block", value_name = "STRATEGY", possible_values = &ExecutionStrategy::variants(), case_insensitive = true, - default_value = DEFAULT_EXECUTION_IMPORT_BLOCK.as_str(), )] - pub execution_import_block: ExecutionStrategy, + pub execution_import_block: Option, /// The means of execution used when calling into the runtime while constructing blocks. #[structopt( @@ -149,9 +163,8 @@ pub struct ExecutionStrategies { value_name = "STRATEGY", possible_values = &ExecutionStrategy::variants(), case_insensitive = true, - default_value = DEFAULT_EXECUTION_BLOCK_CONSTRUCTION.as_str(), )] - pub execution_block_construction: ExecutionStrategy, + pub execution_block_construction: Option, /// The means of execution used when calling into the runtime while using an off-chain worker. #[structopt( @@ -159,9 +172,8 @@ pub struct ExecutionStrategies { value_name = "STRATEGY", possible_values = &ExecutionStrategy::variants(), case_insensitive = true, - default_value = DEFAULT_EXECUTION_OFFCHAIN_WORKER.as_str(), )] - pub execution_offchain_worker: ExecutionStrategy, + pub execution_offchain_worker: Option, /// The means of execution used when calling into the runtime while not syncing, importing or constructing blocks. #[structopt( @@ -169,9 +181,8 @@ pub struct ExecutionStrategies { value_name = "STRATEGY", possible_values = &ExecutionStrategy::variants(), case_insensitive = true, - default_value = DEFAULT_EXECUTION_OTHER.as_str(), )] - pub execution_other: ExecutionStrategy, + pub execution_other: Option, /// The execution strategy that should be used by all execution contexts. #[structopt( diff --git a/client/cli/src/params/keystore_params.rs b/client/cli/src/params/keystore_params.rs new file mode 100644 index 0000000000000000000000000000000000000000..8b20dd247aec6d6e3bb4b8c2b49026ae114e2fe5 --- /dev/null +++ b/client/cli/src/params/keystore_params.rs @@ -0,0 +1,107 @@ +// This file is part of Substrate. + +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use crate::error::Result; +use sc_service::config::KeystoreConfig; +use std::fs; +use std::path::PathBuf; +use structopt::StructOpt; +use sp_core::crypto::SecretString; + +/// default sub directory for the key store +const DEFAULT_KEYSTORE_CONFIG_PATH: &'static str = "keystore"; + +/// Parameters of the keystore +#[derive(Debug, StructOpt)] +pub struct KeystoreParams { + /// Specify custom keystore path. + #[structopt(long = "keystore-path", value_name = "PATH", parse(from_os_str))] + pub keystore_path: Option, + + /// Use interactive shell for entering the password used by the keystore. + #[structopt( + long = "password-interactive", + conflicts_with_all = &[ "password", "password-filename" ] + )] + pub password_interactive: bool, + + /// Password used by the keystore. + #[structopt( + long = "password", + parse(try_from_str = secret_string_from_str), + conflicts_with_all = &[ "password-interactive", "password-filename" ] + )] + pub password: Option, + + /// File that contains the password used by the keystore. + #[structopt( + long = "password-filename", + value_name = "PATH", + parse(from_os_str), + conflicts_with_all = &[ "password-interactive", "password" ] + )] + pub password_filename: Option, +} + +/// Parse a sercret string, returning a displayable error. +pub fn secret_string_from_str(s: &str) -> std::result::Result { + Ok(std::str::FromStr::from_str(s) + .map_err(|_e| "Could not get SecretString".to_string())?) +} + +impl KeystoreParams { + /// Get the keystore configuration for the parameters + pub fn keystore_config(&self, base_path: &PathBuf) -> Result { + let password = if self.password_interactive { + #[cfg(not(target_os = "unknown"))] + { + let mut password = input_keystore_password()?; + let secret = std::str::FromStr::from_str(password.as_str()) + .map_err(|()| "Error reading password")?; + use sp_core::crypto::Zeroize; + password.zeroize(); + Some(secret) + } + #[cfg(target_os = "unknown")] + None + } else if let Some(ref file) = self.password_filename { + let mut password = fs::read_to_string(file) + .map_err(|e| format!("{}", e))?; + let secret = std::str::FromStr::from_str(password.as_str()) + .map_err(|()| "Error reading password")?; + use sp_core::crypto::Zeroize; + password.zeroize(); + Some(secret) + } else { + self.password.clone() + }; + + let path = self + .keystore_path + .clone() + .unwrap_or(base_path.join(DEFAULT_KEYSTORE_CONFIG_PATH)); + + Ok(KeystoreConfig::Path { path, password }) + } +} + +#[cfg(not(target_os = "unknown"))] +fn input_keystore_password() -> Result { + rpassword::read_password_from_tty(Some("Keystore password: ")) + .map_err(|e| format!("{:?}", e).into()) +} diff --git a/client/cli/src/params/mod.rs b/client/cli/src/params/mod.rs index f684cab336423159c6a18ff492c3d7741c4cfded..f648337ed0af6846193d1afaf8518d223d7868c9 100644 --- a/client/cli/src/params/mod.rs +++ b/client/cli/src/params/mod.rs @@ -1,48 +1,55 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . - +// along with this program. If not, see . +mod database_params; mod import_params; -mod transaction_pool_params; -mod shared_params; +mod keystore_params; +mod network_params; mod node_key_params; -mod network_configuration_params; +mod offchain_worker_params; mod pruning_params; +mod shared_params; +mod transaction_pool_params; -use std::str::FromStr; -use std::fmt::Debug; +use std::{fmt::Debug, str::FromStr}; +use sp_runtime::{generic::BlockId, traits::{Block as BlockT, NumberFor}}; +pub use crate::params::database_params::*; pub use crate::params::import_params::*; -pub use crate::params::transaction_pool_params::*; -pub use crate::params::shared_params::*; +pub use crate::params::keystore_params::*; +pub use crate::params::network_params::*; pub use crate::params::node_key_params::*; -pub use crate::params::network_configuration_params::*; +pub use crate::params::offchain_worker_params::*; pub use crate::params::pruning_params::*; +pub use crate::params::shared_params::*; +pub use crate::params::transaction_pool_params::*; /// Wrapper type of `String` that holds an unsigned integer of arbitrary size, formatted as a decimal. -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct BlockNumber(String); impl FromStr for BlockNumber { type Err = String; fn from_str(block_number: &str) -> Result { - if block_number.chars().any(|d| !d.is_digit(10)) { + if let Some(pos) = block_number.chars().position(|d| !d.is_digit(10)) { Err(format!( - "Invalid block number: {}, expected decimal formatted unsigned integer", - block_number, + "Expected block number, found illegal digit at position: {}", + pos, )) } else { Ok(Self(block_number.to_owned())) @@ -60,8 +67,89 @@ impl BlockNumber { N: FromStr, N::Err: std::fmt::Debug, { - self.0 - .parse() - .map_err(|e| format!("BlockNumber: {} parsing failed because of {:?}", self.0, e)) + FromStr::from_str(&self.0).map_err(|e| format!("Failed to parse block number: {:?}", e)) + } +} + +/// Wrapper type that is either a `Hash` or the number of a `Block`. +#[derive(Debug)] +pub struct BlockNumberOrHash(String); + +impl FromStr for BlockNumberOrHash { + type Err = String; + + fn from_str(block_number: &str) -> Result { + if block_number.starts_with("0x") { + if let Some(pos) = &block_number[2..].chars().position(|c| !c.is_ascii_hexdigit()) { + Err(format!( + "Expected block hash, found illegal hex character at position: {}", + 2 + pos, + )) + } else { + Ok(Self(block_number.into())) + } + } else { + BlockNumber::from_str(block_number).map(|v| Self(v.0)) + } + } +} + +impl BlockNumberOrHash { + /// Parse the inner value as `BlockId`. + pub fn parse(&self) -> Result, String> + where + B::Hash: FromStr, + ::Err: std::fmt::Debug, + NumberFor: FromStr, + as FromStr>::Err: std::fmt::Debug, + { + if self.0.starts_with("0x") { + Ok(BlockId::Hash( + FromStr::from_str(&self.0[2..]) + .map_err(|e| format!("Failed to parse block hash: {:?}", e))? + )) + } else { + BlockNumber(self.0.clone()).parse().map(BlockId::Number) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + type Header = sp_runtime::generic::Header; + type Block = sp_runtime::generic::Block; + + #[test] + fn parse_block_number() { + let block_number_or_hash = BlockNumberOrHash::from_str("1234").unwrap(); + let parsed = block_number_or_hash.parse::().unwrap(); + assert_eq!(BlockId::Number(1234), parsed); + } + + #[test] + fn parse_block_hash() { + let hash = sp_core::H256::default(); + let hash_str = format!("{:?}", hash); + let block_number_or_hash = BlockNumberOrHash::from_str(&hash_str).unwrap(); + let parsed = block_number_or_hash.parse::().unwrap(); + assert_eq!(BlockId::Hash(hash), parsed); + } + + #[test] + fn parse_block_hash_fails() { + assert_eq!( + "Expected block hash, found illegal hex character at position: 2", + BlockNumberOrHash::from_str("0xHello").unwrap_err(), + ); + } + + #[test] + fn parse_block_number_fails() { + assert_eq!( + "Expected block number, found illegal digit at position: 3", + BlockNumberOrHash::from_str("345Hello").unwrap_err(), + ); } } diff --git a/client/cli/src/params/network_configuration_params.rs b/client/cli/src/params/network_configuration_params.rs deleted file mode 100644 index b01cdeeb1cbeeea2a406d328d456c6b0ceb0d4f4..0000000000000000000000000000000000000000 --- a/client/cli/src/params/network_configuration_params.rs +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2018-2020 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::path::PathBuf; -use std::iter; -use std::net::Ipv4Addr; -use structopt::StructOpt; -use sc_network::{ - config::{MultiaddrWithPeerId, NonReservedPeerMode, TransportConfig}, multiaddr::Protocol, Multiaddr, -}; -use sc_service::Configuration; - -use crate::error; -use crate::params::node_key_params::NodeKeyParams; - -/// Parameters used to create the network configuration. -#[derive(Debug, StructOpt, Clone)] -pub struct NetworkConfigurationParams { - /// Specify a list of bootnodes. - #[structopt(long = "bootnodes", value_name = "ADDR")] - pub bootnodes: Vec, - - /// Specify a list of reserved node addresses. - #[structopt(long = "reserved-nodes", value_name = "ADDR")] - pub reserved_nodes: Vec, - - /// 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, - - /// Specify a list of sentry node public addresses. - #[structopt( - long = "sentry-nodes", - value_name = "ADDR", - conflicts_with_all = &[ "sentry" ] - )] - pub sentry_nodes: Vec, - - /// 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. - #[structopt(long = "port", value_name = "PORT")] - pub port: Option, - - /// Forbid connecting to private IPv4 addresses (as specified in - /// [RFC1918](https://tools.ietf.org/html/rfc1918)), unless the address was passed with - /// `--reserved-nodes` or `--bootnodes`. - #[structopt(long = "no-private-ipv4")] - pub no_private_ipv4: bool, - - /// Specify the number of outgoing connections we're trying to maintain. - #[structopt(long = "out-peers", value_name = "COUNT", default_value = "25")] - pub out_peers: u32, - - /// Specify the maximum number of incoming connections we're accepting. - #[structopt(long = "in-peers", value_name = "COUNT", default_value = "25")] - pub in_peers: u32, - - /// 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, - - /// Maximum number of peers from which to ask for the same blocks in parallel. - /// - /// This allows downloading announced blocks from multiple peers. Decrease to save - /// traffic and risk increased latency. - #[structopt(long = "max-parallel-downloads", value_name = "COUNT", default_value = "5")] - pub max_parallel_downloads: u32, - - #[allow(missing_docs)] - #[structopt(flatten)] - pub node_key_params: NodeKeyParams, - - /// Experimental feature flag. - #[structopt(long = "use-yamux-flow-control")] - pub use_yamux_flow_control: bool, -} - -impl NetworkConfigurationParams { - /// Fill the given `NetworkConfiguration` by looking at the cli parameters. - pub fn update_config( - &self, - mut config: &mut Configuration, - config_path: PathBuf, - client_id: String, - is_dev: bool, - ) -> error::Result<()> { - config.network.boot_nodes.extend(self.bootnodes.clone()); - config.network.config_path = Some(config_path.clone()); - config.network.net_config_path = Some(config_path.clone()); - - config.network.reserved_nodes.extend(self.reserved_nodes.clone()); - if self.reserved_only { - config.network.non_reserved_mode = NonReservedPeerMode::Deny; - } - - config.network.listen_addresses.extend(self.listen_addr.iter().cloned()); - if config.network.listen_addresses.is_empty() { - let port = match self.port { - Some(port) => port, - None => 30333, - }; - - config.network.listen_addresses = vec![ - iter::once(Protocol::Ip4(Ipv4Addr::new(0, 0, 0, 0))) - .chain(iter::once(Protocol::Tcp(port))) - .collect() - ]; - } - - config.network.client_version = client_id; - self.node_key_params.update_config(&mut config, Some(&config_path))?; - - config.network.in_peers = self.in_peers; - config.network.out_peers = self.out_peers; - - config.network.transport = TransportConfig::Normal { - enable_mdns: !is_dev && !self.no_mdns, - allow_private_ipv4: !self.no_private_ipv4, - wasm_external_transport: None, - use_yamux_flow_control: self.use_yamux_flow_control, - }; - - config.network.max_parallel_downloads = self.max_parallel_downloads; - - Ok(()) - } -} diff --git a/client/cli/src/params/network_params.rs b/client/cli/src/params/network_params.rs new file mode 100644 index 0000000000000000000000000000000000000000..253585544d2600dd00bf9ba7fea3a6bca60b9a7d --- /dev/null +++ b/client/cli/src/params/network_params.rs @@ -0,0 +1,165 @@ +// This file is part of Substrate. + +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use crate::params::node_key_params::NodeKeyParams; +use sc_network::{ + config::{NetworkConfiguration, NodeKeyConfig, NonReservedPeerMode, TransportConfig}, + multiaddr::Protocol, +}; +use sc_service::{ChainSpec, config::{Multiaddr, MultiaddrWithPeerId}}; +use std::path::PathBuf; +use structopt::StructOpt; + +/// Parameters used to create the network configuration. +#[derive(Debug, StructOpt)] +pub struct NetworkParams { + /// Specify a list of bootnodes. + #[structopt(long = "bootnodes", value_name = "ADDR")] + pub bootnodes: Vec, + + /// Specify a list of reserved node addresses. + #[structopt(long = "reserved-nodes", value_name = "ADDR")] + pub reserved_nodes: Vec, + + /// 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, + + /// The public address that other nodes will use to connect to it. + /// This can be used if there's a proxy in front of this node. + #[structopt(long, value_name = "PUBLIC_ADDR")] + pub public_addr: Vec, + + /// Listen on this multiaddress. + #[structopt(long = "listen-addr", value_name = "LISTEN_ADDR")] + pub listen_addr: Vec, + + /// Specify p2p protocol TCP port. + #[structopt(long = "port", value_name = "PORT", conflicts_with_all = &[ "listen-addr" ])] + pub port: Option, + + /// Forbid connecting to private IPv4 addresses (as specified in + /// [RFC1918](https://tools.ietf.org/html/rfc1918)), unless the address was passed with + /// `--reserved-nodes` or `--bootnodes`. + #[structopt(long = "no-private-ipv4")] + pub no_private_ipv4: bool, + + /// Specify the number of outgoing connections we're trying to maintain. + #[structopt(long = "out-peers", value_name = "COUNT", default_value = "25")] + pub out_peers: u32, + + /// Specify the maximum number of incoming connections we're accepting. + #[structopt(long = "in-peers", value_name = "COUNT", default_value = "25")] + pub in_peers: u32, + + /// 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, + + /// Maximum number of peers from which to ask for the same blocks in parallel. + /// + /// This allows downloading announced blocks from multiple peers. Decrease to save + /// traffic and risk increased latency. + #[structopt( + long = "max-parallel-downloads", + value_name = "COUNT", + default_value = "5" + )] + pub max_parallel_downloads: u32, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub node_key_params: NodeKeyParams, + + /// Disable the yamux flow control. This option will be removed in the future once there is + /// enough confidence that this feature is properly working. + #[structopt(long)] + pub no_yamux_flow_control: bool, + + /// Enable peer discovery on local networks. + /// + /// By default this option is true for `--dev` and false otherwise. + #[structopt(long)] + pub discover_local: bool, +} + +impl NetworkParams { + /// Fill the given `NetworkConfiguration` by looking at the cli parameters. + pub fn network_config( + &self, + chain_spec: &Box, + is_dev: bool, + net_config_path: Option, + client_id: &str, + node_name: &str, + node_key: NodeKeyConfig, + ) -> NetworkConfiguration { + let port = self.port.unwrap_or(30333); + + let listen_addresses = if self.listen_addr.is_empty() { + vec![ + Multiaddr::empty() + .with(Protocol::Ip6([0, 0, 0, 0, 0, 0, 0, 0].into())) + .with(Protocol::Tcp(port)), + Multiaddr::empty() + .with(Protocol::Ip4([0, 0, 0, 0].into())) + .with(Protocol::Tcp(port)), + ] + } else { + self.listen_addr.clone() + }; + + let public_addresses = self.public_addr.clone(); + + let mut boot_nodes = chain_spec.boot_nodes().to_vec(); + boot_nodes.extend(self.bootnodes.clone()); + + NetworkConfiguration { + boot_nodes, + net_config_path, + reserved_nodes: self.reserved_nodes.clone(), + non_reserved_mode: if self.reserved_only { + NonReservedPeerMode::Deny + } else { + NonReservedPeerMode::Accept + }, + listen_addresses, + public_addresses, + notifications_protocols: Vec::new(), + node_key, + node_name: node_name.to_string(), + client_version: client_id.to_string(), + in_peers: self.in_peers, + out_peers: self.out_peers, + transport: TransportConfig::Normal { + enable_mdns: !is_dev && !self.no_mdns, + allow_private_ipv4: !self.no_private_ipv4, + wasm_external_transport: None, + use_yamux_flow_control: !self.no_yamux_flow_control, + }, + max_parallel_downloads: self.max_parallel_downloads, + allow_non_globals_in_dht: self.discover_local || is_dev, + } + } +} diff --git a/client/cli/src/params/node_key_params.rs b/client/cli/src/params/node_key_params.rs index c55ec8ee692db5715c88414c905f87fc20ca51fa..689cc6c681c8339e79937e3dbb8ac9e3cfe04c6f 100644 --- a/client/cli/src/params/node_key_params.rs +++ b/client/cli/src/params/node_key_params.rs @@ -1,27 +1,28 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . -use std::{path::PathBuf, str::FromStr}; -use structopt::StructOpt; -use sc_service::Configuration; use sc_network::config::NodeKeyConfig; use sp_core::H256; +use std::{path::PathBuf, str::FromStr}; +use structopt::StructOpt; -use crate::error; use crate::arg_enums::NodeKeyType; +use crate::error; /// 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` @@ -30,7 +31,7 @@ const NODE_KEY_ED25519_FILE: &str = "secret_ed25519"; /// Parameters used to create the `NodeKeyConfig`, which determines the keypair /// used for libp2p networking. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, StructOpt)] pub struct NodeKeyParams { /// The secret key to use for libp2p networking. /// @@ -93,31 +94,23 @@ pub struct NodeKeyParams { impl NodeKeyParams { /// Create a `NodeKeyConfig` from the given `NodeKeyParams` in the context /// of an optional network config storage directory. - pub fn update_config<'a>( - &self, - mut config: &'a mut Configuration, - net_config_path: Option<&PathBuf>, - ) -> error::Result<&'a NodeKeyConfig> { - config.network.node_key = match self.node_key_type { + pub fn node_key(&self, net_config_dir: &PathBuf) -> error::Result { + Ok(match self.node_key_type { NodeKeyType::Ed25519 => { let secret = if let Some(node_key) = self.node_key.as_ref() { parse_ed25519_secret(node_key)? } else { - let path = self.node_key_file.clone() - .or_else(|| net_config_path.map(|d| d.join(NODE_KEY_ED25519_FILE))); + let path = self + .node_key_file + .clone() + .unwrap_or_else(|| net_config_dir.join(NODE_KEY_ED25519_FILE)); - if let Some(path) = path { - sc_network::config::Secret::File(path) - } else { - sc_network::config::Secret::New - } + sc_network::config::Secret::File(path) }; NodeKeyConfig::Ed25519(secret) } - }; - - Ok(&config.network.node_key) + }) } } @@ -128,114 +121,107 @@ fn invalid_node_key(e: impl std::fmt::Display) -> error::Error { /// Parse a Ed25519 secret key from a hex string into a `sc_network::Secret`. fn parse_ed25519_secret(hex: &str) -> error::Result { - H256::from_str(&hex).map_err(invalid_node_key).and_then(|bytes| - sc_network::config::identity::ed25519::SecretKey::from_bytes(bytes) - .map(sc_network::config::Secret::Input) - .map_err(invalid_node_key)) + H256::from_str(&hex) + .map_err(invalid_node_key) + .and_then(|bytes| { + sc_network::config::identity::ed25519::SecretKey::from_bytes(bytes) + .map(sc_network::config::Secret::Input) + .map_err(invalid_node_key) + }) } #[cfg(test)] mod tests { - use sc_network::config::identity::ed25519; use super::*; + use sc_network::config::identity::ed25519; #[test] fn test_node_key_config_input() { - fn secret_input(net_config_dir: Option<&PathBuf>) -> error::Result<()> { + fn secret_input(net_config_dir: &PathBuf) -> error::Result<()> { NodeKeyType::variants().iter().try_for_each(|t| { - let mut config = Configuration::default(); let node_key_type = NodeKeyType::from_str(t).unwrap(); let sk = match node_key_type { - NodeKeyType::Ed25519 => ed25519::SecretKey::generate().as_ref().to_vec() + NodeKeyType::Ed25519 => ed25519::SecretKey::generate().as_ref().to_vec(), }; let params = NodeKeyParams { node_key_type, node_key: Some(format!("{:x}", H256::from_slice(sk.as_ref()))), - node_key_file: None + node_key_file: None, }; - params.update_config(&mut config, net_config_dir).and_then(|c| match c { + params.node_key(net_config_dir).and_then(|c| match c { NodeKeyConfig::Ed25519(sc_network::config::Secret::Input(ref ski)) - if node_key_type == NodeKeyType::Ed25519 && - &sk[..] == ski.as_ref() => Ok(()), - _ => Err(error::Error::Input("Unexpected node key config".into())) + if node_key_type == NodeKeyType::Ed25519 && &sk[..] == ski.as_ref() => + { + Ok(()) + } + _ => Err(error::Error::Input("Unexpected node key config".into())), }) }) } - assert!(secret_input(None).is_ok()); - assert!(secret_input(Some(&PathBuf::from_str("x").unwrap())).is_ok()); + assert!(secret_input(&PathBuf::from_str("x").unwrap()).is_ok()); } #[test] fn test_node_key_config_file() { - fn secret_file(net_config_dir: Option<&PathBuf>) -> error::Result<()> { + fn secret_file(net_config_dir: &PathBuf) -> error::Result<()> { NodeKeyType::variants().iter().try_for_each(|t| { - let mut config = Configuration::default(); let node_key_type = NodeKeyType::from_str(t).unwrap(); let tmp = tempfile::Builder::new().prefix("alice").tempdir()?; let file = tmp.path().join(format!("{}_mysecret", t)).to_path_buf(); let params = NodeKeyParams { node_key_type, node_key: None, - node_key_file: Some(file.clone()) + node_key_file: Some(file.clone()), }; - params.update_config(&mut config, net_config_dir).and_then(|c| match c { + params.node_key(net_config_dir).and_then(|c| match c { NodeKeyConfig::Ed25519(sc_network::config::Secret::File(ref f)) - if node_key_type == NodeKeyType::Ed25519 && f == &file => Ok(()), - _ => Err(error::Error::Input("Unexpected node key config".into())) + if node_key_type == NodeKeyType::Ed25519 && f == &file => + { + Ok(()) + } + _ => Err(error::Error::Input("Unexpected node key config".into())), }) }) } - assert!(secret_file(None).is_ok()); - assert!(secret_file(Some(&PathBuf::from_str("x").unwrap())).is_ok()); + assert!(secret_file(&PathBuf::from_str("x").unwrap()).is_ok()); } #[test] fn test_node_key_config_default() { fn with_def_params(f: F) -> error::Result<()> where - F: Fn(NodeKeyParams) -> error::Result<()> + F: Fn(NodeKeyParams) -> error::Result<()>, { NodeKeyType::variants().iter().try_for_each(|t| { let node_key_type = NodeKeyType::from_str(t).unwrap(); f(NodeKeyParams { node_key_type, node_key: None, - node_key_file: None + node_key_file: None, }) }) } - fn no_config_dir() -> error::Result<()> { - with_def_params(|params| { - let mut config = Configuration::default(); - let typ = params.node_key_type; - params.update_config(&mut config, None) - .and_then(|c| match c { - NodeKeyConfig::Ed25519(sc_network::config::Secret::New) - if typ == NodeKeyType::Ed25519 => Ok(()), - _ => Err(error::Error::Input("Unexpected node key config".into())) - }) - }) - } - fn some_config_dir(net_config_dir: &PathBuf) -> error::Result<()> { with_def_params(|params| { - let mut config = Configuration::default(); let dir = PathBuf::from(net_config_dir.clone()); let typ = params.node_key_type; - params.update_config(&mut config, Some(net_config_dir)) + params + .node_key(net_config_dir) .and_then(move |c| match c { NodeKeyConfig::Ed25519(sc_network::config::Secret::File(ref f)) - if typ == NodeKeyType::Ed25519 && - f == &dir.join(NODE_KEY_ED25519_FILE) => Ok(()), - _ => Err(error::Error::Input("Unexpected node key config".into())) - }) + if typ == NodeKeyType::Ed25519 + && f == &dir.join(NODE_KEY_ED25519_FILE) => + { + Ok(()) + } + _ => Err(error::Error::Input("Unexpected node key config".into())), + }) }) } - assert!(no_config_dir().is_ok()); assert!(some_config_dir(&PathBuf::from_str("x").unwrap()).is_ok()); } } diff --git a/client/cli/src/params/offchain_worker_params.rs b/client/cli/src/params/offchain_worker_params.rs new file mode 100644 index 0000000000000000000000000000000000000000..f8d48edc4729d5f97e4f389fe78dd3cd794423b9 --- /dev/null +++ b/client/cli/src/params/offchain_worker_params.rs @@ -0,0 +1,78 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Offchain worker related configuration parameters. +//! +//! A subset of configuration parameters which are relevant to +//! the inner working of offchain workers. The usage is solely +//! targeted at handling input parameter parsing providing +//! a reasonable abstraction. + +use structopt::StructOpt; +use sc_service::config::OffchainWorkerConfig; +use sc_network::config::Role; + +use crate::error; +use crate::OffchainWorkerEnabled; + + +/// Offchain worker related parameters. +#[derive(Debug, StructOpt)] +pub struct OffchainWorkerParams { + /// 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", + possible_values = &OffchainWorkerEnabled::variants(), + case_insensitive = true, + default_value = "WhenValidating" + )] + pub enabled: OffchainWorkerEnabled, + + /// Enable Offchain Indexing API, which allows block import to write to Offchain DB. + /// + /// Enables a runtime to write directly to a offchain workers + /// DB during block import. + #[structopt( + long = "enable-offchain-indexing", + value_name = "ENABLE_OFFCHAIN_INDEXING" + )] + pub indexing_enabled: bool, +} + +impl OffchainWorkerParams { + /// Load spec to `Configuration` from `OffchainWorkerParams` and spec factory. + pub fn offchain_worker( + &self, + role: &Role, + ) -> error::Result + { + let enabled = match (&self.enabled, role) { + (OffchainWorkerEnabled::WhenValidating, Role::Authority { .. }) => true, + (OffchainWorkerEnabled::Always, _) => true, + (OffchainWorkerEnabled::Never, _) => false, + (OffchainWorkerEnabled::WhenValidating, _) => false, + }; + + let indexing_enabled = enabled && self.indexing_enabled; + + Ok(OffchainWorkerConfig { enabled, indexing_enabled }) + } +} diff --git a/client/cli/src/params/pruning_params.rs b/client/cli/src/params/pruning_params.rs index 8d069a299ff39b7068fed931b4c71dadc7d763c2..7db808e6d8f2f8e249ff0e057a05297bfcf92a72 100644 --- a/client/cli/src/params/pruning_params.rs +++ b/client/cli/src/params/pruning_params.rs @@ -1,26 +1,27 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 structopt::StructOpt; -use sc_service::{Configuration, PruningMode}; +// along with this program. If not, see . use crate::error; +use sc_service::{PruningMode, Role}; +use structopt::StructOpt; /// Parameters to define the pruning mode -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, StructOpt)] pub struct PruningParams { /// Specify the state pruning mode, a number of blocks to keep or 'archive'. /// @@ -32,18 +33,13 @@ pub struct PruningParams { } impl PruningParams { - /// Put block pruning CLI params into `config` object. - pub fn update_config( - &self, - mut config: &mut Configuration, - role: &sc_service::Role, - unsafe_pruning: bool, - ) -> error::Result<()> { + /// Get the pruning value from the parameters + pub fn pruning(&self, unsafe_pruning: bool, role: &Role) -> error::Result { // 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 &self.pruning { + Ok(match &self.pruning { Some(ref s) if s == "archive" => PruningMode::ArchiveAll, None if role.is_network_authority() => PruningMode::ArchiveAll, None => PruningMode::default(), @@ -51,16 +47,15 @@ impl PruningParams { if role.is_network_authority() && !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() + 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()))? - ) - }, - }; - - Ok(()) + PruningMode::keep_blocks(s.parse().map_err(|_| { + error::Error::Input("Invalid pruning mode specified".to_string()) + })?) + } + }) } } diff --git a/client/cli/src/params/shared_params.rs b/client/cli/src/params/shared_params.rs index 41b9cce8264cc0ce46de7d81661b396f4275266b..ad9ab04070563ac5c7ea5939688f410a3257f232 100644 --- a/client/cli/src/params/shared_params.rs +++ b/client/cli/src/params/shared_params.rs @@ -1,112 +1,75 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . +use sc_service::config::BasePath; use std::path::PathBuf; use structopt::StructOpt; -use app_dirs::{AppInfo, AppDataType}; -use sc_service::{ - Configuration, config::DatabaseConfig, ChainSpec, -}; - -use crate::VersionInfo; -use crate::error; - -/// default sub directory to store database -const DEFAULT_DB_CONFIG_PATH : &'static str = "db"; /// Shared parameters used by all `CoreParams`. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, StructOpt)] pub struct SharedParams { /// Specify the chain specification (one of dev, local, or staging). - #[structopt(long = "chain", value_name = "CHAIN_SPEC")] + #[structopt(long, value_name = "CHAIN_SPEC")] pub chain: Option, /// Specify the development chain. - #[structopt(long = "dev")] + #[structopt(long, conflicts_with_all = &["chain"])] pub dev: bool, /// Specify custom base path. - #[structopt(long = "base-path", short = "d", value_name = "PATH", parse(from_os_str))] + #[structopt(long, short = "d", value_name = "PATH", parse(from_os_str))] pub base_path: Option, /// Sets a custom logging filter. Syntax is =, e.g. -lsync=debug. /// /// Log levels (least to most verbose) are error, warn, info, debug, and trace. /// By default, all targets log `info`. The global log level can be set with -l. - #[structopt(short = "l", long = "log", value_name = "LOG_PATTERN")] - pub log: Option, + #[structopt(short = "l", long, value_name = "LOG_PATTERN")] + pub log: Vec, } impl SharedParams { - /// Load spec to `Configuration` from `SharedParams` and spec factory. - pub fn update_config<'a, F>( - &self, - mut config: &'a mut Configuration, - spec_factory: F, - version: &VersionInfo, - ) -> error::Result<&'a dyn ChainSpec> where - F: FnOnce(&str) -> Result, String>, - { - let chain_key = match self.chain { - Some(ref chain) => chain.clone(), - None => if self.dev { "dev".into() } else { "".into() } - }; - let spec = spec_factory(&chain_key)?; - config.network.boot_nodes = spec.boot_nodes().to_vec(); - config.telemetry_endpoints = spec.telemetry_endpoints().clone(); - - config.chain_spec = Some(spec); + /// Specify custom base path. + pub fn base_path(&self) -> Option { + self.base_path.clone().map(Into::into) + } - if config.config_dir.is_none() { - config.config_dir = Some(base_path(self, version)); - } + /// Specify the development chain. + pub fn is_dev(&self) -> bool { + self.dev + } - if config.database.is_none() { - config.database = Some(DatabaseConfig::Path { - path: config - .in_chain_config_dir(DEFAULT_DB_CONFIG_PATH) - .expect("We provided a base_path/config_dir."), - cache_size: None, - }); + /// Get the chain spec for the parameters provided + pub fn chain_id(&self, is_dev: bool) -> String { + match self.chain { + Some(ref chain) => chain.clone(), + None => { + if is_dev { + "dev".into() + } else { + "".into() + } + } } - - Ok(config.expect_chain_spec()) } - /// Initialize substrate. This must be done only once. - /// - /// This method: - /// - /// 1. Set the panic handler - /// 2. Raise the FD limit - /// 3. Initialize the logger - pub fn init(&self, version: &VersionInfo) -> error::Result<()> { - crate::init(self.log.as_ref().map(|v| v.as_ref()).unwrap_or(""), version) + /// Get the filters for the logging + pub fn log_filters(&self) -> &[String] { + &self.log } } - -fn base_path(cli: &SharedParams, version: &VersionInfo) -> PathBuf { - cli.base_path.clone() - .unwrap_or_else(|| - app_dirs::get_app_root( - AppDataType::UserData, - &AppInfo { - name: version.executable_name, - author: version.author - } - ).expect("app directories exist on all supported platforms; qed") - ) -} diff --git a/client/cli/src/params/transaction_pool_params.rs b/client/cli/src/params/transaction_pool_params.rs index 3468c12243b3fe75d872891aebf12b3df6f0e356..3ad278426922ec99ccc42e192cbda9db1d04207b 100644 --- a/client/cli/src/params/transaction_pool_params.rs +++ b/client/cli/src/params/transaction_pool_params.rs @@ -1,29 +1,31 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . +use sc_service::config::TransactionPoolOptions; use structopt::StructOpt; -use sc_service::Configuration; -use crate::error; /// Parameters used to create the pool configuration. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, StructOpt)] pub struct TransactionPoolParams { /// Maximum number of transactions in the transaction pool. #[structopt(long = "pool-limit", value_name = "COUNT", default_value = "8192")] pub pool_limit: usize, + /// Maximum number of kilobytes of all transactions stored in the pool. #[structopt(long = "pool-kbytes", value_name = "COUNT", default_value = "20480")] pub pool_kbytes: usize, @@ -31,19 +33,18 @@ pub struct TransactionPoolParams { impl TransactionPoolParams { /// Fill the given `PoolConfiguration` by looking at the cli parameters. - pub fn update_config( - &self, - config: &mut Configuration, - ) -> error::Result<()> { + pub fn transaction_pool(&self) -> TransactionPoolOptions { + let mut opts = TransactionPoolOptions::default(); + // ready queue - config.transaction_pool.ready.count = self.pool_limit; - config.transaction_pool.ready.total_bytes = self.pool_kbytes * 1024; + opts.ready.count = self.pool_limit; + opts.ready.total_bytes = self.pool_kbytes * 1024; // future queue let factor = 10; - config.transaction_pool.future.count = self.pool_limit / factor; - config.transaction_pool.future.total_bytes = self.pool_kbytes * 1024 / factor; + opts.future.count = self.pool_limit / factor; + opts.future.total_bytes = self.pool_kbytes * 1024 / factor; - Ok(()) + opts } } diff --git a/client/cli/src/runner.rs b/client/cli/src/runner.rs new file mode 100644 index 0000000000000000000000000000000000000000..05445c9d85d85887df7e9d52120546408247c90b --- /dev/null +++ b/client/cli/src/runner.rs @@ -0,0 +1,269 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use crate::CliConfiguration; +use crate::Result; +use crate::Subcommand; +use crate::SubstrateCli; +use chrono::prelude::*; +use futures::pin_mut; +use futures::select; +use futures::{future, future::FutureExt, Future}; +use log::info; +use sc_service::{Configuration, TaskType, TaskManager}; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; +use sp_utils::metrics::{TOKIO_THREADS_ALIVE, TOKIO_THREADS_TOTAL}; +use std::{fmt::Debug, marker::PhantomData, str::FromStr, sync::Arc}; +use sc_client_api::{UsageProvider, BlockBackend, StorageProvider}; + +#[cfg(target_family = "unix")] +async fn main(func: F) -> std::result::Result<(), Box> +where + F: Future> + future::FusedFuture, + E: 'static + std::error::Error, +{ + use tokio::signal::unix::{signal, SignalKind}; + + let mut stream_int = signal(SignalKind::interrupt())?; + let mut stream_term = signal(SignalKind::terminate())?; + + let t1 = stream_int.recv().fuse(); + let t2 = stream_term.recv().fuse(); + let t3 = func; + + pin_mut!(t1, t2, t3); + + select! { + _ = t1 => {}, + _ = t2 => {}, + res = t3 => res?, + } + + Ok(()) +} + +#[cfg(not(unix))] +async fn main(func: F) -> std::result::Result<(), Box> +where + F: Future> + future::FusedFuture, + E: 'static + std::error::Error, +{ + use tokio::signal::ctrl_c; + + let t1 = ctrl_c().fuse(); + let t2 = func; + + pin_mut!(t1, t2); + + select! { + _ = t1 => {}, + res = t2 => res?, + } + + Ok(()) +} + +/// Build a tokio runtime with all features +pub fn build_runtime() -> std::result::Result { + tokio::runtime::Builder::new() + .threaded_scheduler() + .on_thread_start(|| { + TOKIO_THREADS_ALIVE.inc(); + TOKIO_THREADS_TOTAL.inc(); + }) + .on_thread_stop(|| { + TOKIO_THREADS_ALIVE.dec(); + }) + .enable_all() + .build() +} + +fn run_until_exit( + mut tokio_runtime: tokio::runtime::Runtime, + future: FUT, + mut task_manager: TaskManager, +) -> Result<()> +where + FUT: Future> + future::Future, + ERR: 'static + std::error::Error, +{ + let f = future.fuse(); + pin_mut!(f); + + tokio_runtime.block_on(main(f)).map_err(|e| e.to_string())?; + + task_manager.terminate(); + drop(tokio_runtime); + + Ok(()) +} + +/// A Substrate CLI runtime that can be used to run a node or a command +pub struct Runner { + config: Configuration, + tokio_runtime: tokio::runtime::Runtime, + phantom: PhantomData, +} + +impl Runner { + /// Create a new runtime with the command provided in argument + pub fn new(cli: &C, command: &T) -> Result> { + let tokio_runtime = build_runtime()?; + let runtime_handle = tokio_runtime.handle().clone(); + + let task_executor = move |fut, task_type| { + match task_type { + TaskType::Async => { runtime_handle.spawn(fut); } + TaskType::Blocking => { + runtime_handle.spawn(async move { + // `spawn_blocking` is looking for the current runtime, and as such has to + // be called from within `spawn`. + tokio::task::spawn_blocking(move || futures::executor::block_on(fut)) + }); + } + } + }; + + Ok(Runner { + config: command.create_configuration(cli, task_executor.into())?, + tokio_runtime, + phantom: PhantomData, + }) + } + + /// Log information about the node itself. + /// + /// # Example: + /// + /// ```text + /// 2020-06-03 16:14:21 Substrate Node + /// 2020-06-03 16:14:21 ✌️ version 2.0.0-rc3-f4940588c-x86_64-linux-gnu + /// 2020-06-03 16:14:21 ❤️ by Parity Technologies , 2017-2020 + /// 2020-06-03 16:14:21 📋 Chain specification: Flaming Fir + /// 2020-06-03 16:14:21 🏷 Node name: jolly-rod-7462 + /// 2020-06-03 16:14:21 👤 Role: FULL + /// 2020-06-03 16:14:21 💾 Database: RocksDb at /tmp/c/chains/flamingfir7/db + /// 2020-06-03 16:14:21 ⛓ Native runtime: node-251 (substrate-node-1.tx1.au10) + /// ``` + fn print_node_infos(&self) { + info!("{}", C::impl_name()); + info!("✌️ version {}", C::impl_version()); + info!( + "❤️ by {}, {}-{}", + C::author(), + C::copyright_start_year(), + Local::today().year(), + ); + info!("📋 Chain specification: {}", self.config.chain_spec.name()); + info!("🏷 Node name: {}", self.config.network.node_name); + info!("👤 Role: {}", self.config.display_role()); + info!("💾 Database: {} at {}", + self.config.database, + self.config.database.path().map_or_else(|| "".to_owned(), |p| p.display().to_string()) + ); + info!("⛓ Native runtime: {}", C::native_runtime_version(&self.config.chain_spec)); + } + + /// A helper function that runs a future with tokio and stops if the process receives the signal + /// `SIGTERM` or `SIGINT`. + pub fn run_subcommand(self, subcommand: &Subcommand, builder: BU) + -> Result<()> + where + BU: FnOnce(Configuration) + -> sc_service::error::Result<(Arc, Arc, IQ, TaskManager)>, + B: BlockT + for<'de> serde::Deserialize<'de>, + BA: sc_client_api::backend::Backend + 'static, + IQ: sc_service::ImportQueue + 'static, + ::Hash: FromStr, + <::Hash as FromStr>::Err: Debug, + <<::Header as HeaderT>::Number as FromStr>::Err: Debug, + CL: UsageProvider + BlockBackend + StorageProvider + Send + Sync + + 'static, + { + let chain_spec = self.config.chain_spec.cloned_box(); + let network_config = self.config.network.clone(); + let db_config = self.config.database.clone(); + + match subcommand { + Subcommand::BuildSpec(cmd) => cmd.run(chain_spec, network_config), + Subcommand::ExportBlocks(cmd) => { + let (client, _, _, task_manager) = builder(self.config)?; + run_until_exit(self.tokio_runtime, cmd.run(client, db_config), task_manager) + } + Subcommand::ImportBlocks(cmd) => { + let (client, _, import_queue, task_manager) = builder(self.config)?; + run_until_exit(self.tokio_runtime, cmd.run(client, import_queue), task_manager) + } + Subcommand::CheckBlock(cmd) => { + let (client, _, import_queue, task_manager) = builder(self.config)?; + run_until_exit(self.tokio_runtime, cmd.run(client, import_queue), task_manager) + } + Subcommand::Revert(cmd) => { + let (client, backend, _, task_manager) = builder(self.config)?; + run_until_exit(self.tokio_runtime, cmd.run(client, backend), task_manager) + }, + Subcommand::PurgeChain(cmd) => cmd.run(db_config), + Subcommand::ExportState(cmd) => { + let (client, _, _, task_manager) = builder(self.config)?; + run_until_exit(self.tokio_runtime, cmd.run(client, chain_spec), task_manager) + }, + } + } + + /// A helper function that runs a node with tokio and stops if the process receives the signal + /// `SIGTERM` or `SIGINT`. + pub fn run_node_until_exit( + mut self, + initialise: impl FnOnce(Configuration) -> sc_service::error::Result, + ) -> Result<()> { + self.print_node_infos(); + let mut task_manager = initialise(self.config)?; + self.tokio_runtime.block_on(main(task_manager.future().fuse())) + .map_err(|e| e.to_string())?; + task_manager.terminate(); + drop(self.tokio_runtime); + Ok(()) + } + + /// A helper function that runs a command with the configuration of this node + pub fn sync_run(self, runner: impl FnOnce(Configuration) -> Result<()>) -> Result<()> { + runner(self.config) + } + + /// A helper function that runs a future with tokio and stops if the process receives + /// the signal SIGTERM or SIGINT + pub fn async_run( + self, runner: impl FnOnce(Configuration) -> Result<(FUT, TaskManager)>, + ) -> Result<()> + where + FUT: Future>, + { + let (future, task_manager) = runner(self.config)?; + run_until_exit(self.tokio_runtime, future, task_manager) + } + + /// Get an immutable reference to the node Configuration + pub fn config(&self) -> &Configuration { + &self.config + } + + /// Get a mutable reference to the node Configuration + pub fn config_mut(&mut self) -> &mut Configuration { + &mut self.config + } +} diff --git a/client/cli/src/runtime.rs b/client/cli/src/runtime.rs deleted file mode 100644 index 5c9bc7508858dfb4d0c896ef15f08504449f1900..0000000000000000000000000000000000000000 --- a/client/cli/src/runtime.rs +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2017-2020 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::sync::Arc; - -use futures::{Future, future, future::FutureExt}; -use futures::select; -use futures::pin_mut; -use sc_service::{AbstractService, Configuration}; -use sp_utils::metrics::{TOKIO_THREADS_ALIVE, TOKIO_THREADS_TOTAL}; -use crate::error; - -#[cfg(target_family = "unix")] -async fn main(func: F) -> Result<(), Box> -where - F: Future> + future::FusedFuture, - E: 'static + std::error::Error, -{ - use tokio::signal::unix::{signal, SignalKind}; - - let mut stream_int = signal(SignalKind::interrupt())?; - let mut stream_term = signal(SignalKind::terminate())?; - - let t1 = stream_int.recv().fuse(); - let t2 = stream_term.recv().fuse(); - let t3 = func; - - pin_mut!(t1, t2, t3); - - select! { - _ = t1 => {}, - _ = t2 => {}, - res = t3 => res?, - } - - Ok(()) -} - -#[cfg(not(unix))] -async fn main(func: F) -> Result<(), Box> -where - F: Future> + future::FusedFuture, - E: 'static + std::error::Error, -{ - use tokio::signal::ctrl_c; - - let t1 = ctrl_c().fuse(); - let t2 = func; - - pin_mut!(t1, t2); - - select! { - _ = t1 => {}, - res = t2 => res?, - } - - Ok(()) -} - -fn build_runtime() -> Result { - tokio::runtime::Builder::new() - .thread_name("main-tokio-") - .threaded_scheduler() - .on_thread_start(||{ - TOKIO_THREADS_ALIVE.inc(); - TOKIO_THREADS_TOTAL.inc(); - }) - .on_thread_stop(||{ - TOKIO_THREADS_ALIVE.dec(); - }) - .enable_all() - .build() -} - -/// A helper function that runs a future with tokio and stops if the process receives the signal -/// SIGTERM or SIGINT -pub fn run_until_exit( - mut config: Configuration, - future_builder: F, -) -> error::Result<()> -where - F: FnOnce(Configuration) -> error::Result, - FUT: Future> + future::Future, - ERR: 'static + std::error::Error, -{ - let mut runtime = build_runtime()?; - - config.task_executor = { - let runtime_handle = runtime.handle().clone(); - Some(Arc::new(move |fut| { runtime_handle.spawn(fut); })) - }; - - let f = future_builder(config)?; - let f = f.fuse(); - pin_mut!(f); - - runtime.block_on(main(f)).map_err(|e| e.to_string())?; - - Ok(()) -} - -/// A helper function that runs an `AbstractService` with tokio and stops if the process receives -/// the signal SIGTERM or SIGINT -pub fn run_service_until_exit( - mut config: Configuration, - service_builder: F, -) -> error::Result<()> -where - F: FnOnce(Configuration) -> Result, - T: AbstractService + Unpin, -{ - let mut runtime = build_runtime()?; - - config.task_executor = { - let runtime_handle = runtime.handle().clone(); - Some(Arc::new(move |fut| { runtime_handle.spawn(fut); })) - }; - - let service = service_builder(config)?; - - let informant_future = sc_informant::build(&service, sc_informant::OutputFormat::Coloured); - let _informant_handle = runtime.spawn(informant_future); - - // 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 - // and drop the runtime first. - let _telemetry = service.telemetry(); - - let f = service.fuse(); - pin_mut!(f); - - runtime.block_on(main(f)).map_err(|e| e.to_string())?; - drop(runtime); - - Ok(()) -} diff --git a/client/consensus/aura/Cargo.toml b/client/consensus/aura/Cargo.toml index f0fe368acbb037f0b9181263889baa31d3e3f660..d080fd39d0e9bb56798b816359c751da04e0f833 100644 --- a/client/consensus/aura/Cargo.toml +++ b/client/consensus/aura/Cargo.toml @@ -1,48 +1,48 @@ [package] name = "sc-consensus-aura" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] description = "Aura consensus algorithm for substrate" edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-application-crypto = { version = "2.0.0-alpha.5", path = "../../../primitives/application-crypto" } -sp-consensus-aura = { version = "0.8.0-alpha.5", path = "../../../primitives/consensus/aura" } -sp-block-builder = { version = "2.0.0-alpha.5", path = "../../../primitives/block-builder" } -sc-block-builder = { version = "0.8.0-alpha.5", path = "../../../client/block-builder" } -sc-client = { version = "0.8.0-alpha.5", path = "../../" } -sc-client-api = { version = "2.0.0-alpha.5", path = "../../api" } -codec = { package = "parity-scale-codec", version = "1.3.0" } -sp-consensus = { version = "0.8.0-alpha.5", path = "../../../primitives/consensus/common" } +sp-application-crypto = { version = "2.0.0-rc4", path = "../../../primitives/application-crypto" } +sp-consensus-aura = { version = "0.8.0-rc4", path = "../../../primitives/consensus/aura" } +sp-block-builder = { version = "2.0.0-rc4", path = "../../../primitives/block-builder" } +sc-block-builder = { version = "0.8.0-rc4", path = "../../../client/block-builder" } +sc-client-api = { version = "2.0.0-rc4", path = "../../api" } +codec = { package = "parity-scale-codec", version = "1.3.1" } +sp-consensus = { version = "0.8.0-rc4", path = "../../../primitives/consensus/common" } derive_more = "0.99.2" futures = "0.3.4" futures-timer = "3.0.1" -sp-inherents = { version = "2.0.0-alpha.5", path = "../../../primitives/inherents" } -sc-keystore = { version = "2.0.0-alpha.5", path = "../../keystore" } +sp-inherents = { version = "2.0.0-rc4", path = "../../../primitives/inherents" } +sc-keystore = { version = "2.0.0-rc4", path = "../../keystore" } log = "0.4.8" parking_lot = "0.10.0" -sp-core = { version = "2.0.0-alpha.5", path = "../../../primitives/core" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../../primitives/blockchain" } -sp-io = { version = "2.0.0-alpha.5", path = "../../../primitives/io" } -sp-version = { version = "2.0.0-alpha.5", path = "../../../primitives/version" } -sc-consensus-slots = { version = "0.8.0-alpha.5", path = "../slots" } -sp-api = { version = "2.0.0-alpha.5", path = "../../../primitives/api" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime" } -sp-timestamp = { version = "2.0.0-alpha.5", path = "../../../primitives/timestamp" } -sc-telemetry = { version = "2.0.0-alpha.5", path = "../../telemetry" } +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../../primitives/blockchain" } +sp-io = { version = "2.0.0-rc4", path = "../../../primitives/io" } +sp-version = { version = "2.0.0-rc4", path = "../../../primitives/version" } +sc-consensus-slots = { version = "0.8.0-rc4", path = "../slots" } +sp-api = { version = "2.0.0-rc4", path = "../../../primitives/api" } +sp-runtime = { version = "2.0.0-rc4", path = "../../../primitives/runtime" } +sp-timestamp = { version = "2.0.0-rc4", path = "../../../primitives/timestamp" } +sc-telemetry = { version = "2.0.0-rc4", path = "../../telemetry" } +prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.8.0-rc4"} [dev-dependencies] -sp-keyring = { version = "2.0.0-alpha.5", path = "../../../primitives/keyring" } -sc-executor = { version = "0.8.0-alpha.5", path = "../../executor" } -sc-network = { version = "0.8.0-alpha.5", path = "../../network" } -sc-network-test = { version = "0.8.0-dev", path = "../../network/test" } -sc-service = { version = "0.8.0-alpha.5", path = "../../service" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../../test-utils/runtime/client" } +sp-keyring = { version = "2.0.0-rc4", path = "../../../primitives/keyring" } +sc-executor = { version = "0.8.0-rc4", path = "../../executor" } +sc-network = { version = "0.8.0-rc4", path = "../../network" } +sc-network-test = { version = "0.8.0-rc4", path = "../../network/test" } +sc-service = { version = "0.8.0-rc4", default-features = false, path = "../../service" } +substrate-test-runtime-client = { version = "2.0.0-rc4", path = "../../../test-utils/runtime/client" } env_logger = "0.7.0" tempfile = "3.1.0" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/client/consensus/aura/src/digests.rs b/client/consensus/aura/src/digests.rs index 8dd42fc01def2ee6ac93c9551e68f038c658d428..3332e4c6a6dff99f2ee9ad367031fde15a33ada6 100644 --- a/client/consensus/aura/src/digests.rs +++ b/client/consensus/aura/src/digests.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Aura (Authority-Round) digests //! diff --git a/client/consensus/aura/src/lib.rs b/client/consensus/aura/src/lib.rs index 56674546d372bb67ed8b44ef0ece086e1febb653..19bc3bae6c30be2fde338fb6749dc3fd0ee7e2c7 100644 --- a/client/consensus/aura/src/lib.rs +++ b/client/consensus/aura/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Aura (Authority-round) consensus in substrate. //! @@ -30,12 +32,13 @@ #![forbid(missing_docs, unsafe_code)] use std::{ sync::Arc, time::Duration, thread, marker::PhantomData, hash::Hash, fmt::Debug, pin::Pin, - collections::HashMap + collections::HashMap, convert::{TryFrom, TryInto}, }; use futures::prelude::*; use parking_lot::Mutex; use log::{debug, info, trace}; +use prometheus_endpoint::Registry; use codec::{Encode, Decode, Codec}; @@ -46,18 +49,21 @@ use sp_consensus::{ use sp_consensus::import_queue::{ Verifier, BasicQueue, BoxJustificationImport, BoxFinalityProofImport, }; -use sc_client_api::backend::AuxStore; -use sc_client::BlockOf; +use sc_client_api::{backend::AuxStore, BlockOf}; use sp_blockchain::{ self, Result as CResult, well_known_cache_keys::{self, Id as CacheKeyId}, ProvideCache, HeaderBackend, }; use sp_block_builder::BlockBuilder as BlockBuilderApi; -use sp_runtime::{generic::{BlockId, OpaqueDigestItemId}, Justification}; +use sp_core::crypto::Public; +use sp_application_crypto::{AppKey, AppPublic}; +use sp_runtime::{ + generic::{BlockId, OpaqueDigestItemId}, + Justification, +}; use sp_runtime::traits::{Block as BlockT, Header, DigestItemFor, Zero, Member}; use sp_api::ProvideRuntimeApi; - -use sp_core::crypto::Pair; +use sp_core::{traits::BareCryptoStore, crypto::Pair}; use sp_inherents::{InherentDataProviders, InherentData}; use sp_timestamp::{ TimestampInherentData, InherentType as TimestampInherent, InherentError as TIError @@ -151,8 +157,8 @@ pub fn start_aura( E: Environment + Send + Sync + 'static, E::Proposer: Proposer>, P: Pair + Send + Sync, - P::Public: Hash + Member + Encode + Decode, - P::Signature: Hash + Member + Encode + Decode, + P::Public: AppPublic + Hash + Member + Encode + Decode, + P::Signature: TryFrom> + Hash + Member + Encode + Decode, I: BlockImport> + Send + Sync + 'static, Error: std::error::Error + Send + From + 'static, SO: SyncOracle + Send + Sync + Clone, @@ -200,8 +206,8 @@ impl sc_consensus_slots::SimpleSlotWorker for AuraW E::Proposer: Proposer>, I: BlockImport> + Send + Sync + 'static, P: Pair + Send + Sync, - P::Public: Member + Encode + Decode + Hash, - P::Signature: Member + Encode + Decode + Hash + Debug, + P::Public: AppPublic + Public + Member + Encode + Decode + Hash, + P::Signature: TryFrom> + Member + Encode + Decode + Hash + Debug, SO: SyncOracle + Send + Clone, Error: std::error::Error + Send + From + 'static, { @@ -211,7 +217,7 @@ impl sc_consensus_slots::SimpleSlotWorker for AuraW dyn Future> + Send + 'static >>; type Proposer = E::Proposer; - type Claim = P; + type Claim = P::Public; type EpochData = Vec>; fn logging_target(&self) -> &'static str { @@ -241,10 +247,11 @@ impl sc_consensus_slots::SimpleSlotWorker for AuraW 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, sp_application_crypto::key_types::AURA).ok() + }).and_then(|p| { + Some(p.public()) }) } @@ -265,11 +272,30 @@ impl sc_consensus_slots::SimpleSlotWorker for AuraW StorageChanges, B>, Self::Claim, Self::EpochData, - ) -> sp_consensus::BlockImportParams> + Send> { - Box::new(|header, header_hash, body, storage_changes, pair, _epoch| { + ) -> Result< + sp_consensus::BlockImportParams>, + sp_consensus::Error> + Send + 'static> + { + let keystore = self.keystore.clone(); + Box::new(move |header, header_hash, body, storage_changes, public, _epoch| { // sign the pre-sealed hash of the block and then // add it to a digest item. - let signature = pair.sign(header_hash.as_ref()); + let public_type_pair = public.to_public_crypto_pair(); + let public = public.to_raw_vec(); + let signature = keystore.read() + .sign_with( + as AppKey>::ID, + &public_type_pair, + header_hash.as_ref() + ) + .map_err(|e| sp_consensus::Error::CannotSign( + public.clone(), e.to_string(), + ))?; + let signature = signature.clone().try_into() + .map_err(|_| sp_consensus::Error::InvalidSignature( + signature, public + ))?; + let signature_digest_item = as CompatibleDigestItem

>::aura_seal(signature); let mut import_block = BlockImportParams::new(BlockOrigin::Own, header); @@ -278,7 +304,7 @@ impl sc_consensus_slots::SimpleSlotWorker for AuraW import_block.storage_changes = Some(storage_changes); import_block.fork_choice = Some(ForkChoiceStrategy::LongestChain); - import_block + Ok(import_block) }) } @@ -299,27 +325,28 @@ impl sc_consensus_slots::SimpleSlotWorker for AuraW fn proposing_remaining_duration( &self, head: &B::Header, - slot_info: &SlotInfo + slot_info: &SlotInfo, ) -> Option { - // never give more than 20 times more lenience. - const BACKOFF_CAP: u64 = 20; - let slot_remaining = self.slot_remaining_duration(slot_info); + let parent_slot = match find_pre_digest::(head) { Err(_) => return Some(slot_remaining), Ok(d) => d, }; - // we allow a lenience of the number of slots since the head of the - // chain was produced, minus 1 (since there is always a difference of at least 1) - // - // linear back-off. - // in normal cases we only attempt to issue blocks up to the end of the slot. - // when the chain has been stalled for a few slots, we give more lenience. - let slot_lenience = slot_info.number.saturating_sub(parent_slot + 1); - let slot_lenience = std::cmp::min(slot_lenience, BACKOFF_CAP); - let slot_lenience = Duration::from_secs(slot_lenience * slot_info.duration); - Some(slot_lenience + slot_remaining) + if let Some(slot_lenience) = + sc_consensus_slots::slot_lenience_exponential(parent_slot, slot_info) + { + debug!(target: "aura", + "No block for {} slots. Applying linear lenience of {}s", + slot_info.number.saturating_sub(parent_slot + 1), + slot_lenience.as_secs(), + ); + + Some(slot_remaining + slot_lenience) + } else { + Some(slot_remaining) + } } } @@ -331,8 +358,8 @@ impl SlotWorker for AuraWorker>, I: BlockImport> + Send + Sync + 'static, P: Pair + Send + Sync, - P::Public: Member + Encode + Decode + Hash, - P::Signature: Member + Encode + Decode + Hash + Debug, + P::Public: AppPublic + Member + Encode + Decode + Hash, + P::Signature: TryFrom> + Member + Encode + Decode + Hash + Debug, SO: SyncOracle + Send + Sync + Clone, Error: std::error::Error + Send + From + 'static, { @@ -452,8 +479,8 @@ fn check_header( info!( "Slot author is equivocating at slot {} with headers {:?} and {:?}", slot_num, - equivocation_proof.fst_header().hash(), - equivocation_proof.snd_header().hash(), + equivocation_proof.first_header.hash(), + equivocation_proof.second_header.hash(), ); } @@ -788,13 +815,15 @@ impl BlockImport for AuraBlockImport( +pub fn import_queue( slot_duration: SlotDuration, block_import: I, justification_import: Option>, finality_proof_import: Option>, client: Arc, inherent_data_providers: InherentDataProviders, + spawner: &S, + registry: Option<&Registry>, ) -> Result>, sp_consensus::Error> where B: BlockT, C::Api: BlockBuilderApi + AuraApi> + ApiExt, @@ -804,6 +833,7 @@ pub fn import_queue( P: Pair + Send + Sync + 'static, P::Public: Clone + Eq + Send + Sync + Hash + Debug + Encode + Decode, P::Signature: Encode + Decode, + S: sp_core::traits::SpawnNamed, { register_aura_inherent_data_provider(&inherent_data_providers, slot_duration.get())?; initialize_authorities_cache(&*client)?; @@ -813,11 +843,14 @@ pub fn import_queue( inherent_data_providers, phantom: PhantomData, }; + Ok(BasicQueue::new( verifier, Box::new(block_import), justification_import, finality_proof_import, + spawner, + registry, )) } @@ -830,14 +863,17 @@ mod tests { use sc_network::config::ProtocolConfig; use parking_lot::Mutex; use sp_keyring::sr25519::Keyring; - use sc_client::BlockchainEvents; + use sc_client_api::BlockchainEvents; use sp_consensus_aura::sr25519::AuthorityPair; + use sc_consensus_slots::SimpleSlotWorker; use std::task::Poll; use sc_block_builder::BlockBuilderProvider; + use sp_runtime::traits::Header as _; + use substrate_test_runtime_client::runtime::{Header, H256}; type Error = sp_blockchain::Error; - type TestClient = sc_client::Client< + type TestClient = substrate_test_runtime_client::client::Client< substrate_test_runtime_client::Backend, substrate_test_runtime_client::Executor, TestBlock, @@ -868,7 +904,7 @@ mod tests { type Proposal = future::Ready, Error>>; fn propose( - &mut self, + self, _: InherentData, digests: DigestFor, _: Duration, @@ -1017,4 +1053,55 @@ mod tests { Keyring::Charlie.public().into() ]); } + + #[test] + fn current_node_authority_should_claim_slot() { + let net = AuraTestNet::new(4); + + let mut authorities = vec![ + Keyring::Alice.public().into(), + Keyring::Bob.public().into(), + Keyring::Charlie.public().into() + ]; + + let keystore_path = tempfile::tempdir().expect("Creates keystore path"); + let keystore = sc_keystore::Store::open(keystore_path.path(), None).expect("Creates keystore."); + let my_key = keystore.write() + .generate_by_type::(AuthorityPair::ID) + .expect("Key should be created"); + authorities.push(my_key.public()); + + let net = Arc::new(Mutex::new(net)); + + let mut net = net.lock(); + let peer = net.peer(3); + let client = peer.client().as_full().expect("full clients are created").clone(); + let environ = DummyFactory(client.clone()); + + let worker = AuraWorker { + client: client.clone(), + block_import: Arc::new(Mutex::new(client)), + env: environ, + keystore, + sync_oracle: DummyOracle.clone(), + force_authoring: false, + _key_type: PhantomData::, + }; + + let head = Header::new( + 1, + H256::from_low_u64_be(0), + H256::from_low_u64_be(0), + Default::default(), + Default::default() + ); + assert!(worker.claim_slot(&head, 0, &authorities).is_none()); + assert!(worker.claim_slot(&head, 1, &authorities).is_none()); + assert!(worker.claim_slot(&head, 2, &authorities).is_none()); + assert!(worker.claim_slot(&head, 3, &authorities).is_some()); + assert!(worker.claim_slot(&head, 4, &authorities).is_none()); + assert!(worker.claim_slot(&head, 5, &authorities).is_none()); + assert!(worker.claim_slot(&head, 6, &authorities).is_none()); + assert!(worker.claim_slot(&head, 7, &authorities).is_some()); + } } diff --git a/client/consensus/babe/Cargo.toml b/client/consensus/babe/Cargo.toml index 19c5bf9e588b3d51f933855ddd01e1a80cd6eae9..46c67e89171250a5d368d71b2f6f75fcdc230029 100644 --- a/client/consensus/babe/Cargo.toml +++ b/client/consensus/babe/Cargo.toml @@ -1,41 +1,44 @@ [package] name = "sc-consensus-babe" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] description = "BABE consensus algorithm for substrate" edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" documentation = "https://docs.rs/sc-consensus-babe" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive"] } -sp-consensus-babe = { version = "0.8.0-alpha.5", path = "../../../primitives/consensus/babe" } -sp-core = { version = "2.0.0-alpha.5", path = "../../../primitives/core" } -sp-application-crypto = { version = "2.0.0-alpha.5", path = "../../../primitives/application-crypto" } +codec = { package = "parity-scale-codec", version = "1.3.1", features = ["derive"] } +sp-consensus-babe = { version = "0.8.0-rc4", path = "../../../primitives/consensus/babe" } +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } +sp-application-crypto = { version = "2.0.0-rc4", path = "../../../primitives/application-crypto" } num-bigint = "0.2.3" num-rational = "0.2.2" num-traits = "0.2.8" serde = { version = "1.0.104", features = ["derive"] } -sp-version = { version = "2.0.0-alpha.5", path = "../../../primitives/version" } -sp-io = { version = "2.0.0-alpha.5", path = "../../../primitives/io" } -sp-inherents = { version = "2.0.0-alpha.5", path = "../../../primitives/inherents" } -sp-timestamp = { version = "2.0.0-alpha.5", path = "../../../primitives/timestamp" } -sc-telemetry = { version = "2.0.0-alpha.5", path = "../../telemetry" } -sc-keystore = { version = "2.0.0-alpha.5", path = "../../keystore" } -sc-client-api = { version = "2.0.0-alpha.5", path = "../../api" } -sc-client = { version = "0.8.0-alpha.5", path = "../../" } -sc-consensus-epochs = { version = "0.8.0-alpha.5", path = "../epochs" } -sp-api = { version = "2.0.0-alpha.5", path = "../../../primitives/api" } -sp-block-builder = { version = "2.0.0-alpha.5", path = "../../../primitives/block-builder" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../../primitives/blockchain" } -sp-consensus = { version = "0.8.0-alpha.5", path = "../../../primitives/consensus/common" } -sp-consensus-vrf = { version = "0.8.0-alpha.5", path = "../../../primitives/consensus/vrf" } -sc-consensus-uncles = { version = "0.8.0-alpha.5", path = "../uncles" } -sc-consensus-slots = { version = "0.8.0-alpha.5", path = "../slots" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime" } -fork-tree = { version = "2.0.0-alpha.5", path = "../../../utils/fork-tree" } +sp-version = { version = "2.0.0-rc4", path = "../../../primitives/version" } +sp-io = { version = "2.0.0-rc4", path = "../../../primitives/io" } +sp-inherents = { version = "2.0.0-rc4", path = "../../../primitives/inherents" } +sp-timestamp = { version = "2.0.0-rc4", path = "../../../primitives/timestamp" } +sc-telemetry = { version = "2.0.0-rc4", path = "../../telemetry" } +sc-keystore = { version = "2.0.0-rc4", path = "../../keystore" } +sc-client-api = { version = "2.0.0-rc4", path = "../../api" } +sc-consensus-epochs = { version = "0.8.0-rc4", path = "../epochs" } +sp-api = { version = "2.0.0-rc4", path = "../../../primitives/api" } +sp-block-builder = { version = "2.0.0-rc4", path = "../../../primitives/block-builder" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../../primitives/blockchain" } +sp-consensus = { version = "0.8.0-rc4", path = "../../../primitives/consensus/common" } +sp-consensus-vrf = { version = "0.8.0-rc4", path = "../../../primitives/consensus/vrf" } +sc-consensus-uncles = { version = "0.8.0-rc4", path = "../uncles" } +sc-consensus-slots = { version = "0.8.0-rc4", path = "../slots" } +sp-runtime = { version = "2.0.0-rc4", path = "../../../primitives/runtime" } +fork-tree = { version = "2.0.0-rc4", path = "../../../utils/fork-tree" } +prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.8.0-rc4"} futures = "0.3.4" futures-timer = "3.0.1" parking_lot = "0.10.0" @@ -47,18 +50,16 @@ pdqselect = "0.1.0" derive_more = "0.99.2" [dev-dependencies] -sp-keyring = { version = "2.0.0-alpha.5", path = "../../../primitives/keyring" } -sc-executor = { version = "0.8.0-alpha.5", path = "../../executor" } -sc-network = { version = "0.8.0-alpha.5", path = "../../network" } -sc-network-test = { version = "0.8.0-dev", path = "../../network/test" } -sc-service = { version = "0.8.0-alpha.5", path = "../../service" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../../test-utils/runtime/client" } -sc-block-builder = { version = "0.8.0-alpha.5", path = "../../block-builder" } +sp-keyring = { version = "2.0.0-rc4", path = "../../../primitives/keyring" } +sc-executor = { version = "0.8.0-rc4", path = "../../executor" } +sc-network = { version = "0.8.0-rc4", path = "../../network" } +sc-network-test = { version = "0.8.0-rc4", path = "../../network/test" } +sc-service = { version = "0.8.0-rc4", default-features = false, path = "../../service" } +substrate-test-runtime-client = { version = "2.0.0-rc4", path = "../../../test-utils/runtime/client" } +sc-block-builder = { version = "0.8.0-rc4", path = "../../block-builder" } env_logger = "0.7.0" +rand_chacha = "0.2.2" tempfile = "3.1.0" [features] test-helpers = [] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/client/consensus/babe/rpc/Cargo.toml b/client/consensus/babe/rpc/Cargo.toml index 6bdaeb5ddf0709a336b0bccf6d30698ba810d2dd..03da64ff30193080a56491bf9ff46b44d9e050ca 100644 --- a/client/consensus/babe/rpc/Cargo.toml +++ b/client/consensus/babe/rpc/Cargo.toml @@ -1,35 +1,38 @@ [package] name = "sc-consensus-babe-rpc" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] description = "RPC extensions for the BABE consensus algorithm" edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sc-consensus-babe = { version = "0.8.0-alpha.5", path = "../" } -jsonrpc-core = "14.0.3" -jsonrpc-core-client = "14.0.5" -jsonrpc-derive = "14.0.3" -sp-consensus-babe = { version = "0.8.0-alpha.5", path = "../../../../primitives/consensus/babe" } +sc-consensus-babe = { version = "0.8.0-rc4", path = "../" } +sc-rpc-api = { version = "0.8.0-rc4", path = "../../../rpc-api" } +jsonrpc-core = "14.2.0" +jsonrpc-core-client = "14.2.0" +jsonrpc-derive = "14.2.1" +sp-consensus-babe = { version = "0.8.0-rc4", path = "../../../../primitives/consensus/babe" } serde = { version = "1.0.104", features=["derive"] } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../../../primitives/blockchain" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../../../primitives/runtime" } -sc-consensus-epochs = { version = "0.8.0-alpha.5", path = "../../epochs" } -futures = "0.3.4" +sp-blockchain = { version = "2.0.0-rc4", path = "../../../../primitives/blockchain" } +sp-runtime = { version = "2.0.0-rc4", path = "../../../../primitives/runtime" } +sc-consensus-epochs = { version = "0.8.0-rc4", path = "../../epochs" } +futures = { version = "0.3.4", features = ["compat"] } derive_more = "0.99.2" -sp-api = { version = "2.0.0-alpha.5", path = "../../../../primitives/api" } -sp-consensus = { version = "0.8.0-alpha.5", path = "../../../../primitives/consensus/common" } -sp-core = { version = "2.0.0-alpha.5", path = "../../../../primitives/core" } -sc-keystore = { version = "2.0.0-alpha.5", path = "../../../keystore" } +sp-api = { version = "2.0.0-rc4", path = "../../../../primitives/api" } +sp-consensus = { version = "0.8.0-rc4", path = "../../../../primitives/consensus/common" } +sp-core = { version = "2.0.0-rc4", path = "../../../../primitives/core" } +sp-application-crypto = { version = "2.0.0-rc4", path = "../../../../primitives/application-crypto" } +sc-keystore = { version = "2.0.0-rc4", path = "../../../keystore" } [dev-dependencies] -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../../../test-utils/runtime/client" } -sp-application-crypto = { version = "2.0.0-alpha.5", path = "../../../../primitives/application-crypto" } -sp-keyring = { version = "2.0.0-alpha.5", path = "../../../../primitives/keyring" } +sc-consensus = { version = "0.8.0-rc4", path = "../../../consensus/common" } +serde_json = "1.0.50" +sp-keyring = { version = "2.0.0-rc4", path = "../../../../primitives/keyring" } +substrate-test-runtime-client = { version = "2.0.0-rc4", path = "../../../../test-utils/runtime/client" } tempfile = "3.1.0" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/client/consensus/babe/rpc/src/lib.rs b/client/consensus/babe/rpc/src/lib.rs index cb78504b1f78882395f5273afbfc5adb2a5c45a3..652f4f00baac2ae582415142c540b95014d26894 100644 --- a/client/consensus/babe/rpc/src/lib.rs +++ b/client/consensus/babe/rpc/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! RPC api for babe. @@ -30,13 +32,18 @@ use sp_consensus_babe::{ digests::PreDigest, }; use serde::{Deserialize, Serialize}; +use sp_core::{ + crypto::Public, + traits::BareCryptoStore, +}; +use sp_application_crypto::AppKey; use sc_keystore::KeyStorePtr; +use sc_rpc_api::DenyUnsafe; use sp_api::{ProvideRuntimeApi, BlockId}; -use sp_core::crypto::Pair; use sp_runtime::traits::{Block as BlockT, Header as _}; use sp_consensus::{SelectChain, Error as ConsensusError}; use sp_blockchain::{HeaderBackend, HeaderMetadata, Error as BlockChainError}; -use std::{collections::HashMap, fmt, sync::Arc}; +use std::{collections::HashMap, sync::Arc}; type FutureResult = Box + Send>; @@ -49,8 +56,8 @@ pub trait BabeApi { fn epoch_authorship(&self) -> FutureResult>; } -/// Implements the BabeRPC trait for interacting with Babe. -pub struct BabeRPCHandler { +/// Implements the BabeRpc trait for interacting with Babe. +pub struct BabeRpcHandler { /// shared reference to the client. client: Arc, /// shared reference to EpochChanges @@ -61,9 +68,11 @@ pub struct BabeRPCHandler { babe_config: Config, /// The SelectChain strategy select_chain: SC, + /// Whether to deny unsafe calls + deny_unsafe: DenyUnsafe, } -impl BabeRPCHandler { +impl BabeRpcHandler { /// Creates a new instance of the BabeRpc handler. pub fn new( client: Arc, @@ -71,6 +80,7 @@ impl BabeRPCHandler { keystore: KeyStorePtr, babe_config: Config, select_chain: SC, + deny_unsafe: DenyUnsafe, ) -> Self { Self { client, @@ -78,19 +88,23 @@ impl BabeRPCHandler { keystore, babe_config, select_chain, + deny_unsafe, } } } -impl BabeApi for BabeRPCHandler +impl BabeApi for BabeRpcHandler where B: BlockT, C: ProvideRuntimeApi + HeaderBackend + HeaderMetadata + 'static, C::Api: BabeRuntimeApi, - ::Error: fmt::Debug, SC: SelectChain + Clone + 'static, { fn epoch_authorship(&self) -> FutureResult> { + if let Err(err) = self.deny_unsafe.check_if_safe() { + return Box::new(rpc_future::err(err.into())); + } + let ( babe_config, keystore, @@ -116,16 +130,34 @@ impl BabeApi for BabeRPCHandler let mut claims: HashMap = HashMap::new(); + let keys = { + let ks = keystore.read(); + epoch.authorities.iter() + .enumerate() + .filter_map(|(i, a)| { + if ks.has_keys(&[(a.0.to_raw_vec(), AuthorityId::ID)]) { + Some((a.0.clone(), i)) + } else { + None + } + }) + .collect::>() + }; + for slot_number in epoch_start..epoch_end { - let epoch = epoch_data(&shared_epoch, &client, &babe_config, slot_number, &select_chain)?; - if let Some((claim, key)) = authorship::claim_slot(slot_number, &epoch, &babe_config, &keystore) { + if let Some((claim, key)) = + authorship::claim_slot_using_keys(slot_number, &epoch, &keystore, &keys) + { match claim { PreDigest::Primary { .. } => { - claims.entry(key.public()).or_default().primary.push(slot_number); + claims.entry(key).or_default().primary.push(slot_number); } - PreDigest::Secondary { .. } => { - claims.entry(key.public()).or_default().secondary.push(slot_number); + PreDigest::SecondaryPlain { .. } => { + claims.entry(key).or_default().secondary.push(slot_number); } + PreDigest::SecondaryVRF { .. } => { + claims.entry(key).or_default().secondary_vrf.push(slot_number); + }, }; } } @@ -144,6 +176,8 @@ pub struct EpochAuthorship { primary: Vec, /// the array of secondary slots that can be claimed secondary: Vec, + /// The array of secondary VRF slots that can be claimed. + secondary_vrf: Vec, } /// Errors encountered by the RPC @@ -158,7 +192,7 @@ pub enum Error { impl From for jsonrpc_core::Error { fn from(error: Error) -> Self { jsonrpc_core::Error { - message: format!("{}", error).into(), + message: format!("{}", error), code: jsonrpc_core::ErrorCode::ServerError(1234), data: None, } @@ -184,7 +218,7 @@ fn epoch_data( &parent.hash(), parent.number().clone(), slot_number, - |slot| babe_config.genesis_epoch(slot), + |slot| Epoch::genesis(&babe_config, slot), ) .map_err(|e| Error::Consensus(ConsensusError::ChainLookup(format!("{:?}", e))))? .ok_or(Error::Consensus(ConsensusError::InvalidAuthoritiesSet)) @@ -194,7 +228,10 @@ fn epoch_data( mod tests { use super::*; use substrate_test_runtime_client::{ + runtime::Block, + Backend, DefaultTestClientBuilderExt, + TestClient, TestClientBuilderExt, TestClientBuilder, }; @@ -216,8 +253,9 @@ mod tests { (keystore, keystore_path) } - #[test] - fn rpc() { + fn test_babe_rpc_handler( + deny_unsafe: DenyUnsafe + ) -> BabeRpcHandler> { let builder = TestClientBuilder::new(); let (client, longest_chain) = builder.build_with_longest_chain(); let client = Arc::new(client); @@ -229,15 +267,42 @@ mod tests { ).expect("can initialize block-import"); let epoch_changes = link.epoch_changes().clone(); - let select_chain = longest_chain; let keystore = create_temp_keystore::(Ed25519Keyring::Alice).0; - let handler = BabeRPCHandler::new(client.clone(), epoch_changes, keystore, config, select_chain); + + BabeRpcHandler::new( + client.clone(), + epoch_changes, + keystore, + config, + longest_chain, + deny_unsafe, + ) + } + + #[test] + fn epoch_authorship_works() { + let handler = test_babe_rpc_handler(DenyUnsafe::No); let mut io = IoHandler::new(); io.extend_with(BabeApi::to_delegate(handler)); let request = r#"{"jsonrpc":"2.0","method":"babe_epochAuthorship","params": [],"id":1}"#; - let response = r#"{"jsonrpc":"2.0","result":{"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY":{"primary":[0],"secondary":[1,2,4]}},"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":{"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY":{"primary":[0],"secondary":[1,2,4],"secondary_vrf":[]}},"id":1}"#; assert_eq!(Some(response.into()), io.handle_request_sync(request)); } + + #[test] + fn epoch_authorship_is_unsafe() { + let handler = test_babe_rpc_handler(DenyUnsafe::Yes); + let mut io = IoHandler::new(); + + io.extend_with(BabeApi::to_delegate(handler)); + let request = r#"{"jsonrpc":"2.0","method":"babe_epochAuthorship","params": [],"id":1}"#; + + let response = io.handle_request_sync(request).unwrap(); + let mut response: serde_json::Value = serde_json::from_str(&response).unwrap(); + let error: RpcError = serde_json::from_value(response["error"].take()).unwrap(); + + assert_eq!(error, RpcError::method_not_found()) + } } diff --git a/client/consensus/babe/src/authorship.rs b/client/consensus/babe/src/authorship.rs index 074e582bff252395a18e691211eda944b380c723..682e04e380d7c32eeed887ee0db855b68e37039e 100644 --- a/client/consensus/babe/src/authorship.rs +++ b/client/consensus/babe/src/authorship.rs @@ -16,17 +16,24 @@ //! BABE authority selection and slot claiming. -use merlin::Transcript; +use sp_application_crypto::AppKey; use sp_consensus_babe::{ - AuthorityId, BabeAuthorityWeight, BABE_ENGINE_ID, BABE_VRF_PREFIX, - SlotNumber, AuthorityPair, BabeConfiguration + BABE_VRF_PREFIX, + AuthorityId, BabeAuthorityWeight, + SlotNumber, + make_transcript, + make_transcript_data, +}; +use sp_consensus_babe::digests::{ + PreDigest, PrimaryPreDigest, SecondaryPlainPreDigest, SecondaryVRFPreDigest, }; -use sp_consensus_babe::digests::{PreDigest, PrimaryPreDigest, SecondaryPreDigest}; use sp_consensus_vrf::schnorrkel::{VRFOutput, VRFProof}; -use sp_core::{U256, blake2_256}; +use sp_core::{U256, blake2_256, crypto::Public, traits::BareCryptoStore}; use codec::Encode; -use schnorrkel::vrf::VRFInOut; -use sp_core::Pair; +use schnorrkel::{ + keys::PublicKey, + vrf::VRFInOut, +}; use sc_keystore::KeyStorePtr; use super::Epoch; @@ -47,14 +54,44 @@ pub(super) fn calculate_primary_threshold( 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()) + assert!(theta > 0.0, "authority with weight 0."); + + // NOTE: in the equation `p = 1 - (1 - c)^theta` the value of `p` is always + // capped by `c`. For all pratical purposes `c` should always be set to a + // value < 0.5, as such in the computations below we should never be near + // edge cases like `0.999999`. + + let p = BigRational::from_float(1f64 - (1f64 - c).powf(theta)).expect( + "returns None when the given value is not finite; \ + c is a configuration parameter defined in (0, 1]; \ + theta must be > 0 if the given authority's weight is > 0; \ + theta represents the validator's relative weight defined in (0, 1]; \ + powf will always return values in (0, 1] given both the \ + base and exponent are in that domain; \ + qed.", + ); + + let numer = p.numer().to_biguint().expect( + "returns None when the given value is negative; \ + p is defined as `1 - n` where n is defined in (0, 1]; \ + p must be a value in [0, 1); \ + qed." + ); + + let denom = p.denom().to_biguint().expect( + "returns None when the given value is negative; \ + p is defined as `1 - n` where n is defined in (0, 1]; \ + p must be a value in [0, 1); \ + qed." + ); + + ((BigUint::one() << 128) * numer / denom).to_u128().expect( + "returns None if the underlying value cannot be represented with 128 bits; \ + we start with 2^128 which is one more than can be represented with 128 bits; \ + we multiple by p which is defined in [0, 1); \ + the result must be lower than 2^128 by at least one and thus representable with 128 bits; \ + qed.", + ) } /// Returns true if the given VRF output is lower than the given threshold, @@ -87,28 +124,18 @@ pub(super) fn secondary_slot_author( Some(&expected_author.0) } -pub(super) fn make_transcript( - randomness: &[u8], - slot_number: u64, - epoch: u64, -) -> Transcript { - let mut transcript = Transcript::new(&BABE_ENGINE_ID); - transcript.append_u64(b"slot number", slot_number); - transcript.append_u64(b"current epoch", epoch); - transcript.append_message(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)], + epoch: &Epoch, + keys: &[(AuthorityId, usize)], keystore: &KeyStorePtr, - randomness: [u8; 32], -) -> Option<(PreDigest, AuthorityPair)> { + author_secondary_vrf: bool, +) -> Option<(PreDigest, AuthorityId)> { + let Epoch { authorities, randomness, epoch_index, .. } = epoch; + if authorities.is_empty() { return None; } @@ -116,24 +143,44 @@ fn claim_secondary_slot( let expected_author = super::authorship::secondary_slot_author( slot_number, authorities, - randomness, + *randomness, )?; - let keystore = keystore.read(); + for (authority_id, authority_index) in keys { + if authority_id == expected_author { + let pre_digest = if author_secondary_vrf { + let transcript_data = super::authorship::make_transcript_data( + randomness, + slot_number, + *epoch_index, + ); + let result = keystore.read().sr25519_vrf_sign( + AuthorityId::ID, + authority_id.as_ref(), + transcript_data, + ); + if let Ok(signature) = result { + Some(PreDigest::SecondaryVRF(SecondaryVRFPreDigest { + slot_number, + vrf_output: VRFOutput(signature.output), + vrf_proof: VRFProof(signature.proof), + authority_index: *authority_index as u32, + })) + } else { + None + } + } else if keystore.read().has_keys(&[(authority_id.to_raw_vec(), AuthorityId::ID)]) { + Some(PreDigest::SecondaryPlain(SecondaryPlainPreDigest { + slot_number, + authority_index: *authority_index as u32, + })) + } else { + None + }; - 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 = PreDigest::Secondary(SecondaryPreDigest { - slot_number, - authority_index: authority_index as u32, - }); - - return Some((pre_digest, pair)); + if let Some(pre_digest) = pre_digest { + return Some((pre_digest, authority_id.clone())); + } } } @@ -147,17 +194,34 @@ fn claim_secondary_slot( pub fn claim_slot( slot_number: SlotNumber, epoch: &Epoch, - config: &BabeConfiguration, keystore: &KeyStorePtr, -) -> Option<(PreDigest, AuthorityPair)> { - claim_primary_slot(slot_number, epoch, config.c, keystore) +) -> Option<(PreDigest, AuthorityId)> { + let authorities = epoch.authorities.iter() + .enumerate() + .map(|(index, a)| (a.0.clone(), index)) + .collect::>(); + claim_slot_using_keys(slot_number, epoch, keystore, &authorities) +} + +/// Like `claim_slot`, but allows passing an explicit set of key pairs. Useful if we intend +/// to make repeated calls for different slots using the same key pairs. +pub fn claim_slot_using_keys( + slot_number: SlotNumber, + epoch: &Epoch, + keystore: &KeyStorePtr, + keys: &[(AuthorityId, usize)], +) -> Option<(PreDigest, AuthorityId)> { + claim_primary_slot(slot_number, epoch, epoch.config.c, keystore, &keys) .or_else(|| { - if config.secondary_slots { + if epoch.config.allowed_slots.is_secondary_plain_slots_allowed() || + epoch.config.allowed_slots.is_secondary_vrf_slots_allowed() + { claim_secondary_slot( slot_number, - &epoch.authorities, + &epoch, + keys, keystore, - epoch.randomness, + epoch.config.allowed_slots.is_secondary_vrf_slots_allowed(), ) } else { None @@ -165,11 +229,6 @@ pub fn claim_slot( }) } -fn get_keypair(q: &AuthorityPair) -> &schnorrkel::Keypair { - use sp_core::crypto::IsWrappedBy; - sp_core::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, @@ -179,40 +238,88 @@ fn claim_primary_slot( epoch: &Epoch, c: (u64, u64), keystore: &KeyStorePtr, -) -> Option<(PreDigest, AuthorityPair)> { + keys: &[(AuthorityId, usize)], +) -> Option<(PreDigest, AuthorityId)> { 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); + for (authority_id, authority_index) in keys { + let transcript = super::authorship::make_transcript( + randomness, + slot_number, + *epoch_index + ); + let transcript_data = super::authorship::make_transcript_data( + 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| { - PreDigest::Primary(PrimaryPreDigest { + let threshold = super::authorship::calculate_primary_threshold(c, authorities, *authority_index); + + let result = keystore.read().sr25519_vrf_sign( + AuthorityId::ID, + authority_id.as_ref(), + transcript_data, + ); + if let Ok(signature) = result { + let public = PublicKey::from_bytes(&authority_id.to_raw_vec()).ok()?; + let inout = match signature.output.attach_input_hash(&public, transcript) { + Ok(inout) => inout, + Err(_) => continue, + }; + if super::authorship::check_primary_threshold(&inout, threshold) { + let pre_digest = PreDigest::Primary(PrimaryPreDigest { slot_number, - vrf_output: VRFOutput(s.0.to_output()), - vrf_proof: VRFProof(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)); + vrf_output: VRFOutput(signature.output), + vrf_proof: VRFProof(signature.proof), + authority_index: *authority_index as u32, + }); + + return Some((pre_digest, authority_id.clone())); + } } } None } + +#[cfg(test)] +mod tests { + use super::*; + use sp_core::{sr25519::Pair, crypto::Pair as _}; + use sp_consensus_babe::{AuthorityId, BabeEpochConfiguration, AllowedSlots}; + + #[test] + fn claim_secondary_plain_slot_works() { + let keystore = sc_keystore::Store::new_in_memory(); + let valid_public_key = dbg!(keystore.write().sr25519_generate_new( + AuthorityId::ID, + Some(sp_core::crypto::DEV_PHRASE), + ).unwrap()); + + let authorities = vec![ + (AuthorityId::from(Pair::generate().0.public()), 5), + (AuthorityId::from(Pair::generate().0.public()), 7), + ]; + + let mut epoch = Epoch { + epoch_index: 10, + start_slot: 0, + duration: 20, + authorities: authorities.clone(), + randomness: Default::default(), + config: BabeEpochConfiguration { + c: (3, 10), + allowed_slots: AllowedSlots::PrimaryAndSecondaryPlainSlots, + }, + }; + + assert!(claim_slot(10, &epoch, &keystore).is_none()); + + epoch.authorities.push((valid_public_key.clone().into(), 10)); + assert_eq!(claim_slot(10, &epoch, &keystore).unwrap().1, valid_public_key.into()); + } +} diff --git a/client/consensus/babe/src/aux_schema.rs b/client/consensus/babe/src/aux_schema.rs index 6f69e65940c05d60bfef77e839af4887c8910347..4f26568d833430e7fd6454f8f0e58eeb4677688a 100644 --- a/client/consensus/babe/src/aux_schema.rs +++ b/client/consensus/babe/src/aux_schema.rs @@ -24,13 +24,13 @@ use codec::{Decode, Encode}; use sc_client_api::backend::AuxStore; use sp_blockchain::{Result as ClientResult, Error as ClientError}; use sp_runtime::traits::Block as BlockT; -use sp_consensus_babe::BabeBlockWeight; +use sp_consensus_babe::{BabeBlockWeight, BabeGenesisConfiguration}; use sc_consensus_epochs::{EpochChangesFor, SharedEpochChanges, migration::EpochChangesForV0}; -use crate::Epoch; +use crate::{Epoch, migration::EpochV0}; const BABE_EPOCH_CHANGES_VERSION: &[u8] = b"babe_epoch_changes_version"; const BABE_EPOCH_CHANGES_KEY: &[u8] = b"babe_epoch_changes"; -const BABE_EPOCH_CHANGES_CURRENT_VERSION: u32 = 1; +const BABE_EPOCH_CHANGES_CURRENT_VERSION: u32 = 2; fn block_weight_key(block_hash: H) -> Vec { (b"block_weight", block_hash).encode() @@ -53,14 +53,19 @@ fn load_decode(backend: &B, key: &[u8]) -> ClientResult> /// Load or initialize persistent epoch change data from backend. pub(crate) fn load_epoch_changes( backend: &B, + config: &BabeGenesisConfiguration, ) -> ClientResult> { let version = load_decode::<_, u32>(backend, BABE_EPOCH_CHANGES_VERSION)?; let maybe_epoch_changes = match version { - None => load_decode::<_, EpochChangesForV0>( + None => load_decode::<_, EpochChangesForV0>( backend, BABE_EPOCH_CHANGES_KEY, - )?.map(|v0| v0.migrate()), + )?.map(|v0| v0.migrate().map(|_, _, epoch| epoch.migrate(config))), + Some(1) => load_decode::<_, EpochChangesFor>( + backend, + BABE_EPOCH_CHANGES_KEY, + )?.map(|v1| v1.map(|_, _, epoch| epoch.migrate(config))), Some(BABE_EPOCH_CHANGES_CURRENT_VERSION) => load_decode::<_, EpochChangesFor>( backend, BABE_EPOCH_CHANGES_KEY, @@ -74,7 +79,7 @@ pub(crate) fn load_epoch_changes( let epoch_changes = Arc::new(Mutex::new(maybe_epoch_changes.unwrap_or_else(|| { info!(target: "babe", - "Creating empty BABE epoch changes on what appears to be first startup." + "👶 Creating empty BABE epoch changes on what appears to be first startup." ); EpochChangesFor::::default() }))); @@ -107,7 +112,7 @@ pub(crate) fn write_epoch_changes( /// Write the cumulative chain-weight of a block ot aux storage. pub(crate) fn write_block_weight( block_hash: H, - block_weight: &BabeBlockWeight, + block_weight: BabeBlockWeight, write_aux: F, ) -> R where F: FnOnce(&[(Vec, &[u8])]) -> R, @@ -131,18 +136,19 @@ pub(crate) fn load_block_weight( #[cfg(test)] mod test { use super::*; - use crate::Epoch; + use crate::migration::EpochV0; use fork_tree::ForkTree; use substrate_test_runtime_client; use sp_core::H256; use sp_runtime::traits::NumberFor; + use sp_consensus_babe::{AllowedSlots, BabeGenesisConfiguration}; use sc_consensus_epochs::{PersistedEpoch, PersistedEpochHeader, EpochHeader}; use sp_consensus::Error as ConsensusError; use sc_network_test::Block as TestBlock; #[test] fn load_decode_from_v0_epoch_changes() { - let epoch = Epoch { + let epoch = EpochV0 { start_slot: 0, authorities: vec![], randomness: [0; 32], @@ -160,7 +166,7 @@ mod test { client.insert_aux( &[(BABE_EPOCH_CHANGES_KEY, - &EpochChangesForV0::::from_raw(v0_tree).encode()[..])], + &EpochChangesForV0::::from_raw(v0_tree).encode()[..])], &[], ).unwrap(); @@ -169,7 +175,16 @@ mod test { None, ); - let epoch_changes = load_epoch_changes::(&client).unwrap(); + let epoch_changes = load_epoch_changes::( + &client, &BabeGenesisConfiguration { + slot_duration: 10, + epoch_length: 4, + c: (3, 10), + genesis_authorities: Vec::new(), + randomness: Default::default(), + allowed_slots: AllowedSlots::PrimaryAndSecondaryPlainSlots, + }, + ).unwrap(); assert!( epoch_changes.lock() @@ -192,7 +207,7 @@ mod test { assert_eq!( load_decode::<_, u32>(&client, BABE_EPOCH_CHANGES_VERSION).unwrap(), - Some(1), + Some(2), ); } } diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 5365aae2aa6cb30793a41ec9d4f7a02d3df6bc9a..af684499cef8b158ee753414123f88f1de4a0bcf 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -49,6 +49,11 @@ //! //! `blake2_256(epoch_randomness ++ slot_number) % authorities_len`. //! +//! The secondary slots supports either a `SecondaryPlain` or `SecondaryVRF` +//! variant. Comparing with `SecondaryPlain` variant, the `SecondaryVRF` variant +//! generates an additional VRF output. The output is not included in beacon +//! randomness, but can be consumed by parachains. +//! //! 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. @@ -59,23 +64,26 @@ #![forbid(unsafe_code)] #![warn(missing_docs)] pub use sp_consensus_babe::{ - BabeApi, ConsensusLog, BABE_ENGINE_ID, SlotNumber, BabeConfiguration, + BabeApi, ConsensusLog, BABE_ENGINE_ID, SlotNumber, + BabeEpochConfiguration, BabeGenesisConfiguration, AuthorityId, AuthorityPair, AuthoritySignature, BabeAuthorityWeight, VRF_OUTPUT_LENGTH, digests::{ - CompatibleDigestItem, NextEpochDescriptor, PreDigest, PrimaryPreDigest, SecondaryPreDigest, + CompatibleDigestItem, NextEpochDescriptor, NextConfigDescriptor, PreDigest, + PrimaryPreDigest, SecondaryPlainPreDigest, }, }; pub use sp_consensus::SyncOracle; use std::{ collections::HashMap, sync::Arc, u64, pin::Pin, time::{Instant, Duration}, - any::Any, borrow::Cow + any::Any, borrow::Cow, convert::TryInto, }; -use sp_consensus_babe; use sp_consensus::{ImportResult, CanAuthorWith}; use sp_consensus::import_queue::{ BoxJustificationImport, BoxFinalityProofImport, }; +use sp_core::{crypto::Public, traits::BareCryptoStore}; +use sp_application_crypto::AppKey; use sp_runtime::{ generic::{BlockId, OpaqueDigestItemId}, Justification, traits::{Block as BlockT, Header, DigestItemFor, Zero}, @@ -83,7 +91,6 @@ use sp_runtime::{ use sp_api::{ProvideRuntimeApi, NumberFor}; use sc_keystore::KeyStorePtr; use parking_lot::Mutex; -use sp_core::Pair; use sp_inherents::{InherentDataProviders, InherentData}; use sc_telemetry::{telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG}; use sp_consensus::{ @@ -101,7 +108,8 @@ use sc_client_api::{ use sp_block_builder::BlockBuilder as BlockBuilderApi; use futures::prelude::*; -use log::{warn, debug, info, trace}; +use log::{debug, info, log, trace, warn}; +use prometheus_endpoint::Registry; use sc_consensus_slots::{ SlotWorker, SlotInfo, SlotCompatible, StorageChanges, CheckedHeader, check_equivocation, }; @@ -118,36 +126,43 @@ use sp_api::ApiExt; mod aux_schema; mod verification; +mod migration; pub mod authorship; #[cfg(test)] mod tests; /// BABE epoch information -#[derive(Decode, Encode, Default, PartialEq, Eq, Clone, Debug)] +#[derive(Decode, Encode, PartialEq, Eq, Clone, Debug)] pub struct Epoch { - /// The epoch index + /// The epoch index. pub epoch_index: u64, - /// The starting slot of the epoch, + /// The starting slot of the epoch. pub start_slot: SlotNumber, - /// The duration of this epoch + /// The duration of this epoch. pub duration: SlotNumber, - /// The authorities and their weights + /// The authorities and their weights. pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, - /// Randomness for this epoch + /// Randomness for this epoch. pub randomness: [u8; VRF_OUTPUT_LENGTH], + /// Configuration of the epoch. + pub config: BabeEpochConfiguration, } impl EpochT for Epoch { - type NextEpochDescriptor = NextEpochDescriptor; + type NextEpochDescriptor = (NextEpochDescriptor, BabeEpochConfiguration); type SlotNumber = SlotNumber; - fn increment(&self, descriptor: NextEpochDescriptor) -> Epoch { + fn increment( + &self, + (descriptor, config): (NextEpochDescriptor, BabeEpochConfiguration) + ) -> Epoch { Epoch { epoch_index: self.epoch_index + 1, start_slot: self.start_slot + self.duration, duration: self.duration, authorities: descriptor.authorities, randomness: descriptor.randomness, + config, } } @@ -160,6 +175,27 @@ impl EpochT for Epoch { } } +impl Epoch { + /// 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( + genesis_config: &BabeGenesisConfiguration, + slot_number: SlotNumber + ) -> Epoch { + Epoch { + epoch_index: 0, + start_slot: slot_number, + duration: genesis_config.epoch_length, + authorities: genesis_config.genesis_authorities.clone(), + randomness: genesis_config.randomness, + config: BabeEpochConfiguration { + c: genesis_config.c, + allowed_slots: genesis_config.allowed_slots, + }, + } + } +} + #[derive(derive_more::Display, Debug)] enum Error { #[display(fmt = "Multiple BABE pre-runtime digests, rejecting!")] @@ -168,6 +204,8 @@ enum Error { NoPreRuntimeDigest, #[display(fmt = "Multiple BABE epoch change digests, rejecting!")] MultipleEpochChangeDigests, + #[display(fmt = "Multiple BABE config change digests, rejecting!")] + MultipleConfigChangeDigests, #[display(fmt = "Could not extract timestamp and slot: {:?}", _0)] Extraction(sp_consensus::Error), #[display(fmt = "Could not fetch epoch at {:?}", _0)] @@ -200,6 +238,8 @@ enum Error { FetchParentHeader(sp_blockchain::Error), #[display(fmt = "Expected epoch change to happen at {:?}, s{}", _0, _1)] ExpectedEpochChange(B::Hash, u64), + #[display(fmt = "Unexpected config change")] + UnexpectedConfigChange, #[display(fmt = "Unexpected epoch change")] UnexpectedEpochChange, #[display(fmt = "Parent block of {} has no associated weight", _0)] @@ -222,16 +262,6 @@ fn babe_err(error: Error) -> Error { error } -macro_rules! babe_info { - ($($i: expr),+) => { - { - info!(target: "babe", $($i),+); - format!($($i),+) - } - }; -} - - /// Intermediate value passed to block importer. pub struct BabeIntermediate { /// The epoch descriptor. @@ -246,7 +276,7 @@ pub static INTERMEDIATE_KEY: &[u8] = b"babe1"; // and `super::babe::Config` can be eliminated. // https://github.com/paritytech/substrate/issues/2434 #[derive(Clone)] -pub struct Config(sc_consensus_slots::SlotDuration); +pub struct Config(sc_consensus_slots::SlotDuration); impl Config { /// Either fetch the slot duration from disk or compute it from the genesis @@ -255,7 +285,26 @@ impl Config { C: AuxStore + ProvideRuntimeApi, C::Api: BabeApi, { trace!(target: "babe", "Getting slot duration"); - match sc_consensus_slots::SlotDuration::get_or_compute(client, |a, b| a.configuration(b)).map(Self) { + match sc_consensus_slots::SlotDuration::get_or_compute(client, |a, b| { + let has_api_v1 = a.has_api_with::, _>( + &b, |v| v == 1, + )?; + let has_api_v2 = a.has_api_with::, _>( + &b, |v| v == 2, + )?; + + if has_api_v1 { + #[allow(deprecated)] { + Ok(a.configuration_before_version_2(b)?.into()) + } + } else if has_api_v2 { + a.configuration(b) + } else { + Err(sp_blockchain::Error::VersionInvalid( + "Unsupported or invalid BabeApi version".to_string() + )) + } + }).map(Self) { Ok(s) => Ok(s), Err(s) => { warn!(target: "babe", "Failed to get slot duration"); @@ -263,24 +312,12 @@ impl Config { } } } - - /// 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 std::ops::Deref for Config { - type Target = BabeConfiguration; + type Target = BabeGenesisConfiguration; - fn deref(&self) -> &BabeConfiguration { + fn deref(&self) -> &BabeGenesisConfiguration { &*self.0 } } @@ -363,12 +400,12 @@ pub fn start_babe(BabeParams { register_babe_inherent_data_provider(&inherent_data_providers, config.slot_duration())?; sc_consensus_uncles::register_uncles_inherent_data_provider( - client.clone(), + client, select_chain.clone(), &inherent_data_providers, )?; - babe_info!("👶 Starting BABE Authorship worker"); + info!(target: "babe", "👶 Starting BABE Authorship worker"); Ok(sc_consensus_slots::start_slot_worker( config.0, select_chain, @@ -405,7 +442,7 @@ impl sc_consensus_slots::SimpleSlotWorker for BabeWork Error: std::error::Error + Send + From + From + 'static, { type EpochData = ViableEpochDescriptor, Epoch>; - type Claim = (PreDigest, AuthorityPair); + type Claim = (PreDigest, AuthorityId); type SyncOracle = SO; type CreateProposer = Pin> + Send + 'static @@ -438,7 +475,7 @@ impl sc_consensus_slots::SimpleSlotWorker for BabeWork fn authorities_len(&self, epoch_descriptor: &Self::EpochData) -> Option { self.epoch_changes.lock() - .viable_epoch(&epoch_descriptor, |slot| self.config.genesis_epoch(slot)) + .viable_epoch(&epoch_descriptor, |slot| Epoch::genesis(&self.config, slot)) .map(|epoch| epoch.as_ref().authorities.len()) } @@ -453,13 +490,12 @@ impl sc_consensus_slots::SimpleSlotWorker for BabeWork slot_number, self.epoch_changes.lock().viable_epoch( &epoch_descriptor, - |slot| self.config.genesis_epoch(slot) + |slot| Epoch::genesis(&self.config, slot) )?.as_ref(), - &*self.config, &self.keystore, ); - if let Some(_) = s { + if s.is_some() { debug!(target: "babe", "Claimed slot {}", slot_number); } @@ -483,12 +519,30 @@ impl sc_consensus_slots::SimpleSlotWorker for BabeWork StorageChanges, Self::Claim, Self::EpochData, - ) -> sp_consensus::BlockImportParams + Send> { - Box::new(|header, header_hash, body, storage_changes, (_, pair), epoch_descriptor| { + ) -> Result< + sp_consensus::BlockImportParams, + sp_consensus::Error> + Send + 'static> + { + let keystore = self.keystore.clone(); + Box::new(move |header, header_hash, body, storage_changes, (_, public), epoch_descriptor| { // sign the pre-sealed hash of the block and then // add it to a digest item. - let signature = pair.sign(header_hash.as_ref()); - let digest_item = as CompatibleDigestItem>::babe_seal(signature); + let public_type_pair = public.clone().into(); + let public = public.to_raw_vec(); + let signature = keystore.read() + .sign_with( + ::ID, + &public_type_pair, + header_hash.as_ref() + ) + .map_err(|e| sp_consensus::Error::CannotSign( + public.clone(), e.to_string(), + ))?; + let signature: AuthoritySignature = signature.clone().try_into() + .map_err(|_| sp_consensus::Error::InvalidSignature( + signature, public + ))?; + let digest_item = as CompatibleDigestItem>::babe_seal(signature.into()); let mut import_block = BlockImportParams::new(BlockOrigin::Own, header); import_block.post_digests.push(digest_item); @@ -499,7 +553,7 @@ impl sc_consensus_slots::SimpleSlotWorker for BabeWork Box::new(BabeIntermediate:: { epoch_descriptor }) as Box, ); - import_block + Ok(import_block) }) } @@ -520,38 +574,28 @@ impl sc_consensus_slots::SimpleSlotWorker for BabeWork fn proposing_remaining_duration( &self, head: &B::Header, - slot_info: &SlotInfo + slot_info: &SlotInfo, ) -> Option { - // never give more than 2^this times the lenience. - const BACKOFF_CAP: u64 = 8; - - // how many slots it takes before we double the lenience. - const BACKOFF_STEP: u64 = 2; - let slot_remaining = self.slot_remaining_duration(slot_info); + let parent_slot = match find_pre_digest::(head) { Err(_) => return Some(slot_remaining), Ok(d) => d.slot_number(), }; - // we allow a lenience of the number of slots since the head of the - // chain was produced, minus 1 (since there is always a difference of at least 1) - // - // exponential back-off. - // in normal cases we only attempt to issue blocks up to the end of the slot. - // when the chain has been stalled for a few slots, we give more lenience. - let slot_lenience = slot_info.number.saturating_sub(parent_slot + 1); - - let slot_lenience = std::cmp::min(slot_lenience, BACKOFF_CAP); - let slot_duration = slot_info.duration << (slot_lenience / BACKOFF_STEP); + if let Some(slot_lenience) = + sc_consensus_slots::slot_lenience_exponential(parent_slot, slot_info) + { + debug!(target: "babe", + "No block for {} slots. Applying exponential lenience of {}s", + slot_info.number.saturating_sub(parent_slot + 1), + slot_lenience.as_secs(), + ); - if slot_lenience >= 1 { - debug!(target: "babe", "No block for {} slots. Applying 2^({}/{}) lenience", - slot_lenience, slot_lenience, BACKOFF_STEP); + Some(slot_remaining + slot_lenience) + } else { + Some(slot_remaining) } - - let slot_lenience = Duration::from_secs(slot_duration); - Some(slot_lenience + slot_remaining) } } @@ -582,7 +626,7 @@ 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(PreDigest::Secondary(SecondaryPreDigest { + return Ok(PreDigest::SecondaryPlain(SecondaryPlainPreDigest { slot_number: 0, authority_index: 0, })); @@ -619,6 +663,24 @@ fn find_next_epoch_digest(header: &B::Header) Ok(epoch_digest) } +/// Extract the BABE config change digest from the given header, if it exists. +fn find_next_config_digest(header: &B::Header) + -> Result, Error> + where DigestItemFor: CompatibleDigestItem, +{ + let mut config_digest: Option<_> = None; + for log in header.digest().logs() { + trace!(target: "babe", "Checking log {:?}, looking for epoch change digest.", log); + let log = log.try_to::(OpaqueDigestItemId::Consensus(&BABE_ENGINE_ID)); + match (log, config_digest.is_some()) { + (Some(ConsensusLog::NextConfigData(_)), true) => return Err(babe_err(Error::MultipleConfigChangeDigests)), + (Some(ConsensusLog::NextConfigData(config)), false) => config_digest = Some(config), + _ => trace!(target: "babe", "Ignoring digest not meant for us"), + } + } + + Ok(config_digest) +} #[derive(Default, Clone)] struct TimeSource(Arc, Vec<(Instant, u64)>)>>); @@ -658,27 +720,29 @@ impl BabeLink { } /// A verifier for Babe blocks. -pub struct BabeVerifier { +pub struct BabeVerifier { client: Arc, + select_chain: SelectChain, inherent_data_providers: sp_inherents::InherentDataProviders, config: Config, epoch_changes: SharedEpochChanges, time_source: TimeSource, } -impl BabeVerifier - where - Block: BlockT, - Client: HeaderBackend + HeaderMetadata + ProvideRuntimeApi, - Client::Api: BlockBuilderApi, +impl BabeVerifier +where + Block: BlockT, + Client: AuxStore + HeaderBackend + HeaderMetadata + ProvideRuntimeApi, + Client::Api: BlockBuilderApi + + BabeApi, + SelectChain: sp_consensus::SelectChain, { fn check_inherents( &self, block: Block, block_id: BlockId, inherent_data: InherentData, - ) -> Result<(), Error> - { + ) -> Result<(), Error> { let inherent_res = self.client.runtime_api().check_inherents( &block_id, block, @@ -695,13 +759,95 @@ impl BabeVerifier Ok(()) } } + + fn check_and_report_equivocation( + &self, + slot_now: SlotNumber, + slot: SlotNumber, + header: &Block::Header, + author: &AuthorityId, + origin: &BlockOrigin, + ) -> Result<(), Error> { + // don't report any equivocations during initial sync + // as they are most likely stale. + if *origin == BlockOrigin::NetworkInitialSync { + return Ok(()); + } + + // check if authorship of this header is an equivocation and return a proof if so. + let equivocation_proof = + match check_equivocation(&*self.client, slot_now, slot, header, author) + .map_err(Error::Client)? + { + Some(proof) => proof, + None => return Ok(()), + }; + + info!( + "Slot author {:?} is equivocating at slot {} with headers {:?} and {:?}", + author, + slot, + equivocation_proof.first_header.hash(), + equivocation_proof.second_header.hash(), + ); + + // get the best block on which we will build and send the equivocation report. + let best_id = self + .select_chain + .best_chain() + .map(|h| BlockId::Hash(h.hash())) + .map_err(|e| Error::Client(e.into()))?; + + // generate a key ownership proof. we start by trying to generate the + // key owernship proof at the parent of the equivocating header, this + // will make sure that proof generation is successful since it happens + // during the on-going session (i.e. session keys are available in the + // state to be able to generate the proof). this might fail if the + // equivocation happens on the first block of the session, in which case + // its parent would be on the previous session. if generation on the + // parent header fails we try with best block as well. + let generate_key_owner_proof = |block_id: &BlockId| { + self.client + .runtime_api() + .generate_key_ownership_proof(block_id, slot, equivocation_proof.offender.clone()) + .map_err(Error::Client) + }; + + let parent_id = BlockId::Hash(*header.parent_hash()); + let key_owner_proof = match generate_key_owner_proof(&parent_id)? { + Some(proof) => proof, + None => match generate_key_owner_proof(&best_id)? { + Some(proof) => proof, + None => { + debug!(target: "babe", "Equivocation offender is not part of the authority set."); + return Ok(()); + } + }, + }; + + // submit equivocation report at best block. + self.client + .runtime_api() + .submit_report_equivocation_unsigned_extrinsic( + &best_id, + equivocation_proof, + key_owner_proof, + ) + .map_err(Error::Client)?; + + info!(target: "babe", "Submitted equivocation report for author {:?}", author); + + Ok(()) + } } -impl Verifier for BabeVerifier where +impl Verifier for BabeVerifier +where Block: BlockT, Client: HeaderMetadata + HeaderBackend + ProvideRuntimeApi - + Send + Sync + AuxStore + ProvideCache, + + Send + Sync + AuxStore + ProvideCache, Client::Api: BlockBuilderApi + BabeApi, + SelectChain: sp_consensus::SelectChain, { fn verify( &mut self, @@ -746,45 +892,34 @@ impl Verifier for BabeVerifier where .ok_or_else(|| Error::::FetchEpoch(parent_hash))?; let viable_epoch = epoch_changes.viable_epoch( &epoch_descriptor, - |slot| self.config.genesis_epoch(slot) + |slot| Epoch::genesis(&self.config, slot) ).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 v_params = verification::VerificationParams { header: header.clone(), - pre_digest: Some(pre_digest.clone()), + pre_digest: Some(pre_digest), slot_now: slot_now + 1, epoch: viable_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.client, + // proposed at the same slot by the given author. if there was, we will + // report the equivocation to the runtime. + self.check_and_report_equivocation( slot_now, - babe_pre_digest.slot_number(), + 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(), - ); - } + &verified_info.author, + &origin, + )?; // if the body is passed through, we need to use the runtime // to check that the internally-set timestamp in the inherents @@ -910,7 +1045,7 @@ impl BlockImport for BabeBlockImport>, ) -> Result { let hash = block.post_hash(); - let number = block.header.number().clone(); + let number = *block.header.number(); // early exit if block already in chain, otherwise the check for // epoch changes will error when trying to re-import an epoch change @@ -978,19 +1113,32 @@ impl BlockImport for BabeBlockImport(&block.header) .map_err(|e| ConsensusError::ClientImport(e.to_string()))?; + let next_config_digest = find_next_config_digest::(&block.header) + .map_err(|e| ConsensusError::ClientImport(e.to_string()))?; - match (first_in_epoch, next_epoch_digest.is_some()) { - (true, true) => {}, - (false, false) => {}, - (true, false) => { + match (first_in_epoch, next_epoch_digest.is_some(), next_config_digest.is_some()) { + (true, true, _) => {}, + (false, false, false) => {}, + (false, false, true) => { + return Err( + ConsensusError::ClientImport( + babe_err(Error::::UnexpectedConfigChange).into(), + ) + ) + }, + (true, false, _) => { return Err( ConsensusError::ClientImport( babe_err(Error::::ExpectedEpochChange(hash, slot_number)).into(), ) - ); + ) }, - (false, true) => { - return Err(ConsensusError::ClientImport(Error::::UnexpectedEpochChange.into())); + (false, true, _) => { + return Err( + ConsensusError::ClientImport( + babe_err(Error::::UnexpectedEpochChange).into(), + ) + ) }, } @@ -1005,20 +1153,38 @@ impl BlockImport for BabeBlockImport::FetchEpoch(parent_hash).into()) })?; - babe_info!("👶 New epoch {} launching at block {} (block slot {} >= start slot {}).", - viable_epoch.as_ref().epoch_index, - hash, - slot_number, - viable_epoch.as_ref().start_slot); + let epoch_config = next_config_digest.map(Into::into).unwrap_or_else( + || viable_epoch.as_ref().config.clone() + ); + + // restrict info logging during initial sync to avoid spam + let log_level = if block.origin == BlockOrigin::NetworkInitialSync { + log::Level::Debug + } else { + log::Level::Info + }; + + log!(target: "babe", + log_level, + "👶 New epoch {} launching at block {} (block slot {} >= start slot {}).", + viable_epoch.as_ref().epoch_index, + hash, + slot_number, + viable_epoch.as_ref().start_slot, + ); - let next_epoch = viable_epoch.increment(next_epoch_descriptor); + let next_epoch = viable_epoch.increment((next_epoch_descriptor, epoch_config)); - babe_info!("👶 Next epoch starts at slot {}", next_epoch.as_ref().start_slot); + log!(target: "babe", + log_level, + "👶 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 @@ -1060,7 +1226,7 @@ impl BlockImport for BabeBlockImport BlockImport for BabeBlockImport BlockImport for BabeBlockImport( ) -> ClientResult<(BabeBlockImport, BabeLink)> where Client: AuxStore + HeaderBackend + HeaderMetadata, { - let epoch_changes = aux_schema::load_epoch_changes::(&*client)?; + let epoch_changes = aux_schema::load_epoch_changes::(&*client, &config)?; let link = BabeLink { epoch_changes: epoch_changes.clone(), time_source: Default::default(), @@ -1192,24 +1358,29 @@ pub fn block_import( /// /// 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( +pub fn import_queue( babe_link: BabeLink, block_import: Inner, justification_import: Option>, finality_proof_import: Option>, client: Arc, + select_chain: SelectChain, inherent_data_providers: InherentDataProviders, + spawner: &impl sp_core::traits::SpawnNamed, + registry: Option<&Registry>, ) -> ClientResult>> where Inner: BlockImport> + Send + Sync + 'static, Client: ProvideRuntimeApi + ProvideCache + Send + Sync + AuxStore + 'static, Client: HeaderBackend + HeaderMetadata, Client::Api: BlockBuilderApi + BabeApi + ApiExt, + SelectChain: sp_consensus::SelectChain + 'static, { register_babe_inherent_data_provider(&inherent_data_providers, babe_link.config.slot_duration)?; let verifier = BabeVerifier { - client: client.clone(), + client, + select_chain, inherent_data_providers, config: babe_link.config, epoch_changes: babe_link.epoch_changes, @@ -1221,6 +1392,8 @@ pub fn import_queue( Box::new(block_import), justification_import, finality_proof_import, + spawner, + registry, )) } @@ -1251,13 +1424,12 @@ pub mod test_helpers { &parent.hash(), parent.number().clone(), slot_number, - |slot| link.config.genesis_epoch(slot), + |slot| Epoch::genesis(&link.config, slot), ).unwrap().unwrap(); authorship::claim_slot( slot_number, &epoch, - &link.config, keystore, ).map(|(digest, _)| digest) } diff --git a/client/consensus/babe/src/migration.rs b/client/consensus/babe/src/migration.rs new file mode 100644 index 0000000000000000000000000000000000000000..2a5a8749cc3c1f790b6a774ce32e5f392ba38ae0 --- /dev/null +++ b/client/consensus/babe/src/migration.rs @@ -0,0 +1,64 @@ +use codec::{Encode, Decode}; +use sc_consensus_epochs::Epoch as EpochT; +use crate::{ + Epoch, SlotNumber, AuthorityId, BabeAuthorityWeight, BabeGenesisConfiguration, + BabeEpochConfiguration, VRF_OUTPUT_LENGTH, NextEpochDescriptor, +}; + +/// BABE epoch information, version 0. +#[derive(Decode, Encode, PartialEq, Eq, Clone, Debug)] +pub struct EpochV0 { + /// The epoch index. + pub epoch_index: u64, + /// The starting slot of the epoch. + pub start_slot: SlotNumber, + /// The duration of this epoch. + pub duration: SlotNumber, + /// The authorities and their weights. + pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, + /// Randomness for this epoch. + pub randomness: [u8; VRF_OUTPUT_LENGTH], +} + +impl EpochT for EpochV0 { + type NextEpochDescriptor = NextEpochDescriptor; + type SlotNumber = SlotNumber; + + fn increment( + &self, + descriptor: NextEpochDescriptor + ) -> EpochV0 { + EpochV0 { + epoch_index: self.epoch_index + 1, + start_slot: self.start_slot + self.duration, + duration: self.duration, + authorities: descriptor.authorities, + randomness: descriptor.randomness, + } + } + + fn start_slot(&self) -> SlotNumber { + self.start_slot + } + + fn end_slot(&self) -> SlotNumber { + self.start_slot + self.duration + } +} + +impl EpochV0 { + /// Migrate the sturct to current epoch version. + pub fn migrate(self, config: &BabeGenesisConfiguration) -> Epoch { + Epoch { + epoch_index: self.epoch_index, + start_slot: self.start_slot, + duration: self.duration, + authorities: self.authorities, + randomness: self.randomness, + config: BabeEpochConfiguration { + c: config.c, + allowed_slots: config.allowed_slots, + }, + } + } +} diff --git a/client/consensus/babe/src/tests.rs b/client/consensus/babe/src/tests.rs index 20b924669d6147816c0fbf9c0c8e85937b17c1af..958d7845edbc678bad6d0c00bd35e8209d123de5 100644 --- a/client/consensus/babe/src/tests.rs +++ b/client/consensus/babe/src/tests.rs @@ -21,8 +21,14 @@ #![allow(deprecated)] use super::*; use authorship::claim_slot; - -use sp_consensus_babe::{AuthorityPair, SlotNumber}; +use sp_core::{crypto::Pair, vrf::make_transcript as transcript_from_data}; +use sp_consensus_babe::{ + AuthorityPair, + SlotNumber, + AllowedSlots, + make_transcript, + make_transcript_data, +}; use sc_block_builder::{BlockBuilder, BlockBuilderProvider}; use sp_consensus::{ NoNetwork as DummyOracle, Proposal, RecordProof, @@ -35,12 +41,17 @@ use sp_runtime::{generic::DigestItem, traits::{Block as BlockT, DigestFor}}; use sc_client_api::{BlockchainEvents, backend::TransactionFor}; use log::debug; use std::{time::Duration, cell::RefCell, task::Poll}; +use rand::RngCore; +use rand_chacha::{ + rand_core::SeedableRng, + ChaChaRng, +}; type Item = DigestItem; type Error = sp_blockchain::Error; -type TestClient = sc_client::Client< +type TestClient = substrate_test_runtime_client::client::Client< substrate_test_runtime_client::Backend, substrate_test_runtime_client::Executor, TestBlock, @@ -127,7 +138,7 @@ impl DummyProposer { &self.parent_hash, self.parent_number, this_slot, - |slot| self.factory.config.genesis_epoch(slot), + |slot| Epoch::genesis(&self.factory.config, slot), ) .expect("client has data to find epoch") .expect("can compute epoch for baked block"); @@ -159,7 +170,7 @@ impl Proposer for DummyProposer { type Proposal = future::Ready, Error>>; fn propose( - &mut self, + mut self, _: InherentData, pre_digests: DigestFor, _: Duration, @@ -203,8 +214,13 @@ pub struct BabeTestNet { type TestHeader = ::Header; type TestExtrinsic = ::Extrinsic; +type TestSelectChain = substrate_test_runtime_client::LongestChain< + substrate_test_runtime_client::Backend, + TestBlock, +>; + pub struct TestVerifier { - inner: BabeVerifier, + inner: BabeVerifier, mutator: Mutator, } @@ -286,15 +302,20 @@ impl TestNetFactory for BabeTestNet { ) -> Self::Verifier { + use substrate_test_runtime_client::DefaultTestClientBuilderExt; + let client = client.as_full().expect("only full clients are used in test"); trace!(target: "babe", "Creating a verifier"); // ensure block import and verifier are linked correctly. let data = maybe_link.as_ref().expect("babe link always provided to verifier instantiation"); + let (_, longest_chain) = TestClientBuilder::new().build_with_longest_chain(); + TestVerifier { inner: BabeVerifier { client: client.clone(), + select_chain: longest_chain, inherent_data_providers: data.inherent_data_providers.clone(), config: data.link.config.clone(), epoch_changes: data.link.epoch_changes.clone(), @@ -436,7 +457,7 @@ fn authoring_blocks() { #[should_panic] fn rejects_missing_inherent_digest() { run_one_test(|header: &mut TestHeader, stage| { - let v = std::mem::replace(&mut header.digest_mut().logs, vec![]); + let v = std::mem::take(&mut header.digest_mut().logs); header.digest_mut().logs = v.into_iter() .filter(|v| stage == Stage::PostSeal || v.as_babe_pre_digest().is_none()) .collect() @@ -447,7 +468,7 @@ fn rejects_missing_inherent_digest() { #[should_panic] fn rejects_missing_seals() { run_one_test(|header: &mut TestHeader, stage| { - let v = std::mem::replace(&mut header.digest_mut().logs, vec![]); + let v = std::mem::take(&mut header.digest_mut().logs); header.digest_mut().logs = v.into_iter() .filter(|v| stage == Stage::PreSeal || v.as_babe_seal().is_none()) .collect() @@ -458,7 +479,7 @@ fn rejects_missing_seals() { #[should_panic] fn rejects_missing_consensus_digests() { run_one_test(|header: &mut TestHeader, stage| { - let v = std::mem::replace(&mut header.digest_mut().logs, vec![]); + let v = std::mem::take(&mut header.digest_mut().logs); header.digest_mut().logs = v.into_iter() .filter(|v| stage == Stage::PostSeal || v.as_next_epoch_descriptor().is_none()) .collect() @@ -505,28 +526,32 @@ fn can_author_block() { randomness: [0; 32], epoch_index: 1, duration: 100, + config: BabeEpochConfiguration { + c: (3, 10), + allowed_slots: AllowedSlots::PrimaryAndSecondaryPlainSlots, + }, }; - let mut config = crate::BabeConfiguration { + let mut config = crate::BabeGenesisConfiguration { slot_duration: 1000, epoch_length: 100, c: (3, 10), genesis_authorities: Vec::new(), randomness: [0; 32], - secondary_slots: true, + allowed_slots: AllowedSlots::PrimaryAndSecondaryPlainSlots, }; // with secondary slots enabled it should never be empty - match claim_slot(i, &epoch, &config, &keystore) { + match claim_slot(i, &epoch, &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; + config.allowed_slots = AllowedSlots::PrimarySlots; loop { - match claim_slot(i, &epoch, &config, &keystore) { + match claim_slot(i, &epoch, &keystore) { None => i += 1, Some(s) => { debug!(target: "babe", "Authored block {:?}", s.0); @@ -553,7 +578,7 @@ fn propose_and_import_block( let pre_digest = sp_runtime::generic::Digest { logs: vec![ Item::babe_pre_digest( - PreDigest::Secondary(SecondaryPreDigest { + PreDigest::SecondaryPlain(SecondaryPlainPreDigest { authority_index: 0, slot_number, }), @@ -632,7 +657,7 @@ fn importing_block_one_sets_genesis_epoch() { &mut block_import, ); - let genesis_epoch = data.link.config.genesis_epoch(999); + let genesis_epoch = Epoch::genesis(&data.link.config, 999); let epoch_changes = data.link.epoch_changes.lock(); let epoch_for_second_block = epoch_changes.epoch_data_for_child_of( @@ -640,7 +665,7 @@ fn importing_block_one_sets_genesis_epoch() { &block_hash, 1, 1000, - |slot| data.link.config.genesis_epoch(slot), + |slot| Epoch::genesis(&data.link.config, slot), ).unwrap().unwrap(); assert_eq!(epoch_for_second_block, genesis_epoch); @@ -792,3 +817,36 @@ fn verify_slots_are_strictly_increasing() { &mut block_import, ); } + +#[test] +fn babe_transcript_generation_match() { + let _ = env_logger::try_init(); + let keystore_path = tempfile::tempdir().expect("Creates keystore path"); + let keystore = sc_keystore::Store::open(keystore_path.path(), None).expect("Creates keystore"); + let pair = keystore.write().insert_ephemeral_from_seed::("//Alice") + .expect("Generates authority pair"); + + let epoch = Epoch { + start_slot: 0, + authorities: vec![(pair.public(), 1)], + randomness: [0; 32], + epoch_index: 1, + duration: 100, + config: BabeEpochConfiguration { + c: (3, 10), + allowed_slots: AllowedSlots::PrimaryAndSecondaryPlainSlots, + }, + }; + + let orig_transcript = make_transcript(&epoch.randomness.clone(), 1, epoch.epoch_index); + let new_transcript = make_transcript_data(&epoch.randomness, 1, epoch.epoch_index); + + let test = |t: merlin::Transcript| -> [u8; 16] { + let mut b = [0u8; 16]; + t.build_rng() + .finalize(&mut ChaChaRng::from_seed([0u8;32])) + .fill_bytes(&mut b); + b + }; + debug_assert!(test(orig_transcript) == test(transcript_from_data(new_transcript))); +} diff --git a/client/consensus/babe/src/verification.rs b/client/consensus/babe/src/verification.rs index 2fd37280b3b369bdb1e73895dc9ae683030eaa23..fd3c27be4f34ef9bb00ba1ef12a4215d0e2a313d 100644 --- a/client/consensus/babe/src/verification.rs +++ b/client/consensus/babe/src/verification.rs @@ -17,29 +17,28 @@ //! Verification for BABE headers. use sp_runtime::{traits::Header, traits::DigestItemFor}; use sp_core::{Pair, Public}; -use sp_consensus_babe::{AuthoritySignature, SlotNumber, AuthorityPair, AuthorityId}; +use sp_consensus_babe::{make_transcript, AuthoritySignature, SlotNumber, AuthorityPair, AuthorityId}; use sp_consensus_babe::digests::{ - PreDigest, PrimaryPreDigest, SecondaryPreDigest, CompatibleDigestItem + PreDigest, PrimaryPreDigest, SecondaryPlainPreDigest, SecondaryVRFPreDigest, + CompatibleDigestItem }; use sc_consensus_slots::CheckedHeader; use log::{debug, trace}; use super::{find_pre_digest, babe_err, Epoch, BlockT, Error}; -use super::authorship::{make_transcript, calculate_primary_threshold, check_primary_threshold, secondary_slot_author}; +use super::authorship::{calculate_primary_threshold, check_primary_threshold, secondary_slot_author}; /// BABE verification parameters pub(super) struct VerificationParams<'a, B: 'a + BlockT> { - /// the header being verified. + /// The header being verified. pub(super) header: B::Header, - /// the pre-digest of the header being verified. this is optional - if prior + /// 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. + /// 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. + /// 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 @@ -63,7 +62,6 @@ pub(super) fn check_header( pre_digest, slot_now, epoch, - config, } = params; let authorities = &epoch.authorities; @@ -102,13 +100,21 @@ pub(super) fn check_header( primary, sig, &epoch, - config.c, + epoch.config.c, )?; }, - PreDigest::Secondary(secondary) if config.secondary_slots => { - debug!(target: "babe", "Verifying Secondary block"); - - check_secondary_header::( + PreDigest::SecondaryPlain(secondary) if epoch.config.allowed_slots.is_secondary_plain_slots_allowed() => { + debug!(target: "babe", "Verifying Secondary plain block"); + check_secondary_plain_header::( + pre_hash, + secondary, + sig, + &epoch, + )?; + }, + PreDigest::SecondaryVRF(secondary) if epoch.config.allowed_slots.is_secondary_vrf_slots_allowed() => { + debug!(target: "babe", "Verifying Secondary VRF block"); + check_secondary_vrf_header::( pre_hash, secondary, sig, @@ -182,9 +188,9 @@ fn check_primary_header( /// 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( +fn check_secondary_plain_header( pre_hash: B::Hash, - pre_digest: &SecondaryPreDigest, + pre_digest: &SecondaryPlainPreDigest, signature: AuthoritySignature, epoch: &Epoch, ) -> Result<(), Error> { @@ -208,3 +214,43 @@ fn check_secondary_header( Err(Error::BadSignature(pre_hash)) } } + +/// Check a secondary VRF slot proposal header. +fn check_secondary_vrf_header( + pre_hash: B::Hash, + pre_digest: &SecondaryVRFPreDigest, + signature: AuthoritySignature, + epoch: &Epoch, +) -> Result<(), Error> { + // check the signature is valid under the expected authority and + // chain state. + let expected_author = secondary_slot_author( + pre_digest.slot_number, + &epoch.authorities, + epoch.randomness, + ).ok_or_else(|| Error::NoSecondaryAuthorExpected)?; + + let author = &epoch.authorities[pre_digest.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) { + let transcript = make_transcript( + &epoch.randomness, + pre_digest.slot_number, + epoch.epoch_index, + ); + + schnorrkel::PublicKey::from_bytes(author.as_slice()).and_then(|p| { + p.vrf_verify(transcript, &pre_digest.vrf_output, &pre_digest.vrf_proof) + }).map_err(|s| { + babe_err(Error::VRFVerificationFailed(s)) + })?; + + Ok(()) + } else { + Err(Error::BadSignature(pre_hash)) + } +} diff --git a/client/consensus/common/Cargo.toml b/client/consensus/common/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..72bb051a0d0f53a524ed9fe8685857224c16cfc2 --- /dev/null +++ b/client/consensus/common/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "sc-consensus" +version = "0.8.0-rc4" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +description = "Collection of common consensus specific imlementations for Substrate (client)" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +sc-client-api = { version = "2.0.0-rc4", path = "../../api" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../../primitives/blockchain" } +sp-runtime = { version = "2.0.0-rc4", path = "../../../primitives/runtime" } +sp-consensus = { version = "0.8.0-rc4", path = "../../../primitives/consensus/common" } diff --git a/client/consensus/common/src/lib.rs b/client/consensus/common/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..1d9b072cfe964f168ac471b2bfcf3cac29009048 --- /dev/null +++ b/client/consensus/common/src/lib.rs @@ -0,0 +1,20 @@ +// Copyright 2019-2020 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 . + +//! Collection of common consensus specific implementations +mod longest_chain; + +pub use longest_chain::LongestChain; diff --git a/client/consensus/common/src/longest_chain.rs b/client/consensus/common/src/longest_chain.rs new file mode 100644 index 0000000000000000000000000000000000000000..981dbad0f607029671b7ad858f2327578fa24e94 --- /dev/null +++ b/client/consensus/common/src/longest_chain.rs @@ -0,0 +1,101 @@ +// Copyright 2019-2020 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 . +//! Longest chain implementation + +use std::sync::Arc; +use std::marker::PhantomData; +use sc_client_api::backend; +use sp_consensus::{SelectChain, Error as ConsensusError}; +use sp_blockchain::{Backend, HeaderBackend}; +use sp_runtime::{ + traits::{NumberFor, Block as BlockT}, + generic::BlockId, +}; + +/// Implement Longest Chain Select implementation +/// where 'longest' is defined as the highest number of blocks +pub struct LongestChain { + backend: Arc, + _phantom: PhantomData +} + +impl Clone for LongestChain { + fn clone(&self) -> Self { + let backend = self.backend.clone(); + LongestChain { + backend, + _phantom: Default::default() + } + } +} + +impl LongestChain + where + B: backend::Backend, + Block: BlockT, +{ + /// Instantiate a new LongestChain for Backend B + pub fn new(backend: Arc) -> Self { + LongestChain { + backend, + _phantom: Default::default() + } + } + + fn best_block_header(&self) -> sp_blockchain::Result<::Header> { + let info = self.backend.blockchain().info(); + 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")) + } + + fn leaves(&self) -> Result::Hash>, sp_blockchain::Error> { + self.backend.blockchain().leaves() + } +} + +impl SelectChain for LongestChain + where + B: backend::Backend, + Block: BlockT, +{ + + fn leaves(&self) -> Result::Hash>, ConsensusError> { + LongestChain::leaves(self) + .map_err(|e| ConsensusError::ChainLookup(e.to_string()).into()) + } + + fn best_chain(&self) -> Result<::Header, ConsensusError> + { + LongestChain::best_block_header(&self) + .map_err(|e| ConsensusError::ChainLookup(e.to_string()).into()) + } + + fn finality_target( + &self, + target_hash: Block::Hash, + maybe_max_number: Option> + ) -> Result, ConsensusError> { + 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()) + } +} \ No newline at end of file diff --git a/client/consensus/epochs/Cargo.toml b/client/consensus/epochs/Cargo.toml index 3496141ec712bdc4c8daa043e10faaecb13d8b7e..22f8794974953cce9d855a96bfb8a368c4608449 100644 --- a/client/consensus/epochs/Cargo.toml +++ b/client/consensus/epochs/Cargo.toml @@ -1,20 +1,20 @@ [package] name = "sc-consensus-epochs" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] description = "Generic epochs-based utilities for consensus" edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" -[dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive"] } -parking_lot = "0.10.0" -fork-tree = { version = "2.0.0-alpha.5", path = "../../../utils/fork-tree" } -sp-runtime = { path = "../../../primitives/runtime" , version = "2.0.0-alpha.5"} -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../../primitives/blockchain" } -sc-client-api = { path = "../../api" , version = "2.0.0-alpha.5"} - [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.3.1", features = ["derive"] } +parking_lot = "0.10.0" +fork-tree = { version = "2.0.0-rc4", path = "../../../utils/fork-tree" } +sp-runtime = { path = "../../../primitives/runtime" , version = "2.0.0-rc4"} +sp-blockchain = { version = "2.0.0-rc4", path = "../../../primitives/blockchain" } +sc-client-api = { path = "../../api" , version = "2.0.0-rc4"} diff --git a/client/consensus/epochs/src/lib.rs b/client/consensus/epochs/src/lib.rs index 001c172b3490573dea6a0dcfbefc428cf79c13aa..acb07dd668a3c4f3b2c7a2350451d9ac93008926 100644 --- a/client/consensus/epochs/src/lib.rs +++ b/client/consensus/epochs/src/lib.rs @@ -335,6 +335,55 @@ impl EpochChanges where self.inner.rebalance() } + /// Map the epoch changes from one storing data to a different one. + pub fn map(self, mut f: F) -> EpochChanges where + B: Epoch, + F: FnMut(&Hash, &Number, E) -> B, + { + EpochChanges { + inner: self.inner.map(&mut |_, _, header| { + match header { + PersistedEpochHeader::Genesis(epoch_0, epoch_1) => { + PersistedEpochHeader::Genesis( + EpochHeader { + start_slot: epoch_0.start_slot, + end_slot: epoch_0.end_slot, + }, + EpochHeader { + start_slot: epoch_1.start_slot, + end_slot: epoch_1.end_slot, + }, + ) + }, + PersistedEpochHeader::Regular(epoch_n) => { + PersistedEpochHeader::Regular( + EpochHeader { + start_slot: epoch_n.start_slot, + end_slot: epoch_n.end_slot, + }, + ) + }, + } + }), + epochs: self.epochs.into_iter().map(|((hash, number), epoch)| { + let bepoch = match epoch { + PersistedEpoch::Genesis(epoch_0, epoch_1) => { + PersistedEpoch::Genesis( + f(&hash, &number, epoch_0), + f(&hash, &number, epoch_1), + ) + }, + PersistedEpoch::Regular(epoch_n) => { + PersistedEpoch::Regular( + f(&hash, &number, epoch_n) + ) + }, + }; + ((hash, number), bepoch) + }).collect(), + } + } + /// 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. diff --git a/client/consensus/manual-seal/Cargo.toml b/client/consensus/manual-seal/Cargo.toml index b7e5f7b0b1a9ff7c3f14303fa8c0065aa572048d..2da28b9ab9f997199604fa48b31579b6c63dc333 100644 --- a/client/consensus/manual-seal/Cargo.toml +++ b/client/consensus/manual-seal/Cargo.toml @@ -1,40 +1,41 @@ [package] name = "sc-consensus-manual-seal" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] description = "Manual sealing engine for Substrate" edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] derive_more = "0.99.2" futures = "0.3.4" -jsonrpc-core = "14.0.5" -jsonrpc-core-client = "14.0.5" -jsonrpc-derive = "14.0.5" +jsonrpc-core = "14.2.0" +jsonrpc-core-client = "14.2.0" +jsonrpc-derive = "14.2.1" log = "0.4.8" parking_lot = "0.10.0" serde = { version = "1.0", features=["derive"] } assert_matches = "1.3.0" -sc-client = { path = "../../../client" , version = "0.8.0-alpha.5"} -sc-client-api = { path = "../../../client/api" , version = "2.0.0-alpha.5"} -sc-transaction-pool = { path = "../../transaction-pool" , version = "2.0.0-alpha.5"} -sp-blockchain = { path = "../../../primitives/blockchain" , version = "2.0.0-alpha.5"} -sp-consensus = { package = "sp-consensus", path = "../../../primitives/consensus/common" , version = "0.8.0-alpha.5"} -sp-inherents = { path = "../../../primitives/inherents" , version = "2.0.0-alpha.5"} -sp-runtime = { path = "../../../primitives/runtime" , version = "2.0.0-alpha.5"} -sp-transaction-pool = { path = "../../../primitives/transaction-pool" , version = "2.0.0-alpha.5"} +sc-client-api = { path = "../../../client/api", version = "2.0.0-rc4" } +sc-transaction-pool = { path = "../../transaction-pool", version = "2.0.0-rc4" } +sp-blockchain = { path = "../../../primitives/blockchain", version = "2.0.0-rc4" } +sp-consensus = { package = "sp-consensus", path = "../../../primitives/consensus/common", version = "0.8.0-rc4" } +sp-inherents = { path = "../../../primitives/inherents", version = "2.0.0-rc4" } +sp-runtime = { path = "../../../primitives/runtime", version = "2.0.0-rc4" } +sp-core = { path = "../../../primitives/core", version = "2.0.0-rc4" } +sp-transaction-pool = { path = "../../../primitives/transaction-pool", version = "2.0.0-rc4" } +prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.8.0-rc4" } [dev-dependencies] -sc-basic-authorship = { path = "../../basic-authorship" , version = "0.8.0-alpha.5"} -substrate-test-runtime-client = { path = "../../../test-utils/runtime/client" , version = "2.0.0-dev"} -substrate-test-runtime-transaction-pool = { path = "../../../test-utils/runtime/transaction-pool" , version = "2.0.0-dev"} +sc-basic-authorship = { path = "../../basic-authorship", version = "0.8.0-rc4" } +substrate-test-runtime-client = { path = "../../../test-utils/runtime/client", version = "2.0.0-rc4" } +substrate-test-runtime-transaction-pool = { path = "../../../test-utils/runtime/transaction-pool", version = "2.0.0-rc4" } tokio = { version = "0.2", features = ["rt-core", "macros"] } env_logger = "0.7.0" tempfile = "3.1.0" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/client/consensus/manual-seal/src/error.rs b/client/consensus/manual-seal/src/error.rs index d6ee9f176772128a8f597e91b944cbca3e978a0c..2411a839b027ceb51b6e927f5c09ad030571231a 100644 --- a/client/consensus/manual-seal/src/error.rs +++ b/client/consensus/manual-seal/src/error.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! A manual sealing engine: the engine listens for rpc calls to seal blocks and create forks. //! This is suitable for a testing environment. diff --git a/client/consensus/manual-seal/src/finalize_block.rs b/client/consensus/manual-seal/src/finalize_block.rs index b3b60e223805b857c23602ae718a2347c8cb3291..5780a25f97256331eb1d11b2370dd838ec112ac7 100644 --- a/client/consensus/manual-seal/src/finalize_block.rs +++ b/client/consensus/manual-seal/src/finalize_block.rs @@ -23,35 +23,40 @@ use sp_runtime::{ generic::BlockId, }; use std::sync::Arc; -use sc_client_api::backend::Backend as ClientBackend; +use sc_client_api::backend::{Backend as ClientBackend, Finalizer}; +use std::marker::PhantomData; /// params for block finalization. -pub struct FinalizeBlockParams { +pub struct FinalizeBlockParams { /// hash of the block pub hash: ::Hash, /// sender to report errors/success to the rpc. pub sender: rpc::Sender<()>, /// finalization justification pub justification: Option, - /// client backend - pub backend: Arc, + /// Finalizer trait object. + pub finalizer: Arc, + /// phantom type to pin the Backend type + pub _phantom: PhantomData, } + /// finalizes a block in the backend with the given params. -pub async fn finalize_block(params: FinalizeBlockParams) +pub async fn finalize_block(params: FinalizeBlockParams) where B: BlockT, + F: Finalizer, CB: ClientBackend, { let FinalizeBlockParams { hash, mut sender, justification, - backend: back_end, + finalizer, .. } = params; - match back_end.finalize_block(BlockId::Hash(hash), justification) { + match finalizer.finalize_block(BlockId::Hash(hash), justification, true) { Err(e) => { log::warn!("Failed to finalize block {:?}", e); rpc::send_result(&mut sender, Err(e.into())) diff --git a/client/consensus/manual-seal/src/lib.rs b/client/consensus/manual-seal/src/lib.rs index f3a0ca887fd005ed34ade733ed13d9e8e68898b9..77fb5043c5dd68a07af5b0c7cadea0686ad417dc 100644 --- a/client/consensus/manual-seal/src/lib.rs +++ b/client/consensus/manual-seal/src/lib.rs @@ -1,82 +1,50 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! A manual sealing engine: the engine listens for rpc calls to seal blocks and create forks. //! This is suitable for a testing environment. +use futures::prelude::*; use sp_consensus::{ - self, BlockImport, Environment, Proposer, BlockCheckParams, - ForkChoiceStrategy, BlockImportParams, BlockOrigin, - ImportResult, SelectChain, - import_queue::{ - BasicQueue, - CacheKeyId, - Verifier, - BoxBlockImport, - }, + Environment, Proposer, ForkChoiceStrategy, BlockImportParams, BlockOrigin, SelectChain, + import_queue::{BasicQueue, CacheKeyId, Verifier, BoxBlockImport}, }; +use sp_blockchain::HeaderBackend; use sp_inherents::InherentDataProviders; use sp_runtime::{traits::Block as BlockT, Justification}; -use sc_client_api::backend::Backend as ClientBackend; -use futures::prelude::*; +use sc_client_api::backend::{Backend as ClientBackend, Finalizer}; use sc_transaction_pool::txpool; -use std::collections::HashMap; -use std::sync::Arc; +use std::{sync::Arc, marker::PhantomData}; +use prometheus_endpoint::Registry; -pub mod rpc; mod error; mod finalize_block; mod seal_new_block; -use finalize_block::{finalize_block, FinalizeBlockParams}; -use seal_new_block::{seal_new_block, SealBlockParams}; -pub use error::Error; -pub use rpc::{EngineCommand, CreatedBlock}; - -/// The synchronous block-import worker of the engine. -pub struct ManualSealBlockImport { - inner: I, -} - -impl From for ManualSealBlockImport { - fn from(i: I) -> Self { - ManualSealBlockImport { inner: i } - } -} - -impl BlockImport for ManualSealBlockImport - where - B: BlockT, - I: BlockImport, -{ - type Error = I::Error; - type Transaction = (); - - fn check_block(&mut self, block: BlockCheckParams) -> Result - { - self.inner.check_block(block) - } +pub mod rpc; - fn import_block( - &mut self, - block: BlockImportParams, - cache: HashMap>, - ) -> Result { - self.inner.import_block(block, cache) - } -} +use self::{ + finalize_block::{finalize_block, FinalizeBlockParams}, + seal_new_block::{seal_new_block, SealBlockParams}, +}; +pub use self::{ + error::Error, + rpc::{EngineCommand, CreatedBlock}, +}; /// The verifier for the manual seal engine; instantly finalizes. struct ManualSealVerifier; @@ -92,7 +60,7 @@ impl Verifier for ManualSealVerifier { let mut import_params = BlockImportParams::new(origin, header); import_params.justification = justification; import_params.body = body; - import_params.finalized = true; + import_params.finalized = false; import_params.fork_choice = Some(ForkChoiceStrategy::LongestChain); Ok((import_params, None)) @@ -100,37 +68,47 @@ impl Verifier for ManualSealVerifier { } /// Instantiate the import queue for the manual seal consensus engine. -pub fn import_queue(block_import: BoxBlockImport) -> BasicQueue +pub fn import_queue( + block_import: BoxBlockImport, + spawner: &impl sp_core::traits::SpawnNamed, + registry: Option<&Registry>, +) -> BasicQueue + where + Block: BlockT, + Transaction: Send + Sync + 'static, { BasicQueue::new( ManualSealVerifier, block_import, None, None, + spawner, + registry, ) } /// Creates the background authorship task for the manual seal engine. -pub async fn run_manual_seal( +pub async fn run_manual_seal( mut block_import: BoxBlockImport, mut env: E, - backend: Arc, + client: Arc, pool: Arc>, - mut seal_block_channel: S, - select_chain: C, + mut commands_stream: S, + select_chain: SC, inherent_data_providers: InherentDataProviders, ) where + A: txpool::ChainApi + 'static, B: BlockT + 'static, + C: HeaderBackend + Finalizer + 'static, CB: ClientBackend + 'static, E: Environment + 'static, E::Error: std::fmt::Display, >::Error: std::fmt::Display, - A: txpool::ChainApi::Hash> + 'static, S: Stream::Hash>> + Unpin + 'static, - C: SelectChain + 'static, + SC: SelectChain + 'static, { - while let Some(command) = seal_block_channel.next().await { + while let Some(command) = commands_stream.next().await { match command { EngineCommand::SealNewBlock { create_empty, @@ -149,7 +127,7 @@ pub async fn run_manual_seal( block_import: &mut block_import, inherent_data_provider: &inherent_data_providers, pool: pool.clone(), - backend: backend.clone(), + client: client.clone(), } ).await; } @@ -159,7 +137,8 @@ pub async fn run_manual_seal( hash, sender, justification, - backend: backend.clone(), + finalizer: client.clone(), + _phantom: PhantomData, } ).await } @@ -170,26 +149,28 @@ pub async fn run_manual_seal( /// runs the background authorship task for the instant seal engine. /// instant-seal creates a new block for every transaction imported into /// the transaction pool. -pub async fn run_instant_seal( +pub async fn run_instant_seal( block_import: BoxBlockImport, env: E, - backend: Arc, + client: Arc, pool: Arc>, - select_chain: C, + select_chain: SC, inherent_data_providers: InherentDataProviders, ) where - A: txpool::ChainApi::Hash> + 'static, + A: txpool::ChainApi + 'static, B: BlockT + 'static, + C: HeaderBackend + Finalizer + 'static, CB: ClientBackend + 'static, E: Environment + 'static, E::Error: std::fmt::Display, >::Error: std::fmt::Display, - C: SelectChain + 'static + SC: SelectChain + 'static { // instant-seal creates blocks as soon as transactions are imported // into the transaction pool. - let seal_block_channel = pool.validated_pool().import_notification_stream() + let commands_stream = pool.validated_pool() + .import_notification_stream() .map(|_| { EngineCommand::SealNewBlock { create_empty: false, @@ -202,9 +183,9 @@ pub async fn run_instant_seal( run_manual_seal( block_import, env, - backend, + client, pool, - seal_block_channel, + commands_stream, select_chain, inherent_data_providers, ).await @@ -219,16 +200,11 @@ mod tests { AccountKeyring::*, TestClientBuilder, }; - use sc_transaction_pool::{ - BasicPool, - txpool::Options, - }; + use sc_transaction_pool::{BasicPool, RevalidationType, txpool::Options}; use substrate_test_runtime_transaction_pool::{TestApi, uxt}; use sp_transaction_pool::{TransactionPool, MaintainedTransactionPool, TransactionSource}; use sp_runtime::generic::BlockId; - use sp_blockchain::HeaderBackend; use sp_consensus::ImportedAux; - use sc_client::LongestChain; use sp_inherents::InherentDataProviders; use sc_basic_authorship::ProposerFactory; @@ -241,14 +217,17 @@ mod tests { #[tokio::test] async fn instant_seal() { let builder = TestClientBuilder::new(); - let backend = builder.backend(); - let client = Arc::new(builder.build()); - let select_chain = LongestChain::new(backend.clone()); + let (client, select_chain) = builder.build_with_longest_chain(); + let client = Arc::new(client); let inherent_data_providers = InherentDataProviders::new(); - let pool = Arc::new(BasicPool::new(Options::default(), api()).0); + let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let pool = Arc::new(BasicPool::with_revalidation_type( + Options::default(), api(), None, RevalidationType::Full, spawner, + )); let env = ProposerFactory::new( client.clone(), - pool.clone() + pool.clone(), + None, ); // this test checks that blocks are created as soon as transactions are imported into the pool. let (sender, receiver) = futures::channel::oneshot::channel(); @@ -257,7 +236,7 @@ mod tests { .map(move |_| { // we're only going to submit one tx so this fn will only be called once. let mut_sender = Arc::get_mut(&mut sender).unwrap(); - let sender = std::mem::replace(mut_sender, None); + let sender = std::mem::take(mut_sender); EngineCommand::SealNewBlock { create_empty: false, finalize: true, @@ -268,7 +247,7 @@ mod tests { let future = run_manual_seal( Box::new(client.clone()), env, - backend.clone(), + client.clone(), pool.pool().clone(), stream, select_chain, @@ -300,27 +279,30 @@ mod tests { } ); // assert that there's a new block in the db. - assert!(backend.blockchain().header(BlockId::Number(1)).unwrap().is_some()) + assert!(client.header(&BlockId::Number(1)).unwrap().is_some()) } #[tokio::test] async fn manual_seal_and_finalization() { let builder = TestClientBuilder::new(); - let backend = builder.backend(); - let client = Arc::new(builder.build()); - let select_chain = LongestChain::new(backend.clone()); + let (client, select_chain) = builder.build_with_longest_chain(); + let client = Arc::new(client); let inherent_data_providers = InherentDataProviders::new(); - let pool = Arc::new(BasicPool::new(Options::default(), api()).0); + let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let pool = Arc::new(BasicPool::with_revalidation_type( + Options::default(), api(), None, RevalidationType::Full, spawner, + )); let env = ProposerFactory::new( client.clone(), - pool.clone() + pool.clone(), + None, ); // this test checks that blocks are created as soon as an engine command is sent over the stream. let (mut sink, stream) = futures::channel::mpsc::channel(1024); let future = run_manual_seal( Box::new(client.clone()), env, - backend.clone(), + client.clone(), pool.pool().clone(), stream, select_chain, @@ -360,7 +342,7 @@ mod tests { } ); // assert that there's a new block in the db. - let header = backend.blockchain().header(BlockId::Number(1)).unwrap().unwrap(); + let header = client.header(&BlockId::Number(1)).unwrap().unwrap(); let (tx, rx) = futures::channel::oneshot::channel(); sink.send(EngineCommand::FinalizeBlock { sender: Some(tx), @@ -374,22 +356,25 @@ mod tests { #[tokio::test] async fn manual_seal_fork_blocks() { let builder = TestClientBuilder::new(); - let backend = builder.backend(); - let client = Arc::new(builder.build()); - let select_chain = LongestChain::new(backend.clone()); + let (client, select_chain) = builder.build_with_longest_chain(); + let client = Arc::new(client); let inherent_data_providers = InherentDataProviders::new(); let pool_api = api(); - let pool = Arc::new(BasicPool::new(Options::default(), pool_api.clone()).0); + let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let pool = Arc::new(BasicPool::with_revalidation_type( + Options::default(), pool_api.clone(), None, RevalidationType::Full, spawner, + )); let env = ProposerFactory::new( client.clone(), pool.clone(), + None, ); // this test checks that blocks are created as soon as an engine command is sent over the stream. let (mut sink, stream) = futures::channel::mpsc::channel(1024); let future = run_manual_seal( Box::new(client.clone()), env, - backend.clone(), + client.clone(), pool.pool().clone(), stream, select_chain, @@ -431,14 +416,15 @@ mod tests { } ); // assert that there's a new block in the db. - assert!(backend.blockchain().header(BlockId::Number(0)).unwrap().is_some()); + assert!(client.header(&BlockId::Number(0)).unwrap().is_some()); assert!(pool.submit_one(&BlockId::Number(1), SOURCE, uxt(Alice, 1)).await.is_ok()); + let header = client.header(&BlockId::Number(1)).expect("db error").expect("imported above"); pool.maintain(sp_transaction_pool::ChainEvent::NewBlock { - id: BlockId::Number(1), - header: backend.blockchain().header(BlockId::Number(1)).expect("db error").expect("imported above"), + hash: header.hash(), + header, is_new_best: true, - retracted: vec![], + tree_route: None, }).await; let (tx1, rx1) = futures::channel::oneshot::channel(); @@ -452,7 +438,7 @@ mod tests { rx1.await.expect("should be no error receiving"), Ok(_) ); - assert!(backend.blockchain().header(BlockId::Number(1)).unwrap().is_some()); + assert!(client.header(&BlockId::Number(1)).unwrap().is_some()); pool_api.increment_nonce(Alice.into()); assert!(pool.submit_one(&BlockId::Number(2), SOURCE, uxt(Alice, 2)).await.is_ok()); @@ -465,6 +451,6 @@ mod tests { }).await.is_ok()); let imported = rx2.await.unwrap().unwrap(); // assert that fork block is in the db - assert!(backend.blockchain().header(BlockId::Hash(imported.hash)).unwrap().is_some()) + assert!(client.header(&BlockId::Hash(imported.hash)).unwrap().is_some()) } } diff --git a/client/consensus/manual-seal/src/seal_new_block.rs b/client/consensus/manual-seal/src/seal_new_block.rs index 39d73e16ab74fdadde2e3a597fa2ef71615cc9fa..c5aea11ced316bba9a329ed954a01afcd49263ff 100644 --- a/client/consensus/manual-seal/src/seal_new_block.rs +++ b/client/consensus/manual-seal/src/seal_new_block.rs @@ -33,7 +33,6 @@ use sp_consensus::{ import_queue::BoxBlockImport, }; use sp_blockchain::HeaderBackend; -use sc_client_api::backend::Backend as ClientBackend; use std::collections::HashMap; use std::time::Duration; use sp_inherents::InherentDataProviders; @@ -42,7 +41,7 @@ use sp_inherents::InherentDataProviders; const MAX_PROPOSAL_DURATION: u64 = 10; /// params for sealing a new block -pub struct SealBlockParams<'a, B: BlockT, C, CB, E, T, P: txpool::ChainApi> { +pub struct SealBlockParams<'a, B: BlockT, SC, HB, E, T, P: txpool::ChainApi> { /// if true, empty blocks(without extrinsics) will be created. /// otherwise, will return Error::EmptyTransactionPool. pub create_empty: bool, @@ -54,12 +53,12 @@ pub struct SealBlockParams<'a, B: BlockT, C, CB, E, T, P: txpool::ChainApi> { pub sender: rpc::Sender::Hash>>, /// transaction pool pub pool: Arc>, - /// client backend - pub backend: Arc, + /// header backend + pub client: Arc, /// Environment trait object for creating a proposer pub env: &'a mut E, /// SelectChain object - pub select_chain: &'a C, + pub select_chain: &'a SC, /// block import object pub block_import: &'a mut BoxBlockImport, /// inherent data provider @@ -67,28 +66,28 @@ pub struct SealBlockParams<'a, B: BlockT, C, CB, E, T, P: txpool::ChainApi> { } /// seals a new block with the given params -pub async fn seal_new_block( +pub async fn seal_new_block( SealBlockParams { create_empty, finalize, pool, parent_hash, - backend: back_end, + client, select_chain, block_import, env, inherent_data_provider, mut sender, .. - }: SealBlockParams<'_, B, SC, CB, E, T, P> + }: SealBlockParams<'_, B, SC, HB, E, T, P> ) where B: BlockT, - CB: ClientBackend, + HB: HeaderBackend, E: Environment, >::Error: std::fmt::Display, >::Error: std::fmt::Display, - P: txpool::ChainApi::Hash>, + P: txpool::ChainApi, SC: SelectChain, { let future = async { @@ -101,7 +100,7 @@ pub async fn seal_new_block( // or fetch the best_block. let header = match parent_hash { Some(hash) => { - match back_end.blockchain().header(BlockId::Hash(hash))? { + match client.header(BlockId::Hash(hash))? { Some(header) => header, None => return Err(Error::BlockNotFound(format!("{}", hash))), } @@ -109,7 +108,7 @@ pub async fn seal_new_block( None => select_chain.best_chain()? }; - let mut proposer = env.init(&header) + let proposer = env.init(&header) .map_err(|err| Error::StringError(format!("{}", err))).await?; let id = inherent_data_provider.create_inherent_data()?; let inherents_len = id.len(); diff --git a/client/consensus/pow/Cargo.toml b/client/consensus/pow/Cargo.toml index c7832baae0ee4a2a27a35b88c4ec34f31e0854e5..b0b142fd84c32d6974d36457011cd5fda3d19018 100644 --- a/client/consensus/pow/Cargo.toml +++ b/client/consensus/pow/Cargo.toml @@ -1,28 +1,29 @@ [package] name = "sc-consensus-pow" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] description = "PoW consensus algorithm for substrate" edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive"] } -sp-core = { version = "2.0.0-alpha.5", path = "../../../primitives/core" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../../primitives/blockchain" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime" } -sp-api = { version = "2.0.0-alpha.5", path = "../../../primitives/api" } -sc-client-api = { version = "2.0.0-alpha.5", path = "../../api" } -sp-block-builder = { version = "2.0.0-alpha.5", path = "../../../primitives/block-builder" } -sp-inherents = { version = "2.0.0-alpha.5", path = "../../../primitives/inherents" } -sp-consensus-pow = { version = "0.8.0-alpha.5", path = "../../../primitives/consensus/pow" } -sp-consensus = { version = "0.8.0-alpha.5", path = "../../../primitives/consensus/common" } +codec = { package = "parity-scale-codec", version = "1.3.1", features = ["derive"] } +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../../primitives/blockchain" } +sp-runtime = { version = "2.0.0-rc4", path = "../../../primitives/runtime" } +sp-api = { version = "2.0.0-rc4", path = "../../../primitives/api" } +sc-client-api = { version = "2.0.0-rc4", path = "../../api" } +sp-block-builder = { version = "2.0.0-rc4", path = "../../../primitives/block-builder" } +sp-inherents = { version = "2.0.0-rc4", path = "../../../primitives/inherents" } +sp-consensus-pow = { version = "0.8.0-rc4", path = "../../../primitives/consensus/pow" } +sp-consensus = { version = "0.8.0-rc4", path = "../../../primitives/consensus/common" } log = "0.4.8" futures = { version = "0.3.1", features = ["compat"] } -sp-timestamp = { version = "2.0.0-alpha.5", path = "../../../primitives/timestamp" } +sp-timestamp = { version = "2.0.0-rc4", path = "../../../primitives/timestamp" } derive_more = "0.99.2" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.8.0-rc4"} diff --git a/client/consensus/pow/src/lib.rs b/client/consensus/pow/src/lib.rs index de41ea7bd2356f02f5857344b70eae335273a540..8c15528795c5534090ba3c959327a91274ce9c61 100644 --- a/client/consensus/pow/src/lib.rs +++ b/client/consensus/pow/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Proof of work consensus for Substrate. //! @@ -49,8 +51,11 @@ use sp_consensus::{ SelectChain, Error as ConsensusError, CanAuthorWith, RecordProof, BlockImport, BlockCheckParams, ImportResult, }; -use sp_consensus::import_queue::{BoxBlockImport, BasicQueue, Verifier}; +use sp_consensus::import_queue::{ + BoxBlockImport, BasicQueue, Verifier, BoxJustificationImport, BoxFinalityProofImport, +}; use codec::{Encode, Decode}; +use prometheus_endpoint::Registry; use sc_client_api; use log::*; use sp_timestamp::{InherentError as TIError, TimestampInherentData}; @@ -457,8 +462,12 @@ pub type PowImportQueue = BasicQueue; /// Import queue for PoW engine. pub fn import_queue( block_import: BoxBlockImport, + justification_import: Option>, + finality_proof_import: Option>, algorithm: Algorithm, inherent_data_providers: InherentDataProviders, + spawner: &impl sp_core::traits::SpawnNamed, + registry: Option<&Registry>, ) -> Result< PowImportQueue, sp_consensus::Error @@ -474,8 +483,10 @@ pub fn import_queue( Ok(BasicQueue::new( verifier, block_import, - None, - None + justification_import, + finality_proof_import, + spawner, + registry, )) } @@ -599,7 +610,7 @@ fn mine_loop( continue 'outer } - let mut proposer = futures::executor::block_on(env.init(&best_header)) + let proposer = futures::executor::block_on(env.init(&best_header)) .map_err(|e| Error::Environment(format!("{:?}", e)))?; let inherent_data = inherent_data_providers diff --git a/client/consensus/slots/Cargo.toml b/client/consensus/slots/Cargo.toml index bf973ef47a893bbd45a6bb47b03a9f5afbfd99df..39a4a9d47334deb47589092eaef57403d4709f63 100644 --- a/client/consensus/slots/Cargo.toml +++ b/client/consensus/slots/Cargo.toml @@ -1,32 +1,34 @@ [package] name = "sc-consensus-slots" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] description = "Generic slots-based utilities for consensus" edition = "2018" build = "build.rs" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0" } -sc-client-api = { version = "2.0.0-alpha.5", path = "../../api" } -sp-core = { version = "2.0.0-alpha.5", path = "../../../primitives/core" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../../primitives/blockchain" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime" } -sp-state-machine = { version = "0.8.0-alpha.5", path = "../../../primitives/state-machine" } -sp-api = { version = "2.0.0-alpha.5", path = "../../../primitives/api" } -sc-telemetry = { version = "2.0.0-alpha.5", path = "../../telemetry" } -sp-consensus = { version = "0.8.0-alpha.5", path = "../../../primitives/consensus/common" } -sp-inherents = { version = "2.0.0-alpha.5", path = "../../../primitives/inherents" } +codec = { package = "parity-scale-codec", version = "1.3.1" } +sc-client-api = { version = "2.0.0-rc4", path = "../../api" } +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } +sp-application-crypto = { version = "2.0.0-rc4", path = "../../../primitives/application-crypto" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../../primitives/blockchain" } +sp-consensus-slots = { version = "0.8.0-rc4", path = "../../../primitives/consensus/slots" } +sp-runtime = { version = "2.0.0-rc4", path = "../../../primitives/runtime" } +sp-state-machine = { version = "0.8.0-rc4", path = "../../../primitives/state-machine" } +sp-api = { version = "2.0.0-rc4", path = "../../../primitives/api" } +sc-telemetry = { version = "2.0.0-rc4", path = "../../telemetry" } +sp-consensus = { version = "0.8.0-rc4", path = "../../../primitives/consensus/common" } +sp-inherents = { version = "2.0.0-rc4", path = "../../../primitives/inherents" } futures = "0.3.4" futures-timer = "3.0.1" parking_lot = "0.10.0" log = "0.4.8" [dev-dependencies] -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../../test-utils/runtime/client" } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +substrate-test-runtime-client = { version = "2.0.0-rc4", path = "../../../test-utils/runtime/client" } diff --git a/client/consensus/slots/src/aux_schema.rs b/client/consensus/slots/src/aux_schema.rs index df4772a8e92a16be328b0b9d9d61d7501b1e21d0..1f1fe37068f82b2fef9c789bf0877068d0b1d0c3 100644 --- a/client/consensus/slots/src/aux_schema.rs +++ b/client/consensus/slots/src/aux_schema.rs @@ -19,6 +19,7 @@ use codec::{Encode, Decode}; use sc_client_api::backend::AuxStore; use sp_blockchain::{Result as ClientResult, Error as ClientError}; +use sp_consensus_slots::EquivocationProof; use sp_runtime::traits::Header; const SLOT_HEADER_MAP_KEY: &[u8] = b"slot_header_map"; @@ -44,31 +45,6 @@ fn load_decode(backend: &C, key: &[u8]) -> ClientResult> } } -/// Represents an equivocation proof. -#[derive(Debug, Clone)] -pub struct EquivocationProof { - slot: u64, - fst_header: H, - snd_header: H, -} - -impl EquivocationProof { - /// Get the slot number where the equivocation happened. - pub fn slot(&self) -> u64 { - self.slot - } - - /// Get the first header involved in the equivocation. - pub fn fst_header(&self) -> &H { - &self.fst_header - } - - /// Get the second header involved in the equivocation. - pub fn snd_header(&self) -> &H { - &self.snd_header - } -} - /// Checks if the header is an equivocation and returns the proof in that case. /// /// Note: it detects equivocations only when slot_now - slot <= MAX_SLOT_CAPACITY. @@ -78,15 +54,15 @@ pub fn check_equivocation( slot: u64, header: &H, signer: &P, -) -> ClientResult>> +) -> ClientResult>> where H: Header, C: AuxStore, P: Clone + Encode + Decode + PartialEq, { // We don't check equivocations for old headers out of our capacity. - if slot_now - slot > MAX_SLOT_CAPACITY { - return Ok(None) + if slot_now.saturating_sub(slot) > MAX_SLOT_CAPACITY { + return Ok(None); } // Key for this slot. @@ -102,6 +78,11 @@ pub fn check_equivocation( let first_saved_slot = load_decode::<_, u64>(backend, &slot_header_start[..])? .unwrap_or(slot); + if slot_now < first_saved_slot { + // The code below assumes that slots will be visited sequentially. + return Ok(None); + } + for (prev_header, prev_signer) in headers_with_sig.iter() { // A proof of equivocation consists of two headers: // 1) signed by the same voter, @@ -109,12 +90,13 @@ pub fn check_equivocation( // 2) with different hash if header.hash() != prev_header.hash() { return Ok(Some(EquivocationProof { - slot, // 3) and mentioning the same slot. - fst_header: prev_header.clone(), - snd_header: header.clone(), + slot_number: slot, + offender: signer.clone(), + first_header: prev_header.clone(), + second_header: header.clone(), })); } else { - // We don't need to continue in case of duplicated header, + // We don't need to continue in case of duplicated header, // since it's already saved and a possible equivocation // would have been detected before. return Ok(None) diff --git a/client/consensus/slots/src/lib.rs b/client/consensus/slots/src/lib.rs index d0f1f6ec4bf9ea1f91cbe48974981df92d3ac918..7687d3114b31dcd9dd49d6aa5c3d7db0b7d708c2 100644 --- a/client/consensus/slots/src/lib.rs +++ b/client/consensus/slots/src/lib.rs @@ -20,7 +20,6 @@ //! time during which certain events can and/or must occur. This crate //! provides generic functionality for slots. -#![deny(warnings)] #![forbid(unsafe_code, missing_docs)] mod slots; @@ -121,11 +120,10 @@ pub trait SimpleSlotWorker { StorageChanges<>::Transaction, B>, Self::Claim, Self::EpochData, - ) -> sp_consensus::BlockImportParams< - B, - >::Transaction - > - + Send + ) -> Result< + sp_consensus::BlockImportParams>::Transaction>, + sp_consensus::Error + > + Send + 'static >; /// Whether to force authoring if offline. @@ -240,7 +238,7 @@ pub trait SimpleSlotWorker { let logs = self.pre_digest_data(slot_number, &claim); // deadline our production to approx. the end of the slot - let proposing = awaiting_proposer.and_then(move |mut proposer| proposer.propose( + let proposing = awaiting_proposer.and_then(move |proposer| proposer.propose( slot_info.inherent_data, sp_runtime::generic::Digest { logs, @@ -273,7 +271,7 @@ pub trait SimpleSlotWorker { let block_import = self.block_import(); let logging_target = self.logging_target(); - Box::pin(proposal_work.map_ok(move |(proposal, claim)| { + Box::pin(proposal_work.and_then(move |(proposal, claim)| { let (header, body) = proposal.block.deconstruct(); let header_num = *header.number(); let header_hash = header.hash(); @@ -288,6 +286,11 @@ pub trait SimpleSlotWorker { epoch_data, ); + let block_import_params = match block_import_params { + Ok(params) => params, + Err(e) => return future::err(e), + }; + info!( "🔖 Pre-sealed block for proposal at {}. Hash now {:?}, previously {:?}.", header_num, @@ -312,6 +315,7 @@ pub trait SimpleSlotWorker { "hash" => ?parent_hash, "err" => ?err, ); } + future::ready(Ok(())) })) } } @@ -451,7 +455,7 @@ impl SlotDuration { CB: FnOnce(ApiRef, &BlockId) -> sp_blockchain::Result, T: SlotData + Encode + Decode + Debug, { - match client.get_aux(T::SLOT_KEY)? { + let slot_duration = match client.get_aux(T::SLOT_KEY)? { Some(v) => ::decode(&mut &v[..]) .map(SlotDuration) .map_err(|_| { @@ -466,8 +470,8 @@ impl SlotDuration { cb(client.runtime_api(), &BlockId::number(Zero::zero()))?; info!( - "Loaded block-time = {:?} milliseconds from genesis on first-launch", - genesis_slot_duration + "⏱ Loaded block-time = {:?} milliseconds from genesis on first-launch", + genesis_slot_duration.slot_duration() ); genesis_slot_duration @@ -475,7 +479,15 @@ impl SlotDuration { Ok(SlotDuration(genesis_slot_duration)) } + }?; + + if slot_duration.slot_duration() == 0 { + return Err(sp_blockchain::Error::Msg( + "Invalid value for slot_duration: the value must be greater than 0.".into(), + )) } + + Ok(slot_duration) } /// Returns slot data value. @@ -483,3 +495,120 @@ impl SlotDuration { self.0.clone() } } + +/// Calculate a slot duration lenience based on the number of missed slots from current +/// to parent. If the number of skipped slots is greated than 0 this method will apply +/// an exponential backoff of at most `2^7 * slot_duration`, if no slots were skipped +/// this method will return `None.` +pub fn slot_lenience_exponential(parent_slot: u64, slot_info: &SlotInfo) -> Option { + // never give more than 2^this times the lenience. + const BACKOFF_CAP: u64 = 7; + + // how many slots it takes before we double the lenience. + const BACKOFF_STEP: u64 = 2; + + // we allow a lenience of the number of slots since the head of the + // chain was produced, minus 1 (since there is always a difference of at least 1) + // + // exponential back-off. + // in normal cases we only attempt to issue blocks up to the end of the slot. + // when the chain has been stalled for a few slots, we give more lenience. + let skipped_slots = slot_info.number.saturating_sub(parent_slot + 1); + + if skipped_slots == 0 { + None + } else { + let slot_lenience = skipped_slots / BACKOFF_STEP; + let slot_lenience = std::cmp::min(slot_lenience, BACKOFF_CAP); + let slot_lenience = 1 << slot_lenience; + Some(Duration::from_millis(slot_lenience * slot_info.duration)) + } +} + +/// Calculate a slot duration lenience based on the number of missed slots from current +/// to parent. If the number of skipped slots is greated than 0 this method will apply +/// a linear backoff of at most `20 * slot_duration`, if no slots were skipped +/// this method will return `None.` +pub fn slot_lenience_linear(parent_slot: u64, slot_info: &SlotInfo) -> Option { + // never give more than 20 times more lenience. + const BACKOFF_CAP: u64 = 20; + + // we allow a lenience of the number of slots since the head of the + // chain was produced, minus 1 (since there is always a difference of at least 1) + // + // linear back-off. + // in normal cases we only attempt to issue blocks up to the end of the slot. + // when the chain has been stalled for a few slots, we give more lenience. + let skipped_slots = slot_info.number.saturating_sub(parent_slot + 1); + + if skipped_slots == 0 { + None + } else { + let slot_lenience = std::cmp::min(skipped_slots, BACKOFF_CAP); + Some(Duration::from_millis(slot_lenience * slot_info.duration)) + } +} + +#[cfg(test)] +mod test { + use std::time::{Duration, Instant}; + + const SLOT_DURATION: Duration = Duration::from_millis(6000); + + fn slot(n: u64) -> super::slots::SlotInfo { + super::slots::SlotInfo { + number: n, + last_number: n - 1, + duration: SLOT_DURATION.as_millis() as u64, + timestamp: Default::default(), + inherent_data: Default::default(), + ends_at: Instant::now(), + } + } + + #[test] + fn linear_slot_lenience() { + // if no slots are skipped there should be no lenience + assert_eq!(super::slot_lenience_linear(1, &slot(2)), None); + + // otherwise the lenience is incremented linearly with + // the number of skipped slots. + for n in 3..=22 { + assert_eq!( + super::slot_lenience_linear(1, &slot(n)), + Some(SLOT_DURATION * (n - 2) as u32), + ); + } + + // but we cap it to a maximum of 20 slots + assert_eq!( + super::slot_lenience_linear(1, &slot(23)), + Some(SLOT_DURATION * 20), + ); + } + + #[test] + fn exponential_slot_lenience() { + // if no slots are skipped there should be no lenience + assert_eq!(super::slot_lenience_exponential(1, &slot(2)), None); + + // otherwise the lenience is incremented exponentially every two slots + for n in 3..=17 { + assert_eq!( + super::slot_lenience_exponential(1, &slot(n)), + Some(SLOT_DURATION * 2u32.pow((n / 2 - 1) as u32)), + ); + } + + // but we cap it to a maximum of 14 slots + assert_eq!( + super::slot_lenience_exponential(1, &slot(18)), + Some(SLOT_DURATION * 2u32.pow(7)), + ); + + assert_eq!( + super::slot_lenience_exponential(1, &slot(19)), + Some(SLOT_DURATION * 2u32.pow(7)), + ); + } +} diff --git a/client/consensus/uncles/Cargo.toml b/client/consensus/uncles/Cargo.toml index 7e8014199baa5241935cc198cce100bba9677cfa..957e8e3c0b8905d041992ac950718258739b12ce 100644 --- a/client/consensus/uncles/Cargo.toml +++ b/client/consensus/uncles/Cargo.toml @@ -1,21 +1,21 @@ [package] name = "sc-consensus-uncles" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] description = "Generic uncle inclusion utilities for consensus" edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" -[dependencies] -sc-client-api = { version = "2.0.0-alpha.5", path = "../../api" } -sp-core = { version = "2.0.0-alpha.5", path = "../../../primitives/core" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime" } -sp-authorship = { version = "2.0.0-alpha.5", path = "../../../primitives/authorship" } -sp-consensus = { version = "0.8.0-alpha.5", path = "../../../primitives/consensus/common" } -sp-inherents = { version = "2.0.0-alpha.5", path = "../../../primitives/inherents" } -log = "0.4.8" - [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +sc-client-api = { version = "2.0.0-rc4", path = "../../api" } +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } +sp-runtime = { version = "2.0.0-rc4", path = "../../../primitives/runtime" } +sp-authorship = { version = "2.0.0-rc4", path = "../../../primitives/authorship" } +sp-consensus = { version = "0.8.0-rc4", path = "../../../primitives/consensus/common" } +sp-inherents = { version = "2.0.0-rc4", path = "../../../primitives/inherents" } +log = "0.4.8" diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml index 9308d4ee74adf169deb8faff092fd81f26cfbdd9..9eb9dd8914fc974bb7c8b556d6f80e79ff336de9 100644 --- a/client/db/Cargo.toml +++ b/client/db/Cargo.toml @@ -1,48 +1,52 @@ [package] name = "sc-client-db" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Client backend that uses RocksDB database as storage." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] parking_lot = "0.10.0" log = "0.4.8" -rand = "0.7" -kvdb = "0.5.0" -kvdb-rocksdb = { version = "0.7", optional = true } -kvdb-memorydb = "0.5.0" +kvdb = "0.7.0" +kvdb-rocksdb = { version = "0.9", optional = true } +kvdb-memorydb = "0.7.0" linked-hash-map = "0.5.2" hash-db = "0.15.2" -parity-util-mem = { version = "0.6.0", default-features = false, features = ["std"] } -codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive"] } +parity-util-mem = { version = "0.7.0", default-features = false, features = ["std"] } +codec = { package = "parity-scale-codec", version = "1.3.1", features = ["derive"] } +blake2-rfc = "0.2.18" -sc-client-api = { version = "2.0.0-alpha.5", path = "../api" } -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../primitives/runtime" } -sc-client = { version = "0.8.0-alpha.5", path = "../" } -sp-state-machine = { version = "0.8.0-alpha.5", path = "../../primitives/state-machine" } -sc-executor = { version = "0.8.0-alpha.5", path = "../executor" } -sc-state-db = { version = "0.8.0-alpha.5", path = "../state-db" } -sp-trie = { version = "2.0.0-alpha.5", path = "../../primitives/trie" } -sp-consensus = { version = "0.8.0-alpha.5", path = "../../primitives/consensus/common" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../primitives/blockchain" } -prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.8.0-alpha.5", path = "../../utils/prometheus" } +sc-client-api = { version = "2.0.0-rc4", path = "../api" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +sp-runtime = { version = "2.0.0-rc4", path = "../../primitives/runtime" } +sp-state-machine = { version = "0.8.0-rc4", path = "../../primitives/state-machine" } +sc-executor = { version = "0.8.0-rc4", path = "../executor" } +sc-state-db = { version = "0.8.0-rc4", path = "../state-db" } +sp-trie = { version = "2.0.0-rc4", path = "../../primitives/trie" } +sp-consensus = { version = "0.8.0-rc4", path = "../../primitives/consensus/common" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../primitives/blockchain" } +sp-database = { version = "2.0.0-rc4", path = "../../primitives/database" } +parity-db = { version = "0.1.2", optional = true } +prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.8.0-rc4", path = "../../utils/prometheus" } [dev-dependencies] -sp-keyring = { version = "2.0.0-alpha.5", path = "../../primitives/keyring" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../test-utils/runtime/client" } +sp-keyring = { version = "2.0.0-rc4", path = "../../primitives/keyring" } +substrate-test-runtime-client = { version = "2.0.0-rc4", path = "../../test-utils/runtime/client" } env_logger = "0.7.0" quickcheck = "0.9" -kvdb-rocksdb = "0.7" +kvdb-rocksdb = "0.9" tempfile = "3" [features] default = [] test-helpers = [] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +with-kvdb-rocksdb = ["kvdb-rocksdb"] +with-parity-db = ["parity-db"] +with-subdb = [] diff --git a/client/db/src/bench.rs b/client/db/src/bench.rs index 02b30a085af2b9fddf3e22671d3f3ce0c469ec0a..c3bed3e24f617477e838ae271b2452162c3cbad3 100644 --- a/client/db/src/bench.rs +++ b/client/db/src/bench.rs @@ -1,40 +1,42 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! State backend that's useful for benchmarking use std::sync::Arc; -use std::path::PathBuf; use std::cell::{Cell, RefCell}; use std::collections::HashMap; -use rand::Rng; use hash_db::{Prefix, Hasher}; use sp_trie::{MemoryDB, prefixed_key}; -use sp_core::storage::ChildInfo; +use sp_core::{storage::ChildInfo, hexdisplay::HexDisplay}; use sp_runtime::traits::{Block as BlockT, HashFor}; use sp_runtime::Storage; -use sp_state_machine::{DBValue, backend::Backend as StateBackend}; +use sp_state_machine::{DBValue, backend::Backend as StateBackend, StorageCollection}; use kvdb::{KeyValueDB, DBTransaction}; -use kvdb_rocksdb::{Database, DatabaseConfig}; +use crate::storage_cache::{CachingState, SharedCache, new_shared_cache}; type DbState = sp_state_machine::TrieBackend< Arc>>, HashFor >; +type State = CachingState, B>; + struct StorageDb { db: Arc, _block: std::marker::PhantomData, @@ -48,88 +50,186 @@ impl sp_state_machine::Storage> for StorageDb { - path: PathBuf, root: Cell, genesis_root: B::Hash, - state: RefCell>>, + state: RefCell>>, db: Cell>>, genesis: HashMap, (Vec, i32)>, record: Cell>>, - cache_size_mb: Option, + shared_cache: SharedCache, // shared cache is always empty + key_tracker: RefCell, KeyTracker>>, + read_write_tracker: RefCell, + whitelist: RefCell>>, } impl BenchmarkingState { /// Create a new instance that creates a database in a temporary dir. - pub fn new(genesis: Storage, cache_size_mb: Option) -> Result { - let temp_dir = PathBuf::from(std::env::temp_dir()); - let name: String = rand::thread_rng().sample_iter(&rand::distributions::Alphanumeric).take(10).collect(); - let path = temp_dir.join(&name); - + pub fn new(genesis: Storage, _cache_size_mb: Option) -> Result { let mut root = B::Hash::default(); let mut mdb = MemoryDB::>::default(); sp_state_machine::TrieDBMut::>::new(&mut mdb, &mut root); - std::fs::create_dir(&path).map_err(|_| String::from("Error creating temp dir"))?; let mut state = BenchmarkingState { state: RefCell::new(None), db: Cell::new(None), - path, root: Cell::new(root), genesis: Default::default(), genesis_root: Default::default(), record: Default::default(), - cache_size_mb, + shared_cache: new_shared_cache(0, (1, 10)), + key_tracker: Default::default(), + read_write_tracker: Default::default(), + whitelist: Default::default(), }; + state.add_whitelist_to_tracker(); + state.reopen()?; - let child_delta = genesis.children.into_iter().map(|(storage_key, child_content)| ( - storage_key, - child_content.data.into_iter().map(|(k, v)| (k, Some(v))), - child_content.child_info + let child_delta = genesis.children_default.iter().map(|(_storage_key, child_content)| ( + &child_content.child_info, + child_content.data.iter().map(|(k, v)| (k.as_ref(), Some(v.as_ref()))), )); let (root, transaction): (B::Hash, _) = state.state.borrow_mut().as_mut().unwrap().full_storage_root( - genesis.top.into_iter().map(|(k, v)| (k, Some(v))), + genesis.top.iter().map(|(k, v)| (k.as_ref(), Some(v.as_ref()))), child_delta, ); state.genesis = transaction.clone().drain(); state.genesis_root = root.clone(); - state.commit(root, transaction)?; + state.commit(root, transaction, Vec::new())?; + state.record.take(); Ok(state) } fn reopen(&self) -> Result<(), String> { *self.state.borrow_mut() = None; - self.db.set(None); - let mut db_config = DatabaseConfig::with_columns(1); - if let Some(size) = &self.cache_size_mb { - db_config.memory_budget.insert(0, *size); - } - let path = self.path.to_str() - .ok_or_else(|| String::from("Invalid database path"))?; - let db = Arc::new(Database::open(&db_config, &path).map_err(|e| format!("Error opening database: {:?}", e))?); + let db = match self.db.take() { + Some(db) => db, + None => Arc::new(::kvdb_memorydb::create(1)), + }; self.db.set(Some(db.clone())); let storage_db = Arc::new(StorageDb:: { db, _block: Default::default() }); - *self.state.borrow_mut() = Some(DbState::::new(storage_db, self.root.get())); + *self.state.borrow_mut() = Some(State::new( + DbState::::new(storage_db, self.root.get()), + self.shared_cache.clone(), + None + )); Ok(()) } - fn kill(&self) -> Result<(), String> { - self.db.set(None); - *self.state.borrow_mut() = None; - let mut root = B::Hash::default(); - let mut mdb = MemoryDB::>::default(); - sp_state_machine::TrieDBMut::>::new(&mut mdb, &mut root); - self.root.set(root); + fn add_whitelist_to_tracker(&self) { + let mut key_tracker = self.key_tracker.borrow_mut(); + + let whitelisted = KeyTracker { + has_been_read: true, + has_been_written: true, + }; + + let whitelist = self.whitelist.borrow(); - std::fs::remove_dir_all(&self.path).map_err(|_| "Error removing database dir".into()) + whitelist.iter().for_each(|key| { + key_tracker.insert(key.to_vec(), whitelisted); + }); + } + + fn wipe_tracker(&self) { + *self.key_tracker.borrow_mut() = HashMap::new(); + self.add_whitelist_to_tracker(); + *self.read_write_tracker.borrow_mut() = Default::default(); } -} -impl Drop for BenchmarkingState { - fn drop(&mut self) { - self.kill().ok(); + fn add_read_key(&self, key: &[u8]) { + log::trace!(target: "benchmark", "Read: {}", HexDisplay::from(&key)); + + let mut key_tracker = self.key_tracker.borrow_mut(); + let mut read_write_tracker = self.read_write_tracker.borrow_mut(); + + let maybe_tracker = key_tracker.get(key); + + let has_been_read = KeyTracker { + has_been_read: true, + has_been_written: false, + }; + + match maybe_tracker { + None => { + key_tracker.insert(key.to_vec(), has_been_read); + read_write_tracker.add_read(); + }, + Some(tracker) => { + if !tracker.has_been_read { + key_tracker.insert(key.to_vec(), has_been_read); + read_write_tracker.add_read(); + } else { + read_write_tracker.add_repeat_read(); + } + } + } + } + + fn add_write_key(&self, key: &[u8]) { + log::trace!(target: "benchmark", "Write: {}", HexDisplay::from(&key)); + + let mut key_tracker = self.key_tracker.borrow_mut(); + let mut read_write_tracker = self.read_write_tracker.borrow_mut(); + + let maybe_tracker = key_tracker.get(key); + + // If we have written to the key, we also consider that we have read from it. + let has_been_written = KeyTracker { + has_been_read: true, + has_been_written: true, + }; + + match maybe_tracker { + None => { + key_tracker.insert(key.to_vec(), has_been_written); + read_write_tracker.add_write(); + }, + Some(tracker) => { + if !tracker.has_been_written { + key_tracker.insert(key.to_vec(), has_been_written); + read_write_tracker.add_write(); + } else { + read_write_tracker.add_repeat_write(); + } + } + } } } @@ -143,46 +243,50 @@ impl StateBackend> for BenchmarkingState { type TrieBackendStorage = as StateBackend>>::TrieBackendStorage; fn storage(&self, key: &[u8]) -> Result>, Self::Error> { + self.add_read_key(key); self.state.borrow().as_ref().ok_or_else(state_err)?.storage(key) } fn storage_hash(&self, key: &[u8]) -> Result, Self::Error> { + self.add_read_key(key); self.state.borrow().as_ref().ok_or_else(state_err)?.storage_hash(key) } fn child_storage( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) -> Result>, Self::Error> { - self.state.borrow().as_ref().ok_or_else(state_err)?.child_storage(storage_key, child_info, key) + self.add_read_key(key); + self.state.borrow().as_ref().ok_or_else(state_err)?.child_storage(child_info, key) } fn exists_storage(&self, key: &[u8]) -> Result { + self.add_read_key(key); self.state.borrow().as_ref().ok_or_else(state_err)?.exists_storage(key) } fn exists_child_storage( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) -> Result { - self.state.borrow().as_ref().ok_or_else(state_err)?.exists_child_storage(storage_key, child_info, key) + self.add_read_key(key); + self.state.borrow().as_ref().ok_or_else(state_err)?.exists_child_storage(child_info, key) } fn next_storage_key(&self, key: &[u8]) -> Result>, Self::Error> { + self.add_read_key(key); self.state.borrow().as_ref().ok_or_else(state_err)?.next_storage_key(key) } fn next_child_storage_key( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) -> Result>, Self::Error> { - self.state.borrow().as_ref().ok_or_else(state_err)?.next_child_storage_key(storage_key, child_info, key) + self.add_read_key(key); + self.state.borrow().as_ref().ok_or_else(state_err)?.next_child_storage_key(child_info, key) } fn for_keys_with_prefix(&self, prefix: &[u8], f: F) { @@ -199,42 +303,38 @@ impl StateBackend> for BenchmarkingState { fn for_keys_in_child_storage( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, f: F, ) { if let Some(ref state) = *self.state.borrow() { - state.for_keys_in_child_storage(storage_key, child_info, f) + state.for_keys_in_child_storage(child_info, f) } } fn for_child_keys_with_prefix( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, prefix: &[u8], f: F, ) { if let Some(ref state) = *self.state.borrow() { - state.for_child_keys_with_prefix(storage_key, child_info, prefix, f) + state.for_child_keys_with_prefix(child_info, prefix, f) } } - fn storage_root(&self, delta: I) -> (B::Hash, Self::Transaction) where - I: IntoIterator, Option>)> - { + fn storage_root<'a>( + &self, + delta: impl Iterator)>, + ) -> (B::Hash, Self::Transaction) where B::Hash: Ord { self.state.borrow().as_ref().map_or(Default::default(), |s| s.storage_root(delta)) } - fn child_storage_root( + fn child_storage_root<'a>( &self, - storage_key: &[u8], - child_info: ChildInfo, - delta: I, - ) -> (B::Hash, bool, Self::Transaction) where - I: IntoIterator, Option>)>, - { - self.state.borrow().as_ref().map_or(Default::default(), |s| s.child_storage_root(storage_key, child_info, delta)) + child_info: &ChildInfo, + delta: impl Iterator)>, + ) -> (B::Hash, bool, Self::Transaction) where B::Hash: Ord { + self.state.borrow().as_ref().map_or(Default::default(), |s| s.child_storage_root(child_info, delta)) } fn pairs(&self) -> Vec<(Vec, Vec)> { @@ -247,11 +347,10 @@ impl StateBackend> for BenchmarkingState { fn child_keys( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, prefix: &[u8], ) -> Vec> { - self.state.borrow().as_ref().map_or(Default::default(), |s| s.child_keys(storage_key, child_info, prefix)) + self.state.borrow().as_ref().map_or(Default::default(), |s| s.child_keys(child_info, prefix)) } fn as_trie_backend(&mut self) @@ -260,8 +359,11 @@ impl StateBackend> for BenchmarkingState { None } - fn commit(&self, storage_root: as Hasher>::Out, mut transaction: Self::Transaction) - -> Result<(), Self::Error> + fn commit(&self, + storage_root: as Hasher>::Out, + mut transaction: Self::Transaction, + storage_changes: StorageCollection, + ) -> Result<(), Self::Error> { if let Some(db) = self.db.take() { let mut db_transaction = DBTransaction::new(); @@ -275,9 +377,17 @@ impl StateBackend> for BenchmarkingState { } keys.push(key); } - self.record.set(keys); + let mut record = self.record.take(); + record.extend(keys); + self.record.set(record); db.write(db_transaction).map_err(|_| String::from("Error committing transaction"))?; self.root.set(storage_root); + self.db.set(Some(db)); + + // Track DB Writes + storage_changes.iter().for_each(|(key, _)| { + self.add_write_key(key); + }); } else { return Err("Trying to commit to a closed db".into()) } @@ -296,16 +406,30 @@ impl StateBackend> for BenchmarkingState { } } db.write(db_transaction).map_err(|_| String::from("Error committing transaction"))?; + self.db.set(Some(db)); } - self.db.set(None); - *self.state.borrow_mut() = None; - self.root.set(self.genesis_root.clone()); self.reopen()?; + self.wipe_tracker(); Ok(()) } + /// Get the key tracking information for the state db. + fn read_write_count(&self) -> (u32, u32, u32, u32) { + let count = *self.read_write_tracker.borrow_mut(); + (count.reads, count.repeat_reads, count.writes, count.repeat_writes) + } + + /// Reset the key tracking information for the state db. + fn reset_read_write_count(&self) { + self.wipe_tracker() + } + + fn set_whitelist(&self, new: Vec>) { + *self.whitelist.borrow_mut() = new; + } + fn register_overlay_stats(&mut self, stats: &sp_state_machine::StateMachineStats) { self.state.borrow_mut().as_mut().map(|s| s.register_overlay_stats(stats)); } @@ -317,6 +441,6 @@ impl StateBackend> for BenchmarkingState { impl std::fmt::Debug for BenchmarkingState { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "DB at {:?}", self.path) + write!(f, "Bench DB") } } diff --git a/client/db/src/cache/list_cache.rs b/client/db/src/cache/list_cache.rs index f3a8171342c9158997cb1dd08e3d90aa03e94b8a..15ad339b1f2c1a387fd3e5dbac70eaef5df3a79b 100644 --- a/client/db/src/cache/list_cache.rs +++ b/client/db/src/cache/list_cache.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! List-based cache. //! @@ -858,16 +860,15 @@ fn read_forks>( } #[cfg(test)] -pub mod tests { +mod tests { use substrate_test_runtime_client::runtime::H256; use sp_runtime::testing::{Header, Block as RawBlock, ExtrinsicWrapper}; - use sp_runtime::traits::Header as HeaderT; use crate::cache::list_storage::tests::{DummyStorage, FaultyStorage, DummyTransaction}; use super::*; type Block = RawBlock>; - pub fn test_id(number: u64) -> ComplexBlockId { + fn test_id(number: u64) -> ComplexBlockId { ComplexBlockId::new(H256::from_low_u64_be(number), number) } @@ -1764,7 +1765,7 @@ pub mod tests { Some(Entry { valid_from: test_id(20), value: 20 }), vec![5, 6].into_iter().collect(), ))); - + assert_eq!( ops.operations, vec![CommitOperation::BlockFinalized( diff --git a/client/db/src/cache/list_entry.rs b/client/db/src/cache/list_entry.rs index e18434329079b68d1bc4a13af4a06698dd88d9d8..d14fab9274ccb830694082491b5f16bcf27ecf2b 100644 --- a/client/db/src/cache/list_entry.rs +++ b/client/db/src/cache/list_entry.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! List-cache storage entries. @@ -115,10 +117,14 @@ impl StorageEntry { #[cfg(test)] mod tests { - use crate::cache::list_cache::tests::test_id; use crate::cache::list_storage::tests::{DummyStorage, FaultyStorage}; + use substrate_test_runtime_client::runtime::{H256, Block}; use super::*; + fn test_id(number: u64) -> ComplexBlockId { + ComplexBlockId::new(H256::from_low_u64_be(number), number) + } + #[test] fn entry_try_update_works() { // when trying to update with None value diff --git a/client/db/src/cache/list_storage.rs b/client/db/src/cache/list_storage.rs index 606090ee1401dc89d25e1d005824a6fa083cba39..377d744effa60faf57521d2a490852ef757ce1bf 100644 --- a/client/db/src/cache/list_storage.rs +++ b/client/db/src/cache/list_storage.rs @@ -1,34 +1,36 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! List-cache storage definition and implementation. use std::sync::Arc; -use kvdb::{KeyValueDB, DBTransaction}; - use sp_blockchain::{Error as ClientError, Result as ClientResult}; use codec::{Encode, Decode}; use sp_runtime::generic::BlockId; use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor}; -use crate::utils::{self, db_err, meta_keys}; +use sp_database::{Database, Transaction}; +use crate::utils::{self, meta_keys}; use crate::cache::{CacheItemT, ComplexBlockId}; use crate::cache::list_cache::{CommitOperation, Fork}; use crate::cache::list_entry::{Entry, StorageEntry}; +use crate::DbHash; /// Single list-cache metadata. #[derive(Debug)] @@ -97,19 +99,19 @@ pub struct DbColumns { pub struct DbStorage { name: Vec, meta_key: Vec, - db: Arc, + db: Arc>, columns: DbColumns, } impl DbStorage { /// Create new database-backed list cache storage. - pub fn new(name: Vec, db: Arc, columns: DbColumns) -> Self { + pub fn new(name: Vec, db: Arc>, columns: DbColumns) -> Self { let meta_key = meta::key(&name); DbStorage { name, meta_key, db, columns } } /// Get reference to the database. - pub fn db(&self) -> &Arc { &self.db } + pub fn db(&self) -> &Arc> { &self.db } /// Get reference to the database columns. pub fn columns(&self) -> &DbColumns { &self.columns } @@ -135,49 +137,45 @@ impl Storage for DbStorage { } fn read_meta(&self) -> ClientResult> { - self.db.get(self.columns.meta, &self.meta_key) - .map_err(db_err) - .and_then(|meta| match meta { - Some(meta) => meta::decode(&*meta), - None => Ok(Metadata { - finalized: None, - unfinalized: Vec::new(), - }), + match self.db.get(self.columns.meta, &self.meta_key) { + Some(meta) => meta::decode(&*meta), + None => Ok(Metadata { + finalized: None, + unfinalized: Vec::new(), }) + } } fn read_entry(&self, at: &ComplexBlockId) -> ClientResult>> { - self.db.get(self.columns.cache, &self.encode_block_id(at)) - .map_err(db_err) - .and_then(|entry| match entry { - Some(entry) => StorageEntry::::decode(&mut &entry[..]) - .map_err(|_| ClientError::Backend("Failed to decode cache entry".into())) - .map(Some), - None => Ok(None), - }) + match self.db.get(self.columns.cache, &self.encode_block_id(at)) { + Some(entry) => StorageEntry::::decode(&mut &entry[..]) + .map_err(|_| ClientError::Backend("Failed to decode cache entry".into())) + .map(Some), + None => Ok(None), + } } } /// Database-backed list cache storage transaction. pub struct DbStorageTransaction<'a> { storage: &'a DbStorage, - tx: &'a mut DBTransaction, + tx: &'a mut Transaction, } impl<'a> DbStorageTransaction<'a> { /// Create new database transaction. - pub fn new(storage: &'a DbStorage, tx: &'a mut DBTransaction) -> Self { + pub fn new(storage: &'a DbStorage, tx: &'a mut Transaction) -> Self { DbStorageTransaction { storage, tx } } } impl<'a, Block: BlockT, T: CacheItemT> StorageTransaction for DbStorageTransaction<'a> { fn insert_storage_entry(&mut self, at: &ComplexBlockId, entry: &StorageEntry) { - self.tx.put(self.storage.columns.cache, &self.storage.encode_block_id(at), &entry.encode()); + self.tx.set_from_vec(self.storage.columns.cache, &self.storage.encode_block_id(at), entry.encode()); } fn remove_storage_entry(&mut self, at: &ComplexBlockId) { - self.tx.delete(self.storage.columns.cache, &self.storage.encode_block_id(at)); + self.tx.remove(self.storage.columns.cache, &self.storage.encode_block_id(at)); } fn update_meta( @@ -186,10 +184,10 @@ impl<'a, Block: BlockT, T: CacheItemT> StorageTransaction for DbStorag unfinalized: &[Fork], operation: &CommitOperation, ) { - self.tx.put( + self.tx.set_from_vec( self.storage.columns.meta, &self.storage.meta_key, - &meta::encode(best_finalized_entry, unfinalized, operation)); + meta::encode(best_finalized_entry, unfinalized, operation)); } } diff --git a/client/db/src/cache/mod.rs b/client/db/src/cache/mod.rs index 8fd1adc094ae4e241c7f0e73e8ffedecd60a7cd4..5501f0f1864c156745c6a3e63e4d8ced9a1cf25c 100644 --- a/client/db/src/cache/mod.rs +++ b/client/db/src/cache/mod.rs @@ -1,32 +1,34 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! DB-backed cache of blockchain data. use std::{sync::Arc, collections::{HashMap, hash_map::Entry}}; use parking_lot::RwLock; -use kvdb::{KeyValueDB, DBTransaction}; - use sc_client_api::blockchain::{well_known_cache_keys::{self, Id as CacheKeyId}, Cache as BlockchainCache}; -use sp_blockchain::Result as ClientResult; +use sp_blockchain::{Result as ClientResult, HeaderMetadataCache}; +use sp_database::{Database, Transaction}; use codec::{Encode, Decode}; use sp_runtime::generic::BlockId; use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero}; -use crate::utils::{self, COLUMN_META, db_err}; +use crate::utils::{self, COLUMN_META}; +use crate::DbHash; use self::list_cache::{ListCache, PruningStrategy}; @@ -78,7 +80,8 @@ impl CacheItemT for T where T: Clone + Decode + Encode + PartialEq {} /// Database-backed blockchain data cache. pub struct DbCache { cache_at: HashMap, self::list_storage::DbStorage>>, - db: Arc, + header_metadata_cache: Arc>, + db: Arc>, key_lookup_column: u32, header_column: u32, cache_column: u32, @@ -89,7 +92,8 @@ pub struct DbCache { impl DbCache { /// Create new cache. pub fn new( - db: Arc, + db: Arc>, + header_metadata_cache: Arc>, key_lookup_column: u32, header_column: u32, cache_column: u32, @@ -99,6 +103,7 @@ impl DbCache { Self { cache_at: HashMap::new(), db, + header_metadata_cache, key_lookup_column, header_column, cache_column, @@ -113,7 +118,7 @@ impl DbCache { } /// Begin cache transaction. - pub fn transaction<'a>(&'a mut self, tx: &'a mut DBTransaction) -> DbCacheTransaction<'a, Block> { + pub fn transaction<'a>(&'a mut self, tx: &'a mut Transaction) -> DbCacheTransaction<'a, Block> { DbCacheTransaction { cache: self, tx, @@ -125,7 +130,7 @@ impl DbCache { /// Begin cache transaction with given ops. pub fn transaction_with_ops<'a>( &'a mut self, - tx: &'a mut DBTransaction, + tx: &'a mut Transaction, ops: DbCacheTransactionOps, ) -> DbCacheTransaction<'a, Block> { DbCacheTransaction { @@ -169,7 +174,7 @@ impl DbCache { fn get_cache_helper<'a, Block: BlockT>( cache_at: &'a mut HashMap, self::list_storage::DbStorage>>, name: CacheKeyId, - db: &Arc, + db: &Arc>, key_lookup: u32, header: u32, cache: u32, @@ -215,7 +220,7 @@ impl DbCacheTransactionOps { /// Database-backed blockchain data cache transaction valid for single block import. pub struct DbCacheTransaction<'a, Block: BlockT> { cache: &'a mut DbCache, - tx: &'a mut DBTransaction, + tx: &'a mut Transaction, cache_at_ops: HashMap>>, best_finalized_block: Option>, } @@ -328,7 +333,7 @@ impl BlockchainCache for DbCacheSync { let genesis_hash = cache.genesis_hash; let cache_contents = vec![(*key, data)].into_iter().collect(); let db = cache.db.clone(); - let mut dbtx = DBTransaction::new(); + let mut dbtx = Transaction::new(); let tx = cache.transaction(&mut dbtx); let tx = tx.on_block_insert( ComplexBlockId::new(Default::default(), Zero::zero()), @@ -337,8 +342,9 @@ impl BlockchainCache for DbCacheSync { EntryType::Genesis, )?; let tx_ops = tx.into_ops(); - db.write(dbtx).map_err(db_err)?; + db.commit(dbtx)?; cache.commit(tx_ops)?; + Ok(()) } @@ -348,18 +354,24 @@ impl BlockchainCache for DbCacheSync { at: &BlockId, ) -> ClientResult, Block::Hash), Option<(NumberFor, Block::Hash)>, Vec)>> { let mut cache = self.0.write(); + let header_metadata_cache = cache.header_metadata_cache.clone(); let cache = cache.get_cache(*key)?; let storage = cache.storage(); let db = storage.db(); let columns = storage.columns(); let at = match *at { BlockId::Hash(hash) => { - let header = utils::require_header::( - &**db, - columns.key_lookup, - columns.header, - BlockId::Hash(hash.clone()))?; - ComplexBlockId::new(hash, *header.number()) + match header_metadata_cache.header_metadata(hash) { + Some(metadata) => ComplexBlockId::new(hash, metadata.number), + None => { + let header = utils::require_header::( + &**db, + columns.key_lookup, + columns.header, + BlockId::Hash(hash.clone()))?; + ComplexBlockId::new(hash, *header.number()) + } + } }, BlockId::Number(number) => { let hash = utils::require_header::( diff --git a/client/db/src/changes_tries_storage.rs b/client/db/src/changes_tries_storage.rs index a28cd604fe3633d952dfd10a94ea8df01c4bc975..a2299a82337a05f58ec7ba8dc867270813cc4444 100644 --- a/client/db/src/changes_tries_storage.rs +++ b/client/db/src/changes_tries_storage.rs @@ -19,20 +19,22 @@ use std::collections::{HashMap, HashSet}; use std::sync::Arc; use hash_db::Prefix; -use kvdb::{KeyValueDB, DBTransaction}; use codec::{Decode, Encode}; use parking_lot::RwLock; use sp_blockchain::{Error as ClientError, Result as ClientResult}; use sp_trie::MemoryDB; use sc_client_api::backend::PrunableStateChangesTrieStorage; -use sp_blockchain::{well_known_cache_keys, Cache as BlockchainCache}; +use sp_blockchain::{well_known_cache_keys, Cache as BlockchainCache, HeaderMetadataCache}; use sp_core::{ChangesTrieConfiguration, ChangesTrieConfigurationRange, convert_hash}; +use sp_core::storage::PrefixedStorageKey; +use sp_database::Transaction; use sp_runtime::traits::{ Block as BlockT, Header as HeaderT, HashFor, NumberFor, One, Zero, CheckedSub, }; use sp_runtime::generic::{BlockId, DigestItem, ChangesTrieSignal}; -use sp_state_machine::{DBValue, ChangesTrieBuildCache, ChangesTrieCacheAction}; -use crate::utils::{self, Meta, meta_keys, db_err}; +use sp_state_machine::{ChangesTrieBuildCache, ChangesTrieCacheAction}; +use crate::{Database, DbHash}; +use crate::utils::{self, Meta, meta_keys}; use crate::cache::{ DbCacheSync, DbCache, DbCacheTransactionOps, ComplexBlockId, EntryType as CacheEntryType, @@ -76,7 +78,7 @@ impl From> for DbChangesTrieStorageT /// Stores all tries in separate DB column. /// Lock order: meta, tries_meta, cache, build_cache. pub struct DbChangesTrieStorage { - db: Arc, + db: Arc>, meta_column: u32, changes_tries_column: u32, key_lookup_column: u32, @@ -111,7 +113,8 @@ struct ChangesTriesMeta { impl DbChangesTrieStorage { /// Create new changes trie storage. pub fn new( - db: Arc, + db: Arc>, + header_metadata_cache: Arc>, meta_column: u32, changes_tries_column: u32, key_lookup_column: u32, @@ -135,6 +138,7 @@ impl DbChangesTrieStorage { min_blocks_to_keep, cache: DbCacheSync(RwLock::new(DbCache::new( db.clone(), + header_metadata_cache, key_lookup_column, header_column, cache_column, @@ -149,7 +153,7 @@ impl DbChangesTrieStorage { /// Commit new changes trie. pub fn commit( &self, - tx: &mut DBTransaction, + tx: &mut Transaction, mut changes_trie: MemoryDB>, parent_block: ComplexBlockId, block: ComplexBlockId, @@ -160,7 +164,7 @@ impl DbChangesTrieStorage { ) -> ClientResult> { // insert changes trie, associated with block, into DB for (key, (val, _)) in changes_trie.drain() { - tx.put(self.changes_tries_column, key.as_ref(), &val); + tx.set(self.changes_tries_column, key.as_ref(), &val); } // if configuration has not been changed AND block is not finalized => nothing to do here @@ -205,7 +209,7 @@ impl DbChangesTrieStorage { /// Called when block is finalized. pub fn finalize( &self, - tx: &mut DBTransaction, + tx: &mut Transaction, parent_block_hash: Block::Hash, block_hash: Block::Hash, block_num: NumberFor, @@ -254,7 +258,7 @@ impl DbChangesTrieStorage { /// When block is reverted. pub fn revert( &self, - tx: &mut DBTransaction, + tx: &mut Transaction, block: &ComplexBlockId, ) -> ClientResult> { Ok(self.cache.0.write().transaction(tx) @@ -280,7 +284,7 @@ impl DbChangesTrieStorage { /// Prune obsolete changes tries. fn prune( &self, - tx: &mut DBTransaction, + tx: &mut Transaction, block_hash: Block::Hash, block_num: NumberFor, new_header: Option<&Block::Header>, @@ -313,7 +317,7 @@ impl DbChangesTrieStorage { hash: convert_hash(&block_hash), number: block_num, }, - |node| tx.delete(self.changes_tries_column, node.as_ref()), + |node| tx.remove(self.changes_tries_column, node.as_ref()), ); next_digest_range_start = end + One::one(); @@ -481,23 +485,22 @@ where fn with_cached_changed_keys( &self, root: &Block::Hash, - functor: &mut dyn FnMut(&HashMap>, HashSet>>), + functor: &mut dyn FnMut(&HashMap, HashSet>>), ) -> bool { self.build_cache.read().with_changed_keys(root, functor) } - fn get(&self, key: &Block::Hash, _prefix: Prefix) -> Result, String> { - self.db.get(self.changes_tries_column, key.as_ref()) - .map_err(|err| format!("{}", err)) + fn get(&self, key: &Block::Hash, _prefix: Prefix) -> Result>, String> { + Ok(self.db.get(self.changes_tries_column, key.as_ref())) } } /// Read changes tries metadata from database. fn read_tries_meta( - db: &dyn KeyValueDB, + db: &dyn Database, meta_column: u32, ) -> ClientResult> { - match db.get(meta_column, meta_keys::CHANGES_TRIES_META).map_err(db_err)? { + match db.get(meta_column, meta_keys::CHANGES_TRIES_META) { Some(h) => match Decode::decode(&mut &h[..]) { Ok(h) => Ok(h), Err(err) => Err(ClientError::Backend(format!("Error decoding changes tries metadata: {}", err))), @@ -511,11 +514,11 @@ fn read_tries_meta( /// Write changes tries metadata from database. fn write_tries_meta( - tx: &mut DBTransaction, + tx: &mut Transaction, meta_column: u32, meta: &ChangesTriesMeta, ) { - tx.put(meta_column, meta_keys::CHANGES_TRIES_META, &meta.encode()); + tx.set_from_vec(meta_column, meta_keys::CHANGES_TRIES_META, meta.encode()); } #[cfg(test)] @@ -707,7 +710,7 @@ mod tests { let finalize_block = |number| { let header = backend.blockchain().header(BlockId::Number(number)).unwrap().unwrap(); - let mut tx = DBTransaction::new(); + let mut tx = Transaction::new(); let cache_ops = backend.changes_tries_storage.finalize( &mut tx, *header.parent_hash(), @@ -716,7 +719,7 @@ mod tests { None, None, ).unwrap(); - backend.storage.db.write(tx).unwrap(); + backend.storage.db.commit(tx).unwrap(); backend.changes_tries_storage.post_commit(Some(cache_ops)); }; diff --git a/client/db/src/children.rs b/client/db/src/children.rs index 2ef67de6a83e1116d20483982ff284ecbd5adf08..bfba797cd467bdbc3f7a1db5d23b7f97511b5be5 100644 --- a/client/db/src/children.rs +++ b/client/db/src/children.rs @@ -16,23 +16,21 @@ //! Functionality for reading and storing children hashes from db. -use kvdb::{KeyValueDB, DBTransaction}; use codec::{Encode, Decode}; use sp_blockchain; use std::hash::Hash; +use sp_database::{Database, Transaction}; +use crate::DbHash; /// Returns the hashes of the children blocks of the block with `parent_hash`. pub fn read_children< K: Eq + Hash + Clone + Encode + Decode, V: Eq + Hash + Clone + Encode + Decode, ->(db: &dyn KeyValueDB, column: u32, prefix: &[u8], parent_hash: K) -> sp_blockchain::Result> { +>(db: &dyn Database, column: u32, prefix: &[u8], parent_hash: K) -> sp_blockchain::Result> { let mut buf = prefix.to_vec(); parent_hash.using_encoded(|s| buf.extend(s)); - let raw_val_opt = match db.get(column, &buf[..]) { - Ok(raw_val_opt) => raw_val_opt, - Err(_) => return Err(sp_blockchain::Error::Backend("Error reading value from database".into())), - }; + let raw_val_opt = db.get(column, &buf[..]); let raw_val = match raw_val_opt { Some(val) => val, @@ -53,7 +51,7 @@ pub fn write_children< K: Eq + Hash + Clone + Encode + Decode, V: Eq + Hash + Clone + Encode + Decode, >( - tx: &mut DBTransaction, + tx: &mut Transaction, column: u32, prefix: &[u8], parent_hash: K, @@ -61,34 +59,35 @@ pub fn write_children< ) { let mut key = prefix.to_vec(); parent_hash.using_encoded(|s| key.extend(s)); - tx.put_vec(column, &key[..], children_hashes.encode()); + tx.set_from_vec(column, &key[..], children_hashes.encode()); } /// Prepare transaction to remove the children of `parent_hash`. pub fn remove_children< K: Eq + Hash + Clone + Encode + Decode, >( - tx: &mut DBTransaction, + tx: &mut Transaction, column: u32, prefix: &[u8], parent_hash: K, ) { let mut key = prefix.to_vec(); parent_hash.using_encoded(|s| key.extend(s)); - tx.delete(column, &key[..]); + tx.remove(column, &key); } #[cfg(test)] mod tests { use super::*; + use std::sync::Arc; #[test] fn children_write_read_remove() { const PREFIX: &[u8] = b"children"; - let db = ::kvdb_memorydb::create(1); + let db = Arc::new(sp_database::MemDb::default()); - let mut tx = DBTransaction::new(); + let mut tx = Transaction::new(); let mut children1 = Vec::new(); children1.push(1_3); @@ -100,19 +99,19 @@ mod tests { children2.push(1_6); write_children(&mut tx, 0, PREFIX, 1_2, children2); - db.write(tx.clone()).expect("(2) Committing transaction failed"); + db.commit(tx.clone()).unwrap(); - let r1: Vec = read_children(&db, 0, PREFIX, 1_1).expect("(1) Getting r1 failed"); - let r2: Vec = read_children(&db, 0, PREFIX, 1_2).expect("(1) Getting r2 failed"); + let r1: Vec = read_children(&*db, 0, PREFIX, 1_1).expect("(1) Getting r1 failed"); + let r2: Vec = read_children(&*db, 0, PREFIX, 1_2).expect("(1) Getting r2 failed"); assert_eq!(r1, vec![1_3, 1_5]); assert_eq!(r2, vec![1_4, 1_6]); remove_children(&mut tx, 0, PREFIX, 1_2); - db.write(tx).expect("(2) Committing transaction failed"); + db.commit(tx).unwrap(); - let r1: Vec = read_children(&db, 0, PREFIX, 1_1).expect("(2) Getting r1 failed"); - let r2: Vec = read_children(&db, 0, PREFIX, 1_2).expect("(2) Getting r2 failed"); + let r1: Vec = read_children(&*db, 0, PREFIX, 1_1).expect("(2) Getting r1 failed"); + let r2: Vec = read_children(&*db, 0, PREFIX, 1_2).expect("(2) Getting r2 failed"); assert_eq!(r1, vec![1_3, 1_5]); assert_eq!(r2.len(), 0); diff --git a/client/db/src/lib.rs b/client/db/src/lib.rs index f1cb5f9a793c015e61b473b78465bcb4156be05f..7cfde1e1d9d0d49e1f8b8b408ee93f4b6626c1c3 100644 --- a/client/db/src/lib.rs +++ b/client/db/src/lib.rs @@ -1,20 +1,22 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . -//! Client backend that uses RocksDB database as storage. +//! Client backend that is backed by a database. //! //! # Canonicality vs. Finality //! @@ -29,27 +31,32 @@ pub mod light; pub mod offchain; -#[cfg(any(feature = "kvdb-rocksdb", test))] +#[cfg(any(feature = "with-kvdb-rocksdb", test))] pub mod bench; mod children; mod cache; mod changes_tries_storage; mod storage_cache; -#[cfg(any(feature = "kvdb-rocksdb", test))] +#[cfg(any(feature = "with-kvdb-rocksdb", test))] mod upgrade; mod utils; mod stats; +#[cfg(feature = "with-parity-db")] +mod parity_db; +#[cfg(feature = "with-subdb")] +mod subdb; use std::sync::Arc; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::io; use std::collections::HashMap; + use sc_client_api::{ - ForkBlocks, UsageInfo, MemoryInfo, BadBlocks, IoInfo, MemorySize, CloneableSpawn, - execution_extensions::ExecutionExtensions, + UsageInfo, MemoryInfo, IoInfo, MemorySize, backend::{NewBlockState, PrunableStateChangesTrieStorage}, + leaves::{LeafSet, FinalizationDisplaced}, }; use sp_blockchain::{ Result as ClientResult, Error as ClientError, @@ -57,42 +64,36 @@ use sp_blockchain::{ }; use codec::{Decode, Encode}; use hash_db::Prefix; -use kvdb::{KeyValueDB, DBTransaction}; use sp_trie::{MemoryDB, PrefixedMemoryDB, prefixed_key}; +use sp_database::Transaction; use parking_lot::RwLock; -use sp_core::{ChangesTrieConfiguration, traits::CodeExecutor}; +use sp_core::ChangesTrieConfiguration; +use sp_core::offchain::storage::{OffchainOverlayedChange, OffchainOverlayedChanges}; use sp_core::storage::{well_known_keys, ChildInfo}; -use sp_runtime::{ - generic::BlockId, Justification, Storage, - BuildStorage, -}; +use sp_runtime::{generic::BlockId, Justification, Storage}; use sp_runtime::traits::{ Block as BlockT, Header as HeaderT, NumberFor, Zero, One, SaturatedConversion, HashFor, }; -use sc_executor::RuntimeInfo; use sp_state_machine::{ DBValue, ChangesTrieTransaction, ChangesTrieCacheAction, UsageInfo as StateUsageInfo, StorageCollection, ChildStorageCollection, backend::Backend as StateBackend, StateMachineStats, }; -use crate::utils::{DatabaseType, Meta, db_err, meta_keys, read_db, read_meta}; +use crate::utils::{DatabaseType, Meta, meta_keys, read_db, read_meta}; use crate::changes_tries_storage::{DbChangesTrieStorage, DbChangesTrieStorageTransaction}; -use sc_client::leaves::{LeafSet, FinalizationDisplaced}; use sc_state_db::StateDb; use sp_blockchain::{CachedHeaderMetadata, HeaderMetadata, HeaderMetadataCache}; use crate::storage_cache::{CachingState, SyncingCachingState, SharedCache, new_shared_cache}; use crate::stats::StateUsageStats; use log::{trace, debug, warn}; + +// Re-export the Database trait so that one can pass an implementation of it. +pub use sp_database::Database; pub use sc_state_db::PruningMode; -use prometheus_endpoint::Registry; -#[cfg(any(feature = "kvdb-rocksdb", test))] +#[cfg(any(feature = "with-kvdb-rocksdb", test))] pub use bench::BenchmarkingState; -#[cfg(feature = "test-helpers")] -use sc_client::in_mem::Backend as InMemoryBackend; - -const CANONICALIZATION_DELAY: u64 = 4096; const MIN_BLOCKS_TO_KEEP_CHANGES_TRIES_FOR: u32 = 32768; /// Default value for storage cache child ratio. @@ -103,8 +104,9 @@ pub type DbState = sp_state_machine::TrieBackend< Arc>>, HashFor >; -/// Re-export the KVDB trait so that one can pass an implementation of it. -pub use kvdb; +const DB_HASH_LEN: usize = 32; +/// Hash type that this backend uses for the database. +pub type DbHash = [u8; DB_HASH_LEN]; /// A reference tracking state. /// @@ -155,11 +157,10 @@ impl StateBackend> for RefTrackingState { fn child_storage( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) -> Result>, Self::Error> { - self.state.child_storage(storage_key, child_info, key) + self.state.child_storage(child_info, key) } fn exists_storage(&self, key: &[u8]) -> Result { @@ -168,11 +169,10 @@ impl StateBackend> for RefTrackingState { fn exists_child_storage( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) -> Result { - self.state.exists_child_storage(storage_key, child_info, key) + self.state.exists_child_storage(child_info, key) } fn next_storage_key(&self, key: &[u8]) -> Result>, Self::Error> { @@ -181,11 +181,10 @@ impl StateBackend> for RefTrackingState { fn next_child_storage_key( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) -> Result>, Self::Error> { - self.state.next_child_storage_key(storage_key, child_info, key) + self.state.next_child_storage_key(child_info, key) } fn for_keys_with_prefix(&self, prefix: &[u8], f: F) { @@ -198,40 +197,34 @@ impl StateBackend> for RefTrackingState { fn for_keys_in_child_storage( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, f: F, ) { - self.state.for_keys_in_child_storage(storage_key, child_info, f) + self.state.for_keys_in_child_storage(child_info, f) } fn for_child_keys_with_prefix( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, prefix: &[u8], f: F, ) { - self.state.for_child_keys_with_prefix(storage_key, child_info, prefix, f) + self.state.for_child_keys_with_prefix(child_info, prefix, f) } - fn storage_root(&self, delta: I) -> (B::Hash, Self::Transaction) - where - I: IntoIterator, Option>)> - { + fn storage_root<'a>( + &self, + delta: impl Iterator)>, + ) -> (B::Hash, Self::Transaction) where B::Hash: Ord { self.state.storage_root(delta) } - fn child_storage_root( + fn child_storage_root<'a>( &self, - storage_key: &[u8], - child_info: ChildInfo, - delta: I, - ) -> (B::Hash, bool, Self::Transaction) - where - I: IntoIterator, Option>)>, - { - self.state.child_storage_root(storage_key, child_info, delta) + child_info: &ChildInfo, + delta: impl Iterator)>, + ) -> (B::Hash, bool, Self::Transaction) where B::Hash: Ord { + self.state.child_storage_root(child_info, delta) } fn pairs(&self) -> Vec<(Vec, Vec)> { @@ -244,11 +237,10 @@ impl StateBackend> for RefTrackingState { fn child_keys( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, prefix: &[u8], ) -> Vec> { - self.state.child_keys(storage_key, child_info, prefix) + self.state.child_keys(child_info, prefix) } fn as_trie_backend(&mut self) @@ -279,58 +271,61 @@ pub struct DatabaseSettings { } /// Where to find the database.. +#[derive(Debug, Clone)] pub enum DatabaseSettingsSrc { - /// Load a database from a given path. Recommended for most uses. - Path { + /// Load a RocksDB database from a given path. Recommended for most uses. + RocksDb { + /// Path to the database. + path: PathBuf, + /// Cache size in MiB. + cache_size: usize, + }, + + /// Load a ParityDb database from a given path. + ParityDb { + /// Path to the database. + path: PathBuf, + }, + + /// Load a Subdb database from a given path. + SubDb { /// 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), + Custom(Arc>), } -/// Create an instance of db-backed client. -pub fn new_client( - settings: DatabaseSettings, - executor: E, - genesis_storage: &dyn BuildStorage, - fork_blocks: ForkBlocks, - bad_blocks: BadBlocks, - execution_extensions: ExecutionExtensions, - spawn_handle: Box, - prometheus_registry: Option, -) -> Result<( - sc_client::Client< - Backend, - sc_client::LocalCallExecutor, E>, - Block, - RA, - >, - Arc>, - ), - sp_blockchain::Error, -> - where - Block: BlockT, - E: CodeExecutor + RuntimeInfo, -{ - let backend = Arc::new(Backend::new(settings, CANONICALIZATION_DELAY)?); - let executor = sc_client::LocalCallExecutor::new(backend.clone(), executor, spawn_handle); - Ok(( - sc_client::Client::new( - backend.clone(), - executor, - genesis_storage, - fork_blocks, - bad_blocks, - execution_extensions, - prometheus_registry, - )?, - backend, - )) +impl DatabaseSettingsSrc { + /// Return dabase path for databases that are on the disk. + pub fn path(&self) -> Option<&Path> { + match self { + DatabaseSettingsSrc::RocksDb { path, .. } => Some(path.as_path()), + DatabaseSettingsSrc::ParityDb { path, .. } => Some(path.as_path()), + DatabaseSettingsSrc::SubDb { path, .. } => Some(path.as_path()), + DatabaseSettingsSrc::Custom(_) => None, + } + } + /// Check if database supports internal ref counting for state data. + pub fn supports_ref_counting(&self) -> bool { + match self { + DatabaseSettingsSrc::ParityDb { .. } => true, + _ => false, + } + } +} + +impl std::fmt::Display for DatabaseSettingsSrc { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let name = match self { + DatabaseSettingsSrc::RocksDb { .. } => "RocksDb", + DatabaseSettingsSrc::ParityDb { .. } => "ParityDb", + DatabaseSettingsSrc::SubDb { .. } => "SubDb", + DatabaseSettingsSrc::Custom(_) => "Custom", + }; + write!(f, "{}", name) + } } pub(crate) mod columns { @@ -357,33 +352,33 @@ struct PendingBlock { } // wrapper that implements trait required for state_db -struct StateMetaDb<'a>(&'a dyn KeyValueDB); +struct StateMetaDb<'a>(&'a dyn Database); impl<'a> sc_state_db::MetaDb for StateMetaDb<'a> { type Error = io::Error; fn get_meta(&self, key: &[u8]) -> Result>, Self::Error> { - self.0.get(columns::STATE_META, key).map(|r| r.map(|v| v.to_vec())) + Ok(self.0.get(columns::STATE_META, key)) } } /// Block database pub struct BlockchainDb { - db: Arc, + db: Arc>, meta: Arc, Block::Hash>>>, leaves: RwLock>>, - header_metadata_cache: HeaderMetadataCache, + header_metadata_cache: Arc>, } impl BlockchainDb { - fn new(db: Arc) -> ClientResult { + fn new(db: Arc>) -> ClientResult { let meta = read_meta::(&*db, 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(), + header_metadata_cache: Arc::new(HeaderMetadataCache::default()), }) } @@ -412,14 +407,14 @@ impl BlockchainDb { } } -impl sc_client::blockchain::HeaderBackend for BlockchainDb { +impl sc_client_api::blockchain::HeaderBackend for BlockchainDb { fn header(&self, id: BlockId) -> ClientResult> { utils::read_header(&*self.db, columns::KEY_LOOKUP, columns::HEADER, id) } - fn info(&self) -> sc_client::blockchain::Info { + fn info(&self) -> sc_client_api::blockchain::Info { let meta = self.meta.read(); - sc_client::blockchain::Info { + sc_client_api::blockchain::Info { best_hash: meta.best_hash, best_number: meta.best_number, genesis_hash: meta.genesis_hash, @@ -429,7 +424,7 @@ impl sc_client::blockchain::HeaderBackend for BlockchainDb } } - fn status(&self, id: BlockId) -> ClientResult { + fn status(&self, id: BlockId) -> ClientResult { let exists = match id { BlockId::Hash(_) => read_db( &*self.db, @@ -440,8 +435,8 @@ impl sc_client::blockchain::HeaderBackend for BlockchainDb BlockId::Number(n) => n <= self.meta.read().best_number, }; match exists { - true => Ok(sc_client::blockchain::BlockStatus::InChain), - false => Ok(sc_client::blockchain::BlockStatus::Unknown), + true => Ok(sc_client_api::blockchain::BlockStatus::InChain), + false => Ok(sc_client_api::blockchain::BlockStatus::Unknown), } } @@ -457,7 +452,7 @@ impl sc_client::blockchain::HeaderBackend for BlockchainDb } } -impl sc_client::blockchain::Backend for BlockchainDb { +impl sc_client_api::blockchain::Backend for BlockchainDb { fn body(&self, id: BlockId) -> ClientResult>> { match read_db(&*self.db, columns::KEY_LOOKUP, columns::BODY, id)? { Some(body) => match Decode::decode(&mut &body[..]) { @@ -486,7 +481,7 @@ impl sc_client::blockchain::Backend for BlockchainDb Option>> { + fn cache(&self) -> Option>> { None } @@ -499,8 +494,8 @@ impl sc_client::blockchain::Backend for BlockchainDb sc_client::blockchain::ProvideCache for BlockchainDb { - fn cache(&self) -> Option>> { +impl sc_client_api::blockchain::ProvideCache for BlockchainDb { + fn cache(&self) -> Option>> { None } } @@ -509,7 +504,7 @@ impl HeaderMetadata for BlockchainDb { type Error = sp_blockchain::Error; fn header_metadata(&self, hash: Block::Hash) -> Result, Self::Error> { - self.header_metadata_cache.header_metadata(hash).or_else(|_| { + self.header_metadata_cache.header_metadata(hash).map_or_else(|| { self.header(BlockId::hash(hash))?.map(|header| { let header_metadata = CachedHeaderMetadata::from(&header); self.header_metadata_cache.insert_header_metadata( @@ -518,7 +513,7 @@ impl HeaderMetadata for BlockchainDb { ); header_metadata }).ok_or(ClientError::UnknownBlock(format!("header not found in db: {}", hash))) - }) + }, Ok) } fn insert_header_metadata(&self, hash: Block::Hash, metadata: CachedHeaderMetadata) { @@ -536,6 +531,7 @@ pub struct BlockImportOperation { db_updates: PrefixedMemoryDB>, storage_updates: StorageCollection, child_storage_updates: ChildStorageCollection, + offchain_storage_updates: OffchainOverlayedChanges, changes_trie_updates: MemoryDB>, changes_trie_build_cache_update: Option>>, changes_trie_config_update: Option>, @@ -547,11 +543,25 @@ pub struct BlockImportOperation { } impl BlockImportOperation { - fn apply_aux(&mut self, transaction: &mut DBTransaction) { + fn apply_offchain(&mut self, transaction: &mut Transaction) { + for ((prefix, key), value_operation) in self.offchain_storage_updates.drain() { + let key: Vec = prefix + .into_iter() + .chain(sp_core::sp_std::iter::once(b'/')) + .chain(key.into_iter()) + .collect(); + match value_operation { + OffchainOverlayedChange::SetValue(val) => transaction.set_from_vec(columns::OFFCHAIN, &key, val), + OffchainOverlayedChange::Remove => transaction.remove(columns::OFFCHAIN, &key), + } + } + } + + fn apply_aux(&mut self, transaction: &mut Transaction) { for (key, maybe_val) in self.aux_ops.drain(..) { match maybe_val { - Some(val) => transaction.put_vec(columns::AUX, &key, val), - None => transaction.delete(columns::AUX, &key), + Some(val) => transaction.set_from_vec(columns::AUX, &key, val), + None => transaction.remove(columns::AUX, &key), } } } @@ -597,32 +607,25 @@ impl sc_client_api::backend::BlockImportOperation for Bloc &mut self, storage: Storage, ) -> ClientResult { - - if storage.top.iter().any(|(k, _)| well_known_keys::is_child_storage_key(k)) { + if storage.top.keys().any(|k| well_known_keys::is_child_storage_key(&k)) { return Err(sp_blockchain::Error::GenesisInvalid.into()); } - for child_key in storage.children.keys() { - if !well_known_keys::is_child_storage_key(&child_key) { - return Err(sp_blockchain::Error::GenesisInvalid.into()); - } - } - - let child_delta = storage.children.into_iter().map(|(storage_key, child_content)| ( - storage_key, - child_content.data.into_iter().map(|(k, v)| (k, Some(v))), child_content.child_info), - ); + let child_delta = storage.children_default.iter().map(|(_storage_key, child_content)|( + &child_content.child_info, + child_content.data.iter().map(|(k, v)| (&k[..], Some(&v[..]))), + )); let mut changes_trie_config: Option = None; let (root, transaction) = self.old_state.full_storage_root( - storage.top.into_iter().map(|(k, v)| { - if k == well_known_keys::CHANGES_TRIE_CONFIG { + storage.top.iter().map(|(k, v)| { + if &k[..] == well_known_keys::CHANGES_TRIE_CONFIG { changes_trie_config = Some( Decode::decode(&mut &v[..]) .expect("changes trie configuration is encoded properly at genesis") ); } - (k, Some(v)) + (&k[..], Some(&v[..])) }), child_delta ); @@ -659,6 +662,14 @@ impl sc_client_api::backend::BlockImportOperation for Bloc Ok(()) } + fn update_offchain_storage( + &mut self, + offchain_update: OffchainOverlayedChanges, + ) -> ClientResult<()> { + self.offchain_storage_updates = offchain_update; + Ok(()) + } + fn mark_finalized( &mut self, block: BlockId, @@ -676,15 +687,20 @@ impl sc_client_api::backend::BlockImportOperation for Bloc } struct StorageDb { - pub db: Arc, + pub db: Arc>, pub state_db: StateDb>, + prefix_keys: bool, } impl sp_state_machine::Storage> for StorageDb { fn get(&self, key: &Block::Hash, prefix: Prefix) -> Result, String> { - let key = prefixed_key::>(key, prefix); - self.state_db.get(&key, self) - .map_err(|e| format!("Database backend error: {:?}", e)) + if self.prefix_keys { + let key = prefixed_key::>(key, prefix); + self.state_db.get(&key, self) + } else { + self.state_db.get(key.as_ref(), self) + } + .map_err(|e| format!("Database backend error: {:?}", e)) } } @@ -693,7 +709,7 @@ impl sc_state_db::NodeDb for StorageDb { type Key = [u8]; fn get(&self, key: &[u8]) -> Result>, Self::Error> { - self.db.get(columns::STATE, key).map(|r| r.map(|v| v.to_vec())) + Ok(self.db.get(columns::STATE, key)) } } @@ -776,13 +792,14 @@ impl Backend { /// The pruning window is how old a block must be before the state is pruned. pub fn new(config: DatabaseSettings, canonicalization_delay: u64) -> ClientResult { let db = crate::utils::open_database::(&config, DatabaseType::Full)?; - Self::from_kvdb(db as Arc<_>, canonicalization_delay, &config) + Self::from_database(db as Arc<_>, canonicalization_delay, &config) } /// Create new memory-backed client backend for tests. #[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)); + let db = kvdb_memorydb::create(crate::utils::NUM_COLUMNS); + let db = sp_database::as_database(db); let db_setting = DatabaseSettings { state_cache_size: 16777216, state_cache_child_ratio: Some((50, 100)), @@ -793,8 +810,8 @@ impl Backend { Self::new(db_setting, canonicalization_delay).expect("failed to create test-db") } - fn from_kvdb( - db: Arc, + fn from_database( + db: Arc>, canonicalization_delay: u64, config: &DatabaseSettings, ) -> ClientResult { @@ -804,15 +821,20 @@ impl Backend { let map_e = |e: sc_state_db::Error| sp_blockchain::Error::from( format!("State database error: {:?}", e) ); - let state_db: StateDb<_, _> = StateDb::new(config.pruning.clone(), &StateMetaDb(&*db)) - .map_err(map_e)?; + let state_db: StateDb<_, _> = StateDb::new( + config.pruning.clone(), + !config.source.supports_ref_counting(), + &StateMetaDb(&*db), + ).map_err(map_e)?; let storage_db = StorageDb { db: db.clone(), state_db, + prefix_keys: !config.source.supports_ref_counting(), }; let offchain_storage = offchain::LocalStorage::new(db.clone()); let changes_tries_storage = DbChangesTrieStorage::new( db, + blockchain.header_metadata_cache.clone(), columns::META, columns::CHANGES_TRIE, columns::KEY_LOOKUP, @@ -843,61 +865,6 @@ impl Backend { }) } - /// Returns in-memory blockchain that contains the same set of blocks as self. - #[cfg(feature = "test-helpers")] - pub fn as_in_memory(&self) -> InMemoryBackend { - use sc_client_api::backend::{Backend as ClientBackend, BlockImportOperation}; - use sc_client::blockchain::Backend as BlockchainBackend; - - let inmem = InMemoryBackend::::new(); - - // get all headers hashes && sort them by number (could be duplicate) - let mut headers: Vec<(NumberFor, Block::Hash, Block::Header)> = Vec::new(); - for (_, header) in self.blockchain.db.iter(columns::HEADER) { - let header = Block::Header::decode(&mut &header[..]).unwrap(); - let hash = header.hash(); - let number = *header.number(); - let pos = headers.binary_search_by(|item| item.0.cmp(&number)); - match pos { - Ok(pos) => headers.insert(pos, (number, hash, header)), - Err(pos) => headers.insert(pos, (number, hash, header)), - } - } - - // insert all other headers + bodies + justifications - let info = self.blockchain.info(); - for (number, hash, header) in headers { - let id = BlockId::Hash(hash); - let justification = self.blockchain.justification(id).unwrap(); - let body = self.blockchain.body(id).unwrap(); - let state = self.state_at(id).unwrap().pairs(); - - let new_block_state = if number.is_zero() { - NewBlockState::Final - } else if hash == info.best_hash { - NewBlockState::Best - } else { - NewBlockState::Normal - }; - let mut op = inmem.begin_operation().unwrap(); - op.set_block_data(header, body, justification, new_block_state).unwrap(); - op.update_db_storage(vec![(None, state.into_iter().map(|(k, v)| (k, Some(v))).collect())]) - .unwrap(); - inmem.commit_operation(op).unwrap(); - } - - // and now finalize the best block we have - inmem.finalize_block(BlockId::Hash(info.finalized_hash), None).unwrap(); - - inmem - } - - /// Returns total number of blocks (headers) in the block DB. - #[cfg(feature = "test-helpers")] - pub fn blocks_count(&self) -> u64 { - self.blockchain.db.iter(columns::HEADER).count() as u64 - } - /// Handle setting head within a transaction. `route_to` should be the last /// block that existed in the database. `best_to` should be the best block /// to be set. @@ -907,7 +874,7 @@ impl Backend { /// to be best, `route_to` should equal to `best_to`. fn set_head_with_transaction( &self, - transaction: &mut DBTransaction, + transaction: &mut Transaction, route_to: Block::Hash, best_to: (NumberFor, Block::Hash), ) -> ClientResult<(Vec, Vec)> { @@ -957,7 +924,7 @@ impl Backend { } let lookup_key = utils::number_and_hash_to_lookup_key(best_to.0, &best_to.1)?; - transaction.put(columns::META, meta_keys::BEST_BLOCK, &lookup_key); + transaction.set_from_vec(columns::META, meta_keys::BEST_BLOCK, lookup_key); utils::insert_number_to_key_mapping( transaction, columns::KEY_LOOKUP, @@ -984,7 +951,7 @@ impl Backend { fn finalize_block_with_transaction( &self, - transaction: &mut DBTransaction, + transaction: &mut Transaction, hash: &Block::Hash, header: &Block::Header, last_finalized: Option, @@ -1005,10 +972,10 @@ impl Backend { )?; if let Some(justification) = justification { - transaction.put( + transaction.set_from_vec( columns::JUSTIFICATION, &utils::number_and_hash_to_lookup_key(number, hash)?, - &justification.encode(), + justification.encode(), ); } Ok((*hash, number, false, true)) @@ -1017,7 +984,7 @@ impl Backend { // performs forced canonicalization with a delay after importing a non-finalized block. fn force_delayed_canonicalize( &self, - transaction: &mut DBTransaction, + transaction: &mut Transaction, hash: Block::Hash, number: NumberFor, ) @@ -1034,7 +1001,7 @@ impl Backend { let hash = if new_canonical == number_u64 { hash } else { - ::sc_client::blockchain::HeaderBackend::hash(&self.blockchain, new_canonical.saturated_into())? + ::sc_client_api::blockchain::HeaderBackend::hash(&self.blockchain, new_canonical.saturated_into())? .expect("existence of block with number `new_canonical` \ implies existence of blocks with all numbers before it; qed") }; @@ -1051,10 +1018,11 @@ impl Backend { fn try_commit_operation(&self, mut operation: BlockImportOperation) -> ClientResult<()> { - let mut transaction = DBTransaction::new(); + let mut transaction = Transaction::new(); let mut finalization_displaced_leaves = None; operation.apply_aux(&mut transaction); + operation.apply_offchain(&mut transaction); let mut meta_updates = Vec::with_capacity(operation.finalized_blocks.len()); let mut last_finalized_hash = self.blockchain.meta.read().finalized_hash; @@ -1103,17 +1071,17 @@ impl Backend { header_metadata, ); - transaction.put(columns::HEADER, &lookup_key, &pending_block.header.encode()); + transaction.set_from_vec(columns::HEADER, &lookup_key, pending_block.header.encode()); if let Some(body) = &pending_block.body { - transaction.put(columns::BODY, &lookup_key, &body.encode()); + transaction.set_from_vec(columns::BODY, &lookup_key, body.encode()); } if let Some(justification) = pending_block.justification { - transaction.put(columns::JUSTIFICATION, &lookup_key, &justification.encode()); + transaction.set_from_vec(columns::JUSTIFICATION, &lookup_key, justification.encode()); } if number.is_zero() { - transaction.put(columns::META, meta_keys::FINALIZED_BLOCK, &lookup_key); - transaction.put(columns::META, meta_keys::GENESIS_HASH, hash.as_ref()); + transaction.set_from_vec(columns::META, meta_keys::FINALIZED_BLOCK, lookup_key); + transaction.set(columns::META, meta_keys::GENESIS_HASH, hash.as_ref()); // for tests, because config is set from within the reset_storage if operation.changes_trie_config_update.is_none() { @@ -1127,17 +1095,32 @@ impl Backend { let mut bytes: u64 = 0; let mut removal: u64 = 0; let mut bytes_removal: u64 = 0; - for (key, (val, rc)) in operation.db_updates.drain() { + for (mut key, (val, rc)) in operation.db_updates.drain() { + if !self.storage.prefix_keys { + // Strip prefix + key.drain(0 .. key.len() - DB_HASH_LEN); + }; if rc > 0 { ops += 1; bytes += key.len() as u64 + val.len() as u64; - - changeset.inserted.push((key, val.to_vec())); + if rc == 1 { + changeset.inserted.push((key, val.to_vec())); + } else { + changeset.inserted.push((key.clone(), val.to_vec())); + for _ in 0 .. rc - 1 { + changeset.inserted.push((key.clone(), Default::default())); + } + } } else if rc < 0 { removal += 1; bytes_removal += key.len() as u64; - - changeset.deleted.push(key); + if rc == -1 { + changeset.deleted.push(key); + } else { + for _ in 0 .. -rc { + changeset.deleted.push(key.clone()); + } + } } } self.state_usage.tally_writes_nodes(ops, bytes); @@ -1242,7 +1225,7 @@ impl Backend { }; let cache_update = if let Some(set_head) = operation.set_head { - if let Some(header) = sc_client::blockchain::HeaderBackend::header(&self.blockchain, set_head)? { + if let Some(header) = sc_client_api::blockchain::HeaderBackend::header(&self.blockchain, set_head)? { let number = header.number(); let hash = header.hash(); @@ -1260,31 +1243,17 @@ impl Backend { None }; - let write_result = self.storage.db.write(transaction).map_err(db_err); + self.storage.db.commit(transaction)?; if let Some(( number, hash, enacted, retracted, - displaced_leaf, + _displaced_leaf, is_best, mut cache, )) = imported { - if let Err(e) = write_result { - let mut leaves = self.blockchain.leaves.write(); - let mut undo = leaves.undo(); - if let Some(displaced_leaf) = displaced_leaf { - undo.undo_import(displaced_leaf); - } - - if let Some(finalization_displaced) = finalization_displaced_leaves { - undo.undo_finalization(finalization_displaced); - } - - return Err(e) - } - cache.sync_cache( &enacted, &retracted, @@ -1317,7 +1286,7 @@ impl Backend { // was not a child of the last finalized block. fn note_finalized( &self, - transaction: &mut DBTransaction, + transaction: &mut Transaction, is_inserted: bool, f_header: &Block::Header, f_hash: Block::Hash, @@ -1328,7 +1297,7 @@ impl Backend { if self.storage.state_db.best_canonical().map(|c| f_num.saturated_into::() > c).unwrap_or(true) { let lookup_key = utils::number_and_hash_to_lookup_key(f_num, f_hash.clone())?; - transaction.put(columns::META, meta_keys::FINALIZED_BLOCK, &lookup_key); + transaction.set_from_vec(columns::META, meta_keys::FINALIZED_BLOCK, lookup_key); let commit = self.storage.state_db.canonicalize_block(&f_hash) .map_err(|e: sc_state_db::Error| sp_blockchain::Error::from(format!("State database error: {:?}", e)))?; @@ -1357,18 +1326,18 @@ impl Backend { } } -fn apply_state_commit(transaction: &mut DBTransaction, commit: sc_state_db::CommitSet>) { +fn apply_state_commit(transaction: &mut Transaction, commit: sc_state_db::CommitSet>) { for (key, val) in commit.data.inserted.into_iter() { - transaction.put(columns::STATE, &key[..], &val); + transaction.set_from_vec(columns::STATE, &key[..], val); } for key in commit.data.deleted.into_iter() { - transaction.delete(columns::STATE, &key[..]); + transaction.remove(columns::STATE, &key[..]); } for (key, val) in commit.meta.inserted.into_iter() { - transaction.put(columns::STATE_META, &key[..], &val); + transaction.set_from_vec(columns::STATE_META, &key[..], val); } for key in commit.meta.deleted.into_iter() { - transaction.delete(columns::STATE_META, &key[..]); + transaction.remove(columns::STATE_META, &key[..]); } } @@ -1380,19 +1349,19 @@ impl sc_client_api::backend::AuxStore for Backend where Block: Blo I: IntoIterator, D: IntoIterator, >(&self, insert: I, delete: D) -> ClientResult<()> { - let mut transaction = DBTransaction::new(); + let mut transaction = Transaction::new(); for (k, v) in insert { - transaction.put(columns::AUX, k, v); + transaction.set(columns::AUX, k, v); } for k in delete { - transaction.delete(columns::AUX, k); + transaction.remove(columns::AUX, k); } - self.storage.db.write(transaction).map_err(db_err)?; + self.storage.db.commit(transaction)?; Ok(()) } 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)?) + Ok(self.storage.db.get(columns::AUX, key)) } } @@ -1412,6 +1381,7 @@ impl sc_client_api::backend::Backend for Backend { db_updates: PrefixedMemoryDB::default(), storage_updates: Default::default(), child_storage_updates: Default::default(), + offchain_storage_updates: Default::default(), changes_trie_config_update: None, changes_trie_updates: MemoryDB::default(), changes_trie_build_cache_update: None, @@ -1453,36 +1423,24 @@ impl sc_client_api::backend::Backend for Backend { fn finalize_block(&self, block: BlockId, justification: Option) -> ClientResult<()> { - let mut transaction = DBTransaction::new(); + let mut transaction = Transaction::new(); let hash = self.blockchain.expect_block_hash_from_id(&block)?; let header = self.blockchain.expect_header(block)?; let mut displaced = None; - let commit = |displaced| { - let mut changes_trie_cache_ops = None; - let (hash, number, is_best, is_finalized) = self.finalize_block_with_transaction( - &mut transaction, - &hash, - &header, - None, - justification, - &mut changes_trie_cache_ops, - displaced, - )?; - self.storage.db.write(transaction).map_err(db_err)?; - self.blockchain.update_meta(hash, number, is_best, is_finalized); - self.changes_tries_storage.post_commit(changes_trie_cache_ops); - Ok(()) - }; - match commit(&mut displaced) { - Ok(()) => self.storage.state_db.apply_pending(), - e @ Err(_) => { - self.storage.state_db.revert_pending(); - if let Some(displaced) = displaced { - self.blockchain.leaves.write().undo().undo_finalization(displaced); - } - return e; - } - } + + let mut changes_trie_cache_ops = None; + let (hash, number, is_best, is_finalized) = self.finalize_block_with_transaction( + &mut transaction, + &hash, + &header, + None, + justification, + &mut changes_trie_cache_ops, + &mut displaced, + )?; + self.storage.db.commit(transaction)?; + self.blockchain.update_meta(hash, number, is_best, is_finalized); + self.changes_tries_storage.post_commit(changes_trie_cache_ops); Ok(()) } @@ -1497,11 +1455,12 @@ impl sc_client_api::backend::Backend for Backend { fn usage_info(&self) -> Option { let (io_stats, state_stats) = self.io_stats.take_or_else(|| ( - self.storage.db.io_stats(kvdb::IoStatsKind::SincePrevious), + // TODO: implement DB stats and cache size retrieval + kvdb::IoStats::empty(), self.state_usage.take(), ) ); - let database_cache = MemorySize::from_bytes(parity_util_mem::malloc_size(&*self.storage.db)); + let database_cache = MemorySize::from_bytes(0); let state_cache = MemorySize::from_bytes( (*&self.shared_cache).lock().used_storage_cache_size(), ); @@ -1547,7 +1506,7 @@ impl sc_client_api::backend::Backend for Backend { if best_number.is_zero() { return Ok(c.saturated_into::>()) } - let mut transaction = DBTransaction::new(); + let mut transaction = Transaction::new(); match self.storage.state_db.revert_one() { Some(commit) => { apply_state_commit(&mut transaction, commit); @@ -1571,13 +1530,13 @@ impl sc_client_api::backend::Backend for Backend { removed_number, ), )?; - transaction.put(columns::META, meta_keys::BEST_BLOCK, &key); if update_finalized { - transaction.put(columns::META, meta_keys::FINALIZED_BLOCK, &key); + transaction.set_from_vec(columns::META, meta_keys::FINALIZED_BLOCK, key.clone()); } - transaction.delete(columns::KEY_LOOKUP, removed.hash().as_ref()); + transaction.set_from_vec(columns::META, meta_keys::BEST_BLOCK, key); + transaction.remove(columns::KEY_LOOKUP, removed.hash().as_ref()); children::remove_children(&mut transaction, columns::META, meta_keys::CHILDREN_PREFIX, best_hash); - self.storage.db.write(transaction).map_err(db_err)?; + self.storage.db.commit(transaction)?; self.changes_tries_storage.post_commit(Some(changes_trie_cache_ops)); self.blockchain.update_meta(best_hash, best_number, true, update_finalized); } @@ -1591,12 +1550,12 @@ impl sc_client_api::backend::Backend for Backend { let reverted = revert_blocks()?; let revert_leaves = || -> ClientResult<()> { - let mut transaction = DBTransaction::new(); + let mut transaction = Transaction::new(); let mut leaves = self.blockchain.leaves.write(); leaves.revert(best_hash, best_number); leaves.prepare_transaction(&mut transaction, columns::META, meta_keys::LEAF_PREFIX); - self.storage.db.write(transaction).map_err(db_err)?; + self.storage.db.commit(transaction)?; Ok(()) }; @@ -1611,7 +1570,7 @@ impl sc_client_api::backend::Backend for Backend { } fn state_at(&self, block: BlockId) -> ClientResult { - use sc_client::blockchain::HeaderBackend as BcHeaderBackend; + use sc_client_api::blockchain::HeaderBackend as BcHeaderBackend; // special case for genesis initialization match block { @@ -1635,10 +1594,16 @@ impl sc_client_api::backend::Backend for Backend { _ => {} } - match self.blockchain.header(block) { - Ok(Some(ref hdr)) => { - let hash = hdr.hash(); - if !self.have_state_at(&hash, *hdr.number()) { + let hash = match block { + BlockId::Hash(h) => h, + BlockId::Number(n) => self.blockchain.hash(n)?.ok_or_else(|| + sp_blockchain::Error::UnknownBlock(format!("Unknown block number {}", n)) + )?, + }; + + match self.blockchain.header_metadata(hash) { + Ok(ref hdr) => { + if !self.have_state_at(&hash, hdr.number) { return Err( sp_blockchain::Error::UnknownBlock( format!("State already discarded for {:?}", block) @@ -1646,8 +1611,8 @@ impl sc_client_api::backend::Backend for Backend { ) } if let Ok(()) = self.storage.state_db.pin(&hash) { - let root = hdr.state_root(); - let db_state = DbState::::new(self.storage.clone(), *root); + let root = hdr.state_root; + let db_state = DbState::::new(self.storage.clone(), root); let state = RefTrackingState::new( db_state, self.storage.clone(), @@ -1672,22 +1637,17 @@ impl sc_client_api::backend::Backend for Backend { ) } }, - Ok(None) => Err( - sp_blockchain::Error::UnknownBlock( - format!("Unknown state for block {:?}", block) - ) - ), Err(e) => Err(e), } } fn have_state_at(&self, hash: &Block::Hash, number: NumberFor) -> bool { if self.is_archive { - match self.blockchain.header(BlockId::Hash(hash.clone())) { - Ok(Some(header)) => { + match self.blockchain.header_metadata(hash.clone()) { + Ok(header) => { sp_state_machine::Storage::get( self.storage.as_ref(), - &header.state_root(), + &header.state_root, (&[], None), ).unwrap_or(None).is_some() }, @@ -1712,7 +1672,7 @@ pub(crate) mod tests { use crate::columns; use sp_core::H256; use sc_client_api::backend::{Backend as BTrait, BlockImportOperation as Op}; - use sc_client::blockchain::Backend as BLBTrait; + use sc_client_api::blockchain::Backend as BLBTrait; use sp_runtime::testing::{Header, Block as RawBlock, ExtrinsicWrapper}; use sp_runtime::traits::{Hash, BlakeTwo256}; use sp_runtime::generic::DigestItem; @@ -1851,14 +1811,13 @@ pub(crate) mod tests { header.state_root = op.old_state.storage_root(storage .iter() - .cloned() - .map(|(x, y)| (x, Some(y))) + .map(|(x, y)| (&x[..], Some(&y[..]))) ).0.into(); let hash = header.hash(); op.reset_storage(Storage { - top: storage.iter().cloned().collect(), - children: Default::default(), + top: storage.into_iter().collect(), + children_default: Default::default(), }).unwrap(); op.set_block_data( header.clone(), @@ -1894,7 +1853,10 @@ pub(crate) mod tests { (vec![5, 5, 5], Some(vec![4, 5, 6])), ]; - let (root, overlay) = op.old_state.storage_root(storage.iter().cloned()); + let (root, overlay) = op.old_state.storage_root( + storage.iter() + .map(|(k, v)| (&k[..], v.as_ref().map(|v| &v[..]))) + ); op.update_db_storage(overlay).unwrap(); header.state_root = root.into(); @@ -1933,18 +1895,12 @@ pub(crate) mod tests { extrinsics_root: Default::default(), }; - let storage: Vec<(_, _)> = vec![]; - - header.state_root = op.old_state.storage_root(storage - .iter() - .cloned() - .map(|(x, y)| (x, Some(y))) - ).0.into(); + header.state_root = op.old_state.storage_root(std::iter::empty()).0.into(); let hash = header.hash(); op.reset_storage(Storage { - top: storage.iter().cloned().collect(), - children: Default::default(), + top: Default::default(), + children_default: Default::default(), }).unwrap(); key = op.db_updates.insert(EMPTY_PREFIX, b"hello"); @@ -1959,7 +1915,7 @@ pub(crate) mod tests { assert_eq!(backend.storage.db.get( columns::STATE, &sp_trie::prefixed_key::(&key, EMPTY_PREFIX) - ).unwrap().unwrap(), &b"hello"[..]); + ).unwrap(), &b"hello"[..]); hash }; @@ -1996,7 +1952,7 @@ pub(crate) mod tests { assert_eq!(backend.storage.db.get( columns::STATE, &sp_trie::prefixed_key::(&key, EMPTY_PREFIX) - ).unwrap().unwrap(), &b"hello"[..]); + ).unwrap(), &b"hello"[..]); hash }; @@ -2034,7 +1990,7 @@ pub(crate) mod tests { assert!(backend.storage.db.get( columns::STATE, &sp_trie::prefixed_key::(&key, EMPTY_PREFIX) - ).unwrap().is_some()); + ).is_some()); hash }; @@ -2068,7 +2024,7 @@ pub(crate) mod tests { assert!(backend.storage.db.get( columns::STATE, &sp_trie::prefixed_key::(&key, EMPTY_PREFIX) - ).unwrap().is_none()); + ).is_none()); } backend.finalize_block(BlockId::Number(1), None).unwrap(); @@ -2077,7 +2033,7 @@ pub(crate) mod tests { assert!(backend.storage.db.get( columns::STATE, &sp_trie::prefixed_key::(&key, EMPTY_PREFIX) - ).unwrap().is_none()); + ).is_none()); } #[test] @@ -2291,7 +2247,7 @@ pub(crate) mod tests { #[test] fn test_finalize_block_with_justification() { - use sc_client::blockchain::{Backend as BlockChainBackend}; + use sc_client_api::blockchain::{Backend as BlockChainBackend}; let backend = Backend::::new_test(10, 10); diff --git a/client/db/src/light.rs b/client/db/src/light.rs index 808a209f527c170afdbb0e9091c7233a74dbd248..3dc6453cd90da0b4e71124a327cdf825169378a7 100644 --- a/client/db/src/light.rs +++ b/client/db/src/light.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! RocksDB-based light client blockchain storage. @@ -20,26 +22,26 @@ use std::{sync::Arc, collections::HashMap}; use std::convert::TryInto; use parking_lot::RwLock; -use kvdb::{KeyValueDB, DBTransaction}; - -use sc_client_api::{backend::{AuxStore, NewBlockState}, UsageInfo}; -use sc_client::blockchain::{ - BlockStatus, Cache as BlockchainCache,Info as BlockchainInfo, +use sc_client_api::{ + cht, backend::{AuxStore, NewBlockState}, UsageInfo, + blockchain::{ + BlockStatus, Cache as BlockchainCache, Info as BlockchainInfo, + }, + Storage }; -use sc_client::cht; use sp_blockchain::{ CachedHeaderMetadata, HeaderMetadata, HeaderMetadataCache, Error as ClientError, Result as ClientResult, HeaderBackend as BlockchainHeaderBackend, well_known_cache_keys, }; -use sc_client::light::blockchain::Storage as LightBlockchainStorage; +use sp_database::{Database, Transaction}; use codec::{Decode, Encode}; use sp_runtime::generic::{DigestItem, BlockId}; use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Zero, One, NumberFor, HashFor}; use crate::cache::{DbCacheSync, DbCache, ComplexBlockId, EntryType as CacheEntryType}; -use crate::utils::{self, meta_keys, DatabaseType, Meta, db_err, read_db, block_id_to_lookup_key, read_meta}; -use crate::{DatabaseSettings, FrozenForDuration}; +use crate::utils::{self, meta_keys, DatabaseType, Meta, read_db, block_id_to_lookup_key, read_meta}; +use crate::{DatabaseSettings, FrozenForDuration, DbHash}; use log::{trace, warn, debug}; pub(crate) mod columns { @@ -59,10 +61,10 @@ const CHANGES_TRIE_CHT_PREFIX: u8 = 1; /// Light blockchain storage. Stores most recent headers + CHTs for older headers. /// Locks order: meta, cache. pub struct LightStorage { - db: Arc, + db: Arc>, meta: RwLock, Block::Hash>>, cache: Arc>, - header_metadata_cache: HeaderMetadataCache, + header_metadata_cache: Arc>, #[cfg(not(target_os = "unknown"))] io_stats: FrozenForDuration, @@ -78,17 +80,16 @@ impl LightStorage { /// Create new memory-backed `LightStorage` for tests. #[cfg(any(test, feature = "test-helpers"))] pub fn new_test() -> Self { - use utils::NUM_COLUMNS; - - let db = Arc::new(::kvdb_memorydb::create(NUM_COLUMNS)); - + let db = Arc::new(sp_database::MemDb::default()); Self::from_kvdb(db as Arc<_>).expect("failed to create test-db") } - fn from_kvdb(db: Arc) -> ClientResult { + fn from_kvdb(db: Arc>) -> ClientResult { let meta = read_meta::(&*db, columns::HEADER)?; + let header_metadata_cache = Arc::new(HeaderMetadataCache::default()); let cache = DbCache::new( db.clone(), + header_metadata_cache.clone(), columns::KEY_LOOKUP, columns::HEADER, columns::CACHE, @@ -100,7 +101,7 @@ impl LightStorage { db, meta: RwLock::new(meta), cache: Arc::new(DbCacheSync(RwLock::new(cache))), - header_metadata_cache: HeaderMetadataCache::default(), + header_metadata_cache, #[cfg(not(target_os = "unknown"))] io_stats: FrozenForDuration::new(std::time::Duration::from_secs(1)), }) @@ -191,7 +192,7 @@ 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_metadata_cache.header_metadata(hash).map_or_else(|| { self.header(BlockId::hash(hash))?.map(|header| { let header_metadata = CachedHeaderMetadata::from(&header); self.header_metadata_cache.insert_header_metadata( @@ -200,7 +201,7 @@ impl HeaderMetadata for LightStorage { ); header_metadata }).ok_or(ClientError::UnknownBlock(format!("header not found in db: {}", hash))) - }) + }, Ok) } fn insert_header_metadata(&self, hash: Block::Hash, metadata: CachedHeaderMetadata) { @@ -230,7 +231,7 @@ impl LightStorage { /// to be best, `route_to` should equal to `best_to`. fn set_head_with_transaction( &self, - transaction: &mut DBTransaction, + transaction: &mut Transaction, route_to: Block::Hash, best_to: (NumberFor, Block::Hash), ) -> ClientResult<()> { @@ -266,7 +267,7 @@ impl LightStorage { } } - transaction.put(columns::META, meta_keys::BEST_BLOCK, &lookup_key); + transaction.set_from_vec(columns::META, meta_keys::BEST_BLOCK, lookup_key); utils::insert_number_to_key_mapping( transaction, columns::KEY_LOOKUP, @@ -280,7 +281,7 @@ impl LightStorage { // Note that a block is finalized. Only call with child of last finalized block. fn note_finalized( &self, - transaction: &mut DBTransaction, + transaction: &mut Transaction, header: &Block::Header, hash: Block::Hash, ) -> ClientResult<()> { @@ -293,7 +294,7 @@ impl LightStorage { } let lookup_key = utils::number_and_hash_to_lookup_key(header.number().clone(), hash)?; - transaction.put(columns::META, meta_keys::FINALIZED_BLOCK, &lookup_key); + transaction.set_from_vec(columns::META, meta_keys::FINALIZED_BLOCK, lookup_key); // build new CHT(s) if required if let Some(new_cht_number) = cht::is_build_required(cht::size(), *header.number()) { @@ -309,7 +310,7 @@ impl LightStorage { let new_header_cht_root = cht::compute_root::, _>( cht::size(), new_cht_number, cht_range.map(|num| self.hash(num)) )?; - transaction.put( + transaction.set( columns::CHT, &cht_key(HEADER_CHT_PREFIX, new_cht_start)?, new_header_cht_root.as_ref() @@ -327,7 +328,7 @@ impl LightStorage { cht::size(), new_cht_number, cht_range .map(|num| self.changes_trie_root(BlockId::Number(num))) )?; - transaction.put( + transaction.set( columns::CHT, &cht_key(CHANGES_TRIE_CHT_PREFIX, new_cht_start)?, new_changes_trie_cht_root.as_ref() @@ -350,7 +351,7 @@ impl LightStorage { prune_block, hash )?; - transaction.delete(columns::HEADER, &lookup_key); + transaction.remove(columns::HEADER, &lookup_key); } prune_block += One::one(); } @@ -377,7 +378,7 @@ impl LightStorage { } let cht_start = cht::start_number(cht_size, cht_number); - self.db.get(columns::CHT, &cht_key(cht_type, cht_start)?).map_err(db_err)? + self.db.get(columns::CHT, &cht_key(cht_type, cht_start)?) .ok_or_else(no_cht_for_block) .and_then(|hash| Block::Hash::decode(&mut &*hash).map_err(|_| no_cht_for_block())) .map(Some) @@ -394,22 +395,24 @@ impl AuxStore for LightStorage I: IntoIterator, D: IntoIterator, >(&self, insert: I, delete: D) -> ClientResult<()> { - let mut transaction = DBTransaction::new(); + let mut transaction = Transaction::new(); for (k, v) in insert { - transaction.put(columns::AUX, k, v); + transaction.set(columns::AUX, k, v); } for k in delete { - transaction.delete(columns::AUX, k); + transaction.remove(columns::AUX, k); } - self.db.write(transaction).map_err(db_err) + self.db.commit(transaction)?; + + Ok(()) } fn get_aux(&self, key: &[u8]) -> ClientResult>> { - self.db.get(columns::AUX, key).map(|r| r.map(|v| v.to_vec())).map_err(db_err) + Ok(self.db.get(columns::AUX, key)) } } -impl LightBlockchainStorage for LightStorage +impl Storage for LightStorage where Block: BlockT, { fn import_header( @@ -419,7 +422,7 @@ impl LightBlockchainStorage for LightStorage leaf_state: NewBlockState, aux_ops: Vec<(Vec, Option>)>, ) -> ClientResult<()> { - let mut transaction = DBTransaction::new(); + let mut transaction = Transaction::new(); let hash = header.hash(); let number = *header.number(); @@ -427,8 +430,8 @@ impl LightBlockchainStorage for LightStorage for (key, maybe_val) in aux_ops { match maybe_val { - Some(val) => transaction.put_vec(columns::AUX, &key, val), - None => transaction.delete(columns::AUX, &key), + Some(val) => transaction.set_from_vec(columns::AUX, &key, val), + None => transaction.remove(columns::AUX, &key), } } @@ -445,7 +448,7 @@ impl LightBlockchainStorage for LightStorage number, hash, )?; - transaction.put(columns::HEADER, &lookup_key, &header.encode()); + transaction.set_from_vec(columns::HEADER, &lookup_key, header.encode()); let header_metadata = CachedHeaderMetadata::from(&header); self.header_metadata_cache.insert_header_metadata( @@ -456,7 +459,7 @@ impl LightBlockchainStorage for LightStorage let is_genesis = number.is_zero(); if is_genesis { self.cache.0.write().set_genesis_hash(hash); - transaction.put(columns::META, meta_keys::GENESIS_HASH, hash.as_ref()); + transaction.set(columns::META, meta_keys::GENESIS_HASH, hash.as_ref()); } let finalized = match leaf_state { @@ -493,7 +496,7 @@ impl LightBlockchainStorage for LightStorage debug!("Light DB Commit {:?} ({})", hash, number); - self.db.write(transaction).map_err(db_err)?; + self.db.commit(transaction)?; cache.commit(cache_ops) .expect("only fails if cache with given name isn't loaded yet;\ cache is already loaded because there are cache_ops; qed"); @@ -509,10 +512,11 @@ impl LightBlockchainStorage for LightStorage let hash = header.hash(); let number = header.number(); - let mut transaction = DBTransaction::new(); + let mut transaction = Transaction::new(); self.set_head_with_transaction(&mut transaction, hash.clone(), (number.clone(), hash.clone()))?; - self.db.write(transaction).map_err(db_err)?; + self.db.commit(transaction)?; self.update_meta(hash, header.number().clone(), true, false); + Ok(()) } else { Err(ClientError::UnknownBlock(format!("Cannot set head {:?}", id))) @@ -537,7 +541,7 @@ impl LightBlockchainStorage for LightStorage fn finalize_header(&self, id: BlockId) -> ClientResult<()> { if let Some(header) = self.header(id)? { - let mut transaction = DBTransaction::new(); + let mut transaction = Transaction::new(); let hash = header.hash(); let number = *header.number(); self.note_finalized(&mut transaction, &header, hash.clone())?; @@ -550,7 +554,7 @@ impl LightBlockchainStorage for LightStorage )? .into_ops(); - self.db.write(transaction).map_err(db_err)?; + self.db.commit(transaction)?; cache.commit(cache_ops) .expect("only fails if cache with given name isn't loaded yet;\ cache is already loaded because there are cache_ops; qed"); @@ -575,8 +579,9 @@ impl LightBlockchainStorage for LightStorage fn usage_info(&self) -> Option { use sc_client_api::{MemoryInfo, IoInfo, MemorySize}; - let database_cache = MemorySize::from_bytes(parity_util_mem::malloc_size(&*self.db)); - let io_stats = self.io_stats.take_or_else(|| self.db.io_stats(kvdb::IoStatsKind::SincePrevious)); + // TODO: reimplement IO stats + let database_cache = MemorySize::from_bytes(0); + let io_stats = self.io_stats.take_or_else(|| kvdb::IoStats::empty()); Some(UsageInfo { memory: MemoryInfo { @@ -616,7 +621,7 @@ fn cht_key>(cht_type: u8, block: N) -> ClientResult<[u8; 5]> { #[cfg(test)] pub(crate) mod tests { - use sc_client::cht; + use sc_client_api::cht; use sp_core::ChangesTrieConfiguration; use sp_runtime::generic::{DigestItem, ChangesTrieSignal}; use sp_runtime::testing::{H256 as Hash, Header, Block as RawBlock, ExtrinsicWrapper}; @@ -732,21 +737,25 @@ pub(crate) mod tests { #[test] fn import_header_works() { - let db = LightStorage::new_test(); + let raw_db = Arc::new(sp_database::MemDb::default()); + let db = LightStorage::from_kvdb(raw_db.clone()).unwrap(); let genesis_hash = insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); - assert_eq!(db.db.iter(columns::HEADER).count(), 1); - assert_eq!(db.db.iter(columns::KEY_LOOKUP).count(), 2); + assert_eq!(raw_db.count(columns::HEADER), 1); + assert_eq!(raw_db.count(columns::KEY_LOOKUP), 2); let _ = insert_block(&db, HashMap::new(), || default_header(&genesis_hash, 1)); - assert_eq!(db.db.iter(columns::HEADER).count(), 2); - assert_eq!(db.db.iter(columns::KEY_LOOKUP).count(), 4); + assert_eq!(raw_db.count(columns::HEADER), 2); + assert_eq!(raw_db.count(columns::KEY_LOOKUP), 4); } #[test] fn finalized_ancient_headers_are_replaced_with_cht() { - fn insert_headers Header>(header_producer: F) -> LightStorage { - let db = LightStorage::new_test(); + fn insert_headers Header>(header_producer: F) -> + (Arc>, LightStorage) + { + let raw_db = Arc::new(sp_database::MemDb::default()); + let db = LightStorage::from_kvdb(raw_db.clone()).unwrap(); let cht_size: u64 = cht::size(); let ucht_size: usize = cht_size as _; @@ -758,8 +767,8 @@ pub(crate) mod tests { for number in 0..cht::size() { prev_hash = insert_block(&db, HashMap::new(), || header_producer(&prev_hash, 1 + number)); } - assert_eq!(db.db.iter(columns::HEADER).count(), 1 + ucht_size); - assert_eq!(db.db.iter(columns::CHT).count(), 0); + assert_eq!(raw_db.count(columns::HEADER), 1 + ucht_size); + assert_eq!(raw_db.count(columns::CHT), 0); // insert next SIZE blocks && ensure that nothing is pruned for number in 0..(cht_size as _) { @@ -769,8 +778,8 @@ pub(crate) mod tests { || header_producer(&prev_hash, 1 + cht_size + number), ); } - assert_eq!(db.db.iter(columns::HEADER).count(), 1 + ucht_size + ucht_size); - assert_eq!(db.db.iter(columns::CHT).count(), 0); + assert_eq!(raw_db.count(columns::HEADER), 1 + ucht_size + ucht_size); + assert_eq!(raw_db.count(columns::CHT), 0); // insert block #{2 * cht::size() + 1} && check that new CHT is created + headers of this CHT are pruned // nothing is yet finalized, so nothing is pruned. @@ -779,23 +788,23 @@ pub(crate) mod tests { HashMap::new(), || header_producer(&prev_hash, 1 + cht_size + cht_size), ); - assert_eq!(db.db.iter(columns::HEADER).count(), 2 + ucht_size + ucht_size); - assert_eq!(db.db.iter(columns::CHT).count(), 0); + assert_eq!(raw_db.count(columns::HEADER), 2 + ucht_size + ucht_size); + assert_eq!(raw_db.count(columns::CHT), 0); // now finalize the block. for i in (0..(ucht_size + ucht_size)).map(|i| i + 1) { db.finalize_header(BlockId::Number(i as _)).unwrap(); } db.finalize_header(BlockId::Hash(prev_hash)).unwrap(); - db + (raw_db, db) } // when headers are created without changes tries roots - let db = insert_headers(default_header); + let (raw_db, db) = insert_headers(default_header); let cht_size: u64 = cht::size(); - assert_eq!(db.db.iter(columns::HEADER).count(), (1 + cht_size + 1) as usize); - assert_eq!(db.db.iter(columns::KEY_LOOKUP).count(), (2 * (1 + cht_size + 1)) as usize); - assert_eq!(db.db.iter(columns::CHT).count(), 1); + assert_eq!(raw_db.count(columns::HEADER), (1 + cht_size + 1) as usize); + assert_eq!(raw_db.count(columns::KEY_LOOKUP), (2 * (1 + cht_size + 1)) as usize); + assert_eq!(raw_db.count(columns::CHT), 1); assert!((0..cht_size as _).all(|i| db.header(BlockId::Number(1 + i)).unwrap().is_none())); assert!(db.header_cht_root(cht_size, cht_size / 2).unwrap().is_some()); assert!(db.header_cht_root(cht_size, cht_size + cht_size / 2).unwrap().is_none()); @@ -803,9 +812,9 @@ pub(crate) mod tests { assert!(db.changes_trie_cht_root(cht_size, cht_size + cht_size / 2).unwrap().is_none()); // when headers are created with changes tries roots - let db = insert_headers(header_with_changes_trie); - assert_eq!(db.db.iter(columns::HEADER).count(), (1 + cht_size + 1) as usize); - assert_eq!(db.db.iter(columns::CHT).count(), 2); + let (raw_db, db) = insert_headers(header_with_changes_trie); + assert_eq!(raw_db.count(columns::HEADER), (1 + cht_size + 1) as usize); + assert_eq!(raw_db.count(columns::CHT), 2); assert!((0..cht_size as _).all(|i| db.header(BlockId::Number(1 + i)).unwrap().is_none())); assert!(db.header_cht_root(cht_size, cht_size / 2).unwrap().is_some()); assert!(db.header_cht_root(cht_size, cht_size + cht_size / 2).unwrap().is_none()); @@ -963,7 +972,7 @@ pub(crate) mod tests { fn run_checks(db: &LightStorage, max: u64, checks: &[(u64, Option>)]) { for (at, expected) in checks.iter().take_while(|(at, _)| *at <= max) { - let actual = get_authorities(db.cache(), BlockId::Number(*at)); + let actual = authorities(db.cache(), BlockId::Number(*at)); assert_eq!(*expected, actual); } } @@ -978,7 +987,7 @@ pub(crate) mod tests { map } - fn get_authorities(cache: &dyn BlockchainCache, at: BlockId) -> Option> { + fn authorities(cache: &dyn BlockchainCache, at: BlockId) -> Option> { cache.get_at(&well_known_cache_keys::AUTHORITIES, &at).unwrap_or(None) .and_then(|(_, _, val)| Decode::decode(&mut &val[..]).ok()) } @@ -1026,9 +1035,9 @@ pub(crate) mod tests { // ... -> B2(1) -> B2_1(1) -> B2_2(2) // => the cache ignores all writes before best finalized block let hash2_1 = insert_non_best_block(&db, make_authorities(vec![auth1()]), || default_header(&hash2, 3)); - assert_eq!(None, get_authorities(db.cache(), BlockId::Hash(hash2_1))); + assert_eq!(None, authorities(db.cache(), BlockId::Hash(hash2_1))); let hash2_2 = insert_non_best_block(&db, make_authorities(vec![auth1(), auth2()]), || default_header(&hash2_1, 4)); - assert_eq!(None, get_authorities(db.cache(), BlockId::Hash(hash2_2))); + assert_eq!(None, authorities(db.cache(), BlockId::Hash(hash2_2))); } let (hash7, hash8, hash6_1, hash6_2, hash6_1_1, hash6_1_2) = { @@ -1040,55 +1049,55 @@ pub(crate) mod tests { let hash7 = insert_block(&db, make_authorities(vec![auth3()]), || default_header(&hash6, 7)); assert_eq!( - get_authorities(db.cache(), BlockId::Hash(hash6)), + authorities(db.cache(), BlockId::Hash(hash6)), Some(vec![auth1(), auth2()]), ); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); let hash8 = insert_block(&db, make_authorities(vec![auth3()]), || default_header(&hash7, 8)); assert_eq!( - get_authorities(db.cache(), BlockId::Hash(hash6)), + authorities(db.cache(), BlockId::Hash(hash6)), Some(vec![auth1(), auth2()]), ); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); let hash6_1 = insert_block(&db, make_authorities(vec![auth4()]), || default_header(&hash6, 7)); assert_eq!( - get_authorities(db.cache(), BlockId::Hash(hash6)), + authorities(db.cache(), BlockId::Hash(hash6)), Some(vec![auth1(), auth2()]), ); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); let hash6_1_1 = insert_non_best_block(&db, make_authorities(vec![auth5()]), || default_header(&hash6_1, 8)); assert_eq!( - get_authorities(db.cache(), BlockId::Hash(hash6)), + authorities(db.cache(), BlockId::Hash(hash6)), Some(vec![auth1(), auth2()]), ); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_1)), Some(vec![auth5()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1_1)), Some(vec![auth5()])); let hash6_1_2 = insert_non_best_block(&db, make_authorities(vec![auth6()]), || default_header(&hash6_1, 8)); assert_eq!( - get_authorities(db.cache(), BlockId::Hash(hash6)), + authorities(db.cache(), BlockId::Hash(hash6)), Some(vec![auth1(), auth2()]), ); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_1)), Some(vec![auth5()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_2)), Some(vec![auth6()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1_1)), Some(vec![auth5()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1_2)), Some(vec![auth6()])); let hash6_2 = insert_block(&db, make_authorities(vec![auth4()]), || default_header(&hash6_1, 8)); assert_eq!( - get_authorities(db.cache(), BlockId::Hash(hash6)), + authorities(db.cache(), BlockId::Hash(hash6)), Some(vec![auth1(), auth2()]), ); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_1)), Some(vec![auth5()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_2)), Some(vec![auth6()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_2)), Some(vec![auth4()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1_1)), Some(vec![auth5()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1_2)), Some(vec![auth6()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_2)), Some(vec![auth4()])); (hash7, hash8, hash6_1, hash6_2, hash6_1_1, hash6_1_2) }; @@ -1097,27 +1106,27 @@ pub(crate) mod tests { // finalize block hash6_1 db.finalize_header(BlockId::Hash(hash6_1)).unwrap(); assert_eq!( - get_authorities(db.cache(), BlockId::Hash(hash6)), + authorities(db.cache(), BlockId::Hash(hash6)), Some(vec![auth1(), auth2()]), ); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), None); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), None); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_1)), Some(vec![auth5()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_2)), Some(vec![auth6()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_2)), Some(vec![auth4()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash7)), None); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash8)), None); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1_1)), Some(vec![auth5()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1_2)), Some(vec![auth6()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_2)), Some(vec![auth4()])); // finalize block hash6_2 db.finalize_header(BlockId::Hash(hash6_2)).unwrap(); assert_eq!( - get_authorities(db.cache(), BlockId::Hash(hash6)), + authorities(db.cache(), BlockId::Hash(hash6)), Some(vec![auth1(), auth2()]), ); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), None); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), None); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_1)), None); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_2)), None); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_2)), Some(vec![auth4()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash7)), None); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash8)), None); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1_1)), None); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1_2)), None); + assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_2)), Some(vec![auth4()])); } } diff --git a/client/db/src/offchain.rs b/client/db/src/offchain.rs index 3d0f8c6795a940d246835826817fe2661bec74ec..c4f0ce115ca54f1453e857cc34b96fd26918f8a8 100644 --- a/client/db/src/offchain.rs +++ b/client/db/src/offchain.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! RocksDB-based offchain workers local storage. @@ -21,14 +23,14 @@ use std::{ sync::Arc, }; -use crate::columns; -use kvdb::KeyValueDB; +use crate::{columns, Database, DbHash, Transaction}; use parking_lot::Mutex; +use log::error; /// Offchain local storage #[derive(Clone)] pub struct LocalStorage { - db: Arc, + db: Arc>, locks: Arc, Arc>>>>, } @@ -43,12 +45,13 @@ impl LocalStorage { /// Create new offchain storage for tests (backed by memorydb) #[cfg(any(test, feature = "test-helpers"))] pub fn new_test() -> Self { - let db = Arc::new(kvdb_memorydb::create(crate::utils::NUM_COLUMNS)); + let db = kvdb_memorydb::create(crate::utils::NUM_COLUMNS); + let db = sp_database::as_database(db); Self::new(db as _) } /// Create offchain local storage with given `KeyValueDB` backend. - pub fn new(db: Arc) -> Self { + pub fn new(db: Arc>) -> Self { Self { db, locks: Default::default(), @@ -59,20 +62,27 @@ impl LocalStorage { impl sp_core::offchain::OffchainStorage for LocalStorage { fn set(&mut self, prefix: &[u8], key: &[u8], value: &[u8]) { let key: Vec = prefix.iter().chain(key).cloned().collect(); - let mut tx = self.db.transaction(); - tx.put(columns::OFFCHAIN, &key, value); + let mut tx = Transaction::new(); + tx.set(columns::OFFCHAIN, &key, value); + + if let Err(err) = self.db.commit(tx) { + error!("Error setting on local storage: {}", err) + } + } + + fn remove(&mut self, prefix: &[u8], key: &[u8]) { + let key: Vec = prefix.iter().chain(key).cloned().collect(); + let mut tx = Transaction::new(); + tx.remove(columns::OFFCHAIN, &key); - if let Err(e) = self.db.write(tx) { - log::warn!("Error writing to the offchain DB: {:?}", e); + if let Err(err) = self.db.commit(tx) { + error!("Error removing on local storage: {}", err) } } fn get(&self, prefix: &[u8], key: &[u8]) -> Option> { let key: Vec = prefix.iter().chain(key).cloned().collect(); self.db.get(columns::OFFCHAIN, &key) - .ok() - .and_then(|x| x) - .map(|v| v.to_vec()) } fn compare_and_set( @@ -91,9 +101,7 @@ impl sp_core::offchain::OffchainStorage for LocalStorage { let is_set; { let _key_guard = key_lock.lock(); - let val = self.db.get(columns::OFFCHAIN, &key) - .ok() - .and_then(|x| x); + let val = self.db.get(columns::OFFCHAIN, &key); is_set = val.as_ref().map(|x| &**x) == old_value; if is_set { diff --git a/client/db/src/parity_db.rs b/client/db/src/parity_db.rs new file mode 100644 index 0000000000000000000000000000000000000000..7085aa3bf8ccde1495627340352e24d4f9992a14 --- /dev/null +++ b/client/db/src/parity_db.rs @@ -0,0 +1,66 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +/// A `Database` adapter for parity-db. + +use sp_database::{Database, Change, ColumnId, Transaction, error::DatabaseError}; +use crate::utils::NUM_COLUMNS; +use crate::columns; + +struct DbAdapter(parity_db::Db); + +fn handle_err(result: parity_db::Result) -> T { + match result { + Ok(r) => r, + Err(e) => { + panic!("Critical database error: {:?}", e); + } + } +} + +/// Wrap RocksDb database into a trait object that implements `sp_database::Database` +pub fn open(path: &std::path::Path) -> parity_db::Result>> { + let mut config = parity_db::Options::with_columns(path, NUM_COLUMNS as u8); + let mut state_col = &mut config.columns[columns::STATE as usize]; + state_col.ref_counted = true; + state_col.preimage = true; + state_col.uniform = true; + let db = parity_db::Db::open(&config)?; + Ok(std::sync::Arc::new(DbAdapter(db))) +} + +impl Database for DbAdapter { + fn commit(&self, transaction: Transaction) -> Result<(), DatabaseError> { + handle_err(self.0.commit(transaction.0.into_iter().map(|change| + match change { + Change::Set(col, key, value) => (col as u8, key, Some(value)), + Change::Remove(col, key) => (col as u8, key, None), + _ => unimplemented!(), + })) + ); + + Ok(()) + } + + fn get(&self, col: ColumnId, key: &[u8]) -> Option> { + handle_err(self.0.get(col as u8, key)) + } + + fn lookup(&self, _hash: &H) -> Option> { + unimplemented!(); + } +} diff --git a/client/db/src/stats.rs b/client/db/src/stats.rs index 8bc93b5b644cf985ff81fa0aaa0c0154c64eeaa0..8d208024b4bb29a1f064dfc00f3fa14b8df07f85 100644 --- a/client/db/src/stats.rs +++ b/client/db/src/stats.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Database usage statistics diff --git a/client/db/src/storage_cache.rs b/client/db/src/storage_cache.rs index 63268992632410934d0518039882240dee328c0d..434b301ed6240e94539cbf5d3c06265231639039 100644 --- a/client/db/src/storage_cache.rs +++ b/client/db/src/storage_cache.rs @@ -542,11 +542,10 @@ impl>, B: BlockT> StateBackend> for Cachin fn child_storage( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) -> Result>, Self::Error> { - let key = (storage_key.to_vec(), key.to_vec()); + let key = (child_info.storage_key().to_vec(), key.to_vec()); let local_cache = self.cache.local_cache.upgradable_read(); if let Some(entry) = local_cache.child_storage.get(&key).cloned() { trace!("Found in local cache: {:?}", key); @@ -564,7 +563,7 @@ impl>, B: BlockT> StateBackend> for Cachin } } trace!("Cache miss: {:?}", key); - let value = self.state.child_storage(storage_key, child_info, &key.1[..])?; + let value = self.state.child_storage(child_info, &key.1[..])?; // just pass it through the usage counter let value = self.usage.tally_child_key_read(&key, value, false); @@ -579,20 +578,18 @@ impl>, B: BlockT> StateBackend> for Cachin fn exists_child_storage( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) -> Result { - self.state.exists_child_storage(storage_key, child_info, key) + self.state.exists_child_storage(child_info, key) } fn for_keys_in_child_storage( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, f: F, ) { - self.state.for_keys_in_child_storage(storage_key, child_info, f) + self.state.for_keys_in_child_storage(child_info, f) } fn next_storage_key(&self, key: &[u8]) -> Result>, Self::Error> { @@ -601,11 +598,10 @@ impl>, B: BlockT> StateBackend> for Cachin fn next_child_storage_key( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) -> Result>, Self::Error> { - self.state.next_child_storage_key(storage_key, child_info, key) + self.state.next_child_storage_key(child_info, key) } fn for_keys_with_prefix(&self, prefix: &[u8], f: F) { @@ -618,31 +614,26 @@ impl>, B: BlockT> StateBackend> for Cachin fn for_child_keys_with_prefix( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, prefix: &[u8], f: F, ) { - self.state.for_child_keys_with_prefix(storage_key, child_info, prefix, f) + self.state.for_child_keys_with_prefix(child_info, prefix, f) } - fn storage_root(&self, delta: I) -> (B::Hash, Self::Transaction) - where - I: IntoIterator, Option>)>, - { + fn storage_root<'a>( + &self, + delta: impl Iterator)>, + ) -> (B::Hash, Self::Transaction) where B::Hash: Ord { self.state.storage_root(delta) } - fn child_storage_root( + fn child_storage_root<'a>( &self, - storage_key: &[u8], - child_info: ChildInfo, - delta: I, - ) -> (B::Hash, bool, Self::Transaction) - where - I: IntoIterator, Option>)>, - { - self.state.child_storage_root(storage_key, child_info, delta) + child_info: &ChildInfo, + delta: impl Iterator)>, + ) -> (B::Hash, bool, Self::Transaction) where B::Hash: Ord { + self.state.child_storage_root(child_info, delta) } fn pairs(&self) -> Vec<(Vec, Vec)> { @@ -655,11 +646,10 @@ impl>, B: BlockT> StateBackend> for Cachin fn child_keys( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, prefix: &[u8], ) -> Vec> { - self.state.child_keys(storage_key, child_info, prefix) + self.state.child_keys(child_info, prefix) } fn as_trie_backend(&mut self) -> Option<&TrieBackend>> { @@ -758,11 +748,10 @@ impl>, B: BlockT> StateBackend> for Syncin fn child_storage( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) -> Result>, Self::Error> { - self.caching_state().child_storage(storage_key, child_info, key) + self.caching_state().child_storage(child_info, key) } fn exists_storage(&self, key: &[u8]) -> Result { @@ -771,20 +760,18 @@ impl>, B: BlockT> StateBackend> for Syncin fn exists_child_storage( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) -> Result { - self.caching_state().exists_child_storage(storage_key, child_info, key) + self.caching_state().exists_child_storage(child_info, key) } fn for_keys_in_child_storage( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, f: F, ) { - self.caching_state().for_keys_in_child_storage(storage_key, child_info, f) + self.caching_state().for_keys_in_child_storage(child_info, f) } fn next_storage_key(&self, key: &[u8]) -> Result>, Self::Error> { @@ -793,11 +780,10 @@ impl>, B: BlockT> StateBackend> for Syncin fn next_child_storage_key( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) -> Result>, Self::Error> { - self.caching_state().next_child_storage_key(storage_key, child_info, key) + self.caching_state().next_child_storage_key(child_info, key) } fn for_keys_with_prefix(&self, prefix: &[u8], f: F) { @@ -810,31 +796,26 @@ impl>, B: BlockT> StateBackend> for Syncin fn for_child_keys_with_prefix( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, prefix: &[u8], f: F, ) { - self.caching_state().for_child_keys_with_prefix(storage_key, child_info, prefix, f) + self.caching_state().for_child_keys_with_prefix(child_info, prefix, f) } - fn storage_root(&self, delta: I) -> (B::Hash, Self::Transaction) - where - I: IntoIterator, Option>)>, - { + fn storage_root<'a>( + &self, + delta: impl Iterator)>, + ) -> (B::Hash, Self::Transaction) where B::Hash: Ord { self.caching_state().storage_root(delta) } - fn child_storage_root( + fn child_storage_root<'a>( &self, - storage_key: &[u8], - child_info: ChildInfo, - delta: I, - ) -> (B::Hash, bool, Self::Transaction) - where - I: IntoIterator, Option>)>, - { - self.caching_state().child_storage_root(storage_key, child_info, delta) + child_info: &ChildInfo, + delta: impl Iterator)>, + ) -> (B::Hash, bool, Self::Transaction) where B::Hash: Ord { + self.caching_state().child_storage_root(child_info, delta) } fn pairs(&self) -> Vec<(Vec, Vec)> { @@ -847,11 +828,10 @@ impl>, B: BlockT> StateBackend> for Syncin fn child_keys( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, prefix: &[u8], ) -> Vec> { - self.caching_state().child_keys(storage_key, child_info, prefix) + self.caching_state().child_keys(child_info, prefix) } fn as_trie_backend(&mut self) -> Option<&TrieBackend>> { diff --git a/client/db/src/subdb.rs b/client/db/src/subdb.rs new file mode 100644 index 0000000000000000000000000000000000000000..2f72632b045622fcd035e50f7560c2c4b0fe753c --- /dev/null +++ b/client/db/src/subdb.rs @@ -0,0 +1,88 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +/// A `Database` adapter for subdb. + +use sp_database::{self, ColumnId}; +use parking_lot::RwLock; +use blake2_rfc::blake2b::blake2b; +use codec::Encode; +use subdb::{Database, KeyType}; + +/// A database hidden behind an RwLock, so that it implements Send + Sync. +/// +/// Construct by creating a `Database` and then using `.into()`. +pub struct DbAdapter(RwLock>); + +/// Wrap RocksDb database into a trait object that implements `sp_database::Database` +pub fn open( + path: &std::path::Path, + _num_columns: u32, +) -> Result>, subdb::Error> { + let db = subdb::Options::from_path(path.into()).open()?; + Ok(std::sync::Arc::new(DbAdapter(RwLock::new(db)))) +} + +impl sp_database::Database for DbAdapter { + fn get(&self, col: ColumnId, key: &[u8]) -> Option> { + let mut hash = H::default(); + (col, key).using_encoded(|d| + hash.as_mut().copy_from_slice(blake2b(32, &[], d).as_bytes()) + ); + self.0.read().get(&hash) + } + + fn with_get(&self, col: ColumnId, key: &[u8], f: &mut dyn FnMut(&[u8])) { + let mut hash = H::default(); + (col, key).using_encoded(|d| + hash.as_mut().copy_from_slice(blake2b(32, &[], d).as_bytes()) + ); + let _ = self.0.read().get_ref(&hash).map(|d| f(d.as_ref())); + } + + fn set(&self, col: ColumnId, key: &[u8], value: &[u8]) { + let mut hash = H::default(); + (col, key).using_encoded(|d| + hash.as_mut().copy_from_slice(blake2b(32, &[], d).as_bytes()) + ); + self.0.write().insert(&value, &hash); + } + + fn remove(&self, col: ColumnId, key: &[u8]) { + let mut hash = H::default(); + (col, key).using_encoded(|d| + hash.as_mut().copy_from_slice(blake2b(32, &[], d).as_bytes()) + ); + let _ = self.0.write().remove(&hash); + } + + fn lookup(&self, hash: &H) -> Option> { + self.0.read().get(hash) + } + + fn with_lookup(&self, hash: &H, f: &mut dyn FnMut(&[u8])) { + let _ = self.0.read().get_ref(hash).map(|d| f(d.as_ref())); + } + + fn store(&self, hash: &H, preimage: &[u8]) { + self.0.write().insert(preimage, hash); + } + + fn release(&self, hash: &H) { + let _ = self.0.write().remove(hash); + } +} diff --git a/client/db/src/upgrade.rs b/client/db/src/upgrade.rs index 971acf8456b6463fe315768f16e2f8cf3af8254b..95592d071f777db07cf15e8e2765225f0756bfb2 100644 --- a/client/db/src/upgrade.rs +++ b/client/db/src/upgrade.rs @@ -19,18 +19,9 @@ use std::fs; use std::io::{Read, Write, ErrorKind}; use std::path::{Path, PathBuf}; -use std::sync::Arc; -use codec::Encode; -use kvdb_rocksdb::{Database, DatabaseConfig}; -use parking_lot::RwLock; -use sp_blockchain::{well_known_cache_keys, Cache}; -use sp_core::ChangesTrieConfiguration; use sp_runtime::traits::Block as BlockT; -use crate::{ - cache::{ComplexBlockId, DbCache, DbCacheSync}, - utils::{DatabaseType, check_database_type, db_err, read_genesis_hash}, -}; +use crate::utils::DatabaseType; /// Version file name. const VERSION_FILE_NAME: &'static str = "db_version"; @@ -38,69 +29,21 @@ const VERSION_FILE_NAME: &'static str = "db_version"; /// Current db version. const CURRENT_VERSION: u32 = 1; -/// Number of columns in v0. -const V0_NUM_COLUMNS: u32 = 10; - /// Upgrade database to current version. -pub fn upgrade_db(db_path: &Path, db_type: DatabaseType) -> sp_blockchain::Result<()> { - let db_version = current_version(db_path)?; - match db_version { - 0 => migrate_0_to_1::(db_path, db_type)?, - 1 => (), - _ => Err(sp_blockchain::Error::Backend(format!("Future database version: {}", db_version)))?, +pub fn upgrade_db(db_path: &Path, _db_type: DatabaseType) -> sp_blockchain::Result<()> { + let is_empty = db_path.read_dir().map_or(true, |mut d| d.next().is_none()); + if !is_empty { + let db_version = current_version(db_path)?; + match db_version { + 0 => Err(sp_blockchain::Error::Backend(format!("Unsupported database version: {}", db_version)))?, + 1 => (), + _ => Err(sp_blockchain::Error::Backend(format!("Future database version: {}", db_version)))?, + } } update_version(db_path) } -/// Migration from version0 to version1: -/// 1) the number of columns has changed from 10 to 11; -/// 2) changes tries configuration are now cached. -fn migrate_0_to_1(db_path: &Path, db_type: DatabaseType) -> sp_blockchain::Result<()> { - { - let db = open_database(db_path, db_type, V0_NUM_COLUMNS)?; - db.add_column().map_err(db_err)?; - db.flush().map_err(db_err)?; - } - - let db = open_database(db_path, db_type, V0_NUM_COLUMNS + 1)?; - - const V0_FULL_KEY_LOOKUP_COLUMN: u32 = 3; - const V0_FULL_HEADER_COLUMN: u32 = 4; - const V0_FULL_CACHE_COLUMN: u32 = 10; // that's the column we have just added - const V0_LIGHT_KEY_LOOKUP_COLUMN: u32 = 1; - const V0_LIGHT_HEADER_COLUMN: u32 = 2; - const V0_LIGHT_CACHE_COLUMN: u32 = 3; - - let (key_lookup_column, header_column, cache_column) = match db_type { - DatabaseType::Full => ( - V0_FULL_KEY_LOOKUP_COLUMN, - V0_FULL_HEADER_COLUMN, - V0_FULL_CACHE_COLUMN, - ), - DatabaseType::Light => ( - V0_LIGHT_KEY_LOOKUP_COLUMN, - V0_LIGHT_HEADER_COLUMN, - V0_LIGHT_CACHE_COLUMN, - ), - }; - - let genesis_hash: Option = read_genesis_hash(&db)?; - if let Some(genesis_hash) = genesis_hash { - let cache: DbCacheSync = DbCacheSync(RwLock::new(DbCache::new( - Arc::new(db), - key_lookup_column, - header_column, - cache_column, - genesis_hash, - ComplexBlockId::new(genesis_hash, 0.into()), - ))); - let changes_trie_config: Option = None; - cache.initialize(&well_known_cache_keys::CHANGES_TRIE_CONFIG, changes_trie_config.encode())?; - } - - Ok(()) -} /// Reads current database version from the file at given path. /// If the file does not exist returns 0. @@ -118,14 +61,9 @@ fn current_version(path: &Path) -> sp_blockchain::Result { } } -/// Opens database of given type with given number of columns. -fn open_database(db_path: &Path, db_type: DatabaseType, db_columns: u32) -> sp_blockchain::Result { - let db_path = db_path.to_str() - .ok_or_else(|| sp_blockchain::Error::Backend("Invalid database path".into()))?; - let db_cfg = DatabaseConfig::with_columns(db_columns); - let db = Database::open(&db_cfg, db_path).map_err(db_err)?; - check_database_type(&db, db_type)?; - Ok(db) +/// Maps database error to client error +fn db_err(err: std::io::Error) -> sp_blockchain::Error { + sp_blockchain::Error::Backend(format!("{}", err)) } /// Writes current database version to the file. @@ -152,8 +90,6 @@ mod tests { use super::*; fn create_db(db_path: &Path, version: Option) { - let db_cfg = DatabaseConfig::with_columns(V0_NUM_COLUMNS); - Database::open(&db_cfg, db_path.to_str().unwrap()).unwrap(); if let Some(version) = version { fs::create_dir_all(db_path).unwrap(); let mut file = fs::File::create(version_file_path(db_path)).unwrap(); @@ -166,7 +102,7 @@ mod tests { state_cache_size: 0, state_cache_child_ratio: None, pruning: PruningMode::ArchiveAll, - source: DatabaseSettingsSrc::Path { path: db_path.to_owned(), cache_size: None }, + source: DatabaseSettingsSrc::RocksDb { path: db_path.to_owned(), cache_size: 128 }, }, DatabaseType::Full).map(|_| ()) } @@ -184,15 +120,4 @@ mod tests { open_database(db_dir.path()).unwrap(); assert_eq!(current_version(db_dir.path()).unwrap(), CURRENT_VERSION); } - - #[test] - fn upgrade_from_0_to_1_works() { - for version_from_file in &[None, Some(0)] { - let db_dir = tempfile::TempDir::new().unwrap(); - let db_path = db_dir.path(); - create_db(db_path, *version_from_file); - open_database(db_path).unwrap(); - assert_eq!(current_version(db_path).unwrap(), CURRENT_VERSION); - } - } } diff --git a/client/db/src/utils.rs b/client/db/src/utils.rs index f26714eb5a7dbf9edae0fcac6a850e877478fd0e..c25b978be0fc154d5635feee4940339dc5bf5177 100644 --- a/client/db/src/utils.rs +++ b/client/db/src/utils.rs @@ -1,42 +1,42 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Db-based backend utility structures and functions, used by both //! full and light storages. use std::sync::Arc; -use std::{io, convert::TryInto}; +use std::convert::TryInto; -use kvdb::{KeyValueDB, DBTransaction}; -#[cfg(any(feature = "kvdb-rocksdb", test))] -use kvdb_rocksdb::{Database, DatabaseConfig}; use log::debug; use codec::Decode; use sp_trie::DBValue; +use sp_database::Transaction; use sp_runtime::generic::BlockId; use sp_runtime::traits::{ Block as BlockT, Header as HeaderT, Zero, UniqueSaturatedFrom, UniqueSaturatedInto, }; -use crate::{DatabaseSettings, DatabaseSettingsSrc}; +use crate::{DatabaseSettings, DatabaseSettingsSrc, Database, DbHash}; /// 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. -#[cfg(any(feature = "kvdb-rocksdb", feature = "test-helpers", test))] +#[cfg(any(feature = "with-kvdb-rocksdb", feature = "with-parity-db", feature = "test-helpers", test))] pub const NUM_COLUMNS: u32 = 11; /// Meta column. The set of keys in the column is shared by full && light storages. pub const COLUMN_META: u32 = 0; @@ -136,35 +136,35 @@ pub fn lookup_key_to_number(key: &[u8]) -> sp_blockchain::Result where /// Delete number to hash mapping in DB transaction. pub fn remove_number_to_key_mapping>( - transaction: &mut DBTransaction, + transaction: &mut Transaction, key_lookup_col: u32, number: N, ) -> sp_blockchain::Result<()> { - transaction.delete(key_lookup_col, number_index_key(number)?.as_ref()); + transaction.remove(key_lookup_col, number_index_key(number)?.as_ref()); Ok(()) } /// Remove key mappings. pub fn remove_key_mappings, H: AsRef<[u8]>>( - transaction: &mut DBTransaction, + transaction: &mut Transaction, key_lookup_col: u32, number: N, hash: H, ) -> sp_blockchain::Result<()> { remove_number_to_key_mapping(transaction, key_lookup_col, number)?; - transaction.delete(key_lookup_col, hash.as_ref()); + transaction.remove(key_lookup_col, hash.as_ref()); Ok(()) } /// Place a number mapping into the database. This maps number to current perceived /// block hash at that position. pub fn insert_number_to_key_mapping + Clone, H: AsRef<[u8]>>( - transaction: &mut DBTransaction, + transaction: &mut Transaction, key_lookup_col: u32, number: N, hash: H, ) -> sp_blockchain::Result<()> { - transaction.put_vec( + transaction.set_from_vec( key_lookup_col, number_index_key(number.clone())?.as_ref(), number_and_hash_to_lookup_key(number, hash)?, @@ -174,12 +174,12 @@ pub fn insert_number_to_key_mapping + Clone, H: AsRef<[u8]>>( /// Insert a hash to key mapping in the database. pub fn insert_hash_to_key_mapping, H: AsRef<[u8]> + Clone>( - transaction: &mut DBTransaction, + transaction: &mut Transaction, key_lookup_col: u32, number: N, hash: H, ) -> sp_blockchain::Result<()> { - transaction.put_vec( + transaction.set_from_vec( key_lookup_col, hash.clone().as_ref(), number_and_hash_to_lookup_key(number, hash)?, @@ -191,66 +191,91 @@ pub fn insert_hash_to_key_mapping, H: AsRef<[u8]> + Clone>( /// block lookup key is the DB-key header, block and justification are stored under. /// looks up lookup key by hash from DB as necessary. pub fn block_id_to_lookup_key( - db: &dyn KeyValueDB, + db: &dyn Database, key_lookup_col: u32, id: BlockId ) -> Result>, sp_blockchain::Error> where Block: BlockT, ::sp_runtime::traits::NumberFor: UniqueSaturatedFrom + UniqueSaturatedInto, { - let res = match id { + Ok(match id { BlockId::Number(n) => db.get( key_lookup_col, number_index_key(n)?.as_ref(), ), - BlockId::Hash(h) => db.get(key_lookup_col, h.as_ref()), - }; - - res.map_err(db_err) -} - -/// Maps database error to client error -pub fn db_err(err: io::Error) -> sp_blockchain::Error { - sp_blockchain::Error::Backend(format!("{}", err)) + BlockId::Hash(h) => db.get(key_lookup_col, h.as_ref()) + }) } -/// Open RocksDB database. +/// Opens the configured database. pub fn open_database( config: &DatabaseSettings, db_type: DatabaseType, -) -> sp_blockchain::Result> { - let db: Arc = match &config.source { - #[cfg(any(feature = "kvdb-rocksdb", test))] - DatabaseSettingsSrc::Path { path, cache_size } => { +) -> sp_blockchain::Result>> { + let db_open_error = |feat| Err( + sp_blockchain::Error::Backend( + format!("`{}` feature not enabled, database can not be opened", feat), + ), + ); + + let db: Arc> = match &config.source { + #[cfg(any(feature = "with-kvdb-rocksdb", test))] + DatabaseSettingsSrc::RocksDb { path, cache_size } => { // first upgrade database to required version crate::upgrade::upgrade_db::(&path, db_type)?; // and now open database assuming that it has the latest version - let mut db_config = DatabaseConfig::with_columns(NUM_COLUMNS); - - if let Some(cache_size) = cache_size { - let state_col_budget = (*cache_size as f64 * 0.9) as usize; - let other_col_budget = (cache_size - state_col_budget) / (NUM_COLUMNS as usize - 1); - - let mut memory_budget = std::collections::HashMap::new(); - for i in 0..NUM_COLUMNS { - if i == crate::columns::STATE { - memory_budget.insert(i, state_col_budget); - } else { - memory_budget.insert(i, other_col_budget); - } - } - - db_config.memory_budget = memory_budget; - } + let mut db_config = kvdb_rocksdb::DatabaseConfig::with_columns(NUM_COLUMNS); + let state_col_budget = (*cache_size as f64 * 0.9) as usize; + let other_col_budget = (cache_size - state_col_budget) / (NUM_COLUMNS as usize - 1); + let mut memory_budget = std::collections::HashMap::new(); let path = path.to_str() .ok_or_else(|| sp_blockchain::Error::Backend("Invalid database path".into()))?; - Arc::new(Database::open(&db_config, &path).map_err(db_err)?) + + for i in 0..NUM_COLUMNS { + if i == crate::columns::STATE { + memory_budget.insert(i, state_col_budget); + } else { + memory_budget.insert(i, other_col_budget); + } + } + + db_config.memory_budget = memory_budget; + + log::trace!( + target: "db", + "Open RocksDB database at {}, state column budget: {} MiB, others({}) column cache: {} MiB", + path, + state_col_budget, + NUM_COLUMNS, + other_col_budget, + ); + + let db = kvdb_rocksdb::Database::open(&db_config, &path) + .map_err(|err| sp_blockchain::Error::Backend(format!("{}", err)))?; + sp_database::as_database(db) }, - #[cfg(not(any(feature = "kvdb-rocksdb", test)))] - DatabaseSettingsSrc::Path { .. } => { - let msg = "Try to open RocksDB database with RocksDB disabled".into(); - return Err(sp_blockchain::Error::Backend(msg)); + #[cfg(not(any(feature = "with-kvdb-rocksdb", test)))] + DatabaseSettingsSrc::RocksDb { .. } => { + return db_open_error("with-kvdb-rocksdb"); + }, + #[cfg(feature = "with-subdb")] + DatabaseSettingsSrc::SubDb { path } => { + crate::subdb::open(&path, NUM_COLUMNS) + .map_err(|e| sp_blockchain::Error::Backend(format!("{:?}", e)))? + }, + #[cfg(not(feature = "with-subdb"))] + DatabaseSettingsSrc::SubDb { .. } => { + return db_open_error("with-subdb"); + }, + #[cfg(feature = "with-parity-db")] + DatabaseSettingsSrc::ParityDb { path } => { + crate::parity_db::open(&path) + .map_err(|e| sp_blockchain::Error::Backend(format!("{:?}", e)))? + }, + #[cfg(not(feature = "with-parity-db"))] + DatabaseSettingsSrc::ParityDb { .. } => { + return db_open_error("with-parity-db"); }, DatabaseSettingsSrc::Custom(db) => db.clone(), }; @@ -261,8 +286,8 @@ pub fn open_database( } /// Check database type. -pub fn check_database_type(db: &dyn KeyValueDB, db_type: DatabaseType) -> sp_blockchain::Result<()> { - match db.get(COLUMN_META, meta_keys::TYPE).map_err(db_err)? { +pub fn check_database_type(db: &dyn Database, db_type: DatabaseType) -> sp_blockchain::Result<()> { + match db.get(COLUMN_META, meta_keys::TYPE) { Some(stored_type) => { if db_type.as_str().as_bytes() != &*stored_type { return Err(sp_blockchain::Error::Backend( @@ -270,9 +295,9 @@ pub fn check_database_type(db: &dyn KeyValueDB, db_type: DatabaseType) -> sp_blo } }, None => { - let mut transaction = DBTransaction::new(); - transaction.put(COLUMN_META, meta_keys::TYPE, db_type.as_str().as_bytes()); - db.write(transaction).map_err(db_err)?; + let mut transaction = Transaction::new(); + transaction.set(COLUMN_META, meta_keys::TYPE, db_type.as_str().as_bytes()); + db.commit(transaction)?; }, } @@ -281,7 +306,7 @@ pub fn check_database_type(db: &dyn KeyValueDB, db_type: DatabaseType) -> sp_blo /// Read database column entry for the given block. pub fn read_db( - db: &dyn KeyValueDB, + db: &dyn Database, col_index: u32, col: u32, id: BlockId @@ -290,14 +315,14 @@ pub fn read_db( Block: BlockT, { block_id_to_lookup_key(db, col_index, id).and_then(|key| match key { - Some(key) => db.get(col, key.as_ref()).map_err(db_err), + Some(key) => Ok(db.get(col, key.as_ref())), None => Ok(None), }) } /// Read a header from the database. pub fn read_header( - db: &dyn KeyValueDB, + db: &dyn Database, col_index: u32, col: u32, id: BlockId, @@ -315,7 +340,7 @@ pub fn read_header( /// Required header from the database. pub fn require_header( - db: &dyn KeyValueDB, + db: &dyn Database, col_index: u32, col: u32, id: BlockId, @@ -327,7 +352,7 @@ pub fn require_header( } /// Read meta from the database. -pub fn read_meta(db: &dyn KeyValueDB, col_header: u32) -> Result< +pub fn read_meta(db: &dyn Database, col_header: u32) -> Result< Meta<<::Header as HeaderT>::Number, Block::Hash>, sp_blockchain::Error, > @@ -346,11 +371,10 @@ pub fn read_meta(db: &dyn KeyValueDB, col_header: u32) -> Result< }; let load_meta_block = |desc, key| -> Result<_, sp_blockchain::Error> { - if let Some(Some(header)) = db.get(COLUMN_META, key).and_then(|id| - match id { - Some(id) => db.get(col_header, &id).map(|h| h.map(|b| Block::Header::decode(&mut &b[..]).ok())), - None => Ok(None), - }).map_err(db_err)? + if let Some(Some(header)) = match db.get(COLUMN_META, key) { + Some(id) => db.get(col_header, &id).map(|b| Block::Header::decode(&mut &b[..]).ok()), + None => None, + } { let hash = header.hash(); debug!("DB Opened blockchain db, fetched {} = {:?} ({})", desc, hash, header.number()); @@ -373,8 +397,8 @@ pub fn read_meta(db: &dyn KeyValueDB, col_header: u32) -> Result< } /// Read genesis hash from database. -pub fn read_genesis_hash(db: &dyn KeyValueDB) -> sp_blockchain::Result> { - match db.get(COLUMN_META, meta_keys::GENESIS_HASH).map_err(db_err)? { +pub fn read_genesis_hash(db: &dyn Database) -> sp_blockchain::Result> { + match db.get(COLUMN_META, meta_keys::GENESIS_HASH) { Some(h) => match Decode::decode(&mut &h[..]) { Ok(h) => Ok(Some(h)), Err(err) => Err(sp_blockchain::Error::Backend( diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index cae0d56d8ed5eea8fef0e77c92eec6c2d5d9a61b..b12156aeb19844802728bf08c31c39857715cc6e 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -1,32 +1,36 @@ [package] name = "sc-executor" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "A crate that provides means of executing/dispatching calls into the runtime." documentation = "https://docs.rs/sc-executor" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] derive_more = "0.99.2" -codec = { package = "parity-scale-codec", version = "1.3.0" } -sp-io = { version = "2.0.0-alpha.5", path = "../../primitives/io" } -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -sp-trie = { version = "2.0.0-alpha.5", path = "../../primitives/trie" } -sp-serializer = { version = "2.0.0-alpha.5", path = "../../primitives/serializer" } -sp-version = { version = "2.0.0-alpha.5", path = "../../primitives/version" } -sp-panic-handler = { version = "2.0.0-alpha.5", path = "../../primitives/panic-handler" } +codec = { package = "parity-scale-codec", version = "1.3.1" } +sp-io = { version = "2.0.0-rc4", path = "../../primitives/io" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +sp-trie = { version = "2.0.0-rc4", path = "../../primitives/trie" } +sp-serializer = { version = "2.0.0-rc4", path = "../../primitives/serializer" } +sp-version = { version = "2.0.0-rc4", path = "../../primitives/version" } +sp-panic-handler = { version = "2.0.0-rc4", path = "../../primitives/panic-handler" } wasmi = "0.6.2" parity-wasm = "0.41.0" lazy_static = "1.4.0" -sp-wasm-interface = { version = "2.0.0-alpha.5", path = "../../primitives/wasm-interface" } -sp-runtime-interface = { version = "2.0.0-alpha.5", path = "../../primitives/runtime-interface" } -sp-externalities = { version = "0.8.0-alpha.5", path = "../../primitives/externalities" } -sc-executor-common = { version = "0.8.0-alpha.5", path = "common" } -sc-executor-wasmi = { version = "0.8.0-alpha.5", path = "wasmi" } -sc-executor-wasmtime = { version = "0.8.0-alpha.5", path = "wasmtime", optional = true } +sp-api = { version = "2.0.0-rc4", path = "../../primitives/api" } +sp-wasm-interface = { version = "2.0.0-rc4", path = "../../primitives/wasm-interface" } +sp-runtime-interface = { version = "2.0.0-rc4", path = "../../primitives/runtime-interface" } +sp-externalities = { version = "0.8.0-rc4", path = "../../primitives/externalities" } +sc-executor-common = { version = "0.8.0-rc4", path = "common" } +sc-executor-wasmi = { version = "0.8.0-rc4", path = "wasmi" } +sc-executor-wasmtime = { version = "0.8.0-rc4", path = "wasmtime", optional = true } parking_lot = "0.10.0" log = "0.4.8" libsecp256k1 = "0.3.4" @@ -35,11 +39,14 @@ libsecp256k1 = "0.3.4" assert_matches = "1.3.0" wabt = "0.9.2" hex-literal = "0.2.1" -sc-runtime-test = { version = "2.0.0-dev", path = "runtime-test" } -substrate-test-runtime = { version = "2.0.0-dev", path = "../../test-utils/runtime" } -sp-state-machine = { version = "0.8.0-alpha.5", path = "../../primitives/state-machine" } +sc-runtime-test = { version = "2.0.0-rc4", path = "runtime-test" } +substrate-test-runtime = { version = "2.0.0-rc4", path = "../../test-utils/runtime" } +sp-state-machine = { version = "0.8.0-rc4", path = "../../primitives/state-machine" } test-case = "0.3.3" -sp-runtime = { version = "2.0.0-alpha.5", path = "../../primitives/runtime" } +sp-runtime = { version = "2.0.0-rc4", path = "../../primitives/runtime" } +sp-tracing = { version = "2.0.0-rc4", path = "../../primitives/tracing" } +sc-tracing = { version = "2.0.0-rc4", path = "../tracing" } +tracing = "0.1.14" [features] default = [ "std" ] @@ -52,6 +59,3 @@ wasmtime = [ wasmi-errno = [ "wasmi/errno" ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/client/executor/common/Cargo.toml b/client/executor/common/Cargo.toml index 1f52b959d00b1fc72d56b112267a4d70eb0d1b90..970fc2ded34d390b2b60ec1d9571d0aa794933f5 100644 --- a/client/executor/common/Cargo.toml +++ b/client/executor/common/Cargo.toml @@ -1,27 +1,28 @@ [package] name = "sc-executor-common" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "A set of common definitions that are needed for defining execution engines." documentation = "https://docs.rs/sc-executor-common/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] log = "0.4.8" derive_more = "0.99.2" -codec = { package = "parity-scale-codec", version = "1.3.0" } +parity-wasm = "0.41.0" +codec = { package = "parity-scale-codec", version = "1.3.1" } wasmi = "0.6.2" -sp-core = { version = "2.0.0-alpha.5", path = "../../../primitives/core" } -sp-allocator = { version = "2.0.0-alpha.5", path = "../../../primitives/allocator" } -sp-wasm-interface = { version = "2.0.0-alpha.5", path = "../../../primitives/wasm-interface" } -sp-runtime-interface = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime-interface" } -sp-serializer = { version = "2.0.0-alpha.5", path = "../../../primitives/serializer" } +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } +sp-allocator = { version = "2.0.0-rc4", path = "../../../primitives/allocator" } +sp-wasm-interface = { version = "2.0.0-rc4", path = "../../../primitives/wasm-interface" } +sp-runtime-interface = { version = "2.0.0-rc4", path = "../../../primitives/runtime-interface" } +sp-serializer = { version = "2.0.0-rc4", path = "../../../primitives/serializer" } [features] default = [] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/client/executor/common/src/error.rs b/client/executor/common/src/error.rs index 66d520e942411d01c540bd64f7bde4147be28c74..04850e6f8dd7e34b1b438ec1a4c58f6ed026eb5b 100644 --- a/client/executor/common/src/error.rs +++ b/client/executor/common/src/error.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Rust executor possible errors. diff --git a/client/executor/common/src/lib.rs b/client/executor/common/src/lib.rs index cc515dcf9dab9a8f852f2d9b2dc1f3e2af40773f..7f3864e6152fb2a00122bc6e6c2d2e9c2a4102e8 100644 --- a/client/executor/common/src/lib.rs +++ b/client/executor/common/src/lib.rs @@ -18,6 +18,7 @@ #![warn(missing_docs)] -pub mod sandbox; pub mod error; +pub mod sandbox; +pub mod util; pub mod wasm_runtime; diff --git a/client/executor/common/src/sandbox.rs b/client/executor/common/src/sandbox.rs index ccfdc2f3e0e28c2e8b6a1b1734ee8be450b088ff..b2c35b758271829c8771034da08aee46c52dd3db 100644 --- a/client/executor/common/src/sandbox.rs +++ b/client/executor/common/src/sandbox.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! This module implements sandboxing support in the runtime. //! @@ -236,21 +238,33 @@ impl<'a, FE: SandboxCapabilities + 'a> Externals for GuestExternals<'a, FE> { .supervisor_externals .allocate_memory(invoke_args_len) .map_err(|_| trap("Can't allocate memory in supervisor for the arguments"))?; - self + + let deallocate = |this: &mut GuestExternals, ptr, fail_msg| { + this + .supervisor_externals + .deallocate_memory(ptr) + .map_err(|_| trap(fail_msg)) + }; + + if self .supervisor_externals .write_memory(invoke_args_ptr, &invoke_args_data) - .map_err(|_| trap("Can't write invoke args into memory"))?; + .is_err() + { + deallocate(self, invoke_args_ptr, "Failed dealloction after failed write of invoke arguments")?; + return Err(trap("Can't write invoke args into memory")); + } + let result = self.supervisor_externals.invoke( &self.sandbox_instance.dispatch_thunk, invoke_args_ptr, invoke_args_len, state, func_idx, - )?; - self - .supervisor_externals - .deallocate_memory(invoke_args_ptr) - .map_err(|_| trap("Can't deallocate memory for dispatch thunk's invoke arguments"))?; + ); + + deallocate(self, invoke_args_ptr, "Can't deallocate memory for dispatch thunk's invoke arguments")?; + let result = result?; // dispatch_thunk returns pointer to serialized arguments. // Unpack pointer and len of the serialized result data. @@ -264,12 +278,11 @@ impl<'a, FE: SandboxCapabilities + 'a> Externals for GuestExternals<'a, FE> { let serialized_result_val = self.supervisor_externals .read_memory(serialized_result_val_ptr, serialized_result_val_len) - .map_err(|_| trap("Can't read the serialized result from dispatch thunk"))?; - self.supervisor_externals - .deallocate_memory(serialized_result_val_ptr) - .map_err(|_| trap("Can't deallocate memory for dispatch thunk's result"))?; + .map_err(|_| trap("Can't read the serialized result from dispatch thunk")); - deserialize_result(&serialized_result_val) + deallocate(self, serialized_result_val_ptr, "Can't deallocate memory for dispatch thunk's result") + .and_then(|_| serialized_result_val) + .and_then(|serialized_result_val| deserialize_result(&serialized_result_val)) } } diff --git a/client/executor/common/src/util.rs b/client/executor/common/src/util.rs new file mode 100644 index 0000000000000000000000000000000000000000..92a48e14018143944dae245abddb1db481ce4021 --- /dev/null +++ b/client/executor/common/src/util.rs @@ -0,0 +1,140 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! A set of utilities for resetting a wasm instance to its initial state. + +use crate::error::{self, Error}; +use std::mem; +use parity_wasm::elements::{deserialize_buffer, DataSegment, Instruction, Module as RawModule}; + +/// A bunch of information collected from a WebAssembly module. +pub struct WasmModuleInfo { + raw_module: RawModule, +} + +impl WasmModuleInfo { + /// Create `WasmModuleInfo` from the given wasm code. + /// + /// Returns `None` if the wasm code cannot be deserialized. + pub fn new(wasm_code: &[u8]) -> Option { + let raw_module: RawModule = deserialize_buffer(wasm_code).ok()?; + Some(Self { raw_module }) + } + + /// Extract the data segments from the given wasm code. + /// + /// Returns `Err` if the given wasm code cannot be deserialized. + fn data_segments(&self) -> Vec { + self.raw_module + .data_section() + .map(|ds| ds.entries()) + .unwrap_or(&[]) + .to_vec() + } + + /// The number of globals defined in locally in this module. + pub fn declared_globals_count(&self) -> u32 { + self.raw_module + .global_section() + .map(|gs| gs.entries().len() as u32) + .unwrap_or(0) + } + + /// The number of imports of globals. + pub fn imported_globals_count(&self) -> u32 { + self.raw_module + .import_section() + .map(|is| is.globals() as u32) + .unwrap_or(0) + } +} + +/// This is a snapshot of data segments specialzied for a particular instantiation. +/// +/// Note that this assumes that no mutable globals are used. +#[derive(Clone)] +pub struct DataSegmentsSnapshot { + /// The list of data segments represented by (offset, contents). + data_segments: Vec<(u32, Vec)>, +} + +impl DataSegmentsSnapshot { + /// Create a snapshot from the data segments from the module. + pub fn take(module: &WasmModuleInfo) -> error::Result { + let data_segments = module + .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 Err(Error::from("Shared memory is not supported".to_string())), + }; + + // [op, End] + if init_expr.len() != 2 { + return Err(Error::from( + "initializer expression can have only up to 2 expressions in wasm 1.0" + .to_string(), + )); + } + let offset = match &init_expr[0] { + Instruction::I32Const(v) => *v as u32, + Instruction::GetGlobal(_) => { + // In a valid wasm file, initializer expressions can only refer imported + // globals. + // + // At the moment of writing the Substrate Runtime Interface does not provide + // any globals. There is nothing that prevents us from supporting this + // if/when we gain those. + return Err(Error::from( + "Imported globals are not supported yet".to_string(), + )); + } + insn => { + return Err(Error::from(format!( + "{:?} is not supported as initializer expression in wasm 1.0", + insn + ))) + } + }; + + Ok((offset, contents)) + }) + .collect::>>()?; + + Ok(Self { data_segments }) + } + + /// Apply the given snapshot to a linear memory. + /// + /// Linear memory interface is represented by a closure `memory_set`. + pub fn apply( + &self, + mut memory_set: impl FnMut(u32, &[u8]) -> Result<(), E>, + ) -> Result<(), E> { + for (offset, contents) in &self.data_segments { + memory_set(*offset, contents)?; + } + Ok(()) + } +} diff --git a/client/executor/runtime-test/Cargo.toml b/client/executor/runtime-test/Cargo.toml index e50061f4f24bb71639a5204cf326d6be7d397e6f..c01a9428f4fce7265e960ed9a725b4fea12d1539 100644 --- a/client/executor/runtime-test/Cargo.toml +++ b/client/executor/runtime-test/Cargo.toml @@ -1,21 +1,24 @@ [package] name = "sc-runtime-test" -version = "2.0.0-dev" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" build = "build.rs" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" publish = false homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/std" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/io" } -sp-sandbox = { version = "0.8.0-alpha.5", default-features = false, path = "../../../primitives/sandbox" } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/core" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/runtime" } -sp-allocator = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/allocator" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/std" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/io" } +sp-sandbox = { version = "0.8.0-rc4", default-features = false, path = "../../../primitives/sandbox" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/core" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/runtime" } +sp-allocator = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/allocator" } [build-dependencies] wasm-builder-runner = { version = "1.0.5", package = "substrate-wasm-builder-runner", path = "../../../utils/wasm-builder-runner" } @@ -28,6 +31,3 @@ std = [ "sp-std/std", "sp-allocator/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/client/executor/runtime-test/build.rs b/client/executor/runtime-test/build.rs index 647b4768141d2203155bf5325f9ff87f7d9c2446..c5f1f2402bd8b21d278c888044b94362c181672e 100644 --- a/client/executor/runtime-test/build.rs +++ b/client/executor/runtime-test/build.rs @@ -19,7 +19,7 @@ use wasm_builder_runner::WasmBuilder; fn main() { WasmBuilder::new() .with_current_project() - .with_wasm_builder_from_crates_or_path("1.0.9", "../../../utils/wasm-builder") + .with_wasm_builder_from_crates_or_path("1.0.11", "../../../utils/wasm-builder") .export_heap_base() .import_memory() .build() diff --git a/client/executor/runtime-test/src/lib.rs b/client/executor/runtime-test/src/lib.rs index 38a16ae39ea012806d12d90f1a920e622eec4ad0..4962c558eaa2dc7add290ad6d495e6ec061fb9f8 100644 --- a/client/executor/runtime-test/src/lib.rs +++ b/client/executor/runtime-test/src/lib.rs @@ -1,5 +1,4 @@ #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(feature = "strict", deny(warnings))] // Make the WASM binary available. #[cfg(feature = "std")] @@ -11,7 +10,7 @@ use sp_std::{vec::Vec, vec}; #[cfg(not(feature = "std"))] use sp_io::{ storage, hashing::{blake2_128, blake2_256, sha2_256, twox_128, twox_256}, - crypto::{ed25519_verify, sr25519_verify}, + crypto::{ed25519_verify, sr25519_verify}, wasm_tracing, }; #[cfg(not(feature = "std"))] use sp_runtime::{print, traits::{BlakeTwo256, Hash}}; @@ -183,6 +182,12 @@ sp_core::wasm_export_functions! { } } + + fn test_offchain_index_set() { + sp_io::offchain_index::set(b"k", b"v"); + } + + fn test_offchain_local_storage() -> bool { let kind = sp_core::offchain::StorageKind::PERSISTENT; assert_eq!(sp_io::offchain::local_storage_get(kind, b"test"), None); @@ -241,6 +246,14 @@ sp_core::wasm_export_functions! { sp_allocator::FreeingBumpHeapAllocator::new(0); } + fn test_enter_span() -> u64 { + wasm_tracing::enter_span("integration_test_span_target", "integration_test_span_name") + } + + fn test_exit_span(span_id: u64) { + wasm_tracing::exit_span(span_id) + } + fn returns_mutable_static() -> u64 { unsafe { MUTABLE_STATIC += 1; diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index 72055b77884a651d3b6c3d9dd951b206033e5885..21924270b8c1e00779db07b4f7b44a6766c1904e 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -1,19 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . - +// along with this program. If not, see . mod sandbox; use codec::{Encode, Decode}; @@ -45,7 +46,6 @@ fn call_in_wasm( execution_method, Some(1024), HostFunctions::host_functions(), - true, 8, ); executor.call_in_wasm( @@ -54,6 +54,7 @@ fn call_in_wasm( function, call_data, ext, + sp_core::traits::MissingHostFunctions::Allow, ) } @@ -92,9 +93,8 @@ fn call_not_existing_function(wasm_method: WasmExecutionMethod) { "\"Trap: Trap { kind: Host(Other(\\\"Function `missing_external` is only a stub. Calling a stub is not allowed.\\\")) }\"" ), #[cfg(feature = "wasmtime")] - WasmExecutionMethod::Compiled => assert_eq!( - &format!("{:?}", e), - "\"Wasm execution trapped: call to a missing function env:missing_external\"" + WasmExecutionMethod::Compiled => assert!( + format!("{:?}", e).contains("Wasm execution trapped: call to a missing function env:missing_external") ), } } @@ -121,9 +121,8 @@ fn call_yet_another_not_existing_function(wasm_method: WasmExecutionMethod) { "\"Trap: Trap { kind: Host(Other(\\\"Function `yet_another_missing_external` is only a stub. Calling a stub is not allowed.\\\")) }\"" ), #[cfg(feature = "wasmtime")] - WasmExecutionMethod::Compiled => assert_eq!( - &format!("{:?}", e), - "\"Wasm execution trapped: call to a missing function env:yet_another_missing_external\"" + WasmExecutionMethod::Compiled => assert!( + format!("{:?}", e).contains("Wasm execution trapped: call to a missing function env:yet_another_missing_external") ), } } @@ -186,7 +185,7 @@ fn storage_should_work(wasm_method: WasmExecutionMethod) { b"foo".to_vec() => b"bar".to_vec(), b"baz".to_vec() => b"bar".to_vec() ], - children: map![], + children_default: map![], }); assert_eq!(ext, expected); } @@ -220,7 +219,7 @@ fn clear_prefix_should_work(wasm_method: WasmExecutionMethod) { b"aab".to_vec() => b"2".to_vec(), b"bbb".to_vec() => b"5".to_vec() ], - children: map![], + children_default: map![], }); assert_eq!(expected, ext); } @@ -450,6 +449,28 @@ fn ordered_trie_root_should_work(wasm_method: WasmExecutionMethod) { ); } +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn offchain_index(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let (offchain, _state) = testing::TestOffchainExt::new(); + ext.register_extension(OffchainExt::new(offchain)); + call_in_wasm( + "test_offchain_index_set", + &[0], + wasm_method, + &mut ext.ext(), + ).unwrap(); + + use sp_core::offchain::storage::OffchainOverlayedChange; + assert_eq!( + ext.ext() + .get_offchain_storage_changes() + .get(sp_core::offchain::STORAGE_PREFIX, b"k"), + Some(OffchainOverlayedChange::SetValue(b"v".to_vec())) + ); +} + #[test_case(WasmExecutionMethod::Interpreted)] #[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] fn offchain_local_storage_should_work(wasm_method: WasmExecutionMethod) { @@ -476,9 +497,7 @@ 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 { + state.write().expect_request(testing::PendingRequest { method: "POST".into(), uri: "http://localhost:12345".into(), body: vec![1, 2, 3, 4], @@ -511,7 +530,6 @@ fn should_trap_when_heap_exhausted(wasm_method: WasmExecutionMethod) { wasm_method, Some(17), // `17` is the initial number of pages compiled into the binary. HostFunctions::host_functions(), - true, 8, ); executor.call_in_wasm( @@ -520,6 +538,7 @@ fn should_trap_when_heap_exhausted(wasm_method: WasmExecutionMethod) { "test_exhaust_heap", &[0], &mut ext.ext(), + sp_core::traits::MissingHostFunctions::Allow, ).unwrap(); } @@ -601,3 +620,138 @@ fn heap_is_reset_between_calls(wasm_method: WasmExecutionMethod) { // Cal it a second time to check that the heap was freed. instance.call("check_and_set_in_heap", ¶ms).unwrap(); } + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn parallel_execution(wasm_method: WasmExecutionMethod) { + let executor = std::sync::Arc::new(crate::WasmExecutor::new( + wasm_method, + Some(1024), + HostFunctions::host_functions(), + 8, + )); + let code_hash = blake2_256(WASM_BINARY).to_vec(); + let threads: Vec<_> = (0..8).map(|_| + { + let executor = executor.clone(); + let code_hash = code_hash.clone(); + std::thread::spawn(move || { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + assert_eq!( + executor.call_in_wasm( + &WASM_BINARY[..], + Some(code_hash.clone()), + "test_twox_128", + &[0], + &mut ext, + sp_core::traits::MissingHostFunctions::Allow, + ).unwrap(), + hex!("99e9d85137db46ef4bbea33613baafd5").to_vec().encode(), + ); + }) + }).collect(); + + for t in threads.into_iter() { + t.join().unwrap(); + } +} + +#[test_case(WasmExecutionMethod::Interpreted)] +fn wasm_tracing_should_work(wasm_method: WasmExecutionMethod) { + + use std::sync::{Arc, Mutex}; + + use sc_tracing::SpanDatum; + + impl sc_tracing::TraceHandler for TestTraceHandler { + fn process_span(&self, sd: SpanDatum) { + self.0.lock().unwrap().push(sd); + } + } + + struct TestTraceHandler(Arc>>); + + let traces = Arc::new(Mutex::new(Vec::new())); + let handler = TestTraceHandler(traces.clone()); + + // Create subscriber with wasm_tracing disabled + let test_subscriber = sc_tracing::ProfilingSubscriber::new_with_handler( + Box::new(handler), "integration_test_span_target"); + + let _guard = tracing::subscriber::set_default(test_subscriber); + + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + + // Test tracing disabled + assert!(!sp_tracing::wasm_tracing_enabled()); + + let span_id = call_in_wasm( + "test_enter_span", + &[], + wasm_method, + &mut ext, + ).unwrap(); + + assert_eq!( + 0u64.encode(), + span_id + ); + // Repeat to check span id always 0 when deactivated + let span_id = call_in_wasm( + "test_enter_span", + &[], + wasm_method, + &mut ext, + ).unwrap(); + + assert_eq!( + 0u64.encode(), + span_id + ); + + call_in_wasm( + "test_exit_span", + &span_id.encode(), + wasm_method, + &mut ext, + ).unwrap(); + // Check span has not been recorded + let len = traces.lock().unwrap().len(); + assert_eq!(len, 0); + + // Test tracing enabled + sp_tracing::set_wasm_tracing(true); + + let span_id = call_in_wasm( + "test_enter_span", + &[], + wasm_method, + &mut ext, + ).unwrap(); + + let span_id = u64::decode(&mut &span_id[..]).unwrap(); + + assert!( + span_id > 0 + ); + + call_in_wasm( + "test_exit_span", + &span_id.encode(), + wasm_method, + &mut ext, + ).unwrap(); + + // Check there is only the single trace + let len = traces.lock().unwrap().len(); + assert_eq!(len, 1); + + let span_datum = traces.lock().unwrap().pop().unwrap(); + let values = span_datum.values.into_inner(); + assert_eq!(span_datum.target, "integration_test_span_target"); + assert_eq!(span_datum.name, "integration_test_span_name"); + assert_eq!(values.get("wasm").unwrap(), "true"); + assert_eq!(values.get("is_valid_trace").unwrap(), "true"); +} diff --git a/client/executor/src/integration_tests/sandbox.rs b/client/executor/src/integration_tests/sandbox.rs index 8e8b7896cf90b5630486fa780af0a3cc94d9b8dd..f84e446b416c06c2f423d71103dbc1597ec85138 100644 --- a/client/executor/src/integration_tests/sandbox.rs +++ b/client/executor/src/integration_tests/sandbox.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use super::{TestExternalities, call_in_wasm}; use crate::WasmExecutionMethod; diff --git a/client/executor/src/lib.rs b/client/executor/src/lib.rs index c3b41bd1990081693110f57d9a1b221a4e3e48f0..c02568c734b699fc0e4e4fb4f96852048a564d5e 100644 --- a/client/executor/src/lib.rs +++ b/client/executor/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! A crate that provides means of executing/dispatching calls into the runtime. //! @@ -77,7 +79,6 @@ mod tests { WasmExecutionMethod::Interpreted, Some(8), sp_io::SubstrateHostFunctions::host_functions(), - true, 8, ); let res = executor.call_in_wasm( @@ -86,6 +87,7 @@ mod tests { "test_empty_return", &[], &mut ext, + sp_core::traits::MissingHostFunctions::Allow, ).unwrap(); assert_eq!(res, vec![0u8; 0]); } diff --git a/client/executor/src/native_executor.rs b/client/executor/src/native_executor.rs index 778bc808004bb2470b528c802bd14c1d0fe1bc51..b1eb504d5a2b3f28fd154d724f265479eafa8f8a 100644 --- a/client/executor/src/native_executor.rs +++ b/client/executor/src/native_executor.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use crate::{ RuntimeInfo, error::{Error, Result}, @@ -20,7 +22,9 @@ use crate::{ }; use sp_version::{NativeVersion, RuntimeVersion}; use codec::{Decode, Encode}; -use sp_core::{NativeOrEncoded, traits::{CodeExecutor, Externalities, RuntimeCode}}; +use sp_core::{ + NativeOrEncoded, traits::{CodeExecutor, Externalities, RuntimeCode, MissingHostFunctions}, +}; use log::trace; use std::{result, panic::{UnwindSafe, AssertUnwindSafe}, sync::Arc}; use sp_wasm_interface::{HostFunctions, Function}; @@ -83,8 +87,6 @@ pub struct WasmExecutor { host_functions: Arc>, /// WASM runtime cache. cache: Arc, - /// Allow missing function imports. - allow_missing_func_imports: bool, /// The size of the instances cache. max_runtime_instances: usize, } @@ -102,7 +104,6 @@ impl WasmExecutor { method: WasmExecutionMethod, default_heap_pages: Option, host_functions: Vec<&'static dyn Function>, - allow_missing_func_imports: bool, max_runtime_instances: usize, ) -> Self { WasmExecutor { @@ -110,7 +111,6 @@ impl WasmExecutor { default_heap_pages: default_heap_pages.unwrap_or(DEFAULT_HEAP_PAGES), host_functions: Arc::new(host_functions), cache: Arc::new(RuntimeCache::new(max_runtime_instances)), - allow_missing_func_imports, max_runtime_instances, } } @@ -132,6 +132,7 @@ impl WasmExecutor { &self, runtime_code: &RuntimeCode, ext: &mut dyn Externalities, + allow_missing_host_functions: bool, f: F, ) -> Result where F: FnOnce( @@ -146,7 +147,7 @@ impl WasmExecutor { self.method, self.default_heap_pages, &*self.host_functions, - self.allow_missing_func_imports, + allow_missing_host_functions, |instance, version, ext| { let instance = AssertUnwindSafe(instance); let ext = AssertUnwindSafe(ext); @@ -167,7 +168,10 @@ impl sp_core::traits::CallInWasm for WasmExecutor { method: &str, call_data: &[u8], ext: &mut dyn Externalities, + missing_host_functions: MissingHostFunctions, ) -> std::result::Result, String> { + let allow_missing_host_functions = missing_host_functions.allowed(); + if let Some(hash) = code_hash { let code = RuntimeCode { code_fetcher: &sp_core::traits::WrappedRuntimeCode(wasm_code.into()), @@ -175,7 +179,7 @@ impl sp_core::traits::CallInWasm for WasmExecutor { heap_pages: None, }; - self.with_instance(&code, ext, |instance, _, mut ext| { + self.with_instance(&code, ext, allow_missing_host_functions, |instance, _, mut ext| { with_externalities_safe( &mut **ext, move || instance.call(method, call_data), @@ -187,7 +191,7 @@ impl sp_core::traits::CallInWasm for WasmExecutor { self.default_heap_pages, &wasm_code, self.host_functions.to_vec(), - self.allow_missing_func_imports, + allow_missing_host_functions, ) .map_err(|e| format!("Failed to create module: {:?}", e))?; @@ -240,7 +244,6 @@ impl NativeExecutor { fallback_method, default_heap_pages, host_functions, - false, max_runtime_instances, ); @@ -265,8 +268,9 @@ impl RuntimeInfo for NativeExecutor { self.wasm.with_instance( runtime_code, ext, + false, |_instance, version, _ext| - Ok(version.cloned().ok_or_else(|| Error::ApiError("Unknown version".into()))) + Ok(version.cloned().ok_or_else(|| Error::ApiError("Unknown version".into()))), ) } } @@ -290,6 +294,7 @@ impl CodeExecutor for NativeExecutor { let result = self.wasm.with_instance( runtime_code, ext, + false, |instance, onchain_version, mut ext| { let onchain_version = onchain_version.ok_or_else( || Error::ApiError("Unknown version".into()) @@ -372,8 +377,9 @@ impl sp_core::traits::CallInWasm for NativeExecutor< method: &str, call_data: &[u8], ext: &mut dyn Externalities, + missing_host_functions: MissingHostFunctions, ) -> std::result::Result, String> { - self.wasm.call_in_wasm(wasm_blob, code_hash, method, call_data, ext) + self.wasm.call_in_wasm(wasm_blob, code_hash, method, call_data, ext, missing_host_functions) } } diff --git a/client/executor/src/wasm_runtime.rs b/client/executor/src/wasm_runtime.rs index e6c16453f365fb560f577bcda600edbbb586845a..87a08f714dc93ea6ad070e7f157f202b315dd1e5 100644 --- a/client/executor/src/wasm_runtime.rs +++ b/client/executor/src/wasm_runtime.rs @@ -40,6 +40,12 @@ pub enum WasmExecutionMethod { Compiled, } +impl Default for WasmExecutionMethod { + fn default() -> WasmExecutionMethod { + WasmExecutionMethod::Interpreted + } +} + /// A Wasm runtime object along with its cached runtime version. struct VersionedRuntime { /// Runtime code hash. @@ -281,6 +287,25 @@ pub fn create_wasm_runtime_with_code( } } +fn decode_version(version: &[u8]) -> Result { + let v: RuntimeVersion = sp_api::OldRuntimeVersion::decode(&mut &version[..]) + .map_err(|_| + WasmError::Instantiation( + "failed to decode \"Core_version\" result using old runtime version".into(), + ) + )?.into(); + + let core_api_id = sp_core::hashing::blake2_64(b"Core"); + if v.has_api_with(&core_api_id, |v| v >= 3) { + sp_api::RuntimeVersion::decode(&mut &version[..]) + .map_err(|_| + WasmError::Instantiation("failed to decode \"Core_version\" result".into()) + ) + } else { + Ok(v) + } +} + fn create_versioned_wasm_runtime( code: &[u8], code_hash: Vec, @@ -315,10 +340,7 @@ fn create_versioned_wasm_runtime( ).map_err(|_| WasmError::Instantiation("panic in call to get runtime version".into()))? }; let version = match version_result { - Ok(version) => Some(RuntimeVersion::decode(&mut version.as_slice()) - .map_err(|_| - WasmError::Instantiation("failed to decode \"Core_version\" result".into()) - )?), + Ok(version) => Some(decode_version(&version)?), Err(_) => None, }; #[cfg(not(target_os = "unknown"))] @@ -344,7 +366,11 @@ fn create_versioned_wasm_runtime( #[cfg(test)] mod tests { + use super::*; use sp_wasm_interface::HostFunctions; + use sp_api::{Core, RuntimeApiInfo}; + use substrate_test_runtime::Block; + use codec::Encode; #[test] fn host_functions_are_equal() { @@ -353,4 +379,49 @@ mod tests { let equal = &host_functions[..] == &host_functions[..]; assert!(equal, "Host functions are not equal"); } + + #[test] + fn old_runtime_version_decodes() { + let old_runtime_version = sp_api::OldRuntimeVersion { + spec_name: "test".into(), + impl_name: "test".into(), + authoring_version: 1, + spec_version: 1, + impl_version: 1, + apis: sp_api::create_apis_vec!([(Core::::ID, 1)]), + }; + + let version = decode_version(&old_runtime_version.encode()).unwrap(); + assert_eq!(1, version.transaction_version); + } + + #[test] + fn old_runtime_version_decodes_fails_with_version_3() { + let old_runtime_version = sp_api::OldRuntimeVersion { + spec_name: "test".into(), + impl_name: "test".into(), + authoring_version: 1, + spec_version: 1, + impl_version: 1, + apis: sp_api::create_apis_vec!([(Core::::ID, 3)]), + }; + + decode_version(&old_runtime_version.encode()).unwrap_err(); + } + + #[test] + fn new_runtime_version_decodes() { + let old_runtime_version = sp_api::RuntimeVersion { + spec_name: "test".into(), + impl_name: "test".into(), + authoring_version: 1, + spec_version: 1, + impl_version: 1, + apis: sp_api::create_apis_vec!([(Core::::ID, 3)]), + transaction_version: 3, + }; + + let version = decode_version(&old_runtime_version.encode()).unwrap(); + assert_eq!(3, version.transaction_version); + } } diff --git a/client/executor/wasmi/Cargo.toml b/client/executor/wasmi/Cargo.toml index ea8637b9e2830972b19639440546cf486b606c5d..6f5486a5781f2d344ad2a59cccf38d12780a13db 100644 --- a/client/executor/wasmi/Cargo.toml +++ b/client/executor/wasmi/Cargo.toml @@ -1,24 +1,23 @@ [package] name = "sc-executor-wasmi" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "This crate provides an implementation of `WasmRuntime` that is baked by wasmi." documentation = "https://docs.rs/sc-executor-wasmi" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] log = "0.4.8" wasmi = "0.6.2" -parity-wasm = "0.41.0" -codec = { package = "parity-scale-codec", version = "1.3.0" } -sc-executor-common = { version = "0.8.0-alpha.5", path = "../common" } -sp-wasm-interface = { version = "2.0.0-alpha.5", path = "../../../primitives/wasm-interface" } -sp-runtime-interface = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime-interface" } -sp-core = { version = "2.0.0-alpha.5", path = "../../../primitives/core" } -sp-allocator = { version = "2.0.0-alpha.5", path = "../../../primitives/allocator" } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +codec = { package = "parity-scale-codec", version = "1.3.1" } +sc-executor-common = { version = "0.8.0-rc4", path = "../common" } +sp-wasm-interface = { version = "2.0.0-rc4", path = "../../../primitives/wasm-interface" } +sp-runtime-interface = { version = "2.0.0-rc4", path = "../../../primitives/runtime-interface" } +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } +sp-allocator = { version = "2.0.0-rc4", path = "../../../primitives/allocator" } diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index 6348c2413357f03f9de161d4ff537cf8a77e818d..e4b4aca40967d982fe342985f829bf2c4c190e39 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -16,21 +16,25 @@ //! This crate provides an implementation of `WasmModule` that is baked by wasmi. -use sc_executor_common::{error::{Error, WasmError}, sandbox}; -use std::{str, mem, cell::RefCell, sync::Arc}; +use std::{str, cell::RefCell, sync::Arc}; use wasmi::{ Module, ModuleInstance, MemoryInstance, MemoryRef, TableRef, ImportsBuilder, ModuleRef, - memory_units::Pages, RuntimeValue::{I32, I64, self}, + memory_units::Pages, + RuntimeValue::{I32, I64, self}, }; use codec::{Encode, Decode}; use sp_core::sandbox as sandbox_primitives; use log::{error, trace, debug}; -use parity_wasm::elements::{deserialize_buffer, DataSegment, Instruction, Module as RawModule}; use sp_wasm_interface::{ FunctionContext, Pointer, WordSize, Sandbox, MemoryId, Result as WResult, Function, }; use sp_runtime_interface::unpack_ptr_and_len; use sc_executor_common::wasm_runtime::{WasmModule, WasmInstance}; +use sc_executor_common::{ + error::{Error, WasmError}, + sandbox, +}; +use sc_executor_common::util::{DataSegmentsSnapshot, WasmModuleInfo}; struct FunctionExecutor<'a> { sandbox_store: sandbox::Store, @@ -530,52 +534,14 @@ fn instantiate_module( /// /// 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)>, +struct GlobalValsSnapshot { /// The list of all global mutable variables of the module in their sequential order. global_mut_values: Vec, } -impl StateSnapshot { +impl GlobalValsSnapshot { // Returns `None` if instance is not valid. - fn take( - module_instance: &ModuleRef, - data_segments: Vec, - ) -> 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::>>()?; - + fn take(module_instance: &ModuleRef) -> Self { // Collect all values of mutable globals. let global_mut_values = module_instance .globals() @@ -583,42 +549,27 @@ impl StateSnapshot { .filter(|g| g.is_mutable()) .map(|g| g.get()) .collect(); - - Some(Self { - data_segments: prepared_segments, - global_mut_values, - }) + Self { global_mut_values } } /// 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, memory: &MemoryRef) -> Result<(), WasmError> { - // First, erase the memory and copy the data segments into it. - memory - .erase() - .map_err(|e| WasmError::ErasingFailed(e.to_string()))?; - for (offset, contents) in &self.data_segments { - memory - .set(*offset, contents) - .map_err(|_| WasmError::ApplySnapshotFailed)?; - } - - // Second, restore the values of mutable globals. + fn apply(&self, instance: &ModuleRef) -> Result<(), WasmError> { 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)?; - } + { + // 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(()) } } @@ -634,8 +585,9 @@ pub struct WasmiRuntime { allow_missing_func_imports: bool, /// Numer of heap pages this runtime uses. heap_pages: u64, - /// Data segments created for each new instance. - data_segments: Vec, + + global_vals_snapshot: GlobalValsSnapshot, + data_segments_snapshot: DataSegmentsSnapshot, } impl WasmModule for WasmiRuntime { @@ -648,19 +600,11 @@ impl WasmModule for WasmiRuntime { self.allow_missing_func_imports, ).map_err(|e| WasmError::Instantiation(e.to_string()))?; - // Take state snapshot before executing anything. - let state_snapshot = StateSnapshot::take(&instance, self.data_segments.clone()) - .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(Box::new(WasmiInstance { instance, memory, - state_snapshot, + global_vals_snapshot: self.global_vals_snapshot.clone(), + data_segments_snapshot: self.data_segments_snapshot.clone(), host_functions: self.host_functions.clone(), allow_missing_func_imports: self.allow_missing_func_imports, missing_functions, @@ -682,10 +626,29 @@ pub fn create_runtime( // // 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)?; + let (data_segments_snapshot, global_vals_snapshot) = { + let (instance, _, _) = instantiate_module( + heap_pages as usize, + &module, + &host_functions, + allow_missing_func_imports, + ) + .map_err(|e| WasmError::Instantiation(e.to_string()))?; + + let data_segments_snapshot = DataSegmentsSnapshot::take( + &WasmModuleInfo::new(code) + .ok_or_else(|| WasmError::Other("cannot deserialize module".to_string()))?, + ) + .map_err(|e| WasmError::Other(e.to_string()))?; + let global_vals_snapshot = GlobalValsSnapshot::take(&instance); + + (data_segments_snapshot, global_vals_snapshot) + }; + Ok(WasmiRuntime { module, - data_segments, + data_segments_snapshot, + global_vals_snapshot, host_functions: Arc::new(host_functions), allow_missing_func_imports, heap_pages, @@ -698,12 +661,14 @@ pub struct WasmiInstance { instance: ModuleRef, /// The memory instance of used by the wasm module. memory: MemoryRef, - /// The snapshot of the instance's state taken just after the instantiation. - state_snapshot: StateSnapshot, + /// The snapshot of global variable values just after instantiation. + global_vals_snapshot: GlobalValsSnapshot, + /// The snapshot of data segments. + data_segments_snapshot: DataSegmentsSnapshot, /// The host functions registered for this instance. host_functions: Arc>, /// Enable stub generation for functions that are not available in `host_functions`. - /// These stubs will error when the wasm blob tries to call them. + /// These stubs will error when the wasm blob trie to call them. allow_missing_func_imports: bool, /// List of missing functions detected during function resolution missing_functions: Vec, @@ -713,19 +678,26 @@ pub struct WasmiInstance { unsafe impl Send for WasmiInstance {} impl WasmInstance for WasmiInstance { - fn call( - &self, - method: &str, - data: &[u8], - ) -> Result, Error> { - self.state_snapshot.apply(&self.instance, &self.memory) - .map_err(|e| { - // Snapshot restoration failed. This is pretty unexpected since this can happen - // if some invariant is broken or if the system is under extreme memory pressure - // (so erasing fails). - error!(target: "wasm-executor", "snapshot restoration failed: {}", e); - e - })?; + fn call(&self, method: &str, data: &[u8]) -> Result, Error> { + // We reuse a single wasm instance for multiple calls and a previous call (if any) + // altered the state. Therefore, we need to restore the instance to original state. + + // First, zero initialize the linear memory. + self.memory.erase().map_err(|e| { + // Snapshot restoration failed. This is pretty unexpected since this can happen + // if some invariant is broken or if the system is under extreme memory pressure + // (so erasing fails). + error!(target: "wasm-executor", "snapshot restoration failed: {}", e); + WasmError::ErasingFailed(e.to_string()) + })?; + + // Second, reapply data segments into the linear memory. + self.data_segments_snapshot + .apply(|offset, contents| self.memory.set(offset, contents))?; + + // Third, restore the global variables to their initial values. + self.global_vals_snapshot.apply(&self.instance)?; + call_in_wasm_module( &self.instance, &self.memory, @@ -750,18 +722,3 @@ impl WasmInstance for WasmiInstance { } } } - -/// 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/client/executor/wasmtime/Cargo.toml b/client/executor/wasmtime/Cargo.toml index 11f99e7876bbc57dae3b3ec792a3efe30161d476..26eddd1da6d1bf547a0ccfe8007591e0362d0541 100644 --- a/client/executor/wasmtime/Cargo.toml +++ b/client/executor/wasmtime/Cargo.toml @@ -1,27 +1,31 @@ [package] name = "sc-executor-wasmtime" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Defines a `WasmRuntime` that uses the Wasmtime JIT to execute." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] log = "0.4.8" scoped-tls = "1.0" parity-wasm = "0.41.0" -codec = { package = "parity-scale-codec", version = "1.3.0" } -sc-executor-common = { version = "0.8.0-alpha.5", path = "../common" } -sp-wasm-interface = { version = "2.0.0-alpha.5", path = "../../../primitives/wasm-interface" } -sp-runtime-interface = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime-interface" } -sp-core = { version = "2.0.0-alpha.5", path = "../../../primitives/core" } -sp-allocator = { version = "2.0.0-alpha.5", path = "../../../primitives/allocator" } -wasmtime = { package = "substrate-wasmtime", version = "0.13.0-threadsafe.1" } +codec = { package = "parity-scale-codec", version = "1.3.1" } +sc-executor-common = { version = "0.8.0-rc4", path = "../common" } +sp-wasm-interface = { version = "2.0.0-rc4", path = "../../../primitives/wasm-interface" } +sp-runtime-interface = { version = "2.0.0-rc4", path = "../../../primitives/runtime-interface" } +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } +sp-allocator = { version = "2.0.0-rc4", path = "../../../primitives/allocator" } +wasmtime = { package = "substrate-wasmtime", version = "0.16.0-threadsafe.4" } +wasmtime-runtime = { package = "substrate-wasmtime-runtime", version = "0.16.0-threadsafe.4" } +wasmtime-environ = "0.16" +cranelift-wasm = "0.63" +cranelift-codegen = "0.63" [dev-dependencies] assert_matches = "1.3.0" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/client/executor/wasmtime/src/host.rs b/client/executor/wasmtime/src/host.rs index 29187ac66338e87e8694bb89a4dc0fa19c9e534d..8c481e95c43714fa79f704881c07429b998466cb 100644 --- a/client/executor/wasmtime/src/host.rs +++ b/client/executor/wasmtime/src/host.rs @@ -117,7 +117,7 @@ impl<'a> SandboxCapabilities for HostContext<'a> { return Err("Supervisor function returned unexpected result!".into()); } } - Err(err) => Err(err.message().to_string().into()), + Err(err) => Err(err.to_string().into()), } } } diff --git a/client/executor/wasmtime/src/imports.rs b/client/executor/wasmtime/src/imports.rs index 48299ffd62de1caef2e03016d9b8060188548365..36752d72fa02334efc6a99191005da7c9577ce10 100644 --- a/client/executor/wasmtime/src/imports.rs +++ b/client/executor/wasmtime/src/imports.rs @@ -1,26 +1,27 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use crate::state_holder; use sc_executor_common::error::WasmError; use sp_wasm_interface::{Function, Value, ValueType}; use std::any::Any; -use std::rc::Rc; use wasmtime::{ - Callable, Extern, ExternType, Func, FuncType, ImportType, Limits, Memory, MemoryType, Module, + Extern, ExternType, Func, FuncType, ImportType, Limits, Memory, MemoryType, Module, Trap, Val, }; @@ -53,11 +54,11 @@ pub fn resolve_imports( let resolved = match import_ty.name() { "memory" => { memory_import_index = Some(externs.len()); - resolve_memory_import(module, import_ty, heap_pages)? + resolve_memory_import(module, &import_ty, heap_pages)? } _ => resolve_func_import( module, - import_ty, + &import_ty, host_functions, allow_missing_func_imports, )?, @@ -131,7 +132,7 @@ fn resolve_func_import( { Some(host_func) => host_func, None if allow_missing_func_imports => { - return Ok(MissingHostFuncHandler::new(import_ty).into_extern(module, func_ty)); + return Ok(MissingHostFuncHandler::new(import_ty).into_extern(module, &func_ty)); } None => { return Err(WasmError::Other(format!( @@ -163,6 +164,58 @@ struct HostFuncHandler { host_func: &'static dyn Function, } +fn call_static( + static_func: &'static dyn Function, + wasmtime_params: &[Val], + wasmtime_results: &mut [Val], +) -> Result<(), wasmtime::Trap> { + let unwind_result = state_holder::with_context(|host_ctx| { + let mut host_ctx = host_ctx.expect( + "host functions can be called only from wasm instance; + wasm instance is always called initializing context; + therefore host_ctx cannot be None; + qed + ", + ); + // `into_value` panics if it encounters a value that doesn't fit into the values + // available in substrate. + // + // This, however, cannot happen since the signature of this function is created from + // a `dyn Function` signature of which cannot have a non substrate value by definition. + let mut params = wasmtime_params.iter().cloned().map(into_value); + + std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + static_func.execute(&mut host_ctx, &mut params) + })) + }); + + let execution_result = match unwind_result { + Ok(execution_result) => execution_result, + Err(err) => return Err(Trap::new(stringify_panic_payload(err))), + }; + + match execution_result { + Ok(Some(ret_val)) => { + debug_assert!( + wasmtime_results.len() == 1, + "wasmtime function signature, therefore the number of results, should always \ + correspond to the number of results returned by the host function", + ); + wasmtime_results[0] = into_wasmtime_val(ret_val); + Ok(()) + } + Ok(None) => { + debug_assert!( + wasmtime_results.len() == 0, + "wasmtime function signature, therefore the number of results, should always \ + correspond to the number of results returned by the host function", + ); + Ok(()) + } + Err(msg) => Err(Trap::new(msg)), + } +} + impl HostFuncHandler { fn new(host_func: &'static dyn Function) -> Self { Self { @@ -171,63 +224,14 @@ impl HostFuncHandler { } fn into_extern(self, module: &Module) -> Extern { + let host_func = self.host_func; let func_ty = wasmtime_func_sig(self.host_func); - let func = Func::new(module.store(), func_ty, Rc::new(self)); - Extern::Func(func) - } -} - -impl Callable for HostFuncHandler { - fn call( - &self, - wasmtime_params: &[Val], - wasmtime_results: &mut [Val], - ) -> Result<(), wasmtime::Trap> { - let unwind_result = state_holder::with_context(|host_ctx| { - let mut host_ctx = host_ctx.expect( - "host functions can be called only from wasm instance; - wasm instance is always called initializing context; - therefore host_ctx cannot be None; - qed - ", - ); - // `into_value` panics if it encounters a value that doesn't fit into the values - // available in substrate. - // - // This, however, cannot happen since the signature of this function is created from - // a `dyn Function` signature of which cannot have a non substrate value by definition. - let mut params = wasmtime_params.iter().cloned().map(into_value); - - std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { - self.host_func.execute(&mut host_ctx, &mut params) - })) - }); - - let execution_result = match unwind_result { - Ok(execution_result) => execution_result, - Err(err) => return Err(Trap::new(stringify_panic_payload(err))), - }; - - match execution_result { - Ok(Some(ret_val)) => { - debug_assert!( - wasmtime_results.len() == 1, - "wasmtime function signature, therefore the number of results, should always \ - correspond to the number of results returned by the host function", - ); - wasmtime_results[0] = into_wasmtime_val(ret_val); - Ok(()) + let func = Func::new(module.store(), func_ty, + move |_, params, result| { + call_static(host_func, params, result) } - Ok(None) => { - debug_assert!( - wasmtime_results.len() == 0, - "wasmtime function signature, therefore the number of results, should always \ - correspond to the number of results returned by the host function", - ); - Ok(()) - } - Err(msg) => Err(Trap::new(msg)), - } + ); + Extern::Func(func) } } @@ -245,25 +249,18 @@ impl MissingHostFuncHandler { } } - fn into_extern(self, module: &Module, func_ty: &FuncType) -> Extern { - let func = Func::new(module.store(), func_ty.clone(), Rc::new(self)); + fn into_extern(self, wasmtime_module: &Module, func_ty: &FuncType) -> Extern { + let Self { module, name } = self; + let func = Func::new(wasmtime_module.store(), func_ty.clone(), + move |_, _, _| Err(Trap::new(format!( + "call to a missing function {}:{}", + module, name + ))) + ); Extern::Func(func) } } -impl Callable for MissingHostFuncHandler { - fn call( - &self, - _wasmtime_params: &[Val], - _wasmtime_results: &mut [Val], - ) -> Result<(), wasmtime::Trap> { - Err(Trap::new(format!( - "call to a missing function {}:{}", - self.module, self.name - ))) - } -} - fn wasmtime_func_sig(func: &dyn Function) -> wasmtime::FuncType { let params = func .signature() diff --git a/client/executor/wasmtime/src/instance_wrapper.rs b/client/executor/wasmtime/src/instance_wrapper.rs index 159746801a52aa68e45c63b4f060a1804415a2f8..9026b8054e652604d41a7b626c4f09c38f0eebfe 100644 --- a/client/executor/wasmtime/src/instance_wrapper.rs +++ b/client/executor/wasmtime/src/instance_wrapper.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Defines data and logic needed for interaction with an WebAssembly instance of a substrate //! runtime module. @@ -20,11 +22,55 @@ use crate::util; use crate::imports::Imports; -use sc_executor_common::error::{Error, Result}; +use std::{slice, marker}; +use sc_executor_common::{ + error::{Error, Result}, + util::{WasmModuleInfo, DataSegmentsSnapshot}, +}; use sp_wasm_interface::{Pointer, WordSize, Value}; -use std::slice; -use std::marker; -use wasmtime::{Instance, Module, Memory, Table, Val}; +use wasmtime::{Store, Instance, Module, Memory, Table, Val, Func, Extern, Global}; + +mod globals_snapshot; + +pub use globals_snapshot::GlobalsSnapshot; + +pub struct ModuleWrapper { + imported_globals_count: u32, + globals_count: u32, + module: Module, + data_segments_snapshot: DataSegmentsSnapshot, +} + +impl ModuleWrapper { + pub fn new(store: &Store, code: &[u8]) -> Result { + let module = Module::new(&store, code) + .map_err(|e| Error::from(format!("cannot create module: {}", e)))?; + + let module_info = WasmModuleInfo::new(code) + .ok_or_else(|| Error::from("cannot deserialize module".to_string()))?; + let declared_globals_count = module_info.declared_globals_count(); + let imported_globals_count = module_info.imported_globals_count(); + let globals_count = imported_globals_count + declared_globals_count; + + let data_segments_snapshot = DataSegmentsSnapshot::take(&module_info) + .map_err(|e| Error::from(format!("cannot take data segments snapshot: {}", e)))?; + + Ok(Self { + module, + imported_globals_count, + globals_count, + data_segments_snapshot, + }) + } + + pub fn module(&self) -> &Module { + &self.module + } + + pub fn data_segments_snapshot(&self) -> &DataSegmentsSnapshot { + &self.data_segments_snapshot + } +} /// Wrap the given WebAssembly Instance of a wasm module with Substrate-runtime. /// @@ -32,6 +78,8 @@ use wasmtime::{Instance, Module, Memory, Table, Val}; /// routines. pub struct InstanceWrapper { instance: Instance, + globals_count: u32, + imported_globals_count: u32, // The memory instance of the `instance`. // // It is important to make sure that we don't make any copies of this to make it easier to proof @@ -42,16 +90,44 @@ pub struct InstanceWrapper { _not_send_nor_sync: marker::PhantomData<*const ()>, } +fn extern_memory(extern_: &Extern) -> Option<&Memory> { + match extern_ { + Extern::Memory(mem) => Some(mem), + _ => None, + } +} + + +fn extern_global(extern_: &Extern) -> Option<&Global> { + match extern_ { + Extern::Global(glob) => Some(glob), + _ => None, + } +} + +fn extern_table(extern_: &Extern) -> Option<&Table> { + match extern_ { + Extern::Table(table) => Some(table), + _ => None, + } +} + +fn extern_func(extern_: &Extern) -> Option<&Func> { + match extern_ { + Extern::Func(func) => Some(func), + _ => None, + } +} + impl InstanceWrapper { /// Create a new instance wrapper from the given wasm module. - pub fn new(module: &Module, imports: &Imports, heap_pages: u32) -> Result { - let instance = Instance::new(module, &imports.externs) + pub fn new(module_wrapper: &ModuleWrapper, imports: &Imports, heap_pages: u32) -> Result { + let instance = Instance::new(&module_wrapper.module, &imports.externs) .map_err(|e| Error::from(format!("cannot instantiate: {}", e)))?; let memory = match imports.memory_import_index { Some(memory_idx) => { - imports.externs[memory_idx] - .memory() + extern_memory(&imports.externs[memory_idx]) .expect("only memory can be at the `memory_idx`; qed") .clone() } @@ -66,8 +142,10 @@ impl InstanceWrapper { Ok(Self { table: get_table(&instance), - memory, instance, + globals_count: module_wrapper.globals_count, + imported_globals_count: module_wrapper.imported_globals_count, + memory, _not_send_nor_sync: marker::PhantomData, }) } @@ -82,8 +160,7 @@ impl InstanceWrapper { .instance .get_export(name) .ok_or_else(|| Error::from(format!("Exported method {} is not found", name)))?; - let entrypoint = export - .func() + let entrypoint = extern_func(&export) .ok_or_else(|| Error::from(format!("Export {} is not a function", name)))?; match (entrypoint.ty().params(), entrypoint.ty().results()) { (&[wasmtime::ValType::I32, wasmtime::ValType::I32], &[wasmtime::ValType::I64]) => {} @@ -116,8 +193,7 @@ impl InstanceWrapper { .get_export("__heap_base") .ok_or_else(|| Error::from("__heap_base is not found"))?; - let heap_base_global = heap_base_export - .global() + let heap_base_global = extern_global(&heap_base_export) .ok_or_else(|| Error::from("__heap_base is not a global"))?; let heap_base = heap_base_global @@ -135,7 +211,7 @@ impl InstanceWrapper { None => return Ok(None), }; - let global = global.global().ok_or_else(|| format!("`{}` is not a global", name))?; + let global = extern_global(&global).ok_or_else(|| format!("`{}` is not a global", name))?; match global.get() { Val::I32(val) => Ok(Some(Value::I32(val))), @@ -153,8 +229,7 @@ fn get_linear_memory(instance: &Instance) -> Result { .get_export("memory") .ok_or_else(|| Error::from("memory is not exported under `memory` name"))?; - let memory = memory_export - .memory() + let memory = extern_memory(&memory_export) .ok_or_else(|| Error::from("the `memory` export should have memory type"))? .clone(); @@ -165,7 +240,8 @@ fn get_linear_memory(instance: &Instance) -> Result { fn get_table(instance: &Instance) -> Option { instance .get_export("__indirect_function_table") - .and_then(|export| export.table()) + .as_ref() + .and_then(extern_table) .cloned() } diff --git a/client/executor/wasmtime/src/instance_wrapper/globals_snapshot.rs b/client/executor/wasmtime/src/instance_wrapper/globals_snapshot.rs new file mode 100644 index 0000000000000000000000000000000000000000..01d82451fcbbb4884df321103a7ee8fc61f10ed0 --- /dev/null +++ b/client/executor/wasmtime/src/instance_wrapper/globals_snapshot.rs @@ -0,0 +1,131 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use super::InstanceWrapper; +use sc_executor_common::{ + error::{Error, Result}, +}; +use sp_wasm_interface::Value; +use cranelift_codegen::ir; +use cranelift_wasm::GlobalIndex; +use wasmtime_runtime::{ExportGlobal, Export}; + +/// A snapshot of a global variables values. This snapshot can be used later for restoring the +/// values to the preserved state. +/// +/// Technically, a snapshot stores only values of mutable global variables. This is because +/// immutable global variables always have the same values. +pub struct GlobalsSnapshot { + handle: wasmtime_runtime::InstanceHandle, + preserved_mut_globals: Vec<(*mut wasmtime_runtime::VMGlobalDefinition, Value)>, +} + +impl GlobalsSnapshot { + /// Take a snapshot of global variables for a given instance. + pub fn take(instance_wrapper: &InstanceWrapper) -> Result { + // EVIL: + // Usage of an undocumented function. + let handle = unsafe { instance_wrapper.instance.handle().clone() }; + + let mut preserved_mut_globals = vec![]; + + for global_idx in instance_wrapper.imported_globals_count..instance_wrapper.globals_count { + let (def, global) = match handle.lookup_by_declaration( + &wasmtime_environ::EntityIndex::Global(GlobalIndex::from_u32(global_idx)), + ) { + Export::Global(ExportGlobal { definition, global, .. }) => (definition, global), + _ => unreachable!("only globals can be returned for a global request"), + }; + + // skip immutable globals. + if !global.mutability { + continue; + } + + let value = unsafe { + // Safety of this function solely depends on the correctness of the reference and + // the type information of the global. + read_global(def, global.ty)? + }; + preserved_mut_globals.push((def, value)); + } + + Ok(Self { + preserved_mut_globals, + handle, + }) + } + + /// Apply the snapshot to the given instance. + /// + /// This instance must be the same that was used for creation of this snapshot. + pub fn apply(&self, instance_wrapper: &InstanceWrapper) -> Result<()> { + if instance_wrapper.instance.handle() != &self.handle { + return Err(Error::from("unexpected instance handle".to_string())); + } + + for (def, value) in &self.preserved_mut_globals { + unsafe { + // The following writes are safe if the precondition that this is the same instance + // this snapshot was created with: + // + // 1. These pointers must be still not-NULL and allocated. + // 2. The set of global variables is fixed for the lifetime of the same instance. + // 3. We obviously assume that the wasmtime references are correct in the first place. + // 4. We write the data with the same type it was read in the first place. + write_global(*def, *value)?; + } + } + Ok(()) + } +} + +unsafe fn read_global( + def: *const wasmtime_runtime::VMGlobalDefinition, + ty: ir::Type, +) -> Result { + let def = def + .as_ref() + .ok_or_else(|| Error::from("wasmtime global reference is null during read".to_string()))?; + let val = match ty { + ir::types::I32 => Value::I32(*def.as_i32()), + ir::types::I64 => Value::I64(*def.as_i64()), + ir::types::F32 => Value::F32(*def.as_u32()), + ir::types::F64 => Value::F64(*def.as_u64()), + _ => { + return Err(Error::from(format!( + "unsupported global variable type: {}", + ty + ))) + } + }; + Ok(val) +} + +unsafe fn write_global(def: *mut wasmtime_runtime::VMGlobalDefinition, value: Value) -> Result<()> { + let def = def + .as_mut() + .ok_or_else(|| Error::from("wasmtime global reference is null during write".to_string()))?; + match value { + Value::I32(v) => *def.as_i32_mut() = v, + Value::I64(v) => *def.as_i64_mut() = v, + Value::F32(v) => *def.as_u32_mut() = v, + Value::F64(v) => *def.as_u64_mut() = v, + } + Ok(()) +} diff --git a/client/executor/wasmtime/src/runtime.rs b/client/executor/wasmtime/src/runtime.rs index 02acd33e69a628705675105e8644bad177bfc15a..a2ad3bada4ba0354849515db2f57699836604108 100644 --- a/client/executor/wasmtime/src/runtime.rs +++ b/client/executor/wasmtime/src/runtime.rs @@ -15,14 +15,14 @@ // along with Substrate. If not, see . //! Defines the compiled Wasm runtime that uses Wasmtime internally. -use std::rc::Rc; -use std::sync::Arc; use crate::host::HostState; use crate::imports::{Imports, resolve_imports}; -use crate::instance_wrapper::InstanceWrapper; +use crate::instance_wrapper::{ModuleWrapper, InstanceWrapper, GlobalsSnapshot}; use crate::state_holder; +use std::rc::Rc; +use std::sync::Arc; use sc_executor_common::{ error::{Error, Result, WasmError}, wasm_runtime::{WasmModule, WasmInstance}, @@ -30,12 +30,12 @@ use sc_executor_common::{ use sp_allocator::FreeingBumpHeapAllocator; use sp_runtime_interface::unpack_ptr_and_len; use sp_wasm_interface::{Function, Pointer, WordSize, Value}; -use wasmtime::{Config, Engine, Module, Store}; +use wasmtime::{Config, Engine, Store}; /// A `WasmModule` implementation using wasmtime to compile the runtime module to machine code /// and execute the compiled code. pub struct WasmtimeRuntime { - module: Arc, + module_wrapper: Arc, heap_pages: u32, allow_missing_func_imports: bool, host_functions: Vec<&'static dyn Function>, @@ -46,16 +46,24 @@ impl WasmModule for WasmtimeRuntime { // Scan all imports, find the matching host functions, and create stubs that adapt arguments // and results. let imports = resolve_imports( - &self.module, + self.module_wrapper.module(), &self.host_functions, self.heap_pages, self.allow_missing_func_imports, )?; + let instance_wrapper = + InstanceWrapper::new(&self.module_wrapper, &imports, self.heap_pages)?; + let heap_base = instance_wrapper.extract_heap_base()?; + let globals_snapshot = GlobalsSnapshot::take(&instance_wrapper)?; + Ok(Box::new(WasmtimeInstance { - module: self.module.clone(), + instance_wrapper: Rc::new(instance_wrapper), + module_wrapper: Arc::clone(&self.module_wrapper), imports, + globals_snapshot, heap_pages: self.heap_pages, + heap_base, })) } } @@ -63,9 +71,12 @@ impl WasmModule for WasmtimeRuntime { /// A `WasmInstance` implementation that reuses compiled module and spawns instances /// to execute the compiled code. pub struct WasmtimeInstance { - module: Arc, + module_wrapper: Arc, + instance_wrapper: Rc, + globals_snapshot: GlobalsSnapshot, imports: Imports, heap_pages: u32, + heap_base: u32, } // This is safe because `WasmtimeInstance` does not leak reference to `self.imports` @@ -74,23 +85,32 @@ unsafe impl Send for WasmtimeInstance {} impl WasmInstance for WasmtimeInstance { fn call(&self, method: &str, data: &[u8]) -> Result> { - // TODO: reuse the instance and reset globals after call - // https://github.com/paritytech/substrate/issues/5141 - let instance = Rc::new(InstanceWrapper::new(&self.module, &self.imports, self.heap_pages)?); - call_method( - instance, - method, + let entrypoint = self.instance_wrapper.resolve_entrypoint(method)?; + let allocator = FreeingBumpHeapAllocator::new(self.heap_base); + + self.module_wrapper + .data_segments_snapshot() + .apply(|offset, contents| { + self.instance_wrapper + .write_memory_from(Pointer::new(offset), contents) + })?; + + self.globals_snapshot.apply(&*self.instance_wrapper)?; + + perform_call( data, + Rc::clone(&self.instance_wrapper), + entrypoint, + allocator, ) } fn get_global_const(&self, name: &str) -> Result> { - let instance = InstanceWrapper::new(&self.module, &self.imports, self.heap_pages)?; + let instance = InstanceWrapper::new(&self.module_wrapper, &self.imports, self.heap_pages)?; instance.get_global_val(name) } } - /// Create a new `WasmtimeRuntime` given the code. This function performs translation from Wasm to /// machine code, which can be computationally heavy. pub fn create_runtime( @@ -105,30 +125,18 @@ pub fn create_runtime( let engine = Engine::new(&config); let store = Store::new(&engine); - let module = Module::new(&store, code) + + let module_wrapper = ModuleWrapper::new(&store, code) .map_err(|e| WasmError::Other(format!("cannot create module: {}", e)))?; Ok(WasmtimeRuntime { - module: Arc::new(module), + module_wrapper: Arc::new(module_wrapper), heap_pages: heap_pages as u32, allow_missing_func_imports, host_functions, }) } -/// Call a function inside a precompiled Wasm module. -fn call_method( - instance_wrapper: Rc, - method: &str, - data: &[u8], -) -> Result> { - let entrypoint = instance_wrapper.resolve_entrypoint(method)?; - let heap_base = instance_wrapper.extract_heap_base()?; - let allocator = FreeingBumpHeapAllocator::new(heap_base); - - perform_call(data, instance_wrapper, entrypoint, allocator) -} - fn perform_call( data: &[u8], instance_wrapper: Rc, @@ -150,7 +158,7 @@ fn perform_call( Err(trap) => { return Err(Error::from(format!( "Wasm execution trapped: {}", - trap.message() + trap ))); } } diff --git a/client/executor/wasmtime/src/state_holder.rs b/client/executor/wasmtime/src/state_holder.rs index 42cb79e7a356807176033266dd0a4f22eacb5103..711d3bb735d7c04306525ba451f1e4be84ed9d21 100644 --- a/client/executor/wasmtime/src/state_holder.rs +++ b/client/executor/wasmtime/src/state_holder.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use crate::host::{HostContext, HostState}; diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index b684c814d1b93607534c2b73fdc74aa4a99eda8b..36b1d59b0c0b2e4aad1a26a7a500928a9f04c191 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -1,58 +1,60 @@ [package] name = "sc-finality-grandpa" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Integration of the GRANDPA finality gadget into substrate." documentation = "https://docs.rs/sc-finality-grandpa" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -fork-tree = { version = "2.0.0-alpha.5", path = "../../utils/fork-tree" } +derive_more = "0.99.2" +fork-tree = { version = "2.0.0-rc4", path = "../../utils/fork-tree" } futures = "0.3.4" futures-timer = "3.0.1" log = "0.4.8" parking_lot = "0.10.0" rand = "0.7.2" assert_matches = "1.3.0" -parity-scale-codec = { version = "1.3.0", features = ["derive"] } -sp-arithmetic = { version = "2.0.0-alpha.5", path = "../../primitives/arithmetic" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../primitives/runtime" } -sp-utils = { version = "2.0.0-alpha.5", path = "../../primitives/utils" } -sp-consensus = { version = "0.8.0-alpha.5", path = "../../primitives/consensus/common" } -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -sp-api = { version = "2.0.0-alpha.5", path = "../../primitives/api" } -sc-telemetry = { version = "2.0.0-alpha.5", path = "../telemetry" } -sc-keystore = { version = "2.0.0-alpha.5", path = "../keystore" } +parity-scale-codec = { version = "1.3.1", features = ["derive"] } +sp-application-crypto = { version = "2.0.0-rc4", path = "../../primitives/application-crypto" } +sp-arithmetic = { version = "2.0.0-rc4", path = "../../primitives/arithmetic" } +sp-runtime = { version = "2.0.0-rc4", path = "../../primitives/runtime" } +sp-utils = { version = "2.0.0-rc4", path = "../../primitives/utils" } +sp-consensus = { version = "0.8.0-rc4", path = "../../primitives/consensus/common" } +sc-consensus = { version = "0.8.0-rc4", path = "../../client/consensus/common" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +sp-api = { version = "2.0.0-rc4", path = "../../primitives/api" } +sc-telemetry = { version = "2.0.0-rc4", path = "../telemetry" } +sc-keystore = { version = "2.0.0-rc4", path = "../keystore" } serde_json = "1.0.41" -sc-client-api = { version = "2.0.0-alpha.5", path = "../api" } -sc-client = { version = "0.8.0-alpha.5", path = "../" } -sp-inherents = { version = "2.0.0-alpha.5", path = "../../primitives/inherents" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../primitives/blockchain" } -sc-network = { version = "0.8.0-alpha.5", path = "../network" } -sc-network-gossip = { version = "0.8.0-alpha.5", path = "../network-gossip" } -sp-finality-tracker = { version = "2.0.0-alpha.5", path = "../../primitives/finality-tracker" } -sp-finality-grandpa = { version = "2.0.0-alpha.5", path = "../../primitives/finality-grandpa" } -prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.8.0-alpha.5"} -sc-block-builder = { version = "0.8.0-alpha.5", path = "../block-builder" } -finality-grandpa = { version = "0.11.2", features = ["derive-codec"] } +sc-client-api = { version = "2.0.0-rc4", path = "../api" } +sp-inherents = { version = "2.0.0-rc4", path = "../../primitives/inherents" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../primitives/blockchain" } +sc-network = { version = "0.8.0-rc4", path = "../network" } +sc-network-gossip = { version = "0.8.0-rc4", path = "../network-gossip" } +sp-finality-tracker = { version = "2.0.0-rc4", path = "../../primitives/finality-tracker" } +sp-finality-grandpa = { version = "2.0.0-rc4", path = "../../primitives/finality-grandpa" } +prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.8.0-rc4"} +sc-block-builder = { version = "0.8.0-rc4", path = "../block-builder" } +finality-grandpa = { version = "0.12.3", features = ["derive-codec"] } pin-project = "0.4.6" [dev-dependencies] -finality-grandpa = { version = "0.11.2", features = ["derive-codec", "test-helpers"] } -sc-network = { version = "0.8.0-alpha.5", path = "../network" } -sc-network-test = { version = "0.8.0-dev", path = "../network/test" } -sp-keyring = { version = "2.0.0-alpha.5", path = "../../primitives/keyring" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../test-utils/runtime/client" } -sp-consensus-babe = { version = "0.8.0-alpha.5", path = "../../primitives/consensus/babe" } -sp-state-machine = { version = "0.8.0-alpha.5", path = "../../primitives/state-machine" } +finality-grandpa = { version = "0.12.3", features = ["derive-codec", "test-helpers"] } +sc-network = { version = "0.8.0-rc4", path = "../network" } +sc-network-test = { version = "0.8.0-rc4", path = "../network/test" } +sp-keyring = { version = "2.0.0-rc4", path = "../../primitives/keyring" } +substrate-test-runtime-client = { version = "2.0.0-rc4", path = "../../test-utils/runtime/client" } +sp-consensus-babe = { version = "0.8.0-rc4", path = "../../primitives/consensus/babe" } +sp-state-machine = { version = "0.8.0-rc4", path = "../../primitives/state-machine" } env_logger = "0.7.0" tokio = { version = "0.2", features = ["rt-core"] } tempfile = "3.1.0" -sp-api = { version = "2.0.0-alpha.5", path = "../../primitives/api" } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +sp-api = { version = "2.0.0-rc4", path = "../../primitives/api" } diff --git a/client/finality-grandpa/rpc/Cargo.toml b/client/finality-grandpa/rpc/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..a7d8e64087414f69da97087f84bd8c81be11fc51 --- /dev/null +++ b/client/finality-grandpa/rpc/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "sc-finality-grandpa-rpc" +version = "0.8.0-rc4" +authors = ["Parity Technologies "] +description = "RPC extensions for the GRANDPA finality gadget" +repository = "https://github.com/paritytech/substrate/" +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +sc-finality-grandpa = { version = "0.8.0-rc4", path = "../" } +finality-grandpa = { version = "0.12.3", features = ["derive-codec"] } +jsonrpc-core = "14.2.0" +jsonrpc-core-client = "14.2.0" +jsonrpc-derive = "14.2.1" +futures = { version = "0.3.4", features = ["compat"] } +serde = { version = "1.0.105", features = ["derive"] } +serde_json = "1.0.50" +log = "0.4.8" +derive_more = "0.99.2" + +[dev-dependencies] +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } diff --git a/client/finality-grandpa/rpc/src/error.rs b/client/finality-grandpa/rpc/src/error.rs new file mode 100644 index 0000000000000000000000000000000000000000..bfd0596fdf3205d3eda8003a3a0f109b83fe836f --- /dev/null +++ b/client/finality-grandpa/rpc/src/error.rs @@ -0,0 +1,49 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use crate::NOT_READY_ERROR_CODE; + +#[derive(derive_more::Display, derive_more::From)] +/// Top-level error type for the RPC handler +pub enum Error { + /// The GRANDPA RPC endpoint is not ready. + #[display(fmt = "GRANDPA RPC endpoint not ready")] + EndpointNotReady, + /// GRANDPA reports the authority set id to be larger than 32-bits. + #[display(fmt = "GRANDPA reports authority set id unreasonably large")] + AuthoritySetIdReportedAsUnreasonablyLarge, + /// GRANDPA reports voter state with round id or weights larger than 32-bits. + #[display(fmt = "GRANDPA reports voter state as unreasonably large")] + VoterStateReportsUnreasonablyLargeNumbers, +} + +impl From for jsonrpc_core::Error { + fn from(error: Error) -> Self { + jsonrpc_core::Error { + message: format!("{}", error), + code: jsonrpc_core::ErrorCode::ServerError(NOT_READY_ERROR_CODE), + data: None, + } + } +} + +impl From for Error { + fn from(_error: std::num::TryFromIntError) -> Self { + Error::VoterStateReportsUnreasonablyLargeNumbers + } +} diff --git a/client/finality-grandpa/rpc/src/lib.rs b/client/finality-grandpa/rpc/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..1af84b7a84413007be22a8f01be7701648c1d489 --- /dev/null +++ b/client/finality-grandpa/rpc/src/lib.rs @@ -0,0 +1,171 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! RPC API for GRANDPA. +#![warn(missing_docs)] + +use futures::{FutureExt, TryFutureExt}; +use jsonrpc_derive::rpc; + +mod error; +mod report; + +use report::{ReportAuthoritySet, ReportVoterState, ReportedRoundStates}; + +/// Returned when Grandpa RPC endpoint is not ready. +pub const NOT_READY_ERROR_CODE: i64 = 1; + +type FutureResult = + Box + Send>; + +/// Provides RPC methods for interacting with GRANDPA. +#[rpc] +pub trait GrandpaApi { + /// Returns the state of the current best round state as well as the + /// ongoing background rounds. + #[rpc(name = "grandpa_roundState")] + fn round_state(&self) -> FutureResult; +} + +/// Implements the GrandpaApi RPC trait for interacting with GRANDPA. +pub struct GrandpaRpcHandler { + authority_set: AuthoritySet, + voter_state: VoterState, +} + +impl GrandpaRpcHandler { + /// Creates a new GrandpaRpcHander instance. + pub fn new(authority_set: AuthoritySet, voter_state: VoterState) -> Self { + Self { + authority_set, + voter_state, + } + } +} + +impl GrandpaApi for GrandpaRpcHandler +where + VoterState: ReportVoterState + Send + Sync + 'static, + AuthoritySet: ReportAuthoritySet + Send + Sync + 'static, +{ + fn round_state(&self) -> FutureResult { + let round_states = ReportedRoundStates::from(&self.authority_set, &self.voter_state); + let future = async move { round_states }.boxed(); + Box::new(future.map_err(jsonrpc_core::Error::from).compat()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use jsonrpc_core::IoHandler; + use sc_finality_grandpa::{report, AuthorityId}; + use sp_core::crypto::Public; + use std::{collections::HashSet, convert::TryInto}; + + struct TestAuthoritySet; + struct TestVoterState; + struct EmptyVoterState; + + fn voters() -> HashSet { + let voter_id_1 = AuthorityId::from_slice(&[1; 32]); + let voter_id_2 = AuthorityId::from_slice(&[2; 32]); + + vec![voter_id_1, voter_id_2].into_iter().collect() + } + + impl ReportAuthoritySet for TestAuthoritySet { + fn get(&self) -> (u64, HashSet) { + (1, voters()) + } + } + + impl ReportVoterState for EmptyVoterState { + fn get(&self) -> Option> { + None + } + } + + impl ReportVoterState for TestVoterState { + fn get(&self) -> Option> { + let voter_id_1 = AuthorityId::from_slice(&[1; 32]); + let voters_best: HashSet<_> = vec![voter_id_1].into_iter().collect(); + + let best_round_state = report::RoundState { + total_weight: 100_u64.try_into().unwrap(), + threshold_weight: 67_u64.try_into().unwrap(), + prevote_current_weight: 50.into(), + prevote_ids: voters_best, + precommit_current_weight: 0.into(), + precommit_ids: HashSet::new(), + }; + + let past_round_state = report::RoundState { + total_weight: 100_u64.try_into().unwrap(), + threshold_weight: 67_u64.try_into().unwrap(), + prevote_current_weight: 100.into(), + prevote_ids: voters(), + precommit_current_weight: 100.into(), + precommit_ids: voters(), + }; + + let background_rounds = vec![(1, past_round_state)].into_iter().collect(); + + Some(report::VoterState { + background_rounds, + best_round: (2, best_round_state), + }) + } + } + + #[test] + fn uninitialized_rpc_handler() { + let handler = GrandpaRpcHandler::new(TestAuthoritySet, EmptyVoterState); + let mut io = IoHandler::new(); + io.extend_with(GrandpaApi::to_delegate(handler)); + + let request = r#"{"jsonrpc":"2.0","method":"grandpa_roundState","params":[],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","error":{"code":1,"message":"GRANDPA RPC endpoint not ready"},"id":1}"#; + + assert_eq!(Some(response.into()), io.handle_request_sync(request)); + } + + #[test] + fn working_rpc_handler() { + let handler = GrandpaRpcHandler::new(TestAuthoritySet, TestVoterState); + let mut io = IoHandler::new(); + io.extend_with(GrandpaApi::to_delegate(handler)); + + let request = r#"{"jsonrpc":"2.0","method":"grandpa_roundState","params":[],"id":1}"#; + let response = "{\"jsonrpc\":\"2.0\",\"result\":{\ + \"background\":[{\ + \"precommits\":{\"currentWeight\":100,\"missing\":[]},\ + \"prevotes\":{\"currentWeight\":100,\"missing\":[]},\ + \"round\":1,\"thresholdWeight\":67,\"totalWeight\":100\ + }],\ + \"best\":{\ + \"precommits\":{\"currentWeight\":0,\"missing\":[\"5C62Ck4UrFPiBtoCmeSrgF7x9yv9mn38446dhCpsi2mLHiFT\",\"5C7LYpP2ZH3tpKbvVvwiVe54AapxErdPBbvkYhe6y9ZBkqWt\"]},\ + \"prevotes\":{\"currentWeight\":50,\"missing\":[\"5C7LYpP2ZH3tpKbvVvwiVe54AapxErdPBbvkYhe6y9ZBkqWt\"]},\ + \"round\":2,\"thresholdWeight\":67,\"totalWeight\":100\ + },\ + \"setId\":1\ + },\"id\":1}"; + + assert_eq!(io.handle_request_sync(request), Some(response.into())); + } +} diff --git a/client/finality-grandpa/rpc/src/report.rs b/client/finality-grandpa/rpc/src/report.rs new file mode 100644 index 0000000000000000000000000000000000000000..a635728cb938adf73d4ae94e1db1a63d5fcb9f50 --- /dev/null +++ b/client/finality-grandpa/rpc/src/report.rs @@ -0,0 +1,161 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use std::{ + collections::{BTreeSet, HashSet}, + fmt::Debug, + ops::Add, +}; + +use serde::{Deserialize, Serialize}; + +use sc_finality_grandpa::{report, AuthorityId, SharedAuthoritySet, SharedVoterState}; + +use crate::error::Error; + +/// Utility trait to get reporting data for the current GRANDPA authority set. +pub trait ReportAuthoritySet { + fn get(&self) -> (u64, HashSet); +} + +/// Utility trait to get reporting data for the current GRANDPA voter state. +pub trait ReportVoterState { + fn get(&self) -> Option>; +} + +impl ReportAuthoritySet for SharedAuthoritySet +where + N: Add + Ord + Clone + Debug, + H: Clone + Debug + Eq, +{ + fn get(&self) -> (u64, HashSet) { + let current_voters: HashSet = self + .current_authorities() + .iter() + .map(|p| p.0.clone()) + .collect(); + + (self.set_id(), current_voters) + } +} + +impl ReportVoterState for SharedVoterState { + fn get(&self) -> Option> { + self.voter_state() + } +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct Prevotes { + current_weight: u32, + missing: BTreeSet, +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct Precommits { + current_weight: u32, + missing: BTreeSet, +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct RoundState { + round: u32, + total_weight: u32, + threshold_weight: u32, + prevotes: Prevotes, + precommits: Precommits, +} + +impl RoundState { + fn from( + round: u64, + round_state: &report::RoundState, + voters: &HashSet, + ) -> Result { + use std::convert::TryInto; + + let prevotes = &round_state.prevote_ids; + let missing_prevotes = voters.difference(&prevotes).cloned().collect(); + + let precommits = &round_state.precommit_ids; + let missing_precommits = voters.difference(&precommits).cloned().collect(); + + Ok(Self { + round: round.try_into()?, + total_weight: round_state.total_weight.get().try_into()?, + threshold_weight: round_state.threshold_weight.get().try_into()?, + prevotes: Prevotes { + current_weight: round_state.prevote_current_weight.0.try_into()?, + missing: missing_prevotes, + }, + precommits: Precommits { + current_weight: round_state.precommit_current_weight.0.try_into()?, + missing: missing_precommits, + }, + }) + } +} + +/// The state of the current best round, as well as the background rounds in a +/// form suitable for serialization. +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ReportedRoundStates { + set_id: u32, + best: RoundState, + background: Vec, +} + +impl ReportedRoundStates { + pub fn from( + authority_set: &AuthoritySet, + voter_state: &VoterState, + ) -> Result + where + AuthoritySet: ReportAuthoritySet, + VoterState: ReportVoterState, + { + use std::convert::TryFrom; + + let voter_state = voter_state.get().ok_or(Error::EndpointNotReady)?; + + let (set_id, current_voters) = authority_set.get(); + let set_id = + u32::try_from(set_id).map_err(|_| Error::AuthoritySetIdReportedAsUnreasonablyLarge)?; + + let best = { + let (round, round_state) = voter_state.best_round; + RoundState::from(round, &round_state, ¤t_voters)? + }; + + let background = voter_state + .background_rounds + .iter() + .map(|(round, round_state)| RoundState::from(*round, round_state, ¤t_voters)) + .collect::, Error>>()?; + + Ok(Self { + set_id, + best, + background, + }) + } +} diff --git a/client/finality-grandpa/src/authorities.rs b/client/finality-grandpa/src/authorities.rs index 4709216ebef2c745148c2da207a93ea5cfd0ef0e..b4cb254864df7f3150451939e5759e7122b68ca6 100644 --- a/client/finality-grandpa/src/authorities.rs +++ b/client/finality-grandpa/src/authorities.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Utilities for dealing with authorities, authority sets, and handoffs. @@ -20,7 +22,7 @@ use fork_tree::ForkTree; use parking_lot::RwLock; use finality_grandpa::voter_set::VoterSet; use parity_scale_codec::{Encode, Decode}; -use log::{debug, info}; +use log::debug; use sc_telemetry::{telemetry, CONSENSUS_INFO}; use sp_finality_grandpa::{AuthorityId, AuthorityList}; @@ -29,8 +31,17 @@ use std::fmt::Debug; use std::ops::Add; use std::sync::Arc; +/// Error type returned on operations on the `AuthoritySet`. +#[derive(Debug, derive_more::Display, derive_more::From)] +pub enum Error { + #[display("Invalid authority set, either empty or with an authority weight set to 0.")] + InvalidAuthoritySet, + #[display(fmt = "Invalid operation in the pending changes tree: {}", _0)] + ForkTree(fork_tree::Error), +} + /// A shared authority set. -pub(crate) struct SharedAuthoritySet { +pub struct SharedAuthoritySet { inner: Arc>>, } @@ -58,13 +69,17 @@ where N: Add + Ord + Clone + Debug, } /// Get the current set ID. This is incremented every time the set changes. - pub(crate) fn set_id(&self) -> u64 { + pub fn set_id(&self) -> u64 { self.inner.read().set_id } /// Get the current authorities and their weights (for the current set ID). - pub(crate) fn current_authorities(&self) -> VoterSet { - self.inner.read().current_authorities.iter().cloned().collect() + pub fn current_authorities(&self) -> VoterSet { + VoterSet::new(self.inner.read().current_authorities.iter().cloned()).expect( + "current_authorities is non-empty and weights are non-zero; \ + constructor and all mutating operations on `AuthoritySet` ensure this; \ + qed.", + ) } } @@ -87,30 +102,60 @@ pub(crate) struct Status { /// A set of authorities. #[derive(Debug, Clone, Encode, Decode, PartialEq)] pub(crate) struct AuthoritySet { + /// The current active authorities. pub(crate) current_authorities: AuthorityList, + /// The current set id. pub(crate) set_id: u64, - // Tree of pending standard changes across forks. Standard changes are - // enacted on finality and must be enacted (i.e. finalized) in-order across - // a given branch + /// Tree of pending standard changes across forks. Standard changes are + /// enacted on finality and must be enacted (i.e. finalized) in-order across + /// a given branch pub(crate) pending_standard_changes: ForkTree>, - // Pending forced changes across different forks (at most one per fork). - // Forced changes are enacted on block depth (not finality), for this reason - // only one forced change should exist per fork. - pub(crate) pending_forced_changes: Vec>, + /// Pending forced changes across different forks (at most one per fork). + /// Forced changes are enacted on block depth (not finality), for this reason + /// only one forced change should exist per fork. + pending_forced_changes: Vec>, } impl AuthoritySet where H: PartialEq, N: Ord, { + // authority sets must be non-empty and all weights must be greater than 0 + fn invalid_authority_list(authorities: &AuthorityList) -> bool { + authorities.is_empty() || authorities.iter().any(|(_, w)| *w == 0) + } + /// Get a genesis set with given authorities. - pub(crate) fn genesis(initial: AuthorityList) -> Self { - AuthoritySet { + pub(crate) fn genesis(initial: AuthorityList) -> Option { + if Self::invalid_authority_list(&initial) { + return None; + } + + Some(AuthoritySet { current_authorities: initial, set_id: 0, pending_standard_changes: ForkTree::new(), pending_forced_changes: Vec::new(), + }) + } + + /// Create a new authority set. + pub(crate) fn new( + authorities: AuthorityList, + set_id: u64, + pending_standard_changes: ForkTree>, + pending_forced_changes: Vec>, + ) -> Option { + if Self::invalid_authority_list(&authorities) { + return None; } + + Some(AuthoritySet { + current_authorities: authorities, + set_id, + pending_standard_changes, + pending_forced_changes, + }) } /// Get the current set id and a reference to the current authority set. @@ -121,16 +166,62 @@ where H: PartialEq, impl AuthoritySet where - N: Add + Ord + Clone + Debug, - H: Clone + Debug + N: Add + Ord + Clone + Debug, + H: Clone + Debug, { + /// Returns the block hash and height at which the next pending change in + /// the given chain (i.e. it includes `best_hash`) was signalled, `None` if + /// there are no pending changes for the given chain. + /// + /// This is useful since we know that when a change is signalled the + /// underlying runtime authority set management module (e.g. session module) + /// has updated its internal state (e.g. a new session started). + pub(crate) fn next_change( + &self, + best_hash: &H, + is_descendent_of: &F, + ) -> Result, fork_tree::Error> + where + F: Fn(&H, &H) -> Result, + E: std::error::Error, + { + let mut forced = None; + for change in &self.pending_forced_changes { + if is_descendent_of(&change.canon_hash, best_hash)? { + forced = Some((change.canon_hash.clone(), change.canon_height.clone())); + break; + } + } + + let mut standard = None; + for (_, _, change) in self.pending_standard_changes.roots() { + if is_descendent_of(&change.canon_hash, best_hash)? { + standard = Some((change.canon_hash.clone(), change.canon_height.clone())); + break; + } + } + + let earliest = match (forced, standard) { + (Some(forced), Some(standard)) => Some(if forced.1 < standard.1 { + forced + } else { + standard + }), + (Some(forced), None) => Some(forced), + (None, Some(standard)) => Some(standard), + (None, None) => None, + }; + + Ok(earliest) + } + fn add_standard_change( &mut self, pending: PendingChange, is_descendent_of: &F, - ) -> Result<(), fork_tree::Error> where + ) -> Result<(), Error> where F: Fn(&H, &H) -> Result, - E: std::error::Error, + E: std::error::Error, { let hash = pending.canon_hash.clone(); let number = pending.canon_height.clone(); @@ -140,8 +231,8 @@ where (&number, &hash), pending.delay); self.pending_standard_changes.import( - hash.clone(), - number.clone(), + hash, + number, pending, is_descendent_of, )?; @@ -159,15 +250,16 @@ where &mut self, pending: PendingChange, is_descendent_of: &F, - ) -> Result<(), fork_tree::Error> where + ) -> Result<(), Error> where F: Fn(&H, &H) -> Result, - E: std::error::Error, + E: std::error::Error, { for change in self.pending_forced_changes.iter() { if change.canon_hash == pending.canon_hash || - is_descendent_of(&change.canon_hash, &pending.canon_hash)? + is_descendent_of(&change.canon_hash, &pending.canon_hash) + .map_err(fork_tree::Error::Client)? { - return Err(fork_tree::Error::UnfinalizedAncestor); + return Err(fork_tree::Error::UnfinalizedAncestor.into()); } } @@ -201,10 +293,14 @@ where &mut self, pending: PendingChange, is_descendent_of: &F, - ) -> Result<(), fork_tree::Error> where + ) -> Result<(), Error> where F: Fn(&H, &H) -> Result, - E: std::error::Error, + E: std::error::Error, { + if Self::invalid_authority_list(&pending.next_authorities) { + return Err(Error::InvalidAuthoritySet); + } + match pending.delay_kind { DelayKind::Best { .. } => { self.add_forced_change(pending, is_descendent_of) @@ -250,6 +346,7 @@ where best_hash: H, best_number: N, is_descendent_of: &F, + initial_sync: bool, ) -> Result, E> where F: Fn(&H, &H) -> Result, { @@ -262,8 +359,10 @@ where // check if the given best block is in the same branch as the block that signaled the change. if is_descendent_of(&change.canon_hash, &best_hash)? { // apply this change: make the set canonical - info!(target: "afg", "👴 Applying authority set change forced at block #{:?}", - change.canon_height); + afg_log!(initial_sync, + "👴 Applying authority set change forced at block #{:?}", + change.canon_height, + ); telemetry!(CONSENSUS_INFO; "afg.applying_forced_authority_set_change"; "block" => ?change.canon_height ); @@ -305,9 +404,10 @@ where finalized_hash: H, finalized_number: N, is_descendent_of: &F, - ) -> Result, fork_tree::Error> - where F: Fn(&H, &H) -> Result, - E: std::error::Error, + initial_sync: bool, + ) -> Result, Error> where + F: Fn(&H, &H) -> Result, + E: std::error::Error, { let mut status = Status { changed: false, @@ -328,8 +428,10 @@ where self.pending_forced_changes.clear(); if let Some(change) = change { - info!(target: "afg", "👴 Applying authority set change scheduled at block #{:?}", - change.canon_height); + afg_log!(initial_sync, + "👴 Applying authority set change scheduled at block #{:?}", + change.canon_height, + ); telemetry!(CONSENSUS_INFO; "afg.applying_scheduled_authority_set_change"; "block" => ?change.canon_height ); @@ -364,16 +466,16 @@ where finalized_hash: H, finalized_number: N, is_descendent_of: &F, - ) -> Result, fork_tree::Error> - where F: Fn(&H, &H) -> Result, - E: std::error::Error, + ) -> Result, Error> where + F: Fn(&H, &H) -> Result, + E: std::error::Error, { self.pending_standard_changes.finalizes_any_with_descendent_if( &finalized_hash, finalized_number.clone(), is_descendent_of, |change| change.effective_number() == finalized_number - ) + ).map_err(Error::ForkTree) } } @@ -451,8 +553,10 @@ mod tests { #[test] fn current_limit_filters_min() { + let current_authorities = vec![(AuthorityId::from_slice(&[1; 32]), 1)]; + let mut authorities = AuthoritySet { - current_authorities: Vec::new(), + current_authorities: current_authorities.clone(), set_id: 0, pending_standard_changes: ForkTree::new(), pending_forced_changes: Vec::new(), @@ -460,7 +564,7 @@ mod tests { let change = |height| { PendingChange { - next_authorities: Vec::new(), + next_authorities: current_authorities.clone(), delay: 0, canon_height: height, canon_hash: height.to_string(), @@ -496,15 +600,17 @@ mod tests { #[test] fn changes_iterated_in_pre_order() { + let current_authorities = vec![(AuthorityId::from_slice(&[1; 32]), 1)]; + let mut authorities = AuthoritySet { - current_authorities: Vec::new(), + current_authorities: current_authorities.clone(), set_id: 0, pending_standard_changes: ForkTree::new(), pending_forced_changes: Vec::new(), }; let change_a = PendingChange { - next_authorities: Vec::new(), + next_authorities: current_authorities.clone(), delay: 10, canon_height: 5, canon_hash: "hash_a", @@ -512,7 +618,7 @@ mod tests { }; let change_b = PendingChange { - next_authorities: Vec::new(), + next_authorities: current_authorities.clone(), delay: 0, canon_height: 5, canon_hash: "hash_b", @@ -520,7 +626,7 @@ mod tests { }; let change_c = PendingChange { - next_authorities: Vec::new(), + next_authorities: current_authorities.clone(), delay: 5, canon_height: 10, canon_hash: "hash_c", @@ -537,7 +643,7 @@ mod tests { // forced changes are iterated last let change_d = PendingChange { - next_authorities: Vec::new(), + next_authorities: current_authorities.clone(), delay: 2, canon_height: 1, canon_hash: "hash_d", @@ -545,7 +651,7 @@ mod tests { }; let change_e = PendingChange { - next_authorities: Vec::new(), + next_authorities: current_authorities.clone(), delay: 2, canon_height: 0, canon_hash: "hash_e", @@ -599,11 +705,16 @@ mod tests { ); // finalizing "hash_c" won't enact the change signaled at "hash_a" but it will prune out "hash_b" - let status = authorities.apply_standard_changes("hash_c", 11, &is_descendent_of(|base, hash| match (*base, *hash) { - ("hash_a", "hash_c") => true, - ("hash_b", "hash_c") => false, - _ => unreachable!(), - })).unwrap(); + let status = authorities.apply_standard_changes( + "hash_c", + 11, + &is_descendent_of(|base, hash| match (*base, *hash) { + ("hash_a", "hash_c") => true, + ("hash_b", "hash_c") => false, + _ => unreachable!(), + }), + false, + ).unwrap(); assert!(status.changed); assert_eq!(status.new_set_block, None); @@ -613,10 +724,15 @@ mod tests { ); // finalizing "hash_d" will enact the change signaled at "hash_a" - let status = authorities.apply_standard_changes("hash_d", 15, &is_descendent_of(|base, hash| match (*base, *hash) { - ("hash_a", "hash_d") => true, - _ => unreachable!(), - })).unwrap(); + let status = authorities.apply_standard_changes( + "hash_d", + 15, + &is_descendent_of(|base, hash| match (*base, *hash) { + ("hash_a", "hash_d") => true, + _ => unreachable!(), + }), + false, + ).unwrap(); assert!(status.changed); assert_eq!(status.new_set_block, Some(("hash_d", 15))); @@ -671,12 +787,18 @@ mod tests { }); // trying to finalize past `change_c` without finalizing `change_a` first - match authorities.apply_standard_changes("hash_d", 40, &is_descendent_of) { - Err(fork_tree::Error::UnfinalizedAncestor) => {}, - _ => unreachable!(), - } + assert!(matches!( + authorities.apply_standard_changes("hash_d", 40, &is_descendent_of, false), + Err(Error::ForkTree(fork_tree::Error::UnfinalizedAncestor)) + )); + + let status = authorities.apply_standard_changes( + "hash_b", + 15, + &is_descendent_of, + false, + ).unwrap(); - let status = authorities.apply_standard_changes("hash_b", 15, &is_descendent_of).unwrap(); assert!(status.changed); assert_eq!(status.new_set_block, Some(("hash_b", 15))); @@ -684,7 +806,13 @@ mod tests { assert_eq!(authorities.set_id, 1); // after finalizing `change_a` it should be possible to finalize `change_c` - let status = authorities.apply_standard_changes("hash_d", 40, &is_descendent_of).unwrap(); + let status = authorities.apply_standard_changes( + "hash_d", + 40, + &is_descendent_of, + false, + ).unwrap(); + assert!(status.changed); assert_eq!(status.new_set_block, Some(("hash_d", 40))); @@ -817,20 +945,222 @@ mod tests { assert!(authorities.add_pending_change(change_c, &is_descendent_of_a).is_err()); // too early. - assert!(authorities.apply_forced_changes("hash_a10", 10, &static_is_descendent_of(true)).unwrap().is_none()); + assert!( + authorities.apply_forced_changes("hash_a10", 10, &static_is_descendent_of(true), false) + .unwrap() + .is_none() + ); // too late. - assert!(authorities.apply_forced_changes("hash_a16", 16, &static_is_descendent_of(true)).unwrap().is_none()); + assert!( + authorities.apply_forced_changes("hash_a16", 16, &static_is_descendent_of(true), false) + .unwrap() + .is_none() + ); // on time -- chooses the right change. assert_eq!( - authorities.apply_forced_changes("hash_a15", 15, &is_descendent_of_a).unwrap().unwrap(), + authorities.apply_forced_changes("hash_a15", 15, &is_descendent_of_a, false) + .unwrap() + .unwrap(), (42, AuthoritySet { current_authorities: set_a, set_id: 1, pending_standard_changes: ForkTree::new(), pending_forced_changes: Vec::new(), - }) + }), ); } + + #[test] + fn next_change_works() { + let current_authorities = vec![(AuthorityId::from_slice(&[1; 32]), 1)]; + + let mut authorities = AuthoritySet { + current_authorities: current_authorities.clone(), + set_id: 0, + pending_standard_changes: ForkTree::new(), + pending_forced_changes: Vec::new(), + }; + + let new_set = current_authorities.clone(); + + // We have three pending changes with 2 possible roots that are enacted + // immediately on finality (i.e. standard changes). + let change_a0 = PendingChange { + next_authorities: new_set.clone(), + delay: 0, + canon_height: 5, + canon_hash: "hash_a0", + delay_kind: DelayKind::Finalized, + }; + + let change_a1 = PendingChange { + next_authorities: new_set.clone(), + delay: 0, + canon_height: 10, + canon_hash: "hash_a1", + delay_kind: DelayKind::Finalized, + }; + + let change_b = PendingChange { + next_authorities: new_set.clone(), + delay: 0, + canon_height: 4, + canon_hash: "hash_b", + delay_kind: DelayKind::Finalized, + }; + + // A0 (#5) <- A10 (#8) <- A1 (#10) <- best_a + // B (#4) <- best_b + let is_descendent_of = is_descendent_of(|base, hash| match (*base, *hash) { + ("hash_a0", "hash_a1") => true, + ("hash_a0", "best_a") => true, + ("hash_a1", "best_a") => true, + ("hash_a10", "best_a") => true, + ("hash_b", "best_b") => true, + _ => false, + }); + + // add the three pending changes + authorities + .add_pending_change(change_b, &is_descendent_of) + .unwrap(); + authorities + .add_pending_change(change_a0, &is_descendent_of) + .unwrap(); + authorities + .add_pending_change(change_a1, &is_descendent_of) + .unwrap(); + + // the earliest change at block `best_a` should be the change at A0 (#5) + assert_eq!( + authorities + .next_change(&"best_a", &is_descendent_of) + .unwrap(), + Some(("hash_a0", 5)), + ); + + // the earliest change at block `best_b` should be the change at B (#4) + assert_eq!( + authorities + .next_change(&"best_b", &is_descendent_of) + .unwrap(), + Some(("hash_b", 4)), + ); + + // we apply the change at A0 which should prune it and the fork at B + authorities + .apply_standard_changes("hash_a0", 5, &is_descendent_of, false) + .unwrap(); + + // the next change is now at A1 (#10) + assert_eq!( + authorities + .next_change(&"best_a", &is_descendent_of) + .unwrap(), + Some(("hash_a1", 10)), + ); + + // there's no longer any pending change at `best_b` fork + assert_eq!( + authorities + .next_change(&"best_b", &is_descendent_of) + .unwrap(), + None, + ); + + // we a forced change at A10 (#8) + let change_a10 = PendingChange { + next_authorities: new_set.clone(), + delay: 0, + canon_height: 8, + canon_hash: "hash_a10", + delay_kind: DelayKind::Best { + median_last_finalized: 0, + }, + }; + + authorities + .add_pending_change(change_a10, &static_is_descendent_of(false)) + .unwrap(); + + // it should take precedence over the change at A1 (#10) + assert_eq!( + authorities + .next_change(&"best_a", &is_descendent_of) + .unwrap(), + Some(("hash_a10", 8)), + ); + } + + #[test] + fn maintains_authority_list_invariants() { + // empty authority lists are invalid + assert_eq!(AuthoritySet::<(), ()>::genesis(vec![]), None); + assert_eq!( + AuthoritySet::<(), ()>::new(vec![], 0, ForkTree::new(), Vec::new()), + None, + ); + + let invalid_authorities_weight = vec![ + (AuthorityId::from_slice(&[1; 32]), 5), + (AuthorityId::from_slice(&[2; 32]), 0), + ]; + + // authority weight of zero is invalid + assert_eq!( + AuthoritySet::<(), ()>::genesis(invalid_authorities_weight.clone()), + None + ); + assert_eq!( + AuthoritySet::<(), ()>::new( + invalid_authorities_weight.clone(), + 0, + ForkTree::new(), + Vec::new() + ), + None, + ); + + let mut authority_set = + AuthoritySet::<(), u64>::genesis(vec![(AuthorityId::from_slice(&[1; 32]), 5)]).unwrap(); + + let invalid_change_empty_authorities = PendingChange { + next_authorities: vec![], + delay: 10, + canon_height: 5, + canon_hash: (), + delay_kind: DelayKind::Finalized, + }; + + // pending change contains an empty authority set + assert!(matches!( + authority_set.add_pending_change( + invalid_change_empty_authorities.clone(), + &static_is_descendent_of(false) + ), + Err(Error::InvalidAuthoritySet) + )); + + let invalid_change_authorities_weight = PendingChange { + next_authorities: invalid_authorities_weight, + delay: 10, + canon_height: 5, + canon_hash: (), + delay_kind: DelayKind::Best { + median_last_finalized: 0, + }, + }; + + // pending change contains an an authority set + // where one authority has weight of 0 + assert!(matches!( + authority_set.add_pending_change( + invalid_change_authorities_weight, + &static_is_descendent_of(false) + ), + Err(Error::InvalidAuthoritySet) + )); + } } diff --git a/client/finality-grandpa/src/aux_schema.rs b/client/finality-grandpa/src/aux_schema.rs index 525a4a99bab5861e57b6fc25b49bbcaccaea7220..4ed96d058ac6b42941705c046984852fdea0b795 100644 --- a/client/finality-grandpa/src/aux_schema.rs +++ b/client/finality-grandpa/src/aux_schema.rs @@ -97,12 +97,14 @@ where H: Clone + Debug + PartialEq, } } - AuthoritySet { - current_authorities: self.current_authorities, - set_id: self.set_id, - pending_forced_changes: Vec::new(), - pending_standard_changes - } + let authority_set = AuthoritySet::new( + self.current_authorities, + self.set_id, + pending_standard_changes, + Vec::new(), + ); + + authority_set.expect("current_authorities is non-empty and weights are non-zero; qed.") } } @@ -152,7 +154,7 @@ fn migrate_from_version0( None => (0, genesis_round()), }; - let set_id = new_set.current().0; + let set_id = new_set.set_id; let base = last_round_state.prevote_ghost .expect("state is for completed round; completed rounds must have a prevote ghost; qed."); @@ -199,7 +201,7 @@ fn migrate_from_version1( backend, AUTHORITY_SET_KEY, )? { - let set_id = set.current().0; + let set_id = set.set_id; let completed_rounds = |number, state, base| CompletedRounds::new( CompletedRound { @@ -310,7 +312,7 @@ pub(crate) fn load_persistent( .expect("state is for completed round; completed rounds must have a prevote ghost; qed."); VoterSetState::live( - set.current().0, + set.set_id, &set, base, ) @@ -326,15 +328,16 @@ pub(crate) fn load_persistent( } Some(other) => return Err(ClientError::Backend( format!("Unsupported GRANDPA DB version: {:?}", other) - ).into()), + )), } // genesis. - info!(target: "afg", "Loading GRANDPA authority set \ + info!(target: "afg", "👴 Loading GRANDPA authority set \ from genesis on what appears to be first startup."); let genesis_authorities = genesis_authorities()?; - let genesis_set = AuthoritySet::genesis(genesis_authorities.clone()); + let genesis_set = AuthoritySet::genesis(genesis_authorities) + .expect("genesis authorities is non-empty; all weights are non-zero; qed."); let state = make_genesis_round(); let base = state.prevote_ghost .expect("state is for completed round; completed rounds must have a prevote ghost; qed."); @@ -503,12 +506,12 @@ mod test { assert_eq!( *authority_set.inner().read(), - AuthoritySet { - current_authorities: authorities.clone(), - pending_standard_changes: ForkTree::new(), - pending_forced_changes: Vec::new(), + AuthoritySet::new( + authorities.clone(), set_id, - }, + ForkTree::new(), + Vec::new(), + ).unwrap(), ); let mut current_rounds = CurrentRounds::new(); @@ -547,12 +550,12 @@ mod test { }; { - let authority_set = AuthoritySet:: { - current_authorities: authorities.clone(), - pending_standard_changes: ForkTree::new(), - pending_forced_changes: Vec::new(), + let authority_set = AuthoritySet::::new( + authorities.clone(), set_id, - }; + ForkTree::new(), + Vec::new(), + ).unwrap(); let voter_set_state = V1VoterSetState::Live(round_number, round_state.clone()); @@ -593,12 +596,12 @@ mod test { assert_eq!( *authority_set.inner().read(), - AuthoritySet { - current_authorities: authorities.clone(), - pending_standard_changes: ForkTree::new(), - pending_forced_changes: Vec::new(), + AuthoritySet::new( + authorities.clone(), set_id, - }, + ForkTree::new(), + Vec::new(), + ).unwrap(), ); let mut current_rounds = CurrentRounds::new(); diff --git a/client/finality-grandpa/src/communication/gossip.rs b/client/finality-grandpa/src/communication/gossip.rs index 2d39ed7ec433fa2fc9e4f931e1916e922328137d..7d9fe4e7f2da16f95c849730132ce76aadd65189 100644 --- a/client/finality-grandpa/src/communication/gossip.rs +++ b/client/finality-grandpa/src/communication/gossip.rs @@ -110,7 +110,7 @@ const CATCH_UP_THRESHOLD: u64 = 2; const PROPAGATION_ALL: u32 = 4; //in rounds; const PROPAGATION_ALL_AUTHORITIES: u32 = 2; //in rounds; const PROPAGATION_SOME_NON_AUTHORITIES: u32 = 3; //in rounds; -const ROUND_DURATION: u32 = 4; // measured in gossip durations +const ROUND_DURATION: u32 = 2; // measured in gossip durations const MIN_LUCKY: usize = 5; @@ -181,15 +181,27 @@ impl View { } } -/// A local view of protocol state. Only differs from `View` in that we also -/// track the round and set id at which the last commit was observed. +/// A local view of protocol state. Similar to `View` but we additionally track +/// the round and set id at which the last commit was observed, and the instant +/// at which the current round started. struct LocalView { round: Round, set_id: SetId, last_commit: Option<(N, Round, SetId)>, + round_start: Instant, } impl LocalView { + /// Creates a new `LocalView` at the given set id and round. + fn new(set_id: SetId, round: Round) -> LocalView { + LocalView { + set_id, + round, + last_commit: None, + round_start: Instant::now(), + } + } + /// Converts the local view to a `View` discarding round and set id /// information about the last commit. fn as_view(&self) -> View<&N> { @@ -205,9 +217,16 @@ impl LocalView { if set_id != self.set_id { self.set_id = set_id; self.round = Round(1); + self.round_start = Instant::now(); } } + /// Updates the current round. + fn update_round(&mut self, round: Round) { + self.round = round; + self.round_start = Instant::now(); + } + /// Returns the height of the block that the last observed commit finalizes. fn last_commit_height(&self) -> Option<&N> { self.last_commit.as_ref().map(|(number, _, _)| number) @@ -656,7 +675,6 @@ struct Inner { local_view: Option>>, peers: Peers>, live_topics: KeepTopics, - round_start: Instant, authorities: Vec, config: crate::Config, next_rebroadcast: Instant, @@ -689,7 +707,6 @@ impl Inner { local_view: None, peers: Peers::default(), live_topics: KeepTopics::new(), - round_start: Instant::now(), next_rebroadcast: Instant::now() + REBROADCAST_AFTER, authorities: Vec::new(), pending_catch_up: PendingCatchUp::None, @@ -715,10 +732,9 @@ impl Inner { debug!(target: "afg", "Voter {} noting beginning of round {:?} to network.", self.config.name(), (round, set_id)); - local_view.round = round; + local_view.update_round(round); self.live_topics.push(round, set_id); - self.round_start = Instant::now(); self.peers.reshuffle(); } self.multicast_neighbor_packet() @@ -729,13 +745,16 @@ impl Inner { fn note_set(&mut self, set_id: SetId, authorities: Vec) -> MaybeMessage { { let local_view = match self.local_view { - ref mut x @ None => x.get_or_insert(LocalView { - round: Round(1), + ref mut x @ None => x.get_or_insert(LocalView::new( set_id, - last_commit: None, - }), + Round(1), + )), Some(ref mut v) => if v.set_id == set_id { - if self.authorities != authorities { + let diff_authorities = + self.authorities.iter().collect::>() != + authorities.iter().collect(); + + if diff_authorities { debug!(target: "afg", "Gossip validator noted set {:?} twice with different authorities. \ Was the authority set hard forked?", @@ -814,7 +833,7 @@ impl Inner { return Action::Discard(cost::UNKNOWN_VOTER); } - if let Err(()) = super::check_message_sig::( + if !sp_finality_grandpa::check_message_signature( &full.message.message, &full.message.id, &full.message.signature, @@ -887,7 +906,7 @@ impl Inner { // any catch up requests until we import this one (either with a // success or failure). self.pending_catch_up = PendingCatchUp::Processing { - instant: instant.clone(), + instant: *instant, }; // always discard catch up messages, they're point-to-point @@ -1121,8 +1140,10 @@ impl Inner { /// underlying gossip layer, which should happen every 30 seconds. fn round_message_allowed(&self, who: &PeerId, peer: &PeerInfo) -> bool { let round_duration = self.config.gossip_duration * ROUND_DURATION; - let round_elapsed = self.round_start.elapsed(); - + let round_elapsed = match self.local_view { + Some(ref local_view) => local_view.round_start.elapsed(), + None => return false, + }; if !self.config.is_authority && round_elapsed < round_duration * PROPAGATION_ALL @@ -1185,7 +1206,10 @@ impl Inner { /// underlying gossip layer, which should happen every 30 seconds. fn global_message_allowed(&self, who: &PeerId, peer: &PeerInfo) -> bool { let round_duration = self.config.gossip_duration * ROUND_DURATION; - let round_elapsed = self.round_start.elapsed(); + let round_elapsed = match self.local_view { + Some(ref local_view) => local_view.round_start.elapsed(), + None => return false, + }; match peer.roles { ObservedRole::OurSentry | ObservedRole::OurGuardedAuthority => true, @@ -1281,7 +1305,7 @@ impl GossipValidator { inner: parking_lot::RwLock::new(Inner::new(config)), set_state, report_sender: tx, - metrics: metrics, + metrics, }; (val, rx) @@ -1618,7 +1642,10 @@ mod tests { use crate::environment::VoterSetState; let base = (H256::zero(), 0); - let voters = AuthoritySet::genesis(Vec::new()); + + let voters = vec![(AuthorityId::from_slice(&[1; 32]), 1)]; + let voters = AuthoritySet::genesis(voters).unwrap(); + let set_state = VoterSetState::live( 0, &voters, @@ -2317,7 +2344,8 @@ mod tests { let test = |num_round, peers| { // rewind n round durations - val.inner.write().round_start = Instant::now() - round_duration * num_round; + val.inner.write().local_view.as_mut().unwrap().round_start = + Instant::now() - round_duration * num_round; let mut message_allowed = val.message_allowed(); move || { @@ -2445,7 +2473,8 @@ mod tests { } { - val.inner.write().round_start = Instant::now() - round_duration * 4; + val.inner.write().local_view.as_mut().unwrap().round_start = + Instant::now() - round_duration * 4; let mut message_allowed = val.message_allowed(); // on the fourth round duration we should allow messages to authorities // (on the second we would do `sqrt(authorities)`) @@ -2595,12 +2624,12 @@ mod tests { fn allow_noting_different_authorities_for_same_set() { let (val, _) = GossipValidator::::new(config(), voter_set_state(), None); - let a1 = vec![AuthorityId::default()]; + let a1 = vec![AuthorityId::from_slice(&[0; 32])]; val.note_set(SetId(1), a1.clone(), |_, _| {}); assert_eq!(val.inner().read().authorities, a1); - let a2 = vec![AuthorityId::default(), AuthorityId::default()]; + let a2 = vec![AuthorityId::from_slice(&[1; 32]), AuthorityId::from_slice(&[2; 32])]; val.note_set(SetId(1), a2.clone(), |_, _| {}); assert_eq!(val.inner().read().authorities, a2); diff --git a/client/finality-grandpa/src/communication/mod.rs b/client/finality-grandpa/src/communication/mod.rs index 7daa121513416087b8c25d4664acc8e25acaffc4..b7bbad9f8e7c47058b2f38294ea8c0d76901d478 100644 --- a/client/finality-grandpa/src/communication/mod.rs +++ b/client/finality-grandpa/src/communication/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Communication streams for the polite-grandpa networking protocol. //! @@ -33,12 +35,12 @@ use parking_lot::Mutex; use prometheus_endpoint::Registry; use std::{pin::Pin, sync::Arc, task::{Context, Poll}}; +use sp_core::traits::BareCryptoStorePtr; use finality_grandpa::Message::{Prevote, Precommit, PrimaryPropose}; use finality_grandpa::{voter, voter_set::VoterSet}; use sc_network::{NetworkService, ReputationChange}; use sc_network_gossip::{GossipEngine, Network as GossipNetwork}; use parity_scale_codec::{Encode, Decode}; -use sp_core::Pair; use sp_runtime::traits::{Block as BlockT, Hash as HashT, Header as HeaderT, NumberFor}; use sc_telemetry::{telemetry, CONSENSUS_DEBUG, CONSENSUS_INFO}; @@ -56,7 +58,7 @@ use gossip::{ VoteMessage, }; use sp_finality_grandpa::{ - AuthorityPair, AuthorityId, AuthoritySignature, SetId as SetIdNumber, RoundNumber, + AuthorityId, AuthoritySignature, SetId as SetIdNumber, RoundNumber, }; use sp_utils::mpsc::TracingUnboundedReceiver; @@ -103,6 +105,34 @@ mod benefit { pub(super) const PER_EQUIVOCATION: i32 = 10; } +/// A type that ties together our local authority id and a keystore where it is +/// available for signing. +pub struct LocalIdKeystore((AuthorityId, BareCryptoStorePtr)); + +impl LocalIdKeystore { + /// Returns a reference to our local authority id. + fn local_id(&self) -> &AuthorityId { + &(self.0).0 + } + + /// Returns a reference to the keystore. + fn keystore(&self) -> &BareCryptoStorePtr { + &(self.0).1 + } +} + +impl AsRef for LocalIdKeystore { + fn as_ref(&self) -> &BareCryptoStorePtr { + self.keystore() + } +} + +impl From<(AuthorityId, BareCryptoStorePtr)> for LocalIdKeystore { + fn from(inner: (AuthorityId, BareCryptoStorePtr)) -> LocalIdKeystore { + LocalIdKeystore(inner) + } +} + /// If the voter set is larger than this value some telemetry events are not /// sent to avoid increasing usage resource on the node and flooding the /// telemetry server (e.g. received votes, received commits.) @@ -236,16 +266,14 @@ impl> NetworkBridge { let (neighbor_packet_worker, neighbor_packet_sender) = periodic::NeighborPacketWorker::new(); - let bridge = NetworkBridge { + NetworkBridge { service, gossip_engine, validator, neighbor_sender: neighbor_packet_sender, neighbor_packet_worker: Arc::new(Mutex::new(neighbor_packet_worker)), gossip_validator_report_stream: Arc::new(Mutex::new(report_stream)), - }; - - bridge + } } /// Note the beginning of a new round to the `GossipValidator`. @@ -258,7 +286,7 @@ impl> NetworkBridge { // is a no-op if currently in that set. self.validator.note_set( set_id, - voters.voters().iter().map(|(v, _)| v.clone()).collect(), + voters.iter().map(|(v, _)| v.clone()).collect(), |to, neighbor| self.neighbor_sender.send(to, neighbor), ); @@ -272,10 +300,10 @@ impl> NetworkBridge { /// network all within the current set. pub(crate) fn round_communication( &self, + keystore: Option, round: Round, set_id: SetId, voters: Arc>, - local_key: Option, has_voted: HasVoted, ) -> ( impl Stream> + Unpin, @@ -287,10 +315,10 @@ impl> NetworkBridge { &*voters, ); - let locals = local_key.and_then(|pair| { - let id = pair.public(); - if voters.contains_key(&id) { - Some((pair, id)) + let keystore = keystore.and_then(|ks| { + let id = ks.local_id(); + if voters.contains(id) { + Some(ks) } else { None } @@ -304,16 +332,16 @@ impl> NetworkBridge { match decoded { Err(ref e) => { debug!(target: "afg", "Skipping malformed message {:?}: {}", notification, e); - return future::ready(None); + future::ready(None) } Ok(GossipMessage::Vote(msg)) => { // check signature. - if !voters.contains_key(&msg.message.id) { + if !voters.contains(&msg.message.id) { debug!(target: "afg", "Skipping message from unknown voter {}", msg.message.id); return future::ready(None); } - if voters.len() <= TELEMETRY_VOTERS_LIMIT { + if voters.len().get() <= TELEMETRY_VOTERS_LIMIT { match &msg.message.message { PrimaryPropose(propose) => { telemetry!(CONSENSUS_INFO; "afg.received_propose"; @@ -343,17 +371,17 @@ impl> NetworkBridge { } _ => { debug!(target: "afg", "Skipping unknown message type"); - return future::ready(None); + future::ready(None) } } }); let (tx, out_rx) = mpsc::channel(0); let outgoing = OutgoingMessages:: { + keystore, round: round.0, set_id: set_id.0, network: self.gossip_engine.clone(), - locals, sender: tx, has_voted, }; @@ -378,7 +406,7 @@ impl> NetworkBridge { ) { self.validator.note_set( set_id, - voters.voters().iter().map(|(v, _)| v.clone()).collect(), + voters.iter().map(|(v, _)| v.clone()).collect(), |to, neighbor| self.neighbor_sender.send(to, neighbor), ); @@ -476,7 +504,7 @@ fn incoming_global( gossip_validator: &Arc>, voters: &VoterSet, | { - if voters.len() <= TELEMETRY_VOTERS_LIMIT { + if voters.len().get() <= TELEMETRY_VOTERS_LIMIT { let precommits_signed_by: Vec = msg.message.auth_data.iter().map(move |(_, a)| { format!("{}", a) @@ -610,30 +638,6 @@ impl> Clone for NetworkBridge { } } -/// Encode round message localized to a given round and set id. -pub(crate) fn localized_payload( - round: RoundNumber, - set_id: SetIdNumber, - message: &E, -) -> Vec { - let mut buf = Vec::new(); - localized_payload_with_buffer(round, set_id, message, &mut buf); - buf -} - -/// Encode round message localized to a given round and set id using the given -/// buffer. The given buffer will be cleared and the resulting encoded payload -/// will always be written to the start of the buffer. -pub(crate) fn localized_payload_with_buffer( - round: RoundNumber, - set_id: SetIdNumber, - message: &E, - buf: &mut Vec, -) { - buf.clear(); - (message, round, set_id).encode_to(buf) -} - /// Type-safe wrapper around a round number. #[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Encode, Decode)] pub struct Round(pub RoundNumber); @@ -642,48 +646,6 @@ pub struct Round(pub RoundNumber); #[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Encode, Decode)] pub struct SetId(pub SetIdNumber); -/// Check a message signature by encoding the message as a localized payload and -/// verifying the provided signature using the expected authority id. -pub(crate) fn check_message_sig( - message: &Message, - id: &AuthorityId, - signature: &AuthoritySignature, - round: RoundNumber, - set_id: SetIdNumber, -) -> Result<(), ()> { - check_message_sig_with_buffer::( - message, - id, - signature, - round, - set_id, - &mut Vec::new(), - ) -} - -/// Check a message signature by encoding the message as a localized payload and -/// verifying the provided signature using the expected authority id. -/// The encoding necessary to verify the signature will be done using the given -/// buffer, the original content of the buffer will be cleared. -pub(crate) fn check_message_sig_with_buffer( - message: &Message, - id: &AuthorityId, - signature: &AuthoritySignature, - round: RoundNumber, - set_id: SetIdNumber, - buf: &mut Vec, -) -> Result<(), ()> { - let as_public = id.clone(); - localized_payload_with_buffer(round, set_id, message, buf); - - if AuthorityPair::verify(signature, buf, &as_public) { - Ok(()) - } else { - debug!(target: "afg", "Bad signature on message from {:?}", id); - Err(()) - } -} - /// A sink for outgoing messages to the network. Any messages that are sent will /// be replaced, as appropriate, according to the given `HasVoted`. /// NOTE: The votes are stored unsigned, which means that the signatures need to @@ -694,7 +656,7 @@ pub(crate) fn check_message_sig_with_buffer( pub(crate) struct OutgoingMessages { round: RoundNumber, set_id: SetIdNumber, - locals: Option<(AuthorityPair, AuthorityId)>, + keystore: Option, sender: mpsc::Sender>, network: Arc>>, has_voted: HasVoted, @@ -731,16 +693,19 @@ impl Sink> for OutgoingMessages } // when locals exist, sign messages on import - if let Some((ref pair, ref local_id)) = self.locals { - let encoded = localized_payload(self.round, self.set_id, &msg); - let signature = pair.sign(&encoded[..]); - - let target_hash = msg.target().0.clone(); - let signed = SignedMessage:: { - message: msg, - signature, - id: local_id.clone(), - }; + if let Some(ref keystore) = self.keystore { + let target_hash = *(msg.target().0); + let signed = sp_finality_grandpa::sign_message( + keystore.as_ref(), + msg, + keystore.local_id().clone(), + self.round, + self.set_id, + ).ok_or( + Error::Signing(format!( + "Failed to sign GRANDPA vote for round {} targetting {:?}", self.round, target_hash + )) + )?; let message = GossipMessage::Vote(VoteMessage:: { message: signed.clone(), @@ -799,13 +764,13 @@ fn check_compact_commit( ) -> Result<(), ReputationChange> { // 4f + 1 = equivocations from f voters. let f = voters.total_weight() - voters.threshold(); - let full_threshold = voters.total_weight() + f; + let full_threshold = (f + voters.total_weight()).0; // check total weight is not out of range. let mut total_weight = 0; for (_, ref id) in &msg.auth_data { - if let Some(weight) = voters.info(id).map(|info| info.weight()) { - total_weight += weight; + if let Some(weight) = voters.get(id).map(|info| info.weight()) { + total_weight += weight.get(); if total_weight > full_threshold { return Err(cost::MALFORMED_COMMIT); } @@ -815,7 +780,7 @@ fn check_compact_commit( } } - if total_weight < voters.threshold() { + if total_weight < voters.threshold().get() { return Err(cost::MALFORMED_COMMIT); } @@ -828,7 +793,7 @@ fn check_compact_commit( use crate::communication::gossip::Misbehavior; use finality_grandpa::Message as GrandpaMessage; - if let Err(()) = check_message_sig_with_buffer::( + if !sp_finality_grandpa::check_message_signature_with_buffer( &GrandpaMessage::Precommit(precommit.clone()), id, sig, @@ -860,7 +825,7 @@ fn check_catch_up( ) -> Result<(), ReputationChange> { // 4f + 1 = equivocations from f voters. let f = voters.total_weight() - voters.threshold(); - let full_threshold = voters.total_weight() + f; + let full_threshold = (f + voters.total_weight()).0; // check total weight is not out of range for a set of votes. fn check_weight<'a>( @@ -871,8 +836,8 @@ fn check_catch_up( let mut total_weight = 0; for id in votes { - if let Some(weight) = voters.info(&id).map(|info| info.weight()) { - total_weight += weight; + if let Some(weight) = voters.get(&id).map(|info| info.weight()) { + total_weight += weight.get(); if total_weight > full_threshold { return Err(cost::MALFORMED_CATCH_UP); } @@ -882,7 +847,7 @@ fn check_catch_up( } } - if total_weight < voters.threshold() { + if total_weight < voters.threshold().get() { return Err(cost::MALFORMED_CATCH_UP); } @@ -916,7 +881,7 @@ fn check_catch_up( for (msg, id, sig) in messages { signatures_checked += 1; - if let Err(()) = check_message_sig_with_buffer::( + if !sp_finality_grandpa::check_message_signature_with_buffer( &msg, id, sig, diff --git a/client/finality-grandpa/src/communication/periodic.rs b/client/finality-grandpa/src/communication/periodic.rs index f894624bdf79e6e000f7a113c804517633301cb9..dadd7deb57fca1d34dd01baf0d434533f1a99fbe 100644 --- a/client/finality-grandpa/src/communication/periodic.rs +++ b/client/finality-grandpa/src/communication/periodic.rs @@ -86,7 +86,7 @@ impl Stream for NeighborPacketWorker { this.delay.reset(REBROADCAST_AFTER); this.last = Some((to.clone(), packet.clone())); - return Poll::Ready(Some((to, GossipMessage::::from(packet.clone())))); + return Poll::Ready(Some((to, GossipMessage::::from(packet)))); } // Don't return yet, maybe the timer fired. Poll::Pending => {}, @@ -108,6 +108,6 @@ impl Stream for NeighborPacketWorker { return Poll::Ready(Some((to.clone(), GossipMessage::::from(packet.clone())))); } - return Poll::Pending; + Poll::Pending } } diff --git a/client/finality-grandpa/src/communication/tests.rs b/client/finality-grandpa/src/communication/tests.rs index ea995eff6390dd789632b0635fdd21b598561478..273804f7a45080a84c2a3bc39c2c97dbffbeedb6 100644 --- a/client/finality-grandpa/src/communication/tests.rs +++ b/client/finality-grandpa/src/communication/tests.rs @@ -29,7 +29,7 @@ use std::{borrow::Cow, pin::Pin, task::{Context, Poll}}; use crate::environment::SharedVoterSetState; use sp_finality_grandpa::{AuthorityList, GRANDPA_ENGINE_ID}; use super::gossip::{self, GossipValidator}; -use super::{AuthorityId, VoterSet, Round, SetId}; +use super::{VoterSet, Round, SetId}; #[derive(Debug)] pub(crate) enum Event { @@ -142,11 +142,15 @@ fn voter_set_state() -> SharedVoterSetState { use crate::authorities::AuthoritySet; use crate::environment::VoterSetState; use finality_grandpa::round::State as RoundState; - use sp_core::H256; + use sp_core::{crypto::Public, H256}; + use sp_finality_grandpa::AuthorityId; let state = RoundState::genesis((H256::zero(), 0)); let base = state.prevote_ghost.unwrap(); - let voters = AuthoritySet::genesis(Vec::new()); + + let voters = vec![(AuthorityId::from_slice(&[1; 32]), 1)]; + let voters = AuthoritySet::genesis(voters).unwrap(); + let set_state = VoterSetState::live( 0, &voters, @@ -212,7 +216,7 @@ impl sc_network_gossip::ValidatorContext for NoopContext { fn good_commit_leads_to_relay() { let private = [Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; let public = make_ids(&private[..]); - let voter_set = Arc::new(public.iter().cloned().collect::>()); + let voter_set = Arc::new(VoterSet::new(public.iter().cloned()).unwrap()); let round = 1; let set_id = 1; @@ -222,7 +226,7 @@ fn good_commit_leads_to_relay() { let target_number = 500; let precommit = finality_grandpa::Precommit { target_hash: target_hash.clone(), target_number }; - let payload = super::localized_payload( + let payload = sp_finality_grandpa::localized_payload( round, set_id, &finality_grandpa::Message::Precommit(precommit.clone()) ); @@ -360,7 +364,7 @@ fn bad_commit_leads_to_report() { let _ = env_logger::try_init(); let private = [Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; let public = make_ids(&private[..]); - let voter_set = Arc::new(public.iter().cloned().collect::>()); + let voter_set = Arc::new(VoterSet::new(public.iter().cloned()).unwrap()); let round = 1; let set_id = 1; @@ -370,7 +374,7 @@ fn bad_commit_leads_to_report() { let target_number = 500; let precommit = finality_grandpa::Precommit { target_hash: target_hash.clone(), target_number }; - let payload = super::localized_payload( + let payload = sp_finality_grandpa::localized_payload( round, set_id, &finality_grandpa::Message::Precommit(precommit.clone()) ); diff --git a/client/finality-grandpa/src/environment.rs b/client/finality-grandpa/src/environment.rs index dec9492482a5e78ba6e06a752ea29fa9d644acd0..cc6497fc72462b5474c283c9e9694f0998f711d4 100644 --- a/client/finality-grandpa/src/environment.rs +++ b/client/finality-grandpa/src/environment.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use std::collections::BTreeMap; use std::iter::FromIterator; @@ -20,21 +22,19 @@ use std::pin::Pin; use std::sync::Arc; use std::time::Duration; -use log::{debug, warn, info}; +use log::{debug, warn}; use parity_scale_codec::{Decode, Encode}; use futures::prelude::*; use futures_timer::Delay; use parking_lot::RwLock; -use sp_blockchain::{HeaderBackend, Error as ClientError, HeaderMetadata}; use std::marker::PhantomData; -use sc_client_api::{backend::Backend, utils::is_descendent_of}; -use sc_client::apply_aux; +use sc_client_api::{backend::{Backend, apply_aux}, utils::is_descendent_of}; use finality_grandpa::{ - BlockNumberOps, Equivocation, Error as GrandpaError, round::State as RoundState, + BlockNumberOps, Error as GrandpaError, round::State as RoundState, voter, voter_set::VoterSet, }; -use sp_core::Pair; +use sp_blockchain::{HeaderBackend, HeaderMetadata, Error as ClientError}; use sp_runtime::generic::BlockId; use sp_runtime::traits::{ Block as BlockT, Header as HeaderT, NumberFor, One, Zero, @@ -54,7 +54,10 @@ use crate::consensus_changes::SharedConsensusChanges; use crate::justification::GrandpaJustification; use crate::until_imported::UntilVoteTargetImported; use crate::voting_rule::VotingRule; -use sp_finality_grandpa::{AuthorityId, AuthoritySignature, SetId, RoundNumber}; +use sp_finality_grandpa::{ + AuthorityId, AuthoritySignature, Equivocation, EquivocationProof, + GrandpaApi, RoundNumber, SetId, +}; use prometheus_endpoint::{Gauge, U64, register, PrometheusError}; type HistoricalVotes = finality_grandpa::HistoricalVotes< @@ -106,7 +109,7 @@ impl Decode for CompletedRounds { fn decode(value: &mut I) -> Result { <(Vec>, SetId, Vec)>::decode(value) .map(|(rounds, set_id, voters)| CompletedRounds { - rounds: rounds.into(), + rounds, set_id, voters, }) @@ -125,7 +128,7 @@ impl CompletedRounds { let mut rounds = Vec::with_capacity(NUM_LAST_COMPLETED_ROUNDS); rounds.push(genesis); - let voters = voters.current().1.iter().map(|(a, _)| a.clone()).collect(); + let voters = voters.current_authorities.iter().map(|(a, _)| a.clone()).collect(); CompletedRounds { rounds, set_id, voters } } @@ -246,14 +249,14 @@ impl VoterSetState { { if let VoterSetState::Live { completed_rounds, current_rounds } = self { if current_rounds.contains_key(&round) { - return Ok((completed_rounds, current_rounds)); + Ok((completed_rounds, current_rounds)) } else { let msg = "Voter acting on a live round we are not tracking."; - return Err(Error::Safety(msg.to_string())); + Err(Error::Safety(msg.to_string())) } } else { let msg = "Voter acting while in paused state."; - return Err(Error::Safety(msg.to_string())); + Err(Error::Safety(msg.to_string())) } } } @@ -404,7 +407,7 @@ pub(crate) struct Environment, SC, pub(crate) _phantom: PhantomData, } -impl, SC, VR> Environment { +impl, 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. @@ -431,6 +434,98 @@ impl, SC, VR> Environment Environment +where + Block: BlockT, + BE: Backend, + C: crate::ClientForGrandpa, + C::Api: GrandpaApi, + N: NetworkT, + SC: SelectChain + 'static, +{ + /// Report the given equivocation to the GRANDPA runtime module. This method + /// generates a session membership proof of the offender and then submits an + /// extrinsic to report the equivocation. In particular, the session membership + /// proof must be generated at the block at which the given set was active which + /// isn't necessarily the best block if there are pending authority set changes. + fn report_equivocation( + &self, + equivocation: Equivocation>, + ) -> Result<(), Error> { + let is_descendent_of = is_descendent_of(&*self.client, None); + + let best_header = self.select_chain + .best_chain() + .map_err(|e| Error::Blockchain(e.to_string()))?; + + let authority_set = self.authority_set.inner().read(); + + // block hash and number of the next pending authority set change in the + // given best chain. + let next_change = authority_set + .next_change(&best_header.hash(), &is_descendent_of) + .map_err(|e| Error::Safety(e.to_string()))?; + + // find the hash of the latest block in the current set + let current_set_latest_hash = match next_change { + Some((_, n)) if n.is_zero() => { + return Err(Error::Safety( + "Authority set change signalled at genesis.".to_string(), + )) + } + // the next set starts at `n` so the current one lasts until `n - 1`. if + // `n` is later than the best block, then the current set is still live + // at best block. + Some((_, n)) if n > *best_header.number() => best_header.hash(), + Some((h, _)) => { + // this is the header at which the new set will start + let header = self.client.header(BlockId::Hash(h))?.expect( + "got block hash from registered pending change; \ + pending changes are only registered on block import; qed.", + ); + + // its parent block is the last block in the current set + *header.parent_hash() + } + // there is no pending change, the latest block for the current set is + // the best block. + None => best_header.hash(), + }; + + // generate key ownership proof at that block + let key_owner_proof = match self.client + .runtime_api() + .generate_key_ownership_proof( + &BlockId::Hash(current_set_latest_hash), + authority_set.set_id, + equivocation.offender().clone(), + ) + .map_err(Error::Client)? + { + Some(proof) => proof, + None => { + debug!(target: "afg", "Equivocation offender is not part of the authority set."); + return Ok(()); + } + }; + + // submit equivocation report at **best** block + let equivocation_proof = EquivocationProof::new( + authority_set.set_id, + equivocation, + ); + + self.client.runtime_api() + .submit_report_equivocation_extrinsic( + &BlockId::Hash(best_header.hash()), + equivocation_proof, + key_owner_proof, + ).map_err(Error::Client)?; + + Ok(()) + } +} + impl finality_grandpa::Chain> for Environment @@ -438,7 +533,7 @@ where Block: 'static, BE: Backend, C: crate::ClientForGrandpa, - N: NetworkT + 'static + Send, + N: NetworkT + 'static + Send, SC: SelectChain + 'static, VR: VotingRule, NumberFor: BlockNumberOps, @@ -452,7 +547,7 @@ where // signaled asynchronously. therefore the voter could still vote in the next round // before activating the new set. the `authority_set` is updated immediately thus we // restrict the voter based on that. - if self.set_id != self.authority_set.inner().read().current().0 { + if self.set_id != self.authority_set.set_id() { return None; } @@ -528,7 +623,7 @@ where restricted_number >= base_header.number() && restricted_number < target_header.number() }) - .or(Some((target_header.hash(), *target_header.number()))) + .or_else(|| Some((target_header.hash(), *target_header.number()))) }, Ok(None) => { debug!(target: "afg", "Encountered error finding best chain containing {:?}: couldn't find target block", block); @@ -580,23 +675,24 @@ where Block: 'static, B: Backend, C: crate::ClientForGrandpa + 'static, - N: NetworkT + 'static + Send, + C::Api: GrandpaApi, + N: NetworkT + 'static + Send + Sync, SC: SelectChain + 'static, VR: VotingRule, NumberFor: BlockNumberOps, { - type Timer = Pin> + Send>>; + type Timer = Pin> + Send + Sync>>; type Id = AuthorityId; type Signature = AuthoritySignature; // regular round message streams type In = Pin, Self::Signature, Self::Id>, Self::Error> - > + Send>>; + > + Send + Sync>>; type Out = Pin>, Error = Self::Error, - > + Send>>; + > + Send + Sync>>; type Error = CommandOrError>; @@ -607,11 +703,11 @@ where let prevote_timer = Delay::new(self.config.gossip_duration * 2); let precommit_timer = Delay::new(self.config.gossip_duration * 4); - let local_key = crate::is_voter(&self.voters, &self.config.keystore); + let local_key = crate::is_voter(&self.voters, self.config.keystore.as_ref()); let has_voted = match self.voter_set_state.has_voted(round) { HasVoted::Yes(id, vote) => { - if local_key.as_ref().map(|k| k.public() == id).unwrap_or(false) { + if local_key.as_ref().map(|k| k == &id).unwrap_or(false) { HasVoted::Yes(id, vote) } else { HasVoted::No @@ -620,11 +716,18 @@ where HasVoted::No => HasVoted::No, }; + // we can only sign when we have a local key in the authority set + // and we have a reference to the keystore. + let keystore = match (local_key.as_ref(), self.config.keystore.as_ref()) { + (Some(id), Some(keystore)) => Some((id.clone(), keystore.clone()).into()), + _ => None, + }; + let (incoming, outgoing) = self.network.round_communication( + keystore, crate::communication::Round(round), crate::communication::SetId(self.set_id), self.voters.clone(), - local_key.clone(), has_voted, ); @@ -643,7 +746,7 @@ where let outgoing = Box::pin(outgoing.sink_err_into()); voter::RoundData { - voter_id: local_key.map(|pair| pair.public()), + voter_id: local_key, prevote_timer: Box::pin(prevote_timer.map(Ok)), precommit_timer: Box::pin(precommit_timer.map(Ok)), incoming, @@ -652,10 +755,10 @@ where } fn proposed(&self, round: RoundNumber, propose: PrimaryPropose) -> Result<(), Self::Error> { - let local_id = crate::is_voter(&self.voters, &self.config.keystore); + let local_id = crate::is_voter(&self.voters, self.config.keystore.as_ref()); let local_id = match local_id { - Some(id) => id.public(), + Some(id) => id, None => return Ok(()), }; @@ -691,10 +794,10 @@ where } fn prevoted(&self, round: RoundNumber, prevote: Prevote) -> Result<(), Self::Error> { - let local_id = crate::is_voter(&self.voters, &self.config.keystore); + let local_id = crate::is_voter(&self.voters, self.config.keystore.as_ref()); let local_id = match local_id { - Some(id) => id.public(), + Some(id) => id, None => return Ok(()), }; @@ -732,10 +835,10 @@ where } fn precommitted(&self, round: RoundNumber, precommit: Precommit) -> Result<(), Self::Error> { - let local_id = crate::is_voter(&self.voters, &self.config.keystore); + let local_id = crate::is_voter(&self.voters, self.config.keystore.as_ref()); let local_id = match local_id { - Some(id) => id.public(), + Some(id) => id, None => return Ok(()), }; @@ -911,6 +1014,7 @@ where hash, number, (round, commit).into(), + false, ) } @@ -925,19 +1029,23 @@ where fn prevote_equivocation( &self, _round: RoundNumber, - equivocation: ::finality_grandpa::Equivocation, Self::Signature> + equivocation: finality_grandpa::Equivocation, Self::Signature>, ) { warn!(target: "afg", "Detected prevote equivocation in the finality worker: {:?}", equivocation); - // nothing yet; this could craft misbehavior reports of some kind. + if let Err(err) = self.report_equivocation(equivocation.into()) { + warn!(target: "afg", "Error reporting prevote equivocation: {:?}", err); + } } fn precommit_equivocation( &self, _round: RoundNumber, - equivocation: Equivocation, Self::Signature> + equivocation: finality_grandpa::Equivocation, Self::Signature>, ) { warn!(target: "afg", "Detected precommit equivocation in the finality worker: {:?}", equivocation); - // nothing yet + if let Err(err) = self.report_equivocation(equivocation.into()) { + warn!(target: "afg", "Error reporting precommit equivocation: {:?}", err); + } } } @@ -970,6 +1078,7 @@ pub(crate) fn finalize_block( hash: Block::Hash, number: NumberFor, justification_or_commit: JustificationOrCommit, + initial_sync: bool, ) -> Result<(), CommandOrError>> where Block: BlockT, BE: Backend, @@ -1011,6 +1120,7 @@ pub(crate) fn finalize_block( hash, number, &is_descendent_of::(&*client, None), + initial_sync, ).map_err(|e| Error::Safety(e.to_string()))?; // check if this is this is the first finalization of some consensus changes @@ -1091,9 +1201,15 @@ pub(crate) fn finalize_block( let (new_id, set_ref) = authority_set.current(); if set_ref.len() > 16 { - info!("👴 Applying GRANDPA set change to new set with {} authorities", set_ref.len()); + afg_log!(initial_sync, + "👴 Applying GRANDPA set change to new set with {} authorities", + set_ref.len(), + ); } else { - info!("👴 Applying GRANDPA set change to new set {:?}", set_ref); + afg_log!(initial_sync, + "👴 Applying GRANDPA set change to new set {:?}", + set_ref, + ); } telemetry!(CONSENSUS_INFO; "afg.generating_new_authority_set"; diff --git a/client/finality-grandpa/src/finality_proof.rs b/client/finality-grandpa/src/finality_proof.rs index 2c85839b5e3640ca19398767dffb42ea4a3afa05..55f6376579db4ced0e554293d3fabf569d221b94 100644 --- a/client/finality-grandpa/src/finality_proof.rs +++ b/client/finality-grandpa/src/finality_proof.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! GRANDPA block finality proof generation and check. //! @@ -54,6 +56,7 @@ use sc_telemetry::{telemetry, CONSENSUS_INFO}; use sp_finality_grandpa::{AuthorityId, AuthorityList, VersionedAuthorityList, GRANDPA_AUTHORITIES_KEY}; use crate::justification::GrandpaJustification; +use crate::VoterSet; /// Maximum number of fragments that we want to return in a single prove_finality call. const MAX_FRAGMENTS_IN_PROOF: usize = 8; @@ -182,7 +185,7 @@ impl sc_network::config::FinalityProofProvider for FinalityProo let request: FinalityProofRequest = Decode::decode(&mut &request[..]) .map_err(|e| { warn!(target: "afg", "Unable to decode finality proof request: {}", e.what()); - ClientError::Backend(format!("Invalid finality proof request")) + ClientError::Backend("Invalid finality proof request".to_string()) })?; match request { FinalityProofRequest::Original(request) => prove_finality::<_, _, GrandpaJustification>( @@ -218,7 +221,7 @@ pub struct FinalityEffects { /// 2) headers sub-chain (B; F] if B != F; /// 3) proof of GRANDPA::authorities() if the set changes at block F. #[derive(Debug, PartialEq, Encode, Decode)] -struct FinalityProofFragment { +pub(crate) struct FinalityProofFragment { /// The hash of block F for which justification is provided. pub block: Header::Hash, /// Justification of the block F. @@ -341,7 +344,7 @@ pub(crate) fn prove_finality, J>( let proof_fragment = FinalityProofFragment { block: current, justification, - unknown_headers: ::std::mem::replace(&mut unknown_headers, Vec::new()), + unknown_headers: ::std::mem::take(&mut unknown_headers), authorities_proof: new_authorities_proof, }; @@ -396,7 +399,7 @@ pub(crate) fn prove_finality, J>( } // else search for the next justification - current_number = current_number + One::one(); + current_number += One::one(); } if finality_proof.is_empty() { @@ -424,26 +427,7 @@ pub(crate) fn prove_finality, J>( /// /// Returns the vector of headers that MUST be validated + imported /// AND if at least one of those headers is invalid, all other MUST be considered invalid. -pub(crate) fn check_finality_proof( - blockchain: &B, - current_set_id: u64, - current_authorities: AuthorityList, - authorities_provider: &dyn AuthoritySetForFinalityChecker, - remote_proof: Vec, -) -> ClientResult> - where - NumberFor: BlockNumberOps, - B: BlockchainBackend, -{ - do_check_finality_proof::<_, _, GrandpaJustification>( - blockchain, - current_set_id, - current_authorities, - authorities_provider, - remote_proof) -} - -fn do_check_finality_proof( +pub(crate) fn check_finality_proof( blockchain: &B, current_set_id: u64, current_authorities: AuthorityList, @@ -531,7 +515,7 @@ fn check_finality_proof_fragment( new_authorities_proof, )?; - current_set_id = current_set_id + 1; + current_set_id += 1; } Ok(AuthoritiesOrEffects::Effects(FinalityEffects { @@ -588,7 +572,11 @@ impl ProvableJustification for GrandpaJustificatio NumberFor: BlockNumberOps, { fn verify(&self, set_id: u64, authorities: &[(AuthorityId, u64)]) -> ClientResult<()> { - GrandpaJustification::verify(self, set_id, &authorities.iter().cloned().collect()) + let authorities = VoterSet::new(authorities.iter().cloned()).ok_or( + ClientError::Consensus(sp_consensus::Error::InvalidAuthoritiesSet), + )?; + + GrandpaJustification::verify(self, set_id, &authorities) } } @@ -596,11 +584,11 @@ impl ProvableJustification for GrandpaJustificatio pub(crate) mod tests { use substrate_test_runtime_client::runtime::{Block, Header, H256}; use sc_client_api::NewBlockState; - use substrate_test_runtime_client::sc_client::in_mem::Blockchain as InMemoryBlockchain; + use sc_client_api::in_mem::Blockchain as InMemoryBlockchain; use super::*; use sp_core::crypto::Public; - type FinalityProof = super::FinalityProof
; + pub(crate) type FinalityProof = super::FinalityProof
; impl AuthoritySetForFinalityProver for (GetAuthorities, ProveAuthorities) where @@ -616,7 +604,7 @@ pub(crate) mod tests { } } - struct ClosureAuthoritySetForFinalityChecker(pub Closure); + pub(crate) struct ClosureAuthoritySetForFinalityChecker(pub Closure); impl AuthoritySetForFinalityChecker for ClosureAuthoritySetForFinalityChecker where @@ -882,7 +870,7 @@ pub(crate) mod tests { blockchain.insert(header(4).hash(), header(4), None, None, NewBlockState::Final).unwrap(); blockchain.insert(header(5).hash(), header(5), None, None, NewBlockState::Final).unwrap(); blockchain.insert(header(6).hash(), header(6), None, None, NewBlockState::Final).unwrap(); - let effects = do_check_finality_proof::<_, _, TestJustification>( + let effects = check_finality_proof::<_, _, TestJustification>( &blockchain, 0, auth3, @@ -910,7 +898,7 @@ pub(crate) mod tests { let blockchain = test_blockchain(); // when we can't decode proof from Vec - do_check_finality_proof::<_, _, TestJustification>( + check_finality_proof::<_, _, TestJustification>( &blockchain, 1, vec![(AuthorityId::from_slice(&[3u8; 32]), 1u64)], @@ -924,7 +912,7 @@ pub(crate) mod tests { let blockchain = test_blockchain(); // when decoded proof has zero length - do_check_finality_proof::<_, _, TestJustification>( + check_finality_proof::<_, _, TestJustification>( &blockchain, 1, vec![(AuthorityId::from_slice(&[3u8; 32]), 1u64)], @@ -939,7 +927,7 @@ pub(crate) mod tests { // when intermediate (#0) fragment has non-empty unknown headers let authorities = vec![(AuthorityId::from_slice(&[3u8; 32]), 1u64)]; - do_check_finality_proof::<_, _, TestJustification>( + check_finality_proof::<_, _, TestJustification>( &blockchain, 1, authorities.clone(), @@ -964,7 +952,7 @@ pub(crate) mod tests { // when intermediate (#0) fragment has empty authorities proof let authorities = vec![(AuthorityId::from_slice(&[3u8; 32]), 1u64)]; - do_check_finality_proof::<_, _, TestJustification>( + check_finality_proof::<_, _, TestJustification>( &blockchain, 1, authorities.clone(), @@ -989,7 +977,7 @@ pub(crate) mod tests { let initial_authorities = vec![(AuthorityId::from_slice(&[3u8; 32]), 1u64)]; let next_authorities = vec![(AuthorityId::from_slice(&[4u8; 32]), 1u64)]; - let effects = do_check_finality_proof::<_, _, TestJustification>( + let effects = check_finality_proof::<_, _, TestJustification>( &blockchain, 1, initial_authorities.clone(), diff --git a/client/finality-grandpa/src/import.rs b/client/finality-grandpa/src/import.rs index faf319364162203a685bcf18c519297932d3a3f0..b37ab7907a62e75b26d054666b9c1b7f114a69bd 100644 --- a/client/finality-grandpa/src/import.rs +++ b/client/finality-grandpa/src/import.rs @@ -1,22 +1,24 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use std::{sync::Arc, collections::HashMap}; -use log::{debug, trace, info}; +use log::{debug, trace}; use parity_scale_codec::Encode; use parking_lot::RwLockWriteGuard; @@ -27,7 +29,7 @@ use sp_api::{TransactionFor}; use sp_consensus::{ BlockImport, Error as ConsensusError, - BlockCheckParams, BlockImportParams, ImportResult, JustificationImport, + BlockCheckParams, BlockImportParams, BlockOrigin, ImportResult, JustificationImport, SelectChain, }; use sp_finality_grandpa::{ConsensusLog, ScheduledChange, SetId, GRANDPA_ENGINE_ID}; @@ -128,7 +130,12 @@ impl JustificationImport number: NumberFor, justification: Justification, ) -> Result<(), Self::Error> { - GrandpaBlockImport::import_justification(self, hash, number, justification, false) + // this justification was requested by the sync service, therefore we + // are not sure if it should enact a change or not. it could have been a + // request made as part of initial sync but that means the justification + // wasn't part of the block and was requested asynchronously, probably + // makes sense to log in that case. + GrandpaBlockImport::import_justification(self, hash, number, justification, false, false) } } @@ -250,6 +257,7 @@ where &self, block: &mut BlockImportParams>, hash: Block::Hash, + initial_sync: bool, ) -> Result, ConsensusError> { // when we update the authorities, we need to hold the lock // until the block is written to prevent a race if we need to restore @@ -288,7 +296,7 @@ where } } - let number = block.header.number().clone(); + let number = *(block.header.number()); let maybe_change = self.check_new_change( &block.header, hash, @@ -320,11 +328,13 @@ where guard.as_mut().add_pending_change( change, &is_descendent_of, - ).map_err(|e| ConsensusError::from(ConsensusError::ClientImport(e.to_string())))?; + ).map_err(|e| ConsensusError::ClientImport(e.to_string()))?; } let applied_changes = { - let forced_change_set = guard.as_mut().apply_forced_changes(hash, number, &is_descendent_of) + let forced_change_set = guard + .as_mut() + .apply_forced_changes(hash, number, &is_descendent_of, initial_sync) .map_err(|e| ConsensusError::ClientImport(e.to_string())) .map_err(ConsensusError::from)?; @@ -409,17 +419,20 @@ impl BlockImport new_cache: HashMap>, ) -> Result { let hash = block.post_hash(); - let number = block.header.number().clone(); + let number = *block.header.number(); // early exit if block already in chain, otherwise the check for // authority changes will error when trying to re-import a change block match self.inner.status(BlockId::Hash(hash)) { Ok(BlockStatus::InChain) => return Ok(ImportResult::AlreadyInChain), Ok(BlockStatus::Unknown) => {}, - Err(e) => return Err(ConsensusError::ClientImport(e.to_string()).into()), + Err(e) => return Err(ConsensusError::ClientImport(e.to_string())), } - let pending_changes = self.make_authorities_changes(&mut block, hash)?; + // on initial sync we will restrict logging under info to avoid spam. + let initial_sync = block.origin == BlockOrigin::NetworkInitialSync; + + let pending_changes = self.make_authorities_changes(&mut block, hash, initial_sync)?; // we don't want to finalize on `inner.import_block` let mut justification = block.justification.take(); @@ -445,7 +458,7 @@ impl BlockImport e, ); pending_changes.revert(); - return Err(ConsensusError::ClientImport(e.to_string()).into()); + return Err(ConsensusError::ClientImport(e.to_string())); }, } }; @@ -455,7 +468,7 @@ impl BlockImport // Send the pause signal after import but BEFORE sending a `ChangeAuthorities` message. if do_pause { let _ = self.send_voter_commands.unbounded_send( - VoterCommand::Pause(format!("Forced change scheduled after inactivity")) + VoterCommand::Pause("Forced change scheduled after inactivity".to_string()) ); } @@ -492,7 +505,15 @@ impl BlockImport match justification { Some(justification) => { - self.import_justification(hash, number, justification, needs_justification).unwrap_or_else(|err| { + let import_res = self.import_justification( + hash, + number, + justification, + needs_justification, + initial_sync, + ); + + import_res.unwrap_or_else(|err| { if needs_justification || enacts_consensus_change { debug!(target: "afg", "Imported block #{} that enacts authority set change with \ invalid justification: {:?}, requesting justification from peers.", number, err); @@ -604,6 +625,7 @@ where number: NumberFor, justification: Justification, enacts_change: bool, + initial_sync: bool, ) -> Result<(), ConsensusError> { let justification = GrandpaJustification::decode_and_verify_finalizes( &justification, @@ -613,7 +635,7 @@ where ); let justification = match justification { - Err(e) => return Err(ConsensusError::ClientImport(e.to_string()).into()), + Err(e) => return Err(ConsensusError::ClientImport(e.to_string())), Ok(justification) => justification, }; @@ -625,12 +647,17 @@ where hash, number, justification.into(), + initial_sync, ); match result { Err(CommandOrError::VoterCommand(command)) => { - info!(target: "afg", "👴 Imported justification for block #{} that triggers \ - command {}, signaling voter.", number, command); + afg_log!(initial_sync, + "👴 Imported justification for block #{} that triggers \ + command {}, signaling voter.", + number, + command, + ); // send the command to the voter let _ = self.send_voter_commands.unbounded_send(command); @@ -642,8 +669,9 @@ where Error::Blockchain(error) => ConsensusError::ClientImport(error), Error::Client(error) => ConsensusError::ClientImport(error.to_string()), Error::Safety(error) => ConsensusError::ClientImport(error), + Error::Signing(error) => ConsensusError::ClientImport(error), Error::Timer(error) => ConsensusError::ClientImport(error.to_string()), - }.into()); + }); }, Ok(_) => { assert!(!enacts_change, "returns Ok when no authority set change should be enacted; qed;"); diff --git a/client/finality-grandpa/src/justification.rs b/client/finality-grandpa/src/justification.rs index 084c0042ab19a08fe5f17e31aeffd1820958fcb0..0e51a230c5a81bce7fe608ef72cbc774a42172bc 100644 --- a/client/finality-grandpa/src/justification.rs +++ b/client/finality-grandpa/src/justification.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use std::collections::{HashMap, HashSet}; use std::sync::Arc; @@ -26,7 +28,6 @@ use sp_runtime::traits::{NumberFor, Block as BlockT, Header as HeaderT}; use sp_finality_grandpa::AuthorityId; use crate::{Commit, Error}; -use crate::communication; /// A GRANDPA justification for block finality, it includes a commit message and /// an ancestry proof including all headers routing all precommit target blocks @@ -62,7 +63,7 @@ impl GrandpaJustification { }; for signed in commit.precommits.iter() { - let mut current_hash = signed.precommit.target_hash.clone(); + let mut current_hash = signed.precommit.target_hash; loop { if current_hash == commit.target_hash { break; } @@ -72,7 +73,7 @@ impl GrandpaJustification { return error(); } - let parent_hash = current_header.parent_hash().clone(); + let parent_hash = *current_header.parent_hash(); if votes_ancestries_hashes.insert(current_hash) { votes_ancestries.push(current_header); } @@ -88,7 +89,7 @@ impl GrandpaJustification { /// Decode a GRANDPA justification and validate the commit and the votes' /// ancestry proofs finalize the given block. - pub(crate) fn decode_and_verify_finalizes( + pub fn decode_and_verify_finalizes( encoded: &[u8], finalized_target: (Block::Hash, NumberFor), set_id: u64, @@ -132,7 +133,7 @@ impl GrandpaJustification { let mut buf = Vec::new(); let mut visited_hashes = HashSet::new(); for signed in self.commit.precommits.iter() { - if let Err(_) = communication::check_message_sig_with_buffer::( + if !sp_finality_grandpa::check_message_signature_with_buffer( &finality_grandpa::Message::Precommit(signed.precommit.clone()), &signed.id, &signed.signature, @@ -141,7 +142,7 @@ impl GrandpaJustification { &mut buf, ) { return Err(ClientError::BadJustification( - "invalid signature for precommit in grandpa justification".to_string()).into()); + "invalid signature for precommit in grandpa justification".to_string())); } if self.commit.target_hash == signed.precommit.target_hash { @@ -158,7 +159,7 @@ impl GrandpaJustification { }, _ => { return Err(ClientError::BadJustification( - "invalid precommit ancestry proof in grandpa justification".to_string()).into()); + "invalid precommit ancestry proof in grandpa justification".to_string())); }, } } @@ -170,7 +171,7 @@ impl GrandpaJustification { if visited_hashes != ancestry_hashes { return Err(ClientError::BadJustification( - "invalid precommit ancestries in grandpa justification with unused headers".to_string()).into()); + "invalid precommit ancestries in grandpa justification with unused headers".to_string())); } Ok(()) diff --git a/client/finality-grandpa/src/lib.rs b/client/finality-grandpa/src/lib.rs index 800fe3442ea66776eb57745611f29f02ec622a40..7d74d0eebfc48a109427d8271b9f41823ff1ead2 100644 --- a/client/finality-grandpa/src/lib.rs +++ b/client/finality-grandpa/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Integration of the GRANDPA finality gadget into substrate. //! @@ -52,31 +54,38 @@ //! or prune any signaled changes based on whether the signaling block is //! included in the newly-finalized chain. -use futures::prelude::*; -use futures::StreamExt; +#![warn(missing_docs)] + +use futures::{ + prelude::*, + StreamExt, +}; use log::{debug, info}; use sc_client_api::{ backend::{AuxStore, Backend}, LockImportRun, BlockchainEvents, CallExecutor, ExecutionStrategy, Finalizer, TransactionFor, ExecutorProvider, }; -use sp_blockchain::{HeaderBackend, Error as ClientError, HeaderMetadata}; use parity_scale_codec::{Decode, Encode}; use prometheus_endpoint::{PrometheusError, Registry}; +use sp_api::ProvideRuntimeApi; +use sp_blockchain::{HeaderBackend, Error as ClientError, HeaderMetadata}; use sp_runtime::generic::BlockId; use sp_runtime::traits::{NumberFor, Block as BlockT, DigestFor, Zero}; -use sc_keystore::KeyStorePtr; use sp_inherents::InherentDataProviders; use sp_consensus::{SelectChain, BlockImport}; -use sp_core::Pair; +use sp_core::{ + crypto::Public, + traits::BareCryptoStorePtr, +}; +use sp_application_crypto::AppKey; use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver}; use sc_telemetry::{telemetry, CONSENSUS_INFO, CONSENSUS_DEBUG}; -use serde_json; - -use sp_finality_tracker; +use parking_lot::RwLock; use finality_grandpa::Error as GrandpaError; -use finality_grandpa::{voter, BlockNumberOps, voter_set::VoterSet}; +use finality_grandpa::{voter, voter_set::VoterSet}; +pub use finality_grandpa::BlockNumberOps; use std::{fmt, io}; use std::sync::Arc; @@ -84,6 +93,23 @@ use std::time::Duration; use std::pin::Pin; use std::task::{Poll, Context}; +// utility logging macro that takes as first argument a conditional to +// decide whether to log under debug or info level (useful to restrict +// logging under initial sync). +macro_rules! afg_log { + ($condition:expr, $($msg: expr),+ $(,)?) => { + { + let log_level = if $condition { + log::Level::Debug + } else { + log::Level::Info + }; + + log::log!(target: "afg", log_level, $($msg),+); + } + }; +} + mod authorities; mod aux_schema; mod communication; @@ -97,23 +123,24 @@ mod observer; mod until_imported; mod voting_rule; +pub use authorities::SharedAuthoritySet; pub use finality_proof::{FinalityProofProvider, StorageAndProofProvider}; +pub use import::GrandpaBlockImport; pub use justification::GrandpaJustification; -pub use light_import::light_block_import; +pub use light_import::{light_block_import, GrandpaLightBlockImport}; pub use voting_rule::{ BeforeBestBlockBy, ThreeQuartersOfTheUnfinalizedChain, VotingRule, VotingRulesBuilder }; +pub use finality_grandpa::voter::report; use aux_schema::PersistentData; use environment::{Environment, VoterSetState}; -use import::GrandpaBlockImport; use until_imported::UntilGlobalMessageBlocksImported; use communication::{NetworkBridge, Network as NetworkT}; -use sp_finality_grandpa::{AuthorityList, AuthorityPair, AuthoritySignature, SetId}; +use sp_finality_grandpa::{AuthorityList, AuthoritySignature, SetId}; // Re-export these two because it's just so damn convenient. -pub use sp_finality_grandpa::{AuthorityId, ScheduledChange}; -use sp_api::ProvideRuntimeApi; +pub use sp_finality_grandpa::{AuthorityId, AuthorityPair, GrandpaApi, ScheduledChange}; use std::marker::PhantomData; #[cfg(test)] @@ -121,6 +148,7 @@ mod tests; /// A GRANDPA message for a substrate chain. pub type Message = finality_grandpa::Message<::Hash, NumberFor>; + /// A signed message. pub type SignedMessage = finality_grandpa::SignedMessage< ::Hash, @@ -186,7 +214,44 @@ type CommunicationOutH = finality_grandpa::voter::CommunicationOut< AuthorityId, >; -/// Configuration for the GRANDPA service. +/// Shared voter state for querying. +pub struct SharedVoterState { + inner: Arc + Sync + Send>>>>, +} + +impl SharedVoterState { + /// Create a new empty `SharedVoterState` instance. + pub fn empty() -> Self { + Self { + inner: Arc::new(RwLock::new(None)), + } + } + + fn reset( + &self, + voter_state: Box + Sync + Send>, + ) -> Option<()> { + let mut shared_voter_state = self + .inner + .try_write_for(Duration::from_secs(1))?; + + *shared_voter_state = Some(voter_state); + Some(()) + } + + /// Get the inner `VoterState` instance. + pub fn voter_state(&self) -> Option> { + self.inner.read().as_ref().map(|vs| vs.get()) + } +} + +impl Clone for SharedVoterState { + fn clone(&self) -> Self { + SharedVoterState { inner: self.inner.clone() } + } +} + +/// Configuration for the GRANDPA service #[derive(Clone)] pub struct Config { /// The expected duration for a message to be gossiped across the network. @@ -205,7 +270,7 @@ pub struct Config { /// Some local identifier of the voter. pub name: Option, /// The keystore that manages the keys of this node. - pub keystore: Option, + pub keystore: Option, } impl Config { @@ -225,6 +290,8 @@ pub enum Error { Blockchain(String), /// Could not complete a round on disk. Client(ClientError), + /// Could not sign outgoing message + Signing(String), /// An invariant has been violated (e.g. not finalizing pending change blocks in-order) Safety(String), /// A timer failed to fire. @@ -375,6 +442,7 @@ impl fmt::Display for CommandOrError { } } +/// Link between the block importer and the background voter. pub struct LinkHalf { client: Arc, select_chain: SC, @@ -382,6 +450,13 @@ pub struct LinkHalf { voter_commands_rx: TracingUnboundedReceiver>>, } +impl LinkHalf { + /// Get the shared authority set. + pub fn shared_authority_set(&self) -> &SharedAuthoritySet> { + &self.persistent_data.authority_set + } +} + /// Provider for the Grandpa authority set configured on the genesis block. pub trait GenesisAuthoritySetProvider { /// Get the authority set at the genesis block. @@ -406,7 +481,7 @@ impl GenesisAuthoritySetProvider for Arc( voters: &Arc>, client: Arc, network: &NetworkBridge, - keystore: &Option, + keystore: Option<&BareCryptoStorePtr>, metrics: Option, ) -> ( impl Stream< @@ -581,7 +656,7 @@ fn register_finality_tracker_inherent_data_provider( Ok(info.finalized_number) } })) - .map_err(|err| sp_consensus::Error::InherentData(err.into())) + .map_err(|err| sp_consensus::Error::InherentData(err)) } else { Ok(()) } @@ -603,6 +678,8 @@ pub struct GrandpaParams { pub voting_rule: VR, /// The prometheus metrics registry. pub prometheus_registry: Option, + /// The voter state is exposed at an RPC endpoint. + pub shared_voter_state: SharedVoterState, } /// Run a GRANDPA voter as a task. Provide configuration and a link to a @@ -618,6 +695,7 @@ pub fn run_grandpa_voter( NumberFor: BlockNumberOps, DigestFor: Encode, C: ClientForGrandpa + 'static, + C::Api: GrandpaApi, { let GrandpaParams { mut config, @@ -627,6 +705,7 @@ pub fn run_grandpa_voter( telemetry_on_connect, voting_rule, prometheus_registry, + shared_voter_state, } = grandpa_params; // NOTE: we have recently removed `run_grandpa_observer` from the public @@ -657,16 +736,16 @@ pub fn run_grandpa_voter( 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()); + let mut auths = curr.iter().map(|(p, _)| p); + let maybe_authority_id = authority_id(&mut auths, conf.keystore.as_ref()) + .unwrap_or_default(); telemetry!(CONSENSUS_INFO; "afg.authority_set"; "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(); + let authorities: Vec = curr.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") } @@ -687,6 +766,7 @@ pub fn run_grandpa_voter( persistent_data, voter_commands_rx, prometheus_registry, + shared_voter_state, ); let voter_work = voter_work @@ -717,6 +797,7 @@ impl Metrics { #[must_use] struct VoterWork, SC, VR> { voter: Pin>>> + Send>>, + shared_voter_state: SharedVoterState, env: Arc>, voter_commands_rx: TracingUnboundedReceiver>>, network: NetworkBridge, @@ -730,6 +811,7 @@ where Block: BlockT, B: Backend + 'static, C: ClientForGrandpa + 'static, + C::Api: GrandpaApi, N: NetworkT + Sync, NumberFor: BlockNumberOps, SC: SelectChain + 'static, @@ -744,6 +826,7 @@ where persistent_data: PersistentData, voter_commands_rx: TracingUnboundedReceiver>>, prometheus_registry: Option, + shared_voter_state: SharedVoterState, ) -> Self { let metrics = match prometheus_registry.as_ref().map(Metrics::register) { Some(Ok(metrics)) => Some(metrics), @@ -765,7 +848,7 @@ where 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(), + voter_set_state: persistent_data.set_state, metrics: metrics.as_ref().map(|m| m.environment.clone()), _phantom: PhantomData, }); @@ -774,6 +857,7 @@ where // `voter` is set to a temporary value and replaced below when // calling `rebuild_voter`. voter: Box::pin(future::pending()), + shared_voter_state, env, voter_commands_rx, network, @@ -789,9 +873,8 @@ where 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()); + let authority_id = is_voter(&self.env.voters, self.env.config.keystore.as_ref()) + .unwrap_or_default(); telemetry!(CONSENSUS_DEBUG; "afg.starting_new_voter"; "name" => ?self.env.config.name(), @@ -806,7 +889,7 @@ where "authority_id" => authority_id.to_string(), "authority_set_id" => ?self.env.set_id, "authorities" => { - let authorities: Vec = self.env.voters.voters() + let authorities: Vec = self.env.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") @@ -825,7 +908,7 @@ where &self.env.voters, self.env.client.clone(), &self.env.network, - &self.env.config.keystore, + self.env.config.keystore.as_ref(), self.metrics.as_ref().map(|m| m.until_imported.clone()), ); @@ -837,10 +920,18 @@ where global_comms, last_completed_round.number, last_completed_round.votes.clone(), - last_completed_round.base.clone(), + last_completed_round.base, last_finalized, ); + // Repoint shared_voter_state so that the RPC endpoint can query the state + if self.shared_voter_state.reset(voter.voter_state()).is_none() { + info!(target: "afg", + "Timed out trying to update shared GRANDPA voter state. \ + RPC endpoints may return stale data." + ); + } + self.voter = Box::pin(voter); }, VoterSetState::Paused { .. } => @@ -877,11 +968,18 @@ where Ok(Some(set_state)) })?; + let voters = Arc::new(VoterSet::new(new.authorities.into_iter()) + .expect("new authorities come from pending change; \ + pending change comes from `AuthoritySet`; \ + `AuthoritySet` validates authorities is non-empty and weights are non-zero; \ + qed." + ) + ); + self.env = Arc::new(Environment { - voters: Arc::new(new.authorities.into_iter().collect()), + voters, 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(), @@ -923,6 +1021,7 @@ where NumberFor: BlockNumberOps, SC: SelectChain + 'static, C: ClientForGrandpa + 'static, + C::Api: GrandpaApi, VR: VotingRule + Clone + 'static, { type Output = Result<(), Error>; @@ -997,11 +1096,16 @@ pub fn setup_disabled_grandpa( /// Returns the key pair of the node that is being used in the current voter set or `None`. fn is_voter( voters: &Arc>, - keystore: &Option, -) -> Option { + keystore: Option<&BareCryptoStorePtr>, +) -> Option { match keystore { - Some(keystore) => voters.voters().iter() - .find_map(|(p, _)| keystore.read().key_pair::(&p).ok()), + Some(keystore) => voters + .iter() + .find(|(p, _)| { + keystore.read() + .has_keys(&[(p.to_raw_vec(), AuthorityId::ID)]) + }) + .map(|(p, _)| p.clone()), None => None, } } @@ -1009,19 +1113,16 @@ fn is_voter( /// Returns the authority id of this node, if available. fn authority_id<'a, I>( authorities: &mut I, - keystore: &Option, + keystore: Option<&BareCryptoStorePtr>, ) -> Option where I: Iterator, { match keystore { Some(keystore) => { authorities - .find_map(|p| { - keystore.read().key_pair::(&p) - .ok() - .map(|ap| ap.public()) - }) - } + .find(|p| keystore.read().has_keys(&[(p.to_raw_vec(), AuthorityId::ID)])) + .cloned() + }, None => None, } } diff --git a/client/finality-grandpa/src/light_import.rs b/client/finality-grandpa/src/light_import.rs index 276f5d0f28d7ab1c9c3d376bc23ce4f55f03b1a7..a7c9a655467c799ed500e6186fd64cc9825b1a7e 100644 --- a/client/finality-grandpa/src/light_import.rs +++ b/client/finality-grandpa/src/light_import.rs @@ -18,9 +18,7 @@ use std::collections::HashMap; use std::sync::Arc; use log::{info, trace, warn}; use parking_lot::RwLock; -use sc_client_api::{ - backend::{AuxStore, Backend, Finalizer, TransactionFor}, -}; +use sc_client_api::backend::{AuxStore, Backend, Finalizer, TransactionFor}; use sp_blockchain::{HeaderBackend, Error as ClientError, well_known_cache_keys}; use parity_scale_codec::{Encode, Decode}; use sp_consensus::{ @@ -171,7 +169,7 @@ impl FinalityProofImport if *pending_number > chain_info.finalized_number && *pending_number <= chain_info.best_number { - out.push((pending_hash.clone(), *pending_number)); + out.push((*pending_hash, *pending_number)); } } @@ -220,7 +218,7 @@ impl LightAuthoritySet { /// Set new authorities set. pub fn update(&mut self, set_id: u64, authorities: AuthorityList) { self.set_id = set_id; - std::mem::replace(&mut self.authorities, authorities); + self.authorities = authorities; } } @@ -255,7 +253,7 @@ fn do_import_block( J: ProvableJustification, { let hash = block.post_hash(); - let number = block.header.number().clone(); + let number = *block.header.number(); // we don't want to finalize on `inner.import_block` let justification = block.justification.take(); @@ -265,7 +263,7 @@ fn do_import_block( let mut imported_aux = match import_result { Ok(ImportResult::Imported(aux)) => aux, Ok(r) => return Ok(r), - Err(e) => return Err(ConsensusError::ClientImport(e.to_string()).into()), + Err(e) => return Err(ConsensusError::ClientImport(e.to_string())), }; match justification { @@ -319,7 +317,7 @@ fn do_import_finality_proof( { let authority_set_id = data.authority_set.set_id(); let authorities = data.authority_set.authorities(); - let finality_effects = crate::finality_proof::check_finality_proof( + let finality_effects = crate::finality_proof::check_finality_proof::<_, _, J>( backend.blockchain(), authority_set_id, authorities, @@ -359,7 +357,7 @@ fn do_import_finality_proof( .expect_block_number_from_id(&BlockId::Hash(finality_effects.block)) .map_err(|e| ConsensusError::ClientImport(e.to_string()))?; do_finalize_block( - client, + client.clone(), data, finalized_block_hash, finalized_block_number, @@ -372,6 +370,14 @@ fn do_import_finality_proof( finality_effects.new_authorities, ); + // store new authorities set + require_insert_aux( + &client, + LIGHT_AUTHORITY_SET_KEY, + &data.authority_set, + "authority set", + )?; + Ok((finalized_block_hash, finalized_block_number)) } @@ -429,7 +435,7 @@ fn do_import_justification( hash, ); - return Err(ConsensusError::ClientImport(e.to_string()).into()); + return Err(ConsensusError::ClientImport(e.to_string())); }, Ok(justification) => { trace!( @@ -564,13 +570,30 @@ fn on_post_finalization_error(error: ClientError, value_type: &str) -> Consensus #[cfg(test)] pub mod tests { use super::*; - use sp_consensus::{ForkChoiceStrategy, BlockImport}; + use sp_consensus::{import_queue::CacheKeyId, ForkChoiceStrategy, BlockImport}; use sp_finality_grandpa::AuthorityId; use sp_core::{H256, crypto::Public}; - use substrate_test_runtime_client::sc_client::in_mem::Blockchain as InMemoryAuxStore; + use sc_client_api::{in_mem::Blockchain as InMemoryAuxStore, StorageProof, BlockBackend}; use substrate_test_runtime_client::runtime::{Block, Header}; use crate::tests::TestApi; - use crate::finality_proof::tests::TestJustification; + use crate::finality_proof::{ + FinalityProofFragment, + tests::{TestJustification, ClosureAuthoritySetForFinalityChecker}, + }; + + struct OkVerifier; + + impl Verifier for OkVerifier { + fn verify( + &mut self, + origin: BlockOrigin, + header: Header, + _justification: Option, + _body: Option::Extrinsic>>, + ) -> Result<(BlockImportParams, Option)>>), String> { + Ok((BlockImportParams::new(origin, header), None)) + } + } pub struct NoJustificationsImport( pub GrandpaLightBlockImport @@ -666,9 +689,12 @@ pub mod tests { fn import_block( new_cache: HashMap>, justification: Option, - ) -> ImportResult { - let (client, _backend) = substrate_test_runtime_client::new_light(); - let client = Arc::new(client); + ) -> ( + ImportResult, + substrate_test_runtime_client::client::Client, + Arc, + ) { + let (client, backend) = substrate_test_runtime_client::new_light(); let mut import_data = LightImportData { last_finalized: Default::default(), authority_set: LightAuthoritySet::genesis(vec![(AuthorityId::from_slice(&[1; 32]), 1)]), @@ -687,17 +713,21 @@ pub mod tests { block.justification = justification; block.fork_choice = Some(ForkChoiceStrategy::LongestChain); - do_import_block::<_, _, _, TestJustification>( - &*client, - &mut import_data, - block, - new_cache, - ).unwrap() + ( + do_import_block::<_, _, _, TestJustification>( + &client, + &mut import_data, + block, + new_cache, + ).unwrap(), + client, + backend, + ) } #[test] fn finality_proof_not_required_when_consensus_data_does_not_changes_and_no_justification_provided() { - assert_eq!(import_block(HashMap::new(), None), ImportResult::Imported(ImportedAux { + assert_eq!(import_block(HashMap::new(), None).0, ImportResult::Imported(ImportedAux { clear_justification_requests: false, needs_justification: false, bad_justification: false, @@ -710,7 +740,7 @@ pub mod tests { #[test] fn finality_proof_not_required_when_consensus_data_does_not_changes_and_correct_justification_provided() { let justification = TestJustification((0, vec![(AuthorityId::from_slice(&[1; 32]), 1)]), Vec::new()).encode(); - assert_eq!(import_block(HashMap::new(), Some(justification)), ImportResult::Imported(ImportedAux { + assert_eq!(import_block(HashMap::new(), Some(justification)).0, ImportResult::Imported(ImportedAux { clear_justification_requests: false, needs_justification: false, bad_justification: false, @@ -724,7 +754,7 @@ pub mod tests { fn finality_proof_required_when_consensus_data_changes_and_no_justification_provided() { let mut cache = HashMap::new(); cache.insert(well_known_cache_keys::AUTHORITIES, vec![AuthorityId::from_slice(&[2; 32])].encode()); - assert_eq!(import_block(cache, None), ImportResult::Imported(ImportedAux { + assert_eq!(import_block(cache, None).0, ImportResult::Imported(ImportedAux { clear_justification_requests: false, needs_justification: false, bad_justification: false, @@ -740,7 +770,7 @@ pub mod tests { let mut cache = HashMap::new(); cache.insert(well_known_cache_keys::AUTHORITIES, vec![AuthorityId::from_slice(&[2; 32])].encode()); assert_eq!( - import_block(cache, Some(justification)), + import_block(cache, Some(justification)).0, ImportResult::Imported(ImportedAux { clear_justification_requests: false, needs_justification: false, @@ -797,4 +827,54 @@ pub mod tests { assert_eq!(data.authority_set.authorities(), vec![(AuthorityId::from_slice(&[42; 32]), 2)]); assert_eq!(data.consensus_changes.pending_changes(), &[(42, Default::default())]); } + + #[test] + fn authority_set_is_updated_on_finality_proof_import() { + let initial_set_id = 0; + let initial_set = vec![(AuthorityId::from_slice(&[1; 32]), 1)]; + let updated_set = vec![(AuthorityId::from_slice(&[2; 32]), 2)]; + let babe_set_signal = vec![AuthorityId::from_slice(&[42; 32])].encode(); + + // import block #1 without justification + let mut cache = HashMap::new(); + cache.insert(well_known_cache_keys::AUTHORITIES, babe_set_signal); + let (_, client, backend) = import_block(cache, None); + + // import finality proof for block #1 + let hash = client.block_hash(1).unwrap().unwrap(); + let mut verifier = OkVerifier; + let mut import_data = LightImportData { + last_finalized: Default::default(), + authority_set: LightAuthoritySet::genesis(initial_set.clone()), + consensus_changes: ConsensusChanges::empty(), + }; + + // import finality proof + do_import_finality_proof::<_, _, _, TestJustification>( + &client, + backend, + &ClosureAuthoritySetForFinalityChecker( + |_, _, _| Ok(updated_set.clone()) + ), + &mut import_data, + Default::default(), + Default::default(), + vec![ + FinalityProofFragment::
{ + block: hash, + justification: TestJustification( + (initial_set_id, initial_set.clone()), + Vec::new(), + ).encode(), + unknown_headers: Vec::new(), + authorities_proof: Some(StorageProof::new(vec![])), + }, + ].encode(), + &mut verifier, + ).unwrap(); + + // verify that new authorities set has been saved to the aux storage + let data = load_aux_import_data(Default::default(), &client, &TestApi::new(initial_set)).unwrap(); + assert_eq!(data.authority_set.authorities(), updated_set); + } } diff --git a/client/finality-grandpa/src/observer.rs b/client/finality-grandpa/src/observer.rs index fbe19a0716aab09edf57a3097d33827c40857c6d..6a7a1f07b05125cc08e4aa976c36f3e08387b87a 100644 --- a/client/finality-grandpa/src/observer.rs +++ b/client/finality-grandpa/src/observer.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use std::pin::Pin; use std::sync::Arc; @@ -24,7 +26,7 @@ use finality_grandpa::{ BlockNumberOps, Error as GrandpaError, voter, voter_set::VoterSet }; use log::{debug, info, warn}; - +use sp_core::traits::BareCryptoStorePtr; use sp_consensus::SelectChain; use sc_client_api::backend::Backend; use sp_utils::mpsc::TracingUnboundedReceiver; @@ -111,7 +113,7 @@ fn grandpa_observer( Err(e) => return future::err(e.into()), }; - if let Some(_) = validation_result.ghost() { + if validation_result.ghost().is_some() { let finalized_hash = commit.target_hash; let finalized_number = commit.target_number; @@ -124,6 +126,7 @@ fn grandpa_observer( finalized_hash, finalized_number, (round, commit).into(), + false, ) { Ok(_) => {}, Err(e) => return future::err(e), @@ -174,6 +177,7 @@ where select_chain: _, persistent_data, voter_commands_rx, + .. } = link; let network = NetworkBridge::new( @@ -187,7 +191,7 @@ where client, network, persistent_data, - config.keystore.clone(), + config.keystore, voter_commands_rx ); @@ -207,7 +211,7 @@ struct ObserverWork> { client: Arc, network: NetworkBridge, persistent_data: PersistentData, - keystore: Option, + keystore: Option, voter_commands_rx: TracingUnboundedReceiver>>, _phantom: PhantomData, } @@ -224,7 +228,7 @@ where client: Arc, network: NetworkBridge, persistent_data: PersistentData, - keystore: Option, + keystore: Option, voter_commands_rx: TracingUnboundedReceiver>>, ) -> Self { @@ -235,7 +239,7 @@ where client, network, persistent_data, - keystore, + keystore: keystore.clone(), voter_commands_rx, _phantom: PhantomData, }; @@ -256,7 +260,7 @@ where &voters, self.client.clone(), &self.network, - &self.keystore, + self.keystore.as_ref(), None, ); @@ -408,11 +412,13 @@ mod tests { (Arc::new(client), backend) }; + let voters = vec![(sp_keyring::Ed25519Keyring::Alice.public().into(), 1)]; + let persistent_data = aux_schema::load_persistent( &*backend, client.info().genesis_hash, 0, - || Ok(vec![]), + || Ok(voters), ).unwrap(); let (_tx, voter_command_rx) = tracing_unbounded(""); diff --git a/client/finality-grandpa/src/tests.rs b/client/finality-grandpa/src/tests.rs index d7d1d1e48d3a0f0f051b1c4a35f4a044ea8ae2a7..50f9e8eba2357bdf85f08face7c43cc46ba81ea5 100644 --- a/client/finality-grandpa/src/tests.rs +++ b/client/finality-grandpa/src/tests.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Tests and test helpers for GRANDPA. @@ -27,7 +29,6 @@ use parking_lot::Mutex; use futures_timer::Delay; use tokio::runtime::{Runtime, Handle}; use sp_keyring::Ed25519Keyring; -use sc_client::LongestChain; use sc_client_api::backend::TransactionFor; use sp_blockchain::Result; use sp_api::{ApiRef, StorageProof, ProvideRuntimeApi}; @@ -41,7 +42,7 @@ use parity_scale_codec::Decode; use sp_runtime::traits::{Block as BlockT, Header as HeaderT, HashFor}; use sp_runtime::generic::{BlockId, DigestItem}; use sp_core::{H256, crypto::Public}; -use sp_finality_grandpa::{GRANDPA_ENGINE_ID, AuthorityList, GrandpaApi}; +use sp_finality_grandpa::{GRANDPA_ENGINE_ID, AuthorityList, EquivocationProof, GrandpaApi, OpaqueKeyOwnershipProof}; use sp_state_machine::{InMemoryBackend, prove_read, read_proof_check}; use authorities::AuthoritySet; @@ -50,6 +51,7 @@ use finality_proof::{ }; use consensus_changes::ConsensusChanges; use sc_block_builder::BlockBuilderProvider; +use sc_consensus::LongestChain; type PeerData = Mutex< @@ -104,7 +106,7 @@ impl TestNetFactory for GrandpaTestNet { _cfg: &ProtocolConfig, _: &PeerData, ) -> Self::Verifier { - PassThroughVerifier(false) // use non-instant finality. + PassThroughVerifier::new(false) // use non-instant finality. } fn make_block_import(&self, client: PeersClient) @@ -214,6 +216,20 @@ sp_api::mock_impl_runtime_apis! { fn grandpa_authorities(&self) -> AuthorityList { self.inner.genesis_authorities.clone() } + + fn submit_report_equivocation_extrinsic( + _equivocation_proof: EquivocationProof, + _key_owner_proof: OpaqueKeyOwnershipProof, + ) -> Option<()> { + None + } + + fn generate_key_ownership_proof( + _set_id: SetId, + _authority_id: AuthorityId, + ) -> Option { + None + } } } @@ -266,7 +282,7 @@ fn make_ids(keys: &[Ed25519Keyring]) -> AuthorityList { keys.iter().map(|key| key.clone().public().into()).map(|id| (id, 1)).collect() } -fn create_keystore(authority: Ed25519Keyring) -> (KeyStorePtr, tempfile::TempDir) { +fn create_keystore(authority: Ed25519Keyring) -> (BareCryptoStorePtr, tempfile::TempDir) { let keystore_path = tempfile::tempdir().expect("Creates keystore path"); let keystore = sc_keystore::Store::open(keystore_path.path(), None).expect("Creates keystore"); keystore.write().insert_ephemeral_from_seed::(&authority.to_seed()) @@ -295,8 +311,6 @@ fn run_to_completion_with( ) -> u64 where F: FnOnce(Handle) -> Option>>> { - use parking_lot::RwLock; - let mut wait_for = Vec::new(); let highest_finalized = Arc::new(RwLock::new(0)); @@ -354,6 +368,7 @@ fn run_to_completion_with( telemetry_on_connect: None, voting_rule: (), prometheus_registry: None, + shared_voter_state: SharedVoterState::empty(), }; let voter = run_grandpa_voter(grandpa_params).expect("all in order with client and network"); @@ -485,6 +500,7 @@ fn finalize_3_voters_1_full_observer() { telemetry_on_connect: None, voting_rule: (), prometheus_registry: None, + shared_voter_state: SharedVoterState::empty(), }; voters.push(run_grandpa_voter(grandpa_params).expect("all in order with client and network")); @@ -648,6 +664,7 @@ fn transition_3_voters_twice_1_full_observer() { telemetry_on_connect: None, voting_rule: (), prometheus_registry: None, + shared_voter_state: SharedVoterState::empty(), }; let voter = run_grandpa_voter(grandpa_params).expect("all in order with client and network"); @@ -990,7 +1007,6 @@ fn test_bad_justification() { #[test] fn voter_persists_its_votes() { - use std::iter::FromIterator; use std::sync::atomic::{AtomicUsize, Ordering}; use futures::future; use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver}; @@ -1034,7 +1050,7 @@ fn voter_persists_its_votes() { voter_rx: TracingUnboundedReceiver<()>, net: Arc>, client: PeersClient, - keystore: KeyStorePtr, + keystore: BareCryptoStorePtr, } impl Future for ResettableVoter { @@ -1073,6 +1089,7 @@ fn voter_persists_its_votes() { telemetry_on_connect: None, voting_rule: VotingRulesBuilder::default().build(), prometheus_registry: None, + shared_voter_state: SharedVoterState::empty(), }; let voter = run_grandpa_voter(grandpa_params) @@ -1119,7 +1136,7 @@ fn voter_persists_its_votes() { let config = Config { gossip_duration: TEST_GOSSIP_DURATION, justification_period: 32, - keystore: Some(keystore), + keystore: Some(keystore.clone()), name: Some(format!("peer#{}", 1)), is_authority: true, observer_enabled: true, @@ -1143,10 +1160,10 @@ fn voter_persists_its_votes() { ); let (round_rx, round_tx) = network.round_communication( + Some((peers[1].public().into(), keystore).into()), communication::Round(1), communication::SetId(0), - Arc::new(VoterSet::from_iter(voters)), - Some(peers[1].pair().into()), + Arc::new(VoterSet::new(voters).unwrap()), HasVoted::No, ); @@ -1418,6 +1435,7 @@ fn voter_catches_up_to_latest_round_when_behind() { telemetry_on_connect: None, voting_rule: (), prometheus_registry: None, + shared_voter_state: SharedVoterState::empty(), }; Box::pin(run_grandpa_voter(grandpa_params).expect("all in order with client and network")) @@ -1662,7 +1680,7 @@ fn imports_justification_for_regular_blocks_on_import() { }; let msg = finality_grandpa::Message::Precommit(precommit.clone()); - let encoded = communication::localized_payload(round, set_id, &msg); + let encoded = sp_finality_grandpa::localized_payload(round, set_id, &msg); let signature = peers[0].sign(&encoded[..]).into(); let precommit = finality_grandpa::SignedPrecommit { diff --git a/client/finality-grandpa/src/until_imported.rs b/client/finality-grandpa/src/until_imported.rs index 40da7707b6735262d115015422ef3b01c69eebff..3ac94f3b062f0273f975e714c7318b9539243dae 100644 --- a/client/finality-grandpa/src/until_imported.rs +++ b/client/finality-grandpa/src/until_imported.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Helper stream for waiting until one or more blocks are imported before //! passing through inner items. This is done in a generic way to support @@ -31,7 +33,7 @@ use super::{ use log::{debug, warn}; use sp_utils::mpsc::TracingUnboundedReceiver; use futures::prelude::*; -use futures::stream::Fuse; +use futures::stream::{Fuse, StreamExt}; use futures_timer::Delay; use finality_grandpa::voter; use parking_lot::Mutex; @@ -137,17 +139,19 @@ impl Drop for Metrics { } } -/// Buffering imported messages until blocks with given hashes are imported. -#[pin_project::pin_project] -pub(crate) struct UntilImported> { +/// Buffering incoming messages until blocks with given hashes are imported. +pub(crate) struct UntilImported where + Block: BlockT, + I: Stream + Unpin, + M: BlockUntilImported, +{ import_notifications: Fuse>>, block_sync_requester: BlockSyncRequester, status_check: BlockStatus, - #[pin] - inner: Fuse, + incoming_messages: Fuse, ready: VecDeque, /// Interval at which to check status of each awaited block. - check_pending: Pin> + Send>>, + check_pending: Pin> + Send + Sync>>, /// 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. @@ -159,11 +163,17 @@ pub(crate) struct UntilImported, } +impl Unpin for UntilImported where + Block: BlockT, + I: Stream + Unpin, + M: BlockUntilImported, +{} + impl UntilImported where Block: BlockT, BlockStatus: BlockStatusT, BlockSyncRequester: BlockSyncRequesterT, - I: Stream, + I: Stream + Unpin, M: BlockUntilImported, { /// Create a new `UntilImported` wrapper. @@ -171,7 +181,7 @@ impl UntilImported, block_sync_requester: BlockSyncRequester, status_check: BlockStatus, - stream: I, + incoming_messages: I, identifier: &'static str, metrics: Option, ) -> Self { @@ -192,7 +202,7 @@ impl UntilImported Stream for UntilImported, BSyncRequester: BlockSyncRequesterT, - I: Stream, + I: Stream + Unpin, M: BlockUntilImported, { type Item = Result; - fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - // We are using a `this` variable in order to allow multiple simultaneous mutable borrow - // to `self`. - let mut this = self.project(); + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + // We are using a `this` variable in order to allow multiple simultaneous mutable borrow to + // `self`. + let this = &mut *self; loop { - match Stream::poll_next(Pin::new(&mut this.inner), cx) { + match StreamExt::poll_next_unpin(&mut this.incoming_messages, cx) { Poll::Ready(None) => return Poll::Ready(None), Poll::Ready(Some(input)) => { // new input: schedule wait of any parts which require // blocks to be known. - match M::needs_waiting(input, this.status_check)? { + match M::needs_waiting(input, &this.status_check)? { DiscardWaitOrReady::Discard => {}, DiscardWaitOrReady::Wait(items) => { for (target_hash, target_number, wait) in items { @@ -245,12 +255,12 @@ impl Stream for UntilImported return Poll::Ready(None), Poll::Ready(Some(notification)) => { // new block imported. queue up all messages tied to that hash. if let Some((_, _, messages)) = this.pending.remove(¬ification.hash) { - let canon_number = notification.header.number().clone(); + let canon_number = *notification.header.number(); let ready_messages = messages.into_iter() .filter_map(|m| m.wait_completed(canon_number)); @@ -315,7 +325,7 @@ impl Stream for UntilImported BlockUntilImported for SignedMessage { } } - return Ok(DiscardWaitOrReady::Wait(vec![(target_hash, target_number, msg)])) + Ok(DiscardWaitOrReady::Wait(vec![(target_hash, target_number, msg)])) } fn wait_completed(self, canon_number: NumberFor) -> Option { @@ -422,7 +432,7 @@ impl BlockUntilImported for BlockGlobalMessage { let mut query_known = |target_hash, perceived_number| -> Result { // check integrity: all votes for same hash have same number. let canon_number = match checked_hashes.entry(target_hash) { - Entry::Occupied(entry) => entry.get().number().clone(), + Entry::Occupied(entry) => *entry.get().number(), Entry::Vacant(entry) => { if let Some(number) = status_check.block_number(target_hash)? { entry.insert(KnownOrUnknown::Known(number)); @@ -575,7 +585,7 @@ mod tests { origin: BlockOrigin::File, header, is_new_best: false, - retracted: vec![], + tree_route: None, }).unwrap(); } } diff --git a/client/finality-grandpa/src/voting_rule.rs b/client/finality-grandpa/src/voting_rule.rs index 523a1b05cd488645c557b6dfdef69d5c3ed1f7ac..60493867ce1f4c4e9c50e662857ef1ffcd842cba 100644 --- a/client/finality-grandpa/src/voting_rule.rs +++ b/client/finality-grandpa/src/voting_rule.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Handling custom voting rules for GRANDPA. //! @@ -68,7 +70,8 @@ impl VotingRule for () where } /// A custom voting rule that guarantees that our vote is always behind the best -/// block, in the best case exactly one block behind it. +/// block by at least N blocks. In the best case our vote is exactly N blocks +/// behind the best block. #[derive(Clone)] pub struct BeforeBestBlockBy(N); impl VotingRule for BeforeBestBlockBy> where diff --git a/client/informant/Cargo.toml b/client/informant/Cargo.toml index b60886d6dea6cfbb7d4b9151f2a2498b81be4404..74ce14cbbcc49cf8f9e325fa620849f3e7b2b0f2 100644 --- a/client/informant/Cargo.toml +++ b/client/informant/Cargo.toml @@ -1,24 +1,25 @@ [package] name = "sc-informant" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] description = "Substrate informant." edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] ansi_term = "0.12.1" futures = "0.3.4" log = "0.4.8" -parity-util-mem = { version = "0.6.0", default-features = false, features = ["primitive-types"] } +parity-util-mem = { version = "0.7.0", default-features = false, features = ["primitive-types"] } +sc-client-api = { version = "2.0.0-rc4", path = "../api" } +sc-network = { version = "0.8.0-rc4", path = "../network" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../primitives/blockchain" } +sp-runtime = { version = "2.0.0-rc4", path = "../../primitives/runtime" } +sp-utils = { version = "2.0.0-rc2", path = "../../primitives/utils" } +sp-transaction-pool = { version = "2.0.0-rc2", path = "../../primitives/transaction-pool" } wasm-timer = "0.2" -sc-client-api = { version = "2.0.0-alpha.5", path = "../api" } -sc-network = { version = "0.8.0-alpha.5", path = "../network" } -sc-service = { version = "0.8.0-alpha.5", default-features = false, path = "../service" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../primitives/blockchain" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../primitives/runtime" } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/client/informant/src/display.rs b/client/informant/src/display.rs index 42f498998362e6eb1a6d02f4af1fc98ce285030f..4491eb61d69cafcbdc7813e680c024c844db03a5 100644 --- a/client/informant/src/display.rs +++ b/client/informant/src/display.rs @@ -14,15 +14,17 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . +use crate::OutputFormat; use ansi_term::Colour; -use sc_client_api::ClientInfo; use log::info; -use sc_network::SyncState; -use sp_runtime::traits::{Block as BlockT, CheckedDiv, NumberFor, Zero, Saturating}; -use sc_service::NetworkStatus; -use std::{convert::{TryFrom, TryInto}, fmt}; +use sc_client_api::ClientInfo; +use sc_network::{NetworkStatus, SyncState}; +use sp_runtime::traits::{Block as BlockT, CheckedDiv, NumberFor, Saturating, Zero}; +use std::{ + convert::{TryFrom, TryInto}, + fmt, +}; use wasm_timer::Instant; -use crate::OutputFormat; /// State of the informant display system. /// @@ -67,16 +69,22 @@ impl InformantDisplay { self.last_update = Instant::now(); self.last_number = Some(best_number); - let (status, target) = match (net_status.sync_state, net_status.best_seen_block) { - (SyncState::Idle, _) => ("💤 Idle".into(), "".into()), - (SyncState::Downloading, None) => (format!("⚙️ Preparing{}", speed), "".into()), - (SyncState::Downloading, Some(n)) => (format!("⚙️ Syncing{}", speed), format!(", target=#{}", n)), + let (level, status, target) = match (net_status.sync_state, net_status.best_seen_block) { + (SyncState::Idle, _) => ("💤", "Idle".into(), "".into()), + (SyncState::Downloading, None) => ("⚙️ ", format!("Preparing{}", speed), "".into()), + (SyncState::Downloading, Some(n)) => ( + "⚙️ ", + format!("Syncing{}", speed), + format!(", target=#{}", n), + ), }; - if self.format == OutputFormat::Coloured { + if self.format.enable_color { info!( target: "substrate", - "{}{} ({} peers), best: #{} ({}), finalized #{} ({}), {} {}", + "{} {}{}{} ({} peers), best: #{} ({}), finalized #{} ({}), {} {}", + level, + self.format.prefix, Colour::White.bold().paint(&status), target, Colour::White.bold().paint(format!("{}", num_connected_peers)), @@ -86,11 +94,13 @@ impl InformantDisplay { info.chain.finalized_hash, Colour::Green.paint(format!("⬇ {}", TransferRateFormat(net_status.average_download_per_sec))), Colour::Red.paint(format!("⬆ {}", TransferRateFormat(net_status.average_upload_per_sec))), - ); + ) } else { info!( target: "substrate", - "{}{} ({} peers), best: #{} ({}), finalized #{} ({}), ⬇ {} ⬆ {}", + "{} {}{}{} ({} peers), best: #{} ({}), finalized #{} ({}), ⬇ {} ⬆ {}", + level, + self.format.prefix, status, target, num_connected_peers, @@ -100,7 +110,7 @@ impl InformantDisplay { info.chain.finalized_hash, TransferRateFormat(net_status.average_download_per_sec), TransferRateFormat(net_status.average_upload_per_sec), - ); + ) } } } diff --git a/client/informant/src/lib.rs b/client/informant/src/lib.rs index 66d5ed41fb5d418a2bae0952dc263cdee6ff8c84..3daf29a9f78371d58ee34b996a0302a7fb9bd8a8 100644 --- a/client/informant/src/lib.rs +++ b/client/informant/src/lib.rs @@ -1,49 +1,103 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Console informant. Prints sync progress and block events. Runs on the calling thread. use ansi_term::Colour; -use sc_client_api::BlockchainEvents; use futures::prelude::*; -use log::{info, warn, trace}; -use sp_runtime::traits::Header; -use sc_service::AbstractService; -use std::time::Duration; +use log::{info, trace, warn}; +use parity_util_mem::MallocSizeOf; +use sc_client_api::{BlockchainEvents, UsageProvider}; +use sc_network::{network_state::NetworkState, NetworkStatus}; +use sp_blockchain::HeaderMetadata; +use sp_runtime::traits::{Block as BlockT, Header}; +use sp_transaction_pool::TransactionPool; +use sp_utils::{status_sinks, mpsc::tracing_unbounded}; +use std::{fmt::Display, sync::Arc, time::Duration, collections::VecDeque}; mod display; /// The format to print telemetry output in. -#[derive(PartialEq)] -pub enum OutputFormat { - Coloured, - Plain, +#[derive(Clone, Debug)] +pub struct OutputFormat { + /// Enable color output in logs. True by default. + pub enable_color: bool, + /// Defines the informant's prefix for the logs. An empty string by default. + /// + /// By default substrate will show logs without a prefix. Example: + /// + /// ```text + /// 2020-05-28 15:11:06 ✨ Imported #2 (0xc21c…2ca8) + /// 2020-05-28 15:11:07 💤 Idle (0 peers), best: #2 (0xc21c…2ca8), finalized #0 (0x7299…e6df), ⬇ 0 ⬆ 0 + /// ``` + /// + /// But you can define a prefix by setting this string. This will output: + /// + /// ```text + /// 2020-05-28 15:11:06 ✨ [Prefix] Imported #2 (0xc21c…2ca8) + /// 2020-05-28 15:11:07 💤 [Prefix] Idle (0 peers), best: #2 (0xc21c…2ca8), finalized #0 (0x7299…e6df), ⬇ 0 ⬆ 0 + /// ``` + pub prefix: String, } -/// Creates an informant in the form of a `Future` that must be polled regularly. -pub fn build(service: &impl AbstractService, format: OutputFormat) -> impl futures::Future { - let client = service.client(); - let pool = service.transaction_pool(); - - let mut display = display::InformantDisplay::new(format); +impl Default for OutputFormat { + fn default() -> Self { + Self { + enable_color: true, + prefix: String::new(), + } + } +} - let display_notifications = service - .network_status(Duration::from_millis(5000)) +/// Marker trait for a type that implements `TransactionPool` and `MallocSizeOf` on `not(target_os = "unknown")`. +#[cfg(target_os = "unknown")] +pub trait TransactionPoolAndMaybeMallogSizeOf: TransactionPool {} + +/// Marker trait for a type that implements `TransactionPool` and `MallocSizeOf` on `not(target_os = "unknown")`. +#[cfg(not(target_os = "unknown"))] +pub trait TransactionPoolAndMaybeMallogSizeOf: TransactionPool + MallocSizeOf {} + +#[cfg(target_os = "unknown")] +impl TransactionPoolAndMaybeMallogSizeOf for T {} + +#[cfg(not(target_os = "unknown"))] +impl TransactionPoolAndMaybeMallogSizeOf for T {} + +/// Builds the informant and returns a `Future` that drives the informant. +pub fn build( + client: Arc, + network_status_sinks: Arc, NetworkState)>>, + pool: Arc, + format: OutputFormat, +) -> impl futures::Future +where + C: UsageProvider + HeaderMetadata + BlockchainEvents, + >::Error: Display, +{ + let mut display = display::InformantDisplay::new(format.clone()); + + let client_1 = client.clone(); + let (network_status_sink, network_status_stream) = tracing_unbounded("mpsc_network_status"); + network_status_sinks.push(Duration::from_millis(5000), network_status_sink); + + let display_notifications = network_status_stream .for_each(move |(net_status, _)| { - let info = client.usage_info(); + let info = client_1.usage_info(); if let Some(ref usage) = info.usage { trace!(target: "usage", "Usage statistics: {}", usage); } else { @@ -62,13 +116,30 @@ pub fn build(service: &impl AbstractService, format: OutputFormat) -> impl futur future::ready(()) }); - let client = service.client(); + future::join( + display_notifications, + display_block_import(client, format.prefix), + ).map(|_| ()) +} + +fn display_block_import( + client: Arc, + prefix: String, +) -> impl Future +where + C: UsageProvider + HeaderMetadata + BlockchainEvents, + >::Error: Display, +{ let mut last_best = { let info = client.usage_info(); Some((info.chain.best_number, info.chain.best_hash)) }; - let display_block_import = client.import_notification_stream().for_each(move |n| { + // Hashes of the last blocks we have seen at import. + let mut last_blocks = VecDeque::new(); + let max_blocks_to_track = 100; + + client.import_notification_stream().for_each(move |n| { // 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 { @@ -80,7 +151,8 @@ pub fn build(service: &impl AbstractService, format: OutputFormat) -> impl futur match maybe_ancestor { Ok(ref ancestor) if ancestor.hash != *last_hash => info!( - "♻️ Reorg on #{},{} to #{},{}, common ancestor #{},{}", + "♻️ {}Reorg on #{},{} to #{},{}, common ancestor #{},{}", + prefix, Colour::Red.bold().paint(format!("{}", last_num)), last_hash, Colour::Green.bold().paint(format!("{}", n.header.number())), n.hash, Colour::White.bold().paint(format!("{}", ancestor.number)), ancestor.hash, @@ -95,12 +167,25 @@ pub fn build(service: &impl AbstractService, format: OutputFormat) -> impl futur last_best = Some((n.header.number().clone(), n.hash.clone())); } - info!(target: "substrate", "✨ Imported #{} ({})", Colour::White.bold().paint(format!("{}", n.header.number())), n.hash); - future::ready(()) - }); - future::join( - display_notifications, - display_block_import - ).map(|_| ()) + // If we already printed a message for a given block recently, + // we should not print it again. + if !last_blocks.contains(&n.hash) { + last_blocks.push_back(n.hash.clone()); + + if last_blocks.len() > max_blocks_to_track { + last_blocks.pop_front(); + } + + info!( + target: "substrate", + "✨ {}Imported #{} ({})", + prefix, + Colour::White.bold().paint(format!("{}", n.header.number())), + n.hash, + ); + } + + future::ready(()) + }) } diff --git a/client/keystore/Cargo.toml b/client/keystore/Cargo.toml index af9cdf81bfe9a472f12dd4284001b95934ce0bd7..585d3af5215d12d4ca0fcc5600c7458b1f3eaeca 100644 --- a/client/keystore/Cargo.toml +++ b/client/keystore/Cargo.toml @@ -1,27 +1,28 @@ [package] name = "sc-keystore" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Keystore (and session key management) for ed25519 based chains like Polkadot." documentation = "https://docs.rs/sc-keystore" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] derive_more = "0.99.2" -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -sp-application-crypto = { version = "2.0.0-alpha.5", path = "../../primitives/application-crypto" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +sp-application-crypto = { version = "2.0.0-rc4", path = "../../primitives/application-crypto" } hex = "0.4.0" +merlin = { version = "2.0", default-features = false } +parking_lot = "0.10.0" rand = "0.7.2" serde_json = "1.0.41" subtle = "2.1.1" -parking_lot = "0.10.0" [dev-dependencies] tempfile = "3.1.0" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/client/keystore/src/lib.rs b/client/keystore/src/lib.rs index f8bc93097113b300bc85373918021da742700221..7fec32bae246ace852d042a6f1a9c47c1cb1ee3f 100644 --- a/client/keystore/src/lib.rs +++ b/client/keystore/src/lib.rs @@ -19,11 +19,13 @@ #![warn(missing_docs)] use std::{collections::{HashMap, HashSet}, path::PathBuf, fs::{self, File}, io::{self, Write}, sync::Arc}; use sp_core::{ - crypto::{IsWrappedBy, CryptoTypePublicPair, KeyTypeId, Pair as PairT, Protected, Public}, - traits::{BareCryptoStore, BareCryptoStoreError as TraitError}, + crypto::{IsWrappedBy, CryptoTypePublicPair, KeyTypeId, Pair as PairT, ExposeSecret, SecretString, Public}, + traits::{BareCryptoStore, Error as TraitError}, + sr25519::{Public as Sr25519Public, Pair as Sr25519Pair}, + vrf::{VRFTranscriptData, VRFSignature, make_transcript}, Encode, }; -use sp_application_crypto::{AppKey, AppPublic, AppPair, ed25519, sr25519}; +use sp_application_crypto::{AppKey, AppPublic, AppPair, ed25519, sr25519, ecdsa}; use parking_lot::RwLock; /// Keystore pointer @@ -93,14 +95,14 @@ pub struct Store { path: Option, /// Map over `(KeyTypeId, Raw public key)` -> `Key phrase/seed` additional: HashMap<(KeyTypeId, Vec), String>, - password: Option>, + password: Option, } impl Store { /// Open the store at the given path. /// /// Optionally takes a password that will be used to encrypt/decrypt the keys. - pub fn open>(path: T, password: Option>) -> Result { + pub fn open>(path: T, password: Option) -> Result { let path = path.into(); fs::create_dir_all(&path)?; @@ -153,7 +155,7 @@ impl Store { pub fn insert_by_type(&self, key_type: KeyTypeId, suri: &str) -> Result { let pair = Pair::from_string( suri, - self.password.as_ref().map(|p| &***p) + self.password() ).map_err(|_| Error::InvalidSeed)?; self.insert_unknown(key_type, suri, pair.public().as_slice()) .map_err(|_| Error::Unavailable)?; @@ -171,7 +173,7 @@ impl Store { /// /// Places it into the file system store. pub fn generate_by_type(&self, key_type: KeyTypeId) -> Result { - let (pair, phrase, _) = Pair::generate_with_phrase(self.password.as_ref().map(|p| &***p)); + let (pair, phrase, _) = Pair::generate_with_phrase(self.password()); if let Some(path) = self.key_file_path(pair.public().as_slice(), key_type) { let mut file = File::create(path)?; serde_json::to_writer(&file, &phrase)?; @@ -227,7 +229,7 @@ impl Store { let phrase = self.key_phrase_by_type(public.as_slice(), key_type)?; let pair = Pair::from_string( &phrase, - self.password.as_ref().map(|p| &***p), + self.password(), ).map_err(|_| Error::InvalidPhrase)?; if &pair.public() == public { @@ -270,7 +272,7 @@ impl Store { fn raw_public_keys(&self, id: KeyTypeId) -> Result>> { let mut public_keys: Vec> = self.additional.keys() .into_iter() - .filter_map(|k| if k.0 == id { Some(k.1.clone()) } else { None }) + .filter_map(|k| if k.0 == id { Some(k.1.clone()) } else { None }) .collect(); if let Some(path) = &self.path { @@ -308,6 +310,7 @@ impl BareCryptoStore for Store { .fold(Vec::new(), |mut v, k| { v.push(CryptoTypePublicPair(sr25519::CRYPTO_ID, k.clone())); v.push(CryptoTypePublicPair(ed25519::CRYPTO_ID, k.clone())); + v.push(CryptoTypePublicPair(ecdsa::CRYPTO_ID, k.clone())); v })) } @@ -343,6 +346,13 @@ impl BareCryptoStore for Store { .key_pair_by_type::(&pub_key, id) .map_err(|e| TraitError::from(e))?; Ok(key_pair.sign(msg).encode()) + }, + ecdsa::CRYPTO_ID => { + let pub_key = ecdsa::Public::from_slice(key.1.as_slice()); + let key_pair: ecdsa::Pair = self + .key_pair_by_type::(&pub_key, id) + .map_err(|e| TraitError::from(e))?; + Ok(key_pair.sign(msg).encode()) } _ => Err(TraitError::KeyNotSupported(id)) } @@ -355,7 +365,7 @@ impl BareCryptoStore for Store { .map(|k| sr25519::Public::from_slice(k.as_slice())) .collect() }) - .unwrap_or_default() + .unwrap_or_default() } fn sr25519_generate_new( @@ -394,6 +404,29 @@ impl BareCryptoStore for Store { Ok(pair.public()) } + fn ecdsa_public_keys(&self, key_type: KeyTypeId) -> Vec { + self.raw_public_keys(key_type) + .map(|v| { + v.into_iter() + .map(|k| ecdsa::Public::from_slice(k.as_slice())) + .collect() + }) + .unwrap_or_default() + } + + fn ecdsa_generate_new( + &mut self, + id: KeyTypeId, + seed: Option<&str>, + ) -> std::result::Result { + let pair = match seed { + Some(seed) => self.insert_ephemeral_from_seed_by_type::(seed, id), + None => self.generate_by_type::(id), + }.map_err(|e| -> TraitError { e.into() })?; + + Ok(pair.public()) + } + fn insert_unknown(&mut self, key_type: KeyTypeId, suri: &str, public: &[u8]) -> std::result::Result<(), ()> { @@ -401,12 +434,31 @@ impl BareCryptoStore for Store { } fn password(&self) -> Option<&str> { - self.password.as_ref().map(|x| x.as_str()) + self.password.as_ref() + .map(|p| p.expose_secret()) + .map(|p| p.as_str()) } fn has_keys(&self, public_keys: &[(Vec, KeyTypeId)]) -> bool { public_keys.iter().all(|(p, t)| self.key_phrase_by_type(&p, *t).is_ok()) } + + fn sr25519_vrf_sign( + &self, + key_type: KeyTypeId, + public: &Sr25519Public, + transcript_data: VRFTranscriptData, + ) -> std::result::Result { + let transcript = make_transcript(transcript_data); + let pair = self.key_pair_by_type::(public, key_type) + .map_err(|e| TraitError::PairNotFound(e.to_string()))?; + + let (inout, proof, _) = pair.as_ref().vrf_sign(transcript); + Ok(VRFSignature { + output: inout.to_output(), + proof, + }) + } } #[cfg(test)] @@ -414,6 +466,7 @@ mod tests { use super::*; use tempfile::TempDir; use sp_core::{testing::SR25519, crypto::Ss58Codec}; + use std::str::FromStr; #[test] fn basic_store() { @@ -454,7 +507,10 @@ mod tests { fn password_being_used() { let password = String::from("password"); let temp_dir = TempDir::new().unwrap(); - let store = Store::open(temp_dir.path(), Some(password.clone().into())).unwrap(); + let store = Store::open( + temp_dir.path(), + Some(FromStr::from_str(password.as_str()).unwrap()), + ).unwrap(); let pair: ed25519::AppPair = store.write().generate().unwrap(); assert_eq!( @@ -466,7 +522,10 @@ mod tests { let store = Store::open(temp_dir.path(), None).unwrap(); assert!(store.read().key_pair::(&pair.public()).is_err()); - let store = Store::open(temp_dir.path(), Some(password.into())).unwrap(); + let store = Store::open( + temp_dir.path(), + Some(FromStr::from_str(password.as_str()).unwrap()), + ).unwrap(); assert_eq!( pair.public(), store.read().key_pair::(&pair.public()).unwrap().public(), diff --git a/client/light/Cargo.toml b/client/light/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..ced9989c9e9092244c1693c86c7d8bf3357e5a47 --- /dev/null +++ b/client/light/Cargo.toml @@ -0,0 +1,27 @@ +[package] +description = "components for a light client" +name = "sc-light" +version = "2.0.0-rc4" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +authors = ["Parity Technologies "] +edition = "2018" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +documentation = "https://docs.rs/sc-light" + +[dependencies] +parking_lot = "0.10.0" +lazy_static = "1.4.0" +hash-db = "0.15.2" +sp-runtime = { version = "2.0.0-rc2", path = "../../primitives/runtime" } +sp-externalities = { version = "0.8.0-rc2", path = "../../primitives/externalities" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../primitives/blockchain" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +sp-state-machine = { version = "0.8.0-rc2", path = "../../primitives/state-machine" } +sc-client-api = { version = "2.0.0-rc2", path = "../api" } +sp-api = { version = "2.0.0-rc2", path = "../../primitives/api" } +codec = { package = "parity-scale-codec", version = "1.3.1" } +sc-executor = { version = "0.8.0-rc2", path = "../executor" } + +[features] +default = [] diff --git a/client/src/light/backend.rs b/client/light/src/backend.rs similarity index 78% rename from client/src/light/backend.rs rename to client/light/src/backend.rs index 0b334d48b7a251a6173f292e9416e0fa7925d6da..2cf994d3f5993c3f2f0681c0db8cee026234bdf3 100644 --- a/client/src/light/backend.rs +++ b/client/light/src/backend.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Light client backend. Only stores headers and justifications of blocks. //! Everything else is requested from full nodes on demand. @@ -24,7 +26,7 @@ use parking_lot::RwLock; use codec::{Decode, Encode}; use sp_core::ChangesTrieConfiguration; -use sp_core::storage::{well_known_keys, ChildInfo, OwnedChildInfo}; +use sp_core::storage::{well_known_keys, ChildInfo}; use sp_core::offchain::storage::InMemOffchainStorage; use sp_state_machine::{ Backend as StateBackend, TrieBackend, InMemoryBackend, ChangesTrieTransaction, @@ -32,7 +34,6 @@ use sp_state_machine::{ }; use sp_runtime::{generic::BlockId, Justification, Storage}; use sp_runtime::traits::{Block as BlockT, NumberFor, Zero, Header, HashFor}; -use crate::in_mem::check_genesis_storage; use sp_blockchain::{Error as ClientError, Result as ClientResult}; use sc_client_api::{ backend::{ @@ -43,9 +44,10 @@ use sc_client_api::{ HeaderBackend as BlockchainHeaderBackend, well_known_cache_keys, }, light::Storage as BlockchainStorage, + in_mem::check_genesis_storage, UsageInfo, }; -use crate::light::blockchain::Blockchain; +use super::blockchain::Blockchain; use hash_db::Hasher; const IN_MEMORY_EXPECT_PROOF: &str = "InMemory state backend has Void error type and always succeeds; qed"; @@ -251,7 +253,7 @@ where .unwrap_or(false) } - fn remote_blockchain(&self) -> Arc> { + fn remote_blockchain(&self) -> Arc> { self.blockchain.clone() } } @@ -312,17 +314,17 @@ impl BlockImportOperation for ImportOperation self.changes_trie_config_update = Some(changes_trie_config); // this is only called when genesis block is imported => shouldn't be performance bottleneck - let mut storage: HashMap, OwnedChildInfo)>, _> = HashMap::new(); + let mut storage: HashMap, _> = HashMap::new(); storage.insert(None, input.top); // create a list of children keys to re-compute roots for - let child_delta = input.children.iter() - .map(|(storage_key, storage_child)| (storage_key.clone(), None, storage_child.child_info.clone())) - .collect::>(); + let child_delta = input.children_default + .iter() + .map(|(_storage_key, storage_child)| (&storage_child.child_info, std::iter::empty())); // make sure to persist the child storage - for (child_key, storage_child) in input.children { - storage.insert(Some((child_key, storage_child.child_info)), storage_child.data); + for (_child_key, storage_child) in input.children_default.clone() { + storage.insert(Some(storage_child.child_info), storage_child.data); } let storage_update = InMemoryBackend::from(storage); @@ -348,7 +350,11 @@ impl BlockImportOperation for ImportOperation Ok(()) } - fn mark_finalized(&mut self, block: BlockId, _justification: Option) -> ClientResult<()> { + fn mark_finalized( + &mut self, + block: BlockId, + _justification: Option, + ) -> ClientResult<()> { self.finalized_blocks.push(block); Ok(()) } @@ -386,13 +392,12 @@ impl StateBackend for GenesisOrUnavailableState fn child_storage( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) -> ClientResult>> { match *self { GenesisOrUnavailableState::Genesis(ref state) => - Ok(state.child_storage(storage_key, child_info, key).expect(IN_MEMORY_EXPECT_PROOF)), + Ok(state.child_storage(child_info, key).expect(IN_MEMORY_EXPECT_PROOF)), GenesisOrUnavailableState::Unavailable => Err(ClientError::NotAvailableOnLightClient), } } @@ -407,13 +412,12 @@ impl StateBackend for GenesisOrUnavailableState fn next_child_storage_key( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) -> Result>, Self::Error> { match *self { GenesisOrUnavailableState::Genesis(ref state) => Ok( - state.next_child_storage_key(storage_key, child_info, key) + state.next_child_storage_key(child_info, key) .expect(IN_MEMORY_EXPECT_PROOF) ), GenesisOrUnavailableState::Unavailable => Err(ClientError::NotAvailableOnLightClient), @@ -436,35 +440,33 @@ impl StateBackend for GenesisOrUnavailableState fn for_keys_in_child_storage( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, action: A, ) { match *self { GenesisOrUnavailableState::Genesis(ref state) => - state.for_keys_in_child_storage(storage_key, child_info, action), + state.for_keys_in_child_storage(child_info, action), GenesisOrUnavailableState::Unavailable => (), } } fn for_child_keys_with_prefix( &self, - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, prefix: &[u8], action: A, ) { match *self { GenesisOrUnavailableState::Genesis(ref state) => - state.for_child_keys_with_prefix(storage_key, child_info, prefix, action), + state.for_child_keys_with_prefix(child_info, prefix, action), GenesisOrUnavailableState::Unavailable => (), } } - fn storage_root(&self, delta: I) -> (H::Out, Self::Transaction) - where - I: IntoIterator, Option>)> - { + fn storage_root<'a>( + &self, + delta: impl Iterator)>, + ) -> (H::Out, Self::Transaction) where H::Out: Ord { match *self { GenesisOrUnavailableState::Genesis(ref state) => state.storage_root(delta), @@ -472,18 +474,14 @@ impl StateBackend for GenesisOrUnavailableState } } - fn child_storage_root( + fn child_storage_root<'a>( &self, - storage_key: &[u8], - child_info: ChildInfo, - delta: I, - ) -> (H::Out, bool, Self::Transaction) - where - I: IntoIterator, Option>)> - { + child_info: &ChildInfo, + delta: impl Iterator)>, + ) -> (H::Out, bool, Self::Transaction) where H::Out: Ord { match *self { GenesisOrUnavailableState::Genesis(ref state) => { - let (root, is_equal, _) = state.child_storage_root(storage_key, child_info, delta); + let (root, is_equal, _) = state.child_storage_root(child_info, delta); (root, is_equal, Default::default()) }, GenesisOrUnavailableState::Unavailable => @@ -518,53 +516,3 @@ impl StateBackend for GenesisOrUnavailableState } } } - -#[cfg(test)] -mod tests { - use substrate_test_runtime_client::{self, runtime::Block}; - use sc_client_api::backend::NewBlockState; - use crate::light::blockchain::tests::{DummyBlockchain, DummyStorage}; - use sp_runtime::traits::BlakeTwo256; - use super::*; - - #[test] - fn local_state_is_created_when_genesis_state_is_available() { - let def = Default::default(); - let header0 = substrate_test_runtime_client::runtime::Header::new(0, def, def, def, Default::default()); - - let backend: Backend<_, BlakeTwo256> = 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()).unwrap(); - backend.commit_operation(op).unwrap(); - - match backend.state_at(BlockId::Number(0)).unwrap() { - GenesisOrUnavailableState::Genesis(_) => (), - _ => panic!("unexpected state"), - } - } - - #[test] - fn unavailable_state_is_created_when_genesis_state_is_unavailable() { - let backend: Backend<_, BlakeTwo256> = Backend::new( - Arc::new(DummyBlockchain::new(DummyStorage::new())), - ); - - match backend.state_at(BlockId::Number(0)).unwrap() { - GenesisOrUnavailableState::Unavailable => (), - _ => panic!("unexpected state"), - } - } - - #[test] - fn light_aux_store_is_updated_via_non_importing_op() { - let backend = Backend::new(Arc::new(DummyBlockchain::new(DummyStorage::new()))); - let mut op = ClientBackend::::begin_operation(&backend).unwrap(); - BlockImportOperation::::insert_aux(&mut op, vec![(vec![1], Some(vec![2]))]).unwrap(); - ClientBackend::::commit_operation(&backend, op).unwrap(); - - assert_eq!(AuxStore::get_aux(&backend, &[1]).unwrap(), Some(vec![2])); - } -} diff --git a/client/src/light/blockchain.rs b/client/light/src/blockchain.rs similarity index 50% rename from client/src/light/blockchain.rs rename to client/light/src/blockchain.rs index 756147c941b39eaebe4f0e6257a88a33327f31fb..9d557db887d2990549106b5436d0e043ca06a66b 100644 --- a/client/src/light/blockchain.rs +++ b/client/light/src/blockchain.rs @@ -1,31 +1,31 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Light client blockchain backend. Only stores headers and justifications of recent //! blocks. CHT roots are stored for headers of ancient blocks. -use std::future::Future; use std::sync::Arc; use sp_runtime::{Justification, generic::BlockId}; use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero}; use sp_blockchain::{ - HeaderMetadata, CachedHeaderMetadata, - Error as ClientError, Result as ClientResult, + HeaderMetadata, CachedHeaderMetadata, Error as ClientError, Result as ClientResult, }; pub use sc_client_api::{ backend::{ @@ -38,10 +38,10 @@ pub use sc_client_api::{ }, light::{ RemoteBlockchain, LocalOrRemote, Storage - } + }, + cht, }; -use crate::cht; -use crate::light::fetcher::{Fetcher, RemoteHeaderRequest}; +use crate::fetcher::RemoteHeaderRequest; /// Light client blockchain. pub struct Blockchain { @@ -173,154 +173,3 @@ impl RemoteBlockchain for Blockchain })) } } - -/// Returns future that resolves header either locally, or remotely. -pub fn future_header>( - blockchain: &dyn RemoteBlockchain, - fetcher: &F, - id: BlockId, -) -> impl Future, ClientError>> { - use futures::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 substrate_test_runtime_client::runtime::{Hash, Block, Header}; - use sc_client_api::blockchain::Info; - use super::*; - - pub type DummyBlockchain = Blockchain; - - pub struct DummyStorage { - pub changes_tries_cht_roots: HashMap, - pub aux_store: Mutex, Vec>>, - } - - impl DummyStorage { - pub fn new() -> Self { - DummyStorage { - changes_tries_cht_roots: HashMap::new(), - aux_store: Mutex::new(HashMap::new()), - } - } - } - - impl BlockchainHeaderBackend for DummyStorage { - fn header(&self, _id: BlockId) -> ClientResult> { - Err(ClientError::Backend("Test error".into())) - } - - fn info(&self) -> Info { - panic!("Test error") - } - - fn status(&self, _id: BlockId) -> ClientResult { - Err(ClientError::Backend("Test error".into())) - } - - fn number(&self, hash: Hash) -> ClientResult>> { - if hash == Default::default() { - Ok(Some(Default::default())) - } else { - Err(ClientError::Backend("Test error".into())) - } - } - - fn hash(&self, number: u64) -> ClientResult> { - if number == 0 { - Ok(Some(Default::default())) - } else { - Err(ClientError::Backend("Test error".into())) - } - } - } - - 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, - 'b: 'a, - 'c: 'a, - I: IntoIterator, - D: IntoIterator, - >(&self, insert: I, _delete: D) -> ClientResult<()> { - for (k, v) in insert.into_iter() { - self.aux_store.lock().insert(k.to_vec(), v.to_vec()); - } - Ok(()) - } - - fn get_aux(&self, key: &[u8]) -> ClientResult>> { - Ok(self.aux_store.lock().get(key).cloned()) - } - } - - impl Storage for DummyStorage { - fn import_header( - &self, - _header: Header, - _cache: HashMap>, - _state: NewBlockState, - _aux_ops: Vec<(Vec, Option>)>, - ) -> ClientResult<()> { - Ok(()) - } - - fn set_head(&self, _block: BlockId) -> ClientResult<()> { - Err(ClientError::Backend("Test error".into())) - } - - fn finalize_header(&self, _block: BlockId) -> ClientResult<()> { - Err(ClientError::Backend("Test error".into())) - } - - fn last_finalized(&self) -> ClientResult { - Err(ClientError::Backend("Test error".into())) - } - - fn header_cht_root(&self, _cht_size: u64, _block: u64) -> ClientResult> { - Err(ClientError::Backend("Test error".into())) - } - - fn changes_trie_cht_root(&self, cht_size: u64, block: u64) -> ClientResult> { - cht::block_to_cht_number(cht_size, block) - .and_then(|cht_num| self.changes_tries_cht_roots.get(&cht_num)) - .cloned() - .ok_or_else(|| ClientError::Backend( - format!("Test error: CHT for block #{} not found", block) - ).into()) - .map(Some) - } - - fn cache(&self) -> Option>> { - None - } - - fn usage_info(&self) -> Option { - None - } - } -} diff --git a/client/src/light/call_executor.rs b/client/light/src/call_executor.rs similarity index 50% rename from client/src/light/call_executor.rs rename to client/light/src/call_executor.rs index b439a268d2fe18ef4fd1722e7ec2566d4065bea8..81be65339b696cbf3f4b39cf33425a53a8a78bf9 100644 --- a/client/src/light/call_executor.rs +++ b/client/light/src/call_executor.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Methods that light client could use to execute runtime calls. @@ -21,7 +23,7 @@ use std::{ }; use codec::{Encode, Decode}; -use sp_core::{convert_hash, NativeOrEncoded, traits::CodeExecutor}; +use sp_core::{convert_hash, NativeOrEncoded, traits::CodeExecutor, offchain::storage::OffchainOverlayedChanges}; use sp_runtime::{ generic::BlockId, traits::{One, Block as BlockT, Header as HeaderT, HashFor}, }; @@ -108,6 +110,7 @@ impl CallExecutor for method: &str, call_data: &[u8], changes: &RefCell, + offchain_changes: &RefCell, _: Option<&RefCell>>, initialize_block: InitializeBlock<'a, Block>, _manager: ExecutionManager, @@ -134,6 +137,7 @@ impl CallExecutor for method, call_data, changes, + offchain_changes, None, initialize_block, ExecutionManager::NativeWhenPossible, @@ -241,7 +245,11 @@ pub fn check_execution_proof( ) } -fn check_execution_proof_with_make_header Header>( +/// Check remote contextual execution proof using given backend and header factory. +/// +/// Method is executed using passed header as environment' current block. +/// Proof should include both environment preparation proof and method execution proof. +pub fn check_execution_proof_with_make_header( executor: &E, spawn_handle: Box, request: &RemoteCallRequest
, @@ -249,10 +257,11 @@ fn check_execution_proof_with_make_header ClientResult> where - Header: HeaderT, E: CodeExecutor + Clone + 'static, H: Hasher, + Header: HeaderT, H::Out: Ord + codec::Codec + 'static, + MakeNextHeader: Fn(&Header) -> Header, { let local_state_root = request.header.state_root(); let root: H::Out = convert_hash(&local_state_root); @@ -288,231 +297,3 @@ fn check_execution_proof_with_make_header for DummyCallExecutor { - type Error = ClientError; - - type Backend = substrate_test_runtime_client::Backend; - - fn call( - &self, - _id: &BlockId, - _method: &str, - _call_data: &[u8], - _strategy: ExecutionStrategy, - _extensions: 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, - _storage_transaction_cache: Option<&RefCell< - StorageTransactionCache< - Block, - >::State, - > - >>, - _initialize_block: InitializeBlock<'a, Block>, - _execution_manager: ExecutionManager, - _native_call: Option, - _proof_recorder: &Option>, - _extensions: Option, - ) -> ClientResult> where ExecutionManager: Clone { - unreachable!() - } - - fn runtime_version(&self, _id: &BlockId) -> Result { - unreachable!() - } - - fn prove_at_trie_state>>( - &self, - _trie_state: &sp_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, 8) - } - - #[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_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( - &remote_block_id, - method, - &[] - ).unwrap(); - - // check remote execution proof locally - let local_result = check_execution_proof::<_, _, BlakeTwo256>( - &local_executor(), - tasks_executor(), - &RemoteCallRequest { - block: substrate_test_runtime_client::runtime::Hash::default(), - header: remote_header, - method: method.into(), - call_data: vec![], - retry_count: None, - }, - 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::<_, _, BlakeTwo256, _>( - &local_executor(), - tasks_executor(), - &RemoteCallRequest { - block: substrate_test_runtime_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(sp_blockchain::Error::Execution(_)) => (), - _ => panic!("Unexpected execution result: {:?}", execution_result), - } - } - - // prepare remote client - let mut remote_client = substrate_test_runtime_client::new(); - for i in 1u32..3u32 { - let mut digest = Digest::default(); - digest.push(sp_runtime::generic::DigestItem::Other::(i.to_le_bytes().to_vec())); - remote_client.import_justified( - BlockOrigin::Own, - remote_client.new_block(digest).unwrap().build().unwrap().block, - Default::default(), - ).unwrap(); - } - - // check method that doesn't requires environment - 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); - - 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 - sp_panic_handler::set("TEST", "1.2.3"); - execute_with_proof_failure(&remote_client, 2, "Core_version"); - } - - #[test] - fn code_is_executed_at_genesis_only() { - let backend = Arc::new(InMemBackend::::new()); - let def = H256::default(); - let header0 = substrate_test_runtime_client::runtime::Header::new(0, def, def, def, Default::default()); - let hash0 = header0.hash(); - let header1 = substrate_test_runtime_client::runtime::Header::new(1, def, def, hash0, Default::default()); - let hash1 = header1.hash(); - backend.blockchain().insert(hash0, header0, None, None, NewBlockState::Final).unwrap(); - backend.blockchain().insert(hash1, header1, None, None, NewBlockState::Final).unwrap(); - - let genesis_executor = GenesisCallExecutor::new(backend, DummyCallExecutor); - assert_eq!( - genesis_executor.call( - &BlockId::Number(0), - "test_method", - &[], - ExecutionStrategy::NativeElseWasm, - None, - ).unwrap(), - vec![42], - ); - - 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/client/light/src/fetcher.rs b/client/light/src/fetcher.rs new file mode 100644 index 0000000000000000000000000000000000000000..88d20cafc903f38d559926872dc50ab9305515fc --- /dev/null +++ b/client/light/src/fetcher.rs @@ -0,0 +1,343 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Light client data fetcher. Fetches requested data from remote full nodes. + +use std::sync::Arc; +use std::collections::{BTreeMap, HashMap}; +use std::marker::PhantomData; + +use hash_db::{HashDB, Hasher, EMPTY_PREFIX}; +use codec::{Decode, Encode}; +use sp_core::{convert_hash, traits::CodeExecutor}; +use sp_core::storage::{ChildInfo, ChildType}; +use sp_runtime::traits::{ + Block as BlockT, Header as HeaderT, Hash, HashFor, NumberFor, + AtLeast32Bit, CheckedConversion, +}; +use sp_state_machine::{ + ChangesTrieRootsStorage, ChangesTrieAnchorBlockId, ChangesTrieConfigurationRange, + InMemoryChangesTrieStorage, TrieBackend, read_proof_check, key_changes_proof_check_with_db, + read_child_proof_check, CloneableSpawn, +}; +pub use sp_state_machine::StorageProof; +use sp_blockchain::{Error as ClientError, Result as ClientResult}; + +pub use sc_client_api::{ + light::{ + RemoteCallRequest, RemoteHeaderRequest, RemoteReadRequest, RemoteReadChildRequest, + RemoteChangesRequest, ChangesProof, RemoteBodyRequest, Fetcher, FetchChecker, + Storage as BlockchainStorage, + }, + cht, +}; +use crate::blockchain::Blockchain; +use crate::call_executor::check_execution_proof; + +/// Remote data checker. +pub struct LightDataChecker> { + blockchain: Arc>, + executor: E, + spawn_handle: Box, + _hasher: PhantomData<(B, H)>, +} + +impl> LightDataChecker { + /// Create new light data checker. + pub fn new(blockchain: Arc>, executor: E, spawn_handle: Box) -> Self { + Self { + blockchain, executor, spawn_handle, _hasher: PhantomData + } + } + + /// Check remote changes query proof assuming that CHT-s are of given size. + pub fn check_changes_proof_with_cht_size( + &self, + request: &RemoteChangesRequest, + remote_proof: ChangesProof, + cht_size: NumberFor, + ) -> ClientResult, u32)>> + where + H: Hasher, + H::Out: Ord + codec::Codec, + { + // since we need roots of all changes tries for the range begin..max + // => remote node can't use max block greater that one that we have passed + if remote_proof.max_block > request.max_block.0 || remote_proof.max_block < request.last_block.0 { + return Err(ClientError::ChangesTrieAccessFailed(format!( + "Invalid max_block used by the remote node: {}. Local: {}..{}..{}", + remote_proof.max_block, request.first_block.0, request.last_block.0, request.max_block.0, + )).into()); + } + + // check if remote node has responded with extra changes trie roots proofs + // all changes tries roots must be in range [request.first_block.0; request.tries_roots.0) + let is_extra_first_root = remote_proof.roots.keys().next() + .map(|first_root| *first_root < request.first_block.0 + || *first_root >= request.tries_roots.0) + .unwrap_or(false); + let is_extra_last_root = remote_proof.roots.keys().next_back() + .map(|last_root| *last_root >= request.tries_roots.0) + .unwrap_or(false); + if is_extra_first_root || is_extra_last_root { + return Err(ClientError::ChangesTrieAccessFailed(format!( + "Extra changes tries roots proofs provided by the remote node: [{:?}..{:?}]. Expected in range: [{}; {})", + remote_proof.roots.keys().next(), remote_proof.roots.keys().next_back(), + request.first_block.0, request.tries_roots.0, + )).into()); + } + + // if request has been composed when some required headers were already pruned + // => remote node has sent us CHT-based proof of required changes tries roots + // => check that this proof is correct before proceeding with changes proof + let remote_max_block = remote_proof.max_block; + let remote_roots = remote_proof.roots; + let remote_roots_proof = remote_proof.roots_proof; + let remote_proof = remote_proof.proof; + if !remote_roots.is_empty() { + self.check_changes_tries_proof( + cht_size, + &remote_roots, + remote_roots_proof, + )?; + } + + // and now check the key changes proof + get the changes + let mut result = Vec::new(); + let proof_storage = InMemoryChangesTrieStorage::with_proof(remote_proof); + for config_range in &request.changes_trie_configs { + let result_range = key_changes_proof_check_with_db::( + ChangesTrieConfigurationRange { + config: config_range.config.as_ref().ok_or(ClientError::ChangesTriesNotSupported)?, + zero: config_range.zero.0, + end: config_range.end.map(|(n, _)| n), + }, + &RootsStorage { + roots: (request.tries_roots.0, &request.tries_roots.2), + prev_roots: &remote_roots, + }, + &proof_storage, + request.first_block.0, + &ChangesTrieAnchorBlockId { + hash: convert_hash(&request.last_block.1), + number: request.last_block.0, + }, + remote_max_block, + request.storage_key.as_ref(), + &request.key) + .map_err(|err| ClientError::ChangesTrieAccessFailed(err))?; + result.extend(result_range); + } + + Ok(result) + } + + /// Check CHT-based proof for changes tries roots. + pub fn check_changes_tries_proof( + &self, + cht_size: NumberFor, + remote_roots: &BTreeMap, B::Hash>, + remote_roots_proof: StorageProof, + ) -> ClientResult<()> + where + H: Hasher, + H::Out: Ord + codec::Codec, + { + // all the checks are sharing the same storage + let storage = remote_roots_proof.into_memory_db(); + + // remote_roots.keys() are sorted => we can use this to group changes tries roots + // that are belongs to the same CHT + let blocks = remote_roots.keys().cloned(); + cht::for_each_cht_group::(cht_size, blocks, |mut storage, _, cht_blocks| { + // get local changes trie CHT root for given CHT + // it should be there, because it is never pruned AND request has been composed + // when required header has been pruned (=> replaced with CHT) + let first_block = cht_blocks.first().cloned() + .expect("for_each_cht_group never calls callback with empty groups"); + let local_cht_root = self.blockchain.storage().changes_trie_cht_root(cht_size, first_block)? + .ok_or(ClientError::InvalidCHTProof)?; + + // check changes trie root for every block within CHT range + for block in cht_blocks { + // check if the proofs storage contains the root + // normally this happens in when the proving backend is created, but since + // we share the storage for multiple checks, do it here + let mut cht_root = H::Out::default(); + cht_root.as_mut().copy_from_slice(local_cht_root.as_ref()); + if !storage.contains(&cht_root, EMPTY_PREFIX) { + return Err(ClientError::InvalidCHTProof.into()); + } + + // check proof for single changes trie root + let proving_backend = TrieBackend::new(storage, cht_root); + let remote_changes_trie_root = remote_roots[&block]; + cht::check_proof_on_proving_backend::( + local_cht_root, + block, + remote_changes_trie_root, + &proving_backend, + )?; + + // and return the storage to use in following checks + storage = proving_backend.into_storage(); + } + + Ok(storage) + }, storage) + } +} + +impl FetchChecker for LightDataChecker + where + Block: BlockT, + E: CodeExecutor + Clone + 'static, + H: Hasher, + H::Out: Ord + codec::Codec + 'static, + S: BlockchainStorage, +{ + fn check_header_proof( + &self, + request: &RemoteHeaderRequest, + remote_header: Option, + remote_proof: StorageProof, + ) -> ClientResult { + let remote_header = remote_header.ok_or_else(|| + ClientError::from(ClientError::InvalidCHTProof))?; + let remote_header_hash = remote_header.hash(); + cht::check_proof::( + request.cht_root, + request.block, + remote_header_hash, + remote_proof, + ).map(|_| remote_header) + } + + fn check_read_proof( + &self, + request: &RemoteReadRequest, + 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: StorageProof, + ) -> ClientResult, Option>>> { + let child_info = match ChildType::from_prefixed_key(&request.storage_key) { + Some((ChildType::ParentKeyId, storage_key)) => ChildInfo::new_default(storage_key), + None => return Err("Invalid child type".into()), + }; + read_child_proof_check::( + convert_hash(request.header.state_root()), + remote_proof, + &child_info, + request.keys.iter(), + ).map_err(Into::into) + } + + fn check_execution_proof( + &self, + request: &RemoteCallRequest, + remote_proof: StorageProof, + ) -> ClientResult> { + check_execution_proof::<_, _, H>( + &self.executor, + self.spawn_handle.clone(), + request, + remote_proof, + ) + } + + fn check_changes_proof( + &self, + request: &RemoteChangesRequest, + remote_proof: ChangesProof + ) -> ClientResult, u32)>> { + self.check_changes_proof_with_cht_size(request, remote_proof, cht::size()) + } + + fn check_body_proof( + &self, + request: &RemoteBodyRequest, + body: Vec + ) -> ClientResult> { + // TODO: #2621 + let extrinsics_root = HashFor::::ordered_trie_root( + body.iter().map(Encode::encode).collect(), + ); + if *request.header.extrinsics_root() == extrinsics_root { + Ok(body) + } else { + Err(format!("RemoteBodyRequest: invalid extrinsics root expected: {} but got {}", + *request.header.extrinsics_root(), + extrinsics_root, + ).into()) + } + + } +} + +/// A view of BTreeMap as a changes trie roots storage. +struct RootsStorage<'a, Number: AtLeast32Bit, Hash: 'a> { + roots: (Number, &'a [Hash]), + prev_roots: &'a BTreeMap, +} + +impl<'a, H, Number, Hash> ChangesTrieRootsStorage for RootsStorage<'a, Number, Hash> + where + H: Hasher, + Number: std::fmt::Display + std::hash::Hash + Clone + AtLeast32Bit + Encode + Decode + Send + Sync + 'static, + Hash: 'a + Send + Sync + Clone + AsRef<[u8]>, +{ + fn build_anchor( + &self, + _hash: H::Out, + ) -> Result, String> { + Err("build_anchor is only called when building block".into()) + } + + fn root( + &self, + _anchor: &ChangesTrieAnchorBlockId, + block: Number, + ) -> Result, String> { + // we can't ask for roots from parallel forks here => ignore anchor + let root = if block < self.roots.0 { + self.prev_roots.get(&Number::unique_saturated_from(block)).cloned() + } else { + let index: Option = block.checked_sub(&self.roots.0).and_then(|index| index.checked_into()); + match index { + Some(index) => self.roots.1.get(index as usize).cloned(), + None => None, + } + }; + + Ok(root.map(|root| { + let mut hasher_root: H::Out = Default::default(); + hasher_root.as_mut().copy_from_slice(root.as_ref()); + hasher_root + })) + } +} diff --git a/client/light/src/lib.rs b/client/light/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..deea642bd39d0720d23c4ede0cd5061fff08b3b5 --- /dev/null +++ b/client/light/src/lib.rs @@ -0,0 +1,57 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Light client components. + +use sp_runtime::traits::{Block as BlockT, HashFor}; +use sc_client_api::CloneableSpawn; +use std::sync::Arc; +use sp_core::traits::CodeExecutor; + +pub mod backend; +pub mod blockchain; +pub mod call_executor; +pub mod fetcher; + +pub use {backend::*, blockchain::*, call_executor::*, fetcher::*}; + +/// Create an instance of fetch data checker. +pub fn new_fetch_checker>( + blockchain: Arc>, + executor: E, + spawn_handle: Box, +) -> LightDataChecker, B, S> + where + E: CodeExecutor, +{ + LightDataChecker::new(blockchain, executor, spawn_handle) +} + +/// Create an instance of light client blockchain backend. +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>) -> Arc>> + where + B: BlockT, + S: BlockchainStorage, +{ + Arc::new(Backend::new(blockchain)) +} diff --git a/client/network-gossip/Cargo.toml b/client/network-gossip/Cargo.toml index ad2eb2ae0e391f31ce4551c29001f1a2d20ef922..99a1e7eb8bfe88776daae9f35cd8a5f2f0bf1f2a 100644 --- a/client/network-gossip/Cargo.toml +++ b/client/network-gossip/Cargo.toml @@ -1,28 +1,30 @@ [package] description = "Gossiping for the Substrate network protocol" name = "sc-network-gossip" -version = "0.8.0-alpha.5" -license = "GPL-3.0" +version = "0.8.0-rc4" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" authors = ["Parity Technologies "] edition = "2018" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" documentation = "https://docs.rs/sc-network-gossip" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] futures = "0.3.4" futures-timer = "3.0.1" -libp2p = { version = "0.16.2", default-features = false, features = ["libp2p-websocket"] } +libp2p = { version = "0.21.1", default-features = false } log = "0.4.8" lru = "0.4.3" -sc-network = { version = "0.8.0-alpha.5", path = "../network" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../primitives/runtime" } -sp-utils = { version = "2.0.0-alpha.5", path = "../../primitives/utils" } +sc-network = { version = "0.8.0-rc4", path = "../network" } +sp-runtime = { version = "2.0.0-rc4", path = "../../primitives/runtime" } wasm-timer = "0.2" [dev-dependencies] -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../test-utils/runtime/client" } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +async-std = "1.6.2" +quickcheck = "0.9.0" +rand = "0.7.2" +substrate-test-runtime-client = { version = "2.0.0-rc4", path = "../../test-utils/runtime/client" } diff --git a/client/network-gossip/src/bridge.rs b/client/network-gossip/src/bridge.rs index 6a00b3d5a181ab812aea45007c42096535946a0f..df2a5c8e7e94a5432fbd418a2a41a4864a721ec2 100644 --- a/client/network-gossip/src/bridge.rs +++ b/client/network-gossip/src/bridge.rs @@ -20,10 +20,17 @@ use crate::state_machine::{ConsensusGossip, TopicNotification, PERIODIC_MAINTENA use sc_network::{Event, ReputationChange}; use futures::prelude::*; +use futures::channel::mpsc::{channel, Sender, Receiver}; use libp2p::PeerId; +use log::trace; use sp_runtime::{traits::Block as BlockT, ConsensusEngineId}; -use std::{borrow::Cow, pin::Pin, sync::Arc, task::{Context, Poll}}; -use sp_utils::mpsc::TracingUnboundedReceiver; +use std::{ + borrow::Cow, + collections::{HashMap, VecDeque}, + pin::Pin, + sync::Arc, + task::{Context, Poll}, +}; /// Wraps around an implementation of the `Network` crate and provides gossiping capabilities on /// top of it. @@ -31,8 +38,28 @@ pub struct GossipEngine { state_machine: ConsensusGossip, network: Box + Send>, periodic_maintenance_interval: futures_timer::Delay, - network_event_stream: Pin + Send>>, engine_id: ConsensusEngineId, + + /// Incoming events from the network. + network_event_stream: Pin + Send>>, + /// Outgoing events to the consumer. + message_sinks: HashMap>>, + /// Buffered messages (see [`ForwardingState`]). + forwarding_state: ForwardingState, +} + +/// A gossip engine receives messages from the network via the `network_event_stream` and forwards +/// them to upper layers via the `message sinks`. In the scenario where messages have been received +/// from the network but a subscribed message sink is not yet ready to receive the messages, the +/// messages are buffered. To model this process a gossip engine can be in two states. +enum ForwardingState { + /// The gossip engine is currently not forwarding any messages and will poll the network for + /// more messages to forward. + Idle, + /// The gossip engine is in the progress of forwarding messages and thus will not poll the + /// network for more messages until it has send all current messages into the subscribed message + /// sinks. + Busy(VecDeque<(B::Hash, TopicNotification)>), } impl Unpin for GossipEngine {} @@ -40,26 +67,25 @@ impl Unpin for GossipEngine {} impl GossipEngine { /// Create a new instance. pub fn new + Send + Clone + 'static>( - mut network: N, + network: N, engine_id: ConsensusEngineId, protocol_name: impl Into>, validator: Arc>, ) -> Self where B: 'static { - let mut state_machine = ConsensusGossip::new(); - // We grab the event stream before registering the notifications protocol, otherwise we // might miss events. let network_event_stream = network.event_stream(); - network.register_notifications_protocol(engine_id, protocol_name.into()); - state_machine.register_validator(&mut network, engine_id, validator); GossipEngine { - state_machine, + state_machine: ConsensusGossip::new(validator, engine_id), network: Box::new(network), periodic_maintenance_interval: futures_timer::Delay::new(PERIODIC_MAINTENANCE_INTERVAL), - network_event_stream, engine_id, + + network_event_stream, + message_sinks: HashMap::new(), + forwarding_state: ForwardingState::Idle, } } @@ -77,7 +103,7 @@ impl GossipEngine { topic: B::Hash, message: Vec, ) { - self.state_machine.register_message(topic, self.engine_id, message); + self.state_machine.register_message(topic, message); } /// Broadcast all messages with given topic. @@ -87,9 +113,24 @@ impl GossipEngine { /// Get data of valid, incoming messages for a topic (but might have expired meanwhile). pub fn messages_for(&mut self, topic: B::Hash) - -> TracingUnboundedReceiver + -> Receiver { - self.state_machine.messages_for(self.engine_id, topic) + let past_messages = self.state_machine.messages_for(topic).collect::>(); + // The channel length is not critical for correctness. By the implementation of `channel` + // each sender is guaranteed a single buffer slot, making it a non-rendezvous channel and + // thus preventing direct dead-locks. A minimum channel length of 10 is an estimate based on + // the fact that despite `NotificationsReceived` having a `Vec` of messages, it only ever + // contains a single message. + let (mut tx, rx) = channel(usize::max(past_messages.len(), 10)); + + for notification in past_messages{ + tx.try_send(notification) + .expect("receiver known to be live, and buffer size known to suffice; qed"); + } + + self.message_sinks.entry(topic).or_default().push(tx); + + rx } /// Send all messages with given topic to a peer. @@ -99,7 +140,7 @@ impl GossipEngine { topic: B::Hash, force: bool ) { - self.state_machine.send_topic(&mut *self.network, who, topic, self.engine_id, force) + self.state_machine.send_topic(&mut *self.network, who, topic, force) } /// Multicast a message to all peers. @@ -109,14 +150,14 @@ impl GossipEngine { message: Vec, force: bool, ) { - self.state_machine.multicast(&mut *self.network, topic, self.engine_id, message, force) + self.state_machine.multicast(&mut *self.network, topic, message, force) } /// Send addressed message to the given peers. The message is not kept or multicast /// later on. pub fn send_message(&mut self, who: Vec, data: Vec) { for who in &who { - self.state_machine.send_message(&mut *self.network, who, self.engine_id, data.clone()); + self.state_machine.send_message(&mut *self.network, who, data.clone()); } } @@ -135,44 +176,114 @@ impl Future for GossipEngine { fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { let this = &mut *self; - loop { - match this.network_event_stream.poll_next_unpin(cx) { - Poll::Ready(Some(event)) => match event { - Event::NotificationStreamOpened { remote, engine_id: msg_engine_id, role } => { - if msg_engine_id != this.engine_id { - continue; + 'outer: loop { + match &mut this.forwarding_state { + ForwardingState::Idle => { + match this.network_event_stream.poll_next_unpin(cx) { + Poll::Ready(Some(event)) => match event { + Event::NotificationStreamOpened { remote, engine_id, role } => { + if engine_id != this.engine_id { + continue; + } + this.state_machine.new_peer(&mut *this.network, remote, role); + } + Event::NotificationStreamClosed { remote, engine_id } => { + if engine_id != this.engine_id { + continue; + } + this.state_machine.peer_disconnected(&mut *this.network, remote); + }, + Event::NotificationsReceived { remote, messages } => { + let messages = messages.into_iter().filter_map(|(engine, data)| { + if engine == this.engine_id { + Some(data.to_vec()) + } else { + None + } + }).collect(); + + let to_forward = this.state_machine.on_incoming( + &mut *this.network, + remote, + messages, + ); + + this.forwarding_state = ForwardingState::Busy(to_forward.into()); + }, + Event::Dht(_) => {} } - this.state_machine.new_peer(&mut *this.network, remote, role); + // The network event stream closed. Do the same for [`GossipValidator`]. + Poll::Ready(None) => return Poll::Ready(()), + Poll::Pending => break, } - Event::NotificationStreamClosed { remote, engine_id: msg_engine_id } => { - if msg_engine_id != this.engine_id { + } + ForwardingState::Busy(to_forward) => { + let (topic, notification) = match to_forward.pop_front() { + Some(n) => n, + None => { + this.forwarding_state = ForwardingState::Idle; continue; } - this.state_machine.peer_disconnected(&mut *this.network, remote); - }, - Event::NotificationsReceived { remote, messages } => { - let engine_id = this.engine_id.clone(); - this.state_machine.on_incoming( - &mut *this.network, - remote, - messages.into_iter() - .filter_map(|(engine, data)| if engine == engine_id { - Some((engine, data.to_vec())) - } else { None }) - .collect() - ); - }, - Event::Dht(_) => {} + }; + + let sinks = match this.message_sinks.get_mut(&topic) { + Some(sinks) => sinks, + None => { + continue; + }, + }; + + // Make sure all sinks for the given topic are ready. + for sink in sinks.iter_mut() { + match sink.poll_ready(cx) { + Poll::Ready(Ok(())) => {}, + // Receiver has been dropped. Ignore for now, filtered out in (1). + Poll::Ready(Err(_)) => {}, + Poll::Pending => { + // Push back onto queue for later. + to_forward.push_front((topic, notification)); + break 'outer; + } + } + } + + // Filter out all closed sinks. + sinks.retain(|sink| !sink.is_closed()); // (1) + + if sinks.is_empty() { + this.message_sinks.remove(&topic); + continue; + } + + trace!( + target: "gossip", + "Pushing consensus message to sinks for {}.", topic, + ); + + // Send the notification on each sink. + for sink in sinks { + match sink.start_send(notification.clone()) { + Ok(()) => {}, + Err(e) if e.is_full() => unreachable!( + "Previously ensured that all sinks are ready; qed.", + ), + // Receiver got dropped. Will be removed in next iteration (See (1)). + Err(_) => {}, + } + } } - // The network event stream closed. Do the same for [`GossipValidator`]. - Poll::Ready(None) => return Poll::Ready(()), - Poll::Pending => break, } } + while let Poll::Ready(()) = this.periodic_maintenance_interval.poll_unpin(cx) { this.periodic_maintenance_interval.reset(PERIODIC_MAINTENANCE_INTERVAL); this.state_machine.tick(&mut *this.network); + + this.message_sinks.retain(|_, sinks| { + sinks.retain(|sink| !sink.is_closed()); + !sinks.is_empty() + }); } Poll::Pending @@ -181,23 +292,37 @@ impl Future for GossipEngine { #[cfg(test)] mod tests { - use super::*; + use async_std::task::spawn; use crate::{ValidationResult, ValidatorContext}; + use futures::{channel::mpsc::{unbounded, UnboundedSender}, executor::{block_on, block_on_stream}, future::poll_fn}; + use quickcheck::{Arbitrary, Gen, QuickCheck}; + use rand::Rng; + use sc_network::ObservedRole; + use sp_runtime::{testing::H256, traits::{Block as BlockT}}; + use std::convert::TryInto; + use std::sync::{Arc, Mutex}; use substrate_test_runtime_client::runtime::Block; + use super::*; - struct TestNetwork {} + #[derive(Clone, Default)] + struct TestNetwork { + inner: Arc>, + } + + #[derive(Clone, Default)] + struct TestNetworkInner { + event_senders: Vec>, + } - impl Network for Arc { + impl Network for TestNetwork { fn event_stream(&self) -> Pin + Send>> { - let (_tx, rx) = futures::channel::mpsc::channel(0); + let (tx, rx) = unbounded(); + self.inner.lock().unwrap().event_senders.push(tx); - // Return rx and drop tx. Thus the given channel will yield `Poll::Ready(None)` on first - // poll. Box::pin(rx) } fn report_peer(&self, _: PeerId, _: ReputationChange) { - unimplemented!(); } fn disconnect_peer(&self, _: PeerId) { @@ -215,16 +340,15 @@ mod tests { } } - struct TestValidator {} - - impl Validator for TestValidator { + struct AllowAll; + impl Validator for AllowAll { fn validate( &self, - _: &mut dyn ValidatorContext, - _: &PeerId, - _: &[u8] - ) -> ValidationResult { - unimplemented!(); + _context: &mut dyn ValidatorContext, + _sender: &PeerId, + _data: &[u8], + ) -> ValidationResult { + ValidationResult::ProcessAndKeep(H256::default()) } } @@ -234,14 +358,18 @@ mod tests { /// See https://github.com/paritytech/substrate/issues/5000 for details. #[test] fn returns_when_network_event_stream_closes() { + let network = TestNetwork::default(); let mut gossip_engine = GossipEngine::::new( - Arc::new(TestNetwork{}), + network.clone(), [1, 2, 3, 4], "my_protocol".as_bytes(), - Arc::new(TestValidator{}), + Arc::new(AllowAll{}), ); - futures::executor::block_on(futures::future::poll_fn(move |ctx| { + // Drop network event stream sender side. + drop(network.inner.lock().unwrap().event_senders.pop()); + + block_on(poll_fn(move |ctx| { if let Poll::Pending = gossip_engine.poll_unpin(ctx) { panic!( "Expected gossip engine to finish on first poll, given that \ @@ -251,4 +379,270 @@ mod tests { Poll::Ready(()) })) } + + #[test] + fn keeps_multiple_subscribers_per_topic_updated_with_both_old_and_new_messages() { + let topic = H256::default(); + let engine_id = [1, 2, 3, 4]; + let remote_peer = PeerId::random(); + let network = TestNetwork::default(); + + let mut gossip_engine = GossipEngine::::new( + network.clone(), + engine_id.clone(), + "my_protocol".as_bytes(), + Arc::new(AllowAll{}), + ); + + let mut event_sender = network.inner.lock() + .unwrap() + .event_senders + .pop() + .unwrap(); + + // Register the remote peer. + event_sender.start_send( + Event::NotificationStreamOpened { + remote: remote_peer.clone(), + engine_id: engine_id.clone(), + role: ObservedRole::Authority, + } + ).expect("Event stream is unbounded; qed."); + + let messages = vec![vec![1], vec![2]]; + let events = messages.iter().cloned().map(|m| { + Event::NotificationsReceived { + remote: remote_peer.clone(), + messages: vec![(engine_id, m.into())] + } + }).collect::>(); + + // Send first event before subscribing. + event_sender.start_send(events[0].clone()).expect("Event stream is unbounded; qed."); + + let mut subscribers = vec![]; + for _ in 0..2 { + subscribers.push(gossip_engine.messages_for(topic)); + } + + // Send second event after subscribing. + event_sender.start_send(events[1].clone()).expect("Event stream is unbounded; qed."); + + spawn(gossip_engine); + + let mut subscribers = subscribers.into_iter() + .map(|s| block_on_stream(s)) + .collect::>(); + + // Expect each subscriber to receive both events. + for message in messages { + for subscriber in subscribers.iter_mut() { + assert_eq!( + subscriber.next(), + Some(TopicNotification { + message: message.clone(), + sender: Some(remote_peer.clone()), + }), + ); + } + } + } + + #[test] + fn forwarding_to_different_size_and_topic_channels() { + #[derive(Clone, Debug)] + struct ChannelLengthAndTopic{ + length: usize, + topic: H256, + } + + impl Arbitrary for ChannelLengthAndTopic { + fn arbitrary(g: &mut G) -> Self { + Self { + length: g.gen_range(0, 100), + // Make sure channel topics and message topics overlap by choosing a small + // range. + topic: H256::from_low_u64_ne(g.gen_range(0, 10)), + } + } + } + + #[derive(Clone, Debug)] + struct Message { + topic: H256, + } + + impl Arbitrary for Message{ + fn arbitrary(g: &mut G) -> Self { + Self { + // Make sure channel topics and message topics overlap by choosing a small + // range. + topic: H256::from_low_u64_ne(g.gen_range(0, 10)), + } + } + } + + /// Validator that always returns `ProcessAndKeep` interpreting the first 32 bytes of data + /// as the message topic. + struct TestValidator; + + impl Validator for TestValidator { + fn validate( + &self, + _context: &mut dyn ValidatorContext, + _sender: &PeerId, + data: &[u8], + ) -> ValidationResult { + ValidationResult::ProcessAndKeep(H256::from_slice(&data[0..32])) + } + } + + fn prop(channels: Vec, notifications: Vec>) { + let engine_id = [1, 2, 3, 4]; + let remote_peer = PeerId::random(); + let network = TestNetwork::default(); + + let num_channels_per_topic = channels.iter() + .fold(HashMap::new(), |mut acc, ChannelLengthAndTopic { topic, .. }| { + acc.entry(topic).and_modify(|e| *e += 1).or_insert(1); + acc + }); + + let expected_msgs_per_topic_all_chan = notifications.iter() + .fold(HashMap::new(), |mut acc, messages| { + for message in messages { + acc.entry(message.topic).and_modify(|e| *e += 1).or_insert(1); + } + acc + }) + .into_iter() + // Messages are cloned for each channel with the corresponding topic, thus multiply + // with the amount of channels per topic. If there is no channel for a given topic, + // don't expect any messages for the topic to be received. + .map(|(topic, num)| (topic, num_channels_per_topic.get(&topic).unwrap_or(&0) * num)) + .collect::>(); + + let mut gossip_engine = GossipEngine::::new( + network.clone(), + engine_id.clone(), + "my_protocol".as_bytes(), + Arc::new(TestValidator{}), + ); + + // Create channels. + let (txs, mut rxs) = channels.iter() + .map(|ChannelLengthAndTopic { length, topic }| { + (topic.clone(), channel(*length)) + }) + .fold((vec![], vec![]), |mut acc, (topic, (tx, rx))| { + acc.0.push((topic, tx)); acc.1.push((topic, rx)); + acc + }); + + // Insert sender sides into `gossip_engine`. + for (topic, tx) in txs { + match gossip_engine.message_sinks.get_mut(&topic) { + Some(entry) => entry.push(tx), + None => {gossip_engine.message_sinks.insert(topic, vec![tx]);}, + } + } + + + let mut event_sender = network.inner.lock() + .unwrap() + .event_senders + .pop() + .unwrap(); + + // Register the remote peer. + event_sender.start_send( + Event::NotificationStreamOpened { + remote: remote_peer.clone(), + engine_id: engine_id.clone(), + role: ObservedRole::Authority, + } + ).expect("Event stream is unbounded; qed."); + + // Send messages into the network event stream. + for (i_notification, messages) in notifications.iter().enumerate() { + let messages = messages.into_iter().enumerate() + .map(|(i_message, Message { topic })| { + // Embed the topic in the first 256 bytes of the message to be extracted by + // the [`TestValidator`] later on. + let mut message = topic.as_bytes().to_vec(); + + // Make sure the message is unique via `i_notification` and `i_message` to + // ensure [`ConsensusBridge`] does not deduplicate it. + message.push(i_notification.try_into().unwrap()); + message.push(i_message.try_into().unwrap()); + + (engine_id, message.into()) + }).collect(); + + event_sender.start_send(Event::NotificationsReceived { + remote: remote_peer.clone(), + messages, + }).expect("Event stream is unbounded; qed."); + } + + let mut received_msgs_per_topic_all_chan = HashMap::::new(); + + // Poll both gossip engine and each receiver and track the amount of received messages. + block_on(poll_fn(|cx| { + loop { + if let Poll::Ready(()) = gossip_engine.poll_unpin(cx) { + unreachable!( + "Event stream sender side is not dropped, thus gossip engine does not \ + terminate", + ); + } + + let mut progress = false; + + for (topic, rx) in rxs.iter_mut() { + match rx.poll_next_unpin(cx) { + Poll::Ready(Some(_)) => { + progress = true; + received_msgs_per_topic_all_chan.entry(*topic) + .and_modify(|e| *e += 1) + .or_insert(1); + }, + Poll::Ready(None) => unreachable!( + "Sender side of channel is never dropped", + ), + Poll::Pending => {}, + } + } + + if !progress { + break; + } + } + Poll::Ready(()) + })); + + // Compare amount of expected messages with amount of received messages. + for (expected_topic, expected_num) in expected_msgs_per_topic_all_chan.iter() { + assert_eq!( + received_msgs_per_topic_all_chan.get(&expected_topic).unwrap_or(&0), + expected_num, + ); + } + for (received_topic, received_num) in expected_msgs_per_topic_all_chan.iter() { + assert_eq!( + expected_msgs_per_topic_all_chan.get(&received_topic).unwrap_or(&0), + received_num, + ); + } + } + + // Past regressions. + prop(vec![], vec![vec![Message{ topic: H256::default()}]]); + prop( + vec![ChannelLengthAndTopic {length: 71, topic: H256::default()}], + vec![vec![Message{ topic: H256::default()}]], + ); + + QuickCheck::new().quickcheck(prop as fn(_, _)) + } } diff --git a/client/network-gossip/src/lib.rs b/client/network-gossip/src/lib.rs index 4e4d32366f29d4c907561fc844e107edc60b8627..42aeca86cb275a9651e9b04c1a092d58790122dd 100644 --- a/client/network-gossip/src/lib.rs +++ b/client/network-gossip/src/lib.rs @@ -99,7 +99,7 @@ pub trait Network { impl Network for Arc> { fn event_stream(&self) -> Pin + Send>> { - Box::pin(NetworkService::event_stream(self)) + Box::pin(NetworkService::event_stream(self, "network-gossip")) } fn report_peer(&self, peer_id: PeerId, reputation: ReputationChange) { diff --git a/client/network-gossip/src/state_machine.rs b/client/network-gossip/src/state_machine.rs index c846534488bf5a94760688089b8ecb1917cace62..da07bde3e7d1ad97f10f65a8c1204e2fc291c9c5 100644 --- a/client/network-gossip/src/state_machine.rs +++ b/client/network-gossip/src/state_machine.rs @@ -1,30 +1,31 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use crate::{Network, MessageIntent, Validator, ValidatorContext, ValidationResult}; -use std::collections::{HashMap, HashSet, hash_map::Entry}; +use std::collections::{HashMap, HashSet}; use std::sync::Arc; use std::iter; use std::time; -use log::trace; +use log::{error, trace}; use lru::LruCache; use libp2p::PeerId; use sp_runtime::traits::{Block as BlockT, Hash, HashFor}; -use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedSender, TracingUnboundedReceiver}; use sp_runtime::ConsensusEngineId; use sc_network::ObservedRole; use wasm_timer::Instant; @@ -42,20 +43,14 @@ mod rep { pub const GOSSIP_SUCCESS: Rep = Rep::new(1 << 4, "Successfull gossip"); /// Reputation change when a peer sends us a gossip message that we already knew about. pub const DUPLICATE_GOSSIP: Rep = Rep::new(-(1 << 2), "Duplicate gossip"); - /// Reputation change when a peer sends us a gossip message for an unknown engine, whatever that - /// means. - pub const UNKNOWN_GOSSIP: Rep = Rep::new(-(1 << 6), "Unknown gossip message engine id"); - /// Reputation change when a peer sends a message from a topic it isn't registered on. - pub const UNREGISTERED_TOPIC: Rep = Rep::new(-(1 << 10), "Unregistered gossip message topic"); } struct PeerConsensus { known_messages: HashSet, - role: ObservedRole, } /// Topic stream message with sender. -#[derive(Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct TopicNotification { /// Message data. pub message: Vec, @@ -66,7 +61,6 @@ pub struct TopicNotification { struct MessageEntry { message_hash: B::Hash, topic: B::Hash, - engine_id: ConsensusEngineId, message: Vec, sender: Option, } @@ -75,7 +69,6 @@ struct MessageEntry { struct NetworkContext<'g, 'p, B: BlockT> { gossip: &'g mut ConsensusGossip, network: &'p mut dyn Network, - engine_id: ConsensusEngineId, } impl<'g, 'p, B: BlockT> ValidatorContext for NetworkContext<'g, 'p, B> { @@ -89,7 +82,6 @@ impl<'g, 'p, B: BlockT> ValidatorContext for NetworkContext<'g, 'p, B> { self.gossip.multicast( self.network, topic, - self.engine_id.clone(), message, force, ); @@ -97,40 +89,30 @@ impl<'g, 'p, B: BlockT> ValidatorContext for NetworkContext<'g, 'p, B> { /// Send addressed message to a peer. fn send_message(&mut self, who: &PeerId, message: Vec) { - self.network.write_notification(who.clone(), self.engine_id, message); + self.network.write_notification(who.clone(), self.gossip.engine_id, message); } /// Send all messages with given topic to a peer. fn send_topic(&mut self, who: &PeerId, topic: B::Hash, force: bool) { - self.gossip.send_topic(self.network, who, topic, self.engine_id, force); + self.gossip.send_topic(self.network, who, topic, force); } } fn propagate<'a, B: BlockT, I>( network: &mut dyn Network, + engine_id: ConsensusEngineId, messages: I, intent: MessageIntent, peers: &mut HashMap>, - validators: &HashMap>>, + validator: &Arc>, ) // (msg_hash, topic, message) - where I: Clone + IntoIterator)>, + where I: Clone + IntoIterator)>, { - let mut check_fns = HashMap::new(); - let mut message_allowed = move |who: &PeerId, intent: MessageIntent, topic: &B::Hash, engine_id: ConsensusEngineId, message: &Vec| { - let check_fn = match check_fns.entry(engine_id) { - Entry::Occupied(entry) => entry.into_mut(), - Entry::Vacant(vacant) => match validators.get(&engine_id) { - None => return false, // treat all messages with no validator as not allowed - Some(validator) => vacant.insert(validator.message_allowed()), - } - }; - - (check_fn)(who, intent, topic, &message) - }; + let mut message_allowed = validator.message_allowed(); for (id, ref mut peer) in peers.iter_mut() { - for (message_hash, topic, engine_id, message) in messages.clone() { + for (message_hash, topic, message) in messages.clone() { let intent = match intent { MessageIntent::Broadcast { .. } => if peer.known_messages.contains(&message_hash) { @@ -149,7 +131,7 @@ fn propagate<'a, B: BlockT, I>( other => other, }; - if !message_allowed(id, intent, &topic, engine_id, &message) { + if !message_allowed(id, intent, &topic, &message) { continue; } @@ -164,45 +146,26 @@ fn propagate<'a, B: BlockT, I>( /// Consensus network protocol handler. Manages statements and candidate requests. pub struct ConsensusGossip { peers: HashMap>, - live_message_sinks: HashMap<(ConsensusEngineId, B::Hash), Vec>>, messages: Vec>, known_messages: LruCache, - validators: HashMap>>, + engine_id: ConsensusEngineId, + validator: Arc>, next_broadcast: Instant, } impl ConsensusGossip { - /// Create a new instance. - pub fn new() -> Self { + /// Create a new instance using the given validator. + pub fn new(validator: Arc>, engine_id: ConsensusEngineId) -> Self { ConsensusGossip { peers: HashMap::new(), - live_message_sinks: HashMap::new(), messages: Default::default(), known_messages: LruCache::new(KNOWN_MESSAGES_CACHE_SIZE), - validators: Default::default(), + engine_id, + validator, next_broadcast: Instant::now() + REBROADCAST_INTERVAL, } } - /// Register message validator for a message type. - pub fn register_validator( - &mut self, - network: &mut dyn Network, - engine_id: ConsensusEngineId, - validator: Arc> - ) { - self.register_validator_internal(engine_id, validator.clone()); - let peers: Vec<_> = self.peers.iter().map(|(id, peer)| (id.clone(), peer.role.clone())).collect(); - for (id, role) in peers { - let mut context = NetworkContext { gossip: self, network, engine_id: engine_id.clone() }; - validator.new_peer(&mut context, &id, role); - } - } - - fn register_validator_internal(&mut self, engine_id: ConsensusEngineId, validator: Arc>) { - self.validators.insert(engine_id, validator.clone()); - } - /// Handle new connected peer. pub fn new_peer(&mut self, network: &mut dyn Network, who: PeerId, role: ObservedRole) { // light nodes are not valid targets for consensus gossip messages @@ -213,19 +176,17 @@ impl ConsensusGossip { trace!(target:"gossip", "Registering {:?} {}", role, who); self.peers.insert(who.clone(), PeerConsensus { known_messages: HashSet::new(), - role: role.clone(), }); - for (engine_id, v) in self.validators.clone() { - let mut context = NetworkContext { gossip: self, network, engine_id: engine_id.clone() }; - v.new_peer(&mut context, &who, role.clone()); - } + + let validator = self.validator.clone(); + let mut context = NetworkContext { gossip: self, network }; + validator.new_peer(&mut context, &who, role.clone()); } fn register_message_hashed( &mut self, message_hash: B::Hash, topic: B::Hash, - engine_id: ConsensusEngineId, message: Vec, sender: Option, ) { @@ -233,7 +194,6 @@ impl ConsensusGossip { self.messages.push(MessageEntry { message_hash, topic, - engine_id, message, sender, }); @@ -248,19 +208,17 @@ impl ConsensusGossip { pub fn register_message( &mut self, topic: B::Hash, - engine_id: ConsensusEngineId, message: Vec, ) { let message_hash = HashFor::::hash(&message[..]); - self.register_message_hashed(message_hash, topic, engine_id, message, None); + self.register_message_hashed(message_hash, topic, message, None); } /// Call when a peer has been disconnected to stop tracking gossip status. pub fn peer_disconnected(&mut self, network: &mut dyn Network, who: PeerId) { - for (engine_id, v) in self.validators.clone() { - let mut context = NetworkContext { gossip: self, network, engine_id: engine_id.clone() }; - v.peer_disconnected(&mut context, &who); - } + let validator = self.validator.clone(); + let mut context = NetworkContext { gossip: self, network }; + validator.peer_disconnected(&mut context, &who); self.peers.remove(&who); } @@ -276,8 +234,8 @@ impl ConsensusGossip { /// Rebroadcast all messages to all peers. fn rebroadcast(&mut self, network: &mut dyn Network) { let messages = self.messages.iter() - .map(|entry| (&entry.message_hash, &entry.topic, entry.engine_id, &entry.message)); - propagate(network, messages, MessageIntent::PeriodicRebroadcast, &mut self.peers, &self.validators); + .map(|entry| (&entry.message_hash, &entry.topic, &entry.message)); + propagate(network, self.engine_id, messages, MessageIntent::PeriodicRebroadcast, &mut self.peers, &self.validator); } /// Broadcast all messages with given topic. @@ -285,40 +243,21 @@ impl ConsensusGossip { let messages = self.messages.iter() .filter_map(|entry| if entry.topic == topic { - Some((&entry.message_hash, &entry.topic, entry.engine_id, &entry.message)) + Some((&entry.message_hash, &entry.topic, &entry.message)) } else { None } ); let intent = if force { MessageIntent::ForcedBroadcast } else { MessageIntent::Broadcast }; - propagate(network, messages, intent, &mut self.peers, &self.validators); + propagate(network, self.engine_id, messages, intent, &mut self.peers, &self.validator); } /// Prune old or no longer relevant consensus messages. Provide a predicate /// for pruning, which returns `false` when the items with a given topic should be pruned. pub fn collect_garbage(&mut self) { - self.live_message_sinks.retain(|_, sinks| { - sinks.retain(|sink| !sink.is_closed()); - !sinks.is_empty() - }); - let known_messages = &mut self.known_messages; let before = self.messages.len(); - let validators = &self.validators; - - let mut check_fns = HashMap::new(); - let mut message_expired = move |entry: &MessageEntry| { - let engine_id = entry.engine_id; - let check_fn = match check_fns.entry(engine_id) { - Entry::Occupied(entry) => entry.into_mut(), - Entry::Vacant(vacant) => match validators.get(&engine_id) { - None => return true, // treat all messages with no validator as expired - Some(validator) => vacant.insert(validator.message_expired()), - } - }; - - (check_fn)(entry.topic, &entry.message) - }; - self.messages.retain(|entry| !message_expired(entry)); + let mut message_expired = self.validator.message_expired(); + self.messages.retain(|entry| !message_expired(entry.topic, &entry.message)); trace!(target: "gossip", "Cleaned up {} stale messages, {} left ({} known)", before - self.messages.len(), @@ -331,40 +270,29 @@ impl ConsensusGossip { } } - /// Get data of valid, incoming messages for a topic (but might have expired meanwhile) - pub fn messages_for(&mut self, engine_id: ConsensusEngineId, topic: B::Hash) - -> TracingUnboundedReceiver - { - let (tx, rx) = tracing_unbounded("mpsc_gossip_messages_for"); - for entry in self.messages.iter_mut() - .filter(|e| e.topic == topic && e.engine_id == engine_id) - { - tx.unbounded_send(TopicNotification { - message: entry.message.clone(), - sender: entry.sender.clone(), - }) - .expect("receiver known to be live; qed"); - } - - self.live_message_sinks.entry((engine_id, topic)).or_default().push(tx); - - rx + /// Get valid messages received in the past for a topic (might have expired meanwhile). + pub fn messages_for(&mut self, topic: B::Hash) -> impl Iterator + '_ { + self.messages.iter().filter(move |e| e.topic == topic).map(|entry| TopicNotification { + message: entry.message.clone(), + sender: entry.sender.clone(), + }) } - /// Handle an incoming message for topic by who via protocol. Discard message if topic already - /// known, the message is old, its source peers isn't a registered peer or the connection to - /// them is broken. + /// Register incoming messages and return the ones that are new and valid (according to a gossip + /// validator) and should thus be forwarded to the upper layers. pub fn on_incoming( &mut self, network: &mut dyn Network, who: PeerId, - messages: Vec<(ConsensusEngineId, Vec)>, - ) { + messages: Vec>, + ) -> Vec<(B::Hash, TopicNotification)> { + let mut to_forward = vec![]; + if !messages.is_empty() { trace!(target: "gossip", "Received {} messages from peer {}", messages.len(), who); } - for (engine_id, message) in messages { + for message in messages { let message_hash = HashFor::::hash(&message[..]); if self.known_messages.contains(&message_hash) { @@ -374,55 +302,47 @@ impl ConsensusGossip { } // validate the message - let validation = self.validators.get(&engine_id) - .cloned() - .map(|v| { - let mut context = NetworkContext { gossip: self, network, engine_id }; - v.validate(&mut context, &who, &message) - }); + let validation = { + let validator = self.validator.clone(); + let mut context = NetworkContext { gossip: self, network }; + validator.validate(&mut context, &who, &message) + }; + + let (topic, keep) = match validation { + ValidationResult::ProcessAndKeep(topic) => (topic, true), + ValidationResult::ProcessAndDiscard(topic) => (topic, false), + ValidationResult::Discard => { + trace!(target:"gossip", "Discard message from peer {}", who); + continue; + }, + }; - let validation_result = match validation { - Some(ValidationResult::ProcessAndKeep(topic)) => Some((topic, true)), - Some(ValidationResult::ProcessAndDiscard(topic)) => Some((topic, false)), - Some(ValidationResult::Discard) => None, + let peer = match self.peers.get_mut(&who) { + Some(peer) => peer, None => { - trace!(target:"gossip", "Unknown message engine id {:?} from {}", engine_id, who); - network.report_peer(who.clone(), rep::UNKNOWN_GOSSIP); - network.disconnect_peer(who.clone()); + error!(target:"gossip", "Got message from unregistered peer {}", who); continue; } }; - if let Some((topic, keep)) = validation_result { - network.report_peer(who.clone(), rep::GOSSIP_SUCCESS); - if let Some(ref mut peer) = self.peers.get_mut(&who) { - peer.known_messages.insert(message_hash); - if let Entry::Occupied(mut entry) = self.live_message_sinks.entry((engine_id, topic)) { - trace!(target: "gossip", "Pushing consensus message to sinks for {}.", topic); - entry.get_mut().retain(|sink| { - if let Err(e) = sink.unbounded_send(TopicNotification { - message: message.clone(), - sender: Some(who.clone()) - }) { - trace!(target: "gossip", "Error broadcasting message notification: {:?}", e); - } - !sink.is_closed() - }); - if entry.get().is_empty() { - entry.remove_entry(); - } - } - if keep { - self.register_message_hashed(message_hash, topic, engine_id, message, Some(who.clone())); - } - } else { - trace!(target:"gossip", "Ignored statement from unregistered peer {}", who); - network.report_peer(who.clone(), rep::UNREGISTERED_TOPIC); - } - } else { - trace!(target:"gossip", "Discard message from peer {}", who); + network.report_peer(who.clone(), rep::GOSSIP_SUCCESS); + peer.known_messages.insert(message_hash); + to_forward.push((topic, TopicNotification { + message: message.clone(), + sender: Some(who.clone()) + })); + + if keep { + self.register_message_hashed( + message_hash, + topic, + message, + Some(who.clone()), + ); } } + + to_forward } /// Send all messages with given topic to a peer. @@ -431,17 +351,12 @@ impl ConsensusGossip { network: &mut dyn Network, who: &PeerId, topic: B::Hash, - engine_id: ConsensusEngineId, force: bool ) { - let validator = self.validators.get(&engine_id); - let mut message_allowed = match validator { - None => return, // treat all messages with no validator as not allowed - Some(validator) => validator.message_allowed(), - }; + let mut message_allowed = self.validator.message_allowed(); if let Some(ref mut peer) = self.peers.get_mut(who) { - for entry in self.messages.iter().filter(|m| m.topic == topic && m.engine_id == engine_id) { + for entry in self.messages.iter().filter(|m| m.topic == topic) { let intent = if force { MessageIntent::ForcedBroadcast } else { @@ -459,7 +374,7 @@ impl ConsensusGossip { peer.known_messages.insert(entry.message_hash.clone()); trace!(target: "gossip", "Sending topic message to {}: {:?}", who, entry.message); - network.write_notification(who.clone(), engine_id, entry.message.clone()); + network.write_notification(who.clone(), self.engine_id, entry.message.clone()); } } } @@ -469,14 +384,13 @@ impl ConsensusGossip { &mut self, network: &mut dyn Network, topic: B::Hash, - engine_id: ConsensusEngineId, message: Vec, force: bool, ) { let message_hash = HashFor::::hash(&message); - self.register_message_hashed(message_hash, topic, engine_id, message.clone(), None); + self.register_message_hashed(message_hash, topic, message.clone(), None); let intent = if force { MessageIntent::ForcedBroadcast } else { MessageIntent::Broadcast }; - propagate(network, iter::once((&message_hash, &topic, engine_id, &message)), intent, &mut self.peers, &self.validators); + propagate(network, self.engine_id, iter::once((&message_hash, &topic, &message)), intent, &mut self.peers, &self.validator); } /// Send addressed message to a peer. The message is not kept or multicast @@ -485,7 +399,6 @@ impl ConsensusGossip { &mut self, network: &mut dyn Network, who: &PeerId, - engine_id: ConsensusEngineId, message: Vec, ) { let peer = match self.peers.get_mut(who) { @@ -498,16 +411,16 @@ impl ConsensusGossip { trace!(target: "gossip", "Sending direct to {}: {:?}", who, message); peer.known_messages.insert(message_hash); - network.write_notification(who.clone(), engine_id, message); + network.write_notification(who.clone(), self.engine_id, message); } } #[cfg(test)] mod tests { - use std::sync::Arc; + use futures::prelude::*; + use sc_network::{Event, ReputationChange}; use sp_runtime::testing::{H256, Block as RawBlock, ExtrinsicWrapper}; - use futures::executor::block_on_stream; - + use std::{borrow::Cow, pin::Pin, sync::{Arc, Mutex}}; use super::*; type Block = RawBlock>; @@ -518,7 +431,6 @@ mod tests { $consensus.messages.push(MessageEntry { message_hash: $hash, topic: $topic, - engine_id: [0, 0, 0, 0], message: $m, sender: None, }); @@ -538,6 +450,52 @@ mod tests { } } + struct DiscardAll; + impl Validator for DiscardAll{ + fn validate( + &self, + _context: &mut dyn ValidatorContext, + _sender: &PeerId, + _data: &[u8], + ) -> ValidationResult { + ValidationResult::Discard + } + } + + #[derive(Clone, Default)] + struct NoOpNetwork { + inner: Arc>, + } + + #[derive(Clone, Default)] + struct NoOpNetworkInner { + peer_reports: Vec<(PeerId, ReputationChange)>, + } + + impl Network for NoOpNetwork { + fn event_stream(&self) -> Pin + Send>> { + unimplemented!(); + } + + fn report_peer(&self, peer_id: PeerId, reputation_change: ReputationChange) { + self.inner.lock().unwrap().peer_reports.push((peer_id, reputation_change)); + } + + fn disconnect_peer(&self, _: PeerId) { + unimplemented!(); + } + + fn write_notification(&self, _: PeerId, _: ConsensusEngineId, _: Vec) { + unimplemented!(); + } + + fn register_notifications_protocol(&self, _: ConsensusEngineId, _: Cow<'static, [u8]>) {} + + fn announce(&self, _: B::Hash, _: Vec) { + unimplemented!(); + } + } + #[test] fn collects_garbage() { struct AllowOne; @@ -562,7 +520,7 @@ mod tests { let prev_hash = H256::random(); let best_hash = H256::random(); - let mut consensus = ConsensusGossip::::new(); + let mut consensus = ConsensusGossip::::new(Arc::new(AllowAll), [0, 0, 0, 0]); let m1_hash = H256::random(); let m2_hash = H256::random(); let m1 = vec![1, 2, 3]; @@ -573,13 +531,11 @@ mod tests { consensus.known_messages.put(m1_hash, ()); consensus.known_messages.put(m2_hash, ()); - let test_engine_id = Default::default(); - consensus.register_validator_internal(test_engine_id, Arc::new(AllowAll)); consensus.collect_garbage(); assert_eq!(consensus.messages.len(), 2); assert_eq!(consensus.known_messages.len(), 2); - consensus.register_validator_internal(test_engine_id, Arc::new(AllowOne)); + consensus.validator = Arc::new(AllowOne); // m2 is expired consensus.collect_garbage(); @@ -590,116 +546,84 @@ mod tests { } #[test] - fn message_stream_include_those_sent_before_asking_for_stream() { - let mut consensus = ConsensusGossip::::new(); - consensus.register_validator_internal([0, 0, 0, 0], Arc::new(AllowAll)); + fn message_stream_include_those_sent_before_asking() { + let mut consensus = ConsensusGossip::::new(Arc::new(AllowAll), [0, 0, 0, 0]); - let engine_id = [0, 0, 0, 0]; + // Register message. let message = vec![4, 5, 6]; let topic = HashFor::::hash(&[1,2,3]); + consensus.register_message(topic, message.clone()); - consensus.register_message(topic, engine_id, message.clone()); - let mut stream = block_on_stream(consensus.messages_for([0, 0, 0, 0], topic)); - - assert_eq!(stream.next(), Some(TopicNotification { message: message, sender: None })); + assert_eq!( + consensus.messages_for(topic).next(), + Some(TopicNotification { message: message, sender: None }), + ); } #[test] fn can_keep_multiple_messages_per_topic() { - let mut consensus = ConsensusGossip::::new(); + let mut consensus = ConsensusGossip::::new(Arc::new(AllowAll), [0, 0, 0, 0]); let topic = [1; 32].into(); let msg_a = vec![1, 2, 3]; let msg_b = vec![4, 5, 6]; - consensus.register_message(topic, [0, 0, 0, 0], msg_a); - consensus.register_message(topic, [0, 0, 0, 0], msg_b); + consensus.register_message(topic, msg_a); + consensus.register_message(topic, msg_b); assert_eq!(consensus.messages.len(), 2); } #[test] - fn can_keep_multiple_subscribers_per_topic() { - let mut consensus = ConsensusGossip::::new(); - consensus.register_validator_internal([0, 0, 0, 0], Arc::new(AllowAll)); - - let message = vec![4, 5, 6]; - let topic = HashFor::::hash(&[1, 2, 3]); + fn peer_is_removed_on_disconnect() { + let mut consensus = ConsensusGossip::::new(Arc::new(AllowAll), [0, 0, 0, 0]); - consensus.register_message(topic, [0, 0, 0, 0], message.clone()); + let mut network = NoOpNetwork::default(); - 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)); + let peer_id = PeerId::random(); + consensus.new_peer(&mut network, peer_id.clone(), ObservedRole::Full); + assert!(consensus.peers.contains_key(&peer_id)); - assert_eq!(stream1.next(), Some(TopicNotification { message: message.clone(), sender: None })); - assert_eq!(stream2.next(), Some(TopicNotification { message, sender: None })); + consensus.peer_disconnected(&mut network, peer_id.clone()); + assert!(!consensus.peers.contains_key(&peer_id)); } #[test] - fn topics_are_localized_to_engine_id() { - let mut consensus = ConsensusGossip::::new(); - consensus.register_validator_internal([0, 0, 0, 0], Arc::new(AllowAll)); - - let topic = [1; 32].into(); - let msg_a = vec![1, 2, 3]; - let msg_b = vec![4, 5, 6]; - - consensus.register_message(topic, [0, 0, 0, 0], msg_a); - consensus.register_message(topic, [0, 0, 0, 1], msg_b); - - 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 })); + fn on_incoming_ignores_discarded_messages() { + let to_forward = ConsensusGossip::::new( + Arc::new(DiscardAll), + [0, 0, 0, 0], + ).on_incoming( + &mut NoOpNetwork::default(), + PeerId::random(), + vec![vec![1, 2, 3]], + ); - let _ = consensus.live_message_sinks.remove(&([0, 0, 0, 0], topic)); - assert_eq!(stream.next(), None); + assert!( + to_forward.is_empty(), + "Expected `on_incoming` to ignore discarded message but got {:?}", to_forward, + ); } #[test] - fn peer_is_removed_on_disconnect() { - struct TestNetwork; - impl Network for TestNetwork { - fn event_stream( - &self, - ) -> std::pin::Pin + Send>> { - unimplemented!("Not required in tests") - } - - fn report_peer(&self, _: PeerId, _: crate::ReputationChange) { - unimplemented!("Not required in tests") - } - - fn disconnect_peer(&self, _: PeerId) { - unimplemented!("Not required in tests") - } - - fn write_notification(&self, _: PeerId, _: crate::ConsensusEngineId, _: Vec) { - unimplemented!("Not required in tests") - } - - fn register_notifications_protocol( - &self, - _: ConsensusEngineId, - _: std::borrow::Cow<'static, [u8]>, - ) { - unimplemented!("Not required in tests") - } - - fn announce(&self, _: H256, _: Vec) { - unimplemented!("Not required in tests") - } - } - - let mut consensus = ConsensusGossip::::new(); - consensus.register_validator_internal([0, 0, 0, 0], Arc::new(AllowAll)); - - let mut network = TestNetwork; - - let peer_id = PeerId::random(); - consensus.new_peer(&mut network, peer_id.clone(), ObservedRole::Full); - assert!(consensus.peers.contains_key(&peer_id)); + fn on_incoming_ignores_unregistered_peer() { + let mut network = NoOpNetwork::default(); + let remote = PeerId::random(); + + let to_forward = ConsensusGossip::::new( + Arc::new(AllowAll), + [0, 0, 0, 0], + ).on_incoming( + &mut network, + // Unregistered peer. + remote.clone(), + vec![vec![1, 2, 3]], + ); - consensus.peer_disconnected(&mut network, peer_id.clone()); - assert!(!consensus.peers.contains_key(&peer_id)); + assert!( + to_forward.is_empty(), + "Expected `on_incoming` to ignore message from unregistered peer but got {:?}", + to_forward, + ); } } diff --git a/client/network-gossip/src/validator.rs b/client/network-gossip/src/validator.rs index 6b330d7b618c0e702e52cc330ed2bd77b3ffdbdd..fd29aaddafe6dcd89f2e722bdcfa07854fc04225 100644 --- a/client/network-gossip/src/validator.rs +++ b/client/network-gossip/src/validator.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use sc_network::{ObservedRole, PeerId}; use sp_runtime::traits::Block as BlockT; diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 8d67a15c354bdde4adfdee04a3b60293b55e86f7..85f76437259dc0ad5c1c8506e39a4b1e9634109f 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -1,8 +1,8 @@ [package] description = "Substrate network protocol" name = "sc-network" -version = "0.8.0-alpha.5" -license = "GPL-3.0" +version = "0.8.0-rc4" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" authors = ["Parity Technologies "] edition = "2018" homepage = "https://substrate.dev" @@ -10,70 +10,75 @@ repository = "https://github.com/paritytech/substrate/" documentation = "https://docs.rs/sc-network" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + + [build-dependencies] prost-build = "0.6.1" [dependencies] bitflags = "1.2.0" +bs58 = "0.3.1" bytes = "0.5.0" -codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.3.1", features = ["derive"] } derive_more = "0.99.2" either = "1.5.3" erased-serde = "0.3.9" fnv = "1.0.6" -fork-tree = { version = "2.0.0-alpha.5", path = "../../utils/fork-tree" } +fork-tree = { version = "2.0.0-rc4", path = "../../utils/fork-tree" } futures = "0.3.4" -futures_codec = "0.3.3" futures-timer = "3.0.1" -wasm-timer = "0.2" -libp2p = { version = "0.16.2", default-features = false, features = ["libp2p-websocket"] } +futures_codec = "0.4.0" +hex = "0.4.0" +ip_network = "0.3.4" linked-hash-map = "0.5.2" linked_hash_set = "0.1.3" log = "0.4.8" lru = "0.4.0" nohash-hasher = "0.2.0" parking_lot = "0.10.0" +pin-project = "0.4.6" +prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.8.0-rc4", path = "../../utils/prometheus" } prost = "0.6.1" rand = "0.7.2" -hex = "0.4.0" -sc-block-builder = { version = "0.8.0-alpha.5", path = "../block-builder" } -sc-client = { version = "0.8.0-alpha.5", path = "../" } -sc-client-api = { version = "2.0.0-alpha.5", path = "../api" } -sc-peerset = { version = "2.0.0-alpha.5", path = "../peerset" } -pin-project = "0.4.6" +sc-block-builder = { version = "0.8.0-rc4", path = "../block-builder" } +sc-client-api = { version = "2.0.0-rc4", path = "../api" } +sc-peerset = { version = "2.0.0-rc4", path = "../peerset" } serde = { version = "1.0.101", features = ["derive"] } serde_json = "1.0.41" slog = { version = "2.5.2", features = ["nested-values"] } slog_derive = "0.2.0" smallvec = "0.6.10" -sp-arithmetic = { version = "2.0.0-alpha.5", path = "../../primitives/arithmetic" } -sp-utils = { version = "2.0.0-alpha.5", path = "../../primitives/utils" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../primitives/blockchain" } -sp-consensus = { version = "0.8.0-alpha.5", path = "../../primitives/consensus/common" } -sp-consensus-babe = { version = "0.8.0-alpha.5", path = "../../primitives/consensus/babe" } -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../primitives/runtime" } -prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.8.0-alpha.5", path = "../../utils/prometheus" } +sp-arithmetic = { version = "2.0.0-rc4", path = "../../primitives/arithmetic" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../primitives/blockchain" } +sp-consensus = { version = "0.8.0-rc4", path = "../../primitives/consensus/common" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +sp-runtime = { version = "2.0.0-rc4", path = "../../primitives/runtime" } +sp-utils = { version = "2.0.0-rc4", path = "../../primitives/utils" } thiserror = "1" -unsigned-varint = { version = "0.3.1", features = ["futures", "futures-codec"] } +unsigned-varint = { version = "0.4.0", features = ["futures", "futures-codec"] } void = "1.0.2" +wasm-timer = "0.2" zeroize = "1.0.0" +[dependencies.libp2p] +version = "0.21.1" +default-features = false +features = ["identify", "kad", "mdns", "mplex", "noise", "ping", "tcp-async-std", "websocket", "yamux"] + [dev-dependencies] -async-std = "1.5" +async-std = "1.6.2" assert_matches = "1.3" env_logger = "0.7.0" +libp2p = { version = "0.21.1", default-features = false, features = ["secio"] } quickcheck = "0.9.0" rand = "0.7.2" -sp-keyring = { version = "2.0.0-alpha.5", path = "../../primitives/keyring" } -sp-test-primitives = { version = "2.0.0-dev", path = "../../primitives/test-primitives" } -substrate-test-runtime = { version = "2.0.0-dev", path = "../../test-utils/runtime" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../test-utils/runtime/client" } +sp-keyring = { version = "2.0.0-rc4", path = "../../primitives/keyring" } +sp-test-primitives = { version = "2.0.0-rc4", path = "../../primitives/test-primitives" } +substrate-test-runtime = { version = "2.0.0-rc4", path = "../../test-utils/runtime" } +substrate-test-runtime-client = { version = "2.0.0-rc4", path = "../../test-utils/runtime/client" } tempfile = "3.1.0" [features] default = [] - - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/client/network/build.rs b/client/network/build.rs index 0fd1f128660e9aaec36c4ac14e405f77e9588096..8ed460f163eb4f9c0fbab6949bb0028b5e9dd808 100644 --- a/client/network/build.rs +++ b/client/network/build.rs @@ -1,8 +1,9 @@ const PROTOS: &[&str] = &[ - "src/protocol/schema/api.v1.proto", - "src/protocol/schema/light.v1.proto" + "src/schema/api.v1.proto", + "src/schema/finality.v1.proto", + "src/schema/light.v1.proto" ]; fn main() { - prost_build::compile_protos(PROTOS, &["src/protocol"]).unwrap(); + prost_build::compile_protos(PROTOS, &["src/schema"]).unwrap(); } diff --git a/client/network/src/behaviour.rs b/client/network/src/behaviour.rs index 203435134c6cd090bb84b9e6e8d08f384f0b79af..5967613b98e4607b57f8706430ac878040d6d806 100644 --- a/client/network/src/behaviour.rs +++ b/client/network/src/behaviour.rs @@ -15,11 +15,13 @@ // along with Substrate. If not, see . use crate::{ - config::Role, - debug_info, discovery::DiscoveryBehaviour, discovery::DiscoveryOut, + config::{ProtocolId, Role}, block_requests, light_client_handler, finality_requests, + peer_info, discovery::{DiscoveryBehaviour, DiscoveryConfig, DiscoveryOut}, + protocol::{message::{self, Roles}, CustomMessageOutcome, Protocol}, Event, ObservedRole, DhtEvent, ExHashT, }; -use crate::protocol::{self, light_client_handler, message::Roles, CustomMessageOutcome, Protocol}; + +use codec::Encode as _; use libp2p::NetworkBehaviour; use libp2p::core::{Multiaddr, PeerId, PublicKey}; use libp2p::kad::record; @@ -27,8 +29,13 @@ use libp2p::swarm::{NetworkBehaviourAction, NetworkBehaviourEventProcess, PollPa use log::debug; use sp_consensus::{BlockOrigin, import_queue::{IncomingBlock, Origin}}; use sp_runtime::{traits::{Block as BlockT, NumberFor}, ConsensusEngineId, Justification}; -use std::{borrow::Cow, iter, task::Context, task::Poll}; -use void; +use std::{ + borrow::Cow, + collections::{HashSet, VecDeque}, + iter, + task::{Context, Poll}, + time::Duration, +}; /// General behaviour of the network. Combines all protocols together. #[derive(NetworkBehaviour)] @@ -38,17 +45,19 @@ pub struct Behaviour { substrate: Protocol, /// Periodically pings and identifies the nodes we are connected to, and store information in a /// cache. - debug_info: debug_info::DebugInfoBehaviour, + peer_info: peer_info::PeerInfoBehaviour, /// Discovers nodes of the network. discovery: DiscoveryBehaviour, /// Block request handling. - block_requests: protocol::BlockRequests, + block_requests: block_requests::BlockRequests, + /// Finality proof request handling. + finality_proof_requests: finality_requests::FinalityProofRequests, /// Light client request handling. - light_client_handler: protocol::LightClientHandler, + light_client_handler: light_client_handler::LightClientHandler, /// Queue of events to produce for the outside. #[behaviour(ignore)] - events: Vec>, + events: VecDeque>, /// Role of our local node, as originally passed from the configuration. #[behaviour(ignore)] @@ -60,44 +69,68 @@ pub enum BehaviourOut { BlockImport(BlockOrigin, Vec>), JustificationImport(Origin, B::Hash, NumberFor, Justification), FinalityProofImport(Origin, B::Hash, NumberFor, Vec), - /// Started a random Kademlia discovery query. - RandomKademliaStarted, + + /// Started a random iterative Kademlia discovery query. + RandomKademliaStarted(ProtocolId), + + /// We have received a request from a peer and answered it. + AnsweredRequest { + /// Peer which sent us a request. + peer: PeerId, + /// Protocol name of the request. + protocol: Vec, + /// Time it took to build the response. + build_time: Duration, + }, + /// Started a new request with the given node. + RequestStarted { + peer: PeerId, + /// Protocol name of the request. + protocol: Vec, + }, + /// Finished, successfully or not, a previously-started request. + RequestFinished { + /// Who we were requesting. + peer: PeerId, + /// Protocol name of the request. + protocol: Vec, + /// How long before the response came or the request got cancelled. + request_duration: Duration, + }, + + /// Any event represented by the [`Event`] enum. + /// + /// > **Note**: The [`Event`] enum contains the events that are available through the public + /// > API of the library. Event(Event), } impl Behaviour { /// Builds a new `Behaviour`. - pub async fn new( + pub fn new( substrate: Protocol, role: Role, user_agent: String, local_public_key: PublicKey, - known_addresses: Vec<(PeerId, Multiaddr)>, - enable_mdns: bool, - allow_private_ipv4: bool, - discovery_only_if_under_num: u64, - block_requests: protocol::BlockRequests, - light_client_handler: protocol::LightClientHandler, + block_requests: block_requests::BlockRequests, + finality_proof_requests: finality_requests::FinalityProofRequests, + light_client_handler: light_client_handler::LightClientHandler, + disco_config: DiscoveryConfig, ) -> Self { Behaviour { substrate, - debug_info: debug_info::DebugInfoBehaviour::new(user_agent, local_public_key.clone()), - discovery: DiscoveryBehaviour::new( - local_public_key, - known_addresses, - enable_mdns, - allow_private_ipv4, - discovery_only_if_under_num, - ).await, + peer_info: peer_info::PeerInfoBehaviour::new(user_agent, local_public_key), + discovery: disco_config.finish(), block_requests, + finality_proof_requests, light_client_handler, - events: Vec::new(), + events: VecDeque::new(), role, } } /// Returns the list of nodes that we know exist in the network. - pub fn known_peers(&mut self) -> impl Iterator { + pub fn known_peers(&mut self) -> HashSet { self.discovery.known_peers() } @@ -107,17 +140,27 @@ impl Behaviour { } /// Returns the number of nodes that are in the Kademlia k-buckets. - pub fn num_kbuckets_entries(&mut self) -> usize { + pub fn num_kbuckets_entries(&mut self) -> impl ExactSizeIterator { self.discovery.num_kbuckets_entries() } + /// Returns the number of records in the Kademlia record stores. + pub fn num_kademlia_records(&mut self) -> impl ExactSizeIterator { + self.discovery.num_kademlia_records() + } + + /// Returns the total size in bytes of all the records in the Kademlia record stores. + pub fn kademlia_records_total_size(&mut self) -> impl ExactSizeIterator { + self.discovery.kademlia_records_total_size() + } + /// Borrows `self` and returns a struct giving access to the information about a node. /// /// Returns `None` if we don't know anything about this node. Always returns `Some` for nodes /// we're connected to, meaning that if `None` is returned then we're not connected to that /// node. - pub fn node(&self, peer_id: &PeerId) -> Option { - self.debug_info.node(peer_id) + pub fn node(&self, peer_id: &PeerId) -> Option { + self.peer_info.node(peer_id) } /// Registers a new notifications protocol. @@ -134,7 +177,11 @@ impl Behaviour { engine_id: ConsensusEngineId, protocol_name: impl Into>, ) { - let list = self.substrate.register_notifications_protocol(engine_id, protocol_name); + // This is the message that we will send to the remote as part of the initial handshake. + // At the moment, we force this to be an encoded `Roles`. + let handshake_message = Roles::from(&self.role).encode(); + + let list = self.substrate.register_notifications_protocol(engine_id, protocol_name, handshake_message); for (remote, roles) in list { let role = reported_roles_to_observed_role(&self.role, remote, roles); let ev = Event::NotificationStreamOpened { @@ -142,7 +189,7 @@ impl Behaviour { engine_id, role, }; - self.events.push(BehaviourOut::Event(ev)); + self.events.push_back(BehaviourOut::Event(ev)); } } @@ -200,15 +247,41 @@ Behaviour { fn inject_event(&mut self, event: CustomMessageOutcome) { match event { CustomMessageOutcome::BlockImport(origin, blocks) => - self.events.push(BehaviourOut::BlockImport(origin, blocks)), + self.events.push_back(BehaviourOut::BlockImport(origin, blocks)), CustomMessageOutcome::JustificationImport(origin, hash, nb, justification) => - self.events.push(BehaviourOut::JustificationImport(origin, hash, nb, justification)), + self.events.push_back(BehaviourOut::JustificationImport(origin, hash, nb, justification)), CustomMessageOutcome::FinalityProofImport(origin, hash, nb, proof) => - self.events.push(BehaviourOut::FinalityProofImport(origin, hash, nb, proof)), + self.events.push_back(BehaviourOut::FinalityProofImport(origin, hash, nb, proof)), + CustomMessageOutcome::BlockRequest { target, request } => { + match self.block_requests.send_request(&target, request) { + block_requests::SendRequestOutcome::Ok => { + self.events.push_back(BehaviourOut::RequestStarted { + peer: target, + protocol: self.block_requests.protocol_name().to_vec(), + }); + }, + block_requests::SendRequestOutcome::Replaced { request_duration, .. } => { + self.events.push_back(BehaviourOut::RequestFinished { + peer: target.clone(), + protocol: self.block_requests.protocol_name().to_vec(), + request_duration, + }); + self.events.push_back(BehaviourOut::RequestStarted { + peer: target, + protocol: self.block_requests.protocol_name().to_vec(), + }); + } + block_requests::SendRequestOutcome::NotConnected | + block_requests::SendRequestOutcome::EncodeError(_) => {}, + } + }, + CustomMessageOutcome::FinalityProofRequest { target, block_hash, request } => { + self.finality_proof_requests.send_request(&target, block_hash, request); + }, CustomMessageOutcome::NotificationStreamOpened { remote, protocols, roles } => { let role = reported_roles_to_observed_role(&self.role, &remote, roles); for engine_id in protocols { - self.events.push(BehaviourOut::Event(Event::NotificationStreamOpened { + self.events.push_back(BehaviourOut::Event(Event::NotificationStreamOpened { remote: remote.clone(), engine_id, role: role.clone(), @@ -217,14 +290,14 @@ Behaviour { }, CustomMessageOutcome::NotificationStreamClosed { remote, protocols } => for engine_id in protocols { - self.events.push(BehaviourOut::Event(Event::NotificationStreamClosed { + self.events.push_back(BehaviourOut::Event(Event::NotificationStreamClosed { remote: remote.clone(), engine_id, })); }, CustomMessageOutcome::NotificationsReceived { remote, messages } => { let ev = Event::NotificationsReceived { remote, messages }; - self.events.push(BehaviourOut::Event(ev)); + self.events.push_back(BehaviourOut::Event(ev)); }, CustomMessageOutcome::PeerNewBest(peer_id, number) => { self.light_client_handler.update_best_block(&peer_id, number); @@ -234,10 +307,64 @@ Behaviour { } } -impl NetworkBehaviourEventProcess +impl NetworkBehaviourEventProcess> for Behaviour { + fn inject_event(&mut self, event: block_requests::Event) { + match event { + block_requests::Event::AnsweredRequest { peer, total_handling_time } => { + self.events.push_back(BehaviourOut::AnsweredRequest { + peer, + protocol: self.block_requests.protocol_name().to_vec(), + build_time: total_handling_time, + }); + }, + block_requests::Event::Response { peer, original_request: _, response, request_duration } => { + self.events.push_back(BehaviourOut::RequestFinished { + peer: peer.clone(), + protocol: self.block_requests.protocol_name().to_vec(), + request_duration, + }); + let ev = self.substrate.on_block_response(peer, response); + self.inject_event(ev); + } + block_requests::Event::RequestCancelled { peer, request_duration, .. } | + block_requests::Event::RequestTimeout { peer, request_duration, .. } => { + // There doesn't exist any mechanism to report cancellations or timeouts yet, so + // we process them by disconnecting the node. + self.events.push_back(BehaviourOut::RequestFinished { + peer: peer.clone(), + protocol: self.block_requests.protocol_name().to_vec(), + request_duration, + }); + self.substrate.on_block_request_failed(&peer); + } + } + } +} + +impl NetworkBehaviourEventProcess> for Behaviour { + fn inject_event(&mut self, event: finality_requests::Event) { + match event { + finality_requests::Event::Response { peer, block_hash, proof } => { + let response = message::FinalityProofResponse { + id: 0, + block: block_hash, + proof: if !proof.is_empty() { + Some(proof) + } else { + None + }, + }; + let ev = self.substrate.on_finality_proof_response(peer, response); + self.inject_event(ev); + } + } + } +} + +impl NetworkBehaviourEventProcess for Behaviour { - fn inject_event(&mut self, event: debug_info::DebugInfoEvent) { - let debug_info::DebugInfoEvent::Identified { peer_id, mut info } = event; + fn inject_event(&mut self, event: peer_info::PeerInfoEvent) { + let peer_info::PeerInfoEvent::Identified { peer_id, mut info } = event; if info.listen_addrs.len() > 30 { debug!(target: "sub-libp2p", "Node {:?} has reported more than 30 addresses; \ it is identified by {:?} and {:?}", peer_id, info.protocol_version, @@ -248,7 +375,7 @@ impl NetworkBehaviourEventProcess NetworkBehaviourEventProcess DiscoveryOut::UnroutablePeer(_peer_id) => { // Obtaining and reporting listen addresses for unroutable peers back // to Kademlia is handled by the `Identify` protocol, part of the - // `DebugInfoBehaviour`. See the `NetworkBehaviourEventProcess` - // implementation for `DebugInfoEvent`. + // `PeerInfoBehaviour`. See the `NetworkBehaviourEventProcess` + // implementation for `PeerInfoEvent`. } DiscoveryOut::Discovered(peer_id) => { self.substrate.add_discovered_nodes(iter::once(peer_id)); } DiscoveryOut::ValueFound(results) => { - self.events.push(BehaviourOut::Event(Event::Dht(DhtEvent::ValueFound(results)))); + self.events.push_back(BehaviourOut::Event(Event::Dht(DhtEvent::ValueFound(results)))); } DiscoveryOut::ValueNotFound(key) => { - self.events.push(BehaviourOut::Event(Event::Dht(DhtEvent::ValueNotFound(key)))); + self.events.push_back(BehaviourOut::Event(Event::Dht(DhtEvent::ValueNotFound(key)))); } DiscoveryOut::ValuePut(key) => { - self.events.push(BehaviourOut::Event(Event::Dht(DhtEvent::ValuePut(key)))); + self.events.push_back(BehaviourOut::Event(Event::Dht(DhtEvent::ValuePut(key)))); } DiscoveryOut::ValuePutFailed(key) => { - self.events.push(BehaviourOut::Event(Event::Dht(DhtEvent::ValuePutFailed(key)))); + self.events.push_back(BehaviourOut::Event(Event::Dht(DhtEvent::ValuePutFailed(key)))); } - DiscoveryOut::RandomKademliaStarted => { - self.events.push(BehaviourOut::RandomKademliaStarted); + DiscoveryOut::RandomKademliaStarted(protocols) => { + for protocol in protocols { + self.events.push_back(BehaviourOut::RandomKademliaStarted(protocol)); + } } } } @@ -286,8 +415,8 @@ impl NetworkBehaviourEventProcess impl Behaviour { fn poll(&mut self, _: &mut Context, _: &mut impl PollParameters) -> Poll>> { - if !self.events.is_empty() { - return Poll::Ready(NetworkBehaviourAction::GenerateEvent(self.events.remove(0))) + if let Some(event) = self.events.pop_front() { + return Poll::Ready(NetworkBehaviourAction::GenerateEvent(event)) } Poll::Pending diff --git a/client/network/src/block_requests.rs b/client/network/src/block_requests.rs new file mode 100644 index 0000000000000000000000000000000000000000..8f5116657a5c2d8a57aef6203e8c0fcfde389b27 --- /dev/null +++ b/client/network/src/block_requests.rs @@ -0,0 +1,845 @@ +// Copyright 2020 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 . + +//! `NetworkBehaviour` implementation which handles incoming block requests. +//! +//! Every request is coming in on a separate connection substream which gets +//! closed after we have sent the response back. Incoming requests are encoded +//! as protocol buffers (cf. `api.v1.proto`). + +#![allow(unused)] + +use bytes::Bytes; +use codec::{Encode, Decode}; +use crate::{ + chain::Client, + config::ProtocolId, + protocol::{message::{self, BlockAttributes}}, + schema, +}; +use futures::{future::BoxFuture, prelude::*, stream::FuturesUnordered}; +use futures_timer::Delay; +use libp2p::{ + core::{ + ConnectedPoint, + Multiaddr, + PeerId, + connection::ConnectionId, + upgrade::{InboundUpgrade, OutboundUpgrade, ReadOneError, UpgradeInfo, Negotiated}, + upgrade::{DeniedUpgrade, read_one, write_one} + }, + swarm::{ + NegotiatedSubstream, + NetworkBehaviour, + NetworkBehaviourAction, + NotifyHandler, + OneShotHandler, + OneShotHandlerConfig, + PollParameters, + SubstreamProtocol + } +}; +use prost::Message; +use sp_runtime::{generic::BlockId, traits::{Block, Header, One, Zero}}; +use std::{ + cmp::min, + collections::{HashMap, VecDeque}, + io, + iter, + marker::PhantomData, + pin::Pin, + sync::Arc, + time::Duration, + task::{Context, Poll} +}; +use void::{Void, unreachable}; +use wasm_timer::Instant; + +// Type alias for convenience. +pub type Error = Box; + +/// Event generated by the block requests behaviour. +#[derive(Debug)] +pub enum Event { + /// A request came and we have successfully answered it. + AnsweredRequest { + /// Peer which has emitted the request. + peer: PeerId, + /// Time elapsed between when we received the request and when we sent back the response. + total_handling_time: Duration, + }, + + /// A response to a block request has arrived. + Response { + peer: PeerId, + /// The original request passed to `send_request`. + original_request: message::BlockRequest, + response: message::BlockResponse, + /// Time elapsed between the start of the request and the response. + request_duration: Duration, + }, + + /// A request has been cancelled because the peer has disconnected. + /// Disconnects can also happen as a result of violating the network protocol. + /// + /// > **Note**: This event is NOT emitted if a request is overridden by calling `send_request`. + /// > For that, you must check the value returned by `send_request`. + RequestCancelled { + peer: PeerId, + /// The original request passed to `send_request`. + original_request: message::BlockRequest, + /// Time elapsed between the start of the request and the cancellation. + request_duration: Duration, + }, + + /// A request has timed out. + RequestTimeout { + peer: PeerId, + /// The original request passed to `send_request`. + original_request: message::BlockRequest, + /// Time elapsed between the start of the request and the timeout. + request_duration: Duration, + } +} + +/// Configuration options for `BlockRequests`. +#[derive(Debug, Clone)] +pub struct Config { + max_block_data_response: u32, + max_request_len: usize, + max_response_len: usize, + inactivity_timeout: Duration, + request_timeout: Duration, + protocol: Bytes, +} + +impl Config { + /// Create a fresh configuration with the following options: + /// + /// - max. block data in response = 128 + /// - max. request size = 1 MiB + /// - max. response size = 16 MiB + /// - inactivity timeout = 15s + /// - request timeout = 40s + pub fn new(id: &ProtocolId) -> Self { + let mut c = Config { + max_block_data_response: 128, + max_request_len: 1024 * 1024, + max_response_len: 16 * 1024 * 1024, + inactivity_timeout: Duration::from_secs(15), + request_timeout: Duration::from_secs(40), + protocol: Bytes::new(), + }; + c.set_protocol(id); + c + } + + /// Limit the max. number of block data in a response. + pub fn set_max_block_data_response(&mut self, v: u32) -> &mut Self { + self.max_block_data_response = v; + self + } + + /// Limit the max. length of incoming block request bytes. + pub fn set_max_request_len(&mut self, v: usize) -> &mut Self { + self.max_request_len = v; + self + } + + /// Limit the max. size of responses to our block requests. + pub fn set_max_response_len(&mut self, v: usize) -> &mut Self { + self.max_response_len = v; + self + } + + /// Limit the max. duration the substream may remain inactive before closing it. + pub fn set_inactivity_timeout(&mut self, v: Duration) -> &mut Self { + self.inactivity_timeout = v; + self + } + + /// Set protocol to use for upgrade negotiation. + pub fn set_protocol(&mut self, id: &ProtocolId) -> &mut Self { + let mut v = Vec::new(); + v.extend_from_slice(b"/"); + v.extend_from_slice(id.as_bytes()); + v.extend_from_slice(b"/sync/2"); + self.protocol = v.into(); + self + } +} + +/// The block request handling behaviour. +pub struct BlockRequests { + /// This behaviour's configuration. + config: Config, + /// Blockchain client. + chain: Arc>, + /// List of all active connections and the requests we've sent. + peers: HashMap>>, + /// Futures sending back the block request response. Returns the `PeerId` we sent back to, and + /// the total time the handling of this request took. + outgoing: FuturesUnordered>, + /// Events to return as soon as possible from `poll`. + pending_events: VecDeque, Event>>, +} + +/// Local tracking of a libp2p connection. +#[derive(Debug)] +struct Connection { + id: ConnectionId, + ongoing_request: Option>, +} + +#[derive(Debug)] +struct OngoingRequest { + /// `Instant` when the request has been emitted. Used for diagnostic purposes. + emitted: Instant, + request: message::BlockRequest, + timeout: Delay, +} + +/// Outcome of calling `send_request`. +#[derive(Debug)] +#[must_use] +pub enum SendRequestOutcome { + /// Request has been emitted. + Ok, + /// The request has been emitted and has replaced an existing request. + Replaced { + /// The previously-emitted request. + previous: message::BlockRequest, + /// Time that had elapsed since `previous` has been emitted. + request_duration: Duration, + }, + /// Didn't start a request because we have no connection to this node. + /// If `send_request` returns that, it is as if the function had never been called. + NotConnected, + /// Error while serializing the request. + EncodeError(prost::EncodeError), +} + +impl BlockRequests +where + B: Block, +{ + pub fn new(cfg: Config, chain: Arc>) -> Self { + BlockRequests { + config: cfg, + chain, + peers: HashMap::new(), + outgoing: FuturesUnordered::new(), + pending_events: VecDeque::new(), + } + } + + /// Returns the libp2p protocol name used on the wire (e.g. `/foo/sync/2`). + pub fn protocol_name(&self) -> &[u8] { + &self.config.protocol + } + + /// Issue a new block request. + /// + /// Cancels any existing request targeting the same `PeerId`. + /// + /// If the response doesn't arrive in time, or if the remote answers improperly, the target + /// will be disconnected. + pub fn send_request(&mut self, target: &PeerId, req: message::BlockRequest) -> SendRequestOutcome { + // Determine which connection to send the request to. + let connection = if let Some(peer) = self.peers.get_mut(target) { + // We don't want to have multiple requests for any given node, so in priority try to + // find a connection with an existing request, to override it. + if let Some(entry) = peer.iter_mut().find(|c| c.ongoing_request.is_some()) { + entry + } else if let Some(entry) = peer.get_mut(0) { + entry + } else { + log::error!( + target: "sync", + "State inconsistency: empty list of peer connections" + ); + return SendRequestOutcome::NotConnected; + } + } else { + return SendRequestOutcome::NotConnected; + }; + + let protobuf_rq = build_protobuf_block_request( + req.fields, + req.from.clone(), + req.to.clone(), + req.direction, + req.max, + ); + + let mut buf = Vec::with_capacity(protobuf_rq.encoded_len()); + if let Err(err) = protobuf_rq.encode(&mut buf) { + log::warn!( + target: "sync", + "Failed to encode block request {:?}: {:?}", + protobuf_rq, + err + ); + return SendRequestOutcome::EncodeError(err); + } + + let previous_request = connection.ongoing_request.take(); + connection.ongoing_request = Some(OngoingRequest { + emitted: Instant::now(), + request: req.clone(), + timeout: Delay::new(self.config.request_timeout), + }); + + log::trace!(target: "sync", "Enqueueing block request to {:?}: {:?}", target, protobuf_rq); + self.pending_events.push_back(NetworkBehaviourAction::NotifyHandler { + peer_id: target.clone(), + handler: NotifyHandler::One(connection.id), + event: OutboundProtocol { + request: buf, + original_request: req, + max_response_size: self.config.max_response_len, + protocol: self.config.protocol.clone(), + }, + }); + + if let Some(previous_request) = previous_request { + log::debug!( + target: "sync", + "Replacing existing block request on connection {:?}", + connection.id + ); + SendRequestOutcome::Replaced { + previous: previous_request.request, + request_duration: previous_request.emitted.elapsed(), + } + } else { + SendRequestOutcome::Ok + } + } + + /// Callback, invoked when a new block request has been received from remote. + fn on_block_request + ( &mut self + , peer: &PeerId + , request: &schema::v1::BlockRequest + ) -> Result + { + log::trace!( + target: "sync", + "Block request from peer {}: from block {:?} to block {:?}, max blocks {:?}", + peer, + request.from_block, + request.to_block, + request.max_blocks); + + let from_block_id = + match request.from_block { + Some(schema::v1::block_request::FromBlock::Hash(ref h)) => { + let h = Decode::decode(&mut h.as_ref())?; + BlockId::::Hash(h) + } + Some(schema::v1::block_request::FromBlock::Number(ref n)) => { + let n = Decode::decode(&mut n.as_ref())?; + BlockId::::Number(n) + } + None => { + let msg = "missing `BlockRequest::from_block` field"; + return Err(io::Error::new(io::ErrorKind::Other, msg).into()) + } + }; + + let max_blocks = + if request.max_blocks == 0 { + self.config.max_block_data_response + } else { + min(request.max_blocks, self.config.max_block_data_response) + }; + + let direction = + if request.direction == schema::v1::Direction::Ascending as i32 { + schema::v1::Direction::Ascending + } else if request.direction == schema::v1::Direction::Descending as i32 { + schema::v1::Direction::Descending + } else { + let msg = format!("invalid `BlockRequest::direction` value: {}", request.direction); + return Err(io::Error::new(io::ErrorKind::Other, msg).into()) + }; + + let attributes = BlockAttributes::from_be_u32(request.fields)?; + let get_header = attributes.contains(BlockAttributes::HEADER); + let get_body = attributes.contains(BlockAttributes::BODY); + let get_justification = attributes.contains(BlockAttributes::JUSTIFICATION); + + let mut blocks = Vec::new(); + let mut block_id = from_block_id; + while let Some(header) = self.chain.header(block_id).unwrap_or(None) { + if blocks.len() >= max_blocks as usize { + break + } + + let number = *header.number(); + let hash = header.hash(); + let parent_hash = *header.parent_hash(); + let justification = if get_justification { + self.chain.justification(&BlockId::Hash(hash))? + } else { + None + }; + let is_empty_justification = justification.as_ref().map(|j| j.is_empty()).unwrap_or(false); + + let block_data = schema::v1::BlockData { + hash: hash.encode(), + header: if get_header { + header.encode() + } else { + Vec::new() + }, + body: if get_body { + self.chain.block_body(&BlockId::Hash(hash))? + .unwrap_or(Vec::new()) + .iter_mut() + .map(|extrinsic| extrinsic.encode()) + .collect() + } else { + Vec::new() + }, + receipt: Vec::new(), + message_queue: Vec::new(), + justification: justification.unwrap_or(Vec::new()), + is_empty_justification, + }; + + blocks.push(block_data); + + match direction { + schema::v1::Direction::Ascending => { + block_id = BlockId::Number(number + One::one()) + } + schema::v1::Direction::Descending => { + if number.is_zero() { + break + } + block_id = BlockId::Hash(parent_hash) + } + } + } + + Ok(schema::v1::BlockResponse { blocks }) + } +} + +impl NetworkBehaviour for BlockRequests +where + B: Block +{ + type ProtocolsHandler = OneShotHandler, OutboundProtocol, NodeEvent>; + type OutEvent = Event; + + fn new_handler(&mut self) -> Self::ProtocolsHandler { + let p = InboundProtocol { + max_request_len: self.config.max_request_len, + protocol: self.config.protocol.clone(), + marker: PhantomData, + }; + let mut cfg = OneShotHandlerConfig::default(); + cfg.keep_alive_timeout = self.config.inactivity_timeout; + cfg.outbound_substream_timeout = self.config.request_timeout; + OneShotHandler::new(SubstreamProtocol::new(p), cfg) + } + + fn addresses_of_peer(&mut self, _: &PeerId) -> Vec { + Vec::new() + } + + fn inject_connected(&mut self, _peer: &PeerId) { + } + + fn inject_disconnected(&mut self, _peer: &PeerId) { + } + + fn inject_connection_established(&mut self, peer_id: &PeerId, id: &ConnectionId, _: &ConnectedPoint) { + self.peers.entry(peer_id.clone()) + .or_default() + .push(Connection { + id: *id, + ongoing_request: None, + }); + } + + fn inject_connection_closed(&mut self, peer_id: &PeerId, id: &ConnectionId, _: &ConnectedPoint) { + let mut needs_remove = false; + if let Some(entry) = self.peers.get_mut(peer_id) { + if let Some(pos) = entry.iter().position(|i| i.id == *id) { + let ongoing_request = entry.remove(pos).ongoing_request; + if let Some(ongoing_request) = ongoing_request { + log::debug!( + target: "sync", + "Connection {:?} with {} closed with ongoing sync request: {:?}", + id, + peer_id, + ongoing_request + ); + let ev = Event::RequestCancelled { + peer: peer_id.clone(), + original_request: ongoing_request.request.clone(), + request_duration: ongoing_request.emitted.elapsed(), + }; + self.pending_events.push_back(NetworkBehaviourAction::GenerateEvent(ev)); + } + if entry.is_empty() { + needs_remove = true; + } + } else { + log::error!( + target: "sync", + "State inconsistency: connection id not found in list" + ); + } + } else { + log::error!( + target: "sync", + "State inconsistency: peer_id not found in list of connections" + ); + } + if needs_remove { + self.peers.remove(peer_id); + } + } + + fn inject_event( + &mut self, + peer: PeerId, + connection_id: ConnectionId, + node_event: NodeEvent + ) { + match node_event { + NodeEvent::Request(request, mut stream, handling_start) => { + match self.on_block_request(&peer, &request) { + Ok(res) => { + log::trace!( + target: "sync", + "Enqueueing block response for peer {} with {} blocks", + peer, res.blocks.len() + ); + let mut data = Vec::with_capacity(res.encoded_len()); + if let Err(e) = res.encode(&mut data) { + log::debug!( + target: "sync", + "Error encoding block response for peer {}: {}", + peer, e + ) + } else { + self.outgoing.push(async move { + if let Err(e) = write_one(&mut stream, data).await { + log::debug!( + target: "sync", + "Error writing block response: {}", + e + ); + } + (peer, handling_start.elapsed()) + }.boxed()); + } + } + Err(e) => log::debug!( + target: "sync", + "Error handling block request from peer {}: {}", peer, e + ) + } + } + NodeEvent::Response(original_request, response) => { + log::trace!( + target: "sync", + "Received block response from peer {} with {} blocks", + peer, response.blocks.len() + ); + let request_duration = if let Some(connections) = self.peers.get_mut(&peer) { + if let Some(connection) = connections.iter_mut().find(|c| c.id == connection_id) { + if let Some(ongoing_request) = &mut connection.ongoing_request { + if ongoing_request.request == original_request { + let request_duration = ongoing_request.emitted.elapsed(); + connection.ongoing_request = None; + request_duration + } else { + // We're no longer interested in that request. + log::debug!( + target: "sync", + "Received response from {} to obsolete block request {:?}", + peer, + original_request + ); + return; + } + } else { + // We remove from `self.peers` requests we're no longer interested in, + // so this can legitimately happen. + log::trace!( + target: "sync", + "Response discarded because it concerns an obsolete request" + ); + return; + } + } else { + log::error!( + target: "sync", + "State inconsistency: response on non-existing connection {:?}", + connection_id + ); + return; + } + } else { + log::error!( + target: "sync", + "State inconsistency: response on non-connected peer {}", + peer + ); + return; + }; + + let blocks = response.blocks.into_iter().map(|block_data| { + Ok(message::BlockData:: { + hash: Decode::decode(&mut block_data.hash.as_ref())?, + header: if !block_data.header.is_empty() { + Some(Decode::decode(&mut block_data.header.as_ref())?) + } else { + None + }, + body: if original_request.fields.contains(message::BlockAttributes::BODY) { + Some(block_data.body.iter().map(|body| { + Decode::decode(&mut body.as_ref()) + }).collect::, _>>()?) + } else { + None + }, + receipt: if !block_data.message_queue.is_empty() { + Some(block_data.receipt) + } else { + None + }, + message_queue: if !block_data.message_queue.is_empty() { + Some(block_data.message_queue) + } else { + None + }, + justification: if !block_data.justification.is_empty() { + Some(block_data.justification) + } else if block_data.is_empty_justification { + Some(Vec::new()) + } else { + None + }, + }) + }).collect::, codec::Error>>(); + + match blocks { + Ok(blocks) => { + let id = original_request.id; + let ev = Event::Response { + peer, + original_request, + response: message::BlockResponse:: { id, blocks }, + request_duration, + }; + self.pending_events.push_back(NetworkBehaviourAction::GenerateEvent(ev)); + } + Err(err) => { + log::debug!( + target: "sync", + "Failed to decode block response from peer {}: {}", peer, err + ); + } + } + } + } + } + + fn poll(&mut self, cx: &mut Context, _: &mut impl PollParameters) + -> Poll, Event>> + { + if let Some(ev) = self.pending_events.pop_front() { + return Poll::Ready(ev); + } + + // Check the request timeouts. + for (peer, connections) in &mut self.peers { + for connection in connections { + let ongoing_request = match &mut connection.ongoing_request { + Some(rq) => rq, + None => continue, + }; + + if let Poll::Ready(_) = Pin::new(&mut ongoing_request.timeout).poll(cx) { + let original_request = ongoing_request.request.clone(); + let request_duration = ongoing_request.emitted.elapsed(); + connection.ongoing_request = None; + log::debug!( + target: "sync", + "Request timeout for {}: {:?}", + peer, original_request + ); + let ev = Event::RequestTimeout { + peer: peer.clone(), + original_request, + request_duration, + }; + return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)); + } + } + } + + if let Poll::Ready(Some((peer, total_handling_time))) = self.outgoing.poll_next_unpin(cx) { + let ev = Event::AnsweredRequest { + peer, + total_handling_time, + }; + return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)); + } + + Poll::Pending + } +} + +/// Output type of inbound and outbound substream upgrades. +#[derive(Debug)] +pub enum NodeEvent { + /// Incoming request from remote, substream to use for the response, and when we started + /// handling this request. + Request(schema::v1::BlockRequest, T, Instant), + /// Incoming response from remote. + Response(message::BlockRequest, schema::v1::BlockResponse), +} + +/// Substream upgrade protocol. +/// +/// We attempt to parse an incoming protobuf encoded request (cf. `Request`) +/// which will be handled by the `BlockRequests` behaviour, i.e. the request +/// will become visible via `inject_node_event` which then dispatches to the +/// relevant callback to process the message and prepare a response. +#[derive(Debug, Clone)] +pub struct InboundProtocol { + /// The max. request length in bytes. + max_request_len: usize, + /// The protocol to use during upgrade negotiation. + protocol: Bytes, + /// Type of the block. + marker: PhantomData, +} + +impl UpgradeInfo for InboundProtocol { + type Info = Bytes; + type InfoIter = iter::Once; + + fn protocol_info(&self) -> Self::InfoIter { + iter::once(self.protocol.clone()) + } +} + +impl InboundUpgrade for InboundProtocol +where + B: Block, + T: AsyncRead + AsyncWrite + Unpin + Send + 'static +{ + type Output = NodeEvent; + type Error = ReadOneError; + type Future = BoxFuture<'static, Result>; + + fn upgrade_inbound(self, mut s: T, _: Self::Info) -> Self::Future { + // This `Instant` will be passed around until the processing of this request is done. + let handling_start = Instant::now(); + + let future = async move { + let len = self.max_request_len; + let vec = read_one(&mut s, len).await?; + match schema::v1::BlockRequest::decode(&vec[..]) { + Ok(r) => Ok(NodeEvent::Request(r, s, handling_start)), + Err(e) => Err(ReadOneError::Io(io::Error::new(io::ErrorKind::Other, e))) + } + }; + future.boxed() + } +} + +/// Substream upgrade protocol. +/// +/// Sends a request to remote and awaits the response. +#[derive(Debug, Clone)] +pub struct OutboundProtocol { + /// The serialized protobuf request. + request: Vec, + /// The original request. Passed back through the API when the response comes back. + original_request: message::BlockRequest, + /// The max. response length in bytes. + max_response_size: usize, + /// The protocol to use for upgrade negotiation. + protocol: Bytes, +} + +impl UpgradeInfo for OutboundProtocol { + type Info = Bytes; + type InfoIter = iter::Once; + + fn protocol_info(&self) -> Self::InfoIter { + iter::once(self.protocol.clone()) + } +} + +impl OutboundUpgrade for OutboundProtocol +where + B: Block, + T: AsyncRead + AsyncWrite + Unpin + Send + 'static +{ + type Output = NodeEvent; + type Error = ReadOneError; + type Future = BoxFuture<'static, Result>; + + fn upgrade_outbound(self, mut s: T, _: Self::Info) -> Self::Future { + async move { + write_one(&mut s, &self.request).await?; + let vec = read_one(&mut s, self.max_response_size).await?; + + schema::v1::BlockResponse::decode(&vec[..]) + .map(|r| NodeEvent::Response(self.original_request, r)) + .map_err(|e| { + ReadOneError::Io(io::Error::new(io::ErrorKind::Other, e)) + }) + }.boxed() + } +} + +/// Build protobuf block request message. +pub(crate) fn build_protobuf_block_request( + attributes: BlockAttributes, + from_block: message::FromBlock, + to_block: Option, + direction: message::Direction, + max_blocks: Option, +) -> schema::v1::BlockRequest { + schema::v1::BlockRequest { + fields: attributes.to_be_u32(), + from_block: match from_block { + message::FromBlock::Hash(h) => + Some(schema::v1::block_request::FromBlock::Hash(h.encode())), + message::FromBlock::Number(n) => + Some(schema::v1::block_request::FromBlock::Number(n.encode())), + }, + to_block: to_block.map(|h| h.encode()).unwrap_or_default(), + direction: match direction { + message::Direction::Ascending => schema::v1::Direction::Ascending as i32, + message::Direction::Descending => schema::v1::Direction::Descending as i32, + }, + max_blocks: max_blocks.unwrap_or(0), + } +} diff --git a/client/network/src/chain.rs b/client/network/src/chain.rs index 4e7e28be93ec0b744b181d42508b191aeb5b3357..20fbe0284397d513a909cbcf72733a265c060214 100644 --- a/client/network/src/chain.rs +++ b/client/network/src/chain.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Blockchain access trait diff --git a/client/network/src/config.rs b/client/network/src/config.rs index c9290927ebaff5a7814a5a3129c6381fcebc4447..94b2993b4e6bd255e332de67d0219ecf90ff8a0a 100644 --- a/client/network/src/config.rs +++ b/client/network/src/config.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Configuration of the networking layer. //! @@ -21,7 +23,6 @@ pub use crate::chain::{Client, FinalityProofProvider}; pub use crate::on_demand_layer::{AlwaysBadChecker, OnDemand}; -pub use crate::service::{TransactionPool, EmptyTransactionPool}; pub use libp2p::{identity, core::PublicKey, wasm_ext::ExtTransport, build_multiaddr}; // Note: this re-export shouldn't be part of the public API of the crate and will be removed in @@ -29,18 +30,27 @@ pub use libp2p::{identity, core::PublicKey, wasm_ext::ExtTransport, build_multia #[doc(hidden)] pub use crate::protocol::ProtocolConfig; -use crate::service::ExHashT; +use crate::ExHashT; -use sp_consensus::{block_validation::BlockAnnounceValidator, import_queue::ImportQueue}; -use sp_runtime::traits::{Block as BlockT}; -use libp2p::identity::{Keypair, ed25519}; -use libp2p::wasm_ext; -use libp2p::{PeerId, Multiaddr, multiaddr}; use core::{fmt, iter}; -use std::{convert::TryFrom, future::Future, pin::Pin, str::FromStr}; -use std::{error::Error, fs, io::{self, Write}, net::Ipv4Addr, path::{Path, PathBuf}, sync::Arc}; -use zeroize::Zeroize; +use futures::future; +use libp2p::identity::{ed25519, Keypair}; +use libp2p::wasm_ext; +use libp2p::{multiaddr, Multiaddr, PeerId}; use prometheus_endpoint::Registry; +use sp_consensus::{block_validation::BlockAnnounceValidator, import_queue::ImportQueue}; +use sp_runtime::{traits::Block as BlockT, ConsensusEngineId}; +use std::{borrow::Cow, convert::TryFrom, future::Future, pin::Pin, str::FromStr}; +use std::{ + collections::HashMap, + error::Error, + fs, + io::{self, Write}, + net::Ipv4Addr, + path::{Path, PathBuf}, + sync::Arc, +}; +use zeroize::Zeroize; /// Network initialization parameters. pub struct Params { @@ -159,6 +169,70 @@ impl FinalityProofRequestBuilder for DummyFinalityProofRequestBuil /// Shared finality proof request builder struct used by the queue. pub type BoxFinalityProofRequestBuilder = Box + Send + Sync>; +/// Result of the transaction import. +#[derive(Clone, Copy, Debug)] +pub enum TransactionImport { + /// Transaction is good but already known by the transaction pool. + KnownGood, + /// Transaction is good and not yet known. + NewGood, + /// Transaction is invalid. + Bad, + /// Transaction import was not performed. + None, +} + +/// Fuure resolving to transaction import result. +pub type TransactionImportFuture = Pin + Send>>; + +/// 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. + /// + /// This will return future. + fn import( + &self, + transaction: B::Extrinsic, + ) -> TransactionImportFuture; + /// Notify the pool about transactions broadcast. + fn on_broadcasted(&self, propagations: HashMap>); + /// Get transaction by hash. + fn transaction(&self, hash: &H) -> Option; +} + +/// Dummy implementation of the [`TransactionPool`] trait for a transaction pool that is always +/// empty and discards all incoming transactions. +/// +/// Requires the "hash" type to implement the `Default` trait. +/// +/// Useful for testing purposes. +pub struct EmptyTransactionPool; + +impl TransactionPool for EmptyTransactionPool { + fn transactions(&self) -> Vec<(H, B::Extrinsic)> { + Vec::new() + } + + fn hash_of(&self, _transaction: &B::Extrinsic) -> H { + Default::default() + } + + fn import( + &self, + _transaction: B::Extrinsic + ) -> TransactionImportFuture { + Box::pin(future::ready(TransactionImport::KnownGood)) + } + + fn on_broadcasted(&self, _: HashMap>) {} + + fn transaction(&self, _h: &H) -> Option { None } +} + /// Name of a protocol, transmitted on the wire. Should be unique for each chain. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ProtocolId(smallvec::SmallVec<[u8; 6]>); @@ -198,8 +272,21 @@ pub fn parse_str_addr(addr_str: &str) -> Result<(PeerId, Multiaddr), ParseErr> { /// Splits a Multiaddress into a Multiaddress and PeerId. pub fn parse_addr(mut addr: Multiaddr)-> Result<(PeerId, Multiaddr), ParseErr> { let who = match addr.pop() { - Some(multiaddr::Protocol::P2p(key)) => PeerId::from_multihash(key) - .map_err(|_| ParseErr::InvalidPeerId)?, + Some(multiaddr::Protocol::P2p(key)) => { + if !matches!(key.algorithm(), multiaddr::multihash::Code::Identity) { + // (note: this is the "person bowing" emoji) + log::warn!( + "🙇 You are using the peer ID {}. This peer ID uses a legacy, deprecated \ + representation that will no longer be supported in the future. \ + Please refresh it by performing a RPC query to the appropriate node, \ + by looking at its logs, or by using `subkey inspect-node-key` on its \ + private key.", + bs58::encode(key.as_bytes()).into_string() + ); + } + + PeerId::from_multihash(key).map_err(|_| ParseErr::InvalidPeerId)? + }, _ => return Err(ParseErr::PeerIdMissing), }; @@ -307,8 +394,6 @@ impl From for ParseErr { /// Network service configuration. #[derive(Clone, Debug)] pub struct NetworkConfiguration { - /// Directory path to store general network configuration. None means nothing will be saved. - pub config_path: Option, /// Directory path to store network-specific configuration. None means nothing will be saved. pub net_config_path: Option, /// Multiaddresses to listen for incoming connections. @@ -319,6 +404,9 @@ pub struct NetworkConfiguration { pub boot_nodes: Vec, /// The node key configuration, which determines the node's network identity keypair. pub node_key: NodeKeyConfig, + /// List of notifications protocols that the node supports. Must also include a + /// `ConsensusEngineId` for backwards-compatibility. + pub notifications_protocols: Vec<(ConsensusEngineId, Cow<'static, [u8]>)>, /// Maximum allowed number of incoming connections. pub in_peers: u32, /// Number of outgoing connections we're trying to maintain. @@ -335,23 +423,31 @@ pub struct NetworkConfiguration { pub transport: TransportConfig, /// Maximum number of peers to ask the same blocks in parallel. pub max_parallel_downloads: u32, + /// Should we insert non-global addresses into the DHT? + pub allow_non_globals_in_dht: bool, } -impl Default for NetworkConfiguration { - fn default() -> Self { +impl NetworkConfiguration { + /// Create new default configuration + pub fn new, SV: Into>( + node_name: SN, + client_version: SV, + node_key: NodeKeyConfig, + net_config_path: Option, + ) -> Self { NetworkConfiguration { - config_path: None, - net_config_path: None, + net_config_path, listen_addresses: Vec::new(), public_addresses: Vec::new(), boot_nodes: Vec::new(), - node_key: NodeKeyConfig::Ed25519(Secret::New), + node_key, + notifications_protocols: Vec::new(), in_peers: 25, out_peers: 75, reserved_nodes: Vec::new(), non_reserved_mode: NonReservedPeerMode::Accept, - client_version: "unknown".into(), - node_name: "unknown".into(), + client_version: client_version.into(), + node_name: node_name.into(), transport: TransportConfig::Normal { enable_mdns: false, allow_private_ipv4: true, @@ -359,35 +455,47 @@ impl Default for NetworkConfiguration { use_yamux_flow_control: false, }, max_parallel_downloads: 5, + allow_non_globals_in_dht: false, } } } impl NetworkConfiguration { - /// Create a new instance of default settings. - pub fn new() -> Self { - Self::default() - } - /// Create new default configuration for localhost-only connection with random port (useful for testing) pub fn new_local() -> NetworkConfiguration { - let mut config = NetworkConfiguration::new(); + let mut config = NetworkConfiguration::new( + "test-node", + "test-client", + Default::default(), + None, + ); + config.listen_addresses = vec![ iter::once(multiaddr::Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1))) .chain(iter::once(multiaddr::Protocol::Tcp(0))) .collect() ]; + + config.allow_non_globals_in_dht = true; config } /// Create new default configuration for localhost-only connection with random port (useful for testing) pub fn new_memory() -> NetworkConfiguration { - let mut config = NetworkConfiguration::new(); + let mut config = NetworkConfiguration::new( + "test-node", + "test-client", + Default::default(), + None, + ); + config.listen_addresses = vec![ iter::once(multiaddr::Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1))) .chain(iter::once(multiaddr::Protocol::Tcp(0))) .collect() ]; + + config.allow_non_globals_in_dht = true; config } } @@ -452,6 +560,12 @@ pub enum NodeKeyConfig { Ed25519(Secret) } +impl Default for NodeKeyConfig { + fn default() -> NodeKeyConfig { + NodeKeyConfig::Ed25519(Secret::New) + } +} + /// The options for obtaining a Ed25519 secret key. pub type Ed25519Secret = Secret; diff --git a/client/network/src/discovery.rs b/client/network/src/discovery.rs index ed5016642be8b3e47e27588d2a86f3a01ea98614..d08f9d44a15b99e7e6a0cd20c6967f7f4a9a68f0 100644 --- a/client/network/src/discovery.rs +++ b/client/network/src/discovery.rs @@ -26,12 +26,12 @@ //! //! - mDNS. Discovers nodes on the local network by broadcasting UDP packets. //! -//! - Kademlia random walk. Once connected, we perform random Kademlia `FIND_NODE` requests in -//! order for nodes to propagate to us their view of the network. This is performed automatically -//! by the `DiscoveryBehaviour`. +//! - Kademlia random walk. Once connected, we perform random Kademlia `FIND_NODE` requests on the +//! configured Kademlia DHTs in order for nodes to propagate to us their view of the network. This +//! is performed automatically by the `DiscoveryBehaviour`. //! //! Additionally, the `DiscoveryBehaviour` is also capable of storing and loading value in the -//! network-wide DHT. +//! configured DHTs. //! //! ## Usage //! @@ -45,85 +45,145 @@ //! of a node's address, you must call `add_self_reported_address`. //! +use crate::config::ProtocolId; use futures::prelude::*; use futures_timer::Delay; -use libp2p::core::{nodes::listeners::ListenerId, ConnectedPoint, Multiaddr, PeerId, PublicKey}; -use libp2p::swarm::{ProtocolsHandler, NetworkBehaviour, NetworkBehaviourAction, PollParameters}; -use libp2p::kad::{Kademlia, KademliaEvent, Quorum, Record}; +use ip_network::IpNetwork; +use libp2p::core::{connection::{ConnectionId, ListenerId}, ConnectedPoint, Multiaddr, PeerId, PublicKey}; +use libp2p::swarm::{NetworkBehaviour, NetworkBehaviourAction, PollParameters, ProtocolsHandler}; +use libp2p::swarm::protocols_handler::multi::MultiHandler; +use libp2p::kad::{Kademlia, KademliaConfig, KademliaEvent, QueryResult, Quorum, Record}; use libp2p::kad::GetClosestPeersError; -use libp2p::kad::record::{self, store::MemoryStore}; +use libp2p::kad::handler::KademliaHandler; +use libp2p::kad::QueryId; +use libp2p::kad::record::{self, store::{MemoryStore, RecordStore}}; #[cfg(not(target_os = "unknown"))] -use libp2p::{swarm::toggle::Toggle}; +use libp2p::swarm::toggle::Toggle; #[cfg(not(target_os = "unknown"))] use libp2p::mdns::{Mdns, MdnsEvent}; use libp2p::multiaddr::Protocol; -use log::{debug, info, trace, warn, error}; -use std::{cmp, collections::VecDeque, time::Duration}; +use log::{debug, info, trace, warn}; +use std::{cmp, collections::{HashMap, HashSet, VecDeque}, io, time::Duration}; use std::task::{Context, Poll}; use sp_core::hexdisplay::HexDisplay; -/// Implementation of `NetworkBehaviour` that discovers the nodes on the network. -pub struct DiscoveryBehaviour { - /// User-defined list of nodes and their addresses. Typically includes bootstrap nodes and - /// reserved nodes. - user_defined: Vec<(PeerId, Multiaddr)>, - /// Kademlia requests and answers. - kademlia: Kademlia, - /// Discovers nodes on the local network. - #[cfg(not(target_os = "unknown"))] - mdns: Toggle, - /// Stream that fires when we need to perform the next random Kademlia query. - next_kad_random_query: Delay, - /// After `next_kad_random_query` triggers, the next one triggers after this duration. - duration_to_next_kad: Duration, - /// Discovered nodes to return. - discoveries: VecDeque, - /// Identity of our local node. +/// `DiscoveryBehaviour` configuration. +/// +/// Note: In order to discover nodes or load and store values via Kademlia one has to add at least +/// one protocol via [`DiscoveryConfig::add_protocol`]. +pub struct DiscoveryConfig { local_peer_id: PeerId, - /// Number of nodes we're currently connected to. - num_connections: u64, - /// If false, `addresses_of_peer` won't return any private IPv4 address, except for the ones - /// stored in `user_defined`. + user_defined: Vec<(PeerId, Multiaddr)>, allow_private_ipv4: bool, - /// Number of active connections over which we interrupt the discovery process. + allow_non_globals_in_dht: bool, discovery_only_if_under_num: u64, + enable_mdns: bool, + kademlias: HashMap> } -impl DiscoveryBehaviour { - /// Builds a new `DiscoveryBehaviour`. - /// - /// `user_defined` is a list of known address for nodes that never expire. - pub async fn new( - local_public_key: PublicKey, - user_defined: Vec<(PeerId, Multiaddr)>, - enable_mdns: bool, - allow_private_ipv4: bool, - discovery_only_if_under_num: u64, - ) -> Self { - if enable_mdns { - #[cfg(target_os = "unknown")] - warn!(target: "sub-libp2p", "mDNS is not available on this platform"); +impl DiscoveryConfig { + /// Create a default configuration with the given public key. + pub fn new(local_public_key: PublicKey) -> Self { + DiscoveryConfig { + local_peer_id: local_public_key.into_peer_id(), + user_defined: Vec::new(), + allow_private_ipv4: true, + allow_non_globals_in_dht: false, + discovery_only_if_under_num: std::u64::MAX, + enable_mdns: false, + kademlias: HashMap::new() + } + } + + /// Set the number of active connections at which we pause discovery. + pub fn discovery_limit(&mut self, limit: u64) -> &mut Self { + self.discovery_only_if_under_num = limit; + self + } + + /// Set custom nodes which never expire, e.g. bootstrap or reserved nodes. + pub fn with_user_defined(&mut self, user_defined: I) -> &mut Self + where + I: IntoIterator + { + for (peer_id, addr) in user_defined { + for kad in self.kademlias.values_mut() { + kad.add_address(&peer_id, addr.clone()); + } + self.user_defined.push((peer_id, addr)) } + self + } - let local_id = local_public_key.clone().into_peer_id(); - let store = MemoryStore::new(local_id.clone()); - let mut kademlia = Kademlia::new(local_id.clone(), store); - for (peer_id, addr) in &user_defined { - kademlia.add_address(peer_id, addr.clone()); + /// Should private IPv4 addresses be reported? + pub fn allow_private_ipv4(&mut self, value: bool) -> &mut Self { + self.allow_private_ipv4 = value; + self + } + + /// Should non-global addresses be inserted to the DHT? + pub fn allow_non_globals_in_dht(&mut self, value: bool) -> &mut Self { + self.allow_non_globals_in_dht = value; + self + } + + /// Should MDNS discovery be supported? + pub fn with_mdns(&mut self, value: bool) -> &mut Self { + if value && cfg!(target_os = "unknown") { + log::warn!(target: "sub-libp2p", "mDNS is not available on this platform") } + self.enable_mdns = value; + self + } + + /// Add discovery via Kademlia for the given protocol. + pub fn add_protocol(&mut self, p: ProtocolId) -> &mut Self { + // NB: If this protocol name derivation is changed, check if + // `DiscoveryBehaviour::new_handler` is still correct. + let proto_name = { + let mut v = vec![b'/']; + v.extend_from_slice(p.as_bytes()); + v.extend_from_slice(b"/kad"); + v + }; + + self.add_kademlia(p, proto_name); + self + } + fn add_kademlia(&mut self, id: ProtocolId, proto_name: Vec) { + if self.kademlias.contains_key(&id) { + warn!(target: "sub-libp2p", "Discovery already registered for protocol {:?}", id); + return + } + + let mut config = KademliaConfig::default(); + config.set_protocol_name(proto_name); + + let store = MemoryStore::new(self.local_peer_id.clone()); + let mut kad = Kademlia::with_config(self.local_peer_id.clone(), store, config); + + for (peer_id, addr) in &self.user_defined { + kad.add_address(peer_id, addr.clone()); + } + + self.kademlias.insert(id, kad); + } + + /// Create a `DiscoveryBehaviour` from this config. + pub fn finish(self) -> DiscoveryBehaviour { DiscoveryBehaviour { - user_defined, - kademlia, + user_defined: self.user_defined, + kademlias: self.kademlias, next_kad_random_query: Delay::new(Duration::new(0, 0)), duration_to_next_kad: Duration::from_secs(1), - discoveries: VecDeque::new(), - local_peer_id: local_public_key.into_peer_id(), + pending_events: VecDeque::new(), + local_peer_id: self.local_peer_id, num_connections: 0, - allow_private_ipv4, - discovery_only_if_under_num, + allow_private_ipv4: self.allow_private_ipv4, + discovery_only_if_under_num: self.discovery_only_if_under_num, #[cfg(not(target_os = "unknown"))] - mdns: if enable_mdns { + mdns: if self.enable_mdns { match Mdns::new() { Ok(mdns) => Some(mdns).into(), Err(err) => { @@ -134,12 +194,54 @@ impl DiscoveryBehaviour { } else { None.into() }, + allow_non_globals_in_dht: self.allow_non_globals_in_dht } } +} + +/// Implementation of `NetworkBehaviour` that discovers the nodes on the network. +pub struct DiscoveryBehaviour { + /// User-defined list of nodes and their addresses. Typically includes bootstrap nodes and + /// reserved nodes. + user_defined: Vec<(PeerId, Multiaddr)>, + /// Kademlia requests and answers. + kademlias: HashMap>, + /// Discovers nodes on the local network. + #[cfg(not(target_os = "unknown"))] + mdns: Toggle, + /// Stream that fires when we need to perform the next random Kademlia query. + next_kad_random_query: Delay, + /// After `next_kad_random_query` triggers, the next one triggers after this duration. + duration_to_next_kad: Duration, + /// Events to return in priority when polled. + pending_events: VecDeque, + /// Identity of our local node. + local_peer_id: PeerId, + /// Number of nodes we're currently connected to. + num_connections: u64, + /// If false, `addresses_of_peer` won't return any private IPv4 address, except for the ones + /// stored in `user_defined`. + allow_private_ipv4: bool, + /// Number of active connections over which we interrupt the discovery process. + discovery_only_if_under_num: u64, + /// Should non-global addresses be added to the DHT? + allow_non_globals_in_dht: bool +} +impl DiscoveryBehaviour { /// Returns the list of nodes that we know exist in the network. - pub fn known_peers(&mut self) -> impl Iterator { - self.kademlia.kbuckets_entries() + pub fn known_peers(&mut self) -> HashSet { + let mut peers = HashSet::new(); + for k in self.kademlias.values_mut() { + for b in k.kbuckets() { + for e in b.iter() { + if !peers.contains(e.node.key.preimage()) { + peers.insert(e.node.key.preimage().clone()); + } + } + } + } + peers } /// Adds a hard-coded address for the given peer, that never expires. @@ -149,7 +251,10 @@ impl DiscoveryBehaviour { /// If we didn't know this address before, also generates a `Discovered` event. pub fn add_known_address(&mut self, peer_id: PeerId, addr: Multiaddr) { if self.user_defined.iter().all(|(p, a)| *p != peer_id && *a != addr) { - self.discoveries.push_back(peer_id.clone()); + for k in self.kademlias.values_mut() { + k.add_address(&peer_id, addr.clone()); + } + self.pending_events.push_back(DiscoveryOut::Discovered(peer_id.clone())); self.user_defined.push((peer_id, addr)); } } @@ -159,14 +264,22 @@ impl DiscoveryBehaviour { /// **Note**: It is important that you call this method, otherwise the discovery mechanism will /// not properly work. pub fn add_self_reported_address(&mut self, peer_id: &PeerId, addr: Multiaddr) { - self.kademlia.add_address(peer_id, addr); + if self.allow_non_globals_in_dht || self.can_add_to_dht(&addr) { + for k in self.kademlias.values_mut() { + k.add_address(peer_id, addr.clone()); + } + } else { + log::trace!(target: "sub-libp2p", "Ignoring self-reported address {} from {}", addr, peer_id); + } } /// Start fetching a record from the DHT. /// /// A corresponding `ValueFound` or `ValueNotFound` event will later be generated. pub fn get_value(&mut self, key: &record::Key) { - self.kademlia.get_record(key, Quorum::One) + for k in self.kademlias.values_mut() { + k.get_record(key, Quorum::One); + } } /// Start putting a record into the DHT. Other nodes can later fetch that value with @@ -174,12 +287,55 @@ impl DiscoveryBehaviour { /// /// A corresponding `ValuePut` or `ValuePutFailed` event will later be generated. pub fn put_value(&mut self, key: record::Key, value: Vec) { - self.kademlia.put_record(Record::new(key, value), Quorum::All); + for k in self.kademlias.values_mut() { + if let Err(e) = k.put_record(Record::new(key.clone(), value.clone()), Quorum::All) { + warn!(target: "sub-libp2p", "Libp2p => Failed to put record: {:?}", e); + self.pending_events.push_back(DiscoveryOut::ValuePutFailed(key.clone())); + } + } } /// Returns the number of nodes that are in the Kademlia k-buckets. - pub fn num_kbuckets_entries(&mut self) -> usize { - self.kademlia.kbuckets_entries().count() + pub fn num_kbuckets_entries(&mut self) -> impl ExactSizeIterator { + self.kademlias.iter_mut() + .map(|(id, kad)| (id, kad.kbuckets().map(|bucket| bucket.iter().count()).sum())) + } + + /// Returns the number of records in the Kademlia record stores. + pub fn num_kademlia_records(&mut self) -> impl ExactSizeIterator { + // Note that this code is ok only because we use a `MemoryStore`. + self.kademlias.iter_mut().map(|(id, kad)| { + let num = kad.store_mut().records().count(); + (id, num) + }) + } + + /// Returns the total size in bytes of all the records in the Kademlia record stores. + pub fn kademlia_records_total_size(&mut self) -> impl ExactSizeIterator { + // Note that this code is ok only because we use a `MemoryStore`. If the records were + // for example stored on disk, this would load every single one of them every single time. + self.kademlias.iter_mut().map(|(id, kad)| { + let size = kad.store_mut().records().fold(0, |tot, rec| tot + rec.value.len()); + (id, size) + }) + } + + /// Can the given `Multiaddr` be put into the DHT? + /// + /// This test is successful only for global IP addresses and DNS names. + // + // NB: Currently all DNS names are allowed and no check for TLD suffixes is done + // because the set of valid domains is highly dynamic and would require frequent + // updates, for example by utilising publicsuffix.org or IANA. + pub fn can_add_to_dht(&self, addr: &Multiaddr) -> bool { + let ip = match addr.iter().next() { + Some(Protocol::Ip4(ip)) => IpNetwork::from(ip), + Some(Protocol::Ip6(ip)) => IpNetwork::from(ip), + Some(Protocol::Dns(_)) | Some(Protocol::Dns4(_)) | Some(Protocol::Dns6(_)) + => return true, + _ => return false + }; + ip.is_global() } } @@ -209,16 +365,24 @@ pub enum DiscoveryOut { /// Inserting a value into the DHT failed. ValuePutFailed(record::Key), - /// Started a random Kademlia query. - RandomKademliaStarted, + /// Started a random Kademlia query for each DHT identified by the given `ProtocolId`s. + RandomKademliaStarted(Vec), } impl NetworkBehaviour for DiscoveryBehaviour { - type ProtocolsHandler = as NetworkBehaviour>::ProtocolsHandler; + type ProtocolsHandler = MultiHandler>; type OutEvent = DiscoveryOut; fn new_handler(&mut self) -> Self::ProtocolsHandler { - NetworkBehaviour::new_handler(&mut self.kademlia) + let iter = self.kademlias.iter_mut() + .map(|(p, k)| (p.clone(), NetworkBehaviour::new_handler(k))); + + MultiHandler::try_from_iter(iter) + .expect("There can be at most one handler per `ProtocolId` and \ + protocol names contain the `ProtocolId` so no two protocol \ + names in `self.kademlias` can be equal which is the only error \ + `try_from_iter` can return, therefore this call is guaranteed \ + to succeed; qed") } fn addresses_of_peer(&mut self, peer_id: &PeerId) -> Vec { @@ -227,7 +391,11 @@ impl NetworkBehaviour for DiscoveryBehaviour { .collect::>(); { - let mut list_to_filter = self.kademlia.addresses_of_peer(peer_id); + let mut list_to_filter = Vec::new(); + for k in self.kademlias.values_mut() { + list_to_filter.extend(k.addresses_of_peer(peer_id)) + } + #[cfg(not(target_os = "unknown"))] list_to_filter.extend(self.mdns.addresses_of_peer(peer_id)); @@ -246,31 +414,35 @@ impl NetworkBehaviour for DiscoveryBehaviour { list.extend(list_to_filter); } - trace!(target: "sub-libp2p", "Addresses of {:?} are {:?}", peer_id, list); - if list.is_empty() { - if self.kademlia.kbuckets_entries().any(|p| p == peer_id) { - debug!(target: "sub-libp2p", "Requested dialing to {:?} (peer in k-buckets), \ - and no address was found", peer_id); - } else { - debug!(target: "sub-libp2p", "Requested dialing to {:?} (peer not in k-buckets), \ - and no address was found", peer_id); - } - } + trace!(target: "sub-libp2p", "Addresses of {:?}: {:?}", peer_id, list); + list } - fn inject_connected(&mut self, peer_id: PeerId, endpoint: ConnectedPoint) { + fn inject_connection_established(&mut self, peer_id: &PeerId, conn: &ConnectionId, endpoint: &ConnectedPoint) { self.num_connections += 1; - NetworkBehaviour::inject_connected(&mut self.kademlia, peer_id, endpoint) + for k in self.kademlias.values_mut() { + NetworkBehaviour::inject_connection_established(k, peer_id, conn, endpoint) + } } - fn inject_disconnected(&mut self, peer_id: &PeerId, endpoint: ConnectedPoint) { + fn inject_connected(&mut self, peer_id: &PeerId) { + for k in self.kademlias.values_mut() { + NetworkBehaviour::inject_connected(k, peer_id) + } + } + + fn inject_connection_closed(&mut self, peer_id: &PeerId, conn: &ConnectionId, endpoint: &ConnectedPoint) { self.num_connections -= 1; - NetworkBehaviour::inject_disconnected(&mut self.kademlia, peer_id, endpoint) + for k in self.kademlias.values_mut() { + NetworkBehaviour::inject_connection_closed(k, peer_id, conn, endpoint) + } } - fn inject_replaced(&mut self, peer_id: PeerId, closed: ConnectedPoint, opened: ConnectedPoint) { - NetworkBehaviour::inject_replaced(&mut self.kademlia, peer_id, closed, opened) + fn inject_disconnected(&mut self, peer_id: &PeerId) { + for k in self.kademlias.values_mut() { + NetworkBehaviour::inject_disconnected(k, peer_id) + } } fn inject_addr_reach_failure( @@ -279,45 +451,62 @@ impl NetworkBehaviour for DiscoveryBehaviour { addr: &Multiaddr, error: &dyn std::error::Error ) { - NetworkBehaviour::inject_addr_reach_failure(&mut self.kademlia, peer_id, addr, error) + for k in self.kademlias.values_mut() { + NetworkBehaviour::inject_addr_reach_failure(k, peer_id, addr, error) + } } - fn inject_node_event( + fn inject_event( &mut self, peer_id: PeerId, - event: ::OutEvent, + connection: ConnectionId, + (pid, event): ::OutEvent, ) { - NetworkBehaviour::inject_node_event(&mut self.kademlia, peer_id, event) + if let Some(kad) = self.kademlias.get_mut(&pid) { + return kad.inject_event(peer_id, connection, event) + } + log::error!(target: "sub-libp2p", + "inject_node_event: no kademlia instance registered for protocol {:?}", + pid) } fn inject_new_external_addr(&mut self, addr: &Multiaddr) { let new_addr = addr.clone() .with(Protocol::P2p(self.local_peer_id.clone().into())); info!(target: "sub-libp2p", "🔍 Discovered new external address for our node: {}", new_addr); - NetworkBehaviour::inject_new_external_addr(&mut self.kademlia, addr) + for k in self.kademlias.values_mut() { + NetworkBehaviour::inject_new_external_addr(k, addr) + } } fn inject_expired_listen_addr(&mut self, addr: &Multiaddr) { - info!(target: "sub-libp2p", "No longer listening on {}", addr); - NetworkBehaviour::inject_expired_listen_addr(&mut self.kademlia, addr) + for k in self.kademlias.values_mut() { + NetworkBehaviour::inject_expired_listen_addr(k, addr) + } } fn inject_dial_failure(&mut self, peer_id: &PeerId) { - NetworkBehaviour::inject_dial_failure(&mut self.kademlia, peer_id) + for k in self.kademlias.values_mut() { + NetworkBehaviour::inject_dial_failure(k, peer_id) + } } fn inject_new_listen_addr(&mut self, addr: &Multiaddr) { - NetworkBehaviour::inject_new_listen_addr(&mut self.kademlia, addr) + for k in self.kademlias.values_mut() { + NetworkBehaviour::inject_new_listen_addr(k, addr) + } } fn inject_listener_error(&mut self, id: ListenerId, err: &(dyn std::error::Error + 'static)) { - error!(target: "sub-libp2p", "Error on libp2p listener {:?}: {}", id, err); - NetworkBehaviour::inject_listener_error(&mut self.kademlia, id, err); + for k in self.kademlias.values_mut() { + NetworkBehaviour::inject_listener_error(k, id, err) + } } - fn inject_listener_closed(&mut self, id: ListenerId) { - error!(target: "sub-libp2p", "Libp2p listener {:?} closed", id); - NetworkBehaviour::inject_listener_closed(&mut self.kademlia, id); + fn inject_listener_closed(&mut self, id: ListenerId, reason: Result<(), &io::Error>) { + for k in self.kademlias.values_mut() { + NetworkBehaviour::inject_listener_closed(k, id, reason) + } } fn poll( @@ -331,8 +520,7 @@ impl NetworkBehaviour for DiscoveryBehaviour { >, > { // Immediately process the content of `discovered`. - if let Some(peer_id) = self.discoveries.pop_front() { - let ev = DiscoveryOut::Discovered(peer_id); + if let Some(ev) = self.pending_events.pop_front() { return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)); } @@ -340,12 +528,13 @@ impl NetworkBehaviour for DiscoveryBehaviour { while let Poll::Ready(_) = self.next_kad_random_query.poll_unpin(cx) { let actually_started = if self.num_connections < self.discovery_only_if_under_num { let random_peer_id = PeerId::random(); - debug!(target: "sub-libp2p", "Libp2p <= Starting random Kademlia request for \ - {:?}", random_peer_id); - - self.kademlia.get_closest_peers(random_peer_id); + debug!(target: "sub-libp2p", + "Libp2p <= Starting random Kademlia request for {:?}", + random_peer_id); + for k in self.kademlias.values_mut() { + k.get_closest_peers(random_peer_id.clone()); + } true - } else { debug!( target: "sub-libp2p", @@ -362,101 +551,107 @@ impl NetworkBehaviour for DiscoveryBehaviour { Duration::from_secs(60)); if actually_started { - let ev = DiscoveryOut::RandomKademliaStarted; + let ev = DiscoveryOut::RandomKademliaStarted(self.kademlias.keys().cloned().collect()); return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)); } } - // Poll Kademlia. - while let Poll::Ready(ev) = self.kademlia.poll(cx, params) { - match ev { - NetworkBehaviourAction::GenerateEvent(ev) => match ev { - KademliaEvent::UnroutablePeer { peer, .. } => { - let ev = DiscoveryOut::UnroutablePeer(peer); - return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)); - } - KademliaEvent::RoutingUpdated { peer, .. } => { - let ev = DiscoveryOut::Discovered(peer); - return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)); - } - KademliaEvent::GetClosestPeersResult(res) => { - match res { - Err(GetClosestPeersError::Timeout { key, peers }) => { - 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", - HexDisplay::from(&ok.key), ok.peers.len()); - if ok.peers.is_empty() && self.num_connections != 0 { - debug!(target: "sub-libp2p", "Libp2p => Random Kademlia query has yielded empty \ - results"); + // Poll Kademlias. + for (pid, kademlia) in &mut self.kademlias { + while let Poll::Ready(ev) = kademlia.poll(cx, params) { + match ev { + NetworkBehaviourAction::GenerateEvent(ev) => match ev { + KademliaEvent::RoutingUpdated { peer, .. } => { + let ev = DiscoveryOut::Discovered(peer); + return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)); + } + KademliaEvent::UnroutablePeer { peer, .. } => { + let ev = DiscoveryOut::UnroutablePeer(peer); + return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)); + } + KademliaEvent::RoutablePeer { .. } | KademliaEvent::PendingRoutablePeer { .. } => { + // We are not interested in these events at the moment. + } + KademliaEvent::QueryResult { result: QueryResult::GetClosestPeers(res), .. } => { + match res { + Err(GetClosestPeersError::Timeout { key, peers }) => { + 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", + HexDisplay::from(&ok.key), ok.peers.len()); + if ok.peers.is_empty() && self.num_connections != 0 { + debug!(target: "sub-libp2p", "Libp2p => Random Kademlia query has yielded empty \ + results"); + } } } } - } - KademliaEvent::GetRecordResult(res) => { - let ev = match res { - Ok(ok) => { - let results = ok.records - .into_iter() - .map(|r| (r.key, r.value)) - .collect(); - - DiscoveryOut::ValueFound(results) - } - Err(e @ libp2p::kad::GetRecordError::NotFound { .. }) => { - trace!(target: "sub-libp2p", - "Libp2p => Failed to get record: {:?}", e); - DiscoveryOut::ValueNotFound(e.into_key()) - } - Err(e) => { - warn!(target: "sub-libp2p", - "Libp2p => Failed to get record: {:?}", e); - DiscoveryOut::ValueNotFound(e.into_key()) - } - }; - return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)); - } - KademliaEvent::PutRecordResult(res) => { - let ev = match res { - Ok(ok) => DiscoveryOut::ValuePut(ok.key), - Err(e) => { - warn!(target: "sub-libp2p", - "Libp2p => Failed to put record: {:?}", e); - DiscoveryOut::ValuePutFailed(e.into_key()) + KademliaEvent::QueryResult { result: QueryResult::GetRecord(res), .. } => { + let ev = match res { + Ok(ok) => { + let results = ok.records + .into_iter() + .map(|r| (r.record.key, r.record.value)) + .collect(); + + DiscoveryOut::ValueFound(results) + } + Err(e @ libp2p::kad::GetRecordError::NotFound { .. }) => { + trace!(target: "sub-libp2p", + "Libp2p => Failed to get record: {:?}", e); + DiscoveryOut::ValueNotFound(e.into_key()) + } + Err(e) => { + warn!(target: "sub-libp2p", + "Libp2p => Failed to get record: {:?}", e); + DiscoveryOut::ValueNotFound(e.into_key()) + } + }; + return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)); + } + KademliaEvent::QueryResult { result: QueryResult::PutRecord(res), .. } => { + let ev = match res { + Ok(ok) => DiscoveryOut::ValuePut(ok.key), + Err(e) => { + warn!(target: "sub-libp2p", + "Libp2p => Failed to put record: {:?}", e); + DiscoveryOut::ValuePutFailed(e.into_key()) + } + }; + return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)); + } + KademliaEvent::QueryResult { result: QueryResult::RepublishRecord(res), .. } => { + match res { + Ok(ok) => debug!(target: "sub-libp2p", + "Libp2p => Record republished: {:?}", + ok.key), + Err(e) => warn!(target: "sub-libp2p", + "Libp2p => Republishing of record {:?} failed with: {:?}", + e.key(), e) } - }; - return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)); - } - KademliaEvent::RepublishRecordResult(res) => { - match res { - Ok(ok) => debug!(target: "sub-libp2p", - "Libp2p => Record republished: {:?}", - ok.key), - Err(e) => warn!(target: "sub-libp2p", - "Libp2p => Republishing of record {:?} failed with: {:?}", - e.key(), e) + } + // We never start any other type of query. + e => { + warn!(target: "sub-libp2p", "Libp2p => Unhandled Kademlia event: {:?}", e) } } - KademliaEvent::Discovered { .. } => { - // We are not interested in these events at the moment. - } - // We never start any other type of query. - e => { - warn!(target: "sub-libp2p", "Libp2p => Unhandled Kademlia event: {:?}", e) - } - }, - NetworkBehaviourAction::DialAddress { address } => - return Poll::Ready(NetworkBehaviourAction::DialAddress { address }), - NetworkBehaviourAction::DialPeer { peer_id } => - return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }), - NetworkBehaviourAction::SendEvent { peer_id, event } => - return Poll::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }), - NetworkBehaviourAction::ReportObservedAddr { address } => - return Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }), + NetworkBehaviourAction::DialAddress { address } => + return Poll::Ready(NetworkBehaviourAction::DialAddress { address }), + NetworkBehaviourAction::DialPeer { peer_id, condition } => + return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id, condition }), + NetworkBehaviourAction::NotifyHandler { peer_id, handler, event } => + return Poll::Ready(NetworkBehaviourAction::NotifyHandler { + peer_id, + handler, + event: (pid.clone(), event) + }), + NetworkBehaviourAction::ReportObservedAddr { address } => + return Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }), + } } } @@ -471,9 +666,8 @@ impl NetworkBehaviour for DiscoveryBehaviour { continue; } - self.discoveries.extend(list.into_iter().map(|(peer_id, _)| peer_id)); - if let Some(peer_id) = self.discoveries.pop_front() { - let ev = DiscoveryOut::Discovered(peer_id); + self.pending_events.extend(list.map(|(peer_id, _)| DiscoveryOut::Discovered(peer_id))); + if let Some(ev) = self.pending_events.pop_front() { return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)); } }, @@ -482,9 +676,9 @@ impl NetworkBehaviour for DiscoveryBehaviour { }, NetworkBehaviourAction::DialAddress { address } => return Poll::Ready(NetworkBehaviourAction::DialAddress { address }), - NetworkBehaviourAction::DialPeer { peer_id } => - return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }), - NetworkBehaviourAction::SendEvent { event, .. } => + NetworkBehaviourAction::DialPeer { peer_id, condition } => + return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id, condition }), + NetworkBehaviourAction::NotifyHandler { event, .. } => match event {}, // `event` is an enum with no variant NetworkBehaviourAction::ReportObservedAddr { address } => return Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }), @@ -497,6 +691,7 @@ impl NetworkBehaviour for DiscoveryBehaviour { #[cfg(test)] mod tests { + use crate::config::ProtocolId; use futures::prelude::*; use libp2p::identity::Keypair; use libp2p::Multiaddr; @@ -505,7 +700,7 @@ mod tests { use libp2p::core::upgrade::{InboundUpgradeExt, OutboundUpgradeExt}; use libp2p::swarm::Swarm; use std::{collections::HashSet, task::Poll}; - use super::{DiscoveryBehaviour, DiscoveryOut}; + use super::{DiscoveryConfig, DiscoveryOut}; #[test] fn discovery_working() { @@ -534,13 +729,19 @@ mod tests { upgrade::apply(stream, upgrade, endpoint, upgrade::Version::V1) }); - let behaviour = futures::executor::block_on({ - let user_defined = user_defined.clone(); - let keypair_public = keypair.public(); - async move { - DiscoveryBehaviour::new(keypair_public, user_defined, false, true, 50).await - } - }); + let behaviour = { + let protocol_id: &[u8] = b"/test/kad/1.0.0"; + + let mut config = DiscoveryConfig::new(keypair.public()); + config.with_user_defined(user_defined.clone()) + .allow_private_ipv4(true) + .allow_non_globals_in_dht(true) + .discovery_limit(50) + .add_protocol(ProtocolId::from(protocol_id)); + + config.finish() + }; + let mut swarm = Swarm::new(transport, behaviour, keypair.public().into_peer_id()); let listen_addr: Multiaddr = format!("/memory/{}", rand::random::()).parse().unwrap(); diff --git a/client/network/src/error.rs b/client/network/src/error.rs index 158e75fcf1d721551a3f8cfb51f4a3d8b93b73f4..b87e495983eaf9c5d229c203599d1fccb3b8ac70 100644 --- a/client/network/src/error.rs +++ b/client/network/src/error.rs @@ -1,21 +1,24 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Substrate network possible errors. +use crate::config::TransportConfig; use libp2p::{PeerId, Multiaddr}; use std::fmt; @@ -46,7 +49,18 @@ pub enum Error { second_id: PeerId, }, /// Prometheus metrics error. - Prometheus(prometheus_endpoint::PrometheusError) + Prometheus(prometheus_endpoint::PrometheusError), + /// The network addresses are invalid because they don't match the transport. + #[display( + fmt = "The following addresses are invalid because they don't match the transport: {:?}", + addresses, + )] + AddressesForAnotherTransport { + /// Transport used. + transport: TransportConfig, + /// The invalid addresses. + addresses: Vec, + }, } // Make `Debug` use the `Display` implementation. @@ -63,6 +77,7 @@ impl std::error::Error for Error { Error::Client(ref err) => Some(err), Error::DuplicateBootnode { .. } => None, Error::Prometheus(ref err) => Some(err), + Error::AddressesForAnotherTransport { .. } => None, } } } diff --git a/client/network/src/finality_requests.rs b/client/network/src/finality_requests.rs new file mode 100644 index 0000000000000000000000000000000000000000..9bb3cfec744e6639f74ab96b7bbba99a71f7aa19 --- /dev/null +++ b/client/network/src/finality_requests.rs @@ -0,0 +1,403 @@ +// Copyright 2020 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 . + +//! `NetworkBehaviour` implementation which handles incoming finality proof requests. +//! +//! Every request is coming in on a separate connection substream which gets +//! closed after we have sent the response back. Incoming requests are encoded +//! as protocol buffers (cf. `finality.v1.proto`). + +#![allow(unused)] + +use bytes::Bytes; +use codec::{Encode, Decode}; +use crate::{ + chain::FinalityProofProvider, + config::ProtocolId, + protocol::message, + schema, +}; +use futures::{future::BoxFuture, prelude::*, stream::FuturesUnordered}; +use libp2p::{ + core::{ + ConnectedPoint, + Multiaddr, + PeerId, + connection::ConnectionId, + upgrade::{InboundUpgrade, OutboundUpgrade, ReadOneError, UpgradeInfo, Negotiated}, + upgrade::{DeniedUpgrade, read_one, write_one} + }, + swarm::{ + NegotiatedSubstream, + NetworkBehaviour, + NetworkBehaviourAction, + NotifyHandler, + OneShotHandler, + OneShotHandlerConfig, + PollParameters, + SubstreamProtocol + } +}; +use prost::Message; +use sp_runtime::{generic::BlockId, traits::{Block, Header, One, Zero}}; +use std::{ + cmp::min, + collections::VecDeque, + io, + iter, + marker::PhantomData, + sync::Arc, + time::Duration, + task::{Context, Poll} +}; +use void::{Void, unreachable}; + +// Type alias for convenience. +pub type Error = Box; + +/// Event generated by the finality proof requests behaviour. +#[derive(Debug)] +pub enum Event { + /// A response to a finality proof request has arrived. + Response { + peer: PeerId, + /// Block hash originally passed to `send_request`. + block_hash: B::Hash, + /// Finality proof returned by the remote. + proof: Vec, + }, +} + +/// Configuration options for `FinalityProofRequests`. +#[derive(Debug, Clone)] +pub struct Config { + max_request_len: usize, + max_response_len: usize, + inactivity_timeout: Duration, + protocol: Bytes, +} + +impl Config { + /// Create a fresh configuration with the following options: + /// + /// - max. request size = 1 MiB + /// - max. response size = 1 MiB + /// - inactivity timeout = 15s + pub fn new(id: &ProtocolId) -> Self { + let mut c = Config { + max_request_len: 1024 * 1024, + max_response_len: 1024 * 1024, + inactivity_timeout: Duration::from_secs(15), + protocol: Bytes::new(), + }; + c.set_protocol(id); + c + } + + /// Limit the max. length of incoming finality proof request bytes. + pub fn set_max_request_len(&mut self, v: usize) -> &mut Self { + self.max_request_len = v; + self + } + + /// Limit the max. length of incoming finality proof response bytes. + pub fn set_max_response_len(&mut self, v: usize) -> &mut Self { + self.max_response_len = v; + self + } + + /// Limit the max. duration the substream may remain inactive before closing it. + pub fn set_inactivity_timeout(&mut self, v: Duration) -> &mut Self { + self.inactivity_timeout = v; + self + } + + /// Set protocol to use for upgrade negotiation. + pub fn set_protocol(&mut self, id: &ProtocolId) -> &mut Self { + let mut v = Vec::new(); + v.extend_from_slice(b"/"); + v.extend_from_slice(id.as_bytes()); + v.extend_from_slice(b"/finality-proof/1"); + self.protocol = v.into(); + self + } +} + +/// The finality proof request handling behaviour. +pub struct FinalityProofRequests { + /// This behaviour's configuration. + config: Config, + /// How to construct finality proofs. + finality_proof_provider: Option>>, + /// Futures sending back the finality proof request responses. + outgoing: FuturesUnordered>, + /// Events to return as soon as possible from `poll`. + pending_events: VecDeque, Event>>, +} + +impl FinalityProofRequests +where + B: Block, +{ + /// Initializes the behaviour. + /// + /// If the proof provider is `None`, then the behaviour will not support the finality proof + /// requests protocol. + pub fn new(cfg: Config, finality_proof_provider: Option>>) -> Self { + FinalityProofRequests { + config: cfg, + finality_proof_provider, + outgoing: FuturesUnordered::new(), + pending_events: VecDeque::new(), + } + } + + /// Issue a new finality proof request. + /// + /// If the response doesn't arrive in time, or if the remote answers improperly, the target + /// will be disconnected. + pub fn send_request(&mut self, target: &PeerId, block_hash: B::Hash, request: Vec) { + let protobuf_rq = schema::v1::finality::FinalityProofRequest { + block_hash: block_hash.encode(), + request, + }; + + let mut buf = Vec::with_capacity(protobuf_rq.encoded_len()); + if let Err(err) = protobuf_rq.encode(&mut buf) { + log::warn!("failed to encode finality proof request {:?}: {:?}", protobuf_rq, err); + return; + } + + log::trace!("enqueueing finality proof request to {:?}: {:?}", target, protobuf_rq); + self.pending_events.push_back(NetworkBehaviourAction::NotifyHandler { + peer_id: target.clone(), + handler: NotifyHandler::Any, + event: OutboundProtocol { + request: buf, + block_hash, + max_response_size: self.config.max_response_len, + protocol: self.config.protocol.clone(), + }, + }); + } + + /// Callback, invoked when a new finality request has been received from remote. + fn on_finality_request(&mut self, peer: &PeerId, request: &schema::v1::finality::FinalityProofRequest) + -> Result + { + let block_hash = Decode::decode(&mut request.block_hash.as_ref())?; + + log::trace!(target: "sync", "Finality proof request from {} for {}", peer, block_hash); + + // Note that an empty Vec is sent if no proof is available. + let finality_proof = if let Some(provider) = &self.finality_proof_provider { + provider + .prove_finality(block_hash, &request.request)? + .unwrap_or(Vec::new()) + } else { + log::error!("Answering a finality proof request while finality provider is empty"); + return Err(From::from("Empty finality proof provider".to_string())) + }; + + Ok(schema::v1::finality::FinalityProofResponse { proof: finality_proof }) + } +} + +impl NetworkBehaviour for FinalityProofRequests +where + B: Block +{ + type ProtocolsHandler = OneShotHandler, OutboundProtocol, NodeEvent>; + type OutEvent = Event; + + fn new_handler(&mut self) -> Self::ProtocolsHandler { + let p = InboundProtocol { + max_request_len: self.config.max_request_len, + protocol: if self.finality_proof_provider.is_some() { + Some(self.config.protocol.clone()) + } else { + None + }, + marker: PhantomData, + }; + let mut cfg = OneShotHandlerConfig::default(); + cfg.keep_alive_timeout = self.config.inactivity_timeout; + OneShotHandler::new(SubstreamProtocol::new(p), cfg) + } + + fn addresses_of_peer(&mut self, _: &PeerId) -> Vec { + Vec::new() + } + + fn inject_connected(&mut self, _peer: &PeerId) { + } + + fn inject_disconnected(&mut self, _peer: &PeerId) { + } + + fn inject_event( + &mut self, + peer: PeerId, + connection: ConnectionId, + event: NodeEvent + ) { + match event { + NodeEvent::Request(request, mut stream) => { + match self.on_finality_request(&peer, &request) { + Ok(res) => { + log::trace!("enqueueing finality response for peer {}", peer); + let mut data = Vec::with_capacity(res.encoded_len()); + if let Err(e) = res.encode(&mut data) { + log::debug!("error encoding finality response for peer {}: {}", peer, e) + } else { + let future = async move { + if let Err(e) = write_one(&mut stream, data).await { + log::debug!("error writing finality response: {}", e) + } + }; + self.outgoing.push(future.boxed()) + } + } + Err(e) => log::debug!("error handling finality request from peer {}: {}", peer, e) + } + } + NodeEvent::Response(response, block_hash) => { + let ev = Event::Response { + peer, + block_hash, + proof: response.proof, + }; + self.pending_events.push_back(NetworkBehaviourAction::GenerateEvent(ev)); + } + } + } + + fn poll(&mut self, cx: &mut Context, _: &mut impl PollParameters) + -> Poll, Event>> + { + if let Some(ev) = self.pending_events.pop_front() { + return Poll::Ready(ev); + } + + while let Poll::Ready(Some(_)) = self.outgoing.poll_next_unpin(cx) {} + Poll::Pending + } +} + +/// Output type of inbound and outbound substream upgrades. +#[derive(Debug)] +pub enum NodeEvent { + /// Incoming request from remote and substream to use for the response. + Request(schema::v1::finality::FinalityProofRequest, T), + /// Incoming response from remote. + Response(schema::v1::finality::FinalityProofResponse, B::Hash), +} + +/// Substream upgrade protocol. +/// +/// We attempt to parse an incoming protobuf encoded request (cf. `Request`) +/// which will be handled by the `FinalityProofRequests` behaviour, i.e. the request +/// will become visible via `inject_node_event` which then dispatches to the +/// relevant callback to process the message and prepare a response. +#[derive(Debug, Clone)] +pub struct InboundProtocol { + /// The max. request length in bytes. + max_request_len: usize, + /// The protocol to use during upgrade negotiation. If `None`, then the incoming protocol + /// is simply disabled. + protocol: Option, + /// Marker to pin the block type. + marker: PhantomData, +} + +impl UpgradeInfo for InboundProtocol { + type Info = Bytes; + // This iterator will return either 0 elements if `self.protocol` is `None`, or 1 element if + // it is `Some`. + type InfoIter = std::option::IntoIter; + + fn protocol_info(&self) -> Self::InfoIter { + self.protocol.clone().into_iter() + } +} + +impl InboundUpgrade for InboundProtocol +where + B: Block, + T: AsyncRead + AsyncWrite + Unpin + Send + 'static +{ + type Output = NodeEvent; + type Error = ReadOneError; + type Future = BoxFuture<'static, Result>; + + fn upgrade_inbound(self, mut s: T, _: Self::Info) -> Self::Future { + async move { + let len = self.max_request_len; + let vec = read_one(&mut s, len).await?; + match schema::v1::finality::FinalityProofRequest::decode(&vec[..]) { + Ok(r) => Ok(NodeEvent::Request(r, s)), + Err(e) => Err(ReadOneError::Io(io::Error::new(io::ErrorKind::Other, e))) + } + }.boxed() + } +} + +/// Substream upgrade protocol. +/// +/// Sends a request to remote and awaits the response. +#[derive(Debug, Clone)] +pub struct OutboundProtocol { + /// The serialized protobuf request. + request: Vec, + /// Block hash that has been requested. + block_hash: B::Hash, + /// The max. response length in bytes. + max_response_size: usize, + /// The protocol to use for upgrade negotiation. + protocol: Bytes, +} + +impl UpgradeInfo for OutboundProtocol { + type Info = Bytes; + type InfoIter = iter::Once; + + fn protocol_info(&self) -> Self::InfoIter { + iter::once(self.protocol.clone()) + } +} + +impl OutboundUpgrade for OutboundProtocol +where + B: Block, + T: AsyncRead + AsyncWrite + Unpin + Send + 'static +{ + type Output = NodeEvent; + type Error = ReadOneError; + type Future = BoxFuture<'static, Result>; + + fn upgrade_outbound(self, mut s: T, _: Self::Info) -> Self::Future { + async move { + write_one(&mut s, &self.request).await?; + let vec = read_one(&mut s, self.max_response_size).await?; + + schema::v1::finality::FinalityProofResponse::decode(&vec[..]) + .map(|r| NodeEvent::Response(r, self.block_hash)) + .map_err(|e| { + ReadOneError::Io(io::Error::new(io::ErrorKind::Other, e)) + }) + }.boxed() + } +} diff --git a/client/network/src/lib.rs b/client/network/src/lib.rs index b425a7763b648fe87e234e56a992f954e2c8f369..b8e5d7582b96b46934eed9ba76f2742feb4e5d55 100644 --- a/client/network/src/lib.rs +++ b/client/network/src/lib.rs @@ -1,19 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . - +// along with this program. If not, see . #![warn(unused_extern_crates)] #![warn(missing_docs)] @@ -53,9 +54,10 @@ //! - mDNS. We perform a UDP broadcast on the local network. Nodes that listen may respond with //! their identity. More info [here](https://github.com/libp2p/specs/blob/master/discovery/mdns.md). //! mDNS can be disabled in the network configuration. -//! - Kademlia random walk. Once connected, we perform random Kademlia `FIND_NODE` requests in -//! order for nodes to propagate to us their view of the network. More information about Kademlia -//! can be found [on Wikipedia](https://en.wikipedia.org/wiki/Kademlia). +//! - Kademlia random walk. Once connected, we perform random Kademlia `FIND_NODE` requests on the +//! configured Kademlia DHTs (one per configured chain protocol) in order for nodes to propagate to +//! us their view of the network. More information about Kademlia can be found [on +//! Wikipedia](https://en.wikipedia.org/wiki/Kademlia). //! //! ## Connection establishment //! @@ -75,8 +77,9 @@ //! - WebSockets for addresses of the form `/ip4/1.2.3.4/tcp/5/ws`. A TCP/IP connection is open and //! the WebSockets protocol is negotiated on top. Communications then happen inside WebSockets data //! frames. Encryption and multiplexing are additionally negotiated again inside this channel. -//! - DNS for addresses of the form `/dns4/example.com/tcp/5` or `/dns4/example.com/tcp/5/ws`. A +//! - DNS for addresses of the form `/dns/example.com/tcp/5` or `/dns/example.com/tcp/5/ws`. A //! node's address can contain a domain name. +//! - (All of the above using IPv6 instead of IPv4.) //! //! On top of the base-layer protocol, the [Noise](https://noiseprotocol.org/) protocol is //! negotiated and applied. The exact handshake protocol is experimental and is subject to change. @@ -109,7 +112,7 @@ //! to a disconnection. //! - **[`/ipfs/id/1.0.0`](https://github.com/libp2p/specs/tree/master/identify)**. We //! periodically open an ephemeral substream in order to ask information from the remote. -//! - **[`/ipfs/kad/1.0.0`](https://github.com/libp2p/specs/pull/108)**. We periodically open +//! - **[`//kad`](https://github.com/libp2p/specs/pull/108)**. We periodically open //! ephemeral substreams for Kademlia random walk queries. Each Kademlia query is done in a //! separate substream. //! @@ -210,7 +213,14 @@ //! notifications protocol. //! //! At the moment, for backwards-compatibility, notification protocols are tied to the legacy -//! Substrate substream. In the future, though, it will no longer be the case. +//! Substrate substream. Additionally, the handshake message is hardcoded to be a single 8-bits +//! integer representing the role of the node: +//! +//! - 1 for a full node. +//! - 2 for a light node. +//! - 4 for an authority. +//! +//! In the future, though, these restrictions will be removed. //! //! # Usage //! @@ -233,11 +243,15 @@ //! mod behaviour; +mod block_requests; mod chain; -mod debug_info; +mod peer_info; mod discovery; +mod finality_requests; +mod light_client_handler; mod on_demand_layer; mod protocol; +mod schema; mod service; mod transport; mod utils; @@ -246,7 +260,7 @@ pub mod config; pub mod error; pub mod network_state; -pub use service::{NetworkService, NetworkStateInfo, NetworkWorker, ExHashT, ReportHandle}; +pub use service::{NetworkService, NetworkWorker}; pub use protocol::PeerInfo; pub use protocol::event::{Event, DhtEvent, ObservedRole}; pub use protocol::sync::SyncState; @@ -255,3 +269,47 @@ pub use libp2p::{Multiaddr, PeerId}; pub use libp2p::multiaddr; pub use sc_peerset::ReputationChange; +use sp_runtime::traits::{Block as BlockT, NumberFor}; + +/// The maximum allowed number of established connections per peer. +/// +/// Typically, and by design of the network behaviours in this crate, +/// there is a single established connection per peer. However, to +/// avoid unnecessary and nondeterministic connection closure in +/// case of (possibly repeated) simultaneous dialing attempts between +/// two peers, the per-peer connection limit is not set to 1 but 2. +const MAX_CONNECTIONS_PER_PEER: usize = 2; + +/// Minimum Requirements for a Hash within Networking +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 +{} + +/// Trait for providing information about the local network state +pub trait NetworkStateInfo { + /// Returns the local external addresses. + fn external_addresses(&self) -> Vec; + + /// Returns the local Peer ID. + fn local_peer_id(&self) -> PeerId; +} + +/// Overview status of the network. +#[derive(Clone)] +pub struct NetworkStatus { + /// Current global sync state. + pub sync_state: SyncState, + /// Target sync block number. + pub best_seen_block: Option>, + /// Number of peers participating in syncing. + pub num_sync_peers: u32, + /// Total number of connected peers + pub num_connected_peers: usize, + /// Total number of active peers. + pub num_active_peers: usize, + /// Downloaded bytes per second averaged over the past few seconds. + pub average_download_per_sec: u64, + /// Uploaded bytes per second averaged over the past few seconds. + pub average_upload_per_sec: u64, +} diff --git a/client/network/src/protocol/light_client_handler.rs b/client/network/src/light_client_handler.rs similarity index 75% rename from client/network/src/protocol/light_client_handler.rs rename to client/network/src/light_client_handler.rs index 88a951914944ec04aaa7b2986836a6f2ae242506..678a717a898ff47b45174c3807a6d7d6b12a508c 100644 --- a/client/network/src/protocol/light_client_handler.rs +++ b/client/network/src/light_client_handler.rs @@ -27,9 +27,11 @@ use bytes::Bytes; use codec::{self, Encode, Decode}; use crate::{ + block_requests::build_protobuf_block_request, chain::Client, config::ProtocolId, - protocol::{api, message::BlockAttributes} + protocol::message::{BlockAttributes, Direction, FromBlock}, + schema, }; use futures::{channel::oneshot, future::BoxFuture, prelude::*, stream::FuturesUnordered}; use libp2p::{ @@ -37,6 +39,7 @@ use libp2p::{ ConnectedPoint, Multiaddr, PeerId, + connection::ConnectionId, upgrade::{InboundUpgrade, ReadOneError, UpgradeInfo, Negotiated}, upgrade::{OutboundUpgrade, read_one, write_one} }, @@ -44,20 +47,28 @@ use libp2p::{ NegotiatedSubstream, NetworkBehaviour, NetworkBehaviourAction, + NotifyHandler, OneShotHandler, + OneShotHandlerConfig, PollParameters, - SubstreamProtocol + SubstreamProtocol, } }; use nohash_hasher::IntMap; use prost::Message; -use sc_client::light::fetcher; -use sc_client_api::StorageProof; +use sc_client_api::{ + StorageProof, + light::{ + self, RemoteReadRequest, RemoteBodyRequest, ChangesProof, + RemoteCallRequest, RemoteChangesRequest, RemoteHeaderRequest, + } +}; use sc_peerset::ReputationChange; use sp_core::{ - storage::{ChildInfo, StorageKey}, + storage::{ChildInfo, ChildType,StorageKey, PrefixedStorageKey}, hexdisplay::HexDisplay, }; +use smallvec::SmallVec; use sp_blockchain::{Error as ClientError}; use sp_runtime::{ traits::{Block, Header, NumberFor, Zero}, @@ -189,27 +200,27 @@ pub enum Error { #[derive(Debug)] pub enum Request { Body { - request: fetcher::RemoteBodyRequest, + request: RemoteBodyRequest, sender: oneshot::Sender, ClientError>> }, Header { - request: fetcher::RemoteHeaderRequest, + request: light::RemoteHeaderRequest, sender: oneshot::Sender> }, Read { - request: fetcher::RemoteReadRequest, + request: light::RemoteReadRequest, sender: oneshot::Sender, Option>>, ClientError>> }, ReadChild { - request: fetcher::RemoteReadChildRequest, + request: light::RemoteReadChildRequest, sender: oneshot::Sender, Option>>, ClientError>> }, Call { - request: fetcher::RemoteCallRequest, + request: light::RemoteCallRequest, sender: oneshot::Sender, ClientError>> }, Changes { - request: fetcher::RemoteChangesRequest, + request: light::RemoteChangesRequest, sender: oneshot::Sender, u32)>, ClientError>> } } @@ -237,25 +248,39 @@ struct RequestWrapper { retries: usize, /// The actual request. request: Request, - /// Peer information, e.g. `PeerId`. - peer: P + /// The peer to send the request to, e.g. `PeerId`. + peer: P, + /// The connection to use for sending the request. + connection: Option, } /// Information we have about some peer. #[derive(Debug)] struct PeerInfo { - address: Multiaddr, + connections: SmallVec<[(ConnectionId, Multiaddr); crate::MAX_CONNECTIONS_PER_PEER]>, best_block: Option>, status: PeerStatus, } +impl Default for PeerInfo { + fn default() -> Self { + PeerInfo { + connections: SmallVec::new(), + best_block: None, + status: PeerStatus::Idle, + } + } +} + +type RequestId = u64; + /// A peer is either idle or busy processing a request from us. #[derive(Debug, Clone, PartialEq, Eq)] enum PeerStatus { /// The peer is available. Idle, /// We wait for the peer to return us a response for the given request ID. - BusyWith(u64), + BusyWith(RequestId), } /// The light client handler behaviour. @@ -265,7 +290,7 @@ pub struct LightClientHandler { /// Blockchain client. chain: Arc>, /// Verifies that received responses are correct. - checker: Arc>, + checker: Arc>, /// Peer information (addresses, their best block, etc.) peers: HashMap>, /// Futures sending back response to remote clients. @@ -273,9 +298,9 @@ pub struct LightClientHandler { /// Pending (local) requests. pending_requests: VecDeque>, /// Requests on their way to remote peers. - outstanding: IntMap>, + outstanding: IntMap>, /// (Local) Request ID counter - next_request_id: u64, + next_request_id: RequestId, /// Handle to use for reporting misbehaviour of peers. peerset: sc_peerset::PeersetHandle, } @@ -288,7 +313,7 @@ where pub fn new( cfg: Config, chain: Arc>, - checker: Arc>, + checker: Arc>, peerset: sc_peerset::PeersetHandle, ) -> Self { LightClientHandler { @@ -323,35 +348,18 @@ where retries: retries(&req), request: req, peer: (), // we do not know the peer yet + connection: None, }; self.pending_requests.push_back(rw); Ok(()) } - fn next_request_id(&mut self) -> u64 { + fn next_request_id(&mut self) -> RequestId { let id = self.next_request_id; self.next_request_id += 1; id } - // Iterate over peers known to possess a certain block. - fn idle_peers_with_block(&mut self, num: NumberFor) -> impl Iterator + '_ { - self.peers.iter() - .filter(move |(_, info)| { - info.status == PeerStatus::Idle && info.best_block >= Some(num) - }) - .map(|(peer, _)| peer.clone()) - } - - // Iterate over peers without a known block. - fn idle_peers_with_unknown_block(&mut self) -> impl Iterator + '_ { - self.peers.iter() - .filter(|(_, info)| { - info.status == PeerStatus::Idle && info.best_block.is_none() - }) - .map(|(peer, _)| peer.clone()) - } - /// Remove the given peer. /// /// If we have a request to this peer in flight, we move it back to @@ -364,12 +372,50 @@ where retries: rw.retries, request: rw.request, peer: (), // need to find another peer + connection: None, }; self.pending_requests.push_back(rw); } self.peers.remove(peer); } + /// Prepares a request by selecting a suitable peer and connection to send it to. + /// + /// If there is currently no suitable peer for the request, the given request + /// is returned as `Err`. + fn prepare_request(&self, req: RequestWrapper) + -> Result<(PeerId, RequestWrapper), RequestWrapper> + { + let number = required_block(&req.request); + + let mut peer = None; + for (peer_id, peer_info) in self.peers.iter() { + if peer_info.status == PeerStatus::Idle { + match peer_info.best_block { + Some(n) => if n >= number { + peer = Some((peer_id, peer_info)); + break + }, + None => peer = Some((peer_id, peer_info)) + } + } + } + + if let Some((peer_id, peer_info)) = peer { + let connection = peer_info.connections.iter().next().map(|(id, _)| *id); + let rw = RequestWrapper { + timestamp: req.timestamp, + retries: req.retries, + request: req.request, + peer: peer_id.clone(), + connection, + }; + Ok((peer_id.clone(), rw)) + } else { + Err(req) + } + } + /// Process a local request's response from remote. /// /// If successful, this will give us the actual, checked data we should be @@ -392,10 +438,10 @@ where ( &mut self , peer: &PeerId , request: &Request - , response: api::v1::light::Response + , response: schema::v1::light::Response ) -> Result, Error> { - use api::v1::light::response::Response; + use schema::v1::light::response::Response; match response.response { Some(Response::RemoteCallResponse(response)) => if let Request::Call { request , .. } = request { @@ -432,7 +478,7 @@ where } r }; - let reply = self.checker.check_changes_proof(&request, fetcher::ChangesProof { + let reply = self.checker.check_changes_proof(&request, light::ChangesProof { max_block, proof: response.proof, roots, @@ -464,7 +510,7 @@ where ( &mut self , peer: &PeerId , request: &Request - , response: api::v1::BlockResponse + , response: schema::v1::BlockResponse ) -> Result, Error> { let request = if let Request::Body { request , .. } = &request { @@ -489,8 +535,8 @@ where fn on_remote_call_request ( &mut self , peer: &PeerId - , request: &api::v1::light::RemoteCallRequest - ) -> Result + , request: &schema::v1::light::RemoteCallRequest + ) -> Result { log::trace!("remote call request from {} ({} at {:?})", peer, @@ -514,18 +560,18 @@ where }; let response = { - let r = api::v1::light::RemoteCallResponse { proof: proof.encode() }; - api::v1::light::response::Response::RemoteCallResponse(r) + let r = schema::v1::light::RemoteCallResponse { proof: proof.encode() }; + schema::v1::light::response::Response::RemoteCallResponse(r) }; - Ok(api::v1::light::Response { response: Some(response) }) + Ok(schema::v1::light::Response { response: Some(response) }) } fn on_remote_read_request ( &mut self , peer: &PeerId - , request: &api::v1::light::RemoteReadRequest - ) -> Result + , request: &schema::v1::light::RemoteReadRequest + ) -> Result { if request.keys.is_empty() { log::debug!("invalid remote read request sent by {}", peer); @@ -552,18 +598,18 @@ where }; let response = { - let r = api::v1::light::RemoteReadResponse { proof: proof.encode() }; - api::v1::light::response::Response::RemoteReadResponse(r) + let r = schema::v1::light::RemoteReadResponse { proof: proof.encode() }; + schema::v1::light::response::Response::RemoteReadResponse(r) }; - Ok(api::v1::light::Response { response: Some(response) }) + Ok(schema::v1::light::Response { response: Some(response) }) } fn on_remote_read_child_request ( &mut self , peer: &PeerId - , request: &api::v1::light::RemoteReadChildRequest - ) -> Result + , request: &schema::v1::light::RemoteReadChildRequest + ) -> Result { if request.keys.is_empty() { log::debug!("invalid remote child read request sent by {}", peer); @@ -578,49 +624,41 @@ where let block = Decode::decode(&mut request.block.as_ref())?; - let proof = - if let Some(info) = ChildInfo::resolve_child_info(request.child_type, &request.child_info[..]) { - match self.chain.read_child_proof( - &BlockId::Hash(block), - &request.storage_key, - info, - &mut request.keys.iter().map(AsRef::as_ref) - ) { - Ok(proof) => proof, - Err(error) => { - log::trace!("remote read child request from {} ({} {} at {:?}) failed with: {}", - peer, - HexDisplay::from(&request.storage_key), - fmt_keys(request.keys.first(), request.keys.last()), - request.block, - error); - StorageProof::empty() - } - } - } else { + let prefixed_key = PrefixedStorageKey::new_ref(&request.storage_key); + let child_info = match ChildType::from_prefixed_key(prefixed_key) { + Some((ChildType::ParentKeyId, storage_key)) => Ok(ChildInfo::new_default(storage_key)), + None => Err("Invalid child storage key".into()), + }; + let proof = match child_info.and_then(|child_info| self.chain.read_child_proof( + &BlockId::Hash(block), + &child_info, + &mut request.keys.iter().map(AsRef::as_ref) + )) { + Ok(proof) => proof, + Err(error) => { log::trace!("remote read child request from {} ({} {} at {:?}) failed with: {}", peer, HexDisplay::from(&request.storage_key), fmt_keys(request.keys.first(), request.keys.last()), request.block, - "invalid child info and type" - ); + error); StorageProof::empty() - }; + } + }; let response = { - let r = api::v1::light::RemoteReadResponse { proof: proof.encode() }; - api::v1::light::response::Response::RemoteReadResponse(r) + let r = schema::v1::light::RemoteReadResponse { proof: proof.encode() }; + schema::v1::light::response::Response::RemoteReadResponse(r) }; - Ok(api::v1::light::Response { response: Some(response) }) + Ok(schema::v1::light::Response { response: Some(response) }) } fn on_remote_header_request ( &mut self , peer: &PeerId - , request: &api::v1::light::RemoteHeaderRequest - ) -> Result + , request: &schema::v1::light::RemoteHeaderRequest + ) -> Result { log::trace!("remote header proof request from {} ({:?})", peer, request.block); @@ -637,18 +675,18 @@ where }; let response = { - let r = api::v1::light::RemoteHeaderResponse { header, proof: proof.encode() }; - api::v1::light::response::Response::RemoteHeaderResponse(r) + let r = schema::v1::light::RemoteHeaderResponse { header, proof: proof.encode() }; + schema::v1::light::response::Response::RemoteHeaderResponse(r) }; - Ok(api::v1::light::Response { response: Some(response) }) + Ok(schema::v1::light::Response { response: Some(response) }) } fn on_remote_changes_request ( &mut self , peer: &PeerId - , request: &api::v1::light::RemoteChangesRequest - ) -> Result + , request: &schema::v1::light::RemoteChangesRequest + ) -> Result { log::trace!("remote changes proof request from {} for key {} ({:?}..{:?})", peer, @@ -665,28 +703,23 @@ where let min = Decode::decode(&mut request.min.as_ref())?; let max = Decode::decode(&mut request.max.as_ref())?; let key = StorageKey(request.key.clone()); - let storage_key = - if request.storage_key.is_empty() { - None - } else { - Some(StorageKey(request.storage_key.clone())) - }; + let storage_key = if request.storage_key.is_empty() { + None + } else { + Some(PrefixedStorageKey::new_ref(&request.storage_key)) + }; - let proof = match self.chain.key_changes_proof(first, last, min, max, storage_key.as_ref(), &key) { + let proof = match self.chain.key_changes_proof(first, last, min, max, storage_key, &key) { Ok(proof) => proof, Err(error) => { log::trace!("remote changes proof request from {} for key {} ({:?}..{:?}) failed with: {}", peer, - if let Some(sk) = storage_key { - format!("{} : {}", HexDisplay::from(&sk.0), HexDisplay::from(&key.0)) - } else { - HexDisplay::from(&key.0).to_string() - }, + format!("{} : {}", HexDisplay::from(&request.storage_key), HexDisplay::from(&key.0)), request.first, request.last, error); - fetcher::ChangesProof:: { + light::ChangesProof:: { max_block: Zero::zero(), proof: Vec::new(), roots: BTreeMap::new(), @@ -696,18 +729,18 @@ where }; let response = { - let r = api::v1::light::RemoteChangesResponse { + let r = schema::v1::light::RemoteChangesResponse { max: proof.max_block.encode(), proof: proof.proof, roots: proof.roots.into_iter() - .map(|(k, v)| api::v1::light::Pair { fst: k.encode(), snd: v.encode() }) + .map(|(k, v)| schema::v1::light::Pair { fst: k.encode(), snd: v.encode() }) .collect(), roots_proof: proof.roots_proof.encode(), }; - api::v1::light::response::Response::RemoteChangesResponse(r) + schema::v1::light::response::Response::RemoteChangesResponse(r) }; - Ok(api::v1::light::Response { response: Some(response) }) + Ok(schema::v1::light::Response { response: Some(response) }) } } @@ -723,52 +756,82 @@ where max_request_size: self.config.max_request_size, protocol: self.config.light_protocol.clone(), }; - OneShotHandler::new(SubstreamProtocol::new(p), self.config.inactivity_timeout) + let mut cfg = OneShotHandlerConfig::default(); + cfg.keep_alive_timeout = self.config.inactivity_timeout; + OneShotHandler::new(SubstreamProtocol::new(p), cfg) } fn addresses_of_peer(&mut self, peer: &PeerId) -> Vec { self.peers.get(peer) - .map(|info| vec![info.address.clone()]) + .map(|info| info.connections.iter().map(|(_, a)| a.clone()).collect()) .unwrap_or_default() } - fn inject_connected(&mut self, peer: PeerId, info: ConnectedPoint) { + fn inject_connected(&mut self, peer: &PeerId) { + } + + fn inject_connection_established(&mut self, peer: &PeerId, conn: &ConnectionId, info: &ConnectedPoint) { let peer_address = match info { - ConnectedPoint::Listener { send_back_addr, .. } => send_back_addr, - ConnectedPoint::Dialer { address } => address + ConnectedPoint::Listener { send_back_addr, .. } => send_back_addr.clone(), + ConnectedPoint::Dialer { address } => address.clone() }; log::trace!("peer {} connected with address {}", peer, peer_address); - let info = PeerInfo { - address: peer_address, - best_block: None, - status: PeerStatus::Idle, - }; - - self.peers.insert(peer, info); + let entry = self.peers.entry(peer.clone()).or_default(); + entry.connections.push((*conn, peer_address)); } - fn inject_disconnected(&mut self, peer: &PeerId, _: ConnectedPoint) { + fn inject_disconnected(&mut self, peer: &PeerId) { log::trace!("peer {} disconnected", peer); self.remove_peer(peer) } - fn inject_node_event(&mut self, peer: PeerId, event: Event) { + fn inject_connection_closed(&mut self, peer: &PeerId, conn: &ConnectionId, info: &ConnectedPoint) { + let peer_address = match info { + ConnectedPoint::Listener { send_back_addr, .. } => send_back_addr, + ConnectedPoint::Dialer { address } => address + }; + + log::trace!("connection to peer {} closed: {}", peer, peer_address); + + if let Some(info) = self.peers.get_mut(peer) { + info.connections.retain(|(c, _)| c != conn) + } + + // Add any outstanding requests on the closed connection back to the + // pending requests. + if let Some(id) = self.outstanding.iter() + .find(|(_, rw)| &rw.peer == peer && rw.connection == Some(*conn)) // (*) + .map(|(id, _)| *id) + { + let rw = self.outstanding.remove(&id).expect("by (*)"); + let rw = RequestWrapper { + timestamp: rw.timestamp, + retries: rw.retries, + request: rw.request, + peer: (), // need to find another peer + connection: None, + }; + self.pending_requests.push_back(rw); + } + } + + fn inject_event(&mut self, peer: PeerId, conn: ConnectionId, event: Event) { match event { // An incoming request from remote has been received. Event::Request(request, mut stream) => { log::trace!("incoming request from {}", peer); let result = match &request.request { - Some(api::v1::light::request::Request::RemoteCallRequest(r)) => + Some(schema::v1::light::request::Request::RemoteCallRequest(r)) => self.on_remote_call_request(&peer, r), - Some(api::v1::light::request::Request::RemoteReadRequest(r)) => + Some(schema::v1::light::request::Request::RemoteReadRequest(r)) => self.on_remote_read_request(&peer, r), - Some(api::v1::light::request::Request::RemoteHeaderRequest(r)) => + Some(schema::v1::light::request::Request::RemoteHeaderRequest(r)) => self.on_remote_header_request(&peer, r), - Some(api::v1::light::request::Request::RemoteReadChildRequest(r)) => + Some(schema::v1::light::request::Request::RemoteReadChildRequest(r)) => self.on_remote_read_child_request(&peer, r), - Some(api::v1::light::request::Request::RemoteChangesRequest(r)) => + Some(schema::v1::light::request::Request::RemoteChangesRequest(r)) => self.on_remote_changes_request(&peer, r), None => { log::debug!("ignoring request without request data from peer {}", peer); @@ -800,9 +863,10 @@ where // A response to one of our own requests has been received. Event::Response(id, response) => { if let Some(request) = self.outstanding.remove(&id) { - // We first just check if the response originates from the expected peer. + // We first just check if the response originates from the expected peer + // and connection. if request.peer != peer { - log::debug!("was expecting response from {} instead of {}", request.peer, peer); + log::debug!("Expected response from {} instead of {}.", request.peer, peer); self.outstanding.insert(id, request); self.remove_peer(&peer); self.peerset.report_peer(peer, ReputationChange::new_fatal("response from unexpected peer")); @@ -834,6 +898,7 @@ where retries: request.retries, request: request.request, peer: (), + connection: None, }; self.pending_requests.push_back(rw); } @@ -847,6 +912,7 @@ where retries: request.retries - 1, request: request.request, peer: (), + connection: None, }; self.pending_requests.push_back(rw) } else { @@ -886,54 +952,56 @@ where request.timestamp = Instant::now(); request.retries -= 1 } - let number = required_block(&request.request); - let available_peer = { - let p = self.idle_peers_with_block(number).next(); - if p.is_none() { - self.idle_peers_with_unknown_block().next() - } else { - p + + + match self.prepare_request(request) { + Err(request) => { + self.pending_requests.push_front(request); + log::debug!("no peer available to send request to"); + break } - }; - if let Some(peer) = available_peer { - let buf = match serialize_request(&request.request) { - Ok(b) => b, - Err(e) => { - log::debug!("failed to serialize request: {}", e); - send_reply(Err(ClientError::RemoteFetchFailed), request.request); - continue; + Ok((peer, request)) => { + let request_bytes = match serialize_request(&request.request) { + Ok(bytes) => bytes, + Err(error) => { + log::debug!("failed to serialize request: {}", error); + send_reply(Err(ClientError::RemoteFetchFailed), request.request); + continue + } + }; + + let (expected, protocol) = match request.request { + Request::Body { .. } => + (ExpectedResponseTy::Block, self.config.block_protocol.clone()), + _ => + (ExpectedResponseTy::Light, self.config.light_protocol.clone()), + }; + + let peer_id = peer.clone(); + let handler = request.connection.map_or(NotifyHandler::Any, NotifyHandler::One); + + let request_id = self.next_request_id(); + if let Some(p) = self.peers.get_mut(&peer) { + p.status = PeerStatus::BusyWith(request_id); } - }; + self.outstanding.insert(request_id, request); + + let event = OutboundProtocol { + request_id, + request: request_bytes, + expected, + max_response_size: self.config.max_response_size, + protocol, + }; - let id = self.next_request_id(); - log::trace!("sending request {} to peer {}", id, peer); - let protocol = OutboundProtocol { - request: buf, - request_id: id, - expected: match request.request { - Request::Body { .. } => ExpectedResponseTy::Block, - _ => ExpectedResponseTy::Light, - }, - max_response_size: self.config.max_response_size, - protocol: match request.request { - Request::Body { .. } => self.config.block_protocol.clone(), - _ => self.config.light_protocol.clone(), - }, - }; - self.peers.get_mut(&peer).map(|info| info.status = PeerStatus::BusyWith(id)); - let rw = RequestWrapper { - timestamp: request.timestamp, - retries: request.retries, - request: request.request, - peer: peer.clone(), - }; - self.outstanding.insert(id, rw); - return Poll::Ready(NetworkBehaviourAction::SendEvent { peer_id: peer, event: protocol }) + log::trace!("sending request {} to peer {}", request_id, peer_id); - } else { - self.pending_requests.push_front(request); - log::debug!("no peer available to send request to"); - break + return Poll::Ready(NetworkBehaviourAction::NotifyHandler { + peer_id, + handler, + event, + }) + } } } @@ -959,6 +1027,7 @@ where retries: rw.retries - 1, request: rw.request, peer: (), + connection: None, }; self.pending_requests.push_back(rw) } @@ -994,60 +1063,59 @@ fn retries(request: &Request) -> usize { fn serialize_request(request: &Request) -> Result, prost::EncodeError> { let request = match request { Request::Body { request, .. } => { - let rq = api::v1::BlockRequest { - fields: u32::from(BlockAttributes::BODY.bits()), - from_block: Some(api::v1::block_request::FromBlock::Hash(request.header.hash().encode())), - to_block: Vec::new(), - direction: api::v1::Direction::Ascending as i32, - max_blocks: 1, - }; + let rq = build_protobuf_block_request::<_, NumberFor>( + BlockAttributes::BODY, + FromBlock::Hash(request.header.hash()), + None, + Direction::Ascending, + Some(1), + ); let mut buf = Vec::with_capacity(rq.encoded_len()); rq.encode(&mut buf)?; return Ok(buf); } Request::Header { request, .. } => { - let r = api::v1::light::RemoteHeaderRequest { block: request.block.encode() }; - api::v1::light::request::Request::RemoteHeaderRequest(r) + let r = schema::v1::light::RemoteHeaderRequest { block: request.block.encode() }; + schema::v1::light::request::Request::RemoteHeaderRequest(r) } Request::Read { request, .. } => { - let r = api::v1::light::RemoteReadRequest { + let r = schema::v1::light::RemoteReadRequest { block: request.block.encode(), keys: request.keys.clone(), }; - api::v1::light::request::Request::RemoteReadRequest(r) + schema::v1::light::request::Request::RemoteReadRequest(r) } Request::ReadChild { request, .. } => { - let r = api::v1::light::RemoteReadChildRequest { + let r = schema::v1::light::RemoteReadChildRequest { block: request.block.encode(), - storage_key: request.storage_key.clone(), - child_type: request.child_type.clone(), - child_info: request.child_info.clone(), + storage_key: request.storage_key.clone().into_inner(), keys: request.keys.clone(), }; - api::v1::light::request::Request::RemoteReadChildRequest(r) + schema::v1::light::request::Request::RemoteReadChildRequest(r) } Request::Call { request, .. } => { - let r = api::v1::light::RemoteCallRequest { + let r = schema::v1::light::RemoteCallRequest { block: request.block.encode(), method: request.method.clone(), data: request.call_data.clone(), }; - api::v1::light::request::Request::RemoteCallRequest(r) + schema::v1::light::request::Request::RemoteCallRequest(r) } Request::Changes { request, .. } => { - let r = api::v1::light::RemoteChangesRequest { + let r = schema::v1::light::RemoteChangesRequest { first: request.first_block.1.encode(), last: request.last_block.1.encode(), min: request.tries_roots.1.encode(), max: request.max_block.1.encode(), - storage_key: request.storage_key.clone().unwrap_or_default(), + storage_key: request.storage_key.clone().map(|s| s.into_inner()) + .unwrap_or_default(), key: request.key.clone(), }; - api::v1::light::request::Request::RemoteChangesRequest(r) + schema::v1::light::request::Request::RemoteChangesRequest(r) } }; - let rq = api::v1::light::Request { request: Some(request) }; + let rq = schema::v1::light::Request { request: Some(request) }; let mut buf = Vec::with_capacity(rq.encoded_len()); rq.encode(&mut buf)?; Ok(buf) @@ -1095,18 +1163,18 @@ fn send_reply(result: Result, ClientError>, request: Request< #[derive(Debug)] pub enum Event { /// Incoming request from remote and substream to use for the response. - Request(api::v1::light::Request, T), + Request(schema::v1::light::Request, T), /// Incoming response from remote. - Response(u64, Response), + Response(RequestId, Response), } /// Incoming response from remote. #[derive(Debug, Clone)] pub enum Response { /// Incoming light response from remote. - Light(api::v1::light::Response), + Light(schema::v1::light::Response), /// Incoming block response from remote. - Block(api::v1::BlockResponse), + Block(schema::v1::BlockResponse), } /// Substream upgrade protocol. @@ -1140,7 +1208,7 @@ where fn upgrade_inbound(self, mut s: T, _: Self::Info) -> Self::Future { let future = async move { let vec = read_one(&mut s, self.max_request_size).await?; - match api::v1::light::Request::decode(&vec[..]) { + match schema::v1::light::Request::decode(&vec[..]) { Ok(r) => Ok(Event::Request(r, s)), Err(e) => Err(ReadOneError::Io(io::Error::new(io::ErrorKind::Other, e))) } @@ -1157,7 +1225,7 @@ pub struct OutboundProtocol { /// The serialized protobuf request. request: Vec, /// Local identifier for the request. Used to associate it with a response. - request_id: u64, + request_id: RequestId, /// Kind of response expected for this request. expected: ExpectedResponseTy, /// The max. response length in bytes. @@ -1197,14 +1265,14 @@ where match self.expected { ExpectedResponseTy::Light => { - api::v1::light::Response::decode(&vec[..]) + schema::v1::light::Response::decode(&vec[..]) .map(|r| Event::Response(self.request_id, Response::Light(r))) .map_err(|e| { ReadOneError::Io(io::Error::new(io::ErrorKind::Other, e)) }) }, ExpectedResponseTy::Block => { - api::v1::BlockResponse::decode(&vec[..]) + schema::v1::BlockResponse::decode(&vec[..]) .map(|r| Event::Response(self.request_id, Response::Block(r))) .map_err(|e| { ReadOneError::Io(io::Error::new(io::ErrorKind::Other, e)) @@ -1230,13 +1298,14 @@ fn fmt_keys(first: Option<&Vec>, last: Option<&Vec>) -> String { #[cfg(test)] mod tests { + use super::*; use async_std::task; use assert_matches::assert_matches; use codec::Encode; use crate::{ chain::Client, config::ProtocolId, - protocol::api, + schema, }; use futures::{channel::oneshot, prelude::*}; use libp2p::{ @@ -1244,6 +1313,7 @@ mod tests { Multiaddr, core::{ ConnectedPoint, + connection::ConnectionId, identity, muxing::{StreamMuxerBox, SubstreamRef}, transport::{Transport, boxed::Boxed, memory::MemoryTransport}, @@ -1253,8 +1323,7 @@ mod tests { swarm::{NetworkBehaviour, NetworkBehaviourAction, PollParameters}, yamux }; - use sc_client_api::StorageProof; - use sc_client::light::fetcher; + use sc_client_api::{StorageProof, RemoteReadChildRequest, FetchChecker}; use sp_blockchain::{Error as ClientError}; use sp_core::storage::ChildInfo; use std::{ @@ -1269,8 +1338,6 @@ mod tests { use super::{Event, LightClientHandler, Request, Response, OutboundProtocol, PeerStatus}; use void::Void; - const CHILD_INFO: ChildInfo<'static> = ChildInfo::new_default(b"foobarbaz"); - type Block = sp_runtime::generic::Block, substrate_test_runtime::Extrinsic>; type Handler = LightClientHandler; type Swarm = libp2p::swarm::Swarm; @@ -1300,12 +1367,12 @@ mod tests { _mark: std::marker::PhantomData } - impl fetcher::FetchChecker for DummyFetchChecker { + impl light::FetchChecker for DummyFetchChecker { fn check_header_proof( &self, - _request: &fetcher::RemoteHeaderRequest, + _request: &RemoteHeaderRequest, header: Option, - _remote_proof: fetcher::StorageProof, + _remote_proof: StorageProof, ) -> Result { match self.ok { true if header.is_some() => Ok(header.unwrap()), @@ -1315,8 +1382,8 @@ mod tests { fn check_read_proof( &self, - request: &fetcher::RemoteReadRequest, - _: fetcher::StorageProof, + request: &RemoteReadRequest, + _: StorageProof, ) -> Result, Option>>, ClientError> { match self.ok { true => Ok(request.keys @@ -1331,8 +1398,8 @@ mod tests { fn check_read_child_proof( &self, - request: &fetcher::RemoteReadChildRequest, - _: fetcher::StorageProof, + request: &RemoteReadChildRequest, + _: StorageProof, ) -> Result, Option>>, ClientError> { match self.ok { true => Ok(request.keys @@ -1347,8 +1414,8 @@ mod tests { fn check_execution_proof( &self, - _: &fetcher::RemoteCallRequest, - _: fetcher::StorageProof, + _: &RemoteCallRequest, + _: StorageProof, ) -> Result, ClientError> { match self.ok { true => Ok(vec![42]), @@ -1358,8 +1425,8 @@ mod tests { fn check_changes_proof( &self, - _: &fetcher::RemoteChangesRequest, - _: fetcher::ChangesProof + _: &RemoteChangesRequest, + _: ChangesProof ) -> Result, u32)>, ClientError> { match self.ok { true => Ok(vec![(100.into(), 2)]), @@ -1369,7 +1436,7 @@ mod tests { fn check_body_proof( &self, - _: &fetcher::RemoteBodyRequest, + _: &RemoteBodyRequest, body: Vec ) -> Result, ClientError> { match self.ok { @@ -1457,10 +1524,12 @@ mod tests { let pset = peerset(); let mut behaviour = make_behaviour(true, pset.1, make_config()); - behaviour.inject_connected(peer.clone(), empty_dialer()); + behaviour.inject_connection_established(&peer, &ConnectionId::new(1), &empty_dialer()); + behaviour.inject_connected(&peer); assert_eq!(1, behaviour.peers.len()); - behaviour.inject_disconnected(&peer, empty_dialer()); + behaviour.inject_connection_closed(&peer, &ConnectionId::new(1), &empty_dialer()); + behaviour.inject_disconnected(&peer); assert_eq!(0, behaviour.peers.len()) } @@ -1471,8 +1540,10 @@ mod tests { let pset = peerset(); let mut behaviour = make_behaviour(true, pset.1, make_config()); - behaviour.inject_connected(peer0.clone(), empty_dialer()); - behaviour.inject_connected(peer1.clone(), empty_dialer()); + behaviour.inject_connection_established(&peer0, &ConnectionId::new(1), &empty_dialer()); + behaviour.inject_connected(&peer0); + behaviour.inject_connection_established(&peer1, &ConnectionId::new(2), &empty_dialer()); + behaviour.inject_connected(&peer1); // We now know about two peers. assert_eq!(HashSet::from_iter(&[peer0.clone(), peer1.clone()]), behaviour.peers.keys().collect::>()); @@ -1483,7 +1554,7 @@ mod tests { // Issue our first request! let chan = oneshot::channel(); - let request = fetcher::RemoteCallRequest { + let request = light::RemoteCallRequest { block: Default::default(), header: dummy_header(), method: "test".into(), @@ -1494,7 +1565,7 @@ mod tests { assert_eq!(1, behaviour.pending_requests.len()); // The behaviour should now attempt to send the request. - assert_matches!(poll(&mut behaviour), Poll::Ready(NetworkBehaviourAction::SendEvent { peer_id, .. }) => { + assert_matches!(poll(&mut behaviour), Poll::Ready(NetworkBehaviourAction::NotifyHandler { peer_id, .. }) => { assert!(peer_id == peer0 || peer_id == peer1) }); @@ -1534,11 +1605,13 @@ mod tests { let mut behaviour = make_behaviour(false, pset.1, make_config()); // ^--- Making sure the response data check fails. - behaviour.inject_connected(peer.clone(), empty_dialer()); + let conn = ConnectionId::new(1); + behaviour.inject_connection_established(&peer, &conn, &empty_dialer()); + behaviour.inject_connected(&peer); assert_eq!(1, behaviour.peers.len()); let chan = oneshot::channel(); - let request = fetcher::RemoteCallRequest { + let request = light::RemoteCallRequest { block: Default::default(), header: dummy_header(), method: "test".into(), @@ -1556,13 +1629,13 @@ mod tests { let request_id = *behaviour.outstanding.keys().next().unwrap(); let response = { - let r = api::v1::light::RemoteCallResponse { proof: empty_proof() }; - api::v1::light::Response { - response: Some(api::v1::light::response::Response::RemoteCallResponse(r)), + let r = schema::v1::light::RemoteCallResponse { proof: empty_proof() }; + schema::v1::light::Response { + response: Some(schema::v1::light::response::Response::RemoteCallResponse(r)), } }; - behaviour.inject_node_event(peer.clone(), Event::Response(request_id, Response::Light(response))); + behaviour.inject_event(peer.clone(), conn, Event::Response(request_id, Response::Light(response))); assert!(behaviour.peers.is_empty()); poll(&mut behaviour); // More progress @@ -1578,20 +1651,22 @@ mod tests { let pset = peerset(); let mut behaviour = make_behaviour(true, pset.1, make_config()); - behaviour.inject_connected(peer.clone(), empty_dialer()); + let conn = ConnectionId::new(1); + behaviour.inject_connection_established(&peer, &conn, &empty_dialer()); + behaviour.inject_connected(&peer); assert_eq!(1, behaviour.peers.len()); assert_eq!(0, behaviour.pending_requests.len()); assert_eq!(0, behaviour.outstanding.len()); // Some unsolicited response let response = { - let r = api::v1::light::RemoteCallResponse { proof: empty_proof() }; - api::v1::light::Response { - response: Some(api::v1::light::response::Response::RemoteCallResponse(r)), + let r = schema::v1::light::RemoteCallResponse { proof: empty_proof() }; + schema::v1::light::Response { + response: Some(schema::v1::light::response::Response::RemoteCallResponse(r)), } }; - behaviour.inject_node_event(peer.clone(), Event::Response(2347895932, Response::Light(response))); + behaviour.inject_event(peer.clone(), conn, Event::Response(2347895932, Response::Light(response))); assert!(behaviour.peers.is_empty()); poll(&mut behaviour); @@ -1605,11 +1680,13 @@ mod tests { let pset = peerset(); let mut behaviour = make_behaviour(true, pset.1, make_config()); - behaviour.inject_connected(peer.clone(), empty_dialer()); + let conn = ConnectionId::new(1); + behaviour.inject_connection_established(&peer, &conn, &empty_dialer()); + behaviour.inject_connected(&peer); assert_eq!(1, behaviour.peers.len()); let chan = oneshot::channel(); - let request = fetcher::RemoteCallRequest { + let request = light::RemoteCallRequest { block: Default::default(), header: dummy_header(), method: "test".into(), @@ -1627,13 +1704,13 @@ mod tests { let request_id = *behaviour.outstanding.keys().next().unwrap(); let response = { - let r = api::v1::light::RemoteReadResponse { proof: empty_proof() }; // Not a RemoteCallResponse! - api::v1::light::Response { - response: Some(api::v1::light::response::Response::RemoteReadResponse(r)), + let r = schema::v1::light::RemoteReadResponse { proof: empty_proof() }; // Not a RemoteCallResponse! + schema::v1::light::Response { + response: Some(schema::v1::light::response::Response::RemoteReadResponse(r)), } }; - behaviour.inject_node_event(peer.clone(), Event::Response(request_id, Response::Light(response))); + behaviour.inject_event(peer.clone(), conn, Event::Response(request_id, Response::Light(response))); assert!(behaviour.peers.is_empty()); poll(&mut behaviour); // More progress @@ -1653,14 +1730,22 @@ mod tests { let mut behaviour = make_behaviour(false, pset.1, make_config()); // ^--- Making sure the response data check fails. - behaviour.inject_connected(peer1.clone(), empty_dialer()); - behaviour.inject_connected(peer2.clone(), empty_dialer()); - behaviour.inject_connected(peer3.clone(), empty_dialer()); - behaviour.inject_connected(peer4.clone(), empty_dialer()); + let conn1 = ConnectionId::new(1); + behaviour.inject_connection_established(&peer1, &conn1, &empty_dialer()); + behaviour.inject_connected(&peer1); + let conn2 = ConnectionId::new(2); + behaviour.inject_connection_established(&peer2, &conn2, &empty_dialer()); + behaviour.inject_connected(&peer2); + let conn3 = ConnectionId::new(3); + behaviour.inject_connection_established(&peer3, &conn3, &empty_dialer()); + behaviour.inject_connected(&peer3); + let conn4 = ConnectionId::new(3); + behaviour.inject_connection_established(&peer4, &conn4, &empty_dialer()); + behaviour.inject_connected(&peer4); assert_eq!(4, behaviour.peers.len()); let mut chan = oneshot::channel(); - let request = fetcher::RemoteCallRequest { + let request = light::RemoteCallRequest { block: Default::default(), header: dummy_header(), method: "test".into(), @@ -1671,34 +1756,35 @@ mod tests { assert_eq!(1, behaviour.pending_requests.len()); assert_eq!(0, behaviour.outstanding.len()); - assert_matches!(poll(&mut behaviour), Poll::Ready(NetworkBehaviourAction::SendEvent { .. })); + assert_matches!(poll(&mut behaviour), Poll::Ready(NetworkBehaviourAction::NotifyHandler { .. })); assert_eq!(0, behaviour.pending_requests.len()); assert_eq!(1, behaviour.outstanding.len()); - for _ in 0 .. 3 { + for i in 1 ..= 3 { // Construct an invalid response let request_id = *behaviour.outstanding.keys().next().unwrap(); let responding_peer = behaviour.outstanding.values().next().unwrap().peer.clone(); let response = { - let r = api::v1::light::RemoteCallResponse { proof: empty_proof() }; - api::v1::light::Response { - response: Some(api::v1::light::response::Response::RemoteCallResponse(r)) + let r = schema::v1::light::RemoteCallResponse { proof: empty_proof() }; + schema::v1::light::Response { + response: Some(schema::v1::light::response::Response::RemoteCallResponse(r)) } }; - behaviour.inject_node_event(responding_peer, Event::Response(request_id, Response::Light(response.clone()))); - assert_matches!(poll(&mut behaviour), Poll::Ready(NetworkBehaviourAction::SendEvent { .. })); + let conn = ConnectionId::new(i); + behaviour.inject_event(responding_peer, conn, Event::Response(request_id, Response::Light(response.clone()))); + assert_matches!(poll(&mut behaviour), Poll::Ready(NetworkBehaviourAction::NotifyHandler { .. })); assert_matches!(chan.1.try_recv(), Ok(None)) } // Final invalid response let request_id = *behaviour.outstanding.keys().next().unwrap(); let responding_peer = behaviour.outstanding.values().next().unwrap().peer.clone(); let response = { - let r = api::v1::light::RemoteCallResponse { proof: empty_proof() }; - api::v1::light::Response { - response: Some(api::v1::light::response::Response::RemoteCallResponse(r)), + let r = schema::v1::light::RemoteCallResponse { proof: empty_proof() }; + schema::v1::light::Response { + response: Some(schema::v1::light::response::Response::RemoteCallResponse(r)), } }; - behaviour.inject_node_event(responding_peer, Event::Response(request_id, Response::Light(response))); + behaviour.inject_event(responding_peer, conn4, Event::Response(request_id, Response::Light(response))); assert_matches!(poll(&mut behaviour), Poll::Pending); assert_matches!(chan.1.try_recv(), Ok(Some(Err(ClientError::RemoteFetchFailed)))) } @@ -1708,47 +1794,49 @@ mod tests { let pset = peerset(); let mut behaviour = make_behaviour(true, pset.1, make_config()); - behaviour.inject_connected(peer.clone(), empty_dialer()); + let conn = ConnectionId::new(1); + behaviour.inject_connection_established(&peer, &conn, &empty_dialer()); + behaviour.inject_connected(&peer); assert_eq!(1, behaviour.peers.len()); let response = match request { Request::Body { .. } => unimplemented!(), Request::Header{..} => { - let r = api::v1::light::RemoteHeaderResponse { + let r = schema::v1::light::RemoteHeaderResponse { header: dummy_header().encode(), proof: empty_proof() }; - api::v1::light::Response { - response: Some(api::v1::light::response::Response::RemoteHeaderResponse(r)), + schema::v1::light::Response { + response: Some(schema::v1::light::response::Response::RemoteHeaderResponse(r)), } } Request::Read{..} => { - let r = api::v1::light::RemoteReadResponse { proof: empty_proof() }; - api::v1::light::Response { - response: Some(api::v1::light::response::Response::RemoteReadResponse(r)), + let r = schema::v1::light::RemoteReadResponse { proof: empty_proof() }; + schema::v1::light::Response { + response: Some(schema::v1::light::response::Response::RemoteReadResponse(r)), } } Request::ReadChild{..} => { - let r = api::v1::light::RemoteReadResponse { proof: empty_proof() }; - api::v1::light::Response { - response: Some(api::v1::light::response::Response::RemoteReadResponse(r)), + let r = schema::v1::light::RemoteReadResponse { proof: empty_proof() }; + schema::v1::light::Response { + response: Some(schema::v1::light::response::Response::RemoteReadResponse(r)), } } Request::Call{..} => { - let r = api::v1::light::RemoteCallResponse { proof: empty_proof() }; - api::v1::light::Response { - response: Some(api::v1::light::response::Response::RemoteCallResponse(r)), + let r = schema::v1::light::RemoteCallResponse { proof: empty_proof() }; + schema::v1::light::Response { + response: Some(schema::v1::light::response::Response::RemoteCallResponse(r)), } } Request::Changes{..} => { - let r = api::v1::light::RemoteChangesResponse { + let r = schema::v1::light::RemoteChangesResponse { max: iter::repeat(1).take(32).collect(), proof: Vec::new(), roots: Vec::new(), roots_proof: empty_proof() }; - api::v1::light::Response { - response: Some(api::v1::light::response::Response::RemoteChangesResponse(r)), + schema::v1::light::Response { + response: Some(schema::v1::light::response::Response::RemoteChangesResponse(r)), } } }; @@ -1757,12 +1845,12 @@ mod tests { assert_eq!(1, behaviour.pending_requests.len()); assert_eq!(0, behaviour.outstanding.len()); - assert_matches!(poll(&mut behaviour), Poll::Ready(NetworkBehaviourAction::SendEvent { .. })); + assert_matches!(poll(&mut behaviour), Poll::Ready(NetworkBehaviourAction::NotifyHandler { .. })); assert_eq!(0, behaviour.pending_requests.len()); assert_eq!(1, behaviour.outstanding.len()); assert_eq!(1, *behaviour.outstanding.keys().next().unwrap()); - behaviour.inject_node_event(peer.clone(), Event::Response(1, Response::Light(response))); + behaviour.inject_event(peer.clone(), conn, Event::Response(1, Response::Light(response))); poll(&mut behaviour); @@ -1773,7 +1861,7 @@ mod tests { #[test] fn receives_remote_call_response() { let mut chan = oneshot::channel(); - let request = fetcher::RemoteCallRequest { + let request = light::RemoteCallRequest { block: Default::default(), header: dummy_header(), method: "test".into(), @@ -1787,7 +1875,7 @@ mod tests { #[test] fn receives_remote_read_response() { let mut chan = oneshot::channel(); - let request = fetcher::RemoteReadRequest { + let request = light::RemoteReadRequest { header: dummy_header(), block: Default::default(), keys: vec![b":key".to_vec()], @@ -1799,15 +1887,13 @@ mod tests { #[test] fn receives_remote_read_child_response() { - let info = CHILD_INFO.info(); let mut chan = oneshot::channel(); - let request = fetcher::RemoteReadChildRequest { + let child_info = ChildInfo::new_default(&b":child_storage:default:sub"[..]); + let request = light::RemoteReadChildRequest { header: dummy_header(), block: Default::default(), - storage_key: b":child_storage:sub".to_vec(), + storage_key: child_info.prefixed_storage_key(), keys: vec![b":key".to_vec()], - child_info: info.0.to_vec(), - child_type: info.1, retry_count: None, }; issue_request(Request::ReadChild { request, sender: chan.0 }); @@ -1817,7 +1903,7 @@ mod tests { #[test] fn receives_remote_header_response() { let mut chan = oneshot::channel(); - let request = fetcher::RemoteHeaderRequest { + let request = light::RemoteHeaderRequest { cht_root: Default::default(), block: 1, retry_count: None, @@ -1829,7 +1915,7 @@ mod tests { #[test] fn receives_remote_changes_response() { let mut chan = oneshot::channel(); - let request = fetcher::RemoteChangesRequest { + let request = light::RemoteChangesRequest { changes_trie_configs: vec![sp_core::ChangesTrieConfigurationRange { zero: (0, Default::default()), end: None, @@ -1874,7 +1960,7 @@ mod tests { #[test] fn send_receive_call() { let chan = oneshot::channel(); - let request = fetcher::RemoteCallRequest { + let request = light::RemoteCallRequest { block: Default::default(), header: dummy_header(), method: "test".into(), @@ -1889,7 +1975,7 @@ mod tests { #[test] fn send_receive_read() { let chan = oneshot::channel(); - let request = fetcher::RemoteReadRequest { + let request = light::RemoteReadRequest { header: dummy_header(), block: Default::default(), keys: vec![b":key".to_vec()], @@ -1902,15 +1988,13 @@ mod tests { #[test] fn send_receive_read_child() { - let info = CHILD_INFO.info(); let chan = oneshot::channel(); - let request = fetcher::RemoteReadChildRequest { + let child_info = ChildInfo::new_default(&b":child_storage:default:sub"[..]); + let request = light::RemoteReadChildRequest { header: dummy_header(), block: Default::default(), - storage_key: b":child_storage:sub".to_vec(), + storage_key: child_info.prefixed_storage_key(), keys: vec![b":key".to_vec()], - child_info: info.0.to_vec(), - child_type: info.1, retry_count: None, }; send_receive(Request::ReadChild { request, sender: chan.0 }); @@ -1922,7 +2006,7 @@ mod tests { fn send_receive_header() { let _ = env_logger::try_init(); let chan = oneshot::channel(); - let request = fetcher::RemoteHeaderRequest { + let request = light::RemoteHeaderRequest { cht_root: Default::default(), block: 1, retry_count: None, @@ -1935,7 +2019,7 @@ mod tests { #[test] fn send_receive_changes() { let chan = oneshot::channel(); - let request = fetcher::RemoteChangesRequest { + let request = light::RemoteChangesRequest { changes_trie_configs: vec![sp_core::ChangesTrieConfigurationRange { zero: (0, Default::default()), end: None, @@ -1953,4 +2037,22 @@ mod tests { assert_eq!(vec![(100, 2)], task::block_on(chan.1).unwrap().unwrap()); // ^--- from `DummyFetchChecker::check_changes_proof` } + + #[test] + fn body_request_fields_encoded_properly() { + let (sender, _) = oneshot::channel(); + let serialized_request = serialize_request::(&Request::Body { + request: RemoteBodyRequest { + header: dummy_header(), + retry_count: None, + }, + sender, + }).unwrap(); + let deserialized_request = schema::v1::BlockRequest::decode(&serialized_request[..]).unwrap(); + assert!( + BlockAttributes::from_be_u32(deserialized_request.fields) + .unwrap() + .contains(BlockAttributes::BODY) + ); + } } diff --git a/client/network/src/network_state.rs b/client/network/src/network_state.rs index 00d53976ae8fc8960e9045b1dbab7d1621429f26..970a63faed4ea7ac8167bb8b4d987380f39f3861 100644 --- a/client/network/src/network_state.rs +++ b/client/network/src/network_state.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Information about the networking, for diagnostic purposes. //! diff --git a/client/network/src/on_demand_layer.rs b/client/network/src/on_demand_layer.rs index d881bf6fe243a7d5607fa9d3e0afba8760b517a5..084172ee57c4f002c66c27e22bbe6dfc42f750fa 100644 --- a/client/network/src/on_demand_layer.rs +++ b/client/network/src/on_demand_layer.rs @@ -1,22 +1,24 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! On-demand requests service. -use crate::protocol::light_client_handler; +use crate::light_client_handler; use futures::{channel::oneshot, prelude::*}; use parking_lot::Mutex; @@ -219,7 +221,7 @@ impl Future for RemoteResponse { fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { match self.receiver.poll_unpin(cx) { Poll::Ready(Ok(res)) => Poll::Ready(res), - Poll::Ready(Err(_)) => Poll::Ready(Err(From::from(ClientError::RemoteFetchCancelled))), + Poll::Ready(Err(_)) => Poll::Ready(Err(ClientError::RemoteFetchCancelled)), Poll::Pending => Poll::Pending, } } diff --git a/client/network/src/debug_info.rs b/client/network/src/peer_info.rs similarity index 75% rename from client/network/src/debug_info.rs rename to client/network/src/peer_info.rs index 17fb622f7cd3cab44f3b17ab508d7f1a3b258882..e69ad2b17e59c7f856f1e1e4b73be88572519936 100644 --- a/client/network/src/debug_info.rs +++ b/client/network/src/peer_info.rs @@ -17,14 +17,15 @@ use fnv::FnvHashMap; use futures::prelude::*; use libp2p::Multiaddr; -use libp2p::core::nodes::listeners::ListenerId; +use libp2p::core::connection::{ConnectionId, ListenerId}; 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, IdentifyInfo}; use libp2p::ping::{Ping, PingConfig, PingEvent, PingSuccess}; use log::{debug, trace, error}; -use std::error; +use smallvec::SmallVec; +use std::{error, io}; use std::collections::hash_map::Entry; use std::pin::Pin; use std::task::{Context, Poll}; @@ -37,9 +38,8 @@ const CACHE_EXPIRE: Duration = Duration::from_secs(10 * 60); /// Interval at which we perform garbage collection on the node info. const GARBAGE_COLLECT_INTERVAL: Duration = Duration::from_secs(2 * 60); -/// Implementation of `NetworkBehaviour` that holds information about nodes in cache for diagnostic -/// purposes. -pub struct DebugInfoBehaviour { +/// Implementation of `NetworkBehaviour` that holds information about peers in cache. +pub struct PeerInfoBehaviour { /// Periodically ping nodes, and close the connection if it's unresponsive. ping: Ping, /// Periodically identifies the remote and responds to incoming requests. @@ -56,26 +56,39 @@ struct NodeInfo { /// When we will remove the entry about this node from the list, or `None` if we're connected /// to the node. info_expire: Option, - /// How we're connected to the node. - endpoint: ConnectedPoint, + /// Non-empty list of connected endpoints, one per connection. + endpoints: SmallVec<[ConnectedPoint; crate::MAX_CONNECTIONS_PER_PEER]>, /// Version reported by the remote, or `None` if unknown. client_version: Option, /// Latest ping time with this node. latest_ping: Option, } -impl DebugInfoBehaviour { - /// Builds a new `DebugInfoBehaviour`. +impl NodeInfo { + fn new(endpoint: ConnectedPoint) -> Self { + let mut endpoints = SmallVec::new(); + endpoints.push(endpoint); + NodeInfo { + info_expire: None, + endpoints, + client_version: None, + latest_ping: None, + } + } +} + +impl PeerInfoBehaviour { + /// Builds a new `PeerInfoBehaviour`. pub fn new( user_agent: String, local_public_key: PublicKey, ) -> Self { let identify = { let proto_version = "/substrate/1.0".to_string(); - Identify::new(proto_version, user_agent, local_public_key.clone()) + Identify::new(proto_version, user_agent, local_public_key) }; - DebugInfoBehaviour { + PeerInfoBehaviour { ping: Ping::new(PingConfig::new()), identify, nodes_info: FnvHashMap::default(), @@ -121,9 +134,9 @@ impl DebugInfoBehaviour { pub struct Node<'a>(&'a NodeInfo); impl<'a> Node<'a> { - /// Returns the endpoint we are connected to or were last connected to. + /// Returns the endpoint of an established connection to the peer. pub fn endpoint(&self) -> &'a ConnectedPoint { - &self.0.endpoint + &self.0.endpoints[0] // `endpoints` are non-empty by definition } /// Returns the latest version information we know of. @@ -140,8 +153,8 @@ impl<'a> Node<'a> { /// Event that can be emitted by the behaviour. #[derive(Debug)] -pub enum DebugInfoEvent { - /// We have obtained debug information from a peer, including the addresses it is listening +pub enum PeerInfoEvent { + /// We have obtained identity information from a peer, including the addresses it is listening /// on. Identified { /// Id of the peer that has been identified. @@ -151,12 +164,12 @@ pub enum DebugInfoEvent { }, } -impl NetworkBehaviour for DebugInfoBehaviour { +impl NetworkBehaviour for PeerInfoBehaviour { type ProtocolsHandler = IntoProtocolsHandlerSelect< ::ProtocolsHandler, ::ProtocolsHandler >; - type OutEvent = DebugInfoEvent; + type OutEvent = PeerInfoEvent; fn new_handler(&mut self) -> Self::ProtocolsHandler { IntoProtocolsHandler::select(self.ping.new_handler(), self.identify.new_handler()) @@ -168,18 +181,17 @@ impl NetworkBehaviour for DebugInfoBehaviour { list } - fn inject_connected(&mut self, peer_id: PeerId, endpoint: ConnectedPoint) { - self.ping.inject_connected(peer_id.clone(), endpoint.clone()); - self.identify.inject_connected(peer_id.clone(), endpoint.clone()); + fn inject_connected(&mut self, peer_id: &PeerId) { + self.ping.inject_connected(peer_id); + self.identify.inject_connected(peer_id); + } - match self.nodes_info.entry(peer_id) { + fn inject_connection_established(&mut self, peer_id: &PeerId, conn: &ConnectionId, endpoint: &ConnectedPoint) { + self.ping.inject_connection_established(peer_id, conn, endpoint); + self.identify.inject_connection_established(peer_id, conn, endpoint); + match self.nodes_info.entry(peer_id.clone()) { Entry::Vacant(e) => { - e.insert(NodeInfo { - info_expire: None, - endpoint, - client_version: None, - latest_ping: None, - }); + e.insert(NodeInfo::new(endpoint.clone())); } Entry::Occupied(e) => { let e = e.into_mut(); @@ -188,14 +200,26 @@ impl NetworkBehaviour for DebugInfoBehaviour { e.latest_ping = None; } e.info_expire = None; - e.endpoint = endpoint; + e.endpoints.push(endpoint.clone()); } } } - fn inject_disconnected(&mut self, peer_id: &PeerId, endpoint: ConnectedPoint) { - self.ping.inject_disconnected(peer_id, endpoint.clone()); - self.identify.inject_disconnected(peer_id, endpoint); + fn inject_connection_closed(&mut self, peer_id: &PeerId, conn: &ConnectionId, endpoint: &ConnectedPoint) { + self.ping.inject_connection_closed(peer_id, conn, endpoint); + self.identify.inject_connection_closed(peer_id, conn, endpoint); + + if let Some(entry) = self.nodes_info.get_mut(peer_id) { + entry.endpoints.retain(|ep| ep != endpoint) + } else { + error!(target: "sub-libp2p", + "Unknown connection to {:?} closed: {:?}", peer_id, endpoint); + } + } + + fn inject_disconnected(&mut self, peer_id: &PeerId) { + self.ping.inject_disconnected(peer_id); + self.identify.inject_disconnected(peer_id); if let Some(entry) = self.nodes_info.get_mut(peer_id) { entry.info_expire = Some(Instant::now() + CACHE_EXPIRE); @@ -205,26 +229,15 @@ impl NetworkBehaviour for DebugInfoBehaviour { } } - fn inject_node_event( + fn inject_event( &mut self, peer_id: PeerId, + connection: ConnectionId, event: <::Handler as ProtocolsHandler>::OutEvent ) { match event { - EitherOutput::First(event) => self.ping.inject_node_event(peer_id, event), - EitherOutput::Second(event) => self.identify.inject_node_event(peer_id, event), - } - } - - fn inject_replaced(&mut self, peer_id: PeerId, closed_endpoint: ConnectedPoint, new_endpoint: ConnectedPoint) { - self.ping.inject_replaced(peer_id.clone(), closed_endpoint.clone(), new_endpoint.clone()); - self.identify.inject_replaced(peer_id.clone(), closed_endpoint, new_endpoint.clone()); - - if let Some(entry) = self.nodes_info.get_mut(&peer_id) { - entry.endpoint = new_endpoint; - } else { - error!(target: "sub-libp2p", - "Disconnected from node we were not connected to {:?}", peer_id); + EitherOutput::First(event) => self.ping.inject_event(peer_id, connection, event), + EitherOutput::Second(event) => self.identify.inject_event(peer_id, connection, event), } } @@ -258,9 +271,9 @@ impl NetworkBehaviour for DebugInfoBehaviour { self.identify.inject_listener_error(id, err); } - fn inject_listener_closed(&mut self, id: ListenerId) { - self.ping.inject_listener_closed(id); - self.identify.inject_listener_closed(id); + fn inject_listener_closed(&mut self, id: ListenerId, reason: Result<(), &io::Error>) { + self.ping.inject_listener_closed(id, reason); + self.identify.inject_listener_closed(id, reason); } fn poll( @@ -283,11 +296,12 @@ impl NetworkBehaviour for DebugInfoBehaviour { }, Poll::Ready(NetworkBehaviourAction::DialAddress { address }) => return Poll::Ready(NetworkBehaviourAction::DialAddress { address }), - Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }) => - return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }), - Poll::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }) => - return Poll::Ready(NetworkBehaviourAction::SendEvent { + Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id, condition }) => + return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id, condition }), + Poll::Ready(NetworkBehaviourAction::NotifyHandler { peer_id, handler, event }) => + return Poll::Ready(NetworkBehaviourAction::NotifyHandler { peer_id, + handler, event: EitherOutput::First(event) }), Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }) => @@ -302,7 +316,7 @@ impl NetworkBehaviour for DebugInfoBehaviour { match event { IdentifyEvent::Received { peer_id, info, .. } => { self.handle_identify_report(&peer_id, &info); - let event = DebugInfoEvent::Identified { peer_id, info }; + let event = PeerInfoEvent::Identified { peer_id, info }; return Poll::Ready(NetworkBehaviourAction::GenerateEvent(event)); } IdentifyEvent::Error { peer_id, error } => @@ -312,11 +326,12 @@ impl NetworkBehaviour for DebugInfoBehaviour { }, Poll::Ready(NetworkBehaviourAction::DialAddress { address }) => return Poll::Ready(NetworkBehaviourAction::DialAddress { address }), - Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }) => - return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }), - Poll::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }) => - return Poll::Ready(NetworkBehaviourAction::SendEvent { + Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id, condition }) => + return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id, condition }), + Poll::Ready(NetworkBehaviourAction::NotifyHandler { peer_id, handler, event }) => + return Poll::Ready(NetworkBehaviourAction::NotifyHandler { peer_id, + handler, event: EitherOutput::Second(event) }), Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }) => diff --git a/client/network/src/protocol.rs b/client/network/src/protocol.rs index bfe8226c8d61529d3817699731c3b4cd7fdbd1c3..d98ba8d323b40bf04ffca9d5668a08ae1f714690 100644 --- a/client/network/src/protocol.rs +++ b/client/network/src/protocol.rs @@ -1,30 +1,38 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . + +use crate::{ + ExHashT, + chain::{Client, FinalityProofProvider}, + config::{BoxFinalityProofRequestBuilder, ProtocolId, TransactionPool, TransactionImportFuture, TransactionImport}, + error, + utils::interval +}; -use crate::config::ProtocolId; -use crate::utils::interval; use bytes::{Bytes, BytesMut}; -use futures::prelude::*; +use futures::{prelude::*, stream::FuturesUnordered}; use generic_proto::{GenericProto, GenericProtoOut}; use libp2p::{Multiaddr, PeerId}; -use libp2p::core::{ConnectedPoint, nodes::listeners::ListenerId}; +use libp2p::core::{ConnectedPoint, connection::{ConnectionId, ListenerId}}; use libp2p::swarm::{ProtocolsHandler, IntoProtocolsHandler}; use libp2p::swarm::{NetworkBehaviour, NetworkBehaviourAction, PollParameters}; use sp_core::{ - storage::{StorageKey, ChildInfo}, + storage::{StorageKey, PrefixedStorageKey, ChildInfo, ChildType}, hexdisplay::HexDisplay }; use sp_consensus::{ @@ -40,54 +48,42 @@ use sp_runtime::traits::{ use sp_arithmetic::traits::SaturatedConversion; use message::{BlockAnnounce, Message}; use message::generic::{Message as GenericMessage, ConsensusMessage, Roles}; -use prometheus_endpoint::{Registry, Gauge, GaugeVec, HistogramVec, PrometheusError, Opts, register, U64}; +use prometheus_endpoint::{Registry, Gauge, Counter, GaugeVec, HistogramVec, PrometheusError, Opts, register, U64}; use sync::{ChainSync, SyncState}; -use crate::service::{TransactionPool, ExHashT}; -use crate::config::BoxFinalityProofRequestBuilder; use std::borrow::Cow; -use std::collections::{BTreeMap, HashMap, HashSet, VecDeque}; +use std::collections::{BTreeMap, HashMap, HashSet, VecDeque, hash_map::Entry}; use std::sync::Arc; use std::fmt::Write; -use std::{cmp, num::NonZeroUsize, pin::Pin, task::Poll, time}; +use std::{cmp, io, num::NonZeroUsize, pin::Pin, task::Poll, time}; use log::{log, Level, trace, debug, warn, error}; -use crate::chain::{Client, FinalityProofProvider}; use sc_client_api::{ChangesProof, StorageProof}; -use crate::error; use util::LruHashSet; use wasm_timer::Instant; -// Include sources generated from protobuf definitions. -pub mod api { - pub mod v1 { - include!(concat!(env!("OUT_DIR"), "/api.v1.rs")); - pub mod light { - include!(concat!(env!("OUT_DIR"), "/api.v1.light.rs")); - } - } -} - mod generic_proto; mod util; -pub mod block_requests; pub mod message; pub mod event; -pub mod light_client_handler; pub mod sync; -pub use block_requests::BlockRequests; -pub use light_client_handler::LightClientHandler; +pub use generic_proto::LegacyConnectionKillError; const REQUEST_TIMEOUT_SEC: u64 = 40; /// Interval at which we perform time based maintenance const TICK_TIMEOUT: time::Duration = time::Duration::from_millis(1100); -/// Interval at which we propagate extrinsics; +/// Interval at which we propagate transactions; const PROPAGATE_TIMEOUT: time::Duration = time::Duration::from_millis(2900); /// Maximim number of known block hashes to keep for a peer. const MAX_KNOWN_BLOCKS: usize = 1024; // ~32kb per peer + LruHashSet overhead -/// Maximim number of known extrinsic hashes to keep for a peer. -const MAX_KNOWN_EXTRINSICS: usize = 4096; // ~128kb per peer + overhead +/// Maximim number of known transaction hashes to keep for a peer. +/// +/// This should be approx. 2 blocks full of transactions for the network to function properly. +const MAX_KNOWN_TRANSACTIONS: usize = 10240; // ~300kb per peer + overhead. + +/// Maximim number of transaction validation request we keep at any moment. +const MAX_PENDING_TRANSACTIONS: usize = 8192; /// Current protocol version. pub(crate) const CURRENT_VERSION: u32 = 6; @@ -108,22 +104,27 @@ mod rep { pub const CLOGGED_PEER: Rep = Rep::new(-(1 << 12), "Clogged message queue"); /// Reputation change when a peer doesn't respond in time to our messages. pub const TIMEOUT: Rep = Rep::new(-(1 << 10), "Request timeout"); - /// Reputation change when a peer sends us a status message while we already received one. - pub const UNEXPECTED_STATUS: Rep = Rep::new(-(1 << 20), "Unexpected status message"); /// Reputation change when we are a light client and a peer is behind us. pub const PEER_BEHIND_US_LIGHT: Rep = Rep::new(-(1 << 8), "Useless for a light peer"); - /// Reputation change when a peer sends us an extrinsic that we didn't know about. - pub const GOOD_EXTRINSIC: Rep = Rep::new(1 << 7, "Good extrinsic"); - /// Reputation change when a peer sends us a bad extrinsic. - pub const BAD_EXTRINSIC: Rep = Rep::new(-(1 << 12), "Bad extrinsic"); + /// Reputation change when a peer sends us any transaction. + /// + /// This forces node to verify it, thus the negative value here. Once transaction is verified, + /// reputation change should be refunded with `ANY_TRANSACTION_REFUND` + pub const ANY_TRANSACTION: Rep = Rep::new(-(1 << 4), "Any transaction"); + /// Reputation change when a peer sends us any transaction that is not invalid. + pub const ANY_TRANSACTION_REFUND: Rep = Rep::new(1 << 4, "Any transaction (refund)"); + /// Reputation change when a peer sends us an transaction that we didn't know about. + pub const GOOD_TRANSACTION: Rep = Rep::new(1 << 7, "Good transaction"); + /// Reputation change when a peer sends us a bad transaction. + pub const BAD_TRANSACTION: Rep = Rep::new(-(1 << 12), "Bad transaction"); /// We sent an RPC query to the given node, but it failed. pub const RPC_FAILED: Rep = Rep::new(-(1 << 12), "Remote call failed"); /// We received a message that failed to decode. pub const BAD_MESSAGE: Rep = Rep::new(-(1 << 12), "Bad message"); /// We received an unexpected response. pub const UNEXPECTED_RESPONSE: Rep = Rep::new_fatal("Unexpected response packet"); - /// We received an unexpected extrinsic packet. - pub const UNEXPECTED_EXTRINSICS: Rep = Rep::new_fatal("Unexpected extrinsics packet"); + /// We received an unexpected transaction packet. + pub const UNEXPECTED_TRANSACTIONS: Rep = Rep::new_fatal("Unexpected transactions packet"); /// We received an unexpected light node request. pub const UNEXPECTED_REQUEST: Rep = Rep::new_fatal("Unexpected block request packet"); /// Peer has different genesis. @@ -144,6 +145,7 @@ struct Metrics { fork_targets: Gauge, finality_proofs: GaugeVec, justifications: GaugeVec, + propagated_transactions: Counter, } impl Metrics { @@ -189,18 +191,50 @@ impl Metrics { )?; register(g, r)? }, + propagated_transactions: register(Counter::new( + "sync_propagated_transactions", + "Number of transactions propagated to at least one peer", + )?, r)?, }) } } +#[pin_project::pin_project] +struct PendingTransaction { + #[pin] + validation: TransactionImportFuture, + tx_hash: H, +} + +impl Future for PendingTransaction { + type Output = (H, TransactionImport); + + fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll { + let mut this = self.project(); + + if let Poll::Ready(import_result) = Pin::new(&mut this.validation).poll_unpin(cx) { + return Poll::Ready((this.tx_hash.clone(), import_result)); + } + + Poll::Pending + } +} + // Lock must always be taken in order declared here. pub struct Protocol { /// Interval at which we call `tick`. tick_timeout: Pin + Send>>, - /// Interval at which we call `propagate_extrinsics`. + /// Interval at which we call `propagate_transactions`. propagate_timeout: Pin + Send>>, /// Pending list of messages to return from `poll` as a priority. pending_messages: VecDeque>, + /// Pending transactions verification tasks. + pending_transactions: FuturesUnordered>, + /// As multiple peers can send us the same transaction, we group + /// these peers using the transaction hash while the transaction is + /// imported. This prevents that we import the same transaction + /// multiple times concurrently. + pending_transactions_peers: HashMap>, config: ProtocolConfig, genesis_hash: B::Hash, sync: ChainSync, @@ -254,7 +288,7 @@ struct Peer { /// Requests we are no longer interested in. obsolete_requests: HashMap, /// Holds a set of transactions known to this peer. - known_extrinsics: LruHashSet, + known_transactions: LruHashSet, /// Holds a set of blocks known to this peer. known_blocks: LruHashSet, /// Request counter, @@ -300,6 +334,47 @@ impl Default for ProtocolConfig { } } +/// Handshake sent when we open a block announces substream. +#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] +struct BlockAnnouncesHandshake { + /// Roles of the node. + roles: Roles, + /// Best block number. + best_number: NumberFor, + /// Best block hash. + best_hash: B::Hash, + /// Genesis block hash. + genesis_hash: B::Hash, +} + +impl BlockAnnouncesHandshake { + fn build(protocol_config: &ProtocolConfig, chain: &Arc>) -> Self { + let info = chain.info(); + BlockAnnouncesHandshake { + genesis_hash: info.genesis_hash, + roles: protocol_config.roles, + best_number: info.best_number, + best_hash: info.best_hash, + } + } +} + +/// Builds a SCALE-encoded "Status" message to send as handshake for the legacy protocol. +fn build_status_message(protocol_config: &ProtocolConfig, chain: &Arc>) -> Vec { + let info = chain.info(); + let status = message::generic::Status { + version: CURRENT_VERSION, + min_supported_version: MIN_VERSION, + genesis_hash: info.genesis_hash, + roles: protocol_config.roles.into(), + best_number: info.best_number, + best_hash: info.best_hash, + chain_status: Vec::new(), // TODO: find a way to make this backwards-compatible + }; + + Message::::Status(status).encode() +} + /// Fallback mechanism to use to send a notification if no substream is open. #[derive(Debug, Clone, PartialEq, Eq)] enum Fallback { @@ -315,6 +390,7 @@ impl Protocol { /// Create a new instance. pub fn new( config: ProtocolConfig, + local_peer_id: PeerId, chain: Arc>, transaction_pool: Arc>, finality_proof_provider: Option>>, @@ -347,7 +423,14 @@ impl Protocol { let (peerset, peerset_handle) = sc_peerset::Peerset::from_config(peerset_config); let versions = &((MIN_VERSION as u8)..=(CURRENT_VERSION as u8)).collect::>(); - let mut behaviour = GenericProto::new(protocol_id.clone(), versions, peerset, queue_size_report); + let mut behaviour = GenericProto::new( + local_peer_id, + protocol_id.clone(), + versions, + build_status_message(&config, &chain), + peerset, + queue_size_report + ); let mut legacy_equiv_by_name = HashMap::new(); @@ -366,13 +449,18 @@ impl Protocol { proto.extend(b"/block-announces/1"); proto }); - behaviour.register_notif_protocol(block_announces_protocol.clone(), Vec::new()); + behaviour.register_notif_protocol( + block_announces_protocol.clone(), + BlockAnnouncesHandshake::build(&config, &chain).encode() + ); legacy_equiv_by_name.insert(block_announces_protocol.clone(), Fallback::BlockAnnounce); let protocol = Protocol { tick_timeout: Box::pin(interval(TICK_TIMEOUT)), propagate_timeout: Box::pin(interval(PROPAGATE_TIMEOUT)), pending_messages: VecDeque::new(), + pending_transactions: FuturesUnordered::new(), + pending_transactions_peers: HashMap::new(), config, context_data: ContextData { peers: HashMap::new(), @@ -471,9 +559,9 @@ impl Protocol { self.sync.status().queued_blocks } - /// Number of processed blocks. - pub fn num_processed_blocks(&self) -> usize { - self.sync.num_processed_blocks() + /// Number of downloaded blocks. + pub fn num_downloaded_blocks(&self) -> usize { + self.sync.num_downloaded_blocks() } /// Number of active sync requests. @@ -481,26 +569,20 @@ impl Protocol { self.sync.num_sync_requests() } - fn handle_response( - &mut self, - who: PeerId, - response: &message::BlockResponse - ) -> Option> { - if let Some(ref mut peer) = self.context_data.peers.get_mut(&who) { - if let Some(_) = peer.obsolete_requests.remove(&response.id) { - trace!(target: "sync", "Ignoring obsolete block response packet from {} ({})", who, response.id); - return None; - } - // Clear the request. If the response is invalid peer will be disconnected anyway. - let request = peer.block_request.take(); - if request.as_ref().map_or(false, |(_, r)| r.id == response.id) { - return request.map(|(_, r)| r) - } - trace!(target: "sync", "Unexpected response packet from {} ({})", who, response.id); - self.peerset_handle.report_peer(who.clone(), rep::UNEXPECTED_RESPONSE); - self.behaviour.disconnect_peer(&who); - } - None + /// Sync local state with the blockchain state. + pub fn update_chain(&mut self) { + let info = self.context_data.chain.info(); + self.sync.update_chain_info(&info.best_hash, info.best_number); + self.behaviour.set_legacy_handshake_message(build_status_message(&self.config, &self.context_data.chain)); + self.behaviour.set_notif_protocol_handshake( + &self.block_announces_protocol, + BlockAnnouncesHandshake::build(&self.config, &self.context_data.chain).encode() + ); + } + + /// Inform sync about an own imported block. + pub fn own_block_imported(&mut self, hash: B::Hash, number: NumberFor) { + self.sync.update_chain_info(&hash, number); } fn update_peer_info(&mut self, who: &PeerId) { @@ -527,7 +609,7 @@ impl Protocol { 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(), rep::BAD_MESSAGE); + self.peerset_handle.report_peer(who, rep::BAD_MESSAGE); return CustomMessageOutcome::None; } }; @@ -540,11 +622,9 @@ impl Protocol { GenericMessage::Status(s) => return self.on_status_message(who, s), GenericMessage::BlockRequest(r) => self.on_block_request(who, r), GenericMessage::BlockResponse(r) => { - if let Some(request) = self.handle_response(who.clone(), &r) { - let outcome = self.on_block_response(who.clone(), request, r); - self.update_peer_info(&who); - return outcome - } + let outcome = self.on_block_response(who.clone(), r); + self.update_peer_info(&who); + return outcome }, GenericMessage::BlockAnnounce(announce) => { let outcome = self.on_block_announce(who.clone(), announce); @@ -552,7 +632,7 @@ impl Protocol { return outcome; }, GenericMessage::Transactions(m) => - self.on_extrinsics(who, m), + self.on_transactions(who, m), GenericMessage::RemoteCallRequest(request) => self.on_remote_call_request(who, request), GenericMessage::RemoteCallResponse(_) => warn!(target: "sub-libp2p", "Received unexpected RemoteCallResponse"), @@ -577,7 +657,7 @@ impl Protocol { GenericMessage::Consensus(msg) => return if self.protocol_name_by_engine.contains_key(&msg.engine_id) { CustomMessageOutcome::NotificationsReceived { - remote: who.clone(), + remote: who, messages: vec![(msg.engine_id, From::from(msg.data))], } } else { @@ -599,7 +679,7 @@ impl Protocol { return if !messages.is_empty() { CustomMessageOutcome::NotificationsReceived { - remote: who.clone(), + remote: who, messages, } } else { @@ -611,16 +691,6 @@ impl Protocol { CustomMessageOutcome::None } - 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, @@ -636,11 +706,14 @@ impl Protocol { ); } + fn update_peer_request(&mut self, who: &PeerId, request: &mut message::BlockRequest) { + update_peer_request::(&mut self.context_data.peers, who, request) + } + /// Called when a new peer is connected pub fn on_peer_connected(&mut self, who: PeerId) { trace!(target: "sync", "Connecting {}", who); self.handshaking_peers.insert(who.clone(), HandshakingPeer { timestamp: Instant::now() }); - self.send_status(who); } /// Called by peer when it is disconnecting @@ -657,7 +730,7 @@ impl Protocol { self.context_data.peers.remove(&peer) }; if let Some(_peer_data) = removed { - self.sync.peer_disconnected(peer.clone()); + self.sync.peer_disconnected(&peer); // Notify all the notification protocols as closed. CustomMessageOutcome::NotificationStreamClosed { @@ -677,8 +750,8 @@ impl Protocol { // Print some diagnostics. if let Some(peer) = self.context_data.peers.get(&who) { debug!(target: "sync", "Clogged peer {} (protocol_version: {:?}; roles: {:?}; \ - known_extrinsics: {:?}; known_blocks: {:?}; best_hash: {:?}; best_number: {:?})", - who, peer.info.protocol_version, peer.info.roles, peer.known_extrinsics, peer.known_blocks, + known_transactions: {:?}; known_blocks: {:?}; best_hash: {:?}; best_number: {:?})", + who, peer.info.protocol_version, peer.info.roles, peer.known_transactions, peer.known_blocks, peer.info.best_hash, peer.info.best_number); } else { debug!(target: "sync", "Peer clogged before being properly connected"); @@ -718,16 +791,16 @@ impl Protocol { if blocks.len() >= max { break; } - let number = header.number().clone(); + let number = *header.number(); let hash = header.hash(); - let parent_hash = header.parent_hash().clone(); + let parent_hash = *header.parent_hash(); let justification = if get_justification { self.context_data.chain.justification(&BlockId::Hash(hash)).unwrap_or(None) } else { None }; let block_data = message::generic::BlockData { - hash: hash, + hash, header: if get_header { Some(header) } else { None }, body: if get_body { self.context_data @@ -759,7 +832,7 @@ impl Protocol { } let response = message::generic::BlockResponse { id: request.id, - blocks: blocks, + blocks, }; trace!(target: "sync", "Sending BlockResponse with {} blocks", response.blocks.len()); self.send_message(&peer, None, GenericMessage::BlockResponse(response)) @@ -770,12 +843,39 @@ impl Protocol { self.peerset_handle.report_peer(who, reputation) } - fn on_block_response( + /// Must be called in response to a [`CustomMessageOutcome::BlockRequest`] being emitted. + /// Must contain the same `PeerId` and request that have been emitted. + pub fn on_block_response( &mut self, peer: PeerId, - request: message::BlockRequest, response: message::BlockResponse, ) -> CustomMessageOutcome { + let request = if let Some(ref mut p) = self.context_data.peers.get_mut(&peer) { + if p.obsolete_requests.remove(&response.id).is_some() { + trace!(target: "sync", "Ignoring obsolete block response packet from {} ({})", peer, response.id); + return CustomMessageOutcome::None; + } + // Clear the request. If the response is invalid peer will be disconnected anyway. + match p.block_request.take() { + Some((_, request)) if request.id == response.id => request, + Some(_) => { + trace!(target: "sync", "Ignoring obsolete block response packet from {} ({})", peer, response.id); + return CustomMessageOutcome::None; + } + None => { + trace!(target: "sync", "Unexpected response packet from unknown peer {}", peer); + self.behaviour.disconnect_peer(&peer); + self.peerset_handle.report_peer(peer, rep::UNEXPECTED_RESPONSE); + return CustomMessageOutcome::None; + } + } + } else { + trace!(target: "sync", "Unexpected response packet from unknown peer {}", peer); + self.behaviour.disconnect_peer(&peer); + self.peerset_handle.report_peer(peer, rep::UNEXPECTED_RESPONSE); + return CustomMessageOutcome::None; + }; + let blocks_range = || match ( response.blocks.first().and_then(|b| b.header.as_ref().map(|h| h.number())), response.blocks.last().and_then(|b| b.header.as_ref().map(|h| h.number())), @@ -817,12 +917,15 @@ impl Protocol { return CustomMessageOutcome::None } - match self.sync.on_block_data(peer, Some(request), response) { + match self.sync.on_block_data(&peer, Some(request), response) { Ok(sync::OnBlockData::Import(origin, blocks)) => CustomMessageOutcome::BlockImport(origin, blocks), - Ok(sync::OnBlockData::Request(peer, req)) => { - self.send_request(&peer, GenericMessage::BlockRequest(req)); - CustomMessageOutcome::None + Ok(sync::OnBlockData::Request(peer, mut req)) => { + self.update_peer_request(&peer, &mut req); + CustomMessageOutcome::BlockRequest { + target: peer, + request: req, + } } Err(sync::BadPeer(id, repu)) => { self.behaviour.disconnect_peer(&id); @@ -833,6 +936,15 @@ impl Protocol { } } + /// Must be called in response to a [`CustomMessageOutcome::BlockRequest`] if it has failed. + pub fn on_block_request_failed( + &mut self, + peer: &PeerId, + ) { + self.peerset_handle.report_peer(peer.clone(), rep::TIMEOUT); + self.behaviour.disconnect_peer(peer); + } + /// Perform time based maintenance. /// /// > **Note**: This method normally doesn't have to be called except for testing purposes. @@ -885,12 +997,7 @@ impl Protocol { trace!(target: "sync", "New peer {} {:?}", who, status); let _protocol_version = { if self.context_data.peers.contains_key(&who) { - log!( - target: "sync", - if self.important_peers.contains(&who) { Level::Warn } else { Level::Debug }, - "Unexpected status packet from {}", who - ); - self.peerset_handle.report_peer(who, rep::UNEXPECTED_STATUS); + debug!(target: "sync", "Ignoring duplicate status packet from {}", who); return CustomMessageOutcome::None; } if status.genesis_hash != self.genesis_hash { @@ -971,7 +1078,7 @@ impl Protocol { let peer = Peer { info, block_request: None, - known_extrinsics: LruHashSet::new(NonZeroUsize::new(MAX_KNOWN_EXTRINSICS) + known_transactions: LruHashSet::new(NonZeroUsize::new(MAX_KNOWN_TRANSACTIONS) .expect("Constant is nonzero")), known_blocks: LruHashSet::new(NonZeroUsize::new(MAX_KNOWN_BLOCKS) .expect("Constant is nonzero")), @@ -989,7 +1096,13 @@ impl Protocol { if info.roles.is_full() { match self.sync.new_peer(who.clone(), info.best_hash, info.best_number) { Ok(None) => (), - Ok(Some(req)) => self.send_request(&who, GenericMessage::BlockRequest(req)), + Ok(Some(mut req)) => { + self.update_peer_request(&who, &mut req); + self.pending_messages.push_back(CustomMessageOutcome::BlockRequest { + target: who.clone(), + request: req, + }); + }, Err(sync::BadPeer(id, repu)) => { self.behaviour.disconnect_peer(&id); self.peerset_handle.report_peer(id, repu) @@ -1040,12 +1153,13 @@ impl Protocol { &'a mut self, engine_id: ConsensusEngineId, protocol_name: impl Into>, + handshake_message: Vec, ) -> impl ExactSizeIterator + 'a { let protocol_name = protocol_name.into(); if self.protocol_name_by_engine.insert(engine_id, protocol_name.clone()).is_some() { error!(target: "sub-libp2p", "Notifications protocol already registered: {:?}", protocol_name); } else { - self.behaviour.register_notif_protocol(protocol_name.clone(), Vec::new()); + self.behaviour.register_notif_protocol(protocol_name.clone(), handshake_message); self.legacy_equiv_by_name.insert(protocol_name, Fallback::Consensus(engine_id)); } @@ -1053,80 +1167,110 @@ impl Protocol { .map(|(peer_id, peer)| (peer_id, peer.info.roles)) } - /// Called when peer sends us new extrinsics - fn on_extrinsics( + /// Called when peer sends us new transactions + fn on_transactions( &mut self, who: PeerId, - extrinsics: message::Transactions + transactions: message::Transactions, ) { - // sending extrinsic to light node is considered a bad behavior + // sending transaction 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); + trace!(target: "sync", "Peer {} is trying to send transactions to the light node", who); self.behaviour.disconnect_peer(&who); - self.peerset_handle.report_peer(who, rep::UNEXPECTED_EXTRINSICS); + self.peerset_handle.report_peer(who, rep::UNEXPECTED_TRANSACTIONS); return; } - // Accept extrinsics only when fully synced + // Accept transactions only when fully synced if self.sync.status().state != SyncState::Idle { - trace!(target: "sync", "{} Ignoring extrinsics while syncing", who); + trace!(target: "sync", "{} Ignoring transactions while syncing", who); return; } - trace!(target: "sync", "Received {} extrinsics from {}", extrinsics.len(), who); + + trace!(target: "sync", "Received {} transactions from {}", transactions.len(), who); if let Some(ref mut peer) = self.context_data.peers.get_mut(&who) { - for t in extrinsics { + for t in transactions { + if self.pending_transactions.len() > MAX_PENDING_TRANSACTIONS { + debug!( + target: "sync", + "Ignoring any further transactions that exceed `MAX_PENDING_TRANSACTIONS`({}) limit", + MAX_PENDING_TRANSACTIONS, + ); + break; + } + let hash = self.transaction_pool.hash_of(&t); - peer.known_extrinsics.insert(hash); - - self.transaction_pool.import( - self.peerset_handle.clone().into(), - who.clone(), - rep::GOOD_EXTRINSIC, - rep::BAD_EXTRINSIC, - t, - ); + peer.known_transactions.insert(hash.clone()); + + self.peerset_handle.report_peer(who.clone(), rep::ANY_TRANSACTION); + + match self.pending_transactions_peers.entry(hash.clone()) { + Entry::Vacant(entry) => { + self.pending_transactions.push(PendingTransaction { + validation: self.transaction_pool.import(t), + tx_hash: hash, + }); + entry.insert(vec![who.clone()]); + }, + Entry::Occupied(mut entry) => { + entry.get_mut().push(who.clone()); + } + } } } } - /// Propagate one extrinsic. - pub fn propagate_extrinsic( + fn on_handle_transaction_import(&mut self, who: PeerId, import: TransactionImport) { + match import { + TransactionImport::KnownGood => self.peerset_handle.report_peer(who, rep::ANY_TRANSACTION_REFUND), + TransactionImport::NewGood => self.peerset_handle.report_peer(who, rep::GOOD_TRANSACTION), + TransactionImport::Bad => self.peerset_handle.report_peer(who, rep::BAD_TRANSACTION), + TransactionImport::None => {}, + } + } + + /// Propagate one transaction. + pub fn propagate_transaction( &mut self, hash: &H, ) { - debug!(target: "sync", "Propagating extrinsic [{:?}]", hash); + debug!(target: "sync", "Propagating transaction [{:?}]", hash); // Accept transactions only when fully synced if self.sync.status().state != SyncState::Idle { return; } - if let Some(extrinsic) = self.transaction_pool.transaction(hash) { - let propagated_to = self.do_propagate_extrinsics(&[(hash.clone(), extrinsic)]); + if let Some(transaction) = self.transaction_pool.transaction(hash) { + let propagated_to = self.do_propagate_transactions(&[(hash.clone(), transaction)]); self.transaction_pool.on_broadcasted(propagated_to); } } - fn do_propagate_extrinsics( + fn do_propagate_transactions( &mut self, - extrinsics: &[(H, B::Extrinsic)], + transactions: &[(H, B::Extrinsic)], ) -> HashMap> { - let mut propagated_to = HashMap::new(); + let mut propagated_to = HashMap::<_, Vec<_>>::new(); + let mut propagated_transactions = 0; + for (who, peer) in self.context_data.peers.iter_mut() { - // never send extrinsics to the light node + // never send transactions to the light node if !peer.info.roles.is_full() { continue; } - let (hashes, to_send): (Vec<_>, Vec<_>) = extrinsics + let (hashes, to_send): (Vec<_>, Vec<_>) = transactions .iter() - .filter(|&(ref hash, _)| peer.known_extrinsics.insert(hash.clone())) + .filter(|&(ref hash, _)| peer.known_transactions.insert(hash.clone())) .cloned() .unzip(); + propagated_transactions += hashes.len(); + if !to_send.is_empty() { for hash in hashes { propagated_to .entry(hash) - .or_insert_with(Vec::new) + .or_default() .push(who.to_base58()); } trace!(target: "sync", "Sending {} transactions to {}", to_send.len(), who); @@ -1141,18 +1285,22 @@ impl Protocol { } } + if let Some(ref metrics) = self.metrics { + metrics.propagated_transactions.inc_by(propagated_transactions as _) + } + propagated_to } - /// Call when we must propagate ready extrinsics to peers. - pub fn propagate_extrinsics(&mut self) { - debug!(target: "sync", "Propagating extrinsics"); + /// Call when we must propagate ready transactions to peers. + pub fn propagate_transactions(&mut self) { + debug!(target: "sync", "Propagating transactions"); // Accept transactions only when fully synced if self.sync.status().state != SyncState::Idle { return; } - let extrinsics = self.transaction_pool.transactions(); - let propagated_to = self.do_propagate_extrinsics(&extrinsics); + let transactions = self.transaction_pool.transactions(); + let propagated_to = self.do_propagate_transactions(&transactions); self.transaction_pool.on_broadcasted(propagated_to); } @@ -1179,7 +1327,7 @@ impl Protocol { } let is_best = self.context_data.chain.info().best_hash == hash; - debug!(target: "sync", "Reannouncing block {:?}", hash); + debug!(target: "sync", "Reannouncing block {:?} is_best: {}", hash, is_best); self.send_announcement(&header, data, is_best, true) } @@ -1221,22 +1369,6 @@ impl Protocol { } } - /// Send Status message - fn send_status(&mut self, who: PeerId) { - let info = self.context_data.chain.info(); - let status = message::generic::Status { - version: CURRENT_VERSION, - min_supported_version: MIN_VERSION, - genesis_hash: info.genesis_hash, - roles: self.config.roles.into(), - best_number: info.best_number, - best_hash: info.best_hash, - chain_status: Vec::new(), // TODO: find a way to make this backwards-compatible - }; - - self.send_message(&who, None, GenericMessage::Status(status)) - } - fn on_block_announce( &mut self, who: PeerId, @@ -1254,7 +1386,7 @@ impl Protocol { message::BlockState::Normal => false, }; - match self.sync.on_block_announce(who.clone(), hash, &announce, is_their_best) { + match self.sync.on_block_announce(&who, hash, &announce, is_their_best) { sync::OnBlockAnnounce::Nothing => { // `on_block_announce` returns `OnBlockAnnounce::ImportHeader` // when we have all data required to import the block @@ -1274,7 +1406,7 @@ impl Protocol { // to import header from announced block let's construct response to request that normally would have // been sent over network (but it is not in our case) let blocks_to_import = self.sync.on_block_data( - who.clone(), + &who, None, message::generic::BlockResponse { id: 0, @@ -1290,40 +1422,30 @@ impl Protocol { ], }, ); + + if is_their_best { + self.pending_messages.push_back(CustomMessageOutcome::PeerNewBest(who, number)); + } + match blocks_to_import { Ok(sync::OnBlockData::Import(origin, blocks)) => { - if is_their_best { - self.pending_messages.push_back(CustomMessageOutcome::PeerNewBest(who, number)); - } CustomMessageOutcome::BlockImport(origin, blocks) }, - Ok(sync::OnBlockData::Request(peer, req)) => { - self.send_request(&peer, GenericMessage::BlockRequest(req)); - if is_their_best { - CustomMessageOutcome::PeerNewBest(who, number) - } else { - CustomMessageOutcome::None + Ok(sync::OnBlockData::Request(peer, mut req)) => { + self.update_peer_request(&peer, &mut req); + CustomMessageOutcome::BlockRequest { + target: peer, + request: req, } } Err(sync::BadPeer(id, repu)) => { self.behaviour.disconnect_peer(&id); self.peerset_handle.report_peer(id, repu); - if is_their_best { - CustomMessageOutcome::PeerNewBest(who, number) - } else { - CustomMessageOutcome::None - } + CustomMessageOutcome::None } } } - /// Call this when a block has been imported in the import queue - pub fn on_block_imported(&mut self, header: &B::Header, is_best: bool) { - if is_best { - self.sync.update_chain_info(header); - } - } - /// Call this when a block has been finalized. The sync layer may have some additional /// requesting to perform. pub fn on_block_finalized(&mut self, hash: B::Hash, header: &B::Header) { @@ -1388,12 +1510,24 @@ impl Protocol { /// 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. - pub fn blocks_processed( + pub fn on_blocks_processed( &mut self, imported: usize, count: usize, results: Vec<(Result>, BlockImportError>, B::Hash)> ) { + let new_best = results.iter().rev().find_map(|r| match r { + (Ok(BlockImportResult::ImportedUnknown(n, aux, _)), hash) if aux.is_new_best => Some((*n, hash.clone())), + _ => None, + }); + if let Some((best_num, best_hash)) = new_best { + self.sync.update_chain_info(&best_hash, best_num); + self.behaviour.set_legacy_handshake_message(build_status_message(&self.config, &self.context_data.chain)); + self.behaviour.set_notif_protocol_handshake( + &self.block_announces_protocol, + BlockAnnouncesHandshake::build(&self.config, &self.context_data.chain).encode() + ); + } let results = self.sync.on_blocks_processed( imported, count, @@ -1401,15 +1535,12 @@ impl Protocol { ); for result in results { match result { - Ok((id, req)) => { - let msg = GenericMessage::BlockRequest(req); - send_request( - &mut self.behaviour, - &mut self.context_data.stats, - &mut self.context_data.peers, - &id, - msg - ) + Ok((id, mut req)) => { + update_peer_request(&mut self.context_data.peers, &id, &mut req); + self.pending_messages.push_back(CustomMessageOutcome::BlockRequest { + target: id, + request: req, + }); } Err(sync::BadPeer(id, repu)) => { self.behaviour.disconnect_peer(&id); @@ -1519,37 +1650,28 @@ impl Protocol { trace!(target: "sync", "Remote read child request {} from {} ({} {} at {})", request.id, who, HexDisplay::from(&request.storage_key), keys_str(), request.block); - let proof = if let Some(child_info) = ChildInfo::resolve_child_info(request.child_type, &request.child_info[..]) { - match self.context_data.chain.read_child_proof( - &BlockId::Hash(request.block), - &request.storage_key, - child_info, - &mut request.keys.iter().map(AsRef::as_ref), - ) { - Ok(proof) => proof, - Err(error) => { - trace!(target: "sync", "Remote read child request {} from {} ({} {} at {}) failed with: {}", - request.id, - who, - HexDisplay::from(&request.storage_key), - keys_str(), - request.block, - error - ); - StorageProof::empty() - } + let prefixed_key = PrefixedStorageKey::new_ref(&request.storage_key); + let child_info = match ChildType::from_prefixed_key(prefixed_key) { + Some((ChildType::ParentKeyId, storage_key)) => Ok(ChildInfo::new_default(storage_key)), + None => Err("Invalid child storage key".into()), + }; + let proof = match child_info.and_then(|child_info| self.context_data.chain.read_child_proof( + &BlockId::Hash(request.block), + &child_info, + &mut request.keys.iter().map(AsRef::as_ref), + )) { + Ok(proof) => proof, + Err(error) => { + trace!(target: "sync", "Remote read child request {} from {} ({} {} at {}) failed with: {}", + request.id, + who, + HexDisplay::from(&request.storage_key), + keys_str(), + request.block, + error + ); + StorageProof::empty() } - } else { - trace!(target: "sync", "Remote read child request {} from {} ({} {} at {}) failed with: {}", - request.id, - who, - HexDisplay::from(&request.storage_key), - keys_str(), - request.block, - "invalid child info and type", - ); - - StorageProof::empty() }; self.send_message( &who, @@ -1607,14 +1729,16 @@ impl Protocol { request.first, request.last ); - let storage_key = request.storage_key.map(|sk| StorageKey(sk)); let key = StorageKey(request.key); + let prefixed_key = request.storage_key.as_ref() + .map(|storage_key| PrefixedStorageKey::new_ref(storage_key)); + let (first, last, min, max) = (request.first, request.last, request.min, request.max); let proof = match self.context_data.chain.key_changes_proof( - request.first, - request.last, - request.min, - request.max, - storage_key.as_ref(), + first, + last, + min, + max, + prefixed_key, &key, ) { Ok(proof) => proof, @@ -1622,8 +1746,8 @@ impl Protocol { trace!(target: "sync", "Remote changes proof request {} from {} for key {} ({}..{}) failed with: {}", request.id, who, - if let Some(sk) = storage_key { - format!("{} : {}", HexDisplay::from(&sk.0), HexDisplay::from(&key.0)) + if let Some(sk) = request.storage_key.as_ref() { + format!("{} : {}", HexDisplay::from(sk), HexDisplay::from(&key.0)) } else { HexDisplay::from(&key.0).to_string() }, @@ -1685,7 +1809,9 @@ impl Protocol { ); } - fn on_finality_proof_response( + /// Must be called after a [`CustomMessageOutcome::FinalityProofRequest`] has been emitted, + /// to notify of the response having arrived. + pub fn on_finality_proof_response( &mut self, who: PeerId, response: message::FinalityProofResponse, @@ -1764,6 +1890,7 @@ impl Protocol { /// Outcome of an incoming custom message. #[derive(Debug)] +#[must_use] pub enum CustomMessageOutcome { BlockImport(BlockOrigin, Vec>), JustificationImport(Origin, B::Hash, NumberFor, Justification), @@ -1774,30 +1901,38 @@ pub enum CustomMessageOutcome { NotificationStreamClosed { remote: PeerId, protocols: Vec }, /// Messages have been received on one or more notifications protocols. NotificationsReceived { remote: PeerId, messages: Vec<(ConsensusEngineId, Bytes)> }, + /// A new block request must be emitted. + /// You must later call either [`Protocol::on_block_response`] or + /// [`Protocol::on_block_request_failed`]. + /// Each peer can only have one active request. If a request already exists for this peer, it + /// must be silently discarded. + /// It is the responsibility of the handler to ensure that a timeout exists. + BlockRequest { target: PeerId, request: message::BlockRequest }, + /// A new finality proof request must be emitted. + /// Once you have the response, you must call `Protocol::on_finality_proof_response`. + /// It is the responsibility of the handler to ensure that a timeout exists. + /// If the request times out, or the peer responds in an invalid way, the peer has to be + /// disconnect. This will inform the state machine that the request it has emitted is stale. + FinalityProofRequest { target: PeerId, block_hash: B::Hash, request: Vec }, /// Peer has a reported a new head of chain. PeerNewBest(PeerId, NumberFor), None, } -fn send_request( - behaviour: &mut GenericProto, - stats: &mut HashMap<&'static str, PacketStats>, +fn update_peer_request( peers: &mut HashMap>, who: &PeerId, - mut message: Message, + request: &mut message::BlockRequest, ) { - if let GenericMessage::BlockRequest(ref mut r) = message { - 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() { - trace!(target: "sync", "Request {} for {} is now obsolete.", request.id, who); - peer.obsolete_requests.insert(request.id, timestamp); - } - peer.block_request = Some((Instant::now(), r.clone())); + if let Some(ref mut peer) = peers.get_mut(who) { + request.id = peer.next_request_id; + peer.next_request_id += 1; + if let Some((timestamp, request)) = peer.block_request.take() { + trace!(target: "sync", "Request {} for {} is now obsolete.", request.id, who); + peer.obsolete_requests.insert(request.id, timestamp); } + peer.block_request = Some((Instant::now(), request.clone())); } - send_message::(behaviour, stats, who, None, message) } fn send_message( @@ -1830,20 +1965,29 @@ impl NetworkBehaviour for Protocol { self.behaviour.addresses_of_peer(peer_id) } - fn inject_connected(&mut self, peer_id: PeerId, endpoint: ConnectedPoint) { - self.behaviour.inject_connected(peer_id, endpoint) + fn inject_connection_established(&mut self, peer_id: &PeerId, conn: &ConnectionId, endpoint: &ConnectedPoint) { + self.behaviour.inject_connection_established(peer_id, conn, endpoint) } - fn inject_disconnected(&mut self, peer_id: &PeerId, endpoint: ConnectedPoint) { - self.behaviour.inject_disconnected(peer_id, endpoint) + fn inject_connection_closed(&mut self, peer_id: &PeerId, conn: &ConnectionId, endpoint: &ConnectedPoint) { + self.behaviour.inject_connection_closed(peer_id, conn, endpoint) } - fn inject_node_event( + fn inject_connected(&mut self, peer_id: &PeerId) { + self.behaviour.inject_connected(peer_id) + } + + fn inject_disconnected(&mut self, peer_id: &PeerId) { + self.behaviour.inject_disconnected(peer_id) + } + + fn inject_event( &mut self, peer_id: PeerId, + connection: ConnectionId, event: <::Handler as ProtocolsHandler>::OutEvent, ) { - self.behaviour.inject_node_event(peer_id, event) + self.behaviour.inject_event(peer_id, connection, event) } fn poll( @@ -1865,34 +2009,42 @@ impl NetworkBehaviour for Protocol { } while let Poll::Ready(Some(())) = self.propagate_timeout.poll_next_unpin(cx) { - self.propagate_extrinsics(); + self.propagate_transactions(); } - for (id, r) in self.sync.block_requests() { - send_request( - &mut self.behaviour, - &mut self.context_data.stats, - &mut self.context_data.peers, - &id, - GenericMessage::BlockRequest(r) - ) + for (id, mut r) in self.sync.block_requests() { + update_peer_request(&mut self.context_data.peers, &id, &mut r); + let event = CustomMessageOutcome::BlockRequest { + target: id.clone(), + request: r, + }; + self.pending_messages.push_back(event); } - for (id, r) in self.sync.justification_requests() { - send_request( - &mut self.behaviour, - &mut self.context_data.stats, - &mut self.context_data.peers, - &id, - GenericMessage::BlockRequest(r) - ) + for (id, mut r) in self.sync.justification_requests() { + update_peer_request(&mut self.context_data.peers, &id, &mut r); + let event = CustomMessageOutcome::BlockRequest { + target: id, + request: r, + }; + self.pending_messages.push_back(event); } for (id, r) in self.sync.finality_proof_requests() { - send_request( - &mut self.behaviour, - &mut self.context_data.stats, - &mut self.context_data.peers, - &id, - GenericMessage::FinalityProofRequest(r)) + let event = CustomMessageOutcome::FinalityProofRequest { + target: id, + block_hash: r.block, + request: r.request, + }; + self.pending_messages.push_back(event); + } + if let Poll::Ready(Some((tx_hash, result))) = self.pending_transactions.poll_next_unpin(cx) { + if let Some(peers) = self.pending_transactions_peers.remove(&tx_hash) { + peers.into_iter().for_each(|p| self.on_handle_transaction_import(p, result)); + } else { + warn!(target: "sub-libp2p", "Inconsistent state, no peers for pending transaction!"); + } + } + if let Some(message) = self.pending_messages.pop_front() { + return Poll::Ready(NetworkBehaviourAction::GenerateEvent(message)); } let event = match self.behaviour.poll(cx, params) { @@ -1900,21 +2052,21 @@ impl NetworkBehaviour for Protocol { Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)) => ev, Poll::Ready(NetworkBehaviourAction::DialAddress { address }) => return Poll::Ready(NetworkBehaviourAction::DialAddress { address }), - Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }) => - return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }), - Poll::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }) => - return Poll::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }), + Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id, condition }) => + return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id, condition }), + Poll::Ready(NetworkBehaviourAction::NotifyHandler { peer_id, handler, event }) => + return Poll::Ready(NetworkBehaviourAction::NotifyHandler { peer_id, handler, event }), Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }) => return Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }), }; let outcome = match event { GenericProtoOut::CustomProtocolOpen { peer_id, .. } => { - self.on_peer_connected(peer_id.clone()); + self.on_peer_connected(peer_id); CustomMessageOutcome::None } GenericProtoOut::CustomProtocolClosed { peer_id, .. } => { - self.on_peer_disconnected(peer_id.clone()) + self.on_peer_disconnected(peer_id) }, GenericProtoOut::LegacyMessage { peer_id, message } => self.on_custom_message(peer_id, message), @@ -1928,7 +2080,7 @@ impl NetworkBehaviour for Protocol { } Some(Fallback::Transactions) => { if let Ok(m) = message::Transactions::decode(&mut message.as_ref()) { - self.on_extrinsics(peer_id, m); + self.on_transactions(peer_id, m); } else { warn!(target: "sub-libp2p", "Failed to decode transactions list"); } @@ -1967,10 +2119,6 @@ impl NetworkBehaviour for Protocol { } } - fn inject_replaced(&mut self, peer_id: PeerId, closed_endpoint: ConnectedPoint, new_endpoint: ConnectedPoint) { - self.behaviour.inject_replaced(peer_id, closed_endpoint, new_endpoint) - } - fn inject_addr_reach_failure( &mut self, peer_id: Option<&PeerId>, @@ -2000,8 +2148,8 @@ impl NetworkBehaviour for Protocol { self.behaviour.inject_listener_error(id, err); } - fn inject_listener_closed(&mut self, id: ListenerId) { - self.behaviour.inject_listener_closed(id); + fn inject_listener_closed(&mut self, id: ListenerId, reason: Result<(), &io::Error>) { + self.behaviour.inject_listener_closed(id, reason); } } @@ -2028,6 +2176,7 @@ mod tests { let (mut protocol, _) = Protocol::::new( ProtocolConfig::default(), + PeerId::random(), client.clone(), Arc::new(EmptyTransactionPool), None, @@ -2040,7 +2189,7 @@ mod tests { reserved_only: false, priority_groups: Vec::new(), }, - Box::new(DefaultBlockAnnounceValidator::new(client.clone())), + Box::new(DefaultBlockAnnounceValidator), None, Default::default(), None, diff --git a/client/network/src/protocol/block_requests.rs b/client/network/src/protocol/block_requests.rs deleted file mode 100644 index 5a947c0b6b5854ce05e393ea563976bb85656592..0000000000000000000000000000000000000000 --- a/client/network/src/protocol/block_requests.rs +++ /dev/null @@ -1,355 +0,0 @@ -// Copyright 2020 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 . - -//! `NetworkBehaviour` implementation which handles incoming block requests. -//! -//! Every request is coming in on a separate connection substream which gets -//! closed after we have sent the response back. Incoming requests are encoded -//! as protocol buffers (cf. `api.v1.proto`). - -#![allow(unused)] - -use bytes::Bytes; -use codec::{Encode, Decode}; -use crate::{ - chain::Client, - config::ProtocolId, - protocol::{api, message::BlockAttributes} -}; -use futures::{future::BoxFuture, prelude::*, stream::FuturesUnordered}; -use libp2p::{ - core::{ - ConnectedPoint, - Multiaddr, - PeerId, - upgrade::{InboundUpgrade, ReadOneError, UpgradeInfo, Negotiated}, - upgrade::{DeniedUpgrade, read_one, write_one} - }, - swarm::{ - NegotiatedSubstream, - NetworkBehaviour, - NetworkBehaviourAction, - OneShotHandler, - PollParameters, - SubstreamProtocol - } -}; -use prost::Message; -use sp_runtime::{generic::BlockId, traits::{Block, Header, One, Zero}}; -use std::{ - cmp::min, - io, - iter, - sync::Arc, - time::Duration, - task::{Context, Poll} -}; -use void::{Void, unreachable}; - -// Type alias for convenience. -pub type Error = Box; - -/// Configuration options for `BlockRequests`. -#[derive(Debug, Clone)] -pub struct Config { - max_block_data_response: u32, - max_request_len: usize, - inactivity_timeout: Duration, - protocol: Bytes, -} - -impl Config { - /// Create a fresh configuration with the following options: - /// - /// - max. block data in response = 128 - /// - max. request size = 1 MiB - /// - inactivity timeout = 15s - pub fn new(id: &ProtocolId) -> Self { - let mut c = Config { - max_block_data_response: 128, - max_request_len: 1024 * 1024, - inactivity_timeout: Duration::from_secs(15), - protocol: Bytes::new(), - }; - c.set_protocol(id); - c - } - - /// Limit the max. number of block data in a response. - pub fn set_max_block_data_response(&mut self, v: u32) -> &mut Self { - self.max_block_data_response = v; - self - } - - /// Limit the max. length of incoming block request bytes. - pub fn set_max_request_len(&mut self, v: usize) -> &mut Self { - self.max_request_len = v; - self - } - - /// Limit the max. duration the substream may remain inactive before closing it. - pub fn set_inactivity_timeout(&mut self, v: Duration) -> &mut Self { - self.inactivity_timeout = v; - self - } - - /// Set protocol to use for upgrade negotiation. - pub fn set_protocol(&mut self, id: &ProtocolId) -> &mut Self { - let mut v = Vec::new(); - v.extend_from_slice(b"/"); - v.extend_from_slice(id.as_bytes()); - v.extend_from_slice(b"/sync/2"); - self.protocol = v.into(); - self - } -} - -/// The block request handling behaviour. -pub struct BlockRequests { - /// This behaviour's configuration. - config: Config, - /// Blockchain client. - chain: Arc>, - /// Futures sending back the block request response. - outgoing: FuturesUnordered>, -} - -impl BlockRequests -where - B: Block, -{ - pub fn new(cfg: Config, chain: Arc>) -> Self { - BlockRequests { - config: cfg, - chain, - outgoing: FuturesUnordered::new(), - } - } - - /// Callback, invoked when a new block request has been received from remote. - fn on_block_request - ( &mut self - , peer: &PeerId - , request: &api::v1::BlockRequest - ) -> Result - { - log::trace!("block request from peer {}: from block {:?} to block {:?}, max blocks {:?}", - peer, - request.from_block, - request.to_block, - request.max_blocks); - - let from_block_id = - match request.from_block { - Some(api::v1::block_request::FromBlock::Hash(ref h)) => { - let h = Decode::decode(&mut h.as_ref())?; - BlockId::::Hash(h) - } - Some(api::v1::block_request::FromBlock::Number(ref n)) => { - let n = Decode::decode(&mut n.as_ref())?; - BlockId::::Number(n) - } - None => { - let msg = "missing `BlockRequest::from_block` field"; - return Err(io::Error::new(io::ErrorKind::Other, msg).into()) - } - }; - - let max_blocks = - if request.max_blocks == 0 { - self.config.max_block_data_response - } else { - min(request.max_blocks, self.config.max_block_data_response) - }; - - let direction = - if request.direction == api::v1::Direction::Ascending as i32 { - api::v1::Direction::Ascending - } else if request.direction == api::v1::Direction::Descending as i32 { - api::v1::Direction::Descending - } else { - let msg = format!("invalid `BlockRequest::direction` value: {}", request.direction); - return Err(io::Error::new(io::ErrorKind::Other, msg).into()) - }; - - let attributes = BlockAttributes::decode(&mut request.fields.to_be_bytes().as_ref())?; - let get_header = attributes.contains(BlockAttributes::HEADER); - let get_body = attributes.contains(BlockAttributes::BODY); - let get_justification = attributes.contains(BlockAttributes::JUSTIFICATION); - - let mut blocks = Vec::new(); - let mut block_id = from_block_id; - while let Some(header) = self.chain.header(block_id).unwrap_or(None) { - if blocks.len() >= max_blocks as usize { - break - } - - let number = header.number().clone(); - let hash = header.hash(); - let parent_hash = header.parent_hash().clone(); - - let block_data = api::v1::BlockData { - hash: hash.encode(), - header: if get_header { - header.encode() - } else { - Vec::new() - }, - body: if get_body { - self.chain.block_body(&BlockId::Hash(hash))? - .unwrap_or(Vec::new()) - .iter_mut() - .map(|extrinsic| extrinsic.encode()) - .collect() - } else { - Vec::new() - }, - receipt: Vec::new(), - message_queue: Vec::new(), - justification: if get_justification { - self.chain.justification(&BlockId::Hash(hash))?.unwrap_or(Vec::new()) - } else { - Vec::new() - } - }; - - blocks.push(block_data); - - match direction { - api::v1::Direction::Ascending => { - block_id = BlockId::Number(number + One::one()) - } - api::v1::Direction::Descending => { - if number.is_zero() { - break - } - block_id = BlockId::Hash(parent_hash) - } - } - } - - Ok(api::v1::BlockResponse { blocks }) - } -} - -impl NetworkBehaviour for BlockRequests -where - B: Block -{ - type ProtocolsHandler = OneShotHandler>; - type OutEvent = Void; - - fn new_handler(&mut self) -> Self::ProtocolsHandler { - let p = Protocol { - max_request_len: self.config.max_request_len, - protocol: self.config.protocol.clone(), - }; - OneShotHandler::new(SubstreamProtocol::new(p), self.config.inactivity_timeout) - } - - fn addresses_of_peer(&mut self, _: &PeerId) -> Vec { - Vec::new() - } - - fn inject_connected(&mut self, _peer: PeerId, _info: ConnectedPoint) { - } - - fn inject_disconnected(&mut self, _peer: &PeerId, _info: ConnectedPoint) { - } - - fn inject_node_event(&mut self, peer: PeerId, Request(request, mut stream): Request) { - match self.on_block_request(&peer, &request) { - Ok(res) => { - log::trace!("enqueueing block response for peer {} with {} blocks", peer, res.blocks.len()); - let mut data = Vec::with_capacity(res.encoded_len()); - if let Err(e) = res.encode(&mut data) { - log::debug!("error encoding block response for peer {}: {}", peer, e) - } else { - let future = async move { - if let Err(e) = write_one(&mut stream, data).await { - log::debug!("error writing block response: {}", e) - } - }; - self.outgoing.push(future.boxed()) - } - } - Err(e) => log::debug!("error handling block request from peer {}: {}", peer, e) - } - } - - fn poll(&mut self, cx: &mut Context, _: &mut impl PollParameters) -> Poll> { - while let Poll::Ready(Some(_)) = self.outgoing.poll_next_unpin(cx) {} - Poll::Pending - } -} - -/// The incoming block request. -/// -/// Holds the protobuf value and the connection substream which made the -/// request and over which to send the response. -#[derive(Debug)] -pub struct Request(api::v1::BlockRequest, T); - -impl From for Request { - fn from(v: Void) -> Self { - unreachable(v) - } -} - -/// Substream upgrade protocol. -/// -/// We attempt to parse an incoming protobuf encoded request (cf. `Request`) -/// which will be handled by the `BlockRequests` behaviour, i.e. the request -/// will become visible via `inject_node_event` which then dispatches to the -/// relevant callback to process the message and prepare a response. -#[derive(Debug, Clone)] -pub struct Protocol { - /// The max. request length in bytes. - max_request_len: usize, - /// The protocol to use during upgrade negotiation. - protocol: Bytes, -} - -impl UpgradeInfo for Protocol { - type Info = Bytes; - type InfoIter = iter::Once; - - fn protocol_info(&self) -> Self::InfoIter { - iter::once(self.protocol.clone()) - } -} - -impl InboundUpgrade for Protocol -where - T: AsyncRead + AsyncWrite + Unpin + Send + 'static -{ - type Output = Request; - type Error = ReadOneError; - type Future = BoxFuture<'static, Result>; - - fn upgrade_inbound(self, mut s: T, _: Self::Info) -> Self::Future { - let future = async move { - let len = self.max_request_len; - let vec = read_one(&mut s, len).await?; - match api::v1::BlockRequest::decode(&vec[..]) { - Ok(r) => Ok(Request(r, s)), - Err(e) => Err(ReadOneError::Io(io::Error::new(io::ErrorKind::Other, e))) - } - }; - future.boxed() - } -} - diff --git a/client/network/src/protocol/generic_proto.rs b/client/network/src/protocol/generic_proto.rs index f703287f386fdcf9aebcfc8d3fa3d0c5971c7eff..cf8434d8bceffc5140a55d23d4aae1fc4fc4fa43 100644 --- a/client/network/src/protocol/generic_proto.rs +++ b/client/network/src/protocol/generic_proto.rs @@ -21,6 +21,7 @@ //! network, then performs the Substrate protocol handling on top. pub use self::behaviour::{GenericProto, GenericProtoOut}; +pub use self::handler::LegacyConnectionKillError; mod behaviour; mod handler; diff --git a/client/network/src/protocol/generic_proto/behaviour.rs b/client/network/src/protocol/generic_proto/behaviour.rs index c398f6df2d409e93cd774e8b2b2de6dcd048ae18..48b75b6321235114fcafa7d35133128c1837d0c3 100644 --- a/client/network/src/protocol/generic_proto/behaviour.rs +++ b/client/network/src/protocol/generic_proto/behaviour.rs @@ -21,26 +21,34 @@ use crate::protocol::generic_proto::upgrade::RegisteredProtocol; use bytes::BytesMut; use fnv::FnvHashMap; use futures::prelude::*; -use libp2p::core::{ConnectedPoint, Multiaddr, PeerId}; -use libp2p::swarm::{NetworkBehaviour, NetworkBehaviourAction, PollParameters}; +use libp2p::core::{ConnectedPoint, Multiaddr, PeerId, connection::ConnectionId}; +use libp2p::swarm::{ + DialPeerCondition, + NetworkBehaviour, + NetworkBehaviourAction, + NotifyHandler, + PollParameters +}; use log::{debug, error, trace, warn}; +use parking_lot::RwLock; use prometheus_endpoint::HistogramVec; use rand::distributions::{Distribution as _, Uniform}; use smallvec::SmallVec; use std::task::{Context, Poll}; -use std::{borrow::Cow, cmp, collections::hash_map::Entry}; -use std::{error, mem, pin::Pin, str, time::Duration}; +use std::{borrow::Cow, cmp, collections::{hash_map::Entry, VecDeque}}; +use std::{error, mem, pin::Pin, str, sync::Arc, time::Duration}; use wasm_timer::Instant; -/// Network behaviour that handles opening substreams for custom protocols with other nodes. +/// Network behaviour that handles opening substreams for custom protocols with other peers. /// /// ## Legacy vs new protocol /// /// The `GenericProto` behaves as following: /// -/// - Whenever a connection is established, we open a single substream (called "legay protocol" in -/// the source code). This substream name depends on the `protocol_id` and `versions` passed at -/// initialization. If the remote refuses this substream, we close the connection. +/// - Whenever a connection is established, we open a single substream (called "legacy protocol" in +/// the source code) on that connection. This substream name depends on the `protocol_id` and +/// `versions` passed at initialization. If the remote refuses this substream, we close the +/// connection. /// /// - For each registered protocol, we also open an additional substream for this protocol. If the /// remote refuses this substream, then it's fine. @@ -55,34 +63,63 @@ use wasm_timer::Instant; /// /// - The libp2p swarm that opens new connections and reports disconnects. /// - The connection handler (see `handler.rs`) that handles individual connections. -/// - The peerset manager (PSM) that requests links to nodes to be established or broken. +/// - The peerset manager (PSM) that requests links to peers to be established or broken. /// - The external API, that requires knowledge of the links that have been established. /// /// Each connection handler can be in four different states: Enabled+Open, Enabled+Closed, /// Disabled+Open, or Disabled+Closed. The Enabled/Disabled component must be in sync with the /// peerset manager. For example, if the peerset manager requires a disconnection, we disable the -/// existing handler. The Open/Closed component must be in sync with the external API. +/// connection handlers of that peer. The Open/Closed component must be in sync with the external +/// API. /// -/// However a connection handler only exists if we are actually connected to a node. What this -/// means is that there are six possible states for each node: Disconnected, Dialing (trying to -/// reach it), Enabled+Open, Enabled+Closed, Disabled+open, Disabled+Closed. Most notably, the -/// Dialing state must correspond to a "link established" state in the peerset manager. In other -/// words, the peerset manager doesn't differentiate whether we are dialing a node or connected -/// to it. +/// However, a connection handler for a peer only exists if we are actually connected to that peer. +/// What this means is that there are six possible states for each peer: Disconnected, Dialing +/// (trying to connect), Enabled+Open, Enabled+Closed, Disabled+Open, Disabled+Closed. +/// Most notably, the Dialing state must correspond to a "link established" state in the peerset +/// manager. In other words, the peerset manager doesn't differentiate whether we are dialing a +/// peer or connected to it. /// -/// Additionally, there also exists a "banning" system. If we fail to dial a node, we "ban" it for -/// a few seconds. If the PSM requests a node that is in the "banned" state, then we delay the -/// actual dialing attempt until after the ban expires, but the PSM will still consider the link -/// to be established. -/// 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. +/// There may be multiple connections to a peer. However, the status of a peer on +/// the API of this behaviour and towards the peerset manager is aggregated in +/// the following way: +/// +/// 1. The enabled/disabled status is the same across all connections, as +/// decided by the peerset manager. +/// 2. `send_packet` and `write_notification` always send all data over +/// the same connection to preserve the ordering provided by the transport, +/// as long as that connection is open. If it closes, a second open +/// connection may take over, if one exists, but that case should be no +/// different than a single connection failing and being re-established +/// in terms of potential reordering and dropped messages. Messages can +/// be received on any connection. +/// 3. The behaviour reports `GenericProtoOut::CustomProtocolOpen` when the +/// first connection reports `NotifsHandlerOut::Open`. +/// 4. The behaviour reports `GenericProtoOut::CustomProtocolClosed` when the +/// last connection reports `NotifsHandlerOut::Closed`. +/// +/// In this way, the number of actual established connections to the peer is +/// an implementation detail of this behaviour. Note that, in practice and at +/// the time of this writing, there may be at most two connections to a peer +/// and only as a result of simultaneous dialing. However, the implementation +/// accommodates for any number of connections. +/// +/// Additionally, there also exists a "banning" system. If we fail to dial a peer, we "ban" it for +/// a few seconds. If the PSM requests connecting to a peer that is currently "banned", the next +/// dialing attempt is delayed until after the ban expires. However, the PSM will still consider +/// the peer to be connected. This "ban" is thus not a ban in a strict sense: If a "banned" peer +/// tries to connect, the connection is accepted. A ban only delays dialing attempts. /// pub struct GenericProto { + /// `PeerId` of the local node. + local_peer_id: PeerId, + /// Legacy protocol to open with peers. Never modified. legacy_protocol: RegisteredProtocol, /// Notification protocols. Entries are only ever added and not removed. - notif_protocols: Vec<(Cow<'static, [u8]>, Vec)>, + /// Contains, for each protocol, the protocol name and the message to send as part of the + /// initial handshake. + notif_protocols: Vec<(Cow<'static, [u8]>, Arc>>)>, /// Receiver for instructions about who to connect to or disconnect from. peerset: sc_peerset::Peerset, @@ -90,6 +127,18 @@ pub struct GenericProto { /// List of peers in our state. peers: FnvHashMap, + /// The elements in `peers` occasionally contain `Delay` objects that we would normally have + /// to be polled one by one. In order to avoid doing so, as an optimization, every `Delay` is + /// instead put inside of `delays` and reference by a [`DelayId`]. This stream + /// yields `PeerId`s whose `DelayId` is potentially ready. + /// + /// By design, we never remove elements from this list. Elements are removed only when the + /// `Delay` triggers. As such, this stream may produce obsolete elements. + delays: stream::FuturesUnordered + Send>>>, + + /// [`DelayId`] to assign to the next delay. + next_delay_id: DelayId, + /// List of incoming messages we have sent to the peer set manager and that are waiting for an /// answer. incoming: SmallVec<[IncomingPeer; 6]>, @@ -99,12 +148,16 @@ pub struct GenericProto { next_incoming_index: sc_peerset::IncomingIndex, /// Events to produce from `poll()`. - events: SmallVec<[NetworkBehaviourAction; 4]>, + events: VecDeque>, /// If `Some`, report the message queue sizes on this `Histogram`. queue_size_report: Option, } +/// Identifier for a delay firing. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +struct DelayId(u64); + /// State of a peer we're connected to. #[derive(Debug)] enum PeerState { @@ -113,17 +166,17 @@ enum PeerState { /// the state machine code. Poisoned, - /// The peer misbehaved. If the PSM wants us to connect to this node, we will add an artificial + /// The peer misbehaved. If the PSM wants us to connect to this peer, we will add an artificial /// delay to the connection. Banned { - /// Until when the node is banned. + /// Until when the peer is banned. until: Instant, }, - /// The peerset requested that we connect to this peer. We are not connected to this node. + /// The peerset requested that we connect to this peer. We are currently not connected. PendingRequest { - /// When to actually start dialing. - timer: futures_timer::Delay, + /// When to actually start dialing. References an entry in `delays`. + timer: DelayId, /// When the `timer` will trigger. timer_deadline: Instant, }, @@ -131,16 +184,13 @@ enum PeerState { /// The peerset requested that we connect to this peer. We are currently dialing this peer. Requested, - /// We are connected to this peer but the peerset refused it. This peer can still perform - /// Kademlia queries and such, but should get disconnected in a few seconds. + /// We are connected to this peer but the peerset refused it. + /// + /// We may still have ongoing traffic with that peer, but it should cease shortly. Disabled { - /// How we are connected to this peer. - connected_point: ConnectedPoint, - /// If true, we still have a custom protocol open with it. It will likely get closed in - /// a short amount of time, but we need to keep the information in order to not have a - /// state mismatch. - open: bool, - /// If `Some`, the node is banned until the given `Instant`. + /// The connections that are currently open for custom protocol traffic. + open: SmallVec<[ConnectionId; crate::MAX_CONNECTIONS_PER_PEER]>, + /// If `Some`, any dial attempts to this peer are delayed until the given `Instant`. banned_until: Option, }, @@ -148,14 +198,10 @@ enum PeerState { /// will be enabled when `timer` fires. This peer can still perform Kademlia queries and such, /// but should get disconnected in a few seconds. DisabledPendingEnable { - /// How we are connected to this peer. - connected_point: ConnectedPoint, - /// If true, we still have a custom protocol open with it. It will likely get closed in - /// a short amount of time, but we need to keep the information in order to not have a - /// state mismatch. - open: bool, - /// When to enable this remote. - timer: futures_timer::Delay, + /// The connections that are currently open for custom protocol traffic. + open: SmallVec<[ConnectionId; crate::MAX_CONNECTIONS_PER_PEER]>, + /// When to enable this remote. References an entry in `delays`. + timer: DelayId, /// When the `timer` will trigger. timer_deadline: Instant, }, @@ -163,33 +209,41 @@ enum PeerState { /// We are connected to this peer and the peerset has accepted it. The handler is in the /// enabled state. Enabled { - /// How we are connected to this peer. - connected_point: ConnectedPoint, - /// If true, we have a custom protocol open with this peer. - open: bool, + /// The connections that are currently open for custom protocol traffic. + open: SmallVec<[ConnectionId; crate::MAX_CONNECTIONS_PER_PEER]>, }, - /// We are connected to this peer, and we sent an incoming message to the peerset. The handler - /// is in initialization mode. We are waiting for the Accept or Reject from the peerset. There - /// is a corresponding entry in `incoming`. - Incoming { - /// How we are connected to this peer. - connected_point: ConnectedPoint, - }, + /// We received an incoming connection from this peer and forwarded that + /// connection request to the peerset. The connection handlers are waiting + /// for initialisation, i.e. to be enabled or disabled based on whether + /// the peerset accepts or rejects the peer. + Incoming, } impl PeerState { - /// True if we have an open channel with that node. + /// True if there exists an established connection to the peer + /// that is open for custom protocol traffic. fn is_open(&self) -> bool { + self.get_open().is_some() + } + + /// Returns the connection ID of the first established connection + /// that is open for custom protocol traffic. + fn get_open(&self) -> Option { match self { - PeerState::Poisoned => false, - PeerState::Banned { .. } => false, - PeerState::PendingRequest { .. } => false, - PeerState::Requested => false, - PeerState::Disabled { open, .. } => *open, - PeerState::DisabledPendingEnable { open, .. } => *open, - PeerState::Enabled { open, .. } => *open, - PeerState::Incoming { .. } => false, + PeerState::Disabled { open, .. } | + PeerState::DisabledPendingEnable { open, .. } | + PeerState::Enabled { open, .. } => + if !open.is_empty() { + Some(open[0]) + } else { + None + } + PeerState::Poisoned => None, + PeerState::Banned { .. } => None, + PeerState::PendingRequest { .. } => None, + PeerState::Requested => None, + PeerState::Incoming { .. } => None, } } @@ -211,7 +265,7 @@ impl PeerState { /// State of an "incoming" message sent to the peer set manager. #[derive(Debug)] struct IncomingPeer { - /// Id of the node that is concerned. + /// Id of the remote peer of the incoming connection. peer_id: PeerId, /// If true, this "incoming" still corresponds to an actual connection. If false, then the /// connection corresponding to it has been closed or replaced already. @@ -225,10 +279,8 @@ struct IncomingPeer { pub enum GenericProtoOut { /// Opened a custom protocol with the remote. CustomProtocolOpen { - /// Id of the node we have opened a connection with. + /// Id of the peer we are connected to. peer_id: PeerId, - /// Endpoint used for this custom protocol. - endpoint: ConnectedPoint, }, /// Closed a custom protocol with the remote. @@ -275,21 +327,27 @@ impl GenericProto { /// The `queue_size_report` is an optional Prometheus metric that can report the size of the /// messages queue. If passed, it must have one label for the protocol name. pub fn new( + local_peer_id: PeerId, protocol: impl Into, versions: &[u8], + handshake_message: Vec, peerset: sc_peerset::Peerset, queue_size_report: Option, ) -> Self { - let legacy_protocol = RegisteredProtocol::new(protocol, versions); + let legacy_handshake_message = Arc::new(RwLock::new(handshake_message)); + let legacy_protocol = RegisteredProtocol::new(protocol, versions, legacy_handshake_message); GenericProto { + local_peer_id, legacy_protocol, notif_protocols: Vec::new(), peerset, peers: FnvHashMap::default(), + delays: Default::default(), + next_delay_id: DelayId(0), incoming: SmallVec::new(), next_incoming_index: sc_peerset::IncomingIndex(0), - events: SmallVec::new(), + events: VecDeque::new(), queue_size_report, } } @@ -303,7 +361,28 @@ impl GenericProto { protocol_name: impl Into>, handshake_msg: impl Into> ) { - self.notif_protocols.push((protocol_name.into(), handshake_msg.into())); + self.notif_protocols.push((protocol_name.into(), Arc::new(RwLock::new(handshake_msg.into())))); + } + + /// Modifies the handshake of the given notifications protocol. + /// + /// Has no effect if the protocol is unknown. + pub fn set_notif_protocol_handshake( + &mut self, + protocol_name: &[u8], + handshake_message: impl Into> + ) { + if let Some(protocol) = self.notif_protocols.iter_mut().find(|(name, _)| name == &protocol_name) { + *protocol.1.write() = handshake_message.into(); + } + } + + /// Modifies the handshake of the legacy protocol. + pub fn set_legacy_handshake_message( + &mut self, + handshake_message: impl Into> + ) { + *self.legacy_protocol.handshake_message().write() = handshake_message.into(); } /// Returns the number of discovered nodes that we keep in memory. @@ -316,7 +395,7 @@ impl GenericProto { self.peers.iter().filter(|(_, state)| state.is_open()).map(|(id, _)| id) } - /// Returns true if we have a channel open with this node. + /// Returns true if we have an open connection to the given peer. pub fn is_open(&self, peer_id: &PeerId) -> bool { self.peers.get(peer_id).map(|p| p.is_open()).unwrap_or(false) } @@ -327,8 +406,8 @@ impl GenericProto { self.disconnect_peer_inner(peer_id, None); } - /// Inner implementation of `disconnect_peer`. If `ban` is `Some`, we ban the node for the - /// specific duration. + /// Inner implementation of `disconnect_peer`. If `ban` is `Some`, we ban the peer + /// for the specific duration. fn disconnect_peer_inner(&mut self, peer_id: &PeerId, ban: Option) { let mut entry = if let Entry::Occupied(entry) = self.peers.entry(peer_id.clone()) { entry @@ -344,7 +423,11 @@ impl GenericProto { st @ PeerState::Banned { .. } => *entry.into_mut() = st, // DisabledPendingEnable => Disabled. - PeerState::DisabledPendingEnable { open, connected_point, timer_deadline, .. } => { + PeerState::DisabledPendingEnable { + open, + timer_deadline, + timer: _ + } => { debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", peer_id); self.peerset.dropped(peer_id.clone()); let banned_until = Some(if let Some(ban) = ban { @@ -352,24 +435,31 @@ impl GenericProto { } else { timer_deadline }); - *entry.into_mut() = PeerState::Disabled { open, connected_point, banned_until } + *entry.into_mut() = PeerState::Disabled { + open, + banned_until + } }, // Enabled => Disabled. - PeerState::Enabled { open, connected_point } => { + PeerState::Enabled { open } => { debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", peer_id); self.peerset.dropped(peer_id.clone()); debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", peer_id); - self.events.push(NetworkBehaviourAction::SendEvent { + self.events.push_back(NetworkBehaviourAction::NotifyHandler { peer_id: peer_id.clone(), + handler: NotifyHandler::All, event: NotifsHandlerIn::Disable, }); let banned_until = ban.map(|dur| Instant::now() + dur); - *entry.into_mut() = PeerState::Disabled { open, connected_point, banned_until } + *entry.into_mut() = PeerState::Disabled { + open, + banned_until + } }, // Incoming => Disabled. - PeerState::Incoming { connected_point, .. } => { + PeerState::Incoming => { let inc = if let Some(inc) = self.incoming.iter_mut() .find(|i| i.peer_id == *entry.key() && i.alive) { inc @@ -381,12 +471,16 @@ impl GenericProto { inc.alive = false; debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", peer_id); - self.events.push(NetworkBehaviourAction::SendEvent { + self.events.push_back(NetworkBehaviourAction::NotifyHandler { peer_id: peer_id.clone(), + handler: NotifyHandler::All, event: NotifsHandlerIn::Disable, }); let banned_until = ban.map(|dur| Instant::now() + dur); - *entry.into_mut() = PeerState::Disabled { open: false, connected_point, banned_until } + *entry.into_mut() = PeerState::Disabled { + open: SmallVec::new(), + banned_until + } }, PeerState::Poisoned => @@ -418,9 +512,18 @@ impl GenericProto { /// /// Can be called multiple times with the same `PeerId`s. pub fn add_discovered_nodes(&mut self, peer_ids: impl Iterator) { - self.peerset.discovered(peer_ids.into_iter().map(|peer_id| { + let local_peer_id = &self.local_peer_id; + self.peerset.discovered(peer_ids.filter_map(|peer_id| { + if peer_id == *local_peer_id { + error!( + target: "sub-libp2p", + "Discovered our own identity. This is a minor inconsequential bug." + ); + return None; + } + debug!(target: "sub-libp2p", "PSM <= Discovered({:?})", peer_id); - peer_id + Some(peer_id) })); } @@ -441,9 +544,15 @@ impl GenericProto { message: impl Into>, encoded_fallback_message: Vec, ) { - if !self.is_open(target) { - return; - } + let conn = match self.peers.get(target).and_then(|p| p.get_open()) { + None => { + debug!(target: "sub-libp2p", + "Tried to sent notification to {:?} without an open channel.", + target); + return + }, + Some(conn) => conn + }; trace!( target: "sub-libp2p", @@ -453,8 +562,9 @@ impl GenericProto { ); trace!(target: "sub-libp2p", "Handler({:?}) <= Packet", target); - self.events.push(NetworkBehaviourAction::SendEvent { + self.events.push_back(NetworkBehaviourAction::NotifyHandler { peer_id: target.clone(), + handler: NotifyHandler::One(conn), event: NotifsHandlerIn::SendNotification { message: message.into(), encoded_fallback_message, @@ -470,14 +580,21 @@ impl GenericProto { /// 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: Vec) { - if !self.is_open(target) { - return; - } + let conn = match self.peers.get(target).and_then(|p| p.get_open()) { + None => { + debug!(target: "sub-libp2p", + "Tried to sent packet to {:?} without an open channel.", + target); + return + } + Some(conn) => conn + }; trace!(target: "sub-libp2p", "External API => Packet for {:?}", target); trace!(target: "sub-libp2p", "Handler({:?}) <= Packet", target); - self.events.push(NetworkBehaviourAction::SendEvent { + self.events.push_back(NetworkBehaviourAction::NotifyHandler { peer_id: target.clone(), + handler: NotifyHandler::One(conn), event: NotifsHandlerIn::SendLegacy { message, } @@ -489,7 +606,7 @@ impl GenericProto { self.peerset.debug_info() } - /// Function that is called when the peerset wants us to connect to a node. + /// Function that is called when the peerset wants us to connect to a peer. fn peerset_report_connect(&mut self, peer_id: PeerId) { let mut occ_entry = match self.peers.entry(peer_id) { Entry::Occupied(entry) => entry, @@ -497,7 +614,10 @@ impl GenericProto { // If there's no entry in `self.peers`, start dialing. debug!(target: "sub-libp2p", "PSM => Connect({:?}): Starting to connect", entry.key()); debug!(target: "sub-libp2p", "Libp2p <= Dial {:?}", entry.key()); - self.events.push(NetworkBehaviourAction::DialPeer { peer_id: entry.key().clone() }); + self.events.push_back(NetworkBehaviourAction::DialPeer { + peer_id: entry.key().clone(), + condition: DialPeerCondition::Disconnected + }); entry.insert(PeerState::Requested); return; } @@ -507,47 +627,72 @@ impl GenericProto { match mem::replace(occ_entry.get_mut(), PeerState::Poisoned) { PeerState::Banned { ref until } if *until > now => { + let peer_id = occ_entry.key().clone(); debug!(target: "sub-libp2p", "PSM => Connect({:?}): Will start to connect at \ - until {:?}", occ_entry.key(), until); + until {:?}", peer_id, until); + + let delay_id = self.next_delay_id; + self.next_delay_id.0 += 1; + let delay = futures_timer::Delay::new(*until - now); + self.delays.push(async move { + delay.await; + (delay_id, peer_id) + }.boxed()); + *occ_entry.into_mut() = PeerState::PendingRequest { - timer: futures_timer::Delay::new(until.clone() - now), - timer_deadline: until.clone(), + timer: delay_id, + timer_deadline: *until, }; }, PeerState::Banned { .. } => { debug!(target: "sub-libp2p", "PSM => Connect({:?}): Starting to connect", occ_entry.key()); debug!(target: "sub-libp2p", "Libp2p <= Dial {:?}", occ_entry.key()); - self.events.push(NetworkBehaviourAction::DialPeer { peer_id: occ_entry.key().clone() }); + self.events.push_back(NetworkBehaviourAction::DialPeer { + peer_id: occ_entry.key().clone(), + condition: DialPeerCondition::Disconnected + }); *occ_entry.into_mut() = PeerState::Requested; }, - PeerState::Disabled { open, ref connected_point, banned_until: Some(ref banned) } - if *banned > now => { - debug!(target: "sub-libp2p", "PSM => Connect({:?}): Has idle connection through \ - {:?} but node is banned until {:?}", occ_entry.key(), connected_point, banned); + PeerState::Disabled { + open, + banned_until: Some(ref banned) + } if *banned > now => { + let peer_id = occ_entry.key().clone(); + debug!(target: "sub-libp2p", "PSM => Connect({:?}): But peer is banned until {:?}", + peer_id, banned); + + let delay_id = self.next_delay_id; + self.next_delay_id.0 += 1; + let delay = futures_timer::Delay::new(*banned - now); + self.delays.push(async move { + delay.await; + (delay_id, peer_id) + }.boxed()); + *occ_entry.into_mut() = PeerState::DisabledPendingEnable { - connected_point: connected_point.clone(), open, - timer: futures_timer::Delay::new(banned.clone() - now), - timer_deadline: banned.clone(), + timer: delay_id, + timer_deadline: *banned, }; }, - PeerState::Disabled { open, connected_point, banned_until: _ } => { - debug!(target: "sub-libp2p", "PSM => Connect({:?}): Enabling previously-idle \ - connection through {:?}", occ_entry.key(), connected_point); + PeerState::Disabled { open, banned_until: _ } => { + debug!(target: "sub-libp2p", "PSM => Connect({:?}): Enabling connections.", + occ_entry.key()); debug!(target: "sub-libp2p", "Handler({:?}) <= Enable", occ_entry.key()); - self.events.push(NetworkBehaviourAction::SendEvent { + self.events.push_back(NetworkBehaviourAction::NotifyHandler { peer_id: occ_entry.key().clone(), + handler: NotifyHandler::All, event: NotifsHandlerIn::Enable, }); - *occ_entry.into_mut() = PeerState::Enabled { connected_point, open }; + *occ_entry.into_mut() = PeerState::Enabled { open }; }, - PeerState::Incoming { connected_point, .. } => { - debug!(target: "sub-libp2p", "PSM => Connect({:?}): Enabling incoming \ - connection through {:?}", occ_entry.key(), connected_point); + PeerState::Incoming => { + debug!(target: "sub-libp2p", "PSM => Connect({:?}): Enabling connections.", + occ_entry.key()); if let Some(inc) = self.incoming.iter_mut() .find(|i| i.peer_id == *occ_entry.key() && i.alive) { inc.alive = false; @@ -556,26 +701,30 @@ impl GenericProto { incoming for incoming peer") } debug!(target: "sub-libp2p", "Handler({:?}) <= Enable", occ_entry.key()); - self.events.push(NetworkBehaviourAction::SendEvent { + self.events.push_back(NetworkBehaviourAction::NotifyHandler { peer_id: occ_entry.key().clone(), + handler: NotifyHandler::All, event: NotifsHandlerIn::Enable, }); - *occ_entry.into_mut() = PeerState::Enabled { connected_point, open: false }; + *occ_entry.into_mut() = PeerState::Enabled { open: SmallVec::new() }; }, st @ PeerState::Enabled { .. } => { - warn!(target: "sub-libp2p", "PSM => Connect({:?}): Already connected to this \ - peer", occ_entry.key()); + warn!(target: "sub-libp2p", + "PSM => Connect({:?}): Already connected.", + occ_entry.key()); *occ_entry.into_mut() = st; }, st @ PeerState::DisabledPendingEnable { .. } => { - warn!(target: "sub-libp2p", "PSM => Connect({:?}): Already have an idle \ - connection to this peer and waiting to enable it", occ_entry.key()); + warn!(target: "sub-libp2p", + "PSM => Connect({:?}): Already pending enabling.", + occ_entry.key()); *occ_entry.into_mut() = st; }, st @ PeerState::Requested { .. } | st @ PeerState::PendingRequest { .. } => { - warn!(target: "sub-libp2p", "PSM => Connect({:?}): Received a previous \ - request for that peer", occ_entry.key()); + warn!(target: "sub-libp2p", + "PSM => Connect({:?}): Duplicate request.", + occ_entry.key()); *occ_entry.into_mut() = st; }, @@ -584,55 +733,63 @@ impl GenericProto { } } - /// Function that is called when the peerset wants us to disconnect from a node. + /// Function that is called when the peerset wants us to disconnect from a peer. fn peerset_report_disconnect(&mut self, peer_id: PeerId) { let mut entry = match self.peers.entry(peer_id) { Entry::Occupied(entry) => entry, Entry::Vacant(entry) => { - debug!(target: "sub-libp2p", "PSM => Drop({:?}): Node already disabled", entry.key()); + debug!(target: "sub-libp2p", "PSM => Drop({:?}): Already disabled.", entry.key()); return } }; match mem::replace(entry.get_mut(), PeerState::Poisoned) { st @ PeerState::Disabled { .. } | st @ PeerState::Banned { .. } => { - debug!(target: "sub-libp2p", "PSM => Drop({:?}): Node already disabled", entry.key()); + debug!(target: "sub-libp2p", "PSM => Drop({:?}): Already disabled.", entry.key()); *entry.into_mut() = st; }, - PeerState::DisabledPendingEnable { open, connected_point, timer_deadline, .. } => { - debug!(target: "sub-libp2p", "PSM => Drop({:?}): Interrupting pending \ - enable", entry.key()); + PeerState::DisabledPendingEnable { + open, + timer_deadline, + timer: _ + } => { + debug!(target: "sub-libp2p", + "PSM => Drop({:?}): Interrupting pending enabling.", + entry.key()); *entry.into_mut() = PeerState::Disabled { open, - connected_point, banned_until: Some(timer_deadline), }; }, - PeerState::Enabled { open, connected_point } => { - debug!(target: "sub-libp2p", "PSM => Drop({:?}): Disabling connection", entry.key()); + PeerState::Enabled { open } => { + debug!(target: "sub-libp2p", "PSM => Drop({:?}): Disabling connections.", entry.key()); debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", entry.key()); - self.events.push(NetworkBehaviourAction::SendEvent { + self.events.push_back(NetworkBehaviourAction::NotifyHandler { peer_id: entry.key().clone(), + handler: NotifyHandler::All, event: NotifsHandlerIn::Disable, }); - *entry.into_mut() = PeerState::Disabled { open, connected_point, banned_until: None } + *entry.into_mut() = PeerState::Disabled { + open, + banned_until: None + } }, - st @ PeerState::Incoming { .. } => { - error!(target: "sub-libp2p", "PSM => Drop({:?}): Was in incoming mode", + st @ PeerState::Incoming => { + error!(target: "sub-libp2p", "PSM => Drop({:?}): Not enabled (Incoming).", entry.key()); *entry.into_mut() = st; }, PeerState::Requested => { // We don't cancel dialing. Libp2p doesn't expose that on purpose, as other - // sub-systems (such as the discovery mechanism) may require dialing this node as + // sub-systems (such as the discovery mechanism) may require dialing this peer as // well at the same time. - debug!(target: "sub-libp2p", "PSM => Drop({:?}): Was not yet connected", entry.key()); + debug!(target: "sub-libp2p", "PSM => Drop({:?}): Not yet connected.", entry.key()); entry.remove(); }, PeerState::PendingRequest { timer_deadline, .. } => { - debug!(target: "sub-libp2p", "PSM => Drop({:?}): Was not yet connected", entry.key()); + debug!(target: "sub-libp2p", "PSM => Drop({:?}): Not yet connected", entry.key()); *entry.into_mut() = PeerState::Banned { until: timer_deadline } }, @@ -641,7 +798,8 @@ impl GenericProto { } } - /// Function that is called when the peerset wants us to accept an incoming node. + /// Function that is called when the peerset wants us to accept a connection + /// request from a peer. fn peerset_report_accept(&mut self, index: sc_peerset::IncomingIndex) { let incoming = if let Some(pos) = self.incoming.iter().position(|i| i.incoming_id == index) { self.incoming.remove(pos) @@ -658,34 +816,25 @@ impl GenericProto { return } - let state = if let Some(state) = self.peers.get_mut(&incoming.peer_id) { - state - } else { - error!(target: "sub-libp2p", "State mismatch in libp2p: no entry in peers \ - corresponding to an alive incoming"); - return - }; - - let connected_point = if let PeerState::Incoming { connected_point } = state { - connected_point.clone() - } else { - error!(target: "sub-libp2p", "State mismatch in libp2p: entry in peers corresponding \ - to an alive incoming is not in incoming state"); - return - }; - - debug!(target: "sub-libp2p", "PSM => Accept({:?}, {:?}): Enabling connection \ - through {:?}", index, incoming.peer_id, connected_point); - debug!(target: "sub-libp2p", "Handler({:?}) <= Enable", incoming.peer_id); - self.events.push(NetworkBehaviourAction::SendEvent { - peer_id: incoming.peer_id, - event: NotifsHandlerIn::Enable, - }); - - *state = PeerState::Enabled { open: false, connected_point }; + match self.peers.get_mut(&incoming.peer_id) { + Some(state @ PeerState::Incoming) => { + debug!(target: "sub-libp2p", "PSM => Accept({:?}, {:?}): Enabling connections.", + index, incoming.peer_id); + debug!(target: "sub-libp2p", "Handler({:?}) <= Enable", incoming.peer_id); + self.events.push_back(NetworkBehaviourAction::NotifyHandler { + peer_id: incoming.peer_id, + handler: NotifyHandler::All, + event: NotifsHandlerIn::Enable, + }); + *state = PeerState::Enabled { open: SmallVec::new() }; + } + peer => error!(target: "sub-libp2p", + "State mismatch in libp2p: Expected alive incoming. Got {:?}.", + peer) + } } - /// Function that is called when the peerset wants us to reject an incoming node. + /// Function that is called when the peerset wants us to reject an incoming peer. fn peerset_report_reject(&mut self, index: sc_peerset::IncomingIndex) { let incoming = if let Some(pos) = self.incoming.iter().position(|i| i.incoming_id == index) { self.incoming.remove(pos) @@ -695,35 +844,30 @@ impl GenericProto { }; if !incoming.alive { - error!(target: "sub-libp2p", "PSM => Reject({:?}, {:?}): Obsolete incoming, \ + debug!(target: "sub-libp2p", "PSM => Reject({:?}, {:?}): Obsolete incoming, \ ignoring", index, incoming.peer_id); return } - let state = if let Some(state) = self.peers.get_mut(&incoming.peer_id) { - state - } else { - error!(target: "sub-libp2p", "State mismatch in libp2p: no entry in peers \ - corresponding to an alive incoming"); - return - }; - - let connected_point = if let PeerState::Incoming { connected_point } = state { - connected_point.clone() - } else { - error!(target: "sub-libp2p", "State mismatch in libp2p: entry in peers corresponding \ - to an alive incoming is not in incoming state"); - return - }; - - debug!(target: "sub-libp2p", "PSM => Reject({:?}, {:?}): Rejecting connection through \ - {:?}", index, incoming.peer_id, connected_point); - debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", incoming.peer_id); - self.events.push(NetworkBehaviourAction::SendEvent { - peer_id: incoming.peer_id, - event: NotifsHandlerIn::Disable, - }); - *state = PeerState::Disabled { open: false, connected_point, banned_until: None }; + match self.peers.get_mut(&incoming.peer_id) { + Some(state @ PeerState::Incoming) => { + debug!(target: "sub-libp2p", "PSM => Reject({:?}, {:?}): Rejecting connections.", + index, incoming.peer_id); + debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", incoming.peer_id); + self.events.push_back(NetworkBehaviourAction::NotifyHandler { + peer_id: incoming.peer_id, + handler: NotifyHandler::All, + event: NotifsHandlerIn::Disable, + }); + *state = PeerState::Disabled { + open: SmallVec::new(), + banned_until: None + }; + } + peer => error!(target: "sub-libp2p", + "State mismatch in libp2p: Expected alive incoming. Got {:?}.", + peer) + } } } @@ -743,27 +887,33 @@ impl NetworkBehaviour for GenericProto { Vec::new() } - fn inject_connected(&mut self, peer_id: PeerId, connected_point: ConnectedPoint) { - match (self.peers.entry(peer_id.clone()).or_insert(PeerState::Poisoned), connected_point) { - (st @ &mut PeerState::Requested, connected_point) | - (st @ &mut PeerState::PendingRequest { .. }, connected_point) => { - debug!(target: "sub-libp2p", "Libp2p => Connected({:?}): Connection \ - requested by PSM (through {:?})", peer_id, connected_point + fn inject_connected(&mut self, _: &PeerId) { + } + + fn inject_connection_established(&mut self, peer_id: &PeerId, conn: &ConnectionId, endpoint: &ConnectedPoint) { + debug!(target: "sub-libp2p", "Libp2p => Connection ({:?},{:?}) to {} established.", + conn, endpoint, peer_id); + match (self.peers.entry(peer_id.clone()).or_insert(PeerState::Poisoned), endpoint) { + (st @ &mut PeerState::Requested, endpoint) | + (st @ &mut PeerState::PendingRequest { .. }, endpoint) => { + debug!(target: "sub-libp2p", + "Libp2p => Connected({}, {:?}): Connection was requested by PSM.", + peer_id, endpoint ); - debug!(target: "sub-libp2p", "Handler({:?}) <= Enable", peer_id); - self.events.push(NetworkBehaviourAction::SendEvent { + *st = PeerState::Enabled { open: SmallVec::new() }; + self.events.push_back(NetworkBehaviourAction::NotifyHandler { peer_id: peer_id.clone(), - event: NotifsHandlerIn::Enable, + handler: NotifyHandler::One(*conn), + event: NotifsHandlerIn::Enable }); - *st = PeerState::Enabled { open: false, connected_point }; } - // Note: it may seem weird that "Banned" nodes get treated as if there were absent. + // Note: it may seem weird that "Banned" peers get treated as if they were absent. // This is because the word "Banned" means "temporarily prevent outgoing connections to - // this node", and not "banned" in the sense that we would refuse the node altogether. - (st @ &mut PeerState::Poisoned, connected_point @ ConnectedPoint::Listener { .. }) | - (st @ &mut PeerState::Banned { .. }, connected_point @ ConnectedPoint::Listener { .. }) => { - let incoming_id = self.next_incoming_index.clone(); + // this peer", and not "banned" in the sense that we would refuse the peer altogether. + (st @ &mut PeerState::Poisoned, endpoint @ ConnectedPoint::Listener { .. }) | + (st @ &mut PeerState::Banned { .. }, endpoint @ ConnectedPoint::Listener { .. }) => { + let incoming_id = self.next_incoming_index; self.next_incoming_index.0 = match self.next_incoming_index.0.checked_add(1) { Some(v) => v, None => { @@ -771,115 +921,159 @@ impl NetworkBehaviour for GenericProto { return } }; - debug!(target: "sub-libp2p", "Libp2p => Connected({:?}): Incoming connection", - peer_id); - debug!(target: "sub-libp2p", "PSM <= Incoming({:?}, {:?}): Through {:?}", - incoming_id, peer_id, connected_point); + debug!(target: "sub-libp2p", "Libp2p => Connected({}, {:?}): Incoming connection", + peer_id, endpoint); + debug!(target: "sub-libp2p", "PSM <= Incoming({}, {:?}).", + peer_id, incoming_id); self.peerset.incoming(peer_id.clone(), incoming_id); self.incoming.push(IncomingPeer { peer_id: peer_id.clone(), alive: true, incoming_id, }); - *st = PeerState::Incoming { connected_point }; + *st = PeerState::Incoming { }; } - (st @ &mut PeerState::Poisoned, connected_point) | - (st @ &mut PeerState::Banned { .. }, connected_point) => { + (st @ &mut PeerState::Poisoned, endpoint) | + (st @ &mut PeerState::Banned { .. }, endpoint) => { let banned_until = if let PeerState::Banned { until } = st { Some(*until) } else { None }; - debug!(target: "sub-libp2p", "Libp2p => Connected({:?}): Requested by something \ - else than PSM, disabling", peer_id); - debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", peer_id); - self.events.push(NetworkBehaviourAction::SendEvent { + debug!(target: "sub-libp2p", + "Libp2p => Connected({},{:?}): Not requested by PSM, disabling.", + peer_id, endpoint); + *st = PeerState::Disabled { open: SmallVec::new(), banned_until }; + self.events.push_back(NetworkBehaviourAction::NotifyHandler { peer_id: peer_id.clone(), - event: NotifsHandlerIn::Disable, + handler: NotifyHandler::One(*conn), + event: NotifsHandlerIn::Disable }); - *st = PeerState::Disabled { open: false, connected_point, banned_until }; } - st => { - // This is a serious bug either in this state machine or in libp2p. - error!(target: "sub-libp2p", "Received inject_connected for \ - already-connected node; state is {:?}", st - ); + (PeerState::Incoming { .. }, _) => { + debug!(target: "sub-libp2p", + "Secondary connection {:?} to {} waiting for PSM decision.", + conn, peer_id); + }, + + (PeerState::Enabled { .. }, _) => { + debug!(target: "sub-libp2p", "Handler({},{:?}) <= Enable secondary connection", + peer_id, conn); + self.events.push_back(NetworkBehaviourAction::NotifyHandler { + peer_id: peer_id.clone(), + handler: NotifyHandler::One(*conn), + event: NotifsHandlerIn::Enable + }); + } + + (PeerState::Disabled { .. }, _) | (PeerState::DisabledPendingEnable { .. }, _) => { + debug!(target: "sub-libp2p", "Handler({},{:?}) <= Disable secondary connection", + peer_id, conn); + self.events.push_back(NetworkBehaviourAction::NotifyHandler { + peer_id: peer_id.clone(), + handler: NotifyHandler::One(*conn), + event: NotifsHandlerIn::Disable + }); } } } - fn inject_disconnected(&mut self, peer_id: &PeerId, endpoint: ConnectedPoint) { + fn inject_connection_closed(&mut self, peer_id: &PeerId, conn: &ConnectionId, endpoint: &ConnectedPoint) { + debug!(target: "sub-libp2p", "Libp2p => Connection ({:?},{:?}) to {} closed.", + conn, endpoint, peer_id); + match self.peers.get_mut(peer_id) { + Some(PeerState::Disabled { open, .. }) | + Some(PeerState::DisabledPendingEnable { open, .. }) | + Some(PeerState::Enabled { open, .. }) => { + // Check if the "link" to the peer is already considered closed, + // i.e. there is no connection that is open for custom protocols, + // in which case `CustomProtocolClosed` was already emitted. + let closed = open.is_empty(); + open.retain(|c| c != conn); + if open.is_empty() && !closed { + debug!(target: "sub-libp2p", "External API <= Closed({})", peer_id); + let event = GenericProtoOut::CustomProtocolClosed { + peer_id: peer_id.clone(), + reason: "Disconnected by libp2p".into(), + }; + + self.events.push_back(NetworkBehaviourAction::GenerateEvent(event)); + } + } + _ => {} + } + } + + fn inject_disconnected(&mut self, peer_id: &PeerId) { match self.peers.remove(peer_id) { None | Some(PeerState::Requested) | Some(PeerState::PendingRequest { .. }) | Some(PeerState::Banned { .. }) => // This is a serious bug either in this state machine or in libp2p. - error!(target: "sub-libp2p", "Received inject_disconnected for non-connected \ - node {:?}", peer_id), + error!(target: "sub-libp2p", + "`inject_disconnected` called for unknown peer {}", + peer_id), Some(PeerState::Disabled { open, banned_until, .. }) => { - debug!(target: "sub-libp2p", "Libp2p => Disconnected({:?}): Was disabled \ - (through {:?})", peer_id, endpoint); + if !open.is_empty() { + debug_assert!(false); + error!( + target: "sub-libp2p", + "State mismatch: disconnected from {} with non-empty list of connections", + peer_id + ); + } + debug!(target: "sub-libp2p", "Libp2p => Disconnected({}): Was disabled.", peer_id); if let Some(until) = banned_until { self.peers.insert(peer_id.clone(), PeerState::Banned { until }); } - if open { - debug!(target: "sub-libp2p", "External API <= Closed({:?})", peer_id); - let event = GenericProtoOut::CustomProtocolClosed { - peer_id: peer_id.clone(), - reason: "Disconnected by libp2p".into(), - }; - - self.events.push(NetworkBehaviourAction::GenerateEvent(event)); - } } Some(PeerState::DisabledPendingEnable { open, timer_deadline, .. }) => { - debug!(target: "sub-libp2p", "Libp2p => Disconnected({:?}): Was disabled \ - (through {:?}) but pending enable", peer_id, endpoint); - debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", peer_id); + if !open.is_empty() { + debug_assert!(false); + error!( + target: "sub-libp2p", + "State mismatch: disconnected from {} with non-empty list of connections", + peer_id + ); + } + debug!(target: "sub-libp2p", + "Libp2p => Disconnected({}): Was disabled but pending enable.", + peer_id); + debug!(target: "sub-libp2p", "PSM <= Dropped({})", peer_id); self.peerset.dropped(peer_id.clone()); self.peers.insert(peer_id.clone(), PeerState::Banned { until: timer_deadline }); - if open { - debug!(target: "sub-libp2p", "External API <= Closed({:?})", peer_id); - let event = GenericProtoOut::CustomProtocolClosed { - peer_id: peer_id.clone(), - reason: "Disconnected by libp2p".into(), - }; - - self.events.push(NetworkBehaviourAction::GenerateEvent(event)); - } } Some(PeerState::Enabled { open, .. }) => { - debug!(target: "sub-libp2p", "Libp2p => Disconnected({:?}): Was enabled \ - (through {:?})", peer_id, endpoint); - debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", peer_id); + if !open.is_empty() { + debug_assert!(false); + error!( + target: "sub-libp2p", + "State mismatch: disconnected from {} with non-empty list of connections", + peer_id + ); + } + debug!(target: "sub-libp2p", "Libp2p => Disconnected({}): Was enabled.", peer_id); + debug!(target: "sub-libp2p", "PSM <= Dropped({})", peer_id); self.peerset.dropped(peer_id.clone()); - let ban_dur = Uniform::new(5, 10).sample(&mut rand::thread_rng()); self.peers.insert(peer_id.clone(), PeerState::Banned { until: Instant::now() + Duration::from_secs(ban_dur) }); - - if open { - debug!(target: "sub-libp2p", "External API <= Closed({:?})", peer_id); - let event = GenericProtoOut::CustomProtocolClosed { - peer_id: peer_id.clone(), - reason: "Disconnected by libp2p".into(), - }; - - self.events.push(NetworkBehaviourAction::GenerateEvent(event)); - } } // In the incoming state, we don't report "Dropped". Instead we will just ignore the // corresponding Accept/Reject. - Some(PeerState::Incoming { .. }) => { - if let Some(state) = self.incoming.iter_mut().find(|i| i.peer_id == *peer_id) { - debug!(target: "sub-libp2p", "Libp2p => Disconnected({:?}): Was in incoming \ - mode (id {:?}, through {:?})", peer_id, state.incoming_id, endpoint); + Some(PeerState::Incoming { }) => { + if let Some(state) = self.incoming.iter_mut() + .find(|i| i.alive && i.peer_id == *peer_id) + { + debug!(target: "sub-libp2p", + "Libp2p => Disconnected({}): Was in incoming mode with id {:?}.", + peer_id, state.incoming_id); state.alive = false; } else { error!(target: "sub-libp2p", "State mismatch in libp2p: no entry in incoming \ @@ -888,7 +1082,7 @@ impl NetworkBehaviour for GenericProto { } Some(PeerState::Poisoned) => - error!(target: "sub-libp2p", "State of {:?} is poisoned", peer_id), + error!(target: "sub-libp2p", "State of peer {} is poisoned", peer_id), } } @@ -899,13 +1093,13 @@ impl NetworkBehaviour for GenericProto { fn inject_dial_failure(&mut self, peer_id: &PeerId) { if let Entry::Occupied(mut entry) = self.peers.entry(peer_id.clone()) { match mem::replace(entry.get_mut(), PeerState::Poisoned) { - // The node is not in our list. + // The peer is not in our list. st @ PeerState::Banned { .. } => { trace!(target: "sub-libp2p", "Libp2p => Dial failure for {:?}", peer_id); *entry.into_mut() = st; }, - // "Basic" situation: we failed to reach a node that the peerset requested. + // "Basic" situation: we failed to reach a peer that the peerset requested. PeerState::Requested | PeerState::PendingRequest { .. } => { debug!(target: "sub-libp2p", "Libp2p => Dial failure for {:?}", peer_id); *entry.into_mut() = PeerState::Banned { @@ -915,7 +1109,7 @@ impl NetworkBehaviour for GenericProto { self.peerset.dropped(peer_id.clone()) }, - // We can still get dial failures even if we are already connected to the node, + // We can still get dial failures even if we are already connected to the peer, // as an extra diagnostic for an earlier attempt. st @ PeerState::Disabled { .. } | st @ PeerState::Enabled { .. } | st @ PeerState::DisabledPendingEnable { .. } | st @ PeerState::Incoming { .. } => { @@ -928,92 +1122,164 @@ impl NetworkBehaviour for GenericProto { } } else { - // The node is not in our list. + // The peer is not in our list. trace!(target: "sub-libp2p", "Libp2p => Dial failure for {:?}", peer_id); } } - fn inject_node_event( + fn inject_event( &mut self, source: PeerId, + connection: ConnectionId, event: NotifsHandlerOut, ) { match event { - NotifsHandlerOut::Closed { reason } => { - debug!(target: "sub-libp2p", "Handler({:?}) => Closed: {}", source, reason); + NotifsHandlerOut::Closed { endpoint, reason } => { + debug!(target: "sub-libp2p", + "Handler({:?}) => Endpoint {:?} closed for custom protocols: {}", + source, endpoint, reason); let mut entry = if let Entry::Occupied(entry) = self.peers.entry(source.clone()) { entry } else { - error!(target: "sub-libp2p", "State mismatch in the custom protos handler"); + error!(target: "sub-libp2p", "Closed: State mismatch in the custom protos handler"); return }; - debug!(target: "sub-libp2p", "External API <= Closed({:?})", source); - let event = GenericProtoOut::CustomProtocolClosed { - reason, - peer_id: source.clone(), - }; - self.events.push(NetworkBehaviourAction::GenerateEvent(event)); - - match mem::replace(entry.get_mut(), PeerState::Poisoned) { - PeerState::Enabled { open, connected_point } => { - debug_assert!(open); - + let last = match mem::replace(entry.get_mut(), PeerState::Poisoned) { + PeerState::Enabled { mut open } => { + if let Some(pos) = open.iter().position(|c| c == &connection) { + open.remove(pos); + } else { + debug_assert!(false); + error!( + target: "sub-libp2p", + "State mismatch with {}: unknown closed connection", + source + ); + } + + // TODO: We switch the entire peer state to "disabled" because of possible + // race conditions involving the legacy substream. + // Once https://github.com/paritytech/substrate/issues/5670 is done, this + // should be changed to stay in the `Enabled` state. + debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", source); debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", source); self.peerset.dropped(source.clone()); - - debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", source); - self.events.push(NetworkBehaviourAction::SendEvent { + self.events.push_back(NetworkBehaviourAction::NotifyHandler { peer_id: source.clone(), + handler: NotifyHandler::All, event: NotifsHandlerIn::Disable, }); + let last = open.is_empty(); + *entry.into_mut() = PeerState::Disabled { - open: false, - connected_point, + open, banned_until: None }; + + last }, - PeerState::Disabled { open, connected_point, banned_until } => { - debug_assert!(open); - *entry.into_mut() = PeerState::Disabled { open: false, connected_point, banned_until }; + PeerState::Disabled { mut open, banned_until } => { + if let Some(pos) = open.iter().position(|c| c == &connection) { + open.remove(pos); + } else { + debug_assert!(false); + error!( + target: "sub-libp2p", + "State mismatch with {}: unknown closed connection", + source + ); + } + + let last = open.is_empty(); + *entry.into_mut() = PeerState::Disabled { + open, + banned_until + }; + last }, - PeerState::DisabledPendingEnable { open, connected_point, timer, timer_deadline } => { - debug_assert!(open); + PeerState::DisabledPendingEnable { + mut open, + timer, + timer_deadline + } => { + if let Some(pos) = open.iter().position(|c| c == &connection) { + open.remove(pos); + } else { + debug_assert!(false); + error!( + target: "sub-libp2p", + "State mismatch with {}: unknown closed connection", + source + ); + } + + let last = open.is_empty(); *entry.into_mut() = PeerState::DisabledPendingEnable { - open: false, - connected_point, + open, timer, timer_deadline }; + last }, - _ => error!(target: "sub-libp2p", "State mismatch in the custom protos handler"), + state => { + error!(target: "sub-libp2p", + "Unexpected state in the custom protos handler: {:?}", + state); + return + } + }; + + if last { + debug!(target: "sub-libp2p", "External API <= Closed({:?})", source); + let event = GenericProtoOut::CustomProtocolClosed { + reason, + peer_id: source, + }; + self.events.push_back(NetworkBehaviourAction::GenerateEvent(event)); + } else { + debug!(target: "sub-libp2p", "Secondary connection closed custom protocol."); } } - NotifsHandlerOut::Open => { - debug!(target: "sub-libp2p", "Handler({:?}) => Open", source); - let endpoint = match self.peers.get_mut(&source) { - Some(PeerState::Enabled { ref mut open, ref connected_point }) | - Some(PeerState::DisabledPendingEnable { ref mut open, ref connected_point, .. }) | - Some(PeerState::Disabled { ref mut open, ref connected_point, .. }) if !*open => { - *open = true; - connected_point.clone() + NotifsHandlerOut::Open { endpoint } => { + debug!(target: "sub-libp2p", + "Handler({:?}) => Endpoint {:?} open for custom protocols.", + source, endpoint); + + let first = match self.peers.get_mut(&source) { + Some(PeerState::Enabled { ref mut open, .. }) | + Some(PeerState::DisabledPendingEnable { ref mut open, .. }) | + Some(PeerState::Disabled { ref mut open, .. }) => { + let first = open.is_empty(); + if !open.iter().any(|c| *c == connection) { + open.push(connection); + } else { + error!( + target: "sub-libp2p", + "State mismatch: connection with {} opened a second time", + source + ); + } + first } - _ => { - error!(target: "sub-libp2p", "State mismatch in the custom protos handler"); + state => { + error!(target: "sub-libp2p", + "Open: Unexpected state in the custom protos handler: {:?}", + state); return } }; - debug!(target: "sub-libp2p", "External API <= Open({:?})", source); - let event = GenericProtoOut::CustomProtocolOpen { - peer_id: source, - endpoint, - }; - - self.events.push(NetworkBehaviourAction::GenerateEvent(event)); + if first { + debug!(target: "sub-libp2p", "External API <= Open({:?})", source); + let event = GenericProtoOut::CustomProtocolOpen { peer_id: source }; + self.events.push_back(NetworkBehaviourAction::GenerateEvent(event)); + } else { + debug!(target: "sub-libp2p", "Secondary connection opened custom protocol."); + } } NotifsHandlerOut::CustomMessage { message } => { @@ -1025,7 +1291,7 @@ impl NetworkBehaviour for GenericProto { message, }; - self.events.push(NetworkBehaviourAction::GenerateEvent(event)); + self.events.push_back(NetworkBehaviourAction::GenerateEvent(event)); } NotifsHandlerOut::Notification { protocol_name, message } => { @@ -1043,7 +1309,7 @@ impl NetworkBehaviour for GenericProto { message, }; - self.events.push(NetworkBehaviourAction::GenerateEvent(event)); + self.events.push_back(NetworkBehaviourAction::GenerateEvent(event)); } NotifsHandlerOut::Clogged { messages } => { @@ -1052,7 +1318,7 @@ impl NetworkBehaviour for GenericProto { trace!(target: "sub-libp2p", "External API <= Clogged({:?})", source); warn!(target: "sub-libp2p", "Queue of packets to send to {:?} is \ pretty large", source); - self.events.push(NetworkBehaviourAction::GenerateEvent(GenericProtoOut::Clogged { + self.events.push_back(NetworkBehaviourAction::GenerateEvent(GenericProtoOut::Clogged { peer_id: source, messages, })); @@ -1065,11 +1331,12 @@ impl NetworkBehaviour for GenericProto { } NotifsHandlerOut::ProtocolError { error, .. } => { - debug!(target: "sub-libp2p", "Handler({:?}) => Severe protocol error: {:?}", + debug!(target: "sub-libp2p", + "Handler({:?}) => Severe protocol error: {:?}", source, error); - // A severe protocol error happens when we detect a "bad" node, such as a node on - // a different chain, or a node that doesn't speak the same protocol(s). We - // decrease the node's reputation, hence lowering the chances we try this node + // A severe protocol error happens when we detect a "bad" peer, such as a peer on + // a different chain, or a peer that doesn't speak the same protocol(s). We + // decrease the peer's reputation, hence lowering the chances we try this peer // again in the short term. self.peerset.report_peer( source.clone(), @@ -1090,6 +1357,10 @@ impl NetworkBehaviour for GenericProto { Self::OutEvent, >, > { + if let Some(event) = self.events.pop_front() { + return Poll::Ready(event); + } + // Poll for instructions from the peerset. // Note that the peerset is a *best effort* crate, and we have to use defensive programming. loop { @@ -1114,44 +1385,43 @@ impl NetworkBehaviour for GenericProto { } } - for (peer_id, peer_state) in self.peers.iter_mut() { - match mem::replace(peer_state, PeerState::Poisoned) { - PeerState::PendingRequest { mut timer, timer_deadline } => { - if let Poll::Pending = Pin::new(&mut timer).poll(cx) { - *peer_state = PeerState::PendingRequest { timer, timer_deadline }; - continue; - } - + while let Poll::Ready(Some((delay_id, peer_id))) = + Pin::new(&mut self.delays).poll_next(cx) { + let peer_state = match self.peers.get_mut(&peer_id) { + Some(s) => s, + // We intentionally never remove elements from `delays`, and it may + // thus contain peers which are now gone. This is a normal situation. + None => continue, + }; + + match peer_state { + PeerState::PendingRequest { timer, .. } if *timer == delay_id => { debug!(target: "sub-libp2p", "Libp2p <= Dial {:?} now that ban has expired", peer_id); - self.events.push(NetworkBehaviourAction::DialPeer { peer_id: peer_id.clone() }); + self.events.push_back(NetworkBehaviourAction::DialPeer { + peer_id, + condition: DialPeerCondition::Disconnected + }); *peer_state = PeerState::Requested; } - PeerState::DisabledPendingEnable { mut timer, connected_point, open, timer_deadline } => { - if let Poll::Pending = Pin::new(&mut timer).poll(cx) { - *peer_state = PeerState::DisabledPendingEnable { - timer, - connected_point, - open, - timer_deadline - }; - continue; - } - - debug!(target: "sub-libp2p", "Handler({:?}) <= Enable now that ban has expired", peer_id); - self.events.push(NetworkBehaviourAction::SendEvent { - peer_id: peer_id.clone(), + PeerState::DisabledPendingEnable { timer, open, .. } if *timer == delay_id => { + debug!(target: "sub-libp2p", "Handler({:?}) <= Enable (ban expired)", peer_id); + self.events.push_back(NetworkBehaviourAction::NotifyHandler { + peer_id, + handler: NotifyHandler::All, event: NotifsHandlerIn::Enable, }); - *peer_state = PeerState::Enabled { connected_point, open }; + *peer_state = PeerState::Enabled { open: mem::replace(open, Default::default()) }; } - st @ _ => *peer_state = st, + // We intentionally never remove elements from `delays`, and it may + // thus contain obsolete entries. This is a normal situation. + _ => {}, } } - if !self.events.is_empty() { - return Poll::Ready(self.events.remove(0)) + if let Some(event) = self.events.pop_front() { + return Poll::Ready(event); } Poll::Pending diff --git a/client/network/src/protocol/generic_proto/handler.rs b/client/network/src/protocol/generic_proto/handler.rs index e97176cfbbfbb98cfa6f1f1d2f25dc9f5f777990..3b4469a872598f6f0b9c26b7647020a70ab5acc8 100644 --- a/client/network/src/protocol/generic_proto/handler.rs +++ b/client/network/src/protocol/generic_proto/handler.rs @@ -1,20 +1,22 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . - +// along with this program. If not, see . pub use self::group::{NotifsHandlerProto, NotifsHandler, NotifsHandlerIn, NotifsHandlerOut}; +pub use self::legacy::ConnectionKillError as LegacyConnectionKillError; mod group; mod legacy; diff --git a/client/network/src/protocol/generic_proto/handler/group.rs b/client/network/src/protocol/generic_proto/handler/group.rs index 21dc4091c0c4e70beec71c31f8263362ade80d3d..ed3e5642236672241612918230feae9d762e5d02 100644 --- a/client/network/src/protocol/generic_proto/handler/group.rs +++ b/client/network/src/protocol/generic_proto/handler/group.rs @@ -64,8 +64,9 @@ use libp2p::swarm::{ NegotiatedSubstream, }; use log::{debug, error}; +use parking_lot::RwLock; use prometheus_endpoint::HistogramVec; -use std::{borrow::Cow, error, io, str, task::{Context, Poll}}; +use std::{borrow::Cow, error, io, str, sync::Arc, task::{Context, Poll}}; /// Implements the `IntoProtocolsHandler` trait of libp2p. /// @@ -75,11 +76,12 @@ use std::{borrow::Cow, error, io, str, task::{Context, Poll}}; /// /// See the documentation at the module level for more information. pub struct NotifsHandlerProto { - /// Prototypes for handlers for inbound substreams. - in_handlers: Vec, + /// Prototypes for handlers for inbound substreams, and the message we respond with in the + /// handshake. + in_handlers: Vec<(NotifsInHandlerProto, Arc>>)>, - /// Prototypes for handlers for outbound substreams. - out_handlers: Vec, + /// Prototypes for handlers for outbound substreams, and the initial handshake message we send. + out_handlers: Vec<(NotifsOutHandlerProto, Arc>>)>, /// Prototype for handler for backwards-compatibility. legacy: LegacyProtoHandlerProto, @@ -89,11 +91,11 @@ pub struct NotifsHandlerProto { /// /// See the documentation at the module level for more information. pub struct NotifsHandler { - /// Handlers for inbound substreams. - in_handlers: Vec, + /// Handlers for inbound substreams, and the message we respond with in the handshake. + in_handlers: Vec<(NotifsInHandler, Arc>>)>, - /// Handlers for outbound substreams. - out_handlers: Vec, + /// Handlers for outbound substreams, and the initial handshake message we send. + out_handlers: Vec<(NotifsOutHandler, Arc>>)>, /// Handler for backwards-compatibility. legacy: LegacyProtoHandler, @@ -119,7 +121,7 @@ impl IntoProtocolsHandler for NotifsHandlerProto { fn inbound_protocol(&self) -> SelectUpgrade, RegisteredProtocol> { let in_handlers = self.in_handlers.iter() - .map(|h| h.inbound_protocol()) + .map(|(h, _)| h.inbound_protocol()) .collect::>(); SelectUpgrade::new(in_handlers, self.legacy.inbound_protocol()) @@ -129,11 +131,11 @@ impl IntoProtocolsHandler for NotifsHandlerProto { NotifsHandler { in_handlers: self.in_handlers .into_iter() - .map(|p| p.into_handler(remote_peer_id, connected_point)) + .map(|(proto, msg)| (proto.into_handler(remote_peer_id, connected_point), msg)) .collect(), out_handlers: self.out_handlers .into_iter() - .map(|p| p.into_handler(remote_peer_id, connected_point)) + .map(|(proto, msg)| (proto.into_handler(remote_peer_id, connected_point), msg)) .collect(), legacy: self.legacy.into_handler(remote_peer_id, connected_point), enabled: EnabledState::Initial, @@ -143,7 +145,7 @@ impl IntoProtocolsHandler for NotifsHandlerProto { } /// Event that can be received by a `NotifsHandler`. -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum NotifsHandlerIn { /// The node should start using custom protocols. Enable, @@ -181,13 +183,18 @@ pub enum NotifsHandlerIn { /// Event that can be emitted by a `NotifsHandler`. #[derive(Debug)] pub enum NotifsHandlerOut { - /// Opened the substreams with the remote. - Open, + /// The connection is open for custom protocols. + Open { + /// The endpoint of the connection that is open for custom protocols. + endpoint: ConnectedPoint, + }, - /// Closed the substreams with the remote. + /// The connection is closed for custom protocols. Closed { - /// Reason why the substream closed, for diagnostic purposes. + /// The reason for closing, for diagnostic purposes. reason: Cow<'static, str>, + /// The endpoint of the connection that closed for custom protocols. + endpoint: ConnectedPoint, }, /// Received a non-gossiping message on the legacy substream. @@ -227,28 +234,42 @@ pub enum NotifsHandlerOut { impl NotifsHandlerProto { /// Builds a new handler. /// + /// `list` is a list of notification protocols names, and the message to send as part of the + /// handshake. At the moment, the message is always the same whether we open a substream + /// ourselves or respond to handshake from the remote. + /// /// The `queue_size_report` is an optional Prometheus metric that can report the size of the /// messages queue. If passed, it must have one label for the protocol name. - pub fn new(legacy: RegisteredProtocol, list: impl Into, Vec)>>, queue_size_report: Option) -> Self { + pub fn new( + legacy: RegisteredProtocol, + list: impl Into, Arc>>)>>, + queue_size_report: Option + ) -> Self { let list = list.into(); let out_handlers = list .clone() .into_iter() - .map(|(p, _)| { + .map(|(proto_name, initial_message)| { let queue_size_report = queue_size_report.as_ref().and_then(|qs| { - if let Ok(utf8) = str::from_utf8(&p) { + if let Ok(utf8) = str::from_utf8(&proto_name) { Some(qs.with_label_values(&[utf8])) } else { - log::warn!("Ignoring Prometheus metric because {:?} isn't UTF-8", p); + log::warn!("Ignoring Prometheus metric because {:?} isn't UTF-8", proto_name); None } }); - NotifsOutHandlerProto::new(p, queue_size_report) + + (NotifsOutHandlerProto::new(proto_name, queue_size_report), initial_message) }).collect(); + let in_handlers = list.clone() + .into_iter() + .map(|(proto_name, msg)| (NotifsInHandlerProto::new(proto_name), msg)) + .collect(); + NotifsHandlerProto { - in_handlers: list.clone().into_iter().map(|(p, _)| NotifsInHandlerProto::new(p)).collect(), + in_handlers, out_handlers, legacy: LegacyProtoHandlerProto::new(legacy), } @@ -272,7 +293,7 @@ impl ProtocolsHandler for NotifsHandler { fn listen_protocol(&self) -> SubstreamProtocol { let in_handlers = self.in_handlers.iter() - .map(|h| h.listen_protocol().into_upgrade().1) + .map(|(h, _)| h.listen_protocol().into_upgrade().1) .collect::>(); let proto = SelectUpgrade::new(in_handlers, self.legacy.listen_protocol().into_upgrade().1); @@ -285,7 +306,7 @@ impl ProtocolsHandler for NotifsHandler { ) { match out { EitherOutput::First((out, num)) => - self.in_handlers[num].inject_fully_negotiated_inbound(out), + self.in_handlers[num].0.inject_fully_negotiated_inbound(out), EitherOutput::Second(out) => self.legacy.inject_fully_negotiated_inbound(out), } @@ -298,7 +319,7 @@ impl ProtocolsHandler for NotifsHandler { ) { match (out, num) { (EitherOutput::First(out), Some(num)) => - self.out_handlers[num].inject_fully_negotiated_outbound(out, ()), + self.out_handlers[num].0.inject_fully_negotiated_outbound(out, ()), (EitherOutput::Second(out), None) => self.legacy.inject_fully_negotiated_outbound(out, ()), _ => error!("inject_fully_negotiated_outbound called with wrong parameters"), @@ -313,13 +334,20 @@ impl ProtocolsHandler for NotifsHandler { } self.enabled = EnabledState::Enabled; self.legacy.inject_event(LegacyProtoHandlerIn::Enable); - for handler in &mut self.out_handlers { + for (handler, initial_message) in &mut self.out_handlers { + // We create `initial_message` on a separate line to be sure that the lock + // is released as soon as possible. + let initial_message = initial_message.read().clone(); handler.inject_event(NotifsOutHandlerIn::Enable { - initial_message: vec![] + initial_message, }); } for num in self.pending_in.drain(..) { - self.in_handlers[num].inject_event(NotifsInHandlerIn::Accept(vec![])); + // We create `handshake_message` on a separate line to be sure + // that the lock is released as soon as possible. + let handshake_message = self.in_handlers[num].1.read().clone(); + self.in_handlers[num].0 + .inject_event(NotifsInHandlerIn::Accept(handshake_message)); } }, NotifsHandlerIn::Disable => { @@ -330,19 +358,19 @@ impl ProtocolsHandler for NotifsHandler { // The notifications protocols start in the disabled state. If we were in the // "Initial" state, then we shouldn't disable the notifications protocols again. if self.enabled != EnabledState::Initial { - for handler in &mut self.out_handlers { + for (handler, _) in &mut self.out_handlers { handler.inject_event(NotifsOutHandlerIn::Disable); } } self.enabled = EnabledState::Disabled; for num in self.pending_in.drain(..) { - self.in_handlers[num].inject_event(NotifsInHandlerIn::Refuse); + self.in_handlers[num].0.inject_event(NotifsInHandlerIn::Refuse); } }, NotifsHandlerIn::SendLegacy { message } => self.legacy.inject_event(LegacyProtoHandlerIn::SendCustomMessage { message }), NotifsHandlerIn::SendNotification { message, encoded_fallback_message, protocol_name } => { - for handler in &mut self.out_handlers { + for (handler, _) in &mut self.out_handlers { if handler.protocol_name() != &protocol_name[..] { continue; } @@ -367,21 +395,21 @@ impl ProtocolsHandler for NotifsHandler { ) { match (err, num) { (ProtocolsHandlerUpgrErr::Timeout, Some(num)) => - self.out_handlers[num].inject_dial_upgrade_error( + self.out_handlers[num].0.inject_dial_upgrade_error( (), ProtocolsHandlerUpgrErr::Timeout ), (ProtocolsHandlerUpgrErr::Timeout, None) => self.legacy.inject_dial_upgrade_error((), ProtocolsHandlerUpgrErr::Timeout), (ProtocolsHandlerUpgrErr::Timer, Some(num)) => - self.out_handlers[num].inject_dial_upgrade_error( + self.out_handlers[num].0.inject_dial_upgrade_error( (), ProtocolsHandlerUpgrErr::Timer ), (ProtocolsHandlerUpgrErr::Timer, None) => self.legacy.inject_dial_upgrade_error((), ProtocolsHandlerUpgrErr::Timer), (ProtocolsHandlerUpgrErr::Upgrade(UpgradeError::Select(err)), Some(num)) => - self.out_handlers[num].inject_dial_upgrade_error( + self.out_handlers[num].0.inject_dial_upgrade_error( (), ProtocolsHandlerUpgrErr::Upgrade(UpgradeError::Select(err)) ), @@ -391,7 +419,7 @@ impl ProtocolsHandler for NotifsHandler { ProtocolsHandlerUpgrErr::Upgrade(UpgradeError::Select(err)) ), (ProtocolsHandlerUpgrErr::Upgrade(UpgradeError::Apply(EitherError::A(err))), Some(num)) => - self.out_handlers[num].inject_dial_upgrade_error( + self.out_handlers[num].0.inject_dial_upgrade_error( (), ProtocolsHandlerUpgrErr::Upgrade(UpgradeError::Apply(err)) ), @@ -412,7 +440,7 @@ impl ProtocolsHandler for NotifsHandler { return KeepAlive::Yes; } - for handler in &self.in_handlers { + for (handler, _) in &self.in_handlers { let val = handler.connection_keep_alive(); if val.is_yes() { return KeepAlive::Yes; @@ -420,7 +448,7 @@ impl ProtocolsHandler for NotifsHandler { if ret < val { ret = val; } } - for handler in &self.out_handlers { + for (handler, _) in &self.out_handlers { let val = handler.connection_keep_alive(); if val.is_yes() { return KeepAlive::Yes; @@ -437,7 +465,39 @@ impl ProtocolsHandler for NotifsHandler { ) -> Poll< ProtocolsHandlerEvent > { - for (handler_num, handler) in self.in_handlers.iter_mut().enumerate() { + if let Poll::Ready(ev) = self.legacy.poll(cx) { + return match ev { + ProtocolsHandlerEvent::OutboundSubstreamRequest { protocol, info: () } => + Poll::Ready(ProtocolsHandlerEvent::OutboundSubstreamRequest { + protocol: protocol.map_upgrade(EitherUpgrade::B), + info: None, + }), + ProtocolsHandlerEvent::Custom(LegacyProtoHandlerOut::CustomProtocolOpen { endpoint, .. }) => + Poll::Ready(ProtocolsHandlerEvent::Custom( + NotifsHandlerOut::Open { endpoint } + )), + ProtocolsHandlerEvent::Custom(LegacyProtoHandlerOut::CustomProtocolClosed { endpoint, reason }) => + Poll::Ready(ProtocolsHandlerEvent::Custom( + NotifsHandlerOut::Closed { endpoint, reason } + )), + ProtocolsHandlerEvent::Custom(LegacyProtoHandlerOut::CustomMessage { message }) => + Poll::Ready(ProtocolsHandlerEvent::Custom( + NotifsHandlerOut::CustomMessage { message } + )), + ProtocolsHandlerEvent::Custom(LegacyProtoHandlerOut::Clogged { messages }) => + Poll::Ready(ProtocolsHandlerEvent::Custom( + NotifsHandlerOut::Clogged { messages } + )), + ProtocolsHandlerEvent::Custom(LegacyProtoHandlerOut::ProtocolError { is_severe, error }) => + Poll::Ready(ProtocolsHandlerEvent::Custom( + NotifsHandlerOut::ProtocolError { is_severe, error } + )), + ProtocolsHandlerEvent::Close(err) => + Poll::Ready(ProtocolsHandlerEvent::Close(EitherError::B(err))), + } + } + + for (handler_num, (handler, handshake_message)) in self.in_handlers.iter_mut().enumerate() { while let Poll::Ready(ev) = handler.poll(cx) { match ev { ProtocolsHandlerEvent::OutboundSubstreamRequest { .. } => @@ -446,8 +506,12 @@ impl ProtocolsHandler for NotifsHandler { ProtocolsHandlerEvent::Custom(NotifsInHandlerOut::OpenRequest(_)) => match self.enabled { EnabledState::Initial => self.pending_in.push(handler_num), - EnabledState::Enabled => - handler.inject_event(NotifsInHandlerIn::Accept(vec![])), + EnabledState::Enabled => { + // We create `handshake_message` on a separate line to be sure + // that the lock is released as soon as possible. + let handshake_message = handshake_message.read().clone(); + handler.inject_event(NotifsInHandlerIn::Accept(handshake_message)) + }, EnabledState::Disabled => handler.inject_event(NotifsInHandlerIn::Refuse), }, @@ -467,7 +531,7 @@ impl ProtocolsHandler for NotifsHandler { } } - for (handler_num, handler) in self.out_handlers.iter_mut().enumerate() { + for (handler_num, (handler, _)) in self.out_handlers.iter_mut().enumerate() { while let Poll::Ready(ev) = handler.poll(cx) { match ev { ProtocolsHandlerEvent::OutboundSubstreamRequest { protocol, info: () } => @@ -490,38 +554,6 @@ impl ProtocolsHandler for NotifsHandler { } } - while let Poll::Ready(ev) = self.legacy.poll(cx) { - match ev { - ProtocolsHandlerEvent::OutboundSubstreamRequest { protocol, info: () } => - return Poll::Ready(ProtocolsHandlerEvent::OutboundSubstreamRequest { - protocol: protocol.map_upgrade(EitherUpgrade::B), - info: None, - }), - ProtocolsHandlerEvent::Custom(LegacyProtoHandlerOut::CustomProtocolOpen { .. }) => - return Poll::Ready(ProtocolsHandlerEvent::Custom( - NotifsHandlerOut::Open - )), - ProtocolsHandlerEvent::Custom(LegacyProtoHandlerOut::CustomProtocolClosed { reason }) => - return Poll::Ready(ProtocolsHandlerEvent::Custom( - NotifsHandlerOut::Closed { reason } - )), - ProtocolsHandlerEvent::Custom(LegacyProtoHandlerOut::CustomMessage { message }) => - return Poll::Ready(ProtocolsHandlerEvent::Custom( - NotifsHandlerOut::CustomMessage { message } - )), - ProtocolsHandlerEvent::Custom(LegacyProtoHandlerOut::Clogged { messages }) => - return Poll::Ready(ProtocolsHandlerEvent::Custom( - NotifsHandlerOut::Clogged { messages } - )), - ProtocolsHandlerEvent::Custom(LegacyProtoHandlerOut::ProtocolError { is_severe, error }) => - return Poll::Ready(ProtocolsHandlerEvent::Custom( - NotifsHandlerOut::ProtocolError { is_severe, error } - )), - ProtocolsHandlerEvent::Close(err) => - return Poll::Ready(ProtocolsHandlerEvent::Close(EitherError::B(err))), - } - } - Poll::Pending } } diff --git a/client/network/src/protocol/generic_proto/handler/legacy.rs b/client/network/src/protocol/generic_proto/handler/legacy.rs index a2d2fc9246d1c79b761d5e5eb1ce375fba33b49a..c7de2d265e96fdf66f567366bd10fd6cf8ece265 100644 --- a/client/network/src/protocol/generic_proto/handler/legacy.rs +++ b/client/network/src/protocol/generic_proto/handler/legacy.rs @@ -30,7 +30,7 @@ use libp2p::swarm::{ }; use log::{debug, error}; use smallvec::{smallvec, SmallVec}; -use std::{borrow::Cow, error, fmt, io, mem, time::Duration}; +use std::{borrow::Cow, collections::VecDeque, error, fmt, io, mem, time::Duration}; use std::{pin::Pin, task::{Context, Poll}}; /// Implements the `IntoProtocolsHandler` trait of libp2p. @@ -40,9 +40,8 @@ use std::{pin::Pin, task::{Context, Poll}}; /// it is turned into a `LegacyProtoHandler`. It then handles all communications that are specific /// to Substrate on that single connection. /// -/// Note that there can be multiple instance of this struct simultaneously for same peer. However -/// if that happens, only one main instance can communicate with the outer layers of the code. In -/// other words, the outer layers of the code only ever see one handler. +/// Note that there can be multiple instance of this struct simultaneously for same peer, +/// if there are multiple established connections to the peer. /// /// ## State of the handler /// @@ -61,6 +60,7 @@ use std::{pin::Pin, task::{Context, Poll}}; /// these states. For example, if the handler reports a network misbehaviour, it will close the /// substreams but it is the role of the user to send a `Disabled` event if it wants the connection /// to close. Otherwise, the handler will try to reopen substreams. +/// /// The handler starts in the "Initializing" state and must be transitionned to Enabled or Disabled /// as soon as possible. /// @@ -111,13 +111,13 @@ impl IntoProtocolsHandler for LegacyProtoHandlerProto { fn into_handler(self, remote_peer_id: &PeerId, connected_point: &ConnectedPoint) -> Self::Handler { LegacyProtoHandler { protocol: self.protocol, - endpoint: connected_point.to_endpoint(), + endpoint: connected_point.clone(), remote_peer_id: remote_peer_id.clone(), state: ProtocolState::Init { substreams: SmallVec::new(), - init_deadline: Delay::new(Duration::from_secs(5)) + init_deadline: Delay::new(Duration::from_secs(20)) }, - events_queue: SmallVec::new(), + events_queue: VecDeque::new(), } } } @@ -136,13 +136,13 @@ pub struct LegacyProtoHandler { /// Whether we are the connection dialer or listener. Used to determine who, between the local /// node and the remote node, has priority. - endpoint: Endpoint, + endpoint: ConnectedPoint, /// Queue of events to send to the outside. /// /// This queue must only ever be modified to insert elements at the back, or remove the first /// element. - events_queue: SmallVec<[ProtocolsHandlerEvent; 16]>, + events_queue: VecDeque>, } /// State of the handler. @@ -218,12 +218,16 @@ pub enum LegacyProtoHandlerOut { CustomProtocolOpen { /// Version of the protocol that has been opened. version: u8, + /// The connected endpoint. + endpoint: ConnectedPoint, }, /// Closed a custom protocol with the remote. CustomProtocolClosed { /// Reason why the substream closed, for diagnostic purposes. reason: Cow<'static, str>, + /// The connected endpoint. + endpoint: ConnectedPoint, }, /// Receives a message on a custom protocol substream. @@ -272,8 +276,8 @@ impl LegacyProtoHandler { ProtocolState::Init { substreams: incoming, .. } => { if incoming.is_empty() { - if let Endpoint::Dialer = self.endpoint { - self.events_queue.push(ProtocolsHandlerEvent::OutboundSubstreamRequest { + if let ConnectedPoint::Dialer { .. } = self.endpoint { + self.events_queue.push_back(ProtocolsHandlerEvent::OutboundSubstreamRequest { protocol: SubstreamProtocol::new(self.protocol.clone()), info: (), }); @@ -281,12 +285,12 @@ impl LegacyProtoHandler { ProtocolState::Opening { deadline: Delay::new(Duration::from_secs(60)) } - } else { let event = LegacyProtoHandlerOut::CustomProtocolOpen { - version: incoming[0].protocol_version() + version: incoming[0].protocol_version(), + endpoint: self.endpoint.clone() }; - self.events_queue.push(ProtocolsHandlerEvent::Custom(event)); + self.events_queue.push_back(ProtocolsHandlerEvent::Custom(event)); ProtocolState::Normal { substreams: incoming.into_iter().collect(), shutdown: SmallVec::new() @@ -349,26 +353,26 @@ impl LegacyProtoHandler { ProtocolState::Init { substreams, mut init_deadline } => { match Pin::new(&mut init_deadline).poll(cx) { Poll::Ready(()) => { - init_deadline = Delay::new(Duration::from_secs(60)); error!(target: "sub-libp2p", "Handler initialization process is too long \ - with {:?}", self.remote_peer_id) + with {:?}", self.remote_peer_id); + self.state = ProtocolState::KillAsap; }, - Poll::Pending => {} + Poll::Pending => { + self.state = ProtocolState::Init { substreams, init_deadline }; + } } - self.state = ProtocolState::Init { substreams, init_deadline }; None } ProtocolState::Opening { mut deadline } => { match Pin::new(&mut deadline).poll(cx) { Poll::Ready(()) => { - deadline = Delay::new(Duration::from_secs(60)); let event = LegacyProtoHandlerOut::ProtocolError { is_severe: true, error: "Timeout when opening protocol".to_string().into(), }; - self.state = ProtocolState::Opening { deadline }; + self.state = ProtocolState::KillAsap; Some(ProtocolsHandlerEvent::Custom(event)) }, Poll::Pending => { @@ -404,6 +408,7 @@ impl LegacyProtoHandler { if substreams.is_empty() { let event = LegacyProtoHandlerOut::CustomProtocolClosed { reason: "All substreams have been closed by the remote".into(), + endpoint: self.endpoint.clone() }; self.state = ProtocolState::Disabled { shutdown: shutdown.into_iter().collect(), @@ -416,6 +421,7 @@ impl LegacyProtoHandler { if substreams.is_empty() { let event = LegacyProtoHandlerOut::CustomProtocolClosed { reason: format!("Error on the last substream: {:?}", err).into(), + endpoint: self.endpoint.clone() }; self.state = ProtocolState::Disabled { shutdown: shutdown.into_iter().collect(), @@ -479,9 +485,10 @@ impl LegacyProtoHandler { ProtocolState::Opening { .. } => { let event = LegacyProtoHandlerOut::CustomProtocolOpen { - version: substream.protocol_version() + version: substream.protocol_version(), + endpoint: self.endpoint.clone() }; - self.events_queue.push(ProtocolsHandlerEvent::Custom(event)); + self.events_queue.push_back(ProtocolsHandlerEvent::Custom(event)); ProtocolState::Normal { substreams: smallvec![substream], shutdown: SmallVec::new() @@ -558,7 +565,7 @@ impl ProtocolsHandler for LegacyProtoHandler { _ => false, }; - self.events_queue.push(ProtocolsHandlerEvent::Custom(LegacyProtoHandlerOut::ProtocolError { + self.events_queue.push_back(ProtocolsHandlerEvent::Custom(LegacyProtoHandlerOut::ProtocolError { is_severe, error: Box::new(err), })); @@ -580,8 +587,7 @@ impl ProtocolsHandler for LegacyProtoHandler { ProtocolsHandlerEvent > { // Flush the events queue if necessary. - if !self.events_queue.is_empty() { - let event = self.events_queue.remove(0); + if let Some(event) = self.events_queue.pop_front() { return Poll::Ready(event) } diff --git a/client/network/src/protocol/generic_proto/handler/notif_in.rs b/client/network/src/protocol/generic_proto/handler/notif_in.rs index 7558d1d361fd7cf445271b4351cd0c7c5fdd45d7..be78fb970e90b2524fd1478f48462e159dd1b28d 100644 --- a/client/network/src/protocol/generic_proto/handler/notif_in.rs +++ b/client/network/src/protocol/generic_proto/handler/notif_in.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Implementations of the `IntoProtocolsHandler` and `ProtocolsHandler` traits for ingoing //! substreams for a single gossiping protocol. @@ -35,8 +37,7 @@ use libp2p::swarm::{ NegotiatedSubstream, }; use log::{error, warn}; -use smallvec::SmallVec; -use std::{borrow::Cow, fmt, pin::Pin, task::{Context, Poll}}; +use std::{borrow::Cow, collections::VecDeque, fmt, pin::Pin, task::{Context, Poll}}; /// Implements the `IntoProtocolsHandler` trait of libp2p. /// @@ -68,11 +69,11 @@ pub struct NotifsInHandler { /// /// This queue is only ever modified to insert elements at the back, or remove the first /// element. - events_queue: SmallVec<[ProtocolsHandlerEvent; 16]>, + events_queue: VecDeque>, } /// Event that can be received by a `NotifsInHandler`. -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum NotifsInHandlerIn { /// Can be sent back as a response to an `OpenRequest`. Contains the status message to send /// to the remote. @@ -128,7 +129,7 @@ impl IntoProtocolsHandler for NotifsInHandlerProto { in_protocol: self.in_protocol, substream: None, pending_accept_refuses: 0, - events_queue: SmallVec::new(), + events_queue: VecDeque::new(), } } } @@ -158,7 +159,7 @@ impl ProtocolsHandler for NotifsInHandler { ) { // If a substream already exists, we drop it and replace it with the new incoming one. if self.substream.is_some() { - self.events_queue.push(ProtocolsHandlerEvent::Custom(NotifsInHandlerOut::Closed)); + self.events_queue.push_back(ProtocolsHandlerEvent::Custom(NotifsInHandlerOut::Closed)); } // Note that we drop the existing substream, which will send an equivalent to a TCP "RST" @@ -169,7 +170,7 @@ impl ProtocolsHandler for NotifsInHandler { // and we can't close "more" than that anyway. self.substream = Some(proto); - self.events_queue.push(ProtocolsHandlerEvent::Custom(NotifsInHandlerOut::OpenRequest(msg))); + self.events_queue.push_back(ProtocolsHandlerEvent::Custom(NotifsInHandlerOut::OpenRequest(msg))); self.pending_accept_refuses = self.pending_accept_refuses .checked_add(1) .unwrap_or_else(|| { @@ -231,8 +232,7 @@ impl ProtocolsHandler for NotifsInHandler { ProtocolsHandlerEvent > { // Flush the events queue if necessary. - if !self.events_queue.is_empty() { - let event = self.events_queue.remove(0); + if let Some(event) = self.events_queue.pop_front() { return Poll::Ready(event) } diff --git a/client/network/src/protocol/generic_proto/handler/notif_out.rs b/client/network/src/protocol/generic_proto/handler/notif_out.rs index dd38826496e7a3f8289131183d27f7f2c235c230..6b97ad67e34c696f58996a8c13f983f0486b84fa 100644 --- a/client/network/src/protocol/generic_proto/handler/notif_out.rs +++ b/client/network/src/protocol/generic_proto/handler/notif_out.rs @@ -33,10 +33,9 @@ use libp2p::swarm::{ SubstreamProtocol, NegotiatedSubstream, }; -use log::error; +use log::{debug, warn, error}; use prometheus_endpoint::Histogram; -use smallvec::SmallVec; -use std::{borrow::Cow, fmt, mem, pin::Pin, task::{Context, Poll}, time::Duration}; +use std::{borrow::Cow, collections::VecDeque, fmt, mem, pin::Pin, task::{Context, Poll}, time::Duration}; use wasm_timer::Instant; /// Maximum duration to open a substream and receive the handshake message. After that, we @@ -85,7 +84,7 @@ impl IntoProtocolsHandler for NotifsOutHandlerProto { when_connection_open: Instant::now(), queue_size_report: self.queue_size_report, state: State::Disabled, - events_queue: SmallVec::new(), + events_queue: VecDeque::new(), peer_id: peer_id.clone(), } } @@ -116,7 +115,7 @@ pub struct NotifsOutHandler { /// /// This queue must only ever be modified to insert elements at the back, or remove the first /// element. - events_queue: SmallVec<[ProtocolsHandlerEvent; 16]>, + events_queue: VecDeque>, /// Who we are connected to. peer_id: PeerId, @@ -247,7 +246,7 @@ impl ProtocolsHandler for NotifsOutHandler { match mem::replace(&mut self.state, State::Poisoned) { State::Opening { initial_message } => { let ev = NotifsOutHandlerOut::Open { handshake: handshake_msg }; - self.events_queue.push(ProtocolsHandlerEvent::Custom(ev)); + self.events_queue.push_back(ProtocolsHandlerEvent::Custom(ev)); self.state = State::Open { substream, initial_message }; }, // If the handler was disabled while we were negotiating the protocol, immediately @@ -267,7 +266,7 @@ impl ProtocolsHandler for NotifsOutHandler { match mem::replace(&mut self.state, State::Poisoned) { State::Disabled => { let proto = NotificationsOut::new(self.protocol_name.clone(), initial_message.clone()); - self.events_queue.push(ProtocolsHandlerEvent::OutboundSubstreamRequest { + self.events_queue.push_back(ProtocolsHandlerEvent::OutboundSubstreamRequest { protocol: SubstreamProtocol::new(proto).with_timeout(OPEN_TIMEOUT), info: (), }); @@ -280,29 +279,35 @@ impl ProtocolsHandler for NotifsOutHandler { // be recovered. When in doubt, let's drop the existing substream and // open a new one. if sub.close().now_or_never().is_none() { - log::warn!( + warn!( target: "sub-libp2p", "📞 Improperly closed outbound notifications substream" ); } let proto = NotificationsOut::new(self.protocol_name.clone(), initial_message.clone()); - self.events_queue.push(ProtocolsHandlerEvent::OutboundSubstreamRequest { + self.events_queue.push_back(ProtocolsHandlerEvent::OutboundSubstreamRequest { protocol: SubstreamProtocol::new(proto).with_timeout(OPEN_TIMEOUT), info: (), }); self.state = State::Opening { initial_message }; }, - State::Opening { .. } | State::Refused | State::Open { .. } => - error!("☎️ Tried to enable notifications handler that was already enabled"), - State::Poisoned => error!("☎️ Notifications handler in a poisoned state"), + st @ State::Opening { .. } | st @ State::Refused | st @ State::Open { .. } => { + debug!(target: "sub-libp2p", + "Tried to enable notifications handler that was already enabled"); + self.state = st; + } + State::Poisoned => error!("Notifications handler in a poisoned state"), } } NotifsOutHandlerIn::Disable => { match mem::replace(&mut self.state, State::Poisoned) { - State::Disabled | State::DisabledOpen(_) | State::DisabledOpening => - error!("☎️ Tried to disable notifications handler that was already disabled"), + st @ State::Disabled | st @ State::DisabledOpen(_) | st @ State::DisabledOpening => { + debug!(target: "sub-libp2p", + "Tried to disable notifications handler that was already disabled"); + self.state = st; + } State::Opening { .. } => self.state = State::DisabledOpening, State::Refused => self.state = State::Disabled, State::Open { substream, .. } => self.state = State::DisabledOpen(substream), @@ -313,7 +318,7 @@ impl ProtocolsHandler for NotifsOutHandler { NotifsOutHandlerIn::Send(msg) => if let State::Open { substream, .. } = &mut self.state { if substream.push_message(msg).is_err() { - log::warn!( + warn!( target: "sub-libp2p", "📞 Notifications queue with peer {} is full, dropped message (protocol: {:?})", self.peer_id, @@ -325,7 +330,7 @@ impl ProtocolsHandler for NotifsOutHandler { } } else { // This is an API misuse. - log::warn!( + warn!( target: "sub-libp2p", "📞 Tried to send a notification on a disabled handler" ); @@ -341,7 +346,7 @@ impl ProtocolsHandler for NotifsOutHandler { State::Opening { .. } => { self.state = State::Refused; let ev = NotifsOutHandlerOut::Refused; - self.events_queue.push(ProtocolsHandlerEvent::Custom(ev)); + self.events_queue.push_back(ProtocolsHandlerEvent::Custom(ev)); }, State::DisabledOpening => self.state = State::Disabled, State::Poisoned => error!("☎️ Notifications handler in a poisoned state"), @@ -365,9 +370,8 @@ impl ProtocolsHandler for NotifsOutHandler { cx: &mut Context, ) -> Poll> { // Flush the events queue if necessary. - if !self.events_queue.is_empty() { - let event = self.events_queue.remove(0); - return Poll::Ready(event); + if let Some(event) = self.events_queue.pop_front() { + return Poll::Ready(event) } match &mut self.state { @@ -379,7 +383,7 @@ impl ProtocolsHandler for NotifsOutHandler { let initial_message = mem::replace(initial_message, Vec::new()); self.state = State::Opening { initial_message: initial_message.clone() }; let proto = NotificationsOut::new(self.protocol_name.clone(), initial_message); - self.events_queue.push(ProtocolsHandlerEvent::OutboundSubstreamRequest { + self.events_queue.push_back(ProtocolsHandlerEvent::OutboundSubstreamRequest { protocol: SubstreamProtocol::new(proto).with_timeout(OPEN_TIMEOUT), info: (), }); diff --git a/client/network/src/protocol/generic_proto/tests.rs b/client/network/src/protocol/generic_proto/tests.rs index 4548859ac420cd0ab52ed9c9c5cffd9167aef92b..f932a3a08916f3b8ec06078bfa457bb7629e81fe 100644 --- a/client/network/src/protocol/generic_proto/tests.rs +++ b/client/network/src/protocol/generic_proto/tests.rs @@ -18,7 +18,7 @@ use futures::{prelude::*, ready}; use codec::{Encode, Decode}; -use libp2p::core::nodes::listeners::ListenerId; +use libp2p::core::connection::{ConnectionId, ListenerId}; use libp2p::core::ConnectedPoint; use libp2p::swarm::{Swarm, ProtocolsHandler, IntoProtocolsHandler}; use libp2p::swarm::{PollParameters, NetworkBehaviour, NetworkBehaviourAction}; @@ -42,6 +42,7 @@ fn build_nodes() -> (Swarm, Swarm) { for index in 0 .. 2 { let keypair = keypairs[index].clone(); + let local_peer_id = keypair.public().into_peer_id(); let transport = libp2p::core::transport::MemoryTransport .and_then(move |out, endpoint| { let secio = libp2p::secio::SecioConfig::new(keypair); @@ -82,7 +83,7 @@ fn build_nodes() -> (Swarm, Swarm) { }); let behaviour = CustomProtoWithAddr { - inner: GenericProto::new(&b"test"[..], &[1], peerset, None), + inner: GenericProto::new(local_peer_id, &b"test"[..], &[1], vec![], peerset, None), addrs: addrs .iter() .enumerate() @@ -148,20 +149,29 @@ impl NetworkBehaviour for CustomProtoWithAddr { list } - fn inject_connected(&mut self, peer_id: PeerId, endpoint: ConnectedPoint) { - self.inner.inject_connected(peer_id, endpoint) + fn inject_connected(&mut self, peer_id: &PeerId) { + self.inner.inject_connected(peer_id) } - fn inject_disconnected(&mut self, peer_id: &PeerId, endpoint: ConnectedPoint) { - self.inner.inject_disconnected(peer_id, endpoint) + fn inject_disconnected(&mut self, peer_id: &PeerId) { + self.inner.inject_disconnected(peer_id) } - fn inject_node_event( + fn inject_connection_established(&mut self, peer_id: &PeerId, conn: &ConnectionId, endpoint: &ConnectedPoint) { + self.inner.inject_connection_established(peer_id, conn, endpoint) + } + + fn inject_connection_closed(&mut self, peer_id: &PeerId, conn: &ConnectionId, endpoint: &ConnectedPoint) { + self.inner.inject_connection_closed(peer_id, conn, endpoint) + } + + fn inject_event( &mut self, peer_id: PeerId, + connection: ConnectionId, event: <::Handler as ProtocolsHandler>::OutEvent ) { - self.inner.inject_node_event(peer_id, event) + self.inner.inject_event(peer_id, connection, event) } fn poll( @@ -177,10 +187,6 @@ impl NetworkBehaviour for CustomProtoWithAddr { self.inner.poll(cx, params) } - fn inject_replaced(&mut self, peer_id: PeerId, closed_endpoint: ConnectedPoint, new_endpoint: ConnectedPoint) { - self.inner.inject_replaced(peer_id, closed_endpoint, new_endpoint) - } - fn inject_addr_reach_failure(&mut self, peer_id: Option<&PeerId>, addr: &Multiaddr, error: &dyn std::error::Error) { self.inner.inject_addr_reach_failure(peer_id, addr, error) } @@ -205,8 +211,8 @@ impl NetworkBehaviour for CustomProtoWithAddr { self.inner.inject_listener_error(id, err); } - fn inject_listener_closed(&mut self, id: ListenerId) { - self.inner.inject_listener_closed(id); + fn inject_listener_closed(&mut self, id: ListenerId, reason: Result<(), &io::Error>) { + self.inner.inject_listener_closed(id, reason); } } @@ -235,6 +241,8 @@ fn two_nodes_transfer_lots_of_packets() { ); } }, + // An empty handshake is being sent after opening. + Some(GenericProtoOut::LegacyMessage { message, .. }) if message.is_empty() => {}, _ => panic!(), } } @@ -245,6 +253,8 @@ fn two_nodes_transfer_lots_of_packets() { loop { match ready!(service2.poll_next_unpin(cx)) { Some(GenericProtoOut::CustomProtocolOpen { .. }) => {}, + // An empty handshake is being sent after opening. + Some(GenericProtoOut::LegacyMessage { message, .. }) if message.is_empty() => {}, Some(GenericProtoOut::LegacyMessage { message, .. }) => { match Message::::decode(&mut &message[..]).unwrap() { Message::::BlockResponse(BlockResponse { id: _, blocks }) => { @@ -306,6 +316,8 @@ fn basic_two_nodes_requests_in_parallel() { service1.send_packet(&peer_id, msg.encode()); } }, + // An empty handshake is being sent after opening. + Some(GenericProtoOut::LegacyMessage { message, .. }) if message.is_empty() => {}, _ => panic!(), } } @@ -315,6 +327,8 @@ fn basic_two_nodes_requests_in_parallel() { loop { match ready!(service2.poll_next_unpin(cx)) { Some(GenericProtoOut::CustomProtocolOpen { .. }) => {}, + // An empty handshake is being sent after opening. + Some(GenericProtoOut::LegacyMessage { message, .. }) if message.is_empty() => {}, Some(GenericProtoOut::LegacyMessage { message, .. }) => { let pos = to_receive.iter().position(|m| m.encode() == message).unwrap(); to_receive.remove(pos); diff --git a/client/network/src/protocol/generic_proto/upgrade.rs b/client/network/src/protocol/generic_proto/upgrade.rs index 36f826336532619479b94876776c65e8636f8c57..6322a10b572a9fa1e9d60566343e513fc2a6f15a 100644 --- a/client/network/src/protocol/generic_proto/upgrade.rs +++ b/client/network/src/protocol/generic_proto/upgrade.rs @@ -1,19 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . - +// along with this program. If not, see . pub use self::collec::UpgradeCollec; pub use self::legacy::{ RegisteredProtocol, diff --git a/client/network/src/protocol/generic_proto/upgrade/legacy.rs b/client/network/src/protocol/generic_proto/upgrade/legacy.rs index 311e0b04f9724072535cad8dc429d2c1989c4c5d..538532c1aff6b6a2bf70fda5c3dec2672217b9a8 100644 --- a/client/network/src/protocol/generic_proto/upgrade/legacy.rs +++ b/client/network/src/protocol/generic_proto/upgrade/legacy.rs @@ -1,25 +1,28 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use crate::config::ProtocolId; use bytes::BytesMut; use futures::prelude::*; use futures_codec::Framed; use libp2p::core::{Endpoint, UpgradeInfo, InboundUpgrade, OutboundUpgrade, upgrade::ProtocolName}; -use std::{collections::VecDeque, io, pin::Pin, vec::IntoIter as VecIntoIter}; +use parking_lot::RwLock; +use std::{collections::VecDeque, io, pin::Pin, sync::Arc, vec::IntoIter as VecIntoIter}; use std::task::{Context, Poll}; use unsigned_varint::codec::UviBytes; @@ -36,12 +39,13 @@ pub struct RegisteredProtocol { /// List of protocol versions that we support. /// Ordered in descending order so that the best comes first. supported_versions: Vec, + /// Handshake to send after the substream is open. + handshake_message: Arc>>, } impl RegisteredProtocol { - /// Creates a new `RegisteredProtocol`. The `custom_data` parameter will be - /// passed inside the `RegisteredProtocolOutput`. - pub fn new(protocol: impl Into, versions: &[u8]) + /// Creates a new `RegisteredProtocol`. + pub fn new(protocol: impl Into, versions: &[u8], handshake_message: Arc>>) -> Self { let protocol = protocol.into(); let mut base_name = b"/substrate/".to_vec(); @@ -56,8 +60,14 @@ impl RegisteredProtocol { tmp.sort_unstable_by(|a, b| b.cmp(&a)); tmp }, + handshake_message, } } + + /// Returns the `Arc` to the handshake message that was passed at initialization. + pub fn handshake_message(&self) -> &Arc>> { + &self.handshake_message + } } impl Clone for RegisteredProtocol { @@ -66,6 +76,7 @@ impl Clone for RegisteredProtocol { id: self.id.clone(), base_name: self.base_name.clone(), supported_versions: self.supported_versions.clone(), + handshake_message: self.handshake_message.clone(), } } } @@ -242,10 +253,10 @@ impl ProtocolName for RegisteredProtocolName { } impl InboundUpgrade for RegisteredProtocol -where TSubstream: AsyncRead + AsyncWrite + Unpin, +where TSubstream: AsyncRead + AsyncWrite + Unpin + Send + 'static, { type Output = RegisteredProtocolSubstream; - type Future = future::Ready>; + type Future = Pin> + Send>>; type Error = io::Error; fn upgrade_inbound( @@ -253,26 +264,31 @@ where TSubstream: AsyncRead + AsyncWrite + Unpin, socket: TSubstream, info: Self::Info, ) -> Self::Future { - let framed = { - let mut codec = UviBytes::default(); - codec.set_max_len(16 * 1024 * 1024); // 16 MiB hard limit for packets. - Framed::new(socket, codec) - }; - - future::ok(RegisteredProtocolSubstream { - is_closing: false, - endpoint: Endpoint::Listener, - send_queue: VecDeque::new(), - requires_poll_flush: false, - inner: framed.fuse(), - protocol_version: info.version, - clogged_fuse: false, + Box::pin(async move { + let mut framed = { + let mut codec = UviBytes::default(); + codec.set_max_len(16 * 1024 * 1024); // 16 MiB hard limit for packets. + Framed::new(socket, codec) + }; + + let handshake = BytesMut::from(&self.handshake_message.read()[..]); + framed.send(handshake).await?; + + Ok(RegisteredProtocolSubstream { + is_closing: false, + endpoint: Endpoint::Listener, + send_queue: VecDeque::new(), + requires_poll_flush: false, + inner: framed.fuse(), + protocol_version: info.version, + clogged_fuse: false, + }) }) } } impl OutboundUpgrade for RegisteredProtocol -where TSubstream: AsyncRead + AsyncWrite + Unpin, +where TSubstream: AsyncRead + AsyncWrite + Unpin + Send + 'static, { type Output = >::Output; type Future = >::Future; @@ -283,16 +299,25 @@ where TSubstream: AsyncRead + AsyncWrite + Unpin, socket: TSubstream, info: Self::Info, ) -> Self::Future { - let framed = Framed::new(socket, UviBytes::default()); - - future::ok(RegisteredProtocolSubstream { - is_closing: false, - endpoint: Endpoint::Dialer, - send_queue: VecDeque::new(), - requires_poll_flush: false, - inner: framed.fuse(), - protocol_version: info.version, - clogged_fuse: false, + Box::pin(async move { + let mut framed = { + let mut codec = UviBytes::default(); + codec.set_max_len(16 * 1024 * 1024); // 16 MiB hard limit for packets. + Framed::new(socket, codec) + }; + + let handshake = BytesMut::from(&self.handshake_message.read()[..]); + framed.send(handshake).await?; + + Ok(RegisteredProtocolSubstream { + is_closing: false, + endpoint: Endpoint::Dialer, + send_queue: VecDeque::new(), + requires_poll_flush: false, + inner: framed.fuse(), + protocol_version: info.version, + clogged_fuse: false, + }) }) } } diff --git a/client/network/src/protocol/generic_proto/upgrade/notifications.rs b/client/network/src/protocol/generic_proto/upgrade/notifications.rs index f626110a3346cd414bab6a936b6f9fcd6290bd76..efcd0a4c8fb7d3fcdc3479eb43ea99f965d14e63 100644 --- a/client/network/src/protocol/generic_proto/upgrade/notifications.rs +++ b/client/network/src/protocol/generic_proto/upgrade/notifications.rs @@ -44,7 +44,7 @@ use unsigned_varint::codec::UviBytes; /// Maximum allowed size of the two handshake messages, in bytes. const MAX_HANDSHAKE_SIZE: usize = 1024; /// Maximum number of buffered messages before we refuse to accept more. -const MAX_PENDING_MESSAGES: usize = 256; +const MAX_PENDING_MESSAGES: usize = 512; /// Upgrade that accepts a substream, sends back a status message, then becomes a unidirectional /// stream of messages. @@ -390,8 +390,8 @@ pub enum NotificationsOutError { /// Remote doesn't process our messages quickly enough. /// /// > **Note**: This is not necessarily the remote's fault, and could also be caused by the - /// > local node sending data too quickly. Properly doing back-pressure, however, - /// > would require a deep refactoring effort in Substrate as a whole. + /// > local node sending data too quickly. Properly doing back-pressure, however, + /// > would require a deep refactoring effort in Substrate as a whole. Clogged, } diff --git a/client/network/src/protocol/message.rs b/client/network/src/protocol/message.rs index ae83b49e60f57e475bb3399ec6af3e9e672e6c8f..a7fbb92387cf6022e894accbdf4855520a912f15 100644 --- a/client/network/src/protocol/message.rs +++ b/client/network/src/protocol/message.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Network packet message types. These get serialized and put into the lower level protocol payload. @@ -85,6 +87,20 @@ bitflags! { } } +impl BlockAttributes { + /// Encodes attributes as big endian u32, compatible with SCALE-encoding (i.e the + /// significant byte has zero index). + pub fn to_be_u32(&self) -> u32 { + u32::from_be_bytes([self.bits(), 0, 0, 0]) + } + + /// Decodes attributes, encoded with the `encode_to_be_u32()` call. + pub fn from_be_u32(encoded: u32) -> Result { + BlockAttributes::from_bits(encoded.to_be_bytes()[0]) + .ok_or_else(|| Error::from("Invalid BlockAttributes")) + } +} + impl Encode for BlockAttributes { fn encode_to(&self, dest: &mut T) { dest.push_byte(self.bits()) @@ -477,11 +493,6 @@ pub mod generic { pub block: H, /// Child Storage key. pub storage_key: Vec, - /// Child trie source information. - pub child_info: Vec, - /// Child type, its required to resolve `child_info` - /// content and choose child implementation. - pub child_type: u32, /// Storage key. pub keys: Vec>, } diff --git a/client/network/src/protocol/sync.rs b/client/network/src/protocol/sync.rs index 9feded784fe78871646879ba49e3b19a866a6d7c..bfd8c4fe218dec5116e1c2d9a49230af1b96fb61 100644 --- a/client/network/src/protocol/sync.rs +++ b/client/network/src/protocol/sync.rs @@ -27,6 +27,7 @@ //! order to update it. //! +use codec::Encode; use blocks::BlockCollection; use sp_blockchain::{Error as ClientError, Info as BlockchainInfo, HeaderMetadata}; use sp_consensus::{BlockOrigin, BlockStatus, @@ -45,8 +46,9 @@ use log::{debug, trace, warn, info, error}; use sp_runtime::{ Justification, generic::BlockId, - traits::{Block as BlockT, Header, NumberFor, Zero, One, CheckedSub, SaturatedConversion} + traits::{Block as BlockT, Header, NumberFor, Zero, One, CheckedSub, SaturatedConversion, Hash, HashFor} }; +use sp_arithmetic::traits::Saturating; use std::{fmt, ops::Range, collections::{HashMap, HashSet, VecDeque}, sync::Arc}; mod blocks; @@ -90,6 +92,12 @@ mod rep { /// Reputation change for peers which send us a known bad block. pub const BAD_BLOCK: Rep = Rep::new(-(1 << 29), "Bad block"); + /// Peer did not provide us with advertised block data. + pub const NO_BLOCK: Rep = Rep::new(-(1 << 29), "No requested block data"); + + /// Reputation change for peers which send us a known block. + pub const KNOWN_BLOCK: Rep = Rep::new(-(1 << 29), "Duplicate block"); + /// Reputation change for peers which send us a block with bad justifications. pub const BAD_JUSTIFICATION: Rep = Rep::new(-(1 << 16), "Bad justification"); @@ -100,6 +108,50 @@ mod rep { pub const UNKNOWN_ANCESTOR:Rep = Rep::new(-(1 << 16), "DB Error"); } +enum PendingRequests { + Some(HashSet), + All, +} + +impl PendingRequests { + fn add(&mut self, id: &PeerId) { + match self { + PendingRequests::Some(set) => { + set.insert(id.clone()); + } + PendingRequests::All => {}, + } + } + + fn take(&mut self) -> PendingRequests { + std::mem::take(self) + } + + fn set_all(&mut self) { + *self = PendingRequests::All; + } + + fn contains(&self, id: &PeerId) -> bool { + match self { + PendingRequests::Some(set) => set.contains(id), + PendingRequests::All => true, + } + } + + fn is_empty(&self) -> bool { + match self { + PendingRequests::Some(set) => set.is_empty(), + PendingRequests::All => false, + } + } +} + +impl Default for PendingRequests { + fn default() -> Self { + PendingRequests::Some(HashSet::default()) + } +} + /// The main data structure which contains all the state for a chains /// active syncing strategy. pub struct ChainSync { @@ -132,14 +184,14 @@ pub struct ChainSync { request_builder: Option>, /// Fork sync targets. fork_targets: HashMap>, - /// A flag that caches idle state with no pending requests. - is_idle: bool, + /// A set of peers for which there might be potential block requests + pending_requests: PendingRequests, /// A type to check incoming block announcements. block_announce_validator: Box + Send>, /// Maximum number of peers to ask the same blocks in parallel. max_parallel_downloads: u32, - /// Total number of processed blocks (imported or failed). - processed_blocks: usize, + /// Total number of downloaded blocks. + downloaded_blocks: usize, } /// All the data we have about a Peer that we are trying to sync with @@ -184,7 +236,11 @@ pub enum PeerSyncState { /// Available for sync requests. Available, /// Searching for ancestors the Peer has in common with us. - AncestorSearch(NumberFor, AncestorSearchState), + AncestorSearch { + start: NumberFor, + current: NumberFor, + state: AncestorSearchState, + }, /// Actively downloading new blocks, starting from the given Number. DownloadingNew(NumberFor), /// Downloading a stale block with given Hash. Stale means that it is a @@ -317,10 +373,10 @@ impl ChainSync { queue_blocks: Default::default(), request_builder, fork_targets: Default::default(), - is_idle: false, + pending_requests: Default::default(), block_announce_validator, max_parallel_downloads, - processed_blocks: 0, + downloaded_blocks: 0, } } @@ -333,7 +389,7 @@ impl ChainSync { /// Returns the current sync status. pub fn status(&self) -> Status { - let best_seen = self.peers.values().max_by_key(|p| p.best_number).map(|p| p.best_number); + let best_seen = self.peers.values().map(|p| p.best_number).max(); let sync_state = if let Some(n) = best_seen { // A chain is classified as downloading if the provided best block is @@ -360,9 +416,9 @@ impl ChainSync { self.fork_targets.len() } - /// Number of processed blocks. - pub fn num_processed_blocks(&self) -> usize { - self.processed_blocks + /// Number of downloaded blocks. + pub fn num_downloaded_blocks(&self) -> usize { + self.downloaded_blocks } /// Handle a new connected peer. @@ -416,7 +472,7 @@ impl ChainSync { state: PeerSyncState::Available, recently_announced: Default::default(), }); - self.is_idle = false; + self.pending_requests.add(&who); return Ok(None) } @@ -428,17 +484,18 @@ impl ChainSync { best_number ); + self.pending_requests.add(&who); self.peers.insert(who, PeerSync { common_number: Zero::zero(), best_hash, best_number, - state: PeerSyncState::AncestorSearch( - common_best, - AncestorSearchState::ExponentialBackoff(One::one()) - ), + state: PeerSyncState::AncestorSearch { + current: common_best, + start: self.best_queued_number, + state: AncestorSearchState::ExponentialBackoff(One::one()), + }, recently_announced: Default::default() }); - self.is_idle = false; Ok(Some(ancestry_request::(common_best))) } @@ -451,16 +508,16 @@ impl ChainSync { state: PeerSyncState::Available, recently_announced: Default::default(), }); - self.is_idle = false; + self.pending_requests.add(&who); Ok(None) } } } - /// Signal that `best_header` has been queued for import and update the + /// Signal that a new best block has been imported. /// `ChainSync` state with that information. - pub fn update_chain_info(&mut self, best_header: &B::Header) { - self.on_block_queued(&best_header.hash(), *best_header.number()) + pub fn update_chain_info(&mut self, best_hash: &B::Hash, best_number: NumberFor) { + self.on_block_queued(best_hash, best_number); } /// Schedule a justification request for the given block. @@ -481,20 +538,25 @@ 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) { + 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(); + + debug!( + target: "sync", + "Explicit sync request for block {:?} with no peers specified. \ + Syncing from these peers {:?} instead.", + hash, peers, + ); } else { debug!(target: "sync", "Explicit sync request for block {:?} with {:?}", hash, peers); } @@ -505,17 +567,17 @@ impl ChainSync { } trace!(target: "sync", "Downloading requested old fork {:?}", hash); - 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 { + if let PeerSyncState::AncestorSearch {..} = peer.state { continue; } if number > peer.best_number { peer.best_number = number; - peer.best_hash = hash.clone(); + peer.best_hash = *hash; } + self.pending_requests.add(peer_id); } } @@ -578,8 +640,8 @@ impl ChainSync { } /// Get an iterator over all block requests of all peers. - pub fn block_requests(&mut self) -> impl Iterator)> + '_ { - if self.is_idle { + pub fn block_requests(&mut self) -> impl Iterator)> + '_ { + if self.pending_requests.is_empty() { return Either::Left(std::iter::empty()) } if self.queue_blocks.len() > MAX_IMPORTING_BLOCKS { @@ -590,17 +652,17 @@ impl ChainSync { let blocks = &mut self.blocks; let attrs = &self.required_block_attributes; let fork_targets = &mut self.fork_targets; - let mut have_requests = false; let last_finalized = self.client.info().finalized_number; let best_queued = self.best_queued_number; let client = &self.client; let queue = &self.queue_blocks; + let pending_requests = self.pending_requests.take(); let max_parallel = if major_sync { 1 } else { self.max_parallel_downloads }; let iter = self.peers.iter_mut().filter_map(move |(id, peer)| { - if !peer.state.is_available() { - trace!(target: "sync", "Peer {} is busy", id); + if !peer.state.is_available() || !pending_requests.contains(id) { return None } + if let Some((range, req)) = peer_block_request( id, peer, @@ -619,8 +681,7 @@ impl ChainSync { peer.common_number, req, ); - have_requests = true; - Some((id.clone(), req)) + Some((id, req)) } else if let Some((hash, req)) = fork_sync_request( id, fork_targets, @@ -635,15 +696,11 @@ impl ChainSync { ) { trace!(target: "sync", "Downloading fork {:?} from {}", hash, id); peer.state = PeerSyncState::DownloadingStale(hash); - have_requests = true; - Some((id.clone(), req)) + Some((id, req)) } else { None } }); - if !have_requests { - self.is_idle = true; - } Either::Right(iter) } @@ -654,23 +711,29 @@ impl ChainSync { /// /// If this corresponds to a valid block, this outputs the block that /// must be imported in the import queue. - pub fn on_block_data - (&mut self, who: PeerId, request: Option>, response: BlockResponse) -> Result, BadPeer> - { + pub fn on_block_data( + &mut self, + who: &PeerId, + request: Option>, + response: BlockResponse + ) -> Result, BadPeer> { + self.downloaded_blocks += response.blocks.len(); let mut new_blocks: Vec> = - if let Some(peer) = self.peers.get_mut(&who) { + if let Some(peer) = self.peers.get_mut(who) { let mut blocks = response.blocks; if request.as_ref().map_or(false, |r| r.direction == message::Direction::Descending) { trace!(target: "sync", "Reversing incoming block list"); blocks.reverse() } - self.is_idle = false; + self.pending_requests.add(who); if request.is_some() { match &mut peer.state { PeerSyncState::DownloadingNew(start_block) => { - self.blocks.clear_peer_download(&who); - self.blocks.insert(*start_block, blocks, who); + self.blocks.clear_peer_download(who); + let start_block = *start_block; peer.state = PeerSyncState::Available; + validate_blocks::(&blocks, who)?; + self.blocks.insert(start_block, blocks, who.clone()); self.blocks .drain(self.best_queued_number + One::one()) .into_iter() @@ -688,6 +751,11 @@ impl ChainSync { } PeerSyncState::DownloadingStale(_) => { peer.state = PeerSyncState::Available; + if blocks.is_empty() { + debug!(target: "sync", "Empty block response from {}", who); + return Err(BadPeer(who.clone(), rep::NO_BLOCK)); + } + validate_blocks::(&blocks, who)?; blocks.into_iter().map(|b| { IncomingBlock { hash: b.hash, @@ -700,31 +768,43 @@ impl ChainSync { } }).collect() } - PeerSyncState::AncestorSearch(num, state) => { - let matching_hash = match (blocks.get(0), self.client.hash(*num)) { + PeerSyncState::AncestorSearch { current, start, state } => { + let matching_hash = match (blocks.get(0), self.client.hash(*current)) { (Some(block), Ok(maybe_our_block_hash)) => { - trace!(target: "sync", "Got ancestry block #{} ({}) from peer {}", num, block.hash, who); + trace!(target: "sync", "Got ancestry block #{} ({}) from peer {}", current, block.hash, who); maybe_our_block_hash.filter(|x| x == &block.hash) }, (None, _) => { debug!(target: "sync", "Invalid response when searching for ancestor from {}", who); - return Err(BadPeer(who, rep::UNKNOWN_ANCESTOR)) + return Err(BadPeer(who.clone(), rep::UNKNOWN_ANCESTOR)) }, (_, Err(e)) => { info!("❌ Error answering legitimate blockchain query: {:?}", e); - return Err(BadPeer(who, rep::BLOCKCHAIN_READ_ERROR)) + return Err(BadPeer(who.clone(), rep::BLOCKCHAIN_READ_ERROR)) } }; - if matching_hash.is_some() && peer.common_number < *num { - peer.common_number = *num; + if matching_hash.is_some() { + if *start < self.best_queued_number && self.best_queued_number <= peer.best_number { + // We've made progress on this chain since the search was started. + // Opportunistically set common number to updated number + // instead of the one that started the search. + peer.common_number = self.best_queued_number; + } + else if peer.common_number < *current { + peer.common_number = *current; + } } - if matching_hash.is_none() && num.is_zero() { + if matching_hash.is_none() && current.is_zero() { trace!(target:"sync", "Ancestry search: genesis mismatch for peer {}", who); - return Err(BadPeer(who, rep::GENESIS_MISMATCH)) + return Err(BadPeer(who.clone(), rep::GENESIS_MISMATCH)) } - if let Some((next_state, next_num)) = handle_ancestor_search_state(state, *num, matching_hash.is_some()) { - peer.state = PeerSyncState::AncestorSearch(next_num, next_state); - return Ok(OnBlockData::Request(who, ancestry_request::(next_num))) + if let Some((next_state, next_num)) = handle_ancestor_search_state(state, *current, matching_hash.is_some()) { + peer.state = PeerSyncState::AncestorSearch { + current: next_num, + start: *start, + state: next_state, + }; + return Ok(OnBlockData::Request(who.clone(), 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. @@ -747,7 +827,7 @@ impl ChainSync { parent_hash: None, peers: Default::default(), }) - .peers.insert(who); + .peers.insert(who.clone()); } peer.state = PeerSyncState::Available; Vec::new() @@ -760,6 +840,7 @@ impl ChainSync { } } else { // When request.is_none() this is a block announcement. Just accept blocks. + validate_blocks::(&blocks, who)?; blocks.into_iter().map(|b| { IncomingBlock { hash: b.hash, @@ -776,18 +857,28 @@ impl ChainSync { Vec::new() }; - let orig_len = new_blocks.len(); - new_blocks.retain(|b| !self.queue_blocks.contains(&b.hash)); - if new_blocks.len() != orig_len { - debug!(target: "sync", "Ignoring {} blocks that are already queued", orig_len - new_blocks.len()); - } - + // When doing initial sync we don't request blocks in parallel. + // So the only way this can happen is when peers lie about the + // common block. let is_recent = new_blocks.first() .map(|block| { self.peers.iter().any(|(_, peer)| peer.recently_announced.contains(&block.hash)) }) .unwrap_or(false); + if !is_recent && new_blocks.last().map_or(false, |b| self.is_known(&b.hash)) { + // When doing initial sync we don't request blocks in parallel. + // So the only way this can happen is when peers lie about the + // common block. + debug!(target: "sync", "Ignoring known blocks from {}", who); + return Err(BadPeer(who.clone(), rep::KNOWN_BLOCK)); + } + let orig_len = new_blocks.len(); + new_blocks.retain(|b| !self.queue_blocks.contains(&b.hash)); + if new_blocks.len() != orig_len { + debug!(target: "sync", "Ignoring {} blocks that are already queued", orig_len - new_blocks.len()); + } + let origin = if is_recent { BlockOrigin::NetworkBroadcast @@ -822,7 +913,7 @@ impl ChainSync { return Ok(OnBlockJustification::Nothing) }; - self.is_idle = false; + self.pending_requests.add(&who); if let PeerSyncState::DownloadingJustification(hash) = peer.state { peer.state = PeerSyncState::Available; @@ -869,7 +960,7 @@ impl ChainSync { return Ok(OnBlockFinalityProof::Nothing) }; - self.is_idle = false; + self.pending_requests.add(&who); if let PeerSyncState::DownloadingFinalityProof(hash) = peer.state { peer.state = PeerSyncState::Available; @@ -912,8 +1003,6 @@ impl ChainSync { for (_, hash) in &results { self.queue_blocks.remove(&hash); } - self.processed_blocks += results.len(); - for (result, hash) in results { if has_error { continue; @@ -992,7 +1081,7 @@ impl ChainSync { }; } - self.is_idle = false; + self.pending_requests.set_all(); output.into_iter() } @@ -1001,12 +1090,12 @@ impl ChainSync { pub fn on_justification_import(&mut self, hash: B::Hash, number: NumberFor, success: bool) { let finalization_result = if success { Ok((hash, number)) } else { Err(()) }; self.extra_justifications.try_finalize_root((hash, number), finalization_result, true); - self.is_idle = false; + self.pending_requests.set_all(); } pub fn on_finality_proof_import(&mut self, req: (B::Hash, NumberFor), res: Result<(B::Hash, NumberFor), ()>) { self.extra_finality_proofs.try_finalize_root(req, res, true); - self.is_idle = false; + self.pending_requests.set_all(); } /// Notify about finalization of the given block. @@ -1035,7 +1124,7 @@ impl ChainSync { /// Updates our internal state for best queued block and then goes /// through all peers to update our view of their state as well. fn on_block_queued(&mut self, hash: &B::Hash, number: NumberFor) { - if let Some(_) = self.fork_targets.remove(&hash) { + if self.fork_targets.remove(&hash).is_some() { trace!(target: "sync", "Completed fork sync {:?}", hash); } if number > self.best_queued_number { @@ -1043,7 +1132,7 @@ impl ChainSync { self.best_queued_hash = *hash; // Update common blocks for (n, peer) in self.peers.iter_mut() { - if let PeerSyncState::AncestorSearch(_, _) = peer.state { + if let PeerSyncState::AncestorSearch {..} = peer.state { // Wait for ancestry search to complete first. continue; } @@ -1064,7 +1153,7 @@ impl ChainSync { peer.common_number = new_common_number; } } - self.is_idle = false; + self.pending_requests.set_all(); } /// Call when a node announces a new block. @@ -1073,7 +1162,7 @@ impl ChainSync { /// 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, announce: &BlockAnnounce, is_best: bool) + pub fn on_block_announce(&mut self, who: &PeerId, hash: B::Hash, announce: &BlockAnnounce, is_best: bool) -> OnBlockAnnounce { let header = &announce.header; @@ -1088,7 +1177,7 @@ impl ChainSync { let ancient_parent = parent_status == BlockStatus::InChainPruned; let known = self.is_known(&hash); - let peer = if let Some(peer) = self.peers.get_mut(&who) { + let peer = if let Some(peer) = self.peers.get_mut(who) { peer } else { error!(target: "sync", "💔 Called on_block_announce with a bad peer ID"); @@ -1098,12 +1187,27 @@ impl ChainSync { peer.recently_announced.pop_front(); } peer.recently_announced.push_back(hash.clone()); + + // Let external validator check the block announcement. + let assoc_data = announce.data.as_ref().map_or(&[][..], |v| v.as_slice()); + let is_best = match self.block_announce_validator.validate(&header, assoc_data) { + Ok(Validation::Success { is_new_best }) => is_new_best || is_best, + 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 + } + }; + if is_best { // update their best block peer.best_number = number; peer.best_hash = hash; } - if let PeerSyncState::AncestorSearch(_, _) = peer.state { + if let PeerSyncState::AncestorSearch {..} = peer.state { return OnBlockAnnounce::Nothing } // If the announced block is the best they have and is not ahead of us, our common number @@ -1117,31 +1221,17 @@ impl ChainSync { peer.common_number = number - One::one(); } } - self.is_idle = false; + self.pending_requests.add(who); // 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); + target.peers.insert(who.clone()); } 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 - } - } - if ancient_parent { trace!(target: "sync", "Ignored ancient block announced from {}: {} {:?}", who, hash, header); return OnBlockAnnounce::Nothing @@ -1162,34 +1252,33 @@ impl ChainSync { .entry(hash.clone()) .or_insert_with(|| ForkTarget { number, - parent_hash: Some(header.parent_hash().clone()), + parent_hash: Some(*header.parent_hash()), peers: Default::default(), }) - .peers.insert(who); + .peers.insert(who.clone()); } OnBlockAnnounce::Nothing } /// Call when a peer has disconnected. - pub fn peer_disconnected(&mut self, who: PeerId) { - self.blocks.clear_peer_download(&who); - self.peers.remove(&who); - self.extra_justifications.peer_disconnected(&who); - self.extra_finality_proofs.peer_disconnected(&who); - self.is_idle = false; + pub fn peer_disconnected(&mut self, who: &PeerId) { + self.blocks.clear_peer_download(who); + self.peers.remove(who); + self.extra_justifications.peer_disconnected(who); + self.extra_finality_proofs.peer_disconnected(who); + self.pending_requests.set_all(); } /// Restart the sync process. fn restart<'a>(&'a mut self) -> impl Iterator), BadPeer>> + 'a { - self.processed_blocks = 0; self.blocks.clear(); let info = self.client.info(); self.best_queued_hash = info.best_hash; self.best_queued_number = std::cmp::max(info.best_number, self.best_imported_number); - self.is_idle = false; + self.pending_requests.set_all(); debug!(target:"sync", "Restarted with {} ({})", self.best_queued_number, self.best_queued_hash); - let old_peers = std::mem::replace(&mut self.peers, HashMap::new()); + let old_peers = std::mem::take(&mut self.peers); old_peers.into_iter().filter_map(move |(id, p)| { match self.new_peer(id.clone(), p.best_hash, p.best_number) { Ok(None) => None, @@ -1341,14 +1430,24 @@ fn peer_block_request( max_parallel_downloads, MAX_DOWNLOAD_AHEAD, ) { + // The end is not part of the range. + let last = range.end.saturating_sub(One::one()); + + let from = if peer.best_number == last { + message::FromBlock::Hash(peer.best_hash) + } else { + message::FromBlock::Number(last) + }; + let request = message::generic::BlockRequest { id: 0, fields: attrs.clone(), - from: message::FromBlock::Number(range.start), + from, to: None, - direction: message::Direction::Ascending, + direction: message::Direction::Descending, max: Some((range.end - range.start).saturated_into::()) }; + Some((range, request)) } else { None @@ -1382,11 +1481,12 @@ fn fork_sync_request( } if r.number <= best_num { 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 { + let count = if parent_status == BlockStatus::Unknown { + (r.number - finalized).saturated_into::() // up to the last finalized block + } else { // request only single block - count = 1; - } + 1 + }; trace!(target: "sync", "Downloading requested fork {:?} from {}, {} blocks", hash, id, count); return Some((hash.clone(), message::generic::BlockRequest { id: 0, @@ -1416,6 +1516,40 @@ fn is_descendent_of(client: &T, base: &Block::Hash, block: &Block::Has Ok(ancestor.hash == *base) } +fn validate_blocks(blocks: &Vec>, who: &PeerId) -> Result<(), BadPeer> { + for b in blocks { + if let Some(header) = &b.header { + let hash = header.hash(); + if hash != b.hash { + debug!( + target:"sync", + "Bad header received from {}. Expected hash {:?}, got {:?}", + who, + b.hash, + hash, + ); + return Err(BadPeer(who.clone(), rep::BAD_BLOCK)) + } + } + if let (Some(header), Some(body)) = (&b.header, &b.body) { + let expected = *header.extrinsics_root(); + let got = HashFor::::ordered_trie_root(body.iter().map(Encode::encode).collect()); + if expected != got { + debug!( + target:"sync", + "Bad extrinsic root for a block {} received from {}. Expected {:?}, got {:?}", + b.hash, + who, + expected, + got, + ); + return Err(BadPeer(who.clone(), rep::BAD_BLOCK)) + } + } + } + Ok(()) +} + #[cfg(test)] mod test { use super::*; @@ -1436,7 +1570,7 @@ mod test { let client = Arc::new(TestClientBuilder::new().build()); let info = client.info(); - let block_announce_validator = Box::new(DefaultBlockAnnounceValidator::new(client.clone())); + let block_announce_validator = Box::new(DefaultBlockAnnounceValidator); let peer_id = PeerId::random(); let mut sync = ChainSync::new( diff --git a/client/network/src/protocol/sync/blocks.rs b/client/network/src/protocol/sync/blocks.rs index 359287701e66e5b95b9561bbd5982fd50e77e08d..b64c9e053e97b3018562beca4f439d71f17c8edb 100644 --- a/client/network/src/protocol/sync/blocks.rs +++ b/client/network/src/protocol/sync/blocks.rs @@ -1,23 +1,24 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use std::cmp; use std::ops::Range; use std::collections::{HashMap, BTreeMap}; -use std::collections::hash_map::Entry; use log::trace; use libp2p::PeerId; use sp_runtime::traits::{Block as BlockT, NumberFor, One}; @@ -116,17 +117,17 @@ impl BlockCollection { let mut prev: Option<(&NumberFor, &BlockRangeState)> = None; loop { let next = downloading_iter.next(); - break match &(prev, next) { - &(Some((start, &BlockRangeState::Downloading { ref len, downloading })), _) + break match (prev, next) { + (Some((start, &BlockRangeState::Downloading { ref len, downloading })), _) if downloading < max_parallel => (*start .. *start + *len, downloading), - &(Some((start, r)), Some((next_start, _))) if *start + r.len() < *next_start => + (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 - &(Some((start, r)), None) => + (Some((start, r)), None) => (*start + r.len() .. *start + r.len() + count, 0), // last range - &(None, None) => + (None, None) => (first_different .. first_different + count, 0), // empty - &(None, Some((start, _))) if *start > first_different => + (None, Some((start, _))) if *start > first_different => (first_different .. cmp::min(first_different + count, *start), 0), // gap at the start _ => { prev = next; @@ -167,7 +168,7 @@ impl BlockCollection { let mut prev = from; for (start, range_data) in &mut self.blocks { match range_data { - &mut BlockRangeState::Complete(ref mut blocks) if *start <= prev => { + BlockRangeState::Complete(blocks) if *start <= prev => { prev = *start + (blocks.len() as u32).into(); // Remove all elements from `blocks` and add them to `drained` drained.append(blocks); @@ -185,26 +186,22 @@ impl BlockCollection { } pub fn clear_peer_download(&mut self, who: &PeerId) { - match self.peer_requests.entry(who.clone()) { - Entry::Occupied(entry) => { - let start = entry.remove(); - let remove = match self.blocks.get_mut(&start) { - Some(&mut BlockRangeState::Downloading { ref mut downloading, .. }) if *downloading > 1 => { - *downloading = *downloading - 1; - false - }, - Some(&mut BlockRangeState::Downloading { .. }) => { - true - }, - _ => { - false - } - }; - if remove { - self.blocks.remove(&start); + if let Some(start) = self.peer_requests.remove(who) { + let remove = match self.blocks.get_mut(&start) { + Some(&mut BlockRangeState::Downloading { ref mut downloading, .. }) if *downloading > 1 => { + *downloading -= 1; + false + }, + Some(&mut BlockRangeState::Downloading { .. }) => { + true + }, + _ => { + false } - }, - _ => (), + }; + if remove { + self.blocks.remove(&start); + } } } } diff --git a/client/network/src/protocol/sync/extra_requests.rs b/client/network/src/protocol/sync/extra_requests.rs index 3d854b574b01fc26aaf6d1d39e15bed2b46551c2..6d688c130fafdec413e3ff905f3e33802cb85aeb 100644 --- a/client/network/src/protocol/sync/extra_requests.rs +++ b/client/network/src/protocol/sync/extra_requests.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use sp_blockchain::Error as ClientError; use crate::protocol::sync::{PeerSync, PeerSyncState}; @@ -102,11 +104,9 @@ impl ExtraRequests { // 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) => { debug!(target: "sync", "Failed to insert request {:?} into tree: {:?}", request, err); - return; } _ => () } diff --git a/client/network/src/schema.rs b/client/network/src/schema.rs new file mode 100644 index 0000000000000000000000000000000000000000..44fbbffd25406d5b985707f46f8c2e9123ca992a --- /dev/null +++ b/client/network/src/schema.rs @@ -0,0 +1,29 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Include sources generated from protobuf definitions. + +pub mod v1 { + include!(concat!(env!("OUT_DIR"), "/api.v1.rs")); + pub mod finality { + include!(concat!(env!("OUT_DIR"), "/api.v1.finality.rs")); + } + pub mod light { + include!(concat!(env!("OUT_DIR"), "/api.v1.light.rs")); + } +} diff --git a/client/network/src/protocol/schema/api.v1.proto b/client/network/src/schema/api.v1.proto similarity index 81% rename from client/network/src/protocol/schema/api.v1.proto rename to client/network/src/schema/api.v1.proto index ccbf49d666115ea50fbe08885c9242c891d805a1..a933c5811c109616c7adec903b17293ddebaeab7 100644 --- a/client/network/src/protocol/schema/api.v1.proto +++ b/client/network/src/schema/api.v1.proto @@ -51,5 +51,10 @@ message BlockData { bytes message_queue = 5; // optional // Justification if requested. bytes justification = 6; // optional + // True if justification should be treated as present but empty. + // This hack is unfortunately necessary because shortcomings in the protobuf format otherwise + // doesn't make in possible to differentiate between a lack of justification and an empty + // justification. + bool is_empty_justification = 7; // optional, false if absent } diff --git a/client/network/src/schema/finality.v1.proto b/client/network/src/schema/finality.v1.proto new file mode 100644 index 0000000000000000000000000000000000000000..843bc4eca0990cc01b1479e19d68a721395266c4 --- /dev/null +++ b/client/network/src/schema/finality.v1.proto @@ -0,0 +1,19 @@ +// Schema definition for finality proof request/responses. + +syntax = "proto3"; + +package api.v1.finality; + +// Request a finality proof from a peer. +message FinalityProofRequest { + // SCALE-encoded hash of the block to request. + bytes block_hash = 1; + // Opaque chain-specific additional request data. + bytes request = 2; +} + +// Response to a finality proof request. +message FinalityProofResponse { + // Opaque chain-specific finality proof. Empty if no such proof exists. + bytes proof = 1; // optional +} diff --git a/client/network/src/protocol/schema/light.v1.proto b/client/network/src/schema/light.v1.proto similarity index 93% rename from client/network/src/protocol/schema/light.v1.proto rename to client/network/src/schema/light.v1.proto index 1c98d49730cf98dcafb9999056682f6c40efb101..9b5d47719dc28e7930e449ef2fa05a6333a4a18d 100644 --- a/client/network/src/protocol/schema/light.v1.proto +++ b/client/network/src/schema/light.v1.proto @@ -67,13 +67,9 @@ message RemoteReadResponse { message RemoteReadChildRequest { // Block at which to perform call. bytes block = 2; - // Child Storage key. + // Child Storage key, this is relative + // to the child type storage location. bytes storage_key = 3; - // Child trie source information. - bytes child_info = 4; - /// Child type, its required to resolve `child_info` - /// content and choose child implementation. - uint32 child_type = 5; // Storage keys. repeated bytes keys = 6; } diff --git a/client/network/src/service.rs b/client/network/src/service.rs index abe9231abf22e51a19c52c987ac650edbfc9663c..7d4135de6b9ed68d97862da85d0f55f8cd201d42 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Main entry point of the sc-network crate. //! @@ -26,20 +28,25 @@ //! which is then processed by [`NetworkWorker::poll`]. use crate::{ + ExHashT, NetworkStateInfo, behaviour::{Behaviour, BehaviourOut}, config::{parse_addr, parse_str_addr, NonReservedPeerMode, Params, Role, TransportConfig}, + discovery::DiscoveryConfig, error::Error, network_state::{ NetworkState, NotConnectedPeer as NetworkStateNotConnectedPeer, Peer as NetworkStatePeer, }, on_demand_layer::AlwaysBadChecker, - protocol::{self, event::Event, light_client_handler, sync::SyncState, PeerInfo, Protocol}, + light_client_handler, block_requests, finality_requests, + protocol::{self, event::Event, LegacyConnectionKillError, sync::SyncState, PeerInfo, Protocol}, transport, ReputationChange, }; use futures::prelude::*; -use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedSender, TracingUnboundedReceiver}; -use libp2p::swarm::{NetworkBehaviour, SwarmBuilder, SwarmEvent}; -use libp2p::{kad::record, Multiaddr, PeerId}; +use libp2p::{PeerId, Multiaddr}; +use libp2p::core::{ConnectedPoint, Executor, connection::{ConnectionError, PendingConnectionError}, either::EitherError}; +use libp2p::kad::record; +use libp2p::ping::handler::PingFailure; +use libp2p::swarm::{NetworkBehaviour, SwarmBuilder, SwarmEvent, protocols_handler::NodeHandlerWrapperError}; use log::{error, info, trace, warn}; use parking_lot::Mutex; use prometheus_endpoint::{ @@ -51,98 +58,25 @@ use sp_runtime::{ traits::{Block as BlockT, NumberFor}, ConsensusEngineId, }; +use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; use std::{ - borrow::Cow, - collections::{HashMap, HashSet}, - fs, io, + borrow::{Borrow, Cow}, + collections::HashSet, + fs, marker::PhantomData, - path::Path, + num:: NonZeroUsize, pin::Pin, str, - sync::{atomic::{AtomicBool, AtomicUsize, Ordering}, Arc}, + sync::{ + atomic::{AtomicBool, AtomicUsize, Ordering}, + Arc, + }, task::Poll, }; -/// Minimum Requirements for a Hash within Networking -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 -{} - -/// 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. - /// - /// 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: ReputationChange, - reputation_change_bad: ReputationChange, - transaction: B::Extrinsic, - ); - /// Notify the pool about transactions broadcast. - fn on_broadcasted(&self, propagations: HashMap>); - /// Get transaction by hash. - fn transaction(&self, hash: &H) -> Option; -} - -/// Dummy implementation of the [`TransactionPool`] trait for a transaction pool that is always -/// empty and discards all incoming transactions. -/// -/// Requires the "hash" type to implement the `Default` trait. -/// -/// Useful for testing purposes. -pub struct EmptyTransactionPool; - -impl TransactionPool for EmptyTransactionPool { - fn transactions(&self) -> Vec<(H, B::Extrinsic)> { - Vec::new() - } - - fn hash_of(&self, _transaction: &B::Extrinsic) -> H { - Default::default() - } - - fn import( - &self, - _report_handle: ReportHandle, - _who: PeerId, - _rep_change_good: ReputationChange, - _rep_change_bad: ReputationChange, - _transaction: B::Extrinsic - ) {} - - fn on_broadcasted(&self, _: HashMap>) {} - - fn transaction(&self, _h: &H) -> Option { None } -} - -/// A cloneable handle for reporting cost/benefits of peers. -#[derive(Clone)] -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. - pub fn report_peer(&self, who: PeerId, cost_benefit: ReputationChange) { - self.inner.report_peer(who, cost_benefit); - } -} +mod out_events; +#[cfg(test)] +mod tests; /// Substrate network service. Handles network IO and manages connectivity. pub struct NetworkService { @@ -173,10 +107,28 @@ impl NetworkWorker { /// 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> { + // Ensure the listen addresses are consistent with the transport. + ensure_addresses_consistent_with_transport( + params.network_config.listen_addresses.iter(), + ¶ms.network_config.transport, + )?; + ensure_addresses_consistent_with_transport( + params.network_config.boot_nodes.iter().map(|x| &x.multiaddr), + ¶ms.network_config.transport, + )?; + ensure_addresses_consistent_with_transport( + params.network_config.reserved_nodes.iter().map(|x| &x.multiaddr), + ¶ms.network_config.transport, + )?; + ensure_addresses_consistent_with_transport( + params.network_config.public_addresses.iter(), + ¶ms.network_config.transport, + )?; + let (to_worker, from_worker) = tracing_unbounded("mpsc_network_worker"); - if let Some(ref path) = params.network_config.net_config_path { - fs::create_dir_all(Path::new(path))?; + if let Some(path) = params.network_config.net_config_path { + fs::create_dir_all(&path)?; } // List of multiaddresses that we know in the network. @@ -223,12 +175,14 @@ impl NetworkWorker { Role::Sentry { validators } => { for validator in validators { sentries_and_validators.insert(validator.peer_id.clone()); + reserved_nodes.insert(validator.peer_id.clone()); known_addresses.push((validator.peer_id.clone(), validator.multiaddr.clone())); } } Role::Authority { sentry_nodes } => { for sentry_node in sentry_nodes { sentries_and_validators.insert(sentry_node.peer_id.clone()); + reserved_nodes.insert(sentry_node.peer_id.clone()); known_addresses.push((sentry_node.peer_id.clone(), sentry_node.multiaddr.clone())); } } @@ -253,7 +207,13 @@ impl NetworkWorker { 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(); - info!(target: "sub-libp2p", "🏷 Local node identity is: {}", local_peer_id.to_base58()); + let local_peer_id_legacy = bs58::encode(Borrow::<[u8]>::borrow(&local_peer_id)).into_string(); + info!( + target: "sub-libp2p", + "🏷 Local node identity is: {} (legacy representation: {})", + local_peer_id.to_base58(), + local_peer_id_legacy + ); // Initialize the metrics. let metrics = match ¶ms.metrics_registry { @@ -263,7 +223,7 @@ impl NetworkWorker { let checker = params.on_demand.as_ref() .map(|od| od.checker().clone()) - .unwrap_or(Arc::new(AlwaysBadChecker)); + .unwrap_or_else(|| Arc::new(AlwaysBadChecker)); let num_connected = Arc::new(AtomicUsize::new(0)); let is_major_syncing = Arc::new(AtomicBool::new(false)); @@ -272,6 +232,7 @@ impl NetworkWorker { roles: From::from(¶ms.role), max_parallel_downloads: params.network_config.max_parallel_downloads, }, + local_peer_id.clone(), params.chain.clone(), params.transaction_pool, params.finality_proof_provider.clone(), @@ -285,38 +246,65 @@ impl NetworkWorker { )?; // Build the swarm. - let (mut swarm, bandwidth): (Swarm::, _) = { + let (mut swarm, bandwidth): (Swarm, _) = { let user_agent = format!( "{} ({})", params.network_config.client_version, params.network_config.node_name ); let block_requests = { - let config = protocol::block_requests::Config::new(¶ms.protocol_id); - protocol::BlockRequests::new(config, params.chain.clone()) + let config = block_requests::Config::new(¶ms.protocol_id); + block_requests::BlockRequests::new(config, params.chain.clone()) + }; + let finality_proof_requests = { + let config = finality_requests::Config::new(¶ms.protocol_id); + finality_requests::FinalityProofRequests::new(config, params.finality_proof_provider.clone()) }; let light_client_handler = { - let config = protocol::light_client_handler::Config::new(¶ms.protocol_id); - protocol::LightClientHandler::new(config, params.chain, checker, peerset_handle.clone()) + let config = light_client_handler::Config::new(¶ms.protocol_id); + light_client_handler::LightClientHandler::new( + config, + params.chain, + checker, + peerset_handle.clone(), + ) }; - let behaviour = futures::executor::block_on(Behaviour::new( + + let discovery_config = { + let mut config = DiscoveryConfig::new(local_public.clone()); + config.with_user_defined(known_addresses); + config.discovery_limit(u64::from(params.network_config.out_peers) + 15); + config.add_protocol(params.protocol_id.clone()); + config.allow_non_globals_in_dht(params.network_config.allow_non_globals_in_dht); + + match params.network_config.transport { + TransportConfig::MemoryOnly => { + config.with_mdns(false); + config.allow_private_ipv4(false); + } + TransportConfig::Normal { enable_mdns, allow_private_ipv4, .. } => { + config.with_mdns(enable_mdns); + config.allow_private_ipv4(allow_private_ipv4); + } + } + + config + }; + + let mut behaviour = Behaviour::new( protocol, params.role, user_agent, local_public, - known_addresses, - match params.network_config.transport { - TransportConfig::MemoryOnly => false, - TransportConfig::Normal { enable_mdns, .. } => enable_mdns, - }, - match params.network_config.transport { - TransportConfig::MemoryOnly => false, - TransportConfig::Normal { allow_private_ipv4, .. } => allow_private_ipv4, - }, - u64::from(params.network_config.out_peers) + 15, block_requests, - light_client_handler - )); + finality_proof_requests, + light_client_handler, + discovery_config + ); + + for (engine_id, protocol_name) in ¶ms.network_config.notifications_protocols { + behaviour.register_notifications_protocol(*engine_id, protocol_name.clone()); + } let (transport, bandwidth) = { let (config_mem, config_wasm, flowctrl) = match params.network_config.transport { TransportConfig::MemoryOnly => (true, None, false), @@ -325,9 +313,18 @@ impl NetworkWorker { }; transport::build_transport(local_identity, config_mem, config_wasm, flowctrl) }; - let mut builder = SwarmBuilder::new(transport, behaviour, local_peer_id.clone()); + let mut builder = SwarmBuilder::new(transport, behaviour, local_peer_id.clone()) + .peer_connection_limit(crate::MAX_CONNECTIONS_PER_PEER) + .notify_handler_buffer_size(NonZeroUsize::new(32).expect("32 != 0; qed")) + .connection_event_buffer_size(1024); if let Some(spawner) = params.executor { - builder = builder.executor_fn(spawner); + struct SpawnImpl(F); + impl + Send>>)> Executor for SpawnImpl { + fn exec(&self, f: Pin + Send>>) { + (self.0)(f) + } + } + builder = builder.executor(Box::new(SpawnImpl(spawner))); } (builder.build(), bandwidth) }; @@ -353,7 +350,7 @@ impl NetworkWorker { is_major_syncing: is_major_syncing.clone(), peerset: peerset_handle, local_peer_id, - to_worker: to_worker.clone(), + to_worker, _marker: PhantomData, }); @@ -366,7 +363,7 @@ impl NetworkWorker { import_queue: params.import_queue, from_worker, light_client_rqs: params.on_demand.and_then(|od| od.extract_receiver()), - event_streams: Vec::new(), + event_streams: out_events::OutChannels::new(params.metrics_registry.as_ref())?, metrics, boot_node_ids, }) @@ -412,9 +409,9 @@ impl NetworkWorker { self.network_service.user_protocol().num_queued_blocks() } - /// Returns the number of processed blocks. - pub fn num_processed_blocks(&self) -> usize { - self.network_service.user_protocol().num_processed_blocks() + /// Returns the number of downloaded blocks. + pub fn num_downloaded_blocks(&self) -> usize { + self.network_service.user_protocol().num_downloaded_blocks() } /// Number of active sync requests. @@ -433,16 +430,30 @@ impl NetworkWorker { &self.service } - /// You must call this when a new block is imported by the client. - pub fn on_block_imported(&mut self, header: B::Header, is_best: bool) { - self.network_service.user_protocol_mut().on_block_imported(&header, is_best); - } - /// You must call this when a new block is finalized by the client. pub fn on_block_finalized(&mut self, hash: B::Hash, header: B::Header) { self.network_service.user_protocol_mut().on_block_finalized(hash, &header); } + /// This should be called when blocks are added to the + /// chain by something other than the import queue. + /// Currently this is only useful for tests. + pub fn update_chain(&mut self) { + self.network_service.user_protocol_mut().update_chain(); + } + + /// Returns the local `PeerId`. + pub fn local_peer_id(&self) -> &PeerId { + Swarm::::local_peer_id(&self.network_service) + } + + /// Returns the list of addresses we are listening on. + /// + /// Does **NOT** include a trailing `/p2p/` with our `PeerId`. + pub fn listen_addresses(&self) -> impl Iterator { + Swarm::::listeners(&self.network_service) + } + /// Get network state. /// /// **Note**: Use this only for debugging. This API is unstable. There are warnings literally @@ -468,7 +479,7 @@ impl NetworkWorker { Some((peer_id.to_base58(), NetworkStatePeer { endpoint, version_string: swarm.node(peer_id) - .and_then(|i| i.client_version().map(|s| s.to_owned())).clone(), + .and_then(|i| i.client_version().map(|s| s.to_owned())), latest_ping_time: swarm.node(peer_id).and_then(|i| i.latest_ping()), enabled: swarm.user_protocol().is_enabled(&peer_id), open: swarm.user_protocol().is_open(&peer_id), @@ -479,17 +490,18 @@ impl NetworkWorker { let not_connected_peers = { let swarm = &mut *swarm; - let list = swarm.known_peers().filter(|p| open.iter().all(|n| n != *p)) - .cloned().collect::>(); - list.into_iter().map(move |peer_id| { - (peer_id.to_base58(), NetworkStateNotConnectedPeer { - version_string: swarm.node(&peer_id) - .and_then(|i| i.client_version().map(|s| s.to_owned())).clone(), - latest_ping_time: swarm.node(&peer_id).and_then(|i| i.latest_ping()), - known_addresses: NetworkBehaviour::addresses_of_peer(&mut **swarm, &peer_id) - .into_iter().collect(), + swarm.known_peers().into_iter() + .filter(|p| open.iter().all(|n| n != p)) + .map(move |peer_id| { + (peer_id.to_base58(), NetworkStateNotConnectedPeer { + version_string: swarm.node(&peer_id) + .and_then(|i| i.client_version().map(|s| s.to_owned())), + latest_ping_time: swarm.node(&peer_id).and_then(|i| i.latest_ping()), + known_addresses: NetworkBehaviour::addresses_of_peer(&mut **swarm, &peer_id) + .into_iter().collect(), + }) }) - }).collect() + .collect() }; NetworkState { @@ -525,6 +537,11 @@ impl NetworkWorker { } impl NetworkService { + /// Returns the local `PeerId`. + pub fn local_peer_id(&self) -> &PeerId { + &self.local_peer_id + } + /// Writes a message on an open notifications channel. Has no effect if the notifications /// channel with this protocol name is closed. /// @@ -549,22 +566,30 @@ impl NetworkService { /// If this method is called multiple times, the events are duplicated. /// /// The stream never ends (unless the `NetworkWorker` gets shut down). - pub fn event_stream(&self) -> impl Stream { + /// + /// The name passed is used to identify the channel in the Prometheus metrics. Note that the + /// parameter is a `&'static str`, and not a `String`, in order to avoid accidentally having + /// an unbounded set of Prometheus metrics, which would be quite bad in terms of memory + pub fn event_stream(&self, name: &'static str) -> impl Stream { // Note: when transitioning to stable futures, remove the `Error` entirely - let (tx, rx) = tracing_unbounded("mpsc_network_event_stream"); + let (tx, rx) = out_events::channel(name); let _ = self.to_worker.unbounded_send(ServiceToWorkerMsg::EventStream(tx)); rx } /// Registers a new notifications protocol. /// - /// After that, you can call `write_notifications`. + /// After a protocol has been registered, you can call `write_notifications`. + /// + /// **Important**: This method is a work-around, and you are instead strongly encouraged to + /// pass the protocol in the `NetworkConfiguration::notifications_protocols` list instead. + /// If you have no other choice but to use this method, you are very strongly encouraged to + /// call it very early on. Any connection open will retain the protocols that were registered + /// then, and not any new one. /// /// Please call `event_stream` before registering a protocol, otherwise you may miss events /// about the protocol that you have registered. - /// - /// You are very strongly encouraged to call this method very early on. Any connection open - /// will retain the protocols that were registered then, and not any new one. + // TODO: remove this method after https://github.com/paritytech/substrate/issues/4587 pub fn register_notifications_protocol( &self, engine_id: ConsensusEngineId, @@ -581,15 +606,15 @@ impl NetworkService { /// All transactions will be fetched from the `TransactionPool` that was passed at /// initialization as part of the configuration and propagated to peers. pub fn trigger_repropagate(&self) { - let _ = self.to_worker.unbounded_send(ServiceToWorkerMsg::PropagateExtrinsics); + let _ = self.to_worker.unbounded_send(ServiceToWorkerMsg::PropagateTransactions); } /// You must call when new transaction is imported by the transaction pool. /// /// This transaction will be fetched from the `TransactionPool` that was passed at /// initialization as part of the configuration and propagated to peers. - pub fn propagate_extrinsic(&self, hash: H) { - let _ = self.to_worker.unbounded_send(ServiceToWorkerMsg::PropagateExtrinsic(hash)); + pub fn propagate_transaction(&self, hash: H) { + let _ = self.to_worker.unbounded_send(ServiceToWorkerMsg::PropagateTransaction(hash)); } /// Make sure an important block is propagated to peers. @@ -620,7 +645,7 @@ impl NetworkService { pub fn request_justification(&self, hash: &B::Hash, number: NumberFor) { let _ = self .to_worker - .unbounded_send(ServiceToWorkerMsg::RequestJustification(hash.clone(), number)); + .unbounded_send(ServiceToWorkerMsg::RequestJustification(*hash, number)); } /// Are we in the process of downloading the chain? @@ -665,8 +690,15 @@ impl NetworkService { /// Adds a `PeerId` and its address as reserved. The string should encode the address /// and peer ID of the remote node. + /// + /// Returns an `Err` if the given string is not a valid multiaddress + /// or contains an invalid peer ID (which includes the local peer ID). pub fn add_reserved_peer(&self, peer: String) -> Result<(), String> { let (peer_id, addr) = parse_str_addr(&peer).map_err(|e| format!("{:?}", e))?; + // Make sure the local peer ID is never added to the PSM. + if peer_id == self.local_peer_id { + return Err("Local peer ID cannot be added as a reserved peer.".to_string()) + } self.peerset.add_reserved_peer(peer_id.clone()); let _ = self .to_worker @@ -687,12 +719,26 @@ impl NetworkService { } /// Modify a peerset priority group. + /// + /// Returns an `Err` if one of the given addresses contains an invalid + /// peer ID (which includes the local peer ID). pub fn set_priority_group(&self, group_id: String, peers: HashSet) -> Result<(), String> { - let peers = peers.into_iter().map(|p| { - parse_addr(p).map_err(|e| format!("{:?}", e)) - }).collect::, String>>()?; + let peers = peers.into_iter() + .map(|p| match parse_addr(p) { + Err(e) => Err(format!("{:?}", e)), + Ok((peer, addr)) => + // Make sure the local peer ID is never added to the PSM + // or added as a "known address", even if given. + if peer == self.local_peer_id { + Err("Local peer ID in priority group.".to_string()) + } else { + Ok((peer, addr)) + } + }) + .collect::, String>>()?; let peer_ids = peers.iter().map(|(peer_id, _addr)| peer_id.clone()).collect(); + self.peerset.set_priority_group(group_id, peer_ids); for (peer_id, addr) in peers.into_iter() { @@ -708,6 +754,23 @@ impl NetworkService { pub fn num_connected(&self) -> usize { self.num_connected.load(Ordering::Relaxed) } + + /// This function should be called when blocks are added to the chain by something other + /// than the import queue. + /// + /// > **Important**: This function is a hack and can be removed at any time. Do **not** use it. + pub fn update_chain(&self) { + let _ = self + .to_worker + .unbounded_send(ServiceToWorkerMsg::UpdateChain); + } + + /// Inform the network service about an own imported block. + pub fn own_block_imported(&self, hash: B::Hash, number: NumberFor) { + let _ = self + .to_worker + .unbounded_send(ServiceToWorkerMsg::OwnBlockImported(hash, number)); + } } impl sp_consensus::SyncOracle @@ -734,15 +797,6 @@ impl<'a, B: BlockT + 'static, H: ExHashT> sp_consensus::SyncOracle } } -/// Trait for providing information about the local network state -pub trait NetworkStateInfo { - /// Returns the local external addresses. - fn external_addresses(&self) -> Vec; - - /// Returns the local Peer ID. - fn local_peer_id(&self) -> PeerId; -} - impl NetworkStateInfo for NetworkService where B: sp_runtime::traits::Block, @@ -763,15 +817,15 @@ impl NetworkStateInfo for NetworkService /// /// Each entry corresponds to a method of `NetworkService`. enum ServiceToWorkerMsg { - PropagateExtrinsic(H), - PropagateExtrinsics, + PropagateTransaction(H), + PropagateTransactions, RequestJustification(B::Hash, NumberFor), AnnounceBlock(B::Hash, Vec), GetValue(record::Key), PutValue(record::Key, Vec), AddKnownAddress(PeerId, Multiaddr), SyncFork(Vec, B::Hash, NumberFor), - EventStream(TracingUnboundedSender), + EventStream(out_events::Sender), WriteNotification { message: Vec, engine_id: ConsensusEngineId, @@ -782,6 +836,8 @@ enum ServiceToWorkerMsg { protocol_name: Cow<'static, [u8]>, }, DisconnectPeer(PeerId), + UpdateChain, + OwnBlockImported(B::Hash, NumberFor), } /// Main network worker. Must be polled in order for the network to advance. @@ -806,7 +862,7 @@ pub struct NetworkWorker { /// Receiver for queries from the light client that must be processed. light_client_rqs: Option>>, /// Senders for events that happen on the network. - event_streams: Vec>, + event_streams: out_events::OutChannels, /// Prometheus network metrics. metrics: Option, /// The `PeerId`'s of all boot nodes. @@ -815,30 +871,63 @@ pub struct NetworkWorker { struct Metrics { // This list is ordered alphabetically - connections: Gauge, + connections_closed_total: CounterVec, + connections_opened_total: CounterVec, + distinct_peers_connections_closed_total: Counter, + distinct_peers_connections_opened_total: Counter, import_queue_blocks_submitted: Counter, import_queue_finality_proofs_submitted: Counter, import_queue_justifications_submitted: Counter, + incoming_connections_errors_total: CounterVec, + incoming_connections_total: Counter, is_major_syncing: Gauge, issued_light_requests: Counter, - kbuckets_num_nodes: Gauge, + kademlia_random_queries_total: CounterVec, + kademlia_records_count: GaugeVec, + kademlia_records_sizes_total: GaugeVec, + kbuckets_num_nodes: GaugeVec, + listeners_local_addresses: Gauge, + listeners_errors_total: Counter, network_per_sec_bytes: GaugeVec, notifications_queues_size: HistogramVec, - notifications_total: CounterVec, - num_event_stream_channels: Gauge, - opened_notification_streams: GaugeVec, + notifications_sizes: HistogramVec, + notifications_streams_closed_total: CounterVec, + notifications_streams_opened_total: CounterVec, peers_count: Gauge, peerset_num_discovered: Gauge, peerset_num_requested: Gauge, - random_kademalia_queries_total: Counter, + pending_connections: Gauge, + pending_connections_errors_total: CounterVec, + requests_in_total: HistogramVec, + requests_out_finished: HistogramVec, + requests_out_started_total: CounterVec, } impl Metrics { fn register(registry: &Registry) -> Result { Ok(Self { // This list is ordered alphabetically - connections: register(Gauge::new( - "sub_libp2p_connections", "Number of libp2p connections" + connections_closed_total: register(CounterVec::new( + Opts::new( + "sub_libp2p_connections_closed_total", + "Total number of connections closed, by direction and reason" + ), + &["direction", "reason"] + )?, registry)?, + connections_opened_total: register(CounterVec::new( + Opts::new( + "sub_libp2p_connections_opened_total", + "Total number of connections opened by direction" + ), + &["direction"] + )?, registry)?, + distinct_peers_connections_closed_total: register(Counter::new( + "sub_libp2p_distinct_peers_connections_closed_total", + "Total number of connections closed with distinct peers" + )?, registry)?, + distinct_peers_connections_opened_total: register(Counter::new( + "sub_libp2p_distinct_peers_connections_opened_total", + "Total number of connections opened with distinct peers" )?, registry)?, import_queue_blocks_submitted: register(Counter::new( "import_queue_blocks_submitted", @@ -852,6 +941,18 @@ impl Metrics { "import_queue_justifications_submitted", "Number of justifications submitted to the import queue.", )?, registry)?, + incoming_connections_errors_total: register(CounterVec::new( + Opts::new( + "sub_libp2p_incoming_connections_handshake_errors_total", + "Total number of incoming connections that have failed during the \ + initial handshake" + ), + &["reason"] + )?, registry)?, + incoming_connections_total: register(Counter::new( + "sub_libp2p_incoming_connections_total", + "Total number of incoming connections on the listening sockets" + )?, registry)?, is_major_syncing: register(Gauge::new( "sub_libp2p_is_major_syncing", "Whether the node is performing a major sync or not.", )?, registry)?, @@ -859,8 +960,40 @@ impl Metrics { "issued_light_requests", "Number of light client requests that our node has issued.", )?, registry)?, - kbuckets_num_nodes: register(Gauge::new( - "sub_libp2p_kbuckets_num_nodes", "Number of nodes in the Kademlia k-buckets" + kademlia_random_queries_total: register(CounterVec::new( + Opts::new( + "sub_libp2p_kademlia_random_queries_total", + "Number of random Kademlia queries started" + ), + &["protocol"] + )?, registry)?, + kademlia_records_count: register(GaugeVec::new( + Opts::new( + "sub_libp2p_kademlia_records_count", + "Number of records in the Kademlia records store" + ), + &["protocol"] + )?, registry)?, + kademlia_records_sizes_total: register(GaugeVec::new( + Opts::new( + "sub_libp2p_kademlia_records_sizes_total", + "Total size of all the records in the Kademlia records store" + ), + &["protocol"] + )?, registry)?, + kbuckets_num_nodes: register(GaugeVec::new( + Opts::new( + "sub_libp2p_kbuckets_num_nodes", + "Number of nodes in the Kademlia k-buckets" + ), + &["protocol"] + )?, registry)?, + listeners_local_addresses: register(Gauge::new( + "sub_libp2p_listeners_local_addresses", "Number of local addresses we're listening on" + )?, registry)?, + listeners_errors_total: register(Counter::new( + "sub_libp2p_listeners_errors_total", + "Total number of non-fatal errors reported by a listener" )?, registry)?, network_per_sec_bytes: register(GaugeVec::new( Opts::new( @@ -875,25 +1008,32 @@ impl Metrics { "sub_libp2p_notifications_queues_size", "Total size of all the notification queues" ), - buckets: vec![0.0, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0], + buckets: vec![0.0, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0, 511.0, 512.0], }, &["protocol"] )?, registry)?, - notifications_total: register(CounterVec::new( - Opts::new( - "sub_libp2p_notifications_total", - "Number of notification received from all nodes" - ), + notifications_sizes: register(HistogramVec::new( + HistogramOpts { + common_opts: Opts::new( + "sub_libp2p_notifications_sizes", + "Sizes of the notifications send to and received from all nodes" + ), + buckets: prometheus_endpoint::exponential_buckets(64.0, 4.0, 8) + .expect("parameters are always valid values; qed"), + }, &["direction", "protocol"] )?, registry)?, - num_event_stream_channels: register(Gauge::new( - "sub_libp2p_num_event_stream_channels", - "Number of internal active channels that broadcast network events", + notifications_streams_closed_total: register(CounterVec::new( + Opts::new( + "sub_libp2p_notifications_streams_closed_total", + "Total number of notification substreams that have been closed" + ), + &["protocol"] )?, registry)?, - opened_notification_streams: register(GaugeVec::new( + notifications_streams_opened_total: register(CounterVec::new( Opts::new( - "sub_libp2p_opened_notification_streams", - "Number of open notification substreams" + "sub_libp2p_notifications_streams_opened_total", + "Total number of notification substreams that have been opened" ), &["protocol"] )?, registry)?, @@ -906,8 +1046,45 @@ impl Metrics { peerset_num_requested: register(Gauge::new( "sub_libp2p_peerset_num_requested", "Number of nodes that the peerset manager wants us to be connected to", )?, registry)?, - random_kademalia_queries_total: register(Counter::new( - "sub_libp2p_random_kademalia_queries_total", "Number of random Kademlia queries started", + pending_connections: register(Gauge::new( + "sub_libp2p_pending_connections", + "Number of connections in the process of being established", + )?, registry)?, + pending_connections_errors_total: register(CounterVec::new( + Opts::new( + "sub_libp2p_pending_connections_errors_total", + "Total number of pending connection errors" + ), + &["reason"] + )?, registry)?, + requests_in_total: register(HistogramVec::new( + HistogramOpts { + common_opts: Opts::new( + "sub_libp2p_requests_in_total", + "Total number of requests received and answered" + ), + buckets: prometheus_endpoint::exponential_buckets(0.001, 2.0, 16) + .expect("parameters are always valid values; qed"), + }, + &["protocol"] + )?, registry)?, + requests_out_finished: register(HistogramVec::new( + HistogramOpts { + common_opts: Opts::new( + "sub_libp2p_requests_out_finished", + "Time between a request's start and finish (successful or not)" + ), + buckets: prometheus_endpoint::exponential_buckets(0.001, 2.0, 16) + .expect("parameters are always valid values; qed"), + }, + &["protocol"] + )?, registry)?, + requests_out_started_total: register(CounterVec::new( + Opts::new( + "sub_libp2p_requests_out_started_total", + "Total number of requests emitted" + ), + &["protocol"] )?, registry)?, }) } @@ -915,14 +1092,18 @@ impl Metrics { fn update_with_network_event(&self, event: &Event) { match event { Event::NotificationStreamOpened { engine_id, .. } => { - self.opened_notification_streams.with_label_values(&[&engine_id_to_string(&engine_id)]).inc(); + self.notifications_streams_opened_total + .with_label_values(&[&maybe_utf8_bytes_to_string(engine_id)]).inc(); }, Event::NotificationStreamClosed { engine_id, .. } => { - self.opened_notification_streams.with_label_values(&[&engine_id_to_string(&engine_id)]).dec(); + self.notifications_streams_closed_total + .with_label_values(&[&maybe_utf8_bytes_to_string(engine_id)]).inc(); }, Event::NotificationsReceived { messages, .. } => { - for (engine_id, _) in messages { - self.notifications_total.with_label_values(&["in", &engine_id_to_string(&engine_id)]).inc(); + for (engine_id, message) in messages { + self.notifications_sizes + .with_label_values(&["in", &maybe_utf8_bytes_to_string(engine_id)]) + .observe(message.len() as f64); } }, _ => {} @@ -931,7 +1112,7 @@ impl Metrics { } impl Future for NetworkWorker { - type Output = Result<(), io::Error>; + type Output = (); fn poll(mut self: Pin<&mut Self>, cx: &mut std::task::Context) -> Poll { let this = &mut *self; @@ -958,7 +1139,7 @@ impl Future for NetworkWorker { // Process the next message coming from the `NetworkService`. let msg = match this.from_worker.poll_next_unpin(cx) { Poll::Ready(Some(msg)) => msg, - Poll::Ready(None) => return Poll::Ready(Ok(())), + Poll::Ready(None) => return Poll::Ready(()), Poll::Pending => break, }; @@ -967,10 +1148,10 @@ impl Future for NetworkWorker { this.network_service.user_protocol_mut().announce_block(hash, data), ServiceToWorkerMsg::RequestJustification(hash, number) => this.network_service.user_protocol_mut().request_justification(&hash, number), - ServiceToWorkerMsg::PropagateExtrinsic(hash) => - this.network_service.user_protocol_mut().propagate_extrinsic(&hash), - ServiceToWorkerMsg::PropagateExtrinsics => - this.network_service.user_protocol_mut().propagate_extrinsics(), + ServiceToWorkerMsg::PropagateTransaction(hash) => + this.network_service.user_protocol_mut().propagate_transaction(&hash), + ServiceToWorkerMsg::PropagateTransactions => + this.network_service.user_protocol_mut().propagate_transactions(), ServiceToWorkerMsg::GetValue(key) => this.network_service.get_value(&key), ServiceToWorkerMsg::PutValue(key, value) => @@ -983,7 +1164,9 @@ impl Future for NetworkWorker { this.event_streams.push(sender), ServiceToWorkerMsg::WriteNotification { message, engine_id, target } => { if let Some(metrics) = this.metrics.as_ref() { - metrics.notifications_total.with_label_values(&["out", &engine_id_to_string(&engine_id)]).inc(); + metrics.notifications_sizes + .with_label_values(&["out", &maybe_utf8_bytes_to_string(&engine_id)]) + .observe(message.len() as f64); } this.network_service.user_protocol_mut().write_notification(target, engine_id, message) }, @@ -993,6 +1176,10 @@ impl Future for NetworkWorker { }, ServiceToWorkerMsg::DisconnectPeer(who) => this.network_service.user_protocol_mut().disconnect_peer(&who), + ServiceToWorkerMsg::UpdateChain => + this.network_service.user_protocol_mut().update_chain(), + ServiceToWorkerMsg::OwnBlockImported(hash, number) => + this.network_service.user_protocol_mut().own_block_imported(hash, number), } } @@ -1022,36 +1209,94 @@ impl Future for NetworkWorker { } this.import_queue.import_finality_proof(origin, hash, nb, proof); }, - Poll::Ready(SwarmEvent::Behaviour(BehaviourOut::RandomKademliaStarted)) => { + Poll::Ready(SwarmEvent::Behaviour(BehaviourOut::AnsweredRequest { protocol, build_time, .. })) => { + if let Some(metrics) = this.metrics.as_ref() { + metrics.requests_in_total + .with_label_values(&[&maybe_utf8_bytes_to_string(&protocol)]) + .observe(build_time.as_secs_f64()); + } + }, + Poll::Ready(SwarmEvent::Behaviour(BehaviourOut::RequestStarted { protocol, .. })) => { + if let Some(metrics) = this.metrics.as_ref() { + metrics.requests_out_started_total + .with_label_values(&[&maybe_utf8_bytes_to_string(&protocol)]) + .inc(); + } + }, + Poll::Ready(SwarmEvent::Behaviour(BehaviourOut::RequestFinished { protocol, request_duration, .. })) => { + if let Some(metrics) = this.metrics.as_ref() { + metrics.requests_out_finished + .with_label_values(&[&maybe_utf8_bytes_to_string(&protocol)]) + .observe(request_duration.as_secs_f64()); + } + }, + Poll::Ready(SwarmEvent::Behaviour(BehaviourOut::RandomKademliaStarted(protocol))) => { if let Some(metrics) = this.metrics.as_ref() { - metrics.random_kademalia_queries_total.inc(); + metrics.kademlia_random_queries_total + .with_label_values(&[&maybe_utf8_bytes_to_string(protocol.as_bytes())]) + .inc(); } }, Poll::Ready(SwarmEvent::Behaviour(BehaviourOut::Event(ev))) => { - this.event_streams.retain(|sender| sender.unbounded_send(ev.clone()).is_ok()); if let Some(metrics) = this.metrics.as_ref() { metrics.update_with_network_event(&ev); } + this.event_streams.send(ev); }, - Poll::Ready(SwarmEvent::Connected(peer_id)) => { + Poll::Ready(SwarmEvent::ConnectionEstablished { peer_id, endpoint, num_established }) => { trace!(target: "sub-libp2p", "Libp2p => Connected({:?})", peer_id); + if let Some(metrics) = this.metrics.as_ref() { - metrics.connections.inc(); + let direction = match endpoint { + ConnectedPoint::Dialer { .. } => "out", + ConnectedPoint::Listener { .. } => "in", + }; + metrics.connections_opened_total.with_label_values(&[direction]).inc(); + + if num_established.get() == 1 { + metrics.distinct_peers_connections_opened_total.inc(); + } } }, - Poll::Ready(SwarmEvent::Disconnected(peer_id)) => { - trace!(target: "sub-libp2p", "Libp2p => Disconnected({:?})", peer_id); + Poll::Ready(SwarmEvent::ConnectionClosed { peer_id, cause, endpoint, num_established }) => { + trace!(target: "sub-libp2p", "Libp2p => Disconnected({:?}, {:?})", peer_id, cause); if let Some(metrics) = this.metrics.as_ref() { - metrics.connections.dec(); + let direction = match endpoint { + ConnectedPoint::Dialer { .. } => "out", + ConnectedPoint::Listener { .. } => "in", + }; + let reason = match cause { + ConnectionError::IO(_) => "transport-error", + ConnectionError::Handler(NodeHandlerWrapperError::Handler(EitherError::A(EitherError::A( + EitherError::A(EitherError::A(EitherError::B( + EitherError::A(PingFailure::Timeout)))))))) => "ping-timeout", + ConnectionError::Handler(NodeHandlerWrapperError::Handler(EitherError::A(EitherError::A( + EitherError::A(EitherError::A(EitherError::A( + EitherError::B(LegacyConnectionKillError)))))))) => "force-closed", + ConnectionError::Handler(NodeHandlerWrapperError::Handler(_)) => "protocol-error", + ConnectionError::Handler(NodeHandlerWrapperError::KeepAliveTimeout) => "keep-alive-timeout", + }; + metrics.connections_closed_total.with_label_values(&[direction, reason]).inc(); + + // `num_established` represents the number of *remaining* connections. + if num_established == 0 { + metrics.distinct_peers_connections_closed_total.inc(); + } } }, - Poll::Ready(SwarmEvent::NewListenAddr(addr)) => - trace!(target: "sub-libp2p", "Libp2p => NewListenAddr({})", addr), - Poll::Ready(SwarmEvent::ExpiredListenAddr(addr)) => - trace!(target: "sub-libp2p", "Libp2p => ExpiredListenAddr({})", addr), - Poll::Ready(SwarmEvent::UnreachableAddr { peer_id, address, error }) => { - let error = error.to_string(); - + Poll::Ready(SwarmEvent::NewListenAddr(addr)) => { + trace!(target: "sub-libp2p", "Libp2p => NewListenAddr({})", addr); + if let Some(metrics) = this.metrics.as_ref() { + metrics.listeners_local_addresses.inc(); + } + }, + Poll::Ready(SwarmEvent::ExpiredListenAddr(addr)) => { + info!(target: "sub-libp2p", "📪 No longer listening on {}", addr); + if let Some(metrics) = this.metrics.as_ref() { + metrics.listeners_local_addresses.dec(); + } + }, + Poll::Ready(SwarmEvent::UnreachableAddr { peer_id, address, error, .. }) => { trace!( target: "sub-libp2p", "Libp2p => Failed to reach {:?} through {:?}: {}", peer_id, @@ -1059,21 +1304,85 @@ impl Future for NetworkWorker { error, ); - if let Some(peer_id) = peer_id { - if this.boot_node_ids.contains(&peer_id) - && error.contains("Peer ID mismatch") - { + if this.boot_node_ids.contains(&peer_id) { + if let PendingConnectionError::InvalidPeerId = error { error!( - "Connecting to bootnode with peer id `{}` and address `{}` failed \ - because it returned a different peer id!", - peer_id, + "💔 The bootnode you want to connect to at `{}` provided a different peer ID than the one you expect: `{}`.", address, + peer_id, ); } } + + if let Some(metrics) = this.metrics.as_ref() { + match error { + PendingConnectionError::ConnectionLimit(_) => + metrics.pending_connections_errors_total.with_label_values(&["limit-reached"]).inc(), + PendingConnectionError::InvalidPeerId => + metrics.pending_connections_errors_total.with_label_values(&["invalid-peer-id"]).inc(), + PendingConnectionError::Transport(_) | PendingConnectionError::IO(_) => + metrics.pending_connections_errors_total.with_label_values(&["transport-error"]).inc(), + } + } + } + Poll::Ready(SwarmEvent::Dialing(peer_id)) => + trace!(target: "sub-libp2p", "Libp2p => Dialing({:?})", peer_id), + Poll::Ready(SwarmEvent::IncomingConnection { local_addr, send_back_addr }) => { + trace!(target: "sub-libp2p", "Libp2p => IncomingConnection({},{}))", + local_addr, send_back_addr); + if let Some(metrics) = this.metrics.as_ref() { + metrics.incoming_connections_total.inc(); + } + }, + Poll::Ready(SwarmEvent::IncomingConnectionError { local_addr, send_back_addr, error }) => { + trace!(target: "sub-libp2p", "Libp2p => IncomingConnectionError({},{}): {}", + local_addr, send_back_addr, error); + if let Some(metrics) = this.metrics.as_ref() { + let reason = match error { + PendingConnectionError::ConnectionLimit(_) => "limit-reached", + PendingConnectionError::InvalidPeerId => "invalid-peer-id", + PendingConnectionError::Transport(_) | + PendingConnectionError::IO(_) => "transport-error", + }; + + metrics.incoming_connections_errors_total.with_label_values(&[reason]).inc(); + } + }, + Poll::Ready(SwarmEvent::BannedPeer { peer_id, endpoint }) => { + trace!(target: "sub-libp2p", "Libp2p => BannedPeer({}). Connected via {:?}.", + peer_id, endpoint); + if let Some(metrics) = this.metrics.as_ref() { + metrics.incoming_connections_errors_total.with_label_values(&["banned"]).inc(); + } + }, + Poll::Ready(SwarmEvent::UnknownPeerUnreachableAddr { address, error }) => + trace!(target: "sub-libp2p", "Libp2p => UnknownPeerUnreachableAddr({}): {}", + address, error), + Poll::Ready(SwarmEvent::ListenerClosed { reason, addresses }) => { + if let Some(metrics) = this.metrics.as_ref() { + metrics.listeners_local_addresses.sub(addresses.len() as u64); + } + let addrs = addresses.into_iter().map(|a| a.to_string()) + .collect::>().join(", "); + match reason { + Ok(()) => error!( + target: "sub-libp2p", + "📪 Libp2p listener ({}) closed gracefully", + addrs + ), + Err(e) => error!( + target: "sub-libp2p", + "📪 Libp2p listener ({}) closed: {}", + addrs, e + ), + } + }, + Poll::Ready(SwarmEvent::ListenerError { error }) => { + trace!(target: "sub-libp2p", "Libp2p => ListenerError: {}", error); + if let Some(metrics) = this.metrics.as_ref() { + metrics.listeners_errors_total.inc(); + } }, - Poll::Ready(SwarmEvent::StartConnect(peer_id)) => - trace!(target: "sub-libp2p", "Libp2p => StartConnect({:?})", peer_id), }; } @@ -1097,11 +1406,22 @@ impl Future for NetworkWorker { metrics.network_per_sec_bytes.with_label_values(&["in"]).set(this.service.bandwidth.average_download_per_sec()); metrics.network_per_sec_bytes.with_label_values(&["out"]).set(this.service.bandwidth.average_upload_per_sec()); metrics.is_major_syncing.set(is_major_syncing as u64); - metrics.kbuckets_num_nodes.set(this.network_service.num_kbuckets_entries() as u64); - metrics.num_event_stream_channels.set(this.event_streams.len() as u64); + for (proto, num_entries) in this.network_service.num_kbuckets_entries() { + let proto = maybe_utf8_bytes_to_string(proto.as_bytes()); + metrics.kbuckets_num_nodes.with_label_values(&[&proto]).set(num_entries as u64); + } + for (proto, num_entries) in this.network_service.num_kademlia_records() { + let proto = maybe_utf8_bytes_to_string(proto.as_bytes()); + metrics.kademlia_records_count.with_label_values(&[&proto]).set(num_entries as u64); + } + for (proto, num_entries) in this.network_service.kademlia_records_total_size() { + let proto = maybe_utf8_bytes_to_string(proto.as_bytes()); + metrics.kademlia_records_sizes_total.with_label_values(&[&proto]).set(num_entries as u64); + } metrics.peers_count.set(num_connected_peers as u64); metrics.peerset_num_discovered.set(this.network_service.user_protocol().num_discovered_peers() as u64); metrics.peerset_num_requested.set(this.network_service.user_protocol().requested_peers().count() as u64); + metrics.pending_connections.set(Swarm::network_info(&this.network_service).num_connections_pending as u64); } Poll::Pending @@ -1111,8 +1431,10 @@ impl Future for NetworkWorker { impl Unpin for NetworkWorker { } -/// Turns a `ConsensusEngineId` into a representable string. -fn engine_id_to_string(id: &ConsensusEngineId) -> Cow { +/// Turns bytes that are potentially UTF-8 into a reasonable representable string. +/// +/// Meant to be used only for debugging or metrics-reporting purposes. +fn maybe_utf8_bytes_to_string(id: &[u8]) -> Cow { if let Ok(s) = std::str::from_utf8(&id[..]) { Cow::Borrowed(s) } else { @@ -1135,7 +1457,7 @@ impl<'a, B: BlockT, H: ExHashT> Link for NetworkLink<'a, B, H> { count: usize, results: Vec<(Result>, BlockImportError>, B::Hash)> ) { - self.protocol.user_protocol_mut().blocks_processed(imported, count, results) + self.protocol.user_protocol_mut().on_blocks_processed(imported, count, results) } fn justification_imported(&mut self, who: PeerId, hash: &B::Hash, number: NumberFor, success: bool) { self.protocol.user_protocol_mut().justification_import_result(hash.clone(), number, success); @@ -1166,3 +1488,40 @@ impl<'a, B: BlockT, H: ExHashT> Link for NetworkLink<'a, B, H> { } } } + +fn ensure_addresses_consistent_with_transport<'a>( + addresses: impl Iterator, + transport: &TransportConfig, +) -> Result<(), Error> { + if matches!(transport, TransportConfig::MemoryOnly) { + let addresses: Vec<_> = addresses + .filter(|x| x.iter() + .any(|y| !matches!(y, libp2p::core::multiaddr::Protocol::Memory(_))) + ) + .cloned() + .collect(); + + if !addresses.is_empty() { + return Err(Error::AddressesForAnotherTransport { + transport: transport.clone(), + addresses, + }); + } + } else { + let addresses: Vec<_> = addresses + .filter(|x| x.iter() + .any(|y| matches!(y, libp2p::core::multiaddr::Protocol::Memory(_))) + ) + .cloned() + .collect(); + + if !addresses.is_empty() { + return Err(Error::AddressesForAnotherTransport { + transport: transport.clone(), + addresses, + }); + } + } + + Ok(()) +} diff --git a/client/network/src/service/out_events.rs b/client/network/src/service/out_events.rs new file mode 100644 index 0000000000000000000000000000000000000000..1b86a5fa4317d633c70f3dd4d97bf8146d9c81dd --- /dev/null +++ b/client/network/src/service/out_events.rs @@ -0,0 +1,283 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Registering events streams. +//! +//! This code holds the logic that is used for the network service to inform other parts of +//! Substrate about what is happening. +//! +//! # Usage +//! +//! - Create an instance of [`OutChannels`]. +//! - Create channels using the [`channel`] function. The receiving side implements the `Stream` +//! trait. +//! - You cannot directly send an event on a sender. Instead, you have to call +//! [`OutChannels::push`] to put the sender within a [`OutChannels`]. +//! - Send events by calling [`OutChannels::send`]. Events are cloned for each sender in the +//! collection. +//! + +use crate::Event; +use super::maybe_utf8_bytes_to_string; + +use futures::{prelude::*, channel::mpsc, ready, stream::FusedStream}; +use parking_lot::Mutex; +use prometheus_endpoint::{register, CounterVec, GaugeVec, Opts, PrometheusError, Registry, U64}; +use std::{ + convert::TryFrom as _, + fmt, pin::Pin, sync::Arc, + task::{Context, Poll} +}; + +/// Creates a new channel that can be associated to a [`OutChannels`]. +/// +/// The name is used in Prometheus reports. +pub fn channel(name: &'static str) -> (Sender, Receiver) { + let (tx, rx) = mpsc::unbounded(); + let metrics = Arc::new(Mutex::new(None)); + let tx = Sender { inner: tx, name, metrics: metrics.clone() }; + let rx = Receiver { inner: rx, name, metrics }; + (tx, rx) +} + +/// Sending side of a channel. +/// +/// Must be associated with an [`OutChannels`] before anything can be sent on it +/// +/// > **Note**: Contrary to regular channels, this `Sender` is purposefully designed to not +/// implement the `Clone` trait e.g. in Order to not complicate the logic keeping the metrics in +/// sync on drop. If someone adds a `#[derive(Clone)]` below, it is **wrong**. +pub struct Sender { + inner: mpsc::UnboundedSender, + name: &'static str, + /// Clone of [`Receiver::metrics`]. + metrics: Arc>>>>, +} + +impl fmt::Debug for Sender { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_tuple("Sender").finish() + } +} + +impl Drop for Sender { + fn drop(&mut self) { + let metrics = self.metrics.lock(); + if let Some(Some(metrics)) = metrics.as_ref().map(|m| &**m) { + metrics.num_channels.with_label_values(&[self.name]).dec(); + } + } +} + +/// Receiving side of a channel. +pub struct Receiver { + inner: mpsc::UnboundedReceiver, + name: &'static str, + /// Initially contains `None`, and will be set to a value once the corresponding [`Sender`] + /// is assigned to an instance of [`OutChannels`]. + metrics: Arc>>>>, +} + +impl Stream for Receiver { + type Item = Event; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + if let Some(ev) = ready!(Pin::new(&mut self.inner).poll_next(cx)) { + let metrics = self.metrics.lock().clone(); + match metrics.as_ref().map(|m| m.as_ref()) { + Some(Some(metrics)) => metrics.event_out(&ev, self.name), + Some(None) => (), // no registry + None => log::warn!("Inconsistency in out_events: event happened before sender associated"), + } + Poll::Ready(Some(ev)) + } else { + Poll::Ready(None) + } + } +} + +impl fmt::Debug for Receiver { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_tuple("Receiver").finish() + } +} + +impl Drop for Receiver { + fn drop(&mut self) { + if !self.inner.is_terminated() { + // Empty the list to properly decrease the metrics. + while let Some(Some(_)) = self.next().now_or_never() {} + } + } +} + +/// Collection of senders. +pub struct OutChannels { + event_streams: Vec, + /// The metrics we collect. A clone of this is sent to each [`Receiver`] associated with this + /// object. + metrics: Arc>, +} + +impl OutChannels { + /// Creates a new empty collection of senders. + pub fn new(registry: Option<&Registry>) -> Result { + let metrics = if let Some(registry) = registry { + Some(Metrics::register(registry)?) + } else { + None + }; + + Ok(OutChannels { + event_streams: Vec::new(), + metrics: Arc::new(metrics), + }) + } + + /// Adds a new [`Sender`] to the collection. + pub fn push(&mut self, sender: Sender) { + let mut metrics = sender.metrics.lock(); + debug_assert!(metrics.is_none()); + *metrics = Some(self.metrics.clone()); + drop(metrics); + + if let Some(metrics) = &*self.metrics { + metrics.num_channels.with_label_values(&[sender.name]).inc(); + } + + self.event_streams.push(sender); + } + + /// Sends an event. + pub fn send(&mut self, event: Event) { + self.event_streams.retain(|sender| { + sender.inner.unbounded_send(event.clone()).is_ok() + }); + + if let Some(metrics) = &*self.metrics { + for ev in &self.event_streams { + metrics.event_in(&event, 1, ev.name); + } + } + } +} + +impl fmt::Debug for OutChannels { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("OutChannels") + .field("num_channels", &self.event_streams.len()) + .finish() + } +} + +struct Metrics { + // This list is ordered alphabetically + events_total: CounterVec, + notifications_sizes: CounterVec, + num_channels: GaugeVec, +} + +impl Metrics { + fn register(registry: &Registry) -> Result { + Ok(Self { + events_total: register(CounterVec::new( + Opts::new( + "sub_libp2p_out_events_events_total", + "Number of broadcast network events that have been sent or received across all \ + channels" + ), + &["event_name", "action", "name"] + )?, registry)?, + notifications_sizes: register(CounterVec::new( + Opts::new( + "sub_libp2p_out_events_notifications_sizes", + "Size of notification events that have been sent or received across all \ + channels" + ), + &["protocol", "action", "name"] + )?, registry)?, + num_channels: register(GaugeVec::new( + Opts::new( + "sub_libp2p_out_events_num_channels", + "Number of internal active channels that broadcast network events", + ), + &["name"] + )?, registry)?, + }) + } + + fn event_in(&self, event: &Event, num: u64, name: &str) { + match event { + Event::Dht(_) => { + self.events_total + .with_label_values(&["dht", "sent", name]) + .inc_by(num); + } + Event::NotificationStreamOpened { engine_id, .. } => { + self.events_total + .with_label_values(&[&format!("notif-open-{:?}", engine_id), "sent", name]) + .inc_by(num); + }, + Event::NotificationStreamClosed { engine_id, .. } => { + self.events_total + .with_label_values(&[&format!("notif-closed-{:?}", engine_id), "sent", name]) + .inc_by(num); + }, + Event::NotificationsReceived { messages, .. } => { + for (engine_id, message) in messages { + self.events_total + .with_label_values(&[&format!("notif-{:?}", engine_id), "sent", name]) + .inc_by(num); + self.notifications_sizes + .with_label_values(&[&maybe_utf8_bytes_to_string(engine_id), "sent", name]) + .inc_by(num.saturating_mul(u64::try_from(message.len()).unwrap_or(u64::max_value()))); + } + }, + } + } + + fn event_out(&self, event: &Event, name: &str) { + match event { + Event::Dht(_) => { + self.events_total + .with_label_values(&["dht", "received", name]) + .inc(); + } + Event::NotificationStreamOpened { engine_id, .. } => { + self.events_total + .with_label_values(&[&format!("notif-open-{:?}", engine_id), "received", name]) + .inc(); + }, + Event::NotificationStreamClosed { engine_id, .. } => { + self.events_total + .with_label_values(&[&format!("notif-closed-{:?}", engine_id), "received", name]) + .inc(); + }, + Event::NotificationsReceived { messages, .. } => { + for (engine_id, message) in messages { + self.events_total + .with_label_values(&[&format!("notif-{:?}", engine_id), "received", name]) + .inc(); + self.notifications_sizes + .with_label_values(&[&maybe_utf8_bytes_to_string(engine_id), "received", name]) + .inc_by(u64::try_from(message.len()).unwrap_or(u64::max_value())); + } + }, + } + } +} diff --git a/client/network/src/service/tests.rs b/client/network/src/service/tests.rs new file mode 100644 index 0000000000000000000000000000000000000000..17d9553fa66bb2e527fe260561effe14e073ba36 --- /dev/null +++ b/client/network/src/service/tests.rs @@ -0,0 +1,462 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use crate::{config, Event, NetworkService, NetworkWorker}; + +use libp2p::PeerId; +use futures::prelude::*; +use sp_runtime::traits::{Block as BlockT, Header as _}; +use std::{sync::Arc, time::Duration}; +use substrate_test_runtime_client::{TestClientBuilder, TestClientBuilderExt as _}; + +type TestNetworkService = NetworkService< + substrate_test_runtime_client::runtime::Block, + substrate_test_runtime_client::runtime::Hash, +>; + +/// Builds a full node to be used for testing. Returns the node service and its associated events +/// stream. +/// +/// > **Note**: We return the events stream in order to not possibly lose events between the +/// > construction of the service and the moment the events stream is grabbed. +fn build_test_full_node(config: config::NetworkConfiguration) + -> (Arc, impl Stream) +{ + let client = Arc::new( + TestClientBuilder::with_default_backend() + .build_with_longest_chain() + .0, + ); + + #[derive(Clone)] + struct PassThroughVerifier(bool); + impl sp_consensus::import_queue::Verifier for PassThroughVerifier { + fn verify( + &mut self, + origin: sp_consensus::BlockOrigin, + header: B::Header, + justification: Option, + body: Option>, + ) -> Result< + ( + sp_consensus::BlockImportParams, + Option)>>, + ), + String, + > { + let maybe_keys = header + .digest() + .log(|l| { + l.try_as_raw(sp_runtime::generic::OpaqueDigestItemId::Consensus(b"aura")) + .or_else(|| { + l.try_as_raw(sp_runtime::generic::OpaqueDigestItemId::Consensus(b"babe")) + }) + }) + .map(|blob| { + vec![( + sp_blockchain::well_known_cache_keys::AUTHORITIES, + blob.to_vec(), + )] + }); + + let mut import = sp_consensus::BlockImportParams::new(origin, header); + import.body = body; + import.finalized = self.0; + import.justification = justification; + import.fork_choice = Some(sp_consensus::ForkChoiceStrategy::LongestChain); + Ok((import, maybe_keys)) + } + } + + let import_queue = Box::new(sp_consensus::import_queue::BasicQueue::new( + PassThroughVerifier(false), + Box::new(client.clone()), + None, + None, + &sp_core::testing::SpawnBlockingExecutor::new(), + None, + )); + + let worker = NetworkWorker::new(config::Params { + role: config::Role::Full, + executor: None, + network_config: config, + chain: client.clone(), + finality_proof_provider: None, + finality_proof_request_builder: None, + on_demand: None, + transaction_pool: Arc::new(crate::config::EmptyTransactionPool), + protocol_id: config::ProtocolId::from(&b"/test-protocol-name"[..]), + import_queue, + block_announce_validator: Box::new( + sp_consensus::block_validation::DefaultBlockAnnounceValidator, + ), + metrics_registry: None, + }) + .unwrap(); + + let service = worker.service().clone(); + let event_stream = service.event_stream("test"); + + async_std::task::spawn(async move { + futures::pin_mut!(worker); + let _ = worker.await; + }); + + (service, event_stream) +} + +const ENGINE_ID: sp_runtime::ConsensusEngineId = *b"foo\0"; + +/// Builds two nodes and their associated events stream. +/// The nodes are connected together and have the `ENGINE_ID` protocol registered. +fn build_nodes_one_proto() + -> (Arc, impl Stream, Arc, impl Stream) +{ + let listen_addr = config::build_multiaddr![Memory(rand::random::())]; + + let (node1, events_stream1) = build_test_full_node(config::NetworkConfiguration { + notifications_protocols: vec![(ENGINE_ID, From::from(&b"/foo"[..]))], + listen_addresses: vec![listen_addr.clone()], + transport: config::TransportConfig::MemoryOnly, + .. config::NetworkConfiguration::new_local() + }); + + let (node2, events_stream2) = build_test_full_node(config::NetworkConfiguration { + notifications_protocols: vec![(ENGINE_ID, From::from(&b"/foo"[..]))], + listen_addresses: vec![], + reserved_nodes: vec![config::MultiaddrWithPeerId { + multiaddr: listen_addr, + peer_id: node1.local_peer_id().clone(), + }], + transport: config::TransportConfig::MemoryOnly, + .. config::NetworkConfiguration::new_local() + }); + + (node1, events_stream1, node2, events_stream2) +} + +#[test] +fn notifications_state_consistent() { + // Runs two nodes and ensures that events are propagated out of the API in a consistent + // correct order, which means no notification received on a closed substream. + + let (node1, mut events_stream1, node2, mut events_stream2) = build_nodes_one_proto(); + + // Write some initial notifications that shouldn't get through. + for _ in 0..(rand::random::() % 5) { + node1.write_notification(node2.local_peer_id().clone(), ENGINE_ID, b"hello world".to_vec()); + } + for _ in 0..(rand::random::() % 5) { + node2.write_notification(node1.local_peer_id().clone(), ENGINE_ID, b"hello world".to_vec()); + } + + async_std::task::block_on(async move { + // True if we have an active substream from node1 to node2. + let mut node1_to_node2_open = false; + // True if we have an active substream from node2 to node1. + let mut node2_to_node1_open = false; + // We stop the test after a certain number of iterations. + let mut iterations = 0; + // Safe guard because we don't want the test to pass if no substream has been open. + let mut something_happened = false; + + loop { + iterations += 1; + if iterations >= 1_000 { + assert!(something_happened); + break; + } + + // Start by sending a notification from node1 to node2 and vice-versa. Part of the + // test consists in ensuring that notifications get ignored if the stream isn't open. + if rand::random::() % 5 >= 3 { + node1.write_notification(node2.local_peer_id().clone(), ENGINE_ID, b"hello world".to_vec()); + } + if rand::random::() % 5 >= 3 { + node2.write_notification(node1.local_peer_id().clone(), ENGINE_ID, b"hello world".to_vec()); + } + + // Also randomly disconnect the two nodes from time to time. + if rand::random::() % 20 == 0 { + node1.disconnect_peer(node2.local_peer_id().clone()); + } + if rand::random::() % 20 == 0 { + node2.disconnect_peer(node1.local_peer_id().clone()); + } + + // Grab next event from either `events_stream1` or `events_stream2`. + let next_event = { + let next1 = events_stream1.next(); + let next2 = events_stream2.next(); + // We also await on a small timer, otherwise it is possible for the test to wait + // forever while nothing at all happens on the network. + let continue_test = futures_timer::Delay::new(Duration::from_millis(20)); + match future::select(future::select(next1, next2), continue_test).await { + future::Either::Left((future::Either::Left((Some(ev), _)), _)) => + future::Either::Left(ev), + future::Either::Left((future::Either::Right((Some(ev), _)), _)) => + future::Either::Right(ev), + future::Either::Right(_) => continue, + _ => break, + } + }; + + match next_event { + future::Either::Left(Event::NotificationStreamOpened { remote, engine_id, .. }) => { + something_happened = true; + assert!(!node1_to_node2_open); + node1_to_node2_open = true; + assert_eq!(remote, *node2.local_peer_id()); + assert_eq!(engine_id, ENGINE_ID); + } + future::Either::Right(Event::NotificationStreamOpened { remote, engine_id, .. }) => { + something_happened = true; + assert!(!node2_to_node1_open); + node2_to_node1_open = true; + assert_eq!(remote, *node1.local_peer_id()); + assert_eq!(engine_id, ENGINE_ID); + } + future::Either::Left(Event::NotificationStreamClosed { remote, engine_id, .. }) => { + assert!(node1_to_node2_open); + node1_to_node2_open = false; + assert_eq!(remote, *node2.local_peer_id()); + assert_eq!(engine_id, ENGINE_ID); + } + future::Either::Right(Event::NotificationStreamClosed { remote, engine_id, .. }) => { + assert!(node2_to_node1_open); + node2_to_node1_open = false; + assert_eq!(remote, *node1.local_peer_id()); + assert_eq!(engine_id, ENGINE_ID); + } + future::Either::Left(Event::NotificationsReceived { remote, .. }) => { + assert!(node1_to_node2_open); + assert_eq!(remote, *node2.local_peer_id()); + if rand::random::() % 5 >= 4 { + node1.write_notification( + node2.local_peer_id().clone(), + ENGINE_ID, + b"hello world".to_vec() + ); + } + } + future::Either::Right(Event::NotificationsReceived { remote, .. }) => { + assert!(node2_to_node1_open); + assert_eq!(remote, *node1.local_peer_id()); + if rand::random::() % 5 >= 4 { + node2.write_notification( + node1.local_peer_id().clone(), + ENGINE_ID, + b"hello world".to_vec() + ); + } + } + + // Add new events here. + future::Either::Left(Event::Dht(_)) => {} + future::Either::Right(Event::Dht(_)) => {} + }; + } + }); +} + +#[test] +fn lots_of_incoming_peers_works() { + let listen_addr = config::build_multiaddr![Memory(rand::random::())]; + + let (main_node, _) = build_test_full_node(config::NetworkConfiguration { + notifications_protocols: vec![(ENGINE_ID, From::from(&b"/foo"[..]))], + listen_addresses: vec![listen_addr.clone()], + in_peers: u32::max_value(), + transport: config::TransportConfig::MemoryOnly, + .. config::NetworkConfiguration::new_local() + }); + + let main_node_peer_id = main_node.local_peer_id().clone(); + + // We spawn background tasks and push them in this `Vec`. They will all be waited upon before + // this test ends. + let mut background_tasks_to_wait = Vec::new(); + + for _ in 0..32 { + let main_node_peer_id = main_node_peer_id.clone(); + + let (_dialing_node, event_stream) = build_test_full_node(config::NetworkConfiguration { + notifications_protocols: vec![(ENGINE_ID, From::from(&b"/foo"[..]))], + listen_addresses: vec![], + reserved_nodes: vec![config::MultiaddrWithPeerId { + multiaddr: listen_addr.clone(), + peer_id: main_node_peer_id.clone(), + }], + transport: config::TransportConfig::MemoryOnly, + .. config::NetworkConfiguration::new_local() + }); + + background_tasks_to_wait.push(async_std::task::spawn(async move { + // Create a dummy timer that will "never" fire, and that will be overwritten when we + // actually need the timer. Using an Option would be technically cleaner, but it would + // make the code below way more complicated. + let mut timer = futures_timer::Delay::new(Duration::from_secs(3600 * 24 * 7)).fuse(); + + let mut event_stream = event_stream.fuse(); + loop { + futures::select! { + _ = timer => { + // Test succeeds when timer fires. + return; + } + ev = event_stream.next() => { + match ev.unwrap() { + Event::NotificationStreamOpened { remote, .. } => { + assert_eq!(remote, main_node_peer_id); + // Test succeeds after 5 seconds. This timer is here in order to + // detect a potential problem after opening. + timer = futures_timer::Delay::new(Duration::from_secs(5)).fuse(); + } + Event::NotificationStreamClosed { .. } => { + // Test failed. + panic!(); + } + _ => {} + } + } + } + } + })); + } + + futures::executor::block_on(async move { + future::join_all(background_tasks_to_wait).await + }); +} + +#[test] +#[should_panic(expected = "don't match the transport")] +fn ensure_listen_addresses_consistent_with_transport_memory() { + let listen_addr = config::build_multiaddr![Ip4([127, 0, 0, 1]), Tcp(0_u16)]; + + let _ = build_test_full_node(config::NetworkConfiguration { + listen_addresses: vec![listen_addr.clone()], + transport: config::TransportConfig::MemoryOnly, + .. config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None) + }); +} + +#[test] +#[should_panic(expected = "don't match the transport")] +fn ensure_listen_addresses_consistent_with_transport_not_memory() { + let listen_addr = config::build_multiaddr![Memory(rand::random::())]; + + let _ = build_test_full_node(config::NetworkConfiguration { + listen_addresses: vec![listen_addr.clone()], + .. config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None) + }); +} + +#[test] +#[should_panic(expected = "don't match the transport")] +fn ensure_boot_node_addresses_consistent_with_transport_memory() { + let listen_addr = config::build_multiaddr![Memory(rand::random::())]; + let boot_node = config::MultiaddrWithPeerId { + multiaddr: config::build_multiaddr![Ip4([127, 0, 0, 1]), Tcp(0_u16)], + peer_id: PeerId::random(), + }; + + let _ = build_test_full_node(config::NetworkConfiguration { + listen_addresses: vec![listen_addr.clone()], + transport: config::TransportConfig::MemoryOnly, + boot_nodes: vec![boot_node], + .. config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None) + }); +} + +#[test] +#[should_panic(expected = "don't match the transport")] +fn ensure_boot_node_addresses_consistent_with_transport_not_memory() { + let listen_addr = config::build_multiaddr![Ip4([127, 0, 0, 1]), Tcp(0_u16)]; + let boot_node = config::MultiaddrWithPeerId { + multiaddr: config::build_multiaddr![Memory(rand::random::())], + peer_id: PeerId::random(), + }; + + let _ = build_test_full_node(config::NetworkConfiguration { + listen_addresses: vec![listen_addr.clone()], + boot_nodes: vec![boot_node], + .. config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None) + }); +} + +#[test] +#[should_panic(expected = "don't match the transport")] +fn ensure_reserved_node_addresses_consistent_with_transport_memory() { + let listen_addr = config::build_multiaddr![Memory(rand::random::())]; + let reserved_node = config::MultiaddrWithPeerId { + multiaddr: config::build_multiaddr![Ip4([127, 0, 0, 1]), Tcp(0_u16)], + peer_id: PeerId::random(), + }; + + let _ = build_test_full_node(config::NetworkConfiguration { + listen_addresses: vec![listen_addr.clone()], + transport: config::TransportConfig::MemoryOnly, + reserved_nodes: vec![reserved_node], + .. config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None) + }); +} + +#[test] +#[should_panic(expected = "don't match the transport")] +fn ensure_reserved_node_addresses_consistent_with_transport_not_memory() { + let listen_addr = config::build_multiaddr![Ip4([127, 0, 0, 1]), Tcp(0_u16)]; + let reserved_node = config::MultiaddrWithPeerId { + multiaddr: config::build_multiaddr![Memory(rand::random::())], + peer_id: PeerId::random(), + }; + + let _ = build_test_full_node(config::NetworkConfiguration { + listen_addresses: vec![listen_addr.clone()], + reserved_nodes: vec![reserved_node], + .. config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None) + }); +} + +#[test] +#[should_panic(expected = "don't match the transport")] +fn ensure_public_addresses_consistent_with_transport_memory() { + let listen_addr = config::build_multiaddr![Memory(rand::random::())]; + let public_address = config::build_multiaddr![Ip4([127, 0, 0, 1]), Tcp(0_u16)]; + + let _ = build_test_full_node(config::NetworkConfiguration { + listen_addresses: vec![listen_addr.clone()], + transport: config::TransportConfig::MemoryOnly, + public_addresses: vec![public_address], + .. config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None) + }); +} + +#[test] +#[should_panic(expected = "don't match the transport")] +fn ensure_public_addresses_consistent_with_transport_not_memory() { + let listen_addr = config::build_multiaddr![Ip4([127, 0, 0, 1]), Tcp(0_u16)]; + let public_address = config::build_multiaddr![Memory(rand::random::())]; + + let _ = build_test_full_node(config::NetworkConfiguration { + listen_addresses: vec![listen_addr.clone()], + public_addresses: vec![public_address], + .. config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None) + }); +} diff --git a/client/network/src/transport.rs b/client/network/src/transport.rs index 75ee2d5db89b9c64569c23a70c7384080819ef36..0c9a809384e4cf6dc8aaf218cbfc610973d67fe5 100644 --- a/client/network/src/transport.rs +++ b/client/network/src/transport.rs @@ -1,27 +1,32 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use futures::prelude::*; use libp2p::{ InboundUpgradeExt, OutboundUpgradeExt, PeerId, Transport, + core::{ + self, either::{EitherError, EitherOutput}, muxing::StreamMuxerBox, + transport::{boxed::Boxed, OptionalTransport}, upgrade + }, mplex, identity, bandwidth, wasm_ext, noise }; #[cfg(not(target_os = "unknown"))] use libp2p::{tcp, dns, websocket}; -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; @@ -41,14 +46,22 @@ pub fn build_transport( ) -> (Boxed<(PeerId, StreamMuxerBox), io::Error>, Arc) { // Build configuration objects for encryption mechanisms. let noise_config = { - let noise_keypair = noise::Keypair::new().into_authentic(&keypair) - // For more information about this panic, see in "On the Importance of Checking - // Cryptographic Protocols for Faults" by Dan Boneh, Richard A. DeMillo, - // and Richard J. Lipton. + // For more information about these two panics, see in "On the Importance of + // Checking Cryptographic Protocols for Faults" by Dan Boneh, Richard A. DeMillo, + // and Richard J. Lipton. + let noise_keypair_legacy = noise::Keypair::::new().into_authentic(&keypair) + .expect("can only fail in case of a hardware bug; since this signing is performed only \ + once and at initialization, we're taking the bet that the inconvenience of a very \ + rare panic here is basically zero"); + let noise_keypair_spec = noise::Keypair::::new().into_authentic(&keypair) .expect("can only fail in case of a hardware bug; since this signing is performed only \ once and at initialization, we're taking the bet that the inconvenience of a very \ rare panic here is basically zero"); - noise::NoiseConfig::ix(noise_keypair) + + core::upgrade::SelectUpgrade::new( + noise::NoiseConfig::xx(noise_keypair_spec), + noise::NoiseConfig::ix(noise_keypair_legacy) + ) }; // Build configuration objects for multiplexing mechanisms. @@ -96,11 +109,22 @@ pub fn build_transport( // Encryption let transport = transport.and_then(move |stream, endpoint| { core::upgrade::apply(stream, noise_config, endpoint, upgrade::Version::V1) - .and_then(|(remote_id, out)| async move { - let remote_key = match remote_id { - noise::RemoteIdentity::IdentityKey(key) => key, + .map_err(|err| + err.map_err(|err| match err { + EitherError::A(err) => err, + EitherError::B(err) => err, + }) + ) + .and_then(|result| async move { + let remote_key = match &result { + EitherOutput::First((noise::RemoteIdentity::IdentityKey(key), _)) => key.clone(), + EitherOutput::Second((noise::RemoteIdentity::IdentityKey(key), _)) => key.clone(), _ => return Err(upgrade::UpgradeError::Apply(noise::NoiseError::InvalidKey)) }; + let out = match result { + EitherOutput::First((_, o)) => o, + EitherOutput::Second((_, o)) => o, + }; Ok((out, remote_key.into_peer_id())) }) }); diff --git a/client/network/test/Cargo.toml b/client/network/test/Cargo.toml index 769e0faca9e5cd8a1055515f5c9abd66df22b915..9ca5f024d25d052e7116e307d36c08644caef96d 100644 --- a/client/network/test/Cargo.toml +++ b/client/network/test/Cargo.toml @@ -1,34 +1,35 @@ [package] description = "Integration tests for Substrate network protocol" name = "sc-network-test" -version = "0.8.0-dev" -license = "GPL-3.0" +version = "0.8.0-rc4" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" authors = ["Parity Technologies "] edition = "2018" publish = false homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sc-network = { version = "0.8.0-alpha.5", path = "../" } +sc-network = { version = "0.8.0-rc4", path = "../" } log = "0.4.8" parking_lot = "0.10.0" futures = "0.3.4" futures-timer = "3.0.1" rand = "0.7.2" -libp2p = { version = "0.16.2", default-features = false, features = ["libp2p-websocket"] } -sp-consensus = { version = "0.8.0-alpha.5", path = "../../../primitives/consensus/common" } -sc-client = { version = "0.8.0-alpha.5", path = "../../" } -sc-client-api = { version = "2.0.0-alpha.5", path = "../../api" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../../primitives/blockchain" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime" } -sp-core = { version = "2.0.0-alpha.5", path = "../../../primitives/core" } -sc-block-builder = { version = "0.8.0-alpha.5", path = "../../block-builder" } -sp-consensus-babe = { version = "0.8.0-alpha.5", path = "../../../primitives/consensus/babe" } +libp2p = { version = "0.21.1", default-features = false } +sp-consensus = { version = "0.8.0-rc4", path = "../../../primitives/consensus/common" } +sc-consensus = { version = "0.8.0-rc4", path = "../../../client/consensus/common" } +sc-client-api = { version = "2.0.0-rc4", path = "../../api" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../../primitives/blockchain" } +sp-runtime = { version = "2.0.0-rc4", path = "../../../primitives/runtime" } +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } +sc-block-builder = { version = "0.8.0-rc4", path = "../../block-builder" } +sp-consensus-babe = { version = "0.8.0-rc4", path = "../../../primitives/consensus/babe" } env_logger = "0.7.0" -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../../test-utils/runtime/client" } -substrate-test-runtime = { version = "2.0.0-dev", path = "../../../test-utils/runtime" } +substrate-test-runtime-client = { version = "2.0.0-rc4", path = "../../../test-utils/runtime/client" } +substrate-test-runtime = { version = "2.0.0-rc4", path = "../../../test-utils/runtime" } tempfile = "3.1.0" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +sc-service = { version = "0.8.0-rc4", default-features = false, features = ["test-helpers"], path = "../../service" } diff --git a/client/network/test/src/block_import.rs b/client/network/test/src/block_import.rs index aa6d275141fc76ef9d88b0588866a7bb5fc4feaa..6762b74b6b8bd825c9c200015162bfd9274d845e 100644 --- a/client/network/test/src/block_import.rs +++ b/client/network/test/src/block_import.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Testing block import logic. @@ -53,7 +55,12 @@ fn import_single_good_block_works() { let mut expected_aux = ImportedAux::default(); expected_aux.is_new_best = true; - match import_single_block(&mut substrate_test_runtime_client::new(), BlockOrigin::File, block, &mut PassThroughVerifier(true)) { + match import_single_block( + &mut substrate_test_runtime_client::new(), + BlockOrigin::File, + block, + &mut PassThroughVerifier::new(true) + ) { Ok(BlockImportResult::ImportedUnknown(ref num, ref aux, ref org)) if *num == number && *aux == expected_aux && *org == Some(peer_id) => {} r @ _ => panic!("{:?}", r) @@ -63,7 +70,12 @@ fn import_single_good_block_works() { #[test] fn import_single_good_known_block_is_ignored() { let (mut client, _hash, number, _, block) = prepare_good_block(); - match import_single_block(&mut client, BlockOrigin::File, block, &mut PassThroughVerifier(true)) { + match import_single_block( + &mut client, + BlockOrigin::File, + block, + &mut PassThroughVerifier::new(true) + ) { Ok(BlockImportResult::ImportedKnown(ref n)) if *n == number => {} _ => panic!() } @@ -73,7 +85,12 @@ fn import_single_good_known_block_is_ignored() { fn import_single_good_block_without_header_fails() { let (_, _, _, peer_id, mut block) = prepare_good_block(); block.header = None; - match import_single_block(&mut substrate_test_runtime_client::new(), BlockOrigin::File, block, &mut PassThroughVerifier(true)) { + match import_single_block( + &mut substrate_test_runtime_client::new(), + BlockOrigin::File, + block, + &mut PassThroughVerifier::new(true) + ) { Err(BlockImportError::IncompleteHeader(ref org)) if *org == Some(peer_id) => {} _ => panic!() } @@ -81,10 +98,19 @@ fn import_single_good_block_without_header_fails() { #[test] fn async_import_queue_drops() { + let executor = sp_core::testing::SpawnBlockingExecutor::new(); // Perform this test multiple times since it exhibits non-deterministic behavior. for _ in 0..100 { - let verifier = PassThroughVerifier(true); - let queue = BasicQueue::new(verifier, Box::new(substrate_test_runtime_client::new()), None, None); + let verifier = PassThroughVerifier::new(true); + + let queue = BasicQueue::new( + verifier, + Box::new(substrate_test_runtime_client::new()), + None, + None, + &executor, + None, + ); drop(queue); } } diff --git a/client/network/test/src/lib.rs b/client/network/test/src/lib.rs index aa887bf5ca6765b48e9507f977c01b67522d6557..d0f1d4752bb5e3789b40b61896694bc20f783f68 100644 --- a/client/network/test/src/lib.rs +++ b/client/network/test/src/lib.rs @@ -1,19 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . - +// along with this program. If not, see . #![allow(missing_docs)] #[cfg(test)] @@ -27,13 +28,18 @@ use libp2p::build_multiaddr; use log::trace; use sc_network::config::FinalityProofProvider; use sp_blockchain::{ - Result as ClientResult, well_known_cache_keys::{self, Id as CacheKeyId}, Info as BlockchainInfo, + HeaderBackend, Result as ClientResult, + well_known_cache_keys::{self, Id as CacheKeyId}, + Info as BlockchainInfo, +}; +use sc_client_api::{ + BlockchainEvents, BlockImportNotification, FinalityNotifications, ImportNotifications, FinalityNotification, + backend::{TransactionFor, AuxStore, Backend, Finalizer}, BlockBackend, }; -use sc_client_api::{BlockchainEvents, BlockImportNotification, FinalityNotifications, ImportNotifications, FinalityNotification, backend::{TransactionFor, AuxStore, Backend, Finalizer}, BlockBackend}; +use sc_consensus::LongestChain; use sc_block_builder::{BlockBuilder, BlockBuilderProvider}; -use sc_client::LongestChain; use sc_network::config::Role; -use sp_consensus::block_validation::DefaultBlockAnnounceValidator; +use sp_consensus::block_validation::{DefaultBlockAnnounceValidator, BlockAnnounceValidator}; use sp_consensus::import_queue::{ BasicQueue, BoxJustificationImport, Verifier, BoxFinalityProofImport, }; @@ -41,7 +47,7 @@ use sp_consensus::block_import::{BlockImport, ImportResult}; use sp_consensus::Error as ConsensusError; use sp_consensus::{BlockOrigin, ForkChoiceStrategy, BlockImportParams, BlockCheckParams, JustificationImport}; use futures::prelude::*; -use sc_network::{NetworkWorker, NetworkStateInfo, NetworkService, config::ProtocolId}; +use sc_network::{NetworkWorker, NetworkService, config::ProtocolId}; use sc_network::config::{NetworkConfiguration, TransportConfig, BoxFinalityProofRequestBuilder}; use libp2p::PeerId; use parking_lot::Mutex; @@ -51,7 +57,7 @@ use sp_runtime::generic::{BlockId, OpaqueDigestItemId}; use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor}; use sp_runtime::Justification; use substrate_test_runtime_client::{self, AccountKeyring}; - +use sc_service::client::Client; pub use sc_network::config::EmptyTransactionPool; pub use substrate_test_runtime_client::runtime::{Block, Extrinsic, Hash, Transfer}; pub use substrate_test_runtime_client::{TestClient, TestClientBuilder, TestClientBuilderExt}; @@ -61,7 +67,33 @@ type AuthorityId = sp_consensus_babe::AuthorityId; /// A Verifier that accepts all blocks and passes them on with the configured /// finality to be imported. #[derive(Clone)] -pub struct PassThroughVerifier(pub bool); +pub struct PassThroughVerifier { + finalized: bool, + fork_choice: ForkChoiceStrategy, +} + +impl PassThroughVerifier { + /// Create a new instance. + /// + /// Every verified block will use `finalized` for the `BlockImportParams`. + pub fn new(finalized: bool) -> Self { + Self { + finalized, + fork_choice: ForkChoiceStrategy::LongestChain, + } + } + + /// Create a new instance. + /// + /// Every verified block will use `finalized` for the `BlockImportParams` and + /// the given [`ForkChoiceStrategy`]. + pub fn new_with_fork_choice(finalized: bool, fork_choice: ForkChoiceStrategy) -> Self { + Self { + finalized, + fork_choice, + } + } +} /// This `Verifier` accepts all data as valid. impl Verifier for PassThroughVerifier { @@ -79,18 +111,26 @@ impl Verifier for PassThroughVerifier { .map(|blob| vec![(well_known_cache_keys::AUTHORITIES, blob.to_vec())]); let mut import = BlockImportParams::new(origin, header); import.body = body; - import.finalized = self.0; + import.finalized = self.finalized; import.justification = justification; - import.fork_choice = Some(ForkChoiceStrategy::LongestChain); + import.fork_choice = Some(self.fork_choice.clone()); Ok((import, maybe_keys)) } } -pub type PeersFullClient = - sc_client::Client; -pub type PeersLightClient = - sc_client::Client; +pub type PeersFullClient = Client< + substrate_test_runtime_client::Backend, + substrate_test_runtime_client::Executor, + Block, + substrate_test_runtime_client::runtime::RuntimeApi +>; +pub type PeersLightClient = Client< + substrate_test_runtime_client::LightBackend, + substrate_test_runtime_client::LightExecutor, + Block, + substrate_test_runtime_client::runtime::RuntimeApi +>; #[derive(Clone)] pub enum PeersClient { @@ -189,7 +229,7 @@ pub struct Peer { impl Peer { /// Get this peer ID. pub fn id(&self) -> PeerId { - self.network.service().local_peer_id() + self.network.service().local_peer_id().clone() } /// Returns true if we're major syncing. @@ -207,9 +247,9 @@ impl Peer { self.network.num_connected_peers() } - /// Returns the number of processed blocks. - pub fn num_processed_blocks(&self) -> usize { - self.network.num_processed_blocks() + /// Returns the number of downloaded blocks. + pub fn num_downloaded_blocks(&self) -> usize { + self.network.num_downloaded_blocks() } /// Returns true if we have no peer. @@ -280,12 +320,13 @@ impl Peer { } else { Default::default() }; + self.block_import.import_block(import_block, cache).expect("block_import failed"); - self.network.on_block_imported(header, true); self.network.service().announce_block(hash, Vec::new()); at = hash; } + self.network.update_chain(); self.network.service().announce_block(at.clone(), Vec::new()); at } @@ -359,13 +400,9 @@ impl Peer { /// 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()) + mine.blockchain().info().best_hash == others.blockchain().info().best_hash } else { false } @@ -374,7 +411,7 @@ impl Peer { /// Count the total number of imported blocks. pub fn blocks_count(&self) -> u64 { self.backend.as_ref().map( - |backend| backend.blocks_count() + |backend| backend.blockchain().info().best_number ).unwrap_or(0) } @@ -382,6 +419,12 @@ impl Peer { pub fn failed_verifications(&self) -> HashMap<::Hash, String> { self.verifier.failed_verifications.lock().clone() } + + pub fn has_block(&self, hash: &H256) -> bool { + self.backend.as_ref().map( + |backend| backend.blockchain().header(BlockId::hash(*hash)).unwrap().is_some() + ).unwrap_or(false) + } } /// Implements `BlockImport` for any `Transaction`. Internally the transaction is @@ -503,6 +546,15 @@ impl VerifierAdapter { } } +/// Configuration for a full peer. +#[derive(Default)] +pub struct FullPeerConfig { + /// Pruning window size. + pub keep_blocks: Option, + /// Block announce validator. + pub block_announce_validator: Option + Send + Sync>>, +} + pub trait TestNetFactory: Sized { type Verifier: 'static + Verifier; type PeerData: Default; @@ -563,12 +615,12 @@ pub trait TestNetFactory: Sized { } fn add_full_peer(&mut self) { - self.add_full_peer_with_states(None) + self.add_full_peer_with_config(Default::default()) } /// Add a full peer. - fn add_full_peer_with_states(&mut self, keep_blocks: Option) { - let test_client_builder = match keep_blocks { + fn add_full_peer_with_config(&mut self, config: FullPeerConfig) { + let test_client_builder = match config.keep_blocks { Some(keep_blocks) => TestClientBuilder::with_pruning_window(keep_blocks), None => TestClientBuilder::with_default_backend(), }; @@ -596,18 +648,26 @@ pub trait TestNetFactory: Sized { Box::new(block_import.clone()), justification_import, finality_proof_import, + &sp_core::testing::SpawnBlockingExecutor::new(), + None, )); let listen_addr = build_multiaddr![Memory(rand::random::())]; + let mut network_config = NetworkConfiguration::new( + "test-node", + "test-client", + Default::default(), + None, + ); + network_config.transport = TransportConfig::MemoryOnly; + network_config.listen_addresses = vec![listen_addr.clone()]; + network_config.allow_non_globals_in_dht = true; + let network = NetworkWorker::new(sc_network::config::Params { role: Role::Full, executor: None, - network_config: NetworkConfiguration { - listen_addresses: vec![listen_addr.clone()], - transport: TransportConfig::MemoryOnly, - ..NetworkConfiguration::default() - }, + network_config, chain: client.clone(), finality_proof_provider: self.make_finality_proof_provider( PeersClient::Full(client.clone(), backend.clone()), @@ -617,13 +677,14 @@ pub trait TestNetFactory: Sized { transaction_pool: Arc::new(EmptyTransactionPool), protocol_id: ProtocolId::from(&b"test-protocol-name"[..]), import_queue, - block_announce_validator: Box::new(DefaultBlockAnnounceValidator::new(client.clone())), + block_announce_validator: config.block_announce_validator + .unwrap_or(Box::new(DefaultBlockAnnounceValidator)), metrics_registry: None, }).unwrap(); self.mut_peers(|peers| { for peer in peers.iter_mut() { - peer.network.add_known_address(network.service().local_peer_id(), listen_addr.clone()); + peer.network.add_known_address(network.service().local_peer_id().clone(), listen_addr.clone()); } let imported_blocks_stream = Box::pin(client.import_notification_stream().fuse()); @@ -667,18 +728,26 @@ pub trait TestNetFactory: Sized { Box::new(block_import.clone()), justification_import, finality_proof_import, + &sp_core::testing::SpawnBlockingExecutor::new(), + None, )); let listen_addr = build_multiaddr![Memory(rand::random::())]; + let mut network_config = NetworkConfiguration::new( + "test-node", + "test-client", + Default::default(), + None, + ); + network_config.transport = TransportConfig::MemoryOnly; + network_config.listen_addresses = vec![listen_addr.clone()]; + network_config.allow_non_globals_in_dht = true; + let network = NetworkWorker::new(sc_network::config::Params { role: Role::Light, executor: None, - network_config: NetworkConfiguration { - listen_addresses: vec![listen_addr.clone()], - transport: TransportConfig::MemoryOnly, - ..NetworkConfiguration::default() - }, + network_config, chain: client.clone(), finality_proof_provider: self.make_finality_proof_provider( PeersClient::Light(client.clone(), backend.clone()) @@ -688,13 +757,13 @@ pub trait TestNetFactory: Sized { transaction_pool: Arc::new(EmptyTransactionPool), protocol_id: ProtocolId::from(&b"test-protocol-name"[..]), import_queue, - block_announce_validator: Box::new(DefaultBlockAnnounceValidator::new(client.clone())), + block_announce_validator: Box::new(DefaultBlockAnnounceValidator), metrics_registry: None, }).unwrap(); self.mut_peers(|peers| { for peer in peers.iter_mut() { - peer.network.add_known_address(network.service().local_peer_id(), listen_addr.clone()); + peer.network.add_known_address(network.service().local_peer_id().clone(), listen_addr.clone()); } let imported_blocks_stream = Box::pin(client.import_notification_stream().fuse()); @@ -755,6 +824,20 @@ pub trait TestNetFactory: Sized { Poll::Ready(()) } + /// Polls the testnet until all peers are connected to each other. + /// + /// Must be executed in a task context. + fn poll_until_connected(&mut self, cx: &mut FutureContext) -> Poll<()> { + self.poll(cx); + + let num_peers = self.peers().len(); + if self.peers().iter().all(|p| p.num_peers() == num_peers - 1) { + return Poll::Ready(()) + } + + Poll::Pending + } + /// Blocks the current thread until we are sync'ed. /// /// Calls `poll_until_sync` repeatedly. @@ -769,22 +852,27 @@ pub trait TestNetFactory: Sized { futures::executor::block_on(futures::future::poll_fn::<(), _>(|cx| self.poll_until_idle(cx))); } - /// Polls the testnet. Processes all the pending actions and returns `NotReady`. + /// Blocks the current thread until all peers are connected to each other. + /// + /// Calls `poll_until_connected` repeatedly with the runtime passed as parameter. + fn block_until_connected(&mut self) { + futures::executor::block_on( + futures::future::poll_fn::<(), _>(|cx| self.poll_until_connected(cx)), + ); + } + + /// Polls the testnet. Processes all the pending actions. fn poll(&mut self, cx: &mut FutureContext) { self.mut_peers(|peers| { for peer in peers { trace!(target: "sync", "-- Polling {}", peer.id()); - if let Poll::Ready(res) = Pin::new(&mut peer.network).poll(cx) { - res.unwrap(); + if let Poll::Ready(()) = peer.network.poll_unpin(cx) { + panic!("NetworkWorker has terminated unexpectedly.") } trace!(target: "sync", "-- Polling complete {}", peer.id()); // We poll `imported_blocks_stream`. while let Poll::Ready(Some(notification)) = peer.imported_blocks_stream.as_mut().poll_next(cx) { - peer.network.on_block_imported( - notification.header, - true, - ); peer.network.service().announce_block(notification.hash, Vec::new()); } @@ -803,6 +891,17 @@ pub trait TestNetFactory: Sized { pub struct TestNet { peers: Vec>, + fork_choice: ForkChoiceStrategy, +} + +impl TestNet { + /// Create a `TestNet` that used the given fork choice rule. + pub fn with_fork_choice(fork_choice: ForkChoiceStrategy) -> Self { + Self { + peers: Vec::new(), + fork_choice, + } + } } impl TestNetFactory for TestNet { @@ -813,13 +912,14 @@ impl TestNetFactory for TestNet { fn from_config(_config: &ProtocolConfig) -> Self { TestNet { peers: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, } } fn make_verifier(&self, _client: PeersClient, _config: &ProtocolConfig, _peer_data: &()) -> Self::Verifier { - PassThroughVerifier(false) + PassThroughVerifier::new_with_fork_choice(false, self.fork_choice.clone()) } fn peer(&mut self, i: usize) -> &mut Peer<()> { diff --git a/client/network/test/src/sync.rs b/client/network/test/src/sync.rs index 8acf265e9189288758471f69db6873b0418a3edd..1cf2a8fee37982495811a2bd464bb0eb5644b728 100644 --- a/client/network/test/src/sync.rs +++ b/client/network/test/src/sync.rs @@ -1,23 +1,27 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use sp_consensus::BlockOrigin; use std::time::Duration; use futures::executor::block_on; use super::*; +use sp_consensus::block_validation::Validation; +use substrate_test_runtime::Header; fn test_ancestor_search_when_common_is(n: usize) { let _ = ::env_logger::try_init(); @@ -339,13 +343,15 @@ fn syncs_all_forks() { net.peer(0).push_blocks(2, false); net.peer(1).push_blocks(2, false); - net.peer(0).push_blocks(2, true); - net.peer(1).push_blocks(4, false); + let b1 = net.peer(0).push_blocks(2, true); + let b2 = net.peer(1).push_blocks(4, false); net.block_until_sync(); - // Check that all peers have all of the blocks. - assert_eq!(9, net.peer(0).blocks_count()); - assert_eq!(9, net.peer(1).blocks_count()); + // Check that all peers have all of the branches. + assert!(net.peer(0).has_block(&b1)); + assert!(net.peer(0).has_block(&b2)); + assert!(net.peer(1).has_block(&b1)); + assert!(net.peer(1).has_block(&b2)); } #[test] @@ -578,33 +584,20 @@ fn can_sync_explicit_forks() { #[test] fn syncs_header_only_forks() { - let _ = ::env_logger::try_init(); + let _ = env_logger::try_init(); let mut net = TestNet::new(0); - net.add_full_peer_with_states(None); - net.add_full_peer_with_states(Some(3)); + net.add_full_peer_with_config(Default::default()); + net.add_full_peer_with_config(FullPeerConfig { keep_blocks: Some(3), ..Default::default() }); net.peer(0).push_blocks(2, false); net.peer(1).push_blocks(2, false); net.peer(0).push_blocks(2, true); let small_hash = net.peer(0).client().info().best_hash; - let small_number = net.peer(0).client().info().best_number; net.peer(1).push_blocks(4, false); net.block_until_sync(); // Peer 1 will sync the small fork even though common block state is missing - assert_eq!(9, net.peer(0).blocks_count()); - assert_eq!(9, net.peer(1).blocks_count()); - - // Request explicit header-only sync request for the ancient fork. - let first_peer_id = net.peer(0).id(); - net.peer(1).set_sync_fork_request(vec![first_peer_id], small_hash, small_number); - block_on(futures::future::poll_fn::<(), _>(|cx| { - net.poll(cx); - if net.peer(1).client().header(&BlockId::Hash(small_hash)).unwrap().is_none() { - return Poll::Pending - } - Poll::Ready(()) - })); + assert!(net.peer(1).has_block(&small_hash)); } #[test] @@ -682,17 +675,17 @@ fn imports_stale_once() { // check that NEW block is imported from announce message let new_hash = net.peer(0).push_blocks(1, false); import_with_announce(&mut net, new_hash); - assert_eq!(net.peer(1).num_processed_blocks(), 1); + assert_eq!(net.peer(1).num_downloaded_blocks(), 1); // check that KNOWN STALE block is imported from announce message let known_stale_hash = net.peer(0).push_blocks_at(BlockId::Number(0), 1, true); import_with_announce(&mut net, known_stale_hash); - assert_eq!(net.peer(1).num_processed_blocks(), 2); + assert_eq!(net.peer(1).num_downloaded_blocks(), 2); } #[test] fn can_sync_to_peers_with_wrong_common_block() { - let _ = ::env_logger::try_init(); + let _ = env_logger::try_init(); let mut net = TestNet::new(2); net.peer(0).push_blocks(2, true); @@ -719,3 +712,41 @@ fn can_sync_to_peers_with_wrong_common_block() { assert!(net.peer(1).client().header(&BlockId::Hash(final_hash)).unwrap().is_some()); } +/// Returns `is_new_best = true` for each validated announcement. +struct NewBestBlockAnnounceValidator; + +impl BlockAnnounceValidator for NewBestBlockAnnounceValidator { + fn validate( + &mut self, + _: &Header, + _: &[u8], + ) -> Result> { + Ok(Validation::Success { is_new_best: true }) + } +} + +#[test] +fn sync_blocks_when_block_announce_validator_says_it_is_new_best() { + let _ = env_logger::try_init(); + log::trace!(target: "sync", "Test"); + let mut net = TestNet::with_fork_choice(ForkChoiceStrategy::Custom(false)); + net.add_full_peer_with_config(Default::default()); + net.add_full_peer_with_config(Default::default()); + net.add_full_peer_with_config(FullPeerConfig { + block_announce_validator: Some(Box::new(NewBestBlockAnnounceValidator)), + ..Default::default() + }); + + net.block_until_connected(); + + let block_hash = net.peer(0).push_blocks(1, false); + + while !net.peer(2).has_block(&block_hash) { + net.block_until_idle(); + } + + // Peer1 should not have the block, because peer 0 did not reported the block + // as new best. However, peer2 has a special block announcement validator + // that flags all blocks as `is_new_best` and thus, it should have synced the blocks. + assert!(!net.peer(1).has_block(&block_hash)); +} diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml index e7292439e82eb0d4ad27e9f64c897c764b2f18f4..cd5a63a75c8f964c7cf66c0eb326772d353eaf3e 100644 --- a/client/offchain/Cargo.toml +++ b/client/offchain/Cargo.toml @@ -1,32 +1,35 @@ [package] description = "Substrate offchain workers" name = "sc-offchain" -version = "2.0.0-alpha.5" -license = "GPL-3.0" +version = "2.0.0-rc4" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" authors = ["Parity Technologies "] edition = "2018" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] bytes = "0.5" -sc-client-api = { version = "2.0.0-alpha.5", path = "../api" } -sp-api = { version = "2.0.0-alpha.5", path = "../../primitives/api" } +sc-client-api = { version = "2.0.0-rc4", path = "../api" } +sp-api = { version = "2.0.0-rc4", path = "../../primitives/api" } fnv = "1.0.6" futures = "0.3.4" futures-timer = "3.0.1" log = "0.4.8" threadpool = "1.7" num_cpus = "1.10" -sp-offchain = { version = "2.0.0-alpha.5", path = "../../primitives/offchain" } -codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive"] } +sp-offchain = { version = "2.0.0-rc4", path = "../../primitives/offchain" } +codec = { package = "parity-scale-codec", version = "1.3.1", features = ["derive"] } parking_lot = "0.10.0" -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } rand = "0.7.2" -sp-runtime = { version = "2.0.0-alpha.5", path = "../../primitives/runtime" } -sp-utils = { version = "2.0.0-alpha.5", path = "../../primitives/utils" } -sc-network = { version = "0.8.0-alpha.5", path = "../network" } -sc-keystore = { version = "2.0.0-alpha.5", path = "../keystore" } +sp-runtime = { version = "2.0.0-rc4", path = "../../primitives/runtime" } +sp-utils = { version = "2.0.0-rc4", path = "../../primitives/utils" } +sc-network = { version = "0.8.0-rc4", path = "../network" } +sc-keystore = { version = "2.0.0-rc4", path = "../keystore" } [target.'cfg(not(target_os = "unknown"))'.dependencies] hyper = "0.13.2" @@ -34,15 +37,12 @@ hyper-rustls = "0.20" [dev-dependencies] env_logger = "0.7.0" -fdlimit = "0.1.4" -sc-client-db = { version = "0.8.0-alpha.5", default-features = true, path = "../db/" } -sc-transaction-pool = { version = "2.0.0-alpha.5", path = "../../client/transaction-pool" } -sp-transaction-pool = { version = "2.0.0-alpha.5", path = "../../primitives/transaction-pool" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../test-utils/runtime/client" } +sc-client-db = { version = "0.8.0-rc4", default-features = true, path = "../db/" } +sc-transaction-pool = { version = "2.0.0-rc4", path = "../../client/transaction-pool" } +sp-transaction-pool = { version = "2.0.0-rc4", path = "../../primitives/transaction-pool" } +substrate-test-runtime-client = { version = "2.0.0-rc4", path = "../../test-utils/runtime/client" } tokio = "0.2" +lazy_static = "1.4.0" [features] default = [] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/client/offchain/src/api.rs b/client/offchain/src/api.rs index 45a82d230c11a6dd6d6c8ce03635d1c49c6d7ce7..0aa5d4ad788abe1fdbf8c0525ac375cd66a68375 100644 --- a/client/offchain/src/api.rs +++ b/client/offchain/src/api.rs @@ -31,6 +31,7 @@ use sp_core::offchain::{ OpaqueNetworkState, OpaquePeerId, OpaqueMultiaddr, StorageKind, }; pub use sp_offchain::STORAGE_PREFIX; +pub use http::SharedClient; #[cfg(not(target_os = "unknown"))] mod http; @@ -100,6 +101,13 @@ impl OffchainExt for Api { } } + fn local_storage_clear(&mut self, kind: StorageKind, key: &[u8]) { + match kind { + StorageKind::PERSISTENT => self.db.remove(STORAGE_PREFIX, key), + StorageKind::LOCAL => unavailable_yet(LOCAL_DB), + } + } + fn local_storage_compare_and_set( &mut self, kind: StorageKind, @@ -253,8 +261,9 @@ impl AsyncApi { db: S, network_state: Arc, is_validator: bool, - ) -> (Api, AsyncApi) { - let (http_api, http_worker) = http::http(); + shared_client: SharedClient, + ) -> (Api, Self) { + let (http_api, http_worker) = http::http(shared_client); let api = Api { db, @@ -263,7 +272,7 @@ impl AsyncApi { http: http_api, }; - let async_api = AsyncApi { + let async_api = Self { http: Some(http_worker), }; @@ -301,11 +310,14 @@ mod tests { let _ = env_logger::try_init(); let db = LocalStorage::new_test(); let mock = Arc::new(MockNetworkStateInfo()); + let shared_client = SharedClient::new(); + AsyncApi::new( db, mock, false, + shared_client, ) } diff --git a/client/offchain/src/api/http.rs b/client/offchain/src/api/http.rs index a64fe0389706c1098eda9f1c2fbd2294843d7597..1f542b7c11e19b8bd76a39ec3c6555b5c716a866 100644 --- a/client/offchain/src/api/http.rs +++ b/client/offchain/src/api/http.rs @@ -31,11 +31,24 @@ use fnv::FnvHashMap; use futures::{prelude::*, future, channel::mpsc}; use log::error; use sp_core::offchain::{HttpRequestId, Timestamp, HttpRequestStatus, HttpError}; -use std::{fmt, io::Read as _, mem, pin::Pin, task::Context, task::Poll}; +use std::{convert::TryFrom, fmt, io::Read as _, pin::Pin, task::{Context, Poll}}; use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedSender, TracingUnboundedReceiver}; +use std::sync::Arc; +use hyper::{Client as HyperClient, Body, client}; +use hyper_rustls::HttpsConnector; + +/// Wrapper struct used for keeping the hyper_rustls client running. +#[derive(Clone)] +pub struct SharedClient(Arc, Body>>); + +impl SharedClient { + pub fn new() -> Self { + Self(Arc::new(HyperClient::builder().build(HttpsConnector::new()))) + } +} /// Creates a pair of [`HttpApi`] and [`HttpWorker`]. -pub fn http() -> (HttpApi, HttpWorker) { +pub fn http(shared_client: SharedClient) -> (HttpApi, HttpWorker) { let (to_worker, from_api) = tracing_unbounded("mpsc_ocw_to_worker"); let (to_api, from_worker) = tracing_unbounded("mpsc_ocw_to_api"); @@ -51,7 +64,7 @@ pub fn http() -> (HttpApi, HttpWorker) { let engine = HttpWorker { to_api, from_api, - http_client: hyper::Client::builder().build(hyper_rustls::HttpsConnector::new()), + http_client: shared_client.0, requests: Vec::new(), }; @@ -151,8 +164,8 @@ impl HttpApi { _ => return Err(()) }; - let name = hyper::header::HeaderName::from_bytes(name.as_bytes()).map_err(|_| ())?; - let value = hyper::header::HeaderValue::from_str(value).map_err(|_| ())?; + let name = hyper::header::HeaderName::try_from(name).map_err(drop)?; + let value = hyper::header::HeaderValue::try_from(value).map_err(drop)?; // 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); @@ -185,7 +198,7 @@ impl HttpApi { 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 }); + debug_assert!(matches!(deadline, future::MaybeDone::Done(..))); return Err(HttpError::DeadlineReached) } }; @@ -347,7 +360,7 @@ impl HttpApi { if let future::MaybeDone::Done(msg) = next_msg { msg } else { - debug_assert!(if let future::MaybeDone::Done(_) = deadline { true } else { false }); + debug_assert!(matches!(deadline, future::MaybeDone::Done(..))); continue } }; @@ -551,7 +564,7 @@ pub struct HttpWorker { /// Used to receive messages from the `HttpApi`. from_api: TracingUnboundedReceiver, /// The engine that runs HTTP requests. - http_client: hyper::Client, hyper::Body>, + http_client: Arc, Body>>, /// HTTP requests that are being worked on by the engine. requests: Vec<(HttpRequestId, HttpWorkerRequest)>, } @@ -585,25 +598,21 @@ impl Future for HttpWorker { 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) { + let 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, - }); + Poll::Ready(Err(error)) => { + let _ = me.to_api.unbounded_send(WorkerToApi::Fail { id, error }); 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 = response.into_body(); + let (head, body) = response.into_parts(); + let (status_code, headers) = (head.status, head.headers); let (body_tx, body_rx) = mpsc::channel(3); let _ = me.to_api.unbounded_send(WorkerToApi::Response { @@ -689,29 +698,29 @@ impl fmt::Debug for HttpWorkerRequest { mod tests { use core::convert::Infallible; use crate::api::timestamp; - use super::http; + use super::{http, SharedClient}; use sp_core::offchain::{HttpError, HttpRequestId, HttpRequestStatus, Duration}; + use futures::future; + use lazy_static::lazy_static; + + // Using lazy_static to avoid spawning lots of different SharedClients, + // as spawning a SharedClient is CPU-intensive and opens lots of fds. + lazy_static! { + static ref SHARED_CLIENT: SharedClient = SharedClient::new(); + } // 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 { () => {{ - fn tokio_run(future: impl std::future::Future) { - let _ = tokio::runtime::Runtime::new().unwrap().block_on(future); - } - - // We spawn quite a bit of HTTP servers here due to how async API - // works for offchain workers, so be sure to raise the FD limit - // (particularly useful for macOS where the default soft limit may - // not be enough). - fdlimit::raise_fd_limit(); - - let (api, worker) = http(); - std::thread::spawn(move || tokio_run(worker)); + let hyper_client = SHARED_CLIENT.clone(); + let (api, worker) = http(hyper_client.clone()); let (addr_tx, addr_rx) = std::sync::mpsc::channel(); std::thread::spawn(move || { - tokio_run(async move { + let mut rt = tokio::runtime::Runtime::new().unwrap(); + let worker = rt.spawn(worker); + let server = rt.spawn(async move { let server = hyper::Server::bind(&"127.0.0.1:0".parse().unwrap()) .serve(hyper::service::make_service_fn(|_| { async move { Ok::<_, Infallible>(hyper::service::service_fn(move |_req| async move { @@ -721,8 +730,9 @@ mod tests { })) }})); let _ = addr_tx.send(server.local_addr()); - server.await + server.await.map_err(drop) }); + let _ = rt.block_on(future::join(worker, server)); }); (api, addr_rx.recv().unwrap()) }}; @@ -891,10 +901,10 @@ mod tests { #[test] fn response_headers_invalid_call() { let (mut api, addr) = build_api_server!(); - assert!(api.response_headers(HttpRequestId(0xdead)).is_empty()); + assert_eq!(api.response_headers(HttpRequestId(0xdead)), &[]); let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); - assert!(api.response_headers(id).is_empty()); + assert_eq!(api.response_headers(id), &[]); let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); api.request_write_body(id, &[], None).unwrap(); @@ -904,12 +914,12 @@ mod tests { let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); api.response_wait(&[id], None); - assert!(!api.response_headers(id).is_empty()); + assert_ne!(api.response_headers(id), &[]); 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()); + assert_eq!(api.response_headers(id), &[]); } #[test] @@ -917,11 +927,11 @@ mod tests { let (mut api, addr) = build_api_server!(); let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); - assert!(api.response_headers(id).is_empty()); + assert_eq!(api.response_headers(id), &[]); 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()); + assert_eq!(api.response_headers(id), &[]); let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); api.request_add_header(id, "Foo", "Bar").unwrap(); @@ -930,7 +940,7 @@ mod tests { // 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()); + assert_eq!(api.response_headers(id), &[]); } #[test] diff --git a/client/offchain/src/api/http_dummy.rs b/client/offchain/src/api/http_dummy.rs index 5ff77a1068312bbc5da2f71d9c15a9dee7bd8380..1c83325c93b2095fe4bc5fca9c7dbfb4e48e3b2a 100644 --- a/client/offchain/src/api/http_dummy.rs +++ b/client/offchain/src/api/http_dummy.rs @@ -19,8 +19,18 @@ use sp_core::offchain::{HttpRequestId, Timestamp, HttpRequestStatus, HttpError}; use std::{future::Future, pin::Pin, task::Context, task::Poll}; +/// Wrapper struct (wrapping nothing in case of http_dummy) used for keeping the hyper_rustls client running. +#[derive(Clone)] +pub struct SharedClient; + +impl SharedClient { + pub fn new() -> Self { + Self + } +} + /// Creates a pair of [`HttpApi`] and [`HttpWorker`]. -pub fn http() -> (HttpApi, HttpWorker) { +pub fn http(_: SharedClient) -> (HttpApi, HttpWorker) { (HttpApi, HttpWorker) } diff --git a/client/offchain/src/api/timestamp.rs b/client/offchain/src/api/timestamp.rs index e5494fe70d784bca20917a38a530ef37c06b3393..222d3273cb355fa64ac4f52f8dcb568b69be25b8 100644 --- a/client/offchain/src/api/timestamp.rs +++ b/client/offchain/src/api/timestamp.rs @@ -51,12 +51,14 @@ pub fn timestamp_from_now(timestamp: Timestamp) -> Duration { pub fn deadline_to_future( deadline: Option, ) -> futures::future::MaybeDone { - use futures::future; + use futures::future::{self, Either}; - future::maybe_done(match deadline { - Some(deadline) => future::Either::Left( - futures_timer::Delay::new(timestamp_from_now(deadline)) - ), - None => future::Either::Right(future::pending()) + future::maybe_done(match deadline.map(timestamp_from_now) { + None => Either::Left(future::pending()), + // Only apply delay if we need to wait a non-zero duration + Some(duration) if duration <= Duration::from_secs(0) => + Either::Right(Either::Left(future::ready(()))), + Some(duration) => + Either::Right(Either::Right(futures_timer::Delay::new(duration))), }) } diff --git a/client/offchain/src/lib.rs b/client/offchain/src/lib.rs index 94850e3fd3461c3cf79ecd48e905051991324941..f2fb8a8e978a04e87fa0c174f160aa81e87f6abd 100644 --- a/client/offchain/src/lib.rs +++ b/client/offchain/src/lib.rs @@ -19,7 +19,7 @@ //! The offchain workers is a special function of the runtime that //! gets executed after block is imported. During execution //! it's able to asynchronously submit extrinsics that will either -//! be propagated to other nodes added to the next block +//! be propagated to other nodes or added to the next block //! produced by the node as unsigned transactions. //! //! Offchain workers can be used for computation-heavy tasks @@ -41,10 +41,12 @@ use sp_api::{ApiExt, ProvideRuntimeApi}; use futures::future::Future; use log::{debug, warn}; use sc_network::NetworkStateInfo; -use sp_core::{offchain::{self, OffchainStorage}, ExecutionContext}; +use sp_core::{offchain::{self, OffchainStorage}, ExecutionContext, traits::SpawnNamed}; use sp_runtime::{generic::BlockId, traits::{self, Header}}; +use futures::{prelude::*, future::ready}; mod api; +use api::SharedClient; pub use sp_offchain::{OffchainWorkerApi, STORAGE_PREFIX}; @@ -54,16 +56,19 @@ pub struct OffchainWorkers { db: Storage, _block: PhantomData, thread_pool: Mutex, + shared_client: SharedClient, } impl OffchainWorkers { /// Creates new `OffchainWorkers`. pub fn new(client: Arc, db: Storage) -> Self { + let shared_client = SharedClient::new(); Self { client, db, _block: PhantomData, thread_pool: Mutex::new(ThreadPool::new(num_cpus::get())), + shared_client, } } } @@ -119,6 +124,7 @@ impl OffchainWorkers< self.db.clone(), network_state.clone(), is_validator, + self.shared_client.clone(), ); debug!("Spawning offchain workers at {:?}", at); let header = header.clone(); @@ -161,15 +167,51 @@ impl OffchainWorkers< } } +/// Inform the offchain worker about new imported blocks +pub async fn notification_future( + is_validator: bool, + client: Arc, + offchain: Arc>, + spawner: Spawner, + network_state_info: Arc, +) + where + Block: traits::Block, + Client: ProvideRuntimeApi + sc_client_api::BlockchainEvents + Send + Sync + 'static, + Client::Api: OffchainWorkerApi, + Storage: OffchainStorage + 'static, + Spawner: SpawnNamed +{ + client.import_notification_stream().for_each(move |n| { + if n.is_new_best { + spawner.spawn( + "offchain-on-block", + offchain.on_block_imported( + &n.header, + network_state_info.clone(), + is_validator, + ).boxed(), + ); + } else { + log::debug!( + target: "sc_offchain", + "Skipping offchain workers for non-canon block: {:?}", + n.header, + ) + } + + ready(()) + }).await; +} + #[cfg(test)] mod tests { use super::*; use std::sync::Arc; use sc_network::{Multiaddr, PeerId}; - use substrate_test_runtime_client::runtime::Block; + use substrate_test_runtime_client::{TestClient, runtime::Block}; use sc_transaction_pool::{BasicPool, FullChainApi}; use sp_transaction_pool::{TransactionPool, InPoolTransaction}; - use sc_client_api::ExecutorProvider; struct MockNetworkStateInfo(); @@ -183,7 +225,9 @@ mod tests { } } - struct TestPool(BasicPool, Block>); + struct TestPool( + Arc, Block>> + ); impl sp_transaction_pool::OffchainSubmitTransaction for TestPool { fn submit_at( @@ -200,15 +244,17 @@ mod tests { #[test] fn should_call_into_runtime_and_produce_extrinsic() { - // given let _ = env_logger::try_init(); + let client = Arc::new(substrate_test_runtime_client::new()); - let pool = Arc::new(TestPool(BasicPool::new( + let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let pool = TestPool(BasicPool::new_full( Default::default(), - Arc::new(FullChainApi::new(client.clone())), - ).0)); - client.execution_extensions() - .register_transaction_pool(Arc::downgrade(&pool.clone()) as _); + Arc::new(FullChainApi::new(client.clone(), None)), + None, + spawner, + client.clone(), + )); let db = sc_client_db::offchain::LocalStorage::new_test(); let network_state = Arc::new(MockNetworkStateInfo()); let header = client.header(&BlockId::number(0)).unwrap().unwrap(); diff --git a/client/peerset/Cargo.toml b/client/peerset/Cargo.toml index 78d488a9899fc75ec68aad74e48c9017e8ae5de4..06c936b255e3260a44d7a785b134bdb30030e553 100644 --- a/client/peerset/Cargo.toml +++ b/client/peerset/Cargo.toml @@ -1,25 +1,25 @@ [package] description = "Connectivity manager based on reputation" homepage = "http://parity.io" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" name = "sc-peerset" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" repository = "https://github.com/paritytech/substrate/" documentation = "https://docs.rs/sc-peerset" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] futures = "0.3.4" -libp2p = { version = "0.16.2", default-features = false } -sp-utils = { version = "2.0.0-alpha.5", path = "../../primitives/utils"} +libp2p = { version = "0.21.1", default-features = false } +sp-utils = { version = "2.0.0-rc4", path = "../../primitives/utils"} log = "0.4.8" serde_json = "1.0.41" wasm-timer = "0.2" [dev-dependencies] rand = "0.7.2" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/client/peerset/src/lib.rs b/client/peerset/src/lib.rs index 9376e9594b4b702dc3746661196065e4851c78b9..6f28dd036a3cc53408583be8cbe04e24af9a8448 100644 --- a/client/peerset/src/lib.rs +++ b/client/peerset/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Peer Set Manager (PSM). Contains the strategy for choosing which nodes the network should be //! connected to. @@ -180,9 +182,13 @@ pub struct PeersetConfig { /// errors. #[derive(Debug)] pub struct Peerset { + /// Underlying data structure for the nodes's states. data: peersstate::PeersState, /// If true, we only accept reserved nodes. reserved_only: bool, + /// Lists of nodes that don't occupy slots and that we should try to always be connected to. + /// Is kept in sync with the list of reserved nodes in [`Peerset::data`]. + priority_groups: HashMap>, /// Receiver for messages from the `PeersetHandle` and from `tx`. rx: TracingUnboundedReceiver, /// Sending side of `rx`. @@ -207,17 +213,18 @@ impl Peerset { let now = Instant::now(); let mut peerset = Peerset { - data: peersstate::PeersState::new(config.in_peers, config.out_peers, config.reserved_only), + data: peersstate::PeersState::new(config.in_peers, config.out_peers), tx, rx, reserved_only: config.reserved_only, + priority_groups: config.priority_groups.clone().into_iter().collect(), message_queue: VecDeque::new(), created: now, latest_time_update: now, }; - for (group, nodes) in config.priority_groups { - peerset.data.set_priority_group(&group, nodes); + for node in config.priority_groups.into_iter().flat_map(|(_, l)| l) { + peerset.data.add_no_slot_node(node); } for peer_id in config.bootnodes { @@ -233,61 +240,92 @@ impl Peerset { } fn on_add_reserved_peer(&mut self, peer_id: PeerId) { - let mut reserved = self.data.get_priority_group(RESERVED_NODES).unwrap_or_default(); - reserved.insert(peer_id); - self.data.set_priority_group(RESERVED_NODES, reserved); - self.alloc_slots(); + self.on_add_to_priority_group(RESERVED_NODES, peer_id); } fn on_remove_reserved_peer(&mut self, peer_id: PeerId) { - let mut reserved = self.data.get_priority_group(RESERVED_NODES).unwrap_or_default(); - reserved.remove(&peer_id); - self.data.set_priority_group(RESERVED_NODES, reserved); - match self.data.peer(&peer_id) { - peersstate::Peer::Connected(peer) => { - if self.reserved_only { - peer.disconnect(); - self.message_queue.push_back(Message::Drop(peer_id)); - } - } - peersstate::Peer::NotConnected(_) => {}, - peersstate::Peer::Unknown(_) => {}, - } + self.on_remove_from_priority_group(RESERVED_NODES, peer_id); } fn on_set_reserved_only(&mut self, reserved_only: bool) { 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(); + // Disconnect all the nodes that aren't reserved. for peer_id in self.data.connected_peers().cloned().collect::>().into_iter() { + if self.priority_groups.get(RESERVED_NODES).map_or(false, |g| g.contains(&peer_id)) { + continue; + } + let peer = self.data.peer(&peer_id).into_connected() .expect("We are enumerating connected peers, therefore the peer is connected; qed"); - if !reserved.contains(&peer_id) { - peer.disconnect(); - self.message_queue.push_back(Message::Drop(peer_id)); - } + peer.disconnect(); + self.message_queue.push_back(Message::Drop(peer_id)); } + } else { self.alloc_slots(); } } fn on_set_priority_group(&mut self, group_id: &str, peers: HashSet) { - self.data.set_priority_group(group_id, peers); - self.alloc_slots(); + // Determine the difference between the current group and the new list. + let (to_insert, to_remove) = { + let current_group = self.priority_groups.entry(group_id.to_owned()).or_default(); + let to_insert = peers.difference(current_group) + .cloned().collect::>(); + let to_remove = current_group.difference(&peers) + .cloned().collect::>(); + (to_insert, to_remove) + }; + + // Enumerate elements in `peers` not in `current_group`. + for peer_id in &to_insert { + // We don't call `on_add_to_priority_group` here in order to avoid calling + // `alloc_slots` all the time. + self.priority_groups.entry(group_id.to_owned()).or_default().insert(peer_id.clone()); + self.data.add_no_slot_node(peer_id.clone()); + } + + // Enumerate elements in `current_group` not in `peers`. + for peer in to_remove { + self.on_remove_from_priority_group(group_id, peer); + } + + if !to_insert.is_empty() { + self.alloc_slots(); + } } fn on_add_to_priority_group(&mut self, group_id: &str, peer_id: PeerId) { - self.data.add_to_priority_group(group_id, peer_id); + self.priority_groups.entry(group_id.to_owned()).or_default().insert(peer_id.clone()); + self.data.add_no_slot_node(peer_id); self.alloc_slots(); } fn on_remove_from_priority_group(&mut self, group_id: &str, peer_id: PeerId) { - self.data.remove_from_priority_group(group_id, &peer_id); - self.alloc_slots(); + if let Some(priority_group) = self.priority_groups.get_mut(group_id) { + if !priority_group.remove(&peer_id) { + // `PeerId` wasn't in the group in the first place. + return; + } + } else { + // Group doesn't exist, so the `PeerId` can't be in it. + return; + } + + // If that `PeerId` isn't in any other group, then it is no longer no-slot-occupying. + if !self.priority_groups.values().any(|l| l.contains(&peer_id)) { + self.data.remove_no_slot_node(&peer_id); + } + + // Disconnect the peer if necessary. + if group_id != RESERVED_NODES && self.reserved_only { + if let peersstate::Peer::Connected(peer) = self.data.peer(&peer_id) { + peer.disconnect(); + self.message_queue.push_back(Message::Drop(peer_id)); + } + } } fn on_report_peer(&mut self, peer_id: PeerId, change: ReputationChange) { @@ -374,25 +412,82 @@ impl Peerset { fn alloc_slots(&mut self) { self.update_time(); - // Try to grab the next node to attempt to connect to. - while let Some(next) = { - if self.reserved_only { - self.data.priority_not_connected_peer_from_group(RESERVED_NODES) - } else { - self.data.priority_not_connected_peer() - } - } { + // Try to connect to all the reserved nodes that we are not connected to. + loop { + let next = { + let data = &mut self.data; + self.priority_groups + .get(RESERVED_NODES) + .into_iter() + .flatten() + .filter(move |n| { + data.peer(n).into_connected().is_none() + }) + .next() + .cloned() + }; + + let next = match next { + Some(n) => n, + None => break, + }; + + let next = match self.data.peer(&next) { + peersstate::Peer::Unknown(n) => n.discover(), + peersstate::Peer::NotConnected(n) => n, + peersstate::Peer::Connected(_) => { + debug_assert!(false, "State inconsistency: not connected state"); + break; + } + }; + match next.try_outgoing() { Ok(conn) => self.message_queue.push_back(Message::Connect(conn.into_peer_id())), Err(_) => break, // No more slots available. } } + // Nothing more to do if we're in reserved mode. + if self.reserved_only { + return; + } + + // Try to connect to all the nodes in priority groups and that we are not connected to. loop { - if self.reserved_only { - break + let next = { + let data = &mut self.data; + self.priority_groups + .values() + .flatten() + .filter(move |n| { + data.peer(n).into_connected().is_none() + }) + .next() + .cloned() + }; + + let next = match next { + Some(n) => n, + None => break, + }; + + let next = match self.data.peer(&next) { + peersstate::Peer::Unknown(n) => n.discover(), + peersstate::Peer::NotConnected(n) => n, + peersstate::Peer::Connected(_) => { + debug_assert!(false, "State inconsistency: not connected state"); + break; + } + }; + + match next.try_outgoing() { + Ok(conn) => self.message_queue.push_back(Message::Connect(conn.into_peer_id())), + Err(_) => break, // No more slots available. } + } + // Now, we try to connect to non-priority nodes. + loop { // Try to grab the next node to attempt to connect to. let next = match self.data.highest_not_connected_peer() { Some(p) => p, @@ -425,6 +520,13 @@ impl Peerset { trace!(target: "peerset", "Incoming {:?}", peer_id); self.update_time(); + if self.reserved_only { + if !self.priority_groups.get(RESERVED_NODES).map_or(false, |n| n.contains(&peer_id)) { + self.message_queue.push_back(Message::Reject(index)); + return; + } + } + let not_connected = match self.data.peer(&peer_id) { // If we're already connected, don't answer, as the docs mention. peersstate::Peer::Connected(_) => return, @@ -527,9 +629,9 @@ impl Peerset { self.data.peers().len() } - /// Returns priority group by id. - pub fn get_priority_group(&self, group_id: &str) -> Option> { - self.data.get_priority_group(group_id) + /// Returns the content of a priority group. + pub fn priority_group(&self, group_id: &str) -> Option> { + self.priority_groups.get(group_id).map(|l| l.iter()) } } @@ -581,7 +683,6 @@ mod tests { assert_eq!(message, expected_message); peerset = p; } - assert!(peerset.message_queue.is_empty(), peerset.message_queue); peerset } @@ -646,6 +747,26 @@ mod tests { ]); } + #[test] + fn test_peerset_reject_incoming_in_reserved_only() { + let incoming = PeerId::random(); + let ii = IncomingIndex(1); + let config = PeersetConfig { + in_peers: 50, + out_peers: 50, + bootnodes: vec![], + reserved_only: true, + priority_groups: vec![], + }; + + let (mut peerset, _) = Peerset::from_config(config); + peerset.incoming(incoming.clone(), ii); + + assert_messages(peerset, vec![ + Message::Reject(ii), + ]); + } + #[test] fn test_peerset_discovered() { let bootnode = PeerId::random(); @@ -711,4 +832,3 @@ mod tests { futures::executor::block_on(fut); } } - diff --git a/client/peerset/src/peersstate.rs b/client/peerset/src/peersstate.rs index 843ec0a36006f436e3d9b2b9c83175ec632566e5..59879f629e31ecdbfbcb224a8a7dfb437f150746 100644 --- a/client/peerset/src/peersstate.rs +++ b/client/peerset/src/peersstate.rs @@ -14,10 +14,19 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Contains the state storage behind the peerset. +//! Reputation and slots allocation system behind the peerset. +//! +//! The [`PeersState`] state machine is responsible for managing the reputation and allocating +//! slots. It holds a list of nodes, each associated with a reputation value and whether we are +//! connected or not to this node. Thanks to this list, it knows how many slots are occupied. It +//! also holds a list of nodes which don't occupy slots. +//! +//! > Note: This module is purely dedicated to managing slots and reputations. Features such as +//! > for example connecting to some nodes in priority should be added outside of this +//! > module, rather than inside. use libp2p::PeerId; -use log::{error, warn}; +use log::error; use std::{borrow::Cow, collections::{HashSet, HashMap}}; use wasm_timer::Instant; @@ -37,23 +46,24 @@ pub struct PeersState { /// sort, to make the logic easier. nodes: HashMap, - /// Number of non-priority nodes for which the `ConnectionState` is `In`. + /// Number of slot-occupying nodes for which the `ConnectionState` is `In`. num_in: u32, - /// Number of non-priority nodes for which the `ConnectionState` is `In`. + /// Number of slot-occupying nodes for which the `ConnectionState` is `In`. num_out: u32, - /// Maximum allowed number of non-priority nodes for which the `ConnectionState` is `In`. + /// Maximum allowed number of slot-occupying nodes for which the `ConnectionState` is `In`. max_in: u32, - /// Maximum allowed number of non-priority nodes for which the `ConnectionState` is `Out`. + /// Maximum allowed number of slot-occupying nodes for which the `ConnectionState` is `Out`. max_out: u32, - /// 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, + /// List of node identities (discovered or not) that don't occupy slots. + /// + /// Note for future readers: this module is purely dedicated to managing slots. If you are + /// considering adding more features, please consider doing so outside of this module rather + /// than inside. + no_slot_nodes: HashSet, } /// State of a single node that we know about. @@ -106,15 +116,14 @@ impl ConnectionState { impl PeersState { /// Builds a new empty `PeersState`. - pub fn new(in_peers: u32, out_peers: u32, priority_only: bool) -> Self { + pub fn new(in_peers: u32, out_peers: u32) -> Self { PeersState { nodes: HashMap::new(), num_in: 0, num_out: 0, max_in: in_peers, max_out: out_peers, - priority_nodes: HashMap::new(), - priority_only, + no_slot_nodes: HashSet::new(), } } @@ -157,34 +166,6 @@ impl PeersState { .map(|(p, _)| p) } - /// Returns the first priority peer that we are not connected to. - /// - /// If multiple nodes are prioritized, which one is returned is unspecified. - pub fn priority_not_connected_peer(&mut self) -> Option { - let id = self.priority_nodes.values() - .flatten() - .find(|&id| self.nodes.get(id).map_or(false, |node| !node.connection_state.is_connected())) - .cloned(); - id.map(move |id| NotConnectedPeer { - state: self, - peer_id: Cow::Owned(id), - }) - } - - /// Returns the first priority peer that we are not connected to. - /// - /// If multiple nodes are prioritized, which one is returned is unspecified. - pub fn priority_not_connected_peer_from_group(&mut self, group_id: &str) -> Option { - let id = self.priority_nodes.get(group_id) - .and_then(|group| group.iter() - .find(|&id| self.nodes.get(id).map_or(false, |node| !node.connection_state.is_connected())) - .cloned()); - id.map(move |id| NotConnectedPeer { - state: self, - peer_id: Cow::Owned(id), - }) - } - /// Returns the peer with the highest reputation and that we are not connected to. /// /// If multiple nodes have the same reputation, which one is returned is unspecified. @@ -212,170 +193,40 @@ impl PeersState { } } - fn disconnect(&mut self, peer_id: &PeerId) { - let is_priority = self.is_priority(peer_id); - if let Some(mut node) = self.nodes.get_mut(peer_id) { - if !is_priority { - match node.connection_state { - ConnectionState::In => self.num_in -= 1, - ConnectionState::Out => self.num_out -= 1, - ConnectionState::NotConnected { .. } => - debug_assert!(false, "State inconsistency: disconnecting a disconnected node") - } - } - node.connection_state = ConnectionState::NotConnected { - last_connected: Instant::now(), - }; - } else { - warn!(target: "peerset", "Attempting to disconnect unknown peer {}", peer_id); - } - } - - /// 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. - if self.num_out >= self.max_out && !is_priority { - return false; + /// Add a node to the list of nodes that don't occupy slots. + /// + /// Has no effect if the peer was already in the group. + pub fn add_no_slot_node(&mut self, peer_id: PeerId) { + // Reminder: `HashSet::insert` returns false if the node was already in the set + if !self.no_slot_nodes.insert(peer_id.clone()) { + return; } - if let Some(mut peer) = self.nodes.get_mut(peer_id) { - peer.connection_state = ConnectionState::Out; - if !is_priority { - self.num_out += 1; + if let Some(peer) = self.nodes.get_mut(&peer_id) { + match peer.connection_state { + ConnectionState::In => self.num_in -= 1, + ConnectionState::Out => self.num_out -= 1, + ConnectionState::NotConnected { .. } => {}, } - return true; } - false } - /// Tries to accept the peer as an incoming connection. - /// - /// If there are enough slots available, switches the node to "connected" and returns `true`. If - /// the slots are full, the node stays "not connected" and we return `false`. + /// Removes a node from the list of nodes that don't occupy slots. /// - /// 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; + /// Has no effect if the peer was not in the group. + pub fn remove_no_slot_node(&mut self, peer_id: &PeerId) { + // Reminder: `HashSet::remove` returns false if the node was already not in the set + if !self.no_slot_nodes.remove(peer_id) { + return; } - // 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 { - return false; - } - if let Some(mut peer) = self.nodes.get_mut(peer_id) { - peer.connection_state = ConnectionState::In; - if !is_priority { - self.num_in += 1; + if let Some(peer) = self.nodes.get_mut(peer_id) { + match peer.connection_state { + ConnectionState::In => self.num_in += 1, + ConnectionState::Out => self.num_out += 1, + ConnectionState::NotConnected { .. } => {}, } - return true; } - false - } - - /// Sets priority group - pub fn set_priority_group(&mut self, group_id: &str, peers: HashSet) { - // update slot counters - let all_other_groups: HashSet<_> = self.priority_nodes - .iter() - .filter(|(g, _)| *g != group_id) - .flat_map(|(_, id)| id.clone()) - .collect(); - let existing_group = self.priority_nodes.remove(group_id).unwrap_or_default(); - for id in existing_group { - // update slots for nodes that are no longer priority - if !all_other_groups.contains(&id) { - if let Some(peer) = self.nodes.get_mut(&id) { - match peer.connection_state { - ConnectionState::In => self.num_in += 1, - ConnectionState::Out => self.num_out += 1, - ConnectionState::NotConnected { .. } => {}, - } - } - } - } - - for id in &peers { - // update slots for nodes that become priority - if !all_other_groups.contains(id) { - let peer = self.nodes.entry(id.clone()).or_default(); - match peer.connection_state { - ConnectionState::In => self.num_in -= 1, - ConnectionState::Out => self.num_out -= 1, - ConnectionState::NotConnected { .. } => {}, - } - } - } - self.priority_nodes.insert(group_id.into(), peers); - } - - /// Add a peer to a priority group. - pub fn add_to_priority_group(&mut self, group_id: &str, peer_id: PeerId) { - let mut peers = self.priority_nodes.get(group_id).cloned().unwrap_or_default(); - peers.insert(peer_id); - self.set_priority_group(group_id, peers); - } - - /// Remove a peer from a priority group. - pub fn remove_from_priority_group(&mut self, group_id: &str, peer_id: &PeerId) { - let mut peers = self.priority_nodes.get(group_id).cloned().unwrap_or_default(); - peers.remove(peer_id); - self.set_priority_group(group_id, peers); - } - - /// Get priority group content. - pub fn get_priority_group(&self, group_id: &str) -> Option> { - 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)) - } - - /// Returns the reputation value of the node. - fn reputation(&self, peer_id: &PeerId) -> i32 { - self.nodes.get(peer_id).map_or(0, |p| p.reputation) - } - - /// Sets the reputation of the peer. - fn set_reputation(&mut self, peer_id: &PeerId, value: i32) { - let node = self.nodes - .entry(peer_id.clone()) - .or_default(); - node.reputation = value; - } - - /// Performs an arithmetic addition on the reputation score of that peer. - /// - /// In case of overflow, the value will be capped. - /// If the peer is unknown to us, we insert it and consider that it has a reputation of 0. - fn add_reputation(&mut self, peer_id: &PeerId, modifier: i32) { - let node = self.nodes - .entry(peer_id.clone()) - .or_default(); - node.reputation = node.reputation.saturating_add(modifier); } } @@ -437,7 +288,23 @@ impl<'a> ConnectedPeer<'a> { /// Switches the peer to "not connected". pub fn disconnect(self) -> NotConnectedPeer<'a> { - self.state.disconnect(&self.peer_id); + let is_no_slot_occupy = self.state.no_slot_nodes.contains(&*self.peer_id); + if let Some(mut node) = self.state.nodes.get_mut(&*self.peer_id) { + if !is_no_slot_occupy { + match node.connection_state { + ConnectionState::In => self.state.num_in -= 1, + ConnectionState::Out => self.state.num_out -= 1, + ConnectionState::NotConnected { .. } => + debug_assert!(false, "State inconsistency: disconnecting a disconnected node") + } + } + node.connection_state = ConnectionState::NotConnected { + last_connected: Instant::now(), + }; + } else { + debug_assert!(false, "State inconsistency: disconnecting a disconnected node"); + } + NotConnectedPeer { state: self.state, peer_id: self.peer_id, @@ -446,19 +313,27 @@ impl<'a> ConnectedPeer<'a> { /// Returns the reputation value of the node. pub fn reputation(&self) -> i32 { - self.state.reputation(&self.peer_id) + self.state.nodes.get(&*self.peer_id).map_or(0, |p| p.reputation) } /// Sets the reputation of the peer. pub fn set_reputation(&mut self, value: i32) { - self.state.set_reputation(&self.peer_id, value) + if let Some(node) = self.state.nodes.get_mut(&*self.peer_id) { + node.reputation = value; + } else { + debug_assert!(false, "State inconsistency: set_reputation on an unknown node"); + } } /// Performs an arithmetic addition on the reputation score of that peer. /// /// In case of overflow, the value will be capped. pub fn add_reputation(&mut self, modifier: i32) { - self.state.add_reputation(&self.peer_id, modifier) + if let Some(node) = self.state.nodes.get_mut(&*self.peer_id) { + node.reputation = node.reputation.saturating_add(modifier); + } else { + debug_assert!(false, "State inconsistency: add_reputation on an unknown node"); + } } } @@ -520,16 +395,29 @@ impl<'a> NotConnectedPeer<'a> { /// If there are enough slots available, switches the node to "connected" and returns `Ok`. If /// the slots are full, the node stays "not connected" and we return `Err`. /// - /// Note that priority nodes don't count towards the number of slots. + /// Non-slot-occupying nodes don't count towards the number of slots. pub fn try_outgoing(self) -> Result, NotConnectedPeer<'a>> { - if self.state.try_outgoing(&self.peer_id) { - Ok(ConnectedPeer { - state: self.state, - peer_id: self.peer_id, - }) + let is_no_slot_occupy = self.state.no_slot_nodes.contains(&*self.peer_id); + + // 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. + if self.state.num_out >= self.state.max_out && !is_no_slot_occupy { + return Err(self); + } + + if let Some(mut peer) = self.state.nodes.get_mut(&*self.peer_id) { + peer.connection_state = ConnectionState::Out; + if !is_no_slot_occupy { + self.state.num_out += 1; + } } else { - Err(self) + debug_assert!(false, "State inconsistency: try_outgoing on an unknown node"); } + + Ok(ConnectedPeer { + state: self.state, + peer_id: self.peer_id, + }) } /// Tries to accept the peer as an incoming connection. @@ -537,34 +425,54 @@ impl<'a> NotConnectedPeer<'a> { /// If there are enough slots available, switches the node to "connected" and returns `Ok`. If /// the slots are full, the node stays "not connected" and we return `Err`. /// - /// Note that priority nodes don't count towards the number of slots. + /// Non-slot-occupying nodes don't count towards the number of slots. pub fn try_accept_incoming(self) -> Result, NotConnectedPeer<'a>> { - if self.state.try_accept_incoming(&self.peer_id) { - Ok(ConnectedPeer { - state: self.state, - peer_id: self.peer_id, - }) + let is_no_slot_occupy = self.state.no_slot_nodes.contains(&*self.peer_id); + + // 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.state.num_in >= self.state.max_in && !is_no_slot_occupy { + return Err(self); + } + + if let Some(mut peer) = self.state.nodes.get_mut(&*self.peer_id) { + peer.connection_state = ConnectionState::In; + if !is_no_slot_occupy { + self.state.num_in += 1; + } } else { - Err(self) + debug_assert!(false, "State inconsistency: try_accept_incoming on an unknown node"); } + + Ok(ConnectedPeer { + state: self.state, + peer_id: self.peer_id, + }) } /// Returns the reputation value of the node. pub fn reputation(&self) -> i32 { - self.state.reputation(&self.peer_id) + self.state.nodes.get(&*self.peer_id).map_or(0, |p| p.reputation) } /// Sets the reputation of the peer. pub fn set_reputation(&mut self, value: i32) { - self.state.set_reputation(&self.peer_id, value) + if let Some(node) = self.state.nodes.get_mut(&*self.peer_id) { + node.reputation = value; + } else { + debug_assert!(false, "State inconsistency: set_reputation on an unknown node"); + } } /// Performs an arithmetic addition on the reputation score of that peer. /// /// In case of overflow, the value will be capped. - /// If the peer is unknown to us, we insert it and consider that it has a reputation of 0. pub fn add_reputation(&mut self, modifier: i32) { - self.state.add_reputation(&self.peer_id, modifier) + if let Some(node) = self.state.nodes.get_mut(&*self.peer_id) { + node.reputation = node.reputation.saturating_add(modifier); + } else { + debug_assert!(false, "State inconsistency: add_reputation on an unknown node"); + } } /// Un-discovers the peer. Removes it from the list. @@ -618,7 +526,7 @@ mod tests { #[test] fn full_slots_in() { - let mut peers_state = PeersState::new(1, 1, false); + let mut peers_state = PeersState::new(1, 1); let id1 = PeerId::random(); let id2 = PeerId::random(); @@ -632,14 +540,14 @@ mod tests { } #[test] - fn priority_node_doesnt_use_slot() { - let mut peers_state = PeersState::new(1, 1, false); + fn no_slot_node_doesnt_use_slot() { + let mut peers_state = PeersState::new(1, 1); let id1 = PeerId::random(); let id2 = PeerId::random(); - peers_state.set_priority_group("test", vec![id1.clone()].into_iter().collect()); - if let Peer::NotConnected(p) = peers_state.peer(&id1) { - assert!(p.try_accept_incoming().is_ok()); + peers_state.add_no_slot_node(id1.clone()); + if let Peer::Unknown(p) = peers_state.peer(&id1) { + assert!(p.discover().try_accept_incoming().is_ok()); } else { panic!() } if let Peer::Unknown(e) = peers_state.peer(&id2) { @@ -649,7 +557,7 @@ mod tests { #[test] fn disconnecting_frees_slot() { - let mut peers_state = PeersState::new(1, 1, false); + let mut peers_state = PeersState::new(1, 1); let id1 = PeerId::random(); let id2 = PeerId::random(); @@ -659,28 +567,9 @@ mod tests { assert!(peers_state.peer(&id2).into_not_connected().unwrap().try_accept_incoming().is_ok()); } - #[test] - fn priority_not_connected_peer() { - let mut peers_state = PeersState::new(25, 25, false); - let id1 = PeerId::random(); - let id2 = PeerId::random(); - - assert!(peers_state.priority_not_connected_peer().is_none()); - peers_state.peer(&id1).into_unknown().unwrap().discover(); - peers_state.peer(&id2).into_unknown().unwrap().discover(); - - assert!(peers_state.priority_not_connected_peer().is_none()); - peers_state.set_priority_group("test", vec![id1.clone()].into_iter().collect()); - assert!(peers_state.priority_not_connected_peer().is_some()); - peers_state.set_priority_group("test", vec![id2.clone(), id2.clone()].into_iter().collect()); - assert!(peers_state.priority_not_connected_peer().is_some()); - peers_state.set_priority_group("test", vec![].into_iter().collect()); - assert!(peers_state.priority_not_connected_peer().is_none()); - } - #[test] fn highest_not_connected_peer() { - let mut peers_state = PeersState::new(25, 25, false); + let mut peers_state = PeersState::new(25, 25); let id1 = PeerId::random(); let id2 = PeerId::random(); @@ -700,87 +589,11 @@ mod tests { } #[test] - fn disconnect_priority_doesnt_panic() { - let mut peers_state = PeersState::new(1, 1, false); + fn disconnect_no_slot_doesnt_panic() { + let mut peers_state = PeersState::new(1, 1); 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(); + peers_state.add_no_slot_node(id.clone()); + let peer = peers_state.peer(&id).into_unknown().unwrap().discover().try_outgoing().unwrap(); peer.disconnect(); } - - #[test] - fn multiple_priority_groups_slot_count() { - let mut peers_state = PeersState::new(1, 1, false); - let id = PeerId::random(); - - if let Peer::Unknown(p) = peers_state.peer(&id) { - assert!(p.discover().try_accept_incoming().is_ok()); - } else { panic!() } - - assert_eq!(peers_state.num_in, 1); - peers_state.set_priority_group("test1", vec![id.clone()].into_iter().collect()); - assert_eq!(peers_state.num_in, 0); - peers_state.set_priority_group("test2", vec![id.clone()].into_iter().collect()); - assert_eq!(peers_state.num_in, 0); - peers_state.set_priority_group("test1", vec![].into_iter().collect()); - assert_eq!(peers_state.num_in, 0); - 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/client/peerset/tests/fuzz.rs b/client/peerset/tests/fuzz.rs index 44477cec6589dbf2b6ce5922ae4ac3217fe9e973..6fa29e3d834cfcdaa0b035e03849432e20e7b3f3 100644 --- a/client/peerset/tests/fuzz.rs +++ b/client/peerset/tests/fuzz.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use futures::prelude::*; use libp2p::PeerId; @@ -44,13 +46,13 @@ fn test_once() { id }).collect(), priority_groups: { - let list = (0 .. Uniform::new_inclusive(0, 2).sample(&mut rng)).map(|_| { + let nodes = (0 .. Uniform::new_inclusive(0, 2).sample(&mut rng)).map(|_| { let id = PeerId::random(); known_nodes.insert(id.clone()); reserved_nodes.insert(id.clone()); id }).collect(); - vec![("reserved".to_owned(), list)] + vec![("foo".to_string(), nodes)] }, reserved_only: Uniform::new_inclusive(0, 10).sample(&mut rng) == 0, in_peers: Uniform::new_inclusive(0, 25).sample(&mut rng), diff --git a/client/proposer-metrics/Cargo.toml b/client/proposer-metrics/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..b10336f340c2af37a6c6303084d9058f94dd254f --- /dev/null +++ b/client/proposer-metrics/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "sc-proposer-metrics" +version = "0.8.0-rc4" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +description = "Basic metrics for block production." + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +log = "0.4.8" +prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.8.0-rc4"} diff --git a/client/proposer-metrics/src/lib.rs b/client/proposer-metrics/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..5cb749f4a260aa1964e230cb8edb3dd9515f595c --- /dev/null +++ b/client/proposer-metrics/src/lib.rs @@ -0,0 +1,67 @@ +// Copyright 2020 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 . + +//! Prometheus basic proposer metrics. + +use prometheus_endpoint::{register, PrometheusError, Registry, Histogram, HistogramOpts, Gauge, U64}; + +/// Optional shareable link to basic authorship metrics. +#[derive(Clone, Default)] +pub struct MetricsLink(Option); + +impl MetricsLink { + pub fn new(registry: Option<&Registry>) -> Self { + Self( + registry.and_then(|registry| + Metrics::register(registry) + .map_err(|err| log::warn!("Failed to register proposer prometheus metrics: {}", err)) + .ok() + ) + ) + } + + pub fn report(&self, do_this: impl FnOnce(&Metrics) -> O) -> Option { + Some(do_this(self.0.as_ref()?)) + } +} + +/// Authorship metrics. +#[derive(Clone)] +pub struct Metrics { + pub block_constructed: Histogram, + pub number_of_transactions: Gauge, +} + +impl Metrics { + pub fn register(registry: &Registry) -> Result { + Ok(Self { + block_constructed: register( + Histogram::with_opts(HistogramOpts::new( + "proposer_block_constructed", + "Histogram of time taken to construct new block", + ))?, + registry, + )?, + number_of_transactions: register( + Gauge::new( + "proposer_number_of_transactions", + "Number of transactions included in block", + )?, + registry, + )?, + }) + } +} diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index c5043b5b0782b72d00e0f9940d0f6e87f9963c9c..a991cf9afa1ab5983ad5bc26f963a901cf8afeed 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -1,30 +1,31 @@ [package] name = "sc-rpc-api" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate RPC interfaces." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0" } +codec = { package = "parity-scale-codec", version = "1.3.1" } derive_more = "0.99.2" futures = { version = "0.3.1", features = ["compat"] } -jsonrpc-core = "14.0.3" -jsonrpc-core-client = "14.0.5" -jsonrpc-derive = "14.0.3" -jsonrpc-pubsub = "14.0.3" +jsonrpc-core = "14.2.0" +jsonrpc-core-client = "14.2.0" +jsonrpc-derive = "14.2.1" +jsonrpc-pubsub = "14.2.0" log = "0.4.8" parking_lot = "0.10.0" -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -sp-version = { version = "2.0.0-alpha.5", path = "../../primitives/version" } -sp-runtime = { path = "../../primitives/runtime" , version = "2.0.0-alpha.5"} +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +sp-version = { version = "2.0.0-rc4", path = "../../primitives/version" } +sp-runtime = { path = "../../primitives/runtime" , version = "2.0.0-rc4"} +sp-chain-spec = { path = "../../primitives/chain-spec" , version = "2.0.0-rc4"} serde = { version = "1.0.101", features = ["derive"] } serde_json = "1.0.41" -sp-transaction-pool = { version = "2.0.0-alpha.5", path = "../../primitives/transaction-pool" } -sp-rpc = { version = "2.0.0-alpha.5", path = "../../primitives/rpc" } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +sp-transaction-pool = { version = "2.0.0-rc4", path = "../../primitives/transaction-pool" } +sp-rpc = { version = "2.0.0-rc4", path = "../../primitives/rpc" } diff --git a/client/rpc-api/src/author/error.rs b/client/rpc-api/src/author/error.rs index f1b56910086b5cb671689d612d9d2062d4722141..69c036be95fe085bcefeb1f38b8edbe594facaad 100644 --- a/client/rpc-api/src/author/error.rs +++ b/client/rpc-api/src/author/error.rs @@ -1,23 +1,26 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Authoring RPC module errors. use crate::errors; use jsonrpc_core as rpc; +use sp_runtime::transaction_validity::InvalidTransaction; /// Author RPC Result type. pub type Result = std::result::Result; @@ -57,6 +60,8 @@ pub enum Error { /// Invalid session keys encoding. #[display(fmt="Session keys are not encoded correctly")] InvalidSessionKeys, + /// Call to an unsafe RPC was denied. + UnsafeRpcCalled(crate::policy::UnsafeRpcError), } impl std::error::Error for Error { @@ -65,6 +70,7 @@ impl std::error::Error for Error { Error::Client(ref err) => Some(&**err), Error::Pool(ref err) => Some(err), Error::Verification(ref err) => Some(&**err), + Error::UnsafeRpcCalled(ref err) => Some(err), _ => None, } } @@ -109,10 +115,18 @@ impl From for rpc::Error { message: format!("Verification Error: {}", e).into(), data: Some(format!("{:?}", e).into()), }, - Error::Pool(PoolError::InvalidTransaction(e)) => rpc::Error { + Error::Pool(PoolError::InvalidTransaction(InvalidTransaction::Custom(e))) => rpc::Error { code: rpc::ErrorCode::ServerError(POOL_INVALID_TX), message: "Invalid Transaction".into(), - data: serde_json::to_value(e).ok(), + data: Some(format!("Custom error: {}", e).into()), + }, + Error::Pool(PoolError::InvalidTransaction(e)) => { + let msg: &str = e.into(); + rpc::Error { + code: rpc::ErrorCode::ServerError(POOL_INVALID_TX), + message: "Invalid Transaction".into(), + data: Some(msg.into()), + } }, Error::Pool(PoolError::UnknownTransaction(e)) => rpc::Error { code: rpc::ErrorCode::ServerError(POOL_UNKNOWN_VALIDITY), @@ -152,6 +166,7 @@ impl From for rpc::Error { request to insert the key successfully.".into() ), }, + Error::UnsafeRpcCalled(e) => e.into(), e => errors::internal(e), } } diff --git a/client/rpc-api/src/author/mod.rs b/client/rpc-api/src/author/mod.rs index 49c4c996fa9e1705fa4344bcce708ecf66d5b45d..29f5b1d26e84cb9c8644292da26c74e07dd23a39 100644 --- a/client/rpc-api/src/author/mod.rs +++ b/client/rpc-api/src/author/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Substrate block-author/full-node API. diff --git a/client/rpc-api/src/chain/error.rs b/client/rpc-api/src/chain/error.rs index ffa4d82bdff890b923ad51b22ff46ccb5efdee58..fd7bd0a43d778bf2a03be96baa5960e15f3dbd47 100644 --- a/client/rpc-api/src/chain/error.rs +++ b/client/rpc-api/src/chain/error.rs @@ -1,19 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . - +// along with this program. If not, see . //! Error helpers for Chain RPC module. diff --git a/client/rpc-api/src/chain/mod.rs b/client/rpc-api/src/chain/mod.rs index 2ab3851d37663a328e37b4f1d8998d103905d9f3..753ac5617a29d70380e3502d95a2145af8a926a9 100644 --- a/client/rpc-api/src/chain/mod.rs +++ b/client/rpc-api/src/chain/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Substrate blockchain API. @@ -47,7 +49,7 @@ pub trait ChainApi { #[rpc(name = "chain_getBlockHash", alias("chain_getHead"))] fn block_hash( &self, - hash: Option>>, + hash: Option>, ) -> Result>>; /// Get hash of the last finalized block in the canon chain. diff --git a/client/rpc-api/src/child_state/mod.rs b/client/rpc-api/src/child_state/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..d956a7554f8ee798d2fa84c777ae33b591f257ce --- /dev/null +++ b/client/rpc-api/src/child_state/mod.rs @@ -0,0 +1,71 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Substrate state API. + +use jsonrpc_derive::rpc; +use sp_core::storage::{StorageKey, PrefixedStorageKey, StorageData}; +use crate::state::error::FutureResult; + +pub use self::gen_client::Client as ChildStateClient; + +/// Substrate child state API +/// +/// Note that all `PrefixedStorageKey` are desierialized +/// from json and not guaranted valid. +#[rpc] +pub trait ChildStateApi { + /// RPC Metadata + type Metadata; + + /// Returns the keys with prefix from a child storage, leave empty to get all the keys + #[rpc(name = "childstate_getKeys")] + fn storage_keys( + &self, + child_storage_key: PrefixedStorageKey, + prefix: StorageKey, + hash: Option + ) -> FutureResult>; + + /// Returns a child storage entry at a specific block's state. + #[rpc(name = "childstate_getStorage")] + fn storage( + &self, + child_storage_key: PrefixedStorageKey, + key: StorageKey, + hash: Option + ) -> FutureResult>; + + /// Returns the hash of a child storage entry at a block's state. + #[rpc(name = "childstate_getStorageHash")] + fn storage_hash( + &self, + child_storage_key: PrefixedStorageKey, + key: StorageKey, + hash: Option + ) -> FutureResult>; + + /// Returns the size of a child storage entry at a block's state. + #[rpc(name = "childstate_getStorageSize")] + fn storage_size( + &self, + child_storage_key: PrefixedStorageKey, + key: StorageKey, + hash: Option + ) -> FutureResult>; +} diff --git a/client/rpc-api/src/errors.rs b/client/rpc-api/src/errors.rs index b75c34ead3806a7a0be3bb8104c4a30cd961138e..4e1a5b10fc5128fbb3e36dfb788a23c0575e965d 100644 --- a/client/rpc-api/src/errors.rs +++ b/client/rpc-api/src/errors.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use log::warn; diff --git a/client/rpc-api/src/helpers.rs b/client/rpc-api/src/helpers.rs index 912a5664b3c2fb9a1d48747fb46036ac02057b08..025fef1102c492adfb142a837d7e2f5e6a262e11 100644 --- a/client/rpc-api/src/helpers.rs +++ b/client/rpc-api/src/helpers.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use jsonrpc_core::futures::prelude::*; use futures::{channel::oneshot, compat::Compat}; diff --git a/client/rpc-api/src/lib.rs b/client/rpc-api/src/lib.rs index 8ad2d94bfd271ea0732ba811f2285e3f585b1554..cd2608dda92be9bf9fed546e3a3ffaca27005ec9 100644 --- a/client/rpc-api/src/lib.rs +++ b/client/rpc-api/src/lib.rs @@ -22,14 +22,15 @@ mod errors; mod helpers; -mod subscriptions; +mod policy; pub use jsonrpc_core::IoHandlerExtension as RpcExtension; -pub use subscriptions::{Subscriptions, TaskExecutor}; pub use helpers::Receiver; +pub use policy::DenyUnsafe; pub mod author; pub mod chain; pub mod offchain; pub mod state; +pub mod child_state; pub mod system; diff --git a/client/rpc-api/src/offchain/error.rs b/client/rpc-api/src/offchain/error.rs index c28a2a2f3911d7e5cd9bedc9e0e84cb60905d6af..ea5223f1ce7f935aefa8b6629ee2e82eebb48c13 100644 --- a/client/rpc-api/src/offchain/error.rs +++ b/client/rpc-api/src/offchain/error.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Offchain RPC errors. @@ -27,11 +29,16 @@ pub enum Error { /// Unavailable storage kind error. #[display(fmt="This storage kind is not available yet.")] UnavailableStorageKind, + /// Call to an unsafe RPC was denied. + UnsafeRpcCalled(crate::policy::UnsafeRpcError), } impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - None + match self { + Self::UnsafeRpcCalled(err) => Some(err), + _ => None, + } } } @@ -46,6 +53,7 @@ impl From for rpc::Error { message: "This storage kind is not available yet" .into(), data: None, }, + Error::UnsafeRpcCalled(e) => e.into(), } } } diff --git a/client/rpc-api/src/offchain/mod.rs b/client/rpc-api/src/offchain/mod.rs index bbe466ff5994d450164c47e005e0266e83e52440..427b6a1cc017bfeb09e52a43e14c14fa6ddf8669 100644 --- a/client/rpc-api/src/offchain/mod.rs +++ b/client/rpc-api/src/offchain/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Substrate offchain API. diff --git a/client/rpc-api/src/policy.rs b/client/rpc-api/src/policy.rs new file mode 100644 index 0000000000000000000000000000000000000000..141dcfbc415f8294d6f140db7ce74012afa200ac --- /dev/null +++ b/client/rpc-api/src/policy.rs @@ -0,0 +1,62 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Policy-related types. +//! +//! Contains a `DenyUnsafe` type that can be used to deny potentially unsafe +//! RPC when accessed externally. + +use jsonrpc_core as rpc; + +/// Signifies whether a potentially unsafe RPC should be denied. +#[derive(Clone, Copy, Debug)] +pub enum DenyUnsafe { + /// Denies only potentially unsafe RPCs. + Yes, + /// Allows calling every RPCs. + No, +} + +impl DenyUnsafe { + /// Returns `Ok(())` if the RPCs considered unsafe are safe to call, + /// otherwise returns `Err(UnsafeRpcError)`. + pub fn check_if_safe(self) -> Result<(), UnsafeRpcError> { + match self { + DenyUnsafe::Yes => Err(UnsafeRpcError), + DenyUnsafe::No => Ok(()), + } + } +} + +/// Signifies whether an RPC considered unsafe is denied to be called externally. +#[derive(Debug)] +pub struct UnsafeRpcError; + +impl std::fmt::Display for UnsafeRpcError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "RPC call is unsafe to be called externally") + } +} + +impl std::error::Error for UnsafeRpcError {} + +impl From for rpc::Error { + fn from(_: UnsafeRpcError) -> rpc::Error { + rpc::Error::method_not_found() + } +} diff --git a/client/rpc-api/src/state/error.rs b/client/rpc-api/src/state/error.rs index c9c2cf4e454d403dd63baaf383d6e85467996306..2fcca3c343f09efdd2acb1ce767cb2f80a80e5bd 100644 --- a/client/rpc-api/src/state/error.rs +++ b/client/rpc-api/src/state/error.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! State RPC errors. diff --git a/client/rpc-api/src/state/helpers.rs b/client/rpc-api/src/state/helpers.rs new file mode 100644 index 0000000000000000000000000000000000000000..0d176ea67f35be0449bf8bb63c49401260e39070 --- /dev/null +++ b/client/rpc-api/src/state/helpers.rs @@ -0,0 +1,32 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Substrate state API helpers. + +use sp_core::Bytes; +use serde::{Serialize, Deserialize}; + +/// ReadProof struct returned by the RPC +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ReadProof { + /// Block hash used to generate the proof + pub at: Hash, + /// A proof used to prove that storage entries are included in the storage trie + pub proof: Vec, +} diff --git a/client/rpc-api/src/state/mod.rs b/client/rpc-api/src/state/mod.rs index d29e46a4b5637cf85d0745d59a73b0ad69afde7c..1bfbb4786e677bb2eb89cb2b51346f9ae4d56890 100644 --- a/client/rpc-api/src/state/mod.rs +++ b/client/rpc-api/src/state/mod.rs @@ -1,22 +1,25 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Substrate state API. pub mod error; +pub mod helpers; use jsonrpc_core::Result as RpcResult; use jsonrpc_core::futures::Future; @@ -28,6 +31,7 @@ use sp_version::RuntimeVersion; use self::error::FutureResult; pub use self::gen_client::Client as StateClient; +pub use self::helpers::ReadProof; /// Substrate state API #[rpc] @@ -72,50 +76,6 @@ pub trait StateApi { #[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, - child_info: StorageKey, - child_type: u32, - 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, - child_info: StorageKey, - child_type: u32, - 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, - child_info: StorageKey, - child_type: u32, - 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, - child_info: StorageKey, - child_type: u32, - key: StorageKey, - hash: Option - ) -> FutureResult>; - /// Returns the runtime metadata as an opaque blob. #[rpc(name = "state_getMetadata")] fn metadata(&self, hash: Option) -> FutureResult; @@ -144,6 +104,10 @@ pub trait StateApi { at: Option, ) -> FutureResult>>; + /// Returns proof of storage entries at a specific block's state. + #[rpc(name = "state_getReadProof")] + fn read_proof(&self, keys: Vec, hash: Option) -> FutureResult>; + /// New runtime version subscription #[pubsub( subscription = "state_runtimeVersion", diff --git a/client/rpc-api/src/subscriptions.rs b/client/rpc-api/src/subscriptions.rs deleted file mode 100644 index 54881bad5123bfb9c98c0b716f7b1b514bab2d40..0000000000000000000000000000000000000000 --- a/client/rpc-api/src/subscriptions.rs +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2017-2020 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::HashMap; -use std::sync::{Arc, atomic::{self, AtomicUsize}}; - -use log::{error, warn}; -use jsonrpc_pubsub::{SubscriptionId, typed::{Sink, Subscriber}}; -use parking_lot::Mutex; -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 { - next_id: Arc, -} -impl Default for IdProvider { - fn default() -> Self { - IdProvider { - next_id: Arc::new(AtomicUsize::new(1)), - } - } -} - -impl IdProvider { - /// Returns next id for the subscription. - pub fn next_id(&self) -> Id { - self.next_id.fetch_add(1, atomic::Ordering::AcqRel) as u64 - } -} - -/// Subscriptions manager. -/// -/// Takes care of assigning unique subscription ids and -/// driving the sinks into completion. -#[derive(Clone)] -pub struct Subscriptions { - next_id: IdProvider, - active_subscriptions: Arc>>>, - executor: TaskExecutor, -} - -impl Subscriptions { - /// Creates new `Subscriptions` object. - pub fn new(executor: TaskExecutor) -> Self { - Subscriptions { - next_id: Default::default(), - active_subscriptions: Default::default(), - executor, - } - } - - /// Borrows the internal task executor. - /// - /// This can be used to spawn additional tasks on the underlying 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 by the underlying event loop - /// or will be cancelled in case #cancel is invoked. - 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(); - 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() - .select(rx.map_err(|e| warn!("Error timeing out: {:?}", e))) - .then(|_| Ok(())); - - self.active_subscriptions.lock().insert(id, tx); - if self.executor.execute(Box::new(future)).is_err() { - error!("Failed to spawn RPC subscription task"); - } - } - - subscription_id - } - - /// Cancel subscription. - /// - /// Returns true if subscription existed or false otherwise. - pub fn cancel(&self, id: SubscriptionId) -> bool { - if let SubscriptionId::Number(id) = id { - if let Some(tx) = self.active_subscriptions.lock().remove(&id) { - let _ = tx.send(()); - return true; - } - } - false - } -} diff --git a/client/rpc-api/src/system/error.rs b/client/rpc-api/src/system/error.rs index fbb4e44bcb635f0bdb486f0b581068e1d342c061..4897aa485cbe47591b787e771fda59543d3644c4 100644 --- a/client/rpc-api/src/system/error.rs +++ b/client/rpc-api/src/system/error.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! System RPC module errors. diff --git a/client/rpc-api/src/system/helpers.rs b/client/rpc-api/src/system/helpers.rs index 80718cf487c8999df8f14c26a40673d41c57723a..5dbe93543d8e5313a617a91ccfd3fa919ec661ee 100644 --- a/client/rpc-api/src/system/helpers.rs +++ b/client/rpc-api/src/system/helpers.rs @@ -1,27 +1,26 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Substrate system API helpers. use std::fmt; use serde::{Serialize, Deserialize}; -use serde_json::{Value, map::Map}; - -/// Node properties -pub type Properties = Map; +use sp_chain_spec::{Properties, ChainType}; /// Running node's static details. #[derive(Clone, Debug)] @@ -34,6 +33,8 @@ pub struct SystemInfo { pub chain_name: String, /// A custom set of properties defined in the chain spec. pub properties: Properties, + /// The type of this chain. + pub chain_type: ChainType, } /// Health struct returned by the RPC diff --git a/client/rpc-api/src/system/mod.rs b/client/rpc-api/src/system/mod.rs index f12a11e0b36dd7edf14c80e5a8d99e3f995f8b0e..a7b746ee1b114afa525b5c077d22bf34ec1d5f54 100644 --- a/client/rpc-api/src/system/mod.rs +++ b/client/rpc-api/src/system/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Substrate system API. @@ -25,7 +27,7 @@ use futures::{future::BoxFuture, compat::Compat}; use self::error::Result as SystemResult; -pub use self::helpers::{Properties, SystemInfo, Health, PeerInfo, NodeRole}; +pub use self::helpers::{SystemInfo, Health, PeerInfo, NodeRole}; pub use self::gen_client::Client as SystemClient; /// Substrate system RPC API @@ -39,13 +41,17 @@ pub trait SystemApi { #[rpc(name = "system_version")] fn system_version(&self) -> SystemResult; - /// Get the chain's type. Given as a string identifier. + /// Get the chain's name. Given as a string identifier. #[rpc(name = "system_chain")] fn system_chain(&self) -> SystemResult; + /// Get the chain's type. + #[rpc(name = "system_chainType")] + fn system_type(&self) -> SystemResult; + /// Get a custom set of properties as a JSON object, defined in the chain spec. #[rpc(name = "system_properties")] - fn system_properties(&self) -> SystemResult; + fn system_properties(&self) -> SystemResult; /// Return health status of the node. /// @@ -55,16 +61,29 @@ pub trait SystemApi { #[rpc(name = "system_health", returns = "Health")] fn system_health(&self) -> Receiver; + /// Returns the base58-encoded PeerId of the node. + #[rpc(name = "system_localPeerId", returns = "String")] + fn system_local_peer_id(&self) -> Receiver; + + /// Returns the multiaddresses that the local node is listening on + /// + /// The addresses include a trailing `/p2p/` with the local PeerId, and are thus suitable to + /// be passed to `system_addReservedPeer` or as a bootnode address for example. + #[rpc(name = "system_localListenAddresses", returns = "Vec")] + fn system_local_listen_addresses(&self) -> Receiver>; + /// Returns currently connected peers #[rpc(name = "system_peers", returns = "Vec>")] - fn system_peers(&self) -> Receiver>>; + fn system_peers(&self) + -> Compat>>>>; /// 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; + fn system_network_state(&self) + -> Compat>>; /// Adds a reserved peer. Returns the empty string or an error. The string /// parameter should encode a `p2p` multiaddr. diff --git a/client/rpc-servers/Cargo.toml b/client/rpc-servers/Cargo.toml index c834d7dbf7396b89a6a72ccaaf7feca3059e7507..155729817da32e69ddfd6b84552d729ddb16871d 100644 --- a/client/rpc-servers/Cargo.toml +++ b/client/rpc-servers/Cargo.toml @@ -1,24 +1,25 @@ [package] name = "sc-rpc-server" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate RPC servers." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -jsonrpc-core = "14.0.3" -pubsub = { package = "jsonrpc-pubsub", version = "14.0.3" } +jsonrpc-core = "14.2.0" +pubsub = { package = "jsonrpc-pubsub", version = "14.2.0" } log = "0.4.8" serde = "1.0.101" serde_json = "1.0.41" -sp-runtime = { version = "2.0.0-alpha.5", path = "../../primitives/runtime" } +sp-runtime = { version = "2.0.0-rc4", path = "../../primitives/runtime" } [target.'cfg(not(target_os = "unknown"))'.dependencies] -http = { package = "jsonrpc-http-server", version = "14.0.3" } -ws = { package = "jsonrpc-ws-server", version = "14.0.3" } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +http = { package = "jsonrpc-http-server", version = "14.2.0" } +ws = { package = "jsonrpc-ws-server", version = "14.2.0" } +ipc = { version = "14.2.0", package = "jsonrpc-ipc-server" } diff --git a/client/rpc-servers/src/lib.rs b/client/rpc-servers/src/lib.rs index 97fb10c15e4b5593ac247beb25563d29d7627648..1e476262acea8761e8a0e266189934b02ad0f20d 100644 --- a/client/rpc-servers/src/lib.rs +++ b/client/rpc-servers/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Substrate RPC servers. @@ -60,6 +62,8 @@ pub fn rpc_handler( mod inner { use super::*; + /// Type alias for ipc server + pub type IpcServer = ipc::Server; /// Type alias for http server pub type HttpServer = http::Server; /// Type alias for ws server @@ -87,6 +91,23 @@ mod inner { .start_http(addr) } + /// Start IPC server listening on given path. + /// + /// **Note**: Only available if `not(target_os = "unknown")`. + pub fn start_ipc( + addr: &str, + io: RpcHandler, + ) -> io::Result { + let builder = ipc::ServerBuilder::new(io); + #[cfg(target_os = "unix")] + builder.set_security_attributes({ + let security_attributes = ipc::SecurityAttributes::empty(); + security_attributes.set_mode(0o600)?; + security_attributes + }); + builder.start(addr) + } + /// Start WS server listening on given address. /// /// **Note**: Only available if `not(target_os = "unknown")`. diff --git a/client/rpc/Cargo.toml b/client/rpc/Cargo.toml index 7092959b83e9c450984b14b2394dd738ea440a2f..9568a4d44ffef117a0595663c3c57fd433be6af9 100644 --- a/client/rpc/Cargo.toml +++ b/client/rpc/Cargo.toml @@ -1,48 +1,49 @@ [package] name = "sc-rpc" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate Client RPC" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sc-rpc-api = { version = "0.8.0-alpha.5", path = "../rpc-api" } -sc-client-api = { version = "2.0.0-alpha.5", path = "../api" } -sc-client = { version = "0.8.0-alpha.5", path = "../" } -sp-api = { version = "2.0.0-alpha.5", path = "../../primitives/api" } -codec = { package = "parity-scale-codec", version = "1.3.0" } +sc-rpc-api = { version = "0.8.0-rc4", path = "../rpc-api" } +sc-client-api = { version = "2.0.0-rc4", path = "../api" } +sp-api = { version = "2.0.0-rc4", path = "../../primitives/api" } +codec = { package = "parity-scale-codec", version = "1.3.1" } futures = { version = "0.3.1", features = ["compat"] } -jsonrpc-pubsub = "14.0.3" +jsonrpc-pubsub = "14.2.0" log = "0.4.8" -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -rpc = { package = "jsonrpc-core", version = "14.0.3" } -sp-version = { version = "2.0.0-alpha.5", path = "../../primitives/version" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +rpc = { package = "jsonrpc-core", version = "14.2.0" } +sp-version = { version = "2.0.0-rc4", path = "../../primitives/version" } serde_json = "1.0.41" -sp-session = { version = "2.0.0-alpha.5", path = "../../primitives/session" } -sp-offchain = { version = "2.0.0-alpha.5", path = "../../primitives/offchain" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../primitives/runtime" } -sp-utils = { version = "2.0.0-alpha.5", path = "../../primitives/utils" } -sp-rpc = { version = "2.0.0-alpha.5", path = "../../primitives/rpc" } -sp-state-machine = { version = "0.8.0-alpha.5", path = "../../primitives/state-machine" } -sc-executor = { version = "0.8.0-alpha.5", path = "../executor" } -sc-block-builder = { version = "0.8.0-alpha.5", path = "../../client/block-builder" } -sc-keystore = { version = "2.0.0-alpha.5", path = "../keystore" } -sp-transaction-pool = { version = "2.0.0-alpha.5", path = "../../primitives/transaction-pool" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../primitives/blockchain" } +sp-session = { version = "2.0.0-rc4", path = "../../primitives/session" } +sp-offchain = { version = "2.0.0-rc4", path = "../../primitives/offchain" } +sp-runtime = { version = "2.0.0-rc4", path = "../../primitives/runtime" } +sp-utils = { version = "2.0.0-rc4", path = "../../primitives/utils" } +sp-rpc = { version = "2.0.0-rc4", path = "../../primitives/rpc" } +sp-state-machine = { version = "0.8.0-rc4", path = "../../primitives/state-machine" } +sp-chain-spec = { version = "2.0.0-rc4", path = "../../primitives/chain-spec" } +sc-executor = { version = "0.8.0-rc4", path = "../executor" } +sc-block-builder = { version = "0.8.0-rc4", path = "../../client/block-builder" } +sc-keystore = { version = "2.0.0-rc4", path = "../keystore" } +sp-transaction-pool = { version = "2.0.0-rc4", path = "../../primitives/transaction-pool" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../primitives/blockchain" } hash-db = { version = "0.15.2", default-features = false } parking_lot = "0.10.0" [dev-dependencies] assert_matches = "1.3.0" futures01 = { package = "futures", version = "0.1.29" } -sc-network = { version = "0.8.0-alpha.5", path = "../network" } -sp-io = { version = "2.0.0-alpha.5", path = "../../primitives/io" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../test-utils/runtime/client" } +sc-network = { version = "0.8.0-rc4", path = "../network" } +sp-io = { version = "2.0.0-rc4", path = "../../primitives/io" } +substrate-test-runtime-client = { version = "2.0.0-rc4", path = "../../test-utils/runtime/client" } tokio = "0.1.22" -sc-transaction-pool = { version = "2.0.0-alpha.5", path = "../transaction-pool" } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +sc-transaction-pool = { version = "2.0.0-rc4", path = "../transaction-pool" } +lazy_static = "1.4.0" diff --git a/client/rpc/src/author/mod.rs b/client/rpc/src/author/mod.rs index a3f23e8e1437a146932410d08ce6835b40907a6d..974c1b85e1b39816a9be584c6bfc56b10796c2c2 100644 --- a/client/rpc/src/author/mod.rs +++ b/client/rpc/src/author/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Substrate block-author/full-node API. @@ -30,8 +32,8 @@ use rpc::futures::{ }; use futures::{StreamExt as _, compat::Compat}; use futures::future::{ready, FutureExt, TryFutureExt}; -use sc_rpc_api::Subscriptions; -use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; +use sc_rpc_api::DenyUnsafe; +use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId, manager::SubscriptionManager}; use codec::{Encode, Decode}; use sp_core::{Bytes, traits::BareCryptoStorePtr}; use sp_api::ProvideRuntimeApi; @@ -53,9 +55,11 @@ pub struct Author { /// Transactions pool pool: Arc

, /// Subscriptions manager - subscriptions: Subscriptions, + subscriptions: SubscriptionManager, /// The key store. keystore: BareCryptoStorePtr, + /// Whether to deny unsafe calls + deny_unsafe: DenyUnsafe, } impl Author { @@ -63,19 +67,20 @@ impl Author { pub fn new( client: Arc, pool: Arc

, - subscriptions: Subscriptions, + subscriptions: SubscriptionManager, keystore: BareCryptoStorePtr, + deny_unsafe: DenyUnsafe, ) -> Self { Author { client, pool, subscriptions, keystore, + deny_unsafe, } } } - /// Currently we treat all RPC transactions as externals. /// /// Possibly in the future we could allow opt-in for special treatment @@ -97,6 +102,8 @@ impl AuthorApi, BlockHash

> for Author suri: String, public: Bytes, ) -> Result<()> { + self.deny_unsafe.check_if_safe()?; + let key_type = key_type.as_str().try_into().map_err(|_| Error::BadKeyType)?; let mut keystore = self.keystore.write(); keystore.insert_unknown(key_type, &suri, &public[..]) @@ -105,6 +112,8 @@ impl AuthorApi, BlockHash

> for Author } fn rotate_keys(&self) -> Result { + self.deny_unsafe.check_if_safe()?; + let best_block_hash = self.client.info().best_hash; self.client.runtime_api().generate_session_keys( &generic::BlockId::Hash(best_block_hash), @@ -113,6 +122,8 @@ impl AuthorApi, BlockHash

> for Author } fn has_session_keys(&self, session_keys: Bytes) -> Result { + self.deny_unsafe.check_if_safe()?; + let best_block_hash = self.client.info().best_hash; let keys = self.client.runtime_api().decode_session_keys( &generic::BlockId::Hash(best_block_hash), @@ -124,6 +135,8 @@ impl AuthorApi, BlockHash

> for Author } fn has_key(&self, public_key: Bytes, key_type: String) -> Result { + self.deny_unsafe.check_if_safe()?; + let key_type = key_type.as_str().try_into().map_err(|_| Error::BadKeyType)?; Ok(self.keystore.read().has_keys(&[(public_key.to_vec(), key_type)])) } @@ -151,6 +164,8 @@ impl AuthorApi, BlockHash

> for Author &self, bytes_or_hash: Vec>>, ) -> Result>> { + self.deny_unsafe.check_if_safe()?; + let hashes = bytes_or_hash.into_iter() .map(|x| match x { hash::ExtrinsicOrHash::Hash(h) => Ok(h), diff --git a/client/rpc/src/author/tests.rs b/client/rpc/src/author/tests.rs index 8b956c23a5e660cd685c9d6381395068decb4ebc..37edcbe263283ffaab2a638b5c129cee02a9921d 100644 --- a/client/rpc/src/author/tests.rs +++ b/client/rpc/src/author/tests.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use super::*; @@ -30,7 +32,7 @@ use substrate_test_runtime_client::{ DefaultTestClientBuilderExt, TestClientBuilderExt, Backend, Client, }; use sc_transaction_pool::{BasicPool, FullChainApi}; -use tokio::runtime; +use futures::{executor, compat::Future01CompatExt}; fn uxt(sender: AccountKeyring, nonce: u64) -> Extrinsic { let tx = Transfer { @@ -48,7 +50,6 @@ type FullTransactionPool = BasicPool< >; struct TestSetup { - pub runtime: runtime::Runtime, pub client: Arc>, pub keystore: BareCryptoStorePtr, pub pool: Arc, @@ -57,17 +58,18 @@ struct TestSetup { impl Default for TestSetup { fn default() -> Self { let keystore = KeyStore::new(); - let client = Arc::new( - substrate_test_runtime_client::TestClientBuilder::new() - .set_keystore(keystore.clone()) - .build() - ); - let pool = Arc::new(BasicPool::new( + let client_builder = substrate_test_runtime_client::TestClientBuilder::new(); + let client = Arc::new(client_builder.set_keystore(keystore.clone()).build()); + + let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let pool = BasicPool::new_full( Default::default(), - Arc::new(FullChainApi::new(client.clone())), - ).0); + Arc::new(FullChainApi::new(client.clone(), None)), + None, + spawner, + client.clone(), + ); TestSetup { - runtime: runtime::Runtime::new().expect("Failed to create runtime in test setup"), client, keystore, pool, @@ -80,8 +82,9 @@ impl TestSetup { Author { client: self.client.clone(), pool: self.pool.clone(), - subscriptions: Subscriptions::new(Arc::new(self.runtime.executor())), + subscriptions: SubscriptionManager::new(Arc::new(crate::testing::TaskExecutor)), keystore: self.keystore.clone(), + deny_unsafe: DenyUnsafe::No, } } } @@ -119,16 +122,26 @@ fn submit_rich_transaction_should_not_cause_error() { #[test] fn should_watch_extrinsic() { //given - let mut setup = TestSetup::default(); + let 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()); + p.watch_extrinsic( + Default::default(), + subscriber, + uxt(AccountKeyring::Alice, 0).encode().into(), + ); + + let id = executor::block_on(id_rx.compat()).unwrap().unwrap(); + assert_matches!(id, SubscriptionId::String(_)); + + let id = match id { + SubscriptionId::String(id) => id, + _ => unreachable!(), + }; - // then - assert_eq!(setup.runtime.block_on(id_rx), Ok(Ok(1.into()))); // check notifications let replacement = { let tx = Transfer { @@ -140,22 +153,29 @@ fn should_watch_extrinsic() { tx.into_signed_tx() }; 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 (res, data) = executor::block_on(data.into_future().compat()).unwrap(); + + let expected = Some(format!( + r#"{{"jsonrpc":"2.0","method":"test","params":{{"result":"ready","subscription":"{}"}}}}"#, + id, + )); + assert_eq!(res, expected); + let h = blake2_256(&replacement.encode()); - assert_eq!( - 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))) - ); + let expected = Some(format!( + r#"{{"jsonrpc":"2.0","method":"test","params":{{"result":{{"usurped":"0x{}"}},"subscription":"{}"}}}}"#, + HexDisplay::from(&h), + id, + )); + + let res = executor::block_on(data.into_future().compat()).unwrap().0; + assert_eq!(res, expected); } #[test] fn should_return_watch_validation_error() { //given - let mut setup = TestSetup::default(); + let setup = TestSetup::default(); let p = setup.author(); let (subscriber, id_rx, _data) = jsonrpc_pubsub::typed::Subscriber::new_test("test"); @@ -164,7 +184,7 @@ fn should_return_watch_validation_error() { p.watch_extrinsic(Default::default(), subscriber, uxt(AccountKeyring::Alice, 179).encode().into()); // then - let res = setup.runtime.block_on(id_rx).unwrap(); + let res = executor::block_on(id_rx.compat()).unwrap(); assert!(res.is_err(), "Expected the transaction to be rejected as invalid."); } diff --git a/client/rpc/src/chain/chain_full.rs b/client/rpc/src/chain/chain_full.rs index c1b062754bdac41eff2a2c3c04ad1375b09ce915..816dbba8664172a2cf467a5dc723386e689823d3 100644 --- a/client/rpc/src/chain/chain_full.rs +++ b/client/rpc/src/chain/chain_full.rs @@ -18,8 +18,8 @@ use std::sync::Arc; use rpc::futures::future::result; +use jsonrpc_pubsub::manager::SubscriptionManager; -use sc_rpc_api::Subscriptions; use sc_client_api::{BlockchainEvents, BlockBackend}; use sp_runtime::{generic::{BlockId, SignedBlock}, traits::{Block as BlockT}}; @@ -32,14 +32,14 @@ pub struct FullChain { /// Substrate client. client: Arc, /// Current subscriptions. - subscriptions: Subscriptions, + subscriptions: SubscriptionManager, /// phantom member to pin the block type _phantom: PhantomData, } impl FullChain { /// Create new Chain API RPC handler. - pub fn new(client: Arc, subscriptions: Subscriptions) -> Self { + pub fn new(client: Arc, subscriptions: SubscriptionManager) -> Self { Self { client, subscriptions, @@ -56,7 +56,7 @@ impl ChainBackend for FullChain whe &self.client } - fn subscriptions(&self) -> &Subscriptions { + fn subscriptions(&self) -> &SubscriptionManager { &self.subscriptions } diff --git a/client/rpc/src/chain/chain_light.rs b/client/rpc/src/chain/chain_light.rs index b258c8dd3bc2561f65e10c6045cb7d2c1762840e..8a4afbed71c165708fd5d4b0effca47abe6995f7 100644 --- a/client/rpc/src/chain/chain_light.rs +++ b/client/rpc/src/chain/chain_light.rs @@ -19,11 +19,9 @@ use std::sync::Arc; use futures::{future::ready, FutureExt, TryFutureExt}; use rpc::futures::future::{result, Future, Either}; +use jsonrpc_pubsub::manager::SubscriptionManager; -use sc_rpc_api::Subscriptions; -use sc_client::{ - light::{fetcher::{Fetcher, RemoteBodyRequest}, blockchain::RemoteBlockchain}, -}; +use sc_client_api::light::{Fetcher, RemoteBodyRequest, RemoteBlockchain}; use sp_runtime::{ generic::{BlockId, SignedBlock}, traits::{Block as BlockT}, @@ -39,7 +37,7 @@ pub struct LightChain { /// Substrate client. client: Arc, /// Current subscriptions. - subscriptions: Subscriptions, + subscriptions: SubscriptionManager, /// Remote blockchain reference remote_blockchain: Arc>, /// Remote fetcher reference. @@ -50,7 +48,7 @@ impl> LightChain { /// Create new Chain API RPC handler. pub fn new( client: Arc, - subscriptions: Subscriptions, + subscriptions: SubscriptionManager, remote_blockchain: Arc>, fetcher: Arc, ) -> Self { @@ -72,7 +70,7 @@ impl ChainBackend for LightChain &Subscriptions { + fn subscriptions(&self) -> &SubscriptionManager { &self.subscriptions } @@ -80,7 +78,7 @@ impl ChainBackend for LightChain. +// along with this program. If not, see . //! Substrate blockchain API. @@ -30,12 +32,8 @@ use rpc::{ futures::{stream, Future, Sink, Stream}, }; -use sc_rpc_api::Subscriptions; -use sc_client::{ - self, BlockchainEvents, - light::{fetcher::Fetcher, blockchain::RemoteBlockchain}, -}; -use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; +use sc_client_api::{BlockchainEvents, light::{Fetcher, RemoteBlockchain}}; +use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId, manager::SubscriptionManager}; use sp_rpc::{number::NumberOrHex, list::ListOrValue}; use sp_runtime::{ generic::{BlockId, SignedBlock}, @@ -58,7 +56,7 @@ trait ChainBackend: Send + Sync + 'static fn client(&self) -> &Arc; /// Get subscriptions reference. - fn subscriptions(&self) -> &Subscriptions; + fn subscriptions(&self) -> &SubscriptionManager; /// Tries to unwrap passed block hash, or uses best block hash otherwise. fn unwrap_or_best(&self, hash: Option) -> Block::Hash { @@ -77,17 +75,27 @@ trait ChainBackend: Send + Sync + 'static /// Get hash of the n-th block in the canon chain. /// /// By default returns latest block hash. - fn block_hash( - &self, - number: Option>>, - ) -> Result> { - Ok(match number { - None => Some(self.client().info().best_hash), - Some(num_or_hex) => self.client() - .header(BlockId::number(num_or_hex.to_number()?)) - .map_err(client_err)? - .map(|h| h.hash()), - }) + fn block_hash(&self, number: Option) -> Result> { + match number { + None => Ok(Some(self.client().info().best_hash)), + Some(num_or_hex) => { + use std::convert::TryInto; + + // FIXME <2329>: Database seems to limit the block number to u32 for no reason + let block_num: u32 = num_or_hex.try_into().map_err(|_| { + Error::from(format!( + "`{:?}` > u32::max_value(), the max block number is u32.", + num_or_hex + )) + })?; + let block_num = >::from(block_num); + Ok(self + .client() + .header(BlockId::number(block_num)) + .map_err(client_err)? + .map(|h| h.hash())) + } + } } /// Get hash of the last finalized block in the canon chain. @@ -178,7 +186,7 @@ trait ChainBackend: Send + Sync + 'static /// Create new state API that works on full node. pub fn new_full( client: Arc, - subscriptions: Subscriptions, + subscriptions: SubscriptionManager, ) -> Chain where Block: BlockT + 'static, @@ -192,7 +200,7 @@ pub fn new_full( /// Create new state API that works on light node. pub fn new_light>( client: Arc, - subscriptions: Subscriptions, + subscriptions: SubscriptionManager, remote_blockchain: Arc>, fetcher: Arc, ) -> Chain @@ -235,7 +243,7 @@ impl ChainApi, Block::Hash, Block::Header, Signe fn block_hash( &self, - number: Option>>> + number: Option>, ) -> Result>> { match number { None => self.backend.block_hash(None).map(ListOrValue::Value), @@ -280,7 +288,7 @@ impl ChainApi, Block::Hash, Block::Header, Signe /// Subscribe to new headers. fn subscribe_headers( client: &Arc, - subscriptions: &Subscriptions, + subscriptions: &SubscriptionManager, subscriber: Subscriber, best_block_hash: G, stream: F, diff --git a/client/rpc/src/chain/tests.rs b/client/rpc/src/chain/tests.rs index 68d904919b3d74faba6b8bb4add1f56776ab0e9c..b36fc4eab1d865f5a3c97e2d615d88cf33955274 100644 --- a/client/rpc/src/chain/tests.rs +++ b/client/rpc/src/chain/tests.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use super::*; use assert_matches::assert_matches; @@ -23,14 +25,13 @@ use substrate_test_runtime_client::{ }; use sp_rpc::list::ListOrValue; use sc_block_builder::BlockBuilderProvider; +use futures::{executor, compat::{Future01CompatExt, Stream01CompatExt}}; +use crate::testing::TaskExecutor; #[test] fn should_return_header() { - let core = tokio::runtime::Runtime::new().unwrap(); - let remote = core.executor(); - let client = Arc::new(substrate_test_runtime_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + let api = new_full(client.clone(), SubscriptionManager::new(Arc::new(TaskExecutor))); assert_matches!( api.header(Some(client.genesis_hash()).into()).wait(), @@ -61,11 +62,8 @@ fn should_return_header() { #[test] fn should_return_a_block() { - let core = tokio::runtime::Runtime::new().unwrap(); - let remote = core.executor(); - let mut client = Arc::new(substrate_test_runtime_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + let api = new_full(client.clone(), SubscriptionManager::new(Arc::new(TaskExecutor))); let block = client.new_block(Default::default()).unwrap().build().unwrap().block; let block_hash = block.hash(); @@ -115,11 +113,8 @@ fn should_return_a_block() { #[test] fn should_return_block_hash() { - let core = ::tokio::runtime::Runtime::new().unwrap(); - let remote = core.executor(); - let mut client = Arc::new(substrate_test_runtime_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + let api = new_full(client.clone(), SubscriptionManager::new(Arc::new(TaskExecutor))); assert_matches!( api.block_hash(None.into()), @@ -154,7 +149,7 @@ fn should_return_block_hash() { ); assert_matches!( - api.block_hash(Some(vec![0u64.into(), 1.into(), 2.into()].into())), + api.block_hash(Some(vec![0u64.into(), 1u64.into(), 2u64.into()].into())), Ok(ListOrValue::List(list)) if list == &[client.genesis_hash().into(), block.hash().into(), None] ); } @@ -162,11 +157,8 @@ fn should_return_block_hash() { #[test] fn should_return_finalized_hash() { - let core = ::tokio::runtime::Runtime::new().unwrap(); - let remote = core.executor(); - let mut client = Arc::new(substrate_test_runtime_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + let api = new_full(client.clone(), SubscriptionManager::new(Arc::new(TaskExecutor))); assert_matches!( api.finalized_head(), @@ -192,76 +184,79 @@ fn should_return_finalized_hash() { #[test] fn should_notify_about_latest_block() { - let mut core = ::tokio::runtime::Runtime::new().unwrap(); - let remote = core.executor(); let (subscriber, id, transport) = Subscriber::new_test("test"); { let mut client = Arc::new(substrate_test_runtime_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + let api = new_full(client.clone(), SubscriptionManager::new(Arc::new(TaskExecutor))); api.subscribe_all_heads(Default::default(), subscriber); // assert id assigned - assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); + assert!(matches!( + executor::block_on(id.compat()), + Ok(Ok(SubscriptionId::String(_))) + )); let block = client.new_block(Default::default()).unwrap().build().unwrap().block; client.import(BlockOrigin::Own, block).unwrap(); } // assert initial head sent. - let (notification, next) = core.block_on(transport.into_future()).unwrap(); + let (notification, next) = executor::block_on(transport.into_future().compat()).unwrap(); assert!(notification.is_some()); // assert notification sent to transport - let (notification, next) = core.block_on(next.into_future()).unwrap(); + let (notification, next) = executor::block_on(next.into_future().compat()).unwrap(); assert!(notification.is_some()); // no more notifications on this channel - assert_eq!(core.block_on(next.into_future()).unwrap().0, None); + assert_eq!(executor::block_on(next.into_future().compat()).unwrap().0, None); } #[test] fn should_notify_about_best_block() { - let mut core = ::tokio::runtime::Runtime::new().unwrap(); - let remote = core.executor(); let (subscriber, id, transport) = Subscriber::new_test("test"); { let mut client = Arc::new(substrate_test_runtime_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + let api = new_full(client.clone(), SubscriptionManager::new(Arc::new(TaskExecutor))); api.subscribe_new_heads(Default::default(), subscriber); // assert id assigned - assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); + assert!(matches!( + executor::block_on(id.compat()), + Ok(Ok(SubscriptionId::String(_))) + )); let block = client.new_block(Default::default()).unwrap().build().unwrap().block; client.import(BlockOrigin::Own, block).unwrap(); } // assert initial head sent. - let (notification, next) = core.block_on(transport.into_future()).unwrap(); + let (notification, next) = executor::block_on(transport.into_future().compat()).unwrap(); assert!(notification.is_some()); // assert notification sent to transport - let (notification, next) = core.block_on(next.into_future()).unwrap(); + let (notification, next) = executor::block_on(next.into_future().compat()).unwrap(); assert!(notification.is_some()); // no more notifications on this channel - assert_eq!(core.block_on(next.into_future()).unwrap().0, None); + assert_eq!(executor::block_on(Stream01CompatExt::compat(next).into_future()).0, None); } #[test] fn should_notify_about_finalized_block() { - let mut core = ::tokio::runtime::Runtime::new().unwrap(); - let remote = core.executor(); let (subscriber, id, transport) = Subscriber::new_test("test"); { let mut client = Arc::new(substrate_test_runtime_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + let api = new_full(client.clone(), SubscriptionManager::new(Arc::new(TaskExecutor))); api.subscribe_finalized_heads(Default::default(), subscriber); // assert id assigned - assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); + assert!(matches!( + executor::block_on(id.compat()), + Ok(Ok(SubscriptionId::String(_))) + )); let block = client.new_block(Default::default()).unwrap().build().unwrap().block; client.import(BlockOrigin::Own, block).unwrap(); @@ -269,11 +264,11 @@ fn should_notify_about_finalized_block() { } // assert initial head sent. - let (notification, next) = core.block_on(transport.into_future()).unwrap(); + let (notification, next) = executor::block_on(transport.into_future().compat()).unwrap(); assert!(notification.is_some()); // assert notification sent to transport - let (notification, next) = core.block_on(next.into_future()).unwrap(); + let (notification, next) = executor::block_on(next.into_future().compat()).unwrap(); assert!(notification.is_some()); // no more notifications on this channel - assert_eq!(core.block_on(next.into_future()).unwrap().0, None); + assert_eq!(executor::block_on(next.into_future().compat()).unwrap().0, None); } diff --git a/client/rpc/src/lib.rs b/client/rpc/src/lib.rs index ea65785c20a87c827220bbc6affecafe7ecb9937..53a63b449c87e8b3382e3f7b3230539c6a749d15 100644 --- a/client/rpc/src/lib.rs +++ b/client/rpc/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Substrate RPC implementation. //! @@ -22,7 +24,7 @@ mod metadata; -pub use sc_rpc_api::Subscriptions; +pub use sc_rpc_api::DenyUnsafe; pub use self::metadata::Metadata; pub use rpc::IoHandlerExtension as RpcExtension; @@ -31,3 +33,5 @@ pub mod chain; pub mod offchain; pub mod state; pub mod system; +#[cfg(test)] +mod testing; diff --git a/client/rpc/src/metadata.rs b/client/rpc/src/metadata.rs index d35653f8e6278b966cee9e4933577b07075ba786..0416b07a6797bb21501bb71f343106efa595087f 100644 --- a/client/rpc/src/metadata.rs +++ b/client/rpc/src/metadata.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! RPC Metadata use std::sync::Arc; diff --git a/client/rpc/src/offchain/mod.rs b/client/rpc/src/offchain/mod.rs index 61984d4845a7ab68852dd7da0cef214a37758515..f8d2bb6a50f9c653491dc0536e019ad99ce20aa1 100644 --- a/client/rpc/src/offchain/mod.rs +++ b/client/rpc/src/offchain/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Substrate offchain API. @@ -21,6 +23,7 @@ mod tests; /// Re-export the API for backward compatibility. pub use sc_rpc_api::offchain::*; +use sc_rpc_api::DenyUnsafe; use self::error::{Error, Result}; use sp_core::{ Bytes, @@ -34,13 +37,15 @@ use std::sync::Arc; pub struct Offchain { /// Offchain storage storage: Arc>, + deny_unsafe: DenyUnsafe, } impl Offchain { /// Create new instance of Offchain API. - pub fn new(storage: T) -> Self { + pub fn new(storage: T, deny_unsafe: DenyUnsafe) -> Self { Offchain { storage: Arc::new(RwLock::new(storage)), + deny_unsafe, } } } @@ -48,6 +53,8 @@ impl Offchain { impl OffchainApi for Offchain { /// Set offchain local storage under given key and prefix. fn set_local_storage(&self, kind: StorageKind, key: Bytes, value: Bytes) -> Result<()> { + self.deny_unsafe.check_if_safe()?; + let prefix = match kind { StorageKind::PERSISTENT => sp_offchain::STORAGE_PREFIX, StorageKind::LOCAL => return Err(Error::UnavailableStorageKind), @@ -58,6 +65,8 @@ impl OffchainApi for Offchain { /// Get offchain local storage under given key and prefix. fn get_local_storage(&self, kind: StorageKind, key: Bytes) -> Result> { + self.deny_unsafe.check_if_safe()?; + let prefix = match kind { StorageKind::PERSISTENT => sp_offchain::STORAGE_PREFIX, StorageKind::LOCAL => return Err(Error::UnavailableStorageKind), diff --git a/client/rpc/src/offchain/tests.rs b/client/rpc/src/offchain/tests.rs index ac1a6a4de31bcc95bb1f385c3f7d78a75a83fbe1..f65971a7ffe8ae278495dfb80921e979806c187a 100644 --- a/client/rpc/src/offchain/tests.rs +++ b/client/rpc/src/offchain/tests.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use super::*; use assert_matches::assert_matches; @@ -21,7 +23,7 @@ use sp_core::{Bytes, offchain::storage::InMemOffchainStorage}; #[test] fn local_storage_should_work() { let storage = InMemOffchainStorage::default(); - let offchain = Offchain::new(storage); + let offchain = Offchain::new(storage, DenyUnsafe::No); let key = Bytes(b"offchain_storage".to_vec()); let value = Bytes(b"offchain_value".to_vec()); @@ -34,3 +36,20 @@ fn local_storage_should_work() { Ok(Some(ref v)) if *v == value ); } + +#[test] +fn offchain_calls_considered_unsafe() { + let storage = InMemOffchainStorage::default(); + let offchain = Offchain::new(storage, DenyUnsafe::Yes); + let key = Bytes(b"offchain_storage".to_vec()); + let value = Bytes(b"offchain_value".to_vec()); + + assert_matches!( + offchain.set_local_storage(StorageKind::PERSISTENT, key.clone(), value.clone()), + Err(Error::UnsafeRpcCalled(_)) + ); + assert_matches!( + offchain.get_local_storage(StorageKind::PERSISTENT, key), + Err(Error::UnsafeRpcCalled(_)) + ); +} diff --git a/client/rpc/src/state/mod.rs b/client/rpc/src/state/mod.rs index 2747405c04fcac0c7534ea802bb5e1f08a7e1911..921cc7efc699d9d902e114aed7586983411f77f3 100644 --- a/client/rpc/src/state/mod.rs +++ b/client/rpc/src/state/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Substrate state API. @@ -23,12 +25,12 @@ mod state_light; mod tests; use std::sync::Arc; -use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; +use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId, manager::SubscriptionManager}; use rpc::{Result as RpcResult, futures::{Future, future::result}}; -use sc_rpc_api::Subscriptions; -use sc_client::{light::{blockchain::RemoteBlockchain, fetcher::Fetcher}}; -use sp_core::{Bytes, storage::{StorageKey, StorageData, StorageChangeSet}}; +use sc_rpc_api::state::ReadProof; +use sc_client_api::light::{RemoteBlockchain, Fetcher}; +use sp_core::{Bytes, storage::{StorageKey, PrefixedStorageKey, StorageData, StorageChangeSet}}; use sp_version::RuntimeVersion; use sp_runtime::traits::Block as BlockT; @@ -37,7 +39,8 @@ use sp_api::{Metadata, ProvideRuntimeApi, CallApiAt}; use self::error::{Error, FutureResult}; pub use sc_rpc_api::state::*; -use sc_client_api::{ExecutorProvider, StorageProvider, BlockchainEvents, Backend}; +pub use sc_rpc_api::child_state::*; +use sc_client_api::{ExecutorProvider, StorageProvider, BlockchainEvents, Backend, ProofProvider}; use sp_blockchain::{HeaderMetadata, HeaderBackend}; const STORAGE_KEYS_PAGED_MAX_COUNT: u32 = 1000; @@ -103,49 +106,6 @@ pub trait StateBackend: Send + Sync + 'static .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 - fn child_storage_keys( - &self, - block: Option, - child_storage_key: StorageKey, - child_info: StorageKey, - child_type: u32, - prefix: StorageKey, - ) -> FutureResult>; - - /// Returns a child storage entry at a specific block's state. - fn child_storage( - &self, - block: Option, - child_storage_key: StorageKey, - child_info: StorageKey, - child_type: u32, - key: StorageKey, - ) -> FutureResult>; - - /// Returns the hash of a child storage entry at a block's state. - fn child_storage_hash( - &self, - block: Option, - child_storage_key: StorageKey, - child_info: StorageKey, - child_type: u32, - key: StorageKey, - ) -> FutureResult>; - - /// Returns the size of a child storage entry at a block's state. - fn child_storage_size( - &self, - block: Option, - child_storage_key: StorageKey, - child_info: StorageKey, - child_type: u32, - key: StorageKey, - ) -> FutureResult> { - Box::new(self.child_storage(block, child_storage_key, child_info, child_type, key) - .map(|x| x.map(|x| x.0.len() as u64))) - } - /// Returns the runtime metadata as an opaque blob. fn metadata(&self, block: Option) -> FutureResult; @@ -170,6 +130,13 @@ pub trait StateBackend: Send + Sync + 'static at: Option ) -> FutureResult>>; + /// Returns proof of storage entries at a specific block's state. + fn read_proof( + &self, + block: Option, + keys: Vec, + ) -> FutureResult>; + /// New runtime version subscription fn subscribe_runtime_version( &self, @@ -203,29 +170,31 @@ pub trait StateBackend: Send + Sync + 'static /// Create new state API that works on full node. pub fn new_full( client: Arc, - subscriptions: Subscriptions, -) -> State + subscriptions: SubscriptionManager, +) -> (State, ChildState) where Block: BlockT + 'static, BE: Backend + 'static, - Client: ExecutorProvider + StorageProvider + HeaderBackend + Client: ExecutorProvider + StorageProvider + ProofProvider + HeaderBackend + HeaderMetadata + BlockchainEvents + CallApiAt + ProvideRuntimeApi + Send + Sync + 'static, Client::Api: Metadata, { - State { - backend: Box::new(self::state_full::FullState::new(client, subscriptions)), - } + let child_backend = Box::new( + self::state_full::FullState::new(client.clone(), subscriptions.clone()) + ); + let backend = Box::new(self::state_full::FullState::new(client, subscriptions)); + (State { backend }, ChildState { backend: child_backend }) } /// Create new state API that works on light node. pub fn new_light>( client: Arc, - subscriptions: Subscriptions, + subscriptions: SubscriptionManager, remote_blockchain: Arc>, fetcher: Arc, -) -> State +) -> (State, ChildState) where Block: BlockT + 'static, BE: Backend + 'static, @@ -235,14 +204,20 @@ pub fn new_light>( + Send + Sync + 'static, F: Send + Sync + 'static, { - State { - backend: Box::new(self::state_light::LightState::new( + let child_backend = Box::new(self::state_light::LightState::new( + client.clone(), + subscriptions.clone(), + remote_blockchain.clone(), + fetcher.clone(), + )); + + let backend = Box::new(self::state_light::LightState::new( client, subscriptions, remote_blockchain, fetcher, - )), - } + )); + (State { backend }, ChildState { backend: child_backend }) } /// State API with subscriptions support. @@ -307,50 +282,6 @@ impl StateApi for State self.backend.storage_size(block, key) } - fn child_storage( - &self, - child_storage_key: StorageKey, - child_info: StorageKey, - child_type: u32, - key: StorageKey, - block: Option - ) -> FutureResult> { - self.backend.child_storage(block, child_storage_key, child_info, child_type, key) - } - - fn child_storage_keys( - &self, - child_storage_key: StorageKey, - child_info: StorageKey, - child_type: u32, - key_prefix: StorageKey, - block: Option - ) -> FutureResult> { - self.backend.child_storage_keys(block, child_storage_key, child_info, child_type, key_prefix) - } - - fn child_storage_hash( - &self, - child_storage_key: StorageKey, - child_info: StorageKey, - child_type: u32, - key: StorageKey, - block: Option - ) -> FutureResult> { - self.backend.child_storage_hash(block, child_storage_key, child_info, child_type, key) - } - - fn child_storage_size( - &self, - child_storage_key: StorageKey, - child_info: StorageKey, - child_type: u32, - key: StorageKey, - block: Option - ) -> FutureResult> { - self.backend.child_storage_size(block, child_storage_key, child_info, child_type, key) - } - fn metadata(&self, block: Option) -> FutureResult { self.backend.metadata(block) } @@ -372,6 +303,10 @@ impl StateApi for State self.backend.query_storage_at(keys, at) } + fn read_proof(&self, keys: Vec, block: Option) -> FutureResult> { + self.backend.read_proof(block, keys) + } + fn subscribe_storage( &self, meta: Self::Metadata, @@ -402,12 +337,98 @@ impl StateApi for State } } -fn client_err(err: sp_blockchain::Error) -> Error { - Error::Client(Box::new(err)) +/// Child state backend API. +pub trait ChildStateBackend: Send + Sync + 'static + where + Block: BlockT + 'static, + Client: Send + Sync + 'static, +{ + /// Returns the keys with prefix from a child storage, + /// leave prefix empty to get all the keys. + fn storage_keys( + &self, + block: Option, + storage_key: PrefixedStorageKey, + prefix: StorageKey, + ) -> FutureResult>; + + /// Returns a child storage entry at a specific block's state. + fn storage( + &self, + block: Option, + storage_key: PrefixedStorageKey, + key: StorageKey, + ) -> FutureResult>; + + /// Returns the hash of a child storage entry at a block's state. + fn storage_hash( + &self, + block: Option, + storage_key: PrefixedStorageKey, + key: StorageKey, + ) -> FutureResult>; + + /// Returns the size of a child storage entry at a block's state. + fn storage_size( + &self, + block: Option, + storage_key: PrefixedStorageKey, + key: StorageKey, + ) -> FutureResult> { + Box::new(self.storage(block, storage_key, key) + .map(|x| x.map(|x| x.0.len() as u64))) + } } -const CHILD_RESOLUTION_ERROR: &str = "Unexpected child info and type"; +/// Child state API with subscriptions support. +pub struct ChildState { + backend: Box>, +} -fn child_resolution_error() -> sp_blockchain::Error { - sp_blockchain::Error::Msg(CHILD_RESOLUTION_ERROR.to_string()) +impl ChildStateApi for ChildState + where + Block: BlockT + 'static, + Client: Send + Sync + 'static, +{ + type Metadata = crate::metadata::Metadata; + + fn storage( + &self, + storage_key: PrefixedStorageKey, + key: StorageKey, + block: Option + ) -> FutureResult> { + self.backend.storage(block, storage_key, key) + } + + fn storage_keys( + &self, + storage_key: PrefixedStorageKey, + key_prefix: StorageKey, + block: Option + ) -> FutureResult> { + self.backend.storage_keys(block, storage_key, key_prefix) + } + + fn storage_hash( + &self, + storage_key: PrefixedStorageKey, + key: StorageKey, + block: Option + ) -> FutureResult> { + self.backend.storage_hash(block, storage_key, key) + } + + fn storage_size( + &self, + storage_key: PrefixedStorageKey, + key: StorageKey, + block: Option + ) -> FutureResult> { + self.backend.storage_size(block, storage_key, key) + } +} + +fn client_err(err: sp_blockchain::Error) -> Error { + Error::Client(Box::new(err)) } diff --git a/client/rpc/src/state/state_full.rs b/client/rpc/src/state/state_full.rs index bf80820543102483ae5c41a301ad1ab0d322890d..f0ae79a033b58dfb4ae48e344b03ac58975906b3 100644 --- a/client/rpc/src/state/state_full.rs +++ b/client/rpc/src/state/state_full.rs @@ -21,15 +21,16 @@ use std::sync::Arc; use std::ops::Range; use futures::{future, StreamExt as _, TryStreamExt as _}; use log::warn; -use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; +use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId, manager::SubscriptionManager}; use rpc::{Result as RpcResult, futures::{stream, Future, Sink, Stream, future::result}}; -use sc_rpc_api::Subscriptions; +use sc_rpc_api::state::ReadProof; use sc_client_api::backend::Backend; use sp_blockchain::{Result as ClientResult, Error as ClientError, HeaderMetadata, CachedHeaderMetadata, HeaderBackend}; -use sc_client::BlockchainEvents; +use sc_client_api::BlockchainEvents; use sp_core::{ - Bytes, storage::{well_known_keys, StorageKey, StorageData, StorageChangeSet, ChildInfo}, + Bytes, storage::{well_known_keys, StorageKey, StorageData, StorageChangeSet, + ChildInfo, ChildType, PrefixedStorageKey}, }; use sp_version::RuntimeVersion; use sp_runtime::{ @@ -38,9 +39,9 @@ use sp_runtime::{ use sp_api::{Metadata, ProvideRuntimeApi, CallApiAt}; -use super::{StateBackend, error::{FutureResult, Error, Result}, client_err, child_resolution_error}; +use super::{StateBackend, ChildStateBackend, error::{FutureResult, Error, Result}, client_err}; use std::marker::PhantomData; -use sc_client_api::{CallExecutor, StorageProvider, ExecutorProvider}; +use sc_client_api::{CallExecutor, StorageProvider, ExecutorProvider, ProofProvider}; /// Ranges to query in state_queryStorage. struct QueryStorageRange { @@ -59,7 +60,7 @@ struct QueryStorageRange { /// State API backend for full nodes. pub struct FullState { client: Arc, - subscriptions: Subscriptions, + subscriptions: SubscriptionManager, _phantom: PhantomData<(BE, Block)> } @@ -71,7 +72,7 @@ impl FullState Block: BlockT + 'static, { /// Create new state API backend for full nodes. - pub fn new(client: Arc, subscriptions: Subscriptions) -> Self { + pub fn new(client: Arc, subscriptions: SubscriptionManager) -> Self { Self { client, subscriptions, _phantom: PhantomData } } @@ -218,7 +219,7 @@ impl FullState impl StateBackend for FullState where Block: BlockT + 'static, BE: Backend + 'static, - Client: ExecutorProvider + StorageProvider + HeaderBackend + Client: ExecutorProvider + StorageProvider + ProofProvider + HeaderBackend + HeaderMetadata + BlockchainEvents + CallApiAt + ProvideRuntimeApi + Send + Sync + 'static, @@ -308,66 +309,6 @@ impl StateBackend for FullState, - child_storage_key: StorageKey, - child_info: StorageKey, - child_type: u32, - 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, - ChildInfo::resolve_child_info(child_type, &child_info.0[..]) - .ok_or_else(child_resolution_error)?, - &prefix, - )) - .map_err(client_err))) - } - - fn child_storage( - &self, - block: Option, - child_storage_key: StorageKey, - child_info: StorageKey, - child_type: u32, - key: StorageKey, - ) -> FutureResult> { - Box::new(result( - self.block_or_best(block) - .and_then(|block| self.client.child_storage( - &BlockId::Hash(block), - &child_storage_key, - ChildInfo::resolve_child_info(child_type, &child_info.0[..]) - .ok_or_else(child_resolution_error)?, - &key, - )) - .map_err(client_err))) - } - - fn child_storage_hash( - &self, - block: Option, - child_storage_key: StorageKey, - child_info: StorageKey, - child_type: u32, - 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, - ChildInfo::resolve_child_info(child_type, &child_info.0[..]) - .ok_or_else(child_resolution_error)?, - &key, - )) - .map_err(client_err))) - } - fn metadata(&self, block: Option) -> FutureResult { Box::new(result( self.block_or_best(block) @@ -410,6 +351,26 @@ impl StateBackend for FullState, + keys: Vec, + ) -> FutureResult> { + Box::new(result( + self.block_or_best(block) + .and_then(|block| { + self.client + .read_proof( + &BlockId::Hash(block), + &mut keys.iter().map(|key| key.0.as_ref()), + ) + .map(|proof| proof.iter_nodes().map(|node| node.into()).collect()) + .map(|proof| ReadProof { at: block, proof }) + }) + .map_err(client_err), + )) + } + fn subscribe_runtime_version( &self, _meta: crate::metadata::Metadata, @@ -493,7 +454,7 @@ impl StateBackend for FullState StateBackend for FullState ChildStateBackend for FullState where + Block: BlockT + 'static, + BE: Backend + 'static, + Client: ExecutorProvider + StorageProvider + HeaderBackend + + HeaderMetadata + BlockchainEvents + + CallApiAt + ProvideRuntimeApi + + Send + Sync + 'static, + Client::Api: Metadata, +{ + fn storage_keys( + &self, + block: Option, + storage_key: PrefixedStorageKey, + prefix: StorageKey, + ) -> FutureResult> { + Box::new(result( + self.block_or_best(block) + .and_then(|block| { + let child_info = match ChildType::from_prefixed_key(&storage_key) { + Some((ChildType::ParentKeyId, storage_key)) => ChildInfo::new_default(storage_key), + None => return Err("Invalid child storage key".into()), + }; + self.client.child_storage_keys( + &BlockId::Hash(block), + &child_info, + &prefix, + ) + }) + .map_err(client_err))) + } + + fn storage( + &self, + block: Option, + storage_key: PrefixedStorageKey, + key: StorageKey, + ) -> FutureResult> { + Box::new(result( + self.block_or_best(block) + .and_then(|block| { + let child_info = match ChildType::from_prefixed_key(&storage_key) { + Some((ChildType::ParentKeyId, storage_key)) => ChildInfo::new_default(storage_key), + None => return Err("Invalid child storage key".into()), + }; + self.client.child_storage( + &BlockId::Hash(block), + &child_info, + &key, + ) + }) + .map_err(client_err))) + } + + fn storage_hash( + &self, + block: Option, + storage_key: PrefixedStorageKey, + key: StorageKey, + ) -> FutureResult> { + Box::new(result( + self.block_or_best(block) + .and_then(|block| { + let child_info = match ChildType::from_prefixed_key(&storage_key) { + Some((ChildType::ParentKeyId, storage_key)) => ChildInfo::new_default(storage_key), + None => return Err("Invalid child storage key".into()), + }; + self.client.child_storage_hash( + &BlockId::Hash(block), + &child_info, + &key, + ) + }) + .map_err(client_err))) + } +} + /// Splits passed range into two subranges where: /// - first range has at least one element in it; /// - second range (optionally) starts at given `middle` element. diff --git a/client/rpc/src/state/state_light.rs b/client/rpc/src/state/state_light.rs index 092419ad0129e6f4109a19d3f916dc0eb24f5738..ec275a2d78b79d9a071c6220d8013e39d0b31ccd 100644 --- a/client/rpc/src/state/state_light.rs +++ b/client/rpc/src/state/state_light.rs @@ -28,7 +28,7 @@ use futures::{ StreamExt as _, TryStreamExt as _, }; use hash_db::Hasher; -use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; +use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId, manager::SubscriptionManager}; use log::warn; use parking_lot::Mutex; use rpc::{ @@ -38,30 +38,32 @@ use rpc::{ futures::stream::Stream, }; -use sc_rpc_api::Subscriptions; +use sc_rpc_api::state::ReadProof; use sp_blockchain::{Error as ClientError, HeaderBackend}; -use sc_client::{ +use sc_client_api::{ BlockchainEvents, light::{ - blockchain::{future_header, RemoteBlockchain}, - fetcher::{Fetcher, RemoteCallRequest, RemoteReadRequest, RemoteReadChildRequest}, + RemoteCallRequest, RemoteReadRequest, RemoteReadChildRequest, + RemoteBlockchain, Fetcher, future_header, }, }; use sp_core::{ - Bytes, OpaqueMetadata, storage::{StorageKey, StorageData, StorageChangeSet}, + Bytes, OpaqueMetadata, + storage::{StorageKey, PrefixedStorageKey, StorageData, StorageChangeSet}, }; use sp_version::RuntimeVersion; use sp_runtime::{generic::BlockId, traits::{Block as BlockT, HashFor}}; -use super::{StateBackend, error::{FutureResult, Error}, client_err}; +use super::{StateBackend, ChildStateBackend, error::{FutureResult, Error}, client_err}; /// Storage data map of storage keys => (optional) storage value. type StorageMap = HashMap>; /// State API backend for light nodes. +#[derive(Clone)] pub struct LightState, Client> { client: Arc, - subscriptions: Subscriptions, + subscriptions: SubscriptionManager, version_subscriptions: SimpleSubscriptions, storage_subscriptions: Arc>>, remote_blockchain: Arc>, @@ -141,7 +143,7 @@ impl + 'static, Client> LightState, - subscriptions: Subscriptions, + subscriptions: SubscriptionManager, remote_blockchain: Arc>, fetcher: Arc, ) -> Self { @@ -233,69 +235,7 @@ impl StateBackend for LightState, key: StorageKey, ) -> FutureResult> { - Box::new(self - .storage(block, key) - .and_then(|maybe_storage| - result(Ok(maybe_storage.map(|storage| HashFor::::hash(&storage.0)))) - ) - ) - } - - fn child_storage_keys( - &self, - _block: Option, - _child_storage_key: StorageKey, - _child_info: StorageKey, - _child_type: u32, - _prefix: StorageKey, - ) -> FutureResult> { - Box::new(result(Err(client_err(ClientError::NotAvailableOnLightClient)))) - } - - fn child_storage( - &self, - block: Option, - child_storage_key: StorageKey, - child_info: StorageKey, - child_type: u32, - 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, - child_info: child_info.0, - child_type, - 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, - child_info: StorageKey, - child_type: u32, - key: StorageKey, - ) -> FutureResult> { - Box::new(self - .child_storage(block, child_storage_key, child_info, child_type, key) + Box::new(StateBackend::storage(self, block, key) .and_then(|maybe_storage| result(Ok(maybe_storage.map(|storage| HashFor::::hash(&storage.0)))) ) @@ -339,6 +279,14 @@ impl StateBackend for LightState, + _keys: Vec, + ) -> FutureResult> { + Box::new(result(Err(client_err(ClientError::NotAvailableOnLightClient)))) + } + fn subscribe_storage( &self, _meta: crate::metadata::Metadata, @@ -518,6 +466,65 @@ impl StateBackend for LightState ChildStateBackend for LightState + where + Block: BlockT, + Client: BlockchainEvents + HeaderBackend + Send + Sync + 'static, + F: Fetcher + 'static +{ + fn storage_keys( + &self, + _block: Option, + _storage_key: PrefixedStorageKey, + _prefix: StorageKey, + ) -> FutureResult> { + Box::new(result(Err(client_err(ClientError::NotAvailableOnLightClient)))) + } + + fn storage( + &self, + block: Option, + storage_key: PrefixedStorageKey, + 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, + 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 storage_hash( + &self, + block: Option, + storage_key: PrefixedStorageKey, + key: StorageKey, + ) -> FutureResult> { + Box::new(ChildStateBackend::storage(self, block, storage_key, key) + .and_then(|maybe_storage| + result(Ok(maybe_storage.map(|storage| HashFor::::hash(&storage.0)))) + ) + ) + } +} + /// Resolve header by hash. fn resolve_header>( remote_blockchain: &dyn RemoteBlockchain, diff --git a/client/rpc/src/state/tests.rs b/client/rpc/src/state/tests.rs index 4a9b701959c8c292a3b4dba25d89762fedfd8f62..0cc16ce8d5e927e3b55b8f3b292de1483fed1730 100644 --- a/client/rpc/src/state/tests.rs +++ b/client/rpc/src/state/tests.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use super::*; use super::state_full::split_range; @@ -21,7 +23,7 @@ use self::error::Error; use std::sync::Arc; use assert_matches::assert_matches; use futures01::stream::Stream; -use sp_core::{storage::{well_known_keys, ChildInfo}, ChangesTrieConfiguration}; +use sp_core::{storage::ChildInfo, ChangesTrieConfiguration}; use sp_core::hash::H256; use sc_block_builder::BlockBuilderProvider; use sp_io::hashing::blake2_256; @@ -31,27 +33,30 @@ use substrate_test_runtime_client::{ runtime, }; use sp_runtime::generic::BlockId; +use crate::testing::TaskExecutor; +use futures::{executor, compat::Future01CompatExt}; + +const STORAGE_KEY: &[u8] = b"child"; -const CHILD_INFO: ChildInfo<'static> = ChildInfo::new_default(b"unique_id"); +fn prefixed_storage_key() -> PrefixedStorageKey { + let child_info = ChildInfo::new_default(&STORAGE_KEY[..]); + child_info.prefixed_storage_key() +} #[test] fn should_return_storage() { 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 child_info = ChildInfo::new_default(STORAGE_KEY); let client = TestClientBuilder::new() .add_extra_storage(KEY.to_vec(), VALUE.to_vec()) - .add_extra_child_storage(STORAGE_KEY.to_vec(), CHILD_INFO, KEY.to_vec(), CHILD_VALUE.to_vec()) + .add_extra_child_storage(&child_info, KEY.to_vec(), CHILD_VALUE.to_vec()) .build(); let genesis_hash = client.genesis_hash(); - let client = new_full(Arc::new(client), Subscriptions::new(Arc::new(core.executor()))); + let (client, child) = new_full(Arc::new(client), SubscriptionManager::new(Arc::new(TaskExecutor))); let key = StorageKey(KEY.to_vec()); - let storage_key = StorageKey(STORAGE_KEY.to_vec()); - let (child_info, child_type) = CHILD_INFO.info(); - let child_info = StorageKey(child_info.to_vec()); assert_eq!( client.storage(key.clone(), Some(genesis_hash).into()).wait() @@ -68,9 +73,10 @@ fn should_return_storage() { VALUE.len(), ); assert_eq!( - core.block_on( - client.child_storage(storage_key, child_info, child_type, key, Some(genesis_hash).into()) + executor::block_on( + child.storage(prefixed_storage_key(), key, Some(genesis_hash).into()) .map(|x| x.map(|x| x.0.len())) + .compat(), ).unwrap().unwrap() as usize, CHILD_VALUE.len(), ); @@ -79,45 +85,35 @@ fn should_return_storage() { #[test] fn should_return_child_storage() { - let (child_info, child_type) = CHILD_INFO.info(); - let child_info = StorageKey(child_info.to_vec()); - let core = tokio::runtime::Runtime::new().unwrap(); + let child_info = ChildInfo::new_default(STORAGE_KEY); let client = Arc::new(substrate_test_runtime_client::TestClientBuilder::new() - .add_child_storage("test", "key", CHILD_INFO, vec![42_u8]) + .add_child_storage(&child_info, "key", vec![42_u8]) .build()); let genesis_hash = client.genesis_hash(); - 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 (_client, child) = new_full(client, SubscriptionManager::new(Arc::new(TaskExecutor))); + let child_key = prefixed_storage_key(); let key = StorageKey(b"key".to_vec()); assert_matches!( - client.child_storage( + child.storage( child_key.clone(), - child_info.clone(), - child_type, 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.storage_hash( child_key.clone(), - child_info.clone(), - child_type, key.clone(), Some(genesis_hash).into(), ).wait().map(|x| x.is_some()), Ok(true) ); assert_matches!( - client.child_storage_size( + child.storage_size( child_key.clone(), - child_info.clone(), - child_type, key.clone(), None, ).wait(), @@ -127,10 +123,9 @@ fn should_return_child_storage() { #[test] fn should_call_contract() { - let core = tokio::runtime::Runtime::new().unwrap(); let client = Arc::new(substrate_test_runtime_client::new()); let genesis_hash = client.genesis_hash(); - let client = new_full(client, Subscriptions::new(Arc::new(core.executor()))); + let (client, _child) = new_full(client, SubscriptionManager::new(Arc::new(TaskExecutor))); assert_matches!( client.call("balanceOf".into(), Bytes(vec![1,2,3]), Some(genesis_hash).into()).wait(), @@ -140,18 +135,19 @@ fn should_call_contract() { #[test] fn should_notify_about_storage_changes() { - let mut core = tokio::runtime::Runtime::new().unwrap(); - let remote = core.executor(); let (subscriber, id, transport) = Subscriber::new_test("test"); { let mut client = Arc::new(substrate_test_runtime_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + let (api, _child) = new_full(client.clone(), SubscriptionManager::new(Arc::new(TaskExecutor))); api.subscribe_storage(Default::default(), subscriber, None.into()); // assert id assigned - assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); + assert!(matches!( + executor::block_on(id.compat()), + Ok(Ok(SubscriptionId::String(_))) + )); let mut builder = client.new_block(Default::default()).unwrap(); builder.push_transfer(runtime::Transfer { @@ -165,21 +161,19 @@ fn should_notify_about_storage_changes() { } // assert notification sent to transport - let (notification, next) = core.block_on(transport.into_future()).unwrap(); + let (notification, next) = executor::block_on(transport.into_future().compat()).unwrap(); assert!(notification.is_some()); // no more notifications on this channel - assert_eq!(core.block_on(next.into_future()).unwrap().0, None); + assert_eq!(executor::block_on(next.into_future().compat()).unwrap().0, None); } #[test] fn should_send_initial_storage_changes_and_notifications() { - let mut core = tokio::runtime::Runtime::new().unwrap(); - let remote = core.executor(); let (subscriber, id, transport) = Subscriber::new_test("test"); { let mut client = Arc::new(substrate_test_runtime_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + let (api, _child) = new_full(client.clone(), SubscriptionManager::new(Arc::new(TaskExecutor))); let alice_balance_key = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Alice.into())); @@ -188,7 +182,10 @@ fn should_send_initial_storage_changes_and_notifications() { ]).into()); // assert id assigned - assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); + assert!(matches!( + executor::block_on(id.compat()), + Ok(Ok(SubscriptionId::String(_))) + )); let mut builder = client.new_block(Default::default()).unwrap(); builder.push_transfer(runtime::Transfer { @@ -202,20 +199,19 @@ fn should_send_initial_storage_changes_and_notifications() { } // assert initial values sent to transport - let (notification, next) = core.block_on(transport.into_future()).unwrap(); + let (notification, next) = executor::block_on(transport.into_future().compat()).unwrap(); assert!(notification.is_some()); // assert notification sent to transport - let (notification, next) = core.block_on(next.into_future()).unwrap(); + let (notification, next) = executor::block_on(next.into_future().compat()).unwrap(); assert!(notification.is_some()); // no more notifications on this channel - assert_eq!(core.block_on(next.into_future()).unwrap().0, None); + assert_eq!(executor::block_on(next.into_future().compat()).unwrap().0, None); } #[test] fn should_query_storage() { fn run_tests(mut client: Arc, has_changes_trie_config: bool) { - let core = tokio::runtime::Runtime::new().unwrap(); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(core.executor()))); + let (api, _child) = new_full(client.clone(), SubscriptionManager::new(Arc::new(TaskExecutor))); let mut add_block = |nonce| { let mut builder = client.new_block(Default::default()).unwrap(); @@ -431,16 +427,15 @@ fn should_split_ranges() { #[test] fn should_return_runtime_version() { - let core = tokio::runtime::Runtime::new().unwrap(); - let client = Arc::new(substrate_test_runtime_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(core.executor()))); + let (api, _child) = new_full(client.clone(), SubscriptionManager::new(Arc::new(TaskExecutor))); let result = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\ - \"specVersion\":2,\"implVersion\":2,\"apis\":[[\"0xdf6acb689907609b\",2],\ + \"specVersion\":2,\"implVersion\":2,\"apis\":[[\"0xdf6acb689907609b\",3],\ [\"0x37e397fc7c91f5e4\",1],[\"0xd2bc9897eed08f15\",2],[\"0x40fe3ad401f8959a\",4],\ - [\"0xc6e9a76309f39b09\",1],[\"0xdd718d5cc53262d4\",1],[\"0xcbca25e39f142387\",1],\ - [\"0xf78b278be53f454c\",2],[\"0xab3c0572291feb8b\",1],[\"0xbc9d89904f5b923f\",1]]}"; + [\"0xc6e9a76309f39b09\",1],[\"0xdd718d5cc53262d4\",1],[\"0xcbca25e39f142387\",2],\ + [\"0xf78b278be53f454c\",2],[\"0xab3c0572291feb8b\",1],[\"0xbc9d89904f5b923f\",1]],\ + \"transactionVersion\":1}"; let runtime_version = api.runtime_version(None.into()).wait().unwrap(); let serialized = serde_json::to_string(&runtime_version).unwrap(); @@ -452,24 +447,27 @@ fn should_return_runtime_version() { #[test] fn should_notify_on_runtime_version_initially() { - let mut core = tokio::runtime::Runtime::new().unwrap(); let (subscriber, id, transport) = Subscriber::new_test("test"); { let client = Arc::new(substrate_test_runtime_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(core.executor()))); + let (api, _child) = new_full(client.clone(), SubscriptionManager::new(Arc::new(TaskExecutor))); api.subscribe_runtime_version(Default::default(), subscriber); // assert id assigned - assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); + assert!(matches!( + executor::block_on(id.compat()), + Ok(Ok(SubscriptionId::String(_))) + )); + } // assert initial version sent. - let (notification, next) = core.block_on(transport.into_future()).unwrap(); + let (notification, next) = executor::block_on(transport.into_future().compat()).unwrap(); assert!(notification.is_some()); // no more notifications on this channel - assert_eq!(core.block_on(next.into_future()).unwrap().0, None); + assert_eq!(executor::block_on(next.into_future().compat()).unwrap().0, None); } #[test] diff --git a/client/rpc/src/system/mod.rs b/client/rpc/src/system/mod.rs index 9565992cf44c526ecf235185be4cfd3243fe1020..4b8abbe1444620e23467edfef567d9fd0f71c570 100644 --- a/client/rpc/src/system/mod.rs +++ b/client/rpc/src/system/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Substrate system API. @@ -21,26 +23,40 @@ mod tests; use futures::{future::BoxFuture, FutureExt, TryFutureExt}; use futures::{channel::oneshot, compat::Compat}; -use sc_rpc_api::Receiver; +use sc_rpc_api::{DenyUnsafe, Receiver}; use sp_utils::mpsc::TracingUnboundedSender; use sp_runtime::traits::{self, Header as HeaderT}; use self::error::Result; pub use sc_rpc_api::system::*; -pub use self::helpers::{Properties, SystemInfo, Health, PeerInfo, NodeRole}; +pub use self::helpers::{SystemInfo, Health, PeerInfo, NodeRole}; pub use self::gen_client::Client as SystemClient; +macro_rules! bail_if_unsafe { + ($value: expr) => { + if let Err(err) = $value.check_if_safe() { + return async move { Err(err.into()) }.boxed().compat(); + } + }; +} + /// System API implementation pub struct System { info: SystemInfo, send_back: TracingUnboundedSender>, + deny_unsafe: DenyUnsafe, } /// Request to be processed. pub enum Request { /// Must return the health of the network. Health(oneshot::Sender), + /// Must return the base58-encoded local `PeerId`. + LocalPeerId(oneshot::Sender), + /// Must return the string representation of the addresses we listen on, including the + /// trailing `/p2p/`. + LocalListenAddresses(oneshot::Sender>), /// Must return information about the peers we are connected to. Peers(oneshot::Sender::Number>>>), /// Must return the state of the network. @@ -61,10 +77,12 @@ impl System { pub fn new( info: SystemInfo, send_back: TracingUnboundedSender>, + deny_unsafe: DenyUnsafe, ) -> Self { System { info, send_back, + deny_unsafe, } } } @@ -82,7 +100,11 @@ impl SystemApi::Number> for Sy Ok(self.info.chain_name.clone()) } - fn system_properties(&self) -> Result { + fn system_type(&self) -> Result { + Ok(self.info.chain_type.clone()) + } + + fn system_properties(&self) -> Result { Ok(self.info.properties.clone()) } @@ -92,21 +114,49 @@ impl SystemApi::Number> for Sy Receiver(Compat::new(rx)) } - fn system_peers(&self) -> Receiver::Number>>> { + fn system_local_peer_id(&self) -> Receiver { let (tx, rx) = oneshot::channel(); - let _ = self.send_back.unbounded_send(Request::Peers(tx)); + let _ = self.send_back.unbounded_send(Request::LocalPeerId(tx)); Receiver(Compat::new(rx)) } - fn system_network_state(&self) -> Receiver { + fn system_local_listen_addresses(&self) -> Receiver> { let (tx, rx) = oneshot::channel(); - let _ = self.send_back.unbounded_send(Request::NetworkState(tx)); + let _ = self.send_back.unbounded_send(Request::LocalListenAddresses(tx)); Receiver(Compat::new(rx)) } + fn system_peers(&self) + -> Compat::Number>>>>> + { + bail_if_unsafe!(self.deny_unsafe); + + let (tx, rx) = oneshot::channel(); + let _ = self.send_back.unbounded_send(Request::Peers(tx)); + + async move { + rx.await.map_err(|_| rpc::Error::internal_error()) + }.boxed().compat() + } + + fn system_network_state(&self) + -> Compat>> + { + bail_if_unsafe!(self.deny_unsafe); + + let (tx, rx) = oneshot::channel(); + let _ = self.send_back.unbounded_send(Request::NetworkState(tx)); + + async move { + rx.await.map_err(|_| rpc::Error::internal_error()) + }.boxed().compat() + } + fn system_add_reserved_peer(&self, peer: String) -> Compat>> { + bail_if_unsafe!(self.deny_unsafe); + let (tx, rx) = oneshot::channel(); let _ = self.send_back.unbounded_send(Request::NetworkAddReservedPeer(peer, tx)); async move { @@ -121,6 +171,8 @@ impl SystemApi::Number> for Sy fn system_remove_reserved_peer(&self, peer: String) -> Compat>> { + bail_if_unsafe!(self.deny_unsafe); + let (tx, rx) = oneshot::channel(); let _ = self.send_back.unbounded_send(Request::NetworkRemoveReservedPeer(peer, tx)); async move { diff --git a/client/rpc/src/system/tests.rs b/client/rpc/src/system/tests.rs index d45894743c104013d4eee67b85cebdb9b1bc3360..7fe5cdc752a06bde155f071cc5e812237b8b7403 100644 --- a/client/rpc/src/system/tests.rs +++ b/client/rpc/src/system/tests.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use super::*; @@ -20,7 +22,8 @@ use sc_network::{self, PeerId}; use sc_network::config::Role; use substrate_test_runtime_client::runtime::Block; use assert_matches::assert_matches; -use futures::{prelude::*, channel::mpsc}; +use futures::prelude::*; +use sp_utils::mpsc::tracing_unbounded; use std::thread; struct Status { @@ -44,7 +47,7 @@ impl Default for Status { fn api>>(sync: T) -> System { let status = sync.into().unwrap_or_default(); let should_have_peers = !status.is_dev; - let (tx, rx) = mpsc::unbounded(); + let (tx, rx) = tracing_unbounded("rpc_system_tests"); thread::spawn(move || { futures::executor::block_on(rx.for_each(move |request| { match request { @@ -55,6 +58,15 @@ fn api>>(sync: T) -> System { should_have_peers, }); }, + Request::LocalPeerId(sender) => { + let _ = sender.send("QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV".to_string()); + }, + Request::LocalListenAddresses(sender) => { + let _ = sender.send(vec![ + "/ip4/198.51.100.19/tcp/30333/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV".to_string(), + "/ip4/127.0.0.1/tcp/30334/ws/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV".to_string(), + ]); + }, Request::Peers(sender) => { let mut peers = vec![]; for _peer in 0..status.peers { @@ -100,12 +112,17 @@ fn api>>(sync: T) -> System { future::ready(()) })) }); - System::new(SystemInfo { - impl_name: "testclient".into(), - impl_version: "0.2.0".into(), - chain_name: "testchain".into(), - properties: Default::default(), - }, tx) + System::new( + SystemInfo { + impl_name: "testclient".into(), + impl_version: "0.2.0".into(), + chain_name: "testchain".into(), + properties: Default::default(), + chain_type: Default::default(), + }, + tx, + sc_rpc_api::DenyUnsafe::No + ) } fn wait_receiver(rx: Receiver) -> T { @@ -117,7 +134,7 @@ fn wait_receiver(rx: Receiver) -> T { fn system_name_works() { assert_eq!( api(None).system_name().unwrap(), - "testclient".to_owned() + "testclient".to_owned(), ); } @@ -125,7 +142,7 @@ fn system_name_works() { fn system_version_works() { assert_eq!( api(None).system_version().unwrap(), - "0.2.0".to_owned() + "0.2.0".to_owned(), ); } @@ -133,7 +150,7 @@ fn system_version_works() { fn system_chain_works() { assert_eq!( api(None).system_chain().unwrap(), - "testchain".to_owned() + "testchain".to_owned(), ); } @@ -141,7 +158,15 @@ fn system_chain_works() { fn system_properties_works() { assert_eq!( api(None).system_properties().unwrap(), - serde_json::map::Map::new() + serde_json::map::Map::new(), + ); +} + +#[test] +fn system_type_works() { + assert_eq!( + api(None).system_type().unwrap(), + Default::default(), ); } @@ -199,16 +224,40 @@ fn system_health() { ); } +#[test] +fn system_local_peer_id_works() { + assert_eq!( + wait_receiver(api(None).system_local_peer_id()), + "QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV".to_owned(), + ); +} + +#[test] +fn system_local_listen_addresses_works() { + assert_eq!( + wait_receiver(api(None).system_local_listen_addresses()), + vec![ + "/ip4/198.51.100.19/tcp/30333/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV".to_string(), + "/ip4/127.0.0.1/tcp/30334/ws/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV".to_string(), + ] + ); +} + #[test] fn system_peers() { + let mut runtime = tokio::runtime::current_thread::Runtime::new().unwrap(); + let peer_id = PeerId::random(); + let req = api(Status { + peer_id: peer_id.clone(), + peers: 1, + is_syncing: false, + is_dev: true, + }).system_peers(); + let res = runtime.block_on(req).unwrap(); + assert_eq!( - wait_receiver(api(Status { - peer_id: peer_id.clone(), - peers: 1, - is_syncing: false, - is_dev: true, - }).system_peers()), + res, vec![PeerInfo { peer_id: peer_id.to_base58(), roles: "FULL".into(), @@ -221,7 +270,10 @@ fn system_peers() { #[test] fn system_network_state() { - let res = wait_receiver(api(None).system_network_state()); + let mut runtime = tokio::runtime::current_thread::Runtime::new().unwrap(); + let req = api(None).system_network_state(); + let res = runtime.block_on(req).unwrap(); + assert_eq!( serde_json::from_value::(res).unwrap(), sc_network::network_state::NetworkState { diff --git a/client/rpc/src/testing.rs b/client/rpc/src/testing.rs new file mode 100644 index 0000000000000000000000000000000000000000..afca07a7fbe6a63048c9cfdc4d44cf2fcb933095 --- /dev/null +++ b/client/rpc/src/testing.rs @@ -0,0 +1,44 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Testing utils used by the RPC tests. + +use rpc::futures::future as future01; +use futures::{executor, compat::Future01CompatExt, FutureExt}; + +// Executor shared by all tests. +// +// This shared executor is used to prevent `Too many open files` errors +// on systems with a lot of cores. +lazy_static::lazy_static! { + static ref EXECUTOR: executor::ThreadPool = executor::ThreadPool::new() + .expect("Failed to create thread pool executor for tests"); +} + +type Boxed01Future01 = Box + Send + 'static>; + +pub struct TaskExecutor; +impl future01::Executor for TaskExecutor { + fn execute( + &self, + future: Boxed01Future01, + ) -> std::result::Result<(), future01::ExecuteError>{ + EXECUTOR.spawn_ok(future.compat().map(drop)); + Ok(()) + } +} diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 530142c745eeddb2501dbd46cfa81fec3bc6bb92..29f89635f663d5598056f663d21bd88f355b781e 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -1,27 +1,33 @@ [package] name = "sc-service" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate service. Starts a thread that spins up the network, client, and extrinsic pool. Manages communication between them." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [features] -default = ["rocksdb"] +default = ["db"] # 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 = ["sc-client-db/kvdb-rocksdb"] +db = ["sc-client-db/with-kvdb-rocksdb", "sc-client-db/with-parity-db"] wasmtime = [ "sc-executor/wasmtime", ] +# exposes the client type +test-helpers = [] [dependencies] derive_more = "0.99.2" futures01 = { package = "futures", version = "0.1.29" } -futures = "0.3.4" -futures-diagnose = "1.0" +futures = { version = "0.3.4", features = ["compat"] } +jsonrpc-pubsub = "14.2.0" +rand = "0.7.3" parking_lot = "0.10.0" lazy_static = "1.4.0" log = "0.4.8" @@ -29,52 +35,58 @@ slog = { version = "2.5.2", features = ["nested-values"] } futures-timer = "3.0.1" wasm-timer = "0.2" exit-future = "0.2.0" +pin-project = "0.4.8" +hash-db = "0.15.2" serde = "1.0.101" serde_json = "1.0.41" -sysinfo = "0.12.0" -target_info = "0.1.0" -sc-keystore = { version = "2.0.0-alpha.5", path = "../keystore" } -sp-io = { version = "2.0.0-alpha.5", path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../primitives/runtime" } -sp-utils = { version = "2.0.0-alpha.5", path = "../../primitives/utils" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../primitives/blockchain" } -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -sp-session = { version = "2.0.0-alpha.5", path = "../../primitives/session" } -sp-application-crypto = { version = "2.0.0-alpha.5", path = "../../primitives/application-crypto" } -sp-consensus = { version = "0.8.0-alpha.5", path = "../../primitives/consensus/common" } -sc-network = { version = "0.8.0-alpha.5", path = "../network" } -sc-chain-spec = { version = "2.0.0-alpha.5", path = "../chain-spec" } -sc-client-api = { version = "2.0.0-alpha.5", path = "../api" } -sc-client = { version = "0.8.0-alpha.5", path = "../" } -sp-api = { version = "2.0.0-alpha.5", path = "../../primitives/api" } -sc-client-db = { version = "0.8.0-alpha.5", path = "../db" } -codec = { package = "parity-scale-codec", version = "1.3.0" } -sc-executor = { version = "0.8.0-alpha.5", path = "../executor" } -sc-transaction-pool = { version = "2.0.0-alpha.5", path = "../transaction-pool" } -sp-transaction-pool = { version = "2.0.0-alpha.5", path = "../../primitives/transaction-pool" } -sc-rpc-server = { version = "2.0.0-alpha.5", path = "../rpc-servers" } -sc-rpc = { version = "2.0.0-alpha.5", path = "../rpc" } -sc-telemetry = { version = "2.0.0-alpha.5", path = "../telemetry" } -sc-offchain = { version = "2.0.0-alpha.5", path = "../offchain" } -parity-multiaddr = { package = "parity-multiaddr", version = "0.7.3" } -prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus" , version = "0.8.0-alpha.5"} -sc-tracing = { version = "2.0.0-alpha.5", path = "../tracing" } +sysinfo = "0.13.3" +sc-keystore = { version = "2.0.0-rc4", path = "../keystore" } +sp-io = { version = "2.0.0-rc4", path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc4", path = "../../primitives/runtime" } +sp-trie = { version = "2.0.0-rc4", path = "../../primitives/trie" } +sp-externalities = { version = "0.8.0-rc4", path = "../../primitives/externalities" } +sp-utils = { version = "2.0.0-rc4", path = "../../primitives/utils" } +sp-version = { version = "2.0.0-rc4", path = "../../primitives/version" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../primitives/blockchain" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +sp-session = { version = "2.0.0-rc4", path = "../../primitives/session" } +sp-state-machine = { version = "0.8.0-rc4", path = "../../primitives/state-machine" } +sp-application-crypto = { version = "2.0.0-rc4", path = "../../primitives/application-crypto" } +sp-consensus = { version = "0.8.0-rc4", path = "../../primitives/consensus/common" } +sc-network = { version = "0.8.0-rc4", path = "../network" } +sc-chain-spec = { version = "2.0.0-rc4", path = "../chain-spec" } +sc-light = { version = "2.0.0-rc4", path = "../light" } +sc-client-api = { version = "2.0.0-rc4", path = "../api" } +sp-api = { version = "2.0.0-rc4", path = "../../primitives/api" } +sc-client-db = { version = "0.8.0-rc4", default-features = false, path = "../db" } +codec = { package = "parity-scale-codec", version = "1.3.1" } +sc-executor = { version = "0.8.0-rc4", path = "../executor" } +sc-transaction-pool = { version = "2.0.0-rc4", path = "../transaction-pool" } +sp-transaction-pool = { version = "2.0.0-rc4", path = "../../primitives/transaction-pool" } +sc-rpc-server = { version = "2.0.0-rc4", path = "../rpc-servers" } +sc-rpc = { version = "2.0.0-rc4", path = "../rpc" } +sc-block-builder = { version = "0.8.0-rc4", path = "../block-builder" } +sp-block-builder = { version = "2.0.0-rc4", path = "../../primitives/block-builder" } +sc-informant = { version = "0.8.0-rc2", path = "../informant" } +sc-telemetry = { version = "2.0.0-rc4", path = "../telemetry" } +sc-offchain = { version = "2.0.0-rc4", path = "../offchain" } +prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.8.0-rc4"} +sc-tracing = { version = "2.0.0-rc4", path = "../tracing" } tracing = "0.1.10" -parity-util-mem = { version = "0.6.0", default-features = false, features = ["primitive-types"] } - +parity-util-mem = { version = "0.7.0", default-features = false, features = ["primitive-types"] } -[target.'cfg(any(unix, windows))'.dependencies] +[target.'cfg(all(any(unix, windows), not(target_os = "android"), not(target_os = "ios")))'.dependencies] netstat2 = "0.8.1" [target.'cfg(target_os = "linux")'.dependencies] procfs = '0.7.8' +[target.'cfg(not(target_os = "unknown"))'.dependencies] +tempfile = "3.1.0" +directories = "2.0.2" [dev-dependencies] -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../test-utils/runtime/client" } -sp-consensus-babe = { version = "0.8.0-alpha.5", path = "../../primitives/consensus/babe" } -grandpa = { version = "0.8.0-alpha.5", package = "sc-finality-grandpa", path = "../finality-grandpa" } -grandpa-primitives = { version = "2.0.0-alpha.5", package = "sp-finality-grandpa", path = "../../primitives/finality-grandpa" } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +substrate-test-runtime-client = { version = "2.0.0-rc4", path = "../../test-utils/runtime/client" } +sp-consensus-babe = { version = "0.8.0-rc4", path = "../../primitives/consensus/babe" } +grandpa = { version = "0.8.0-rc4", package = "sc-finality-grandpa", path = "../finality-grandpa" } +grandpa-primitives = { version = "2.0.0-rc4", package = "sp-finality-grandpa", path = "../../primitives/finality-grandpa" } diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 205f877999f82665e250914e9978df45fb5e802d..49d2d61f9c2bb7cfc0744ac7f51c2e97ef375ee1 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -1,60 +1,70 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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::Error, DEFAULT_PROTOCOL_ID, MallocSizeOfWasm}; -use crate::{TaskManagerBuilder, start_rpc_servers, build_network_future, TransactionPoolAdapter}; -use crate::status_sinks; -use crate::config::{Configuration, DatabaseConfig, KeystoreConfig, PrometheusConfig}; -use crate::metrics::MetricsService; +// along with this program. If not, see . + +use crate::{ + NetworkStatus, NetworkState, error::Error, DEFAULT_PROTOCOL_ID, MallocSizeOfWasm, + start_rpc_servers, build_network_future, TransactionPoolAdapter, TaskManager, SpawnTaskHandle, + status_sinks, metrics::MetricsService, + client::{light, Client, ClientConfig}, + config::{Configuration, KeystoreConfig, PrometheusConfig, OffchainWorkerConfig}, +}; use sc_client_api::{ - self, - BlockchainEvents, - backend::RemoteBackend, light::RemoteBlockchain, - execution_extensions::ExtensionsFactory, - ExecutorProvider, CallExecutor + self, light::RemoteBlockchain, execution_extensions::ExtensionsFactory, ExecutorProvider, + ForkBlocks, BadBlocks, CloneableSpawn, UsageProvider, backend::RemoteBackend, }; -use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedSender}; -use sc_client::Client; +use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedSender, TracingUnboundedReceiver}; use sc_chain_spec::get_extension; -use sp_consensus::import_queue::ImportQueue; +use sp_consensus::{ + block_validation::{BlockAnnounceValidator, DefaultBlockAnnounceValidator, Chain}, + import_queue::ImportQueue, +}; use futures::{ Future, FutureExt, StreamExt, future::ready, }; -use sc_keystore::{Store as Keystore}; +use jsonrpc_pubsub::manager::SubscriptionManager; +use sc_keystore::Store as Keystore; use log::{info, warn, error}; use sc_network::config::{Role, FinalityProofProvider, OnDemand, BoxFinalityProofRequestBuilder}; -use sc_network::{NetworkService, NetworkStateInfo}; +use sc_network::NetworkService; use parking_lot::{Mutex, RwLock}; use sp_runtime::generic::BlockId; use sp_runtime::traits::{ - Block as BlockT, NumberFor, SaturatedConversion, HashFor, -}; -use sp_api::ProvideRuntimeApi; -use sc_executor::{NativeExecutor, NativeExecutionDispatch}; -use std::{ - io::{Read, Write, Seek}, - marker::PhantomData, sync::Arc, pin::Pin + Block as BlockT, SaturatedConversion, HashFor, Zero, BlockIdTo, }; +use sp_api::{ProvideRuntimeApi, CallApiAt}; +use sc_executor::{NativeExecutor, NativeExecutionDispatch, RuntimeInfo}; +use std::{collections::HashMap, marker::PhantomData, sync::Arc, pin::Pin}; use wasm_timer::SystemTime; use sc_telemetry::{telemetry, SUBSTRATE_INFO}; -use sp_transaction_pool::{MaintainedTransactionPool, ChainEvent}; -use sp_blockchain; - -pub type BackgroundTask = Pin + Send>>; +use sp_transaction_pool::{LocalTransactionPool, MaintainedTransactionPool}; +use prometheus_endpoint::Registry; +use sc_client_db::{Backend, DatabaseSettings}; +use sp_core::traits::CodeExecutor; +use sp_runtime::BuildStorage; +use sc_client_api::{ + BlockBackend, BlockchainEvents, + backend::StorageProvider, + proof_provider::ProofProvider, + execution_extensions::ExecutionExtensions +}; +use sp_blockchain::{HeaderMetadata, HeaderBackend}; +use crate::{ServiceComponents, TelemetryOnConnectSinks, RpcHandlers, NetworkStatusSinks}; /// Aggregator for the components required to build a service. /// @@ -79,7 +89,7 @@ pub struct ServiceBuilder, backend: Arc, - tasks_builder: TaskManagerBuilder, + task_manager: TaskManager, keystore: Arc>, fetcher: Option, select_chain: Option, @@ -87,12 +97,61 @@ pub struct ServiceBuilder, finality_proof_provider: Option, transaction_pool: Arc, - rpc_extensions: TRpc, + rpc_extensions_builder: Box + Send>, remote_backend: Option>>, marker: PhantomData<(TBl, TRtApi)>, - background_tasks: Vec<(&'static str, BackgroundTask)>, + block_announce_validator_builder: Option) -> Box + Send> + Send>>, +} + +/// A utility trait for building an RPC extension given a `DenyUnsafe` instance. +/// This is useful since at service definition time we don't know whether the +/// specific interface where the RPC extension will be exposed is safe or not. +/// This trait allows us to lazily build the RPC extension whenever we bind the +/// service to an interface. +pub trait RpcExtensionBuilder { + /// The type of the RPC extension that will be built. + type Output: sc_rpc::RpcExtension; + + /// Returns an instance of the RPC extension for a particular `DenyUnsafe` + /// value, e.g. the RPC extension might not expose some unsafe methods. + fn build(&self, deny: sc_rpc::DenyUnsafe) -> Self::Output; +} + +impl RpcExtensionBuilder for F where + F: Fn(sc_rpc::DenyUnsafe) -> R, + R: sc_rpc::RpcExtension, +{ + type Output = R; + + fn build(&self, deny: sc_rpc::DenyUnsafe) -> Self::Output { + (*self)(deny) + } +} + +/// A utility struct for implementing an `RpcExtensionBuilder` given a cloneable +/// `RpcExtension`, the resulting builder will simply ignore the provided +/// `DenyUnsafe` instance and return a static `RpcExtension` instance. +struct NoopRpcExtensionBuilder(R); + +impl RpcExtensionBuilder for NoopRpcExtensionBuilder where + R: Clone + sc_rpc::RpcExtension, +{ + type Output = R; + + fn build(&self, _deny: sc_rpc::DenyUnsafe) -> Self::Output { + self.0.clone() + } +} + +impl From for NoopRpcExtensionBuilder where + R: sc_rpc::RpcExtension, +{ + fn from(e: R) -> NoopRpcExtensionBuilder { + NoopRpcExtensionBuilder(e) + } } + /// Full client type. pub type TFullClient = Client< TFullBackend, @@ -105,7 +164,7 @@ pub type TFullClient = Client< pub type TFullBackend = sc_client_db::Backend; /// Full client call executor type. -pub type TFullCallExecutor = sc_client::LocalCallExecutor< +pub type TFullCallExecutor = crate::client::LocalCallExecutor< sc_client_db::Backend, NativeExecutor, >; @@ -119,19 +178,19 @@ pub type TLightClient = Client< >; /// Light client backend type. -pub type TLightBackend = sc_client::light::backend::Backend< +pub type TLightBackend = sc_light::Backend< sc_client_db::light::LightStorage, HashFor, >; /// Light call executor type. -pub type TLightCallExecutor = sc_client::light::call_executor::GenesisCallExecutor< - sc_client::light::backend::Backend< +pub type TLightCallExecutor = sc_light::GenesisCallExecutor< + sc_light::Backend< sc_client_db::light::LightStorage, HashFor >, - sc_client::LocalCallExecutor< - sc_client::light::backend::Backend< + crate::client::LocalCallExecutor< + sc_light::Backend< sc_client_db::light::LightStorage, HashFor >, @@ -143,7 +202,7 @@ type TFullParts = ( TFullClient, Arc>, Arc>, - TaskManagerBuilder, + TaskManager, ); /// Creates a new full client for the given config. @@ -168,10 +227,12 @@ fn new_full_parts( password.clone() )?, KeystoreConfig::InMemory => Keystore::new_in_memory(), - KeystoreConfig::None => return Err("No keystore config provided!".into()), }; - let tasks_builder = TaskManagerBuilder::new(); + let task_manager = { + let registry = config.prometheus_config.as_ref().map(|cfg| &cfg.registry); + TaskManager::new(config.task_executor.clone(), registry)? + }; let executor = NativeExecutor::::new( config.wasm_method, @@ -179,12 +240,12 @@ fn new_full_parts( config.max_runtime_instances, ); - let chain_spec = config.expect_chain_spec(); - let fork_blocks = get_extension::>(chain_spec.extensions()) + let chain_spec = &config.chain_spec; + let fork_blocks = get_extension::>(chain_spec.extensions()) .cloned() .unwrap_or_default(); - let bad_blocks = get_extension::>(chain_spec.extensions()) + let bad_blocks = get_extension::>(chain_spec.extensions()) .cloned() .unwrap_or_default(); @@ -194,15 +255,7 @@ fn new_full_parts( state_cache_child_ratio: config.state_cache_child_ratio.map(|v| (v, 100)), pruning: config.pruning.clone(), - source: match config.expect_database() { - DatabaseConfig::Path { path, cache_size } => - sc_client_db::DatabaseSettingsSrc::Path { - path: path.clone(), - cache_size: cache_size.clone().map(|u| u as usize), - }, - DatabaseConfig::Custom(db) => - sc_client_db::DatabaseSettingsSrc::Custom(db.clone()), - }, + source: config.database.clone(), }; let extensions = sc_client_api::execution_extensions::ExecutionExtensions::new( @@ -210,19 +263,69 @@ fn new_full_parts( Some(keystore.clone()), ); - sc_client_db::new_client( + new_client( db_config, executor, - config.expect_chain_spec().as_storage_builder(), + chain_spec.as_storage_builder(), fork_blocks, bad_blocks, extensions, - Box::new(tasks_builder.spawn_handle()), + Box::new(task_manager.spawn_handle()), config.prometheus_config.as_ref().map(|config| config.registry.clone()), + ClientConfig { + offchain_worker_enabled : config.offchain_worker.enabled , + offchain_indexing_api: config.offchain_worker.indexing_enabled, + }, )? }; - Ok((client, backend, keystore, tasks_builder)) + Ok((client, backend, keystore, task_manager)) +} + + +/// Create an instance of db-backed client. +pub fn new_client( + settings: DatabaseSettings, + executor: E, + genesis_storage: &dyn BuildStorage, + fork_blocks: ForkBlocks, + bad_blocks: BadBlocks, + execution_extensions: ExecutionExtensions, + spawn_handle: Box, + prometheus_registry: Option, + config: ClientConfig, +) -> Result<( + crate::client::Client< + Backend, + crate::client::LocalCallExecutor, E>, + Block, + RA, + >, + Arc>, +), + sp_blockchain::Error, +> + where + Block: BlockT, + E: CodeExecutor + RuntimeInfo, +{ + const CANONICALIZATION_DELAY: u64 = 4096; + + let backend = Arc::new(Backend::new(settings, CANONICALIZATION_DELAY)?); + let executor = crate::client::LocalCallExecutor::new(backend.clone(), executor, spawn_handle, config.clone()); + Ok(( + crate::client::Client::new( + backend.clone(), + executor, + genesis_storage, + fork_blocks, + bad_blocks, + execution_extensions, + prometheus_registry, + config, + )?, + backend, + )) } impl ServiceBuilder<(), (), (), (), (), (), (), (), (), (), ()> { @@ -242,7 +345,7 @@ impl ServiceBuilder<(), (), (), (), (), (), (), (), (), (), ()> { (), TFullBackend, >, Error> { - let (client, backend, keystore, tasks_builder) = new_full_parts(&config)?; + let (client, backend, keystore, task_manager) = new_full_parts(&config)?; let client = Arc::new(client); @@ -251,16 +354,16 @@ impl ServiceBuilder<(), (), (), (), (), (), (), (), (), (), ()> { client, backend, keystore, - tasks_builder, + task_manager, fetcher: None, select_chain: None, import_queue: (), finality_proof_request_builder: None, finality_proof_provider: None, transaction_pool: Arc::new(()), - rpc_extensions: Default::default(), + rpc_extensions_builder: Box::new(|_| ()), remote_backend: None, - background_tasks: Default::default(), + block_announce_validator_builder: None, marker: PhantomData, }) } @@ -281,7 +384,10 @@ impl ServiceBuilder<(), (), (), (), (), (), (), (), (), (), ()> { (), TLightBackend, >, Error> { - let tasks_builder = TaskManagerBuilder::new(); + let task_manager = { + let registry = config.prometheus_config.as_ref().map(|cfg| &cfg.registry); + TaskManager::new(config.task_executor.clone(), registry)? + }; let keystore = match &config.keystore { KeystoreConfig::Path { path, password } => Keystore::open( @@ -289,7 +395,6 @@ impl ServiceBuilder<(), (), (), (), (), (), (), (), (), (), ()> { password.clone() )?, KeystoreConfig::InMemory => Keystore::new_in_memory(), - KeystoreConfig::None => return Err("No keystore config provided!".into()), }; let executor = NativeExecutor::::new( @@ -304,34 +409,26 @@ impl ServiceBuilder<(), (), (), (), (), (), (), (), (), (), ()> { state_cache_child_ratio: config.state_cache_child_ratio.map(|v| (v, 100)), pruning: config.pruning.clone(), - source: match config.expect_database() { - DatabaseConfig::Path { path, cache_size } => - sc_client_db::DatabaseSettingsSrc::Path { - path: path.clone(), - cache_size: cache_size.clone().map(|u| u as usize), - }, - DatabaseConfig::Custom(db) => - sc_client_db::DatabaseSettingsSrc::Custom(db.clone()), - }, + source: config.database.clone(), }; sc_client_db::light::LightStorage::new(db_settings)? }; - let light_blockchain = sc_client::light::new_light_blockchain(db_storage); + let light_blockchain = sc_light::new_light_blockchain(db_storage); let fetch_checker = Arc::new( - sc_client::light::new_fetch_checker::<_, TBl, _>( + sc_light::new_fetch_checker::<_, TBl, _>( light_blockchain.clone(), executor.clone(), - Box::new(tasks_builder.spawn_handle()), + Box::new(task_manager.spawn_handle()), ), ); let fetcher = Arc::new(sc_network::config::OnDemand::new(fetch_checker)); - let backend = sc_client::light::new_light_backend(light_blockchain); + let backend = sc_light::new_light_backend(light_blockchain); let remote_blockchain = backend.remote_blockchain(); - let client = Arc::new(sc_client::light::new_light( + let client = Arc::new(light::new_light( backend.clone(), - config.expect_chain_spec().as_storage_builder(), + config.chain_spec.as_storage_builder(), executor, - Box::new(tasks_builder.spawn_handle()), + Box::new(task_manager.spawn_handle()), config.prometheus_config.as_ref().map(|config| config.registry.clone()), )?); @@ -339,7 +436,7 @@ impl ServiceBuilder<(), (), (), (), (), (), (), (), (), (), ()> { config, client, backend, - tasks_builder, + task_manager, keystore, fetcher: Some(fetcher.clone()), select_chain: None, @@ -347,17 +444,38 @@ impl ServiceBuilder<(), (), (), (), (), (), (), (), (), (), ()> { finality_proof_request_builder: None, finality_proof_provider: None, transaction_pool: Arc::new(()), - rpc_extensions: Default::default(), + rpc_extensions_builder: Box::new(|_| ()), remote_backend: Some(remote_blockchain), - background_tasks: Default::default(), + block_announce_validator_builder: None, marker: PhantomData, }) } } impl - ServiceBuilder { + ServiceBuilder< + TBl, + TRtApi, + TCl, + TFchr, + TSc, + TImpQu, + TFprb, + TFpp, + TExPool, + TRpc, + Backend + > +{ + /// Returns a reference to the configuration that was stored in this builder. + pub fn config(&self) -> &Configuration { + &self.config + } + + /// Returns a reference to the optional prometheus registry that was stored in this builder. + pub fn prometheus_registry(&self) -> Option<&Registry> { + self.config.prometheus_config.as_ref().map(|config| &config.registry) + } /// Returns a reference to the client that was stored in this builder. pub fn client(&self) -> &Arc { @@ -398,6 +516,16 @@ impl self.remote_backend.clone() } + /// Returns a spawn handle created by the task manager. + pub fn spawn_handle(&self) -> SpawnTaskHandle { + self.task_manager.spawn_handle() + } + + /// Consume the builder and return the parts needed for chain operations. + pub fn to_chain_ops_parts(self) -> (Arc, Arc, TImpQu, TaskManager) { + (self.client, self.backend, self.import_queue, self.task_manager) + } + /// Defines which head-of-chain strategy to use. pub fn with_opt_select_chain( self, @@ -412,7 +540,7 @@ impl config: self.config, client: self.client, backend: self.backend, - tasks_builder: self.tasks_builder, + task_manager: self.task_manager, keystore: self.keystore, fetcher: self.fetcher, select_chain, @@ -420,9 +548,9 @@ impl finality_proof_request_builder: self.finality_proof_request_builder, finality_proof_provider: self.finality_proof_provider, transaction_pool: self.transaction_pool, - rpc_extensions: self.rpc_extensions, + rpc_extensions_builder: self.rpc_extensions_builder, remote_backend: self.remote_backend, - background_tasks: self.background_tasks, + block_announce_validator_builder: self.block_announce_validator_builder, marker: self.marker, }) } @@ -439,7 +567,7 @@ impl /// Defines which import queue to use. pub fn with_import_queue( self, - builder: impl FnOnce(&Configuration, Arc, Option, Arc) + builder: impl FnOnce(&Configuration, Arc, Option, Arc, &SpawnTaskHandle, Option<&Registry>) -> Result ) -> Result, Error> @@ -448,14 +576,16 @@ impl &self.config, self.client.clone(), self.select_chain.clone(), - self.transaction_pool.clone() + self.transaction_pool.clone(), + &self.task_manager.spawn_handle(), + self.config.prometheus_config.as_ref().map(|config| &config.registry), )?; Ok(ServiceBuilder { config: self.config, client: self.client, backend: self.backend, - tasks_builder: self.tasks_builder, + task_manager: self.task_manager, keystore: self.keystore, fetcher: self.fetcher, select_chain: self.select_chain, @@ -463,9 +593,9 @@ impl finality_proof_request_builder: self.finality_proof_request_builder, finality_proof_provider: self.finality_proof_provider, transaction_pool: self.transaction_pool, - rpc_extensions: self.rpc_extensions, + rpc_extensions_builder: self.rpc_extensions_builder, remote_backend: self.remote_backend, - background_tasks: self.background_tasks, + block_announce_validator_builder: self.block_announce_validator_builder, marker: self.marker, }) } @@ -493,7 +623,7 @@ impl config: self.config, client: self.client, backend: self.backend, - tasks_builder: self.tasks_builder, + task_manager: self.task_manager, keystore: self.keystore, fetcher: self.fetcher, select_chain: self.select_chain, @@ -501,9 +631,9 @@ impl finality_proof_request_builder: self.finality_proof_request_builder, finality_proof_provider, transaction_pool: self.transaction_pool, - rpc_extensions: self.rpc_extensions, + rpc_extensions_builder: self.rpc_extensions_builder, remote_backend: self.remote_backend, - background_tasks: self.background_tasks, + block_announce_validator_builder: self.block_announce_validator_builder, marker: self.marker, }) } @@ -538,6 +668,8 @@ impl Option, Option, Arc, + &SpawnTaskHandle, + Option<&Registry>, ) -> Result<(UImpQu, Option), Error> ) -> Result, Error> @@ -548,14 +680,16 @@ impl self.backend.clone(), self.fetcher.clone(), self.select_chain.clone(), - self.transaction_pool.clone() + self.transaction_pool.clone(), + &self.task_manager.spawn_handle(), + self.config.prometheus_config.as_ref().map(|config| &config.registry), )?; Ok(ServiceBuilder { config: self.config, client: self.client, backend: self.backend, - tasks_builder: self.tasks_builder, + task_manager: self.task_manager, keystore: self.keystore, fetcher: self.fetcher, select_chain: self.select_chain, @@ -563,9 +697,9 @@ impl finality_proof_request_builder: fprb, finality_proof_provider: self.finality_proof_provider, transaction_pool: self.transaction_pool, - rpc_extensions: self.rpc_extensions, + rpc_extensions_builder: self.rpc_extensions_builder, remote_backend: self.remote_backend, - background_tasks: self.background_tasks, + block_announce_validator_builder: self.block_announce_validator_builder, marker: self.marker, }) } @@ -580,41 +714,33 @@ impl Option, Option, Arc, + &SpawnTaskHandle, + Option<&Registry>, ) -> 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) + self.with_import_queue_and_opt_fprb(|cfg, cl, b, f, sc, tx, tb, pr| + builder(cfg, cl, b, f, sc, tx, tb, pr) .map(|(q, f)| (q, Some(f))) ) } /// Defines which transaction pool to use. pub fn with_transaction_pool( - mut self, + self, transaction_pool_builder: impl FnOnce( - sc_transaction_pool::txpool::Options, - Arc, - Option, - ) -> Result<(UExPool, Option), Error> + &Self, + ) -> Result, Error>, ) -> Result, Error> where TSc: Clone, TFchr: Clone { - let (transaction_pool, background_task) = transaction_pool_builder( - self.config.transaction_pool.clone(), - self.client.clone(), - self.fetcher.clone(), - )?; - - if let Some(background_task) = background_task{ - self.background_tasks.push(("txpool-background", background_task)); - } + let transaction_pool = transaction_pool_builder(&self)?; Ok(ServiceBuilder { config: self.config, client: self.client, - tasks_builder: self.tasks_builder, + task_manager: self.task_manager, backend: self.backend, keystore: self.keystore, fetcher: self.fetcher, @@ -622,28 +748,37 @@ impl import_queue: self.import_queue, finality_proof_request_builder: self.finality_proof_request_builder, finality_proof_provider: self.finality_proof_provider, - transaction_pool: Arc::new(transaction_pool), - rpc_extensions: self.rpc_extensions, + transaction_pool: transaction_pool, + rpc_extensions_builder: self.rpc_extensions_builder, remote_backend: self.remote_backend, - background_tasks: self.background_tasks, + block_announce_validator_builder: self.block_announce_validator_builder, marker: self.marker, }) } - /// Defines the RPC extensions to use. - pub fn with_rpc_extensions( + /// Defines the RPC extension builder to use. Unlike `with_rpc_extensions`, + /// this method is useful in situations where the RPC extensions need to + /// access to a `DenyUnsafe` instance to avoid exposing sensitive methods. + pub fn with_rpc_extensions_builder( self, - rpc_ext_builder: impl FnOnce(&Self) -> Result, - ) -> Result, Error> - where TSc: Clone, TFchr: Clone { - let rpc_extensions = rpc_ext_builder(&self)?; + rpc_extensions_builder: impl FnOnce(&Self) -> Result, + ) -> Result< + ServiceBuilder, + Error, + > + where + TSc: Clone, + TFchr: Clone, + URpcBuilder: RpcExtensionBuilder + Send + 'static, + URpc: sc_rpc::RpcExtension, + { + let rpc_extensions_builder = rpc_extensions_builder(&self)?; Ok(ServiceBuilder { config: self.config, client: self.client, backend: self.backend, - tasks_builder: self.tasks_builder, + task_manager: self.task_manager, keystore: self.keystore, fetcher: self.fetcher, select_chain: self.select_chain, @@ -651,55 +786,64 @@ impl finality_proof_request_builder: self.finality_proof_request_builder, finality_proof_provider: self.finality_proof_provider, transaction_pool: self.transaction_pool, - rpc_extensions, + rpc_extensions_builder: Box::new(rpc_extensions_builder), remote_backend: self.remote_backend, - background_tasks: self.background_tasks, + block_announce_validator_builder: self.block_announce_validator_builder, marker: self.marker, }) } -} -/// Implemented on `ServiceBuilder`. Allows running block commands, such as import/export/validate -/// components to the builder. -pub trait ServiceBuilderCommand { - /// Block type this API operates on. - type Block: BlockT; - /// Native execution dispatch required by some commands. - type NativeDispatch: NativeExecutionDispatch + 'static; - /// Starts the process of importing blocks. - fn import_blocks( + /// Defines the RPC extensions to use. + pub fn with_rpc_extensions( self, - input: impl Read + Seek + Send + 'static, - force: bool, - ) -> Pin> + Send>>; + rpc_extensions: impl FnOnce(&Self) -> Result, + ) -> Result< + ServiceBuilder, + Error, + > + where + TSc: Clone, + TFchr: Clone, + URpc: Clone + sc_rpc::RpcExtension + Send + 'static, + { + let rpc_extensions = rpc_extensions(&self)?; + self.with_rpc_extensions_builder(|_| Ok(NoopRpcExtensionBuilder::from(rpc_extensions))) + } - /// Performs the blocks export. - fn export_blocks( - self, - output: impl Write + 'static, - from: NumberFor, - to: Option>, - binary: bool - ) -> Pin>>>; - - /// Performs a revert of `blocks` blocks. - fn revert_chain( - &self, - blocks: NumberFor - ) -> Result<(), Error>; - - /// Re-validate known block. - fn check_block( + /// Defines the `BlockAnnounceValidator` to use. `DefaultBlockAnnounceValidator` will be used by + /// default. + pub fn with_block_announce_validator( self, - block: BlockId - ) -> Pin> + Send>>; + block_announce_validator_builder: + impl FnOnce(Arc) -> Box + Send> + Send + 'static, + ) -> Result, Error> + where TSc: Clone, TFchr: Clone { + Ok(ServiceBuilder { + config: self.config, + client: self.client, + backend: self.backend, + task_manager: self.task_manager, + 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, + transaction_pool: self.transaction_pool, + rpc_extensions_builder: self.rpc_extensions_builder, + remote_backend: self.remote_backend, + block_announce_validator_builder: Some(Box::new(block_announce_validator_builder)), + marker: self.marker, + }) + } } -impl +impl ServiceBuilder< TBl, TRtApi, - Client, + TCl, Arc>, TSc, TImpQu, @@ -709,8 +853,12 @@ ServiceBuilder< TRpc, TBackend, > where - Client: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: + TCl: ProvideRuntimeApi + HeaderMetadata + Chain + + BlockBackend + BlockIdTo + ProofProvider + + HeaderBackend + BlockchainEvents + ExecutorProvider + UsageProvider + + StorageProvider + CallApiAt + + Send + 'static, + >::Api: sp_api::Metadata + sc_offchain::OffchainWorkerApi + sp_transaction_pool::runtime_api::TaggedTransactionQueue + @@ -720,11 +868,10 @@ ServiceBuilder< TBl: BlockT, TRtApi: 'static + Send + Sync, TBackend: 'static + sc_client_api::backend::Backend + Send, - TExec: 'static + sc_client::CallExecutor + Send + Sync + Clone, TSc: Clone, TImpQu: 'static + ImportQueue, TExPool: MaintainedTransactionPool::Hash> + MallocSizeOfWasm + 'static, - TRpc: sc_rpc::RpcExtension + Clone, + TRpc: sc_rpc::RpcExtension, { /// Set an ExecutionExtensionsFactory @@ -733,27 +880,12 @@ ServiceBuilder< Ok(self) } - /// Builds the service. - pub fn build(self) -> Result, - TSc, - NetworkStatus, - NetworkService::Hash>, - TExPool, - sc_offchain::OffchainWorkers< - Client, - TBackend::OffchainStorage, - TBl - >, - >, Error> - where TExec: CallExecutor, - { + fn build_common(self) -> Result, Error> { let ServiceBuilder { marker: _, mut config, client, - tasks_builder, + mut task_manager, fetcher: on_demand, backend, keystore, @@ -762,25 +894,19 @@ ServiceBuilder< finality_proof_request_builder, finality_proof_provider, transaction_pool, - rpc_extensions, + rpc_extensions_builder, remote_backend, - background_tasks, + block_announce_validator_builder, } = self; + let chain_info = client.usage_info().chain; + sp_session::generate_initial_session_keys( client.clone(), - &BlockId::Hash(client.chain_info().best_hash), + &BlockId::Hash(chain_info.best_hash), config.dev_key_seed.clone().map(|s| vec![s]).unwrap_or_default(), )?; - // A side-channel for essential tasks to communicate shutdown. - let (essential_failed_tx, essential_failed_rx) = tracing_unbounded("mpsc_essential_tasks"); - - let import_queue = Box::new(import_queue); - let chain_info = client.chain_info(); - let chain_spec = config.expect_chain_spec(); - - let version = config.full_version(); info!("📦 Highest known block at #{}", chain_info.best_number); telemetry!( SUBSTRATE_INFO; @@ -789,179 +915,69 @@ ServiceBuilder< "best" => ?chain_info.best_hash ); - // make transaction pool available for off-chain runtime calls. - client.execution_extensions() - .register_transaction_pool(Arc::downgrade(&transaction_pool) as _); - - let transaction_pool_adapter = Arc::new(TransactionPoolAdapter { - imports_external_transactions: !matches!(config.role, Role::Light), - pool: transaction_pool.clone(), - client: client.clone(), - executor: tasks_builder.spawn_handle(), - }); - - let protocol_id = { - let protocol_id_full = match 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(); - sc_network::config::ProtocolId::from(protocol_id_full) - }; + let (system_rpc_tx, system_rpc_rx) = tracing_unbounded("mpsc_system_rpc"); - let block_announce_validator = - Box::new(sp_consensus::block_validation::DefaultBlockAnnounceValidator::new(client.clone())); + let (network, network_status_sinks, network_future) = build_network( + &config, client.clone(), transaction_pool.clone(), task_manager.spawn_handle(), + on_demand.clone(), block_announce_validator_builder, finality_proof_request_builder, + finality_proof_provider, system_rpc_rx, import_queue + )?; - let network_params = sc_network::config::Params { - role: config.role.clone(), - executor: { - let spawn_handle = tasks_builder.spawn_handle(); - Some(Box::new(move |fut| { - spawn_handle.spawn("libp2p-node", fut); - })) - }, - 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, - block_announce_validator, - metrics_registry: config.prometheus_config.as_ref().map(|config| config.registry.clone()) - }; + let spawn_handle = task_manager.spawn_handle(); - let has_bootnodes = !network_params.network_config.boot_nodes.is_empty(); - let network_mut = sc_network::NetworkWorker::new(network_params)?; - let network = network_mut.service().clone(); - let network_status_sinks = Arc::new(Mutex::new(status_sinks::StatusSinks::new())); + // The network worker is responsible for gathering all network messages and processing + // them. This is quite a heavy task, and at the time of the writing of this comment it + // frequently happens that this future takes several seconds or in some situations + // even more than a minute until it has processed its entire queue. This is clearly an + // issue, and ideally we would like to fix the network future to take as little time as + // possible, but we also take the extra harm-prevention measure to execute the networking + // future using `spawn_blocking`. + spawn_handle.spawn_blocking( + "network-worker", + network_future + ); let offchain_storage = backend.offchain_storage(); - let offchain_workers = match (config.offchain_worker, offchain_storage.clone()) { - (true, Some(db)) => { + let offchain_workers = match (config.offchain_worker.clone(), offchain_storage.clone()) { + (OffchainWorkerConfig {enabled: true, .. }, Some(db)) => { Some(Arc::new(sc_offchain::OffchainWorkers::new(client.clone(), db))) }, - (true, None) => { + (OffchainWorkerConfig {enabled: true, .. }, None) => { warn!("Offchain workers disabled, due to lack of offchain storage support in backend."); None }, _ => None, }; - let spawn_handle = tasks_builder.spawn_handle(); - - // Spawn background tasks which were stacked during the - // service building. - for (title, background_task) in background_tasks { - spawn_handle.spawn(title, background_task); - } - - { - // block notifications - let txpool = Arc::downgrade(&transaction_pool); - let offchain = offchain_workers.as_ref().map(Arc::downgrade); - let notifications_spawn_handle = tasks_builder.spawn_handle(); - let network_state_info: Arc = network.clone(); - let is_validator = config.role.is_authority(); - - let (import_stream, finality_stream) = ( - client.import_notification_stream().map(|n| ChainEvent::NewBlock { - id: BlockId::Hash(n.hash), - header: n.header, - retracted: n.retracted, - is_new_best: n.is_new_best, - }), - client.finality_notification_stream().map(|n| ChainEvent::Finalized { - hash: n.hash - }) - ); - let events = futures::stream::select(import_stream, finality_stream) - .for_each(move |event| { - // offchain worker is only interested in block import events - if let ChainEvent::NewBlock { ref header, is_new_best, .. } = event { - let offchain = offchain.as_ref().and_then(|o| o.upgrade()); - match offchain { - Some(offchain) if is_new_best => { - notifications_spawn_handle.spawn( - "offchain-on-block", - offchain.on_block_imported( - &header, - network_state_info.clone(), - is_validator, - ), - ); - }, - Some(_) => log::debug!( - target: "sc_offchain", - "Skipping offchain workers for non-canon block: {:?}", - header, - ), - _ => {}, - } - }; - - let txpool = txpool.upgrade(); - if let Some(txpool) = txpool.as_ref() { - notifications_spawn_handle.spawn( - "txpool-maintain", - txpool.maintain(event), - ); - } - - ready(()) - }); + // Inform the tx pool about imported and finalized blocks. + spawn_handle.spawn( + "txpool-notifications", + sc_transaction_pool::notification_future(client.clone(), transaction_pool.clone()), + ); + // Inform the offchain worker about new imported blocks + if let Some(offchain) = offchain_workers.clone() { spawn_handle.spawn( - "txpool-and-offchain-notif", - events, + "offchain-notifications", + sc_offchain::notification_future( + config.role.is_authority(), + client.clone(), + offchain, + task_manager.spawn_handle(), + network.clone() + ) ); } - { - // extrinsic notifications - let network = Arc::downgrade(&network); - let transaction_pool_ = transaction_pool.clone(); - let events = transaction_pool.import_notification_stream() - .for_each(move |hash| { - if let Some(network) = network.upgrade() { - network.propagate_extrinsic(hash); - } - let status = transaction_pool_.status(); - telemetry!(SUBSTRATE_INFO; "txpool.import"; - "ready" => status.ready, - "future" => status.future - ); - ready(()) - }); - - spawn_handle.spawn( - "telemetry-on-block", - events, - ); - } + spawn_handle.spawn( + "on-transaction-imported", + transaction_notifications(transaction_pool.clone(), network.clone()), + ); // Prometheus metrics. - let mut metrics_service = if let Some(PrometheusConfig { port, registry }) = config.prometheus_config.clone() { + let metrics_service = if let Some(PrometheusConfig { port, registry }) = config.prometheus_config.clone() { // Set static metrics. - - - let role_bits = match config.role { - Role::Full => 1u64, - Role::Light => 2u64, - Role::Sentry { .. } => 3u64, - Role::Authority { .. } => 4u64, - }; - let metrics = MetricsService::with_prometheus( - ®istry, - &config.name, - &config.impl_version, - role_bits, - )?; + let metrics = MetricsService::with_prometheus(®istry, &config)?; spawn_handle.spawn( "prometheus-endpoint", prometheus_endpoint::init_prometheus(port, registry).map(drop) @@ -973,163 +989,42 @@ ServiceBuilder< }; // Periodically notify the telemetry. - let transaction_pool_ = transaction_pool.clone(); - let client_ = client.clone(); - let (state_tx, state_rx) = tracing_unbounded::<(NetworkStatus<_>, NetworkState)>("mpsc_netstat1"); - 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_.usage_info(); - metrics_service.tick( - &info, - &transaction_pool_.status(), - &net_status, - ); - ready(()) - }); - - spawn_handle.spawn( - "telemetry-periodic-send", - tel_task, - ); + spawn_handle.spawn("telemetry-periodic-send", telemetry_periodic_send( + client.clone(), transaction_pool.clone(), metrics_service, network_status_sinks.clone() + )); // Periodically send the network state to the telemetry. - let (netstat_tx, netstat_rx) = tracing_unbounded::<(NetworkStatus<_>, NetworkState)>("mpsc_netstat2"); - 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, - ); - ready(()) - }); spawn_handle.spawn( "telemetry-periodic-network-state", - tel_task_2, + telemetry_periodic_network_state(network_status_sinks.clone()), ); // RPC - let (system_rpc_tx, system_rpc_rx) = tracing_unbounded("mpsc_system_rpc"); - let gen_handler = || { - use sc_rpc::{chain, state, author, system, offchain}; - - let system_info = sc_rpc::system::SystemInfo { - chain_name: chain_spec.name().into(), - impl_name: config.impl_name.into(), - impl_version: config.impl_version.into(), - properties: chain_spec.properties().clone(), - }; - - let subscriptions = sc_rpc::Subscriptions::new(Arc::new(tasks_builder.spawn_handle())); - - let (chain, state) = if let (Some(remote_backend), Some(on_demand)) = - (remote_backend.as_ref(), on_demand.as_ref()) { - // Light clients - let chain = sc_rpc::chain::new_light( - client.clone(), - subscriptions.clone(), - remote_backend.clone(), - on_demand.clone() - ); - let state = sc_rpc::state::new_light( - client.clone(), - subscriptions.clone(), - remote_backend.clone(), - on_demand.clone() - ); - (chain, state) - - } else { - // Full nodes - let chain = sc_rpc::chain::new_full(client.clone(), subscriptions.clone()); - let state = sc_rpc::state::new_full(client.clone(), subscriptions.clone()); - (chain, state) - }; - - let author = sc_rpc::author::Author::new( - client.clone(), - transaction_pool.clone(), - subscriptions, - keystore.clone(), - ); - let system = system::System::new(system_info, system_rpc_tx.clone()); - - match offchain_storage.clone() { - Some(storage) => { - let offchain = sc_rpc::offchain::Offchain::new(storage); - sc_rpc_server::rpc_handler(( - state::StateApi::to_delegate(state), - chain::ChainApi::to_delegate(chain), - offchain::OffchainApi::to_delegate(offchain), - author::AuthorApi::to_delegate(author), - system::SystemApi::to_delegate(system), - rpc_extensions.clone(), - )) - }, - None => sc_rpc_server::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)?; - - spawn_handle.spawn( - "network-worker", - build_network_future( - config.role.clone(), - network_mut, - client.clone(), - network_status_sinks.clone(), - system_rpc_rx, - has_bootnodes, - config.announce_block, - ), + let gen_handler = |deny_unsafe: sc_rpc::DenyUnsafe| gen_handler( + deny_unsafe, &config, &task_manager, client.clone(), transaction_pool.clone(), + keystore.clone(), on_demand.clone(), remote_backend.clone(), &*rpc_extensions_builder, + offchain_storage.clone(), system_rpc_tx.clone() ); + let rpc = start_rpc_servers(&config, gen_handler)?; + // This is used internally, so don't restrict access to unsafe RPC + let rpc_handlers = Arc::new(RpcHandlers(gen_handler(sc_rpc::DenyUnsafe::No))); let telemetry_connection_sinks: Arc>>> = Default::default(); // Telemetry let telemetry = config.telemetry_endpoints.clone().map(|endpoints| { - let is_authority = config.role.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.expect_chain_spec().name().to_owned(); - let telemetry_connection_sinks_ = telemetry_connection_sinks.clone(); - let telemetry = sc_telemetry::init_telemetry(sc_telemetry::TelemetryConfig { + let genesis_hash = match client.block_hash(Zero::zero()) { + Ok(Some(hash)) => hash, + _ => Default::default(), + }; + + let (telemetry, future) = build_telemetry( + &mut config, endpoints, - wasm_external_transport: config.telemetry_external_transport.take(), - }); - let startup_time = SystemTime::UNIX_EPOCH.elapsed() - .map(|dur| dur.as_millis()) - .unwrap_or(0); - let future = telemetry.clone() - .for_each(move |event| { - // Safe-guard in case we add more events in the future. - let sc_telemetry::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, - "startup_time" => startup_time, - "network_id" => network_id.clone() - ); - - telemetry_connection_sinks_.lock().retain(|sink| { - sink.unbounded_send(()).is_ok() - }); - ready(()) - }); + telemetry_connection_sinks.clone(), + network.clone(), + genesis_hash, + ); spawn_handle.spawn( "telemetry-worker", @@ -1150,23 +1045,369 @@ ServiceBuilder< } } - Ok(Service { + // Spawn informant task + spawn_handle.spawn("informant", sc_informant::build( + client.clone(), + network_status_sinks.clone(), + transaction_pool.clone(), + config.informant_output_format, + )); + + task_manager.keep_alive((telemetry, config.base_path, rpc, rpc_handlers.clone())); + + Ok(ServiceComponents { client, - task_manager: tasks_builder.into_task_manager(config.task_executor.ok_or(Error::TaskExecutorRequired)?), + task_manager, network, - network_status_sinks, select_chain, transaction_pool, - essential_failed_tx, - essential_failed_rx, rpc_handlers, - _rpc: rpc, - _telemetry: telemetry, - _offchain_workers: offchain_workers, - _telemetry_on_connect_sinks: telemetry_connection_sinks.clone(), keystore, - marker: PhantomData::, - prometheus_registry: config.prometheus_config.map(|config| config.registry) + offchain_workers, + telemetry_on_connect_sinks: TelemetryOnConnectSinks(telemetry_connection_sinks), + network_status_sinks: NetworkStatusSinks::new(network_status_sinks), + prometheus_registry: config.prometheus_config.map(|config| config.registry), }) } + + /// Builds the light service. + pub fn build_light(self) -> Result, Error> { + self.build_common() + } +} + +impl +ServiceBuilder< + TBl, + TRtApi, + TCl, + Arc>, + TSc, + TImpQu, + BoxFinalityProofRequestBuilder, + Arc>, + TExPool, + TRpc, + TBackend, +> where + TCl: ProvideRuntimeApi + HeaderMetadata + Chain + + BlockBackend + BlockIdTo + ProofProvider + + HeaderBackend + BlockchainEvents + ExecutorProvider + UsageProvider + + StorageProvider + CallApiAt + + Send + 'static, + >::Api: + sp_api::Metadata + + sc_offchain::OffchainWorkerApi + + sp_transaction_pool::runtime_api::TaggedTransactionQueue + + sp_session::SessionKeys + + sp_api::ApiErrorExt + + sp_api::ApiExt, + TBl: BlockT, + TRtApi: 'static + Send + Sync, + TBackend: 'static + sc_client_api::backend::Backend + Send, + TSc: Clone, + TImpQu: 'static + ImportQueue, + TExPool: MaintainedTransactionPool::Hash> + + LocalTransactionPool::Hash> + + MallocSizeOfWasm + + 'static, + TRpc: sc_rpc::RpcExtension, +{ + + /// Builds the full service. + pub fn build_full(self) -> Result, Error> { + self.build_common() + } +} + +async fn transaction_notifications( + transaction_pool: Arc, + network: Arc::Hash>> +) + where + TBl: BlockT, + TExPool: MaintainedTransactionPool::Hash>, +{ + // transaction notifications + transaction_pool.import_notification_stream() + .for_each(move |hash| { + network.propagate_transaction(hash); + let status = transaction_pool.status(); + telemetry!(SUBSTRATE_INFO; "txpool.import"; + "ready" => status.ready, + "future" => status.future + ); + ready(()) + }) + .await; +} + +// Periodically notify the telemetry. +async fn telemetry_periodic_send( + client: Arc, + transaction_pool: Arc, + mut metrics_service: MetricsService, + network_status_sinks: Arc, NetworkState)>> +) + where + TBl: BlockT, + TCl: ProvideRuntimeApi + UsageProvider, + TExPool: MaintainedTransactionPool::Hash>, +{ + let (state_tx, state_rx) = tracing_unbounded::<(NetworkStatus<_>, NetworkState)>("mpsc_netstat1"); + network_status_sinks.push(std::time::Duration::from_millis(5000), state_tx); + state_rx.for_each(move |(net_status, _)| { + let info = client.usage_info(); + metrics_service.tick( + &info, + &transaction_pool.status(), + &net_status, + ); + ready(()) + }).await; +} + +async fn telemetry_periodic_network_state( + network_status_sinks: Arc, NetworkState)>> +) { + // Periodically send the network state to the telemetry. + let (netstat_tx, netstat_rx) = tracing_unbounded::<(NetworkStatus<_>, NetworkState)>("mpsc_netstat2"); + network_status_sinks.push(std::time::Duration::from_secs(30), netstat_tx); + netstat_rx.for_each(move |(_, network_state)| { + telemetry!( + SUBSTRATE_INFO; + "system.network_state"; + "state" => network_state, + ); + ready(()) + }).await; +} + +fn build_telemetry( + config: &mut Configuration, + endpoints: sc_telemetry::TelemetryEndpoints, + telemetry_connection_sinks: Arc>>>, + network: Arc::Hash>>, + genesis_hash: ::Hash, +) -> (sc_telemetry::Telemetry, Pin + Send>>) { + let is_authority = config.role.is_authority(); + let network_id = network.local_peer_id().to_base58(); + let name = config.network.node_name.clone(); + let impl_name = config.impl_name.clone(); + let impl_version = config.impl_version.clone(); + let chain_name = config.chain_spec.name().to_owned(); + let telemetry = sc_telemetry::init_telemetry(sc_telemetry::TelemetryConfig { + endpoints, + wasm_external_transport: config.telemetry_external_transport.take(), + }); + let startup_time = SystemTime::UNIX_EPOCH.elapsed() + .map(|dur| dur.as_millis()) + .unwrap_or(0); + let future = telemetry.clone() + .for_each(move |event| { + // Safe-guard in case we add more events in the future. + let sc_telemetry::TelemetryEvent::Connected = event; + + telemetry!(SUBSTRATE_INFO; "system.connected"; + "name" => name.clone(), + "implementation" => impl_name.clone(), + "version" => impl_version.clone(), + "config" => "", + "chain" => chain_name.clone(), + "genesis_hash" => ?genesis_hash, + "authority" => is_authority, + "startup_time" => startup_time, + "network_id" => network_id.clone() + ); + + telemetry_connection_sinks.lock().retain(|sink| { + sink.unbounded_send(()).is_ok() + }); + ready(()) + }) + .boxed(); + + (telemetry, future) +} + +fn gen_handler( + deny_unsafe: sc_rpc::DenyUnsafe, + config: &Configuration, + task_manager: &TaskManager, + client: Arc, + transaction_pool: Arc, + keystore: Arc>, + on_demand: Option>>, + remote_backend: Option>>, + rpc_extensions_builder: &(dyn RpcExtensionBuilder + Send), + offchain_storage: Option<>::OffchainStorage>, + system_rpc_tx: TracingUnboundedSender> +) -> jsonrpc_pubsub::PubSubHandler + where + TBl: BlockT, + TCl: ProvideRuntimeApi + BlockchainEvents + HeaderBackend + + HeaderMetadata + ExecutorProvider + + CallApiAt + ProofProvider + + StorageProvider + BlockBackend + Send + Sync + 'static, + TExPool: MaintainedTransactionPool::Hash> + 'static, + TBackend: sc_client_api::backend::Backend + 'static, + TRpc: sc_rpc::RpcExtension, + >::Api: + sp_session::SessionKeys + + sp_api::Metadata, +{ + use sc_rpc::{chain, state, author, system, offchain}; + + let system_info = sc_rpc::system::SystemInfo { + chain_name: config.chain_spec.name().into(), + impl_name: config.impl_name.clone(), + impl_version: config.impl_version.clone(), + properties: config.chain_spec.properties(), + chain_type: config.chain_spec.chain_type(), + }; + + let subscriptions = SubscriptionManager::new(Arc::new(task_manager.spawn_handle())); + + let (chain, state, child_state) = if let (Some(remote_backend), Some(on_demand)) = + (remote_backend, on_demand) { + // Light clients + let chain = sc_rpc::chain::new_light( + client.clone(), + subscriptions.clone(), + remote_backend.clone(), + on_demand.clone() + ); + let (state, child_state) = sc_rpc::state::new_light( + client.clone(), + subscriptions.clone(), + remote_backend.clone(), + on_demand.clone() + ); + (chain, state, child_state) + + } else { + // Full nodes + let chain = sc_rpc::chain::new_full(client.clone(), subscriptions.clone()); + let (state, child_state) = sc_rpc::state::new_full(client.clone(), subscriptions.clone()); + (chain, state, child_state) + }; + + let author = sc_rpc::author::Author::new( + client.clone(), + transaction_pool.clone(), + subscriptions, + keystore.clone(), + deny_unsafe, + ); + let system = system::System::new(system_info, system_rpc_tx.clone(), deny_unsafe); + + let maybe_offchain_rpc = offchain_storage.clone() + .map(|storage| { + let offchain = sc_rpc::offchain::Offchain::new(storage, deny_unsafe); + // FIXME: Use plain Option (don't collect into HashMap) when we upgrade to jsonrpc 14.1 + // https://github.com/paritytech/jsonrpc/commit/20485387ed06a48f1a70bf4d609a7cde6cf0accf + let delegate = offchain::OffchainApi::to_delegate(offchain); + delegate.into_iter().collect::>() + }).unwrap_or_default(); + + sc_rpc_server::rpc_handler(( + state::StateApi::to_delegate(state), + state::ChildStateApi::to_delegate(child_state), + chain::ChainApi::to_delegate(chain), + maybe_offchain_rpc, + author::AuthorApi::to_delegate(author), + system::SystemApi::to_delegate(system), + rpc_extensions_builder.build(deny_unsafe), + )) +} + +fn build_network( + config: &Configuration, + client: Arc, + transaction_pool: Arc, + spawn_handle: SpawnTaskHandle, + on_demand: Option>>, + block_announce_validator_builder: Option) -> Box + Send> + Send + >>, + finality_proof_request_builder: Option>, + finality_proof_provider: Option>>, + system_rpc_rx: TracingUnboundedReceiver>, + import_queue: TImpQu +) -> Result< + ( + Arc::Hash>>, + Arc, NetworkState)>>, + Pin + Send>> + ), + Error +> + where + TBl: BlockT, + TCl: ProvideRuntimeApi + HeaderMetadata + Chain + + BlockBackend + BlockIdTo + ProofProvider + + HeaderBackend + BlockchainEvents + 'static, + TExPool: MaintainedTransactionPool::Hash> + 'static, + TImpQu: ImportQueue + 'static, +{ + let transaction_pool_adapter = Arc::new(TransactionPoolAdapter { + imports_external_transactions: !matches!(config.role, Role::Light), + pool: transaction_pool.clone(), + client: client.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(); + sc_network::config::ProtocolId::from(protocol_id_full) + }; + + let block_announce_validator = if let Some(f) = block_announce_validator_builder { + f(client.clone()) + } else { + Box::new(DefaultBlockAnnounceValidator) + }; + + let network_params = sc_network::config::Params { + role: config.role.clone(), + executor: { + Some(Box::new(move |fut| { + spawn_handle.spawn("libp2p-node", fut); + })) + }, + 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: Box::new(import_queue), + protocol_id, + block_announce_validator, + metrics_registry: config.prometheus_config.as_ref().map(|config| config.registry.clone()) + }; + + let has_bootnodes = !network_params.network_config.boot_nodes.is_empty(); + let network_mut = sc_network::NetworkWorker::new(network_params)?; + let network = network_mut.service().clone(); + let network_status_sinks = Arc::new(status_sinks::StatusSinks::new()); + + let future = build_network_future( + config.role.clone(), + network_mut, + client.clone(), + network_status_sinks.clone(), + system_rpc_rx, + has_bootnodes, + config.announce_block, + ).boxed(); + + Ok((network, network_status_sinks, future)) } diff --git a/client/service/src/chain_ops.rs b/client/service/src/chain_ops.rs deleted file mode 100644 index 12fae3224108a66feed5e593e8de50bb97c8a9cf..0000000000000000000000000000000000000000 --- a/client/service/src/chain_ops.rs +++ /dev/null @@ -1,299 +0,0 @@ -// Copyright 2017-2020 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 utilities. - -use crate::error; -use crate::builder::{ServiceBuilderCommand, ServiceBuilder}; -use crate::error::Error; -use sc_chain_spec::ChainSpec; -use log::{warn, info}; -use futures::{future, prelude::*}; -use sp_runtime::traits::{ - Block as BlockT, NumberFor, One, Zero, Header, SaturatedConversion -}; -use sp_runtime::generic::{BlockId, SignedBlock}; -use codec::{Decode, Encode, IoReader}; -use sc_client::{Client, LocalCallExecutor}; -use sp_consensus::{ - BlockOrigin, - import_queue::{IncomingBlock, Link, BlockImportError, BlockImportResult, ImportQueue}, -}; -use sc_executor::{NativeExecutor, NativeExecutionDispatch}; - -use std::{io::{Read, Write, Seek}, pin::Pin}; -use sc_client_api::BlockBackend; - -/// Build a chain spec json -pub fn build_spec(spec: &dyn ChainSpec, raw: bool) -> error::Result { - Ok(spec.as_json(raw)?) -} - -impl< - TBl, TRtApi, TBackend, - TExecDisp, TFchr, TSc, TImpQu, TFprb, TFpp, - TExPool, TRpc, Backend -> ServiceBuilderCommand for ServiceBuilder< - TBl, TRtApi, - Client>, TBl, TRtApi>, - TFchr, TSc, TImpQu, TFprb, TFpp, TExPool, TRpc, Backend -> where - TBl: BlockT, - TBackend: 'static + sc_client_api::backend::Backend + Send, - TExecDisp: 'static + NativeExecutionDispatch, - TImpQu: 'static + ImportQueue, - TRtApi: 'static + Send + Sync, -{ - type Block = TBl; - type NativeDispatch = TExecDisp; - - fn import_blocks( - self, - input: impl Read + Seek + Send + 'static, - force: bool, - ) -> Pin> + Send>> { - struct WaitLink { - imported_blocks: u64, - has_error: bool, - } - - 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; - } - } - } - } - - let client = self.client; - let mut queue = self.import_queue; - - let mut io_reader_input = IoReader(input); - let mut count = None::; - let mut read_block_count = 0; - let mut link = WaitLink::new(); - - // Importing blocks is implemented as a future, because we want the operation to be - // interruptible. - // - // Every time we read a block from the input or import a bunch of blocks from the import - // queue, the `Future` re-schedules itself and returns `Poll::Pending`. - // This makes it possible either to interleave other operations in-between the block imports, - // or to stop the operation completely. - let import = future::poll_fn(move |cx| { - // Start by reading the number of blocks if not done so already. - let count = match count { - Some(c) => c, - None => { - let c: u64 = match Decode::decode(&mut io_reader_input) { - Ok(c) => c, - Err(err) => { - let err = format!("Error reading file: {}", err); - return std::task::Poll::Ready(Err(From::from(err))); - }, - }; - info!("📦 Importing {} blocks", c); - count = Some(c); - c - } - }; - - // Read blocks from the input. - if read_block_count < count { - match SignedBlock::::decode(&mut io_reader_input) { - Ok(signed) => { - let (header, extrinsics) = signed.block.deconstruct(); - let hash = header.hash(); - // import queue handles verification and importing it into the client - queue.import_blocks(BlockOrigin::File, vec![ - IncomingBlock:: { - hash, - header: Some(header), - body: Some(extrinsics), - justification: signed.justification, - origin: None, - allow_missing_state: false, - import_existing: force, - } - ]); - } - Err(e) => { - warn!("Error reading block data at {}: {}", read_block_count, e); - return std::task::Poll::Ready(Ok(())); - } - } - - read_block_count += 1; - if read_block_count % 1000 == 0 { - info!("#{} blocks were added to the queue", read_block_count); - } - - cx.waker().wake_by_ref(); - return std::task::Poll::Pending; - } - - let blocks_before = link.imported_blocks; - queue.poll_actions(cx, &mut link); - - if link.has_error { - info!( - "Stopping after #{} blocks because of an error", - link.imported_blocks, - ); - return std::task::Poll::Ready(Ok(())); - } - - if link.imported_blocks / 1000 != blocks_before / 1000 { - info!( - "#{} blocks were imported (#{} left)", - link.imported_blocks, - count - link.imported_blocks - ); - } - - if link.imported_blocks >= count { - info!("🎉 Imported {} blocks. Best: #{}", read_block_count, client.chain_info().best_number); - return std::task::Poll::Ready(Ok(())); - - } else { - // Polling the import queue will re-schedule the task when ready. - return std::task::Poll::Pending; - } - }); - Box::pin(import) - } - - fn export_blocks( - self, - mut output: impl Write + 'static, - from: NumberFor, - to: Option>, - binary: bool - ) -> Pin>>> { - let client = self.client; - let mut block = from; - - let last = match to { - Some(v) if v.is_zero() => One::one(), - Some(v) => v, - None => client.chain_info().best_number, - }; - - let mut wrote_header = false; - - // Exporting blocks is implemented as a future, because we want the operation to be - // interruptible. - // - // Every time we write a block to the output, the `Future` re-schedules itself and returns - // `Poll::Pending`. - // This makes it possible either to interleave other operations in-between the block exports, - // or to stop the operation completely. - let export = future::poll_fn(move |cx| { - if last < block { - return std::task::Poll::Ready(Err("Invalid block range specified".into())); - } - - if !wrote_header { - info!("Exporting blocks from #{} to #{}", block, last); - if binary { - let last_: u64 = last.saturated_into::(); - let block_: u64 = block.saturated_into::(); - let len: u64 = last_ - block_ + 1; - output.write_all(&len.encode())?; - } - wrote_header = true; - } - - match client.block(&BlockId::number(block))? { - Some(block) => { - if binary { - output.write_all(&block.encode())?; - } else { - serde_json::to_writer(&mut output, &block) - .map_err(|e| format!("Error writing JSON: {}", e))?; - } - }, - // Reached end of the chain. - None => return std::task::Poll::Ready(Ok(())), - } - if (block % 10000.into()).is_zero() { - info!("#{}", block); - } - if block == last { - return std::task::Poll::Ready(Ok(())); - } - block += One::one(); - - // Re-schedule the task in order to continue the operation. - cx.waker().wake_by_ref(); - std::task::Poll::Pending - }); - - Box::pin(export) - } - - fn revert_chain( - &self, - blocks: NumberFor - ) -> Result<(), Error> { - let reverted = self.client.revert(blocks)?; - let info = self.client.chain_info(); - - if reverted.is_zero() { - info!("There aren't any non-finalized blocks to revert."); - } else { - info!("Reverted {} blocks. Best: #{} ({})", reverted, info.best_number, info.best_hash); - } - Ok(()) - } - - fn check_block( - self, - block_id: BlockId - ) -> Pin> + Send>> { - match self.client.block(&block_id) { - Ok(Some(block)) => { - let mut buf = Vec::new(); - 1u64.encode_to(&mut buf); - block.encode_to(&mut buf); - let reader = std::io::Cursor::new(buf); - self.import_blocks(reader, true) - } - Ok(None) => Box::pin(future::err("Unknown block".into())), - Err(e) => Box::pin(future::err(format!("Error reading block: {:?}", e).into())), - } - } -} diff --git a/client/service/src/chain_ops/check_block.rs b/client/service/src/chain_ops/check_block.rs new file mode 100644 index 0000000000000000000000000000000000000000..34baeb55445a88ec41d2e729ecdc4c4eb782c1f6 --- /dev/null +++ b/client/service/src/chain_ops/check_block.rs @@ -0,0 +1,51 @@ +// Copyright 2017-2020 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; +use futures::{future, prelude::*}; +use sp_runtime::traits::Block as BlockT; +use sp_runtime::generic::BlockId; +use codec::Encode; +use sp_consensus::import_queue::ImportQueue; +use sc_client_api::{BlockBackend, UsageProvider}; + +use std::pin::Pin; +use std::sync::Arc; +use crate::chain_ops::import_blocks; + +/// Re-validate known block. +pub fn check_block( + client: Arc, + import_queue: IQ, + block_id: BlockId +) -> Pin> + Send>> +where + C: BlockBackend + UsageProvider + Send + Sync + 'static, + B: BlockT + for<'de> serde::Deserialize<'de>, + IQ: ImportQueue + 'static, +{ + match client.block(&block_id) { + Ok(Some(block)) => { + let mut buf = Vec::new(); + 1u64.encode_to(&mut buf); + block.encode_to(&mut buf); + let reader = std::io::Cursor::new(buf); + import_blocks(client, import_queue, reader, true, true) + } + Ok(None) => Box::pin(future::err("Unknown block".into())), + Err(e) => Box::pin(future::err(format!("Error reading block: {:?}", e).into())), + } +} diff --git a/client/service/src/chain_ops/export_blocks.rs b/client/service/src/chain_ops/export_blocks.rs new file mode 100644 index 0000000000000000000000000000000000000000..2f32cbf7fbdb7cf08cdb1fdb618ac5d6c0ef5cec --- /dev/null +++ b/client/service/src/chain_ops/export_blocks.rs @@ -0,0 +1,104 @@ +// Copyright 2017-2020 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; +use log::info; +use futures::{future, prelude::*}; +use sp_runtime::traits::{ + Block as BlockT, NumberFor, One, Zero, SaturatedConversion +}; +use sp_runtime::generic::BlockId; +use codec::Encode; + +use std::{io::Write, pin::Pin}; +use sc_client_api::{BlockBackend, UsageProvider}; +use std::sync::Arc; +use std::task::Poll; + +/// Performs the blocks export. +pub fn export_blocks( + client: Arc, + mut output: impl Write + 'static, + from: NumberFor, + to: Option>, + binary: bool +) -> Pin>>> +where + C: BlockBackend + UsageProvider + 'static, + B: BlockT, +{ + let mut block = from; + + let last = match to { + Some(v) if v.is_zero() => One::one(), + Some(v) => v, + None => client.usage_info().chain.best_number, + }; + + let mut wrote_header = false; + + // Exporting blocks is implemented as a future, because we want the operation to be + // interruptible. + // + // Every time we write a block to the output, the `Future` re-schedules itself and returns + // `Poll::Pending`. + // This makes it possible either to interleave other operations in-between the block exports, + // or to stop the operation completely. + let export = future::poll_fn(move |cx| { + let client = &client; + + if last < block { + return Poll::Ready(Err("Invalid block range specified".into())); + } + + if !wrote_header { + info!("Exporting blocks from #{} to #{}", block, last); + if binary { + let last_: u64 = last.saturated_into::(); + let block_: u64 = block.saturated_into::(); + let len: u64 = last_ - block_ + 1; + output.write_all(&len.encode())?; + } + wrote_header = true; + } + + match client.block(&BlockId::number(block))? { + Some(block) => { + if binary { + output.write_all(&block.encode())?; + } else { + serde_json::to_writer(&mut output, &block) + .map_err(|e| format!("Error writing JSON: {}", e))?; + } + }, + // Reached end of the chain. + None => return Poll::Ready(Ok(())), + } + if (block % 10000.into()).is_zero() { + info!("#{}", block); + } + if block == last { + return Poll::Ready(Ok(())); + } + block += One::one(); + + // Re-schedule the task in order to continue the operation. + cx.waker().wake_by_ref(); + Poll::Pending + }); + + Box::pin(export) +} diff --git a/client/service/src/chain_ops/export_raw_state.rs b/client/service/src/chain_ops/export_raw_state.rs new file mode 100644 index 0000000000000000000000000000000000000000..3fe44dbdb142d29f1737896e21f7a077f1dd68f8 --- /dev/null +++ b/client/service/src/chain_ops/export_raw_state.rs @@ -0,0 +1,71 @@ +// Copyright 2020 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; +use sp_runtime::traits::Block as BlockT; +use sp_runtime::generic::BlockId; +use sp_core::storage::{StorageKey, well_known_keys, ChildInfo, Storage, StorageChild, StorageMap}; +use sc_client_api::{StorageProvider, UsageProvider}; + +use std::{collections::HashMap, sync::Arc}; + +/// Export the raw state at the given `block`. If `block` is `None`, the +/// best block will be used. +pub fn export_raw_state( + client: Arc, + block: Option>, +) -> Result +where + C: UsageProvider + StorageProvider, + B: BlockT, + BA: sc_client_api::backend::Backend, +{ + let block = block.unwrap_or_else( + || BlockId::Hash(client.usage_info().chain.best_hash) + ); + + let empty_key = StorageKey(Vec::new()); + let mut top_storage = client.storage_pairs(&block, &empty_key)?; + let mut children_default = HashMap::new(); + + // Remove all default child storage roots from the top storage and collect the child storage + // pairs. + while let Some(pos) = top_storage + .iter() + .position(|(k, _)| k.0.starts_with(well_known_keys::DEFAULT_CHILD_STORAGE_KEY_PREFIX)) { + let (key, _) = top_storage.swap_remove(pos); + + let key = StorageKey( + key.0[well_known_keys::DEFAULT_CHILD_STORAGE_KEY_PREFIX.len()..].to_vec(), + ); + let child_info = ChildInfo::new_default(&key.0); + + let keys = client.child_storage_keys(&block, &child_info, &empty_key)?; + let mut pairs = StorageMap::new(); + keys.into_iter().try_for_each(|k| { + if let Some(value) = client.child_storage(&block, &child_info, &k)? { + pairs.insert(k.0, value.0); + } + + Ok::<_, Error>(()) + })?; + + children_default.insert(key.0, StorageChild { child_info, data: pairs }); + } + + let top = top_storage.into_iter().map(|(k, v)| (k.0, v.0)).collect(); + Ok(Storage { top, children_default }) +} diff --git a/client/service/src/chain_ops/import_blocks.rs b/client/service/src/chain_ops/import_blocks.rs new file mode 100644 index 0000000000000000000000000000000000000000..46ad0d0501d93f5292274a734a511d8c249be583 --- /dev/null +++ b/client/service/src/chain_ops/import_blocks.rs @@ -0,0 +1,472 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use crate::error; +use crate::error::Error; +use sc_chain_spec::ChainSpec; +use log::{warn, info}; +use futures::{future, prelude::*}; +use sp_runtime::traits::{ + Block as BlockT, NumberFor, Zero, Header, MaybeSerializeDeserialize, +}; +use sp_runtime::generic::SignedBlock; +use codec::{Decode, IoReader as CodecIoReader}; +use sp_consensus::{ + BlockOrigin, + import_queue::{IncomingBlock, Link, BlockImportError, BlockImportResult, ImportQueue}, +}; + +use std::{io::{Read, Seek}, pin::Pin}; +use std::time::{Duration, Instant}; +use futures_timer::Delay; +use std::task::Poll; +use serde_json::{de::IoRead as JsonIoRead, Deserializer, StreamDeserializer}; +use std::convert::{TryFrom, TryInto}; +use sp_runtime::traits::{CheckedDiv, Saturating}; +use sc_client_api::UsageProvider; + +/// Number of blocks we will add to the queue before waiting for the queue to catch up. +const MAX_PENDING_BLOCKS: u64 = 1_024; + +/// Number of milliseconds to wait until next poll. +const DELAY_TIME: u64 = 2_000; + +/// Number of milliseconds that must have passed between two updates. +const TIME_BETWEEN_UPDATES: u64 = 3_000; + +use std::sync::Arc; + +/// Build a chain spec json +pub fn build_spec(spec: &dyn ChainSpec, raw: bool) -> error::Result { + spec.as_json(raw).map_err(Into::into) +} + + +/// Helper enum that wraps either a binary decoder (from parity-scale-codec), or a JSON decoder +/// (from serde_json). Implements the Iterator Trait, calling `next()` will decode the next +/// SignedBlock and return it. +enum BlockIter where + R: std::io::Read + std::io::Seek, +{ + Binary { + // Total number of blocks we are expecting to decode. + num_expected_blocks: u64, + // Number of blocks we have decoded thus far. + read_block_count: u64, + // Reader to the data, used for decoding new blocks. + reader: CodecIoReader, + }, + Json { + // Nubmer of blocks we have decoded thus far. + read_block_count: u64, + // Stream to the data, used for decoding new blocks. + reader: StreamDeserializer<'static, JsonIoRead, SignedBlock>, + }, +} + +impl BlockIter where + R: Read + Seek + 'static, + B: BlockT + MaybeSerializeDeserialize, +{ + fn new(input: R, binary: bool) -> Result { + if binary { + let mut reader = CodecIoReader(input); + // If the file is encoded in binary format, it is expected to first specify the number + // of blocks that are going to be decoded. We read it and add it to our enum struct. + let num_expected_blocks: u64 = Decode::decode(&mut reader) + .map_err(|e| format!("Failed to decode the number of blocks: {:?}", e))?; + Ok(BlockIter::Binary { + num_expected_blocks, + read_block_count: 0, + reader, + }) + } else { + let stream_deser = Deserializer::from_reader(input) + .into_iter::>(); + Ok(BlockIter::Json { + reader: stream_deser, + read_block_count: 0, + }) + } + } + + /// Returns the number of blocks read thus far. + fn read_block_count(&self) -> u64 { + match self { + BlockIter::Binary { read_block_count, .. } + | BlockIter::Json { read_block_count, .. } + => *read_block_count, + } + } + + /// Returns the total number of blocks to be imported, if possible. + fn num_expected_blocks(&self) -> Option { + match self { + BlockIter::Binary { num_expected_blocks, ..} => Some(*num_expected_blocks), + BlockIter::Json {..} => None + } + } +} + +impl Iterator for BlockIter where + R: Read + Seek + 'static, + B: BlockT + MaybeSerializeDeserialize, +{ + type Item = Result, String>; + + fn next(&mut self) -> Option { + match self { + BlockIter::Binary { num_expected_blocks, read_block_count, reader } => { + if read_block_count < num_expected_blocks { + let block_result: Result, _> = SignedBlock::::decode(reader) + .map_err(|e| e.to_string()); + *read_block_count += 1; + Some(block_result) + } else { + // `read_block_count` == `num_expected_blocks` so we've read enough blocks. + None + } + } + BlockIter::Json { reader, read_block_count } => { + let res = Some(reader.next()?.map_err(|e| e.to_string())); + *read_block_count += 1; + res + } + } + } +} + +/// Imports the SignedBlock to the queue. +fn import_block_to_queue( + signed_block: SignedBlock, + queue: &mut TImpQu, + force: bool +) where + TBl: BlockT + MaybeSerializeDeserialize, + TImpQu: 'static + ImportQueue, +{ + let (header, extrinsics) = signed_block.block.deconstruct(); + let hash = header.hash(); + // import queue handles verification and importing it into the client. + queue.import_blocks(BlockOrigin::File, vec![ + IncomingBlock:: { + hash, + header: Some(header), + body: Some(extrinsics), + justification: signed_block.justification, + origin: None, + allow_missing_state: false, + import_existing: force, + } + ]); +} + +/// Returns true if we have imported every block we were supposed to import, else returns false. +fn importing_is_done( + num_expected_blocks: Option, + read_block_count: u64, + imported_blocks: u64 +) -> bool { + if let Some(num_expected_blocks) = num_expected_blocks { + imported_blocks >= num_expected_blocks + } else { + imported_blocks >= read_block_count + } +} + +/// Structure used to log the block importing speed. +struct Speedometer { + best_number: NumberFor, + last_number: Option>, + last_update: Instant, +} + +impl Speedometer { + /// Creates a fresh Speedometer. + fn new() -> Self { + Self { + best_number: NumberFor::::from(0), + last_number: None, + last_update: Instant::now(), + } + } + + /// Calculates `(best_number - last_number) / (now - last_update)` and + /// logs the speed of import. + fn display_speed(&self) { + // Number of milliseconds elapsed since last time. + let elapsed_ms = { + let elapsed = self.last_update.elapsed(); + let since_last_millis = elapsed.as_secs() * 1000; + let since_last_subsec_millis = elapsed.subsec_millis() as u64; + since_last_millis + since_last_subsec_millis + }; + + // Number of blocks that have been imported since last time. + let diff = match self.last_number { + None => return, + Some(n) => self.best_number.saturating_sub(n) + }; + + if let Ok(diff) = TryInto::::try_into(diff) { + // If the number of blocks can be converted to a regular integer, then it's easy: just + // do the math and turn it into a `f64`. + let speed = diff.saturating_mul(10_000).checked_div(u128::from(elapsed_ms)) + .map_or(0.0, |s| s as f64) / 10.0; + info!("📦 Current best block: {} ({:4.1} bps)", self.best_number, speed); + } else { + // If the number of blocks can't be converted to a regular integer, then we need a more + // algebraic approach and we stay within the realm of integers. + let one_thousand = NumberFor::::from(1_000); + let elapsed = NumberFor::::from( + >::try_from(elapsed_ms).unwrap_or(u32::max_value()) + ); + + let speed = diff.saturating_mul(one_thousand).checked_div(&elapsed) + .unwrap_or_else(Zero::zero); + info!("📦 Current best block: {} ({} bps)", self.best_number, speed) + } + } + + /// Updates the Speedometer. + fn update(&mut self, best_number: NumberFor) { + self.last_number = Some(self.best_number); + self.best_number = best_number; + self.last_update = Instant::now(); + } + + // If more than TIME_BETWEEN_UPDATES has elapsed since last update, + // then print and update the speedometer. + fn notify_user(&mut self, best_number: NumberFor) { + let delta = Duration::from_millis(TIME_BETWEEN_UPDATES); + if Instant::now().duration_since(self.last_update) >= delta { + self.display_speed(); + self.update(best_number); + } + } +} + +/// Different State that the `import_blocks` future could be in. +enum ImportState where + R: Read + Seek + 'static, + B: BlockT + MaybeSerializeDeserialize, +{ + /// We are reading from the BlockIter structure, adding those blocks to the queue if possible. + Reading{block_iter: BlockIter}, + /// The queue is full (contains at least MAX_PENDING_BLOCKS blocks) and we are waiting for it to + /// catch up. + WaitingForImportQueueToCatchUp{ + block_iter: BlockIter, + delay: Delay, + block: SignedBlock + }, + // We have added all the blocks to the queue but they are still being processed. + WaitingForImportQueueToFinish{ + num_expected_blocks: Option, + read_block_count: u64, + delay: Delay, + }, +} + +/// Starts the process of importing blocks. +pub fn import_blocks( + client: Arc, + mut import_queue: IQ, + input: impl Read + Seek + Send + 'static, + force: bool, + binary: bool, +) -> Pin> + Send>> +where + C: UsageProvider + Send + Sync + 'static, + B: BlockT + for<'de> serde::Deserialize<'de>, + IQ: ImportQueue + 'static, +{ + struct WaitLink { + imported_blocks: u64, + has_error: bool, + } + + impl WaitLink { + fn new() -> WaitLink { + WaitLink { + imported_blocks: 0, + has_error: false, + } + } + } + + impl Link for WaitLink { + fn blocks_processed( + &mut self, + imported: usize, + _num_expected_blocks: 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; + } + } + } + } + + let mut link = WaitLink::new(); + let block_iter_res: Result, String> = BlockIter::new(input, binary); + + let block_iter = match block_iter_res { + Ok(block_iter) => block_iter, + Err(e) => { + // We've encountered an error while creating the block iterator + // so we can just return a future that returns an error. + return future::ready(Err(Error::Other(e))).boxed() + } + }; + + let mut state = Some(ImportState::Reading{block_iter}); + let mut speedometer = Speedometer::::new(); + + // Importing blocks is implemented as a future, because we want the operation to be + // interruptible. + // + // Every time we read a block from the input or import a bunch of blocks from the import + // queue, the `Future` re-schedules itself and returns `Poll::Pending`. + // This makes it possible either to interleave other operations in-between the block imports, + // or to stop the operation completely. + let import = future::poll_fn(move |cx| { + let client = &client; + let queue = &mut import_queue; + match state.take().expect("state should never be None; qed") { + ImportState::Reading{mut block_iter} => { + match block_iter.next() { + None => { + // The iterator is over: we now need to wait for the import queue to finish. + let num_expected_blocks = block_iter.num_expected_blocks(); + let read_block_count = block_iter.read_block_count(); + let delay = Delay::new(Duration::from_millis(DELAY_TIME)); + state = Some(ImportState::WaitingForImportQueueToFinish { + num_expected_blocks, read_block_count, delay + }); + }, + Some(block_result) => { + let read_block_count = block_iter.read_block_count(); + match block_result { + Ok(block) => { + if read_block_count - link.imported_blocks >= MAX_PENDING_BLOCKS { + // The queue is full, so do not add this block and simply wait + // until the queue has made some progress. + let delay = Delay::new(Duration::from_millis(DELAY_TIME)); + state = Some(ImportState::WaitingForImportQueueToCatchUp { + block_iter, delay, block + }); + } else { + // Queue is not full, we can keep on adding blocks to the queue. + import_block_to_queue(block, queue, force); + state = Some(ImportState::Reading{block_iter}); + } + } + Err(e) => { + return Poll::Ready( + Err(Error::Other( + format!("Error reading block #{}: {}", read_block_count, e) + ))) + } + } + } + } + }, + ImportState::WaitingForImportQueueToCatchUp{block_iter, mut delay, block} => { + let read_block_count = block_iter.read_block_count(); + if read_block_count - link.imported_blocks >= MAX_PENDING_BLOCKS { + // Queue is still full, so wait until there is room to insert our block. + match Pin::new(&mut delay).poll(cx) { + Poll::Pending => { + state = Some(ImportState::WaitingForImportQueueToCatchUp { + block_iter, delay, block + }); + return Poll::Pending + }, + Poll::Ready(_) => { + delay.reset(Duration::from_millis(DELAY_TIME)); + }, + } + state = Some(ImportState::WaitingForImportQueueToCatchUp { + block_iter, delay, block + }); + } else { + // Queue is no longer full, so we can add our block to the queue. + import_block_to_queue(block, queue, force); + // Switch back to Reading state. + state = Some(ImportState::Reading{block_iter}); + } + }, + ImportState::WaitingForImportQueueToFinish { + num_expected_blocks, read_block_count, mut delay + } => { + // All the blocks have been added to the queue, which doesn't mean they + // have all been properly imported. + if importing_is_done(num_expected_blocks, read_block_count, link.imported_blocks) { + // Importing is done, we can log the result and return. + info!( + "🎉 Imported {} blocks. Best: #{}", + read_block_count, client.usage_info().chain.best_number + ); + return Poll::Ready(Ok(())) + } else { + // Importing is not done, we still have to wait for the queue to finish. + // Wait for the delay, because we know the queue is lagging behind. + match Pin::new(&mut delay).poll(cx) { + Poll::Pending => { + state = Some(ImportState::WaitingForImportQueueToFinish { + num_expected_blocks, read_block_count, delay + }); + return Poll::Pending + }, + Poll::Ready(_) => { + delay.reset(Duration::from_millis(DELAY_TIME)); + }, + } + + state = Some(ImportState::WaitingForImportQueueToFinish { + num_expected_blocks, read_block_count, delay + }); + } + } + } + + queue.poll_actions(cx, &mut link); + + let best_number = client.usage_info().chain.best_number; + speedometer.notify_user(best_number); + + if link.has_error { + return Poll::Ready(Err( + Error::Other( + format!("Stopping after #{} blocks because of an error", link.imported_blocks) + ) + )) + } + + cx.waker().wake_by_ref(); + Poll::Pending + }); + Box::pin(import) +} diff --git a/bin/node/cli/tests/factory.rs b/client/service/src/chain_ops/mod.rs similarity index 55% rename from bin/node/cli/tests/factory.rs rename to client/service/src/chain_ops/mod.rs index 2930cd52e2e16e497d197849a9833d492c3868d7..af6e6f632fc06438f8396c158425d57d30727ecd 100644 --- a/bin/node/cli/tests/factory.rs +++ b/client/service/src/chain_ops/mod.rs @@ -14,27 +14,16 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -#![cfg(unix)] - -use assert_cmd::cargo::cargo_bin; -use std::process::{Command, Stdio}; -use tempfile::tempdir; - -mod common; - -#[test] -fn factory_works() { - let base_path = tempdir().expect("could not create a temp dir"); - - let status = Command::new(cargo_bin("substrate")) - .stdout(Stdio::null()) - .args(&["factory", "--dev", "-d"]) - .arg(base_path.path()) - .status() - .unwrap(); - assert!(status.success()); - - // Make sure that the `dev` chain folder exists & `db` - assert!(base_path.path().join("chains/dev/").exists()); - assert!(base_path.path().join("chains/dev/db").exists()); -} +//! Chain utilities. + +mod check_block; +mod export_blocks; +mod export_raw_state; +mod import_blocks; +mod revert_chain; + +pub use check_block::*; +pub use export_blocks::*; +pub use export_raw_state::*; +pub use import_blocks::*; +pub use revert_chain::*; diff --git a/client/service/src/chain_ops/revert_chain.rs b/client/service/src/chain_ops/revert_chain.rs new file mode 100644 index 0000000000000000000000000000000000000000..129aea0408685048f8c3fb29704aa331978946df --- /dev/null +++ b/client/service/src/chain_ops/revert_chain.rs @@ -0,0 +1,43 @@ +// Copyright 2017-2020 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; +use log::info; +use sp_runtime::traits::{Block as BlockT, NumberFor, Zero}; +use sc_client_api::{Backend, UsageProvider}; +use std::sync::Arc; + +/// Performs a revert of `blocks` blocks. +pub fn revert_chain( + client: Arc, + backend: Arc, + blocks: NumberFor +) -> Result<(), Error> +where + B: BlockT, + C: UsageProvider, + BA: Backend, +{ + let reverted = backend.revert(blocks, false)?; + let info = client.usage_info().chain; + + if reverted.is_zero() { + info!("There aren't any non-finalized blocks to revert."); + } else { + info!("Reverted {} blocks. Best: #{} ({})", reverted, info.best_number, info.best_hash); + } + Ok(()) +} diff --git a/client/src/block_rules.rs b/client/service/src/client/block_rules.rs similarity index 82% rename from client/src/block_rules.rs rename to client/service/src/client/block_rules.rs index e5614511817d35b5f2dbe4ebfb9501c5410553ec..247d09197b604c7335c5141f6409b9b727c67b97 100644 --- a/client/src/block_rules.rs +++ b/client/service/src/client/block_rules.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Client fixed chain specification rules diff --git a/client/src/call_executor.rs b/client/service/src/client/call_executor.rs similarity index 87% rename from client/src/call_executor.rs rename to client/service/src/client/call_executor.rs index 1160449eeef88c251673251d873c76855d7bcab3..049bd888b13c78ca4f67eaadfa7dfa551b01c313 100644 --- a/client/src/call_executor.rs +++ b/client/service/src/client/call_executor.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use std::{sync::Arc, panic::UnwindSafe, result, cell::RefCell}; use codec::{Encode, Decode}; @@ -25,9 +27,10 @@ use sp_state_machine::{ }; use sc_executor::{RuntimeVersion, RuntimeInfo, NativeVersion}; use sp_externalities::Extensions; -use sp_core::{NativeOrEncoded, NeverNativeValue, traits::CodeExecutor}; +use sp_core::{NativeOrEncoded, NeverNativeValue, traits::CodeExecutor, offchain::storage::OffchainOverlayedChanges}; use sp_api::{ProofRecorder, InitializeBlock, StorageTransactionCache}; use sc_client_api::{backend, call_executor::CallExecutor, CloneableSpawn}; +use super::client::ClientConfig; /// Call executor that executes methods locally, querying all required /// data from local backend. @@ -35,6 +38,7 @@ pub struct LocalCallExecutor { backend: Arc, executor: E, spawn_handle: Box, + client_config: ClientConfig, } impl LocalCallExecutor { @@ -43,11 +47,13 @@ impl LocalCallExecutor { backend: Arc, executor: E, spawn_handle: Box, + client_config: ClientConfig, ) -> Self { LocalCallExecutor { backend, executor, spawn_handle, + client_config, } } } @@ -58,6 +64,7 @@ impl Clone for LocalCallExecutor where E: Clone { backend: self.backend.clone(), executor: self.executor.clone(), spawn_handle: self.spawn_handle.clone(), + client_config: self.client_config.clone(), } } } @@ -81,6 +88,11 @@ where extensions: Option, ) -> sp_blockchain::Result> { let mut changes = OverlayedChanges::default(); + let mut offchain_changes = if self.client_config.offchain_indexing_api { + OffchainOverlayedChanges::enabled() + } else { + OffchainOverlayedChanges::disabled() + }; let changes_trie = backend::changes_tries_state_at_block( id, self.backend.changes_trie_storage() )?; @@ -90,6 +102,7 @@ where &state, changes_trie, &mut changes, + &mut offchain_changes, &self.executor, method, call_data, @@ -120,6 +133,7 @@ where method: &str, call_data: &[u8], changes: &RefCell, + offchain_changes: &RefCell, storage_transaction_cache: Option<&RefCell< StorageTransactionCache >>, @@ -143,6 +157,9 @@ where let mut state = self.backend.state_at(*at)?; + let changes = &mut *changes.borrow_mut(); + let offchain_changes = &mut *offchain_changes.borrow_mut(); + match recorder { Some(recorder) => { let trie_state = state.as_trie_backend() @@ -160,11 +177,11 @@ where recorder.clone(), ); - let changes = &mut *changes.borrow_mut(); let mut state_machine = StateMachine::new( &backend, changes_trie_state, changes, + offchain_changes, &self.executor, method, call_data, @@ -179,11 +196,11 @@ where None => { let state_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&state); let runtime_code = state_runtime_code.runtime_code()?; - let changes = &mut *changes.borrow_mut(); let mut state_machine = StateMachine::new( &state, changes_trie_state, changes, + offchain_changes, &self.executor, method, call_data, @@ -198,6 +215,7 @@ where fn runtime_version(&self, id: &BlockId) -> sp_blockchain::Result { let mut overlay = OverlayedChanges::default(); + let mut offchain_overlay = OffchainOverlayedChanges::default(); let changes_trie_state = backend::changes_tries_state_at_block( id, self.backend.changes_trie_storage(), @@ -206,6 +224,7 @@ where let mut cache = StorageTransactionCache::::default(); let mut ext = Ext::new( &mut overlay, + &mut offchain_overlay, &mut cache, &state, changes_trie_state, diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs new file mode 100644 index 0000000000000000000000000000000000000000..2f101465d516f935701a8ff2f622f3902515ef2b --- /dev/null +++ b/client/service/src/client/client.rs @@ -0,0 +1,1991 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Substrate Client + +use std::{ + marker::PhantomData, + collections::{HashSet, BTreeMap, HashMap}, + sync::Arc, panic::UnwindSafe, result, +}; +use log::{info, trace, warn}; +use parking_lot::{Mutex, RwLock}; +use codec::{Encode, Decode}; +use hash_db::Prefix; +use sp_core::{ + convert_hash, + storage::{well_known_keys, ChildInfo, PrefixedStorageKey, StorageData, StorageKey}, + ChangesTrieConfiguration, ExecutionContext, NativeOrEncoded, +}; +use sc_telemetry::{telemetry, SUBSTRATE_INFO}; +use sp_runtime::{ + Justification, BuildStorage, + generic::{BlockId, SignedBlock, DigestItem}, + traits::{ + Block as BlockT, Header as HeaderT, Zero, NumberFor, + HashFor, SaturatedConversion, One, DigestFor, + }, +}; +use sp_state_machine::{ + DBValue, Backend as StateBackend, ChangesTrieAnchorBlockId, + prove_read, prove_child_read, ChangesTrieRootsStorage, ChangesTrieStorage, + ChangesTrieConfigurationRange, key_changes, key_changes_proof, +}; +use sc_executor::RuntimeVersion; +use sp_consensus::{ + Error as ConsensusError, BlockStatus, BlockImportParams, BlockCheckParams, + ImportResult, BlockOrigin, ForkChoiceStrategy, RecordProof, +}; +use sp_blockchain::{ + self as blockchain, + Backend as ChainBackend, + HeaderBackend as ChainHeaderBackend, ProvideCache, Cache, + well_known_cache_keys::Id as CacheKeyId, + HeaderMetadata, CachedHeaderMetadata, +}; +use sp_trie::StorageProof; +use sp_api::{ + CallApiAt, ConstructRuntimeApi, Core as CoreApi, ApiExt, ApiRef, ProvideRuntimeApi, + CallApiAtParams, +}; +use sc_block_builder::{BlockBuilderApi, BlockBuilderProvider}; +use sc_client_api::{ + backend::{ + self, BlockImportOperation, PrunableStateChangesTrieStorage, + ClientImportOperation, Finalizer, ImportSummary, NewBlockState, + changes_tries_state_at_block, StorageProvider, + LockImportRun, apply_aux, + }, + client::{ + ImportNotifications, FinalityNotification, FinalityNotifications, BlockImportNotification, + ClientInfo, BlockchainEvents, BlockBackend, ProvideUncles, BadBlocks, ForkBlocks, + BlockOf, + }, + execution_extensions::ExecutionExtensions, + notifications::{StorageNotifications, StorageEventStream}, + KeyIterator, CallExecutor, ExecutorProvider, ProofProvider, + cht, UsageProvider +}; +use sp_utils::mpsc::{TracingUnboundedSender, tracing_unbounded}; +use sp_blockchain::Error; +use prometheus_endpoint::Registry; +use super::{ + genesis, block_rules::{BlockRules, LookupResult as BlockLookupResult}, +}; +use sc_light::{call_executor::prove_execution, fetcher::ChangesProof}; +use rand::Rng; + +#[cfg(feature="test-helpers")] +use { + sp_core::traits::CodeExecutor, + sc_client_api::{CloneableSpawn, in_mem}, + sc_executor::RuntimeInfo, + super::call_executor::LocalCallExecutor, +}; + +type NotificationSinks = Mutex>>; + +/// Substrate Client +pub struct Client where Block: BlockT { + backend: Arc, + executor: E, + storage_notifications: Mutex>, + import_notification_sinks: NotificationSinks>, + finality_notification_sinks: NotificationSinks>, + // holds the block hash currently being imported. TODO: replace this with block queue + importing_block: RwLock>, + block_rules: BlockRules, + execution_extensions: ExecutionExtensions, + config: ClientConfig, + _phantom: PhantomData, +} + +// used in importing a block, where additional changes are made after the runtime +// executed. +enum PrePostHeader { + // they are the same: no post-runtime digest items. + Same(H), + // different headers (pre, post). + Different(H, H), +} + +impl PrePostHeader { + // get a reference to the "post-header" -- the header as it should be after all changes are applied. + fn post(&self) -> &H { + match *self { + PrePostHeader::Same(ref h) => h, + PrePostHeader::Different(_, ref h) => h, + } + } + + // convert to the "post-header" -- the header as it should be after all changes are applied. + fn into_post(self) -> H { + match self { + PrePostHeader::Same(h) => h, + PrePostHeader::Different(_, h) => h, + } + } +} + +/// Create an instance of in-memory client. +#[cfg(feature="test-helpers")] +pub fn new_in_mem( + executor: E, + genesis_storage: &S, + keystore: Option, + prometheus_registry: Option, + spawn_handle: Box, + config: ClientConfig, +) -> sp_blockchain::Result, + LocalCallExecutor, E>, + Block, + RA +>> where + E: CodeExecutor + RuntimeInfo, + S: BuildStorage, + Block: BlockT, +{ + new_with_backend( + Arc::new(in_mem::Backend::new()), + executor, + genesis_storage, + keystore, + spawn_handle, + prometheus_registry, + config, + ) +} + +/// Relevant client configuration items relevant for the client. +#[derive(Debug,Clone,Default)] +pub struct ClientConfig { + /// Enable the offchain worker db. + pub offchain_worker_enabled: bool, + /// If true, allows access from the runtime to write into offchain worker db. + pub offchain_indexing_api: bool, +} + +/// Create a client with the explicitly provided backend. +/// This is useful for testing backend implementations. +#[cfg(feature="test-helpers")] +pub fn new_with_backend( + backend: Arc, + executor: E, + build_genesis_storage: &S, + keystore: Option, + spawn_handle: Box, + prometheus_registry: Option, + config: ClientConfig, +) -> sp_blockchain::Result, Block, RA>> + where + E: CodeExecutor + RuntimeInfo, + S: BuildStorage, + Block: BlockT, + B: backend::LocalBackend + 'static, +{ + let call_executor = LocalCallExecutor::new(backend.clone(), executor, spawn_handle, config.clone()); + let extensions = ExecutionExtensions::new(Default::default(), keystore); + Client::new( + backend, + call_executor, + build_genesis_storage, + Default::default(), + Default::default(), + extensions, + prometheus_registry, + config, + ) +} + +impl BlockOf for Client where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, +{ + type Type = Block; +} + +impl LockImportRun for Client + where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, +{ + fn lock_import_and_run(&self, f: F) -> Result + where + F: FnOnce(&mut ClientImportOperation) -> Result, + Err: From, + { + let inner = || { + let _import_lock = self.backend.get_import_lock().write(); + + let mut op = ClientImportOperation { + op: self.backend.begin_operation()?, + notify_imported: None, + notify_finalized: Vec::new(), + }; + + let r = f(&mut op)?; + + let ClientImportOperation { op, notify_imported, notify_finalized } = op; + self.backend.commit_operation(op)?; + + self.notify_finalized(notify_finalized)?; + self.notify_imported(notify_imported)?; + + Ok(r) + }; + + let result = inner(); + *self.importing_block.write() = None; + + result + } +} + +impl LockImportRun for &Client + where + Block: BlockT, + B: backend::Backend, + E: CallExecutor, +{ + fn lock_import_and_run(&self, f: F) -> Result + where + F: FnOnce(&mut ClientImportOperation) -> Result, + Err: From, + { + (**self).lock_import_and_run(f) + } +} + +impl Client where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, + Block::Header: Clone, +{ + /// Creates new Substrate Client with given blockchain and code executor. + pub fn new( + backend: Arc, + executor: E, + build_genesis_storage: &dyn BuildStorage, + fork_blocks: ForkBlocks, + bad_blocks: BadBlocks, + execution_extensions: ExecutionExtensions, + prometheus_registry: Option, + config: ClientConfig, + ) -> sp_blockchain::Result { + if backend.blockchain().header(BlockId::Number(Zero::zero()))?.is_none() { + let genesis_storage = build_genesis_storage.build_storage()?; + let mut op = backend.begin_operation()?; + backend.begin_state_operation(&mut op, BlockId::Hash(Default::default()))?; + let state_root = op.reset_storage(genesis_storage)?; + let genesis_block = genesis::construct_genesis_block::(state_root.into()); + info!("🔨 Initializing Genesis block/state (state: {}, header-hash: {})", + genesis_block.header().state_root(), + genesis_block.header().hash() + ); + op.set_block_data( + genesis_block.deconstruct().0, + Some(vec![]), + None, + NewBlockState::Final + )?; + backend.commit_operation(op)?; + } + + Ok(Client { + backend, + executor, + storage_notifications: Mutex::new(StorageNotifications::new(prometheus_registry)), + import_notification_sinks: Default::default(), + finality_notification_sinks: Default::default(), + importing_block: Default::default(), + block_rules: BlockRules::new(fork_blocks, bad_blocks), + execution_extensions, + config, + _phantom: Default::default(), + }) + } + + /// returns a reference to the block import notification sinks + /// useful for test environments. + pub fn import_notification_sinks(&self) -> &NotificationSinks> { + &self.import_notification_sinks + } + + /// returns a reference to the finality notification sinks + /// useful for test environments. + pub fn finality_notification_sinks(&self) -> &NotificationSinks> { + &self.finality_notification_sinks + } + + /// Get a reference to the state at a given block. + pub fn state_at(&self, block: &BlockId) -> sp_blockchain::Result { + self.backend.state_at(*block) + } + + /// Get the code at a given block. + pub fn code_at(&self, id: &BlockId) -> sp_blockchain::Result> { + Ok(StorageProvider::storage(self, id, &StorageKey(well_known_keys::CODE.to_vec()))? + .expect("None is returned if there's no value stored for the given key;\ + ':code' key is always defined; qed").0) + } + + /// Get the RuntimeVersion at a given block. + pub fn runtime_version_at(&self, id: &BlockId) -> sp_blockchain::Result { + self.executor.runtime_version(id) + } + + /// Reads given header and generates CHT-based header proof for CHT of given size. + pub fn header_proof_with_cht_size( + &self, + id: &BlockId, + cht_size: NumberFor, + ) -> sp_blockchain::Result<(Block::Header, StorageProof)> { + let proof_error = || sp_blockchain::Error::Backend(format!("Failed to generate header proof for {:?}", id)); + let header = self.backend.blockchain().expect_header(*id)?; + let block_num = *header.number(); + let cht_num = cht::block_to_cht_number(cht_size, block_num).ok_or_else(proof_error)?; + let cht_start = cht::start_number(cht_size, cht_num); + let mut current_num = cht_start; + let cht_range = ::std::iter::from_fn(|| { + let old_current_num = current_num; + current_num = current_num + One::one(); + Some(old_current_num) + }); + let headers = cht_range.map(|num| self.block_hash(num)); + let proof = cht::build_proof::, _, _>( + cht_size, + cht_num, + std::iter::once(block_num), + headers, + )?; + Ok((header, proof)) + } + + /// Does the same work as `key_changes_proof`, but assumes that CHTs are of passed size. + pub fn key_changes_proof_with_cht_size( + &self, + first: Block::Hash, + last: Block::Hash, + min: Block::Hash, + max: Block::Hash, + storage_key: Option<&PrefixedStorageKey>, + key: &StorageKey, + cht_size: NumberFor, + ) -> sp_blockchain::Result> { + struct AccessedRootsRecorder<'a, Block: BlockT> { + storage: &'a dyn ChangesTrieStorage, NumberFor>, + min: NumberFor, + required_roots_proofs: Mutex, Block::Hash>>, + }; + + impl<'a, Block: BlockT> ChangesTrieRootsStorage, NumberFor> for + AccessedRootsRecorder<'a, Block> + { + fn build_anchor(&self, hash: Block::Hash) + -> Result>, String> + { + self.storage.build_anchor(hash) + } + + fn root( + &self, + anchor: &ChangesTrieAnchorBlockId>, + block: NumberFor, + ) -> Result, String> { + let root = self.storage.root(anchor, block)?; + if block < self.min { + if let Some(ref root) = root { + self.required_roots_proofs.lock().insert( + block, + root.clone() + ); + } + } + Ok(root) + } + } + + impl<'a, Block: BlockT> ChangesTrieStorage, NumberFor> for + AccessedRootsRecorder<'a, Block> + { + fn as_roots_storage(&self) + -> &dyn sp_state_machine::ChangesTrieRootsStorage, NumberFor> + { + self + } + + fn with_cached_changed_keys( + &self, + root: &Block::Hash, + functor: &mut dyn FnMut(&HashMap, HashSet>>), + ) -> bool { + self.storage.with_cached_changed_keys(root, functor) + } + + fn get(&self, key: &Block::Hash, prefix: Prefix) -> Result, String> { + self.storage.get(key, prefix) + } + } + + let first_number = self.backend.blockchain() + .expect_block_number_from_id(&BlockId::Hash(first))?; + let (storage, configs) = self.require_changes_trie(first_number, last, true)?; + let min_number = self.backend.blockchain().expect_block_number_from_id(&BlockId::Hash(min))?; + + let recording_storage = AccessedRootsRecorder:: { + storage: storage.storage(), + min: min_number, + required_roots_proofs: Mutex::new(BTreeMap::new()), + }; + + let max_number = std::cmp::min( + self.backend.blockchain().info().best_number, + self.backend.blockchain().expect_block_number_from_id(&BlockId::Hash(max))?, + ); + + // fetch key changes proof + let mut proof = Vec::new(); + for (config_zero, config_end, config) in configs { + let last_number = self.backend.blockchain() + .expect_block_number_from_id(&BlockId::Hash(last))?; + let config_range = ChangesTrieConfigurationRange { + config: &config, + zero: config_zero, + end: config_end.map(|(config_end_number, _)| config_end_number), + }; + let proof_range = key_changes_proof::, _>( + config_range, + &recording_storage, + first_number, + &ChangesTrieAnchorBlockId { + hash: convert_hash(&last), + number: last_number, + }, + max_number, + storage_key, + &key.0, + ) + .map_err(|err| sp_blockchain::Error::ChangesTrieAccessFailed(err))?; + proof.extend(proof_range); + } + + // now gather proofs for all changes tries roots that were touched during key_changes_proof + // execution AND are unknown (i.e. replaced with CHT) to the requester + let roots = recording_storage.required_roots_proofs.into_inner(); + let roots_proof = self.changes_trie_roots_proof(cht_size, roots.keys().cloned())?; + + Ok(ChangesProof { + max_block: max_number, + proof, + roots: roots.into_iter().map(|(n, h)| (n, convert_hash(&h))).collect(), + roots_proof, + }) + } + + /// Generate CHT-based proof for roots of changes tries at given blocks. + fn changes_trie_roots_proof>>( + &self, + cht_size: NumberFor, + blocks: I + ) -> sp_blockchain::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 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)?; + proofs.push(cht_proof); + Ok(()) + }, ())?; + + Ok(StorageProof::merge(proofs)) + } + + /// Generates CHT-based proof for roots of changes tries at given blocks (that are part of single CHT). + fn changes_trie_roots_proof_at_cht( + &self, + cht_size: NumberFor, + cht_num: NumberFor, + blocks: Vec> + ) -> sp_blockchain::Result { + let cht_start = cht::start_number(cht_size, cht_num); + let mut current_num = cht_start; + let cht_range = ::std::iter::from_fn(|| { + let old_current_num = current_num; + current_num = current_num + One::one(); + Some(old_current_num) + }); + let roots = cht_range + .map(|num| self.header(&BlockId::Number(num)) + .map(|block| + block.and_then(|block| block.digest().log(DigestItem::as_changes_trie_root).cloned())) + ); + let proof = cht::build_proof::, _, _>( + cht_size, + cht_num, + blocks, + roots, + )?; + Ok(proof) + } + + /// Returns changes trie storage and all configurations that have been active in the range [first; last]. + /// + /// Configurations are returned in descending order (and obviously never overlap). + /// If fail_if_disabled is false, returns maximal consequent configurations ranges, starting from last and + /// stopping on either first, or when CT have been disabled. + /// If fail_if_disabled is true, fails when there's a subrange where CT have been disabled + /// inside first..last blocks range. + fn require_changes_trie( + &self, + first: NumberFor, + last: Block::Hash, + fail_if_disabled: bool, + ) -> sp_blockchain::Result<( + &dyn PrunableStateChangesTrieStorage, + Vec<(NumberFor, Option<(NumberFor, Block::Hash)>, ChangesTrieConfiguration)>, + )> { + let storage = match self.backend.changes_trie_storage() { + Some(storage) => storage, + None => return Err(sp_blockchain::Error::ChangesTriesNotSupported), + }; + + let mut configs = Vec::with_capacity(1); + let mut current = last; + loop { + let config_range = storage.configuration_at(&BlockId::Hash(current))?; + match config_range.config { + Some(config) => configs.push((config_range.zero.0, config_range.end, config)), + None if !fail_if_disabled => return Ok((storage, configs)), + None => return Err(sp_blockchain::Error::ChangesTriesNotSupported), + } + + if config_range.zero.0 < first { + break; + } + + current = *self.backend.blockchain().expect_header(BlockId::Hash(config_range.zero.1))?.parent_hash(); + } + + Ok((storage, configs)) + } + + /// Apply a checked and validated block to an operation. If a justification is provided + /// then `finalized` *must* be true. + fn apply_block( + &self, + operation: &mut ClientImportOperation, + import_block: BlockImportParams>, + new_cache: HashMap>, + ) -> sp_blockchain::Result where + Self: ProvideRuntimeApi, + >::Api: CoreApi + + ApiExt, + { + let BlockImportParams { + origin, + header, + justification, + post_digests, + body, + storage_changes, + finalized, + auxiliary, + fork_choice, + intermediates, + import_existing, + .. + } = import_block; + + assert!(justification.is_some() && finalized || justification.is_none()); + + if !intermediates.is_empty() { + return Err(Error::IncompletePipeline) + } + + let fork_choice = fork_choice.ok_or(Error::IncompletePipeline)?; + + let import_headers = if post_digests.is_empty() { + PrePostHeader::Same(header) + } else { + let mut post_header = header.clone(); + for item in post_digests { + post_header.digest_mut().push(item); + } + PrePostHeader::Different(header, post_header) + }; + + let hash = import_headers.post().hash(); + let height = (*import_headers.post().number()).saturated_into::(); + + *self.importing_block.write() = Some(hash); + + let result = self.execute_and_import_block( + operation, + origin, + hash, + import_headers, + justification, + body, + storage_changes, + new_cache, + finalized, + auxiliary, + fork_choice, + import_existing, + ); + + if let Ok(ImportResult::Imported(ref aux)) = result { + if aux.is_new_best { + // don't send telemetry block import events during initial sync for every + // block to avoid spamming the telemetry server, these events will be randomly + // sent at a rate of 1/10. + if origin != BlockOrigin::NetworkInitialSync || + rand::thread_rng().gen_bool(0.1) + { + telemetry!(SUBSTRATE_INFO; "block.import"; + "height" => height, + "best" => ?hash, + "origin" => ?origin + ); + } + } + } + + result + } + + fn execute_and_import_block( + &self, + operation: &mut ClientImportOperation, + origin: BlockOrigin, + hash: Block::Hash, + import_headers: PrePostHeader, + justification: Option, + body: Option>, + storage_changes: Option, Block>>, + new_cache: HashMap>, + finalized: bool, + aux: Vec<(Vec, Option>)>, + fork_choice: ForkChoiceStrategy, + import_existing: bool, + ) -> sp_blockchain::Result where + Self: ProvideRuntimeApi, + >::Api: CoreApi + + ApiExt, + { + let parent_hash = import_headers.post().parent_hash().clone(); + let status = self.backend.blockchain().status(BlockId::Hash(hash))?; + match (import_existing, status) { + (false, blockchain::BlockStatus::InChain) => return Ok(ImportResult::AlreadyInChain), + (false, blockchain::BlockStatus::Unknown) => {}, + (true, blockchain::BlockStatus::InChain) => {}, + (true, blockchain::BlockStatus::Unknown) => + return Err(Error::UnknownBlock(format!("{:?}", hash))), + } + + 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(sp_blockchain::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 + // and get a new chain head. + let make_notifications = match origin { + BlockOrigin::NetworkBroadcast | BlockOrigin::Own | BlockOrigin::ConsensusBroadcast => true, + BlockOrigin::Genesis | BlockOrigin::NetworkInitialSync | BlockOrigin::File => false, + }; + + let storage_changes = match storage_changes { + Some(storage_changes) => { + self.backend.begin_state_operation(&mut operation.op, BlockId::Hash(parent_hash))?; + + // 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, + info.best_hash, + make_notifications, + )?; + } + + operation.op.update_cache(new_cache); + + let ( + main_sc, + child_sc, + offchain_sc, + tx, _, + changes_trie_tx, + ) = storage_changes.into_inner(); + + if self.config.offchain_indexing_api { + operation.op.update_offchain_storage(offchain_sc)?; + } + + operation.op.update_db_storage(tx)?; + operation.op.update_storage(main_sc.clone(), child_sc.clone())?; + + if let Some(changes_trie_transaction) = changes_trie_tx { + operation.op.update_changes_trie(changes_trie_transaction)?; + } + + Some((main_sc, child_sc)) + }, + None => None, + }; + + let is_new_best = finalized || match fork_choice { + ForkChoiceStrategy::LongestChain => import_headers.post().number() > &info.best_number, + ForkChoiceStrategy::Custom(v) => v, + }; + + let leaf_state = if finalized { + NewBlockState::Final + } else if is_new_best { + NewBlockState::Best + } else { + NewBlockState::Normal + }; + + let tree_route = if is_new_best && info.best_hash != parent_hash { + let route_from_best = sp_blockchain::tree_route( + self.backend.blockchain(), + info.best_hash, + parent_hash, + )?; + Some(route_from_best) + } else { + None + }; + + trace!( + "Imported {}, (#{}), best={}, origin={:?}", + hash, + import_headers.post().number(), + is_new_best, + origin, + ); + + operation.op.set_block_data( + import_headers.post().clone(), + body, + justification, + leaf_state, + )?; + + operation.op.insert_aux(aux)?; + + if make_notifications { + if finalized { + operation.notify_finalized.push(hash); + } + + operation.notify_imported = Some(ImportSummary { + hash, + origin, + header: import_headers.into_post(), + is_new_best, + storage_changes, + tree_route, + }) + } + + Ok(ImportResult::imported(is_new_best)) + } + + /// Prepares the storage changes for a block. + /// + /// It checks if the state should be enacted and if the `import_block` maybe already provides + /// the required storage changes. If the state should be enacted and the storage changes are not + /// provided, the block is re-executed to get the storage changes. + fn prepare_block_storage_changes( + &self, + import_block: &mut BlockImportParams>, + ) -> sp_blockchain::Result> + where + Self: ProvideRuntimeApi, + >::Api: CoreApi + + ApiExt, + { + let parent_hash = import_block.header.parent_hash(); + let at = BlockId::Hash(*parent_hash); + let enact_state = match self.block_status(&at)? { + BlockStatus::Unknown => return Ok(Some(ImportResult::UnknownParent)), + BlockStatus::InChainWithState | BlockStatus::Queued => true, + BlockStatus::InChainPruned if import_block.allow_missing_state => false, + BlockStatus::InChainPruned => return Ok(Some(ImportResult::MissingState)), + BlockStatus::KnownBad => return Ok(Some(ImportResult::KnownBad)), + }; + + match (enact_state, &mut import_block.storage_changes, &mut import_block.body) { + // We have storage changes and should enact the state, so we don't need to do anything + // here + (true, Some(_), _) => {}, + // We should enact state, but don't have any storage changes, so we need to execute the + // block. + (true, ref mut storage_changes @ None, Some(ref body)) => { + let runtime_api = self.runtime_api(); + let execution_context = if import_block.origin == BlockOrigin::NetworkInitialSync { + ExecutionContext::Syncing + } else { + ExecutionContext::Importing + }; + + runtime_api.execute_block_with_context( + &at, + execution_context, + Block::new(import_block.header.clone(), body.clone()), + )?; + + let state = self.backend.state_at(at)?; + let changes_trie_state = changes_tries_state_at_block( + &at, + self.backend.changes_trie_storage(), + )?; + + let gen_storage_changes = runtime_api.into_storage_changes( + &state, + changes_trie_state.as_ref(), + *parent_hash, + )?; + + if import_block.header.state_root() + != &gen_storage_changes.transaction_storage_root + { + return Err(Error::InvalidStateRoot) + } else { + **storage_changes = Some(gen_storage_changes); + } + }, + // No block body, no storage changes + (true, None, None) => {}, + // We should not enact the state, so we set the storage changes to `None`. + (false, changes, _) => { + changes.take(); + } + }; + + Ok(None) + } + + fn apply_finality_with_block_hash( + &self, + operation: &mut ClientImportOperation, + block: Block::Hash, + justification: Option, + best_block: Block::Hash, + notify: bool, + ) -> sp_blockchain::Result<()> { + // find tree route from last finalized to given block. + let last_finalized = self.backend.blockchain().last_finalized()?; + + if block == last_finalized { + warn!("Possible safety violation: attempted to re-finalize last finalized block {:?} ", last_finalized); + return Ok(()); + } + + let route_from_finalized = sp_blockchain::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 \ + same chain as last finalized {:?}", retracted, last_finalized); + + return Err(sp_blockchain::Error::NotInFinalizedChain); + } + + let route_from_best = sp_blockchain::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 inaccurate since we might have a "better" block + // further along this chain, but since best chain selection logic is + // plugable we cannot make a better choice here. usages that need + // an accurate "best" block need to go through `SelectChain` + // instead. + operation.op.mark_head(BlockId::Hash(block))?; + } + + let enacted = route_from_finalized.enacted(); + assert!(enacted.len() > 0); + for finalize_new in &enacted[..enacted.len() - 1] { + operation.op.mark_finalized(BlockId::Hash(finalize_new.hash), None)?; + } + + assert_eq!(enacted.last().map(|e| e.hash), Some(block)); + operation.op.mark_finalized(BlockId::Hash(block), justification)?; + + if notify { + // sometimes when syncing, tons of blocks can be finalized at once. + // we'll send notifications spuriously in that case. + const MAX_TO_NOTIFY: usize = 256; + let enacted = route_from_finalized.enacted(); + let start = enacted.len() - std::cmp::min(enacted.len(), MAX_TO_NOTIFY); + for finalized in &enacted[start..] { + operation.notify_finalized.push(finalized.hash); + } + } + + Ok(()) + } + + fn notify_finalized( + &self, + notify_finalized: Vec, + ) -> sp_blockchain::Result<()> { + let mut sinks = self.finality_notification_sinks.lock(); + + if notify_finalized.is_empty() { + // cleanup any closed finality notification sinks + // since we won't be running the loop below which + // would also remove any closed sinks. + sinks.retain(|sink| !sink.is_closed()); + + return Ok(()); + } + + // We assume the list is sorted and only want to inform the + // telemetry once about the finalized block. + if let Some(last) = notify_finalized.last() { + let header = self.header(&BlockId::Hash(*last))? + .expect( + "Header already known to exist in DB because it is \ + indicated in the tree route; qed" + ); + + telemetry!(SUBSTRATE_INFO; "notify.finalized"; + "height" => format!("{}", header.number()), + "best" => ?last, + ); + } + + for finalized_hash in notify_finalized { + let header = self.header(&BlockId::Hash(finalized_hash))? + .expect( + "Header already known to exist in DB because it is \ + indicated in the tree route; qed" + ); + + let notification = FinalityNotification { + header, + hash: finalized_hash, + }; + + sinks.retain(|sink| sink.unbounded_send(notification.clone()).is_ok()); + } + + Ok(()) + } + + fn notify_imported( + &self, + notify_import: Option>, + ) -> sp_blockchain::Result<()> { + let notify_import = match notify_import { + Some(notify_import) => notify_import, + None => { + // cleanup any closed import notification sinks since we won't + // be sending any notifications below which would remove any + // closed sinks. this is necessary since during initial sync we + // won't send any import notifications which could lead to a + // temporary leak of closed/discarded notification sinks (e.g. + // from consensus code). + self.import_notification_sinks + .lock() + .retain(|sink| !sink.is_closed()); + + return Ok(()); + } + }; + + 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( + ¬ify_import.hash, + storage_changes.0.into_iter(), + storage_changes.1.into_iter().map(|(sk, v)| (sk, v.into_iter())), + ); + } + + let notification = BlockImportNotification:: { + hash: notify_import.hash, + origin: notify_import.origin, + header: notify_import.header, + is_new_best: notify_import.is_new_best, + tree_route: notify_import.tree_route.map(Arc::new), + }; + + self.import_notification_sinks.lock() + .retain(|sink| sink.unbounded_send(notification.clone()).is_ok()); + + Ok(()) + } + + /// Attempts to revert the chain by `n` blocks guaranteeing that no block is + /// reverted past the last finalized block. Returns the number of blocks + /// that were successfully reverted. + pub fn revert(&self, n: NumberFor) -> sp_blockchain::Result> { + Ok(self.backend.revert(n, false)?) + } + + /// Attempts to revert the chain by `n` blocks disregarding finality. This + /// method will revert any finalized blocks as requested and can potentially + /// leave the node in an inconsistent state. Other modules in the system that + /// persist data and that rely on finality (e.g. consensus parts) will be + /// unaffected by the revert. Use this method with caution and making sure + /// that no other data needs to be reverted for consistency aside from the + /// block data. + /// + /// Returns the number of blocks that were successfully reverted. + pub fn unsafe_revert(&self, n: NumberFor) -> sp_blockchain::Result> { + Ok(self.backend.revert(n, true)?) + } + + /// Get blockchain info. + pub fn chain_info(&self) -> blockchain::Info { + self.backend.blockchain().info() + } + + /// Get block status. + pub fn block_status(&self, id: &BlockId) -> sp_blockchain::Result { + // this can probably be implemented more efficiently + if let BlockId::Hash(ref h) = id { + if self.importing_block.read().as_ref().map_or(false, |importing| h == importing) { + return Ok(BlockStatus::Queued); + } + } + let hash_and_number = match id.clone() { + BlockId::Hash(hash) => self.backend.blockchain().number(hash)?.map(|n| (hash, n)), + BlockId::Number(n) => self.backend.blockchain().hash(n)?.map(|hash| (hash, n)), + }; + match hash_and_number { + Some((hash, number)) => { + if self.backend.have_state_at(&hash, number) { + Ok(BlockStatus::InChainWithState) + } else { + Ok(BlockStatus::InChainPruned) + } + } + None => Ok(BlockStatus::Unknown), + } + } + + /// Get block header by id. + pub fn header(&self, id: &BlockId) -> sp_blockchain::Result::Header>> { + self.backend.blockchain().header(*id) + } + + /// Get block body by id. + pub fn body(&self, id: &BlockId) -> sp_blockchain::Result::Extrinsic>>> { + self.backend.blockchain().body(*id) + } + + /// Gets the uncles of the block with `target_hash` going back `max_generation` ancestors. + pub fn uncles(&self, target_hash: Block::Hash, max_generation: NumberFor) -> sp_blockchain::Result> { + let load_header = |id: Block::Hash| -> sp_blockchain::Result { + match self.backend.blockchain().header(BlockId::Hash(id))? { + Some(hdr) => Ok(hdr), + None => Err(Error::UnknownBlock(format!("{:?}", id))), + } + }; + + let genesis_hash = self.backend.blockchain().info().genesis_hash; + if genesis_hash == target_hash { return Ok(Vec::new()); } + + let mut current_hash = target_hash; + let mut current = load_header(current_hash)?; + let mut ancestor_hash = *current.parent_hash(); + let mut ancestor = load_header(ancestor_hash)?; + let mut uncles = Vec::new(); + + for _generation in 0..max_generation.saturated_into() { + let children = self.backend.blockchain().children(ancestor_hash)?; + uncles.extend(children.into_iter().filter(|h| h != ¤t_hash)); + current_hash = ancestor_hash; + if genesis_hash == current_hash { break; } + current = ancestor; + ancestor_hash = *current.parent_hash(); + ancestor = load_header(ancestor_hash)?; + } + trace!("Collected {} uncles", uncles.len()); + Ok(uncles) + } + + /// Prepare in-memory header that is used in execution environment. + fn prepare_environment_block(&self, parent: &BlockId) -> sp_blockchain::Result { + let parent_header = self.backend.blockchain().expect_header(*parent)?; + Ok(<::Header as HeaderT>::new( + self.backend.blockchain().expect_block_number_from_id(parent)? + One::one(), + Default::default(), + Default::default(), + parent_header.hash(), + Default::default(), + )) + } +} + +impl UsageProvider for Client where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, +{ + /// Get usage info about current client. + fn usage_info(&self) -> ClientInfo { + ClientInfo { + chain: self.chain_info(), + usage: self.backend.usage_info(), + } + } +} + +impl ProofProvider for Client where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, +{ + fn read_proof( + &self, + id: &BlockId, + keys: &mut dyn Iterator, + ) -> sp_blockchain::Result { + self.state_at(id) + .and_then(|state| prove_read(state, keys) + .map_err(Into::into)) + } + + fn read_child_proof( + &self, + id: &BlockId, + child_info: &ChildInfo, + keys: &mut dyn Iterator, + ) -> sp_blockchain::Result { + self.state_at(id) + .and_then(|state| prove_child_read(state, child_info, keys) + .map_err(Into::into)) + } + + fn execution_proof( + &self, + id: &BlockId, + method: &str, + call_data: &[u8] + ) -> sp_blockchain::Result<(Vec, StorageProof)> { + // Make sure we include the `:code` and `:heap_pages` in the execution proof to be + // backwards compatible. + // + // TODO: Remove when solved: https://github.com/paritytech/substrate/issues/5047 + let code_proof = self.read_proof( + id, + &mut [well_known_keys::CODE, well_known_keys::HEAP_PAGES].iter().map(|v| *v), + )?; + + let state = self.state_at(id)?; + let header = self.prepare_environment_block(id)?; + prove_execution( + state, + header, + &self.executor, + method, + call_data, + ).map(|(r, p)| { + (r, StorageProof::merge(vec![p, code_proof])) + }) + } + + fn header_proof(&self, id: &BlockId) -> sp_blockchain::Result<(Block::Header, StorageProof)> { + self.header_proof_with_cht_size(id, cht::size()) + } + + fn key_changes_proof( + &self, + first: Block::Hash, + last: Block::Hash, + min: Block::Hash, + max: Block::Hash, + storage_key: Option<&PrefixedStorageKey>, + key: &StorageKey, + ) -> sp_blockchain::Result> { + self.key_changes_proof_with_cht_size( + first, + last, + min, + max, + storage_key, + key, + cht::size(), + ) + } +} + + +impl BlockBuilderProvider for Client + where + B: backend::Backend + Send + Sync + 'static, + E: CallExecutor + Send + Sync + 'static, + Block: BlockT, + Self: ChainHeaderBackend + ProvideRuntimeApi, + >::Api: ApiExt> + + BlockBuilderApi, +{ + fn new_block_at>( + &self, + parent: &BlockId, + inherent_digests: DigestFor, + record_proof: R, + ) -> sp_blockchain::Result> { + sc_block_builder::BlockBuilder::new( + self, + self.expect_block_hash_from_id(parent)?, + self.expect_block_number_from_id(parent)?, + record_proof.into(), + inherent_digests, + &self.backend + ) + } + + fn new_block( + &self, + inherent_digests: DigestFor, + ) -> sp_blockchain::Result> { + let info = self.chain_info(); + sc_block_builder::BlockBuilder::new( + self, + info.best_hash, + info.best_number, + RecordProof::No, + inherent_digests, + &self.backend, + ) + } +} + +impl ExecutorProvider for Client where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, +{ + type Executor = E; + + fn executor(&self) -> &Self::Executor { + &self.executor + } + + fn execution_extensions(&self) -> &ExecutionExtensions { + &self.execution_extensions + } +} + +impl StorageProvider for Client where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, +{ + fn storage_keys(&self, id: &BlockId, key_prefix: &StorageKey) -> sp_blockchain::Result> { + let keys = self.state_at(id)?.keys(&key_prefix.0).into_iter().map(StorageKey).collect(); + Ok(keys) + } + + fn storage_pairs(&self, id: &BlockId, key_prefix: &StorageKey) + -> sp_blockchain::Result> + { + let state = self.state_at(id)?; + let keys = state + .keys(&key_prefix.0) + .into_iter() + .map(|k| { + let d = state.storage(&k).ok().flatten().unwrap_or_default(); + (StorageKey(k), StorageData(d)) + }) + .collect(); + Ok(keys) + } + + + fn storage_keys_iter<'a>( + &self, + id: &BlockId, + prefix: Option<&'a StorageKey>, + start_key: Option<&StorageKey> + ) -> sp_blockchain::Result> { + let state = self.state_at(id)?; + let start_key = start_key + .or(prefix) + .map(|key| key.0.clone()) + .unwrap_or_else(Vec::new); + Ok(KeyIterator::new(state, prefix, start_key)) + } + + + fn storage( + &self, + id: &BlockId, + key: &StorageKey, + ) -> sp_blockchain::Result> { + Ok(self.state_at(id)? + .storage(&key.0).map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))? + .map(StorageData) + ) + } + + + fn storage_hash( + &self, + id: &BlockId, + key: &StorageKey, + ) -> sp_blockchain::Result> { + Ok(self.state_at(id)? + .storage_hash(&key.0).map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))? + ) + } + + fn child_storage_keys( + &self, + id: &BlockId, + child_info: &ChildInfo, + key_prefix: &StorageKey + ) -> sp_blockchain::Result> { + let keys = self.state_at(id)? + .child_keys(child_info, &key_prefix.0) + .into_iter() + .map(StorageKey) + .collect(); + Ok(keys) + } + + fn child_storage( + &self, + id: &BlockId, + child_info: &ChildInfo, + key: &StorageKey + ) -> sp_blockchain::Result> { + Ok(self.state_at(id)? + .child_storage(child_info, &key.0) + .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))? + .map(StorageData)) + } + + fn child_storage_hash( + &self, + id: &BlockId, + child_info: &ChildInfo, + key: &StorageKey + ) -> sp_blockchain::Result> { + Ok(self.state_at(id)? + .child_storage_hash(child_info, &key.0) + .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))? + ) + } + + fn max_key_changes_range( + &self, + first: NumberFor, + last: BlockId, + ) -> sp_blockchain::Result, BlockId)>> { + let last_number = self.backend.blockchain().expect_block_number_from_id(&last)?; + let last_hash = self.backend.blockchain().expect_block_hash_from_id(&last)?; + if first > last_number { + return Err(sp_blockchain::Error::ChangesTrieAccessFailed("Invalid changes trie range".into())); + } + + let (storage, configs) = match self.require_changes_trie(first, last_hash, false).ok() { + Some((storage, configs)) => (storage, configs), + None => return Ok(None), + }; + + let first_available_changes_trie = configs.last().map(|config| config.0); + match first_available_changes_trie { + Some(first_available_changes_trie) => { + let oldest_unpruned = storage.oldest_pruned_digest_range_end(); + let first = std::cmp::max(first_available_changes_trie, oldest_unpruned); + Ok(Some((first, last))) + }, + None => Ok(None) + } + } + + fn key_changes( + &self, + first: NumberFor, + last: BlockId, + storage_key: Option<&PrefixedStorageKey>, + key: &StorageKey + ) -> sp_blockchain::Result, u32)>> { + let last_number = self.backend.blockchain().expect_block_number_from_id(&last)?; + let last_hash = self.backend.blockchain().expect_block_hash_from_id(&last)?; + let (storage, configs) = self.require_changes_trie(first, last_hash, true)?; + + let mut result = Vec::new(); + let best_number = self.backend.blockchain().info().best_number; + for (config_zero, config_end, config) in configs { + let range_first = ::std::cmp::max(first, config_zero + One::one()); + let range_anchor = match config_end { + Some((config_end_number, config_end_hash)) => if last_number > config_end_number { + ChangesTrieAnchorBlockId { hash: config_end_hash, number: config_end_number } + } else { + ChangesTrieAnchorBlockId { hash: convert_hash(&last_hash), number: last_number } + }, + None => ChangesTrieAnchorBlockId { hash: convert_hash(&last_hash), number: last_number }, + }; + + let config_range = ChangesTrieConfigurationRange { + config: &config, + zero: config_zero.clone(), + end: config_end.map(|(config_end_number, _)| config_end_number), + }; + let result_range: Vec<(NumberFor, u32)> = key_changes::, _>( + config_range, + storage.storage(), + range_first, + &range_anchor, + best_number, + storage_key, + &key.0) + .and_then(|r| r.map(|r| r.map(|(block, tx)| (block, tx))).collect::>()) + .map_err(|err| sp_blockchain::Error::ChangesTrieAccessFailed(err))?; + result.extend(result_range); + } + + Ok(result) + } +} + +impl HeaderMetadata for Client where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, +{ + type Error = sp_blockchain::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, + Block: BlockT, +{ + fn uncles(&self, target_hash: Block::Hash, max_generation: NumberFor) -> sp_blockchain::Result> { + Ok(Client::uncles(self, target_hash, max_generation)? + .into_iter() + .filter_map(|hash| Client::header(self, &BlockId::Hash(hash)).unwrap_or(None)) + .collect() + ) + } +} + +impl ChainHeaderBackend for Client where + B: backend::Backend, + E: CallExecutor + Send + Sync, + Block: BlockT, + RA: Send + Sync, +{ + fn header(&self, id: BlockId) -> sp_blockchain::Result> { + self.backend.blockchain().header(id) + } + + fn info(&self) -> blockchain::Info { + self.backend.blockchain().info() + } + + fn status(&self, id: BlockId) -> sp_blockchain::Result { + self.backend.blockchain().status(id) + } + + fn number(&self, hash: Block::Hash) -> sp_blockchain::Result::Header as HeaderT>::Number>> { + self.backend.blockchain().number(hash) + } + + fn hash(&self, number: NumberFor) -> sp_blockchain::Result> { + self.backend.blockchain().hash(number) + } +} + +impl sp_runtime::traits::BlockIdTo for Client where + B: backend::Backend, + E: CallExecutor + Send + Sync, + Block: BlockT, + RA: Send + Sync, +{ + type Error = Error; + + fn to_hash(&self, block_id: &BlockId) -> sp_blockchain::Result> { + self.block_hash_from_id(block_id) + } + + fn to_number(&self, block_id: &BlockId) -> sp_blockchain::Result>> { + self.block_number_from_id(block_id) + } +} + +impl ChainHeaderBackend for &Client where + B: backend::Backend, + E: CallExecutor + Send + Sync, + Block: BlockT, + RA: Send + Sync, +{ + fn header(&self, id: BlockId) -> sp_blockchain::Result> { + (**self).backend.blockchain().header(id) + } + + fn info(&self) -> blockchain::Info { + (**self).backend.blockchain().info() + } + + fn status(&self, id: BlockId) -> sp_blockchain::Result { + (**self).status(id) + } + + fn number(&self, hash: Block::Hash) -> sp_blockchain::Result::Header as HeaderT>::Number>> { + (**self).number(hash) + } + + fn hash(&self, number: NumberFor) -> sp_blockchain::Result> { + (**self).hash(number) + } +} + +impl ProvideCache for Client where + B: backend::Backend, + Block: BlockT, +{ + fn cache(&self) -> Option>> { + self.backend.blockchain().cache() + } +} + +impl ProvideRuntimeApi for Client where + B: backend::Backend, + E: CallExecutor + Send + Sync, + Block: BlockT, + RA: ConstructRuntimeApi, +{ + type Api = >::RuntimeApi; + + fn runtime_api<'a>(&'a self) -> ApiRef<'a, Self::Api> { + RA::construct_runtime_api(self) + } +} + +impl CallApiAt for Client where + B: backend::Backend, + E: CallExecutor + Send + Sync, + Block: BlockT, +{ + type Error = Error; + type StateBackend = B::State; + + fn call_api_at< + 'a, + R: Encode + Decode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, + C: CoreApi, + >( + &self, + params: CallApiAtParams<'a, Block, C, NC, B::State>, + ) -> sp_blockchain::Result> { + let core_api = params.core_api; + let at = params.at; + + let (manager, extensions) = self.execution_extensions.manager_and_extensions( + at, + params.context, + ); + + self.executor.contextual_call::<_, fn(_,_) -> _,_,_>( + || core_api.initialize_block(at, &self.prepare_environment_block(at)?), + at, + params.function, + ¶ms.arguments, + params.overlayed_changes, + params.offchain_changes, + Some(params.storage_transaction_cache), + params.initialize_block, + manager, + params.native_call, + params.recorder, + Some(extensions), + ) + } + + fn runtime_version_at(&self, at: &BlockId) -> sp_blockchain::Result { + self.runtime_version_at(at) + } +} + +/// 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 sp_consensus::BlockImport for &Client where + B: backend::Backend, + E: CallExecutor + Send + Sync, + Block: BlockT, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: CoreApi + + ApiExt, +{ + type Error = ConsensusError; + type Transaction = backend::TransactionFor; + + /// Import a checked and validated block. If a justification is provided in + /// `BlockImportParams` then `finalized` *must* be true. + /// + /// NOTE: only use this implementation when there are NO consensus-level BlockImport + /// objects. Otherwise, importing blocks directly into the client would be bypassing + /// important verification work. + /// + /// If you are not sure that there are no BlockImport objects provided by the consensus + /// algorithm, don't use this function. + fn import_block( + &mut self, + mut import_block: BlockImportParams>, + new_cache: HashMap>, + ) -> Result { + let span = tracing::span!(tracing::Level::DEBUG, "import_block"); + let _enter = span.enter(); + + if let Some(res) = self.prepare_block_storage_changes(&mut import_block).map_err(|e| { + warn!("Block prepare storage changes error:\n{:?}", e); + ConsensusError::ClientImport(e.to_string()) + })? { + return Ok(res) + } + + self.lock_import_and_run(|operation| { + self.apply_block(operation, import_block, new_cache) + }).map_err(|e| { + warn!("Block import error:\n{:?}", e); + ConsensusError::ClientImport(e.to_string()).into() + }) + } + + /// Check block preconditions. + fn check_block( + &mut self, + block: BlockCheckParams, + ) -> Result { + let BlockCheckParams { hash, number, parent_hash, allow_missing_state, import_existing } = block; + + // Check the block against white and black lists if any are defined + // (i.e. fork blocks and bad blocks respectively) + match self.block_rules.lookup(number, &hash) { + BlockLookupResult::KnownBad => { + trace!( + "Rejecting known bad block: #{} {:?}", + number, + hash, + ); + return Ok(ImportResult::KnownBad); + }, + BlockLookupResult::Expected(expected_hash) => { + trace!( + "Rejecting block from known invalid fork. Got {:?}, expected: {:?} at height {}", + hash, + expected_hash, + number + ); + return Ok(ImportResult::KnownBad); + }, + BlockLookupResult::NotSpecial => {} + } + + // Own status must be checked first. If the block and ancestry is pruned + // this function must return `AlreadyInChain` rather than `MissingState` + match self.block_status(&BlockId::Hash(hash)) + .map_err(|e| ConsensusError::ClientImport(e.to_string()))? + { + BlockStatus::InChainWithState | BlockStatus::Queued if !import_existing => return Ok(ImportResult::AlreadyInChain), + BlockStatus::InChainWithState | BlockStatus::Queued => {}, + BlockStatus::InChainPruned => return Ok(ImportResult::AlreadyInChain), + BlockStatus::Unknown => {}, + BlockStatus::KnownBad => return Ok(ImportResult::KnownBad), + } + + match self.block_status(&BlockId::Hash(parent_hash)) + .map_err(|e| ConsensusError::ClientImport(e.to_string()))? + { + BlockStatus::InChainWithState | BlockStatus::Queued => {}, + BlockStatus::Unknown => return Ok(ImportResult::UnknownParent), + BlockStatus::InChainPruned if allow_missing_state => {}, + BlockStatus::InChainPruned => return Ok(ImportResult::MissingState), + BlockStatus::KnownBad => return Ok(ImportResult::KnownBad), + } + + + Ok(ImportResult::imported(false)) + } +} + +impl sp_consensus::BlockImport for Client where + B: backend::Backend, + E: CallExecutor + Send + Sync, + Block: BlockT, + Self: ProvideRuntimeApi, + >::Api: CoreApi + + ApiExt, +{ + type Error = ConsensusError; + type Transaction = backend::TransactionFor; + + fn import_block( + &mut self, + import_block: BlockImportParams, + new_cache: HashMap>, + ) -> Result { + (&*self).import_block(import_block, new_cache) + } + + fn check_block( + &mut self, + block: BlockCheckParams, + ) -> Result { + (&*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, + ) -> sp_blockchain::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, + ) -> sp_blockchain::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, + ) -> sp_blockchain::Result<()> { + (**self).apply_finality(operation, id, justification, notify) + } + + fn finalize_block( + &self, + id: BlockId, + justification: Option, + notify: bool, + ) -> sp_blockchain::Result<()> { + (**self).finalize_block(id, justification, notify) + } +} + +impl BlockchainEvents for Client +where + E: CallExecutor, + Block: BlockT, +{ + /// Get block import event stream. + fn import_notification_stream(&self) -> ImportNotifications { + let (sink, stream) = tracing_unbounded("mpsc_import_notification_stream"); + self.import_notification_sinks.lock().push(sink); + stream + } + + fn finality_notification_stream(&self) -> FinalityNotifications { + let (sink, stream) = tracing_unbounded("mpsc_finality_notification_stream"); + self.finality_notification_sinks.lock().push(sink); + stream + } + + /// Get storage changes event stream. + fn storage_changes_notification_stream( + &self, + filter_keys: Option<&[StorageKey]>, + child_filter_keys: Option<&[(StorageKey, Option>)]>, + ) -> sp_blockchain::Result> { + Ok(self.storage_notifications.lock().listen(filter_keys, child_filter_keys)) + } +} + +impl BlockBackend for Client + where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, +{ + fn block_body( + &self, + id: &BlockId, + ) -> sp_blockchain::Result::Extrinsic>>> { + self.body(id) + } + + fn block(&self, id: &BlockId) -> sp_blockchain::Result>> + { + Ok(match (self.header(id)?, self.body(id)?, self.justification(id)?) { + (Some(header), Some(extrinsics), justification) => + Some(SignedBlock { block: Block::new(header, extrinsics), justification }), + _ => None, + }) + } + + fn block_status(&self, id: &BlockId) -> sp_blockchain::Result { + // this can probably be implemented more efficiently + if let BlockId::Hash(ref h) = id { + if self.importing_block.read().as_ref().map_or(false, |importing| h == importing) { + return Ok(BlockStatus::Queued); + } + } + let hash_and_number = match id.clone() { + BlockId::Hash(hash) => self.backend.blockchain().number(hash)?.map(|n| (hash, n)), + BlockId::Number(n) => self.backend.blockchain().hash(n)?.map(|hash| (hash, n)), + }; + match hash_and_number { + Some((hash, number)) => { + if self.backend.have_state_at(&hash, number) { + Ok(BlockStatus::InChainWithState) + } else { + Ok(BlockStatus::InChainPruned) + } + } + None => Ok(BlockStatus::Unknown), + } + } + + fn justification(&self, id: &BlockId) -> sp_blockchain::Result> { + self.backend.blockchain().justification(*id) + } + + fn block_hash(&self, number: NumberFor) -> sp_blockchain::Result> { + self.backend.blockchain().hash(number) + } +} + +impl backend::AuxStore for Client + where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, + Self: ProvideRuntimeApi, + >::Api: CoreApi, +{ + /// Insert auxiliary data into key-value store. + fn insert_aux< + 'a, + 'b: 'a, + 'c: 'a, + I: IntoIterator, + D: IntoIterator, + >(&self, insert: I, delete: D) -> sp_blockchain::Result<()> { + // Import is locked here because we may have other block import + // operations that tries to set aux data. Note that for consensus + // layer, one can always use atomic operations to make sure + // import is only locked once. + self.lock_import_and_run(|operation| { + apply_aux(operation, insert, delete) + }) + } + /// Query auxiliary data from key-value store. + fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result>> { + backend::AuxStore::get_aux(&*self.backend, key) + } +} + +impl backend::AuxStore for &Client + where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: CoreApi, +{ + fn insert_aux< + 'a, + 'b: 'a, + 'c: 'a, + I: IntoIterator, + D: IntoIterator, + >(&self, insert: I, delete: D) -> sp_blockchain::Result<()> { + (**self).insert_aux(insert, delete) + } + + fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result>> { + (**self).get_aux(key) + } +} + +impl sp_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<_>) + } +} diff --git a/client/service/src/client/genesis.rs b/client/service/src/client/genesis.rs new file mode 100644 index 0000000000000000000000000000000000000000..4df08025e38264ab0a5f5b09631c95e4681d1b10 --- /dev/null +++ b/client/service/src/client/genesis.rs @@ -0,0 +1,43 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Tool for creating the genesis block. + +use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Hash as HashT, Zero}; + +/// Create a genesis block, given the initial storage. +pub fn construct_genesis_block< + Block: BlockT +> ( + state_root: Block::Hash +) -> Block { + let extrinsics_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( + Vec::new(), + ); + + Block::new( + <::Header as HeaderT>::new( + Zero::zero(), + extrinsics_root, + state_root, + Default::default(), + Default::default() + ), + Default::default() + ) +} diff --git a/client/service/src/client/light.rs b/client/service/src/client/light.rs new file mode 100644 index 0000000000000000000000000000000000000000..8b9b65fc2faddade57ead7c676fbfc8fd453dc2f --- /dev/null +++ b/client/service/src/client/light.rs @@ -0,0 +1,78 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Light client utilities. + +use std::sync::Arc; + +use sc_executor::RuntimeInfo; +use sp_core::traits::CodeExecutor; +use sp_runtime::BuildStorage; +use sp_runtime::traits::{Block as BlockT, HashFor}; +use sp_blockchain::Result as ClientResult; +use prometheus_endpoint::Registry; + +use super::call_executor::LocalCallExecutor; +use super::client::{Client,ClientConfig}; +use sc_client_api::{ + light::Storage as BlockchainStorage, CloneableSpawn, +}; +use sc_light::{Backend, GenesisCallExecutor}; + + +/// Create an instance of light client. +pub fn new_light( + backend: Arc>>, + genesis_storage: &dyn BuildStorage, + code_executor: E, + spawn_handle: Box, + prometheus_registry: Option, +) -> ClientResult< + Client< + Backend>, + GenesisCallExecutor< + Backend>, + LocalCallExecutor>, E> + >, + B, + RA + > + > + where + B: BlockT, + S: BlockchainStorage + 'static, + E: CodeExecutor + RuntimeInfo + Clone + 'static, +{ + let local_executor = LocalCallExecutor::new( + backend.clone(), + code_executor, + spawn_handle.clone(), + ClientConfig::default() + ); + let executor = GenesisCallExecutor::new(backend.clone(), local_executor); + Client::new( + backend, + executor, + genesis_storage, + Default::default(), + Default::default(), + Default::default(), + prometheus_registry, + ClientConfig::default(), + ) +} diff --git a/client/service/src/client/mod.rs b/client/service/src/client/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..7c96f61a7867a6f68aab035e69494db8e53d748a --- /dev/null +++ b/client/service/src/client/mod.rs @@ -0,0 +1,59 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Substrate Client and associated logic. +//! +//! The [`Client`] is one of the most important components of Substrate. It mainly comprises two +//! parts: +//! +//! - A database containing the blocks and chain state, generally referred to as +//! the [`Backend`](sc_client_api::backend::Backend). +//! - A runtime environment, generally referred to as the [`Executor`](CallExecutor). +//! +//! # Initialization +//! +//! Creating a [`Client`] is done by calling the `new` method and passing to it a +//! [`Backend`](sc_client_api::backend::Backend) and an [`Executor`](CallExecutor). +//! +//! The former is typically provided by the `sc-client-db` crate. +//! +//! The latter typically requires passing one of: +//! +//! - A [`LocalCallExecutor`] running the runtime locally. +//! - A [`RemoteCallExecutor`](light::call_executor::RemoteCallRequest) that will ask a +//! third-party to perform the executions. +//! - A [`RemoteOrLocalCallExecutor`](light::call_executor::RemoteOrLocalCallExecutor), combination +//! of the two. +//! +//! Additionally, the fourth generic parameter of the `Client` is a marker type representing +//! the ways in which the runtime can interface with the outside. Any code that builds a `Client` +//! is responsible for putting the right marker. + +pub mod genesis; +pub mod light; +mod call_executor; +mod client; +mod block_rules; + +pub use self::{ + call_executor::LocalCallExecutor, + client::{Client, ClientConfig}, +}; + +#[cfg(feature="test-helpers")] +pub use self::client::{new_with_backend, new_in_mem}; diff --git a/client/service/src/config.rs b/client/service/src/config.rs index 109ff1bfd50b56f9c828d4a54fb55ec5a3742754..397dacd747b14ecdf0b899b77c0c46014378922e 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -1,77 +1,57 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Service configuration. -pub use sc_client::ExecutionStrategies; -pub use sc_client_db::{kvdb::KeyValueDB, PruningMode}; -pub use sc_network::{Multiaddr, config::{MultiaddrWithPeerId, ExtTransport, NetworkConfiguration, Role}}; +pub use sc_client_db::{Database, PruningMode, DatabaseSettingsSrc as DatabaseConfig}; +pub use sc_network::Multiaddr; +pub use sc_network::config::{ExtTransport, MultiaddrWithPeerId, NetworkConfiguration, Role, NodeKeyConfig}; pub use sc_executor::WasmExecutionMethod; +use sc_client_api::execution_extensions::ExecutionStrategies; -use std::{future::Future, path::{PathBuf, Path}, pin::Pin, net::SocketAddr, sync::Arc}; +use std::{io, future::Future, path::{PathBuf, Path}, pin::Pin, net::SocketAddr, sync::Arc}; pub use sc_transaction_pool::txpool::Options as TransactionPoolOptions; use sc_chain_spec::ChainSpec; -use sp_core::crypto::Protected; -use target_info::Target; -use sc_telemetry::TelemetryEndpoints; +use sp_core::crypto::SecretString; +pub use sc_telemetry::TelemetryEndpoints; use prometheus_endpoint::Registry; - -/// Executable version. Used to pass version information from the root crate. -#[derive(Clone)] -pub struct VersionInfo { - /// Implementation name. - pub name: &'static str, - /// Implementation version. - pub version: &'static str, - /// SCM Commit hash. - pub commit: &'static str, - /// Executable file name. - pub executable_name: &'static str, - /// Executable file description. - pub description: &'static str, - /// Executable file author. - pub author: &'static str, - /// Support URL. - pub support_url: &'static str, - /// Copyright starting year (x-current year) - pub copyright_start_year: i32, -} +#[cfg(not(target_os = "unknown"))] +use tempfile::TempDir; /// Service configuration. +#[derive(Debug)] pub struct Configuration { /// Implementation name - pub impl_name: &'static str, - /// Implementation version - pub impl_version: &'static str, - /// Git commit if any. - pub impl_commit: &'static str, + pub impl_name: String, + /// Implementation version (see sc-cli to see an example of format) + pub impl_version: String, /// Node role. pub role: Role, /// How to spawn background tasks. Mandatory, otherwise creating a `Service` will error. - pub task_executor: Option + Send>>) + Send + Sync>>, + pub task_executor: TaskExecutor, /// Extrinsic pool configuration. pub transaction_pool: TransactionPoolOptions, /// Network configuration. pub network: NetworkConfiguration, - /// Path to the base configuration directory. - pub config_dir: Option, /// Configuration for the keystore. pub keystore: KeystoreConfig, /// Configuration for the database. - pub database: Option, + 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 @@ -79,9 +59,7 @@ pub struct Configuration { /// Pruning settings. pub pruning: PruningMode, /// Chain configuration. - pub chain_spec: Option>, - /// Node name. - pub name: String, + pub chain_spec: Box, /// Wasm execution method. pub wasm_method: WasmExecutionMethod, /// Execution strategies. @@ -90,10 +68,14 @@ pub struct Configuration { pub rpc_http: Option, /// RPC over Websockets binding address. `None` if disabled. pub rpc_ws: Option, + /// RPC over IPC binding path. `None` if disabled. + pub rpc_ipc: Option, /// Maximum number of connections for WebSockets RPC server. `None` if default. pub rpc_ws_max_connections: Option, /// CORS settings for HTTP & WS servers. `None` if all origins are allowed. pub rpc_cors: Option>, + /// RPC methods to expose (by default only a safe subset or all of them). + pub rpc_methods: RpcMethods, /// Prometheus endpoint configuration. `None` if disabled. pub prometheus_config: Option, /// Telemetry service URL. `None` if disabled. @@ -104,7 +86,7 @@ pub struct Configuration { /// The default number of 64KB pages to allocate for Wasm execution pub default_heap_pages: Option, /// Should offchain workers be executed. - pub offchain_worker: bool, + pub offchain_worker: OffchainWorkerConfig, /// Enable authoring even when offline. pub force_authoring: bool, /// Disable GRANDPA when running in validator mode @@ -125,19 +107,30 @@ pub struct Configuration { pub max_runtime_instances: usize, /// Announce block automatically after they have been imported pub announce_block: bool, + /// Base path of the configuration + pub base_path: Option, + /// Configuration of the output format that the informant uses. + pub informant_output_format: sc_informant::OutputFormat, +} + +/// Type for tasks spawned by the executor. +#[derive(PartialEq)] +pub enum TaskType { + /// Regular non-blocking futures. Polling the task is expected to be a lightweight operation. + Async, + /// The task might perform a lot of expensive CPU operations and/or call `thread::sleep`. + Blocking, } /// Configuration of the client keystore. -#[derive(Clone)] +#[derive(Debug, Clone)] pub enum KeystoreConfig { - /// No config supplied. - None, /// Keystore at a path on-disk. Recommended for native nodes. Path { /// The path of the keystore. path: PathBuf, /// Node keystore's password. - password: Option> + password: Option }, /// In-memory keystore. Recommended for in-browser nodes. InMemory, @@ -147,29 +140,22 @@ impl KeystoreConfig { /// Returns the path for the keystore. pub fn path(&self) -> Option<&Path> { match self { - Self::Path { path, .. } => Some(&path), - Self::None | Self::InMemory => None, + Self::Path { path, .. } => Some(path), + Self::InMemory => None, } } } - /// 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), +#[derive(Debug, Clone, Default)] +pub struct OffchainWorkerConfig { + /// If this is allowed. + pub enabled: bool, + /// allow writes from the runtime to the offchain worker database. + pub indexing_enabled: bool, } /// Configuration of the Prometheus endpoint. -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct PrometheusConfig { /// Port to use. pub port: SocketAddr, @@ -190,123 +176,155 @@ impl PrometheusConfig { } } -impl Default for Configuration { - /// Create a default config - fn default() -> Self { - Configuration { - impl_name: "parity-substrate", - impl_version: "0.0.0", - impl_commit: "", - chain_spec: None, - config_dir: None, - name: Default::default(), - role: Role::Full, - task_executor: None, - transaction_pool: Default::default(), - network: Default::default(), - keystore: KeystoreConfig::None, - database: None, - state_cache_size: Default::default(), - state_cache_child_ratio: Default::default(), - pruning: PruningMode::default(), - wasm_method: WasmExecutionMethod::Interpreted, - execution_strategies: Default::default(), - rpc_http: None, - rpc_ws: None, - rpc_ws_max_connections: None, - rpc_cors: Some(vec![]), - prometheus_config: None, - telemetry_endpoints: None, - telemetry_external_transport: None, - default_heap_pages: None, - offchain_worker: Default::default(), - force_authoring: false, - disable_grandpa: false, - dev_key_seed: None, - tracing_targets: Default::default(), - tracing_receiver: Default::default(), - max_runtime_instances: 8, - announce_block: true, - } - } -} - impl Configuration { - /// Create a default config using `VersionInfo` - pub fn from_version(version: &VersionInfo) -> Self { - let mut config = Configuration::default(); - config.impl_name = version.name; - config.impl_version = version.version; - config.impl_commit = version.commit; - - config + /// Returns a string displaying the node role. + pub fn display_role(&self) -> String { + self.role.to_string() } - /// Returns full version string of this configuration. - pub fn full_version(&self) -> String { - full_version_from_strs(self.impl_version, self.impl_commit) + /// Returns the prometheus metrics registry, if available. + pub fn prometheus_registry<'a>(&'a self) -> Option<&'a Registry> { + self.prometheus_config.as_ref().map(|config| &config.registry) } +} - /// Implementation id and version. - pub fn client_id(&self) -> String { - format!("{}/v{}", self.impl_name, self.full_version()) - } +/// Available RPC methods. +#[derive(Debug, Copy, Clone)] +pub enum RpcMethods { + /// Expose every RPC method only when RPC is listening on `localhost`, + /// otherwise serve only safe RPC methods. + Auto, + /// Allow only a safe subset of RPC methods. + Safe, + /// Expose every RPC method (even potentially unsafe ones). + Unsafe, +} - /// 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.expect_chain_spec().id()); - path.push(sub); - path - }) +impl Default for RpcMethods { + fn default() -> RpcMethods { + RpcMethods::Auto } +} - /// Return a reference to the `ChainSpec` of this `Configuration`. - /// - /// ### Panics +/// The base path that is used for everything that needs to be write on disk to run a node. +#[derive(Debug)] +pub enum BasePath { + /// A temporary directory is used as base path and will be deleted when dropped. + #[cfg(not(target_os = "unknown"))] + Temporary(TempDir), + /// A path on the disk. + Permanenent(PathBuf), +} + +impl BasePath { + /// Create a `BasePath` instance using a temporary directory prefixed with "substrate" and use + /// it as base path. /// - /// This method panic if the `chain_spec` is `None` - pub fn expect_chain_spec(&self) -> &dyn ChainSpec { - &**self.chain_spec.as_ref().expect("chain_spec must be specified") + /// Note: the temporary directory will be created automatically and deleted when the `BasePath` + /// instance is dropped. + #[cfg(not(target_os = "unknown"))] + pub fn new_temp_dir() -> io::Result { + Ok(BasePath::Temporary( + tempfile::Builder::new().prefix("substrate").tempdir()?, + )) } - /// Return a reference to the `DatabaseConfig` of this `Configuration`. + /// Create a `BasePath` instance based on an existing path on disk. /// - /// ### Panics - /// - /// This method panic if the `database` is `None` - pub fn expect_database(&self) -> &DatabaseConfig { - self.database.as_ref().expect("database must be specified") + /// Note: this function will not ensure that the directory exist nor create the directory. It + /// will also not delete the directory when the instance is dropped. + pub fn new>(path: P) -> BasePath { + BasePath::Permanenent(path.as_ref().to_path_buf()) } - /// Returns a string displaying the node role. - pub fn display_role(&self) -> String { - self.role.to_string() + /// Create a base path from values describing the project. + #[cfg(not(target_os = "unknown"))] + pub fn from_project(qualifier: &str, organization: &str, application: &str) -> BasePath { + BasePath::new( + directories::ProjectDirs::from(qualifier, organization, application) + .expect("app directories exist on all supported platforms; qed") + .data_local_dir(), + ) } - /// Use in memory keystore config when it is not required at all. - /// - /// This function returns an error if the keystore is already set to something different than - /// `KeystoreConfig::None`. - pub fn use_in_memory_keystore(&mut self) -> Result<(), String> { - match &mut self.keystore { - cfg @ KeystoreConfig::None => { *cfg = KeystoreConfig::InMemory; Ok(()) }, - _ => Err("Keystore config specified when it should not be!".into()), + /// Retrieve the base path. + pub fn path(&self) -> &Path { + match self { + #[cfg(not(target_os = "unknown"))] + BasePath::Temporary(temp_dir) => temp_dir.path(), + BasePath::Permanenent(path) => path.as_path(), } } } -/// Returns platform info -pub fn platform() -> String { - let env = Target::env(); - let env_dash = if env.is_empty() { "" } else { "-" }; - format!("{}-{}{}{}", Target::arch(), Target::os(), env_dash, env) +impl std::convert::From for BasePath { + fn from(path: PathBuf) -> Self { + BasePath::new(path) + } } -/// Returns full version string, using supplied version and commit. -pub fn full_version_from_strs(impl_version: &str, impl_commit: &str) -> String { - let commit_dash = if impl_commit.is_empty() { "" } else { "-" }; - format!("{}{}{}-{}", impl_version, commit_dash, impl_commit, platform()) +type TaskExecutorInner = Arc + Send>>, TaskType) + Send + Sync>; + +/// Callable object that execute tasks. +/// +/// This struct can be created easily using `Into`. +/// +/// # Examples +/// +/// ## Using tokio +/// +/// ``` +/// # use sc_service::TaskExecutor; +/// # mod tokio { pub mod runtime { +/// # #[derive(Clone)] +/// # pub struct Runtime; +/// # impl Runtime { +/// # pub fn new() -> Result { Ok(Runtime) } +/// # pub fn handle(&self) -> &Self { &self } +/// # pub fn spawn(&self, _: std::pin::Pin + Send>>) {} +/// # } +/// # } } +/// use tokio::runtime::Runtime; +/// +/// let runtime = Runtime::new().unwrap(); +/// let handle = runtime.handle().clone(); +/// let task_executor: TaskExecutor = (move |future, _task_type| { +/// handle.spawn(future); +/// }).into(); +/// ``` +/// +/// ## Using async-std +/// +/// ``` +/// # use sc_service::TaskExecutor; +/// # mod async_std { pub mod task { +/// # pub fn spawn(_: std::pin::Pin + Send>>) {} +/// # } } +/// let task_executor: TaskExecutor = (|future, _task_type| { +/// async_std::task::spawn(future); +/// }).into(); +/// ``` +#[derive(Clone)] +pub struct TaskExecutor(TaskExecutorInner); + +impl std::fmt::Debug for TaskExecutor { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "TaskExecutor") + } +} + +impl std::convert::From for TaskExecutor +where + F: Fn(Pin + Send>>, TaskType) + Send + Sync + 'static, +{ + fn from(x: F) -> Self { + Self(Arc::new(x)) + } +} + +impl TaskExecutor { + /// Spawns a new asynchronous task. + pub fn spawn(&self, future: Pin + Send>>, task_type: TaskType) { + self.0(future, task_type) + } } diff --git a/client/service/src/error.rs b/client/service/src/error.rs index 5a78a1878923080ee05d2c5c46568356b8a71a59..ffe1b39405501d224b7c56f40facb11776775f10 100644 --- a/client/service/src/error.rs +++ b/client/service/src/error.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Errors that can occur during the service operation. diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 0ceb310d07c80c78125d7a3a2aec62c40ff86042..b8b722503749cf9fd7fec1d20883ea863527c152 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -1,79 +1,84 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Substrate service. Starts a thread that spins up the network, client, and extrinsic pool. //! Manages communication between them. #![warn(missing_docs)] +#![recursion_limit = "1024"] pub mod config; -#[macro_use] pub mod chain_ops; pub mod error; mod metrics; mod builder; -mod status_sinks; +#[cfg(feature = "test-helpers")] +pub mod client; +#[cfg(not(feature = "test-helpers"))] +mod client; mod task_manager; -use std::{borrow::Cow, io, pin::Pin}; -use std::marker::PhantomData; +use std::{io, pin::Pin}; use std::net::SocketAddr; use std::collections::HashMap; use std::time::Duration; -use wasm_timer::Instant; -use std::task::{Poll, Context}; +use std::task::Poll; use parking_lot::Mutex; -use sc_client::Client; -use futures::{ - Future, FutureExt, Stream, StreamExt, - compat::*, - sink::SinkExt, - task::{Spawn, FutureObj, SpawnError}, -}; -use sc_network::{NetworkService, network_state::NetworkState, PeerId, ReportHandle}; -use log::{log, warn, debug, error, Level}; +use futures::{Future, FutureExt, Stream, StreamExt, stream, compat::*}; +use sc_network::{NetworkStatus, network_state::NetworkState, PeerId}; +use log::{warn, debug, error}; use codec::{Encode, Decode}; use sp_runtime::generic::BlockId; -use sp_runtime::traits::{NumberFor, Block as BlockT}; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; use parity_util_mem::MallocSizeOf; -use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; +use sp_utils::{status_sinks, mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}}; pub use self::error::Error; pub use self::builder::{ - new_full_client, - ServiceBuilder, ServiceBuilderCommand, TFullClient, TLightClient, TFullBackend, TLightBackend, - TFullCallExecutor, TLightCallExecutor, + new_full_client, new_client, + ServiceBuilder, TFullClient, TLightClient, TFullBackend, TLightBackend, + TFullCallExecutor, TLightCallExecutor, RpcExtensionBuilder, +}; +pub use config::{ + BasePath, Configuration, DatabaseConfig, PruningMode, Role, RpcMethods, TaskExecutor, TaskType, }; -pub use config::{Configuration, Role, PruningMode, DatabaseConfig}; pub use sc_chain_spec::{ - ChainSpec, GenericChainSpec, Properties, RuntimeGenesis, Extension as ChainSpecExtension + ChainSpec, GenericChainSpec, Properties, RuntimeGenesis, Extension as ChainSpecExtension, + NoExtension, ChainType, }; pub use sp_transaction_pool::{TransactionPool, InPoolTransaction, error::IntoPoolError}; pub use sc_transaction_pool::txpool::Options as TransactionPoolOptions; -pub use sc_client::FinalityNotifications; pub use sc_rpc::Metadata as RpcMetadata; pub use sc_executor::NativeExecutionDispatch; #[doc(hidden)] pub use std::{ops::Deref, result::Result, sync::Arc}; #[doc(hidden)] -pub use sc_network::config::{FinalityProofProvider, OnDemand, BoxFinalityProofRequestBuilder}; -pub use task_manager::{TaskManagerBuilder, SpawnTaskHandle}; -use task_manager::TaskManager; +pub use sc_network::config::{ + FinalityProofProvider, OnDemand, BoxFinalityProofRequestBuilder, TransactionImport, + TransactionImportFuture, +}; +pub use sc_tracing::TracingReceiver; +pub use task_manager::SpawnTaskHandle; +pub use task_manager::TaskManager; +pub use sp_consensus::import_queue::ImportQueue; +use sc_client_api::{Backend, BlockchainEvents}; const DEFAULT_PROTOCOL_ID: &str = "sup"; @@ -87,69 +92,10 @@ impl MallocSizeOfWasm for T {} #[cfg(target_os = "unknown")] impl MallocSizeOfWasm for T {} -/// Substrate service. -pub struct Service { - client: Arc, - task_manager: TaskManager, - select_chain: Option, - network: Arc, - /// Sinks to propagate network status updates. - /// For each element, every time the `Interval` fires we push an element on the sender. - network_status_sinks: Arc>>, - transaction_pool: Arc, - /// Send a signal when a spawned essential task has concluded. The next time - /// the service future is polled it should complete with an error. - essential_failed_tx: TracingUnboundedSender<()>, - /// A receiver for spawned essential-tasks concluding. - essential_failed_rx: TracingUnboundedReceiver<()>, - rpc_handlers: sc_rpc_server::RpcHandler, - _rpc: Box, - _telemetry: Option, - _telemetry_on_connect_sinks: Arc>>>, - _offchain_workers: Option>, - keystore: sc_keystore::KeyStorePtr, - marker: PhantomData, - prometheus_registry: Option, -} - -impl Unpin for Service {} - -/// Abstraction over a Substrate service. -pub trait AbstractService: 'static + Future> + - Spawn + Send + Unpin { - /// Type of block of this chain. - type Block: BlockT; - /// Backend storage for the client. - type Backend: 'static + sc_client_api::backend::Backend; - /// How to execute calls towards the runtime. - type CallExecutor: 'static + sc_client::CallExecutor + Send + Sync + Clone; - /// API that the runtime provides. - type RuntimeApi: Send + Sync; - /// Chain selection algorithm. - type SelectChain: sp_consensus::SelectChain; - /// Transaction pool. - type TransactionPool: TransactionPool + MallocSizeOfWasm; - - /// Get event stream for telemetry connection established events. - fn telemetry_on_connect_stream(&self) -> TracingUnboundedReceiver<()>; - - /// return a shared instance of Telemetry (if enabled) - fn telemetry(&self) -> Option; - - /// Spawns a task in the background that runs the future passed as parameter. - fn spawn_task(&self, name: impl Into>, task: impl Future + Send + 'static); - - /// 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, name: impl Into>, task: impl Future + Send + 'static); - - /// Returns a handle for spawning tasks. - fn spawn_task_handle(&self) -> SpawnTaskHandle; - - /// Returns the keystore that stores keys. - fn keystore(&self) -> sc_keystore::KeyStorePtr; +/// RPC handlers that can perform RPC queries. +pub struct RpcHandlers(sc_rpc_server::RpcHandler); +impl RpcHandlers { /// Starts an RPC query. /// /// The query is passed as a string and must be a JSON text similar to what an HTTP client @@ -159,311 +105,233 @@ pub trait AbstractService: 'static + Future> + /// /// 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) -> Pin> + Send>>; - - /// Get shared client instance. - fn client(&self) -> Arc>; - - /// Get clone of select chain. - fn select_chain(&self) -> Option; - - /// Get shared network instance. - fn network(&self) - -> Arc::Hash>>; - - /// Returns a receiver that periodically receives a status of the network. - fn network_status(&self, interval: Duration) -> TracingUnboundedReceiver<(NetworkStatus, NetworkState)>; - - /// Get shared transaction pool instance. - fn transaction_pool(&self) -> Arc; - - /// Get a handle to a future that will resolve on exit. - #[deprecated(note = "Use `spawn_task`/`spawn_essential_task` instead, those functions will attach on_exit signal.")] - fn on_exit(&self) -> ::exit_future::Exit; - - /// Get the prometheus metrics registry, if available. - fn prometheus_registry(&self) -> Option; -} - -impl AbstractService for - Service, TSc, NetworkStatus, - NetworkService, TExPool, TOc> -where - TBl: BlockT, - TBackend: 'static + sc_client_api::backend::Backend, - TExec: 'static + sc_client::CallExecutor + Send + Sync + Clone, - TRtApi: 'static + Send + Sync, - TSc: sp_consensus::SelectChain + 'static + Clone + Send + Unpin, - TExPool: 'static + TransactionPool + MallocSizeOfWasm, - TOc: 'static + Send + Sync, -{ - type Block = TBl; - type Backend = TBackend; - type CallExecutor = TExec; - type RuntimeApi = TRtApi; - type SelectChain = TSc; - type TransactionPool = TExPool; - - fn telemetry_on_connect_stream(&self) -> TracingUnboundedReceiver<()> { - let (sink, stream) = tracing_unbounded("mpsc_telemetry_on_connect"); - self._telemetry_on_connect_sinks.lock().push(sink); - stream - } - - fn telemetry(&self) -> Option { - self._telemetry.as_ref().map(|t| t.clone()) - } - - fn keystore(&self) -> sc_keystore::KeyStorePtr { - self.keystore.clone() - } - - fn spawn_task(&self, name: impl Into>, task: impl Future + Send + 'static) { - self.task_manager.spawn(name, task) - } - - fn spawn_essential_task(&self, name: impl Into>, task: impl Future + Send + 'static) { - let mut essential_failed = self.essential_failed_tx.clone(); - let essential_task = std::panic::AssertUnwindSafe(task) - .catch_unwind() - .map(move |_| { - error!("Essential task failed. Shutting down service."); - let _ = essential_failed.send(()); - }); - - let _ = self.spawn_task(name, essential_task); - } - - fn spawn_task_handle(&self) -> SpawnTaskHandle { - self.task_manager.spawn_handle() - } - - fn rpc_query(&self, mem: &RpcSession, request: &str) -> Pin> + Send>> { - Box::pin( - self.rpc_handlers.handle_request(request, mem.metadata.clone()) - .compat() - .map(|res| res.expect("this should never fail")) - ) - } - - fn client(&self) -> Arc> { - self.client.clone() - } - - fn select_chain(&self) -> Option { - self.select_chain.clone() + pub fn rpc_query(&self, mem: &RpcSession, request: &str) + -> Pin> + Send>> { + self.0.handle_request(request, mem.metadata.clone()) + .compat() + .map(|res| res.expect("this should never fail")) + .boxed() } +} - fn network(&self) - -> Arc::Hash>> - { - self.network.clone() +/// Sinks to propagate network status updates. +/// For each element, every time the `Interval` fires we push an element on the sender. +pub struct NetworkStatusSinks( + Arc, NetworkState)>>, +); + +impl NetworkStatusSinks { + fn new( + sinks: Arc, NetworkState)>> + ) -> Self { + Self(sinks) } - fn network_status(&self, interval: Duration) -> TracingUnboundedReceiver<(NetworkStatus, NetworkState)> { + /// Returns a receiver that periodically receives a status of the network. + pub fn network_status(&self, interval: Duration) + -> TracingUnboundedReceiver<(NetworkStatus, NetworkState)> { let (sink, stream) = tracing_unbounded("mpsc_network_status"); - self.network_status_sinks.lock().push(interval, sink); + self.0.push(interval, sink); stream } - - fn transaction_pool(&self) -> Arc { - self.transaction_pool.clone() - } - - fn on_exit(&self) -> exit_future::Exit { - self.task_manager.on_exit() - } - - fn prometheus_registry(&self) -> Option { - self.prometheus_registry.clone() - } } -impl Future for - Service -{ - type Output = Result<(), Error>; +/// Sinks to propagate telemetry connection established events. +pub struct TelemetryOnConnectSinks(pub Arc>>>); - fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { - let this = Pin::into_inner(self); - - match Pin::new(&mut this.essential_failed_rx).poll_next(cx) { - Poll::Pending => {}, - Poll::Ready(_) => { - // Ready(None) should not be possible since we hold a live - // sender. - return Poll::Ready(Err(Error::Other("Essential task failed.".into()))); - } - } - - this.task_manager.process_receiver(cx); - - // The service future never ends. - Poll::Pending +impl TelemetryOnConnectSinks { + /// Get event stream for telemetry connection established events. + pub fn on_connect_stream(&self) -> TracingUnboundedReceiver<()> { + let (sink, stream) =tracing_unbounded("mpsc_telemetry_on_connect"); + self.0.lock().push(sink); + stream } } -impl Spawn for - Service -{ - fn spawn_obj( - &self, - future: FutureObj<'static, ()> - ) -> Result<(), SpawnError> { - self.task_manager.scheduler().unbounded_send((Box::pin(future), From::from("unnamed"))) - .map_err(|_| SpawnError::shutdown()) - } +/// The individual components of the chain, built by the service builder. You are encouraged to +/// deconstruct this into its fields. +pub struct ServiceComponents, TSc, TExPool, TCl> { + /// A blockchain client. + pub client: Arc, + /// A shared transaction pool instance. + pub transaction_pool: Arc, + /// The chain task manager. + pub task_manager: TaskManager, + /// A keystore that stores keys. + pub keystore: sc_keystore::KeyStorePtr, + /// A shared network instance. + pub network: Arc::Hash>>, + /// RPC handlers that can perform RPC queries. + pub rpc_handlers: Arc, + /// A shared instance of the chain selection algorithm. + pub select_chain: Option, + /// Sinks to propagate network status updates. + pub network_status_sinks: NetworkStatusSinks, + /// A prometheus metrics registry, (if enabled). + pub prometheus_registry: Option, + /// Shared Telemetry connection sinks, + pub telemetry_on_connect_sinks: TelemetryOnConnectSinks, + /// A shared offchain workers instance. + pub offchain_workers: Option>>, } /// Builds a never-ending future that continuously polls the network. /// /// The `status_sink` contain a list of senders to send a periodic network status to. -fn build_network_future< +async fn build_network_future< B: BlockT, - C: sc_client::BlockchainEvents, + C: BlockchainEvents, H: sc_network::ExHashT > ( role: Role, mut network: sc_network::NetworkWorker, client: Arc, - status_sinks: Arc, NetworkState)>>>, + status_sinks: Arc, NetworkState)>>, mut rpc_rx: TracingUnboundedReceiver>, should_have_peers: bool, announce_imported_blocks: bool, -) -> impl Future { +) { let mut imported_blocks_stream = client.import_notification_stream().fuse(); - let mut finality_notification_stream = client.finality_notification_stream().fuse(); - futures::future::poll_fn(move |cx| { - let before_polling = Instant::now(); + // Stream of finalized blocks reported by the client. + let mut finality_notification_stream = { + let mut finality_notification_stream = client.finality_notification_stream().fuse(); - // We poll `imported_blocks_stream`. - while let Poll::Ready(Some(notification)) = Pin::new(&mut imported_blocks_stream).poll_next(cx) { - network.on_block_imported(notification.header, notification.is_new_best); + // We tweak the `Stream` in order to merge together multiple items if they happen to be + // ready. This way, we only get the latest finalized block. + stream::poll_fn(move |cx| { + let mut last = None; + while let Poll::Ready(Some(item)) = Pin::new(&mut finality_notification_stream).poll_next(cx) { + last = Some(item); + } + if let Some(last) = last { + Poll::Ready(Some(last)) + } else { + Poll::Pending + } + }).fuse() + }; + + loop { + futures::select!{ + // List of blocks that the client has imported. + notification = imported_blocks_stream.next() => { + let notification = match notification { + Some(n) => n, + // If this stream is shut down, that means the client has shut down, and the + // most appropriate thing to do for the network future is to shut down too. + None => return, + }; + + if announce_imported_blocks { + network.service().announce_block(notification.hash, Vec::new()); + } - if announce_imported_blocks { - network.service().announce_block(notification.hash, Vec::new()); + if let sp_consensus::BlockOrigin::Own = notification.origin { + network.service().own_block_imported( + notification.hash, + notification.header.number().clone(), + ); + } } - } - // We poll `finality_notification_stream`, but we only take the last event. - let mut last = None; - while let Poll::Ready(Some(item)) = Pin::new(&mut finality_notification_stream).poll_next(cx) { - last = Some(item); - } - if let Some(notification) = last { - network.on_block_finalized(notification.hash, notification.header); - } + // List of blocks that the client has finalized. + notification = finality_notification_stream.select_next_some() => { + network.on_block_finalized(notification.hash, notification.header); + } - // Poll the RPC requests and answer them. - while let Poll::Ready(Some(request)) = Pin::new(&mut rpc_rx).poll_next(cx) { - match request { - sc_rpc::system::Request::Health(sender) => { - let _ = sender.send(sc_rpc::system::Health { - peers: network.peers_debug_info().len(), - is_syncing: network.service().is_major_syncing(), - should_have_peers, - }); - }, - sc_rpc::system::Request::Peers(sender) => { - let _ = sender.send(network.peers_debug_info().into_iter().map(|(peer_id, p)| - sc_rpc::system::PeerInfo { - peer_id: peer_id.to_base58(), - roles: format!("{:?}", p.roles), - protocol_version: p.protocol_version, - best_hash: p.best_hash, - best_number: p.best_number, - } - ).collect()); - } - sc_rpc::system::Request::NetworkState(sender) => { - if let Some(network_state) = serde_json::to_value(&network.network_state()).ok() { - let _ = sender.send(network_state); + // Answer incoming RPC requests. + request = rpc_rx.select_next_some() => { + match request { + sc_rpc::system::Request::Health(sender) => { + let _ = sender.send(sc_rpc::system::Health { + peers: network.peers_debug_info().len(), + is_syncing: network.service().is_major_syncing(), + should_have_peers, + }); + }, + sc_rpc::system::Request::LocalPeerId(sender) => { + let _ = sender.send(network.local_peer_id().to_base58()); + }, + sc_rpc::system::Request::LocalListenAddresses(sender) => { + let peer_id = network.local_peer_id().clone().into(); + let p2p_proto_suffix = sc_network::multiaddr::Protocol::P2p(peer_id); + let addresses = network.listen_addresses() + .map(|addr| addr.clone().with(p2p_proto_suffix.clone()).to_string()) + .collect(); + let _ = sender.send(addresses); + }, + sc_rpc::system::Request::Peers(sender) => { + let _ = sender.send(network.peers_debug_info().into_iter().map(|(peer_id, p)| + sc_rpc::system::PeerInfo { + peer_id: peer_id.to_base58(), + roles: format!("{:?}", p.roles), + protocol_version: p.protocol_version, + best_hash: p.best_hash, + best_number: p.best_number, + } + ).collect()); } - } - sc_rpc::system::Request::NetworkAddReservedPeer(peer_addr, sender) => { - let x = network.add_reserved_peer(peer_addr) - .map_err(sc_rpc::system::error::Error::MalformattedPeerArg); - let _ = sender.send(x); - } - sc_rpc::system::Request::NetworkRemoveReservedPeer(peer_id, sender) => { - let _ = match peer_id.parse::() { - Ok(peer_id) => { - network.remove_reserved_peer(peer_id); - sender.send(Ok(())) + sc_rpc::system::Request::NetworkState(sender) => { + if let Some(network_state) = serde_json::to_value(&network.network_state()).ok() { + let _ = sender.send(network_state); } - Err(e) => sender.send(Err(sc_rpc::system::error::Error::MalformattedPeerArg( - e.to_string(), - ))), - }; - } - sc_rpc::system::Request::NodeRoles(sender) => { - use sc_rpc::system::NodeRole; + } + sc_rpc::system::Request::NetworkAddReservedPeer(peer_addr, sender) => { + let x = network.add_reserved_peer(peer_addr) + .map_err(sc_rpc::system::error::Error::MalformattedPeerArg); + let _ = sender.send(x); + } + sc_rpc::system::Request::NetworkRemoveReservedPeer(peer_id, sender) => { + let _ = match peer_id.parse::() { + Ok(peer_id) => { + network.remove_reserved_peer(peer_id); + sender.send(Ok(())) + } + Err(e) => sender.send(Err(sc_rpc::system::error::Error::MalformattedPeerArg( + e.to_string(), + ))), + }; + } + sc_rpc::system::Request::NodeRoles(sender) => { + use sc_rpc::system::NodeRole; - let node_role = match role { - Role::Authority { .. } => NodeRole::Authority, - Role::Light => NodeRole::LightClient, - Role::Full => NodeRole::Full, - Role::Sentry { .. } => NodeRole::Sentry, - }; + let node_role = match role { + Role::Authority { .. } => NodeRole::Authority, + Role::Light => NodeRole::LightClient, + Role::Full => NodeRole::Full, + Role::Sentry { .. } => NodeRole::Sentry, + }; - let _ = sender.send(vec![node_role]); + let _ = sender.send(vec![node_role]); + } } - }; - } + } - // Interval report for the external API. - status_sinks.lock().poll(cx, || { - let status = NetworkStatus { - sync_state: network.sync_state(), - best_seen_block: network.best_seen_block(), - num_sync_peers: network.num_sync_peers(), - num_connected_peers: network.num_connected_peers(), - num_active_peers: network.num_active_peers(), - average_download_per_sec: network.average_download_per_sec(), - average_upload_per_sec: network.average_upload_per_sec(), - }; - let state = network.network_state(); - (status, state) - }); - - // Main network polling. - if let Poll::Ready(Ok(())) = Pin::new(&mut network).poll(cx).map_err(|err| { - warn!(target: "service", "Error in network: {:?}", err); - }) { - return Poll::Ready(()); + // The network worker has done something. Nothing special to do, but could be + // used in the future to perform actions in response of things that happened on + // the network. + _ = (&mut network).fuse() => {} + + // At a regular interval, we send the state of the network on what is called + // the "status sinks". + ready_sink = status_sinks.next().fuse() => { + let status = NetworkStatus { + sync_state: network.sync_state(), + best_seen_block: network.best_seen_block(), + num_sync_peers: network.num_sync_peers(), + num_connected_peers: network.num_connected_peers(), + num_active_peers: network.num_active_peers(), + average_download_per_sec: network.average_download_per_sec(), + average_upload_per_sec: network.average_upload_per_sec(), + }; + let state = network.network_state(); + ready_sink.send((status, state)); + } } - - // Now some diagnostic for performances. - let polling_dur = before_polling.elapsed(); - log!( - target: "service", - if polling_dur >= Duration::from_secs(1) { Level::Warn } else { Level::Trace }, - "⚠️ Polling the network future took {:?}", - polling_dur - ); - - Poll::Pending - }) -} - -/// Overview status of the network. -#[derive(Clone)] -pub struct NetworkStatus { - /// Current global sync state. - pub sync_state: sc_network::SyncState, - /// Target sync block number. - pub best_seen_block: Option>, - /// Number of peers participating in syncing. - pub num_sync_peers: u32, - /// Total number of connected peers - pub num_connected_peers: usize, - /// Total number of active peers. - pub num_active_peers: usize, - /// Downloaded bytes per second averaged over the past few seconds. - pub average_download_per_sec: u64, - /// Uploaded bytes per second averaged over the past few seconds. - pub average_upload_per_sec: u64, + } } #[cfg(not(target_os = "unknown"))] @@ -479,6 +347,16 @@ mod waiting { } } + pub struct IpcServer(pub Option); + impl Drop for IpcServer { + fn drop(&mut self) { + if let Some(server) = self.0.take() { + server.close_handle().close(); + let _ = server.wait(); + } + } + } + pub struct WsServer(pub Option); impl Drop for WsServer { fn drop(&mut self) { @@ -492,7 +370,7 @@ mod waiting { /// 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 sc_rpc_server::RpcHandler>( +fn start_rpc_servers sc_rpc_server::RpcHandler>( config: &Configuration, mut gen_handler: H ) -> Result, error::Error> { @@ -514,10 +392,24 @@ fn start_rpc_servers sc_rpc_server::RpcHandler>( }) } + fn deny_unsafe(addr: &SocketAddr, methods: &RpcMethods) -> sc_rpc::DenyUnsafe { + let is_exposed_addr = !addr.ip().is_loopback(); + match (is_exposed_addr, methods) { + | (_, RpcMethods::Unsafe) + | (false, RpcMethods::Auto) => sc_rpc::DenyUnsafe::No, + _ => sc_rpc::DenyUnsafe::Yes + } + } + Ok(Box::new(( + config.rpc_ipc.as_ref().map(|path| sc_rpc_server::start_ipc(&*path, gen_handler(sc_rpc::DenyUnsafe::No))), maybe_start_server( config.rpc_http, - |address| sc_rpc_server::start_http(address, config.rpc_cors.as_ref(), gen_handler()), + |address| sc_rpc_server::start_http( + address, + config.rpc_cors.as_ref(), + gen_handler(deny_unsafe(&address, &config.rpc_methods)), + ), )?.map(|s| waiting::HttpServer(Some(s))), maybe_start_server( config.rpc_ws, @@ -525,15 +417,15 @@ fn start_rpc_servers sc_rpc_server::RpcHandler>( address, config.rpc_ws_max_connections, config.rpc_cors.as_ref(), - gen_handler(), + gen_handler(deny_unsafe(&address, &config.rpc_methods)), ), - )?.map(|s| waiting::WsServer(Some(s))).map(Mutex::new), + )?.map(|s| waiting::WsServer(Some(s))), ))) } /// 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 sc_rpc_server::RpcHandler>( +fn start_rpc_servers sc_rpc_server::RpcHandler>( _: &Configuration, _: H ) -> Result, error::Error> { @@ -566,7 +458,6 @@ pub struct TransactionPoolAdapter { imports_external_transactions: bool, pool: Arc

, client: Arc, - executor: SpawnTaskHandle, } /// Get transactions for propagation. @@ -609,42 +500,42 @@ where fn import( &self, - report_handle: ReportHandle, - who: PeerId, - reputation_change_good: sc_network::ReputationChange, - reputation_change_bad: sc_network::ReputationChange, - transaction: B::Extrinsic - ) { + transaction: B::Extrinsic, + ) -> TransactionImportFuture { if !self.imports_external_transactions { debug!("Transaction rejected"); - return; + Box::pin(futures::future::ready(TransactionImport::None)); } let encoded = transaction.encode(); - match Decode::decode(&mut &encoded[..]) { - Ok(uxt) => { - let best_block_id = BlockId::hash(self.client.info().best_hash); - let source = sp_transaction_pool::TransactionSource::External; - let import_future = self.pool.submit_one(&best_block_id, source, uxt); - let import_future = import_future - .map(move |import_result| { - match import_result { - Ok(_) => report_handle.report_peer(who, reputation_change_good), - Err(e) => match e.into_pool_error() { - Ok(sp_transaction_pool::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), - } - } - }); - - self.executor.spawn("extrinsic-import", import_future); + let uxt = match Decode::decode(&mut &encoded[..]) { + Ok(uxt) => uxt, + Err(e) => { + debug!("Transaction invalid: {:?}", e); + return Box::pin(futures::future::ready(TransactionImport::Bad)); } - Err(e) => debug!("Error decoding transaction {}", e), - } + }; + + let best_block_id = BlockId::hash(self.client.info().best_hash); + + let import_future = self.pool.submit_one(&best_block_id, sp_transaction_pool::TransactionSource::External, uxt); + Box::pin(async move { + match import_future.await { + Ok(_) => TransactionImport::NewGood, + Err(e) => match e.into_pool_error() { + Ok(sp_transaction_pool::error::Error::AlreadyImported(_)) => TransactionImport::KnownGood, + Ok(e) => { + debug!("Error adding transaction to the pool: {:?}", e); + TransactionImport::Bad + } + Err(e) => { + debug!("Error converting pool error: {:?}", e); + // it is not bad at least, just some internal node logic error, so peer is innocent. + TransactionImport::KnownGood + } + } + } + }) } fn on_broadcasted(&self, propagations: HashMap>) { @@ -674,10 +565,14 @@ mod tests { // given let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain(); let client = Arc::new(client); - let pool = Arc::new(BasicPool::new( + let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let pool = BasicPool::new_full( Default::default(), - Arc::new(FullChainApi::new(client.clone())), - ).0); + Arc::new(FullChainApi::new(client.clone(), None)), + None, + spawner, + client.clone(), + ); let source = sp_runtime::transaction_validity::TransactionSource::External; let best = longest_chain.best_chain().unwrap(); let transaction = Transfer { diff --git a/client/service/src/metrics.rs b/client/service/src/metrics.rs index 740a795edae5bd200466cc174239ea0628dee69c..c9726e8e367c50027ee0cc619bc6f251392a65e4 100644 --- a/client/service/src/metrics.rs +++ b/client/service/src/metrics.rs @@ -1,40 +1,42 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . + +use std::{convert::TryFrom, time::SystemTime}; -use crate::NetworkStatus; +use crate::{NetworkStatus, config::Configuration}; use prometheus_endpoint::{register, Gauge, U64, F64, Registry, PrometheusError, Opts, GaugeVec}; -use sc_client::ClientInfo; use sc_telemetry::{telemetry, SUBSTRATE_INFO}; -use std::convert::TryFrom; use sp_runtime::traits::{NumberFor, Block, SaturatedConversion, UniqueSaturatedInto}; use sp_transaction_pool::PoolStatus; use sp_utils::metrics::register_globals; +use sc_client_api::ClientInfo; +use sc_network::config::Role; -#[cfg(any(windows, unix))] use sysinfo::{self, ProcessExt, SystemExt}; -#[cfg(any(unix, windows))] -use netstat2::{TcpState, ProtocolSocketInfo, iterate_sockets_info, AddressFamilyFlags, ProtocolFlags}; - -#[cfg(target_os = "linux")] -use procfs; +#[cfg(all(any(unix, windows), not(target_os = "android"), not(target_os = "ios")))] +use netstat2::{ + TcpState, ProtocolSocketInfo, iterate_sockets_info, AddressFamilyFlags, ProtocolFlags, +}; struct PrometheusMetrics { // system - #[cfg(any(unix, windows))] + #[cfg(all(any(unix, windows), not(target_os = "android"), not(target_os = "ios")))] load_avg: GaugeVec, // process @@ -42,8 +44,8 @@ struct PrometheusMetrics { memory_usage_bytes: Gauge, threads: Gauge, open_files: GaugeVec, - - #[cfg(any(unix, windows))] + + #[cfg(all(any(unix, windows), not(target_os = "android"), not(target_os = "ios")))] netstat: GaugeVec, // -- inner counters @@ -71,16 +73,23 @@ impl PrometheusMetrics { .const_label("name", name) .const_label("version", version) )?, ®istry)?.set(1); - + register(Gauge::::new( "node_roles", "The roles the node is running as", )?, ®istry)?.set(roles); register_globals(registry)?; - + + let start_time_since_epoch = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) + .unwrap_or_default(); + register(Gauge::::new( + "process_start_time_seconds", + "Number of seconds between the UNIX epoch and the moment the process started", + )?, registry)?.set(start_time_since_epoch.as_secs()); + Ok(Self { // system - #[cfg(any(unix, windows))] + #[cfg(all(any(unix, windows), not(target_os = "android"), not(target_os = "ios")))] load_avg: register(GaugeVec::new( Opts::new("load_avg", "System load average"), &["over"] @@ -95,7 +104,7 @@ impl PrometheusMetrics { "cpu_usage_percentage", "Node CPU usage", )?, registry)?, - #[cfg(any(unix, windows))] + #[cfg(all(any(unix, windows), not(target_os = "android"), not(target_os = "ios")))] netstat: register(GaugeVec::new( Opts::new("netstat_tcp", "Current TCP connections "), &["status"] @@ -113,7 +122,6 @@ impl PrometheusMetrics { // --- internal // generic internals - block_height: register(GaugeVec::new( Opts::new("block_height", "Block height info of the chain"), &["status"] @@ -128,7 +136,6 @@ impl PrometheusMetrics { )?, registry)?, // I/ O - network_per_sec_bytes: register(GaugeVec::new( Opts::new("network_per_sec_bytes", "Networking bytes per second"), &["direction"] @@ -147,7 +154,7 @@ impl PrometheusMetrics { } } -#[cfg(any(unix, windows))] +#[cfg(all(any(unix, windows), not(target_os = "android"), not(target_os = "ios")))] #[derive(Default)] struct ConnectionsCount { listen: u64, @@ -179,9 +186,9 @@ struct ProcessInfo { pub struct MetricsService { metrics: Option, - #[cfg(any(windows, unix))] + #[cfg(all(any(unix, windows), not(target_os = "android"), not(target_os = "ios")))] system: sysinfo::System, - pid: Option, + pid: Option, } #[cfg(target_os = "linux")] @@ -196,12 +203,14 @@ impl MetricsService { pid: Some(process.pid), } } + fn process_info(&mut self) -> ProcessInfo { let pid = self.pid.clone().expect("unix always has a pid. qed"); - let mut info = self._process_info_for(&pid); + let mut info = self.process_info_for(&pid); let process = procfs::process::Process::new(pid).expect("Our process exists. qed."); info.threads = process.stat().ok().map(|s| - u64::try_from(s.num_threads).expect("There are no negative thread counts. qed")); + u64::try_from(s.num_threads).expect("There are no negative thread counts. qed"), + ); info.open_fd = process.fd().ok().map(|i| i.into_iter().fold(FdCounter::default(), |mut f, info| { match info.target { @@ -218,33 +227,33 @@ impl MetricsService { ); info } - } -#[cfg(all(any(unix, windows), not(target_os = "linux")))] +#[cfg(all(any(unix, windows), not(target_os = "android"), not(target_os = "ios"), not(target_os = "linux")))] impl MetricsService { fn inner_new(metrics: Option) -> Self { Self { metrics, system: sysinfo::System::new(), - pid: sysinfo::get_current_pid().ok() + pid: sysinfo::get_current_pid().ok(), } } - + fn process_info(&mut self) -> ProcessInfo { - self.pid.map(|pid| self._process_info_for(&pid)).unwrap_or_else(ProcessInfo::default) + self.pid.map(|pid| self.process_info_for(&pid)).unwrap_or_default() } } -#[cfg(not(any(unix, windows)))] + +#[cfg(not(all(any(unix, windows), not(target_os = "android"), not(target_os = "ios"))))] impl MetricsService { fn inner_new(metrics: Option) -> Self { Self { metrics, - pid: None + pid: None, } } - + fn process_info(&mut self) -> ProcessInfo { ProcessInfo::default() } @@ -252,11 +261,17 @@ impl MetricsService { impl MetricsService { - - pub fn with_prometheus(registry: &Registry, name: &str, version: &str, roles: u64) + pub fn with_prometheus(registry: &Registry, config: &Configuration) -> Result { - PrometheusMetrics::setup(registry, name, version, roles).map(|p| { + let role_bits = match config.role { + Role::Full => 1u64, + Role::Light => 2u64, + Role::Sentry { .. } => 3u64, + Role::Authority { .. } => 4u64, + }; + + PrometheusMetrics::setup(registry, &config.network.node_name, &config.impl_version, role_bits).map(|p| { Self::inner_new(Some(p)) }) } @@ -265,8 +280,8 @@ impl MetricsService { Self::inner_new(None) } - #[cfg(any(windows, unix))] - fn _process_info_for(&mut self, pid: &i32) -> ProcessInfo { + #[cfg(all(any(unix, windows), not(target_os = "android"), not(target_os = "ios")))] + fn process_info_for(&mut self, pid: &sysinfo::Pid) -> ProcessInfo { let mut info = ProcessInfo::default(); if self.system.refresh_process(*pid) { let prc = self.system.get_process(*pid) @@ -277,7 +292,7 @@ impl MetricsService { info } - #[cfg(any(unix, windows))] + #[cfg(all(any(unix, windows), not(target_os = "android"), not(target_os = "ios")))] fn connections_info(&self) -> Option { self.pid.as_ref().and_then(|pid| { let af_flags = AddressFamilyFlags::IPV4 | AddressFamilyFlags::IPV6; @@ -285,15 +300,12 @@ impl MetricsService { let netstat_pid = *pid as u32; iterate_sockets_info(af_flags, proto_flags).ok().map(|iter| - iter.filter_map(|r| + iter.filter_map(|r| r.ok().and_then(|s| { - if s.associated_pids.contains(&netstat_pid) { - match s.protocol_socket_info { - ProtocolSocketInfo::Tcp(info) => Some(info.state), - _ => None - } - } else { - None + match s.protocol_socket_info { + ProtocolSocketInfo::Tcp(info) + if s.associated_pids.contains(&netstat_pid) => Some(info.state), + _ => None } }) ).fold(ConnectionsCount::default(), |mut counter, socket_state| { @@ -317,7 +329,7 @@ impl MetricsService { &mut self, info: &ClientInfo, txpool_status: &PoolStatus, - net_status: &NetworkStatus + net_status: &NetworkStatus, ) { let best_number = info.chain.best_number.saturated_into::(); @@ -377,8 +389,12 @@ impl MetricsService { } - metrics.network_per_sec_bytes.with_label_values(&["download"]).set(net_status.average_download_per_sec); - metrics.network_per_sec_bytes.with_label_values(&["upload"]).set(net_status.average_upload_per_sec); + metrics.network_per_sec_bytes.with_label_values(&["download"]).set( + net_status.average_download_per_sec, + ); + metrics.network_per_sec_bytes.with_label_values(&["upload"]).set( + net_status.average_upload_per_sec, + ); metrics.block_height.with_label_values(&["finalized"]).set(finalized_number); metrics.block_height.with_label_values(&["best"]).set(best_number); @@ -396,14 +412,18 @@ impl MetricsService { metrics.database_cache.set(info.memory.database_cache.as_bytes() as u64); metrics.state_cache.set(info.memory.state_cache.as_bytes() as u64); - metrics.state_db.with_label_values(&["non_canonical"]).set(info.memory.state_db.non_canonical.as_bytes() as u64); + metrics.state_db.with_label_values(&["non_canonical"]).set( + info.memory.state_db.non_canonical.as_bytes() as u64, + ); if let Some(pruning) = info.memory.state_db.pruning { metrics.state_db.with_label_values(&["pruning"]).set(pruning.as_bytes() as u64); } - metrics.state_db.with_label_values(&["pinned"]).set(info.memory.state_db.pinned.as_bytes() as u64); + metrics.state_db.with_label_values(&["pinned"]).set( + info.memory.state_db.pinned.as_bytes() as u64, + ); } - #[cfg(any(unix, windows))] + #[cfg(all(any(unix, windows), not(target_os = "android"), not(target_os = "ios")))] { let load = self.system.get_load_average(); metrics.load_avg.with_label_values(&["1min"]).set(load.one); diff --git a/client/service/src/status_sinks.rs b/client/service/src/status_sinks.rs deleted file mode 100644 index 4b1dce52f9a319ee02c2033f0214fffd6fe56a86..0000000000000000000000000000000000000000 --- a/client/service/src/status_sinks.rs +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright 2019-2020 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::{Stream, stream::futures_unordered::FuturesUnordered}; -use std::time::Duration; -use std::pin::Pin; -use std::task::{Poll, Context}; -use futures_timer::Delay; -use sp_utils::mpsc::TracingUnboundedSender; - -/// 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: 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: TracingUnboundedSender) { - self.entries.push(YieldAfter { - delay: Delay::new(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 `Poll::Pending`. 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, cx: &mut Context, mut status_grab: impl FnMut() -> T) { - loop { - match Pin::new(&mut self.entries).poll_next(cx) { - Poll::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(interval), - interval, - sender: Some(sender), - }); - } - } - Poll::Ready(None) | - Poll::Pending => break, - } - } - } -} - -impl futures::Future for YieldAfter { - type Output = (TracingUnboundedSender, Duration); - - fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { - let this = Pin::into_inner(self); - - match Pin::new(&mut this.delay).poll(cx) { - Poll::Pending => Poll::Pending, - Poll::Ready(()) => { - let sender = this.sender.take() - .expect("sender is always Some unless the future is finished; qed"); - Poll::Ready((sender, this.interval)) - } - } - } -} - -#[cfg(test)] -mod tests { - use super::StatusSinks; - use futures::prelude::*; - use futures::channel::mpsc; - use std::time::Duration; - use std::task::Poll; - - #[test] - fn works() { - // We're not testing that the `StatusSink` properly enforces an order in the intervals, as - // this easily causes test failures on busy CPUs. - - let mut status_sinks = StatusSinks::new(); - - let (tx, rx) = mpsc::unbounded(); - status_sinks.push(Duration::from_millis(100), tx); - - let mut val_order = 5; - - futures::executor::block_on(futures::future::select( - futures::future::poll_fn(move |cx| { - status_sinks.poll(cx, || { val_order += 1; val_order }); - Poll::<()>::Pending - }), - Box::pin(async { - let items: Vec = rx.take(3).collect().await; - assert_eq!(items, [6, 7, 8]); - }) - )); - } -} diff --git a/client/service/src/task_manager.rs b/client/service/src/task_manager.rs index 7c5862e8535c4bcacdb846f9f228c630ccfc0c3d..b6cc26005570a0a33bdf7e8af4c5e327459ceda8 100644 --- a/client/service/src/task_manager.rs +++ b/client/service/src/task_manager.rs @@ -13,110 +13,123 @@ //! Substrate service tasks management module. -use std::{ - result::Result, sync::Arc, - task::{Poll, Context}, - borrow::Cow, pin::Pin, -}; +use std::{panic, result::Result, pin::Pin}; use exit_future::Signal; -use log::{debug, error}; +use log::debug; use futures::{ - Future, FutureExt, Stream, - future::select, + Future, FutureExt, StreamExt, + future::{select, Either, BoxFuture}, compat::*, task::{Spawn, FutureObj, SpawnError}, + sink::SinkExt, +}; +use prometheus_endpoint::{ + exponential_buckets, register, + PrometheusError, + CounterVec, HistogramOpts, HistogramVec, Opts, Registry, U64 }; use sc_client_api::CloneableSpawn; -use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedSender, TracingUnboundedReceiver}; - -/// Type alias for service task executor (usually runtime). -pub type ServiceTaskExecutor = Arc + Send>>) + Send + Sync>; - -/// Type alias for the task scheduler. -pub type TaskScheduler = TracingUnboundedSender<(Pin + Send>>, Cow<'static, str>)>; - -/// Helper struct to setup background tasks execution for service. -pub struct TaskManagerBuilder { - /// A future that resolves when the service has exited, this is useful to - /// make sure any internally spawned futures stop when the service does. - on_exit: exit_future::Exit, - /// A signal that makes the exit future above resolve, fired on service drop. - signal: Option, - /// Sender for futures that must be spawned as background tasks. - to_spawn_tx: TaskScheduler, - /// Receiver for futures that must be spawned as background tasks. - to_spawn_rx: TracingUnboundedReceiver<(Pin + Send>>, Cow<'static, str>)>, -} - -impl TaskManagerBuilder { - /// New asynchronous task manager setup. - pub fn new() -> Self { - let (signal, on_exit) = exit_future::signal(); - let (to_spawn_tx, to_spawn_rx) = tracing_unbounded("mpsc_task_manager"); - Self { - on_exit, - signal: Some(signal), - to_spawn_tx, - to_spawn_rx, - } - } - - /// Get spawn handle. - /// - /// Tasks spawned through this handle will get scheduled once - /// service is up and running. - pub fn spawn_handle(&self) -> SpawnTaskHandle { - SpawnTaskHandle { - on_exit: self.on_exit.clone(), - sender: self.to_spawn_tx.clone(), - } - } +use sp_utils::mpsc::{TracingUnboundedSender, TracingUnboundedReceiver, tracing_unbounded}; +use crate::{config::{TaskExecutor, TaskType}, Error}; - /// Convert into actual task manager from initial setup. - pub(crate) fn into_task_manager(self, executor: ServiceTaskExecutor) -> TaskManager { - let TaskManagerBuilder { - on_exit, - signal, - to_spawn_rx, - to_spawn_tx - } = self; - TaskManager { - on_exit, - signal, - to_spawn_tx, - to_spawn_rx, - executor, - } - } -} +mod prometheus_future; /// An handle for spawning tasks in the service. #[derive(Clone)] pub struct SpawnTaskHandle { - sender: TaskScheduler, on_exit: exit_future::Exit, + executor: TaskExecutor, + metrics: Option, } impl SpawnTaskHandle { /// Spawns the given task with the given name. - pub fn spawn(&self, name: impl Into>, task: impl Future + Send + 'static) { + /// + /// Note that the `name` is a `&'static str`. The reason for this choice is that statistics + /// about this task are getting reported to the Prometheus endpoint (if enabled), and that + /// therefore the set of possible task names must be bounded. + /// + /// In other words, it would be a bad idea for someone to do for example + /// `spawn(format!("{:?}", some_public_key))`. + pub fn spawn(&self, name: &'static str, task: impl Future + Send + 'static) { + self.spawn_inner(name, task, TaskType::Async) + } + + /// Spawns the blocking task with the given name. See also `spawn`. + pub fn spawn_blocking(&self, name: &'static str, task: impl Future + Send + 'static) { + self.spawn_inner(name, task, TaskType::Blocking) + } + + /// Helper function that implements the spawning logic. See `spawn` and `spawn_blocking`. + fn spawn_inner( + &self, + name: &'static str, + task: impl Future + Send + 'static, + task_type: TaskType, + ) { let on_exit = self.on_exit.clone(); + let metrics = self.metrics.clone(); + + // Note that we increase the started counter here and not within the future. This way, + // we could properly visualize on Prometheus situations where the spawning doesn't work. + if let Some(metrics) = &self.metrics { + metrics.tasks_spawned.with_label_values(&[name]).inc(); + // We do a dummy increase in order for the task to show up in metrics. + metrics.tasks_ended.with_label_values(&[name, "finished"]).inc_by(0); + } + let future = async move { - futures::pin_mut!(task); - let _ = select(on_exit, task).await; + if let Some(metrics) = metrics { + // Add some wrappers around `task`. + let task = { + let poll_duration = metrics.poll_duration.with_label_values(&[name]); + let poll_start = metrics.poll_start.with_label_values(&[name]); + let inner = prometheus_future::with_poll_durations(poll_duration, poll_start, task); + // The logic of `AssertUnwindSafe` here is ok considering that we throw + // away the `Future` after it has panicked. + panic::AssertUnwindSafe(inner).catch_unwind() + }; + futures::pin_mut!(task); + + match select(on_exit, task).await { + Either::Right((Err(payload), _)) => { + metrics.tasks_ended.with_label_values(&[name, "panic"]).inc(); + panic::resume_unwind(payload) + } + Either::Right((Ok(()), _)) => { + metrics.tasks_ended.with_label_values(&[name, "finished"]).inc(); + } + Either::Left(((), _)) => { + // The `on_exit` has triggered. + metrics.tasks_ended.with_label_values(&[name, "interrupted"]).inc(); + } + } + + } else { + futures::pin_mut!(task); + let _ = select(on_exit, task).await; + } }; - if self.sender.unbounded_send((Box::pin(future), name.into())).is_err() { - error!("Failed to send task to spawn over channel"); - } + + self.executor.spawn(Box::pin(future), task_type); } } impl Spawn for SpawnTaskHandle { fn spawn_obj(&self, future: FutureObj<'static, ()>) -> Result<(), SpawnError> { - let future = select(self.on_exit.clone(), future).map(drop); - self.sender.unbounded_send((Box::pin(future), From::from("unnamed"))) - .map_err(|_| SpawnError::shutdown()) + self.spawn("unnamed", future); + Ok(()) + } +} + +impl sp_core::traits::SpawnNamed for SpawnTaskHandle { + fn spawn_blocking(&self, name: &'static str, future: BoxFuture<'static, ()>) { + self.spawn_blocking(name, future); + } + + fn spawn(&self, name: &'static str, future: BoxFuture<'static, ()>) { + self.spawn(name, future); } } @@ -135,6 +148,63 @@ impl futures01::future::Executor for SpawnTaskHandle { } } +/// A wrapper over `SpawnTaskHandle` that will notify a receiver whenever any +/// task spawned through it fails. The service should be on the receiver side +/// and will shut itself down whenever it receives any message, i.e. an +/// essential task has failed. +pub struct SpawnEssentialTaskHandle { + essential_failed_tx: TracingUnboundedSender<()>, + inner: SpawnTaskHandle, +} + +impl SpawnEssentialTaskHandle { + /// Creates a new `SpawnEssentialTaskHandle`. + pub fn new( + essential_failed_tx: TracingUnboundedSender<()>, + spawn_task_handle: SpawnTaskHandle, + ) -> SpawnEssentialTaskHandle { + SpawnEssentialTaskHandle { + essential_failed_tx, + inner: spawn_task_handle, + } + } + + /// Spawns the given task with the given name. + /// + /// See also [`SpawnTaskHandle::spawn`]. + pub fn spawn(&self, name: &'static str, task: impl Future + Send + 'static) { + self.spawn_inner(name, task, TaskType::Async) + } + + /// Spawns the blocking task with the given name. + /// + /// See also [`SpawnTaskHandle::spawn_blocking`]. + pub fn spawn_blocking( + &self, + name: &'static str, + task: impl Future + Send + 'static, + ) { + self.spawn_inner(name, task, TaskType::Blocking) + } + + fn spawn_inner( + &self, + name: &'static str, + task: impl Future + Send + 'static, + task_type: TaskType, + ) { + let mut essential_failed = self.essential_failed_tx.clone(); + let essential_task = std::panic::AssertUnwindSafe(task) + .catch_unwind() + .map(move |_| { + log::error!("Essential task `{}` failed. Shutting down service.", name); + let _ = essential_failed.send(()); + }); + + let _ = self.inner.spawn_inner(name, essential_task, task_type); + } +} + /// Helper struct to manage background/async tasks in Service. pub struct TaskManager { /// A future that resolves when the service has exited, this is useful to @@ -142,57 +212,131 @@ pub struct TaskManager { on_exit: exit_future::Exit, /// A signal that makes the exit future above resolve, fired on service drop. signal: Option, - /// Sender for futures that must be spawned as background tasks. - to_spawn_tx: TaskScheduler, - /// Receiver for futures that must be spawned as background tasks. - to_spawn_rx: TracingUnboundedReceiver<(Pin + Send>>, Cow<'static, str>)>, /// How to spawn background tasks. - executor: ServiceTaskExecutor, + executor: TaskExecutor, + /// Prometheus metric where to report the polling times. + metrics: Option, + /// Send a signal when a spawned essential task has concluded. The next time + /// the service future is polled it should complete with an error. + essential_failed_tx: TracingUnboundedSender<()>, + /// A receiver for spawned essential-tasks concluding. + essential_failed_rx: TracingUnboundedReceiver<()>, + /// Things to keep alive until the task manager is dropped. + keep_alive: Box, } impl TaskManager { - /// Spawn background/async task, which will be aware on exit signal. - pub(super) fn spawn(&self, name: impl Into>, task: impl Future + Send + 'static) { - let on_exit = self.on_exit.clone(); - let future = async move { - futures::pin_mut!(task); - let _ = select(on_exit, task).await; - }; - if self.to_spawn_tx.unbounded_send((Box::pin(future), name.into())).is_err() { - error!("Failed to send task to spawn over channel"); - } + /// If a Prometheus registry is passed, it will be used to report statistics about the + /// service tasks. + pub(super) fn new( + executor: TaskExecutor, + prometheus_registry: Option<&Registry> + ) -> Result { + let (signal, on_exit) = exit_future::signal(); + // A side-channel for essential tasks to communicate shutdown. + let (essential_failed_tx, essential_failed_rx) = tracing_unbounded("mpsc_essential_tasks"); + + let metrics = prometheus_registry.map(Metrics::register).transpose()?; + + Ok(Self { + on_exit, + signal: Some(signal), + executor, + metrics, + essential_failed_tx, + essential_failed_rx, + keep_alive: Box::new(()), + }) } - pub(super) fn spawn_handle(&self) -> SpawnTaskHandle { + + /// Get a handle for spawning tasks. + pub fn spawn_handle(&self) -> SpawnTaskHandle { SpawnTaskHandle { on_exit: self.on_exit.clone(), - sender: self.to_spawn_tx.clone(), + executor: self.executor.clone(), + metrics: self.metrics.clone(), } } - /// Get sender where background/async tasks can be sent. - pub(super) fn scheduler(&self) -> TaskScheduler { - self.to_spawn_tx.clone() + /// Get a handle for spawning essential tasks. + pub fn spawn_essential_handle(&self) -> SpawnEssentialTaskHandle { + SpawnEssentialTaskHandle::new(self.essential_failed_tx.clone(), self.spawn_handle()) + } + + /// Return a future that will end if an essential task fails. + pub fn future<'a>(&'a mut self) -> Pin> + Send + 'a>> { + Box::pin(async move { + self.essential_failed_rx.next().await; + + Err(Error::Other("Essential task failed.".into())) + }) } - /// Process background task receiver. - pub(super) fn process_receiver(&mut self, cx: &mut Context) { - while let Poll::Ready(Some((task_to_spawn, name))) = Pin::new(&mut self.to_spawn_rx).poll_next(cx) { - (self.executor)(Box::pin(futures_diagnose::diagnose(name, task_to_spawn))); + /// Signal to terminate all the running tasks. + pub fn terminate(&mut self) { + if let Some(signal) = self.signal.take() { + let _ = signal.fire(); } } - /// Clone on exit signal. - pub(super) fn on_exit(&self) -> exit_future::Exit { - self.on_exit.clone() + /// Set what the task manager should keep alivei + pub(super) fn keep_alive(&mut self, to_keep_alive: T) { + self.keep_alive = Box::new(to_keep_alive); } } impl Drop for TaskManager { fn drop(&mut self) { debug!(target: "service", "Tasks manager shutdown"); - if let Some(signal) = self.signal.take() { - let _ = signal.fire(); - } + self.terminate(); + } +} + +#[derive(Clone)] +struct Metrics { + // This list is ordered alphabetically + poll_duration: HistogramVec, + poll_start: CounterVec, + tasks_spawned: CounterVec, + tasks_ended: CounterVec, +} + +impl Metrics { + fn register(registry: &Registry) -> Result { + Ok(Self { + poll_duration: register(HistogramVec::new( + HistogramOpts { + common_opts: Opts::new( + "tasks_polling_duration", + "Duration in seconds of each invocation of Future::poll" + ), + buckets: exponential_buckets(0.001, 4.0, 9) + .expect("function parameters are constant and always valid; qed"), + }, + &["task_name"] + )?, registry)?, + poll_start: register(CounterVec::new( + Opts::new( + "tasks_polling_started_total", + "Total number of times we started invoking Future::poll" + ), + &["task_name"] + )?, registry)?, + tasks_spawned: register(CounterVec::new( + Opts::new( + "tasks_spawned_total", + "Total number of tasks that have been spawned on the Service" + ), + &["task_name"] + )?, registry)?, + tasks_ended: register(CounterVec::new( + Opts::new( + "tasks_ended_total", + "Total number of tasks for which Future::poll has returned Ready(()) or panicked" + ), + &["task_name", "reason"] + )?, registry)?, + }) } } diff --git a/client/service/src/task_manager/prometheus_future.rs b/client/service/src/task_manager/prometheus_future.rs new file mode 100644 index 0000000000000000000000000000000000000000..53bd59aa7a507ed52e240c4f44f718efa1567c6c --- /dev/null +++ b/client/service/src/task_manager/prometheus_future.rs @@ -0,0 +1,69 @@ +// Copyright 2020 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. + +//! Wrapper around a `Future` that reports statistics about when the `Future` is polled. + +use futures::prelude::*; +use prometheus_endpoint::{Counter, Histogram, U64}; +use std::{fmt, pin::Pin, task::{Context, Poll}}; + +/// Wraps around a `Future`. Report the polling duration to the `Histogram` and when the polling +/// starts to the `Counter`. +pub fn with_poll_durations( + poll_duration: Histogram, + poll_start: Counter, + inner: T +) -> PrometheusFuture { + PrometheusFuture { + inner, + poll_duration, + poll_start, + } +} + +/// Wraps around `Future` and adds diagnostics to it. +#[pin_project::pin_project] +#[derive(Clone)] +pub struct PrometheusFuture { + /// The inner future doing the actual work. + #[pin] + inner: T, + poll_duration: Histogram, + poll_start: Counter, +} + +impl Future for PrometheusFuture +where + T: Future, +{ + type Output = T::Output; + + fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { + let this = self.project(); + + this.poll_start.inc(); + let _timer = this.poll_duration.start_timer(); + Future::poll(this.inner, cx) + + // `_timer` is dropped here and will observe the duration + } +} + +impl fmt::Debug for PrometheusFuture +where + T: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.inner, f) + } +} diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index 39c17420bf571fc7688b728999f3e302bf6a7f23..6a886ebcbaccb02139337ee121d609e181f199d3 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -1,28 +1,44 @@ [package] name = "sc-service-test" -version = "2.0.0-dev" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" publish = false homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] +hex-literal = "0.2.1" tempfile = "3.1.0" tokio = "0.1.22" futures01 = { package = "futures", version = "0.1.29" } log = "0.4.8" env_logger = "0.7.0" fdlimit = "0.1.4" +parking_lot = "0.10.0" +sc-light = { version = "2.0.0-rc4", path = "../../light" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../../primitives/blockchain" } +sp-api = { version = "2.0.0-rc4", path = "../../../primitives/api" } +sp-state-machine = { version = "0.8.0-rc4", path = "../../../primitives/state-machine" } +sp-externalities = { version = "0.8.0-rc4", path = "../../../primitives/externalities" } +sp-trie = { version = "2.0.0-rc4", path = "../../../primitives/trie" } +sp-storage = { version = "2.0.0-rc4", path = "../../../primitives/storage" } +sc-client-db = { version = "0.8.0-rc4", default-features = false, path = "../../db" } futures = { version = "0.3.1", features = ["compat"] } -sc-service = { version = "0.8.0-alpha.5", default-features = false, path = "../../service" } -sc-network = { version = "0.8.0-alpha.5", path = "../../network" } -sp-consensus = { version = "0.8.0-alpha.5", path = "../../../primitives/consensus/common" } -sc-client = { version = "0.8.0-alpha.5", path = "../../" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime" } -sp-core = { version = "2.0.0-alpha.5", path = "../../../primitives/core" } -sp-transaction-pool = { version = "2.0.0-alpha.5", path = "../../../primitives/transaction-pool" } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +sc-service = { version = "0.8.0-rc4", default-features = false, features = ["test-helpers"], path = "../../service" } +sc-network = { version = "0.8.0-rc4", path = "../../network" } +sp-consensus = { version = "0.8.0-rc4", path = "../../../primitives/consensus/common" } +sp-runtime = { version = "2.0.0-rc4", path = "../../../primitives/runtime" } +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } +sp-transaction-pool = { version = "2.0.0-rc4", path = "../../../primitives/transaction-pool" } +substrate-test-runtime = { version = "2.0.0-rc4", path = "../../../test-utils/runtime" } +substrate-test-runtime-client = { version = "2.0.0-rc4", path = "../../../test-utils/runtime/client" } +sc-client-api = { version = "2.0.0-rc4", path = "../../api" } +sc-block-builder = { version = "0.8.0-rc4", path = "../../block-builder" } +sc-executor = { version = "0.8.0-rc4", path = "../../executor" } +sp-panic-handler = { version = "2.0.0-rc4", path = "../../../primitives/panic-handler" } +parity-scale-codec = "1.3.1" diff --git a/client/service/test/src/client/db.rs b/client/service/test/src/client/db.rs new file mode 100644 index 0000000000000000000000000000000000000000..36d49732246e579d610a707d827c0b5d49c00ea6 --- /dev/null +++ b/client/service/test/src/client/db.rs @@ -0,0 +1,57 @@ +// This file is part of Substrate. + +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use sp_core::offchain::{OffchainStorage, storage::InMemOffchainStorage}; +use std::sync::Arc; + +type TestBackend = sc_client_api::in_mem::Backend; + +#[test] +fn test_leaves_with_complex_block_tree() { + let backend = Arc::new(TestBackend::new()); + + substrate_test_runtime_client::trait_tests::test_leaves_for_backend(backend); +} + +#[test] +fn test_blockchain_query_by_number_gets_canonical() { + let backend = Arc::new(TestBackend::new()); + + substrate_test_runtime_client::trait_tests::test_blockchain_query_by_number_gets_canonical(backend); +} + +#[test] +fn in_memory_offchain_storage() { + + let mut storage = InMemOffchainStorage::default(); + assert_eq!(storage.get(b"A", b"B"), None); + assert_eq!(storage.get(b"B", b"A"), None); + + storage.set(b"A", b"B", b"C"); + assert_eq!(storage.get(b"A", b"B"), Some(b"C".to_vec())); + assert_eq!(storage.get(b"B", b"A"), None); + + storage.compare_and_set(b"A", b"B", Some(b"X"), b"D"); + assert_eq!(storage.get(b"A", b"B"), Some(b"C".to_vec())); + storage.compare_and_set(b"A", b"B", Some(b"C"), b"D"); + assert_eq!(storage.get(b"A", b"B"), Some(b"D".to_vec())); + + assert!(!storage.compare_and_set(b"B", b"A", Some(b""), b"Y")); + assert!(storage.compare_and_set(b"B", b"A", None, b"X")); + assert_eq!(storage.get(b"B", b"A"), Some(b"X".to_vec())); +} diff --git a/client/service/test/src/client/light.rs b/client/service/test/src/client/light.rs new file mode 100644 index 0000000000000000000000000000000000000000..e72c290d43bbeaf363a241692663b440e8570d43 --- /dev/null +++ b/client/service/test/src/client/light.rs @@ -0,0 +1,905 @@ +// This file is part of Substrate. + +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use sc_light::{ + call_executor::{ + GenesisCallExecutor, + check_execution_proof, + check_execution_proof_with_make_header, + }, + fetcher::LightDataChecker, + blockchain::{BlockchainCache, Blockchain}, + backend::{Backend, GenesisOrUnavailableState}, +}; +use std::sync::Arc; +use sp_runtime::{ + traits::{BlakeTwo256, HashFor, NumberFor}, + generic::BlockId, traits::{Block as _, Header as HeaderT}, Digest, +}; +use std::collections::HashMap; +use parking_lot::Mutex; +use substrate_test_runtime_client::{ + runtime::{Hash, Block, Header}, TestClient, ClientBlockImportExt, +}; +use sp_api::{InitializeBlock, StorageTransactionCache, ProofRecorder, OffchainOverlayedChanges}; +use sp_consensus::{BlockOrigin}; +use sc_executor::{NativeExecutor, WasmExecutionMethod, RuntimeVersion, NativeVersion}; +use sp_core::{H256, tasks::executor as tasks_executor, NativeOrEncoded}; +use sc_client_api::{ + blockchain::Info, backend::NewBlockState, Backend as ClientBackend, ProofProvider, + in_mem::{Backend as InMemBackend, Blockchain as InMemoryBlockchain}, + AuxStore, Storage, CallExecutor, cht, ExecutionStrategy, StorageProof, BlockImportOperation, + RemoteCallRequest, StorageProvider, ChangesProof, RemoteBodyRequest, RemoteReadRequest, + RemoteChangesRequest, FetchChecker, RemoteReadChildRequest, RemoteHeaderRequest, BlockBackend, +}; +use sp_externalities::Extensions; +use sc_block_builder::BlockBuilderProvider; +use sp_blockchain::{ + BlockStatus, Result as ClientResult, Error as ClientError, CachedHeaderMetadata, + HeaderBackend, well_known_cache_keys +}; +use std::panic::UnwindSafe; +use std::cell::RefCell; +use sp_state_machine::{OverlayedChanges, ExecutionManager}; +use parity_scale_codec::{Decode, Encode}; +use super::prepare_client_with_key_changes; +use substrate_test_runtime_client::{ + AccountKeyring, runtime::{self, Extrinsic}, +}; + +use sp_core::{blake2_256, ChangesTrieConfiguration, storage::{well_known_keys, StorageKey, ChildInfo}}; +use sp_state_machine::Backend as _; + +pub type DummyBlockchain = Blockchain; + +pub struct DummyStorage { + pub changes_tries_cht_roots: HashMap, + pub aux_store: Mutex, Vec>>, +} + +impl DummyStorage { + pub fn new() -> Self { + DummyStorage { + changes_tries_cht_roots: HashMap::new(), + aux_store: Mutex::new(HashMap::new()), + } + } +} + +impl sp_blockchain::HeaderBackend for DummyStorage { + fn header(&self, _id: BlockId) -> ClientResult> { + Err(ClientError::Backend("Test error".into())) + } + + fn info(&self) -> Info { + panic!("Test error") + } + + fn status(&self, _id: BlockId) -> ClientResult { + Err(ClientError::Backend("Test error".into())) + } + + fn number(&self, hash: Hash) -> ClientResult>> { + if hash == Default::default() { + Ok(Some(Default::default())) + } else { + Err(ClientError::Backend("Test error".into())) + } + } + + fn hash(&self, number: u64) -> ClientResult> { + if number == 0 { + Ok(Some(Default::default())) + } else { + Err(ClientError::Backend("Test error".into())) + } + } +} + +impl sp_blockchain::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, + 'b: 'a, + 'c: 'a, + I: IntoIterator, + D: IntoIterator, + >(&self, insert: I, _delete: D) -> ClientResult<()> { + for (k, v) in insert.into_iter() { + self.aux_store.lock().insert(k.to_vec(), v.to_vec()); + } + Ok(()) + } + + fn get_aux(&self, key: &[u8]) -> ClientResult>> { + Ok(self.aux_store.lock().get(key).cloned()) + } +} + +impl Storage for DummyStorage { + fn import_header( + &self, + _header: Header, + _cache: HashMap>, + _state: NewBlockState, + _aux_ops: Vec<(Vec, Option>)>, + ) -> ClientResult<()> { + Ok(()) + } + + fn set_head(&self, _block: BlockId) -> ClientResult<()> { + Err(ClientError::Backend("Test error".into())) + } + + fn finalize_header(&self, _block: BlockId) -> ClientResult<()> { + Err(ClientError::Backend("Test error".into())) + } + + fn last_finalized(&self) -> ClientResult { + Err(ClientError::Backend("Test error".into())) + } + + fn header_cht_root(&self, _cht_size: u64, _block: u64) -> ClientResult> { + Err(ClientError::Backend("Test error".into())) + } + + fn changes_trie_cht_root(&self, cht_size: u64, block: u64) -> ClientResult> { + cht::block_to_cht_number(cht_size, block) + .and_then(|cht_num| self.changes_tries_cht_roots.get(&cht_num)) + .cloned() + .ok_or_else(|| ClientError::Backend( + format!("Test error: CHT for block #{} not found", block) + ).into()) + .map(Some) + } + + fn cache(&self) -> Option>> { + None + } + + fn usage_info(&self) -> Option { + None + } +} + +struct DummyCallExecutor; + +impl CallExecutor for DummyCallExecutor { + type Error = ClientError; + + type Backend = substrate_test_runtime_client::Backend; + + fn call( + &self, + _id: &BlockId, + _method: &str, + _call_data: &[u8], + _strategy: ExecutionStrategy, + _extensions: 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 + UnwindSafe, + >( + &self, + _initialize_block_fn: IB, + _at: &BlockId, + _method: &str, + _call_data: &[u8], + _changes: &RefCell, + _offchain_changes: &RefCell, + _storage_transaction_cache: Option<&RefCell< + StorageTransactionCache< + Block, + >::State, + > + >>, + _initialize_block: InitializeBlock<'a, Block>, + _execution_manager: ExecutionManager, + _native_call: Option, + _proof_recorder: &Option>, + _extensions: Option, + ) -> ClientResult> where ExecutionManager: Clone { + unreachable!() + } + + fn runtime_version(&self, _id: &BlockId) -> Result { + unreachable!() + } + + fn prove_at_trie_state>>( + &self, + _trie_state: &sp_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, 8) +} + +#[test] +fn local_state_is_created_when_genesis_state_is_available() { + let def = Default::default(); + let header0 = substrate_test_runtime_client::runtime::Header::new(0, def, def, def, Default::default()); + + let backend: Backend<_, BlakeTwo256> = 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()).unwrap(); + backend.commit_operation(op).unwrap(); + + match backend.state_at(BlockId::Number(0)).unwrap() { + GenesisOrUnavailableState::Genesis(_) => (), + _ => panic!("unexpected state"), + } +} + +#[test] +fn unavailable_state_is_created_when_genesis_state_is_unavailable() { + let backend: Backend<_, BlakeTwo256> = Backend::new( + Arc::new(DummyBlockchain::new(DummyStorage::new())), + ); + + match backend.state_at(BlockId::Number(0)).unwrap() { + GenesisOrUnavailableState::Unavailable => (), + _ => panic!("unexpected state"), + } +} + +#[test] +fn light_aux_store_is_updated_via_non_importing_op() { + let backend = Backend::new(Arc::new(DummyBlockchain::new(DummyStorage::new()))); + let mut op = ClientBackend::::begin_operation(&backend).unwrap(); + BlockImportOperation::::insert_aux(&mut op, vec![(vec![1], Some(vec![2]))]).unwrap(); + ClientBackend::::commit_operation(&backend, op).unwrap(); + + assert_eq!(AuxStore::get_aux(&backend, &[1]).unwrap(), Some(vec![2])); +} + +#[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_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( + &remote_block_id, + method, + &[] + ).unwrap(); + + // check remote execution proof locally + let local_result = check_execution_proof::<_, _, BlakeTwo256>( + &local_executor(), + tasks_executor(), + &RemoteCallRequest { + block: substrate_test_runtime_client::runtime::Hash::default(), + header: remote_header, + method: method.into(), + call_data: vec![], + retry_count: None, + }, + 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::<_, _, BlakeTwo256, _>( + &local_executor(), + tasks_executor(), + &RemoteCallRequest { + block: substrate_test_runtime_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(sp_blockchain::Error::Execution(_)) => (), + _ => panic!("Unexpected execution result: {:?}", execution_result), + } + } + + // prepare remote client + let mut remote_client = substrate_test_runtime_client::new(); + for i in 1u32..3u32 { + let mut digest = Digest::default(); + digest.push(sp_runtime::generic::DigestItem::Other::(i.to_le_bytes().to_vec())); + remote_client.import_justified( + BlockOrigin::Own, + remote_client.new_block(digest).unwrap().build().unwrap().block, + Default::default(), + ).unwrap(); + } + + // check method that doesn't requires environment + 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); + + 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 + sp_panic_handler::set("TEST", "1.2.3"); + execute_with_proof_failure(&remote_client, 2, "Core_version"); +} + +#[test] +fn code_is_executed_at_genesis_only() { + let backend = Arc::new(InMemBackend::::new()); + let def = H256::default(); + let header0 = substrate_test_runtime_client::runtime::Header::new(0, def, def, def, Default::default()); + let hash0 = header0.hash(); + let header1 = substrate_test_runtime_client::runtime::Header::new(1, def, def, hash0, Default::default()); + let hash1 = header1.hash(); + backend.blockchain().insert(hash0, header0, None, None, NewBlockState::Final).unwrap(); + backend.blockchain().insert(hash1, header1, None, None, NewBlockState::Final).unwrap(); + + let genesis_executor = GenesisCallExecutor::new(backend, DummyCallExecutor); + assert_eq!( + genesis_executor.call( + &BlockId::Number(0), + "test_method", + &[], + ExecutionStrategy::NativeElseWasm, + None, + ).unwrap(), + vec![42], + ); + + 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), + } +} + + +type TestChecker = LightDataChecker< + NativeExecutor, + BlakeTwo256, + Block, + DummyStorage, +>; + +fn prepare_for_read_proof_check() -> (TestChecker, Header, StorageProof, u32) { + // prepare remote client + let remote_client = substrate_test_runtime_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(); + + // '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, + &mut std::iter::once(well_known_keys::HEAP_PAGES), + ).unwrap(); + + // check remote read proof locally + let local_storage = InMemoryBlockchain::::new(); + local_storage.insert( + remote_block_hash, + remote_block_header.clone(), + None, + None, + NewBlockState::Final, + ).unwrap(); + let local_checker = LightDataChecker::new( + Arc::new(DummyBlockchain::new(DummyStorage::new())), + local_executor(), + tasks_executor(), + ); + (local_checker, remote_block_header, remote_read_proof, heap_pages) +} + +fn prepare_for_read_child_proof_check() -> (TestChecker, Header, StorageProof, Vec) { + use substrate_test_runtime_client::DefaultTestClientBuilderExt; + use substrate_test_runtime_client::TestClientBuilderExt; + let child_info = ChildInfo::new_default(b"child1"); + let child_info = &child_info; + // prepare remote client + let remote_client = substrate_test_runtime_client::TestClientBuilder::new() + .add_extra_child_storage( + child_info, + 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, + child_info, + &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, + child_info, + &mut std::iter::once("key1".as_bytes()), + ).unwrap(); + + // check locally + let local_storage = InMemoryBlockchain::::new(); + local_storage.insert( + remote_block_hash, + remote_block_header.clone(), + None, + None, + NewBlockState::Final, + ).unwrap(); + let local_checker = LightDataChecker::new( + Arc::new(DummyBlockchain::new(DummyStorage::new())), + local_executor(), + tasks_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 mut remote_client = substrate_test_runtime_client::new(); + let mut local_headers_hashes = Vec::new(); + for i in 0..4 { + let block = remote_client.new_block(Default::default()).unwrap().build().unwrap().block; + remote_client.import(BlockOrigin::Own, block).unwrap(); + local_headers_hashes.push( + remote_client.block_hash(i + 1) + .map_err(|_| ClientError::Backend("TestError".into())) + ); + } + + // 'fetch' header proof from remote node + let remote_block_id = BlockId::Number(1); + let (remote_block_header, remote_header_proof) = remote_client.header_proof_with_cht_size(&remote_block_id, 4).unwrap(); + + // check remote read proof locally + let local_storage = InMemoryBlockchain::::new(); + let local_cht_root = cht::compute_root::(4, 0, local_headers_hashes).unwrap(); + if insert_cht { + local_storage.insert_cht_root(1, local_cht_root); + } + let local_checker = LightDataChecker::new( + Arc::new(DummyBlockchain::new(DummyStorage::new())), + local_executor(), + tasks_executor(), + ); + (local_checker, local_cht_root, remote_block_header, remote_header_proof) +} + +fn header_with_computed_extrinsics_root(extrinsics: Vec) -> Header { + use sp_trie::{TrieConfiguration, trie_types::Layout}; + let iter = extrinsics.iter().map(Encode::encode); + let extrinsics_root = Layout::::ordered_trie_root(iter); + + // only care about `extrinsics_root` + Header::new(0, extrinsics_root, H256::zero(), H256::zero(), Default::default()) +} + +#[test] +fn storage_read_proof_is_generated_and_checked() { + let (local_checker, remote_block_header, remote_read_proof, heap_pages) = prepare_for_read_proof_check(); + assert_eq!((&local_checker as &dyn FetchChecker).check_read_proof(&RemoteReadRequest::
{ + block: remote_block_header.hash(), + header: remote_block_header, + keys: vec![well_known_keys::HEAP_PAGES.to_vec()], + retry_count: None, + }, 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 child_info = ChildInfo::new_default(&b"child1"[..]); + 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: child_info.prefixed_storage_key(), + keys: vec![b"key1".to_vec()], + retry_count: None, + }, + remote_read_proof + ).unwrap().remove(b"key1".as_ref()).unwrap().unwrap(), result); +} + +#[test] +fn header_proof_is_generated_and_checked() { + let (local_checker, local_cht_root, remote_block_header, remote_header_proof) = prepare_for_header_proof_check(true); + assert_eq!((&local_checker as &dyn FetchChecker).check_header_proof(&RemoteHeaderRequest::
{ + cht_root: local_cht_root, + block: 1, + retry_count: None, + }, Some(remote_block_header.clone()), remote_header_proof).unwrap(), remote_block_header); +} + +#[test] +fn check_header_proof_fails_if_cht_root_is_invalid() { + let (local_checker, _, mut remote_block_header, remote_header_proof) = prepare_for_header_proof_check(true); + remote_block_header.number = 100; + assert!((&local_checker as &dyn FetchChecker).check_header_proof(&RemoteHeaderRequest::
{ + cht_root: Default::default(), + block: 1, + retry_count: None, + }, Some(remote_block_header.clone()), remote_header_proof).is_err()); +} + +#[test] +fn check_header_proof_fails_if_invalid_header_provided() { + let (local_checker, local_cht_root, mut remote_block_header, remote_header_proof) = prepare_for_header_proof_check(true); + remote_block_header.number = 100; + assert!((&local_checker as &dyn FetchChecker).check_header_proof(&RemoteHeaderRequest::
{ + cht_root: local_cht_root, + block: 1, + retry_count: None, + }, Some(remote_block_header.clone()), remote_header_proof).is_err()); +} + +#[test] +fn changes_proof_is_generated_and_checked_when_headers_are_not_pruned() { + let (remote_client, local_roots, test_cases) = prepare_client_with_key_changes(); + let local_checker = TestChecker::new( + Arc::new(DummyBlockchain::new(DummyStorage::new())), + local_executor(), + tasks_executor(), + ); + let local_checker = &local_checker as &dyn FetchChecker; + let max = remote_client.chain_info().best_number; + let max_hash = remote_client.chain_info().best_hash; + + for (index, (begin, end, key, expected_result)) in test_cases.into_iter().enumerate() { + let begin_hash = remote_client.block_hash(begin).unwrap().unwrap(); + let end_hash = remote_client.block_hash(end).unwrap().unwrap(); + + // '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, None, &key + ).unwrap(); + + // check proof on local client + let local_roots_range = local_roots.clone()[(begin - 1) as usize..].to_vec(); + let config = ChangesTrieConfiguration::new(4, 2); + let request = RemoteChangesRequest::
{ + changes_trie_configs: vec![sp_core::ChangesTrieConfigurationRange { + zero: (0, Default::default()), + end: None, + config: Some(config), + }], + first_block: (begin, begin_hash), + last_block: (end, end_hash), + 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 { + max_block: remote_proof.max_block, + proof: remote_proof.proof, + roots: remote_proof.roots, + roots_proof: remote_proof.roots_proof, + }).unwrap(); + + // ..and ensure that result is the same as on remote node + match local_result == expected_result { + true => (), + false => panic!(format!("Failed test {}: local = {:?}, expected = {:?}", + index, local_result, expected_result)), + } + } +} + +#[test] +fn changes_proof_is_generated_and_checked_when_headers_are_pruned() { + // we're testing this test case here: + // (1, 4, dave.clone(), vec![(4, 0), (1, 1), (1, 0)]), + let (remote_client, remote_roots, _) = prepare_client_with_key_changes(); + let dave = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec(); + let dave = StorageKey(dave); + + // 'fetch' changes proof from remote node: + // we're fetching changes for range b1..b4 + // we do not know changes trie roots before b3 (i.e. we only know b3+b4) + // but we have changes trie CHT root for b1...b4 + let b1 = remote_client.block_hash_from_id(&BlockId::Number(1)).unwrap().unwrap(); + 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, None, &dave, 4 + ).unwrap(); + + // prepare local checker, having a root of changes trie CHT#0 + let local_cht_root = cht::compute_root::(4, 0, remote_roots.iter().cloned().map(|ct| Ok(Some(ct)))).unwrap(); + let mut local_storage = DummyStorage::new(); + local_storage.changes_tries_cht_roots.insert(0, local_cht_root); + let local_checker = TestChecker::new( + Arc::new(DummyBlockchain::new(local_storage)), + local_executor(), + tasks_executor(), + ); + + // check proof on local client + let config = ChangesTrieConfiguration::new(4, 2); + let request = RemoteChangesRequest::
{ + changes_trie_configs: vec![sp_core::ChangesTrieConfigurationRange { + zero: (0, Default::default()), + end: None, + config: Some(config), + }], + first_block: (1, b1), + 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, + }; + let local_result = local_checker.check_changes_proof_with_cht_size(&request, ChangesProof { + max_block: remote_proof.max_block, + proof: remote_proof.proof, + roots: remote_proof.roots, + roots_proof: remote_proof.roots_proof, + }, 4).unwrap(); + + assert_eq!(local_result, vec![(4, 0), (1, 1), (1, 0)]); +} + +#[test] +fn check_changes_proof_fails_if_proof_is_wrong() { + let (remote_client, local_roots, test_cases) = prepare_client_with_key_changes(); + let local_checker = TestChecker::new( + Arc::new(DummyBlockchain::new(DummyStorage::new())), + local_executor(), + tasks_executor(), + ); + let local_checker = &local_checker as &dyn FetchChecker; + let max = remote_client.chain_info().best_number; + let max_hash = remote_client.chain_info().best_hash; + + let (begin, end, key, _) = test_cases[0].clone(); + let begin_hash = remote_client.block_hash(begin).unwrap().unwrap(); + let end_hash = remote_client.block_hash(end).unwrap().unwrap(); + + // '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, None, &key).unwrap(); + + let local_roots_range = local_roots.clone()[(begin - 1) as usize..].to_vec(); + let config = ChangesTrieConfiguration::new(4, 2); + let request = RemoteChangesRequest::
{ + changes_trie_configs: vec![sp_core::ChangesTrieConfigurationRange { + zero: (0, Default::default()), + end: None, + config: Some(config), + }], + first_block: (begin, begin_hash), + 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, + }; + + // check proof on local client using max from the future + assert!(local_checker.check_changes_proof(&request, ChangesProof { + max_block: remote_proof.max_block + 1, + proof: remote_proof.proof.clone(), + roots: remote_proof.roots.clone(), + roots_proof: remote_proof.roots_proof.clone(), + }).is_err()); + + // check proof on local client using broken proof + assert!(local_checker.check_changes_proof(&request, ChangesProof { + max_block: remote_proof.max_block, + proof: local_roots_range.clone().into_iter().map(|v| v.as_ref().to_vec()).collect(), + roots: remote_proof.roots, + roots_proof: remote_proof.roots_proof, + }).is_err()); + + // extra roots proofs are provided + assert!(local_checker.check_changes_proof(&request, ChangesProof { + max_block: remote_proof.max_block, + proof: remote_proof.proof.clone(), + roots: vec![(begin - 1, Default::default())].into_iter().collect(), + 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: StorageProof::empty(), + }).is_err()); +} + +#[test] +fn check_changes_tries_proof_fails_if_proof_is_wrong() { + // we're testing this test case here: + // (1, 4, dave.clone(), vec![(4, 0), (1, 1), (1, 0)]), + let (remote_client, remote_roots, _) = prepare_client_with_key_changes(); + let local_cht_root = cht::compute_root::( + 4, 0, remote_roots.iter().cloned().map(|ct| Ok(Some(ct)))).unwrap(); + let dave = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec(); + let dave = StorageKey(dave); + + // 'fetch' changes proof from remote node: + // we're fetching changes for range b1..b4 + // we do not know changes trie roots before b3 (i.e. we only know b3+b4) + // but we have changes trie CHT root for b1...b4 + let b1 = remote_client.block_hash_from_id(&BlockId::Number(1)).unwrap().unwrap(); + 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, 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())), + local_executor(), + tasks_executor(), + ); + assert!(local_checker.check_changes_tries_proof(4, &remote_proof.roots, + remote_proof.roots_proof.clone()).is_err()); + + // fails when proof is broken + let mut local_storage = DummyStorage::new(); + local_storage.changes_tries_cht_roots.insert(0, local_cht_root); + let local_checker = TestChecker::new( + Arc::new(DummyBlockchain::new(local_storage)), + local_executor(), + tasks_executor(), + ); + let result = local_checker.check_changes_tries_proof( + 4, &remote_proof.roots, StorageProof::empty() + ); + assert!(result.is_err()); +} + +#[test] +fn check_body_proof_faulty() { + let header = header_with_computed_extrinsics_root( + vec![Extrinsic::IncludeData(vec![1, 2, 3, 4])] + ); + let block = Block::new(header.clone(), Vec::new()); + + let local_checker = TestChecker::new( + Arc::new(DummyBlockchain::new(DummyStorage::new())), + local_executor(), + tasks_executor(), + ); + + let body_request = RemoteBodyRequest { + header: header.clone(), + retry_count: None, + }; + + assert!( + local_checker.check_body_proof(&body_request, block.extrinsics).is_err(), + "vec![1, 2, 3, 4] != vec![]" + ); +} + +#[test] +fn check_body_proof_of_same_data_should_succeed() { + let extrinsics = vec![Extrinsic::IncludeData(vec![1, 2, 3, 4, 5, 6, 7, 8, 255])]; + + let header = header_with_computed_extrinsics_root(extrinsics.clone()); + let block = Block::new(header.clone(), extrinsics); + + let local_checker = TestChecker::new( + Arc::new(DummyBlockchain::new(DummyStorage::new())), + local_executor(), + tasks_executor(), + ); + + let body_request = RemoteBodyRequest { + header: header.clone(), + retry_count: None, + }; + + assert!(local_checker.check_body_proof(&body_request, block.extrinsics).is_ok()); +} diff --git a/client/service/test/src/client/mod.rs b/client/service/test/src/client/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..2124f0ced412294b134a153642dd8e2bec581133 --- /dev/null +++ b/client/service/test/src/client/mod.rs @@ -0,0 +1,1804 @@ +// This file is part of Substrate. + +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use parity_scale_codec::{Encode, Decode, Joiner}; +use sc_executor::native_executor_instance; +use sp_state_machine::{StateMachine, OverlayedChanges, ExecutionStrategy, InMemoryBackend}; +use substrate_test_runtime_client::{ + prelude::*, + runtime::{ + self, genesismap::{GenesisConfig, insert_genesis_block}, + Hash, Transfer, Block, BlockNumber, Header, Digest, RuntimeApi, + }, + AccountKeyring, Sr25519Keyring, TestClientBuilder, ClientBlockImportExt, + BlockBuilderExt, DefaultTestClientBuilderExt, TestClientBuilderExt, ClientExt, +}; +use sc_client_api::{ + StorageProvider, BlockBackend, in_mem, BlockchainEvents, +}; +use sc_client_db::{Backend, DatabaseSettings, DatabaseSettingsSrc, PruningMode}; +use sc_block_builder::BlockBuilderProvider; +use sc_service::client::{self, Client, LocalCallExecutor, new_in_mem}; +use sp_runtime::traits::{ + BlakeTwo256, Block as BlockT, Header as HeaderT, +}; +use substrate_test_runtime::TestAPI; +use sp_state_machine::backend::Backend as _; +use sp_api::{ProvideRuntimeApi, OffchainOverlayedChanges}; +use sp_core::tasks::executor as tasks_executor; +use sp_core::{H256, ChangesTrieConfiguration, blake2_256}; +use std::collections::{HashMap, HashSet}; +use std::sync::Arc; +use sp_consensus::{ + BlockOrigin, SelectChain, BlockImport, Error as ConsensusError, BlockCheckParams, ImportResult, + BlockStatus, BlockImportParams, ForkChoiceStrategy, +}; +use sp_storage::StorageKey; +use sp_trie::{TrieConfiguration, trie_types::Layout}; +use sp_runtime::{generic::BlockId, DigestItem}; +use hex_literal::hex; + +mod light; +mod db; + +native_executor_instance!( + Executor, + substrate_test_runtime_client::runtime::api::dispatch, + substrate_test_runtime_client::runtime::native_version, +); + +fn executor() -> sc_executor::NativeExecutor { + sc_executor::NativeExecutor::new( + sc_executor::WasmExecutionMethod::Interpreted, + None, + 8, + ) +} + +pub fn prepare_client_with_key_changes() -> ( + client::Client< + substrate_test_runtime_client::Backend, + substrate_test_runtime_client::Executor, + Block, + RuntimeApi + >, + Vec, + Vec<(u64, u64, Vec, Vec<(u64, u32)>)>, +) { + // prepare block structure + let blocks_transfers = vec![ + vec![(AccountKeyring::Alice, AccountKeyring::Dave), (AccountKeyring::Bob, AccountKeyring::Dave)], + vec![(AccountKeyring::Charlie, AccountKeyring::Eve)], + vec![], + vec![(AccountKeyring::Alice, AccountKeyring::Dave)], + ]; + + // prepare client ang import blocks + let mut local_roots = Vec::new(); + let config = Some(ChangesTrieConfiguration::new(4, 2)); + let mut remote_client = TestClientBuilder::new().changes_trie_config(config).build(); + let mut nonces: HashMap<_, u64> = Default::default(); + for (i, block_transfers) in blocks_transfers.into_iter().enumerate() { + let mut builder = remote_client.new_block(Default::default()).unwrap(); + for (from, to) in block_transfers { + builder.push_transfer(Transfer { + from: from.into(), + to: to.into(), + amount: 1, + nonce: *nonces.entry(from).and_modify(|n| { *n = *n + 1 }).or_default(), + }).unwrap(); + } + let block = builder.build().unwrap().block; + remote_client.import(BlockOrigin::Own, block).unwrap(); + + let header = remote_client.header(&BlockId::Number(i as u64 + 1)).unwrap().unwrap(); + let trie_root = header.digest().log(DigestItem::as_changes_trie_root) + .map(|root| H256::from_slice(root.as_ref())) + .unwrap(); + local_roots.push(trie_root); + } + + // prepare test cases + let alice = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Alice.into())).to_vec(); + let bob = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Bob.into())).to_vec(); + let charlie = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Charlie.into())).to_vec(); + let dave = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec(); + let eve = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Eve.into())).to_vec(); + let ferdie = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Ferdie.into())).to_vec(); + let test_cases = vec![ + (1, 4, alice.clone(), vec![(4, 0), (1, 0)]), + (1, 3, alice.clone(), vec![(1, 0)]), + (2, 4, alice.clone(), vec![(4, 0)]), + (2, 3, alice.clone(), vec![]), + (1, 4, bob.clone(), vec![(1, 1)]), + (1, 1, bob.clone(), vec![(1, 1)]), + (2, 4, bob.clone(), vec![]), + (1, 4, charlie.clone(), vec![(2, 0)]), + (1, 4, dave.clone(), vec![(4, 0), (1, 1), (1, 0)]), + (1, 1, dave.clone(), vec![(1, 1), (1, 0)]), + (3, 4, dave.clone(), vec![(4, 0)]), + (1, 4, eve.clone(), vec![(2, 0)]), + (1, 1, eve.clone(), vec![]), + (3, 4, eve.clone(), vec![]), + (1, 4, ferdie.clone(), vec![]), + ]; + + (remote_client, local_roots, test_cases) +} + +fn construct_block( + backend: &InMemoryBackend, + number: BlockNumber, + parent_hash: Hash, + state_root: Hash, + txs: Vec, +) -> (Vec, Hash) { + let transactions = txs.into_iter().map(|tx| tx.into_signed_tx()).collect::>(); + + let iter = transactions.iter().map(Encode::encode); + let extrinsics_root = Layout::::ordered_trie_root(iter).into(); + + let mut header = Header { + parent_hash, + number, + state_root, + extrinsics_root, + digest: Digest { logs: vec![] }, + }; + let hash = header.hash(); + let mut overlay = OverlayedChanges::default(); + let mut offchain_overlay = OffchainOverlayedChanges::default(); + let backend_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&backend); + let runtime_code = backend_runtime_code.runtime_code().expect("Code is part of the backend"); + + StateMachine::new( + backend, + sp_state_machine::disabled_changes_trie_state::<_, u64>(), + &mut overlay, + &mut offchain_overlay, + &executor(), + "Core_initialize_block", + &header.encode(), + Default::default(), + &runtime_code, + tasks_executor(), + ).execute( + ExecutionStrategy::NativeElseWasm, + ).unwrap(); + + for tx in transactions.iter() { + StateMachine::new( + backend, + sp_state_machine::disabled_changes_trie_state::<_, u64>(), + &mut overlay, + &mut offchain_overlay, + &executor(), + "BlockBuilder_apply_extrinsic", + &tx.encode(), + Default::default(), + &runtime_code, + tasks_executor(), + ).execute( + ExecutionStrategy::NativeElseWasm, + ).unwrap(); + } + + let ret_data = StateMachine::new( + backend, + sp_state_machine::disabled_changes_trie_state::<_, u64>(), + &mut overlay, + &mut offchain_overlay, + &executor(), + "BlockBuilder_finalize_block", + &[], + Default::default(), + &runtime_code, + tasks_executor(), + ).execute( + ExecutionStrategy::NativeElseWasm, + ).unwrap(); + header = Header::decode(&mut &ret_data[..]).unwrap(); + + (vec![].and(&Block { header, extrinsics: transactions }), hash) +} + +fn block1(genesis_hash: Hash, backend: &InMemoryBackend) -> (Vec, Hash) { + construct_block( + backend, + 1, + genesis_hash, + hex!("25e5b37074063ab75c889326246640729b40d0c86932edc527bc80db0e04fe5c").into(), + vec![Transfer { + from: AccountKeyring::One.into(), + to: AccountKeyring::Two.into(), + amount: 69, + nonce: 0, + }], + ) +} + +#[test] +fn construct_genesis_should_work_with_native() { + let mut storage = GenesisConfig::new( + None, + vec![Sr25519Keyring::One.public().into(), Sr25519Keyring::Two.public().into()], + vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], + 1000, + None, + Default::default(), + ).genesis_map(); + let genesis_hash = insert_genesis_block(&mut storage); + + let backend = InMemoryBackend::from(storage); + let (b1data, _b1hash) = block1(genesis_hash, &backend); + let backend_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&backend); + let runtime_code = backend_runtime_code.runtime_code().expect("Code is part of the backend"); + + let mut overlay = OverlayedChanges::default(); + let mut offchain_overlay = OffchainOverlayedChanges::default(); + + let _ = StateMachine::new( + &backend, + sp_state_machine::disabled_changes_trie_state::<_, u64>(), + &mut overlay, + &mut offchain_overlay, + &executor(), + "Core_execute_block", + &b1data, + Default::default(), + &runtime_code, + tasks_executor(), + ).execute( + ExecutionStrategy::NativeElseWasm, + ).unwrap(); +} + +#[test] +fn construct_genesis_should_work_with_wasm() { + let mut storage = GenesisConfig::new( + None, + vec![Sr25519Keyring::One.public().into(), Sr25519Keyring::Two.public().into()], + vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], + 1000, + None, + Default::default(), + ).genesis_map(); + let genesis_hash = insert_genesis_block(&mut storage); + + let backend = InMemoryBackend::from(storage); + let (b1data, _b1hash) = block1(genesis_hash, &backend); + let backend_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&backend); + let runtime_code = backend_runtime_code.runtime_code().expect("Code is part of the backend"); + + let mut overlay = OverlayedChanges::default(); + let mut offchain_overlay = OffchainOverlayedChanges::default(); + + let _ = StateMachine::new( + &backend, + sp_state_machine::disabled_changes_trie_state::<_, u64>(), + &mut overlay, + &mut offchain_overlay, + &executor(), + "Core_execute_block", + &b1data, + Default::default(), + &runtime_code, + tasks_executor(), + ).execute( + ExecutionStrategy::AlwaysWasm, + ).unwrap(); +} + +#[test] +fn construct_genesis_with_bad_transaction_should_panic() { + let mut storage = GenesisConfig::new( + None, + vec![Sr25519Keyring::One.public().into(), Sr25519Keyring::Two.public().into()], + vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], + 68, + None, + Default::default(), + ).genesis_map(); + let genesis_hash = insert_genesis_block(&mut storage); + + let backend = InMemoryBackend::from(storage); + let (b1data, _b1hash) = block1(genesis_hash, &backend); + let backend_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&backend); + let runtime_code = backend_runtime_code.runtime_code().expect("Code is part of the backend"); + + let mut overlay = OverlayedChanges::default(); + let mut offchain_overlay = OffchainOverlayedChanges::default(); + + let r = StateMachine::new( + &backend, + sp_state_machine::disabled_changes_trie_state::<_, u64>(), + &mut overlay, + &mut offchain_overlay, + &executor(), + "Core_execute_block", + &b1data, + Default::default(), + &runtime_code, + tasks_executor(), + ).execute( + ExecutionStrategy::NativeElseWasm, + ); + assert!(r.is_err()); +} + + +#[test] +fn client_initializes_from_genesis_ok() { + let client = substrate_test_runtime_client::new(); + + assert_eq!( + client.runtime_api().balance_of( + &BlockId::Number(client.chain_info().best_number), + AccountKeyring::Alice.into(), + ).unwrap(), + 1000 + ); + assert_eq!( + client.runtime_api().balance_of( + &BlockId::Number(client.chain_info().best_number), + AccountKeyring::Ferdie.into(), + ).unwrap(), + 0 + ); +} + +#[test] +fn block_builder_works_with_no_transactions() { + let mut client = substrate_test_runtime_client::new(); + + let block = client.new_block(Default::default()).unwrap().build().unwrap().block; + + client.import(BlockOrigin::Own, block).unwrap(); + + assert_eq!(client.chain_info().best_number, 1); +} + +#[test] +fn block_builder_works_with_transactions() { + let mut client = substrate_test_runtime_client::new(); + + let mut builder = client.new_block(Default::default()).unwrap(); + + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 42, + nonce: 0, + }).unwrap(); + + let block = builder.build().unwrap().block; + client.import(BlockOrigin::Own, block).unwrap(); + + assert_eq!(client.chain_info().best_number, 1); + assert_ne!( + client.state_at(&BlockId::Number(1)).unwrap().pairs(), + client.state_at(&BlockId::Number(0)).unwrap().pairs() + ); + assert_eq!( + client.runtime_api().balance_of( + &BlockId::Number(client.chain_info().best_number), + AccountKeyring::Alice.into(), + ).unwrap(), + 958 + ); + assert_eq!( + client.runtime_api().balance_of( + &BlockId::Number(client.chain_info().best_number), + AccountKeyring::Ferdie.into(), + ).unwrap(), + 42 + ); +} + +#[test] +fn block_builder_does_not_include_invalid() { + let mut client = substrate_test_runtime_client::new(); + + let mut builder = client.new_block(Default::default()).unwrap(); + + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 42, + nonce: 0, + }).unwrap(); + + assert!( + builder.push_transfer(Transfer { + from: AccountKeyring::Eve.into(), + to: AccountKeyring::Alice.into(), + amount: 42, + nonce: 0, + }).is_err() + ); + + let block = builder.build().unwrap().block; + client.import(BlockOrigin::Own, block).unwrap(); + + assert_eq!(client.chain_info().best_number, 1); + assert_ne!( + client.state_at(&BlockId::Number(1)).unwrap().pairs(), + client.state_at(&BlockId::Number(0)).unwrap().pairs() + ); + assert_eq!(client.body(&BlockId::Number(1)).unwrap().unwrap().len(), 1) +} + +#[test] +fn best_containing_with_genesis_block() { + // block tree: + // G + + let (client, longest_chain_select) = TestClientBuilder::new().build_with_longest_chain(); + + let genesis_hash = client.chain_info().genesis_hash; + + assert_eq!( + genesis_hash.clone(), + longest_chain_select.finality_target(genesis_hash.clone(), None).unwrap().unwrap() + ); +} + +#[test] +fn best_containing_with_hash_not_found() { + // block tree: + // G + + let (client, longest_chain_select) = TestClientBuilder::new().build_with_longest_chain(); + + let uninserted_block = client.new_block(Default::default()).unwrap().build().unwrap().block; + + assert_eq!( + None, + longest_chain_select.finality_target(uninserted_block.hash().clone(), None).unwrap() + ); +} + +#[test] +fn uncles_with_only_ancestors() { + // block tree: + // G -> A1 -> A2 + let mut client = substrate_test_runtime_client::new(); + + // G -> A1 + let a1 = client.new_block(Default::default()).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + + // A1 -> A2 + let a2 = client.new_block(Default::default()).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a2.clone()).unwrap(); + let v: Vec = Vec::new(); + assert_eq!(v, client.uncles(a2.hash(), 3).unwrap()); +} + +#[test] +fn uncles_with_multiple_forks() { + // block tree: + // G -> A1 -> A2 -> A3 -> A4 -> A5 + // A1 -> B2 -> B3 -> B4 + // B2 -> C3 + // A1 -> D2 + let mut client = substrate_test_runtime_client::new(); + + // G -> A1 + let a1 = client.new_block(Default::default()).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + + // A1 -> A2 + let a2 = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a2.clone()).unwrap(); + + // A2 -> A3 + let a3 = client.new_block_at( + &BlockId::Hash(a2.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a3.clone()).unwrap(); + + // A3 -> A4 + let a4 = client.new_block_at( + &BlockId::Hash(a3.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a4.clone()).unwrap(); + + // A4 -> A5 + let a5 = client.new_block_at( + &BlockId::Hash(a4.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a5.clone()).unwrap(); + + // A1 -> B2 + let mut builder = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap(); + // this push is required as otherwise B2 has the same hash as A2 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 41, + nonce: 0, + }).unwrap(); + let b2 = builder.build().unwrap().block; + client.import(BlockOrigin::Own, b2.clone()).unwrap(); + + // B2 -> B3 + let b3 = client.new_block_at( + &BlockId::Hash(b2.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, b3.clone()).unwrap(); + + // B3 -> B4 + let b4 = client.new_block_at( + &BlockId::Hash(b3.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, b4.clone()).unwrap(); + + // // B2 -> C3 + let mut builder = client.new_block_at( + &BlockId::Hash(b2.hash()), + Default::default(), + false, + ).unwrap(); + // this push is required as otherwise C3 has the same hash as B3 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 1, + nonce: 1, + }).unwrap(); + let c3 = builder.build().unwrap().block; + client.import(BlockOrigin::Own, c3.clone()).unwrap(); + + // A1 -> D2 + let mut builder = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap(); + // this push is required as otherwise D2 has the same hash as B2 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 1, + nonce: 0, + }).unwrap(); + let d2 = builder.build().unwrap().block; + client.import(BlockOrigin::Own, d2.clone()).unwrap(); + + let genesis_hash = client.chain_info().genesis_hash; + + let uncles1 = client.uncles(a4.hash(), 10).unwrap(); + assert_eq!(vec![b2.hash(), d2.hash()], uncles1); + + let uncles2 = client.uncles(a4.hash(), 0).unwrap(); + assert_eq!(0, uncles2.len()); + + let uncles3 = client.uncles(a1.hash(), 10).unwrap(); + assert_eq!(0, uncles3.len()); + + let uncles4 = client.uncles(genesis_hash, 10).unwrap(); + assert_eq!(0, uncles4.len()); + + let uncles5 = client.uncles(d2.hash(), 10).unwrap(); + assert_eq!(vec![a2.hash(), b2.hash()], uncles5); + + let uncles6 = client.uncles(b3.hash(), 1).unwrap(); + assert_eq!(vec![c3.hash()], uncles6); +} + +#[test] +fn best_containing_on_longest_chain_with_single_chain_3_blocks() { + // block tree: + // G -> A1 -> A2 + + let (mut client, longest_chain_select) = TestClientBuilder::new().build_with_longest_chain(); + + // G -> A1 + let a1 = client.new_block(Default::default()).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + + // A1 -> A2 + let a2 = client.new_block(Default::default()).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a2.clone()).unwrap(); + + let genesis_hash = client.chain_info().genesis_hash; + + assert_eq!(a2.hash(), longest_chain_select.finality_target(genesis_hash, None).unwrap().unwrap()); + assert_eq!(a2.hash(), longest_chain_select.finality_target(a1.hash(), None).unwrap().unwrap()); + assert_eq!(a2.hash(), longest_chain_select.finality_target(a2.hash(), None).unwrap().unwrap()); +} + +#[test] +fn best_containing_on_longest_chain_with_multiple_forks() { + // block tree: + // G -> A1 -> A2 -> A3 -> A4 -> A5 + // A1 -> B2 -> B3 -> B4 + // B2 -> C3 + // A1 -> D2 + let (mut client, longest_chain_select) = TestClientBuilder::new().build_with_longest_chain(); + + // G -> A1 + let a1 = client.new_block(Default::default()).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + + // A1 -> A2 + let a2 = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a2.clone()).unwrap(); + + // A2 -> A3 + let a3 = client.new_block_at( + &BlockId::Hash(a2.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a3.clone()).unwrap(); + + // A3 -> A4 + let a4 = client.new_block_at( + &BlockId::Hash(a3.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a4.clone()).unwrap(); + + // A4 -> A5 + let a5 = client.new_block_at( + &BlockId::Hash(a4.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a5.clone()).unwrap(); + + // A1 -> B2 + let mut builder = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap(); + // this push is required as otherwise B2 has the same hash as A2 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 41, + nonce: 0, + }).unwrap(); + let b2 = builder.build().unwrap().block; + client.import(BlockOrigin::Own, b2.clone()).unwrap(); + + // B2 -> B3 + let b3 = client.new_block_at( + &BlockId::Hash(b2.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, b3.clone()).unwrap(); + + // B3 -> B4 + let b4 = client.new_block_at( + &BlockId::Hash(b3.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, b4.clone()).unwrap(); + + // // B2 -> C3 + let mut builder = client.new_block_at( + &BlockId::Hash(b2.hash()), + Default::default(), + false, + ).unwrap(); + // this push is required as otherwise C3 has the same hash as B3 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 1, + nonce: 1, + }).unwrap(); + let c3 = builder.build().unwrap().block; + client.import(BlockOrigin::Own, c3.clone()).unwrap(); + + // A1 -> D2 + let mut builder = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap(); + // this push is required as otherwise D2 has the same hash as B2 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 1, + nonce: 0, + }).unwrap(); + let d2 = builder.build().unwrap().block; + client.import(BlockOrigin::Own, d2.clone()).unwrap(); + + assert_eq!(client.chain_info().best_hash, a5.hash()); + + let genesis_hash = client.chain_info().genesis_hash; + let leaves = longest_chain_select.leaves().unwrap(); + + assert!(leaves.contains(&a5.hash())); + assert!(leaves.contains(&b4.hash())); + assert!(leaves.contains(&c3.hash())); + assert!(leaves.contains(&d2.hash())); + assert_eq!(leaves.len(), 4); + + // search without restriction + + assert_eq!(a5.hash(), longest_chain_select.finality_target( + genesis_hash, None).unwrap().unwrap()); + assert_eq!(a5.hash(), longest_chain_select.finality_target( + a1.hash(), None).unwrap().unwrap()); + assert_eq!(a5.hash(), longest_chain_select.finality_target( + a2.hash(), None).unwrap().unwrap()); + assert_eq!(a5.hash(), longest_chain_select.finality_target( + a3.hash(), None).unwrap().unwrap()); + assert_eq!(a5.hash(), longest_chain_select.finality_target( + a4.hash(), None).unwrap().unwrap()); + assert_eq!(a5.hash(), longest_chain_select.finality_target( + a5.hash(), None).unwrap().unwrap()); + + assert_eq!(b4.hash(), longest_chain_select.finality_target( + b2.hash(), None).unwrap().unwrap()); + assert_eq!(b4.hash(), longest_chain_select.finality_target( + b3.hash(), None).unwrap().unwrap()); + assert_eq!(b4.hash(), longest_chain_select.finality_target( + b4.hash(), None).unwrap().unwrap()); + + assert_eq!(c3.hash(), longest_chain_select.finality_target( + c3.hash(), None).unwrap().unwrap()); + + assert_eq!(d2.hash(), longest_chain_select.finality_target( + d2.hash(), None).unwrap().unwrap()); + + + // search only blocks with number <= 5. equivalent to without restriction for this scenario + + assert_eq!(a5.hash(), longest_chain_select.finality_target( + genesis_hash, Some(5)).unwrap().unwrap()); + assert_eq!(a5.hash(), longest_chain_select.finality_target( + a1.hash(), Some(5)).unwrap().unwrap()); + assert_eq!(a5.hash(), longest_chain_select.finality_target( + a2.hash(), Some(5)).unwrap().unwrap()); + assert_eq!(a5.hash(), longest_chain_select.finality_target( + a3.hash(), Some(5)).unwrap().unwrap()); + assert_eq!(a5.hash(), longest_chain_select.finality_target( + a4.hash(), Some(5)).unwrap().unwrap()); + assert_eq!(a5.hash(), longest_chain_select.finality_target( + a5.hash(), Some(5)).unwrap().unwrap()); + + assert_eq!(b4.hash(), longest_chain_select.finality_target( + b2.hash(), Some(5)).unwrap().unwrap()); + assert_eq!(b4.hash(), longest_chain_select.finality_target( + b3.hash(), Some(5)).unwrap().unwrap()); + assert_eq!(b4.hash(), longest_chain_select.finality_target( + b4.hash(), Some(5)).unwrap().unwrap()); + + assert_eq!(c3.hash(), longest_chain_select.finality_target( + c3.hash(), Some(5)).unwrap().unwrap()); + + assert_eq!(d2.hash(), longest_chain_select.finality_target( + d2.hash(), Some(5)).unwrap().unwrap()); + + + // search only blocks with number <= 4 + + assert_eq!(a4.hash(), longest_chain_select.finality_target( + genesis_hash, Some(4)).unwrap().unwrap()); + assert_eq!(a4.hash(), longest_chain_select.finality_target( + a1.hash(), Some(4)).unwrap().unwrap()); + assert_eq!(a4.hash(), longest_chain_select.finality_target( + a2.hash(), Some(4)).unwrap().unwrap()); + assert_eq!(a4.hash(), longest_chain_select.finality_target( + a3.hash(), Some(4)).unwrap().unwrap()); + assert_eq!(a4.hash(), longest_chain_select.finality_target( + a4.hash(), Some(4)).unwrap().unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a5.hash(), Some(4)).unwrap()); + + assert_eq!(b4.hash(), longest_chain_select.finality_target( + b2.hash(), Some(4)).unwrap().unwrap()); + assert_eq!(b4.hash(), longest_chain_select.finality_target( + b3.hash(), Some(4)).unwrap().unwrap()); + assert_eq!(b4.hash(), longest_chain_select.finality_target( + b4.hash(), Some(4)).unwrap().unwrap()); + + assert_eq!(c3.hash(), longest_chain_select.finality_target( + c3.hash(), Some(4)).unwrap().unwrap()); + + assert_eq!(d2.hash(), longest_chain_select.finality_target( + d2.hash(), Some(4)).unwrap().unwrap()); + + + // search only blocks with number <= 3 + + assert_eq!(a3.hash(), longest_chain_select.finality_target( + genesis_hash, Some(3)).unwrap().unwrap()); + assert_eq!(a3.hash(), longest_chain_select.finality_target( + a1.hash(), Some(3)).unwrap().unwrap()); + assert_eq!(a3.hash(), longest_chain_select.finality_target( + a2.hash(), Some(3)).unwrap().unwrap()); + assert_eq!(a3.hash(), longest_chain_select.finality_target( + a3.hash(), Some(3)).unwrap().unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a4.hash(), Some(3)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a5.hash(), Some(3)).unwrap()); + + assert_eq!(b3.hash(), longest_chain_select.finality_target( + b2.hash(), Some(3)).unwrap().unwrap()); + assert_eq!(b3.hash(), longest_chain_select.finality_target( + b3.hash(), Some(3)).unwrap().unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + b4.hash(), Some(3)).unwrap()); + + assert_eq!(c3.hash(), longest_chain_select.finality_target( + c3.hash(), Some(3)).unwrap().unwrap()); + + assert_eq!(d2.hash(), longest_chain_select.finality_target( + d2.hash(), Some(3)).unwrap().unwrap()); + + + // search only blocks with number <= 2 + + assert_eq!(a2.hash(), longest_chain_select.finality_target( + genesis_hash, Some(2)).unwrap().unwrap()); + assert_eq!(a2.hash(), longest_chain_select.finality_target( + a1.hash(), Some(2)).unwrap().unwrap()); + assert_eq!(a2.hash(), longest_chain_select.finality_target( + a2.hash(), Some(2)).unwrap().unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a3.hash(), Some(2)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a4.hash(), Some(2)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a5.hash(), Some(2)).unwrap()); + + assert_eq!(b2.hash(), longest_chain_select.finality_target( + b2.hash(), Some(2)).unwrap().unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + b3.hash(), Some(2)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + b4.hash(), Some(2)).unwrap()); + + assert_eq!(None, longest_chain_select.finality_target( + c3.hash(), Some(2)).unwrap()); + + assert_eq!(d2.hash(), longest_chain_select.finality_target( + d2.hash(), Some(2)).unwrap().unwrap()); + + + // search only blocks with number <= 1 + + assert_eq!(a1.hash(), longest_chain_select.finality_target( + genesis_hash, Some(1)).unwrap().unwrap()); + assert_eq!(a1.hash(), longest_chain_select.finality_target( + a1.hash(), Some(1)).unwrap().unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a2.hash(), Some(1)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a3.hash(), Some(1)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a4.hash(), Some(1)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a5.hash(), Some(1)).unwrap()); + + assert_eq!(None, longest_chain_select.finality_target( + b2.hash(), Some(1)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + b3.hash(), Some(1)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + b4.hash(), Some(1)).unwrap()); + + assert_eq!(None, longest_chain_select.finality_target( + c3.hash(), Some(1)).unwrap()); + + assert_eq!(None, longest_chain_select.finality_target( + d2.hash(), Some(1)).unwrap()); + + // search only blocks with number <= 0 + + assert_eq!(genesis_hash, longest_chain_select.finality_target( + genesis_hash, Some(0)).unwrap().unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a1.hash(), Some(0)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a2.hash(), Some(0)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a3.hash(), Some(0)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a4.hash(), Some(0)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a5.hash(), Some(0)).unwrap()); + + assert_eq!(None, longest_chain_select.finality_target( + b2.hash(), Some(0)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + b3.hash(), Some(0)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + b4.hash(), Some(0)).unwrap()); + + assert_eq!(None, longest_chain_select.finality_target( + c3.hash().clone(), Some(0)).unwrap()); + + assert_eq!(None, longest_chain_select.finality_target( + d2.hash().clone(), Some(0)).unwrap()); +} + +#[test] +fn best_containing_on_longest_chain_with_max_depth_higher_than_best() { + // block tree: + // G -> A1 -> A2 + + let (mut client, longest_chain_select) = TestClientBuilder::new().build_with_longest_chain(); + + // G -> A1 + let a1 = client.new_block(Default::default()).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + + // A1 -> A2 + let a2 = client.new_block(Default::default()).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a2.clone()).unwrap(); + + let genesis_hash = client.chain_info().genesis_hash; + + assert_eq!(a2.hash(), longest_chain_select.finality_target(genesis_hash, Some(10)).unwrap().unwrap()); +} + +#[test] +fn key_changes_works() { + let (client, _, test_cases) = prepare_client_with_key_changes(); + + 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), + None, + &StorageKey(key), + ).unwrap(); + match actual_result == expected_result { + true => (), + false => panic!(format!("Failed test {}: actual = {:?}, expected = {:?}", + index, actual_result, expected_result)), + } + } +} + +#[test] +fn import_with_justification() { + let mut client = substrate_test_runtime_client::new(); + + // G -> A1 + let a1 = client.new_block(Default::default()).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + + // A1 -> A2 + let a2 = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a2.clone()).unwrap(); + + // A2 -> A3 + let justification = vec![1, 2, 3]; + let a3 = client.new_block_at( + &BlockId::Hash(a2.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import_justified(BlockOrigin::Own, a3.clone(), justification.clone()).unwrap(); + + assert_eq!( + client.chain_info().finalized_hash, + a3.hash(), + ); + + assert_eq!( + client.justification(&BlockId::Hash(a3.hash())).unwrap(), + Some(justification), + ); + + assert_eq!( + client.justification(&BlockId::Hash(a1.hash())).unwrap(), + None, + ); + + assert_eq!( + client.justification(&BlockId::Hash(a2.hash())).unwrap(), + None, + ); +} + +#[test] +fn importing_diverged_finalized_block_should_trigger_reorg() { + let mut client = substrate_test_runtime_client::new(); + + // G -> A1 -> A2 + // \ + // -> B1 + let a1 = client.new_block_at( + &BlockId::Number(0), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + + let a2 = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a2.clone()).unwrap(); + + let mut b1 = client.new_block_at( + &BlockId::Number(0), + Default::default(), + false, + ).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: 1, + nonce: 0, + }).unwrap(); + // create but don't import B1 just yet + let b1 = b1.build().unwrap().block; + + // A2 is the current best since it's the longest chain + assert_eq!( + client.chain_info().best_hash, + a2.hash(), + ); + + // importing B1 as finalized should trigger a re-org and set it as new best + let justification = vec![1, 2, 3]; + client.import_justified(BlockOrigin::Own, b1.clone(), justification).unwrap(); + + assert_eq!( + client.chain_info().best_hash, + b1.hash(), + ); + + assert_eq!( + client.chain_info().finalized_hash, + b1.hash(), + ); +} + +#[test] +fn finalizing_diverged_block_should_trigger_reorg() { + let (mut client, select_chain) = TestClientBuilder::new().build_with_longest_chain(); + + // G -> A1 -> A2 + // \ + // -> B1 -> B2 + let a1 = client.new_block_at( + &BlockId::Number(0), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + + let a2 = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a2.clone()).unwrap(); + + let mut b1 = client.new_block_at( + &BlockId::Number(0), + Default::default(), + false, + ).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: 1, + nonce: 0, + }).unwrap(); + let b1 = b1.build().unwrap().block; + client.import(BlockOrigin::Own, b1.clone()).unwrap(); + + let b2 = client.new_block_at( + &BlockId::Hash(b1.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, b2.clone()).unwrap(); + + // A2 is the current best since it's the longest chain + assert_eq!( + client.chain_info().best_hash, + a2.hash(), + ); + + // we finalize block B1 which is on a different branch from current best + // which should trigger a re-org. + ClientExt::finalize_block(&client, BlockId::Hash(b1.hash()), None).unwrap(); + + // B1 should now be the latest finalized + assert_eq!( + client.chain_info().finalized_hash, + b1.hash(), + ); + + // and B1 should be the new best block (`finalize_block` as no way of + // knowing about B2) + assert_eq!( + client.chain_info().best_hash, + b1.hash(), + ); + + // `SelectChain` should report B2 as best block though + assert_eq!( + select_chain.best_chain().unwrap().hash(), + b2.hash(), + ); + + // after we build B3 on top of B2 and import it + // it should be the new best block, + let b3 = client.new_block_at( + &BlockId::Hash(b2.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, b3.clone()).unwrap(); + + assert_eq!( + client.chain_info().best_hash, + b3.hash(), + ); +} + +#[test] +fn get_header_by_block_number_doesnt_panic() { + let client = substrate_test_runtime_client::new(); + + // backend uses u32 for block numbers, make sure we don't panic when + // trying to convert + let id = BlockId::::Number(72340207214430721); + client.header(&id).expect_err("invalid block number overflows u32"); +} + +#[test] +fn state_reverted_on_reorg() { + let _ = env_logger::try_init(); + let mut client = substrate_test_runtime_client::new(); + + let current_balance = |client: &substrate_test_runtime_client::TestClient| + client.runtime_api().balance_of( + &BlockId::number(client.chain_info().best_number), AccountKeyring::Alice.into(), + ).unwrap(); + + // G -> A1 -> A2 + // \ + // -> B1 + let mut a1 = client.new_block_at( + &BlockId::Number(0), + Default::default(), + false, + ).unwrap(); + a1.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Bob.into(), + amount: 10, + nonce: 0, + }).unwrap(); + let a1 = a1.build().unwrap().block; + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + + let mut b1 = client.new_block_at( + &BlockId::Number(0), + Default::default(), + false, + ).unwrap(); + b1.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 50, + nonce: 0, + }).unwrap(); + let b1 = b1.build().unwrap().block; + // Reorg to B1 + client.import_as_best(BlockOrigin::Own, b1.clone()).unwrap(); + + assert_eq!(950, current_balance(&client)); + let mut a2 = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap(); + a2.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Charlie.into(), + amount: 10, + nonce: 1, + }).unwrap(); + let a2 = a2.build().unwrap().block; + // Re-org to A2 + client.import_as_best(BlockOrigin::Own, a2).unwrap(); + assert_eq!(980, current_balance(&client)); +} + +#[test] +fn doesnt_import_blocks_that_revert_finality() { + let _ = env_logger::try_init(); + 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::RocksDb { + path: tmp.path().into(), + cache_size: 1024, + }, + }, + u64::max_value(), + ).unwrap()); + + let mut client = TestClientBuilder::with_backend(backend).build(); + + // -> C1 + // / + // G -> A1 -> A2 + // \ + // -> B1 -> B2 -> B3 + + let a1 = client.new_block_at( + &BlockId::Number(0), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + + let a2 = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a2.clone()).unwrap(); + + let mut b1 = client.new_block_at(&BlockId::Number(0), Default::default(), false).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: 1, + nonce: 0, + }).unwrap(); + let b1 = b1.build().unwrap().block; + client.import(BlockOrigin::Own, b1.clone()).unwrap(); + + let b2 = client.new_block_at(&BlockId::Hash(b1.hash()), Default::default(), false) + .unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, b2.clone()).unwrap(); + + // prepare B3 before we finalize A2, because otherwise we won't be able to + // read changes trie configuration after A2 is finalized + let b3 = client.new_block_at(&BlockId::Hash(b2.hash()), Default::default(), false) + .unwrap().build().unwrap().block; + + // we will finalize A2 which should make it impossible to import a new + // B3 at the same height but that doesn't include it + ClientExt::finalize_block(&client, BlockId::Hash(a2.hash()), None).unwrap(); + + let import_err = client.import(BlockOrigin::Own, b3).err().unwrap(); + let expected_err = ConsensusError::ClientImport( + sp_blockchain::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(), false).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.build().unwrap().block; + + let import_err = client.import(BlockOrigin::Own, c1).err().unwrap(); + let expected_err = ConsensusError::ClientImport( + sp_blockchain::Error::NotInFinalizedChain.to_string() + ); + + assert_eq!( + import_err.to_string(), + expected_err.to_string(), + ); +} + + +#[test] +fn respects_block_rules() { + fn run_test( + record_only: bool, + known_bad: &mut HashSet, + fork_rules: &mut Vec<(u64, H256)>, + ) { + let mut client = if record_only { + TestClientBuilder::new().build() + } else { + TestClientBuilder::new() + .set_block_rules( + Some(fork_rules.clone()), + Some(known_bad.clone()), + ) + .build() + }; + + let block_ok = client.new_block_at(&BlockId::Number(0), Default::default(), false) + .unwrap().build().unwrap().block; + + let params = BlockCheckParams { + hash: block_ok.hash().clone(), + number: 0, + parent_hash: block_ok.header().parent_hash().clone(), + allow_missing_state: false, + import_existing: false, + }; + assert_eq!(client.check_block(params).unwrap(), ImportResult::imported(false)); + + // this is 0x0d6d6612a10485370d9e085aeea7ec427fb3f34d961c6a816cdbe5cde2278864 + let mut block_not_ok = client.new_block_at(&BlockId::Number(0), Default::default(), false) + .unwrap(); + block_not_ok.push_storage_change(vec![0], Some(vec![1])).unwrap(); + let block_not_ok = block_not_ok.build().unwrap().block; + + let params = BlockCheckParams { + hash: block_not_ok.hash().clone(), + number: 0, + parent_hash: block_not_ok.header().parent_hash().clone(), + allow_missing_state: false, + import_existing: false, + }; + if record_only { + known_bad.insert(block_not_ok.hash()); + } else { + assert_eq!(client.check_block(params).unwrap(), ImportResult::KnownBad); + } + + // Now going to the fork + client.import_as_final(BlockOrigin::Own, block_ok).unwrap(); + + // And check good fork + let mut block_ok = client.new_block_at(&BlockId::Number(1), Default::default(), false) + .unwrap(); + block_ok.push_storage_change(vec![0], Some(vec![2])).unwrap(); + let block_ok = block_ok.build().unwrap().block; + + let params = BlockCheckParams { + hash: block_ok.hash().clone(), + number: 1, + parent_hash: block_ok.header().parent_hash().clone(), + allow_missing_state: false, + import_existing: false, + }; + if record_only { + fork_rules.push((1, block_ok.hash().clone())); + } + assert_eq!(client.check_block(params).unwrap(), ImportResult::imported(false)); + + // And now try bad fork + let mut block_not_ok = client.new_block_at(&BlockId::Number(1), Default::default(), false) + .unwrap(); + block_not_ok.push_storage_change(vec![0], Some(vec![3])).unwrap(); + let block_not_ok = block_not_ok.build().unwrap().block; + + let params = BlockCheckParams { + hash: block_not_ok.hash().clone(), + number: 1, + parent_hash: block_not_ok.header().parent_hash().clone(), + allow_missing_state: false, + import_existing: false, + }; + + if !record_only { + assert_eq!(client.check_block(params).unwrap(), ImportResult::KnownBad); + } + } + + let mut known_bad = HashSet::new(); + let mut fork_rules = Vec::new(); + + // records what bad_blocks and fork_blocks hashes should be + run_test(true, &mut known_bad, &mut fork_rules); + + // enforces rules and actually makes assertions + run_test(false, &mut known_bad, &mut fork_rules); +} + +#[test] +fn returns_status_for_pruned_blocks() { + let _ = env_logger::try_init(); + let tmp = tempfile::tempdir().unwrap(); + + // set to prune after 1 block + // states + let backend = Arc::new(Backend::new( + DatabaseSettings { + state_cache_size: 1 << 20, + state_cache_child_ratio: None, + pruning: PruningMode::keep_blocks(1), + source: DatabaseSettingsSrc::RocksDb { + path: tmp.path().into(), + cache_size: 1024, + }, + }, + u64::max_value(), + ).unwrap()); + + let mut client = TestClientBuilder::with_backend(backend).build(); + + let a1 = client.new_block_at(&BlockId::Number(0), Default::default(), false) + .unwrap().build().unwrap().block; + + let mut b1 = client.new_block_at(&BlockId::Number(0), Default::default(), false).unwrap(); + + // b1 is created, but not imported + b1.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 1, + nonce: 0, + }).unwrap(); + let b1 = b1.build().unwrap().block; + + let check_block_a1 = BlockCheckParams { + hash: a1.hash().clone(), + number: 0, + parent_hash: a1.header().parent_hash().clone(), + allow_missing_state: false, + import_existing: false, + }; + + assert_eq!(client.check_block(check_block_a1.clone()).unwrap(), ImportResult::imported(false)); + assert_eq!(client.block_status(&BlockId::hash(check_block_a1.hash)).unwrap(), BlockStatus::Unknown); + + client.import_as_final(BlockOrigin::Own, a1.clone()).unwrap(); + + assert_eq!(client.check_block(check_block_a1.clone()).unwrap(), ImportResult::AlreadyInChain); + assert_eq!(client.block_status(&BlockId::hash(check_block_a1.hash)).unwrap(), BlockStatus::InChainWithState); + + let a2 = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default(), false) + .unwrap().build().unwrap().block; + client.import_as_final(BlockOrigin::Own, a2.clone()).unwrap(); + + let check_block_a2 = BlockCheckParams { + hash: a2.hash().clone(), + number: 1, + parent_hash: a1.header().parent_hash().clone(), + allow_missing_state: false, + import_existing: false, + }; + + assert_eq!(client.check_block(check_block_a1.clone()).unwrap(), ImportResult::AlreadyInChain); + assert_eq!(client.block_status(&BlockId::hash(check_block_a1.hash)).unwrap(), BlockStatus::InChainPruned); + assert_eq!(client.check_block(check_block_a2.clone()).unwrap(), ImportResult::AlreadyInChain); + assert_eq!(client.block_status(&BlockId::hash(check_block_a2.hash)).unwrap(), BlockStatus::InChainWithState); + + let a3 = client.new_block_at(&BlockId::Hash(a2.hash()), Default::default(), false) + .unwrap().build().unwrap().block; + + client.import_as_final(BlockOrigin::Own, a3.clone()).unwrap(); + let check_block_a3 = BlockCheckParams { + hash: a3.hash().clone(), + number: 2, + parent_hash: a2.header().parent_hash().clone(), + allow_missing_state: false, + import_existing: false, + }; + + // a1 and a2 are both pruned at this point + assert_eq!(client.check_block(check_block_a1.clone()).unwrap(), ImportResult::AlreadyInChain); + assert_eq!(client.block_status(&BlockId::hash(check_block_a1.hash)).unwrap(), BlockStatus::InChainPruned); + assert_eq!(client.check_block(check_block_a2.clone()).unwrap(), ImportResult::AlreadyInChain); + assert_eq!(client.block_status(&BlockId::hash(check_block_a2.hash)).unwrap(), BlockStatus::InChainPruned); + assert_eq!(client.check_block(check_block_a3.clone()).unwrap(), ImportResult::AlreadyInChain); + assert_eq!(client.block_status(&BlockId::hash(check_block_a3.hash)).unwrap(), BlockStatus::InChainWithState); + + let mut check_block_b1 = BlockCheckParams { + hash: b1.hash().clone(), + number: 0, + parent_hash: b1.header().parent_hash().clone(), + allow_missing_state: false, + import_existing: false, + }; + assert_eq!(client.check_block(check_block_b1.clone()).unwrap(), ImportResult::MissingState); + check_block_b1.allow_missing_state = true; + assert_eq!(client.check_block(check_block_b1.clone()).unwrap(), ImportResult::imported(false)); + check_block_b1.parent_hash = H256::random(); + assert_eq!(client.check_block(check_block_b1.clone()).unwrap(), ImportResult::UnknownParent); +} + +#[test] +fn imports_blocks_with_changes_tries_config_change() { + // create client with initial 4^2 configuration + let mut client = TestClientBuilder::with_default_backend() + .changes_trie_config(Some(ChangesTrieConfiguration { + digest_interval: 4, + digest_levels: 2, + })).build(); + + // =================================================================== + // blocks 1,2,3,4,5,6,7,8,9,10 are empty + // block 11 changes the key + // block 12 is the L1 digest that covers this change + // blocks 13,14,15,16,17,18,19,20,21,22 are empty + // block 23 changes the configuration to 5^1 AND is skewed digest + // =================================================================== + // blocks 24,25 are changing the key + // block 26 is empty + // block 27 changes the key + // block 28 is the L1 digest (NOT SKEWED!!!) that covers changes AND changes configuration to 3^1 + // =================================================================== + // block 29 is empty + // block 30 changes the key + // block 31 is L1 digest that covers this change + // =================================================================== + (1..11).for_each(|number| { + let block = client.new_block_at(&BlockId::Number(number - 1), Default::default(), false) + .unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, block).unwrap(); + }); + (11..12).for_each(|number| { + let mut block = client.new_block_at(&BlockId::Number(number - 1), Default::default(), false).unwrap(); + block.push_storage_change(vec![42], Some(number.to_le_bytes().to_vec())).unwrap(); + let block = block.build().unwrap().block; + client.import(BlockOrigin::Own, block).unwrap(); + }); + (12..23).for_each(|number| { + let block = client.new_block_at(&BlockId::Number(number - 1), Default::default(), false) + .unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, block).unwrap(); + }); + (23..24).for_each(|number| { + let mut block = client.new_block_at(&BlockId::Number(number - 1), Default::default(), false).unwrap(); + block.push_changes_trie_configuration_update(Some(ChangesTrieConfiguration { + digest_interval: 5, + digest_levels: 1, + })).unwrap(); + let block = block.build().unwrap().block; + client.import(BlockOrigin::Own, block).unwrap(); + }); + (24..26).for_each(|number| { + let mut block = client.new_block_at(&BlockId::Number(number - 1), Default::default(), false).unwrap(); + block.push_storage_change(vec![42], Some(number.to_le_bytes().to_vec())).unwrap(); + let block = block.build().unwrap().block; + client.import(BlockOrigin::Own, block).unwrap(); + }); + (26..27).for_each(|number| { + let block = client.new_block_at(&BlockId::Number(number - 1), Default::default(), false) + .unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, block).unwrap(); + }); + (27..28).for_each(|number| { + let mut block = client.new_block_at(&BlockId::Number(number - 1), Default::default(), false).unwrap(); + block.push_storage_change(vec![42], Some(number.to_le_bytes().to_vec())).unwrap(); + let block = block.build().unwrap().block; + client.import(BlockOrigin::Own, block).unwrap(); + }); + (28..29).for_each(|number| { + let mut block = client.new_block_at(&BlockId::Number(number - 1), Default::default(), false).unwrap(); + block.push_changes_trie_configuration_update(Some(ChangesTrieConfiguration { + digest_interval: 3, + digest_levels: 1, + })).unwrap(); + let block = block.build().unwrap().block; + client.import(BlockOrigin::Own, block).unwrap(); + }); + (29..30).for_each(|number| { + let block = client.new_block_at(&BlockId::Number(number - 1), Default::default(), false) + .unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, block).unwrap(); + }); + (30..31).for_each(|number| { + let mut block = client.new_block_at(&BlockId::Number(number - 1), Default::default(), false).unwrap(); + block.push_storage_change(vec![42], Some(number.to_le_bytes().to_vec())).unwrap(); + let block = block.build().unwrap().block; + client.import(BlockOrigin::Own, block).unwrap(); + }); + (31..32).for_each(|number| { + let block = client.new_block_at(&BlockId::Number(number - 1), Default::default(), false) + .unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, block).unwrap(); + }); + + // now check that configuration cache works + assert_eq!( + client.key_changes(1, BlockId::Number(31), None, &StorageKey(vec![42])).unwrap(), + vec![(30, 0), (27, 0), (25, 0), (24, 0), (11, 0)] + ); +} + +#[test] +fn storage_keys_iter_prefix_and_start_key_works() { + let client = substrate_test_runtime_client::new(); + + let prefix = StorageKey(hex!("3a").to_vec()); + + let res: Vec<_> = client.storage_keys_iter(&BlockId::Number(0), Some(&prefix), None) + .unwrap() + .map(|x| x.0) + .collect(); + assert_eq!(res, [hex!("3a636f6465").to_vec(), hex!("3a686561707061676573").to_vec()]); + + let res: Vec<_> = client.storage_keys_iter(&BlockId::Number(0), Some(&prefix), Some(&StorageKey(hex!("3a636f6465").to_vec()))) + .unwrap() + .map(|x| x.0) + .collect(); + assert_eq!(res, [hex!("3a686561707061676573").to_vec()]); + + let res: Vec<_> = client.storage_keys_iter(&BlockId::Number(0), Some(&prefix), Some(&StorageKey(hex!("3a686561707061676573").to_vec()))) + .unwrap() + .map(|x| x.0) + .collect(); + assert_eq!(res, Vec::>::new()); +} + +#[test] +fn storage_keys_iter_works() { + let client = substrate_test_runtime_client::new(); + + let prefix = StorageKey(hex!("").to_vec()); + + let res: Vec<_> = client.storage_keys_iter(&BlockId::Number(0), Some(&prefix), None) + .unwrap() + .take(2) + .map(|x| x.0) + .collect(); + assert_eq!(res, [hex!("0befda6e1ca4ef40219d588a727f1271").to_vec(), hex!("3a636f6465").to_vec()]); + + let res: Vec<_> = client.storage_keys_iter(&BlockId::Number(0), Some(&prefix), Some(&StorageKey(hex!("3a636f6465").to_vec()))) + .unwrap() + .take(3) + .map(|x| x.0) + .collect(); + assert_eq!(res, [ + hex!("3a686561707061676573").to_vec(), + hex!("6644b9b8bc315888ac8e41a7968dc2b4141a5403c58acdf70b7e8f7e07bf5081").to_vec(), + hex!("79c07e2b1d2e2abfd4855b936617eeff5e0621c4869aa60c02be9adcc98a0d1d").to_vec(), + ]); + + let res: Vec<_> = client.storage_keys_iter(&BlockId::Number(0), Some(&prefix), Some(&StorageKey(hex!("79c07e2b1d2e2abfd4855b936617eeff5e0621c4869aa60c02be9adcc98a0d1d").to_vec()))) + .unwrap() + .take(1) + .map(|x| x.0) + .collect(); + assert_eq!(res, [hex!("cf722c0832b5231d35e29f319ff27389f5032bfc7bfc3ba5ed7839f2042fb99f").to_vec()]); +} + +#[test] +fn cleans_up_closed_notification_sinks_on_block_import() { + use substrate_test_runtime_client::GenesisInit; + + // NOTE: we need to build the client here instead of using the client + // provided by test_runtime_client otherwise we can't access the private + // `import_notification_sinks` and `finality_notification_sinks` fields. + let mut client = + new_in_mem::< + _, + substrate_test_runtime_client::runtime::Block, + _, + substrate_test_runtime_client::runtime::RuntimeApi + >( + substrate_test_runtime_client::new_native_executor(), + &substrate_test_runtime_client::GenesisParameters::default().genesis_storage(), + None, + None, + sp_core::tasks::executor(), + Default::default(), + ) + .unwrap(); + + type TestClient = Client< + in_mem::Backend, + LocalCallExecutor, sc_executor::NativeExecutor>, + substrate_test_runtime_client::runtime::Block, + substrate_test_runtime_client::runtime::RuntimeApi, + >; + + let import_notif1 = client.import_notification_stream(); + let import_notif2 = client.import_notification_stream(); + let finality_notif1 = client.finality_notification_stream(); + let finality_notif2 = client.finality_notification_stream(); + + // for some reason I can't seem to use `ClientBlockImportExt` + let bake_and_import_block = |client: &mut TestClient, origin| { + let block = client + .new_block(Default::default()) + .unwrap() + .build() + .unwrap() + .block; + + let (header, extrinsics) = block.deconstruct(); + let mut import = BlockImportParams::new(origin, header); + import.body = Some(extrinsics); + import.fork_choice = Some(ForkChoiceStrategy::LongestChain); + client.import_block(import, Default::default()).unwrap(); + }; + + // after importing a block we should still have 4 notification sinks + // (2 import + 2 finality) + bake_and_import_block(&mut client, BlockOrigin::Own); + assert_eq!(client.import_notification_sinks().lock().len(), 2); + assert_eq!(client.finality_notification_sinks().lock().len(), 2); + + // if we drop one import notification receiver and one finality + // notification receiver + drop(import_notif2); + drop(finality_notif2); + + // the sinks should be cleaned up after block import + bake_and_import_block(&mut client, BlockOrigin::Own); + assert_eq!(client.import_notification_sinks().lock().len(), 1); + assert_eq!(client.finality_notification_sinks().lock().len(), 1); + + // the same thing should happen if block import happens during initial + // sync + drop(import_notif1); + drop(finality_notif1); + + bake_and_import_block(&mut client, BlockOrigin::NetworkInitialSync); + assert_eq!(client.import_notification_sinks().lock().len(), 0); + assert_eq!(client.finality_notification_sinks().lock().len(), 0); +} + diff --git a/client/service/test/src/lib.rs b/client/service/test/src/lib.rs index d63fd4009ec2e7c31987d019d1eb0dd6d8cb1422..ac95dd11e8b2758841ffd04c21d827d38239185b 100644 --- a/client/service/test/src/lib.rs +++ b/client/service/test/src/lib.rs @@ -1,93 +1,156 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Service integration test utils. use std::iter; -use std::sync::{Arc, Mutex, MutexGuard}; +use std::sync::Arc; use std::net::Ipv4Addr; use std::pin::Pin; use std::time::Duration; -use log::info; +use log::{info, debug}; use futures01::{Future, Stream, Poll}; use futures::{FutureExt as _, TryFutureExt as _}; use tempfile::TempDir; use tokio::{runtime::Runtime, prelude::FutureExt}; use tokio::timer::Interval; use sc_service::{ - AbstractService, + TaskManager, GenericChainSpec, ChainSpecExtension, Configuration, - config::{DatabaseConfig, KeystoreConfig}, + config::{BasePath, DatabaseConfig, KeystoreConfig}, RuntimeGenesis, Role, Error, + TaskExecutor, + client::Client, }; -use sc_network::{multiaddr, Multiaddr, NetworkStateInfo}; -use sc_network::config::{NetworkConfiguration, TransportConfig, NodeKeyConfig, Secret, NonReservedPeerMode}; +use sp_blockchain::HeaderBackend; +use sc_network::{multiaddr, Multiaddr}; +use sc_network::config::{NetworkConfiguration, TransportConfig}; use sp_runtime::{generic::BlockId, traits::Block as BlockT}; use sp_transaction_pool::TransactionPool; +use sc_client_api::{Backend, CallExecutor}; +use parking_lot::Mutex; + +#[cfg(test)] +mod client; /// Maximum duration of single wait call. const MAX_WAIT_TIME: Duration = Duration::from_secs(60 * 3); struct TestNet { runtime: Runtime, - authority_nodes: Vec<(usize, SyncService, U, Multiaddr)>, - full_nodes: Vec<(usize, SyncService, U, Multiaddr)>, - light_nodes: Vec<(usize, SyncService, Multiaddr)>, + authority_nodes: Vec<(usize, F, U, Multiaddr)>, + full_nodes: Vec<(usize, F, U, Multiaddr)>, + light_nodes: Vec<(usize, L, Multiaddr)>, chain_spec: GenericChainSpec, base_port: u16, nodes: usize, } -/// Wraps around an `Arc` and implements `Future`. -pub struct SyncService(Arc>); +pub trait TestNetNode: Clone + Future + Send + 'static { + type Block: BlockT; + type Backend: Backend; + type Executor: CallExecutor + Send + Sync; + type RuntimeApi: Send + Sync; + type TransactionPool: TransactionPool; -impl SyncService { - pub fn get(&self) -> MutexGuard { - self.0.lock().unwrap() - } + fn client(&self) -> Arc>; + fn transaction_pool(&self) -> Arc; + fn network(&self) -> Arc::Hash>>; } -impl Clone for SyncService { - fn clone(&self) -> Self { - Self(self.0.clone()) +pub struct TestNetComponents { + task_manager: Arc>, + client: Arc>, + transaction_pool: Arc, + network: Arc::Hash>>, +} + +impl +TestNetComponents { + pub fn new( + task_manager: TaskManager, + client: Arc>, + network: Arc::Hash>>, + transaction_pool: Arc, + ) -> Self { + Self { + client, transaction_pool, network, + task_manager: Arc::new(Mutex::new(task_manager)), + } } } -impl From for SyncService { - fn from(service: T) -> Self { - SyncService(Arc::new(Mutex::new(service))) + +impl Clone for +TestNetComponents { + fn clone(&self) -> Self { + Self { + task_manager: self.task_manager.clone(), + client: self.client.clone(), + transaction_pool: self.transaction_pool.clone(), + network: self.network.clone(), + } } } -impl> + Unpin> Future for SyncService { +impl Future for + TestNetComponents +{ type Item = (); type Error = sc_service::Error; fn poll(&mut self) -> Poll { - let mut f = self.0.lock().unwrap(); - futures::compat::Compat::new(&mut *f).poll() + futures::compat::Compat::new(&mut self.task_manager.lock().future()).poll() + } +} + +impl TestNetNode for +TestNetComponents + where + TBl: BlockT, + TBackend: sc_client_api::Backend + Send + Sync + 'static, + TExec: CallExecutor + Send + Sync + 'static, + TRtApi: Send + Sync + 'static, + TExPool: TransactionPool + Send + Sync + 'static, +{ + type Block = TBl; + type Backend = TBackend; + type Executor = TExec; + type RuntimeApi = TRtApi; + type TransactionPool = TExPool; + + fn client(&self) -> Arc> { + self.client.clone() + } + fn transaction_pool(&self) -> Arc { + self.transaction_pool.clone() + } + fn network(&self) -> Arc::Hash>> { + self.network.clone() } } impl TestNet -where F: Send + 'static, L: Send +'static, U: Clone + Send + 'static +where F: Clone + Send + 'static, L: Clone + Send +'static, U: Clone + Send + 'static { pub fn run_until_all_full( &mut self, @@ -95,8 +158,8 @@ where F: Send + 'static, L: Send +'static, U: Clone + Send + 'static light_predicate: LP, ) where - FP: Send + Fn(usize, &SyncService) -> bool + 'static, - LP: Send + Fn(usize, &SyncService) -> bool + 'static, + FP: Send + Fn(usize, &F) -> bool + 'static, + LP: Send + Fn(usize, &L) -> bool + 'static, { let full_nodes = self.full_nodes.clone(); let light_nodes = self.light_nodes.clone(); @@ -135,7 +198,7 @@ fn node_config, role: Role, - task_executor: Arc + Send>>) + Send + Sync>, + task_executor: TaskExecutor, key_seed: Option, base_port: u16, root: &TempDir, @@ -143,68 +206,60 @@ fn node_config TestNet where - F: AbstractService, - L: AbstractService, + F: TestNetNode, + L: TestNetNode, E: ChainSpecExtension + Clone + 'static + Send, G: RuntimeGenesis + 'static, { @@ -256,58 +313,66 @@ impl TestNet where authorities: impl Iterator Result<(F, U), Error>)> ) { let executor = self.runtime.executor(); + let task_executor: TaskExecutor = { + let executor = executor.clone(); + (move |fut: Pin + Send>>, _| { + executor.spawn(fut.unit_error().compat()); + }).into() + }; for (key, authority) in authorities { - let task_executor = { - let executor = executor.clone(); - Arc::new(move |fut: Pin + Send>>| executor.spawn(fut.unit_error().compat())) - }; let node_config = node_config( self.nodes, &self.chain_spec, Role::Authority { sentry_nodes: Vec::new() }, - task_executor, + task_executor.clone(), Some(key), self.base_port, &temp, ); let addr = node_config.network.listen_addresses.iter().next().unwrap().clone(); 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())); + let addr = addr.with(multiaddr::Protocol::P2p(service.network().local_peer_id().clone().into())); self.authority_nodes.push((self.nodes, service, user_data, addr)); self.nodes += 1; } for full in full { - let task_executor = { - let executor = executor.clone(); - Arc::new(move |fut: Pin + Send>>| executor.spawn(fut.unit_error().compat())) - }; - let node_config = node_config(self.nodes, &self.chain_spec, Role::Full, task_executor, None, self.base_port, &temp); + let node_config = node_config( + self.nodes, + &self.chain_spec, + Role::Full, + task_executor.clone(), + None, + self.base_port, + &temp, + ); let addr = node_config.network.listen_addresses.iter().next().unwrap().clone(); 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())); + let addr = addr.with(multiaddr::Protocol::P2p(service.network().local_peer_id().clone().into())); self.full_nodes.push((self.nodes, service, user_data, addr)); self.nodes += 1; } for light in light { - let task_executor = { - let executor = executor.clone(); - Arc::new(move |fut: Pin + Send>>| executor.spawn(fut.unit_error().compat())) - }; - let node_config = node_config(self.nodes, &self.chain_spec, Role::Light, task_executor, None, self.base_port, &temp); + let node_config = node_config( + self.nodes, + &self.chain_spec, + Role::Light, + task_executor.clone(), + None, + self.base_port, + &temp, + ); let addr = node_config.network.listen_addresses.iter().next().unwrap().clone(); - let service = SyncService::from(light(node_config).expect("Error creating test node service")); + let service = 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())); + let addr = addr.with(multiaddr::Protocol::P2p(service.network().local_peer_id().clone().into())); self.light_nodes.push((self.nodes, service, addr)); self.nodes += 1; } @@ -326,9 +391,9 @@ pub fn connectivity( E: ChainSpecExtension + Clone + 'static + Send, G: RuntimeGenesis + 'static, Fb: Fn(Configuration) -> Result, - F: AbstractService, + F: TestNetNode, Lb: Fn(Configuration) -> Result, - L: AbstractService, + L: TestNetNode, { const NUM_FULL_NODES: usize = 5; const NUM_LIGHT_NODES: usize = 5; @@ -352,19 +417,25 @@ pub fn connectivity( info!("Checking star topology"); 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()) + service.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()) + service.network().add_reserved_peer(first_address.to_string()) .expect("Error adding reserved peer"); } network.run_until_all_full( - move |_index, service| service.get().network().num_connected() - == expected_full_connections, - move |_index, service| service.get().network().num_connected() - == expected_light_connections, + move |_index, service| { + let connected = service.network().num_connected(); + debug!("Got {}/{} full connections...", connected, expected_full_connections); + connected == expected_full_connections + }, + move |_index, service| { + let connected = service.network().num_connected(); + debug!("Got {}/{} light connections...", connected, expected_light_connections); + connected == expected_light_connections + }, ); network.runtime @@ -393,24 +464,30 @@ pub fn connectivity( 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()) + service.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()) + service.network().add_reserved_peer(address.to_string()) .expect("Error adding reserved peer"); address = node_id.clone(); } } network.run_until_all_full( - move |_index, service| service.get().network().num_connected() - == expected_full_connections, - move |_index, service| service.get().network().num_connected() - == expected_light_connections, + move |_index, service| { + let connected = service.network().num_connected(); + debug!("Got {}/{} full connections...", connected, expected_full_connections); + connected == expected_full_connections + }, + move |_index, service| { + let connected = service.network().num_connected(); + debug!("Got {}/{} light connections...", connected, expected_light_connections); + connected == expected_light_connections + }, ); } temp.close().expect("Error removing temp dir"); @@ -425,9 +502,9 @@ pub fn sync( mut extrinsic_factory: ExF ) where Fb: Fn(Configuration) -> Result<(F, U), Error>, - F: AbstractService, + F: TestNetNode, Lb: Fn(Configuration) -> Result, - L: AbstractService, + L: TestNetNode, B: FnMut(&F, &mut U), ExF: FnMut(&F, &U) -> ::Extrinsic, U: Clone + Send + 'static, @@ -457,38 +534,41 @@ pub fn sync( info!("Generating #{}", i + 1); } - make_block_and_import(&first_service.get(), first_user_data); + make_block_and_import(&first_service, first_user_data); } + network.full_nodes[0].1.network().update_chain(); network.full_nodes[0].3.clone() }; info!("Running sync"); for (_, service, _, _) in network.full_nodes.iter().skip(1) { - service.get().network().add_reserved_peer(first_address.to_string()).expect("Error adding reserved peer"); + service.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.network().add_reserved_peer(first_address.to_string()) + .expect("Error adding reserved peer"); } network.run_until_all_full( |_index, service| - service.get().client().chain_info().best_number == (NUM_BLOCKS as u32).into(), + service.client().info().best_number == (NUM_BLOCKS as u32).into(), |_index, service| - service.get().client().chain_info().best_number == (NUM_BLOCKS as u32).into(), + service.client().info().best_number == (NUM_BLOCKS as u32).into(), ); 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().chain_info().best_number); - let extrinsic = extrinsic_factory(&first_service.get(), first_user_data); + let best_block = BlockId::number(first_service.client().info().best_number); + let extrinsic = extrinsic_factory(&first_service, first_user_data); let source = sp_transaction_pool::TransactionSource::External; futures::executor::block_on( - first_service.get().transaction_pool().submit_one(&best_block, source, extrinsic) + first_service.transaction_pool().submit_one(&best_block, source, extrinsic) ).expect("failed to submit extrinsic"); network.run_until_all_full( - |_index, service| service.get().transaction_pool().ready().count() == 1, + |_index, service| service.transaction_pool().ready().count() == 1, |_index, _service| true, ); } @@ -500,9 +580,9 @@ pub fn consensus( authorities: impl IntoIterator ) where Fb: Fn(Configuration) -> Result, - F: AbstractService, + F: TestNetNode, Lb: Fn(Configuration) -> Result, - L: AbstractService, + L: TestNetNode, E: ChainSpecExtension + Clone + 'static + Send, G: RuntimeGenesis + 'static, { @@ -522,19 +602,22 @@ pub fn consensus( info!("Checking consensus"); 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"); + service.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.network().add_reserved_peer(first_address.to_string()) + .expect("Error adding reserved peer"); } for (_, service, _, _) in network.authority_nodes.iter().skip(1) { - service.get().network().add_reserved_peer(first_address.to_string()).expect("Error adding reserved peer"); + service.network().add_reserved_peer(first_address.to_string()) + .expect("Error adding reserved peer"); } network.run_until_all_full( |_index, service| - service.get().client().chain_info().finalized_number >= (NUM_BLOCKS as u32 / 2).into(), + service.client().info().finalized_number >= (NUM_BLOCKS as u32 / 2).into(), |_index, service| - service.get().client().chain_info().best_number >= (NUM_BLOCKS as u32 / 2).into(), + service.client().info().best_number >= (NUM_BLOCKS as u32 / 2).into(), ); info!("Adding more peers"); @@ -547,15 +630,17 @@ pub fn consensus( (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"); + service.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.network().add_reserved_peer(first_address.to_string()) + .expect("Error adding reserved peer"); } network.run_until_all_full( |_index, service| - service.get().client().chain_info().finalized_number >= (NUM_BLOCKS as u32).into(), + service.client().info().finalized_number >= (NUM_BLOCKS as u32).into(), |_index, service| - service.get().client().chain_info().best_number >= (NUM_BLOCKS as u32).into(), + service.client().info().best_number >= (NUM_BLOCKS as u32).into(), ); } diff --git a/client/src/client.rs b/client/src/client.rs deleted file mode 100644 index 13d654a7c2ab66beb48125edb2fb9af925fa6c0e..0000000000000000000000000000000000000000 --- a/client/src/client.rs +++ /dev/null @@ -1,3550 +0,0 @@ -// Copyright 2017-2020 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 Client - -use std::{ - marker::PhantomData, collections::{HashSet, BTreeMap, HashMap}, sync::Arc, panic::UnwindSafe, - result, -}; -use log::{info, trace, warn}; -use parking_lot::{Mutex, RwLock}; -use codec::{Encode, Decode}; -use hash_db::Prefix; -use sp_core::{ - ChangesTrieConfiguration, convert_hash, traits::CodeExecutor, - NativeOrEncoded, storage::{StorageKey, StorageData, well_known_keys, ChildInfo}, -}; -use sc_telemetry::{telemetry, SUBSTRATE_INFO}; -use sp_runtime::{ - Justification, BuildStorage, - generic::{BlockId, SignedBlock, DigestItem}, - traits::{ - Block as BlockT, Header as HeaderT, Zero, NumberFor, HashFor, SaturatedConversion, One, - DigestFor, - }, -}; -use sp_state_machine::{ - DBValue, Backend as StateBackend, ChangesTrieAnchorBlockId, - prove_read, prove_child_read, ChangesTrieRootsStorage, ChangesTrieStorage, - ChangesTrieConfigurationRange, key_changes, key_changes_proof, -}; -use sc_executor::{RuntimeVersion, RuntimeInfo}; -use sp_consensus::{ - Error as ConsensusError, BlockStatus, BlockImportParams, BlockCheckParams, ImportResult, - BlockOrigin, ForkChoiceStrategy, SelectChain, RecordProof, -}; -use sp_blockchain::{self as blockchain, - Backend as ChainBackend, - HeaderBackend as ChainHeaderBackend, ProvideCache, Cache, - well_known_cache_keys::Id as CacheKeyId, - HeaderMetadata, CachedHeaderMetadata, -}; -use sp_trie::StorageProof; - -use sp_api::{ - CallApiAt, ConstructRuntimeApi, Core as CoreApi, ApiExt, ApiRef, ProvideRuntimeApi, - CallApiAtParams, -}; -use sc_block_builder::{BlockBuilderApi, BlockBuilderProvider}; - -pub use sc_client_api::{ - backend::{ - self, BlockImportOperation, PrunableStateChangesTrieStorage, - ClientImportOperation, Finalizer, ImportSummary, NewBlockState, - changes_tries_state_at_block, StorageProvider, - LockImportRun, - }, - client::{ - ImportNotifications, FinalityNotification, FinalityNotifications, BlockImportNotification, - ClientInfo, BlockchainEvents, BlockBackend, ProvideUncles, BadBlocks, ForkBlocks, - BlockOf, - }, - execution_extensions::{ExecutionExtensions, ExecutionStrategies}, - notifications::{StorageNotifications, StorageEventStream}, - CallExecutor, ExecutorProvider, ProofProvider, CloneableSpawn, -}; -use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedSender}; -use sp_blockchain::Error; -use prometheus_endpoint::Registry; - -use crate::{ - call_executor::LocalCallExecutor, - light::{call_executor::prove_execution, fetcher::ChangesProof}, - in_mem, genesis, cht, block_rules::{BlockRules, LookupResult as BlockLookupResult}, -}; -use crate::client::backend::KeyIterator; - -/// Substrate Client -pub struct Client where Block: BlockT { - backend: Arc, - executor: E, - storage_notifications: Mutex>, - import_notification_sinks: Mutex>>>, - finality_notification_sinks: Mutex>>>, - // holds the block hash currently being imported. TODO: replace this with block queue - importing_block: RwLock>, - block_rules: BlockRules, - execution_extensions: ExecutionExtensions, - _phantom: PhantomData, -} - -// used in importing a block, where additional changes are made after the runtime -// executed. -enum PrePostHeader { - // they are the same: no post-runtime digest items. - Same(H), - // different headers (pre, post). - Different(H, H), -} - -impl PrePostHeader { - // get a reference to the "post-header" -- the header as it should be after all changes are applied. - fn post(&self) -> &H { - match *self { - PrePostHeader::Same(ref h) => h, - PrePostHeader::Different(_, ref h) => h, - } - } - - // convert to the "post-header" -- the header as it should be after all changes are applied. - fn into_post(self) -> H { - match self { - PrePostHeader::Same(h) => h, - PrePostHeader::Different(_, h) => h, - } - } -} - -/// Create an instance of in-memory client. -pub fn new_in_mem( - executor: E, - genesis_storage: &S, - keystore: Option, - prometheus_registry: Option, - spawn_handle: Box, -) -> sp_blockchain::Result, - LocalCallExecutor, E>, - Block, - RA ->> where - E: CodeExecutor + RuntimeInfo, - S: BuildStorage, - Block: BlockT, -{ - new_with_backend(Arc::new(in_mem::Backend::new()), executor, genesis_storage, keystore, spawn_handle, prometheus_registry) -} - -/// Create a client with the explicitly provided backend. -/// This is useful for testing backend implementations. -pub fn new_with_backend( - backend: Arc, - executor: E, - build_genesis_storage: &S, - keystore: Option, - spawn_handle: Box, - prometheus_registry: Option, -) -> sp_blockchain::Result, Block, RA>> - where - E: CodeExecutor + RuntimeInfo, - S: BuildStorage, - Block: BlockT, - B: backend::LocalBackend + 'static, -{ - let call_executor = LocalCallExecutor::new(backend.clone(), executor, spawn_handle); - let extensions = ExecutionExtensions::new(Default::default(), keystore); - Client::new( - backend, - call_executor, - build_genesis_storage, - Default::default(), - Default::default(), - extensions, - prometheus_registry, - ) -} - -impl BlockOf for Client where - B: backend::Backend, - E: CallExecutor, - Block: BlockT, -{ - type Type = Block; -} - -impl LockImportRun for Client - where - B: backend::Backend, - E: CallExecutor, - Block: BlockT, -{ - fn lock_import_and_run(&self, f: F) -> Result - where - F: FnOnce(&mut ClientImportOperation) -> Result, - Err: From, - { - let inner = || { - let _import_lock = self.backend.get_import_lock().write(); - - let mut op = ClientImportOperation { - op: self.backend.begin_operation()?, - notify_imported: None, - notify_finalized: Vec::new(), - }; - - let r = f(&mut op)?; - - let ClientImportOperation { op, notify_imported, notify_finalized } = op; - self.backend.commit_operation(op)?; - - self.notify_finalized(notify_finalized)?; - self.notify_imported(notify_imported)?; - - Ok(r) - }; - - let result = inner(); - *self.importing_block.write() = None; - - result - } -} - -impl LockImportRun for &Client - where - Block: BlockT, - B: backend::Backend, - E: CallExecutor, -{ - fn lock_import_and_run(&self, f: F) -> Result - where - F: FnOnce(&mut ClientImportOperation) -> Result, - Err: From, - { - (**self).lock_import_and_run(f) - } -} - -impl Client where - B: backend::Backend, - E: CallExecutor, - Block: BlockT, -{ - /// Creates new Substrate Client with given blockchain and code executor. - pub fn new( - backend: Arc, - executor: E, - build_genesis_storage: &dyn BuildStorage, - fork_blocks: ForkBlocks, - bad_blocks: BadBlocks, - execution_extensions: ExecutionExtensions, - _prometheus_registry: Option, - ) -> sp_blockchain::Result { - if backend.blockchain().header(BlockId::Number(Zero::zero()))?.is_none() { - let genesis_storage = build_genesis_storage.build_storage()?; - let mut op = backend.begin_operation()?; - backend.begin_state_operation(&mut op, BlockId::Hash(Default::default()))?; - let state_root = op.reset_storage(genesis_storage)?; - let genesis_block = genesis::construct_genesis_block::(state_root.into()); - info!("🔨 Initializing Genesis block/state (state: {}, header-hash: {})", - genesis_block.header().state_root(), - genesis_block.header().hash() - ); - op.set_block_data( - genesis_block.deconstruct().0, - Some(vec![]), - None, - NewBlockState::Final - )?; - backend.commit_operation(op)?; - } - - Ok(Client { - backend, - executor, - storage_notifications: Default::default(), - import_notification_sinks: Default::default(), - finality_notification_sinks: Default::default(), - importing_block: Default::default(), - block_rules: BlockRules::new(fork_blocks, bad_blocks), - execution_extensions, - _phantom: Default::default(), - }) - } - - /// Get a reference to the state at a given block. - pub fn state_at(&self, block: &BlockId) -> sp_blockchain::Result { - self.backend.state_at(*block) - } - - /// Get the code at a given block. - pub fn code_at(&self, id: &BlockId) -> sp_blockchain::Result> { - Ok(StorageProvider::storage(self, id, &StorageKey(well_known_keys::CODE.to_vec()))? - .expect("None is returned if there's no value stored for the given key;\ - ':code' key is always defined; qed").0) - } - - /// Get the RuntimeVersion at a given block. - pub fn runtime_version_at(&self, id: &BlockId) -> sp_blockchain::Result { - self.executor.runtime_version(id) - } - - /// Get block hash by number. - pub fn block_hash(&self, - block_number: <::Header as HeaderT>::Number - ) -> sp_blockchain::Result> { - self.backend.blockchain().hash(block_number) - } - - /// Reads given header and generates CHT-based header proof for CHT of given size. - pub fn header_proof_with_cht_size( - &self, - id: &BlockId, - cht_size: NumberFor, - ) -> sp_blockchain::Result<(Block::Header, StorageProof)> { - let proof_error = || sp_blockchain::Error::Backend(format!("Failed to generate header proof for {:?}", id)); - let header = self.backend.blockchain().expect_header(*id)?; - let block_num = *header.number(); - let cht_num = cht::block_to_cht_number(cht_size, block_num).ok_or_else(proof_error)?; - let cht_start = cht::start_number(cht_size, cht_num); - let mut current_num = cht_start; - let cht_range = ::std::iter::from_fn(|| { - let old_current_num = current_num; - current_num = current_num + One::one(); - Some(old_current_num) - }); - let headers = cht_range.map(|num| self.block_hash(num)); - let proof = cht::build_proof::, _, _>( - cht_size, - cht_num, - std::iter::once(block_num), - headers, - )?; - Ok((header, proof)) - } - - /// Does the same work as `key_changes_proof`, but assumes that CHTs are of passed size. - pub fn key_changes_proof_with_cht_size( - &self, - first: Block::Hash, - last: Block::Hash, - min: Block::Hash, - max: Block::Hash, - storage_key: Option<&StorageKey>, - key: &StorageKey, - cht_size: NumberFor, - ) -> sp_blockchain::Result> { - struct AccessedRootsRecorder<'a, Block: BlockT> { - storage: &'a dyn ChangesTrieStorage, NumberFor>, - min: NumberFor, - required_roots_proofs: Mutex, Block::Hash>>, - }; - - impl<'a, Block: BlockT> ChangesTrieRootsStorage, NumberFor> for - AccessedRootsRecorder<'a, Block> - { - fn build_anchor(&self, hash: Block::Hash) - -> Result>, String> - { - self.storage.build_anchor(hash) - } - - fn root( - &self, - anchor: &ChangesTrieAnchorBlockId>, - block: NumberFor, - ) -> Result, String> { - let root = self.storage.root(anchor, block)?; - if block < self.min { - if let Some(ref root) = root { - self.required_roots_proofs.lock().insert( - block, - root.clone() - ); - } - } - Ok(root) - } - } - - impl<'a, Block: BlockT> ChangesTrieStorage, NumberFor> for - AccessedRootsRecorder<'a, Block> - { - fn as_roots_storage(&self) - -> &dyn sp_state_machine::ChangesTrieRootsStorage, NumberFor> - { - self - } - - fn with_cached_changed_keys( - &self, - root: &Block::Hash, - functor: &mut dyn FnMut(&HashMap>, HashSet>>), - ) -> bool { - self.storage.with_cached_changed_keys(root, functor) - } - - fn get(&self, key: &Block::Hash, prefix: Prefix) -> Result, String> { - self.storage.get(key, prefix) - } - } - - let first_number = self.backend.blockchain() - .expect_block_number_from_id(&BlockId::Hash(first))?; - let (storage, configs) = self.require_changes_trie(first_number, last, true)?; - let min_number = self.backend.blockchain().expect_block_number_from_id(&BlockId::Hash(min))?; - - let recording_storage = AccessedRootsRecorder:: { - storage: storage.storage(), - min: min_number, - required_roots_proofs: Mutex::new(BTreeMap::new()), - }; - - let max_number = std::cmp::min( - self.backend.blockchain().info().best_number, - self.backend.blockchain().expect_block_number_from_id(&BlockId::Hash(max))?, - ); - - // fetch key changes proof - let mut proof = Vec::new(); - for (config_zero, config_end, config) in configs { - let last_number = self.backend.blockchain() - .expect_block_number_from_id(&BlockId::Hash(last))?; - let config_range = ChangesTrieConfigurationRange { - config: &config, - zero: config_zero, - end: config_end.map(|(config_end_number, _)| config_end_number), - }; - let proof_range = key_changes_proof::, _>( - config_range, - &recording_storage, - first_number, - &ChangesTrieAnchorBlockId { - hash: convert_hash(&last), - number: last_number, - }, - max_number, - storage_key.as_ref().map(|x| &x.0[..]), - &key.0, - ) - .map_err(|err| sp_blockchain::Error::ChangesTrieAccessFailed(err))?; - proof.extend(proof_range); - } - - // now gather proofs for all changes tries roots that were touched during key_changes_proof - // execution AND are unknown (i.e. replaced with CHT) to the requester - let roots = recording_storage.required_roots_proofs.into_inner(); - let roots_proof = self.changes_trie_roots_proof(cht_size, roots.keys().cloned())?; - - Ok(ChangesProof { - max_block: max_number, - proof, - roots: roots.into_iter().map(|(n, h)| (n, convert_hash(&h))).collect(), - roots_proof, - }) - } - - /// Generate CHT-based proof for roots of changes tries at given blocks. - fn changes_trie_roots_proof>>( - &self, - cht_size: NumberFor, - blocks: I - ) -> sp_blockchain::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 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)?; - proofs.push(cht_proof); - Ok(()) - }, ())?; - - Ok(StorageProof::merge(proofs)) - } - - /// Generates CHT-based proof for roots of changes tries at given blocks (that are part of single CHT). - fn changes_trie_roots_proof_at_cht( - &self, - cht_size: NumberFor, - cht_num: NumberFor, - blocks: Vec> - ) -> sp_blockchain::Result { - let cht_start = cht::start_number(cht_size, cht_num); - let mut current_num = cht_start; - let cht_range = ::std::iter::from_fn(|| { - let old_current_num = current_num; - current_num = current_num + One::one(); - Some(old_current_num) - }); - let roots = cht_range - .map(|num| self.header(&BlockId::Number(num)) - .map(|block| - block.and_then(|block| block.digest().log(DigestItem::as_changes_trie_root).cloned())) - ); - let proof = cht::build_proof::, _, _>( - cht_size, - cht_num, - blocks, - roots, - )?; - Ok(proof) - } - - /// Returns changes trie storage and all configurations that have been active in the range [first; last]. - /// - /// Configurations are returned in descending order (and obviously never overlap). - /// If fail_if_disabled is false, returns maximal consequent configurations ranges, starting from last and - /// stopping on either first, or when CT have been disabled. - /// If fail_if_disabled is true, fails when there's a subrange where CT have been disabled - /// inside first..last blocks range. - fn require_changes_trie( - &self, - first: NumberFor, - last: Block::Hash, - fail_if_disabled: bool, - ) -> sp_blockchain::Result<( - &dyn PrunableStateChangesTrieStorage, - Vec<(NumberFor, Option<(NumberFor, Block::Hash)>, ChangesTrieConfiguration)>, - )> { - let storage = match self.backend.changes_trie_storage() { - Some(storage) => storage, - None => return Err(sp_blockchain::Error::ChangesTriesNotSupported), - }; - - let mut configs = Vec::with_capacity(1); - let mut current = last; - loop { - let config_range = storage.configuration_at(&BlockId::Hash(current))?; - match config_range.config { - Some(config) => configs.push((config_range.zero.0, config_range.end, config)), - None if !fail_if_disabled => return Ok((storage, configs)), - None => return Err(sp_blockchain::Error::ChangesTriesNotSupported), - } - - if config_range.zero.0 < first { - break; - } - - current = *self.backend.blockchain().expect_header(BlockId::Hash(config_range.zero.1))?.parent_hash(); - } - - Ok((storage, configs)) - } - - /// Apply a checked and validated block to an operation. If a justification is provided - /// then `finalized` *must* be true. - fn apply_block( - &self, - operation: &mut ClientImportOperation, - import_block: BlockImportParams>, - new_cache: HashMap>, - ) -> sp_blockchain::Result where - Self: ProvideRuntimeApi, - >::Api: CoreApi + - ApiExt, - { - let BlockImportParams { - origin, - header, - justification, - post_digests, - body, - storage_changes, - finalized, - auxiliary, - fork_choice, - intermediates, - import_existing, - .. - } = import_block; - - assert!(justification.is_some() && finalized || justification.is_none()); - - if !intermediates.is_empty() { - return Err(Error::IncompletePipeline) - } - - let fork_choice = fork_choice.ok_or(Error::IncompletePipeline)?; - - let import_headers = if post_digests.is_empty() { - PrePostHeader::Same(header) - } else { - let mut post_header = header.clone(); - for item in post_digests { - post_header.digest_mut().push(item); - } - PrePostHeader::Different(header, post_header) - }; - - let hash = import_headers.post().hash(); - let height = (*import_headers.post().number()).saturated_into::(); - - *self.importing_block.write() = Some(hash); - - let result = self.execute_and_import_block( - operation, - origin, - hash, - import_headers, - justification, - body, - storage_changes, - new_cache, - finalized, - auxiliary, - fork_choice, - import_existing, - ); - - 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 - } - - fn execute_and_import_block( - &self, - operation: &mut ClientImportOperation, - origin: BlockOrigin, - hash: Block::Hash, - import_headers: PrePostHeader, - justification: Option, - body: Option>, - storage_changes: Option, Block>>, - new_cache: HashMap>, - finalized: bool, - aux: Vec<(Vec, Option>)>, - fork_choice: ForkChoiceStrategy, - import_existing: bool, - ) -> sp_blockchain::Result where - Self: ProvideRuntimeApi, - >::Api: CoreApi + - ApiExt, - { - let parent_hash = import_headers.post().parent_hash().clone(); - let status = self.backend.blockchain().status(BlockId::Hash(hash))?; - match (import_existing, status) { - (false, blockchain::BlockStatus::InChain) => return Ok(ImportResult::AlreadyInChain), - (false, blockchain::BlockStatus::Unknown) => {}, - (true, blockchain::BlockStatus::InChain) => {}, - (true, blockchain::BlockStatus::Unknown) => - return Err(Error::UnknownBlock(format!("{:?}", hash))), - } - - 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(sp_blockchain::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 - // and get a new chain head. - let make_notifications = match origin { - BlockOrigin::NetworkBroadcast | BlockOrigin::Own | BlockOrigin::ConsensusBroadcast => true, - BlockOrigin::Genesis | BlockOrigin::NetworkInitialSync | BlockOrigin::File => false, - }; - - let storage_changes = match storage_changes { - Some(storage_changes) => { - self.backend.begin_state_operation(&mut operation.op, BlockId::Hash(parent_hash))?; - - // 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, - info.best_hash, - make_notifications, - )?; - } - - operation.op.update_cache(new_cache); - - let (main_sc, child_sc, tx, _, changes_trie_tx) = storage_changes.into_inner(); - - operation.op.update_db_storage(tx)?; - operation.op.update_storage(main_sc.clone(), child_sc.clone())?; - - if let Some(changes_trie_transaction) = changes_trie_tx { - operation.op.update_changes_trie(changes_trie_transaction)?; - } - - Some((main_sc, child_sc)) - }, - None => None, - }; - - let is_new_best = finalized || match fork_choice { - ForkChoiceStrategy::LongestChain => import_headers.post().number() > &info.best_number, - ForkChoiceStrategy::Custom(v) => v, - }; - - let leaf_state = if finalized { - NewBlockState::Final - } else if is_new_best { - NewBlockState::Best - } else { - NewBlockState::Normal - }; - - let retracted = if is_new_best { - let route_from_best = sp_blockchain::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( - import_headers.post().clone(), - body, - justification, - leaf_state, - )?; - - operation.op.insert_aux(aux)?; - - if make_notifications { - if finalized { - operation.notify_finalized.push(hash); - } - - operation.notify_imported = Some(ImportSummary { - hash, - origin, - header: import_headers.into_post(), - is_new_best, - storage_changes, - retracted, - }) - } - - Ok(ImportResult::imported(is_new_best)) - } - - /// Prepares the storage changes for a block. - /// - /// It checks if the state should be enacted and if the `import_block` maybe already provides - /// the required storage changes. If the state should be enacted and the storage changes are not - /// provided, the block is re-executed to get the storage changes. - fn prepare_block_storage_changes( - &self, - import_block: &mut BlockImportParams>, - ) -> sp_blockchain::Result> - where - Self: ProvideRuntimeApi, - >::Api: CoreApi + - ApiExt, - { - let parent_hash = import_block.header.parent_hash(); - let at = BlockId::Hash(*parent_hash); - let enact_state = match self.block_status(&at)? { - BlockStatus::Unknown => return Ok(Some(ImportResult::UnknownParent)), - BlockStatus::InChainWithState | BlockStatus::Queued => true, - BlockStatus::InChainPruned if import_block.allow_missing_state => false, - BlockStatus::InChainPruned => return Ok(Some(ImportResult::MissingState)), - BlockStatus::KnownBad => return Ok(Some(ImportResult::KnownBad)), - }; - - match (enact_state, &mut import_block.storage_changes, &mut import_block.body) { - // We have storage changes and should enact the state, so we don't need to do anything - // here - (true, Some(_), _) => {}, - // We should enact state, but don't have any storage changes, so we need to execute the - // block. - (true, ref mut storage_changes @ None, Some(ref body)) => { - let runtime_api = self.runtime_api(); - - runtime_api.execute_block( - &at, - Block::new(import_block.header.clone(), body.clone()), - )?; - - let state = self.backend.state_at(at)?; - let changes_trie_state = changes_tries_state_at_block( - &at, - self.backend.changes_trie_storage(), - )?; - - let gen_storage_changes = runtime_api.into_storage_changes( - &state, - changes_trie_state.as_ref(), - *parent_hash, - )?; - - if import_block.header.state_root() - != &gen_storage_changes.transaction_storage_root - { - return Err(Error::InvalidStateRoot) - } else { - **storage_changes = Some(gen_storage_changes); - } - }, - // No block body, no storage changes - (true, None, None) => {}, - // We should not enact the state, so we set the storage changes to `None`. - (false, changes, _) => { - changes.take(); - } - }; - - Ok(None) - } - - fn apply_finality_with_block_hash( - &self, - operation: &mut ClientImportOperation, - block: Block::Hash, - justification: Option, - best_block: Block::Hash, - notify: bool, - ) -> sp_blockchain::Result<()> { - // find tree route from last finalized to given block. - let last_finalized = self.backend.blockchain().last_finalized()?; - - if block == last_finalized { - warn!("Possible safety violation: attempted to re-finalize last finalized block {:?} ", last_finalized); - return Ok(()); - } - - let route_from_finalized = sp_blockchain::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 \ - same chain as last finalized {:?}", retracted, last_finalized); - - return Err(sp_blockchain::Error::NotInFinalizedChain); - } - - let route_from_best = sp_blockchain::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 inaccurate since we might have a "better" block - // further along this chain, but since best chain selection logic is - // plugable we cannot make a better choice here. usages that need - // an accurate "best" block need to go through `SelectChain` - // instead. - operation.op.mark_head(BlockId::Hash(block))?; - } - - let enacted = route_from_finalized.enacted(); - assert!(enacted.len() > 0); - for finalize_new in &enacted[..enacted.len() - 1] { - operation.op.mark_finalized(BlockId::Hash(finalize_new.hash), None)?; - } - - assert_eq!(enacted.last().map(|e| e.hash), Some(block)); - operation.op.mark_finalized(BlockId::Hash(block), justification)?; - - if notify { - // sometimes when syncing, tons of blocks can be finalized at once. - // we'll send notifications spuriously in that case. - const MAX_TO_NOTIFY: usize = 256; - let enacted = route_from_finalized.enacted(); - let start = enacted.len() - ::std::cmp::min(enacted.len(), MAX_TO_NOTIFY); - for finalized in &enacted[start..] { - operation.notify_finalized.push(finalized.hash); - } - } - - Ok(()) - } - - fn notify_finalized( - &self, - notify_finalized: Vec, - ) -> sp_blockchain::Result<()> { - let mut sinks = self.finality_notification_sinks.lock(); - - if notify_finalized.is_empty() { - // cleanup any closed finality notification sinks - // since we won't be running the loop below which - // would also remove any closed sinks. - sinks.retain(|sink| !sink.is_closed()); - - return Ok(()); - } - - for finalized_hash in notify_finalized { - let header = self.header(&BlockId::Hash(finalized_hash))? - .expect("header already known to exist in DB because it is indicated in the tree route; qed"); - - telemetry!(SUBSTRATE_INFO; "notify.finalized"; - "height" => format!("{}", header.number()), - "best" => ?finalized_hash, - ); - - let notification = FinalityNotification { - header, - hash: finalized_hash, - }; - - sinks.retain(|sink| sink.unbounded_send(notification.clone()).is_ok()); - } - - Ok(()) - } - - fn notify_imported( - &self, - notify_import: Option>, - ) -> sp_blockchain::Result<()> { - let notify_import = match notify_import { - Some(notify_import) => notify_import, - None => { - // cleanup any closed import notification sinks since we won't - // be sending any notifications below which would remove any - // closed sinks. this is necessary since during initial sync we - // won't send any import notifications which could lead to a - // temporary leak of closed/discarded notification sinks (e.g. - // from consensus code). - self.import_notification_sinks - .lock() - .retain(|sink| !sink.is_closed()); - - return Ok(()); - } - }; - - 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( - ¬ify_import.hash, - storage_changes.0.into_iter(), - storage_changes.1.into_iter().map(|(sk, v)| (sk, v.into_iter())), - ); - } - - let notification = BlockImportNotification:: { - 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() - .retain(|sink| sink.unbounded_send(notification.clone()).is_ok()); - - Ok(()) - } - - /// Attempts to revert the chain by `n` blocks guaranteeing that no block is - /// reverted past the last finalized block. Returns the number of blocks - /// that were successfully reverted. - pub fn revert(&self, n: NumberFor) -> sp_blockchain::Result> { - Ok(self.backend.revert(n, false)?) - } - - /// Attempts to revert the chain by `n` blocks disregarding finality. This - /// method will revert any finalized blocks as requested and can potentially - /// leave the node in an inconsistent state. Other modules in the system that - /// persist data and that rely on finality (e.g. consensus parts) will be - /// unaffected by the revert. Use this method with caution and making sure - /// that no other data needs to be reverted for consistency aside from the - /// block data. - /// - /// Returns the number of blocks that were successfully reverted. - pub fn unsafe_revert(&self, n: NumberFor) -> sp_blockchain::Result> { - Ok(self.backend.revert(n, true)?) - } - - /// Get usage info about current client. - pub fn usage_info(&self) -> ClientInfo { - ClientInfo { - chain: self.chain_info(), - usage: self.backend.usage_info(), - } - } - - /// Get blockchain info. - pub fn chain_info(&self) -> blockchain::Info { - self.backend.blockchain().info() - } - - /// Get block status. - pub fn block_status(&self, id: &BlockId) -> sp_blockchain::Result { - // this can probably be implemented more efficiently - if let BlockId::Hash(ref h) = id { - if self.importing_block.read().as_ref().map_or(false, |importing| h == importing) { - return Ok(BlockStatus::Queued); - } - } - let hash_and_number = match id.clone() { - BlockId::Hash(hash) => self.backend.blockchain().number(hash)?.map(|n| (hash, n)), - BlockId::Number(n) => self.backend.blockchain().hash(n)?.map(|hash| (hash, n)), - }; - match hash_and_number { - Some((hash, number)) => { - if self.backend.have_state_at(&hash, number) { - Ok(BlockStatus::InChainWithState) - } else { - Ok(BlockStatus::InChainPruned) - } - } - None => Ok(BlockStatus::Unknown), - } - } - - /// Get block header by id. - pub fn header(&self, id: &BlockId) -> sp_blockchain::Result::Header>> { - self.backend.blockchain().header(*id) - } - - /// Get block body by id. - pub fn body(&self, id: &BlockId) -> sp_blockchain::Result::Extrinsic>>> { - self.backend.blockchain().body(*id) - } - - /// Gets the uncles of the block with `target_hash` going back `max_generation` ancestors. - pub fn uncles(&self, target_hash: Block::Hash, max_generation: NumberFor) -> sp_blockchain::Result> { - let load_header = |id: Block::Hash| -> sp_blockchain::Result { - match self.backend.blockchain().header(BlockId::Hash(id))? { - Some(hdr) => Ok(hdr), - None => Err(Error::UnknownBlock(format!("{:?}", id))), - } - }; - - let genesis_hash = self.backend.blockchain().info().genesis_hash; - if genesis_hash == target_hash { return Ok(Vec::new()); } - - let mut current_hash = target_hash; - let mut current = load_header(current_hash)?; - let mut ancestor_hash = *current.parent_hash(); - let mut ancestor = load_header(ancestor_hash)?; - let mut uncles = Vec::new(); - - for _generation in 0..max_generation.saturated_into() { - let children = self.backend.blockchain().children(ancestor_hash)?; - uncles.extend(children.into_iter().filter(|h| h != ¤t_hash)); - current_hash = ancestor_hash; - if genesis_hash == current_hash { break; } - current = ancestor; - ancestor_hash = *current.parent_hash(); - ancestor = load_header(ancestor_hash)?; - } - trace!("Collected {} uncles", uncles.len()); - Ok(uncles) - } - - /// Prepare in-memory header that is used in execution environment. - fn prepare_environment_block(&self, parent: &BlockId) -> sp_blockchain::Result { - let parent_header = self.backend.blockchain().expect_header(*parent)?; - Ok(<::Header as HeaderT>::new( - self.backend.blockchain().expect_block_number_from_id(parent)? + One::one(), - Default::default(), - Default::default(), - parent_header.hash(), - Default::default(), - )) - } -} - -impl ProofProvider for Client where - B: backend::Backend, - E: CallExecutor, - Block: BlockT, -{ - fn read_proof( - &self, - id: &BlockId, - keys: &mut dyn Iterator, - ) -> sp_blockchain::Result { - self.state_at(id) - .and_then(|state| prove_read(state, keys) - .map_err(Into::into)) - } - - fn read_child_proof( - &self, - id: &BlockId, - storage_key: &[u8], - child_info: ChildInfo, - keys: &mut dyn Iterator, - ) -> sp_blockchain::Result { - self.state_at(id) - .and_then(|state| prove_child_read(state, storage_key, child_info, keys) - .map_err(Into::into)) - } - - fn execution_proof( - &self, - id: &BlockId, - method: &str, - call_data: &[u8] - ) -> sp_blockchain::Result<(Vec, StorageProof)> { - // Make sure we include the `:code` and `:heap_pages` in the execution proof to be - // backwards compatible. - // - // TODO: Remove when solved: https://github.com/paritytech/substrate/issues/5047 - let code_proof = self.read_proof( - id, - &mut [well_known_keys::CODE, well_known_keys::HEAP_PAGES].iter().map(|v| *v), - )?; - - let state = self.state_at(id)?; - let header = self.prepare_environment_block(id)?; - prove_execution( - state, - header, - &self.executor, - method, - call_data, - ).map(|(r, p)| { - (r, StorageProof::merge(vec![p, code_proof])) - }) - } - - fn header_proof(&self, id: &BlockId) -> sp_blockchain::Result<(Block::Header, StorageProof)> { - self.header_proof_with_cht_size(id, cht::size()) - } - - fn key_changes_proof( - &self, - first: Block::Hash, - last: Block::Hash, - min: Block::Hash, - max: Block::Hash, - storage_key: Option<&StorageKey>, - key: &StorageKey, - ) -> sp_blockchain::Result> { - self.key_changes_proof_with_cht_size( - first, - last, - min, - max, - storage_key, - key, - cht::size(), - ) - } -} - - -impl BlockBuilderProvider for Client - where - B: backend::Backend + Send + Sync + 'static, - E: CallExecutor + Send + Sync + 'static, - Block: BlockT, - Self: ChainHeaderBackend + ProvideRuntimeApi, - >::Api: ApiExt> - + BlockBuilderApi, -{ - fn new_block_at>( - &self, - parent: &BlockId, - inherent_digests: DigestFor, - record_proof: R, - ) -> sp_blockchain::Result> { - sc_block_builder::BlockBuilder::new( - self, - self.expect_block_hash_from_id(parent)?, - self.expect_block_number_from_id(parent)?, - record_proof.into(), - inherent_digests, - &self.backend - ) - } - - fn new_block( - &self, - inherent_digests: DigestFor, - ) -> sp_blockchain::Result> { - let info = self.chain_info(); - sc_block_builder::BlockBuilder::new( - self, - info.best_hash, - info.best_number, - RecordProof::No, - inherent_digests, - &self.backend, - ) - } -} - -impl ExecutorProvider for Client where - B: backend::Backend, - E: CallExecutor, - Block: BlockT, -{ - type Executor = E; - - fn executor(&self) -> &Self::Executor { - &self.executor - } - - fn execution_extensions(&self) -> &ExecutionExtensions { - &self.execution_extensions - } -} - -impl StorageProvider for Client where - B: backend::Backend, - E: CallExecutor, - Block: BlockT, -{ - fn storage_keys(&self, id: &BlockId, key_prefix: &StorageKey) -> sp_blockchain::Result> { - let keys = self.state_at(id)?.keys(&key_prefix.0).into_iter().map(StorageKey).collect(); - Ok(keys) - } - - fn storage_pairs(&self, id: &BlockId, key_prefix: &StorageKey) - -> sp_blockchain::Result> - { - let state = self.state_at(id)?; - let keys = state - .keys(&key_prefix.0) - .into_iter() - .map(|k| { - let d = state.storage(&k).ok().flatten().unwrap_or_default(); - (StorageKey(k), StorageData(d)) - }) - .collect(); - Ok(keys) - } - - - fn storage_keys_iter<'a>( - &self, - id: &BlockId, - prefix: Option<&'a StorageKey>, - start_key: Option<&StorageKey> - ) -> sp_blockchain::Result> { - let state = self.state_at(id)?; - let start_key = start_key - .or(prefix) - .map(|key| key.0.clone()) - .unwrap_or_else(Vec::new); - Ok(KeyIterator::new(state, prefix, start_key)) - } - - - fn storage(&self, id: &BlockId, key: &StorageKey) -> sp_blockchain::Result> - { - Ok(self.state_at(id)? - .storage(&key.0).map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))? - .map(StorageData) - ) - } - - - fn storage_hash(&self, id: &BlockId, key: &StorageKey) -> sp_blockchain::Result> - { - Ok(self.state_at(id)? - .storage_hash(&key.0).map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))? - ) - } - - - fn child_storage_keys( - &self, - id: &BlockId, - child_storage_key: &StorageKey, - child_info: ChildInfo, - key_prefix: &StorageKey - ) -> sp_blockchain::Result> { - let keys = self.state_at(id)? - .child_keys(&child_storage_key.0, child_info, &key_prefix.0) - .into_iter() - .map(StorageKey) - .collect(); - Ok(keys) - } - - - fn child_storage( - &self, - id: &BlockId, - storage_key: &StorageKey, - child_info: ChildInfo, - key: &StorageKey - ) -> sp_blockchain::Result> { - Ok(self.state_at(id)? - .child_storage(&storage_key.0, child_info, &key.0) - .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))? - .map(StorageData)) - } - - - fn child_storage_hash( - &self, - id: &BlockId, - storage_key: &StorageKey, - child_info: ChildInfo, - key: &StorageKey - ) -> sp_blockchain::Result> { - Ok(self.state_at(id)? - .child_storage_hash(&storage_key.0, child_info, &key.0) - .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))? - ) - } - - fn max_key_changes_range( - &self, - first: NumberFor, - last: BlockId, - ) -> sp_blockchain::Result, BlockId)>> { - let last_number = self.backend.blockchain().expect_block_number_from_id(&last)?; - let last_hash = self.backend.blockchain().expect_block_hash_from_id(&last)?; - if first > last_number { - return Err(sp_blockchain::Error::ChangesTrieAccessFailed("Invalid changes trie range".into())); - } - - let (storage, configs) = match self.require_changes_trie(first, last_hash, false).ok() { - Some((storage, configs)) => (storage, configs), - None => return Ok(None), - }; - - let first_available_changes_trie = configs.last().map(|config| config.0); - match first_available_changes_trie { - Some(first_available_changes_trie) => { - let oldest_unpruned = storage.oldest_pruned_digest_range_end(); - let first = std::cmp::max(first_available_changes_trie, oldest_unpruned); - Ok(Some((first, last))) - }, - None => Ok(None) - } - } - - fn key_changes( - &self, - first: NumberFor, - last: BlockId, - storage_key: Option<&StorageKey>, - key: &StorageKey - ) -> sp_blockchain::Result, u32)>> { - let last_number = self.backend.blockchain().expect_block_number_from_id(&last)?; - let last_hash = self.backend.blockchain().expect_block_hash_from_id(&last)?; - let (storage, configs) = self.require_changes_trie(first, last_hash, true)?; - - let mut result = Vec::new(); - let best_number = self.backend.blockchain().info().best_number; - for (config_zero, config_end, config) in configs { - let range_first = ::std::cmp::max(first, config_zero + One::one()); - let range_anchor = match config_end { - Some((config_end_number, config_end_hash)) => if last_number > config_end_number { - ChangesTrieAnchorBlockId { hash: config_end_hash, number: config_end_number } - } else { - ChangesTrieAnchorBlockId { hash: convert_hash(&last_hash), number: last_number } - }, - None => ChangesTrieAnchorBlockId { hash: convert_hash(&last_hash), number: last_number }, - }; - - let config_range = ChangesTrieConfigurationRange { - config: &config, - zero: config_zero.clone(), - end: config_end.map(|(config_end_number, _)| config_end_number), - }; - let result_range: Vec<(NumberFor, u32)> = key_changes::, _>( - config_range, - storage.storage(), - 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| sp_blockchain::Error::ChangesTrieAccessFailed(err))?; - result.extend(result_range); - } - - Ok(result) - } -} - -impl HeaderMetadata for Client where - B: backend::Backend, - E: CallExecutor, - Block: BlockT, -{ - type Error = sp_blockchain::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, - Block: BlockT, -{ - fn uncles(&self, target_hash: Block::Hash, max_generation: NumberFor) -> sp_blockchain::Result> { - Ok(Client::uncles(self, target_hash, max_generation)? - .into_iter() - .filter_map(|hash| Client::header(self, &BlockId::Hash(hash)).unwrap_or(None)) - .collect() - ) - } -} - -impl ChainHeaderBackend for Client where - B: backend::Backend, - E: CallExecutor + Send + Sync, - Block: BlockT, - RA: Send + Sync, -{ - fn header(&self, id: BlockId) -> sp_blockchain::Result> { - self.backend.blockchain().header(id) - } - - fn info(&self) -> blockchain::Info { - self.backend.blockchain().info() - } - - fn status(&self, id: BlockId) -> sp_blockchain::Result { - self.backend.blockchain().status(id) - } - - fn number(&self, hash: Block::Hash) -> sp_blockchain::Result::Header as HeaderT>::Number>> { - self.backend.blockchain().number(hash) - } - - fn hash(&self, number: NumberFor) -> sp_blockchain::Result> { - self.backend.blockchain().hash(number) - } -} - -impl sp_runtime::traits::BlockIdTo for Client where - B: backend::Backend, - E: CallExecutor + Send + Sync, - Block: BlockT, - RA: Send + Sync, -{ - type Error = Error; - - fn to_hash(&self, block_id: &BlockId) -> sp_blockchain::Result> { - self.block_hash_from_id(block_id) - } - - fn to_number(&self, block_id: &BlockId) -> sp_blockchain::Result>> { - self.block_number_from_id(block_id) - } -} - -impl ChainHeaderBackend for &Client where - B: backend::Backend, - E: CallExecutor + Send + Sync, - Block: BlockT, - RA: Send + Sync, -{ - fn header(&self, id: BlockId) -> sp_blockchain::Result> { - (**self).backend.blockchain().header(id) - } - - fn info(&self) -> blockchain::Info { - (**self).backend.blockchain().info() - } - - fn status(&self, id: BlockId) -> sp_blockchain::Result { - (**self).status(id) - } - - fn number(&self, hash: Block::Hash) -> sp_blockchain::Result::Header as HeaderT>::Number>> { - (**self).number(hash) - } - - fn hash(&self, number: NumberFor) -> sp_blockchain::Result> { - (**self).hash(number) - } -} - -impl ProvideCache for Client where - B: backend::Backend, - Block: BlockT, -{ - fn cache(&self) -> Option>> { - self.backend.blockchain().cache() - } -} - -impl ProvideRuntimeApi for Client where - B: backend::Backend, - E: CallExecutor + Send + Sync, - Block: BlockT, - RA: ConstructRuntimeApi, -{ - type Api = >::RuntimeApi; - - fn runtime_api<'a>(&'a self) -> ApiRef<'a, Self::Api> { - RA::construct_runtime_api(self) - } -} - -impl CallApiAt for Client where - B: backend::Backend, - E: CallExecutor + Send + Sync, - Block: BlockT, -{ - type Error = Error; - type StateBackend = B::State; - - fn call_api_at< - 'a, - R: Encode + Decode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe, - C: CoreApi, - >( - &self, - params: CallApiAtParams<'a, Block, C, NC, B::State>, - ) -> sp_blockchain::Result> { - let core_api = params.core_api; - let at = params.at; - - let (manager, extensions) = self.execution_extensions.manager_and_extensions( - at, - params.context, - ); - - self.executor.contextual_call::<_, fn(_,_) -> _,_,_>( - || core_api.initialize_block(at, &self.prepare_environment_block(at)?), - at, - params.function, - ¶ms.arguments, - params.overlayed_changes, - Some(params.storage_transaction_cache), - params.initialize_block, - manager, - params.native_call, - params.recorder, - Some(extensions), - ) - } - - fn runtime_version_at(&self, at: &BlockId) -> sp_blockchain::Result { - self.runtime_version_at(at) - } -} - -/// 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 sp_consensus::BlockImport for &Client where - B: backend::Backend, - E: CallExecutor + Send + Sync, - Block: BlockT, - Client: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: CoreApi + - ApiExt, -{ - type Error = ConsensusError; - type Transaction = backend::TransactionFor; - - /// Import a checked and validated block. If a justification is provided in - /// `BlockImportParams` then `finalized` *must* be true. - /// - /// NOTE: only use this implementation when there are NO consensus-level BlockImport - /// objects. Otherwise, importing blocks directly into the client would be bypassing - /// important verification work. - /// - /// If you are not sure that there are no BlockImport objects provided by the consensus - /// algorithm, don't use this function. - fn import_block( - &mut self, - mut import_block: BlockImportParams>, - new_cache: HashMap>, - ) -> Result { - let span = tracing::span!(tracing::Level::DEBUG, "import_block"); - let _enter = span.enter(); - - if let Some(res) = self.prepare_block_storage_changes(&mut import_block).map_err(|e| { - warn!("Block prepare storage changes error:\n{:?}", e); - ConsensusError::ClientImport(e.to_string()) - })? { - return Ok(res) - } - - self.lock_import_and_run(|operation| { - self.apply_block(operation, import_block, new_cache) - }).map_err(|e| { - warn!("Block import error:\n{:?}", e); - ConsensusError::ClientImport(e.to_string()).into() - }) - } - - /// Check block preconditions. - fn check_block( - &mut self, - block: BlockCheckParams, - ) -> Result { - let BlockCheckParams { hash, number, parent_hash, allow_missing_state, import_existing } = block; - - // Check the block against white and black lists if any are defined - // (i.e. fork blocks and bad blocks respectively) - match self.block_rules.lookup(number, &hash) { - BlockLookupResult::KnownBad => { - trace!( - "Rejecting known bad block: #{} {:?}", - number, - hash, - ); - return Ok(ImportResult::KnownBad); - }, - BlockLookupResult::Expected(expected_hash) => { - trace!( - "Rejecting block from known invalid fork. Got {:?}, expected: {:?} at height {}", - hash, - expected_hash, - number - ); - return Ok(ImportResult::KnownBad); - }, - BlockLookupResult::NotSpecial => {} - } - - // Own status must be checked first. If the block and ancestry is pruned - // this function must return `AlreadyInChain` rather than `MissingState` - match self.block_status(&BlockId::Hash(hash)) - .map_err(|e| ConsensusError::ClientImport(e.to_string()))? - { - BlockStatus::InChainWithState | BlockStatus::Queued if !import_existing => return Ok(ImportResult::AlreadyInChain), - BlockStatus::InChainWithState | BlockStatus::Queued => {}, - BlockStatus::InChainPruned => return Ok(ImportResult::AlreadyInChain), - BlockStatus::Unknown => {}, - BlockStatus::KnownBad => return Ok(ImportResult::KnownBad), - } - - match self.block_status(&BlockId::Hash(parent_hash)) - .map_err(|e| ConsensusError::ClientImport(e.to_string()))? - { - BlockStatus::InChainWithState | BlockStatus::Queued => {}, - BlockStatus::Unknown => return Ok(ImportResult::UnknownParent), - BlockStatus::InChainPruned if allow_missing_state => {}, - BlockStatus::InChainPruned => return Ok(ImportResult::MissingState), - BlockStatus::KnownBad => return Ok(ImportResult::KnownBad), - } - - - Ok(ImportResult::imported(false)) - } -} - -impl sp_consensus::BlockImport for Client where - B: backend::Backend, - E: CallExecutor + Send + Sync, - Block: BlockT, - Self: ProvideRuntimeApi, - >::Api: CoreApi + - ApiExt, -{ - type Error = ConsensusError; - type Transaction = backend::TransactionFor; - - fn import_block( - &mut self, - import_block: BlockImportParams, - new_cache: HashMap>, - ) -> Result { - (&*self).import_block(import_block, new_cache) - } - - fn check_block( - &mut self, - block: BlockCheckParams, - ) -> Result { - (&*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, - ) -> sp_blockchain::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, - ) -> sp_blockchain::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, - ) -> sp_blockchain::Result<()> { - (**self).apply_finality(operation, id, justification, notify) - } - - fn finalize_block( - &self, - id: BlockId, - justification: Option, - notify: bool, - ) -> sp_blockchain::Result<()> { - (**self).finalize_block(id, justification, notify) - } -} - -impl BlockchainEvents for Client -where - E: CallExecutor, - Block: BlockT, -{ - /// Get block import event stream. - fn import_notification_stream(&self) -> ImportNotifications { - let (sink, stream) = tracing_unbounded("mpsc_import_notification_stream"); - self.import_notification_sinks.lock().push(sink); - stream - } - - fn finality_notification_stream(&self) -> FinalityNotifications { - let (sink, stream) = tracing_unbounded("mpsc_finality_notification_stream"); - self.finality_notification_sinks.lock().push(sink); - stream - } - - /// Get storage changes event stream. - fn storage_changes_notification_stream( - &self, - filter_keys: Option<&[StorageKey]>, - child_filter_keys: Option<&[(StorageKey, Option>)]>, - ) -> sp_blockchain::Result> { - Ok(self.storage_notifications.lock().listen(filter_keys, child_filter_keys)) - } -} - -/// Implement Longest Chain Select implementation -/// where 'longest' is defined as the highest number of blocks -pub struct LongestChain { - backend: Arc, - _phantom: PhantomData -} - -impl Clone for LongestChain { - fn clone(&self) -> Self { - let backend = self.backend.clone(); - LongestChain { - backend, - _phantom: Default::default() - } - } -} - -impl LongestChain -where - B: backend::Backend, - Block: BlockT, -{ - /// Instantiate a new LongestChain for Backend B - pub fn new(backend: Arc) -> Self { - LongestChain { - backend, - _phantom: Default::default() - } - } - - fn best_block_header(&self) -> sp_blockchain::Result<::Header> { - let info = self.backend.blockchain().info(); - 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")) - } - - fn leaves(&self) -> Result::Hash>, sp_blockchain::Error> { - self.backend.blockchain().leaves() - } -} - -impl SelectChain for LongestChain -where - B: backend::Backend, - Block: BlockT, -{ - - fn leaves(&self) -> Result::Hash>, ConsensusError> { - LongestChain::leaves(self) - .map_err(|e| ConsensusError::ChainLookup(e.to_string()).into()) - } - - fn best_chain(&self) - -> Result<::Header, ConsensusError> - { - LongestChain::best_block_header(&self) - .map_err(|e| ConsensusError::ChainLookup(e.to_string()).into()) - } - - fn finality_target( - &self, - target_hash: Block::Hash, - maybe_max_number: Option> - ) -> Result, ConsensusError> { - 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()) - } -} - -impl BlockBackend for Client - where - B: backend::Backend, - E: CallExecutor, - Block: BlockT, -{ - fn block_body( - &self, - id: &BlockId, - ) -> sp_blockchain::Result::Extrinsic>>> { - self.body(id) - } - - fn block(&self, id: &BlockId) -> sp_blockchain::Result>> - { - Ok(match (self.header(id)?, self.body(id)?, self.justification(id)?) { - (Some(header), Some(extrinsics), justification) => - Some(SignedBlock { block: Block::new(header, extrinsics), justification }), - _ => None, - }) - } - - fn block_status(&self, id: &BlockId) -> sp_blockchain::Result { - // this can probably be implemented more efficiently - if let BlockId::Hash(ref h) = id { - if self.importing_block.read().as_ref().map_or(false, |importing| h == importing) { - return Ok(BlockStatus::Queued); - } - } - let hash_and_number = match id.clone() { - BlockId::Hash(hash) => self.backend.blockchain().number(hash)?.map(|n| (hash, n)), - BlockId::Number(n) => self.backend.blockchain().hash(n)?.map(|hash| (hash, n)), - }; - match hash_and_number { - Some((hash, number)) => { - if self.backend.have_state_at(&hash, number) { - Ok(BlockStatus::InChainWithState) - } else { - Ok(BlockStatus::InChainPruned) - } - } - None => Ok(BlockStatus::Unknown), - } - } - - fn justification(&self, id: &BlockId) -> sp_blockchain::Result> { - self.backend.blockchain().justification(*id) - } -} - -impl backend::AuxStore for Client - where - B: backend::Backend, - E: CallExecutor, - Block: BlockT, - Self: ProvideRuntimeApi, - >::Api: CoreApi, -{ - /// Insert auxiliary data into key-value store. - fn insert_aux< - 'a, - 'b: 'a, - 'c: 'a, - I: IntoIterator, - D: IntoIterator, - >(&self, insert: I, delete: D) -> sp_blockchain::Result<()> { - // Import is locked here because we may have other block import - // operations that tries to set aux data. Note that for consensus - // layer, one can always use atomic operations to make sure - // import is only locked once. - self.lock_import_and_run(|operation| { - apply_aux(operation, insert, delete) - }) - } - /// Query auxiliary data from key-value store. - fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result>> { - backend::AuxStore::get_aux(&*self.backend, key) - } -} - -impl backend::AuxStore for &Client - where - B: backend::Backend, - E: CallExecutor, - Block: BlockT, - Client: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: CoreApi, -{ - fn insert_aux< - 'a, - 'b: 'a, - 'c: 'a, - I: IntoIterator, - D: IntoIterator, - >(&self, insert: I, delete: D) -> sp_blockchain::Result<()> { - (**self).insert_aux(insert, delete) - } - - fn get_aux(&self, key: &[u8]) -> sp_blockchain::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, D, I>( - operation: &mut ClientImportOperation, - insert: I, - delete: D, -) -> sp_blockchain::Result<()> -where - Block: BlockT, - 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))) - ) -} - -impl sp_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; - use super::*; - use sp_core::{blake2_256, H256}; - use sp_runtime::DigestItem; - use sp_consensus::{BlockOrigin, SelectChain, BlockImport}; - use substrate_test_runtime_client::{ - prelude::*, - client_ext::ClientExt, - sc_client_db::{Backend, DatabaseSettings, DatabaseSettingsSrc, PruningMode}, - runtime::{self, Block, Transfer, RuntimeApi, TestAPI}, - }; - use hex_literal::hex; - - /// Returns tuple, consisting of: - /// 1) test client pre-filled with blocks changing balances; - /// 2) roots of changes tries for these blocks - /// 3) test cases in form (begin, end, key, vec![(block, extrinsic)]) that are required to pass - pub fn prepare_client_with_key_changes() -> ( - substrate_test_runtime_client::sc_client::Client, - Vec, - Vec<(u64, u64, Vec, Vec<(u64, u32)>)>, - ) { - // prepare block structure - let blocks_transfers = vec![ - vec![(AccountKeyring::Alice, AccountKeyring::Dave), (AccountKeyring::Bob, AccountKeyring::Dave)], - vec![(AccountKeyring::Charlie, AccountKeyring::Eve)], - vec![], - vec![(AccountKeyring::Alice, AccountKeyring::Dave)], - ]; - - // prepare client ang import blocks - let mut local_roots = Vec::new(); - let config = Some(ChangesTrieConfiguration::new(4, 2)); - let mut remote_client = TestClientBuilder::new().changes_trie_config(config).build(); - let mut nonces: HashMap<_, u64> = Default::default(); - for (i, block_transfers) in blocks_transfers.into_iter().enumerate() { - let mut builder = remote_client.new_block(Default::default()).unwrap(); - for (from, to) in block_transfers { - builder.push_transfer(Transfer { - from: from.into(), - to: to.into(), - amount: 1, - nonce: *nonces.entry(from).and_modify(|n| { *n = *n + 1 }).or_default(), - }).unwrap(); - } - let block = builder.build().unwrap().block; - remote_client.import(BlockOrigin::Own, block).unwrap(); - - let header = remote_client.header(&BlockId::Number(i as u64 + 1)).unwrap().unwrap(); - let trie_root = header.digest().log(DigestItem::as_changes_trie_root) - .map(|root| H256::from_slice(root.as_ref())) - .unwrap(); - local_roots.push(trie_root); - } - - // prepare test cases - let alice = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Alice.into())).to_vec(); - let bob = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Bob.into())).to_vec(); - let charlie = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Charlie.into())).to_vec(); - let dave = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec(); - let eve = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Eve.into())).to_vec(); - let ferdie = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Ferdie.into())).to_vec(); - let test_cases = vec![ - (1, 4, alice.clone(), vec![(4, 0), (1, 0)]), - (1, 3, alice.clone(), vec![(1, 0)]), - (2, 4, alice.clone(), vec![(4, 0)]), - (2, 3, alice.clone(), vec![]), - - (1, 4, bob.clone(), vec![(1, 1)]), - (1, 1, bob.clone(), vec![(1, 1)]), - (2, 4, bob.clone(), vec![]), - - (1, 4, charlie.clone(), vec![(2, 0)]), - - (1, 4, dave.clone(), vec![(4, 0), (1, 1), (1, 0)]), - (1, 1, dave.clone(), vec![(1, 1), (1, 0)]), - (3, 4, dave.clone(), vec![(4, 0)]), - - (1, 4, eve.clone(), vec![(2, 0)]), - (1, 1, eve.clone(), vec![]), - (3, 4, eve.clone(), vec![]), - - (1, 4, ferdie.clone(), vec![]), - ]; - - (remote_client, local_roots, test_cases) - } - - #[test] - fn client_initializes_from_genesis_ok() { - let client = substrate_test_runtime_client::new(); - - assert_eq!( - client.runtime_api().balance_of( - &BlockId::Number(client.chain_info().best_number), - AccountKeyring::Alice.into() - ).unwrap(), - 1000 - ); - assert_eq!( - client.runtime_api().balance_of( - &BlockId::Number(client.chain_info().best_number), - AccountKeyring::Ferdie.into() - ).unwrap(), - 0 - ); - } - - #[test] - fn block_builder_works_with_no_transactions() { - let mut client = substrate_test_runtime_client::new(); - - let block = client.new_block(Default::default()).unwrap().build().unwrap().block; - - client.import(BlockOrigin::Own, block).unwrap(); - - assert_eq!(client.chain_info().best_number, 1); - } - - #[test] - fn block_builder_works_with_transactions() { - let mut client = substrate_test_runtime_client::new(); - - let mut builder = client.new_block(Default::default()).unwrap(); - - builder.push_transfer(Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Ferdie.into(), - amount: 42, - nonce: 0, - }).unwrap(); - - let block = builder.build().unwrap().block; - client.import(BlockOrigin::Own, block).unwrap(); - - assert_eq!(client.chain_info().best_number, 1); - assert_ne!( - client.state_at(&BlockId::Number(1)).unwrap().pairs(), - client.state_at(&BlockId::Number(0)).unwrap().pairs() - ); - assert_eq!( - client.runtime_api().balance_of( - &BlockId::Number(client.chain_info().best_number), - AccountKeyring::Alice.into() - ).unwrap(), - 958 - ); - assert_eq!( - client.runtime_api().balance_of( - &BlockId::Number(client.chain_info().best_number), - AccountKeyring::Ferdie.into() - ).unwrap(), - 42 - ); - } - - #[test] - fn block_builder_does_not_include_invalid() { - let mut client = substrate_test_runtime_client::new(); - - let mut builder = client.new_block(Default::default()).unwrap(); - - builder.push_transfer(Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Ferdie.into(), - amount: 42, - nonce: 0, - }).unwrap(); - - assert!( - builder.push_transfer(Transfer { - from: AccountKeyring::Eve.into(), - to: AccountKeyring::Alice.into(), - amount: 42, - nonce: 0, - }).is_err() - ); - - let block = builder.build().unwrap().block; - client.import(BlockOrigin::Own, block).unwrap(); - - assert_eq!(client.chain_info().best_number, 1); - assert_ne!( - client.state_at(&BlockId::Number(1)).unwrap().pairs(), - client.state_at(&BlockId::Number(0)).unwrap().pairs() - ); - assert_eq!(client.body(&BlockId::Number(1)).unwrap().unwrap().len(), 1) - } - - #[test] - fn best_containing_with_genesis_block() { - // block tree: - // G - - let (client, longest_chain_select) = TestClientBuilder::new().build_with_longest_chain(); - - let genesis_hash = client.chain_info().genesis_hash; - - assert_eq!( - genesis_hash.clone(), - longest_chain_select.finality_target(genesis_hash.clone(), None).unwrap().unwrap() - ); - } - - #[test] - fn best_containing_with_hash_not_found() { - // block tree: - // G - - let (client, longest_chain_select) = TestClientBuilder::new().build_with_longest_chain(); - - let uninserted_block = client.new_block(Default::default()).unwrap().build().unwrap().block; - - assert_eq!( - None, - longest_chain_select.finality_target(uninserted_block.hash().clone(), None).unwrap() - ); - } - - #[test] - fn uncles_with_only_ancestors() { - // block tree: - // G -> A1 -> A2 - let mut client = substrate_test_runtime_client::new(); - - // G -> A1 - let a1 = client.new_block(Default::default()).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, a1.clone()).unwrap(); - - // A1 -> A2 - let a2 = client.new_block(Default::default()).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, a2.clone()).unwrap(); - let v: Vec = Vec::new(); - assert_eq!(v, client.uncles(a2.hash(), 3).unwrap()); - } - - #[test] - fn uncles_with_multiple_forks() { - // block tree: - // G -> A1 -> A2 -> A3 -> A4 -> A5 - // A1 -> B2 -> B3 -> B4 - // B2 -> C3 - // A1 -> D2 - let mut client = substrate_test_runtime_client::new(); - - // G -> A1 - let a1 = client.new_block(Default::default()).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, a1.clone()).unwrap(); - - // A1 -> A2 - let a2 = client.new_block_at( - &BlockId::Hash(a1.hash()), - Default::default(), - false, - ).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, a2.clone()).unwrap(); - - // A2 -> A3 - let a3 = client.new_block_at( - &BlockId::Hash(a2.hash()), - Default::default(), - false, - ).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, a3.clone()).unwrap(); - - // A3 -> A4 - let a4 = client.new_block_at( - &BlockId::Hash(a3.hash()), - Default::default(), - false, - ).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, a4.clone()).unwrap(); - - // A4 -> A5 - let a5 = client.new_block_at( - &BlockId::Hash(a4.hash()), - Default::default(), - false, - ).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, a5.clone()).unwrap(); - - // A1 -> B2 - let mut builder = client.new_block_at( - &BlockId::Hash(a1.hash()), - Default::default(), - false, - ).unwrap(); - // this push is required as otherwise B2 has the same hash as A2 and won't get imported - builder.push_transfer(Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Ferdie.into(), - amount: 41, - nonce: 0, - }).unwrap(); - let b2 = builder.build().unwrap().block; - client.import(BlockOrigin::Own, b2.clone()).unwrap(); - - // B2 -> B3 - let b3 = client.new_block_at( - &BlockId::Hash(b2.hash()), - Default::default(), - false, - ).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, b3.clone()).unwrap(); - - // B3 -> B4 - let b4 = client.new_block_at( - &BlockId::Hash(b3.hash()), - Default::default(), - false, - ).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, b4.clone()).unwrap(); - - // // B2 -> C3 - let mut builder = client.new_block_at( - &BlockId::Hash(b2.hash()), - Default::default(), - false, - ).unwrap(); - // this push is required as otherwise C3 has the same hash as B3 and won't get imported - builder.push_transfer(Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Ferdie.into(), - amount: 1, - nonce: 1, - }).unwrap(); - let c3 = builder.build().unwrap().block; - client.import(BlockOrigin::Own, c3.clone()).unwrap(); - - // A1 -> D2 - let mut builder = client.new_block_at( - &BlockId::Hash(a1.hash()), - Default::default(), - false, - ).unwrap(); - // this push is required as otherwise D2 has the same hash as B2 and won't get imported - builder.push_transfer(Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Ferdie.into(), - amount: 1, - nonce: 0, - }).unwrap(); - let d2 = builder.build().unwrap().block; - client.import(BlockOrigin::Own, d2.clone()).unwrap(); - - let genesis_hash = client.chain_info().genesis_hash; - - let uncles1 = client.uncles(a4.hash(), 10).unwrap(); - assert_eq!(vec![b2.hash(), d2.hash()], uncles1); - - let uncles2 = client.uncles(a4.hash(), 0).unwrap(); - assert_eq!(0, uncles2.len()); - - let uncles3 = client.uncles(a1.hash(), 10).unwrap(); - assert_eq!(0, uncles3.len()); - - let uncles4 = client.uncles(genesis_hash, 10).unwrap(); - assert_eq!(0, uncles4.len()); - - let uncles5 = client.uncles(d2.hash(), 10).unwrap(); - assert_eq!(vec![a2.hash(), b2.hash()], uncles5); - - let uncles6 = client.uncles(b3.hash(), 1).unwrap(); - assert_eq!(vec![c3.hash()], uncles6); - } - - #[test] - fn best_containing_on_longest_chain_with_single_chain_3_blocks() { - // block tree: - // G -> A1 -> A2 - - let (mut client, longest_chain_select) = TestClientBuilder::new().build_with_longest_chain(); - - // G -> A1 - let a1 = client.new_block(Default::default()).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, a1.clone()).unwrap(); - - // A1 -> A2 - let a2 = client.new_block(Default::default()).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, a2.clone()).unwrap(); - - let genesis_hash = client.chain_info().genesis_hash; - - assert_eq!(a2.hash(), longest_chain_select.finality_target(genesis_hash, None).unwrap().unwrap()); - assert_eq!(a2.hash(), longest_chain_select.finality_target(a1.hash(), None).unwrap().unwrap()); - assert_eq!(a2.hash(), longest_chain_select.finality_target(a2.hash(), None).unwrap().unwrap()); - } - - #[test] - fn best_containing_on_longest_chain_with_multiple_forks() { - // block tree: - // G -> A1 -> A2 -> A3 -> A4 -> A5 - // A1 -> B2 -> B3 -> B4 - // B2 -> C3 - // A1 -> D2 - let (mut client, longest_chain_select) = TestClientBuilder::new().build_with_longest_chain(); - - // G -> A1 - let a1 = client.new_block(Default::default()).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, a1.clone()).unwrap(); - - // A1 -> A2 - let a2 = client.new_block_at( - &BlockId::Hash(a1.hash()), - Default::default(), - false, - ).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, a2.clone()).unwrap(); - - // A2 -> A3 - let a3 = client.new_block_at( - &BlockId::Hash(a2.hash()), - Default::default(), - false, - ).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, a3.clone()).unwrap(); - - // A3 -> A4 - let a4 = client.new_block_at( - &BlockId::Hash(a3.hash()), - Default::default(), - false, - ).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, a4.clone()).unwrap(); - - // A4 -> A5 - let a5 = client.new_block_at( - &BlockId::Hash(a4.hash()), - Default::default(), - false, - ).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, a5.clone()).unwrap(); - - // A1 -> B2 - let mut builder = client.new_block_at( - &BlockId::Hash(a1.hash()), - Default::default(), - false, - ).unwrap(); - // this push is required as otherwise B2 has the same hash as A2 and won't get imported - builder.push_transfer(Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Ferdie.into(), - amount: 41, - nonce: 0, - }).unwrap(); - let b2 = builder.build().unwrap().block; - client.import(BlockOrigin::Own, b2.clone()).unwrap(); - - // B2 -> B3 - let b3 = client.new_block_at( - &BlockId::Hash(b2.hash()), - Default::default(), - false, - ).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, b3.clone()).unwrap(); - - // B3 -> B4 - let b4 = client.new_block_at( - &BlockId::Hash(b3.hash()), - Default::default(), - false, - ).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, b4.clone()).unwrap(); - - // // B2 -> C3 - let mut builder = client.new_block_at( - &BlockId::Hash(b2.hash()), - Default::default(), - false, - ).unwrap(); - // this push is required as otherwise C3 has the same hash as B3 and won't get imported - builder.push_transfer(Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Ferdie.into(), - amount: 1, - nonce: 1, - }).unwrap(); - let c3 = builder.build().unwrap().block; - client.import(BlockOrigin::Own, c3.clone()).unwrap(); - - // A1 -> D2 - let mut builder = client.new_block_at( - &BlockId::Hash(a1.hash()), - Default::default(), - false, - ).unwrap(); - // this push is required as otherwise D2 has the same hash as B2 and won't get imported - builder.push_transfer(Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Ferdie.into(), - amount: 1, - nonce: 0, - }).unwrap(); - let d2 = builder.build().unwrap().block; - client.import(BlockOrigin::Own, d2.clone()).unwrap(); - - assert_eq!(client.chain_info().best_hash, a5.hash()); - - let genesis_hash = client.chain_info().genesis_hash; - let leaves = longest_chain_select.leaves().unwrap(); - - assert!(leaves.contains(&a5.hash())); - assert!(leaves.contains(&b4.hash())); - assert!(leaves.contains(&c3.hash())); - assert!(leaves.contains(&d2.hash())); - assert_eq!(leaves.len(), 4); - - // search without restriction - - assert_eq!(a5.hash(), longest_chain_select.finality_target( - genesis_hash, None).unwrap().unwrap()); - assert_eq!(a5.hash(), longest_chain_select.finality_target( - a1.hash(), None).unwrap().unwrap()); - assert_eq!(a5.hash(), longest_chain_select.finality_target( - a2.hash(), None).unwrap().unwrap()); - assert_eq!(a5.hash(), longest_chain_select.finality_target( - a3.hash(), None).unwrap().unwrap()); - assert_eq!(a5.hash(), longest_chain_select.finality_target( - a4.hash(), None).unwrap().unwrap()); - assert_eq!(a5.hash(), longest_chain_select.finality_target( - a5.hash(), None).unwrap().unwrap()); - - assert_eq!(b4.hash(), longest_chain_select.finality_target( - b2.hash(), None).unwrap().unwrap()); - assert_eq!(b4.hash(), longest_chain_select.finality_target( - b3.hash(), None).unwrap().unwrap()); - assert_eq!(b4.hash(), longest_chain_select.finality_target( - b4.hash(), None).unwrap().unwrap()); - - assert_eq!(c3.hash(), longest_chain_select.finality_target( - c3.hash(), None).unwrap().unwrap()); - - assert_eq!(d2.hash(), longest_chain_select.finality_target( - d2.hash(), None).unwrap().unwrap()); - - - // search only blocks with number <= 5. equivalent to without restriction for this scenario - - assert_eq!(a5.hash(), longest_chain_select.finality_target( - genesis_hash, Some(5)).unwrap().unwrap()); - assert_eq!(a5.hash(), longest_chain_select.finality_target( - a1.hash(), Some(5)).unwrap().unwrap()); - assert_eq!(a5.hash(), longest_chain_select.finality_target( - a2.hash(), Some(5)).unwrap().unwrap()); - assert_eq!(a5.hash(), longest_chain_select.finality_target( - a3.hash(), Some(5)).unwrap().unwrap()); - assert_eq!(a5.hash(), longest_chain_select.finality_target( - a4.hash(), Some(5)).unwrap().unwrap()); - assert_eq!(a5.hash(), longest_chain_select.finality_target( - a5.hash(), Some(5)).unwrap().unwrap()); - - assert_eq!(b4.hash(), longest_chain_select.finality_target( - b2.hash(), Some(5)).unwrap().unwrap()); - assert_eq!(b4.hash(), longest_chain_select.finality_target( - b3.hash(), Some(5)).unwrap().unwrap()); - assert_eq!(b4.hash(), longest_chain_select.finality_target( - b4.hash(), Some(5)).unwrap().unwrap()); - - assert_eq!(c3.hash(), longest_chain_select.finality_target( - c3.hash(), Some(5)).unwrap().unwrap()); - - assert_eq!(d2.hash(), longest_chain_select.finality_target( - d2.hash(), Some(5)).unwrap().unwrap()); - - - // search only blocks with number <= 4 - - assert_eq!(a4.hash(), longest_chain_select.finality_target( - genesis_hash, Some(4)).unwrap().unwrap()); - assert_eq!(a4.hash(), longest_chain_select.finality_target( - a1.hash(), Some(4)).unwrap().unwrap()); - assert_eq!(a4.hash(), longest_chain_select.finality_target( - a2.hash(), Some(4)).unwrap().unwrap()); - assert_eq!(a4.hash(), longest_chain_select.finality_target( - a3.hash(), Some(4)).unwrap().unwrap()); - assert_eq!(a4.hash(), longest_chain_select.finality_target( - a4.hash(), Some(4)).unwrap().unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a5.hash(), Some(4)).unwrap()); - - assert_eq!(b4.hash(), longest_chain_select.finality_target( - b2.hash(), Some(4)).unwrap().unwrap()); - assert_eq!(b4.hash(), longest_chain_select.finality_target( - b3.hash(), Some(4)).unwrap().unwrap()); - assert_eq!(b4.hash(), longest_chain_select.finality_target( - b4.hash(), Some(4)).unwrap().unwrap()); - - assert_eq!(c3.hash(), longest_chain_select.finality_target( - c3.hash(), Some(4)).unwrap().unwrap()); - - assert_eq!(d2.hash(), longest_chain_select.finality_target( - d2.hash(), Some(4)).unwrap().unwrap()); - - - // search only blocks with number <= 3 - - assert_eq!(a3.hash(), longest_chain_select.finality_target( - genesis_hash, Some(3)).unwrap().unwrap()); - assert_eq!(a3.hash(), longest_chain_select.finality_target( - a1.hash(), Some(3)).unwrap().unwrap()); - assert_eq!(a3.hash(), longest_chain_select.finality_target( - a2.hash(), Some(3)).unwrap().unwrap()); - assert_eq!(a3.hash(), longest_chain_select.finality_target( - a3.hash(), Some(3)).unwrap().unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a4.hash(), Some(3)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a5.hash(), Some(3)).unwrap()); - - assert_eq!(b3.hash(), longest_chain_select.finality_target( - b2.hash(), Some(3)).unwrap().unwrap()); - assert_eq!(b3.hash(), longest_chain_select.finality_target( - b3.hash(), Some(3)).unwrap().unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - b4.hash(), Some(3)).unwrap()); - - assert_eq!(c3.hash(), longest_chain_select.finality_target( - c3.hash(), Some(3)).unwrap().unwrap()); - - assert_eq!(d2.hash(), longest_chain_select.finality_target( - d2.hash(), Some(3)).unwrap().unwrap()); - - - // search only blocks with number <= 2 - - assert_eq!(a2.hash(), longest_chain_select.finality_target( - genesis_hash, Some(2)).unwrap().unwrap()); - assert_eq!(a2.hash(), longest_chain_select.finality_target( - a1.hash(), Some(2)).unwrap().unwrap()); - assert_eq!(a2.hash(), longest_chain_select.finality_target( - a2.hash(), Some(2)).unwrap().unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a3.hash(), Some(2)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a4.hash(), Some(2)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a5.hash(), Some(2)).unwrap()); - - assert_eq!(b2.hash(), longest_chain_select.finality_target( - b2.hash(), Some(2)).unwrap().unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - b3.hash(), Some(2)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - b4.hash(), Some(2)).unwrap()); - - assert_eq!(None, longest_chain_select.finality_target( - c3.hash(), Some(2)).unwrap()); - - assert_eq!(d2.hash(), longest_chain_select.finality_target( - d2.hash(), Some(2)).unwrap().unwrap()); - - - // search only blocks with number <= 1 - - assert_eq!(a1.hash(), longest_chain_select.finality_target( - genesis_hash, Some(1)).unwrap().unwrap()); - assert_eq!(a1.hash(), longest_chain_select.finality_target( - a1.hash(), Some(1)).unwrap().unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a2.hash(), Some(1)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a3.hash(), Some(1)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a4.hash(), Some(1)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a5.hash(), Some(1)).unwrap()); - - assert_eq!(None, longest_chain_select.finality_target( - b2.hash(), Some(1)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - b3.hash(), Some(1)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - b4.hash(), Some(1)).unwrap()); - - assert_eq!(None, longest_chain_select.finality_target( - c3.hash(), Some(1)).unwrap()); - - assert_eq!(None, longest_chain_select.finality_target( - d2.hash(), Some(1)).unwrap()); - - // search only blocks with number <= 0 - - assert_eq!(genesis_hash, longest_chain_select.finality_target( - genesis_hash, Some(0)).unwrap().unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a1.hash(), Some(0)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a2.hash(), Some(0)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a3.hash(), Some(0)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a4.hash(), Some(0)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a5.hash(), Some(0)).unwrap()); - - assert_eq!(None, longest_chain_select.finality_target( - b2.hash(), Some(0)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - b3.hash(), Some(0)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - b4.hash(), Some(0)).unwrap()); - - assert_eq!(None, longest_chain_select.finality_target( - c3.hash().clone(), Some(0)).unwrap()); - - assert_eq!(None, longest_chain_select.finality_target( - d2.hash().clone(), Some(0)).unwrap()); - } - - #[test] - fn best_containing_on_longest_chain_with_max_depth_higher_than_best() { - // block tree: - // G -> A1 -> A2 - - let (mut client, longest_chain_select) = TestClientBuilder::new().build_with_longest_chain(); - - // G -> A1 - let a1 = client.new_block(Default::default()).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, a1.clone()).unwrap(); - - // A1 -> A2 - let a2 = client.new_block(Default::default()).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, a2.clone()).unwrap(); - - let genesis_hash = client.chain_info().genesis_hash; - - assert_eq!(a2.hash(), longest_chain_select.finality_target(genesis_hash, Some(10)).unwrap().unwrap()); - } - - #[test] - fn key_changes_works() { - let (client, _, test_cases) = prepare_client_with_key_changes(); - - 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), - None, - &StorageKey(key), - ).unwrap(); - match actual_result == expected_result { - true => (), - false => panic!(format!("Failed test {}: actual = {:?}, expected = {:?}", - index, actual_result, expected_result)), - } - } - } - - #[test] - fn import_with_justification() { - let mut client = substrate_test_runtime_client::new(); - - // G -> A1 - let a1 = client.new_block(Default::default()).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, a1.clone()).unwrap(); - - // A1 -> A2 - let a2 = client.new_block_at( - &BlockId::Hash(a1.hash()), - Default::default(), - false, - ).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, a2.clone()).unwrap(); - - // A2 -> A3 - let justification = vec![1, 2, 3]; - let a3 = client.new_block_at( - &BlockId::Hash(a2.hash()), - Default::default(), - false, - ).unwrap().build().unwrap().block; - client.import_justified(BlockOrigin::Own, a3.clone(), justification.clone()).unwrap(); - - assert_eq!( - client.chain_info().finalized_hash, - a3.hash(), - ); - - assert_eq!( - client.justification(&BlockId::Hash(a3.hash())).unwrap(), - Some(justification), - ); - - assert_eq!( - client.justification(&BlockId::Hash(a1.hash())).unwrap(), - None, - ); - - assert_eq!( - client.justification(&BlockId::Hash(a2.hash())).unwrap(), - None, - ); - } - - #[test] - fn importing_diverged_finalized_block_should_trigger_reorg() { - let mut client = substrate_test_runtime_client::new(); - - // G -> A1 -> A2 - // \ - // -> B1 - let a1 = client.new_block_at( - &BlockId::Number(0), - Default::default(), - false, - ).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, a1.clone()).unwrap(); - - let a2 = client.new_block_at( - &BlockId::Hash(a1.hash()), - Default::default(), - false, - ).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, a2.clone()).unwrap(); - - let mut b1 = client.new_block_at( - &BlockId::Number(0), - Default::default(), - false, - ).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: 1, - nonce: 0, - }).unwrap(); - // create but don't import B1 just yet - let b1 = b1.build().unwrap().block; - - // A2 is the current best since it's the longest chain - assert_eq!( - client.chain_info().best_hash, - a2.hash(), - ); - - // importing B1 as finalized should trigger a re-org and set it as new best - let justification = vec![1, 2, 3]; - client.import_justified(BlockOrigin::Own, b1.clone(), justification).unwrap(); - - assert_eq!( - client.chain_info().best_hash, - b1.hash(), - ); - - assert_eq!( - client.chain_info().finalized_hash, - b1.hash(), - ); - } - - #[test] - fn finalizing_diverged_block_should_trigger_reorg() { - - let (mut client, select_chain) = TestClientBuilder::new().build_with_longest_chain(); - - // G -> A1 -> A2 - // \ - // -> B1 -> B2 - let a1 = client.new_block_at( - &BlockId::Number(0), - Default::default(), - false, - ).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, a1.clone()).unwrap(); - - let a2 = client.new_block_at( - &BlockId::Hash(a1.hash()), - Default::default(), - false, - ).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, a2.clone()).unwrap(); - - let mut b1 = client.new_block_at( - &BlockId::Number(0), - Default::default(), - false, - ).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: 1, - nonce: 0, - }).unwrap(); - let b1 = b1.build().unwrap().block; - client.import(BlockOrigin::Own, b1.clone()).unwrap(); - - let b2 = client.new_block_at( - &BlockId::Hash(b1.hash()), - Default::default(), - false, - ).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, b2.clone()).unwrap(); - - // A2 is the current best since it's the longest chain - assert_eq!( - client.chain_info().best_hash, - a2.hash(), - ); - - // we finalize block B1 which is on a different branch from current best - // which should trigger a re-org. - ClientExt::finalize_block(&client, BlockId::Hash(b1.hash()), None).unwrap(); - - // B1 should now be the latest finalized - assert_eq!( - client.chain_info().finalized_hash, - b1.hash(), - ); - - // and B1 should be the new best block (`finalize_block` as no way of - // knowing about B2) - assert_eq!( - client.chain_info().best_hash, - b1.hash(), - ); - - // `SelectChain` should report B2 as best block though - assert_eq!( - select_chain.best_chain().unwrap().hash(), - b2.hash(), - ); - - // after we build B3 on top of B2 and import it - // it should be the new best block, - let b3 = client.new_block_at( - &BlockId::Hash(b2.hash()), - Default::default(), - false, - ).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, b3.clone()).unwrap(); - - assert_eq!( - client.chain_info().best_hash, - b3.hash(), - ); - } - - #[test] - fn get_header_by_block_number_doesnt_panic() { - let client = substrate_test_runtime_client::new(); - - // backend uses u32 for block numbers, make sure we don't panic when - // trying to convert - let id = BlockId::::Number(72340207214430721); - client.header(&id).expect_err("invalid block number overflows u32"); - } - - #[test] - fn state_reverted_on_reorg() { - let _ = env_logger::try_init(); - let mut client = substrate_test_runtime_client::new(); - - let current_balance = |client: &substrate_test_runtime_client::TestClient| - client.runtime_api().balance_of( - &BlockId::number(client.chain_info().best_number), AccountKeyring::Alice.into() - ).unwrap(); - - // G -> A1 -> A2 - // \ - // -> B1 - let mut a1 = client.new_block_at( - &BlockId::Number(0), - Default::default(), - false, - ).unwrap(); - a1.push_transfer(Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Bob.into(), - amount: 10, - nonce: 0, - }).unwrap(); - let a1 = a1.build().unwrap().block; - client.import(BlockOrigin::Own, a1.clone()).unwrap(); - - let mut b1 = client.new_block_at( - &BlockId::Number(0), - Default::default(), - false, - ).unwrap(); - b1.push_transfer(Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Ferdie.into(), - amount: 50, - nonce: 0, - }).unwrap(); - let b1 = b1.build().unwrap().block; - // Reorg to B1 - client.import_as_best(BlockOrigin::Own, b1.clone()).unwrap(); - - assert_eq!(950, current_balance(&client)); - let mut a2 = client.new_block_at( - &BlockId::Hash(a1.hash()), - Default::default(), - false, - ).unwrap(); - a2.push_transfer(Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Charlie.into(), - amount: 10, - nonce: 1, - }).unwrap(); - let a2 = a2.build().unwrap().block; - // Re-org to A2 - client.import_as_best(BlockOrigin::Own, a2).unwrap(); - assert_eq!(980, current_balance(&client)); - } - - #[test] - fn doesnt_import_blocks_that_revert_finality() { - let _ = env_logger::try_init(); - 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 mut client = TestClientBuilder::with_backend(backend).build(); - - // -> C1 - // / - // G -> A1 -> A2 - // \ - // -> B1 -> B2 -> B3 - - let a1 = client.new_block_at( - &BlockId::Number(0), - Default::default(), - false, - ).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, a1.clone()).unwrap(); - - let a2 = client.new_block_at( - &BlockId::Hash(a1.hash()), - Default::default(), - false, - ).unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, a2.clone()).unwrap(); - - let mut b1 = client.new_block_at(&BlockId::Number(0), Default::default(), false).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: 1, - nonce: 0, - }).unwrap(); - let b1 = b1.build().unwrap().block; - client.import(BlockOrigin::Own, b1.clone()).unwrap(); - - let b2 = client.new_block_at(&BlockId::Hash(b1.hash()), Default::default(), false) - .unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, b2.clone()).unwrap(); - - // prepare B3 before we finalize A2, because otherwise we won't be able to - // read changes trie configuration after A2 is finalized - let b3 = client.new_block_at(&BlockId::Hash(b2.hash()), Default::default(), false) - .unwrap().build().unwrap().block; - - // we will finalize A2 which should make it impossible to import a new - // B3 at the same height but that doesn't include it - ClientExt::finalize_block(&client, BlockId::Hash(a2.hash()), None).unwrap(); - - let import_err = client.import(BlockOrigin::Own, b3).err().unwrap(); - let expected_err = ConsensusError::ClientImport( - sp_blockchain::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(), false).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.build().unwrap().block; - - let import_err = client.import(BlockOrigin::Own, c1).err().unwrap(); - let expected_err = ConsensusError::ClientImport( - sp_blockchain::Error::NotInFinalizedChain.to_string() - ); - - assert_eq!( - import_err.to_string(), - expected_err.to_string(), - ); - } - - - #[test] - fn respects_block_rules() { - - fn run_test( - record_only: bool, - known_bad: &mut HashSet, - fork_rules: &mut Vec<(u64, H256)>, - ) { - let mut client = if record_only { - TestClientBuilder::new().build() - } else { - TestClientBuilder::new() - .set_block_rules( - Some(fork_rules.clone()), - Some(known_bad.clone()), - ) - .build() - }; - - let block_ok = client.new_block_at(&BlockId::Number(0), Default::default(), false) - .unwrap().build().unwrap().block; - - let params = BlockCheckParams { - hash: block_ok.hash().clone(), - number: 0, - parent_hash: block_ok.header().parent_hash().clone(), - allow_missing_state: false, - import_existing: false, - }; - assert_eq!(client.check_block(params).unwrap(), ImportResult::imported(false)); - - // this is 0x0d6d6612a10485370d9e085aeea7ec427fb3f34d961c6a816cdbe5cde2278864 - let mut block_not_ok = client.new_block_at(&BlockId::Number(0), Default::default(), false) - .unwrap(); - block_not_ok.push_storage_change(vec![0], Some(vec![1])).unwrap(); - let block_not_ok = block_not_ok.build().unwrap().block; - - let params = BlockCheckParams { - hash: block_not_ok.hash().clone(), - number: 0, - parent_hash: block_not_ok.header().parent_hash().clone(), - allow_missing_state: false, - import_existing: false, - }; - if record_only { - known_bad.insert(block_not_ok.hash()); - } else { - assert_eq!(client.check_block(params).unwrap(), ImportResult::KnownBad); - } - - // Now going to the fork - client.import_as_final(BlockOrigin::Own, block_ok).unwrap(); - - // And check good fork - let mut block_ok = client.new_block_at(&BlockId::Number(1), Default::default(), false) - .unwrap(); - block_ok.push_storage_change(vec![0], Some(vec![2])).unwrap(); - let block_ok = block_ok.build().unwrap().block; - - let params = BlockCheckParams { - hash: block_ok.hash().clone(), - number: 1, - parent_hash: block_ok.header().parent_hash().clone(), - allow_missing_state: false, - import_existing: false, - }; - if record_only { - fork_rules.push((1, block_ok.hash().clone())); - } - assert_eq!(client.check_block(params).unwrap(), ImportResult::imported(false)); - - // And now try bad fork - let mut block_not_ok = client.new_block_at(&BlockId::Number(1), Default::default(), false) - .unwrap(); - block_not_ok.push_storage_change(vec![0], Some(vec![3])).unwrap(); - let block_not_ok = block_not_ok.build().unwrap().block; - - let params = BlockCheckParams { - hash: block_not_ok.hash().clone(), - number: 1, - parent_hash: block_not_ok.header().parent_hash().clone(), - allow_missing_state: false, - import_existing: false, - }; - - if !record_only { - assert_eq!(client.check_block(params).unwrap(), ImportResult::KnownBad); - } - } - - let mut known_bad = HashSet::new(); - let mut fork_rules = Vec::new(); - - // records what bad_blocks and fork_blocks hashes should be - run_test(true, &mut known_bad, &mut fork_rules); - - // enforces rules and actually makes assertions - run_test(false, &mut known_bad, &mut fork_rules); - } - - #[test] - fn returns_status_for_pruned_blocks() { - let _ = env_logger::try_init(); - let tmp = tempfile::tempdir().unwrap(); - - // set to prune after 1 block - // states - let backend = Arc::new(Backend::new( - DatabaseSettings { - state_cache_size: 1 << 20, - state_cache_child_ratio: None, - pruning: PruningMode::keep_blocks(1), - source: DatabaseSettingsSrc::Path { - path: tmp.path().into(), - cache_size: None, - } - }, - u64::max_value(), - ).unwrap()); - - let mut client = TestClientBuilder::with_backend(backend).build(); - - let a1 = client.new_block_at(&BlockId::Number(0), Default::default(), false) - .unwrap().build().unwrap().block; - - let mut b1 = client.new_block_at(&BlockId::Number(0), Default::default(), false).unwrap(); - - // b1 is created, but not imported - b1.push_transfer(Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Ferdie.into(), - amount: 1, - nonce: 0, - }).unwrap(); - let b1 = b1.build().unwrap().block; - - let check_block_a1 = BlockCheckParams { - hash: a1.hash().clone(), - number: 0, - parent_hash: a1.header().parent_hash().clone(), - allow_missing_state: false, - import_existing: false, - }; - - assert_eq!(client.check_block(check_block_a1.clone()).unwrap(), ImportResult::imported(false)); - assert_eq!(client.block_status(&BlockId::hash(check_block_a1.hash)).unwrap(), BlockStatus::Unknown); - - client.import_as_final(BlockOrigin::Own, a1.clone()).unwrap(); - - assert_eq!(client.check_block(check_block_a1.clone()).unwrap(), ImportResult::AlreadyInChain); - assert_eq!(client.block_status(&BlockId::hash(check_block_a1.hash)).unwrap(), BlockStatus::InChainWithState); - - let a2 = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default(), false) - .unwrap().build().unwrap().block; - client.import_as_final(BlockOrigin::Own, a2.clone()).unwrap(); - - let check_block_a2 = BlockCheckParams { - hash: a2.hash().clone(), - number: 1, - parent_hash: a1.header().parent_hash().clone(), - allow_missing_state: false, - import_existing: false, - }; - - assert_eq!(client.check_block(check_block_a1.clone()).unwrap(), ImportResult::AlreadyInChain); - assert_eq!(client.block_status(&BlockId::hash(check_block_a1.hash)).unwrap(), BlockStatus::InChainPruned); - assert_eq!(client.check_block(check_block_a2.clone()).unwrap(), ImportResult::AlreadyInChain); - assert_eq!(client.block_status(&BlockId::hash(check_block_a2.hash)).unwrap(), BlockStatus::InChainWithState); - - let a3 = client.new_block_at(&BlockId::Hash(a2.hash()), Default::default(), false) - .unwrap().build().unwrap().block; - - client.import_as_final(BlockOrigin::Own, a3.clone()).unwrap(); - let check_block_a3 = BlockCheckParams { - hash: a3.hash().clone(), - number: 2, - parent_hash: a2.header().parent_hash().clone(), - allow_missing_state: false, - import_existing: false, - }; - - // a1 and a2 are both pruned at this point - assert_eq!(client.check_block(check_block_a1.clone()).unwrap(), ImportResult::AlreadyInChain); - assert_eq!(client.block_status(&BlockId::hash(check_block_a1.hash)).unwrap(), BlockStatus::InChainPruned); - assert_eq!(client.check_block(check_block_a2.clone()).unwrap(), ImportResult::AlreadyInChain); - assert_eq!(client.block_status(&BlockId::hash(check_block_a2.hash)).unwrap(), BlockStatus::InChainPruned); - assert_eq!(client.check_block(check_block_a3.clone()).unwrap(), ImportResult::AlreadyInChain); - assert_eq!(client.block_status(&BlockId::hash(check_block_a3.hash)).unwrap(), BlockStatus::InChainWithState); - - let mut check_block_b1 = BlockCheckParams { - hash: b1.hash().clone(), - number: 0, - parent_hash: b1.header().parent_hash().clone(), - allow_missing_state: false, - import_existing: false, - }; - assert_eq!(client.check_block(check_block_b1.clone()).unwrap(), ImportResult::MissingState); - check_block_b1.allow_missing_state = true; - assert_eq!(client.check_block(check_block_b1.clone()).unwrap(), ImportResult::imported(false)); - check_block_b1.parent_hash = H256::random(); - assert_eq!(client.check_block(check_block_b1.clone()).unwrap(), ImportResult::UnknownParent); - } - - #[test] - fn imports_blocks_with_changes_tries_config_change() { - // create client with initial 4^2 configuration - let mut client = TestClientBuilder::with_default_backend() - .changes_trie_config(Some(ChangesTrieConfiguration { - digest_interval: 4, - digest_levels: 2, - })).build(); - - // =================================================================== - // blocks 1,2,3,4,5,6,7,8,9,10 are empty - // block 11 changes the key - // block 12 is the L1 digest that covers this change - // blocks 13,14,15,16,17,18,19,20,21,22 are empty - // block 23 changes the configuration to 5^1 AND is skewed digest - // =================================================================== - // blocks 24,25 are changing the key - // block 26 is empty - // block 27 changes the key - // block 28 is the L1 digest (NOT SKEWED!!!) that covers changes AND changes configuration to 3^1 - // =================================================================== - // block 29 is empty - // block 30 changes the key - // block 31 is L1 digest that covers this change - // =================================================================== - (1..11).for_each(|number| { - let block = client.new_block_at(&BlockId::Number(number - 1), Default::default(), false) - .unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, block).unwrap(); - }); - (11..12).for_each(|number| { - let mut block = client.new_block_at(&BlockId::Number(number - 1), Default::default(), false).unwrap(); - block.push_storage_change(vec![42], Some(number.to_le_bytes().to_vec())).unwrap(); - let block = block.build().unwrap().block; - client.import(BlockOrigin::Own, block).unwrap(); - }); - (12..23).for_each(|number| { - let block = client.new_block_at(&BlockId::Number(number - 1), Default::default(), false) - .unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, block).unwrap(); - }); - (23..24).for_each(|number| { - let mut block = client.new_block_at(&BlockId::Number(number - 1), Default::default(), false).unwrap(); - block.push_changes_trie_configuration_update(Some(ChangesTrieConfiguration { - digest_interval: 5, - digest_levels: 1, - })).unwrap(); - let block = block.build().unwrap().block; - client.import(BlockOrigin::Own, block).unwrap(); - }); - (24..26).for_each(|number| { - let mut block = client.new_block_at(&BlockId::Number(number - 1), Default::default(), false).unwrap(); - block.push_storage_change(vec![42], Some(number.to_le_bytes().to_vec())).unwrap(); - let block = block.build().unwrap().block; - client.import(BlockOrigin::Own, block).unwrap(); - }); - (26..27).for_each(|number| { - let block = client.new_block_at(&BlockId::Number(number - 1), Default::default(), false) - .unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, block).unwrap(); - }); - (27..28).for_each(|number| { - let mut block = client.new_block_at(&BlockId::Number(number - 1), Default::default(), false).unwrap(); - block.push_storage_change(vec![42], Some(number.to_le_bytes().to_vec())).unwrap(); - let block = block.build().unwrap().block; - client.import(BlockOrigin::Own, block).unwrap(); - }); - (28..29).for_each(|number| { - let mut block = client.new_block_at(&BlockId::Number(number - 1), Default::default(), false).unwrap(); - block.push_changes_trie_configuration_update(Some(ChangesTrieConfiguration { - digest_interval: 3, - digest_levels: 1, - })).unwrap(); - let block = block.build().unwrap().block; - client.import(BlockOrigin::Own, block).unwrap(); - }); - (29..30).for_each(|number| { - let block = client.new_block_at(&BlockId::Number(number - 1), Default::default(), false) - .unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, block).unwrap(); - }); - (30..31).for_each(|number| { - let mut block = client.new_block_at(&BlockId::Number(number - 1), Default::default(), false).unwrap(); - block.push_storage_change(vec![42], Some(number.to_le_bytes().to_vec())).unwrap(); - let block = block.build().unwrap().block; - client.import(BlockOrigin::Own, block).unwrap(); - }); - (31..32).for_each(|number| { - let block = client.new_block_at(&BlockId::Number(number - 1), Default::default(), false) - .unwrap().build().unwrap().block; - client.import(BlockOrigin::Own, block).unwrap(); - }); - - // now check that configuration cache works - assert_eq!( - client.key_changes(1, BlockId::Number(31), None, &StorageKey(vec![42])).unwrap(), - vec![(30, 0), (27, 0), (25, 0), (24, 0), (11, 0)] - ); - } - - #[test] - fn storage_keys_iter_prefix_and_start_key_works() { - let client = substrate_test_runtime_client::new(); - - let prefix = StorageKey(hex!("3a").to_vec()); - - let res: Vec<_> = client.storage_keys_iter(&BlockId::Number(0), Some(&prefix), None) - .unwrap() - .map(|x| x.0) - .collect(); - assert_eq!(res, [hex!("3a636f6465").to_vec(), hex!("3a686561707061676573").to_vec()]); - - let res: Vec<_> = client.storage_keys_iter(&BlockId::Number(0), Some(&prefix), Some(&StorageKey(hex!("3a636f6465").to_vec()))) - .unwrap() - .map(|x| x.0) - .collect(); - assert_eq!(res, [hex!("3a686561707061676573").to_vec()]); - - let res: Vec<_> = client.storage_keys_iter(&BlockId::Number(0), Some(&prefix), Some(&StorageKey(hex!("3a686561707061676573").to_vec()))) - .unwrap() - .map(|x| x.0) - .collect(); - assert_eq!(res, Vec::>::new()); - } - - #[test] - fn storage_keys_iter_works() { - let client = substrate_test_runtime_client::new(); - - let prefix = StorageKey(hex!("").to_vec()); - - let res: Vec<_> = client.storage_keys_iter(&BlockId::Number(0), Some(&prefix), None) - .unwrap() - .take(2) - .map(|x| x.0) - .collect(); - assert_eq!(res, [hex!("0befda6e1ca4ef40219d588a727f1271").to_vec(), hex!("3a636f6465").to_vec()]); - - let res: Vec<_> = client.storage_keys_iter(&BlockId::Number(0), Some(&prefix), Some(&StorageKey(hex!("3a636f6465").to_vec()))) - .unwrap() - .take(3) - .map(|x| x.0) - .collect(); - assert_eq!(res, [ - hex!("3a686561707061676573").to_vec(), - hex!("6644b9b8bc315888ac8e41a7968dc2b4141a5403c58acdf70b7e8f7e07bf5081").to_vec(), - hex!("79c07e2b1d2e2abfd4855b936617eeff5e0621c4869aa60c02be9adcc98a0d1d").to_vec(), - ]); - - let res: Vec<_> = client.storage_keys_iter(&BlockId::Number(0), Some(&prefix), Some(&StorageKey(hex!("79c07e2b1d2e2abfd4855b936617eeff5e0621c4869aa60c02be9adcc98a0d1d").to_vec()))) - .unwrap() - .take(1) - .map(|x| x.0) - .collect(); - assert_eq!(res, [hex!("cf722c0832b5231d35e29f319ff27389f5032bfc7bfc3ba5ed7839f2042fb99f").to_vec()]); - } - - #[test] - fn cleans_up_closed_notification_sinks_on_block_import() { - use substrate_test_runtime_client::GenesisInit; - - // NOTE: we need to build the client here instead of using the client - // provided by test_runtime_client otherwise we can't access the private - // `import_notification_sinks` and `finality_notification_sinks` fields. - let mut client = - new_in_mem::< - _, - substrate_test_runtime_client::runtime::Block, - _, - substrate_test_runtime_client::runtime::RuntimeApi - >( - substrate_test_runtime_client::new_native_executor(), - &substrate_test_runtime_client::GenesisParameters::default().genesis_storage(), - None, - None, - sp_core::tasks::executor(), - ) - .unwrap(); - - type TestClient = Client< - in_mem::Backend, - LocalCallExecutor, sc_executor::NativeExecutor>, - substrate_test_runtime_client::runtime::Block, - substrate_test_runtime_client::runtime::RuntimeApi, - >; - - let import_notif1 = client.import_notification_stream(); - let import_notif2 = client.import_notification_stream(); - let finality_notif1 = client.finality_notification_stream(); - let finality_notif2 = client.finality_notification_stream(); - - // for some reason I can't seem to use `ClientBlockImportExt` - let bake_and_import_block = |client: &mut TestClient, origin| { - let block = client - .new_block(Default::default()) - .unwrap() - .build() - .unwrap() - .block; - - let (header, extrinsics) = block.deconstruct(); - let mut import = BlockImportParams::new(origin, header); - import.body = Some(extrinsics); - import.fork_choice = Some(ForkChoiceStrategy::LongestChain); - client.import_block(import, Default::default()).unwrap(); - }; - - // after importing a block we should still have 4 notification sinks - // (2 import + 2 finality) - bake_and_import_block(&mut client, BlockOrigin::Own); - assert_eq!(client.import_notification_sinks.lock().len(), 2); - assert_eq!(client.finality_notification_sinks.lock().len(), 2); - - // if we drop one import notification receiver and one finality - // notification receiver - drop(import_notif2); - drop(finality_notif2); - - // the sinks should be cleaned up after block import - bake_and_import_block(&mut client, BlockOrigin::Own); - assert_eq!(client.import_notification_sinks.lock().len(), 1); - assert_eq!(client.finality_notification_sinks.lock().len(), 1); - - // the same thing should happen if block import happens during initial - // sync - drop(import_notif1); - drop(finality_notif1); - - bake_and_import_block(&mut client, BlockOrigin::NetworkInitialSync); - assert_eq!(client.import_notification_sinks.lock().len(), 0); - assert_eq!(client.finality_notification_sinks.lock().len(), 0); - } -} diff --git a/client/src/genesis.rs b/client/src/genesis.rs deleted file mode 100644 index 2c84ff1e4331af066d43e314d31059740adcce6e..0000000000000000000000000000000000000000 --- a/client/src/genesis.rs +++ /dev/null @@ -1,256 +0,0 @@ -// Copyright 2017-2020 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 . - -//! Tool for creating the genesis block. - -use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Hash as HashT, Zero}; - -/// Create a genesis block, given the initial storage. -pub fn construct_genesis_block< - Block: BlockT -> ( - state_root: Block::Hash -) -> Block { - let extrinsics_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( - Vec::new(), - ); - - Block::new( - <::Header as HeaderT>::new( - Zero::zero(), - extrinsics_root, - state_root, - Default::default(), - Default::default() - ), - Default::default() - ) -} - -#[cfg(test)] -mod tests { - use codec::{Encode, Decode, Joiner}; - use sc_executor::native_executor_instance; - use sp_state_machine::{ - StateMachine, OverlayedChanges, ExecutionStrategy, - InMemoryBackend, - }; - use substrate_test_runtime_client::{ - runtime::genesismap::{GenesisConfig, insert_genesis_block}, - runtime::{Hash, Transfer, Block, BlockNumber, Header, Digest}, - AccountKeyring, Sr25519Keyring, - }; - use sp_runtime::traits::BlakeTwo256; - use sp_core::tasks::executor as tasks_executor; - use hex_literal::*; - - native_executor_instance!( - Executor, - substrate_test_runtime_client::runtime::api::dispatch, - substrate_test_runtime_client::runtime::native_version, - ); - - fn executor() -> sc_executor::NativeExecutor { - sc_executor::NativeExecutor::new(sc_executor::WasmExecutionMethod::Interpreted, None, 8) - } - - fn construct_block( - backend: &InMemoryBackend, - number: BlockNumber, - parent_hash: Hash, - state_root: Hash, - txs: Vec - ) -> (Vec, Hash) { - use sp_trie::{TrieConfiguration, trie_types::Layout}; - - let transactions = txs.into_iter().map(|tx| tx.into_signed_tx()).collect::>(); - - let iter = transactions.iter().map(Encode::encode); - let extrinsics_root = Layout::::ordered_trie_root(iter).into(); - - let mut header = Header { - parent_hash, - number, - state_root, - extrinsics_root, - digest: Digest { logs: vec![], }, - }; - let hash = header.hash(); - let mut overlay = OverlayedChanges::default(); - let backend_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&backend); - let runtime_code = backend_runtime_code.runtime_code().expect("Code is part of the backend"); - - StateMachine::new( - backend, - sp_state_machine::disabled_changes_trie_state::<_, u64>(), - &mut overlay, - &executor(), - "Core_initialize_block", - &header.encode(), - Default::default(), - &runtime_code, - tasks_executor(), - ).execute( - ExecutionStrategy::NativeElseWasm, - ).unwrap(); - - for tx in transactions.iter() { - StateMachine::new( - backend, - sp_state_machine::disabled_changes_trie_state::<_, u64>(), - &mut overlay, - &executor(), - "BlockBuilder_apply_extrinsic", - &tx.encode(), - Default::default(), - &runtime_code, - tasks_executor(), - ).execute( - ExecutionStrategy::NativeElseWasm, - ).unwrap(); - } - - let ret_data = StateMachine::new( - backend, - sp_state_machine::disabled_changes_trie_state::<_, u64>(), - &mut overlay, - &executor(), - "BlockBuilder_finalize_block", - &[], - Default::default(), - &runtime_code, - tasks_executor(), - ).execute( - ExecutionStrategy::NativeElseWasm, - ).unwrap(); - header = Header::decode(&mut &ret_data[..]).unwrap(); - - (vec![].and(&Block { header, extrinsics: transactions }), hash) - } - - fn block1(genesis_hash: Hash, backend: &InMemoryBackend) -> (Vec, Hash) { - construct_block( - backend, - 1, - genesis_hash, - hex!("25e5b37074063ab75c889326246640729b40d0c86932edc527bc80db0e04fe5c").into(), - vec![Transfer { - from: AccountKeyring::One.into(), - to: AccountKeyring::Two.into(), - amount: 69, - nonce: 0, - }] - ) - } - - #[test] - fn construct_genesis_should_work_with_native() { - let mut storage = GenesisConfig::new( - None, - vec![Sr25519Keyring::One.public().into(), Sr25519Keyring::Two.public().into()], - vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], - 1000, - None, - Default::default(), - ).genesis_map(); - let genesis_hash = insert_genesis_block(&mut storage); - - let backend = InMemoryBackend::from(storage); - let (b1data, _b1hash) = block1(genesis_hash, &backend); - let backend_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&backend); - let runtime_code = backend_runtime_code.runtime_code().expect("Code is part of the backend"); - - let mut overlay = OverlayedChanges::default(); - let _ = StateMachine::new( - &backend, - sp_state_machine::disabled_changes_trie_state::<_, u64>(), - &mut overlay, - &executor(), - "Core_execute_block", - &b1data, - Default::default(), - &runtime_code, - tasks_executor(), - ).execute( - ExecutionStrategy::NativeElseWasm, - ).unwrap(); - } - - #[test] - fn construct_genesis_should_work_with_wasm() { - let mut storage = GenesisConfig::new(None, - vec![Sr25519Keyring::One.public().into(), Sr25519Keyring::Two.public().into()], - vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], - 1000, - None, - Default::default(), - ).genesis_map(); - let genesis_hash = insert_genesis_block(&mut storage); - - let backend = InMemoryBackend::from(storage); - let (b1data, _b1hash) = block1(genesis_hash, &backend); - let backend_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&backend); - let runtime_code = backend_runtime_code.runtime_code().expect("Code is part of the backend"); - - let mut overlay = OverlayedChanges::default(); - let _ = StateMachine::new( - &backend, - sp_state_machine::disabled_changes_trie_state::<_, u64>(), - &mut overlay, - &executor(), - "Core_execute_block", - &b1data, - Default::default(), - &runtime_code, - tasks_executor(), - ).execute( - ExecutionStrategy::AlwaysWasm, - ).unwrap(); - } - - #[test] - fn construct_genesis_with_bad_transaction_should_panic() { - let mut storage = GenesisConfig::new(None, - vec![Sr25519Keyring::One.public().into(), Sr25519Keyring::Two.public().into()], - vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], - 68, - None, - Default::default(), - ).genesis_map(); - let genesis_hash = insert_genesis_block(&mut storage); - - let backend = InMemoryBackend::from(storage); - let (b1data, _b1hash) = block1(genesis_hash, &backend); - let backend_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&backend); - let runtime_code = backend_runtime_code.runtime_code().expect("Code is part of the backend"); - - let mut overlay = OverlayedChanges::default(); - let r = StateMachine::new( - &backend, - sp_state_machine::disabled_changes_trie_state::<_, u64>(), - &mut overlay, - &executor(), - "Core_execute_block", - &b1data, - Default::default(), - &runtime_code, - tasks_executor(), - ).execute( - ExecutionStrategy::NativeElseWasm, - ); - assert!(r.is_err()); - } -} diff --git a/client/src/lib.rs b/client/src/lib.rs deleted file mode 100644 index 20a3ed058aa7cb5fd562e87e03aac6ae078d40ab..0000000000000000000000000000000000000000 --- a/client/src/lib.rs +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2017-2020 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 Client and associated logic. -//! -//! The [`Client`] is one of the most important components of Substrate. It mainly comprises two -//! parts: -//! -//! - A database containing the blocks and chain state, generally referred to as -//! the [`Backend`](sc_client_api::backend::Backend). -//! - A runtime environment, generally referred to as the [`Executor`](CallExecutor). -//! -//! # Initialization -//! -//! Creating a [`Client`] is done by calling the `new` method and passing to it a -//! [`Backend`](sc_client_api::backend::Backend) and an [`Executor`](CallExecutor). -//! -//! The former is typically provided by the `sc-client-db` crate. -//! -//! The latter typically requires passing one of: -//! -//! - A [`LocalCallExecutor`] running the runtime locally. -//! - A [`RemoteCallExecutor`](light::call_executor::RemoteCallRequest) that will ask a -//! third-party to perform the executions. -//! - A [`RemoteOrLocalCallExecutor`](light::call_executor::RemoteOrLocalCallExecutor), combination -//! of the two. -//! -//! Additionally, the fourth generic parameter of the `Client` is a marker type representing -//! the ways in which the runtime can interface with the outside. Any code that builds a `Client` -//! is responsible for putting the right marker. -//! -//! ## Example -//! -//! ``` -//! use std::sync::Arc; -//! use sc_client::{Client, in_mem::Backend, LocalCallExecutor}; -//! use sp_runtime::Storage; -//! use sc_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 -//! // compiling a runtime. In a typical use-case, these types would have been to be generated -//! // from your runtime. -//! use substrate_test_runtime_client::{LocalExecutor, runtime::Block, runtime::RuntimeApi}; -//! -//! let backend = Arc::new(Backend::::new()); -//! let client = Client::<_, _, _, RuntimeApi>::new( -//! backend.clone(), -//! LocalCallExecutor::new( -//! backend.clone(), -//! NativeExecutor::::new(WasmExecutionMethod::Interpreted, None, 8), -//! sp_core::tasks::executor(), -//! ), -//! // This parameter provides the storage for the chain genesis. -//! &::default(), -//! Default::default(), -//! Default::default(), -//! Default::default(), -//! None, -//! ); -//! ``` -//! - -#![warn(missing_docs)] -#![recursion_limit="128"] - -pub mod cht; -pub mod in_mem; -pub mod genesis; -pub mod light; -pub mod leaves; -mod call_executor; -mod client; -mod block_rules; - -pub use sc_client_api::{ - blockchain, - blockchain::well_known_cache_keys, - blockchain::Info as ChainInfo, - notifications::{StorageEventStream, StorageChangeSet}, - call_executor::CallExecutor, - utils, -}; -pub use crate::{ - call_executor::LocalCallExecutor, - client::{ - new_with_backend, - new_in_mem, - BlockBackend, ImportNotifications, FinalityNotifications, BlockchainEvents, LockImportRun, - BlockImportNotification, Client, ClientInfo, ExecutionStrategies, FinalityNotification, - LongestChain, BlockOf, ProvideUncles, BadBlocks, ForkBlocks, apply_aux, - }, - leaves::LeafSet, -}; -pub use sp_state_machine::{ExecutionStrategy, StorageProof, StateMachine}; diff --git a/client/src/light/fetcher.rs b/client/src/light/fetcher.rs deleted file mode 100644 index 0ae0e68e0c8781d0a08e84aceeea40817a1d8873..0000000000000000000000000000000000000000 --- a/client/src/light/fetcher.rs +++ /dev/null @@ -1,833 +0,0 @@ -// Copyright 2017-2020 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 . - -//! Light client data fetcher. Fetches requested data from remote full nodes. - -use std::sync::Arc; -use std::collections::{BTreeMap, HashMap}; -use std::marker::PhantomData; - -use hash_db::{HashDB, Hasher, EMPTY_PREFIX}; -use codec::{Decode, Encode}; -use sp_core::{convert_hash, traits::CodeExecutor}; -use sp_runtime::traits::{ - Block as BlockT, Header as HeaderT, Hash, HashFor, NumberFor, - AtLeast32Bit, CheckedConversion, -}; -use sp_state_machine::{ - ChangesTrieRootsStorage, ChangesTrieAnchorBlockId, ChangesTrieConfigurationRange, - InMemoryChangesTrieStorage, TrieBackend, read_proof_check, key_changes_proof_check_with_db, - read_child_proof_check, CloneableSpawn, -}; -pub use sp_state_machine::StorageProof; -use sp_blockchain::{Error as ClientError, Result as ClientResult}; - -use crate::cht; -pub use sc_client_api::{ - light::{ - RemoteCallRequest, RemoteHeaderRequest, RemoteReadRequest, RemoteReadChildRequest, - RemoteChangesRequest, ChangesProof, RemoteBodyRequest, Fetcher, FetchChecker, - Storage as BlockchainStorage, - }, -}; -use crate::light::blockchain::{Blockchain}; -use crate::light::call_executor::check_execution_proof; - -/// Remote data checker. -pub struct LightDataChecker> { - blockchain: Arc>, - executor: E, - spawn_handle: Box, - _hasher: PhantomData<(B, H)>, -} - -impl> LightDataChecker { - /// Create new light data checker. - pub fn new(blockchain: Arc>, executor: E, spawn_handle: Box) -> Self { - Self { - blockchain, executor, spawn_handle, _hasher: PhantomData - } - } - - /// Check remote changes query proof assuming that CHT-s are of given size. - fn check_changes_proof_with_cht_size( - &self, - request: &RemoteChangesRequest, - remote_proof: ChangesProof, - cht_size: NumberFor, - ) -> ClientResult, u32)>> - where - H: Hasher, - H::Out: Ord + codec::Codec, - { - // since we need roots of all changes tries for the range begin..max - // => remote node can't use max block greater that one that we have passed - if remote_proof.max_block > request.max_block.0 || remote_proof.max_block < request.last_block.0 { - return Err(ClientError::ChangesTrieAccessFailed(format!( - "Invalid max_block used by the remote node: {}. Local: {}..{}..{}", - remote_proof.max_block, request.first_block.0, request.last_block.0, request.max_block.0, - )).into()); - } - - // check if remote node has responded with extra changes trie roots proofs - // all changes tries roots must be in range [request.first_block.0; request.tries_roots.0) - let is_extra_first_root = remote_proof.roots.keys().next() - .map(|first_root| *first_root < request.first_block.0 - || *first_root >= request.tries_roots.0) - .unwrap_or(false); - let is_extra_last_root = remote_proof.roots.keys().next_back() - .map(|last_root| *last_root >= request.tries_roots.0) - .unwrap_or(false); - if is_extra_first_root || is_extra_last_root { - return Err(ClientError::ChangesTrieAccessFailed(format!( - "Extra changes tries roots proofs provided by the remote node: [{:?}..{:?}]. Expected in range: [{}; {})", - remote_proof.roots.keys().next(), remote_proof.roots.keys().next_back(), - request.first_block.0, request.tries_roots.0, - )).into()); - } - - // if request has been composed when some required headers were already pruned - // => remote node has sent us CHT-based proof of required changes tries roots - // => check that this proof is correct before proceeding with changes proof - let remote_max_block = remote_proof.max_block; - let remote_roots = remote_proof.roots; - let remote_roots_proof = remote_proof.roots_proof; - let remote_proof = remote_proof.proof; - if !remote_roots.is_empty() { - self.check_changes_tries_proof( - cht_size, - &remote_roots, - remote_roots_proof, - )?; - } - - // and now check the key changes proof + get the changes - let mut result = Vec::new(); - let proof_storage = InMemoryChangesTrieStorage::with_proof(remote_proof); - for config_range in &request.changes_trie_configs { - let result_range = key_changes_proof_check_with_db::( - ChangesTrieConfigurationRange { - config: config_range.config.as_ref().ok_or(ClientError::ChangesTriesNotSupported)?, - zero: config_range.zero.0, - end: config_range.end.map(|(n, _)| n), - }, - &RootsStorage { - roots: (request.tries_roots.0, &request.tries_roots.2), - prev_roots: &remote_roots, - }, - &proof_storage, - request.first_block.0, - &ChangesTrieAnchorBlockId { - hash: convert_hash(&request.last_block.1), - number: request.last_block.0, - }, - remote_max_block, - request.storage_key.as_ref().map(Vec::as_slice), - &request.key) - .map_err(|err| ClientError::ChangesTrieAccessFailed(err))?; - result.extend(result_range); - } - - Ok(result) - } - - /// Check CHT-based proof for changes tries roots. - fn check_changes_tries_proof( - &self, - cht_size: NumberFor, - remote_roots: &BTreeMap, B::Hash>, - remote_roots_proof: StorageProof, - ) -> ClientResult<()> - where - H: Hasher, - H::Out: Ord + codec::Codec, - { - // all the checks are sharing the same storage - let storage = remote_roots_proof.into_memory_db(); - - // remote_roots.keys() are sorted => we can use this to group changes tries roots - // that are belongs to the same CHT - let blocks = remote_roots.keys().cloned(); - cht::for_each_cht_group::(cht_size, blocks, |mut storage, _, cht_blocks| { - // get local changes trie CHT root for given CHT - // it should be there, because it is never pruned AND request has been composed - // when required header has been pruned (=> replaced with CHT) - let first_block = cht_blocks.first().cloned() - .expect("for_each_cht_group never calls callback with empty groups"); - let local_cht_root = self.blockchain.storage().changes_trie_cht_root(cht_size, first_block)? - .ok_or(ClientError::InvalidCHTProof)?; - - // check changes trie root for every block within CHT range - for block in cht_blocks { - // check if the proofs storage contains the root - // normally this happens in when the proving backend is created, but since - // we share the storage for multiple checks, do it here - let mut cht_root = H::Out::default(); - cht_root.as_mut().copy_from_slice(local_cht_root.as_ref()); - if !storage.contains(&cht_root, EMPTY_PREFIX) { - return Err(ClientError::InvalidCHTProof.into()); - } - - // check proof for single changes trie root - let proving_backend = TrieBackend::new(storage, cht_root); - let remote_changes_trie_root = remote_roots[&block]; - cht::check_proof_on_proving_backend::( - local_cht_root, - block, - remote_changes_trie_root, - &proving_backend, - )?; - - // and return the storage to use in following checks - storage = proving_backend.into_storage(); - } - - Ok(storage) - }, storage) - } -} - -impl FetchChecker for LightDataChecker - where - Block: BlockT, - E: CodeExecutor + Clone + 'static, - H: Hasher, - H::Out: Ord + codec::Codec + 'static, - S: BlockchainStorage, -{ - fn check_header_proof( - &self, - request: &RemoteHeaderRequest, - remote_header: Option, - remote_proof: StorageProof, - ) -> ClientResult { - let remote_header = remote_header.ok_or_else(|| - ClientError::from(ClientError::InvalidCHTProof))?; - let remote_header_hash = remote_header.hash(); - cht::check_proof::( - request.cht_root, - request.block, - remote_header_hash, - remote_proof, - ).map(|_| remote_header) - } - - fn check_read_proof( - &self, - request: &RemoteReadRequest, - 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: StorageProof, - ) -> ClientResult, Option>>> { - read_child_proof_check::( - convert_hash(request.header.state_root()), - remote_proof, - &request.storage_key, - request.keys.iter(), - ).map_err(Into::into) - } - - fn check_execution_proof( - &self, - request: &RemoteCallRequest, - remote_proof: StorageProof, - ) -> ClientResult> { - check_execution_proof::<_, _, H>( - &self.executor, - self.spawn_handle.clone(), - request, - remote_proof, - ) - } - - fn check_changes_proof( - &self, - request: &RemoteChangesRequest, - remote_proof: ChangesProof - ) -> ClientResult, u32)>> { - self.check_changes_proof_with_cht_size(request, remote_proof, cht::size()) - } - - fn check_body_proof( - &self, - request: &RemoteBodyRequest, - body: Vec - ) -> ClientResult> { - // TODO: #2621 - let extrinsics_root = HashFor::::ordered_trie_root( - body.iter().map(Encode::encode).collect(), - ); - if *request.header.extrinsics_root() == extrinsics_root { - Ok(body) - } else { - Err(format!("RemoteBodyRequest: invalid extrinsics root expected: {} but got {}", - *request.header.extrinsics_root(), - extrinsics_root, - ).into()) - } - - } -} - -/// A view of BTreeMap as a changes trie roots storage. -struct RootsStorage<'a, Number: AtLeast32Bit, Hash: 'a> { - roots: (Number, &'a [Hash]), - prev_roots: &'a BTreeMap, -} - -impl<'a, H, Number, Hash> ChangesTrieRootsStorage for RootsStorage<'a, Number, Hash> - where - H: Hasher, - Number: std::fmt::Display + std::hash::Hash + Clone + AtLeast32Bit + Encode + Decode + Send + Sync + 'static, - Hash: 'a + Send + Sync + Clone + AsRef<[u8]>, -{ - fn build_anchor( - &self, - _hash: H::Out, - ) -> Result, String> { - Err("build_anchor is only called when building block".into()) - } - - fn root( - &self, - _anchor: &ChangesTrieAnchorBlockId, - block: Number, - ) -> Result, String> { - // we can't ask for roots from parallel forks here => ignore anchor - let root = if block < self.roots.0 { - self.prev_roots.get(&Number::unique_saturated_from(block)).cloned() - } else { - let index: Option = block.checked_sub(&self.roots.0).and_then(|index| index.checked_into()); - match index { - Some(index) => self.roots.1.get(index as usize).cloned(), - None => None, - } - }; - - Ok(root.map(|root| { - let mut hasher_root: H::Out = Default::default(); - hasher_root.as_mut().copy_from_slice(root.as_ref()); - hasher_root - })) - } -} - -#[cfg(test)] -pub mod tests { - use codec::Decode; - use crate::client::tests::prepare_client_with_key_changes; - use sc_executor::{NativeExecutor, WasmExecutionMethod}; - use sp_blockchain::Error as ClientError; - use sc_client_api::backend::NewBlockState; - use substrate_test_runtime_client::{ - blockchain::HeaderBackend, AccountKeyring, ClientBlockImportExt, - runtime::{self, Hash, Block, Header, Extrinsic}, - tasks_executor, - }; - use sp_consensus::BlockOrigin; - - use crate::in_mem::Blockchain as InMemoryBlockchain; - use crate::light::fetcher::{FetchChecker, LightDataChecker, RemoteHeaderRequest}; - use crate::light::blockchain::tests::{DummyStorage, DummyBlockchain}; - use sp_core::{blake2_256, ChangesTrieConfiguration, H256}; - use sp_core::storage::{well_known_keys, StorageKey, ChildInfo}; - use sp_runtime::{generic::BlockId, traits::BlakeTwo256}; - use sp_state_machine::Backend; - use super::*; - use sc_client_api::{StorageProvider, ProofProvider}; - use sc_block_builder::BlockBuilderProvider; - - const CHILD_INFO_1: ChildInfo<'static> = ChildInfo::new_default(b"unique_id_1"); - - type TestChecker = LightDataChecker< - NativeExecutor, - BlakeTwo256, - Block, - DummyStorage, - >; - - fn local_executor() -> NativeExecutor { - NativeExecutor::new(WasmExecutionMethod::Interpreted, None, 8) - } - - fn prepare_for_read_proof_check() -> (TestChecker, Header, StorageProof, u32) { - // prepare remote client - let remote_client = substrate_test_runtime_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(); - - // '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, - &mut std::iter::once(well_known_keys::HEAP_PAGES), - ).unwrap(); - - // check remote read proof locally - let local_storage = InMemoryBlockchain::::new(); - local_storage.insert( - remote_block_hash, - remote_block_header.clone(), - None, - None, - NewBlockState::Final, - ).unwrap(); - let local_checker = LightDataChecker::new( - Arc::new(DummyBlockchain::new(DummyStorage::new())), - local_executor(), - tasks_executor(), - ); - (local_checker, remote_block_header, remote_read_proof, heap_pages) - } - - fn prepare_for_read_child_proof_check() -> (TestChecker, Header, StorageProof, Vec) { - use substrate_test_runtime_client::DefaultTestClientBuilderExt; - use substrate_test_runtime_client::TestClientBuilderExt; - // prepare remote client - let remote_client = substrate_test_runtime_client::TestClientBuilder::new() - .add_extra_child_storage( - b":child_storage:default:child1".to_vec(), - CHILD_INFO_1, - 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()), - CHILD_INFO_1, - &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", - CHILD_INFO_1, - &mut std::iter::once("key1".as_bytes()), - ).unwrap(); - - // check locally - let local_storage = InMemoryBlockchain::::new(); - local_storage.insert( - remote_block_hash, - remote_block_header.clone(), - None, - None, - NewBlockState::Final, - ).unwrap(); - let local_checker = LightDataChecker::new( - Arc::new(DummyBlockchain::new(DummyStorage::new())), - local_executor(), - tasks_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 mut remote_client = substrate_test_runtime_client::new(); - let mut local_headers_hashes = Vec::new(); - for i in 0..4 { - let block = remote_client.new_block(Default::default()).unwrap().build().unwrap().block; - remote_client.import(BlockOrigin::Own, block).unwrap(); - local_headers_hashes.push( - remote_client.block_hash(i + 1) - .map_err(|_| ClientError::Backend("TestError".into())) - ); - } - - // 'fetch' header proof from remote node - let remote_block_id = BlockId::Number(1); - let (remote_block_header, remote_header_proof) = remote_client.header_proof_with_cht_size(&remote_block_id, 4).unwrap(); - - // check remote read proof locally - let local_storage = InMemoryBlockchain::::new(); - let local_cht_root = cht::compute_root::(4, 0, local_headers_hashes).unwrap(); - if insert_cht { - local_storage.insert_cht_root(1, local_cht_root); - } - let local_checker = LightDataChecker::new( - Arc::new(DummyBlockchain::new(DummyStorage::new())), - local_executor(), - tasks_executor(), - ); - (local_checker, local_cht_root, remote_block_header, remote_header_proof) - } - - fn header_with_computed_extrinsics_root(extrinsics: Vec) -> Header { - use sp_trie::{TrieConfiguration, trie_types::Layout}; - let iter = extrinsics.iter().map(Encode::encode); - let extrinsics_root = Layout::::ordered_trie_root(iter); - - // only care about `extrinsics_root` - Header::new(0, extrinsics_root, H256::zero(), H256::zero(), Default::default()) - } - - #[test] - fn storage_read_proof_is_generated_and_checked() { - let (local_checker, remote_block_header, remote_read_proof, heap_pages) = prepare_for_read_proof_check(); - assert_eq!((&local_checker as &dyn FetchChecker).check_read_proof(&RemoteReadRequest::
{ - block: remote_block_header.hash(), - header: remote_block_header, - keys: vec![well_known_keys::HEAP_PAGES.to_vec()], - retry_count: None, - }, 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(); - let child_infos = CHILD_INFO_1.info(); - 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(), - child_info: child_infos.0.to_vec(), - child_type: child_infos.1, - keys: vec![b"key1".to_vec()], - retry_count: None, - }, - remote_read_proof - ).unwrap().remove(b"key1".as_ref()).unwrap().unwrap(), result); - } - - #[test] - fn header_proof_is_generated_and_checked() { - let (local_checker, local_cht_root, remote_block_header, remote_header_proof) = prepare_for_header_proof_check(true); - assert_eq!((&local_checker as &dyn FetchChecker).check_header_proof(&RemoteHeaderRequest::
{ - cht_root: local_cht_root, - block: 1, - retry_count: None, - }, Some(remote_block_header.clone()), remote_header_proof).unwrap(), remote_block_header); - } - - #[test] - fn check_header_proof_fails_if_cht_root_is_invalid() { - let (local_checker, _, mut remote_block_header, remote_header_proof) = prepare_for_header_proof_check(true); - remote_block_header.number = 100; - assert!((&local_checker as &dyn FetchChecker).check_header_proof(&RemoteHeaderRequest::
{ - cht_root: Default::default(), - block: 1, - retry_count: None, - }, Some(remote_block_header.clone()), remote_header_proof).is_err()); - } - - #[test] - fn check_header_proof_fails_if_invalid_header_provided() { - let (local_checker, local_cht_root, mut remote_block_header, remote_header_proof) = prepare_for_header_proof_check(true); - remote_block_header.number = 100; - assert!((&local_checker as &dyn FetchChecker).check_header_proof(&RemoteHeaderRequest::
{ - cht_root: local_cht_root, - block: 1, - retry_count: None, - }, Some(remote_block_header.clone()), remote_header_proof).is_err()); - } - - #[test] - fn changes_proof_is_generated_and_checked_when_headers_are_not_pruned() { - let (remote_client, local_roots, test_cases) = prepare_client_with_key_changes(); - let local_checker = TestChecker::new( - Arc::new(DummyBlockchain::new(DummyStorage::new())), - local_executor(), - tasks_executor(), - ); - let local_checker = &local_checker as &dyn FetchChecker; - let max = remote_client.chain_info().best_number; - let max_hash = remote_client.chain_info().best_hash; - - for (index, (begin, end, key, expected_result)) in test_cases.into_iter().enumerate() { - let begin_hash = remote_client.block_hash(begin).unwrap().unwrap(); - let end_hash = remote_client.block_hash(end).unwrap().unwrap(); - - // '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, None, &key - ).unwrap(); - - // check proof on local client - let local_roots_range = local_roots.clone()[(begin - 1) as usize..].to_vec(); - let config = ChangesTrieConfiguration::new(4, 2); - let request = RemoteChangesRequest::
{ - changes_trie_configs: vec![sp_core::ChangesTrieConfigurationRange { - zero: (0, Default::default()), - end: None, - config: Some(config), - }], - first_block: (begin, begin_hash), - last_block: (end, end_hash), - 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 { - max_block: remote_proof.max_block, - proof: remote_proof.proof, - roots: remote_proof.roots, - roots_proof: remote_proof.roots_proof, - }).unwrap(); - - // ..and ensure that result is the same as on remote node - match local_result == expected_result { - true => (), - false => panic!(format!("Failed test {}: local = {:?}, expected = {:?}", - index, local_result, expected_result)), - } - } - } - - #[test] - fn changes_proof_is_generated_and_checked_when_headers_are_pruned() { - // we're testing this test case here: - // (1, 4, dave.clone(), vec![(4, 0), (1, 1), (1, 0)]), - let (remote_client, remote_roots, _) = prepare_client_with_key_changes(); - let dave = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec(); - let dave = StorageKey(dave); - - // 'fetch' changes proof from remote node: - // we're fetching changes for range b1..b4 - // we do not know changes trie roots before b3 (i.e. we only know b3+b4) - // but we have changes trie CHT root for b1...b4 - let b1 = remote_client.block_hash_from_id(&BlockId::Number(1)).unwrap().unwrap(); - 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, None, &dave, 4 - ).unwrap(); - - // prepare local checker, having a root of changes trie CHT#0 - let local_cht_root = cht::compute_root::(4, 0, remote_roots.iter().cloned().map(|ct| Ok(Some(ct)))).unwrap(); - let mut local_storage = DummyStorage::new(); - local_storage.changes_tries_cht_roots.insert(0, local_cht_root); - let local_checker = TestChecker::new( - Arc::new(DummyBlockchain::new(local_storage)), - local_executor(), - tasks_executor(), - ); - - // check proof on local client - let config = ChangesTrieConfiguration::new(4, 2); - let request = RemoteChangesRequest::
{ - changes_trie_configs: vec![sp_core::ChangesTrieConfigurationRange { - zero: (0, Default::default()), - end: None, - config: Some(config), - }], - first_block: (1, b1), - 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, - }; - let local_result = local_checker.check_changes_proof_with_cht_size(&request, ChangesProof { - max_block: remote_proof.max_block, - proof: remote_proof.proof, - roots: remote_proof.roots, - roots_proof: remote_proof.roots_proof, - }, 4).unwrap(); - - assert_eq!(local_result, vec![(4, 0), (1, 1), (1, 0)]); - } - - #[test] - fn check_changes_proof_fails_if_proof_is_wrong() { - let (remote_client, local_roots, test_cases) = prepare_client_with_key_changes(); - let local_checker = TestChecker::new( - Arc::new(DummyBlockchain::new(DummyStorage::new())), - local_executor(), - tasks_executor(), - ); - let local_checker = &local_checker as &dyn FetchChecker; - let max = remote_client.chain_info().best_number; - let max_hash = remote_client.chain_info().best_hash; - - let (begin, end, key, _) = test_cases[0].clone(); - let begin_hash = remote_client.block_hash(begin).unwrap().unwrap(); - let end_hash = remote_client.block_hash(end).unwrap().unwrap(); - - // '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, None, &key).unwrap(); - - let local_roots_range = local_roots.clone()[(begin - 1) as usize..].to_vec(); - let config = ChangesTrieConfiguration::new(4, 2); - let request = RemoteChangesRequest::
{ - changes_trie_configs: vec![sp_core::ChangesTrieConfigurationRange { - zero: (0, Default::default()), - end: None, - config: Some(config), - }], - first_block: (begin, begin_hash), - 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, - }; - - // check proof on local client using max from the future - assert!(local_checker.check_changes_proof(&request, ChangesProof { - max_block: remote_proof.max_block + 1, - proof: remote_proof.proof.clone(), - roots: remote_proof.roots.clone(), - roots_proof: remote_proof.roots_proof.clone(), - }).is_err()); - - // check proof on local client using broken proof - assert!(local_checker.check_changes_proof(&request, ChangesProof { - max_block: remote_proof.max_block, - proof: local_roots_range.clone().into_iter().map(|v| v.as_ref().to_vec()).collect(), - roots: remote_proof.roots, - roots_proof: remote_proof.roots_proof, - }).is_err()); - - // extra roots proofs are provided - assert!(local_checker.check_changes_proof(&request, ChangesProof { - max_block: remote_proof.max_block, - proof: remote_proof.proof.clone(), - roots: vec![(begin - 1, Default::default())].into_iter().collect(), - 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: StorageProof::empty(), - }).is_err()); - } - - #[test] - fn check_changes_tries_proof_fails_if_proof_is_wrong() { - // we're testing this test case here: - // (1, 4, dave.clone(), vec![(4, 0), (1, 1), (1, 0)]), - let (remote_client, remote_roots, _) = prepare_client_with_key_changes(); - let local_cht_root = cht::compute_root::( - 4, 0, remote_roots.iter().cloned().map(|ct| Ok(Some(ct)))).unwrap(); - let dave = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec(); - let dave = StorageKey(dave); - - // 'fetch' changes proof from remote node: - // we're fetching changes for range b1..b4 - // we do not know changes trie roots before b3 (i.e. we only know b3+b4) - // but we have changes trie CHT root for b1...b4 - let b1 = remote_client.block_hash_from_id(&BlockId::Number(1)).unwrap().unwrap(); - 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, 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())), - local_executor(), - tasks_executor(), - ); - assert!(local_checker.check_changes_tries_proof(4, &remote_proof.roots, - remote_proof.roots_proof.clone()).is_err()); - - // fails when proof is broken - let mut local_storage = DummyStorage::new(); - local_storage.changes_tries_cht_roots.insert(0, local_cht_root); - let local_checker = TestChecker::new( - Arc::new(DummyBlockchain::new(local_storage)), - local_executor(), - tasks_executor(), - ); - let result = local_checker.check_changes_tries_proof( - 4, &remote_proof.roots, StorageProof::empty() - ); - assert!(result.is_err()); - } - - #[test] - fn check_body_proof_faulty() { - let header = header_with_computed_extrinsics_root( - vec![Extrinsic::IncludeData(vec![1, 2, 3, 4])] - ); - let block = Block::new(header.clone(), Vec::new()); - - let local_checker = TestChecker::new( - Arc::new(DummyBlockchain::new(DummyStorage::new())), - local_executor(), - tasks_executor(), - ); - - let body_request = RemoteBodyRequest { - header: header.clone(), - retry_count: None, - }; - - assert!( - local_checker.check_body_proof(&body_request, block.extrinsics).is_err(), - "vec![1, 2, 3, 4] != vec![]" - ); - } - - #[test] - fn check_body_proof_of_same_data_should_succeed() { - let extrinsics = vec![Extrinsic::IncludeData(vec![1, 2, 3, 4, 5, 6, 7, 8, 255])]; - - let header = header_with_computed_extrinsics_root(extrinsics.clone()); - let block = Block::new(header.clone(), extrinsics); - - let local_checker = TestChecker::new( - Arc::new(DummyBlockchain::new(DummyStorage::new())), - local_executor(), - tasks_executor(), - ); - - let body_request = RemoteBodyRequest { - header: header.clone(), - retry_count: None, - }; - - assert!(local_checker.check_body_proof(&body_request, block.extrinsics).is_ok()); - } -} diff --git a/client/src/light/mod.rs b/client/src/light/mod.rs deleted file mode 100644 index 2bb6c85376859af3ab0bfb07b8863d86bd544f5c..0000000000000000000000000000000000000000 --- a/client/src/light/mod.rs +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2017-2020 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 . - -//! Light client components. - -pub mod backend; -pub mod blockchain; -pub mod call_executor; -pub mod fetcher; - -use std::sync::Arc; - -use sc_executor::RuntimeInfo; -use sp_core::traits::CodeExecutor; -use sp_runtime::BuildStorage; -use sp_runtime::traits::{Block as BlockT, HashFor}; -use sp_blockchain::Result as ClientResult; -use prometheus_endpoint::Registry; - -use crate::call_executor::LocalCallExecutor; -use crate::client::Client; -use sc_client_api::{ - light::Storage as BlockchainStorage, CloneableSpawn, -}; -use crate::light::backend::Backend; -use crate::light::blockchain::Blockchain; -use crate::light::call_executor::GenesisCallExecutor; -use crate::light::fetcher::LightDataChecker; - -/// Create an instance of light client blockchain backend. -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>) -> Arc>> - where - B: BlockT, - S: BlockchainStorage, -{ - Arc::new(Backend::new(blockchain)) -} - -/// Create an instance of light client. -pub fn new_light( - backend: Arc>>, - genesis_storage: &dyn BuildStorage, - code_executor: E, - spawn_handle: Box, - prometheus_registry: Option, -) -> ClientResult< - Client< - Backend>, - GenesisCallExecutor< - Backend>, - LocalCallExecutor>, E> - >, - B, - RA - > - > - where - B: BlockT, - S: BlockchainStorage + 'static, - E: CodeExecutor + RuntimeInfo + Clone + 'static, -{ - let local_executor = LocalCallExecutor::new(backend.clone(), code_executor, spawn_handle.clone()); - let executor = GenesisCallExecutor::new(backend.clone(), local_executor); - Client::new( - backend, - executor, - genesis_storage, - Default::default(), - Default::default(), - Default::default(), - prometheus_registry, - ) -} - -/// Create an instance of fetch data checker. -pub fn new_fetch_checker>( - blockchain: Arc>, - executor: E, - spawn_handle: Box, -) -> LightDataChecker, B, S> - where - E: CodeExecutor, -{ - LightDataChecker::new(blockchain, executor, spawn_handle) -} diff --git a/client/state-db/Cargo.toml b/client/state-db/Cargo.toml index 9da3c4e1274cd6065999b2a0214280b4b44ce87d..0fc30cda9f4ffe293be12b5fc57b8c8a9f2c57d6 100644 --- a/client/state-db/Cargo.toml +++ b/client/state-db/Cargo.toml @@ -1,24 +1,24 @@ [package] name = "sc-state-db" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "State database maintenance. Handles canonicalization and pruning in the database." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] parking_lot = "0.10.0" log = "0.4.8" -sc-client-api = { version = "2.0.0-alpha.5", path = "../api" } -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive"] } -parity-util-mem = "0.6" +sc-client-api = { version = "2.0.0-rc4", path = "../api" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +codec = { package = "parity-scale-codec", version = "1.3.1", features = ["derive"] } +parity-util-mem = { version = "0.7.0", default-features = false, features = ["primitive-types"] } parity-util-mem-derive = "0.1.0" [dev-dependencies] env_logger = "0.7.0" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/client/state-db/src/lib.rs b/client/state-db/src/lib.rs index 49b1a59285e11eb332bb099b7839f8b7383f5439..61470894e487e3884bc873301ff17e39345a0877 100644 --- a/client/state-db/src/lib.rs +++ b/client/state-db/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! State database maintenance. Handles canonicalization and pruning in the database. The input to //! this module is a `ChangeSet` which is basically a list of key-value pairs (trie nodes) that @@ -201,9 +203,10 @@ struct StateDbSync { impl StateDbSync { fn new( mode: PruningMode, + ref_counting: bool, db: &D, ) -> Result, Error> { - trace!(target: "state-db", "StateDb settings: {:?}", mode); + trace!(target: "state-db", "StateDb settings: {:?}. Ref-counting: {}", mode, ref_counting); // Check that settings match Self::check_meta(&mode, db)?; @@ -214,7 +217,7 @@ impl StateDbSync unimplemented!(), - PruningMode::Constrained(_) => Some(RefWindow::new(db)?), + PruningMode::Constrained(_) => Some(RefWindow::new(db, ref_counting)?), PruningMode::ArchiveAll | PruningMode::ArchiveCanonical => None, }; @@ -387,8 +390,11 @@ impl StateDbSync(&self, key: &Key, db: &D) -> Result, Error> - where Key: AsRef + pub fn get(&self, key: &Q, db: &D) -> Result, Error> + where + Q: AsRef, + Key: std::borrow::Borrow, + Q: std::hash::Hash + Eq, { if let Some(value) = self.non_canonical.get(key) { return Ok(Some(value)); @@ -438,10 +444,11 @@ impl StateDb( mode: PruningMode, + ref_counting: bool, db: &D, ) -> Result, Error> { Ok(StateDb { - db: RwLock::new(StateDbSync::new(mode, db)?) + db: RwLock::new(StateDbSync::new(mode, ref_counting, db)?) }) } @@ -475,8 +482,11 @@ impl StateDb(&self, key: &Key, db: &D) -> Result, Error> - where Key: AsRef + pub fn get(&self, key: &Q, db: &D) -> Result, Error> + where + Q: AsRef, + Key: std::borrow::Borrow, + Q: std::hash::Hash + Eq, { self.db.read().get(key, db) } @@ -523,7 +533,7 @@ mod tests { fn make_test_db(settings: PruningMode) -> (TestDb, StateDb) { let mut db = make_db(&[91, 921, 922, 93, 94]); - let state_db = StateDb::new(settings, &db).unwrap(); + let state_db = StateDb::new(settings, false, &db).unwrap(); db.commit( &state_db @@ -638,7 +648,7 @@ mod tests { #[test] fn detects_incompatible_mode() { let mut db = make_db(&[]); - let state_db = StateDb::new(PruningMode::ArchiveAll, &db).unwrap(); + let state_db = StateDb::new(PruningMode::ArchiveAll, false, &db).unwrap(); db.commit( &state_db .insert_block::( @@ -650,7 +660,7 @@ mod tests { .unwrap(), ); let new_mode = PruningMode::Constrained(Constraints { max_blocks: Some(2), max_mem: None }); - let state_db: Result, _> = StateDb::new(new_mode, &db); + let state_db: Result, _> = StateDb::new(new_mode, false, &db); assert!(state_db.is_err()); } } diff --git a/client/state-db/src/noncanonical.rs b/client/state-db/src/noncanonical.rs index 6a34523b66fff9e510518a4db4a884b5a693daf4..d77f20c50d05f30916f024666607dc7f3f16d440 100644 --- a/client/state-db/src/noncanonical.rs +++ b/client/state-db/src/noncanonical.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Canonicalization window. //! Maintains trees of block overlays and allows discarding trees/roots @@ -40,7 +42,7 @@ pub struct NonCanonicalOverlay { values: HashMap, //ref counted //would be deleted but kept around because block is pinned, ref counted. pinned: HashMap, - pinned_insertions: HashMap>, + pinned_insertions: HashMap, u32)>, } #[derive(Encode, Decode)] @@ -90,25 +92,44 @@ fn discard_values(values: &mut HashMap, inserted } fn discard_descendants( - levels: &mut VecDeque>>, + levels: &mut (&mut [Vec>], &mut [Vec>]), mut values: &mut HashMap, - index: usize, parents: &mut HashMap, pinned: &HashMap, - pinned_insertions: &mut HashMap>, + pinned_insertions: &mut HashMap, u32)>, hash: &BlockHash, -) { - let mut discarded = Vec::new(); - if let Some(level) = levels.get_mut(index) { +) -> u32 { + let (first, mut remainder) = if let Some((first, rest)) = levels.0.split_first_mut() { + (Some(first), (rest, &mut levels.1[..])) + } else { + if let Some((first, rest)) = levels.1.split_first_mut() { + (Some(first), (&mut levels.0[..], rest)) + } else { + (None, (&mut levels.0[..], &mut levels.1[..])) + } + }; + let mut pinned_children = 0; + if let Some(level) = first { *level = level.drain(..).filter_map(|overlay| { let parent = parents.get(&overlay.hash) .expect("there is a parent entry for each entry in levels; qed"); if parent == hash { - discarded.push(overlay.hash.clone()); + let mut num_pinned = discard_descendants( + &mut remainder, + values, + parents, + pinned, + pinned_insertions, + &overlay.hash + ); if pinned.contains_key(&overlay.hash) { + num_pinned += 1; + } + if num_pinned != 0 { // save to be discarded later. - pinned_insertions.insert(overlay.hash.clone(), overlay.inserted); + pinned_insertions.insert(overlay.hash.clone(), (overlay.inserted, num_pinned)); + pinned_children += num_pinned; } else { // discard immediately. parents.remove(&overlay.hash); @@ -120,9 +141,7 @@ fn discard_descendants( } }).collect(); } - for hash in discarded { - discard_descendants(levels, values, index + 1, parents, pinned, pinned_insertions, &hash); - } + pinned_children } impl NonCanonicalOverlay { @@ -346,19 +365,23 @@ impl NonCanonicalOverlay { // discard unfinalized overlays and values for (i, overlay) in level.into_iter().enumerate() { - if i != index { + let mut pinned_children = if i != index { discard_descendants( - &mut self.levels, + &mut self.levels.as_mut_slices(), &mut self.values, - 0, &mut self.parents, &self.pinned, &mut self.pinned_insertions, &overlay.hash, - ); - } + ) + } else { + 0 + }; if self.pinned.contains_key(&overlay.hash) { - self.pinned_insertions.insert(overlay.hash.clone(), overlay.inserted); + pinned_children += 1; + } + if pinned_children != 0 { + self.pinned_insertions.insert(overlay.hash.clone(), (overlay.inserted, pinned_children)); } else { self.parents.remove(&overlay.hash); discard_values(&mut self.values, overlay.inserted); @@ -372,7 +395,11 @@ impl NonCanonicalOverlay { } /// Get a value from the node overlay. This searches in every existing changeset. - pub fn get(&self, key: &Key) -> Option { + pub fn get(&self, key: &Q) -> Option + where + Key: std::borrow::Borrow, + Q: std::hash::Hash + Eq, + { if let Some((_, value)) = self.values.get(&key) { return Some(value.clone()); } @@ -435,37 +462,47 @@ impl NonCanonicalOverlay { debug_assert!(false, "Trying to pin pending state"); return; } - // Also pin all parents - let mut parent = Some(hash); - while let Some(hash) = parent { - let refs = self.pinned.entry(hash.clone()).or_default(); - if *refs == 0 { - trace!(target: "state-db-pin", "Pinned non-canon block: {:?}", hash); - } - *refs += 1; - parent = self.parents.get(hash); + let refs = self.pinned.entry(hash.clone()).or_default(); + if *refs == 0 { + trace!(target: "state-db-pin", "Pinned non-canon block: {:?}", hash); } + *refs += 1; } /// Discard pinned state pub fn unpin(&mut self, hash: &BlockHash) { - // Also unpin all parents - let mut parent = Some(hash.clone()); - while let Some(hash) = parent { - parent = self.parents.get(&hash).cloned(); - match self.pinned.entry(hash.clone()) { - Entry::Occupied(mut entry) => { - *entry.get_mut() -= 1; - if *entry.get() == 0 { - entry.remove(); - if let Some(inserted) = self.pinned_insertions.remove(&hash) { + let removed = match self.pinned.entry(hash.clone()) { + Entry::Occupied(mut entry) => { + *entry.get_mut() -= 1; + if *entry.get() == 0 { + entry.remove(); + true + } else { + false + } + }, + Entry::Vacant(_) => false, + }; + + if removed { + let mut parent = Some(hash.clone()); + while let Some(hash) = parent { + parent = self.parents.get(&hash).cloned(); + match self.pinned_insertions.entry(hash.clone()) { + Entry::Occupied(mut entry) => { + entry.get_mut().1 -= 1; + if entry.get().1 == 0 { + let (inserted, _) = entry.remove(); trace!(target: "state-db-pin", "Discarding unpinned non-canon block: {:?}", hash); discard_values(&mut self.values, inserted); self.parents.remove(&hash); + true + } else { + false } - } - }, - Entry::Vacant(_) => {}, + }, + Entry::Vacant(_) => break, + }; } } } diff --git a/client/state-db/src/pruning.rs b/client/state-db/src/pruning.rs index 6cf5f260060f500432ff306eb2e3f3c6a69f9089..69b07c285fad8318152611d9473c508367a9f73c 100644 --- a/client/state-db/src/pruning.rs +++ b/client/state-db/src/pruning.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Pruning window. //! @@ -45,6 +47,10 @@ pub struct RefWindow { /// Number of calls of `prune_one` after /// last call `apply_pending` or `revert_pending` pending_prunings: usize, + /// Keep track of re-inserted keys and do not delete them when pruning. + /// Setting this to false requires backend that supports reference + /// counting. + count_insertions: bool, } #[derive(Debug, PartialEq, Eq, parity_util_mem_derive::MallocSizeOf)] @@ -66,7 +72,7 @@ fn to_journal_key(block: u64) -> Vec { } impl RefWindow { - pub fn new(db: &D) -> Result, Error> { + pub fn new(db: &D, count_insertions: bool) -> Result, Error> { let last_pruned = db.get_meta(&to_meta_key(LAST_PRUNED, &())) .map_err(|e| Error::Db(e))?; let pending_number: u64 = match last_pruned { @@ -80,6 +86,7 @@ impl RefWindow { pending_number: pending_number, pending_canonicalizations: 0, pending_prunings: 0, + count_insertions, }; // read the journal trace!(target: "state-db", "Reading pruning journal. Pending #{}", pending_number); @@ -99,17 +106,19 @@ impl RefWindow { } fn import>(&mut self, hash: &BlockHash, journal_key: Vec, inserted: I, deleted: Vec) { - // remove all re-inserted keys from death rows - for k in inserted { - if let Some(block) = self.death_index.remove(&k) { - self.death_rows[(block - self.pending_number) as usize].deleted.remove(&k); + if self.count_insertions { + // remove all re-inserted keys from death rows + for k in inserted { + if let Some(block) = self.death_index.remove(&k) { + self.death_rows[(block - self.pending_number) as usize].deleted.remove(&k); + } } - } - // add new keys - let imported_block = self.pending_number + self.death_rows.len() as u64; - for k in deleted.iter() { - self.death_index.insert(k.clone(), imported_block); + // add new keys + let imported_block = self.pending_number + self.death_rows.len() as u64; + for k in deleted.iter() { + self.death_index.insert(k.clone(), imported_block); + } } self.death_rows.push_back( DeathRow { @@ -157,8 +166,12 @@ impl RefWindow { /// Add a change set to the window. Creates a journal record and pushes it to `commit` pub fn note_canonical(&mut self, hash: &BlockHash, commit: &mut CommitSet) { trace!(target: "state-db", "Adding to pruning window: {:?} ({} inserted, {} deleted)", hash, commit.data.inserted.len(), commit.data.deleted.len()); - let inserted = commit.data.inserted.iter().map(|(k, _)| k.clone()).collect(); - let deleted = ::std::mem::replace(&mut commit.data.deleted, Vec::new()); + let inserted = if self.count_insertions { + commit.data.inserted.iter().map(|(k, _)| k.clone()).collect() + } else { + Default::default() + }; + let deleted = ::std::mem::take(&mut commit.data.deleted); let journal_record = JournalRecord { hash: hash.clone(), inserted, @@ -177,8 +190,10 @@ impl RefWindow { for _ in 0 .. self.pending_prunings { let pruned = self.death_rows.pop_front().expect("pending_prunings is always < death_rows.len()"); trace!(target: "state-db", "Applying pruning {:?} ({} deleted)", pruned.hash, pruned.deleted.len()); - for k in pruned.deleted.iter() { - self.death_index.remove(&k); + if self.count_insertions { + for k in pruned.deleted.iter() { + self.death_index.remove(&k); + } } self.pending_number += 1; } @@ -192,8 +207,10 @@ impl RefWindow { // We don't bother to track and revert that for now. This means that a few nodes might end up no being // deleted in case transaction fails and `revert_pending` is called. self.death_rows.truncate(self.death_rows.len() - self.pending_canonicalizations); - let new_max_block = self.death_rows.len() as u64 + self.pending_number; - self.death_index.retain(|_, block| *block < new_max_block); + if self.count_insertions { + let new_max_block = self.death_rows.len() as u64 + self.pending_number; + self.death_index.retain(|_, block| *block < new_max_block); + } self.pending_canonicalizations = 0; self.pending_prunings = 0; } @@ -207,7 +224,7 @@ mod tests { use crate::test::{make_db, make_commit, TestDb}; fn check_journal(pruning: &RefWindow, db: &TestDb) { - let restored: RefWindow = RefWindow::new(db).unwrap(); + let restored: RefWindow = RefWindow::new(db, pruning.count_insertions).unwrap(); assert_eq!(pruning.pending_number, restored.pending_number); assert_eq!(pruning.death_rows, restored.death_rows); assert_eq!(pruning.death_index, restored.death_index); @@ -216,7 +233,7 @@ mod tests { #[test] fn created_from_empty_db() { let db = make_db(&[]); - let pruning: RefWindow = RefWindow::new(&db).unwrap(); + let pruning: RefWindow = RefWindow::new(&db, true).unwrap(); assert_eq!(pruning.pending_number, 0); assert!(pruning.death_rows.is_empty()); assert!(pruning.death_index.is_empty()); @@ -225,7 +242,7 @@ mod tests { #[test] fn prune_empty() { let db = make_db(&[]); - let mut pruning: RefWindow = RefWindow::new(&db).unwrap(); + let mut pruning: RefWindow = RefWindow::new(&db, true).unwrap(); let mut commit = CommitSet::default(); pruning.prune_one(&mut commit); assert_eq!(pruning.pending_number, 0); @@ -238,7 +255,7 @@ mod tests { #[test] fn prune_one() { let mut db = make_db(&[1, 2, 3]); - let mut pruning: RefWindow = RefWindow::new(&db).unwrap(); + let mut pruning: RefWindow = RefWindow::new(&db, true).unwrap(); let mut commit = make_commit(&[4, 5], &[1, 3]); let h = H256::random(); pruning.note_canonical(&h, &mut commit); @@ -267,7 +284,7 @@ mod tests { #[test] fn prune_two() { let mut db = make_db(&[1, 2, 3]); - let mut pruning: RefWindow = RefWindow::new(&db).unwrap(); + let mut pruning: RefWindow = RefWindow::new(&db, true).unwrap(); let mut commit = make_commit(&[4], &[1]); pruning.note_canonical(&H256::random(), &mut commit); db.commit(&commit); @@ -295,7 +312,7 @@ mod tests { #[test] fn prune_two_pending() { let mut db = make_db(&[1, 2, 3]); - let mut pruning: RefWindow = RefWindow::new(&db).unwrap(); + let mut pruning: RefWindow = RefWindow::new(&db, true).unwrap(); let mut commit = make_commit(&[4], &[1]); pruning.note_canonical(&H256::random(), &mut commit); db.commit(&commit); @@ -318,7 +335,7 @@ mod tests { #[test] fn reinserted_survives() { let mut db = make_db(&[1, 2, 3]); - let mut pruning: RefWindow = RefWindow::new(&db).unwrap(); + let mut pruning: RefWindow = RefWindow::new(&db, true).unwrap(); let mut commit = make_commit(&[], &[2]); pruning.note_canonical(&H256::random(), &mut commit); db.commit(&commit); @@ -351,7 +368,7 @@ mod tests { #[test] fn reinserted_survive_pending() { let mut db = make_db(&[1, 2, 3]); - let mut pruning: RefWindow = RefWindow::new(&db).unwrap(); + let mut pruning: RefWindow = RefWindow::new(&db, true).unwrap(); let mut commit = make_commit(&[], &[2]); pruning.note_canonical(&H256::random(), &mut commit); db.commit(&commit); @@ -377,4 +394,30 @@ mod tests { pruning.apply_pending(); assert_eq!(pruning.pending_number, 3); } + + #[test] + fn reinserted_ignores() { + let mut db = make_db(&[1, 2, 3]); + let mut pruning: RefWindow = RefWindow::new(&db, false).unwrap(); + let mut commit = make_commit(&[], &[2]); + pruning.note_canonical(&H256::random(), &mut commit); + db.commit(&commit); + let mut commit = make_commit(&[2], &[]); + pruning.note_canonical(&H256::random(), &mut commit); + db.commit(&commit); + let mut commit = make_commit(&[], &[2]); + pruning.note_canonical(&H256::random(), &mut commit); + db.commit(&commit); + assert!(db.data_eq(&make_db(&[1, 2, 3]))); + pruning.apply_pending(); + + check_journal(&pruning, &db); + + let mut commit = CommitSet::default(); + pruning.prune_one(&mut commit); + db.commit(&commit); + assert!(db.data_eq(&make_db(&[1, 3]))); + assert!(pruning.death_index.is_empty()); + } + } diff --git a/client/state-db/src/test.rs b/client/state-db/src/test.rs index accafa9bf831fb323b7f0247080f85d08d1c3f4d..11ce4ad8226202d0f08a9e77bdddfb8e7772deaa 100644 --- a/client/state-db/src/test.rs +++ b/client/state-db/src/test.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Test utils diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index bb7e7e510372bc253ba6fa2130c6f0e1b7d4a31b..aaa2d11aece9900a589082ee4d550425b16e8590 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -1,22 +1,24 @@ [package] name = "sc-telemetry" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] description = "Telemetry utils" edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" documentation = "https://docs.rs/sc-telemetry" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -bytes = "0.5" parking_lot = "0.10.0" futures = "0.3.4" futures-timer = "3.0.1" wasm-timer = "0.2.0" -libp2p = { version = "0.16.2", default-features = false, features = ["libp2p-websocket"] } +libp2p = { version = "0.21.1", default-features = false, features = ["dns", "tcp-async-std", "wasm-ext", "websocket"] } log = "0.4.8" pin-project = "0.4.6" rand = "0.7.2" @@ -26,6 +28,3 @@ slog-json = { version = "2.3.0", features = ["nested-values"] } slog-scope = "4.1.2" take_mut = "0.2.2" void = "1.0.2" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 6c90d6bbcca9f3a60fc765e056abd908c0ea0636..315bedbe5b6d92d4a96fa5085658d95c1c99a29b 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Telemetry utilities. //! diff --git a/client/telemetry/src/worker.rs b/client/telemetry/src/worker.rs index 8f43bb612a10503d0d8968821bc90f1469140f85..e01ac62d12dc36fdab9e4feebec33eed662ba93c 100644 --- a/client/telemetry/src/worker.rs +++ b/client/telemetry/src/worker.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Contains the object that makes the telemetry work. //! @@ -26,7 +28,6 @@ //! events indicating what happened since the latest polling. //! -use bytes::BytesMut; use futures::{prelude::*, ready}; use libp2p::{core::transport::OptionalTransport, Multiaddr, Transport, wasm_ext}; use log::{trace, warn, error}; @@ -59,8 +60,8 @@ impl, I> StreamAndSink for T {} type WsTrans = libp2p::core::transport::boxed::Boxed< Pin, + Vec, + Item = Result, io::Error>, Error = io::Error > + Send>>, io::Error @@ -90,12 +91,12 @@ impl TelemetryWorker { libp2p::websocket::framed::WsConfig::new(inner) .and_then(|connec, _| { let connec = connec - .with(|item: BytesMut| { + .with(|item| { let item = libp2p::websocket::framed::OutgoingData::Binary(item); future::ready(Ok::<_, io::Error>(item)) }) .try_filter(|item| future::ready(item.is_data())) - .map_ok(|data| BytesMut::from(data.as_ref())); + .map_ok(|data| data.into_bytes()); future::ready(Ok::<_, io::Error>(connec)) }) }); @@ -187,7 +188,7 @@ impl TelemetryWorker { /// For some context, we put this object around the `wasm_ext::ExtTransport` in order to make sure /// that each telemetry message maps to one single call to `write` in the WASM FFI. #[pin_project::pin_project] -struct StreamSink(#[pin] T, Option); +struct StreamSink(#[pin] T, Option>); impl From for StreamSink { fn from(inner: T) -> StreamSink { @@ -196,15 +197,15 @@ impl From for StreamSink { } impl Stream for StreamSink { - type Item = Result; + type Item = Result, io::Error>; fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { let this = self.project(); - let mut buf = [0; 128]; + let mut buf = vec![0; 128]; match ready!(AsyncRead::poll_read(this.0, cx, &mut buf)) { Ok(0) => Poll::Ready(None), Ok(n) => { - let buf: BytesMut = buf[..n].into(); + buf.truncate(n); Poll::Ready(Some(Ok(buf))) }, Err(err) => Poll::Ready(Some(Err(err))), @@ -230,7 +231,7 @@ impl StreamSink { } } -impl Sink for StreamSink { +impl Sink> for StreamSink { type Error = io::Error; fn poll_ready(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { @@ -238,7 +239,7 @@ impl Sink for StreamSink { Poll::Ready(Ok(())) } - fn start_send(self: Pin<&mut Self>, item: BytesMut) -> Result<(), Self::Error> { + fn start_send(self: Pin<&mut Self>, item: Vec) -> Result<(), Self::Error> { let this = self.project(); debug_assert!(this.1.is_none()); *this.1 = Some(item); diff --git a/client/telemetry/src/worker/node.rs b/client/telemetry/src/worker/node.rs index 454f504d660050995cba1f6c122c311ba35741ee..eef7ca7e815536aaaa26f8e2d20f17dc67e2f1e5 100644 --- a/client/telemetry/src/worker/node.rs +++ b/client/telemetry/src/worker/node.rs @@ -1,22 +1,23 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Contains the `Node` struct, which handles communications with a single telemetry endpoint. -use bytes::BytesMut; use futures::prelude::*; use futures_timer::Delay; use libp2p::Multiaddr; @@ -55,7 +56,7 @@ struct NodeSocketConnected { /// Where to send data. sink: TTrans::Output, /// Queue of packets to send. - pending: VecDeque, + pending: VecDeque>, /// If true, we need to flush the sink. need_flush: bool, /// A timeout for the socket to write data. @@ -101,15 +102,15 @@ impl Node { impl Node where TTrans: Clone + Unpin, TTrans::Dial: Unpin, - TTrans::Output: Sink - + Stream> + TTrans::Output: Sink, Error = TSinkErr> + + Stream, TSinkErr>> + Unpin, TSinkErr: fmt::Debug { /// Sends a WebSocket frame to the node. Returns an error if we are not connected to the node. /// /// After calling this method, you should call `poll` in order for it to be properly processed. - pub fn send_message(&mut self, payload: impl Into) -> Result<(), ()> { + pub fn send_message(&mut self, payload: impl Into>) -> Result<(), ()> { if let NodeSocket::Connected(NodeSocketConnected { pending, .. }) = &mut self.socket { if pending.len() <= MAX_PENDING { trace!(target: "telemetry", "Adding log entry to queue for {:?}", self.addr); @@ -201,8 +202,8 @@ fn gen_rand_reconnect_delay() -> Delay { } impl NodeSocketConnected -where TTrans::Output: Sink - + Stream> +where TTrans::Output: Sink, Error = TSinkErr> + + Stream, TSinkErr>> + Unpin { /// Processes the queue of messages for the connected socket. diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index 319526b61044858240908719d233aaef5a134f98..c4564e5fe53f59ff53f00997af0c85f9ce15ce96 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -1,26 +1,28 @@ [package] name = "sc-tracing" -version = "2.0.0-alpha.5" -license = "GPL-3.0" +version = "2.0.0-rc4" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" authors = ["Parity Technologies "] edition = "2018" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Instrumentation implementation for substrate." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] erased-serde = "0.3.9" log = { version = "0.4.8" } parking_lot = "0.10.0" +rustc-hash = "1.1.0" serde = "1.0.101" serde_json = "1.0.41" slog = { version = "2.5.2", features = ["nested-values"] } tracing-core = "0.1.7" +sp-tracing = { version = "2.0.0-rc2", path = "../../primitives/tracing" } -sc-telemetry = { version = "2.0.0-alpha.5", path = "../telemetry" } +sc-telemetry = { version = "2.0.0-rc4", path = "../telemetry" } [dev-dependencies] tracing = "0.1.10" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/client/tracing/src/lib.rs b/client/tracing/src/lib.rs index c00bca9275eec7fa2bf99050b6413c99f846bc78..c62b8d5b1e9c95f8a02bde84fad19c101ac075e3 100644 --- a/client/tracing/src/lib.rs +++ b/client/tracing/src/lib.rs @@ -20,23 +20,11 @@ //! //! # Usage //! -//! Monitor performance throughout the codebase via the creation of `Span`s. -//! A span is set in the following way: -//! ``` -//! let span = tracing::span!(tracing::Level::INFO, "my_span_name"); -//! let _guard = span.enter(); -//! ``` -//! To begin timing, a span must be entered. When the span is dropped, the execution time -//! is recorded and details sent to the `Receiver` which defines how to process it. +//! See `sp-tracing` for examples on how to use tracing. //! -//! It's possible to record values with each span in the following way: -//! ``` -//! let span = tracing::span!(tracing::Level::INFO, "my_span_name", my_number = 10, a_key = "a value"); -//! let _guard = span.enter(); -//! ``` //! Currently we provide `Log` (default), `Telemetry` variants for `Receiver` -use std::collections::HashMap; +use rustc_hash::FxHashMap; use std::fmt; use std::sync::atomic::{AtomicU64, Ordering}; use std::time::{Duration, Instant}; @@ -50,10 +38,14 @@ use tracing_core::{ Level, metadata::Metadata, span::{Attributes, Id, Record}, - subscriber::Subscriber + subscriber::Subscriber, }; use sc_telemetry::{telemetry, SUBSTRATE_INFO}; +use sp_tracing::proxy::{WASM_NAME_KEY, WASM_TARGET_KEY, WASM_TRACE_IDENTIFIER}; + +const ZERO_DURATION: Duration = Duration::from_nanos(0); +const PROXY_TARGET: &'static str = "sp_tracing::proxy"; /// Used to configure how to receive the metrics #[derive(Debug, Clone)] @@ -70,36 +62,55 @@ impl Default for TracingReceiver { } } +/// A handler for tracing `SpanDatum` +pub trait TraceHandler: Send + Sync { + /// Process a `SpanDatum` + fn process_span(&self, span: SpanDatum); +} + +/// Represents a single instance of a tracing span #[derive(Debug)] -struct SpanDatum { - id: u64, - name: &'static str, - target: &'static str, - level: Level, - line: u32, - start_time: Instant, - overall_time: Duration, - values: Visitor, +pub struct SpanDatum { + pub id: u64, + pub name: String, + pub target: String, + pub level: Level, + pub line: u32, + pub start_time: Instant, + pub overall_time: Duration, + pub values: Visitor, } +/// Holds associated values for a tracing span #[derive(Clone, Debug)] -struct Visitor(Vec<(String, String)>); +pub struct Visitor(FxHashMap); + +impl Visitor { + /// Consume the Visitor, returning the inner FxHashMap + pub fn into_inner(self) -> FxHashMap { + self.0 + } +} impl Visit for Visitor { fn record_i64(&mut self, field: &Field, value: i64) { - self.record_debug(field, &value) + self.0.insert(field.name().to_string(), value.to_string()); } fn record_u64(&mut self, field: &Field, value: u64) { - self.record_debug(field, &value) + self.0.insert(field.name().to_string(), value.to_string()); } fn record_bool(&mut self, field: &Field, value: bool) { - self.record_debug(field, &value) + self.0.insert(field.name().to_string(), value.to_string()); + } + + fn record_str(&mut self, field: &Field, value: &str) { + self.0.insert(field.name().to_string(), value.to_owned()); } fn record_debug(&mut self, field: &Field, value: &dyn std::fmt::Debug) { - self.0.push((field.name().to_string(), format!("{:?}",value))); + self.0.insert(field.name().to_string(), format!("{:?}", value)); } } @@ -117,7 +128,7 @@ impl Serialize for Visitor { impl fmt::Display for Visitor { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let values = self.0.iter().map(|(k,v)| format!("{}={}",k,v)).collect::>().join(", "); + let values = self.0.iter().map(|(k, v)| format!("{}={}", k, v)).collect::>().join(", "); write!(f, "{}", values) } } @@ -147,23 +158,50 @@ impl Value for Visitor { pub struct ProfilingSubscriber { next_id: AtomicU64, targets: Vec<(String, Level)>, - receiver: TracingReceiver, - span_data: Mutex>, + trace_handler: Box, + span_data: Mutex>, } impl ProfilingSubscriber { - /// Takes a `Receiver` and a comma separated list of targets, - /// either with a level: "pallet=trace" - /// or without: "pallet". - pub fn new(receiver: TracingReceiver, targets: &str) -> Self { + /// Takes a `TracingReceiver` and a comma separated list of targets, + /// either with a level: "pallet=trace,frame=debug" + /// or without: "pallet,frame" in which case the level defaults to `trace`. + /// wasm_tracing indicates whether to enable wasm traces + pub fn new(receiver: TracingReceiver, targets: &str) -> ProfilingSubscriber { + match receiver { + TracingReceiver::Log => Self::new_with_handler(Box::new(LogTraceHandler), targets), + TracingReceiver::Telemetry => Self::new_with_handler( + Box::new(TelemetryTraceHandler), + targets, + ), + } + } + + /// Allows use of a custom TraceHandler to create a new instance of ProfilingSubscriber. + /// Takes a comma separated list of targets, + /// either with a level, eg: "pallet=trace" + /// or without: "pallet" in which case the level defaults to `trace`. + /// wasm_tracing indicates whether to enable wasm traces + pub fn new_with_handler(trace_handler: Box, targets: &str) + -> ProfilingSubscriber + { let targets: Vec<_> = targets.split(',').map(|s| parse_target(s)).collect(); ProfilingSubscriber { next_id: AtomicU64::new(1), targets, - receiver, - span_data: Mutex::new(HashMap::new()), + trace_handler, + span_data: Mutex::new(FxHashMap::default()), } } + + fn check_target(&self, target: &str, level: &Level) -> bool { + for t in &self.targets { + if target.starts_with(t.0.as_str()) && level <= &t.1 { + return true; + } + } + false + } } // Default to TRACE if no level given or unable to parse Level @@ -185,36 +223,45 @@ fn parse_target(s: &str) -> (String, Level) { impl Subscriber for ProfilingSubscriber { fn enabled(&self, metadata: &Metadata<'_>) -> bool { - for t in &self.targets { - if metadata.target().starts_with(t.0.as_str()) && metadata.level() <= &t.1 { - log::debug!("Enabled target: {}, level: {}", metadata.target(), metadata.level()); - return true; - } else { - log::debug!("Disabled target: {}, level: {}", metadata.target(), metadata.level()); - } + if metadata.target() == PROXY_TARGET || self.check_target(metadata.target(), metadata.level()) { + log::debug!(target: "tracing", "Enabled target: {}, level: {}", metadata.target(), metadata.level()); + true + } else { + log::debug!(target: "tracing", "Disabled target: {}, level: {}", metadata.target(), metadata.level()); + false } - false } fn new_span(&self, attrs: &Attributes<'_>) -> Id { let id = self.next_id.fetch_add(1, Ordering::Relaxed); - let mut values = Visitor(Vec::new()); + let mut values = Visitor(FxHashMap::default()); attrs.record(&mut values); + // If this is a wasm trace, check if target/level is enabled + if let Some(wasm_target) = values.0.get(WASM_TARGET_KEY) { + if !self.check_target(wasm_target, attrs.metadata().level()) { + return Id::from_u64(id); + } + } let span_datum = SpanDatum { id, - name: attrs.metadata().name(), - target: attrs.metadata().target(), + name: attrs.metadata().name().to_owned(), + target: attrs.metadata().target().to_owned(), level: attrs.metadata().level().clone(), line: attrs.metadata().line().unwrap_or(0), start_time: Instant::now(), - overall_time: Duration::from_nanos(0), + overall_time: ZERO_DURATION, values, }; self.span_data.lock().insert(id, span_datum); Id::from_u64(id) } - fn record(&self, _span: &Id, _values: &Record<'_>) {} + fn record(&self, span: &Id, values: &Record<'_>) { + let mut span_data = self.span_data.lock(); + if let Some(s) = span_data.get_mut(&span.into_u64()) { + values.record(&mut s.values); + } + } fn record_follows_from(&self, _span: &Id, _follows: &Id) {} @@ -225,65 +272,89 @@ impl Subscriber for ProfilingSubscriber { let start_time = Instant::now(); if let Some(mut s) = span_data.get_mut(&span.into_u64()) { s.start_time = start_time; - } else { - log::warn!("Tried to enter span {:?} that has already been closed!", span); } } fn exit(&self, span: &Id) { - let mut span_data = self.span_data.lock(); let end_time = Instant::now(); + let mut span_data = self.span_data.lock(); if let Some(mut s) = span_data.get_mut(&span.into_u64()) { s.overall_time = end_time - s.start_time + s.overall_time; } } fn try_close(&self, span: Id) -> bool { - let mut span_data = self.span_data.lock(); - if let Some(data) = span_data.remove(&span.into_u64()) { - self.send_span(data); + let span_datum = { + let mut span_data = self.span_data.lock(); + span_data.remove(&span.into_u64()) + }; + if let Some(mut span_datum) = span_datum { + if span_datum.name == WASM_TRACE_IDENTIFIER { + span_datum.values.0.insert("wasm".to_owned(), "true".to_owned()); + if let Some(n) = span_datum.values.0.remove(WASM_NAME_KEY) { + span_datum.name = n; + } + if let Some(t) = span_datum.values.0.remove(WASM_TARGET_KEY) { + span_datum.target = t; + } + } + if self.check_target(&span_datum.target, &span_datum.level) { + self.trace_handler.process_span(span_datum); + } }; true } } -impl ProfilingSubscriber { - fn send_span(&self, span_datum: SpanDatum) { - match self.receiver { - TracingReceiver::Log => print_log(span_datum), - TracingReceiver::Telemetry => send_telemetry(span_datum), - } +/// TraceHandler for sending span data to the logger +pub struct LogTraceHandler; + +fn log_level(level: Level) -> log::Level { + match level { + Level::TRACE => log::Level::Trace, + Level::DEBUG => log::Level::Debug, + Level::INFO => log::Level::Info, + Level::WARN => log::Level::Warn, + Level::ERROR => log::Level::Error, } } -fn print_log(span_datum: SpanDatum) { - if span_datum.values.0.is_empty() { - log::info!("TRACING: {} {}: {}, line: {}, time: {}", - span_datum.level, - span_datum.target, - span_datum.name, - span_datum.line, - span_datum.overall_time.as_nanos(), - ); - } else { - log::info!("TRACING: {} {}: {}, line: {}, time: {}, {}", - span_datum.level, - span_datum.target, - span_datum.name, - span_datum.line, - span_datum.overall_time.as_nanos(), - span_datum.values - ); +impl TraceHandler for LogTraceHandler { + fn process_span(&self, span_datum: SpanDatum) { + if span_datum.values.0.is_empty() { + log::log!( + log_level(span_datum.level), + "{}: {}, time: {}", + span_datum.target, + span_datum.name, + span_datum.overall_time.as_nanos(), + ); + } else { + log::log!( + log_level(span_datum.level), + "{}: {}, time: {}, {}", + span_datum.target, + span_datum.name, + span_datum.overall_time.as_nanos(), + span_datum.values, + ); + } } } -fn send_telemetry(span_datum: SpanDatum) { - telemetry!(SUBSTRATE_INFO; "tracing.profiling"; - "name" => span_datum.name, - "target" => span_datum.target, - "line" => span_datum.line, - "time" => span_datum.overall_time.as_nanos(), - "values" => span_datum.values - ); +/// TraceHandler for sending span data to telemetry, +/// Please see telemetry documentation for details on how to specify endpoints and +/// set the required telemetry level to activate tracing messages +pub struct TelemetryTraceHandler; + +impl TraceHandler for TelemetryTraceHandler { + fn process_span(&self, span_datum: SpanDatum) { + telemetry!(SUBSTRATE_INFO; "tracing.profiling"; + "name" => span_datum.name, + "target" => span_datum.target, + "line" => span_datum.line, + "time" => span_datum.overall_time.as_nanos(), + "values" => span_datum.values + ); + } } - diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index 29b80698424e1a60a8d4fc542d6dea3354706910..290b63cc8c2338fd41b5b98bb908b45bd2a1e052 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -1,38 +1,42 @@ [package] name = "sc-transaction-pool" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate transaction pool implementation." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0" } +codec = { package = "parity-scale-codec", version = "1.3.1" } derive_more = "0.99.2" futures = { version = "0.3.1", features = ["compat"] } futures-diagnose = "1.0" +intervalier = "0.4.0" log = "0.4.8" +parity-util-mem = { version = "0.7.0", default-features = false, features = ["primitive-types"] } parking_lot = "0.10.0" +prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.8.0-rc4"} +sc-client-api = { version = "2.0.0-rc4", path = "../api" } +sc-transaction-graph = { version = "2.0.0-rc4", path = "./graph" } +sp-api = { version = "2.0.0-rc4", path = "../../primitives/api" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +sp-runtime = { version = "2.0.0-rc4", path = "../../primitives/runtime" } +sp-tracing = { version = "2.0.0-rc4", path = "../../primitives/tracing" } +sp-transaction-pool = { version = "2.0.0-rc4", path = "../../primitives/transaction-pool" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../primitives/blockchain" } +sp-utils = { version = "2.0.0-rc4", path = "../../primitives/utils" } wasm-timer = "0.2" -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -sp-api = { version = "2.0.0-alpha.5", path = "../../primitives/api" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../primitives/runtime" } -sp-utils = { version = "2.0.0-alpha.5", path = "../../primitives/utils" } -sc-transaction-graph = { version = "2.0.0-alpha.5", path = "./graph" } -sp-transaction-pool = { version = "2.0.0-alpha.5", path = "../../primitives/transaction-pool" } -sc-client-api = { version = "2.0.0-alpha.5", path = "../api" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../primitives/blockchain" } -intervalier = "0.3.1" -parity-util-mem = { version = "0.6.0", default-features = false, features = ["primitive-types"] } [dev-dependencies] assert_matches = "1.3.0" hex = "0.4" -sp-keyring = { version = "2.0.0-alpha.5", path = "../../primitives/keyring" } -substrate-test-runtime-transaction-pool = { version = "2.0.0-dev", path = "../../test-utils/runtime/transaction-pool" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../test-utils/runtime/client" } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +sp-keyring = { version = "2.0.0-rc4", path = "../../primitives/keyring" } +sp-consensus = { version = "0.8.0-rc4", path = "../../primitives/consensus/common" } +substrate-test-runtime-transaction-pool = { version = "2.0.0-rc4", path = "../../test-utils/runtime/transaction-pool" } +substrate-test-runtime-client = { version = "2.0.0-rc4", path = "../../test-utils/runtime/client" } +sc-block-builder = { version = "0.8.0-rc4", path = "../block-builder" } diff --git a/client/transaction-pool/graph/Cargo.toml b/client/transaction-pool/graph/Cargo.toml index df2fd8546a2650453d273d558bf6b17355509b5c..ecce54505dc6d40f6a888468a7827745df34eeb3 100644 --- a/client/transaction-pool/graph/Cargo.toml +++ b/client/transaction-pool/graph/Cargo.toml @@ -1,13 +1,16 @@ [package] name = "sc-transaction-graph" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Generic Transaction Pool" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] derive_more = "0.99.2" futures = "0.3.4" @@ -15,23 +18,20 @@ log = "0.4.8" parking_lot = "0.10.0" serde = { version = "1.0.101", features = ["derive"] } wasm-timer = "0.2" -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../../primitives/blockchain" } -sp-utils = { version = "2.0.0-alpha.5", path = "../../../primitives/utils" } -sp-core = { version = "2.0.0-alpha.5", path = "../../../primitives/core" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime" } -sp-transaction-pool = { version = "2.0.0-alpha.5", path = "../../../primitives/transaction-pool" } -parity-util-mem = { version = "0.6.0", default-features = false, features = ["primitive-types"] } +sp-blockchain = { version = "2.0.0-rc4", path = "../../../primitives/blockchain" } +sp-utils = { version = "2.0.0-rc4", path = "../../../primitives/utils" } +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } +sp-runtime = { version = "2.0.0-rc4", path = "../../../primitives/runtime" } +sp-transaction-pool = { version = "2.0.0-rc4", path = "../../../primitives/transaction-pool" } +parity-util-mem = { version = "0.7.0", default-features = false, features = ["primitive-types"] } linked-hash-map = "0.5.2" [dev-dependencies] assert_matches = "1.3.0" -codec = { package = "parity-scale-codec", version = "1.3.0" } -substrate-test-runtime = { version = "2.0.0-dev", path = "../../../test-utils/runtime" } +codec = { package = "parity-scale-codec", version = "1.3.1" } +substrate-test-runtime = { version = "2.0.0-rc4", path = "../../../test-utils/runtime" } criterion = "0.3" [[bench]] name = "basics" harness = false - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/client/transaction-pool/graph/benches/basics.rs b/client/transaction-pool/graph/benches/basics.rs index 23b4dba3488061429a39c04bcd717b55ee007c78..bb10086bd4a558330d8d36e4bf3b92d791fdcae4 100644 --- a/client/transaction-pool/graph/benches/basics.rs +++ b/client/transaction-pool/graph/benches/basics.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use criterion::{criterion_group, criterion_main, Criterion}; @@ -49,7 +51,6 @@ fn to_tag(nonce: u64, from: AccountId) -> Tag { impl ChainApi for TestApi { type Block = Block; - type Hash = H256; type Error = sp_transaction_pool::error::Error; type ValidationFuture = Ready>; type BodyFuture = Ready>>>; @@ -105,7 +106,7 @@ impl ChainApi for TestApi { }) } - fn hash_and_length(&self, uxt: &ExtrinsicFor) -> (Self::Hash, usize) { + fn hash_and_length(&self, uxt: &ExtrinsicFor) -> (H256, usize) { let encoded = uxt.encode(); (blake2_256(&encoded).into(), encoded.len()) } diff --git a/client/transaction-pool/graph/src/base_pool.rs b/client/transaction-pool/graph/src/base_pool.rs index 38151e9bfd23b87b3fd4511022eaa7f9953ab46a..25da341e6794e55632af2c104cadd59262ed027b 100644 --- a/client/transaction-pool/graph/src/base_pool.rs +++ b/client/transaction-pool/graph/src/base_pool.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! A basic version of the dependency graph. //! @@ -259,6 +261,11 @@ impl BasePool bool { + self.future.contains(tx_hash) || self.ready.contains(tx_hash) + } + /// Imports transaction to the pool. /// /// The pool consists of two parts: Future and Ready. @@ -270,7 +277,7 @@ impl BasePool, ) -> error::Result> { - if self.future.contains(&tx.hash) || self.ready.contains(&tx.hash) { + if self.is_imported(&tx.hash) { return Err(error::Error::AlreadyImported(Box::new(tx.hash.clone()))) } diff --git a/client/transaction-pool/graph/src/error.rs b/client/transaction-pool/graph/src/error.rs index 6fd7748e369aba3508251c04f976a49a0214b312..392ddaa39be6f2d809792985b283cf5630d09792 100644 --- a/client/transaction-pool/graph/src/error.rs +++ b/client/transaction-pool/graph/src/error.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Transaction pool errors. diff --git a/client/transaction-pool/graph/src/future.rs b/client/transaction-pool/graph/src/future.rs index 76181c837f988586d72ebd3568b4c31a35ac6b8d..80e6825d4ff9d3097f485d8fe86ca388ef0a3197 100644 --- a/client/transaction-pool/graph/src/future.rs +++ b/client/transaction-pool/graph/src/future.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use std::{ collections::{HashMap, HashSet}, diff --git a/client/transaction-pool/graph/src/lib.rs b/client/transaction-pool/graph/src/lib.rs index ed10ef38d2bfd868eda7504b74bbe3018dee0c6f..bf220ce22973a97190ad7a0d5da2ba50e9e0acd6 100644 --- a/client/transaction-pool/graph/src/lib.rs +++ b/client/transaction-pool/graph/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Generic Transaction Pool //! @@ -30,14 +32,13 @@ mod pool; mod ready; mod rotator; mod validated_pool; +mod tracked_map; pub mod base_pool; pub mod watcher; pub use self::base_pool::Transaction; pub use self::pool::{ - Pool, - Options, ChainApi, EventStream, ExtrinsicFor, - BlockHash, ExHash, NumberFor, TransactionFor, - ValidatedTransaction, + Pool, Options, ChainApi, EventStream, ExtrinsicFor, ExtrinsicHash, + BlockHash, NumberFor, TransactionFor, ValidatedTransaction, }; diff --git a/client/transaction-pool/graph/src/listener.rs b/client/transaction-pool/graph/src/listener.rs index 92ba71007e209f6ef06d249864b25cdda191776b..1bc3720fa6b85e8eea21b75d1a15bffd9f210758 100644 --- a/client/transaction-pool/graph/src/listener.rs +++ b/client/transaction-pool/graph/src/listener.rs @@ -1,39 +1,41 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use std::{ - collections::HashMap, hash, + collections::HashMap, hash, fmt::Debug, }; use linked_hash_map::LinkedHashMap; use serde::Serialize; -use crate::{watcher, ChainApi, BlockHash}; +use crate::{watcher, ChainApi, ExtrinsicHash, BlockHash}; use log::{debug, trace, warn}; use sp_runtime::traits; /// Extrinsic pool default listener. pub struct Listener { - watchers: HashMap>>, - finality_watchers: LinkedHashMap, Vec>, + watchers: HashMap>>, + finality_watchers: LinkedHashMap, Vec>, } /// Maximum number of blocks awaiting finality at any time. const MAX_FINALITY_WATCHERS: usize = 512; -impl Default for Listener { +impl Default for Listener { fn default() -> Self { Listener { watchers: Default::default(), @@ -43,7 +45,7 @@ impl Default for Listener { } impl Listener { - fn fire(&mut self, hash: &H, fun: F) where F: FnOnce(&mut watcher::Sender>) { + fn fire(&mut self, hash: &H, fun: F) where F: FnOnce(&mut watcher::Sender>) { let clean = if let Some(h) = self.watchers.get_mut(hash) { fun(h); h.is_done() @@ -59,7 +61,7 @@ impl Listener { /// Creates a new watcher for given verified extrinsic. /// /// The watcher can be used to subscribe to life-cycle events of that extrinsic. - pub fn create_watcher(&mut self, hash: H) -> watcher::Watcher> { + pub fn create_watcher(&mut self, hash: H) -> watcher::Watcher> { let sender = self.watchers.entry(hash.clone()).or_insert_with(watcher::Sender::default); sender.new_watcher(hash) } @@ -72,7 +74,7 @@ impl Listener { /// New transaction was added to the ready pool or promoted from the future pool. pub fn ready(&mut self, tx: &H, old: Option<&H>) { - trace!(target: "txpool", "[{:?}] Ready (replaced: {:?})", tx, old); + trace!(target: "txpool", "[{:?}] Ready (replaced with {:?})", tx, old); self.fire(tx, |watcher| watcher.ready()); if let Some(old) = old { self.fire(old, |watcher| watcher.usurped(tx.clone())); @@ -87,7 +89,7 @@ impl Listener { /// Transaction was dropped from the pool because of the limit. pub fn dropped(&mut self, tx: &H, by: Option<&H>) { - trace!(target: "txpool", "[{:?}] Dropped (replaced by {:?})", tx, by); + trace!(target: "txpool", "[{:?}] Dropped (replaced with {:?})", tx, by); self.fire(tx, |watcher| match by { Some(t) => watcher.usurped(t.clone()), None => watcher.dropped(), @@ -97,9 +99,9 @@ impl Listener { /// Transaction was removed as invalid. pub fn invalid(&mut self, tx: &H, warn: bool) { if warn { - warn!(target: "txpool", "Extrinsic invalid: {:?}", tx); + warn!(target: "txpool", "[{:?}] Extrinsic invalid", tx); } else { - debug!(target: "txpool", "Extrinsic invalid: {:?}", tx); + debug!(target: "txpool", "[{:?}] Extrinsic invalid", tx); } self.fire(tx, |watcher| watcher.invalid()); } @@ -129,10 +131,12 @@ impl Listener { } /// Notify all watchers that transactions have been finalized - pub fn finalized(&mut self, block_hash: BlockHash, txs: Vec) { - self.finality_watchers.remove(&block_hash); - for h in txs { - self.fire(&h, |s| s.finalized(block_hash.clone())) + pub fn finalized(&mut self, block_hash: BlockHash) { + if let Some(hashes) = self.finality_watchers.remove(&block_hash) { + for hash in hashes { + log::debug!(target: "txpool", "[{:?}] Sent finalization event (block {:?})", hash, block_hash); + self.fire(&hash, |s| s.finalized(block_hash)) + } } } } diff --git a/client/transaction-pool/graph/src/pool.rs b/client/transaction-pool/graph/src/pool.rs index 0b817b155d8ecaef12aee3461e0e475d20b15a86..750d5f5d10eb745fe5e2c1f47c15d0974716b808 100644 --- a/client/transaction-pool/graph/src/pool.rs +++ b/client/transaction-pool/graph/src/pool.rs @@ -1,33 +1,32 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use std::{ - hash, collections::HashMap, sync::Arc, }; -use crate::base_pool as base; -use crate::watcher::Watcher; -use serde::Serialize; +use crate::{base_pool as base, watcher::Watcher}; -use futures::{Future, FutureExt}; +use futures::Future; use sp_runtime::{ generic::BlockId, - traits::{self, SaturatedConversion}, + traits::{self, SaturatedConversion, Block as BlockT}, transaction_validity::{ TransactionValidity, TransactionTag as Tag, TransactionValidityError, TransactionSource, }, @@ -42,19 +41,19 @@ pub use crate::validated_pool::ValidatedTransaction; /// Modification notification event stream type; pub type EventStream = TracingUnboundedReceiver; -/// Extrinsic hash type for a pool. -pub type ExHash = ::Hash; /// Block hash type for a pool. pub type BlockHash = <::Block as traits::Block>::Hash; +/// Extrinsic hash type for a pool. +pub type ExtrinsicHash = <::Block as traits::Block>::Hash; /// Extrinsic type for a pool. pub type ExtrinsicFor = <::Block as traits::Block>::Extrinsic; /// Block number type for the ChainApi pub type NumberFor = traits::NumberFor<::Block>; /// A type of transaction stored in the pool -pub type TransactionFor = Arc, ExtrinsicFor>>; +pub type TransactionFor = Arc, ExtrinsicFor>>; /// A type of validated transaction stored in the pool. pub type ValidatedTransactionFor = ValidatedTransaction< - ExHash, + ExtrinsicHash, ExtrinsicFor, ::Error, >; @@ -62,15 +61,15 @@ pub type ValidatedTransactionFor = ValidatedTransaction< /// Concrete extrinsic validation and query logic. pub trait ChainApi: Send + Sync { /// Block type. - type Block: traits::Block; - /// Transaction Hash type - type Hash: hash::Hash + Eq + traits::Member + Serialize; + type Block: BlockT; /// Error type. type Error: From + error::IntoPoolError; /// Validate transaction future. type ValidationFuture: Future> + Send + Unpin; /// Body future (since block body might be remote) - type BodyFuture: Future::Extrinsic>>, Self::Error>> + Unpin + Send + 'static; + type BodyFuture: Future< + Output = Result::Extrinsic>>, Self::Error> + > + Unpin + Send + 'static; /// Verify extrinsic at given block. fn validate_transaction( @@ -81,13 +80,19 @@ pub trait ChainApi: Send + Sync { ) -> Self::ValidationFuture; /// Returns a block number given the block id. - fn block_id_to_number(&self, at: &BlockId) -> Result>, Self::Error>; + fn block_id_to_number( + &self, + at: &BlockId, + ) -> Result>, Self::Error>; /// Returns a block hash given the block id. - fn block_id_to_hash(&self, at: &BlockId) -> Result>, Self::Error>; + fn block_id_to_hash( + &self, + at: &BlockId, + ) -> Result::Hash>, Self::Error>; /// Returns hash and encoding length of the extrinsic. - fn hash_and_length(&self, uxt: &ExtrinsicFor) -> (Self::Hash, usize); + fn hash_and_length(&self, uxt: &ExtrinsicFor) -> (ExtrinsicHash, usize); /// Returns a block body given the block id. fn block_body(&self, at: &BlockId) -> Self::BodyFuture; @@ -120,6 +125,14 @@ impl Default for Options { } } +/// Should we check that the transaction is banned +/// in the pool, before we verify it? +#[derive(Copy, Clone)] +enum CheckBannedBeforeVerify { + Yes, + No, +} + /// Extrinsics pool that performs validation. pub struct Pool { validated_pool: Arc>, @@ -128,7 +141,6 @@ pub struct Pool { #[cfg(not(target_os = "unknown"))] impl parity_util_mem::MallocSizeOf for Pool where - B::Hash: parity_util_mem::MallocSizeOf, ExtrinsicFor: parity_util_mem::MallocSizeOf, { fn size_of(&self, ops: &mut parity_util_mem::MallocSizeOfOps) -> usize { @@ -145,23 +157,29 @@ impl Pool { } /// Imports a bunch of unverified extrinsics to the pool - pub async fn submit_at( + pub async fn submit_at( + &self, + at: &BlockId, + source: TransactionSource, + xts: impl IntoIterator>, + ) -> Result, B::Error>>, B::Error> { + let xts = xts.into_iter().map(|xt| (source, xt)); + let validated_transactions = self.verify(at, xts, CheckBannedBeforeVerify::Yes).await?; + Ok(self.validated_pool.submit(validated_transactions.into_iter().map(|(_, tx)| tx))) + } + + /// Resubmit the given extrinsics to the pool. + /// + /// This does not check if a transaction is banned, before we verify it again. + pub async fn resubmit_at( &self, at: &BlockId, source: TransactionSource, - xts: T, - force: bool, - ) -> Result, B::Error>>, B::Error> where - T: IntoIterator>, - { - let validated_pool = self.validated_pool.clone(); + xts: impl IntoIterator>, + ) -> Result, B::Error>>, B::Error> { let xts = xts.into_iter().map(|xt| (source, xt)); - self.verify(at, xts, force) - .map(move |validated_transactions| validated_transactions - .map(|validated_transactions| validated_pool.submit(validated_transactions - .into_iter() - .map(|(_, tx)| tx)))) - .await + let validated_transactions = self.verify(at, xts, CheckBannedBeforeVerify::No).await?; + Ok(self.validated_pool.submit(validated_transactions.into_iter().map(|(_, tx)| tx))) } /// Imports one unverified extrinsic to the pool @@ -170,13 +188,9 @@ impl Pool { at: &BlockId, source: TransactionSource, xt: ExtrinsicFor, - ) -> Result, B::Error> { - self.submit_at(at, source, 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") - )) - .await + ) -> Result, B::Error> { + let res = self.submit_at(at, source, std::iter::once(xt)).await?.pop(); + res.expect("One extrinsic passed; one result returned; qed") } /// Import a single extrinsic and starts to watch their progress in the pool. @@ -185,10 +199,14 @@ impl Pool { at: &BlockId, source: TransactionSource, xt: ExtrinsicFor, - ) -> Result, BlockHash>, B::Error> { + ) -> Result, ExtrinsicHash>, B::Error> { let block_number = self.resolve_block_number(at)?; let (_, tx) = self.verify_one( - at, block_number, source, xt, false + at, + block_number, + source, + xt, + CheckBannedBeforeVerify::Yes, ).await; self.validated_pool.submit_and_watch(tx) } @@ -196,7 +214,7 @@ impl Pool { /// Resubmit some transaction that were validated elsewhere. pub fn resubmit( &self, - revalidated_transactions: HashMap, ValidatedTransactionFor>, + revalidated_transactions: HashMap, ValidatedTransactionFor>, ) { let now = Instant::now(); @@ -213,7 +231,11 @@ impl Pool { /// Used to clear the pool from transactions that were part of recently imported block. /// The main difference from the `prune` is that we do not revalidate any transactions /// and ignore unknown passed hashes. - pub fn prune_known(&self, at: &BlockId, hashes: &[ExHash]) -> Result<(), B::Error> { + pub fn prune_known( + &self, + at: &BlockId, + hashes: &[ExtrinsicHash], + ) -> Result<(), B::Error> { // Get details of all extrinsics that are already in the pool let in_pool_tags = self.validated_pool.extrinsics_tags(hashes) .into_iter().filter_map(|x| x).flat_map(|x| x); @@ -297,7 +319,7 @@ impl Pool { &self, at: &BlockId, tags: impl IntoIterator, - known_imported_hashes: impl IntoIterator> + Clone, + known_imported_hashes: impl IntoIterator> + Clone, ) -> Result<(), B::Error> { log::debug!(target: "txpool", "Pruning at {:?}", at); // Prune all transactions that provide given tags @@ -320,7 +342,11 @@ impl Pool { .into_iter() .map(|tx| (tx.source, tx.data.clone())); - let reverified_transactions = self.verify(at, pruned_transactions, false).await?; + let reverified_transactions = self.verify( + at, + pruned_transactions, + CheckBannedBeforeVerify::Yes, + ).await?; log::trace!(target: "txpool", "Pruning at {:?}. Resubmitting transactions.", at); // And finally - submit reverified transactions back to the pool @@ -334,7 +360,7 @@ impl Pool { } /// Returns transaction hash - pub fn hash_of(&self, xt: &ExtrinsicFor) -> ExHash { + pub fn hash_of(&self, xt: &ExtrinsicFor) -> ExtrinsicHash { self.validated_pool.api().hash_and_length(xt).0 } @@ -350,23 +376,17 @@ impl Pool { &self, at: &BlockId, xts: impl IntoIterator)>, - force: bool, - ) -> Result, ValidatedTransactionFor>, B::Error> { + check: CheckBannedBeforeVerify, + ) -> Result, ValidatedTransactionFor>, B::Error> { // we need a block number to compute tx validity let block_number = self.resolve_block_number(at)?; - let mut result = HashMap::new(); - - for (hash, validated_tx) in - futures::future::join_all( - xts.into_iter() - .map(|(source, xt)| self.verify_one(at, block_number, source, xt, force)) - ) - .await - { - result.insert(hash, validated_tx); - } - Ok(result) + let res = futures::future::join_all( + xts.into_iter() + .map(|(source, xt)| self.verify_one(at, block_number, source, xt, check)) + ).await.into_iter().collect::>(); + + Ok(res) } /// Returns future that validates single transaction at given block. @@ -376,14 +396,13 @@ impl Pool { block_number: NumberFor, source: TransactionSource, xt: ExtrinsicFor, - force: bool, - ) -> (ExHash, ValidatedTransactionFor) { + check: CheckBannedBeforeVerify, + ) -> (ExtrinsicHash, ValidatedTransactionFor) { let (hash, bytes) = self.validated_pool.api().hash_and_length(&xt); - if !force && self.validated_pool.is_banned(&hash) { - return ( - hash.clone(), - ValidatedTransaction::Invalid(hash, error::Error::TemporarilyBanned.into()), - ) + + let ignore_banned = matches!(check, CheckBannedBeforeVerify::No); + if let Err(err) = self.validated_pool.check_is_known(&hash, ignore_banned) { + return (hash.clone(), ValidatedTransaction::Invalid(hash, err.into())) } let validation_result = self.validated_pool.api().validate_transaction( @@ -442,9 +461,12 @@ mod tests { use futures::executor::block_on; use super::*; use sp_transaction_pool::TransactionStatus; - use sp_runtime::transaction_validity::{ValidTransaction, InvalidTransaction, TransactionSource}; + use sp_runtime::{ + traits::Hash, + transaction_validity::{ValidTransaction, InvalidTransaction, TransactionSource}, + }; use codec::Encode; - use substrate_test_runtime::{Block, Extrinsic, Transfer, H256, AccountId}; + use substrate_test_runtime::{Block, Extrinsic, Transfer, H256, AccountId, Hashing}; use assert_matches::assert_matches; use wasm_timer::Instant; use crate::base_pool::Limit; @@ -455,14 +477,13 @@ mod tests { #[derive(Clone, Debug, Default)] struct TestApi { delay: Arc>>>, - invalidate: Arc>>, - clear_requirements: Arc>>, - add_requirements: Arc>>, + invalidate: Arc>>, + clear_requirements: Arc>>, + add_requirements: Arc>>, } impl ChainApi for TestApi { type Block = Block; - type Hash = u64; type Error = error::Error; type ValidationFuture = futures::future::Ready>; type BodyFuture = futures::future::Ready>>>; @@ -516,7 +537,10 @@ mod tests { } /// Returns a block number given the block id. - fn block_id_to_number(&self, at: &BlockId) -> Result>, Self::Error> { + fn block_id_to_number( + &self, + at: &BlockId, + ) -> Result>, Self::Error> { Ok(match at { BlockId::Number(num) => Some(*num), BlockId::Hash(_) => None, @@ -524,7 +548,10 @@ mod tests { } /// Returns a block hash given the block id. - fn block_id_to_hash(&self, at: &BlockId) -> Result>, Self::Error> { + fn block_id_to_hash( + &self, + at: &BlockId, + ) -> Result::Hash>, Self::Error> { Ok(match at { BlockId::Number(num) => Some(H256::from_low_u64_be(*num)).into(), BlockId::Hash(_) => None, @@ -532,12 +559,10 @@ mod tests { } /// Hash the extrinsic. - fn hash_and_length(&self, uxt: &ExtrinsicFor) -> (Self::Hash, usize) { - let len = uxt.encode().len(); - ( - (H256::from(uxt.transfer().from.clone()).to_low_u64_be() << 5) + uxt.transfer().nonce, - len - ) + fn hash_and_length(&self, uxt: &ExtrinsicFor) -> (BlockHash, usize) { + let encoded = uxt.encode(); + let len = encoded.len(); + (Hashing::hash(&encoded), len) } fn block_body(&self, _id: &BlockId) -> Self::BodyFuture { @@ -597,19 +622,19 @@ mod tests { #[test] fn should_notify_about_pool_events() { - let stream = { + let (stream, hash0, hash1) = { // given let pool = pool(); let stream = pool.validated_pool().import_notification_stream(); // when - let _hash = block_on(pool.submit_one(&BlockId::Number(0), SOURCE, uxt(Transfer { + let hash0 = block_on(pool.submit_one(&BlockId::Number(0), SOURCE, 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 = block_on(pool.submit_one(&BlockId::Number(0), SOURCE, uxt(Transfer { + let hash1 = block_on(pool.submit_one(&BlockId::Number(0), SOURCE, uxt(Transfer { from: AccountId::from_h256(H256::from_low_u64_be(1)), to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, @@ -625,13 +650,14 @@ mod tests { assert_eq!(pool.validated_pool().status().ready, 2); assert_eq!(pool.validated_pool().status().future, 1); - stream + + (stream, hash0, hash1) }; // then let mut it = futures::executor::block_on_stream(stream); - assert_eq!(it.next(), Some(32)); - assert_eq!(it.next(), Some(33)); + assert_eq!(it.next(), Some(hash0)); + assert_eq!(it.next(), Some(hash1)); assert_eq!(it.next(), None); } @@ -793,7 +819,10 @@ mod tests { // then let mut stream = futures::executor::block_on_stream(watcher.into_stream()); assert_eq!(stream.next(), Some(TransactionStatus::Ready)); - assert_eq!(stream.next(), Some(TransactionStatus::InBlock(H256::from_low_u64_be(2).into()))); + assert_eq!( + stream.next(), + Some(TransactionStatus::InBlock(H256::from_low_u64_be(2).into())), + ); } #[test] @@ -810,14 +839,19 @@ mod tests { assert_eq!(pool.validated_pool().status().future, 0); // when - block_on(pool.prune_tags(&BlockId::Number(2), vec![vec![0u8]], vec![2u64])).unwrap(); + block_on( + pool.prune_tags(&BlockId::Number(2), vec![vec![0u8]], vec![watcher.hash().clone()]), + ).unwrap(); assert_eq!(pool.validated_pool().status().ready, 0); assert_eq!(pool.validated_pool().status().future, 0); // then let mut stream = futures::executor::block_on_stream(watcher.into_stream()); assert_eq!(stream.next(), Some(TransactionStatus::Ready)); - assert_eq!(stream.next(), Some(TransactionStatus::InBlock(H256::from_low_u64_be(2).into()))); + assert_eq!( + stream.next(), + Some(TransactionStatus::InBlock(H256::from_low_u64_be(2).into())), + ); } #[test] diff --git a/client/transaction-pool/graph/src/ready.rs b/client/transaction-pool/graph/src/ready.rs index c856535a6165140844a339d0539aa291236a561f..b98512b05d5cfc4418f3b11a9e0cba74d9453b66 100644 --- a/client/transaction-pool/graph/src/ready.rs +++ b/client/transaction-pool/graph/src/ready.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use std::{ collections::{HashMap, HashSet, BTreeSet}, @@ -23,15 +25,17 @@ use std::{ use serde::Serialize; use log::trace; -use parking_lot::RwLock; use sp_runtime::traits::Member; use sp_runtime::transaction_validity::{ TransactionTag as Tag, }; use sp_transaction_pool::error; -use crate::future::WaitingTransaction; -use crate::base_pool::Transaction; +use crate::{ + base_pool::Transaction, + future::WaitingTransaction, + tracked_map::{self, ReadOnlyTrackedMap, TrackedMap}, +}; /// An in-pool transaction reference. /// @@ -111,11 +115,17 @@ pub struct ReadyTransactions { /// tags that are provided by Ready transactions provided_tags: HashMap, /// Transactions that are ready (i.e. don't have any requirements external to the pool) - ready: Arc>>>, + ready: TrackedMap>, /// Best transactions that are ready to be included to the block without any other previous transaction. best: BTreeSet>, } +impl tracked_map::Size for ReadyTx { + fn size(&self) -> usize { + self.transaction.transaction.bytes + } +} + impl Default for ReadyTransactions { fn default() -> Self { ReadyTransactions { @@ -265,12 +275,7 @@ impl ReadyTransactions { ) -> Vec>> { let mut removed = vec![]; let mut ready = self.ready.write(); - loop { - let hash = match to_remove.pop() { - Some(hash) => hash, - None => return removed, - }; - + while let Some(hash) = to_remove.pop() { if let Some(mut tx) = ready.remove(&hash) { let invalidated = tx.transaction.transaction.provides .iter() @@ -309,6 +314,8 @@ impl ReadyTransactions { removed.push(tx.transaction.transaction); } } + + removed } /// Removes transactions that provide given tag. @@ -320,17 +327,16 @@ impl ReadyTransactions { let mut removed = vec![]; let mut to_remove = vec![tag]; - loop { - let tag = match to_remove.pop() { - Some(tag) => tag, - None => return removed, - }; - + while let Some(tag) = to_remove.pop() { let res = self.provided_tags.remove(&tag) - .and_then(|hash| self.ready.write().remove(&hash)); + .and_then(|hash| self.ready.write().remove(&hash)); if let Some(tx) = res { let unlocks = tx.unlocks; + + // Make sure we remove it from best txs + self.best.remove(&tx.transaction); + let tx = tx.transaction.transaction; // prune previous transactions as well @@ -393,6 +399,8 @@ impl ReadyTransactions { removed.push(tx); } } + + removed } /// Checks if the transaction is providing the same tags as other transactions. @@ -466,18 +474,18 @@ impl ReadyTransactions { /// Returns number of transactions in this queue. pub fn len(&self) -> usize { - self.ready.read().len() + self.ready.len() } /// Returns sum of encoding lengths of all transactions in this queue. pub fn bytes(&self) -> usize { - self.ready.read().values().fold(0, |acc, tx| acc + tx.transaction.transaction.bytes) + self.ready.bytes() } } /// Iterator of ready transactions ordered by priority. pub struct BestIterator { - all: Arc>>>, + all: ReadOnlyTrackedMap>, awaiting: HashMap)>, best: BTreeSet>, } diff --git a/client/transaction-pool/graph/src/rotator.rs b/client/transaction-pool/graph/src/rotator.rs index be96174d1d91696832201bae8d9c6db4d1d0769f..65e21d0d4b5068262a6caf00add896ab51f4a710 100644 --- a/client/transaction-pool/graph/src/rotator.rs +++ b/client/transaction-pool/graph/src/rotator.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Rotate extrinsic inside the pool. //! diff --git a/client/transaction-pool/graph/src/tracked_map.rs b/client/transaction-pool/graph/src/tracked_map.rs new file mode 100644 index 0000000000000000000000000000000000000000..c799eb0b96ea146b16951d3822502a55940b763b --- /dev/null +++ b/client/transaction-pool/graph/src/tracked_map.rs @@ -0,0 +1,189 @@ +// This file is part of Substrate. + +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use std::{ + collections::HashMap, + sync::{Arc, atomic::{AtomicIsize, Ordering as AtomicOrdering}}, +}; +use parking_lot::{RwLock, RwLockWriteGuard, RwLockReadGuard}; + +/// Something that can report it's size. +pub trait Size { + fn size(&self) -> usize; +} + +/// Map with size tracking. +/// +/// Size reported might be slightly off and only approximately true. +#[derive(Debug, parity_util_mem::MallocSizeOf)] +pub struct TrackedMap { + index: Arc>>, + bytes: AtomicIsize, + length: AtomicIsize, +} + +impl Default for TrackedMap { + fn default() -> Self { + Self { + index: Arc::new(HashMap::default().into()), + bytes: 0.into(), + length: 0.into(), + } + } +} + +impl TrackedMap { + /// Current tracked length of the content. + pub fn len(&self) -> usize { + std::cmp::max(self.length.load(AtomicOrdering::Relaxed), 0) as usize + } + + /// Current sum of content length. + pub fn bytes(&self) -> usize { + std::cmp::max(self.bytes.load(AtomicOrdering::Relaxed), 0) as usize + } + + /// Read-only clone of the interior. + pub fn clone(&self) -> ReadOnlyTrackedMap { + ReadOnlyTrackedMap(self.index.clone()) + } + + /// Lock map for read. + pub fn read<'a>(&'a self) -> TrackedMapReadAccess<'a, K, V> { + TrackedMapReadAccess { + inner_guard: self.index.read(), + } + } + + /// Lock map for write. + pub fn write<'a>(&'a self) -> TrackedMapWriteAccess<'a, K, V> { + TrackedMapWriteAccess { + inner_guard: self.index.write(), + bytes: &self.bytes, + length: &self.length, + } + } +} + +/// Read-only access to map. +/// +/// The only thing can be done is .read(). +pub struct ReadOnlyTrackedMap(Arc>>); + +impl ReadOnlyTrackedMap +where + K: Eq + std::hash::Hash +{ + /// Lock map for read. + pub fn read<'a>(&'a self) -> TrackedMapReadAccess<'a, K, V> { + TrackedMapReadAccess { + inner_guard: self.0.read(), + } + } +} + +pub struct TrackedMapReadAccess<'a, K, V> { + inner_guard: RwLockReadGuard<'a, HashMap>, +} + +impl<'a, K, V> TrackedMapReadAccess<'a, K, V> +where + K: Eq + std::hash::Hash +{ + /// Returns true if map contains key. + pub fn contains_key(&self, key: &K) -> bool { + self.inner_guard.contains_key(key) + } + + /// Returns reference to the contained value by key, if exists. + pub fn get(&self, key: &K) -> Option<&V> { + self.inner_guard.get(key) + } + + /// Returns iterator over all values. + pub fn values(&self) -> std::collections::hash_map::Values { + self.inner_guard.values() + } +} + +pub struct TrackedMapWriteAccess<'a, K, V> { + bytes: &'a AtomicIsize, + length: &'a AtomicIsize, + inner_guard: RwLockWriteGuard<'a, HashMap>, +} + +impl<'a, K, V> TrackedMapWriteAccess<'a, K, V> +where + K: Eq + std::hash::Hash, V: Size +{ + /// Insert value and return previous (if any). + pub fn insert(&mut self, key: K, val: V) -> Option { + let new_bytes = val.size(); + self.bytes.fetch_add(new_bytes as isize, AtomicOrdering::Relaxed); + self.length.fetch_add(1, AtomicOrdering::Relaxed); + self.inner_guard.insert(key, val).and_then(|old_val| { + self.bytes.fetch_sub(old_val.size() as isize, AtomicOrdering::Relaxed); + self.length.fetch_sub(1, AtomicOrdering::Relaxed); + Some(old_val) + }) + } + + /// Remove value by key. + pub fn remove(&mut self, key: &K) -> Option { + let val = self.inner_guard.remove(key); + if let Some(size) = val.as_ref().map(Size::size) { + self.bytes.fetch_sub(size as isize, AtomicOrdering::Relaxed); + self.length.fetch_sub(1, AtomicOrdering::Relaxed); + } + val + } + + /// Returns mutable reference to the contained value by key, if exists. + pub fn get_mut(&mut self, key: &K) -> Option<&mut V> { + self.inner_guard.get_mut(key) + } +} + +#[cfg(test)] +mod tests { + + use super::*; + + impl Size for i32 { + fn size(&self) -> usize { *self as usize / 10 } + } + + #[test] + fn basic() { + let map = TrackedMap::default(); + map.write().insert(5, 10); + map.write().insert(6, 20); + + assert_eq!(map.bytes(), 3); + assert_eq!(map.len(), 2); + + map.write().insert(6, 30); + + assert_eq!(map.bytes(), 4); + assert_eq!(map.len(), 2); + + map.write().remove(&6); + assert_eq!(map.bytes(), 1); + assert_eq!(map.len(), 1); + } +} \ No newline at end of file diff --git a/client/transaction-pool/graph/src/validated_pool.rs b/client/transaction-pool/graph/src/validated_pool.rs index 2ff2acfe24fc8db886c2639fd8a9d2c346642532..bde76196ec4c5052aedf3212c4a2be022576d6dd 100644 --- a/client/transaction-pool/graph/src/validated_pool.rs +++ b/client/transaction-pool/graph/src/validated_pool.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use std::{ collections::{HashSet, HashMap}, @@ -20,12 +22,11 @@ use std::{ sync::Arc, }; -use crate::{base_pool as base, BlockHash}; +use crate::base_pool as base; use crate::listener::Listener; use crate::rotator::PoolRotator; use crate::watcher::Watcher; use serde::Serialize; -use log::{debug, warn}; use parking_lot::{Mutex, RwLock}; use sp_runtime::{ @@ -38,7 +39,9 @@ use wasm_timer::Instant; use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedSender}; use crate::base_pool::PruneStatus; -use crate::pool::{EventStream, Options, ChainApi, ExHash, ExtrinsicFor, TransactionFor}; +use crate::pool::{ + EventStream, Options, ChainApi, BlockHash, ExtrinsicHash, ExtrinsicFor, TransactionFor, +}; /// Pre-validated transaction. Validated pool only accepts transactions wrapped in this enum. #[derive(Debug)] @@ -81,7 +84,7 @@ impl ValidatedTransaction { /// A type of validated transaction stored in the pool. pub type ValidatedTransactionFor = ValidatedTransaction< - ExHash, + ExtrinsicHash, ExtrinsicFor, ::Error, >; @@ -90,19 +93,18 @@ pub type ValidatedTransactionFor = ValidatedTransaction< pub struct ValidatedPool { api: Arc, options: Options, - listener: RwLock, B>>, + listener: RwLock, B>>, pool: RwLock, + ExtrinsicHash, ExtrinsicFor, >>, - import_notification_sinks: Mutex>>>, - rotator: PoolRotator>, + import_notification_sinks: Mutex>>>, + rotator: PoolRotator>, } #[cfg(not(target_os = "unknown"))] impl parity_util_mem::MallocSizeOf for ValidatedPool where - B::Hash: parity_util_mem::MallocSizeOf, ExtrinsicFor: parity_util_mem::MallocSizeOf, { fn size_of(&self, ops: &mut parity_util_mem::MallocSizeOfOps) -> usize { @@ -126,19 +128,39 @@ impl ValidatedPool { } /// Bans given set of hashes. - pub fn ban(&self, now: &Instant, hashes: impl IntoIterator>) { + pub fn ban(&self, now: &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 { + pub fn is_banned(&self, hash: &ExtrinsicHash) -> bool { self.rotator.is_banned(hash) } + /// A fast check before doing any further processing of a transaction, like validation. + /// + /// If `ingore_banned` is `true`, it will not check if the transaction is banned. + /// + /// It checks if the transaction is already imported or banned. If so, it returns an error. + pub fn check_is_known( + &self, + tx_hash: &ExtrinsicHash, + ignore_banned: bool, + ) -> Result<(), B::Error> { + if !ignore_banned && self.is_banned(tx_hash) { + Err(error::Error::TemporarilyBanned.into()) + } else if self.pool.read().is_imported(tx_hash) { + Err(error::Error::AlreadyImported(Box::new(tx_hash.clone())).into()) + } else { + Ok(()) + } + } + /// Imports a bunch of pre-validated transactions to the pool. - pub fn submit(&self, txs: T) -> Vec, B::Error>> where - T: IntoIterator> - { + pub fn submit( + &self, + txs: impl IntoIterator>, + ) -> Vec, B::Error>> { let results = txs.into_iter() .map(|validated_tx| self.submit_one(validated_tx)) .collect::>(); @@ -157,7 +179,7 @@ impl ValidatedPool { } /// Submit single pre-validated transaction to the pool. - fn submit_one(&self, tx: ValidatedTransactionFor) -> Result, B::Error> { + fn submit_one(&self, tx: ValidatedTransactionFor) -> Result, B::Error> { match tx { ValidatedTransaction::Valid(tx) => { let imported = self.pool.write().import(tx)?; @@ -182,16 +204,16 @@ impl ValidatedPool { } } - fn enforce_limits(&self) -> HashSet> { + 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); + log::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) { - debug!( + log::debug!( target: "txpool", "Enforcing limits ({}/{}kB ready, {}/{}kB future", ready_limit.count, ready_limit.total_bytes / 1024, @@ -207,8 +229,11 @@ impl ValidatedPool { self.rotator.ban(&Instant::now(), removed.iter().map(|x| x.clone())); removed }; + if !removed.is_empty() { + log::debug!(target: "txpool", "Enforcing limits: {} dropped", removed.len()); + } + // run notifications - debug!(target: "txpool", "Enforcing limits: {} dropped", removed.len()); let mut listener = self.listener.write(); for h in &removed { listener.dropped(h, None); @@ -224,7 +249,7 @@ impl ValidatedPool { pub fn submit_and_watch( &self, tx: ValidatedTransactionFor, - ) -> Result, BlockHash>, B::Error> { + ) -> Result, ExtrinsicHash>, B::Error> { match tx { ValidatedTransaction::Valid(tx) => { let hash = self.api.hash_and_length(&tx.data).0; @@ -246,7 +271,7 @@ impl ValidatedPool { /// /// Removes and then submits passed transactions and all dependent transactions. /// Transactions that are missing from the pool are not submitted. - pub fn resubmit(&self, mut updated_transactions: HashMap, ValidatedTransactionFor>) { + pub fn resubmit(&self, mut updated_transactions: HashMap, ValidatedTransactionFor>) { #[derive(Debug, Clone, Copy, PartialEq)] enum Status { Future, Ready, Failed, Dropped }; @@ -322,7 +347,7 @@ impl ValidatedPool { // we do not want to fail if single transaction import has failed // nor we do want to propagate this error, because it could tx unknown to caller // => let's just notify listeners (and issue debug message) - warn!( + log::warn!( target: "txpool", "[{:?}] Removing invalid transaction from update: {}", hash, @@ -365,7 +390,7 @@ impl ValidatedPool { } /// For each extrinsic, returns tags that it provides (if known), or None (if it is unknown). - pub fn extrinsics_tags(&self, hashes: &[ExHash]) -> Vec>> { + pub fn extrinsics_tags(&self, hashes: &[ExtrinsicHash]) -> Vec>> { self.pool.read().by_hashes(&hashes) .into_iter() .map(|existing_in_pool| existing_in_pool @@ -374,7 +399,7 @@ impl ValidatedPool { } /// Get ready transaction by hash - pub fn ready_by_hash(&self, hash: &ExHash) -> Option> { + pub fn ready_by_hash(&self, hash: &ExtrinsicHash) -> Option> { self.pool.read().ready_by_hash(hash) } @@ -382,7 +407,7 @@ impl ValidatedPool { pub fn prune_tags( &self, tags: impl IntoIterator, - ) -> Result, ExtrinsicFor>, B::Error> { + ) -> 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 @@ -404,8 +429,8 @@ impl ValidatedPool { pub fn resubmit_pruned( &self, at: &BlockId, - known_imported_hashes: impl IntoIterator> + Clone, - pruned_hashes: Vec>, + known_imported_hashes: impl IntoIterator> + Clone, + pruned_hashes: Vec>, pruned_xts: Vec>, ) -> Result<(), B::Error> { debug_assert_eq!(pruned_hashes.len(), pruned_xts.len()); @@ -436,7 +461,7 @@ impl ValidatedPool { pub fn fire_pruned( &self, at: &BlockId, - hashes: impl Iterator>, + hashes: impl Iterator>, ) -> Result<(), B::Error> { let header_hash = self.api.block_id_to_hash(at)? .ok_or_else(|| error::Error::InvalidBlockId(format!("{:?}", at)).into())?; @@ -469,7 +494,7 @@ impl ValidatedPool { .map(|tx| tx.hash.clone()) .collect::>() }; - let futures_to_remove: Vec> = { + let futures_to_remove: Vec> = { let p = self.pool.read(); let mut hashes = Vec::new(); for tx in p.futures() { @@ -490,7 +515,7 @@ impl ValidatedPool { /// Get rotator reference. #[cfg(test)] - pub fn rotator(&self) -> &PoolRotator> { + pub fn rotator(&self) -> &PoolRotator> { &self.rotator } @@ -503,14 +528,14 @@ impl ValidatedPool { /// /// Consumers of this stream should use the `ready` method to actually get the /// pending transactions in the right order. - pub fn import_notification_stream(&self) -> EventStream> { + pub fn import_notification_stream(&self) -> EventStream> { let (sink, stream) = tracing_unbounded("mpsc_import_notifications"); self.import_notification_sinks.lock().push(sink); stream } /// Invoked when extrinsics are broadcasted. - pub fn on_broadcasted(&self, propagated: HashMap, Vec>) { + 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); @@ -523,20 +548,20 @@ impl ValidatedPool { /// to prevent them from entering the pool right away. /// Note this is not the case for the dependent transactions - those may /// still be valid so we want to be able to re-import them. - pub fn remove_invalid(&self, hashes: &[ExHash]) -> Vec> { + pub fn remove_invalid(&self, hashes: &[ExtrinsicHash]) -> Vec> { // early exit in case there is no invalid transactions. if hashes.is_empty() { return vec![]; } - debug!(target: "txpool", "Removing invalid transactions: {:?}", hashes); + log::debug!(target: "txpool", "Removing invalid transactions: {:?}", hashes); // temporarily ban invalid transactions self.rotator.ban(&Instant::now(), hashes.iter().cloned()); let invalid = self.pool.write().remove_subtree(hashes); - debug!(target: "txpool", "Removed invalid transactions: {:?}", invalid); + log::debug!(target: "txpool", "Removed invalid transactions: {:?}", invalid); let mut listener = self.listener.write(); for tx in &invalid { @@ -558,16 +583,8 @@ impl ValidatedPool { /// Notify all watchers that transactions in the block with hash have been finalized pub async fn on_block_finalized(&self, block_hash: BlockHash) -> Result<(), B::Error> { - debug!(target: "txpool", "Attempting to notify watchers of finalization for {}", block_hash); - // fetch all extrinsic hashes - if let Some(txs) = self.api.block_body(&BlockId::Hash(block_hash.clone())).await? { - let tx_hashes = txs.into_iter() - .map(|tx| self.api.hash_and_length(&tx).0) - .collect::>(); - // notify the watcher that these extrinsics have been finalized - self.listener.write().finalized(block_hash, tx_hashes); - } - + log::trace!(target: "txpool", "Attempting to notify watchers of finalization for {}", block_hash); + self.listener.write().finalized(block_hash); Ok(()) } diff --git a/client/transaction-pool/graph/src/watcher.rs b/client/transaction-pool/graph/src/watcher.rs index d54cc2718b7cbf40f33633df249d7a8d36da826a..9d9a91bb23f69acb0ad42a1eba4dcadecc856c66 100644 --- a/client/transaction-pool/graph/src/watcher.rs +++ b/client/transaction-pool/graph/src/watcher.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Extrinsics status updates. diff --git a/client/transaction-pool/src/api.rs b/client/transaction-pool/src/api.rs index bf104c8d78191c231b7102e97d31ccdf1237fefa..a14d5b0db18ea2001291cf972538287c9d2ba458 100644 --- a/client/transaction-pool/src/api.rs +++ b/client/transaction-pool/src/api.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Chain api required for the transaction pool. @@ -23,9 +25,7 @@ use futures::{ }; use sc_client_api::{ - blockchain::HeaderBackend, - light::{Fetcher, RemoteCallRequest, RemoteBodyRequest}, - BlockBackend, + blockchain::HeaderBackend, light::{Fetcher, RemoteCallRequest, RemoteBodyRequest}, BlockBackend, }; use sp_runtime::{ generic::BlockId, traits::{self, Block as BlockT, BlockIdTo, Header as HeaderT, Hash as HashT}, @@ -33,22 +33,38 @@ use sp_runtime::{ }; use sp_transaction_pool::runtime_api::TaggedTransactionQueue; use sp_api::{ProvideRuntimeApi, ApiExt}; +use prometheus_endpoint::Registry as PrometheusRegistry; -use crate::error::{self, Error}; +use crate::{metrics::{ApiMetrics, ApiMetricsExt}, error::{self, Error}}; /// The transaction pool logic for full client. pub struct FullChainApi { client: Arc, pool: ThreadPool, _marker: PhantomData, + metrics: Option>, } -impl FullChainApi where - Block: BlockT, - Client: ProvideRuntimeApi + BlockIdTo, -{ +impl FullChainApi { /// Create new transaction pool logic. - pub fn new(client: Arc) -> Self { + pub fn new( + client: Arc, + prometheus: Option<&PrometheusRegistry>, + ) -> Self { + let metrics = prometheus.map(ApiMetrics::register).and_then(|r| { + match r { + Err(err) => { + log::warn!( + target: "txpool", + "Failed to register transaction pool api prometheus metrics: {:?}", + err, + ); + None + }, + Ok(api) => Some(Arc::new(api)) + } + }); + FullChainApi { client, pool: ThreadPoolBuilder::new() @@ -56,22 +72,25 @@ impl FullChainApi where .name_prefix("txpool-verifier") .create() .expect("Failed to spawn verifier threads, that are critical for node operation."), - _marker: Default::default() + _marker: Default::default(), + metrics, } } } -impl sc_transaction_graph::ChainApi for FullChainApi where +impl sc_transaction_graph::ChainApi for FullChainApi +where Block: BlockT, Client: ProvideRuntimeApi + BlockBackend + BlockIdTo, Client: Send + Sync + 'static, Client::Api: TaggedTransactionQueue, - sp_api::ApiErrorFor: Send, + sp_api::ApiErrorFor: Send + std::fmt::Display, { type Block = Block; - type Hash = Block::Hash; type Error = error::Error; - type ValidationFuture = Pin> + Send>>; + type ValidationFuture = Pin< + Box> + Send> + >; type BodyFuture = Ready::Extrinsic>>>>; fn block_body(&self, id: &BlockId) -> Self::BodyFuture { @@ -88,24 +107,19 @@ impl sc_transaction_graph::ChainApi for FullChainApi, _>( - &at, |v| v >= 2, - ) - .unwrap_or_default(); - let res = if has_v2 { - runtime_api.validate_transaction(&at, source, uxt) - } else { - #[allow(deprecated)] // old validate_transaction - runtime_api.validate_transaction_before_version_2(&at, uxt) - }; - let res = res.map_err(|e| Error::RuntimeApi(format!("{:?}", e))); - if let Err(e) = tx.send(res) { - log::warn!("Unable to send a validate transaction result: {:?}", e); - } - })); + let metrics = self.metrics.clone(); + metrics.report(|m| m.validations_scheduled.inc()); + + self.pool.spawn_ok(futures_diagnose::diagnose( + "validate-transaction", + async move { + let res = validate_transaction_blocking(&*client, &at, source, uxt); + if let Err(e) = tx.send(res) { + log::warn!("Unable to send a validate transaction result: {:?}", e); + } + metrics.report(|m| m.validations_finished.inc()); + }, + )); Box::pin(async move { match rx.await { @@ -129,13 +143,72 @@ impl sc_transaction_graph::ChainApi for FullChainApi) -> (Self::Hash, usize) { + fn hash_and_length( + &self, + ex: &sc_transaction_graph::ExtrinsicFor, + ) -> (sc_transaction_graph::ExtrinsicHash, usize) { ex.using_encoded(|x| { ( as traits::Hash>::hash(x), x.len()) }) } } +/// Helper function to validate a transaction using a full chain API. +/// This method will call into the runtime to perform the validation. +fn validate_transaction_blocking( + client: &Client, + at: &BlockId, + source: TransactionSource, + uxt: sc_transaction_graph::ExtrinsicFor>, +) -> error::Result +where + Block: BlockT, + Client: ProvideRuntimeApi + BlockBackend + BlockIdTo, + Client: Send + Sync + 'static, + Client::Api: TaggedTransactionQueue, + sp_api::ApiErrorFor: Send + std::fmt::Display, +{ + sp_tracing::enter_span!("validate_transaction"); + let runtime_api = client.runtime_api(); + let has_v2 = sp_tracing::tracing_span! { "check_version"; + runtime_api + .has_api_with::, _>(&at, |v| v >= 2) + .unwrap_or_default() + }; + + sp_tracing::enter_span!("runtime::validate_transaction"); + let res = if has_v2 { + runtime_api.validate_transaction(&at, source, uxt) + } else { + #[allow(deprecated)] // old validate_transaction + runtime_api.validate_transaction_before_version_2(&at, uxt) + }; + + res.map_err(|e| Error::RuntimeApi(e.to_string())) +} + +impl FullChainApi +where + Block: BlockT, + Client: ProvideRuntimeApi + BlockBackend + BlockIdTo, + Client: Send + Sync + 'static, + Client::Api: TaggedTransactionQueue, + sp_api::ApiErrorFor: Send + std::fmt::Display, +{ + /// Validates a transaction by calling into the runtime, same as + /// `validate_transaction` but blocks the current thread when performing + /// validation. Only implemented for `FullChainApi` since we can call into + /// the runtime locally. + pub fn validate_transaction_blocking( + &self, + at: &BlockId, + source: TransactionSource, + uxt: sc_transaction_graph::ExtrinsicFor, + ) -> error::Result { + validate_transaction_blocking(&*self.client, at, source, uxt) + } +} + /// The transaction pool logic for light client. pub struct LightChainApi { client: Arc, @@ -143,11 +216,7 @@ pub struct LightChainApi { _phantom: PhantomData, } -impl LightChainApi where - Block: BlockT, - Client: HeaderBackend, - F: Fetcher, -{ +impl LightChainApi { /// Create new transaction pool logic. pub fn new(client: Arc, fetcher: Arc) -> Self { LightChainApi { @@ -158,16 +227,23 @@ impl LightChainApi where } } -impl sc_transaction_graph::ChainApi for LightChainApi where - Block: BlockT, - Client: HeaderBackend + 'static, - F: Fetcher + 'static, +impl sc_transaction_graph::ChainApi for + LightChainApi where + Block: BlockT, + Client: HeaderBackend + 'static, + F: Fetcher + 'static, { type Block = Block; - type Hash = Block::Hash; type Error = error::Error; - type ValidationFuture = Box> + Send + Unpin>; - type BodyFuture = Pin::Extrinsic>>>> + Send>>; + type ValidationFuture = Box< + dyn Future> + Send + Unpin + >; + type BodyFuture = Pin< + Box< + dyn Future::Extrinsic>>>> + + Send + > + >; fn validate_transaction( &self, @@ -204,15 +280,24 @@ impl sc_transaction_graph::ChainApi for LightChainApi) -> error::Result>> { + fn block_id_to_number( + &self, + at: &BlockId, + ) -> error::Result>> { Ok(self.client.block_number_from_id(at)?) } - fn block_id_to_hash(&self, at: &BlockId) -> error::Result>> { + fn block_id_to_hash( + &self, + at: &BlockId, + ) -> error::Result>> { Ok(self.client.block_hash_from_id(at)?) } - fn hash_and_length(&self, ex: &sc_transaction_graph::ExtrinsicFor) -> (Self::Hash, usize) { + fn hash_and_length( + &self, + ex: &sc_transaction_graph::ExtrinsicFor, + ) -> (sc_transaction_graph::ExtrinsicHash, usize) { ex.using_encoded(|x| { (<::Hashing as HashT>::hash(x), x.len()) }) diff --git a/client/transaction-pool/src/error.rs b/client/transaction-pool/src/error.rs index fa48b387c41d88ebfeab55278d777ff31b0dc1f0..c0f795df1801a0c59313aac28346bb6797ff04b7 100644 --- a/client/transaction-pool/src/error.rs +++ b/client/transaction-pool/src/error.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Transaction pool error. diff --git a/client/transaction-pool/src/lib.rs b/client/transaction-pool/src/lib.rs index c50d9dbbb45acdf82945ba9bfc6923c0e9817d04..fd6d64a340db319cd1c60458046c7b51e2e2f63e 100644 --- a/client/transaction-pool/src/lib.rs +++ b/client/transaction-pool/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Substrate transaction pool implementation. @@ -21,33 +23,44 @@ #![warn(unused_extern_crates)] mod api; -pub mod error; mod revalidation; +mod metrics; -#[cfg(any(feature = "test-helpers", test))] +pub mod error; + +#[cfg(test)] pub mod testing; pub use sc_transaction_graph as txpool; pub use crate::api::{FullChainApi, LightChainApi}; -use std::{collections::HashMap, sync::Arc, pin::Pin}; -use futures::{prelude::*, future::ready, channel::oneshot}; +use std::{collections::{HashMap, HashSet}, sync::Arc, pin::Pin}; +use futures::{prelude::*, future::{self, ready}, channel::oneshot}; use parking_lot::Mutex; use sp_runtime::{ generic::BlockId, traits::{Block as BlockT, NumberFor, AtLeast32Bit, Extrinsic, Zero}, }; +use sp_core::traits::SpawnNamed; use sp_transaction_pool::{ TransactionPool, PoolStatus, ImportNotificationStream, TxHash, TransactionFor, TransactionStatusStreamFor, MaintainedTransactionPool, PoolFuture, ChainEvent, TransactionSource, }; +use sc_transaction_graph::{ChainApi, ExtrinsicHash}; use wasm_timer::Instant; -type BoxedReadyIterator = Box>> + Send>; +use prometheus_endpoint::Registry as PrometheusRegistry; +use crate::metrics::MetricsLink as PrometheusMetrics; + +type BoxedReadyIterator = Box< + dyn Iterator>> + Send +>; -type ReadyIteratorFor = BoxedReadyIterator, sc_transaction_graph::ExtrinsicFor>; +type ReadyIteratorFor = BoxedReadyIterator< + sc_transaction_graph::ExtrinsicHash, sc_transaction_graph::ExtrinsicFor +>; type PolledIterator = Pin> + Send>>; @@ -55,13 +68,14 @@ type PolledIterator = Pin where Block: BlockT, - PoolApi: sc_transaction_graph::ChainApi, + PoolApi: ChainApi, { pool: Arc>, api: Arc, revalidation_strategy: Arc>>>, revalidation_queue: Arc>, ready_poll: Arc, Block>>>, + metrics: PrometheusMetrics, } struct ReadyPoll { @@ -108,8 +122,7 @@ impl ReadyPoll { #[cfg(not(target_os = "unknown"))] impl parity_util_mem::MallocSizeOf for BasicPool where - PoolApi: sc_transaction_graph::ChainApi, - PoolApi::Hash: parity_util_mem::MallocSizeOf, + PoolApi: ChainApi, Block: BlockT, { fn size_of(&self, ops: &mut parity_util_mem::MallocSizeOfOps) -> usize { @@ -138,19 +151,8 @@ pub enum RevalidationType { impl BasicPool where Block: BlockT, - PoolApi: sc_transaction_graph::ChainApi + 'static, + PoolApi: ChainApi + 'static, { - /// Create new basic transaction pool with provided api. - /// - /// It will also optionally return background task that might be started by the - /// caller. - pub fn new( - options: sc_transaction_graph::Options, - pool_api: Arc, - ) -> (Self, Option + Send>>>) { - Self::with_revalidation_type(options, pool_api, RevalidationType::Full) - } - /// Create new basic transaction pool with provided api, for tests. #[cfg(test)] pub fn new_test( @@ -166,19 +168,34 @@ impl BasicPool revalidation_queue: Arc::new(revalidation_queue), revalidation_strategy: Arc::new(Mutex::new(RevalidationStrategy::Always)), ready_poll: Default::default(), + metrics: Default::default(), }, background_task, notifier, ) } + /// Create new basic transaction pool for a light node with the provided api. + pub fn new_light( + options: sc_transaction_graph::Options, + pool_api: Arc, + prometheus: Option<&PrometheusRegistry>, + spawner: impl SpawnNamed, + ) -> Self { + Self::with_revalidation_type( + options, pool_api, prometheus, RevalidationType::Light, spawner, + ) + } + /// Create new basic transaction pool with provided api and custom /// revalidation type. pub fn with_revalidation_type( options: sc_transaction_graph::Options, pool_api: Arc, + prometheus: Option<&PrometheusRegistry>, revalidation_type: RevalidationType, - ) -> (Self, Option + Send>>>) { + spawner: impl SpawnNamed, + ) -> Self { let pool = Arc::new(sc_transaction_graph::Pool::new(options, pool_api.clone())); let (revalidation_queue, background_task) = match revalidation_type { RevalidationType::Light => (revalidation::RevalidationQueue::new(pool_api.clone(), pool.clone()), None), @@ -187,21 +204,24 @@ impl BasicPool (queue, Some(background)) }, }; - ( - BasicPool { - api: pool_api, - pool, - revalidation_queue: Arc::new(revalidation_queue), - revalidation_strategy: Arc::new(Mutex::new( - match revalidation_type { - RevalidationType::Light => RevalidationStrategy::Light(RevalidationStatus::NotScheduled), - RevalidationType::Full => RevalidationStrategy::Always, - } - )), - ready_poll: Default::default(), - }, - background_task, - ) + + if let Some(background_task) = background_task { + spawner.spawn("txpool-background", background_task); + } + + BasicPool { + api: pool_api, + pool, + revalidation_queue: Arc::new(revalidation_queue), + revalidation_strategy: Arc::new(Mutex::new( + match revalidation_type { + RevalidationType::Light => RevalidationStrategy::Light(RevalidationStatus::NotScheduled), + RevalidationType::Full => RevalidationStrategy::Always, + } + )), + ready_poll: Default::default(), + metrics: PrometheusMetrics::new(prometheus), + } } /// Gets shared reference to the underlying pool. @@ -213,11 +233,13 @@ impl BasicPool impl TransactionPool for BasicPool where Block: BlockT, - PoolApi: 'static + sc_transaction_graph::ChainApi, + PoolApi: 'static + ChainApi, { type Block = PoolApi::Block; - type Hash = sc_transaction_graph::ExHash; - type InPoolTransaction = sc_transaction_graph::base_pool::Transaction, TransactionFor>; + type Hash = sc_transaction_graph::ExtrinsicHash; + type InPoolTransaction = sc_transaction_graph::base_pool::Transaction< + TxHash, TransactionFor + >; type Error = PoolApi::Error; fn submit_at( @@ -228,9 +250,10 @@ impl TransactionPool for BasicPool ) -> PoolFuture, Self::Error>>, Self::Error> { let pool = self.pool.clone(); let at = *at; - async move { - pool.submit_at(&at, source, xts, false).await - }.boxed() + + self.metrics.report(|metrics| metrics.submitted_transactions.inc_by(xts.len() as u64)); + + async move { pool.submit_at(&at, source, xts).await }.boxed() } fn submit_one( @@ -241,9 +264,10 @@ impl TransactionPool for BasicPool ) -> PoolFuture, Self::Error> { let pool = self.pool.clone(); let at = *at; - async move { - pool.submit_one(&at, source, xt).await - }.boxed() + + self.metrics.report(|metrics| metrics.submitted_transactions.inc()); + + async move { pool.submit_one(&at, source, xt).await }.boxed() } fn submit_and_watch( @@ -255,6 +279,8 @@ impl TransactionPool for BasicPool let at = *at; let pool = self.pool.clone(); + self.metrics.report(|metrics| metrics.submitted_transactions.inc()); + async move { pool.submit_and_watch(&at, source, xt) .map(|result| result.map(|watcher| Box::new(watcher.into_stream()) as _)) @@ -263,7 +289,9 @@ impl TransactionPool for BasicPool } fn remove_invalid(&self, hashes: &[TxHash]) -> Vec> { - self.pool.validated_pool().remove_invalid(hashes) + let removed = self.pool.validated_pool().remove_invalid(hashes); + self.metrics.report(|metrics| metrics.validations_invalid.inc_by(removed.len() as u64)); + removed } fn status(&self) -> PoolStatus { @@ -288,6 +316,7 @@ impl TransactionPool for BasicPool fn ready_at(&self, at: NumberFor) -> PolledIterator { if self.ready_poll.lock().updated_at() >= at { + log::trace!(target: "txpool", "Transaction pool already processed block #{}", at); let iterator: ReadyIteratorFor = Box::new(self.pool.validated_pool().ready()); return Box::pin(futures::future::ready(iterator)); } @@ -308,6 +337,88 @@ impl TransactionPool for BasicPool } } +impl BasicPool, Block> +where + Block: BlockT, + Client: sp_api::ProvideRuntimeApi + + sc_client_api::BlockBackend + + sp_runtime::traits::BlockIdTo, + Client: sc_client_api::ExecutorProvider + Send + Sync + 'static, + Client::Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue, + sp_api::ApiErrorFor: Send + std::fmt::Display, +{ + /// Create new basic transaction pool for a full node with the provided api. + pub fn new_full( + options: sc_transaction_graph::Options, + pool_api: Arc>, + prometheus: Option<&PrometheusRegistry>, + spawner: impl SpawnNamed, + client: Arc, + ) -> Arc { + let pool = Arc::new(Self::with_revalidation_type( + options, pool_api, prometheus, RevalidationType::Full, spawner + )); + + // make transaction pool available for off-chain runtime calls. + client.execution_extensions().register_transaction_pool(&pool); + + pool + } +} + +impl sp_transaction_pool::LocalTransactionPool + for BasicPool, Block> +where + Block: BlockT, + Client: sp_api::ProvideRuntimeApi + + sc_client_api::BlockBackend + + sp_runtime::traits::BlockIdTo, + Client: Send + Sync + 'static, + Client::Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue, + sp_api::ApiErrorFor: Send + std::fmt::Display, +{ + type Block = Block; + type Hash = sc_transaction_graph::ExtrinsicHash>; + type Error = as ChainApi>::Error; + + fn submit_local( + &self, + at: &BlockId, + xt: sp_transaction_pool::LocalTransactionFor, + ) -> Result { + use sc_transaction_graph::ValidatedTransaction; + use sp_runtime::traits::SaturatedConversion; + use sp_runtime::transaction_validity::TransactionValidityError; + + let validity = self + .api + .validate_transaction_blocking(at, TransactionSource::Local, xt.clone())? + .map_err(|e| { + Self::Error::Pool(match e { + TransactionValidityError::Invalid(i) => i.into(), + TransactionValidityError::Unknown(u) => u.into(), + }) + })?; + + let (hash, bytes) = self.pool.validated_pool().api().hash_and_length(&xt); + let block_number = self + .api + .block_id_to_number(at)? + .ok_or_else(|| error::Error::BlockIdConversion(format!("{:?}", at)))?; + + let validated = ValidatedTransaction::valid_at( + block_number.saturated_into::(), + hash.clone(), + TransactionSource::Local, + xt, + bytes, + validity, + ); + + self.pool.validated_pool().submit(vec![validated]).remove(0) + } +} + #[cfg_attr(test, derive(Debug))] enum RevalidationStatus { /// The revalidation has never been completed. @@ -392,22 +503,51 @@ impl RevalidationStatus { } } +/// Prune the known txs for the given block. +async fn prune_known_txs_for_block>( + block_id: BlockId, + api: &Api, + pool: &sc_transaction_graph::Pool, +) -> Vec> { + let hashes = api.block_body(&block_id).await + .unwrap_or_else(|e| { + log::warn!("Prune known transactions: error request {:?}!", e); + None + }) + .unwrap_or_default() + .into_iter() + .map(|tx| pool.hash_of(&tx)) + .collect::>(); + + log::trace!(target: "txpool", "Pruning transactions: {:?}", hashes); + + if let Err(e) = pool.prune_known(&block_id, &hashes) { + log::error!("Cannot prune known in the pool {:?}!", e); + } + + hashes +} + impl MaintainedTransactionPool for BasicPool where Block: BlockT, - PoolApi: 'static + sc_transaction_graph::ChainApi, + PoolApi: 'static + ChainApi, { fn maintain(&self, event: ChainEvent) -> Pin + Send>> { match event { - ChainEvent::NewBlock { id, retracted, .. } => { - let id = id.clone(); + ChainEvent::NewBlock { hash, tree_route, is_new_best, .. } => { let pool = self.pool.clone(); let api = self.api.clone(); + let id = BlockId::hash(hash); let block_number = match api.block_id_to_number(&id) { Ok(Some(number)) => number, _ => { - log::trace!(target: "txpool", "Skipping chain event - no number for that block {:?}", id); + log::trace!( + target: "txpool", + "Skipping chain event - no number for that block {:?}", + id, + ); return Box::pin(ready(())); } }; @@ -418,40 +558,59 @@ impl MaintainedTransactionPool for BasicPool Some(20.into()), ); let revalidation_strategy = self.revalidation_strategy.clone(); - let retracted = retracted.clone(); let revalidation_queue = self.revalidation_queue.clone(); let ready_poll = self.ready_poll.clone(); + let metrics = self.metrics.clone(); async move { - // We don't query block if we won't prune anything - if !pool.validated_pool().status().is_empty() { - let hashes = api.block_body(&id).await - .unwrap_or_else(|e| { - log::warn!("Prune known transactions: error request {:?}!", e); - None - }) - .unwrap_or_default() - .into_iter() - .map(|tx| pool.hash_of(&tx)) - .collect::>(); - - if let Err(e) = pool.prune_known(&id, &hashes) { - log::error!("Cannot prune known in the pool {:?}!", e); + // We keep track of everything we prune so that later we won't add + // tranactions with those hashes from the retracted blocks. + let mut pruned_log = HashSet::>::new(); + + // If there is a tree route, we use this to prune known tx based on the enacted + // blocks. Before pruning enacted transactions, we inform the listeners about + // retracted blocks and their transactions. This order is important, because + // if we enact and retract the same transaction at the same time, we want to + // send first the retract and than the prune event. + if let Some(ref tree_route) = tree_route { + for retracted in tree_route.retracted() { + // notify txs awaiting finality that it has been retracted + pool.validated_pool().on_block_retracted(retracted.hash.clone()); } + + future::join_all( + tree_route + .enacted() + .iter() + .map(|h| + prune_known_txs_for_block( + BlockId::Hash(h.hash.clone()), + &*api, + &*pool, + ), + ), + ).await.into_iter().for_each(|enacted_log|{ + pruned_log.extend(enacted_log); + }) } - let extra_pool = pool.clone(); - // After #5200 lands, this arguably might be moved to the handler of "all blocks notification". - ready_poll.lock().trigger(block_number, move || Box::new(extra_pool.validated_pool().ready())); + // If this is a new best block, we need to prune its transactions from the pool. + if is_new_best { + pruned_log.extend(prune_known_txs_for_block(id.clone(), &*api, &*pool).await); + } + + metrics.report( + |metrics| metrics.block_transactions_pruned.inc_by(pruned_log.len() as u64) + ); - if next_action.resubmit { + if let (true, Some(tree_route)) = (next_action.resubmit, tree_route) { let mut resubmit_transactions = Vec::new(); - for retracted_hash in retracted { - // notify txs awaiting finality that it has been retracted - pool.validated_pool().on_block_retracted(retracted_hash.clone()); + for retracted in tree_route.retracted() { + let hash = retracted.hash.clone(); - let block_transactions = api.block_body(&BlockId::hash(retracted_hash.clone())).await + let block_transactions = api.block_body(&BlockId::hash(hash)) + .await .unwrap_or_else(|e| { log::warn!("Failed to fetch block body {:?}!", e); None @@ -460,25 +619,62 @@ impl MaintainedTransactionPool for BasicPool .into_iter() .filter(|tx| tx.is_signed().unwrap_or(true)); - resubmit_transactions.extend(block_transactions); + let mut resubmitted_to_report = 0; + + resubmit_transactions.extend( + block_transactions.into_iter().filter(|tx| { + let tx_hash = pool.hash_of(&tx); + let contains = pruned_log.contains(&tx_hash); + + // need to count all transactions, not just filtered, here + resubmitted_to_report += 1; + + if !contains { + log::debug!( + target: "txpool", + "[{:?}]: Resubmitting from retracted block {:?}", + tx_hash, + hash, + ); + } + !contains + }) + ); + + metrics.report( + |metrics| metrics.block_transactions_resubmitted.inc_by(resubmitted_to_report) + ); } - if let Err(e) = pool.submit_at( + + if let Err(e) = pool.resubmit_at( &id, // These transactions are coming from retracted blocks, we should // simply consider them external. TransactionSource::External, resubmit_transactions, - true ).await { log::debug!( target: "txpool", - "[{:?}] Error re-submitting transactions: {:?}", id, e + "[{:?}] Error re-submitting transactions: {:?}", + id, + e, ) } } + let extra_pool = pool.clone(); + // After #5200 lands, this arguably might be moved to the + // handler of "all blocks notification". + ready_poll.lock().trigger( + block_number, + move || Box::new(extra_pool.validated_pool().ready()), + ); + if next_action.revalidate { - let hashes = pool.validated_pool().ready().map(|tx| tx.hash.clone()).collect(); + let hashes = pool.validated_pool() + .ready() + .map(|tx| tx.hash.clone()) + .collect(); revalidation_queue.revalidate_later(block_number, hashes).await; } @@ -500,3 +696,23 @@ impl MaintainedTransactionPool for BasicPool } } } + +/// Inform the transaction pool about imported and finalized blocks. +pub async fn notification_future( + client: Arc, + txpool: Arc +) + where + Block: BlockT, + Client: sc_client_api::BlockchainEvents, + Pool: MaintainedTransactionPool, +{ + let import_stream = client.import_notification_stream().map(Into::into).fuse(); + let finality_stream = client.finality_notification_stream() + .map(Into::into) + .fuse(); + + futures::stream::select(import_stream, finality_stream) + .for_each(|evt| txpool.maintain(evt)) + .await +} diff --git a/client/transaction-pool/src/metrics.rs b/client/transaction-pool/src/metrics.rs new file mode 100644 index 0000000000000000000000000000000000000000..376e6dfe94488611db828fdbce0f5f9294c1747d --- /dev/null +++ b/client/transaction-pool/src/metrics.rs @@ -0,0 +1,129 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Transaction pool Prometheus metrics. + +use std::sync::Arc; + +use prometheus_endpoint::{register, Counter, PrometheusError, Registry, U64}; + +#[derive(Clone, Default)] +pub struct MetricsLink(Arc>); + +impl MetricsLink { + pub fn new(registry: Option<&Registry>) -> Self { + Self(Arc::new( + registry.and_then(|registry| + Metrics::register(registry) + .map_err(|err| { log::warn!("Failed to register prometheus metrics: {}", err); }) + .ok() + ) + )) + } + + pub fn report(&self, do_this: impl FnOnce(&Metrics)) { + if let Some(metrics) = self.0.as_ref() { + do_this(metrics); + } + } +} + +/// Transaction pool Prometheus metrics. +pub struct Metrics { + pub submitted_transactions: Counter, + pub validations_invalid: Counter, + pub block_transactions_pruned: Counter, + pub block_transactions_resubmitted: Counter, +} + +impl Metrics { + pub fn register(registry: &Registry) -> Result { + Ok(Self { + submitted_transactions: register( + Counter::new( + "sub_txpool_submitted_transactions", + "Total number of transactions submitted", + )?, + registry, + )?, + validations_invalid: register( + Counter::new( + "sub_txpool_validations_invalid", + "Total number of transactions that were removed from the pool as invalid", + )?, + registry, + )?, + block_transactions_pruned: register( + Counter::new( + "sub_txpool_block_transactions_pruned", + "Total number of transactions that was requested to be pruned by block events", + )?, + registry, + )?, + block_transactions_resubmitted: register( + Counter::new( + "sub_txpool_block_transactions_resubmitted", + "Total number of transactions that was requested to be resubmitted by block events", + )?, + registry, + )?, + }) + } +} + +/// Transaction pool api Prometheus metrics. +pub struct ApiMetrics { + pub validations_scheduled: Counter, + pub validations_finished: Counter, +} + +impl ApiMetrics { + /// Register the metrics at the given Prometheus registry. + pub fn register(registry: &Registry) -> Result { + Ok(Self { + validations_scheduled: register( + Counter::new( + "sub_txpool_validations_scheduled", + "Total number of transactions scheduled for validation", + )?, + registry, + )?, + validations_finished: register( + Counter::new( + "sub_txpool_validations_finished", + "Total number of transactions that finished validation", + )?, + registry, + )?, + }) + } +} + +/// An extension trait for [`ApiMetrics`]. +pub trait ApiMetricsExt { + /// Report an event to the metrics. + fn report(&self, report: impl FnOnce(&ApiMetrics)); +} + +impl ApiMetricsExt for Option> { + fn report(&self, report: impl FnOnce(&ApiMetrics)) { + if let Some(metrics) = self.as_ref() { + report(metrics) + } + } +} diff --git a/client/transaction-pool/src/revalidation.rs b/client/transaction-pool/src/revalidation.rs index 9bcb2dac395816a73ff9799f4fe533845c06205a..af9a76c055b6bc0fb643c4f54377ab30e5d35789 100644 --- a/client/transaction-pool/src/revalidation.rs +++ b/client/transaction-pool/src/revalidation.rs @@ -1,24 +1,26 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Pool periodic revalidation. use std::{sync::Arc, pin::Pin, collections::{HashMap, HashSet, BTreeMap}}; -use sc_transaction_graph::{ChainApi, Pool, ExHash, NumberFor, ValidatedTransaction}; +use sc_transaction_graph::{ChainApi, Pool, ExtrinsicHash, NumberFor, ValidatedTransaction}; use sp_runtime::traits::{Zero, SaturatedConversion}; use sp_runtime::generic::BlockId; use sp_runtime::transaction_validity::TransactionValidityError; @@ -30,14 +32,14 @@ use std::time::Duration; #[cfg(not(test))] const BACKGROUND_REVALIDATION_INTERVAL: Duration = Duration::from_millis(200); #[cfg(test)] -pub const BACKGROUND_REVALIDATION_INTERVAL: Duration = Duration::from_millis(5); +pub const BACKGROUND_REVALIDATION_INTERVAL: Duration = Duration::from_millis(1); -const BACKGROUND_REVALIDATION_BATCH_SIZE: usize = 20; +const MIN_BACKGROUND_REVALIDATION_BATCH_SIZE: usize = 20; /// Payload from queue to worker. struct WorkerPayload { at: NumberFor, - transactions: Vec>, + transactions: Vec>, } /// Async revalidation worker. @@ -47,8 +49,8 @@ struct RevalidationWorker { api: Arc, pool: Arc>, best_block: NumberFor, - block_ordered: BTreeMap, HashSet>>, - members: HashMap, NumberFor>, + block_ordered: BTreeMap, HashSet>>, + members: HashMap, NumberFor>, } impl Unpin for RevalidationWorker {} @@ -61,18 +63,22 @@ async fn batch_revalidate( pool: Arc>, api: Arc, at: NumberFor, - batch: impl IntoIterator>, + batch: impl IntoIterator>, ) { let mut invalid_hashes = Vec::new(); let mut revalidated = HashMap::new(); - for ext_hash in batch { - let ext = match pool.validated_pool().ready_by_hash(&ext_hash) { - Some(ext) => ext, - None => continue, - }; - - match api.validate_transaction(&BlockId::Number(at), ext.source, ext.data.clone()).await { + let validation_results = futures::future::join_all( + batch.into_iter().filter_map(|ext_hash| { + pool.validated_pool().ready_by_hash(&ext_hash).map(|ext| { + api.validate_transaction(&BlockId::Number(at), ext.source, ext.data.clone()) + .map(move |validation_result| (validation_result, ext_hash, ext)) + }) + }) + ).await; + + for (validation_result, ext_hash, ext) in validation_results { + match validation_result { Ok(Err(TransactionValidityError::Invalid(err))) => { log::debug!(target: "txpool", "[{:?}]: Revalidation: invalid {:?}", ext_hash, err); invalid_hashes.push(ext_hash); @@ -127,22 +133,22 @@ impl RevalidationWorker { } } - fn prepare_batch(&mut self) -> Vec> { + fn prepare_batch(&mut self) -> Vec> { let mut queued_exts = Vec::new(); - let mut left = BACKGROUND_REVALIDATION_BATCH_SIZE; + let mut left = std::cmp::max(MIN_BACKGROUND_REVALIDATION_BATCH_SIZE, self.members.len() / 4); // Take maximum of count transaction by order // which they got into the pool while left > 0 { let first_block = match self.block_ordered.keys().next().cloned() { - Some(bn) => bn, - None => break, + Some(bn) => bn, + None => break, }; let mut block_drained = false; if let Some(extrinsics) = self.block_ordered.get_mut(&first_block) { let to_queue = extrinsics.iter().take(left).cloned().collect::>(); if to_queue.len() == extrinsics.len() { - block_drained = true; + block_drained = true; } else { for xt in &to_queue { extrinsics.remove(xt); @@ -153,7 +159,7 @@ impl RevalidationWorker { } if block_drained { - self.block_ordered.remove(&first_block); + self.block_ordered.remove(&first_block); } } @@ -176,7 +182,7 @@ impl RevalidationWorker { for ext_hash in transactions { // we don't add something that already scheduled for revalidation if self.members.contains_key(&ext_hash) { - log::debug!( + log::trace!( target: "txpool", "[{:?}] Skipped adding for revalidation: Already there.", ext_hash, @@ -214,12 +220,21 @@ impl RevalidationWorker { loop { futures::select! { - _ = interval.next() => { + _guard = interval.next() => { let next_batch = this.prepare_batch(); let batch_len = next_batch.len(); batch_revalidate(this.pool.clone(), this.api.clone(), this.best_block, next_batch).await; + #[cfg(test)] + { + use intervalier::Guard; + // only trigger test events if something was processed + if batch_len == 0 { + _guard.expect("Always some() in tests").skip(); + } + } + if batch_len > 0 || this.len() > 0 { log::debug!( target: "txpool", @@ -234,6 +249,16 @@ impl RevalidationWorker { Some(worker_payload) => { this.best_block = worker_payload.at; this.push(worker_payload); + + if this.members.len() > 0 { + log::debug!( + target: "txpool", + "Updated revalidation queue at {}. Transactions: {:?}", + this.best_block, + this.members, + ); + } + continue; }, // R.I.P. worker! @@ -313,9 +338,9 @@ where /// If queue configured with background worker, this will return immediately. /// If queue configured without background worker, this will resolve after /// revalidation is actually done. - pub async fn revalidate_later(&self, at: NumberFor, transactions: Vec>) { + pub async fn revalidate_later(&self, at: NumberFor, transactions: Vec>) { if transactions.len() > 0 { - log::debug!(target: "txpool", "Added {} transactions to revalidation queue", transactions.len()); + log::debug!(target: "txpool", "Sent {} transactions to revalidation queue", transactions.len()); } if let Some(ref to_worker) = self.background { @@ -338,9 +363,7 @@ mod tests { use sp_transaction_pool::TransactionSource; use substrate_test_runtime_transaction_pool::{TestApi, uxt}; use futures::executor::block_on; - use substrate_test_runtime_client::{ - AccountKeyring::*, - }; + use substrate_test_runtime_client::AccountKeyring::*; fn setup() -> (Arc, Pool) { let test_api = Arc::new(TestApi::empty()); diff --git a/client/transaction-pool/src/testing/mod.rs b/client/transaction-pool/src/testing/mod.rs index a8f40c6b6475b57656bb0f373851f2162f283be5..350c4137c37b23a5d1fdfde94f0b19acde7cbdb4 100644 --- a/client/transaction-pool/src/testing/mod.rs +++ b/client/transaction-pool/src/testing/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . //! Tests for top-level transaction pool api diff --git a/client/transaction-pool/src/testing/pool.rs b/client/transaction-pool/src/testing/pool.rs index c6c54d97209445f17b2daad50377555cdd0906e4..a938313733ecd3105bf5b23b0095752492dac008 100644 --- a/client/transaction-pool/src/testing/pool.rs +++ b/client/transaction-pool/src/testing/pool.rs @@ -1,34 +1,40 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Substrate is distributed in the hope that it will be useful, +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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 . +// along with this program. If not, see . use crate::*; use sp_transaction_pool::TransactionStatus; -use futures::executor::block_on; +use futures::executor::{block_on, block_on_stream}; use txpool::{self, Pool}; use sp_runtime::{ generic::BlockId, - transaction_validity::{ValidTransaction, InvalidTransaction, TransactionSource}, + transaction_validity::{ValidTransaction, TransactionSource, InvalidTransaction}, }; use substrate_test_runtime_client::{ - runtime::{Block, Hash, Index, Header, Extrinsic, Transfer}, - AccountKeyring::*, + runtime::{Block, Hash, Index, Header, Extrinsic, Transfer}, AccountKeyring::*, + ClientBlockImportExt, }; use substrate_test_runtime_transaction_pool::{TestApi, uxt}; use futures::{prelude::*, task::Poll}; use codec::Encode; +use std::collections::BTreeSet; +use sc_client_api::client::BlockchainEvents; +use sc_block_builder::BlockBuilderProvider; +use sp_consensus::BlockOrigin; fn pool() -> Pool { Pool::new(Default::default(), TestApi::with_alice_nonce(209).into()) @@ -40,7 +46,7 @@ fn maintained_pool() -> ( intervalier::BackSignalControl, ) { let (pool, background_task, notifier) = BasicPool::new_test( - std::sync::Arc::new(TestApi::with_alice_nonce(209)) + Arc::new(TestApi::with_alice_nonce(209)), ); let thread_pool = futures::executor::ThreadPool::new().unwrap(); @@ -48,16 +54,6 @@ fn maintained_pool() -> ( (pool, thread_pool, notifier) } -fn header(number: u64) -> Header { - Header { - number, - digest: Default::default(), - extrinsics_root: Default::default(), - parent_hash: Default::default(), - state_root: Default::default(), - } -} - const SOURCE: TransactionSource = TransactionSource::External; #[test] @@ -110,6 +106,7 @@ fn prune_tags_should_work() { let pending: Vec<_> = pool.validated_pool().ready().map(|a| a.data.transfer().nonce).collect(); assert_eq!(pending, vec![209, 210]); + pool.validated_pool().api().push_block(1, Vec::new()); block_on( pool.prune_tags( &BlockId::number(1), @@ -138,6 +135,37 @@ fn should_ban_invalid_transactions() { block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt.clone())).unwrap_err(); } +#[test] +fn only_prune_on_new_best() { + let pool = maintained_pool().0; + let uxt = uxt(Alice, 209); + + let _ = block_on( + pool.submit_and_watch(&BlockId::number(1), SOURCE, uxt.clone()) + ).expect("1. Imported"); + let header = pool.api.push_block(1, vec![uxt.clone()]); + assert_eq!(pool.status().ready, 1); + + let event = ChainEvent::NewBlock { + hash: header.hash(), + is_new_best: false, + header: header.clone(), + tree_route: None, + }; + block_on(pool.maintain(event)); + assert_eq!(pool.status().ready, 1); + + let header = pool.api.push_block(2, vec![uxt]); + let event = ChainEvent::NewBlock { + hash: header.hash(), + is_new_best: true, + header: header.clone(), + tree_route: None, + }; + block_on(pool.maintain(event)); + assert_eq!(pool.status().ready, 0); +} + #[test] fn should_correctly_prune_transactions_providing_more_than_one_tag() { let api = Arc::new(TestApi::with_alice_nonce(209)); @@ -151,6 +179,7 @@ fn should_correctly_prune_transactions_providing_more_than_one_tag() { // remove the transaction that just got imported. api.increment_nonce(Alice.into()); + api.push_block(1, Vec::new()); block_on(pool.prune_tags(&BlockId::number(1), vec![vec![209]], vec![])).expect("1. Pruned"); assert_eq!(pool.validated_pool().status().ready, 0); // it's re-imported to future @@ -158,6 +187,7 @@ fn should_correctly_prune_transactions_providing_more_than_one_tag() { // so now let's insert another transaction that also provides the 155 api.increment_nonce(Alice.into()); + api.push_block(2, Vec::new()); let xt = uxt(Alice, 211); block_on(pool.submit_one(&BlockId::number(2), SOURCE, xt.clone())).expect("2. Imported"); assert_eq!(pool.validated_pool().status().ready, 1); @@ -167,30 +197,36 @@ fn should_correctly_prune_transactions_providing_more_than_one_tag() { // prune it and make sure the pool is empty api.increment_nonce(Alice.into()); + api.push_block(3, Vec::new()); block_on(pool.prune_tags(&BlockId::number(3), vec![vec![155]], vec![])).expect("2. Pruned"); assert_eq!(pool.validated_pool().status().ready, 0); assert_eq!(pool.validated_pool().status().future, 2); } -fn block_event(id: u64) -> ChainEvent { +fn block_event(header: Header) -> ChainEvent { ChainEvent::NewBlock { - id: BlockId::number(id), + hash: header.hash(), is_new_best: true, - retracted: vec![], - header: header(id), + tree_route: None, + header, } } -fn block_event_with_retracted(id: u64, retracted: Vec) -> ChainEvent { +fn block_event_with_retracted( + header: Header, + retracted_start: Hash, + api: &TestApi, +) -> ChainEvent { + let tree_route = api.tree_route(retracted_start, header.parent_hash).expect("Tree route exists"); + ChainEvent::NewBlock { - id: BlockId::number(id), + hash: header.hash(), is_new_best: true, - retracted: retracted, - header: header(id), + tree_route: Some(Arc::new(tree_route)), + header, } } - #[test] fn should_prune_old_during_maintenance() { let xt = uxt(Alice, 209); @@ -200,9 +236,9 @@ fn should_prune_old_during_maintenance() { block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.clone())).expect("1. Imported"); assert_eq!(pool.status().ready, 1); - pool.api.push_block(1, vec![xt.clone()]); + let header = pool.api.push_block(1, vec![xt.clone()]); - block_on(pool.maintain(block_event(1))); + block_on(pool.maintain(block_event(header))); assert_eq!(pool.status().ready, 0); } @@ -217,11 +253,11 @@ fn should_revalidate_during_maintenance() { assert_eq!(pool.status().ready, 2); assert_eq!(pool.api.validation_requests().len(), 2); - pool.api.push_block(1, vec![xt1.clone()]); + let header = pool.api.push_block(1, vec![xt1.clone()]); - block_on(pool.maintain(block_event(1))); + block_on(pool.maintain(block_event(header))); assert_eq!(pool.status().ready, 1); - block_on(notifier.next_blocking()); + block_on(notifier.next()); // test that pool revalidated transaction that left ready and not included in the block assert_eq!(pool.api.validation_requests().len(), 3); @@ -230,42 +266,58 @@ fn should_revalidate_during_maintenance() { #[test] fn should_resubmit_from_retracted_during_maintenance() { let xt = uxt(Alice, 209); - let retracted_hash = Hash::random(); let (pool, _guard, _notifier) = maintained_pool(); block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.clone())).expect("1. Imported"); assert_eq!(pool.status().ready, 1); - pool.api.push_block(1, vec![]); - pool.api.push_fork_block(retracted_hash, vec![xt.clone()]); + let header = pool.api.push_block(1, vec![]); + let fork_header = pool.api.push_block(1, vec![]); - let event = block_event_with_retracted(1, vec![retracted_hash]); + let event = block_event_with_retracted(header, fork_header.hash(), &*pool.api); block_on(pool.maintain(event)); assert_eq!(pool.status().ready, 1); } + +#[test] +fn should_not_resubmit_from_retracted_during_maintenance_if_tx_is_also_in_enacted() { + let xt = uxt(Alice, 209); + + let (pool, _guard, _notifier) = maintained_pool(); + + block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.clone())).expect("1. Imported"); + assert_eq!(pool.status().ready, 1); + + let header = pool.api.push_block(1, vec![xt.clone()]); + let fork_header = pool.api.push_block(1, vec![xt]); + + let event = block_event_with_retracted(header, fork_header.hash(), &*pool.api); + + block_on(pool.maintain(event)); + assert_eq!(pool.status().ready, 0); +} + #[test] fn should_not_retain_invalid_hashes_from_retracted() { let xt = uxt(Alice, 209); - let retracted_hash = Hash::random(); let (pool, _guard, mut notifier) = maintained_pool(); block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.clone())).expect("1. Imported"); assert_eq!(pool.status().ready, 1); - pool.api.push_block(1, vec![]); - pool.api.push_fork_block(retracted_hash, vec![xt.clone()]); + let header = pool.api.push_block(1, vec![]); + let fork_header = pool.api.push_block(1, vec![xt.clone()]); pool.api.add_invalid(&xt); - let event = block_event_with_retracted(1, vec![retracted_hash]); + let event = block_event_with_retracted(header, fork_header.hash(), &*pool.api); block_on(pool.maintain(event)); - // maintenance is in background - block_on(notifier.next_blocking()); - + block_on(notifier.next()); + assert_eq!(pool.status().ready, 0); } @@ -278,19 +330,18 @@ fn should_revalidate_transaction_multiple_times() { block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.clone())).expect("1. Imported"); assert_eq!(pool.status().ready, 1); - pool.api.push_block(1, vec![xt.clone()]); + let header = pool.api.push_block(1, vec![xt.clone()]); - block_on(pool.maintain(block_event(1))); - block_on(notifier.next_blocking()); + block_on(pool.maintain(block_event(header))); block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.clone())).expect("1. Imported"); assert_eq!(pool.status().ready, 1); - pool.api.push_block(2, vec![]); + let header = pool.api.push_block(2, vec![]); pool.api.add_invalid(&xt); - block_on(pool.maintain(block_event(2))); - block_on(notifier.next_blocking()); + block_on(pool.maintain(block_event(header))); + block_on(notifier.next()); assert_eq!(pool.status().ready, 0); } @@ -307,16 +358,16 @@ fn should_revalidate_across_many_blocks() { block_on(pool.submit_one(&BlockId::number(1), SOURCE, xt2.clone())).expect("1. Imported"); assert_eq!(pool.status().ready, 2); - pool.api.push_block(1, vec![]); - block_on(pool.maintain(block_event(1))); - block_on(notifier.next_blocking()); + let header = pool.api.push_block(1, vec![]); + block_on(pool.maintain(block_event(header))); + block_on(notifier.next()); block_on(pool.submit_one(&BlockId::number(2), SOURCE, xt3.clone())).expect("1. Imported"); assert_eq!(pool.status().ready, 3); - pool.api.push_block(2, vec![xt1.clone()]); - block_on(pool.maintain(block_event(2))); - block_on(notifier.next_blocking()); + let header = pool.api.push_block(2, vec![xt1.clone()]); + block_on(pool.maintain(block_event(header))); + block_on(notifier.next()); assert_eq!(pool.status().ready, 2); // xt1 and xt2 validated twice, then xt3 once, then xt2 and xt3 again @@ -360,8 +411,9 @@ fn should_push_watchers_during_maintaince() { pool.api.add_invalid(&tx4); // clear timer events if any - block_on(pool.maintain(block_event(0))); - block_on(notifier.next_blocking()); + let header = pool.api.push_block(1, vec![]); + block_on(pool.maintain(block_event(header))); + block_on(notifier.next()); // then // hash3 is now invalid @@ -377,8 +429,9 @@ fn should_push_watchers_during_maintaince() { ); // when - let header_hash = pool.api.push_block(1, vec![tx0, tx1, tx2]).hash(); - block_on(pool.maintain(block_event(1))); + let header = pool.api.push_block(2, vec![tx0, tx1, tx2]); + let header_hash = header.hash(); + block_on(pool.maintain(block_event(header))); let event = ChainEvent::Finalized { hash: header_hash.clone() }; block_on(pool.maintain(event)); @@ -389,15 +442,24 @@ fn should_push_watchers_during_maintaince() { // events for hash2 are: Ready, InBlock assert_eq!( futures::executor::block_on_stream(watcher0).collect::>(), - vec![TransactionStatus::Ready, TransactionStatus::InBlock(header_hash.clone()), TransactionStatus::Finalized(header_hash.clone())], + vec![ + TransactionStatus::Ready, + TransactionStatus::InBlock(header_hash.clone()), + TransactionStatus::Finalized(header_hash.clone())], ); assert_eq!( futures::executor::block_on_stream(watcher1).collect::>(), - vec![TransactionStatus::Ready, TransactionStatus::InBlock(header_hash.clone()), TransactionStatus::Finalized(header_hash.clone())], + vec![ + TransactionStatus::Ready, + TransactionStatus::InBlock(header_hash.clone()), + TransactionStatus::Finalized(header_hash.clone())], ); assert_eq!( futures::executor::block_on_stream(watcher2).collect::>(), - vec![TransactionStatus::Ready, TransactionStatus::InBlock(header_hash.clone()), TransactionStatus::Finalized(header_hash.clone())], + vec![ + TransactionStatus::Ready, + TransactionStatus::InBlock(header_hash.clone()), + TransactionStatus::Finalized(header_hash.clone())], ); } @@ -417,18 +479,18 @@ fn finalization() { let xt = uxt(Alice, 209); let api = TestApi::with_alice_nonce(209); api.push_block(1, vec![]); - let (pool, _background) = BasicPool::new(Default::default(), api.into()); + let (pool, _background, _) = BasicPool::new_test(api.into()); let watcher = block_on( pool.submit_and_watch(&BlockId::number(1), SOURCE, xt.clone()) ).expect("1. Imported"); pool.api.push_block(2, vec![xt.clone()]); - let header = pool.api.chain().read().header_by_number.get(&2).cloned().unwrap(); + let header = pool.api.chain().read().block_by_number.get(&2).unwrap()[0].header().clone(); let event = ChainEvent::NewBlock { - id: BlockId::Hash(header.hash()), + hash: header.hash(), is_new_best: true, header: header.clone(), - retracted: vec![] + tree_route: None, }; block_on(pool.maintain(event)); @@ -448,7 +510,7 @@ fn fork_aware_finalization() { // starting block A1 (last finalized.) api.push_block(1, vec![]); - let (pool, _background) = BasicPool::new(Default::default(), api.into()); + let (pool, _background, _) = BasicPool::new_test(api.into()); let mut canon_watchers = vec![]; let from_alice = uxt(Alice, 1); @@ -467,7 +529,6 @@ fn fork_aware_finalization() { let c2; let d2; - // block B1 { let watcher = block_on( @@ -478,10 +539,10 @@ fn fork_aware_finalization() { assert_eq!(pool.status().ready, 1); let event = ChainEvent::NewBlock { - id: BlockId::Number(2), + hash: header.hash(), is_new_best: true, header: header.clone(), - retracted: vec![], + tree_route: None, }; b1 = header.hash(); block_on(pool.maintain(event)); @@ -492,16 +553,16 @@ fn fork_aware_finalization() { // block C2 { - let header = pool.api.push_fork_block_with_parent(b1, vec![from_dave.clone()]); + let header = pool.api.push_block_with_parent(b1, vec![from_dave.clone()]); from_dave_watcher = block_on( pool.submit_and_watch(&BlockId::number(1), SOURCE, from_dave.clone()) ).expect("1. Imported"); assert_eq!(pool.status().ready, 1); let event = ChainEvent::NewBlock { - id: BlockId::Hash(header.hash()), + hash: header.hash(), is_new_best: true, header: header.clone(), - retracted: vec![] + tree_route: None, }; c2 = header.hash(); block_on(pool.maintain(event)); @@ -514,13 +575,13 @@ fn fork_aware_finalization() { pool.submit_and_watch(&BlockId::number(1), SOURCE, from_bob.clone()) ).expect("1. Imported"); assert_eq!(pool.status().ready, 1); - let header = pool.api.push_fork_block_with_parent(c2, vec![from_bob.clone()]); + let header = pool.api.push_block_with_parent(c2, vec![from_bob.clone()]); let event = ChainEvent::NewBlock { - id: BlockId::Hash(header.hash()), + hash: header.hash(), is_new_best: true, header: header.clone(), - retracted: vec![] + tree_route: None, }; d2 = header.hash(); block_on(pool.maintain(event)); @@ -536,14 +597,10 @@ fn fork_aware_finalization() { let header = pool.api.push_block(3, vec![from_charlie.clone()]); canon_watchers.push((watcher, header.hash())); - let event = ChainEvent::NewBlock { - id: BlockId::Number(3), - is_new_best: true, - header: header.clone(), - retracted: vec![c2, d2], - }; + let event = block_event_with_retracted(header.clone(), d2, &*pool.api); block_on(pool.maintain(event)); assert_eq!(pool.status().ready, 2); + let event = ChainEvent::Finalized { hash: header.hash() }; block_on(pool.maintain(event)); } @@ -559,10 +616,10 @@ fn fork_aware_finalization() { canon_watchers.push((w, header.hash())); let event = ChainEvent::NewBlock { - id: BlockId::Hash(header.hash()), + hash: header.hash(), is_new_best: true, header: header.clone(), - retracted: vec![] + tree_route: None, }; d1 = header.hash(); block_on(pool.maintain(event)); @@ -578,10 +635,10 @@ fn fork_aware_finalization() { let header = pool.api.push_block(5, vec![from_dave, from_bob]); e1 = header.hash(); let event = ChainEvent::NewBlock { - id: BlockId::Hash(header.hash()), + hash: header.hash(), is_new_best: true, header: header.clone(), - retracted: vec![] + tree_route: None, }; block_on(pool.maintain(event)); assert_eq!(pool.status().ready, 0); @@ -599,7 +656,7 @@ fn fork_aware_finalization() { { - let mut stream= futures::executor::block_on_stream(from_dave_watcher); + let mut stream = futures::executor::block_on_stream(from_dave_watcher); assert_eq!(stream.next(), Some(TransactionStatus::Ready)); assert_eq!(stream.next(), Some(TransactionStatus::InBlock(c2.clone()))); assert_eq!(stream.next(), Some(TransactionStatus::Retracted(c2))); @@ -610,7 +667,7 @@ fn fork_aware_finalization() { } { - let mut stream= futures::executor::block_on_stream(from_bob_watcher); + let mut stream = futures::executor::block_on_stream(from_bob_watcher); assert_eq!(stream.next(), Some(TransactionStatus::Ready)); assert_eq!(stream.next(), Some(TransactionStatus::InBlock(d2.clone()))); assert_eq!(stream.next(), Some(TransactionStatus::Retracted(d2))); @@ -621,6 +678,277 @@ fn fork_aware_finalization() { } } +/// Tests that when pruning and retracing a tx by the same event, we generate +/// the correct events in the correct order. +#[test] +fn prune_and_retract_tx_at_same_time() { + let api = TestApi::empty(); + // starting block A1 (last finalized.) + api.push_block(1, vec![]); + + let (pool, _background, _) = BasicPool::new_test(api.into()); + + let from_alice = uxt(Alice, 1); + pool.api.increment_nonce(Alice.into()); + + let watcher = block_on( + pool.submit_and_watch(&BlockId::number(1), SOURCE, from_alice.clone()) + ).expect("1. Imported"); + + // Block B1 + let b1 = { + let header = pool.api.push_block(2, vec![from_alice.clone()]); + assert_eq!(pool.status().ready, 1); + + let event = ChainEvent::NewBlock { + hash: header.hash(), + is_new_best: true, + header: header.clone(), + tree_route: None, + }; + block_on(pool.maintain(event)); + assert_eq!(pool.status().ready, 0); + header.hash() + }; + + // Block B2 + let b2 = { + let header = pool.api.push_block(2, vec![from_alice.clone()]); + assert_eq!(pool.status().ready, 0); + + let event = block_event_with_retracted(header.clone(), b1, &*pool.api); + block_on(pool.maintain(event)); + assert_eq!(pool.status().ready, 0); + + let event = ChainEvent::Finalized { hash: header.hash() }; + block_on(pool.maintain(event)); + + header.hash() + }; + + { + let mut stream = futures::executor::block_on_stream(watcher); + assert_eq!(stream.next(), Some(TransactionStatus::Ready)); + assert_eq!(stream.next(), Some(TransactionStatus::InBlock(b1.clone()))); + assert_eq!(stream.next(), Some(TransactionStatus::Retracted(b1))); + assert_eq!(stream.next(), Some(TransactionStatus::InBlock(b2.clone()))); + assert_eq!(stream.next(), Some(TransactionStatus::Finalized(b2))); + assert_eq!(stream.next(), None); + } +} + + +/// This test ensures that transactions from a fork are re-submitted if +/// the forked block is not part of the retracted blocks. This happens as the +/// retracted block list only contains the route from the old best to the new +/// best, without any further forks. +/// +/// Given the following: +/// +/// -> D0 (old best, tx0) +/// / +/// C - -> D1 (tx1) +/// \ +/// -> D2 (new best) +/// +/// Retracted will contain `D0`, but we need to re-submit `tx0` and `tx1` as both +/// blocks are not part of the canonical chain. +#[test] +fn resubmit_tx_of_fork_that_is_not_part_of_retracted() { + let api = TestApi::empty(); + // starting block A1 (last finalized.) + api.push_block(1, vec![]); + + let (pool, _background, _) = BasicPool::new_test(api.into()); + + let tx0 = uxt(Alice, 1); + let tx1 = uxt(Dave, 2); + pool.api.increment_nonce(Alice.into()); + pool.api.increment_nonce(Dave.into()); + + let d0; + + // Block D0 + { + let _ = block_on( + pool.submit_and_watch(&BlockId::number(1), SOURCE, tx0.clone()) + ).expect("1. Imported"); + let header = pool.api.push_block(2, vec![tx0.clone()]); + assert_eq!(pool.status().ready, 1); + + let event = ChainEvent::NewBlock { + hash: header.hash(), + is_new_best: true, + header: header.clone(), + tree_route: None, + }; + d0 = header.hash(); + block_on(pool.maintain(event)); + assert_eq!(pool.status().ready, 0); + } + + // Block D1 + { + let _ = block_on( + pool.submit_and_watch(&BlockId::number(1), SOURCE, tx1.clone()) + ).expect("1. Imported"); + let header = pool.api.push_block(2, vec![tx1.clone()]); + assert_eq!(pool.status().ready, 1); + let event = ChainEvent::NewBlock { + hash: header.hash(), + is_new_best: false, + header: header.clone(), + tree_route: None, + }; + block_on(pool.maintain(event)); + + // Only transactions from new best should be pruned + assert_eq!(pool.status().ready, 1); + } + + // Block D2 + { + let header = pool.api.push_block(2, vec![]); + let event = block_event_with_retracted(header, d0, &*pool.api); + block_on(pool.maintain(event)); + assert_eq!(pool.status().ready, 2); + } +} + +#[test] +fn resubmit_from_retracted_fork() { + let api = TestApi::empty(); + // starting block A1 (last finalized.) + api.push_block(1, vec![]); + + let (pool, _background, _) = BasicPool::new_test(api.into()); + + let tx0 = uxt(Alice, 1); + let tx1 = uxt(Dave, 2); + let tx2 = uxt(Bob, 3); + + // Transactions of the fork that will be enacted later + let tx3 = uxt(Eve, 1); + let tx4 = uxt(Ferdie, 2); + let tx5 = uxt(One, 3); + + pool.api.increment_nonce(Alice.into()); + pool.api.increment_nonce(Dave.into()); + pool.api.increment_nonce(Bob.into()); + pool.api.increment_nonce(Eve.into()); + pool.api.increment_nonce(Ferdie.into()); + pool.api.increment_nonce(One.into()); + + // Block D0 + { + let _ = block_on( + pool.submit_and_watch(&BlockId::number(1), SOURCE, tx0.clone()) + ).expect("1. Imported"); + let header = pool.api.push_block(2, vec![tx0.clone()]); + assert_eq!(pool.status().ready, 1); + + let event = ChainEvent::NewBlock { + hash: header.hash(), + is_new_best: true, + header: header.clone(), + tree_route: None, + }; + block_on(pool.maintain(event)); + assert_eq!(pool.status().ready, 0); + } + + // Block E0 + { + let _ = block_on( + pool.submit_and_watch(&BlockId::number(1), SOURCE, tx1.clone()) + ).expect("1. Imported"); + let header = pool.api.push_block(3, vec![tx1.clone()]); + let event = ChainEvent::NewBlock { + hash: header.hash(), + is_new_best: true, + header: header.clone(), + tree_route: None, + }; + block_on(pool.maintain(event)); + assert_eq!(pool.status().ready, 0); + } + + // Block F0 + let f0 = { + let _ = block_on( + pool.submit_and_watch(&BlockId::number(1), SOURCE, tx2.clone()) + ).expect("1. Imported"); + let header = pool.api.push_block(4, vec![tx2.clone()]); + let event = ChainEvent::NewBlock { + hash: header.hash(), + is_new_best: true, + header: header.clone(), + tree_route: None, + }; + block_on(pool.maintain(event)); + assert_eq!(pool.status().ready, 0); + header.hash() + }; + + // Block D1 + let d1 = { + let _ = block_on( + pool.submit_and_watch(&BlockId::number(1), SOURCE, tx3.clone()) + ).expect("1. Imported"); + let header = pool.api.push_block(2, vec![tx3.clone()]); + let event = ChainEvent::NewBlock { + hash: header.hash(), + is_new_best: false, + header: header.clone(), + tree_route: None, + }; + block_on(pool.maintain(event)); + assert_eq!(pool.status().ready, 1); + header.hash() + }; + + // Block E1 + let e1 = { + let _ = block_on( + pool.submit_and_watch(&BlockId::number(1), SOURCE, tx4.clone()) + ).expect("1. Imported"); + let header = pool.api.push_block_with_parent(d1.clone(), vec![tx4.clone()]); + let event = ChainEvent::NewBlock { + hash: header.hash(), + is_new_best: false, + header: header.clone(), + tree_route: None, + }; + block_on(pool.maintain(event)); + assert_eq!(pool.status().ready, 2); + header.hash() + }; + + // Block F1 + let f1_header = { + let _ = block_on( + pool.submit_and_watch(&BlockId::number(1), SOURCE, tx5.clone()) + ).expect("1. Imported"); + let header = pool.api.push_block_with_parent(e1.clone(), vec![tx5.clone()]); + // Don't announce the block event to the pool directly, because we will + // re-org to this block. + assert_eq!(pool.status().ready, 3); + header + }; + + let ready = pool.ready().map(|t| t.data.encode()).collect::>(); + let expected_ready = vec![tx3, tx4, tx5].iter().map(Encode::encode).collect::>(); + assert_eq!(expected_ready, ready); + + let event = block_event_with_retracted(f1_header, f0, &*pool.api); + block_on(pool.maintain(event)); + + assert_eq!(pool.status().ready, 3); + let ready = pool.ready().map(|t| t.data.encode()).collect::>(); + let expected_ready = vec![tx0, tx1, tx2].iter().map(Encode::encode).collect::>(); + assert_eq!(expected_ready, ready); +} + #[test] fn ready_set_should_not_resolve_before_block_update() { let (pool, _guard, _notifier) = maintained_pool(); @@ -633,12 +961,12 @@ fn ready_set_should_not_resolve_before_block_update() { #[test] fn ready_set_should_resolve_after_block_update() { let (pool, _guard, _notifier) = maintained_pool(); - pool.api.push_block(1, vec![]); + let header = pool.api.push_block(1, vec![]); let xt1 = uxt(Alice, 209); block_on(pool.submit_one(&BlockId::number(1), SOURCE, xt1.clone())).expect("1. Imported"); - block_on(pool.maintain(block_event(1))); + block_on(pool.maintain(block_event(header))); assert!(pool.ready_at(1).now_or_never().is_some()); } @@ -646,7 +974,7 @@ fn ready_set_should_resolve_after_block_update() { #[test] fn ready_set_should_eventually_resolve_when_block_update_arrives() { let (pool, _guard, _notifier) = maintained_pool(); - pool.api.push_block(1, vec![]); + let header = pool.api.push_block(1, vec![]); let xt1 = uxt(Alice, 209); @@ -660,7 +988,7 @@ fn ready_set_should_eventually_resolve_when_block_update_arrives() { panic!("Ready set should not be ready before block update!"); } - block_on(pool.maintain(block_event(1))); + block_on(pool.maintain(block_event(header))); match ready_set_future.poll_unpin(&mut context) { Poll::Pending => { @@ -678,8 +1006,9 @@ fn should_not_accept_old_signatures() { use std::convert::TryFrom; let client = Arc::new(substrate_test_runtime_client::new()); + let pool = Arc::new( - BasicPool::new(Default::default(), Arc::new(FullChainApi::new(client))).0 + BasicPool::new_test(Arc::new(FullChainApi::new(client, None))).0 ); let transfer = Transfer { @@ -695,13 +1024,70 @@ fn should_not_accept_old_signatures() { "c427eb672e8c441c86d31f1a81b22b43102058e9ce237cabe9897ea5099ffd426cd1c6a1f4f2869c3df57901d36bedcb295657adb3a4355add86ed234eb83108" ).expect("hex invalid")[..]).expect("signature construction failed"); - let xt = Extrinsic::Transfer { transfer, signature: old_singature, exhaust_resources_when_not_first: false }; + let xt = Extrinsic::Transfer { + transfer, + signature: old_singature, + exhaust_resources_when_not_first: false, + }; assert_matches::assert_matches!( block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.clone())), Err(error::Error::Pool( sp_transaction_pool::error::Error::InvalidTransaction(InvalidTransaction::BadProof) )), - "Should be invalid transactiono with bad proof", + "Should be invalid transaction with bad proof", + ); +} + +#[test] +fn import_notification_to_pool_maintain_works() { + let mut client = Arc::new(substrate_test_runtime_client::new()); + + let pool = Arc::new( + BasicPool::new_test(Arc::new(FullChainApi::new(client.clone(), None))).0 ); + + // Prepare the extrisic, push it to the pool and check that it was added. + let xt = uxt(Alice, 0); + block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.clone())).expect("1. Imported"); + assert_eq!(pool.status().ready, 1); + + let mut import_stream = block_on_stream(client.import_notification_stream()); + + // Build the block with the transaction included + let mut block_builder = client.new_block(Default::default()).unwrap(); + block_builder.push(xt).unwrap(); + let block = block_builder.build().unwrap().block; + client.import(BlockOrigin::Own, block).unwrap(); + + // Get the notification of the block import and maintain the pool with it, + // Now, the pool should not contain any transactions. + let evt = import_stream.next().expect("Importing a block leads to an event"); + block_on(pool.maintain(evt.into())); + assert_eq!(pool.status().ready, 0); +} + +// When we prune transactions, we need to make sure that we remove +#[test] +fn pruning_a_transaction_should_remove_it_from_best_transaction() { + let (pool, _guard, _notifier) = maintained_pool(); + + let xt1 = Extrinsic::IncludeData(Vec::new()); + + block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt1.clone())).expect("1. Imported"); + let header = pool.api.push_block(1, vec![xt1.clone()]); + + // This will prune `xt1`. + block_on(pool.maintain(block_event(header))); + + // Submit the tx again. + block_on(pool.submit_one(&BlockId::number(1), SOURCE, xt1.clone())).expect("2. Imported"); + + let mut iterator = block_on(pool.ready_at(1)); + + assert_eq!(iterator.next().unwrap().data, xt1.clone()); + + // If the tx was not removed from the best txs, the tx would be + // returned a second time by the iterator. + assert!(iterator.next().is_none()); } diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 6ac08309348f0140a3e59adb48d2a3146845f465..78fc85acc623afe058b5bd05a4a9a4bcb899660c 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -6,6 +6,205 @@ The format is based on [Keep a Changelog]. ## Unreleased +## 2.0.0-rc3 -> 2.0.0-rc4 (Rhinoceros) + +Runtime +------- + +* Staking Payout Creates Controller (#6496) +* `pallet-scheduler`: Check that `when` is not in the past (#6480) +* Fix `sp-api` handling of multiple arguments (#6484) +* Fix issues with `Operational` transactions validity and prioritization. (#6435) +* pallet-atomic-swap: generialized swap action (#6421) +* Avoid multisig reentrancy (#6445) +* Root origin use no filter by default. Scheduler and Democracy dispatch without asserting BaseCallFilter (#6408) +* Scale and increase validator count (#6417) +* Pallet: Atomic Swap (#6349) +* Restrict remove_proxies (#6383) +* Stored call in multisig (#6319) +* Allow Sudo to do anything (#6375) +* vesting: Force Vested Transfer (#6368) +* Add events for balance reserve and unreserve functions (#6330) +* Introduce frozen indices. (#6307) + +Client +------ + +* client/network/service: Add primary dimension to connection metrics (#6472) +* Fix Babe secondary plain slots claiming (#6451) +* add network propagated metrics (#6438) +* client/authority-discovery: Compare PeerIds and not Multihashes (#6414) +* Update sync chain info on own block import (#6424) +* Remove --legacy-network-protocol CLI flag (#6411) +* Runtime interface to add support for tracing from wasm (#6381) +* Remove penalty on duplicate Status message (#6377) +* Fix the broken weight multiplier update function (#6334) +* client/authority-discovery: Don't add own address to priority group (#6370) +* Split the service initialisation up into seperate functions (#6332) +* Fix transaction pool event sending (#6341) +* Add a [prefix]_process_start_time_seconds metric (#6315) +* new crate sc-light (#6235) +* Allow adding a prefix to the informant (#6174) + +API +--- + +* seal: Remove ext_dispatch_call and ext_get_runtime_storage (#6464) +* seal: Refactor ext_gas_price (#6478) +* Implement nested storage transactions (#6269) +* Allow empty values in the storage (#6364) +* add system_dryRun (#6300) +* Introduce in-origin filtering (#6318) +* add extend_lock for StorageLock (#6323) +* Deprecate FunctionOf and remove its users (#6340) +* transaction-pool: expose blocking api for tx submission (#6325) + + +## 2.0.0-rc2 -> 2.0.0-rc3 + +Runtime +------- + +* Introduce stacked filtering (#6273) +* Allow "anonymous" proxied accounts (#6236) +* Allow over-weight collective proposals to be closed (#6163) +* Fix Election when ForceNone V1 (#6166) + +Client +------ + +* Make transaction pool prune transactions only of canonical blocks (#6123) +* Rename all the election operations (#6245) +* Sentry nodes and validator nodes also imply reserved (#6251) +* Fix peerset not filtering incoming connections in reserved-only (#6249) +* Use Subscription Manager from `jsonrpc-pubsub` (#6208) +* Add a Substrate networking Grafana dashboard template (#6171) +* Add subkey inspect-node-key (#6153) + +## 2.0.0-rc1 -> 2.0.0-rc2 + +(nothing of note) + +## 2.0.0-alpha.8 -> 2.0.0-rc1 + +Runtime +------- + +* Allow operational recovery path if on_initialize use fullblock. (#6089) +* Maximum extrinsic weight limit (#6067) + +Client +------ + +* Add JSON format to import blocks and set it as default (#5816) +* Upgrade to libp2p v0.19 - Changes the default PeerId representation (#6064) + + +## 2.0.0-alpha.7 -> 2.0.0-alpha.8 + +**License Changed** +From this release forward, the code is released under a new – more relaxed – license scheme: Client (`sc-*`) is released under "GPL 3.0 or newer with the Classpath Exception", while primitives, FRAME, the pallets, utils and test-utils are released under "Apache 2.0". More details in the [Relax licensing scheme PR](https://github.com/paritytech/substrate/pull/5947). + +Runtime +------- + +* Democracy weight (#5828) +* Make `Digest` support `StorageAppend` (#5922) + +Client +------ + +* Meter block import results via prometheus (#6025) +* Added RuntimePublic for ecdsa public key. (#6029) +* Benchmarks for elections-phragmen pallet (#5845) +* Monitor transactions rejected from the pool as invalid (#5992) +* client/network: Remove default Kademlia DHT in favor of per protocol DHT (#5993) +* Allow passing multiple --log CLI options (#5982) +* client: Replace `unsafe_rpc_expose` with an `RpcMethods` enum (#5729) + +## 2.0.0-alpha.6 -> 2.0.0-alpha.7 + +Runtime +------- + +* Use `storage::append` in the implementation of the storage types (#5889) +* pallet-sudo: Store `DispatchResult` in `Sudid` event (#5804) +* Enable Offchain Equalise (#5683) +* Add support for custom runtime upgrade logic (#5782) +* Require `fn` token in `decl_storage` `get` (#5717) +* Child trie api changes BREAKING (#4857) +* Pass max-total to RewardRemainder on end_era (#5697) +* Transaction versioning in the RuntimeVersion (#5582) +* emit TipClosed event on success tip payout (#5656) + +Client +------ + +* Adds `export-state` subcommand (#5842) +* Drop ClientProvider (#5823) +* Move spawning tasks from thread pools to Service's TaskManager for block importing (#5647) +* Reputation penalty for sending empty block response (#5814) +* Move sc-client into sc-service (#5502) +* Use new block requests protocol (#5760) +* Fix leak in stream notifications (#5739) +* network: Only insert global addresses into the DHT. (#5735) +* enum Pays for PaysFee (#5733) +* Migrate away from `SimpleDispatchInfo` (#5686) +* Child trie api changes BREAKING (#4857) +* subkey: compute and inspect a moduleid (#5676) +* Listen on ipv6 by default as well (#5677) +* Adjustments to Kademlia-related metrics (#5660) +* client/authority-discovery: Allow to be run by sentry node (#5568) +* Add alternative RPC methods to system_networkState (#5643) +* Several tweaks to networking Prometheus metrics (#5636) +* Use a Kademlia instance per `ProtocolId`. (#5045) +* Report tasks metrics to Prometheus (#5619) + +API +--- + +* Child trie api changes BREAKING (#4857) +* Pass max-total to RewardRemainder on end_era (#5697) +* Implement iter for doublemap (#5504) + +## 2.0.0-alpha.5 -> 2.0.0-alpha.6 + +Runtime +------- + +* Unsigned Validation best practices (#5563) +* Generate Unit Tests for Benchmarks (#5527) +* Mandate weight annotation (#5357) +* Make Staking pallet using a proper Time module. (#4662) +* Pass transaction source to validate_transaction (#5366) +* on_initialize return weight consumed and default cost to default DispatchInfo instead of zero (#5382) + +Client +------ + +* Add new RPC method to get the chain type (#5576) +* Reuse wasmtime instances, the PR (#5567) +* Prometheus Metrics: Turn notifications_total counter into notifications_sizes histogram (#5535) +* Make verbosity level mandatory with telemetry opt (#5057) +* Additional Metrics collected and exposed via prometheus (#5414) +* Switch to new light client protocol (#5472) +* client/finality-grandpa: Instrument until-imported queue (#5438) +* Batch benchmarks together with `*` notation. (#5436) +* src/service/src/builder: Fix memory metric exposed in bytes not KiB (#5459) +* Make transactions and block announces use notifications substre… (#5360) +* Adds state_queryStorageAt (#5362) +* Offchain Phragmén BREAKING. (#4517) +* `sc_rpc::system::SystemInfo.impl_version` now returns the full version (2.0.0-alpha.2-b950f731c-x86_64-linux-gnu) instead of the short version (1.0.0) (#5271) + +API +--- + +* Unsigned Validation best practices (#5563) +* Split the Roles in three types (#5520) +* Pass transaction source to validate_transaction (#5366) +* on_initialize return weight consumed and default cost to default DispatchInfo instead of zero (#5382) + + ## 2.0.0-alpha.4 -> 2.0.0-alpha.5 Runtime @@ -51,4 +250,4 @@ API * client/authority-discovery: Instrument code with Prometheus (#5195) * Don't include `:code` by default in storage proofs (#5179) * client/network-gossip: Merge GossipEngine and GossipEngineInner (#5042) -* Introduce `on_runtime_upgrade` (#5058) \ No newline at end of file +* Introduce `on_runtime_upgrade` (#5058) diff --git a/docs/CODEOWNERS b/docs/CODEOWNERS index d4404346294a53abc2520cdfab7f7a4fc582f1f0..d9342de399503bd157ebb9779ee38db1ecda736f 100644 --- a/docs/CODEOWNERS +++ b/docs/CODEOWNERS @@ -18,15 +18,7 @@ # are more recognizable on GitHub, you can use them for mentioning unlike an email. # - The latest matching rule, if multiple, takes precedence. -# Wasm execution and the wasm side of Substrate Runtime Interface -/client/executor/ @pepyakin -/primitives/io/ @pepyakin @NikVolf - -# Crypto, execution extensions, etc. -/primitives/core/ @NikVolf - # Block production -/primitives/authorship/ @NikVolf /client/basic-authorship/ @NikVolf # Sandboxing capability of Substrate Runtime @@ -34,55 +26,39 @@ /primitives/core/src/sandbox.rs @pepyakin # Transaction pool -/client/transaction-pool/ @tomusdrw @NikVolf -/primitives/transaction-pool/ @tomusdrw @NikVolf +/client/transaction-pool/ @NikVolf +/primitives/transaction-pool/ @NikVolf # Offchain /client/offchain/ @tomusdrw /primitives/offchain/ @tomusdrw -# Everything that has RPC in it -/bin/node/rpc/ @tomusdrw -/bin/node/rpc-client/ @tomusdrw -/client/rpc/ @tomusdrw -/primitives/rpc/ @tomusdrw - # GRANDPA, BABE, consensus stuff -/frame/babe/ @andresilva @DemiMarie-parity -/frame/grandpa/ @andresilva @DemiMarie-parity -/client/finality-grandpa/ @andresilva @DemiMarie-parity -/client/consensus/babe/ @andresilva @DemiMarie-parity -/client/consensus/slots/ @andresilva @DemiMarie-parity +/frame/babe/ @andresilva +/frame/grandpa/ @andresilva +/client/finality-grandpa/ @andresilva +/client/consensus/babe/ @andresilva +/client/consensus/slots/ @andresilva /client/consensus/pow/ @sorpaas /primitives/consensus/pow/ @sorpaas # Contracts -/frame/contracts/ @pepyakin @thiolliere -/frame/contracts/src/wasm/runtime.rs @Robbepop +/frame/contracts/ @pepyakin # EVM /frame/evm/ @sorpaas -# Inflation points -/frame/staking/src/inflation.rs @thiolliere - -# NPoS and Governance and Phragmén +# NPoS and election /frame/staking/ @kianenigma /frame/elections/ @kianenigma /frame/elections-phragmen/ @kianenigma -/primitives/phragmen/ @kianenigma +/primitives/npos-elections/ @kianenigma # Fixed point arithmetic -/primitives/sp-arithmetic/ @kianenigma @thiolliere - -# End to end testing of substrate node -/bin/node/executor/ @kianenigma +/primitives/sp-arithmetic/ @kianenigma # Transaction weight stuff -/frame/support/src/weights.rs @kianenigma - -# Support crates -/frame/support/ @thiolliere @kianenigma +/frame/support/src/weights.rs @shawntabrizi # Authority discovery /client/authority-discovery/ @mxinden diff --git a/docs/CONTRIBUTING.adoc b/docs/CONTRIBUTING.adoc index b573aef50d874b304f3b135b4cffd08811fcfdea..1d82a43921d2fbbe72e8c273981ab3d4f242faea 100644 --- a/docs/CONTRIBUTING.adoc +++ b/docs/CONTRIBUTING.adoc @@ -19,17 +19,30 @@ There are a few basic ground-rules for contributors (including the maintainer(s) == Merge Process -Merging pull requests once CI is successful: +*In General* -. A PR needs to be reviewed and approved by project maintainers unless: - - it does not alter any logic (e.g. comments, dependencies, docs), then it may be tagged https://github.com/paritytech/substrate/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aopen+label%3AA2-insubstantial[`insubstantial`] and merged by its author once CI is complete. - - 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. +A PR needs to be reviewed and approved by project maintainers unless: +- it does not alter any logic (e.g. comments, dependencies, docs), then it may be tagged https://github.com/paritytech/substrate/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aopen+label%3AA2-insubstantial[`insubstantial`] and merged by its author once CI is complete. +- 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. + +*Labels TLDR:* + +- `A-*` Pull request status. ONE REQUIRED. +- `B-*` Changelog and/or Runtime-upgrade post composition markers. ONE REQUIRED. (used by automation) +- `C-*` Release notes release-priority markers. EXACTLY ONE REQUIRED. (used by automation) +- `D-*` More general tags on the PR denoting various implications and requirements. + +*Process:* + +. Please tag each PR with exactly one `A`, `B` and `C` label at the minimum. . Once a PR is ready for review please add the https://github.com/paritytech/substrate/pulls?q=is%3Apr+is%3Aopen+label%3AA0-pleasereview[`A0-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-mergeoncegreen[`A8-mergeoncegreen`], it is ready to merge. +. 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-mergeoncegreen[`A8-mergeoncegreen`], it is ready to merge. . PRs must be tagged with respect to _release notes_ with https://github.com/paritytech/substrate/labels/B0-silent[`B0-silent`] and `B1-..`. The former indicates that no changes should be mentioned in any release notes. The latter indicates that the changes should be reported in the corresponding release note -. PRs that break the external API must be tagged with https://github.com/paritytech/substrate/labels/B2-breaksapi[`B2-breaksapi`], when it changes the FRAME or consensus of running system with https://github.com/paritytech/substrate/labels/B3-breaksconsensus[`B3-breaksconsensus`] -. No PR should be merged until all reviews' comments are addressed. +. PRs that break the external API must be tagged with https://github.com/paritytech/substrate/labels/D2-breaksapi[`D2-breaksapi`], when it changes the FRAME or consensus of running system with https://github.com/paritytech/substrate/labels/B3-breaksconsensus[`B3-breaksconsensus`]. +. PRs should be labeled with their release importance via the `C1-C9`. +. PRs should be categorized into projects. +. No PR should be merged until all reviews' comments are addressed and CI is successful. *Reviewing pull requests*: @@ -49,19 +62,19 @@ When reviewing a pull request, the end-goal is to suggest useful changes to the === Updating Polkadot as well -**All pull requests will be checked agains either Polkadot master, or your provided Polkadot companion PR**. That is, If your PR changes the external APIs or interfaces used by Polkadot. 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 below. +**All pull requests will be checked against either Polkadot master, or your provided Polkadot companion PR**. That is, If your PR changes the external APIs or interfaces used by Polkadot. 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 below. To create a Polkadot companion PR: . Pull latest Polkadot master (or clone it, if you haven't yet). . Override your local cargo config to point to your local substrate (pointing to your WIP branch): place `paths = ["path/to/substrate"]` in `~/.cargo/config`. . Make the changes required and build polkadot locally. -. Submit all this as a PR against the Polkadot Repo. Link to your Polkadot PR in the _description_ of your Substrate PR as "polkadot companion: [URL]" OR use the same name for your Polkdadot branch as the Substrate branch. +. Submit all this as a PR against the Polkadot Repo. Link to your Polkadot PR in the _description_ of your Substrate PR as "polkadot companion: [URL]" . Now you should see that the `check_polkadot` CI job will build your Substrate PR agains the mentioned Polkadot branch in your PR description. . Wait for reviews on both -. Once both PRs have been green lit, they can both be merged 🍻. +. Once both PRs have been green lit, they can both be merged 🍻. -If your PR is reviewed well, but a Polkadot PR is missing, signal it with https://github.com/paritytech/substrate/labels/A7-needspolkadotpr[`A7-needspolkadotpr`] to prevent it from getting automatically merged. +If your PR is reviewed well, but a Polkadot PR is missing, signal it with https://github.com/paritytech/substrate/labels/A7-needspolkadotpr[`A7-needspolkadotpr`] to prevent it from getting automatically merged. 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. @@ -69,6 +82,14 @@ As there might be multiple pending PRs that might conflict with one another, a) 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. +== Issues +Please label issues with the following labels: + +. `I-*` Issue severity and type. EXACTLY ONE REQUIRED. +. `P-*` Issue priority. AT MOST ONE ALLOWED. +. `Q-*` Issue difficulty. AT MOST ONE ALLOWED. +. `Z-*` More general tags on the issue, denoting context and resolution. + == Releases Declaring formal releases remains the prerogative of the project maintainer(s). diff --git a/docs/PULL_REQUEST_TEMPLATE.md b/docs/PULL_REQUEST_TEMPLATE.md index 9755fa0e40ff9bcef1003d0933b174cc1adee06b..8ca6ba9b01fe21795d8ce57a99c736ac67220586 100644 --- a/docs/PULL_REQUEST_TEMPLATE.md +++ b/docs/PULL_REQUEST_TEMPLATE.md @@ -6,17 +6,24 @@ Before you submitting, please check that: - What does it do? - What important points reviewers should know? - Is there something left for follow-up PRs? -- [ ] You labeled the PR with appropriate labels if you have permissions to do so. +- [ ] You labeled the PR appropriately if you have permissions to do so: + - [ ] `A*` for PR status (**one required**) + - [ ] `B*` for changelog (**one required**) + - [ ] `C*` for release notes (**exactly one required**) + - [ ] `D*` for various implications/requirements + - [ ] Github's project assignment - [ ] You mentioned a related issue if this PR related to it, e.g. `Fixes #228` or `Related #1337`. - [ ] You asked any particular reviewers to review. If you aren't sure, start with GH suggestions. -- [ ] Your PR adheres [the style guide](https://github.com/paritytech/polkadot/wiki/Style-Guide) - - In particular, mind the maximal line length. +- [ ] Your PR adheres to [the style guide](https://wiki.parity.io/Substrate-Style-Guide) + - In particular, mind the maximal line length of 100 (120 in exceptional circumstances). - There is no commented code checked in unless necessary. - 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? +Refer to [the contributing guide](https://github.com/paritytech/substrate/blob/master/docs/CONTRIBUTING.adoc) for details. + After you've read this notice feel free to remove it. Thank you! diff --git a/docs/README.adoc b/docs/README.adoc index 8d762fee05f8789f164b0c5a263e334c28668176..51e7748b67c094194e8b1a810fe92e8cfe4d32d8 100644 --- a/docs/README.adoc +++ b/docs/README.adoc @@ -291,7 +291,7 @@ cargo run --release \-- \ --chain=local \ --alice \ --node-key 0000000000000000000000000000000000000000000000000000000000000001 \ - --telemetry-url ws://telemetry.polkadot.io:1024 \ + --telemetry-url 'ws://telemetry.polkadot.io:1024 0' \ --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: @@ -303,7 +303,7 @@ cargo run --release \-- \ --chain=local \ --bob \ --port 30334 \ - --telemetry-url ws://telemetry.polkadot.io:1024 \ + --telemetry-url 'ws://telemetry.polkadot.io:1024 0' \ --validator Additional Substrate CLI usage options are available and may be shown by running `cargo run \-- --help`. diff --git a/docs/media/sub.gif b/docs/media/sub.gif new file mode 100644 index 0000000000000000000000000000000000000000..d8d73d9171aac0751961206256cf1d219416814e Binary files /dev/null and b/docs/media/sub.gif differ diff --git a/frame/assets/Cargo.toml b/frame/assets/Cargo.toml index 8b242ff0e8ef149e47b86365ba14acf7abe9cc0a..4deb7b8a9bb1bde7fc4f83ecce1d509e1c843944 100644 --- a/frame/assets/Cargo.toml +++ b/frame/assets/Cargo.toml @@ -1,27 +1,30 @@ [package] name = "pallet-assets" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME asset management pallet" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } # Needed for various traits. In our case, `OnFinalize`. -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } # Needed for type-safe access to storage DB. -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } # `system` module provides us with all sorts of useful stuff and macros depend on it being around. -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -sp-std = { version = "2.0.0-alpha.5", path = "../../primitives/std" } -sp-io = { version = "2.0.0-alpha.5", path = "../../primitives/io" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +sp-std = { version = "2.0.0-rc4", path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc4", path = "../../primitives/io" } [features] default = ["std"] @@ -32,6 +35,3 @@ std = [ "frame-support/std", "frame-system/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index 388eb7780bd6dc7df7525d9e015c20790b0c4594..b64548145c316b5735ef636d61ca3df823c1fea8 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Assets Module //! @@ -86,7 +87,7 @@ //! ```rust,ignore //! use pallet_assets as assets; //! use frame_support::{decl_module, dispatch, ensure}; -//! use frame_system::{self as system, ensure_signed}; +//! use frame_system::ensure_signed; //! //! pub trait Trait: assets::Trait { } //! @@ -133,8 +134,8 @@ #![cfg_attr(not(feature = "std"), no_std)] use frame_support::{Parameter, decl_module, decl_event, decl_storage, decl_error, ensure}; -use sp_runtime::traits::{Member, AtLeast32Bit, Zero, StaticLookup}; -use frame_system::{self as system, ensure_signed}; +use sp_runtime::traits::{Member, AtLeast32Bit, AtLeast32BitUnsigned, Zero, StaticLookup}; +use frame_system::ensure_signed; use sp_runtime::traits::One; /// The module configuration trait. @@ -143,7 +144,7 @@ pub trait Trait: frame_system::Trait { type Event: From> + Into<::Event>; /// The units in which we record balances. - type Balance: Member + Parameter + AtLeast32Bit + Default + Copy; + type Balance: Member + Parameter + AtLeast32BitUnsigned + Default + Copy; /// The arithmetic type of asset identifier. type AssetId: Parameter + AtLeast32Bit + Default + Copy; @@ -157,7 +158,14 @@ decl_module! { /// 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. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + /// + /// # + /// - `O(1)` + /// - 1 storage mutation (codec `O(1)`). + /// - 2 storage writes (condec `O(1)`). + /// - 1 event. + /// # + #[weight = 0] fn issue(origin, #[compact] total: T::Balance) { let origin = ensure_signed(origin)?; @@ -171,7 +179,14 @@ decl_module! { } /// Move some assets from one holder to another. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + /// + /// # + /// - `O(1)` + /// - 1 static lookup + /// - 2 storage mutations (codec `O(1)`). + /// - 1 event. + /// # + #[weight = 0] fn transfer(origin, #[compact] id: T::AssetId, target: ::Source, @@ -190,7 +205,14 @@ decl_module! { } /// Destroy any assets of `id` owned by `origin`. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + /// + /// # + /// - `O(1)` + /// - 1 storage mutation (codec `O(1)`). + /// - 1 storage deletion (codec `O(1)`). + /// - 1 event. + /// # + #[weight = 0] fn destroy(origin, #[compact] id: T::AssetId) { let origin = ensure_signed(origin)?; let balance = >::take((id, &origin)); @@ -235,6 +257,8 @@ decl_storage! { /// The next asset identifier up for grabs. NextAssetId get(fn next_asset_id): T::AssetId; /// The total unit supply of an asset. + /// + /// TWOX-NOTE: `AssetId` is trusted, so this is safe. TotalSupply: map hasher(twox_64_concat) T::AssetId => T::Balance; } } @@ -260,17 +284,12 @@ mod tests { use frame_support::{impl_outer_origin, assert_ok, assert_noop, parameter_types, weights::Weight}; use sp_core::H256; - // The testing primitives are very useful for avoiding having to work with signatures - // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. use sp_runtime::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; impl_outer_origin! { pub enum Origin for Test where system = frame_system {} } - // For testing the pallet, we construct most of a mock runtime. This means - // first constructing a configuration type (`Test`) which `impl`s each of the - // configuration traits of pallets we want to use. #[derive(Clone, Eq, PartialEq)] pub struct Test; parameter_types! { @@ -280,6 +299,7 @@ mod tests { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type Call = (); @@ -292,6 +312,10 @@ mod tests { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); @@ -299,6 +323,7 @@ mod tests { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } impl Trait for Test { type Event = (); @@ -307,8 +332,6 @@ mod tests { } type Assets = Module; - // This function basically just builds a genesis storage key/value store according to - // our desired mockup. fn new_test_ext() -> sp_io::TestExternalities { frame_system::GenesisConfig::default().build_storage::().unwrap().into() } diff --git a/frame/atomic-swap/Cargo.toml b/frame/atomic-swap/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..829c40b675c35945eb58ed8a73aaa08050ed405e --- /dev/null +++ b/frame/atomic-swap/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "pallet-atomic-swap" +version = "2.0.0-rc4" +authors = ["Parity Technologies "] +edition = "2018" +license = "Apache-2.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +description = "FRAME atomic swap pallet" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +serde = { version = "1.0.101", optional = true } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/core" } + +[dev-dependencies] +pallet-balances = { version = "2.0.0-rc4", path = "../balances" } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "frame-support/std", + "frame-system/std", + "sp-runtime/std", + "sp-std/std", + "sp-io/std", + "sp-core/std", +] diff --git a/frame/atomic-swap/src/lib.rs b/frame/atomic-swap/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..56aa67310fb48f985e7344e034134c1ced659f1f --- /dev/null +++ b/frame/atomic-swap/src/lib.rs @@ -0,0 +1,327 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! # Atomic Swap +//! +//! A module for atomically sending funds. +//! +//! - [`atomic_swap::Trait`](./trait.Trait.html) +//! - [`Call`](./enum.Call.html) +//! - [`Module`](./struct.Module.html) +//! +//! ## Overview +//! +//! A module for atomically sending funds from an origin to a target. A proof +//! is used to allow the target to approve (claim) the swap. If the swap is not +//! claimed within a specified duration of time, the sender may cancel it. +//! +//! ## Interface +//! +//! ### Dispatchable Functions +//! +//! * `create_swap` - called by a sender to register a new atomic swap +//! * `claim_swap` - called by the target to approve a swap +//! * `cancel_swap` - may be called by a sender after a specified duration + +// Ensure we're `no_std` when compiling for Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +mod tests; + +use sp_std::{prelude::*, marker::PhantomData, ops::{Deref, DerefMut}}; +use sp_io::hashing::blake2_256; +use frame_support::{ + Parameter, decl_module, decl_storage, decl_event, decl_error, ensure, + traits::{Get, Currency, ReservableCurrency, BalanceStatus}, + weights::Weight, + dispatch::DispatchResult, +}; +use frame_system::{self as system, ensure_signed}; +use codec::{Encode, Decode}; +use sp_runtime::RuntimeDebug; + +/// Pending atomic swap operation. +#[derive(Clone, Eq, PartialEq, RuntimeDebug, Encode, Decode)] +pub struct PendingSwap { + /// Source of the swap. + pub source: T::AccountId, + /// Action of this swap. + pub action: T::SwapAction, + /// End block of the lock. + pub end_block: T::BlockNumber, +} + +/// Hashed proof type. +pub type HashedProof = [u8; 32]; + +/// Definition of a pending atomic swap action. It contains the following three phrases: +/// +/// - **Reserve**: reserve the resources needed for a swap. This is to make sure that **Claim** +/// succeeds with best efforts. +/// - **Claim**: claim any resources reserved in the first phrase. +/// - **Cancel**: cancel any resources reserved in the first phrase. +pub trait SwapAction { + /// Reserve the resources needed for the swap, from the given `source`. The reservation is + /// allowed to fail. If that is the case, the the full swap creation operation is cancelled. + fn reserve(&self, source: &T::AccountId) -> DispatchResult; + /// Claim the reserved resources, with `source` and `target`. Returns whether the claim + /// succeeds. + fn claim(&self, source: &T::AccountId, target: &T::AccountId) -> bool; + /// Weight for executing the operation. + fn weight(&self) -> Weight; + /// Cancel the resources reserved in `source`. + fn cancel(&self, source: &T::AccountId); +} + +/// A swap action that only allows transferring balances. +#[derive(Clone, RuntimeDebug, Eq, PartialEq, Encode, Decode)] +pub struct BalanceSwapAction> { + value: ::AccountId>>::Balance, + _marker: PhantomData, +} + +impl BalanceSwapAction where + C: ReservableCurrency, +{ + /// Create a new swap action value of balance. + pub fn new(value: ::AccountId>>::Balance) -> Self { + Self { value, _marker: PhantomData } + } +} + +impl Deref for BalanceSwapAction where + C: ReservableCurrency, +{ + type Target = ::AccountId>>::Balance; + + fn deref(&self) -> &Self::Target { + &self.value + } +} + +impl DerefMut for BalanceSwapAction where + C: ReservableCurrency, +{ + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.value + } +} + +impl SwapAction for BalanceSwapAction where + C: ReservableCurrency, +{ + fn reserve(&self, source: &T::AccountId) -> DispatchResult { + C::reserve(&source, self.value) + } + + fn claim(&self, source: &T::AccountId, target: &T::AccountId) -> bool { + C::repatriate_reserved(source, target, self.value, BalanceStatus::Free).is_ok() + } + + fn weight(&self) -> Weight { + T::DbWeight::get().reads_writes(1, 1) + } + + fn cancel(&self, source: &T::AccountId) { + C::unreserve(source, self.value); + } +} + +/// Atomic swap's pallet configuration trait. +pub trait Trait: frame_system::Trait { + /// The overarching event type. + type Event: From> + Into<::Event>; + /// Swap action. + type SwapAction: SwapAction + Parameter; + /// Limit of proof size. + /// + /// Atomic swap is only atomic if once the proof is revealed, both parties can submit the proofs + /// on-chain. If A is the one that generates the proof, then it requires that either: + /// - A's blockchain has the same proof length limit as B's blockchain. + /// - Or A's blockchain has shorter proof length limit as B's blockchain. + /// + /// If B sees A is on a blockchain with larger proof length limit, then it should kindly refuse + /// to accept the atomic swap request if A generates the proof, and asks that B generates the + /// proof instead. + type ProofLimit: Get; +} + +decl_storage! { + trait Store for Module as AtomicSwap { + pub PendingSwaps: double_map + hasher(twox_64_concat) T::AccountId, hasher(blake2_128_concat) HashedProof + => Option>; + } +} + +decl_error! { + pub enum Error for Module { + /// Swap already exists. + AlreadyExist, + /// Swap proof is invalid. + InvalidProof, + /// Proof is too large. + ProofTooLarge, + /// Source does not match. + SourceMismatch, + /// Swap has already been claimed. + AlreadyClaimed, + /// Swap does not exist. + NotExist, + /// Claim action mismatch. + ClaimActionMismatch, + /// Duration has not yet passed for the swap to be cancelled. + DurationNotPassed, + } +} + +decl_event!( + /// Event of atomic swap pallet. + pub enum Event where + AccountId = ::AccountId, + PendingSwap = PendingSwap, + { + /// Swap created. + NewSwap(AccountId, HashedProof, PendingSwap), + /// Swap claimed. The last parameter indicates whether the execution succeeds. + SwapClaimed(AccountId, HashedProof, bool), + /// Swap cancelled. + SwapCancelled(AccountId, HashedProof), + } +); + +decl_module! { + /// Module definition of atomic swap pallet. + pub struct Module for enum Call where origin: T::Origin { + type Error = Error; + + fn deposit_event() = default; + + /// Register a new atomic swap, declaring an intention to send funds from origin to target + /// on the current blockchain. The target can claim the fund using the revealed proof. If + /// the fund is not claimed after `duration` blocks, then the sender can cancel the swap. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// - `target`: Receiver of the atomic swap. + /// - `hashed_proof`: The blake2_256 hash of the secret proof. + /// - `balance`: Funds to be sent from origin. + /// - `duration`: Locked duration of the atomic swap. For safety reasons, it is recommended + /// that the revealer uses a shorter duration than the counterparty, to prevent the + /// situation where the revealer reveals the proof too late around the end block. + #[weight = T::DbWeight::get().reads_writes(1, 1).saturating_add(40_000_000)] + fn create_swap( + origin, + target: T::AccountId, + hashed_proof: HashedProof, + action: T::SwapAction, + duration: T::BlockNumber, + ) { + let source = ensure_signed(origin)?; + ensure!( + !PendingSwaps::::contains_key(&target, hashed_proof), + Error::::AlreadyExist + ); + + action.reserve(&source)?; + + let swap = PendingSwap { + source, + action, + end_block: frame_system::Module::::block_number() + duration, + }; + PendingSwaps::::insert(target.clone(), hashed_proof.clone(), swap.clone()); + + Self::deposit_event( + RawEvent::NewSwap(target, hashed_proof, swap) + ); + } + + /// Claim an atomic swap. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// - `proof`: Revealed proof of the claim. + /// - `action`: Action defined in the swap, it must match the entry in blockchain. Otherwise + /// the operation fails. This is used for weight calculation. + #[weight = T::DbWeight::get().reads_writes(1, 1) + .saturating_add(40_000_000) + .saturating_add((proof.len() as Weight).saturating_mul(100)) + .saturating_add(action.weight()) + ] + fn claim_swap( + origin, + proof: Vec, + action: T::SwapAction, + ) -> DispatchResult { + ensure!( + proof.len() <= T::ProofLimit::get() as usize, + Error::::ProofTooLarge, + ); + + let target = ensure_signed(origin)?; + let hashed_proof = blake2_256(&proof); + + let swap = PendingSwaps::::get(&target, hashed_proof) + .ok_or(Error::::InvalidProof)?; + ensure!(swap.action == action, Error::::ClaimActionMismatch); + + let succeeded = swap.action.claim(&swap.source, &target); + + PendingSwaps::::remove(target.clone(), hashed_proof.clone()); + + Self::deposit_event( + RawEvent::SwapClaimed(target, hashed_proof, succeeded) + ); + + Ok(()) + } + + /// Cancel an atomic swap. Only possible after the originally set duration has passed. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// - `target`: Target of the original atomic swap. + /// - `hashed_proof`: Hashed proof of the original atomic swap. + #[weight = T::DbWeight::get().reads_writes(1, 1).saturating_add(40_000_000)] + fn cancel_swap( + origin, + target: T::AccountId, + hashed_proof: HashedProof, + ) { + let source = ensure_signed(origin)?; + + let swap = PendingSwaps::::get(&target, hashed_proof) + .ok_or(Error::::NotExist)?; + ensure!( + swap.source == source, + Error::::SourceMismatch, + ); + ensure!( + frame_system::Module::::block_number() >= swap.end_block, + Error::::DurationNotPassed, + ); + + swap.action.cancel(&swap.source); + PendingSwaps::::remove(&target, hashed_proof.clone()); + + Self::deposit_event( + RawEvent::SwapCancelled(target, hashed_proof) + ); + } + } +} diff --git a/frame/atomic-swap/src/tests.rs b/frame/atomic-swap/src/tests.rs new file mode 100644 index 0000000000000000000000000000000000000000..82cd30d5d32dd6ef619c33f362eabd446924c32f --- /dev/null +++ b/frame/atomic-swap/src/tests.rs @@ -0,0 +1,154 @@ +#![cfg(test)] + +use super::*; + +use frame_support::{ + impl_outer_origin, parameter_types, weights::Weight, +}; +use sp_core::H256; +use sp_runtime::{ + Perbill, + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, +}; + +impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} +} + +#[derive(Clone, Eq, Debug, PartialEq)] +pub struct Test; +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} +impl frame_system::Trait for Test { + type BaseCallFilter = (); + 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 DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); +} +parameter_types! { + pub const ExistentialDeposit: u64 = 1; +} +impl pallet_balances::Trait for Test { + type Balance = u64; + type DustRemoval = (); + type Event = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); +} +parameter_types! { + pub const ProofLimit: u32 = 1024; + pub const ExpireDuration: u64 = 100; +} +impl Trait for Test { + type Event = (); + type SwapAction = BalanceSwapAction; + type ProofLimit = ProofLimit; +} +type System = frame_system::Module; +type Balances = pallet_balances::Module; +type AtomicSwap = Module; + +const A: u64 = 1; +const B: u64 = 2; + +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + let genesis = pallet_balances::GenesisConfig:: { + balances: vec![ + (A, 100), + (B, 200), + ], + }; + genesis.assimilate_storage(&mut t).unwrap(); + t.into() +} + +#[test] +fn two_party_successful_swap() { + let mut chain1 = new_test_ext(); + let mut chain2 = new_test_ext(); + + // A generates a random proof. Keep it secret. + let proof: [u8; 2] = [4, 2]; + // The hashed proof is the blake2_256 hash of the proof. This is public. + let hashed_proof = blake2_256(&proof); + + // A creates the swap on chain1. + chain1.execute_with(|| { + AtomicSwap::create_swap( + Origin::signed(A), + B, + hashed_proof.clone(), + BalanceSwapAction::new(50), + 1000, + ).unwrap(); + + assert_eq!(Balances::free_balance(A), 100 - 50); + assert_eq!(Balances::free_balance(B), 200); + }); + + // B creates the swap on chain2. + chain2.execute_with(|| { + AtomicSwap::create_swap( + Origin::signed(B), + A, + hashed_proof.clone(), + BalanceSwapAction::new(75), + 1000, + ).unwrap(); + + assert_eq!(Balances::free_balance(A), 100); + assert_eq!(Balances::free_balance(B), 200 - 75); + }); + + // A reveals the proof and claims the swap on chain2. + chain2.execute_with(|| { + AtomicSwap::claim_swap( + Origin::signed(A), + proof.to_vec(), + BalanceSwapAction::new(75), + ).unwrap(); + + assert_eq!(Balances::free_balance(A), 100 + 75); + assert_eq!(Balances::free_balance(B), 200 - 75); + }); + + // B use the revealed proof to claim the swap on chain1. + chain1.execute_with(|| { + AtomicSwap::claim_swap( + Origin::signed(B), + proof.to_vec(), + BalanceSwapAction::new(50), + ).unwrap(); + + assert_eq!(Balances::free_balance(A), 100 - 50); + assert_eq!(Balances::free_balance(B), 200 + 50); + }); +} diff --git a/frame/aura/Cargo.toml b/frame/aura/Cargo.toml index 36e79116618e35c296590c96a1666e03bd349784..a648be5f10b17048e7fa1408b704ffe6609a7bb8 100644 --- a/frame/aura/Cargo.toml +++ b/frame/aura/Cargo.toml @@ -1,31 +1,34 @@ [package] name = "pallet-aura" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME AURA consensus pallet" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-application-crypto = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/application-crypto" } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-inherents = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/inherents" } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/core" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } +sp-application-crypto = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/application-crypto" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-inherents = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/inherents" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } serde = { version = "1.0.101", optional = true } -pallet-session = { version = "2.0.0-alpha.5", default-features = false, path = "../session" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -sp-io ={ path = "../../primitives/io", default-features = false , version = "2.0.0-alpha.5"} -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -sp-consensus-aura = { path = "../../primitives/consensus/aura", default-features = false, version = "0.8.0-alpha.5"} -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } -sp-timestamp = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/timestamp" } -pallet-timestamp = { version = "2.0.0-alpha.5", default-features = false, path = "../timestamp" } +pallet-session = { version = "2.0.0-rc4", default-features = false, path = "../session" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +sp-consensus-aura = { version = "0.8.0-rc4", path = "../../primitives/consensus/aura", default-features = false } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } +sp-timestamp = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/timestamp" } +pallet-timestamp = { version = "2.0.0-rc4", default-features = false, path = "../timestamp" } [dev-dependencies] +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/core" } +sp-io ={ version = "2.0.0-rc4", path = "../../primitives/io" } lazy_static = "1.4.0" parking_lot = "0.10.0" @@ -35,8 +38,6 @@ std = [ "sp-application-crypto/std", "codec/std", "sp-inherents/std", - "sp-io/std", - "sp-core/std", "sp-std/std", "serde", "sp-runtime/std", @@ -46,6 +47,3 @@ std = [ "sp-timestamp/std", "pallet-timestamp/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/aura/src/lib.rs b/frame/aura/src/lib.rs index e2aafde9efe6ef699bcd61ef861fe7104dd7e331..ca3d1f15f421bfae638a69a45f012a76e407e54a 100644 --- a/frame/aura/src/lib.rs +++ b/frame/aura/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Aura Module //! @@ -161,6 +162,27 @@ impl FindAuthor for Module { } } +/// We can not implement `FindAuthor` twice, because the compiler does not know if +/// `u32 == T::AuthorityId` and thus, prevents us to implement the trait twice. +#[doc(hidden)] +pub struct FindAccountFromAuthorIndex(sp_std::marker::PhantomData<(T, Inner)>); + +impl> FindAuthor + for FindAccountFromAuthorIndex +{ + fn find_author<'a, I>(digests: I) -> Option + where I: 'a + IntoIterator + { + let i = Inner::find_author(digests)?; + + let validators = >::authorities(); + validators.get(i as usize).map(|k| k.clone()) + } +} + +/// Find the authority ID of the Aura authority who authored the current block. +pub type AuraAuthorId = FindAccountFromAuthorIndex>; + impl IsMember for Module { fn is_member(authority_id: &T::AuthorityId) -> bool { Self::authorities() diff --git a/frame/aura/src/mock.rs b/frame/aura/src/mock.rs index 05a161ee49c3d6c9ac7c51028d31f1dd9d193bc8..5695c50ac575d031e65b0bb6fd09f458682ffbe4 100644 --- a/frame/aura/src/mock.rs +++ b/frame/aura/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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. +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utilities @@ -45,6 +46,7 @@ parameter_types! { } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -57,6 +59,10 @@ impl frame_system::Trait for Test { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); @@ -64,12 +70,14 @@ impl frame_system::Trait for Test { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } impl pallet_timestamp::Trait for Test { type Moment = u64; type OnTimestampSet = Aura; type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); } impl Trait for Test { diff --git a/frame/aura/src/tests.rs b/frame/aura/src/tests.rs index a7cb5503c4712acb79c0902be5f9a707e6f7ad07..ca0fc3de3763809d1f7d4c50d4adf862b8e9305d 100644 --- a/frame/aura/src/tests.rs +++ b/frame/aura/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Tests for the module. diff --git a/frame/authority-discovery/Cargo.toml b/frame/authority-discovery/Cargo.toml index f67d4ee038ab374a5cd2c75c947f141fc58fdde2..3270437ce8bd2786346795b4949c8bbdaa0c9041 100644 --- a/frame/authority-discovery/Cargo.toml +++ b/frame/authority-discovery/Cargo.toml @@ -1,28 +1,31 @@ [package] name = "pallet-authority-discovery" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for authority discovery" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-authority-discovery = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/authority-discovery" } -sp-application-crypto = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/application-crypto" } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/core" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } +sp-authority-discovery = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/authority-discovery" } +sp-application-crypto = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/application-crypto" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } serde = { version = "1.0.101", optional = true } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/io" } -pallet-session = { version = "2.0.0-alpha.5", features = ["historical" ], path = "../session", default-features = false } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } +pallet-session = { version = "2.0.0-rc4", features = ["historical" ], path = "../session", default-features = false } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } [dev-dependencies] -sp-staking = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/staking" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +sp-io = { version = "2.0.0-rc4", path = "../../primitives/io" } +sp-staking = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/staking" } [features] default = ["std"] @@ -30,8 +33,6 @@ std = [ "sp-application-crypto/std", "sp-authority-discovery/std", "codec/std", - "sp-core/std", - "sp-io/std", "sp-std/std", "serde", "pallet-session/std", @@ -39,6 +40,3 @@ std = [ "frame-support/std", "frame-system/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/authority-discovery/src/lib.rs b/frame/authority-discovery/src/lib.rs index b8f28b432ba75f14594ee50e9b6fbfeb0ee73312..f048fe011bd9ba2dbde4d9ef12bb8b18f191f854 100644 --- a/frame/authority-discovery/src/lib.rs +++ b/frame/authority-discovery/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Authority discovery module. //! @@ -122,6 +123,7 @@ mod tests { type ValidatorIdOf = ConvertInto; type DisabledValidatorsThreshold = DisabledValidatorsThreshold; type NextSessionRotation = pallet_session::PeriodicSessions; + type WeightInfo = (); } impl pallet_session::historical::Trait for Test { @@ -142,6 +144,7 @@ mod tests { } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = BlockNumber; @@ -154,6 +157,10 @@ mod tests { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); @@ -161,6 +168,7 @@ mod tests { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } impl_outer_origin! { diff --git a/frame/authorship/Cargo.toml b/frame/authorship/Cargo.toml index fb966113d55ee67fda4dcf946487f82a9185d6a6..08114eb4016f14af32c22100a9cc5ddfe05df6c2 100644 --- a/frame/authorship/Cargo.toml +++ b/frame/authorship/Cargo.toml @@ -1,38 +1,38 @@ [package] name = "pallet-authorship" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" description = "Block and Uncle Author tracking for the FRAME" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/core" } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-inherents = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/inherents" } -sp-authorship = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/authorship" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } -sp-io ={ path = "../../primitives/io", default-features = false , version = "2.0.0-alpha.5"} +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-inherents = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/inherents" } +sp-authorship = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/authorship" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } impl-trait-for-tuples = "0.1.3" +[dev-dependencies] +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +sp-io ={ version = "2.0.0-rc4", path = "../../primitives/io" } + [features] default = ["std"] std = [ "codec/std", - "sp-core/std", "sp-inherents/std", "sp-runtime/std", "sp-std/std", "frame-support/std", "frame-system/std", - "sp-io/std", "sp-authorship/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/authorship/src/lib.rs b/frame/authorship/src/lib.rs index d71a71e5bf0ef18d1a8e35167200c0753f69d4df..b62e924d00fc9809bfe8855734c15c622b089818 100644 --- a/frame/authorship/src/lib.rs +++ b/frame/authorship/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Authorship tracking for FRAME runtimes. //! @@ -27,7 +28,7 @@ use frame_support::traits::{FindAuthor, VerifySeal, Get}; use codec::{Encode, Decode}; use frame_system::ensure_none; use sp_runtime::traits::{Header as HeaderT, One, Zero}; -use frame_support::weights::{Weight, SimpleDispatchInfo, WeighData}; +use frame_support::weights::{Weight, DispatchClass}; use sp_inherents::{InherentIdentifier, ProvideInherent, InherentData}; use sp_authorship::{INHERENT_IDENTIFIER, UnclesInherentData, InherentError}; @@ -197,7 +198,7 @@ decl_module! { T::EventHandler::note_author(Self::author()); - SimpleDispatchInfo::default().weigh_data(()) + 0 } fn on_finalize() { @@ -207,7 +208,7 @@ decl_module! { } /// Provide a set of uncles. - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + #[weight = (0, DispatchClass::Mandatory)] fn set_uncles(origin, new_uncles: Vec) -> dispatch::DispatchResult { ensure_none(origin)?; ensure!(new_uncles.len() <= MAX_UNCLES, Error::::TooManyUncles); @@ -417,6 +418,7 @@ mod tests { } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -429,6 +431,10 @@ mod tests { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); @@ -436,6 +442,7 @@ mod tests { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } parameter_types! { diff --git a/frame/babe/Cargo.toml b/frame/babe/Cargo.toml index 8f885500224053f5ccb8ecb80615b468a34bc514..e29965ee4628549586ffaf52a3d14153c93696c2 100644 --- a/frame/babe/Cargo.toml +++ b/frame/babe/Cargo.toml @@ -1,50 +1,64 @@ [package] name = "pallet-babe" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Consensus extension module for BABE consensus. Collects on-chain randomness from VRF outputs and manages epoch transitions." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +frame-benchmarking = { version = "2.0.0-rc4", default-features = false, path = "../benchmarking", optional = true } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } +pallet-authorship = { version = "2.0.0-rc4", default-features = false, path = "../authorship" } +pallet-session = { version = "2.0.0-rc4", default-features = false, path = "../session" } +pallet-timestamp = { version = "2.0.0-rc4", default-features = false, path = "../timestamp" } serde = { version = "1.0.101", optional = true } -sp-inherents = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/inherents" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -sp-staking = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/staking" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } -pallet-timestamp = { version = "2.0.0-alpha.5", default-features = false, path = "../timestamp" } -sp-timestamp = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/timestamp" } -pallet-session = { version = "2.0.0-alpha.5", default-features = false, path = "../session" } -sp-consensus-babe = { version = "0.8.0-alpha.5", default-features = false, path = "../../primitives/consensus/babe" } -sp-consensus-vrf = { version = "0.8.0-alpha.5", default-features = false, path = "../../primitives/consensus/vrf" } -sp-io = { path = "../../primitives/io", default-features = false , version = "2.0.0-alpha.5"} +sp-application-crypto = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/application-crypto" } +sp-consensus-babe = { version = "0.8.0-rc4", default-features = false, path = "../../primitives/consensus/babe" } +sp-consensus-vrf = { version = "0.8.0-rc4", default-features = false, path = "../../primitives/consensus/vrf" } +sp-inherents = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/inherents" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +sp-session = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/session" } +sp-staking = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/staking" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-timestamp = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/timestamp" } [dev-dependencies] -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } +frame-benchmarking = { version = "2.0.0-rc4", path = "../benchmarking" } +pallet-balances = { version = "2.0.0-rc4", path = "../balances" } +pallet-offences = { version = "2.0.0-rc4", path = "../offences" } +pallet-staking = { version = "2.0.0-rc4", path = "../staking" } +pallet-staking-reward-curve = { version = "2.0.0-rc4", path = "../staking/reward-curve" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } [features] default = ["std"] std = [ - "serde", "codec/std", - "sp-std/std", + "frame-benchmarking/std", "frame-support/std", - "sp-runtime/std", - "sp-staking/std", "frame-system/std", + "pallet-authorship/std", + "pallet-session/std", "pallet-timestamp/std", - "sp-timestamp/std", - "sp-inherents/std", + "serde", + "sp-application-crypto/std", "sp-consensus-babe/std", "sp-consensus-vrf/std", - "pallet-session/std", + "sp-inherents/std", "sp-io/std", + "sp-runtime/std", + "sp-session/std", + "sp-staking/std", + "sp-std/std", + "sp-timestamp/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +runtime-benchmarks = ["frame-benchmarking"] diff --git a/frame/babe/src/benchmarking.rs b/frame/babe/src/benchmarking.rs new file mode 100644 index 0000000000000000000000000000000000000000..e168c1b93b29c5fb40ff8198cfa598960025325b --- /dev/null +++ b/frame/babe/src/benchmarking.rs @@ -0,0 +1,108 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Benchmarks for the BABE Pallet. + +#![cfg_attr(not(feature = "std"), no_std)] + +use super::*; +use frame_benchmarking::benchmarks; + +type Header = sp_runtime::generic::Header; + +benchmarks! { + _ { } + + check_equivocation_proof { + let x in 0 .. 1; + + // NOTE: generated with the test below `test_generate_equivocation_report_blob`. + // the output is not deterministic since keys are generated randomly (and therefore + // signature content changes). it should not affect the benchmark. + // with the current benchmark setup it is not possible to generate this programatically + // from the benchmark setup. + const EQUIVOCATION_PROOF_BLOB: [u8; 416] = [ + 222, 241, 46, 66, 243, 228, 135, 233, 177, 64, 149, 170, 141, 92, 193, 106, 51, 73, 31, + 27, 80, 218, 220, 248, 129, 29, 20, 128, 243, 250, 134, 39, 11, 0, 0, 0, 0, 0, 0, 0, + 158, 4, 7, 240, 67, 153, 134, 190, 251, 196, 229, 95, 136, 165, 234, 228, 255, 18, 2, + 187, 76, 125, 108, 50, 67, 33, 196, 108, 38, 115, 179, 86, 40, 36, 27, 5, 105, 58, 228, + 94, 198, 65, 212, 218, 213, 61, 170, 21, 51, 249, 182, 121, 101, 91, 204, 25, 31, 87, + 219, 208, 43, 119, 211, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 6, 66, 65, 66, 69, 52, 2, 0, 0, 0, 0, 11, + 0, 0, 0, 0, 0, 0, 0, 5, 66, 65, 66, 69, 1, 1, 188, 192, 217, 91, 138, 78, 217, 80, 8, + 29, 140, 55, 242, 210, 170, 184, 73, 98, 135, 212, 236, 209, 115, 52, 200, 79, 175, + 172, 242, 161, 199, 47, 236, 93, 101, 95, 43, 34, 141, 16, 247, 220, 33, 59, 31, 197, + 27, 7, 196, 62, 12, 238, 236, 124, 136, 191, 29, 36, 22, 238, 242, 202, 57, 139, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 40, 23, 175, 153, 83, 6, 33, 65, 123, 51, 80, 223, 126, 186, 226, 225, 240, 105, 28, + 169, 9, 54, 11, 138, 46, 194, 201, 250, 48, 242, 125, 117, 116, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 6, 66, 65, + 66, 69, 52, 2, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 5, 66, 65, 66, 69, 1, 1, 142, 12, + 124, 11, 167, 227, 103, 88, 78, 23, 228, 33, 96, 41, 207, 183, 227, 189, 114, 70, 254, + 30, 128, 243, 233, 83, 214, 45, 74, 182, 120, 119, 64, 243, 219, 119, 63, 240, 205, + 123, 231, 82, 205, 174, 143, 70, 2, 86, 182, 20, 16, 141, 145, 91, 116, 195, 58, 223, + 175, 145, 255, 7, 121, 133 + ]; + + let equivocation_proof1: sp_consensus_babe::EquivocationProof
= + Decode::decode(&mut &EQUIVOCATION_PROOF_BLOB[..]).unwrap(); + + let equivocation_proof2 = equivocation_proof1.clone(); + }: { + sp_consensus_babe::check_equivocation_proof::
(equivocation_proof1); + } verify { + assert!(sp_consensus_babe::check_equivocation_proof::
(equivocation_proof2)); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::*; + use frame_support::assert_ok; + + #[test] + fn test_benchmarks() { + new_test_ext(3).execute_with(|| { + assert_ok!(test_benchmark_check_equivocation_proof::()); + }) + } + + #[test] + fn test_generate_equivocation_report_blob() { + let (pairs, mut ext) = new_test_ext_with_pairs(3); + + let offending_authority_index = 0; + let offending_authority_pair = &pairs[0]; + + ext.execute_with(|| { + start_era(1); + + let equivocation_proof = generate_equivocation_proof( + offending_authority_index, + offending_authority_pair, + CurrentSlot::get() + 1, + ); + + println!("equivocation_proof: {:?}", equivocation_proof); + println!( + "equivocation_proof.encode(): {:?}", + equivocation_proof.encode() + ); + }); + } +} diff --git a/frame/babe/src/equivocation.rs b/frame/babe/src/equivocation.rs new file mode 100644 index 0000000000000000000000000000000000000000..322dff92f2398b330efff33357125da694c85451 --- /dev/null +++ b/frame/babe/src/equivocation.rs @@ -0,0 +1,271 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! +//! An opt-in utility module for reporting equivocations. +//! +//! This module defines an offence type for BABE equivocations +//! and some utility traits to wire together: +//! - a system for reporting offences; +//! - a system for submitting unsigned transactions; +//! - a way to get the current block author; +//! +//! These can be used in an offchain context in order to submit equivocation +//! reporting extrinsics (from the client that's import BABE blocks). +//! And in a runtime context, so that the BABE pallet can validate the +//! equivocation proofs in the extrinsic and report the offences. +//! +//! IMPORTANT: +//! When using this module for enabling equivocation reporting it is required +//! that the `ValidateUnsigned` for the BABE pallet is used in the runtime +//! definition. +//! + +use frame_support::{debug, traits::KeyOwnerProofSystem}; +use sp_consensus_babe::{EquivocationProof, SlotNumber}; +use sp_runtime::transaction_validity::{ + InvalidTransaction, TransactionPriority, TransactionSource, TransactionValidity, + TransactionValidityError, ValidTransaction, +}; +use sp_runtime::{DispatchResult, Perbill}; +use sp_staking::{ + offence::{Kind, Offence, OffenceError, ReportOffence}, + SessionIndex, +}; +use sp_std::prelude::*; + +use crate::{Call, Module, Trait}; + +/// A trait with utility methods for handling equivocation reports in BABE. +/// The trait provides methods for reporting an offence triggered by a valid +/// equivocation report, checking the current block author (to declare as the +/// reporter), and also for creating and submitting equivocation report +/// extrinsics (useful only in offchain context). +pub trait HandleEquivocation { + /// Report an offence proved by the given reporters. + fn report_offence( + reporters: Vec, + offence: BabeEquivocationOffence, + ) -> Result<(), OffenceError>; + + /// Returns true if all of the offenders at the given time slot have already been reported. + fn is_known_offence(offenders: &[T::KeyOwnerIdentification], time_slot: &SlotNumber) -> bool; + + /// Create and dispatch an equivocation report extrinsic. + fn submit_unsigned_equivocation_report( + equivocation_proof: EquivocationProof, + key_owner_proof: T::KeyOwnerProof, + ) -> DispatchResult; + + /// Fetch the current block author id, if defined. + fn block_author() -> Option; +} + +impl HandleEquivocation for () { + fn report_offence( + _reporters: Vec, + _offence: BabeEquivocationOffence, + ) -> Result<(), OffenceError> { + Ok(()) + } + + fn is_known_offence(_offenders: &[T::KeyOwnerIdentification], _time_slot: &SlotNumber) -> bool { + true + } + + fn submit_unsigned_equivocation_report( + _equivocation_proof: EquivocationProof, + _key_owner_proof: T::KeyOwnerProof, + ) -> DispatchResult { + Ok(()) + } + + fn block_author() -> Option { + None + } +} + +/// Generic equivocation handler. This type implements `HandleEquivocation` +/// using existing subsystems that are part of frame (type bounds described +/// below) and will dispatch to them directly, it's only purpose is to wire all +/// subsystems together. +pub struct EquivocationHandler { + _phantom: sp_std::marker::PhantomData<(I, R)>, +} + +impl Default for EquivocationHandler { + fn default() -> Self { + Self { + _phantom: Default::default(), + } + } +} + +impl HandleEquivocation for EquivocationHandler +where + // We use the authorship pallet to fetch the current block author and use + // `offchain::SendTransactionTypes` for unsigned extrinsic creation and + // submission. + T: Trait + pallet_authorship::Trait + frame_system::offchain::SendTransactionTypes>, + // A system for reporting offences after valid equivocation reports are + // processed. + R: ReportOffence< + T::AccountId, + T::KeyOwnerIdentification, + BabeEquivocationOffence, + >, +{ + fn report_offence( + reporters: Vec, + offence: BabeEquivocationOffence, + ) -> Result<(), OffenceError> { + R::report_offence(reporters, offence) + } + + fn is_known_offence(offenders: &[T::KeyOwnerIdentification], time_slot: &SlotNumber) -> bool { + R::is_known_offence(offenders, time_slot) + } + + fn submit_unsigned_equivocation_report( + equivocation_proof: EquivocationProof, + key_owner_proof: T::KeyOwnerProof, + ) -> DispatchResult { + use frame_system::offchain::SubmitTransaction; + + let call = Call::report_equivocation_unsigned(equivocation_proof, key_owner_proof); + + match SubmitTransaction::>::submit_unsigned_transaction(call.into()) { + Ok(()) => debug::info!("Submitted BABE equivocation report."), + Err(e) => debug::error!("Error submitting equivocation report: {:?}", e), + } + + Ok(()) + } + + fn block_author() -> Option { + Some(>::author()) + } +} + +/// A `ValidateUnsigned` implementation that restricts calls to `report_equivocation_unsigned` +/// to local calls (i.e. extrinsics generated on this node) or that already in a block. This +/// guarantees that only block authors can include unsigned equivocation reports. +impl frame_support::unsigned::ValidateUnsigned for Module { + type Call = Call; + fn validate_unsigned(source: TransactionSource, call: &Self::Call) -> TransactionValidity { + if let Call::report_equivocation_unsigned(equivocation_proof, _) = call { + // discard equivocation report not coming from the local node + match source { + TransactionSource::Local | TransactionSource::InBlock => { /* allowed */ } + _ => { + debug::warn!( + target: "babe", + "rejecting unsigned report equivocation transaction because it is not local/in-block." + ); + + return InvalidTransaction::Call.into(); + } + } + + ValidTransaction::with_tag_prefix("BabeEquivocation") + // We assign the maximum priority for any equivocation report. + .priority(TransactionPriority::max_value()) + // Only one equivocation report for the same offender at the same slot. + .and_provides(( + equivocation_proof.offender.clone(), + equivocation_proof.slot_number, + )) + // We don't propagate this. This can never be included on a remote node. + .propagate(false) + .build() + } else { + InvalidTransaction::Call.into() + } + } + + fn pre_dispatch(call: &Self::Call) -> Result<(), TransactionValidityError> { + if let Call::report_equivocation_unsigned(equivocation_proof, key_owner_proof) = call { + // check the membership proof to extract the offender's id + let key = ( + sp_consensus_babe::KEY_TYPE, + equivocation_proof.offender.clone(), + ); + + let offender = T::KeyOwnerProofSystem::check_proof(key, key_owner_proof.clone()) + .ok_or(InvalidTransaction::BadProof)?; + + // check if the offence has already been reported, + // and if so then we can discard the report. + let is_known_offence = T::HandleEquivocation::is_known_offence( + &[offender], + &equivocation_proof.slot_number, + ); + + if is_known_offence { + Err(InvalidTransaction::Stale.into()) + } else { + Ok(()) + } + } else { + Err(InvalidTransaction::Call.into()) + } + } +} + +/// A BABE equivocation offence report. +/// +/// When a validator released two or more blocks at the same slot. +pub struct BabeEquivocationOffence { + /// A babe slot number in which this incident happened. + pub slot: SlotNumber, + /// The session index in which the incident happened. + pub session_index: SessionIndex, + /// The size of the validator set at the time of the offence. + pub validator_set_count: u32, + /// The authority that produced the equivocation. + pub offender: FullIdentification, +} + +impl Offence + for BabeEquivocationOffence +{ + const ID: Kind = *b"babe:equivocatio"; + type TimeSlot = SlotNumber; + + 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() + } +} diff --git a/frame/babe/src/lib.rs b/frame/babe/src/lib.rs index 5f85b910880670e646eb7c903688f754fcefa1b3..f80ac186434d0796387439899f8993eaadaa41f5 100644 --- a/frame/babe/src/lib.rs +++ b/frame/babe/src/lib.rs @@ -1,55 +1,64 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! 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, unused_must_use)] - -use pallet_timestamp; +#![warn(unused_must_use, unsafe_code, unused_variables, unused_must_use)] -use sp_std::{result, prelude::*}; +use codec::{Decode, Encode}; use frame_support::{ - decl_storage, decl_module, traits::{FindAuthor, Get, Randomness as RandomnessT}, - weights::{Weight, SimpleDispatchInfo, WeighData}, + decl_error, decl_module, decl_storage, + traits::{FindAuthor, Get, KeyOwnerProofSystem, Randomness as RandomnessT}, + weights::Weight, + Parameter, }; -use sp_timestamp::OnTimestampSet; -use sp_runtime::{generic::DigestItem, ConsensusEngineId, Perbill}; -use sp_runtime::traits::{IsMember, SaturatedConversion, Saturating, Hash, One}; -use sp_staking::{ - SessionIndex, - offence::{Offence, Kind}, +use frame_system::{ensure_none, ensure_signed}; +use sp_application_crypto::Public; +use sp_runtime::{ + generic::DigestItem, + traits::{Hash, IsMember, One, SaturatedConversion, Saturating}, + ConsensusEngineId, KeyTypeId, }; +use sp_session::{GetSessionNumber, GetValidatorCount}; +use sp_std::{prelude::*, result}; +use sp_timestamp::OnTimestampSet; -use codec::{Encode, Decode}; -use sp_inherents::{InherentIdentifier, InherentData, ProvideInherent, MakeFatalError}; use sp_consensus_babe::{ - BABE_ENGINE_ID, ConsensusLog, BabeAuthorityWeight, SlotNumber, - inherents::{INHERENT_IDENTIFIER, BabeInherentData}, - digests::{NextEpochDescriptor, RawPreDigest}, + digests::{NextConfigDescriptor, NextEpochDescriptor, PreDigest}, + inherents::{BabeInherentData, INHERENT_IDENTIFIER}, + BabeAuthorityWeight, ConsensusLog, EquivocationProof, SlotNumber, BABE_ENGINE_ID, }; use sp_consensus_vrf::schnorrkel; -pub use sp_consensus_babe::{AuthorityId, VRF_OUTPUT_LENGTH, RANDOMNESS_LENGTH, PUBLIC_KEY_LENGTH}; +use sp_inherents::{InherentData, InherentIdentifier, MakeFatalError, ProvideInherent}; -#[cfg(all(feature = "std", test))] -mod tests; +pub use sp_consensus_babe::{AuthorityId, PUBLIC_KEY_LENGTH, RANDOMNESS_LENGTH, VRF_OUTPUT_LENGTH}; +mod equivocation; + +#[cfg(any(feature = "runtime-benchmarks", test))] +mod benchmarking; #[cfg(all(feature = "std", test))] mod mock; +#[cfg(all(feature = "std", test))] +mod tests; + +pub use equivocation::{BabeEquivocationOffence, EquivocationHandler, HandleEquivocation}; pub trait Trait: pallet_timestamp::Trait { /// The amount of time, in slots, that each epoch should last. @@ -68,6 +77,30 @@ pub trait Trait: pallet_timestamp::Trait { /// 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; + + /// The proof of key ownership, used for validating equivocation reports. + /// The proof must include the session index and validator count of the + /// session at which the equivocation occurred. + type KeyOwnerProof: Parameter + GetSessionNumber + GetValidatorCount; + + /// The identification of a key owner, used when reporting equivocations. + type KeyOwnerIdentification: Parameter; + + /// A system for proving ownership of keys, i.e. that a given key was part + /// of a validator set, needed for validating equivocation reports. + type KeyOwnerProofSystem: KeyOwnerProofSystem< + (KeyTypeId, AuthorityId), + Proof = Self::KeyOwnerProof, + IdentificationTuple = Self::KeyOwnerIdentification, + >; + + /// The equivocation handling subsystem, defines methods to report an + /// offence (after the equivocation has been validated) and for submitting a + /// transaction to report an equivocation (from an offchain context). + /// NOTE: when enabling equivocation handling (i.e. this type isn't set to + /// `()`) you must use this pallet's `ValidateUnsigned` in the runtime + /// definition. + type HandleEquivocation: HandleEquivocation; } /// Trigger an epoch change, if any should take place. @@ -102,7 +135,18 @@ impl EpochChangeTrigger for SameAuthoritiesForever { const UNDER_CONSTRUCTION_SEGMENT_LENGTH: usize = 256; -type MaybeVrf = Option; +type MaybeRandomness = Option; + +decl_error! { + pub enum Error for Module { + /// An equivocation proof provided as part of an equivocation report is invalid. + InvalidEquivocationProof, + /// A key ownership proof provided as part of an equivocation report is invalid. + InvalidKeyOwnershipProof, + /// A given equivocation report is valid but already previously reported. + DuplicateOffenceReport, + } +} decl_storage! { trait Store for Module as Babe { @@ -134,6 +178,9 @@ decl_storage! { // variable to its underlying value. pub Randomness get(fn randomness): schnorrkel::Randomness; + /// Next epoch configuration, if changed. + NextEpochConfig: Option; + /// Next epoch randomness. NextRandomness: schnorrkel::Randomness; @@ -147,11 +194,13 @@ decl_storage! { /// We reset all segments and return to `0` at the beginning of every /// epoch. SegmentIndex build(|_| 0): u32; - UnderConstruction: map hasher(twox_64_concat) u32 => Vec; + + /// TWOX-NOTE: `SegmentIndex` is an increasing integer, so this is okay. + UnderConstruction: map hasher(twox_64_concat) u32 => Vec; /// 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; + Initialized get(fn initialized): Option; /// How late the current block is compared to its parent. /// @@ -184,7 +233,7 @@ decl_module! { fn on_initialize(now: T::BlockNumber) -> Weight { Self::do_initialize(now); - SimpleDispatchInfo::default().weigh_data(()) + 0 } /// Block finalization @@ -194,17 +243,95 @@ decl_module! { // 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); + if let Some(Some(randomness)) = Initialized::take() { + Self::deposit_randomness(&randomness); } // remove temporary "environment" entry from storage Lateness::::kill(); } + + /// Report authority equivocation/misbehavior. This method will verify + /// the equivocation proof and validate the given key ownership proof + /// against the extracted offender. If both are valid, the offence will + /// be reported. + #[weight = weight::weight_for_report_equivocation::()] + fn report_equivocation( + origin, + equivocation_proof: EquivocationProof, + key_owner_proof: T::KeyOwnerProof, + ) { + let reporter = ensure_signed(origin)?; + + Self::do_report_equivocation( + Some(reporter), + equivocation_proof, + key_owner_proof, + )?; + } + + /// Report authority equivocation/misbehavior. This method will verify + /// the equivocation proof and validate the given key ownership proof + /// against the extracted offender. If both are valid, the offence will + /// be reported. + /// This extrinsic must be called unsigned and it is expected that only + /// block authors will call it (validated in `ValidateUnsigned`), as such + /// if the block author is defined it will be defined as the equivocation + /// reporter. + #[weight = weight::weight_for_report_equivocation::()] + fn report_equivocation_unsigned( + origin, + equivocation_proof: EquivocationProof, + key_owner_proof: T::KeyOwnerProof, + ) { + ensure_none(origin)?; + + Self::do_report_equivocation( + T::HandleEquivocation::block_author(), + equivocation_proof, + key_owner_proof, + )?; + } + } +} + +mod weight { + use frame_support::{ + traits::Get, + weights::{constants::WEIGHT_PER_MICROS, Weight}, + }; + + pub fn weight_for_report_equivocation() -> Weight { + // checking membership proof + (35 * WEIGHT_PER_MICROS) + .saturating_add(T::DbWeight::get().reads(5)) + // check equivocation proof + .saturating_add(110 * WEIGHT_PER_MICROS) + // report offence + .saturating_add(110 * WEIGHT_PER_MICROS) + // worst case we are considering is that the given offender + // is backed by 200 nominators + .saturating_add(T::DbWeight::get().reads(14 + 3 * 200)) + .saturating_add(T::DbWeight::get().writes(10 + 3 * 200)) } } impl RandomnessT<::Hash> for Module { + /// 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. fn random(subject: &[u8]) -> T::Hash { let mut subject = subject.to_vec(); subject.reserve(VRF_OUTPUT_LENGTH); @@ -223,7 +350,7 @@ impl FindAuthor for Module { { for (id, mut data) in digests.into_iter() { if id == BABE_ENGINE_ID { - let pre_digest: RawPreDigest = RawPreDigest::decode(&mut data).ok()?; + let pre_digest: PreDigest = PreDigest::decode(&mut data).ok()?; return Some(pre_digest.authority_index()) } } @@ -252,52 +379,6 @@ impl pallet_session::ShouldEndSession for Module { } } -// 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. -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() - } -} - impl Module { /// Determine the BABE slot duration based on the Timestamp module configuration. pub fn slot_duration() -> T::Moment { @@ -334,6 +415,9 @@ impl Module { // -------------- IMPORTANT NOTE -------------- // This implementation is linked to how [`should_epoch_change`] is working. This might need to // be updated accordingly, if the underlying mechanics of slot and epochs change. + // + // WEIGHT NOTE: This function is tied to the weight of `EstimateNextSessionRotation`. If you update + // this function, you must also update the corresponding weight. pub fn next_expected_epoch_change(now: T::BlockNumber) -> Option { let next_slot = Self::current_epoch_start().saturating_add(T::EpochDuration::get()); next_slot @@ -345,6 +429,15 @@ impl Module { }) } + /// Plan an epoch config change. The epoch config change is recorded and will be enacted on the + /// next call to `enact_epoch_change`. The config will be activated one epoch after. Multiple calls to this + /// method will replace any existing planned config change that had not been enacted yet. + pub fn plan_config_change( + config: NextConfigDescriptor, + ) { + NextEpochConfig::put(config); + } + /// 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. /// @@ -380,12 +473,15 @@ impl Module { // so that nodes can track changes. let next_randomness = NextRandomness::get(); - let next = NextEpochDescriptor { + let next_epoch = NextEpochDescriptor { authorities: next_authorities, randomness: next_randomness, }; + Self::deposit_consensus(ConsensusLog::NextEpochData(next_epoch)); - Self::deposit_consensus(ConsensusLog::NextEpochData(next)) + if let Some(next_config) = NextEpochConfig::take() { + Self::deposit_consensus(ConsensusLog::NextConfigData(next_config)); + } } // finds the start slot of the current epoch. only guaranteed to @@ -400,17 +496,17 @@ impl Module { >::deposit_log(log.into()) } - fn deposit_vrf_output(vrf_output: &schnorrkel::RawVRFOutput) { + fn deposit_randomness(randomness: &schnorrkel::Randomness) { let segment_idx = ::get(); let mut segment = ::get(&segment_idx); if segment.len() < UNDER_CONSTRUCTION_SEGMENT_LENGTH { // push onto current segment: not full. - segment.push(*vrf_output); + segment.push(*randomness); ::insert(&segment_idx, &segment); } else { // move onto the next segment and update the index. let segment_idx = segment_idx + 1; - ::insert(&segment_idx, &vec![vrf_output.clone()]); + ::insert(&segment_idx, &vec![randomness.clone()]); ::put(&segment_idx); } } @@ -423,18 +519,18 @@ impl Module { return; } - let maybe_pre_digest: Option = >::digest() + let maybe_pre_digest: Option = >::digest() .logs .iter() .filter_map(|s| s.as_pre_runtime()) .filter_map(|(id, mut data)| if id == BABE_ENGINE_ID { - RawPreDigest::decode(&mut data).ok() + PreDigest::decode(&mut data).ok() } else { None }) .next(); - let maybe_vrf = maybe_pre_digest.and_then(|digest| { + let maybe_randomness: Option = 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. @@ -463,17 +559,38 @@ impl Module { Lateness::::put(lateness); CurrentSlot::put(current_slot); - if let RawPreDigest::Primary(primary) = digest { + if let PreDigest::Primary(primary) = 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(primary.vrf_output) + // + // Reconstruct the bytes of VRFInOut using the authority id. + Authorities::get() + .get(primary.authority_index as usize) + .and_then(|author| { + schnorrkel::PublicKey::from_bytes(author.0.as_slice()).ok() + }) + .and_then(|pubkey| { + let transcript = sp_consensus_babe::make_transcript( + &Self::randomness(), + current_slot, + EpochIndex::get(), + ); + + primary.vrf_output.0.attach_input_hash( + &pubkey, + transcript + ).ok() + }) + .map(|inout| { + inout.make_bytes(&sp_consensus_babe::BABE_VRF_INOUT_CONTEXT) + }) } else { None } }); - Initialized::put(maybe_vrf); + Initialized::put(maybe_randomness); // enact epoch change, if necessary. T::EpochChangeTrigger::trigger::(now) @@ -504,6 +621,69 @@ impl Module { Authorities::put(authorities); } } + + fn do_report_equivocation( + reporter: Option, + equivocation_proof: EquivocationProof, + key_owner_proof: T::KeyOwnerProof, + ) -> Result<(), Error> { + let offender = equivocation_proof.offender.clone(); + let slot_number = equivocation_proof.slot_number; + + // validate the equivocation proof + if !sp_consensus_babe::check_equivocation_proof(equivocation_proof) { + return Err(Error::InvalidEquivocationProof.into()); + } + + let validator_set_count = key_owner_proof.validator_count(); + let session_index = key_owner_proof.session(); + + let epoch_index = (slot_number.saturating_sub(GenesisSlot::get()) / T::EpochDuration::get()) + .saturated_into::(); + + // check that the slot number is consistent with the session index + // in the key ownership proof (i.e. slot is for that epoch) + if epoch_index != session_index { + return Err(Error::InvalidKeyOwnershipProof.into()); + } + + // check the membership proof and extract the offender's id + let key = (sp_consensus_babe::KEY_TYPE, offender); + let offender = T::KeyOwnerProofSystem::check_proof(key, key_owner_proof) + .ok_or(Error::InvalidKeyOwnershipProof)?; + + let offence = BabeEquivocationOffence { + slot: slot_number, + validator_set_count, + offender, + session_index, + }; + + let reporters = match reporter { + Some(id) => vec![id], + None => vec![], + }; + + T::HandleEquivocation::report_offence(reporters, offence) + .map_err(|_| Error::DuplicateOffenceReport)?; + + Ok(()) + } + + /// Submits an extrinsic to report an equivocation. This method will create + /// an unsigned extrinsic with a call to `report_equivocation_unsigned` and + /// will push the transaction to the pool. Only useful in an offchain + /// context. + pub fn submit_unsigned_equivocation_report( + equivocation_proof: EquivocationProof, + key_owner_proof: T::KeyOwnerProof, + ) -> Option<()> { + T::HandleEquivocation::submit_unsigned_equivocation_report( + equivocation_proof, + key_owner_proof, + ) + .ok() + } } impl OnTimestampSet for Module { @@ -514,6 +694,12 @@ impl frame_support::traits::EstimateNextSessionRotation Option { Self::next_expected_epoch_change(now) } + + // The validity of this weight depends on the implementation of `estimate_next_session_rotation` + fn weight(_now: T::BlockNumber) -> Weight { + // Read: Current Slot, Epoch Index, Genesis Slot + T::DbWeight::get().reads(3) + } } impl frame_support::traits::Lateness for Module { @@ -562,7 +748,7 @@ impl pallet_session::OneSessionHandler for Module { fn compute_randomness( last_epoch_randomness: schnorrkel::Randomness, epoch_index: u64, - rho: impl Iterator, + rho: impl Iterator, rho_size_hint: Option, ) -> schnorrkel::Randomness { let mut s = Vec::with_capacity(40 + rho_size_hint.unwrap_or(0) * VRF_OUTPUT_LENGTH); diff --git a/frame/babe/src/mock.rs b/frame/babe/src/mock.rs index ea802b268e399c6f71577507df49b60288e880f5..8a0356d8da7e8596dec5b155522fd0f7b5e78a43 100644 --- a/frame/babe/src/mock.rs +++ b/frame/babe/src/mock.rs @@ -1,40 +1,52 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utilities use codec::Encode; -use super::{Trait, Module, GenesisConfig, CurrentSlot}; +use super::{Trait, Module, CurrentSlot}; use sp_runtime::{ Perbill, impl_opaque_keys, - testing::{Header, UintAuthorityId, Digest, DigestItem}, - traits::IdentityLookup, + curve::PiecewiseLinear, + testing::{Digest, DigestItem, Header, TestXt,}, + traits::{Convert, Header as _, IdentityLookup, OpaqueKeys, SaturatedConversion}, }; use frame_system::InitKind; use frame_support::{ - impl_outer_origin, parameter_types, StorageValue, - traits::OnInitialize, + impl_outer_dispatch, impl_outer_origin, parameter_types, StorageValue, + traits::{KeyOwnerProofSystem, OnInitialize}, weights::Weight, }; use sp_io; -use sp_core::H256; -use sp_consensus_vrf::schnorrkel::{RawVRFOutput, RawVRFProof}; +use sp_core::{H256, U256, crypto::{KeyTypeId, Pair}}; +use sp_consensus_babe::{AuthorityId, AuthorityPair, SlotNumber}; +use sp_consensus_vrf::schnorrkel::{VRFOutput, VRFProof}; +use sp_staking::SessionIndex; +use pallet_staking::EraIndex; impl_outer_origin!{ - pub enum Origin for Test where system = frame_system {} + pub enum Origin for Test where system = frame_system {} +} + +impl_outer_dispatch! { + pub enum Call for Test where origin: Origin { + babe::Babe, + staking::Staking, + } } type DummyValidatorId = u64; @@ -48,17 +60,17 @@ parameter_types! { pub const MaximumBlockWeight: Weight = 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 DisabledValidatorsThreshold: Perbill = Perbill::from_percent(16); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; - type Call = (); + type Call = Call; type Hash = H256; type Version = (); type Hashing = sp_runtime::traits::BlakeTwo256; @@ -68,61 +80,212 @@ impl frame_system::Trait for Test { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type ModuleToIndex = (); - type AccountData = (); + type AccountData = pallet_balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); +} + +impl frame_system::offchain::SendTransactionTypes for Test +where + Call: From, +{ + type OverarchingCall = Call; + type Extrinsic = TestXt; } impl_opaque_keys! { pub struct MockSessionKeys { - pub dummy: UintAuthorityId, + pub babe_authority: super::Module, } } impl pallet_session::Trait for Test { type Event = (); type ValidatorId = ::AccountId; + type ValidatorIdOf = pallet_staking::StashOf; type ShouldEndSession = Babe; - type SessionHandler = (Babe,); - type SessionManager = (); - type ValidatorIdOf = (); + type NextSessionRotation = Babe; + type SessionManager = pallet_session::historical::NoteHistoricalRoot; + type SessionHandler = ::KeyTypeIdProviders; type Keys = MockSessionKeys; type DisabledValidatorsThreshold = DisabledValidatorsThreshold; - type NextSessionRotation = Babe; + type WeightInfo = (); +} + +impl pallet_session::historical::Trait for Test { + type FullIdentification = pallet_staking::Exposure; + type FullIdentificationOf = pallet_staking::ExposureOf; +} + +parameter_types! { + pub const UncleGenerations: u64 = 0; +} + +impl pallet_authorship::Trait for Test { + type FindAuthor = pallet_session::FindAccountFromAuthorIndex; + type UncleGenerations = UncleGenerations; + type FilterUncle = (); + type EventHandler = (); +} + +parameter_types! { + pub const MinimumPeriod: u64 = 1; } impl pallet_timestamp::Trait for Test { type Moment = u64; type OnTimestampSet = Babe; type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); +} + +parameter_types! { + pub const ExistentialDeposit: u128 = 1; +} + +impl pallet_balances::Trait for Test { + type Balance = u128; + type DustRemoval = (); + type Event = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); +} + +pallet_staking_reward_curve::build! { + const REWARD_CURVE: PiecewiseLinear<'static> = curve!( + min_inflation: 0_025_000u64, + 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: SessionIndex = 3; + pub const BondingDuration: EraIndex = 3; + pub const SlashDeferDuration: EraIndex = 0; + pub const AttestationPeriod: u64 = 100; + pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE; + pub const MaxNominatorRewardedPerValidator: u32 = 64; + pub const ElectionLookahead: u64 = 0; + pub const StakingUnsignedPriority: u64 = u64::max_value() / 2; +} + +pub struct CurrencyToVoteHandler; + +impl Convert for CurrencyToVoteHandler { + fn convert(x: u128) -> u128 { + x + } +} + +impl Convert for CurrencyToVoteHandler { + fn convert(x: u128) -> u64 { + x.saturated_into() + } +} + +impl pallet_staking::Trait for Test { + type RewardRemainder = (); + type CurrencyToVote = CurrencyToVoteHandler; + type Event = (); + type Currency = Balances; + type Slash = (); + type Reward = (); + type SessionsPerEra = SessionsPerEra; + type BondingDuration = BondingDuration; + type SlashDeferDuration = SlashDeferDuration; + type SlashCancelOrigin = frame_system::EnsureRoot; + type SessionInterface = Self; + type UnixTime = pallet_timestamp::Module; + type RewardCurve = RewardCurve; + type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; + type NextNewSession = Session; + type ElectionLookahead = ElectionLookahead; + type Call = Call; + type UnsignedPriority = StakingUnsignedPriority; + type MaxIterations = (); + type MinSolutionScoreBump = (); + type WeightInfo = (); +} + +parameter_types! { + pub OffencesWeightSoftLimit: Weight = Perbill::from_percent(60) * MaximumBlockWeight::get(); +} + +impl pallet_offences::Trait for Test { + type Event = (); + type IdentificationTuple = pallet_session::historical::IdentificationTuple; + type OnOffenceHandler = Staking; + type WeightSoftLimit = OffencesWeightSoftLimit; + type WeightInfo = (); } impl Trait for Test { type EpochDuration = EpochDuration; type ExpectedBlockTime = ExpectedBlockTime; type EpochChangeTrigger = crate::ExternalTrigger; -} -pub fn new_test_ext(authorities: Vec) -> sp_io::TestExternalities { - let mut t = frame_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() + type KeyOwnerProofSystem = Historical; + + type KeyOwnerProof = + >::Proof; + + type KeyOwnerIdentification = >::IdentificationTuple; + + type HandleEquivocation = super::EquivocationHandler; } +pub type Balances = pallet_balances::Module; +pub type Historical = pallet_session::historical::Module; +pub type Offences = pallet_offences::Module; +pub type Session = pallet_session::Module; +pub type Staking = pallet_staking::Module; +pub type System = frame_system::Module; +pub type Timestamp = pallet_timestamp::Module; +pub type Babe = Module; + pub fn go_to_block(n: u64, s: u64) { - let pre_digest = make_pre_digest(0, s, RawVRFOutput([1; 32]), RawVRFProof([0xff; 64])); - System::initialize(&n, &Default::default(), &Default::default(), &pre_digest, InitKind::Full); + use frame_support::traits::OnFinalize; + + System::on_finalize(System::block_number()); + Session::on_finalize(System::block_number()); + Staking::on_finalize(System::block_number()); + + let parent_hash = if System::block_number() > 1 { + let hdr = System::finalize(); + hdr.hash() + } else { + System::parent_hash() + }; + + let pre_digest = make_secondary_plain_pre_digest(0, s); + + System::initialize(&n, &parent_hash, &Default::default(), &pre_digest, InitKind::Full); System::set_block_number(n); + Timestamp::set_timestamp(n); + if s > 1 { CurrentSlot::put(s); } - // includes a call into `Babe::do_initialize`. + + System::on_initialize(n); Session::on_initialize(n); + Staking::on_initialize(n); } /// Slots will grow accordingly to blocks @@ -134,14 +297,27 @@ pub fn progress_to_block(n: u64) { } } +/// Progress to the first block at the given session +pub fn start_session(session_index: SessionIndex) { + let missing = (session_index - Session::current_index()) * 3; + progress_to_block(System::block_number() + missing as u64 + 1); + assert_eq!(Session::current_index(), session_index); +} + +/// Progress to the first block at the given era +pub fn start_era(era_index: EraIndex) { + start_session((era_index * 3).into()); + assert_eq!(Staking::current_era(), Some(era_index)); +} + pub fn make_pre_digest( authority_index: sp_consensus_babe::AuthorityIndex, slot_number: sp_consensus_babe::SlotNumber, - vrf_output: RawVRFOutput, - vrf_proof: RawVRFProof, + vrf_output: VRFOutput, + vrf_proof: VRFProof, ) -> Digest { - let digest_data = sp_consensus_babe::digests::RawPreDigest::Primary( - sp_consensus_babe::digests::RawPrimaryPreDigest { + let digest_data = sp_consensus_babe::digests::PreDigest::Primary( + sp_consensus_babe::digests::PrimaryPreDigest { authority_index, slot_number, vrf_output, @@ -152,6 +328,138 @@ pub fn make_pre_digest( Digest { logs: vec![log] } } -pub type System = frame_system::Module; -pub type Babe = Module; -pub type Session = pallet_session::Module; +pub fn make_secondary_plain_pre_digest( + authority_index: sp_consensus_babe::AuthorityIndex, + slot_number: sp_consensus_babe::SlotNumber, +) -> Digest { + let digest_data = sp_consensus_babe::digests::PreDigest::SecondaryPlain( + sp_consensus_babe::digests::SecondaryPlainPreDigest { + authority_index, + slot_number, + } + ); + let log = DigestItem::PreRuntime(sp_consensus_babe::BABE_ENGINE_ID, digest_data.encode()); + Digest { logs: vec![log] } +} + +pub fn new_test_ext(authorities_len: usize) -> sp_io::TestExternalities { + new_test_ext_with_pairs(authorities_len).1 +} + +pub fn new_test_ext_with_pairs(authorities_len: usize) -> (Vec, sp_io::TestExternalities) { + let pairs = (0..authorities_len).map(|i| { + AuthorityPair::from_seed(&U256::from(i).into()) + }).collect::>(); + + let public = pairs.iter().map(|p| p.public()).collect(); + + (pairs, new_test_ext_raw_authorities(public)) +} + +pub fn new_test_ext_raw_authorities(authorities: Vec) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default() + .build_storage::() + .unwrap(); + + // stashes are the index. + let session_keys: Vec<_> = authorities + .iter() + .enumerate() + .map(|(i, k)| { + ( + i as u64, + i as u64, + MockSessionKeys { + babe_authority: AuthorityId::from(k.clone()), + }, + ) + }) + .collect(); + + // controllers are the index + 1000 + let stakers: Vec<_> = (0..authorities.len()) + .map(|i| { + ( + i as u64, + i as u64 + 1000, + 10_000, + pallet_staking::StakerStatus::::Validator, + ) + }) + .collect(); + + let balances: Vec<_> = (0..authorities.len()) + .map(|i| (i as u64, 10_000_000)) + .collect(); + + // NOTE: this will initialize the babe authorities + // through OneSessionHandler::on_genesis_session + pallet_session::GenesisConfig:: { keys: session_keys } + .assimilate_storage(&mut t) + .unwrap(); + + pallet_balances::GenesisConfig:: { balances } + .assimilate_storage(&mut t) + .unwrap(); + + let staking_config = pallet_staking::GenesisConfig:: { + stakers, + validator_count: 8, + force_era: pallet_staking::Forcing::ForceNew, + minimum_validator_count: 0, + invulnerables: vec![], + ..Default::default() + }; + + staking_config.assimilate_storage(&mut t).unwrap(); + + t.into() +} + +/// Creates an equivocation at the current block, by generating two headers. +pub fn generate_equivocation_proof( + offender_authority_index: u32, + offender_authority_pair: &AuthorityPair, + slot_number: SlotNumber, +) -> sp_consensus_babe::EquivocationProof
{ + use sp_consensus_babe::digests::CompatibleDigestItem; + + let current_block = System::block_number(); + let current_slot = CurrentSlot::get(); + + let make_header = || { + let parent_hash = System::parent_hash(); + let pre_digest = make_secondary_plain_pre_digest(offender_authority_index, slot_number); + System::initialize(¤t_block, &parent_hash, &Default::default(), &pre_digest, InitKind::Full); + System::set_block_number(current_block); + Timestamp::set_timestamp(current_block); + System::finalize() + }; + + // sign the header prehash and sign it, adding it to the block as the seal + // digest item + let seal_header = |header: &mut Header| { + let prehash = header.hash(); + let seal = ::babe_seal( + offender_authority_pair.sign(prehash.as_ref()), + ); + header.digest_mut().push(seal); + }; + + // generate two headers at the current block + let mut h1 = make_header(); + let mut h2 = make_header(); + + seal_header(&mut h1); + seal_header(&mut h2); + + // restore previous runtime state + go_to_block(current_block, current_slot); + + sp_consensus_babe::EquivocationProof { + slot_number, + offender: offender_authority_pair.public(), + first_header: h1, + second_header: h2, + } +} diff --git a/frame/babe/src/tests.rs b/frame/babe/src/tests.rs index 24aba100178e058112600873602218581613c3b3..bdd6748c3b3516c33c3b3db1420a5cda7b07f1bc 100644 --- a/frame/babe/src/tests.rs +++ b/frame/babe/src/tests.rs @@ -1,26 +1,32 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Consensus extension module tests for BABE consensus. -use super::*; +use super::{Call, *}; +use frame_support::{ + assert_err, assert_ok, + traits::{Currency, OnFinalize}, +}; use mock::*; -use frame_support::traits::OnFinalize; use pallet_session::ShouldEndSession; -use sp_consensus_vrf::schnorrkel::{RawVRFOutput, RawVRFProof}; +use sp_consensus_babe::AllowedSlots; +use sp_consensus_vrf::schnorrkel::{VRFOutput, VRFProof}; +use sp_core::crypto::{IsWrappedBy, Pair}; const EMPTY_RANDOMNESS: [u8; 32] = [ 74, 25, 49, 128, 53, 97, 244, 49, @@ -37,14 +43,14 @@ fn empty_randomness_is_correct() { #[test] fn initial_values() { - new_test_ext(vec![0, 1, 2, 3]).execute_with(|| { + new_test_ext(4).execute_with(|| { assert_eq!(Babe::authorities().len(), 4) }) } #[test] fn check_module() { - new_test_ext(vec![0, 1, 2, 3]).execute_with(|| { + new_test_ext(4).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"); @@ -53,14 +59,29 @@ fn check_module() { #[test] fn first_block_epoch_zero_start() { - new_test_ext(vec![0, 1, 2, 3]).execute_with(|| { + let (pairs, mut ext) = new_test_ext_with_pairs(4); + + ext.execute_with(|| { let genesis_slot = 100; - let first_vrf = RawVRFOutput([1; 32]); + + let pair = sp_core::sr25519::Pair::from_ref(&pairs[0]).as_ref(); + let transcript = sp_consensus_babe::make_transcript( + &Babe::randomness(), + genesis_slot, + 0, + ); + let vrf_inout = pair.vrf_sign(transcript); + let vrf_randomness: sp_consensus_vrf::schnorrkel::Randomness = vrf_inout.0 + .make_bytes::<[u8; 32]>(&sp_consensus_babe::BABE_VRF_INOUT_CONTEXT); + let vrf_output = VRFOutput(vrf_inout.0.to_output()); + let vrf_proof = VRFProof(vrf_inout.1); + + let first_vrf = vrf_output; let pre_digest = make_pre_digest( 0, genesis_slot, first_vrf.clone(), - RawVRFProof([0xff; 64]), + vrf_proof, ); assert_eq!(Babe::genesis_slot(), 0); @@ -83,7 +104,7 @@ fn first_block_epoch_zero_start() { let header = System::finalize(); assert_eq!(SegmentIndex::get(), 0); - assert_eq!(UnderConstruction::get(0), vec![first_vrf]); + assert_eq!(UnderConstruction::get(0), vec![vrf_randomness]); assert_eq!(Babe::randomness(), [0; 32]); assert_eq!(NextRandomness::get(), [0; 32]); @@ -91,10 +112,9 @@ fn first_block_epoch_zero_start() { assert_eq!(pre_digest.logs.len(), 1); assert_eq!(header.digest.logs[0], pre_digest.logs[0]); - let authorities = Babe::authorities(); let consensus_log = sp_consensus_babe::ConsensusLog::NextEpochData( sp_consensus_babe::digests::NextEpochDescriptor { - authorities, + authorities: Babe::authorities(), randomness: Babe::randomness(), } ); @@ -107,7 +127,7 @@ fn first_block_epoch_zero_start() { #[test] fn authority_index() { - new_test_ext(vec![0, 1, 2, 3]).execute_with(|| { + new_test_ext(4).execute_with(|| { assert_eq!( Babe::find_author((&[(BABE_ENGINE_ID, &[][..])]).into_iter().cloned()), None, "Trivially invalid authorities are ignored") @@ -116,7 +136,7 @@ fn authority_index() { #[test] fn can_predict_next_epoch_change() { - new_test_ext(vec![]).execute_with(|| { + new_test_ext(1).execute_with(|| { assert_eq!(::EpochDuration::get(), 3); // this sets the genesis slot to 6; go_to_block(1, 6); @@ -134,3 +154,434 @@ fn can_predict_next_epoch_change() { assert_eq!(Babe::next_expected_epoch_change(System::block_number()), Some(5 + 2)); }) } + +#[test] +fn can_enact_next_config() { + new_test_ext(1).execute_with(|| { + assert_eq!(::EpochDuration::get(), 3); + // this sets the genesis slot to 6; + go_to_block(1, 6); + assert_eq!(Babe::genesis_slot(), 6); + assert_eq!(Babe::current_slot(), 6); + assert_eq!(Babe::epoch_index(), 0); + go_to_block(2, 7); + + Babe::plan_config_change(NextConfigDescriptor::V1 { + c: (1, 4), + allowed_slots: AllowedSlots::PrimarySlots, + }); + + progress_to_block(4); + Babe::on_finalize(9); + let header = System::finalize(); + + let consensus_log = sp_consensus_babe::ConsensusLog::NextConfigData( + sp_consensus_babe::digests::NextConfigDescriptor::V1 { + c: (1, 4), + allowed_slots: AllowedSlots::PrimarySlots, + } + ); + let consensus_digest = DigestItem::Consensus(BABE_ENGINE_ID, consensus_log.encode()); + + assert_eq!(header.digest.logs[2], consensus_digest.clone()) + }); +} + +#[test] +fn report_equivocation_current_session_works() { + let (pairs, mut ext) = new_test_ext_with_pairs(3); + + ext.execute_with(|| { + start_era(1); + + let authorities = Babe::authorities(); + let validators = Session::validators(); + + // make sure that all authorities have the same balance + for validator in &validators { + assert_eq!(Balances::total_balance(validator), 10_000_000); + assert_eq!(Staking::slashable_balance_of(validator), 10_000); + + assert_eq!( + Staking::eras_stakers(1, validator), + pallet_staking::Exposure { + total: 10_000, + own: 10_000, + others: vec![], + }, + ); + } + + // we will use the validator at index 0 as the offending authority + let offending_validator_index = 0; + let offending_validator_id = Session::validators()[offending_validator_index]; + let offending_authority_pair = pairs + .into_iter() + .find(|p| p.public() == authorities[offending_validator_index].0) + .unwrap(); + + // generate an equivocation proof. it creates two headers at the given + // slot with different block hashes and signed by the given key + let equivocation_proof = generate_equivocation_proof( + offending_validator_index as u32, + &offending_authority_pair, + CurrentSlot::get(), + ); + + // create the key ownership proof + let key = ( + sp_consensus_babe::KEY_TYPE, + &offending_authority_pair.public(), + ); + let key_owner_proof = Historical::prove(key).unwrap(); + + // report the equivocation + Babe::report_equivocation_unsigned(Origin::none(), equivocation_proof, key_owner_proof) + .unwrap(); + + // start a new era so that the results of the offence report + // are applied at era end + start_era(2); + + // check that the balance of offending validator is slashed 100%. + assert_eq!( + Balances::total_balance(&offending_validator_id), + 10_000_000 - 10_000 + ); + assert_eq!(Staking::slashable_balance_of(&offending_validator_id), 0); + assert_eq!( + Staking::eras_stakers(2, offending_validator_id), + pallet_staking::Exposure { + total: 0, + own: 0, + others: vec![], + }, + ); + + // check that the balances of all other validators are left intact. + for validator in &validators { + if *validator == offending_validator_id { + continue; + } + + assert_eq!(Balances::total_balance(validator), 10_000_000); + assert_eq!(Staking::slashable_balance_of(validator), 10_000); + assert_eq!( + Staking::eras_stakers(2, validator), + pallet_staking::Exposure { + total: 10_000, + own: 10_000, + others: vec![], + }, + ); + } + }) +} + +#[test] +fn report_equivocation_old_session_works() { + let (pairs, mut ext) = new_test_ext_with_pairs(3); + + ext.execute_with(|| { + start_era(1); + + let authorities = Babe::authorities(); + + // we will use the validator at index 0 as the offending authority + let offending_validator_index = 0; + let offending_validator_id = Session::validators()[offending_validator_index]; + let offending_authority_pair = pairs + .into_iter() + .find(|p| p.public() == authorities[offending_validator_index].0) + .unwrap(); + + // generate an equivocation proof at the current slot + let equivocation_proof = generate_equivocation_proof( + offending_validator_index as u32, + &offending_authority_pair, + CurrentSlot::get(), + ); + + // create the key ownership proof + let key = ( + sp_consensus_babe::KEY_TYPE, + &offending_authority_pair.public(), + ); + let key_owner_proof = Historical::prove(key).unwrap(); + + // start a new era and report the equivocation + // from the previous era + start_era(2); + + // check the balance of the offending validator + assert_eq!(Balances::total_balance(&offending_validator_id), 10_000_000); + assert_eq!( + Staking::slashable_balance_of(&offending_validator_id), + 10_000 + ); + + // report the equivocation + Babe::report_equivocation_unsigned(Origin::none(), equivocation_proof, key_owner_proof) + .unwrap(); + + // start a new era so that the results of the offence report + // are applied at era end + start_era(3); + + // check that the balance of offending validator is slashed 100%. + assert_eq!( + Balances::total_balance(&offending_validator_id), + 10_000_000 - 10_000 + ); + assert_eq!(Staking::slashable_balance_of(&offending_validator_id), 0); + assert_eq!( + Staking::eras_stakers(3, offending_validator_id), + pallet_staking::Exposure { + total: 0, + own: 0, + others: vec![], + }, + ); + }) +} + +#[test] +fn report_equivocation_invalid_key_owner_proof() { + let (pairs, mut ext) = new_test_ext_with_pairs(3); + + ext.execute_with(|| { + start_era(1); + + let authorities = Babe::authorities(); + + // we will use the validator at index 0 as the offending authority + let offending_validator_index = 0; + let offending_authority_pair = pairs + .into_iter() + .find(|p| p.public() == authorities[offending_validator_index].0) + .unwrap(); + + // generate an equivocation proof at the current slot + let equivocation_proof = generate_equivocation_proof( + offending_validator_index as u32, + &offending_authority_pair, + CurrentSlot::get(), + ); + + // create the key ownership proof + let key = ( + sp_consensus_babe::KEY_TYPE, + &offending_authority_pair.public(), + ); + let mut key_owner_proof = Historical::prove(key).unwrap(); + + // we change the session index in the key ownership proof + // which should make it invalid + key_owner_proof.session = 0; + assert_err!( + Babe::report_equivocation_unsigned( + Origin::none(), + equivocation_proof.clone(), + key_owner_proof + ), + Error::::InvalidKeyOwnershipProof, + ); + + // it should fail as well if we create a key owner proof + // for a different authority than the offender + let key = (sp_consensus_babe::KEY_TYPE, &authorities[1].0); + let key_owner_proof = Historical::prove(key).unwrap(); + + // we need to progress to a new era to make sure that the key + // ownership proof is properly checked, otherwise since the state + // is still available the historical module will just check + // against current session data. + start_era(2); + + assert_err!( + Babe::report_equivocation_unsigned(Origin::none(), equivocation_proof, key_owner_proof), + Error::::InvalidKeyOwnershipProof, + ); + }) +} + +#[test] +fn report_equivocation_invalid_equivocation_proof() { + use sp_runtime::traits::Header; + + let (pairs, mut ext) = new_test_ext_with_pairs(3); + + ext.execute_with(|| { + start_era(1); + + let authorities = Babe::authorities(); + + // we will use the validator at index 0 as the offending authority + let offending_validator_index = 0; + let offending_authority_pair = pairs + .into_iter() + .find(|p| p.public() == authorities[offending_validator_index].0) + .unwrap(); + + // create the key ownership proof + let key = ( + sp_consensus_babe::KEY_TYPE, + &offending_authority_pair.public(), + ); + let key_owner_proof = Historical::prove(key).unwrap(); + + let assert_invalid_equivocation = |equivocation_proof| { + assert_err!( + Babe::report_equivocation_unsigned( + Origin::none(), + equivocation_proof, + key_owner_proof.clone(), + ), + Error::::InvalidEquivocationProof, + ) + }; + + // both headers have the same hash, no equivocation. + let mut equivocation_proof = generate_equivocation_proof( + offending_validator_index as u32, + &offending_authority_pair, + CurrentSlot::get(), + ); + equivocation_proof.second_header = equivocation_proof.first_header.clone(); + assert_invalid_equivocation(equivocation_proof); + + // missing preruntime digest from one header + let mut equivocation_proof = generate_equivocation_proof( + offending_validator_index as u32, + &offending_authority_pair, + CurrentSlot::get(), + ); + equivocation_proof.first_header.digest_mut().logs.remove(0); + assert_invalid_equivocation(equivocation_proof); + + // missing seal from one header + let mut equivocation_proof = generate_equivocation_proof( + offending_validator_index as u32, + &offending_authority_pair, + CurrentSlot::get(), + ); + equivocation_proof.first_header.digest_mut().logs.remove(1); + assert_invalid_equivocation(equivocation_proof); + + // invalid slot number in proof compared to runtime digest + let mut equivocation_proof = generate_equivocation_proof( + offending_validator_index as u32, + &offending_authority_pair, + CurrentSlot::get(), + ); + equivocation_proof.slot_number = 0; + assert_invalid_equivocation(equivocation_proof.clone()); + + // different slot numbers in headers + let h1 = equivocation_proof.first_header; + let mut equivocation_proof = generate_equivocation_proof( + offending_validator_index as u32, + &offending_authority_pair, + CurrentSlot::get() + 1, + ); + + // use the header from the previous equivocation generated + // at the previous slot + equivocation_proof.first_header = h1.clone(); + + assert_invalid_equivocation(equivocation_proof.clone()); + + // invalid seal signature + let mut equivocation_proof = generate_equivocation_proof( + offending_validator_index as u32, + &offending_authority_pair, + CurrentSlot::get() + 1, + ); + + // replace the seal digest with the digest from the + // previous header at the previous slot + equivocation_proof.first_header.digest_mut().pop(); + equivocation_proof + .first_header + .digest_mut() + .push(h1.digest().logs().last().unwrap().clone()); + + assert_invalid_equivocation(equivocation_proof.clone()); + }) +} + +#[test] +fn report_equivocation_validate_unsigned_prevents_duplicates() { + use sp_runtime::transaction_validity::{ + InvalidTransaction, TransactionLongevity, TransactionPriority, TransactionSource, + TransactionValidity, ValidTransaction, + }; + + let (pairs, mut ext) = new_test_ext_with_pairs(3); + + ext.execute_with(|| { + start_era(1); + + let authorities = Babe::authorities(); + + // generate and report an equivocation for the validator at index 0 + let offending_validator_index = 0; + let offending_authority_pair = pairs + .into_iter() + .find(|p| p.public() == authorities[offending_validator_index].0) + .unwrap(); + + let equivocation_proof = generate_equivocation_proof( + offending_validator_index as u32, + &offending_authority_pair, + CurrentSlot::get(), + ); + + let key = ( + sp_consensus_babe::KEY_TYPE, + &offending_authority_pair.public(), + ); + let key_owner_proof = Historical::prove(key).unwrap(); + + let inner = + Call::report_equivocation_unsigned(equivocation_proof.clone(), key_owner_proof.clone()); + + // only local/inblock reports are allowed + assert_eq!( + ::validate_unsigned( + TransactionSource::External, + &inner, + ), + InvalidTransaction::Call.into(), + ); + + // the transaction is valid when passed as local + let tx_tag = (offending_authority_pair.public(), CurrentSlot::get()); + assert_eq!( + ::validate_unsigned( + TransactionSource::Local, + &inner, + ), + TransactionValidity::Ok(ValidTransaction { + priority: TransactionPriority::max_value(), + requires: vec![], + provides: vec![("BabeEquivocation", tx_tag).encode()], + longevity: TransactionLongevity::max_value(), + propagate: false, + }) + ); + + // the pre dispatch checks should also pass + assert_ok!(::pre_dispatch(&inner)); + + // we submit the report + Babe::report_equivocation_unsigned(Origin::none(), equivocation_proof, key_owner_proof) + .unwrap(); + + // the report should now be considered stale and the transaction is invalid + assert_err!( + ::pre_dispatch(&inner), + InvalidTransaction::Stale, + ); + }); +} diff --git a/frame/balances/Cargo.toml b/frame/balances/Cargo.toml index f8a59ad15476fbd0c4f69fc418c17c67be3a7506..88c8657d4744b28f739408cfab74dfed8c63e0d3 100644 --- a/frame/balances/Cargo.toml +++ b/frame/balances/Cargo.toml @@ -1,26 +1,29 @@ [package] name = "pallet-balances" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet to manage balances" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -frame-benchmarking = { version = "2.0.0-alpha.5", default-features = false, path = "../benchmarking", optional = true } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +frame-benchmarking = { version = "2.0.0-rc4", default-features = false, path = "../benchmarking", optional = true } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -pallet-transaction-payment = { version = "2.0.0-alpha.5", path = "../transaction-payment" } +sp-io = { version = "2.0.0-rc4", path = "../../primitives/io" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +pallet-transaction-payment = { version = "2.0.0-rc4", path = "../transaction-payment" } [features] default = ["std"] @@ -28,13 +31,9 @@ std = [ "serde", "codec/std", "sp-std/std", - "sp-io/std", "sp-runtime/std", "frame-benchmarking/std", "frame-support/std", "frame-system/std", ] runtime-benchmarks = ["frame-benchmarking"] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/balances/src/benchmarking.rs b/frame/balances/src/benchmarking.rs index 161fdab96b934a5bf234604406c554b261fb7907..a5f8e6fe36cd48190f964348e68580a185cd28d0 100644 --- a/frame/balances/src/benchmarking.rs +++ b/frame/balances/src/benchmarking.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Balances pallet benchmarking. @@ -51,10 +52,13 @@ benchmarks! { let _ = as Currency<_>>::make_free_balance_be(&caller, balance); // Transfer `e - 1` existential deposits + 1 unit, which guarantees to create one account, and reap this user. - let recipient = account("recipient", u, SEED); - let recipient_lookup: ::Source = T::Lookup::unlookup(recipient); + let recipient: T::AccountId = account("recipient", u, SEED); + let recipient_lookup: ::Source = T::Lookup::unlookup(recipient.clone()); let transfer_amount = existential_deposit.saturating_mul((e - 1).into()) + 1.into(); }: _(RawOrigin::Signed(caller), recipient_lookup, transfer_amount) + verify { + assert_eq!(Balances::::free_balance(&recipient), transfer_amount); + } // Benchmark `transfer` with the best possible condition: // * Both accounts exist and will continue to exist. @@ -119,3 +123,45 @@ benchmarks! { let _ = as Currency<_>>::make_free_balance_be(&user, balance_amount); }: set_balance(RawOrigin::Root, user_lookup, 0.into(), 0.into()) } + +#[cfg(test)] +mod tests { + use super::*; + use crate::tests_composite::{ExtBuilder, Test}; + use frame_support::assert_ok; + + #[test] + fn transfer() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(test_benchmark_transfer::()); + }); + } + + #[test] + fn transfer_best_case() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(test_benchmark_transfer_best_case::()); + }); + } + + #[test] + fn transfer_keep_alive() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(test_benchmark_transfer_keep_alive::()); + }); + } + + #[test] + fn transfer_set_balance() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(test_benchmark_set_balance::()); + }); + } + + #[test] + fn transfer_set_balance_killing() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(test_benchmark_set_balance_killing::()); + }); + } +} diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index 39e15b3f4f585d38b3d68752b1803782ae0b3619..fefe054b6d580fe019d8ee1f4042668161970b5b 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Balances Module //! @@ -159,7 +160,8 @@ use sp_std::{cmp, result, mem, fmt::Debug, ops::BitOr, convert::Infallible}; use codec::{Codec, Encode, Decode}; use frame_support::{ StorageValue, Parameter, decl_event, decl_storage, decl_module, decl_error, ensure, - weights::SimpleDispatchInfo, traits::{ + weights::Weight, + traits::{ Currency, OnKilledAccount, OnUnbalanced, TryDrop, StoredMap, WithdrawReason, WithdrawReasons, LockIdentifier, LockableCurrency, ExistenceRequirement, Imbalance, SignedImbalance, ReservableCurrency, Get, ExistenceRequirement::KeepAlive, @@ -169,7 +171,7 @@ use frame_support::{ use sp_runtime::{ RuntimeDebug, DispatchResult, DispatchError, traits::{ - Zero, AtLeast32Bit, StaticLookup, Member, CheckedAdd, CheckedSub, + Zero, AtLeast32BitUnsigned, StaticLookup, Member, CheckedAdd, CheckedSub, MaybeSerializeDeserialize, Saturating, Bounded, }, }; @@ -177,9 +179,25 @@ use frame_system::{self as system, ensure_signed, ensure_root}; pub use self::imbalances::{PositiveImbalance, NegativeImbalance}; +pub trait WeightInfo { + fn transfer(u: u32, e: u32, ) -> Weight; + fn transfer_best_case(u: u32, e: u32, ) -> Weight; + fn transfer_keep_alive(u: u32, e: u32, ) -> Weight; + fn set_balance(u: u32, e: u32, ) -> Weight; + fn set_balance_killing(u: u32, e: u32, ) -> Weight; +} + +impl WeightInfo for () { + fn transfer(_u: u32, _e: u32, ) -> Weight { 1_000_000_000 } + fn transfer_best_case(_u: u32, _e: u32, ) -> Weight { 1_000_000_000 } + fn transfer_keep_alive(_u: u32, _e: u32, ) -> Weight { 1_000_000_000 } + fn set_balance(_u: u32, _e: u32, ) -> Weight { 1_000_000_000 } + fn set_balance_killing(_u: u32, _e: u32, ) -> Weight { 1_000_000_000 } +} + pub trait Subtrait: frame_system::Trait { /// The balance of an account. - type Balance: Parameter + Member + AtLeast32Bit + Codec + Default + Copy + + type Balance: Parameter + Member + AtLeast32BitUnsigned + Codec + Default + Copy + MaybeSerializeDeserialize + Debug; /// The minimum amount required to keep an account open. @@ -187,11 +205,14 @@ pub trait Subtrait: frame_system::Trait { /// The means of storing the balances of an account. type AccountStore: StoredMap>; + + /// Weight information for the extrinsics in this pallet. + type WeightInfo: WeightInfo; } pub trait Trait: frame_system::Trait { /// The balance of an account. - type Balance: Parameter + Member + AtLeast32Bit + Codec + Default + Copy + + type Balance: Parameter + Member + AtLeast32BitUnsigned + Codec + Default + Copy + MaybeSerializeDeserialize + Debug; /// Handler for the unbalanced reduction when removing a dust account. @@ -205,12 +226,16 @@ pub trait Trait: frame_system::Trait { /// The means of storing the balances of an account. type AccountStore: StoredMap>; + + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; } impl, I: Instance> Subtrait for T { type Balance = T::Balance; type ExistentialDeposit = T::ExistentialDeposit; type AccountStore = T::AccountStore; + type WeightInfo = >::WeightInfo; } decl_event!( @@ -229,6 +254,13 @@ decl_event!( BalanceSet(AccountId, Balance, Balance), /// Some amount was deposited (e.g. for transaction fees). Deposit(AccountId, Balance), + /// Some balance was reserved (moved from free to reserved). + Reserved(AccountId, Balance), + /// Some balance was unreserved (moved from reserved to free). + Unreserved(AccountId, Balance), + /// Some balance was moved from the reserve of the first account to the second account. + /// Final argument indicates the destination balance type. + ReserveRepatriated(AccountId, AccountId, Balance, Status), } ); @@ -364,9 +396,6 @@ decl_storage! { /// The balance of an account. /// - /// NOTE: THIS MAY NEVER BE IN EXISTENCE AND YET HAVE A `total().is_zero()`. If the total - /// is ever zero, then the entry *MUST* be removed. - /// /// NOTE: This is only used in the case that this module is used to store balances. pub Account: map hasher(blake2_128_concat) T::AccountId => AccountData; @@ -383,10 +412,6 @@ decl_storage! { config(balances): Vec<(T::AccountId, T::Balance)>; // ^^ begin, length, amount liquid at genesis build(|config: &GenesisConfig| { - assert!( - >::ExistentialDeposit::get() > Zero::zero(), - "The existential deposit should be greater than zero." - ); for (_, balance) in &config.balances { assert!( *balance >= >::ExistentialDeposit::get(), @@ -431,9 +456,12 @@ decl_module! { /// - Removing enough funds from an account will trigger `T::DustRemoval::on_unbalanced`. /// - `transfer_keep_alive` works the same way as `transfer`, but has an additional /// check that the transfer will not kill the origin account. - /// + /// --------------------------------- + /// - Base Weight: 73.64 µs, worst case scenario (account created, account removed) + /// - DB Weight: 1 Read and 1 Write to destination account + /// - Origin account is already in memory, so no DB operations for them. /// # - #[weight = SimpleDispatchInfo::FixedNormal(1_000_000)] + #[weight = T::DbWeight::get().reads_writes(1, 1) + 70_000_000] pub fn transfer( origin, dest: ::Source, @@ -456,8 +484,13 @@ decl_module! { /// # /// - Independent of the arguments. /// - Contains a limited number of reads and writes. + /// --------------------- + /// - Base Weight: + /// - Creating: 27.56 µs + /// - Killing: 35.11 µs + /// - DB Weight: 1 Read, 1 Write to `who` /// # - #[weight = SimpleDispatchInfo::FixedOperational(50_000)] + #[weight = T::DbWeight::get().reads_writes(1, 1) + 35_000_000] fn set_balance( origin, who: ::Source, @@ -495,7 +528,11 @@ decl_module! { /// Exactly as `transfer`, except the origin must be root and the source account may be /// specified. - #[weight = SimpleDispatchInfo::FixedNormal(1_000_000)] + /// # + /// - Same as transfer, but additional read and write because the source account is + /// not assumed to be in the overlay. + /// # + #[weight = T::DbWeight::get().reads_writes(2, 2) + 70_000_000] pub fn force_transfer( origin, source: ::Source, @@ -514,7 +551,12 @@ decl_module! { /// 99% of the time you want [`transfer`] instead. /// /// [`transfer`]: struct.Module.html#method.transfer - #[weight = SimpleDispatchInfo::FixedNormal(1_000_000)] + /// # + /// - Cheaper than transfer because account cannot be killed. + /// - Base Weight: 51.4 µs + /// - DB Weight: 1 Read and 1 Write to dest (sender is in overlay already) + /// # + #[weight = T::DbWeight::get().reads_writes(1, 1) + 50_000_000] pub fn transfer_keep_alive( origin, dest: ::Source, @@ -587,11 +629,11 @@ impl, I: Instance> Module { /// /// NOTE: LOW-LEVEL: This will not attempt to maintain total issuance. It is expected that /// the caller will do this. - fn mutate_account( + pub fn mutate_account( who: &T::AccountId, f: impl FnOnce(&mut AccountData) -> R ) -> R { - Self::try_mutate_account(who, |a| -> Result { Ok(f(a)) }) + Self::try_mutate_account(who, |a, _| -> Result { Ok(f(a)) }) .expect("Error is infallible; qed") } @@ -606,13 +648,13 @@ impl, I: Instance> Module { /// the caller will do this. fn try_mutate_account( who: &T::AccountId, - f: impl FnOnce(&mut AccountData) -> Result + f: impl FnOnce(&mut AccountData, bool) -> Result ) -> Result { T::AccountStore::try_mutate_exists(who, |maybe_account| { + let is_new = maybe_account.is_none(); let mut account = maybe_account.take().unwrap_or_default(); - let was_zero = account.total().is_zero(); - f(&mut account).map(move |result| { - let maybe_endowed = if was_zero { Some(account.free) } else { None }; + f(&mut account, is_new).map(move |result| { + let maybe_endowed = if is_new { Some(account.free) } else { None }; *maybe_account = Self::post_mutation(who, account); (maybe_endowed, result) }) @@ -830,6 +872,7 @@ impl, I: Instance> PartialEq for ElevatedTrait { } impl, I: Instance> Eq for ElevatedTrait {} impl, I: Instance> frame_system::Trait for ElevatedTrait { + type BaseCallFilter = T::BaseCallFilter; type Origin = T::Origin; type Call = T::Call; type Index = T::Index; @@ -842,6 +885,10 @@ impl, I: Instance> frame_system::Trait for ElevatedTrait { type Event = (); type BlockHashCount = T::BlockHashCount; type MaximumBlockWeight = T::MaximumBlockWeight; + type DbWeight = T::DbWeight; + type BlockExecutionWeight = T::BlockExecutionWeight; + type ExtrinsicBaseWeight = T::ExtrinsicBaseWeight; + type MaximumExtrinsicWeight = T::MaximumBlockWeight; type MaximumBlockLength = T::MaximumBlockLength; type AvailableBlockRatio = T::AvailableBlockRatio; type Version = T::Version; @@ -849,6 +896,7 @@ impl, I: Instance> frame_system::Trait for ElevatedTrait { type OnNewAccount = T::OnNewAccount; type OnKilledAccount = T::OnKilledAccount; type AccountData = T::AccountData; + type SystemWeightInfo = T::SystemWeightInfo; } impl, I: Instance> Trait for ElevatedTrait { type Balance = T::Balance; @@ -856,6 +904,7 @@ impl, I: Instance> Trait for ElevatedTrait { type DustRemoval = (); type ExistentialDeposit = T::ExistentialDeposit; type AccountStore = T::AccountStore; + type WeightInfo = >::WeightInfo; } impl, I: Instance> Currency for Module where @@ -944,8 +993,8 @@ impl, I: Instance> Currency for Module where ) -> DispatchResult { if value.is_zero() || transactor == dest { return Ok(()) } - Self::try_mutate_account(dest, |to_account| -> DispatchResult { - Self::try_mutate_account(transactor, |from_account| -> DispatchResult { + Self::try_mutate_account(dest, |to_account, _| -> DispatchResult { + Self::try_mutate_account(transactor, |from_account, _| -> DispatchResult { from_account.free = from_account.free.checked_sub(&value) .ok_or(Error::::InsufficientBalance)?; @@ -1016,8 +1065,8 @@ impl, I: Instance> Currency for Module where ) -> Result { if value.is_zero() { return Ok(PositiveImbalance::zero()) } - Self::try_mutate_account(who, |account| -> Result { - ensure!(!account.total().is_zero(), Error::::DeadAccount); + Self::try_mutate_account(who, |account, is_new| -> Result { + ensure!(!is_new, Error::::DeadAccount); account.free = account.free.checked_add(&value).ok_or(Error::::Overflow)?; Ok(PositiveImbalance::new(value)) }) @@ -1035,10 +1084,10 @@ impl, I: Instance> Currency for Module where ) -> Self::PositiveImbalance { if value.is_zero() { return Self::PositiveImbalance::zero() } - Self::try_mutate_account(who, |account| -> Result { + Self::try_mutate_account(who, |account, is_new| -> Result { // bail if not yet created and this operation wouldn't be enough to create it. let ed = T::ExistentialDeposit::get(); - ensure!(value >= ed || !account.total().is_zero(), Self::PositiveImbalance::zero()); + ensure!(value >= ed || !is_new, Self::PositiveImbalance::zero()); // defensive only: overflow should never happen, however in case it does, then this // operation is a no-op. @@ -1059,7 +1108,7 @@ impl, I: Instance> Currency for Module where ) -> result::Result { if value.is_zero() { return Ok(NegativeImbalance::zero()); } - Self::try_mutate_account(who, |account| + Self::try_mutate_account(who, |account, _| -> Result { let new_free_account = account.free.checked_sub(&value) @@ -1083,7 +1132,7 @@ impl, I: Instance> Currency for Module where fn make_free_balance_be(who: &T::AccountId, value: Self::Balance) -> SignedImbalance { - Self::try_mutate_account(who, |account| + Self::try_mutate_account(who, |account, is_new| -> Result, ()> { let ed = T::ExistentialDeposit::get(); @@ -1094,7 +1143,7 @@ impl, I: Instance> Currency for Module where // equal and opposite cause (returned as an Imbalance), then in the // instance that there's no other accounts on the system at all, we might // underflow the issuance and our arithmetic will be off. - ensure!(value + account.reserved >= ed || !account.total().is_zero(), ()); + ensure!(value.saturating_add(account.reserved) >= ed || !is_new, ()); let imbalance = if account.free <= value { SignedImbalance::Positive(PositiveImbalance::new(value - account.free)) @@ -1132,11 +1181,14 @@ impl, I: Instance> ReservableCurrency for Module fn reserve(who: &T::AccountId, value: Self::Balance) -> DispatchResult { if value.is_zero() { return Ok(()) } - Self::try_mutate_account(who, |account| -> DispatchResult { + Self::try_mutate_account(who, |account, _| -> DispatchResult { account.free = account.free.checked_sub(&value).ok_or(Error::::InsufficientBalance)?; account.reserved = account.reserved.checked_add(&value).ok_or(Error::::Overflow)?; - Self::ensure_can_withdraw(who, value, WithdrawReason::Reserve.into(), account.free) - }) + Self::ensure_can_withdraw(&who, value.clone(), WithdrawReason::Reserve.into(), account.free) + })?; + + Self::deposit_event(RawEvent::Reserved(who.clone(), value)); + Ok(()) } /// Unreserve some funds, returning any amount that was unable to be unreserved. @@ -1145,14 +1197,17 @@ impl, I: Instance> ReservableCurrency for Module fn unreserve(who: &T::AccountId, value: Self::Balance) -> Self::Balance { if value.is_zero() { return Zero::zero() } - Self::mutate_account(who, |account| { + let actual = Self::mutate_account(who, |account| { let actual = cmp::min(account.reserved, value); account.reserved -= actual; // defensive only: this can never fail since total issuance which is at least free+reserved // fits into the same data type. account.free = account.free.saturating_add(actual); - value - actual - }) + actual + }); + + Self::deposit_event(RawEvent::Unreserved(who.clone(), actual.clone())); + value - actual } /// Slash from reserved balance, returning the negative imbalance created, @@ -1193,18 +1248,21 @@ impl, I: Instance> ReservableCurrency for Module }; } - Self::try_mutate_account(beneficiary, |to_account| -> Result { - ensure!(!to_account.total().is_zero(), Error::::DeadAccount); - Self::try_mutate_account(slashed, |from_account| -> Result { + let actual = Self::try_mutate_account(beneficiary, |to_account, is_new|-> Result { + ensure!(!is_new, Error::::DeadAccount); + Self::try_mutate_account(slashed, |from_account, _| -> Result { let actual = cmp::min(from_account.reserved, value); match status { Status::Free => to_account.free = to_account.free.checked_add(&actual).ok_or(Error::::Overflow)?, Status::Reserved => to_account.reserved = to_account.reserved.checked_add(&actual).ok_or(Error::::Overflow)?, } from_account.reserved -= actual; - Ok(value - actual) + Ok(actual) }) - }) + })?; + + Self::deposit_event(RawEvent::ReserveRepatriated(slashed.clone(), beneficiary.clone(), actual, status)); + Ok(value - actual) } } @@ -1215,7 +1273,14 @@ impl, I: Instance> ReservableCurrency for Module /// storage (which is the default in most examples and tests) then there's no need.** impl, I: Instance> OnKilledAccount for Module { fn on_killed_account(who: &T::AccountId) { - Account::::remove(who); + Account::::mutate_exists(who, |account| { + let total = account.as_ref().map(|acc| acc.total()).unwrap_or_default(); + if !total.is_zero() { + T::DustRemoval::on_unbalanced(NegativeImbalance::new(total)); + Self::deposit_event(RawEvent::DustLost(who.clone(), total)); + } + *account = None; + }); } } @@ -1235,12 +1300,9 @@ where ) { if amount.is_zero() || reasons.is_none() { return } let mut new_lock = Some(BalanceLock { id, amount, reasons: reasons.into() }); - let mut locks = Self::locks(who).into_iter().filter_map(|l| - if l.id == id { - new_lock.take() - } else { - Some(l) - }).collect::>(); + let mut locks = Self::locks(who).into_iter() + .filter_map(|l| if l.id == id { new_lock.take() } else { Some(l) }) + .collect::>(); if let Some(lock) = new_lock { locks.push(lock) } @@ -1289,7 +1351,7 @@ impl, I: Instance> IsDeadAccount for Module wher T::Balance: MaybeSerializeDeserialize + Debug { fn is_dead_account(who: &T::AccountId) -> bool { - // this should always be exactly equivalent to `Self::account(who).total().is_zero()` + // this should always be exactly equivalent to `Self::account(who).total().is_zero()` if ExistentialDeposit > 0 !T::AccountStore::is_explicit(who) } } diff --git a/frame/balances/src/tests.rs b/frame/balances/src/tests.rs index 8055c2013eaebc5de75e8d1a1b53c22dd87dc62e..210c75631da6387b8f7386248059ff473f135d06 100644 --- a/frame/balances/src/tests.rs +++ b/frame/balances/src/tests.rs @@ -1,29 +1,44 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Macro for creating the tests for the module. #![cfg(test)] +#[derive(Debug)] +pub struct CallWithDispatchInfo; +impl sp_runtime::traits::Dispatchable for CallWithDispatchInfo { + type Origin = (); + type Trait = (); + type Info = frame_support::weights::DispatchInfo; + type PostInfo = frame_support::weights::PostDispatchInfo; + + fn dispatch(self, _origin: Self::Origin) + -> sp_runtime::DispatchResultWithInfo { + panic!("Do not use dummy implementation for dispatch."); + } +} + #[macro_export] macro_rules! decl_tests { ($test:ty, $ext_builder:ty, $existential_deposit:expr) => { use crate::*; - use sp_runtime::{Fixed64, traits::{SignedExtension, BadOrigin}}; + use sp_runtime::{FixedPointNumber, traits::{SignedExtension, BadOrigin}}; use frame_support::{ assert_noop, assert_ok, assert_err, traits::{ @@ -31,7 +46,7 @@ macro_rules! decl_tests { Currency, ReservableCurrency, ExistenceRequirement::AllowDeath, StoredMap } }; - use pallet_transaction_payment::ChargeTransactionPayment; + use pallet_transaction_payment::{ChargeTransactionPayment, Multiplier}; use frame_system::RawOrigin; const ID_1: LockIdentifier = *b"1 "; @@ -40,11 +55,23 @@ macro_rules! decl_tests { pub type System = frame_system::Module<$test>; pub type Balances = Module<$test>; - pub const CALL: &<$test as frame_system::Trait>::Call = &(); + pub const CALL: &<$test as frame_system::Trait>::Call = &$crate::tests::CallWithDispatchInfo; /// 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, pays_fee: true, ..Default::default() } + DispatchInfo { weight: w, ..Default::default() } + } + + fn events() -> Vec { + let evt = System::events().into_iter().map(|evt| evt.event).collect::>(); + + System::reset_events(); + + evt + } + + fn last_event() -> Event { + system::Module::::events().pop().expect("Event expected").event } #[test] @@ -140,7 +167,7 @@ macro_rules! decl_tests { .monied(true) .build() .execute_with(|| { - pallet_transaction_payment::NextFeeMultiplier::put(Fixed64::from_natural(1)); + pallet_transaction_payment::NextFeeMultiplier::put(Multiplier::saturating_from_integer(1)); Balances::set_lock(ID_1, &1, 10, WithdrawReason::Reserve.into()); assert_noop!( >::transfer(&1, &2, 1, AllowDeath), @@ -148,20 +175,20 @@ macro_rules! decl_tests { ); assert_noop!( >::reserve(&1, 1), - Error::<$test, _>::LiquidityRestrictions + Error::<$test, _>::LiquidityRestrictions, ); assert!( as SignedExtension>::pre_dispatch( ChargeTransactionPayment::from(1), &1, CALL, - info_from_weight(1), + &info_from_weight(1), 1, ).is_err()); assert!( as SignedExtension>::pre_dispatch( ChargeTransactionPayment::from(0), &1, CALL, - info_from_weight(1), + &info_from_weight(1), 1, ).is_ok()); @@ -172,14 +199,14 @@ macro_rules! decl_tests { ChargeTransactionPayment::from(1), &1, CALL, - info_from_weight(1), + &info_from_weight(1), 1, ).is_err()); assert!( as SignedExtension>::pre_dispatch( ChargeTransactionPayment::from(0), &1, CALL, - info_from_weight(1), + &info_from_weight(1), 1, ).is_err()); }); @@ -463,6 +490,10 @@ macro_rules! decl_tests { let _ = Balances::deposit_creating(&2, 1); assert_ok!(Balances::reserve(&1, 110)); assert_ok!(Balances::repatriate_reserved(&1, &2, 41, Status::Free), 0); + assert_eq!( + last_event(), + Event::balances(RawEvent::ReserveRepatriated(1, 2, 41, Status::Free)), + ); assert_eq!(Balances::reserved_balance(1), 69); assert_eq!(Balances::free_balance(1), 0); assert_eq!(Balances::reserved_balance(2), 0); @@ -660,5 +691,101 @@ macro_rules! decl_tests { assert_eq!(Balances::reserved_balance(1), 0); }); } + + #[test] + fn emit_events_with_reserve_and_unreserve() { + <$ext_builder>::default() + .build() + .execute_with(|| { + let _ = Balances::deposit_creating(&1, 100); + + System::set_block_number(2); + let _ = Balances::reserve(&1, 10); + + assert_eq!( + last_event(), + Event::balances(RawEvent::Reserved(1, 10)), + ); + + System::set_block_number(3); + let _ = Balances::unreserve(&1, 5); + + assert_eq!( + last_event(), + Event::balances(RawEvent::Unreserved(1, 5)), + ); + + System::set_block_number(4); + let _ = Balances::unreserve(&1, 6); + + // should only unreserve 5 + assert_eq!( + last_event(), + Event::balances(RawEvent::Unreserved(1, 5)), + ); + }); + } + + #[test] + fn emit_events_with_existential_deposit() { + <$ext_builder>::default() + .existential_deposit(100) + .build() + .execute_with(|| { + assert_ok!(Balances::set_balance(RawOrigin::Root.into(), 1, 100, 0)); + + assert_eq!( + events(), + [ + Event::system(system::RawEvent::NewAccount(1)), + Event::balances(RawEvent::Endowed(1, 100)), + Event::balances(RawEvent::BalanceSet(1, 100, 0)), + ] + ); + + let _ = Balances::slash(&1, 1); + + assert_eq!( + events(), + [ + Event::balances(RawEvent::DustLost(1, 99)), + Event::system(system::RawEvent::KilledAccount(1)) + ] + ); + }); + } + + #[test] + fn emit_events_with_no_existential_deposit_suicide() { + <$ext_builder>::default() + .existential_deposit(0) + .build() + .execute_with(|| { + assert_ok!(Balances::set_balance(RawOrigin::Root.into(), 1, 100, 0)); + + assert_eq!( + events(), + [ + Event::system(system::RawEvent::NewAccount(1)), + Event::balances(RawEvent::Endowed(1, 100)), + Event::balances(RawEvent::BalanceSet(1, 100, 0)), + ] + ); + + let _ = Balances::slash(&1, 100); + + // no events + assert_eq!(events(), []); + + assert_ok!(System::suicide(Origin::signed(1))); + + assert_eq!( + events(), + [ + Event::system(system::RawEvent::KilledAccount(1)) + ] + ); + }); + } } } diff --git a/frame/balances/src/tests_composite.rs b/frame/balances/src/tests_composite.rs index 8935dc4c9a12364d30c6f74a2bc5076306c38223..8e764112ba24ccf135148378be62f28bc8ab3428 100644 --- a/frame/balances/src/tests_composite.rs +++ b/frame/balances/src/tests_composite.rs @@ -1,37 +1,53 @@ -// Copyright 2018-2020 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. +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utilities #![cfg(test)] -use sp_runtime::{Perbill, traits::{ConvertInto, IdentityLookup}, testing::Header}; +use sp_runtime::{ + Perbill, + traits::IdentityLookup, + testing::Header, +}; use sp_core::H256; use sp_io; -use frame_support::{impl_outer_origin, parameter_types}; +use frame_support::{impl_outer_origin, impl_outer_event, parameter_types}; use frame_support::traits::Get; -use frame_support::weights::{Weight, DispatchInfo}; +use frame_support::weights::{Weight, DispatchInfo, IdentityFee}; use std::cell::RefCell; -use crate::{GenesisConfig, Module, Trait, decl_tests}; +use crate::{GenesisConfig, Module, Trait, decl_tests, tests::CallWithDispatchInfo}; use frame_system as system; impl_outer_origin!{ pub enum Origin for Test {} } +mod balances { + pub use crate::Event; +} + +impl_outer_event! { + pub enum Event for Test { + system, + balances, + } +} + thread_local! { static EXISTENTIAL_DEPOSIT: RefCell = RefCell::new(0); } @@ -51,18 +67,23 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; - type Call = (); + type Call = CallWithDispatchInfo; type Hash = H256; type Hashing = ::sp_runtime::traits::BlakeTwo256; type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; - type Event = (); + type Event = Event; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -70,25 +91,25 @@ impl frame_system::Trait for Test { type AccountData = super::AccountData; type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } parameter_types! { - pub const TransactionBaseFee: u64 = 0; pub const TransactionByteFee: u64 = 1; } impl pallet_transaction_payment::Trait for Test { type Currency = Module; type OnTransactionPayment = (); - type TransactionBaseFee = TransactionBaseFee; type TransactionByteFee = TransactionByteFee; - type WeightToFee = ConvertInto; + type WeightToFee = IdentityFee; type FeeMultiplierUpdate = (); } impl Trait for Test { type Balance = u64; type DustRemoval = (); - type Event = (); + type Event = Event; type ExistentialDeposit = ExistentialDeposit; type AccountStore = system::Module; + type WeightInfo = (); } pub struct ExtBuilder { @@ -131,7 +152,10 @@ impl ExtBuilder { vec![] }, }.assimilate_storage(&mut t).unwrap(); - t.into() + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext } } diff --git a/frame/balances/src/tests_local.rs b/frame/balances/src/tests_local.rs index c8a4a298f57fd90abcf0db63ed1e0d0b1323857f..86abc2b6044ce4f6802b794968140c25e3b72ba4 100644 --- a/frame/balances/src/tests_local.rs +++ b/frame/balances/src/tests_local.rs @@ -1,37 +1,53 @@ -// Copyright 2018-2020 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. +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utilities #![cfg(test)] -use sp_runtime::{Perbill, traits::{ConvertInto, IdentityLookup}, testing::Header}; +use sp_runtime::{ + Perbill, + traits::IdentityLookup, + testing::Header, +}; use sp_core::H256; use sp_io; -use frame_support::{impl_outer_origin, parameter_types}; +use frame_support::{impl_outer_origin, impl_outer_event, parameter_types}; use frame_support::traits::{Get, StorageMapShim}; -use frame_support::weights::{Weight, DispatchInfo}; +use frame_support::weights::{Weight, DispatchInfo, IdentityFee}; use std::cell::RefCell; -use crate::{GenesisConfig, Module, Trait, decl_tests}; +use crate::{GenesisConfig, Module, Trait, decl_tests, tests::CallWithDispatchInfo}; use frame_system as system; impl_outer_origin!{ pub enum Origin for Test {} } +mod balances { + pub use crate::Event; +} + +impl_outer_event! { + pub enum Event for Test { + system, + balances, + } +} + thread_local! { static EXISTENTIAL_DEPOSIT: RefCell = RefCell::new(0); } @@ -51,18 +67,23 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; - type Call = (); + type Call = CallWithDispatchInfo; type Hash = H256; type Hashing = ::sp_runtime::traits::BlakeTwo256; type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; - type Event = (); + type Event = Event; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -70,23 +91,22 @@ impl frame_system::Trait for Test { type AccountData = super::AccountData; type OnNewAccount = (); type OnKilledAccount = Module; + type SystemWeightInfo = (); } parameter_types! { - pub const TransactionBaseFee: u64 = 0; pub const TransactionByteFee: u64 = 1; } impl pallet_transaction_payment::Trait for Test { type Currency = Module; type OnTransactionPayment = (); - type TransactionBaseFee = TransactionBaseFee; type TransactionByteFee = TransactionByteFee; - type WeightToFee = ConvertInto; + type WeightToFee = IdentityFee; type FeeMultiplierUpdate = (); } impl Trait for Test { type Balance = u64; type DustRemoval = (); - type Event = (); + type Event = Event; type ExistentialDeposit = ExistentialDeposit; type AccountStore = StorageMapShim< super::Account, @@ -94,6 +114,7 @@ impl Trait for Test { system::CallKillAccount, u64, super::AccountData >; + type WeightInfo = (); } pub struct ExtBuilder { @@ -139,8 +160,45 @@ impl ExtBuilder { vec![] }, }.assimilate_storage(&mut t).unwrap(); - t.into() + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext } } decl_tests!{ Test, ExtBuilder, EXISTENTIAL_DEPOSIT } + +#[test] +fn emit_events_with_no_existential_deposit_suicide_with_dust() { + ::default() + .existential_deposit(0) + .build() + .execute_with(|| { + assert_ok!(Balances::set_balance(RawOrigin::Root.into(), 1, 100, 0)); + + assert_eq!( + events(), + [ + Event::system(system::RawEvent::NewAccount(1)), + Event::balances(RawEvent::Endowed(1, 100)), + Event::balances(RawEvent::BalanceSet(1, 100, 0)), + ] + ); + + let _ = Balances::slash(&1, 99); + + // no events + assert_eq!(events(), []); + + assert_ok!(System::suicide(Origin::signed(1))); + + assert_eq!( + events(), + [ + Event::balances(RawEvent::DustLost(1, 1)), + Event::system(system::RawEvent::KilledAccount(1)) + ] + ); + }); +} diff --git a/frame/benchmark/Cargo.toml b/frame/benchmark/Cargo.toml index 804a28370449c46056caf5b4e97a515f6e33b9c7..79d9a8d7711e0c06a9c7ca1994909416e8cee51d 100644 --- a/frame/benchmark/Cargo.toml +++ b/frame/benchmark/Cargo.toml @@ -1,22 +1,25 @@ [package] name = "pallet-benchmark" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Patterns to benchmark in a FRAME runtime." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } -frame-benchmarking = { version = "2.0.0-alpha.5", default-features = false, path = "../benchmarking", optional = true } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } +frame-benchmarking = { version = "2.0.0-rc4", default-features = false, path = "../benchmarking", optional = true } [features] default = ["std"] @@ -31,6 +34,3 @@ std = [ "frame-benchmarking/std", ] runtime-benchmarks = ["frame-benchmarking"] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/benchmark/src/benchmarking.rs b/frame/benchmark/src/benchmarking.rs index 1e4740da2c0595b45be30c4a1dc2496176f7d157..ddf3df9eaad4cb5a367724a5b2b1508359856bc4 100644 --- a/frame/benchmark/src/benchmarking.rs +++ b/frame/benchmark/src/benchmarking.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Benchmarks for common FRAME Pallet operations. diff --git a/frame/benchmark/src/lib.rs b/frame/benchmark/src/lib.rs index b571ffb5b9cab6272908585270a44e86efa48e6d..422272f817c7a2f75c2b991a40a01929b4dc48b2 100644 --- a/frame/benchmark/src/lib.rs +++ b/frame/benchmark/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! A pallet that contains common runtime patterns in an isolated manner. //! This pallet is **not** meant to be used in a production blockchain, just @@ -70,7 +71,7 @@ decl_module! { fn deposit_event() = default; /// Do nothing. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] pub fn do_nothing(_origin, input: u32) { if input > 0 { return Ok(()); @@ -82,7 +83,7 @@ decl_module! { /// storage database, however, the `repeat` calls will all pull from the /// storage overlay cache. You must consider this when analyzing the /// results of the benchmark. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] pub fn read_value(_origin, repeat: u32) { for _ in 0..repeat { MyValue::get(); @@ -90,7 +91,7 @@ decl_module! { } /// Put a value into a storage value. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] pub fn put_value(_origin, repeat: u32) { for r in 0..repeat { MyValue::put(r); @@ -102,7 +103,7 @@ decl_module! { /// storage database, however, the `repeat` calls will all pull from the /// storage overlay cache. You must consider this when analyzing the /// results of the benchmark. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] pub fn exists_value(_origin, repeat: u32) { for _ in 0..repeat { MyValue::exists(); @@ -110,7 +111,7 @@ decl_module! { } /// Remove a value from storage `repeat` number of times. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] pub fn remove_value(_origin, repeat: u32) { for r in 0..repeat { MyMap::remove(r); @@ -118,7 +119,7 @@ decl_module! { } /// Read a value from storage map `repeat` number of times. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] pub fn read_map(_origin, repeat: u32) { for r in 0..repeat { MyMap::get(r); @@ -126,7 +127,7 @@ decl_module! { } /// Insert a value into a map. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] pub fn insert_map(_origin, repeat: u32) { for r in 0..repeat { MyMap::insert(r, r); @@ -134,7 +135,7 @@ decl_module! { } /// Check is a map contains a value `repeat` number of times. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] pub fn contains_key_map(_origin, repeat: u32) { for r in 0..repeat { MyMap::contains_key(r); @@ -142,7 +143,7 @@ decl_module! { } /// Read a value from storage `repeat` number of times. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] pub fn remove_prefix(_origin, repeat: u32) { for r in 0..repeat { MyDoubleMap::remove_prefix(r); @@ -150,21 +151,21 @@ decl_module! { } /// Add user to the list. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] pub fn add_member_list(origin) { let who = ensure_signed(origin)?; MyMemberList::::mutate(|x| x.push(who)); } /// Append user to the list. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] pub fn append_member_list(origin) { let who = ensure_signed(origin)?; - MyMemberList::::append(&[who])?; + MyMemberList::::append(who); } /// Encode a vector of accounts to bytes. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] pub fn encode_accounts(_origin, accounts: Vec) { let bytes = accounts.encode(); @@ -176,7 +177,7 @@ decl_module! { } /// Decode bytes into a vector of accounts. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] pub fn decode_accounts(_origin, bytes: Vec) { let accounts: Vec = Decode::decode(&mut bytes.as_slice()).map_err(|_| "Could not decode")?; diff --git a/frame/benchmarking/Cargo.toml b/frame/benchmarking/Cargo.toml index 7ed60664190ee53bfe21574ad67133aca99de639..0823ec626cb4f3b2b6b22895bc55c277cf75ab1c 100644 --- a/frame/benchmarking/Cargo.toml +++ b/frame/benchmarking/Cargo.toml @@ -1,23 +1,27 @@ [package] name = "frame-benchmarking" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Macro for benchmarking a FRAME runtime." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] linregress = "0.1" -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -sp-api = { version = "2.0.0-alpha.5", path = "../../primitives/api", default-features = false } -sp-runtime-interface = { version = "2.0.0-alpha.5", path = "../../primitives/runtime-interface", default-features = false } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../primitives/runtime", default-features = false } -sp-std = { version = "2.0.0-alpha.5", path = "../../primitives/std", default-features = false } -sp-io = { path = "../../primitives/io", default-features = false, version = "2.0.0-alpha.5"} -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } +paste = "0.1" +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +sp-api = { version = "2.0.0-rc4", path = "../../primitives/api", default-features = false } +sp-runtime-interface = { version = "2.0.0-rc4", path = "../../primitives/runtime-interface", default-features = false } +sp-runtime = { version = "2.0.0-rc4", path = "../../primitives/runtime", default-features = false } +sp-std = { version = "2.0.0-rc4", path = "../../primitives/std", default-features = false } +sp-io = { version = "2.0.0-rc4", path = "../../primitives/io", default-features = false } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } [features] default = [ "std" ] @@ -30,6 +34,3 @@ std = [ "frame-support/std", "frame-system/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/benchmarking/src/analysis.rs b/frame/benchmarking/src/analysis.rs index fdf1210832cadc2b06f870ee2373b36d278e2109..c17e206c34c6c3ef7113d1ddb683943269de8088 100644 --- a/frame/benchmarking/src/analysis.rs +++ b/frame/benchmarking/src/analysis.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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. +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Tools for analysing the benchmark results. @@ -21,31 +22,47 @@ use linregress::{FormulaRegressionBuilder, RegressionDataBuilder, RegressionMode use crate::BenchmarkResults; pub struct Analysis { - base: u128, - slopes: Vec, - names: Vec, - value_dists: Option, u128, u128)>>, - model: Option, + pub base: u128, + pub slopes: Vec, + pub names: Vec, + pub value_dists: Option, u128, u128)>>, + pub model: Option, +} + +pub enum BenchmarkSelector { + ExtrinsicTime, + StorageRootTime, + Reads, + Writes, } impl Analysis { - pub fn median_slopes(r: &Vec) -> Option { - let results = r[0].0.iter().enumerate().map(|(i, &(param, _))| { + pub fn median_slopes(r: &Vec, selector: BenchmarkSelector) -> Option { + let results = r[0].components.iter().enumerate().map(|(i, &(param, _))| { let mut counted = BTreeMap::, usize>::new(); - for (params, _, _) in r.iter() { - let mut p = params.iter().map(|x| x.1).collect::>(); + for result in r.iter() { + let mut p = result.components.iter().map(|x| x.1).collect::>(); p[i] = 0; *counted.entry(p).or_default() += 1; } let others: Vec = counted.iter().max_by_key(|i| i.1).expect("r is not empty; qed").0.clone(); let values = r.iter() .filter(|v| - v.0.iter() + v.components.iter() .map(|x| x.1) .zip(others.iter()) .enumerate() .all(|(j, (v1, v2))| j == i || v1 == *v2) - ).map(|(ps, v, _)| (ps[i].1, *v)) + ).map(|result| { + // Extract the data we are interested in analyzing + let data = match selector { + BenchmarkSelector::ExtrinsicTime => result.extrinsic_time, + BenchmarkSelector::StorageRootTime => result.storage_root_time, + BenchmarkSelector::Reads => result.reads.into(), + BenchmarkSelector::Writes => result.writes.into(), + }; + (result.components[i].1, data) + }) .collect::>(); (format!("{:?}", param), i, others, values) }).collect::>(); @@ -96,12 +113,18 @@ impl Analysis { }) } - pub fn min_squares_iqr(r: &Vec) -> Option { + pub fn min_squares_iqr(r: &Vec, selector: BenchmarkSelector) -> Option { let mut results = BTreeMap::, Vec>::new(); - for &(ref params, t, _) in r.iter() { - let p = params.iter().map(|x| x.1).collect::>(); - results.entry(p).or_default().push(t); + for result in r.iter() { + let p = result.components.iter().map(|x| x.1).collect::>(); + results.entry(p).or_default().push(match selector { + BenchmarkSelector::ExtrinsicTime => result.extrinsic_time, + BenchmarkSelector::StorageRootTime => result.storage_root_time, + BenchmarkSelector::Reads => result.reads.into(), + BenchmarkSelector::Writes => result.writes.into(), + }) } + for (_, rs) in results.iter_mut() { rs.sort(); let ql = rs.len() / 4; @@ -110,7 +133,7 @@ impl Analysis { let mut data = vec![("Y", results.iter().flat_map(|x| x.1.iter().map(|v| *v as f64)).collect())]; - let names = r[0].0.iter().map(|x| format!("{:?}", x.0)).collect::>(); + let names = r[0].components.iter().map(|x| format!("{:?}", x.0)).collect::>(); data.extend(names.iter() .enumerate() .map(|(i, p)| ( @@ -138,6 +161,8 @@ impl Analysis { .collect(); let value_dists = results.iter().map(|(p, vs)| { + // Avoid divide by zero + if vs.len() == 0 { return (p.clone(), 0, 0) } let total = vs.iter() .fold(0u128, |acc, v| acc + *v); let mean = total / vs.len() as u128; @@ -178,13 +203,23 @@ impl std::fmt::Display for Analysis { writeln!(f, "\nData points distribution:")?; writeln!(f, "{} mean µs sigma µs %", self.names.iter().map(|p| format!("{:>5}", p)).collect::>().join(" "))?; for (param_values, mean, sigma) in value_dists.iter() { - writeln!(f, "{} {:>8} {:>8} {:>3}.{}%", - param_values.iter().map(|v| format!("{:>5}", v)).collect::>().join(" "), - ms(*mean), - ms(*sigma), - (sigma * 100 / mean), - (sigma * 1000 / mean % 10) - )?; + if *mean == 0 { + writeln!(f, "{} {:>8} {:>8} {:>3}.{}%", + param_values.iter().map(|v| format!("{:>5}", v)).collect::>().join(" "), + ms(*mean), + ms(*sigma), + "?", + "?" + )?; + } else { + writeln!(f, "{} {:>8} {:>8} {:>3}.{}%", + param_values.iter().map(|v| format!("{:>5}", v)).collect::>().join(" "), + ms(*mean), + ms(*sigma), + (sigma * 100 / mean), + (sigma * 1000 / mean % 10) + )?; + } } } if let Some(ref model) = self.model { @@ -204,40 +239,88 @@ impl std::fmt::Display for Analysis { } } +impl std::fmt::Debug for Analysis { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.base)?; + for (&m, n) in self.slopes.iter().zip(self.names.iter()) { + write!(f, " + ({} * {})", m, n)?; + } + write!(f,"") + } +} + #[cfg(test)] mod tests { use super::*; use crate::BenchmarkParameter; + fn benchmark_result( + components: Vec<(BenchmarkParameter, u32)>, + extrinsic_time: u128, + storage_root_time: u128, + reads: u32, + writes: u32, + ) -> BenchmarkResults { + BenchmarkResults { + components, + extrinsic_time, + storage_root_time, + reads, + repeat_reads: 0, + writes, + repeat_writes: 0, + } + } + #[test] fn analysis_median_slopes_should_work() { - let a = Analysis::median_slopes(&vec![ - (vec![(BenchmarkParameter::n, 1), (BenchmarkParameter::m, 5)], 11_500_000, 0), - (vec![(BenchmarkParameter::n, 2), (BenchmarkParameter::m, 5)], 12_500_000, 0), - (vec![(BenchmarkParameter::n, 3), (BenchmarkParameter::m, 5)], 13_500_000, 0), - (vec![(BenchmarkParameter::n, 4), (BenchmarkParameter::m, 5)], 14_500_000, 0), - (vec![(BenchmarkParameter::n, 3), (BenchmarkParameter::m, 1)], 13_100_000, 0), - (vec![(BenchmarkParameter::n, 3), (BenchmarkParameter::m, 3)], 13_300_000, 0), - (vec![(BenchmarkParameter::n, 3), (BenchmarkParameter::m, 7)], 13_700_000, 0), - (vec![(BenchmarkParameter::n, 3), (BenchmarkParameter::m, 10)], 14_000_000, 0), - ]).unwrap(); - assert_eq!(a.base, 10_000_000); - assert_eq!(a.slopes, vec![1_000_000, 100_000]); + let data = vec![ + benchmark_result(vec![(BenchmarkParameter::n, 1), (BenchmarkParameter::m, 5)], 11_500_000, 0, 3, 10), + benchmark_result(vec![(BenchmarkParameter::n, 2), (BenchmarkParameter::m, 5)], 12_500_000, 0, 4, 10), + benchmark_result(vec![(BenchmarkParameter::n, 3), (BenchmarkParameter::m, 5)], 13_500_000, 0, 5, 10), + benchmark_result(vec![(BenchmarkParameter::n, 4), (BenchmarkParameter::m, 5)], 14_500_000, 0, 6, 10), + benchmark_result(vec![(BenchmarkParameter::n, 3), (BenchmarkParameter::m, 1)], 13_100_000, 0, 5, 2), + benchmark_result(vec![(BenchmarkParameter::n, 3), (BenchmarkParameter::m, 3)], 13_300_000, 0, 5, 6), + benchmark_result(vec![(BenchmarkParameter::n, 3), (BenchmarkParameter::m, 7)], 13_700_000, 0, 5, 14), + benchmark_result(vec![(BenchmarkParameter::n, 3), (BenchmarkParameter::m, 10)], 14_000_000, 0, 5, 20), + ]; + + let extrinsic_time = Analysis::median_slopes(&data, BenchmarkSelector::ExtrinsicTime).unwrap(); + assert_eq!(extrinsic_time.base, 10_000_000); + assert_eq!(extrinsic_time.slopes, vec![1_000_000, 100_000]); + + let reads = Analysis::median_slopes(&data, BenchmarkSelector::Reads).unwrap(); + assert_eq!(reads.base, 2); + assert_eq!(reads.slopes, vec![1, 0]); + + let writes = Analysis::median_slopes(&data, BenchmarkSelector::Writes).unwrap(); + assert_eq!(writes.base, 0); + assert_eq!(writes.slopes, vec![0, 2]); } #[test] fn analysis_median_min_squares_should_work() { - let a = Analysis::min_squares_iqr(&vec![ - (vec![(BenchmarkParameter::n, 1), (BenchmarkParameter::m, 5)], 11_500_000, 0), - (vec![(BenchmarkParameter::n, 2), (BenchmarkParameter::m, 5)], 12_500_000, 0), - (vec![(BenchmarkParameter::n, 3), (BenchmarkParameter::m, 5)], 13_500_000, 0), - (vec![(BenchmarkParameter::n, 4), (BenchmarkParameter::m, 5)], 14_500_000, 0), - (vec![(BenchmarkParameter::n, 3), (BenchmarkParameter::m, 1)], 13_100_000, 0), - (vec![(BenchmarkParameter::n, 3), (BenchmarkParameter::m, 3)], 13_300_000, 0), - (vec![(BenchmarkParameter::n, 3), (BenchmarkParameter::m, 7)], 13_700_000, 0), - (vec![(BenchmarkParameter::n, 3), (BenchmarkParameter::m, 10)], 14_000_000, 0), - ]).unwrap(); - assert_eq!(a.base, 10_000_000); - assert_eq!(a.slopes, vec![1_000_000, 100_000]); + let data = vec![ + benchmark_result(vec![(BenchmarkParameter::n, 1), (BenchmarkParameter::m, 5)], 11_500_000, 0, 3, 10), + benchmark_result(vec![(BenchmarkParameter::n, 2), (BenchmarkParameter::m, 5)], 12_500_000, 0, 4, 10), + benchmark_result(vec![(BenchmarkParameter::n, 3), (BenchmarkParameter::m, 5)], 13_500_000, 0, 5, 10), + benchmark_result(vec![(BenchmarkParameter::n, 4), (BenchmarkParameter::m, 5)], 14_500_000, 0, 6, 10), + benchmark_result(vec![(BenchmarkParameter::n, 3), (BenchmarkParameter::m, 1)], 13_100_000, 0, 5, 2), + benchmark_result(vec![(BenchmarkParameter::n, 3), (BenchmarkParameter::m, 3)], 13_300_000, 0, 5, 6), + benchmark_result(vec![(BenchmarkParameter::n, 3), (BenchmarkParameter::m, 7)], 13_700_000, 0, 5, 14), + benchmark_result(vec![(BenchmarkParameter::n, 3), (BenchmarkParameter::m, 10)], 14_000_000, 0, 5, 20), + ]; + + let extrinsic_time = Analysis::min_squares_iqr(&data, BenchmarkSelector::ExtrinsicTime).unwrap(); + assert_eq!(extrinsic_time.base, 10_000_000); + assert_eq!(extrinsic_time.slopes, vec![1_000_000, 100_000]); + + let reads = Analysis::min_squares_iqr(&data, BenchmarkSelector::Reads).unwrap(); + assert_eq!(reads.base, 2); + assert_eq!(reads.slopes, vec![1, 0]); + + let writes = Analysis::min_squares_iqr(&data, BenchmarkSelector::Writes).unwrap(); + assert_eq!(writes.base, 0); + assert_eq!(writes.slopes, vec![0, 2]); } } diff --git a/frame/benchmarking/src/lib.rs b/frame/benchmarking/src/lib.rs index b1427b792de3a9b4e4e85a226c4e0035ebf4b35b..532cb273c989d0f81ab745238709a9db5e22ee5d 100644 --- a/frame/benchmarking/src/lib.rs +++ b/frame/benchmarking/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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. +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Macro for benchmarking a FRAME runtime. @@ -25,10 +26,12 @@ mod analysis; pub use utils::*; #[cfg(feature = "std")] -pub use analysis::Analysis; +pub use analysis::{Analysis, BenchmarkSelector}; #[doc(hidden)] pub use sp_io::storage::root as storage_root; -pub use sp_runtime::traits::Dispatchable; +pub use sp_runtime::traits::Zero; +pub use frame_support; +pub use paste; /// Construct pallet benchmarks for weighing dispatchables. /// @@ -68,6 +71,9 @@ pub use sp_runtime::traits::Dispatchable; /// (or not) by each arm. Syntax is available to allow for only the range to be drawn upon if /// desired, allowing an alternative instancing expression to be given. /// +/// Note that the ranges are *inclusive* on both sides. This is in contrast to ranges in Rust which +/// are left-inclusive right-exclusive. +/// /// Each arm may also have a block of code which is run prior to any instancing and a block of code /// which is run afterwards. All code blocks may draw upon the specific value of each parameter /// at any time. Local variables are shared between the two pre- and post- code blocks, but do not @@ -79,7 +85,10 @@ pub use sp_runtime::traits::Dispatchable; /// Example: /// ```ignore /// benchmarks! { +/// where_clause { where T::A: From } // Optional line to give additional bound on `T`. +/// /// // common parameter; just one for this example. +/// // will be `1`, `MAX_LENGTH` or any value inbetween /// _ { /// let l in 1 .. MAX_LENGTH => initialize_l(l); /// } @@ -124,9 +133,49 @@ pub use sp_runtime::traits::Dispatchable; /// }: { m.into_iter().collect::() } /// } /// ``` +/// +/// Test functions are automatically generated for each benchmark and are accessible to you when you +/// run `cargo test`. All tests are named `test_benchmark_`, expect you to pass them +/// the Runtime Trait, and run them in a test externalities environment. The test function runs your +/// benchmark just like a regular benchmark, but only testing at the lowest and highest values for +/// each component. The function will return `Ok(())` if the benchmarks return no errors. +/// +/// You can optionally add a `verify` code block at the end of a benchmark to test any final state +/// of your benchmark in a unit test. For example: +/// +/// ```ignore +/// sort_vector { +/// let x in 1 .. 10000; +/// let mut m = Vec::::new(); +/// for i in (0..x).rev() { +/// m.push(i); +/// } +/// }: { +/// m.sort(); +/// } verify { +/// ensure!(m[0] == 0, "You forgot to sort!") +/// } +/// ``` +/// +/// These `verify` blocks will not execute when running your actual benchmarks! +/// +/// You can construct benchmark tests like so: +/// +/// ```ignore +/// #[test] +/// fn test_benchmarks() { +/// new_test_ext().execute_with(|| { +/// assert_ok!(test_benchmark_dummy::()); +/// assert_err!(test_benchmark_other_name::(), "Bad origin"); +/// assert_ok!(test_benchmark_sort_vector::()); +/// assert_err!(test_benchmark_broken_benchmark::(), "You forgot to sort!"); +/// }); +/// } +/// ``` #[macro_export] macro_rules! benchmarks { ( + $( where_clause { where $( $where_ty:ty: $where_bound:path ),* $(,)? } )? _ { $( let $common:ident in $common_from:tt .. $common_to:expr => $common_instancer:expr; @@ -134,15 +183,21 @@ macro_rules! benchmarks { } $( $rest:tt )* ) => { - $crate::benchmarks_iter!(NO_INSTANCE { - $( { $common , $common_from , $common_to , $common_instancer } )* - } ( ) $( $rest )* ); + $crate::benchmarks_iter!( + NO_INSTANCE + { $( $( $where_ty: $where_bound ),* )? } + { $( { $common , $common_from , $common_to , $common_instancer } )* } + ( ) + $( $rest )* + ); } } +/// Same as [`benchmarks`] but for instantiable module. #[macro_export] macro_rules! benchmarks_instance { ( + $( where_clause { where $( $where_ty:ty: $where_bound:path ),* $(,)? } )? _ { $( let $common:ident in $common_from:tt .. $common_to:expr => $common_instancer:expr; @@ -150,122 +205,234 @@ macro_rules! benchmarks_instance { } $( $rest:tt )* ) => { - $crate::benchmarks_iter!(INSTANCE { - $( { $common , $common_from , $common_to , $common_instancer } )* - } ( ) $( $rest )* ); + $crate::benchmarks_iter!( + INSTANCE + { $( $( $where_ty: $where_bound ),* )? } + { $( { $common , $common_from , $common_to , $common_instancer } )* } + ( ) + $( $rest )* + ); } } #[macro_export] -#[allow(missing_docs)] +#[doc(hidden)] macro_rules! benchmarks_iter { // mutation arm: ( $instance:ident + { $( $where_clause:tt )* } { $( $common:tt )* } ( $( $names:ident )* ) $name:ident { $( $code:tt )* }: _ ( $origin:expr $( , $arg:expr )* ) + verify $postcode:block $( $rest:tt )* ) => { $crate::benchmarks_iter! { - $instance { $( $common )* } ( $( $names )* ) $name { $( $code )* }: $name ( $origin $( , $arg )* ) $( $rest )* + $instance + { $( $where_clause )* } + { $( $common )* } + ( $( $names )* ) + $name { $( $code )* }: $name ( $origin $( , $arg )* ) + verify $postcode + $( $rest )* } }; // no instance mutation arm: ( NO_INSTANCE + { $( $where_clause:tt )* } { $( $common:tt )* } ( $( $names:ident )* ) $name:ident { $( $code:tt )* }: $dispatch:ident ( $origin:expr $( , $arg:expr )* ) + verify $postcode:block $( $rest:tt )* ) => { $crate::benchmarks_iter! { NO_INSTANCE - { $( $common )* } ( $( $names )* ) $name { $( $code )* }: { - as $crate::Dispatchable>::dispatch(Call::::$dispatch($($arg),*), $origin.into())?; - } $( $rest )* + { $( $where_clause )* } + { $( $common )* } + ( $( $names )* ) + $name { $( $code )* }: { + < + Call as $crate::frame_support::traits::UnfilteredDispatchable + >::dispatch_bypass_filter(Call::::$dispatch($($arg),*), $origin.into())?; + } + verify $postcode + $( $rest )* } }; // instance mutation arm: ( INSTANCE + { $( $where_clause:tt )* } { $( $common:tt )* } ( $( $names:ident )* ) $name:ident { $( $code:tt )* }: $dispatch:ident ( $origin:expr $( , $arg:expr )* ) + verify $postcode:block $( $rest:tt )* ) => { $crate::benchmarks_iter! { INSTANCE - { $( $common )* } ( $( $names )* ) $name { $( $code )* }: { - as $crate::Dispatchable>::dispatch(Call::::$dispatch($($arg),*), $origin.into())?; - } $( $rest )* + { $( $where_clause )* } + { $( $common )* } + ( $( $names )* ) + $name { $( $code )* }: { + < + Call as $crate::frame_support::traits::UnfilteredDispatchable + >::dispatch_bypass_filter(Call::::$dispatch($($arg),*), $origin.into())?; + } + verify $postcode + $( $rest )* } }; // iteration arm: ( $instance:ident + { $( $where_clause:tt )* } { $( $common:tt )* } ( $( $names:ident )* ) $name:ident { $( $code:tt )* }: $eval:block + verify $postcode:block $( $rest:tt )* ) => { $crate::benchmark_backend! { - $instance $name { $( $common )* } { } { $eval } { $( $code )* } + $instance + $name + { $( $where_clause )* } + { $( $common )* } + { } + { $eval } + { $( $code )* } + $postcode } - $crate::benchmarks_iter!( $instance { $( $common )* } ( $( $names )* $name ) $( $rest )* ); + + #[cfg(test)] + $crate::impl_benchmark_test!( { $( $where_clause )* } $instance $name ); + + $crate::benchmarks_iter!( + $instance + { $( $where_clause )* } + { $( $common )* } + ( $( $names )* $name ) + $( $rest )* + ); }; // iteration-exit arm - ( $instance:ident { $( $common:tt )* } ( $( $names:ident )* ) ) => { - $crate::selected_benchmark!( $instance $( $names ),* ); - $crate::impl_benchmark!( $instance $( $names ),* ); - } + ( $instance:ident { $( $where_clause:tt )* } { $( $common:tt )* } ( $( $names:ident )* ) ) => { + $crate::selected_benchmark!( { $( $where_clause)* } $instance $( $names ),* ); + $crate::impl_benchmark!( { $( $where_clause )* } $instance $( $names ),* ); + }; + // add verify block to _() format + ( + $instance:ident + { $( $where_clause:tt )* } + { $( $common:tt )* } + ( $( $names:ident )* ) + $name:ident { $( $code:tt )* }: _ ( $origin:expr $( , $arg:expr )* ) + $( $rest:tt )* + ) => { + $crate::benchmarks_iter! { + $instance + { $( $where_clause )* } + { $( $common )* } + ( $( $names )* ) + $name { $( $code )* }: _ ( $origin $( , $arg )* ) + verify { } + $( $rest )* + } + }; + // add verify block to name() format + ( + $instance:ident + { $( $where_clause:tt )* } + { $( $common:tt )* } + ( $( $names:ident )* ) + $name:ident { $( $code:tt )* }: $dispatch:ident ( $origin:expr $( , $arg:expr )* ) + $( $rest:tt )* + ) => { + $crate::benchmarks_iter! { + $instance + { $( $where_clause )* } + { $( $common )* } + ( $( $names )* ) + $name { $( $code )* }: $dispatch ( $origin $( , $arg )* ) + verify { } + $( $rest )* + } + }; + // add verify block to {} format + ( + $instance:ident + { $( $where_clause:tt )* } + { $( $common:tt )* } + ( $( $names:ident )* ) + $name:ident { $( $code:tt )* }: $eval:block + $( $rest:tt )* + ) => { + $crate::benchmarks_iter!( + $instance + { $( $where_clause )* } + { $( $common )* } + ( $( $names )* ) + $name { $( $code )* }: $eval + verify { } + $( $rest )* + ); + }; } #[macro_export] -#[allow(missing_docs)] +#[doc(hidden)] macro_rules! benchmark_backend { // parsing arms ($instance:ident $name:ident { + $( $where_clause:tt )* + } { $( $common:tt )* } { $( PRE { $( $pre_parsed:tt )* } )* } { $eval:block } { let $pre_id:tt : $pre_ty:ty = $pre_ex:expr; $( $rest:tt )* - } ) => { + } $postcode:block) => { $crate::benchmark_backend! { - $instance $name { $( $common )* } { + $instance $name { $( $where_clause )* } { $( $common )* } { $( PRE { $( $pre_parsed )* } )* PRE { $pre_id , $pre_ty , $pre_ex } - } { $eval } { $( $rest )* } + } { $eval } { $( $rest )* } $postcode } }; ($instance:ident $name:ident { + $( $where_clause:tt )* + } { $( $common:tt )* } { $( $parsed:tt )* } { $eval:block } { let $param:ident in ( $param_from:expr ) .. $param_to:expr => $param_instancer:expr; $( $rest:tt )* - }) => { + } $postcode:block) => { $crate::benchmark_backend! { - $instance $name { $( $common )* } { + $instance $name { $( $where_clause )* } { $( $common )* } { $( $parsed )* PARAM { $param , $param_from , $param_to , $param_instancer } - } { $eval } { $( $rest )* } + } { $eval } { $( $rest )* } $postcode } }; // mutation arm to look after defaulting to a common param ($instance:ident $name:ident { + $( $where_clause:tt )* + } { $( { $common:ident , $common_from:tt , $common_to:expr , $common_instancer:expr } )* } { $( $parsed:tt )* } { $eval:block } { let $param:ident in ...; $( $rest:tt )* - }) => { + } $postcode:block) => { $crate::benchmark_backend! { - $instance $name { + $instance $name { $( $where_clause )* } { $( { $common , $common_from , $common_to , $common_instancer } )* } { $( $parsed )* @@ -275,20 +442,22 @@ macro_rules! benchmark_backend { .. ({ $( let $common = $common_to; )* $param }) => ({ $( let $common = || -> Result<(), &'static str> { $common_instancer ; Ok(()) }; )* $param()? }); $( $rest )* - } + } $postcode } }; // mutation arm to look after defaulting only the range to common param ($instance:ident $name:ident { + $( $where_clause:tt )* + } { $( { $common:ident , $common_from:tt , $common_to:expr , $common_instancer:expr } )* } { $( $parsed:tt )* } { $eval:block } { let $param:ident in _ .. _ => $param_instancer:expr ; $( $rest:tt )* - }) => { + } $postcode:block) => { $crate::benchmark_backend! { - $instance $name { + $instance $name { $( $where_clause )* } { $( { $common , $common_from , $common_to , $common_instancer } )* } { $( $parsed )* @@ -298,68 +467,78 @@ macro_rules! benchmark_backend { .. ({ $( let $common = $common_to; )* $param }) => $param_instancer ; $( $rest )* - } + } $postcode } }; // mutation arm to look after a single tt for param_from. ($instance:ident $name:ident { + $( $where_clause:tt )* + } { $( $common:tt )* } { $( $parsed:tt )* } { $eval:block } { let $param:ident in $param_from:tt .. $param_to:expr => $param_instancer:expr ; $( $rest:tt )* - }) => { + } $postcode:block) => { $crate::benchmark_backend! { - $instance $name { $( $common )* } { $( $parsed )* } { $eval } { + $instance $name { $( $where_clause )* } { $( $common )* } { $( $parsed )* } { $eval } { let $param in ( $param_from ) .. $param_to => $param_instancer; $( $rest )* - } + } $postcode } }; // mutation arm to look after the default tail of `=> ()` ($instance:ident $name:ident { + $( $where_clause:tt )* + } { $( $common:tt )* } { $( $parsed:tt )* } { $eval:block } { let $param:ident in $param_from:tt .. $param_to:expr; $( $rest:tt )* - }) => { + } $postcode:block) => { $crate::benchmark_backend! { - $instance $name { $( $common )* } { $( $parsed )* } { $eval } { + $instance $name { $( $where_clause )* } { $( $common )* } { $( $parsed )* } { $eval } { let $param in $param_from .. $param_to => (); $( $rest )* - } + } $postcode } }; // mutation arm to look after `let _ =` ($instance:ident $name:ident { + $( $where_clause:tt )* + } { $( $common:tt )* } { $( $parsed:tt )* } { $eval:block } { let $pre_id:tt = $pre_ex:expr; $( $rest:tt )* - }) => { + } $postcode:block) => { $crate::benchmark_backend! { - $instance $name { $( $common )* } { $( $parsed )* } { $eval } { + $instance $name { $( $where_clause )* } { $( $common )* } { $( $parsed )* } { $eval } { let $pre_id : _ = $pre_ex; $( $rest )* - } + } $postcode } }; // no instance actioning arm (NO_INSTANCE $name:ident { + $( $where_clause:tt )* + } { $( { $common:ident , $common_from:tt , $common_to:expr , $common_instancer:expr } )* } { $( PRE { $pre_id:tt , $pre_ty:ty , $pre_ex:expr } )* $( PARAM { $param:ident , $param_from:expr , $param_to:expr , $param_instancer:expr } )* - } { $eval:block } { $( $post:tt )* } ) => { + } { $eval:block } { $( $post:tt )* } $postcode:block) => { #[allow(non_camel_case_types)] struct $name; #[allow(unused_variables)] - impl $crate::BenchmarkingSetup for $name { + impl $crate::BenchmarkingSetup for $name + where $( $where_clause )* + { fn components(&self) -> Vec<($crate::BenchmarkParameter, u32, u32)> { vec! [ $( @@ -376,7 +555,9 @@ macro_rules! benchmark_backend { )* $( // Prepare instance - let $param = components.iter().find(|&c| c.0 == $crate::BenchmarkParameter::$param).unwrap().1; + let $param = components.iter() + .find(|&c| c.0 == $crate::BenchmarkParameter::$param) + .unwrap().1; )* $( let $pre_id : $pre_ty = $pre_ex; @@ -386,19 +567,44 @@ macro_rules! benchmark_backend { Ok(Box::new(move || -> Result<(), &'static str> { $eval; Ok(()) })) } + + fn verify(&self, components: &[($crate::BenchmarkParameter, u32)]) + -> Result Result<(), &'static str>>, &'static str> + { + $( + let $common = $common_from; + )* + $( + // Prepare instance + let $param = components.iter() + .find(|&c| c.0 == $crate::BenchmarkParameter::$param) + .unwrap().1; + )* + $( + let $pre_id : $pre_ty = $pre_ex; + )* + $( $param_instancer ; )* + $( $post )* + + Ok(Box::new(move || -> Result<(), &'static str> { $eval; $postcode; Ok(()) })) + } } }; // instance actioning arm (INSTANCE $name:ident { + $( $where_clause:tt )* + } { $( { $common:ident , $common_from:tt , $common_to:expr , $common_instancer:expr } )* } { $( PRE { $pre_id:tt , $pre_ty:ty , $pre_ex:expr } )* $( PARAM { $param:ident , $param_from:expr , $param_to:expr , $param_instancer:expr } )* - } { $eval:block } { $( $post:tt )* } ) => { + } { $eval:block } { $( $post:tt )* } $postcode:block) => { #[allow(non_camel_case_types)] struct $name; #[allow(unused_variables)] - impl, I: Instance> $crate::BenchmarkingSetupInstance for $name { + impl, I: Instance> $crate::BenchmarkingSetupInstance for $name + where $( $where_clause )* + { fn components(&self) -> Vec<($crate::BenchmarkParameter, u32, u32)> { vec! [ $( @@ -415,7 +621,9 @@ macro_rules! benchmark_backend { )* $( // Prepare instance - let $param = components.iter().find(|&c| c.0 == $crate::BenchmarkParameter::$param).unwrap().1; + let $param = components.iter() + .find(|&c| c.0 == $crate::BenchmarkParameter::$param) + .unwrap().1; )* $( let $pre_id : $pre_ty = $pre_ex; @@ -425,27 +633,50 @@ macro_rules! benchmark_backend { Ok(Box::new(move || -> Result<(), &'static str> { $eval; Ok(()) })) } + + fn verify(&self, components: &[($crate::BenchmarkParameter, u32)]) + -> Result Result<(), &'static str>>, &'static str> + { + $( + let $common = $common_from; + )* + $( + // Prepare instance + let $param = components.iter() + .find(|&c| c.0 == $crate::BenchmarkParameter::$param) + .unwrap().1; + )* + $( + let $pre_id : $pre_ty = $pre_ex; + )* + $( $param_instancer ; )* + $( $post )* + + Ok(Box::new(move || -> Result<(), &'static str> { $eval; $postcode; Ok(()) })) + } } } } -/// Creates a `SelectedBenchmark` enum implementing `BenchmarkingSetup`. -/// -/// Every variant must implement [`BenchmarkingSetup`]. -/// -/// ```nocompile -/// -/// struct Transfer; -/// impl BenchmarkingSetup for Transfer { ... } -/// -/// struct SetBalance; -/// impl BenchmarkingSetup for SetBalance { ... } -/// -/// selected_benchmark!(Transfer, SetBalance); -/// ``` +// Creates a `SelectedBenchmark` enum implementing `BenchmarkingSetup`. +// +// Every variant must implement [`BenchmarkingSetup`]. +// +// ```nocompile +// +// struct Transfer; +// impl BenchmarkingSetup for Transfer { ... } +// +// struct SetBalance; +// impl BenchmarkingSetup for SetBalance { ... } +// +// selected_benchmark!(Transfer, SetBalance); +// ``` #[macro_export] +#[doc(hidden)] macro_rules! selected_benchmark { ( + { $( $where_clause:tt )* } NO_INSTANCE $( $bench:ident ),* ) => { // The list of available benchmarks for this pallet. @@ -455,7 +686,9 @@ macro_rules! selected_benchmark { } // Allow us to select a benchmark from the list of available benchmarks. - impl $crate::BenchmarkingSetup for SelectedBenchmark { + impl $crate::BenchmarkingSetup for SelectedBenchmark + where $( $where_clause )* + { fn components(&self) -> Vec<($crate::BenchmarkParameter, u32, u32)> { match self { $( Self::$bench => <$bench as $crate::BenchmarkingSetup>::components(&$bench), )* @@ -469,9 +702,18 @@ macro_rules! selected_benchmark { $( Self::$bench => <$bench as $crate::BenchmarkingSetup>::instance(&$bench, components), )* } } + + fn verify(&self, components: &[($crate::BenchmarkParameter, u32)]) + -> Result Result<(), &'static str>>, &'static str> + { + match self { + $( Self::$bench => <$bench as $crate::BenchmarkingSetup>::verify(&$bench, components), )* + } + } } }; ( + { $( $where_clause:tt )* } INSTANCE $( $bench:ident ),* ) => { // The list of available benchmarks for this pallet. @@ -481,7 +723,9 @@ macro_rules! selected_benchmark { } // Allow us to select a benchmark from the list of available benchmarks. - impl, I: Instance> $crate::BenchmarkingSetupInstance for SelectedBenchmark { + impl, I: Instance> $crate::BenchmarkingSetupInstance for SelectedBenchmark + where $( $where_clause )* + { fn components(&self) -> Vec<($crate::BenchmarkParameter, u32, u32)> { match self { $( Self::$bench => <$bench as $crate::BenchmarkingSetupInstance>::components(&$bench), )* @@ -495,17 +739,27 @@ macro_rules! selected_benchmark { $( Self::$bench => <$bench as $crate::BenchmarkingSetupInstance>::instance(&$bench, components), )* } } + + fn verify(&self, components: &[($crate::BenchmarkParameter, u32)]) + -> Result Result<(), &'static str>>, &'static str> + { + match self { + $( Self::$bench => <$bench as $crate::BenchmarkingSetupInstance>::verify(&$bench, components), )* + } + } } } } #[macro_export] +#[doc(hidden)] macro_rules! impl_benchmark { ( + { $( $where_clause:tt )* } NO_INSTANCE $( $name:ident ),* ) => { impl $crate::Benchmarking<$crate::BenchmarkResults> for Module - where T: frame_system::Trait + where T: frame_system::Trait, $( $where_clause )* { fn benchmarks() -> Vec<&'static [u8]> { vec![ $( stringify!($name).as_ref() ),* ] @@ -517,6 +771,7 @@ macro_rules! impl_benchmark { highest_range_values: &[u32], steps: &[u32], repeat: u32, + whitelist: &[Vec] ) -> Result, &'static str> { // Map the input to the selected benchmark. let extrinsic = sp_std::str::from_utf8(extrinsic) @@ -526,6 +781,9 @@ macro_rules! impl_benchmark { _ => return Err("Could not find extrinsic."), }; + // Add whitelist to DB + $crate::benchmarking::set_whitelist(whitelist.to_vec()); + // Warm up the DB $crate::benchmarking::commit_db(); $crate::benchmarking::wipe_db(); @@ -542,6 +800,9 @@ macro_rules! impl_benchmark { let steps = steps.get(idx).cloned().unwrap_or(prev_steps); prev_steps = steps; + // Skip this loop if steps is zero + if steps == 0 { continue } + let lowest = lowest_range_values.get(idx).cloned().unwrap_or(*low); let highest = highest_range_values.get(idx).cloned().unwrap_or(*high); @@ -569,20 +830,45 @@ macro_rules! impl_benchmark { // Run the benchmark `repeat` times. for _ in 0..repeat { - // Set the block number to 1 so events are deposited. - frame_system::Module::::set_block_number(1.into()); - // Set up the externalities environment for the setup we want to benchmark. - let closure_to_benchmark = >::instance(&selected_benchmark, &c)?; + // Set up the externalities environment for the setup we want to + // benchmark. + let closure_to_benchmark = < + SelectedBenchmark as $crate::BenchmarkingSetup + >::instance(&selected_benchmark, &c)?; + + // Set the block number to at least 1 so events are deposited. + if $crate::Zero::is_zero(&frame_system::Module::::block_number()) { + frame_system::Module::::set_block_number(1.into()); + } // Commit the externalities to the database, flushing the DB cache. // This will enable worst case scenario for reading from the database. $crate::benchmarking::commit_db(); + // Reset the read/write counter so we don't count operations in the setup process. + $crate::benchmarking::reset_read_write_count(); + // Time the extrinsic logic. + frame_support::debug::trace!( + target: "benchmark", + "Start Benchmark: {:?} {:?}", name, component_value + ); + let start_extrinsic = $crate::benchmarking::current_time(); closure_to_benchmark()?; let finish_extrinsic = $crate::benchmarking::current_time(); let elapsed_extrinsic = finish_extrinsic - start_extrinsic; + // Commit the changes to get proper write count + $crate::benchmarking::commit_db(); + frame_support::debug::trace!( + target: "benchmark", + "End Benchmark: {} ns", elapsed_extrinsic + ); + let read_write_count = $crate::benchmarking::read_write_count(); + frame_support::debug::trace!( + target: "benchmark", + "Read/Write Count {:?}", read_write_count + ); // Time the storage root recalculation. let start_storage_root = $crate::benchmarking::current_time(); @@ -590,7 +876,15 @@ macro_rules! impl_benchmark { let finish_storage_root = $crate::benchmarking::current_time(); let elapsed_storage_root = finish_storage_root - start_storage_root; - results.push((c.clone(), elapsed_extrinsic, elapsed_storage_root)); + results.push($crate::BenchmarkResults { + components: c.clone(), + extrinsic_time: elapsed_extrinsic, + storage_root_time: elapsed_storage_root, + reads: read_write_count.0, + repeat_reads: read_write_count.1, + writes: read_write_count.2, + repeat_writes: read_write_count.3, + }); // Wipe the DB back to the genesis state. $crate::benchmarking::wipe_db(); @@ -602,10 +896,12 @@ macro_rules! impl_benchmark { } }; ( + { $( $where_clause:tt )* } INSTANCE $( $name:ident ),* ) => { - impl, I: Instance> $crate::Benchmarking<$crate::BenchmarkResults> for Module - where T: frame_system::Trait + impl, I: Instance> $crate::Benchmarking<$crate::BenchmarkResults> + for Module + where T: frame_system::Trait, $( $where_clause )* { fn benchmarks() -> Vec<&'static [u8]> { vec![ $( stringify!($name).as_ref() ),* ] @@ -617,6 +913,7 @@ macro_rules! impl_benchmark { highest_range_values: &[u32], steps: &[u32], repeat: u32, + whitelist: &[Vec] ) -> Result, &'static str> { // Map the input to the selected benchmark. let extrinsic = sp_std::str::from_utf8(extrinsic) @@ -626,11 +923,16 @@ macro_rules! impl_benchmark { _ => return Err("Could not find extrinsic."), }; + // Add whitelist to DB + $crate::benchmarking::set_whitelist(whitelist.to_vec()); + // Warm up the DB $crate::benchmarking::commit_db(); $crate::benchmarking::wipe_db(); - let components = >::components(&selected_benchmark); + let components = < + SelectedBenchmark as $crate::BenchmarkingSetupInstance + >::components(&selected_benchmark); let mut results: Vec<$crate::BenchmarkResults> = Vec::new(); // Default number of steps for a component. @@ -642,6 +944,9 @@ macro_rules! impl_benchmark { let steps = steps.get(idx).cloned().unwrap_or(prev_steps); prev_steps = steps; + // Skip this loop if steps is zero + if steps == 0 { continue } + let lowest = lowest_range_values.get(idx).cloned().unwrap_or(*low); let highest = highest_range_values.get(idx).cloned().unwrap_or(*high); @@ -669,20 +974,44 @@ macro_rules! impl_benchmark { // Run the benchmark `repeat` times. for _ in 0..repeat { - // Set the block number to 1 so events are deposited. - frame_system::Module::::set_block_number(1.into()); // Set up the externalities environment for the setup we want to benchmark. - let closure_to_benchmark = >::instance(&selected_benchmark, &c)?; + let closure_to_benchmark = < + SelectedBenchmark as $crate::BenchmarkingSetupInstance + >::instance(&selected_benchmark, &c)?; + + // Set the block number to at least 1 so events are deposited. + if $crate::Zero::is_zero(&frame_system::Module::::block_number()) { + frame_system::Module::::set_block_number(1.into()); + } // Commit the externalities to the database, flushing the DB cache. // This will enable worst case scenario for reading from the database. $crate::benchmarking::commit_db(); + // Reset the read/write counter so we don't count operations in the setup process. + $crate::benchmarking::reset_read_write_count(); + // Time the extrinsic logic. + frame_support::debug::trace!( + target: "benchmark", + "Start Benchmark: {:?} {:?}", name, component_value + ); + let start_extrinsic = $crate::benchmarking::current_time(); closure_to_benchmark()?; let finish_extrinsic = $crate::benchmarking::current_time(); let elapsed_extrinsic = finish_extrinsic - start_extrinsic; + // Commit the changes to get proper write count + $crate::benchmarking::commit_db(); + frame_support::debug::trace!( + target: "benchmark", + "End Benchmark: {} ns", elapsed_extrinsic + ); + let read_write_count = $crate::benchmarking::read_write_count(); + frame_support::debug::trace!( + target: "benchmark", + "Read/Write Count {:?}", read_write_count + ); // Time the storage root recalculation. let start_storage_root = $crate::benchmarking::current_time(); @@ -690,7 +1019,15 @@ macro_rules! impl_benchmark { let finish_storage_root = $crate::benchmarking::current_time(); let elapsed_storage_root = finish_storage_root - start_storage_root; - results.push((c.clone(), elapsed_extrinsic, elapsed_storage_root)); + results.push($crate::BenchmarkResults { + components: c.clone(), + extrinsic_time: elapsed_extrinsic, + storage_root_time: elapsed_storage_root, + reads: read_write_count.0, + repeat_reads: read_write_count.1, + writes: read_write_count.2, + repeat_writes: read_write_count.3, + }); // Wipe the DB back to the genesis state. $crate::benchmarking::wipe_db(); @@ -703,37 +1040,164 @@ macro_rules! impl_benchmark { } } +// This creates a unit test for one benchmark of the main benchmark macro. +// It runs the benchmark using the `high` and `low` value for each component +// and ensure that everything completes successfully. +#[macro_export] +#[doc(hidden)] +macro_rules! impl_benchmark_test { + ( + { $( $where_clause:tt )* } + NO_INSTANCE + $name:ident + ) => { + $crate::paste::item! { + fn [] () -> Result<(), &'static str> + where T: frame_system::Trait, $( $where_clause )* + { + let selected_benchmark = SelectedBenchmark::$name; + let components = < + SelectedBenchmark as $crate::BenchmarkingSetup + >::components(&selected_benchmark); + + assert!( + components.len() != 0, + "You need to add components to your benchmark!", + ); + for (_, (name, low, high)) in components.iter().enumerate() { + // Test only the low and high value, assuming values in the middle won't break + for component_value in vec![low, high] { + // Select the max value for all the other components. + let c: Vec<($crate::BenchmarkParameter, u32)> = components.iter() + .enumerate() + .map(|(_, (n, _, h))| + if n == name { + (*n, *component_value) + } else { + (*n, *h) + } + ) + .collect(); + + // Set up the verification state + let closure_to_verify = < + SelectedBenchmark as $crate::BenchmarkingSetup + >::verify(&selected_benchmark, &c)?; + + // Set the block number to at least 1 so events are deposited. + if $crate::Zero::is_zero(&frame_system::Module::::block_number()) { + frame_system::Module::::set_block_number(1.into()); + } + + // Run verification + closure_to_verify()?; + + // Reset the state + $crate::benchmarking::wipe_db(); + } + } + Ok(()) + } + } + }; + ( + { $( $where_clause:tt )* } + INSTANCE + $name:ident + ) => { + $crate::paste::item! { + fn [] () -> Result<(), &'static str> + where T: frame_system::Trait, $( $where_clause )* + { + let selected_benchmark = SelectedBenchmark::$name; + let components = < + SelectedBenchmark as $crate::BenchmarkingSetupInstance + >::components(&selected_benchmark); + + for (_, (name, low, high)) in components.iter().enumerate() { + // Test only the low and high value, assuming values in the middle won't break + for component_value in vec![low, high] { + // Select the max value for all the other components. + let c: Vec<($crate::BenchmarkParameter, u32)> = components.iter() + .enumerate() + .map(|(_, (n, _, h))| + if n == name { + (*n, *component_value) + } else { + (*n, *h) + } + ) + .collect(); + + // Set up the verification state + let closure_to_verify = < + SelectedBenchmark as $crate::BenchmarkingSetupInstance + >::verify(&selected_benchmark, &c)?; + + // Set the block number to at least 1 so events are deposited. + if $crate::Zero::is_zero(&frame_system::Module::::block_number()) { + frame_system::Module::::set_block_number(1.into()); + } + + // Run verification + closure_to_verify()?; + + // Reset the state + $crate::benchmarking::wipe_db(); + } + } + Ok(()) + } + } + }; +} + /// This macro adds pallet benchmarks to a `Vec` object. /// /// First create an object that holds in the input parameters for the benchmark: /// /// ```ignore -/// let params = (&pallet, &benchmark, &lowest_range_values, &highest_range_values, &steps, repeat); +/// let params = (&pallet, &benchmark, &lowest_range_values, &highest_range_values, &steps, repeat, &whitelist); /// ``` /// +/// The `whitelist` is a `Vec>` of storage keys that you would like to skip for DB tracking. For example: +/// +/// ```ignore +/// let whitelist: Vec> = vec![ +/// // Block Number +/// hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec(), +/// // Total Issuance +/// hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec(), +/// // Execution Phase +/// hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec(), +/// // Event Count +/// hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec(), +/// ]; +/// /// Then define a mutable local variable to hold your `BenchmarkBatch` object: /// /// ```ignore /// let mut batches = Vec::::new(); /// ```` /// -/// Then add the pallets you want to benchmark to this object, including the string -/// you want to use target a particular pallet: +/// Then add the pallets you want to benchmark to this object, using their crate name and generated +/// module struct: /// /// ```ignore -/// add_benchmark!(params, batches, b"balances", Balances); -/// add_benchmark!(params, batches, b"identity", Identity); -/// add_benchmark!(params, batches, b"session", SessionBench::); +/// add_benchmark!(params, batches, pallet_balances, Balances); +/// add_benchmark!(params, batches, pallet_session, SessionBench::); +/// add_benchmark!(params, batches, frame_system, SystemBench::); /// ... /// ``` /// /// At the end of `dispatch_benchmark`, you should return this batches object. #[macro_export] macro_rules! add_benchmark { - ( $params:ident, $batches:ident, $name:literal, $( $location:tt )* ) => ( - let (pallet, benchmark, lowest_range_values, highest_range_values, steps, repeat) = $params; - if &pallet[..] == &$name[..] || &pallet[..] == &b"*"[..] { + ( $params:ident, $batches:ident, $name:ident, $( $location:tt )* ) => ( + let name_string = stringify!($name).as_bytes(); + let (pallet, benchmark, lowest_range_values, highest_range_values, steps, repeat, whitelist) = $params; + if &pallet[..] == &name_string[..] || &pallet[..] == &b"*"[..] { if &pallet[..] == &b"*"[..] || &benchmark[..] == &b"*"[..] { for benchmark in $( $location )*::benchmarks().into_iter() { $batches.push($crate::BenchmarkBatch { @@ -743,8 +1207,9 @@ macro_rules! add_benchmark { &highest_range_values[..], &steps[..], repeat, + whitelist, )?, - pallet: pallet.to_vec(), + pallet: name_string.to_vec(), benchmark: benchmark.to_vec(), }); } @@ -756,8 +1221,9 @@ macro_rules! add_benchmark { &highest_range_values[..], &steps[..], repeat, + whitelist, )?, - pallet: pallet.to_vec(), + pallet: name_string.to_vec(), benchmark: benchmark.clone(), }); } diff --git a/frame/benchmarking/src/tests.rs b/frame/benchmarking/src/tests.rs index b3537617c7282da135db2c9ea59c6ff6506b3487..56e6da149438c77f36a7a5a0f3afb95b63e97ab2 100644 --- a/frame/benchmarking/src/tests.rs +++ b/frame/benchmarking/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for the module. @@ -22,19 +23,33 @@ use super::*; use codec::Decode; use sp_std::prelude::*; use sp_runtime::{traits::{BlakeTwo256, IdentityLookup}, testing::{H256, Header}}; -use frame_support::{dispatch::DispatchResult, decl_module, impl_outer_origin}; +use frame_support::{ + dispatch::DispatchResult, + decl_module, decl_storage, impl_outer_origin, assert_ok, assert_err, ensure +}; use frame_system::{RawOrigin, ensure_signed, ensure_none}; +decl_storage! { + trait Store for Module as Test where + ::OtherEvent: Into<::Event> + { + Value get(fn value): Option; + } +} + decl_module! { - pub struct Module for enum Call where origin: T::Origin { - #[weight = frame_support::weights::SimpleDispatchInfo::default()] - fn dummy(origin, _n: u32) -> DispatchResult { + pub struct Module for enum Call where + origin: T::Origin, ::OtherEvent: Into<::Event> + { + #[weight = 0] + fn set_value(origin, n: u32) -> DispatchResult { let _sender = ensure_signed(origin)?; + Value::put(n); Ok(()) } - #[weight = frame_support::weights::SimpleDispatchInfo::default()] - fn other_dummy(origin, _n: u32) -> DispatchResult { + #[weight = 0] + fn dummy(origin, _n: u32) -> DispatchResult { let _sender = ensure_none(origin)?; Ok(()) } @@ -45,17 +60,23 @@ impl_outer_origin! { pub enum Origin for Test where system = frame_system {} } -pub trait Trait { +pub trait OtherTrait { + type OtherEvent; +} + +pub trait Trait: OtherTrait where Self::OtherEvent: Into { type Event; type BlockNumber; type AccountId: 'static + Default + Decode; - type Origin: From> + Into, Self::Origin>>; + type Origin: From> + + Into, Self::Origin>>; } #[derive(Clone, Eq, PartialEq)] pub struct Test; impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -68,6 +89,10 @@ impl frame_system::Trait for Test { type Event = (); type BlockHashCount = (); type MaximumBlockWeight = (); + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = (); type MaximumBlockLength = (); type AvailableBlockRatio = (); type Version = (); @@ -75,6 +100,7 @@ impl frame_system::Trait for Test { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } impl Trait for Test { @@ -84,49 +110,73 @@ impl Trait for Test { type AccountId = u64; } -// This function basically just builds a genesis storage key/value store according to -// our desired mockup. +impl OtherTrait for Test { + type OtherEvent = (); +} + fn new_test_ext() -> sp_io::TestExternalities { frame_system::GenesisConfig::default().build_storage::().unwrap().into() } benchmarks!{ + where_clause { where ::OtherEvent: Into<::Event> } + _ { // Define a common range for `b`. let b in 1 .. 1000 => (); } - dummy { + set_value { let b in ...; - let caller = account("caller", 0, 0); + let caller = account::("caller", 0, 0); }: _ (RawOrigin::Signed(caller), b.into()) + verify { + assert_eq!(Value::get(), Some(b)); + } other_name { let b in ...; - let caller = account("caller", 0, 0); - }: other_dummy (RawOrigin::Signed(caller), b.into()) + }: dummy (RawOrigin::None, b.into()) sort_vector { - let x in 0 .. 10000; + let x in 1 .. 10000; let mut m = Vec::::new(); - for i in 0..x { + for i in (0..x).rev() { m.push(i); } }: { m.sort(); + } verify { + ensure!(m[0] == 0, "You forgot to sort!") + } + + bad_origin { + let b in ...; + let caller = account::("caller", 0, 0); + }: dummy (RawOrigin::Signed(caller), b.into()) + + bad_verify { + let x in 1 .. 10000; + let mut m = Vec::::new(); + for i in (0..x).rev() { + m.push(i); + } + }: { } + verify { + ensure!(m[0] == 0, "You forgot to sort!") } } #[test] fn benchmarks_macro_works() { - // Check benchmark creation for `dummy`. - let selected_benchmark = SelectedBenchmark::dummy; + // Check benchmark creation for `set_value`. + let selected = SelectedBenchmark::set_value; - let components = >::components(&selected_benchmark); + let components = >::components(&selected); assert_eq!(components, vec![(BenchmarkParameter::b, 1, 1000)]); let closure = >::instance( - &selected_benchmark, + &selected, &[(BenchmarkParameter::b, 1)], ).expect("failed to create closure"); @@ -138,31 +188,57 @@ fn benchmarks_macro_works() { #[test] fn benchmarks_macro_rename_works() { // Check benchmark creation for `other_dummy`. - let selected_benchmark = SelectedBenchmark::other_name; - let components = >::components(&selected_benchmark); + let selected = SelectedBenchmark::other_name; + let components = >::components(&selected); assert_eq!(components, vec![(BenchmarkParameter::b, 1, 1000)]); let closure = >::instance( - &selected_benchmark, + &selected, &[(BenchmarkParameter::b, 1)], ).expect("failed to create closure"); new_test_ext().execute_with(|| { - assert_eq!(closure(), Err("Bad origin")); + assert_ok!(closure()); }); } #[test] fn benchmarks_macro_works_for_non_dispatchable() { - let selected_benchmark = SelectedBenchmark::sort_vector; + let selected = SelectedBenchmark::sort_vector; - let components = >::components(&selected_benchmark); - assert_eq!(components, vec![(BenchmarkParameter::x, 0, 10000)]); + let components = >::components(&selected); + assert_eq!(components, vec![(BenchmarkParameter::x, 1, 10000)]); let closure = >::instance( - &selected_benchmark, + &selected, &[(BenchmarkParameter::x, 1)], ).expect("failed to create closure"); assert_eq!(closure(), Ok(())); } + +#[test] +fn benchmarks_macro_verify_works() { + // Check postcondition for benchmark `set_value` is valid. + let selected = SelectedBenchmark::set_value; + + let closure = >::verify( + &selected, + &[(BenchmarkParameter::b, 1)], + ).expect("failed to create closure"); + + new_test_ext().execute_with(|| { + assert_ok!(closure()); + }); +} + +#[test] +fn benchmarks_generate_unit_tests() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_set_value::()); + assert_ok!(test_benchmark_other_name::()); + assert_ok!(test_benchmark_sort_vector::()); + assert_err!(test_benchmark_bad_origin::(), "Bad origin"); + assert_err!(test_benchmark_bad_verify::(), "You forgot to sort!"); + }); +} diff --git a/frame/benchmarking/src/utils.rs b/frame/benchmarking/src/utils.rs index a6f262eab99ec87f9ecd9597fb411e0772587a1d..7f9d9121100e3b45dc78ae6497537335c6ee3919 100644 --- a/frame/benchmarking/src/utils.rs +++ b/frame/benchmarking/src/utils.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Interfaces, types and utils for benchmarking a FRAME runtime. @@ -43,7 +44,16 @@ pub struct BenchmarkBatch { /// Results from running benchmarks on a FRAME pallet. /// Contains duration of the function call in nanoseconds along with the benchmark parameters /// used for that benchmark result. -pub type BenchmarkResults = (Vec<(BenchmarkParameter, u32)>, u128, u128); +#[derive(Encode, Decode, Default, Clone, PartialEq, Debug)] +pub struct BenchmarkResults { + pub components: Vec<(BenchmarkParameter, u32)>, + pub extrinsic_time: u128, + pub storage_root_time: u128, + pub reads: u32, + pub repeat_reads: u32, + pub writes: u32, + pub repeat_writes: u32, +} sp_api::decl_runtime_apis! { /// Runtime api for benchmarking a FRAME runtime. @@ -82,6 +92,20 @@ pub trait Benchmarking { fn commit_db(&mut self) { self.commit() } + + /// Get the read/write count + fn read_write_count(&self) -> (u32, u32, u32, u32) { + self.read_write_count() + } + + /// Reset the read/write count + fn reset_read_write_count(&mut self) { + self.reset_read_write_count() + } + + fn set_whitelist(&mut self, new: Vec>) { + self.set_whitelist(new) + } } /// The pallet benchmarking trait. @@ -105,6 +129,7 @@ pub trait Benchmarking { highest_range_values: &[u32], steps: &[u32], repeat: u32, + whitelist: &[Vec] ) -> Result, &'static str>; } @@ -113,8 +138,11 @@ pub trait BenchmarkingSetup { /// Return the components and their ranges which should be tested in this benchmark. fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)>; - /// Set up the storage, and prepare a closure to test in a single run of the benchmark. + /// Set up the storage, and prepare a closure to run the benchmark. fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result Result<(), &'static str>>, &'static str>; + + /// Set up the storage, and prepare a closure to test and verify the benchmark + fn verify(&self, components: &[(BenchmarkParameter, u32)]) -> Result Result<(), &'static str>>, &'static str>; } /// The required setup for creating a benchmark. @@ -122,8 +150,11 @@ pub trait BenchmarkingSetupInstance { /// Return the components and their ranges which should be tested in this benchmark. fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)>; - /// Set up the storage, and prepare a closure to test in a single run of the benchmark. + /// Set up the storage, and prepare a closure to run the benchmark. fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result Result<(), &'static str>>, &'static str>; + + /// Set up the storage, and prepare a closure to test and verify the benchmark + fn verify(&self, components: &[(BenchmarkParameter, u32)]) -> Result Result<(), &'static str>>, &'static str>; } /// Grab an account, seeded by a name and index. diff --git a/frame/collective/Cargo.toml b/frame/collective/Cargo.toml index 113705c2c8b90c95f068971bb0f810c7b401debc..c1b2f01089c59a4d61e265dc1165a253c86673c1 100644 --- a/frame/collective/Cargo.toml +++ b/frame/collective/Cargo.toml @@ -1,27 +1,30 @@ [package] name = "pallet-collective" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Collective system: Members of a set of account IDs can make their collective feelings known through dispatched calls from one of two specialized origins." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/core" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -frame-benchmarking = { version = "2.0.0-alpha.5", default-features = false, path = "../benchmarking", optional = true } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/core" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +frame-benchmarking = { version = "2.0.0-rc4", default-features = false, path = "../benchmarking", optional = true } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } [dev-dependencies] hex-literal = "0.2.1" -pallet-balances = { version = "2.0.0-alpha.5", path = "../balances" } +pallet-balances = { version = "2.0.0-rc4", path = "../balances" } [features] default = ["std"] @@ -40,6 +43,3 @@ runtime-benchmarks = [ "sp-runtime/runtime-benchmarks", "frame-system/runtime-benchmarks", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/collective/src/benchmarking.rs b/frame/collective/src/benchmarking.rs index 51db4ee109b06bc550759574432b3170f630e907..b9558d8c8ce1c54badba18e5de6558f13591d54d 100644 --- a/frame/collective/src/benchmarking.rs +++ b/frame/collective/src/benchmarking.rs @@ -1,185 +1,652 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Staking pallet benchmarking. use super::*; use frame_system::RawOrigin as SystemOrigin; +use frame_system::EventRecord; use frame_benchmarking::{benchmarks_instance, account}; +use sp_runtime::traits::Bounded; +use sp_std::mem::size_of; +use frame_system::Call as SystemCall; use frame_system::Module as System; use crate::Module as Collective; const SEED: u32 = 0; +const MAX_BYTES: u32 = 1_024; + +fn assert_last_event, I: Instance>(generic_event: >::Event) { + let events = System::::events(); + let system_event: ::Event = generic_event.into(); + // compare to the last event record + let EventRecord { event, .. } = &events[events.len() - 1]; + assert_eq!(event, &system_event); +} + benchmarks_instance! { - _{ - // User account seed. - let u in 1 .. 1000 => (); - // Old members. - let n in 1 .. 1000 => (); - // New members. - let m in 1 .. 1000 => (); - // Existing proposals. - let p in 1 .. 100 => (); - } + _{ } set_members { - let m in ...; - let n in ...; + let m in 1 .. MAX_MEMBERS; + let n in 1 .. MAX_MEMBERS; + let p in 1 .. T::MaxProposals::get(); - // Construct `new_members`. - // It should influence timing since it will sort this vector. - let mut new_members = vec![]; + // Set old members. + // We compute the difference of old and new members, so it should influence timing. + let mut old_members = vec![]; + let mut last_old_member = T::AccountId::default(); for i in 0 .. m { - let member = account("member", i, SEED); - new_members.push(member); + last_old_member = account("old member", i, SEED); + old_members.push(last_old_member.clone()); + } + let old_members_count = old_members.len() as u32; + + Collective::::set_members( + SystemOrigin::Root.into(), + old_members.clone(), + Some(last_old_member.clone()), + MAX_MEMBERS, + )?; + + // Set a high threshold for proposals passing so that they stay around. + let threshold = m.max(2); + // Length of the proposals should be irrelevant to `set_members`. + let length = 100; + for i in 0 .. p { + // Proposals should be different so that different proposal hashes are generated + let proposal: T::Proposal = SystemCall::::remark(vec![i as u8; length]).into(); + Collective::::propose( + SystemOrigin::Signed(last_old_member.clone()).into(), + threshold, + Box::new(proposal.clone()), + MAX_BYTES, + )?; + let hash = T::Hashing::hash_of(&proposal); + // Vote on the proposal to increase state relevant for `set_members`. + // Not voting for `last_old_member` because they proposed and not voting for the first member + // to keep the proposal from passing. + for j in 2 .. m - 1 { + let voter = &old_members[j as usize]; + let approve = true; + Collective::::vote( + SystemOrigin::Signed(voter.clone()).into(), + hash, + i, + approve, + )?; + } } - // Set old members. - // We compute the difference of old and new members, so it should influence timing. - let mut old_members = vec![]; + // Construct `new_members`. + // It should influence timing since it will sort this vector. + let mut new_members = vec![]; + let mut last_member = T::AccountId::default(); for i in 0 .. n { - let old_member = account("old member", i, SEED); - old_members.push(old_member); + last_member = account("member", i, SEED); + new_members.push(last_member.clone()); } - let prime = Some(account("prime", 0, SEED)); + }: _(SystemOrigin::Root, new_members.clone(), Some(last_member), MAX_MEMBERS) + verify { + new_members.sort(); + assert_eq!(Collective::::members(), new_members); + } - Collective::::set_members(SystemOrigin::Root.into(), old_members, prime.clone())?; + execute { + let m in 1 .. MAX_MEMBERS; + let b in 1 .. MAX_BYTES; - }: _(SystemOrigin::Root, new_members, prime) + let bytes_in_storage = b + size_of::() as u32; - execute { - let u in ...; + // Construct `members`. + let mut members = vec![]; + for i in 0 .. m - 1 { + let member = account("member", i, SEED); + members.push(member); + } - let caller: T::AccountId = account("caller", u, SEED); - let proposal: T::Proposal = Call::::close(Default::default(), Default::default()).into(); + let caller: T::AccountId = account("caller", 0, SEED); + members.push(caller.clone()); - Collective::::set_members(SystemOrigin::Root.into(), vec![caller.clone()], None)?; + Collective::::set_members(SystemOrigin::Root.into(), members, None, MAX_MEMBERS)?; - }: _(SystemOrigin::Signed(caller), Box::new(proposal)) + let proposal: T::Proposal = SystemCall::::remark(vec![1; b as usize]).into(); - propose { - let u in ...; + }: _(SystemOrigin::Signed(caller), Box::new(proposal.clone()), bytes_in_storage) + verify { + let proposal_hash = T::Hashing::hash_of(&proposal); + // Note that execution fails due to mis-matched origin + assert_last_event::( + RawEvent::MemberExecuted(proposal_hash, Err(DispatchError::BadOrigin)).into() + ); + } - let caller: T::AccountId = account("caller", u, SEED); - let proposal: T::Proposal = Call::::close(Default::default(), Default::default()).into(); + // This tests when execution would happen immediately after proposal + propose_execute { + let m in 1 .. MAX_MEMBERS; + let b in 1 .. MAX_BYTES; - Collective::::set_members(SystemOrigin::Root.into(), vec![caller.clone()], None)?; + let bytes_in_storage = b + size_of::() as u32; - let member_count = 0; + // Construct `members`. + let mut members = vec![]; + for i in 0 .. m - 1 { + let member = account("member", i, SEED); + members.push(member); + } - }: _(SystemOrigin::Signed(caller), member_count, Box::new(proposal.into())) + let caller: T::AccountId = account("caller", 0, SEED); + members.push(caller.clone()); - propose_else_branch { - let u in ...; - let p in ...; + Collective::::set_members(SystemOrigin::Root.into(), members, None, MAX_MEMBERS)?; - let caller: T::AccountId = account("caller", u, SEED); - let proposal: T::Proposal = Call::::close(Default::default(), Default::default()).into(); + let proposal: T::Proposal = SystemCall::::remark(vec![1; b as usize]).into(); + let threshold = 1; - Collective::::set_members(SystemOrigin::Root.into(), vec![caller.clone()], None)?; + }: propose(SystemOrigin::Signed(caller), threshold, Box::new(proposal.clone()), bytes_in_storage) + verify { + let proposal_hash = T::Hashing::hash_of(&proposal); + // Note that execution fails due to mis-matched origin + assert_last_event::( + RawEvent::Executed(proposal_hash, Err(DispatchError::BadOrigin)).into() + ); + } - let member_count = 3; + // This tests when proposal is created and queued as "proposed" + propose_proposed { + let m in 2 .. MAX_MEMBERS; + let p in 1 .. T::MaxProposals::get(); + let b in 1 .. MAX_BYTES; - // Add previous proposals. - for i in 0 .. p { - let proposal: T::Proposal = Call::::close(Default::default(), (i + 1).into()).into(); - Collective::::propose(SystemOrigin::Signed(caller.clone()).into(), member_count.clone(), Box::new(proposal.into()))?; + let bytes_in_storage = b + size_of::() as u32; + + // Construct `members`. + let mut members = vec![]; + for i in 0 .. m - 1 { + let member = account("member", i, SEED); + members.push(member); } + let caller: T::AccountId = account("caller", 0, SEED); + members.push(caller.clone()); + Collective::::set_members(SystemOrigin::Root.into(), members, None, MAX_MEMBERS)?; - }: propose(SystemOrigin::Signed(caller), member_count, Box::new(proposal.into())) + let threshold = m; + // Add previous proposals. + for i in 0 .. p - 1 { + // Proposals should be different so that different proposal hashes are generated + let proposal: T::Proposal = SystemCall::::remark(vec![i as u8; b as usize]).into(); + Collective::::propose( + SystemOrigin::Signed(caller.clone()).into(), + threshold, + Box::new(proposal), + bytes_in_storage, + )?; + } - vote { - let u in ...; + assert_eq!(Collective::::proposals().len(), (p - 1) as usize); - let caller1: T::AccountId = account("caller1", u, SEED); - let caller2: T::AccountId = account("caller2", u, SEED); + let proposal: T::Proposal = SystemCall::::remark(vec![p as u8; b as usize]).into(); - let proposal: Box = Box::new(Call::::close(Default::default(), Default::default()).into()); + }: propose(SystemOrigin::Signed(caller.clone()), threshold, Box::new(proposal.clone()), bytes_in_storage) + verify { + // New proposal is recorded + assert_eq!(Collective::::proposals().len(), p as usize); let proposal_hash = T::Hashing::hash_of(&proposal); + assert_last_event::(RawEvent::Proposed(caller, p - 1, proposal_hash, threshold).into()); + } + + vote { + // We choose 5 as a minimum so we always trigger a vote in the voting loop (`for j in ...`) + let m in 5 .. MAX_MEMBERS; + + let p = T::MaxProposals::get(); + let b = MAX_BYTES; + let bytes_in_storage = b + size_of::() as u32; + + // Construct `members`. + let mut members = vec![]; + let proposer: T::AccountId = account("proposer", 0, SEED); + members.push(proposer.clone()); + for i in 1 .. m - 1 { + let member = account("member", i, SEED); + members.push(member); + } + let voter: T::AccountId = account("voter", 0, SEED); + members.push(voter.clone()); + Collective::::set_members(SystemOrigin::Root.into(), members.clone(), None, MAX_MEMBERS)?; - Collective::::set_members(SystemOrigin::Root.into(), vec![caller1.clone(), caller2.clone()], None)?; + // Threshold is 1 less than the number of members so that one person can vote nay + let threshold = m - 1; - let member_count = 3; - Collective::::propose(SystemOrigin::Signed(caller1.clone()).into(), member_count, proposal)?; + // Add previous proposals + let mut last_hash = T::Hash::default(); + for i in 0 .. p { + // Proposals should be different so that different proposal hashes are generated + let proposal: T::Proposal = SystemCall::::remark(vec![i as u8; b as usize]).into(); + Collective::::propose( + SystemOrigin::Signed(proposer.clone()).into(), + threshold, + Box::new(proposal.clone()), + bytes_in_storage, + )?; + last_hash = T::Hashing::hash_of(&proposal); + } - let index = 0; + let index = p - 1; + // Have almost everyone vote aye on last proposal, while keeping it from passing. + // Proposer already voted aye so we start at 1. + for j in 1 .. m - 3 { + let voter = &members[j as usize]; + let approve = true; + Collective::::vote( + SystemOrigin::Signed(voter.clone()).into(), + last_hash.clone(), + index, + approve, + )?; + } + // Voter votes aye without resolving the vote. let approve = true; + Collective::::vote( + SystemOrigin::Signed(voter.clone()).into(), + last_hash.clone(), + index, + approve, + )?; - }: _(SystemOrigin::Signed(caller2), proposal_hash, index, approve) + assert_eq!(Collective::::proposals().len(), p as usize); - vote_not_approve { - let u in ...; + // Voter switches vote to nay, but does not kill the vote, just updates + inserts + let approve = false; - let caller1: T::AccountId = account("caller1", u, SEED); - let caller2: T::AccountId = account("caller2", u, SEED); + }: _(SystemOrigin::Signed(voter), last_hash.clone(), index, approve) + verify { + // All proposals exist and the last proposal has just been updated. + assert_eq!(Collective::::proposals().len(), p as usize); + let voting = Collective::::voting(&last_hash).ok_or(Error::::ProposalMissing)?; + assert_eq!(voting.ayes.len(), (m - 3) as usize); + assert_eq!(voting.nays.len(), 1); + } - let proposal: Box = Box::new(Call::::close(Default::default(), Default::default()).into()); - let proposal_hash = T::Hashing::hash_of(&proposal); + close_early_disapproved { + // We choose 4 as a minimum so we always trigger a vote in the voting loop (`for j in ...`) + let m in 4 .. MAX_MEMBERS; + let p in 1 .. T::MaxProposals::get(); + let b in 1 .. MAX_BYTES; + + let bytes_in_storage = b + size_of::() as u32; + + // Construct `members`. + let mut members = vec![]; + let proposer: T::AccountId = account("proposer", 0, SEED); + members.push(proposer.clone()); + for i in 1 .. m - 1 { + let member = account("member", i, SEED); + members.push(member); + } + let voter: T::AccountId = account("voter", 0, SEED); + members.push(voter.clone()); + Collective::::set_members(SystemOrigin::Root.into(), members.clone(), None, MAX_MEMBERS)?; + + // Threshold is total members so that one nay will disapprove the vote + let threshold = m; - Collective::::set_members(SystemOrigin::Root.into(), vec![caller1.clone(), caller2.clone()], None)?; + // Add previous proposals + let mut last_hash = T::Hash::default(); + for i in 0 .. p { + // Proposals should be different so that different proposal hashes are generated + let proposal: T::Proposal = SystemCall::::remark(vec![i as u8; b as usize]).into(); + Collective::::propose( + SystemOrigin::Signed(proposer.clone()).into(), + threshold, + Box::new(proposal.clone()), + bytes_in_storage, + )?; + last_hash = T::Hashing::hash_of(&proposal); + } - let member_count = 3; - Collective::::propose(SystemOrigin::Signed(caller1.clone()).into(), member_count, proposal)?; + let index = p - 1; + // Have most everyone vote aye on last proposal, while keeping it from passing. + // Proposer already voted aye so we start at 1. + for j in 1 .. m - 2 { + let voter = &members[j as usize]; + let approve = true; + Collective::::vote( + SystemOrigin::Signed(voter.clone()).into(), + last_hash.clone(), + index, + approve, + )?; + } + // Voter votes aye without resolving the vote. + let approve = true; + Collective::::vote( + SystemOrigin::Signed(voter.clone()).into(), + last_hash.clone(), + index, + approve, + )?; - let index = 0; + assert_eq!(Collective::::proposals().len(), p as usize); + + // Voter switches vote to nay, which kills the vote let approve = false; + Collective::::vote( + SystemOrigin::Signed(voter.clone()).into(), + last_hash.clone(), + index, + approve, + )?; + + }: close(SystemOrigin::Signed(voter), last_hash.clone(), index, Weight::max_value(), bytes_in_storage) + verify { + // The last proposal is removed. + assert_eq!(Collective::::proposals().len(), (p - 1) as usize); + assert_last_event::(RawEvent::Disapproved(last_hash).into()); + } - }: vote(SystemOrigin::Signed(caller2), proposal_hash, index, approve) + close_early_approved { + // We choose 4 as a minimum so we always trigger a vote in the voting loop (`for j in ...`) + let m in 4 .. MAX_MEMBERS; + let p in 1 .. T::MaxProposals::get(); + let b in 1 .. MAX_BYTES; - vote_approved { - let u in ...; + let bytes_in_storage = b + size_of::() as u32; - let caller1: T::AccountId = account("caller1", u, SEED); - let caller2: T::AccountId = account("caller2", u, SEED); - - let proposal: Box = Box::new(Call::::close(Default::default(), Default::default()).into()); - let proposal_hash = T::Hashing::hash_of(&proposal); + // Construct `members`. + let mut members = vec![]; + for i in 0 .. m - 1 { + let member = account("member", i, SEED); + members.push(member); + } + let caller: T::AccountId = account("caller", 0, SEED); + members.push(caller.clone()); + Collective::::set_members(SystemOrigin::Root.into(), members.clone(), None, MAX_MEMBERS)?; - Collective::::set_members(SystemOrigin::Root.into(), vec![caller1.clone(), caller2.clone()], None)?; + // Threshold is 2 so any two ayes will approve the vote + let threshold = 2; + + // Add previous proposals + let mut last_hash = T::Hash::default(); + for i in 0 .. p { + // Proposals should be different so that different proposal hashes are generated + let proposal: T::Proposal = SystemCall::::remark(vec![i as u8; b as usize]).into(); + Collective::::propose( + SystemOrigin::Signed(caller.clone()).into(), + threshold, + Box::new(proposal.clone()), + bytes_in_storage, + )?; + last_hash = T::Hashing::hash_of(&proposal); + } + + // Caller switches vote to nay on their own proposal, allowing them to be the deciding approval vote + Collective::::vote( + SystemOrigin::Signed(caller.clone()).into(), + last_hash.clone(), + p - 1, + false, + )?; + + // Have almost everyone vote nay on last proposal, while keeping it from failing. + for j in 2 .. m - 1 { + let voter = &members[j as usize]; + let approve = false; + Collective::::vote( + SystemOrigin::Signed(voter.clone()).into(), + last_hash.clone(), + p - 1, + approve, + )?; + } - let member_count = 2; - Collective::::propose(SystemOrigin::Signed(caller1.clone()).into(), member_count, proposal)?; + // Member zero is the first aye + Collective::::vote( + SystemOrigin::Signed(members[0].clone()).into(), + last_hash.clone(), + p - 1, + true, + )?; - let index = 0; + assert_eq!(Collective::::proposals().len(), p as usize); + + // Caller switches vote to aye, which passes the vote + let index = p - 1; let approve = true; + Collective::::vote( + SystemOrigin::Signed(caller.clone()).into(), + last_hash.clone(), + index, approve, + )?; + + }: close(SystemOrigin::Signed(caller), last_hash.clone(), index, Weight::max_value(), bytes_in_storage) + verify { + // The last proposal is removed. + assert_eq!(Collective::::proposals().len(), (p - 1) as usize); + assert_last_event::(RawEvent::Executed(last_hash, Err(DispatchError::BadOrigin)).into()); + } - }: vote(SystemOrigin::Signed(caller2), proposal_hash, index, approve) + close_disapproved { + // We choose 4 as a minimum so we always trigger a vote in the voting loop (`for j in ...`) + let m in 4 .. MAX_MEMBERS; + let p in 1 .. T::MaxProposals::get(); + let b in 1 .. MAX_BYTES; - close { - let u in ...; + let bytes_in_storage = b + size_of::() as u32; - let caller1: T::AccountId = account("caller1", u, SEED); - let caller2: T::AccountId = account("caller2", u, SEED); - - let proposal: Box = Box::new(Call::::close(Default::default(), Default::default()).into()); - let proposal_hash = T::Hashing::hash_of(&proposal); + // Construct `members`. + let mut members = vec![]; + for i in 0 .. m - 1 { + let member = account("member", i, SEED); + members.push(member); + } + let caller: T::AccountId = account("caller", 0, SEED); + members.push(caller.clone()); + Collective::::set_members( + SystemOrigin::Root.into(), + members.clone(), + Some(caller.clone()), + MAX_MEMBERS, + )?; + + // Threshold is one less than total members so that two nays will disapprove the vote + let threshold = m - 1; + + // Add proposals + let mut last_hash = T::Hash::default(); + for i in 0 .. p { + // Proposals should be different so that different proposal hashes are generated + let proposal: T::Proposal = SystemCall::::remark(vec![i as u8; b as usize]).into(); + Collective::::propose( + SystemOrigin::Signed(caller.clone()).into(), + threshold, + Box::new(proposal.clone()), + bytes_in_storage, + )?; + last_hash = T::Hashing::hash_of(&proposal); + } - Collective::::set_members(SystemOrigin::Root.into(), vec![caller1.clone(), caller2.clone()], None)?; - let member_count = 2; - Collective::::propose(SystemOrigin::Signed(caller1.clone()).into(), member_count, proposal)?; + let index = p - 1; + // Have almost everyone vote aye on last proposal, while keeping it from passing. + // A few abstainers will be the nay votes needed to fail the vote. + for j in 2 .. m - 1 { + let voter = &members[j as usize]; + let approve = true; + Collective::::vote( + SystemOrigin::Signed(voter.clone()).into(), + last_hash.clone(), + index, + approve, + )?; + } - let index = 0; - let approve = true; + // caller is prime, prime votes nay + Collective::::vote( + SystemOrigin::Signed(caller.clone()).into(), + last_hash.clone(), + index, + false, + )?; + + System::::set_block_number(T::BlockNumber::max_value()); + assert_eq!(Collective::::proposals().len(), p as usize); + + // Prime nay will close it as disapproved + }: close(SystemOrigin::Signed(caller), last_hash, index, Weight::max_value(), bytes_in_storage) + verify { + assert_eq!(Collective::::proposals().len(), (p - 1) as usize); + assert_last_event::(RawEvent::Disapproved(last_hash).into()); + } - let vote_end = T::MotionDuration::get() + 1u32.into(); - System::::set_block_number(vote_end); + close_approved { + // We choose 4 as a minimum so we always trigger a vote in the voting loop (`for j in ...`) + let m in 4 .. MAX_MEMBERS; + let p in 1 .. T::MaxProposals::get(); + let b in 1 .. MAX_BYTES; - }: _(SystemOrigin::Signed(caller2), proposal_hash, index) + let bytes_in_storage = b + size_of::() as u32; + + // Construct `members`. + let mut members = vec![]; + for i in 0 .. m - 1 { + let member = account("member", i, SEED); + members.push(member); + } + let caller: T::AccountId = account("caller", 0, SEED); + members.push(caller.clone()); + Collective::::set_members( + SystemOrigin::Root.into(), + members.clone(), + Some(caller.clone()), + MAX_MEMBERS, + )?; + + // Threshold is two, so any two ayes will pass the vote + let threshold = 2; + + // Add proposals + let mut last_hash = T::Hash::default(); + for i in 0 .. p { + // Proposals should be different so that different proposal hashes are generated + let proposal: T::Proposal = SystemCall::::remark(vec![i as u8; b as usize]).into(); + Collective::::propose( + SystemOrigin::Signed(caller.clone()).into(), + threshold, + Box::new(proposal.clone()), + bytes_in_storage, + )?; + last_hash = T::Hashing::hash_of(&proposal); + } + + // Have almost everyone vote nay on last proposal, while keeping it from failing. + // A few abstainers will be the aye votes needed to pass the vote. + for j in 2 .. m - 1 { + let voter = &members[j as usize]; + let approve = false; + Collective::::vote( + SystemOrigin::Signed(voter.clone()).into(), + last_hash.clone(), + p - 1, + approve + )?; + } + + // caller is prime, prime already votes aye by creating the proposal + System::::set_block_number(T::BlockNumber::max_value()); + assert_eq!(Collective::::proposals().len(), p as usize); + + // Prime aye will close it as approved + }: close(SystemOrigin::Signed(caller), last_hash, p - 1, Weight::max_value(), bytes_in_storage) + verify { + assert_eq!(Collective::::proposals().len(), (p - 1) as usize); + assert_last_event::(RawEvent::Executed(last_hash, Err(DispatchError::BadOrigin)).into()); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::tests::{new_test_ext, Test}; + use frame_support::assert_ok; + + #[test] + fn set_members() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_set_members::()); + }); + } + + #[test] + fn execute() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_execute::()); + }); + } + + #[test] + fn propose_execute() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_propose_execute::()); + }); + } + + #[test] + fn propose_proposed() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_propose_proposed::()); + }); + } + + #[test] + fn vote() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_vote::()); + }); + } + + #[test] + fn close_early_disapproved() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_close_early_disapproved::()); + }); + } + + #[test] + fn close_early_approved() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_close_early_approved::()); + }); + } + + #[test] + fn close_disapproved() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_close_disapproved::()); + }); + } + + #[test] + fn close_approved() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_close_approved::()); + }); + } } diff --git a/frame/collective/src/lib.rs b/frame/collective/src/lib.rs index 49c1bd38914930a6e1cfb9d229b7f1e9aef0dac7..e2567d0477585f180d571c14020898f4053d3159 100644 --- a/frame/collective/src/lib.rs +++ b/frame/collective/src/lib.rs @@ -1,24 +1,27 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Collective system: Members of a set of account IDs can make their collective feelings known //! through dispatched calls from one of two specialized origins. //! //! The membership can be provided in one of two ways: either directly, using the Root-dispatchable //! function `set_members`, or indirectly, through implementing the `ChangeMembers`. +//! The pallet assumes that the amount of members stays at or below `MAX_MEMBERS` for its weight +//! calculations, but enforces this neither in `set_members` nor in `change_members_sorted`. //! //! A "prime" member may be set allowing their vote to act as the default vote in case of any //! abstentions after the voting period. @@ -38,13 +41,19 @@ use sp_std::{prelude::*, result}; use sp_core::u32_trait::Value as U32; -use sp_runtime::RuntimeDebug; -use sp_runtime::traits::Hash; -use frame_support::weights::SimpleDispatchInfo; +use sp_io::storage; +use sp_runtime::{RuntimeDebug, traits::Hash}; + use frame_support::{ - dispatch::{Dispatchable, Parameter}, codec::{Encode, Decode}, - traits::{Get, ChangeMembers, InitializeMembers, EnsureOrigin}, decl_module, decl_event, - decl_storage, decl_error, ensure, + codec::{Decode, Encode}, + debug, decl_error, decl_event, decl_module, decl_storage, + dispatch::{ + DispatchError, DispatchResult, DispatchResultWithPostInfo, Dispatchable, Parameter, + PostDispatchInfo, + }, + ensure, + traits::{ChangeMembers, EnsureOrigin, Get, InitializeMembers}, + weights::{DispatchClass, GetDispatchInfo, Weight}, }; use frame_system::{self as system, ensure_signed, ensure_root}; @@ -60,22 +69,62 @@ pub type ProposalIndex = u32; /// vote exactly once, therefore also the number of votes for any given motion. pub type MemberCount = u32; +/// The maximum number of members supported by the pallet. Used for weight estimation. +/// +/// NOTE: +/// + Benchmarks will need to be re-run and weights adjusted if this changes. +/// + This pallet assumes that dependents keep to the limit without enforcing it. +pub const MAX_MEMBERS: MemberCount = 100; + +pub trait WeightInfo { + fn set_members(m: u32, n: u32, p: u32, ) -> Weight; + fn execute(m: u32, b: u32, ) -> Weight; + fn propose_execute(m: u32, b: u32, ) -> Weight; + fn propose_proposed(m: u32, p: u32, b: u32, ) -> Weight; + fn vote(m: u32, ) -> Weight; + fn close_early_disapproved(m: u32, p: u32, b: u32, ) -> Weight; + fn close_early_approved(m: u32, p: u32, b: u32, ) -> Weight; + fn close_disapproved(m: u32, p: u32, b: u32, ) -> Weight; + fn close_approved(m: u32, p: u32, b: u32, ) -> Weight; +} + +impl WeightInfo for () { + fn set_members(_m: u32, _n: u32, _p: u32, ) -> Weight { 1_000_000_000 } + fn execute(_m: u32, _b: u32, ) -> Weight { 1_000_000_000 } + fn propose_execute(_m: u32, _b: u32, ) -> Weight { 1_000_000_000 } + fn propose_proposed(_m: u32, _p: u32, _b: u32, ) -> Weight { 1_000_000_000 } + fn vote(_m: u32, ) -> Weight { 1_000_000_000 } + fn close_early_disapproved(_m: u32, _p: u32, _b: u32, ) -> Weight { 1_000_000_000 } + fn close_early_approved(_m: u32, _p: u32, _b: u32, ) -> Weight { 1_000_000_000 } + fn close_disapproved(_m: u32, _p: u32, _b: u32, ) -> Weight { 1_000_000_000 } + fn close_approved(_m: u32, _p: u32, _b: u32, ) -> Weight { 1_000_000_000 } +} + pub trait Trait: frame_system::Trait { /// The outer origin type. type Origin: From>; /// The outer call dispatch type. - type Proposal: Parameter + Dispatchable>::Origin> + From>; + type Proposal: Parameter + + Dispatchable>::Origin, PostInfo=PostDispatchInfo> + + From> + + GetDispatchInfo; /// The outer event type. type Event: From> + Into<::Event>; /// The time-out for council motions. type MotionDuration: Get; + + /// Maximum number of proposals allowed to be active in parallel. + type MaxProposals: Get; + + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; } /// Origin for the collective module. -#[derive(PartialEq, Eq, Clone, RuntimeDebug)] +#[derive(PartialEq, Eq, Clone, RuntimeDebug, Encode, Decode)] pub enum RawOrigin { /// It has been condoned by a given number of members of the collective from a given total. Members(MemberCount, MemberCount), @@ -143,11 +192,11 @@ decl_event! { Approved(Hash), /// A motion was not approved by the required threshold. Disapproved(Hash), - /// A motion was executed; `bool` is true if returned without error. - Executed(Hash, bool), - /// A single member did some action; `bool` is true if returned without error. - MemberExecuted(Hash, bool), - /// A proposal was closed after its duration was up. + /// A motion was executed; result will be `Ok` if it returned without error. + Executed(Hash, DispatchResult), + /// A single member did some action; result will be `Ok` if it returned without error. + MemberExecuted(Hash, DispatchResult), + /// A proposal was closed because its threshold was reached or after its duration was up. Closed(Hash, MemberCount, MemberCount), } } @@ -166,14 +215,154 @@ decl_error! { DuplicateVote, /// Members are already initialized! AlreadyInitialized, - /// The close call is made too early, before the end of the voting. + /// The close call was made too early, before the end of the voting. TooEarly, + /// There can only be a maximum of `MaxProposals` active proposals. + TooManyProposals, + /// The given weight bound for the proposal was too low. + WrongProposalWeight, + /// The given length bound for the proposal was too low. + WrongProposalLength, } } -// Note: this module is not benchmarked. The weights are obtained based on the similarity of the -// executed logic with other democracy function. Note that councillor operations are assigned to the -// operational class. +/// Functions for calcuating the weight of dispatchables. +mod weight_for { + use frame_support::{traits::Get, weights::Weight}; + use super::{Trait, Instance}; + + /// Calculate the weight for `set_members`. + /// + /// Based on benchmark: + /// 0 + M * 20.47 + N * 0.109 + P * 26.29 µs (min squares analysis) + /// + /// Note: The complexity of `set_members` is quadratic (`O(MP + N)`), so the linear approximation + /// of the benchmark is not always permissible. It is here, though, because the linear approximation + /// covered the range of possible values and we estimate weight via the worst case (max paramter + /// values) before execution so we can be sure that we are only overestimating. + pub(crate) fn set_members, I: Instance>( + old_count: Weight, + new_count: Weight, + proposals: Weight, + ) -> Weight { + let db = T::DbWeight::get(); + db.reads_writes(1, 1) // mutate `Members` + .saturating_add(db.writes(1)) // set `Prime` + .saturating_add(db.reads(1)) // read `Proposals` + .saturating_add(db.reads_writes(proposals, proposals)) // update votes (`Voting`) + .saturating_add(old_count.saturating_mul(21_000_000)) // M + .saturating_add(new_count.saturating_mul(110_000)) // N + .saturating_add(proposals.saturating_mul(27_000_000)) // P + } + + /// Calculate the weight for `execute`. + /// + /// Based on benchmark: + /// 22.62 + M * 0.115 + B * 0.003 µs (min squares analysis) + pub(crate) fn execute, I: Instance>( + members: Weight, + proposal: Weight, + length: Weight, + ) -> Weight { + T::DbWeight::get().reads(1) // read members for `is_member` + .saturating_add(23_000_000) // constant + .saturating_add(length.saturating_mul(4_000)) // B + .saturating_add(members.saturating_mul(120_000)) // M + .saturating_add(proposal) // P + } + + /// Calculate the weight for `propose` if the proposal is executed straight away (`threshold < 2`). + /// + /// Based on benchmark: + /// 28.12 + M * 0.218 + B * 0.003 µs (min squares analysis) + pub(crate) fn propose_execute, I: Instance>( + members: Weight, + proposal: Weight, + length: Weight, + ) -> Weight { + T::DbWeight::get().reads(2) // `is_member` + `contains_key` + .saturating_add(29_000_000) // constant + .saturating_add(length.saturating_mul(3_000)) // B + .saturating_add(members.saturating_mul(220_000)) // M + .saturating_add(proposal) // P1 + } + + /// Calculate the weight for `propose` if the proposal is put up for a vote (`threshold >= 2`). + /// + /// Based on benchmark: + /// 49.75 + M * 0.105 + P2 0.502 + B * 0.006 µs (min squares analysis) + pub(crate) fn propose_proposed, I: Instance>( + members: Weight, + proposals: Weight, + length: Weight, + ) -> Weight { + T::DbWeight::get().reads(2) // `is_member` + `contains_key` + .saturating_add(T::DbWeight::get().reads_writes(2, 4)) // `proposal` insertion + .saturating_add(50_000_000) // constant + .saturating_add(length.saturating_mul(6_000)) // B + .saturating_add(members.saturating_mul(110_000)) // M + .saturating_add(proposals.saturating_mul(510_000)) // P2 + } + + /// Calculate the weight for `vote`. + /// + /// Based on benchmark: + /// 24.03 + M * 0.349 + P * 0.119 + B * 0.003 µs (min squares analysis) + pub(crate) fn vote, I: Instance>( + members: Weight, + ) -> Weight { + T::DbWeight::get().reads(1) // read `Members` + .saturating_add(T::DbWeight::get().reads_writes(1, 1)) // mutate `Voting` + .saturating_add(30_000_000) // constant + .saturating_add(members.saturating_mul(500_000)) // M + } + + /// Calculate the weight for `close`. + /// + /// Based on benchmarks: + /// - early disapproved: 37.21 + M * 0.239 + P2 * 0.466 + B * 0.002 µs (min squares analysis) + /// - early approved: 50.82 + M * 0.211 + P2 * 0.478 + B * 0.008 µs (min squares analysis) + /// - disapproved: 51.08 + M * 0.224 + P2 * 0.475 + B * 0.003 µs (min squares analysis) + /// - approved: 65.95 + M * 0.226 + P2 * 0.487 + B * 0.005 µs (min squares analysis) + pub(crate) fn close, I: Instance>( + members: Weight, + proposal_weight: Weight, + proposals: Weight, + length: Weight, + ) -> Weight { + let db = T::DbWeight::get(); + close_without_finalize::(members, length) + .saturating_add(db.reads(1)) // `Prime` + .saturating_add(db.writes(1)) // `Proposals` + .saturating_add(db.writes(1)) // `Voting` + .saturating_add(proposal_weight) // P1 + .saturating_add(proposals.saturating_mul(490_000)) // P2 + } + + /// Calculate the weight for `close` without the call to `approve/disapprove_proposal`. + pub(crate) fn close_without_finalize, I: Instance>( + members: Weight, + length: Weight, + ) -> Weight { + T::DbWeight::get().reads(3) // `Members`, `Voting`, `ProposalOf` + .saturating_add(66_000_000) // constant + .saturating_add(length.saturating_mul(8_000)) // B + .saturating_add(members.saturating_mul(250_000)) // M + } +} + +/// Return the weight of a dispatch call result as an `Option`. +/// +/// Will return the weight regardless of what the state of the result is. +fn get_result_weight(result: DispatchResultWithPostInfo) -> Option { + match result { + Ok(post_info) => post_info.actual_weight, + Err(err) => err.post_info.actual_weight, + } +} + + +// Note that councillor operations are assigned to the operational class. decl_module! { pub struct Module, I: Instance=DefaultInstance> for enum Call where origin: ::Origin { type Error = Error; @@ -182,72 +371,231 @@ decl_module! { /// Set the collective's membership. /// - /// - `new_members`: The new member list. Be nice to the chain and - // provide it sorted. + /// - `new_members`: The new member list. Be nice to the chain and provide it sorted. /// - `prime`: The prime member whose vote sets the default. + /// - `old_count`: The upper bound for the previous number of members in storage. + /// Used for weight estimation. /// /// Requires root origin. - #[weight = SimpleDispatchInfo::FixedOperational(100_000)] - fn set_members(origin, new_members: Vec, prime: Option) { + /// + /// NOTE: Does not enforce the expected `MAX_MEMBERS` limit on the amount of members, but + /// the weight estimations rely on it to estimate dispatchable weight. + /// + /// # + /// ## Weight + /// - `O(MP + N)` where: + /// - `M` old-members-count (code- and governance-bounded) + /// - `N` new-members-count (code- and governance-bounded) + /// - `P` proposals-count (code-bounded) + /// - DB: + /// - 1 storage mutation (codec `O(M)` read, `O(N)` write) for reading and writing the members + /// - 1 storage read (codec `O(P)`) for reading the proposals + /// - `P` storage mutations (codec `O(M)`) for updating the votes for each proposal + /// - 1 storage write (codec `O(1)`) for deleting the old `prime` and setting the new one + /// # + #[weight = ( + weight_for::set_members::( + (*old_count).into(), // M + new_members.len() as Weight, // N + T::MaxProposals::get().into(), // P + ), + DispatchClass::Operational + )] + fn set_members(origin, + new_members: Vec, + prime: Option, + old_count: MemberCount, + ) -> DispatchResultWithPostInfo { ensure_root(origin)?; + if new_members.len() > MAX_MEMBERS as usize { + debug::error!( + "New members count exceeds maximum amount of members expected. (expected: {}, actual: {})", + MAX_MEMBERS, + new_members.len() + ); + } + + let old = Members::::get(); + if old.len() > old_count as usize { + debug::warn!( + "Wrong count used to estimate set_members weight. (expected: {}, actual: {})", + old_count, + old.len() + ); + } let mut new_members = new_members; new_members.sort(); - let old = Members::::get(); - >::set_members_sorted(&new_members[..], &old); + >::set_members_sorted(&new_members, &old); Prime::::set(prime); + + Ok(Some(weight_for::set_members::( + old.len() as Weight, // M + new_members.len() as Weight, // N + T::MaxProposals::get().into(), // P + )).into()) } /// Dispatch a proposal from a member using the `Member` origin. /// /// Origin must be a member of the collective. - #[weight = SimpleDispatchInfo::FixedOperational(100_000)] - fn execute(origin, proposal: Box<>::Proposal>) { + /// + /// # + /// ## Weight + /// - `O(M + P)` where `M` members-count (code-bounded) and `P` complexity of dispatching `proposal` + /// - DB: 1 read (codec `O(M)`) + DB access of `proposal` + /// - 1 event + /// # + #[weight = ( + weight_for::execute::( + MAX_MEMBERS.into(), + proposal.get_dispatch_info().weight, + *length_bound as Weight, + ), + DispatchClass::Operational + )] + fn execute(origin, + proposal: Box<>::Proposal>, + #[compact] length_bound: u32, + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; - ensure!(Self::is_member(&who), Error::::NotMember); + let members = Self::members(); + ensure!(members.contains(&who), Error::::NotMember); + let proposal_len = proposal.using_encoded(|x| x.len()); + ensure!(proposal_len <= length_bound as usize, Error::::WrongProposalLength); let proposal_hash = T::Hashing::hash_of(&proposal); - let ok = proposal.dispatch(RawOrigin::Member(who).into()).is_ok(); - Self::deposit_event(RawEvent::MemberExecuted(proposal_hash, ok)); + let result = proposal.dispatch(RawOrigin::Member(who).into()); + Self::deposit_event( + RawEvent::MemberExecuted(proposal_hash, result.map(|_| ()).map_err(|e| e.error)) + ); + + Ok(get_result_weight(result).map(|w| weight_for::execute::( + members.len() as Weight, + w, + proposal_len as Weight + )).into()) } + /// Add a new proposal to either be voted on or executed directly. + /// + /// Requires the sender to be member. + /// + /// `threshold` determines whether `proposal` is executed directly (`threshold < 2`) + /// or put up for voting. + /// /// # - /// - Bounded storage reads and writes. - /// - Argument `threshold` has bearing on weight. + /// ## Weight + /// - `O(B + M + P1)` or `O(B + M + P2)` where: + /// - `B` is `proposal` size in bytes (length-fee-bounded) + /// - `M` is members-count (code- and governance-bounded) + /// - branching is influenced by `threshold` where: + /// - `P1` is proposal execution complexity (`threshold < 2`) + /// - `P2` is proposals-count (code-bounded) (`threshold >= 2`) + /// - DB: + /// - 1 storage read `is_member` (codec `O(M)`) + /// - 1 storage read `ProposalOf::contains_key` (codec `O(1)`) + /// - DB accesses influenced by `threshold`: + /// - EITHER storage accesses done by `proposal` (`threshold < 2`) + /// - OR proposal insertion (`threshold <= 2`) + /// - 1 storage mutation `Proposals` (codec `O(P2)`) + /// - 1 storage mutation `ProposalCount` (codec `O(1)`) + /// - 1 storage write `ProposalOf` (codec `O(B)`) + /// - 1 storage write `Voting` (codec `O(M)`) + /// - 1 event /// # - #[weight = SimpleDispatchInfo::FixedOperational(5_000_000)] - fn propose(origin, #[compact] threshold: MemberCount, proposal: Box<>::Proposal>) { + #[weight = ( + if *threshold < 2 { + weight_for::propose_execute::( + MAX_MEMBERS.into(), // M + proposal.get_dispatch_info().weight, // P1 + *length_bound as Weight, // B + ) + } else { + weight_for::propose_proposed::( + MAX_MEMBERS.into(), // M + T::MaxProposals::get().into(), // P2 + *length_bound as Weight, // B + ) + }, + DispatchClass::Operational + )] + fn propose(origin, + #[compact] threshold: MemberCount, + proposal: Box<>::Proposal>, + #[compact] length_bound: u32 + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; - ensure!(Self::is_member(&who), Error::::NotMember); + let members = Self::members(); + ensure!(members.contains(&who), Error::::NotMember); + let proposal_len = proposal.using_encoded(|x| x.len()); + ensure!(proposal_len <= length_bound as usize, Error::::WrongProposalLength); let proposal_hash = T::Hashing::hash_of(&proposal); - ensure!(!>::contains_key(proposal_hash), Error::::DuplicateProposal); if threshold < 2 { let seats = Self::members().len() as MemberCount; - let ok = proposal.dispatch(RawOrigin::Members(1, seats).into()).is_ok(); - Self::deposit_event(RawEvent::Executed(proposal_hash, ok)); + let result = proposal.dispatch(RawOrigin::Members(1, seats).into()); + Self::deposit_event( + RawEvent::Executed(proposal_hash, result.map(|_| ()).map_err(|e| e.error)) + ); + + Ok(get_result_weight(result).map(|w| weight_for::propose_execute::( + members.len() as Weight, // M + w, // P1 + proposal_len as Weight, // B + )).into()) } else { + let active_proposals = + >::try_mutate(|proposals| -> Result { + proposals.push(proposal_hash); + ensure!( + proposals.len() <= T::MaxProposals::get() as usize, + Error::::TooManyProposals + ); + Ok(proposals.len()) + })?; let index = Self::proposal_count(); >::mutate(|i| *i += 1); - >::mutate(|proposals| proposals.push(proposal_hash)); >::insert(proposal_hash, *proposal); let end = system::Module::::block_number() + T::MotionDuration::get(); let votes = Votes { index, threshold, ayes: vec![who.clone()], nays: vec![], end }; >::insert(proposal_hash, votes); Self::deposit_event(RawEvent::Proposed(who, index, proposal_hash, threshold)); + + Ok(Some(weight_for::propose_proposed::( + members.len() as Weight, // M + active_proposals as Weight, // P2 + proposal_len as Weight, // B + )).into()) } } + /// Add an aye or nay vote for the sender to the given proposal. + /// + /// Requires the sender to be a member. + /// /// # - /// - Bounded storage read and writes. - /// - Will be slightly heavier if the proposal is approved / disapproved after the vote. + /// ## Weight + /// - `O(M)` where `M` is members-count (code- and governance-bounded) + /// - DB: + /// - 1 storage read `Members` (codec `O(M)`) + /// - 1 storage mutation `Voting` (codec `O(M)`) + /// - 1 event /// # - #[weight = SimpleDispatchInfo::FixedOperational(200_000)] - fn vote(origin, proposal: T::Hash, #[compact] index: ProposalIndex, approve: bool) { + #[weight = ( + weight_for::vote::(MAX_MEMBERS.into()), + DispatchClass::Operational + )] + fn vote(origin, + proposal: T::Hash, + #[compact] index: ProposalIndex, + approve: bool, + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; - ensure!(Self::is_member(&who), Error::::NotMember); + let members = Self::members(); + ensure!(members.contains(&who), Error::::NotMember); let mut voting = Self::voting(&proposal).ok_or(Error::::ProposalMissing)?; ensure!(voting.index == index, Error::::WrongIndex); @@ -279,64 +627,175 @@ decl_module! { let no_votes = voting.nays.len() as MemberCount; Self::deposit_event(RawEvent::Voted(who, proposal, approve, yes_votes, no_votes)); - let seats = Self::members().len() as MemberCount; + Voting::::insert(&proposal, voting); - let approved = yes_votes >= voting.threshold; - let disapproved = seats.saturating_sub(no_votes) < voting.threshold; - if approved || disapproved { - Self::finalize_proposal(approved, seats, voting, proposal); - } else { - Voting::::insert(&proposal, voting); - } + Ok(Some(weight_for::vote::(members.len() as Weight)).into()) } - /// May be called by any signed account after the voting duration has ended in order to - /// finish voting and close the proposal. + /// Close a vote that is either approved, disapproved or whose voting period has ended. + /// + /// May be called by any signed account in order to finish voting and close the proposal. /// - /// Abstentions are counted as rejections unless there is a prime member set and the prime - /// member cast an approval. + /// If called before the end of the voting period it will only close the vote if it is + /// has enough votes to be approved or disapproved. /// - /// - the weight of `proposal` preimage. - /// - up to three events deposited. - /// - one read, two removals, one mutation. (plus three static reads.) - /// - computation and i/o `O(P + L + M)` where: - /// - `M` is number of members, - /// - `P` is number of active proposals, - /// - `L` is the encoded length of `proposal` preimage. - #[weight = SimpleDispatchInfo::FixedOperational(200_000)] - fn close(origin, proposal: T::Hash, #[compact] index: ProposalIndex) { + /// If called after the end of the voting period abstentions are counted as rejections + /// unless there is a prime member set and the prime member cast an approval. + /// + /// + `proposal_weight_bound`: The maximum amount of weight consumed by executing the closed proposal. + /// + `length_bound`: The upper bound for the length of the proposal in storage. Checked via + /// `storage::read` so it is `size_of::() == 4` larger than the pure length. + /// + /// # + /// ## Weight + /// - `O(B + M + P1 + P2)` where: + /// - `B` is `proposal` size in bytes (length-fee-bounded) + /// - `M` is members-count (code- and governance-bounded) + /// - `P1` is the complexity of `proposal` preimage. + /// - `P2` is proposal-count (code-bounded) + /// - DB: + /// - 2 storage reads (`Members`: codec `O(M)`, `Prime`: codec `O(1)`) + /// - 3 mutations (`Voting`: codec `O(M)`, `ProposalOf`: codec `O(B)`, `Proposals`: codec `O(P2)`) + /// - any mutations done while executing `proposal` (`P1`) + /// - up to 3 events + /// # + #[weight = ( + weight_for::close::( + MAX_MEMBERS.into(), // `M` + *proposal_weight_bound, // `P1` + T::MaxProposals::get().into(), // `P2` + *length_bound as Weight, // B + ), + DispatchClass::Operational + )] + fn close(origin, + proposal_hash: T::Hash, + #[compact] index: ProposalIndex, + #[compact] proposal_weight_bound: Weight, + #[compact] length_bound: u32 + ) -> DispatchResultWithPostInfo { let _ = ensure_signed(origin)?; - let voting = Self::voting(&proposal).ok_or(Error::::ProposalMissing)?; + let voting = Self::voting(&proposal_hash).ok_or(Error::::ProposalMissing)?; ensure!(voting.index == index, Error::::WrongIndex); - ensure!(system::Module::::block_number() >= voting.end, Error::::TooEarly); - - // default to true only if there's a prime and they voted in favour. - let default = Self::prime().map_or( - false, - |who| voting.ayes.iter().any(|a| a == &who), - ); let mut no_votes = voting.nays.len() as MemberCount; let mut yes_votes = voting.ayes.len() as MemberCount; let seats = Self::members().len() as MemberCount; + let approved = yes_votes >= voting.threshold; + let disapproved = seats.saturating_sub(no_votes) < voting.threshold; + // Allow (dis-)approving the proposal as soon as there are enough votes. + if approved { + let (proposal, len) = Self::validate_and_get_proposal( + &proposal_hash, + length_bound, + proposal_weight_bound + )?; + Self::deposit_event(RawEvent::Closed(proposal_hash, yes_votes, no_votes)); + let approve_weight = Self::do_approve_proposal(seats, voting, proposal_hash, proposal); + return Ok(Some( + weight_for::close_without_finalize::(seats.into(), len as Weight) + .saturating_add(approve_weight) + ).into()); + } else if disapproved { + Self::deposit_event(RawEvent::Closed(proposal_hash, yes_votes, no_votes)); + let disapprove_weight = Self::do_disapprove_proposal(proposal_hash); + return Ok(Some( + weight_for::close_without_finalize::(seats.into(), 0) + .saturating_add(disapprove_weight) + ).into()); + } + + // Only allow actual closing of the proposal after the voting period has ended. + ensure!(system::Module::::block_number() >= voting.end, Error::::TooEarly); + + // default to true only if there's a prime and they voted in favour. + let default = Self::prime().map_or(false, |who| voting.ayes.iter().any(|a| a == &who)); + let abstentions = seats - (yes_votes + no_votes); match default { true => yes_votes += abstentions, false => no_votes += abstentions, } + let approved = yes_votes >= voting.threshold; - Self::deposit_event(RawEvent::Closed(proposal, yes_votes, no_votes)); - Self::finalize_proposal(yes_votes >= voting.threshold, seats, voting, proposal); + if approved { + let (proposal, len) = Self::validate_and_get_proposal( + &proposal_hash, + length_bound, + proposal_weight_bound + )?; + Self::deposit_event(RawEvent::Closed(proposal_hash, yes_votes, no_votes)); + let approve_weight = Self::do_approve_proposal(seats, voting, proposal_hash, proposal); + return Ok(Some( + weight_for::close_without_finalize::(seats.into(), len as Weight) + .saturating_add(T::DbWeight::get().reads(1)) // read `Prime` + .saturating_add(approve_weight) + ).into()); + } else { + Self::deposit_event(RawEvent::Closed(proposal_hash, yes_votes, no_votes)); + let disapprove_weight = Self::do_disapprove_proposal(proposal_hash); + return Ok(Some( + weight_for::close_without_finalize::(seats.into(), 0) + .saturating_add(T::DbWeight::get().reads(1)) // read `Prime` + .saturating_add(disapprove_weight) + ).into()); + } + } + + /// Disapprove a proposal, close, and remove it from the system, regardless of its current state. + /// + /// Must be called by the Root origin. + /// + /// Parameters: + /// * `proposal_hash`: The hash of the proposal that should be disapproved. + /// + /// # + /// Complexity: O(P) where P is the number of max proposals + /// Base Weight: .49 * P + /// DB Weight: + /// * Reads: Proposals + /// * Writes: Voting, Proposals, ProposalOf + /// # + #[weight = T::DbWeight::get().reads_writes(1, 3) // `Voting`, `Proposals`, `ProposalOf` + .saturating_add(490_000 * Weight::from(T::MaxProposals::get())) // P2 + ] + fn disapprove_proposal(origin, proposal_hash: T::Hash) -> DispatchResultWithPostInfo { + ensure_root(origin)?; + let actual_weight = Self::do_disapprove_proposal(proposal_hash); + Ok(Some(actual_weight).into()) } } } impl, I: Instance> Module { + /// Check whether `who` is a member of the collective. pub fn is_member(who: &T::AccountId) -> bool { + // Note: The dispatchables *do not* use this to check membership so make sure + // to update those if this is changed. Self::members().contains(who) } + /// Ensure that the right proposal bounds were passed and get the proposal from storage. + /// + /// Checks the length in storage via `storage::read` which adds an extra `size_of::() == 4` + /// to the length. + fn validate_and_get_proposal( + hash: &T::Hash, + length_bound: u32, + weight_bound: Weight + ) -> Result<(>::Proposal, usize), DispatchError> { + let key = ProposalOf::::hashed_key_for(hash); + // read the length of the proposal storage entry directly + let proposal_len = storage::read(&key, &mut [0; 0], 0) + .ok_or(Error::::ProposalMissing)?; + ensure!(proposal_len <= length_bound, Error::::WrongProposalLength); + let proposal = ProposalOf::::get(hash).ok_or(Error::::ProposalMissing)?; + let proposal_weight = proposal.get_dispatch_info().weight; + ensure!(proposal_weight <= weight_bound, Error::::WrongProposalWeight); + Ok((proposal, proposal_len as usize)) + } + /// Weight: /// If `approved`: /// - the weight of `proposal` preimage. @@ -351,39 +810,80 @@ impl, I: Instance> Module { /// Two removals, one mutation. /// Computation and i/o `O(P)` where: /// - `P` is number of active proposals - fn finalize_proposal( - approved: bool, + fn do_approve_proposal( seats: MemberCount, voting: Votes, - proposal: T::Hash, - ) { - if approved { - Self::deposit_event(RawEvent::Approved(proposal)); - - // execute motion, assuming it exists. - if let Some(p) = ProposalOf::::take(&proposal) { - let origin = RawOrigin::Members(voting.threshold, seats).into(); - let ok = p.dispatch(origin).is_ok(); - Self::deposit_event(RawEvent::Executed(proposal, ok)); - } - } else { - // disapproved - ProposalOf::::remove(&proposal); - Self::deposit_event(RawEvent::Disapproved(proposal)); - } + proposal_hash: T::Hash, + proposal: >::Proposal, + ) -> Weight { + let mut weight: Weight = 0; + Self::deposit_event(RawEvent::Approved(proposal_hash)); + + let dispatch_weight = proposal.get_dispatch_info().weight; + let origin = RawOrigin::Members(voting.threshold, seats).into(); + let result = proposal.dispatch(origin); + Self::deposit_event( + RawEvent::Executed(proposal_hash, result.map(|_| ()).map_err(|e| e.error)) + ); + weight = weight.saturating_add( + // default to the dispatch info weight for safety + get_result_weight(result).unwrap_or(dispatch_weight) // P1 + ); + + let remove_proposal_weight = Self::remove_proposal(proposal_hash); + weight.saturating_add(remove_proposal_weight) + } - // remove vote - Voting::::remove(&proposal); - Proposals::::mutate(|proposals| proposals.retain(|h| h != &proposal)); + fn do_disapprove_proposal(proposal_hash: T::Hash) -> Weight { + // disapproved + Self::deposit_event(RawEvent::Disapproved(proposal_hash)); + Self::remove_proposal(proposal_hash) + } + + // Removes a proposal from the pallet, cleaning up votes and the vector of proposals. + fn remove_proposal(proposal_hash: T::Hash) -> Weight { + // remove proposal and vote + ProposalOf::::remove(&proposal_hash); + Voting::::remove(&proposal_hash); + let num_proposals = Proposals::::mutate(|proposals| { + proposals.retain(|h| h != &proposal_hash); + proposals.len() + 1 // calculate weight based on original length + }); + T::DbWeight::get().reads_writes(1, 3) // `Voting`, `Proposals`, `ProposalOf` + .saturating_add(490_000 * num_proposals as Weight) // P2 } } impl, I: Instance> ChangeMembers for Module { + /// Update the members of the collective. Votes are updated and the prime is reset. + /// + /// NOTE: Does not enforce the expected `MAX_MEMBERS` limit on the amount of members, but + /// the weight estimations rely on it to estimate dispatchable weight. + /// + /// # + /// ## Weight + /// - `O(MP + N)` + /// - where `M` old-members-count (governance-bounded) + /// - where `N` new-members-count (governance-bounded) + /// - where `P` proposals-count + /// - DB: + /// - 1 storage read (codec `O(P)`) for reading the proposals + /// - `P` storage mutations for updating the votes (codec `O(M)`) + /// - 1 storage write (codec `O(N)`) for storing the new members + /// - 1 storage write (codec `O(1)`) for deleting the old prime + /// # fn change_members_sorted( _incoming: &[T::AccountId], outgoing: &[T::AccountId], new: &[T::AccountId], ) { + if new.len() > MAX_MEMBERS as usize { + debug::error!( + "New members count exceeds maximum amount of members expected. (expected: {}, actual: {})", + MAX_MEMBERS, + new.len() + ); + } // remove accounts from all current voting in motions. let mut outgoing = outgoing.to_vec(); outgoing.sort_unstable(); @@ -539,12 +1039,14 @@ mod tests { pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const MotionDuration: u64 = 3; + pub const MaxProposals: u32 = 100; } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; - type Call = (); + type Call = Call; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = u64; @@ -553,6 +1055,10 @@ mod tests { type Event = Event; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -560,18 +1066,23 @@ mod tests { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } impl Trait for Test { type Origin = Origin; type Proposal = Call; type Event = Event; type MotionDuration = MotionDuration; + type MaxProposals = MaxProposals; + type WeightInfo = (); } impl Trait for Test { type Origin = Origin; type Proposal = Call; type Event = Event; type MotionDuration = MotionDuration; + type MaxProposals = MaxProposals; + type WeightInfo = (); } pub type Block = sp_runtime::generic::Block; @@ -589,7 +1100,7 @@ mod tests { } ); - fn make_ext() -> sp_io::TestExternalities { + pub fn new_test_ext() -> sp_io::TestExternalities { let mut ext: sp_io::TestExternalities = GenesisConfig { collective_Instance1: Some(collective::GenesisConfig { members: vec![1, 2, 3], @@ -603,7 +1114,7 @@ mod tests { #[test] fn motions_basic_environment_works() { - make_ext().execute_with(|| { + new_test_ext().execute_with(|| { assert_eq!(Collective::members(), vec![1, 2, 3]); assert_eq!(Collective::proposals(), Vec::::new()); }); @@ -615,21 +1126,23 @@ mod tests { #[test] fn close_works() { - make_ext().execute_with(|| { + new_test_ext().execute_with(|| { let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); + let proposal_weight = proposal.get_dispatch_info().weight; let hash = BlakeTwo256::hash_of(&proposal); - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); System::set_block_number(3); assert_noop!( - Collective::close(Origin::signed(4), hash.clone(), 0), + Collective::close(Origin::signed(4), hash.clone(), 0, proposal_weight, proposal_len), Error::::TooEarly ); System::set_block_number(4); - assert_ok!(Collective::close(Origin::signed(4), hash.clone(), 0)); + assert_ok!(Collective::close(Origin::signed(4), hash.clone(), 0, proposal_weight, proposal_len)); let record = |event| EventRecord { phase: Phase::Initialization, event, topics: vec![] }; assert_eq!(System::events(), vec![ @@ -641,18 +1154,57 @@ mod tests { }); } + #[test] + fn proposal_weight_limit_works_on_approve() { + new_test_ext().execute_with(|| { + let proposal = Call::Collective(crate::Call::set_members(vec![1, 2, 3], None, MAX_MEMBERS)); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); + let proposal_weight = proposal.get_dispatch_info().weight; + let hash = BlakeTwo256::hash_of(&proposal); + // Set 1 as prime voter + Prime::::set(Some(1)); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); + // With 1's prime vote, this should pass + System::set_block_number(4); + assert_noop!( + Collective::close(Origin::signed(4), hash.clone(), 0, proposal_weight - 100, proposal_len), + Error::::WrongProposalWeight + ); + assert_ok!(Collective::close(Origin::signed(4), hash.clone(), 0, proposal_weight, proposal_len)); + }) + } + + #[test] + fn proposal_weight_limit_ignored_on_disapprove() { + new_test_ext().execute_with(|| { + let proposal = Call::Collective(crate::Call::set_members(vec![1, 2, 3], None, MAX_MEMBERS)); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); + let proposal_weight = proposal.get_dispatch_info().weight; + let hash = BlakeTwo256::hash_of(&proposal); + + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); + // No votes, this proposal wont pass + System::set_block_number(4); + assert_ok!( + Collective::close(Origin::signed(4), hash.clone(), 0, proposal_weight - 100, proposal_len) + ); + }) + } + #[test] fn close_with_prime_works() { - make_ext().execute_with(|| { + new_test_ext().execute_with(|| { let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); + let proposal_weight = proposal.get_dispatch_info().weight; let hash = BlakeTwo256::hash_of(&proposal); - assert_ok!(Collective::set_members(Origin::ROOT, vec![1, 2, 3], Some(3))); + assert_ok!(Collective::set_members(Origin::root(), vec![1, 2, 3], Some(3), MAX_MEMBERS)); - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); System::set_block_number(4); - assert_ok!(Collective::close(Origin::signed(4), hash.clone(), 0)); + assert_ok!(Collective::close(Origin::signed(4), hash.clone(), 0, proposal_weight, proposal_len)); let record = |event| EventRecord { phase: Phase::Initialization, event, topics: vec![] }; assert_eq!(System::events(), vec![ @@ -666,16 +1218,18 @@ mod tests { #[test] fn close_with_voting_prime_works() { - make_ext().execute_with(|| { + new_test_ext().execute_with(|| { let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); + let proposal_weight = proposal.get_dispatch_info().weight; let hash = BlakeTwo256::hash_of(&proposal); - assert_ok!(Collective::set_members(Origin::ROOT, vec![1, 2, 3], Some(1))); + assert_ok!(Collective::set_members(Origin::root(), vec![1, 2, 3], Some(1), MAX_MEMBERS)); - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); System::set_block_number(4); - assert_ok!(Collective::close(Origin::signed(4), hash.clone(), 0)); + assert_ok!(Collective::close(Origin::signed(4), hash.clone(), 0, proposal_weight, proposal_len)); let record = |event| EventRecord { phase: Phase::Initialization, event, topics: vec![] }; assert_eq!(System::events(), vec![ @@ -683,18 +1237,19 @@ mod tests { record(Event::collective_Instance1(RawEvent::Voted(2, hash.clone(), true, 2, 0))), record(Event::collective_Instance1(RawEvent::Closed(hash.clone(), 3, 0))), record(Event::collective_Instance1(RawEvent::Approved(hash.clone()))), - record(Event::collective_Instance1(RawEvent::Executed(hash.clone(), false))) + record(Event::collective_Instance1(RawEvent::Executed(hash.clone(), Err(DispatchError::BadOrigin)))) ]); }); } #[test] fn removal_of_old_voters_votes_works() { - make_ext().execute_with(|| { + new_test_ext().execute_with(|| { let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); let hash = BlakeTwo256::hash_of(&proposal); let end = 4; - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); assert_eq!( Collective::voting(&hash), @@ -707,8 +1262,9 @@ mod tests { ); let proposal = make_proposal(69); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); let hash = BlakeTwo256::hash_of(&proposal); - assert_ok!(Collective::propose(Origin::signed(2), 2, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(2), 2, Box::new(proposal.clone()), proposal_len)); assert_ok!(Collective::vote(Origin::signed(3), hash.clone(), 1, false)); assert_eq!( Collective::voting(&hash), @@ -724,31 +1280,33 @@ mod tests { #[test] fn removal_of_old_voters_votes_works_with_set_members() { - make_ext().execute_with(|| { + new_test_ext().execute_with(|| { let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); let hash = BlakeTwo256::hash_of(&proposal); let end = 4; - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); assert_eq!( Collective::voting(&hash), Some(Votes { index: 0, threshold: 3, ayes: vec![1, 2], nays: vec![], end }) ); - assert_ok!(Collective::set_members(Origin::ROOT, vec![2, 3, 4], None)); + assert_ok!(Collective::set_members(Origin::root(), vec![2, 3, 4], None, MAX_MEMBERS)); assert_eq!( Collective::voting(&hash), Some(Votes { index: 0, threshold: 3, ayes: vec![2], nays: vec![], end }) ); let proposal = make_proposal(69); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); let hash = BlakeTwo256::hash_of(&proposal); - assert_ok!(Collective::propose(Origin::signed(2), 2, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(2), 2, Box::new(proposal.clone()), proposal_len)); assert_ok!(Collective::vote(Origin::signed(3), hash.clone(), 1, false)); assert_eq!( Collective::voting(&hash), Some(Votes { index: 1, threshold: 2, ayes: vec![2], nays: vec![3], end }) ); - assert_ok!(Collective::set_members(Origin::ROOT, vec![2, 4], None)); + assert_ok!(Collective::set_members(Origin::root(), vec![2, 4], None, MAX_MEMBERS)); assert_eq!( Collective::voting(&hash), Some(Votes { index: 1, threshold: 2, ayes: vec![2], nays: vec![], end }) @@ -758,11 +1316,12 @@ mod tests { #[test] fn propose_works() { - make_ext().execute_with(|| { + new_test_ext().execute_with(|| { let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); let hash = proposal.blake2_256().into(); let end = 4; - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); assert_eq!(Collective::proposals(), vec![hash]); assert_eq!(Collective::proposal_of(&hash), Some(proposal)); assert_eq!( @@ -785,12 +1344,59 @@ mod tests { }); } + #[test] + fn limit_active_proposals() { + new_test_ext().execute_with(|| { + for i in 0..MaxProposals::get() { + let proposal = make_proposal(i as u64); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); + } + let proposal = make_proposal(MaxProposals::get() as u64 + 1); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); + assert_noop!( + Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len), + Error::::TooManyProposals + ); + }) + } + + #[test] + fn correct_validate_and_get_proposal() { + new_test_ext().execute_with(|| { + let proposal = Call::Collective(crate::Call::set_members(vec![1, 2, 3], None, MAX_MEMBERS)); + let length = proposal.encode().len() as u32; + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), length)); + + let hash = BlakeTwo256::hash_of(&proposal); + let weight = proposal.get_dispatch_info().weight; + assert_noop!( + Collective::validate_and_get_proposal(&BlakeTwo256::hash_of(&vec![3; 4]), length, weight), + Error::::ProposalMissing + ); + assert_noop!( + Collective::validate_and_get_proposal(&hash, length - 2, weight), + Error::::WrongProposalLength + ); + assert_noop!( + Collective::validate_and_get_proposal(&hash, length, weight - 10), + Error::::WrongProposalWeight + ); + let res = Collective::validate_and_get_proposal(&hash, length, weight); + assert_ok!(res.clone()); + let (retrieved_proposal, len) = res.unwrap(); + assert_eq!(length as usize, len); + assert_eq!(proposal, retrieved_proposal); + }) + } + #[test] fn motions_ignoring_non_collective_proposals_works() { - make_ext().execute_with(|| { + new_test_ext().execute_with(|| { let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); assert_noop!( - Collective::propose(Origin::signed(42), 3, Box::new(proposal.clone())), + Collective::propose(Origin::signed(42), 3, Box::new(proposal.clone()), proposal_len), Error::::NotMember ); }); @@ -798,10 +1404,11 @@ mod tests { #[test] fn motions_ignoring_non_collective_votes_works() { - make_ext().execute_with(|| { + new_test_ext().execute_with(|| { let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); let hash: H256 = proposal.blake2_256().into(); - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); assert_noop!( Collective::vote(Origin::signed(42), hash.clone(), 0, true), Error::::NotMember, @@ -811,11 +1418,12 @@ mod tests { #[test] fn motions_ignoring_bad_index_collective_vote_works() { - make_ext().execute_with(|| { + new_test_ext().execute_with(|| { System::set_block_number(3); let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); let hash: H256 = proposal.blake2_256().into(); - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); assert_noop!( Collective::vote(Origin::signed(2), hash.clone(), 1, true), Error::::WrongIndex, @@ -825,11 +1433,12 @@ mod tests { #[test] fn motions_revoting_works() { - make_ext().execute_with(|| { + new_test_ext().execute_with(|| { let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); let hash: H256 = proposal.blake2_256().into(); let end = 4; - assert_ok!(Collective::propose(Origin::signed(1), 2, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 2, Box::new(proposal.clone()), proposal_len)); assert_eq!( Collective::voting(&hash), Some(Votes { index: 0, threshold: 2, ayes: vec![1], nays: vec![], end }) @@ -876,24 +1485,30 @@ mod tests { #[test] fn motions_reproposing_disapproved_works() { - make_ext().execute_with(|| { + new_test_ext().execute_with(|| { let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); + let proposal_weight = proposal.get_dispatch_info().weight; let hash: H256 = proposal.blake2_256().into(); - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, false)); + assert_ok!(Collective::close(Origin::signed(2), hash.clone(), 0, proposal_weight, proposal_len)); assert_eq!(Collective::proposals(), vec![]); - assert_ok!(Collective::propose(Origin::signed(1), 2, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 2, Box::new(proposal.clone()), proposal_len)); assert_eq!(Collective::proposals(), vec![hash]); }); } #[test] fn motions_disapproval_works() { - make_ext().execute_with(|| { + new_test_ext().execute_with(|| { let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); + let proposal_weight = proposal.get_dispatch_info().weight; let hash: H256 = proposal.blake2_256().into(); - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, false)); + assert_ok!(Collective::close(Origin::signed(2), hash.clone(), 0, proposal_weight, proposal_len)); assert_eq!(System::events(), vec![ EventRecord { @@ -918,6 +1533,13 @@ mod tests { )), topics: vec![], }, + EventRecord { + phase: Phase::Initialization, + event: Event::collective_Instance1(RawEvent::Closed( + hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), 1, 1, + )), + topics: vec![], + }, EventRecord { phase: Phase::Initialization, event: Event::collective_Instance1(RawEvent::Disapproved( @@ -931,11 +1553,14 @@ mod tests { #[test] fn motions_approval_works() { - make_ext().execute_with(|| { + new_test_ext().execute_with(|| { let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); + let proposal_weight = proposal.get_dispatch_info().weight; let hash: H256 = proposal.blake2_256().into(); - assert_ok!(Collective::propose(Origin::signed(1), 2, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 2, Box::new(proposal.clone()), proposal_len)); assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); + assert_ok!(Collective::close(Origin::signed(2), hash.clone(), 0, proposal_weight, proposal_len)); assert_eq!(System::events(), vec![ EventRecord { @@ -959,6 +1584,13 @@ mod tests { )), topics: vec![], }, + EventRecord { + phase: Phase::Initialization, + event: Event::collective_Instance1(RawEvent::Closed( + hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), 2, 0, + )), + topics: vec![], + }, EventRecord { phase: Phase::Initialization, event: Event::collective_Instance1(RawEvent::Approved( @@ -970,11 +1602,60 @@ mod tests { phase: Phase::Initialization, event: Event::collective_Instance1(RawEvent::Executed( hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), - false, + Err(DispatchError::BadOrigin), )), topics: vec![], } ]); }); } + + #[test] + fn close_disapprove_does_not_care_about_weight_or_len() { + // This test confirms that if you close a proposal that would be disapproved, + // we do not care about the proposal length or proposal weight since it will + // not be read from storage or executed. + new_test_ext().execute_with(|| { + let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); + let hash: H256 = proposal.blake2_256().into(); + assert_ok!(Collective::propose(Origin::signed(1), 2, Box::new(proposal.clone()), proposal_len)); + // First we make the proposal succeed + assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); + // It will not close with bad weight/len information + assert_noop!( + Collective::close(Origin::signed(2), hash.clone(), 0, 0, 0), + Error::::WrongProposalLength, + ); + assert_noop!( + Collective::close(Origin::signed(2), hash.clone(), 0, 0, proposal_len), + Error::::WrongProposalWeight, + ); + // Now we make the proposal fail + assert_ok!(Collective::vote(Origin::signed(1), hash.clone(), 0, false)); + assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, false)); + // It can close even if the weight/len information is bad + assert_ok!(Collective::close(Origin::signed(2), hash.clone(), 0, 0, 0)); + }) + } + + #[test] + fn disapprove_proposal_works() { + new_test_ext().execute_with(|| { + let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); + let hash: H256 = proposal.blake2_256().into(); + assert_ok!(Collective::propose(Origin::signed(1), 2, Box::new(proposal.clone()), proposal_len)); + // Proposal would normally succeed + assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); + // But Root can disapprove and remove it anyway + assert_ok!(Collective::disapprove_proposal(Origin::root(), hash.clone())); + let record = |event| EventRecord { phase: Phase::Initialization, event, topics: vec![] }; + assert_eq!(System::events(), vec![ + record(Event::collective_Instance1(RawEvent::Proposed(1, 0, hash.clone(), 2))), + record(Event::collective_Instance1(RawEvent::Voted(2, hash.clone(), true, 2, 0))), + record(Event::collective_Instance1(RawEvent::Disapproved(hash.clone()))), + ]); + }) + } } diff --git a/frame/contracts/COMPLEXITY.md b/frame/contracts/COMPLEXITY.md index 7e8c2903c79b9348d2441b46e181a0c59a6562d0..dbb1a5c5cdef20668516b5f6acb0cf79d894a929 100644 --- a/frame/contracts/COMPLEXITY.md +++ b/frame/contracts/COMPLEXITY.md @@ -4,19 +4,19 @@ This analysis is on the computing and memory complexity of specific procedures. The primary goal is to come up with decent pricing for functions that can be invoked by a user (via extrinsics) or by untrusted code that prevents DoS attacks. -# Sandboxing +## Sandboxing It makes sense to describe the sandboxing module first because the smart-contract module is built upon it. -## Memory +### Memory -### set +#### set Copies data from the supervisor's memory to the guest's memory. **complexity**: It doesn't allocate, and the computational complexity is proportional to the number of bytes to copy. -### get +#### get Copies data from the guest's memory to the supervisor's memory. @@ -78,17 +78,10 @@ The size of the arguments and the return value depends on the exact function in **complexity**: Memory and computational complexity can be considered as a constant. -# `AccountDb` +## Transactional Storage -`AccountDb` is an abstraction that supports collecting changes to accounts with the ability to efficiently reverting them. Contract -execution contexts operate on the AccountDb. All changes are flushed into underlying storage only after origin transaction succeeds. - -## Relation to the underlying storage - -At present, `AccountDb` is implemented as a cascade of overlays with the direct storage at the bottom. The direct -storage `AccountDb` leverages child tries. Each overlay is represented by a `Map`. On a commit from an overlay to an -overlay, maps are merged. On commit from an overlay to the bottommost `AccountDb` all changes are flushed to the storage -and on revert, the overlay is just discarded. +The contracts module makes use of the nested storage transactions feature offered by +the underlying storage which allows efficient roll back of changes made by contracts. > ℹ️ The underlying storage has a overlay layer implemented as a `Map`. If the runtime reads a storage location and the > respective key doesn't exist in the overlay, then the underlying storage performs a DB access, but the value won't be @@ -105,23 +98,24 @@ storage access. ## get_storage, get_code_hash, get_rent_allowance, get_balance, contract_exists -These functions check the local cache for a requested value and, if it is there, the value is returned. Otherwise, these functions will ask an underlying `AccountDb` for the value. This means that the number of lookups is proportional to the depth of the overlay cascade. If the value can't be found before reaching the bottommost `AccountDb`, then a DB read will be performed (in case `get_balance` the function `free_balance` will be invoked). - -A lookup in the local cache consists of at least one `Map` lookup, for locating the specific account. For `get_storage` there is a second lookup: because account's storage is implemented as a nested map, another lookup is required for fetching a storage value by a key. +Those query the underlying storage for the requested value. If the value was modified in the +current block they are served from the cache. Otherwise a database read is performed. -These functions return an owned value as its result, so memory usage depends on the value being returned. - -**complexity**: The memory complexity is proportional to the size of the value. The computational complexity is proportional to the depth of the overlay cascade and the size of the value; the cost is dominated by the DB read though. +**complexity**: The memory complexity is proportional to the size of the value. The computational complexity is proportional the size of the value; the cost is dominated by the DB read. ## set_storage, set_balance, set_rent_allowance -These functions only modify the local `Map`. - -A lookup in the local cache consists of at least one `Map` lookup, for locating the specific account. For `get_storage` there is a second lookup: because account's storage is implemented as a nested map, another lookup is required for fetching a storage value by a key. +These function write to the underlying storage which caches those values and does not write +them to the database immediately. -While these functions only modify the local `Map`, if changes made by them are committed to the bottommost `AccountDb`, each changed entry in the `Map` will require a DB write. Moreover, if the balance of the account is changed to be below `existential_deposit` then that account along with all its storage will be removed, which requires time proportional to the number of storage entries that account has. It should be ensured that pricing accounts for these facts. +While these functions only modify the local cache, they trigger a database write later when +all changes that were not rolled back are written to storage. Moreover, if the balance of the +account is changed to be below `existential_deposit` then that account along with all its storage +will be removed, which requires time proportional to the number of storage entries that account has. +It should be ensured that pricing accounts for these facts. -**complexity**: Each lookup has a logarithmical computing time to the number of already inserted entries. No additional memory is required. +**complexity**: Each lookup has a logarithmical computing time to the number of already inserted entries. +No additional memory is required. ## instantiate_contract @@ -131,9 +125,11 @@ Calls `contract_exists` and if it doesn't exist, do not modify the local `Map` s ## commit -In this function, all cached values will be inserted into the underlying `AccountDb` or into the storage. +In this function, all values modified in the current transactions are committed to the parent +transaction. -We are doing `N` inserts into `Map` (`O(log M)` complexity) or into the storage, where `N` is the size of the committed `Map` and `M` is the size of the map of the underlying overlay. Consider adjusting the price of modifying the `AccountDb` to account for this (since pricing for the count of entries in `commit` will make the price of commit way less predictable). No additional memory is required. +This will trigger `N` inserts into parent transaction (`O(log M)` complexity) or into the storage, where `N` is the size of the current transaction and `M` is the size of the parent transaction. Consider adjusting the price of modifying the +current transaction to account for this (since pricing for the count of entries in `commit` will make the price of commit way less predictable). No additional memory is required. Note that in case of storage modification we need to construct a key in the underlying storage. In order to do that we need: @@ -143,21 +139,21 @@ Note that in case of storage modification we need to construct a key in the unde There is also a special case to think of: if the balance of some account goes below `existential_deposit`, then all storage entries of that account will be erased, which requires time proportional to the number of storage entries that account has. -**complexity**: `N` inserts into a `Map` or eventually into the storage (if committed). Every deleted account will induce removal of all its storage which is proportional to the number of storage entries that account has. +**complexity**: `N` inserts into a transaction or eventually into the storage (if committed). Every deleted account will induce removal of all its storage which is proportional to the number of storage entries that account has. ## revert -Consists of dropping (in the Rust sense) of the `AccountDb`. +Consists of dropping (in the Rust sense) of the current transaction. **complexity**: Computing complexity is proportional to a number of changed entries in a overlay. No additional memory is required. -# Executive +## Executive -## Transfer +### Transfer This function performs the following steps: -1. Querying source and destination balances from an overlay (see `get_balance`), +1. Querying source and destination balances from the current transaction (see `get_balance`), 2. Querying `existential_deposit`. 3. Executing `ensure_account_liquid` hook. 4. Updating source and destination balance in the overlay (see `set_balance`). @@ -171,9 +167,9 @@ returns with an error. Assuming marshaled size of a balance value is of the constant size we can neglect its effect on the performance. -**complexity**: 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. For the current `AccountDb` implementation computing complexity also depends on the depth of the `AccountDb` cascade. Memorywise it can be assumed to be constant. +**complexity**: 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. Memorywise it can be assumed to be constant. -## Initialization +### Initialization Before a call or instantiate can be performed the execution context must be initialized. @@ -188,7 +184,7 @@ implementation they just involve a DB read. For subsequent calls and instantiations during contract execution, the initialization requires no expensive operations. -## Terminate +### Terminate This function performs the following steps: @@ -204,17 +200,17 @@ the call stack is of a fixed maximum size we consider this operation as constant we are using child trie removal which is linear in the amount of stored keys. Upcoming changes will make the account removal constant time. - -## Call +### Call This function receives input data for the contract execution. The execution consists of the following steps: 1. Initialization of the execution context. 2. Checking rent payment. 3. Loading code from the DB. -4. `transfer`-ing funds between the caller and the destination account. -5. Executing the code of the destination account. -6. Committing overlayed changed to the underlying `AccountDb`. +4. Starting a new storage transaction. +5. `transfer`-ing funds between the caller and the destination account. +6. Executing the code of the destination account. +7. Committing or rolling back the storage transaction. **Note** that the complexity of executing the contract code should be considered separately. @@ -235,22 +231,24 @@ Loading code most likely will trigger a DB read, since the code is immutable and 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. -Finally, all changes are `commit`-ted into the underlying overlay. The complexity of this depends on the number of changes performed by the code. Thus, the pricing of storage modification should account for that. +Finally, the current storage transaction is closed. The complexity of this depends on the number of changes performed by the code. Thus, the pricing of storage modification should account for that. **complexity**: + - 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. -## Instantiate +### Instantiate 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 instantiated contract. -4. Executing the constructor code. This will yield the final code of the code. -5. Storing the code for the newly instantiated contract in the overlay. -6. Committing overlayed changed to the underlying `AccountDb`. +3. Starting a new storage transaction. +4. `transfer`-ing funds between self and the newly instantiated contract. +5. Executing the constructor code. This will yield the final code of the code. +6. Storing the code for the newly instantiated contract in the overlay. +7. Committing or rolling back the storage transaction. **Note** that the complexity of executing the constructor code should be considered separately. @@ -262,19 +260,43 @@ Also, `transfer` can make up to 2 DB reads and up to 2 DB writes (if flushed to Storing the code in the overlay may induce another DB write (if flushed to the storage) with the size proportional to the size of the constructor code. -Finally, all changes are `commit`-ted into the underlying overlay. The complexity of this depends on the number of changes performed by the constructor code. Thus, the pricing of storage modification should account for that. +Finally, the current storage transaction is closed.. The complexity of this depends on the number of changes performed by the constructor code. Thus, the pricing of storage modification should account for that. **complexity**: Up to 2 DB reads and induces up to 3 DB writes (if flushed to the storage), one of which is dependent on the size of the code. Additionally, if the source account removal takes place a DB write will be performed per one storage entry that the account has. -# Externalities +## Contracts API + +Each API function invoked from a contract can involve some overhead. + +## Getter functions + +Those are simple getter functions which copy a requested value to contract memory. They +all have the following two arguments: + +- `output_ptr`: Pointer into contract memory where to copy the value. +- `output_len_ptr`: Pointer into contract memory where the size of the buffer is stored. The size of the copied value is also stored there. -Each external function invoked from a contract can involve some overhead. +**complexity**: The size of the returned value is constant for a given runtime. Therefore we +consider its complexity constant even though some of them might involve at most one DB read. Some of those +functions call into other pallets of the runtime. The assumption here is that those functions are also +linear in regard to the size of the data that is returned and therefore considered constant for a +given runtime. -## ext_gas +This is the list of getters: -**complexity**: This is of constant complexity. +- ext_caller +- ext_address +- ext_weight_to_fee +- ext_gas_left +- ext_balance +- ext_value_transferred +- ext_now +- ext_minimum_balance +- ext_tombstone_deposit +- ext_rent_allowance +- ext_block_number -## ext_set_storage +### ext_set_storage This function receives a `key` and `value` as arguments. It consists of the following steps: @@ -283,7 +305,7 @@ This function receives a `key` and `value` as arguments. It consists of the foll **complexity**: Complexity is proportional to the size of the `value`. This function induces a DB write of size proportional to the `value` size (if flushed to the storage), so should be priced accordingly. -## ext_clear_storage +### ext_clear_storage This function receives a `key` as argument. It consists of the following steps: @@ -293,23 +315,22 @@ This function receives a `key` as argument. It consists of the following steps: **complexity**: Complexity is constant. This function induces a DB write to clear the storage entry (upon being flushed to the storage) and should be priced accordingly. -## ext_get_storage +### ext_get_storage This function receives a `key` as an argument. It consists of the following steps: 1. Reading the sandbox memory for `key` (see sandboxing memory get). 2. Reading the storage with the given key (see `get_storage`). It receives back the owned result buffer. -3. Replacing the scratch buffer. +3. Writing the storage value to contract memory. Key is of a constant size. Therefore, the sandbox memory load can be considered to be of constant complexity. Unless the value is cached, a DB read will be performed. The size of the value is not known until the read is performed. Moreover, the DB read has to be synchronous and no progress can be made until the value is fetched. -**complexity**: The memory and computing complexity is proportional to the size of the fetched value. This function performs a -DB read. +**complexity**: The memory and computing complexity is proportional to the size of the fetched value. This function performs a DB read. -## ext_transfer +### ext_transfer This function receives the following arguments: @@ -320,18 +341,19 @@ It consists of the following steps: 1. Loading `account` 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. -4. Invoking the executive function `transfer`. +3. Invoking the executive function `transfer`. Loading of `account` and `value` buffers should be charged. This is because the sizes of buffers are specified by the calling code, even though marshaled representations are, essentially, of constant size. This can be fixed by assigning an upper bound for sizes of `AccountId` and `Balance`. -## ext_call +### ext_call This function receives the following arguments: - `callee` buffer of a marshaled `AccountId`, - `gas` limit which is plain u64, - `value` buffer of a marshaled `Balance`, -- `input_data`. An arbitrarily sized byte vector. +- `input_data` an arbitrarily sized byte vector. +- `output_ptr` pointer to contract memory. It consists of the following steps: @@ -339,14 +361,15 @@ It consists of the following steps: 2. Loading `value` buffer from the sandbox memory and then decoding it. 3. Loading `input_data` buffer from the sandbox memory. 4. Invoking the executive function `call`. +5. Writing output buffer to contract memory. Loading of `callee` and `value` buffers should be charged. This is because the sizes of buffers are specified by the calling code, even though marshaled representations are, essentially, of constant size. This can be fixed by assigning an upper bound for sizes of `AccountId` and `Balance`. 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. +**complexity**: All complexity comes from loading and writing buffers and executing `call` executive function. The former component is proportional to the sizes of `callee`, `value`, `input_data` and `output_ptr` buffers. The latter component completely depends on the complexity of `call` executive function, and also dominated by it. -## ext_instantiate +### ext_instantiate This function receives the following arguments: @@ -368,7 +391,7 @@ Loading `init_code` and `input_data` should be charged in any case. **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_terminate +### ext_terminate This function receives the following arguments: @@ -382,16 +405,23 @@ Loading of the `beneficiary` buffer should be charged. This is because the sizes **complexity**: All complexity comes from loading buffers and executing `terminate` executive function. The former component is proportional to the size of the `beneficiary` buffer. The latter component completely depends on the complexity of `terminate` executive function and also dominated by it. -## ext_return +### ext_input -This function receives a `data` buffer as an argument. Execution of the function consists of the following steps: +This function receives a pointer to contract memory. It copies the input to the contract call to this location. -1. Loading `data` buffer from the sandbox memory (see sandboxing memory get), -2. Trapping +**complexity**: The complextity is proportional to the size of the input buffer. + +### ext_return + +This function receives a `data` buffer and `flags` arguments. Execution of the function consists of the following steps: + +1. Loading `data` buffer from the sandbox memory (see sandboxing memory get). +2. Storing the `u32` flags value. +3. Trapping **complexity**: The complexity of this function is proportional to the size of the `data` buffer. -## ext_deposit_event +### ext_deposit_event This function receives a `data` buffer as an argument. Execution of the function consists of the following steps: @@ -402,49 +432,7 @@ This function receives a `data` buffer as an argument. Execution of the function **complexity**: The complexity of this function is proportional to the size of the `data` buffer. -## ext_caller - -This function serializes the address of the caller into the scratch buffer. - -**complexity**: Assuming that the address is of constant size, this function has constant complexity. - -## ext_random - -This function serializes a random number generated by the given subject into the scratch buffer. -The complexity of this function highly depends on the complexity of `System::random`. `max_subject_len` -limits the size of the subject buffer. - -**complexity**: The complexity of this function depends on the implementation of `System::random`. - -## ext_now - -This function serializes the current block's timestamp into the scratch buffer. - -**complexity**: Assuming that the timestamp is of constant size, this function has constant complexity. - -## ext_scratch_size - -This function returns the size of the scratch buffer. - -**complexity**: This function is of constant complexity. - -## ext_scratch_read - -This function copies slice of data from the scratch buffer to the sandbox memory. The calling code specifies the slice length. Execution of the function consists of the following steps: - -1. Storing a specified slice of the scratch buffer into the sandbox memory (see sandboxing memory set) - -**complexity**: The computing complexity of this function is proportional to the length of the slice. No additional memory is required. - -## ext_scratch_write - -This function copies slice of data from the sandbox memory to the scratch buffer. The calling code specifies the slice length. Execution of the function consists of the following steps: - -1. Loading a slice from the sandbox memory into the (see sandboxing memory get) - -**complexity**: Complexity is proportional to the length of the slice. - -## ext_set_rent_allowance +### ext_set_rent_allowance This function receives the following argument: @@ -457,22 +445,6 @@ It consists of the following steps: **complexity**: Complexity is proportional to the size of the `value`. This function induces a DB write of size proportional to the `value` size (if flushed to the storage), so should be priced accordingly. -## ext_rent_allowance - -It consists of the following steps: - -1. Invoking `get_rent_allowance` AccountDB function. -2. Serializing the rent allowance of the current contract into the scratch buffer. - -**complexity**: Assuming that the rent allowance is of constant size, this function has constant complexity. This -function performs a DB read. - -## ext_block_number - -This function serializes the current block's number into the scratch buffer. - -**complexity**: Assuming that the block number is of constant size, this function has constant complexity. - ## Built-in hashing functions This paragraph concerns the following supported built-in hash functions: diff --git a/frame/contracts/Cargo.toml b/frame/contracts/Cargo.toml index a9318002cee2a71d290b56687f7123d5a1f994d7..df5a47bb0e0b3cd6b95aef870f63c1e346b81b81 100644 --- a/frame/contracts/Cargo.toml +++ b/frame/contracts/Cargo.toml @@ -1,35 +1,40 @@ [package] name = "pallet-contracts" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for WASM contracts" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true, features = ["derive"] } pwasm-utils = { version = "0.12.0", default-features = false } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } parity-wasm = { version = "0.41.0", default-features = false } wasmi-validation = { version = "0.3.0", default-features = false } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/core" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/io" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-sandbox = { version = "0.8.0-alpha.5", default-features = false, path = "../../primitives/sandbox" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } -pallet-contracts-primitives = { version = "2.0.0-alpha.5", default-features = false, path = "common" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/core" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-sandbox = { version = "0.8.0-rc4", default-features = false, path = "../../primitives/sandbox" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } +pallet-contracts-primitives = { version = "2.0.0-rc4", default-features = false, path = "common" } +bitflags = "1.0" [dev-dependencies] wabt = "0.9.2" assert_matches = "1.3.0" hex-literal = "0.2.1" -pallet-balances = { version = "2.0.0-alpha.5", path = "../balances" } -pallet-timestamp = { version = "2.0.0-alpha.5", path = "../timestamp" } -pallet-randomness-collective-flip = { version = "2.0.0-alpha.5", path = "../randomness-collective-flip" } +pretty_assertions = "0.6.1" +pallet-balances = { version = "2.0.0-rc4", path = "../balances" } +pallet-timestamp = { version = "2.0.0-rc4", path = "../timestamp" } +pallet-randomness-collective-flip = { version = "2.0.0-rc4", path = "../randomness-collective-flip" } [features] default = ["std"] @@ -48,6 +53,3 @@ std = [ "wasmi-validation/std", "pallet-contracts-primitives/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/contracts/common/Cargo.toml b/frame/contracts/common/Cargo.toml index d181896bd2a6c2bf4d25524e7fec277823f3cd02..e6e2bc653a21841acfcc7ba243620e1c3b014d14 100644 --- a/frame/contracts/common/Cargo.toml +++ b/frame/contracts/common/Cargo.toml @@ -1,18 +1,21 @@ [package] name = "pallet-contracts-primitives" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "A crate that hosts a common definitions that are relevant for the pallet-contracts." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] # This crate should not rely on any of the frame primitives. -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/std" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/runtime" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/std" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/runtime" } [features] default = ["std"] @@ -21,6 +24,3 @@ std = [ "sp-runtime/std", "sp-std/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/contracts/fixtures/caller_contract.wat b/frame/contracts/fixtures/caller_contract.wat new file mode 100644 index 0000000000000000000000000000000000000000..369007834dc7b0684fd719118068ca2019690b28 --- /dev/null +++ b/frame/contracts/fixtures/caller_contract.wat @@ -0,0 +1,284 @@ +(module + (import "env" "ext_input" (func $ext_input (param i32 i32))) + (import "env" "ext_balance" (func $ext_balance (param i32 i32))) + (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32))) + (import "env" "ext_instantiate" (func $ext_instantiate (param i32 i32 i64 i32 i32 i32 i32 i32 i32 i32 i32) (result i32))) + (import "env" "ext_println" (func $ext_println (param i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func $current_balance (param $sp i32) (result i64) + (i32.store + (i32.sub (get_local $sp) (i32.const 16)) + (i32.const 8) + ) + (call $ext_balance + (i32.sub (get_local $sp) (i32.const 8)) + (i32.sub (get_local $sp) (i32.const 16)) + ) + (call $assert + (i32.eq (i32.load (i32.sub (get_local $sp) (i32.const 16))) (i32.const 8)) + ) + (i64.load (i32.sub (get_local $sp) (i32.const 8))) + ) + + (func (export "deploy")) + + (func (export "call") + (local $sp i32) + (local $exit_code i32) + (local $balance i64) + + ;; Length of the buffer + (i32.store (i32.const 20) (i32.const 32)) + + ;; Copy input to this contracts memory + (call $ext_input (i32.const 24) (i32.const 20)) + + ;; Input data is the code hash of the contract to be deployed. + (call $assert + (i32.eq + (i32.load (i32.const 20)) + (i32.const 32) + ) + ) + + ;; Read current balance into local variable. + (set_local $sp (i32.const 1024)) + (set_local $balance + (call $current_balance (get_local $sp)) + ) + + ;; Fail to deploy the contract since it returns a non-zero exit status. + (set_local $exit_code + (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. + (i32.const 0) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer. + (i32.const 9) ;; Pointer to input data buffer address + (i32.const 7) ;; Length of input data buffer + (i32.const 4294967295) ;; u32 max sentinel value: do not copy address + (i32.const 0) ;; Length is ignored in this case + (i32.const 4294967295) ;; u32 max sentinel value: do not copy output + (i32.const 0) ;; Length is ignored in this case + ) + ) + + ;; Check non-zero exit status. + (call $assert + (i32.eq (get_local $exit_code) (i32.const 2)) ;; ReturnCode::CalleeReverted + ) + + ;; Check that balance has not changed. + (call $assert + (i64.eq (get_local $balance) (call $current_balance (get_local $sp))) + ) + + ;; Fail to deploy the contract due to insufficient gas. + (set_local $exit_code + (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. + (i32.const 0) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer. + (i32.const 8) ;; Pointer to input data buffer address + (i32.const 8) ;; Length of input data buffer + (i32.const 4294967295) ;; u32 max sentinel value: do not copy address + (i32.const 0) ;; Length is ignored in this case + (i32.const 4294967295) ;; u32 max sentinel value: do not copy output + (i32.const 0) ;; Length is ignored in this case + ) + ) + + ;; Check for special trap exit status. + (call $assert + (i32.eq (get_local $exit_code) (i32.const 1)) ;; ReturnCode::CalleeTrapped + ) + + ;; Check that balance has not changed. + (call $assert + (i64.eq (get_local $balance) (call $current_balance (get_local $sp))) + ) + + ;; Length of the output buffer + (i32.store + (i32.sub (get_local $sp) (i32.const 4)) + (i32.const 8) + ) + + ;; Deploy the contract successfully. + (set_local $exit_code + (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. + (i32.const 0) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer. + (i32.const 8) ;; Pointer to input data buffer address + (i32.const 8) ;; Length of input data buffer + (i32.const 16) ;; Pointer to the address output buffer + (i32.sub (get_local $sp) (i32.const 4)) ;; Pointer to the address buffer length + (i32.const 4294967295) ;; u32 max sentinel value: do not copy output + (i32.const 0) ;; Length is ignored in this case + + ) + ) + + ;; Check for success exit status. + (call $assert + (i32.eq (get_local $exit_code) (i32.const 0)) ;; ReturnCode::Success + ) + + ;; Check that address has the expected length + (call $assert + (i32.eq (i32.load (i32.sub (get_local $sp) (i32.const 4))) (i32.const 8)) + ) + + ;; Check that balance has been deducted. + (set_local $balance + (i64.sub (get_local $balance) (i64.load (i32.const 0))) + ) + (call $assert + (i64.eq (get_local $balance) (call $current_balance (get_local $sp))) + ) + + ;; Zero out destination buffer of output + (i32.store + (i32.sub (get_local $sp) (i32.const 4)) + (i32.const 0) + ) + + ;; Length of the output buffer + (i32.store + (i32.sub (get_local $sp) (i32.const 8)) + (i32.const 4) + ) + + ;; Call the new contract and expect it to return failing exit code. + (set_local $exit_code + (call $ext_call + (i32.const 16) ;; Pointer to "callee" address. + (i32.const 8) ;; Length of "callee" 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 9) ;; Pointer to input data buffer address + (i32.const 7) ;; Length of input data buffer + (i32.sub (get_local $sp) (i32.const 4)) ;; Ptr to output buffer + (i32.sub (get_local $sp) (i32.const 8)) ;; Ptr to output buffer len + ) + ) + + ;; Check non-zero exit status. + (call $assert + (i32.eq (get_local $exit_code) (i32.const 2)) ;; ReturnCode::CalleeReverted + ) + + ;; Check that output buffer contains the expected return data. + (call $assert + (i32.eq (i32.load (i32.sub (get_local $sp) (i32.const 8))) (i32.const 3)) + ) + (call $assert + (i32.eq + (i32.load (i32.sub (get_local $sp) (i32.const 4))) + (i32.const 0x00776655) + ) + ) + + ;; Check that balance has not changed. + (call $assert + (i64.eq (get_local $balance) (call $current_balance (get_local $sp))) + ) + + ;; Fail to call the contract due to insufficient gas. + (set_local $exit_code + (call $ext_call + (i32.const 16) ;; Pointer to "callee" address. + (i32.const 8) ;; Length of "callee" address. + (i64.const 100) ;; How much gas to devote for the execution. + (i32.const 0) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer. + (i32.const 8) ;; Pointer to input data buffer address + (i32.const 8) ;; Length of input data buffer + (i32.const 4294967295) ;; u32 max sentinel value: do not copy output + (i32.const 0) ;; Length is ignored in this cas + ) + ) + + ;; Check for special trap exit status. + (call $assert + (i32.eq (get_local $exit_code) (i32.const 1)) ;; ReturnCode::CalleeTrapped + ) + + ;; Check that balance has not changed. + (call $assert + (i64.eq (get_local $balance) (call $current_balance (get_local $sp))) + ) + + ;; Zero out destination buffer of output + (i32.store + (i32.sub (get_local $sp) (i32.const 4)) + (i32.const 0) + ) + + ;; Length of the output buffer + (i32.store + (i32.sub (get_local $sp) (i32.const 8)) + (i32.const 4) + ) + + ;; Call the contract successfully. + (set_local $exit_code + (call $ext_call + (i32.const 16) ;; Pointer to "callee" address. + (i32.const 8) ;; Length of "callee" 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 8) ;; Pointer to input data buffer address + (i32.const 8) ;; Length of input data buffer + (i32.sub (get_local $sp) (i32.const 4)) ;; Ptr to output buffer + (i32.sub (get_local $sp) (i32.const 8)) ;; Ptr to output buffer len + ) + ) + + ;; Check for success exit status. + (call $assert + (i32.eq (get_local $exit_code) (i32.const 0)) ;; ReturnCode::Success + ) + + ;; Check that the output buffer contains the expected return data. + (call $assert + (i32.eq (i32.load (i32.sub (get_local $sp) (i32.const 8))) (i32.const 4)) + ) + (call $assert + (i32.eq + (i32.load (i32.sub (get_local $sp) (i32.const 4))) + (i32.const 0x77665544) + ) + ) + + ;; Check that balance has been deducted. + (set_local $balance + (i64.sub (get_local $balance) (i64.load (i32.const 0))) + ) + (call $assert + (i64.eq (get_local $balance) (call $current_balance (get_local $sp))) + ) + ) + + (data (i32.const 0) "\00\80") ;; The value to transfer on instantiation and calls. + ;; Chosen to be greater than existential deposit. + (data (i32.const 8) "\00\01\22\33\44\55\66\77") ;; The input data to instantiations and calls. +) diff --git a/frame/contracts/fixtures/check_default_rent_allowance.wat b/frame/contracts/fixtures/check_default_rent_allowance.wat new file mode 100644 index 0000000000000000000000000000000000000000..b3076a04325e30e05b754f0bcdc0f59611cdf180 --- /dev/null +++ b/frame/contracts/fixtures/check_default_rent_allowance.wat @@ -0,0 +1,43 @@ +(module + (import "env" "ext_rent_allowance" (func $ext_rent_allowance (param i32 i32))) + (import "env" "memory" (memory 1 1)) + + ;; [0, 8) reserved for $ext_rent_allowance output + + ;; [8, 16) length of the buffer + (data (i32.const 8) "\08") + + ;; [16, inf) zero initialized + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call")) + + (func (export "deploy") + ;; fill the buffer with the rent allowance. + (call $ext_rent_allowance (i32.const 0) (i32.const 8)) + + ;; assert len == 8 + (call $assert + (i32.eq + (i32.load (i32.const 8)) + (i32.const 8) + ) + ) + + ;; assert that contents of the buffer is equal to >::max_value(). + (call $assert + (i64.eq + (i64.load (i32.const 0)) + (i64.const 0xFFFFFFFFFFFFFFFF) + ) + ) + ) +) diff --git a/frame/contracts/fixtures/crypto_hashes.wat b/frame/contracts/fixtures/crypto_hashes.wat new file mode 100644 index 0000000000000000000000000000000000000000..f7b244b8c1e369471a93b86845179c2098378e3e --- /dev/null +++ b/frame/contracts/fixtures/crypto_hashes.wat @@ -0,0 +1,81 @@ +(module + (import "env" "ext_input" (func $ext_input (param i32 i32))) + (import "env" "ext_return" (func $ext_return (param i32 i32 i32))) + + (import "env" "ext_hash_sha2_256" (func $ext_hash_sha2_256 (param i32 i32 i32))) + (import "env" "ext_hash_keccak_256" (func $ext_hash_keccak_256 (param i32 i32 i32))) + (import "env" "ext_hash_blake2_256" (func $ext_hash_blake2_256 (param i32 i32 i32))) + (import "env" "ext_hash_blake2_128" (func $ext_hash_blake2_128 (param i32 i32 i32))) + + (import "env" "memory" (memory 1 1)) + + (type $hash_fn_sig (func (param i32 i32 i32))) + (table 8 funcref) + (elem (i32.const 1) + $ext_hash_sha2_256 + $ext_hash_keccak_256 + $ext_hash_blake2_256 + $ext_hash_blake2_128 + ) + (data (i32.const 1) "20202010201008") ;; Output sizes of the hashes in order in hex. + + ;; Not in use by the tests besides instantiating the contract. + (func (export "deploy")) + + ;; Called by the tests. + ;; + ;; The `call` function expects data in a certain format in the input buffer. + ;; + ;; 1. The first byte encodes an identifier for the crypto hash function + ;; under test. (*) + ;; 2. The rest encodes the input data that is directly fed into the + ;; crypto hash function chosen in 1. + ;; + ;; The `deploy` function then computes the chosen crypto hash function + ;; given the input and puts the result into the output buffer. + ;; After contract execution the test driver then asserts that the returned + ;; values are equal to the expected bytes for the input and chosen hash + ;; function. + ;; + ;; (*) The possible value for the crypto hash identifiers can be found below: + ;; + ;; | value | Algorithm | Bit Width | + ;; |-------|-----------|-----------| + ;; | 0 | SHA2 | 256 | + ;; | 1 | KECCAK | 256 | + ;; | 2 | BLAKE2 | 256 | + ;; | 3 | BLAKE2 | 128 | + ;; --------------------------------- + (func (export "call") + (local $chosen_hash_fn i32) + (local $input_len_ptr i32) + (local $input_ptr i32) + (local $input_len i32) + (local $output_ptr i32) + (local $output_len i32) + (local.set $input_len_ptr (i32.const 256)) + (local.set $input_ptr (i32.const 10)) + (i32.store (local.get $input_len_ptr) (i32.const 246)) + (call $ext_input (local.get $input_ptr) (local.get $input_len_ptr)) + (local.set $chosen_hash_fn (i32.load8_u (local.get $input_ptr))) + (if (i32.gt_u (local.get $chosen_hash_fn) (i32.const 7)) + ;; We check that the chosen hash fn identifier is within bounds: [0,7] + (unreachable) + ) + (local.set $input_ptr (i32.add (local.get $input_ptr) (i32.const 1))) + (local.set $input_len (i32.sub (i32.load (local.get $input_len_ptr)) (i32.const 1))) + (local.set $output_len (i32.load8_u (local.get $chosen_hash_fn))) + (call_indirect (type $hash_fn_sig) + (local.get $input_ptr) + (local.get $input_len) + (local.get $input_ptr) + (local.get $chosen_hash_fn) ;; Which crypto hash function to execute. + ) + (call $ext_return + (i32.const 0) + (local.get $input_ptr) ;; Linear memory location of the output buffer. + (local.get $output_len) ;; Number of output buffer bytes. + ) + (unreachable) + ) +) diff --git a/frame/contracts/fixtures/destroy_and_transfer.wat b/frame/contracts/fixtures/destroy_and_transfer.wat new file mode 100644 index 0000000000000000000000000000000000000000..ee191aa019bfb5f60126c3face20aff2a687c8a2 --- /dev/null +++ b/frame/contracts/fixtures/destroy_and_transfer.wat @@ -0,0 +1,157 @@ +(module + (import "env" "ext_input" (func $ext_input (param i32 i32))) + (import "env" "ext_get_storage" (func $ext_get_storage (param i32 i32 i32) (result i32))) + (import "env" "ext_set_storage" (func $ext_set_storage (param i32 i32 i32))) + (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32))) + (import "env" "ext_instantiate" (func $ext_instantiate (param i32 i32 i64 i32 i32 i32 i32 i32 i32 i32 i32) (result i32))) + (import "env" "memory" (memory 1 1)) + + ;; [0, 8) Endowment to send when creating contract. + (data (i32.const 0) "\00\00\01") + + ;; [8, 16) Value to send when calling contract. + + ;; [16, 48) The key to store the contract address under. + + ;; [48, 80) Buffer where to store the input to the contract + + ;; [80, 88) Buffer where to store the address of the instantiated contract + + ;; [88, 96) Size of the buffer + (data (i32.const 88) "\08") + + ;; [96, 100) Size of the input buffer + (data (i32.const 96) "\20") + + (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 $ext_input (i32.const 48) (i32.const 96)) + (call $assert + (i32.eq + (i32.load (i32.const 96)) + (i32.const 32) + ) + ) + + ;; 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 80) ;; Buffer where to store address of new contract + (i32.const 88) ;; Pointer to the length of the buffer + (i32.const 4294967295) ;; u32 max sentinel value: do not copy output + (i32.const 0) ;; Length is ignored in this cas + ) + (i32.const 0) + ) + ) + + ;; Check that address has expected length + (call $assert + (i32.eq + (i32.load (i32.const 88)) + (i32.const 8) + ) + ) + + ;; Store the return address. + (call $ext_set_storage + (i32.const 16) ;; Pointer to the key + (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 80) ;; Pointer to the value + (i32.const 88) ;; Pointer to the len of the value + ) + (i32.const 0) + ) + ) + (call $assert + (i32.eq + (i32.load (i32.const 88)) + (i32.const 8) + ) + ) + + ;; 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 4294967295) ;; u32 max sentinel value: do not copy output + (i32.const 0) ;; Length is ignored in this case + + ) + (i32.const 0x1) + ) + ) + + ;; 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 4294967295) ;; u32 max sentinel value: do not copy output + (i32.const 0) ;; Length is ignored in this case + ) + (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 4294967295) ;; u32 max sentinel value: do not copy output + (i32.const 0) ;; Length is ignored in this case + ) + (i32.const 0) + ) + ) + ) +) diff --git a/frame/contracts/fixtures/drain.wat b/frame/contracts/fixtures/drain.wat new file mode 100644 index 0000000000000000000000000000000000000000..1b3172b2a01a4b620df2a57b08536ee120b272f1 --- /dev/null +++ b/frame/contracts/fixtures/drain.wat @@ -0,0 +1,54 @@ +(module + (import "env" "ext_balance" (func $ext_balance (param i32 i32))) + (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32))) + (import "env" "memory" (memory 1 1)) + + ;; [0, 8) reserved for $ext_balance output + + ;; [8, 16) length of the buffer + (data (i32.const 8) "\08") + + ;; [16, inf) zero initialized + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "deploy")) + + (func (export "call") + ;; Send entire remaining balance to the 0 address. + (call $ext_balance (i32.const 0) (i32.const 8)) + + ;; Balance should be encoded as a u64. + (call $assert + (i32.eq + (i32.load (i32.const 8)) + (i32.const 8) + ) + ) + + ;; Self-destruct by sending full balance to the 0 address. + (call $assert + (i32.eq + (call $ext_call + (i32.const 16) ;; 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 0) ;; Length of input data buffer + (i32.const 4294967295) ;; u32 max sentinel value: do not copy output + (i32.const 0) ;; Length is ignored in this case + ) + (i32.const 0) + ) + ) + ) +) diff --git a/frame/contracts/fixtures/restoration.wat b/frame/contracts/fixtures/restoration.wat new file mode 100644 index 0000000000000000000000000000000000000000..4107587ada7f538253126977a6fe2f1dbbe8d64a --- /dev/null +++ b/frame/contracts/fixtures/restoration.wat @@ -0,0 +1,78 @@ +(module + (import "env" "ext_set_storage" (func $ext_set_storage (param i32 i32 i32))) + (import "env" "ext_input" (func $ext_input (param i32 i32))) + (import "env" "ext_restore_to" + (func $ext_restore_to + (param i32 i32 i32 i32 i32 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") + ;; copy code hash to contract memory + (call $ext_input (i32.const 264) (i32.const 304)) + (call $assert + (i32.eq + (i32.load (i32.const 304)) + (i32.const 32) + ) + ) + + (call $ext_restore_to + ;; Pointer and length of the encoded dest buffer. + (i32.const 256) + (i32.const 8) + ;; Pointer and length of the encoded code hash buffer + (i32.const 264) + (i32.const 32) + ;; Pointer and length of the encoded rent_allowance buffer + (i32.const 296) + (i32.const 8) + ;; Pointer and number of items in the delta buffer. + ;; This buffer specifies multiple keys for removal before restoration. + (i32.const 100) + (i32.const 1) + ) + ) + (func (export "deploy") + ;; Data to restore + (call $ext_set_storage + (i32.const 0) + (i32.const 0) + (i32.const 4) + ) + + ;; ACL + (call $ext_set_storage + (i32.const 100) + (i32.const 0) + (i32.const 4) + ) + ) + + ;; Data to restore + (data (i32.const 0) "\28") + + ;; Buffer that has ACL storage keys. + (data (i32.const 100) "\01") + + ;; Address of bob + (data (i32.const 256) "\02\00\00\00\00\00\00\00") + + ;; [264, 296) Code hash of SET_RENT (copied here by ext_input) + + ;; [296, 304) Rent allowance + (data (i32.const 296) "\32\00\00\00\00\00\00\00") + + ;; [304, 308) Size of SET_RENT buffer + (data (i32.const 304) "\20") +) diff --git a/frame/contracts/fixtures/return_from_start_fn.wat b/frame/contracts/fixtures/return_from_start_fn.wat new file mode 100644 index 0000000000000000000000000000000000000000..ba73ef25ed39aa885194acd042f8084376bcd4a1 --- /dev/null +++ b/frame/contracts/fixtures/return_from_start_fn.wat @@ -0,0 +1,28 @@ +(module + (import "env" "ext_return" (func $ext_return (param i32 i32 i32))) + (import "env" "ext_deposit_event" (func $ext_deposit_event (param i32 i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + (start $start) + (func $start + (call $ext_deposit_event + (i32.const 0) ;; The topics buffer + (i32.const 0) ;; The topics buffer's length + (i32.const 8) ;; The data buffer + (i32.const 4) ;; The data buffer's length + ) + (call $ext_return + (i32.const 0) + (i32.const 8) + (i32.const 4) + ) + (unreachable) + ) + + (func (export "call") + (unreachable) + ) + (func (export "deploy")) + + (data (i32.const 8) "\01\02\03\04") +) diff --git a/frame/contracts/fixtures/return_with_data.wat b/frame/contracts/fixtures/return_with_data.wat new file mode 100644 index 0000000000000000000000000000000000000000..ad42845ae02088089105a633cad277eb46381054 --- /dev/null +++ b/frame/contracts/fixtures/return_with_data.wat @@ -0,0 +1,33 @@ +(module + (import "env" "ext_input" (func $ext_input (param i32 i32))) + (import "env" "ext_return" (func $ext_return (param i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + ;; [0, 128) buffer where input is copied + + ;; [128, 132) length of the input buffer + (data (i32.const 128) "\80") + + ;; Deploy routine is the same as call. + (func (export "deploy") + (call $call) + ) + + ;; Call reads the first 4 bytes (LE) as the exit status and returns the rest as output data. + (func $call (export "call") + ;; Copy input into this contracts memory. + (call $ext_input (i32.const 0) (i32.const 128)) + + ;; Copy all but the first 4 bytes of the input data as the output data. + ;; Use the first byte as exit status + (call $ext_return + (i32.load8_u (i32.const 0)) ;; Exit status + (i32.const 4) ;; Pointer to the data to return. + (i32.sub ;; Count of bytes to copy. + (i32.load (i32.const 128)) + (i32.const 4) + ) + ) + (unreachable) + ) +) diff --git a/frame/contracts/fixtures/run_out_of_gas.wat b/frame/contracts/fixtures/run_out_of_gas.wat new file mode 100644 index 0000000000000000000000000000000000000000..52ee92539fd521d656235cc3f3feb555bcd12cb9 --- /dev/null +++ b/frame/contracts/fixtures/run_out_of_gas.wat @@ -0,0 +1,7 @@ +(module + (func (export "call") + (loop $inf (br $inf)) ;; just run out of gas + (unreachable) + ) + (func (export "deploy")) +) diff --git a/frame/contracts/fixtures/self_destruct.wat b/frame/contracts/fixtures/self_destruct.wat new file mode 100644 index 0000000000000000000000000000000000000000..baa38e4d47be8a11f801ae3652ae8a995ce1f60f --- /dev/null +++ b/frame/contracts/fixtures/self_destruct.wat @@ -0,0 +1,80 @@ +(module + (import "env" "ext_input" (func $ext_input (param i32 i32))) + (import "env" "ext_address" (func $ext_address (param i32 i32))) + (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32))) + (import "env" "ext_terminate" (func $ext_terminate (param i32 i32))) + (import "env" "memory" (memory 1 1)) + + ;; [0, 8) reserved for $ext_address output + + ;; [8, 16) length of the buffer + (data (i32.const 8) "\08") + + ;; [16, 24) Address of django + (data (i32.const 16) "\04\00\00\00\00\00\00\00") + + ;; [24, 32) reserved for output of $ext_input + + ;; [32, 36) length of the buffer + (data (i32.const 32) "\04") + + ;; [36, inf) zero initialized + + (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. + (call $ext_input (i32.const 24) (i32.const 32)) + (if (i32.load (i32.const 32)) + (then + (call $ext_address (i32.const 0) (i32.const 8)) + + ;; Expect address to be 8 bytes. + (call $assert + (i32.eq + (i32.load (i32.const 8)) + (i32.const 8) + ) + ) + + ;; Recursively call self with empty input data. + (call $assert + (i32.eq + (call $ext_call + (i32.const 0) ;; 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 36) ;; 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 4294967295) ;; u32 max sentinel value: do not copy output + (i32.const 0) ;; Length is ignored in this case + ) + (i32.const 0) + ) + ) + ) + (else + ;; Try to terminate and give balance to django. + (call $ext_terminate + (i32.const 16) ;; Pointer to beneficiary address + (i32.const 8) ;; Length of beneficiary address + ) + (unreachable) ;; ext_terminate never returns + ) + ) + ) +) diff --git a/frame/contracts/fixtures/self_destructing_constructor.wat b/frame/contracts/fixtures/self_destructing_constructor.wat new file mode 100644 index 0000000000000000000000000000000000000000..3b99db001cd38a77039b1b8ef4eb8beaf46bd26b --- /dev/null +++ b/frame/contracts/fixtures/self_destructing_constructor.wat @@ -0,0 +1,54 @@ +(module + (import "env" "ext_balance" (func $ext_balance (param i32 i32))) + (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32))) + (import "env" "memory" (memory 1 1)) + + ;; [0, 8) reserved for $ext_balance output + + ;; [8, 16) length of the buffer + (data (i32.const 8) "\08") + + ;; [16, inf) zero initialized + + (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 (i32.const 0) (i32.const 8)) + + ;; Balance should be encoded as a u64. + (call $assert + (i32.eq + (i32.load (i32.const 8)) + (i32.const 8) + ) + ) + + ;; Self-destruct by sending full balance to the 0 address. + (call $assert + (i32.eq + (call $ext_call + (i32.const 16) ;; 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 0) ;; Length of input data buffer + (i32.const 4294967295) ;; u32 max sentinel value: do not copy output + (i32.const 0) ;; Length is ignored in this case + ) + (i32.const 0) + ) + ) + ) + + (func (export "call")) +) diff --git a/frame/contracts/fixtures/set_empty_storage.wat b/frame/contracts/fixtures/set_empty_storage.wat new file mode 100644 index 0000000000000000000000000000000000000000..d550eb2314b86d0dbb187887f23c8894a18f7348 --- /dev/null +++ b/frame/contracts/fixtures/set_empty_storage.wat @@ -0,0 +1,15 @@ +;; This module stores a KV pair into the storage +(module + (import "env" "ext_set_storage" (func $ext_set_storage (param i32 i32 i32))) + (import "env" "memory" (memory 16 16)) + + (func (export "call") + ) + (func (export "deploy") + (call $ext_set_storage + (i32.const 0) ;; Pointer to storage key + (i32.const 0) ;; Pointer to value + (i32.load (i32.const 0)) ;; Size of value + ) + ) +) diff --git a/frame/contracts/fixtures/set_rent.wat b/frame/contracts/fixtures/set_rent.wat new file mode 100644 index 0000000000000000000000000000000000000000..4e6424e7201045d011ecf3367d704a2aa25daa82 --- /dev/null +++ b/frame/contracts/fixtures/set_rent.wat @@ -0,0 +1,100 @@ +(module + (import "env" "ext_transfer" (func $ext_transfer (param i32 i32 i32 i32))) + (import "env" "ext_set_storage" (func $ext_set_storage (param i32 i32 i32))) + (import "env" "ext_clear_storage" (func $ext_clear_storage (param i32))) + (import "env" "ext_set_rent_allowance" (func $ext_set_rent_allowance (param i32 i32))) + (import "env" "ext_input" (func $ext_input (param i32 i32))) + (import "env" "memory" (memory 1 1)) + + ;; insert a value of 4 bytes into storage + (func $call_0 + (call $ext_set_storage + (i32.const 1) + (i32.const 0) + (i32.const 4) + ) + ) + + ;; remove the value inserted by call_1 + (func $call_1 + (call $ext_clear_storage + (i32.const 1) + ) + ) + + ;; transfer 50 to CHARLIE + (func $call_2 + (call $ext_transfer (i32.const 68) (i32.const 8) (i32.const 76) (i32.const 8)) + ) + + ;; do nothing + (func $call_else) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + ;; Dispatch the call according to input size + (func (export "call") + (local $input_size i32) + (i32.store (i32.const 64) (i32.const 64)) + (call $ext_input (i32.const 1024) (i32.const 64)) + (set_local $input_size + (i32.load (i32.const 64)) + ) + (block $IF_ELSE + (block $IF_2 + (block $IF_1 + (block $IF_0 + (br_table $IF_0 $IF_1 $IF_2 $IF_ELSE + (get_local $input_size) + ) + (unreachable) + ) + (call $call_0) + return + ) + (call $call_1) + return + ) + (call $call_2) + return + ) + (call $call_else) + ) + + ;; Set into storage a 4 bytes value + ;; Set call set_rent_allowance with input + (func (export "deploy") + (call $ext_set_storage + (i32.const 0) + (i32.const 0) + (i32.const 4) + ) + (call $ext_input + (i32.const 0) + (i32.const 64) + ) + (call $ext_set_rent_allowance + (i32.const 0) + (i32.load (i32.const 64)) + ) + ) + + ;; Encoding of 10 in balance + (data (i32.const 0) "\28") + + ;; Size of the buffer at address 0 + (data (i32.const 64) "\40") + + ;; encoding of Charlies's account id + (data (i32.const 68) "\03") + + ;; encoding of 50 balance + (data (i32.const 76) "\32") +) diff --git a/frame/contracts/fixtures/storage_size.wat b/frame/contracts/fixtures/storage_size.wat new file mode 100644 index 0000000000000000000000000000000000000000..579aeda3a064dabebe78ab2a47a0aa797326dc5a --- /dev/null +++ b/frame/contracts/fixtures/storage_size.wat @@ -0,0 +1,68 @@ +(module + (import "env" "ext_get_storage" (func $ext_get_storage (param i32 i32 i32) (result i32))) + (import "env" "ext_set_storage" (func $ext_set_storage (param i32 i32 i32))) + (import "env" "ext_input" (func $ext_input (param i32 i32))) + (import "env" "memory" (memory 16 16)) + + ;; [0, 32) storage key + (data (i32.const 0) "\01") + + ;; [32, 36) buffer where input is copied (expected size of storage item) + + ;; [36, 40) size of the input buffer + (data (i32.const 36) "\04") + + ;; [40, 44) size of buffer for ext_get_storage set to max + (data (i32.const 40) "\FF\FF\FF\FF") + + ;; [44, inf) ext_get_storage buffer + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call") + (call $ext_input (i32.const 32) (i32.const 36)) + + ;; assert input size == 4 + (call $assert + (i32.eq + (i32.load (i32.const 36)) + (i32.const 4) + ) + ) + + ;; place a garbage value in storage, the size of which is specified by the call input. + (call $ext_set_storage + (i32.const 0) ;; Pointer to storage key + (i32.const 0) ;; Pointer to value + (i32.load (i32.const 32)) ;; Size of value + ) + + (call $assert + (i32.eq + (call $ext_get_storage + (i32.const 0) ;; Pointer to storage key + (i32.const 44) ;; buffer where to copy result + (i32.const 40) ;; pointer to size of buffer + ) + (i32.const 0) + ) + ) + + (call $assert + (i32.eq + (i32.load (i32.const 40)) + (i32.load (i32.const 32)) + ) + ) + ) + + (func (export "deploy")) + +) diff --git a/frame/contracts/rpc/Cargo.toml b/frame/contracts/rpc/Cargo.toml index fa13d8ec3fe4a3fbca2f89750772a3f3a8f91251..35989a349049c6cb9eb1d3e42e3655d365fc39da 100644 --- a/frame/contracts/rpc/Cargo.toml +++ b/frame/contracts/rpc/Cargo.toml @@ -1,29 +1,29 @@ [package] name = "pallet-contracts-rpc" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Node-specific RPC methods for interaction with contracts." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0" } -jsonrpc-core = "14.0.3" -jsonrpc-core-client = "14.0.5" -jsonrpc-derive = "14.0.3" -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../../primitives/blockchain" } -sp-core = { version = "2.0.0-alpha.5", path = "../../../primitives/core" } -sp-rpc = { version = "2.0.0-alpha.5", path = "../../../primitives/rpc" } +codec = { package = "parity-scale-codec", version = "1.3.1" } +jsonrpc-core = "14.2.0" +jsonrpc-core-client = "14.2.0" +jsonrpc-derive = "14.2.1" +sp-blockchain = { version = "2.0.0-rc4", path = "../../../primitives/blockchain" } +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } +sp-rpc = { version = "2.0.0-rc4", path = "../../../primitives/rpc" } serde = { version = "1.0.101", features = ["derive"] } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime" } -sp-api = { version = "2.0.0-alpha.5", path = "../../../primitives/api" } -pallet-contracts-primitives = { version = "2.0.0-alpha.5", path = "../common" } -pallet-contracts-rpc-runtime-api = { version = "0.8.0-alpha.5", path = "./runtime-api" } +sp-runtime = { version = "2.0.0-rc4", path = "../../../primitives/runtime" } +sp-api = { version = "2.0.0-rc4", path = "../../../primitives/api" } +pallet-contracts-primitives = { version = "2.0.0-rc4", path = "../common" } +pallet-contracts-rpc-runtime-api = { version = "0.8.0-rc4", path = "./runtime-api" } [dev-dependencies] serde_json = "1.0.41" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/contracts/rpc/runtime-api/Cargo.toml b/frame/contracts/rpc/runtime-api/Cargo.toml index 692bd3f25ef85b3c695240897cc55bb0546eddcd..e97003c44d94bc4cea9f8bd85c0eafb7c1717d30 100644 --- a/frame/contracts/rpc/runtime-api/Cargo.toml +++ b/frame/contracts/rpc/runtime-api/Cargo.toml @@ -1,19 +1,22 @@ [package] name = "pallet-contracts-rpc-runtime-api" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Runtime API definition required by Contracts RPC extensions." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-api = { version = "2.0.0-alpha.5", default-features = false, path = "../../../../primitives/api" } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../../../primitives/std" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../../../primitives/runtime" } -pallet-contracts-primitives = { version = "2.0.0-alpha.5", default-features = false, path = "../../common" } +sp-api = { version = "2.0.0-rc4", default-features = false, path = "../../../../primitives/api" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../../../primitives/std" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../../../primitives/runtime" } +pallet-contracts-primitives = { version = "2.0.0-rc4", default-features = false, path = "../../common" } [features] default = ["std"] @@ -24,6 +27,3 @@ std = [ "sp-runtime/std", "pallet-contracts-primitives/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/contracts/rpc/runtime-api/src/lib.rs b/frame/contracts/rpc/runtime-api/src/lib.rs index 6fb629b02458129e0bc8ffe13bdf363cd45479e1..7d208cf7763e7f2458cf507285dacaaa0cd2ce3f 100644 --- a/frame/contracts/rpc/runtime-api/src/lib.rs +++ b/frame/contracts/rpc/runtime-api/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Runtime API definition required by Contracts RPC extensions. //! @@ -34,12 +35,15 @@ pub enum ContractExecResult { /// /// There is a status code and, optionally, some data returned by the contract. Success { - /// Status code returned by the contract. - status: u8, + /// Flags that the contract passed along on returning to alter its exit behaviour. + /// Described in `pallet_contracts::exec::ReturnFlags`. + flags: u32, /// Output data returned by the contract. /// /// Can be empty. data: Vec, + /// How much gas was consumed by the call. + gas_consumed: u64, }, /// The contract execution either trapped or returned an error. Error, diff --git a/frame/contracts/rpc/src/lib.rs b/frame/contracts/rpc/src/lib.rs index 52dddb177bbc74538f869419d20beebd1cc2b916..d99ed1e78a652cd90006b1dabed65be2df2827c8 100644 --- a/frame/contracts/rpc/src/lib.rs +++ b/frame/contracts/rpc/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Node-specific RPC methods for interaction with contracts. @@ -31,6 +32,7 @@ use sp_runtime::{ generic::BlockId, traits::{Block as BlockT, Header as HeaderT}, }; +use std::convert::TryInto; pub use self::gen_client::Client as ContractsClient; pub use pallet_contracts_rpc_runtime_api::{ @@ -46,9 +48,10 @@ const CONTRACT_IS_A_TOMBSTONE: i64 = 3; /// This value is used to set the upper bound for maximal contract calls to /// prevent blocking the RPC for too long. /// -/// Based on W3F research spreadsheet: -/// https://docs.google.com/spreadsheets/d/1h0RqncdqiWI4KgxO0z9JIpZEJESXjX_ZCK6LFX6veDo/view -const GAS_PER_SECOND: u64 = 1_000_000_000; +/// As 1 gas is equal to 1 weight we base this on the conducted benchmarks which +/// determined runtime weights: +/// https://github.com/paritytech/substrate/pull/5446 +const GAS_PER_SECOND: u64 = 1_000_000_000_000; /// A private newtype for converting `ContractAccessError` into an RPC error. struct ContractAccessError(pallet_contracts_primitives::ContractAccessError); @@ -78,7 +81,7 @@ pub struct CallRequest { origin: AccountId, dest: AccountId, value: Balance, - gas_limit: number::NumberOrHex, + gas_limit: number::NumberOrHex, input_data: Bytes, } @@ -89,10 +92,12 @@ pub struct CallRequest { pub enum RpcContractExecResult { /// Successful execution Success { - /// Status code - status: u8, + /// The return flags + flags: u32, /// Output data data: Bytes, + /// How much gas was consumed by the call. + gas_consumed: u64, }, /// Error execution Error(()), @@ -101,9 +106,14 @@ pub enum RpcContractExecResult { impl From for RpcContractExecResult { fn from(r: ContractExecResult) -> Self { match r { - ContractExecResult::Success { status, data } => RpcContractExecResult::Success { - status, + ContractExecResult::Success { + flags, + data, + gas_consumed + } => RpcContractExecResult::Success { + flags, data: data.into(), + gas_consumed, }, ContractExecResult::Error => RpcContractExecResult::Error(()), } @@ -201,9 +211,11 @@ where gas_limit, input_data, } = call_request; - let gas_limit = gas_limit.to_number().map_err(|e| Error { + + // Make sure that gas_limit fits into 64 bits. + let gas_limit: u64 = gas_limit.try_into().map_err(|_| Error { code: ErrorCode::InvalidParams, - message: e, + message: format!("{:?} doesn't fit in 64 bit unsigned value", gas_limit), data: None, })?; @@ -280,16 +292,31 @@ fn runtime_error_into_rpc_err(err: impl std::fmt::Debug) -> Error { #[cfg(test)] mod tests { use super::*; + use sp_core::U256; + + #[test] + fn call_request_should_serialize_deserialize_properly() { + type Req = CallRequest; + let req: Req = serde_json::from_str(r#" + { + "origin": "5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL", + "dest": "5DRakbLVnjVrW6niwLfHGW24EeCEvDAFGEXrtaYS5M4ynoom", + "value": 0, + "gasLimit": 1000000000000, + "inputData": "0x8c97db39" + } + "#).unwrap(); + assert_eq!(req.gas_limit.into_u256(), U256::from(0xe8d4a51000u64)); + } #[test] - fn should_serialize_deserialize_properly() { + fn result_should_serialize_deserialize_properly() { fn test(expected: &str) { let res: RpcContractExecResult = serde_json::from_str(expected).unwrap(); let actual = serde_json::to_string(&res).unwrap(); assert_eq!(actual, expected); } - - test(r#"{"success":{"status":5,"data":"0x1234"}}"#); + test(r#"{"success":{"flags":5,"data":"0x1234","gas_consumed":5000}}"#); test(r#"{"error":null}"#); } } diff --git a/frame/contracts/src/account_db.rs b/frame/contracts/src/account_db.rs deleted file mode 100644 index 165581e67646df41afa60945e5baefd6e62feb30..0000000000000000000000000000000000000000 --- a/frame/contracts/src/account_db.rs +++ /dev/null @@ -1,389 +0,0 @@ -// Copyright 2018-2020 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 . - -//! Auxiliaries to help with managing partial changes to accounts state. - -use super::{ - AliveContractInfo, BalanceOf, CodeHash, ContractInfo, ContractInfoOf, Trait, TrieId, - TrieIdGenerator, -}; -use crate::exec::StorageKey; -use sp_std::cell::RefCell; -use sp_std::collections::btree_map::{BTreeMap, Entry}; -use sp_std::prelude::*; -use sp_io::hashing::blake2_256; -use sp_runtime::traits::{Bounded, Zero}; -use frame_support::traits::{Currency, Get, Imbalance, SignedImbalance}; -use frame_support::{storage::child, StorageMap}; -use frame_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 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. -impl Default for ChangeEntry { - fn default() -> Self { - ChangeEntry { - rent_allowance: Default::default(), - balance: Default::default(), - code_hash: Default::default(), - storage: Default::default(), - reset: false, - } - } -} - -pub type ChangeSet = BTreeMap<::AccountId, ChangeEntry>; - -pub trait AccountDb { - /// Account is used when overlayed otherwise trie_id must be provided. - /// This is for performance reason. - /// - /// Trie id is None iff account doesn't have an associated trie id in >. - /// Because DirectAccountDb bypass the lookup for this association. - fn get_storage(&self, account: &T::AccountId, trie_id: Option<&TrieId>, location: &StorageKey) -> Option>; - /// If account has an alive contract then return the code hash associated. - fn get_code_hash(&self, account: &T::AccountId) -> Option>; - /// If account has an alive contract then return the rent allowance associated. - fn get_rent_allowance(&self, account: &T::AccountId) -> Option>; - /// Returns false iff account has no alive contract nor tombstone. - fn contract_exists(&self, account: &T::AccountId) -> bool; - fn get_balance(&self, account: &T::AccountId) -> BalanceOf; - - fn commit(&mut self, change_set: ChangeSet); -} - -pub struct DirectAccountDb; -impl AccountDb for DirectAccountDb { - fn get_storage( - &self, - _account: &T::AccountId, - trie_id: Option<&TrieId>, - location: &StorageKey - ) -> Option> { - trie_id.and_then(|id| child::get_raw(id, crate::trie_unique_id(&id[..]), &blake2_256(location))) - } - fn get_code_hash(&self, account: &T::AccountId) -> Option> { - >::get(account).and_then(|i| i.as_alive().map(|i| i.code_hash)) - } - fn get_rent_allowance(&self, account: &T::AccountId) -> Option> { - >::get(account).and_then(|i| i.as_alive().map(|i| i.rent_allowance)) - } - fn contract_exists(&self, account: &T::AccountId) -> bool { - >::contains_key(account) - } - fn get_balance(&self, account: &T::AccountId) -> BalanceOf { - T::Currency::free_balance(account) - } - 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() { - let imbalance = T::Currency::make_free_balance_be(&address, balance); - total_imbalance = total_imbalance.merge(imbalance); - } - - 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), - None => None, - // Cannot commit changes to tombstone contract - Some(ContractInfo::Tombstone(_)) => continue, - }; - - 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, info.child_trie_unique_id()); - >::remove(&address); - continue; - } - // Existing contract is being replaced by a new one. - (true, Some(info), Some(code_hash)) => { - child::kill_storage(&info.trie_id, info.child_trie_unique_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 { - new_info.rent_allowance = rent_allowance; - } - - if let Some(code_hash) = changed.code_hash { - new_info.code_hash = code_hash; - } - - if !changed.storage.is_empty() { - new_info.last_write = Some(>::block_number()); - } - - for (k, v) in changed.storage.into_iter() { - if let Some(value) = child::get_raw( - &new_info.trie_id[..], - new_info.child_trie_unique_id(), - &blake2_256(&k), - ) { - new_info.storage_size -= value.len() as u32; - } - if let Some(value) = v { - new_info.storage_size += value.len() as u32; - child::put_raw(&new_info.trie_id[..], new_info.child_trie_unique_id(), &blake2_256(&k), &value[..]); - } else { - child::kill(&new_info.trie_id[..], new_info.child_trie_unique_id(), &blake2_256(&k)); - } - } - - if old_info - .map(|old_info| old_info != new_info) - .unwrap_or(true) - { - >::insert(&address, ContractInfo::Alive(new_info)); - } - } - } - - match total_imbalance { - // If we've detected a positive imbalance as a result of our contract-level machinations - // then it's indicative of a buggy contracts system. - // Panicking is far from ideal as it opens up a DoS attack on block validators, however - // it's a less bad option than allowing arbitrary value to be created. - SignedImbalance::Positive(ref p) if !p.peek().is_zero() => - panic!("contract subsystem resulting in positive imbalance!"), - _ => {} - } - } -} -pub struct OverlayAccountDb<'a, T: Trait + 'a> { - local: RefCell>, - underlying: &'a dyn AccountDb, -} -impl<'a, T: Trait> OverlayAccountDb<'a, T> { - pub fn new(underlying: &'a dyn AccountDb) -> OverlayAccountDb<'a, T> { - OverlayAccountDb { - local: RefCell::new(ChangeSet::new()), - underlying, - } - } - - pub fn into_change_set(self) -> ChangeSet { - self.local.into_inner() - } - - pub fn set_storage( - &mut self, - account: &T::AccountId, - location: StorageKey, - value: Option>, - ) { - self.local.borrow_mut() - .entry(account.clone()) - .or_insert(Default::default()) - .storage - .insert(location, value); - } - - /// Return an error if contract already exists (either if it is alive or tombstone) - pub fn instantiate_contract( - &mut self, - account: &T::AccountId, - code_hash: CodeHash, - ) -> Result<(), &'static str> { - if self.contract_exists(account) { - return Err("Alive contract or tombstone already exists"); - } - - let mut local = self.local.borrow_mut(); - let contract = local.entry(account.clone()).or_insert_with(|| Default::default()); - - contract.code_hash = Some(code_hash); - contract.rent_allowance = Some(>::max_value()); - - 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 - .borrow_mut() - .entry(account.clone()) - .or_insert(Default::default()) - .rent_allowance = Some(rent_allowance); - } - pub fn set_balance(&mut self, account: &T::AccountId, balance: BalanceOf) { - self.local - .borrow_mut() - .entry(account.clone()) - .or_insert(Default::default()) - .balance = Some(balance); - } -} - -impl<'a, T: Trait> AccountDb for OverlayAccountDb<'a, T> { - fn get_storage( - &self, - account: &T::AccountId, - trie_id: Option<&TrieId>, - location: &StorageKey - ) -> Option> { - self.local - .borrow() - .get(account) - .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()) - .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()) - .unwrap_or_else(|| self.underlying.get_rent_allowance(account)) - } - fn contract_exists(&self, account: &T::AccountId) -> bool { - self.local - .borrow() - .get(account) - .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(|changes| changes.balance()) - .unwrap_or_else(|| self.underlying.get_balance(account)) - } - fn commit(&mut self, s: ChangeSet) { - let mut local = self.local.borrow_mut(); - - for (address, changed) in s.into_iter() { - match local.entry(address) { - Entry::Occupied(e) => { - let mut value = e.into_mut(); - 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/frame/contracts/src/exec.rs b/frame/contracts/src/exec.rs index 402622331d0ecc33ae66a8920b0568aaad099dd2..67e2a4375e44c04aa74b332c271c8ecd3a40ded4 100644 --- a/frame/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -15,20 +15,19 @@ // along with Substrate. If not, see . use super::{CodeHash, Config, ContractAddressFor, Event, RawEvent, Trait, - TrieId, BalanceOf, ContractInfo}; -use crate::account_db::{AccountDb, DirectAccountDb, OverlayAccountDb}; -use crate::gas::{Gas, GasMeter, Token, approx_gas_for_balance}; -use crate::rent; - + TrieId, BalanceOf, ContractInfo, TrieIdGenerator}; +use crate::{gas::{Gas, GasMeter, Token}, rent, storage, Error, ContractInfoOf}; +use bitflags::bitflags; use sp_std::prelude::*; -use sp_runtime::traits::{Bounded, CheckedAdd, CheckedSub, Zero}; +use sp_runtime::traits::{Bounded, Zero, Convert, Saturating}; use frame_support::{ - storage::unhashed, dispatch::DispatchError, - traits::{WithdrawReason, Currency, Time, Randomness}, + dispatch::DispatchError, + traits::{ExistenceRequirement, Currency, Time, Randomness}, + weights::Weight, + ensure, StorageMap, }; pub type AccountIdOf = ::AccountId; -pub type CallOf = ::Call; pub type MomentOf = <::Time as Time>::Moment; pub type SeedOf = ::Hash; pub type BlockNumberOf = ::BlockNumber; @@ -37,58 +36,40 @@ 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; -/// A status code return to the source of a contract call or instantiation indicating success or -/// failure. A code of 0 indicates success and that changes are applied. All other codes indicate -/// failure and that changes are reverted. The particular code in the case of failure is opaque and -/// may be interpreted by the calling contract. -pub type StatusCode = u8; +bitflags! { + /// Flags used by a contract to customize exit behaviour. + pub struct ReturnFlags: u32 { + /// If this bit is set all changes made by the contract exection are rolled back. + const REVERT = 0x0000_0001; + } +} -/// The status code indicating success. -pub const STATUS_SUCCESS: StatusCode = 0; +/// Describes whether we deal with a contract or a plain account. +pub enum TransactorKind { + /// Transaction was initiated from a plain account. That can be either be through a + /// signed transaction or through RPC. + PlainAccount, + /// The call was initiated by a contract account. + Contract, +} /// Output of a contract call or instantiation which ran to completion. #[cfg_attr(test, derive(PartialEq, Eq, Debug))] pub struct ExecReturnValue { - pub status: StatusCode, + /// Flags passed along by `ext_return`. Empty when `ext_return` was never called. + pub flags: ReturnFlags, + /// Buffer passed along by `ext_return`. Empty when `ext_return` was never called. pub data: Vec, } impl ExecReturnValue { - /// Returns whether the call or instantiation exited with a successful status code. + /// We understand the absense of a revert flag as success. pub fn is_success(&self) -> bool { - self.status == STATUS_SUCCESS + !self.flags.contains(ReturnFlags::REVERT) } } -/// An error indicating some failure to execute a contract call or instantiation. This can include -/// 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(sp_runtime::RuntimeDebug))] -pub struct ExecError { - pub reason: DispatchError, - /// This is an allocated buffer that may be reused. The buffer must be cleared explicitly - /// before reuse. - pub buffer: Vec, -} - -pub type ExecResult = Result; - -/// Evaluate an expression of type Result<_, &'static str> and either resolve to the value if Ok or -/// 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( - $crate::exec::ExecError { reason: reason.into(), buffer: $buffer } - ), - } - } -} +pub type ExecResult = Result; /// An interface that provides access to the external environment in which the /// smart-contract is executed. @@ -105,8 +86,8 @@ pub trait Ext { fn get_storage(&self, key: &StorageKey) -> Option>; /// Sets the storage entry by the given key to the specified value. If `value` is `None` then - /// the storage entry is deleted. Returns an Err if the value size is too large. - fn set_storage(&mut self, key: StorageKey, value: Option>) -> Result<(), &'static str>; + /// the storage entry is deleted. + fn set_storage(&mut self, key: StorageKey, value: Option>); /// Instantiate a contract from the given code. /// @@ -118,7 +99,7 @@ pub trait Ext { value: BalanceOf, gas_meter: &mut GasMeter, input_data: Vec, - ) -> Result<(AccountIdOf, ExecReturnValue), ExecError>; + ) -> Result<(AccountIdOf, ExecReturnValue), DispatchError>; /// Transfer some amount of funds into the specified account. fn transfer( @@ -129,6 +110,12 @@ pub trait Ext { ) -> Result<(), DispatchError>; /// Transfer all funds to `beneficiary` and delete the contract. + /// + /// Since this function removes the self contract eagerly, if succeeded, no further actions should + /// be performed on this `Ext` instance. + /// + /// This function will fail if the same contract is present on the contract + /// call stack. fn terminate( &mut self, beneficiary: &AccountIdOf, @@ -144,17 +131,20 @@ pub trait Ext { input_data: Vec, ) -> ExecResult; - /// Notes a call dispatch. - fn note_dispatch_call(&mut self, call: CallOf); - - /// Notes a restoration request. - fn note_restore_to( + /// Restores the given destination contract sacrificing the current one. + /// + /// Since this function removes the self contract eagerly, if succeeded, no further actions should + /// be performed on this `Ext` instance. + /// + /// This function will fail if the same contract is present + /// on the contract call stack. + fn restore_to( &mut self, dest: AccountIdOf, code_hash: CodeHash, rent_allowance: BalanceOf, delta: Vec, - ); + ) -> Result<(), &'static str>; /// Returns a reference to the account id of the caller. fn caller(&self) -> &AccountIdOf; @@ -199,10 +189,8 @@ pub trait Ext { /// Returns the maximum allowed size of a storage item. fn max_value_size(&self) -> u32; - /// Returns the value of runtime under the given key. - /// - /// Returns `None` if the value doesn't exist. - fn get_runtime_storage(&self, key: &[u8]) -> Option>; + /// Returns the price for the specified amount of weight. + fn get_weight_price(&self, weight: Weight) -> BalanceOf; } /// Loader is a companion of the `Vm` trait. It loads an appropriate abstract @@ -258,43 +246,11 @@ impl Token for ExecFeeToken { } } -#[cfg_attr(any(feature = "std", test), derive(PartialEq, Eq, Clone))] -#[derive(sp_runtime::RuntimeDebug)] -pub enum DeferredAction { - DepositEvent { - /// A list of topics this event will be deposited with. - topics: Vec, - /// The event to deposit. - event: Event, - }, - DispatchRuntimeCall { - /// The account id of the contract who dispatched this call. - origin: T::AccountId, - /// The call to dispatch. - call: ::Call, - }, - RestoreTo { - /// The account id of the contract which is removed during the restoration and transfers - /// its storage to the restored contract. - donor: T::AccountId, - /// The account id of the restored contract. - dest: T::AccountId, - /// The code hash of the restored contract. - code_hash: CodeHash, - /// The initial rent allowance to set. - rent_allowance: BalanceOf, - /// The keys to delete upon restoration. - delta: Vec, - }, -} - pub struct ExecutionContext<'a, T: Trait + 'a, V, L> { pub caller: Option<&'a ExecutionContext<'a, T, V, L>>, pub self_account: T::AccountId, pub self_trie_id: Option, - pub overlay: OverlayAccountDb<'a, T>, pub depth: usize, - pub deferred: Vec>, pub config: &'a Config, pub vm: &'a V, pub loader: &'a L, @@ -317,9 +273,7 @@ where caller: None, self_trie_id: None, self_account: origin, - overlay: OverlayAccountDb::::new(&DirectAccountDb), depth: 0, - deferred: Vec::new(), config: &cfg, vm: &vm, loader: &loader, @@ -335,9 +289,7 @@ where caller: Some(self), self_trie_id: trie_id, self_account: dest, - overlay: OverlayAccountDb::new(&self.overlay), depth: self.depth + 1, - deferred: Vec::new(), config: self.config, vm: self.vm, loader: self.loader, @@ -346,23 +298,6 @@ where } } - /// Transfer balance to `dest` without calling any contract code. - pub fn transfer( - &mut self, - dest: T::AccountId, - value: BalanceOf, - gas_meter: &mut GasMeter - ) -> Result<(), DispatchError> { - transfer( - gas_meter, - TransferCause::Call, - &self.self_account.clone(), - &dest, - value, - self, - ) - } - /// Make a call to the specified address, optionally transferring some funds. pub fn call( &mut self, @@ -372,20 +307,14 @@ where input_data: Vec, ) -> ExecResult { if self.depth == self.config.max_depth as usize { - return Err(ExecError { - reason: "reached maximum depth, cannot make a call".into(), - buffer: input_data, - }); + Err("reached maximum depth, cannot make a call")? } if gas_meter .charge(self.config, ExecFeeToken::Call) .is_out_of_gas() { - return Err(ExecError { - reason: "not enough gas to pay base call fee".into(), - buffer: input_data, - }); + Err("not enough gas to pay base call fee")? } // Assumption: `collect_rent` doesn't collide with overlay because @@ -395,38 +324,31 @@ where // Calls to dead contracts always fail. if let Some(ContractInfo::Tombstone(_)) = contract_info { - return Err(ExecError { - reason: "contract has been evicted".into(), - buffer: input_data, - }); + Err("contract has been evicted")? }; + let transactor_kind = self.transactor_kind(); let caller = self.self_account.clone(); let dest_trie_id = contract_info.and_then(|i| i.as_alive().map(|i| i.trie_id.clone())); self.with_nested_context(dest.clone(), dest_trie_id, |nested| { if value > BalanceOf::::zero() { - try_or_exec_error!( - transfer( - gas_meter, - TransferCause::Call, - &caller, - &dest, - value, - nested, - ), - input_data - ); + transfer( + gas_meter, + TransferCause::Call, + transactor_kind, + &caller, + &dest, + value, + nested, + )? } // If code_hash is not none, then the destination account is a live contract, otherwise // it is a regular account since tombstone accounts have already been rejected. - match nested.overlay.get_code_hash(&dest) { - Some(dest_code_hash) => { - let executable = try_or_exec_error!( - nested.loader.load_main(&dest_code_hash), - input_data - ); + match storage::code_hash::(&dest) { + Ok(dest_code_hash) => { + let executable = nested.loader.load_main(&dest_code_hash)?; let output = nested.vm .execute( &executable, @@ -434,10 +356,9 @@ where input_data, gas_meter, )?; - Ok(output) } - None => Ok(ExecReturnValue { status: STATUS_SUCCESS, data: Vec::new() }), + Err(storage::ContractAbsentError) => Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() }), } }) } @@ -448,24 +369,19 @@ where gas_meter: &mut GasMeter, code_hash: &CodeHash, input_data: Vec, - ) -> Result<(T::AccountId, ExecReturnValue), ExecError> { + ) -> Result<(T::AccountId, ExecReturnValue), DispatchError> { if self.depth == self.config.max_depth as usize { - return Err(ExecError { - reason: "reached maximum depth, cannot instantiate".into(), - buffer: input_data, - }); + Err("reached maximum depth, cannot instantiate")? } if gas_meter .charge(self.config, ExecFeeToken::Instantiate) .is_out_of_gas() { - return Err(ExecError { - reason: "not enough gas to pay base instantiate fee".into(), - buffer: input_data, - }); + Err("not enough gas to pay base instantiate fee")? } + let transactor_kind = self.transactor_kind(); let caller = self.self_account.clone(); let dest = T::DetermineContractAddress::contract_address_for( code_hash, @@ -474,32 +390,33 @@ where ); // TrieId has not been generated yet and storage is empty since contract is new. - let dest_trie_id = None; - - let output = self.with_nested_context(dest.clone(), dest_trie_id, |nested| { - try_or_exec_error!( - nested.overlay.instantiate_contract(&dest, code_hash.clone()), - input_data - ); + // + // Generate it now. + let dest_trie_id = ::TrieIdGenerator::trie_id(&dest); + + let output = self.with_nested_context(dest.clone(), Some(dest_trie_id), |nested| { + storage::place_contract::( + &dest, + nested + .self_trie_id + .clone() + .expect("the nested context always has to have self_trie_id"), + code_hash.clone() + )?; // Send funds unconditionally here. If the `endowment` is below existential_deposit // then error will be returned here. - try_or_exec_error!( - transfer( - gas_meter, - TransferCause::Instantiate, - &caller, - &dest, - endowment, - nested, - ), - input_data - ); - - let executable = try_or_exec_error!( - nested.loader.load_init(&code_hash), - input_data - ); + transfer( + gas_meter, + TransferCause::Instantiate, + transactor_kind, + &caller, + &dest, + endowment, + nested, + )?; + + let executable = nested.loader.load_init(&code_hash)?; let output = nested.vm .execute( &executable, @@ -509,18 +426,12 @@ where )?; // Error out if insufficient remaining balance. - if nested.overlay.get_balance(&dest) < nested.config.existential_deposit { - return Err(ExecError { - reason: "insufficient remaining balance".into(), - buffer: output.data, - }); + if T::Currency::free_balance(&dest) < nested.config.existential_deposit { + Err("insufficient remaining balance")? } // Deposit an instantiation event. - nested.deferred.push(DeferredAction::DepositEvent { - event: RawEvent::Instantiated(caller.clone(), dest.clone()), - topics: Vec::new(), - }); + deposit_event::(vec![], RawEvent::Instantiated(caller.clone(), dest.clone())); Ok(output) })?; @@ -528,32 +439,6 @@ where Ok((dest, output)) } - pub fn terminate( - &mut self, - beneficiary: &T::AccountId, - gas_meter: &mut GasMeter, - ) -> Result<(), DispatchError> { - let self_id = self.self_account.clone(); - let value = self.overlay.get_balance(&self_id); - if let Some(caller) = self.caller { - if caller.is_live(&self_id) { - return Err(DispatchError::Other( - "Cannot terminate a contract that is present on the call stack", - )); - } - } - transfer( - gas_meter, - TransferCause::Terminate, - &self_id, - beneficiary, - value, - self, - )?; - self.overlay.destroy_contract(&self_id); - Ok(()) - } - fn new_call_context<'b>( &'b mut self, caller: T::AccountId, @@ -570,22 +455,20 @@ where } } + /// Execute the given closure within a nested execution context. fn with_nested_context(&mut self, dest: T::AccountId, trie_id: Option, func: F) -> ExecResult where F: FnOnce(&mut ExecutionContext) -> ExecResult { - let (output, change_set, deferred) = { - let mut nested = self.nested(dest, trie_id); - let output = func(&mut nested)?; - (output, nested.overlay.into_change_set(), nested.deferred) - }; - - if output.is_success() { - self.overlay.commit(change_set); - self.deferred.extend(deferred); - } - - Ok(output) + use frame_support::storage::TransactionOutcome::*; + let mut nested = self.nested(dest, trie_id); + frame_support::storage::with_transaction(|| { + let output = func(&mut nested); + match output { + Ok(ref rv) if !rv.flags.contains(ReturnFlags::REVERT) => Commit(output), + _ => Rollback(output), + } + }) } /// Returns whether a contract, identified by address, is currently live in the execution @@ -594,6 +477,17 @@ where &self.self_account == account || self.caller.map_or(false, |caller| caller.is_live(account)) } + + fn transactor_kind(&self) -> TransactorKind { + if self.depth == 0 { + debug_assert!(self.self_trie_id.is_none()); + debug_assert!(self.caller.is_none()); + debug_assert!(ContractInfoOf::::get(&self.self_account).is_none()); + TransactorKind::PlainAccount + } else { + TransactorKind::Contract + } + } } #[cfg_attr(test, derive(Debug, PartialEq, Eq))] @@ -605,21 +499,19 @@ pub enum TransferFeeKind { #[cfg_attr(test, derive(Debug, PartialEq, Eq))] #[derive(Copy, Clone)] -pub struct TransferFeeToken { +pub struct TransferFeeToken { kind: TransferFeeKind, - gas_price: Balance, } -impl Token for TransferFeeToken> { +impl Token for TransferFeeToken { type Metadata = Config; #[inline] fn calculate_amount(&self, metadata: &Config) -> Gas { - let balance_fee = match self.kind { - TransferFeeKind::ContractInstantiate => metadata.contract_account_instantiate_fee, - TransferFeeKind::Transfer => return metadata.schedule.transfer_cost, - }; - approx_gas_for_balance(self.gas_price, balance_fee) + match self.kind { + TransferFeeKind::ContractInstantiate => metadata.schedule.instantiate_cost, + TransferFeeKind::Transfer => metadata.schedule.transfer_cost, + } } } @@ -649,6 +541,7 @@ enum TransferCause { fn transfer<'a, T: Trait, V: Vm, L: Loader>( gas_meter: &mut GasMeter, cause: TransferCause, + origin: TransactorKind, transactor: &T::AccountId, dest: &T::AccountId, value: BalanceOf, @@ -656,6 +549,7 @@ fn transfer<'a, T: Trait, V: Vm, L: Loader>( ) -> Result<(), DispatchError> { use self::TransferCause::*; use self::TransferFeeKind::*; + use self::TransactorKind::*; let token = { let kind: TransferFeeKind = match cause { @@ -668,7 +562,6 @@ fn transfer<'a, T: Trait, V: Vm, L: Loader>( }; TransferFeeToken { kind, - gas_price: gas_meter.gas_price(), } }; @@ -676,48 +569,36 @@ fn transfer<'a, T: Trait, V: Vm, L: Loader>( Err("not enough gas to pay transfer fee")? } - // We allow balance to go below the existential deposit here: - let from_balance = ctx.overlay.get_balance(transactor); - let new_from_balance = match from_balance.checked_sub(&value) { - Some(b) => b, - None => Err("balance too low to send value")?, - }; - let to_balance = ctx.overlay.get_balance(dest); - if to_balance.is_zero() && value < ctx.config.existential_deposit { - Err("value too low to create account")? - } - - // Only ext_terminate is allowed to bring the sender below the existential deposit - let required_balance = match cause { - Terminate => 0.into(), - _ => ctx.config.existential_deposit - }; - - T::Currency::ensure_can_withdraw( - transactor, - value, - WithdrawReason::Transfer.into(), - new_from_balance.checked_sub(&required_balance) - .ok_or("brings sender below existential deposit")?, - )?; - - let new_to_balance = match to_balance.checked_add(&value) { - Some(b) => b, - None => Err("destination balance too high to receive value")?, + // Only ext_terminate is allowed to bring the sender below the subsistence + // threshold or even existential deposit. + let existence_requirement = match (cause, origin) { + (Terminate, _) => ExistenceRequirement::AllowDeath, + (_, Contract) => { + ensure!( + T::Currency::total_balance(transactor).saturating_sub(value) >= + ctx.config.subsistence_threshold(), + Error::::InsufficientBalance, + ); + ExistenceRequirement::KeepAlive + }, + (_, PlainAccount) => ExistenceRequirement::KeepAlive, }; - - if transactor != dest { - ctx.overlay.set_balance(transactor, new_from_balance); - ctx.overlay.set_balance(dest, new_to_balance); - ctx.deferred.push(DeferredAction::DepositEvent { - event: RawEvent::Transfer(transactor.clone(), dest.clone(), value), - topics: Vec::new(), - }); - } + T::Currency::transfer(transactor, dest, value, existence_requirement)?; Ok(()) } +/// A context that is active within a call. +/// +/// This context has some invariants that must be held at all times. Specifically: +///`ctx` always points to a context of an alive contract. That implies that it has an existent +/// `self_trie_id`. +/// +/// Be advised that there are brief time spans where these invariants could be invalidated. +/// For example, when a contract requests self-termination the contract is removed eagerly. That +/// implies that the control won't be returned to the contract anymore, but there is still some code +/// on the path of the return from that call context. Therefore, care must be taken in these +/// situations. struct CallContext<'a, 'b: 'a, T: Trait + 'b, V: Vm + 'b, L: Loader> { ctx: &'a mut ExecutionContext<'b, T, V, L>, caller: T::AccountId, @@ -735,20 +616,32 @@ where type T = T; fn get_storage(&self, key: &StorageKey) -> Option> { - self.ctx.overlay.get_storage(&self.ctx.self_account, self.ctx.self_trie_id.as_ref(), key) + let trie_id = self.ctx.self_trie_id.as_ref().expect( + "`ctx.self_trie_id` points to an alive contract within the `CallContext`;\ + it cannot be `None`;\ + expect can't fail;\ + qed", + ); + storage::read_contract_storage(trie_id, key) } - fn set_storage(&mut self, key: StorageKey, value: Option>) -> Result<(), &'static str> { - if let Some(ref value) = value { - if self.max_value_size() < value.len() as u32 { - return Err("value size exceeds maximum"); - } + fn set_storage(&mut self, key: StorageKey, value: Option>) { + let trie_id = self.ctx.self_trie_id.as_ref().expect( + "`ctx.self_trie_id` points to an alive contract within the `CallContext`;\ + it cannot be `None`;\ + expect can't fail;\ + qed", + ); + if let Err(storage::ContractAbsentError) = + storage::write_contract_storage::(&self.ctx.self_account, trie_id, &key, value) + { + panic!( + "the contract must be in the alive state within the `CallContext`;\ + the contract cannot be absent in storage; + write_contract_storage cannot return `None`; + qed" + ); } - - self.ctx - .overlay - .set_storage(&self.ctx.self_account, key, value); - Ok(()) } fn instantiate( @@ -757,7 +650,7 @@ where endowment: BalanceOf, gas_meter: &mut GasMeter, input_data: Vec, - ) -> Result<(AccountIdOf, ExecReturnValue), ExecError> { + ) -> Result<(AccountIdOf, ExecReturnValue), DispatchError> { self.ctx.instantiate(endowment, gas_meter, code_hash, input_data) } @@ -767,7 +660,15 @@ where value: BalanceOf, gas_meter: &mut GasMeter, ) -> Result<(), DispatchError> { - self.ctx.transfer(to.clone(), value, gas_meter) + transfer( + gas_meter, + TransferCause::Call, + TransactorKind::Contract, + &self.ctx.self_account.clone(), + &to, + value, + self.ctx, + ) } fn terminate( @@ -775,7 +676,31 @@ where beneficiary: &AccountIdOf, gas_meter: &mut GasMeter, ) -> Result<(), DispatchError> { - self.ctx.terminate(beneficiary, gas_meter) + let self_id = self.ctx.self_account.clone(); + let value = T::Currency::free_balance(&self_id); + if let Some(caller_ctx) = self.ctx.caller { + if caller_ctx.is_live(&self_id) { + return Err(DispatchError::Other( + "Cannot terminate a contract that is present on the call stack", + )); + } + } + transfer( + gas_meter, + TransferCause::Terminate, + TransactorKind::Contract, + &self_id, + beneficiary, + value, + self.ctx, + )?; + let self_trie_id = self.ctx.self_trie_id.as_ref().expect( + "this function is only invoked by in the context of a contract;\ + a contract has a trie id;\ + this can't be None; qed", + ); + storage::destroy_contract::(&self_id, self_trie_id); + Ok(()) } fn call( @@ -788,27 +713,40 @@ where self.ctx.call(to.clone(), value, gas_meter, input_data) } - fn note_dispatch_call(&mut self, call: CallOf) { - self.ctx.deferred.push(DeferredAction::DispatchRuntimeCall { - origin: self.ctx.self_account.clone(), - call, - }); - } - - fn note_restore_to( + fn restore_to( &mut self, dest: AccountIdOf, code_hash: CodeHash, rent_allowance: BalanceOf, delta: Vec, - ) { - self.ctx.deferred.push(DeferredAction::RestoreTo { - donor: self.ctx.self_account.clone(), - dest, - code_hash, + ) -> Result<(), &'static str> { + if let Some(caller_ctx) = self.ctx.caller { + if caller_ctx.is_live(&self.ctx.self_account) { + return Err( + "Cannot perform restoration of a contract that is present on the call stack", + ); + } + } + + let result = crate::rent::restore_to::( + self.ctx.self_account.clone(), + dest.clone(), + code_hash.clone(), rent_allowance, delta, - }); + ); + if let Ok(_) = result { + deposit_event::( + vec![], + RawEvent::Restored( + self.ctx.self_account.clone(), + dest, + code_hash, + rent_allowance, + ), + ); + } + result } fn address(&self) -> &T::AccountId { @@ -820,7 +758,7 @@ where } fn balance(&self) -> BalanceOf { - self.ctx.overlay.get_balance(&self.ctx.self_account) + T::Currency::free_balance(&self.ctx.self_account) } fn value_transferred(&self) -> BalanceOf { @@ -844,18 +782,25 @@ where } fn deposit_event(&mut self, topics: Vec, data: Vec) { - self.ctx.deferred.push(DeferredAction::DepositEvent { + deposit_event::( topics, - event: RawEvent::ContractExecution(self.ctx.self_account.clone(), data), - }); + RawEvent::ContractExecution(self.ctx.self_account.clone(), data) + ); } fn set_rent_allowance(&mut self, rent_allowance: BalanceOf) { - self.ctx.overlay.set_rent_allowance(&self.ctx.self_account, rent_allowance) + if let Err(storage::ContractAbsentError) = + storage::set_rent_allowance::(&self.ctx.self_account, rent_allowance) + { + panic!( + "`self_account` points to an alive contract within the `CallContext`; + set_rent_allowance cannot return `Err`; qed" + ); + } } fn rent_allowance(&self) -> BalanceOf { - self.ctx.overlay.get_rent_allowance(&self.ctx.self_account) + storage::rent_allowance::(&self.ctx.self_account) .unwrap_or(>::max_value()) // Must never be triggered actually } @@ -865,52 +810,57 @@ where self.ctx.config.max_value_size } - fn get_runtime_storage(&self, key: &[u8]) -> Option> { - unhashed::get_raw(&key) + fn get_weight_price(&self, weight: Weight) -> BalanceOf { + T::WeightPrice::convert(weight) } } +fn deposit_event( + topics: Vec, + event: Event, +) { + >::deposit_event_indexed( + &*topics, + ::Event::from(event).into(), + ) +} + /// These tests exercise the executive layer. /// /// In these tests the VM/loader are mocked. Instead of dealing with wasm bytecode they use simple closures. /// This allows you to tackle executive logic more thoroughly without writing a /// wasm VM code. -/// -/// Because it's the executive layer: -/// -/// - no gas meter setup and teardown logic. All balances are *AFTER* gas purchase. -/// - executive layer doesn't alter any storage! #[cfg(test)] mod tests { use super::{ - BalanceOf, ExecFeeToken, ExecutionContext, Ext, Loader, TransferFeeKind, TransferFeeToken, - Vm, ExecResult, RawEvent, DeferredAction, + BalanceOf, Event, ExecFeeToken, ExecResult, ExecutionContext, Ext, Loader, + RawEvent, TransferFeeKind, TransferFeeToken, Vm, ReturnFlags, }; use crate::{ - account_db::AccountDb, gas::GasMeter, tests::{ExtBuilder, Test}, - exec::{ExecReturnValue, ExecError, STATUS_SUCCESS}, CodeHash, Config, + gas::GasMeter, tests::{ExtBuilder, Test, MetaEvent}, + exec::ExecReturnValue, CodeHash, Config, + gas::Gas, + storage, }; - use std::{cell::RefCell, rc::Rc, collections::HashMap, marker::PhantomData}; - use assert_matches::assert_matches; + use crate::tests::test_utils::{place_contract, set_balance, get_balance}; use sp_runtime::DispatchError; + use assert_matches::assert_matches; + use std::{cell::RefCell, collections::HashMap, marker::PhantomData, rc::Rc}; const ALICE: u64 = 1; const BOB: u64 = 2; const CHARLIE: u64 = 3; - impl<'a, T, V, L> ExecutionContext<'a, T, V, L> - where T: crate::Trait - { - fn events(&self) -> Vec> { - self.deferred - .iter() - .filter(|action| match *action { - DeferredAction::DepositEvent { .. } => true, - _ => false, - }) - .cloned() - .collect() - } + const GAS_LIMIT: Gas = 10_000_000_000; + + fn events() -> Vec> { + >::events() + .into_iter() + .filter_map(|meta| match meta.event { + MetaEvent::contracts(contract_event) => Some(contract_event), + _ => None, + }) + .collect() } struct MockCtx<'a> { @@ -997,13 +947,13 @@ mod tests { } fn exec_success() -> ExecResult { - Ok(ExecReturnValue { status: STATUS_SUCCESS, data: Vec::new() }) + Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() }) } #[test] fn it_works() { let value = Default::default(); - let mut gas_meter = GasMeter::::with_limit(10000, 1); + let mut gas_meter = GasMeter::::new(GAS_LIMIT); let data = vec![]; let vm = MockVm::new(); @@ -1019,7 +969,7 @@ mod tests { ExtBuilder::default().build().execute_with(|| { let cfg = Config::preload(); let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); - ctx.overlay.instantiate_contract(&BOB, exec_ch).unwrap(); + place_contract(&BOB, exec_ch); assert_matches!( ctx.call(BOB, value, &mut gas_meter, data), @@ -1041,10 +991,10 @@ mod tests { 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); + set_balance(&origin, 100); + set_balance(&dest, 0); - let mut gas_meter = GasMeter::::with_limit(1000, 1); + let mut gas_meter = GasMeter::::new(GAS_LIMIT); let result = ctx.call(dest, 0, &mut gas_meter, vec![]); assert_matches!(result, Ok(_)); @@ -1062,9 +1012,9 @@ mod tests { let cfg = Config::preload(); let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); - ctx.overlay.set_balance(&origin, 100); + set_balance(&origin, 100); - let mut gas_meter = GasMeter::::with_limit(1000, 1); + let mut gas_meter = GasMeter::::new(GAS_LIMIT); let result = ctx.instantiate(1, &mut gas_meter, &code, vec![]); assert_matches!(result, Ok(_)); @@ -1087,52 +1037,52 @@ mod tests { 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); - ctx.overlay.set_balance(&dest, 0); + set_balance(&origin, 100); + set_balance(&dest, 0); let output = ctx.call( dest, 55, - &mut GasMeter::::with_limit(1000, 1), + &mut GasMeter::::new(GAS_LIMIT), vec![], ).unwrap(); assert!(output.is_success()); - assert_eq!(ctx.overlay.get_balance(&origin), 45); - assert_eq!(ctx.overlay.get_balance(&dest), 55); + assert_eq!(get_balance(&origin), 45); + assert_eq!(get_balance(&dest), 55); }); } #[test] fn changes_are_reverted_on_failing_call() { - // This test verifies that a contract is able to transfer - // some funds to another account. + // This test verifies that changes are reverted on a call which fails (or equally, returns + // a non-zero status code). let origin = ALICE; let dest = BOB; let vm = MockVm::new(); let mut loader = MockLoader::empty(); let return_ch = loader.insert( - |_| Ok(ExecReturnValue { status: 1, data: Vec::new() }) + |_| Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: Vec::new() }) ); ExtBuilder::default().build().execute_with(|| { let cfg = Config::preload(); let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); - ctx.overlay.instantiate_contract(&BOB, return_ch).unwrap(); - ctx.overlay.set_balance(&origin, 100); - ctx.overlay.set_balance(&dest, 0); + place_contract(&BOB, return_ch); + set_balance(&origin, 100); + set_balance(&dest, 0); let output = ctx.call( dest, 55, - &mut GasMeter::::with_limit(1000, 1), + &mut GasMeter::::new(GAS_LIMIT), vec![], ).unwrap(); assert!(!output.is_success()); - assert_eq!(ctx.overlay.get_balance(&origin), 100); - assert_eq!(ctx.overlay.get_balance(&dest), 0); + assert_eq!(get_balance(&origin), 100); + assert_eq!(get_balance(&dest), 0); }); } @@ -1149,10 +1099,10 @@ mod tests { 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); + set_balance(&origin, 100); + set_balance(&dest, 0); - let mut gas_meter = GasMeter::::with_limit(1000, 1); + let mut gas_meter = GasMeter::::new(GAS_LIMIT); let result = ctx.call(dest, 50, &mut gas_meter, vec![]); assert_matches!(result, Ok(_)); @@ -1163,7 +1113,6 @@ mod tests { ExecFeeToken::Call, TransferFeeToken { kind: TransferFeeKind::Transfer, - gas_price: 1u64 }, ); }); @@ -1175,10 +1124,10 @@ mod tests { 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); + set_balance(&origin, 100); + set_balance(&dest, 15); - let mut gas_meter = GasMeter::::with_limit(1000, 1); + let mut gas_meter = GasMeter::::new(GAS_LIMIT); let result = ctx.call(dest, 50, &mut gas_meter, vec![]); assert_matches!(result, Ok(_)); @@ -1189,7 +1138,6 @@ mod tests { ExecFeeToken::Call, TransferFeeToken { kind: TransferFeeKind::Transfer, - gas_price: 1u64 }, ); }); @@ -1204,10 +1152,10 @@ mod tests { 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); + set_balance(&origin, 100); + set_balance(&dest, 15); - let mut gas_meter = GasMeter::::with_limit(1000, 1); + let mut gas_meter = GasMeter::::new(GAS_LIMIT); let result = ctx.instantiate(50, &mut gas_meter, &code, vec![]); assert_matches!(result, Ok(_)); @@ -1218,7 +1166,6 @@ mod tests { ExecFeeToken::Instantiate, TransferFeeToken { kind: TransferFeeKind::ContractInstantiate, - gas_price: 1u64 }, ); }); @@ -1237,24 +1184,21 @@ mod tests { 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); + set_balance(&origin, 0); let result = ctx.call( dest, 100, - &mut GasMeter::::with_limit(1000, 1), + &mut GasMeter::::new(GAS_LIMIT), vec![], ); assert_matches!( result, - Err(ExecError { - reason: DispatchError::Other("balance too low to send value"), - buffer: _, - }) + Err(DispatchError::Module { message: Some("InsufficientBalance"), .. }) ); - assert_eq!(ctx.overlay.get_balance(&origin), 0); - assert_eq!(ctx.overlay.get_balance(&dest), 0); + assert_eq!(get_balance(&origin), 0); + assert_eq!(get_balance(&dest), 0); }); } @@ -1268,18 +1212,18 @@ mod tests { let vm = MockVm::new(); let mut loader = MockLoader::empty(); let return_ch = loader.insert( - |_| Ok(ExecReturnValue { status: STATUS_SUCCESS, data: vec![1, 2, 3, 4] }) + |_| Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: vec![1, 2, 3, 4] }) ); ExtBuilder::default().build().execute_with(|| { let cfg = Config::preload(); let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); - ctx.overlay.instantiate_contract(&BOB, return_ch).unwrap(); + place_contract(&BOB, return_ch); let result = ctx.call( dest, 0, - &mut GasMeter::::with_limit(1000, 1), + &mut GasMeter::::new(GAS_LIMIT), vec![], ); @@ -1299,18 +1243,18 @@ mod tests { let vm = MockVm::new(); let mut loader = MockLoader::empty(); let return_ch = loader.insert( - |_| Ok(ExecReturnValue { status: 1, data: vec![1, 2, 3, 4] }) + |_| Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: vec![1, 2, 3, 4] }) ); ExtBuilder::default().build().execute_with(|| { let cfg = Config::preload(); let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); - ctx.overlay.instantiate_contract(&BOB, return_ch).unwrap(); + place_contract(&BOB, return_ch); let result = ctx.call( dest, 0, - &mut GasMeter::::with_limit(1000, 1), + &mut GasMeter::::new(GAS_LIMIT), vec![], ); @@ -1333,12 +1277,12 @@ mod tests { ExtBuilder::default().build().execute_with(|| { let cfg = Config::preload(); let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); - ctx.overlay.instantiate_contract(&BOB, input_data_ch).unwrap(); + place_contract(&BOB, input_data_ch); let result = ctx.call( BOB, 0, - &mut GasMeter::::with_limit(10000, 1), + &mut GasMeter::::new(GAS_LIMIT), vec![1, 2, 3, 4], ); assert_matches!(result, Ok(_)); @@ -1359,11 +1303,11 @@ mod tests { let cfg = Config::preload(); let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); - ctx.overlay.set_balance(&ALICE, 100); + set_balance(&ALICE, 100); let result = ctx.instantiate( 1, - &mut GasMeter::::with_limit(10000, 1), + &mut GasMeter::::new(GAS_LIMIT), &input_data_ch, vec![1, 2, 3, 4], ); @@ -1390,10 +1334,7 @@ mod tests { // Verify that we've got proper error and set `reached_bottom`. assert_matches!( r, - Err(ExecError { - reason: DispatchError::Other("reached maximum depth, cannot make a call"), - buffer: _, - }) + Err(DispatchError::Other("reached maximum depth, cannot make a call")) ); *reached_bottom = true; } else { @@ -1407,13 +1348,13 @@ mod tests { ExtBuilder::default().build().execute_with(|| { let cfg = Config::preload(); let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); - ctx.overlay.set_balance(&BOB, 1); - ctx.overlay.instantiate_contract(&BOB, recurse_ch).unwrap(); + set_balance(&BOB, 1); + place_contract(&BOB, recurse_ch); let result = ctx.call( BOB, value, - &mut GasMeter::::with_limit(100000, 1), + &mut GasMeter::::new(GAS_LIMIT), vec![], ); @@ -1453,13 +1394,13 @@ mod tests { let cfg = Config::preload(); let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); - ctx.overlay.instantiate_contract(&dest, bob_ch).unwrap(); - ctx.overlay.instantiate_contract(&CHARLIE, charlie_ch).unwrap(); + place_contract(&dest, bob_ch); + place_contract(&CHARLIE, charlie_ch); let result = ctx.call( dest, 0, - &mut GasMeter::::with_limit(10000, 1), + &mut GasMeter::::new(GAS_LIMIT), vec![], ); @@ -1494,13 +1435,13 @@ mod tests { ExtBuilder::default().build().execute_with(|| { let cfg = Config::preload(); let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); - ctx.overlay.instantiate_contract(&BOB, bob_ch).unwrap(); - ctx.overlay.instantiate_contract(&CHARLIE, charlie_ch).unwrap(); + place_contract(&BOB, bob_ch); + place_contract(&CHARLIE, charlie_ch); let result = ctx.call( BOB, 0, - &mut GasMeter::::with_limit(10000, 1), + &mut GasMeter::::new(GAS_LIMIT), vec![], ); @@ -1522,7 +1463,7 @@ mod tests { assert_matches!( ctx.instantiate( 0, // <- zero endowment - &mut GasMeter::::with_limit(10000, 1), + &mut GasMeter::::new(GAS_LIMIT), &dummy_ch, vec![], ), @@ -1537,18 +1478,18 @@ mod tests { let mut loader = MockLoader::empty(); let dummy_ch = loader.insert( - |_| Ok(ExecReturnValue { status: STATUS_SUCCESS, data: vec![80, 65, 83, 83] }) + |_| Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: vec![80, 65, 83, 83] }) ); 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); + set_balance(&ALICE, 1000); let instantiated_contract_address = assert_matches!( ctx.instantiate( 100, - &mut GasMeter::::with_limit(10000, 1), + &mut GasMeter::::new(GAS_LIMIT), &dummy_ch, vec![], ), @@ -1557,16 +1498,9 @@ mod tests { // 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(), - } + assert_eq!(storage::code_hash::(&instantiated_contract_address).unwrap(), dummy_ch); + assert_eq!(&events(), &[ + RawEvent::Instantiated(ALICE, instantiated_contract_address) ]); }); } @@ -1577,18 +1511,18 @@ mod tests { let mut loader = MockLoader::empty(); let dummy_ch = loader.insert( - |_| Ok(ExecReturnValue { status: 1, data: vec![70, 65, 73, 76] }) + |_| Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: vec![70, 65, 73, 76] }) ); 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); + set_balance(&ALICE, 1000); let instantiated_contract_address = assert_matches!( ctx.instantiate( 100, - &mut GasMeter::::with_limit(10000, 1), + &mut GasMeter::::new(GAS_LIMIT), &dummy_ch, vec![], ), @@ -1596,8 +1530,8 @@ mod tests { ); // Check that the account has not been created. - assert!(ctx.overlay.get_code_hash(&instantiated_contract_address).is_none()); - assert!(ctx.events().is_empty()); + assert!(storage::code_hash::(&instantiated_contract_address).is_err()); + assert!(events().is_empty()); }); } @@ -1628,12 +1562,12 @@ mod tests { 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.set_balance(&BOB, 100); - ctx.overlay.instantiate_contract(&BOB, instantiator_ch).unwrap(); + set_balance(&ALICE, 1000); + set_balance(&BOB, 100); + place_contract(&BOB, instantiator_ch); assert_matches!( - ctx.call(BOB, 20, &mut GasMeter::::with_limit(1000, 1), vec![]), + ctx.call(BOB, 20, &mut GasMeter::::new(GAS_LIMIT), vec![]), Ok(_) ); @@ -1641,20 +1575,9 @@ mod tests { // 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(), - }, + assert_eq!(storage::code_hash::(&instantiated_contract_address).unwrap(), dummy_ch); + assert_eq!(&events(), &[ + RawEvent::Instantiated(BOB, instantiated_contract_address) ]); }); } @@ -1665,7 +1588,7 @@ mod tests { let mut loader = MockLoader::empty(); let dummy_ch = loader.insert( - |_| Err(ExecError { reason: "It's a trap!".into(), buffer: Vec::new() }) + |_| Err("It's a trap!".into()) ); let instantiator_ch = loader.insert({ let dummy_ch = dummy_ch.clone(); @@ -1678,7 +1601,7 @@ mod tests { ctx.gas_meter, vec![] ), - Err(ExecError { reason: DispatchError::Other("It's a trap!"), buffer: _ }) + Err(DispatchError::Other("It's a trap!")) ); exec_success() @@ -1688,23 +1611,18 @@ mod tests { 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.set_balance(&BOB, 100); - ctx.overlay.instantiate_contract(&BOB, instantiator_ch).unwrap(); + set_balance(&ALICE, 1000); + set_balance(&BOB, 100); + place_contract(&BOB, instantiator_ch); assert_matches!( - ctx.call(BOB, 20, &mut GasMeter::::with_limit(1000, 1), vec![]), + ctx.call(BOB, 20, &mut GasMeter::::new(GAS_LIMIT), vec![]), Ok(_) ); // 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(), - }, - ]); + assert_eq!(&events(), &[]); }); } @@ -1725,23 +1643,20 @@ mod tests { .execute_with(|| { let cfg = Config::preload(); let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); - ctx.overlay.set_balance(&ALICE, 1000); + set_balance(&ALICE, 1000); assert_matches!( ctx.instantiate( 100, - &mut GasMeter::::with_limit(10000, 1), + &mut GasMeter::::new(GAS_LIMIT), &terminate_ch, vec![], ), - Err(ExecError { - reason: DispatchError::Other("insufficient remaining balance"), - buffer - }) if buffer == Vec::::new() + Err(DispatchError::Other("insufficient remaining balance")) ); assert_eq!( - &ctx.events(), + &events(), &[] ); }); @@ -1761,12 +1676,11 @@ mod tests { ExtBuilder::default().build().execute_with(|| { let cfg = Config::preload(); let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); - - ctx.overlay.set_balance(&ALICE, 100); + set_balance(&ALICE, 100); let result = ctx.instantiate( 1, - &mut GasMeter::::with_limit(10000, 1), + &mut GasMeter::::new(GAS_LIMIT), &rent_allowance_ch, vec![], ); diff --git a/frame/contracts/src/gas.rs b/frame/contracts/src/gas.rs index 362f15f3aae795ef44b346285de79cd557291a23..0ae1952de0914b8d6226c374761bf1a7157d1786 100644 --- a/frame/contracts/src/gas.rs +++ b/frame/contracts/src/gas.rs @@ -14,22 +14,18 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use crate::{GasSpent, Module, Trait, BalanceOf, NegativeImbalanceOf}; -use sp_std::convert::TryFrom; -use sp_runtime::traits::{ - CheckedMul, Zero, SaturatedConversion, AtLeast32Bit, UniqueSaturatedInto, -}; -use frame_support::{ - traits::{Currency, ExistenceRequirement, Imbalance, OnUnbalanced, WithdrawReason}, StorageValue, - dispatch::DispatchError, +use crate::Trait; +use sp_std::marker::PhantomData; +use sp_runtime::traits::Zero; +use frame_support::dispatch::{ + DispatchError, DispatchResultWithPostInfo, PostDispatchInfo, DispatchErrorWithPostInfo, }; #[cfg(test)] use std::{any::Any, fmt::Debug}; -// Gas units are chosen to be represented by u64 so that gas metering instructions can operate on -// them efficiently. -pub type Gas = u64; +// Gas is essentially the same as weight. It is a 1 to 1 correspondence. +pub type Gas = frame_support::weights::Weight; #[must_use] #[derive(Debug, PartialEq, Eq)] @@ -88,20 +84,19 @@ pub struct ErasedToken { } pub struct GasMeter { - limit: Gas, + gas_limit: Gas, /// Amount of gas left from initial gas limit. Can reach zero. gas_left: Gas, - gas_price: BalanceOf, - + _phantom: PhantomData, #[cfg(test)] tokens: Vec, } impl GasMeter { - pub fn with_limit(gas_limit: Gas, gas_price: BalanceOf) -> GasMeter { + pub fn new(gas_limit: Gas) -> Self { GasMeter { - limit: gas_limit, + gas_limit, gas_left: gas_limit, - gas_price, + _phantom: PhantomData, #[cfg(test)] tokens: Vec::new(), } @@ -147,6 +142,14 @@ impl GasMeter { } } + // Account for not fully used gas. + // + // This can be used after dispatching a runtime call to refund gas that was not + // used by the dispatchable. + pub fn refund(&mut self, gas: Gas) { + self.gas_left = self.gas_left.saturating_add(gas).max(self.gas_limit); + } + /// Allocate some amount of gas and perform some work with /// a newly created nested gas meter. /// @@ -165,7 +168,7 @@ impl GasMeter { f(None) } else { self.gas_left = self.gas_left - amount; - let mut nested = GasMeter::with_limit(amount, self.gas_price); + let mut nested = GasMeter::new(amount); let r = f(Some(&mut nested)); @@ -175,8 +178,9 @@ impl GasMeter { } } - pub fn gas_price(&self) -> BalanceOf { - self.gas_price + /// Returns how much gas was used. + pub fn gas_spent(&self) -> Gas { + self.gas_limit - self.gas_left } /// Returns how much gas left from the initial budget. @@ -184,9 +188,17 @@ impl GasMeter { self.gas_left } - /// Returns how much gas was spent. - fn spent(&self) -> Gas { - self.limit - self.gas_left + /// Turn this GasMeter into a DispatchResult that contains the actually used gas. + pub fn into_dispatch_result(self, result: Result) -> DispatchResultWithPostInfo where + E: Into, + { + let post_info = PostDispatchInfo { + actual_weight: Some(self.gas_spent()), + }; + + result + .map(|_| post_info) + .map_err(|e| DispatchErrorWithPostInfo { post_info, error: e.into() }) } #[cfg(test)] @@ -195,68 +207,6 @@ impl GasMeter { } } -/// Buy the given amount of gas. -/// -/// Cost is calculated by multiplying the gas cost (taken from the storage) by the `gas_limit`. -/// The funds are deducted from `transactor`. -pub fn buy_gas( - transactor: &T::AccountId, - gas_limit: Gas, -) -> Result<(GasMeter, NegativeImbalanceOf), DispatchError> { - // Buy the specified amount of gas. - let gas_price = >::gas_price(); - let cost = if gas_price.is_zero() { - >::zero() - } else { - as TryFrom>::try_from(gas_limit).ok() - .and_then(|gas_limit| gas_price.checked_mul(&gas_limit)) - .ok_or("overflow multiplying gas limit by price")? - }; - - let imbalance = T::Currency::withdraw( - transactor, - cost, - WithdrawReason::Fee.into(), - ExistenceRequirement::KeepAlive - )?; - - Ok((GasMeter::with_limit(gas_limit, gas_price), imbalance)) -} - -/// Refund the unused gas. -pub fn refund_unused_gas( - transactor: &T::AccountId, - gas_meter: GasMeter, - imbalance: NegativeImbalanceOf, -) { - let gas_spent = gas_meter.spent(); - let gas_left = gas_meter.gas_left(); - - // Increase total spent gas. - // This cannot overflow, since `gas_spent` is never greater than `block_gas_limit`, which - // also has Gas type. - GasSpent::mutate(|block_gas_spent| *block_gas_spent += gas_spent); - - // Refund gas left by the price it was bought at. - let refund = gas_meter.gas_price * gas_left.unique_saturated_into(); - let refund_imbalance = T::Currency::deposit_creating(transactor, refund); - if let Ok(imbalance) = imbalance.offset(refund_imbalance) { - T::GasPayment::on_unbalanced(imbalance); - } -} - -/// A little handy utility for converting a value in balance units into approximate value in gas units -/// at the given gas price. -pub fn approx_gas_for_balance(gas_price: Balance, balance: Balance) -> Gas - where Balance: AtLeast32Bit -{ - if gas_price.is_zero() { - Zero::zero() - } else { - (balance / gas_price).saturated_into::() - } -} - /// A simple utility macro that helps to match against a /// list of tokens. #[macro_export] @@ -298,7 +248,7 @@ macro_rules! match_tokens { #[cfg(test)] mod tests { use super::{GasMeter, Token}; - use crate::{tests::Test, gas::approx_gas_for_balance}; + use crate::tests::Test; /// A trivial token that charges the specified number of gas units. #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -326,26 +276,24 @@ mod tests { #[test] fn it_works() { - let gas_meter = GasMeter::::with_limit(50000, 10); + let gas_meter = GasMeter::::new(50000); assert_eq!(gas_meter.gas_left(), 50000); } #[test] fn simple() { - let mut gas_meter = GasMeter::::with_limit(50000, 10); + let mut gas_meter = GasMeter::::new(50000); let result = gas_meter .charge(&MultiplierTokenMetadata { multiplier: 3 }, MultiplierToken(10)); assert!(!result.is_out_of_gas()); assert_eq!(gas_meter.gas_left(), 49_970); - assert_eq!(gas_meter.spent(), 30); - assert_eq!(gas_meter.gas_price(), 10); } #[test] fn tracing() { - let mut gas_meter = GasMeter::::with_limit(50000, 10); + let mut gas_meter = GasMeter::::new(50000); assert!(!gas_meter.charge(&(), SimpleToken(1)).is_out_of_gas()); assert!(!gas_meter .charge(&MultiplierTokenMetadata { multiplier: 3 }, MultiplierToken(10)) @@ -358,7 +306,7 @@ mod tests { // This test makes sure that nothing can be executed if there is no gas. #[test] fn refuse_to_execute_anything_if_zero() { - let mut gas_meter = GasMeter::::with_limit(0, 10); + let mut gas_meter = GasMeter::::new(0); assert!(gas_meter.charge(&(), SimpleToken(1)).is_out_of_gas()); } @@ -369,7 +317,7 @@ mod tests { // if the gas meter runs out of gas. However, this is just a nice property to have. #[test] fn overcharge_is_unrecoverable() { - let mut gas_meter = GasMeter::::with_limit(200, 10); + let mut gas_meter = GasMeter::::new(200); // The first charge is should lead to OOG. assert!(gas_meter.charge(&(), SimpleToken(300)).is_out_of_gas()); @@ -383,25 +331,7 @@ mod tests { // possible. #[test] fn charge_exact_amount() { - let mut gas_meter = GasMeter::::with_limit(25, 10); + let mut gas_meter = GasMeter::::new(25); assert!(!gas_meter.charge(&(), SimpleToken(25)).is_out_of_gas()); } - - // A unit test for `fn approx_gas_for_balance()`, and makes - // sure setting gas_price 0 does not cause `div by zero` error. - #[test] - fn approx_gas_for_balance_works() { - let tests = vec![ - (approx_gas_for_balance(0_u64, 123), 0), - (approx_gas_for_balance(0_u64, 456), 0), - (approx_gas_for_balance(1_u64, 123), 123), - (approx_gas_for_balance(1_u64, 456), 456), - (approx_gas_for_balance(100_u64, 900), 9), - (approx_gas_for_balance(123_u64, 900), 7), - ]; - - for (lhs, rhs) in tests { - assert_eq!(lhs, rhs); - } - } } diff --git a/frame/contracts/src/lib.rs b/frame/contracts/src/lib.rs index 090b345099e916a827382adbd5903bb4cecfeb6c..18c88c02b479351c9f19d44715bf00536c6e4150 100644 --- a/frame/contracts/src/lib.rs +++ b/frame/contracts/src/lib.rs @@ -64,15 +64,6 @@ //! 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 @@ -90,8 +81,7 @@ #[macro_use] mod gas; - -mod account_db; +mod storage; mod exec; mod wasm; mod rent; @@ -100,35 +90,31 @@ mod rent; mod tests; use crate::exec::ExecutionContext; -use crate::account_db::{AccountDb, DirectAccountDb}; use crate::wasm::{WasmLoader, WasmVm}; pub use crate::gas::{Gas, GasMeter}; -pub use crate::exec::{ExecResult, ExecReturnValue, ExecError, StatusCode}; +pub use crate::exec::{ExecResult, ExecReturnValue}; #[cfg(feature = "std")] use serde::{Serialize, Deserialize}; use sp_core::crypto::UncheckedFrom; use sp_std::{prelude::*, marker::PhantomData, fmt::Debug}; use codec::{Codec, Encode, Decode}; -use sp_io::hashing::blake2_256; use sp_runtime::{ - traits::{Hash, StaticLookup, Zero, MaybeSerializeDeserialize, Member, SignedExtension}, - transaction_validity::{ - ValidTransaction, InvalidTransaction, TransactionValidity, TransactionValidityError, + traits::{ + Hash, StaticLookup, Zero, MaybeSerializeDeserialize, Member, Convert, Saturating, }, RuntimeDebug, }; -use frame_support::dispatch::{DispatchResult, Dispatchable}; use frame_support::{ - Parameter, decl_module, decl_event, decl_storage, decl_error, storage::child, - parameter_types, IsSubType, - weights::DispatchInfo, + decl_module, decl_event, decl_storage, decl_error, + parameter_types, storage::child::ChildInfo, + dispatch::{DispatchResult, DispatchResultWithPostInfo}, + traits::{OnUnbalanced, Currency, Get, Time, Randomness}, }; -use frame_support::traits::{OnUnbalanced, Currency, Get, Time, Randomness}; -use frame_system::{self as system, ensure_signed, RawOrigin, ensure_root}; -use sp_core::storage::well_known_keys::CHILD_STORAGE_KEY_PREFIX; +use frame_system::{ensure_signed, ensure_root}; use pallet_contracts_primitives::{RentProjection, ContractAccessError}; +use frame_support::weights::Weight; pub type CodeHash = ::Hash; pub type TrieId = Vec; @@ -138,11 +124,6 @@ pub trait ContractAddressFor { fn contract_address_for(code_hash: &CodeHash, data: &[u8], origin: &AccountId) -> AccountId; } -/// A function that returns the fee for dispatching a `Call`. -pub trait ComputeDispatchFee { - fn compute_dispatch_fee(call: &Call) -> Balance; -} - /// Information for managing an account and its sub trie abstraction. /// This is the required info to cache for an account #[derive(Encode, Decode, RuntimeDebug)] @@ -212,8 +193,15 @@ pub type AliveContractInfo = pub struct RawAliveContractInfo { /// Unique ID for the subtree encoded as a bytes vector. pub trie_id: TrieId, - /// The size of stored value in octet. + /// The total number of bytes used by this contract. + /// + /// It is a sum of each key-value pair stored by this contract. pub storage_size: u32, + /// The number of key-value pairs that have values of zero length. + /// The condition `empty_pair_count ≤ total_pair_count` always holds. + pub empty_pair_count: u32, + /// The total number of key-value pairs in storage of this contract. + pub total_pair_count: u32, /// The code associated with a given account. pub code_hash: CodeHash, /// Pay rent at most up to this value. @@ -226,15 +214,14 @@ pub struct RawAliveContractInfo { impl RawAliveContractInfo { /// Associated child trie unique id is built from the hash part of the trie id. - pub fn child_trie_unique_id(&self) -> child::ChildInfo { - trie_unique_id(&self.trie_id[..]) + pub fn child_trie_info(&self) -> ChildInfo { + child_trie_info(&self.trie_id[..]) } } /// Associated child trie unique id is built from the hash part of the trie id. -pub(crate) fn trie_unique_id(trie_id: &[u8]) -> child::ChildInfo { - let start = CHILD_STORAGE_KEY_PREFIX.len() + b"default:".len(); - child::ChildInfo::new_default(&trie_id[start ..]) +pub(crate) fn child_trie_info(trie_id: &[u8]) -> ChildInfo { + ChildInfo::new_default(trie_id) } pub type TombstoneContractInfo = @@ -258,6 +245,12 @@ where } } +impl From> for ContractInfo { + fn from(alive_info: AliveContractInfo) -> Self { + Self::Alive(alive_info) + } +} + /// Get a trie id (trie id must be unique and collision resistant depending upon its context). /// Note that it is different than encode because trie id should be collision resistant /// (being a proper unique identifier). @@ -267,10 +260,6 @@ pub trait TrieIdGenerator { /// /// The implementation must ensure every new trie id is unique: two consecutive calls with the /// same parameter needs to return different trie id values. - /// - /// Also, the implementation is responsible for ensuring that `TrieId` starts with - /// `:child_storage:`. - /// TODO: We want to change this, see https://github.com/paritytech/substrate/issues/2325 fn trie_id(account_id: &AccountId) -> TrieId; } @@ -294,17 +283,12 @@ where let mut buf = Vec::new(); buf.extend_from_slice(account_id.as_ref()); buf.extend_from_slice(&new_seed.to_le_bytes()[..]); - - // TODO: see https://github.com/paritytech/substrate/issues/2325 - CHILD_STORAGE_KEY_PREFIX.iter() - .chain(b"default:") - .chain(T::Hashing::hash(&buf[..]).as_ref().iter()) - .cloned() - .collect() + T::Hashing::hash(&buf[..]).as_ref().into() } } -pub type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; +pub type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; pub type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; @@ -321,35 +305,18 @@ parameter_types! { pub const DefaultRentDepositOffset: u32 = 1000; /// A reasonable default value for [`Trait::SurchargeReward`]. pub const DefaultSurchargeReward: u32 = 150; - /// A reasonable default value for [`Trait::TransferFee`]. - pub const DefaultTransferFee: u32 = 0; - /// 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 reasonable default value for [`Trait::TransactionByteFee`]. - pub const DefaultTransactionByteFee: u32 = 0; - /// A reasonable default value for [`Trait::ContractFee`]. - pub const DefaultContractFee: u32 = 21; - /// A reasonable default value for [`Trait::CallBaseFee`]. - pub const DefaultCallBaseFee: u32 = 1000; - /// 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 reasonable default value for [`Trait::BlockGasLimit`]. - pub const DefaultBlockGasLimit: u32 = 10_000_000; } pub trait Trait: frame_system::Trait { - type Currency: Currency; type Time: Time; type Randomness: Randomness; - /// The outer call dispatch type. - type Call: Parameter + Dispatchable::Origin> + IsSubType, Self>; + /// The currency in which fees are paid and contract balances are held. + type Currency: Currency; /// The overarching event type. type Event: From> + Into<::Event>; @@ -357,18 +324,9 @@ pub trait Trait: frame_system::Trait { /// 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. - type ComputeDispatchFee: ComputeDispatchFee<::Call, BalanceOf>; - /// trie id generator type TrieIdGenerator: TrieIdGenerator; - /// Handler for the unbalanced reduction when making a gas payment. - type GasPayment: OnUnbalanced>; - /// Handler for rent payments. type RentPayment: OnUnbalanced>; @@ -381,8 +339,11 @@ pub trait Trait: frame_system::Trait { /// The minimum amount required to generate a tombstone. type TombstoneDeposit: Get>; - /// Size of a contract at the time of instantiation. This is a simple way to ensure - /// that empty contracts eventually gets deleted. + /// A size offset for an contract. A just created account with untouched storage will have that + /// much of storage from the perspective of the state rent. + /// + /// This is a simple way to ensure that contracts with empty storage eventually get deleted by + /// making them pay rent. This creates an incentive to remove them early in order to save rent. type StorageSizeOffset: Get; /// Price of a byte of storage per one block interval. Should be greater than 0. @@ -401,29 +362,15 @@ pub trait Trait: frame_system::Trait { /// to removal of a contract. type SurchargeReward: 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>; - - /// 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 instantiating a contract. - type InstantiateBaseFee: Get; - /// The maximum nesting level of a call/instantiate stack. type MaxDepth: Get; /// The maximum size of a storage value in bytes. type MaxValueSize: Get; - /// The maximum amount of gas that could be expended per block. - type BlockGasLimit: Get; + /// Used to answer contracts's queries regarding the current weight price. This is **not** + /// used to calculate the actual fee and is only for informational purposes. + type WeightPrice: Convert>; } /// Simple contract address determiner. @@ -449,19 +396,6 @@ where } } -/// The default dispatch fee computor computes the fee in the same way that -/// 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 { - let encoded_len = call.using_encoded(|encoded| encoded.len() as u32); - let base_fee = T::TransactionBaseFee::get(); - let byte_fee = T::TransactionByteFee::get(); - base_fee + byte_fee * encoded_len.into() - } -} - decl_error! { /// Error for the contracts module. pub enum Error for Module { @@ -476,7 +410,16 @@ decl_error! { /// Tombstones don't match. InvalidTombstone, /// An origin TrieId written in the current block. - InvalidContractOrigin + InvalidContractOrigin, + /// The executed contract exhausted its gas limit. + OutOfGas, + /// The output buffer supplied to a contract API call was too small. + OutputBufferTooSmall, + /// Performing the requested transfer would have brought the contract below + /// the subsistence threshold. No transfer is allowed to do this in order to allow + /// for a tombstone to be created. Use `ext_terminate` to remove a contract without + /// leaving a tombstone behind. + InsufficientBalance, } } @@ -494,8 +437,12 @@ decl_module! { /// The minimum amount required to generate a tombstone. const TombstoneDeposit: BalanceOf = T::TombstoneDeposit::get(); - /// Size of a contract at the time of instantiation. This is a simple way to ensure that - /// empty contracts eventually gets deleted. + /// A size offset for an contract. A just created account with untouched storage will have that + /// much of storage from the perspective of the state rent. + /// + /// This is a simple way to ensure that contracts with empty storage eventually get deleted + /// by making them pay rent. This creates an incentive to remove them early in order to save + /// rent. const StorageSizeOffset: u32 = T::StorageSizeOffset::get(); /// Price of a byte of storage per one block interval. Should be greater than 0. @@ -514,24 +461,6 @@ decl_module! { /// to removal of a contract. const SurchargeReward: BalanceOf = T::SurchargeReward::get(); - /// 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(); - - /// The fee required to instantiate a contract instance. A reasonable default value - /// is 21. - const ContractFee: BalanceOf = T::ContractFee::get(); - - /// The base fee charged for calling into a contract. A reasonable default - /// value is 135. - const CallBaseFee: Gas = T::CallBaseFee::get(); - - /// The base fee charged for instantiating a contract. A reasonable default value - /// is 175. - const InstantiateBaseFee: Gas = T::InstantiateBaseFee::get(); - /// The maximum nesting level of a call/instantiate stack. A reasonable default /// value is 100. const MaxDepth: u32 = T::MaxDepth::get(); @@ -539,16 +468,12 @@ decl_module! { /// The maximum size of a storage value in bytes. A reasonable default is 16 KiB. const MaxValueSize: u32 = T::MaxValueSize::get(); - /// The maximum amount of gas that could be expended per block. A reasonable - /// default value is 10_000_000. - const BlockGasLimit: Gas = T::BlockGasLimit::get(); - fn deposit_event() = default; /// Updates the schedule for metering contracts. /// /// The schedule must have a greater version than the stored schedule. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] pub fn update_schedule(origin, schedule: Schedule) -> DispatchResult { ensure_root(origin)?; if >::current_schedule().version >= schedule.version { @@ -563,24 +488,17 @@ decl_module! { /// Stores the given binary Wasm code into the chain's storage and returns its `codehash`. /// You can instantiate contracts only with stored code. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = Module::::calc_code_put_costs(&code)] pub fn put_code( origin, - #[compact] gas_limit: Gas, code: Vec ) -> DispatchResult { - let origin = ensure_signed(origin)?; - - let (mut gas_meter, imbalance) = gas::buy_gas::(&origin, gas_limit)?; - + ensure_signed(origin)?; let schedule = >::current_schedule(); - let result = wasm::save_code::(code, &mut gas_meter, &schedule); + let result = wasm::save_code::(code, &schedule); if let Ok(code_hash) = result { Self::deposit_event(RawEvent::CodeStored(code_hash)); } - - gas::refund_unused_gas::(&origin, gas_meter, imbalance); - result.map(|_| ()).map_err(Into::into) } @@ -591,20 +509,22 @@ decl_module! { /// * If the account is a regular account, any value will be transferred. /// * If no account exists and the call value is not less than `existential_deposit`, /// a regular account will be created and any value will be transferred. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = *gas_limit] pub fn call( origin, dest: ::Source, #[compact] value: BalanceOf, #[compact] gas_limit: Gas, data: Vec - ) -> DispatchResult { + ) -> DispatchResultWithPostInfo { let origin = ensure_signed(origin)?; let dest = T::Lookup::lookup(dest)?; + let mut gas_meter = GasMeter::new(gas_limit); - Self::bare_call(origin, dest, value, gas_limit, data) - .map(|_| ()) - .map_err(|e| e.reason.into()) + let result = Self::execute_wasm(origin, &mut gas_meter, |ctx, gas_meter| { + ctx.call(dest, value, gas_meter, data) + }); + gas_meter.into_dispatch_result(result) } /// Instantiates a new contract from the `codehash` generated by `put_code`, optionally transferring some balance. @@ -617,22 +537,22 @@ 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. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = *gas_limit] pub fn instantiate( origin, #[compact] endowment: BalanceOf, #[compact] gas_limit: Gas, code_hash: CodeHash, data: Vec - ) -> DispatchResult { + ) -> DispatchResultWithPostInfo { let origin = ensure_signed(origin)?; + let mut gas_meter = GasMeter::new(gas_limit); - Self::execute_wasm(origin, gas_limit, |ctx, gas_meter| { + let result = Self::execute_wasm(origin, &mut gas_meter, |ctx, gas_meter| { ctx.instantiate(endowment, gas_meter, &code_hash, data) .map(|(_address, output)| output) - }) - .map(|_| ()) - .map_err(|e| e.reason.into()) + }); + gas_meter.into_dispatch_result(result) } /// Allows block producers to claim a small reward for evicting a contract. If a block producer @@ -640,7 +560,7 @@ decl_module! { /// /// If contract is not evicted as a result of this call, no actions are taken and /// the sender is not eligible for the reward. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] fn claim_surcharge(origin, dest: T::AccountId, aux_sender: Option) { let origin = origin.into(); let (signed, rewarded) = match (origin, aux_sender) { @@ -667,10 +587,6 @@ decl_module! { T::Currency::deposit_into_existing(&rewarded, T::SurchargeReward::get())?; } } - - fn on_finalize() { - GasSpent::kill(); - } } } @@ -680,16 +596,22 @@ impl Module { /// /// This function is similar to `Self::call`, but doesn't perform any address lookups and better /// suitable for calling directly from Rust. + /// + /// It returns the exection result and the amount of used weight. 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) - }) + ) -> (ExecResult, Gas) { + let mut gas_meter = GasMeter::new(gas_limit); + ( + Self::execute_wasm(origin, &mut gas_meter, |ctx, gas_meter| { + ctx.call(dest, value, gas_meter, input_data) + }), + gas_meter.gas_spent(), + ) } /// Query storage of a specified contract under a specified key. @@ -702,12 +624,7 @@ impl Module { .get_alive() .ok_or(ContractAccessError::IsTombstone)?; - let maybe_value = AccountDb::::get_storage( - &DirectAccountDb, - &address, - Some(&contract_info.trie_id), - &key, - ); + let maybe_value = storage::read_contract_storage(&contract_info.trie_id, &key); Ok(maybe_value) } @@ -719,164 +636,20 @@ impl Module { } impl Module { + fn calc_code_put_costs(code: &Vec) -> Gas { + >::current_schedule().put_code_per_byte_cost.saturating_mul(code.len() as Gas) + } + fn execute_wasm( origin: T::AccountId, - gas_limit: Gas, - func: impl FnOnce(&mut ExecutionContext, &mut GasMeter) -> ExecResult + gas_meter: &mut GasMeter, + func: impl FnOnce(&mut ExecutionContext, &mut GasMeter) -> ExecResult, ) -> 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) = - 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); let loader = WasmLoader::new(&cfg.schedule); let mut ctx = ExecutionContext::top_level(origin.clone(), &cfg, &vm, &loader); - - let result = func(&mut ctx, &mut gas_meter); - - if result.as_ref().map(|output| output.is_success()).unwrap_or(false) { - // Commit all changes that made it thus far into the persistent storage. - DirectAccountDb.commit(ctx.overlay.into_change_set()); - } - - // Refund cost of the unused gas. - // - // NOTE: This should go after the commit to the storage, since the storage changes - // can alter the balance of the caller. - gas::refund_unused_gas::(&origin, gas_meter, imbalance); - - // Execute deferred actions. - ctx.deferred.into_iter().for_each(|deferred| { - use self::exec::DeferredAction::*; - match deferred { - DepositEvent { - topics, - event, - } => >::deposit_event_indexed( - &*topics, - ::Event::from(event).into(), - ), - DispatchRuntimeCall { - origin: who, - call, - } => { - let result = call.dispatch(RawOrigin::Signed(who.clone()).into()); - Self::deposit_event(RawEvent::Dispatched(who, result.is_ok())); - } - RestoreTo { - donor, - dest, - code_hash, - rent_allowance, - delta, - } => { - let result = Self::restore_to( - donor.clone(), dest.clone(), code_hash.clone(), rent_allowance.clone(), delta - ); - Self::deposit_event( - RawEvent::Restored(donor, dest, code_hash, rent_allowance, result.is_ok()) - ); - } - } - }); - - result - } - - fn restore_to( - origin: T::AccountId, - dest: T::AccountId, - code_hash: CodeHash, - rent_allowance: BalanceOf, - delta: Vec - ) -> DispatchResult { - let mut origin_contract = >::get(&origin) - .and_then(|c| c.get_alive()) - .ok_or(Error::::InvalidSourceContract)?; - - let current_block = >::block_number(); - - if origin_contract.last_write == Some(current_block) { - Err(Error::::InvalidContractOrigin)? - } - - let dest_tombstone = >::get(&dest) - .and_then(|c| c.get_tombstone()) - .ok_or(Error::::InvalidDestinationContract)?; - - let last_write = if !delta.is_empty() { - Some(current_block) - } else { - origin_contract.last_write - }; - - let key_values_taken = delta.iter() - .filter_map(|key| { - child::get_raw( - &origin_contract.trie_id, - origin_contract.child_trie_unique_id(), - &blake2_256(key), - ).map(|value| { - child::kill( - &origin_contract.trie_id, - origin_contract.child_trie_unique_id(), - &blake2_256(key), - ); - - (key, value) - }) - }) - .collect::>(); - - let tombstone = >::new( - // This operation is cheap enough because last_write (delta not included) - // is not this block as it has been checked earlier. - &child::child_root( - &origin_contract.trie_id, - )[..], - code_hash, - ); - - if tombstone != dest_tombstone { - for (key, value) in key_values_taken { - child::put_raw( - &origin_contract.trie_id, - origin_contract.child_trie_unique_id(), - &blake2_256(key), - &value, - ); - } - - return Err(Error::::InvalidTombstone.into()); - } - - origin_contract.storage_size -= key_values_taken.iter() - .map(|(_, value)| value.len() as u32) - .sum::(); - - >::remove(&origin); - >::insert(&dest, ContractInfo::Alive(RawAliveContractInfo { - trie_id: origin_contract.trie_id, - storage_size: origin_contract.storage_size, - code_hash, - rent_allowance, - deduct_block: current_block, - last_write, - })); - - let origin_free_balance = T::Currency::free_balance(&origin); - T::Currency::make_free_balance_be(&origin, >::zero()); - T::Currency::deposit_creating(&dest, origin_free_balance); - - Ok(()) + func(&mut ctx, gas_meter) } } @@ -887,9 +660,6 @@ decl_event! { ::AccountId, ::Hash { - /// 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. Instantiated(AccountId, AccountId), @@ -901,7 +671,7 @@ decl_event! { /// - `tombstone`: `bool`: True if the evicted contract left behind a tombstone. Evicted(AccountId, bool), - /// Restoration for a contract has been initiated. + /// Restoration for a contract has been successful. /// /// # Params /// @@ -909,8 +679,7 @@ decl_event! { /// - `dest`: `AccountId`: Account ID of the restored contract /// - `code_hash`: `Hash`: Code hash of the restored contract /// - `rent_allowance: `Balance`: Rent allowance of the restored contract - /// - `success`: `bool`: True if the restoration was successful - Restored(AccountId, AccountId, Hash, Balance, bool), + Restored(AccountId, AccountId, Hash, Balance), /// Code with the specified hash has been stored. CodeStored(Hash), @@ -918,10 +687,6 @@ decl_event! { /// Triggered when the current schedule is updated. ScheduleUpdated(u32), - /// A call was dispatched from the given account. The bool signals whether it was - /// successful execution or not. - Dispatched(AccountId, bool), - /// An event deposited upon execution of a contract from the account. ContractExecution(AccountId, Vec), } @@ -929,8 +694,6 @@ decl_event! { decl_storage! { trait Store for Module as Contracts { - /// Gas spent so far in this block. - GasSpent get(fn gas_spent): Gas; /// Current cost schedule for contracts. CurrentSchedule get(fn current_schedule) config(): Schedule = Schedule::default(); /// A mapping from an original code hash to the original code, untouched by instrumentation. @@ -940,9 +703,9 @@ decl_storage! { /// The subtrie counter. pub AccountCounter: u64 = 0; /// The code associated with a given account. + /// + /// TWOX-NOTE: SAFE since `AccountId` is a secure hash. pub ContractInfoOf: map hasher(twox_64_concat) T::AccountId => Option>; - /// The price of one unit of gas. - GasPrice get(fn gas_price) config(): BalanceOf = 1.into(); } } @@ -956,7 +719,6 @@ pub struct Config { pub tombstone_deposit: BalanceOf, pub max_depth: u32, pub max_value_size: u32, - pub contract_account_instantiate_fee: BalanceOf, } impl Config { @@ -967,9 +729,27 @@ impl Config { tombstone_deposit: T::TombstoneDeposit::get(), max_depth: T::MaxDepth::get(), max_value_size: T::MaxValueSize::get(), - contract_account_instantiate_fee: T::ContractFee::get(), } } + + /// Subsistence threshold is the extension of the minimum balance (aka existential deposit) by the + /// tombstone deposit, required for leaving a tombstone. + /// + /// Rent or any contract initiated balance transfer mechanism cannot make the balance lower + /// than the subsistence threshold in order to guarantee that a tombstone is created. + /// + /// The only way to completely kill a contract without a tombstone is calling `ext_terminate`. + fn subsistence_threshold(&self) -> BalanceOf { + self.existential_deposit.saturating_add(self.tombstone_deposit) + } + + /// The same as `subsistence_threshold` but without the need for a preloaded instance. + /// + /// This is for cases where this value is needed in rent calculation rather than + /// during contract execution. + fn subsistence_threshold_uncached() -> BalanceOf { + T::Currency::minimum_balance().saturating_add(T::TombstoneDeposit::get()) + } } /// Definition of the cost schedule and other parameterizations for wasm vm. @@ -1006,6 +786,9 @@ pub struct Schedule { /// Base gas cost to instantiate a contract. pub instantiate_base_cost: Gas, + /// Base gas cost to dispatch a runtime call. + pub dispatch_base_cost: Gas, + /// Gas cost per one byte read from the sandbox memory. pub sandbox_data_read_cost: Gas, @@ -1015,6 +798,9 @@ pub struct Schedule { /// Cost for a simple balance transfer. pub transfer_cost: Gas, + /// Cost for instantiating a new contract. + pub instantiate_cost: Gas, + /// The maximum number of topics supported by an event. pub max_event_topics: u32, @@ -1038,22 +824,29 @@ pub struct Schedule { pub max_subject_len: u32, } +// 500 (2 instructions per nano second on 2GHZ) * 1000x slowdown through wasmi +// This is a wild guess and should be viewed as a rough estimation. +// Proper benchmarks are needed before this value and its derivatives can be used in production. +const WASM_INSTRUCTION_COST: Gas = 500_000; + impl Default for Schedule { fn default() -> Schedule { Schedule { version: 0, - put_code_per_byte_cost: 1, - grow_mem_cost: 1, - regular_op_cost: 1, - return_data_per_byte_cost: 1, - event_data_per_byte_cost: 1, - event_per_topic_cost: 1, - event_base_cost: 1, - call_base_cost: 135, - instantiate_base_cost: 175, - sandbox_data_read_cost: 1, - sandbox_data_write_cost: 1, - transfer_cost: 100, + put_code_per_byte_cost: WASM_INSTRUCTION_COST, + grow_mem_cost: WASM_INSTRUCTION_COST, + regular_op_cost: WASM_INSTRUCTION_COST, + return_data_per_byte_cost: WASM_INSTRUCTION_COST, + event_data_per_byte_cost: WASM_INSTRUCTION_COST, + event_per_topic_cost: WASM_INSTRUCTION_COST, + event_base_cost: WASM_INSTRUCTION_COST, + call_base_cost: 135 * WASM_INSTRUCTION_COST, + dispatch_base_cost: 135 * WASM_INSTRUCTION_COST, + instantiate_base_cost: 175 * WASM_INSTRUCTION_COST, + sandbox_data_read_cost: WASM_INSTRUCTION_COST, + sandbox_data_write_cost: WASM_INSTRUCTION_COST, + transfer_cost: 100 * WASM_INSTRUCTION_COST, + instantiate_cost: 200 * WASM_INSTRUCTION_COST, max_event_topics: 4, max_stack_height: 64 * 1024, max_memory_pages: 16, @@ -1063,69 +856,3 @@ 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 sp_std::fmt::Debug for CheckBlockGasLimit { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - write!(f, "CheckBlockGasLimit") - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - Ok(()) - } -} - -impl SignedExtension for CheckBlockGasLimit { - const IDENTIFIER: &'static str = "CheckBlockGasLimit"; - type AccountId = T::AccountId; - type Call = ::Call; - type AdditionalSigned = (); - type DispatchInfo = DispatchInfo; - type Pre = (); - - fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) } - - fn validate( - &self, - _: &Self::AccountId, - call: &Self::Call, - _: Self::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/frame/contracts/src/rent.rs b/frame/contracts/src/rent.rs index 8b6825419c81e570033f695f52cf03c1f20847b6..a3f582810afe1445ea3857dbf9ce54f3c6483ad8 100644 --- a/frame/contracts/src/rent.rs +++ b/frame/contracts/src/rent.rs @@ -18,8 +18,10 @@ use crate::{ AliveContractInfo, BalanceOf, ContractInfo, ContractInfoOf, Module, RawEvent, - TombstoneContractInfo, Trait, + TombstoneContractInfo, Trait, CodeHash, Config }; +use sp_std::prelude::*; +use sp_io::hashing::blake2_256; use frame_support::storage::child; use frame_support::traits::{Currency, ExistenceRequirement, Get, OnUnbalanced, WithdrawReason}; use frame_support::StorageMap; @@ -85,45 +87,47 @@ enum Verdict { /// This function accounts for the storage rent deposit. I.e. if the contract possesses enough funds /// then the fee can drop to zero. fn compute_fee_per_block( - balance: &BalanceOf, + free_balance: &BalanceOf, contract: &AliveContractInfo, ) -> BalanceOf { - let free_storage = balance + let free_storage = free_balance .checked_div(&T::RentDepositOffset::get()) .unwrap_or_else(Zero::zero); - let effective_storage_size = - >::from(contract.storage_size).saturating_sub(free_storage); + // For now, we treat every empty KV pair as if it was one byte long. + let empty_pairs_equivalent = contract.empty_pair_count; + + let effective_storage_size = >::from( + contract.storage_size + T::StorageSizeOffset::get() + empty_pairs_equivalent, + ) + .saturating_sub(free_storage); effective_storage_size .checked_mul(&T::RentByteFee::get()) .unwrap_or(>::max_value()) } -/// Subsistence threshold is the extension of the minimum balance (aka existential deposit) by the -/// tombstone deposit, required for leaving a tombstone. -/// -/// Rent mechanism cannot make the balance lower than subsistence threshold. -fn subsistence_threshold() -> BalanceOf { - T::Currency::minimum_balance() + T::TombstoneDeposit::get() -} - /// Returns amount of funds available to consume by rent mechanism. /// /// Rent mechanism cannot consume more than `rent_allowance` set by the contract and it cannot make /// the balance lower than [`subsistence_threshold`]. /// -/// In case the balance is below the subsistence threshold, this function returns `None`. +/// In case the toal_balance is below the subsistence threshold, this function returns `None`. fn rent_budget( - balance: &BalanceOf, + total_balance: &BalanceOf, + free_balance: &BalanceOf, contract: &AliveContractInfo, ) -> Option> { - let subsistence_threshold = subsistence_threshold::(); - if *balance < subsistence_threshold { + let subsistence_threshold = Config::::subsistence_threshold_uncached(); + // Reserved balance contributes towards the subsistence threshold to stay consistent + // with the existential deposit where the reserved balance is also counted. + if *total_balance < subsistence_threshold { return None; } - let rent_allowed_to_charge = *balance - subsistence_threshold; + // However, reserved balance cannot be charged so we need to use the free balance + // to calculate the actual budget (which can be 0). + let rent_allowed_to_charge = free_balance.saturating_sub(subsistence_threshold); Some(>::min( contract.rent_allowance, rent_allowed_to_charge, @@ -151,21 +155,22 @@ fn consider_case( return Verdict::Exempt; } - let balance = T::Currency::free_balance(account); + let total_balance = T::Currency::total_balance(account); + let free_balance = T::Currency::free_balance(account); // An amount of funds to charge per block for storage taken up by the contract. - let fee_per_block = compute_fee_per_block::(&balance, contract); + let fee_per_block = compute_fee_per_block::(&free_balance, contract); if fee_per_block.is_zero() { // The rent deposit offset reduced the fee to 0. This means that the contract // gets the rent for free. return Verdict::Exempt; } - let rent_budget = match rent_budget::(&balance, contract) { + let rent_budget = match rent_budget::(&total_balance, &free_balance, contract) { Some(rent_budget) => rent_budget, None => { - // The contract's balance is already below subsistence threshold. That indicates that - // the contract cannot afford to leave a tombstone. + // The contract's total balance is already below subsistence threshold. That + // indicates that the contract cannot afford to leave a tombstone. // // So cleanly wipe the contract. return Verdict::Kill; @@ -188,7 +193,7 @@ fn consider_case( account, dues_limited, WithdrawReason::Fee.into(), - balance.saturating_sub(dues_limited), + free_balance.saturating_sub(dues_limited), ) .is_ok(); @@ -223,8 +228,7 @@ fn enact_verdict( Verdict::Kill => { >::remove(account); child::kill_storage( - &alive_contract_info.trie_id, - alive_contract_info.child_trie_unique_id(), + &alive_contract_info.child_trie_info(), ); >::deposit_event(RawEvent::Evicted(account.clone(), false)); None @@ -235,7 +239,9 @@ fn enact_verdict( } // Note: this operation is heavy. - let child_storage_root = child::child_root(&alive_contract_info.trie_id); + let child_storage_root = child::root( + &alive_contract_info.child_trie_info(), + ); let tombstone = >::new( &child_storage_root[..], @@ -245,8 +251,7 @@ fn enact_verdict( >::insert(account, &tombstone_info); child::kill_storage( - &alive_contract_info.trie_id, - alive_contract_info.child_trie_unique_id(), + &alive_contract_info.child_trie_info(), ); >::deposit_event(RawEvent::Evicted(account.clone(), true)); @@ -362,14 +367,15 @@ pub fn compute_rent_projection( }; // Compute how much would the fee per block be with the *updated* balance. - let balance = T::Currency::free_balance(account); - let fee_per_block = compute_fee_per_block::(&balance, &alive_contract_info); + let total_balance = T::Currency::total_balance(account); + let free_balance = T::Currency::free_balance(account); + let fee_per_block = compute_fee_per_block::(&free_balance, &alive_contract_info); if fee_per_block.is_zero() { return Ok(RentProjection::NoEviction); } // Then compute how much the contract will sustain under these circumstances. - let rent_budget = rent_budget::(&balance, &alive_contract_info).expect( + let rent_budget = rent_budget::(&total_balance, &free_balance, &alive_contract_info).expect( "the contract exists and in the alive state; the updated balance must be greater than subsistence deposit; this function doesn't return `None`; @@ -391,3 +397,90 @@ pub fn compute_rent_projection( current_block_number + blocks_left, )) } + +/// Restores the destination account using the origin as prototype. +/// +/// The restoration will be performed iff: +/// - origin exists and is alive, +/// - the origin's storage is not written in the current block +/// - the restored account has tombstone +/// - the tombstone matches the hash of the origin storage root, and code hash. +/// +/// Upon succesful restoration, `origin` will be destroyed, all its funds are transferred to +/// the restored account. The restored account will inherit the last write block and its last +/// deduct block will be set to the current block. +pub fn restore_to( + origin: T::AccountId, + dest: T::AccountId, + code_hash: CodeHash, + rent_allowance: BalanceOf, + delta: Vec, +) -> Result<(), &'static str> { + let mut origin_contract = >::get(&origin) + .and_then(|c| c.get_alive()) + .ok_or("Cannot restore from inexisting or tombstone contract")?; + + let child_trie_info = origin_contract.child_trie_info(); + + let current_block = >::block_number(); + + if origin_contract.last_write == Some(current_block) { + return Err("Origin TrieId written in the current block"); + } + + let dest_tombstone = >::get(&dest) + .and_then(|c| c.get_tombstone()) + .ok_or("Cannot restore to inexisting or alive contract")?; + + let last_write = if !delta.is_empty() { + Some(current_block) + } else { + origin_contract.last_write + }; + + let key_values_taken = delta.iter() + .filter_map(|key| { + child::get_raw(&child_trie_info, &blake2_256(key)).map(|value| { + child::kill(&child_trie_info, &blake2_256(key)); + (key, value) + }) + }) + .collect::>(); + + let tombstone = >::new( + // This operation is cheap enough because last_write (delta not included) + // is not this block as it has been checked earlier. + &child::root(&child_trie_info)[..], + code_hash, + ); + + if tombstone != dest_tombstone { + for (key, value) in key_values_taken { + child::put_raw(&child_trie_info, &blake2_256(key), &value); + } + + return Err("Tombstones don't match"); + } + + origin_contract.storage_size -= key_values_taken.iter() + .map(|(_, value)| value.len() as u32) + .sum::(); + + >::remove(&origin); + >::insert(&dest, ContractInfo::Alive(AliveContractInfo:: { + trie_id: origin_contract.trie_id, + storage_size: origin_contract.storage_size, + empty_pair_count: origin_contract.empty_pair_count, + total_pair_count: origin_contract.total_pair_count, + code_hash, + rent_allowance, + deduct_block: current_block, + last_write, + })); + + let origin_free_balance = T::Currency::free_balance(&origin); + T::Currency::make_free_balance_be(&origin, >::zero()); + T::Currency::deposit_creating(&dest, origin_free_balance); + + Ok(()) +} diff --git a/frame/contracts/src/storage.rs b/frame/contracts/src/storage.rs new file mode 100644 index 0000000000000000000000000000000000000000..4c5ad892a967b1012060f4aaa682b3f1292a3d6c --- /dev/null +++ b/frame/contracts/src/storage.rs @@ -0,0 +1,195 @@ +// 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 contains routines for accessing and altering a contract related state. + +use crate::{ + exec::{AccountIdOf, StorageKey}, + AliveContractInfo, BalanceOf, CodeHash, ContractInfo, ContractInfoOf, Trait, TrieId, +}; +use sp_std::prelude::*; +use sp_io::hashing::blake2_256; +use sp_runtime::traits::Bounded; +use frame_support::{storage::child, StorageMap}; + +/// An error that means that the account requested either doesn't exist or represents a tombstone +/// account. +#[cfg_attr(test, derive(PartialEq, Eq, Debug))] +pub struct ContractAbsentError; + +/// Reads a storage kv pair of a contract. +/// +/// The read is performed from the `trie_id` only. The `address` is not necessary. If the contract +/// doesn't store under the given `key` `None` is returned. +pub fn read_contract_storage(trie_id: &TrieId, key: &StorageKey) -> Option> { + child::get_raw(&crate::child_trie_info(&trie_id), &blake2_256(key)) +} + +/// Update a storage entry into a contract's kv storage. +/// +/// If the `opt_new_value` is `None` then the kv pair is removed. +/// +/// This function also updates the bookkeeping info such as: number of total non-empty pairs a +/// contract owns, the last block the storage was written to, etc. That's why, in contrast to +/// `read_contract_storage`, this function also requires the `account` ID. +/// +/// If the contract specified by the id `account` doesn't exist `Err` is returned.` +pub fn write_contract_storage( + account: &AccountIdOf, + trie_id: &TrieId, + key: &StorageKey, + opt_new_value: Option>, +) -> Result<(), ContractAbsentError> { + let mut new_info = match >::get(account) { + Some(ContractInfo::Alive(alive)) => alive, + None | Some(ContractInfo::Tombstone(_)) => return Err(ContractAbsentError), + }; + + let hashed_key = blake2_256(key); + let child_trie_info = &crate::child_trie_info(&trie_id); + + // In order to correctly update the book keeping we need to fetch the previous + // value of the key-value pair. + // + // It might be a bit more clean if we had an API that supported getting the size + // of the value without going through the loading of it. But at the moment of + // writing, there is no such API. + // + // That's not a show stopper in any case, since the performance cost is + // dominated by the trie traversal anyway. + let opt_prev_value = child::get_raw(&child_trie_info, &hashed_key); + + // Update the total number of KV pairs and the number of empty pairs. + match (&opt_prev_value, &opt_new_value) { + (Some(prev_value), None) => { + new_info.total_pair_count -= 1; + if prev_value.is_empty() { + new_info.empty_pair_count -= 1; + } + }, + (None, Some(new_value)) => { + new_info.total_pair_count += 1; + if new_value.is_empty() { + new_info.empty_pair_count += 1; + } + }, + (Some(prev_value), Some(new_value)) => { + if prev_value.is_empty() { + new_info.empty_pair_count -= 1; + } + if new_value.is_empty() { + new_info.empty_pair_count += 1; + } + } + (None, None) => {} + } + + // Update the total storage size. + let prev_value_len = opt_prev_value + .as_ref() + .map(|old_value| old_value.len() as u32) + .unwrap_or(0); + let new_value_len = opt_new_value + .as_ref() + .map(|new_value| new_value.len() as u32) + .unwrap_or(0); + new_info.storage_size = new_info + .storage_size + .saturating_add(new_value_len) + .saturating_sub(prev_value_len); + + new_info.last_write = Some(>::block_number()); + >::insert(&account, ContractInfo::Alive(new_info)); + + // Finally, perform the change on the storage. + match opt_new_value { + Some(new_value) => child::put_raw(&child_trie_info, &hashed_key, &new_value[..]), + None => child::kill(&child_trie_info, &hashed_key), + } + + Ok(()) +} + +/// Returns the rent allowance set for the contract give by the account id. +pub fn rent_allowance( + account: &AccountIdOf, +) -> Result, ContractAbsentError> { + >::get(account) + .and_then(|i| i.as_alive().map(|i| i.rent_allowance)) + .ok_or(ContractAbsentError) +} + +/// Set the rent allowance for the contract given by the account id. +/// +/// Returns `Err` if the contract doesn't exist or is a tombstone. +pub fn set_rent_allowance( + account: &AccountIdOf, + rent_allowance: BalanceOf, +) -> Result<(), ContractAbsentError> { + >::mutate(account, |maybe_contract_info| match maybe_contract_info { + Some(ContractInfo::Alive(ref mut alive_info)) => { + alive_info.rent_allowance = rent_allowance; + Ok(()) + } + _ => Err(ContractAbsentError), + }) +} + +/// Returns the code hash of the contract specified by `account` ID. +pub fn code_hash(account: &AccountIdOf) -> Result, ContractAbsentError> { + >::get(account) + .and_then(|i| i.as_alive().map(|i| i.code_hash)) + .ok_or(ContractAbsentError) +} + +/// Creates a new contract descriptor in the storage with the given code hash at the given address. +/// +/// Returns `Err` if there is already a contract (or a tombstone) exists at the given address. +pub fn place_contract( + account: &AccountIdOf, + trie_id: TrieId, + ch: CodeHash, +) -> Result<(), &'static str> { + >::mutate(account, |maybe_contract_info| { + if maybe_contract_info.is_some() { + return Err("Alive contract or tombstone already exists"); + } + + *maybe_contract_info = Some( + AliveContractInfo:: { + code_hash: ch, + storage_size: 0, + trie_id, + deduct_block: >::block_number(), + rent_allowance: >::max_value(), + empty_pair_count: 0, + total_pair_count: 0, + last_write: None, + } + .into(), + ); + + Ok(()) + }) +} + +/// Removes the contract and all the storage associated with it. +/// +/// This function doesn't affect the account. +pub fn destroy_contract(address: &AccountIdOf, trie_id: &TrieId) { + >::remove(address); + child::kill_storage(&crate::child_trie_info(&trie_id)); +} diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index 04b9b1ee4ca7775ebb53d434bbcc64cd465cef49..aac191e76ea74cb1614757f537ad7b7b3c505e9f 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -14,31 +14,26 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -// TODO: #1417 Add more integration tests -// also remove the #![allow(unused)] below. - -#![allow(unused)] - use crate::{ - BalanceOf, ComputeDispatchFee, ContractAddressFor, ContractInfo, ContractInfoOf, GenesisConfig, - Module, RawAliveContractInfo, RawEvent, Trait, TrieId, TrieIdFromParentCounter, Schedule, - TrieIdGenerator, CheckBlockGasLimit, account_db::{AccountDb, DirectAccountDb, OverlayAccountDb}, + BalanceOf, ContractAddressFor, ContractInfo, ContractInfoOf, GenesisConfig, Module, + RawAliveContractInfo, RawEvent, Trait, TrieId, Schedule, TrieIdGenerator, gas::Gas, + Error, }; use assert_matches::assert_matches; use hex_literal::*; -use codec::{Decode, Encode, KeyedVec}; +use codec::Encode; use sp_runtime::{ - Perbill, BuildStorage, transaction_validity::{InvalidTransaction, ValidTransaction}, - traits::{BlakeTwo256, Hash, IdentityLookup, SignedExtension}, - testing::{Digest, DigestItem, Header, UintAuthorityId, H256}, + Perbill, + traits::{BlakeTwo256, Hash, IdentityLookup, Convert}, + testing::{Header, H256}, }; use frame_support::{ - assert_ok, assert_err, impl_outer_dispatch, impl_outer_event, impl_outer_origin, parameter_types, - storage::child, StorageMap, StorageValue, traits::{Currency, Get}, - weights::{DispatchInfo, DispatchClass, Weight}, + assert_ok, assert_err_ignore_postinfo, impl_outer_dispatch, impl_outer_event, + impl_outer_origin, parameter_types, StorageMap, StorageValue, + traits::{Currency, Get}, + weights::{Weight, PostDispatchInfo}, }; -use std::{cell::RefCell, sync::atomic::{AtomicUsize, Ordering}}; -use sp_core::storage::well_known_keys; +use std::cell::RefCell; use frame_system::{self as system, EventRecord, Phase}; mod contracts { @@ -46,7 +41,7 @@ mod contracts { // needs to give a name for the current crate. // This hack is required for `impl_outer_event!`. pub use super::super::*; - use frame_support::impl_outer_event; + pub use frame_support::impl_outer_event; } use pallet_balances as balances; @@ -68,11 +63,36 @@ impl_outer_dispatch! { } } +pub mod test_utils { + use super::{Test, Balances}; + use crate::{ContractInfoOf, TrieIdGenerator, CodeHash}; + use crate::storage::{write_contract_storage, read_contract_storage}; + use crate::exec::StorageKey; + use frame_support::{StorageMap, traits::Currency}; + + pub fn set_storage(addr: &u64, key: &StorageKey, value: Option>) { + let contract_info = >::get(&addr).unwrap().get_alive().unwrap(); + write_contract_storage::(&1, &contract_info.trie_id, key, value).unwrap(); + } + pub fn get_storage(addr: &u64, key: &StorageKey) -> Option> { + let contract_info = >::get(&addr).unwrap().get_alive().unwrap(); + read_contract_storage(&contract_info.trie_id, key) + } + pub fn place_contract(address: &u64, code_hash: CodeHash) { + let trie_id = ::TrieIdGenerator::trie_id(address); + crate::storage::place_contract::(&address, trie_id, code_hash).unwrap() + } + pub fn set_balance(who: &u64, amount: u64) { + let imbalance = Balances::deposit_creating(who, amount); + drop(imbalance); + } + pub fn get_balance(who: &u64) -> u64 { + Balances::free_balance(who) + } +} + thread_local! { static EXISTENTIAL_DEPOSIT: RefCell = RefCell::new(0); - static TRANSFER_FEE: RefCell = RefCell::new(0); - static INSTANTIATION_FEE: RefCell = RefCell::new(0); - static BLOCK_GAS_LIMIT: RefCell = RefCell::new(0); } pub struct ExistentialDeposit; @@ -80,16 +100,6 @@ impl Get for ExistentialDeposit { fn get() -> u64 { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow()) } } -pub struct TransferFee; -impl Get for TransferFee { - fn get() -> u64 { TRANSFER_FEE.with(|v| *v.borrow()) } -} - -pub struct BlockGasLimit; -impl Get for BlockGasLimit { - fn get() -> u64 { BLOCK_GAS_LIMIT.with(|v| *v.borrow()) } -} - #[derive(Clone, Eq, PartialEq, Debug)] pub struct Test; parameter_types! { @@ -99,11 +109,12 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; type Hash = H256; - type Call = (); + type Call = Call; type Hashing = BlakeTwo256; type AccountId = u64; type Lookup = IdentityLookup; @@ -111,6 +122,10 @@ impl frame_system::Trait for Test { type Event = MetaEvent; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); @@ -118,6 +133,7 @@ impl frame_system::Trait for Test { type AccountData = pallet_balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } impl pallet_balances::Trait for Test { type Balance = u64; @@ -125,6 +141,7 @@ impl pallet_balances::Trait for Test { type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; + type WeightInfo = (); } parameter_types! { pub const MinimumPeriod: u64 = 1; @@ -133,6 +150,7 @@ impl pallet_timestamp::Trait for Test { type Moment = u64; type OnTimestampSet = (); type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); } parameter_types! { pub const SignedClaimHandicap: u64 = 2; @@ -141,24 +159,27 @@ parameter_types! { pub const RentByteFee: u64 = 4; pub const RentDepositOffset: u64 = 10_000; pub const SurchargeReward: u64 = 150; - pub const TransactionBaseFee: u64 = 2; - pub const TransactionByteFee: u64 = 6; - pub const ContractFee: u64 = 21; - pub const CallBaseFee: u64 = 135; - pub const InstantiateBaseFee: u64 = 175; pub const MaxDepth: u32 = 100; pub const MaxValueSize: u32 = 16_384; } + +parameter_types! { + pub const TransactionByteFee: u64 = 0; +} + +impl Convert> for Test { + fn convert(w: Weight) -> BalanceOf { + w + } +} + impl Trait for Test { - type Currency = Balances; type Time = Timestamp; type Randomness = Randomness; - type Call = Call; + type Currency = Balances; type DetermineContractAddress = DummyContractAddressFor; type Event = MetaEvent; - type ComputeDispatchFee = DummyComputeDispatchFee; type TrieIdGenerator = DummyTrieIdGenerator; - type GasPayment = (); type RentPayment = (); type SignedClaimHandicap = SignedClaimHandicap; type TombstoneDeposit = TombstoneDeposit; @@ -166,14 +187,9 @@ impl Trait for Test { type RentByteFee = RentByteFee; type RentDepositOffset = RentDepositOffset; type SurchargeReward = SurchargeReward; - type TransactionBaseFee = TransactionBaseFee; - type TransactionByteFee = TransactionByteFee; - type ContractFee = ContractFee; - type CallBaseFee = CallBaseFee; - type InstantiateBaseFee = InstantiateBaseFee; type MaxDepth = MaxDepth; type MaxValueSize = MaxValueSize; - type BlockGasLimit = BlockGasLimit; + type WeightPrice = Self; } type Balances = pallet_balances::Module; @@ -192,50 +208,32 @@ impl ContractAddressFor for DummyContractAddressFor { pub struct DummyTrieIdGenerator; impl TrieIdGenerator for DummyTrieIdGenerator { fn trie_id(account_id: &u64) -> TrieId { - use sp_core::storage::well_known_keys; - let new_seed = super::AccountCounter::mutate(|v| { *v = v.wrapping_add(1); *v }); - // TODO: see https://github.com/paritytech/substrate/issues/2325 let mut res = vec![]; - res.extend_from_slice(well_known_keys::CHILD_STORAGE_KEY_PREFIX); - res.extend_from_slice(b"default:"); res.extend_from_slice(&new_seed.to_le_bytes()); res.extend_from_slice(&account_id.to_le_bytes()); res } } -pub struct DummyComputeDispatchFee; -impl ComputeDispatchFee for DummyComputeDispatchFee { - fn compute_dispatch_fee(call: &Call) -> u64 { - 69 - } -} - const ALICE: u64 = 1; const BOB: u64 = 2; const CHARLIE: u64 = 3; const DJANGO: u64 = 4; +const GAS_LIMIT: Gas = 10_000_000_000; + pub struct ExtBuilder { existential_deposit: u64, - gas_price: u64, - block_gas_limit: u64, - transfer_fee: u64, - instantiation_fee: u64, } impl Default for ExtBuilder { fn default() -> Self { Self { existential_deposit: 1, - gas_price: 2, - block_gas_limit: 100_000_000, - transfer_fee: 0, - instantiation_fee: 0, } } } @@ -244,27 +242,8 @@ impl ExtBuilder { self.existential_deposit = existential_deposit; self } - pub fn gas_price(mut self, gas_price: u64) -> Self { - self.gas_price = gas_price; - self - } - pub fn block_gas_limit(mut self, block_gas_limit: u64) -> Self { - self.block_gas_limit = block_gas_limit; - self - } - pub fn transfer_fee(mut self, transfer_fee: u64) -> Self { - self.transfer_fee = transfer_fee; - self - } - 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); - 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) -> sp_io::TestExternalities { self.set_associated_consts(); @@ -272,12 +251,11 @@ impl ExtBuilder { pallet_balances::GenesisConfig:: { balances: vec![], }.assimilate_storage(&mut t).unwrap(); - GenesisConfig:: { + GenesisConfig { current_schedule: Schedule { enable_println: true, ..Default::default() }, - gas_price: self.gas_price, }.assimilate_storage(&mut t).unwrap(); let mut ext = sp_io::TestExternalities::new(t); ext.execute_with(|| System::set_block_number(1)); @@ -285,32 +263,48 @@ impl ExtBuilder { } } -/// Generate Wasm binary and code hash from wabt source. -fn compile_module(wabt_module: &str) - -> Result<(Vec, ::Output), wabt::Error> - where T: frame_system::Trait +/// Load a given wasm module represented by a .wat file and returns a wasm binary contents along +/// with it's hash. +/// +/// The fixture files are located under the `fixtures/` directory. +fn compile_module( + fixture_name: &str, +) -> Result<(Vec, ::Output), wabt::Error> +where + T: frame_system::Trait, { - let wasm = wabt::wat2wasm(wabt_module)?; - let code_hash = T::Hashing::hash(&wasm); - Ok((wasm, code_hash)) + use std::fs; + + let fixture_path = ["fixtures/", fixture_name, ".wat"].concat(); + let module_wat_source = + fs::read_to_string(&fixture_path).expect(&format!("Unable to find {} fixture", fixture_name)); + let wasm_binary = wabt::wat2wasm(module_wat_source)?; + let code_hash = T::Hashing::hash(&wasm_binary); + Ok((wasm_binary, code_hash)) } -// Perform a simple transfer to a non-existent account supplying way more gas than needed. -// Then we check that the all unused gas is refunded. +// Perform a simple transfer to a non-existent account. +// Then we check that only the base costs are returned as actual costs. #[test] -fn refunds_unused_gas() { - ExtBuilder::default().gas_price(2).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 100_000_000); +fn returns_base_call_cost() { + ExtBuilder::default().build().execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 100_000_000); - assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, 100_000, Vec::new())); - - // 2 * 135 - gas price multiplied by the call base fee. - assert_eq!(Balances::free_balance(ALICE), 100_000_000 - (2 * 135)); + assert_eq!( + Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, Vec::new()), + Ok( + PostDispatchInfo { + actual_weight: Some(67500000), + } + ) + ); }); } #[test] fn account_removal_does_not_remove_storage() { + use self::test_utils::{set_storage, get_storage}; + ExtBuilder::default().existential_deposit(100).build().execute_with(|| { let trie_id1 = ::TrieIdGenerator::trie_id(&1); let trie_id2 = ::TrieIdGenerator::trie_id(&2); @@ -319,568 +313,177 @@ fn account_removal_does_not_remove_storage() { // Set up two accounts with free balance above the existential threshold. { - Balances::deposit_creating(&1, 110); - ContractInfoOf::::insert(1, &ContractInfo::Alive(RawAliveContractInfo { + let alice_contract_info = ContractInfo::Alive(RawAliveContractInfo { trie_id: trie_id1.clone(), - storage_size: ::StorageSizeOffset::get(), + storage_size: 0, + empty_pair_count: 0, + total_pair_count: 0, deduct_block: System::block_number(), code_hash: H256::repeat_byte(1), rent_allowance: 40, last_write: None, - })); + }); + let _ = Balances::deposit_creating(&ALICE, 110); + ContractInfoOf::::insert(ALICE, &alice_contract_info); + set_storage(&ALICE, &key1, Some(b"1".to_vec())); + set_storage(&ALICE, &key2, Some(b"2".to_vec())); - 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 { + let bob_contract_info = ContractInfo::Alive(RawAliveContractInfo { trie_id: trie_id2.clone(), - storage_size: ::StorageSizeOffset::get(), + storage_size: 0, + empty_pair_count: 0, + total_pair_count: 0, 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()); + }); + let _ = Balances::deposit_creating(&BOB, 110); + ContractInfoOf::::insert(BOB, &bob_contract_info); + set_storage(&BOB, &key1, Some(b"3".to_vec())); + set_storage(&BOB, &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. + // Transfer funds from ALICE account of such amount that after this transfer + // the balance of the ALICE account will be below the existential threshold. // // This does not remove the contract storage as we are not notified about a // account removal. This cannot happen in reality because a contract can only // remove itself by `ext_terminate`. There is no external event that can remove // the account appart from that. - assert_ok!(Balances::transfer(Origin::signed(1), 2, 20)); + assert_ok!(Balances::transfer(Origin::signed(ALICE), BOB, 20)); // Verify that no entries are removed. { assert_eq!( - >::get_storage(&DirectAccountDb, &1, Some(&trie_id1), key1), + get_storage(&ALICE, key1), Some(b"1".to_vec()) ); assert_eq!( - >::get_storage(&DirectAccountDb, &1, Some(&trie_id1), key2), + get_storage(&ALICE, key2), Some(b"2".to_vec()) ); assert_eq!( - >::get_storage(&DirectAccountDb, &2, Some(&trie_id2), key1), + get_storage(&BOB, key1), Some(b"3".to_vec()) ); assert_eq!( - >::get_storage(&DirectAccountDb, &2, Some(&trie_id2), key2), + get_storage(&BOB, key2), Some(b"4".to_vec()) ); } }); } -const CODE_RETURN_FROM_START_FN: &str = r#" -(module - (import "env" "ext_return" (func $ext_return (param i32 i32))) - (import "env" "ext_deposit_event" (func $ext_deposit_event (param i32 i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - (start $start) - (func $start - (call $ext_deposit_event - (i32.const 0) ;; The topics buffer - (i32.const 0) ;; The topics buffer's length - (i32.const 8) ;; The data buffer - (i32.const 4) ;; The data buffer's length - ) - (call $ext_return - (i32.const 8) - (i32.const 4) - ) - (unreachable) - ) - - (func (export "call") - (unreachable) - ) - (func (export "deploy")) - - (data (i32.const 8) "\01\02\03\04") -) -"#; - #[test] fn instantiate_and_call_and_deposit_event() { - let (wasm, code_hash) = compile_module::(CODE_RETURN_FROM_START_FN).unwrap(); - - ExtBuilder::default().existential_deposit(100).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); - - assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm)); - - // Check at the end to get hash on error easily - let creation = Contracts::instantiate( - Origin::signed(ALICE), - 100, - 100_000, - code_hash.into(), - vec![], - ); - - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(BOB)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances( - pallet_balances::RawEvent::Endowed(BOB, 100) - ), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Transfer(ALICE, BOB, 100)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::ContractExecution(BOB, vec![1, 2, 3, 4])), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Instantiated(ALICE, BOB)), - topics: vec![], - } - ]); - - assert_ok!(creation); - assert!(ContractInfoOf::::contains_key(BOB)); - }); -} - -const CODE_DISPATCH_CALL: &str = r#" -(module - (import "env" "ext_dispatch_call" (func $ext_dispatch_call (param i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func (export "call") - (call $ext_dispatch_call - (i32.const 8) ;; Pointer to the start of encoded call buffer - (i32.const 11) ;; Length of the buffer - ) - ) - (func (export "deploy")) - - (data (i32.const 8) "\00\00\03\00\00\00\00\00\00\00\C8") -) -"#; - -#[test] -fn dispatch_call() { - // This test can fail due to the encoding changes. In case it becomes too annoying - // let's rewrite so as we use this module controlled call or we serialize it in runtime. - let encoded = Encode::encode(&Call::Balances(pallet_balances::Call::transfer(CHARLIE, 50))); - assert_eq!(&encoded[..], &hex!("00000300000000000000C8")[..]); - - let (wasm, code_hash) = compile_module::(CODE_DISPATCH_CALL).unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); - - assert_ok!(Contracts::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::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())), - topics: vec![], - }, - ]); - - assert_ok!(Contracts::instantiate( - Origin::signed(ALICE), - 100, - 100_000, - code_hash.into(), - vec![], - )); - - assert_ok!(Contracts::call( - Origin::signed(ALICE), - BOB, // newly created account - 0, - 100_000, - vec![], - )); - - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(BOB)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances( - pallet_balances::RawEvent::Endowed(BOB, 100) - ), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Transfer(ALICE, BOB, 100)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Instantiated(ALICE, BOB)), - topics: vec![], - }, - - // Dispatching the call. - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(CHARLIE)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances( - pallet_balances::RawEvent::Endowed(CHARLIE, 50) - ), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances( - pallet_balances::RawEvent::Transfer(BOB, CHARLIE, 50) - ), - topics: vec![], - }, - - // Event emitted as a result of dispatch. - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Dispatched(BOB, true)), - topics: vec![], - } - ]); - }); -} - -const CODE_DISPATCH_CALL_THEN_TRAP: &str = r#" -(module - (import "env" "ext_dispatch_call" (func $ext_dispatch_call (param i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func (export "call") - (call $ext_dispatch_call - (i32.const 8) ;; Pointer to the start of encoded call buffer - (i32.const 11) ;; Length of the buffer - ) - (unreachable) ;; trap so that the top level transaction fails - ) - (func (export "deploy")) - - (data (i32.const 8) "\00\00\03\00\00\00\00\00\00\00\C8") -) -"#; - -#[test] -fn dispatch_call_not_dispatched_after_top_level_transaction_failure() { - // This test can fail due to the encoding changes. In case it becomes too annoying - // let's rewrite so as we use this module controlled call or we serialize it in runtime. - let encoded = Encode::encode(&Call::Balances(pallet_balances::Call::transfer(CHARLIE, 50))); - assert_eq!(&encoded[..], &hex!("00000300000000000000C8")[..]); + let (wasm, code_hash) = compile_module::("return_from_start_fn").unwrap(); - let (wasm, code_hash) = compile_module::(CODE_DISPATCH_CALL_THEN_TRAP).unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); + ExtBuilder::default() + .existential_deposit(100) + .build() + .execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm)); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), 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::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())), - topics: vec![], - }, - ]); - - assert_ok!(Contracts::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!( - Contracts::call( + // Check at the end to get hash on error easily + let creation = Contracts::instantiate( Origin::signed(ALICE), - BOB, // newly created account - 0, - 100_000, + 100, + GAS_LIMIT, + code_hash.into(), vec![], - ), - "contract trapped during execution" - ); - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(BOB)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances( - pallet_balances::RawEvent::Endowed(BOB, 100) - ), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Transfer(ALICE, BOB, 100)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Instantiated(ALICE, BOB)), - topics: vec![], - }, - // ABSENCE of events which would be caused by dispatched Balances::transfer call - ]); - }); -} + ); + + pretty_assertions::assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::system(frame_system::RawEvent::NewAccount(BOB)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::balances( + pallet_balances::RawEvent::Endowed(BOB, 100) + ), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::balances( + pallet_balances::RawEvent::Transfer(ALICE, BOB, 100) + ), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::ContractExecution(BOB, vec![1, 2, 3, 4])), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::Instantiated(ALICE, BOB)), + topics: vec![], + } + ]); -const CODE_RUN_OUT_OF_GAS: &str = r#" -(module - (func (export "call") - (loop $inf (br $inf)) ;; just run out of gas - (unreachable) - ) - (func (export "deploy")) -) -"#; + assert_ok!(creation); + assert!(ContractInfoOf::::contains_key(BOB)); + }); +} #[test] fn run_out_of_gas() { - let (wasm, code_hash) = compile_module::(CODE_RUN_OUT_OF_GAS).unwrap(); + let (wasm, code_hash) = compile_module::("run_out_of_gas").unwrap(); ExtBuilder::default() .existential_deposit(50) .build() .execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); + let _ = Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm)); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); assert_ok!(Contracts::instantiate( Origin::signed(ALICE), 100, - 100_000, + GAS_LIMIT, code_hash.into(), vec![], )); // Call the contract with a fixed gas limit. It must run out of gas because it just // loops forever. - assert_err!( + assert_err_ignore_postinfo!( Contracts::call( Origin::signed(ALICE), BOB, // newly created account 0, - 1000, + 67_500_000, vec![], ), - "ran out of gas during contract execution" + Error::::OutOfGas, ); }); } -const CODE_SET_RENT: &str = r#" -(module - (import "env" "ext_dispatch_call" (func $ext_dispatch_call (param i32 i32))) - (import "env" "ext_set_storage" (func $ext_set_storage (param i32 i32 i32))) - (import "env" "ext_clear_storage" (func $ext_clear_storage (param i32))) - (import "env" "ext_set_rent_allowance" (func $ext_set_rent_allowance (param i32 i32))) - (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)) - - ;; insert a value of 4 bytes into storage - (func $call_0 - (call $ext_set_storage - (i32.const 1) - (i32.const 0) - (i32.const 4) - ) - ) - - ;; remove the value inserted by call_1 - (func $call_1 - (call $ext_clear_storage - (i32.const 1) - ) - ) - - ;; transfer 50 to ALICE - (func $call_2 - (call $ext_dispatch_call - (i32.const 68) - (i32.const 11) - ) - ) - - ;; do nothing - (func $call_else) - - (func $assert (param i32) - (block $ok - (br_if $ok - (get_local 0) - ) - (unreachable) - ) - ) - - ;; Dispatch the call according to input size - (func (export "call") - (local $input_size i32) - (set_local $input_size - (call $ext_scratch_size) - ) - (block $IF_ELSE - (block $IF_2 - (block $IF_1 - (block $IF_0 - (br_table $IF_0 $IF_1 $IF_2 $IF_ELSE - (get_local $input_size) - ) - (unreachable) - ) - (call $call_0) - return - ) - (call $call_1) - return - ) - (call $call_2) - return - ) - (call $call_else) - ) - - ;; Set into storage a 4 bytes value - ;; Set call set_rent_allowance with input - (func (export "deploy") - (local $input_size i32) - (set_local $input_size - (call $ext_scratch_size) - ) - (call $ext_set_storage - (i32.const 0) - (i32.const 0) - (i32.const 4) - ) - (call $ext_scratch_read - (i32.const 0) - (i32.const 0) - (get_local $input_size) - ) - (call $ext_set_rent_allowance - (i32.const 0) - (get_local $input_size) - ) - ) - - ;; Encoding of 10 in balance - (data (i32.const 0) "\28") - - ;; Encoding of call transfer 50 to CHARLIE - (data (i32.const 68) "\00\00\03\00\00\00\00\00\00\00\C8") -) -"#; - /// Input data for each call in set_rent code mod call { pub fn set_storage_4_byte() -> Vec { vec![] } @@ -898,143 +501,243 @@ fn test_set_rent_code_and_hash() { let encoded = Encode::encode(&Call::Balances(pallet_balances::Call::transfer(CHARLIE, 50))); assert_eq!(&encoded[..], &hex!("00000300000000000000C8")[..]); - let (wasm, code_hash) = compile_module::(CODE_SET_RENT).unwrap(); + let (wasm, code_hash) = compile_module::("set_rent").unwrap(); - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm)); + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), 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::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())), - topics: vec![], - }, - ]); - }); + // 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::Initialization, + event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())), + topics: vec![], + }, + ]); + }); } #[test] fn storage_size() { - let (wasm, code_hash) = compile_module::(CODE_SET_RENT).unwrap(); + let (wasm, code_hash) = compile_module::("set_rent").unwrap(); // Storage size - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm)); - assert_ok!(Contracts::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!(Contracts::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!(Contracts::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 + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 30_000, + GAS_LIMIT, + 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, + 4 + ); + assert_eq!( + bob_contract.total_pair_count, + 1, + ); + assert_eq!( + bob_contract.empty_pair_count, + 0, + ); -fn initialize_block(number: u64) { - System::initialize( - &number, - &[0u8; 32].into(), - &[0u8; 32].into(), - &Default::default(), - Default::default(), - ); -} + assert_ok!(Contracts::call( + Origin::signed(ALICE), + BOB, + 0, + GAS_LIMIT, + call::set_storage_4_byte() + )); + let bob_contract = ContractInfoOf::::get(BOB) + .unwrap() + .get_alive() + .unwrap(); + assert_eq!( + bob_contract.storage_size, + 4 + 4 + ); + assert_eq!( + bob_contract.total_pair_count, + 2, + ); + assert_eq!( + bob_contract.empty_pair_count, + 0, + ); -#[test] -fn deduct_blocks() { - let (wasm, code_hash) = compile_module::(CODE_SET_RENT).unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm)); - assert_ok!(Contracts::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 - initialize_block(5); - - // Trigger rent through call - assert_ok!(Contracts::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 - initialize_block(12); - - // Trigger rent through call - assert_ok!(Contracts::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!(Contracts::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); - }); + assert_ok!(Contracts::call( + Origin::signed(ALICE), + BOB, + 0, + GAS_LIMIT, + call::remove_storage_4_byte() + )); + let bob_contract = ContractInfoOf::::get(BOB) + .unwrap() + .get_alive() + .unwrap(); + assert_eq!( + bob_contract.storage_size, + 4 + ); + assert_eq!( + bob_contract.total_pair_count, + 1, + ); + assert_eq!( + bob_contract.empty_pair_count, + 0, + ); + }); } #[test] -fn call_contract_removals() { - removals(|| { - // Call on already-removed account might fail, and this is fine. - Contracts::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()); - true - }); +fn empty_kv_pairs() { + let (wasm, code_hash) = compile_module::("set_empty_storage").unwrap(); + + ExtBuilder::default() + .build() + .execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 30_000, + GAS_LIMIT, + code_hash.into(), + vec![], + )); + let bob_contract = ContractInfoOf::::get(BOB) + .unwrap() + .get_alive() + .unwrap(); + + assert_eq!( + bob_contract.storage_size, + 0, + ); + assert_eq!( + bob_contract.total_pair_count, + 1, + ); + assert_eq!( + bob_contract.empty_pair_count, + 1, + ); + }); +} + +fn initialize_block(number: u64) { + System::initialize( + &number, + &[0u8; 32].into(), + &[0u8; 32].into(), + &Default::default(), + Default::default(), + ); +} + +#[test] +fn deduct_blocks() { + let (wasm, code_hash) = compile_module::("set_rent").unwrap(); + + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + // Create + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 30_000, + GAS_LIMIT, 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 + initialize_block(5); + + // Trigger rent through call + assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, 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 + initialize_block(12); + + // Trigger rent through call + assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, 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!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, 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] +fn call_contract_removals() { + removals(|| { + // Call on already-removed account might fail, and this is fine. + let _ = Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()); + true + }); } #[test] fn inherent_claim_surcharge_contract_removals() { - removals(|| Contracts::claim_surcharge(Origin::NONE, BOB, Some(ALICE)).is_ok()); + removals(|| Contracts::claim_surcharge(Origin::none(), BOB, Some(ALICE)).is_ok()); } #[test] @@ -1045,10 +748,10 @@ fn signed_claim_surcharge_contract_removals() { #[test] fn claim_surcharge_malus() { // Test surcharge malus for inherent - claim_surcharge(4, || Contracts::claim_surcharge(Origin::NONE, BOB, Some(ALICE)).is_ok(), true); - claim_surcharge(3, || Contracts::claim_surcharge(Origin::NONE, BOB, Some(ALICE)).is_ok(), true); - claim_surcharge(2, || Contracts::claim_surcharge(Origin::NONE, BOB, Some(ALICE)).is_ok(), true); - claim_surcharge(1, || Contracts::claim_surcharge(Origin::NONE, BOB, Some(ALICE)).is_ok(), false); + claim_surcharge(4, || Contracts::claim_surcharge(Origin::none(), BOB, Some(ALICE)).is_ok(), true); + claim_surcharge(3, || Contracts::claim_surcharge(Origin::none(), BOB, Some(ALICE)).is_ok(), true); + claim_surcharge(2, || Contracts::claim_surcharge(Origin::none(), BOB, Some(ALICE)).is_ok(), true); + claim_surcharge(1, || Contracts::claim_surcharge(Origin::none(), BOB, Some(ALICE)).is_ok(), false); // Test surcharge malus for signed claim_surcharge(4, || Contracts::claim_surcharge(Origin::signed(ALICE), BOB, None).is_ok(), true); @@ -1060,335 +763,285 @@ fn claim_surcharge_malus() { /// Claim surcharge with the given trigger_call at the given blocks. /// If `removes` is true then assert that the contract is a tombstone. fn claim_surcharge(blocks: u64, trigger_call: impl Fn() -> bool, removes: bool) { - let (wasm, code_hash) = compile_module::(CODE_SET_RENT).unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm)); - assert_ok!(Contracts::instantiate( - Origin::signed(ALICE), - 100, - 100_000, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance - )); - - // Advance blocks - initialize_block(blocks); - - // 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()); - } - }); + let (wasm, code_hash) = compile_module::("set_rent").unwrap(); + + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + // Create + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 100, + GAS_LIMIT, code_hash.into(), + ::Balance::from(1_000u32).encode() // rent allowance + )); + + // Advance blocks + initialize_block(blocks); + + // 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()); + } + }); } /// Test for all kind of removals for the given trigger: /// * if balance is reached and balance > subsistence threshold /// * if allowance is exceeded /// * if balance is reached and balance < subsistence threshold +/// * this case cannot be triggered by a contract: we check whether a tombstone is left fn removals(trigger_call: impl Fn() -> bool) { - let (wasm, code_hash) = compile_module::(CODE_SET_RENT).unwrap(); + let (wasm, code_hash) = compile_module::("set_rent").unwrap(); // Balance reached and superior to subsistence threshold - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm.clone())); - assert_ok!(Contracts::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 - initialize_block(10); - - // 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 - initialize_block(20); - - // 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 + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone())); + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 100, + GAS_LIMIT, 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 + initialize_block(10); + + // 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 + initialize_block(20); + + // 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 - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm.clone())); - assert_ok!(Contracts::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 - initialize_block(10); - - // 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 - initialize_block(20); - - // 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 + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone())); + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 1_000, + GAS_LIMIT, + 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 + initialize_block(10); + + // 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 + initialize_block(20); + + // 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 - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm.clone())); - assert_ok!(Contracts::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!(Contracts::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 - initialize_block(10); - - // Trigger rent through call - assert!(trigger_call()); - assert!(ContractInfoOf::::get(BOB).is_none()); - assert_eq!(Balances::free_balance(BOB), Balances::minimum_balance()); - - // Advance blocks - initialize_block(20); - - // 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 + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + let subsistence_threshold = + Balances::minimum_balance() + ::TombstoneDeposit::get(); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone())); + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 50 + subsistence_threshold, + GAS_LIMIT, + 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 + subsistence_threshold, + ); + + // Transfer funds + assert_ok!(Contracts::call( + Origin::signed(ALICE), + BOB, + 0, + GAS_LIMIT, + call::transfer() + )); + assert_eq!( + ContractInfoOf::::get(BOB) + .unwrap() + .get_alive() + .unwrap() + .rent_allowance, + 1_000 + ); + assert_eq!(Balances::free_balance(BOB), subsistence_threshold); + + // Advance blocks + initialize_block(10); + + // Trigger rent through call + assert!(trigger_call()); + assert_matches!(ContractInfoOf::::get(BOB), Some(ContractInfo::Tombstone(_))); + assert_eq!(Balances::free_balance(BOB), subsistence_threshold); + + // Advance blocks + initialize_block(20); + + // Trigger rent must have no effect + assert!(trigger_call()); + assert_matches!(ContractInfoOf::::get(BOB), Some(ContractInfo::Tombstone(_))); + assert_eq!(Balances::free_balance(BOB), subsistence_threshold); + }); } #[test] fn call_removed_contract() { - let (wasm, code_hash) = compile_module::(CODE_SET_RENT).unwrap(); + let (wasm, code_hash) = compile_module::("set_rent").unwrap(); // Balance reached and superior to subsistence threshold - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm.clone())); - assert_ok!(Contracts::instantiate( - Origin::signed(ALICE), - 100, - 100_000, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance - )); - - // Calling contract should succeed. - assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); - - // Advance blocks - initialize_block(10); - - // Calling contract should remove contract and fail. - assert_err!( - Contracts::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()), - "contract has been evicted" - ); - // Calling a contract that is about to evict shall emit an event. - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Evicted(BOB, true)), - topics: vec![], - }, - ]); - - // Subsequent contract calls should also fail. - assert_err!( - Contracts::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()), - "contract has been evicted" - ); - }) -} + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + // Create + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone())); + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 100, + GAS_LIMIT, code_hash.into(), + ::Balance::from(1_000u32).encode() // rent allowance + )); -const CODE_CHECK_DEFAULT_RENT_ALLOWANCE: &str = r#" -(module - (import "env" "ext_rent_allowance" (func $ext_rent_allowance)) - (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) - ) - ) + // Calling contract should succeed. + assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null())); - (func (export "call")) + // Advance blocks + initialize_block(10); - (func (export "deploy") - ;; fill the scratch buffer with the rent allowance. - (call $ext_rent_allowance) + // Calling contract should remove contract and fail. + assert_err_ignore_postinfo!( + Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()), + "contract has been evicted" + ); + // Calling a contract that is about to evict shall emit an event. + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::Evicted(BOB, true)), + topics: vec![], + }, + ]); - ;; 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 >::max_value(). - (call $assert - (i64.eq - (i64.load - (i32.const 8) - ) - (i64.const 0xFFFFFFFFFFFFFFFF) - ) - ) - ) -) -"#; + // Subsequent contract calls should also fail. + assert_err_ignore_postinfo!( + Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()), + "contract has been evicted" + ); + }) +} #[test] fn default_rent_allowance_on_instantiate() { - let (wasm, code_hash) = compile_module::(CODE_CHECK_DEFAULT_RENT_ALLOWANCE).unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm)); - assert_ok!(Contracts::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 - initialize_block(5); - - // Trigger rent through call - assert_ok!(Contracts::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()) - }); -} + let (wasm, code_hash) = compile_module::("check_default_rent_allowance").unwrap(); -const CODE_RESTORATION: &str = r#" -(module - (import "env" "ext_set_storage" (func $ext_set_storage (param i32 i32 i32))) - (import "env" "ext_restore_to" (func $ext_restore_to (param i32 i32 i32 i32 i32 i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func (export "call") - (call $ext_restore_to - ;; Pointer and length of the encoded dest buffer. - (i32.const 256) - (i32.const 8) - ;; Pointer and length of the encoded code hash buffer - (i32.const 264) - (i32.const 32) - ;; Pointer and length of the encoded rent_allowance buffer - (i32.const 296) - (i32.const 8) - ;; Pointer and number of items in the delta buffer. - ;; This buffer specifies multiple keys for removal before restoration. - (i32.const 100) - (i32.const 1) - ) - ) - (func (export "deploy") - ;; Data to restore - (call $ext_set_storage - (i32.const 0) - (i32.const 0) - (i32.const 4) - ) - - ;; ACL - (call $ext_set_storage - (i32.const 100) - (i32.const 0) - (i32.const 4) - ) - ) - - ;; Data to restore - (data (i32.const 0) "\28") - - ;; Buffer that has ACL storage keys. - (data (i32.const 100) "\01") - - ;; Address of bob - (data (i32.const 256) "\02\00\00\00\00\00\00\00") - - ;; Code hash of SET_RENT - (data (i32.const 264) - "\c2\1c\41\10\a5\22\d8\59\1c\4c\77\35\dd\2d\bf\a1" - "\13\0b\50\93\76\9b\92\31\97\b7\c5\74\26\aa\38\2a" - ) - - ;; Rent allowance - (data (i32.const 296) "\32\00\00\00\00\00\00\00") -) -"#; + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + // Create + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 30_000, + GAS_LIMIT, + 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 + initialize_block(5); + + // Trigger rent through call + assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null())); + + // Check contract is still alive + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive(); + assert!(bob_contract.is_some()) + }); +} #[test] fn restorations_dirty_storage_and_different_storage() { @@ -1411,1472 +1064,544 @@ fn restoration_success() { } fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage: bool) { - let (set_rent_wasm, set_rent_code_hash) = compile_module::(CODE_SET_RENT).unwrap(); - let (restoration_wasm, restoration_code_hash) = - compile_module::(CODE_RESTORATION).unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, restoration_wasm)); - assert_ok!(Contracts::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::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::CodeStored(restoration_code_hash.into())), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(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!(Contracts::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!(Contracts::call( - Origin::signed(ALICE), - BOB, 0, 100_000, - call::set_storage_4_byte()) - ); - } + let (set_rent_wasm, set_rent_code_hash) = compile_module::("set_rent").unwrap(); + let (restoration_wasm, restoration_code_hash) = compile_module::("restoration").unwrap(); - // Advance 4 blocks, to the 5th. - initialize_block(5); - - /// Preserve `BOB`'s code hash for later introspection. - let bob_code_hash = ContractInfoOf::::get(BOB).unwrap() - .get_alive().unwrap().code_hash; - // 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!( - Contracts::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()), - "contract has been evicted" - ); - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts( - RawEvent::Evicted(BOB.clone(), true) - ), - topics: vec![], - }, - ]); - - /// 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!(Contracts::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. - initialize_block(6); - } + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), restoration_wasm)); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), set_rent_wasm)); - // Perform a call to `DJANGO`. This should either perform restoration successfully or - // fail depending on the test parameters. - assert_ok!(Contracts::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()); - match (test_different_storage, test_restore_to_with_dirty_storage) { - (true, false) => { - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts( - RawEvent::Restored(DJANGO, BOB, bob_code_hash, 50, false) - ), - topics: vec![], - }, - ]); - } - (_, true) => { - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Evicted(BOB, true)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(CHARLIE)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(CHARLIE, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(DJANGO)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(DJANGO, 30_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Transfer(CHARLIE, DJANGO, 30_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Instantiated(CHARLIE, DJANGO)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Restored( - DJANGO, - BOB, - bob_code_hash, - 50, - false, - )), - topics: vec![], - }, - ]); - } - _ => unreachable!(), - } - } 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()); + // 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::Initialization, - event: MetaEvent::system(system::RawEvent::KilledAccount(DJANGO)), + event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), topics: vec![], }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::CodeStored(restoration_code_hash.into())), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(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!(Contracts::instantiate( + Origin::signed(ALICE), + 30_000, + GAS_LIMIT, + 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!(Contracts::call( + Origin::signed(ALICE), + BOB, 0, GAS_LIMIT, + call::set_storage_4_byte()) + ); + } + + // Advance 4 blocks, to the 5th. + initialize_block(5); + + // 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_ignore_postinfo!( + Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()), + "contract has been evicted" + ); + assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); + assert_eq!(System::events(), vec![ EventRecord { phase: Phase::Initialization, event: MetaEvent::contracts( - RawEvent::Restored(DJANGO, BOB, bob_contract.code_hash, 50, true) + RawEvent::Evicted(BOB.clone(), true) ), topics: vec![], }, ]); - } - }); -} -const CODE_STORAGE_SIZE: &str = r#" -(module - (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))) - (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 16 16)) - - (func $assert (param i32) - (block $ok - (br_if $ok - (get_local 0) - ) - (unreachable) - ) - ) - - (func (export "call") - ;; assert $ext_scratch_size == 8 - (call $assert - (i32.eq - (call $ext_scratch_size) - (i32.const 4) - ) - ) - - ;; copy contents of the scratch buffer into the contract's memory. - (call $ext_scratch_read - (i32.const 32) ;; Pointer in memory to the place where to copy. - (i32.const 0) ;; Offset from the start of the scratch buffer. - (i32.const 4) ;; Count of bytes to copy. - ) - - ;; place a garbage value in storage, the size of which is specified by the call input. - (call $ext_set_storage - (i32.const 0) ;; Pointer to storage key - (i32.const 0) ;; Pointer to value - (i32.load (i32.const 32)) ;; Size of value - ) - - (call $assert - (i32.eq - (call $ext_get_storage - (i32.const 0) ;; Pointer to storage key - ) - (i32.const 0) - ) - ) + // 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. + let _ = Balances::deposit_creating(&CHARLIE, 1_000_000); + assert_ok!(Contracts::instantiate( + Origin::signed(CHARLIE), + 30_000, + GAS_LIMIT, + restoration_code_hash.into(), + ::Balance::from(0u32).encode() + )); - (call $assert - (i32.eq - (call $ext_scratch_size) - (i32.load (i32.const 32)) - ) - ) - ) + // Before performing a call to `DJANGO` save its original trie id. + let django_trie_id = ContractInfoOf::::get(DJANGO).unwrap() + .get_alive().unwrap().trie_id; - (func (export "deploy")) + if !test_restore_to_with_dirty_storage { + // Advance 1 block, to the 6th. + initialize_block(6); + } - (data (i32.const 0) "\01") ;; Storage key (32 B) -) -"#; + // Perform a call to `DJANGO`. This should either perform restoration successfully or + // fail depending on the test parameters. + let perform_the_restoration = || { + Contracts::call( + Origin::signed(ALICE), + DJANGO, + 0, + GAS_LIMIT, + set_rent_code_hash.as_ref().to_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_err_ignore_postinfo!( + perform_the_restoration(), + "contract trapped during execution" + ); + + 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, 8); + assert_eq!(django_contract.trie_id, django_trie_id); + assert_eq!(django_contract.deduct_block, System::block_number()); + match (test_different_storage, test_restore_to_with_dirty_storage) { + (true, false) => { + assert_eq!(System::events(), vec![]); + } + (_, true) => { + pretty_assertions::assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::Evicted(BOB, true)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::system(frame_system::RawEvent::NewAccount(CHARLIE)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(CHARLIE, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::system(frame_system::RawEvent::NewAccount(DJANGO)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(DJANGO, 30_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::balances( + pallet_balances::RawEvent::Transfer(CHARLIE, DJANGO, 30_000) + ), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::Instantiated(CHARLIE, DJANGO)), + topics: vec![], + }, + ]); + } + _ => unreachable!(), + } + } else { + assert_ok!(perform_the_restoration()); + + // 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, 4); + assert_eq!(bob_contract.trie_id, django_trie_id); + assert_eq!(bob_contract.deduct_block, System::block_number()); + assert!(ContractInfoOf::::get(DJANGO).is_none()); + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::system(system::RawEvent::KilledAccount(DJANGO)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts( + RawEvent::Restored(DJANGO, BOB, bob_contract.code_hash, 50) + ), + topics: vec![], + }, + ]); + } + }); +} #[test] fn storage_max_value_limit() { - let (wasm, code_hash) = compile_module::(CODE_STORAGE_SIZE).unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm)); - assert_ok!(Contracts::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!(Contracts::call( - Origin::signed(ALICE), - BOB, - 0, - 100_000, - Encode::encode(&self::MaxValueSize::get()), - )); - - // Call contract with too large a storage value. - assert_err!( - Contracts::call( + let (wasm, code_hash) = compile_module::("storage_size").unwrap(); + + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + // Create + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 30_000, + GAS_LIMIT, + 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!(Contracts::call( Origin::signed(ALICE), BOB, 0, - 100_000, - Encode::encode(&(self::MaxValueSize::get() + 1)), - ), - "contract trapped during execution" - ); - }); -} - -const CODE_RETURN_WITH_DATA: &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_scratch_write" (func $ext_scratch_write (param i32 i32))) - (import "env" "memory" (memory 1 1)) - - ;; Deploy routine is the same as call. - (func (export "deploy") (result i32) - (call $call) - ) - - ;; Call reads the first 4 bytes (LE) as the exit status and returns the rest as output data. - (func $call (export "call") (result i32) - (local $buf_size i32) - (local $exit_status i32) - - ;; Find out the size of the scratch buffer - (set_local $buf_size (call $ext_scratch_size)) - - ;; Copy scratch buffer into this contract memory. - (call $ext_scratch_read - (i32.const 0) ;; The pointer where to store the scratch buffer contents, - (i32.const 0) ;; Offset from the start of the scratch buffer. - (get_local $buf_size) ;; Count of bytes to copy. - ) - - ;; Copy all but the first 4 bytes of the input data as the output data. - (call $ext_scratch_write - (i32.const 4) ;; Pointer to the data to return. - (i32.sub ;; Count of bytes to copy. - (get_local $buf_size) - (i32.const 4) - ) - ) - - ;; Return the first 4 bytes of the input data as the exit status. - (i32.load (i32.const 0)) - ) -) -"#; - -const CODE_CALLER_CONTRACT: &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" "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)) - - (func $assert (param i32) - (block $ok - (br_if $ok - (get_local 0) - ) - (unreachable) - ) - ) - - (func $current_balance (param $sp i32) (result i64) - (call $ext_balance) - (call $assert - (i32.eq (call $ext_scratch_size) (i32.const 8)) - ) - (call $ext_scratch_read - (i32.sub (get_local $sp) (i32.const 8)) - (i32.const 0) - (i32.const 8) - ) - (i64.load (i32.sub (get_local $sp) (i32.const 8))) - ) - - (func (export "deploy")) - - (func (export "call") - (local $sp i32) - (local $exit_code i32) - (local $balance i64) - - ;; 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 24) ;; 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. - ) - - ;; Read current balance into local variable. - (set_local $sp (i32.const 1024)) - (set_local $balance - (call $current_balance (get_local $sp)) - ) - - ;; Fail to deploy the contract since it returns a non-zero exit status. - (set_local $exit_code - (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. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer. - (i32.const 9) ;; Pointer to input data buffer address - (i32.const 7) ;; Length of input data buffer - ) - ) - - ;; Check non-zero exit status. - (call $assert - (i32.eq (get_local $exit_code) (i32.const 0x11)) - ) - - ;; Check that scratch buffer is empty since contract instantiation failed. - (call $assert - (i32.eq (call $ext_scratch_size) (i32.const 0)) - ) - - ;; Check that balance has not changed. - (call $assert - (i64.eq (get_local $balance) (call $current_balance (get_local $sp))) - ) - - ;; Fail to deploy the contract due to insufficient gas. - (set_local $exit_code - (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. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer. - (i32.const 8) ;; Pointer to input data buffer address - (i32.const 8) ;; Length of input data buffer - ) - ) - - ;; Check for special trap exit status. - (call $assert - (i32.eq (get_local $exit_code) (i32.const 0x0100)) - ) - - ;; Check that scratch buffer is empty since contract instantiation failed. - (call $assert - (i32.eq (call $ext_scratch_size) (i32.const 0)) - ) - - ;; Check that balance has not changed. - (call $assert - (i64.eq (get_local $balance) (call $current_balance (get_local $sp))) - ) - - ;; Deploy the contract successfully. - (set_local $exit_code - (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. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer. - (i32.const 8) ;; Pointer to input data buffer address - (i32.const 8) ;; Length of input data buffer - ) - ) - - ;; Check for success exit status. - (call $assert - (i32.eq (get_local $exit_code) (i32.const 0x00)) - ) - - ;; Check that scratch buffer contains the address of the new contract. - (call $assert - (i32.eq (call $ext_scratch_size) (i32.const 8)) - ) - - ;; Copy contract address from scratch buffer into this contract's memory. - (call $ext_scratch_read - (i32.const 16) ;; 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. - ) - - ;; Check that balance has been deducted. - (set_local $balance - (i64.sub (get_local $balance) (i64.load (i32.const 0))) - ) - (call $assert - (i64.eq (get_local $balance) (call $current_balance (get_local $sp))) - ) - - ;; Call the new contract and expect it to return failing exit code. - (set_local $exit_code - (call $ext_call - (i32.const 16) ;; Pointer to "callee" address. - (i32.const 8) ;; Length of "callee" 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 9) ;; Pointer to input data buffer address - (i32.const 7) ;; Length of input data buffer - ) - ) - - ;; Check non-zero exit status. - (call $assert - (i32.eq (get_local $exit_code) (i32.const 0x11)) - ) - - ;; Check that scratch buffer contains the expected return data. - (call $assert - (i32.eq (call $ext_scratch_size) (i32.const 3)) - ) - (i32.store - (i32.sub (get_local $sp) (i32.const 4)) - (i32.const 0) - ) - (call $ext_scratch_read - (i32.sub (get_local $sp) (i32.const 4)) - (i32.const 0) - (i32.const 3) - ) - (call $assert - (i32.eq - (i32.load (i32.sub (get_local $sp) (i32.const 4))) - (i32.const 0x00776655) - ) - ) - - ;; Check that balance has not changed. - (call $assert - (i64.eq (get_local $balance) (call $current_balance (get_local $sp))) - ) - - ;; Fail to call the contract due to insufficient gas. - (set_local $exit_code - (call $ext_call - (i32.const 16) ;; Pointer to "callee" address. - (i32.const 8) ;; Length of "callee" address. - (i64.const 100) ;; How much gas to devote for the execution. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer. - (i32.const 8) ;; Pointer to input data buffer address - (i32.const 8) ;; Length of input data buffer - ) - ) - - ;; Check for special trap exit status. - (call $assert - (i32.eq (get_local $exit_code) (i32.const 0x0100)) - ) - - ;; Check that scratch buffer is empty since call trapped. - (call $assert - (i32.eq (call $ext_scratch_size) (i32.const 0)) - ) - - ;; Check that balance has not changed. - (call $assert - (i64.eq (get_local $balance) (call $current_balance (get_local $sp))) - ) - - ;; Call the contract successfully. - (set_local $exit_code - (call $ext_call - (i32.const 16) ;; Pointer to "callee" address. - (i32.const 8) ;; Length of "callee" 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 8) ;; Pointer to input data buffer address - (i32.const 8) ;; Length of input data buffer - ) - ) - - ;; Check for success exit status. - (call $assert - (i32.eq (get_local $exit_code) (i32.const 0x00)) - ) - - ;; Check that scratch buffer contains the expected return data. - (call $assert - (i32.eq (call $ext_scratch_size) (i32.const 4)) - ) - (i32.store - (i32.sub (get_local $sp) (i32.const 4)) - (i32.const 0) - ) - (call $ext_scratch_read - (i32.sub (get_local $sp) (i32.const 4)) - (i32.const 0) - (i32.const 4) - ) - (call $assert - (i32.eq - (i32.load (i32.sub (get_local $sp) (i32.const 4))) - (i32.const 0x77665544) - ) - ) - - ;; Check that balance has been deducted. - (set_local $balance - (i64.sub (get_local $balance) (i64.load (i32.const 0))) - ) - (call $assert - (i64.eq (get_local $balance) (call $current_balance (get_local $sp))) - ) - ) - - (data (i32.const 0) "\00\80") ;; The value to transfer on instantiation and calls. - ;; Chosen to be greater than existential deposit. - (data (i32.const 8) "\00\11\22\33\44\55\66\77") ;; The input data to instantiations and calls. -) -"#; + GAS_LIMIT * 2, // we are copying a huge buffer + Encode::encode(&self::MaxValueSize::get()), + )); -#[test] -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(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, callee_wasm)); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, caller_wasm)); - - assert_ok!(Contracts::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!(Contracts::call( - Origin::signed(ALICE), - BOB, - 0, - 200_000, - callee_code_hash.as_ref().to_vec(), - )); - }); + // Call contract with too large a storage value. + assert_err_ignore_postinfo!( + Contracts::call( + Origin::signed(ALICE), + BOB, + 0, + GAS_LIMIT, + Encode::encode(&(self::MaxValueSize::get() + 1)), + ), + "contract trapped during execution" + ); + }); } #[test] -fn deploy_works_without_gas_price() { - let (wasm, code_hash) = compile_module::(CODE_GET_RUNTIME_STORAGE).unwrap(); - ExtBuilder::default().existential_deposit(50).gas_price(0).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm)); - assert_ok!(Contracts::instantiate( - Origin::signed(ALICE), - 100, - 100_000, - code_hash.into(), - vec![], - )); - }); -} - -const CODE_DRAIN: &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) - ) - ) +fn deploy_and_call_other_contract() { + let (callee_wasm, callee_code_hash) = compile_module::("return_with_data").unwrap(); + let (caller_wasm, caller_code_hash) = compile_module::("caller_contract").unwrap(); - (func (export "deploy")) + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + // Create + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), callee_wasm)); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), caller_wasm)); - (func (export "call") - ;; Send entire remaining balance to the 0 address. - (call $ext_balance) + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 100_000, + GAS_LIMIT, + caller_code_hash.into(), + vec![], + )); - ;; 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 scratch 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) - ) - ) - ) -) -"#; + // Call BOB contract, which attempts to instantiate and call the callee contract and + // makes various assertions on the results from those calls. + assert_ok!(Contracts::call( + Origin::signed(ALICE), + BOB, + 0, + GAS_LIMIT, + callee_code_hash.as_ref().to_vec(), + )); + }); +} #[test] fn cannot_self_destruct_through_draning() { - let (wasm, code_hash) = compile_module::(CODE_DRAIN).unwrap(); - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm)); - - // Instantiate the BOB contract. - assert_ok!(Contracts::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(_)) - ); + let (wasm, code_hash) = compile_module::("drain").unwrap(); + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); - // Call BOB with no input data, forcing it to run until out-of-balance - // and eventually trapping because below existential deposit. - assert_err!( - Contracts::call( + // Instantiate the BOB contract. + assert_ok!(Contracts::instantiate( Origin::signed(ALICE), - BOB, - 0, 100_000, + GAS_LIMIT, + code_hash.into(), vec![], - ), - "contract trapped during execution" - ); - }); -} - -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_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32))) - (import "env" "ext_terminate" (func $ext_terminate (param i32 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 scratch buffer - (i32.const 8) ;; Length of encoded address - ) + // Check that the BOB contract has been instantiated. + assert_matches!( + ContractInfoOf::::get(BOB), + Some(ContractInfo::Alive(_)) + ); - ;; Recursively call self with empty input 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) - ) - ) - ) - (else - ;; Try to terminate and give balance to django. - (call $ext_terminate - (i32.const 32) ;; Pointer to beneficiary address - (i32.const 8) ;; Length of beneficiary address - ) - (unreachable) ;; ext_terminate never returns - ) - ) - ) - ;; Address of django - (data (i32.const 32) "\04\00\00\00\00\00\00\00") -) -"#; + // Call BOB with no input data, forcing it to run until out-of-balance + // and eventually trapping because below existential deposit. + assert_err_ignore_postinfo!( + Contracts::call( + Origin::signed(ALICE), + BOB, + 0, + GAS_LIMIT, + vec![], + ), + "contract trapped during execution" + ); + }); +} #[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!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm)); - - // Instantiate the BOB contract. - assert_ok!(Contracts::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(_)) - ); + let (wasm, code_hash) = compile_module::("self_destruct").unwrap(); + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); - // Call BOB with input data, forcing it make a recursive call to itself to - // self-destruct, resulting in a trap. - assert_err!( - Contracts::call( + // Instantiate the BOB contract. + assert_ok!(Contracts::instantiate( Origin::signed(ALICE), - BOB, - 0, 100_000, - vec![0], - ), - "contract trapped during execution" - ); + GAS_LIMIT, + code_hash.into(), + vec![], + )); - // Check that BOB is still alive. - assert_matches!( - ContractInfoOf::::get(BOB), - Some(ContractInfo::Alive(_)) - ); - }); + // 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_ignore_postinfo!( + Contracts::call( + Origin::signed(ALICE), + BOB, + 0, + GAS_LIMIT, + vec![0], + ), + "contract trapped during execution" + ); + + // Check that BOB is still alive. + assert_matches!( + ContractInfoOf::::get(BOB), + Some(ContractInfo::Alive(_)) + ); + }); } #[test] fn self_destruct_works() { - 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!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm)); - - // Instantiate the BOB contract. - assert_ok!(Contracts::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(_)) - ); + let (wasm, code_hash) = compile_module::("self_destruct").unwrap(); + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); - // Call BOB without input data which triggers termination. - assert_matches!( - Contracts::call( + // Instantiate the BOB contract. + assert_ok!(Contracts::instantiate( Origin::signed(ALICE), - BOB, - 0, 100_000, + GAS_LIMIT, + code_hash.into(), vec![], - ), - Ok(()) - ); - - // Check that account is gone - assert!(ContractInfoOf::::get(BOB).is_none()); + )); - // check that the beneficiary (django) got remaining balance - assert_eq!(Balances::free_balance(DJANGO), 100_000); - }); -} + // Check that the BOB contract has been instantiated. + 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))) - (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) - ) - ) + // Call BOB without input data which triggers termination. + assert_matches!( + Contracts::call( + Origin::signed(ALICE), + BOB, + 0, + GAS_LIMIT, + vec![], + ), + Ok(_) + ); - ;; 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 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) - ) - ) - ) + // Check that account is gone + assert!(ContractInfoOf::::get(BOB).is_none()); - (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. -) -"#; + // check that the beneficiary (django) got remaining balance + assert_eq!(Balances::free_balance(DJANGO), 100_000); + }); +} // 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!(Contracts::put_code(Origin::signed(ALICE), 100_000, callee_wasm)); - assert_ok!(Contracts::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!(Contracts::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(_)) - ); + let (callee_wasm, callee_code_hash) = compile_module::("self_destruct").unwrap(); + let (caller_wasm, caller_code_hash) = compile_module::("destroy_and_transfer").unwrap(); - // Call BOB, which calls CHARLIE, forcing CHARLIE to self-destruct. - assert_ok!(Contracts::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 scratch 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")) -) -"#; + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + // Create + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), callee_wasm)); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), caller_wasm)); -#[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!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm)); - - // Fail to instantiate the BOB because the call that is issued in the deploy - // function exhausts all balances which puts it below the existential deposit. - assert_err!( - Contracts::instantiate( + // This deploys the BOB contract, which in turn deploys the CHARLIE contract during + // construction. + assert_ok!(Contracts::instantiate( Origin::signed(ALICE), - 100_000, - 100_000, - code_hash.into(), - vec![], - ), - "contract trapped during execution" - ); - }); -} + 200_000, + GAS_LIMIT, + caller_code_hash.into(), + 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, pays_fee: true }; - let check = CheckBlockGasLimit::(Default::default()); - let call: Call = crate::Call::put_code(1000, vec![]).into(); + // Check that the CHARLIE contract has been instantiated. + assert_matches!( + ContractInfoOf::::get(CHARLIE), + Some(ContractInfo::Alive(_)) + ); - assert_eq!( - check.validate(&0, &call, info, 0), InvalidTransaction::ExhaustsResources.into(), - ); + // Call BOB, which calls CHARLIE, forcing CHARLIE to self-destruct. + assert_ok!(Contracts::call( + Origin::signed(ALICE), + BOB, + 0, + GAS_LIMIT, + CHARLIE.encode(), + )); - let call: Call = crate::Call::update_schedule(Default::default()).into(); - assert_eq!(check.validate(&0, &call, info, 0), Ok(Default::default())); - }); + // Check that CHARLIE has moved on to the great beyond (ie. died). + assert!(ContractInfoOf::::get(CHARLIE).is_none()); + }); } -const CODE_GET_RUNTIME_STORAGE: &str = r#" -(module - (import "env" "ext_get_runtime_storage" - (func $ext_get_runtime_storage (param i32 i32) (result i32)) - ) - (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_scratch_write" (func $ext_scratch_write (param i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func (export "deploy")) - - (func $assert (param i32) - (block $ok - (br_if $ok - (get_local 0) - ) - (unreachable) - ) - ) - - (func $call (export "call") - ;; Load runtime storage for the first key and assert that it exists. - (call $assert - (i32.eq - (call $ext_get_runtime_storage - (i32.const 16) - (i32.const 4) - ) - (i32.const 0) - ) - ) - - ;; assert $ext_scratch_size == 4 - (call $assert - (i32.eq - (call $ext_scratch_size) - (i32.const 4) - ) - ) - - ;; copy contents of the scratch buffer into the contract's memory. - (call $ext_scratch_read - (i32.const 4) ;; Pointer in memory to the place where to copy. - (i32.const 0) ;; Offset from the start of the scratch buffer. - (i32.const 4) ;; Count of bytes to copy. - ) - - ;; assert that contents of the buffer is equal to the i32 value of 0x14144020. - (call $assert - (i32.eq - (i32.load - (i32.const 4) - ) - (i32.const 0x14144020) - ) - ) - - ;; Load the second key and assert that it doesn't exist. - (call $assert - (i32.eq - (call $ext_get_runtime_storage - (i32.const 20) - (i32.const 4) - ) - (i32.const 1) - ) - ) - ) - - ;; The first key, 4 bytes long. - (data (i32.const 16) "\01\02\03\04") - ;; The second key, 4 bytes long. - (data (i32.const 20) "\02\03\04\05") -) -"#; - #[test] -fn get_runtime_storage() { - let (wasm, code_hash) = compile_module::(CODE_GET_RUNTIME_STORAGE).unwrap(); - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); - - frame_support::storage::unhashed::put_raw( - &[1, 2, 3, 4], - 0x14144020u32.to_le_bytes().to_vec().as_ref() - ); +fn cannot_self_destruct_in_constructor() { + let (wasm, code_hash) = compile_module::("self_destructing_constructor").unwrap(); + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm)); - assert_ok!(Contracts::instantiate( - Origin::signed(ALICE), - 100, - 100_000, - code_hash.into(), - vec![], - )); - assert_ok!(Contracts::call( - Origin::signed(ALICE), - BOB, - 0, - 100_000, - vec![], - )); - }); + // Fail to instantiate the BOB because the call that is issued in the deploy + // function exhausts all balances which puts it below the existential deposit. + assert_err_ignore_postinfo!( + Contracts::instantiate( + Origin::signed(ALICE), + 100_000, + GAS_LIMIT, + code_hash.into(), + vec![], + ), + "contract trapped during execution" + ); + }); } -const CODE_CRYPTO_HASHES: &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_scratch_write" (func $ext_scratch_write (param i32 i32))) - - (import "env" "ext_hash_sha2_256" (func $ext_hash_sha2_256 (param i32 i32 i32))) - (import "env" "ext_hash_keccak_256" (func $ext_hash_keccak_256 (param i32 i32 i32))) - (import "env" "ext_hash_blake2_256" (func $ext_hash_blake2_256 (param i32 i32 i32))) - (import "env" "ext_hash_blake2_128" (func $ext_hash_blake2_128 (param i32 i32 i32))) - - (import "env" "memory" (memory 1 1)) - - (type $hash_fn_sig (func (param i32 i32 i32))) - (table 8 funcref) - (elem (i32.const 1) - $ext_hash_sha2_256 - $ext_hash_keccak_256 - $ext_hash_blake2_256 - $ext_hash_blake2_128 - ) - (data (i32.const 1) "20202010201008") ;; Output sizes of the hashes in order in hex. - - ;; Not in use by the tests besides instantiating the contract. - (func (export "deploy")) - - ;; Called by the tests. - ;; - ;; The `call` function expects data in a certain format in the scratch - ;; buffer. - ;; - ;; 1. The first byte encodes an identifier for the crypto hash function - ;; under test. (*) - ;; 2. The rest encodes the input data that is directly fed into the - ;; crypto hash function chosen in 1. - ;; - ;; The `deploy` function then computes the chosen crypto hash function - ;; given the input and puts the result back into the scratch buffer. - ;; After contract execution the test driver then asserts that the returned - ;; values are equal to the expected bytes for the input and chosen hash - ;; function. - ;; - ;; (*) The possible value for the crypto hash identifiers can be found below: - ;; - ;; | value | Algorithm | Bit Width | - ;; |-------|-----------|-----------| - ;; | 0 | SHA2 | 256 | - ;; | 1 | KECCAK | 256 | - ;; | 2 | BLAKE2 | 256 | - ;; | 3 | BLAKE2 | 128 | - ;; --------------------------------- - (func (export "call") (result i32) - (local $chosen_hash_fn i32) - (local $input_ptr i32) - (local $input_len i32) - (local $output_ptr i32) - (local $output_len i32) - (local.set $input_ptr (i32.const 10)) - (call $ext_scratch_read (local.get $input_ptr) (i32.const 0) (call $ext_scratch_size)) - (local.set $chosen_hash_fn (i32.load8_u (local.get $input_ptr))) - (if (i32.gt_u (local.get $chosen_hash_fn) (i32.const 7)) - ;; We check that the chosen hash fn identifier is within bounds: [0,7] - (unreachable) - ) - (local.set $input_ptr (i32.add (local.get $input_ptr) (i32.const 1))) - (local.set $input_len (i32.sub (call $ext_scratch_size) (i32.const 1))) - (local.set $output_ptr (i32.const 100)) - (local.set $output_len (i32.load8_u (local.get $chosen_hash_fn))) - (call_indirect (type $hash_fn_sig) - (local.get $input_ptr) - (local.get $input_len) - (local.get $output_ptr) - (local.get $chosen_hash_fn) ;; Which crypto hash function to execute. - ) - (call $ext_scratch_write - (local.get $output_ptr) ;; Linear memory location of the output buffer. - (local.get $output_len) ;; Number of output buffer bytes. - ) - (i32.const 0) - ) -) -"#; - #[test] fn crypto_hashes() { - let (wasm, code_hash) = compile_module::(&CODE_CRYPTO_HASHES).unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm)); - - // Instantiate the CRYPTO_HASHES contract. - assert_ok!(Contracts::instantiate( - Origin::signed(ALICE), - 100_000, - 100_000, - code_hash.into(), - vec![], - )); - // Perform the call. - let input = b"_DEAD_BEEF"; - use sp_io::hashing::*; - // Wraps a hash function into a more dynamic form usable for testing. - macro_rules! dyn_hash_fn { - ($name:ident) => { - Box::new(|input| $name(input).as_ref().to_vec().into_boxed_slice()) - }; - } - // All hash functions and their associated output byte lengths. - let test_cases: &[(Box Box<[u8]>>, usize)] = &[ - (dyn_hash_fn!(sha2_256), 32), - (dyn_hash_fn!(keccak_256), 32), - (dyn_hash_fn!(blake2_256), 32), - (dyn_hash_fn!(blake2_128), 16), - ]; - // Test the given hash functions for the input: "_DEAD_BEEF" - for (n, (hash_fn, expected_size)) in test_cases.iter().enumerate() { - // We offset data in the contract tables by 1. - let mut params = vec![(n + 1) as u8]; - params.extend_from_slice(input); - let result = >::bare_call( - ALICE, - BOB, - 0, + let (wasm, code_hash) = compile_module::("crypto_hashes").unwrap(); + + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); + + // Instantiate the CRYPTO_HASHES contract. + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), 100_000, - params, - ).unwrap(); - assert_eq!(result.status, 0); - let expected = hash_fn(input.as_ref()); - assert_eq!(&result.data[..*expected_size], &*expected); - } - }) + GAS_LIMIT, + code_hash.into(), + vec![], + )); + // Perform the call. + let input = b"_DEAD_BEEF"; + use sp_io::hashing::*; + // Wraps a hash function into a more dynamic form usable for testing. + macro_rules! dyn_hash_fn { + ($name:ident) => { + Box::new(|input| $name(input).as_ref().to_vec().into_boxed_slice()) + }; + } + // All hash functions and their associated output byte lengths. + let test_cases: &[(Box Box<[u8]>>, usize)] = &[ + (dyn_hash_fn!(sha2_256), 32), + (dyn_hash_fn!(keccak_256), 32), + (dyn_hash_fn!(blake2_256), 32), + (dyn_hash_fn!(blake2_128), 16), + ]; + // Test the given hash functions for the input: "_DEAD_BEEF" + for (n, (hash_fn, expected_size)) in test_cases.iter().enumerate() { + // We offset data in the contract tables by 1. + let mut params = vec![(n + 1) as u8]; + params.extend_from_slice(input); + let result = >::bare_call( + ALICE, + BOB, + 0, + GAS_LIMIT, + params, + ).0.unwrap(); + assert!(result.is_success()); + let expected = hash_fn(input.as_ref()); + assert_eq!(&result.data[..*expected_size], &*expected); + } + }) } diff --git a/frame/contracts/src/wasm/code_cache.rs b/frame/contracts/src/wasm/code_cache.rs index cb942a25892cd1553b381ab8f856329c395e188a..ba7a02356d2826c649afd8ae6dcd5b8bfb62ab27 100644 --- a/frame/contracts/src/wasm/code_cache.rs +++ b/frame/contracts/src/wasm/code_cache.rs @@ -26,49 +26,20 @@ //! this guarantees that every instrumented contract code in cache cannot have the version equal to the current one. //! Thus, before executing a contract it should be reinstrument with new schedule. -use crate::gas::{Gas, GasMeter, Token}; use crate::wasm::{prepare, runtime::Env, PrefabWasmModule}; use crate::{CodeHash, CodeStorage, PristineCode, Schedule, Trait}; use sp_std::prelude::*; -use sp_runtime::traits::{Hash, Bounded}; +use sp_runtime::traits::Hash; use frame_support::StorageMap; -/// Gas metering token that used for charging storing code into the code storage. -/// -/// Specifies the code length in bytes. -#[cfg_attr(test, derive(Debug, PartialEq, Eq))] -#[derive(Copy, Clone)] -pub struct PutCodeToken(u32); - -impl Token for PutCodeToken { - type Metadata = Schedule; - - fn calculate_amount(&self, metadata: &Schedule) -> Gas { - metadata - .put_code_per_byte_cost - .checked_mul(self.0.into()) - .unwrap_or_else(|| Bounded::max_value()) - } -} - /// Put code in the storage. The hash of code is used as a key and is returned /// as a result of this function. /// /// This function instruments the given code and caches it in the storage. pub fn save( original_code: Vec, - gas_meter: &mut GasMeter, schedule: &Schedule, ) -> Result, &'static str> { - // The first time instrumentation is on the user. However, consequent reinstrumentation - // due to the schedule changes is on governance system. - if gas_meter - .charge(schedule, PutCodeToken(original_code.len() as u32)) - .is_out_of_gas() - { - return Err("there is not enough gas for storing the code"); - } - let prefab_module = prepare::prepare_contract::(&original_code, schedule)?; let code_hash = T::Hashing::hash(&original_code); diff --git a/frame/contracts/src/wasm/mod.rs b/frame/contracts/src/wasm/mod.rs index 8911fb72b6130c66fa1cf7d88d6fcc86b062b5dd..500c0f4dcc52035d08f39bb83e167f2fb9d37fe2 100644 --- a/frame/contracts/src/wasm/mod.rs +++ b/frame/contracts/src/wasm/mod.rs @@ -151,17 +151,19 @@ impl<'a, T: Trait> crate::exec::Vm for WasmVm<'a> { mod tests { use super::*; use std::collections::HashMap; - use std::cell::RefCell; use sp_core::H256; - use crate::exec::{Ext, StorageKey, ExecError, ExecReturnValue, STATUS_SUCCESS}; + use crate::exec::{Ext, StorageKey, ExecReturnValue, ReturnFlags}; use crate::gas::{Gas, GasMeter}; use crate::tests::{Test, Call}; use crate::wasm::prepare::prepare_contract; - use crate::CodeHash; + use crate::{CodeHash, BalanceOf}; use wabt; use hex_literal::hex; use assert_matches::assert_matches; use sp_runtime::DispatchError; + use frame_support::weights::Weight; + + const GAS_LIMIT: Gas = 10_000_000_000; #[derive(Debug, PartialEq, Eq)] struct DispatchEntry(Call); @@ -203,22 +205,10 @@ mod tests { instantiates: Vec, terminations: Vec, transfers: Vec, - dispatches: Vec, restores: Vec, // (topics, data) events: Vec<(Vec, Vec)>, next_account_id: u64, - - /// Runtime storage keys works the following way. - /// - /// - If the test code requests a value and it doesn't exist in this storage map then a - /// panic happens. - /// - If the value does exist it is returned and then removed from the map. So a panic - /// happens if the same value is requested for the second time. - /// - /// This behavior is used to prevent mixing up an access to unexpected location and empty - /// cell. - runtime_storage_keys: RefCell, Option>>>, } impl Ext for MockExt { @@ -227,11 +217,8 @@ mod tests { fn get_storage(&self, key: &StorageKey) -> Option> { self.storage.get(key).cloned() } - fn set_storage(&mut self, key: StorageKey, value: Option>) - -> Result<(), &'static str> - { + fn set_storage(&mut self, key: StorageKey, value: Option>) { *self.storage.entry(key).or_insert(Vec::new()) = value.unwrap_or(Vec::new()); - Ok(()) } fn instantiate( &mut self, @@ -239,7 +226,7 @@ mod tests { endowment: u64, gas_meter: &mut GasMeter, data: Vec, - ) -> Result<(u64, ExecReturnValue), ExecError> { + ) -> Result<(u64, ExecReturnValue), DispatchError> { self.instantiates.push(InstantiateEntry { code_hash: code_hash.clone(), endowment, @@ -252,7 +239,7 @@ mod tests { Ok(( address, ExecReturnValue { - status: STATUS_SUCCESS, + flags: ReturnFlags::empty(), data: Vec::new(), }, )) @@ -286,7 +273,7 @@ mod tests { }); // Assume for now that it was just a plain transfer. // TODO: Add tests for different call outcomes. - Ok(ExecReturnValue { status: STATUS_SUCCESS, data: Vec::new() }) + Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() }) } fn terminate( &mut self, @@ -299,22 +286,20 @@ mod tests { }); Ok(()) } - fn note_dispatch_call(&mut self, call: Call) { - self.dispatches.push(DispatchEntry(call)); - } - fn note_restore_to( + fn restore_to( &mut self, dest: u64, code_hash: H256, rent_allowance: u64, delta: Vec, - ) { + ) -> Result<(), &'static str> { self.restores.push(RestoreEntry { dest, code_hash, rent_allowance, delta, }); + Ok(()) } fn caller(&self) -> &u64 { &42 @@ -361,17 +346,8 @@ mod tests { fn max_value_size(&self) -> u32 { 16_384 } - fn get_runtime_storage(&self, key: &[u8]) -> Option> { - let opt_value = self.runtime_storage_keys - .borrow_mut() - .remove(key); - opt_value.unwrap_or_else(|| - panic!( - "{:?} doesn't exist. values that do exist {:?}", - key, - self.runtime_storage_keys - ) - ) + fn get_weight_price(&self, weight: Weight) -> BalanceOf { + BalanceOf::::from(1312_u32).saturating_mul(weight.into()) } } @@ -381,9 +357,7 @@ mod tests { fn get_storage(&self, key: &[u8; 32]) -> Option> { (**self).get_storage(key) } - fn set_storage(&mut self, key: [u8; 32], value: Option>) - -> Result<(), &'static str> - { + fn set_storage(&mut self, key: [u8; 32], value: Option>) { (**self).set_storage(key, value) } fn instantiate( @@ -392,7 +366,7 @@ mod tests { value: u64, gas_meter: &mut GasMeter, input_data: Vec, - ) -> Result<(u64, ExecReturnValue), ExecError> { + ) -> Result<(u64, ExecReturnValue), DispatchError> { (**self).instantiate(code, value, gas_meter, input_data) } fn transfer( @@ -419,17 +393,14 @@ mod tests { ) -> ExecResult { (**self).call(to, value, gas_meter, input_data) } - fn note_dispatch_call(&mut self, call: Call) { - (**self).note_dispatch_call(call) - } - fn note_restore_to( + fn restore_to( &mut self, dest: u64, code_hash: H256, rent_allowance: u64, delta: Vec, - ) { - (**self).note_restore_to( + ) -> Result<(), &'static str> { + (**self).restore_to( dest, code_hash, rent_allowance, @@ -475,8 +446,8 @@ mod tests { fn max_value_size(&self) -> u32 { (**self).max_value_size() } - fn get_runtime_storage(&self, key: &[u8]) -> Option> { - (**self).get_runtime_storage(key) + fn get_weight_price(&self, weight: Weight) -> BalanceOf { + (**self).get_weight_price(weight) } } @@ -513,16 +484,14 @@ mod tests { ;; value_ptr: u32, ;; value_len: u32, ;;) -> u32 - (import "env" "ext_transfer" (func $ext_transfer (param i32 i32 i32 i32) (result i32))) + (import "env" "ext_transfer" (func $ext_transfer (param i32 i32 i32 i32))) (import "env" "memory" (memory 1 1)) (func (export "call") - (drop - (call $ext_transfer - (i32.const 4) ;; Pointer to "account" address. - (i32.const 8) ;; Length of "account" address. - (i32.const 12) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer. - ) + (call $ext_transfer + (i32.const 4) ;; Pointer to "account" address. + (i32.const 8) ;; Length of "account" address. + (i32.const 12) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer. ) ) (func (export "deploy")) @@ -544,7 +513,7 @@ mod tests { CODE_TRANSFER, vec![], &mut mock_ext, - &mut GasMeter::with_limit(50_000, 1), + &mut GasMeter::new(GAS_LIMIT), ).unwrap(); assert_eq!( @@ -553,7 +522,7 @@ mod tests { to: 7, value: 153, data: Vec::new(), - gas_left: 49978, + gas_left: 9989500000, }] ); } @@ -567,9 +536,11 @@ mod tests { ;; value_ptr: u32, ;; value_len: u32, ;; input_data_ptr: u32, - ;; input_data_len: u32 + ;; input_data_len: u32, + ;; output_ptr: u32, + ;; output_len_ptr: u32 ;;) -> u32 - (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32))) + (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32))) (import "env" "memory" (memory 1 1)) (func (export "call") (drop @@ -581,6 +552,8 @@ mod tests { (i32.const 8) ;; Length of the buffer with value to transfer. (i32.const 20) ;; Pointer to input data buffer address (i32.const 4) ;; Length of input data buffer + (i32.const 4294967295) ;; u32 max value is the sentinel value: do not copy output + (i32.const 0) ;; Length is ignored in this case ) ) ) @@ -604,7 +577,7 @@ mod tests { CODE_CALL, vec![], &mut mock_ext, - &mut GasMeter::with_limit(50_000, 1), + &mut GasMeter::new(GAS_LIMIT), ).unwrap(); assert_eq!( @@ -613,7 +586,7 @@ mod tests { to: 9, value: 6, data: vec![1, 2, 3, 4], - gas_left: 49971, + gas_left: 9984500000, }] ); } @@ -628,8 +601,13 @@ mod tests { ;; value_len: u32, ;; input_data_ptr: u32, ;; input_data_len: u32, + ;; input_data_len: u32, + ;; address_ptr: u32, + ;; address_len_ptr: u32, + ;; output_ptr: u32, + ;; output_len_ptr: u32 ;; ) -> u32 - (import "env" "ext_instantiate" (func $ext_instantiate (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 i32 i32 i32 i32) (result i32))) (import "env" "memory" (memory 1 1)) (func (export "call") (drop @@ -641,6 +619,10 @@ mod tests { (i32.const 8) ;; Length of the buffer with value to transfer (i32.const 12) ;; Pointer to input data buffer address (i32.const 4) ;; Length of input data buffer + (i32.const 4294967295) ;; u32 max value is the sentinel value: do not copy address + (i32.const 0) ;; Length is ignored in this case + (i32.const 4294967295) ;; u32 max value is the sentinel value: do not copy output + (i32.const 0) ;; Length is ignored in this case ) ) ) @@ -666,7 +648,7 @@ mod tests { CODE_INSTANTIATE, vec![], &mut mock_ext, - &mut GasMeter::with_limit(50_000, 1), + &mut GasMeter::new(GAS_LIMIT), ).unwrap(); assert_eq!( @@ -675,7 +657,7 @@ mod tests { code_hash: [0x11; 32].into(), endowment: 3, data: vec![1, 2, 3, 4], - gas_left: 49947, + gas_left: 9971500000, }] ); } @@ -709,14 +691,14 @@ mod tests { CODE_TERMINATE, vec![], &mut mock_ext, - &mut GasMeter::with_limit(50_000, 1), + &mut GasMeter::new(GAS_LIMIT), ).unwrap(); assert_eq!( &mock_ext.terminations, &[TerminationEntry { beneficiary: 0x09, - gas_left: 49989, + gas_left: 9994500000, }] ); } @@ -730,9 +712,11 @@ mod tests { ;; value_ptr: u32, ;; value_len: u32, ;; input_data_ptr: u32, - ;; input_data_len: u32 + ;; input_data_len: u32, + ;; output_ptr: u32, + ;; output_len_ptr: u32 ;;) -> u32 - (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32))) + (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32))) (import "env" "memory" (memory 1 1)) (func (export "call") (drop @@ -744,6 +728,8 @@ mod tests { (i32.const 8) ;; Length of the buffer with value to transfer. (i32.const 20) ;; Pointer to input data buffer address (i32.const 4) ;; Length of input data buffer + (i32.const 4294967295) ;; u32 max value is the sentinel value: do not copy output + (i32.const 0) ;; Length is ignored in this cas ) ) ) @@ -767,7 +753,7 @@ mod tests { &CODE_TRANSFER_LIMITED_GAS, vec![], &mut mock_ext, - &mut GasMeter::with_limit(50_000, 1), + &mut GasMeter::new(GAS_LIMIT), ).unwrap(); assert_eq!( @@ -783,12 +769,21 @@ mod tests { const CODE_GET_STORAGE: &str = r#" (module - (import "env" "ext_get_storage" (func $ext_get_storage (param i32) (result i32))) - (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_return" (func $ext_return (param i32 i32))) + (import "env" "ext_get_storage" (func $ext_get_storage (param i32 i32 i32) (result i32))) + (import "env" "ext_return" (func $ext_return (param i32 i32 i32))) (import "env" "memory" (memory 1 1)) + ;; [0, 32) key for get storage + (data (i32.const 0) + "\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11" + "\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11" + ) + + ;; [32, 36) buffer size = 128 bytes + (data (i32.const 32) "\80") + + ;; [36; inf) buffer where the result is copied + (func $assert (param i32) (block $ok (br_if $ok @@ -801,12 +796,13 @@ mod tests { (func (export "call") (local $buf_size i32) - - ;; Load a storage value into the scratch buf. + ;; Load a storage value into contract memory. (call $assert (i32.eq (call $ext_get_storage - (i32.const 4) ;; The pointer to the storage key to fetch + (i32.const 0) ;; The pointer to the storage key to fetch + (i32.const 36) ;; Pointer to the output buffer + (i32.const 32) ;; Pointer to the size of the buffer ) ;; Return value 0 means that the value is found and there were @@ -815,23 +811,14 @@ mod tests { ) ) - ;; Find out the size of the scratch buffer + ;; Find out the size of the buffer (set_local $buf_size - (call $ext_scratch_size) - ) - - ;; Copy scratch buffer into this contract memory. - (call $ext_scratch_read - (i32.const 36) ;; The pointer where to store the scratch buffer contents, - ;; 36 = 4 + 32 - (i32.const 0) ;; Offset from the start of the scratch buffer. - (get_local ;; Count of bytes to copy. - $buf_size - ) + (i32.load (i32.const 32)) ) ;; Return the contents of the buffer (call $ext_return + (i32.const 0) (i32.const 36) (get_local $buf_size) ) @@ -841,16 +828,11 @@ mod tests { ) (func (export "deploy")) - - (data (i32.const 4) - "\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11" - "\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11" - ) ) "#; #[test] - fn get_storage_puts_data_into_scratch_buf() { + fn get_storage_puts_data_into_buf() { let mut mock_ext = MockExt::default(); mock_ext .storage @@ -860,21 +842,21 @@ mod tests { CODE_GET_STORAGE, vec![], mock_ext, - &mut GasMeter::with_limit(50_000, 1), + &mut GasMeter::new(GAS_LIMIT), ).unwrap(); - assert_eq!(output, ExecReturnValue { status: STATUS_SUCCESS, data: [0x22; 32].to_vec() }); + assert_eq!(output, ExecReturnValue { flags: ReturnFlags::empty(), data: [0x22; 32].to_vec() }); } - /// calls `ext_caller`, loads the address from the scratch buffer and - /// compares it with the constant 42. + /// calls `ext_caller` and compares the result with the constant 42. const CODE_CALLER: &str = r#" (module - (import "env" "ext_caller" (func $ext_caller)) - (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_caller" (func $ext_caller (param i32 i32))) (import "env" "memory" (memory 1 1)) + ;; size of our buffer is 32 bytes + (data (i32.const 32) "\20") + (func $assert (param i32) (block $ok (br_if $ok @@ -885,30 +867,21 @@ mod tests { ) (func (export "call") - ;; fill the scratch buffer with the caller. - (call $ext_caller) + ;; fill the buffer with the caller. + (call $ext_caller (i32.const 0) (i32.const 32)) - ;; assert $ext_scratch_size == 8 + ;; assert len == 8 (call $assert (i32.eq - (call $ext_scratch_size) + (i32.load (i32.const 32)) (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 42. (call $assert (i64.eq - (i64.load - (i32.const 8) - ) + (i64.load (i32.const 0)) (i64.const 42) ) ) @@ -924,19 +897,19 @@ mod tests { CODE_CALLER, vec![], MockExt::default(), - &mut GasMeter::with_limit(50_000, 1), + &mut GasMeter::new(GAS_LIMIT), ).unwrap(); } - /// calls `ext_address`, loads the address from the scratch buffer and - /// compares it with the constant 69. + /// calls `ext_address` and compares the result with the constant 69. const CODE_ADDRESS: &str = r#" (module - (import "env" "ext_address" (func $ext_address)) - (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 (param i32 i32))) (import "env" "memory" (memory 1 1)) + ;; size of our buffer is 32 bytes + (data (i32.const 32) "\20") + (func $assert (param i32) (block $ok (br_if $ok @@ -947,30 +920,21 @@ mod tests { ) (func (export "call") - ;; fill the scratch buffer with the self address. - (call $ext_address) + ;; fill the buffer with the self address. + (call $ext_address (i32.const 0) (i32.const 32)) - ;; assert $ext_scratch_size == 8 + ;; assert size == 8 (call $assert (i32.eq - (call $ext_scratch_size) + (i32.load (i32.const 32)) (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 69. (call $assert (i64.eq - (i64.load - (i32.const 8) - ) + (i64.load (i32.const 0)) (i64.const 69) ) ) @@ -986,17 +950,18 @@ mod tests { CODE_ADDRESS, vec![], MockExt::default(), - &mut GasMeter::with_limit(50_000, 1), + &mut GasMeter::new(GAS_LIMIT), ).unwrap(); } const CODE_BALANCE: &str = r#" (module - (import "env" "ext_balance" (func $ext_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" "ext_balance" (func $ext_balance (param i32 i32))) (import "env" "memory" (memory 1 1)) + ;; size of our buffer is 32 bytes + (data (i32.const 32) "\20") + (func $assert (param i32) (block $ok (br_if $ok @@ -1007,30 +972,21 @@ mod tests { ) (func (export "call") - ;; This stores the balance in the scratch buffer - (call $ext_balance) + ;; This stores the balance in the buffer + (call $ext_balance (i32.const 0) (i32.const 32)) - ;; assert $ext_scratch_size == 8 + ;; assert len == 8 (call $assert (i32.eq - (call $ext_scratch_size) + (i32.load (i32.const 32)) (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 228. (call $assert (i64.eq - (i64.load - (i32.const 8) - ) + (i64.load (i32.const 0)) (i64.const 228) ) ) @@ -1041,7 +997,7 @@ mod tests { #[test] fn balance() { - let mut gas_meter = GasMeter::with_limit(50_000, 1); + let mut gas_meter = GasMeter::new(GAS_LIMIT); let _ = execute( CODE_BALANCE, vec![], @@ -1052,11 +1008,12 @@ mod tests { const CODE_GAS_PRICE: &str = r#" (module - (import "env" "ext_gas_price" (func $ext_gas_price)) - (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_weight_to_fee" (func $ext_weight_to_fee (param i64 i32 i32))) (import "env" "memory" (memory 1 1)) + ;; size of our buffer is 32 bytes + (data (i32.const 32) "\20") + (func $assert (param i32) (block $ok (br_if $ok @@ -1067,31 +1024,22 @@ mod tests { ) (func (export "call") - ;; This stores the gas price in the scratch buffer - (call $ext_gas_price) + ;; This stores the gas price in the buffer + (call $ext_weight_to_fee (i64.const 2) (i32.const 0) (i32.const 32)) - ;; assert $ext_scratch_size == 8 + ;; assert len == 8 (call $assert (i32.eq - (call $ext_scratch_size) + (i32.load (i32.const 32)) (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 1312. + ;; assert that contents of the buffer is equal to the i64 value of 2 * 1312. (call $assert (i64.eq - (i64.load - (i32.const 8) - ) - (i64.const 1312) + (i64.load (i32.const 0)) + (i64.const 2624) ) ) ) @@ -1101,7 +1049,7 @@ mod tests { #[test] fn gas_price() { - let mut gas_meter = GasMeter::with_limit(50_000, 1312); + let mut gas_meter = GasMeter::new(GAS_LIMIT); let _ = execute( CODE_GAS_PRICE, vec![], @@ -1112,12 +1060,13 @@ mod tests { const CODE_GAS_LEFT: &str = r#" (module - (import "env" "ext_gas_left" (func $ext_gas_left)) - (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_return" (func $ext_return (param i32 i32))) + (import "env" "ext_gas_left" (func $ext_gas_left (param i32 i32))) + (import "env" "ext_return" (func $ext_return (param i32 i32 i32))) (import "env" "memory" (memory 1 1)) + ;; size of our buffer is 32 bytes + (data (i32.const 32) "\20") + (func $assert (param i32) (block $ok (br_if $ok @@ -1128,28 +1077,19 @@ mod tests { ) (func (export "call") - ;; This stores the gas left in the scratch buffer - (call $ext_gas_left) + ;; This stores the gas left in the buffer + (call $ext_gas_left (i32.const 0) (i32.const 32)) - ;; assert $ext_scratch_size == 8 + ;; assert len == 8 (call $assert (i32.eq - (call $ext_scratch_size) + (i32.load (i32.const 32)) (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. - ) - - (call $ext_return - (i32.const 8) - (i32.const 8) - ) + ;; return gas left + (call $ext_return (i32.const 0) (i32.const 0) (i32.const 8)) (unreachable) ) @@ -1159,7 +1099,7 @@ mod tests { #[test] fn gas_left() { - let mut gas_meter = GasMeter::with_limit(50_000, 1312); + let mut gas_meter = GasMeter::new(GAS_LIMIT); let output = execute( CODE_GAS_LEFT, @@ -1169,17 +1109,18 @@ mod tests { ).unwrap(); let gas_left = Gas::decode(&mut output.data.as_slice()).unwrap(); - assert!(gas_left < 50_000, "gas_left must be less than initial"); + assert!(gas_left < GAS_LIMIT, "gas_left must be less than initial"); assert!(gas_left > gas_meter.gas_left(), "gas_left must be greater than final"); } const CODE_VALUE_TRANSFERRED: &str = r#" (module - (import "env" "ext_value_transferred" (func $ext_value_transferred)) - (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_value_transferred" (func $ext_value_transferred (param i32 i32))) (import "env" "memory" (memory 1 1)) + ;; size of our buffer is 32 bytes + (data (i32.const 32) "\20") + (func $assert (param i32) (block $ok (br_if $ok @@ -1190,30 +1131,21 @@ mod tests { ) (func (export "call") - ;; This stores the value transferred in the scratch buffer - (call $ext_value_transferred) + ;; This stores the value transferred in the buffer + (call $ext_value_transferred (i32.const 0) (i32.const 32)) - ;; assert $ext_scratch_size == 8 + ;; assert len == 8 (call $assert (i32.eq - (call $ext_scratch_size) + (i32.load (i32.const 32)) (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 1337. (call $assert (i64.eq - (i64.load - (i32.const 8) - ) + (i64.load (i32.const 0)) (i64.const 1337) ) ) @@ -1224,7 +1156,7 @@ mod tests { #[test] fn value_transferred() { - let mut gas_meter = GasMeter::with_limit(50_000, 1); + let mut gas_meter = GasMeter::new(GAS_LIMIT); let _ = execute( CODE_VALUE_TRANSFERRED, vec![], @@ -1233,52 +1165,15 @@ mod tests { ).unwrap(); } - const CODE_DISPATCH_CALL: &str = r#" -(module - (import "env" "ext_dispatch_call" (func $ext_dispatch_call (param i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func (export "call") - (call $ext_dispatch_call - (i32.const 8) ;; Pointer to the start of encoded call buffer - (i32.const 13) ;; Length of the buffer - ) - ) - (func (export "deploy")) - - (data (i32.const 8) "\00\01\2A\00\00\00\00\00\00\00\E5\14\00") -) -"#; - - #[test] - fn dispatch_call() { - // This test can fail due to the encoding changes. In case it becomes too annoying - // let's rewrite so as we use this module controlled call or we serialize it in runtime. - - let mut mock_ext = MockExt::default(); - let _ = execute( - CODE_DISPATCH_CALL, - vec![], - &mut mock_ext, - &mut GasMeter::with_limit(50_000, 1), - ).unwrap(); - - assert_eq!( - &mock_ext.dispatches, - &[DispatchEntry( - Call::Balances(pallet_balances::Call::set_balance(42, 1337, 0)), - )] - ); - } - const CODE_RETURN_FROM_START_FN: &str = r#" (module - (import "env" "ext_return" (func $ext_return (param i32 i32))) + (import "env" "ext_return" (func $ext_return (param i32 i32 i32))) (import "env" "memory" (memory 1 1)) (start $start) (func $start (call $ext_return + (i32.const 0) (i32.const 8) (i32.const 4) ) @@ -1300,19 +1195,20 @@ mod tests { CODE_RETURN_FROM_START_FN, vec![], MockExt::default(), - &mut GasMeter::with_limit(50_000, 1), + &mut GasMeter::new(GAS_LIMIT), ).unwrap(); - assert_eq!(output, ExecReturnValue { status: STATUS_SUCCESS, data: vec![1, 2, 3, 4] }); + assert_eq!(output, ExecReturnValue { flags: ReturnFlags::empty(), data: vec![1, 2, 3, 4] }); } const CODE_TIMESTAMP_NOW: &str = r#" (module - (import "env" "ext_now" (func $ext_now)) - (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_now" (func $ext_now (param i32 i32))) (import "env" "memory" (memory 1 1)) + ;; size of our buffer is 32 bytes + (data (i32.const 32) "\20") + (func $assert (param i32) (block $ok (br_if $ok @@ -1323,30 +1219,21 @@ mod tests { ) (func (export "call") - ;; This stores the block timestamp in the scratch buffer - (call $ext_now) + ;; This stores the block timestamp in the buffer + (call $ext_now (i32.const 0) (i32.const 32)) - ;; assert $ext_scratch_size == 8 + ;; assert len == 8 (call $assert (i32.eq - (call $ext_scratch_size) + (i32.load (i32.const 32)) (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 1111. (call $assert (i64.eq - (i64.load - (i32.const 8) - ) + (i64.load (i32.const 0)) (i64.const 1111) ) ) @@ -1357,7 +1244,7 @@ mod tests { #[test] fn now() { - let mut gas_meter = GasMeter::with_limit(50_000, 1); + let mut gas_meter = GasMeter::new(GAS_LIMIT); let _ = execute( CODE_TIMESTAMP_NOW, vec![], @@ -1368,11 +1255,12 @@ mod tests { 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" "ext_minimum_balance" (func $ext_minimum_balance (param i32 i32))) (import "env" "memory" (memory 1 1)) + ;; size of our buffer is 32 bytes + (data (i32.const 32) "\20") + (func $assert (param i32) (block $ok (br_if $ok @@ -1383,29 +1271,20 @@ mod tests { ) (func (export "call") - (call $ext_minimum_balance) + (call $ext_minimum_balance (i32.const 0) (i32.const 32)) - ;; assert $ext_scratch_size == 8 + ;; assert len == 8 (call $assert (i32.eq - (call $ext_scratch_size) + (i32.load (i32.const 32)) (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.load (i32.const 0)) (i64.const 666) ) ) @@ -1416,7 +1295,7 @@ mod tests { #[test] fn minimum_balance() { - let mut gas_meter = GasMeter::with_limit(50_000, 1); + let mut gas_meter = GasMeter::new(GAS_LIMIT); let _ = execute( CODE_MINIMUM_BALANCE, vec![], @@ -1427,11 +1306,12 @@ mod tests { const CODE_TOMBSTONE_DEPOSIT: &str = r#" (module - (import "env" "ext_tombstone_deposit" (func $ext_tombstone_deposit)) - (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_tombstone_deposit" (func $ext_tombstone_deposit (param i32 i32))) (import "env" "memory" (memory 1 1)) + ;; size of our buffer is 32 bytes + (data (i32.const 32) "\20") + (func $assert (param i32) (block $ok (br_if $ok @@ -1442,29 +1322,20 @@ mod tests { ) (func (export "call") - (call $ext_tombstone_deposit) + (call $ext_tombstone_deposit (i32.const 0) (i32.const 32)) - ;; assert $ext_scratch_size == 8 + ;; assert len == 8 (call $assert (i32.eq - (call $ext_scratch_size) + (i32.load (i32.const 32)) (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 16. (call $assert (i64.eq - (i64.load - (i32.const 8) - ) + (i64.load (i32.const 0)) (i64.const 16) ) ) @@ -1475,7 +1346,7 @@ mod tests { #[test] fn tombstone_deposit() { - let mut gas_meter = GasMeter::with_limit(50_000, 1); + let mut gas_meter = GasMeter::new(GAS_LIMIT); let _ = execute( CODE_TOMBSTONE_DEPOSIT, vec![], @@ -1486,12 +1357,21 @@ mod tests { const CODE_RANDOM: &str = r#" (module - (import "env" "ext_random" (func $ext_random (param i32 i32))) - (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_return" (func $ext_return (param i32 i32))) + (import "env" "ext_random" (func $ext_random (param i32 i32 i32 i32))) + (import "env" "ext_return" (func $ext_return (param i32 i32 i32))) (import "env" "memory" (memory 1 1)) + ;; [0,128) is reserved for the result of PRNG. + + ;; the subject used for the PRNG. [128,160) + (data (i32.const 128) + "\00\01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F" + "\00\01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F" + ) + + ;; size of our buffer is 128 bytes + (data (i32.const 160) "\80") + (func $assert (param i32) (block $ok (br_if $ok @@ -1502,48 +1382,36 @@ mod tests { ) (func (export "call") - ;; This stores the block random seed in the scratch buffer + ;; This stores the block random seed in the buffer (call $ext_random - (i32.const 40) ;; Pointer in memory to the start of the subject buffer + (i32.const 128) ;; Pointer in memory to the start of the subject buffer (i32.const 32) ;; The subject buffer's length + (i32.const 0) ;; Pointer to the output buffer + (i32.const 160) ;; Pointer to the output buffer length ) - ;; assert $ext_scratch_size == 32 + ;; assert len == 32 (call $assert (i32.eq - (call $ext_scratch_size) + (i32.load (i32.const 160)) (i32.const 32) ) ) - ;; 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 32) ;; Count of bytes to copy. - ) - - ;; return the data from the contract + ;; return the random data (call $ext_return - (i32.const 8) + (i32.const 0) + (i32.const 0) (i32.const 32) ) ) (func (export "deploy")) - - ;; [8,40) is reserved for the result of PRNG. - - ;; the subject used for the PRNG. [40,72) - (data (i32.const 40) - "\00\01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F" - "\00\01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F" - ) ) "#; #[test] fn random() { - let mut gas_meter = GasMeter::with_limit(50_000, 1); + let mut gas_meter = GasMeter::new(GAS_LIMIT); let output = execute( CODE_RANDOM, @@ -1556,7 +1424,7 @@ mod tests { assert_eq!( output, ExecReturnValue { - status: STATUS_SUCCESS, + flags: ReturnFlags::empty(), data: hex!("000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F").to_vec(), }, ); @@ -1588,7 +1456,7 @@ mod tests { #[test] fn deposit_event() { let mut mock_ext = MockExt::default(); - let mut gas_meter = GasMeter::with_limit(50_000, 1); + let mut gas_meter = GasMeter::new(GAS_LIMIT); let _ = execute( CODE_DEPOSIT_EVENT, vec![], @@ -1601,7 +1469,7 @@ mod tests { vec![0x00, 0x01, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x14, 0x00]) ]); - assert_eq!(gas_meter.gas_left(), 49934); + assert_eq!(gas_meter.gas_left(), 9967000000); } const CODE_DEPOSIT_EVENT_MAX_TOPICS: &str = r#" @@ -1634,7 +1502,7 @@ mod tests { #[test] fn deposit_event_max_topics() { // Checks that the runtime traps if there are more than `max_topic_events` topics. - let mut gas_meter = GasMeter::with_limit(50_000, 1); + let mut gas_meter = GasMeter::new(GAS_LIMIT); assert_matches!( execute( @@ -1643,9 +1511,7 @@ mod tests { MockExt::default(), &mut gas_meter ), - Err(ExecError { - reason: DispatchError::Other("contract trapped during execution"), buffer: _ - }) + Err(DispatchError::Other("contract trapped during execution")) ); } @@ -1678,7 +1544,7 @@ mod tests { #[test] fn deposit_event_duplicates() { // Checks that the runtime traps if there are duplicates. - let mut gas_meter = GasMeter::with_limit(50_000, 1); + let mut gas_meter = GasMeter::new(GAS_LIMIT); assert_matches!( execute( @@ -1687,19 +1553,19 @@ mod tests { MockExt::default(), &mut gas_meter ), - Err(ExecError { reason: DispatchError::Other("contract trapped during execution"), buffer: _ }) + Err(DispatchError::Other("contract trapped during execution")) ); } - /// calls `ext_block_number`, loads the current block number from the scratch buffer and - /// compares it with the constant 121. + /// calls `ext_block_number` compares the result with the constant 121. const CODE_BLOCK_NUMBER: &str = r#" (module - (import "env" "ext_block_number" (func $ext_block_number)) - (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_block_number" (func $ext_block_number (param i32 i32))) (import "env" "memory" (memory 1 1)) + ;; size of our buffer is 32 bytes + (data (i32.const 32) "\20") + (func $assert (param i32) (block $ok (br_if $ok @@ -1710,30 +1576,21 @@ mod tests { ) (func (export "call") - ;; This stores the block height in the scratch buffer - (call $ext_block_number) + ;; This stores the block height in the buffer + (call $ext_block_number (i32.const 0) (i32.const 32)) - ;; assert $ext_scratch_size == 8 + ;; assert len == 8 (call $assert (i32.eq - (call $ext_scratch_size) + (i32.load (i32.const 32)) (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 121. (call $assert (i64.eq - (i64.load - (i32.const 8) - ) + (i64.load (i32.const 0)) (i64.const 121) ) ) @@ -1749,232 +1606,65 @@ mod tests { CODE_BLOCK_NUMBER, vec![], MockExt::default(), - &mut GasMeter::with_limit(50_000, 1), + &mut GasMeter::new(GAS_LIMIT), ).unwrap(); } - // asserts that the size of the input data is 4. - const CODE_SIMPLE_ASSERT: &str = r#" -(module - (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) - - (func $assert (param i32) - (block $ok - (br_if $ok - (get_local 0) - ) - (unreachable) - ) - ) - - (func (export "deploy")) - - (func (export "call") - (call $assert - (i32.eq - (call $ext_scratch_size) - (i32.const 4) - ) - ) - ) -) -"#; - - #[test] - fn output_buffer_capacity_preserved_on_success() { - let mut input_data = Vec::with_capacity(1_234); - input_data.extend_from_slice(&[1, 2, 3, 4][..]); - - let output = execute( - CODE_SIMPLE_ASSERT, - input_data, - MockExt::default(), - &mut GasMeter::with_limit(50_000, 1), - ).unwrap(); - - assert_eq!(output.data.len(), 0); - assert_eq!(output.data.capacity(), 1_234); - } - - #[test] - fn output_buffer_capacity_preserved_on_failure() { - let mut input_data = Vec::with_capacity(1_234); - input_data.extend_from_slice(&[1, 2, 3, 4, 5][..]); - - let error = execute( - CODE_SIMPLE_ASSERT, - input_data, - MockExt::default(), - &mut GasMeter::with_limit(50_000, 1), - ).err().unwrap(); - - assert_eq!(error.buffer.capacity(), 1_234); - } - const CODE_RETURN_WITH_DATA: &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_scratch_write" (func $ext_scratch_write (param i32 i32))) + (import "env" "ext_input" (func $ext_input (param i32 i32))) + (import "env" "ext_return" (func $ext_return (param i32 i32 i32))) (import "env" "memory" (memory 1 1)) + (data (i32.const 32) "\20") + ;; Deploy routine is the same as call. - (func (export "deploy") (result i32) + (func (export "deploy") (call $call) ) ;; Call reads the first 4 bytes (LE) as the exit status and returns the rest as output data. - (func $call (export "call") (result i32) - (local $buf_size i32) - (local $exit_status i32) - - ;; Find out the size of the scratch buffer - (set_local $buf_size (call $ext_scratch_size)) - - ;; Copy scratch buffer into this contract memory. - (call $ext_scratch_read - (i32.const 0) ;; The pointer where to store the scratch buffer contents, - (i32.const 0) ;; Offset from the start of the scratch buffer. - (get_local $buf_size) ;; Count of bytes to copy. + (func $call (export "call") + ;; Copy input data this contract memory. + (call $ext_input + (i32.const 0) ;; Pointer where to store input + (i32.const 32) ;; Pointer to the length of the buffer ) ;; 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.sub ;; Count of bytes to copy. - (get_local $buf_size) - (i32.const 4) - ) + (call $ext_return + (i32.load (i32.const 0)) + (i32.const 4) + (i32.sub (i32.load (i32.const 32)) (i32.const 4)) ) - - ;; Return the first 4 bytes of the input data as the exit status. - (i32.load (i32.const 0)) + (unreachable) ) ) "#; #[test] - fn return_with_success_status() { + fn ext_return_with_success_status() { let output = execute( CODE_RETURN_WITH_DATA, - hex!("00112233445566778899").to_vec(), + hex!("00000000445566778899").to_vec(), MockExt::default(), - &mut GasMeter::with_limit(50_000, 1), + &mut GasMeter::new(GAS_LIMIT), ).unwrap(); - assert_eq!(output, ExecReturnValue { status: 0, data: hex!("445566778899").to_vec() }); + assert_eq!(output, ExecReturnValue { flags: ReturnFlags::empty(), data: hex!("445566778899").to_vec() }); assert!(output.is_success()); } #[test] - fn return_with_failure_status() { + fn return_with_revert_status() { let output = execute( CODE_RETURN_WITH_DATA, - hex!("112233445566778899").to_vec(), + hex!("010000005566778899").to_vec(), MockExt::default(), - &mut GasMeter::with_limit(50_000, 1), + &mut GasMeter::new(GAS_LIMIT), ).unwrap(); - assert_eq!(output, ExecReturnValue { status: 17, data: hex!("5566778899").to_vec() }); + assert_eq!(output, ExecReturnValue { flags: ReturnFlags::REVERT, data: hex!("5566778899").to_vec() }); assert!(!output.is_success()); } - - const CODE_GET_RUNTIME_STORAGE: &str = r#" -(module - (import "env" "ext_get_runtime_storage" - (func $ext_get_runtime_storage (param i32 i32) (result i32)) - ) - (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_scratch_write" (func $ext_scratch_write (param i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func (export "deploy")) - - (func $assert (param i32) - (block $ok - (br_if $ok - (get_local 0) - ) - (unreachable) - ) - ) - - (func $call (export "call") - ;; Load runtime storage for the first key and assert that it exists. - (call $assert - (i32.eq - (call $ext_get_runtime_storage - (i32.const 16) - (i32.const 4) - ) - (i32.const 0) - ) - ) - - ;; assert $ext_scratch_size == 4 - (call $assert - (i32.eq - (call $ext_scratch_size) - (i32.const 4) - ) - ) - - ;; copy contents of the scratch buffer into the contract's memory. - (call $ext_scratch_read - (i32.const 4) ;; Pointer in memory to the place where to copy. - (i32.const 0) ;; Offset from the start of the scratch buffer. - (i32.const 4) ;; Count of bytes to copy. - ) - - ;; assert that contents of the buffer is equal to the i32 value of 0x14144020. - (call $assert - (i32.eq - (i32.load - (i32.const 4) - ) - (i32.const 0x14144020) - ) - ) - - ;; Load the second key and assert that it doesn't exist. - (call $assert - (i32.eq - (call $ext_get_runtime_storage - (i32.const 20) - (i32.const 4) - ) - (i32.const 1) - ) - ) - ) - - ;; The first key, 4 bytes long. - (data (i32.const 16) "\01\02\03\04") - ;; The second key, 4 bytes long. - (data (i32.const 20) "\02\03\04\05") -) -"#; - - #[test] - fn get_runtime_storage() { - let mut gas_meter = GasMeter::with_limit(50_000, 1); - let mock_ext = MockExt::default(); - - // "\01\02\03\04" - Some(0x14144020) - // "\02\03\04\05" - None - *mock_ext.runtime_storage_keys.borrow_mut() = [ - ([1, 2, 3, 4].to_vec(), Some(0x14144020u32.to_le_bytes().to_vec())), - ([2, 3, 4, 5].to_vec().to_vec(), None), - ] - .iter() - .cloned() - .collect(); - let _ = execute( - CODE_GET_RUNTIME_STORAGE, - vec![], - mock_ext, - &mut gas_meter, - ).unwrap(); - } } diff --git a/frame/contracts/src/wasm/prepare.rs b/frame/contracts/src/wasm/prepare.rs index ba934f353ec250340fd2bd1c14f69e6ee251379f..03f33f2dc627f5b11ce60cc36bf17adbb374a21a 100644 --- a/frame/contracts/src/wasm/prepare.rs +++ b/frame/contracts/src/wasm/prepare.rs @@ -227,11 +227,7 @@ impl<'a> ContractModule<'a> { }; // Then check the signature. - // Both "call" and "deploy" has a [] -> [] or [] -> [i32] function type. - // - // The [] -> [] signature predates the [] -> [i32] signature and is supported for - // backwards compatibility. This will likely be removed once ink! is updated to - // generate modules with the new function signatures. + // Both "call" and "deploy" has a () -> () function type. let func_ty_idx = func_entries.get(fn_idx as usize) .ok_or_else(|| "export refers to non-existent function")? .type_ref(); diff --git a/frame/contracts/src/wasm/runtime.rs b/frame/contracts/src/wasm/runtime.rs index 7cede5542fc6f8bde389f6b99fc960b7b3512e24..a221e3c7cf4cb6a3f7989ceec002a1cb14858b7c 100644 --- a/frame/contracts/src/wasm/runtime.rs +++ b/frame/contracts/src/wasm/runtime.rs @@ -16,14 +16,17 @@ //! Environment definition of the wasm smart-contract runtime. -use crate::{Schedule, Trait, CodeHash, ComputeDispatchFee, BalanceOf}; +use crate::{Schedule, Trait, CodeHash, BalanceOf, Error}; use crate::exec::{ - Ext, ExecResult, ExecError, ExecReturnValue, StorageKey, TopicOf, STATUS_SUCCESS, + Ext, ExecResult, ExecReturnValue, StorageKey, TopicOf, ReturnFlags, }; -use crate::gas::{Gas, GasMeter, Token, GasMeterResult, approx_gas_for_balance}; +use crate::gas::{Gas, GasMeter, Token, GasMeterResult}; +use crate::wasm::env_def::ConvertibleToWasm; use sp_sandbox; +use parity_wasm::elements::ValueType; use frame_system; -use sp_std::{prelude::*, mem, convert::TryInto}; +use frame_support::dispatch::DispatchError; +use sp_std::prelude::*; use codec::{Decode, Encode}; use sp_runtime::traits::{Bounded, SaturatedConversion}; use sp_io::hashing::{ @@ -33,33 +36,81 @@ use sp_io::hashing::{ sha2_256, }; -/// 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; +/// Every error that can be returned from a runtime API call. +#[repr(u32)] +pub enum ReturnCode { + /// API call successful. + Success = 0, + /// The called function trapped and has its state changes reverted. + /// In this case no output buffer is returned. + /// Can only be returned from `ext_call` and `ext_instantiate`. + CalleeTrapped = 1, + /// The called function ran to completion but decided to revert its state. + /// An output buffer is returned when one was supplied. + /// Can only be returned from `ext_call` and `ext_instantiate`. + CalleeReverted = 2, + /// The passed key does not exist in storage. + KeyNotFound = 3, +} + +impl ConvertibleToWasm for ReturnCode { + type NativeType = Self; + const VALUE_TYPE: ValueType = ValueType::I32; + fn to_typed_value(self) -> sp_sandbox::Value { + sp_sandbox::Value::I32(self as i32) + } + fn from_typed_value(_: sp_sandbox::Value) -> Option { + debug_assert!(false, "We will never receive a ReturnCode but only send it to wasm."); + None + } +} + +impl From for ReturnCode { + fn from(from: ExecReturnValue) -> ReturnCode { + if from.flags.contains(ReturnFlags::REVERT) { + Self::CalleeReverted + } else { + Self::Success + } + } +} + +/// The data passed through when a contract uses `ext_return`. +struct ReturnData { + /// The flags as passed through by the contract. They are still unchecked and + /// will later be parsed into a `ReturnFlags` bitflags struct. + flags: u32, + /// The output buffer passed by the contract as return data. + data: Vec, +} -/// Enumerates all possible *special* trap conditions. +/// Enumerates all possible reasons why a trap was generated. /// -/// In this runtime traps used not only for signaling about errors but also -/// to just terminate quickly in some cases. -enum SpecialTrap { +/// This is either used to supply the caller with more information about why an error +/// occurred (the SupervisorError variant). +/// The other case is where the trap does not constitute an error but rather was invoked +/// as a quick way to terminate the application (all other variants). +enum TrapReason { + /// The supervisor trapped the contract because of an error condition occurred during + /// execution in privileged code. + SupervisorError(DispatchError), /// Signals that trap was generated in response to call `ext_return` host function. - Return(Vec), - /// Signals that trap was generated because the contract exhausted its gas limit. - OutOfGas, + Return(ReturnData), /// Signals that a trap was generated in response to a succesful call to the /// `ext_terminate` host function. Termination, + /// Signals that a trap was generated because of a successful restoration. + Restoration, } /// Can only be used for one call. pub(crate) struct Runtime<'a, E: Ext + 'a> { ext: &'a mut E, - scratch_buf: Vec, + input_data: Option>, schedule: &'a Schedule, memory: sp_sandbox::Memory, gas_meter: &'a mut GasMeter, - special_trap: Option, + trap_reason: Option, } impl<'a, E: Ext + 'a> Runtime<'a, E> { pub(crate) fn new( @@ -71,12 +122,11 @@ impl<'a, E: Ext + 'a> Runtime<'a, E> { ) -> Self { Runtime { ext, - // Put the input data into the scratch buffer immediately. - scratch_buf: input_data, + input_data: Some(input_data), schedule, memory, gas_meter, - special_trap: None, + trap_reason: None, } } } @@ -85,47 +135,39 @@ pub(crate) fn to_execution_result( runtime: Runtime, sandbox_result: Result, ) -> ExecResult { - match runtime.special_trap { + match runtime.trap_reason { // The trap was the result of the execution `return` host function. - Some(SpecialTrap::Return(data)) => { + Some(TrapReason::Return(ReturnData{ flags, data })) => { + let flags = ReturnFlags::from_bits(flags).ok_or_else(|| + "used reserved bit in return flags" + )?; return Ok(ExecReturnValue { - status: STATUS_SUCCESS, + flags, data, }) }, - Some(SpecialTrap::Termination) => { + Some(TrapReason::Termination) => { return Ok(ExecReturnValue { - status: STATUS_SUCCESS, + flags: ReturnFlags::empty(), data: Vec::new(), }) }, - Some(SpecialTrap::OutOfGas) => { - return Err(ExecError { - reason: "ran out of gas during contract execution".into(), - buffer: runtime.scratch_buf, + Some(TrapReason::Restoration) => { + return Ok(ExecReturnValue { + flags: ReturnFlags::empty(), + data: Vec::new(), }) - }, + } + Some(TrapReason::SupervisorError(error)) => Err(error)?, None => (), } // Check the exact type of the error. match sandbox_result { // No traps were generated. Proceed normally. - Ok(sp_sandbox::ReturnValue::Unit) => { - let mut buffer = runtime.scratch_buf; - buffer.clear(); - Ok(ExecReturnValue { status: STATUS_SUCCESS, data: buffer }) - } - Ok(sp_sandbox::ReturnValue::Value(sp_sandbox::Value::I32(exit_code))) => { - let status = (exit_code & 0xFF).try_into() - .expect("exit_code is masked into the range of a u8; qed"); - Ok(ExecReturnValue { status, data: runtime.scratch_buf }) + Ok(_) => { + Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() }) } - // This should never happen as the return type of exported functions should have been - // validated by the code preparation process. However, because panics are really - // undesirable in the runtime code, we treat this as a trap for now. Eventually, we might - // want to revisit this. - Ok(_) => Err(ExecError { reason: "return type error".into(), buffer: runtime.scratch_buf }), // `Error::Module` is returned only if instantiation or linking failed (i.e. // wasm binary tried to import a function that is not provided by the host). // This shouldn't happen because validation process ought to reject such binaries. @@ -133,10 +175,10 @@ pub(crate) fn to_execution_result( // Because panics are really undesirable in the runtime code, we treat this as // a trap for now. Eventually, we might want to revisit this. Err(sp_sandbox::Error::Module) => - Err(ExecError { reason: "validation error".into(), buffer: runtime.scratch_buf }), + Err("validation error")?, // Any other kind of a trap should result in a failure. Err(sp_sandbox::Error::Execution) | Err(sp_sandbox::Error::OutOfBounds) => - Err(ExecError { reason: "contract trapped during execution".into(), buffer: runtime.scratch_buf }), + Err("contract trapped during execution")?, } } @@ -153,8 +195,6 @@ pub enum RuntimeToken { /// The given number of bytes is read from the sandbox memory and /// is returned as the return data buffer of the call. ReturnData(u32), - /// Dispatch fee calculated by `T::ComputeDispatchFee`. - ComputedDispatchFee(Gas), /// (topic_count, data_bytes): A buffer of the given size is posted as an event indexed with the /// given number of topics. DepositEvent(u32, u32), @@ -195,7 +235,6 @@ impl Token for RuntimeToken { data_and_topics_cost.checked_add(metadata.event_base_cost) ) }, - ComputedDispatchFee(gas) => Some(gas), }; value.unwrap_or_else(|| Bounded::max_value()) @@ -208,13 +247,13 @@ impl Token for RuntimeToken { fn charge_gas>( gas_meter: &mut GasMeter, metadata: &Tok::Metadata, - special_trap: &mut Option, + trap_reason: &mut Option, token: Tok, ) -> Result<(), sp_sandbox::HostError> { match gas_meter.charge(metadata, token) { GasMeterResult::Proceed => Ok(()), GasMeterResult::OutOfGas => { - *special_trap = Some(SpecialTrap::OutOfGas); + *trap_reason = Some(TrapReason::SupervisorError(Error::::OutOfGas.into())); Err(sp_sandbox::HostError) }, } @@ -236,7 +275,7 @@ fn read_sandbox_memory( charge_gas( ctx.gas_meter, ctx.schedule, - &mut ctx.special_trap, + &mut ctx.trap_reason, RuntimeToken::ReadMemory(len), )?; @@ -245,31 +284,6 @@ fn read_sandbox_memory( Ok(buf) } -/// Read designated chunk from the sandbox memory into the scratch buffer, consuming an -/// appropriate amount of gas. Resizes the scratch buffer to the specified length on success. -/// -/// Returns `Err` if one of the following conditions occurs: -/// -/// - calculating the gas cost resulted in overflow. -/// - out of gas -/// - requested buffer is not within the bounds of the sandbox memory. -fn read_sandbox_memory_into_scratch( - ctx: &mut Runtime, - ptr: u32, - len: u32, -) -> Result<(), sp_sandbox::HostError> { - charge_gas( - ctx.gas_meter, - ctx.schedule, - &mut ctx.special_trap, - RuntimeToken::ReadMemory(len), - )?; - - ctx.scratch_buf.resize(len as usize, 0); - ctx.memory.get(ptr, ctx.scratch_buf.as_mut_slice()).map_err(|_| sp_sandbox::HostError)?; - Ok(()) -} - /// Read designated chunk from the sandbox memory into the supplied buffer, consuming /// an appropriate amount of gas. /// @@ -286,7 +300,7 @@ fn read_sandbox_memory_into_buf( charge_gas( ctx.gas_meter, ctx.schedule, - &mut ctx.special_trap, + &mut ctx.trap_reason, RuntimeToken::ReadMemory(buf.len() as u32), )?; @@ -319,26 +333,79 @@ fn read_sandbox_memory_as( /// - calculating the gas cost resulted in overflow. /// - out of gas /// - designated area is not within the bounds of the sandbox memory. -fn write_sandbox_memory( - schedule: &Schedule, - special_trap: &mut Option, - gas_meter: &mut GasMeter, - memory: &sp_sandbox::Memory, +fn write_sandbox_memory( + ctx: &mut Runtime, ptr: u32, buf: &[u8], ) -> Result<(), sp_sandbox::HostError> { charge_gas( - gas_meter, - schedule, - special_trap, + ctx.gas_meter, + ctx.schedule, + &mut ctx.trap_reason, RuntimeToken::WriteMemory(buf.len() as u32), )?; - memory.set(ptr, buf)?; + ctx.memory.set(ptr, buf)?; + + Ok(()) +} + +/// Write the given buffer and its length to the designated locations in sandbox memory. +// +/// `out_ptr` is the location in sandbox memory where `buf` should be written to. +/// `out_len_ptr` is an in-out location in sandbox memory. It is read to determine the +/// lenght of the buffer located at `out_ptr`. If that buffer is large enough the actual +/// `buf.len()` is written to this location. +/// +/// If `out_ptr` is set to the sentinel value of `u32::max_value()` and `allow_skip` is true the +/// operation is skipped and `Ok` is returned. This is supposed to help callers to make copying +/// output optional. For example to skip copying back the output buffer of an `ext_call` +/// when the caller is not interested in the result. +/// +/// In addition to the error conditions of `write_sandbox_memory` this functions returns +/// `Err` if the size of the buffer located at `out_ptr` is too small to fit `buf`. +fn write_sandbox_output( + ctx: &mut Runtime, + out_ptr: u32, + out_len_ptr: u32, + buf: &[u8], + allow_skip: bool, +) -> Result<(), sp_sandbox::HostError> { + if allow_skip && out_ptr == u32::max_value() { + return Ok(()); + } + + let buf_len = buf.len() as u32; + let len: u32 = read_sandbox_memory_as(ctx, out_len_ptr, 4)?; + + if len < buf_len { + Err(map_err(ctx, Error::::OutputBufferTooSmall))? + } + + charge_gas( + ctx.gas_meter, + ctx.schedule, + &mut ctx.trap_reason, + RuntimeToken::WriteMemory(buf_len.saturating_add(4)), + )?; + + ctx.memory.set(out_ptr, buf)?; + ctx.memory.set(out_len_ptr, &buf_len.encode())?; Ok(()) } +/// Stores a DispatchError returned from an Ext function into the trap_reason. +/// +/// This allows through supervisor generated errors to the caller. +fn map_err(ctx: &mut Runtime, err: Error) -> sp_sandbox::HostError where + E: Ext, + Error: Into, +{ + ctx.trap_reason = Some(TrapReason::SupervisorError(err.into())); + sp_sandbox::HostError +} + // *********************************************************** // * AFTER MAKING A CHANGE MAKE SURE TO UPDATE COMPLEXITY.MD * // *********************************************************** @@ -357,7 +424,7 @@ define_env!(Env, , charge_gas( &mut ctx.gas_meter, ctx.schedule, - &mut ctx.special_trap, + &mut ctx.trap_reason, RuntimeToken::Explicit(amount) )?; Ok(()) @@ -386,7 +453,7 @@ define_env!(Env, , let mut key: StorageKey = [0; 32]; read_sandbox_memory_into_buf(ctx, key_ptr, &mut key)?; let value = Some(read_sandbox_memory(ctx, value_ptr, value_len)?); - ctx.ext.set_storage(key, value).map_err(|_| sp_sandbox::HostError)?; + ctx.ext.set_storage(key, value); Ok(()) }, @@ -398,33 +465,41 @@ define_env!(Env, , ext_clear_storage(ctx, key_ptr: u32) => { let mut key: StorageKey = [0; 32]; read_sandbox_memory_into_buf(ctx, key_ptr, &mut key)?; - ctx.ext.set_storage(key, None).map_err(|_| sp_sandbox::HostError)?; + ctx.ext.set_storage(key, None); Ok(()) }, - // Retrieve the value under the given key from the storage and return 0. - // If there is no entry under the given key then this function will return 1 and - // clear the scratch buffer. + // Retrieve the value under the given key from storage. + // + // # Parameters // - // - key_ptr: pointer into the linear memory where the key - // of the requested value is placed. - ext_get_storage(ctx, key_ptr: u32) -> u32 => { + // - `key_ptr`: pointer into the linear memory where the key of the requested value is placed. + // - `out_ptr`: pointer to the linear memory where the value is written to. + // - `out_len_ptr`: in-out pointer into linear memory where the buffer length + // is read from and the value length is written to. + // + // # Errors + // + // If there is no entry under the given key then this function will return + // `ReturnCode::KeyNotFound`. + // + // # Traps + // + // Traps if the supplied buffer length is smaller than the size of the stored value. + ext_get_storage(ctx, key_ptr: u32, out_ptr: u32, out_len_ptr: u32) -> ReturnCode => { let mut key: StorageKey = [0; 32]; read_sandbox_memory_into_buf(ctx, key_ptr, &mut key)?; if let Some(value) = ctx.ext.get_storage(&key) { - ctx.scratch_buf = value; - Ok(0) + write_sandbox_output(ctx, out_ptr, out_len_ptr, &value, false)?; + Ok(ReturnCode::Success) } else { - ctx.scratch_buf.clear(); - Ok(1) + Ok(ReturnCode::KeyNotFound) } }, // Transfer some value to another account. // - // If the value transfer was succesful zero is returned. Otherwise one is returned. - // The scratch buffer is not touched. The receiver can be a plain account or - // a contract. + // # Parameters // // - account_ptr: a pointer to the address of the beneficiary account // Should be decodable as an `T::AccountId`. Traps otherwise. @@ -432,38 +507,34 @@ define_env!(Env, , // - value_ptr: a pointer to the buffer with value, how much value to send. // Should be decodable as a `T::Balance`. Traps otherwise. // - value_len: length of the value buffer. + // + // # Traps + // + // Traps if the transfer wasn't succesful. This can happen when the value transfered + // brings the sender below the existential deposit. Use `ext_terminate` to remove + // the caller contract. ext_transfer( ctx, account_ptr: u32, account_len: u32, value_ptr: u32, value_len: u32 - ) -> u32 => { + ) => { let callee: <::T as frame_system::Trait>::AccountId = read_sandbox_memory_as(ctx, account_ptr, account_len)?; let value: BalanceOf<::T> = read_sandbox_memory_as(ctx, value_ptr, value_len)?; - match ctx.ext.transfer(&callee, value, ctx.gas_meter) { - Ok(_) => Ok(0), - Err(_) => Ok(1), - } + ctx.ext.transfer(&callee, value, ctx.gas_meter).map_err(|e| map_err(ctx, e)) }, // Make a call to another contract. // - // If the called contract runs to completion, then this returns the status code the callee - // 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. The scratch buffer is filled with the - // output data returned by the called contract, even in the case of a failure status. - // - // This call fails if it would bring the calling contract below the existential deposit. - // In order to destroy a contract `ext_terminate` must be used. + // The callees output buffer is copied to `output_ptr` and its length to `output_len_ptr`. + // The copy of the output buffer can be skipped by supplying the sentinel value + // of `u32::max_value()` to `output_ptr`. // - // 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 - // state changes made by the called contract are reverted. + // # Parameters // // - callee_ptr: a pointer to the address of the callee contract. // Should be decodable as an `T::AccountId`. Traps otherwise. @@ -474,6 +545,23 @@ 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 callee. // - input_data_len: length of the input data buffer. + // - output_ptr: a pointer where the output buffer is copied to. + // - output_len_ptr: in-out pointer to where the length of the buffer is read from + // and the actual length is written to. + // + // # Errors + // + // `ReturnCode::CalleeReverted`: The callee ran to completion but decided to have its + // changes reverted. The delivery of the output buffer is still possible. + // `ReturnCode::CalleeTrapped`: The callee trapped during execution. All changes are reverted + // and no output buffer is delivered. + // + // # Traps + // + // - Transfer of balance failed. This call can not bring the sender below the existential + // deposit. Use `ext_terminate` to remove the caller. + // - Callee does not exist. + // - Supplied output buffer is too small. ext_call( ctx, callee_ptr: u32, @@ -482,16 +570,14 @@ define_env!(Env, , value_ptr: u32, value_len: u32, input_data_ptr: u32, - input_data_len: u32 - ) -> u32 => { + input_data_len: u32, + output_ptr: u32, + output_len_ptr: u32 + ) -> ReturnCode => { let callee: <::T as frame_system::Trait>::AccountId = read_sandbox_memory_as(ctx, callee_ptr, callee_len)?; - let value: BalanceOf<::T> = - read_sandbox_memory_as(ctx, value_ptr, value_len)?; - - // Read input data into the scratch buffer, then take ownership of it. - read_sandbox_memory_into_scratch(ctx, input_data_ptr, input_data_len)?; - let input_data = mem::replace(&mut ctx.scratch_buf, Vec::new()); + let value: BalanceOf<::T> = read_sandbox_memory_as(ctx, value_ptr, value_len)?; + let input_data = read_sandbox_memory(ctx, input_data_ptr, input_data_len)?; let nested_gas_limit = if gas == 0 { ctx.gas_meter.gas_left() @@ -508,22 +594,20 @@ define_env!(Env, , nested_meter, input_data, ) - .map_err(|err| err.buffer) + .map_err(|_| ()) } // there is not enough gas to allocate for the nested call. - None => Err(input_data), + None => Err(()), } }); match call_outcome { Ok(output) => { - ctx.scratch_buf = output.data; - Ok(output.status.into()) + write_sandbox_output(ctx, output_ptr, output_len_ptr, &output.data, true)?; + Ok(output.into()) }, - Err(buffer) => { - ctx.scratch_buf = buffer; - ctx.scratch_buf.clear(); - Ok(TRAP_RETURN_CODE) + Err(_) => { + Ok(ReturnCode::CalleeTrapped) }, } }, @@ -531,29 +615,14 @@ define_env!(Env, , // Instantiate a contract with the specified code hash. // // This function creates an account and executes the constructor defined in the code specified - // by the code hash. + // by the code hash. The address of this new account is copied to `address_ptr` and its length + // to `address_len_ptr`. The constructors output buffer is copied to `output_ptr` and its + // length to `output_len_ptr`. // - // If the constructor runs to completion, then this returns the status code that the newly - // 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. + // The copy of the output buffer and address can be skipped by supplying the sentinel value + // of `u32::max_value()` to `output_ptr` or `address_ptr`. // - // This call fails if it would bring the calling contract below the existential deposit. - // In order to destroy a contract `ext_terminate` must be used. - // - // 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 - // state changes made by the called contract are reverted. - - // 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 instantiation and puts the address of the instantiated - // contract into the scratch buffer. Otherwise, returns non-zero value and clears the scratch - // buffer. + // # Parameters // // - code_hash_ptr: a pointer to the buffer that contains the initializer code. // - code_hash_len: length of the initializer code buffer. @@ -563,6 +632,28 @@ 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. + // - address_ptr: a pointer where the new account's address is copied to. + // - address_len_ptr: in-out pointer to where the length of the buffer is read from + // and the actual length is written to. + // - output_ptr: a pointer where the output buffer is copied to. + // - output_len_ptr: in-out pointer to where the length of the buffer is read from + // and the actual length is written to. + // + // # Errors + // + // `ReturnCode::CalleeReverted`: The callee's constructor ran to completion but decided to have + // its changes reverted. The delivery of the output buffer is still possible but the + // account was not created and no address is returned. + // `ReturnCode::CalleeTrapped`: The callee trapped during execution. All changes are reverted + // and no output buffer is delivered. The accounts was not created and no address is + // returned. + // + // # Traps + // + // - Transfer of balance failed. This call can not bring the sender below the existential + // deposit. Use `ext_terminate` to remove the caller. + // - Code hash does not exist. + // - Supplied output buffers are too small. ext_instantiate( ctx, code_hash_ptr: u32, @@ -571,16 +662,16 @@ define_env!(Env, , value_ptr: u32, value_len: u32, input_data_ptr: u32, - input_data_len: u32 - ) -> u32 => { + input_data_len: u32, + address_ptr: u32, + address_len_ptr: u32, + output_ptr: u32, + output_len_ptr: u32 + ) -> ReturnCode => { let code_hash: CodeHash<::T> = read_sandbox_memory_as(ctx, code_hash_ptr, code_hash_len)?; - let value: BalanceOf<::T> = - read_sandbox_memory_as(ctx, value_ptr, value_len)?; - - // Read input data into the scratch buffer, then take ownership of it. - read_sandbox_memory_into_scratch(ctx, input_data_ptr, input_data_len)?; - let input_data = mem::replace(&mut ctx.scratch_buf, Vec::new()); + let value: BalanceOf<::T> = read_sandbox_memory_as(ctx, value_ptr, value_len)?; + let input_data = read_sandbox_memory(ctx, input_data_ptr, input_data_len)?; let nested_gas_limit = if gas == 0 { ctx.gas_meter.gas_left() @@ -597,27 +688,24 @@ define_env!(Env, , nested_meter, input_data ) - .map_err(|err| err.buffer) + .map_err(|_| ()) } // there is not enough gas to allocate for the nested call. - None => Err(input_data), + None => Err(()), } }); match instantiate_outcome { Ok((address, output)) => { - let is_success = output.is_success(); - ctx.scratch_buf = output.data; - ctx.scratch_buf.clear(); - if is_success { - // Write the address to the scratch buffer. - address.encode_to(&mut ctx.scratch_buf); + if !output.flags.contains(ReturnFlags::REVERT) { + write_sandbox_output( + ctx, address_ptr, address_len_ptr, &address.encode(), true + )?; } - Ok(output.status.into()) + write_sandbox_output(ctx, output_ptr, output_len_ptr, &output.data, true)?; + Ok(output.into()) }, - Err(buffer) => { - ctx.scratch_buf = buffer; - ctx.scratch_buf.clear(); - Ok(TRAP_RETURN_CODE) + Err(_) => { + Ok(ReturnCode::CalleeTrapped) }, } }, @@ -641,27 +729,48 @@ define_env!(Env, , read_sandbox_memory_as(ctx, beneficiary_ptr, beneficiary_len)?; if let Ok(_) = ctx.ext.terminate(&beneficiary, ctx.gas_meter) { - ctx.special_trap = Some(SpecialTrap::Termination); + ctx.trap_reason = Some(TrapReason::Termination); } Err(sp_sandbox::HostError) }, - // Save a data buffer as a result of the execution, terminate the execution and return a - // successful result to the caller. + ext_input(ctx, buf_ptr: u32, buf_len_ptr: u32) => { + if let Some(input) = ctx.input_data.take() { + write_sandbox_output(ctx, buf_ptr, buf_len_ptr, &input, false) + } else { + Err(sp_sandbox::HostError) + } + }, + + // Cease contract execution and save a data buffer as a result of the execution. + // + // This function never retuns as it stops execution of the caller. + // This is the only way to return a data buffer to the caller. Returning from + // execution without calling this function is equivalent to calling: + // ``` + // ext_return(0, 0, 0); + // ``` + // + // The flags argument is a bitfield that can be used to signal special return + // conditions to the supervisor: + // --- lsb --- + // bit 0 : REVERT - Revert all storage changes made by the caller. + // bit [1, 31]: Reserved for future use. + // --- msb --- // - // This is the only way to return a data buffer to the caller. - ext_return(ctx, data_ptr: u32, data_len: u32) => { + // Using a reserved bit triggers a trap. + ext_return(ctx, flags: u32, data_ptr: u32, data_len: u32) => { charge_gas( ctx.gas_meter, ctx.schedule, - &mut ctx.special_trap, + &mut ctx.trap_reason, RuntimeToken::ReturnData(data_len) )?; - read_sandbox_memory_into_scratch(ctx, data_ptr, data_len)?; - let output_buf = mem::replace(&mut ctx.scratch_buf, Vec::new()); - - ctx.special_trap = Some(SpecialTrap::Return(output_buf)); + ctx.trap_reason = Some(TrapReason::Return(ReturnData { + flags, + data: read_sandbox_memory(ctx, data_ptr, data_len)?, + })); // The trap mechanism is used to immediately terminate the execution. // This trap should be handled appropriately before returning the result @@ -669,98 +778,131 @@ define_env!(Env, , Err(sp_sandbox::HostError) }, - // Stores the address of the caller into the scratch buffer. + // Stores the address of the caller into the supplied buffer. + // + // The value is stored to linear memory at the address pointed to by `out_ptr`. + // `out_len_ptr` must point to a u32 value that describes the available space at + // `out_ptr`. This call overwrites it with the size of the value. If the available + // space at `out_ptr` is less than the size of the value a trap is triggered. // // 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); - Ok(()) + // address of the contract will be returned. The value is encoded as T::AccountId. + ext_caller(ctx, out_ptr: u32, out_len_ptr: u32) => { + write_sandbox_output(ctx, out_ptr, out_len_ptr, &ctx.ext.caller().encode(), false) }, - // Stores the address of the current contract into the scratch buffer. - ext_address(ctx) => { - ctx.scratch_buf.clear(); - ctx.ext.address().encode_to(&mut ctx.scratch_buf); - Ok(()) + // Stores the address of the current contract into the supplied buffer. + // + // The value is stored to linear memory at the address pointed to by `out_ptr`. + // `out_len_ptr` must point to a u32 value that describes the available space at + // `out_ptr`. This call overwrites it with the size of the value. If the available + // space at `out_ptr` is less than the size of the value a trap is triggered. + ext_address(ctx, out_ptr: u32, out_len_ptr: u32) => { + write_sandbox_output(ctx, out_ptr, out_len_ptr, &ctx.ext.address().encode(), false) }, - // Stores the gas price for the current transaction into the scratch buffer. + // Stores the price for the specified amount of gas into the supplied buffer. // - // The data is encoded as T::Balance. The current contents of the scratch buffer are overwritten. - ext_gas_price(ctx) => { - ctx.scratch_buf.clear(); - ctx.gas_meter.gas_price().encode_to(&mut ctx.scratch_buf); - Ok(()) + // The value is stored to linear memory at the address pointed to by `out_ptr`. + // `out_len_ptr` must point to a u32 value that describes the available space at + // `out_ptr`. This call overwrites it with the size of the value. If the available + // space at `out_ptr` is less than the size of the value a trap is triggered. + // + // The data is encoded as T::Balance. + // + // # Note + // + // It is recommended to avoid specifying very small values for `gas` as the prices for a single + // gas can be smaller than one. + ext_weight_to_fee(ctx, gas: u64, out_ptr: u32, out_len_ptr: u32) => { + write_sandbox_output( + ctx, out_ptr, out_len_ptr, &ctx.ext.get_weight_price(gas).encode(), false + ) }, - // Stores the amount of gas left into the scratch buffer. + // Stores the amount of gas left into the supplied buffer. // - // The data is encoded as Gas. The current contents of the scratch buffer are overwritten. - ext_gas_left(ctx) => { - ctx.scratch_buf.clear(); - ctx.gas_meter.gas_left().encode_to(&mut ctx.scratch_buf); - Ok(()) + // The value is stored to linear memory at the address pointed to by `out_ptr`. + // `out_len_ptr` must point to a u32 value that describes the available space at + // `out_ptr`. This call overwrites it with the size of the value. If the available + // space at `out_ptr` is less than the size of the value a trap is triggered. + // + // The data is encoded as Gas. + ext_gas_left(ctx, out_ptr: u32, out_len_ptr: u32) => { + write_sandbox_output(ctx, out_ptr, out_len_ptr, &ctx.gas_meter.gas_left().encode(), false) }, - // Stores the balance of the current account into the scratch buffer. + // Stores the balance of the current account into the supplied buffer. // - // The data is encoded as T::Balance. The current contents of the scratch buffer are overwritten. - ext_balance(ctx) => { - ctx.scratch_buf.clear(); - ctx.ext.balance().encode_to(&mut ctx.scratch_buf); - Ok(()) + // The value is stored to linear memory at the address pointed to by `out_ptr`. + // `out_len_ptr` must point to a u32 value that describes the available space at + // `out_ptr`. This call overwrites it with the size of the value. If the available + // space at `out_ptr` is less than the size of the value a trap is triggered. + // + // The data is encoded as T::Balance. + ext_balance(ctx, out_ptr: u32, out_len_ptr: u32) => { + write_sandbox_output(ctx, out_ptr, out_len_ptr, &ctx.ext.balance().encode(), false) }, - // Stores the value transferred along with this call or as endowment into the scratch buffer. + // Stores the value transferred along with this call or as endowment into the supplied buffer. // - // The data is encoded as T::Balance. The current contents of the scratch buffer are overwritten. - ext_value_transferred(ctx) => { - ctx.scratch_buf.clear(); - ctx.ext.value_transferred().encode_to(&mut ctx.scratch_buf); - Ok(()) + // The value is stored to linear memory at the address pointed to by `out_ptr`. + // `out_len_ptr` must point to a u32 value that describes the available space at + // `out_ptr`. This call overwrites it with the size of the value. If the available + // space at `out_ptr` is less than the size of the value a trap is triggered. + // + // The data is encoded as T::Balance. + ext_value_transferred(ctx, out_ptr: u32, out_len_ptr: u32) => { + write_sandbox_output( + ctx, out_ptr, out_len_ptr, &ctx.ext.value_transferred().encode(), false + ) }, - // Stores the random number for the current block for the given subject into the scratch - // buffer. + // Stores a random number for the current block and the given subject into the supplied buffer. // - // The data is encoded as T::Hash. The current contents of the scratch buffer are - // overwritten. - ext_random(ctx, subject_ptr: u32, subject_len: u32) => { + // The value is stored to linear memory at the address pointed to by `out_ptr`. + // `out_len_ptr` must point to a u32 value that describes the available space at + // `out_ptr`. This call overwrites it with the size of the value. If the available + // space at `out_ptr` is less than the size of the value a trap is triggered. + // + // The data is encoded as T::Hash. + ext_random(ctx, subject_ptr: u32, subject_len: u32, out_ptr: u32, out_len_ptr: u32) => { // The length of a subject can't exceed `max_subject_len`. if subject_len > ctx.schedule.max_subject_len { return Err(sp_sandbox::HostError); } - let subject_buf = read_sandbox_memory(ctx, subject_ptr, subject_len)?; - ctx.scratch_buf.clear(); - ctx.ext.random(&subject_buf).encode_to(&mut ctx.scratch_buf); - Ok(()) + write_sandbox_output( + ctx, out_ptr, out_len_ptr, &ctx.ext.random(&subject_buf).encode(), false + ) }, - // Load the latest block timestamp into the scratch buffer - ext_now(ctx) => { - ctx.scratch_buf.clear(); - ctx.ext.now().encode_to(&mut ctx.scratch_buf); - Ok(()) + // Load the latest block timestamp into the supplied buffer + // + // The value is stored to linear memory at the address pointed to by `out_ptr`. + // `out_len_ptr` must point to a u32 value that describes the available space at + // `out_ptr`. This call overwrites it with the size of the value. If the available + // space at `out_ptr` is less than the size of the value a trap is triggered. + ext_now(ctx, out_ptr: u32, out_len_ptr: u32) => { + write_sandbox_output(ctx, out_ptr, out_len_ptr, &ctx.ext.now().encode(), false) }, - // Stores the minimum balance (a.k.a. existential deposit) into the scratch buffer. + // Stores the minimum balance (a.k.a. existential deposit) into the supplied 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(()) + // The data is encoded as T::Balance. + ext_minimum_balance(ctx, out_ptr: u32, out_len_ptr: u32) => { + write_sandbox_output(ctx, out_ptr, out_len_ptr, &ctx.ext.minimum_balance().encode(), false) }, - // Stores the tombstone deposit into the scratch buffer. + // Stores the tombstone deposit into the supplied buffer. // - // The data is encoded as T::Balance. The current contents of the scratch - // buffer are overwritten. + // The value is stored to linear memory at the address pointed to by `out_ptr`. + // `out_len_ptr` must point to a u32 value that describes the available space at + // `out_ptr`. This call overwrites it with the size of the value. If the available + // space at `out_ptr` is less than the size of the value a trap is triggered. + // + // The data is encoded as T::Balance. // // # Note // @@ -768,49 +910,24 @@ define_env!(Env, , // a contract to leave a tombstone the balance of the contract must not go // below the sum of existential deposit and the tombstone deposit. The sum // is commonly referred as subsistence threshold in code. - ext_tombstone_deposit(ctx) => { - ctx.scratch_buf.clear(); - ctx.ext.tombstone_deposit().encode_to(&mut ctx.scratch_buf); - Ok(()) + ext_tombstone_deposit(ctx, out_ptr: u32, out_len_ptr: u32) => { + write_sandbox_output( + ctx, out_ptr, out_len_ptr, &ctx.ext.tombstone_deposit().encode(), false + ) }, - // Decodes the given buffer as a `T::Call` and adds it to the list - // of to-be-dispatched calls. + // Try to restore the given destination contract sacrificing the caller. // - // All calls made it to the top-level context will be dispatched before - // finishing the execution of the calling extrinsic. - ext_dispatch_call(ctx, call_ptr: u32, call_len: u32) => { - let call: <::T as Trait>::Call = - read_sandbox_memory_as(ctx, call_ptr, call_len)?; - - // Charge gas for dispatching this call. - let fee = { - let balance_fee = <::T as Trait>::ComputeDispatchFee::compute_dispatch_fee(&call); - approx_gas_for_balance(ctx.gas_meter.gas_price(), balance_fee) - }; - charge_gas( - &mut ctx.gas_meter, - ctx.schedule, - &mut ctx.special_trap, - RuntimeToken::ComputedDispatchFee(fee) - )?; - - ctx.ext.note_dispatch_call(call); - - Ok(()) - }, - - // Record a request to restore the caller contract to the specified contract. + // This function will compute a tombstone hash from the caller's storage and the given code hash + // and if the hash matches the hash found in the tombstone at the specified address - kill + // the caller contract and restore the destination contract and set the specified `rent_allowance`. + // All caller's funds are transfered to the destination. // - // At the finalization stage, i.e. when all changes from the extrinsic that invoked this - // contract are committed, this function will compute a tombstone hash from the caller's - // storage and the given code hash and if the hash matches the hash found in the tombstone at - // the specified address - kill the caller contract and restore the destination contract and set - // the specified `rent_allowance`. All caller's funds are transferred to the destination. + // If there is no tombstone at the destination address, the hashes don't match or this contract + // instance is already present on the contract call stack, a trap is generated. // - // This function doesn't perform restoration right away but defers it to the end of the - // transaction. If there is no tombstone in the destination address or if the hashes don't match - // then restoration is cancelled and no changes are made. + // Otherwise, the destination contract is restored. This function is diverging and stops execution + // even on success. // // `dest_ptr`, `dest_len` - the pointer and the length of a buffer that encodes `T::AccountId` // with the address of the to be restored contract. @@ -858,62 +975,15 @@ define_env!(Env, , delta }; - ctx.ext.note_restore_to( + if let Ok(()) = ctx.ext.restore_to( dest, code_hash, rent_allowance, delta, - ); - - Ok(()) - }, - - // Returns the size of the scratch buffer. - // - // For more details on the scratch buffer see `ext_scratch_read`. - ext_scratch_size(ctx) -> u32 => { - 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`. - // - // 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 - // function that uses the scratch buffer the contents of the scratch buffer are overwritten. - ext_scratch_read(ctx, dest_ptr: u32, offset: u32, len: u32) => { - let offset = offset as usize; - if offset > ctx.scratch_buf.len() { - // Offset can't be larger than scratch buffer length. - return Err(sp_sandbox::HostError); + ) { + ctx.trap_reason = Some(TrapReason::Restoration); } - - // This can't panic since `offset <= ctx.scratch_buf.len()`. - let src = &ctx.scratch_buf[offset..]; - if src.len() != len as usize { - return Err(sp_sandbox::HostError); - } - - // Finally, perform the write. - write_sandbox_memory( - ctx.schedule, - &mut ctx.special_trap, - ctx.gas_meter, - &ctx.memory, - dest_ptr, - src, - )?; - - Ok(()) - }, - - // Copy data from contract memory starting from `src_ptr` with length `len` into the scratch - // buffer. This overwrites the entire scratch buffer and resizes to `len`. Specifying a `len` - // of zero clears the scratch buffer. - // - // This should be used before exiting a call or instantiation in order to set the return data. - ext_scratch_write(ctx, src_ptr: u32, len: u32) => { - read_sandbox_memory_into_scratch(ctx, src_ptr, len) + Err(sp_sandbox::HostError) }, // Deposit a contract event with the data buffer and optional list of topics. There is a limit @@ -945,7 +1015,7 @@ define_env!(Env, , charge_gas( ctx.gas_meter, ctx.schedule, - &mut ctx.special_trap, + &mut ctx.trap_reason, RuntimeToken::DepositEvent(topics.len() as u32, data_len) )?; ctx.ext.deposit_event(topics, event_data); @@ -966,14 +1036,16 @@ define_env!(Env, , Ok(()) }, - // Stores the rent allowance into the scratch buffer. + // Stores the rent allowance into the supplied buffer. // - // The data is encoded as T::Balance. The current contents of the scratch buffer are overwritten. - ext_rent_allowance(ctx) => { - ctx.scratch_buf.clear(); - ctx.ext.rent_allowance().encode_to(&mut ctx.scratch_buf); - - Ok(()) + // The value is stored to linear memory at the address pointed to by `out_ptr`. + // `out_len_ptr` must point to a u32 value that describes the available space at + // `out_ptr`. This call overwrites it with the size of the value. If the available + // space at `out_ptr` is less than the size of the value a trap is triggered. + // + // The data is encoded as T::Balance. + ext_rent_allowance(ctx, out_ptr: u32, out_len_ptr: u32) => { + write_sandbox_output(ctx, out_ptr, out_len_ptr, &ctx.ext.rent_allowance().encode(), false) }, // Prints utf8 encoded string from the data buffer. @@ -987,37 +1059,14 @@ define_env!(Env, , Ok(()) }, - // Stores the current block number of the current contract into the scratch buffer. - ext_block_number(ctx) => { - ctx.scratch_buf.clear(); - ctx.ext.block_number().encode_to(&mut ctx.scratch_buf); - Ok(()) - }, - - // Retrieve the value under the given key from the **runtime** storage and return 0. - // If there is no entry under the given key then this function will return 1 and - // clear the scratch buffer. - // - // - key_ptr: the pointer into the linear memory where the requested value is placed. - // - key_len: the length of the key in bytes. - ext_get_runtime_storage(ctx, key_ptr: u32, key_len: u32) -> u32 => { - // Steal the scratch buffer so that we hopefully save an allocation for the `key_buf`. - read_sandbox_memory_into_scratch(ctx, key_ptr, key_len)?; - let key_buf = mem::replace(&mut ctx.scratch_buf, Vec::new()); - - match ctx.ext.get_runtime_storage(&key_buf) { - Some(value_buf) => { - // The given value exists. - ctx.scratch_buf = value_buf; - Ok(0) - } - None => { - // Put back the `key_buf` and allow its allocation to be reused. - ctx.scratch_buf = key_buf; - ctx.scratch_buf.clear(); - Ok(1) - } - } + // Stores the current block number of the current contract into the supplied buffer. + // + // The value is stored to linear memory at the address pointed to by `out_ptr`. + // `out_len_ptr` must point to a u32 value that describes the available space at + // `out_ptr`. This call overwrites it with the size of the value. If the available + // space at `out_ptr` is less than the size of the value a trap is triggered. + ext_block_number(ctx, out_ptr: u32, out_len_ptr: u32) => { + write_sandbox_output(ctx, out_ptr, out_len_ptr, &ctx.ext.block_number().encode(), false) }, // Computes the SHA2 256-bit hash on the given input buffer. @@ -1117,7 +1166,7 @@ define_env!(Env, , }, ); -/// Computes the given hash function on the scratch buffer. +/// Computes the given hash function on the supplied input. /// /// Reads from the sandboxed input buffer into an intermediate buffer. /// Returns the result directly to the output buffer of the sandboxed memory. @@ -1141,17 +1190,13 @@ where F: FnOnce(&[u8]) -> R, R: AsRef<[u8]>, { - // Copy the input buffer directly into the scratch buffer to avoid - // heap allocations. + // Copy input into supervisor memory. let input = read_sandbox_memory(ctx, input_ptr, input_len)?; - // Compute the hash on the scratch buffer using the given hash function. + // Compute the hash on the input buffer using the given hash function. let hash = hash_fn(&input); // Write the resulting hash back into the sandboxed output buffer. write_sandbox_memory( - ctx.schedule, - &mut ctx.special_trap, - ctx.gas_meter, - &ctx.memory, + ctx, output_ptr, hash.as_ref(), )?; diff --git a/frame/democracy/Cargo.toml b/frame/democracy/Cargo.toml index 788645764410b9bf35dcf969e1ee152a20716a64..9532be0e8ee2ddc0b996a3f91a3b17faac9a1bee 100644 --- a/frame/democracy/Cargo.toml +++ b/frame/democracy/Cargo.toml @@ -1,28 +1,32 @@ [package] name = "pallet-democracy" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for democracy" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -frame-benchmarking = { version = "2.0.0-alpha.5", default-features = false, path = "../benchmarking", optional = true } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +frame-benchmarking = { version = "2.0.0-rc4", default-features = false, path = "../benchmarking", optional = true } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -pallet-balances = { version = "2.0.0-alpha.5", path = "../balances" } -pallet-scheduler = { version = "2.0.0-alpha.5", path = "../scheduler" } -sp-storage = { version = "2.0.0-alpha.5", path = "../../primitives/storage" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0-rc4", path = "../balances" } +pallet-scheduler = { version = "2.0.0-rc4", path = "../scheduler" } +sp-storage = { version = "2.0.0-rc4", path = "../../primitives/storage" } +substrate-test-utils = { version = "2.0.0-rc4", path = "../../test-utils" } hex-literal = "0.2.1" [features] @@ -40,8 +44,6 @@ std = [ runtime-benchmarks = [ "frame-benchmarking", "frame-system/runtime-benchmarks", + "frame-support/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/democracy/src/benchmarking.rs b/frame/democracy/src/benchmarking.rs index 1df205a4f548c7f316d3cd4b920d8a01dfc2a401..77d49c80fc7577ad8d0cac042d7cdb1b0eb4f7fa 100644 --- a/frame/democracy/src/benchmarking.rs +++ b/frame/democracy/src/benchmarking.rs @@ -1,38 +1,48 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Democracy pallet benchmarking. use super::*; use frame_benchmarking::{benchmarks, account}; -use frame_support::traits::{Currency, Get, EnsureOrigin}; -use frame_system::{RawOrigin, Module as System, self}; +use frame_support::{ + IterableStorageMap, + traits::{Currency, Get, EnsureOrigin, OnInitialize, UnfilteredDispatchable}, +}; +use frame_system::{RawOrigin, Module as System, self, EventRecord}; use sp_runtime::traits::{Bounded, One}; use crate::Module as Democracy; const SEED: u32 = 0; -const MAX_USERS: u32 = 1000; const MAX_REFERENDUMS: u32 = 100; const MAX_PROPOSALS: u32 = 100; const MAX_SECONDERS: u32 = 100; -const MAX_VETOERS: u32 = 100; const MAX_BYTES: u32 = 16_384; +fn assert_last_event(generic_event: ::Event) { + let events = System::::events(); + let system_event: ::Event = generic_event.into(); + // compare to the last event record + let EventRecord { event, .. } = &events[events.len() - 1]; + assert_eq!(event, &system_event); +} + fn funded_account(name: &'static str, index: u32) -> T::AccountId { let caller: T::AccountId = account(name, index, SEED); T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); @@ -44,7 +54,11 @@ fn add_proposal(n: u32) -> Result { let value = T::MinimumDeposit::get(); let proposal_hash: T::Hash = T::Hashing::hash_of(&n); - Democracy::::propose(RawOrigin::Signed(other).into(), proposal_hash, value.into())?; + Democracy::::propose( + RawOrigin::Signed(other).into(), + proposal_hash, + value.into(), + )?; Ok(proposal_hash) } @@ -54,23 +68,24 @@ fn add_referendum(n: u32) -> Result { let vote_threshold = VoteThreshold::SimpleMajority; Democracy::::inject_referendum( - 0.into(), + T::LaunchPeriod::get(), proposal_hash, vote_threshold, 0.into(), ); let referendum_index: ReferendumIndex = ReferendumCount::get() - 1; - let _ = T::Scheduler::schedule_named( - (DEMOCRACY_ID, referendum_index), - 0.into(), + T::Scheduler::schedule_named( + (DEMOCRACY_ID, referendum_index).encode(), + 1.into(), None, 63, + system::RawOrigin::Root.into(), Call::enact_proposal(proposal_hash, referendum_index).into(), - ); + ).map_err(|_| "failed to schedule named")?; Ok(referendum_index) } -fn account_vote() -> AccountVote> { +fn account_vote(b: BalanceOf) -> AccountVote> { let v = Vote { aye: true, conviction: Conviction::Locked1x, @@ -78,20 +93,10 @@ fn account_vote() -> AccountVote> { AccountVote::Standard { vote: v, - balance: BalanceOf::::one(), + balance: b, } } -fn open_activate_proxy(u: u32) -> Result { - let caller = funded_account::("caller", u); - let proxy = funded_account::("proxy", u); - - Democracy::::open_proxy(RawOrigin::Signed(proxy.clone()).into(), caller.clone())?; - Democracy::::activate_proxy(RawOrigin::Signed(caller).into(), proxy.clone())?; - - Ok(proxy) -} - benchmarks! { _ { } @@ -103,116 +108,189 @@ benchmarks! { add_proposal::(i)?; } + assert_eq!(Democracy::::public_props().len(), p as usize, "Proposals not created."); + let caller = funded_account::("caller", 0); let proposal_hash: T::Hash = T::Hashing::hash_of(&p); let value = T::MinimumDeposit::get(); }: _(RawOrigin::Signed(caller), proposal_hash, value.into()) + verify { + assert_eq!(Democracy::::public_props().len(), (p + 1) as usize, "Proposals not created."); + } second { let s in 0 .. MAX_SECONDERS; + let caller = funded_account::("caller", 0); + let proposal_hash = add_proposal::(s)?; + // Create s existing "seconds" for i in 0 .. s { let seconder = funded_account::("seconder", i); - Democracy::::second(RawOrigin::Signed(seconder).into(), 0)?; + Democracy::::second(RawOrigin::Signed(seconder).into(), 0, u32::max_value())?; } - let caller = funded_account::("caller", 0); - let proposal_hash = add_proposal::(s)?; - }: _(RawOrigin::Signed(caller), 0) + let deposits = Democracy::::deposit_of(0).ok_or("Proposal not created")?; + assert_eq!(deposits.0.len(), (s + 1) as usize, "Seconds not recorded"); + }: _(RawOrigin::Signed(caller), 0, u32::max_value()) + verify { + let deposits = Democracy::::deposit_of(0).ok_or("Proposal not created")?; + assert_eq!(deposits.0.len(), (s + 2) as usize, "`second` benchmark did not work"); + } - vote { + vote_new { let r in 1 .. MAX_REFERENDUMS; let caller = funded_account::("caller", 0); - let account_vote = account_vote::(); + let account_vote = account_vote::(100.into()); + // We need to create existing direct votes for i in 0 .. r { let ref_idx = add_referendum::(i)?; Democracy::::vote(RawOrigin::Signed(caller.clone()).into(), ref_idx, account_vote.clone())?; } + let votes = match VotingOf::::get(&caller) { + Voting::Direct { votes, .. } => votes, + _ => return Err("Votes are not direct"), + }; + assert_eq!(votes.len(), r as usize, "Votes were not recorded."); + + let referendum_index = add_referendum::(r)?; + + }: vote(RawOrigin::Signed(caller.clone()), referendum_index, account_vote) + verify { + let votes = match VotingOf::::get(&caller) { + Voting::Direct { votes, .. } => votes, + _ => return Err("Votes are not direct"), + }; + assert_eq!(votes.len(), (r + 1) as usize, "Vote was not recorded."); + } - let referendum_index = r - 1; - - }: _(RawOrigin::Signed(caller), referendum_index, account_vote) - - proxy_vote { + vote_existing { let r in 1 .. MAX_REFERENDUMS; - let caller = funded_account::("caller", r); - let proxy = open_activate_proxy::(r)?; - let account_vote = account_vote::(); + let caller = funded_account::("caller", 0); + let account_vote = account_vote::(100.into()); - for i in 0 .. r { + // We need to create existing direct votes + for i in 0 ..=r { let ref_idx = add_referendum::(i)?; Democracy::::vote(RawOrigin::Signed(caller.clone()).into(), ref_idx, account_vote.clone())?; } - - let referendum_index = r - 1; - - }: _(RawOrigin::Signed(proxy), referendum_index, account_vote) + let votes = match VotingOf::::get(&caller) { + Voting::Direct { votes, .. } => votes, + _ => return Err("Votes are not direct"), + }; + assert_eq!(votes.len(), (r + 1) as usize, "Votes were not recorded."); + + // Change vote from aye to nay + let nay = Vote { aye: false, conviction: Conviction::Locked1x }; + let new_vote = AccountVote::Standard { vote: nay, balance: 1000.into() }; + let referendum_index = Democracy::::referendum_count() - 1; + + // This tests when a user changes a vote + }: vote(RawOrigin::Signed(caller.clone()), referendum_index, new_vote) + verify { + let votes = match VotingOf::::get(&caller) { + Voting::Direct { votes, .. } => votes, + _ => return Err("Votes are not direct"), + }; + assert_eq!(votes.len(), (r + 1) as usize, "Vote was incorrectly added"); + let referendum_info = Democracy::::referendum_info(referendum_index) + .ok_or("referendum doesn't exist")?; + let tally = match referendum_info { + ReferendumInfo::Ongoing(r) => r.tally, + _ => return Err("referendum not ongoing"), + }; + assert_eq!(tally.nays, 1000.into(), "changed vote was not recorded"); + } emergency_cancel { - let u in 1 .. MAX_USERS; - - let referendum_index = add_referendum::(u)?; + let r in 1 .. MAX_REFERENDUMS; let origin = T::CancellationOrigin::successful_origin(); + + // Create and cancel a bunch of referendums + for i in 0 .. r { + let ref_idx = add_referendum::(i)?; + let call = Call::::emergency_cancel(ref_idx); + call.dispatch_bypass_filter(origin.clone())?; + } + + // Lets now measure one more + let referendum_index = add_referendum::(r)?; let call = Call::::emergency_cancel(referendum_index); - }: { - let _ = call.dispatch(origin)?; + assert!(Democracy::::referendum_status(referendum_index).is_ok()); + }: { call.dispatch_bypass_filter(origin)? } + verify { + // Referendum has been canceled + assert!(Democracy::::referendum_status(referendum_index).is_err()); } + // Worst case scenario, we external propose a previously blacklisted proposal external_propose { - let u in 1 .. MAX_USERS; + let p in 1 .. MAX_PROPOSALS; + let v in 1 .. MAX_VETOERS as u32; let origin = T::ExternalOrigin::successful_origin(); - let proposal_hash = T::Hashing::hash_of(&u); + let proposal_hash = T::Hashing::hash_of(&p); + // Add proposal to blacklist with block number 0 + Blacklist::::insert( + proposal_hash, + (T::BlockNumber::zero(), vec![T::AccountId::default(); v as usize]) + ); + let call = Call::::external_propose(proposal_hash); - }: { - let _ = call.dispatch(origin)?; + }: { call.dispatch_bypass_filter(origin)? } + verify { + // External proposal created + ensure!(>::exists(), "External proposal didn't work"); } external_propose_majority { - let u in 1 .. MAX_USERS; + let p in 1 .. MAX_PROPOSALS; let origin = T::ExternalMajorityOrigin::successful_origin(); - let proposal_hash = T::Hashing::hash_of(&u); + let proposal_hash = T::Hashing::hash_of(&p); let call = Call::::external_propose_majority(proposal_hash); - - }: { - let _ = call.dispatch(origin)?; + }: { call.dispatch_bypass_filter(origin)? } + verify { + // External proposal created + ensure!(>::exists(), "External proposal didn't work"); } external_propose_default { - let u in 1 .. MAX_USERS; + let p in 1 .. MAX_PROPOSALS; let origin = T::ExternalDefaultOrigin::successful_origin(); - let proposal_hash = T::Hashing::hash_of(&u); + let proposal_hash = T::Hashing::hash_of(&p); let call = Call::::external_propose_default(proposal_hash); - - }: { - let _ = call.dispatch(origin)?; + }: { call.dispatch_bypass_filter(origin)? } + verify { + // External proposal created + ensure!(>::exists(), "External proposal didn't work"); } fast_track { - let u in 1 .. MAX_USERS; + let p in 1 .. MAX_PROPOSALS; let origin_propose = T::ExternalDefaultOrigin::successful_origin(); - let proposal_hash: T::Hash = T::Hashing::hash_of(&u); + let proposal_hash: T::Hash = T::Hashing::hash_of(&p); Democracy::::external_propose_default(origin_propose, proposal_hash.clone())?; + // NOTE: Instant origin may invoke a little bit more logic, but may not always succeed. let origin_fast_track = T::FastTrackOrigin::successful_origin(); let voting_period = T::FastTrackVotingPeriod::get(); let delay = 0; let call = Call::::fast_track(proposal_hash, voting_period.into(), delay.into()); - }: { - let _ = call.dispatch(origin_fast_track)?; + }: { call.dispatch_bypass_filter(origin_fast_track)? } + verify { + assert_eq!(Democracy::::referendum_count(), 1, "referendum not created") } veto_external { // Existing veto-ers - let v in 0 .. MAX_VETOERS; + let v in 0 .. MAX_VETOERS as u32; let proposal_hash: T::Hash = T::Hashing::hash_of(&v); @@ -223,85 +301,229 @@ benchmarks! { for i in 0 .. v { vetoers.push(account("vetoer", i, SEED)); } + vetoers.sort(); Blacklist::::insert(proposal_hash, (T::BlockNumber::zero(), vetoers)); let call = Call::::veto_external(proposal_hash); let origin = T::VetoOrigin::successful_origin(); - }: { - let _ = call.dispatch(origin)?; + ensure!(NextExternal::::get().is_some(), "no external proposal"); + }: { call.dispatch_bypass_filter(origin)? } + verify { + assert!(NextExternal::::get().is_none()); + let (_, new_vetoers) = >::get(&proposal_hash).ok_or("no blacklist")?; + assert_eq!(new_vetoers.len(), (v + 1) as usize, "vetoers not added"); } cancel_referendum { - let u in 1 .. MAX_USERS; - - let referendum_index = add_referendum::(u)?; + let r in 0 .. MAX_REFERENDUMS; + // Should have no effect on the execution time. + for i in 0..r { + add_referendum::(i)?; + } + let referendum_index = add_referendum::(r)?; }: _(RawOrigin::Root, referendum_index) cancel_queued { - let u in 1 .. MAX_USERS; - - let referendum_index = add_referendum::(u)?; + let r in 1 .. MAX_REFERENDUMS; + // Should have no effect on the execution time. + for i in 0..r { + add_referendum::(i)?; + } + let referendum_index = add_referendum::(r)?; }: _(RawOrigin::Root, referendum_index) - open_proxy { - let u in 1 .. MAX_USERS; + // Note that we have a separate benchmark for `launch_next` + on_initialize_external { + let r in 0 .. MAX_REFERENDUMS; - let caller: T::AccountId = funded_account::("caller", u); - let proxy: T::AccountId = funded_account::("proxy", u); + for i in 0..r { + add_referendum::(i)?; + } - }: _(RawOrigin::Signed(proxy), caller) + assert_eq!(Democracy::::referendum_count(), r, "referenda not created"); - activate_proxy { - let u in 1 .. MAX_USERS; + // Launch external + LastTabledWasExternal::put(false); - let caller: T::AccountId = funded_account::("caller", u); - let proxy: T::AccountId = funded_account::("proxy", u); - Democracy::::open_proxy(RawOrigin::Signed(proxy.clone()).into(), caller.clone())?; + let origin = T::ExternalMajorityOrigin::successful_origin(); + let proposal_hash = T::Hashing::hash_of(&r); + let call = Call::::external_propose_majority(proposal_hash); + call.dispatch_bypass_filter(origin)?; + // External proposal created + ensure!(>::exists(), "External proposal didn't work"); - }: _(RawOrigin::Signed(caller), proxy) + let block_number = T::LaunchPeriod::get(); - close_proxy { - let u in 1 .. MAX_USERS; + }: { Democracy::::on_initialize(block_number) } + verify { + // One extra because of next external + assert_eq!(Democracy::::referendum_count(), r + 1, "referenda not created"); + ensure!(!>::exists(), "External wasn't taken"); - let proxy = open_activate_proxy::(u)?; + // All but the new next external should be finished + for i in 0 .. r { + if let Some(value) = ReferendumInfoOf::::get(i) { + match value { + ReferendumInfo::Finished { .. } => (), + ReferendumInfo::Ongoing(_) => return Err("Referendum was not finished"), + } + } + } + } - }: _(RawOrigin::Signed(proxy)) + on_initialize_public { + let r in 1 .. MAX_REFERENDUMS; - deactivate_proxy { - let u in 1 .. MAX_USERS; + for i in 0..r { + add_referendum::(i)?; + } - let caller = funded_account::("caller", u); - let proxy = open_activate_proxy::(u)?; + assert_eq!(Democracy::::referendum_count(), r, "referenda not created"); - }: _(RawOrigin::Signed(caller), proxy) + // Launch public + LastTabledWasExternal::put(true); - delegate { - let u in 1 .. MAX_USERS; + let block_number = T::LaunchPeriod::get(); - let caller = funded_account::("caller", u); - let d: T::AccountId = funded_account::("delegate", u); - let balance = 1u32; + }: { Democracy::::on_initialize(block_number) } + verify { + // One extra because of next public + assert_eq!(Democracy::::referendum_count(), r + 1, "referenda not created"); - }: _(RawOrigin::Signed(caller), d.into(), Conviction::Locked1x, balance.into()) + // All should be finished + for i in 0 .. r { + if let Some(value) = ReferendumInfoOf::::get(i) { + match value { + ReferendumInfo::Finished { .. } => (), + ReferendumInfo::Ongoing(_) => return Err("Referendum was not finished"), + } + } + } + } - undelegate { + on_initialize_no_launch_no_maturing { let r in 1 .. MAX_REFERENDUMS; - let other = funded_account::("other", 0); - let account_vote = account_vote::(); + for i in 0..r { + add_referendum::(i)?; + } + + for (key, mut info) in ReferendumInfoOf::::iter() { + if let ReferendumInfo::Ongoing(ref mut status) = info { + status.end += 100.into(); + } + ReferendumInfoOf::::insert(key, info); + } + + assert_eq!(Democracy::::referendum_count(), r, "referenda not created"); + assert_eq!(Democracy::::lowest_unbaked(), 0, "invalid referenda init"); + }: { Democracy::::on_initialize(0.into()) } + verify { + // All should be on going for i in 0 .. r { + if let Some(value) = ReferendumInfoOf::::get(i) { + match value { + ReferendumInfo::Finished { .. } => return Err("Referendum has been finished"), + ReferendumInfo::Ongoing(_) => (), + } + } + } + } + + delegate { + let r in 1 .. MAX_REFERENDUMS; + + let initial_balance: BalanceOf = 100.into(); + let delegated_balance: BalanceOf = 1000.into(); + + let caller = funded_account::("caller", 0); + // Caller will initially delegate to `old_delegate` + let old_delegate: T::AccountId = funded_account::("old_delegate", r); + Democracy::::delegate( + RawOrigin::Signed(caller.clone()).into(), + old_delegate.clone(), + Conviction::Locked1x, + delegated_balance, + )?; + let (target, balance) = match VotingOf::::get(&caller) { + Voting::Delegating { target, balance, .. } => (target, balance), + _ => return Err("Votes are not direct"), + }; + assert_eq!(target, old_delegate, "delegation target didn't work"); + assert_eq!(balance, delegated_balance, "delegation balance didn't work"); + // Caller will now switch to `new_delegate` + let new_delegate: T::AccountId = funded_account::("new_delegate", r); + let account_vote = account_vote::(initial_balance); + // We need to create existing direct votes for the `new_delegate` + for i in 0..r { let ref_idx = add_referendum::(i)?; - Democracy::::vote(RawOrigin::Signed(other.clone()).into(), ref_idx, account_vote.clone())?; + Democracy::::vote(RawOrigin::Signed(new_delegate.clone()).into(), ref_idx, account_vote.clone())?; } + let votes = match VotingOf::::get(&new_delegate) { + Voting::Direct { votes, .. } => votes, + _ => return Err("Votes are not direct"), + }; + assert_eq!(votes.len(), r as usize, "Votes were not recorded."); + }: _(RawOrigin::Signed(caller.clone()), new_delegate.clone(), Conviction::Locked1x, delegated_balance) + verify { + let (target, balance) = match VotingOf::::get(&caller) { + Voting::Delegating { target, balance, .. } => (target, balance), + _ => return Err("Votes are not direct"), + }; + assert_eq!(target, new_delegate, "delegation target didn't work"); + assert_eq!(balance, delegated_balance, "delegation balance didn't work"); + let delegations = match VotingOf::::get(&new_delegate) { + Voting::Direct { delegations, .. } => delegations, + _ => return Err("Votes are not direct"), + }; + assert_eq!(delegations.capital, delegated_balance, "delegation was not recorded."); + } - let delegator = funded_account::("delegator", r); - let conviction = Conviction::Locked1x; - let balance = 1u32; + undelegate { + let r in 1 .. MAX_REFERENDUMS; - Democracy::::delegate(RawOrigin::Signed(delegator.clone()).into(), other.clone().into(), conviction, balance.into())?; + let initial_balance: BalanceOf = 100.into(); + let delegated_balance: BalanceOf = 1000.into(); - }: _(RawOrigin::Signed(delegator)) + let caller = funded_account::("caller", 0); + // Caller will delegate + let the_delegate: T::AccountId = funded_account::("delegate", r); + Democracy::::delegate( + RawOrigin::Signed(caller.clone()).into(), + the_delegate.clone(), + Conviction::Locked1x, + delegated_balance, + )?; + let (target, balance) = match VotingOf::::get(&caller) { + Voting::Delegating { target, balance, .. } => (target, balance), + _ => return Err("Votes are not direct"), + }; + assert_eq!(target, the_delegate, "delegation target didn't work"); + assert_eq!(balance, delegated_balance, "delegation balance didn't work"); + // We need to create votes direct votes for the `delegate` + let account_vote = account_vote::(initial_balance); + for i in 0..r { + let ref_idx = add_referendum::(i)?; + Democracy::::vote( + RawOrigin::Signed(the_delegate.clone()).into(), + ref_idx, + account_vote.clone() + )?; + } + let votes = match VotingOf::::get(&the_delegate) { + Voting::Direct { votes, .. } => votes, + _ => return Err("Votes are not direct"), + }; + assert_eq!(votes.len(), r as usize, "Votes were not recorded."); + }: _(RawOrigin::Signed(caller.clone())) + verify { + // Voting should now be direct + match VotingOf::::get(&caller) { + Voting::Direct { .. } => (), + _ => return Err("undelegation failed"), + } + } clear_public_proposals { let p in 0 .. MAX_PROPOSALS; @@ -316,131 +538,269 @@ benchmarks! { // Num of bytes in encoded proposal let b in 0 .. MAX_BYTES; - let caller = funded_account::("caller", b); - let encoded_proposal = vec![0; b as usize]; - }: _(RawOrigin::Signed(caller), encoded_proposal) + let caller = funded_account::("caller", 0); + let encoded_proposal = vec![1; b as usize]; + }: _(RawOrigin::Signed(caller), encoded_proposal.clone()) + verify { + let proposal_hash = T::Hashing::hash(&encoded_proposal[..]); + match Preimages::::get(proposal_hash) { + Some(PreimageStatus::Available { .. }) => (), + _ => return Err("preimage not available") + } + } note_imminent_preimage { // Num of bytes in encoded proposal let b in 0 .. MAX_BYTES; // d + 1 to include the one we are testing - let encoded_proposal = vec![0; b as usize]; + let encoded_proposal = vec![1; b as usize]; let proposal_hash = T::Hashing::hash(&encoded_proposal[..]); let block_number = T::BlockNumber::one(); Preimages::::insert(&proposal_hash, PreimageStatus::Missing(block_number)); - let caller = funded_account::("caller", b); - let encoded_proposal = vec![0; b as usize]; - }: _(RawOrigin::Signed(caller), encoded_proposal) + let caller = funded_account::("caller", 0); + let encoded_proposal = vec![1; b as usize]; + }: _(RawOrigin::Signed(caller), encoded_proposal.clone()) + verify { + let proposal_hash = T::Hashing::hash(&encoded_proposal[..]); + match Preimages::::get(proposal_hash) { + Some(PreimageStatus::Available { .. }) => (), + _ => return Err("preimage not available") + } + } reap_preimage { // Num of bytes in encoded proposal let b in 0 .. MAX_BYTES; - let encoded_proposal = vec![0; b as usize]; + let encoded_proposal = vec![1; b as usize]; let proposal_hash = T::Hashing::hash(&encoded_proposal[..]); - let caller = funded_account::("caller", b); - Democracy::::note_preimage(RawOrigin::Signed(caller.clone()).into(), encoded_proposal.clone())?; + let submitter = funded_account::("submitter", b); + Democracy::::note_preimage(RawOrigin::Signed(submitter.clone()).into(), encoded_proposal.clone())?; // We need to set this otherwise we get `Early` error. let block_number = T::VotingPeriod::get() + T::EnactmentPeriod::get() + T::BlockNumber::one(); System::::set_block_number(block_number.into()); - }: _(RawOrigin::Signed(caller), proposal_hash) + assert!(Preimages::::contains_key(proposal_hash)); + + let caller = funded_account::("caller", 0); + }: _(RawOrigin::Signed(caller), proposal_hash.clone(), u32::max_value()) + verify { + let proposal_hash = T::Hashing::hash(&encoded_proposal[..]); + assert!(!Preimages::::contains_key(proposal_hash)); + } + + // Test when unlock will remove locks + unlock_remove { + let r in 1 .. MAX_REFERENDUMS; - unlock { - let u in 1 .. MAX_USERS; + let locker = funded_account::("locker", 0); + // Populate votes so things are locked + let base_balance: BalanceOf = 100.into(); + let small_vote = account_vote::(base_balance); + // Vote and immediately unvote + for i in 0 .. r { + let ref_idx = add_referendum::(i)?; + Democracy::::vote(RawOrigin::Signed(locker.clone()).into(), ref_idx, small_vote.clone())?; + Democracy::::remove_vote(RawOrigin::Signed(locker.clone()).into(), ref_idx)?; + } - let caller = funded_account::("caller", u); - let locked_until = T::BlockNumber::zero(); - Locks::::insert(&caller, locked_until); + let caller = funded_account::("caller", 0); + }: unlock(RawOrigin::Signed(caller), locker.clone()) + verify { + // Note that we may want to add a `get_lock` api to actually verify + let voting = VotingOf::::get(&locker); + assert_eq!(voting.locked_balance(), BalanceOf::::zero()); + } - T::Currency::extend_lock( - DEMOCRACY_ID, - &caller, - Bounded::max_value(), - WithdrawReason::Transfer.into() - ); + // Test when unlock will set a new value + unlock_set { + let r in 1 .. MAX_REFERENDUMS; + + let locker = funded_account::("locker", 0); + // Populate votes so things are locked + let base_balance: BalanceOf = 100.into(); + let small_vote = account_vote::(base_balance); + for i in 0 .. r { + let ref_idx = add_referendum::(i)?; + Democracy::::vote(RawOrigin::Signed(locker.clone()).into(), ref_idx, small_vote.clone())?; + } - let other = caller.clone(); + // Create a big vote so lock increases + let big_vote = account_vote::(base_balance * 10.into()); + let referendum_index = add_referendum::(r)?; + Democracy::::vote(RawOrigin::Signed(locker.clone()).into(), referendum_index, big_vote)?; - }: _(RawOrigin::Signed(caller), other) + let votes = match VotingOf::::get(&locker) { + Voting::Direct { votes, .. } => votes, + _ => return Err("Votes are not direct"), + }; + assert_eq!(votes.len(), (r + 1) as usize, "Votes were not recorded."); + + let voting = VotingOf::::get(&locker); + assert_eq!(voting.locked_balance(), base_balance * 10.into()); + + Democracy::::remove_vote(RawOrigin::Signed(locker.clone()).into(), referendum_index)?; + + let caller = funded_account::("caller", 0); + }: unlock(RawOrigin::Signed(caller), locker.clone()) + verify { + let votes = match VotingOf::::get(&locker) { + Voting::Direct { votes, .. } => votes, + _ => return Err("Votes are not direct"), + }; + assert_eq!(votes.len(), r as usize, "Vote was not removed"); + + let voting = VotingOf::::get(&locker); + // Note that we may want to add a `get_lock` api to actually verify + assert_eq!(voting.locked_balance(), base_balance); + } remove_vote { let r in 1 .. MAX_REFERENDUMS; let caller = funded_account::("caller", 0); - let account_vote = account_vote::(); + let account_vote = account_vote::(100.into()); for i in 0 .. r { let ref_idx = add_referendum::(i)?; Democracy::::vote(RawOrigin::Signed(caller.clone()).into(), ref_idx, account_vote.clone())?; } + let votes = match VotingOf::::get(&caller) { + Voting::Direct { votes, .. } => votes, + _ => return Err("Votes are not direct"), + }; + assert_eq!(votes.len(), r as usize, "Votes not created"); + let referendum_index = r - 1; - }: _(RawOrigin::Signed(caller), referendum_index) + }: _(RawOrigin::Signed(caller.clone()), referendum_index) + verify { + let votes = match VotingOf::::get(&caller) { + Voting::Direct { votes, .. } => votes, + _ => return Err("Votes are not direct"), + }; + assert_eq!(votes.len(), (r - 1) as usize, "Vote was not removed"); + } remove_other_vote { let r in 1 .. MAX_REFERENDUMS; let other = funded_account::("other", r); - let account_vote = account_vote::(); + let account_vote = account_vote::(100.into()); for i in 0 .. r { let ref_idx = add_referendum::(i)?; Democracy::::vote(RawOrigin::Signed(other.clone()).into(), ref_idx, account_vote.clone())?; } + let votes = match VotingOf::::get(&other) { + Voting::Direct { votes, .. } => votes, + _ => return Err("Votes are not direct"), + }; + assert_eq!(votes.len(), r as usize, "Votes not created"); + let referendum_index = r - 1; ReferendumInfoOf::::insert( referendum_index, ReferendumInfo::Finished { end: T::BlockNumber::zero(), approved: true } ); - let caller = funded_account::("caller", r); + let caller = funded_account::("caller", 0); System::::set_block_number(T::EnactmentPeriod::get() * 10u32.into()); - }: _(RawOrigin::Signed(caller), other, referendum_index) - - proxy_delegate { - let u in 1 .. MAX_USERS; - - let other: T::AccountId = account("other", u, SEED); - let proxy = open_activate_proxy::(u)?; - let conviction = Conviction::Locked1x; - let balance = 1u32; - - }: _(RawOrigin::Signed(proxy), other, conviction, balance.into()) + }: _(RawOrigin::Signed(caller), other.clone(), referendum_index) + verify { + let votes = match VotingOf::::get(&other) { + Voting::Direct { votes, .. } => votes, + _ => return Err("Votes are not direct"), + }; + assert_eq!(votes.len(), (r - 1) as usize, "Vote was not removed"); + } - proxy_undelegate { - let r in 1 .. MAX_REFERENDUMS; + enact_proposal_execute { + // Num of bytes in encoded proposal + let b in 0 .. MAX_BYTES; - let other = funded_account::("other", 0); - let account_vote = account_vote::(); + let proposer = funded_account::("proposer", 0); + let raw_call = Call::note_preimage(vec![1; b as usize]); + let generic_call: T::Proposal = raw_call.into(); + let encoded_proposal = generic_call.encode(); + let proposal_hash = T::Hashing::hash(&encoded_proposal[..]); + Democracy::::note_preimage(RawOrigin::Signed(proposer).into(), encoded_proposal)?; - for i in 0 .. r { - let ref_idx = add_referendum::(i)?; - Democracy::::vote(RawOrigin::Signed(other.clone()).into(), ref_idx, account_vote.clone())?; + match Preimages::::get(proposal_hash) { + Some(PreimageStatus::Available { .. }) => (), + _ => return Err("preimage not available") } + }: enact_proposal(RawOrigin::Root, proposal_hash, 0) + verify { + // Fails due to mismatched origin + assert_last_event::(RawEvent::Executed(0, false).into()); + } - let proxy = open_activate_proxy::(r)?; - let conviction = Conviction::Locked1x; - let balance = 1u32; - Democracy::::proxy_delegate(RawOrigin::Signed(proxy.clone()).into(), other, conviction, balance.into())?; - - }: _(RawOrigin::Signed(proxy)) - - proxy_remove_vote { - let u in 1 .. MAX_USERS; + enact_proposal_slash { + // Num of bytes in encoded proposal + let b in 0 .. MAX_BYTES; - let referendum_index = add_referendum::(u)?; - let account_vote = account_vote::(); - let proxy = open_activate_proxy::(u)?; + let proposer = funded_account::("proposer", 0); + // Random invalid bytes + let encoded_proposal = vec![200; b as usize]; + let proposal_hash = T::Hashing::hash(&encoded_proposal[..]); + Democracy::::note_preimage(RawOrigin::Signed(proposer).into(), encoded_proposal)?; - Democracy::::proxy_vote(RawOrigin::Signed(proxy.clone()).into(), referendum_index, account_vote)?; + match Preimages::::get(proposal_hash) { + Some(PreimageStatus::Available { .. }) => (), + _ => return Err("preimage not available") + } + }: { + assert_eq!( + Democracy::::enact_proposal(RawOrigin::Root.into(), proposal_hash, 0), + Err(Error::::PreimageInvalid.into()) + ); + } +} - }: _(RawOrigin::Signed(proxy), referendum_index) +#[cfg(test)] +mod tests { + use super::*; + use crate::tests::{new_test_ext, Test}; + use frame_support::assert_ok; + + #[test] + fn test_benchmarks() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_propose::()); + assert_ok!(test_benchmark_second::()); + assert_ok!(test_benchmark_vote_new::()); + assert_ok!(test_benchmark_vote_existing::()); + assert_ok!(test_benchmark_emergency_cancel::()); + assert_ok!(test_benchmark_external_propose::()); + assert_ok!(test_benchmark_external_propose_majority::()); + assert_ok!(test_benchmark_external_propose_default::()); + assert_ok!(test_benchmark_fast_track::()); + assert_ok!(test_benchmark_veto_external::()); + assert_ok!(test_benchmark_cancel_referendum::()); + assert_ok!(test_benchmark_cancel_queued::()); + assert_ok!(test_benchmark_on_initialize_external::()); + assert_ok!(test_benchmark_on_initialize_public::()); + assert_ok!(test_benchmark_on_initialize_no_launch_no_maturing::()); + assert_ok!(test_benchmark_delegate::()); + assert_ok!(test_benchmark_undelegate::()); + assert_ok!(test_benchmark_clear_public_proposals::()); + assert_ok!(test_benchmark_note_preimage::()); + assert_ok!(test_benchmark_note_imminent_preimage::()); + assert_ok!(test_benchmark_reap_preimage::()); + assert_ok!(test_benchmark_unlock_remove::()); + assert_ok!(test_benchmark_unlock_set::()); + assert_ok!(test_benchmark_remove_vote::()); + assert_ok!(test_benchmark_remove_other_vote::()); + assert_ok!(test_benchmark_enact_proposal_execute::()); + assert_ok!(test_benchmark_enact_proposal_slash::()); + }); + } } diff --git a/frame/democracy/src/conviction.rs b/frame/democracy/src/conviction.rs index a057ee2a357503d0a51648874b92a9006c3d1087..bb563e4b74830b24bf789454a3fe36de3a3e0e0c 100644 --- a/frame/democracy/src/conviction.rs +++ b/frame/democracy/src/conviction.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The conviction datatype. diff --git a/frame/democracy/src/lib.rs b/frame/democracy/src/lib.rs index b09f305c642477cc277653a5ddd33be68a4a9766..ae256f9d732c355348f4d15182e6d5d5187d74e1 100644 --- a/frame/democracy/src/lib.rs +++ b/frame/democracy/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Democracy Pallet //! @@ -51,8 +52,6 @@ //! account or an external origin) suggests that the system adopt. //! - **Referendum:** A proposal that is in the process of being voted on for //! either acceptance or rejection as a change to the system. -//! - **Proxy:** An account that has full voting power on behalf of a separate "Stash" account -//! that holds the funds. //! - **Delegation:** The act of granting your voting power to the decisions of another account for //! up to a certain conviction. //! @@ -92,23 +91,13 @@ //! - `reap_vote` - Remove some account's expired votes. //! - `unlock` - Redetermine the account's balance lock, potentially making tokens available. //! -//! Proxy administration: -//! - `activate_proxy` - Activates a proxy that is already open to the sender. -//! - `close_proxy` - Clears the proxy status, called by the proxy. -//! - `deactivate_proxy` - Deactivates a proxy back to the open status, called by the stash. -//! - `open_proxy` - Opens a proxy account on behalf of the sender. -//! -//! Proxy actions: -//! - `proxy_vote` - Votes in a referendum on behalf of a stash account. -//! - `proxy_unvote` - Cancel a previous vote, done on behalf of the voter by a proxy. -//! - `proxy_delegate` - Delegate voting power, done on behalf of the voter by a proxy. -//! - `proxy_undelegate` - Stop delegating voting power, done on behalf of the voter by a proxy. -//! //! Preimage actions: //! - `note_preimage` - Registers the preimage for an upcoming proposal, requires //! a deposit that is returned once the proposal is enacted. +//! - `note_preimage_operational` - same but provided by `T::OperationalPreimageOrigin`. //! - `note_imminent_preimage` - Registers the preimage for an upcoming proposal. //! Does not require a deposit, but the proposal must be in the dispatch queue. +//! - `note_imminent_preimage_operational` - same but provided by `T::OperationalPreimageOrigin`. //! - `reap_preimage` - Removes the preimage for an expired proposal. Will only //! work under the condition that it's the same account that noted it and //! after the voting period, OR it's a different account after the enactment period. @@ -168,14 +157,15 @@ use sp_runtime::{ DispatchResult, DispatchError, RuntimeDebug, traits::{Zero, Hash, Dispatchable, Saturating}, }; -use codec::{Ref, Encode, Decode}; +use codec::{Encode, Decode, Input}; use frame_support::{ decl_module, decl_storage, decl_event, decl_error, ensure, Parameter, - weights::{SimpleDispatchInfo, Weight, WeighData}, + weights::{Weight, DispatchClass}, traits::{ Currency, ReservableCurrency, LockableCurrency, WithdrawReason, LockIdentifier, Get, OnUnbalanced, BalanceStatus, schedule::Named as ScheduleNamed, EnsureOrigin - } + }, + dispatch::DispatchResultWithPostInfo, }; use frame_system::{self as system, ensure_signed, ensure_root}; @@ -186,7 +176,7 @@ mod types; pub use vote_threshold::{Approved, VoteThreshold}; pub use vote::{Vote, AccountVote, Voting}; pub use conviction::Conviction; -pub use types::{ReferendumInfo, ReferendumStatus, ProxyState, Tally, UnvoteScope, Delegations}; +pub use types::{ReferendumInfo, ReferendumStatus, Tally, UnvoteScope, Delegations}; #[cfg(test)] mod tests; @@ -196,6 +186,11 @@ pub mod benchmarking; const DEMOCRACY_ID: LockIdentifier = *b"democrac"; +/// The maximum number of vetoers on a single proposal used to compute Weight. +/// +/// NOTE: This is not enforced by any logic. +pub const MAX_VETOERS: Weight = 100; + /// A proposal index. pub type PropIndex = u32; @@ -206,6 +201,66 @@ type BalanceOf = <::Currency as Currency< = <::Currency as Currency<::AccountId>>::NegativeImbalance; +pub trait WeightInfo { + fn propose(p: u32, ) -> Weight; + fn second(s: u32, ) -> Weight; + fn vote_new(r: u32, ) -> Weight; + fn vote_existing(r: u32, ) -> Weight; + fn emergency_cancel(r: u32, ) -> Weight; + fn external_propose(p: u32, v: u32, ) -> Weight; + fn external_propose_majority(p: u32, ) -> Weight; + fn external_propose_default(p: u32, ) -> Weight; + fn fast_track(p: u32, ) -> Weight; + fn veto_external(v: u32, ) -> Weight; + fn cancel_referendum(r: u32, ) -> Weight; + fn cancel_queued(r: u32, ) -> Weight; + fn on_initialize_external(r: u32, ) -> Weight; + fn on_initialize_public(r: u32, ) -> Weight; + fn on_initialize_no_launch_no_maturing(r: u32, ) -> Weight; + fn delegate(r: u32, ) -> Weight; + fn undelegate(r: u32, ) -> Weight; + fn clear_public_proposals(p: u32, ) -> Weight; + fn note_preimage(b: u32, ) -> Weight; + fn note_imminent_preimage(b: u32, ) -> Weight; + fn reap_preimage(b: u32, ) -> Weight; + fn unlock_remove(r: u32, ) -> Weight; + fn unlock_set(r: u32, ) -> Weight; + fn remove_vote(r: u32, ) -> Weight; + fn remove_other_vote(r: u32, ) -> Weight; + fn enact_proposal_execute(b: u32, ) -> Weight; + fn enact_proposal_slash(b: u32, ) -> Weight; +} + +impl WeightInfo for () { + fn propose(_p: u32, ) -> Weight { 1_000_000_000 } + fn second(_s: u32, ) -> Weight { 1_000_000_000 } + fn vote_new(_r: u32, ) -> Weight { 1_000_000_000 } + fn vote_existing(_r: u32, ) -> Weight { 1_000_000_000 } + fn emergency_cancel(_r: u32, ) -> Weight { 1_000_000_000 } + fn external_propose(_p: u32, _v: u32, ) -> Weight { 1_000_000_000 } + fn external_propose_majority(_p: u32, ) -> Weight { 1_000_000_000 } + fn external_propose_default(_p: u32, ) -> Weight { 1_000_000_000 } + fn fast_track(_p: u32, ) -> Weight { 1_000_000_000 } + fn veto_external(_v: u32, ) -> Weight { 1_000_000_000 } + fn cancel_referendum(_r: u32, ) -> Weight { 1_000_000_000 } + fn cancel_queued(_r: u32, ) -> Weight { 1_000_000_000 } + fn on_initialize_external(_r: u32, ) -> Weight { 1_000_000_000 } + fn on_initialize_public(_r: u32, ) -> Weight { 1_000_000_000 } + fn on_initialize_no_launch_no_maturing(_r: u32, ) -> Weight { 1_000_000_000 } + fn delegate(_r: u32, ) -> Weight { 1_000_000_000 } + fn undelegate(_r: u32, ) -> Weight { 1_000_000_000 } + fn clear_public_proposals(_p: u32, ) -> Weight { 1_000_000_000 } + fn note_preimage(_b: u32, ) -> Weight { 1_000_000_000 } + fn note_imminent_preimage(_b: u32, ) -> Weight { 1_000_000_000 } + fn reap_preimage(_b: u32, ) -> Weight { 1_000_000_000 } + fn unlock_remove(_r: u32, ) -> Weight { 1_000_000_000 } + fn unlock_set(_r: u32, ) -> Weight { 1_000_000_000 } + fn remove_vote(_r: u32, ) -> Weight { 1_000_000_000 } + fn remove_other_vote(_r: u32, ) -> Weight { 1_000_000_000 } + fn enact_proposal_execute(_b: u32, ) -> Weight { 1_000_000_000 } + fn enact_proposal_slash(_b: u32, ) -> Weight { 1_000_000_000 } +} + pub trait Trait: frame_system::Trait + Sized { type Proposal: Parameter + Dispatchable + From>; type Event: From> + Into<::Event>; @@ -264,6 +319,11 @@ pub trait Trait: frame_system::Trait + Sized { type CancellationOrigin: EnsureOrigin; /// Origin for anyone able to veto proposals. + /// + /// # Warning + /// + /// The number of Vetoers for a proposal must be small, extrinsics are weighted according to + /// [MAX_VETOERS](./const.MAX_VETOERS.html) type VetoOrigin: EnsureOrigin; /// Period in blocks where an external proposal may not be re-submitted after being vetoed. @@ -272,11 +332,26 @@ pub trait Trait: frame_system::Trait + Sized { /// The amount of balance that must be deposited per byte of preimage stored. type PreimageByteDeposit: Get>; + /// An origin that can provide a preimage using operational extrinsics. + type OperationalPreimageOrigin: EnsureOrigin; + /// Handler for the unbalanced reduction when slashing a preimage deposit. type Slash: OnUnbalanced>; /// The Scheduler. - type Scheduler: ScheduleNamed; + type Scheduler: ScheduleNamed; + + /// Overarching type of all pallets origins. + type PalletsOrigin: From>; + + /// The maximum number of votes for an account. + /// + /// Also used to compute weight, an overly big value can + /// lead to extrinsic with very big weight: see `delegate` for instance. + type MaxVotes: Get; + + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; } #[derive(Clone, Encode, Decode, RuntimeDebug)] @@ -303,6 +378,14 @@ impl PreimageStatus as Democracy { // TODO: Refactor public proposal queue into its own pallet. @@ -312,8 +395,10 @@ decl_storage! { /// The public proposals. Unsorted. The second item is the proposal's hash. pub PublicProps get(fn public_props): Vec<(PropIndex, T::Hash, T::AccountId)>; /// Those who have locked a deposit. + /// + /// TWOX-NOTE: Safe, as increasing integer keys are safe. pub DepositOf get(fn deposit_of): - map hasher(twox_64_concat) PropIndex => Option<(BalanceOf, Vec)>; + map hasher(twox_64_concat) PropIndex => Option<(Vec, BalanceOf)>; /// Map of hashes to the proposal preimage, along with who registered it and their deposit. /// The block number is the block at which it was deposited. @@ -330,23 +415,23 @@ decl_storage! { pub LowestUnbaked get(fn lowest_unbaked) build(|_| 0 as ReferendumIndex): ReferendumIndex; /// Information concerning any given referendum. + /// + /// TWOX-NOTE: SAFE as indexes are not under an attacker’s control. pub ReferendumInfoOf get(fn referendum_info): map hasher(twox_64_concat) ReferendumIndex => Option>>; /// All votes for a particular voter. We store the balance for the number of votes that we /// have recorded. The second item is the total amount of delegations, that will be added. + /// + /// TWOX-NOTE: SAFE as `AccountId`s are crypto hashes anyway. pub VotingOf: map hasher(twox_64_concat) T::AccountId => Voting, T::AccountId, T::BlockNumber>; - /// Who is able to vote for whom. Value is the fund-holding account, key is the - /// vote-transaction-sending account. - // TODO: Refactor proxy into its own pallet. - // https://github.com/paritytech/substrate/issues/5322 - pub Proxy get(fn proxy): map hasher(twox_64_concat) T::AccountId => Option>; - /// Accounts for which there are locks in action which may be removed at some point in the /// future. The value is the block number at which the lock expires and may be removed. - pub Locks get(locks): map hasher(twox_64_concat) T::AccountId => Option; + /// + /// TWOX-NOTE: OK ― `AccountId` is a secure hash. + pub Locks get(fn locks): map hasher(twox_64_concat) T::AccountId => Option; /// True if the last referendum tabled was submitted externally. False if it was a public /// proposal. @@ -367,6 +452,11 @@ decl_storage! { /// Record of all proposals that have been subject to emergency cancellation. pub Cancellations: map hasher(identity) T::Hash => bool; + + /// Storage version of the pallet. + /// + /// New networks start with last version. + StorageVersion build(|_| Some(Releases::V1)): Option; } } @@ -420,8 +510,6 @@ decl_error! { ValueLow, /// Proposal does not exist ProposalMissing, - /// Not a proxy - NotProxy, /// Unknown index BadIndex, /// Cannot cancel the same proposal twice @@ -438,10 +526,6 @@ decl_error! { NoProposal, /// Identity may not veto a proposal twice AlreadyVetoed, - /// Already a proxy - AlreadyProxy, - /// Wrong proxy - WrongProxy, /// Not delegated NotDelegated, /// Preimage already noted @@ -464,12 +548,6 @@ decl_error! { NotLocked, /// The lock on the account to be unlocked has not yet expired. NotExpired, - /// A proxy-pairing was attempted to an account that was not open. - NotOpen, - /// A proxy-pairing was attempted to an account that was open to another account. - WrongOpen, - /// A proxy-de-pairing was attempted to an account that was not active. - NotActive, /// The given account did not vote on the referendum. NotVoter, /// The actor has no permission to conduct the action. @@ -491,6 +569,67 @@ decl_error! { InstantNotAllowed, /// Delegation to oneself makes no sense. Nonsense, + /// Invalid upper bound. + WrongUpperBound, + /// Maximum number of votes reached. + MaxVotesReached, + } +} + +/// Functions for calcuating the weight of some dispatchables. +mod weight_for { + use frame_support::{traits::Get, weights::Weight}; + use super::Trait; + + /// Calculate the weight for `delegate`. + /// - Db reads: 2*`VotingOf`, `balances locks` + /// - Db writes: 2*`VotingOf`, `balances locks` + /// - Db reads per votes: `ReferendumInfoOf` + /// - Db writes per votes: `ReferendumInfoOf` + /// - Base Weight: 65.78 + 8.229 * R µs + // NOTE: weight must cover an incorrect voting of origin with 100 votes. + pub fn delegate(votes: Weight) -> Weight { + T::DbWeight::get().reads_writes(votes.saturating_add(3), votes.saturating_add(3)) + .saturating_add(66_000_000) + .saturating_add(votes.saturating_mul(8_100_000)) + } + + /// Calculate the weight for `undelegate`. + /// - Db reads: 2*`VotingOf` + /// - Db writes: 2*`VotingOf` + /// - Db reads per votes: `ReferendumInfoOf` + /// - Db writes per votes: `ReferendumInfoOf` + /// - Base Weight: 33.29 + 8.104 * R µs + pub fn undelegate(votes: Weight) -> Weight { + T::DbWeight::get().reads_writes(votes.saturating_add(2), votes.saturating_add(2)) + .saturating_add(33_000_000) + .saturating_add(votes.saturating_mul(8_000_000)) + } + + /// Calculate the weight for `note_preimage`. + /// # + /// - Complexity: `O(E)` with E size of `encoded_proposal` (protected by a required deposit). + /// - Db reads: `Preimages` + /// - Db writes: `Preimages` + /// - Base Weight: 37.93 + .004 * b µs + /// # + pub fn note_preimage(encoded_proposal_len: Weight) -> Weight { + T::DbWeight::get().reads_writes(1, 1) + .saturating_add(38_000_000) + .saturating_add(encoded_proposal_len.saturating_mul(4_000)) + } + + /// Calculate the weight for `note_imminent_preimage`. + /// # + /// - Complexity: `O(E)` with E size of `encoded_proposal` (protected by a required deposit). + /// - Db reads: `Preimages` + /// - Db writes: `Preimages` + /// - Base Weight: 28.04 + .003 * b µs + /// # + pub fn note_imminent_preimage(encoded_proposal_len: Weight) -> Weight { + T::DbWeight::get().reads_writes(1, 1) + .saturating_add(28_000_000) + .saturating_add(encoded_proposal_len.saturating_mul(3_000)) } } @@ -523,13 +662,10 @@ decl_module! { /// The amount of balance that must be deposited per byte of preimage stored. const PreimageByteDeposit: BalanceOf = T::PreimageByteDeposit::get(); - fn deposit_event() = default; + /// The maximum number of votes for an account. + const MaxVotes: u32 = T::MaxVotes::get(); - fn on_runtime_upgrade() -> Weight { - Self::migrate(); - - SimpleDispatchInfo::default().weigh_data(()) - } + fn deposit_event() = default; /// Propose a sensitive action to be taken. /// @@ -542,25 +678,24 @@ decl_module! { /// Emits `Proposed`. /// /// # - /// - `O(P)` - /// - P is the number proposals in the `PublicProps` vec. - /// - Two DB changes, one DB entry. + /// - Complexity: `O(1)` + /// - Db reads: `PublicPropCount`, `PublicProps` + /// - Db writes: `PublicPropCount`, `PublicProps`, `DepositOf` + /// ------------------- + /// Base Weight: 42.58 + .127 * P µs with `P` the number of proposals `PublicProps` /// # - #[weight = SimpleDispatchInfo::FixedNormal(5_000_000)] - fn propose(origin, - proposal_hash: T::Hash, - #[compact] value: BalanceOf - ) { + #[weight = 50_000_000 + T::DbWeight::get().reads_writes(2, 3)] + fn propose(origin, proposal_hash: T::Hash, #[compact] value: BalanceOf) { let who = ensure_signed(origin)?; ensure!(value >= T::MinimumDeposit::get(), Error::::ValueLow); + T::Currency::reserve(&who, value)?; let index = Self::public_prop_count(); PublicPropCount::put(index + 1); - >::insert(index, (value, &[&who][..])); + >::insert(index, (&[&who][..], value)); - let new_prop = (index, proposal_hash, who); - >::append_or_put(&[Ref::from(&new_prop)][..]); + >::append((index, proposal_hash, who)); Self::deposit_event(RawEvent::Proposed(index, value)); } @@ -571,19 +706,30 @@ decl_module! { /// must have funds to cover the deposit, equal to the original deposit. /// /// - `proposal`: The index of the proposal to second. + /// - `seconds_upper_bound`: an upper bound on the current number of seconds on this + /// proposal. Extrinsic is weighted according to this value with no refund. /// /// # - /// - `O(S)`. - /// - S is the number of seconds a proposal already has. - /// - One DB entry. + /// - Complexity: `O(S)` where S is the number of seconds a proposal already has. + /// - Db reads: `DepositOf` + /// - Db writes: `DepositOf` + /// --------- + /// - Base Weight: 22.28 + .229 * S µs /// # - #[weight = SimpleDispatchInfo::FixedNormal(5_000_000)] - fn second(origin, #[compact] proposal: PropIndex) { + #[weight = 23_000_000 + .saturating_add(230_000.saturating_mul(Weight::from(*seconds_upper_bound))) + .saturating_add(T::DbWeight::get().reads_writes(1, 1)) + ] + fn second(origin, #[compact] proposal: PropIndex, #[compact] seconds_upper_bound: u32) { let who = ensure_signed(origin)?; + + let seconds = Self::len_of_deposit_of(proposal) + .ok_or_else(|| Error::::ProposalMissing)?; + ensure!(seconds <= seconds_upper_bound, Error::::WrongUpperBound); let mut deposit = Self::deposit_of(proposal) .ok_or(Error::::ProposalMissing)?; - T::Currency::reserve(&who, deposit.0)?; - deposit.1.push(who); + T::Currency::reserve(&who, deposit.1)?; + deposit.0.push(who); >::insert(proposal, deposit); } @@ -596,11 +742,16 @@ decl_module! { /// - `vote`: The vote configuration. /// /// # - /// - `O(R)`. - /// - R is the number of referendums the voter has voted on. - /// - One DB change, one DB entry. + /// - Complexity: `O(R)` where R is the number of referendums the voter has voted on. + /// weight is charged as if maximum votes. + /// - Db reads: `ReferendumInfoOf`, `VotingOf`, `balances locks` + /// - Db writes: `ReferendumInfoOf`, `VotingOf`, `balances locks` + /// -------------------- + /// - Base Weight: + /// - Vote New: 49.24 + .333 * R µs + /// - Vote Existing: 49.94 + .343 * R µs /// # - #[weight = SimpleDispatchInfo::FixedNormal(200_000)] + #[weight = 50_000_000 + 350_000 * Weight::from(T::MaxVotes::get()) + T::DbWeight::get().reads_writes(3, 3)] fn vote(origin, #[compact] ref_index: ReferendumIndex, vote: AccountVote>, @@ -609,28 +760,6 @@ decl_module! { Self::try_vote(&who, ref_index, vote) } - /// Vote in a referendum on behalf of a stash. If `vote.is_aye()`, the vote is to enact - /// the proposal; otherwise it is a vote to keep the status quo. - /// - /// The dispatch origin of this call must be _Signed_. - /// - /// - `ref_index`: The index of the referendum to proxy vote for. - /// - `vote`: The vote configuration. - /// - /// # - /// - `O(1)`. - /// - One DB change, one DB entry. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(200_000)] - fn proxy_vote(origin, - #[compact] ref_index: ReferendumIndex, - vote: AccountVote>, - ) -> DispatchResult { - let who = ensure_signed(origin)?; - let voter = Self::proxy(who).and_then(|a| a.as_active()).ok_or(Error::::NotProxy)?; - Self::try_vote(&voter, ref_index, vote) - } - /// Schedule an emergency cancellation of a referendum. Cannot happen twice to the same /// referendum. /// @@ -639,9 +768,13 @@ decl_module! { /// -`ref_index`: The index of the referendum to cancel. /// /// # - /// - `O(1)`. + /// - Complexity: `O(1)`. + /// - Db reads: `ReferendumInfoOf`, `Cancellations` + /// - Db writes: `ReferendumInfoOf`, `Cancellations` + /// ------------- + /// - Base Weight: 34.25 µs /// # - #[weight = SimpleDispatchInfo::FixedOperational(500_000)] + #[weight = (35_000_000 + T::DbWeight::get().reads_writes(2, 2), DispatchClass::Operational)] fn emergency_cancel(origin, ref_index: ReferendumIndex) { T::CancellationOrigin::ensure_origin(origin)?; @@ -661,10 +794,13 @@ decl_module! { /// - `proposal_hash`: The preimage hash of the proposal. /// /// # - /// - `O(1)`. - /// - One DB change. + /// - Complexity `O(V)` with V number of vetoers in the blacklist of proposal. + /// Decoding vec of length V. Charged as maximum + /// - Db reads: `NextExternal`, `Blacklist` + /// - Db writes: `NextExternal` + /// - Base Weight: 13.8 + .106 * V µs /// # - #[weight = SimpleDispatchInfo::FixedNormal(5_000_000)] + #[weight = 15_000_000 + 110_000 * MAX_VETOERS + T::DbWeight::get().reads_writes(2, 1)] fn external_propose(origin, proposal_hash: T::Hash) { T::ExternalOrigin::ensure_origin(origin)?; ensure!(!>::exists(), Error::::DuplicateProposal); @@ -688,10 +824,11 @@ decl_module! { /// pre-scheduled `external_propose` call. /// /// # - /// - `O(1)`. - /// - One DB change. + /// - Complexity: `O(1)` + /// - Db write: `NextExternal` + /// - Base Weight: 3.065 µs /// # - #[weight = SimpleDispatchInfo::FixedNormal(5_000_000)] + #[weight = 3_100_000 + T::DbWeight::get().writes(1)] fn external_propose_majority(origin, proposal_hash: T::Hash) { T::ExternalMajorityOrigin::ensure_origin(origin)?; >::put((proposal_hash, VoteThreshold::SimpleMajority)); @@ -708,10 +845,11 @@ decl_module! { /// pre-scheduled `external_propose` call. /// /// # - /// - `O(1)`. - /// - One DB change. + /// - Complexity: `O(1)` + /// - Db write: `NextExternal` + /// - Base Weight: 3.087 µs /// # - #[weight = SimpleDispatchInfo::FixedNormal(5_000_000)] + #[weight = 3_100_000 + T::DbWeight::get().writes(1)] fn external_propose_default(origin, proposal_hash: T::Hash) { T::ExternalDefaultOrigin::ensure_origin(origin)?; >::put((proposal_hash, VoteThreshold::SuperMajorityAgainst)); @@ -732,11 +870,12 @@ decl_module! { /// Emits `Started`. /// /// # - /// - One DB clear. - /// - One DB change. - /// - One extra DB entry. + /// - Complexity: `O(1)` + /// - Db reads: `NextExternal`, `ReferendumCount` + /// - Db writes: `NextExternal`, `ReferendumCount`, `ReferendumInfoOf` + /// - Base Weight: 30.1 µs /// # - #[weight = SimpleDispatchInfo::FixedNormal(200_000)] + #[weight = 30_000_000 + T::DbWeight::get().reads_writes(2, 3)] fn fast_track(origin, proposal_hash: T::Hash, voting_period: T::BlockNumber, @@ -781,13 +920,13 @@ decl_module! { /// Emits `Vetoed`. /// /// # - /// - Two DB entries. - /// - One DB clear. - /// - Performs a binary search on `existing_vetoers` which should not - /// be very large. - /// - O(log v), v is number of `existing_vetoers` + /// - Complexity: `O(V + log(V))` where V is number of `existing vetoers` + /// Performs a binary search on `existing_vetoers` which should not be very large. + /// - Db reads: `NextExternal`, `Blacklist` + /// - Db writes: `NextExternal`, `Blacklist` + /// - Base Weight: 29.87 + .188 * V µs /// # - #[weight = SimpleDispatchInfo::FixedNormal(200_000)] + #[weight = 30_000_000 + 180_000 * MAX_VETOERS + T::DbWeight::get().reads_writes(2, 2)] fn veto_external(origin, proposal_hash: T::Hash) { let who = T::VetoOrigin::ensure_origin(origin)?; @@ -818,9 +957,11 @@ decl_module! { /// - `ref_index`: The index of the referendum to cancel. /// /// # - /// - `O(1)`. + /// - Complexity: `O(1)`. + /// - Db writes: `ReferendumInfoOf` + /// - Base Weight: 21.57 µs /// # - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + #[weight = (22_000_000 + T::DbWeight::get().writes(1), DispatchClass::Operational)] fn cancel_referendum(origin, #[compact] ref_index: ReferendumIndex) { ensure_root(origin)?; Self::internal_cancel_referendum(ref_index); @@ -833,93 +974,24 @@ decl_module! { /// - `which`: The index of the referendum to cancel. /// /// # - /// - One DB change. - /// - O(d) where d is the items in the dispatch queue. + /// - `O(D)` where `D` is the items in the dispatch queue. Weighted as `D = 10`. + /// - Db reads: `scheduler lookup`, scheduler agenda` + /// - Db writes: `scheduler lookup`, scheduler agenda` + /// - Base Weight: 36.78 + 3.277 * D µs /// # - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + #[weight = (68_000_000 + T::DbWeight::get().reads_writes(2, 2), DispatchClass::Operational)] fn cancel_queued(origin, which: ReferendumIndex) { ensure_root(origin)?; - T::Scheduler::cancel_named((DEMOCRACY_ID, which)) + T::Scheduler::cancel_named((DEMOCRACY_ID, which).encode()) .map_err(|_| Error::::ProposalMissing)?; } + /// Weight: see `begin_block` fn on_initialize(n: T::BlockNumber) -> Weight { - if let Err(e) = Self::begin_block(n) { + Self::begin_block(n).unwrap_or_else(|e| { sp_runtime::print(e); - } - - SimpleDispatchInfo::default().weigh_data(()) - } - - /// Specify a proxy that is already open to us. Called by the stash. - /// - /// NOTE: Used to be called `set_proxy`. - /// - /// The dispatch origin of this call must be _Signed_. - /// - /// - `proxy`: The account that will be activated as proxy. - /// - /// # - /// - One extra DB entry. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(100_000)] - fn activate_proxy(origin, proxy: T::AccountId) { - let who = ensure_signed(origin)?; - Proxy::::try_mutate(&proxy, |a| match a.take() { - None => Err(Error::::NotOpen), - Some(ProxyState::Active(_)) => Err(Error::::AlreadyProxy), - Some(ProxyState::Open(x)) if &x == &who => { - *a = Some(ProxyState::Active(who)); - Ok(()) - } - Some(ProxyState::Open(_)) => Err(Error::::WrongOpen), - })?; - } - - /// Clear the proxy. Called by the proxy. - /// - /// NOTE: Used to be called `resign_proxy`. - /// - /// The dispatch origin of this call must be _Signed_. - /// - /// # - /// - One DB clear. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(100_000)] - fn close_proxy(origin) { - let who = ensure_signed(origin)?; - Proxy::::mutate(&who, |a| { - if a.is_some() { - system::Module::::dec_ref(&who); - } - *a = None; - }); - } - - /// Deactivate the proxy, but leave open to this account. Called by the stash. - /// - /// The proxy must already be active. - /// - /// NOTE: Used to be called `remove_proxy`. - /// - /// The dispatch origin of this call must be _Signed_. - /// - /// - `proxy`: The account that will be deactivated as proxy. - /// - /// # - /// - One DB clear. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(100_000)] - fn deactivate_proxy(origin, proxy: T::AccountId) { - let who = ensure_signed(origin)?; - Proxy::::try_mutate(&proxy, |a| match a.take() { - None | Some(ProxyState::Open(_)) => Err(Error::::NotActive), - Some(ProxyState::Active(x)) if &x == &who => { - *a = Some(ProxyState::Open(who)); - Ok(()) - } - Some(ProxyState::Active(_)) => Err(Error::::WrongProxy), - })?; + 0 + }) } /// Delegate the voting power (with some given conviction) of the sending account. @@ -941,11 +1013,26 @@ decl_module! { /// Emits `Delegated`. /// /// # + /// - Complexity: `O(R)` where R is the number of referendums the voter delegating to has + /// voted on. Weight is charged as if maximum votes. + /// - Db reads: 2*`VotingOf`, `balances locks` + /// - Db writes: 2*`VotingOf`, `balances locks` + /// - Db reads per votes: `ReferendumInfoOf` + /// - Db writes per votes: `ReferendumInfoOf` + /// - Base Weight: 65.78 + 8.229 * R µs + // NOTE: weight must cover an incorrect voting of origin with 100 votes. /// # - #[weight = SimpleDispatchInfo::FixedNormal(500_000)] - pub fn delegate(origin, to: T::AccountId, conviction: Conviction, balance: BalanceOf) { + #[weight = weight_for::delegate::(T::MaxVotes::get().into())] + pub fn delegate( + origin, + to: T::AccountId, + conviction: Conviction, + balance: BalanceOf + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; - Self::try_delegate(who, to, conviction, balance)?; + let votes = Self::try_delegate(who, to, conviction, balance)?; + + Ok(Some(weight_for::delegate::(votes.into())).into()) } /// Undelegate the voting power of the sending account. @@ -959,12 +1046,20 @@ decl_module! { /// Emits `Undelegated`. /// /// # - /// - O(1). + /// - Complexity: `O(R)` where R is the number of referendums the voter delegating to has + /// voted on. Weight is charged as if maximum votes. + /// - Db reads: 2*`VotingOf` + /// - Db writes: 2*`VotingOf` + /// - Db reads per votes: `ReferendumInfoOf` + /// - Db writes per votes: `ReferendumInfoOf` + /// - Base Weight: 33.29 + 8.104 * R µs + // NOTE: weight must cover an incorrect voting of origin with 100 votes. /// # - #[weight = SimpleDispatchInfo::FixedNormal(500_000)] - fn undelegate(origin) { + #[weight = weight_for::undelegate::(T::MaxVotes::get().into())] + fn undelegate(origin) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; - Self::try_undelegate(who)?; + let votes = Self::try_undelegate(who)?; + Ok(Some(weight_for::undelegate::(votes.into())).into()) } /// Clears all public proposals. @@ -973,12 +1068,12 @@ decl_module! { /// /// # /// - `O(1)`. - /// - One DB clear. + /// - Db writes: `PublicProps` + /// - Base Weight: 2.505 µs /// # - #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + #[weight = 2_500_000 + T::DbWeight::get().writes(1)] fn clear_public_proposals(origin) { ensure_root(origin)?; - >::kill(); } @@ -992,30 +1087,21 @@ decl_module! { /// Emits `PreimageNoted`. /// /// # - /// - Dependent on the size of `encoded_proposal` but protected by a - /// required deposit. + /// see `weight_for::note_preimage` /// # - #[weight = SimpleDispatchInfo::FixedNormal(100_000)] + #[weight = weight_for::note_preimage::((encoded_proposal.len() as u32).into())] fn note_preimage(origin, encoded_proposal: Vec) { - let who = ensure_signed(origin)?; - let proposal_hash = T::Hashing::hash(&encoded_proposal[..]); - ensure!(!>::contains_key(&proposal_hash), Error::::DuplicatePreimage); - - let deposit = >::from(encoded_proposal.len() as u32) - .saturating_mul(T::PreimageByteDeposit::get()); - T::Currency::reserve(&who, deposit)?; - - let now = >::block_number(); - let a = PreimageStatus::Available { - data: encoded_proposal, - provider: who.clone(), - deposit, - since: now, - expiry: None, - }; - >::insert(proposal_hash, a); + Self::note_preimage_inner(ensure_signed(origin)?, encoded_proposal)?; + } - Self::deposit_event(RawEvent::PreimageNoted(proposal_hash, who, deposit)); + /// Same as `note_preimage` but origin is `OperationalPreimageOrigin`. + #[weight = ( + weight_for::note_preimage::((encoded_proposal.len() as u32).into()), + DispatchClass::Operational, + )] + fn note_preimage_operational(origin, encoded_proposal: Vec) { + let who = T::OperationalPreimageOrigin::ensure_origin(origin)?; + Self::note_preimage_inner(who, encoded_proposal)?; } /// Register the preimage for an upcoming proposal. This requires the proposal to be @@ -1028,27 +1114,21 @@ decl_module! { /// Emits `PreimageNoted`. /// /// # - /// - Dependent on the size of `encoded_proposal` and length of dispatch queue. + /// see `weight_for::note_preimage` /// # - #[weight = SimpleDispatchInfo::FixedNormal(100_000)] + #[weight = weight_for::note_imminent_preimage::((encoded_proposal.len() as u32).into())] fn note_imminent_preimage(origin, encoded_proposal: Vec) { - let who = ensure_signed(origin)?; - let proposal_hash = T::Hashing::hash(&encoded_proposal[..]); - let status = Preimages::::get(&proposal_hash).ok_or(Error::::NotImminent)?; - let expiry = status.to_missing_expiry().ok_or(Error::::DuplicatePreimage)?; - - let now = >::block_number(); - let free = >::zero(); - let a = PreimageStatus::Available { - data: encoded_proposal, - provider: who.clone(), - deposit: Zero::zero(), - since: now, - expiry: Some(expiry), - }; - >::insert(proposal_hash, a); + Self::note_imminent_preimage_inner(ensure_signed(origin)?, encoded_proposal)?; + } - Self::deposit_event(RawEvent::PreimageNoted(proposal_hash, who, free)); + /// Same as `note_imminent_preimage` but origin is `OperationalPreimageOrigin`. + #[weight = ( + weight_for::note_imminent_preimage::((encoded_proposal.len() as u32).into()), + DispatchClass::Operational, + )] + fn note_imminent_preimage_operational(origin, encoded_proposal: Vec) { + let who = T::OperationalPreimageOrigin::ensure_origin(origin)?; + Self::note_imminent_preimage_inner(who, encoded_proposal)?; } /// Remove an expired proposal preimage and collect the deposit. @@ -1056,6 +1136,8 @@ decl_module! { /// The dispatch origin of this call must be _Signed_. /// /// - `proposal_hash`: The preimage hash of a proposal. + /// - `proposal_length_upper_bound`: an upper bound on length of the proposal. + /// Extrinsic is weighted according to this value with no refund. /// /// This will only work after `VotingPeriod` blocks from the time that the preimage was /// noted, if it's the same account doing it. If it's a different account, then it'll only @@ -1064,11 +1146,21 @@ decl_module! { /// Emits `PreimageReaped`. /// /// # - /// - One DB clear. + /// - Complexity: `O(D)` where D is length of proposal. + /// - Db reads: `Preimages` + /// - Db writes: `Preimages` + /// - Base Weight: 39.31 + .003 * b µs /// # - #[weight = SimpleDispatchInfo::FixedNormal(10_000)] - fn reap_preimage(origin, proposal_hash: T::Hash) { + #[weight = (39_000_000 + T::DbWeight::get().reads_writes(1, 1)) + .saturating_add(3_000.saturating_mul(Weight::from(*proposal_len_upper_bound)))] + fn reap_preimage(origin, proposal_hash: T::Hash, #[compact] proposal_len_upper_bound: u32) { let who = ensure_signed(origin)?; + + ensure!( + Self::pre_image_data_len(proposal_hash)? <= proposal_len_upper_bound, + Error::::WrongUpperBound, + ); + let (provider, deposit, since, expiry) = >::get(&proposal_hash) .and_then(|m| match m { PreimageStatus::Available { provider, deposit, since, expiry, .. } @@ -1094,38 +1186,20 @@ decl_module! { /// - `target`: The account to remove the lock on. /// /// # - /// - `O(1)`. + /// - Complexity `O(R)` with R number of vote of target. + /// - Db reads: `VotingOf`, `balances locks`, `target account` + /// - Db writes: `VotingOf`, `balances locks`, `target account` + /// - Base Weight: + /// - Unlock Remove: 42.96 + .048 * R + /// - Unlock Set: 37.63 + .327 * R /// # - #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + #[weight = 43_000_000 + 330_000 * Weight::from(T::MaxVotes::get()) + + T::DbWeight::get().reads_writes(3, 3)] fn unlock(origin, target: T::AccountId) { ensure_signed(origin)?; Self::update_lock(&target); } - /// Become a proxy. - /// - /// This must be called prior to a later `activate_proxy`. - /// - /// Origin must be a Signed. - /// - /// - `target`: The account whose votes will later be proxied. - /// - /// `close_proxy` must be called before the account can be destroyed. - /// - /// # - /// - One extra DB entry. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(100_000)] - fn open_proxy(origin, target: T::AccountId) { - let who = ensure_signed(origin)?; - Proxy::::mutate(&who, |a| { - if a.is_none() { - system::Module::::inc_ref(&who); - } - *a = Some(ProxyState::Open(target)); - }); - } - /// Remove a vote for a referendum. /// /// If: @@ -1153,8 +1227,12 @@ decl_module! { /// /// # /// - `O(R + log R)` where R is the number of referenda that `target` has voted on. + /// Weight is calculated for the maximum number of vote. + /// - Db reads: `ReferendumInfoOf`, `VotingOf` + /// - Db writes: `ReferendumInfoOf`, `VotingOf` + /// - Base Weight: 21.03 + .359 * R /// # - #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + #[weight = 21_000_000 + 360_000 * Weight::from(T::MaxVotes::get()) + T::DbWeight::get().reads_writes(2, 2)] fn remove_vote(origin, index: ReferendumIndex) -> DispatchResult { let who = ensure_signed(origin)?; Self::try_remove_vote(&who, index, UnvoteScope::Any) @@ -1175,8 +1253,12 @@ decl_module! { /// /// # /// - `O(R + log R)` where R is the number of referenda that `target` has voted on. + /// Weight is calculated for the maximum number of vote. + /// - Db reads: `ReferendumInfoOf`, `VotingOf` + /// - Db writes: `ReferendumInfoOf`, `VotingOf` + /// - Base Weight: 19.15 + .372 * R /// # - #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + #[weight = 19_000_000 + 370_000 * Weight::from(T::MaxVotes::get()) + T::DbWeight::get().reads_writes(2, 2)] fn remove_other_vote(origin, target: T::AccountId, index: ReferendumIndex) -> DispatchResult { let who = ensure_signed(origin)?; let scope = if target == who { UnvoteScope::Any } else { UnvoteScope::OnlyExpired }; @@ -1184,82 +1266,8 @@ decl_module! { Ok(()) } - /// Delegate the voting power (with some given conviction) of a proxied account. - /// - /// The balance delegated is locked for as long as it's delegated, and thereafter for the - /// time appropriate for the conviction's lock period. - /// - /// The dispatch origin of this call must be _Signed_, and the signing account must have - /// been set as the proxy account for `target`. - /// - /// - `target`: The account whole voting power shall be delegated and whose balance locked. - /// This account must either: - /// - be delegating already; or - /// - have no voting activity (if there is, then it will need to be removed/consolidated - /// through `reap_vote` or `unvote`). - /// - `to`: The account whose voting the `target` account's voting power will follow. - /// - `conviction`: The conviction that will be attached to the delegated votes. When the - /// account is undelegated, the funds will be locked for the corresponding period. - /// - `balance`: The amount of the account's balance to be used in delegating. This must - /// not be more than the account's current balance. - /// - /// Emits `Delegated`. - /// - /// # - /// # - #[weight = SimpleDispatchInfo::FixedNormal(500_000)] - pub fn proxy_delegate(origin, - to: T::AccountId, - conviction: Conviction, - balance: BalanceOf, - ) { - let who = ensure_signed(origin)?; - let target = Self::proxy(who).and_then(|a| a.as_active()).ok_or(Error::::NotProxy)?; - Self::try_delegate(target, to, conviction, balance)?; - } - - /// Undelegate the voting power of a proxied account. - /// - /// Tokens may be unlocked following once an amount of time consistent with the lock period - /// of the conviction with which the delegation was issued. - /// - /// The dispatch origin of this call must be _Signed_ and the signing account must be a - /// proxy for some other account which is currently delegating. - /// - /// Emits `Undelegated`. - /// - /// # - /// - O(1). - /// # - #[weight = SimpleDispatchInfo::FixedNormal(500_000)] - fn proxy_undelegate(origin) { - let who = ensure_signed(origin)?; - let target = Self::proxy(who).and_then(|a| a.as_active()).ok_or(Error::::NotProxy)?; - Self::try_undelegate(target)?; - } - - /// Remove a proxied vote for a referendum. - /// - /// Exactly equivalent to `remove_vote` except that it operates on the account that the - /// sender is a proxy for. - /// - /// The dispatch origin of this call must be _Signed_ and the signing account must be a - /// proxy for some other account which has a registered vote for the referendum of `index`. - /// - /// - `index`: The index of referendum of the vote to be removed. - /// - /// # - /// - `O(R + log R)` where R is the number of referenda that `target` has voted on. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(10_000)] - fn proxy_remove_vote(origin, index: ReferendumIndex) -> DispatchResult { - let who = ensure_signed(origin)?; - let target = Self::proxy(who).and_then(|a| a.as_active()).ok_or(Error::::NotProxy)?; - Self::try_remove_vote(&target, index, UnvoteScope::Any) - } - /// Enact a proposal from a referendum. For now we just make the weight be the maximum. - #[weight = SimpleDispatchInfo::MaxNormal] + #[weight = T::MaximumBlockWeight::get()] fn enact_proposal(origin, proposal_hash: T::Hash, index: ReferendumIndex) -> DispatchResult { ensure_root(origin)?; Self::do_enact_proposal(proposal_hash, index) @@ -1268,31 +1276,12 @@ decl_module! { } impl Module { - fn migrate() { - use frame_support::{Twox64Concat, migration::{StorageKeyIterator, remove_storage_prefix}}; - remove_storage_prefix(b"Democracy", b"VotesOf", &[]); - remove_storage_prefix(b"Democracy", b"VotersFor", &[]); - remove_storage_prefix(b"Democracy", b"Delegations", &[]); - for (who, (end, proposal_hash, threshold, delay)) - in StorageKeyIterator::< - ReferendumIndex, - (T::BlockNumber, T::Hash, VoteThreshold, T::BlockNumber), - Twox64Concat, - >::new(b"Democracy", b"ReferendumInfoOf").drain() - { - let status = ReferendumStatus { - end, proposal_hash, threshold, delay, tally: Tally::default() - }; - ReferendumInfoOf::::insert(who, ReferendumInfo::Ongoing(status)) - } - } - // exposed immutables. /// Get the amount locked in support of `proposal`; `None` if proposal isn't a valid proposal /// index. pub fn backing_for(proposal: PropIndex) -> Option> { - Self::deposit_of(proposal).map(|(d, l)| d * (l.len() as u32).into()) + Self::deposit_of(proposal).map(|(l, d)| d * (l.len() as u32).into()) } /// Get all referenda ready for tally at block `n`. @@ -1301,7 +1290,14 @@ impl Module { ) -> Vec<(ReferendumIndex, ReferendumStatus>)> { let next = Self::lowest_unbaked(); let last = Self::referendum_count(); - (next..last).into_iter() + Self::maturing_referenda_at_inner(n, next..last) + } + + fn maturing_referenda_at_inner( + n: T::BlockNumber, + range: core::ops::Range, + ) -> Vec<(ReferendumIndex, ReferendumStatus>)> { + range.into_iter() .map(|i| (i, Self::referendum_info(i))) .filter_map(|(i, maybe_info)| match maybe_info { Some(ReferendumInfo::Ongoing(status)) => Some((i, status)), @@ -1313,16 +1309,6 @@ impl Module { // Exposed mutables. - #[cfg(feature = "std")] - pub fn force_proxy(stash: T::AccountId, proxy: T::AccountId) { - Proxy::::mutate(&proxy, |o| { - if o.is_none() { - system::Module::::inc_ref(&proxy); - } - *o = Some(ProxyState::Active(stash)) - }) - } - /// Start a referendum. pub fn internal_start_referendum( proposal_hash: T::Hash, @@ -1378,7 +1364,10 @@ impl Module { } votes[i].1 = vote; } - Err(i) => votes.insert(i, (ref_index, vote)), + Err(i) => { + ensure!(votes.len() as u32 <= T::MaxVotes::get(), Error::::MaxVotesReached); + votes.insert(i, (ref_index, vote)); + } } // Shouldn't be possible to fail, but we handle it gracefully. status.tally.add(vote).ok_or(Error::::Overflow)?; @@ -1441,11 +1430,14 @@ impl Module { Ok(()) } - fn increase_upstream_delegation(who: &T::AccountId, amount: Delegations>) { + /// Return the number of votes for `who` + fn increase_upstream_delegation(who: &T::AccountId, amount: Delegations>) -> u32 { VotingOf::::mutate(who, |voting| match voting { - Voting::Delegating { delegations, .. } => + Voting::Delegating { delegations, .. } => { // We don't support second level delegating, so we don't need to do anything more. - *delegations = delegations.saturating_add(amount), + *delegations = delegations.saturating_add(amount); + 1 + }, Voting::Direct { votes, delegations, .. } => { *delegations = delegations.saturating_add(amount); for &(ref_index, account_vote) in votes.iter() { @@ -1457,15 +1449,19 @@ impl Module { ); } } + votes.len() as u32 } }) } - fn reduce_upstream_delegation(who: &T::AccountId, amount: Delegations>) { + /// Return the number of votes for `who` + fn reduce_upstream_delegation(who: &T::AccountId, amount: Delegations>) -> u32 { VotingOf::::mutate(who, |voting| match voting { - Voting::Delegating { delegations, .. } => - // We don't support second level delegating, so we don't need to do anything more. - *delegations = delegations.saturating_sub(amount), + Voting::Delegating { delegations, .. } => { + // We don't support second level delegating, so we don't need to do anything more. + *delegations = delegations.saturating_sub(amount); + 1 + } Voting::Direct { votes, delegations, .. } => { *delegations = delegations.saturating_sub(amount); for &(ref_index, account_vote) in votes.iter() { @@ -1477,20 +1473,23 @@ impl Module { ); } } + votes.len() as u32 } }) } /// Attempt to delegate `balance` times `conviction` of voting power from `who` to `target`. + /// + /// Return the upstream number of votes. fn try_delegate( who: T::AccountId, target: T::AccountId, conviction: Conviction, balance: BalanceOf, - ) -> DispatchResult { + ) -> Result { ensure!(who != target, Error::::Nonsense); ensure!(balance <= T::Currency::free_balance(&who), Error::::InsufficientFunds); - VotingOf::::try_mutate(&who, |voting| -> DispatchResult { + let votes = VotingOf::::try_mutate(&who, |voting| -> Result { let mut old = Voting::Delegating { balance, target: target.clone(), @@ -1511,7 +1510,7 @@ impl Module { voting.set_common(delegations, prior); } } - Self::increase_upstream_delegation(&target, conviction.votes(balance)); + let votes = Self::increase_upstream_delegation(&target, conviction.votes(balance)); // Extend the lock to `balance` (rather than setting it) since we don't know what other // votes are in place. T::Currency::extend_lock( @@ -1520,15 +1519,17 @@ impl Module { balance, WithdrawReason::Transfer.into() ); - Ok(()) + Ok(votes) })?; Self::deposit_event(Event::::Delegated(who, target)); - Ok(()) + Ok(votes) } /// Attempt to end the current delegation. - fn try_undelegate(who: T::AccountId) -> DispatchResult { - VotingOf::::try_mutate(&who, |voting| -> DispatchResult { + /// + /// Return the number of votes of upstream. + fn try_undelegate(who: T::AccountId) -> Result { + let votes = VotingOf::::try_mutate(&who, |voting| -> Result { let mut old = Voting::default(); sp_std::mem::swap(&mut old, voting); match old { @@ -1540,20 +1541,21 @@ impl Module { mut prior, } => { // remove any delegation votes to our current target. - Self::reduce_upstream_delegation(&target, conviction.votes(balance)); + let votes = Self::reduce_upstream_delegation(&target, conviction.votes(balance)); let now = system::Module::::block_number(); let lock_periods = conviction.lock_periods().into(); prior.accumulate(now + T::EnactmentPeriod::get() * lock_periods, balance); voting.set_common(delegations, prior); + + Ok(votes) } Voting::Direct { .. } => { - return Err(Error::::NotDelegating.into()) + Err(Error::::NotDelegating.into()) } } - Ok(()) })?; Self::deposit_event(Event::::Undelegated(who)); - Ok(()) + Ok(votes) } /// Rejig the lock on an account. It will never get more stringent (since that would indicate @@ -1623,7 +1625,7 @@ impl Module { let (prop_index, proposal, _) = public_props.swap_remove(winner_index); >::put(public_props); - if let Some((deposit, depositors)) = >::take(prop_index) { + if let Some((depositors, deposit)) = >::take(prop_index) { // refund depositors for d in &depositors { T::Currency::unreserve(d, deposit); @@ -1685,10 +1687,11 @@ impl Module { }); if T::Scheduler::schedule_named( - (DEMOCRACY_ID, index), + (DEMOCRACY_ID, index).encode(), when, None, 63, + system::RawOrigin::Root.into(), Call::enact_proposal(status.proposal_hash, index).into(), ).is_err() { frame_support::print("LOGIC ERROR: bake_referendum/schedule_named failed"); @@ -1702,19 +1705,179 @@ impl Module { } /// Current era is ending; we should finish up any proposals. - fn begin_block(now: T::BlockNumber) -> DispatchResult { + /// + /// + /// # + /// If a referendum is launched or maturing take full block weight. Otherwise: + /// - Complexity: `O(R)` where `R` is the number of unbaked referenda. + /// - Db reads: `LastTabledWasExternal`, `NextExternal`, `PublicProps`, `account`, + /// `ReferendumCount`, `LowestUnbaked` + /// - Db writes: `PublicProps`, `account`, `ReferendumCount`, `DepositOf`, `ReferendumInfoOf` + /// - Db reads per R: `DepositOf`, `ReferendumInfoOf` + /// - Base Weight: 58.58 + 10.9 * R µs + /// # + fn begin_block(now: T::BlockNumber) -> Result { + let mut weight = 60_000_000 + T::DbWeight::get().reads_writes(6, 5); + // pick out another public referendum if it's time. 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); + weight = T::MaximumBlockWeight::get(); } // tally up votes for any expiring referenda. - for (index, info) in Self::maturing_referenda_at(now).into_iter() { + let next = Self::lowest_unbaked(); + let last = Self::referendum_count(); + let r = Weight::from(last.saturating_sub(next)); + weight += 11_000_000 * r + T::DbWeight::get().reads(2 * r); + for (index, info) in Self::maturing_referenda_at_inner(now, next..last).into_iter() { let approved = Self::bake_referendum(now, index, info)?; ReferendumInfoOf::::insert(index, ReferendumInfo::Finished { end: now, approved }); + weight = T::MaximumBlockWeight::get(); } + + Ok(weight) + } + + /// Reads the length of account in DepositOf without getting the complete value in the runtime. + /// + /// Return 0 if no deposit for this proposal. + fn len_of_deposit_of(proposal: PropIndex) -> Option { + // DepositOf first tuple element is a vec, decoding its len is equivalent to decode a + // `Compact`. + decode_compact_u32_at(&>::hashed_key_for(proposal)) + } + + /// Check that pre image exists and its value is variant `PreimageStatus::Missing`. + /// + /// This check is done without getting the complete value in the runtime to avoid copying a big + /// value in the runtime. + fn check_pre_image_is_missing(proposal_hash: T::Hash) -> DispatchResult { + // To decode the enum variant we only need the first byte. + let mut buf = [0u8; 1]; + let key = >::hashed_key_for(proposal_hash); + let bytes = match sp_io::storage::read(&key, &mut buf, 0) { + Some(bytes) => bytes, + None => return Err(Error::::NotImminent.into()), + }; + // The value may be smaller that 1 byte. + let mut input = &buf[0..buf.len().min(bytes as usize)]; + + match input.read_byte() { + Ok(0) => Ok(()), // PreimageStatus::Missing is variant 0 + Ok(1) => Err(Error::::DuplicatePreimage.into()), + _ => { + sp_runtime::print("Failed to decode `PreimageStatus` variant"); + Err(Error::::NotImminent.into()) + } + } + } + + /// Check that pre image exists, its value is variant `PreimageStatus::Available` and decode + /// the length of `data: Vec` fields. + /// + /// This check is done without getting the complete value in the runtime to avoid copying a big + /// value in the runtime. + /// + /// If the pre image is missing variant or doesn't exist then the error `PreimageMissing` is + /// returned. + fn pre_image_data_len(proposal_hash: T::Hash) -> Result { + // To decode the `data` field of Available variant we need: + // * one byte for the variant + // * at most 5 bytes to decode a `Compact` + let mut buf = [0u8; 6]; + let key = >::hashed_key_for(proposal_hash); + let bytes = match sp_io::storage::read(&key, &mut buf, 0) { + Some(bytes) => bytes, + None => return Err(Error::::PreimageMissing.into()), + }; + // The value may be smaller that 6 bytes. + let mut input = &buf[0..buf.len().min(bytes as usize)]; + + match input.read_byte() { + Ok(1) => (), // Check that input exists and is second variant. + Ok(0) => return Err(Error::::PreimageMissing.into()), + _ => { + sp_runtime::print("Failed to decode `PreimageStatus` variant"); + return Err(Error::::PreimageMissing.into()); + } + } + + // Decode the length of the vector. + let len = codec::Compact::::decode(&mut input).map_err(|_| { + sp_runtime::print("Failed to decode `PreimageStatus` variant"); + DispatchError::from(Error::::PreimageMissing) + })?.0; + + Ok(len) + } + + // See `note_preimage` + fn note_preimage_inner(who: T::AccountId, encoded_proposal: Vec) -> DispatchResult { + let proposal_hash = T::Hashing::hash(&encoded_proposal[..]); + ensure!(!>::contains_key(&proposal_hash), Error::::DuplicatePreimage); + + let deposit = >::from(encoded_proposal.len() as u32) + .saturating_mul(T::PreimageByteDeposit::get()); + T::Currency::reserve(&who, deposit)?; + + let now = >::block_number(); + let a = PreimageStatus::Available { + data: encoded_proposal, + provider: who.clone(), + deposit, + since: now, + expiry: None, + }; + >::insert(proposal_hash, a); + + Self::deposit_event(RawEvent::PreimageNoted(proposal_hash, who, deposit)); + + Ok(()) + } + + // See `note_imminent_preimage` + fn note_imminent_preimage_inner(who: T::AccountId, encoded_proposal: Vec) -> DispatchResult { + let proposal_hash = T::Hashing::hash(&encoded_proposal[..]); + Self::check_pre_image_is_missing(proposal_hash)?; + let status = Preimages::::get(&proposal_hash).ok_or(Error::::NotImminent)?; + let expiry = status.to_missing_expiry().ok_or(Error::::DuplicatePreimage)?; + + let now = >::block_number(); + let free = >::zero(); + let a = PreimageStatus::Available { + data: encoded_proposal, + provider: who.clone(), + deposit: Zero::zero(), + since: now, + expiry: Some(expiry), + }; + >::insert(proposal_hash, a); + + Self::deposit_event(RawEvent::PreimageNoted(proposal_hash, who, free)); + Ok(()) } } + +/// Decode `Compact` from the trie at given key. +fn decode_compact_u32_at(key: &[u8]) -> Option { + // `Compact` takes at most 5 bytes. + let mut buf = [0u8; 5]; + let bytes = match sp_io::storage::read(&key, &mut buf, 0) { + Some(bytes) => bytes, + None => return None, + }; + // The value may be smaller than 5 bytes. + let mut input = &buf[0..buf.len().min(bytes as usize)]; + match codec::Compact::::decode(&mut input) { + Ok(c) => Some(c.0), + Err(_) => { + sp_runtime::print("Failed to decode compact u32 at:"); + sp_runtime::print(key); + None + } + } +} diff --git a/frame/democracy/src/tests.rs b/frame/democracy/src/tests.rs index 8fca8fa4cfba25b1e6a9d9dab0d509c8dfe028ac..78eb143407828eee077f7d6fcea69e9d517afd21 100644 --- a/frame/democracy/src/tests.rs +++ b/frame/democracy/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The crate's tests. @@ -21,7 +22,8 @@ use std::cell::RefCell; use codec::Encode; use frame_support::{ impl_outer_origin, impl_outer_dispatch, assert_noop, assert_ok, parameter_types, - ord_parameter_types, traits::{Contains, OnInitialize}, weights::Weight, + impl_outer_event, ord_parameter_types, traits::{Contains, OnInitialize, Filter}, + weights::Weight, }; use sp_core::H256; use sp_runtime::{ @@ -29,7 +31,7 @@ use sp_runtime::{ testing::Header, Perbill, }; use pallet_balances::{BalanceLock, Error as BalancesError}; -use frame_system::EnsureSignedBy; +use frame_system::{EnsureSignedBy, EnsureRoot}; mod cancellation; mod delegation; @@ -37,10 +39,10 @@ mod external_proposing; mod fast_tracking; mod lock_voting; mod preimage; -mod proxying; mod public_proposals; mod scheduling; mod voting; +mod decoders; const AYE: Vote = Vote { aye: true, conviction: Conviction::None }; const NAY: Vote = Vote { aye: false, conviction: Conviction::None }; @@ -53,21 +55,44 @@ impl_outer_origin! { impl_outer_dispatch! { pub enum Call for Test where origin: Origin { + frame_system::System, pallet_balances::Balances, democracy::Democracy, } } +mod democracy { + pub use crate::Event; +} + +impl_outer_event! { + pub enum Event for Test { + system, + pallet_balances, + pallet_scheduler, + democracy, + } +} + +// Test that a fitlered call can be dispatched. +pub struct BaseFilter; +impl Filter for BaseFilter { + fn filter(call: &Call) -> bool { + !matches!(call, &Call::Balances(pallet_balances::Call::set_balance(..))) + } +} + // 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: Weight = 1024; + pub const MaximumBlockWeight: Weight = 1_000_000; pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = BaseFilter; type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -77,9 +102,13 @@ impl frame_system::Trait for Test { type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; - type Event = (); + type Event = Event; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -87,23 +116,30 @@ impl frame_system::Trait for Test { type AccountData = pallet_balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } parameter_types! { - pub const ExistentialDeposit: u64 = 1; - pub const MaximumWeight: u32 = 1000000; + pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * MaximumBlockWeight::get(); } impl pallet_scheduler::Trait for Test { - type Event = (); + type Event = Event; type Origin = Origin; + type PalletsOrigin = OriginCaller; type Call = Call; - type MaximumWeight = MaximumWeight; + type MaximumWeight = MaximumSchedulerWeight; + type ScheduleOrigin = EnsureRoot; + type WeightInfo = (); +} +parameter_types! { + pub const ExistentialDeposit: u64 = 1; } impl pallet_balances::Trait for Test { type Balance = u64; - type Event = (); + type Event = Event; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; + type WeightInfo = (); } parameter_types! { pub const LaunchPeriod: u64 = 2; @@ -112,6 +148,7 @@ parameter_types! { pub const MinimumDeposit: u64 = 1; pub const EnactmentPeriod: u64 = 2; pub const CooloffPeriod: u64 = 2; + pub const MaxVotes: u32 = 100; } ord_parameter_types! { pub const One: u64 = 1; @@ -126,6 +163,8 @@ impl Contains for OneToFive { fn sorted_members() -> Vec { vec![1, 2, 3, 4, 5] } + #[cfg(feature = "runtime-benchmarks")] + fn add(_m: &u64) {} } thread_local! { static PREIMAGE_BYTE_DEPOSIT: RefCell = RefCell::new(0); @@ -141,7 +180,7 @@ impl Get for InstantAllowed { } impl super::Trait for Test { type Proposal = Call; - type Event = (); + type Event = Event; type Currency = pallet_balances::Module; type EnactmentPeriod = EnactmentPeriod; type LaunchPeriod = LaunchPeriod; @@ -160,9 +199,13 @@ impl super::Trait for Test { type InstantOrigin = EnsureSignedBy; type InstantAllowed = InstantAllowed; type Scheduler = Scheduler; + type MaxVotes = MaxVotes; + type OperationalPreimageOrigin = EnsureSignedBy; + type PalletsOrigin = OriginCaller; + type WeightInfo = (); } -fn new_test_ext() -> sp_io::TestExternalities { +pub fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); pallet_balances::GenesisConfig::{ balances: vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)], @@ -173,6 +216,12 @@ fn new_test_ext() -> sp_io::TestExternalities { ext } +/// Execute the function two times, with `true` and with `false`. +pub fn new_test_ext_execute_with_cond(execute: impl FnOnce(bool) -> () + Clone) { + new_test_ext().execute_with(|| (execute.clone())(false)); + new_test_ext().execute_with(|| execute(true)); +} + type System = frame_system::Module; type Balances = pallet_balances::Module; type Scheduler = pallet_scheduler::Module; @@ -191,6 +240,14 @@ fn set_balance_proposal(value: u64) -> Vec { Call::Balances(pallet_balances::Call::set_balance(42, value, 0)).encode() } +#[test] +fn set_balance_proposal_is_correctly_filtered_out() { + for i in 0..10 { + let call = Call::decode(&mut &set_balance_proposal(i)[..]).unwrap(); + assert!(!::BaseCallFilter::filter(&call)); + } +} + fn set_balance_proposal_hash(value: u64) -> H256 { BlakeTwo256::hash(&set_balance_proposal(value)[..]) } @@ -210,7 +267,7 @@ fn propose_set_balance(who: u64, value: u64, delay: u64) -> DispatchResult { Democracy::propose( Origin::signed(who), set_balance_proposal_hash(value), - delay + delay, ) } @@ -218,14 +275,14 @@ fn propose_set_balance_and_note(who: u64, value: u64, delay: u64) -> DispatchRes Democracy::propose( Origin::signed(who), set_balance_proposal_hash_and_note(value), - delay + delay, ) } fn next_block() { System::set_block_number(System::block_number() + 1); Scheduler::on_initialize(System::block_number()); - assert_eq!(Democracy::begin_block(System::block_number()), Ok(())); + assert!(Democracy::begin_block(System::block_number()).is_ok()); } fn fast_forward_to(n: u64) { diff --git a/frame/democracy/src/tests/cancellation.rs b/frame/democracy/src/tests/cancellation.rs index 998b0c14d8c8074738f847b8d7b9497e3340b4b5..4221865a3e5b0cda7ced129ee0f60e31e728705e 100644 --- a/frame/democracy/src/tests/cancellation.rs +++ b/frame/democracy/src/tests/cancellation.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The tests for cancelation functionality. @@ -28,7 +29,7 @@ fn cancel_referendum_should_work() { 0 ); assert_ok!(Democracy::vote(Origin::signed(1), r, aye(1))); - assert_ok!(Democracy::cancel_referendum(Origin::ROOT, r.into())); + assert_ok!(Democracy::cancel_referendum(Origin::root(), r.into())); next_block(); next_block(); @@ -52,8 +53,8 @@ fn cancel_queued_should_work() { assert!(pallet_scheduler::Agenda::::get(6)[0].is_some()); - assert_noop!(Democracy::cancel_queued(Origin::ROOT, 1), Error::::ProposalMissing); - assert_ok!(Democracy::cancel_queued(Origin::ROOT, 0)); + assert_noop!(Democracy::cancel_queued(Origin::root(), 1), Error::::ProposalMissing); + assert_ok!(Democracy::cancel_queued(Origin::root(), 0)); assert!(pallet_scheduler::Agenda::::get(6)[0].is_none()); }); } diff --git a/frame/democracy/src/tests/decoders.rs b/frame/democracy/src/tests/decoders.rs new file mode 100644 index 0000000000000000000000000000000000000000..6b8e661ca9fd9715e9dea882eb3c1e580535eb77 --- /dev/null +++ b/frame/democracy/src/tests/decoders.rs @@ -0,0 +1,81 @@ +// Copyright 2020 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 for various partial storage decoders + +use super::*; +use frame_support::storage::{migration, StorageMap, unhashed}; + +#[test] +fn test_decode_compact_u32_at() { + new_test_ext().execute_with(|| { + let v = codec::Compact(u64::max_value()); + migration::put_storage_value(b"test", b"", &[], v); + assert_eq!(decode_compact_u32_at(b"test"), None); + + for v in vec![0, 10, u32::max_value()] { + let compact_v = codec::Compact(v); + unhashed::put(b"test", &compact_v); + assert_eq!(decode_compact_u32_at(b"test"), Some(v)); + } + + unhashed::kill(b"test"); + assert_eq!(decode_compact_u32_at(b"test"), None); + }) +} + +#[test] +fn len_of_deposit_of() { + new_test_ext().execute_with(|| { + for l in vec![0, 1, 200, 1000] { + let value: (Vec, u64) = ((0..l).map(|_| Default::default()).collect(), 3u64); + DepositOf::::insert(2, value); + assert_eq!(Democracy::len_of_deposit_of(2), Some(l)); + } + + DepositOf::::remove(2); + assert_eq!(Democracy::len_of_deposit_of(2), None); + }) +} + +#[test] +fn pre_image() { + new_test_ext().execute_with(|| { + let key = Default::default(); + let missing = PreimageStatus::Missing(0); + Preimages::::insert(key, missing); + assert!(Democracy::pre_image_data_len(key).is_err()); + assert_eq!(Democracy::check_pre_image_is_missing(key), Ok(())); + + Preimages::::remove(key); + assert!(Democracy::pre_image_data_len(key).is_err()); + assert!(Democracy::check_pre_image_is_missing(key).is_err()); + + for l in vec![0, 10, 100, 1000u32] { + let available = PreimageStatus::Available{ + data: (0..l).map(|i| i as u8).collect(), + provider: 0, + deposit: 0, + since: 0, + expiry: None, + }; + + Preimages::::insert(key, available); + assert_eq!(Democracy::pre_image_data_len(key), Ok(l)); + assert!(Democracy::check_pre_image_is_missing(key).is_err()); + } + }) +} diff --git a/frame/democracy/src/tests/delegation.rs b/frame/democracy/src/tests/delegation.rs index 061a48b587798219f5562e8ca13fadd214c4cfe8..34dec6d0b49a6d6805d0e1f8bdf65b3114a90884 100644 --- a/frame/democracy/src/tests/delegation.rs +++ b/frame/democracy/src/tests/delegation.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The tests for functionality concerning delegation. diff --git a/frame/democracy/src/tests/external_proposing.rs b/frame/democracy/src/tests/external_proposing.rs index a249a806ee9edf4af87b6ecc81920783ac29c431..473eac81cdcb08c89bd3583706ccfb9bc0a145fd 100644 --- a/frame/democracy/src/tests/external_proposing.rs +++ b/frame/democracy/src/tests/external_proposing.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The tests for functionality concerning the "external" origin. diff --git a/frame/democracy/src/tests/fast_tracking.rs b/frame/democracy/src/tests/fast_tracking.rs index 5ce9b15baf34cde31d2788679f3bdb106e1e8a84..8df34001cde043231587816bf253632a6f7123c0 100644 --- a/frame/democracy/src/tests/fast_tracking.rs +++ b/frame/democracy/src/tests/fast_tracking.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The tests for fast-tracking functionality. diff --git a/frame/democracy/src/tests/lock_voting.rs b/frame/democracy/src/tests/lock_voting.rs index e83d974a8dc27fc990950ed1ae3895946b643e03..93867030588c31b3e146814bccbc4a428b4756eb 100644 --- a/frame/democracy/src/tests/lock_voting.rs +++ b/frame/democracy/src/tests/lock_voting.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The tests for functionality concerning locking and lock-voting. diff --git a/frame/democracy/src/tests/preimage.rs b/frame/democracy/src/tests/preimage.rs index 7d977b0ba83acd514e73fb77d18c485269451161..4100a6a6b6375e7208f8105bcfdb000d10ba8ade 100644 --- a/frame/democracy/src/tests/preimage.rs +++ b/frame/democracy/src/tests/preimage.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The preimage tests. @@ -38,13 +39,14 @@ fn missing_preimage_should_fail() { #[test] fn preimage_deposit_should_be_required_and_returned() { - new_test_ext().execute_with(|| { + new_test_ext_execute_with_cond(|operational| { // fee of 100 is too much. PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow_mut() = 100); assert_noop!( - Democracy::note_preimage(Origin::signed(6), vec![0; 500]), - BalancesError::::InsufficientBalance, - ); + if operational { Democracy::note_preimage_operational(Origin::signed(6), vec![0; 500]) } + else { Democracy::note_preimage(Origin::signed(6), vec![0; 500]) }, + BalancesError::::InsufficientBalance, + ); // fee of 1 is reasonable. PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow_mut() = 1); let r = Democracy::inject_referendum( @@ -68,19 +70,22 @@ fn preimage_deposit_should_be_required_and_returned() { #[test] fn preimage_deposit_should_be_reapable_earlier_by_owner() { - new_test_ext().execute_with(|| { + new_test_ext_execute_with_cond(|operational| { PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow_mut() = 1); - assert_ok!(Democracy::note_preimage(Origin::signed(6), set_balance_proposal(2))); + assert_ok!( + if operational { Democracy::note_preimage_operational(Origin::signed(6), set_balance_proposal(2)) } + else { Democracy::note_preimage(Origin::signed(6), set_balance_proposal(2)) } + ); assert_eq!(Balances::reserved_balance(6), 12); next_block(); assert_noop!( - Democracy::reap_preimage(Origin::signed(6), set_balance_proposal_hash(2)), - Error::::TooEarly - ); + Democracy::reap_preimage(Origin::signed(6), set_balance_proposal_hash(2), u32::max_value()), + Error::::TooEarly + ); next_block(); - assert_ok!(Democracy::reap_preimage(Origin::signed(6), set_balance_proposal_hash(2))); + assert_ok!(Democracy::reap_preimage(Origin::signed(6), set_balance_proposal_hash(2), u32::max_value())); assert_eq!(Balances::free_balance(6), 60); assert_eq!(Balances::reserved_balance(6), 0); @@ -89,26 +94,29 @@ fn preimage_deposit_should_be_reapable_earlier_by_owner() { #[test] fn preimage_deposit_should_be_reapable() { - new_test_ext().execute_with(|| { + new_test_ext_execute_with_cond(|operational| { assert_noop!( - Democracy::reap_preimage(Origin::signed(5), set_balance_proposal_hash(2)), + Democracy::reap_preimage(Origin::signed(5), set_balance_proposal_hash(2), u32::max_value()), Error::::PreimageMissing ); PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow_mut() = 1); - assert_ok!(Democracy::note_preimage(Origin::signed(6), set_balance_proposal(2))); + assert_ok!( + if operational { Democracy::note_preimage_operational(Origin::signed(6), set_balance_proposal(2)) } + else { Democracy::note_preimage(Origin::signed(6), set_balance_proposal(2)) } + ); assert_eq!(Balances::reserved_balance(6), 12); next_block(); next_block(); next_block(); assert_noop!( - Democracy::reap_preimage(Origin::signed(5), set_balance_proposal_hash(2)), + Democracy::reap_preimage(Origin::signed(5), set_balance_proposal_hash(2), u32::max_value()), Error::::TooEarly ); next_block(); - assert_ok!(Democracy::reap_preimage(Origin::signed(5), set_balance_proposal_hash(2))); + assert_ok!(Democracy::reap_preimage(Origin::signed(5), set_balance_proposal_hash(2), u32::max_value())); assert_eq!(Balances::reserved_balance(6), 0); assert_eq!(Balances::free_balance(6), 48); assert_eq!(Balances::free_balance(5), 62); @@ -117,7 +125,7 @@ fn preimage_deposit_should_be_reapable() { #[test] fn noting_imminent_preimage_for_free_should_work() { - new_test_ext().execute_with(|| { + new_test_ext_execute_with_cond(|operational| { PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow_mut() = 1); let r = Democracy::inject_referendum( @@ -129,14 +137,15 @@ fn noting_imminent_preimage_for_free_should_work() { assert_ok!(Democracy::vote(Origin::signed(1), r, aye(1))); assert_noop!( - Democracy::note_imminent_preimage(Origin::signed(7), set_balance_proposal(2)), - Error::::NotImminent - ); + if operational { Democracy::note_imminent_preimage_operational(Origin::signed(6), set_balance_proposal(2)) } + else { Democracy::note_imminent_preimage(Origin::signed(6), set_balance_proposal(2)) }, + Error::::NotImminent + ); next_block(); // Now we're in the dispatch queue it's all good. - assert_ok!(Democracy::note_imminent_preimage(Origin::signed(7), set_balance_proposal(2))); + assert_ok!(Democracy::note_imminent_preimage(Origin::signed(6), set_balance_proposal(2))); next_block(); @@ -152,6 +161,6 @@ fn reaping_imminent_preimage_should_fail() { assert_ok!(Democracy::vote(Origin::signed(1), r, aye(1))); next_block(); next_block(); - assert_noop!(Democracy::reap_preimage(Origin::signed(6), h), Error::::Imminent); + assert_noop!(Democracy::reap_preimage(Origin::signed(6), h, u32::max_value()), Error::::Imminent); }); } diff --git a/frame/democracy/src/tests/proxying.rs b/frame/democracy/src/tests/proxying.rs deleted file mode 100644 index 412adf6be03e707a22e9cd3bb03df3c8f2e6c6cd..0000000000000000000000000000000000000000 --- a/frame/democracy/src/tests/proxying.rs +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2017-2020 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 tests for functionality concerning proxying. - -use super::*; - -#[test] -fn proxy_should_work() { - new_test_ext().execute_with(|| { - assert_eq!(Democracy::proxy(10), None); - assert!(System::allow_death(&10)); - - assert_noop!(Democracy::activate_proxy(Origin::signed(1), 10), Error::::NotOpen); - - assert_ok!(Democracy::open_proxy(Origin::signed(10), 1)); - assert!(!System::allow_death(&10)); - assert_eq!(Democracy::proxy(10), Some(ProxyState::Open(1))); - - assert_noop!(Democracy::activate_proxy(Origin::signed(2), 10), Error::::WrongOpen); - assert_ok!(Democracy::activate_proxy(Origin::signed(1), 10)); - assert_eq!(Democracy::proxy(10), Some(ProxyState::Active(1))); - - // Can't set when already set. - assert_noop!(Democracy::activate_proxy(Origin::signed(2), 10), Error::::AlreadyProxy); - - // But this works because 11 isn't proxying. - assert_ok!(Democracy::open_proxy(Origin::signed(11), 2)); - assert_ok!(Democracy::activate_proxy(Origin::signed(2), 11)); - assert_eq!(Democracy::proxy(10), Some(ProxyState::Active(1))); - assert_eq!(Democracy::proxy(11), Some(ProxyState::Active(2))); - - // 2 cannot fire 1's proxy: - assert_noop!(Democracy::deactivate_proxy(Origin::signed(2), 10), Error::::WrongProxy); - - // 1 deactivates their proxy: - assert_ok!(Democracy::deactivate_proxy(Origin::signed(1), 10)); - assert_eq!(Democracy::proxy(10), Some(ProxyState::Open(1))); - // but the proxy account cannot be killed until the proxy is closed. - assert!(!System::allow_death(&10)); - - // and then 10 closes it completely: - assert_ok!(Democracy::close_proxy(Origin::signed(10))); - assert_eq!(Democracy::proxy(10), None); - assert!(System::allow_death(&10)); - - // 11 just closes without 2's "permission". - assert_ok!(Democracy::close_proxy(Origin::signed(11))); - assert_eq!(Democracy::proxy(11), None); - assert!(System::allow_death(&11)); - }); -} - -#[test] -fn voting_and_removing_votes_should_work_with_proxy() { - new_test_ext().execute_with(|| { - System::set_block_number(0); - assert_ok!(propose_set_balance_and_note(1, 2, 1)); - - fast_forward_to(2); - let r = 0; - assert_ok!(Democracy::open_proxy(Origin::signed(10), 1)); - assert_ok!(Democracy::activate_proxy(Origin::signed(1), 10)); - - assert_ok!(Democracy::proxy_vote(Origin::signed(10), r, aye(1))); - assert_eq!(tally(r), Tally { ayes: 1, nays: 0, turnout: 10 }); - - assert_ok!(Democracy::proxy_remove_vote(Origin::signed(10), r)); - assert_eq!(tally(r), Tally { ayes: 0, nays: 0, turnout: 0 }); - }); -} - -#[test] -fn delegation_and_undelegation_should_work_with_proxy() { - new_test_ext().execute_with(|| { - System::set_block_number(0); - assert_ok!(propose_set_balance_and_note(1, 2, 1)); - fast_forward_to(2); - let r = 0; - assert_ok!(Democracy::open_proxy(Origin::signed(10), 1)); - assert_ok!(Democracy::activate_proxy(Origin::signed(1), 10)); - assert_ok!(Democracy::vote(Origin::signed(2), r, aye(2))); - - assert_ok!(Democracy::proxy_delegate(Origin::signed(10), 2, Conviction::None, 10)); - assert_eq!(tally(r), Tally { ayes: 3, nays: 0, turnout: 30 }); - - assert_ok!(Democracy::proxy_undelegate(Origin::signed(10))); - assert_eq!(tally(r), Tally { ayes: 2, nays: 0, turnout: 20 }); - }); -} - diff --git a/frame/democracy/src/tests/public_proposals.rs b/frame/democracy/src/tests/public_proposals.rs index 04246e86f1da4fb530fb47a58bb9fbb07120bc43..68ec790baae8610591c8cf768e66644824f4c09a 100644 --- a/frame/democracy/src/tests/public_proposals.rs +++ b/frame/democracy/src/tests/public_proposals.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The tests for the public proposal queue. @@ -34,10 +35,10 @@ fn backing_for_should_work() { fn deposit_for_proposals_should_be_taken() { new_test_ext().execute_with(|| { assert_ok!(propose_set_balance_and_note(1, 2, 5)); - assert_ok!(Democracy::second(Origin::signed(2), 0)); - assert_ok!(Democracy::second(Origin::signed(5), 0)); - assert_ok!(Democracy::second(Origin::signed(5), 0)); - assert_ok!(Democracy::second(Origin::signed(5), 0)); + assert_ok!(Democracy::second(Origin::signed(2), 0, u32::max_value())); + assert_ok!(Democracy::second(Origin::signed(5), 0, u32::max_value())); + assert_ok!(Democracy::second(Origin::signed(5), 0, u32::max_value())); + assert_ok!(Democracy::second(Origin::signed(5), 0, u32::max_value())); assert_eq!(Balances::free_balance(1), 5); assert_eq!(Balances::free_balance(2), 15); assert_eq!(Balances::free_balance(5), 35); @@ -48,10 +49,10 @@ fn deposit_for_proposals_should_be_taken() { fn deposit_for_proposals_should_be_returned() { new_test_ext().execute_with(|| { assert_ok!(propose_set_balance_and_note(1, 2, 5)); - assert_ok!(Democracy::second(Origin::signed(2), 0)); - assert_ok!(Democracy::second(Origin::signed(5), 0)); - assert_ok!(Democracy::second(Origin::signed(5), 0)); - assert_ok!(Democracy::second(Origin::signed(5), 0)); + assert_ok!(Democracy::second(Origin::signed(2), 0, u32::max_value())); + assert_ok!(Democracy::second(Origin::signed(5), 0, u32::max_value())); + assert_ok!(Democracy::second(Origin::signed(5), 0, u32::max_value())); + assert_ok!(Democracy::second(Origin::signed(5), 0, u32::max_value())); fast_forward_to(3); assert_eq!(Balances::free_balance(1), 10); assert_eq!(Balances::free_balance(2), 20); @@ -77,7 +78,21 @@ fn poor_proposer_should_not_work() { fn poor_seconder_should_not_work() { new_test_ext().execute_with(|| { assert_ok!(propose_set_balance_and_note(2, 2, 11)); - assert_noop!(Democracy::second(Origin::signed(1), 0), BalancesError::::InsufficientBalance); + assert_noop!( + Democracy::second(Origin::signed(1), 0, u32::max_value()), + BalancesError::::InsufficientBalance + ); + }); +} + +#[test] +fn invalid_seconds_upper_bound_should_not_work() { + new_test_ext().execute_with(|| { + assert_ok!(propose_set_balance_and_note(1, 2, 5)); + assert_noop!( + Democracy::second(Origin::signed(2), 0, 0), + Error::::WrongUpperBound + ); }); } diff --git a/frame/democracy/src/tests/scheduling.rs b/frame/democracy/src/tests/scheduling.rs index db9724deddc223d8895ce807f91ce65e9c020a8b..5bcfbae9946892596f21c9fc7b568e9db0bbb0d3 100644 --- a/frame/democracy/src/tests/scheduling.rs +++ b/frame/democracy/src/tests/scheduling.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The tests for functionality concerning normal starting, ending and enacting of referenda. diff --git a/frame/democracy/src/tests/voting.rs b/frame/democracy/src/tests/voting.rs index 43aed29a32d8bc8c0cc59ab0d84b7fcef44dd4aa..9ae57797d15dd703f545d5720e1ed78477fd8940 100644 --- a/frame/democracy/src/tests/voting.rs +++ b/frame/democracy/src/tests/voting.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The tests for normal voting functionality. diff --git a/frame/democracy/src/types.rs b/frame/democracy/src/types.rs index 3454326364de60412048467b8602df796110e3fd..8ee0838f8a36d14fb841b488f0055d452f1b6b18 100644 --- a/frame/democracy/src/types.rs +++ b/frame/democracy/src/types.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Miscellaneous additional datatypes. @@ -196,24 +197,6 @@ impl ReferendumInfo { - /// Account is open to becoming a proxy but is not yet assigned. - Open(AccountId), - /// Account is actively being a proxy. - Active(AccountId), -} - -impl ProxyState { - pub (crate) fn as_active(self) -> Option { - match self { - ProxyState::Active(a) => Some(a), - ProxyState::Open(_) => None, - } - } -} - /// Whether an `unvote` operation is able to make actions that are not strictly always in the /// interest of an account. pub enum UnvoteScope { diff --git a/frame/democracy/src/vote.rs b/frame/democracy/src/vote.rs index a41eb342aa12cb1ee862a0119a49f97620a0620d..09ff0d71e48ca9cf44142b4c8ab306aedaa4dc39 100644 --- a/frame/democracy/src/vote.rs +++ b/frame/democracy/src/vote.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The vote datatype. diff --git a/frame/democracy/src/vote_threshold.rs b/frame/democracy/src/vote_threshold.rs index fd976b44001cf189d497ec81c9fba789843e72d0..2268a55936c50aafa47fc5281e71d7dad5299607 100644 --- a/frame/democracy/src/vote_threshold.rs +++ b/frame/democracy/src/vote_threshold.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Voting thresholds. diff --git a/frame/elections-phragmen/Cargo.toml b/frame/elections-phragmen/Cargo.toml index fb219bbebc33d5a864e3d0beee08e32e07e2eab5..afbd53d3da0919885dfb3ed39a3ca503088b96a6 100644 --- a/frame/elections-phragmen/Cargo.toml +++ b/frame/elections-phragmen/Cargo.toml @@ -1,29 +1,32 @@ [package] name = "pallet-elections-phragmen" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" -description = "FRAME election pallet for PHRAGMEN" +description = "FRAME pallet based on seq-Phragmén election method." + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } serde = { version = "1.0.101", optional = true } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -sp-phragmen = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/phragmen" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +sp-npos-elections = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/npos-elections" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +frame-benchmarking = { version = "2.0.0-rc4", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-io = { version = "2.0.0-alpha.5", path = "../../primitives/io" } +sp-io = { version = "2.0.0-rc4", path = "../../primitives/io" } hex-literal = "0.2.1" -pallet-balances = { version = "2.0.0-alpha.5", path = "../balances" } -pallet-scheduler = { version = "2.0.0-alpha.5", path = "../scheduler" } -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -substrate-test-utils = { version = "2.0.0-alpha.5", path = "../../test-utils" } +pallet-balances = { version = "2.0.0-rc4", path = "../balances" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +substrate-test-utils = { version = "2.0.0-rc4", path = "../../test-utils" } [features] default = ["std"] @@ -32,11 +35,12 @@ std = [ "codec/std", "frame-support/std", "sp-runtime/std", - "sp-phragmen/std", + "sp-npos-elections/std", "frame-system/std", "sp-std/std", ] -runtime-benchmarks = ["frame-support/runtime-benchmarks"] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +runtime-benchmarks = [ + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", +] diff --git a/frame/elections-phragmen/src/benchmarking.rs b/frame/elections-phragmen/src/benchmarking.rs new file mode 100644 index 0000000000000000000000000000000000000000..6de9ad57e244fa080c41815436be290546885fb4 --- /dev/null +++ b/frame/elections-phragmen/src/benchmarking.rs @@ -0,0 +1,600 @@ +// Copyright 2020 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 . + +//! Elections-Phragmen pallet benchmarking. + +#![cfg(feature = "runtime-benchmarks")] + +use super::*; + +use frame_system::RawOrigin; +use frame_benchmarking::{benchmarks, account}; +use frame_support::traits::OnInitialize; + +use crate::Module as Elections; + +const BALANCE_FACTOR: u32 = 250; +const MAX_VOTERS: u32 = 500; +const MAX_CANDIDATES: u32 = 100; + +type Lookup = <::Lookup as StaticLookup>::Source; + +/// grab new account with infinite balance. +fn endowed_account(name: &'static str, index: u32) -> T::AccountId { + let account: T::AccountId = account(name, index, 0); + let amount = default_stake::(BALANCE_FACTOR); + let _ = T::Currency::make_free_balance_be(&account, amount); + // important to increase the total issuance since T::CurrencyToVote will need it to be sane for + // phragmen to work. + T::Currency::issue(amount); + account +} + +/// Account to lookup type of system trait. +fn as_lookup(account: T::AccountId) -> Lookup { + T::Lookup::unlookup(account) +} + +/// Get a reasonable amount of stake based on the execution trait's configuration +fn default_stake(factor: u32) -> BalanceOf { + let factor = BalanceOf::::from(factor); + T::Currency::minimum_balance() * factor +} + +/// Get the current number of candidates. +fn candidate_count() -> u32 { + >::decode_len().unwrap_or(0usize) as u32 +} + +/// Get the number of votes of a voter. +fn vote_count_of(who: &T::AccountId) -> u32 { + >::get(who).1.len() as u32 +} + +/// A `DefunctVoter` struct with correct value +fn defunct_for(who: T::AccountId) -> DefunctVoter> { + DefunctVoter { + who: as_lookup::(who.clone()), + candidate_count: candidate_count::(), + vote_count: vote_count_of::(&who), + } +} + +/// Add `c` new candidates. +fn submit_candidates(c: u32, prefix: &'static str) + -> Result, &'static str> +{ + (0..c).map(|i| { + let account = endowed_account::(prefix, i); + >::submit_candidacy( + RawOrigin::Signed(account.clone()).into(), + candidate_count::(), + ).map_err(|_| "failed to submit candidacy")?; + Ok(account) + }).collect::>() +} + +/// Add `c` new candidates with self vote. +fn submit_candidates_with_self_vote(c: u32, prefix: &'static str) + -> Result, &'static str> +{ + let candidates = submit_candidates::(c, prefix)?; + let stake = default_stake::(BALANCE_FACTOR); + let _ = candidates.iter().map(|c| + submit_voter::(c.clone(), vec![c.clone()], stake) + ).collect::>()?; + Ok(candidates) +} + + +/// Submit one voter. +fn submit_voter(caller: T::AccountId, votes: Vec, stake: BalanceOf) + -> Result<(), &'static str> +{ + >::vote(RawOrigin::Signed(caller).into(), votes, stake) + .map_err(|_| "failed to submit vote") +} + +/// create `num_voter` voters who randomly vote for at most `votes` of `all_candidates` if +/// available. +fn distribute_voters(mut all_candidates: Vec, num_voters: u32, votes: usize) + -> Result<(), &'static str> +{ + let stake = default_stake::(BALANCE_FACTOR); + for i in 0..num_voters { + // to ensure that votes are different + all_candidates.rotate_left(1); + let votes = all_candidates + .iter() + .cloned() + .take(votes) + .collect::>(); + let voter = endowed_account::("voter", i); + submit_voter::(voter, votes, stake)?; + } + Ok(()) +} + +/// Fill the seats of members and runners-up up until `m`. Note that this might include either only +/// members, or members and runners-up. +fn fill_seats_up_to(m: u32) -> Result, &'static str> { + let candidates = submit_candidates_with_self_vote::(m, "fill_seats_up_to")?; + assert_eq!(>::candidates().len() as u32, m, "wrong number of candidates."); + >::do_phragmen(); + assert_eq!(>::candidates().len(), 0, "some candidates remaining."); + assert_eq!( + >::members().len() + >::runners_up().len(), + m as usize, + "wrong number of members and runners-up", + ); + Ok(candidates) +} + +/// removes all the storage items to reverse any genesis state. +fn clean() { + >::kill(); + >::kill(); + >::kill(); + let _ = >::drain(); +} + +benchmarks! { + _ { + // User account seed + let u in 0 .. 1000 => (); + } + + // -- Signed ones + vote { + let u in ...; + // we fix the number of voted candidates to max + let v = MAXIMUM_VOTE; + clean::(); + + // create a bunch of candidates. + let all_candidates = submit_candidates::(MAXIMUM_VOTE as u32, "candidates")?; + + let caller = endowed_account::("caller", u); + let stake = default_stake::(BALANCE_FACTOR); + + // vote for all of them. + let votes = all_candidates.into_iter().take(v).collect(); + + }: _(RawOrigin::Signed(caller), votes, stake) + + vote_update { + let u in ...; + // we fix the number of voted candidates to max + let v = MAXIMUM_VOTE; + clean::(); + + // create a bunch of candidates. + let all_candidates = submit_candidates::(MAXIMUM_VOTE as u32, "candidates")?; + + let caller = endowed_account::("caller", u); + let stake = default_stake::(BALANCE_FACTOR); + + // original votes. + let mut votes = all_candidates.into_iter().take(v).collect::>(); + submit_voter::(caller.clone(), votes.clone(), stake)?; + // new votes. + votes.rotate_left(1); + }: vote(RawOrigin::Signed(caller), votes, stake) + + remove_voter { + let u in ...; + // we fix the number of voted candidates to max + let v = MAXIMUM_VOTE as u32; + clean::(); + + // create a bunch of candidates. + let all_candidates = submit_candidates::(v, "candidates")?; + + let caller = endowed_account::("caller", u); + + let stake = default_stake::(BALANCE_FACTOR); + submit_voter::(caller.clone(), all_candidates, stake)?; + + }: _(RawOrigin::Signed(caller)) + + report_defunct_voter_correct { + // number of already existing candidates that may or may not be voted by the reported + // account. + let c in 1 .. MAX_CANDIDATES; + // number of candidates that the reported voter voted for. The worse case of search here is + // basically `c * v`. + let v in 1 .. (MAXIMUM_VOTE as u32); + // we fix the number of members to when members and runners-up to the desired. We'll be in + // this state almost always. + let m = T::DesiredMembers::get() + T::DesiredRunnersUp::get(); + clean::(); + + let stake = default_stake::(BALANCE_FACTOR); + + // create m members and runners combined. + let _ = fill_seats_up_to::(m)?; + + // create a bunch of candidates as well. + let bailing_candidates = submit_candidates::(v, "bailing_candidates")?; + let all_candidates = submit_candidates::(c, "all_candidates")?; + + // account 1 is the reporter and it doesn't matter how many it votes. But it has to be a + // voter. + let account_1 = endowed_account::("caller", 0); + submit_voter::( + account_1.clone(), + all_candidates.iter().take(1).cloned().collect(), + stake, + )?; + + // account 2 votes for all of the mentioned candidates. + let account_2 = endowed_account::("caller_2", 1); + submit_voter::( + account_2.clone(), + bailing_candidates.clone(), + stake, + )?; + + // all the bailers go away. + bailing_candidates.into_iter().for_each(|b| { + let count = candidate_count::(); + assert!(>::renounce_candidacy( + RawOrigin::Signed(b).into(), + Renouncing::Candidate(count), + ).is_ok()); + }); + let defunct = defunct_for::(account_2.clone()); + }: report_defunct_voter(RawOrigin::Signed(account_1.clone()), defunct) + verify { + assert!(>::is_voter(&account_1)); + assert!(!>::is_voter(&account_2)); + #[cfg(test)] + { + // reset members in between benchmark tests. + use crate::tests::MEMBERS; + MEMBERS.with(|m| *m.borrow_mut() = vec![]); + } + } + + report_defunct_voter_incorrect { + // number of already existing candidates that may or may not be voted by the reported + // account. + let c in 1 .. MAX_CANDIDATES; + // number of candidates that the reported voter voted for. The worse case of search here is + // basically `c * v`. + let v in 1 .. (MAXIMUM_VOTE as u32); + // we fix the number of members to when members and runners-up to the desired. We'll be in + // this state almost always. + let m = T::DesiredMembers::get() + T::DesiredRunnersUp::get(); + + clean::(); + let stake = default_stake::(BALANCE_FACTOR); + + // create m members and runners combined. + let _ = fill_seats_up_to::(m)?; + + // create a bunch of candidates as well. + let all_candidates = submit_candidates::(c, "candidates")?; + + // account 1 is the reporter and it doesn't matter how many it votes. + let account_1 = endowed_account::("caller", 0); + submit_voter::( + account_1.clone(), + all_candidates.iter().take(1).cloned().collect(), + stake, + )?; + + // account 2 votes for a bunch of crap, and finally a correct candidate. + let account_2 = endowed_account::("caller_2", 1); + let mut invalid: Vec = + (0..(v-1)).map(|seed| account::("invalid", 0, seed).clone()).collect(); + invalid.push(all_candidates.last().unwrap().clone()); + submit_voter::( + account_2.clone(), + invalid, + stake, + )?; + + let defunct = defunct_for::(account_2.clone()); + // no one bails out. account_1 is slashed and removed as voter now. + }: report_defunct_voter(RawOrigin::Signed(account_1.clone()), defunct) + verify { + assert!(!>::is_voter(&account_1)); + assert!(>::is_voter(&account_2)); + #[cfg(test)] + { + // reset members in between benchmark tests. + use crate::tests::MEMBERS; + MEMBERS.with(|m| *m.borrow_mut() = vec![]); + } + } + + submit_candidacy { + // number of already existing candidates. + let c in 1 .. MAX_CANDIDATES; + // we fix the number of members to when members and runners-up to the desired. We'll be in + // this state almost always. + let m = T::DesiredMembers::get() + T::DesiredRunnersUp::get(); + + clean::(); + let stake = default_stake::(BALANCE_FACTOR); + + // create m members and runners combined. + let _ = fill_seats_up_to::(m)?; + + // create previous candidates; + let _ = submit_candidates::(c, "candidates")?; + + // we assume worse case that: extrinsic is successful and candidate is not duplicate. + let candidate_account = endowed_account::("caller", 0); + }: _(RawOrigin::Signed(candidate_account.clone()), candidate_count::()) + verify { + #[cfg(test)] + { + // reset members in between benchmark tests. + use crate::tests::MEMBERS; + MEMBERS.with(|m| *m.borrow_mut() = vec![]); + } + } + + renounce_candidacy_candidate { + // this will check members, runners-up and candidate for removal. Members and runners-up are + // limited by the runtime bound, nonetheless we fill them by `m`. + // number of already existing candidates. + let c in 1 .. MAX_CANDIDATES; + // we fix the number of members to when members and runners-up to the desired. We'll be in + // this state almost always. + let m = T::DesiredMembers::get() + T::DesiredRunnersUp::get(); + + clean::(); + + // create m members and runners combined. + let _ = fill_seats_up_to::(m)?; + let all_candidates = submit_candidates::(c, "caller")?; + + let bailing = all_candidates[0].clone(); // Should be ("caller", 0) + let count = candidate_count::(); + }: renounce_candidacy(RawOrigin::Signed(bailing), Renouncing::Candidate(count)) + verify { + #[cfg(test)] + { + // reset members in between benchmark tests. + use crate::tests::MEMBERS; + MEMBERS.with(|m| *m.borrow_mut() = vec![]); + } + } + + renounce_candidacy_member_runner_up { + // removing members and runners will be cheaper than a candidate. + // we fix the number of members to when members and runners-up to the desired. We'll be in + // this state almost always. + let u in ...; + let m = T::DesiredMembers::get() + T::DesiredRunnersUp::get(); + clean::(); + + // create m members and runners combined. + let members_and_runners_up = fill_seats_up_to::(m)?; + + let bailing = members_and_runners_up[0].clone(); + let renouncing = if >::is_member(&bailing) { + Renouncing::Member + } else if >::is_runner_up(&bailing) { + Renouncing::RunnerUp + } else { + panic!("Bailing must be a member or runner-up for this bench to be sane."); + }; + }: renounce_candidacy(RawOrigin::Signed(bailing.clone()), renouncing) + verify { + #[cfg(test)] + { + // reset members in between benchmark tests. + use crate::tests::MEMBERS; + MEMBERS.with(|m| *m.borrow_mut() = vec![]); + } + } + + // -- Root ones + remove_member_without_replacement { + // worse case is when we remove a member and we have no runner as a replacement. This + // triggers phragmen again. The only parameter is how many candidates will compete for the + // new slot. + let c in 1 .. MAX_CANDIDATES; + clean::(); + + // fill only desired members. no runners-up. + let all_members = fill_seats_up_to::(T::DesiredMembers::get())?; + assert_eq!(>::members().len() as u32, T::DesiredMembers::get()); + + // submit a new one to compensate, with self-vote. + let replacements = submit_candidates_with_self_vote::(c, "new_candidate")?; + + // create some voters for these replacements. + distribute_voters::(replacements, MAX_VOTERS, MAXIMUM_VOTE)?; + + let to_remove = as_lookup::(all_members[0].clone()); + }: remove_member(RawOrigin::Root, to_remove, false) + verify { + // must still have the desired number of members members. + assert_eq!(>::members().len() as u32, T::DesiredMembers::get()); + #[cfg(test)] + { + // reset members in between benchmark tests. + use crate::tests::MEMBERS; + MEMBERS.with(|m| *m.borrow_mut() = vec![]); + } + } + + remove_member_with_replacement { + // easy case. We have a runner up. Nothing will have that much of an impact. m will be + // number of members and runners. There is always at least one runner. + let u in ...; + let m = T::DesiredMembers::get() + T::DesiredRunnersUp::get(); + clean::(); + + let _ = fill_seats_up_to::(m)?; + let removing = as_lookup::(>::members_ids()[0].clone()); + }: remove_member(RawOrigin::Root, removing, true) + verify { + // must still have enough members. + assert_eq!(>::members().len() as u32, T::DesiredMembers::get()); + #[cfg(test)] + { + // reset members in between benchmark tests. + use crate::tests::MEMBERS; + MEMBERS.with(|m| *m.borrow_mut() = vec![]); + } + } + + remove_member_wrong_refund { + // The root call by mistake indicated that this will have no replacement, while it has! + // this has now consumed a lot of weight and need to refund. + let u in ...; + let m = T::DesiredMembers::get() + T::DesiredRunnersUp::get(); + clean::(); + + let _ = fill_seats_up_to::(m)?; + let removing = as_lookup::(>::members_ids()[0].clone()); + }: { + assert_eq!( + >::remove_member(RawOrigin::Root.into(), removing, false).unwrap_err().error, + Error::::InvalidReplacement.into(), + ); + } + verify { + // must still have enough members. + assert_eq!(>::members().len() as u32, T::DesiredMembers::get()); + #[cfg(test)] + { + // reset members in between benchmark tests. + use crate::tests::MEMBERS; + MEMBERS.with(|m| *m.borrow_mut() = vec![]); + } + } + + on_initialize { + // if n % TermDuration is zero, then we run phragmen. The weight function must and should + // check this as it is cheap to do so. TermDuration is not a storage item, it is a constant + // encoded in the runtime. + let c in 1 .. MAX_CANDIDATES; + clean::(); + + // create c candidates. + let all_candidates = submit_candidates_with_self_vote::(c, "candidates")?; + // create 500 voters, each voting the maximum 16 + distribute_voters::(all_candidates, MAX_VOTERS, MAXIMUM_VOTE)?; + }: { + // elect + >::on_initialize(T::TermDuration::get()); + } + verify { + assert_eq!(>::members().len() as u32, T::DesiredMembers::get().min(c)); + assert_eq!( + >::runners_up().len() as u32, + T::DesiredRunnersUp::get().min(c.saturating_sub(T::DesiredMembers::get())), + ); + + #[cfg(test)] + { + // reset members in between benchmark tests. + use crate::tests::MEMBERS; + MEMBERS.with(|m| *m.borrow_mut() = vec![]); + } + } + + phragmen { + // This is just to focus on phragmen in the context of this module. We always select 20 + // members, this is hard-coded in the runtime and cannot be trivially changed at this stage. + // Yet, change the number of voters, candidates and edge per voter to see the impact. Note + // that we give all candidates a self vote to make sure they are all considered. + let c in 1 .. MAX_CANDIDATES; + let v in 1 .. MAX_VOTERS; + let e in 1 .. (MAXIMUM_VOTE as u32); + clean::(); + + let all_candidates = submit_candidates_with_self_vote::(c, "candidates")?; + let _ = distribute_voters::(all_candidates, v, e as usize)?; + }: { + >::on_initialize(T::TermDuration::get()); + } + verify { + assert_eq!(>::members().len() as u32, T::DesiredMembers::get().min(c)); + assert_eq!( + >::runners_up().len() as u32, + T::DesiredRunnersUp::get().min(c.saturating_sub(T::DesiredMembers::get())), + ); + + #[cfg(test)] + { + // reset members in between benchmark tests. + use crate::tests::MEMBERS; + MEMBERS.with(|m| *m.borrow_mut() = vec![]); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::tests::{ExtBuilder, Test}; + use frame_support::assert_ok; + + #[test] + fn test_benchmarks_elections_phragmen() { + ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| { + assert_ok!(test_benchmark_vote::()); + }); + + ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| { + assert_ok!(test_benchmark_remove_voter::()); + }); + + ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| { + assert_ok!(test_benchmark_report_defunct_voter_correct::()); + }); + + ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| { + assert_ok!(test_benchmark_report_defunct_voter_incorrect::()); + }); + + ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| { + assert_ok!(test_benchmark_submit_candidacy::()); + }); + + ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| { + assert_ok!(test_benchmark_renounce_candidacy_candidate::()); + }); + + ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| { + assert_ok!(test_benchmark_renounce_candidacy_member_runner_up::()); + }); + + ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| { + assert_ok!(test_benchmark_remove_member_without_replacement::()); + }); + + ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| { + assert_ok!(test_benchmark_remove_member_with_replacement::()); + }); + + ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| { + assert_ok!(test_benchmark_on_initialize::()); + }); + + ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| { + assert_ok!(test_benchmark_phragmen::()); + }); + } +} diff --git a/frame/elections-phragmen/src/lib.rs b/frame/elections-phragmen/src/lib.rs index 28fc66bef95b3db5117816e9a70d680bd933f814..c59ac590316dec4a65065cf511e979beed20e764 100644 --- a/frame/elections-phragmen/src/lib.rs +++ b/frame/elections-phragmen/src/lib.rs @@ -1,20 +1,21 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! # Phragmén Election Module. //! //! An election module based on sequential phragmen. //! @@ -65,7 +66,7 @@ //! //! ##### Renouncing candidacy. //! -//! All candidates, elected or not, can renounce their candidacy. A call to [`renounce_candidacy`] +//! All candidates, elected or not, can renounce their candidacy. A call to [`Module::renounce_candidacy`] //! will always cause the candidacy bond to be refunded. //! //! Note that with the members being the default candidates for the next round and votes persisting @@ -82,34 +83,99 @@ #![cfg_attr(not(feature = "std"), no_std)] +use codec::{Encode, Decode}; use sp_std::prelude::*; use sp_runtime::{ - print, DispatchResult, DispatchError, Perbill, traits::{Zero, StaticLookup, Convert}, + DispatchError, RuntimeDebug, Perbill, + traits::{Zero, StaticLookup, Convert}, }; use frame_support::{ decl_storage, decl_event, ensure, decl_module, decl_error, - weights::{SimpleDispatchInfo, Weight, WeighData}, storage::{StorageMap, IterableStorageMap}, + weights::{Weight, constants::{WEIGHT_PER_MICROS, WEIGHT_PER_NANOS}}, + storage::{StorageMap, IterableStorageMap}, + dispatch::{DispatchResultWithPostInfo, WithPostDispatchInfo}, traits::{ Currency, Get, LockableCurrency, LockIdentifier, ReservableCurrency, WithdrawReasons, ChangeMembers, OnUnbalanced, WithdrawReason, Contains, BalanceStatus, InitializeMembers, + ContainsLengthBound, } }; -use sp_phragmen::{build_support_map, ExtendedBalance}; -use frame_system::{self as system, ensure_signed, ensure_root}; +use sp_npos_elections::{build_support_map, ExtendedBalance, VoteWeight, ElectionResult}; +use frame_system::{ensure_signed, ensure_root}; -const MODULE_ID: LockIdentifier = *b"phrelect"; +mod benchmarking; /// The maximum votes allowed per voter. pub const MAXIMUM_VOTE: usize = 16; -type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; +type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; +/// An indication that the renouncing account currently has which of the below roles. +#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug)] +pub enum Renouncing { + /// A member is renouncing. + Member, + /// A runner-up is renouncing. + RunnerUp, + /// A candidate is renouncing, while the given total number of candidates exists. + Candidate(#[codec(compact)] u32), +} + +/// Information needed to prove the defunct-ness of a voter. +#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug)] +pub struct DefunctVoter { + /// the voter's who's being challenged for being defunct + pub who: AccountId, + /// The number of votes that `who` has placed. + #[codec(compact)] + pub vote_count: u32, + /// The number of current active candidates. + #[codec(compact)] + pub candidate_count: u32 +} + +pub trait WeightInfo { + fn vote(u: u32, ) -> Weight; + fn vote_update(u: u32, ) -> Weight; + fn remove_voter(u: u32, ) -> Weight; + fn report_defunct_voter_correct(c: u32, v: u32, ) -> Weight; + fn report_defunct_voter_incorrect(c: u32, v: u32, ) -> Weight; + fn submit_candidacy(c: u32, ) -> Weight; + fn renounce_candidacy_candidate(c: u32, ) -> Weight; + fn renounce_candidacy_member_runner_up(u: u32, ) -> Weight; + fn remove_member_without_replacement(c: u32, ) -> Weight; + fn remove_member_with_replacement(u: u32, ) -> Weight; + fn remove_member_wrong_refund(u: u32, ) -> Weight; + fn on_initialize(c: u32, ) -> Weight; + fn phragmen(c: u32, v: u32, e: u32, ) -> Weight; +} + +impl WeightInfo for () { + fn vote(_u: u32, ) -> Weight { 1_000_000_000 } + fn vote_update(_u: u32, ) -> Weight { 1_000_000_000 } + fn remove_voter(_u: u32, ) -> Weight { 1_000_000_000 } + fn report_defunct_voter_correct(_c: u32, _v: u32, ) -> Weight { 1_000_000_000 } + fn report_defunct_voter_incorrect(_c: u32, _v: u32, ) -> Weight { 1_000_000_000 } + fn submit_candidacy(_c: u32, ) -> Weight { 1_000_000_000 } + fn renounce_candidacy_candidate(_c: u32, ) -> Weight { 1_000_000_000 } + fn renounce_candidacy_member_runner_up(_u: u32, ) -> Weight { 1_000_000_000 } + fn remove_member_without_replacement(_c: u32, ) -> Weight { 1_000_000_000 } + fn remove_member_with_replacement(_u: u32, ) -> Weight { 1_000_000_000 } + fn remove_member_wrong_refund(_u: u32, ) -> Weight { 1_000_000_000 } + fn on_initialize(_c: u32, ) -> Weight { 1_000_000_000 } + fn phragmen(_c: u32, _v: u32, _e: u32, ) -> Weight { 1_000_000_000 } +} + pub trait Trait: frame_system::Trait { /// The overarching event type.c type Event: From> + Into<::Event>; + /// Identifier for the elections-phragmen pallet's lock + type ModuleId: Get; + /// The currency that people are electing with. type Currency: LockableCurrency + @@ -123,7 +189,7 @@ pub trait Trait: frame_system::Trait { /// 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>; + type CurrencyToVote: Convert, VoteWeight> + Convert>; /// How much should be locked up in order to submit one's candidacy. type CandidacyBond: Get>; @@ -150,6 +216,9 @@ pub trait Trait: frame_system::Trait { /// round will happen. If set to zero, no elections are ever triggered and the module will /// be in passive mode. type TermDuration: Get; + + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; } decl_storage! { @@ -163,6 +232,8 @@ decl_storage! { pub ElectionRounds get(fn election_rounds): u32 = Zero::zero(); /// Votes and locked stake of a particular voter. + /// + /// TWOX-NOTE: SAFE as `AccountId` is a crypto hash pub Voting get(fn voting): map hasher(twox_64_concat) T::AccountId => (BalanceOf, Vec); /// The present candidate list. Sorted based on account-id. A current member or runner-up @@ -185,8 +256,12 @@ decl_storage! { // Note: all members will only vote for themselves, hence they must be given exactly // their own stake as total backing. Any sane election should behave as such. // Nonetheless, stakes will be updated for term 1 onwards according to the election. - >::append(&[(member.clone(), *stake)]) - .expect("Failed to append genesis members."); + Members::::mutate(|members| { + match members.binary_search_by(|(a, _b)| a.cmp(member)) { + Ok(_) => panic!("Duplicate member in elections phragmen genesis: {}", member), + Err(pos) => members.insert(pos, (member.clone(), *stake)), + } + }); // set self-votes to make persistent. >::vote( @@ -205,7 +280,6 @@ decl_storage! { } decl_error! { - /// Error for the elections-phragmen module. pub enum Error for Module { /// Cannot vote when no candidates or members exist. UnableToVote, @@ -231,26 +305,16 @@ decl_error! { RunnerSubmit, /// Candidate does not have enough funds. InsufficientCandidateFunds, - /// Origin is not a candidate, member or a runner up. - InvalidOrigin, /// Not a member. NotMember, - } -} - -mod migration { - use super::*; - use frame_support::{migration::{StorageKeyIterator, take_storage_item}, Twox64Concat}; - pub fn migrate() { - for (who, votes) in StorageKeyIterator - ::, Twox64Concat> - ::new(b"PhragmenElection", b"VotesOf") - .drain() - { - if let Some(stake) = take_storage_item::<_, BalanceOf, Twox64Concat>(b"PhragmenElection", b"StakeOf", &who) { - Voting::::insert(who, (stake, votes)); - } - } + /// The provided count of number of candidates is incorrect. + InvalidCandidateCount, + /// The provided count of number of votes is incorrect. + InvalidVoteCount, + /// The renouncing origin presented a wrong `Renouncing` parameter. + InvalidRenouncing, + /// Prediction regarding replacement after member removal is wrong. + InvalidReplacement, } } @@ -260,63 +324,73 @@ decl_module! { fn deposit_event() = default; - fn on_runtime_upgrade() -> Weight { - migration::migrate::(); - - SimpleDispatchInfo::default().weigh_data(()) - } - 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(); + const ModuleId: LockIdentifier = T::ModuleId::get(); - /// Vote for a set of candidates for the upcoming round of election. + /// Vote for a set of candidates for the upcoming round of election. This can be called to + /// set the initial votes, or update already existing votes. + /// + /// Upon initial voting, `value` units of `who`'s balance is locked and a bond amount is + /// reserved. /// /// The `votes` should: /// - not be empty. - /// - be less than the number of candidates. + /// - be less than the number of possible candidates. Note that all current members and + /// runners-up are also automatically candidates for the next round. /// - /// 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. + /// Base weight: 47.93 µs + /// State reads: + /// - Candidates.len() + Members.len() + RunnersUp.len() + /// - Voting (is_voter) + /// - [AccountBalance(who) (unreserve + total_balance)] + /// State writes: + /// - Voting + /// - Lock + /// - [AccountBalance(who) (unreserve -- only when creating a new voter)] /// # - #[weight = SimpleDispatchInfo::FixedNormal(100_000)] - fn vote(origin, votes: Vec, #[compact] value: BalanceOf) { + #[weight = 50 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(4, 2)] + 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!(votes.len() <= MAXIMUM_VOTE, Error::::MaximumVotesExceeded); + ensure!(!votes.is_empty(), Error::::NoVotes); + + let candidates_count = >::decode_len().unwrap_or(0); + let members_count = >::decode_len().unwrap_or(0); + let runners_up_count = >::decode_len().unwrap_or(0); + + // addition is valid: candidates, members and runners-up will never overlap. + let allowed_votes = candidates_count + members_count + runners_up_count; ensure!(!allowed_votes.is_zero(), Error::::UnableToVote); ensure!(votes.len() <= allowed_votes, Error::::TooManyVotes); - ensure!(votes.len() <= MAXIMUM_VOTE, Error::::MaximumVotesExceeded); - ensure!(!votes.is_empty(), Error::::NoVotes); - ensure!( - value > T::Currency::minimum_balance(), - Error::::LowBalance, - ); + ensure!(value > T::Currency::minimum_balance(), Error::::LowBalance); + // first time voter. Reserve bond. if !Self::is_voter(&who) { - // first time voter. Reserve bond. T::Currency::reserve(&who, T::VotingBond::get()) .map_err(|_| Error::::UnableToPayBond)?; } + // Amount to be locked up. let locked_balance = value.min(T::Currency::total_balance(&who)); // lock T::Currency::set_lock( - MODULE_ID, + T::ModuleId::get(), &who, locked_balance, WithdrawReasons::except(WithdrawReason::TransactionPayment), @@ -328,14 +402,19 @@ decl_module! { /// Remove `origin` as a voter. This removes the lock and returns the bond. /// /// # - /// #### State - /// Reads: O(1) - /// Writes: O(1) + /// Base weight: 36.8 µs + /// All state access is from do_remove_voter. + /// State reads: + /// - Voting + /// - [AccountData(who)] + /// State writes: + /// - Voting + /// - Locks + /// - [AccountData(who)] /// # - #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + #[weight = 35 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(1, 2)] fn remove_voter(origin) { let who = ensure_signed(origin)?; - ensure!(Self::is_voter(&who), Error::::MustBeVoter); Self::do_remove_voter(&who, true); @@ -347,27 +426,62 @@ decl_module! { /// /// 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. + /// longer a candidate nor an active member or a runner-up. + /// + /// + /// The origin must provide the number of current candidates and votes of the reported target + /// for the purpose of accurate weight calculation. /// /// # - /// #### State - /// Reads: O(NLogM) given M current candidates and N votes for `target`. - /// Writes: O(1) + /// No Base weight based on min square analysis. + /// Complexity of candidate_count: 1.755 µs + /// Complexity of vote_count: 18.51 µs + /// State reads: + /// - Voting(reporter) + /// - Candidate.len() + /// - Voting(Target) + /// - Candidates, Members, RunnersUp (is_defunct_voter) + /// State writes: + /// - Lock(reporter || target) + /// - [AccountBalance(reporter)] + AccountBalance(target) + /// - Voting(reporter || target) + /// Note: the db access is worse with respect to db, which is when the report is correct. /// # - #[weight = SimpleDispatchInfo::FixedNormal(1_000_000)] - fn report_defunct_voter(origin, target: ::Source) { + #[weight = + Weight::from(defunct.candidate_count).saturating_mul(2 * WEIGHT_PER_MICROS) + .saturating_add(Weight::from(defunct.vote_count).saturating_mul(19 * WEIGHT_PER_MICROS)) + .saturating_add(T::DbWeight::get().reads_writes(6, 3)) + ] + fn report_defunct_voter( + origin, + defunct: DefunctVoter<::Source>, + ) { let reporter = ensure_signed(origin)?; - let target = T::Lookup::lookup(target)?; + let target = T::Lookup::lookup(defunct.who)?; ensure!(reporter != target, Error::::ReportSelf); ensure!(Self::is_voter(&reporter), Error::::MustBeVoter); - // 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); + let DefunctVoter { candidate_count, vote_count, .. } = defunct; + + ensure!( + >::decode_len().unwrap_or(0) as u32 <= candidate_count, + Error::::InvalidCandidateCount, + ); + + let (_, votes) = >::get(&target); + // indirect way to ensure target is a voter. We could call into `::contains()`, but it + // would have the same effect with one extra db access. Note that votes cannot be + // submitted with length 0. Hence, a non-zero length means that the target is a voter. + ensure!(votes.len() > 0, Error::::MustBeVoter); + + // ensure that the size of votes that need to be searched is correct. + ensure!( + votes.len() as u32 <= vote_count, + Error::::InvalidVoteCount, + ); + + let valid = Self::is_defunct_voter(&votes); if valid { // reporter will get the voting bond of the target T::Currency::repatriate_reserved(&target, &reporter, T::VotingBond::get(), BalanceStatus::Free)?; @@ -383,7 +497,6 @@ decl_module! { Self::deposit_event(RawEvent::VoterReported(target, reporter, valid)); } - /// Submit oneself for candidacy. /// /// A candidate will either: @@ -393,21 +506,40 @@ decl_module! { /// removed. /// /// # - /// #### State - /// Reads: O(LogN) Given N candidates. - /// Writes: O(1) + /// Base weight = 33.33 µs + /// Complexity of candidate_count: 0.375 µs + /// State reads: + /// - Candidates.len() + /// - Candidates + /// - Members + /// - RunnersUp + /// - [AccountBalance(who)] + /// State writes: + /// - [AccountBalance(who)] + /// - Candidates /// # - #[weight = SimpleDispatchInfo::FixedNormal(500_000)] - fn submit_candidacy(origin) { + #[weight = + (35 * WEIGHT_PER_MICROS) + .saturating_add(Weight::from(*candidate_count).saturating_mul(375 * WEIGHT_PER_NANOS)) + .saturating_add(T::DbWeight::get().reads_writes(4, 1)) + ] + fn submit_candidacy(origin, #[compact] candidate_count: u32) { let who = ensure_signed(origin)?; + let actual_count = >::decode_len().unwrap_or(0); + ensure!( + actual_count as u32 <= candidate_count, + Error::::InvalidCandidateCount, + ); + let is_candidate = Self::is_candidate(&who); ensure!(is_candidate.is_err(), Error::::DuplicatedCandidate); + // assured to be an error, error always contains the index. let index = is_candidate.unwrap_err(); ensure!(!Self::is_member(&who), Error::::MemberSubmit); - ensure!(!Self::is_runner(&who), Error::::RunnerSubmit); + ensure!(!Self::is_runner_up(&who), Error::::RunnerSubmit); T::Currency::reserve(&who, T::CandidacyBond::get()) .map_err(|_| Error::::InsufficientCandidateFunds)?; @@ -419,94 +551,155 @@ decl_module! { /// outcomes exist: /// - `origin` is a candidate and not elected in any set. In this case, the bond is /// unreserved, returned and origin is removed as a candidate. - /// - `origin` is a current runner up. In this case, the bond is unreserved, returned and - /// origin is removed as a runner. + /// - `origin` is a current runner-up. In this case, the bond is unreserved, returned and + /// origin is removed as a runner-up. /// - `origin` is a current member. In this case, the bond is unreserved and origin is /// removed as a member, consequently not being a candidate for the next round anymore. /// Similar to [`remove_voter`], if replacement runners exists, they are immediately used. - #[weight = SimpleDispatchInfo::FixedOperational(2_000_000)] - fn renounce_candidacy(origin) { - let who = ensure_signed(origin)?; - - // NOTE: this function attempts the 3 conditions (being a candidate, member, runner) and - // fails if none are matched. Unlike other Palette functions and modules where checks - // happen first and then execution happens, this function is written the other way - // around. The main intention is that reading all of the candidates, members and runners - // from storage is expensive. Furthermore, we know (soft proof) that they are always - // mutually exclusive. Hence, we try one, and only then decode more storage. - - if let Ok(_replacement) = Self::remove_and_replace_member(&who) { - T::Currency::unreserve(&who, T::CandidacyBond::get()); - Self::deposit_event(RawEvent::MemberRenounced(who.clone())); - - // safety guard to make sure we do only one arm. Better to read runners later. - return Ok(()); - } - - let mut runners_up_with_stake = Self::runners_up(); - if let Some(index) = runners_up_with_stake.iter() - .position(|(ref r, ref _s)| r == &who) - { - runners_up_with_stake.remove(index); - // unreserve the bond - T::Currency::unreserve(&who, T::CandidacyBond::get()); - // update storage. - >::put(runners_up_with_stake); - // safety guard to make sure we do only one arm. Better to read runners later. - return Ok(()); - } - - let mut candidates = Self::candidates(); - if let Ok(index) = candidates.binary_search(&who) { - candidates.remove(index); - // unreserve the bond - T::Currency::unreserve(&who, T::CandidacyBond::get()); - // update storage. - >::put(candidates); - // safety guard to make sure we do only one arm. Better to read runners later. - return Ok(()); + /// + /// If a candidate is renouncing: + /// Base weight: 17.28 µs + /// Complexity of candidate_count: 0.235 µs + /// State reads: + /// - Candidates + /// - [AccountBalance(who) (unreserve)] + /// State writes: + /// - Candidates + /// - [AccountBalance(who) (unreserve)] + /// If member is renouncing: + /// Base weight: 46.25 µs + /// State reads: + /// - Members, RunnersUp (remove_and_replace_member), + /// - [AccountData(who) (unreserve)] + /// State writes: + /// - Members, RunnersUp (remove_and_replace_member), + /// - [AccountData(who) (unreserve)] + /// If runner is renouncing: + /// Base weight: 46.25 µs + /// State reads: + /// - RunnersUp (remove_and_replace_member), + /// - [AccountData(who) (unreserve)] + /// State writes: + /// - RunnersUp (remove_and_replace_member), + /// - [AccountData(who) (unreserve)] + /// + /// Weight note: The call into changeMembers need to be accounted for. + /// + #[weight = match *renouncing { + Renouncing::Candidate(count) => { + (18 * WEIGHT_PER_MICROS) + .saturating_add(Weight::from(count).saturating_mul(235 * WEIGHT_PER_NANOS)) + .saturating_add(T::DbWeight::get().reads_writes(1, 1)) + }, + Renouncing::Member => { + 46 * WEIGHT_PER_MICROS + + T::DbWeight::get().reads_writes(2, 2) + }, + Renouncing::RunnerUp => { + 46 * WEIGHT_PER_MICROS + + T::DbWeight::get().reads_writes(1, 1) } - - Err(Error::::InvalidOrigin)? + }] + fn renounce_candidacy(origin, renouncing: Renouncing) { + let who = ensure_signed(origin)?; + match renouncing { + Renouncing::Member => { + // returns NoMember error in case of error. + let _ = Self::remove_and_replace_member(&who)?; + T::Currency::unreserve(&who, T::CandidacyBond::get()); + Self::deposit_event(RawEvent::MemberRenounced(who.clone())); + }, + Renouncing::RunnerUp => { + let mut runners_up_with_stake = Self::runners_up(); + if let Some(index) = runners_up_with_stake + .iter() + .position(|(ref r, ref _s)| r == &who) + { + runners_up_with_stake.remove(index); + // unreserve the bond + T::Currency::unreserve(&who, T::CandidacyBond::get()); + // update storage. + >::put(runners_up_with_stake); + } else { + Err(Error::::InvalidRenouncing)?; + } + } + Renouncing::Candidate(count) => { + let mut candidates = Self::candidates(); + ensure!(count >= candidates.len() as u32, Error::::InvalidRenouncing); + if let Some(index) = candidates.iter().position(|x| *x == who) { + candidates.remove(index); + // unreserve the bond + T::Currency::unreserve(&who, T::CandidacyBond::get()); + // update storage. + >::put(candidates); + } else { + Err(Error::::InvalidRenouncing)?; + } + } + }; } /// Remove a particular member from the set. This is effective immediately and the bond of /// the outgoing member is slashed. /// /// 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. + /// outgoing member. Otherwise, a new phragmen election 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) + /// If we have a replacement: + /// - Base weight: 50.93 µs + /// - State reads: + /// - RunnersUp.len() + /// - Members, RunnersUp (remove_and_replace_member) + /// - State writes: + /// - Members, RunnersUp (remove_and_replace_member) + /// Else, since this is a root call and will go into phragmen, we assume full block for now. /// # - #[weight = SimpleDispatchInfo::FixedOperational(2_000_000)] - fn remove_member(origin, who: ::Source) -> DispatchResult { + #[weight = if *has_replacement { + 50 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(3, 2) + } else { + T::MaximumBlockWeight::get() + }] + fn remove_member( + origin, + who: ::Source, + has_replacement: bool, + ) -> DispatchResultWithPostInfo { ensure_root(origin)?; let who = T::Lookup::lookup(who)?; + let will_have_replacement = >::decode_len().unwrap_or(0) > 0; + if will_have_replacement != has_replacement { + // In both cases, we will change more weight than neede. Refund and abort. + return Err(Error::::InvalidReplacement.with_weight( + // refund. The weight value comes from a benchmark which is special to this. + // 5.751 µs + 6 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(1, 0) + )); + } // else, prediction was correct. + Self::remove_and_replace_member(&who).map(|had_replacement| { let (imbalance, _) = T::Currency::slash_reserved(&who, T::CandidacyBond::get()); T::KickedMember::on_unbalanced(imbalance); Self::deposit_event(RawEvent::MemberKicked(who.clone())); if !had_replacement { + // if we end up here, we will charge a full block weight. Self::do_phragmen(); } - }) + + // no refund needed. + None.into() + }).map_err(|e| e.into()) } /// What to do at the end of each block. Checks if an election needs to happen or not. fn on_initialize(n: T::BlockNumber) -> Weight { - if let Err(e) = Self::end_block(n) { - print("Guru meditation"); - print(e); - } - - SimpleDispatchInfo::default().weigh_data(()) + // returns the correct weight. + Self::end_block(n) } } } @@ -516,10 +709,13 @@ decl_event!( 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. + /// A new term with new members. This indicates that enough candidates existed to run the + /// election, not that enough have has been elected. The inner value must be examined for + /// this purpose. A `NewTerm([])` indicates that some candidates got their bond slashed and + /// none were elected, whilst `EmptyTerm` means that no candidates existed to begin with. NewTerm(Vec<(AccountId, Balance)>), - /// No (or not enough) candidates existed for this round. + /// No (or not enough) candidates existed for this round. This is different from + /// `NewTerm([])`. See the description of `NewTerm`. EmptyTerm, /// A member has been removed. This should always be followed by either `NewTerm` ot /// `EmptyTerm`. @@ -533,13 +729,19 @@ decl_event!( ); impl Module { - /// Attempts to remove a member `who`. If a runner up exists, it is used as the replacement. + /// Attempts to remove a member `who`. If a runner-up exists, it is used as the replacement and + /// Ok(true). is returned. + /// /// Otherwise, `Ok(false)` is returned to signal the caller. /// - /// In both cases, [`Members`], [`ElectionRounds`] and [`RunnersUp`] storage are updated - /// accordingly. Furthermore, the membership change is reported. + /// If a replacement exists, `Members` and `RunnersUp` storage is updated, where the first + /// element of `RunnersUp` is used as the replacement and `Ok(true)` is returned. Else, + /// `Ok(false)` is returned with no storage updated. /// - /// O(phragmen) in the worse case. + /// Note that this function _will_ call into `T::ChangeMembers` in case any change happens + /// (`Ok(true)`). + /// + /// If replacement exists, this will read and write from/into both `Members` and `RunnersUp`. fn remove_and_replace_member(who: &T::AccountId) -> Result { let mut members_with_stake = Self::members(); if let Ok(index) = members_with_stake.binary_search_by(|(ref m, ref _s)| m.cmp(who)) { @@ -572,7 +774,7 @@ 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. + /// O(LogN) given N candidates. fn is_candidate(who: &T::AccountId) -> Result<(), usize> { Self::candidates().binary_search(who).map(|_| ()) } @@ -586,15 +788,15 @@ impl Module { /// Check if `who` is currently an active member. /// - /// Limited number of members. Binary search. Constant time factor. O(1) + /// O(LogN) given N members. Since members are limited, O(1). fn is_member(who: &T::AccountId) -> bool { Self::members().binary_search_by(|(a, _b)| a.cmp(who)).is_ok() } - /// Check if `who` is currently an active runner. + /// Check if `who` is currently an active runner-up. /// - /// Limited number of runners-up. Binary search. Constant time factor. O(1) - fn is_runner(who: &T::AccountId) -> bool { + /// O(LogN) given N runners-up. Since runners-up are limited, O(1). + fn is_runner_up(who: &T::AccountId) -> bool { Self::runners_up().iter().position(|(a, _b)| a == who).is_some() } @@ -623,29 +825,28 @@ impl Module { 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. + /// Check if `votes` will correspond to a defunct voter. As no origin is part of the inputs, + /// this function does not check the origin 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_runner(v) && !Self::is_candidate(v).is_ok()) - } else { - false - } + /// Reads Members, RunnersUp, Candidates and Voting(who) from database. + fn is_defunct_voter(votes: &[T::AccountId]) -> bool { + votes.iter().all(|v| + !Self::is_member(v) && !Self::is_runner_up(v) && !Self::is_candidate(v).is_ok() + ) } /// 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`. + /// If unreserve is true, has 3 storage reads and 1 reads. + /// + /// DB access: Voting and Lock are always written to, if unreserve, then 1 read and write added. fn do_remove_voter(who: &T::AccountId, unreserve: bool) { // remove storage and lock. Voting::::remove(who); - T::Currency::remove_lock(MODULE_ID, who); + T::Currency::remove_lock(T::ModuleId::get(), who); if unreserve { T::Currency::unreserve(who, T::VotingBond::get()); @@ -657,33 +858,26 @@ impl Module { Voting::::get(who).0 } - /// The locked stake of a voter. - fn votes_of(who: &T::AccountId) -> Vec { - Voting::::get(who).1 - } - /// 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) -> DispatchResult { + fn end_block(block_number: T::BlockNumber) -> Weight { if !Self::term_duration().is_zero() { if (block_number % Self::term_duration()).is_zero() { Self::do_phragmen(); + return T::MaximumBlockWeight::get() } } - Ok(()) + 0 } /// Run the phragmen election with all required side processes and state updates. /// - /// Calls the appropriate `ChangeMembers` function variant internally. + /// 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; @@ -699,17 +893,28 @@ impl Module { // previous runners_up are also always candidates for the next round. candidates.append(&mut Self::runners_up_ids()); + // helper closures to deal with balance/stake. + let to_votes = |b: BalanceOf| -> VoteWeight { + , VoteWeight>>::convert(b) + }; + let to_balance = |e: ExtendedBalance| -> BalanceOf { + >>::convert(e) + }; + let stake_of = |who: &T::AccountId| -> VoteWeight { + to_votes(Self::locked_stake_of(who)) + }; + let voters_and_votes = Voting::::iter() - .map(|(voter, (stake, targets))| { (voter, stake, targets) }) + .map(|(voter, (stake, targets))| { (voter, to_votes(stake), targets) }) .collect::>(); - let maybe_phragmen_result = sp_phragmen::elect::<_, _, T::CurrencyToVote, Perbill>( + let maybe_phragmen_result = sp_npos_elections::seq_phragmen::( num_to_elect, 0, candidates, voters_and_votes.clone(), ); - if let Some(phragmen_result) = maybe_phragmen_result { + if let Some(ElectionResult { winners, assignments }) = maybe_phragmen_result { let old_members_ids = >::take().into_iter() .map(|(m, _)| m) .collect::>(); @@ -718,30 +923,28 @@ impl Module { .collect::>(); // 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 + // 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_with_approval = winners; let new_set = new_set_with_approval .into_iter() .filter_map(|(m, a)| if a.is_zero() { None } else { Some(m) } ) .collect::>(); - let stake_of = |who: &T::AccountId| -> ExtendedBalance { - , u64>>::convert( - Self::locked_stake_of(who) - ) as ExtendedBalance - }; - let staked_assignments = sp_phragmen::assignment_ratio_to_staked( - phragmen_result.assignments, + // OPTIMISATION NOTE: we could bail out here if `new_set.len() == 0`. There isn't much + // left to do. Yet, re-arranging the code would require duplicating the slashing of + // exposed candidates, cleaning any previous members, and so on. For now, in favour of + // readability and veracity, we keep it simple. + + let staked_assignments = sp_npos_elections::assignment_ratio_to_staked( + assignments, stake_of, ); let (support_map, _) = build_support_map::(&new_set, &staked_assignments); - let to_balance = |e: ExtendedBalance| - >>::convert(e); let new_set_with_stake = new_set .into_iter() .map(|ref m| { @@ -759,17 +962,17 @@ impl Module { let mut new_members = (&new_set_with_stake[..split_point]).to_vec(); // save the runners up as-is. They are sorted based on desirability. - // sort and save the members. + // save the members, sorted based on account id. new_members.sort_by(|i, j| i.0.cmp(&j.0)); - let mut prime_votes: Vec<_> = new_members.iter().map(|c| (&c.0, BalanceOf::::zero())).collect(); + let mut prime_votes: Vec<_> = new_members.iter().map(|c| (&c.0, VoteWeight::zero())).collect(); for (_, stake, targets) in voters_and_votes.into_iter() { for (votes, who) in targets.iter() .enumerate() .map(|(votes, who)| ((MAXIMUM_VOTE - votes) as u32, who)) { if let Ok(i) = prime_votes.binary_search_by_key(&who, |k| k.0) { - prime_votes[i].1 += stake * votes.into(); + prime_votes[i].1 += stake * votes as VoteWeight; } } } @@ -869,19 +1072,29 @@ impl Contains for Module { } } +impl ContainsLengthBound for Module { + fn min_len() -> usize { 0 } + + /// Implementation uses a parameter type so calling is cost-free. + fn max_len() -> usize { + Self::desired_members() as usize + } +} + #[cfg(test)] mod tests { use super::*; use std::cell::RefCell; - use frame_support::{assert_ok, assert_noop, parameter_types, weights::Weight}; + use frame_support::{assert_ok, assert_noop, assert_err_with_weight, parameter_types, + weights::Weight, + }; use substrate_test_utils::assert_eq_uvec; use sp_core::H256; use sp_runtime::{ - Perbill, testing::Header, BuildStorage, + Perbill, testing::Header, BuildStorage, DispatchResult, traits::{BlakeTwo256, IdentityLookup, Block as BlockT}, }; use crate as elections_phragmen; - use frame_system as system; parameter_types! { pub const BlockHashCount: u64 = 250; @@ -891,10 +1104,11 @@ mod tests { } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; - type Call = (); + type Call = Call; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = u64; @@ -903,6 +1117,10 @@ mod tests { type Event = Event; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -910,11 +1128,12 @@ mod tests { type AccountData = pallet_balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } parameter_types! { pub const ExistentialDeposit: u64 = 1; -} + } impl pallet_balances::Trait for Test { type Balance = u64; @@ -922,7 +1141,8 @@ mod tests { type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = frame_system::Module; -} + type WeightInfo = (); + } parameter_types! { pub const CandidacyBond: u64 = 3; @@ -989,7 +1209,7 @@ mod tests { new_plus_outgoing.extend_from_slice(outgoing); new_plus_outgoing.sort(); - assert_eq!(old_plus_incoming, new_plus_outgoing); + assert_eq!(old_plus_incoming, new_plus_outgoing, "change members call is incorrect!"); MEMBERS.with(|m| *m.borrow_mut() = new.to_vec()); PRIME.with(|p| *p.borrow_mut() = None); @@ -1011,7 +1231,12 @@ mod tests { } } + parameter_types!{ + pub const ElectionsPhragmenModuleId: LockIdentifier = *b"phrelect"; + } + impl Trait for Test { + type ModuleId = ElectionsPhragmenModuleId; type Event = Event; type Currency = Balances; type CurrencyToVote = CurrencyToVoteHandler; @@ -1025,6 +1250,7 @@ mod tests { type LoserCandidate = (); type KickedMember = (); type BadReport = (); + type WeightInfo = (); } pub type Block = sp_runtime::generic::Block; @@ -1036,7 +1262,7 @@ mod tests { NodeBlock = Block, UncheckedExtrinsic = UncheckedExtrinsic { - System: system::{Module, Call, Event}, + System: frame_system::{Module, Call, Event}, Balances: pallet_balances::{Module, Call, Event, Config}, Elections: elections_phragmen::{Module, Call, Event, Config}, } @@ -1048,6 +1274,7 @@ mod tests { voter_bond: u64, term_duration: u64, desired_runners_up: u32, + desired_members: u32, } impl Default for ExtBuilder { @@ -1056,8 +1283,9 @@ mod tests { genesis_members: vec![], balance_factor: 1, voter_bond: 2, - desired_runners_up: 0, term_duration: 5, + desired_runners_up: 0, + desired_members: 2, } } } @@ -1079,11 +1307,24 @@ mod tests { self.genesis_members = members; self } - pub fn build(self) -> sp_io::TestExternalities { + #[cfg(feature = "runtime-benchmarks")] + pub fn desired_members(mut self, count: u32) -> Self { + self.desired_members = count; + self + } + pub fn balance_factor(mut self, factor: u64) -> Self { + self.balance_factor = factor; + self + } + fn set_constants(&self) { 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); + DESIRED_MEMBERS.with(|m| *m.borrow_mut() = self.desired_members); MEMBERS.with(|m| *m.borrow_mut() = self.genesis_members.iter().map(|(m, _)| m.clone()).collect::>()); + } + pub fn build_and_execute(self, test: impl FnOnce() -> ()) { + self.set_constants(); let mut ext: sp_io::TestExternalities = GenesisConfig { pallet_balances: Some(pallet_balances::GenesisConfig::{ balances: vec![ @@ -1099,8 +1340,9 @@ mod tests { members: self.genesis_members }), }.build_storage().unwrap().into(); - ext.execute_with(|| System::set_block_number(1)); - ext + ext.execute_with(pre_conditions); + ext.execute_with(test); + ext.execute_with(post_conditions) } } @@ -1114,13 +1356,83 @@ mod tests { fn has_lock(who: &u64) -> u64 { let lock = Balances::locks(who)[0].clone(); - assert_eq!(lock.id, MODULE_ID); + assert_eq!(lock.id, ElectionsPhragmenModuleId::get()); lock.amount } + fn intersects(a: &[T], b: &[T]) -> bool { + a.iter().any(|e| b.contains(e)) + } + + fn ensure_members_sorted() { + let mut members = Elections::members().clone(); + members.sort(); + assert_eq!(Elections::members(), members); + } + + fn ensure_candidates_sorted() { + let mut candidates = Elections::candidates().clone(); + candidates.sort(); + assert_eq!(Elections::candidates(), candidates); + } + + fn ensure_members_has_approval_stake() { + // we filter members that have no approval state. This means that even we have more seats + // than candidates, we will never ever chose a member with no votes. + assert!( + Elections::members().iter().chain( + Elections::runners_up().iter() + ).all(|(_, s)| *s != Zero::zero()) + ); + } + + fn ensure_member_candidates_runners_up_disjoint() { + // members, candidates and runners-up must always be disjoint sets. + assert!(!intersects(&Elections::members_ids(), &Elections::candidates())); + assert!(!intersects(&Elections::members_ids(), &Elections::runners_up_ids())); + assert!(!intersects(&Elections::candidates(), &Elections::runners_up_ids())); + } + + fn pre_conditions() { + System::set_block_number(1); + ensure_members_sorted(); + ensure_candidates_sorted(); + } + + fn post_conditions() { + ensure_members_sorted(); + ensure_candidates_sorted(); + ensure_member_candidates_runners_up_disjoint(); + ensure_members_has_approval_stake(); + } + + fn submit_candidacy(origin: Origin) -> DispatchResult { + Elections::submit_candidacy(origin, Elections::candidates().len() as u32) + } + + fn vote(origin: Origin, votes: Vec, stake: u64) -> DispatchResult { + // historical note: helper function was created in a period of time in which the API of vote + // call was changing. Currently it is a wrapper for the original call and does not do much. + // Nonetheless, totally harmless. + ensure_signed(origin.clone()).expect("vote origin must be signed"); + Elections::vote(origin, votes, stake) + } + + fn votes_of(who: &u64) -> Vec { + Voting::::get(who).1 + } + + fn defunct_for(who: u64) -> DefunctVoter { + DefunctVoter { + who, + candidate_count: Elections::candidates().len() as u32, + vote_count: votes_of(&who).len() as u32 + } + } + #[test] fn params_should_work() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { assert_eq!(Elections::desired_members(), 2); assert_eq!(Elections::term_duration(), 5); assert_eq!(Elections::election_rounds(), 0); @@ -1129,17 +1441,17 @@ mod tests { assert_eq!(Elections::runners_up(), vec![]); assert_eq!(Elections::candidates(), vec![]); - assert_eq!(>::decode_len().unwrap(), 0); + assert_eq!(>::decode_len(), None); assert!(Elections::is_candidate(&1).is_err()); assert_eq!(all_voters(), vec![]); - assert_eq!(Elections::votes_of(&1), vec![]); + assert_eq!(votes_of(&1), vec![]); }); } #[test] fn genesis_members_should_work() { - ExtBuilder::default().genesis_members(vec![(1, 10), (2, 20)]).build().execute_with(|| { + ExtBuilder::default().genesis_members(vec![(1, 10), (2, 20)]).build_and_execute(|| { System::set_block_number(1); assert_eq!(Elections::members(), vec![(1, 10), (2, 20)]); @@ -1148,7 +1460,24 @@ mod tests { // they will persist since they have self vote. System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); + + assert_eq!(Elections::members_ids(), vec![1, 2]); + }) + } + + #[test] + fn genesis_members_unsorted_should_work() { + ExtBuilder::default().genesis_members(vec![(2, 20), (1, 10)]).build_and_execute(|| { + System::set_block_number(1); + assert_eq!(Elections::members(), vec![(1, 10), (2, 20)]); + + assert_eq!(Elections::voting(1), (10, vec![1])); + assert_eq!(Elections::voting(2), (20, vec![2])); + + // they will persist since they have self vote. + System::set_block_number(5); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![1, 2]); }) @@ -1158,22 +1487,34 @@ mod tests { #[should_panic = "Genesis member does not have enough stake"] fn genesis_members_cannot_over_stake_0() { // 10 cannot lock 20 as their stake and extra genesis will panic. - ExtBuilder::default().genesis_members(vec![(1, 20), (2, 20)]).build(); + ExtBuilder::default() + .genesis_members(vec![(1, 20), (2, 20)]) + .build_and_execute(|| {}); } #[test] #[should_panic] fn genesis_members_cannot_over_stake_1() { // 10 cannot reserve 20 as voting bond and extra genesis will panic. - ExtBuilder::default().voter_bond(20).genesis_members(vec![(1, 10), (2, 20)]).build(); + ExtBuilder::default() + .voter_bond(20) + .genesis_members(vec![(1, 10), (2, 20)]) + .build_and_execute(|| {}); + } + + #[test] + #[should_panic = "Duplicate member in elections phragmen genesis: 2"] + fn genesis_members_cannot_be_duplicate() { + ExtBuilder::default() + .genesis_members(vec![(1, 10), (2, 10), (2, 10)]) + .build_and_execute(|| {}); } #[test] fn term_duration_zero_is_passive() { ExtBuilder::default() .term_duration(0) - .build() - .execute_with(|| + .build_and_execute(|| { assert_eq!(Elections::term_duration(), 0); assert_eq!(Elections::desired_members(), 2); @@ -1184,7 +1525,7 @@ mod tests { assert_eq!(Elections::candidates(), vec![]); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![]); assert_eq!(Elections::runners_up(), vec![]); @@ -1194,13 +1535,13 @@ mod tests { #[test] fn simple_candidate_submission_should_work() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { 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_ok!(submit_candidacy(Origin::signed(1))); assert_eq!(balances(&1), (7, 3)); assert_eq!(Elections::candidates(), vec![1]); @@ -1209,7 +1550,7 @@ mod tests { assert!(Elections::is_candidate(&2).is_err()); assert_eq!(balances(&2), (20, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + assert_ok!(submit_candidacy(Origin::signed(2))); assert_eq!(balances(&2), (17, 3)); assert_eq!(Elections::candidates(), vec![1, 2]); @@ -1221,11 +1562,11 @@ mod tests { #[test] fn simple_candidate_submission_with_no_votes_should_work() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { assert_eq!(Elections::candidates(), Vec::::new()); - assert_ok!(Elections::submit_candidacy(Origin::signed(1))); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + assert_ok!(submit_candidacy(Origin::signed(1))); + assert_ok!(submit_candidacy(Origin::signed(2))); assert!(Elections::is_candidate(&1).is_ok()); assert!(Elections::is_candidate(&2).is_ok()); @@ -1235,7 +1576,7 @@ mod tests { assert_eq!(Elections::runners_up(), vec![]); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert!(Elections::is_candidate(&1).is_err()); assert!(Elections::is_candidate(&2).is_err()); @@ -1248,12 +1589,12 @@ mod tests { #[test] fn dupe_candidate_submission_should_not_work() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { assert_eq!(Elections::candidates(), Vec::::new()); - assert_ok!(Elections::submit_candidacy(Origin::signed(1))); + assert_ok!(submit_candidacy(Origin::signed(1))); assert_eq!(Elections::candidates(), vec![1]); assert_noop!( - Elections::submit_candidacy(Origin::signed(1)), + submit_candidacy(Origin::signed(1)), Error::::DuplicatedCandidate, ); }); @@ -1262,19 +1603,19 @@ mod tests { #[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)); + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(vote(Origin::signed(2), vec![5], 20)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + 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)), + submit_candidacy(Origin::signed(5)), Error::::MemberSubmit, ); }); @@ -1282,22 +1623,22 @@ mod tests { #[test] fn runner_candidate_submission_should_not_work() { - 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))); + ExtBuilder::default().desired_runners_up(2).build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::vote(Origin::signed(2), vec![5, 4], 20)); - assert_ok!(Elections::vote(Origin::signed(1), vec![3], 10)); + assert_ok!(vote(Origin::signed(2), vec![5, 4], 20)); + assert_ok!(vote(Origin::signed(1), vec![3], 10)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![4, 5]); assert_eq!(Elections::runners_up_ids(), vec![3]); assert_noop!( - Elections::submit_candidacy(Origin::signed(3)), + submit_candidacy(Origin::signed(3)), Error::::RunnerSubmit, ); }); @@ -1305,10 +1646,10 @@ mod tests { #[test] fn poor_candidate_submission_should_not_work() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { assert_eq!(Elections::candidates(), Vec::::new()); assert_noop!( - Elections::submit_candidacy(Origin::signed(7)), + submit_candidacy(Origin::signed(7)), Error::::InsufficientCandidateFunds, ); }); @@ -1316,12 +1657,12 @@ mod tests { #[test] fn simple_voting_should_work() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { 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_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(vote(Origin::signed(2), vec![5], 20)); assert_eq!(balances(&2), (18, 2)); assert_eq!(has_lock(&2), 20); @@ -1330,12 +1671,12 @@ mod tests { #[test] fn can_vote_with_custom_stake() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { 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_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(vote(Origin::signed(2), vec![5], 12)); assert_eq!(balances(&2), (18, 2)); assert_eq!(has_lock(&2), 12); @@ -1344,19 +1685,19 @@ mod tests { #[test] fn can_update_votes_and_stake() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { 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_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(vote(Origin::signed(2), vec![5], 20)); assert_eq!(balances(&2), (18, 2)); assert_eq!(has_lock(&2), 20); assert_eq!(Elections::locked_stake_of(&2), 20); // can update; different stake; different lock and reserve. - assert_ok!(Elections::vote(Origin::signed(2), vec![5, 4], 15)); + assert_ok!(vote(Origin::signed(2), vec![5, 4], 15)); assert_eq!(balances(&2), (18, 2)); assert_eq!(has_lock(&2), 15); assert_eq!(Elections::locked_stake_of(&2), 15); @@ -1365,73 +1706,73 @@ mod tests { #[test] fn cannot_vote_for_no_candidate() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { assert_noop!( - Elections::vote(Origin::signed(2), vec![], 20), - Error::::UnableToVote, + vote(Origin::signed(2), vec![], 20), + Error::::NoVotes, ); }); } #[test] fn can_vote_for_old_members_even_when_no_new_candidates() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::vote(Origin::signed(2), vec![4, 5], 20)); + assert_ok!(vote(Origin::signed(2), vec![4, 5], 20)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + 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)); + assert_ok!(vote(Origin::signed(3), vec![4, 5], 10)); }); } #[test] fn prime_works() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(3))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::vote(Origin::signed(1), vec![4, 3], 10)); - assert_ok!(Elections::vote(Origin::signed(2), vec![4], 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_ok!(vote(Origin::signed(1), vec![4, 3], 10)); + assert_ok!(vote(Origin::signed(2), vec![4], 20)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + 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)); + assert_ok!(vote(Origin::signed(3), vec![4, 5], 10)); assert_eq!(PRIME.with(|p| *p.borrow()), Some(4)); }); } #[test] fn prime_votes_for_exiting_members_are_removed() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(3))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::vote(Origin::signed(1), vec![4, 3], 10)); - assert_ok!(Elections::vote(Origin::signed(2), vec![4], 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_ok!(vote(Origin::signed(1), vec![4, 3], 10)); + assert_ok!(vote(Origin::signed(2), vec![4], 20)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); - assert_ok!(Elections::renounce_candidacy(Origin::signed(4))); + assert_ok!(Elections::renounce_candidacy(Origin::signed(4), Renouncing::Candidate(3))); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![3, 5]); assert_eq!(Elections::candidates(), vec![]); @@ -1441,13 +1782,36 @@ mod tests { } #[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))); + fn cannot_vote_for_more_than_candidates_and_members_and_runners() { + ExtBuilder::default() + .desired_runners_up(1) + .balance_factor(10) + .build_and_execute( + || { + // when we have only candidates + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + + assert_noop!( + // content of the vote is irrelevant. + vote(Origin::signed(1), vec![9, 99, 999, 9999], 5), + Error::::TooManyVotes, + ); + + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); + + System::set_block_number(5); + Elections::end_block(System::block_number()); + // now we have 2 members, 1 runner-up, and 1 new candidate + assert_ok!(submit_candidacy(Origin::signed(2))); + + assert_ok!(vote(Origin::signed(1), vec![9, 99, 999, 9999], 5)); assert_noop!( - Elections::vote(Origin::signed(2), vec![10, 20, 30], 20), + vote(Origin::signed(1), vec![9, 99, 999, 9_999, 99_999], 5), Error::::TooManyVotes, ); }); @@ -1455,12 +1819,12 @@ mod tests { #[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))); + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); assert_noop!( - Elections::vote(Origin::signed(2), vec![4], 1), + vote(Origin::signed(2), vec![4], 1), Error::::LowBalance, ); }) @@ -1468,11 +1832,11 @@ mod tests { #[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))); + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::vote(Origin::signed(2), vec![4, 5], 30)); + assert_ok!(vote(Origin::signed(2), vec![4, 5], 30)); // you can lie but won't get away with it. assert_eq!(Elections::locked_stake_of(&2), 20); assert_eq!(has_lock(&2), 20); @@ -1481,22 +1845,22 @@ mod tests { #[test] fn remove_voter_should_work() { - ExtBuilder::default().voter_bond(8).build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + ExtBuilder::default().voter_bond(8).build_and_execute(|| { + assert_ok!(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_ok!(vote(Origin::signed(2), vec![5], 20)); + assert_ok!(vote(Origin::signed(3), vec![5], 30)); assert_eq_uvec!(all_voters(), vec![2, 3]); assert_eq!(Elections::locked_stake_of(&2), 20); assert_eq!(Elections::locked_stake_of(&3), 30); - assert_eq!(Elections::votes_of(&2), vec![5]); - assert_eq!(Elections::votes_of(&3), vec![5]); + assert_eq!(votes_of(&2), vec![5]); + assert_eq!(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!(votes_of(&2), vec![]); assert_eq!(Elections::locked_stake_of(&2), 0); assert_eq!(balances(&2), (20, 0)); @@ -1506,16 +1870,16 @@ mod tests { #[test] fn non_voter_remove_should_not_work() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { assert_noop!(Elections::remove_voter(Origin::signed(3)), Error::::MustBeVoter); }); } #[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)); + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(vote(Origin::signed(2), vec![5], 20)); assert_ok!(Elections::remove_voter(Origin::signed(2))); assert_eq!(all_voters(), vec![]); @@ -1526,19 +1890,19 @@ mod tests { #[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))); + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(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!(vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(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())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![3, 5]); }); @@ -1546,67 +1910,122 @@ mod tests { #[test] fn reporter_must_be_voter() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { assert_noop!( - Elections::report_defunct_voter(Origin::signed(1), 2), + Elections::report_defunct_voter(Origin::signed(1), defunct_for(2)), Error::::MustBeVoter, ); }); } + #[test] + fn reporter_must_provide_lengths() { + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + + // both are defunct. + assert_ok!(vote(Origin::signed(5), vec![99, 999, 9999], 50)); + assert_ok!(vote(Origin::signed(4), vec![999], 40)); + + // 3 candidates! incorrect candidate length. + assert_noop!( + Elections::report_defunct_voter(Origin::signed(4), DefunctVoter { + who: 5, + candidate_count: 2, + vote_count: 3, + }), + Error::::InvalidCandidateCount, + ); + + // 3 votes! incorrect vote length + assert_noop!( + Elections::report_defunct_voter(Origin::signed(4), DefunctVoter { + who: 5, + candidate_count: 3, + vote_count: 2, + }), + Error::::InvalidVoteCount, + ); + + // correct. + assert_ok!(Elections::report_defunct_voter(Origin::signed(4), DefunctVoter { + who: 5, + candidate_count: 3, + vote_count: 3, + })); + }); + } + + #[test] + fn reporter_can_overestimate_length() { + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + + // both are defunct. + assert_ok!(vote(Origin::signed(5), vec![99], 50)); + assert_ok!(vote(Origin::signed(4), vec![999], 40)); + + // 2 candidates! overestimation is okay. + assert_ok!(Elections::report_defunct_voter(Origin::signed(4), defunct_for(5))); + }); + } + #[test] fn can_detect_defunct_voter() { - ExtBuilder::default().desired_runners_up(2).build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(6))); - - 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)); - assert_ok!(Elections::vote(Origin::signed(6), vec![6], 30)); + ExtBuilder::default().desired_runners_up(2).build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(6))); + + assert_ok!(vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(2), vec![4, 5], 20)); + assert_ok!(vote(Origin::signed(6), vec![6], 30)); // will be soon a defunct voter. - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![4, 5]); assert_eq!(Elections::runners_up_ids(), vec![6]); assert_eq!(Elections::candidates(), vec![]); // all of them have a member or runner-up 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); - assert_eq!(Elections::is_defunct_voter(&6), false); + assert_eq!(Elections::is_defunct_voter(&votes_of(&5)), false); + assert_eq!(Elections::is_defunct_voter(&votes_of(&4)), false); + assert_eq!(Elections::is_defunct_voter(&votes_of(&2)), false); + assert_eq!(Elections::is_defunct_voter(&votes_of(&6)), false); // defunct - assert_eq!(Elections::is_defunct_voter(&3), true); + assert_eq!(Elections::is_defunct_voter(&votes_of(&3)), true); - assert_ok!(Elections::submit_candidacy(Origin::signed(1))); - assert_ok!(Elections::vote(Origin::signed(1), vec![1], 10)); + assert_ok!(submit_candidacy(Origin::signed(1))); + assert_ok!(vote(Origin::signed(1), vec![1], 10)); // has a candidate voted for. - assert_eq!(Elections::is_defunct_voter(&1), false); + assert_eq!(Elections::is_defunct_voter(&votes_of(&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))); + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(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)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(2), vec![4, 5], 20)); // will be soon a defunct voter. - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![4, 5]); assert_eq!(Elections::candidates(), vec![]); @@ -1614,7 +2033,7 @@ mod tests { assert_eq!(balances(&3), (28, 2)); assert_eq!(balances(&5), (45, 5)); - assert_ok!(Elections::report_defunct_voter(Origin::signed(5), 3)); + assert_ok!(Elections::report_defunct_voter(Origin::signed(5), defunct_for(3))); assert!(System::events().iter().any(|event| { event.event == Event::elections_phragmen(RawEvent::VoterReported(3, 5, true)) })); @@ -1626,15 +2045,15 @@ mod tests { #[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))); + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(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!(vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![4, 5]); assert_eq!(Elections::candidates(), vec![]); @@ -1642,7 +2061,7 @@ mod tests { assert_eq!(balances(&4), (35, 5)); assert_eq!(balances(&5), (45, 5)); - assert_ok!(Elections::report_defunct_voter(Origin::signed(5), 4)); + assert_ok!(Elections::report_defunct_voter(Origin::signed(5), defunct_for(4))); assert!(System::events().iter().any(|event| { event.event == Event::elections_phragmen(RawEvent::VoterReported(4, 5, false)) })); @@ -1652,23 +2071,22 @@ mod tests { }); } - #[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))); + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(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_ok!(vote(Origin::signed(2), vec![5], 20)); + assert_ok!(vote(Origin::signed(4), vec![4], 15)); + assert_ok!(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!(votes_of(&2), vec![5]); + assert_eq!(votes_of(&3), vec![3]); + assert_eq!(votes_of(&4), vec![4]); assert_eq!(Elections::candidates(), vec![3, 4, 5]); assert_eq!(>::decode_len().unwrap(), 3); @@ -1676,13 +2094,13 @@ mod tests { assert_eq!(Elections::election_rounds(), 0); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + 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!(>::decode_len(), None); assert_eq!(Elections::election_rounds(), 1); }); @@ -1690,24 +2108,24 @@ mod tests { #[test] fn defunct_voter_will_be_counted() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + ExtBuilder::default().build_and_execute(|| { + assert_ok!(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)); + assert_ok!(vote(Origin::signed(3), vec![4], 30)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + 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))); + assert_ok!(submit_candidacy(Origin::signed(4))); System::set_block_number(10); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); // candidate 4 is affected by an old vote. assert_eq!(Elections::members(), vec![(4, 30), (5, 50)]); @@ -1718,19 +2136,19 @@ mod tests { #[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))); + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + assert_ok!(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)); + assert_ok!(vote(Origin::signed(2), vec![2], 20)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::election_rounds(), 1); assert_eq!(Elections::members_ids(), vec![4, 5]); @@ -1739,34 +2157,39 @@ mod tests { #[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))); + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::candidates(), vec![]); assert_eq!(Elections::election_rounds(), 1); assert_eq!(Elections::members_ids(), vec![]); + + assert_eq!( + System::events().iter().last().unwrap().event, + Event::elections_phragmen(RawEvent::NewTerm(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))); + ExtBuilder::default().desired_runners_up(2).build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + assert_ok!(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)); + assert_ok!(vote(Origin::signed(2), vec![3], 20)); + assert_ok!(vote(Origin::signed(3), vec![2], 30)); + assert_ok!(vote(Origin::signed(4), vec![5], 40)); + assert_ok!(vote(Origin::signed(5), vec![4], 50)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + 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) @@ -1781,26 +2204,26 @@ mod tests { #[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))); + ExtBuilder::default().desired_runners_up(2).build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + assert_ok!(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)); + assert_ok!(vote(Origin::signed(2), vec![2], 20)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + 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)); + assert_ok!(vote(Origin::signed(5), vec![5], 15)); System::set_block_number(10); - assert_ok!(Elections::end_block(System::block_number())); + 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)]); }); @@ -1808,26 +2231,26 @@ mod tests { #[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))); + ExtBuilder::default().desired_runners_up(1).build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(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)); + assert_ok!(vote(Origin::signed(2), vec![2], 20)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + 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)); + assert_ok!(submit_candidacy(Origin::signed(3))); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); System::set_block_number(10); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::runners_up_ids(), vec![3]); assert_eq!(balances(&2), (15, 2)); @@ -1836,24 +2259,24 @@ mod tests { #[test] fn members_lose_bond_once_outgoing() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { assert_eq!(balances(&5), (50, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(5))); assert_eq!(balances(&5), (47, 3)); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_ok!(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())); + 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())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![]); assert_eq!(balances(&5), (47, 0)); @@ -1862,17 +2285,17 @@ mod tests { #[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))); + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::vote(Origin::signed(4), vec![5], 40)); + assert_ok!(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())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![5]); @@ -1885,24 +2308,24 @@ mod tests { #[test] fn current_members_are_always_next_candidate() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(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)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + 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!(submit_candidacy(Origin::signed(2))); + assert_ok!(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!(submit_candidacy(Origin::signed(3))); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); assert_ok!(Elections::remove_voter(Origin::signed(4))); @@ -1910,7 +2333,7 @@ mod tests { assert_eq!(Elections::candidates(), vec![2, 3]); System::set_block_number(10); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); // 4 removed; 5 and 3 are the new best. assert_eq!(Elections::members_ids(), vec![3, 5]); @@ -1921,20 +2344,20 @@ mod tests { 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))); + ExtBuilder::default().desired_runners_up(2).build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + assert_ok!(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)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + assert_ok!(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())); + 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)]); @@ -1954,23 +2377,23 @@ mod tests { #[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))); + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(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)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + 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!(submit_candidacy(Origin::signed(3))); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); - assert_ok!(Elections::remove_member(Origin::ROOT, 4)); + assert_ok!(Elections::remove_member(Origin::root(), 4, false)); assert_eq!(balances(&4), (35, 2)); // slashed assert_eq!(Elections::election_rounds(), 2); // new election round @@ -1978,24 +2401,68 @@ mod tests { }); } + #[test] + fn remove_member_should_indicate_replacement() { + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); + + System::set_block_number(5); + Elections::end_block(System::block_number()); + assert_eq!(Elections::members_ids(), vec![4, 5]); + + // no replacement yet. + assert_err_with_weight!( + Elections::remove_member(Origin::root(), 4, true), + Error::::InvalidReplacement, + Some(6000000), + ); + }); + + ExtBuilder::default().desired_runners_up(1).build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); + + System::set_block_number(5); + Elections::end_block(System::block_number()); + assert_eq!(Elections::members_ids(), vec![4, 5]); + assert_eq!(Elections::runners_up_ids(), vec![3]); + + // there is a replacement! and this one needs a weight refund. + assert_err_with_weight!( + Elections::remove_member(Origin::root(), 4, false), + Error::::InvalidReplacement, + Some(6000000) // only thing that matters for now is that it is NOT the full block. + ); + }); + } + #[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))); + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(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_ok!(vote(Origin::signed(2), vec![3], 20)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(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())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![3, 5]); assert_eq!(Elections::election_rounds(), 1); @@ -2006,7 +2473,7 @@ mod tests { // meanwhile, no one cares to become a candidate again. System::set_block_number(10); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![]); assert_eq!(Elections::election_rounds(), 2); }); @@ -2014,33 +2481,33 @@ mod tests { #[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))); + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(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)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + 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))); + assert_ok!(submit_candidacy(Origin::signed(1))); + assert_ok!(submit_candidacy(Origin::signed(2))); + assert_ok!(submit_candidacy(Origin::signed(3))); // 5 will change their vote and becomes an `outgoing` - assert_ok!(Elections::vote(Origin::signed(5), vec![4], 8)); + assert_ok!(vote(Origin::signed(5), vec![4], 8)); // 4 will stay in the set - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); // 3 will become a winner - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(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)); + assert_ok!(vote(Origin::signed(2), vec![2], 20)); + assert_ok!(vote(Origin::signed(1), vec![1], 10)); System::set_block_number(10); - assert_ok!(Elections::end_block(System::block_number())); + 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)]); @@ -2061,16 +2528,16 @@ mod tests { #[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))); + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(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)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![10], 50)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq_uvec!(Elections::members_ids(), vec![3, 4]); assert_eq!(Elections::election_rounds(), 1); @@ -2079,19 +2546,19 @@ mod tests { #[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))); + ExtBuilder::default().desired_runners_up(2).build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + assert_ok!(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)); + assert_ok!(vote(Origin::signed(2), vec![3], 20)); + assert_ok!(vote(Origin::signed(3), vec![2], 30)); + assert_ok!(vote(Origin::signed(4), vec![5], 40)); + assert_ok!(vote(Origin::signed(5), vec![4], 50)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); // id: low -> high. assert_eq!(Elections::members(), vec![(4, 50), (5, 40)]); // merit: low -> high. @@ -2101,15 +2568,15 @@ mod tests { #[test] fn candidates_are_sorted() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(3))); assert_eq!(Elections::candidates(), vec![3, 5]); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::renounce_candidacy(Origin::signed(3))); + assert_ok!(submit_candidacy(Origin::signed(2))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::renounce_candidacy(Origin::signed(3), Renouncing::Candidate(4))); assert_eq!(Elections::candidates(), vec![2, 4, 5]); }) @@ -2117,65 +2584,44 @@ mod tests { #[test] fn runner_up_replacement_maintains_members_order() { - 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(2))); + ExtBuilder::default().desired_runners_up(2).build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(2))); - assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(5), vec![2], 50)); + assert_ok!(vote(Origin::signed(2), vec![5], 20)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![2], 50)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![2, 4]); - assert_ok!(Elections::remove_member(Origin::ROOT, 2)); + assert_ok!(Elections::remove_member(Origin::root(), 2, true)); assert_eq!(Elections::members_ids(), vec![4, 5]); }); } - #[test] - fn runner_up_replacement_works_when_out_of_order() { - 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![5], 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![2], 50)); - - System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members_ids(), vec![2, 4]); - assert_ok!(Elections::renounce_candidacy(Origin::signed(3))); - }); - } - #[test] fn can_renounce_candidacy_member_with_runners_bond_is_refunded() { - 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))); + ExtBuilder::default().desired_runners_up(2).build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + assert_ok!(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)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(2), vec![2], 20)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![4, 5]); assert_eq!(Elections::runners_up_ids(), vec![2, 3]); - assert_ok!(Elections::renounce_candidacy(Origin::signed(4))); + assert_ok!(Elections::renounce_candidacy(Origin::signed(4), Renouncing::Member)); assert_eq!(balances(&4), (38, 2)); // 2 is voting bond. assert_eq!(Elections::members_ids(), vec![3, 5]); @@ -2185,56 +2631,48 @@ mod tests { #[test] fn can_renounce_candidacy_member_without_runners_bond_is_refunded() { - 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))); + ExtBuilder::default().desired_runners_up(2).build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(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!(vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![4, 5]); assert_eq!(Elections::runners_up_ids(), vec![]); - assert_eq!(Elections::candidates(), vec![2, 3]); - assert_ok!(Elections::renounce_candidacy(Origin::signed(4))); + assert_ok!(Elections::renounce_candidacy(Origin::signed(4), Renouncing::Member)); assert_eq!(balances(&4), (38, 2)); // 2 is voting bond. // no replacement assert_eq!(Elections::members_ids(), vec![5]); assert_eq!(Elections::runners_up_ids(), vec![]); - // still candidate - assert_eq!(Elections::candidates(), vec![2, 3]); }) } #[test] fn can_renounce_candidacy_runner() { - 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))); + ExtBuilder::default().desired_runners_up(2).build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + assert_ok!(submit_candidacy(Origin::signed(2))); - assert_ok!(Elections::vote(Origin::signed(5), vec![4], 50)); - assert_ok!(Elections::vote(Origin::signed(4), vec![5], 40)); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); + assert_ok!(vote(Origin::signed(5), vec![4], 50)); + assert_ok!(vote(Origin::signed(4), vec![5], 40)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(2), vec![2], 20)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![4, 5]); assert_eq!(Elections::runners_up_ids(), vec![2, 3]); - assert_ok!(Elections::renounce_candidacy(Origin::signed(3))); + assert_ok!(Elections::renounce_candidacy(Origin::signed(3), Renouncing::RunnerUp)); assert_eq!(balances(&3), (28, 2)); // 2 is voting bond. assert_eq!(Elections::members_ids(), vec![4, 5]); @@ -2242,14 +2680,38 @@ mod tests { }) } + // #[test] + // fn runner_up_replacement_works_when_out_of_order() { + // ExtBuilder::default().desired_runners_up(2).build_and_execute(|| { + // assert_ok!(submit_candidacy(Origin::signed(5))); + // assert_ok!(submit_candidacy(Origin::signed(4))); + // assert_ok!(submit_candidacy(Origin::signed(3))); + // assert_ok!(submit_candidacy(Origin::signed(2))); + + // assert_ok!(vote(Origin::signed(2), vec![5], 20)); + // assert_ok!(vote(Origin::signed(3), vec![3], 30)); + // assert_ok!(vote(Origin::signed(4), vec![4], 40)); + // assert_ok!(vote(Origin::signed(5), vec![2], 50)); + + // System::set_block_number(5); + // Elections::end_block(System::block_number()); + + // assert_eq!(Elections::members_ids(), vec![2, 4]); + // assert_eq!(ELections::runners_up_ids(), vec![3, 5]); + // assert_ok!(Elections::renounce_candidacy(Origin::signed(3), Renouncing::RunnerUp)); + // assert_eq!(Elections::members_ids(), vec![2, 4]); + // assert_eq!(ELections::runners_up_ids(), vec![5]); + // }); + // } + #[test] fn can_renounce_candidacy_candidate() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); assert_eq!(balances(&5), (47, 3)); assert_eq!(Elections::candidates(), vec![5]); - assert_ok!(Elections::renounce_candidacy(Origin::signed(5))); + assert_ok!(Elections::renounce_candidacy(Origin::signed(5), Renouncing::Candidate(1))); assert_eq!(balances(&5), (50, 0)); assert_eq!(Elections::candidates(), vec![]); }) @@ -2257,26 +2719,109 @@ mod tests { #[test] fn wrong_renounce_candidacy_should_fail() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { + assert_noop!( + Elections::renounce_candidacy(Origin::signed(5), Renouncing::Candidate(0)), + Error::::InvalidRenouncing, + ); + assert_noop!( + Elections::renounce_candidacy(Origin::signed(5), Renouncing::Member), + Error::::NotMember, + ); + assert_noop!( + Elections::renounce_candidacy(Origin::signed(5), Renouncing::RunnerUp), + Error::::InvalidRenouncing, + ); + }) + } + + #[test] + fn non_member_renounce_member_should_fail() { + ExtBuilder::default().desired_runners_up(1).build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + + assert_ok!(vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + + System::set_block_number(5); + Elections::end_block(System::block_number()); + + assert_eq!(Elections::members_ids(), vec![4, 5]); + assert_eq!(Elections::runners_up_ids(), vec![3]); + + assert_noop!( + Elections::renounce_candidacy(Origin::signed(3), Renouncing::Member), + Error::::NotMember, + ); + }) + } + + #[test] + fn non_runner_up_renounce_runner_up_should_fail() { + ExtBuilder::default().desired_runners_up(1).build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + + assert_ok!(vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + + System::set_block_number(5); + Elections::end_block(System::block_number()); + + assert_eq!(Elections::members_ids(), vec![4, 5]); + assert_eq!(Elections::runners_up_ids(), vec![3]); + + assert_noop!( + Elections::renounce_candidacy(Origin::signed(4), Renouncing::RunnerUp), + Error::::InvalidRenouncing, + ); + }) + } + + #[test] + fn wrong_candidate_count_renounce_should_fail() { + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + assert_noop!( - Elections::renounce_candidacy(Origin::signed(5)), - Error::::InvalidOrigin, + Elections::renounce_candidacy(Origin::signed(4), Renouncing::Candidate(2)), + Error::::InvalidRenouncing, ); + + assert_ok!(Elections::renounce_candidacy(Origin::signed(4), Renouncing::Candidate(3))); + }) + } + + #[test] + fn renounce_candidacy_count_can_overestimate() { + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + // while we have only 3 candidates. + assert_ok!(Elections::renounce_candidacy(Origin::signed(4), Renouncing::Candidate(4))); }) } #[test] fn behavior_with_dupe_candidate() { - ExtBuilder::default().desired_runners_up(2).build().execute_with(|| { + ExtBuilder::default().desired_runners_up(2).build_and_execute(|| { >::put(vec![1, 1, 2, 3, 4]); - assert_ok!(Elections::vote(Origin::signed(5), vec![1], 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)); + assert_ok!(vote(Origin::signed(5), vec![1], 50)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(2), vec![2], 20)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![1, 4]); assert_eq!(Elections::runners_up_ids(), vec![2, 3]); diff --git a/frame/elections/Cargo.toml b/frame/elections/Cargo.toml index 6043ac4681e212afb462540552af02639c8af4bd..b7914d66fd70bf44d38563275e4451af566c5570 100644 --- a/frame/elections/Cargo.toml +++ b/frame/elections/Cargo.toml @@ -1,26 +1,29 @@ [package] name = "pallet-elections" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for elections" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/core" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/core" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } [dev-dependencies] hex-literal = "0.2.1" -pallet-balances = { version = "2.0.0-alpha.5", path = "../balances" } +pallet-balances = { version = "2.0.0-rc4", path = "../balances" } [features] default = ["std"] @@ -34,6 +37,3 @@ std = [ "sp-runtime/std", "frame-system/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/elections/src/lib.rs b/frame/elections/src/lib.rs index a8ea0b8c2e4555d8990ba485e749f3c49b11024c..c9d3c5455fc789c5d93ae1f2a18b7a300cddab9f 100644 --- a/frame/elections/src/lib.rs +++ b/frame/elections/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Election module for stake-weighted membership selection of a collective. //! @@ -30,14 +31,14 @@ use sp_runtime::{ }; use frame_support::{ decl_storage, decl_event, ensure, decl_module, decl_error, - weights::{Weight, SimpleDispatchInfo, WeighData}, + weights::{Weight, DispatchClass}, traits::{ Currency, ExistenceRequirement, Get, LockableCurrency, LockIdentifier, BalanceStatus, - OnUnbalanced, ReservableCurrency, WithdrawReason, WithdrawReasons, ChangeMembers + OnUnbalanced, ReservableCurrency, WithdrawReason, WithdrawReasons, ChangeMembers, } }; use codec::{Encode, Decode}; -use frame_system::{self as system, ensure_signed, ensure_root}; +use frame_system::{ensure_signed, ensure_root}; mod mock; mod tests; @@ -126,8 +127,6 @@ pub enum CellStatus { Hole, } -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. @@ -149,6 +148,9 @@ const APPROVAL_FLAG_LEN: usize = 32; pub trait Trait: frame_system::Trait { type Event: From> + Into<::Event>; + /// Identifier for the elections pallet's lock + type ModuleId: Get; + /// The currency that people are electing with. type Currency: LockableCurrency @@ -235,16 +237,25 @@ decl_storage! { // 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`. + /// + /// TWOX-NOTE: SAFE as `AccountId` is a crypto hash and `SetIndex` is not + /// attacker-controlled. pub ApprovalsOf get(fn approvals_of): map hasher(twox_64_concat) (T::AccountId, SetIndex) => Vec; /// The vote index and list slot that the candidate `who` was registered or `None` if they /// are not currently registered. + /// + /// TWOX-NOTE: SAFE as `AccountId` is a crypto hash. pub RegisterInfoOf get(fn candidate_reg_info): map hasher(twox_64_concat) T::AccountId => Option<(VoteIndex, u32)>; /// Basic information about a voter. + /// + /// TWOX-NOTE: SAFE as `AccountId` is a crypto hash. pub VoterInfoOf get(fn voter_info): map hasher(twox_64_concat) T::AccountId => Option>>; /// The present voter list (chunked and capped at [`VOTER_SET_SIZE`]). + /// + /// TWOX-NOTE: OKAY ― `SetIndex` is not user-controlled data. pub Voters get(fn voters): map hasher(twox_64_concat) SetIndex => Vec>; /// the next free set to store a voter in. This will keep growing. pub NextVoterSet get(fn next_nonfull_voter_set): SetIndex = 0; @@ -263,10 +274,6 @@ decl_storage! { /// 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(fn proxy): map hasher(blake2_128_concat) T::AccountId => Option; } } @@ -281,8 +288,6 @@ decl_error! { CannotReapPresenting, /// Cannot reap during grace period. ReapGrace, - /// Not a proxy. - NotProxy, /// Invalid reporter index. InvalidReporterIndex, /// Invalid target index. @@ -379,6 +384,8 @@ decl_module! { /// The chunk size of the approval vector. const APPROVAL_SET_SIZE: u32 = APPROVAL_SET_SIZE as u32; + const ModuleId: LockIdentifier = T::ModuleId::get(); + fn deposit_event() = default; /// Set candidate approvals. Approval slots stay valid as long as candidates in those slots @@ -405,35 +412,18 @@ decl_module! { /// - Two extra DB entries, one DB change. /// - Argument `votes` is limited in length to number of candidates. /// # - #[weight = SimpleDispatchInfo::FixedNormal(2_500_000)] + #[weight = 2_500_000_000] fn set_approvals( origin, votes: Vec, #[compact] index: VoteIndex, hint: SetIndex, - #[compact] value: BalanceOf + #[compact] value: BalanceOf, ) -> DispatchResult { let who = ensure_signed(origin)?; 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. - /// - /// # - /// - Same as `set_approvals` with one additional storage read. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(2_500_000)] - fn proxy_set_approvals(origin, - votes: Vec, - #[compact] index: VoteIndex, - hint: SetIndex, - #[compact] value: BalanceOf - ) -> DispatchResult { - let who = Self::proxy(ensure_signed(origin)?).ok_or(Error::::NotProxy)?; - 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. @@ -446,13 +436,13 @@ decl_module! { /// - O(1). /// - Two fewer DB entries, one DB change. /// # - #[weight = SimpleDispatchInfo::FixedNormal(2_500_000)] + #[weight = 2_500_000_000] fn reap_inactive_voter( origin, #[compact] reporter_index: u32, who: ::Source, #[compact] who_index: u32, - #[compact] assumed_vote_index: VoteIndex + #[compact] assumed_vote_index: VoteIndex, ) { let reporter = ensure_signed(origin)?; let who = T::Lookup::lookup(who)?; @@ -494,7 +484,7 @@ decl_module! { ); T::Currency::remove_lock( - MODULE_ID, + T::ModuleId::get(), if valid { &who } else { &reporter } ); @@ -520,7 +510,7 @@ decl_module! { /// - O(1). /// - Two fewer DB entries, one DB change. /// # - #[weight = SimpleDispatchInfo::FixedNormal(1_250_000)] + #[weight = 1_250_000_000] fn retract_voter(origin, #[compact] index: u32) { let who = ensure_signed(origin)?; @@ -532,7 +522,7 @@ decl_module! { Self::remove_voter(&who, index); T::Currency::unreserve(&who, T::VotingBond::get()); - T::Currency::remove_lock(MODULE_ID, &who); + T::Currency::remove_lock(T::ModuleId::get(), &who); } /// Submit oneself for candidacy. @@ -548,7 +538,7 @@ decl_module! { /// - Independent of input. /// - Three DB changes. /// # - #[weight = SimpleDispatchInfo::FixedNormal(2_500_000)] + #[weight = 2_500_000_000] fn submit_candidacy(origin, #[compact] slot: u32) { let who = ensure_signed(origin)?; @@ -585,12 +575,12 @@ decl_module! { /// - O(voters) compute. /// - One DB change. /// # - #[weight = SimpleDispatchInfo::FixedNormal(10_000_000)] + #[weight = 10_000_000_000] fn present_winner( origin, candidate: ::Source, #[compact] total: BalanceOf, - #[compact] index: VoteIndex + #[compact] index: VoteIndex, ) -> DispatchResult { let who = ensure_signed(origin)?; ensure!( @@ -659,7 +649,7 @@ decl_module! { /// Set the desired member count; if lower than the current count, then seats will not be up /// election when they expire. If more, then a new vote will be started if one is not /// already in progress. - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + #[weight = (0, DispatchClass::Operational)] fn set_desired_seats(origin, #[compact] count: u32) { ensure_root(origin)?; DesiredSeats::put(count); @@ -669,7 +659,7 @@ decl_module! { /// /// Note: A tally should happen instantly (if not already in a presentation /// period) to fill the seat if removal means that the desired members are not met. - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + #[weight = (0, DispatchClass::Operational)] fn remove_member(origin, who: ::Source) { ensure_root(origin)?; let who = T::Lookup::lookup(who)?; @@ -684,7 +674,7 @@ decl_module! { /// Set the presentation duration. If there is currently a vote being presented for, will /// invoke `finalize_vote`. - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + #[weight = (0, DispatchClass::Operational)] fn set_presentation_duration(origin, #[compact] count: T::BlockNumber) { ensure_root(origin)?; >::put(count); @@ -692,7 +682,7 @@ decl_module! { /// Set the presentation duration. If there is current a vote being presented for, will /// invoke `finalize_vote`. - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + #[weight = (0, DispatchClass::Operational)] fn set_term_duration(origin, #[compact] count: T::BlockNumber) { ensure_root(origin)?; >::put(count); @@ -703,7 +693,7 @@ decl_module! { print("Guru meditation"); print(e); } - SimpleDispatchInfo::default().weigh_data(()) + 0 } } } @@ -883,7 +873,7 @@ impl Module { if set_len + 1 == VOTER_SET_SIZE { NextVoterSet::put(next + 1); } - >::append_or_insert(next, &[Some(who.clone())][..]) + >::append(next, Some(who.clone())); } } @@ -892,7 +882,7 @@ impl Module { } T::Currency::set_lock( - MODULE_ID, + T::ModuleId::get(), &who, locked_balance, WithdrawReasons::all(), diff --git a/frame/elections/src/mock.rs b/frame/elections/src/mock.rs index 2898be26ca3001200d1806297b4695a655e212ea..c9b2523c4bc8a8dbb705b541bf5bd4e37525dd39 100644 --- a/frame/elections/src/mock.rs +++ b/frame/elections/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Mock file for election module. @@ -21,7 +22,7 @@ use std::cell::RefCell; use frame_support::{ StorageValue, StorageMap, parameter_types, assert_ok, - traits::{Get, ChangeMembers, Currency}, + traits::{Get, ChangeMembers, Currency, LockIdentifier}, weights::Weight, }; use sp_core::H256; @@ -38,8 +39,9 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; - type Call = (); + type Call = Call; type Index = u64; type BlockNumber = u64; type Hash = H256; @@ -50,6 +52,10 @@ impl frame_system::Trait for Test { type Event = Event; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -57,6 +63,7 @@ impl frame_system::Trait for Test { type AccountData = pallet_balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } parameter_types! { @@ -68,6 +75,7 @@ impl pallet_balances::Trait for Test { type Event = Event; type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; + type WeightInfo = (); } parameter_types! { @@ -121,6 +129,10 @@ impl ChangeMembers for TestChangeMembers { } } +parameter_types!{ + pub const ElectionModuleId: LockIdentifier = *b"py/elect"; +} + impl elections::Trait for Test { type Event = Event; type Currency = Balances; @@ -138,6 +150,7 @@ impl elections::Trait for Test { type InactiveGracePeriod = InactiveGracePeriod; type VotingPeriod = VotingPeriod; type DecayRatio = DecayRatio; + type ModuleId = ElectionModuleId; } pub type Block = sp_runtime::generic::Block; diff --git a/frame/elections/src/tests.rs b/frame/elections/src/tests.rs index 64b01f12e0cfe8c3b9971bee6e3772f4a2fb2adf..247b6272524b1c64073e4a6157af1b2a5e2bd3a3 100644 --- a/frame/elections/src/tests.rs +++ b/frame/elections/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for election module. @@ -670,7 +671,7 @@ fn retracting_active_voter_should_slash_reporter() { 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::set_desired_seats(Origin::root(), 3)); assert_ok!(Elections::end_block(System::block_number())); System::set_block_number(10); @@ -867,45 +868,6 @@ fn election_voting_should_work() { }); } -#[test] -fn election_proxy_voting_should_work() { - ExtBuilder::default().build().execute_with(|| { - 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(|| { @@ -1283,7 +1245,7 @@ fn election_second_tally_should_use_runners_up() { 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::set_desired_seats(Origin::root(), 3)); assert_ok!(Elections::end_block(System::block_number())); System::set_block_number(10); diff --git a/frame/evm/Cargo.toml b/frame/evm/Cargo.toml index 95b3c24d8796e683c30c60d6a2cb3e3a5ffd4990..8b030be4b7a54c6b39a7f0d8f57e01f1197ea557 100644 --- a/frame/evm/Cargo.toml +++ b/frame/evm/Cargo.toml @@ -1,24 +1,27 @@ [package] name = "pallet-evm" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME EVM contracts pallet" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } -pallet-timestamp = { version = "2.0.0-alpha.5", default-features = false, path = "../timestamp" } -pallet-balances = { version = "2.0.0-alpha.5", default-features = false, path = "../balances" } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/core" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/io" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } +pallet-timestamp = { version = "2.0.0-rc4", default-features = false, path = "../timestamp" } +pallet-balances = { version = "2.0.0-rc4", default-features = false, path = "../balances" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/core" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } primitive-types = { version = "0.7.0", default-features = false, features = ["rlp"] } rlp = { version = "0.4", default-features = false } evm = { version = "0.16", default-features = false } @@ -42,6 +45,3 @@ std = [ "evm/std", "pallet-timestamp/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/evm/src/backend.rs b/frame/evm/src/backend.rs index c610f24bb1db2d763979e978dd183c5719a731b9..09f31d8aeba83392e038b6f4ffbba3ff6c4f71fa 100644 --- a/frame/evm/src/backend.rs +++ b/frame/evm/src/backend.rs @@ -5,6 +5,7 @@ use serde::{Serialize, Deserialize}; use codec::{Encode, Decode}; use sp_core::{U256, H256, H160}; use sp_runtime::traits::UniqueSaturatedInto; +use frame_support::traits::Get; use frame_support::storage::{StorageMap, StorageDoubleMap}; use sha3::{Keccak256, Digest}; use evm::backend::{Backend as BackendT, ApplyBackend, Apply}; @@ -91,7 +92,7 @@ impl<'vicinity, T: Trait> BackendT for Backend<'vicinity, T> { } fn chain_id(&self) -> U256 { - U256::from(sp_io::misc::chain_id()) + U256::from(T::ChainId::get()) } fn exists(&self, _address: H160) -> bool { diff --git a/frame/evm/src/lib.rs b/frame/evm/src/lib.rs index a50c545a461c1937d9d58eb06a86ff372558ca66..e2d99827dc954fc322e99bdebea43b26515ce424 100644 --- a/frame/evm/src/lib.rs +++ b/frame/evm/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! EVM execution module for Substrate @@ -20,27 +21,30 @@ #![cfg_attr(not(feature = "std"), no_std)] mod backend; +mod tests; pub use crate::backend::{Account, Log, Vicinity, Backend}; use sp_std::{vec::Vec, marker::PhantomData}; +#[cfg(feature = "std")] +use codec::{Encode, Decode}; +#[cfg(feature = "std")] +use serde::{Serialize, Deserialize}; use frame_support::{ensure, decl_module, decl_storage, decl_event, decl_error}; -use frame_support::weights::{Weight, DispatchClass, FunctionOf}; -use frame_support::traits::{Currency, WithdrawReason, ExistenceRequirement}; -use frame_system::{self as system, ensure_signed}; +use frame_support::weights::Weight; +use frame_support::traits::{Currency, WithdrawReason, ExistenceRequirement, Get}; +use frame_system::ensure_signed; use sp_runtime::ModuleId; -use frame_support::weights::SimpleDispatchInfo; use sp_core::{U256, H256, H160, Hasher}; use sp_runtime::{ DispatchResult, traits::{UniqueSaturatedInto, AccountIdConversion, SaturatedConversion}, }; use sha3::{Digest, Keccak256}; -use evm::{ExitReason, ExitSucceed, ExitError, Config}; +pub use evm::{ExitReason, ExitSucceed, ExitError, ExitRevert, ExitFatal}; +use evm::Config; use evm::executor::StackExecutor; use evm::backend::ApplyBackend; -const MODULE_ID: ModuleId = ModuleId(*b"py/ethvm"); - /// Type alias for currency balance. pub type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; @@ -116,10 +120,21 @@ impl Precompiles for () { } } +/// Substrate system chain ID. +pub struct SystemChainId; + +impl Get for SystemChainId { + fn get() -> u64 { + sp_io::misc::chain_id() + } +} + static ISTANBUL_CONFIG: Config = Config::istanbul(); /// EVM module trait pub trait Trait: frame_system::Trait + pallet_timestamp::Trait { + /// The EVM's module id + type ModuleId: Get; /// Calculator for current gas price. type FeeCalculator: FeeCalculator; /// Convert account ID to H160; @@ -130,6 +145,8 @@ pub trait Trait: frame_system::Trait + pallet_timestamp::Trait { type Event: From> + Into<::Event>; /// Precompiles associated with this EVM engine. type Precompiles: Precompiles; + /// Chain ID of EVM. + type ChainId: Get; /// EVM config used in the module. fn config() -> &'static Config { @@ -137,11 +154,43 @@ pub trait Trait: frame_system::Trait + pallet_timestamp::Trait { } } +#[cfg(feature = "std")] +#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, Serialize, Deserialize)] +/// Account definition used for genesis block construction. +pub struct GenesisAccount { + /// Account nonce. + pub nonce: U256, + /// Account balance. + pub balance: U256, + /// Full account storage. + pub storage: std::collections::BTreeMap, + /// Account code. + pub code: Vec, +} + decl_storage! { trait Store for Module as EVM { - Accounts get(fn accounts) config(): map hasher(blake2_128_concat) H160 => Account; - AccountCodes: map hasher(blake2_128_concat) H160 => Vec; - AccountStorages: double_map hasher(blake2_128_concat) H160, hasher(blake2_128_concat) H256 => H256; + Accounts get(fn accounts): map hasher(blake2_128_concat) H160 => Account; + AccountCodes get(fn account_codes): map hasher(blake2_128_concat) H160 => Vec; + AccountStorages get(fn account_storages): + double_map hasher(blake2_128_concat) H160, hasher(blake2_128_concat) H256 => H256; + } + + add_extra_genesis { + config(accounts): std::collections::BTreeMap; + build(|config: &GenesisConfig| { + for (address, account) in &config.accounts { + Accounts::insert(address, Account { + balance: account.balance, + nonce: account.nonce, + }); + AccountCodes::insert(address, &account.code); + + for (index, value) in &account.storage { + AccountStorages::insert(address, index, value); + } + } + }); } } @@ -154,6 +203,12 @@ decl_event! { Log(Log), /// A contract has been created at given address. Created(H160), + /// A contract was attempted to be created, but the execution failed. + CreatedFailed(H160), + /// A contract has been executed successfully with states applied. + Executed(H160), + /// A contract has been executed with errors. States are reverted with only gas fees applied. + ExecutedFailed(H160), /// A deposit has been made at a given address. BalanceDeposit(AccountId, H160, U256), /// A withdrawal has been made from a given address. @@ -173,12 +228,6 @@ decl_error! { WithdrawFailed, /// Gas price is too low. GasPriceTooLow, - /// Call failed - ExitReasonFailed, - /// Call reverted - ExitReasonRevert, - /// Call returned VM fatal error - ExitReasonFatal, /// Nonce is invalid InvalidNonce, } @@ -190,8 +239,10 @@ decl_module! { fn deposit_event() = default; + const ModuleId: ModuleId = T::ModuleId::get(); + /// Deposit balance from currency/balances module into EVM. - #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + #[weight = 0] fn deposit_balance(origin, value: BalanceOf) { let sender = ensure_signed(origin)?; @@ -212,7 +263,7 @@ decl_module! { } /// Withdraw balance from EVM into currency/balances module. - #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + #[weight = 0] fn withdraw_balance(origin, value: BalanceOf) { let sender = ensure_signed(origin)?; let address = T::ConvertAccountId::convert_account_id(&sender); @@ -236,7 +287,7 @@ decl_module! { } /// Issue an EVM call operation. This is similar to a message call transaction in Ethereum. - #[weight = FunctionOf(|(_, _, _, gas_limit, gas_price, _): (&H160, &Vec, &U256, &u32, &U256, &Option)| (*gas_price).saturated_into::().saturating_mul(*gas_limit), DispatchClass::Normal, true)] + #[weight = (*gas_price).saturated_into::().saturating_mul(*gas_limit as Weight)] fn call( origin, target: H160, @@ -246,28 +297,34 @@ decl_module! { gas_price: U256, nonce: Option, ) -> DispatchResult { + ensure!(gas_price >= T::FeeCalculator::min_gas_price(), Error::::GasPriceTooLow); + let sender = ensure_signed(origin)?; let source = T::ConvertAccountId::convert_account_id(&sender); - Self::execute_evm( + match Self::execute_call( source, + target, + input, value, gas_limit, gas_price, nonce, - |executor| ((), executor.transact_call( - source, - target, - value, - input, - gas_limit as usize, - )), - ).map_err(Into::into) + )? { + ExitReason::Succeed(_) => { + Module::::deposit_event(Event::::Executed(target)); + }, + ExitReason::Error(_) | ExitReason::Revert(_) | ExitReason::Fatal(_) => { + Module::::deposit_event(Event::::ExecutedFailed(target)); + }, + } + + Ok(()) } /// Issue an EVM create operation. This is similar to a contract creation transaction in /// Ethereum. - #[weight = FunctionOf(|(_, _, gas_limit, gas_price, _): (&Vec, &U256, &u32, &U256, &Option)| (*gas_price).saturated_into::().saturating_mul(*gas_limit), DispatchClass::Normal, true)] + #[weight = (*gas_price).saturated_into::().saturating_mul(*gas_limit as Weight)] fn create( origin, init: Vec, @@ -276,33 +333,32 @@ decl_module! { gas_price: U256, nonce: Option, ) -> DispatchResult { + ensure!(gas_price >= T::FeeCalculator::min_gas_price(), Error::::GasPriceTooLow); + let sender = ensure_signed(origin)?; let source = T::ConvertAccountId::convert_account_id(&sender); - let create_address = Self::execute_evm( + match Self::execute_create( source, + init, value, gas_limit, gas_price, - nonce, - |executor| { - (executor.create_address( - evm::CreateScheme::Legacy { caller: source }, - ), executor.transact_create( - source, - value, - init, - gas_limit as usize, - )) + nonce + )? { + (create_address, ExitReason::Succeed(_)) => { + Module::::deposit_event(Event::::Created(create_address)); }, - )?; + (create_address, _) => { + Module::::deposit_event(Event::::CreatedFailed(create_address)); + }, + } - Module::::deposit_event(Event::::Created(create_address)); Ok(()) } /// Issue an EVM create2 operation. - #[weight = FunctionOf(|(_, _, _, gas_limit, gas_price, _): (&Vec, &H256, &U256, &u32, &U256, &Option)| (*gas_price).saturated_into::().saturating_mul(*gas_limit), DispatchClass::Normal, true)] + #[weight = (*gas_price).saturated_into::().saturating_mul(*gas_limit as Weight)] fn create2( origin, init: Vec, @@ -312,30 +368,28 @@ decl_module! { gas_price: U256, nonce: Option, ) -> DispatchResult { + ensure!(gas_price >= T::FeeCalculator::min_gas_price(), Error::::GasPriceTooLow); + let sender = ensure_signed(origin)?; let source = T::ConvertAccountId::convert_account_id(&sender); - let code_hash = H256::from_slice(Keccak256::digest(&init).as_slice()); - let create_address = Self::execute_evm( + match Self::execute_create2( source, + init, + salt, value, gas_limit, gas_price, - nonce, - |executor| { - (executor.create_address( - evm::CreateScheme::Create2 { caller: source, code_hash, salt }, - ), executor.transact_create2( - source, - value, - init, - salt, - gas_limit as usize, - )) + nonce + )? { + (create_address, ExitReason::Succeed(_)) => { + Module::::deposit_event(Event::::Created(create_address)); }, - )?; + (create_address, _) => { + Module::::deposit_event(Event::::CreatedFailed(create_address)); + }, + } - Module::::deposit_event(Event::::Created(create_address)); Ok(()) } } @@ -347,7 +401,7 @@ impl Module { /// This actually does computation. If you need to keep using it, then make sure you cache the /// value and only call this once. pub fn account_id() -> T::AccountId { - MODULE_ID.into_account() + T::ModuleId::get().into_account() } /// Check whether an account is empty. @@ -374,6 +428,91 @@ impl Module { AccountStorages::remove_prefix(address); } + /// Execute a create transaction on behalf of given sender. + pub fn execute_create( + source: H160, + init: Vec, + value: U256, + gas_limit: u32, + gas_price: U256, + nonce: Option + ) -> Result<(H160, ExitReason), Error> { + Self::execute_evm( + source, + value, + gas_limit, + gas_price, + nonce, + |executor| { + (executor.create_address( + evm::CreateScheme::Legacy { caller: source }, + ), executor.transact_create( + source, + value, + init, + gas_limit as usize, + )) + }, + ) + } + + /// Execute a create2 transaction on behalf of a given sender. + pub fn execute_create2( + source: H160, + init: Vec, + salt: H256, + value: U256, + gas_limit: u32, + gas_price: U256, + nonce: Option + ) -> Result<(H160, ExitReason), Error> { + let code_hash = H256::from_slice(Keccak256::digest(&init).as_slice()); + Self::execute_evm( + source, + value, + gas_limit, + gas_price, + nonce, + |executor| { + (executor.create_address( + evm::CreateScheme::Create2 { caller: source, code_hash, salt }, + ), executor.transact_create2( + source, + value, + init, + salt, + gas_limit as usize, + )) + }, + ) + } + + /// Execute a call transaction on behalf of a given sender. + pub fn execute_call( + source: H160, + target: H160, + input: Vec, + value: U256, + gas_limit: u32, + gas_price: U256, + nonce: Option, + ) -> Result> { + Ok(Self::execute_evm( + source, + value, + gas_limit, + gas_price, + nonce, + |executor| ((), executor.transact_call( + source, + target, + value, + input, + gas_limit as usize, + )), + )?.1) + } + /// Execute an EVM operation. fn execute_evm( source: H160, @@ -382,11 +521,9 @@ impl Module { gas_price: U256, nonce: Option, f: F, - ) -> Result> where + ) -> Result<(R, ExitReason), Error> where F: FnOnce(&mut StackExecutor>) -> (R, ExitReason), { - ensure!(gas_price >= T::FeeCalculator::min_gas_price(), Error::::GasPriceTooLow); - let vicinity = Vicinity { gas_price, origin: source, @@ -413,19 +550,12 @@ impl Module { let (retv, reason) = f(&mut executor); - let ret = match reason { - ExitReason::Succeed(_) => Ok(retv), - ExitReason::Error(_) => Err(Error::::ExitReasonFailed), - ExitReason::Revert(_) => Err(Error::::ExitReasonRevert), - ExitReason::Fatal(_) => Err(Error::::ExitReasonFatal), - }; - 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 + Ok((retv, reason)) } } diff --git a/frame/evm/src/tests.rs b/frame/evm/src/tests.rs new file mode 100644 index 0000000000000000000000000000000000000000..f391b4dfe6160f7e068db19c6f5371711b92f4ef --- /dev/null +++ b/frame/evm/src/tests.rs @@ -0,0 +1,164 @@ +#![cfg(test)] + +use super::*; + +use std::{str::FromStr, collections::BTreeMap}; +use frame_support::{ + assert_ok, impl_outer_origin, parameter_types, impl_outer_dispatch, +}; +use sp_core::H256; +use sp_runtime::{ + Perbill, + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, +}; + +impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} +} + +impl_outer_dispatch! { + pub enum OuterCall for Test where origin: Origin { + self::EVM, + } +} + +#[derive(Clone, Eq, PartialEq)] +pub struct Test; +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} +impl frame_system::Trait for Test { + type BaseCallFilter = (); + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Call = OuterCall; + type Hashing = BlakeTwo256; + type AccountId = H256; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); +} + +parameter_types! { + pub const ExistentialDeposit: u64 = 1; +} +impl pallet_balances::Trait for Test { + type Balance = u64; + type DustRemoval = (); + type Event = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); +} + +parameter_types! { + pub const MinimumPeriod: u64 = 1000; +} +impl pallet_timestamp::Trait for Test { + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); +} + +/// Fixed gas price of `0`. +pub struct FixedGasPrice; +impl FeeCalculator for FixedGasPrice { + fn min_gas_price() -> U256 { + // Gas price is always one token per gas. + 0.into() + } +} +parameter_types! { + pub const EVMModuleId: ModuleId = ModuleId(*b"py/evmpa"); +} +impl Trait for Test { + type ChainId = SystemChainId; + type ModuleId = EVMModuleId; + type FeeCalculator = FixedGasPrice; + type ConvertAccountId = HashTruncateConvertAccountId; + type Currency = Balances; + type Event = Event; + type Precompiles = (); +} + +type System = frame_system::Module; +type Balances = pallet_balances::Module; +type EVM = Module; + +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + + let mut accounts = BTreeMap::new(); + accounts.insert( + H160::from_str("1000000000000000000000000000000000000001").unwrap(), + GenesisAccount { + nonce: U256::from(1), + balance: U256::from(1000000), + storage: Default::default(), + code: vec![ + 0x00, // STOP + ], + } + ); + accounts.insert( + H160::from_str("1000000000000000000000000000000000000002").unwrap(), + GenesisAccount { + nonce: U256::from(1), + balance: U256::from(1000000), + storage: Default::default(), + code: vec![ + 0xff, // INVALID + ], + } + ); + + pallet_balances::GenesisConfig::::default().assimilate_storage(&mut t).unwrap(); + GenesisConfig { accounts }.assimilate_storage(&mut t).unwrap(); + t.into() +} + +#[test] +fn fail_call_return_ok() { + new_test_ext().execute_with(|| { + assert_ok!(EVM::call( + Origin::signed(H256::default()), + H160::from_str("1000000000000000000000000000000000000001").unwrap(), + Vec::new(), + U256::default(), + 1000000, + U256::default(), + None, + )); + + assert_ok!(EVM::call( + Origin::signed(H256::default()), + H160::from_str("1000000000000000000000000000000000000002").unwrap(), + Vec::new(), + U256::default(), + 1000000, + U256::default(), + None, + )); + }); +} diff --git a/frame/example-offchain-worker/Cargo.toml b/frame/example-offchain-worker/Cargo.toml index 6b3452d01894f30c46fcfefb8c81f7e0125ae9df..50d398a512268d83e09066c5e9d509b28a9bd247 100644 --- a/frame/example-offchain-worker/Cargo.toml +++ b/frame/example-offchain-worker/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-example-offchain-worker" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" license = "Unlicense" @@ -8,15 +8,18 @@ homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME example pallet for offchain worker" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } serde = { version = "1.0.101", optional = true } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/core" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/core" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } lite-json = { version = "0.1", default-features = false } [features] @@ -32,6 +35,3 @@ std = [ "sp-runtime/std", "sp-std/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/example-offchain-worker/src/lib.rs b/frame/example-offchain-worker/src/lib.rs index e64b3dfa7757c40c1d49bf4d1c99b6ecf881fbc7..aae51c6f27f68f0105211f2249b6da6c5d539fcf 100644 --- a/frame/example-offchain-worker/src/lib.rs +++ b/frame/example-offchain-worker/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Offchain Worker Example Module //! @@ -22,12 +23,12 @@ //! Run `cargo doc --package pallet-example-offchain-worker --open` to view this module's //! documentation. //! -//! - \[`pallet_example_offchain_worker::Trait`](./trait.Trait.html) -//! - \[`Call`](./enum.Call.html) -//! - \[`Module`](./struct.Module.html) +//! - [`pallet_example_offchain_worker::Trait`](./trait.Trait.html) +//! - [`Call`](./enum.Call.html) +//! - [`Module`](./struct.Module.html) //! //! -//! \## Overview +//! ## Overview //! //! In this example we are going to build a very simplistic, naive and definitely NOT //! production-ready oracle for BTC/USD price. @@ -40,22 +41,32 @@ //! one unsigned transaction floating in the network. #![cfg_attr(not(feature = "std"), no_std)] +use frame_system::{ + self as system, + ensure_signed, + ensure_none, + offchain::{ + AppCrypto, CreateSignedTransaction, SendUnsignedTransaction, SendSignedTransaction, + SignedPayload, SigningTypes, Signer, SubmitTransaction, + } +}; use frame_support::{ debug, dispatch::DispatchResult, decl_module, decl_storage, decl_event, traits::Get, - weights::SimpleDispatchInfo, }; -use frame_system::{self as system, ensure_signed, ensure_none, offchain}; use sp_core::crypto::KeyTypeId; use sp_runtime::{ + RuntimeDebug, offchain::{http, Duration, storage::StorageValueRef}, traits::Zero, transaction_validity::{ InvalidTransaction, ValidTransaction, TransactionValidity, TransactionSource, + TransactionPriority, }, }; -use sp_std::{vec, vec::Vec}; +use codec::{Encode, Decode}; +use sp_std::vec::Vec; use lite_json::json::JsonValue; #[cfg(test)] @@ -75,18 +86,25 @@ pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"btc!"); /// the types with this pallet-specific identifier. pub mod crypto { use super::KEY_TYPE; - use sp_runtime::app_crypto::{app_crypto, sr25519}; + use sp_runtime::{ + app_crypto::{app_crypto, sr25519}, + traits::Verify, + }; + use sp_core::sr25519::Signature as Sr25519Signature; app_crypto!(sr25519, KEY_TYPE); + + pub struct TestAuthId; + impl frame_system::offchain::AppCrypto<::Signer, Sr25519Signature> for TestAuthId { + type RuntimeAppPublic = Public; + type GenericSignature = sp_core::sr25519::Signature; + type GenericPublic = sp_core::sr25519::Public; + } } /// This pallet's configuration trait -pub trait Trait: frame_system::Trait { - /// The type to sign and submit transactions. - type SubmitSignedTransaction: - offchain::SubmitSignedTransaction::Call>; - /// The type to submit unsigned transactions. - type SubmitUnsignedTransaction: - offchain::SubmitUnsignedTransaction::Call>; +pub trait Trait: CreateSignedTransaction> { + /// The identifier type for an offchain worker. + type AuthorityId: AppCrypto; /// The overarching event type. type Event: From> + Into<::Event>; @@ -106,6 +124,27 @@ pub trait Trait: frame_system::Trait { /// /// This ensures that we only accept unsigned transactions once, every `UnsignedInterval` blocks. type UnsignedInterval: Get; + + /// A configuration for base priority of unsigned transactions. + /// + /// This is exposed so that it can be tuned for particular runtime, when + /// multiple pallets send unsigned transactions. + type UnsignedPriority: Get; +} + +/// Payload used by this example crate to hold price +/// data required to submit a transaction. +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] +pub struct PricePayload { + block_number: BlockNumber, + price: u32, + public: Public, +} + +impl SignedPayload for PricePayload { + fn public(&self) -> T::Public { + self.public.clone() + } } decl_storage! { @@ -150,7 +189,7 @@ decl_module! { /// working and receives (and provides) meaningful data. /// This example is not focused on correctness of the oracle itself, but rather its /// purpose is to showcase offchain worker capabilities. - #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + #[weight = 0] pub fn submit_price(origin, price: u32) -> DispatchResult { // Retrieve sender of the transaction. let who = ensure_signed(origin)?; @@ -175,7 +214,7 @@ decl_module! { /// /// This example is not focused on correctness of the oracle itself, but rather its /// purpose is to showcase offchain worker capabilities. - #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + #[weight = 0] pub fn submit_price_unsigned(origin, _block_number: T::BlockNumber, price: u32) -> DispatchResult { @@ -189,6 +228,22 @@ decl_module! { Ok(()) } + #[weight = 0] + pub fn submit_price_unsigned_with_signed_payload( + origin, + price_payload: PricePayload, + _signature: T::Signature, + ) -> DispatchResult { + // This ensures that the function can only be called via unsigned transaction. + ensure_none(origin)?; + // Add the price to the on-chain list, but mark it as coming from an empty address. + Self::add_price(Default::default(), price_payload.price); + // now increment the block number at which we expect next unsigned transaction. + let current_block = >::block_number(); + >::put(current_block + T::UnsignedInterval::get()); + Ok(()) + } + /// Offchain Worker entry point. /// /// By implementing `fn offchain_worker` within `decl_module!` you declare a new offchain @@ -229,7 +284,9 @@ decl_module! { let should_send = Self::choose_transaction_type(block_number); let res = match should_send { TransactionType::Signed => Self::fetch_price_and_send_signed(), - TransactionType::Unsigned => Self::fetch_price_and_send_unsigned(block_number), + TransactionType::UnsignedForAny => Self::fetch_price_and_send_unsigned_for_any_account(block_number), + TransactionType::UnsignedForAll => Self::fetch_price_and_send_unsigned_for_all_accounts(block_number), + TransactionType::Raw => Self::fetch_price_and_send_raw_unsigned(block_number), TransactionType::None => Ok(()), }; if let Err(e) = res { @@ -241,7 +298,9 @@ decl_module! { enum TransactionType { Signed, - Unsigned, + UnsignedForAny, + UnsignedForAll, + Raw, None, } @@ -304,12 +363,11 @@ impl Module { // transactions in a row. If a strict order is desired, it's better to use // the storage entry for that. (for instance store both block number and a flag // indicating the type of next transaction to send). - let send_signed = block_number % 2.into() == Zero::zero(); - if send_signed { - TransactionType::Signed - } else { - TransactionType::Unsigned - } + let transaction_type = block_number % 3.into(); + if transaction_type == Zero::zero() { TransactionType::Signed } + else if transaction_type == T::BlockNumber::from(1) { TransactionType::UnsignedForAny } + else if transaction_type == T::BlockNumber::from(2) { TransactionType::UnsignedForAll } + else { TransactionType::Raw } }, // We are in the grace period, we should not send a transaction this time. Err(RECENTLY_SENT) => TransactionType::None, @@ -324,44 +382,41 @@ impl Module { /// A helper function to fetch the price and send signed transaction. fn fetch_price_and_send_signed() -> Result<(), &'static str> { - use system::offchain::SubmitSignedTransaction; - // Firstly we check if there are any accounts in the local keystore that are capable of - // signing the transaction. - // If not it doesn't even make sense to make external HTTP requests, since we won't be able - // to put the results back on-chain. - if !T::SubmitSignedTransaction::can_sign() { + let signer = Signer::::all_accounts(); + if !signer.can_sign() { return Err( "No local accounts available. Consider adding one via `author_insertKey` RPC." )? } - // Make an external HTTP request to fetch the current price. // Note this call will block until response is received. let price = Self::fetch_price().map_err(|_| "Failed to fetch price")?; - // Received price is wrapped into a call to `submit_price` public function of this pallet. - // This means that the transaction, when executed, will simply call that function passing - // `price` as an argument. - let call = Call::submit_price(price); - - // Using `SubmitSignedTransaction` associated type we create and submit a transaction + // Using `send_signed_transaction` associated type we create and submit a transaction // representing the call, we've just created. // Submit signed will return a vector of results for all accounts that were found in the // local keystore with expected `KEY_TYPE`. - let results = T::SubmitSignedTransaction::submit_signed(call); + let results = signer.send_signed_transaction( + |_account| { + // Received price is wrapped into a call to `submit_price` public function of this pallet. + // This means that the transaction, when executed, will simply call that function passing + // `price` as an argument. + Call::submit_price(price) + } + ); + for (acc, res) in &results { match res { - Ok(()) => debug::info!("[{:?}] Submitted price of {} cents", acc, price), - Err(e) => debug::error!("[{:?}] Failed to submit transaction: {:?}", acc, e), + Ok(()) => debug::info!("[{:?}] Submitted price of {} cents", acc.id, price), + Err(e) => debug::error!("[{:?}] Failed to submit transaction: {:?}", acc.id, e), } } Ok(()) } - /// A helper function to fetch the price and send unsigned transaction. - fn fetch_price_and_send_unsigned(block_number: T::BlockNumber) -> Result<(), &'static str> { - use system::offchain::SubmitUnsignedTransaction; + /// A helper function to fetch the price and send a raw unsigned transaction. + fn fetch_price_and_send_raw_unsigned(block_number: T::BlockNumber) -> Result<(), &'static str> { // Make sure we don't fetch the price if unsigned transaction is going to be rejected // anyway. let next_unsigned_at = >::get(); @@ -378,14 +433,101 @@ impl Module { // passing `price` as an argument. let call = Call::submit_price_unsigned(block_number, price); - // Now let's create an unsigned transaction out of this call and submit it to the pool. + // Now let's create a transaction out of this call and submit it to the pool. + // Here we showcase two ways to send an unsigned transaction / unsigned payload (raw) + // // By default unsigned transactions are disallowed, so we need to whitelist this case // by writing `UnsignedValidator`. Note that it's EXTREMELY important to carefuly // implement unsigned validation logic, as any mistakes can lead to opening DoS or spam // attack vectors. See validation logic docs for more details. - T::SubmitUnsignedTransaction::submit_unsigned(call) - .map_err(|()| "Unable to submit unsigned transaction.".into()) + // + SubmitTransaction::>::submit_unsigned_transaction(call.into()) + .map_err(|()| "Unable to submit unsigned transaction.")?; + + Ok(()) + } + + /// A helper function to fetch the price, sign payload and send an unsigned transaction + fn fetch_price_and_send_unsigned_for_any_account(block_number: T::BlockNumber) -> Result<(), &'static str> { + // Make sure we don't fetch the price if unsigned transaction is going to be rejected + // anyway. + let next_unsigned_at = >::get(); + if next_unsigned_at > block_number { + return Err("Too early to send unsigned transaction") + } + + // Make an external HTTP request to fetch the current price. + // Note this call will block until response is received. + let price = Self::fetch_price().map_err(|_| "Failed to fetch price")?; + + // Received price is wrapped into a call to `submit_price_unsigned` public function of this + // pallet. This means that the transaction, when executed, will simply call that function + // passing `price` as an argument. + let call = Call::submit_price_unsigned(block_number, price); + // Now let's create a transaction out of this call and submit it to the pool. + // Here we showcase two ways to send an unsigned transaction with a signed payload + SubmitTransaction::>::submit_unsigned_transaction(call.into()) + .map_err(|()| "Unable to submit unsigned transaction.")?; + + // -- Sign using any account + let (_, result) = Signer::::any_account().send_unsigned_transaction( + |account| PricePayload { + price, + block_number, + public: account.public.clone() + }, + |payload, signature| { + Call::submit_price_unsigned_with_signed_payload(payload, signature) + } + ).ok_or("No local accounts accounts available.")?; + result.map_err(|()| "Unable to submit transaction")?; + + Ok(()) + } + + /// A helper function to fetch the price, sign payload and send an unsigned transaction + fn fetch_price_and_send_unsigned_for_all_accounts(block_number: T::BlockNumber) -> Result<(), &'static str> { + // Make sure we don't fetch the price if unsigned transaction is going to be rejected + // anyway. + let next_unsigned_at = >::get(); + if next_unsigned_at > block_number { + return Err("Too early to send unsigned transaction") + } + + // Make an external HTTP request to fetch the current price. + // Note this call will block until response is received. + let price = Self::fetch_price().map_err(|_| "Failed to fetch price")?; + + // Received price is wrapped into a call to `submit_price_unsigned` public function of this + // pallet. This means that the transaction, when executed, will simply call that function + // passing `price` as an argument. + let call = Call::submit_price_unsigned(block_number, price); + + // Now let's create a transaction out of this call and submit it to the pool. + // Here we showcase two ways to send an unsigned transaction with a signed payload + SubmitTransaction::>::submit_unsigned_transaction(call.into()) + .map_err(|()| "Unable to submit unsigned transaction.")?; + + // -- Sign using all accounts + let transaction_results = Signer::::all_accounts() + .send_unsigned_transaction( + |account| PricePayload { + price, + block_number, + public: account.public.clone() + }, + |payload, signature| { + Call::submit_price_unsigned_with_signed_payload(payload, signature) + } + ); + for (_account_id, result) in transaction_results.into_iter() { + if result.is_err() { + return Err("Unable to submit transaction"); + } + } + + Ok(()) } /// Fetch current price and return the result in cents. @@ -500,6 +642,58 @@ impl Module { Some(prices.iter().fold(0_u32, |a, b| a.saturating_add(*b)) / prices.len() as u32) } } + + fn validate_transaction_parameters( + block_number: &T::BlockNumber, + new_price: &u32, + ) -> TransactionValidity { + // Now let's check if the transaction has any chance to succeed. + let next_unsigned_at = >::get(); + if &next_unsigned_at > block_number { + return InvalidTransaction::Stale.into(); + } + // Let's make sure to reject transactions from the future. + let current_block = >::block_number(); + if ¤t_block < block_number { + return InvalidTransaction::Future.into(); + } + + // We prioritize transactions that are more far away from current average. + // + // Note this doesn't make much sense when building an actual oracle, but this example + // is here mostly to show off offchain workers capabilities, not about building an + // oracle. + let avg_price = Self::average_price() + .map(|price| if &price > new_price { price - new_price } else { new_price - price }) + .unwrap_or(0); + + ValidTransaction::with_tag_prefix("ExampleOffchainWorker") + // We set base priority to 2**20 and hope it's included before any other + // transactions in the pool. Next we tweak the priority depending on how much + // it differs from the current average. (the more it differs the more priority it + // has). + .priority(T::UnsignedPriority::get().saturating_add(avg_price as _)) + // This transaction does not require anything else to go before into the pool. + // In theory we could require `previous_unsigned_at` transaction to go first, + // but it's not necessary in our case. + //.and_requires() + // We set the `provides` tag to be the same as `next_unsigned_at`. This makes + // sure only one transaction produced after `next_unsigned_at` will ever + // get to the transaction pool and will end up in the block. + // We can still have multiple transactions compete for the same "spot", + // and the one with higher priority will replace other one in the pool. + .and_provides(next_unsigned_at) + // The transaction is only valid for next 5 blocks. After that it's + // going to be revalidated by the pool. + .longevity(5) + // It's fine to propagate that transaction to other peers, which means it can be + // created even by nodes that don't produce blocks. + // Note that sometimes it's better to keep it for yourself (if you are the block + // producer), since for instance in some schemes others may copy your solution and + // claim a reward. + .propagate(true) + .build() + } } #[allow(deprecated)] // ValidateUnsigned @@ -516,53 +710,16 @@ impl frame_support::unsigned::ValidateUnsigned for Module { call: &Self::Call, ) -> TransactionValidity { // Firstly let's check that we call the right function. - if let Call::submit_price_unsigned(block_number, new_price) = call { - // Now let's check if the transaction has any chance to succeed. - let next_unsigned_at = >::get(); - if &next_unsigned_at > block_number { - return InvalidTransaction::Stale.into(); - } - // Let's make sure to reject transactions from the future. - let current_block = >::block_number(); - if ¤t_block < block_number { - return InvalidTransaction::Future.into(); + if let Call::submit_price_unsigned_with_signed_payload( + ref payload, ref signature + ) = call { + let signature_valid = SignedPayload::::verify::(payload, signature.clone()); + if !signature_valid { + return InvalidTransaction::BadProof.into(); } - - // We prioritize transactions that are more far away from current average. - // - // Note this doesn't make much sense when building an actual oracle, but this example - // is here mostly to show off offchain workers capabilities, not about building an - // oracle. - let avg_price = Self::average_price() - .map(|price| if &price > new_price { price - new_price } else { new_price - price }) - .unwrap_or(0); - - Ok(ValidTransaction { - // We set base priority to 2**20 to make sure it's included before any other - // transactions in the pool. Next we tweak the priority depending on how much - // it differs from the current average. (the more it differs the more priority it - // has). - priority: (1 << 20) + avg_price as u64, - // This transaction does not require anything else to go before into the pool. - // In theory we could require `previous_unsigned_at` transaction to go first, - // but it's not necessary in our case. - requires: vec![], - // We set the `provides` tag to be the same as `next_unsigned_at`. This makes - // sure only one transaction produced after `next_unsigned_at` will ever - // get to the transaction pool and will end up in the block. - // We can still have multiple transactions compete for the same "spot", - // and the one with higher priority will replace other one in the pool. - provides: vec![codec::Encode::encode(&(KEY_TYPE.0, next_unsigned_at))], - // The transaction is only valid for next 5 blocks. After that it's - // going to be revalidated by the pool. - longevity: 5, - // It's fine to propagate that transaction to other peers, which means it can be - // created even by nodes that don't produce blocks. - // Note that sometimes it's better to keep it for yourself (if you are the block - // producer), since for instance in some schemes others may copy your solution and - // claim a reward. - propagate: true, - }) + Self::validate_transaction_parameters(&payload.block_number, &payload.price) + } else if let Call::submit_price_unsigned(block_number, new_price) = call { + Self::validate_transaction_parameters(block_number, new_price) } else { InvalidTransaction::Call.into() } diff --git a/frame/example-offchain-worker/src/tests.rs b/frame/example-offchain-worker/src/tests.rs index f64503b0a92a84a33fb3d4949e2dd1c575882a8d..e008fe40533ad208113fb2a6e51b67d3eadbf43b 100644 --- a/frame/example-offchain-worker/src/tests.rs +++ b/frame/example-offchain-worker/src/tests.rs @@ -1,36 +1,41 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::*; -use codec::Decode; +use codec::{Encode, Decode}; use frame_support::{ assert_ok, impl_outer_origin, parameter_types, - weights::{GetDispatchInfo, Weight}, + weights::Weight, }; use sp_core::{ H256, offchain::{OffchainExt, TransactionPoolExt, testing}, + sr25519::Signature, testing::KeyStore, traits::KeystoreExt, }; use sp_runtime::{ Perbill, RuntimeAppPublic, testing::{Header, TestXt}, - traits::{BlakeTwo256, IdentityLookup, Extrinsic as ExtrinsicsT}, + traits::{ + BlakeTwo256, IdentityLookup, Extrinsic as ExtrinsicT, + IdentifyAccount, Verify, + }, }; impl_outer_origin! { @@ -40,7 +45,7 @@ impl_outer_origin! { // 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)] +#[derive(Clone, Eq, PartialEq, Encode, Decode)] pub struct Test; parameter_types! { pub const BlockHashCount: u64 = 250; @@ -49,6 +54,7 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Call = (); type Index = u64; @@ -61,6 +67,10 @@ impl frame_system::Trait for Test { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -68,25 +78,33 @@ impl frame_system::Trait for Test { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } type Extrinsic = TestXt, ()>; -type SubmitTransaction = frame_system::offchain::TransactionSubmitter< - crypto::Public, - Test, - Extrinsic ->; - -impl frame_system::offchain::CreateTransaction for Test { - type Public = sp_core::sr25519::Public; - type Signature = sp_core::sr25519::Signature; - - fn create_transaction>( - call: ::Call, - _public: Self::Public, - _account: ::AccountId, - nonce: ::Index, - ) -> Option<(::Call, ::SignaturePayload)> { +type AccountId = <::Signer as IdentifyAccount>::AccountId; + +impl frame_system::offchain::SigningTypes for Test { + type Public = ::Signer; + type Signature = Signature; +} + +impl frame_system::offchain::SendTransactionTypes for Test where + Call: From, +{ + type OverarchingCall = Call; + type Extrinsic = Extrinsic; +} + +impl frame_system::offchain::CreateSignedTransaction for Test where + Call: From, +{ + fn create_transaction>( + call: Call, + _public: ::Signer, + _account: AccountId, + nonce: u64, + ) -> Option<(Call, ::SignaturePayload)> { Some((call, (nonce, ()))) } } @@ -94,15 +112,16 @@ impl frame_system::offchain::CreateTransaction for Test { parameter_types! { pub const GracePeriod: u64 = 5; pub const UnsignedInterval: u64 = 128; + pub const UnsignedPriority: u64 = 1 << 20; } impl Trait for Test { type Event = (); + type AuthorityId = crypto::TestAuthId; type Call = Call; - type SubmitSignedTransaction = SubmitTransaction; - type SubmitUnsignedTransaction = SubmitTransaction; type GracePeriod = GracePeriod; type UnsignedInterval = UnsignedInterval; + type UnsignedPriority = UnsignedPriority; } type Example = Module; @@ -136,6 +155,52 @@ fn should_make_http_call_and_parse_result() { }); } +#[test] +fn knows_how_to_mock_several_http_calls() { + let (offchain, state) = testing::TestOffchainExt::new(); + let mut t = sp_io::TestExternalities::default(); + t.register_extension(OffchainExt::new(offchain)); + + { + let mut state = state.write(); + state.expect_request(testing::PendingRequest { + method: "GET".into(), + uri: "https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=USD".into(), + response: Some(br#"{"USD": 1}"#.to_vec()), + sent: true, + ..Default::default() + }); + + state.expect_request(testing::PendingRequest { + method: "GET".into(), + uri: "https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=USD".into(), + response: Some(br#"{"USD": 2}"#.to_vec()), + sent: true, + ..Default::default() + }); + + state.expect_request(testing::PendingRequest { + method: "GET".into(), + uri: "https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=USD".into(), + response: Some(br#"{"USD": 3}"#.to_vec()), + sent: true, + ..Default::default() + }); + } + + + t.execute_with(|| { + let price1 = Example::fetch_price().unwrap(); + let price2 = Example::fetch_price().unwrap(); + let price3 = Example::fetch_price().unwrap(); + + assert_eq!(price1, 100); + assert_eq!(price2, 200); + assert_eq!(price3, 300); + }) + +} + #[test] fn should_submit_signed_transaction_on_chain() { const PHRASE: &str = "news slush supreme milk chapter athlete soap sausage put clutch what kitten"; @@ -169,38 +234,139 @@ fn should_submit_signed_transaction_on_chain() { } #[test] -fn should_submit_unsigned_transaction_on_chain() { +fn should_submit_unsigned_transaction_on_chain_for_any_account() { + const PHRASE: &str = "news slush supreme milk chapter athlete soap sausage put clutch what kitten"; let (offchain, offchain_state) = testing::TestOffchainExt::new(); let (pool, pool_state) = testing::TestTransactionPoolExt::new(); + + let keystore = KeyStore::new(); + + keystore.write().sr25519_generate_new( + crate::crypto::Public::ID, + Some(&format!("{}/hunter1", PHRASE)) + ).unwrap(); + let mut t = sp_io::TestExternalities::default(); t.register_extension(OffchainExt::new(offchain)); t.register_extension(TransactionPoolExt::new(pool)); + t.register_extension(KeystoreExt(keystore.clone())); price_oracle_response(&mut offchain_state.write()); + let public_key = keystore.read() + .sr25519_public_keys(crate::crypto::Public::ID) + .get(0) + .unwrap() + .clone(); + + let price_payload = PricePayload { + block_number: 1, + price: 15523, + public: ::Public::from(public_key), + }; + + // let signature = price_payload.sign::().unwrap(); t.execute_with(|| { // when - Example::fetch_price_and_send_unsigned(1).unwrap(); + Example::fetch_price_and_send_unsigned_for_any_account(1).unwrap(); // then let tx = pool_state.write().transactions.pop().unwrap(); - assert!(pool_state.read().transactions.is_empty()); let tx = Extrinsic::decode(&mut &*tx).unwrap(); assert_eq!(tx.signature, None); - assert_eq!(tx.call, Call::submit_price_unsigned(1, 15523)); + if let Call::submit_price_unsigned_with_signed_payload(body, signature) = tx.call { + assert_eq!(body, price_payload); + + let signature_valid = ::Public, + ::BlockNumber + > as SignedPayload>::verify::(&price_payload, signature); + + assert!(signature_valid); + } }); } #[test] -fn weights_work() { - // must have a default weight. - let default_call = >::submit_price(10); - let info = default_call.get_dispatch_info(); - // aka. `let info = as GetDispatchInfo>::get_dispatch_info(&default_call);` - assert_eq!(info.weight, 10_000); +fn should_submit_unsigned_transaction_on_chain_for_all_accounts() { + const PHRASE: &str = "news slush supreme milk chapter athlete soap sausage put clutch what kitten"; + let (offchain, offchain_state) = testing::TestOffchainExt::new(); + let (pool, pool_state) = testing::TestTransactionPoolExt::new(); + + let keystore = KeyStore::new(); + + keystore.write().sr25519_generate_new( + crate::crypto::Public::ID, + Some(&format!("{}/hunter1", PHRASE)) + ).unwrap(); + + let mut t = sp_io::TestExternalities::default(); + t.register_extension(OffchainExt::new(offchain)); + t.register_extension(TransactionPoolExt::new(pool)); + t.register_extension(KeystoreExt(keystore.clone())); + + price_oracle_response(&mut offchain_state.write()); + + let public_key = keystore.read() + .sr25519_public_keys(crate::crypto::Public::ID) + .get(0) + .unwrap() + .clone(); + + let price_payload = PricePayload { + block_number: 1, + price: 15523, + public: ::Public::from(public_key), + }; + + // let signature = price_payload.sign::().unwrap(); + t.execute_with(|| { + // when + Example::fetch_price_and_send_unsigned_for_all_accounts(1).unwrap(); + // then + let tx = pool_state.write().transactions.pop().unwrap(); + let tx = Extrinsic::decode(&mut &*tx).unwrap(); + assert_eq!(tx.signature, None); + if let Call::submit_price_unsigned_with_signed_payload(body, signature) = tx.call { + assert_eq!(body, price_payload); + + let signature_valid = ::Public, + ::BlockNumber + > as SignedPayload>::verify::(&price_payload, signature); + + assert!(signature_valid); + } + }); +} + +#[test] +fn should_submit_raw_unsigned_transaction_on_chain() { + let (offchain, offchain_state) = testing::TestOffchainExt::new(); + let (pool, pool_state) = testing::TestTransactionPoolExt::new(); + + let keystore = KeyStore::new(); + + let mut t = sp_io::TestExternalities::default(); + t.register_extension(OffchainExt::new(offchain)); + t.register_extension(TransactionPoolExt::new(pool)); + t.register_extension(KeystoreExt(keystore)); + + price_oracle_response(&mut offchain_state.write()); + + t.execute_with(|| { + // when + Example::fetch_price_and_send_raw_unsigned(1).unwrap(); + // then + let tx = pool_state.write().transactions.pop().unwrap(); + assert!(pool_state.read().transactions.is_empty()); + let tx = Extrinsic::decode(&mut &*tx).unwrap(); + assert_eq!(tx.signature, None); + assert_eq!(tx.call, Call::submit_price_unsigned(1, 15523)); + }); } fn price_oracle_response(state: &mut testing::OffchainState) { - state.expect_request(0, testing::PendingRequest { + state.expect_request(testing::PendingRequest { method: "GET".into(), uri: "https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=USD".into(), response: Some(br#"{"USD": 155.23}"#.to_vec()), diff --git a/frame/example/Cargo.toml b/frame/example/Cargo.toml index 4053cc0b1a51a47d17a23566afc36c1798b34988..cf09a3d4b296020564afeec2daf4dc46e1878231 100644 --- a/frame/example/Cargo.toml +++ b/frame/example/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-example" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" license = "Unlicense" @@ -8,20 +8,23 @@ homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME example pallet" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } -pallet-balances = { version = "2.0.0-alpha.5", default-features = false, path = "../balances" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/io" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } +pallet-balances = { version = "2.0.0-rc4", default-features = false, path = "../balances" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } -frame-benchmarking = { version = "2.0.0-alpha.5", default-features = false, path = "../benchmarking", optional = true } +frame-benchmarking = { version = "2.0.0-rc4", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core", default-features = false } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core", default-features = false } [features] default = ["std"] @@ -37,6 +40,3 @@ std = [ "sp-std/std" ] runtime-benchmarks = ["frame-benchmarking"] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/example/src/lib.rs b/frame/example/src/lib.rs index e8ce89a863aebbfb6a14d572df1f6a25eab24941..8a6374f22720b837dce0a1844a62a3516d8ffd2a 100644 --- a/frame/example/src/lib.rs +++ b/frame/example/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! # Example Pallet //! @@ -255,17 +256,16 @@ use sp_std::marker::PhantomData; use frame_support::{ - dispatch::DispatchResult, decl_module, decl_storage, decl_event, - weights::{ - SimpleDispatchInfo, DispatchInfo, DispatchClass, ClassifyDispatch, WeighData, Weight, - PaysFee, - }, + dispatch::{DispatchResult, IsSubType}, decl_module, decl_storage, decl_event, + weights::{DispatchClass, ClassifyDispatch, WeighData, Weight, PaysFee, Pays}, }; use sp_std::prelude::*; -use frame_system::{self as system, ensure_signed, ensure_root}; +use frame_system::{ensure_signed, ensure_root}; use codec::{Encode, Decode}; use sp_runtime::{ - traits::{SignedExtension, Bounded, SaturatedConversion}, + traits::{ + SignedExtension, Bounded, SaturatedConversion, DispatchInfoOf, + }, transaction_validity::{ ValidTransaction, TransactionValidityError, InvalidTransaction, TransactionValidity, }, @@ -306,8 +306,8 @@ impl ClassifyDispatch<(&BalanceOf,)> for WeightFor } impl PaysFee<(&BalanceOf,)> for WeightForSetDummy { - fn pays_fee(&self, _target: (&BalanceOf,)) -> bool { - true + fn pays_fee(&self, _target: (&BalanceOf,)) -> Pays { + Pays::Yes } } @@ -467,7 +467,7 @@ decl_module! { // 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). - #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + #[weight = 0] fn accumulate_dummy(origin, increase_by: T::Balance) -> DispatchResult { // This is a public call, so we ensure that the origin is some signed account. let _sender = ensure_signed(origin)?; @@ -516,13 +516,12 @@ decl_module! { // The signature could also look like: `fn on_initialize()`. // This function could also very well have a weight annotation, similar to any other. The - // only difference being that if it is not annotated, the default is - // `SimpleDispatchInfo::zero()`, which resolves into no weight. + // only difference is that it mut be returned, not annotated. fn on_initialize(_n: T::BlockNumber) -> Weight { // Anything that needs to be done at the start of the block. // We don't do anything here. - SimpleDispatchInfo::default().weigh_data(()) + 0 } // The signature could also look like: `fn on_finalize()` @@ -610,16 +609,14 @@ impl sp_std::fmt::Debug for WatchDummy { } } -impl SignedExtension for WatchDummy { +impl SignedExtension for WatchDummy +where + ::Call: IsSubType>, +{ const IDENTIFIER: &'static str = "WatchDummy"; type AccountId = T::AccountId; - // Note that this could also be assigned to the top-level call enum. It is passed into the - // Balances Pallet directly and since `Trait: pallet_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 pallets. - type Call = Call; + type Call = ::Call; type AdditionalSigned = (); - type DispatchInfo = DispatchInfo; type Pre = (); fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) } @@ -628,7 +625,7 @@ impl SignedExtension for WatchDummy { &self, _who: &Self::AccountId, call: &Self::Call, - _info: Self::DispatchInfo, + _info: &DispatchInfoOf, len: usize, ) -> TransactionValidity { // if the transaction is too big, just drop it. @@ -637,8 +634,8 @@ impl SignedExtension for WatchDummy { } // check for `set_dummy` - match call { - Call::set_dummy(..) => { + match call.is_sub_type() { + Some(Call::set_dummy(..)) => { sp_runtime::print("set_dummy was received."); let mut valid_tx = ValidTransaction::default(); @@ -671,26 +668,41 @@ mod benchmarking { // This will measure the execution time of `set_dummy` for b in [1..1000] range. set_dummy { let b in ...; - let caller = account("caller", 0, 0); - }: set_dummy (RawOrigin::Signed(caller), b.into()) + }: set_dummy (RawOrigin::Root, b.into()) // This will measure the execution time of `set_dummy` for b in [1..10] range. another_set_dummy { let b in 1 .. 10; - let caller = account("caller", 0, 0); - }: set_dummy (RawOrigin::Signed(caller), b.into()) + }: set_dummy (RawOrigin::Root, b.into()) // This will measure the execution time of sorting a vector. sort_vector { let x in 0 .. 10000; let mut m = Vec::::new(); - for i in 0..x { + for i in (0..x).rev() { m.push(i); } }: { m.sort(); } } + + #[cfg(test)] + mod tests { + use super::*; + use crate::tests::{new_test_ext, Test}; + use frame_support::assert_ok; + + #[test] + fn test_benchmarks() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_accumulate_dummy::()); + assert_ok!(test_benchmark_set_dummy::()); + assert_ok!(test_benchmark_another_set_dummy::()); + assert_ok!(test_benchmark_sort_vector::()); + }); + } + } } #[cfg(test)] @@ -698,8 +710,8 @@ mod tests { use super::*; use frame_support::{ - assert_ok, impl_outer_origin, parameter_types, weights::GetDispatchInfo, - traits::{OnInitialize, OnFinalize} + assert_ok, impl_outer_origin, parameter_types, impl_outer_dispatch, + weights::{DispatchInfo, GetDispatchInfo}, traits::{OnInitialize, OnFinalize} }; use sp_core::H256; // The testing primitives are very useful for avoiding having to work with signatures @@ -714,6 +726,12 @@ mod tests { pub enum Origin for Test where system = frame_system {} } + impl_outer_dispatch! { + pub enum OuterCall for Test where origin: Origin { + self::Example, + } + } + // For testing the pallet, we construct most of a mock runtime. This means // first constructing a configuration type (`Test`) which `impl`s each of the // configuration traits of pallets we want to use. @@ -726,11 +744,12 @@ mod tests { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; type Hash = H256; - type Call = (); + type Call = OuterCall; type Hashing = BlakeTwo256; type AccountId = u64; type Lookup = IdentityLookup; @@ -738,6 +757,10 @@ mod tests { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -745,6 +768,7 @@ mod tests { type AccountData = pallet_balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } parameter_types! { pub const ExistentialDeposit: u64 = 1; @@ -755,6 +779,7 @@ mod tests { type Event = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; + type WeightInfo = (); } impl Trait for Test { type Event = (); @@ -764,7 +789,7 @@ mod tests { // This function basically just builds a genesis storage key/value store according to // our desired mockup. - fn new_test_ext() -> sp_io::TestExternalities { + pub fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); // We use default for brevity, but you can configure as desired if needed. pallet_balances::GenesisConfig::::default().assimilate_storage(&mut t).unwrap(); @@ -810,17 +835,17 @@ mod tests { #[test] fn signed_ext_watch_dummy_works() { new_test_ext().execute_with(|| { - let call = >::set_dummy(10); + let call = >::set_dummy(10).into(); let info = DispatchInfo::default(); assert_eq!( - WatchDummy::(PhantomData).validate(&1, &call, info, 150) + WatchDummy::(PhantomData).validate(&1, &call, &info, 150) .unwrap() .priority, Bounded::max_value(), ); assert_eq!( - WatchDummy::(PhantomData).validate(&1, &call, info, 250), + WatchDummy::(PhantomData).validate(&1, &call, &info, 250), InvalidTransaction::ExhaustsResources.into(), ); }) @@ -828,11 +853,11 @@ mod tests { #[test] fn weights_work() { - // must have a default weight. + // must have a defined 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); + assert_eq!(info.weight, 0); // must have a custom weight of `100 * arg = 2000` let custom_call = >::set_dummy(20); diff --git a/frame/executive/Cargo.toml b/frame/executive/Cargo.toml index 3c494199cb2374e07a45b1b888d3af52545681b8..52225d9824042561fbeb9a26d6942591334d6390 100644 --- a/frame/executive/Cargo.toml +++ b/frame/executive/Cargo.toml @@ -1,29 +1,34 @@ [package] name = "frame-executive" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME executives engine" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } serde = { version = "1.0.101", optional = true } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +sp-tracing = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/tracing" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } [dev-dependencies] hex-literal = "0.2.1" -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -sp-io ={ path = "../../primitives/io", version = "2.0.0-alpha.5"} -pallet-indices = { version = "2.0.0-alpha.5", path = "../indices" } -pallet-balances = { version = "2.0.0-alpha.5", path = "../balances" } -pallet-transaction-payment = { version = "2.0.0-alpha.5", path = "../transaction-payment" } -sp-version = { version = "2.0.0-alpha.5", path = "../../primitives/version" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +sp-io ={ version = "2.0.0-rc4", path = "../../primitives/io" } +pallet-indices = { version = "2.0.0-rc4", path = "../indices" } +pallet-balances = { version = "2.0.0-rc4", path = "../balances" } +pallet-transaction-payment = { version = "2.0.0-rc4", path = "../transaction-payment" } +sp-version = { version = "2.0.0-rc4", path = "../../primitives/version" } [features] default = ["std"] @@ -33,8 +38,6 @@ std = [ "frame-system/std", "serde", "sp-runtime/std", + "sp-tracing/std", "sp-std/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index d30b66e0837df9af76f7d5ae4da3231b95690c9f..24dccf8b0b4a41f97e996e2e005d65051ff9a782 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Executive Module //! @@ -60,26 +61,65 @@ //! # pub type AllModules = u64; //! # pub enum Runtime {}; //! # use sp_runtime::transaction_validity::{ -//! TransactionValidity, UnknownTransaction, TransactionSource, +//! # TransactionValidity, UnknownTransaction, TransactionSource, //! # }; //! # use sp_runtime::traits::ValidateUnsigned; //! # impl ValidateUnsigned for Runtime { -//! # type Call = (); +//! # type Call = (); //! # -//! # fn validate_unsigned(_source: TransactionSource, _call: &Self::Call) -> TransactionValidity { -//! # UnknownTransaction::NoUnsignedValidator.into() -//! # } +//! # fn validate_unsigned(_source: TransactionSource, _call: &Self::Call) -> TransactionValidity { +//! # UnknownTransaction::NoUnsignedValidator.into() +//! # } //! # } //! /// Executive: handles dispatch to the various modules. //! pub type Executive = executive::Executive; //! ``` +//! +//! ### Custom `OnRuntimeUpgrade` logic +//! +//! You can add custom logic that should be called in your runtime on a runtime upgrade. This is +//! done by setting an optional generic parameter. The custom logic will be called before +//! the on runtime upgrade logic of all modules is called. +//! +//! ``` +//! # use sp_runtime::generic; +//! # use frame_executive as executive; +//! # pub struct UncheckedExtrinsic {}; +//! # pub struct Header {}; +//! # type Context = frame_system::ChainContext; +//! # pub type Block = generic::Block; +//! # pub type Balances = u64; +//! # pub type AllModules = u64; +//! # pub enum Runtime {}; +//! # use sp_runtime::transaction_validity::{ +//! # TransactionValidity, UnknownTransaction, TransactionSource, +//! # }; +//! # use sp_runtime::traits::ValidateUnsigned; +//! # impl ValidateUnsigned for Runtime { +//! # type Call = (); +//! # +//! # fn validate_unsigned(_source: TransactionSource, _call: &Self::Call) -> TransactionValidity { +//! # UnknownTransaction::NoUnsignedValidator.into() +//! # } +//! # } +//! struct CustomOnRuntimeUpgrade; +//! impl frame_support::traits::OnRuntimeUpgrade for CustomOnRuntimeUpgrade { +//! fn on_runtime_upgrade() -> frame_support::weights::Weight { +//! // Do whatever you want. +//! 0 +//! } +//! } +//! +//! pub type Executive = executive::Executive; +//! ``` #![cfg_attr(not(feature = "std"), no_std)] use sp_std::{prelude::*, marker::PhantomData}; use frame_support::{ - storage::StorageValue, weights::{GetDispatchInfo, DispatchInfo}, + storage::StorageValue, weights::{GetDispatchInfo, DispatchInfo, DispatchClass}, traits::{OnInitialize, OnFinalize, OnRuntimeUpgrade, OffchainWorker}, + dispatch::PostDispatchInfo, }; use sp_runtime::{ generic::Digest, ApplyExtrinsicResult, @@ -102,8 +142,19 @@ pub type CheckedOf = >::Checked; pub type CallOf = as Applyable>::Call; pub type OriginOf = as Dispatchable>::Origin; -pub struct Executive( - PhantomData<(System, Block, Context, UnsignedValidator, AllModules)> +/// Main entry point for certain runtime actions as e.g. `execute_block`. +/// +/// Generic parameters: +/// - `System`: Something that implements `frame_system::Trait` +/// - `Block`: The block type of the runtime +/// - `Context`: The context that is used when checking an extrinsic. +/// - `UnsignedValidator`: The unsigned transaction validator of the runtime. +/// - `AllModules`: Tuple that contains all modules. Will be used to call e.g. `on_initialize`. +/// - `OnRuntimeUpgrade`: Custom logic that should be called after a runtime upgrade. Modules are +/// already called by `AllModules`. It will be called before all modules will +/// be called. +pub struct Executive( + PhantomData<(System, Block, Context, UnsignedValidator, AllModules, OnRuntimeUpgrade)> ); impl< @@ -116,13 +167,15 @@ impl< OnInitialize + OnFinalize + OffchainWorker, -> ExecuteBlock for Executive + COnRuntimeUpgrade: OnRuntimeUpgrade, +> ExecuteBlock for + Executive where Block::Extrinsic: Checkable + Codec, CheckedOf: - Applyable + + Applyable + GetDispatchInfo, - CallOf: Dispatchable, + CallOf: Dispatchable, OriginOf: From>, UnsignedValidator: ValidateUnsigned>, { @@ -141,13 +194,14 @@ impl< OnInitialize + OnFinalize + OffchainWorker, -> Executive + COnRuntimeUpgrade: OnRuntimeUpgrade, +> Executive where Block::Extrinsic: Checkable + Codec, CheckedOf: - Applyable + + Applyable + GetDispatchInfo, - CallOf: Dispatchable, + CallOf: Dispatchable, OriginOf: From>, UnsignedValidator: ValidateUnsigned>, { @@ -180,9 +234,10 @@ where ) { if Self::runtime_upgraded() { // System is not part of `AllModules`, so we need to call this manually. - as OnRuntimeUpgrade>::on_runtime_upgrade(); - let weight = ::on_runtime_upgrade(); - >::register_extra_weight_unchecked(weight); + let mut weight = as OnRuntimeUpgrade>::on_runtime_upgrade(); + weight = weight.saturating_add(COnRuntimeUpgrade::on_runtime_upgrade()); + weight = weight.saturating_add(::on_runtime_upgrade()); + >::register_extra_weight_unchecked(weight, DispatchClass::Mandatory); } >::initialize( block_number, @@ -192,8 +247,9 @@ where frame_system::InitKind::Full, ); as OnInitialize>::on_initialize(*block_number); - let weight = >::on_initialize(*block_number); - >::register_extra_weight_unchecked(weight); + let weight = >::on_initialize(*block_number) + .saturating_add(>::get()); + >::register_extra_weight_unchecked(weight, DispatchClass::Mandatory); frame_system::Module::::note_finished_initialize(); } @@ -237,10 +293,16 @@ where // any initial checks Self::initial_checks(&block); + let signature_batching = sp_runtime::SignatureBatching::start(); + // execute extrinsics let (header, extrinsics) = block.deconstruct(); Self::execute_extrinsics_with_book_keeping(extrinsics, *header.number()); + if !signature_batching.verify() { + panic!("Signature verification failed."); + } + // any final checks Self::final_checks(&header); } @@ -307,11 +369,11 @@ where // Decode parameters and dispatch let dispatch_info = xt.get_dispatch_info(); - let r = Applyable::apply::(xt, dispatch_info, encoded_len)?; + let r = Applyable::apply::(xt, &dispatch_info, encoded_len)?; - >::note_applied_extrinsic(&r, encoded_len as u32, dispatch_info); + >::note_applied_extrinsic(&r, dispatch_info); - Ok(r) + Ok(r.map(|_| ()).map_err(|e| e.error)) } fn final_checks(header: &System::Header) { @@ -344,11 +406,20 @@ where source: TransactionSource, uxt: Block::Extrinsic, ) -> TransactionValidity { - let encoded_len = uxt.using_encoded(|d| d.len()); - let xt = uxt.check(&Default::default())?; + use sp_tracing::tracing_span; - let dispatch_info = xt.get_dispatch_info(); - xt.validate::(source, dispatch_info, encoded_len) + sp_tracing::enter_span!("validate_transaction"); + + let encoded_len = tracing_span!{ "using_encoded"; uxt.using_encoded(|d| d.len()) }; + + let xt = tracing_span!{ "check"; uxt.check(&Default::default())? }; + + let dispatch_info = tracing_span!{ "dispatch_info"; xt.get_dispatch_info() }; + + tracing_span! { + "validate"; + xt.validate::(source, &dispatch_info, encoded_len) + } } /// Start an offchain worker and generate extrinsics. @@ -385,35 +456,36 @@ mod tests { use sp_core::H256; use sp_runtime::{ generic::Era, Perbill, DispatchError, testing::{Digest, Header, Block}, - traits::{Header as HeaderT, BlakeTwo256, IdentityLookup, ConvertInto}, + traits::{Header as HeaderT, BlakeTwo256, IdentityLookup}, transaction_validity::{InvalidTransaction, UnknownTransaction, TransactionValidityError}, }; use frame_support::{ impl_outer_event, impl_outer_origin, parameter_types, impl_outer_dispatch, - weights::Weight, + weights::{Weight, RuntimeDbWeight, IdentityFee, WeightToFeePolynomial}, traits::{Currency, LockIdentifier, LockableCurrency, WithdrawReasons, WithdrawReason}, }; use frame_system::{self as system, Call as SystemCall, ChainContext, LastRuntimeUpgradeInfo}; use pallet_balances::Call as BalancesCall; use hex_literal::hex; + const TEST_KEY: &[u8] = &*b":test:key:"; mod custom { - use frame_support::weights::{SimpleDispatchInfo, Weight}; + use frame_support::weights::{Weight, DispatchClass}; pub trait Trait: frame_system::Trait {} frame_support::decl_module! { pub struct Module for enum Call where origin: T::Origin { - #[weight = SimpleDispatchInfo::FixedNormal(100)] + #[weight = 100] fn some_function(origin) { // NOTE: does not make any different. let _ = frame_system::ensure_signed(origin); } - #[weight = SimpleDispatchInfo::FixedOperational(200)] + #[weight = (200, DispatchClass::Operational)] fn some_root_operation(origin) { let _ = frame_system::ensure_root(origin); } - #[weight = SimpleDispatchInfo::InsecureFreeNormal] + #[weight = 0] fn some_unsigned_message(origin) { let _ = frame_system::ensure_none(origin); } @@ -428,6 +500,11 @@ mod tests { fn on_finalize() { println!("on_finalize(?)"); } + + fn on_runtime_upgrade() -> Weight { + sp_io::storage::set(super::TEST_KEY, "module".as_bytes()); + 0 + } } } } @@ -462,8 +539,15 @@ mod tests { pub const MaximumBlockWeight: Weight = 1024; pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); + pub const BlockExecutionWeight: Weight = 10; + pub const ExtrinsicBaseWeight: Weight = 5; + pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { + read: 10, + write: 100, + }; } impl frame_system::Trait for Runtime { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type Call = Call; @@ -476,35 +560,41 @@ mod tests { type Event = MetaEvent; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = DbWeight; + type BlockExecutionWeight = BlockExecutionWeight; + type ExtrinsicBaseWeight = ExtrinsicBaseWeight; + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = RuntimeVersion; type ModuleToIndex = (); - type AccountData = pallet_balances::AccountData; + type AccountData = pallet_balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } + + type Balance = u64; parameter_types! { - pub const ExistentialDeposit: u64 = 1; + pub const ExistentialDeposit: Balance = 1; } impl pallet_balances::Trait for Runtime { - type Balance = u64; + type Balance = Balance; type Event = MetaEvent; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; + type WeightInfo = (); } parameter_types! { - pub const TransactionBaseFee: u64 = 10; - pub const TransactionByteFee: u64 = 0; + pub const TransactionByteFee: Balance = 0; } impl pallet_transaction_payment::Trait for Runtime { type Currency = Balances; type OnTransactionPayment = (); - type TransactionBaseFee = TransactionBaseFee; type TransactionByteFee = TransactionByteFee; - type WeightToFee = ConvertInto; + type WeightToFee = IdentityFee; type FeeMultiplierUpdate = (); } impl custom::Trait for Runtime {} @@ -543,13 +633,33 @@ mod tests { frame_system::CheckEra, frame_system::CheckNonce, frame_system::CheckWeight, - pallet_transaction_payment::ChargeTransactionPayment + pallet_transaction_payment::ChargeTransactionPayment, ); type AllModules = (System, Balances, Custom); type TestXt = sp_runtime::testing::TestXt; - type Executive = super::Executive, ChainContext, Runtime, AllModules>; - fn extra(nonce: u64, fee: u64) -> SignedExtra { + // Will contain `true` when the custom runtime logic was called. + const CUSTOM_ON_RUNTIME_KEY: &[u8] = &*b":custom:on_runtime"; + + struct CustomOnRuntimeUpgrade; + impl OnRuntimeUpgrade for CustomOnRuntimeUpgrade { + fn on_runtime_upgrade() -> Weight { + sp_io::storage::set(TEST_KEY, "custom_upgrade".as_bytes()); + sp_io::storage::set(CUSTOM_ON_RUNTIME_KEY, &true.encode()); + 0 + } + } + + type Executive = super::Executive< + Runtime, + Block, + ChainContext, + Runtime, + AllModules, + CustomOnRuntimeUpgrade + >; + + fn extra(nonce: u64, fee: Balance) -> SignedExtra { ( frame_system::CheckEra::from(Era::Immortal), frame_system::CheckNonce::from(nonce), @@ -558,7 +668,7 @@ mod tests { ) } - fn sign_extra(who: u64, nonce: u64, fee: u64) -> Option<(u64, SignedExtra)> { + fn sign_extra(who: u64, nonce: u64, fee: Balance) -> Option<(u64, SignedExtra)> { Some((who, extra(nonce, fee))) } @@ -569,7 +679,9 @@ mod tests { balances: vec![(1, 211)], }.assimilate_storage(&mut t).unwrap(); let xt = TestXt::new(Call::Balances(BalancesCall::transfer(2, 69)), sign_extra(1, 0, 0)); - let weight = xt.get_dispatch_info().weight as u64; + let weight = xt.get_dispatch_info().weight + ::ExtrinsicBaseWeight::get(); + let fee: Balance + = ::WeightToFee::calc(&weight); let mut t = sp_io::TestExternalities::new(t); t.execute_with(|| { Executive::initialize_block(&Header::new( @@ -581,12 +693,12 @@ mod tests { )); let r = Executive::apply_extrinsic(xt); assert!(r.is_ok()); - assert_eq!(>::total_balance(&1), 142 - 10 - weight); + assert_eq!(>::total_balance(&1), 142 - fee); assert_eq!(>::total_balance(&2), 69); }); } - fn new_test_ext(balance_factor: u64) -> sp_io::TestExternalities { + fn new_test_ext(balance_factor: Balance) -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); pallet_balances::GenesisConfig:: { balances: vec![(1, 111 * balance_factor)], @@ -601,7 +713,7 @@ mod tests { header: Header { parent_hash: [69u8; 32].into(), number: 1, - state_root: hex!("489ae9b57a19bb4733a264dc64bbcae9b140a904657a681ed3bb5fbbe8cf412b").into(), + state_root: hex!("e8ff7b3dd4375f6f3a76e24a1999e2a7be2d15b353e49ac94ace1eae3e80eb87").into(), extrinsics_root: hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into(), digest: Digest { logs: vec![], }, }, @@ -669,8 +781,10 @@ mod tests { let xt = TestXt::new(Call::Balances(BalancesCall::transfer(33, 0)), sign_extra(1, 0, 0)); let encoded = xt.encode(); let encoded_len = encoded.len() as Weight; - let limit = AvailableBlockRatio::get() * MaximumBlockWeight::get() - 175; - let num_to_exhaust_block = limit / encoded_len; + // Block execution weight + on_initialize weight + let base_block_weight = 175 + ::BlockExecutionWeight::get(); + let limit = AvailableBlockRatio::get() * MaximumBlockWeight::get() - base_block_weight; + let num_to_exhaust_block = limit / (encoded_len + 5); t.execute_with(|| { Executive::initialize_block(&Header::new( 1, @@ -679,8 +793,8 @@ mod tests { [69u8; 32].into(), Digest::default(), )); - // Initial block weight form the custom module. - assert_eq!(>::all_extrinsics_weight(), 175); + // Base block execution weight + `on_initialize` weight from the custom module. + assert_eq!(>::block_weight().total(), base_block_weight); for nonce in 0..=num_to_exhaust_block { let xt = TestXt::new( @@ -690,8 +804,9 @@ mod tests { if nonce != num_to_exhaust_block { assert!(res.is_ok()); assert_eq!( - >::all_extrinsics_weight(), - encoded_len * (nonce + 1) + 175, + >::block_weight().total(), + //--------------------- on_initialize + block_execution + extrinsic_base weight + (encoded_len + 5) * (nonce + 1) + base_block_weight, ); assert_eq!(>::extrinsic_index(), Some(nonce as u32 + 1)); } else { @@ -709,7 +824,18 @@ mod tests { let len = xt.clone().encode().len() as u32; let mut t = new_test_ext(1); t.execute_with(|| { - assert_eq!(>::all_extrinsics_weight(), 0); + // Block execution weight + on_initialize weight from custom module + let base_block_weight = 175 + ::BlockExecutionWeight::get(); + + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + assert_eq!(>::block_weight().total(), base_block_weight); assert_eq!(>::all_extrinsics_len(), 0); assert!(Executive::apply_extrinsic(xt.clone()).unwrap().is_ok()); @@ -717,13 +843,28 @@ mod tests { assert!(Executive::apply_extrinsic(x2.clone()).unwrap().is_ok()); // default weight for `TestXt` == encoded length. - assert_eq!(>::all_extrinsics_weight(), (3 * len) as Weight); + let extrinsic_weight = len as Weight + ::ExtrinsicBaseWeight::get(); + assert_eq!( + >::block_weight().total(), + base_block_weight + 3 * extrinsic_weight, + ); assert_eq!(>::all_extrinsics_len(), 3 * len); let _ = >::finalize(); - - assert_eq!(>::all_extrinsics_weight(), 0); + // All extrinsics length cleaned on `System::finalize` assert_eq!(>::all_extrinsics_len(), 0); + + // New Block + Executive::initialize_block(&Header::new( + 2, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + // Block weight cleaned up on `System::initialize` + assert_eq!(>::block_weight().total(), base_block_weight); }); } @@ -747,7 +888,7 @@ mod tests { let execute_with_lock = |lock: WithdrawReasons| { let mut t = new_test_ext(1); t.execute_with(|| { - as LockableCurrency>::set_lock( + as LockableCurrency>::set_lock( id, &1, 110, @@ -757,7 +898,10 @@ mod tests { Call::System(SystemCall::remark(vec![1u8])), sign_extra(1, 0, 0), ); - let weight = xt.get_dispatch_info().weight as u64; + let weight = xt.get_dispatch_info().weight + + ::ExtrinsicBaseWeight::get(); + let fee: Balance = + ::WeightToFee::calc(&weight); Executive::initialize_block(&Header::new( 1, H256::default(), @@ -769,7 +913,7 @@ mod tests { if lock == WithdrawReasons::except(WithdrawReason::TransactionPayment) { assert!(Executive::apply_extrinsic(xt).unwrap().is_ok()); // tx fee has been deducted. - assert_eq!(>::total_balance(&1), 111 - 10 - weight); + assert_eq!(>::total_balance(&1), 111 - fee); } else { assert_eq!( Executive::apply_extrinsic(xt), @@ -789,9 +933,10 @@ mod tests { new_test_ext(1).execute_with(|| { Executive::initialize_block(&Header::new_from_number(1)); - // NOTE: might need updates over time if system and balance introduce new weights. For - // now only accounts for the custom module. - assert_eq!(>::all_extrinsics_weight(), 150 + 25); + // NOTE: might need updates over time if new weights are introduced. + // For now it only accounts for the base block execution weight and + // the `on_initialize` weight defined in the custom test module. + assert_eq!(>::block_weight().total(), 175 + 10); }) } @@ -866,4 +1011,26 @@ mod tests { assert_eq!(result, last.was_upgraded(¤t)); } } + + #[test] + fn custom_runtime_upgrade_is_called_before_modules() { + new_test_ext(1).execute_with(|| { + // Make sure `on_runtime_upgrade` is called. + RUNTIME_VERSION.with(|v| *v.borrow_mut() = sp_version::RuntimeVersion { + spec_version: 1, + ..Default::default() + }); + + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + assert_eq!(&sp_io::storage::get(TEST_KEY).unwrap()[..], *b"module"); + assert_eq!(sp_io::storage::get(CUSTOM_ON_RUNTIME_KEY).unwrap(), true.encode()); + }); + } } diff --git a/frame/finality-tracker/Cargo.toml b/frame/finality-tracker/Cargo.toml index e261fae05f5afd4bda7e69a0fc26e3d052890488..f9922af84e119d2a59a6855ce7f6767e1219094b 100644 --- a/frame/finality-tracker/Cargo.toml +++ b/frame/finality-tracker/Cargo.toml @@ -1,29 +1,32 @@ [package] name = "pallet-finality-tracker" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME Pallet that tracks the last finalized block, as perceived by block authors." documentation = "https://docs.rs/pallet-finality-tracker" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", default-features = false, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -sp-inherents = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/inherents" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -sp-finality-tracker = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/finality-tracker" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +sp-inherents = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/inherents" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +sp-finality-tracker = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/finality-tracker" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } impl-trait-for-tuples = "0.1.3" [dev-dependencies] -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/core" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/io" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/core" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } [features] default = ["std"] @@ -37,6 +40,3 @@ std = [ "sp-finality-tracker/std", "sp-inherents/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/finality-tracker/src/lib.rs b/frame/finality-tracker/src/lib.rs index 4a6e2392f2b31e5269bf083acd9176ff5deeebc8..0cbf383c1a09d054c88f114b5694a1d94c42eea9 100644 --- a/frame/finality-tracker/src/lib.rs +++ b/frame/finality-tracker/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! FRAME Pallet that tracks the last finalized block, as perceived by block authors. @@ -23,6 +24,7 @@ use sp_runtime::traits::{One, Zero, SaturatedConversion}; use sp_std::{prelude::*, result, cmp, vec}; use frame_support::{decl_module, decl_storage, decl_error, ensure}; use frame_support::traits::Get; +use frame_support::weights::{DispatchClass}; use frame_system::{ensure_none, Trait as SystemTrait}; use sp_finality_tracker::{INHERENT_IDENTIFIER, FinalizedInherentData}; @@ -76,7 +78,7 @@ decl_module! { /// Hint that the author of this block thinks the best finalized /// block is the given number. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = (0, DispatchClass::Mandatory)] fn final_hint(origin, #[compact] hint: T::BlockNumber) { ensure_none(origin)?; ensure!(!::Update::exists(), Error::::AlreadyUpdated); @@ -207,11 +209,14 @@ mod tests { use sp_io::TestExternalities; use sp_core::H256; use sp_runtime::{ - testing::Header, Perbill, - traits::{BlakeTwo256, IdentityLookup, Header as HeaderT}, + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, + Perbill, }; use frame_support::{ - assert_ok, impl_outer_origin, parameter_types, weights::Weight, traits::OnFinalize + assert_ok, impl_outer_origin, parameter_types, + weights::Weight, + traits::OnFinalize, }; use frame_system as system; use std::cell::RefCell; @@ -248,6 +253,7 @@ mod tests { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -260,6 +266,10 @@ mod tests { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); @@ -267,6 +277,7 @@ mod tests { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } parameter_types! { pub const WindowSize: u64 = 11; @@ -329,10 +340,7 @@ mod tests { &Default::default(), Default::default(), ); - assert_ok!(FinalityTracker::dispatch( - Call::final_hint(i-1), - Origin::NONE, - )); + assert_ok!(FinalityTracker::final_hint(Origin::none(), i - 1)); FinalityTracker::on_finalize(i); let hdr = System::finalize(); parent_hash = hdr.hash(); diff --git a/frame/generic-asset/Cargo.toml b/frame/generic-asset/Cargo.toml index b531a0ed9af24be72d5146a0d06ada267521a8e8..f39a45837850d5aced6fa6195e5d0146324f251f 100644 --- a/frame/generic-asset/Cargo.toml +++ b/frame/generic-asset/Cargo.toml @@ -1,24 +1,27 @@ [package] name = "pallet-generic-asset" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Centrality Developers "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for generic asset management" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } [dev-dependencies] -sp-io ={ version = "2.0.0-alpha.5", path = "../../primitives/io" } -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } +sp-io ={ version = "2.0.0-rc4", path = "../../primitives/io" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } [features] default = ["std"] @@ -30,6 +33,3 @@ std =[ "frame-support/std", "frame-system/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/generic-asset/src/lib.rs b/frame/generic-asset/src/lib.rs index b16666cb6b7e1c5dd96616a38035d141a70f371d..c85920edf350b88603e8e7dc06303079fa6a46c4 100644 --- a/frame/generic-asset/src/lib.rs +++ b/frame/generic-asset/src/lib.rs @@ -157,7 +157,7 @@ use codec::{Decode, Encode, HasCompact, Input, Output, Error as CodecError}; use sp_runtime::{RuntimeDebug, DispatchResult, DispatchError}; use sp_runtime::traits::{ CheckedAdd, CheckedSub, MaybeSerializeDeserialize, Member, One, Saturating, AtLeast32Bit, - Zero, Bounded, + Zero, Bounded, AtLeast32BitUnsigned }; use sp_std::prelude::*; @@ -165,12 +165,13 @@ use sp_std::{cmp, result, fmt::Debug}; use frame_support::{ decl_event, decl_module, decl_storage, ensure, decl_error, traits::{ - Currency, ExistenceRequirement, Imbalance, LockIdentifier, LockableCurrency, ReservableCurrency, - SignedImbalance, WithdrawReason, WithdrawReasons, TryDrop, BalanceStatus, + Currency, ExistenceRequirement, Imbalance, LockIdentifier, LockableCurrency, + ReservableCurrency, SignedImbalance, WithdrawReason, WithdrawReasons, TryDrop, + BalanceStatus, }, Parameter, StorageMap, }; -use frame_system::{self as system, ensure_signed, ensure_root}; +use frame_system::{ensure_signed, ensure_root}; mod mock; mod tests; @@ -178,25 +179,15 @@ mod tests; pub use self::imbalances::{NegativeImbalance, PositiveImbalance}; pub trait Trait: frame_system::Trait { - type Balance: Parameter - + Member - + AtLeast32Bit - + Default - + Copy - + MaybeSerializeDeserialize - + Debug; + type Balance: Parameter + Member + AtLeast32BitUnsigned + Default + Copy + Debug + + MaybeSerializeDeserialize; type AssetId: Parameter + Member + AtLeast32Bit + Default + Copy; type Event: From> + Into<::Event>; } pub trait Subtrait: frame_system::Trait { - type Balance: Parameter - + Member - + AtLeast32Bit - + Default - + Copy - + MaybeSerializeDeserialize - + Debug; + type Balance: Parameter + Member + AtLeast32BitUnsigned + Default + Copy + Debug + + MaybeSerializeDeserialize; type AssetId: Parameter + Member + AtLeast32Bit + Default + Copy; } @@ -360,14 +351,14 @@ decl_module! { fn deposit_event() = default; /// Create a new kind of asset. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] fn create(origin, options: AssetOptions) -> DispatchResult { let origin = ensure_signed(origin)?; Self::create_asset(None, Some(origin), options) } /// Transfer some liquid free balance to another account. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] pub fn transfer(origin, #[compact] asset_id: T::AssetId, to: T::AccountId, #[compact] amount: T::Balance) { let origin = ensure_signed(origin)?; ensure!(!amount.is_zero(), Error::::ZeroAmount); @@ -377,7 +368,7 @@ decl_module! { /// Updates permission for a given `asset_id` and an account. /// /// The `origin` must have `update` permission. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] fn update_permission( origin, #[compact] asset_id: T::AssetId, @@ -400,7 +391,7 @@ decl_module! { /// Mints an asset, increases its total issuance. /// The origin must have `mint` permissions. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] fn mint(origin, #[compact] asset_id: T::AssetId, to: T::AccountId, amount: T::Balance) -> DispatchResult { let who = ensure_signed(origin)?; Self::mint_free(&asset_id, &who, &to, &amount)?; @@ -410,7 +401,7 @@ decl_module! { /// Burns an asset, decreases its total issuance. /// The `origin` must have `burn` permissions. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] fn burn(origin, #[compact] asset_id: T::AssetId, to: T::AccountId, amount: T::Balance) -> DispatchResult { let who = ensure_signed(origin)?; Self::burn_free(&asset_id, &who, &to, &amount)?; @@ -420,7 +411,7 @@ decl_module! { /// Can be used to create reserved tokens. /// Requires Root call. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] fn create_reserved( origin, asset_id: T::AssetId, @@ -442,16 +433,22 @@ pub struct BalanceLock { decl_storage! { trait Store for Module as GenericAsset { /// Total issuance of a given asset. + /// + /// TWOX-NOTE: `AssetId` is trusted. 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 hasher(twox_64_concat) T::AssetId => T::Balance; /// The free balance of a given asset under an account. + /// + /// TWOX-NOTE: `AssetId` is trusted. pub FreeBalance: double_map hasher(twox_64_concat) T::AssetId, hasher(blake2_128_concat) T::AccountId => T::Balance; /// The reserved balance of a given asset under an account. + /// + /// TWOX-NOTE: `AssetId` is trusted. pub ReservedBalance: double_map hasher(twox_64_concat) T::AssetId, hasher(blake2_128_concat) T::AccountId => T::Balance; @@ -459,6 +456,8 @@ decl_storage! { pub NextAssetId get(fn next_asset_id) config(): T::AssetId; /// Permission options for a given asset. + /// + /// TWOX-NOTE: `AssetId` is trusted. pub Permissions get(fn get_permission): map hasher(twox_64_concat) T::AssetId => PermissionVersions; @@ -1112,6 +1111,7 @@ impl PartialEq for ElevatedTrait { } impl Eq for ElevatedTrait {} impl frame_system::Trait for ElevatedTrait { + type BaseCallFilter = T::BaseCallFilter; type Origin = T::Origin; type Call = T::Call; type Index = T::Index; @@ -1124,6 +1124,10 @@ impl frame_system::Trait for ElevatedTrait { type Event = (); type BlockHashCount = T::BlockHashCount; type MaximumBlockWeight = T::MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = T::MaximumBlockWeight; type MaximumBlockLength = T::MaximumBlockLength; type AvailableBlockRatio = T::AvailableBlockRatio; type Version = T::Version; @@ -1131,6 +1135,7 @@ impl frame_system::Trait for ElevatedTrait { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } impl Trait for ElevatedTrait { type Balance = T::Balance; diff --git a/frame/generic-asset/src/mock.rs b/frame/generic-asset/src/mock.rs index c805b793bc7b4e358e8c8f2b4b5045a8c14dd360..8c0a06a1564df1840a7a47f8ca5d9e59d874f0a5 100644 --- a/frame/generic-asset/src/mock.rs +++ b/frame/generic-asset/src/mock.rs @@ -34,9 +34,6 @@ impl_outer_origin! { pub enum Origin for Test where system = frame_system {} } -// For testing the pallet, we construct most of a mock runtime. This means -// first constructing a configuration type (`Test`) which `impl`s each of the -// configuration traits of pallets we want to use. #[derive(Clone, Eq, PartialEq)] pub struct Test; parameter_types! { @@ -46,6 +43,7 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -57,6 +55,10 @@ impl frame_system::Trait for Test { type Header = Header; type Event = TestEvent; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type BlockHashCount = BlockHashCount; @@ -65,6 +67,7 @@ impl frame_system::Trait for Test { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } impl Trait for Test { @@ -141,8 +144,6 @@ impl ExtBuilder { } } -// This function basically just builds a genesis storage key/value store according to -// our desired mockup. pub fn new_test_ext() -> sp_io::TestExternalities { frame_system::GenesisConfig::default() .build_storage::() diff --git a/frame/generic-asset/src/tests.rs b/frame/generic-asset/src/tests.rs index d5c0a877dfe75aba4236a2130372a80b06f74a6c..a094f69ba1fc581f0138574e06c202c404050cd6 100644 --- a/frame/generic-asset/src/tests.rs +++ b/frame/generic-asset/src/tests.rs @@ -598,7 +598,7 @@ fn create_reserved_should_create_a_default_account_with_the_balance_given() { let created_asset_id = 9; let created_account_id = 0; - assert_ok!(GenericAsset::create_reserved(Origin::ROOT, created_asset_id, options)); + assert_ok!(GenericAsset::create_reserved(Origin::root(), created_asset_id, options)); // Tests for side effects. assert_eq!(>::get(created_asset_id), expected_total_issuance); diff --git a/frame/grandpa/Cargo.toml b/frame/grandpa/Cargo.toml index 206b563bd9555c9f163d82473788a8baf3ecc275..0f2477d50e8a94eda0a60982ab44559d2a873e98 100644 --- a/frame/grandpa/Cargo.toml +++ b/frame/grandpa/Cargo.toml @@ -1,36 +1,50 @@ [package] name = "pallet-grandpa" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for GRANDPA finality gadget" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/core" } -sp-finality-grandpa = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/finality-grandpa" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -sp-staking = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/staking" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } -pallet-session = { version = "2.0.0-alpha.5", default-features = false, path = "../session" } -pallet-finality-tracker = { version = "2.0.0-alpha.5", default-features = false, path = "../finality-tracker" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-application-crypto = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/application-crypto" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/core" } +sp-finality-grandpa = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/finality-grandpa" } +sp-session = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/session" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +sp-staking = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/staking" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } +pallet-session = { version = "2.0.0-rc4", default-features = false, path = "../session" } +pallet-finality-tracker = { version = "2.0.0-rc4", default-features = false, path = "../finality-tracker" } [dev-dependencies] -sp-io ={ version = "2.0.0-alpha.5", path = "../../primitives/io" } +grandpa = { package = "finality-grandpa", version = "0.12.3", features = ["derive-codec"] } +sp-io = { version = "2.0.0-rc4", path = "../../primitives/io" } +sp-keyring = { version = "2.0.0-rc4", path = "../../primitives/keyring" } +pallet-balances = { version = "2.0.0-rc4", path = "../balances" } +pallet-offences = { version = "2.0.0-rc4", path = "../offences" } +pallet-staking = { version = "2.0.0-rc4", path = "../staking" } +pallet-staking-reward-curve = { version = "2.0.0-rc4", path = "../staking/reward-curve" } +pallet-timestamp = { version = "2.0.0-rc4", path = "../timestamp" } [features] default = ["std"] std = [ "serde", "codec/std", + "sp-application-crypto/std", "sp-core/std", "sp-finality-grandpa/std", + "sp-session/std", "sp-std/std", "frame-support/std", "sp-runtime/std", @@ -39,6 +53,3 @@ std = [ "pallet-session/std", "pallet-finality-tracker/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/grandpa/src/equivocation.rs b/frame/grandpa/src/equivocation.rs new file mode 100644 index 0000000000000000000000000000000000000000..9ac1c12128565ed0cf81ac1f6dece2d22c99bab8 --- /dev/null +++ b/frame/grandpa/src/equivocation.rs @@ -0,0 +1,379 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! +//! An opt-in utility module for reporting equivocations. +//! +//! This module defines an offence type for GRANDPA equivocations +//! and some utility traits to wire together: +//! - a key ownership proof system (e.g. to prove that a given authority was +//! part of a session); +//! - a system for reporting offences; +//! - a system for signing and submitting transactions; +//! +//! These can be used in an offchain context in order to submit equivocation +//! reporting extrinsics (from the client that's running the GRANDPA protocol). +//! And in a runtime context, so that the GRANDPA module can validate the +//! equivocation proofs in the extrinsic and report the offences. +//! +//! IMPORTANT: +//! When using this module for enabling equivocation reporting it is required +//! that the `ValidateEquivocationReport` signed extension is used in the runtime +//! definition. Failure to do so will allow invalid equivocation reports to be +//! accepted by the runtime. +//! + +use sp_std::prelude::*; + +use codec::{self as codec, Decode, Encode}; +use frame_support::{debug, dispatch::IsSubType, traits::KeyOwnerProofSystem}; +use frame_system::offchain::{AppCrypto, CreateSignedTransaction, Signer}; +use sp_finality_grandpa::{EquivocationProof, RoundNumber, SetId}; +use sp_runtime::{ + traits::{DispatchInfoOf, SignedExtension}, + transaction_validity::{ + InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction, + }, + DispatchResult, Perbill, +}; +use sp_session::GetSessionNumber; +use sp_staking::{ + offence::{Kind, Offence, OffenceError, ReportOffence}, + SessionIndex, +}; + +/// Ensure that equivocation reports are only processed if valid. +#[derive(Encode, Decode, Clone, Eq, PartialEq)] +pub struct ValidateEquivocationReport(sp_std::marker::PhantomData); + +impl Default for ValidateEquivocationReport { + fn default() -> ValidateEquivocationReport { + ValidateEquivocationReport::new() + } +} + +impl ValidateEquivocationReport { + pub fn new() -> ValidateEquivocationReport { + ValidateEquivocationReport(Default::default()) + } +} + +impl sp_std::fmt::Debug for ValidateEquivocationReport { + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "ValidateEquivocationReport") + } +} + +/// Custom validity error used when validating equivocation reports. +#[derive(Debug)] +#[repr(u8)] +pub enum ReportEquivocationValidityError { + /// The proof provided in the report is not valid. + InvalidEquivocationProof = 1, + /// The proof provided in the report is not valid. + InvalidKeyOwnershipProof = 2, + /// The set id provided in the report is not valid. + InvalidSetId = 3, + /// The session index provided in the report is not valid. + InvalidSession = 4, +} + +impl From for TransactionValidityError { + fn from(e: ReportEquivocationValidityError) -> TransactionValidityError { + TransactionValidityError::from(InvalidTransaction::Custom(e as u8)) + } +} + +impl SignedExtension for ValidateEquivocationReport +where + ::Call: IsSubType>, +{ + const IDENTIFIER: &'static str = "ValidateEquivocationReport"; + type AccountId = T::AccountId; + type Call = ::Call; + type AdditionalSigned = (); + type Pre = (); + + fn additional_signed( + &self, + ) -> sp_std::result::Result { + Ok(()) + } + + fn validate( + &self, + _who: &Self::AccountId, + call: &Self::Call, + _info: &DispatchInfoOf, + _len: usize, + ) -> TransactionValidity { + let (equivocation_proof, key_owner_proof) = match call.is_sub_type() { + Some(super::Call::report_equivocation(equivocation_proof, key_owner_proof)) => { + (equivocation_proof, key_owner_proof) + } + _ => return Ok(ValidTransaction::default()), + }; + + // validate the key ownership proof extracting the id of the offender. + if let None = T::KeyOwnerProofSystem::check_proof( + ( + sp_finality_grandpa::KEY_TYPE, + equivocation_proof.offender().clone(), + ), + key_owner_proof.clone(), + ) { + return Err(ReportEquivocationValidityError::InvalidKeyOwnershipProof.into()); + } + + // we check the equivocation within the context of its set id (and + // associated session). + let set_id = equivocation_proof.set_id(); + let session_index = key_owner_proof.session(); + + // validate equivocation proof (check votes are different and + // signatures are valid). + if !sp_finality_grandpa::check_equivocation_proof(equivocation_proof.clone()) { + return Err(ReportEquivocationValidityError::InvalidEquivocationProof.into()); + } + + // fetch the current and previous sets last session index. on the + // genesis set there's no previous set. + let previous_set_id_session_index = if set_id == 0 { + None + } else { + let session_index = + if let Some(session_id) = >::session_for_set(set_id - 1) { + session_id + } else { + return Err(ReportEquivocationValidityError::InvalidSetId.into()); + }; + + Some(session_index) + }; + + let set_id_session_index = + if let Some(session_id) = >::session_for_set(set_id) { + session_id + } else { + return Err(ReportEquivocationValidityError::InvalidSetId.into()); + }; + + // check that the session id for the membership proof is within the + // bounds of the set id reported in the equivocation. + if session_index > set_id_session_index || + previous_set_id_session_index + .map(|previous_index| session_index <= previous_index) + .unwrap_or(false) + { + return Err(ReportEquivocationValidityError::InvalidSession.into()); + } + + Ok(ValidTransaction::default()) + } +} + +/// A trait with utility methods for handling equivocation reports in GRANDPA. +/// The offence type is generic, and the trait provides , reporting an offence +/// triggered by a valid equivocation report, and also for creating and +/// submitting equivocation report extrinsics (useful only in offchain context). +pub trait HandleEquivocation { + /// The offence type used for reporting offences on valid equivocation reports. + type Offence: GrandpaOffence; + + /// Report an offence proved by the given reporters. + fn report_offence( + reporters: Vec, + offence: Self::Offence, + ) -> Result<(), OffenceError>; + + /// Create and dispatch an equivocation report extrinsic. + fn submit_equivocation_report( + equivocation_proof: EquivocationProof, + key_owner_proof: T::KeyOwnerProof, + ) -> DispatchResult; +} + +impl HandleEquivocation for () { + type Offence = GrandpaEquivocationOffence; + + fn report_offence( + _reporters: Vec, + _offence: GrandpaEquivocationOffence, + ) -> Result<(), OffenceError> { + Ok(()) + } + + fn submit_equivocation_report( + _equivocation_proof: EquivocationProof, + _key_owner_proof: T::KeyOwnerProof, + ) -> DispatchResult { + Ok(()) + } +} + +/// Generic equivocation handler. This type implements `HandleEquivocation` +/// using existing subsystems that are part of frame (type bounds described +/// below) and will dispatch to them directly, it's only purpose is to wire all +/// subsystems together. +pub struct EquivocationHandler> { + _phantom: sp_std::marker::PhantomData<(I, C, S, R, O)>, +} + +impl Default for EquivocationHandler { + fn default() -> Self { + Self { + _phantom: Default::default(), + } + } +} + +impl HandleEquivocation + for EquivocationHandler +where + // A signed transaction creator. Used for signing and submitting equivocation reports. + T: super::Trait + CreateSignedTransaction>, + // Application-specific crypto bindings. + C: AppCrypto, + // The offence type that should be used when reporting. + O: GrandpaOffence, + // A system for reporting offences after valid equivocation reports are + // processed. + R: ReportOffence, +{ + type Offence = O; + + fn report_offence(reporters: Vec, offence: O) -> Result<(), OffenceError> { + R::report_offence(reporters, offence) + } + + fn submit_equivocation_report( + equivocation_proof: EquivocationProof, + key_owner_proof: T::KeyOwnerProof, + ) -> DispatchResult { + use frame_system::offchain::SendSignedTransaction; + + let signer = Signer::::all_accounts(); + if !signer.can_sign() { + return Err( + "No local accounts available. Consider adding one via `author_insertKey` RPC.", + )?; + } + + let results = signer.send_signed_transaction(|_account| { + super::Call::report_equivocation(equivocation_proof.clone(), key_owner_proof.clone()) + }); + + for (acc, res) in &results { + match res { + Ok(()) => debug::info!("[{:?}] Submitted GRANDPA equivocation report.", acc.id), + Err(e) => debug::error!( + "[{:?}] Error submitting equivocation report: {:?}", + acc.id, + e + ), + } + } + + Ok(()) + } +} + +/// A round number and set id which point on the time of an offence. +#[derive(Copy, Clone, PartialOrd, Ord, Eq, PartialEq, Encode, Decode)] +pub struct GrandpaTimeSlot { + // The order of these matters for `derive(Ord)`. + /// Grandpa Set ID. + pub set_id: SetId, + /// Round number. + pub round: RoundNumber, +} + +/// A grandpa equivocation offence report. +#[allow(dead_code)] +pub struct GrandpaEquivocationOffence { + /// Time slot at which this incident happened. + pub time_slot: GrandpaTimeSlot, + /// The session index in which the incident happened. + pub session_index: SessionIndex, + /// The size of the validator set at the time of the offence. + pub validator_set_count: u32, + /// The authority which produced this equivocation. + pub offender: FullIdentification, +} + +/// An interface for types that will be used as GRANDPA offences and must also +/// implement the `Offence` trait. This trait provides a constructor that is +/// provided all available data during processing of GRANDPA equivocations. +pub trait GrandpaOffence: Offence { + /// Create a new GRANDPA offence using the given equivocation details. + fn new( + session_index: SessionIndex, + validator_set_count: u32, + offender: FullIdentification, + set_id: SetId, + round: RoundNumber, + ) -> Self; +} + +impl GrandpaOffence + for GrandpaEquivocationOffence +{ + fn new( + session_index: SessionIndex, + validator_set_count: u32, + offender: FullIdentification, + set_id: SetId, + round: RoundNumber, + ) -> Self { + GrandpaEquivocationOffence { + session_index, + validator_set_count, + offender, + time_slot: GrandpaTimeSlot { set_id, round }, + } + } +} + +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/frame/grandpa/src/lib.rs b/frame/grandpa/src/lib.rs index 030699b52587262eef974a923fd4074a7fb043e3..91d783cb1ad7a07c311eaf6d5eb64bc45996e12e 100644 --- a/frame/grandpa/src/lib.rs +++ b/frame/grandpa/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! GRANDPA Consensus module for runtime. //! @@ -31,27 +32,68 @@ pub use sp_finality_grandpa as fg_primitives; use sp_std::prelude::*; -use codec::{self as codec, Encode, Decode}; -use frame_support::{decl_event, decl_storage, decl_module, decl_error, storage}; -use sp_runtime::{ - DispatchResult, generic::{DigestItem, OpaqueDigestItemId}, traits::Zero, Perbill, + +use codec::{self as codec, Decode, Encode}; +pub use fg_primitives::{AuthorityId, AuthorityList, AuthorityWeight, VersionedAuthorityList}; +use fg_primitives::{ + ConsensusLog, EquivocationProof, ScheduledChange, SetId, GRANDPA_AUTHORITIES_KEY, + GRANDPA_ENGINE_ID, }; -use sp_staking::{ - SessionIndex, - offence::{Offence, Kind}, +use frame_support::{ + decl_error, decl_event, decl_module, decl_storage, storage, traits::KeyOwnerProofSystem, + Parameter, }; -use fg_primitives::{ - GRANDPA_AUTHORITIES_KEY, GRANDPA_ENGINE_ID, ScheduledChange, ConsensusLog, SetId, RoundNumber, +use frame_system::{ensure_signed, DigestOf}; +use sp_runtime::{ + generic::{DigestItem, OpaqueDigestItemId}, + traits::Zero, + DispatchResult, KeyTypeId, }; -pub use fg_primitives::{AuthorityId, AuthorityList, AuthorityWeight, VersionedAuthorityList}; -use frame_system::{self as system, ensure_signed, DigestOf}; +use sp_session::{GetSessionNumber, GetValidatorCount}; +use sp_staking::SessionIndex; +mod equivocation; +#[cfg(all(feature = "std", test))] mod mock; +#[cfg(all(feature = "std", test))] mod tests; +pub use equivocation::{ + EquivocationHandler, GrandpaEquivocationOffence, GrandpaOffence, GrandpaTimeSlot, + HandleEquivocation, ValidateEquivocationReport, +}; + pub trait Trait: frame_system::Trait { /// The event type of this module. type Event: From + Into<::Event>; + + /// The function call. + type Call: From>; + + /// The proof of key ownership, used for validating equivocation reports. + /// The proof must include the session index and validator count of the + /// session at which the equivocation occurred. + type KeyOwnerProof: Parameter + GetSessionNumber + GetValidatorCount; + + /// The identification of a key owner, used when reporting equivocations. + type KeyOwnerIdentification: Parameter; + + /// A system for proving ownership of keys, i.e. that a given key was part + /// of a validator set, needed for validating equivocation reports. + type KeyOwnerProofSystem: KeyOwnerProofSystem< + (KeyTypeId, AuthorityId), + Proof = Self::KeyOwnerProof, + IdentificationTuple = Self::KeyOwnerIdentification, + >; + + /// The equivocation handling subsystem, defines methods to report an + /// offence (after the equivocation has been validated) and for submitting a + /// transaction to report an equivocation (from an offchain context). + /// NOTE: when enabling equivocation handling (i.e. this type isn't set to + /// `()`) you must add the `equivocation::ValidateEquivocationReport` signed + /// extension to the runtime's `SignedExtra` definition, otherwise + /// equivocation reports won't be properly validated. + type HandleEquivocation: HandleEquivocation; } /// A stored pending change, old format. @@ -146,6 +188,10 @@ decl_error! { ChangePending, /// Cannot signal forced change so soon after last. TooSoon, + /// A key ownership proof provided as part of an equivocation report is invalid. + InvalidKeyOwnershipProof, + /// A given equivocation report is valid but already previously reported. + DuplicateOffenceReport, } } @@ -169,11 +215,15 @@ decl_storage! { /// A mapping from grandpa set ID to the index of the *most recent* session for which its /// members were responsible. + /// + /// TWOX-NOTE: `SetId` is not under user control. SetIdSession get(fn session_for_set): map hasher(twox_64_concat) SetId => Option; } add_extra_genesis { config(authorities): AuthorityList; - build(|config| Module::::initialize_authorities(&config.authorities)) + build(|config| { + Module::::initialize(&config.authorities) + }) } } @@ -183,11 +233,50 @@ decl_module! { fn deposit_event() = default; - /// Report some misbehavior. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] - fn report_misbehavior(origin, _report: Vec) { - ensure_signed(origin)?; - // FIXME: https://github.com/paritytech/substrate/issues/1112 + /// Report voter equivocation/misbehavior. This method will verify the + /// equivocation proof and validate the given key ownership proof + /// against the extracted offender. If both are valid, the offence + /// will be reported. + /// + /// Since the weight of the extrinsic is 0, in order to avoid DoS by + /// submission of invalid equivocation reports, a mandatory pre-validation of + /// the extrinsic is implemented in a `SignedExtension`. + #[weight = 0] + fn report_equivocation( + origin, + equivocation_proof: EquivocationProof, + key_owner_proof: T::KeyOwnerProof, + ) { + let reporter_id = ensure_signed(origin)?; + + let (session_index, validator_set_count) = ( + key_owner_proof.session(), + key_owner_proof.validator_count(), + ); + + // we have already checked this proof in `SignedExtension`, we to + // check it again to get the full identification of the offender. + let offender = + T::KeyOwnerProofSystem::check_proof( + (fg_primitives::KEY_TYPE, equivocation_proof.offender().clone()), + key_owner_proof, + ).ok_or(Error::::InvalidKeyOwnershipProof)?; + + // the set id and round when the offence happened + let set_id = equivocation_proof.set_id(); + let round = equivocation_proof.round(); + + // report to the offences module rewarding the sender. + T::HandleEquivocation::report_offence( + vec![reporter_id], + >::Offence::new( + session_index, + validator_set_count, + offender, + set_id, + round, + ), + ).map_err(|_| Error::::DuplicateOffenceReport)?; } fn on_finalize(block_number: T::BlockNumber) { @@ -351,7 +440,9 @@ impl Module { >::deposit_log(log.into()); } - fn initialize_authorities(authorities: &AuthorityList) { + // Perform module initialization, abstracted so that it can be called either through genesis + // config builder or through `on_genesis_session`. + fn initialize(authorities: &AuthorityList) { if !authorities.is_empty() { assert!( Self::grandpa_authorities().is_empty(), @@ -359,6 +450,22 @@ impl Module { ); Self::set_grandpa_authorities(authorities); } + + // NOTE: initialize first session of first set. this is necessary for + // the genesis set and session since we only update the set -> session + // mapping whenever a new session starts, i.e. through `on_new_session`. + SetIdSession::insert(0, 0); + } + + /// Submits an extrinsic to report an equivocation. This method will sign an + /// extrinsic with a call to `report_equivocation` with any reporting keys + /// available in the keystore and will push the transaction to the pool. + /// Only useful in an offchain context. + pub fn submit_report_equivocation_extrinsic( + equivocation_proof: EquivocationProof, + key_owner_proof: T::KeyOwnerProof, + ) -> Option<()> { + T::HandleEquivocation::submit_equivocation_report(equivocation_proof, key_owner_proof).ok() } } @@ -411,7 +518,7 @@ impl pallet_session::OneSessionHandler for Module where I: Iterator { let authorities = validators.map(|(_, k)| (k, 1)).collect::>(); - Self::initialize_authorities(&authorities); + Self::initialize(&authorities); } fn on_new_session<'a, I: 'a>(changed: bool, validators: I, _queued_validators: I) @@ -453,55 +560,3 @@ impl pallet_finality_tracker::OnFinalizationStalled fo >::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. -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/frame/grandpa/src/mock.rs b/frame/grandpa/src/mock.rs index 8b94becd5aa6a123f846325b20e6e9632e8d67a6..991ada4fbf35bc85af46c553b6df3edf54afe4a3 100644 --- a/frame/grandpa/src/mock.rs +++ b/frame/grandpa/src/mock.rs @@ -1,58 +1,104 @@ -// Copyright 2018-2020 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. +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utilities #![cfg(test)] -use sp_runtime::{Perbill, DigestItem, traits::IdentityLookup, testing::{Header, UintAuthorityId}}; +use crate::{ + equivocation::ValidateEquivocationReport, AuthorityId, AuthorityList, Call as GrandpaCall, + ConsensusLog, Module, Trait, +}; +use ::grandpa as finality_grandpa; +use codec::Encode; +use frame_support::{ + impl_outer_dispatch, impl_outer_event, impl_outer_origin, parameter_types, + traits::{KeyOwnerProofSystem, OnFinalize, OnInitialize}, + weights::{DispatchInfo, Weight}, +}; +use pallet_staking::EraIndex; +use sp_core::{crypto::KeyTypeId, H256}; +use sp_finality_grandpa::{RoundNumber, SetId, GRANDPA_ENGINE_ID}; use sp_io; -use frame_support::{impl_outer_origin, impl_outer_event, parameter_types, weights::Weight}; -use sp_core::H256; -use codec::{Encode, Decode}; -use crate::{AuthorityId, AuthorityList, GenesisConfig, Trait, Module, ConsensusLog}; -use sp_finality_grandpa::GRANDPA_ENGINE_ID; +use sp_keyring::Ed25519Keyring; +use sp_runtime::{ + curve::PiecewiseLinear, + impl_opaque_keys, + testing::{Header, TestXt, UintAuthorityId}, + traits::{ + Convert, Extrinsic as ExtrinsicT, IdentityLookup, OpaqueKeys, SaturatedConversion, + SignedExtension, + }, + transaction_validity::TransactionValidityError, + DigestItem, Perbill, +}; +use sp_staking::SessionIndex; use frame_system as system; -impl_outer_origin!{ - pub enum Origin for Test where system = frame_system {} +use pallet_balances as balances; +use pallet_offences as offences; +use pallet_session as session; +use pallet_staking as staking; +use pallet_timestamp as timestamp; + +impl_outer_origin! { + pub enum Origin for Test {} } -pub fn grandpa_log(log: ConsensusLog) -> DigestItem { - DigestItem::Consensus(GRANDPA_ENGINE_ID, log.encode()) +impl_outer_dispatch! { + pub enum Call for Test where origin: Origin { + grandpa::Grandpa, + staking::Staking, + } } -// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. -#[derive(Clone, PartialEq, Eq, Debug, Decode, Encode)] -pub struct Test; +impl_opaque_keys! { + pub struct TestSessionKeys { + pub grandpa_authority: super::Module, + } +} -impl Trait for Test { - type Event = TestEvent; +impl_outer_event! { + pub enum TestEvent for Test { + system, + balances, + grandpa, + offences, + session, + staking, + } } + +#[derive(Clone, Eq, PartialEq)] +pub struct Test; + parameter_types! { pub const BlockHashCount: u64 = 250; pub const MaximumBlockWeight: Weight = 1024; pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); } + impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; - type Call = (); + type Call = Call; type Hash = H256; type Hashing = sp_runtime::traits::BlakeTwo256; type AccountId = u64; @@ -61,24 +107,240 @@ impl frame_system::Trait for Test { type Event = TestEvent; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); type ModuleToIndex = (); - type AccountData = (); + type AccountData = balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); +} + +impl system::offchain::SendTransactionTypes for Test +where + Call: From, +{ + type OverarchingCall = Call; + type Extrinsic = TestXt; +} + +parameter_types! { + pub const Period: u64 = 1; + pub const Offset: u64 = 0; + pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(17); +} + +/// Custom `SessionHandler` since we use `TestSessionKeys` as `Keys`. +impl session::Trait for Test { + type Event = TestEvent; + type ValidatorId = u64; + type ValidatorIdOf = staking::StashOf; + type ShouldEndSession = session::PeriodicSessions; + type NextSessionRotation = session::PeriodicSessions; + type SessionManager = session::historical::NoteHistoricalRoot; + type SessionHandler = ::KeyTypeIdProviders; + type Keys = TestSessionKeys; + type DisabledValidatorsThreshold = DisabledValidatorsThreshold; + type WeightInfo = (); +} + +impl session::historical::Trait for Test { + type FullIdentification = staking::Exposure; + type FullIdentificationOf = staking::ExposureOf; +} + +parameter_types! { + pub const ExistentialDeposit: u128 = 1; +} + +impl balances::Trait for Test { + type Balance = u128; + type DustRemoval = (); + type Event = TestEvent; + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); +} + +parameter_types! { + pub const MinimumPeriod: u64 = 3; +} + +impl timestamp::Trait for Test { + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); +} + +pallet_staking_reward_curve::build! { + const REWARD_CURVE: PiecewiseLinear<'static> = curve!( + min_inflation: 0_025_000u64, + 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: SessionIndex = 3; + pub const BondingDuration: EraIndex = 3; + pub const SlashDeferDuration: EraIndex = 0; + pub const AttestationPeriod: u64 = 100; + pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE; + pub const MaxNominatorRewardedPerValidator: u32 = 64; + pub const ElectionLookahead: u64 = 0; + pub const StakingUnsignedPriority: u64 = u64::max_value() / 2; +} + +pub struct CurrencyToVoteHandler; + +impl Convert for CurrencyToVoteHandler { + fn convert(x: u128) -> u128 { + x + } +} + +impl Convert for CurrencyToVoteHandler { + fn convert(x: u128) -> u64 { + x.saturated_into() + } +} + +impl staking::Trait for Test { + type RewardRemainder = (); + type CurrencyToVote = CurrencyToVoteHandler; + type Event = TestEvent; + type Currency = Balances; + type Slash = (); + type Reward = (); + type SessionsPerEra = SessionsPerEra; + type BondingDuration = BondingDuration; + type SlashDeferDuration = SlashDeferDuration; + type SlashCancelOrigin = system::EnsureRoot; + type SessionInterface = Self; + type UnixTime = timestamp::Module; + type RewardCurve = RewardCurve; + type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; + type NextNewSession = Session; + type ElectionLookahead = ElectionLookahead; + type Call = Call; + type UnsignedPriority = StakingUnsignedPriority; + type MaxIterations = (); + type MinSolutionScoreBump = (); + type WeightInfo = (); +} + +parameter_types! { + pub OffencesWeightSoftLimit: Weight = Perbill::from_percent(60) * MaximumBlockWeight::get(); +} + +impl offences::Trait for Test { + type Event = TestEvent; + type IdentificationTuple = session::historical::IdentificationTuple; + type OnOffenceHandler = Staking; + type WeightSoftLimit = OffencesWeightSoftLimit; + type WeightInfo = (); +} + +impl Trait for Test { + type Event = TestEvent; + type Call = Call; + + type KeyOwnerProofSystem = Historical; + + type KeyOwnerProof = + >::Proof; + + type KeyOwnerIdentification = >::IdentificationTuple; + + type HandleEquivocation = super::EquivocationHandler< + Self::KeyOwnerIdentification, + reporting_keys::ReporterAppCrypto, + Test, + Offences, + >; +} + +pub mod reporting_keys { + use sp_core::crypto::KeyTypeId; + + pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"test"); + + mod app { + use sp_application_crypto::{app_crypto, ed25519}; + app_crypto!(ed25519, super::KEY_TYPE); + + impl sp_runtime::traits::IdentifyAccount for Public { + type AccountId = u64; + fn into_account(self) -> Self::AccountId { + super::super::Grandpa::grandpa_authorities() + .iter() + .map(|(k, _)| k) + .position(|b| *b == self.0.clone().into()) + .unwrap() as u64 + } + } + } + + pub type ReporterId = app::Public; + + pub struct ReporterAppCrypto; + impl frame_system::offchain::AppCrypto + for ReporterAppCrypto + { + type RuntimeAppPublic = ReporterId; + type GenericSignature = sp_core::ed25519::Signature; + type GenericPublic = sp_core::ed25519::Public; + } +} + +type Extrinsic = TestXt; + +impl system::offchain::CreateSignedTransaction for Test +where + Call: From, +{ + fn create_transaction>( + call: Call, + _public: reporting_keys::ReporterId, + _account: ::AccountId, + nonce: ::Index, + ) -> Option<(Call, ::SignaturePayload)> { + Some((call, (nonce, ()))) + } +} + +impl frame_system::offchain::SigningTypes for Test { + type Public = reporting_keys::ReporterId; + type Signature = sp_core::ed25519::Signature; } mod grandpa { pub use crate::Event; } -impl_outer_event!{ - pub enum TestEvent for Test { - system, - grandpa, - } +pub type Balances = pallet_balances::Module; +pub type Historical = pallet_session::historical::Module; +pub type Offences = pallet_offences::Module; +pub type Session = pallet_session::Module; +pub type Staking = pallet_staking::Module; +pub type System = frame_system::Module; +pub type Timestamp = pallet_timestamp::Module; +pub type Grandpa = Module; + +pub fn grandpa_log(log: ConsensusLog) -> DigestItem { + DigestItem::Consensus(GRANDPA_ENGINE_ID, log.encode()) } pub fn to_authorities(vec: Vec<(u64, u64)>) -> AuthorityList { @@ -87,13 +349,164 @@ pub fn to_authorities(vec: Vec<(u64, u64)>) -> AuthorityList { .collect() } -pub fn new_test_ext(authorities: Vec<(u64, u64)>) -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - GenesisConfig { - authorities: to_authorities(authorities), - }.assimilate_storage::(&mut t).unwrap(); +pub fn extract_keyring(id: &AuthorityId) -> Ed25519Keyring { + let mut raw_public = [0; 32]; + raw_public.copy_from_slice(id.as_ref()); + Ed25519Keyring::from_raw_public(raw_public).unwrap() +} + +pub fn new_test_ext(vec: Vec<(u64, u64)>) -> sp_io::TestExternalities { + new_test_ext_raw_authorities(to_authorities(vec)) +} + +pub fn new_test_ext_raw_authorities(authorities: AuthorityList) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default() + .build_storage::() + .unwrap(); + + // stashes are the index. + let session_keys: Vec<_> = authorities + .iter() + .enumerate() + .map(|(i, (k, _))| { + ( + i as u64, + i as u64, + TestSessionKeys { + grandpa_authority: AuthorityId::from(k.clone()), + }, + ) + }) + .collect(); + + // controllers are the index + 1000 + let stakers: Vec<_> = (0..authorities.len()) + .map(|i| { + ( + i as u64, + i as u64 + 1000, + 10_000, + staking::StakerStatus::::Validator, + ) + }) + .collect(); + + let balances: Vec<_> = (0..authorities.len()) + .map(|i| (i as u64, 10_000_000)) + .collect(); + + // NOTE: this will initialize the grandpa authorities + // through OneSessionHandler::on_genesis_session + session::GenesisConfig:: { keys: session_keys } + .assimilate_storage(&mut t) + .unwrap(); + + balances::GenesisConfig:: { balances } + .assimilate_storage(&mut t) + .unwrap(); + + let staking_config = staking::GenesisConfig:: { + stakers, + validator_count: 8, + force_era: staking::Forcing::ForceNew, + minimum_validator_count: 0, + invulnerables: vec![], + ..Default::default() + }; + + staking_config.assimilate_storage(&mut t).unwrap(); + t.into() } -pub type System = frame_system::Module; -pub type Grandpa = Module; +pub fn start_session(session_index: SessionIndex) { + let mut parent_hash = System::parent_hash(); + + for i in Session::current_index()..session_index { + Staking::on_finalize(System::block_number()); + System::set_block_number((i + 1).into()); + Timestamp::set_timestamp(System::block_number() * 6000); + + // In order to be able to use `System::parent_hash()` in the tests + // we need to first get it via `System::finalize` and then set it + // the `System::initialize`. However, it is needed to be taken into + // consideration that finalizing will prune some data in `System` + // storage including old values `BlockHash` if that reaches above + // `BlockHashCount` capacity. + if System::block_number() > 1 { + let hdr = System::finalize(); + parent_hash = hdr.hash(); + } + + System::initialize( + &(i as u64 + 1), + &parent_hash, + &Default::default(), + &Default::default(), + Default::default(), + ); + + Session::on_initialize(System::block_number()); + System::on_initialize(System::block_number()); + } + + assert_eq!(Session::current_index(), session_index); +} + +pub fn start_era(era_index: EraIndex) { + start_session((era_index * 3).into()); + assert_eq!(Staking::current_era(), Some(era_index)); +} + +pub fn initialize_block(number: u64, parent_hash: H256) { + System::initialize( + &number, + &parent_hash, + &Default::default(), + &Default::default(), + Default::default(), + ); +} + +pub fn report_equivocation( + equivocation_proof: sp_finality_grandpa::EquivocationProof, + key_owner_proof: sp_session::MembershipProof, +) -> Result, TransactionValidityError> { + let inner = GrandpaCall::report_equivocation(equivocation_proof, key_owner_proof); + let call = Call::Grandpa(inner.clone()); + + ValidateEquivocationReport::::new().validate(&0, &call, &DispatchInfo::default(), 0)?; + + Ok(inner) +} + +pub fn generate_equivocation_proof( + set_id: SetId, + vote1: (RoundNumber, H256, u64, &Ed25519Keyring), + vote2: (RoundNumber, H256, u64, &Ed25519Keyring), +) -> sp_finality_grandpa::EquivocationProof { + let signed_prevote = |round, hash, number, keyring: &Ed25519Keyring| { + let prevote = finality_grandpa::Prevote { + target_hash: hash, + target_number: number, + }; + + let prevote_msg = finality_grandpa::Message::Prevote(prevote.clone()); + let payload = sp_finality_grandpa::localized_payload(round, set_id, &prevote_msg); + let signed = keyring.sign(&payload).into(); + (prevote, signed) + }; + + let (prevote1, signed1) = signed_prevote(vote1.0, vote1.1, vote1.2, vote1.3); + let (prevote2, signed2) = signed_prevote(vote2.0, vote2.1, vote2.2, vote2.3); + + sp_finality_grandpa::EquivocationProof::new( + set_id, + sp_finality_grandpa::Equivocation::Prevote(finality_grandpa::Equivocation { + round_number: vote1.0, + identity: vote1.3.public().into(), + first: (prevote1, signed1), + second: (prevote2, signed2), + }), + ) +} diff --git a/frame/grandpa/src/tests.rs b/frame/grandpa/src/tests.rs index b583c31968d896e36e11811ff0193bea7a629ff9..5f901f227668f91d5d3b1330cc0a941fb9c68636 100644 --- a/frame/grandpa/src/tests.rs +++ b/frame/grandpa/src/tests.rs @@ -1,40 +1,36 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for the module. #![cfg(test)] -use sp_runtime::{testing::{H256, Digest}, traits::Header}; -use frame_support::traits::OnFinalize; +use super::*; use crate::mock::*; -use frame_system::{EventRecord, Phase}; use codec::{Decode, Encode}; use fg_primitives::ScheduledChange; -use super::*; - -fn initialize_block(number: u64, parent_hash: H256) { - System::initialize( - &number, - &parent_hash, - &Default::default(), - &Default::default(), - Default::default(), - ); -} +use frame_support::{ + assert_err, assert_ok, + traits::{Currency, OnFinalize, UnfilteredDispatchable}, +}; +use frame_system::{EventRecord, Phase}; +use sp_core::H256; +use sp_keyring::Ed25519Keyring; +use sp_runtime::testing::Digest; #[test] fn authorities_change_logged() { @@ -319,3 +315,348 @@ fn time_slot_have_sane_ord() { ]; assert!(FIXTURE.windows(2).all(|f| f[0] < f[1])); } + +fn test_authorities() -> AuthorityList { + let authorities = vec![ + Ed25519Keyring::Alice, + Ed25519Keyring::Bob, + Ed25519Keyring::Charlie, + ]; + + authorities + .into_iter() + .map(|id| (id.public().into(), 1u64)) + .collect() +} + +#[test] +fn report_equivocation_current_set_works() { + let authorities = test_authorities(); + + new_test_ext_raw_authorities(authorities).execute_with(|| { + assert_eq!(Staking::current_era(), Some(0)); + assert_eq!(Session::current_index(), 0); + + start_era(1); + + let authorities = Grandpa::grandpa_authorities(); + + // make sure that all authorities have the same balance + for i in 0..authorities.len() { + assert_eq!(Balances::total_balance(&(i as u64)), 10_000_000); + assert_eq!(Staking::slashable_balance_of(&(i as u64)), 10_000); + + assert_eq!( + Staking::eras_stakers(1, i as u64), + pallet_staking::Exposure { + total: 10_000, + own: 10_000, + others: vec![], + }, + ); + } + + let equivocation_authority_index = 0; + let equivocation_key = &authorities[equivocation_authority_index].0; + let equivocation_keyring = extract_keyring(equivocation_key); + + let set_id = Grandpa::current_set_id(); + + // generate an equivocation proof, with two votes in the same round for + // different block hashes signed by the same key + let equivocation_proof = generate_equivocation_proof( + set_id, + (1, H256::random(), 10, &equivocation_keyring), + (1, H256::random(), 10, &equivocation_keyring), + ); + + // create the key ownership proof + let key_owner_proof = + Historical::prove((sp_finality_grandpa::KEY_TYPE, &equivocation_key)).unwrap(); + + // report the equivocation and the tx should be dispatched successfully + let inner = report_equivocation(equivocation_proof, key_owner_proof).unwrap(); + assert_ok!(inner.dispatch_bypass_filter(Origin::signed(1))); + + start_era(2); + + // check that the balance of 0-th validator is slashed 100%. + assert_eq!(Balances::total_balance(&0), 10_000_000 - 10_000); + assert_eq!(Staking::slashable_balance_of(&0), 0); + + assert_eq!( + Staking::eras_stakers(2, 0), + pallet_staking::Exposure { + total: 0, + own: 0, + others: vec![], + }, + ); + + // check that the balances of all other validators are left intact. + for i in 1..authorities.len() { + assert_eq!(Balances::total_balance(&(i as u64)), 10_000_000); + assert_eq!(Staking::slashable_balance_of(&(i as u64)), 10_000); + + assert_eq!( + Staking::eras_stakers(2, i as u64), + pallet_staking::Exposure { + total: 10_000, + own: 10_000, + others: vec![], + }, + ); + } + }); +} + +#[test] +fn report_equivocation_old_set_works() { + let authorities = test_authorities(); + + new_test_ext_raw_authorities(authorities).execute_with(|| { + start_era(1); + + let authorities = Grandpa::grandpa_authorities(); + + let equivocation_authority_index = 0; + let equivocation_key = &authorities[equivocation_authority_index].0; + + // create the key ownership proof in the "old" set + let key_owner_proof = + Historical::prove((sp_finality_grandpa::KEY_TYPE, &equivocation_key)).unwrap(); + + start_era(2); + + // make sure that all authorities have the same balance + for i in 0..authorities.len() { + assert_eq!(Balances::total_balance(&(i as u64)), 10_000_000); + assert_eq!(Staking::slashable_balance_of(&(i as u64)), 10_000); + + assert_eq!( + Staking::eras_stakers(2, i as u64), + pallet_staking::Exposure { + total: 10_000, + own: 10_000, + others: vec![], + }, + ); + } + + let equivocation_keyring = extract_keyring(equivocation_key); + + let set_id = Grandpa::current_set_id(); + + // generate an equivocation proof for the old set, + let equivocation_proof = generate_equivocation_proof( + set_id - 1, + (1, H256::random(), 10, &equivocation_keyring), + (1, H256::random(), 10, &equivocation_keyring), + ); + + // report the equivocation using the key ownership proof generated on + // the old set, the tx should be dispatched successfully + let inner = report_equivocation(equivocation_proof, key_owner_proof).unwrap(); + assert_ok!(inner.dispatch_bypass_filter(Origin::signed(1))); + + start_era(3); + + // check that the balance of 0-th validator is slashed 100%. + assert_eq!(Balances::total_balance(&0), 10_000_000 - 10_000); + assert_eq!(Staking::slashable_balance_of(&0), 0); + + assert_eq!( + Staking::eras_stakers(3, 0), + pallet_staking::Exposure { + total: 0, + own: 0, + others: vec![], + }, + ); + + // check that the balances of all other validators are left intact. + for i in 1..authorities.len() { + assert_eq!(Balances::total_balance(&(i as u64)), 10_000_000); + assert_eq!(Staking::slashable_balance_of(&(i as u64)), 10_000); + + assert_eq!( + Staking::eras_stakers(3, i as u64), + pallet_staking::Exposure { + total: 10_000, + own: 10_000, + others: vec![], + }, + ); + } + }); +} + +#[test] +fn report_equivocation_invalid_set_id() { + let authorities = test_authorities(); + + new_test_ext_raw_authorities(authorities).execute_with(|| { + start_era(1); + + let authorities = Grandpa::grandpa_authorities(); + + let equivocation_authority_index = 0; + let equivocation_key = &authorities[equivocation_authority_index].0; + let equivocation_keyring = extract_keyring(equivocation_key); + + let key_owner_proof = + Historical::prove((sp_finality_grandpa::KEY_TYPE, &equivocation_key)).unwrap(); + + let set_id = Grandpa::current_set_id(); + + // generate an equivocation for a future set + let equivocation_proof = generate_equivocation_proof( + set_id + 1, + (1, H256::random(), 10, &equivocation_keyring), + (1, H256::random(), 10, &equivocation_keyring), + ); + + // it should be filtered by the signed extension validation + assert_err!( + report_equivocation(equivocation_proof, key_owner_proof), + equivocation::ReportEquivocationValidityError::InvalidSetId, + ); + }); +} + +#[test] +fn report_equivocation_invalid_session() { + let authorities = test_authorities(); + + new_test_ext_raw_authorities(authorities).execute_with(|| { + start_era(1); + + let authorities = Grandpa::grandpa_authorities(); + + let equivocation_authority_index = 0; + let equivocation_key = &authorities[equivocation_authority_index].0; + let equivocation_keyring = extract_keyring(equivocation_key); + + // generate a key ownership proof at set id = 1 + let key_owner_proof = + Historical::prove((sp_finality_grandpa::KEY_TYPE, &equivocation_key)).unwrap(); + + start_era(2); + + let set_id = Grandpa::current_set_id(); + + // generate an equivocation proof at set id = 2 + let equivocation_proof = generate_equivocation_proof( + set_id, + (1, H256::random(), 10, &equivocation_keyring), + (1, H256::random(), 10, &equivocation_keyring), + ); + + // report an equivocation for the current set using an key ownership + // proof from the previous set, the session should be invalid. + assert_err!( + report_equivocation(equivocation_proof, key_owner_proof), + equivocation::ReportEquivocationValidityError::InvalidSession, + ); + }); +} + +#[test] +fn report_equivocation_invalid_key_owner_proof() { + let authorities = test_authorities(); + + new_test_ext_raw_authorities(authorities).execute_with(|| { + start_era(1); + let authorities = Grandpa::grandpa_authorities(); + + let invalid_owner_authority_index = 1; + let invalid_owner_key = &authorities[invalid_owner_authority_index].0; + + // generate a key ownership proof for the authority at index 1 + let invalid_key_owner_proof = + Historical::prove((sp_finality_grandpa::KEY_TYPE, &invalid_owner_key)).unwrap(); + + let equivocation_authority_index = 0; + let equivocation_key = &authorities[equivocation_authority_index].0; + let equivocation_keyring = extract_keyring(equivocation_key); + + let set_id = Grandpa::current_set_id(); + + // generate an equivocation proof for the authority at index 0 + let equivocation_proof = generate_equivocation_proof( + set_id, + (1, H256::random(), 10, &equivocation_keyring), + (1, H256::random(), 10, &equivocation_keyring), + ); + + // we need to start a new era otherwise the key ownership proof won't be + // checked since the authorities are part of the current session + start_era(2); + + // report an equivocation for the current set using a key ownership + // proof for a different key than the one in the equivocation proof. + assert_err!( + report_equivocation(equivocation_proof, invalid_key_owner_proof), + equivocation::ReportEquivocationValidityError::InvalidKeyOwnershipProof, + ); + }); +} + +#[test] +fn report_equivocation_invalid_equivocation_proof() { + let authorities = test_authorities(); + + new_test_ext_raw_authorities(authorities).execute_with(|| { + start_era(1); + + let authorities = Grandpa::grandpa_authorities(); + + let equivocation_authority_index = 0; + let equivocation_key = &authorities[equivocation_authority_index].0; + let equivocation_keyring = extract_keyring(equivocation_key); + + // generate a key ownership proof at set id = 1 + let key_owner_proof = + Historical::prove((sp_finality_grandpa::KEY_TYPE, &equivocation_key)).unwrap(); + + let set_id = Grandpa::current_set_id(); + + let assert_invalid_equivocation_proof = |equivocation_proof| { + assert_err!( + report_equivocation(equivocation_proof, key_owner_proof.clone()), + equivocation::ReportEquivocationValidityError::InvalidEquivocationProof, + ); + }; + + start_era(2); + + // both votes target the same block number and hash, + // there is no equivocation. + assert_invalid_equivocation_proof(generate_equivocation_proof( + set_id, + (1, H256::zero(), 10, &equivocation_keyring), + (1, H256::zero(), 10, &equivocation_keyring), + )); + + // votes targetting different rounds, there is no equivocation. + assert_invalid_equivocation_proof(generate_equivocation_proof( + set_id, + (1, H256::random(), 10, &equivocation_keyring), + (2, H256::random(), 10, &equivocation_keyring), + )); + + // votes signed with different authority keys + assert_invalid_equivocation_proof(generate_equivocation_proof( + set_id, + (1, H256::random(), 10, &equivocation_keyring), + (1, H256::random(), 10, &Ed25519Keyring::Charlie), + )); + + // votes signed with a key that isn't part of the authority set + assert_invalid_equivocation_proof(generate_equivocation_proof( + set_id, + (1, H256::random(), 10, &equivocation_keyring), + (1, H256::random(), 10, &Ed25519Keyring::Dave), + )); + }); +} diff --git a/frame/identity/Cargo.toml b/frame/identity/Cargo.toml index 22b385d06d76f36677a50b2afcbe51ad564e970f..8dcfd5bd2d11927d2a4d2329281b01367a246d51 100644 --- a/frame/identity/Cargo.toml +++ b/frame/identity/Cargo.toml @@ -1,27 +1,30 @@ [package] name = "pallet-identity" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME identity management pallet" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } enumflags2 = { version = "0.6.2" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -frame-benchmarking = { version = "2.0.0-alpha.5", default-features = false, path = "../benchmarking", optional = true } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +frame-benchmarking = { version = "2.0.0-rc4", default-features = false, path = "../benchmarking", optional = true } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -pallet-balances = { version = "2.0.0-alpha.5", path = "../balances" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0-rc4", path = "../balances" } [features] default = ["std"] @@ -36,6 +39,3 @@ std = [ "frame-system/std", ] runtime-benchmarks = ["frame-benchmarking"] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index b5236e62191ae08bb8a301ce1f9dd85649edfbe3..042f7aa9c79b5453261376965c6cc4508daa9fcb 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Identity pallet benchmarking. @@ -27,9 +28,6 @@ use sp_runtime::traits::Bounded; use crate::Module as Identity; -// The maximum number of identity registrars we will test. -const MAX_REGISTRARS: u32 = 50; - // Support Functions fn account(name: &'static str, index: u32) -> T::AccountId { let entropy = (name, index).using_encoded(blake2_256); @@ -53,9 +51,9 @@ fn add_registrars(r: u32) -> Result<(), &'static str> { Ok(()) } -// Adds `s` sub-accounts to the identity of `who`. Each wil have 32 bytes of raw data added to it. -// This additionally returns the vector of sub-accounts to it can be modified if needed. -fn add_sub_accounts(who: &T::AccountId, s: u32) -> Result, &'static str> { +// Create `s` sub-accounts for the identity of `who` and return them. +// Each will have 32 bytes of raw data added to it. +fn create_sub_accounts(who: &T::AccountId, s: u32) -> Result, &'static str> { let mut subs = Vec::new(); let who_origin = RawOrigin::Signed(who.clone()); let data = Data::Raw(vec![0; 32]); @@ -70,9 +68,18 @@ fn add_sub_accounts(who: &T::AccountId, s: u32) -> Result(1); Identity::::set_identity(who_origin.clone().into(), info)?; + Ok(subs) +} + +// Adds `s` sub-accounts to the identity of `who`. Each will have 32 bytes of raw data added to it. +// This additionally returns the vector of sub-accounts so it can be modified if needed. +fn add_sub_accounts(who: &T::AccountId, s: u32) -> Result, &'static str> { + let who_origin = RawOrigin::Signed(who.clone()); + let subs = create_sub_accounts::(who, s)?; + Identity::::set_subs(who_origin.into(), subs.clone())?; - return Ok(subs) + Ok(subs) } // This creates an `IdentityInfo` object with `num_fields` extra fields. @@ -98,7 +105,9 @@ fn create_identity_info(num_fields: u32) -> IdentityInfo { benchmarks! { // These are the common parameters along with their instancing. _ { - let r in 1 .. MAX_REGISTRARS => add_registrars::(r)?; + let r in 1 .. T::MaxRegistrars::get() => add_registrars::(r)?; + // extra parameter for the set_subs bench for previous sub accounts + let p in 1 .. T::MaxSubAccounts::get() => (); let s in 1 .. T::MaxSubAccounts::get() => { // Give them s many sub accounts let caller = account::("caller", 0); @@ -114,7 +123,7 @@ benchmarks! { } add_registrar { - let r in ...; + let r in 1 .. T::MaxRegistrars::get() - 1 => add_registrars::(r)?; }: _(RawOrigin::Root, account::("registrar", r + 1)) set_identity { @@ -153,16 +162,13 @@ benchmarks! { set_subs { let caller = account::("caller", 0); - // Give them s many sub accounts. - let s in 1 .. T::MaxSubAccounts::get() - 1 => { - let _ = add_sub_accounts::(&caller, s)?; + // Give them p many previous sub accounts. + let p in 1 .. T::MaxSubAccounts::get() => { + let _ = add_sub_accounts::(&caller, p)?; }; - - let mut subs = Module::::subs(&caller); - - // Create an s + 1 sub account. - let data = Data::Raw(vec![0; 32]); - subs.push((account::("sub", s + 1), data)); + // Create a new subs vec with s sub accounts + let s in 1 .. T::MaxSubAccounts::get() => (); + let subs = create_sub_accounts::(&caller, s)?; }: _(RawOrigin::Signed(caller), subs) @@ -210,7 +216,7 @@ benchmarks! { set_fee { let caller = account::("caller", 0); - let r in ...; + let r in 1 .. T::MaxRegistrars::get() - 1 => add_registrars::(r)?; Identity::::add_registrar(RawOrigin::Root.into(), caller.clone())?; }: _(RawOrigin::Signed(caller), r, 10.into()) @@ -219,7 +225,7 @@ benchmarks! { let caller = account::("caller", 0); let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); - let r in ...; + let r in 1 .. T::MaxRegistrars::get() - 1 => add_registrars::(r)?; Identity::::add_registrar(RawOrigin::Root.into(), caller.clone())?; }: _(RawOrigin::Signed(caller), r, account::("new", 0)) @@ -228,7 +234,7 @@ benchmarks! { let caller = account::("caller", 0); let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); - let r in ...; + let r in 1 .. T::MaxRegistrars::get() - 1 => add_registrars::(r)?; Identity::::add_registrar(RawOrigin::Root.into(), caller.clone())?; let fields = IdentityFields( @@ -247,7 +253,7 @@ benchmarks! { let caller = account::("caller", 0); let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); - let r in ...; + let r in 1 .. T::MaxRegistrars::get() - 1 => add_registrars::(r)?; // For this x, it's the user identity that gts the fields, not the caller. let x in _ .. _ => { let info = create_identity_info::(x); @@ -280,3 +286,27 @@ benchmarks! { } }: _(RawOrigin::Root, caller_lookup) } + +#[cfg(test)] +mod tests { + use super::*; + use crate::tests::{new_test_ext, Test}; + use frame_support::assert_ok; + + #[test] + fn test_benchmarks() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_add_registrar::()); + assert_ok!(test_benchmark_set_identity::()); + assert_ok!(test_benchmark_set_subs::()); + assert_ok!(test_benchmark_clear_identity::()); + assert_ok!(test_benchmark_request_judgement::()); + assert_ok!(test_benchmark_cancel_request::()); + assert_ok!(test_benchmark_set_fee::()); + assert_ok!(test_benchmark_set_account_id::()); + assert_ok!(test_benchmark_set_fields::()); + assert_ok!(test_benchmark_provide_judgement::()); + assert_ok!(test_benchmark_kill_identity::()); + }); + } +} diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index e18689001bec65145043179ea3673c2ce65b1a33..765d837a8a17d868a7fa6be20a66a702448130eb 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Identity Module //! @@ -69,20 +70,49 @@ use sp_std::prelude::*; use sp_std::{fmt::Debug, ops::Add, iter::once}; use enumflags2::BitFlags; use codec::{Encode, Decode}; -use sp_runtime::{DispatchResult, RuntimeDebug}; +use sp_runtime::{DispatchError, RuntimeDebug}; use sp_runtime::traits::{StaticLookup, Zero, AppendZerosInput}; use frame_support::{ decl_module, decl_event, decl_storage, ensure, decl_error, + dispatch::DispatchResultWithPostInfo, traits::{Currency, ReservableCurrency, OnUnbalanced, Get, BalanceStatus, EnsureOrigin}, - weights::SimpleDispatchInfo, + weights::Weight, }; -use frame_system::{self as system, ensure_signed, ensure_root}; +use frame_system::ensure_signed; mod benchmarking; type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; +pub trait WeightInfo { + fn add_registrar(r: u32, ) -> Weight; + fn set_identity(r: u32, x: u32, ) -> Weight; + fn set_subs(p: u32, s: u32, ) -> Weight; + fn clear_identity(r: u32, s: u32, x: u32, ) -> Weight; + fn request_judgement(r: u32, x: u32, ) -> Weight; + fn cancel_request(r: u32, x: u32, ) -> Weight; + fn set_fee(r: u32, ) -> Weight; + fn set_account_id(r: u32, ) -> Weight; + fn set_fields(r: u32, ) -> Weight; + fn provide_judgement(r: u32, x: u32, ) -> Weight; + fn kill_identity(r: u32, s: u32, x: u32, ) -> Weight; +} + +impl WeightInfo for () { + fn add_registrar(_r: u32, ) -> Weight { 1_000_000_000 } + fn set_identity(_r: u32, _x: u32, ) -> Weight { 1_000_000_000 } + fn set_subs(_p: u32, _s: u32, ) -> Weight { 1_000_000_000 } + fn clear_identity(_r: u32, _s: u32, _x: u32, ) -> Weight { 1_000_000_000 } + fn request_judgement(_r: u32, _x: u32, ) -> Weight { 1_000_000_000 } + fn cancel_request(_r: u32, _x: u32, ) -> Weight { 1_000_000_000 } + fn set_fee(_r: u32, ) -> Weight { 1_000_000_000 } + fn set_account_id(_r: u32, ) -> Weight { 1_000_000_000 } + fn set_fields(_r: u32, ) -> Weight { 1_000_000_000 } + fn provide_judgement(_r: u32, _x: u32, ) -> Weight { 1_000_000_000 } + fn kill_identity(_r: u32, _s: u32, _x: u32, ) -> Weight { 1_000_000_000 } +} + pub trait Trait: frame_system::Trait { /// The overarching event type. type Event: From> + Into<::Event>; @@ -108,6 +138,10 @@ pub trait Trait: frame_system::Trait { /// required to access an identity, but can be pretty high. type MaxAdditionalFields: Get; + /// Maxmimum number of registrars allowed in the system. Needed to bound the complexity + /// of, e.g., updating judgements. + type MaxRegistrars: Get; + /// What to do with slashed funds. type Slashed: OnUnbalanced>; @@ -116,6 +150,9 @@ pub trait Trait: frame_system::Trait { /// The origin which may add or remove registrars. Root can always do this. type RegistrarOrigin: EnsureOrigin; + + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; } /// Either underlying data blob if it is at most 32 bytes, or a hash of it. If the data is greater @@ -383,6 +420,8 @@ pub struct RegistrarInfo< decl_storage! { trait Store for Module as Identity { /// Information that is pertinent to identify the entity behind an account. + /// + /// TWOX-NOTE: OK ― `AccountId` is a secure hash. pub IdentityOf get(fn identity): map hasher(twox_64_concat) T::AccountId => Option>>; @@ -394,6 +433,8 @@ decl_storage! { /// Alternative "sub" identities of this account. /// /// The first item is the deposit, the second is a vector of the accounts. + /// + /// TWOX-NOTE: OK ― `AccountId` is a secure hash. pub SubsOf get(fn subs_of): map hasher(twox_64_concat) T::AccountId => (BalanceOf, Vec); @@ -451,41 +492,195 @@ decl_error! { InvalidTarget, /// Too many additional fields. TooManyFields, + /// Maximum amount of registrars reached. Cannot add any more. + TooManyRegistrars, +} } + +/// Functions for calcuating the weight of dispatchables. +mod weight_for { + use frame_support::{traits::Get, weights::Weight}; + use super::Trait; + + /// Weight calculation for `add_registrar`. + /// + /// Based on benchmark: + /// 22.24 + R * 0.371 µs (min squares analysis) + pub(crate) fn add_registrar( + registrars: Weight + ) -> Weight { + T::DbWeight::get().reads_writes(1, 1) + + 23_000_000 // constant + + 380_000 * registrars // R + } + + /// Weight calculation for `set_identity`. + /// + /// Based on benchmark: + /// 50.64 + R * 0.215 + X * 1.424 µs (min squares analysis) + pub(crate) fn set_identity( + judgements: Weight, + extra_fields: Weight + ) -> Weight { + T::DbWeight::get().reads_writes(1, 1) + + 51_000_000 // constant + + 220_000 * judgements // R + + 1_500_000 * extra_fields // X + } + + /// Weight calculation for `set_subs`. + /// + /// Based on benchmark: + /// 36.21 + P * 2.481 + S * 3.633 µs (min squares analysis) + pub(crate) fn set_subs( + old_subs: Weight, + subs: Weight + ) -> Weight { + let db = T::DbWeight::get(); + db.reads(1) // storage-exists (`IdentityOf::contains_key`) + .saturating_add(db.reads_writes(1, old_subs)) // `SubsOf::get` read + P old DB deletions + .saturating_add(db.writes(subs + 1)) // S + 1 new DB writes + .saturating_add(37_000_000) // constant + .saturating_add(2_500_000 * old_subs) // P + .saturating_add(subs.saturating_mul(3_700_000)) // S + } + + /// Weight calculation for `clear_identity`. + /// + /// Based on benchmark: + /// 43.19 + R * 0.099 + S * 2.547 + X * 0.875 µs (min squares analysis) + pub(crate) fn clear_identity( + judgements: Weight, + subs: Weight, + extra_fields: Weight + ) -> Weight { + T::DbWeight::get().reads_writes(2, subs + 2) // S + 2 deletions + + 44_000_000 // constant + + 100_000 * judgements // R + + 2_600_000 * subs // S + + 900_000 * extra_fields // X + } + + /// Weight calculation for `request_judgement`. + /// + /// Based on benchmark: + /// 51.51 + R * 0.32 + X * 1.85 µs (min squares analysis) + pub(crate) fn request_judgement( + judgements: Weight, + extra_fields: Weight + ) -> Weight { + T::DbWeight::get().reads_writes(2, 1) + + 52_000_000 // constant + + 400_000 * judgements // R + + 1_900_000 * extra_fields // X + } + + /// Weight calculation for `cancel_request`. + /// + /// Based on benchmark: + /// 40.95 + R * 0.219 + X * 1.655 µs (min squares analysis) + pub(crate) fn cancel_request( + judgements: Weight, + extra_fields: Weight + ) -> Weight { + T::DbWeight::get().reads_writes(1, 1) + + 41_000_000 // constant + + 300_000 * judgements // R + + 1_700_000 * extra_fields // X + } + + /// Weight calculation for `provide_judgement`. + /// + /// Based on benchmark: + /// 40.77 + R * 0.282 + X * 1.66 µs (min squares analysis) + pub(crate) fn provide_judgement( + judgements: Weight, + extra_fields: Weight + ) -> Weight { + T::DbWeight::get().reads_writes(2, 1) + + 41_000_000 // constant + + 300_000 * judgements // R + + 1_700_000 * extra_fields// X + } + + /// Weight calculation for `kill_identity`. + /// + /// Based on benchmark: + /// 83.96 + R * 0.122 + S * 2.533 + X * 0.867 µs (min squares analysis) + pub(crate) fn kill_identity( + judgements: Weight, + subs: Weight, + extra_fields: Weight + ) -> Weight { + let db = T::DbWeight::get(); + db.reads_writes(2, subs + 2) // 2 `take`s + S deletions + + db.reads_writes(1, 1) // balance ops + + 84_000_000 // constant + + 130_000 * judgements // R + + 2_600_000 * subs // S + + 900_000 * extra_fields // X + } } decl_module! { - // Simple declaration of the `Module` type. Lets the macro know what it's working on. + /// Identity module declaration. pub struct Module for enum Call where origin: T::Origin { + /// The amount held on deposit for a registered identity. + const BasicDeposit: BalanceOf = T::BasicDeposit::get(); + + /// The amount held on deposit per additional field for a registered identity. + const FieldDeposit: BalanceOf = T::FieldDeposit::get(); + + /// The amount held on deposit for a registered subaccount. This should account for the fact + /// that one storage item's value will increase by the size of an account ID, and there will be + /// another trie item whose value is the size of an account ID plus 32 bytes. + const SubAccountDeposit: BalanceOf = T::SubAccountDeposit::get(); + + /// The maximum number of sub-accounts allowed per identified account. + const MaxSubAccounts: u32 = T::MaxSubAccounts::get(); + + /// Maximum number of additional fields that may be stored in an ID. Needed to bound the I/O + /// required to access an identity, but can be pretty high. + const MaxAdditionalFields: u32 = T::MaxAdditionalFields::get(); + + /// Maxmimum number of registrars allowed in the system. Needed to bound the complexity + /// of, e.g., updating judgements. + const MaxRegistrars: u32 = T::MaxRegistrars::get(); + type Error = Error; fn deposit_event() = default; /// Add a registrar to the system. /// - /// The dispatch origin for this call must be `RegistrarOrigin` or `Root`. + /// The dispatch origin for this call must be `T::RegistrarOrigin`. /// /// - `account`: the account of the registrar. /// /// Emits `RegistrarAdded` if successful. /// /// # - /// - `O(R)` where `R` registrar-count (governance-bounded). + /// - `O(R)` where `R` registrar-count (governance-bounded and code-bounded). /// - One storage mutation (codec `O(R)`). /// - One event. /// # - #[weight = SimpleDispatchInfo::FixedNormal(10_000)] - fn add_registrar(origin, account: T::AccountId) { - T::RegistrarOrigin::try_origin(origin) - .map(|_| ()) - .or_else(ensure_root)?; - - let i = >::mutate(|r| { - r.push(Some(RegistrarInfo { account, fee: Zero::zero(), fields: Default::default() })); - (r.len() - 1) as RegistrarIndex - }); + #[weight = weight_for::add_registrar::(T::MaxRegistrars::get().into()) ] + fn add_registrar(origin, account: T::AccountId) -> DispatchResultWithPostInfo { + T::RegistrarOrigin::ensure_origin(origin)?; + + let (i, registrar_count) = >::try_mutate( + |registrars| -> Result<(RegistrarIndex, usize), DispatchError> { + ensure!(registrars.len() < T::MaxRegistrars::get() as usize, Error::::TooManyRegistrars); + registrars.push(Some(RegistrarInfo { + account, fee: Zero::zero(), fields: Default::default() + })); + Ok(((registrars.len() - 1) as RegistrarIndex, registrars.len())) + } + )?; Self::deposit_event(RawEvent::RegistrarAdded(i)); + + Ok(Some(weight_for::add_registrar::(registrar_count as Weight)).into()) } /// Set an account's identity information and reserve the appropriate deposit. @@ -493,21 +688,25 @@ decl_module! { /// If the account already has identity information, the deposit is taken as part payment /// for the new deposit. /// - /// The dispatch origin for this call must be _Signed_ and the sender must have a registered - /// identity. + /// The dispatch origin for this call must be _Signed_. /// /// - `info`: The identity information. /// /// Emits `IdentitySet` if successful. /// /// # - /// - `O(X + X' + R)` where `X` additional-field-count (deposit-bounded and code-bounded). - /// - At most two balance operations. + /// - `O(X + X' + R)` + /// - where `X` additional-field-count (deposit-bounded and code-bounded) + /// - where `R` judgements-count (registrar-count-bounded) + /// - One balance reserve operation. /// - One storage mutation (codec-read `O(X' + R)`, codec-write `O(X + R)`). /// - One event. /// # - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] - fn set_identity(origin, info: IdentityInfo) { + #[weight = weight_for::set_identity::( + T::MaxRegistrars::get().into(), // R + T::MaxAdditionalFields::get().into(), // X + )] + fn set_identity(origin, info: IdentityInfo) -> DispatchResultWithPostInfo { let sender = ensure_signed(origin)?; let extra_fields = info.additional.len() as u32; ensure!(extra_fields <= T::MaxAdditionalFields::get(), Error::::TooManyFields); @@ -532,8 +731,14 @@ decl_module! { let _ = T::Currency::unreserve(&sender, old_deposit - id.deposit); } + let judgements = id.judgements.len() as Weight; >::insert(&sender, id); Self::deposit_event(RawEvent::IdentitySet(sender)); + + Ok(Some(weight_for::set_identity::( + judgements, // R + extra_fields as Weight // X + )).into()) } /// Set the sub-accounts of the sender. @@ -544,16 +749,24 @@ decl_module! { /// The dispatch origin for this call must be _Signed_ and the sender must have a registered /// identity. /// - /// - `subs`: The identity's sub-accounts. + /// - `subs`: The identity's (new) sub-accounts. /// /// # - /// - `O(S)` where `S` subs-count (hard- and deposit-bounded). - /// - At most two balance operations. - /// - At most O(2 * S + 1) storage mutations; codec complexity `O(1 * S + S * 1)`); - /// one storage-exists. + /// - `O(P + S)` + /// - where `P` old-subs-count (hard- and deposit-bounded). + /// - where `S` subs-count (hard- and deposit-bounded). + /// - At most one balance operations. + /// - DB: + /// - `P + S` storage mutations (codec complexity `O(1)`) + /// - One storage read (codec complexity `O(P)`). + /// - One storage write (codec complexity `O(S)`). + /// - One storage-exists (`IdentityOf::contains_key`). /// # - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] - fn set_subs(origin, subs: Vec<(T::AccountId, Data)>) { + #[weight = weight_for::set_subs::( + T::MaxSubAccounts::get().into(), // P + subs.len() as Weight // S + )] + fn set_subs(origin, subs: Vec<(T::AccountId, Data)>) -> DispatchResultWithPostInfo { let sender = ensure_signed(origin)?; ensure!(>::contains_key(&sender), Error::::NotFound); ensure!(subs.len() <= T::MaxSubAccounts::get() as usize, Error::::TooManySubAccounts); @@ -576,15 +789,21 @@ decl_module! { >::insert(&id, (sender.clone(), name)); id }).collect::>(); + let new_subs = ids.len() as Weight; if ids.is_empty() { >::remove(&sender); } else { >::insert(&sender, (new_deposit, ids)); } + + Ok(Some(weight_for::set_subs::( + old_ids.len() as Weight, // P + new_subs // S + )).into()) } - /// Clear an account's identity info and all sub-account and return all deposits. + /// Clear an account's identity info and all sub-accounts and return all deposits. /// /// Payment: All reserved balances on the account are returned. /// @@ -594,17 +813,25 @@ decl_module! { /// Emits `IdentityCleared` if successful. /// /// # - /// - `O(R + S + X)`. - /// - One balance-reserve operation. - /// - `S + 2` storage deletions. + /// - `O(R + S + X)` + /// - where `R` registrar-count (governance-bounded). + /// - where `S` subs-count (hard- and deposit-bounded). + /// - where `X` additional-field-count (deposit-bounded and code-bounded). + /// - One balance-unreserve operation. + /// - `2` storage reads and `S + 2` storage deletions. /// - One event. /// # - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] - fn clear_identity(origin) { + #[weight = weight_for::clear_identity::( + T::MaxRegistrars::get().into(), // R + T::MaxSubAccounts::get().into(), // S + T::MaxAdditionalFields::get().into(), // X + )] + fn clear_identity(origin) -> DispatchResultWithPostInfo { let sender = ensure_signed(origin)?; let (subs_deposit, sub_ids) = >::take(&sender); - let deposit = >::take(&sender).ok_or(Error::::NotNamed)?.total_deposit() + let id = >::take(&sender).ok_or(Error::::NotNamed)?; + let deposit = id.total_deposit() + subs_deposit; for sub in sub_ids.iter() { >::remove(sub); @@ -613,6 +840,12 @@ decl_module! { let _ = T::Currency::unreserve(&sender, deposit.clone()); Self::deposit_event(RawEvent::IdentityCleared(sender, deposit)); + + Ok(Some(weight_for::clear_identity::( + id.judgements.len() as Weight, // R + sub_ids.len() as Weight, // S + id.info.additional.len() as Weight // X + )).into()) } /// Request a judgement from a registrar. @@ -627,7 +860,7 @@ decl_module! { /// - `max_fee`: The maximum fee that may be paid. This should just be auto-populated as: /// /// ```nocompile - /// Self::registrars(reg_index).unwrap().fee + /// Self::registrars().get(reg_index).unwrap().fee /// ``` /// /// Emits `JudgementRequested` if successful. @@ -638,11 +871,14 @@ decl_module! { /// - Storage: 1 read `O(R)`, 1 mutate `O(X + R)`. /// - One event. /// # - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + #[weight = weight_for::request_judgement::( + T::MaxRegistrars::get().into(), // R + T::MaxAdditionalFields::get().into(), // X + )] fn request_judgement(origin, #[compact] reg_index: RegistrarIndex, #[compact] max_fee: BalanceOf, - ) { + ) -> DispatchResultWithPostInfo { let sender = ensure_signed(origin)?; let registrars = >::get(); let registrar = registrars.get(reg_index as usize).and_then(Option::as_ref) @@ -662,9 +898,13 @@ decl_module! { T::Currency::reserve(&sender, registrar.fee)?; + let judgements = id.judgements.len() as Weight; + let extra_fields = id.info.additional.len() as Weight; >::insert(&sender, id); Self::deposit_event(RawEvent::JudgementRequested(sender, reg_index)); + + Ok(Some(weight_for::request_judgement::(judgements, extra_fields)).into()) } /// Cancel a previous request. @@ -682,10 +922,13 @@ decl_module! { /// - `O(R + X)`. /// - One balance-reserve operation. /// - One storage mutation `O(R + X)`. - /// - One event. + /// - One event /// # - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] - fn cancel_request(origin, reg_index: RegistrarIndex) { + #[weight = weight_for::cancel_request::( + T::MaxRegistrars::get().into(), // R + T::MaxAdditionalFields::get().into(), // X + )] + fn cancel_request(origin, reg_index: RegistrarIndex) -> DispatchResultWithPostInfo { let sender = ensure_signed(origin)?; let mut id = >::get(&sender).ok_or(Error::::NoIdentity)?; @@ -698,9 +941,13 @@ decl_module! { }; let _ = T::Currency::unreserve(&sender, fee); + let judgements = id.judgements.len() as Weight; + let extra_fields = id.info.additional.len() as Weight; >::insert(&sender, id); Self::deposit_event(RawEvent::JudgementUnrequested(sender, reg_index)); + + Ok(Some(weight_for::request_judgement::(judgements, extra_fields)).into()) } /// Set the fee required for a judgement to be requested from a registrar. @@ -714,20 +961,28 @@ decl_module! { /// # /// - `O(R)`. /// - One storage mutation `O(R)`. + /// - Benchmark: 7.315 + R * 0.329 µs (min squares analysis) /// # - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + #[weight = T::DbWeight::get().reads_writes(1, 1) + + 7_400_000 // constant + + 330_000 * T::MaxRegistrars::get() as Weight // R + ] fn set_fee(origin, #[compact] index: RegistrarIndex, #[compact] fee: BalanceOf, - ) -> DispatchResult { + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; - >::mutate(|rs| + let registrars = >::mutate(|rs| -> Result { rs.get_mut(index as usize) .and_then(|x| x.as_mut()) .and_then(|r| if r.account == who { r.fee = fee; Some(()) } else { None }) - .ok_or_else(|| Error::::InvalidIndex.into()) - ) + .ok_or_else(|| DispatchError::from(Error::::InvalidIndex))?; + Ok(rs.len()) + })?; + Ok(Some(T::DbWeight::get().reads_writes(1, 1) + + 7_400_000 + 330_000 * registrars as Weight // R + ).into()) } /// Change the account associated with a registrar. @@ -741,20 +996,28 @@ decl_module! { /// # /// - `O(R)`. /// - One storage mutation `O(R)`. + /// - Benchmark: 8.823 + R * 0.32 µs (min squares analysis) /// # - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + #[weight = T::DbWeight::get().reads_writes(1, 1) + + 8_900_000 // constant + + 320_000 * T::MaxRegistrars::get() as Weight // R + ] fn set_account_id(origin, #[compact] index: RegistrarIndex, new: T::AccountId, - ) -> DispatchResult { + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; - >::mutate(|rs| + let registrars = >::mutate(|rs| -> Result { rs.get_mut(index as usize) .and_then(|x| x.as_mut()) .and_then(|r| if r.account == who { r.account = new; Some(()) } else { None }) - .ok_or_else(|| Error::::InvalidIndex.into()) - ) + .ok_or_else(|| DispatchError::from(Error::::InvalidIndex))?; + Ok(rs.len()) + })?; + Ok(Some(T::DbWeight::get().reads_writes(1, 1) + + 8_900_000 + 320_000 * registrars as Weight // R + ).into()) } /// Set the field information for a registrar. @@ -768,20 +1031,28 @@ decl_module! { /// # /// - `O(R)`. /// - One storage mutation `O(R)`. + /// - Benchmark: 7.464 + R * 0.325 µs (min squares analysis) /// # - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + #[weight = T::DbWeight::get().reads_writes(1, 1) + + 7_500_000 // constant + + 330_000 * T::MaxRegistrars::get() as Weight // R + ] fn set_fields(origin, #[compact] index: RegistrarIndex, fields: IdentityFields, - ) -> DispatchResult { + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; - >::mutate(|rs| + let registrars = >::mutate(|rs| -> Result { rs.get_mut(index as usize) .and_then(|x| x.as_mut()) .and_then(|r| if r.account == who { r.fields = fields; Some(()) } else { None }) - .ok_or_else(|| Error::::InvalidIndex.into()) - ) + .ok_or_else(|| DispatchError::from(Error::::InvalidIndex))?; + Ok(rs.len()) + })?; + Ok(Some(T::DbWeight::get().reads_writes(1, 1) + + 7_500_000 + 330_000 * registrars as Weight // R + ).into()) } /// Provide a judgement for an account's identity. @@ -803,12 +1074,15 @@ decl_module! { /// - Storage: 1 read `O(R)`, 1 mutate `O(R + X)`. /// - One event. /// # - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + #[weight = weight_for::provide_judgement::( + T::MaxRegistrars::get().into(), // R + T::MaxAdditionalFields::get().into(), // X + )] fn provide_judgement(origin, #[compact] reg_index: RegistrarIndex, target: ::Source, judgement: Judgement>, - ) { + ) -> DispatchResultWithPostInfo { let sender = ensure_signed(origin)?; let target = T::Lookup::lookup(target)?; ensure!(!judgement.has_deposit(), Error::::InvalidJudgement); @@ -829,8 +1103,13 @@ decl_module! { } Err(position) => id.judgements.insert(position, item), } + + let judgements = id.judgements.len() as Weight; + let extra_fields = id.info.additional.len() as Weight; >::insert(&target, id); Self::deposit_event(RawEvent::JudgementGiven(target, reg_index)); + + Ok(Some(weight_for::provide_judgement::(judgements, extra_fields)).into()) } /// Remove an account's identity and sub-account information and slash the deposits. @@ -839,7 +1118,7 @@ decl_module! { /// `Slash`. Verification request deposits are not returned; they should be cancelled /// manually using `cancel_request`. /// - /// The dispatch origin for this call must be _Root_ or match `T::ForceOrigin`. + /// The dispatch origin for this call must match `T::ForceOrigin`. /// /// - `target`: the account whose identity the judgement is upon. This must be an account /// with a registered identity. @@ -852,18 +1131,20 @@ decl_module! { /// - `S + 2` storage mutations. /// - One event. /// # - #[weight = SimpleDispatchInfo::FixedNormal(100_000)] - fn kill_identity(origin, target: ::Source) { - T::ForceOrigin::try_origin(origin) - .map(|_| ()) - .or_else(ensure_root)?; + #[weight = weight_for::kill_identity::( + T::MaxRegistrars::get().into(), // R + T::MaxSubAccounts::get().into(), // S + T::MaxAdditionalFields::get().into(), // X + )] + fn kill_identity(origin, target: ::Source) -> DispatchResultWithPostInfo { + T::ForceOrigin::ensure_origin(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 (subs_deposit, sub_ids) = >::take(&target); - let deposit = >::take(&target).ok_or(Error::::NotNamed)?.total_deposit() - + subs_deposit; + let id = >::take(&target).ok_or(Error::::NotNamed)?; + let deposit = id.total_deposit() + subs_deposit; for sub in sub_ids.iter() { >::remove(sub); } @@ -871,6 +1152,12 @@ decl_module! { T::Slashed::on_unbalanced(T::Currency::slash_reserved(&target, deposit).0); Self::deposit_event(RawEvent::IdentityKilled(target, deposit)); + + Ok(Some(weight_for::kill_identity::( + id.judgements.len() as Weight, // R + sub_ids.len() as Weight, // S + id.info.additional.len() as Weight // X + )).into()) } } } @@ -895,9 +1182,7 @@ mod tests { ord_parameter_types, }; use sp_core::H256; - use frame_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 frame_system::{EnsureSignedBy, EnsureOneOf, EnsureRoot}; use sp_runtime::{ Perbill, testing::Header, traits::{BlakeTwo256, IdentityLookup}, }; @@ -906,9 +1191,6 @@ mod tests { pub enum Origin for Test where system = frame_system {} } - // For testing the pallet, we construct most of a mock runtime. This means - // first constructing a configuration type (`Test`) which `impl`s each of the - // configuration traits of pallets we want to use. #[derive(Clone, Eq, PartialEq)] pub struct Test; parameter_types! { @@ -918,6 +1200,7 @@ mod tests { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -930,6 +1213,10 @@ mod tests { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -937,6 +1224,7 @@ mod tests { type AccountData = pallet_balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } parameter_types! { pub const ExistentialDeposit: u64 = 1; @@ -947,6 +1235,7 @@ mod tests { type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; + type WeightInfo = (); } parameter_types! { pub const BasicDeposit: u64 = 10; @@ -954,11 +1243,22 @@ mod tests { pub const SubAccountDeposit: u64 = 10; pub const MaxSubAccounts: u32 = 2; pub const MaxAdditionalFields: u32 = 2; + pub const MaxRegistrars: u32 = 20; } ord_parameter_types! { pub const One: u64 = 1; pub const Two: u64 = 2; } + type EnsureOneOrRoot = EnsureOneOf< + u64, + EnsureRoot, + EnsureSignedBy + >; + type EnsureTwoOrRoot = EnsureOneOf< + u64, + EnsureRoot, + EnsureSignedBy + >; impl Trait for Test { type Event = (); type Currency = Balances; @@ -968,18 +1268,17 @@ mod tests { type SubAccountDeposit = SubAccountDeposit; type MaxSubAccounts = MaxSubAccounts; type MaxAdditionalFields = MaxAdditionalFields; - type RegistrarOrigin = EnsureSignedBy; - type ForceOrigin = EnsureSignedBy; + type MaxRegistrars = MaxRegistrars; + type RegistrarOrigin = EnsureOneOrRoot; + type ForceOrigin = EnsureTwoOrRoot; + type WeightInfo = (); } type System = frame_system::Module; type Balances = pallet_balances::Module; type Identity = Module; - // This function basically just builds a genesis storage key/value store according to - // our desired mockup. - fn new_test_ext() -> sp_io::TestExternalities { + pub fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - // We use default for brevity, but you can configure as desired if needed. pallet_balances::GenesisConfig:: { balances: vec![ (1, 10), @@ -1024,6 +1323,20 @@ mod tests { }); } + #[test] + fn amount_of_registrars_is_limited() { + new_test_ext().execute_with(|| { + for i in 1..MaxRegistrars::get() + 1 { + assert_ok!(Identity::add_registrar(Origin::signed(1), i as u64)); + } + let last_registrar = MaxRegistrars::get() as u64 + 1; + assert_noop!( + Identity::add_registrar(Origin::signed(1), last_registrar), + Error::::TooManyRegistrars + ); + }); + } + #[test] fn registration_should_work() { new_test_ext().execute_with(|| { @@ -1155,7 +1468,7 @@ mod tests { new_test_ext().execute_with(|| { assert_ok!(Identity::set_identity(Origin::signed(10), ten())); assert_ok!(Identity::set_subs(Origin::signed(10), vec![(20, Data::Raw(vec![40; 1]))])); - assert_ok!(Identity::kill_identity(Origin::ROOT, 10)); + assert_ok!(Identity::kill_identity(Origin::signed(2), 10)); assert_eq!(Balances::free_balance(10), 80); assert!(Identity::super_of(20).is_none()); }); diff --git a/frame/im-online/Cargo.toml b/frame/im-online/Cargo.toml index dabcc45ef166af7fdf5c47e6a86bbc41732017a0..7324342ec8afbb0aaf81de299a4e3e2098d0f1b1 100644 --- a/frame/im-online/Cargo.toml +++ b/frame/im-online/Cargo.toml @@ -1,28 +1,31 @@ [package] name = "pallet-im-online" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME's I'm online pallet" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-application-crypto = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/application-crypto" } -pallet-authorship = { version = "2.0.0-alpha.5", default-features = false, path = "../authorship" } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/core" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } +sp-application-crypto = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/application-crypto" } +pallet-authorship = { version = "2.0.0-rc4", default-features = false, path = "../authorship" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/core" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } serde = { version = "1.0.101", optional = true } -pallet-session = { version = "2.0.0-alpha.5", default-features = false, path = "../session" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -sp-staking = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/staking" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } +pallet-session = { version = "2.0.0-rc4", default-features = false, path = "../session" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +sp-staking = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/staking" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } -frame-benchmarking = { version = "2.0.0-alpha.5", default-features = false, path = "../benchmarking", optional = true } +frame-benchmarking = { version = "2.0.0-rc4", default-features = false, path = "../benchmarking", optional = true } [features] default = ["std", "pallet-session/historical"] @@ -41,6 +44,3 @@ std = [ "frame-system/std", ] runtime-benchmarks = ["frame-benchmarking"] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/im-online/src/benchmarking.rs b/frame/im-online/src/benchmarking.rs index 973bd0c36147c6c4c7e38eba55ef2fc490a0d85b..92d9b9d5a5364524065b263af8e422628b847420 100644 --- a/frame/im-online/src/benchmarking.rs +++ b/frame/im-online/src/benchmarking.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! I'm Online pallet benchmarking. @@ -25,6 +26,7 @@ use frame_benchmarking::benchmarks; use sp_core::offchain::{OpaquePeerId, OpaqueMultiaddr}; use sp_runtime::traits::{ValidateUnsigned, Zero}; use sp_runtime::transaction_validity::TransactionSource; +use frame_support::traits::UnfilteredDispatchable; use crate::Module as ImOnline; @@ -49,6 +51,7 @@ pub fn create_heartbeat(k: u32, e: u32) -> network_state, session_index: 0, authority_index: k-1, + validators_len: keys.len() as u32, }; let encoded_heartbeat = input_heartbeat.encode(); @@ -75,50 +78,30 @@ benchmarks! { }: { ImOnline::::validate_unsigned(TransactionSource::InBlock, &call)?; } + + validate_unsigned_and_then_heartbeat { + let k in 1 .. MAX_KEYS; + let e in 1 .. MAX_EXTERNAL_ADDRESSES; + let (input_heartbeat, signature) = create_heartbeat::(k, e)?; + let call = Call::heartbeat(input_heartbeat, signature); + }: { + ImOnline::::validate_unsigned(TransactionSource::InBlock, &call)?; + call.dispatch_bypass_filter(RawOrigin::None.into())?; + } } #[cfg(test)] mod tests { - use crate::*; - use super::SelectedBenchmark; - use crate::mock::*; + use super::*; + use crate::mock::{new_test_ext, Runtime}; use frame_support::assert_ok; #[test] - fn test_heartbeat_benchmark() { + fn test_benchmarks() { new_test_ext().execute_with(|| { - let k = 10; - - assert_eq!(ReceivedHeartbeats::iter_prefix(0).count(), 0); - - let selected_benchmark = SelectedBenchmark::heartbeat; - let c = vec![(frame_benchmarking::BenchmarkParameter::k, k)]; - let closure_to_benchmark = - >::instance( - &selected_benchmark, - &c - ).unwrap(); - - assert_ok!(closure_to_benchmark()); - - assert_eq!(ReceivedHeartbeats::iter_prefix(0).count(), 1); - }); - } - - #[test] - fn test_validate_unsigned_benchmark() { - new_test_ext().execute_with(|| { - let k = 10; - - let selected_benchmark = SelectedBenchmark::validate_unsigned; - let c = vec![(frame_benchmarking::BenchmarkParameter::k, k)]; - let closure_to_benchmark = - >::instance( - &selected_benchmark, - &c - ).unwrap(); - - assert_ok!(closure_to_benchmark()); + assert_ok!(test_benchmark_heartbeat::()); + assert_ok!(test_benchmark_validate_unsigned::()); + assert_ok!(test_benchmark_validate_unsigned_and_then_heartbeat::()); }); } } diff --git a/frame/im-online/src/lib.rs b/frame/im-online/src/lib.rs index cbce3095b69b54757ae9f6a0ccd11c454901a2bd..cdc7fea00d2181b09df8e5029f681583b7bd84c1 100644 --- a/frame/im-online/src/lib.rs +++ b/frame/im-online/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # I'm online Module //! @@ -43,14 +44,14 @@ //! //! ``` //! use frame_support::{decl_module, dispatch}; -//! use frame_system::{self as system, ensure_signed}; +//! use frame_system::ensure_signed; //! use pallet_im_online::{self as im_online}; //! //! pub trait Trait: im_online::Trait {} //! //! decl_module! { //! pub struct Module for enum Call where origin: T::Origin { -//! #[weight = frame_support::weights::SimpleDispatchInfo::default()] +//! #[weight = 0] //! pub fn is_online(origin, authority_index: u32) -> dispatch::DispatchResult { //! let _sender = ensure_signed(origin)?; //! let _is_online = >::is_online(authority_index); @@ -81,7 +82,7 @@ use pallet_session::historical::IdentificationTuple; use sp_runtime::{ offchain::storage::StorageValueRef, RuntimeDebug, - traits::{Convert, Member, Saturating, AtLeast32Bit}, Perbill, + traits::{Convert, Member, Saturating, AtLeast32BitUnsigned}, Perbill, transaction_validity::{ TransactionValidity, ValidTransaction, InvalidTransaction, TransactionSource, TransactionPriority, @@ -94,9 +95,13 @@ use sp_staking::{ use frame_support::{ decl_module, decl_event, decl_storage, Parameter, debug, decl_error, traits::Get, + weights::Weight, +}; +use frame_system::ensure_none; +use frame_system::offchain::{ + SendTransactionTypes, + SubmitTransaction, }; -use frame_system::{self as system, ensure_none}; -use frame_system::offchain::SubmitUnsignedTransaction; pub mod sr25519 { mod app_sr25519 { @@ -155,7 +160,7 @@ struct HeartbeatStatus { pub sent_at: BlockNumber, } -impl HeartbeatStatus { +impl HeartbeatStatus { /// Returns true if heartbeat has been recently sent. /// /// Parameters: @@ -217,21 +222,29 @@ pub struct Heartbeat pub session_index: SessionIndex, /// An index of the authority on the list of validators. pub authority_index: AuthIndex, + /// The length of session validator set + pub validators_len: u32, +} + +pub trait WeightInfo { + fn heartbeat(k: u32, e: u32, ) -> Weight; + fn validate_unsigned(k: u32, e: u32, ) -> Weight; + fn validate_unsigned_and_then_heartbeat(k: u32, e: u32, ) -> Weight; +} + +impl WeightInfo for () { + fn heartbeat(_k: u32, _e: u32, ) -> Weight { 1_000_000_000 } + fn validate_unsigned(_k: u32, _e: u32, ) -> Weight { 1_000_000_000 } + fn validate_unsigned_and_then_heartbeat(_k: u32, _e: u32, ) -> Weight { 1_000_000_000 } } -pub trait Trait: frame_system::Trait + pallet_session::historical::Trait { +pub trait Trait: SendTransactionTypes> + pallet_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>; - /// A dispatchable call type. - type Call: From>; - - /// A transaction submitter. - type SubmitTransaction: SubmitUnsignedTransaction::Call>; - /// An expected duration of the session. /// /// This parameter is used to determine the longevity of `heartbeat` transaction @@ -247,6 +260,15 @@ pub trait Trait: frame_system::Trait + pallet_session::historical::Trait { IdentificationTuple, UnresponsivenessOffence>, >; + + /// A configuration for base priority of unsigned transactions. + /// + /// This is exposed so that it can be tuned for particular runtime, when + /// multiple pallets send unsigned transactions. + type UnsignedPriority: Get; + + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; } decl_event!( @@ -258,7 +280,7 @@ decl_event!( 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. + /// At the end of the session, at least one validator was found to be offline. SomeOffline(Vec), } ); @@ -310,13 +332,30 @@ decl_module! { fn deposit_event() = default; - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + /// # + /// - Complexity: `O(K + E)` where K is length of `Keys` and E is length of + /// `Heartbeat.network_state.external_address` + /// + /// - `O(K)`: decoding of length `K` + /// - `O(E)`: decoding/encoding of length `E` + /// - DbReads: pallet_session `Validators`, pallet_session `CurrentIndex`, `Keys`, + /// `ReceivedHeartbeats` + /// - DbWrites: `ReceivedHeartbeats` + /// # + // NOTE: the weight include cost of validate_unsigned as it is part of the cost to import + // block with such an extrinsic. + #[weight = (310_000_000 + T::DbWeight::get().reads_writes(4, 1)) + .saturating_add(750_000.saturating_mul(heartbeat.validators_len as Weight)) + .saturating_add( + 1_200_000.saturating_mul(heartbeat.network_state.external_addresses.len() as Weight) + ) + ] fn heartbeat( origin, heartbeat: Heartbeat, // since signature verification is done in `validate_unsigned` // we can skip doing it here again. - _signature: ::Signature + _signature: ::Signature, ) { ensure_none(origin)?; @@ -436,9 +475,17 @@ impl Module { } let session_index = >::current_index(); + let validators_len = >::validators().len() as u32; + Ok(Self::local_authority_keys() .map(move |(authority_index, key)| - Self::send_single_heartbeat(authority_index, key, session_index, block_number) + Self::send_single_heartbeat( + authority_index, + key, + session_index, + block_number, + validators_len, + ) )) } @@ -447,7 +494,8 @@ impl Module { authority_index: u32, key: T::AuthorityId, session_index: SessionIndex, - block_number: T::BlockNumber + block_number: T::BlockNumber, + validators_len: u32, ) -> OffchainResult { // A helper function to prepare heartbeat call. let prepare_heartbeat = || -> OffchainResult> { @@ -458,8 +506,11 @@ impl Module { network_state, session_index, authority_index, + validators_len, }; + let signature = key.sign(&heartbeat_data.encode()).ok_or(OffchainErr::FailedSigning)?; + Ok(Call::heartbeat(heartbeat_data, signature)) }; @@ -484,7 +535,7 @@ impl Module { call, ); - T::SubmitTransaction::submit_unsigned(call) + SubmitTransaction::>::submit_unsigned_transaction(call.into()) .map_err(|_| OffchainErr::SubmitTransaction)?; Ok(()) @@ -493,9 +544,18 @@ impl Module { } fn local_authority_keys() -> impl Iterator { - // we run only when a local authority key is configured + // on-chain storage + // + // At index `idx`: + // 1. A (ImOnline) public key to be used by a validator at index `idx` to send im-online + // heartbeats. let authorities = Keys::::get(); + + // local keystore + // + // All `ImOnline` public (+private) keys currently in the local keystore. let mut local_keys = T::AuthorityId::all(); + local_keys.sort(); authorities.into_iter() @@ -557,6 +617,11 @@ impl Module { Keys::::put(keys); } } + + #[cfg(test)] + fn set_keys(keys: Vec) { + Keys::::put(&keys) + } } impl sp_runtime::BoundToRuntimeAppPublic for Module { @@ -623,6 +688,9 @@ impl pallet_session::OneSessionHandler for Module { } } +/// Invalid transaction custom error. Returned when validators_len field in heartbeat is incorrect. +const INVALID_VALIDATORS_LEN: u8 = 10; + impl frame_support::unsigned::ValidateUnsigned for Module { type Call = Call; @@ -644,6 +712,9 @@ impl frame_support::unsigned::ValidateUnsigned for Module { // verify that the incoming (unverified) pubkey is actually an authority id let keys = Keys::::get(); + if keys.len() as u32 != heartbeat.validators_len { + return InvalidTransaction::Custom(INVALID_VALIDATORS_LEN).into(); + } let authority_id = match keys.get(heartbeat.authority_index as usize) { Some(id) => id, None => return InvalidTransaction::BadProof.into(), @@ -658,13 +729,14 @@ impl frame_support::unsigned::ValidateUnsigned for Module { return InvalidTransaction::BadProof.into(); } - Ok(ValidTransaction { - priority: TransactionPriority::max_value(), - requires: vec![], - provides: vec![(current_session, authority_id).encode()], - longevity: TryInto::::try_into(T::SessionDuration::get() / 2.into()).unwrap_or(64_u64), - propagate: true, - }) + ValidTransaction::with_tag_prefix("ImOnline") + .priority(T::UnsignedPriority::get()) + .and_provides((current_session, authority_id)) + .longevity(TryInto::::try_into( + T::SessionDuration::get() / 2.into() + ).unwrap_or(64_u64)) + .propagate(true) + .build() } else { InvalidTransaction::Call.into() } @@ -679,11 +751,11 @@ pub struct UnresponsivenessOffence { /// /// It acts as a time measure for unresponsiveness reports and effectively will always point /// at the end of the session. - session_index: SessionIndex, + pub session_index: SessionIndex, /// The size of the validator set in current session/era. - validator_set_count: u32, + pub validator_set_count: u32, /// Authorities that were unresponsive during the current era. - offenders: Vec, + pub offenders: Vec, } impl Offence for UnresponsivenessOffence { diff --git a/frame/im-online/src/mock.rs b/frame/im-online/src/mock.rs index 3dc0543d8881b7d4154fe9895448038c99a1ad3b..968aad1f95bab047f344b42f3978dc78bdaada83 100644 --- a/frame/im-online/src/mock.rs +++ b/frame/im-online/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utilities @@ -27,7 +28,6 @@ use sp_runtime::testing::{Header, UintAuthorityId, TestXt}; use sp_runtime::traits::{IdentityLookup, BlakeTwo256, ConvertInto}; use sp_core::H256; use frame_support::{impl_outer_origin, impl_outer_dispatch, parameter_types, weights::Weight}; - use frame_system as system; impl_outer_origin!{ pub enum Origin for Runtime {} @@ -40,7 +40,11 @@ impl_outer_dispatch! { } thread_local! { - pub static VALIDATORS: RefCell>> = RefCell::new(Some(vec![1, 2, 3])); + pub static VALIDATORS: RefCell>> = RefCell::new(Some(vec![ + 1, + 2, + 3, + ])); } pub struct TestSessionManager; @@ -68,7 +72,6 @@ impl pallet_session::historical::SessionManager for TestSessionManager /// An extrinsic type used for tests. pub type Extrinsic = TestXt; -type SubmitTransaction = frame_system::offchain::TransactionSubmitter<(), Call, Extrinsic>; type IdentificationTuple = (u64, u64); type Offence = crate::UnresponsivenessOffence; @@ -83,14 +86,19 @@ impl ReportOffence for OffenceHandler { OFFENCES.with(|l| l.borrow_mut().push((reporters, offence))); Ok(()) } + + fn is_known_offence(_offenders: &[IdentificationTuple], _time_slot: &SessionIndex) -> bool { + false + } } pub fn new_test_ext() -> sp_io::TestExternalities { - let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + let t = frame_system::GenesisConfig::default() + .build_storage::() + .unwrap(); t.into() } - #[derive(Clone, PartialEq, Eq, Debug)] pub struct Runtime; @@ -102,6 +110,7 @@ parameter_types! { } impl frame_system::Trait for Runtime { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -114,6 +123,10 @@ impl frame_system::Trait for Runtime { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -121,6 +134,7 @@ impl frame_system::Trait for Runtime { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } parameter_types! { @@ -142,6 +156,7 @@ impl pallet_session::Trait for Runtime { type Event = (); type DisabledValidatorsThreshold = DisabledValidatorsThreshold; type NextSessionRotation = pallet_session::PeriodicSessions; + type WeightInfo = (); } impl pallet_session::historical::Trait for Runtime { @@ -160,13 +175,24 @@ impl pallet_authorship::Trait for Runtime { type EventHandler = ImOnline; } +parameter_types! { + pub const UnsignedPriority: u64 = 1 << 20; +} + impl Trait for Runtime { type AuthorityId = UintAuthorityId; type Event = (); - type Call = Call; - type SubmitTransaction = SubmitTransaction; type ReportUnresponsiveness = OffenceHandler; type SessionDuration = Period; + type UnsignedPriority = UnsignedPriority; + type WeightInfo = (); +} + +impl frame_system::offchain::SendTransactionTypes for Runtime where + Call: From, +{ + type OverarchingCall = Call; + type Extrinsic = Extrinsic; } /// Im Online module. @@ -178,5 +204,7 @@ pub fn advance_session() { let now = System::block_number().max(1); System::set_block_number(now + 1); Session::rotate_session(); + let keys = Session::validators().into_iter().map(UintAuthorityId).collect(); + ImOnline::set_keys(keys); assert_eq!(Session::current_index(), (now / Period::get()) as u32); } diff --git a/frame/im-online/src/tests.rs b/frame/im-online/src/tests.rs index c7bf2afcca629f74765c1519abdd063e63dae1f1..835d8440e6d5b0e0f16caf750d841361a3012edc 100644 --- a/frame/im-online/src/tests.rs +++ b/frame/im-online/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for the im-online module. @@ -27,7 +28,7 @@ use sp_core::offchain::{ testing::{TestOffchainExt, TestTransactionPoolExt}, }; use frame_support::{dispatch, assert_noop}; -use sp_runtime::testing::UintAuthorityId; +use sp_runtime::{testing::UintAuthorityId, transaction_validity::TransactionValidityError}; #[test] fn test_unresponsiveness_slash_fraction() { @@ -61,15 +62,15 @@ fn should_report_offline_validators() { let block = 1; System::set_block_number(block); // buffer new validators - Session::rotate_session(); + advance_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(); + advance_session(); // when // we end current session and start the next one - Session::rotate_session(); + advance_session(); // then let offences = OFFENCES.with(|l| l.replace(vec![])); @@ -87,9 +88,9 @@ fn should_report_offline_validators() { // 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(); + let _ = heartbeat(block, 3, idx as u32, v.into(), Session::validators()).unwrap(); } - Session::rotate_session(); + advance_session(); // then let offences = OFFENCES.with(|l| l.replace(vec![])); @@ -111,6 +112,7 @@ fn heartbeat( session_index: u32, authority_index: u32, id: UintAuthorityId, + validators: Vec, ) -> dispatch::DispatchResult { use frame_support::unsigned::ValidateUnsigned; @@ -122,15 +124,20 @@ fn heartbeat( }, session_index, authority_index, + validators_len: validators.len() as u32, }; let signature = id.sign(&heartbeat.encode()).unwrap(); ImOnline::pre_dispatch(&crate::Call::heartbeat(heartbeat.clone(), signature.clone())) - .map_err(|e| <&'static str>::from(e))?; + .map_err(|e| match e { + TransactionValidityError::Invalid(InvalidTransaction::Custom(INVALID_VALIDATORS_LEN)) => + "invalid validators len", + e @ _ => <&'static str>::from(e), + })?; ImOnline::heartbeat( - Origin::system(frame_system::RawOrigin::None), + Origin::none(), heartbeat, - signature + signature, ) } @@ -152,7 +159,7 @@ fn should_mark_online_validator_when_heartbeat_is_received() { assert!(!ImOnline::is_online(2)); // when - let _ = heartbeat(1, 2, 0, 1.into()).unwrap(); + let _ = heartbeat(1, 2, 0, 1.into(), Session::validators()).unwrap(); // then assert!(ImOnline::is_online(0)); @@ -160,7 +167,7 @@ fn should_mark_online_validator_when_heartbeat_is_received() { assert!(!ImOnline::is_online(2)); // and when - let _ = heartbeat(1, 2, 2, 3.into()).unwrap(); + let _ = heartbeat(1, 2, 2, 3.into(), Session::validators()).unwrap(); // then assert!(ImOnline::is_online(0)); @@ -170,11 +177,11 @@ fn should_mark_online_validator_when_heartbeat_is_received() { } #[test] -fn late_heartbeat_should_fail() { +fn late_heartbeat_and_invalid_keys_len_should_fail() { new_test_ext().execute_with(|| { advance_session(); // given - VALIDATORS.with(|l| *l.borrow_mut() = Some(vec![1, 2, 4, 4, 5, 6])); + 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(); @@ -183,8 +190,11 @@ fn late_heartbeat_should_fail() { 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"); + assert_noop!(heartbeat(1, 3, 0, 1.into(), Session::validators()), "Transaction is outdated"); + assert_noop!(heartbeat(1, 1, 0, 1.into(), Session::validators()), "Transaction is outdated"); + + // invalid validators_len + assert_noop!(heartbeat(1, 2, 0, 1.into(), vec![]), "invalid validators len"); }); } @@ -220,7 +230,7 @@ fn should_generate_heartbeats() { // check stuff about the transaction. let ex: Extrinsic = Decode::decode(&mut &*transaction).unwrap(); let heartbeat = match ex.call { - crate::mock::Call::ImOnline(crate::Call::heartbeat(h, _)) => h, + crate::mock::Call::ImOnline(crate::Call::heartbeat(h, ..)) => h, e => panic!("Unexpected call: {:?}", e), }; @@ -229,6 +239,7 @@ fn should_generate_heartbeats() { network_state: sp_io::offchain::network_state().unwrap(), session_index: 2, authority_index: 2, + validators_len: 3, }); }); } @@ -248,7 +259,7 @@ fn should_cleanup_received_heartbeats_on_session_end() { 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(); + let _ = heartbeat(1, 2, 0, 1.into(), Session::validators()).unwrap(); // the heartbeat is stored assert!(!ImOnline::received_heartbeats(&2, &0).is_none()); @@ -315,7 +326,7 @@ fn should_not_send_a_report_if_already_online() { ImOnline::note_uncle(3, 0); // when - UintAuthorityId::set_all_keys(vec![0]); // all authorities use pallet_session key 0 + UintAuthorityId::set_all_keys(vec![1, 2, 3]); // we expect error, since the authority is already online. let mut res = ImOnline::send_heartbeats(4).unwrap(); assert_eq!(res.next().unwrap().unwrap(), ()); @@ -330,7 +341,7 @@ fn should_not_send_a_report_if_already_online() { // check stuff about the transaction. let ex: Extrinsic = Decode::decode(&mut &*transaction).unwrap(); let heartbeat = match ex.call { - crate::mock::Call::ImOnline(crate::Call::heartbeat(h, _)) => h, + crate::mock::Call::ImOnline(crate::Call::heartbeat(h, ..)) => h, e => panic!("Unexpected call: {:?}", e), }; @@ -339,6 +350,7 @@ fn should_not_send_a_report_if_already_online() { network_state: sp_io::offchain::network_state().unwrap(), session_index: 2, authority_index: 0, + validators_len: 3, }); }); } diff --git a/frame/indices/Cargo.toml b/frame/indices/Cargo.toml index f28f393642bedac28e1644f35046d6ad9c1b4a2e..3ec8ea363bc9a764a2406dd2798aff5ed48d4682 100644 --- a/frame/indices/Cargo.toml +++ b/frame/indices/Cargo.toml @@ -1,26 +1,31 @@ [package] name = "pallet-indices" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME indices management pallet" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-keyring = { version = "2.0.0-alpha.5", optional = true, path = "../../primitives/keyring" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/core" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-keyring = { version = "2.0.0-rc4", optional = true, path = "../../primitives/keyring" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/core" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } + +frame-benchmarking = { version = "2.0.0-rc4", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -pallet-balances = { version = "2.0.0-alpha.5", path = "../balances" } +pallet-balances = { version = "2.0.0-rc4", path = "../balances" } [features] default = ["std"] @@ -35,6 +40,7 @@ std = [ "sp-runtime/std", "frame-system/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +runtime-benchmarks = [ + "frame-benchmarking", + "frame-support/runtime-benchmarks", +] diff --git a/frame/indices/src/address.rs b/frame/indices/src/address.rs index f4487eeb693dec14bfcc3bae7229c3ce41177329..0fd89333813289d448f85e50cdf1002b8386e2db 100644 --- a/frame/indices/src/address.rs +++ b/frame/indices/src/address.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Address type that is union of index and id for an account. diff --git a/frame/indices/src/benchmarking.rs b/frame/indices/src/benchmarking.rs new file mode 100644 index 0000000000000000000000000000000000000000..a6b543bb43f4abac986c537ddc1fedf258d27e54 --- /dev/null +++ b/frame/indices/src/benchmarking.rs @@ -0,0 +1,124 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Benchmarks for Indices Pallet + +#![cfg(feature = "runtime-benchmarks")] + +use super::*; +use frame_system::RawOrigin; +use frame_benchmarking::{benchmarks, account}; +use sp_runtime::traits::Bounded; + +use crate::Module as Indices; + +const SEED: u32 = 0; + +benchmarks! { + _ { } + + claim { + // Index being claimed + let i in 0 .. 1000; + let account_index = T::AccountIndex::from(i); + let caller: T::AccountId = account("caller", 0, SEED); + T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + }: _(RawOrigin::Signed(caller.clone()), account_index) + verify { + assert_eq!(Accounts::::get(account_index).unwrap().0, caller); + } + + transfer { + // Index being claimed + let i in 0 .. 1000; + let account_index = T::AccountIndex::from(i); + // Setup accounts + let caller: T::AccountId = account("caller", 0, SEED); + T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + let recipient: T::AccountId = account("recipient", i, SEED); + T::Currency::make_free_balance_be(&recipient, BalanceOf::::max_value()); + // Claim the index + Indices::::claim(RawOrigin::Signed(caller.clone()).into(), account_index)?; + }: _(RawOrigin::Signed(caller.clone()), recipient.clone(), account_index) + verify { + assert_eq!(Accounts::::get(account_index).unwrap().0, recipient); + } + + free { + // Index being claimed + let i in 0 .. 1000; + let account_index = T::AccountIndex::from(i); + // Setup accounts + let caller: T::AccountId = account("caller", 0, SEED); + T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + // Claim the index + Indices::::claim(RawOrigin::Signed(caller.clone()).into(), account_index)?; + }: _(RawOrigin::Signed(caller.clone()), account_index) + verify { + assert_eq!(Accounts::::get(account_index), None); + } + + force_transfer { + // Index being claimed + let i in 0 .. 1000; + let account_index = T::AccountIndex::from(i); + // Setup accounts + let original: T::AccountId = account("original", 0, SEED); + T::Currency::make_free_balance_be(&original, BalanceOf::::max_value()); + let recipient: T::AccountId = account("recipient", i, SEED); + T::Currency::make_free_balance_be(&recipient, BalanceOf::::max_value()); + // Claim the index + Indices::::claim(RawOrigin::Signed(original).into(), account_index)?; + }: _(RawOrigin::Root, recipient.clone(), account_index, false) + verify { + assert_eq!(Accounts::::get(account_index).unwrap().0, recipient); + } + + freeze { + // Index being claimed + let i in 0 .. 1000; + let account_index = T::AccountIndex::from(i); + // Setup accounts + let caller: T::AccountId = account("caller", 0, SEED); + T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + // Claim the index + Indices::::claim(RawOrigin::Signed(caller.clone()).into(), account_index)?; + }: _(RawOrigin::Signed(caller.clone()), account_index) + verify { + assert_eq!(Accounts::::get(account_index).unwrap().2, true); + } + + // TODO in another PR: lookup and unlookup trait weights (not critical) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::{new_test_ext, Test}; + use frame_support::assert_ok; + + #[test] + fn test_benchmarks() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_claim::()); + assert_ok!(test_benchmark_transfer::()); + assert_ok!(test_benchmark_free::()); + assert_ok!(test_benchmark_force_transfer::()); + assert_ok!(test_benchmark_freeze::()); + }); + } +} diff --git a/frame/indices/src/lib.rs b/frame/indices/src/lib.rs index d2ba664d425ffce1ef0aac0745fea825d7183a42..5224e03347ceb89d115b9eb0ea62af6c22607da3 100644 --- a/frame/indices/src/lib.rs +++ b/frame/indices/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! An index is a short form of an address. This module handles allocation //! of indices for a newly created accounts. @@ -22,23 +23,39 @@ use sp_std::prelude::*; use codec::Codec; use sp_runtime::traits::{ - StaticLookup, Member, LookupError, Zero, One, BlakeTwo256, Hash, Saturating, AtLeast32Bit + StaticLookup, Member, LookupError, Zero, Saturating, AtLeast32Bit }; use frame_support::{Parameter, decl_module, decl_error, decl_event, decl_storage, ensure}; -use frame_support::weights::{Weight, SimpleDispatchInfo, WeighData}; use frame_support::dispatch::DispatchResult; use frame_support::traits::{Currency, ReservableCurrency, Get, BalanceStatus::Reserved}; -use frame_support::storage::migration::take_storage_value; +use frame_support::weights::{Weight, constants::WEIGHT_PER_MICROS}; use frame_system::{ensure_signed, ensure_root}; use self::address::Address as RawAddress; mod mock; pub mod address; mod tests; +mod benchmarking; pub type Address = RawAddress<::AccountId, ::AccountIndex>; type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; +pub trait WeightInfo { + fn claim(i: u32, ) -> Weight; + fn transfer(i: u32, ) -> Weight; + fn free(i: u32, ) -> Weight; + fn force_transfer(i: u32, ) -> Weight; + fn freeze(i: u32, ) -> Weight; +} + +impl WeightInfo for () { + fn claim(_i: u32, ) -> Weight { 1_000_000_000 } + fn transfer(_i: u32, ) -> Weight { 1_000_000_000 } + fn free(_i: u32, ) -> Weight { 1_000_000_000 } + fn force_transfer(_i: u32, ) -> Weight { 1_000_000_000 } + fn freeze(_i: u32, ) -> Weight { 1_000_000_000 } +} + /// The module's config trait. pub trait Trait: frame_system::Trait { /// Type used for storing an account's index; implies the maximum number of accounts the system @@ -53,6 +70,9 @@ pub trait Trait: frame_system::Trait { /// The overarching event type. type Event: From> + Into<::Event>; + + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; } decl_storage! { @@ -61,9 +81,9 @@ decl_storage! { pub Accounts build(|config: &GenesisConfig| config.indices.iter() .cloned() - .map(|(a, b)| (a, (b, Zero::zero()))) + .map(|(a, b)| (a, (b, Zero::zero(), false))) .collect::>() - ): map hasher(blake2_128_concat) T::AccountIndex => Option<(T::AccountId, BalanceOf)>; + ): map hasher(blake2_128_concat) T::AccountIndex => Option<(T::AccountId, BalanceOf, bool)>; } add_extra_genesis { config(indices): Vec<(T::AccountIndex, T::AccountId)>; @@ -79,6 +99,8 @@ decl_event!( IndexAssigned(AccountId, AccountIndex), /// A account index has been freed up (unassigned). IndexFreed(AccountIndex), + /// A account index has been frozen to its current account ID. + IndexFrozen(AccountIndex, AccountId), } ); @@ -92,6 +114,8 @@ decl_error! { InUse, /// The source and destination accounts are identical. NotTransfer, + /// The index is permanent and may not be freed/changed. + Permanent, } } @@ -99,12 +123,6 @@ decl_module! { pub struct Module for enum Call where origin: T::Origin, system = frame_system { fn deposit_event() = default; - fn on_initialize() -> Weight { - Self::migrations(); - - SimpleDispatchInfo::default().weigh_data(()) - } - /// Assign an previously unassigned index. /// /// Payment: `Deposit` is reserved from the sender account. @@ -120,14 +138,17 @@ decl_module! { /// - One storage mutation (codec `O(1)`). /// - One reserve operation. /// - One event. + /// ------------------- + /// - Base Weight: 28.69 µs + /// - DB Weight: 1 Read/Write (Accounts) /// # - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = T::DbWeight::get().reads_writes(1, 1) + 30 * WEIGHT_PER_MICROS] fn claim(origin, index: T::AccountIndex) { let who = ensure_signed(origin)?; Accounts::::try_mutate(index, |maybe_value| { ensure!(maybe_value.is_none(), Error::::InUse); - *maybe_value = Some((who.clone(), T::Deposit::get())); + *maybe_value = Some((who.clone(), T::Deposit::get(), false)); T::Currency::reserve(&who, T::Deposit::get()) })?; Self::deposit_event(RawEvent::IndexAssigned(who, index)); @@ -148,17 +169,23 @@ decl_module! { /// - One storage mutation (codec `O(1)`). /// - One transfer operation. /// - One event. + /// ------------------- + /// - Base Weight: 33.74 µs + /// - DB Weight: + /// - Reads: Indices Accounts, System Account (recipient) + /// - Writes: Indices Accounts, System Account (recipient) /// # - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = T::DbWeight::get().reads_writes(2, 2) + 35 * WEIGHT_PER_MICROS] fn transfer(origin, new: T::AccountId, index: T::AccountIndex) { let who = ensure_signed(origin)?; ensure!(who != new, Error::::NotTransfer); Accounts::::try_mutate(index, |maybe_value| -> DispatchResult { - let (account, amount) = maybe_value.take().ok_or(Error::::NotAssigned)?; + let (account, amount, perm) = maybe_value.take().ok_or(Error::::NotAssigned)?; + ensure!(!perm, Error::::Permanent); ensure!(&account == &who, Error::::NotOwner); let lost = T::Currency::repatriate_reserved(&who, &new, amount, Reserved)?; - *maybe_value = Some((new.clone(), amount.saturating_sub(lost))); + *maybe_value = Some((new.clone(), amount.saturating_sub(lost), false)); Ok(()) })?; Self::deposit_event(RawEvent::IndexAssigned(new, index)); @@ -179,13 +206,17 @@ decl_module! { /// - One storage mutation (codec `O(1)`). /// - One reserve operation. /// - One event. + /// ------------------- + /// - Base Weight: 25.53 µs + /// - DB Weight: 1 Read/Write (Accounts) /// # - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = T::DbWeight::get().reads_writes(1, 1) + 25 * WEIGHT_PER_MICROS] fn free(origin, index: T::AccountIndex) { let who = ensure_signed(origin)?; Accounts::::try_mutate(index, |maybe_value| -> DispatchResult { - let (account, amount) = maybe_value.take().ok_or(Error::::NotAssigned)?; + let (account, amount, perm) = maybe_value.take().ok_or(Error::::NotAssigned)?; + ensure!(!perm, Error::::Permanent); ensure!(&account == &who, Error::::NotOwner); T::Currency::unreserve(&who, amount); Ok(()) @@ -200,6 +231,7 @@ decl_module! { /// /// - `index`: the index to be (re-)assigned. /// - `new`: the new owner of the index. This function is a no-op if it is equal to sender. + /// - `freeze`: if set to `true`, will freeze the index so it cannot be transferred. /// /// Emits `IndexAssigned` if successful. /// @@ -208,19 +240,57 @@ decl_module! { /// - One storage mutation (codec `O(1)`). /// - Up to one reserve operation. /// - One event. + /// ------------------- + /// - Base Weight: 26.83 µs + /// - DB Weight: + /// - Reads: Indices Accounts, System Account (original owner) + /// - Writes: Indices Accounts, System Account (original owner) /// # - #[weight = frame_support::weights::SimpleDispatchInfo::default()] - fn force_transfer(origin, new: T::AccountId, index: T::AccountIndex) { + #[weight = T::DbWeight::get().reads_writes(2, 2) + 25 * WEIGHT_PER_MICROS] + fn force_transfer(origin, new: T::AccountId, index: T::AccountIndex, freeze: bool) { ensure_root(origin)?; Accounts::::mutate(index, |maybe_value| { - if let Some((account, amount)) = maybe_value.take() { + if let Some((account, amount, _)) = maybe_value.take() { T::Currency::unreserve(&account, amount); } - *maybe_value = Some((new.clone(), Zero::zero())); + *maybe_value = Some((new.clone(), Zero::zero(), freeze)); }); Self::deposit_event(RawEvent::IndexAssigned(new, index)); } + + /// Freeze an index so it will always point to the sender account. This consumes the deposit. + /// + /// The dispatch origin for this call must be _Signed_ and the signing account must have a + /// non-frozen account `index`. + /// + /// - `index`: the index to be frozen in place. + /// + /// Emits `IndexFrozen` if successful. + /// + /// # + /// - `O(1)`. + /// - One storage mutation (codec `O(1)`). + /// - Up to one slash operation. + /// - One event. + /// ------------------- + /// - Base Weight: 30.86 µs + /// - DB Weight: 1 Read/Write (Accounts) + /// # + #[weight = T::DbWeight::get().reads_writes(1, 1) + 30 * WEIGHT_PER_MICROS] + fn freeze(origin, index: T::AccountIndex) { + let who = ensure_signed(origin)?; + + Accounts::::try_mutate(index, |maybe_value| -> DispatchResult { + let (account, amount, perm) = maybe_value.take().ok_or(Error::::NotAssigned)?; + ensure!(!perm, Error::::Permanent); + ensure!(&account == &who, Error::::NotOwner); + T::Currency::slash_reserved(&who, amount); + *maybe_value = Some((account, Zero::zero(), true)); + Ok(()) + })?; + Self::deposit_event(RawEvent::IndexFrozen(index, who)); + } } } @@ -241,30 +311,6 @@ impl Module { address::Address::Index(i) => Self::lookup_index(i), } } - - /// Do any migrations. - fn migrations() { - if let Some(set_count) = take_storage_value::(b"Indices", b"NextEnumSet", b"") { - // migrations need doing. - let set_size: T::AccountIndex = 64.into(); - - let mut set_index: T::AccountIndex = Zero::zero(); - while set_index < set_count { - let maybe_accounts = take_storage_value::>(b"Indices", b"EnumSet", BlakeTwo256::hash_of(&set_index).as_ref()); - if let Some(accounts) = maybe_accounts { - for (item_index, target) in accounts.into_iter().enumerate() { - if target != T::AccountId::default() && !T::Currency::total_balance(&target).is_zero() { - let index = set_index * set_size + T::AccountIndex::from(item_index as u32); - Accounts::::insert(index, (target, BalanceOf::::zero())); - } - } - } else { - break; - } - set_index += One::one(); - } - } - } } impl StaticLookup for Module { diff --git a/frame/indices/src/mock.rs b/frame/indices/src/mock.rs index 355b3cc792c9456a0537c263d0f79a5ec58e7042..97e7a954f8f58876497edf1a2cc431ac56a6ec5a 100644 --- a/frame/indices/src/mock.rs +++ b/frame/indices/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utilities @@ -49,6 +50,7 @@ parameter_types! { } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Call = (); type Index = u64; @@ -61,6 +63,10 @@ impl frame_system::Trait for Test { type Event = MetaEvent; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -68,6 +74,7 @@ impl frame_system::Trait for Test { type AccountData = pallet_balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } parameter_types! { @@ -80,6 +87,7 @@ impl pallet_balances::Trait for Test { type Event = MetaEvent; type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; + type WeightInfo = (); } parameter_types! { @@ -91,6 +99,7 @@ impl Trait for Test { type Currency = Balances; type Deposit = Deposit; type Event = MetaEvent; + type WeightInfo = (); } pub fn new_test_ext() -> sp_io::TestExternalities { diff --git a/frame/indices/src/tests.rs b/frame/indices/src/tests.rs index 9e434cfbe2a1c299ff2f16988c3b350af494d2fc..e288871d5530739f07aa0212d9721f681d1c1912 100644 --- a/frame/indices/src/tests.rs +++ b/frame/indices/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Tests for the module. @@ -47,6 +48,20 @@ fn freeing_should_work() { }); } +#[test] +fn freezing_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(Indices::claim(Some(1).into(), 0)); + assert_noop!(Indices::freeze(Some(1).into(), 1), Error::::NotAssigned); + assert_noop!(Indices::freeze(Some(2).into(), 0), Error::::NotOwner); + assert_ok!(Indices::freeze(Some(1).into(), 0)); + assert_noop!(Indices::freeze(Some(1).into(), 0), Error::::Permanent); + + assert_noop!(Indices::free(Some(1).into(), 0), Error::::Permanent); + assert_noop!(Indices::transfer(Some(1).into(), 2, 0), Error::::Permanent); + }); +} + #[test] fn indexing_lookup_should_work() { new_test_ext().execute_with(|| { @@ -86,7 +101,7 @@ fn transfer_index_on_accounts_should_work() { fn force_transfer_index_on_preowned_should_work() { new_test_ext().execute_with(|| { assert_ok!(Indices::claim(Some(1).into(), 0)); - assert_ok!(Indices::force_transfer(Origin::ROOT, 3, 0)); + assert_ok!(Indices::force_transfer(Origin::root(), 3, 0, false)); assert_eq!(Balances::reserved_balance(1), 0); assert_eq!(Balances::reserved_balance(3), 0); assert_eq!(Indices::lookup_index(0), Some(3)); @@ -96,7 +111,7 @@ fn force_transfer_index_on_preowned_should_work() { #[test] fn force_transfer_index_on_free_should_work() { new_test_ext().execute_with(|| { - assert_ok!(Indices::force_transfer(Origin::ROOT, 3, 0)); + assert_ok!(Indices::force_transfer(Origin::root(), 3, 0, false)); assert_eq!(Balances::reserved_balance(3), 0); assert_eq!(Indices::lookup_index(0), Some(3)); }); diff --git a/frame/membership/Cargo.toml b/frame/membership/Cargo.toml index 41e56b584f550332fe1b91f5763fa31765086d75..5df5d4ad6e3b8f3dc732635ce3610602799b5070 100644 --- a/frame/membership/Cargo.toml +++ b/frame/membership/Cargo.toml @@ -1,24 +1,27 @@ [package] name = "pallet-membership" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME membership management pallet" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/io" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } [dev-dependencies] -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } [features] default = ["std"] @@ -31,6 +34,3 @@ std = [ "frame-support/std", "frame-system/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/membership/src/lib.rs b/frame/membership/src/lib.rs index 8f086fa2f32114a6b2e17bc8d5f228cfee070d08..7d56390b8b317e0e8270256dc274b122c5580381 100644 --- a/frame/membership/src/lib.rs +++ b/frame/membership/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Membership Module //! @@ -25,10 +26,9 @@ use sp_std::prelude::*; use frame_support::{ decl_module, decl_storage, decl_event, decl_error, - traits::{ChangeMembers, InitializeMembers, EnsureOrigin}, - weights::SimpleDispatchInfo, + traits::{ChangeMembers, InitializeMembers, EnsureOrigin, Contains}, }; -use frame_system::{self as system, ensure_root, ensure_signed}; +use frame_system::ensure_signed; pub trait Trait: frame_system::Trait { /// The overarching event type. @@ -117,12 +117,10 @@ decl_module! { /// Add a member `who` to the set. /// - /// May only be called from `AddOrigin` or root. - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] - fn add_member(origin, who: T::AccountId) { - T::AddOrigin::try_origin(origin) - .map(|_| ()) - .or_else(ensure_root)?; + /// May only be called from `T::AddOrigin`. + #[weight = 50_000_000] + pub fn add_member(origin, who: T::AccountId) { + T::AddOrigin::ensure_origin(origin)?; let mut members = >::get(); let location = members.binary_search(&who).err().ok_or(Error::::AlreadyMember)?; @@ -136,12 +134,10 @@ decl_module! { /// Remove a member `who` from the set. /// - /// May only be called from `RemoveOrigin` or root. - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] - fn remove_member(origin, who: T::AccountId) { - T::RemoveOrigin::try_origin(origin) - .map(|_| ()) - .or_else(ensure_root)?; + /// May only be called from `T::RemoveOrigin`. + #[weight = 50_000_000] + pub fn remove_member(origin, who: T::AccountId) { + T::RemoveOrigin::ensure_origin(origin)?; let mut members = >::get(); let location = members.binary_search(&who).ok().ok_or(Error::::NotMember)?; @@ -156,14 +152,12 @@ decl_module! { /// Swap out one member `remove` for another `add`. /// - /// May only be called from `SwapOrigin` or root. + /// May only be called from `T::SwapOrigin`. /// /// Prime membership is *not* passed from `remove` to `add`, if extant. - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] - fn swap_member(origin, remove: T::AccountId, add: T::AccountId) { - T::SwapOrigin::try_origin(origin) - .map(|_| ()) - .or_else(ensure_root)?; + #[weight = 50_000_000] + pub fn swap_member(origin, remove: T::AccountId, add: T::AccountId) { + T::SwapOrigin::ensure_origin(origin)?; if remove == add { return Ok(()) } @@ -187,12 +181,10 @@ decl_module! { /// Change the membership to a new set, disregarding the existing membership. Be nice and /// pass `members` pre-sorted. /// - /// May only be called from `ResetOrigin` or root. - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] - fn reset_members(origin, members: Vec) { - T::ResetOrigin::try_origin(origin) - .map(|_| ()) - .or_else(ensure_root)?; + /// May only be called from `T::ResetOrigin`. + #[weight = 50_000_000] + pub fn reset_members(origin, members: Vec) { + T::ResetOrigin::ensure_origin(origin)?; let mut members = members; members.sort(); @@ -211,8 +203,8 @@ decl_module! { /// May only be called from `Signed` origin of a current member. /// /// Prime membership is passed from the origin account to `new`, if extant. - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] - fn change_key(origin, new: T::AccountId) { + #[weight = 50_000_000] + pub fn change_key(origin, new: T::AccountId) { let remove = ensure_signed(origin)?; if remove != new { @@ -239,22 +231,22 @@ decl_module! { } /// Set the prime member. Must be a current member. - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] - fn set_prime(origin, who: T::AccountId) { - T::PrimeOrigin::try_origin(origin) - .map(|_| ()) - .or_else(ensure_root)?; + /// + /// May only be called from `T::PrimeOrigin`. + #[weight = 50_000_000] + pub fn set_prime(origin, who: T::AccountId) { + T::PrimeOrigin::ensure_origin(origin)?; Self::members().binary_search(&who).ok().ok_or(Error::::NotMember)?; Prime::::put(&who); T::MembershipChanged::set_prime(Some(who)); } /// Remove the prime member if it exists. - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] - fn clear_prime(origin) { - T::PrimeOrigin::try_origin(origin) - .map(|_| ()) - .or_else(ensure_root)?; + /// + /// May only be called from `T::PrimeOrigin`. + #[weight = 50_000_000] + pub fn clear_prime(origin) { + T::PrimeOrigin::ensure_origin(origin)?; Prime::::kill(); T::MembershipChanged::set_prime(None); } @@ -272,6 +264,16 @@ impl, I: Instance> Module { } } +impl, I: Instance> Contains for Module { + fn sorted_members() -> Vec { + Self::members() + } + + fn count() -> usize { + Members::::decode_len().unwrap_or(0) + } +} + #[cfg(test)] mod tests { use super::*; @@ -282,8 +284,6 @@ mod tests { ord_parameter_types }; use sp_core::H256; - // The testing primitives are very useful for avoiding having to work with signatures - // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. use sp_runtime::{Perbill, traits::{BlakeTwo256, IdentityLookup, BadOrigin}, testing::Header}; use frame_system::EnsureSignedBy; @@ -291,9 +291,6 @@ mod tests { pub enum Origin for Test where system = frame_system {} } - // For testing the pallet, we construct most of a mock runtime. This means - // first constructing a configuration type (`Test`) which `impl`s each of the - // configuration traits of pallets we want to use. #[derive(Clone, Eq, PartialEq)] pub struct Test; parameter_types! { @@ -303,6 +300,7 @@ mod tests { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -315,6 +313,10 @@ mod tests { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -322,6 +324,7 @@ mod tests { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } ord_parameter_types! { pub const One: u64 = 1; @@ -373,8 +376,6 @@ mod tests { type Membership = Module; - // This function basically just builds a genesis storage key/value store according to - // our desired mockup. fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); // We use default for brevity, but you can configure as desired if needed. diff --git a/frame/metadata/Cargo.toml b/frame/metadata/Cargo.toml index f965e1dddcb09687f4cdc193c62f09e60f4d12e5..ae9cf736e957f2d626c2819e3786a51eff3f4bba 100644 --- a/frame/metadata/Cargo.toml +++ b/frame/metadata/Cargo.toml @@ -1,18 +1,21 @@ [package] name = "frame-metadata" -version = "11.0.0-alpha.5" +version = "11.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Decodable variant of the RuntimeMetadata." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } serde = { version = "1.0.101", optional = true, features = ["derive"] } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/core" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/core" } [features] default = ["std"] @@ -22,6 +25,3 @@ std = [ "sp-core/std", "serde", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/metadata/src/lib.rs b/frame/metadata/src/lib.rs index bec69999b2187338ea48c5f57941105c70fbc691..c0eeb76b6f97625179caa47bb08b7232ea1835ca 100644 --- a/frame/metadata/src/lib.rs +++ b/frame/metadata/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Decodable variant of the RuntimeMetadata. //! diff --git a/frame/multisig/Cargo.toml b/frame/multisig/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..d0b79bf4e329e245e8dc98bbcf3bce0862d0b230 --- /dev/null +++ b/frame/multisig/Cargo.toml @@ -0,0 +1,44 @@ +[package] +name = "pallet-multisig" +version = "2.0.0-rc4" +authors = ["Parity Technologies "] +edition = "2018" +license = "Apache-2.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +description = "FRAME multi-signature dispatch pallet" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +serde = { version = "1.0.101", optional = true } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/core" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } + +frame-benchmarking = { version = "2.0.0-rc4", default-features = false, path = "../benchmarking", optional = true } + +[dev-dependencies] +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0-rc4", path = "../balances" } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "sp-runtime/std", + "frame-support/std", + "frame-system/std", + "sp-io/std", + "sp-std/std" +] +runtime-benchmarks = [ + "frame-benchmarking", + "frame-support/runtime-benchmarks", +] diff --git a/frame/multisig/src/benchmarking.rs b/frame/multisig/src/benchmarking.rs new file mode 100644 index 0000000000000000000000000000000000000000..8113d179cd1576c43dfb0418dbcf94327f63b44b --- /dev/null +++ b/frame/multisig/src/benchmarking.rs @@ -0,0 +1,289 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Benchmarks for Multisig Pallet + +#![cfg(feature = "runtime-benchmarks")] + +use super::*; +use frame_system::RawOrigin; +use frame_benchmarking::{benchmarks, account}; +use sp_runtime::traits::Bounded; +use core::convert::TryInto; + +use crate::Module as Multisig; + +const SEED: u32 = 0; + +fn setup_multi(s: u32, z: u32) + -> Result<(Vec, Vec), &'static str> +{ + let mut signatories: Vec = Vec::new(); + for i in 0 .. s { + let signatory = account("signatory", i, SEED); + // Give them some balance for a possible deposit + let balance = BalanceOf::::max_value(); + T::Currency::make_free_balance_be(&signatory, balance); + signatories.push(signatory); + } + signatories.sort(); + // Must first convert to outer call type. + let call: ::Call = frame_system::Call::::remark(vec![0; z as usize]).into(); + let call_data = call.encode(); + return Ok((signatories, call_data)) +} + +benchmarks! { + _ { } + + as_multi_threshold_1 { + // Transaction Length + let z in 0 .. 10_000; + let max_signatories = T::MaxSignatories::get().into(); + let (mut signatories, _) = setup_multi::(max_signatories, z)?; + let call: ::Call = frame_system::Call::::remark(vec![0; z as usize]).into(); + let call_hash = call.using_encoded(blake2_256); + let multi_account_id = Multisig::::multi_account_id(&signatories, 1); + let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; + }: _(RawOrigin::Signed(caller.clone()), signatories, Box::new(call)) + verify { + // If the benchmark resolves, then the call was dispatched successfully. + } + + as_multi_create { + // Signatories, need at least 2 total people + let s in 2 .. T::MaxSignatories::get() as u32; + // Transaction Length + let z in 0 .. 10_000; + let (mut signatories, call) = setup_multi::(s, z)?; + let call_hash = blake2_256(&call); + let multi_account_id = Multisig::::multi_account_id(&signatories, s.try_into().unwrap()); + let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; + }: as_multi(RawOrigin::Signed(caller), s as u16, signatories, None, call, false, 0) + verify { + assert!(Multisigs::::contains_key(multi_account_id, call_hash)); + } + + as_multi_create_store { + // Signatories, need at least 2 total people + let s in 2 .. T::MaxSignatories::get() as u32; + // Transaction Length + let z in 0 .. 10_000; + let (mut signatories, call) = setup_multi::(s, z)?; + let call_hash = blake2_256(&call); + let multi_account_id = Multisig::::multi_account_id(&signatories, s.try_into().unwrap()); + let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; + T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + }: as_multi(RawOrigin::Signed(caller), s as u16, signatories, None, call, true, 0) + verify { + assert!(Multisigs::::contains_key(multi_account_id, call_hash)); + assert!(Calls::::contains_key(call_hash)); + } + + as_multi_approve { + // Signatories, need at least 3 people (so we don't complete the multisig) + let s in 3 .. T::MaxSignatories::get() as u32; + // Transaction Length + let z in 0 .. 10_000; + let (mut signatories, call) = setup_multi::(s, z)?; + let call_hash = blake2_256(&call); + let multi_account_id = Multisig::::multi_account_id(&signatories, s.try_into().unwrap()); + let mut signatories2 = signatories.clone(); + let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; + // before the call, get the timepoint + let timepoint = Multisig::::timepoint(); + // Create the multi, storing for worst case + Multisig::::as_multi(RawOrigin::Signed(caller).into(), s as u16, signatories, None, call.clone(), true, 0)?; + let caller2 = signatories2.remove(0); + }: as_multi(RawOrigin::Signed(caller2), s as u16, signatories2, Some(timepoint), call, false, 0) + verify { + let multisig = Multisigs::::get(multi_account_id, call_hash).ok_or("multisig not created")?; + assert_eq!(multisig.approvals.len(), 2); + } + + as_multi_complete { + // Signatories, need at least 2 people + let s in 2 .. T::MaxSignatories::get() as u32; + // Transaction Length + let z in 0 .. 10_000; + let (mut signatories, call) = setup_multi::(s, z)?; + let call_hash = blake2_256(&call); + let multi_account_id = Multisig::::multi_account_id(&signatories, s.try_into().unwrap()); + let mut signatories2 = signatories.clone(); + let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; + // before the call, get the timepoint + let timepoint = Multisig::::timepoint(); + // Create the multi, storing it for worst case + Multisig::::as_multi(RawOrigin::Signed(caller).into(), s as u16, signatories, None, call.clone(), true, 0)?; + // Everyone except the first person approves + for i in 1 .. s - 1 { + let mut signatories_loop = signatories2.clone(); + let caller_loop = signatories_loop.remove(i as usize); + let o = RawOrigin::Signed(caller_loop).into(); + Multisig::::as_multi(o, s as u16, signatories_loop, Some(timepoint), call.clone(), false, 0)?; + } + let caller2 = signatories2.remove(0); + assert!(Multisigs::::contains_key(&multi_account_id, call_hash)); + }: as_multi(RawOrigin::Signed(caller2), s as u16, signatories2, Some(timepoint), call, false, Weight::max_value()) + verify { + assert!(!Multisigs::::contains_key(&multi_account_id, call_hash)); + } + + approve_as_multi_create { + // Signatories, need at least 2 people + let s in 2 .. T::MaxSignatories::get() as u32; + // Transaction Length + let z in 0 .. 10_000; + let (mut signatories, call) = setup_multi::(s, z)?; + let multi_account_id = Multisig::::multi_account_id(&signatories, s.try_into().unwrap()); + let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; + let call_hash = blake2_256(&call); + // Create the multi + }: approve_as_multi(RawOrigin::Signed(caller), s as u16, signatories, None, call_hash, 0) + verify { + assert!(Multisigs::::contains_key(multi_account_id, call_hash)); + } + + approve_as_multi_approve { + // Signatories, need at least 2 people + let s in 2 .. T::MaxSignatories::get() as u32; + // Transaction Length + let z in 0 .. 10_000; + let (mut signatories, call) = setup_multi::(s, z)?; + let mut signatories2 = signatories.clone(); + let multi_account_id = Multisig::::multi_account_id(&signatories, s.try_into().unwrap()); + let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; + let call_hash = blake2_256(&call); + // before the call, get the timepoint + let timepoint = Multisig::::timepoint(); + // Create the multi + Multisig::::as_multi( + RawOrigin::Signed(caller.clone()).into(), + s as u16, + signatories, + None, + call.clone(), + false, + 0 + )?; + let caller2 = signatories2.remove(0); + }: approve_as_multi(RawOrigin::Signed(caller2), s as u16, signatories2, Some(timepoint), call_hash, 0) + verify { + let multisig = Multisigs::::get(multi_account_id, call_hash).ok_or("multisig not created")?; + assert_eq!(multisig.approvals.len(), 2); + } + + approve_as_multi_complete { + // Signatories, need at least 2 people + let s in 2 .. T::MaxSignatories::get() as u32; + // Transaction Length + let z in 0 .. 10_000; + let (mut signatories, call) = setup_multi::(s, z)?; + let multi_account_id = Multisig::::multi_account_id(&signatories, s.try_into().unwrap()); + let mut signatories2 = signatories.clone(); + let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; + T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + let call_hash = blake2_256(&call); + // before the call, get the timepoint + let timepoint = Multisig::::timepoint(); + // Create the multi + Multisig::::as_multi(RawOrigin::Signed(caller).into(), s as u16, signatories, None, call.clone(), true, 0)?; + // Everyone except the first person approves + for i in 1 .. s - 1 { + let mut signatories_loop = signatories2.clone(); + let caller_loop = signatories_loop.remove(i as usize); + let o = RawOrigin::Signed(caller_loop).into(); + Multisig::::as_multi(o, s as u16, signatories_loop, Some(timepoint), call.clone(), false, 0)?; + } + let caller2 = signatories2.remove(0); + assert!(Multisigs::::contains_key(&multi_account_id, call_hash)); + }: approve_as_multi( + RawOrigin::Signed(caller2), + s as u16, + signatories2, + Some(timepoint), + call_hash, + Weight::max_value() + ) + verify { + assert!(!Multisigs::::contains_key(multi_account_id, call_hash)); + } + + cancel_as_multi { + // Signatories, need at least 2 people + let s in 2 .. T::MaxSignatories::get() as u32; + // Transaction Length + let z in 0 .. 10_000; + let (mut signatories, call) = setup_multi::(s, z)?; + let multi_account_id = Multisig::::multi_account_id(&signatories, s.try_into().unwrap()); + let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; + let call_hash = blake2_256(&call); + let timepoint = Multisig::::timepoint(); + // Create the multi + let o = RawOrigin::Signed(caller.clone()).into(); + Multisig::::as_multi(o, s as u16, signatories.clone(), None, call.clone(), true, 0)?; + assert!(Multisigs::::contains_key(&multi_account_id, call_hash)); + }: _(RawOrigin::Signed(caller), s as u16, signatories, timepoint, call_hash) + verify { + assert!(!Multisigs::::contains_key(multi_account_id, call_hash)); + } + + cancel_as_multi_store { + // Signatories, need at least 2 people + let s in 2 .. T::MaxSignatories::get() as u32; + // Transaction Length + let z in 0 .. 10_000; + let (mut signatories, call) = setup_multi::(s, z)?; + let multi_account_id = Multisig::::multi_account_id(&signatories, s.try_into().unwrap()); + let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; + T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + let call_hash = blake2_256(&call); + let timepoint = Multisig::::timepoint(); + // Create the multi + let o = RawOrigin::Signed(caller.clone()).into(); + Multisig::::as_multi(o, s as u16, signatories.clone(), None, call.clone(), true, 0)?; + assert!(Multisigs::::contains_key(&multi_account_id, call_hash)); + assert!(Calls::::contains_key(call_hash)); + }: cancel_as_multi(RawOrigin::Signed(caller), s as u16, signatories, timepoint, call_hash) + verify { + assert!(!Multisigs::::contains_key(&multi_account_id, call_hash)); + assert!(!Calls::::contains_key(call_hash)); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::tests::{new_test_ext, Test}; + use frame_support::assert_ok; + + #[test] + fn test_benchmarks() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_as_multi_threshold_1::()); + assert_ok!(test_benchmark_as_multi_create::()); + assert_ok!(test_benchmark_as_multi_create_store::()); + assert_ok!(test_benchmark_as_multi_approve::()); + assert_ok!(test_benchmark_as_multi_complete::()); + assert_ok!(test_benchmark_approve_as_multi_create::()); + assert_ok!(test_benchmark_approve_as_multi_approve::()); + assert_ok!(test_benchmark_approve_as_multi_complete::()); + assert_ok!(test_benchmark_cancel_as_multi::()); + assert_ok!(test_benchmark_cancel_as_multi_store::()); + }); + } +} diff --git a/frame/multisig/src/lib.rs b/frame/multisig/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..35727a1cacbf2ee93547dac01fcfc882a501439d --- /dev/null +++ b/frame/multisig/src/lib.rs @@ -0,0 +1,734 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! # Multisig Module +//! A module for doing multisig dispatch. +//! +//! - [`multisig::Trait`](./trait.Trait.html) +//! - [`Call`](./enum.Call.html) +//! +//! ## Overview +//! +//! This module contains functionality for multi-signature dispatch, a (potentially) stateful +//! operation, allowing multiple signed +//! origins (accounts) to coordinate and dispatch a call from a well-known origin, derivable +//! deterministically from the set of account IDs and the threshold number of accounts from the +//! set that must approve it. In the case that the threshold is just one then this is a stateless +//! operation. This is useful for multisig wallets where cryptographic threshold signatures are +//! not available or desired. +//! +//! ## Interface +//! +//! ### Dispatchable Functions +//! +//! * `as_multi` - Approve and if possible dispatch a call from a composite origin formed from a +//! number of signed origins. +//! * `approve_as_multi` - Approve a call from a composite origin. +//! * `cancel_as_multi` - Cancel a call from a composite origin. +//! +//! [`Call`]: ./enum.Call.html +//! [`Trait`]: ./trait.Trait.html + +// Ensure we're `no_std` when compiling for Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::prelude::*; +use codec::{Encode, Decode}; +use sp_io::hashing::blake2_256; +use frame_support::{decl_module, decl_event, decl_error, decl_storage, Parameter, ensure, RuntimeDebug}; +use frame_support::{traits::{Get, ReservableCurrency, Currency}, + weights::{Weight, GetDispatchInfo, constants::{WEIGHT_PER_NANOS, WEIGHT_PER_MICROS}}, + dispatch::{DispatchResultWithPostInfo, DispatchErrorWithPostInfo, PostDispatchInfo}, +}; +use frame_system::{self as system, ensure_signed, RawOrigin}; +use sp_runtime::{DispatchError, DispatchResult, traits::{Dispatchable, Zero}}; + +mod tests; +mod benchmarking; + +type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; +/// Just a bunch of bytes, but they should decode to a valid `Call`. +pub type OpaqueCall = Vec; + +pub trait WeightInfo { + fn as_multi_threshold_1(z: u32, ) -> Weight; + fn as_multi_create(s: u32, z: u32, ) -> Weight; + fn as_multi_create_store(s: u32, z: u32, ) -> Weight; + fn as_multi_approve(s: u32, z: u32, ) -> Weight; + fn as_multi_complete(s: u32, z: u32, ) -> Weight; + fn approve_as_multi_create(s: u32, z: u32, ) -> Weight; + fn approve_as_multi_approve(s: u32, z: u32, ) -> Weight; + fn approve_as_multi_complete(s: u32, z: u32, ) -> Weight; + fn cancel_as_multi(s: u32, z: u32, ) -> Weight; + fn cancel_as_multi_store(s: u32, z: u32, ) -> Weight; +} + +impl WeightInfo for () { + fn as_multi_threshold_1(_z: u32, ) -> Weight { 1_000_000_000 } + fn as_multi_create(_s: u32, _z: u32, ) -> Weight { 1_000_000_000 } + fn as_multi_create_store(_s: u32, _z: u32, ) -> Weight { 1_000_000_000 } + fn as_multi_approve(_s: u32, _z: u32, ) -> Weight { 1_000_000_000 } + fn as_multi_complete(_s: u32, _z: u32, ) -> Weight { 1_000_000_000 } + fn approve_as_multi_create(_s: u32, _z: u32, ) -> Weight { 1_000_000_000 } + fn approve_as_multi_approve(_s: u32, _z: u32, ) -> Weight { 1_000_000_000 } + fn approve_as_multi_complete(_s: u32, _z: u32, ) -> Weight { 1_000_000_000 } + fn cancel_as_multi(_s: u32, _z: u32, ) -> Weight { 1_000_000_000 } + fn cancel_as_multi_store(_s: u32, _z: u32, ) -> Weight { 1_000_000_000 } +} + +/// Configuration trait. +pub trait Trait: frame_system::Trait { + /// The overarching event type. + type Event: From> + Into<::Event>; + + /// The overarching call type. + type Call: Parameter + Dispatchable + + GetDispatchInfo + From>; + + /// The currency mechanism. + type Currency: ReservableCurrency; + + /// The base amount of currency needed to reserve for creating a multisig execution or to store + /// a dispatch call for later. + /// + /// This is held for an additional storage item whose value size is + /// `4 + sizeof((BlockNumber, Balance, AccountId))` bytes and whose key size is + /// `32 + sizeof(AccountId)` bytes. + type DepositBase: Get>; + + /// The amount of currency needed per unit threshold when creating a multisig execution. + /// + /// This is held for adding 32 bytes more into a pre-existing storage value. + type DepositFactor: Get>; + + /// The maximum amount of signatories allowed in the multisig. + type MaxSignatories: Get; + + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; +} + +/// A global extrinsic index, formed as the extrinsic index within a block, together with that +/// block's height. This allows a transaction in which a multisig operation of a particular +/// composite was created to be uniquely identified. +#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, Default, RuntimeDebug)] +pub struct Timepoint { + /// The height of the chain at the point in time. + height: BlockNumber, + /// The index of the extrinsic at the point in time. + index: u32, +} + +/// An open multisig operation. +#[derive(Clone, Eq, PartialEq, Encode, Decode, Default, RuntimeDebug)] +pub struct Multisig { + /// The extrinsic when the multisig operation was opened. + when: Timepoint, + /// The amount held in reserve of the `depositor`, to be returned once the operation ends. + deposit: Balance, + /// The account who opened it (i.e. the first to approve it). + depositor: AccountId, + /// The approvals achieved so far, including the depositor. Always sorted. + approvals: Vec, +} + +decl_storage! { + trait Store for Module as Multisig { + /// The set of open multisig operations. + pub Multisigs: double_map + hasher(twox_64_concat) T::AccountId, hasher(blake2_128_concat) [u8; 32] + => Option, T::AccountId>>; + + pub Calls: map hasher(identity) [u8; 32] => Option<(OpaqueCall, T::AccountId, BalanceOf)>; + } +} + +decl_error! { + pub enum Error for Module { + /// Threshold must be 2 or greater. + MinimumThreshold, + /// Call is already approved by this signatory. + AlreadyApproved, + /// Call doesn't need any (more) approvals. + NoApprovalsNeeded, + /// There are too few signatories in the list. + TooFewSignatories, + /// There are too many signatories in the list. + TooManySignatories, + /// The signatories were provided out of order; they should be ordered. + SignatoriesOutOfOrder, + /// The sender was contained in the other signatories; it shouldn't be. + SenderInSignatories, + /// Multisig operation not found when attempting to cancel. + NotFound, + /// Only the account that originally created the multisig is able to cancel it. + NotOwner, + /// No timepoint was given, yet the multisig operation is already underway. + NoTimepoint, + /// A different timepoint was given to the multisig operation that is underway. + WrongTimepoint, + /// A timepoint was given, yet no multisig operation is underway. + UnexpectedTimepoint, + /// The maximum weight information provided was too low. + WeightTooLow, + /// The data to be stored is already stored. + AlreadyStored, + } +} + +decl_event! { + /// Events type. + pub enum Event where + AccountId = ::AccountId, + BlockNumber = ::BlockNumber, + CallHash = [u8; 32] + { + /// A new multisig operation has begun. First param is the account that is approving, + /// second is the multisig account, third is hash of the call. + NewMultisig(AccountId, AccountId, CallHash), + /// A multisig operation has been approved by someone. First param is the account that is + /// approving, third is the multisig account, fourth is hash of the call. + MultisigApproval(AccountId, Timepoint, AccountId, CallHash), + /// A multisig operation has been executed. First param is the account that is + /// approving, third is the multisig account, fourth is hash of the call to be executed. + MultisigExecuted(AccountId, Timepoint, AccountId, CallHash, DispatchResult), + /// A multisig operation has been cancelled. First param is the account that is + /// cancelling, third is the multisig account, fourth is hash of the call. + MultisigCancelled(AccountId, Timepoint, AccountId, CallHash), + } +} + +mod weight_of { + use super::*; + + /// - Base Weight: 33.72 + 0.002 * Z µs + /// - DB Weight: None + /// - Plus Call Weight + pub fn as_multi_threshold_1( + call_len: usize, + call_weight: Weight, + ) -> Weight { + (34 * WEIGHT_PER_MICROS) + .saturating_add((2 * WEIGHT_PER_NANOS).saturating_mul(call_len as Weight)) + .saturating_add(call_weight) + } + + /// - Base Weight: + /// - Create: 38.82 + 0.121 * S + .001 * Z µs + /// - Create w/ Store: 54.22 + 0.120 * S + .003 * Z µs + /// - Approve: 29.86 + 0.143 * S + .001 * Z µs + /// - Complete: 39.55 + 0.267 * S + .002 * Z µs + /// - DB Weight: + /// - Reads: Multisig Storage, [Caller Account], Calls, Depositor Account + /// - Writes: Multisig Storage, [Caller Account], Calls, Depositor Account + /// - Plus Call Weight + pub fn as_multi( + sig_len: usize, + call_len: usize, + call_weight: Weight, + calls_write: bool, + refunded: bool, + ) -> Weight { + call_weight + .saturating_add(55 * WEIGHT_PER_MICROS) + .saturating_add((250 * WEIGHT_PER_NANOS).saturating_mul(sig_len as Weight)) + .saturating_add((3 * WEIGHT_PER_NANOS).saturating_mul(call_len as Weight)) + .saturating_add(T::DbWeight::get().reads_writes(1, 1)) // Multisig read/write + .saturating_add(T::DbWeight::get().reads(1)) // Calls read + .saturating_add(T::DbWeight::get().writes(calls_write.into())) // Calls write + .saturating_add(T::DbWeight::get().reads_writes(refunded.into(), refunded.into())) // Deposit refunded + } +} + +enum CallOrHash { + Call(OpaqueCall, bool), + Hash([u8; 32]), +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + type Error = Error; + + /// Deposit one of this module's events by using the default implementation. + fn deposit_event() = default; + + /// Immediately dispatch a multi-signature call using a single approval from the caller. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// - `other_signatories`: The accounts (other than the sender) who are part of the + /// multi-signature, but do not participate in the approval process. + /// - `call`: The call to be executed. + /// + /// Result is equivalent to the dispatched result. + /// + /// # + /// O(Z + C) where Z is the length of the call and C its execution weight. + /// ------------------------------- + /// - Base Weight: 33.72 + 0.002 * Z µs + /// - DB Weight: None + /// - Plus Call Weight + /// # + #[weight = ( + weight_of::as_multi_threshold_1::( + call.using_encoded(|c| c.len()), + call.get_dispatch_info().weight + ), + call.get_dispatch_info().class, + )] + fn as_multi_threshold_1(origin, + other_signatories: Vec, + call: Box<::Call>, + ) -> DispatchResultWithPostInfo { + let who = ensure_signed(origin)?; + let max_sigs = T::MaxSignatories::get() as usize; + ensure!(!other_signatories.is_empty(), Error::::TooFewSignatories); + let other_signatories_len = other_signatories.len(); + ensure!(other_signatories_len < max_sigs, Error::::TooManySignatories); + let signatories = Self::ensure_sorted_and_insert(other_signatories, who.clone())?; + + let id = Self::multi_account_id(&signatories, 1); + + let call_len = call.using_encoded(|c| c.len()); + let result = call.dispatch(RawOrigin::Signed(id.clone()).into()); + + result.map(|post_dispatch_info| post_dispatch_info.actual_weight + .map(|actual_weight| weight_of::as_multi_threshold_1::( + call_len, + actual_weight, + )) + .into() + ).map_err(|err| match err.post_info.actual_weight { + Some(actual_weight) => { + let weight_used = weight_of::as_multi_threshold_1::( + call_len, + actual_weight, + ); + let post_info = Some(weight_used).into(); + let error = err.error.into(); + DispatchErrorWithPostInfo { post_info, error } + }, + None => err, + }) + } + + /// Register approval for a dispatch to be made from a deterministic composite account if + /// approved by a total of `threshold - 1` of `other_signatories`. + /// + /// If there are enough, then dispatch the call. + /// + /// Payment: `DepositBase` will be reserved if this is the first approval, plus + /// `threshold` times `DepositFactor`. It is returned once this dispatch happens or + /// is cancelled. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// - `threshold`: The total number of approvals for this dispatch before it is executed. + /// - `other_signatories`: The accounts (other than the sender) who can approve this + /// dispatch. May not be empty. + /// - `maybe_timepoint`: If this is the first approval, then this must be `None`. If it is + /// not the first approval, then it must be `Some`, with the timepoint (block number and + /// transaction index) of the first approval transaction. + /// - `call`: The call to be executed. + /// + /// NOTE: Unless this is the final approval, you will generally want to use + /// `approve_as_multi` instead, since it only requires a hash of the call. + /// + /// Result is equivalent to the dispatched result if `threshold` is exactly `1`. Otherwise + /// on success, result is `Ok` and the result from the interior call, if it was executed, + /// may be found in the deposited `MultisigExecuted` event. + /// + /// # + /// - `O(S + Z + Call)`. + /// - Up to one balance-reserve or unreserve operation. + /// - One passthrough operation, one insert, both `O(S)` where `S` is the number of + /// signatories. `S` is capped by `MaxSignatories`, with weight being proportional. + /// - One call encode & hash, both of complexity `O(Z)` where `Z` is tx-len. + /// - One encode & hash, both of complexity `O(S)`. + /// - Up to one binary search and insert (`O(logS + S)`). + /// - I/O: 1 read `O(S)`, up to 1 mutate `O(S)`. Up to one remove. + /// - One event. + /// - The weight of the `call`. + /// - Storage: inserts one item, value size bounded by `MaxSignatories`, with a + /// deposit taken for its lifetime of + /// `DepositBase + threshold * DepositFactor`. + /// ------------------------------- + /// - Base Weight: + /// - Create: 41.89 + 0.118 * S + .002 * Z µs + /// - Create w/ Store: 53.57 + 0.119 * S + .003 * Z µs + /// - Approve: 31.39 + 0.136 * S + .002 * Z µs + /// - Complete: 39.94 + 0.26 * S + .002 * Z µs + /// - DB Weight: + /// - Reads: Multisig Storage, [Caller Account], Calls (if `store_call`) + /// - Writes: Multisig Storage, [Caller Account], Calls (if `store_call`) + /// - Plus Call Weight + /// # + #[weight = weight_of::as_multi::( + other_signatories.len(), + call.len(), + *max_weight, + true, // assume worst case: calls write + true, // assume worst case: refunded + )] + fn as_multi(origin, + threshold: u16, + other_signatories: Vec, + maybe_timepoint: Option>, + call: OpaqueCall, + store_call: bool, + max_weight: Weight, + ) -> DispatchResultWithPostInfo { + let who = ensure_signed(origin)?; + Self::operate(who, threshold, other_signatories, maybe_timepoint, CallOrHash::Call(call, store_call), max_weight) + } + + /// Register approval for a dispatch to be made from a deterministic composite account if + /// approved by a total of `threshold - 1` of `other_signatories`. + /// + /// Payment: `DepositBase` will be reserved if this is the first approval, plus + /// `threshold` times `DepositFactor`. It is returned once this dispatch happens or + /// is cancelled. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// - `threshold`: The total number of approvals for this dispatch before it is executed. + /// - `other_signatories`: The accounts (other than the sender) who can approve this + /// dispatch. May not be empty. + /// - `maybe_timepoint`: If this is the first approval, then this must be `None`. If it is + /// not the first approval, then it must be `Some`, with the timepoint (block number and + /// transaction index) of the first approval transaction. + /// - `call_hash`: The hash of the call to be executed. + /// + /// NOTE: If this is the final approval, you will want to use `as_multi` instead. + /// + /// # + /// - `O(S)`. + /// - Up to one balance-reserve or unreserve operation. + /// - One passthrough operation, one insert, both `O(S)` where `S` is the number of + /// signatories. `S` is capped by `MaxSignatories`, with weight being proportional. + /// - One encode & hash, both of complexity `O(S)`. + /// - Up to one binary search and insert (`O(logS + S)`). + /// - I/O: 1 read `O(S)`, up to 1 mutate `O(S)`. Up to one remove. + /// - One event. + /// - Storage: inserts one item, value size bounded by `MaxSignatories`, with a + /// deposit taken for its lifetime of + /// `DepositBase + threshold * DepositFactor`. + /// ---------------------------------- + /// - Base Weight: + /// - Create: 44.71 + 0.088 * S + /// - Approve: 31.48 + 0.116 * S + /// - DB Weight: + /// - Read: Multisig Storage, [Caller Account] + /// - Write: Multisig Storage, [Caller Account] + /// # + #[weight = weight_of::as_multi::( + other_signatories.len(), + 0, // call_len is zero in this case + *max_weight, + true, // assume worst case: calls write + true, // assume worst case: refunded + )] + fn approve_as_multi(origin, + threshold: u16, + other_signatories: Vec, + maybe_timepoint: Option>, + call_hash: [u8; 32], + max_weight: Weight, + ) -> DispatchResultWithPostInfo { + let who = ensure_signed(origin)?; + Self::operate(who, threshold, other_signatories, maybe_timepoint, CallOrHash::Hash(call_hash), max_weight) + } + + /// Cancel a pre-existing, on-going multisig transaction. Any deposit reserved previously + /// for this operation will be unreserved on success. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// - `threshold`: The total number of approvals for this dispatch before it is executed. + /// - `other_signatories`: The accounts (other than the sender) who can approve this + /// dispatch. May not be empty. + /// - `timepoint`: The timepoint (block number and transaction index) of the first approval + /// transaction for this dispatch. + /// - `call_hash`: The hash of the call to be executed. + /// + /// # + /// - `O(S)`. + /// - Up to one balance-reserve or unreserve operation. + /// - One passthrough operation, one insert, both `O(S)` where `S` is the number of + /// signatories. `S` is capped by `MaxSignatories`, with weight being proportional. + /// - One encode & hash, both of complexity `O(S)`. + /// - One event. + /// - I/O: 1 read `O(S)`, one remove. + /// - Storage: removes one item. + /// ---------------------------------- + /// - Base Weight: 36.07 + 0.124 * S + /// - DB Weight: + /// - Read: Multisig Storage, [Caller Account], Refund Account, Calls + /// - Write: Multisig Storage, [Caller Account], Refund Account, Calls + /// # + #[weight = T::DbWeight::get().reads_writes(3, 3) + .saturating_add(36 * WEIGHT_PER_MICROS) + .saturating_add((other_signatories.len() as Weight).saturating_mul(100 * WEIGHT_PER_NANOS)) + ] + fn cancel_as_multi(origin, + threshold: u16, + other_signatories: Vec, + timepoint: Timepoint, + call_hash: [u8; 32], + ) -> DispatchResult { + let who = ensure_signed(origin)?; + ensure!(threshold >= 2, Error::::MinimumThreshold); + let max_sigs = T::MaxSignatories::get() as usize; + ensure!(!other_signatories.is_empty(), Error::::TooFewSignatories); + ensure!(other_signatories.len() < max_sigs, Error::::TooManySignatories); + let signatories = Self::ensure_sorted_and_insert(other_signatories, who.clone())?; + + let id = Self::multi_account_id(&signatories, threshold); + + let m = >::get(&id, call_hash) + .ok_or(Error::::NotFound)?; + ensure!(m.when == timepoint, Error::::WrongTimepoint); + ensure!(m.depositor == who, Error::::NotOwner); + + let _ = T::Currency::unreserve(&m.depositor, m.deposit); + >::remove(&id, &call_hash); + Self::clear_call(&call_hash); + + Self::deposit_event(RawEvent::MultisigCancelled(who, timepoint, id, call_hash)); + Ok(()) + } + } +} + +impl Module { + /// Derive a multi-account ID from the sorted list of accounts and the threshold that are + /// required. + /// + /// NOTE: `who` must be sorted. If it is not, then you'll get the wrong answer. + pub fn multi_account_id(who: &[T::AccountId], threshold: u16) -> T::AccountId { + let entropy = (b"modlpy/utilisuba", who, threshold).using_encoded(blake2_256); + T::AccountId::decode(&mut &entropy[..]).unwrap_or_default() + } + + fn operate( + who: T::AccountId, + threshold: u16, + other_signatories: Vec, + maybe_timepoint: Option>, + call_or_hash: CallOrHash, + max_weight: Weight, + ) -> DispatchResultWithPostInfo { + ensure!(threshold >= 2, Error::::MinimumThreshold); + let max_sigs = T::MaxSignatories::get() as usize; + ensure!(!other_signatories.is_empty(), Error::::TooFewSignatories); + let other_signatories_len = other_signatories.len(); + ensure!(other_signatories_len < max_sigs, Error::::TooManySignatories); + let signatories = Self::ensure_sorted_and_insert(other_signatories, who.clone())?; + + let id = Self::multi_account_id(&signatories, threshold); + + // Threshold > 1; this means it's a multi-step operation. We extract the `call_hash`. + let (call_hash, call_len, maybe_call, store) = match call_or_hash { + CallOrHash::Call(call, should_store) => { + let call_hash = blake2_256(&call); + let call_len = call.len(); + (call_hash, call_len, Some(call), should_store) + } + CallOrHash::Hash(h) => (h, 0, None, false), + }; + + // Branch on whether the operation has already started or not. + if let Some(mut m) = >::get(&id, call_hash) { + // Yes; ensure that the timepoint exists and agrees. + let timepoint = maybe_timepoint.ok_or(Error::::NoTimepoint)?; + ensure!(m.when == timepoint, Error::::WrongTimepoint); + + // Ensure that either we have not yet signed or that it is at threshold. + let mut approvals = m.approvals.len() as u16; + // We only bother with the approval if we're below threshold. + let maybe_pos = m.approvals.binary_search(&who).err().filter(|_| approvals < threshold); + // Bump approvals if not yet voted and the vote is needed. + if maybe_pos.is_some() { approvals += 1; } + + // We only bother fetching/decoding call if we know that we're ready to execute. + let maybe_approved_call = if approvals >= threshold { + Self::get_call(&call_hash, maybe_call.as_ref().map(|c| c.as_ref())) + } else { None }; + + if let Some(call) = maybe_approved_call { + // verify weight + ensure!(call.get_dispatch_info().weight <= max_weight, Error::::WeightTooLow); + + // Clean up storage before executing call to avoid an possibility of reentrancy + // attack. + >::remove(&id, call_hash); + Self::clear_call(&call_hash); + T::Currency::unreserve(&m.depositor, m.deposit); + + let result = call.dispatch(RawOrigin::Signed(id.clone()).into()); + Self::deposit_event(RawEvent::MultisigExecuted( + who, timepoint, id, call_hash, result.map(|_| ()).map_err(|e| e.error) + )); + Ok(get_result_weight(result).map(|actual_weight| weight_of::as_multi::( + other_signatories_len, + call_len, + actual_weight, + true, // Call is removed + true, // User is refunded + )).into()) + } else { + // We cannot dispatch the call now; either it isn't available, or it is, but we + // don't have threshold approvals even with our signature. + + // Store the call if desired. + let stored = if let Some(data) = maybe_call.filter(|_| store) { + Self::store_call_and_reserve(who.clone(), &call_hash, data, BalanceOf::::zero())?; + true + } else { + false + }; + + if let Some(pos) = maybe_pos { + // Record approval. + m.approvals.insert(pos, who.clone()); + >::insert(&id, call_hash, m); + Self::deposit_event(RawEvent::MultisigApproval(who, timepoint, id, call_hash)); + } else { + // If we already approved and didn't store the Call, then this was useless and + // we report an error. + ensure!(stored, Error::::AlreadyApproved); + } + + // Call is not made, so the actual weight does not include call + Ok(Some(weight_of::as_multi::( + other_signatories_len, + call_len, + 0, + stored, // Call stored? + false, // No refund + )).into()) + } + } else { + // Not yet started; there should be no timepoint given. + ensure!(maybe_timepoint.is_none(), Error::::UnexpectedTimepoint); + + // Just start the operation by recording it in storage. + let deposit = T::DepositBase::get() + T::DepositFactor::get() * threshold.into(); + + // Store the call if desired. + let stored = if let Some(data) = maybe_call.filter(|_| store) { + Self::store_call_and_reserve(who.clone(), &call_hash, data, deposit)?; + true + } else { + T::Currency::reserve(&who, deposit)?; + false + }; + + >::insert(&id, call_hash, Multisig { + when: Self::timepoint(), + deposit, + depositor: who.clone(), + approvals: vec![who.clone()], + }); + Self::deposit_event(RawEvent::NewMultisig(who, id, call_hash)); + // Call is not made, so we can return that weight + return Ok(Some(weight_of::as_multi::( + other_signatories_len, + call_len, + 0, + stored, // Call stored? + false, // No refund + )).into()) + } + } + + /// Place a call's encoded data in storage, reserving funds as appropriate. + /// + /// We store `data` here because storing `call` would result in needing another `.encode`. + /// + /// Returns a `bool` indicating whether the data did end up being stored. + fn store_call_and_reserve( + who: T::AccountId, + hash: &[u8; 32], + data: OpaqueCall, + other_deposit: BalanceOf, + ) -> DispatchResult { + ensure!(!Calls::::contains_key(hash), Error::::AlreadyStored); + let deposit = other_deposit + T::DepositBase::get() + + T::DepositFactor::get() * BalanceOf::::from(((data.len() + 31) / 32) as u32); + T::Currency::reserve(&who, deposit)?; + Calls::::insert(&hash, (data, who, deposit)); + Ok(()) + } + + /// Attempt to decode and return the call, provided by the user or from storage. + fn get_call(hash: &[u8; 32], maybe_known: Option<&[u8]>) -> Option<::Call> { + maybe_known.map_or_else(|| { + Calls::::get(hash).and_then(|(data, ..)| { + Decode::decode(&mut &data[..]).ok() + }) + }, |data| { + Decode::decode(&mut &data[..]).ok() + }) + } + + /// Attempt to remove a call from storage, returning any deposit on it to the owner. + fn clear_call(hash: &[u8; 32]) { + if let Some((_, who, deposit)) = Calls::::take(hash) { + T::Currency::unreserve(&who, deposit); + } + } + + /// The current `Timepoint`. + pub fn timepoint() -> Timepoint { + Timepoint { + height: >::block_number(), + index: >::extrinsic_index().unwrap_or_default(), + } + } + + /// Check that signatories is sorted and doesn't contain sender, then insert sender. + fn ensure_sorted_and_insert(other_signatories: Vec, who: T::AccountId) + -> Result, DispatchError> + { + let mut signatories = other_signatories; + let mut maybe_last = None; + let mut index = 0; + for item in signatories.iter() { + if let Some(last) = maybe_last { + ensure!(last < item, Error::::SignatoriesOutOfOrder); + } + if item <= &who { + ensure!(item != &who, Error::::SenderInSignatories); + index += 1; + } + maybe_last = Some(item); + } + signatories.insert(index, who); + Ok(signatories) + } +} + +/// Return the weight of a dispatch call result as an `Option`. +/// +/// Will return the weight regardless of what the state of the result is. +fn get_result_weight(result: DispatchResultWithPostInfo) -> Option { + match result { + Ok(post_info) => post_info.actual_weight, + Err(err) => err.post_info.actual_weight, + } +} diff --git a/frame/multisig/src/tests.rs b/frame/multisig/src/tests.rs new file mode 100644 index 0000000000000000000000000000000000000000..888dcecb3a8fd9cd1a8e8f60ede7f644828d0093 --- /dev/null +++ b/frame/multisig/src/tests.rs @@ -0,0 +1,577 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Tests for Multisig Pallet + +#![cfg(test)] + +use super::*; + +use frame_support::{ + assert_ok, assert_noop, impl_outer_origin, parameter_types, impl_outer_dispatch, + weights::Weight, impl_outer_event, traits::Filter, +}; +use sp_core::H256; +use sp_runtime::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; +use crate as multisig; + +impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} +} + +impl_outer_event! { + pub enum TestEvent for Test { + system, + pallet_balances, + multisig, + } +} +impl_outer_dispatch! { + pub enum Call for Test where origin: Origin { + frame_system::System, + pallet_balances::Balances, + multisig::Multisig, + } +} + +// For testing the pallet, we construct most of a mock runtime. This means +// first constructing a configuration type (`Test`) which `impl`s each of the +// configuration traits of pallets we want to use. +#[derive(Clone, Eq, PartialEq)] +pub struct Test; +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} +impl frame_system::Trait for Test { + type BaseCallFilter = TestBaseCallFilter; + 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 = TestEvent; + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); +} +parameter_types! { + pub const ExistentialDeposit: u64 = 1; +} +impl pallet_balances::Trait for Test { + type Balance = u64; + type Event = TestEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); +} +parameter_types! { + pub const DepositBase: u64 = 1; + pub const DepositFactor: u64 = 1; + pub const MaxSignatories: u16 = 3; +} +pub struct TestBaseCallFilter; +impl Filter for TestBaseCallFilter { + fn filter(c: &Call) -> bool { + match *c { + Call::Balances(_) => true, + // Needed for benchmarking + Call::System(frame_system::Call::remark(_)) => true, + _ => false, + } + } +} +impl Trait for Test { + type Event = TestEvent; + type Call = Call; + type Currency = Balances; + type DepositBase = DepositBase; + type DepositFactor = DepositFactor; + type MaxSignatories = MaxSignatories; + type WeightInfo = (); +} +type System = frame_system::Module; +type Balances = pallet_balances::Module; +type Multisig = Module; + +use pallet_balances::Call as BalancesCall; +use pallet_balances::Error as BalancesError; + +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + pallet_balances::GenesisConfig:: { + balances: vec![(1, 10), (2, 10), (3, 10), (4, 10), (5, 2)], + }.assimilate_storage(&mut t).unwrap(); + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext +} + +fn last_event() -> TestEvent { + system::Module::::events().pop().map(|e| e.event).expect("Event expected") +} + +fn expect_event>(e: E) { + assert_eq!(last_event(), e.into()); +} + +fn now() -> Timepoint { + Multisig::timepoint() +} + +#[test] +fn multisig_deposit_is_taken_and_returned() { + new_test_ext().execute_with(|| { + let multi = Multisig::multi_account_id(&[1, 2, 3][..], 2); + assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); + + let call = Call::Balances(BalancesCall::transfer(6, 15)); + let call_weight = call.get_dispatch_info().weight; + let data = call.encode(); + assert_ok!(Multisig::as_multi(Origin::signed(1), 2, vec![2, 3], None, data.clone(), false, 0)); + assert_eq!(Balances::free_balance(1), 2); + assert_eq!(Balances::reserved_balance(1), 3); + + assert_ok!(Multisig::as_multi(Origin::signed(2), 2, vec![1, 3], Some(now()), data, false, call_weight)); + assert_eq!(Balances::free_balance(1), 5); + assert_eq!(Balances::reserved_balance(1), 0); + }); +} + +#[test] +fn multisig_deposit_is_taken_and_returned_with_call_storage() { + new_test_ext().execute_with(|| { + let multi = Multisig::multi_account_id(&[1, 2, 3][..], 2); + assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); + + let call = Call::Balances(BalancesCall::transfer(6, 15)); + let call_weight = call.get_dispatch_info().weight; + let data = call.encode(); + let hash = blake2_256(&data); + assert_ok!(Multisig::as_multi(Origin::signed(1), 2, vec![2, 3], None, data, true, 0)); + assert_eq!(Balances::free_balance(1), 0); + assert_eq!(Balances::reserved_balance(1), 5); + + assert_ok!(Multisig::approve_as_multi(Origin::signed(2), 2, vec![1, 3], Some(now()), hash, call_weight)); + assert_eq!(Balances::free_balance(1), 5); + assert_eq!(Balances::reserved_balance(1), 0); + }); +} + +#[test] +fn multisig_deposit_is_taken_and_returned_with_alt_call_storage() { + new_test_ext().execute_with(|| { + let multi = Multisig::multi_account_id(&[1, 2, 3][..], 3); + assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); + + let call = Call::Balances(BalancesCall::transfer(6, 15)); + let call_weight = call.get_dispatch_info().weight; + let data = call.encode(); + let hash = blake2_256(&data); + + assert_ok!(Multisig::approve_as_multi(Origin::signed(1), 3, vec![2, 3], None, hash.clone(), 0)); + assert_eq!(Balances::free_balance(1), 1); + assert_eq!(Balances::reserved_balance(1), 4); + + assert_ok!(Multisig::as_multi(Origin::signed(2), 3, vec![1, 3], Some(now()), data, true, 0)); + assert_eq!(Balances::free_balance(2), 3); + assert_eq!(Balances::reserved_balance(2), 2); + assert_eq!(Balances::free_balance(1), 1); + assert_eq!(Balances::reserved_balance(1), 4); + + assert_ok!(Multisig::approve_as_multi(Origin::signed(3), 3, vec![1, 2], Some(now()), hash, call_weight)); + assert_eq!(Balances::free_balance(1), 5); + assert_eq!(Balances::reserved_balance(1), 0); + assert_eq!(Balances::free_balance(2), 5); + assert_eq!(Balances::reserved_balance(2), 0); + }); +} + +#[test] +fn cancel_multisig_returns_deposit() { + new_test_ext().execute_with(|| { + let call = Call::Balances(BalancesCall::transfer(6, 15)).encode(); + let hash = blake2_256(&call); + assert_ok!(Multisig::approve_as_multi(Origin::signed(1), 3, vec![2, 3], None, hash.clone(), 0)); + assert_ok!(Multisig::approve_as_multi(Origin::signed(2), 3, vec![1, 3], Some(now()), hash.clone(), 0)); + assert_eq!(Balances::free_balance(1), 6); + assert_eq!(Balances::reserved_balance(1), 4); + assert_ok!( + Multisig::cancel_as_multi(Origin::signed(1), 3, vec![2, 3], now(), hash.clone()), + ); + assert_eq!(Balances::free_balance(1), 10); + assert_eq!(Balances::reserved_balance(1), 0); + }); +} + +#[test] +fn timepoint_checking_works() { + new_test_ext().execute_with(|| { + let multi = Multisig::multi_account_id(&[1, 2, 3][..], 2); + assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); + + let call = Call::Balances(BalancesCall::transfer(6, 15)).encode(); + let hash = blake2_256(&call); + + assert_noop!( + Multisig::approve_as_multi(Origin::signed(2), 2, vec![1, 3], Some(now()), hash.clone(), 0), + Error::::UnexpectedTimepoint, + ); + + assert_ok!(Multisig::approve_as_multi(Origin::signed(1), 2, vec![2, 3], None, hash, 0)); + + assert_noop!( + Multisig::as_multi(Origin::signed(2), 2, vec![1, 3], None, call.clone(), false, 0), + Error::::NoTimepoint, + ); + let later = Timepoint { index: 1, .. now() }; + assert_noop!( + Multisig::as_multi(Origin::signed(2), 2, vec![1, 3], Some(later), call.clone(), false, 0), + Error::::WrongTimepoint, + ); + }); +} + +#[test] +fn multisig_2_of_3_works_with_call_storing() { + new_test_ext().execute_with(|| { + let multi = Multisig::multi_account_id(&[1, 2, 3][..], 2); + assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); + + let call = Call::Balances(BalancesCall::transfer(6, 15)); + let call_weight = call.get_dispatch_info().weight; + let data = call.encode(); + let hash = blake2_256(&data); + assert_ok!(Multisig::as_multi(Origin::signed(1), 2, vec![2, 3], None, data, true, 0)); + assert_eq!(Balances::free_balance(6), 0); + + assert_ok!(Multisig::approve_as_multi(Origin::signed(2), 2, vec![1, 3], Some(now()), hash, call_weight)); + assert_eq!(Balances::free_balance(6), 15); + }); +} + +#[test] +fn multisig_2_of_3_works() { + new_test_ext().execute_with(|| { + let multi = Multisig::multi_account_id(&[1, 2, 3][..], 2); + assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); + + let call = Call::Balances(BalancesCall::transfer(6, 15)); + let call_weight = call.get_dispatch_info().weight; + let data = call.encode(); + let hash = blake2_256(&data); + assert_ok!(Multisig::approve_as_multi(Origin::signed(1), 2, vec![2, 3], None, hash, 0)); + assert_eq!(Balances::free_balance(6), 0); + + assert_ok!(Multisig::as_multi(Origin::signed(2), 2, vec![1, 3], Some(now()), data, false, call_weight)); + assert_eq!(Balances::free_balance(6), 15); + }); +} + +#[test] +fn multisig_3_of_3_works() { + new_test_ext().execute_with(|| { + let multi = Multisig::multi_account_id(&[1, 2, 3][..], 3); + assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); + + let call = Call::Balances(BalancesCall::transfer(6, 15)); + let call_weight = call.get_dispatch_info().weight; + let data = call.encode(); + let hash = blake2_256(&data); + assert_ok!(Multisig::approve_as_multi(Origin::signed(1), 3, vec![2, 3], None, hash.clone(), 0)); + assert_ok!(Multisig::approve_as_multi(Origin::signed(2), 3, vec![1, 3], Some(now()), hash.clone(), 0)); + assert_eq!(Balances::free_balance(6), 0); + + assert_ok!(Multisig::as_multi(Origin::signed(3), 3, vec![1, 2], Some(now()), data, false, call_weight)); + assert_eq!(Balances::free_balance(6), 15); + }); +} + +#[test] +fn cancel_multisig_works() { + new_test_ext().execute_with(|| { + let call = Call::Balances(BalancesCall::transfer(6, 15)).encode(); + let hash = blake2_256(&call); + assert_ok!(Multisig::approve_as_multi(Origin::signed(1), 3, vec![2, 3], None, hash.clone(), 0)); + assert_ok!(Multisig::approve_as_multi(Origin::signed(2), 3, vec![1, 3], Some(now()), hash.clone(), 0)); + assert_noop!( + Multisig::cancel_as_multi(Origin::signed(2), 3, vec![1, 3], now(), hash.clone()), + Error::::NotOwner, + ); + assert_ok!( + Multisig::cancel_as_multi(Origin::signed(1), 3, vec![2, 3], now(), hash.clone()), + ); + }); +} + +#[test] +fn cancel_multisig_with_call_storage_works() { + new_test_ext().execute_with(|| { + let call = Call::Balances(BalancesCall::transfer(6, 15)).encode(); + let hash = blake2_256(&call); + assert_ok!(Multisig::as_multi(Origin::signed(1), 3, vec![2, 3], None, call, true, 0)); + assert_eq!(Balances::free_balance(1), 4); + assert_ok!(Multisig::approve_as_multi(Origin::signed(2), 3, vec![1, 3], Some(now()), hash.clone(), 0)); + assert_noop!( + Multisig::cancel_as_multi(Origin::signed(2), 3, vec![1, 3], now(), hash.clone()), + Error::::NotOwner, + ); + assert_ok!( + Multisig::cancel_as_multi(Origin::signed(1), 3, vec![2, 3], now(), hash.clone()), + ); + assert_eq!(Balances::free_balance(1), 10); + }); +} + +#[test] +fn cancel_multisig_with_alt_call_storage_works() { + new_test_ext().execute_with(|| { + let call = Call::Balances(BalancesCall::transfer(6, 15)).encode(); + let hash = blake2_256(&call); + assert_ok!(Multisig::approve_as_multi(Origin::signed(1), 3, vec![2, 3], None, hash.clone(), 0)); + assert_eq!(Balances::free_balance(1), 6); + assert_ok!(Multisig::as_multi(Origin::signed(2), 3, vec![1, 3], Some(now()), call, true, 0)); + assert_eq!(Balances::free_balance(2), 8); + assert_ok!(Multisig::cancel_as_multi(Origin::signed(1), 3, vec![2, 3], now(), hash)); + assert_eq!(Balances::free_balance(1), 10); + assert_eq!(Balances::free_balance(2), 10); + }); +} + +#[test] +fn multisig_2_of_3_as_multi_works() { + new_test_ext().execute_with(|| { + let multi = Multisig::multi_account_id(&[1, 2, 3][..], 2); + assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); + + let call = Call::Balances(BalancesCall::transfer(6, 15)); + let call_weight = call.get_dispatch_info().weight; + let data = call.encode(); + assert_ok!(Multisig::as_multi(Origin::signed(1), 2, vec![2, 3], None, data.clone(), false, 0)); + assert_eq!(Balances::free_balance(6), 0); + + assert_ok!(Multisig::as_multi(Origin::signed(2), 2, vec![1, 3], Some(now()), data, false, call_weight)); + assert_eq!(Balances::free_balance(6), 15); + }); +} + +#[test] +fn multisig_2_of_3_as_multi_with_many_calls_works() { + new_test_ext().execute_with(|| { + let multi = Multisig::multi_account_id(&[1, 2, 3][..], 2); + assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); + + let call1 = Call::Balances(BalancesCall::transfer(6, 10)); + let call1_weight = call1.get_dispatch_info().weight; + let data1 = call1.encode(); + let call2 = Call::Balances(BalancesCall::transfer(7, 5)); + let call2_weight = call2.get_dispatch_info().weight; + let data2 = call2.encode(); + + assert_ok!(Multisig::as_multi(Origin::signed(1), 2, vec![2, 3], None, data1.clone(), false, 0)); + assert_ok!(Multisig::as_multi(Origin::signed(2), 2, vec![1, 3], None, data2.clone(), false, 0)); + assert_ok!(Multisig::as_multi(Origin::signed(3), 2, vec![1, 2], Some(now()), data1, false, call1_weight)); + assert_ok!(Multisig::as_multi(Origin::signed(3), 2, vec![1, 2], Some(now()), data2, false, call2_weight)); + + assert_eq!(Balances::free_balance(6), 10); + assert_eq!(Balances::free_balance(7), 5); + }); +} + +#[test] +fn multisig_2_of_3_cannot_reissue_same_call() { + new_test_ext().execute_with(|| { + let multi = Multisig::multi_account_id(&[1, 2, 3][..], 2); + assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); + + let call = Call::Balances(BalancesCall::transfer(6, 10)); + let call_weight = call.get_dispatch_info().weight; + let data = call.encode(); + let hash = blake2_256(&data); + assert_ok!(Multisig::as_multi(Origin::signed(1), 2, vec![2, 3], None, data.clone(), false, 0)); + assert_ok!(Multisig::as_multi(Origin::signed(2), 2, vec![1, 3], Some(now()), data.clone(), false, call_weight)); + assert_eq!(Balances::free_balance(multi), 5); + + assert_ok!(Multisig::as_multi(Origin::signed(1), 2, vec![2, 3], None, data.clone(), false, 0)); + assert_ok!(Multisig::as_multi(Origin::signed(3), 2, vec![1, 2], Some(now()), data.clone(), false, call_weight)); + + let err = DispatchError::from(BalancesError::::InsufficientBalance).stripped(); + expect_event(RawEvent::MultisigExecuted(3, now(), multi, hash, Err(err))); + }); +} + +#[test] +fn minimum_threshold_check_works() { + new_test_ext().execute_with(|| { + let call = Call::Balances(BalancesCall::transfer(6, 15)).encode(); + assert_noop!( + Multisig::as_multi(Origin::signed(1), 0, vec![2], None, call.clone(), false, 0), + Error::::MinimumThreshold, + ); + assert_noop!( + Multisig::as_multi(Origin::signed(1), 1, vec![2], None, call.clone(), false, 0), + Error::::MinimumThreshold, + ); + }); +} + +#[test] +fn too_many_signatories_fails() { + new_test_ext().execute_with(|| { + let call = Call::Balances(BalancesCall::transfer(6, 15)).encode(); + assert_noop!( + Multisig::as_multi(Origin::signed(1), 2, vec![2, 3, 4], None, call.clone(), false, 0), + Error::::TooManySignatories, + ); + }); +} + +#[test] +fn duplicate_approvals_are_ignored() { + new_test_ext().execute_with(|| { + let call = Call::Balances(BalancesCall::transfer(6, 15)).encode(); + let hash = blake2_256(&call); + assert_ok!(Multisig::approve_as_multi(Origin::signed(1), 2, vec![2, 3], None, hash.clone(), 0)); + assert_noop!( + Multisig::approve_as_multi(Origin::signed(1), 2, vec![2, 3], Some(now()), hash.clone(), 0), + Error::::AlreadyApproved, + ); + assert_ok!(Multisig::approve_as_multi(Origin::signed(2), 2, vec![1, 3], Some(now()), hash.clone(), 0)); + assert_noop!( + Multisig::approve_as_multi(Origin::signed(3), 2, vec![1, 2], Some(now()), hash.clone(), 0), + Error::::AlreadyApproved, + ); + }); +} + +#[test] +fn multisig_1_of_3_works() { + new_test_ext().execute_with(|| { + let multi = Multisig::multi_account_id(&[1, 2, 3][..], 1); + assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); + + let call = Call::Balances(BalancesCall::transfer(6, 15)).encode(); + let hash = blake2_256(&call); + assert_noop!( + Multisig::approve_as_multi(Origin::signed(1), 1, vec![2, 3], None, hash.clone(), 0), + Error::::MinimumThreshold, + ); + assert_noop!( + Multisig::as_multi(Origin::signed(1), 1, vec![2, 3], None, call.clone(), false, 0), + Error::::MinimumThreshold, + ); + let boxed_call = Box::new(Call::Balances(BalancesCall::transfer(6, 15))); + assert_ok!(Multisig::as_multi_threshold_1(Origin::signed(1), vec![2, 3], boxed_call)); + + assert_eq!(Balances::free_balance(6), 15); + }); +} + +#[test] +fn multisig_filters() { + new_test_ext().execute_with(|| { + let call = Box::new(Call::System(frame_system::Call::set_code(vec![]))); + assert_noop!( + Multisig::as_multi_threshold_1(Origin::signed(1), vec![2], call.clone()), + DispatchError::BadOrigin, + ); + }); +} + +#[test] +fn weight_check_works() { + new_test_ext().execute_with(|| { + let multi = Multisig::multi_account_id(&[1, 2, 3][..], 2); + assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); + + let call = Call::Balances(BalancesCall::transfer(6, 15)); + let data = call.encode(); + assert_ok!(Multisig::as_multi(Origin::signed(1), 2, vec![2, 3], None, data.clone(), false, 0)); + assert_eq!(Balances::free_balance(6), 0); + + assert_noop!( + Multisig::as_multi(Origin::signed(2), 2, vec![1, 3], Some(now()), data, false, 0), + Error::::WeightTooLow, + ); + }); +} + +#[test] +fn multisig_handles_no_preimage_after_all_approve() { + // This test checks the situation where everyone approves a multi-sig, but no-one provides the call data. + // In the end, any of the multisig callers can approve again with the call data and the call will go through. + new_test_ext().execute_with(|| { + let multi = Multisig::multi_account_id(&[1, 2, 3][..], 3); + assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); + + let call = Call::Balances(BalancesCall::transfer(6, 15)); + let call_weight = call.get_dispatch_info().weight; + let data = call.encode(); + let hash = blake2_256(&data); + assert_ok!(Multisig::approve_as_multi(Origin::signed(1), 3, vec![2, 3], None, hash.clone(), 0)); + assert_ok!(Multisig::approve_as_multi(Origin::signed(2), 3, vec![1, 3], Some(now()), hash.clone(), 0)); + assert_ok!(Multisig::approve_as_multi(Origin::signed(3), 3, vec![1, 2], Some(now()), hash.clone(), 0)); + assert_eq!(Balances::free_balance(6), 0); + + assert_ok!(Multisig::as_multi(Origin::signed(3), 3, vec![1, 2], Some(now()), data, false, call_weight)); + assert_eq!(Balances::free_balance(6), 15); + }); +} diff --git a/frame/nicks/Cargo.toml b/frame/nicks/Cargo.toml index ea88021d2528b8897c02a721ffc6fcf64564358d..143e5b198e15861101d77f5e9daf7aebb3ade915 100644 --- a/frame/nicks/Cargo.toml +++ b/frame/nicks/Cargo.toml @@ -1,25 +1,28 @@ [package] name = "pallet-nicks" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for nick management" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -pallet-balances = { version = "2.0.0-alpha.5", path = "../balances" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0-rc4", path = "../balances" } [features] default = ["std"] @@ -32,6 +35,3 @@ std = [ "frame-support/std", "frame-system/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/nicks/src/lib.rs b/frame/nicks/src/lib.rs index ae005e2500b85ab3da72aa94746681d1eaa01f3a..970c070b2e3d7794bf7b47fa81951a28f88c5087 100644 --- a/frame/nicks/src/lib.rs +++ b/frame/nicks/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Nicks Module //! @@ -45,9 +46,8 @@ use sp_runtime::{ use frame_support::{ decl_module, decl_event, decl_storage, ensure, decl_error, traits::{Currency, EnsureOrigin, ReservableCurrency, OnUnbalanced, Get}, - weights::SimpleDispatchInfo, }; -use frame_system::{self as system, ensure_signed, ensure_root}; +use frame_system::ensure_signed; type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; @@ -110,7 +110,7 @@ decl_error! { } decl_module! { - // Simple declaration of the `Module` type. Lets the macro know what it's working on. + /// Nicks module declaration. pub struct Module for enum Call where origin: T::Origin { type Error = Error; @@ -141,7 +141,7 @@ decl_module! { /// - One storage read/write. /// - One event. /// # - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + #[weight = 50_000_000] fn set_name(origin, name: Vec) { let sender = ensure_signed(origin)?; @@ -171,7 +171,7 @@ decl_module! { /// - One storage read/write. /// - One event. /// # - #[weight = SimpleDispatchInfo::FixedNormal(70_000)] + #[weight = 70_000_000] fn clear_name(origin) { let sender = ensure_signed(origin)?; @@ -187,7 +187,7 @@ decl_module! { /// 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`. + /// The dispatch origin for this call must match `T::ForceOrigin`. /// /// # /// - O(1). @@ -195,11 +195,9 @@ decl_module! { /// - One storage read/write. /// - One event. /// # - #[weight = SimpleDispatchInfo::FixedNormal(70_000)] + #[weight = 70_000_000] fn kill_name(origin, target: ::Source) { - T::ForceOrigin::try_origin(origin) - .map(|_| ()) - .or_else(ensure_root)?; + T::ForceOrigin::ensure_origin(origin)?; // Figure out who we're meant to be clearing. let target = T::Lookup::lookup(target)?; @@ -215,7 +213,7 @@ decl_module! { /// /// No length checking is done on the name. /// - /// The dispatch origin for this call must be _Root_ or match `T::ForceOrigin`. + /// The dispatch origin for this call must match `T::ForceOrigin`. /// /// # /// - O(1). @@ -223,11 +221,9 @@ decl_module! { /// - One storage read/write. /// - One event. /// # - #[weight = SimpleDispatchInfo::FixedNormal(70_000)] + #[weight = 70_000_000] fn force_name(origin, target: ::Source, name: Vec) { - T::ForceOrigin::try_origin(origin) - .map(|_| ()) - .or_else(ensure_root)?; + T::ForceOrigin::ensure_origin(origin)?; let target = T::Lookup::lookup(target)?; let deposit = >::get(&target).map(|x| x.1).unwrap_or_else(Zero::zero); @@ -248,8 +244,6 @@ mod tests { }; use sp_core::H256; use frame_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 sp_runtime::{ Perbill, testing::Header, traits::{BlakeTwo256, IdentityLookup, BadOrigin}, }; @@ -258,9 +252,6 @@ mod tests { pub enum Origin for Test where system = frame_system {} } - // For testing the pallet, we construct most of a mock runtime. This means - // first constructing a configuration type (`Test`) which `impl`s each of the - // configuration traits of pallets we want to use. #[derive(Clone, Eq, PartialEq)] pub struct Test; parameter_types! { @@ -270,6 +261,7 @@ mod tests { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -282,6 +274,10 @@ mod tests { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -289,6 +285,7 @@ mod tests { type AccountData = pallet_balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } parameter_types! { pub const ExistentialDeposit: u64 = 1; @@ -299,6 +296,7 @@ mod tests { type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; + type WeightInfo = (); } parameter_types! { pub const ReservationFee: u64 = 2; @@ -321,11 +319,8 @@ mod tests { type Balances = pallet_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() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - // We use default for brevity, but you can configure as desired if needed. pallet_balances::GenesisConfig:: { balances: vec![ (1, 10), diff --git a/frame/offences/Cargo.toml b/frame/offences/Cargo.toml index b858c03ba5ac0b58c038422e8d077ba7c278ddc6..74487ba16394340e628046332c95181b769daa42 100644 --- a/frame/offences/Cargo.toml +++ b/frame/offences/Cargo.toml @@ -1,26 +1,29 @@ [package] name = "pallet-offences" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME offences pallet" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -pallet-balances = { version = "2.0.0-alpha.5", default-features = false, path = "../balances" } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } +pallet-balances = { version = "2.0.0-rc4", default-features = false, path = "../balances" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } serde = { version = "1.0.101", optional = true } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -sp-staking = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/staking" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +sp-staking = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/staking" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } [dev-dependencies] -sp-io = { version = "2.0.0-alpha.5", path = "../../primitives/io" } -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } +sp-io = { version = "2.0.0-rc4", path = "../../primitives/io" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } [features] default = ["std"] @@ -34,6 +37,4 @@ std = [ "frame-support/std", "frame-system/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +runtime-benchmarks = [] diff --git a/frame/offences/benchmarking/Cargo.toml b/frame/offences/benchmarking/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..b942a98baa2c38b03eab74ef8b0c67bf725bba0f --- /dev/null +++ b/frame/offences/benchmarking/Cargo.toml @@ -0,0 +1,54 @@ +[package] +name = "pallet-offences-benchmarking" +version = "2.0.0-rc4" +authors = ["Parity Technologies "] +edition = "2018" +license = "Apache-2.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +description = "FRAME offences pallet benchmarking" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +frame-benchmarking = { version = "2.0.0-rc4", default-features = false, path = "../../benchmarking" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../../system" } +pallet-babe = { version = "2.0.0-rc4", default-features = false, path = "../../babe" } +pallet-balances = { version = "2.0.0-rc4", default-features = false, path = "../../balances" } +pallet-grandpa = { version = "2.0.0-rc4", default-features = false, path = "../../grandpa" } +pallet-im-online = { version = "2.0.0-rc4", default-features = false, path = "../../im-online" } +pallet-offences = { version = "2.0.0-rc4", default-features = false, features = ["runtime-benchmarks"], path = "../../offences" } +pallet-session = { version = "2.0.0-rc4", default-features = false, path = "../../session" } +pallet-staking = { version = "2.0.0-rc4", default-features = false, features = ["runtime-benchmarks"], path = "../../staking" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/runtime" } +sp-staking = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/staking" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/std" } + +[dev-dependencies] +codec = { package = "parity-scale-codec", version = "1.3.1", features = ["derive"] } +pallet-staking-reward-curve = { version = "2.0.0-rc4", path = "../../staking/reward-curve" } +pallet-timestamp = { version = "2.0.0-rc4", path = "../../timestamp" } +serde = { version = "1.0.101" } +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } +sp-io = { version = "2.0.0-rc4", path = "../../../primitives/io" } + +[features] +default = ["std"] +std = [ + "frame-benchmarking/std", + "frame-support/std", + "frame-system/std", + "pallet-babe/std", + "pallet-balances/std", + "pallet-grandpa/std", + "pallet-im-online/std", + "pallet-offences/std", + "pallet-session/std", + "pallet-staking/std", + "sp-runtime/std", + "sp-staking/std", + "sp-std/std", +] diff --git a/frame/offences/benchmarking/src/lib.rs b/frame/offences/benchmarking/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..d0cc1bce225b5c8a854ab7b66f1e7da69450fe87 --- /dev/null +++ b/frame/offences/benchmarking/src/lib.rs @@ -0,0 +1,415 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Offences pallet benchmarking. + +#![cfg_attr(not(feature = "std"), no_std)] + +mod mock; + +use sp_std::prelude::*; +use sp_std::vec; + +use frame_system::{RawOrigin, Module as System, Trait as SystemTrait}; +use frame_benchmarking::{benchmarks, account}; +use frame_support::traits::{Currency, OnInitialize}; + +use sp_runtime::{Perbill, traits::{Convert, StaticLookup, Saturating, UniqueSaturatedInto}}; +use sp_staking::offence::{ReportOffence, Offence, OffenceDetails}; + +use pallet_balances::{Trait as BalancesTrait}; +use pallet_babe::BabeEquivocationOffence; +use pallet_grandpa::{GrandpaEquivocationOffence, GrandpaTimeSlot}; +use pallet_im_online::{Trait as ImOnlineTrait, Module as ImOnline, UnresponsivenessOffence}; +use pallet_offences::{Trait as OffencesTrait, Module as Offences}; +use pallet_session::historical::{Trait as HistoricalTrait, IdentificationTuple}; +use pallet_session::{Trait as SessionTrait, SessionManager}; +use pallet_staking::{ + Module as Staking, Trait as StakingTrait, RewardDestination, ValidatorPrefs, + Exposure, IndividualExposure, ElectionStatus, MAX_NOMINATIONS, Event as StakingEvent +}; + +const SEED: u32 = 0; + +const MAX_REPORTERS: u32 = 100; +const MAX_OFFENDERS: u32 = 100; +const MAX_NOMINATORS: u32 = 100; +const MAX_DEFERRED_OFFENCES: u32 = 100; + +pub struct Module(Offences); + +pub trait Trait: + SessionTrait + + StakingTrait + + OffencesTrait + + ImOnlineTrait + + HistoricalTrait + + BalancesTrait + + IdTupleConvert +{} + +/// A helper trait to make sure we can convert `IdentificationTuple` coming from historical +/// and the one required by offences. +pub trait IdTupleConvert { + /// Convert identification tuple from `historical` trait to the one expected by `offences`. + fn convert(id: IdentificationTuple) -> ::IdentificationTuple; +} + +impl IdTupleConvert for T where + ::IdentificationTuple: From> +{ + fn convert(id: IdentificationTuple) -> ::IdentificationTuple { + id.into() + } +} + +type LookupSourceOf = <::Lookup as StaticLookup>::Source; +type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; + +struct Offender { + pub controller: T::AccountId, + pub stash: T::AccountId, + pub nominator_stashes: Vec, +} + +fn bond_amount() -> BalanceOf { + T::Currency::minimum_balance().saturating_mul(10_000.into()) +} + +fn create_offender(n: u32, nominators: u32) -> Result, &'static str> { + let stash: T::AccountId = account("stash", n, SEED); + let controller: T::AccountId = account("controller", n, SEED); + let controller_lookup: LookupSourceOf = T::Lookup::unlookup(controller.clone()); + let reward_destination = RewardDestination::Staked; + let raw_amount = bond_amount::(); + // add twice as much balance to prevent the account from being killed. + let free_amount = raw_amount.saturating_mul(2.into()); + T::Currency::make_free_balance_be(&stash, free_amount); + let amount: BalanceOf = raw_amount.into(); + Staking::::bond( + RawOrigin::Signed(stash.clone()).into(), + controller_lookup.clone(), + amount.clone(), + reward_destination.clone(), + )?; + + let validator_prefs = ValidatorPrefs { + commission: Perbill::from_percent(50), + }; + Staking::::validate(RawOrigin::Signed(controller.clone()).into(), validator_prefs)?; + + let mut individual_exposures = vec![]; + let mut nominator_stashes = vec![]; + // Create n nominators + for i in 0 .. nominators { + let nominator_stash: T::AccountId = account("nominator stash", n * MAX_NOMINATORS + i, SEED); + let nominator_controller: T::AccountId = account("nominator controller", n * MAX_NOMINATORS + i, SEED); + let nominator_controller_lookup: LookupSourceOf = T::Lookup::unlookup(nominator_controller.clone()); + T::Currency::make_free_balance_be(&nominator_stash, free_amount.into()); + + Staking::::bond( + RawOrigin::Signed(nominator_stash.clone()).into(), + nominator_controller_lookup.clone(), + amount.clone(), + reward_destination, + )?; + + let selected_validators: Vec> = vec![controller_lookup.clone()]; + Staking::::nominate(RawOrigin::Signed(nominator_controller.clone()).into(), selected_validators)?; + + individual_exposures.push(IndividualExposure { + who: nominator_stash.clone(), + value: amount.clone(), + }); + nominator_stashes.push(nominator_stash.clone()); + } + + let exposure = Exposure { + total: amount.clone() * n.into(), + own: amount, + others: individual_exposures, + }; + let current_era = 0u32; + Staking::::add_era_stakers(current_era.into(), stash.clone().into(), exposure); + + Ok(Offender { controller, stash, nominator_stashes }) +} + +fn make_offenders(num_offenders: u32, num_nominators: u32) -> Result< + (Vec>, Vec>), + &'static str +> { + Staking::::new_session(0); + + let mut offenders = vec![]; + for i in 0 .. num_offenders { + let offender = create_offender::(i + 1, num_nominators)?; + offenders.push(offender); + } + + Staking::::start_session(0); + + let id_tuples = offenders.iter() + .map(|offender| + ::ValidatorIdOf::convert(offender.controller.clone()) + .expect("failed to get validator id from account id")) + .map(|validator_id| + ::FullIdentificationOf::convert(validator_id.clone()) + .map(|full_id| (validator_id, full_id)) + .expect("failed to convert validator id to full identification")) + .collect::>>(); + Ok((id_tuples, offenders)) +} + +#[cfg(test)] +fn check_events::Event>>(expected: I) { + let events = System::::events() .into_iter() + .map(|frame_system::EventRecord { event, .. }| event).collect::>(); + let expected = expected.collect::>(); + let lengths = (events.len(), expected.len()); + let length_mismatch = if lengths.0 != lengths.1 { + fn pretty(header: &str, ev: &[D]) { + println!("{}", header); + for (idx, ev) in ev.iter().enumerate() { + println!("\t[{:04}] {:?}", idx, ev); + } + } + pretty("--Got:", &events); + pretty("--Expected:", &expected); + format!("Mismatching length. Got: {}, expected: {}", lengths.0, lengths.1) + } else { Default::default() }; + + for (idx, (a, b)) in events.into_iter().zip(expected).enumerate() { + assert_eq!(a, b, "Mismatch at: {}. {}", idx, length_mismatch); + } + + if !length_mismatch.is_empty() { + panic!(length_mismatch); + } +} + +benchmarks! { + _ { } + + report_offence_im_online { + let r in 1 .. MAX_REPORTERS; + // we skip 1 offender, because in such case there is no slashing + let o in 2 .. MAX_OFFENDERS; + let n in 0 .. MAX_NOMINATORS.min(MAX_NOMINATIONS as u32); + + // Make r reporters + let mut reporters = vec![]; + for i in 0 .. r { + let reporter = account("reporter", i, SEED); + reporters.push(reporter); + } + + // make sure reporters actually get rewarded + Staking::::set_slash_reward_fraction(Perbill::one()); + + let (offenders, raw_offenders) = make_offenders::(o, n)?; + let keys = ImOnline::::keys(); + let validator_set_count = keys.len() as u32; + + let slash_fraction = UnresponsivenessOffence::::slash_fraction( + offenders.len() as u32, validator_set_count, + ); + let offence = UnresponsivenessOffence { + session_index: 0, + validator_set_count, + offenders, + }; + assert_eq!(System::::event_count(), 0); + }: { + let _ = ::ReportUnresponsiveness::report_offence( + reporters.clone(), + offence + ); + } + verify { + // make sure the report was not deferred + assert!(Offences::::deferred_offences().is_empty()); + let slash_amount = slash_fraction * bond_amount::().unique_saturated_into() as u32; + let reward_amount = slash_amount * (1 + n) / 2; + let mut slash_events = raw_offenders.into_iter() + .flat_map(|offender| { + core::iter::once(offender.stash).chain(offender.nominator_stashes.into_iter()) + }) + .map(|stash| ::Event::from( + StakingEvent::::Slash(stash, BalanceOf::::from(slash_amount)) + )) + .collect::>(); + let reward_events = reporters.into_iter() + .flat_map(|reporter| vec![ + frame_system::Event::::NewAccount(reporter.clone()).into(), + ::Event::from( + pallet_balances::Event::::Endowed(reporter.clone(), (reward_amount / r).into()) + ).into() + ]); + + // rewards are applied after first offender and it's nominators + let slash_rest = slash_events.split_off(1 + n as usize); + + // make sure that all slashes have been applied + #[cfg(test)] + check_events::( + std::iter::empty() + .chain(slash_events.into_iter().map(Into::into)) + .chain(reward_events) + .chain(slash_rest.into_iter().map(Into::into)) + .chain(std::iter::once(::Event::from( + pallet_offences::Event::Offence( + UnresponsivenessOffence::::ID, + 0_u32.to_le_bytes().to_vec(), + true + ) + ).into())) + ); + } + + report_offence_grandpa { + let r in 1 .. MAX_REPORTERS; + let n in 0 .. MAX_NOMINATORS.min(MAX_NOMINATIONS as u32); + let o = 1; + + // Make r reporters + let mut reporters = vec![]; + for i in 0 .. r { + let reporter = account("reporter", i, SEED); + reporters.push(reporter); + } + + // make sure reporters actually get rewarded + Staking::::set_slash_reward_fraction(Perbill::one()); + + let (mut offenders, raw_offenders) = make_offenders::(o, n)?; + let keys = ImOnline::::keys(); + + let offence = GrandpaEquivocationOffence { + time_slot: GrandpaTimeSlot { set_id: 0, round: 0 }, + session_index: 0, + validator_set_count: keys.len() as u32, + offender: T::convert(offenders.pop().unwrap()), + }; + assert_eq!(System::::event_count(), 0); + }: { + let _ = Offences::::report_offence(reporters, offence); + } + verify { + // make sure the report was not deferred + assert!(Offences::::deferred_offences().is_empty()); + // make sure that all slashes have been applied + assert_eq!( + System::::event_count(), 0 + + 1 // offence + + 2 * r // reporter (reward + endowment) + + o // offenders slashed + + o * n // nominators slashed + ); + } + + report_offence_babe { + let n in 0 .. MAX_NOMINATORS.min(MAX_NOMINATIONS as u32); + + // for babe equivocation reports the number of reporters + // and offenders is always 1 + let reporters = vec![account("reporter", 1, SEED)]; + + // make sure reporters actually get rewarded + Staking::::set_slash_reward_fraction(Perbill::one()); + + let (mut offenders, raw_offenders) = make_offenders::(1, n)?; + let keys = ImOnline::::keys(); + + let offence = BabeEquivocationOffence { + slot: 0, + session_index: 0, + validator_set_count: keys.len() as u32, + offender: T::convert(offenders.pop().unwrap()), + }; + assert_eq!(System::::event_count(), 0); + }: { + let _ = Offences::::report_offence(reporters, offence); + } + verify { + // make sure the report was not deferred + assert!(Offences::::deferred_offences().is_empty()); + // make sure that all slashes have been applied + assert_eq!( + System::::event_count(), 0 + + 1 // offence + + 2 // reporter (reward + endowment) + + 1 // offenders slashed + + n // nominators slashed + ); + } + + on_initialize { + let d in 1 .. MAX_DEFERRED_OFFENCES; + let o = 10; + let n = 100; + + Staking::::put_election_status(ElectionStatus::Closed); + + let mut deferred_offences = vec![]; + let offenders = make_offenders::(o, n)?.0; + let offence_details = offenders.into_iter() + .map(|offender| OffenceDetails { + offender: T::convert(offender), + reporters: vec![], + }) + .collect::>(); + + for i in 0 .. d { + let fractions = offence_details.iter() + .map(|_| Perbill::from_percent(100 * (i + 1) / MAX_DEFERRED_OFFENCES)) + .collect::>(); + deferred_offences.push((offence_details.clone(), fractions.clone(), 0u32)); + } + + Offences::::set_deferred_offences(deferred_offences); + assert!(!Offences::::deferred_offences().is_empty()); + }: { + Offences::::on_initialize(0.into()); + } + verify { + // make sure that all deferred offences were reported with Ok status. + assert!(Offences::::deferred_offences().is_empty()); + assert_eq!( + System::::event_count(), d * (0 + + o // offenders slashed + + o * n // nominators slashed + )); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::{new_test_ext, Test}; + use frame_support::assert_ok; + + #[test] + fn test_benchmarks() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_report_offence_im_online::()); + assert_ok!(test_benchmark_report_offence_grandpa::()); + assert_ok!(test_benchmark_report_offence_babe::()); + assert_ok!(test_benchmark_on_initialize::()); + }); + } +} diff --git a/frame/offences/benchmarking/src/mock.rs b/frame/offences/benchmarking/src/mock.rs new file mode 100644 index 0000000000000000000000000000000000000000..ad6e8a14d5622f0fe1922fc31e5801262ab10323 --- /dev/null +++ b/frame/offences/benchmarking/src/mock.rs @@ -0,0 +1,237 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Mock file for offences benchmarking. + +#![cfg(test)] + +use super::*; +use frame_support::{ + parameter_types, + weights::{Weight, constants::WEIGHT_PER_SECOND}, +}; +use frame_system as system; +use sp_runtime::{ + SaturatedConversion, + traits::{IdentityLookup, Block as BlockT}, + testing::{Header, UintAuthorityId}, +}; + + +type AccountId = u64; +type AccountIndex = u32; +type BlockNumber = u64; +type Balance = u64; + +parameter_types! { + pub const MaximumBlockWeight: Weight = 2 * WEIGHT_PER_SECOND; +} + +impl frame_system::Trait for Test { + type BaseCallFilter = (); + type Origin = Origin; + type Index = AccountIndex; + type BlockNumber = BlockNumber; + type Call = Call; + type Hash = sp_core::H256; + type Hashing = ::sp_runtime::traits::BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = sp_runtime::testing::Header; + type Event = Event; + type BlockHashCount = (); + type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type AvailableBlockRatio = (); + type MaximumBlockLength = (); + type Version = (); + type ModuleToIndex = (); + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (Balances,); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = (); + type SystemWeightInfo = (); +} +parameter_types! { + pub const ExistentialDeposit: Balance = 10; +} +impl pallet_balances::Trait for Test { + type Balance = Balance; + type Event = Event; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); +} + +parameter_types! { + pub const MinimumPeriod: u64 = 5; +} +impl pallet_timestamp::Trait for Test { + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); +} +impl pallet_session::historical::Trait for Test { + type FullIdentification = pallet_staking::Exposure; + type FullIdentificationOf = pallet_staking::ExposureOf; +} + +sp_runtime::impl_opaque_keys! { + pub struct SessionKeys { + pub foo: sp_runtime::testing::UintAuthorityId, + } +} + +pub struct TestSessionHandler; +impl pallet_session::SessionHandler for TestSessionHandler { + const KEY_TYPE_IDS: &'static [sp_runtime::KeyTypeId] = &[]; + + fn on_genesis_session(_validators: &[(AccountId, Ks)]) {} + + fn on_new_session( + _: bool, + _: &[(AccountId, Ks)], + _: &[(AccountId, Ks)], + ) {} + + fn on_disabled(_: usize) {} +} + +parameter_types! { + pub const Period: u64 = 1; + pub const Offset: u64 = 0; +} + +impl pallet_session::Trait for Test { + type SessionManager = pallet_session::historical::NoteHistoricalRoot; + type Keys = SessionKeys; + type ShouldEndSession = pallet_session::PeriodicSessions; + type NextSessionRotation = pallet_session::PeriodicSessions; + type SessionHandler = TestSessionHandler; + type Event = Event; + type ValidatorId = AccountId; + type ValidatorIdOf = pallet_staking::StashOf; + type DisabledValidatorsThreshold = (); + type WeightInfo = (); +} +pallet_staking_reward_curve::build! { + const I_NPOS: sp_runtime::curve::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 RewardCurve: &'static sp_runtime::curve::PiecewiseLinear<'static> = &I_NPOS; + pub const MaxNominatorRewardedPerValidator: u32 = 64; +} + +pub type Extrinsic = sp_runtime::testing::TestXt; + +pub struct CurrencyToVoteHandler; +impl Convert for CurrencyToVoteHandler { + fn convert(x: u64) -> u64 { + x + } +} +impl Convert for CurrencyToVoteHandler { + fn convert(x: u128) -> u64 { + x.saturated_into() + } +} + +impl pallet_staking::Trait for Test { + type Currency = Balances; + type UnixTime = pallet_timestamp::Module; + type CurrencyToVote = CurrencyToVoteHandler; + type RewardRemainder = (); + type Event = Event; + type Slash = (); + type Reward = (); + type SessionsPerEra = (); + type SlashDeferDuration = (); + type SlashCancelOrigin = frame_system::EnsureRoot; + type BondingDuration = (); + type SessionInterface = Self; + type RewardCurve = RewardCurve; + type NextNewSession = Session; + type ElectionLookahead = (); + type Call = Call; + type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; + type UnsignedPriority = (); + type MaxIterations = (); + type MinSolutionScoreBump = (); + type WeightInfo = (); +} + +impl pallet_im_online::Trait for Test { + type AuthorityId = UintAuthorityId; + type Event = Event; + type SessionDuration = Period; + type ReportUnresponsiveness = Offences; + type UnsignedPriority = (); + type WeightInfo = (); +} + +parameter_types! { + pub OffencesWeightSoftLimit: Weight = Perbill::from_percent(60) * MaximumBlockWeight::get(); +} + +impl pallet_offences::Trait for Test { + type Event = Event; + type IdentificationTuple = pallet_session::historical::IdentificationTuple; + type OnOffenceHandler = Staking; + type WeightSoftLimit = OffencesWeightSoftLimit; + type WeightInfo = (); +} + +impl frame_system::offchain::SendTransactionTypes for Test where Call: From { + type Extrinsic = Extrinsic; + type OverarchingCall = Call; +} + +impl crate::Trait for Test {} + +pub type Block = sp_runtime::generic::Block; +pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic; + +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: system::{Module, Call, Event}, + Balances: pallet_balances::{Module, Call, Storage, Config, Event}, + Staking: pallet_staking::{Module, Call, Config, Storage, Event, ValidateUnsigned}, + Session: pallet_session::{Module, Call, Storage, Event, Config}, + ImOnline: pallet_im_online::{Module, Call, Storage, Event, ValidateUnsigned, Config}, + Offences: pallet_offences::{Module, Call, Storage, Event}, + } +); + +pub fn new_test_ext() -> sp_io::TestExternalities { + let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + sp_io::TestExternalities::new(t) +} diff --git a/frame/offences/src/lib.rs b/frame/offences/src/lib.rs index 0ba7cd87f24552b9e14c5227b3683d1246b434f8..fe4662efa88dcfc9692e922bf1edb8682cbedd85 100644 --- a/frame/offences/src/lib.rs +++ b/frame/offences/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Offences Module //! @@ -27,15 +28,15 @@ mod tests; use sp_std::vec::Vec; use frame_support::{ decl_module, decl_event, decl_storage, Parameter, debug, - weights::{Weight, SimpleDispatchInfo, WeighData}, + traits::Get, + weights::Weight, }; -use sp_runtime::{traits::Hash, Perbill}; +use sp_runtime::{traits::{Hash, Zero}, Perbill}; use sp_staking::{ SessionIndex, offence::{Offence, ReportOffence, Kind, OnOffenceHandler, OffenceDetails, OffenceError}, }; use codec::{Encode, Decode}; -use frame_system as system; /// A binary blob which represents a SCALE codec-encoded `O::TimeSlot`. type OpaqueTimeSlot = Vec; @@ -44,12 +45,26 @@ type OpaqueTimeSlot = Vec; type ReportIdOf = ::Hash; /// Type of data stored as a deferred offence -type DeferredOffenceOf = ( +pub type DeferredOffenceOf = ( Vec::AccountId, ::IdentificationTuple>>, Vec, SessionIndex, ); +pub trait WeightInfo { + fn report_offence_im_online(r: u32, o: u32, n: u32, ) -> Weight; + fn report_offence_grandpa(r: u32, n: u32, ) -> Weight; + fn report_offence_babe(r: u32, n: u32, ) -> Weight; + fn on_initialize(d: u32, ) -> Weight; +} + +impl WeightInfo for () { + fn report_offence_im_online(_r: u32, _o: u32, _n: u32, ) -> Weight { 1_000_000_000 } + fn report_offence_grandpa(_r: u32, _n: u32, ) -> Weight { 1_000_000_000 } + fn report_offence_babe(_r: u32, _n: u32, ) -> Weight { 1_000_000_000 } + fn on_initialize(_d: u32, ) -> Weight { 1_000_000_000 } +} + /// Offences trait pub trait Trait: frame_system::Trait { /// The overarching event type. @@ -57,7 +72,13 @@ pub trait Trait: frame_system::Trait { /// Full identification of the validator. type IdentificationTuple: Parameter + Ord; /// A handler called for every offence report. - type OnOffenceHandler: OnOffenceHandler; + type OnOffenceHandler: OnOffenceHandler; + /// The a soft limit on maximum weight that may be consumed while dispatching deferred offences in + /// `on_initialize`. + /// Note it's going to be exceeded before we stop adding to it, so it has to be set conservatively. + type WeightSoftLimit: Get; + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; } decl_storage! { @@ -69,7 +90,7 @@ decl_storage! { /// Deferred reports that have been rejected by the offence handler and need to be submitted /// at a later time. - DeferredOffences get(deferred_offences): Vec>; + DeferredOffences get(fn deferred_offences): Vec>; /// A vector of reports of the same kind that happened at the same time slot. ConcurrentReportsIndex: @@ -99,33 +120,41 @@ decl_module! { pub struct Module for enum Call where origin: T::Origin { fn deposit_event() = default; - fn on_runtime_upgrade() -> Weight { - Reports::::remove_all(); - ConcurrentReportsIndex::::remove_all(); - ReportsByKindIndex::remove_all(); - - SimpleDispatchInfo::default().weigh_data(()) - } - fn on_initialize(now: T::BlockNumber) -> Weight { // only decode storage if we can actually submit anything again. - if T::OnOffenceHandler::can_report() { - >::mutate(|deferred| { - // keep those that fail to be reported again. An error log is emitted here; this - // should not happen if staking's `can_report` is implemented properly. - deferred.retain(|(o, p, s)| { - T::OnOffenceHandler::on_offence(&o, &p, *s).map_err(|_| { - debug::native::error!( - target: "pallet-offences", - "re-submitting a deferred slash returned Err at {}. This should not happen with pallet-staking", - now, - ); - }).is_err() - }) - }) + if !T::OnOffenceHandler::can_report() { + return 0; } - SimpleDispatchInfo::default().weigh_data(()) + let limit = T::WeightSoftLimit::get(); + let mut consumed = Weight::zero(); + + >::mutate(|deferred| { + deferred.retain(|(offences, perbill, session)| { + if consumed >= limit { + true + } else { + // keep those that fail to be reported again. An error log is emitted here; this + // should not happen if staking's `can_report` is implemented properly. + match T::OnOffenceHandler::on_offence(&offences, &perbill, *session) { + Ok(weight) => { + consumed += weight; + false + }, + Err(_) => { + debug::native::error!( + target: "pallet-offences", + "re-submitting a deferred slash returned Err at {}. This should not happen with pallet-staking", + now, + ); + true + }, + } + } + }) + }); + + consumed } } } @@ -171,6 +200,15 @@ where Ok(()) } + + fn is_known_offence(offenders: &[T::IdentificationTuple], time_slot: &O::TimeSlot) -> bool { + let any_unknown = offenders.iter().any(|offender| { + let report_id = Self::report_id::(time_slot, offender); + !>::contains_key(&report_id) + }); + + !any_unknown + } } impl Module { @@ -249,6 +287,11 @@ impl Module { None } } + + #[cfg(feature = "runtime-benchmarks")] + pub fn set_deferred_offences(offences: Vec>) { + >::put(offences); + } } struct TriageOutcome { diff --git a/frame/offences/src/mock.rs b/frame/offences/src/mock.rs index e464200396ebde9be263ee75ea610813203d34c1..f981e70835c0e14acf0a7b03ac4bd1dcd9b30c77 100644 --- a/frame/offences/src/mock.rs +++ b/frame/offences/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utilities @@ -31,7 +32,7 @@ use sp_runtime::traits::{IdentityLookup, BlakeTwo256}; use sp_core::H256; use frame_support::{ impl_outer_origin, impl_outer_event, parameter_types, StorageMap, StorageDoubleMap, - weights::Weight, + weights::{Weight, constants::{WEIGHT_PER_SECOND, RocksDbWeight}}, }; use frame_system as system; @@ -44,20 +45,23 @@ pub struct OnOffenceHandler; thread_local! { pub static ON_OFFENCE_PERBILL: RefCell> = RefCell::new(Default::default()); pub static CAN_REPORT: RefCell = RefCell::new(true); + pub static OFFENCE_WEIGHT: RefCell = RefCell::new(Default::default()); } -impl offence::OnOffenceHandler for OnOffenceHandler { +impl + offence::OnOffenceHandler for OnOffenceHandler +{ fn on_offence( _offenders: &[OffenceDetails], slash_fraction: &[Perbill], _offence_session: SessionIndex, - ) -> Result<(), ()> { - if >::can_report() { + ) -> Result { + if >::can_report() { ON_OFFENCE_PERBILL.with(|f| { *f.borrow_mut() = slash_fraction.to_vec(); }); - Ok(()) + Ok(OFFENCE_WEIGHT.with(|w| *w.borrow())) } else { Err(()) } @@ -78,16 +82,21 @@ pub fn with_on_offence_fractions) -> R>(f: F) -> }) } +pub fn set_offence_weight(new: Weight) { + OFFENCE_WEIGHT.with(|w| *w.borrow_mut() = new); +} + // 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: Weight = 1024; + pub const MaximumBlockWeight: Weight = 2 * WEIGHT_PER_SECOND; pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Runtime { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -100,6 +109,10 @@ impl frame_system::Trait for Runtime { type Event = TestEvent; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = RocksDbWeight; + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -107,12 +120,19 @@ impl frame_system::Trait for Runtime { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); +} + +parameter_types! { + pub OffencesWeightSoftLimit: Weight = Perbill::from_percent(60) * MaximumBlockWeight::get(); } impl Trait for Runtime { type Event = TestEvent; type IdentificationTuple = u64; type OnOffenceHandler = OnOffenceHandler; + type WeightSoftLimit = OffencesWeightSoftLimit; + type WeightInfo = (); } mod offences { diff --git a/frame/offences/src/tests.rs b/frame/offences/src/tests.rs index 3179a0752318f1340ae924599734423b793fb012..ca9f46a198820ba93a2618803fab956f610636f2 100644 --- a/frame/offences/src/tests.rs +++ b/frame/offences/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for the offences module. @@ -21,7 +22,7 @@ use super::*; use crate::mock::{ Offences, System, Offence, TestEvent, KIND, new_test_ext, with_on_offence_fractions, - offence_reports, set_can_report, + offence_reports, set_can_report, set_offence_weight, }; use sp_runtime::Perbill; use frame_support::traits::OnInitialize; @@ -173,6 +174,77 @@ fn doesnt_deposit_event_for_dups() { }); } +#[test] +fn reports_if_an_offence_is_dup() { + type TestOffence = Offence; + + new_test_ext().execute_with(|| { + let time_slot = 42; + assert_eq!(offence_reports(KIND, time_slot), vec![]); + + let offence = |time_slot, offenders| TestOffence { + validator_set_count: 5, + time_slot, + offenders, + }; + + let mut test_offence = offence(time_slot, vec![0]); + + // the report for authority 0 at time slot 42 should not be a known + // offence + assert!( + !>::is_known_offence( + &test_offence.offenders, + &test_offence.time_slot + ) + ); + + // we report an offence for authority 0 at time slot 42 + Offences::report_offence(vec![], test_offence.clone()).unwrap(); + + // the same report should be a known offence now + assert!( + >::is_known_offence( + &test_offence.offenders, + &test_offence.time_slot + ) + ); + + // and reporting it again should yield a duplicate report error + assert_eq!( + Offences::report_offence(vec![], test_offence.clone()), + Err(OffenceError::DuplicateReport) + ); + + // after adding a new offender to the offence report + test_offence.offenders.push(1); + + // it should not be a known offence anymore + assert!( + !>::is_known_offence( + &test_offence.offenders, + &test_offence.time_slot + ) + ); + + // and reporting it again should work without any error + assert_eq!( + Offences::report_offence(vec![], test_offence.clone()), + Ok(()) + ); + + // creating a new offence for the same authorities on the next slot + // should be considered a new offence and thefore not known + let test_offence_next_slot = offence(time_slot + 1, vec![0, 1]); + assert!( + !>::is_known_offence( + &test_offence_next_slot.offenders, + &test_offence_next_slot.time_slot + ) + ); + }); +} + #[test] fn should_properly_count_offences() { // We report two different authorities for the same issue. Ultimately, the 1st authority @@ -264,3 +336,48 @@ fn should_queue_and_resubmit_rejected_offence() { assert_eq!(Offences::deferred_offences().len(), 0); }) } + +#[test] +fn weight_soft_limit_is_used() { + new_test_ext().execute_with(|| { + set_can_report(false); + // Only 2 can fit in one block + set_offence_weight(::WeightSoftLimit::get() / 2); + + // Queue 3 offences + // #1 + let offence = Offence { + validator_set_count: 5, + time_slot: 42, + offenders: vec![5], + }; + Offences::report_offence(vec![], offence).unwrap(); + // #2 + let offence = Offence { + validator_set_count: 5, + time_slot: 62, + offenders: vec![5], + }; + Offences::report_offence(vec![], offence).unwrap(); + // #3 + let offence = Offence { + validator_set_count: 5, + time_slot: 72, + offenders: vec![5], + }; + Offences::report_offence(vec![], offence).unwrap(); + // 3 are queued + assert_eq!(Offences::deferred_offences().len(), 3); + + // Allow reporting + set_can_report(true); + + Offences::on_initialize(3); + // Two are completed, one is left in the queue + assert_eq!(Offences::deferred_offences().len(), 1); + + Offences::on_initialize(4); + // All are done now + assert_eq!(Offences::deferred_offences().len(), 0); + }) +} diff --git a/frame/proxy/Cargo.toml b/frame/proxy/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..07e2abac3173e95f1d2a5571954de2028d5e0784 --- /dev/null +++ b/frame/proxy/Cargo.toml @@ -0,0 +1,45 @@ +[package] +name = "pallet-proxy" +version = "2.0.0-rc4" +authors = ["Parity Technologies "] +edition = "2018" +license = "Apache-2.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +description = "FRAME proxying pallet" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +serde = { version = "1.0.101", optional = true } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/core" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } + +frame-benchmarking = { version = "2.0.0-rc4", default-features = false, path = "../benchmarking", optional = true } + +[dev-dependencies] +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0-rc4", path = "../balances" } +pallet-utility = { version = "2.0.0-rc4", path = "../utility" } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "sp-runtime/std", + "frame-support/std", + "frame-system/std", + "sp-std/std", + "sp-io/std" +] +runtime-benchmarks = [ + "frame-benchmarking", + "frame-support/runtime-benchmarks", +] diff --git a/frame/proxy/src/benchmarking.rs b/frame/proxy/src/benchmarking.rs new file mode 100644 index 0000000000000000000000000000000000000000..3cbe517dfd7da782cb69f0079037d035c1c09680 --- /dev/null +++ b/frame/proxy/src/benchmarking.rs @@ -0,0 +1,108 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Benchmarks for Proxy Pallet + +#![cfg(feature = "runtime-benchmarks")] + +use super::*; +use frame_system::RawOrigin; +use frame_benchmarking::{benchmarks, account}; +use sp_runtime::traits::Bounded; +use crate::Module as Proxy; + +const SEED: u32 = 0; + +fn add_proxies(n: u32, maybe_who: Option) -> Result<(), &'static str> { + let caller = maybe_who.unwrap_or_else(|| account("caller", 0, SEED)); + T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + for i in 0..n { + Proxy::::add_proxy( + RawOrigin::Signed(caller.clone()).into(), + account("target", i, SEED), + T::ProxyType::default() + )?; + } + Ok(()) +} + +benchmarks! { + _ { + let p in 1 .. (T::MaxProxies::get() - 1).into() => add_proxies::(p, None)?; + } + + proxy { + let p in ...; + // In this case the caller is the "target" proxy + let caller: T::AccountId = account("target", p - 1, SEED); + // ... and "real" is the traditional caller. This is not a typo. + let real: T::AccountId = account("caller", 0, SEED); + let call: ::Call = frame_system::Call::::remark(vec![]).into(); + }: _(RawOrigin::Signed(caller), real, Some(T::ProxyType::default()), Box::new(call)) + + add_proxy { + let p in ...; + let caller: T::AccountId = account("caller", 0, SEED); + }: _(RawOrigin::Signed(caller), account("target", T::MaxProxies::get().into(), SEED), T::ProxyType::default()) + + remove_proxy { + let p in ...; + let caller: T::AccountId = account("caller", 0, SEED); + }: _(RawOrigin::Signed(caller), account("target", 0, SEED), T::ProxyType::default()) + + remove_proxies { + let p in ...; + let caller: T::AccountId = account("caller", 0, SEED); + }: _(RawOrigin::Signed(caller)) + + anonymous { + let p in ...; + }: _(RawOrigin::Signed(account("caller", 0, SEED)), T::ProxyType::default(), 0) + + kill_anonymous { + let p in 0 .. (T::MaxProxies::get() - 2).into(); + + let caller: T::AccountId = account("caller", 0, SEED); + T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + Module::::anonymous(RawOrigin::Signed(account("caller", 0, SEED)).into(), T::ProxyType::default(), 0)?; + let height = system::Module::::block_number(); + let ext_index = system::Module::::extrinsic_index().unwrap_or(0); + let anon = Module::::anonymous_account(&caller, &T::ProxyType::default(), 0, None); + + add_proxies::(p, Some(anon.clone()))?; + + }: _(RawOrigin::Signed(anon), caller, T::ProxyType::default(), 0, height, ext_index) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::tests::{new_test_ext, Test}; + use frame_support::assert_ok; + + #[test] + fn test_benchmarks() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_proxy::()); + assert_ok!(test_benchmark_add_proxy::()); + assert_ok!(test_benchmark_remove_proxy::()); + assert_ok!(test_benchmark_remove_proxies::()); + assert_ok!(test_benchmark_anonymous::()); + assert_ok!(test_benchmark_kill_anonymous::()); + }); + } +} diff --git a/frame/proxy/src/lib.rs b/frame/proxy/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..79879a51fa61bf27aff1b3c57be8fa12aded7c01 --- /dev/null +++ b/frame/proxy/src/lib.rs @@ -0,0 +1,414 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! # Proxy Module +//! A module allowing accounts to give permission to other accounts to dispatch types of calls from +//! their signed origin. +//! +//! - [`proxy::Trait`](./trait.Trait.html) +//! - [`Call`](./enum.Call.html) +//! +//! ## Overview +//! +//! ## Interface +//! +//! ### Dispatchable Functions +//! +//! [`Call`]: ./enum.Call.html +//! [`Trait`]: ./trait.Trait.html + +// Ensure we're `no_std` when compiling for Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::prelude::*; +use codec::{Encode, Decode}; +use sp_io::hashing::blake2_256; +use sp_runtime::{DispatchResult, traits::{Dispatchable, Zero}}; +use sp_runtime::traits::Member; +use frame_support::{ + decl_module, decl_event, decl_error, decl_storage, Parameter, ensure, traits::{ + Get, ReservableCurrency, Currency, InstanceFilter, + OriginTrait, IsType, + }, weights::{Weight, GetDispatchInfo, constants::{WEIGHT_PER_MICROS, WEIGHT_PER_NANOS}}, + dispatch::{PostDispatchInfo, IsSubType}, +}; +use frame_system::{self as system, ensure_signed}; + +mod tests; +mod benchmarking; + +type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; + +pub trait WeightInfo { + fn proxy(p: u32, ) -> Weight; + fn add_proxy(p: u32, ) -> Weight; + fn remove_proxy(p: u32, ) -> Weight; + fn remove_proxies(p: u32, ) -> Weight; + fn anonymous(p: u32, ) -> Weight; + fn kill_anonymous(p: u32, ) -> Weight; +} + +impl WeightInfo for () { + fn proxy(_p: u32, ) -> Weight { 1_000_000_000 } + fn add_proxy(_p: u32, ) -> Weight { 1_000_000_000 } + fn remove_proxy(_p: u32, ) -> Weight { 1_000_000_000 } + fn remove_proxies(_p: u32, ) -> Weight { 1_000_000_000 } + fn anonymous(_p: u32, ) -> Weight { 1_000_000_000 } + fn kill_anonymous(_p: u32, ) -> Weight { 1_000_000_000 } +} + +/// Configuration trait. +pub trait Trait: frame_system::Trait { + /// The overarching event type. + type Event: From> + Into<::Event>; + + /// The overarching call type. + type Call: Parameter + Dispatchable + + GetDispatchInfo + From> + IsSubType> + + IsType<::Call>; + + /// The currency mechanism. + type Currency: ReservableCurrency; + + /// A kind of proxy; specified with the proxy and passed in to the `IsProxyable` fitler. + /// The instance filter determines whether a given call may be proxied under this type. + /// + /// IMPORTANT: `Default` must be provided and MUST BE the the *most permissive* value. + type ProxyType: Parameter + Member + Ord + PartialOrd + InstanceFilter<::Call> + + Default; + + /// The base amount of currency needed to reserve for creating a proxy. + /// + /// This is held for an additional storage item whose value size is + /// `sizeof(Balance)` bytes and whose key size is `sizeof(AccountId)` bytes. + type ProxyDepositBase: Get>; + + /// The amount of currency needed per proxy added. + /// + /// This is held for adding 32 bytes plus an instance of `ProxyType` more into a pre-existing + /// storage value. + type ProxyDepositFactor: Get>; + + /// The maximum amount of proxies allowed for a single account. + type MaxProxies: Get; + + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; +} + +decl_storage! { + trait Store for Module as Proxy { + /// The set of account proxies. Maps the account which has delegated to the accounts + /// which are being delegated to, together with the amount held on deposit. + pub Proxies: map hasher(twox_64_concat) T::AccountId => (Vec<(T::AccountId, T::ProxyType)>, BalanceOf); + } +} + +decl_error! { + pub enum Error for Module { + /// There are too many proxies registered. + TooMany, + /// Proxy registration not found. + NotFound, + /// Sender is not a proxy of the account to be proxied. + NotProxy, + /// A call which is incompatible with the proxy type's filter was attempted. + Unproxyable, + /// Account is already a proxy. + Duplicate, + /// Call may not be made by proxy because it may escalate its privileges. + NoPermission, + } +} + +decl_event! { + /// Events type. + pub enum Event where + AccountId = ::AccountId, + ProxyType = ::ProxyType + { + /// A proxy was executed correctly, with the given result. + ProxyExecuted(DispatchResult), + /// Anonymous account (first parameter) has been created by new proxy (second) with given + /// disambiguation index and proxy type. + AnonymousCreated(AccountId, AccountId, ProxyType, u16), + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + type Error = Error; + + /// Deposit one of this module's events by using the default implementation. + fn deposit_event() = default; + + /// The base amount of currency needed to reserve for creating a proxy. + const ProxyDepositBase: BalanceOf = T::ProxyDepositBase::get(); + + /// The amount of currency needed per proxy added. + const ProxyDepositFactor: BalanceOf = T::ProxyDepositFactor::get(); + + /// The maximum amount of proxies allowed for a single account. + const MaxProxies: u16 = T::MaxProxies::get(); + + /// Dispatch the given `call` from an account that the sender is authorised for through + /// `add_proxy`. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// Parameters: + /// - `real`: The account that the proxy will make a call on behalf of. + /// - `force_proxy_type`: Specify the exact proxy type to be used and checked for this call. + /// - `call`: The call to be made by the `real` account. + /// + /// # + /// P is the number of proxies the user has + /// - Base weight: 19.87 + .141 * P µs + /// - DB weight: 1 storage read. + /// - Plus the weight of the `call` + /// # + #[weight = { + let di = call.get_dispatch_info(); + (T::DbWeight::get().reads(1) + .saturating_add(di.weight) + .saturating_add(20 * WEIGHT_PER_MICROS) + .saturating_add((140 * WEIGHT_PER_NANOS).saturating_mul(T::MaxProxies::get().into())), + di.class) + }] + fn proxy(origin, + real: T::AccountId, + force_proxy_type: Option, + call: Box<::Call> + ) { + let who = ensure_signed(origin)?; + let (_, proxy_type) = Proxies::::get(&real).0.into_iter() + .find(|x| &x.0 == &who && force_proxy_type.as_ref().map_or(true, |y| &x.1 == y)) + .ok_or(Error::::NotProxy)?; + + // This is a freshly authenticated new account, the origin restrictions doesn't apply. + let mut origin: T::Origin = frame_system::RawOrigin::Signed(real).into(); + origin.add_filter(move |c: &::Call| { + let c = ::Call::from_ref(c); + match c.is_sub_type() { + Some(Call::add_proxy(_, ref pt)) | Some(Call::remove_proxy(_, ref pt)) + if !proxy_type.is_superset(&pt) => false, + Some(Call::remove_proxies(..)) | Some(Call::kill_anonymous(..)) + if proxy_type != T::ProxyType::default() => false, + _ => proxy_type.filter(c) + } + }); + let e = call.dispatch(origin); + Self::deposit_event(RawEvent::ProxyExecuted(e.map(|_| ()).map_err(|e| e.error))); + } + + /// Register a proxy account for the sender that is able to make calls on its behalf. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// Parameters: + /// - `proxy`: The account that the `caller` would like to make a proxy. + /// - `proxy_type`: The permissions allowed for this proxy account. + /// + /// # + /// P is the number of proxies the user has + /// - Base weight: 17.48 + .176 * P µs + /// - DB weight: 1 storage read and write. + /// # + #[weight = T::DbWeight::get().reads_writes(1, 1) + .saturating_add(18 * WEIGHT_PER_MICROS) + .saturating_add((200 * WEIGHT_PER_NANOS).saturating_mul(T::MaxProxies::get().into())) + ] + fn add_proxy(origin, proxy: T::AccountId, proxy_type: T::ProxyType) -> DispatchResult { + let who = ensure_signed(origin)?; + Proxies::::try_mutate(&who, |(ref mut proxies, ref mut deposit)| { + ensure!(proxies.len() < T::MaxProxies::get() as usize, Error::::TooMany); + let typed_proxy = (proxy, proxy_type); + let i = proxies.binary_search(&typed_proxy).err().ok_or(Error::::Duplicate)?; + proxies.insert(i, typed_proxy); + let new_deposit = T::ProxyDepositBase::get() + + T::ProxyDepositFactor::get() * (proxies.len() as u32).into(); + if new_deposit > *deposit { + T::Currency::reserve(&who, new_deposit - *deposit)?; + } else if new_deposit < *deposit { + T::Currency::unreserve(&who, *deposit - new_deposit); + } + *deposit = new_deposit; + Ok(()) + }) + } + + /// Unregister a proxy account for the sender. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// Parameters: + /// - `proxy`: The account that the `caller` would like to remove as a proxy. + /// - `proxy_type`: The permissions currently enabled for the removed proxy account. + /// + /// # + /// P is the number of proxies the user has + /// - Base weight: 14.37 + .164 * P µs + /// - DB weight: 1 storage read and write. + /// # + #[weight = T::DbWeight::get().reads_writes(1, 1) + .saturating_add(14 * WEIGHT_PER_MICROS) + .saturating_add((160 * WEIGHT_PER_NANOS).saturating_mul(T::MaxProxies::get().into())) + ] + fn remove_proxy(origin, proxy: T::AccountId, proxy_type: T::ProxyType) -> DispatchResult { + let who = ensure_signed(origin)?; + Proxies::::try_mutate_exists(&who, |x| { + let (mut proxies, old_deposit) = x.take().ok_or(Error::::NotFound)?; + let typed_proxy = (proxy, proxy_type); + let i = proxies.binary_search(&typed_proxy).ok().ok_or(Error::::NotFound)?; + proxies.remove(i); + let new_deposit = if proxies.is_empty() { + BalanceOf::::zero() + } else { + T::ProxyDepositBase::get() + T::ProxyDepositFactor::get() * (proxies.len() as u32).into() + }; + if new_deposit > old_deposit { + T::Currency::reserve(&who, new_deposit - old_deposit)?; + } else if new_deposit < old_deposit { + T::Currency::unreserve(&who, old_deposit - new_deposit); + } + if !proxies.is_empty() { + *x = Some((proxies, new_deposit)) + } + Ok(()) + }) + } + + /// Unregister all proxy accounts for the sender. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// WARNING: This may be called on accounts created by `anonymous`, however if done, then + /// the unreserved fees will be inaccessible. **All access to this account will be lost.** + /// + /// # + /// P is the number of proxies the user has + /// - Base weight: 13.73 + .129 * P µs + /// - DB weight: 1 storage read and write. + /// # + #[weight = T::DbWeight::get().reads_writes(1, 1) + .saturating_add(14 * WEIGHT_PER_MICROS) + .saturating_add((130 * WEIGHT_PER_NANOS).saturating_mul(T::MaxProxies::get().into())) + ] + fn remove_proxies(origin) { + let who = ensure_signed(origin)?; + let (_, old_deposit) = Proxies::::take(&who); + T::Currency::unreserve(&who, old_deposit); + } + + /// Spawn a fresh new account that is guaranteed to be otherwise inaccessible, and + /// initialize it with a proxy of `proxy_type` for `origin` sender. + /// + /// Requires a `Signed` origin. + /// + /// - `proxy_type`: The type of the proxy that the sender will be registered as over the + /// new account. This will almost always be the most permissive `ProxyType` possible to + /// allow for maximum flexibility. + /// - `index`: A disambiguation index, in case this is called multiple times in the same + /// transaction (e.g. with `utility::batch`). Unless you're using `batch` you probably just + /// want to use `0`. + /// + /// Fails with `Duplicate` if this has already been called in this transaction, from the + /// same sender, with the same parameters. + /// + /// Fails if there are insufficient funds to pay for deposit. + /// + /// # + /// P is the number of proxies the user has + /// - Base weight: 36.48 + .039 * P µs + /// - DB weight: 1 storage read and write. + /// # + #[weight = T::DbWeight::get().reads_writes(1, 1) + .saturating_add(36 * WEIGHT_PER_MICROS) + .saturating_add((40 * WEIGHT_PER_NANOS).saturating_mul(T::MaxProxies::get().into())) + ] + fn anonymous(origin, proxy_type: T::ProxyType, index: u16) { + let who = ensure_signed(origin)?; + + let anonymous = Self::anonymous_account(&who, &proxy_type, index, None); + ensure!(!Proxies::::contains_key(&anonymous), Error::::Duplicate); + let deposit = T::ProxyDepositBase::get() + T::ProxyDepositFactor::get(); + T::Currency::reserve(&who, deposit)?; + Proxies::::insert(&anonymous, (vec![(who.clone(), proxy_type.clone())], deposit)); + Self::deposit_event(RawEvent::AnonymousCreated(anonymous, who, proxy_type, index)); + } + + /// Removes a previously spawned anonymous proxy. + /// + /// WARNING: **All access to this account will be lost.** Any funds held in it will be + /// inaccessible. + /// + /// Requires a `Signed` origin, and the sender account must have been created by a call to + /// `anonymous` with corresponding parameters. + /// + /// - `spawner`: The account that originally called `anonymous` to create this account. + /// - `index`: The disambiguation index originally passed to `anonymous`. Probably `0`. + /// - `proxy_type`: The proxy type originally passed to `anonymous`. + /// - `height`: The height of the chain when the call to `anonymous` was processed. + /// - `ext_index`: The extrinsic index in which the call to `anonymous` was processed. + /// + /// Fails with `NoPermission` in case the caller is not a previously created anonymous + /// account whose `anonymous` call has corresponding parameters. + /// + /// # + /// P is the number of proxies the user has + /// - Base weight: 15.65 + .137 * P µs + /// - DB weight: 1 storage read and write. + /// # + #[weight = T::DbWeight::get().reads_writes(1, 1) + .saturating_add(15 * WEIGHT_PER_MICROS) + .saturating_add((140 * WEIGHT_PER_NANOS).saturating_mul(T::MaxProxies::get().into())) + ] + fn kill_anonymous(origin, + spawner: T::AccountId, + proxy_type: T::ProxyType, + index: u16, + #[compact] height: T::BlockNumber, + #[compact] ext_index: u32, + ) { + let who = ensure_signed(origin)?; + + let when = (height, ext_index); + let proxy = Self::anonymous_account(&spawner, &proxy_type, index, Some(when)); + ensure!(proxy == who, Error::::NoPermission); + + let (_, deposit) = Proxies::::take(&who); + T::Currency::unreserve(&spawner, deposit); + } + } +} + +impl Module { + pub fn anonymous_account( + who: &T::AccountId, + proxy_type: &T::ProxyType, + index: u16, + maybe_when: Option<(T::BlockNumber, u32)>, + ) -> T::AccountId { + let (height, ext_index) = maybe_when.unwrap_or_else(|| ( + system::Module::::block_number(), + system::Module::::extrinsic_index().unwrap_or_default() + )); + let entropy = (b"modlpy/proxy____", who, height, ext_index, proxy_type, index) + .using_encoded(blake2_256); + T::AccountId::decode(&mut &entropy[..]).unwrap_or_default() + } +} diff --git a/frame/proxy/src/tests.rs b/frame/proxy/src/tests.rs new file mode 100644 index 0000000000000000000000000000000000000000..11f11e24d47725eac8a87fb37f37933aad199c8d --- /dev/null +++ b/frame/proxy/src/tests.rs @@ -0,0 +1,357 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Tests for Proxy Pallet + +#![cfg(test)] + +use super::*; + +use frame_support::{ + assert_ok, assert_noop, impl_outer_origin, parameter_types, impl_outer_dispatch, + weights::Weight, impl_outer_event, RuntimeDebug, dispatch::DispatchError, traits::Filter, +}; +use codec::{Encode, Decode}; +use sp_core::H256; +use sp_runtime::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; +use crate as proxy; + +impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} +} +impl_outer_event! { + pub enum TestEvent for Test { + system, + pallet_balances, + proxy, + pallet_utility, + } +} +impl_outer_dispatch! { + pub enum Call for Test where origin: Origin { + frame_system::System, + pallet_balances::Balances, + proxy::Proxy, + pallet_utility::Utility, + } +} + +// For testing the pallet, we construct most of a mock runtime. This means +// first constructing a configuration type (`Test`) which `impl`s each of the +// configuration traits of pallets we want to use. +#[derive(Clone, Eq, PartialEq)] +pub struct Test; +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} +impl frame_system::Trait for Test { + type BaseCallFilter = BaseFilter; + 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 = TestEvent; + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); +} +parameter_types! { + pub const ExistentialDeposit: u64 = 1; +} +impl pallet_balances::Trait for Test { + type Balance = u64; + type Event = TestEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); +} +impl pallet_utility::Trait for Test { + type Event = TestEvent; + type Call = Call; + type WeightInfo = (); +} +parameter_types! { + pub const ProxyDepositBase: u64 = 1; + pub const ProxyDepositFactor: u64 = 1; + pub const MaxProxies: u16 = 4; +} +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug)] +pub enum ProxyType { + Any, + JustTransfer, + JustUtility, +} +impl Default for ProxyType { fn default() -> Self { Self::Any } } +impl InstanceFilter for ProxyType { + fn filter(&self, c: &Call) -> bool { + match self { + ProxyType::Any => true, + ProxyType::JustTransfer => matches!(c, Call::Balances(pallet_balances::Call::transfer(..))), + ProxyType::JustUtility => matches!(c, Call::Utility(..)), + } + } + fn is_superset(&self, o: &Self) -> bool { + self == &ProxyType::Any || self == o + } +} +pub struct BaseFilter; +impl Filter for BaseFilter { + fn filter(c: &Call) -> bool { + match *c { + // Remark is used as a no-op call in the benchmarking + Call::System(SystemCall::remark(_)) => true, + Call::System(_) => false, + _ => true, + } + } +} +impl Trait for Test { + type Event = TestEvent; + type Call = Call; + type Currency = Balances; + type ProxyType = ProxyType; + type ProxyDepositBase = ProxyDepositBase; + type ProxyDepositFactor = ProxyDepositFactor; + type MaxProxies = MaxProxies; + type WeightInfo = (); +} + +type System = frame_system::Module; +type Balances = pallet_balances::Module; +type Utility = pallet_utility::Module; +type Proxy = Module; + +use frame_system::Call as SystemCall; +use pallet_balances::Call as BalancesCall; +use pallet_balances::Error as BalancesError; +use pallet_balances::Event as BalancesEvent; +use pallet_utility::Call as UtilityCall; +use pallet_utility::Event as UtilityEvent; +use super::Call as ProxyCall; + +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + pallet_balances::GenesisConfig:: { + balances: vec![(1, 10), (2, 10), (3, 10), (4, 10), (5, 2)], + }.assimilate_storage(&mut t).unwrap(); + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext +} + +fn last_event() -> TestEvent { + system::Module::::events().pop().expect("Event expected").event +} + +fn expect_event>(e: E) { + assert_eq!(last_event(), e.into()); +} + +fn last_events(n: usize) -> Vec { + system::Module::::events().into_iter().rev().take(n).rev().map(|e| e.event).collect() +} + +fn expect_events(e: Vec) { + assert_eq!(last_events(e.len()), e); +} + +#[test] +fn filtering_works() { + new_test_ext().execute_with(|| { + Balances::mutate_account(&1, |a| a.free = 1000); + assert_ok!(Proxy::add_proxy(Origin::signed(1), 2, ProxyType::Any)); + assert_ok!(Proxy::add_proxy(Origin::signed(1), 3, ProxyType::JustTransfer)); + assert_ok!(Proxy::add_proxy(Origin::signed(1), 4, ProxyType::JustUtility)); + + let call = Box::new(Call::Balances(BalancesCall::transfer(6, 1))); + assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone())); + expect_event(RawEvent::ProxyExecuted(Ok(()))); + assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone())); + expect_event(RawEvent::ProxyExecuted(Ok(()))); + assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone())); + expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin))); + + let derivative_id = Utility::derivative_account_id(1, 0); + Balances::mutate_account(&derivative_id, |a| a.free = 1000); + let inner = Box::new(Call::Balances(BalancesCall::transfer(6, 1))); + + let call = Box::new(Call::Utility(UtilityCall::as_derivative(0, inner.clone()))); + assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone())); + expect_event(RawEvent::ProxyExecuted(Ok(()))); + assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone())); + expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin))); + assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone())); + expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin))); + + let call = Box::new(Call::Utility(UtilityCall::batch(vec![*inner]))); + assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone())); + expect_events(vec![UtilityEvent::BatchCompleted.into(), RawEvent::ProxyExecuted(Ok(())).into()]); + assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone())); + expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin))); + assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone())); + expect_events(vec![ + UtilityEvent::BatchInterrupted(0, DispatchError::BadOrigin).into(), + RawEvent::ProxyExecuted(Ok(())).into(), + ]); + + let inner = Box::new(Call::Proxy(ProxyCall::add_proxy(5, ProxyType::Any))); + let call = Box::new(Call::Utility(UtilityCall::batch(vec![*inner]))); + assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone())); + expect_events(vec![UtilityEvent::BatchCompleted.into(), RawEvent::ProxyExecuted(Ok(())).into()]); + assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone())); + expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin))); + assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone())); + expect_events(vec![ + UtilityEvent::BatchInterrupted(0, DispatchError::BadOrigin).into(), + RawEvent::ProxyExecuted(Ok(())).into(), + ]); + + let call = Box::new(Call::Proxy(ProxyCall::remove_proxies())); + assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone())); + expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin))); + assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone())); + expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin))); + assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone())); + expect_events(vec![BalancesEvent::::Unreserved(1, 5).into(), RawEvent::ProxyExecuted(Ok(())).into()]); + }); +} + +#[test] +fn add_remove_proxies_works() { + new_test_ext().execute_with(|| { + assert_ok!(Proxy::add_proxy(Origin::signed(1), 2, ProxyType::Any)); + assert_noop!(Proxy::add_proxy(Origin::signed(1), 2, ProxyType::Any), Error::::Duplicate); + assert_eq!(Balances::reserved_balance(1), 2); + assert_ok!(Proxy::add_proxy(Origin::signed(1), 2, ProxyType::JustTransfer)); + assert_eq!(Balances::reserved_balance(1), 3); + assert_ok!(Proxy::add_proxy(Origin::signed(1), 3, ProxyType::Any)); + assert_eq!(Balances::reserved_balance(1), 4); + assert_ok!(Proxy::add_proxy(Origin::signed(1), 4, ProxyType::JustUtility)); + assert_eq!(Balances::reserved_balance(1), 5); + assert_noop!(Proxy::add_proxy(Origin::signed(1), 4, ProxyType::Any), Error::::TooMany); + assert_noop!(Proxy::remove_proxy(Origin::signed(1), 3, ProxyType::JustTransfer), Error::::NotFound); + assert_ok!(Proxy::remove_proxy(Origin::signed(1), 4, ProxyType::JustUtility)); + assert_eq!(Balances::reserved_balance(1), 4); + assert_ok!(Proxy::remove_proxy(Origin::signed(1), 3, ProxyType::Any)); + assert_eq!(Balances::reserved_balance(1), 3); + assert_ok!(Proxy::remove_proxy(Origin::signed(1), 2, ProxyType::Any)); + assert_eq!(Balances::reserved_balance(1), 2); + assert_ok!(Proxy::remove_proxy(Origin::signed(1), 2, ProxyType::JustTransfer)); + assert_eq!(Balances::reserved_balance(1), 0); + }); +} + +#[test] +fn cannot_add_proxy_without_balance() { + new_test_ext().execute_with(|| { + assert_ok!(Proxy::add_proxy(Origin::signed(5), 3, ProxyType::Any)); + assert_eq!(Balances::reserved_balance(5), 2); + assert_noop!( + Proxy::add_proxy(Origin::signed(5), 4, ProxyType::Any), + BalancesError::::InsufficientBalance + ); + }); +} + +#[test] +fn proxying_works() { + new_test_ext().execute_with(|| { + assert_ok!(Proxy::add_proxy(Origin::signed(1), 2, ProxyType::JustTransfer)); + assert_ok!(Proxy::add_proxy(Origin::signed(1), 3, ProxyType::Any)); + + let call = Box::new(Call::Balances(BalancesCall::transfer(6, 1))); + assert_noop!(Proxy::proxy(Origin::signed(4), 1, None, call.clone()), Error::::NotProxy); + assert_noop!( + Proxy::proxy(Origin::signed(2), 1, Some(ProxyType::Any), call.clone()), + Error::::NotProxy + ); + assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone())); + expect_event(RawEvent::ProxyExecuted(Ok(()))); + assert_eq!(Balances::free_balance(6), 1); + + let call = Box::new(Call::System(SystemCall::set_code(vec![]))); + assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone())); + expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin))); + + let call = Box::new(Call::Balances(BalancesCall::transfer_keep_alive(6, 1))); + assert_ok!(Call::Proxy(super::Call::proxy(1, None, call.clone())).dispatch(Origin::signed(2))); + expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin))); + assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone())); + expect_event(RawEvent::ProxyExecuted(Ok(()))); + assert_eq!(Balances::free_balance(6), 2); + }); +} + +#[test] +fn anonymous_works() { + new_test_ext().execute_with(|| { + assert_ok!(Proxy::anonymous(Origin::signed(1), ProxyType::Any, 0)); + let anon = Proxy::anonymous_account(&1, &ProxyType::Any, 0, None); + expect_event(RawEvent::AnonymousCreated(anon.clone(), 1, ProxyType::Any, 0)); + + // other calls to anonymous allowed as long as they're not exactly the same. + assert_ok!(Proxy::anonymous(Origin::signed(1), ProxyType::JustTransfer, 0)); + assert_ok!(Proxy::anonymous(Origin::signed(1), ProxyType::Any, 1)); + let anon2 = Proxy::anonymous_account(&2, &ProxyType::Any, 0, None); + assert_ok!(Proxy::anonymous(Origin::signed(2), ProxyType::Any, 0)); + assert_noop!(Proxy::anonymous(Origin::signed(1), ProxyType::Any, 0), Error::::Duplicate); + System::set_extrinsic_index(1); + assert_ok!(Proxy::anonymous(Origin::signed(1), ProxyType::Any, 0)); + System::set_extrinsic_index(0); + System::set_block_number(2); + assert_ok!(Proxy::anonymous(Origin::signed(1), ProxyType::Any, 0)); + + let call = Box::new(Call::Balances(BalancesCall::transfer(6, 1))); + assert_ok!(Balances::transfer(Origin::signed(3), anon, 5)); + assert_ok!(Proxy::proxy(Origin::signed(1), anon, None, call)); + expect_event(RawEvent::ProxyExecuted(Ok(()))); + assert_eq!(Balances::free_balance(6), 1); + + let call = Box::new(Call::Proxy(ProxyCall::kill_anonymous(1, ProxyType::Any, 0, 1, 0))); + assert_ok!(Proxy::proxy(Origin::signed(2), anon2, None, call.clone())); + let de = DispatchError::from(Error::::NoPermission).stripped(); + expect_event(RawEvent::ProxyExecuted(Err(de))); + assert_noop!( + Proxy::kill_anonymous(Origin::signed(1), 1, ProxyType::Any, 0, 1, 0), + Error::::NoPermission + ); + assert_eq!(Balances::free_balance(1), 0); + assert_ok!(Proxy::proxy(Origin::signed(1), anon, None, call.clone())); + assert_eq!(Balances::free_balance(1), 2); + assert_noop!(Proxy::proxy(Origin::signed(1), anon, None, call.clone()), Error::::NotProxy); + }); +} diff --git a/frame/randomness-collective-flip/Cargo.toml b/frame/randomness-collective-flip/Cargo.toml index acd1c216884c036715f0f52b997cb0b78d5c6669..64324bc8c59b6b908a4a9575865ba3ee395c45df 100644 --- a/frame/randomness-collective-flip/Cargo.toml +++ b/frame/randomness-collective-flip/Cargo.toml @@ -1,24 +1,27 @@ [package] name = "pallet-randomness-collective-flip" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME randomness collective flip pallet" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] safe-mix = { version = "1.0", default-features = false } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } [dev-dependencies] -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -sp-io = { version = "2.0.0-alpha.5", path = "../../primitives/io" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +sp-io = { version = "2.0.0-rc4", path = "../../primitives/io" } [features] default = ["std"] @@ -30,6 +33,3 @@ std = [ "sp-runtime/std", "sp-std/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/randomness-collective-flip/src/lib.rs b/frame/randomness-collective-flip/src/lib.rs index fdc465b4dc3bb0e9163bc750595a290138a7b24d..4f7c4ef5e803c88edf23358ac50a974cbfa8c276 100644 --- a/frame/randomness-collective-flip/src/lib.rs +++ b/frame/randomness-collective-flip/src/lib.rs @@ -1,25 +1,27 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # 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. +//! adversaries. Using this pallet as a randomness source is advisable primarily in low-security +//! situations like testing. //! //! ## Public Functions //! @@ -35,15 +37,15 @@ //! ### Example - Get random seed for the current block //! //! ``` -//! use frame_support::{decl_module, dispatch, traits::Randomness, weights::SimpleDispatchInfo}; +//! use frame_support::{decl_module, dispatch, traits::Randomness}; //! //! pub trait Trait: frame_system::Trait {} //! //! decl_module! { //! pub struct Module for enum Call where origin: T::Origin { -//! #[weight = SimpleDispatchInfo::default()] +//! #[weight = 0] //! pub fn random_module_example(origin) -> dispatch::DispatchResult { -//! let _random_seed = >::random_seed(); +//! let _random_value = >::random(&b"my context"[..]); //! Ok(()) //! } //! } @@ -57,7 +59,7 @@ use sp_std::{prelude::*, convert::TryInto}; use sp_runtime::traits::Hash; use frame_support::{ decl_module, decl_storage, traits::Randomness, - weights::{Weight, SimpleDispatchInfo, WeighData} + weights::Weight }; use safe_mix::TripletMix; use codec::Encode; @@ -83,7 +85,7 @@ decl_module! { values[index] = parent_hash; }); - SimpleDispatchInfo::default().weigh_data(()) + 0 } } } @@ -98,17 +100,6 @@ decl_storage! { } 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 @@ -116,22 +107,6 @@ impl Randomness for Module { /// 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`. @@ -183,6 +158,7 @@ mod tests { } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -195,6 +171,10 @@ mod tests { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); @@ -202,6 +182,7 @@ mod tests { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } type System = frame_system::Module; diff --git a/frame/recovery/Cargo.toml b/frame/recovery/Cargo.toml index 3347014f6e8cafc53a28626aad5124e35fa25b6a..63f4d4dcdd14672a7b96a8b0f920a058f1dad5a9 100644 --- a/frame/recovery/Cargo.toml +++ b/frame/recovery/Cargo.toml @@ -1,26 +1,29 @@ [package] name = "pallet-recovery" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME account recovery pallet" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } enumflags2 = { version = "0.6.2" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -pallet-balances = { version = "2.0.0-alpha.5", path = "../balances" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0-rc4", path = "../balances" } [features] default = ["std"] @@ -33,6 +36,3 @@ std = [ "frame-support/std", "frame-system/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/recovery/src/lib.rs b/frame/recovery/src/lib.rs index c055f2bd97c67777893d493feb4d51c3934048ed..9c7503666a7f47970e4119a40157c70d6e515cb0 100644 --- a/frame/recovery/src/lib.rs +++ b/frame/recovery/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Recovery Pallet //! @@ -159,7 +160,7 @@ use codec::{Encode, Decode}; use frame_support::{ decl_module, decl_event, decl_storage, decl_error, ensure, - Parameter, RuntimeDebug, weights::{GetDispatchInfo, SimpleDispatchInfo, FunctionOf}, + Parameter, RuntimeDebug, weights::GetDispatchInfo, traits::{Currency, ReservableCurrency, Get, BalanceStatus}, dispatch::PostDispatchInfo, }; @@ -319,6 +320,18 @@ decl_module! { pub struct Module for enum Call where origin: T::Origin { type Error = Error; + /// The base amount of currency needed to reserve for creating a recovery configuration. + const ConfigDepositBase: BalanceOf = T::ConfigDepositBase::get(); + + /// The amount of currency needed per additional user when creating a recovery configuration. + const FriendDepositFactor: BalanceOf = T::FriendDepositFactor::get(); + + /// The maximum amount of friends allowed in a recovery configuration. + const MaxFriends: u16 = T::MaxFriends::get(); + + /// The base amount of currency needed to reserve for starting a recovery. + const RecoveryDeposit: BalanceOf = T::RecoveryDeposit::get(); + /// Deposit one of this module's events by using the default implementation. fn deposit_event() = default; @@ -335,11 +348,7 @@ decl_module! { /// - The weight of the `call` + 10,000. /// - One storage lookup to check account is recovered by `who`. O(1) /// # - #[weight = FunctionOf( - |args: (&T::AccountId, &Box<::Call>)| args.1.get_dispatch_info().weight + 10_000, - |args: (&T::AccountId, &Box<::Call>)| args.1.get_dispatch_info().class, - true - )] + #[weight = (call.get_dispatch_info().weight + 10_000, call.get_dispatch_info().class)] fn as_recovered(origin, account: T::AccountId, call: Box<::Call> @@ -365,7 +374,7 @@ decl_module! { /// - One storage write O(1) /// - One event /// # - #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + #[weight = 0] fn set_recovered(origin, lost: T::AccountId, rescuer: T::AccountId) { ensure_root(origin)?; // Create the recovery storage item. @@ -400,7 +409,7 @@ decl_module! { /// /// Total Complexity: O(F + X) /// # - #[weight = SimpleDispatchInfo::FixedNormal(100_000)] + #[weight = 100_000_000] fn create_recovery(origin, friends: Vec, threshold: u16, @@ -460,7 +469,7 @@ decl_module! { /// /// Total Complexity: O(F + X) /// # - #[weight = SimpleDispatchInfo::FixedNormal(100_000)] + #[weight = 100_000_000] fn initiate_recovery(origin, account: T::AccountId) { let who = ensure_signed(origin)?; // Check that the account is recoverable @@ -506,7 +515,7 @@ decl_module! { /// /// Total Complexity: O(F + logF + V + logV) /// # - #[weight = SimpleDispatchInfo::FixedNormal(100_000)] + #[weight = 100_000_000] fn vouch_recovery(origin, lost: T::AccountId, rescuer: T::AccountId) { let who = ensure_signed(origin)?; // Get the recovery configuration for the lost account. @@ -545,7 +554,7 @@ decl_module! { /// /// Total Complexity: O(F + V) /// # - #[weight = SimpleDispatchInfo::FixedNormal(100_000)] + #[weight = 100_000_000] fn claim_recovery(origin, account: T::AccountId) { let who = ensure_signed(origin)?; // Get the recovery configuration for the lost account @@ -590,7 +599,7 @@ decl_module! { /// /// Total Complexity: O(V + X) /// # - #[weight = SimpleDispatchInfo::FixedNormal(30_000)] + #[weight = 30_000_000] fn close_recovery(origin, rescuer: T::AccountId) { let who = ensure_signed(origin)?; // Take the active recovery process started by the rescuer for this account. @@ -622,11 +631,11 @@ decl_module! { /// /// Total Complexity: O(F + X) /// # - #[weight = SimpleDispatchInfo::FixedNormal(30_000)] + #[weight = 30_000_000] fn remove_recovery(origin) { let who = ensure_signed(origin)?; // Check there are no active recoveries - let mut active_recoveries = >::iter_prefix(&who); + let mut active_recoveries = >::iter_prefix_values(&who); ensure!(active_recoveries.next().is_none(), Error::::StillActive); // Take the recovery configuration for this account. let recovery_config = >::take(&who).ok_or(Error::::NotRecoverable)?; @@ -647,7 +656,7 @@ decl_module! { /// # /// - One storage mutation to check account is recovered by `who`. O(1) /// # - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] fn cancel_recovered(origin, account: T::AccountId) { let who = ensure_signed(origin)?; // Check `who` is allowed to make a call on behalf of `account` diff --git a/frame/recovery/src/mock.rs b/frame/recovery/src/mock.rs index 9327ece572212af48e739eac3725925592c9bc95..6b8ef169c0076ee441e19d6d849063b1b09e7b5b 100644 --- a/frame/recovery/src/mock.rs +++ b/frame/recovery/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utilities @@ -24,8 +25,6 @@ use frame_support::{ traits::{OnInitialize, OnFinalize}, }; use sp_core::H256; -// The testing primitives are very useful for avoiding having to work with signatures -// or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. use sp_runtime::{ Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header, }; @@ -49,9 +48,6 @@ impl_outer_dispatch! { } } -// For testing the pallet, we construct most of a mock runtime. This means -// first constructing a configuration type (`Test`) which `impl`s each of the -// configuration traits of pallets we want to use. #[derive(Clone, Eq, PartialEq)] pub struct Test; @@ -63,6 +59,7 @@ parameter_types! { } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Call = Call; type Index = u64; @@ -75,6 +72,10 @@ impl frame_system::Trait for Test { type Event = TestEvent; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -82,6 +83,7 @@ impl frame_system::Trait for Test { type AccountData = pallet_balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } parameter_types! { @@ -94,6 +96,7 @@ impl pallet_balances::Trait for Test { type Event = TestEvent; type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; + type WeightInfo = (); } parameter_types! { diff --git a/frame/recovery/src/tests.rs b/frame/recovery/src/tests.rs index fb993043a5b005f4e94976f99a9701af6ab83b79..8e9484f0fb089588cfe1ef9c347fcbe6d517ae8d 100644 --- a/frame/recovery/src/tests.rs +++ b/frame/recovery/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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. +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Tests for the module. @@ -45,7 +46,7 @@ fn set_recovered_works() { // Not accessible by a normal user assert_noop!(Recovery::set_recovered(Origin::signed(1), 5, 1), BadOrigin); // Root can set a recovered account though - assert_ok!(Recovery::set_recovered(Origin::ROOT, 5, 1)); + assert_ok!(Recovery::set_recovered(Origin::root(), 5, 1)); // Account 1 should now be able to make a call through account 5 let call = Box::new(Call::Balances(BalancesCall::transfer(1, 100))); assert_ok!(Recovery::as_recovered(Origin::signed(1), 5, call)); diff --git a/frame/scheduler/Cargo.toml b/frame/scheduler/Cargo.toml index 531de95867bbbaace5557f7b0e2d7e3d057088b8..003a8c20c504c9f310074b955ba6a3bbdd864cb7 100644 --- a/frame/scheduler/Cargo.toml +++ b/frame/scheduler/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-scheduler" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" license = "Unlicense" @@ -11,15 +11,17 @@ description = "FRAME example pallet" [dependencies] serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.2.0", default-features = false } -frame-benchmarking = { version = "2.0.0-alpha.4", default-features = false, path = "../benchmarking" } -frame-support = { version = "2.0.0-alpha.4", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.4", default-features = false, path = "../system" } -sp-runtime = { version = "2.0.0-alpha.4", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "2.0.0-alpha.4", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-alpha.4", default-features = false, path = "../../primitives/io" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } + +frame-benchmarking = { version = "2.0.0-rc4", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "2.0.0-alpha.4", path = "../../primitives/core", default-features = false } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core", default-features = false } +substrate-test-utils = { version = "2.0.0-rc4", path = "../../test-utils" } [features] default = ["std"] @@ -33,3 +35,8 @@ std = [ "sp-io/std", "sp-std/std" ] +runtime-benchmarks = [ + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", +] diff --git a/frame/scheduler/src/benchmarking.rs b/frame/scheduler/src/benchmarking.rs new file mode 100644 index 0000000000000000000000000000000000000000..748017829fa133bfe34a60660701036dbf0e2a2d --- /dev/null +++ b/frame/scheduler/src/benchmarking.rs @@ -0,0 +1,161 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Scheduler pallet benchmarking. + +#![cfg(feature = "runtime-benchmarks")] + +use super::*; +use sp_std::{vec, prelude::*}; +use frame_system::RawOrigin; +use frame_support::{ensure, traits::OnInitialize}; +use frame_benchmarking::benchmarks; + +use crate::Module as Scheduler; +use frame_system::Module as System; + +const MAX_SCHEDULED: u32 = 50; +const BLOCK_NUMBER: u32 = 2; + +// Add `n` named items to the schedule +fn fill_schedule (when: T::BlockNumber, n: u32) -> Result<(), &'static str> { + // Essentially a no-op call. + let call = frame_system::Call::set_storage(vec![]); + for i in 0..n { + // Named schedule is strictly heavier than anonymous + Scheduler::::do_schedule_named( + i.encode(), + when, + // Add periodicity + Some((T::BlockNumber::one(), 100)), + // HARD_DEADLINE priority means it gets executed no matter what + 0, + frame_system::RawOrigin::Root.into(), + call.clone().into(), + )?; + } + ensure!(Agenda::::get(when).len() == n as usize, "didn't fill schedule"); + Ok(()) +} + +benchmarks! { + _ { } + + schedule { + let s in 0 .. MAX_SCHEDULED; + let when = BLOCK_NUMBER.into(); + let periodic = Some((T::BlockNumber::one(), 100)); + let priority = 0; + // Essentially a no-op call. + let call = Box::new(frame_system::Call::set_storage(vec![]).into()); + + fill_schedule::(when, s)?; + }: _(RawOrigin::Root, when, periodic, priority, call) + verify { + ensure!( + Agenda::::get(when).len() == (s + 1) as usize, + "didn't add to schedule" + ); + } + + cancel { + let s in 1 .. MAX_SCHEDULED; + let when = BLOCK_NUMBER.into(); + + fill_schedule::(when, s)?; + assert_eq!(Agenda::::get(when).len(), s as usize); + }: _(RawOrigin::Root, when, 0) + verify { + ensure!( + Lookup::::get(0.encode()).is_none(), + "didn't remove from lookup" + ); + // Removed schedule is NONE + ensure!( + Agenda::::get(when)[0].is_none(), + "didn't remove from schedule" + ); + } + + schedule_named { + let s in 0 .. MAX_SCHEDULED; + let id = s.encode(); + let when = BLOCK_NUMBER.into(); + let periodic = Some((T::BlockNumber::one(), 100)); + let priority = 0; + // Essentially a no-op call. + let call = Box::new(frame_system::Call::set_storage(vec![]).into()); + + fill_schedule::(when, s)?; + }: _(RawOrigin::Root, id, when, periodic, priority, call) + verify { + ensure!( + Agenda::::get(when).len() == (s + 1) as usize, + "didn't add to schedule" + ); + } + + cancel_named { + let s in 1 .. MAX_SCHEDULED; + let when = BLOCK_NUMBER.into(); + + fill_schedule::(when, s)?; + }: _(RawOrigin::Root, 0.encode()) + verify { + ensure!( + Lookup::::get(0.encode()).is_none(), + "didn't remove from lookup" + ); + // Removed schedule is NONE + ensure!( + Agenda::::get(when)[0].is_none(), + "didn't remove from schedule" + ); + } + + on_initialize { + let s in 0 .. MAX_SCHEDULED; + let when = BLOCK_NUMBER.into(); + fill_schedule::(when, s)?; + }: { Scheduler::::on_initialize(BLOCK_NUMBER.into()); } + verify { + assert_eq!(System::::event_count(), s); + // Next block should have all the schedules again + ensure!( + Agenda::::get(when + T::BlockNumber::one()).len() == s as usize, + "didn't append schedule" + ); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::tests::{new_test_ext, Test}; + use frame_support::assert_ok; + + #[test] + fn test_benchmarks() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_schedule::()); + assert_ok!(test_benchmark_cancel::()); + assert_ok!(test_benchmark_schedule_named::()); + assert_ok!(test_benchmark_cancel_named::()); + assert_ok!(test_benchmark_on_initialize::()); + }); + } +} diff --git a/frame/scheduler/src/lib.rs b/frame/scheduler/src/lib.rs index f70204cb1a6b7201c89173cbe0dba6d5f10236ab..0b8c9173a9c3d4e4c2992e55d516ae4aa2e5d907 100644 --- a/frame/scheduler/src/lib.rs +++ b/frame/scheduler/src/lib.rs @@ -1,59 +1,85 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! # Scheduler +//! A module for scheduling dispatches. //! -//! \# Scheduler +//! - [`scheduler::Trait`](./trait.Trait.html) +//! - [`Call`](./enum.Call.html) +//! - [`Module`](./struct.Module.html) //! -//! - \[`scheduler::Trait`](./trait.Trait.html) -//! - \[`Call`](./enum.Call.html) -//! - \[`Module`](./struct.Module.html) +//! ## Overview //! -//! \## Overview +//! This module exposes capabilities for scheduling dispatches to occur at a +//! specified block number or at a specified period. These scheduled dispatches +//! may be named or anonymous and may be canceled. //! -//! // Short description of pallet's purpose. -//! // Links to Traits that should be implemented. -//! // What this pallet is for. -//! // What functionality the pallet provides. -//! // When to use the pallet (use case examples). -//! // How it is used. -//! // Inputs it uses and the source of each input. -//! // Outputs it produces. +//! **NOTE:** The scheduled calls will be dispatched with the default filter +//! for the origin: namely `frame_system::Trait::BaseCallFilter` for all origin +//! except root which will get no filter. And not the filter contained in origin +//! use to call `fn schedule`. //! -//! \## Terminology +//! If a call is scheduled using proxy or whatever mecanism which adds filter, +//! then those filter will not be used when dispatching the schedule call. //! -//! \## Goals +//! ## Interface //! -//! \## Interface +//! ### Dispatchable Functions //! -//! \### Dispatchable Functions +//! * `schedule` - schedule a dispatch, which may be periodic, to occur at a +//! specified block and with a specified priority. +//! * `cancel` - cancel a scheduled dispatch, specified by block number and +//! index. +//! * `schedule_named` - augments the `schedule` interface with an additional +//! `Vec` parameter that can be used for identification. +//! * `cancel_named` - the named complement to the cancel function. // Ensure we're `no_std` when compiling for Wasm. #![cfg_attr(not(feature = "std"), no_std)] -use sp_std::prelude::*; -use codec::{Encode, Decode}; -use sp_runtime::{RuntimeDebug, traits::{Zero, One}}; +mod benchmarking; + +use sp_std::{prelude::*, marker::PhantomData, borrow::Borrow}; +use codec::{Encode, Decode, Codec}; +use sp_runtime::{RuntimeDebug, traits::{Zero, One, BadOrigin}}; use frame_support::{ - dispatch::{Dispatchable, DispatchResult, Parameter}, decl_module, decl_storage, decl_event, - traits::{Get, schedule}, + decl_module, decl_storage, decl_event, decl_error, IterableStorageMap, + dispatch::{Dispatchable, DispatchError, DispatchResult, Parameter}, + traits::{Get, schedule, OriginTrait, EnsureOrigin, IsType}, weights::{GetDispatchInfo, Weight}, }; use frame_system::{self as system}; +pub trait WeightInfo { + fn schedule(s: u32, ) -> Weight; + fn cancel(s: u32, ) -> Weight; + fn schedule_named(s: u32, ) -> Weight; + fn cancel_named(s: u32, ) -> Weight; + fn on_initialize(s: u32, ) -> Weight; +} + +impl WeightInfo for () { + fn schedule(_s: u32, ) -> Weight { 1_000_000_000 } + fn cancel(_s: u32, ) -> Weight { 1_000_000_000 } + fn schedule_named(_s: u32, ) -> Weight { 1_000_000_000 } + fn cancel_named(_s: u32, ) -> Weight { 1_000_000_000 } + fn on_initialize(_s: u32, ) -> Weight { 1_000_000_000 } +} + /// Our pallet's configuration trait. All our types and constants go in here. If the /// pallet is dependent on specific other pallets, then their configuration traits /// should be added to our implied traits list. @@ -64,14 +90,24 @@ pub trait Trait: system::Trait { type Event: From> + Into<::Event>; /// The aggregated origin which the dispatch will take. - type Origin: From>; + type Origin: OriginTrait + From + IsType<::Origin>; + + /// The caller origin, overarching type of all pallets origins. + type PalletsOrigin: From> + Codec + Clone + Eq; /// The aggregated call type. - type Call: Parameter + Dispatchable::Origin> + GetDispatchInfo; + type Call: Parameter + Dispatchable::Origin> + GetDispatchInfo + From>; /// The maximum weight that may be scheduled per block for any dispatchables of less priority /// than `schedule::HARD_DEADLINE`. type MaximumWeight: Get; + + /// Required origin to schedule or cancel calls. + type ScheduleOrigin: EnsureOrigin<::Origin>; + + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; } /// Just a simple index for naming period tasks. @@ -79,9 +115,19 @@ pub type PeriodicIndex = u32; /// The location of a scheduled task that can be used to remove it. pub type TaskAddress = (BlockNumber, u32); +#[cfg_attr(any(feature = "std", test), derive(PartialEq, Eq))] +#[derive(Clone, RuntimeDebug, Encode, Decode)] +struct ScheduledV1 { + maybe_id: Option>, + priority: schedule::Priority, + call: Call, + maybe_periodic: Option>, +} + /// Information regarding an item to be executed in the future. +#[cfg_attr(any(feature = "std", test), derive(PartialEq, Eq))] #[derive(Clone, RuntimeDebug, Encode, Decode)] -pub struct Scheduled { +pub struct ScheduledV2 { /// The unique identity for this task, if there is one. maybe_id: Option>, /// This task's priority. @@ -90,31 +136,160 @@ pub struct Scheduled { call: Call, /// If the call is periodic, then this points to the information concerning that. maybe_periodic: Option>, + /// The origin to dispatch the call. + origin: PalletsOrigin, + _phantom: PhantomData, +} + +/// The current version of Scheduled struct. +pub type Scheduled = ScheduledV2; + +// A value placed in storage that represents the current version of the Scheduler storage. +// This value is used by the `on_runtime_upgrade` logic to determine whether we run +// storage migration logic. +#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug)] +enum Releases { + V1, + V2, +} + +impl Default for Releases { + fn default() -> Self { + Releases::V1 + } } decl_storage! { trait Store for Module as Scheduler { /// Items to be executed, indexed by the block number that they should be executed on. pub Agenda: map hasher(twox_64_concat) T::BlockNumber - => Vec::Call, T::BlockNumber>>>; + => Vec::Call, T::BlockNumber, T::PalletsOrigin, T::AccountId>>>; /// Lookup from identity to the block number and index of the task. Lookup: map hasher(twox_64_concat) Vec => Option>; + + /// Storage version of the pallet. + /// + /// New networks start with last version. + StorageVersion build(|_| Releases::V2): Releases; } } decl_event!( pub enum Event where ::BlockNumber { - Scheduled(BlockNumber), + Scheduled(BlockNumber, u32), + Canceled(BlockNumber, u32), Dispatched(TaskAddress, Option>, DispatchResult), } ); +decl_error! { + pub enum Error for Module { + /// Failed to schedule a call + FailedToSchedule, + /// Failed to cancel a scheduled call + FailedToCancel, + /// Given target block number is in the past. + TargetBlockNumberInPast, + } +} + decl_module! { - // Simple declaration of the `Module` type. Lets the macro know what its working on. + /// Scheduler module declaration. pub struct Module for enum Call where origin: ::Origin { + type Error = Error; fn deposit_event() = default; + /// Anonymously schedule a task. + /// + /// # + /// - S = Number of already scheduled calls + /// - Base Weight: 22.29 + .126 * S µs + /// - DB Weight: + /// - Read: Agenda + /// - Write: Agenda + /// - Will use base weight of 25 which should be good for up to 30 scheduled calls + /// # + #[weight = 25_000_000 + T::DbWeight::get().reads_writes(1, 1)] + fn schedule(origin, + when: T::BlockNumber, + maybe_periodic: Option>, + priority: schedule::Priority, + call: Box<::Call>, + ) { + T::ScheduleOrigin::ensure_origin(origin.clone())?; + let origin = ::Origin::from(origin); + Self::do_schedule(when, maybe_periodic, priority, origin.caller().clone(), *call)?; + } + + /// Cancel an anonymously scheduled task. + /// + /// # + /// - S = Number of already scheduled calls + /// - Base Weight: 22.15 + 2.869 * S µs + /// - DB Weight: + /// - Read: Agenda + /// - Write: Agenda, Lookup + /// - Will use base weight of 100 which should be good for up to 30 scheduled calls + /// # + #[weight = 100_000_000 + T::DbWeight::get().reads_writes(1, 2)] + fn cancel(origin, when: T::BlockNumber, index: u32) { + T::ScheduleOrigin::ensure_origin(origin.clone())?; + let origin = ::Origin::from(origin); + Self::do_cancel(Some(origin.caller().clone()), (when, index))?; + } + + /// Schedule a named task. + /// + /// # + /// - S = Number of already scheduled calls + /// - Base Weight: 29.6 + .159 * S µs + /// - DB Weight: + /// - Read: Agenda, Lookup + /// - Write: Agenda, Lookup + /// - Will use base weight of 35 which should be good for more than 30 scheduled calls + /// # + #[weight = 35_000_000 + T::DbWeight::get().reads_writes(2, 2)] + fn schedule_named(origin, + id: Vec, + when: T::BlockNumber, + maybe_periodic: Option>, + priority: schedule::Priority, + call: Box<::Call>, + ) { + T::ScheduleOrigin::ensure_origin(origin.clone())?; + let origin = ::Origin::from(origin); + Self::do_schedule_named(id, when, maybe_periodic, priority, origin.caller().clone(), *call)?; + } + + /// Cancel a named scheduled task. + /// + /// # + /// - S = Number of already scheduled calls + /// - Base Weight: 24.91 + 2.907 * S µs + /// - DB Weight: + /// - Read: Agenda, Lookup + /// - Write: Agenda, Lookup + /// - Will use base weight of 100 which should be good for up to 30 scheduled calls + /// # + #[weight = 100_000_000 + T::DbWeight::get().reads_writes(2, 2)] + fn cancel_named(origin, id: Vec) { + T::ScheduleOrigin::ensure_origin(origin.clone())?; + let origin = ::Origin::from(origin); + Self::do_cancel_named(Some(origin.caller().clone()), id)?; + } + + /// Execute the scheduled calls + /// + /// # + /// - S = Number of already scheduled calls + /// - N = Named scheduled calls + /// - P = Periodic Calls + /// - Base Weight: 9.243 + 23.45 * S µs + /// - DB Weight: + /// - Read: Agenda + Lookup * N + Agenda(Future) * P + /// - Write: Agenda + Lookup * N + Agenda(future) * P + /// # fn on_initialize(now: T::BlockNumber) -> Weight { let limit = T::MaximumWeight::get(); let mut queued = Agenda::::take(now).into_iter() @@ -122,16 +297,34 @@ decl_module! { .filter_map(|(index, s)| s.map(|inner| (index as u32, inner))) .collect::>(); queued.sort_by_key(|(_, s)| s.priority); - let mut result = 0; - let unused_items = queued.into_iter() + let base_weight: Weight = T::DbWeight::get().reads_writes(1, 2) // Agenda + Agenda(next) + .saturating_add(10_000_000); // Base Weight + let mut total_weight: Weight = 0; + queued.into_iter() .enumerate() - .scan(0, |cumulative_weight, (order, (index, s))| { - *cumulative_weight += s.call.get_dispatch_info().weight; + .scan(base_weight, |cumulative_weight, (order, (index, s))| { + *cumulative_weight = cumulative_weight + .saturating_add(s.call.get_dispatch_info().weight) + .saturating_add(25_000_000); // Base multiplier + + if s.maybe_id.is_some() { + // Remove/Modify Lookup + *cumulative_weight = cumulative_weight.saturating_add(T::DbWeight::get().writes(1)); + } + if s.maybe_periodic.is_some() { + // Read/Write Agenda for future block + *cumulative_weight = cumulative_weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); + } + Some((order, index, *cumulative_weight, s)) }) .filter_map(|(order, index, cumulative_weight, mut s)| { + // We allow a scheduled call if any is true: + // - It's priority is `HARD_DEADLINE` + // - It does not push the weight past the limit. + // - It is the first item in the schedule if s.priority <= schedule::HARD_DEADLINE || cumulative_weight <= limit || order == 0 { - let r = s.call.clone().dispatch(system::RawOrigin::Root.into()); + let r = s.call.clone().dispatch(s.origin.clone().into()); let maybe_id = s.maybe_id.clone(); if let &Some((period, count)) = &s.maybe_periodic { if count > 1 { @@ -140,11 +333,12 @@ decl_module! { s.maybe_periodic = None; } let next = now + period; + // If scheduled is named, place it's information in `Lookup` if let Some(ref id) = s.maybe_id { - let next_index = Agenda::::decode_len(now + period).unwrap_or(0) as u32; - Lookup::::insert(id, (next, next_index)); + let next_index = Agenda::::decode_len(now + period).unwrap_or(0); + Lookup::::insert(id, (next, next_index as u32)); } - Agenda::::append_or_insert(next, &[Some(s)][..]); + Agenda::::append(next, Some(s)); } else { if let Some(ref id) = s.maybe_id { Lookup::::remove(id); @@ -155,67 +349,121 @@ decl_module! { maybe_id, r.map(|_| ()).map_err(|e| e.error) )); - result = cumulative_weight; + total_weight = cumulative_weight; None } else { Some(Some(s)) } }) - .collect::>(); - if !unused_items.is_empty() { - let next = now + One::one(); - Agenda::::append_or_insert(next, &unused_items[..]); - } - result + .for_each(|unused| { + let next = now + One::one(); + Agenda::::append(next, unused); + }); + + total_weight } } } -impl schedule::Anon::Call> for Module { - type Address = TaskAddress; +impl Module { + /// Migrate storage format from V1 to V2. + /// Return true if migration is performed. + pub fn migrate_v1_to_t2() -> bool { + if StorageVersion::get() == Releases::V1 { + StorageVersion::put(Releases::V2); - fn schedule( + Agenda::::translate::< + Vec::Call, T::BlockNumber>>>, _ + >(|_, agenda| Some( + agenda + .into_iter() + .map(|schedule| schedule.map(|schedule| ScheduledV2 { + maybe_id: schedule.maybe_id, + priority: schedule.priority, + call: schedule.call, + maybe_periodic: schedule.maybe_periodic, + origin: system::RawOrigin::Root.into(), + _phantom: Default::default(), + })) + .collect::>() + )); + + true + } else { + false + } + } + + fn do_schedule( when: T::BlockNumber, maybe_periodic: Option>, priority: schedule::Priority, + origin: T::PalletsOrigin, call: ::Call - ) -> Self::Address { + ) -> Result, DispatchError> { + if when <= frame_system::Module::::block_number() { + return Err(Error::::TargetBlockNumberInPast.into()) + } + // sanitize maybe_periodic let maybe_periodic = maybe_periodic .filter(|p| p.1 > 1 && !p.0.is_zero()) // Remove one from the number of repetitions since we will schedule one now. .map(|(p, c)| (p, c - 1)); - let s = Some(Scheduled { maybe_id: None, priority, call, maybe_periodic }); - Agenda::::append_or_insert(when, &[s][..]); - (when, Agenda::::decode_len(when).unwrap_or(1) as u32 - 1) + let s = Some(Scheduled { + maybe_id: None, priority, call, maybe_periodic, origin, _phantom: PhantomData::::default(), + }); + Agenda::::append(when, s); + let index = Agenda::::decode_len(when).unwrap_or(1) as u32 - 1; + Self::deposit_event(RawEvent::Scheduled(when, index)); + + Ok((when, index)) } - fn cancel((when, index): Self::Address) -> Result<(), ()> { - if let Some(s) = Agenda::::mutate(when, |agenda| agenda.get_mut(index as usize).and_then(Option::take)) { + fn do_cancel( + origin: Option, + (when, index): TaskAddress + ) -> Result<(), DispatchError> { + let scheduled = Agenda::::try_mutate( + when, + |agenda| { + agenda.get_mut(index as usize) + .map_or(Ok(None), |s| -> Result>, DispatchError> { + if let (Some(ref o), Some(ref s)) = (origin, s.borrow()) { + if *o != s.origin { + return Err(BadOrigin.into()); + } + }; + Ok(s.take()) + }) + }, + )?; + if let Some(s) = scheduled { if let Some(id) = s.maybe_id { - Lookup::::remove(id) + Lookup::::remove(id); } + Self::deposit_event(RawEvent::Canceled(when, index)); Ok(()) } else { - Err(()) + Err(Error::::FailedToCancel)? } } -} -impl schedule::Named::Call> for Module { - type Address = TaskAddress; - - fn schedule_named( - id: impl Encode, + fn do_schedule_named( + id: Vec, when: T::BlockNumber, maybe_periodic: Option>, priority: schedule::Priority, + origin: T::PalletsOrigin, call: ::Call, - ) -> Result { - // determine id and ensure it is unique - let id = id.encode(); + ) -> Result, DispatchError> { + // ensure id it is unique if Lookup::::contains_key(&id) { - return Err(()) + return Err(Error::::FailedToSchedule)? + } + + if when <= frame_system::Module::::block_number() { + return Err(Error::::TargetBlockNumberInPast.into()) } // sanitize maybe_periodic @@ -224,22 +472,76 @@ impl schedule::Named::Call> for Module // Remove one from the number of repetitions since we will schedule one now. .map(|(p, c)| (p, c - 1)); - let s = Scheduled { maybe_id: Some(id.clone()), priority, call, maybe_periodic }; - Agenda::::append_or_insert(when, &[Some(s)][..]); + let s = Scheduled { + maybe_id: Some(id.clone()), priority, call, maybe_periodic, origin, _phantom: Default::default() + }; + Agenda::::append(when, Some(s)); let index = Agenda::::decode_len(when).unwrap_or(1) as u32 - 1; let address = (when, index); Lookup::::insert(&id, &address); + Self::deposit_event(RawEvent::Scheduled(when, index)); + Ok(address) } - fn cancel_named(id: impl Encode) -> Result<(), ()> { - if let Some((when, index)) = id.using_encoded(|d| Lookup::::take(d)) { - let i = index as usize; - Agenda::::mutate(when, |agenda| if let Some(s) = agenda.get_mut(i) { *s = None }); - Ok(()) - } else { - Err(()) - } + fn do_cancel_named(origin: Option, id: Vec) -> DispatchResult { + Lookup::::try_mutate_exists(id, |lookup| -> DispatchResult { + if let Some((when, index)) = lookup.take() { + let i = index as usize; + Agenda::::try_mutate(when, |agenda| -> DispatchResult { + if let Some(s) = agenda.get_mut(i) { + if let (Some(ref o), Some(ref s)) = (origin, s.borrow()) { + if *o != s.origin { + return Err(BadOrigin.into()); + } + } + *s = None; + } + Ok(()) + })?; + Self::deposit_event(RawEvent::Canceled(when, index)); + Ok(()) + } else { + Err(Error::::FailedToCancel)? + } + }) + } +} + +impl schedule::Anon::Call, T::PalletsOrigin> for Module { + type Address = TaskAddress; + + fn schedule( + when: T::BlockNumber, + maybe_periodic: Option>, + priority: schedule::Priority, + origin: T::PalletsOrigin, + call: ::Call + ) -> Result { + Self::do_schedule(when, maybe_periodic, priority, origin, call) + } + + fn cancel((when, index): Self::Address) -> Result<(), ()> { + Self::do_cancel(None, (when, index)).map_err(|_| ()) + } +} + +impl schedule::Named::Call, T::PalletsOrigin> for Module { + type Address = TaskAddress; + + fn schedule_named( + id: Vec, + when: T::BlockNumber, + maybe_periodic: Option>, + priority: schedule::Priority, + origin: T::PalletsOrigin, + call: ::Call, + ) -> Result { + Self::do_schedule_named(id, when, maybe_periodic, priority, origin, call).map_err(|_| ()) + } + + fn cancel_named(id: Vec) -> Result<(), ()> { + Self::do_cancel_named(None, id).map_err(|_| ()) } } @@ -248,58 +550,59 @@ mod tests { use super::*; use frame_support::{ - impl_outer_event, impl_outer_origin, impl_outer_dispatch, parameter_types, assert_ok, - traits::{OnInitialize, OnFinalize, schedule::{Anon, Named}}, - weights::{DispatchClass, FunctionOf} + impl_outer_event, impl_outer_origin, impl_outer_dispatch, parameter_types, assert_ok, ord_parameter_types, + assert_noop, assert_err, Hashable, + traits::{OnInitialize, OnFinalize, Filter}, + weights::constants::RocksDbWeight, }; use sp_core::H256; - // The testing primitives are very useful for avoiding having to work with signatures - // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. use sp_runtime::{ Perbill, testing::Header, traits::{BlakeTwo256, IdentityLookup}, }; + use frame_system::{EnsureOneOf, EnsureRoot, EnsureSignedBy}; use crate as scheduler; mod logger { use super::*; use std::cell::RefCell; - use frame_system::ensure_root; thread_local! { - static LOG: RefCell> = RefCell::new(Vec::new()); + static LOG: RefCell> = RefCell::new(Vec::new()); } - pub fn log() -> Vec { + pub fn log() -> Vec<(OriginCaller, u32)> { LOG.with(|log| log.borrow().clone()) } pub trait Trait: system::Trait { type Event: From + Into<::Event>; } - decl_storage! { - trait Store for Module as Logger { - } - } decl_event! { pub enum Event { Logged(u32, Weight), } } decl_module! { - // Simple declaration of the `Module` type. Lets the macro know what its working on. - pub struct Module for enum Call where origin: ::Origin { + pub struct Module for enum Call + where + origin: ::Origin, + ::Origin: OriginTrait + { fn deposit_event() = default; - #[weight = FunctionOf( - |args: (&u32, &Weight)| *args.1, - |_: (&u32, &Weight)| DispatchClass::Normal, - true - )] + #[weight = *weight] fn log(origin, i: u32, weight: Weight) { - ensure_root(origin)?; Self::deposit_event(Event::Logged(i, weight)); LOG.with(|log| { - log.borrow_mut().push(i); + log.borrow_mut().push((origin.caller().clone(), i)); + }) + } + + #[weight = *weight] + fn log_without_filter(origin, i: u32, weight: Weight) { + Self::deposit_event(Event::Logged(i, weight)); + LOG.with(|log| { + log.borrow_mut().push((origin.caller().clone(), i)); }) } } @@ -324,20 +627,27 @@ mod tests { scheduler, } } - // For testing the pallet, we construct most of a mock runtime. This means - // first constructing a configuration type (`Test`) which `impl`s each of the - // configuration traits of pallets we want to use. + + // Scheduler must dispatch with root and no filter, this tests base filter is indeed not used. + pub struct BaseFilter; + impl Filter for BaseFilter { + fn filter(call: &Call) -> bool { + !matches!(call, Call::Logger(logger::Call::log(_, _))) + } + } + #[derive(Clone, Eq, PartialEq)] pub struct Test; parameter_types! { pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockWeight: Weight = 2_000_000_000_000; pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl system::Trait for Test { + type BaseCallFilter = BaseFilter; type Origin = Origin; - type Call = (); + type Call = Call; type Index = u64; type BlockNumber = u64; type Hash = H256; @@ -348,6 +658,10 @@ mod tests { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = RocksDbWeight; + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -355,26 +669,32 @@ mod tests { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } impl logger::Trait for Test { type Event = (); } parameter_types! { - pub const MaximumWeight: Weight = 10_000; + pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * MaximumBlockWeight::get(); + } + ord_parameter_types! { + pub const One: u64 = 1; } + impl Trait for Test { type Event = (); type Origin = Origin; + type PalletsOrigin = OriginCaller; type Call = Call; - type MaximumWeight = MaximumWeight; + type MaximumWeight = MaximumSchedulerWeight; + type ScheduleOrigin = EnsureOneOf, EnsureSignedBy>; + type WeightInfo = (); } type System = system::Module; type Logger = logger::Module; type Scheduler = Module; - // This function basically just builds a genesis storage key/value store according to - // our desired mockup. - fn new_test_ext() -> sp_io::TestExternalities { + pub fn new_test_ext() -> sp_io::TestExternalities { let t = system::GenesisConfig::default().build_storage::().unwrap(); t.into() } @@ -387,16 +707,22 @@ mod tests { } } + fn root() -> OriginCaller { + system::RawOrigin::Root.into() + } + #[test] fn basic_scheduling_works() { new_test_ext().execute_with(|| { - Scheduler::schedule(4, None, 127, Call::Logger(logger::Call::log(42, 1000))); + let call = Call::Logger(logger::Call::log(42, 1000)); + assert!(!::BaseCallFilter::filter(&call)); + let _ = Scheduler::do_schedule(4, None, 127, root(), call); run_to_block(3); assert!(logger::log().is_empty()); run_to_block(4); - assert_eq!(logger::log(), vec![42u32]); + assert_eq!(logger::log(), vec![(root(), 42u32)]); run_to_block(100); - assert_eq!(logger::log(), vec![42u32]); + assert_eq!(logger::log(), vec![(root(), 42u32)]); }); } @@ -404,21 +730,23 @@ mod tests { fn periodic_scheduling_works() { new_test_ext().execute_with(|| { // at #4, every 3 blocks, 3 times. - Scheduler::schedule(4, Some((3, 3)), 127, Call::Logger(logger::Call::log(42, 1000))); + let _ = Scheduler::do_schedule( + 4, Some((3, 3)), 127, root(), Call::Logger(logger::Call::log(42, 1000)) + ); run_to_block(3); assert!(logger::log().is_empty()); run_to_block(4); - assert_eq!(logger::log(), vec![42u32]); + assert_eq!(logger::log(), vec![(root(), 42u32)]); run_to_block(6); - assert_eq!(logger::log(), vec![42u32]); + assert_eq!(logger::log(), vec![(root(), 42u32)]); run_to_block(7); - assert_eq!(logger::log(), vec![42u32, 42u32]); + assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32)]); run_to_block(9); - assert_eq!(logger::log(), vec![42u32, 42u32]); + assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32)]); run_to_block(10); - assert_eq!(logger::log(), vec![42u32, 42u32, 42u32]); + assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32), (root(), 42u32)]); run_to_block(100); - assert_eq!(logger::log(), vec![42u32, 42u32, 42u32]); + assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32), (root(), 42u32)]); }); } @@ -426,12 +754,16 @@ mod tests { fn cancel_named_scheduling_works_with_normal_cancel() { new_test_ext().execute_with(|| { // at #4. - Scheduler::schedule_named(1u32, 4, None, 127, Call::Logger(logger::Call::log(69, 1000))).unwrap(); - let i = Scheduler::schedule(4, None, 127, Call::Logger(logger::Call::log(42, 1000))); + Scheduler::do_schedule_named( + 1u32.encode(), 4, None, 127, root(), Call::Logger(logger::Call::log(69, 1000)) + ).unwrap(); + let i = Scheduler::do_schedule( + 4, None, 127, root(), Call::Logger(logger::Call::log(42, 1000)) + ).unwrap(); run_to_block(3); assert!(logger::log().is_empty()); - assert_ok!(Scheduler::cancel_named(1u32)); - assert_ok!(Scheduler::cancel(i)); + assert_ok!(Scheduler::do_cancel_named(None, 1u32.encode())); + assert_ok!(Scheduler::do_cancel(None, i)); run_to_block(100); assert!(logger::log().is_empty()); }); @@ -441,82 +773,357 @@ mod tests { fn cancel_named_periodic_scheduling_works() { new_test_ext().execute_with(|| { // at #4, every 3 blocks, 3 times. - Scheduler::schedule_named(1u32, 4, Some((3, 3)), 127, Call::Logger(logger::Call::log(42, 1000))).unwrap(); + Scheduler::do_schedule_named( + 1u32.encode(), 4, Some((3, 3)), 127, root(), Call::Logger(logger::Call::log(42, 1000)) + ).unwrap(); // same id results in error. - assert!(Scheduler::schedule_named(1u32, 4, None, 127, Call::Logger(logger::Call::log(69, 1000))).is_err()); + assert!(Scheduler::do_schedule_named( + 1u32.encode(), 4, None, 127, root(), Call::Logger(logger::Call::log(69, 1000)) + ).is_err()); // different id is ok. - Scheduler::schedule_named(2u32, 8, None, 127, Call::Logger(logger::Call::log(69, 1000))).unwrap(); + Scheduler::do_schedule_named( + 2u32.encode(), 8, None, 127, root(), Call::Logger(logger::Call::log(69, 1000)) + ).unwrap(); run_to_block(3); assert!(logger::log().is_empty()); run_to_block(4); - assert_eq!(logger::log(), vec![42u32]); + assert_eq!(logger::log(), vec![(root(), 42u32)]); run_to_block(6); - assert_ok!(Scheduler::cancel_named(1u32)); + assert_ok!(Scheduler::do_cancel_named(None, 1u32.encode())); run_to_block(100); - assert_eq!(logger::log(), vec![42u32, 69u32]); + assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 69u32)]); }); } #[test] fn scheduler_respects_weight_limits() { new_test_ext().execute_with(|| { - Scheduler::schedule(4, None, 127, Call::Logger(logger::Call::log(42, 6000))); - Scheduler::schedule(4, None, 127, Call::Logger(logger::Call::log(69, 6000))); + let _ = Scheduler::do_schedule( + 4, None, 127, root(), Call::Logger(logger::Call::log(42, MaximumSchedulerWeight::get() / 2)) + ); + let _ = Scheduler::do_schedule( + 4, None, 127, root(), Call::Logger(logger::Call::log(69, MaximumSchedulerWeight::get() / 2)) + ); + // 69 and 42 do not fit together run_to_block(4); - assert_eq!(logger::log(), vec![42u32]); + assert_eq!(logger::log(), vec![(root(), 42u32)]); run_to_block(5); - assert_eq!(logger::log(), vec![42u32, 69u32]); + assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 69u32)]); }); } #[test] fn scheduler_respects_hard_deadlines_more() { new_test_ext().execute_with(|| { - Scheduler::schedule(4, None, 0, Call::Logger(logger::Call::log(42, 6000))); - Scheduler::schedule(4, None, 0, Call::Logger(logger::Call::log(69, 6000))); + let _ = Scheduler::do_schedule( + 4, None, 0, root(), Call::Logger(logger::Call::log(42, MaximumSchedulerWeight::get() / 2)) + ); + let _ = Scheduler::do_schedule( + 4, None, 0, root(), Call::Logger(logger::Call::log(69, MaximumSchedulerWeight::get() / 2)) + ); + // With base weights, 69 and 42 should not fit together, but do because of hard deadlines run_to_block(4); - assert_eq!(logger::log(), vec![42u32, 69u32]); + assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 69u32)]); }); } #[test] fn scheduler_respects_priority_ordering() { new_test_ext().execute_with(|| { - Scheduler::schedule(4, None, 1, Call::Logger(logger::Call::log(42, 6000))); - Scheduler::schedule(4, None, 0, Call::Logger(logger::Call::log(69, 6000))); + let _ = Scheduler::do_schedule( + 4, None, 1, root(), Call::Logger(logger::Call::log(42, MaximumSchedulerWeight::get() / 2)) + ); + let _ = Scheduler::do_schedule( + 4, None, 0, root(), Call::Logger(logger::Call::log(69, MaximumSchedulerWeight::get() / 2)) + ); run_to_block(4); - assert_eq!(logger::log(), vec![69u32, 42u32]); + assert_eq!(logger::log(), vec![(root(), 69u32), (root(), 42u32)]); }); } #[test] fn scheduler_respects_priority_ordering_with_soft_deadlines() { new_test_ext().execute_with(|| { - Scheduler::schedule(4, None, 255, Call::Logger(logger::Call::log(42, 5000))); - Scheduler::schedule(4, None, 127, Call::Logger(logger::Call::log(69, 5000))); - Scheduler::schedule(4, None, 126, Call::Logger(logger::Call::log(2600, 6000))); + let _ = Scheduler::do_schedule( + 4, None, 255, root(), Call::Logger(logger::Call::log(42, MaximumSchedulerWeight::get() / 3)) + ); + let _ = Scheduler::do_schedule( + 4, None, 127, root(), Call::Logger(logger::Call::log(69, MaximumSchedulerWeight::get() / 2)) + ); + let _ = Scheduler::do_schedule( + 4, None, 126, root(), Call::Logger(logger::Call::log(2600, MaximumSchedulerWeight::get() / 2)) + ); + + // 2600 does not fit with 69 or 42, but has higher priority, so will go through run_to_block(4); - assert_eq!(logger::log(), vec![2600u32]); + assert_eq!(logger::log(), vec![(root(), 2600u32)]); + // 69 and 42 fit together run_to_block(5); - assert_eq!(logger::log(), vec![2600u32, 69u32, 42u32]); + assert_eq!(logger::log(), vec![(root(), 2600u32), (root(), 69u32), (root(), 42u32)]); }); } #[test] - fn initialize_weight_is_correct() { + fn on_initialize_weight_is_correct() { new_test_ext().execute_with(|| { - Scheduler::schedule(1, None, 255, Call::Logger(logger::Call::log(3, 1000))); - Scheduler::schedule(1, None, 128, Call::Logger(logger::Call::log(42, 5000))); - Scheduler::schedule(1, None, 127, Call::Logger(logger::Call::log(69, 5000))); - Scheduler::schedule(1, None, 126, Call::Logger(logger::Call::log(2600, 6000))); - let weight = Scheduler::on_initialize(1); - assert_eq!(weight, 6000); - let weight = Scheduler::on_initialize(2); - assert_eq!(weight, 10000); - let weight = Scheduler::on_initialize(3); - assert_eq!(weight, 1000); - let weight = Scheduler::on_initialize(4); - assert_eq!(weight, 0); + let base_weight: Weight = ::DbWeight::get().reads_writes(1, 2) + 10_000_000; + let base_multiplier = 25_000_000; + let named_multiplier = ::DbWeight::get().writes(1); + let periodic_multiplier = ::DbWeight::get().reads_writes(1, 1); + + // Named + assert_ok!( + Scheduler::do_schedule_named( + 1u32.encode(), 1, None, 255, root(), + Call::Logger(logger::Call::log(3, MaximumSchedulerWeight::get() / 3)) + ) + ); + // Anon Periodic + let _ = Scheduler::do_schedule( + 1, Some((1000, 3)), 128, root(), Call::Logger(logger::Call::log(42, MaximumSchedulerWeight::get() / 3)) + ); + // Anon + let _ = Scheduler::do_schedule( + 1, None, 127, root(), Call::Logger(logger::Call::log(69, MaximumSchedulerWeight::get() / 2)) + ); + // Named Periodic + assert_ok!(Scheduler::do_schedule_named( + 2u32.encode(), 1, Some((1000, 3)), 126, root(), + Call::Logger(logger::Call::log(2600, MaximumSchedulerWeight::get() / 2))) + ); + + // Will include the named periodic only + let actual_weight = Scheduler::on_initialize(1); + let call_weight = MaximumSchedulerWeight::get() / 2; + assert_eq!( + actual_weight, call_weight + base_weight + base_multiplier + named_multiplier + periodic_multiplier + ); + assert_eq!(logger::log(), vec![(root(), 2600u32)]); + + // Will include anon and anon periodic + let actual_weight = Scheduler::on_initialize(2); + let call_weight = MaximumSchedulerWeight::get() / 2 + MaximumSchedulerWeight::get() / 3; + assert_eq!(actual_weight, call_weight + base_weight + base_multiplier * 2 + periodic_multiplier); + assert_eq!(logger::log(), vec![(root(), 2600u32), (root(), 69u32), (root(), 42u32)]); + + // Will include named only + let actual_weight = Scheduler::on_initialize(3); + let call_weight = MaximumSchedulerWeight::get() / 3; + assert_eq!(actual_weight, call_weight + base_weight + base_multiplier + named_multiplier); + assert_eq!(logger::log(), vec![(root(), 2600u32), (root(), 69u32), (root(), 42u32), (root(), 3u32)]); + + // Will contain none + let actual_weight = Scheduler::on_initialize(4); + assert_eq!(actual_weight, 0); + }); + } + + #[test] + fn root_calls_works() { + new_test_ext().execute_with(|| { + let call = Box::new(Call::Logger(logger::Call::log(69, 1000))); + let call2 = Box::new(Call::Logger(logger::Call::log(42, 1000))); + assert_ok!(Scheduler::schedule_named(Origin::root(), 1u32.encode(), 4, None, 127, call)); + assert_ok!(Scheduler::schedule(Origin::root(), 4, None, 127, call2)); + run_to_block(3); + // Scheduled calls are in the agenda. + assert_eq!(Agenda::::get(4).len(), 2); + assert!(logger::log().is_empty()); + assert_ok!(Scheduler::cancel_named(Origin::root(), 1u32.encode())); + assert_ok!(Scheduler::cancel(Origin::root(), 4, 1)); + // Scheduled calls are made NONE, so should not effect state + run_to_block(100); + assert!(logger::log().is_empty()); + }); + } + + #[test] + fn fails_to_schedule_task_in_the_past() { + new_test_ext().execute_with(|| { + run_to_block(3); + + let call = Box::new(Call::Logger(logger::Call::log(69, 1000))); + let call2 = Box::new(Call::Logger(logger::Call::log(42, 1000))); + + assert_err!( + Scheduler::schedule_named(Origin::root(), 1u32.encode(), 2, None, 127, call), + Error::::TargetBlockNumberInPast, + ); + + assert_err!( + Scheduler::schedule(Origin::root(), 2, None, 127, call2.clone()), + Error::::TargetBlockNumberInPast, + ); + + assert_err!( + Scheduler::schedule(Origin::root(), 3, None, 127, call2), + Error::::TargetBlockNumberInPast, + ); + }); + } + + #[test] + fn should_use_orign() { + new_test_ext().execute_with(|| { + let call = Box::new(Call::Logger(logger::Call::log(69, 1000))); + let call2 = Box::new(Call::Logger(logger::Call::log(42, 1000))); + assert_ok!( + Scheduler::schedule_named(system::RawOrigin::Signed(1).into(), 1u32.encode(), 4, None, 127, call) + ); + assert_ok!(Scheduler::schedule(system::RawOrigin::Signed(1).into(), 4, None, 127, call2)); + run_to_block(3); + // Scheduled calls are in the agenda. + assert_eq!(Agenda::::get(4).len(), 2); + assert!(logger::log().is_empty()); + assert_ok!(Scheduler::cancel_named(system::RawOrigin::Signed(1).into(), 1u32.encode())); + assert_ok!(Scheduler::cancel(system::RawOrigin::Signed(1).into(), 4, 1)); + // Scheduled calls are made NONE, so should not effect state + run_to_block(100); + assert!(logger::log().is_empty()); + }); + } + + #[test] + fn should_check_orign() { + new_test_ext().execute_with(|| { + let call = Box::new(Call::Logger(logger::Call::log(69, 1000))); + let call2 = Box::new(Call::Logger(logger::Call::log(42, 1000))); + assert_noop!( + Scheduler::schedule_named(system::RawOrigin::Signed(2).into(), 1u32.encode(), 4, None, 127, call), + BadOrigin + ); + assert_noop!(Scheduler::schedule(system::RawOrigin::Signed(2).into(), 4, None, 127, call2), BadOrigin); + }); + } + + #[test] + fn should_check_orign_for_cancel() { + new_test_ext().execute_with(|| { + let call = Box::new(Call::Logger(logger::Call::log_without_filter(69, 1000))); + let call2 = Box::new(Call::Logger(logger::Call::log_without_filter(42, 1000))); + assert_ok!( + Scheduler::schedule_named(system::RawOrigin::Signed(1).into(), 1u32.encode(), 4, None, 127, call) + ); + assert_ok!(Scheduler::schedule(system::RawOrigin::Signed(1).into(), 4, None, 127, call2)); + run_to_block(3); + // Scheduled calls are in the agenda. + assert_eq!(Agenda::::get(4).len(), 2); + assert!(logger::log().is_empty()); + assert_noop!(Scheduler::cancel_named(system::RawOrigin::Signed(2).into(), 1u32.encode()), BadOrigin); + assert_noop!(Scheduler::cancel(system::RawOrigin::Signed(2).into(), 4, 1), BadOrigin); + assert_noop!(Scheduler::cancel_named(system::RawOrigin::Root.into(), 1u32.encode()), BadOrigin); + assert_noop!(Scheduler::cancel(system::RawOrigin::Root.into(), 4, 1), BadOrigin); + run_to_block(5); + assert_eq!( + logger::log(), + vec![(system::RawOrigin::Signed(1).into(), 69u32), (system::RawOrigin::Signed(1).into(), 42u32)] + ); + }); + } + + #[test] + fn migration_to_v2_works() { + use substrate_test_utils::assert_eq_uvec; + + new_test_ext().execute_with(|| { + for i in 0..3u64 { + let k = i.twox_64_concat(); + let old = vec![ + Some(ScheduledV1 { + maybe_id: None, + priority: i as u8 + 10, + call: Call::Logger(logger::Call::log(96, 100)), + maybe_periodic: None, + }), + None, + Some(ScheduledV1 { + maybe_id: Some(b"test".to_vec()), + priority: 123, + call: Call::Logger(logger::Call::log(69, 1000)), + maybe_periodic: Some((456u64, 10)), + }), + ]; + frame_support::migration::put_storage_value( + b"Scheduler", + b"Agenda", + &k, + old, + ); + } + + assert_eq!(StorageVersion::get(), Releases::V1); + + assert!(Scheduler::migrate_v1_to_t2()); + + assert_eq_uvec!(Agenda::::iter().collect::>(), vec![ + ( + 0, + vec![ + Some(ScheduledV2 { + maybe_id: None, + priority: 10, + call: Call::Logger(logger::Call::log(96, 100)), + maybe_periodic: None, + origin: root(), + _phantom: PhantomData::::default(), + }), + None, + Some(ScheduledV2 { + maybe_id: Some(b"test".to_vec()), + priority: 123, + call: Call::Logger(logger::Call::log(69, 1000)), + maybe_periodic: Some((456u64, 10)), + origin: root(), + _phantom: PhantomData::::default(), + }), + ]), + ( + 1, + vec![ + Some(ScheduledV2 { + maybe_id: None, + priority: 11, + call: Call::Logger(logger::Call::log(96, 100)), + maybe_periodic: None, + origin: root(), + _phantom: PhantomData::::default(), + }), + None, + Some(ScheduledV2 { + maybe_id: Some(b"test".to_vec()), + priority: 123, + call: Call::Logger(logger::Call::log(69, 1000)), + maybe_periodic: Some((456u64, 10)), + origin: root(), + _phantom: PhantomData::::default(), + }), + ] + ), + ( + 2, + vec![ + Some(ScheduledV2 { + maybe_id: None, + priority: 12, + call: Call::Logger(logger::Call::log(96, 100)), + maybe_periodic: None, + origin: root(), + _phantom: PhantomData::::default(), + }), + None, + Some(ScheduledV2 { + maybe_id: Some(b"test".to_vec()), + priority: 123, + call: Call::Logger(logger::Call::log(69, 1000)), + maybe_periodic: Some((456u64, 10)), + origin: root(), + _phantom: PhantomData::::default(), + }), + ] + ) + ]); + + assert_eq!(StorageVersion::get(), Releases::V2); }); } } diff --git a/frame/scored-pool/Cargo.toml b/frame/scored-pool/Cargo.toml index b878c5bb47559d3d8eab8cb842d8eb00182abed7..05fc56fc65a28d7030277c339567336d6c9ae25b 100644 --- a/frame/scored-pool/Cargo.toml +++ b/frame/scored-pool/Cargo.toml @@ -1,25 +1,28 @@ [package] name = "pallet-scored-pool" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for scored pools" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } serde = { version = "1.0.101", optional = true } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } [dev-dependencies] -pallet-balances = { version = "2.0.0-alpha.5", path = "../balances" } -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0-rc4", path = "../balances" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } [features] default = ["std"] @@ -32,6 +35,3 @@ std = [ "frame-support/std", "frame-system/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/scored-pool/src/lib.rs b/frame/scored-pool/src/lib.rs index d162f42c3f745bff162fe00eead33a6026fe227e..35c36b03195e859b6e467f5db957b180ec5f7a98 100644 --- a/frame/scored-pool/src/lib.rs +++ b/frame/scored-pool/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Scored Pool Module //! @@ -54,14 +55,14 @@ //! //! ``` //! use frame_support::{decl_module, dispatch}; -//! use frame_system::{self as system, ensure_signed}; +//! use frame_system::ensure_signed; //! use pallet_scored_pool::{self as scored_pool}; //! //! pub trait Trait: scored_pool::Trait {} //! //! decl_module! { //! pub struct Module for enum Call where origin: T::Origin { -//! #[weight = frame_support::weights::SimpleDispatchInfo::default()] +//! #[weight = 0] //! pub fn candidate(origin) -> dispatch::DispatchResult { //! let who = ensure_signed(origin)?; //! @@ -97,12 +98,10 @@ use sp_std::{ use frame_support::{ decl_module, decl_storage, decl_event, ensure, decl_error, traits::{EnsureOrigin, ChangeMembers, InitializeMembers, Currency, Get, ReservableCurrency}, - weights::{Weight, SimpleDispatchInfo, WeighData}, -}; -use frame_system::{self as system, ensure_root, ensure_signed}; -use sp_runtime::{ - traits::{AtLeast32Bit, MaybeSerializeDeserialize, Zero, StaticLookup}, + weights::Weight, }; +use frame_system::{ensure_root, ensure_signed}; +use sp_runtime::traits::{AtLeast32Bit, MaybeSerializeDeserialize, Zero, StaticLookup}; type BalanceOf = <>::Currency as Currency<::AccountId>>::Balance; type PoolT = Vec<(::AccountId, Option<>::Score>)>; @@ -191,8 +190,8 @@ decl_storage! { >::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. + // 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()) ); @@ -252,7 +251,7 @@ decl_module! { let pool = >::get(); >::refresh_members(pool, ChangeReceiver::MembershipChanged); } - SimpleDispatchInfo::default().weigh_data(()) + 0 } /// Add `origin` to the pool of candidates. @@ -266,7 +265,7 @@ decl_module! { /// /// The `index` parameter of this function must be set to /// the index of the transactor in the `Pool`. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] pub fn submit_candidacy(origin) { let who = ensure_signed(origin)?; ensure!(!>::contains_key(&who), Error::::AlreadyInPool); @@ -276,10 +275,7 @@ decl_module! { // 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); - Err(e)? - } + >::append((who.clone(), Option::<>::Score>::None)); >::insert(&who, true); @@ -296,7 +292,7 @@ decl_module! { /// /// The `index` parameter of this function must be set to /// the index of the transactor in the `Pool`. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] pub fn withdraw_candidacy( origin, index: u32 @@ -312,19 +308,17 @@ decl_module! { /// Kick a member `who` from the set. /// - /// May only be called from `KickOrigin` or root. + /// May only be called from `T::KickOrigin`. /// /// The `index` parameter of this function must be set to /// the index of `dest` in the `Pool`. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] pub fn kick( origin, dest: ::Source, index: u32 ) { - T::KickOrigin::try_origin(origin) - .map(|_| ()) - .or_else(ensure_root)?; + T::KickOrigin::ensure_origin(origin)?; let who = T::Lookup::lookup(dest)?; @@ -337,20 +331,18 @@ decl_module! { /// Score a member `who` with `score`. /// - /// May only be called from `ScoreOrigin` or root. + /// May only be called from `T::ScoreOrigin`. /// /// The `index` parameter of this function must be set to /// the index of the `dest` in the `Pool`. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] pub fn score( origin, dest: ::Source, index: u32, score: T::Score ) { - T::ScoreOrigin::try_origin(origin) - .map(|_| ()) - .or_else(ensure_root)?; + T::ScoreOrigin::ensure_origin(origin)?; let who = T::Lookup::lookup(dest)?; @@ -382,7 +374,7 @@ decl_module! { /// (this happens each `Period`). /// /// May only be called from root. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] pub fn change_member_count(origin, count: u32) { ensure_root(origin)?; >::put(&count); diff --git a/frame/scored-pool/src/mock.rs b/frame/scored-pool/src/mock.rs index a28b7891370eafbdc47260ef602ae2a69660c119..552028afc9469ad1dcbda754c8cf653d07a1ccfd 100644 --- a/frame/scored-pool/src/mock.rs +++ b/frame/scored-pool/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utilities @@ -21,8 +22,6 @@ use super::*; use std::cell::RefCell; use frame_support::{impl_outer_origin, parameter_types, weights::Weight, ord_parameter_types}; use sp_core::H256; -// The testing primitives are very useful for avoiding having to work with signatures -// or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. use sp_runtime::{ Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header, }; @@ -32,9 +31,6 @@ impl_outer_origin! { pub enum Origin for Test where system = frame_system {} } -// For testing the pallet, we construct most of a mock runtime. This means -// first constructing a configuration type (`Test`) which `impl`s each of the -// configuration traits of pallets we want to use. #[derive(Clone, Eq, PartialEq)] pub struct Test; parameter_types! { @@ -54,6 +50,7 @@ ord_parameter_types! { } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -66,6 +63,10 @@ impl frame_system::Trait for Test { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -73,6 +74,7 @@ impl frame_system::Trait for Test { type AccountData = pallet_balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } impl pallet_balances::Trait for Test { @@ -81,6 +83,7 @@ impl pallet_balances::Trait for Test { type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; + type WeightInfo = (); } thread_local! { @@ -125,11 +128,8 @@ impl Trait for Test { type System = frame_system::Module; type Balances = pallet_balances::Module; -// This function basically just builds a genesis storage key/value store according to -// our desired mockup. pub fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - // We use default for brevity, but you can configure as desired if needed. pallet_balances::GenesisConfig:: { balances: vec![ (5, 500_000), diff --git a/frame/scored-pool/src/tests.rs b/frame/scored-pool/src/tests.rs index 8d87a20f757b223443b2b134fb1d66f0ab793b53..9c0074ff6e6899f6efe7967c1ddeb28661a3b5fd 100644 --- a/frame/scored-pool/src/tests.rs +++ b/frame/scored-pool/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for the module. diff --git a/frame/session/Cargo.toml b/frame/session/Cargo.toml index f12a8b4a71f2fc8df7f81ac50098c32ffd9cd7aa..c882df7115f3878b848dfdb02818ac7e7dad85c2 100644 --- a/frame/session/Cargo.toml +++ b/frame/session/Cargo.toml @@ -1,29 +1,33 @@ [package] name = "pallet-session" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME sessions pallet" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -sp-staking = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/staking" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } -pallet-timestamp = { version = "2.0.0-alpha.5", default-features = false, path = "../timestamp" } -sp-trie = { optional = true, path = "../../primitives/trie", default-features = false, version = "2.0.0-alpha.5"} -sp-io ={ path = "../../primitives/io", default-features = false , version = "2.0.0-alpha.5"} +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/core" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +sp-session = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/session" } +sp-staking = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/staking" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } +pallet-timestamp = { version = "2.0.0-rc4", default-features = false, path = "../timestamp" } +sp-trie = { version = "2.0.0-rc4", optional = true, default-features = false, path = "../../primitives/trie" } impl-trait-for-tuples = "0.1.3" [dev-dependencies] -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -sp-application-crypto = { version = "2.0.0-alpha.5", path = "../../primitives/application-crypto" } +sp-application-crypto = { version = "2.0.0-rc4", path = "../../primitives/application-crypto" } lazy_static = "1.4.0" [features] @@ -33,13 +37,12 @@ std = [ "serde", "codec/std", "sp-std/std", + "sp-io/std", "frame-support/std", + "sp-core/std", "sp-runtime/std", + "sp-session/std", "sp-staking/std", "pallet-timestamp/std", "sp-trie/std", - "sp-io/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/session/benchmarking/Cargo.toml b/frame/session/benchmarking/Cargo.toml index 181fb37bfdbc10025ba7d9a1baa1840662c3fe79..1c2dbf729109622806bcfcd146a7521422634da1 100644 --- a/frame/session/benchmarking/Cargo.toml +++ b/frame/session/benchmarking/Cargo.toml @@ -1,31 +1,45 @@ [package] name = "pallet-session-benchmarking" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME sessions pallet benchmarking" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/std" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/runtime" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../../system" } -frame-benchmarking = { version = "2.0.0-alpha.5", default-features = false, path = "../../benchmarking" } -pallet-staking = { version = "2.0.0-alpha.5", default-features = false, features = ["runtime-benchmarks"], path = "../../staking" } -pallet-session = { version = "2.0.0-alpha.5", default-features = false, path = "../../session" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/std" } +sp-session = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/session" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/runtime" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../../system" } +frame-benchmarking = { version = "2.0.0-rc4", default-features = false, path = "../../benchmarking" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../../support" } +pallet-staking = { version = "2.0.0-rc4", default-features = false, features = ["runtime-benchmarks"], path = "../../staking" } +pallet-session = { version = "2.0.0-rc4", default-features = false, path = "../../session" } +rand = { version = "0.7.2", default-features = false } + +[dev-dependencies] +serde = { version = "1.0.101" } +codec = { package = "parity-scale-codec", version = "1.3.1", features = ["derive"] } +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } +pallet-staking-reward-curve = { version = "2.0.0-rc4", path = "../../staking/reward-curve" } +sp-io ={ version = "2.0.0-rc4", path = "../../../primitives/io" } +pallet-timestamp = { version = "2.0.0-rc4", path = "../../timestamp" } +pallet-balances = { version = "2.0.0-rc4", path = "../../balances" } [features] default = ["std"] std = [ "sp-std/std", + "sp-session/std", "sp-runtime/std", "frame-system/std", "frame-benchmarking/std", + "frame-support/std", "pallet-staking/std", "pallet-session/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/session/benchmarking/src/lib.rs b/frame/session/benchmarking/src/lib.rs index db925bd72ee45e204eca8faeee4a97d0d4d6a09d..cc471893356d54eee36ec998e0bf8b6c5ff2c57f 100644 --- a/frame/session/benchmarking/src/lib.rs +++ b/frame/session/benchmarking/src/lib.rs @@ -1,57 +1,169 @@ -// Copyright 2020 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. +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Benchmarks for the Session Pallet. // This is separated into its own crate due to cyclic dependency issues. #![cfg_attr(not(feature = "std"), no_std)] +mod mock; + use sp_std::prelude::*; use sp_std::vec; -use frame_system::RawOrigin; use frame_benchmarking::benchmarks; - -use pallet_session::*; -use pallet_session::Module as Session; - +use frame_support::{ + codec::Decode, + storage::StorageValue, + traits::{KeyOwnerProofSystem, OnInitialize}, +}; +use frame_system::RawOrigin; +use pallet_session::{historical::Module as Historical, Module as Session, *}; use pallet_staking::{ + benchmarking::create_validator_with_nominators, testing_utils::create_validators, MAX_NOMINATIONS, - benchmarking::create_validator_with_nominators, }; +use sp_runtime::traits::{One, StaticLookup}; + +const MAX_VALIDATORS: u32 = 1000; pub struct Module(pallet_session::Module); +pub trait Trait: pallet_session::Trait + pallet_session::historical::Trait + pallet_staking::Trait {} -pub trait Trait: pallet_session::Trait + pallet_staking::Trait {} +impl OnInitialize for Module { + fn on_initialize(n: T::BlockNumber) -> frame_support::weights::Weight { + pallet_session::Module::::on_initialize(n) + } +} benchmarks! { _ { } set_keys { let n in 1 .. MAX_NOMINATIONS as u32; - let validator = create_validator_with_nominators::(n, MAX_NOMINATIONS as u32)?; + let v_stash = create_validator_with_nominators::(n, MAX_NOMINATIONS as u32, false)?; + let v_controller = pallet_staking::Module::::bonded(&v_stash).ok_or("not stash")?; let keys = T::Keys::default(); let proof: Vec = vec![0,1,2,3]; - }: _(RawOrigin::Signed(validator), keys, proof) + }: _(RawOrigin::Signed(v_controller), keys, proof) purge_keys { let n in 1 .. MAX_NOMINATIONS as u32; - let validator = create_validator_with_nominators::(n, MAX_NOMINATIONS as u32)?; + let v_stash = create_validator_with_nominators::(n, MAX_NOMINATIONS as u32, false)?; + let v_controller = pallet_staking::Module::::bonded(&v_stash).ok_or("not stash")?; let keys = T::Keys::default(); let proof: Vec = vec![0,1,2,3]; - Session::::set_keys(RawOrigin::Signed(validator.clone()).into(), keys, proof)?; - }: _(RawOrigin::Signed(validator)) + Session::::set_keys(RawOrigin::Signed(v_controller.clone()).into(), keys, proof)?; + }: _(RawOrigin::Signed(v_controller)) + + check_membership_proof_current_session { + let n in 2 .. MAX_VALIDATORS as u32; + + let (key, key_owner_proof1) = check_membership_proof_setup::(n); + let key_owner_proof2 = key_owner_proof1.clone(); + }: { + Historical::::check_proof(key, key_owner_proof1); + } + verify { + assert!(Historical::::check_proof(key, key_owner_proof2).is_some()); + } + + check_membership_proof_historical_session { + let n in 2 .. MAX_VALIDATORS as u32; + + let (key, key_owner_proof1) = check_membership_proof_setup::(n); + + // skip to the next session so that the session is historical + // and the membership merkle proof must be checked. + Session::::rotate_session(); + + let key_owner_proof2 = key_owner_proof1.clone(); + }: { + Historical::::check_proof(key, key_owner_proof1); + } + verify { + assert!(Historical::::check_proof(key, key_owner_proof2).is_some()); + } +} + +/// Sets up the benchmark for checking a membership proof. It creates the given +/// number of validators, sets random session keys and then creates a membership +/// proof for the first authority and returns its key and the proof. +fn check_membership_proof_setup( + n: u32, +) -> ( + (sp_runtime::KeyTypeId, &'static [u8; 32]), + sp_session::MembershipProof, +) { + pallet_staking::ValidatorCount::put(n); + + // create validators and set random session keys + for (n, who) in create_validators::(n, 1000) + .unwrap() + .into_iter() + .enumerate() + { + use rand::RngCore; + use rand::SeedableRng; + + let validator = T::Lookup::lookup(who).unwrap(); + let controller = pallet_staking::Module::::bonded(validator).unwrap(); + + let keys = { + let mut keys = [0u8; 128]; + + // we keep the keys for the first validator as 0x00000... + if n > 0 { + let mut rng = rand::rngs::StdRng::seed_from_u64(n as u64); + rng.fill_bytes(&mut keys); + } + + keys + }; + + let keys: T::Keys = Decode::decode(&mut &keys[..]).unwrap(); + let proof: Vec = vec![]; + + Session::::set_keys(RawOrigin::Signed(controller).into(), keys, proof).unwrap(); + } + + Module::::on_initialize(T::BlockNumber::one()); + + // skip sessions until the new validator set is enacted + while Session::::validators().len() < n as usize { + Session::::rotate_session(); + } + + let key = (sp_runtime::KeyTypeId(*b"babe"), &[0u8; 32]); + + (key, Historical::::prove(key).unwrap()) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::{new_test_ext, Test}; + use frame_support::assert_ok; + + #[test] + fn test_benchmarks() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_set_keys::()); + assert_ok!(test_benchmark_purge_keys::()); + }); + } } diff --git a/frame/session/benchmarking/src/mock.rs b/frame/session/benchmarking/src/mock.rs new file mode 100644 index 0000000000000000000000000000000000000000..ee99d72187cb857c67ca51d790956658a4f892f0 --- /dev/null +++ b/frame/session/benchmarking/src/mock.rs @@ -0,0 +1,200 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Mock file for session benchmarking. + +#![cfg(test)] + +use sp_runtime::traits::{Convert, SaturatedConversion, IdentityLookup}; +use frame_support::{impl_outer_origin, impl_outer_dispatch, parameter_types}; + +type AccountId = u64; +type AccountIndex = u32; +type BlockNumber = u64; +type Balance = u64; + +type System = frame_system::Module; +type Balances = pallet_balances::Module; +type Staking = pallet_staking::Module; +type Session = pallet_session::Module; + +impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} +} + +impl_outer_dispatch! { + pub enum Call for Test where origin: Origin { + pallet_staking::Staking, + } +} + +pub struct CurrencyToVoteHandler; +impl Convert for CurrencyToVoteHandler { + fn convert(x: u64) -> u64 { + x + } +} +impl Convert for CurrencyToVoteHandler { + fn convert(x: u128) -> u64 { + x.saturated_into() + } +} + +#[derive(Clone, Eq, PartialEq, Debug)] +pub struct Test; + +impl frame_system::Trait for Test { + type BaseCallFilter = (); + type Origin = Origin; + type Index = AccountIndex; + type BlockNumber = BlockNumber; + type Call = Call; + type Hash = sp_core::H256; + type Hashing = ::sp_runtime::traits::BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = sp_runtime::testing::Header; + type Event = (); + type BlockHashCount = (); + type MaximumBlockWeight = (); + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = (); + type AvailableBlockRatio = (); + type MaximumBlockLength = (); + type Version = (); + type ModuleToIndex = (); + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = Balances; + type SystemWeightInfo = (); +} +parameter_types! { + pub const ExistentialDeposit: Balance = 10; +} +impl pallet_balances::Trait for Test { + type Balance = Balance; + type Event = (); + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); +} + +parameter_types! { + pub const MinimumPeriod: u64 = 5; +} +impl pallet_timestamp::Trait for Test { + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); +} +impl pallet_session::historical::Trait for Test { + type FullIdentification = pallet_staking::Exposure; + type FullIdentificationOf = pallet_staking::ExposureOf; +} + +sp_runtime::impl_opaque_keys! { + pub struct SessionKeys { + pub foo: sp_runtime::testing::UintAuthorityId, + } +} + +pub struct TestSessionHandler; +impl pallet_session::SessionHandler for TestSessionHandler { + const KEY_TYPE_IDS: &'static [sp_runtime::KeyTypeId] = &[]; + + fn on_genesis_session(_validators: &[(AccountId, Ks)]) {} + + fn on_new_session( + _: bool, + _: &[(AccountId, Ks)], + _: &[(AccountId, Ks)], + ) {} + + fn on_disabled(_: usize) {} +} + +impl pallet_session::Trait for Test { + type SessionManager = pallet_session::historical::NoteHistoricalRoot; + type Keys = SessionKeys; + type ShouldEndSession = pallet_session::PeriodicSessions<(), ()>; + type NextSessionRotation = pallet_session::PeriodicSessions<(), ()>; + type SessionHandler = TestSessionHandler; + type Event = (); + type ValidatorId = AccountId; + type ValidatorIdOf = pallet_staking::StashOf; + type DisabledValidatorsThreshold = (); + type WeightInfo = (); +} +pallet_staking_reward_curve::build! { + const I_NPOS: sp_runtime::curve::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 RewardCurve: &'static sp_runtime::curve::PiecewiseLinear<'static> = &I_NPOS; + pub const MaxNominatorRewardedPerValidator: u32 = 64; + pub const UnsignedPriority: u64 = 1 << 20; +} + +pub type Extrinsic = sp_runtime::testing::TestXt; + +impl frame_system::offchain::SendTransactionTypes for Test where + Call: From, +{ + type OverarchingCall = Call; + type Extrinsic = Extrinsic; +} + +impl pallet_staking::Trait for Test { + type Currency = Balances; + type UnixTime = pallet_timestamp::Module; + type CurrencyToVote = CurrencyToVoteHandler; + type RewardRemainder = (); + type Event = (); + type Slash = (); + type Reward = (); + type SessionsPerEra = (); + type SlashDeferDuration = (); + type SlashCancelOrigin = frame_system::EnsureRoot; + type BondingDuration = (); + type SessionInterface = Self; + type RewardCurve = RewardCurve; + type NextNewSession = Session; + type ElectionLookahead = (); + type Call = Call; + type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; + type UnsignedPriority = UnsignedPriority; + type MaxIterations = (); + type MinSolutionScoreBump = (); + type WeightInfo = (); +} + +impl crate::Trait for Test {} + +pub fn new_test_ext() -> sp_io::TestExternalities { + let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + sp_io::TestExternalities::new(t) +} diff --git a/frame/session/src/historical.rs b/frame/session/src/historical/mod.rs similarity index 85% rename from frame/session/src/historical.rs rename to frame/session/src/historical/mod.rs index f9990dd1e8a7a716f4a557467fe5364602c45fe3..20c3d57464c89c9a3f6b4877e64210e489a79513 100644 --- a/frame/session/src/historical.rs +++ b/frame/session/src/historical/mod.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! An opt-in utility for tracking historical sessions in FRAME-session. //! @@ -27,15 +28,18 @@ use sp_std::prelude::*; use codec::{Encode, Decode}; -use sp_runtime::{KeyTypeId, RuntimeDebug}; +use sp_runtime::KeyTypeId; use sp_runtime::traits::{Convert, OpaqueKeys}; +use sp_session::{MembershipProof, ValidatorCount}; use frame_support::{decl_module, decl_storage}; use frame_support::{Parameter, print}; use sp_trie::{MemoryDB, Trie, TrieMut, Recorder, EMPTY_PREFIX}; use sp_trie::trie_types::{TrieDBMut, TrieDB}; use super::{SessionIndex, Module as SessionModule}; -type ValidatorCount = u32; +mod shared; +pub mod offchain; +pub mod onchain; /// Trait necessary for the historical module. pub trait Trait: super::Trait { @@ -116,6 +120,7 @@ impl crate::SessionManager for NoteHistoricalRoot { fn new_session(new_index: SessionIndex) -> Option> { + StoredRange::mutate(|range| { range.get_or_insert_with(|| (new_index, new_index)).1 = new_index + 1; }); @@ -126,7 +131,7 @@ impl crate::SessionManager for NoteHistoricalRoot::generate_for(new_validators) { Ok(trie) => >::insert(new_index, &(trie.root, count)), Err(reason) => { @@ -143,10 +148,13 @@ impl crate::SessionManager for NoteHistoricalRoot>::start_session(start_index) } + fn end_session(end_index: SessionIndex) { + onchain::store_session_validator_set_to_offchain::(end_index); >::end_session(end_index) } } @@ -154,7 +162,7 @@ impl crate::SessionManager for NoteHistoricalRoot = (::ValidatorId, ::FullIdentification); -/// a trie instance for checking and generating proofs. +/// A trie instance for checking and generating proofs. pub struct ProvingTrie { db: MemoryDB, root: T::Hash, @@ -250,66 +258,69 @@ impl ProvingTrie { .ok()? .and_then(|raw| >::decode(&mut &*raw).ok()) } - -} - -/// Proof of ownership of a specific key. -#[derive(Encode, Decode, Clone, Eq, PartialEq, RuntimeDebug)] -pub struct Proof { - session: SessionIndex, - trie_nodes: Vec>, -} - -impl Proof { - /// Returns a session this proof was generated for. - pub fn session(&self) -> SessionIndex { - self.session - } } impl> frame_support::traits::KeyOwnerProofSystem<(KeyTypeId, D)> for Module { - type Proof = Proof; + type Proof = MembershipProof; type IdentificationTuple = IdentificationTuple; fn prove(key: (KeyTypeId, D)) -> Option { let session = >::current_index(); - let validators = >::validators().into_iter() + let validators = >::validators() + .into_iter() .filter_map(|validator| { T::FullIdentificationOf::convert(validator.clone()) .map(|full_id| (validator, full_id)) - }); + }) + .collect::>(); + + let count = validators.len() as ValidatorCount; + let trie = ProvingTrie::::generate_for(validators).ok()?; let (id, data) = key; - - trie.prove(id, data.as_ref()).map(|trie_nodes| Proof { - session, - trie_nodes, - }) + trie.prove(id, data.as_ref()) + .map(|trie_nodes| MembershipProof { + session, + trie_nodes, + validator_count: count, + }) } - fn check_proof(key: (KeyTypeId, D), proof: Proof) -> Option> { + fn check_proof(key: (KeyTypeId, D), proof: Self::Proof) -> Option> { let (id, data) = key; if proof.session == >::current_index() { - >::key_owner(id, data.as_ref()).and_then(|owner| - T::FullIdentificationOf::convert(owner.clone()).map(move |id| (owner, id)) - ) + >::key_owner(id, data.as_ref()).and_then(|owner| { + T::FullIdentificationOf::convert(owner.clone()).and_then(move |id| { + let count = >::validators().len() as ValidatorCount; + + if count != proof.validator_count { + return None; + } + + Some((owner, id)) + }) + }) } else { - let (root, _) = >::get(&proof.session)?; - let trie = ProvingTrie::::from_nodes(root, &proof.trie_nodes); + let (root, count) = >::get(&proof.session)?; + if count != proof.validator_count { + return None; + } + + let trie = ProvingTrie::::from_nodes(root, &proof.trie_nodes); trie.query(id, data.as_ref()) } } } #[cfg(test)] -mod tests { +pub(crate) mod tests { use super::*; - use sp_core::crypto::key_types::DUMMY; + use sp_runtime::key_types::DUMMY; use sp_runtime::testing::UintAuthorityId; use crate::mock::{ NEXT_VALIDATORS, force_new_session, @@ -319,7 +330,7 @@ mod tests { type Historical = Module; - fn new_test_ext() -> sp_io::TestExternalities { + pub(crate) fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); crate::GenesisConfig:: { keys: NEXT_VALIDATORS.with(|l| diff --git a/frame/session/src/historical/offchain.rs b/frame/session/src/historical/offchain.rs new file mode 100644 index 0000000000000000000000000000000000000000..97655d1a18b3280b85e7d2074e8071152611dfea --- /dev/null +++ b/frame/session/src/historical/offchain.rs @@ -0,0 +1,263 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Off-chain logic for creating a proof based data provided by on-chain logic. +//! +//! Validator-set extracting an iterator from an off-chain worker stored list containing +//! historical validator-sets. +//! Based on the logic of historical slashing, but the validation is done off-chain. +//! Use [`fn store_current_session_validator_set_to_offchain()`](super::onchain) to store the +//! required data to the offchain validator set. +//! This is used in conjunction with [`ProvingTrie`](super::ProvingTrie) and +//! the off-chain indexing API. + +use sp_runtime::{offchain::storage::StorageValueRef, KeyTypeId}; +use sp_session::MembershipProof; + +use super::super::{Module as SessionModule, SessionIndex}; +use super::{IdentificationTuple, ProvingTrie, Trait}; + +use super::shared; +use sp_std::prelude::*; + + +/// A set of validators, which was used for a fixed session index. +struct ValidatorSet { + validator_set: Vec>, +} + +impl ValidatorSet { + /// Load the set of validators for a particular session index from the off-chain storage. + /// + /// If none is found or decodable given `prefix` and `session`, it will return `None`. + /// Empty validator sets should only ever exist for genesis blocks. + pub fn load_from_offchain_db(session_index: SessionIndex) -> Option { + let derived_key = shared::derive_key(shared::PREFIX, session_index); + StorageValueRef::persistent(derived_key.as_ref()) + .get::>() + .flatten() + .map(|validator_set| Self { validator_set }) + } + + #[inline] + fn len(&self) -> usize { + self.validator_set.len() + } +} + +/// Implement conversion into iterator for usage +/// with [ProvingTrie](super::ProvingTrie::generate_for). +impl sp_std::iter::IntoIterator for ValidatorSet { + type Item = (T::ValidatorId, T::FullIdentification); + type IntoIter = sp_std::vec::IntoIter; + fn into_iter(self) -> Self::IntoIter { + self.validator_set.into_iter() + } +} + +/// Create a proof based on the data available in the off-chain database. +/// +/// Based on the yielded `MembershipProof` the implementer may decide what +/// to do, i.e. in case of a failed proof, enqueue a transaction back on +/// chain reflecting that, with all its consequences such as i.e. slashing. +pub fn prove_session_membership>( + session_index: SessionIndex, + session_key: (KeyTypeId, D), +) -> Option { + let validators = ValidatorSet::::load_from_offchain_db(session_index)?; + let count = validators.len() as u32; + let trie = ProvingTrie::::generate_for(validators.into_iter()).ok()?; + + let (id, data) = session_key; + trie.prove(id, data.as_ref()) + .map(|trie_nodes| MembershipProof { + session: session_index, + trie_nodes, + validator_count: count, + }) +} + + +/// Attempt to prune anything that is older than `first_to_keep` session index. +/// +/// Due to re-organisation it could be that the `first_to_keep` might be less +/// than the stored one, in which case the conservative choice is made to keep records +/// up to the one that is the lesser. +pub fn prune_older_than(first_to_keep: SessionIndex) { + let derived_key = shared::LAST_PRUNE.to_vec(); + let entry = StorageValueRef::persistent(derived_key.as_ref()); + match entry.mutate(|current: Option>| -> Result<_, ()> { + match current { + Some(Some(current)) if current < first_to_keep => Ok(first_to_keep), + // do not move the cursor, if the new one would be behind ours + Some(Some(current)) => Ok(current), + None => Ok(first_to_keep), + // if the storage contains undecodable data, overwrite with current anyways + // which might leak some entries being never purged, but that is acceptable + // in this context + Some(None) => Ok(first_to_keep), + } + }) { + Ok(Ok(new_value)) => { + // on a re-org this is not necessarily true, with the above they might be equal + if new_value < first_to_keep { + for session_index in new_value..first_to_keep { + let derived_key = shared::derive_key(shared::PREFIX, session_index); + let _ = StorageValueRef::persistent(derived_key.as_ref()).clear(); + } + } + } + Ok(Err(_)) => {} // failed to store the value calculated with the given closure + Err(_) => {} // failed to calculate the value to store with the given closure + } +} + +/// Keep the newest `n` items, and prune all items older than that. +pub fn keep_newest(n_to_keep: usize) { + let session_index = >::current_index(); + let n_to_keep = n_to_keep as SessionIndex; + if n_to_keep < session_index { + prune_older_than::(session_index - n_to_keep) + } +} + +#[cfg(test)] +mod tests { + use super::super::{onchain, Module}; + use super::*; + use crate::mock::{ + force_new_session, set_next_validators, Session, System, Test, NEXT_VALIDATORS, + }; + use codec::Encode; + use frame_support::traits::{KeyOwnerProofSystem, OnInitialize}; + use sp_core::crypto::key_types::DUMMY; + use sp_core::offchain::{ + testing::TestOffchainExt, + OffchainExt, + StorageKind, + }; + + use sp_runtime::testing::UintAuthorityId; + + type Historical = Module; + + pub fn new_test_ext() -> sp_io::TestExternalities { + let mut ext = frame_system::GenesisConfig::default() + .build_storage::() + .expect("Failed to create test externalities."); + + crate::GenesisConfig:: { + keys: NEXT_VALIDATORS.with(|l| { + l.borrow() + .iter() + .cloned() + .map(|i| (i, i, UintAuthorityId(i).into())) + .collect() + }), + } + .assimilate_storage(&mut ext) + .unwrap(); + + + let mut ext = sp_io::TestExternalities::new(ext); + + let (offchain, offchain_state) = TestOffchainExt::with_offchain_db(ext.offchain_db()); + + const ITERATIONS: u32 = 5u32; + let mut seed = [0u8; 32]; + seed[0..4].copy_from_slice(&ITERATIONS.to_le_bytes()); + offchain_state.write().seed = seed; + + ext.register_extension(OffchainExt::new(offchain)); + ext + } + + #[test] + fn encode_decode_roundtrip() { + use codec::{Decode, Encode}; + use super::super::super::Trait as SessionTrait; + use super::super::Trait as HistoricalTrait; + + let sample = ( + 22u32 as ::ValidatorId, + 7_777_777 as ::FullIdentification); + + let encoded = sample.encode(); + let decoded = Decode::decode(&mut encoded.as_slice()).expect("Must decode"); + assert_eq!(sample, decoded); + } + + #[test] + fn onchain_to_offchain() { + let mut ext = new_test_ext(); + + const DATA: &[u8] = &[7,8,9,10,11]; + ext.execute_with(|| { + b"alphaomega"[..].using_encoded(|key| sp_io::offchain_index::set(key, DATA)); + }); + + ext.persist_offchain_overlay(); + + ext.execute_with(|| { + let data = + b"alphaomega"[..].using_encoded(|key| { + sp_io::offchain::local_storage_get(StorageKind::PERSISTENT, key) + }); + assert_eq!(data, Some(DATA.to_vec())); + }); + } + + + #[test] + fn historical_proof_offchain() { + let mut ext = new_test_ext(); + let encoded_key_1 = UintAuthorityId(1).encode(); + + ext.execute_with(|| { + set_next_validators(vec![1, 2]); + force_new_session(); + + System::set_block_number(1); + Session::on_initialize(1); + + // "on-chain" + onchain::store_current_session_validator_set_to_offchain::(); + assert_eq!(>::current_index(), 1); + + set_next_validators(vec![7, 8]); + + force_new_session(); + }); + + ext.persist_offchain_overlay(); + + ext.execute_with(|| { + + + System::set_block_number(2); + Session::on_initialize(2); + assert_eq!(>::current_index(), 2); + + // "off-chain" + let proof = prove_session_membership::(1, (DUMMY, &encoded_key_1)); + assert!(proof.is_some()); + let proof = proof.expect("Must be Some(Proof)"); + + assert!(Historical::check_proof((DUMMY, &encoded_key_1[..]), proof.clone()).is_some()); + }); + } +} diff --git a/frame/session/src/historical/onchain.rs b/frame/session/src/historical/onchain.rs new file mode 100644 index 0000000000000000000000000000000000000000..745603a49829be556cddd7f1fbfe244a1ea0a93d --- /dev/null +++ b/frame/session/src/historical/onchain.rs @@ -0,0 +1,62 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! On-chain logic to store a validator-set for deferred validation using an off-chain worker. + +use codec::Encode; +use sp_runtime::traits::Convert; + +use super::super::Trait as SessionTrait; +use super::super::{Module as SessionModule, SessionIndex}; +use super::Trait as HistoricalTrait; + +use super::shared; +use sp_std::prelude::*; + +/// Store the validator-set associated to the `session_index` to the off-chain database. +/// +/// Further processing is then done [`off-chain side`](super::offchain). +/// +/// **Must** be called from on-chain, i.e. a call that originates from +/// `on_initialize(..)` or `on_finalization(..)`. +/// **Must** be called during the session, which validator-set is to be stored for further +/// off-chain processing. Otherwise the `FullIdentification` might not be available. +pub fn store_session_validator_set_to_offchain( + session_index: SessionIndex, +) { + let encoded_validator_list = >::validators() + .into_iter() + .filter_map(|validator_id: ::ValidatorId| { + let full_identification = + <::FullIdentificationOf>::convert(validator_id.clone()); + full_identification.map(|full_identification| (validator_id, full_identification)) + }) + .collect::>(); + + encoded_validator_list.using_encoded(|encoded_validator_list| { + let derived_key = shared::derive_key(shared::PREFIX, session_index); + sp_io::offchain_index::set(derived_key.as_slice(), encoded_validator_list); + }); +} + +/// Store the validator set associated to the _current_ session index to the off-chain database. +/// +/// See [`fn store_session_validator_set_...(..)`](Self::store_session_validator_set_to_offchain) +/// for further information and restrictions. +pub fn store_current_session_validator_set_to_offchain() { + store_session_validator_set_to_offchain::(>::current_index()); +} diff --git a/frame/session/src/historical/shared.rs b/frame/session/src/historical/shared.rs new file mode 100644 index 0000000000000000000000000000000000000000..fda0361b05959ab388a34d31d7fce5e1efc8ea4b --- /dev/null +++ b/frame/session/src/historical/shared.rs @@ -0,0 +1,39 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Shared logic between on-chain and off-chain components used for slashing using an off-chain +//! worker. + + +use super::SessionIndex; +use sp_std::prelude::*; +use codec::Encode; + +pub(super) const PREFIX: &[u8] = b"session_historical"; +pub(super) const LAST_PRUNE: &[u8] = b"session_historical_last_prune"; + +/// Derive the key used to store the list of validators +pub(super) fn derive_key>(prefix: P, session_index: SessionIndex) -> Vec { + let prefix: &[u8] = prefix.as_ref(); + session_index.using_encoded(|encoded_session_index| { + prefix.into_iter() + .chain(b"/".into_iter()) + .chain(encoded_session_index.into_iter()) + .copied() + .collect::>() + }) +} \ No newline at end of file diff --git a/frame/session/src/lib.rs b/frame/session/src/lib.rs index 9346b060fa48a8afd22d01dc1d88d6a6b743a8e4..668d9b832889acd8c9948cbb03369b2005a5b884 100644 --- a/frame/session/src/lib.rs +++ b/frame/session/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Session Module //! @@ -110,9 +111,9 @@ use frame_support::{ Get, FindAuthor, ValidatorRegistration, EstimateNextSessionRotation, EstimateNextNewSession, }, dispatch::{self, DispatchResult, DispatchError}, - weights::{Weight, SimpleDispatchInfo, WeighData}, + weights::Weight, }; -use frame_system::{self as system, ensure_signed}; +use frame_system::ensure_signed; #[cfg(test)] mod mock; @@ -170,6 +171,14 @@ impl< offset }) } + + fn weight(_now: BlockNumber) -> Weight { + // Weight note: `estimate_next_session_rotation` has no storage reads and trivial computational overhead. + // There should be no risk to the chain having this weight value be zero for now. + // However, this value of zero was not properly calculated, and so it would be reasonable + // to come back here and properly calculate the weight of this function. + 0 + } } /// A trait for managing creation of new validator set. @@ -210,7 +219,7 @@ pub trait SessionHandler { /// 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). + /// [`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. @@ -342,6 +351,16 @@ impl ValidatorRegistration for Module { } } +pub trait WeightInfo { + fn set_keys(n: u32, ) -> Weight; + fn purge_keys(n: u32, ) -> Weight; +} + +impl WeightInfo for () { + fn set_keys(_n: u32, ) -> Weight { 1_000_000_000 } + fn purge_keys(_n: u32, ) -> Weight { 1_000_000_000 } +} + pub trait Trait: frame_system::Trait { /// The overarching event type. type Event: From + Into<::Event>; @@ -350,6 +369,8 @@ pub trait Trait: frame_system::Trait { type ValidatorId: Member + Parameter; /// A conversion from account ID to validator ID. + /// + /// Its cost must be at most one storage read. type ValidatorIdOf: Convert>; /// Indicator for when to end the session. @@ -374,6 +395,9 @@ pub trait Trait: frame_system::Trait { /// After the threshold is reached `disabled` method starts to return true, /// which in combination with `pallet_staking` forces a new era. type DisabledValidatorsThreshold: Get; + + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; } decl_storage! { @@ -423,7 +447,7 @@ decl_storage! { for (account, val, keys) in config.keys.iter().cloned() { >::inner_set_keys(&val, keys) .expect("genesis config must not contain duplicates; qed"); - system::Module::::inc_ref(&account); + frame_system::Module::::inc_ref(&account); } let initial_validators_0 = T::SessionManager::new_session(0) @@ -493,12 +517,16 @@ decl_module! { /// The dispatch origin of this function must be signed. /// /// # - /// - O(log n) in number of accounts. - /// - One extra DB entry. - /// - Increases system account refs by one on success iff there were previously no keys set. - /// In this case, purge_keys will need to be called before the account can be removed. + /// - Complexity: `O(1)` + /// Actual cost depends on the number of length of `T::Keys::key_ids()` which is fixed. + /// - DbReads: `origin account`, `T::ValidatorIdOf`, `NextKeys` + /// - DbWrites: `origin account`, `NextKeys` + /// - DbReads per key id: `KeyOwner` + /// - DbWrites per key id: `KeyOwner` /// # - #[weight = SimpleDispatchInfo::FixedNormal(150_000)] + #[weight = 200_000_000 + + T::DbWeight::get().reads(2 + T::Keys::key_ids().len() as Weight) + + T::DbWeight::get().writes(1 + T::Keys::key_ids().len() as Weight)] pub fn set_keys(origin, keys: T::Keys, proof: Vec) -> dispatch::DispatchResult { let who = ensure_signed(origin)?; @@ -515,11 +543,14 @@ decl_module! { /// The dispatch origin of this function must be signed. /// /// # - /// - O(N) in number of key types. - /// - Removes N + 1 DB entries. - /// - Reduces system account refs by one on success. + /// - Complexity: `O(1)` in number of key types. + /// Actual cost depends on the number of length of `T::Keys::key_ids()` which is fixed. + /// - DbReads: `T::ValidatorIdOf`, `NextKeys`, `origin account` + /// - DbWrites: `NextKeys`, `origin account` + /// - DbWrites per key id: `KeyOwnder` /// # - #[weight = SimpleDispatchInfo::FixedNormal(150_000)] + #[weight = 120_000_000 + + T::DbWeight::get().reads_writes(2, 1 + T::Keys::key_ids().len() as Weight)] pub fn purge_keys(origin) { let who = ensure_signed(origin)?; Self::do_purge_keys(&who)?; @@ -530,9 +561,13 @@ decl_module! { fn on_initialize(n: T::BlockNumber) -> Weight { if T::ShouldEndSession::should_end_session(n) { Self::rotate_session(); + T::MaximumBlockWeight::get() + } else { + // NOTE: the non-database part of the weight for `should_end_session(n)` is + // included as weight for empty block, the database part is expected to be in + // cache. + 0 } - - SimpleDispatchInfo::default().weigh_data(()) } } } @@ -670,7 +705,7 @@ impl Module { let old_keys = Self::inner_set_keys(&who, keys)?; if old_keys.is_none() { - system::Module::::inc_ref(&account); + frame_system::Module::::inc_ref(&account); } Ok(()) @@ -718,7 +753,7 @@ impl Module { let key_data = old_keys.get_raw(*id); Self::clear_key_owner(*id, key_data); } - system::Module::::dec_ref(&account); + frame_system::Module::::dec_ref(&account); Ok(()) } @@ -772,4 +807,8 @@ impl EstimateNextNewSession for Module { fn estimate_next_new_session(now: T::BlockNumber) -> Option { T::NextSessionRotation::estimate_next_session_rotation(now) } + + fn weight(now: T::BlockNumber) -> Weight { + T::NextSessionRotation::weight(now) + } } diff --git a/frame/session/src/mock.rs b/frame/session/src/mock.rs index dd28d357491dafb1a7f39e8195a75ea8117bad84..57991ad7c44a5064ad12e1d23fde198403f6dd02 100644 --- a/frame/session/src/mock.rs +++ b/frame/session/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Mock helpers for Session. @@ -150,6 +151,16 @@ pub fn reset_before_session_end_called() { BEFORE_SESSION_END_CALLED.with(|b| *b.borrow_mut() = false); } +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + GenesisConfig:: { + keys: NEXT_VALIDATORS.with(|l| + l.borrow().iter().cloned().map(|i| (i, i, UintAuthorityId(i).into())).collect() + ), + }.assimilate_storage(&mut t).unwrap(); + sp_io::TestExternalities::new(t) +} + #[derive(Clone, Eq, PartialEq)] pub struct Test; @@ -162,6 +173,7 @@ parameter_types! { } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -174,6 +186,10 @@ impl frame_system::Trait for Test { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); @@ -181,12 +197,14 @@ impl frame_system::Trait for Test { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } impl pallet_timestamp::Trait for Test { type Moment = u64; type OnTimestampSet = (); type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); } parameter_types! { @@ -206,6 +224,7 @@ impl Trait for Test { type Event = (); type DisabledValidatorsThreshold = DisabledValidatorsThreshold; type NextSessionRotation = (); + type WeightInfo = (); } #[cfg(feature = "historical")] diff --git a/frame/session/src/tests.rs b/frame/session/src/tests.rs index 4e95d91cc7ef8e35b0e94327cc002d1de944f43e..75def78046bebf97111feca0320a256d17bb3207 100644 --- a/frame/session/src/tests.rs +++ b/frame/session/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // Tests for the Session Pallet @@ -21,21 +22,11 @@ use frame_support::{traits::OnInitialize, assert_ok}; use sp_core::crypto::key_types::DUMMY; use sp_runtime::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, + SESSION_CHANGED, TEST_SESSION_CHANGED, authorities, force_new_session, + set_next_validators, set_session_length, session_changed, Origin, System, Session, + reset_before_session_end_called, before_session_end_called, new_test_ext, }; -fn new_test_ext() -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - GenesisConfig:: { - keys: NEXT_VALIDATORS.with(|l| - l.borrow().iter().cloned().map(|i| (i, i, UintAuthorityId(i).into())).collect() - ), - }.assimilate_storage(&mut t).unwrap(); - sp_io::TestExternalities::new(t) -} - fn initialize_block(block: u64) { SESSION_CHANGED.with(|l| *l.borrow_mut() = false); System::set_block_number(block); diff --git a/frame/society/Cargo.toml b/frame/society/Cargo.toml index be419fb63fe2d0800dde5802e9ce1cf02de52b14..67c4c3296639a8683e0ff3ceaedea72aba144731 100644 --- a/frame/society/Cargo.toml +++ b/frame/society/Cargo.toml @@ -1,33 +1,35 @@ [package] name = "pallet-society" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME society pallet" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-io ={ path = "../../primitives/io", default-features = false , version = "2.0.0-alpha.5"} -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } rand_chacha = { version = "0.2", default-features = false } [dev-dependencies] -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -pallet-balances = { version = "2.0.0-alpha.5", path = "../balances" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +sp-io ={ version = "2.0.0-rc4", path = "../../primitives/io" } +pallet-balances = { version = "2.0.0-rc4", path = "../balances" } [features] default = ["std"] std = [ "codec/std", "serde", - "sp-io/std", "sp-runtime/std", "rand_chacha/std", "sp-std/std", @@ -38,6 +40,3 @@ runtime-benchmarks = [ "sp-runtime/runtime-benchmarks", "frame-system/runtime-benchmarks", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/society/src/lib.rs b/frame/society/src/lib.rs index 2061c21d9c5f992cb6a6254918a9133d14483ca6..684fe5043745a4bdaaad32cc798b80dee0316471 100644 --- a/frame/society/src/lib.rs +++ b/frame/society/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Society Module //! @@ -260,7 +261,7 @@ use sp_runtime::{Percent, ModuleId, RuntimeDebug, } }; use frame_support::{decl_error, decl_module, decl_storage, decl_event, ensure, dispatch::DispatchResult}; -use frame_support::weights::{SimpleDispatchInfo, Weight, WeighData}; +use frame_support::weights::Weight; use frame_support::traits::{ Currency, ReservableCurrency, Randomness, Get, ChangeMembers, BalanceStatus, ExistenceRequirement::AllowDeath, EnsureOrigin @@ -269,13 +270,14 @@ use frame_system::{self as system, ensure_signed, ensure_root}; type BalanceOf = <>::Currency as Currency<::AccountId>>::Balance; -const MODULE_ID: ModuleId = ModuleId(*b"py/socie"); - /// The module's configuration trait. pub trait Trait: system::Trait { /// The overarching event type. type Event: From> + Into<::Event>; + /// The societies's module id + type ModuleId: Get; + /// The currency type used for bidding. type Currency: ReservableCurrency; @@ -402,18 +404,18 @@ impl BidKind { decl_storage! { trait Store for Module, I: Instance=DefaultInstance> as Society { /// The first member. - pub Founder get(founder) build(|config: &GenesisConfig| config.members.first().cloned()): + pub Founder get(fn founder) build(|config: &GenesisConfig| config.members.first().cloned()): Option; /// A hash of the rules of this society concerning membership. Can only be set once and /// only by the founder. - pub Rules get(rules): Option; + pub Rules get(fn rules): Option; /// The current set of candidates; bidders that are attempting to become members. - pub Candidates get(candidates): Vec>>; + pub Candidates get(fn candidates): Vec>>; /// The set of suspended candidates. - pub SuspendedCandidates get(suspended_candidate): + pub SuspendedCandidates get(fn suspended_candidate): map hasher(twox_64_concat) T::AccountId => Option<(BalanceOf, BidKind>)>; @@ -421,7 +423,7 @@ decl_storage! { pub Pot get(fn pot) config(): BalanceOf; /// The most primary from the most recently approved members. - pub Head get(head) build(|config: &GenesisConfig| config.members.first().cloned()): + pub Head get(fn head) build(|config: &GenesisConfig| config.members.first().cloned()): Option; /// The current set of members, ordered. @@ -491,6 +493,9 @@ decl_module! { /// The number of blocks between membership challenges. const ChallengePeriod: T::BlockNumber = T::ChallengePeriod::get(); + /// The societies's module id + const ModuleId: ModuleId = T::ModuleId::get(); + // Used for handling module events. fn deposit_event() = default; @@ -527,7 +532,7 @@ decl_module! { /// /// Total Complexity: O(M + B + C + logM + logB + X) /// # - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + #[weight = T::MaximumBlockWeight::get() / 10] pub fn bid(origin, value: BalanceOf) -> DispatchResult { let who = ensure_signed(origin)?; ensure!(!>::contains_key(&who), Error::::Suspended); @@ -566,7 +571,7 @@ decl_module! { /// /// Total Complexity: O(B + X) /// # - #[weight = SimpleDispatchInfo::FixedNormal(20_000)] + #[weight = T::MaximumBlockWeight::get() / 10] pub fn unbid(origin, pos: u32) -> DispatchResult { let who = ensure_signed(origin)?; @@ -636,7 +641,7 @@ decl_module! { /// /// Total Complexity: O(M + B + C + logM + logB + X) /// # - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + #[weight = T::MaximumBlockWeight::get() / 10] pub fn vouch(origin, who: T::AccountId, value: BalanceOf, tip: BalanceOf) -> DispatchResult { let voucher = ensure_signed(origin)?; // Check user is not suspended. @@ -677,7 +682,7 @@ decl_module! { /// /// Total Complexity: O(B) /// # - #[weight = SimpleDispatchInfo::FixedNormal(20_000)] + #[weight = T::MaximumBlockWeight::get() / 10] pub fn unvouch(origin, pos: u32) -> DispatchResult { let voucher = ensure_signed(origin)?; ensure!(Self::vouching(&voucher) == Some(VouchingStatus::Vouching), Error::::NotVouching); @@ -715,7 +720,7 @@ decl_module! { /// /// Total Complexity: O(M + logM + C) /// # - #[weight = SimpleDispatchInfo::FixedNormal(30_000)] + #[weight = T::MaximumBlockWeight::get() / 10] pub fn vote(origin, candidate: ::Source, approve: bool) { let voter = ensure_signed(origin)?; let candidate = T::Lookup::lookup(candidate)?; @@ -746,7 +751,7 @@ decl_module! { /// /// Total Complexity: O(M + logM) /// # - #[weight = SimpleDispatchInfo::FixedNormal(20_000)] + #[weight = T::MaximumBlockWeight::get() / 10] pub fn defender_vote(origin, approve: bool) { let voter = ensure_signed(origin)?; let members = >::get(); @@ -778,7 +783,7 @@ decl_module! { /// /// Total Complexity: O(M + logM + P + X) /// # - #[weight = SimpleDispatchInfo::FixedNormal(30_000)] + #[weight = T::MaximumBlockWeight::get() / 10] pub fn payout(origin) { let who = ensure_signed(origin)?; @@ -820,7 +825,7 @@ decl_module! { /// /// Total Complexity: O(1) /// # - #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + #[weight = T::MaximumBlockWeight::get() / 10] fn found(origin, founder: T::AccountId, max_members: u32, rules: Vec) { T::FounderSetOrigin::ensure_origin(origin)?; ensure!(!>::exists(), Error::::AlreadyFounded); @@ -847,7 +852,7 @@ decl_module! { /// /// Total Complexity: O(1) /// # - #[weight = SimpleDispatchInfo::FixedNormal(20_000)] + #[weight = T::MaximumBlockWeight::get() / 10] fn unfound(origin) { let founder = ensure_signed(origin)?; ensure!(Founder::::get() == Some(founder.clone()), Error::::NotFounder); @@ -889,7 +894,7 @@ decl_module! { /// /// Total Complexity: O(M + logM + B) /// # - #[weight = SimpleDispatchInfo::FixedNormal(30_000)] + #[weight = T::MaximumBlockWeight::get() / 10] fn judge_suspended_member(origin, who: T::AccountId, forgive: bool) { T::SuspensionJudgementOrigin::ensure_origin(origin)?; ensure!(>::contains_key(&who), Error::::NotSuspended); @@ -960,7 +965,7 @@ decl_module! { /// /// Total Complexity: O(M + logM + B + X) /// # - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + #[weight = T::MaximumBlockWeight::get() / 10] fn judge_suspended_candidate(origin, who: T::AccountId, judgement: Judgement) { T::SuspensionJudgementOrigin::ensure_origin(origin)?; if let Some((value, kind)) = >::get(&who) { @@ -1020,7 +1025,7 @@ decl_module! { /// /// Total Complexity: O(1) /// # - #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + #[weight = T::MaximumBlockWeight::get() / 10] fn set_max_members(origin, max: u32) { ensure_root(origin)?; ensure!(max > 1, Error::::MaxMembers); @@ -1031,10 +1036,14 @@ decl_module! { fn on_initialize(n: T::BlockNumber) -> Weight { let mut members = vec![]; + let mut weight = 0; + // Run a candidate/membership rotation if (n % T::RotationPeriod::get()).is_zero() { members = >::get(); Self::rotate_period(&mut members); + + weight += T::MaximumBlockWeight::get() / 20; } // Run a challenge rotation @@ -1044,9 +1053,11 @@ decl_module! { members = >::get(); } Self::rotate_challenge(&mut members); + + weight += T::MaximumBlockWeight::get() / 20; } - SimpleDispatchInfo::default().weigh_data(()) + weight } } } @@ -1570,7 +1581,7 @@ impl, I: Instance> Module { /// This actually does computation. If you need to keep using it, then make sure you cache the /// value and only call this once. pub fn account_id() -> T::AccountId { - MODULE_ID.into_account() + T::ModuleId::get().into_account() } /// The account ID of the payouts pot. This is where payouts are made from. @@ -1578,7 +1589,7 @@ impl, I: Instance> Module { /// This actually does computation. If you need to keep using it, then make sure you cache the /// value and only call this once. pub fn payouts() -> T::AccountId { - MODULE_ID.into_sub_account(b"payouts") + T::ModuleId::get().into_sub_account(b"payouts") } /// Return the duration of the lock, in blocks, with the given number of members. diff --git a/frame/society/src/mock.rs b/frame/society/src/mock.rs index a66a5e6e047d44230b35f62fcf1a78043b5e1085..f29dbc8cb17ad5aee8821f8888d89f85c2eee910 100644 --- a/frame/society/src/mock.rs +++ b/frame/society/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utilities @@ -22,8 +23,6 @@ use frame_support::{ impl_outer_origin, parameter_types, ord_parameter_types, traits::{OnInitialize, OnFinalize} }; use sp_core::H256; -// The testing primitives are very useful for avoiding having to work with signatures -// or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. use sp_runtime::{ Perbill, testing::Header, @@ -35,9 +34,6 @@ impl_outer_origin! { pub enum Origin for Test {} } -// For testing the pallet, we construct most of a mock runtime. This means -// first constructing a configuration type (`Test`) which `impl`s each of the -// configuration traits of pallets we want to use. #[derive(Clone, Eq, PartialEq)] pub struct Test; parameter_types! { @@ -55,6 +51,7 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const ExistentialDeposit: u64 = 1; + pub const SocietyModuleId: ModuleId = ModuleId(*b"py/socie"); } ord_parameter_types! { @@ -63,6 +60,7 @@ ord_parameter_types! { } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -75,6 +73,10 @@ impl frame_system::Trait for Test { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -82,6 +84,7 @@ impl frame_system::Trait for Test { type OnNewAccount = (); type OnKilledAccount = (); type AccountData = pallet_balances::AccountData; + type SystemWeightInfo = (); } impl pallet_balances::Trait for Test { @@ -90,6 +93,7 @@ impl pallet_balances::Trait for Test { type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; + type WeightInfo = (); } impl Trait for Test { @@ -106,6 +110,7 @@ impl Trait for Test { type FounderSetOrigin = EnsureSignedBy; type SuspensionJudgementOrigin = EnsureSignedBy; type ChallengePeriod = ChallengePeriod; + type ModuleId = SocietyModuleId; } pub type Society = Module; diff --git a/frame/society/src/tests.rs b/frame/society/src/tests.rs index 8b10dc32e7ba0de12199d35ce580e77319090d26..0374c7bcd7a6079d1b7960a5f87fef0e89d17547 100644 --- a/frame/society/src/tests.rs +++ b/frame/society/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for the module. @@ -812,7 +813,7 @@ fn max_limits_work() { // No candidates because full assert_eq!(Society::candidates().len(), 0); // Increase member limit - assert_ok!(Society::set_max_members(Origin::ROOT, 200)); + assert_ok!(Society::set_max_members(Origin::root(), 200)); // Rotate period run_to_block(16); // Candidates are back! diff --git a/frame/staking/Cargo.toml b/frame/staking/Cargo.toml index aac5616e4ea18cd2ff64d9dc0a4fe0da46e24c00..144095cfa97744ac22ec36be1d7be7d796e20a4e 100644 --- a/frame/staking/Cargo.toml +++ b/frame/staking/Cargo.toml @@ -1,63 +1,55 @@ [package] name = "pallet-staking" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet staking" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-phragmen = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/phragmen" } -sp-io ={ path = "../../primitives/io", default-features = false , version = "2.0.0-alpha.5"} -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -sp-staking = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/staking" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } -pallet-session = { version = "2.0.0-alpha.5", features = ["historical"], path = "../session", default-features = false } -pallet-authorship = { version = "2.0.0-alpha.5", default-features = false, path = "../authorship" } -sp-application-crypto = { version = "2.0.0-alpha.4", default-features = false, path = "../../primitives/application-crypto" } static_assertions = "1.1.0" - -# Optional imports for tesing-utils feature -pallet-indices = { version = "2.0.0-alpha.4", optional = true, path = "../indices", default-features = false } -sp-core = { version = "2.0.0-alpha.4", optional = true, path = "../../primitives/core", default-features = false } -rand = { version = "0.7.3", optional = true, default-features = false } +serde = { version = "1.0.101", optional = true } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-npos-elections = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/npos-elections" } +sp-io ={ version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +sp-staking = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/staking" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } +pallet-session = { version = "2.0.0-rc4", default-features = false, features = ["historical"], path = "../session" } +pallet-authorship = { version = "2.0.0-rc4", default-features = false, path = "../authorship" } +sp-application-crypto = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/application-crypto" } # Optional imports for benchmarking -frame-benchmarking = { version = "2.0.0-alpha.5", default-features = false, path = "../benchmarking", optional = true } +frame-benchmarking = { version = "2.0.0-rc4", default-features = false, path = "../benchmarking", optional = true } rand_chacha = { version = "0.2", default-features = false, optional = true } [dev-dependencies] -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -sp-storage = { version = "2.0.0-alpha.5", path = "../../primitives/storage" } -pallet-balances = { version = "2.0.0-alpha.5", path = "../balances" } -pallet-timestamp = { version = "2.0.0-alpha.5", path = "../timestamp" } -pallet-staking-reward-curve = { version = "2.0.0-alpha.5", path = "../staking/reward-curve" } -substrate-test-utils = { version = "2.0.0-alpha.5", path = "../../test-utils" } -frame-benchmarking = { version = "2.0.0-alpha.5", path = "../benchmarking" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +sp-storage = { version = "2.0.0-rc4", path = "../../primitives/storage" } +pallet-balances = { version = "2.0.0-rc4", path = "../balances" } +pallet-timestamp = { version = "2.0.0-rc4", path = "../timestamp" } +pallet-staking-reward-curve = { version = "2.0.0-rc4", path = "../staking/reward-curve" } +substrate-test-utils = { version = "2.0.0-rc4", path = "../../test-utils" } +frame-benchmarking = { version = "2.0.0-rc4", path = "../benchmarking" } rand_chacha = { version = "0.2" } -parking_lot = "0.10.0" +parking_lot = "0.10.2" env_logger = "0.7.1" hex = "0.4" [features] -testing-utils = [ - "std", - "pallet-indices/std", - "sp-core/std", - "rand/std", -] default = ["std"] std = [ "serde", "codec/std", "sp-std/std", - "sp-phragmen/std", + "sp-npos-elections/std", "sp-io/std", "frame-support/std", "sp-runtime/std", @@ -66,12 +58,8 @@ std = [ "frame-system/std", "pallet-authorship/std", "sp-application-crypto/std", - "sp-core/std", ] runtime-benchmarks = [ - "rand_chacha", "frame-benchmarking", + "rand_chacha", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/staking/fuzz/.gitignore b/frame/staking/fuzz/.gitignore deleted file mode 100644 index 572e03bdf321b6cc3a99488183436905cefd086d..0000000000000000000000000000000000000000 --- a/frame/staking/fuzz/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ - -target -corpus -artifacts diff --git a/frame/staking/fuzz/Cargo.toml b/frame/staking/fuzz/Cargo.toml deleted file mode 100644 index a78fbf17dc8a3a1dd3c8572167d8d1d27692059a..0000000000000000000000000000000000000000 --- a/frame/staking/fuzz/Cargo.toml +++ /dev/null @@ -1,38 +0,0 @@ -[package] -name = "pallet-staking-fuzz" -version = "0.0.0" -authors = ["Automatically generated"] -publish = false -edition = "2018" - -[package.metadata] -cargo-fuzz = true - -[dependencies] -libfuzzer-sys = "0.3" -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -pallet-staking = { version = "2.0.0-alpha.2", path = "..", features = ["testing-utils"] } -pallet-staking-reward-curve = { version = "2.0.0-alpha.2", path = "../reward-curve" } -pallet-session = { version = "2.0.0-alpha.2", path = "../../session" } -pallet-indices = { version = "2.0.0-alpha.2", path = "../../indices" } -pallet-balances = { version = "2.0.0-alpha.2", path = "../../balances" } -pallet-timestamp = { version = "2.0.0-alpha.2", path = "../../timestamp" } -frame-system = { version = "2.0.0-alpha.2", path = "../../system" } -frame-support = { version = "2.0.0-alpha.2", path = "../../support" } -sp-std = { version = "2.0.0-alpha.2", path = "../../../primitives/std" } -sp-io ={ version = "2.0.0-alpha.2", path = "../../../primitives/io" } -sp-core = { version = "2.0.0-alpha.2", path = "../../../primitives/core" } -sp-phragmen = { version = "2.0.0-alpha.2", path = "../../../primitives/phragmen" } -sp-runtime = { version = "2.0.0-alpha.2", path = "../../../primitives/runtime" } -rand = "0.7.3" - -# Prevent this from interfering with workspaces -[workspace] -members = ["."] - -[[bin]] -name = "submit_solution" -path = "fuzz_targets/submit_solution.rs" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/staking/fuzz/fuzz_targets/submit_solution.rs b/frame/staking/fuzz/fuzz_targets/submit_solution.rs deleted file mode 100644 index 5d1fcf1d7ea850dd033b89e41514cd672848ab24..0000000000000000000000000000000000000000 --- a/frame/staking/fuzz/fuzz_targets/submit_solution.rs +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2020 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 . - -//! Fuzzing for staking pallet. - -#![no_main] -use libfuzzer_sys::fuzz_target; -use mock::Test; -use pallet_staking::testing_utils::{ - self, USER, get_seq_phragmen_solution, get_weak_solution, setup_chain_stakers, - set_validator_count, signed_account, -}; -use frame_support::assert_ok; -use sp_runtime::{traits::Dispatchable, DispatchError}; - -mod mock; - -#[repr(u32)] -#[allow(dead_code)] -#[derive(Debug, Clone, Copy)] -enum Mode { - /// Initial submission. This will be rather cheap. - InitialSubmission, - /// A better submission that will replace the previous ones. This is the most expensive. - StrongerSubmission, - /// A weak submission that will be rejected. This will be rather cheap. - WeakerSubmission, -} - -pub fn new_test_ext() -> Result { - frame_system::GenesisConfig::default().build_storage::().map(Into::into) -} - -fuzz_target!(|do_reduce: bool| { - let ext = new_test_ext(); - let mode: Mode = unsafe { std::mem::transmute(testing_utils::random(0, 2)) }; - let num_validators = testing_utils::random(50, 500); - let num_nominators = testing_utils::random(200, 2000); - let edge_per_voter = testing_utils::random(1, 16); - let to_elect = testing_utils::random(10, num_validators); - - println!("+++ instance with params {} / {} / {} / {:?} / {}", - num_nominators, - num_validators, - edge_per_voter, - mode, - to_elect, - ); - - ext.unwrap_or_default().execute_with(|| { - // initial setup - set_validator_count::(to_elect); - setup_chain_stakers::( - num_validators, - num_nominators, - edge_per_voter, - ); - - println!("++ Chain setup done."); - - // stuff to submit - let (winners, compact, score) = match mode { - Mode::InitialSubmission => { - /* No need to setup anything */ - get_seq_phragmen_solution::(do_reduce) - }, - Mode::StrongerSubmission => { - let (winners, compact, score) = get_weak_solution::(false); - assert_ok!( - >::submit_election_solution( - signed_account::(USER), - winners, - compact, - score, - ) - ); - get_seq_phragmen_solution::(do_reduce) - }, - Mode::WeakerSubmission => { - let (winners, compact, score) = get_seq_phragmen_solution::(do_reduce); - assert_ok!( - >::submit_election_solution( - signed_account::(USER), - winners, - compact, - score, - ) - ); - get_weak_solution::(false) - } - }; - - println!("++ Submission ready."); - - // must have chosen correct number of winners. - assert_eq!(winners.len() as u32, >::validator_count()); - - // final call and origin - let call = pallet_staking::Call::::submit_election_solution( - winners, - compact, - score, - ); - let caller = signed_account::(USER); - - // actually submit - match mode { - Mode::WeakerSubmission => { - assert_eq!( - call.dispatch(caller.into()).unwrap_err(), - DispatchError::Module { index: 0, error: 11, message: Some("PhragmenWeakSubmission") }, - ); - }, - _ => assert_ok!(call.dispatch(caller.into())), - }; - }) -}); diff --git a/primitives/phragmen/fuzzer/.gitignore b/frame/staking/fuzzer/.gitignore similarity index 100% rename from primitives/phragmen/fuzzer/.gitignore rename to frame/staking/fuzzer/.gitignore diff --git a/frame/staking/fuzz/Cargo.lock b/frame/staking/fuzzer/Cargo.lock similarity index 85% rename from frame/staking/fuzz/Cargo.lock rename to frame/staking/fuzzer/Cargo.lock index f6e8cfa08d6675144979b3a5ef10eaa8f9dcf0d3..e451e12d101310d0ec36d08f0105b8fbd496cc64 100644 --- a/frame/staking/fuzz/Cargo.lock +++ b/frame/staking/fuzzer/Cargo.lock @@ -28,11 +28,31 @@ dependencies = [ "memchr", ] +[[package]] +name = "alga" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f823d037a7ec6ea2197046bafd4ae150e6bc36f9ca347404f46a46823fa84f2" +dependencies = [ + "approx", + "num-complex", + "num-traits", +] + +[[package]] +name = "approx" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3" +dependencies = [ + "num-traits", +] + [[package]] name = "arbitrary" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16971f2f0ce65c5cf2a1546cc6a0af102ecb11e265ddaa9433fb3e5bfdf676a4" +checksum = "75153c95fdedd7db9732dfbfc3702324a1627eec91ba56e37cd0ac78314ab2ed" [[package]] name = "arrayref" @@ -69,9 +89,9 @@ checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" [[package]] name = "backtrace" -version = "0.3.45" +version = "0.3.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad235dabf00f36301792cfe82499880ba54c6486be094d1047b02bacb67c14e8" +checksum = "b1e692897359247cc6bb902933361652380af0f1b7651ae5c5013407f30e109e" dependencies = [ "backtrace-sys", "cfg-if", @@ -81,9 +101,9 @@ dependencies = [ [[package]] name = "backtrace-sys" -version = "0.1.33" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17b52e737c40a7d75abca20b29a19a0eb7ba9fc72c5a72dd282a0a3c2c0dc35" +checksum = "7de8aba10a69c8e8d7622c5710229485ec32e9d55fdad160ea559c086fdcd118" dependencies = [ "cc", "libc", @@ -109,9 +129,13 @@ checksum = "5da9b3d9f6f585199287a473f4f8dfab6566cf827d15c00c219f53c645687ead" [[package]] name = "bitvec" -version = "0.15.2" +version = "0.17.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993f74b4c99c1908d156b8d2e0fb6277736b0ecbd833982fd1241d39b2766a6" +checksum = "41262f11d771fd4a61aa3ce019fca363b4b6c282fca9da2a31186d3965a47a5c" +dependencies = [ + "either", + "radium", +] [[package]] name = "blake2-rfc" @@ -146,9 +170,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.2.0" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f359dc14ff8911330a51ef78022d376f25ed00248912803b58f00cb1c27f742" +checksum = "12ae9db68ad7fac5fe51304d20f016c911539251075a214f8e663babefa35187" [[package]] name = "byte-slice-cast" @@ -168,15 +192,6 @@ version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" -[[package]] -name = "c2-chacha" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" -dependencies = [ - "ppv-lite86", -] - [[package]] name = "cc" version = "1.0.50" @@ -249,19 +264,6 @@ dependencies = [ "subtle 1.0.0", ] -[[package]] -name = "curve25519-dalek" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b7dcd30ba50cdf88b55b033456138b7c0ac4afdc436d82e1b79f370f24cc66d" -dependencies = [ - "byteorder", - "clear_on_drop", - "digest", - "rand_core 0.3.1", - "subtle 2.2.2", -] - [[package]] name = "curve25519-dalek" version = "2.0.0" @@ -272,14 +274,14 @@ dependencies = [ "digest", "rand_core 0.5.1", "subtle 2.2.2", - "zeroize 1.1.0", + "zeroize", ] [[package]] name = "derive_more" -version = "0.99.3" +version = "0.99.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a806e96c59a76a5ba6e18735b6cf833344671e61e7863f2edb5c518ea2cac95c" +checksum = "e2323f3f47db9a0e77ce7a300605d8d2098597fc451ed1a97bb1f6411bb550a7" dependencies = [ "proc-macro2", "quote", @@ -302,11 +304,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978710b352437433c97b2bff193f2fb1dfd58a093f863dd95e225a19baa599a2" dependencies = [ "clear_on_drop", - "curve25519-dalek 2.0.0", + "curve25519-dalek", "rand 0.7.3", "sha2", ] +[[package]] +name = "either" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" + [[package]] name = "environmental" version = "1.1.1" @@ -343,12 +351,11 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "fixed-hash" -version = "0.5.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3367952ceb191f4ab95dd5685dc163ac539e36202f9fcfd0cb22f9f9c542fefc" +checksum = "32529fc42e86ec06e5047092082aab9ad459b070c5d2a76b14f4f5ce70bf2e84" dependencies = [ "byteorder", - "libc", "rand 0.7.3", "rustc-hex", "static_assertions", @@ -356,10 +363,11 @@ dependencies = [ [[package]] name = "frame-benchmarking" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "frame-support", "frame-system", + "linregress", "parity-scale-codec", "sp-api", "sp-io", @@ -370,7 +378,7 @@ dependencies = [ [[package]] name = "frame-metadata" -version = "11.0.0-alpha.3" +version = "11.0.0-alpha.5" dependencies = [ "parity-scale-codec", "serde", @@ -380,7 +388,7 @@ dependencies = [ [[package]] name = "frame-support" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "bitmask", "frame-metadata", @@ -403,7 +411,7 @@ dependencies = [ [[package]] name = "frame-support-procedural" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "frame-support-procedural-tools", "proc-macro2", @@ -413,7 +421,7 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "frame-support-procedural-tools-derive", "proc-macro-crate", @@ -424,7 +432,7 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools-derive" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "proc-macro2", "quote", @@ -433,7 +441,7 @@ dependencies = [ [[package]] name = "frame-system" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "frame-support", "impl-trait-for-tuples", @@ -492,6 +500,7 @@ dependencies = [ "futures-core", "futures-task", "futures-util", + "num_cpus", ] [[package]] @@ -597,6 +606,15 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "hermit-abi" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "725cf19794cf90aa94e65050cb4191ff5d8fa87a498383774c47b332e3af952e" +dependencies = [ + "libc", +] + [[package]] name = "hex" version = "0.4.2" @@ -670,9 +688,9 @@ checksum = "f65877bf7d44897a473350b1046277941cee20b263397e90869c50b6e766088b" [[package]] name = "js-sys" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cb931d43e71f560c81badb0191596562bafad2be06a3f9025b845c847c60df5" +checksum = "6a27d435371a2fa5b6d2b028a74bbdb1234f308da363226a2854ca3ff8ba7055" dependencies = [ "wasm-bindgen", ] @@ -691,20 +709,26 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.67" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018" +checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" [[package]] name = "libfuzzer-sys" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb789afcc589a08928d1e466087445ab740a0f70a2ee23d9349a0e3723d65e1b" +checksum = "8d718794b8e23533b9069bd2c4597d69e41cc7ab1c02700a502971aca0cdcf24" dependencies = [ "arbitrary", "cc", ] +[[package]] +name = "libm" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" + [[package]] name = "libsecp256k1" version = "0.3.5" @@ -721,6 +745,17 @@ dependencies = [ "typenum", ] +[[package]] +name = "linregress" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9290cf6f928576eeb9c096c6fad9d8d452a0a1a70a2bbffa6e36064eedc0aac9" +dependencies = [ + "failure", + "nalgebra", + "statrs", +] + [[package]] name = "lock_api" version = "0.3.3" @@ -739,6 +774,15 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "matrixmultiply" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4f7ec66360130972f34830bfad9ef05c6610a43938a467bcc9ab9369ab3478f" +dependencies = [ + "rawpointer", +] + [[package]] name = "maybe-uninit" version = "2.0.0" @@ -753,9 +797,9 @@ checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" [[package]] name = "memory-db" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "198831fe8722331a395bc199a5d08efbc197497ef354cb4c77b969c02ffc0fc4" +checksum = "f58381b20ebe2c578e75dececd9da411414903415349548ccc46aac3209cdfbc" dependencies = [ "ahash", "hash-db", @@ -771,14 +815,31 @@ checksum = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" [[package]] name = "merlin" -version = "1.3.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b0942b357c1b4d0dc43ba724674ec89c3218e6ca2b3e8269e7cb53bcecd2f6e" +checksum = "c6feca46f4fa3443a01769d768727f10c10a20fdb65e52dc16a81f0c8269bb78" dependencies = [ "byteorder", "keccak", - "rand_core 0.4.2", - "zeroize 1.1.0", + "rand_core 0.5.1", + "zeroize", +] + +[[package]] +name = "nalgebra" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aaa9fddbc34c8c35dd2108515587b8ce0cab396f17977b8c738568e4edb521a2" +dependencies = [ + "alga", + "approx", + "generic-array", + "matrixmultiply", + "num-complex", + "num-rational", + "num-traits", + "rand 0.6.5", + "typenum", ] [[package]] @@ -798,6 +859,16 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-complex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" +dependencies = [ + "autocfg 1.0.0", + "num-traits", +] + [[package]] name = "num-integer" version = "0.1.42" @@ -810,9 +881,9 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da4dc79f9e6c81bef96148c8f6b8e72ad4541caa4a24373e900a36da07de03a3" +checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" dependencies = [ "autocfg 1.0.0", "num-bigint", @@ -827,6 +898,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" dependencies = [ "autocfg 1.0.0", + "libm", +] + +[[package]] +name = "num_cpus" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6" +dependencies = [ + "hermit-abi", + "libc", ] [[package]] @@ -846,7 +928,7 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "pallet-authorship" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "frame-support", "frame-system", @@ -862,7 +944,7 @@ dependencies = [ [[package]] name = "pallet-balances" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "frame-benchmarking", "frame-support", @@ -876,7 +958,7 @@ dependencies = [ [[package]] name = "pallet-indices" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "frame-support", "frame-system", @@ -891,7 +973,7 @@ dependencies = [ [[package]] name = "pallet-session" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "frame-support", "frame-system", @@ -908,7 +990,7 @@ dependencies = [ [[package]] name = "pallet-staking" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "frame-support", "frame-system", @@ -921,7 +1003,7 @@ dependencies = [ "sp-application-crypto", "sp-core", "sp-io", - "sp-phragmen", + "sp-npos-elections", "sp-runtime", "sp-staking", "sp-std", @@ -945,14 +1027,14 @@ dependencies = [ "rand 0.7.3", "sp-core", "sp-io", - "sp-phragmen", + "sp-npos-elections", "sp-runtime", "sp-std", ] [[package]] name = "pallet-staking-reward-curve" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -962,7 +1044,7 @@ dependencies = [ [[package]] name = "pallet-timestamp" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "frame-benchmarking", "frame-support", @@ -980,7 +1062,7 @@ dependencies = [ name = "parity-scale-codec" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f509c5e67ca0605ee17dcd3f91ef41cadd685c75a298fb6261b781a5acb3f910" +checksum = "329c8f7f4244ddb5c37c103641027a76c530e65e8e4b8240b29f81ea40508b17" dependencies = [ "arrayvec 0.5.1", "bitvec", @@ -991,7 +1073,7 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "1.3.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a0ec292e92e8ec7c58e576adacc1e3f399c597c8f263c42f18420abe58e7245" dependencies = [ @@ -1003,9 +1085,9 @@ dependencies = [ [[package]] name = "parity-util-mem" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef1476e40bf8f5c6776e9600983435821ca86eb9819d74a6207cca69d091406a" +checksum = "6e42755f26e5ea21a6a819d9e63cbd70713e9867a2b767ec2cc65ca7659532c5" dependencies = [ "cfg-if", "impl-trait-for-tuples", @@ -1078,15 +1160,15 @@ dependencies = [ "cloudabi", "libc", "redox_syscall", - "smallvec 1.3.0", + "smallvec 1.2.0", "winapi", ] [[package]] name = "paste" -version = "0.1.7" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e1afe738d71b1ebab5f1207c055054015427dbfc7bbe9ee1266894156ec046" +checksum = "092d791bf7847f70bbd49085489fba25fc2c193571752bff9e36e74e72403932" dependencies = [ "paste-impl", "proc-macro-hack", @@ -1094,9 +1176,9 @@ dependencies = [ [[package]] name = "paste-impl" -version = "0.1.7" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d4dc4a7f6f743211c5aab239640a65091535d97d43d92a52bca435a640892bb" +checksum = "406c23fb4c45cc6f68a9bbabb8ec7bd6f8cfcbd17e9e8f72c2460282f8325729" dependencies = [ "proc-macro-hack", "proc-macro2", @@ -1128,9 +1210,9 @@ checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" [[package]] name = "primitive-types" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4336f4f5d5524fa60bcbd6fe626f9223d8142a50e7053e979acdf0da41ab975" +checksum = "e5e4b9943a2da369aec5e96f7c10ebc74fcf434d39590d974b0a3460e6f67fbb" dependencies = [ "fixed-hash", "impl-codec", @@ -1149,26 +1231,21 @@ dependencies = [ [[package]] name = "proc-macro-hack" -version = "0.5.11" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] +checksum = "fcfdefadc3d57ca21cf17990a28ef4c0f7c61383a28cb7604cf4a18e6ede1420" [[package]] name = "proc-macro-nested" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" +checksum = "8e946095f9d3ed29ec38de908c22f95d9ac008e424c7bcae54c75a79c527c694" [[package]] name = "proc-macro2" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" +checksum = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3" dependencies = [ "unicode-xid", ] @@ -1182,6 +1259,25 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "def50a86306165861203e7f84ecffbbdfdea79f0e51039b33de1e952358c47ac" + +[[package]] +name = "rand" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" +dependencies = [ + "cloudabi", + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "winapi", +] + [[package]] name = "rand" version = "0.6.5" @@ -1209,7 +1305,7 @@ checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ "getrandom", "libc", - "rand_chacha 0.2.1", + "rand_chacha 0.2.2", "rand_core 0.5.1", "rand_hc 0.2.0", ] @@ -1226,11 +1322,11 @@ dependencies = [ [[package]] name = "rand_chacha" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" dependencies = [ - "c2-chacha", + "ppv-lite86", "rand_core 0.5.1", ] @@ -1329,6 +1425,12 @@ dependencies = [ "rand_core 0.3.1", ] +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + [[package]] name = "rdrand" version = "0.4.0" @@ -1346,9 +1448,9 @@ checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" [[package]] name = "regex" -version = "1.3.4" +version = "1.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322cf97724bea3ee221b78fe25ac9c46114ebb51747ad5babd51a2fc6a8235a8" +checksum = "7f6946991529684867e47d86474e3a6d0c0ab9b82d5821e314b1ede31fa3a4b3" dependencies = [ "aho-corasick", "memchr", @@ -1358,9 +1460,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.16" +version = "0.6.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1132f845907680735a84409c3bebc64d1364a5683ffbce899550cd09d5eaefc1" +checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae" [[package]] name = "rustc-demangle" @@ -1391,19 +1493,20 @@ dependencies = [ [[package]] name = "schnorrkel" -version = "0.8.5" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eacd8381b3c37840c9c9f40472af529e49975bdcbc24f83c31059fd6539023d3" +checksum = "021b403afe70d81eea68f6ea12f6b3c9588e5d536a94c3bf80f15e7faa267862" dependencies = [ - "curve25519-dalek 1.2.3", - "failure", + "arrayref", + "arrayvec 0.5.1", + "curve25519-dalek", + "getrandom", "merlin", - "rand 0.6.5", - "rand_core 0.4.2", - "rand_os", + "rand 0.7.3", + "rand_core 0.5.1", "sha2", "subtle 2.2.2", - "zeroize 0.9.3", + "zeroize", ] [[package]] @@ -1435,18 +1538,18 @@ checksum = "a0eddf2e8f50ced781f288c19f18621fa72a3779e3cb58dbf23b07469b0abeb4" [[package]] name = "serde" -version = "1.0.104" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" +checksum = "e707fbbf255b8fc8c3b99abb91e7257a622caeb20a9818cbadbeeede4e0932ff" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.104" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" +checksum = "ac5d00fc561ba2724df6758a17de23df5914f20e41cb00f94d5b7ae42fffaff8" dependencies = [ "proc-macro2", "quote", @@ -1482,13 +1585,13 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.3.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" [[package]] name = "sp-api" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "hash-db", "parity-scale-codec", @@ -1502,7 +1605,7 @@ dependencies = [ [[package]] name = "sp-api-proc-macro" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "blake2-rfc", "proc-macro-crate", @@ -1513,7 +1616,7 @@ dependencies = [ [[package]] name = "sp-application-crypto" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "parity-scale-codec", "serde", @@ -1524,7 +1627,7 @@ dependencies = [ [[package]] name = "sp-arithmetic" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "integer-sqrt", "num-traits", @@ -1536,7 +1639,7 @@ dependencies = [ [[package]] name = "sp-authorship" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "parity-scale-codec", "sp-inherents", @@ -1546,12 +1649,13 @@ dependencies = [ [[package]] name = "sp-core" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "base58", "blake2-rfc", "byteorder", "ed25519-dalek", + "futures", "hash-db", "hash256-std-hasher", "hex", @@ -1566,7 +1670,6 @@ dependencies = [ "primitive-types", "rand 0.7.3", "regex", - "rustc-hex", "schnorrkel", "serde", "sha2", @@ -1580,12 +1683,12 @@ dependencies = [ "tiny-keccak", "twox-hash", "wasmi", - "zeroize 1.1.0", + "zeroize", ] [[package]] name = "sp-debug-derive" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "proc-macro2", "quote", @@ -1594,7 +1697,7 @@ dependencies = [ [[package]] name = "sp-externalities" -version = "0.8.0-alpha.3" +version = "0.8.0-alpha.5" dependencies = [ "environmental", "sp-std", @@ -1603,7 +1706,7 @@ dependencies = [ [[package]] name = "sp-inherents" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "derive_more", "parity-scale-codec", @@ -1614,7 +1717,7 @@ dependencies = [ [[package]] name = "sp-io" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "hash-db", "libsecp256k1", @@ -1631,7 +1734,7 @@ dependencies = [ [[package]] name = "sp-keyring" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "lazy_static", "sp-core", @@ -1641,27 +1744,26 @@ dependencies = [ [[package]] name = "sp-panic-handler" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "backtrace", "log", ] [[package]] -name = "sp-phragmen" -version = "2.0.0-alpha.3" +name = "sp-npos-elections" +version = "2.0.0-alpha.5" dependencies = [ "parity-scale-codec", "serde", - "sp-core", - "sp-phragmen-compact", + "sp-npos-elections-compact", "sp-runtime", "sp-std", ] [[package]] -name = "sp-phragmen-compact" -version = "2.0.0-dev" +name = "sp-npos-elections-compact" +version = "2.0.0-rc3" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1671,7 +1773,7 @@ dependencies = [ [[package]] name = "sp-runtime" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "hash256-std-hasher", "impl-trait-for-tuples", @@ -1691,7 +1793,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "parity-scale-codec", "primitive-types", @@ -1704,7 +1806,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "Inflector", "proc-macro-crate", @@ -1715,7 +1817,7 @@ dependencies = [ [[package]] name = "sp-staking" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "parity-scale-codec", "sp-runtime", @@ -1724,7 +1826,7 @@ dependencies = [ [[package]] name = "sp-state-machine" -version = "0.8.0-alpha.3" +version = "0.8.0-alpha.5" dependencies = [ "hash-db", "log", @@ -1742,11 +1844,11 @@ dependencies = [ [[package]] name = "sp-std" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" [[package]] name = "sp-storage" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "impl-serde 0.2.3", "serde", @@ -1756,7 +1858,7 @@ dependencies = [ [[package]] name = "sp-timestamp" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", @@ -1769,7 +1871,7 @@ dependencies = [ [[package]] name = "sp-trie" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "hash-db", "memory-db", @@ -1782,7 +1884,7 @@ dependencies = [ [[package]] name = "sp-version" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "impl-serde 0.2.3", "parity-scale-codec", @@ -1793,7 +1895,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.5" dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", @@ -1807,6 +1909,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "statrs" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10102ac8d55e35db2b3fafc26f81ba8647da2e15879ab686a67e6d19af2685e8" +dependencies = [ + "rand 0.5.6", +] + [[package]] name = "strum" version = "0.16.0" @@ -1830,9 +1941,9 @@ dependencies = [ [[package]] name = "substrate-bip39" -version = "0.3.1" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be511be555a3633e71739a79e4ddff6a6aaa6579fa6114182a51d72c3eb93c5" +checksum = "c004e8166d6e0aa3a9d5fa673e5b7098ff25f930de1013a21341988151e681bb" dependencies = [ "hmac", "pbkdf2", @@ -1854,9 +1965,9 @@ checksum = "7c65d530b10ccaeac294f349038a597e435b18fb456aadd0840a623f83b9e941" [[package]] name = "syn" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859" +checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03" dependencies = [ "proc-macro2", "quote", @@ -1886,9 +1997,9 @@ dependencies = [ [[package]] name = "tiny-bip39" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6848cd8f566953ce1e8faeba12ee23cbdbb0437754792cd857d44628b5685e3" +checksum = "b0165e045cc2ae1660270ca65e1676dbaab60feb0f91b10f7d0665e9b47e31f2" dependencies = [ "failure", "hmac", @@ -1958,7 +2069,7 @@ dependencies = [ "hashbrown", "log", "rustc-hex", - "smallvec 1.3.0", + "smallvec 1.2.0", ] [[package]] @@ -2003,7 +2114,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" dependencies = [ - "smallvec 1.3.0", + "smallvec 1.2.0", ] [[package]] @@ -2026,9 +2137,9 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasm-bindgen" -version = "0.2.59" +version = "0.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3557c397ab5a8e347d434782bcd31fc1483d927a6826804cec05cc792ee2519d" +checksum = "2cc57ce05287f8376e998cbddfb4c8cb43b84a7ec55cf4551d7c00eef317a47f" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2036,9 +2147,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.59" +version = "0.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0da9c9a19850d3af6df1cb9574970b566d617ecfaf36eb0b706b6f3ef9bd2f8" +checksum = "d967d37bf6c16cca2973ca3af071d0a2523392e4a594548155d89a678f4237cd" dependencies = [ "bumpalo", "lazy_static", @@ -2051,9 +2162,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "457414a91863c0ec00090dba537f88ab955d93ca6555862c29b6d860990b8a8a" +checksum = "7add542ea1ac7fdaa9dc25e031a6af33b7d63376292bd24140c637d00d1c312a" dependencies = [ "cfg-if", "js-sys", @@ -2063,9 +2174,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.59" +version = "0.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f6fde1d36e75a714b5fe0cffbb78978f222ea6baebb726af13c78869fdb4205" +checksum = "8bd151b63e1ea881bb742cd20e1d6127cef28399558f3b5d415289bc41eee3a4" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2073,9 +2184,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.59" +version = "0.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25bda4168030a6412ea8a047e27238cadf56f0e53516e1e83fec0a8b7c786f6d" +checksum = "d68a5b36eef1be7868f668632863292e37739656a80fc4b9acec7b0bd35a4931" dependencies = [ "proc-macro2", "quote", @@ -2086,9 +2197,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.59" +version = "0.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc9f36ad51f25b0219a3d4d13b90eb44cd075dff8b6280cca015775d7acaddd8" +checksum = "daf76fe7d25ac79748a37538b7daeed1c7a6867c92d3245c12c6222e4a20d639" [[package]] name = "wasm-timer" @@ -2131,9 +2242,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "721c6263e2c66fd44501cc5efbfa2b7dfa775d13e4ea38c46299646ed1f9c70a" +checksum = "2d6f51648d8c56c366144378a33290049eafdd784071077f6fe37dae64c1c4cb" dependencies = [ "js-sys", "wasm-bindgen", @@ -2161,12 +2272,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "zeroize" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45af6a010d13e4cf5b54c94ba5a2b2eba5596b9e46bf5875612d332a1f2b3f86" - [[package]] name = "zeroize" version = "1.1.0" diff --git a/frame/staking/fuzzer/Cargo.toml b/frame/staking/fuzzer/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..5cd0ae1180a70e3d28d8bbad2b16d761e5311cbf --- /dev/null +++ b/frame/staking/fuzzer/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "pallet-staking-fuzz" +version = "0.0.0" +authors = ["Automatically generated"] +publish = false +edition = "2018" +license = "Apache-2.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +description = "FRAME pallet staking fuzzing" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +honggfuzz = "0.5" +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +pallet-staking = { version = "2.0.0-rc4", path = "..", features = ["runtime-benchmarks"] } +pallet-staking-reward-curve = { version = "2.0.0-rc4", path = "../reward-curve" } +pallet-session = { version = "2.0.0-rc4", path = "../../session" } +pallet-indices = { version = "2.0.0-rc4", path = "../../indices" } +pallet-balances = { version = "2.0.0-rc4", path = "../../balances" } +pallet-timestamp = { version = "2.0.0-rc4", path = "../../timestamp" } +frame-system = { version = "2.0.0-rc4", path = "../../system" } +frame-support = { version = "2.0.0-rc4", path = "../../support" } +sp-std = { version = "2.0.0-rc4", path = "../../../primitives/std" } +sp-io ={ version = "2.0.0-rc4", path = "../../../primitives/io" } +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } +sp-npos-elections = { version = "2.0.0-rc4", path = "../../../primitives/npos-elections" } +sp-runtime = { version = "2.0.0-rc4", path = "../../../primitives/runtime" } + +[[bin]] +name = "submit_solution" +path = "src/submit_solution.rs" diff --git a/frame/staking/fuzz/fuzz_targets/mock.rs b/frame/staking/fuzzer/src/mock.rs similarity index 73% rename from frame/staking/fuzz/fuzz_targets/mock.rs rename to frame/staking/fuzzer/src/mock.rs index 4bb3437f92368b35b7bfd2ef4f4529214972e6ca..89213ea9786bace7b488a978c35c14224c5f3a4d 100644 --- a/frame/staking/fuzz/fuzz_targets/mock.rs +++ b/frame/staking/fuzzer/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Mock file for staking fuzzing. @@ -24,11 +25,11 @@ type AccountIndex = u32; type BlockNumber = u64; type Balance = u64; -type System = frame_system::Module; -type Balances = pallet_balances::Module; -type Staking = pallet_staking::Module; -type Indices = pallet_indices::Module; -type Session = pallet_session::Module; +pub type System = frame_system::Module; +pub type Balances = pallet_balances::Module; +pub type Staking = pallet_staking::Module; +pub type Indices = pallet_indices::Module; +pub type Session = pallet_session::Module; impl_outer_origin! { pub enum Origin for Test where system = frame_system {} @@ -56,7 +57,12 @@ impl Convert for CurrencyToVoteHandler { pub struct Test; impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = (); type Index = AccountIndex; type BlockNumber = BlockNumber; type Call = Call; @@ -75,6 +81,7 @@ impl frame_system::Trait for Test { type AccountData = pallet_balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (Balances,); + type SystemWeightInfo = (); } parameter_types! { pub const ExistentialDeposit: Balance = 10; @@ -85,12 +92,14 @@ impl pallet_balances::Trait for Test { type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; + type WeightInfo = (); } impl pallet_indices::Trait for Test { type AccountIndex = AccountIndex; type Event = (); type Currency = Balances; type Deposit = (); + type WeightInfo = (); } parameter_types! { pub const MinimumPeriod: u64 = 5; @@ -99,6 +108,7 @@ impl pallet_timestamp::Trait for Test { type Moment = u64; type OnTimestampSet = (); type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); } impl pallet_session::historical::Trait for Test { type FullIdentification = pallet_staking::Exposure; @@ -136,6 +146,7 @@ impl pallet_session::Trait for Test { type ValidatorId = AccountId; type ValidatorIdOf = pallet_staking::StashOf; type DisabledValidatorsThreshold = (); + type WeightInfo = (); } pallet_staking_reward_curve::build! { const I_NPOS: sp_runtime::curve::PiecewiseLinear<'static> = curve!( @@ -150,18 +161,21 @@ pallet_staking_reward_curve::build! { parameter_types! { pub const RewardCurve: &'static sp_runtime::curve::PiecewiseLinear<'static> = &I_NPOS; pub const MaxNominatorRewardedPerValidator: u32 = 64; + pub const MaxIterations: u32 = 20; } pub type Extrinsic = sp_runtime::testing::TestXt; -type SubmitTransaction = frame_system::offchain::TransactionSubmitter< - sp_runtime::testing::UintAuthorityId, - Test, - Extrinsic, ->; + +impl frame_system::offchain::SendTransactionTypes for Test where + Call: From, +{ + type OverarchingCall = Call; + type Extrinsic = Extrinsic; +} impl pallet_staking::Trait for Test { type Currency = Balances; - type Time = pallet_timestamp::Module; + type UnixTime = pallet_timestamp::Module; type CurrencyToVote = CurrencyToVoteHandler; type RewardRemainder = (); type Event = (); @@ -176,7 +190,9 @@ impl pallet_staking::Trait for Test { type NextNewSession = Session; type ElectionLookahead = (); type Call = Call; - type SubmitTransaction = SubmitTransaction; - type KeyType = sp_runtime::testing::UintAuthorityId; + type MaxIterations = MaxIterations; + type MinSolutionScoreBump = (); type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; + type UnsignedPriority = (); + type WeightInfo = (); } diff --git a/frame/staking/fuzzer/src/submit_solution.rs b/frame/staking/fuzzer/src/submit_solution.rs new file mode 100644 index 0000000000000000000000000000000000000000..7293cf23890a5869e70e102e0c613d52c13829c0 --- /dev/null +++ b/frame/staking/fuzzer/src/submit_solution.rs @@ -0,0 +1,182 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Fuzzing for staking pallet. +//! +//! HFUZZ_RUN_ARGS="-n 8" cargo hfuzz run submit_solution + +use honggfuzz::fuzz; + +use mock::Test; +use pallet_staking::testing_utils::*; +use frame_support::{assert_ok, storage::StorageValue, traits::UnfilteredDispatchable}; +use frame_system::RawOrigin; +use sp_runtime::DispatchError; +use sp_core::offchain::{testing::TestOffchainExt, OffchainExt}; +use pallet_staking::{EraElectionStatus, ElectionStatus, Module as Staking, Call as StakingCall}; + +mod mock; + +#[repr(u32)] +#[allow(dead_code)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum Mode { + /// Initial submission. This will be rather cheap. + InitialSubmission, + /// A better submission that will replace the previous ones. This is the most expensive. + StrongerSubmission, + /// A weak submission that will be rejected. This will be rather cheap. + WeakerSubmission, +} + +pub fn new_test_ext(iterations: u32) -> sp_io::TestExternalities { + let mut ext: sp_io::TestExternalities = frame_system::GenesisConfig::default() + .build_storage::() + .map(Into::into) + .expect("Failed to create test externalities."); + + let (offchain, offchain_state) = TestOffchainExt::new(); + + let mut seed = [0u8; 32]; + seed[0..4].copy_from_slice(&iterations.to_le_bytes()); + offchain_state.write().seed = seed; + + ext.register_extension(OffchainExt::new(offchain)); + + ext +} + +fn main() { + let to_range = |x: u32, a: u32, b: u32| { + let collapsed = x % b; + if collapsed >= a { + collapsed + } else { + collapsed + a + } + }; + loop { + fuzz!(|data: (u32, u32, u32, u32, u32)| { + let (mut num_validators, mut num_nominators, mut edge_per_voter, mut to_elect, mode_u32) = data; + // always run with 5 iterations. + let mut ext = new_test_ext(5); + let mode: Mode = unsafe { std::mem::transmute(mode_u32) }; + num_validators = to_range(num_validators, 50, 1000); + num_nominators = to_range(num_nominators, 50, 2000); + edge_per_voter = to_range(edge_per_voter, 1, 16); + to_elect = to_range(to_elect, 20, num_validators); + + let do_reduce = true; + + println!("+++ instance with params {} / {} / {} / {} / {:?}({})", + num_nominators, + num_validators, + edge_per_voter, + to_elect, + mode, + mode_u32, + ); + + ext.execute_with(|| { + // initial setup + init_active_era(); + + assert_ok!(create_validators_with_nominators_for_era::( + num_validators, + num_nominators, + edge_per_voter as usize, + true, + None, + )); + + >::put(ElectionStatus::Open(1)); + assert!(>::create_stakers_snapshot().0); + + let origin = RawOrigin::Signed(create_funded_user::("fuzzer", 0, 100)); + + // stuff to submit + let (winners, compact, score, size) = match mode { + Mode::InitialSubmission => { + /* No need to setup anything */ + get_seq_phragmen_solution::(do_reduce) + }, + Mode::StrongerSubmission => { + let (winners, compact, score, size) = get_weak_solution::(false); + println!("Weak on chain score = {:?}", score); + assert_ok!( + >::submit_election_solution( + origin.clone().into(), + winners, + compact, + score, + current_era::(), + size, + ) + ); + get_seq_phragmen_solution::(do_reduce) + }, + Mode::WeakerSubmission => { + let (winners, compact, score, size) = get_seq_phragmen_solution::(do_reduce); + println!("Strong on chain score = {:?}", score); + assert_ok!( + >::submit_election_solution( + origin.clone().into(), + winners, + compact, + score, + current_era::(), + size, + ) + ); + get_weak_solution::(false) + } + }; + + // must have chosen correct number of winners. + assert_eq!(winners.len() as u32, >::validator_count()); + + // final call and origin + let call = StakingCall::::submit_election_solution( + winners, + compact, + score, + current_era::(), + size, + ); + + // actually submit + match mode { + Mode::WeakerSubmission => { + assert_eq!( + call.dispatch_bypass_filter(origin.clone().into()).unwrap_err().error, + DispatchError::Module { + index: 0, + error: 16, + message: Some("PhragmenWeakSubmission"), + }, + ); + }, + // NOTE: so exhaustive pattern doesn't work here.. maybe some rust issue? + // or due to `#[repr(u32)]`? + Mode::InitialSubmission | Mode::StrongerSubmission => { + assert_ok!(call.dispatch_bypass_filter(origin.into())); + } + }; + }) + }); + } +} diff --git a/frame/staking/reward-curve/Cargo.toml b/frame/staking/reward-curve/Cargo.toml index b3b749e96cd51fa050dfb6233f0c99eadf6ad3fb..3d677c7456d6f51a7012cd97a85ce06df72be13d 100644 --- a/frame/staking/reward-curve/Cargo.toml +++ b/frame/staking/reward-curve/Cargo.toml @@ -1,13 +1,16 @@ [package] name = "pallet-staking-reward-curve" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Reward Curve for FRAME staking pallet" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [lib] proc-macro = true @@ -18,7 +21,4 @@ proc-macro2 = "1.0.6" proc-macro-crate = "0.1.4" [dev-dependencies] -sp-runtime = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime" } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +sp-runtime = { version = "2.0.0-rc4", path = "../../../primitives/runtime" } diff --git a/frame/staking/reward-curve/src/lib.rs b/frame/staking/reward-curve/src/lib.rs index d000afc49b515ea4ea2d20daf1c65b9c5ea4cf1a..9b55b346d5fd11bf59a9c8e4ccd76841384b46f0 100644 --- a/frame/staking/reward-curve/src/lib.rs +++ b/frame/staking/reward-curve/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Proc macro to generate the reward curve functions and tests. @@ -268,10 +269,14 @@ impl INPoS { } } + // calculates x from: + // y = i_0 + (i_ideal * x_ideal - i_0) * 2^((x_ideal - x)/d) + // See web3 docs for the details fn compute_opposite_after_x_ideal(&self, y: u32) -> u32 { if y == self.i_0 { return u32::max_value(); } + // Note: the log term calculated here represents a per_million 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(); diff --git a/frame/staking/reward-curve/src/log.rs b/frame/staking/reward-curve/src/log.rs index e0929a95970139450c0e953f6df7e8849e5ae727..28acd5deed2bbf7c879f30307bf14075752f506d 100644 --- a/frame/staking/reward-curve/src/log.rs +++ b/frame/staking/reward-curve/src/log.rs @@ -1,48 +1,65 @@ use std::convert::TryInto; -/// Return Per-million value. +/// Simple u32 power of 2 function - simply uses a bit shift +macro_rules! pow2 { + ($n:expr) => { + 1_u32 << $n + } +} + +/// Returns the k_th per_million taylor term for a log2 function +fn taylor_term(k: u32, y_num: u128, y_den: u128) -> u32 { + let _2_div_ln_2: u128 = 2_885_390u128; + + if k == 0 { + (_2_div_ln_2 * (y_num).pow(1) / (y_den).pow(1)).try_into().unwrap() + } else { + let mut res = _2_div_ln_2 * (y_num).pow(3) / (y_den).pow(3); + for _ in 1..k { + res = res * (y_num).pow(2) / (y_den).pow(2); + } + res /= 2 * k as u128 + 1; + + res.try_into().unwrap() + } +} + +/// Performs a log2 operation using a rational fraction +/// +/// result = log2(p/q) where p/q is bound to [1, 1_000_000] +/// Where: +/// * q represents the numerator of the rational fraction input +/// * p represents the denominator of the rational fraction input +/// * result represents a per-million output of log2 pub fn log2(p: u32, q: u32) -> u32 { - assert!(p >= q); + assert!(p >= q); // keep p/q bound to [1, inf) 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); + // log2(1) = 0 if p == q { return 0 } + // find the power of 2 where q * 2^n <= p < q * 2^(n+1) let mut n = 0u32; - while !(p >= (1u32 << n)*q) || !(p < (1u32 << (n+1))*q) { + while !(p >= pow2!(n) * q) || !(p < pow2!(n + 1) * q) { n += 1; + assert!(n < 32); // cannot represent 2^32 in u32 } - assert!(p < (1u32 << (n+1)) * q); - - let y_num: u32 = (p - (1u32 << n) * q).try_into().unwrap(); - let y_den: u32 = (p + (1u32 << n) * q).try_into().unwrap(); - - let _2_div_ln_2 = 2_885_390u32; + assert!(p < pow2!(n + 1) * q); - 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 y_num: u32 = (p - pow2!(n) * q).try_into().unwrap(); + let y_den: u32 = (p + pow2!(n) * q).try_into().unwrap(); + // Loop through each Taylor series coefficient until it reaches 10^-6 let mut res = n * 1_000_000u32; let mut k = 0; loop { - let term = taylor_term(k); + let term = taylor_term(k, y_num.into(), y_den.into()); if term == 0 { break } @@ -68,3 +85,43 @@ fn test_log() { } } } + +#[test] +#[should_panic] +fn test_log_p_must_be_greater_than_q() { + let p: u32 = 1_000; + let q: u32 = 1_001; + let _ = log2(p, q); +} + +#[test] +#[should_panic] +fn test_log_p_upper_bound() { + let p: u32 = 1_000_001; + let q: u32 = 1_000_000; + let _ = log2(p, q); +} + +#[test] +#[should_panic] +fn test_log_q_limit() { + let p: u32 = 1_000_000; + let q: u32 = 0; + let _ = log2(p, q); +} + +#[test] +fn test_log_of_one_boundary() { + let p: u32 = 1_000_000; + let q: u32 = 1_000_000; + assert_eq!(log2(p, q), 0); +} + +#[test] +fn test_log_of_largest_input() { + let p: u32 = 1_000_000; + let q: u32 = 1; + let expected = 19_931_568; + let tolerance = 100; + assert!((log2(p, q) as i32 - expected as i32).abs() < tolerance); +} \ No newline at end of file diff --git a/frame/staking/reward-curve/tests/test.rs b/frame/staking/reward-curve/tests/test.rs index 89f8653fe18d937881a2b6f916c2bca26918716c..45ad59e00ad279f9c4db932370183fdeb336ef1c 100644 --- a/frame/staking/reward-curve/tests/test.rs +++ b/frame/staking/reward-curve/tests/test.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test crate for pallet-staking-reward-curve. Allows to test for procedural macro. //! See tests directory. diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index d4edac63d2497846844a64873f3f9e0a5b9e90d9..b2035c22b675c258ecd7bce220f154db00628d54 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -1,112 +1,63 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Staking pallet benchmarking. use super::*; - -use rand_chacha::{rand_core::{RngCore, SeedableRng}, ChaChaRng}; - -use sp_runtime::traits::{Dispatchable, One}; -use sp_io::hashing::blake2_256; - -use frame_system::RawOrigin; -use frame_benchmarking::{benchmarks, account}; - use crate::Module as Staking; -use frame_system::Module as System; +use testing_utils::*; +use sp_runtime::traits::One; +use frame_system::RawOrigin; +pub use frame_benchmarking::{benchmarks, account}; const SEED: u32 = 0; - -fn create_funded_user(string: &'static str, n: u32) -> T::AccountId { - let user = account(string, n, SEED); - let balance = T::Currency::minimum_balance() * 100.into(); - T::Currency::make_free_balance_be(&user, balance); - user -} - -pub fn create_stash_controller(n: u32) -> Result<(T::AccountId, T::AccountId), &'static str> { - let stash = create_funded_user::("stash", n); - let controller = create_funded_user::("controller", n); - let controller_lookup: ::Source = T::Lookup::unlookup(controller.clone()); - let reward_destination = RewardDestination::Staked; - let amount = T::Currency::minimum_balance() * 10.into(); - Staking::::bond(RawOrigin::Signed(stash.clone()).into(), controller_lookup, amount, reward_destination)?; - return Ok((stash, controller)) -} - -fn create_validators(max: u32) -> Result::Source>, &'static str> { - let mut validators: Vec<::Source> = Vec::with_capacity(max as usize); - for i in 0 .. max { - let (stash, controller) = create_stash_controller::(i)?; - let validator_prefs = ValidatorPrefs { - commission: Perbill::from_percent(50), - }; - Staking::::validate(RawOrigin::Signed(controller).into(), validator_prefs)?; - let stash_lookup: ::Source = T::Lookup::unlookup(stash); - validators.push(stash_lookup); - } - Ok(validators) -} - -// This function generates v validators and n nominators who are randomly nominating up to MAX_NOMINATIONS. -pub fn create_validators_with_nominators_for_era(v: u32, n: u32) -> Result<(), &'static str> { - let mut validators: Vec<::Source> = Vec::with_capacity(v as usize); - let mut rng = ChaChaRng::from_seed(SEED.using_encoded(blake2_256)); - - // Create v validators - for i in 0 .. v { - let (v_stash, v_controller) = create_stash_controller::(i)?; - let validator_prefs = ValidatorPrefs { - commission: Perbill::from_percent(50), - }; - Staking::::validate(RawOrigin::Signed(v_controller.clone()).into(), validator_prefs)?; - let stash_lookup: ::Source = T::Lookup::unlookup(v_stash.clone()); - validators.push(stash_lookup.clone()); - } - - // Create n nominators - for j in 0 .. n { - let (_n_stash, n_controller) = create_stash_controller::(u32::max_value() - j)?; - - // Have them randomly validate - let mut available_validators = validators.clone(); - let mut selected_validators: Vec<::Source> = Vec::with_capacity(MAX_NOMINATIONS); - for _ in 0 .. v.min(MAX_NOMINATIONS as u32) { - let selected = rng.next_u32() as usize % available_validators.len(); - let validator = available_validators.remove(selected); - selected_validators.push(validator); - } - Staking::::nominate(RawOrigin::Signed(n_controller.clone()).into(), selected_validators)?; +const MAX_SPANS: u32 = 100; +const MAX_VALIDATORS: u32 = 1000; +const MAX_SLASHES: u32 = 1000; + +// Add slashing spans to a user account. Not relevant for actual use, only to benchmark +// read and write operations. +fn add_slashing_spans(who: &T::AccountId, spans: u32) { + if spans == 0 { return } + + // For the first slashing span, we initialize + let mut slashing_spans = crate::slashing::SlashingSpans::new(0); + SpanSlash::::insert((who, 0), crate::slashing::SpanRecord::default()); + + for i in 1 .. spans { + assert!(slashing_spans.end_span(i)); + SpanSlash::::insert((who, i), crate::slashing::SpanRecord::default()); } - - ValidatorCount::put(v); - - Ok(()) + SlashingSpans::::insert(who, slashing_spans); } -// This function generates one validator being nominated by n nominators. -// It starts an era and creates pending payouts. -pub fn create_validator_with_nominators(n: u32, upper_bound: u32) -> Result { +// This function generates one validator being nominated by n nominators, and returns the validator +// stash account. It also starts an era and creates pending payouts. +pub fn create_validator_with_nominators( + n: u32, + upper_bound: u32, + dead: bool, +) -> Result { let mut points_total = 0; let mut points_individual = Vec::new(); MinimumValidatorCount::put(0); - let (v_stash, v_controller) = create_stash_controller::(0)?; + let (v_stash, v_controller) = create_stash_controller::(0, 100)?; let validator_prefs = ValidatorPrefs { commission: Perbill::from_percent(50), }; @@ -114,11 +65,15 @@ pub fn create_validator_with_nominators(n: u32, upper_bound: u32) -> R let stash_lookup: ::Source = T::Lookup::unlookup(v_stash.clone()); points_total += 10; - points_individual.push((v_stash, 10)); + points_individual.push((v_stash.clone(), 10)); // Give the validator n nominators, but keep total users in the system the same. for i in 0 .. upper_bound { - let (_n_stash, n_controller) = create_stash_controller::(u32::max_value() - i)?; + let (_n_stash, n_controller) = if !dead { + create_stash_controller::(u32::max_value() - i, 100)? + } else { + create_stash_and_dead_controller::(u32::max_value() - i, 100)? + }; if i < n { Staking::::nominate(RawOrigin::Signed(n_controller.clone()).into(), vec![stash_lookup.clone()])?; } @@ -144,7 +99,7 @@ pub fn create_validator_with_nominators(n: u32, upper_bound: u32) -> R let total_payout = T::Currency::minimum_balance() * 1000.into(); >::insert(current_era, total_payout); - Ok(v_controller) + Ok(v_stash) } benchmarks! { @@ -155,112 +110,204 @@ benchmarks! { bond { let u in ...; - let stash = create_funded_user::("stash",u); - let controller = create_funded_user::("controller", u); - let controller_lookup: ::Source = T::Lookup::unlookup(controller); + let stash = create_funded_user::("stash", u, 100); + let controller = create_funded_user::("controller", u, 100); + let controller_lookup: ::Source = T::Lookup::unlookup(controller.clone()); let reward_destination = RewardDestination::Staked; let amount = T::Currency::minimum_balance() * 10.into(); - }: _(RawOrigin::Signed(stash), controller_lookup, amount, reward_destination) + }: _(RawOrigin::Signed(stash.clone()), controller_lookup, amount, reward_destination) + verify { + assert!(Bonded::::contains_key(stash)); + assert!(Ledger::::contains_key(controller)); + } bond_extra { let u in ...; - let (stash, _) = create_stash_controller::(u)?; + let (stash, controller) = create_stash_controller::(u, 100)?; let max_additional = T::Currency::minimum_balance() * 10.into(); + let ledger = Ledger::::get(&controller).ok_or("ledger not created before")?; + let original_bonded: BalanceOf = ledger.active; }: _(RawOrigin::Signed(stash), max_additional) + verify { + let ledger = Ledger::::get(&controller).ok_or("ledger not created after")?; + let new_bonded: BalanceOf = ledger.active; + assert!(original_bonded < new_bonded); + } unbond { let u in ...; - let (_, controller) = create_stash_controller::(u)?; + let (_, controller) = create_stash_controller::(u, 100)?; let amount = T::Currency::minimum_balance() * 10.into(); - }: _(RawOrigin::Signed(controller), amount) + let ledger = Ledger::::get(&controller).ok_or("ledger not created before")?; + let original_bonded: BalanceOf = ledger.active; + }: _(RawOrigin::Signed(controller.clone()), amount) + verify { + let ledger = Ledger::::get(&controller).ok_or("ledger not created after")?; + let new_bonded: BalanceOf = ledger.active; + assert!(original_bonded > new_bonded); + } + + // Withdraw only updates the ledger + withdraw_unbonded_update { + // Slashing Spans + let s in 0 .. MAX_SPANS; + let (stash, controller) = create_stash_controller::(0, 100)?; + add_slashing_spans::(&stash, s); + let amount = T::Currency::minimum_balance() * 5.into(); // Half of total + Staking::::unbond(RawOrigin::Signed(controller.clone()).into(), amount)?; + CurrentEra::put(EraIndex::max_value()); + let ledger = Ledger::::get(&controller).ok_or("ledger not created before")?; + let original_total: BalanceOf = ledger.total; + }: withdraw_unbonded(RawOrigin::Signed(controller.clone()), s) + verify { + let ledger = Ledger::::get(&controller).ok_or("ledger not created after")?; + let new_total: BalanceOf = ledger.total; + assert!(original_total > new_total); + } // Worst case scenario, everything is removed after the bonding duration - withdraw_unbonded { - let u in ...; - let (stash, controller) = create_stash_controller::(u)?; + withdraw_unbonded_kill { + // Slashing Spans + let s in 0 .. MAX_SPANS; + let (stash, controller) = create_stash_controller::(0, 100)?; + add_slashing_spans::(&stash, s); let amount = T::Currency::minimum_balance() * 10.into(); Staking::::unbond(RawOrigin::Signed(controller.clone()).into(), amount)?; - let current_block = System::::block_number(); - // let unbond_block = current_block + T::BondingDuration::get().into() + 10.into(); - // System::::set_block_number(unbond_block); - }: _(RawOrigin::Signed(controller)) + CurrentEra::put(EraIndex::max_value()); + let ledger = Ledger::::get(&controller).ok_or("ledger not created before")?; + let original_total: BalanceOf = ledger.total; + }: withdraw_unbonded(RawOrigin::Signed(controller.clone()), s) + verify { + assert!(!Ledger::::contains_key(controller)); + } validate { let u in ...; - let (_, controller) = create_stash_controller::(u)?; + let (stash, controller) = create_stash_controller::(u, 100)?; let prefs = ValidatorPrefs::default(); }: _(RawOrigin::Signed(controller), prefs) + verify { + assert!(Validators::::contains_key(stash)); + } // Worst case scenario, MAX_NOMINATIONS nominate { let n in 1 .. MAX_NOMINATIONS as u32; - let (_, controller) = create_stash_controller::(n + 1)?; - let validators = create_validators::(n)?; + let (stash, controller) = create_stash_controller::(n + 1, 100)?; + let validators = create_validators::(n, 100)?; }: _(RawOrigin::Signed(controller), validators) + verify { + assert!(Nominators::::contains_key(stash)); + } chill { let u in ...; - let (_, controller) = create_stash_controller::(u)?; + let (_, controller) = create_stash_controller::(u, 100)?; }: _(RawOrigin::Signed(controller)) set_payee { let u in ...; - let (_, controller) = create_stash_controller::(u)?; + let (stash, controller) = create_stash_controller::(u, 100)?; + assert_eq!(Payee::::get(&stash), RewardDestination::Staked); }: _(RawOrigin::Signed(controller), RewardDestination::Controller) + verify { + assert_eq!(Payee::::get(&stash), RewardDestination::Controller); + } set_controller { let u in ...; - let (stash, _) = create_stash_controller::(u)?; - let new_controller = create_funded_user::("new_controller", u); - let new_controller_lookup = T::Lookup::unlookup(new_controller); + let (stash, _) = create_stash_controller::(u, 100)?; + let new_controller = create_funded_user::("new_controller", u, 100); + let new_controller_lookup = T::Lookup::unlookup(new_controller.clone()); }: _(RawOrigin::Signed(stash), new_controller_lookup) + verify { + assert!(Ledger::::contains_key(&new_controller)); + } set_validator_count { - let c in 0 .. 1000; + let c in 0 .. MAX_VALIDATORS; }: _(RawOrigin::Root, c) + verify { + assert_eq!(ValidatorCount::get(), c); + } - force_no_eras { let i in 1 .. 1; }: _(RawOrigin::Root) + force_no_eras { let i in 0 .. 1; }: _(RawOrigin::Root) + verify { assert_eq!(ForceEra::get(), Forcing::ForceNone); } - force_new_era {let i in 1 .. 1; }: _(RawOrigin::Root) + force_new_era {let i in 0 .. 1; }: _(RawOrigin::Root) + verify { assert_eq!(ForceEra::get(), Forcing::ForceNew); } - force_new_era_always { let i in 1 .. 1; }: _(RawOrigin::Root) + force_new_era_always { let i in 0 .. 1; }: _(RawOrigin::Root) + verify { assert_eq!(ForceEra::get(), Forcing::ForceAlways); } // Worst case scenario, the list of invulnerables is very long. set_invulnerables { - let v in 0 .. 1000; + let v in 0 .. MAX_VALIDATORS; let mut invulnerables = Vec::new(); for i in 0 .. v { invulnerables.push(account("invulnerable", i, SEED)); } }: _(RawOrigin::Root, invulnerables) + verify { + assert_eq!(Invulnerables::::get().len(), v as usize); + } force_unstake { - let u in ...; - let (stash, _) = create_stash_controller::(u)?; - }: _(RawOrigin::Root, stash) + // Slashing Spans + let s in 0 .. MAX_SPANS; + let (stash, controller) = create_stash_controller::(0, 100)?; + add_slashing_spans::(&stash, s); + }: _(RawOrigin::Root, stash, s) + verify { + assert!(!Ledger::::contains_key(&controller)); + } cancel_deferred_slash { - let s in 1 .. 1000; + let s in 1 .. MAX_SLASHES; let mut unapplied_slashes = Vec::new(); let era = EraIndex::one(); - for _ in 0 .. 1000 { + for _ in 0 .. MAX_SLASHES { unapplied_slashes.push(UnappliedSlash::>::default()); } UnappliedSlashes::::insert(era, &unapplied_slashes); let slash_indices: Vec = (0 .. s).collect(); }: _(RawOrigin::Root, era, slash_indices) + verify { + assert_eq!(UnappliedSlashes::::get(&era).len(), (MAX_SLASHES - s) as usize); + } payout_stakers { - let n in 1 .. MAX_NOMINATIONS as u32; - let validator = create_validator_with_nominators::(n, MAX_NOMINATIONS as u32)?; + let n in 1 .. T::MaxNominatorRewardedPerValidator::get() as u32; + let validator = create_validator_with_nominators::(n, T::MaxNominatorRewardedPerValidator::get() as u32, true)?; + + let current_era = CurrentEra::get().unwrap(); + let caller = account("caller", 0, SEED); + let balance_before = T::Currency::free_balance(&validator); + }: _(RawOrigin::Signed(caller), validator.clone(), current_era) + verify { + // Validator has been paid! + let balance_after = T::Currency::free_balance(&validator); + assert!(balance_before < balance_after); + } + + payout_stakers_alive_controller { + let n in 1 .. T::MaxNominatorRewardedPerValidator::get() as u32; + let validator = create_validator_with_nominators::(n, T::MaxNominatorRewardedPerValidator::get() as u32, false)?; + let current_era = CurrentEra::get().unwrap(); - let caller = account("caller", n, SEED); - }: _(RawOrigin::Signed(caller), validator, current_era) + let caller = account("caller", 0, SEED); + let balance_before = T::Currency::free_balance(&validator); + }: payout_stakers(RawOrigin::Signed(caller), validator.clone(), current_era) + verify { + // Validator has been paid! + let balance_after = T::Currency::free_balance(&validator); + assert!(balance_before < balance_after); + } rebond { - let l in 1 .. 1000; - let (_, controller) = create_stash_controller::(u)?; + let l in 1 .. MAX_UNLOCKING_CHUNKS as u32; + let (_, controller) = create_stash_controller::(u, 100)?; let mut staking_ledger = Ledger::::get(controller.clone()).unwrap(); let unlock_chunk = UnlockChunk::> { value: 1.into(), @@ -269,8 +316,14 @@ benchmarks! { for _ in 0 .. l { staking_ledger.unlocking.push(unlock_chunk.clone()) } - Ledger::::insert(controller.clone(), staking_ledger); - }: _(RawOrigin::Signed(controller), (l + 100).into()) + Ledger::::insert(controller.clone(), staking_ledger.clone()); + let original_bonded: BalanceOf = staking_ledger.active; + }: _(RawOrigin::Signed(controller.clone()), (l + 100).into()) + verify { + let ledger = Ledger::::get(&controller).ok_or("ledger not created after")?; + let new_bonded: BalanceOf = ledger.active; + assert!(original_bonded < new_bonded); + } set_history_depth { let e in 1 .. 100; @@ -285,19 +338,26 @@ benchmarks! { >::insert(i, BalanceOf::::one()); ErasStartSessionIndex::insert(i, i); } - }: _(RawOrigin::Root, EraIndex::zero()) + }: _(RawOrigin::Root, EraIndex::zero(), u32::max_value()) + verify { + assert_eq!(HistoryDepth::get(), 0); + } reap_stash { - let u in 1 .. 1000; - let (stash, controller) = create_stash_controller::(u)?; + let s in 1 .. MAX_SPANS; + let (stash, controller) = create_stash_controller::(0, 100)?; + add_slashing_spans::(&stash, s); T::Currency::make_free_balance_be(&stash, 0.into()); - }: _(RawOrigin::Signed(controller), stash) + }: _(RawOrigin::Signed(controller), stash.clone(), s) + verify { + assert!(!Bonded::::contains_key(&stash)); + } new_era { let v in 1 .. 10; let n in 1 .. 100; MinimumValidatorCount::put(0); - create_validators_with_nominators_for_era::(v, n)?; + create_validators_with_nominators_for_era::(v, n, MAX_NOMINATIONS, false, None)?; let session_index = SessionIndex::one(); }: { let validators = Staking::::new_era(session_index).ok_or("`new_era` failed")?; @@ -305,8 +365,8 @@ benchmarks! { } do_slash { - let l in 1 .. 1000; - let (stash, controller) = create_stash_controller::(0)?; + let l in 1 .. MAX_UNLOCKING_CHUNKS as u32; + let (stash, controller) = create_stash_controller::(0, 100)?; let mut staking_ledger = Ledger::::get(controller.clone()).unwrap(); let unlock_chunk = UnlockChunk::> { value: 1.into(), @@ -317,6 +377,7 @@ benchmarks! { } Ledger::::insert(controller.clone(), staking_ledger.clone()); let slash_amount = T::Currency::minimum_balance() * 10.into(); + let balance_before = T::Currency::free_balance(&stash); }: { crate::slashing::do_slash::( &stash, @@ -324,13 +385,16 @@ benchmarks! { &mut BalanceOf::::zero(), &mut NegativeImbalanceOf::::zero() ); + } verify { + let balance_after = T::Currency::free_balance(&stash); + assert!(balance_before > balance_after); } payout_all { let v in 1 .. 10; let n in 1 .. 100; MinimumValidatorCount::put(0); - create_validators_with_nominators_for_era::(v, n)?; + create_validators_with_nominators_for_era::(v, n, MAX_NOMINATIONS, false, None)?; // Start a new Era let new_validators = Staking::::new_era(SessionIndex::one()).unwrap(); assert!(new_validators.len() == v as usize); @@ -338,12 +402,12 @@ benchmarks! { let current_era = CurrentEra::get().unwrap(); let mut points_total = 0; let mut points_individual = Vec::new(); - let mut payout_calls = Vec::new(); + let mut payout_calls_arg = Vec::new(); for validator in new_validators.iter() { points_total += 10; points_individual.push((validator.clone(), 10)); - payout_calls.push(Call::::payout_stakers(validator.clone(), current_era)) + payout_calls_arg.push((validator.clone(), current_era)); } // Give Era Points @@ -360,31 +424,218 @@ benchmarks! { let caller: T::AccountId = account("caller", 0, SEED); }: { - for call in payout_calls { - call.dispatch(RawOrigin::Signed(caller.clone()).into())?; + for arg in payout_calls_arg { + >::payout_stakers(RawOrigin::Signed(caller.clone()).into(), arg.0, arg.1)?; + } + } + + // This benchmark create `v` validators intent, `n` nominators intent, each nominator nominate + // MAX_NOMINATIONS in the set of the first `w` validators. + // It builds a solution with `w` winners composed of nominated validators randomly nominated, + // `a` assignment with MAX_NOMINATIONS. + submit_solution_initial { + // number of validator intent + let v in 1000 .. 2000; + // number of nominator intent + let n in 1000 .. 2000; + // number of assignments. Basically, number of active nominators. + let a in 200 .. 500; + // number of winners, also ValidatorCount + let w in 16 .. 100; + + ensure!(w as usize >= MAX_NOMINATIONS, "doesn't support lower value"); + + let winners = create_validators_with_nominators_for_era::( + v, + n, + MAX_NOMINATIONS, + false, + Some(w), + )?; + + // needed for the solution to be generates. + assert!(>::create_stakers_snapshot().0); + + // set number of winners + ValidatorCount::put(w); + + // create a assignments in total for the w winners. + let (winners, assignments) = create_assignments_for_offchain::(a, winners)?; + + let ( + winners, + compact, + score, + size + ) = offchain_election::prepare_submission::(assignments, winners, false).unwrap(); + + // needed for the solution to be accepted + >::put(ElectionStatus::Open(T::BlockNumber::from(1u32))); + + let era = >::current_era().unwrap_or(0); + let caller: T::AccountId = account("caller", n, SEED); + }: { + let result = >::submit_election_solution( + RawOrigin::Signed(caller.clone()).into(), + winners, + compact, + score.clone(), + era, + size, + ); + assert!(result.is_ok()); + } + verify { + // new solution has been accepted. + assert_eq!(>::queued_score().unwrap(), score); + } + + // same as submit_solution_initial but we place a very weak solution on chian first. + submit_solution_better { + // number of validator intent + let v in 1000 .. 2000; + // number of nominator intent + let n in 1000 .. 2000; + // number of assignments. Basically, number of active nominators. + let a in 200 .. 500; + // number of winners, also ValidatorCount + let w in 16 .. 100; + + ensure!(w as usize >= MAX_NOMINATIONS, "doesn't support lower value"); + + let winners = create_validators_with_nominators_for_era::( + v, + n, + MAX_NOMINATIONS, + false, + Some(w), + )?; + + // needed for the solution to be generates. + assert!(>::create_stakers_snapshot().0); + + // set number of winners + ValidatorCount::put(w); + + // create a assignments in total for the w winners. + let (winners, assignments) = create_assignments_for_offchain::(a, winners)?; + + let single_winner = winners[0].0.clone(); + + let ( + winners, + compact, + score, + size + ) = offchain_election::prepare_submission::(assignments, winners, false).unwrap(); + + // needed for the solution to be accepted + >::put(ElectionStatus::Open(T::BlockNumber::from(1u32))); + + let era = >::current_era().unwrap_or(0); + let caller: T::AccountId = account("caller", n, SEED); + + // submit a very bad solution on-chain + { + // this is needed to fool the chain to accept this solution. + ValidatorCount::put(1); + let (winners, compact, score, size) = get_single_winner_solution::(single_winner)?; + assert!( + >::submit_election_solution( + RawOrigin::Signed(caller.clone()).into(), + winners, + compact, + score.clone(), + era, + size, + ).is_ok()); + + // new solution has been accepted. + assert_eq!(>::queued_score().unwrap(), score); + ValidatorCount::put(w); + } + }: { + let result = >::submit_election_solution( + RawOrigin::Signed(caller.clone()).into(), + winners, + compact, + score.clone(), + era, + size, + ); + assert!(result.is_ok()); + } + verify { + // new solution has been accepted. + assert_eq!(>::queued_score().unwrap(), score); + } + + // This will be early rejected based on the score. + submit_solution_weaker { + // number of validator intent + let v in 1000 .. 2000; + // number of nominator intent + let n in 1000 .. 2000; + + MinimumValidatorCount::put(0); + create_validators_with_nominators_for_era::(v, n, MAX_NOMINATIONS, false, None)?; + + // needed for the solution to be generates. + assert!(>::create_stakers_snapshot().0); + + // needed for the solution to be accepted + >::put(ElectionStatus::Open(T::BlockNumber::from(1u32))); + let caller: T::AccountId = account("caller", n, SEED); + let era = >::current_era().unwrap_or(0); + + // submit a seq-phragmen with all the good stuff on chain. + { + let (winners, compact, score, size) = get_seq_phragmen_solution::(true); + assert!( + >::submit_election_solution( + RawOrigin::Signed(caller.clone()).into(), + winners, + compact, + score.clone(), + era, + size, + ).is_ok() + ); + + // new solution has been accepted. + assert_eq!(>::queued_score().unwrap(), score); } + + // prepare a bad solution. This will be very early rejected. + let (winners, compact, score, size) = get_weak_solution::(true); + }: { + assert!( + >::submit_election_solution( + RawOrigin::Signed(caller.clone()).into(), + winners, + compact, + score.clone(), + era, + size, + ).is_err() + ); } } #[cfg(test)] mod tests { - use crate::*; - use crate::mock::*; + use super::*; + use crate::mock::{ExtBuilder, Test, Balances, Staking, Origin}; use frame_support::assert_ok; - use crate::benchmarking::{ - create_validators_with_nominators_for_era, - create_validator_with_nominators, - SelectedBenchmark, - }; - #[test] fn create_validators_with_nominators_for_era_works() { ExtBuilder::default().has_stakers(false).build().execute_with(|| { let v = 10; let n = 100; - create_validators_with_nominators_for_era::(v,n).unwrap(); + create_validators_with_nominators_for_era::(v, n, MAX_NOMINATIONS, false, None) + .unwrap(); let count_validators = Validators::::iter().count(); let count_nominators = Nominators::::iter().count(); @@ -399,24 +650,52 @@ mod tests { ExtBuilder::default().has_stakers(false).build().execute_with(|| { let n = 10; - let validator = create_validator_with_nominators::( + let validator_stash = create_validator_with_nominators::( n, - MAX_NOMINATIONS as u32, + ::MaxNominatorRewardedPerValidator::get() as u32, + false, ).unwrap(); let current_era = CurrentEra::get().unwrap(); - let controller = validator; - let ledger = Staking::ledger(&controller).unwrap(); - let stash = ledger.stash; - let original_free_balance = Balances::free_balance(&stash); - assert_ok!(Staking::payout_stakers(Origin::signed(1337), stash, current_era)); - let new_free_balance = Balances::free_balance(&stash); + let original_free_balance = Balances::free_balance(&validator_stash); + assert_ok!(Staking::payout_stakers(Origin::signed(1337), validator_stash, current_era)); + let new_free_balance = Balances::free_balance(&validator_stash); assert!(original_free_balance < new_free_balance); }); } + #[test] + fn add_slashing_spans_works() { + ExtBuilder::default().has_stakers(false).build().execute_with(|| { + let n = 10; + + let validator_stash = create_validator_with_nominators::( + n, + ::MaxNominatorRewardedPerValidator::get() as u32, + false, + ).unwrap(); + + // Add 20 slashing spans + let num_of_slashing_spans = 20; + add_slashing_spans::(&validator_stash, num_of_slashing_spans); + + let slashing_spans = SlashingSpans::::get(&validator_stash).unwrap(); + assert_eq!(slashing_spans.iter().count(), num_of_slashing_spans as usize); + for i in 0 .. num_of_slashing_spans { + assert!(SpanSlash::::contains_key((&validator_stash, i))); + } + + // Test everything is cleaned up + assert_ok!(Staking::kill_stash(&validator_stash, num_of_slashing_spans)); + assert!(SlashingSpans::::get(&validator_stash).is_none()); + for i in 0 .. num_of_slashing_spans { + assert!(!SpanSlash::::contains_key((&validator_stash, i))); + } + }); + } + #[test] fn test_payout_all() { ExtBuilder::default().has_stakers(false).build().execute_with(|| { @@ -434,4 +713,47 @@ mod tests { assert_ok!(closure_to_benchmark()); }); } + + #[test] + fn test_benchmarks() { + ExtBuilder::default().has_stakers(false).build().execute_with(|| { + assert_ok!(test_benchmark_bond::()); + assert_ok!(test_benchmark_bond_extra::()); + assert_ok!(test_benchmark_unbond::()); + assert_ok!(test_benchmark_withdraw_unbonded_update::()); + assert_ok!(test_benchmark_withdraw_unbonded_kill::()); + assert_ok!(test_benchmark_validate::()); + assert_ok!(test_benchmark_nominate::()); + assert_ok!(test_benchmark_chill::()); + assert_ok!(test_benchmark_set_payee::()); + assert_ok!(test_benchmark_set_controller::()); + assert_ok!(test_benchmark_set_validator_count::()); + assert_ok!(test_benchmark_force_no_eras::()); + assert_ok!(test_benchmark_force_new_era::()); + assert_ok!(test_benchmark_force_new_era_always::()); + assert_ok!(test_benchmark_set_invulnerables::()); + assert_ok!(test_benchmark_force_unstake::()); + assert_ok!(test_benchmark_cancel_deferred_slash::()); + assert_ok!(test_benchmark_payout_stakers::()); + assert_ok!(test_benchmark_payout_stakers_alive_controller::()); + assert_ok!(test_benchmark_rebond::()); + assert_ok!(test_benchmark_set_history_depth::()); + assert_ok!(test_benchmark_reap_stash::()); + assert_ok!(test_benchmark_new_era::()); + assert_ok!(test_benchmark_do_slash::()); + assert_ok!(test_benchmark_payout_all::()); + // only run one of them to same time on the CI. ignore the other two. + assert_ok!(test_benchmark_submit_solution_initial::()); + }); + } + + #[test] + #[ignore] + fn test_benchmarks_offchain() { + ExtBuilder::default().has_stakers(false).build().execute_with(|| { + assert_ok!(test_benchmark_submit_solution_better::()); + assert_ok!(test_benchmark_submit_solution_weaker::()); + }); + } + } diff --git a/frame/staking/src/inflation.rs b/frame/staking/src/inflation.rs index d20741d9bc44d656134bfe9297268f41ea3b52b8..2161fe20af8299a5d163f7b17f5ae1a0e7e059d1 100644 --- a/frame/staking/src/inflation.rs +++ b/frame/staking/src/inflation.rs @@ -1,30 +1,32 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! This module expose one function `P_NPoS` (Payout NPoS) or `compute_total_payout` which returns //! 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. -use sp_runtime::{Perbill, traits::AtLeast32Bit, curve::PiecewiseLinear}; +use sp_runtime::{Perbill, traits::AtLeast32BitUnsigned, curve::PiecewiseLinear}; -/// The total payout to all validators (and their nominators) per era. +/// The total payout to all validators (and their nominators) per era and maximum payout. /// /// Defined as such: -/// `payout = yearly_inflation(npos_token_staked / total_tokens) * total_tokens / era_per_year` +/// `staker-payout = yearly_inflation(npos_token_staked / total_tokens) * total_tokens / era_per_year` +/// `maximum-payout = max_yearly_inflation * total_tokens / era_per_year` /// /// `era_duration` is expressed in millisecond. pub fn compute_total_payout( @@ -32,7 +34,7 @@ pub fn compute_total_payout( npos_token_staked: N, total_tokens: N, era_duration: u64 -) -> (N, N) where N: AtLeast32Bit + Clone { +) -> (N, N) where N: AtLeast32BitUnsigned + Clone { // Milliseconds per year for the Julian year (365.25 days). const MILLISECONDS_PER_YEAR: u64 = 1000 * 3600 * 24 * 36525 / 100; diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index b566d616a80ee9c35a702668a6edfdf6d48d1f24..924937bf36009a866f38960559b4e286462968b1 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Staking Module //! @@ -24,25 +25,25 @@ //! //! ## Overview //! -//! The Staking module is the means by which a set of network maintainers (known as _authorities_ -//! in some contexts and _validators_ in others) are chosen based upon those who voluntarily place -//! funds under deposit. Under deposit, those funds are rewarded under normal operation but are -//! held at pain of _slash_ (expropriation) should the staked maintainer be found not to be -//! discharging its duties properly. +//! The Staking module is the means by which a set of network maintainers (known as _authorities_ in +//! some contexts and _validators_ in others) are chosen based upon those who voluntarily place +//! funds under deposit. Under deposit, those funds are rewarded under normal operation but are held +//! at pain of _slash_ (expropriation) should the staked maintainer be found not to be discharging +//! its duties properly. //! //! ### Terminology //! //! //! - Staking: The process of locking up funds for some time, placing them at risk of slashing -//! (loss) in order to become a rewarded maintainer of the network. +//! (loss) in order to become a rewarded maintainer of the network. //! - Validating: The process of running a node to actively maintain the network, either by -//! producing blocks or guaranteeing finality of the chain. +//! producing blocks or guaranteeing finality of the chain. //! - Nominating: The process of placing staked funds behind one or more validators in order to -//! share in any reward, and punishment, they take. +//! share in any reward, and punishment, they take. //! - Stash account: The account holding an owner's funds used for staking. //! - Controller account: The account that controls an owner's funds for staking. //! - Era: A (whole) number of sessions, which is the period that the validator set (and each -//! validator's active nominator set) is recalculated and where rewards are paid out. +//! validator's active nominator set) is recalculated and where rewards are paid out. //! - Slash: The punishment of a staker by reducing its funds. //! //! ### Goals @@ -105,10 +106,10 @@ //! valid behavior_ while _punishing any misbehavior or lack of availability_. //! //! Rewards must be claimed for each era before it gets too old by `$HISTORY_DEPTH` using the -//! `payout_stakers` call. Any account can call `payout_stakers`, which pays the reward to -//! the validator as well as its nominators. -//! Only the [`T::MaxNominatorRewardedPerValidator`] biggest stakers can claim their reward. This -//! is to limit the i/o cost to mutate storage for each nominator's account. +//! `payout_stakers` call. Any account can call `payout_stakers`, which pays the reward to the +//! validator as well as its nominators. Only the [`Trait::MaxNominatorRewardedPerValidator`] +//! biggest stakers can claim their reward. This is to limit the i/o cost to mutate storage for each +//! nominator's account. //! //! Slashing can occur at any point in time, once misbehavior is reported. Once slashing is //! determined, a value is deducted from the balance of the validator and all the nominators who @@ -117,8 +118,8 @@ //! Slashing logic is further described in the documentation of the `slashing` module. //! //! Similar to slashing, rewards are also shared among a validator and its associated nominators. -//! Yet, the reward funds are not always transferred to the stash account and can be configured. -//! See [Reward Calculation](#reward-calculation) for more details. +//! Yet, the reward funds are not always transferred to the stash account and can be configured. See +//! [Reward Calculation](#reward-calculation) for more details. //! //! #### Chilling //! @@ -150,27 +151,43 @@ //! //! ``` //! use frame_support::{decl_module, dispatch}; -//! use frame_system::{self as system, ensure_signed}; +//! use frame_system::ensure_signed; //! use pallet_staking::{self as staking}; //! //! pub trait Trait: staking::Trait {} //! //! decl_module! { -//! pub struct Module for enum Call where origin: T::Origin { -//! /// Reward a validator. -//! #[weight = frame_support::weights::SimpleDispatchInfo::default()] -//! pub fn reward_myself(origin) -> dispatch::DispatchResult { -//! let reported = ensure_signed(origin)?; -//! >::reward_by_ids(vec![(reported, 10)]); -//! Ok(()) -//! } -//! } +//! pub struct Module for enum Call where origin: T::Origin { +//! /// Reward a validator. +//! #[weight = 0] +//! pub fn reward_myself(origin) -> dispatch::DispatchResult { +//! let reported = ensure_signed(origin)?; +//! >::reward_by_ids(vec![(reported, 10)]); +//! Ok(()) +//! } +//! } //! } //! # fn main() { } //! ``` //! //! ## Implementation Details //! +//! ### Era payout +//! +//! The era payout is computed using yearly inflation curve defined at +//! [`T::RewardCurve`](./trait.Trait.html#associatedtype.RewardCurve) as such: +//! +//! ```nocompile +//! staker_payout = yearly_inflation(npos_token_staked / total_tokens) * total_tokens / era_per_year +//! ``` +//! This payout is used to reward stakers as defined in next section +//! +//! ```nocompile +//! remaining_payout = max_yearly_inflation * total_tokens / era_per_year - staker_payout +//! ``` +//! The remaining reward is send to the configurable end-point +//! [`T::RewardRemainder`](./trait.Trait.html#associatedtype.RewardRemainder). +//! //! ### Reward Calculation //! //! Validators and nominators are rewarded at the end of each era. The total reward of an era is @@ -191,8 +208,8 @@ //! The validator and its nominator split their reward as following: //! //! The validator can declare an amount, named -//! [`commission`](./struct.ValidatorPrefs.html#structfield.commission), that does not -//! get shared with the nominators at each reward payout through its +//! [`commission`](./struct.ValidatorPrefs.html#structfield.commission), that does not get shared +//! with the nominators at each reward payout through its //! [`ValidatorPrefs`](./struct.ValidatorPrefs.html). This value gets deducted from the total reward //! that is paid to the validator and its nominators. The remaining portion is split among the //! validator and all of the nominators that nominated the validator, proportional to the value @@ -201,8 +218,8 @@ //! [`others`](./struct.Exposure.html#structfield.others) by //! [`total`](./struct.Exposure.html#structfield.total) in [`Exposure`](./struct.Exposure.html)). //! -//! All entities who receive a reward have the option to choose their reward destination -//! through the [`Payee`](./struct.Payee.html) storage item (see +//! All entities who receive a reward have the option to choose their reward destination through the +//! [`Payee`](./struct.Payee.html) storage item (see //! [`set_payee`](enum.Call.html#variant.set_payee)), to be one of the following: //! //! - Controller account, (obviously) not increasing the staked value. @@ -227,9 +244,8 @@ //! //! ### Election Algorithm //! -//! The current election algorithm is implemented based on Phragmén. -//! The reference implementation can be found -//! [here](https://github.com/w3f/consensus/tree/master/NPoS). +//! The current election algorithm is implemented based on Phragmén. The reference implementation +//! can be found [here](https://github.com/w3f/consensus/tree/master/NPoS). //! //! The election algorithm, aside from electing the validators with the most stake value and votes, //! tries to divide the nominator votes among candidates in an equal manner. To further assure this, @@ -239,8 +255,8 @@ //! //! ## GenesisConfig //! -//! The Staking module depends on the [`GenesisConfig`](./struct.GenesisConfig.html). -//! The `GenesisConfig` is optional and allow to set some initial stakers. +//! The Staking module depends on the [`GenesisConfig`](./struct.GenesisConfig.html). The +//! `GenesisConfig` is optional and allow to set some initial stakers. //! //! ## Related Modules //! @@ -255,7 +271,7 @@ mod mock; #[cfg(test)] mod tests; -#[cfg(feature = "testing-utils")] +#[cfg(any(feature = "runtime-benchmarks", test))] pub mod testing_utils; #[cfg(any(feature = "runtime-benchmarks", test))] pub mod benchmarking; @@ -273,10 +289,13 @@ use sp_std::{ }; use codec::{HasCompact, Encode, Decode}; use frame_support::{ - decl_module, decl_event, decl_storage, ensure, decl_error, debug, - weights::{SimpleDispatchInfo, Weight}, + decl_module, decl_event, decl_storage, ensure, decl_error, + weights::{Weight, constants::{WEIGHT_PER_MICROS, WEIGHT_PER_NANOS}}, storage::IterableStorageMap, - dispatch::{IsSubType, DispatchResult}, + dispatch::{ + IsSubType, DispatchResult, DispatchResultWithPostInfo, DispatchErrorWithPostInfo, + WithPostDispatchInfo, + }, traits::{ Currency, LockIdentifier, LockableCurrency, WithdrawReasons, OnUnbalanced, Imbalance, Get, UnixTime, EstimateNextNewSession, EnsureOrigin, @@ -284,15 +303,15 @@ use frame_support::{ }; use pallet_session::historical; use sp_runtime::{ - Perbill, PerU16, PerThing, RuntimeDebug, + Percent, Perbill, PerU16, PerThing, RuntimeDebug, DispatchError, curve::PiecewiseLinear, traits::{ - Convert, Zero, StaticLookup, CheckedSub, Saturating, SaturatedConversion, AtLeast32Bit, - SignedExtension, + Convert, Zero, StaticLookup, CheckedSub, Saturating, SaturatedConversion, + AtLeast32BitUnsigned, Dispatchable, }, transaction_validity::{ TransactionValidityError, TransactionValidity, ValidTransaction, InvalidTransaction, - TransactionSource, + TransactionSource, TransactionPriority, }, }; use sp_staking::{ @@ -303,11 +322,12 @@ use sp_staking::{ use sp_runtime::{Serialize, Deserialize}; use frame_system::{ self as system, ensure_signed, ensure_root, ensure_none, - offchain::SubmitUnsignedTransaction, + offchain::SendTransactionTypes, }; -use sp_phragmen::{ - ExtendedBalance, Assignment, PhragmenScore, PhragmenResult, build_support_map, evaluate_support, - elect, generate_compact_solution_type, is_score_better, VotingLimit, SupportMap, +use sp_npos_elections::{ + ExtendedBalance, Assignment, ElectionScore, ElectionResult as PrimitiveElectionResult, + build_support_map, evaluate_support, seq_phragmen, generate_compact_solution_type, + is_score_better, VotingLimit, SupportMap, VoteWeight, }; const DEFAULT_MINIMUM_VALIDATOR_COUNT: u32 = 4; @@ -315,6 +335,19 @@ const STAKING_ID: LockIdentifier = *b"staking "; pub const MAX_UNLOCKING_CHUNKS: usize = 32; pub const MAX_NOMINATIONS: usize = ::LIMIT; +pub(crate) const LOG_TARGET: &'static str = "staking"; + +// syntactic sugar for logging. +#[macro_export] +macro_rules! log { + ($level:tt, $patter:expr $(, $values:expr)* $(,)?) => { + frame_support::debug::$level!( + target: crate::LOG_TARGET, + $patter $(, $values)* + ) + }; +} + /// Data type used to index nominators in the compact type pub type NominatorIndex = u32; @@ -342,18 +375,18 @@ generate_compact_solution_type!(pub GenericCompactAssignments, 16); #[derive(Encode, Decode, RuntimeDebug)] pub struct ActiveEraInfo { /// Index of era. - index: EraIndex, - /// Moment of start expresed as millisecond from `$UNIX_EPOCH`. + pub index: EraIndex, + /// Moment of start expressed as millisecond from `$UNIX_EPOCH`. /// /// Start can be none if start hasn't been set for the era yet, /// Start is set on the first on_finalize of the era to guarantee usage of `Time`. start: Option, } -/// Accuracy used for on-chain phragmen. +/// Accuracy used for on-chain election. pub type ChainAccuracy = Perbill; -/// Accuracy used for off-chain phragmen. This better be small. +/// Accuracy used for off-chain election. This better be small. pub type OffchainAccuracy = PerU16; /// The balance type of this module. @@ -460,7 +493,7 @@ pub struct StakingLedger { impl< AccountId, - Balance: HasCompact + Copy + Saturating + AtLeast32Bit, + Balance: HasCompact + Copy + Saturating + AtLeast32BitUnsigned, > StakingLedger { /// Remove entries from `unlocking` that are sufficiently old and reduce the /// total by the sum of their balances. @@ -511,7 +544,7 @@ impl< } impl StakingLedger where - Balance: AtLeast32Bit + Saturating + Copy, + Balance: AtLeast32BitUnsigned + Saturating + Copy, { /// Slash the validator for a given amount of balance. This can grow the value /// of the slash in the case that the validator has less than `minimum_balance` @@ -583,10 +616,10 @@ pub struct Nominations { #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, RuntimeDebug)] pub struct IndividualExposure { /// The stash account of the nominator in question. - who: AccountId, + pub who: AccountId, /// Amount of funds exposed. #[codec(compact)] - value: Balance, + pub value: Balance, } /// A snapshot of the stake backing a single validator in the system. @@ -651,6 +684,22 @@ pub enum ElectionStatus { Open(BlockNumber), } +/// Some indications about the size of the election. This must be submitted with the solution. +/// +/// Note that these values must reflect the __total__ number, not only those that are present in the +/// solution. In short, these should be the same size as the size of the values dumped in +/// `SnapshotValidators` and `SnapshotNominators`. +#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, Default)] +pub struct ElectionSize { + /// Number of validators in the snapshot of the current election round. + #[codec(compact)] + pub validators: ValidatorIndex, + /// Number of nominators in the snapshot of the current election round. + #[codec(compact)] + pub nominators: NominatorIndex, +} + + impl ElectionStatus { fn is_open_at(&self, n: BlockNumber) -> bool { *self == Self::Open(n) @@ -714,7 +763,135 @@ impl SessionInterface<::AccountId> for T whe } } -pub trait Trait: frame_system::Trait { +pub mod weight { + use super::*; + + /// All weight notes are pertaining to the case of a better solution, in which we execute + /// the longest code path. + /// Weight: 0 + (0.63 μs * v) + (0.36 μs * n) + (96.53 μs * a ) + (8 μs * w ) with: + /// * v validators in snapshot validators, + /// * n nominators in snapshot nominators, + /// * a assignment in the submitted solution + /// * w winners in the submitted solution + /// + /// State reads: + /// - Initial checks: + /// - ElectionState, CurrentEra, QueuedScore + /// - SnapshotValidators.len() + SnapShotNominators.len() + /// - ValidatorCount + /// - SnapshotValidators + /// - SnapshotNominators + /// - Iterate over nominators: + /// - compact.len() * Nominators(who) + /// - (non_self_vote_edges) * SlashingSpans + /// - For `assignment_ratio_to_staked`: Basically read the staked value of each stash. + /// - (winners.len() + compact.len()) * (Ledger + Bonded) + /// - TotalIssuance (read a gzillion times potentially, but well it is cached.) + /// - State writes: + /// - QueuedElected, QueuedScore + pub fn weight_for_submit_solution( + winners: &Vec, + compact: &CompactAssignments, + size: &ElectionSize, + ) -> Weight { + (630 * WEIGHT_PER_NANOS).saturating_mul(size.validators as Weight) + .saturating_add((360 * WEIGHT_PER_NANOS).saturating_mul(size.nominators as Weight)) + .saturating_add((96 * WEIGHT_PER_MICROS).saturating_mul(compact.len() as Weight)) + .saturating_add((8 * WEIGHT_PER_MICROS).saturating_mul(winners.len() as Weight)) + // Initial checks + .saturating_add(T::DbWeight::get().reads(8)) + // Nominators + .saturating_add(T::DbWeight::get().reads(compact.len() as Weight)) + // SlashingSpans (upper bound for invalid solution) + .saturating_add(T::DbWeight::get().reads(compact.edge_count() as Weight)) + // `assignment_ratio_to_staked` + .saturating_add(T::DbWeight::get().reads(2 * ((winners.len() + compact.len()) as Weight))) + .saturating_add(T::DbWeight::get().reads(1)) + // write queued score and elected + .saturating_add(T::DbWeight::get().writes(2)) + } + + /// Weight of `submit_solution` in case of a correct submission. + /// + /// refund: we charged compact.len() * read(1) for SlashingSpans. A valid solution only reads + /// winners.len(). + pub fn weight_for_correct_submit_solution( + winners: &Vec, + compact: &CompactAssignments, + size: &ElectionSize, + ) -> Weight { + // NOTE: for consistency, we re-compute the original weight to maintain their relation and + // prevent any foot-guns. + let original_weight = weight_for_submit_solution::(winners, compact, size); + original_weight + .saturating_sub(T::DbWeight::get().reads(compact.edge_count() as Weight)) + .saturating_add(T::DbWeight::get().reads(winners.len() as Weight)) + } +} + +pub trait WeightInfo { + fn bond(u: u32, ) -> Weight; + fn bond_extra(u: u32, ) -> Weight; + fn unbond(u: u32, ) -> Weight; + fn withdraw_unbonded_update(s: u32, ) -> Weight; + fn withdraw_unbonded_kill(s: u32, ) -> Weight; + fn validate(u: u32, ) -> Weight; + fn nominate(n: u32, ) -> Weight; + fn chill(u: u32, ) -> Weight; + fn set_payee(u: u32, ) -> Weight; + fn set_controller(u: u32, ) -> Weight; + fn set_validator_count(c: u32, ) -> Weight; + fn force_no_eras(i: u32, ) -> Weight; + fn force_new_era(i: u32, ) -> Weight; + fn force_new_era_always(i: u32, ) -> Weight; + fn set_invulnerables(v: u32, ) -> Weight; + fn force_unstake(s: u32, ) -> Weight; + fn cancel_deferred_slash(s: u32, ) -> Weight; + fn payout_stakers(n: u32, ) -> Weight; + fn payout_stakers_alive_controller(n: u32, ) -> Weight; + fn rebond(l: u32, ) -> Weight; + fn set_history_depth(e: u32, ) -> Weight; + fn reap_stash(s: u32, ) -> Weight; + fn new_era(v: u32, n: u32, ) -> Weight; + fn do_slash(l: u32, ) -> Weight; + fn payout_all(v: u32, n: u32, ) -> Weight; + fn submit_solution_initial(v: u32, n: u32, a: u32, w: u32, ) -> Weight; + fn submit_solution_better(v: u32, n: u32, a: u32, w: u32, ) -> Weight; + fn submit_solution_weaker(v: u32, n: u32, ) -> Weight; +} + +impl WeightInfo for () { + fn bond(_u: u32, ) -> Weight { 1_000_000_000 } + fn bond_extra(_u: u32, ) -> Weight { 1_000_000_000 } + fn unbond(_u: u32, ) -> Weight { 1_000_000_000 } + fn withdraw_unbonded_update(_s: u32, ) -> Weight { 1_000_000_000 } + fn withdraw_unbonded_kill(_s: u32, ) -> Weight { 1_000_000_000 } + fn validate(_u: u32, ) -> Weight { 1_000_000_000 } + fn nominate(_n: u32, ) -> Weight { 1_000_000_000 } + fn chill(_u: u32, ) -> Weight { 1_000_000_000 } + fn set_payee(_u: u32, ) -> Weight { 1_000_000_000 } + fn set_controller(_u: u32, ) -> Weight { 1_000_000_000 } + fn set_validator_count(_c: u32, ) -> Weight { 1_000_000_000 } + fn force_no_eras(_i: u32, ) -> Weight { 1_000_000_000 } + fn force_new_era(_i: u32, ) -> Weight { 1_000_000_000 } + fn force_new_era_always(_i: u32, ) -> Weight { 1_000_000_000 } + fn set_invulnerables(_v: u32, ) -> Weight { 1_000_000_000 } + fn force_unstake(_s: u32, ) -> Weight { 1_000_000_000 } + fn cancel_deferred_slash(_s: u32, ) -> Weight { 1_000_000_000 } + fn payout_stakers(_n: u32, ) -> Weight { 1_000_000_000 } + fn payout_stakers_alive_controller(_n: u32, ) -> Weight { 1_000_000_000 } + fn rebond(_l: u32, ) -> Weight { 1_000_000_000 } + fn set_history_depth(_e: u32, ) -> Weight { 1_000_000_000 } + fn reap_stash(_s: u32, ) -> Weight { 1_000_000_000 } + fn new_era(_v: u32, _n: u32, ) -> Weight { 1_000_000_000 } + fn do_slash(_l: u32, ) -> Weight { 1_000_000_000 } + fn payout_all(_v: u32, _n: u32, ) -> Weight { 1_000_000_000 } + fn submit_solution_initial(_v: u32, _n: u32, _a: u32, _w: u32, ) -> Weight { 1_000_000_000 } + fn submit_solution_better(_v: u32, _n: u32, _a: u32, _w: u32, ) -> Weight { 1_000_000_000 } + fn submit_solution_weaker(_v: u32, _n: u32, ) -> Weight { 1_000_000_000 } +} + +pub trait Trait: frame_system::Trait + SendTransactionTypes> { /// The staking balance. type Currency: LockableCurrency; @@ -724,14 +901,15 @@ pub trait Trait: frame_system::Trait { /// is not used. type UnixTime: UnixTime; - /// Convert a balance into a number used for election calculation. - /// 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. TODO: #2908 - type CurrencyToVote: Convert, u64> + Convert>; + /// Convert a balance into a number used for election calculation. This must fit into a `u64` + /// but is allowed to be sensibly lossy. The `u64` is used to communicate with the + /// [`sp_npos_elections`] crate which accepts u64 numbers and does operations in 128. + /// Consequently, the backward convert is used convert the u128s from sp-elections back to a + /// [`BalanceOf`]. + type CurrencyToVote: Convert, VoteWeight> + Convert>; /// Tokens have been minted and are unused for validator-reward. + /// See [Era payout](./index.html#era-payout). type RewardRemainder: OnUnbalanced>; /// The overarching event type. @@ -749,9 +927,10 @@ pub trait Trait: frame_system::Trait { /// Number of eras that staked funds must remain bonded for. type BondingDuration: Get; - /// Number of eras that slashes are deferred by, after computation. This - /// should be less than the bonding duration. Set to 0 if slashes should be - /// applied immediately, without opportunity for intervention. + /// Number of eras that slashes are deferred by, after computation. + /// + /// This should be less than the bonding duration. Set to 0 if slashes + /// should be applied immediately, without opportunity for intervention. type SlashDeferDuration: Get; /// The origin which can cancel a deferred slash. Root can always do this. @@ -760,28 +939,47 @@ pub trait Trait: frame_system::Trait { /// Interface for interacting with a session module. type SessionInterface: self::SessionInterface; - /// The NPoS reward curve to use. + /// The NPoS reward curve used to define yearly inflation. + /// See [Era payout](./index.html#era-payout). type RewardCurve: Get<&'static PiecewiseLinear<'static>>; /// Something that can estimate the next session change, accurately or as a best effort guess. type NextNewSession: EstimateNextNewSession; - /// How many blocks ahead of the era, within the last do we try to run the phragmen offchain? + /// The number of blocks before the end of the era from which election submissions are allowed. + /// /// Setting this to zero will disable the offchain compute and only on-chain seq-phragmen will /// be used. + /// + /// This is bounded by being within the last session. Hence, setting it to a value more than the + /// length of a session will be pointless. type ElectionLookahead: Get; /// The overarching call type. - type Call: From> + IsSubType, Self> + Clone; + type Call: Dispatchable + From> + IsSubType> + Clone; + + /// Maximum number of balancing iterations to run in the offchain submission. + /// + /// If set to 0, balance_solution will not be executed at all. + type MaxIterations: Get; - /// A transaction submitter. - type SubmitTransaction: SubmitUnsignedTransaction::Call>; + /// The threshold of improvement that should be provided for a new solution to be accepted. + type MinSolutionScoreBump: Get; /// The maximum number of nominators rewarded for each validator. /// /// For each validator only the `$MaxNominatorRewardedPerValidator` biggest stakers can claim /// their reward. This used to limit the i/o cost for the nominator payout. type MaxNominatorRewardedPerValidator: Get; + + /// A configuration for base priority of unsigned transactions. + /// + /// This is exposed so that it can be tuned for particular runtime, when + /// multiple pallets send unsigned transactions. + type UnsignedPriority: Get; + + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; } /// Mode of era-forcing. @@ -802,19 +1000,20 @@ impl Default for Forcing { fn default() -> Self { Forcing::NotForcing } } -// A value placed in storage that represents the current version of the Staking storage. -// This value is used by the `on_runtime_upgrade` logic to determine whether we run -// storage migration logic. This should match directly with the semantic versions of the Rust crate. +// A value placed in storage that represents the current version of the Staking storage. This value +// is used by the `on_runtime_upgrade` logic to determine whether we run storage migration logic. +// This should match directly with the semantic versions of the Rust crate. #[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug)] enum Releases { V1_0_0Ancient, V2_0_0, V3_0_0, + V4_0_0, } impl Default for Releases { fn default() -> Self { - Releases::V3_0_0 + Releases::V4_0_0 } } @@ -824,9 +1023,9 @@ decl_storage! { /// /// Information is kept for eras in `[current_era - history_depth; current_era]`. /// - /// Must be more than the number of eras delayed by session otherwise. - /// I.e. active era must always be in history. - /// I.e. `active_era > current_era - history_depth` must be guaranteed. + /// Must be more than the number of eras delayed by session otherwise. I.e. active era must + /// always be in history. I.e. `active_era > current_era - history_depth` must be + /// guaranteed. HistoryDepth get(fn history_depth) config(): u32 = 84; /// The ideal number of staking participants. @@ -986,23 +1185,21 @@ decl_storage! { pub QueuedElected get(fn queued_elected): Option>>; /// The score of the current [`QueuedElected`]. - pub QueuedScore get(fn queued_score): Option; + pub QueuedScore get(fn queued_score): Option; /// Flag to control the execution of the offchain election. When `Open(_)`, we accept /// solutions to be submitted. pub EraElectionStatus get(fn era_election_status): ElectionStatus; - /// True if the current planned session is final. + /// True if the current **planned** session is final. Note that this does not take era + /// forcing into account. pub IsCurrentSessionFinal get(fn is_current_session_final): bool = false; /// True if network has been upgraded to this version. /// Storage version of the pallet. /// /// This is set to v3.0.0 for new networks. - StorageVersion build(|_: &GenesisConfig| Releases::V3_0_0): Releases; - - /// The era where we migrated from Lazy Payouts to Simple Payouts - MigrateEra: Option; + StorageVersion build(|_: &GenesisConfig| Releases::V4_0_0): Releases; } add_extra_genesis { config(stakers): @@ -1040,6 +1237,9 @@ decl_storage! { decl_event!( pub enum Event where Balance = BalanceOf, ::AccountId { + /// The era payout has been set; the first balance is the validator-payout; the second is + /// the remainder from the maximum amount of reward. + EraPayout(EraIndex, Balance, Balance), /// The staker has been rewarded by this amount. `AccountId` is the stash account. Reward(AccountId, Balance), /// One validator (and its nominators) has been slashed by the given amount. @@ -1049,6 +1249,8 @@ decl_event!( OldSlashingReportDiscarded(SessionIndex), /// A new set of stakers was elected with the given computation method. StakingElection(ElectionCompute), + /// A new solution for the upcoming election has been stored. + SolutionStored(ElectionCompute), /// An account has bonded this amount. /// /// NOTE: This event is only emitted when funds are bonded via a dispatchable. Notably, @@ -1122,6 +1324,14 @@ decl_error! { PhragmenBogusEdge, /// The claimed score does not match with the one computed from the data. PhragmenBogusScore, + /// The election size is invalid. + PhragmenBogusElectionSize, + /// The call is not allowed at the given time due to restrictions of election period. + CallNotAllowed, + /// Incorrect previous history depth input provided. + IncorrectHistoryDepth, + /// Incorrect number of slashing spans provided. + IncorrectSlashingSpans, } } @@ -1133,6 +1343,36 @@ decl_module! { /// Number of eras that staked funds must remain bonded for. const BondingDuration: EraIndex = T::BondingDuration::get(); + /// Number of eras that slashes are deferred by, after computation. + /// + /// This should be less than the bonding duration. + /// Set to 0 if slashes should be applied immediately, without opportunity for + /// intervention. + const SlashDeferDuration: EraIndex = T::SlashDeferDuration::get(); + + /// The number of blocks before the end of the era from which election submissions are allowed. + /// + /// Setting this to zero will disable the offchain compute and only on-chain seq-phragmen will + /// be used. + /// + /// This is bounded by being within the last session. Hence, setting it to a value more than the + /// length of a session will be pointless. + const ElectionLookahead: T::BlockNumber = T::ElectionLookahead::get(); + + /// Maximum number of balancing iterations to run in the offchain submission. + /// + /// If set to 0, balance_solution will not be executed at all. + const MaxIterations: u32 = T::MaxIterations::get(); + + /// The threshold of improvement that should be provided for a new solution to be accepted. + const MinSolutionScoreBump: Perbill = T::MinSolutionScoreBump::get(); + + /// The maximum number of nominators rewarded for each validator. + /// + /// For each validator only the `$MaxNominatorRewardedPerValidator` biggest stakers can claim + /// their reward. This used to limit the i/o cost for the nominator payout. + const MaxNominatorRewardedPerValidator: u32 = T::MaxNominatorRewardedPerValidator::get(); + type Error = Error; fn deposit_event() = default; @@ -1143,46 +1383,46 @@ decl_module! { /// worker, if applicable, will execute at the end of the current block, and solutions may /// be submitted. fn on_initialize(now: T::BlockNumber) -> Weight { + let mut consumed_weight = 0; + let mut add_weight = |reads, writes, weight| { + consumed_weight += T::DbWeight::get().reads_writes(reads, writes); + consumed_weight += weight; + }; if // if we don't have any ongoing offchain compute. Self::era_election_status().is_closed() && - Self::is_current_session_final() + // either current session final based on the plan, or we're forcing. + (Self::is_current_session_final() || Self::will_era_be_forced()) { - if let Some(next_session_change) = T::NextNewSession::estimate_next_new_session(now){ + if let Some(next_session_change) = T::NextNewSession::estimate_next_new_session(now) { if let Some(remaining) = next_session_change.checked_sub(&now) { if remaining <= T::ElectionLookahead::get() && !remaining.is_zero() { // create snapshot. - if Self::create_stakers_snapshot() { + let (did_snapshot, snapshot_weight) = Self::create_stakers_snapshot(); + add_weight(0, 0, snapshot_weight); + if did_snapshot { // Set the flag to make sure we don't waste any compute here in the same era // after we have triggered the offline compute. >::put( ElectionStatus::::Open(now) ); - debug::native::info!( - target: "staking", - "Election window is Open({:?}). Snapshot created", - now, - ); + add_weight(0, 1, 0); + log!(info, "💸 Election window is Open({:?}). Snapshot created", now); } else { - debug::native::warn!( - target: "staking", - "Failed to create snapshot at {:?}. Election window will remain closed.", - now, - ); + log!(warn, "💸 Failed to create snapshot at {:?}.", now); } - } } } else { - debug::native::warn!( - target: "staking", - "estimate_next_new_session() failed to execute. Election status cannot be changed.", - ); + log!(warn, "💸 Estimating next session change failed."); } + add_weight(0, 0, T::NextNewSession::weight(now)) } - - // weight - 50_000 + // For `era_election_status`, `is_current_session_final`, `will_era_be_forced` + add_weight(3, 0, 0); + // Additional read from `on_finalize` + add_weight(1, 0, 0); + consumed_weight } /// Check if the current block number is the one at which the election window has been set @@ -1193,23 +1433,12 @@ decl_module! { if Self::era_election_status().is_open_at(now) { let offchain_status = set_check_offchain_execution_status::(now); if let Err(why) = offchain_status { - debug::native::warn!( - target: "staking", - "skipping offchain worker in open election window due to [{}]", - why, - ); + log!(debug, "skipping offchain worker in open election window due to [{}]", why); } else { if let Err(e) = compute_offchain_election::() { - debug::native::warn!( - target: "staking", - "Error in phragmen offchain worker: {:?}", - e, - ); + log!(error, "💸 Error in election offchain worker: {:?}", e); } else { - debug::native::debug!( - target: "staking", - "Executed offchain worker thread without errors. Transaction submitted to the pool.", - ); + log!(debug, "Executed offchain worker thread without errors."); } } } @@ -1221,17 +1450,11 @@ decl_module! { if active_era.start.is_none() { let now_as_millis_u64 = T::UnixTime::now().as_millis().saturated_into::(); active_era.start = Some(now_as_millis_u64); + // This write only ever happens once, we don't include it in the weight in general ActiveEra::put(active_era); } } - } - - fn on_runtime_upgrade() -> Weight { - // For Kusama the type hasn't actually changed as Moment was u64 and was the number of - // millisecond since unix epoch. - StorageVersion::put(Releases::V3_0_0); - Self::migrate_last_reward_to_claimed_rewards(); - 0 + // `on_finalize` weight is tracked in `on_initialize` } /// Take the origin account as a stash and lock up `value` of its balance. `controller` will @@ -1250,9 +1473,14 @@ decl_module! { /// /// NOTE: Two of the storage writes (`Self::bonded`, `Self::payee`) are _never_ cleaned /// unless the `origin` falls below _existential deposit_ and gets removed as dust. + /// ------------------ + /// Base Weight: 67.87 µs + /// DB Weight: + /// - Read: Bonded, Ledger, [Origin Account], Current Era, History Depth, Locks + /// - Write: Bonded, Payee, [Origin Account], Locks, Ledger /// # - #[weight = SimpleDispatchInfo::FixedNormal(500_000)] - fn bond(origin, + #[weight = 67 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(5, 4)] + pub fn bond(origin, controller: ::Source, #[compact] value: BalanceOf, payee: RewardDestination, @@ -1305,7 +1533,8 @@ decl_module! { /// Unlike [`bond`] or [`unbond`] this function does not impose any limitation on the amount /// that can be added. /// - /// The dispatch origin for this call must be _Signed_ by the stash, not the controller. + /// The dispatch origin for this call must be _Signed_ by the stash, not the controller and + /// it can be only called when [`EraElectionStatus`] is `Closed`. /// /// Emits `Bonded`. /// @@ -1313,9 +1542,15 @@ decl_module! { /// - Independent of the arguments. Insignificant complexity. /// - O(1). /// - One DB entry. + /// ------------ + /// Base Weight: 54.88 µs + /// DB Weight: + /// - Read: Era Election Status, Bonded, Ledger, [Origin Account], Locks + /// - Write: [Origin Account], Locks, Ledger /// # - #[weight = SimpleDispatchInfo::FixedNormal(500_000)] + #[weight = 55 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(4, 2)] fn bond_extra(origin, #[compact] max_additional: BalanceOf) { + ensure!(Self::era_election_status().is_closed(), Error::::CallNotAllowed); let stash = ensure_signed(origin)?; let controller = Self::bonded(&stash).ok_or(Error::::NotStash)?; @@ -1344,6 +1579,7 @@ decl_module! { /// to be called first to remove some of the chunks (if possible). /// /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. + /// And, it can be only called when [`EraElectionStatus`] is `Closed`. /// /// Emits `Unbonded`. /// @@ -1357,9 +1593,15 @@ decl_module! { /// The only way to clean the aforementioned storage item is also user-controlled via /// `withdraw_unbonded`. /// - One DB entry. + /// ---------- + /// Base Weight: 50.34 µs + /// DB Weight: + /// - Read: Era Election Status, Ledger, Current Era, Locks, [Origin Account] + /// - Write: [Origin Account], Locks, Ledger /// - #[weight = SimpleDispatchInfo::FixedNormal(400_000)] + #[weight = 50 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(4, 2)] fn unbond(origin, #[compact] value: BalanceOf) { + ensure!(Self::era_election_status().is_closed(), Error::::CallNotAllowed); let controller = ensure_signed(origin)?; let mut ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; ensure!( @@ -1392,6 +1634,7 @@ decl_module! { /// whatever it wants. /// /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. + /// And, it can be only called when [`EraElectionStatus`] is `Closed`. /// /// Emits `Withdrawn`. /// @@ -1403,9 +1646,29 @@ decl_module! { /// indirectly user-controlled. See [`unbond`] for more detail. /// - Contains a limited number of reads, yet the size of which could be large based on `ledger`. /// - Writes are limited to the `origin` account key. + /// --------------- + /// Complexity O(S) where S is the number of slashing spans to remove + /// Base Weight: + /// Update: 50.52 + .028 * S µs + /// - Reads: EraElectionStatus, Ledger, Current Era, Locks, [Origin Account] + /// - Writes: [Origin Account], Locks, Ledger + /// Kill: 79.41 + 2.366 * S µs + /// - Reads: EraElectionStatus, Ledger, Current Era, Bonded, Slashing Spans, [Origin Account], Locks + /// - Writes: Bonded, Slashing Spans (if S > 0), Ledger, Payee, Validators, Nominators, [Origin Account], Locks + /// - Writes Each: SpanSlash * S + /// NOTE: Weight annotation is the kill scenario, we refund otherwise. /// # - #[weight = SimpleDispatchInfo::FixedNormal(400_000)] - fn withdraw_unbonded(origin) { + #[weight = T::DbWeight::get().reads_writes(6, 6) + .saturating_add(80 * WEIGHT_PER_MICROS) + .saturating_add( + (2 * WEIGHT_PER_MICROS).saturating_mul(Weight::from(*num_slashing_spans)) + ) + .saturating_add(T::DbWeight::get().writes(Weight::from(*num_slashing_spans))) + // if slashing spans is non-zero, add 1 more write + .saturating_add(T::DbWeight::get().writes(Weight::from(*num_slashing_spans).min(1))) + ] + fn withdraw_unbonded(origin, num_slashing_spans: u32) -> DispatchResultWithPostInfo { + ensure!(Self::era_election_status().is_closed(), Error::::CallNotAllowed); let controller = ensure_signed(origin)?; let mut ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; let (stash, old_total) = (ledger.stash.clone(), ledger.total); @@ -1413,17 +1676,21 @@ decl_module! { ledger = ledger.consolidate_unlocked(current_era) } - if ledger.unlocking.is_empty() && ledger.active.is_zero() { + let post_info_weight = if ledger.unlocking.is_empty() && ledger.active.is_zero() { // This account must have called `unbond()` with some value that caused the active // portion to fall below existential deposit + will have no more unlocking chunks // left. We can now safely remove all staking-related information. - Self::kill_stash(&stash)?; + Self::kill_stash(&stash, num_slashing_spans)?; // remove the lock. T::Currency::remove_lock(STAKING_ID, &stash); + // This is worst case scenario, so we use the full weight and return None + None } else { // This was the consequence of a partial unbond. just update the ledger and move on. Self::update_ledger(&controller, &ledger); - } + // This is only an update, so we use less overall weight + Some(50 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(4, 2)) + }; // `old_total` should never be less than the new total because // `consolidate_unlocked` strictly subtracts balance. @@ -1432,6 +1699,8 @@ decl_module! { let value = old_total - ledger.total; Self::deposit_event(RawEvent::Withdrawn(stash, value)); } + + Ok(post_info_weight.into()) } /// Declare the desire to validate for the origin controller. @@ -1439,14 +1708,21 @@ decl_module! { /// Effects will be felt at the beginning of the next era. /// /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. + /// And, it can be only called when [`EraElectionStatus`] is `Closed`. /// /// # /// - Independent of the arguments. Insignificant complexity. /// - Contains a limited number of reads. /// - Writes are limited to the `origin` account key. + /// ----------- + /// Base Weight: 17.13 µs + /// DB Weight: + /// - Read: Era Election Status, Ledger + /// - Write: Nominators, Validators /// # - #[weight = SimpleDispatchInfo::FixedNormal(750_000)] - fn validate(origin, prefs: ValidatorPrefs) { + #[weight = 17 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(2, 2)] + pub fn validate(origin, prefs: ValidatorPrefs) { + ensure!(Self::era_election_status().is_closed(), Error::::CallNotAllowed); let controller = ensure_signed(origin)?; let ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; let stash = &ledger.stash; @@ -1456,23 +1732,35 @@ decl_module! { /// Declare the desire to nominate `targets` for the origin controller. /// - /// Effects will be felt at the beginning of the next era. + /// Effects will be felt at the beginning of the next era. This can only be called when + /// [`EraElectionStatus`] is `Closed`. /// /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. + /// And, it can be only called when [`EraElectionStatus`] is `Closed`. /// /// # - /// - The transaction's complexity is proportional to the size of `targets`, - /// which is capped at CompactAssignments::LIMIT. + /// - The transaction's complexity is proportional to the size of `targets` (N) + /// which is capped at CompactAssignments::LIMIT (MAX_NOMINATIONS). /// - Both the reads and writes follow a similar pattern. + /// --------- + /// Base Weight: 22.34 + .36 * N µs + /// where N is the number of targets + /// DB Weight: + /// - Reads: Era Election Status, Ledger, Current Era + /// - Writes: Validators, Nominators /// # - #[weight = SimpleDispatchInfo::FixedNormal(750_000)] - fn nominate(origin, targets: Vec<::Source>) { + #[weight = T::DbWeight::get().reads_writes(3, 2) + .saturating_add(22 * WEIGHT_PER_MICROS) + .saturating_add((360 * WEIGHT_PER_NANOS).saturating_mul(targets.len() as Weight)) + ] + pub fn nominate(origin, targets: Vec<::Source>) { + ensure!(Self::era_election_status().is_closed(), Error::::CallNotAllowed); let controller = ensure_signed(origin)?; let ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; let stash = &ledger.stash; ensure!(!targets.is_empty(), Error::::EmptyTargets); let targets = targets.into_iter() - .take(::LIMIT) + .take(MAX_NOMINATIONS) .map(|t| T::Lookup::lookup(t)) .collect::, _>>()?; @@ -1492,14 +1780,21 @@ decl_module! { /// Effects will be felt at the beginning of the next era. /// /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. + /// And, it can be only called when [`EraElectionStatus`] is `Closed`. /// /// # /// - Independent of the arguments. Insignificant complexity. /// - Contains one read. /// - Writes are limited to the `origin` account key. + /// -------- + /// Base Weight: 16.53 µs + /// DB Weight: + /// - Read: EraElectionStatus, Ledger + /// - Write: Validators, Nominators /// # - #[weight = SimpleDispatchInfo::FixedNormal(500_000)] + #[weight = 16 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(2, 2)] fn chill(origin) { + ensure!(Self::era_election_status().is_closed(), Error::::CallNotAllowed); let controller = ensure_signed(origin)?; let ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; Self::chill_stash(&ledger.stash); @@ -1515,8 +1810,13 @@ decl_module! { /// - Independent of the arguments. Insignificant complexity. /// - Contains a limited number of reads. /// - Writes are limited to the `origin` account key. + /// --------- + /// - Base Weight: 11.33 µs + /// - DB Weight: + /// - Read: Ledger + /// - Write: Payee /// # - #[weight = SimpleDispatchInfo::FixedNormal(500_000)] + #[weight = 11 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(1, 1)] fn set_payee(origin, payee: RewardDestination) { let controller = ensure_signed(origin)?; let ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; @@ -1534,8 +1834,13 @@ decl_module! { /// - Independent of the arguments. Insignificant complexity. /// - Contains a limited number of reads. /// - Writes are limited to the `origin` account key. + /// ---------- + /// Base Weight: 25.22 µs + /// DB Weight: + /// - Read: Bonded, Ledger New Controller, Ledger Old Controller + /// - Write: Bonded, Ledger New Controller, Ledger Old Controller /// # - #[weight = SimpleDispatchInfo::FixedNormal(750_000)] + #[weight = 25 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(3, 3)] fn set_controller(origin, controller: ::Source) { let stash = ensure_signed(origin)?; let old_controller = Self::bonded(&stash).ok_or(Error::::NotStash)?; @@ -1551,21 +1856,58 @@ decl_module! { } } - // ----- Root calls. - - /// The ideal number of validators. - #[weight = SimpleDispatchInfo::FixedNormal(5_000)] + /// Sets the ideal number of validators. + /// + /// The dispatch origin must be Root. + /// + /// # + /// Base Weight: 1.717 µs + /// Write: Validator Count + /// # + #[weight = 2 * WEIGHT_PER_MICROS + T::DbWeight::get().writes(1)] fn set_validator_count(origin, #[compact] new: u32) { ensure_root(origin)?; ValidatorCount::put(new); } + /// Increments the ideal number of validators. + /// + /// The dispatch origin must be Root. + /// + /// # + /// Base Weight: 1.717 µs + /// Read/Write: Validator Count + /// # + #[weight = 2 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(1, 1)] + fn increase_validator_count(origin, #[compact] additional: u32) { + ensure_root(origin)?; + ValidatorCount::mutate(|n| *n += additional); + } + + /// Scale up the ideal number of validators by a factor. + /// + /// The dispatch origin must be Root. + /// + /// # + /// Base Weight: 1.717 µs + /// Read/Write: Validator Count + /// # + #[weight = 2 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(1, 1)] + fn scale_validator_count(origin, factor: Percent) { + ensure_root(origin)?; + ValidatorCount::mutate(|n| *n += factor * *n); + } + /// Force there to be no new eras indefinitely. /// + /// The dispatch origin must be Root. + /// /// # /// - No arguments. + /// - Base Weight: 1.857 µs + /// - Write: ForceEra /// # - #[weight = SimpleDispatchInfo::FixedNormal(5_000)] + #[weight = 2 * WEIGHT_PER_MICROS + T::DbWeight::get().writes(1)] fn force_no_eras(origin) { ensure_root(origin)?; ForceEra::put(Forcing::ForceNone); @@ -1574,29 +1916,62 @@ decl_module! { /// Force there to be a new era at the end of the next session. After this, it will be /// reset to normal (non-forced) behaviour. /// + /// The dispatch origin must be Root. + /// /// # /// - No arguments. + /// - Base Weight: 1.959 µs + /// - Write ForceEra /// # - #[weight = SimpleDispatchInfo::FixedNormal(5_000)] + #[weight = 2 * WEIGHT_PER_MICROS + T::DbWeight::get().writes(1)] fn force_new_era(origin) { ensure_root(origin)?; ForceEra::put(Forcing::ForceNew); } /// Set the validators who cannot be slashed (if any). - #[weight = SimpleDispatchInfo::FixedNormal(5_000)] + /// + /// The dispatch origin must be Root. + /// + /// # + /// - O(V) + /// - Base Weight: 2.208 + .006 * V µs + /// - Write: Invulnerables + /// # + #[weight = T::DbWeight::get().writes(1) + .saturating_add(2 * WEIGHT_PER_MICROS) + .saturating_add((6 * WEIGHT_PER_NANOS).saturating_mul(validators.len() as Weight)) + ] fn set_invulnerables(origin, validators: Vec) { ensure_root(origin)?; >::put(validators); } /// Force a current staker to become completely unstaked, immediately. - #[weight = SimpleDispatchInfo::FixedNormal(10_000)] - fn force_unstake(origin, stash: T::AccountId) { + /// + /// The dispatch origin must be Root. + /// + /// # + /// O(S) where S is the number of slashing spans to be removed + /// Base Weight: 53.07 + 2.365 * S µs + /// Reads: Bonded, Slashing Spans, Account, Locks + /// Writes: Bonded, Slashing Spans (if S > 0), Ledger, Payee, Validators, Nominators, Account, Locks + /// Writes Each: SpanSlash * S + /// # + #[weight = T::DbWeight::get().reads_writes(4, 7) + .saturating_add(53 * WEIGHT_PER_MICROS) + .saturating_add( + WEIGHT_PER_MICROS.saturating_mul(2).saturating_mul(Weight::from(*num_slashing_spans)) + ) + .saturating_add(T::DbWeight::get().writes(Weight::from(*num_slashing_spans))) + // if slashing spans is non-zero, add 1 more write + .saturating_add(T::DbWeight::get().writes(Weight::from(*num_slashing_spans > 0))) + ] + fn force_unstake(origin, stash: T::AccountId, num_slashing_spans: u32) { ensure_root(origin)?; // remove all staking-related information. - Self::kill_stash(&stash)?; + Self::kill_stash(&stash, num_slashing_spans)?; // remove the lock. T::Currency::remove_lock(STAKING_ID, &stash); @@ -1604,27 +1979,38 @@ decl_module! { /// Force there to be a new era at the end of sessions indefinitely. /// + /// The dispatch origin must be Root. + /// /// # - /// - One storage write + /// - Base Weight: 2.05 µs + /// - Write: ForceEra /// # - #[weight = SimpleDispatchInfo::FixedNormal(5_000)] + #[weight = 2 * WEIGHT_PER_MICROS + T::DbWeight::get().writes(1)] fn force_new_era_always(origin) { ensure_root(origin)?; ForceEra::put(Forcing::ForceAlways); } - /// Cancel enactment of a deferred slash. Can be called by either the root origin or - /// the `T::SlashCancelOrigin`. - /// passing the era and indices of the slashes for that era to kill. + /// Cancel enactment of a deferred slash. + /// + /// Can be called by the `T::SlashCancelOrigin`. + /// + /// Parameters: era and indices of the slashes for that era to kill. /// /// # - /// - One storage write. + /// Complexity: O(U + S) + /// with U unapplied slashes weighted with U=1000 + /// and S is the number of slash indices to be canceled. + /// - Base: 5870 + 34.61 * S µs + /// - Read: Unapplied Slashes + /// - Write: Unapplied Slashes /// # - #[weight = SimpleDispatchInfo::FixedNormal(1_000_000)] + #[weight = T::DbWeight::get().reads_writes(1, 1) + .saturating_add(5_870 * WEIGHT_PER_MICROS) + .saturating_add((35 * WEIGHT_PER_MICROS).saturating_mul(slash_indices.len() as Weight)) + ] fn cancel_deferred_slash(origin, era: EraIndex, slash_indices: Vec) { - T::SlashCancelOrigin::try_origin(origin) - .map(|_| ()) - .or_else(ensure_root)?; + T::SlashCancelOrigin::ensure_origin(origin)?; ensure!(!slash_indices.is_empty(), Error::::EmptyTargets); ensure!(is_sorted_and_unique(&slash_indices), Error::::NotSortedAndUnique); @@ -1641,69 +2027,6 @@ decl_module! { ::UnappliedSlashes::insert(&era, &unapplied); } - /// **This extrinsic will be removed after `MigrationEra + HistoryDepth` has passed, giving - /// opportunity for users to claim all rewards before moving to Simple Payouts. After this - /// time, you should use `payout_stakers` instead.** - /// - /// Make one nominator's payout for one era. - /// - /// - `who` is the controller account of the nominator to pay out. - /// - `era` may not be lower than one following the most recently paid era. If it is higher, - /// then it indicates an instruction to skip the payout of all previous eras. - /// - `validators` is the list of all validators that `who` had exposure to during `era`, - /// alongside the index of `who` in the clipped exposure of the validator. - /// I.e. each element is a tuple of - /// `(validator, index of `who` in clipped exposure of validator)`. - /// If it is incomplete, then less than the full reward will be paid out. - /// It must not exceed `MAX_NOMINATIONS`. - /// - /// WARNING: once an era is payed for a validator such validator can't claim the payout of - /// previous era. - /// - /// WARNING: Incorrect arguments here can result in loss of payout. Be very careful. - /// - /// # - /// - Number of storage read of `O(validators)`; `validators` is the argument of the call, - /// and is bounded by `MAX_NOMINATIONS`. - /// - Each storage read is `O(N)` size and decode complexity; `N` is the maximum - /// nominations that can be given to a single validator. - /// - Computation complexity: `O(MAX_NOMINATIONS * logN)`; `MAX_NOMINATIONS` is the - /// maximum number of validators that may be nominated by a single nominator, it is - /// bounded only economically (all nominators are required to place a minimum stake). - /// # - #[weight = SimpleDispatchInfo::FixedNormal(500_000)] - fn payout_nominator(origin, era: EraIndex, validators: Vec<(T::AccountId, u32)>) - -> DispatchResult - { - let who = ensure_signed(origin)?; - Self::do_payout_nominator(who, era, validators) - } - - /// **This extrinsic will be removed after `MigrationEra + HistoryDepth` has passed, giving - /// opportunity for users to claim all rewards before moving to Simple Payouts. After this - /// time, you should use `payout_stakers` instead.** - /// - /// Make one validator's payout for one era. - /// - /// - `who` is the controller account of the validator to pay out. - /// - `era` may not be lower than one following the most recently paid era. If it is higher, - /// then it indicates an instruction to skip the payout of all previous eras. - /// - /// WARNING: once an era is payed for a validator such validator can't claim the payout of - /// previous era. - /// - /// WARNING: Incorrect arguments here can result in loss of payout. Be very careful. - /// - /// # - /// - Time complexity: O(1). - /// - Contains a limited number of reads and writes. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(500_000)] - fn payout_validator(origin, era: EraIndex) -> DispatchResult { - let who = ensure_signed(origin)?; - Self::do_payout_validator(who, era) - } - /// Pay out all the stakers behind a single validator for a single era. /// /// - `validator_stash` is the stash account of the validator. Their nominators, up to @@ -1713,40 +2036,101 @@ decl_module! { /// The origin of this call must be _Signed_. Any account can call this function, even if /// it is not one of the stakers. /// + /// This can only be called when [`EraElectionStatus`] is `Closed`. + /// /// # /// - Time complexity: at most O(MaxNominatorRewardedPerValidator). /// - Contains a limited number of reads and writes. + /// ----------- + /// N is the Number of payouts for the validator (including the validator) + /// Base Weight: + /// - Reward Destination Staked: 110 + 54.2 * N µs (Median Slopes) + /// - Reward Destination Controller (Creating): 120 + 41.95 * N µs (Median Slopes) + /// DB Weight: + /// - Read: EraElectionStatus, CurrentEra, HistoryDepth, ErasValidatorReward, + /// ErasStakersClipped, ErasRewardPoints, ErasValidatorPrefs (8 items) + /// - Read Each: Bonded, Ledger, Payee, Locks, System Account (5 items) + /// - Write Each: System Account, Locks, Ledger (3 items) /// # - #[weight = SimpleDispatchInfo::FixedNormal(500_000)] + #[weight = + 120 * WEIGHT_PER_MICROS + + 54 * WEIGHT_PER_MICROS * Weight::from(T::MaxNominatorRewardedPerValidator::get()) + + T::DbWeight::get().reads(7) + + T::DbWeight::get().reads(5) * Weight::from(T::MaxNominatorRewardedPerValidator::get() + 1) + + T::DbWeight::get().writes(3) * Weight::from(T::MaxNominatorRewardedPerValidator::get() + 1) + ] fn payout_stakers(origin, validator_stash: T::AccountId, era: EraIndex) -> DispatchResult { + ensure!(Self::era_election_status().is_closed(), Error::::CallNotAllowed); ensure_signed(origin)?; Self::do_payout_stakers(validator_stash, era) } /// Rebond a portion of the stash scheduled to be unlocked. /// + /// The dispatch origin must be signed by the controller, and it can be only called when + /// [`EraElectionStatus`] is `Closed`. + /// /// # - /// - Time complexity: O(1). Bounded by `MAX_UNLOCKING_CHUNKS`. + /// - Time complexity: O(L), where L is unlocking chunks + /// - Bounded by `MAX_UNLOCKING_CHUNKS`. /// - Storage changes: Can't increase storage, only decrease it. + /// --------------- + /// - Base Weight: 34.51 µs * .048 L µs + /// - DB Weight: + /// - Reads: EraElectionStatus, Ledger, Locks, [Origin Account] + /// - Writes: [Origin Account], Locks, Ledger /// # - #[weight = SimpleDispatchInfo::FixedNormal(500_000)] - fn rebond(origin, #[compact] value: BalanceOf) { + #[weight = + 35 * WEIGHT_PER_MICROS + + 50 * WEIGHT_PER_NANOS * (MAX_UNLOCKING_CHUNKS as Weight) + + T::DbWeight::get().reads_writes(3, 2) + ] + fn rebond(origin, #[compact] value: BalanceOf) -> DispatchResultWithPostInfo { + ensure!(Self::era_election_status().is_closed(), Error::::CallNotAllowed); let controller = ensure_signed(origin)?; let ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; - ensure!( - !ledger.unlocking.is_empty(), - Error::::NoUnlockChunk, - ); + ensure!(!ledger.unlocking.is_empty(), Error::::NoUnlockChunk); let ledger = ledger.rebond(value); Self::update_ledger(&controller, &ledger); + Ok(Some( + 35 * WEIGHT_PER_MICROS + + 50 * WEIGHT_PER_NANOS * (ledger.unlocking.len() as Weight) + + T::DbWeight::get().reads_writes(3, 2) + ).into()) } - /// Set history_depth value. + /// Set `HistoryDepth` value. This function will delete any history information + /// when `HistoryDepth` is reduced. + /// + /// Parameters: + /// - `new_history_depth`: The new history depth you would like to set. + /// - `era_items_deleted`: The number of items that will be deleted by this dispatch. + /// This should report all the storage items that will be deleted by clearing old + /// era history. Needed to report an accurate weight for the dispatch. Trusted by + /// `Root` to report an accurate number. /// /// Origin must be root. - #[weight = SimpleDispatchInfo::FixedOperational(500_000)] - fn set_history_depth(origin, #[compact] new_history_depth: EraIndex) { + /// + /// # + /// - E: Number of history depths removed, i.e. 10 -> 7 = 3 + /// - Base Weight: 29.13 * E µs + /// - DB Weight: + /// - Reads: Current Era, History Depth + /// - Writes: History Depth + /// - Clear Prefix Each: Era Stakers, EraStakersClipped, ErasValidatorPrefs + /// - Writes Each: ErasValidatorReward, ErasRewardPoints, ErasTotalStake, ErasStartSessionIndex + /// # + #[weight = { + let items = Weight::from(*_era_items_deleted); + T::DbWeight::get().reads_writes(2, 1) + .saturating_add(T::DbWeight::get().reads_writes(items, items)) + + }] + fn set_history_depth(origin, + #[compact] new_history_depth: EraIndex, + #[compact] _era_items_deleted: u32, + ) { ensure_root(origin)?; if let Some(current_era) = Self::current_era() { HistoryDepth::mutate(|history_depth| { @@ -1767,14 +2151,31 @@ decl_module! { /// This can be called from any origin. /// /// - `stash`: The stash account to reap. Its balance must be zero. - #[weight = frame_support::weights::SimpleDispatchInfo::default()] - fn reap_stash(_origin, stash: T::AccountId) { + /// + /// # + /// Complexity: O(S) where S is the number of slashing spans on the account. + /// Base Weight: 75.94 + 2.396 * S µs + /// DB Weight: + /// - Reads: Stash Account, Bonded, Slashing Spans, Locks + /// - Writes: Bonded, Slashing Spans (if S > 0), Ledger, Payee, Validators, Nominators, Stash Account, Locks + /// - Writes Each: SpanSlash * S + /// # + #[weight = T::DbWeight::get().reads_writes(4, 7) + .saturating_add(76 * WEIGHT_PER_MICROS) + .saturating_add( + WEIGHT_PER_MICROS.saturating_mul(2).saturating_mul(Weight::from(*num_slashing_spans)) + ) + .saturating_add(T::DbWeight::get().writes(Weight::from(*num_slashing_spans))) + // if slashing spans is non-zero, add 1 more write + .saturating_add(T::DbWeight::get().writes(Weight::from(*num_slashing_spans).min(1))) + ] + fn reap_stash(_origin, stash: T::AccountId, num_slashing_spans: u32) { ensure!(T::Currency::total_balance(&stash).is_zero(), Error::::FundedTarget); - Self::kill_stash(&stash)?; + Self::kill_stash(&stash, num_slashing_spans)?; T::Currency::remove_lock(STAKING_ID, &stash); } - /// Submit a phragmen result to the chain. If the solution: + /// Submit an election result to the chain. If the solution: /// /// 1. is valid. /// 2. has a better score than a potentially existing solution on chain. @@ -1787,7 +2188,7 @@ decl_module! { /// 2. `assignments`: the compact version of an assignment vector that encodes the edge /// weights. /// - /// Both of which may be computed using [`phragmen`], or any other algorithm. + /// Both of which may be computed using _phragmen_, or any other algorithm. /// /// Additionally, the submitter must provide: /// @@ -1819,51 +2220,26 @@ decl_module! { /// minimized (to ensure less variance) /// /// # - /// E: number of edges. m: size of winner committee. n: number of nominators. d: edge degree - /// (16 for now) v: number of on-chain validator candidates. - /// - /// NOTE: given a solution which is reduced, we can enable a new check the ensure `|E| < n + - /// m`. We don't do this _yet_, but our offchain worker code executes it nonetheless. - /// - /// major steps (all done in `check_and_replace_solution`): - /// - /// - Storage: O(1) read `ElectionStatus`. - /// - Storage: O(1) read `PhragmenScore`. - /// - Storage: O(1) read `ValidatorCount`. - /// - Storage: O(1) length read from `SnapshotValidators`. - /// - /// - Storage: O(v) reads of `AccountId` to fetch `snapshot_validators`. - /// - Memory: O(m) iterations to map winner index to validator id. - /// - Storage: O(n) reads `AccountId` to fetch `snapshot_nominators`. - /// - Memory: O(n + m) reads to map index to `AccountId` for un-compact. - /// - /// - Storage: O(e) accountid reads from `Nomination` to read correct nominations. - /// - Storage: O(e) calls into `slashable_balance_of_extended` to convert ratio to staked. - /// - /// - Memory: build_support_map. O(e). - /// - Memory: evaluate_support: O(E). - /// - /// - Storage: O(e) writes to `QueuedElected`. - /// - Storage: O(1) write to `QueuedScore` - /// - /// The weight of this call is 1/10th of the blocks total weight. + /// See `crate::weight` module. /// # - #[weight = SimpleDispatchInfo::FixedNormal(100_000_000)] + #[weight = weight::weight_for_submit_solution::(winners, compact, size)] pub fn submit_election_solution( origin, winners: Vec, - compact_assignments: CompactAssignments, - score: PhragmenScore, + compact: CompactAssignments, + score: ElectionScore, era: EraIndex, - ) { + size: ElectionSize, + ) -> DispatchResultWithPostInfo { let _who = ensure_signed(origin)?; Self::check_and_replace_solution( winners, - compact_assignments, + compact, ElectionCompute::Signed, score, era, - )? + size, + ) } /// Unsigned version of `submit_election_solution`. @@ -1871,110 +2247,89 @@ decl_module! { /// Note that this must pass the [`ValidateUnsigned`] check which only allows transactions /// from the local node to be included. In other words, only the block author can include a /// transaction in the block. - #[weight = SimpleDispatchInfo::FixedNormal(100_000_000)] + /// + /// # + /// See `crate::weight` module. + /// # + #[weight = weight::weight_for_submit_solution::(winners, compact, size)] pub fn submit_election_solution_unsigned( origin, winners: Vec, - compact_assignments: CompactAssignments, - score: PhragmenScore, + compact: CompactAssignments, + score: ElectionScore, era: EraIndex, - ) { + size: ElectionSize, + ) -> DispatchResultWithPostInfo { ensure_none(origin)?; - Self::check_and_replace_solution( + let adjustments = Self::check_and_replace_solution( winners, - compact_assignments, + compact, ElectionCompute::Unsigned, score, era, - )? - // TODO: instead of returning an error, panic. This makes the entire produced block - // invalid. - // This ensures that block authors will not ever try and submit a solution which is not - // an improvement, since they will lose their authoring points/rewards. + size, + ).expect( + "An unsigned solution can only be submitted by validators; A validator should \ + always produce correct solutions, else this block should not be imported, thus \ + effectively depriving the validators from their authoring reward. Hence, this panic + is expected." + ); + Ok(adjustments) } } } impl Module { - /// Migrate `last_reward` to `claimed_rewards` - pub fn migrate_last_reward_to_claimed_rewards() { - use frame_support::migration::{StorageIterator, put_storage_value}; - // Migrate from `last_reward` to `claimed_rewards`. - // We will construct a vector from `current_era - history_depth` to `last_reward` - // for each validator and nominator. - // - // Old Staking Ledger - #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] - struct OldStakingLedger { - pub stash: AccountId, - #[codec(compact)] - pub total: Balance, - #[codec(compact)] - pub active: Balance, - pub unlocking: Vec>, - pub last_reward: Option, - } - // Current era and history depth - let current_era = Self::current_era().unwrap_or(0); - let history_depth = Self::history_depth(); - let last_payout_era = current_era.saturating_sub(history_depth); - // Convert all ledgers to the new format. - for (hash, old_ledger) in StorageIterator::>>::new(b"Staking", b"Ledger").drain() { - let last_reward = old_ledger.last_reward.unwrap_or(0); - let new_ledger = StakingLedger { - stash: old_ledger.stash, - total: old_ledger.total, - active: old_ledger.active, - unlocking: old_ledger.unlocking, - claimed_rewards: (last_payout_era..=last_reward).collect(), - }; - put_storage_value(b"Staking", b"Ledger", &hash, new_ledger); - } - MigrateEra::put(current_era); - } - /// The total balance that can be slashed from a stash account as of right now. pub fn slashable_balance_of(stash: &T::AccountId) -> BalanceOf { + // Weight note: consider making the stake accessible through stash. Self::bonded(stash).and_then(Self::ledger).map(|l| l.active).unwrap_or_default() } - /// internal impl of [`slashable_balance_of`] that returns [`ExtendedBalance`]. - fn slashable_balance_of_extended(stash: &T::AccountId) -> ExtendedBalance { - , u64>>::convert( + /// internal impl of [`slashable_balance_of`] that returns [`VoteWeight`]. + fn slashable_balance_of_vote_weight(stash: &T::AccountId) -> VoteWeight { + , VoteWeight>>::convert( Self::slashable_balance_of(stash) - ) as ExtendedBalance + ) } /// Dump the list of validators and nominators into vectors and keep them on-chain. /// /// This data is used to efficiently evaluate election results. returns `true` if the operation /// is successful. - fn create_stakers_snapshot() -> bool { + pub fn create_stakers_snapshot() -> (bool, Weight) { + let mut consumed_weight = 0; + let mut add_db_reads_writes = |reads, writes| { + consumed_weight += T::DbWeight::get().reads_writes(reads, writes); + }; let validators = >::iter().map(|(v, _)| v).collect::>(); let mut nominators = >::iter().map(|(n, _)| n).collect::>(); let num_validators = validators.len(); let num_nominators = nominators.len(); + add_db_reads_writes((num_validators + num_nominators) as Weight, 0); + if num_validators > MAX_VALIDATORS || num_nominators.saturating_add(num_validators) > MAX_NOMINATORS { - debug::native::warn!( - target: "staking", - "Snapshot size too big [{} <> {}][{} <> {}].", + log!( + warn, + "💸 Snapshot size too big [{} <> {}][{} <> {}].", num_validators, MAX_VALIDATORS, num_nominators, MAX_NOMINATORS, ); - false + (false, consumed_weight) } else { // all validators nominate themselves; nominators.extend(validators.clone()); >::put(validators); >::put(nominators); - true + add_db_reads_writes(0, 2); + (true, consumed_weight) } } @@ -1984,150 +2339,16 @@ impl Module { >::kill(); } - fn do_payout_nominator(who: T::AccountId, era: EraIndex, validators: Vec<(T::AccountId, u32)>) - -> DispatchResult - { - // validators len must not exceed `MAX_NOMINATIONS` to avoid querying more validator - // exposure than necessary. - if validators.len() > MAX_NOMINATIONS { - return Err(Error::::InvalidNumberOfNominations.into()); - } - // If migrate_era is not populated, then you should use `payout_stakers` - let migrate_era = MigrateEra::get().ok_or(Error::::InvalidEraToReward)?; - // This payout mechanism will only work for eras before the migration. - // Subsequent payouts should use `payout_stakers`. - ensure!(era < migrate_era, Error::::InvalidEraToReward); - let current_era = CurrentEra::get().ok_or(Error::::InvalidEraToReward)?; - ensure!(era <= current_era, Error::::InvalidEraToReward); - let history_depth = Self::history_depth(); - ensure!(era >= current_era.saturating_sub(history_depth), Error::::InvalidEraToReward); - - // Note: if era has no reward to be claimed, era may be future. better not to update - // `nominator_ledger.last_reward` in this case. - let era_payout = >::get(&era) - .ok_or_else(|| Error::::InvalidEraToReward)?; - - let mut nominator_ledger = >::get(&who).ok_or_else(|| Error::::NotController)?; - - nominator_ledger.claimed_rewards.retain(|&x| x >= current_era.saturating_sub(history_depth)); - match nominator_ledger.claimed_rewards.binary_search(&era) { - Ok(_) => Err(Error::::AlreadyClaimed)?, - Err(pos) => nominator_ledger.claimed_rewards.insert(pos, era), - } - - >::insert(&who, &nominator_ledger); - - let mut reward = Perbill::zero(); - let era_reward_points = >::get(&era); - - for (validator, nominator_index) in validators.into_iter() { - let commission = Self::eras_validator_prefs(&era, &validator).commission; - let validator_exposure = >::get(&era, &validator); - - if let Some(nominator_exposure) = validator_exposure.others - .get(nominator_index as usize) - { - if nominator_exposure.who != nominator_ledger.stash { - continue; - } - - let nominator_exposure_part = Perbill::from_rational_approximation( - nominator_exposure.value, - validator_exposure.total, - ); - let validator_point = era_reward_points.individual.get(&validator) - .map(|points| *points) - .unwrap_or_else(|| Zero::zero()); - let validator_point_part = Perbill::from_rational_approximation( - validator_point, - era_reward_points.total, - ); - reward = reward.saturating_add( - validator_point_part - .saturating_mul(Perbill::one().saturating_sub(commission)) - .saturating_mul(nominator_exposure_part) - ); - } - } - - if let Some(imbalance) = Self::make_payout(&nominator_ledger.stash, reward * era_payout) { - Self::deposit_event(RawEvent::Reward(who, imbalance.peek())); - } - - Ok(()) - } - - fn do_payout_validator(who: T::AccountId, era: EraIndex) -> DispatchResult { - // If migrate_era is not populated, then you should use `payout_stakers` - let migrate_era = MigrateEra::get().ok_or(Error::::InvalidEraToReward)?; - // This payout mechanism will only work for eras before the migration. - // Subsequent payouts should use `payout_stakers`. - ensure!(era < migrate_era, Error::::InvalidEraToReward); - let current_era = CurrentEra::get().ok_or(Error::::InvalidEraToReward)?; - ensure!(era <= current_era, Error::::InvalidEraToReward); - let history_depth = Self::history_depth(); - ensure!(era >= current_era.saturating_sub(history_depth), Error::::InvalidEraToReward); - - // Note: if era has no reward to be claimed, era may be future. better not to update - // `ledger.last_reward` in this case. - let era_payout = >::get(&era) - .ok_or_else(|| Error::::InvalidEraToReward)?; - - let mut ledger = >::get(&who).ok_or_else(|| Error::::NotController)?; - - ledger.claimed_rewards.retain(|&x| x >= current_era.saturating_sub(history_depth)); - match ledger.claimed_rewards.binary_search(&era) { - Ok(_) => Err(Error::::AlreadyClaimed)?, - Err(pos) => ledger.claimed_rewards.insert(pos, era), - } - - >::insert(&who, &ledger); - - let era_reward_points = >::get(&era); - let commission = Self::eras_validator_prefs(&era, &ledger.stash).commission; - let exposure = >::get(&era, &ledger.stash); - - let exposure_part = Perbill::from_rational_approximation( - exposure.own, - exposure.total, - ); - let validator_point = era_reward_points.individual.get(&ledger.stash) - .map(|points| *points) - .unwrap_or_else(|| Zero::zero()); - let validator_point_part = Perbill::from_rational_approximation( - validator_point, - era_reward_points.total, - ); - let reward = validator_point_part.saturating_mul( - commission.saturating_add( - Perbill::one().saturating_sub(commission).saturating_mul(exposure_part) - ) - ); - - if let Some(imbalance) = Self::make_payout(&ledger.stash, reward * era_payout) { - Self::deposit_event(RawEvent::Reward(who, imbalance.peek())); - } - - Ok(()) - } - fn do_payout_stakers( validator_stash: T::AccountId, era: EraIndex, ) -> DispatchResult { - /* Validate input data */ + // Validate input data let current_era = CurrentEra::get().ok_or(Error::::InvalidEraToReward)?; ensure!(era <= current_era, Error::::InvalidEraToReward); let history_depth = Self::history_depth(); ensure!(era >= current_era.saturating_sub(history_depth), Error::::InvalidEraToReward); - // If there was no migration, then this function is always valid. - if let Some(migrate_era) = MigrateEra::get() { - // This payout mechanism will only work for eras on and after the migration. - // Payouts before then should use `payout_nominator`/`payout_validator`. - ensure!(migrate_era <= era, Error::::InvalidEraToReward); - } - // Note: if era has no reward to be claimed, era may be future. better not to update // `ledger.claimed_rewards` in this case. let era_payout = >::get(&era) @@ -2241,7 +2462,7 @@ impl Module { match dest { RewardDestination::Controller => Self::bonded(stash) .and_then(|controller| - T::Currency::deposit_into_existing(&controller, amount).ok() + Some(T::Currency::deposit_creating(&controller, amount)) ), RewardDestination::Stash => T::Currency::deposit_into_existing(stash, amount).ok(), @@ -2276,16 +2497,19 @@ impl Module { Forcing::ForceAlways => (), Forcing::NotForcing if era_length >= T::SessionsPerEra::get() => (), _ => { - // not forcing, not a new era either. If final, set the flag. - if era_length + 1 >= T::SessionsPerEra::get() { + // Either `ForceNone`, or `NotForcing && era_length < T::SessionsPerEra::get()`. + if era_length + 1 == T::SessionsPerEra::get() { IsCurrentSessionFinal::put(true); + } else if era_length >= T::SessionsPerEra::get() { + // Should only happen when we are ready to trigger an era but we have ForceNone, + // otherwise previous arm would short circuit. + Self::close_election_window(); } return None }, } // new era. - IsCurrentSessionFinal::put(false); Self::new_era(session_index) } else { // Set initial era @@ -2294,31 +2518,36 @@ impl Module { } /// Basic and cheap checks that we perform in validate unsigned, and in the execution. - pub fn pre_dispatch_checks(score: PhragmenScore, era: EraIndex) -> Result<(), Error> { + /// + /// State reads: ElectionState, CurrentEr, QueuedScore. + /// + /// This function does weight refund in case of errors, which is based upon the fact that it is + /// called at the very beginning of the call site's function. + pub fn pre_dispatch_checks(score: ElectionScore, era: EraIndex) -> DispatchResultWithPostInfo { // discard solutions that are not in-time // check window open ensure!( Self::era_election_status().is_open(), - Error::::PhragmenEarlySubmission, + Error::::PhragmenEarlySubmission.with_weight(T::DbWeight::get().reads(1)), ); // check current era. - if let Some(current_era) = Self::active_era().map(|e| e.index) { + if let Some(current_era) = Self::current_era() { ensure!( current_era == era, - Error::::PhragmenEarlySubmission, + Error::::PhragmenEarlySubmission.with_weight(T::DbWeight::get().reads(2)), ) } // assume the given score is valid. Is it better than what we have on-chain, if we have any? if let Some(queued_score) = Self::queued_score() { ensure!( - is_score_better(queued_score, score), - Error::::PhragmenWeakSubmission, + is_score_better(score, queued_score, T::MinSolutionScoreBump::get()), + Error::::PhragmenWeakSubmission.with_weight(T::DbWeight::get().reads(3)), ) } - Ok(()) + Ok(None.into()) } /// Checks a given solution and if correct and improved, writes it on chain as the queued result @@ -2327,20 +2556,48 @@ impl Module { winners: Vec, compact_assignments: CompactAssignments, compute: ElectionCompute, - claimed_score: PhragmenScore, + claimed_score: ElectionScore, era: EraIndex, - ) -> Result<(), Error> { + election_size: ElectionSize, + ) -> DispatchResultWithPostInfo { // Do the basic checks. era, claimed score and window open. Self::pre_dispatch_checks(claimed_score, era)?; + // the weight that we will refund in case of a correct submission. We compute this now + // because the data needed for it will be consumed further down. + let adjusted_weight = weight::weight_for_correct_submit_solution::( + &winners, + &compact_assignments, + &election_size, + ); // Check that the number of presented winners is sane. Most often we have more candidates - // that we need. Then it should be Self::validator_count(). Else it should be all the + // than we need. Then it should be `Self::validator_count()`. Else it should be all the // candidates. - let snapshot_length = >::decode_len() - .map_err(|_| Error::::SnapshotUnavailable)?; - let desired_winners = Self::validator_count().min(snapshot_length as u32); + let snapshot_validators_length = >::decode_len() + .map(|l| l as u32) + .ok_or_else(|| Error::::SnapshotUnavailable)?; + + // size of the solution must be correct. + ensure!( + snapshot_validators_length == u32::from(election_size.validators), + Error::::PhragmenBogusElectionSize, + ); + + // check the winner length only here and when we know the length of the snapshot validators + // length. + let desired_winners = Self::validator_count().min(snapshot_validators_length); ensure!(winners.len() as u32 == desired_winners, Error::::PhragmenBogusWinnerCount); + let snapshot_nominators_len = >::decode_len() + .map(|l| l as u32) + .ok_or_else(|| Error::::SnapshotUnavailable)?; + + // rest of the size of the solution must be correct. + ensure!( + snapshot_nominators_len == election_size.nominators, + Error::::PhragmenBogusElectionSize, + ); + // decode snapshot validators. let snapshot_validators = Self::snapshot_validators() .ok_or(Error::::SnapshotUnavailable)?; @@ -2354,7 +2611,7 @@ impl Module { }).collect::, Error>>()?; // decode the rest of the snapshot. - let snapshot_nominators = >::snapshot_nominators() + let snapshot_nominators = Self::snapshot_nominators() .ok_or(Error::::SnapshotUnavailable)?; // helpers @@ -2371,11 +2628,7 @@ impl Module { validator_at, ).map_err(|e| { // log the error since it is not propagated into the runtime error. - debug::native::warn!( - target: "staking", - "un-compacting solution failed due to {:?}", - e, - ); + log!(warn, "💸 un-compacting solution failed due to {:?}", e); Error::::PhragmenBogusCompact })?; @@ -2390,12 +2643,9 @@ impl Module { // all of the indices must map to either a validator or a nominator. If this is ever // not the case, then the locking system of staking is most likely faulty, or we // have bigger problems. - debug::native::error!( - target: "staking", - "detected an error in the staking locking and snapshot." - ); + log!(error, "💸 detected an error in the staking locking and snapshot."); // abort. - return Err(Error::::PhragmenBogusNominator); + return Err(Error::::PhragmenBogusNominator.into()); } if !is_validator { @@ -2412,14 +2662,14 @@ impl Module { // each target in the provided distribution must be actually nominated by the // nominator after the last non-zero slash. if nomination.targets.iter().find(|&tt| tt == t).is_none() { - return Err(Error::::PhragmenBogusNomination); + return Err(Error::::PhragmenBogusNomination.into()); } if ::SlashingSpans::get(&t).map_or( false, |spans| nomination.submitted_in < spans.last_nonzero_slash(), ) { - return Err(Error::::PhragmenSlashedNomination); + return Err(Error::::PhragmenSlashedNomination.into()); } } } else { @@ -2436,9 +2686,9 @@ impl Module { } // convert into staked assignments. - let staked_assignments = sp_phragmen::assignment_ratio_to_staked( + let staked_assignments = sp_npos_elections::assignment_ratio_to_staked( assignments, - Self::slashable_balance_of_extended, + Self::slashable_balance_of_vote_weight, ); // build the support map thereof in order to evaluate. @@ -2457,10 +2707,11 @@ impl Module { // At last, alles Ok. Exposures and store the result. let exposures = Self::collect_exposure(supports); - debug::native::info!( - target: "staking", - "A better solution (with compute {:?}) has been validated and stored on chain.", + log!( + info, + "💸 A better solution (with compute {:?} and score {:?}) has been validated and stored on chain.", compute, + submitted_score, ); // write new results. @@ -2471,8 +2722,10 @@ impl Module { }); QueuedScore::put(submitted_score); - Ok(()) + // emit event. + Self::deposit_event(RawEvent::SolutionStored(compute)); + Ok(Some(adjusted_weight).into()) } /// Start a session potentially starting an era. @@ -2553,16 +2806,20 @@ impl Module { let now_as_millis_u64 = T::UnixTime::now().as_millis().saturated_into::(); let era_duration = now_as_millis_u64 - active_era_start; - let (total_payout, _max_payout) = inflation::compute_total_payout( + let (validator_payout, max_payout) = inflation::compute_total_payout( &T::RewardCurve::get(), Self::eras_total_stake(&active_era.index), T::Currency::total_issuance(), // Duration of era; more than u64::MAX is rewarded as u64::MAX. era_duration.saturated_into::(), ); + let rest = max_payout.saturating_sub(validator_payout); + + Self::deposit_event(RawEvent::EraPayout(active_era.index, validator_payout, rest)); // Set ending era reward. - >::insert(&active_era.index, total_payout); + >::insert(&active_era.index, validator_payout); + T::RewardRemainder::on_unbalanced(T::Currency::issue(rest)); } } @@ -2586,6 +2843,17 @@ impl Module { maybe_new_validators } + + /// Remove all the storage items associated with the election. + fn close_election_window() { + // Close window. + >::put(ElectionStatus::Closed); + // Kill snapshots. + Self::kill_stakers_snapshot(); + // Don't track final session. + IsCurrentSessionFinal::put(false); + } + /// Select the new validator set at the end of the era. /// /// Runs [`try_do_phragmen`] and updates the following storage items: @@ -2606,12 +2874,9 @@ impl Module { elected_stashes, exposures, compute, - }) = Self::try_do_phragmen() { - // We have chosen the new validator set. Submission is no longer allowed. - >::put(ElectionStatus::Closed); - - // kill the snapshots. - Self::kill_stakers_snapshot(); + }) = Self::try_do_election() { + // Totally close the election round and data. + Self::close_election_window(); // Populate Stakers and write slot stake. let mut total_stake: BalanceOf = Zero::zero(); @@ -2640,9 +2905,9 @@ impl Module { // emit event Self::deposit_event(RawEvent::StakingElection(compute)); - debug::native::info!( - target: "staking", - "new validator set of size {:?} has been elected via {:?} for era {:?}", + log!( + info, + "💸 new validator set of size {:?} has been elected via {:?} for era {:?}", elected_stashes.len(), compute, current_era, @@ -2655,12 +2920,12 @@ impl Module { } /// Select a new validator set from the assembled stakers and their role preferences. It tries - /// first to peek into [`QueuedElected`]. Otherwise, it runs a new phragmen. + /// first to peek into [`QueuedElected`]. Otherwise, it runs a new on-chain phragmen election. /// /// If [`QueuedElected`] and [`QueuedScore`] exists, they are both removed. No further storage /// is updated. - fn try_do_phragmen() -> Option>> { - // a phragmen result from either a stored submission or locally executed one. + fn try_do_election() -> Option>> { + // an election result from either a stored submission or locally executed one. let next_result = >::take().or_else(|| Self::do_phragmen_with_post_processing::(ElectionCompute::OnChain) ); @@ -2672,11 +2937,11 @@ impl Module { next_result } - /// Execute phragmen and return the new results. The edge weights are processed into support + /// Execute election and return the new results. The edge weights are processed into support /// values. /// - /// This is basically a wrapper around [`do_phragmen`] which translates `PhragmenResult` into - /// `ElectionResult`. + /// This is basically a wrapper around [`do_phragmen`] which translates + /// `PrimitiveElectionResult` into `ElectionResult`. /// /// No storage item is updated. fn do_phragmen_with_post_processing(compute: ElectionCompute) @@ -2691,9 +2956,9 @@ impl Module { .collect::>(); let assignments = phragmen_result.assignments; - let staked_assignments = sp_phragmen::assignment_ratio_to_staked( + let staked_assignments = sp_npos_elections::assignment_ratio_to_staked( assignments, - Self::slashable_balance_of_extended, + Self::slashable_balance_of_vote_weight, ); let (supports, _) = build_support_map::( @@ -2722,18 +2987,18 @@ impl Module { } } - /// Execute phragmen and return the new results. No post-processing is applied and the raw edge - /// weights are returned. + /// Execute phragmen election and return the new results. No post-processing is applied and the + /// raw edge weights are returned. /// /// Self votes are added and nominations before the most recent slashing span are reaped. /// /// No storage item is updated. - fn do_phragmen() -> Option> { - let mut all_nominators: Vec<(T::AccountId, BalanceOf, Vec)> = Vec::new(); + fn do_phragmen() -> Option> { + let mut all_nominators: Vec<(T::AccountId, VoteWeight, Vec)> = Vec::new(); let mut all_validators = Vec::new(); for (validator, _) in >::iter() { // append self vote - let self_vote = (validator.clone(), Self::slashable_balance_of(&validator), vec![validator.clone()]); + let self_vote = (validator.clone(), Self::slashable_balance_of_vote_weight(&validator), vec![validator.clone()]); all_nominators.push(self_vote); all_validators.push(validator); } @@ -2753,11 +3018,11 @@ impl Module { (nominator, targets) }); all_nominators.extend(nominator_votes.map(|(n, ns)| { - let s = Self::slashable_balance_of(&n); + let s = Self::slashable_balance_of_vote_weight(&n); (n, s, ns) })); - elect::<_, _, T::CurrencyToVote, Accuracy>( + seq_phragmen::<_, Accuracy>( Self::validator_count() as usize, Self::minimum_validator_count().max(1) as usize, all_validators, @@ -2765,14 +3030,14 @@ impl Module { ) } - /// Consume a set of [`Supports`] from [`sp_phragmen`] and collect them into a [`Exposure`] + /// Consume a set of [`Supports`] from [`sp_npos_elections`] and collect them into a [`Exposure`] fn collect_exposure(supports: SupportMap) -> Vec<(T::AccountId, Exposure>)> { let to_balance = |e: ExtendedBalance| >>::convert(e); supports.into_iter().map(|(validator, support)| { // build `struct exposure` from `support` - let mut others = Vec::new(); + let mut others = Vec::with_capacity(support.voters.len()); let mut own: BalanceOf = Zero::zero(); let mut total: BalanceOf = Zero::zero(); support.voters @@ -2804,16 +3069,18 @@ impl Module { /// This is called: /// - after a `withdraw_unbond()` call that frees all of a stash's bonded balance. /// - through `reap_stash()` if the balance has fallen to zero (through slashing). - fn kill_stash(stash: &T::AccountId) -> DispatchResult { - let controller = Bonded::::take(stash).ok_or(Error::::NotStash)?; + fn kill_stash(stash: &T::AccountId, num_slashing_spans: u32) -> DispatchResult { + let controller = >::get(stash).ok_or(Error::::NotStash)?; + + slashing::clear_stash_metadata::(stash, num_slashing_spans)?; + + >::remove(stash); >::remove(&controller); >::remove(stash); >::remove(stash); >::remove(stash); - slashing::clear_stash_metadata::(stash); - system::Module::::dec_ref(stash); Ok(()) @@ -2878,6 +3145,29 @@ impl Module { _ => ForceEra::put(Forcing::ForceNew), } } + + fn will_era_be_forced() -> bool { + match ForceEra::get() { + Forcing::ForceAlways | Forcing::ForceNew => true, + Forcing::ForceNone | Forcing::NotForcing => false, + } + } + + #[cfg(feature = "runtime-benchmarks")] + pub fn add_era_stakers(current_era: EraIndex, controller: T::AccountId, exposure: Exposure>) { + >::insert(¤t_era, &controller, &exposure); + } + + #[cfg(feature = "runtime-benchmarks")] + pub fn put_election_status(status: ElectionStatus::) { + >::put(status); + } + + #[cfg(feature = "runtime-benchmarks")] + pub fn set_slash_reward_fraction(fraction: Perbill) { + SlashRewardFraction::put(fraction); + } + } /// In this implementation `new_session(session)` must be called before `end_session(session-1)` @@ -2969,7 +3259,9 @@ impl Convert> } /// This is intended to be used with `FilterHistoricalOffences`. -impl OnOffenceHandler> for Module where +impl + OnOffenceHandler, Weight> +for Module where T: pallet_session::Trait::AccountId>, T: pallet_session::historical::Trait< FullIdentification = Exposure<::AccountId, BalanceOf>, @@ -2977,24 +3269,32 @@ impl OnOffenceHandler, T::SessionHandler: pallet_session::SessionHandler<::AccountId>, T::SessionManager: pallet_session::SessionManager<::AccountId>, - T::ValidatorIdOf: Convert<::AccountId, Option<::AccountId>> + T::ValidatorIdOf: Convert< + ::AccountId, + Option<::AccountId>, + >, { fn on_offence( offenders: &[OffenceDetails>], slash_fraction: &[Perbill], slash_session: SessionIndex, - ) -> Result<(), ()> { + ) -> Result { if !Self::can_report() { return Err(()) } let reward_proportion = SlashRewardFraction::get(); + let mut consumed_weight: Weight = 0; + let mut add_db_reads_writes = |reads, writes| { + consumed_weight += T::DbWeight::get().reads_writes(reads, writes); + }; let active_era = { let active_era = Self::active_era(); + add_db_reads_writes(1, 0); if active_era.is_none() { // this offence need not be re-submitted. - return Ok(()) + return Ok(consumed_weight) } active_era.expect("value checked not to be `None`; qed").index }; @@ -3003,6 +3303,7 @@ impl OnOffenceHandler OnOffenceHandler return Ok(()), // before bonding period. defensive - should be filtered out. Some(&(ref slash_era, _)) => *slash_era, + // before bonding period. defensive - should be filtered out. + None => return Ok(consumed_weight), } }; @@ -3025,14 +3328,18 @@ impl OnOffenceHandler OnOffenceHandler(unapplied); + { + let slash_cost = (6, 5); + let reward_cost = (2, 2); + add_db_reads_writes( + (1 + nominators_len) * slash_cost.0 + reward_cost.0 * reporters_len, + (1 + nominators_len) * slash_cost.1 + reward_cost.1 * reporters_len + ); + } } else { // defer to end of some `slash_defer_duration` from now. ::UnappliedSlashes::mutate( active_era, move |for_later| for_later.push(unapplied), ); + add_db_reads_writes(1, 1); } + } else { + add_db_reads_writes(4 /* fetch_spans */, 5 /* kick_out_if_recent */) } } - Ok(()) + Ok(consumed_weight) } fn can_report() -> bool { @@ -3094,84 +3420,9 @@ impl ReportOffence Ok(()) } } -} - -/// Disallows any transactions that change the election result to be submitted after the election -/// window is open. -#[derive(Encode, Decode, Clone, Eq, PartialEq)] -pub struct LockStakingStatus(sp_std::marker::PhantomData); - -impl sp_std::fmt::Debug for LockStakingStatus { - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - write!(f, "LockStakingStatus") - } -} - -impl LockStakingStatus { - /// Create new `LockStakingStatus`. - pub fn new() -> Self { - Self(sp_std::marker::PhantomData) - } -} - -impl Default for LockStakingStatus { - fn default() -> Self { - Self::new() - } -} - -impl SignedExtension for LockStakingStatus { - const IDENTIFIER: &'static str = "LockStakingStatus"; - type AccountId = T::AccountId; - type Call = ::Call; - type AdditionalSigned = (); - type DispatchInfo = frame_support::weights::DispatchInfo; - type Pre = (); - - fn additional_signed(&self) -> Result<(), TransactionValidityError> { Ok(()) } - - fn validate( - &self, - _who: &Self::AccountId, - call: &Self::Call, - _info: Self::DispatchInfo, - _len: usize, - ) -> TransactionValidity { - if let Some(inner_call) = call.is_sub_type() { - if let ElectionStatus::Open(_) = >::era_election_status() { - match inner_call { - Call::::set_payee(..) | - Call::::set_controller(..) | - Call::::set_validator_count(..) | - Call::::force_no_eras(..) | - Call::::force_new_era(..) | - Call::::set_invulnerables(..) | - Call::::force_unstake(..) | - Call::::force_new_era_always(..) | - Call::::cancel_deferred_slash(..) | - Call::::set_history_depth(..) | - Call::::reap_stash(..) | - Call::::submit_election_solution(..) | - Call::::submit_election_solution_unsigned(..) => { - // These calls are allowed. Nothing. - } - _ => { - return Err(InvalidTransaction::Stale.into()); - } - } - } - } - - Ok(Default::default()) - } -} -impl From> for InvalidTransaction { - fn from(e: Error) -> Self { - match e { - >::PhragmenEarlySubmission => InvalidTransaction::Future, - _ => InvalidTransaction::Custom(e.as_u8()), - } + fn is_known_offence(offenders: &[Offender], time_slot: &O::TimeSlot) -> bool { + R::is_known_offence(offenders, time_slot) } } @@ -3184,6 +3435,7 @@ impl frame_support::unsigned::ValidateUnsigned for Module { _, score, era, + _, ) = call { use offchain_election::DEFAULT_LONGEVITY; @@ -3191,60 +3443,68 @@ impl frame_support::unsigned::ValidateUnsigned for Module { match source { TransactionSource::Local | TransactionSource::InBlock => { /* allowed */ } _ => { - debug::native::debug!( - target: "staking", - "rejecting unsigned transaction because it is not local/in-block." - ); + log!(debug, "rejecting unsigned transaction because it is not local/in-block."); return InvalidTransaction::Call.into(); } } - if let Err(e) = Self::pre_dispatch_checks(*score, *era) { - debug::native::debug!( - target: "staking", - "validate unsigned failed due to {:?}.", - e, + if let Err(error_with_post_info) = Self::pre_dispatch_checks(*score, *era) { + let invalid = to_invalid(error_with_post_info); + log!( + debug, + "validate unsigned pre dispatch checks failed due to error #{:?}.", + invalid, ); - let invalid: InvalidTransaction = e.into(); - return invalid.into(); + return invalid .into(); } - debug::native::debug!( - target: "staking", - "Validated an unsigned transaction from the local node for era {}.", - era, - ); + log!(debug, "validateUnsigned succeeded for a solution at era {}.", era); - Ok(ValidTransaction { + ValidTransaction::with_tag_prefix("StakingOffchain") // The higher the score[0], the better a solution is. - priority: score[0].saturated_into(), - // no requires. - requires: vec![], + .priority(T::UnsignedPriority::get().saturating_add(score[0].saturated_into())) // Defensive only. A single solution can exist in the pool per era. Each validator // will run OCW at most once per era, hence there should never exist more than one // transaction anyhow. - provides: vec![("StakingOffchain", era).encode()], + .and_provides(era) // Note: this can be more accurate in the future. We do something like // `era_end_block - current_block` but that is not needed now as we eagerly run // offchain workers now and the above should be same as `T::ElectionLookahead` // without the need to query more storage in the validation phase. If we randomize // offchain worker, then we might re-consider this. - longevity: TryInto::::try_into(T::ElectionLookahead::get()).unwrap_or(DEFAULT_LONGEVITY), + .longevity(TryInto::::try_into( + T::ElectionLookahead::get()).unwrap_or(DEFAULT_LONGEVITY) + ) // We don't propagate this. This can never the validated at a remote node. - propagate: false, - }) + .propagate(false) + .build() } else { InvalidTransaction::Call.into() } } - fn pre_dispatch(_: &Self::Call) -> Result<(), TransactionValidityError> { - // IMPORTANT NOTE: By default, a sane `pre-dispatch` should always do the same checks as - // `validate_unsigned` and overriding this should be done with care. this module has only - // one unsigned entry point, in which we call into `>::pre_dispatch_checks()` - // which is all the important checks that we do in `validate_unsigned`. Hence, we can safely - // override this to save some time. - Ok(()) + fn pre_dispatch(call: &Self::Call) -> Result<(), TransactionValidityError> { + if let Call::submit_election_solution_unsigned( + _, + _, + score, + era, + _, + ) = call { + // IMPORTANT NOTE: These checks are performed in the dispatch call itself, yet we need + // to duplicate them here to prevent a block producer from putting a previously + // validated, yet no longer valid solution on chain. + // OPTIMISATION NOTE: we could skip this in the `submit_election_solution_unsigned` + // since we already do it here. The signed version needs it though. Yer for now we keep + // this duplicate check here so both signed and unsigned can use a singular + // `check_and_replace_solution`. + Self::pre_dispatch_checks(*score, *era) + .map(|_| ()) + .map_err(to_invalid) + .map_err(Into::into) + } else { + Err(InvalidTransaction::Call.into()) + } } } @@ -3252,3 +3512,14 @@ impl frame_support::unsigned::ValidateUnsigned for Module { fn is_sorted_and_unique(list: &[u32]) -> bool { list.windows(2).all(|w| w[0] < w[1]) } + +/// convert a DispatchErrorWithPostInfo to a custom InvalidTransaction with the inner code being the +/// error number. +fn to_invalid(error_with_post_info: DispatchErrorWithPostInfo) -> InvalidTransaction { + let error = error_with_post_info.error; + let error_number = match error { + DispatchError::Module { error, ..} => error, + _ => 0, + }; + InvalidTransaction::Custom(error_number) +} diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index f8123416534ab44be108776e004cde7bba16e9bb..34f2d001a0e861b473a0d7c77d710c330c502e29 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -1,22 +1,23 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utilities -use std::{collections::{HashSet, HashMap}, cell::RefCell}; +use std::{collections::HashSet, cell::RefCell}; use sp_runtime::Perbill; use sp_runtime::curve::PiecewiseLinear; use sp_runtime::traits::{IdentityLookup, Convert, SaturatedConversion, Zero}; @@ -27,43 +28,44 @@ use frame_support::{ assert_ok, impl_outer_origin, parameter_types, impl_outer_dispatch, impl_outer_event, StorageValue, StorageMap, StorageDoubleMap, IterableStorageMap, traits::{Currency, Get, FindAuthor, OnFinalize, OnInitialize}, - weights::Weight, + weights::{Weight, constants::RocksDbWeight}, }; -use frame_system::offchain::TransactionSubmitter; use sp_io; -use sp_phragmen::{ - build_support_map, evaluate_support, reduce, ExtendedBalance, StakedAssignment, PhragmenScore, +use sp_npos_elections::{ + build_support_map, evaluate_support, reduce, ExtendedBalance, StakedAssignment, ElectionScore, + VoteWeight, }; use crate::*; -const INIT_TIMESTAMP: u64 = 30_000; +pub const INIT_TIMESTAMP: u64 = 30_000; /// The AccountId alias in this test module. pub(crate) type AccountId = u64; pub(crate) type AccountIndex = u64; pub(crate) type BlockNumber = u64; -pub(crate) type Balance = u64; +pub(crate) type Balance = u128; /// 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: Balance) -> u64 { + x.saturated_into() } } -impl Convert for CurrencyToVoteHandler { - fn convert(x: u128) -> u64 { - x.saturated_into() +impl Convert for CurrencyToVoteHandler { + fn convert(x: u128) -> Balance { + x } } thread_local! { static SESSION: RefCell<(Vec, HashSet)> = RefCell::new(Default::default()); static SESSION_PER_ERA: RefCell = RefCell::new(3); - static EXISTENTIAL_DEPOSIT: RefCell = RefCell::new(0); + static EXISTENTIAL_DEPOSIT: RefCell = RefCell::new(0); static SLASH_DEFER_DURATION: RefCell = RefCell::new(0); static ELECTION_LOOKAHEAD: RefCell = RefCell::new(0); static PERIOD: RefCell = RefCell::new(1); + static MAX_ITERATIONS: RefCell = RefCell::new(0); } /// Another session handler struct to test on_disabled. @@ -104,8 +106,8 @@ pub fn is_disabled(controller: AccountId) -> bool { } pub struct ExistentialDeposit; -impl Get for ExistentialDeposit { - fn get() -> u64 { +impl Get for ExistentialDeposit { + fn get() -> Balance { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow()) } } @@ -143,6 +145,13 @@ impl Get for SlashDeferDuration { } } +pub struct MaxIterations; +impl Get for MaxIterations { + fn get() -> u32 { + MAX_ITERATIONS.with(|v| *v.borrow()) + } +} + impl_outer_origin! { pub enum Origin for Test where system = frame_system {} } @@ -172,8 +181,8 @@ impl_outer_event! { /// Author of block is always 11 pub struct Author11; -impl FindAuthor for Author11 { - fn find_author<'a, I>(_digests: I) -> Option +impl FindAuthor for Author11 { + fn find_author<'a, I>(_digests: I) -> Option where I: 'a + IntoIterator, { Some(11) @@ -191,6 +200,7 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = AccountIndex; type BlockNumber = BlockNumber; @@ -203,13 +213,18 @@ impl frame_system::Trait for Test { type Event = MetaEvent; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = RocksDbWeight; + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); type ModuleToIndex = (); - type AccountData = pallet_balances::AccountData; + type AccountData = pallet_balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } impl pallet_balances::Trait for Test { type Balance = Balance; @@ -217,6 +232,7 @@ impl pallet_balances::Trait for Test { type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; + type WeightInfo = (); } parameter_types! { pub const Offset: BlockNumber = 0; @@ -238,6 +254,7 @@ impl pallet_session::Trait for Test { type ValidatorIdOf = crate::StashOf; type DisabledValidatorsThreshold = DisabledValidatorsThreshold; type NextSessionRotation = pallet_session::PeriodicSessions; + type WeightInfo = (); } impl pallet_session::historical::Trait for Test { @@ -257,6 +274,7 @@ impl pallet_timestamp::Trait for Test { type Moment = u64; type OnTimestampSet = (); type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); } pallet_staking_reward_curve::build! { const I_NPOS: PiecewiseLinear<'static> = curve!( @@ -272,13 +290,30 @@ parameter_types! { pub const BondingDuration: EraIndex = 3; pub const RewardCurve: &'static PiecewiseLinear<'static> = &I_NPOS; pub const MaxNominatorRewardedPerValidator: u32 = 64; + pub const UnsignedPriority: u64 = 1 << 20; + pub const MinSolutionScoreBump: Perbill = Perbill::zero(); +} + +thread_local! { + pub static REWARD_REMAINDER_UNBALANCED: RefCell = RefCell::new(0); +} + +pub struct RewardRemainderMock; + +impl OnUnbalanced> for RewardRemainderMock { + fn on_nonzero_unbalanced(amount: NegativeImbalanceOf) { + REWARD_REMAINDER_UNBALANCED.with(|v| { + *v.borrow_mut() += amount.peek(); + }); + drop(amount); + } } impl Trait for Test { type Currency = Balances; type UnixTime = Timestamp; type CurrencyToVote = CurrencyToVoteHandler; - type RewardRemainder = (); + type RewardRemainder = RewardRemainderMock; type Event = MetaEvent; type Slash = (); type Reward = (); @@ -291,12 +326,21 @@ impl Trait for Test { type NextNewSession = Session; type ElectionLookahead = ElectionLookahead; type Call = Call; - type SubmitTransaction = SubmitTransaction; + type MaxIterations = MaxIterations; + type MinSolutionScoreBump = MinSolutionScoreBump; type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; + type UnsignedPriority = UnsignedPriority; + type WeightInfo = (); +} + +impl frame_system::offchain::SendTransactionTypes for Test where + Call: From, +{ + type OverarchingCall = Call; + type Extrinsic = Extrinsic; } pub type Extrinsic = TestXt; -type SubmitTransaction = TransactionSubmitter<(), Test, Extrinsic>; pub struct ExtBuilder { session_length: BlockNumber, @@ -312,6 +356,7 @@ pub struct ExtBuilder { num_validators: Option, invulnerables: Vec, has_stakers: bool, + max_offchain_iterations: u32, } impl Default for ExtBuilder { @@ -330,12 +375,13 @@ impl Default for ExtBuilder { num_validators: None, invulnerables: vec![], has_stakers: true, + max_offchain_iterations: 0, } } } impl ExtBuilder { - pub fn existential_deposit(mut self, existential_deposit: u64) -> Self { + pub fn existential_deposit(mut self, existential_deposit: Balance) -> Self { self.existential_deposit = existential_deposit; self } @@ -367,7 +413,7 @@ impl ExtBuilder { self.num_validators = Some(num_validators); self } - pub fn invulnerables(mut self, invulnerables: Vec) -> Self { + pub fn invulnerables(mut self, invulnerables: Vec) -> Self { self.invulnerables = invulnerables; self } @@ -387,6 +433,10 @@ impl ExtBuilder { self.has_stakers = has; self } + pub fn max_offchain_iterations(mut self, iterations: u32) -> Self { + self.max_offchain_iterations = iterations; + self + } pub fn offchain_phragmen_ext(self) -> Self { self.session_per_era(4) .session_length(5) @@ -398,6 +448,7 @@ impl ExtBuilder { SESSION_PER_ERA.with(|v| *v.borrow_mut() = self.session_per_era); ELECTION_LOOKAHEAD.with(|v| *v.borrow_mut() = self.election_lookahead); PERIOD.with(|v| *v.borrow_mut() = self.session_length); + MAX_ITERATIONS.with(|v| *v.borrow_mut() = self.max_offchain_iterations); } pub fn build(self) -> sp_io::TestExternalities { let _ = env_logger::try_init(); @@ -413,7 +464,7 @@ impl ExtBuilder { let num_validators = self.num_validators.unwrap_or(self.validator_count); let validators = (0..num_validators) - .map(|x| ((x + 1) * 10 + 1) as u64) + .map(|x| ((x + 1) * 10 + 1) as AccountId) .collect::>(); let _ = pallet_balances::GenesisConfig:: { @@ -432,7 +483,7 @@ impl ExtBuilder { (41, balance_factor * 2000), (100, 2000 * balance_factor), (101, 2000 * balance_factor), - // This allow us to have a total_payout different from 0. + // This allows us to have a total_payout different from 0. (999, 1_000_000_000_000), ], }.assimilate_storage(&mut storage); @@ -471,7 +522,7 @@ impl ExtBuilder { keys: validators.iter().map(|x| ( *x, *x, - SessionKeys { other: UintAuthorityId(*x) } + SessionKeys { other: UintAuthorityId(*x as u64) } )).collect(), }.assimilate_storage(&mut storage); @@ -491,6 +542,11 @@ impl ExtBuilder { ext } + pub fn build_and_execute(self, test: impl FnOnce() -> ()) { + let mut ext = self.build(); + ext.execute_with(test); + ext.execute_with(post_conditions); + } } pub type System = frame_system::Module; @@ -499,61 +555,92 @@ pub type Session = pallet_session::Module; pub type Timestamp = pallet_timestamp::Module; pub type Staking = Module; -pub fn active_era() -> EraIndex { - Staking::active_era().unwrap().index +pub(crate) fn current_era() -> EraIndex { + Staking::current_era().unwrap() } -pub fn check_exposure_all(era: EraIndex) { - ErasStakers::::iter_prefix(era).for_each(check_exposure) +fn post_conditions() { + check_nominators(); + check_exposures(); + check_ledgers(); } -pub fn check_nominator_all(era: EraIndex) { - >::iter() - .for_each(|(acc, _)| check_nominator_exposure(era, acc)); +pub(crate) fn active_era() -> EraIndex { + Staking::active_era().unwrap().index } -/// Check for each selected validator: expo.total = Sum(expo.other) + expo.own -pub fn check_exposure(expo: Exposure) { - assert_eq!( - expo.total as u128, - expo.own as u128 + expo.others.iter().map(|e| e.value as u128).sum::(), - "wrong total exposure", - ); +fn check_ledgers() { + // check the ledger of all stakers. + Bonded::::iter().for_each(|(_, ctrl)| assert_ledger_consistent(ctrl)) } -/// Check that for each nominator: slashable_balance > sum(used_balance) -/// Note: we might not consume all of a nominator's balance, but we MUST NOT over spend it. -pub fn check_nominator_exposure(era: EraIndex, stash: AccountId) { - assert_is_stash(stash); - let mut sum = 0; - Session::validators() - .iter() - .map(|v| Staking::eras_stakers(era, v)) - .for_each(|e| e.others.iter().filter(|i| i.who == stash).for_each(|i| sum += i.value)); - let nominator_stake = Staking::slashable_balance_of(&stash); - // a nominator cannot over-spend. - assert!( - nominator_stake >= sum, - "failed: Nominator({}) stake({}) >= sum divided({})", - stash, - nominator_stake, - sum, - ); +fn check_exposures() { + // a check per validator to ensure the exposure struct is always sane. + let era = active_era(); + ErasStakers::::iter_prefix_values(era).for_each(|expo| { + assert_eq!( + expo.total as u128, + expo.own as u128 + expo.others.iter().map(|e| e.value as u128).sum::(), + "wrong total exposure.", + ); + }) } -pub fn assert_is_stash(acc: AccountId) { - assert!(Staking::bonded(&acc).is_some(), "Not a stash."); +fn check_nominators() { + // a check per nominator to ensure their entire stake is correctly distributed. Will only kick- + // in if the nomination was submitted before the current era. + let era = active_era(); + >::iter() + .filter_map(|(nominator, nomination)| + if nomination.submitted_in > era { + Some(nominator) + } else { + None + }) + .for_each(|nominator| { + // must be bonded. + assert_is_stash(nominator); + let mut sum = 0; + Session::validators() + .iter() + .map(|v| Staking::eras_stakers(era, v)) + .for_each(|e| { + let individual = e.others.iter().filter(|e| e.who == nominator).collect::>(); + let len = individual.len(); + match len { + 0 => { /* not supporting this validator at all. */ }, + 1 => sum += individual[0].value, + _ => panic!("nominator cannot back a validator more than once."), + }; + }); + + let nominator_stake = Staking::slashable_balance_of(&nominator); + // a nominator cannot over-spend. + assert!( + nominator_stake >= sum, + "failed: Nominator({}) stake({}) >= sum divided({})", + nominator, + nominator_stake, + sum, + ); + + let diff = nominator_stake - sum; + assert!(diff < 100); + }); } -pub fn assert_ledger_consistent(stash: AccountId) { - assert_is_stash(stash); - let ledger = Staking::ledger(stash - 1).unwrap(); +fn assert_is_stash(acc: AccountId) { + assert!(Staking::bonded(&acc).is_some(), "Not a stash."); +} +fn assert_ledger_consistent(ctrl: AccountId) { + // ensures ledger.total == ledger.active + sum(ledger.unlocking). + let ledger = Staking::ledger(ctrl).expect("Not a controller."); let real_total: Balance = ledger.unlocking.iter().fold(ledger.active, |a, c| a + c.value); assert_eq!(real_total, ledger.total); } -pub fn bond_validator(stash: u64, ctrl: u64, val: u64) { +pub(crate) fn bond_validator(stash: AccountId, ctrl: AccountId, val: Balance) { let _ = Balances::make_free_balance_be(&stash, val); let _ = Balances::make_free_balance_be(&ctrl, val); assert_ok!(Staking::bond( @@ -568,7 +655,12 @@ pub fn bond_validator(stash: u64, ctrl: u64, val: u64) { )); } -pub fn bond_nominator(stash: u64, ctrl: u64, val: u64, target: Vec) { +pub(crate) fn bond_nominator( + stash: AccountId, + ctrl: AccountId, + val: Balance, + target: Vec, +) { let _ = Balances::make_free_balance_be(&stash, val); let _ = Balances::make_free_balance_be(&ctrl, val); assert_ok!(Staking::bond( @@ -580,7 +672,7 @@ pub fn bond_nominator(stash: u64, ctrl: u64, val: u64, target: Vec) { assert_ok!(Staking::nominate(Origin::signed(ctrl), target)); } -pub fn run_to_block(n: BlockNumber) { +pub(crate) fn run_to_block(n: BlockNumber) { Staking::on_finalize(System::block_number()); for b in System::block_number() + 1..=n { System::set_block_number(b); @@ -592,12 +684,12 @@ pub fn run_to_block(n: BlockNumber) { } } -pub fn advance_session() { +pub(crate) fn advance_session() { let current_index = Session::current_index(); start_session(current_index + 1); } -pub fn start_session(session_index: SessionIndex) { +pub(crate) fn start_session(session_index: SessionIndex) { assert_eq!(>::get(), 1, "start_session can only be used with session length 1."); for i in Session::current_index()..session_index { Staking::on_finalize(System::block_number()); @@ -610,12 +702,16 @@ pub fn start_session(session_index: SessionIndex) { assert_eq!(Session::current_index(), session_index); } -pub fn start_era(era_index: EraIndex) { +// This start and activate the era given. +// Because the mock use pallet-session which delays session by one, this will be one session after +// the election happened, not the first session after the election has happened. +pub(crate) fn start_era(era_index: EraIndex) { start_session((era_index * >::get()).into()); assert_eq!(Staking::current_era().unwrap(), era_index); + assert_eq!(Staking::active_era().unwrap().index, era_index); } -pub fn current_total_payout_for_duration(duration: u64) -> u64 { +pub(crate) fn current_total_payout_for_duration(duration: u64) -> Balance { inflation::compute_total_payout( ::RewardCurve::get(), Staking::eras_total_stake(Staking::active_era().unwrap().index), @@ -624,7 +720,7 @@ pub fn current_total_payout_for_duration(duration: u64) -> u64 { ).0 } -pub fn reward_all_elected() { +pub(crate) fn reward_all_elected() { let rewards = ::SessionInterface::validators() .into_iter() .map(|v| (v, 1)); @@ -632,14 +728,14 @@ pub fn reward_all_elected() { >::reward_by_ids(rewards) } -pub fn validator_controllers() -> Vec { +pub(crate) fn validator_controllers() -> Vec { Session::validators() .into_iter() .map(|s| Staking::bonded(&s).expect("no controller for validator")) .collect() } -pub fn on_offence_in_era( +pub(crate) fn on_offence_in_era( offenders: &[OffenceDetails< AccountId, pallet_session::historical::IdentificationTuple, @@ -669,7 +765,7 @@ pub fn on_offence_in_era( } } -pub fn on_offence_now( +pub(crate) fn on_offence_now( offenders: &[OffenceDetails>], slash_fraction: &[Perbill], ) { @@ -677,11 +773,23 @@ pub fn on_offence_now( on_offence_in_era(offenders, slash_fraction, now) } +pub(crate) fn add_slash(who: &AccountId) { + on_offence_now( + &[ + OffenceDetails { + offender: (who.clone(), Staking::eras_stakers(Staking::active_era().unwrap().index, who.clone())), + reporters: vec![], + }, + ], + &[Perbill::from_percent(10)], + ); +} + // winners will be chosen by simply their unweighted total backing stake. Nominator stake is // distributed evenly. -pub fn horrible_phragmen_with_post_processing( +pub(crate) fn horrible_phragmen_with_post_processing( do_reduce: bool, -) -> (CompactAssignments, Vec, PhragmenScore) { +) -> (CompactAssignments, Vec, ElectionScore) { let mut backing_stake_of: BTreeMap = BTreeMap::new(); // self stake @@ -748,12 +856,16 @@ pub fn horrible_phragmen_with_post_processing( // Ensure that this result is worse than seq-phragmen. Otherwise, it should not have been used // for testing. let score = { - let (_, _, better_score) = prepare_submission_with(true, |_| {}); + let (_, _, better_score) = prepare_submission_with(true, 0, |_| {}); let support = build_support_map::(&winners, &staked_assignment).0; let score = evaluate_support(&support); - assert!(sp_phragmen::is_score_better(score, better_score)); + assert!(sp_npos_elections::is_score_better::( + better_score, + score, + MinSolutionScoreBump::get(), + )); score }; @@ -773,7 +885,7 @@ pub fn horrible_phragmen_with_post_processing( // convert back to ratio assignment. This takes less space. let assignments_reduced = - sp_phragmen::assignment_staked_to_ratio::(staked_assignment); + sp_npos_elections::assignment_staked_to_ratio::(staked_assignment); let compact = CompactAssignments::from_assignment(assignments_reduced, nominator_index, validator_index) @@ -787,23 +899,35 @@ pub fn horrible_phragmen_with_post_processing( // Note: this should always logically reproduce [`offchain_election::prepare_submission`], yet we // cannot do it since we want to have `tweak` injected into the process. -pub fn prepare_submission_with( +pub(crate) fn prepare_submission_with( do_reduce: bool, + iterations: usize, tweak: impl FnOnce(&mut Vec>), -) -> (CompactAssignments, Vec, PhragmenScore) { - // run phragmen on the default stuff. - let sp_phragmen::PhragmenResult { +) -> (CompactAssignments, Vec, ElectionScore) { + // run election on the default stuff. + let sp_npos_elections::ElectionResult { winners, assignments, } = Staking::do_phragmen::().unwrap(); - let winners = winners.into_iter().map(|(w, _)| w).collect::>(); + let winners = sp_npos_elections::to_without_backing(winners); - let stake_of = |who: &AccountId| -> ExtendedBalance { - >::convert( + let stake_of = |who: &AccountId| -> VoteWeight { + >::convert( Staking::slashable_balance_of(&who) - ) as ExtendedBalance + ) }; - let mut staked = sp_phragmen::assignment_ratio_to_staked(assignments, stake_of); + + let mut staked = sp_npos_elections::assignment_ratio_to_staked(assignments, stake_of); + let (mut support_map, _) = build_support_map::(&winners, &staked); + + if iterations > 0 { + sp_npos_elections::balance_solution( + &mut staked, + &mut support_map, + Zero::zero(), + iterations, + ); + } // apply custom tweaks. awesome for testing. tweak(&mut staked); @@ -834,13 +958,13 @@ pub fn prepare_submission_with( ) }; - let assignments_reduced = sp_phragmen::assignment_staked_to_ratio(staked); + let assignments_reduced = sp_npos_elections::assignment_staked_to_ratio(staked); // re-compute score by converting, yet again, into staked type let score = { - let staked = sp_phragmen::assignment_ratio_to_staked( + let staked = sp_npos_elections::assignment_ratio_to_staked( assignments_reduced.clone(), - Staking::slashable_balance_of_extended, + Staking::slashable_balance_of_vote_weight, ); let (support_map, _) = build_support_map::( @@ -863,39 +987,7 @@ pub fn prepare_submission_with( } /// Make all validator and nominator request their payment -pub fn make_all_reward_payment_before_migration(era: EraIndex) { - let validators_with_reward = ErasRewardPoints::::get(era).individual.keys() - .cloned() - .collect::>(); - - // reward nominators - let mut nominator_controllers = HashMap::new(); - for validator in Staking::eras_reward_points(era).individual.keys() { - let validator_exposure = Staking::eras_stakers_clipped(era, validator); - for (nom_index, nom) in validator_exposure.others.iter().enumerate() { - if let Some(nom_ctrl) = Staking::bonded(nom.who) { - nominator_controllers.entry(nom_ctrl) - .or_insert(vec![]) - .push((validator.clone(), nom_index as u32)); - } - } - } - for (nominator_controller, validators_with_nom_index) in nominator_controllers { - assert_ok!(Staking::payout_nominator( - Origin::signed(nominator_controller), - era, - validators_with_nom_index, - )); - } - - // reward validators - for validator_controller in validators_with_reward.iter().filter_map(Staking::bonded) { - assert_ok!(Staking::payout_validator(Origin::signed(validator_controller), era)); - } -} - -/// Make all validator and nominator request their payment -pub fn make_all_reward_payment(era: EraIndex) { +pub(crate) fn make_all_reward_payment(era: EraIndex) { let validators_with_reward = ErasRewardPoints::::get(era).individual.keys() .cloned() .collect::>(); @@ -927,3 +1019,17 @@ macro_rules! assert_session_era { ); }; } + +pub(crate) fn staking_events() -> Vec> { + System::events().into_iter().map(|r| r.event).filter_map(|e| { + if let MetaEvent::staking(inner) = e { + Some(inner) + } else { + None + } + }).collect() +} + +pub(crate) fn balances(who: &AccountId) -> (Balance, Balance) { + (Balances::free_balance(who), Balances::reserved_balance(who)) +} diff --git a/frame/staking/src/offchain_election.rs b/frame/staking/src/offchain_election.rs index 0d4cf49f103b9fd634ad178235159244f4f743b2..79f3a5c2d94fec73f2297e6a18de804c8d0f7d2b 100644 --- a/frame/staking/src/offchain_election.rs +++ b/frame/staking/src/offchain_election.rs @@ -1,53 +1,56 @@ -// Copyright 2020 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. +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Helpers for offchain worker election. +use codec::Decode; use crate::{ Call, CompactAssignments, Module, NominatorIndex, OffchainAccuracy, Trait, ValidatorIndex, + ElectionSize, }; -use frame_system::offchain::SubmitUnsignedTransaction; -use sp_phragmen::{ - build_support_map, evaluate_support, reduce, Assignment, ExtendedBalance, PhragmenResult, - PhragmenScore, +use frame_system::offchain::SubmitTransaction; +use sp_npos_elections::{ + build_support_map, evaluate_support, reduce, Assignment, ExtendedBalance, ElectionResult, + ElectionScore, balance_solution, }; use sp_runtime::offchain::storage::StorageValueRef; -use sp_runtime::PerThing; -use sp_runtime::RuntimeDebug; +use sp_runtime::{PerThing, RuntimeDebug, traits::{TrailingZeroInput, Zero}}; +use frame_support::traits::Get; use sp_std::{convert::TryInto, prelude::*}; /// Error types related to the offchain election machinery. #[derive(RuntimeDebug)] pub enum OffchainElectionError { - /// Phragmen election returned None. This means less candidate that minimum number of needed + /// election returned None. This means less candidate that minimum number of needed /// validators were present. The chain is in trouble and not much that we can do about it. ElectionFailed, /// Submission to the transaction pool failed. PoolSubmissionFailed, /// The snapshot data is not available. SnapshotUnavailable, - /// Error from phragmen crate. This usually relates to compact operation. - PhragmenError(sp_phragmen::Error), + /// Error from npos-election crate. This usually relates to compact operation. + InternalElectionError(sp_npos_elections::Error), /// One of the computed winners is invalid. InvalidWinner, } -impl From for OffchainElectionError { - fn from(e: sp_phragmen::Error) -> Self { - Self::PhragmenError(e) +impl From for OffchainElectionError { + fn from(e: sp_npos_elections::Error) -> Self { + Self::InternalElectionError(e) } } @@ -104,38 +107,45 @@ pub(crate) fn set_check_offchain_execution_status( /// unsigned transaction, without any signature. pub(crate) fn compute_offchain_election() -> Result<(), OffchainElectionError> { // compute raw solution. Note that we use `OffchainAccuracy`. - let PhragmenResult { + let ElectionResult { winners, assignments, } = >::do_phragmen::() .ok_or(OffchainElectionError::ElectionFailed)?; // process and prepare it for submission. - let (winners, compact, score) = prepare_submission::(assignments, winners, true)?; + let (winners, compact, score, size) = prepare_submission::(assignments, winners, true)?; - // defensive-only: active era can never be none except genesis. - let era = >::active_era().map(|e| e.index).unwrap_or_default(); + // defensive-only: current era can never be none except genesis. + let current_era = >::current_era().unwrap_or_default(); // send it. - let call: ::Call = Call::submit_election_solution_unsigned( + let call = Call::submit_election_solution_unsigned( winners, compact, score, - era, + current_era, + size, ).into(); - T::SubmitTransaction::submit_unsigned(call) + SubmitTransaction::>::submit_unsigned_transaction(call) .map_err(|_| OffchainElectionError::PoolSubmissionFailed) } -/// Takes a phragmen result and spits out some data that can be submitted to the chain. + +/// Takes an election result and spits out some data that can be submitted to the chain. /// /// This does a lot of stuff; read the inline comments. pub fn prepare_submission( assignments: Vec>, winners: Vec<(T::AccountId, ExtendedBalance)>, do_reduce: bool, -) -> Result<(Vec, CompactAssignments, PhragmenScore), OffchainElectionError> where +) -> Result<( + Vec, + CompactAssignments, + ElectionScore, + ElectionSize, +), OffchainElectionError> where ExtendedBalance: From<::Inner>, { // make sure that the snapshot is available. @@ -159,23 +169,42 @@ pub fn prepare_submission( }; // Clean winners. - let winners = winners - .into_iter() - .map(|(w, _)| w) - .collect::>(); + let winners = sp_npos_elections::to_without_backing(winners); // convert into absolute value and to obtain the reduced version. - let mut staked = sp_phragmen::assignment_ratio_to_staked( + let mut staked = sp_npos_elections::assignment_ratio_to_staked( assignments, - >::slashable_balance_of_extended, + >::slashable_balance_of_vote_weight, ); + let (mut support_map, _) = build_support_map::(&winners, &staked); + // balance a random number of times. + let iterations_executed = match T::MaxIterations::get() { + 0 => { + // Don't run balance_solution at all + 0 + } + iterations @ _ => { + let seed = sp_io::offchain::random_seed(); + let iterations = ::decode(&mut TrailingZeroInput::new(seed.as_ref())) + .expect("input is padded with zeroes; qed") % iterations.saturating_add(1); + balance_solution( + &mut staked, + &mut support_map, + Zero::zero(), + iterations as usize, + ) + } + }; + + // reduce if do_reduce { reduce(&mut staked); } // Convert back to ratio assignment. This takes less space. - let low_accuracy_assignment = sp_phragmen::assignment_staked_to_ratio(staked); + let low_accuracy_assignment = sp_npos_elections::assignment_staked_to_ratio_normalized(staked) + .map_err(|e| OffchainElectionError::from(e))?; // convert back to staked to compute the score in the receiver's accuracy. This can be done // nicer, for now we do it as such since this code is not time-critical. This ensure that the @@ -186,9 +215,9 @@ pub fn prepare_submission( // assignment set is also all multiples of this value. After reduce, this no longer holds. Hence // converting to ratio thereafter is not trivially reversible. let score = { - let staked = sp_phragmen::assignment_ratio_to_staked( + let staked = sp_npos_elections::assignment_ratio_to_staked( low_accuracy_assignment.clone(), - >::slashable_balance_of_extended, + >::slashable_balance_of_vote_weight, ); let (support_map, _) = build_support_map::(&winners, &staked); @@ -215,5 +244,18 @@ pub fn prepare_submission( } } - Ok((winners_indexed, compact, score)) + // both conversions are safe; snapshots are not created if they exceed. + let size = ElectionSize { + validators: snapshot_validators.len() as ValidatorIndex, + nominators: snapshot_nominators.len() as NominatorIndex, + }; + + crate::log!( + info, + "prepared solution after {} equalization iterations with score {:?}", + iterations_executed, + score, + ); + + Ok((winners_indexed, compact, score, size)) } diff --git a/frame/staking/src/slashing.rs b/frame/staking/src/slashing.rs index 26f0828989d733bfc720de288f33f0efcafd462d..4e43b754b8e377659e3ba30a468a279bdb2fb8db 100644 --- a/frame/staking/src/slashing.rs +++ b/frame/staking/src/slashing.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! A slashing implementation for NPoS systems. //! @@ -50,11 +51,11 @@ use super::{ EraIndex, Trait, Module, Store, BalanceOf, Exposure, Perbill, SessionInterface, - NegativeImbalanceOf, UnappliedSlash, + NegativeImbalanceOf, UnappliedSlash, Error, }; -use sp_runtime::{traits::{Zero, Saturating}, RuntimeDebug}; +use sp_runtime::{traits::{Zero, Saturating}, RuntimeDebug, DispatchResult}; use frame_support::{ - StorageMap, StorageDoubleMap, + StorageMap, StorageDoubleMap, ensure, traits::{Currency, OnUnbalanced, Imbalance}, }; use sp_std::vec::Vec; @@ -100,7 +101,7 @@ pub struct SlashingSpans { impl SlashingSpans { // creates a new record of slashing spans for a stash, starting at the beginning // of the bonding period, relative to now. - fn new(window_start: EraIndex) -> Self { + pub(crate) fn new(window_start: EraIndex) -> Self { SlashingSpans { span_index: 0, last_start: window_start, @@ -115,7 +116,7 @@ impl SlashingSpans { // update the slashing spans to reflect the start of a new span at the era after `now` // returns `true` if a new span was started, `false` otherwise. `false` indicates // that internal state is unchanged. - fn end_span(&mut self, now: EraIndex) -> bool { + pub(crate) fn end_span(&mut self, now: EraIndex) -> bool { let next_start = now + 1; if next_start <= self.last_start { return false } @@ -547,12 +548,19 @@ pub(crate) fn clear_era_metadata(obsolete_era: EraIndex) { } /// Clear slashing metadata for a dead account. -pub(crate) fn clear_stash_metadata(stash: &T::AccountId) { - let spans = match as Store>::SlashingSpans::take(stash) { - None => return, +pub(crate) fn clear_stash_metadata( + stash: &T::AccountId, + num_slashing_spans: u32, +) -> DispatchResult { + let spans = match as Store>::SlashingSpans::get(stash) { + None => return Ok(()), Some(s) => s, }; + ensure!(num_slashing_spans as usize >= spans.iter().count(), Error::::IncorrectSlashingSpans); + + as Store>::SlashingSpans::remove(stash); + // kill slashing-span metadata for account. // // this can only happen while the account is staked _if_ they are completely slashed. @@ -561,6 +569,8 @@ pub(crate) fn clear_stash_metadata(stash: &T::AccountId) { for span in spans.iter() { as Store>::SpanSlash::remove(&(stash.clone(), span.index)); } + + Ok(()) } // apply the slash to a stash account, deducting any missing funds from the reward diff --git a/frame/staking/src/testing_utils.rs b/frame/staking/src/testing_utils.rs index 29a395b89de4dda8aa2c56755ed941a52ff99411..27a2575eb0df33d7871552ecee95cf351241aa5d 100644 --- a/frame/staking/src/testing_utils.rs +++ b/frame/staking/src/testing_utils.rs @@ -1,225 +1,180 @@ -// Copyright 2020 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. +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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. +// 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. -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Testing utils for staking. Needs the `testing-utils` feature to be enabled. -//! -//! Note that these helpers should NOT be used with the actual crate tests, but are rather designed -//! for when the module is being externally tested (i.e. fuzzing, benchmarking, e2e tests). Enabling -//! this feature in the current crate's Cargo.toml will leak the all of this into a normal release -//! build. Just don't do it. +//! Testing utils for staking. Provides some common functions to setup staking state, such as +//! bonding validators, nominators, and generating different types of solutions. use crate::*; -use codec::{Decode, Encode}; -use frame_support::assert_ok; +use crate::Module as Staking; +use frame_benchmarking::{account}; use frame_system::RawOrigin; -use pallet_indices::address::Address; -use rand::Rng; -use sp_core::hashing::blake2_256; -use sp_phragmen::{ - build_support_map, evaluate_support, reduce, Assignment, PhragmenScore, StakedAssignment, -}; - -const CTRL_PREFIX: u32 = 1000; -const NOMINATOR_PREFIX: u32 = 1_000_000; - -/// A dummy suer. -pub const USER: u32 = 999_999_999; - -/// Address type of the `T` -pub type AddressOf = Address<::AccountId, u32>; - -/// Random number in the range `[a, b]`. -pub fn random(a: u32, b: u32) -> u32 { - rand::thread_rng().gen_range(a, b) +use sp_io::hashing::blake2_256; +use rand_chacha::{rand_core::{RngCore, SeedableRng}, ChaChaRng}; +use sp_npos_elections::*; + +const SEED: u32 = 0; + +/// Grab a funded user. +pub fn create_funded_user(string: &'static str, n: u32, balance_factor: u32) -> T::AccountId { + let user = account(string, n, SEED); + let balance = T::Currency::minimum_balance() * balance_factor.into(); + T::Currency::make_free_balance_be(&user, balance); + // ensure T::CurrencyToVote will work correctly. + T::Currency::issue(balance); + user } -/// Set the desired validator count, with related storage items. -pub fn set_validator_count(to_elect: u32) { - ValidatorCount::put(to_elect); - MinimumValidatorCount::put(to_elect / 2); - >::put(ElectionStatus::Open(T::BlockNumber::from(1u32))); +/// Create a stash and controller pair. +pub fn create_stash_controller(n: u32, balance_factor: u32) + -> Result<(T::AccountId, T::AccountId), &'static str> +{ + let stash = create_funded_user::("stash", n, balance_factor); + let controller = create_funded_user::("controller", n, balance_factor); + let controller_lookup: ::Source = T::Lookup::unlookup(controller.clone()); + let reward_destination = RewardDestination::Staked; + let amount = T::Currency::minimum_balance() * (balance_factor / 10).max(1).into(); + Staking::::bond(RawOrigin::Signed(stash.clone()).into(), controller_lookup, amount, reward_destination)?; + return Ok((stash, controller)) } -/// Build an account with the given index. -pub fn account(index: u32) -> T::AccountId { - let entropy = (b"benchmark/staking", index).using_encoded(blake2_256); - T::AccountId::decode(&mut &entropy[..]).unwrap_or_default() +/// Create a stash and controller pair, where the controller is dead, and payouts go to controller. +/// This is used to test worst case payout scenarios. +pub fn create_stash_and_dead_controller(n: u32, balance_factor: u32) + -> Result<(T::AccountId, T::AccountId), &'static str> +{ + let stash = create_funded_user::("stash", n, balance_factor); + // controller has no funds + let controller = create_funded_user::("controller", n, 0); + let controller_lookup: ::Source = T::Lookup::unlookup(controller.clone()); + let reward_destination = RewardDestination::Controller; + let amount = T::Currency::minimum_balance() * (balance_factor / 10).max(1).into(); + Staking::::bond(RawOrigin::Signed(stash.clone()).into(), controller_lookup, amount, reward_destination)?; + return Ok((stash, controller)) } -/// Build an address given Index -pub fn address(index: u32) -> AddressOf { - pallet_indices::address::Address::Id(account::(index)) +/// create `max` validators. +pub fn create_validators( + max: u32, + balance_factor: u32, +) -> Result::Source>, &'static str> { + let mut validators: Vec<::Source> = Vec::with_capacity(max as usize); + for i in 0 .. max { + let (stash, controller) = create_stash_controller::(i, balance_factor)?; + let validator_prefs = ValidatorPrefs { + commission: Perbill::from_percent(50), + }; + Staking::::validate(RawOrigin::Signed(controller).into(), validator_prefs)?; + let stash_lookup: ::Source = T::Lookup::unlookup(stash); + validators.push(stash_lookup); + } + Ok(validators) } -/// Generate signed origin from `who`. -pub fn signed(who: T::AccountId) -> T::Origin { - RawOrigin::Signed(who).into() -} +/// This function generates validators and nominators who are randomly nominating +/// `edge_per_nominator` random validators (until `to_nominate` if provided). +/// +/// Parameters: +/// - `validators`: number of bonded validators +/// - `nominators`: number of bonded nominators. +/// - `edge_per_nominator`: number of edge (vote) per nominator. +/// - `randomize_stake`: whether to randomize the stakes. +/// - `to_nominate`: if `Some(n)`, only the first `n` bonded validator are voted upon. +/// Else, all of them are considered and `edge_per_nominator` random validators are voted for. +/// +/// Return the validators choosen to be nominated. +pub fn create_validators_with_nominators_for_era( + validators: u32, + nominators: u32, + edge_per_nominator: usize, + randomize_stake: bool, + to_nominate: Option, +) -> Result::Source>, &'static str> { + let mut validators_stash: Vec<::Source> + = Vec::with_capacity(validators as usize); + let mut rng = ChaChaRng::from_seed(SEED.using_encoded(blake2_256)); + + // Create validators + for i in 0 .. validators { + let balance_factor = if randomize_stake { rng.next_u32() % 255 + 10 } else { 100u32 }; + let (v_stash, v_controller) = create_stash_controller::(i, balance_factor)?; + let validator_prefs = ValidatorPrefs { + commission: Perbill::from_percent(50), + }; + Staking::::validate(RawOrigin::Signed(v_controller.clone()).into(), validator_prefs)?; + let stash_lookup: ::Source = T::Lookup::unlookup(v_stash.clone()); + validators_stash.push(stash_lookup.clone()); + } -/// Generate signed origin from `index`. -pub fn signed_account(index: u32) -> T::Origin { - signed::(account::(index)) -} + let to_nominate = to_nominate.unwrap_or(validators_stash.len() as u32) as usize; + let validator_choosen = validators_stash[0..to_nominate].to_vec(); + + // Create nominators + for j in 0 .. nominators { + let balance_factor = if randomize_stake { rng.next_u32() % 255 + 10 } else { 100u32 }; + let (_n_stash, n_controller) = create_stash_controller::( + u32::max_value() - j, + balance_factor, + )?; + + // Have them randomly validate + let mut available_validators = validator_choosen.clone(); + let mut selected_validators: Vec<::Source> = + Vec::with_capacity(edge_per_nominator); + + for _ in 0 .. validators.min(edge_per_nominator as u32) { + let selected = rng.next_u32() as usize % available_validators.len(); + let validator = available_validators.remove(selected); + selected_validators.push(validator); + } + Staking::::nominate(RawOrigin::Signed(n_controller.clone()).into(), selected_validators)?; + } -/// Bond a validator. -pub fn bond_validator(stash: T::AccountId, ctrl: u32, val: BalanceOf) -where - T::Lookup: StaticLookup>, -{ - let _ = T::Currency::make_free_balance_be(&stash, val); - assert_ok!(>::bond( - signed::(stash), - address::(ctrl), - val, - RewardDestination::Controller - )); - assert_ok!(>::validate( - signed_account::(ctrl), - ValidatorPrefs::default() - )); -} + ValidatorCount::put(validators); -pub fn bond_nominator( - stash: T::AccountId, - ctrl: u32, - val: BalanceOf, - target: Vec>, -) where - T::Lookup: StaticLookup>, -{ - let _ = T::Currency::make_free_balance_be(&stash, val); - assert_ok!(>::bond( - signed::(stash), - address::(ctrl), - val, - RewardDestination::Controller - )); - assert_ok!(>::nominate(signed_account::(ctrl), target)); + Ok(validator_choosen) } -/// Bond `nun_validators` validators and `num_nominator` nominators with `edge_per_voter` random -/// votes per nominator. -pub fn setup_chain_stakers(num_validators: u32, num_voters: u32, edge_per_voter: u32) -where - T::Lookup: StaticLookup>, -{ - (0..num_validators).for_each(|i| { - bond_validator::( - account::(i), - i + CTRL_PREFIX, - >::from(random(1, 1000)) * T::Currency::minimum_balance(), - ); - }); - - (0..num_voters).for_each(|i| { - let mut targets: Vec> = Vec::with_capacity(edge_per_voter as usize); - let mut all_targets = (0..num_validators) - .map(|t| address::(t)) - .collect::>(); - assert!(num_validators >= edge_per_voter); - (0..edge_per_voter).for_each(|_| { - let target = all_targets.remove(random(0, all_targets.len() as u32 - 1) as usize); - targets.push(target); - }); - bond_nominator::( - account::(i + NOMINATOR_PREFIX), - i + NOMINATOR_PREFIX + CTRL_PREFIX, - >::from(random(1, 1000)) * T::Currency::minimum_balance(), - targets, - ); - }); - - >::create_stakers_snapshot(); -} /// Build a _really bad_ but acceptable solution for election. This should always yield a solution /// which has a less score than the seq-phragmen. pub fn get_weak_solution( do_reduce: bool, -) -> (Vec, CompactAssignments, PhragmenScore) { +) -> (Vec, CompactAssignments, ElectionScore, ElectionSize) { let mut backing_stake_of: BTreeMap> = BTreeMap::new(); // self stake - >::enumerate().for_each(|(who, _p)| { + >::iter().for_each(|(who, _p)| { *backing_stake_of.entry(who.clone()).or_insert(Zero::zero()) += >::slashable_balance_of(&who) }); - // add nominator stuff - >::enumerate().for_each(|(who, nomination)| { - nomination.targets.into_iter().for_each(|v| { - *backing_stake_of.entry(v).or_insert(Zero::zero()) += - >::slashable_balance_of(&who) - }) - }); - - // elect winners + // elect winners. We chose the.. least backed ones. let mut sorted: Vec = backing_stake_of.keys().cloned().collect(); sorted.sort_by_key(|x| backing_stake_of.get(x).unwrap()); let winners: Vec = sorted .iter() + .rev() .cloned() .take(>::validator_count() as usize) .collect(); let mut staked_assignments: Vec> = Vec::new(); - >::enumerate().for_each(|(who, nomination)| { - let mut dist: Vec<(T::AccountId, ExtendedBalance)> = Vec::new(); - nomination.targets.into_iter().for_each(|v| { - if winners.iter().find(|&w| *w == v).is_some() { - dist.push((v, ExtendedBalance::zero())); - } - }); - - if dist.len() == 0 { - return; - } - - // assign real stakes. just split the stake. - let stake = , u64>>::convert( - >::slashable_balance_of(&who), - ) as ExtendedBalance; - - let mut sum: ExtendedBalance = Zero::zero(); - let dist_len = dist.len() as ExtendedBalance; - - // assign main portion - // only take the first half into account. This should highly imbalance stuff, which is good. - dist.iter_mut() - .take(if dist_len > 1 { - (dist_len as usize) / 2 - } else { - 1 - }) - .for_each(|(_, w)| { - let partial = stake / dist_len; - *w = partial; - sum += partial; - }); - - // assign the leftover to last. - let leftover = stake - sum; - let last = dist.last_mut().unwrap(); - last.1 += leftover; - - staked_assignments.push(StakedAssignment { - who, - distribution: dist, - }); - }); + // you could at this point start adding some of the nominator's stake, but for now we don't. + // This solution must be bad. // add self support to winners. winners.iter().for_each(|w| { @@ -254,28 +209,22 @@ pub fn get_weak_solution( .position(|x| x == a) .and_then(|i| >::try_into(i).ok()) }; - let stake_of = |who: &T::AccountId| -> ExtendedBalance { + let stake_of = |who: &T::AccountId| -> VoteWeight { , u64>>::convert( >::slashable_balance_of(who), - ) as ExtendedBalance + ) }; // convert back to ratio assignment. This takes less space. - let low_accuracy_assignment: Vec> = - staked_assignments - .into_iter() - .map(|sa| sa.into_assignment(true)) - .collect(); + let low_accuracy_assignment = assignment_staked_to_ratio_normalized(staked_assignments) + .expect("Failed to normalize"); // re-calculate score based on what the chain will decode. let score = { - let staked: Vec> = low_accuracy_assignment - .iter() - .map(|a| { - let stake = stake_of(&a.who); - a.clone().into_staked(stake, true) - }) - .collect(); + let staked = assignment_ratio_to_staked::<_, OffchainAccuracy, _>( + low_accuracy_assignment.clone(), + stake_of + ); let (support_map, _) = build_support_map::(winners.as_slice(), staked.as_slice()); @@ -303,15 +252,20 @@ pub fn get_weak_solution( }) .collect::>(); - (winners, compact, score) + let size = ElectionSize { + validators: snapshot_validators.len() as ValidatorIndex, + nominators: snapshot_nominators.len() as NominatorIndex, + }; + + (winners, compact, score, size) } /// Create a solution for seq-phragmen. This uses the same internal function as used by the offchain /// worker code. pub fn get_seq_phragmen_solution( do_reduce: bool, -) -> (Vec, CompactAssignments, PhragmenScore) { - let sp_phragmen::PhragmenResult { +) -> (Vec, CompactAssignments, ElectionScore, ElectionSize) { + let sp_npos_elections::ElectionResult { winners, assignments, } = >::do_phragmen::().unwrap(); @@ -319,22 +273,76 @@ pub fn get_seq_phragmen_solution( offchain_election::prepare_submission::(assignments, winners, do_reduce).unwrap() } -/// Remove all validator, nominators, votes and exposures. -pub fn clean(era: EraIndex) - where - ::AccountId: codec::EncodeLike, - u32: codec::EncodeLike, -{ - >::enumerate().for_each(|(k, _)| { - let ctrl = >::bonded(&k).unwrap(); - >::remove(&k); - >::remove(&k); - >::remove(&ctrl); - >::remove(k, era); - }); - >::enumerate().for_each(|(k, _)| >::remove(k)); - >::remove_all(); - >::remove_all(); - >::kill(); - QueuedScore::kill(); +/// Returns a solution in which only one winner is elected with just a self vote. +pub fn get_single_winner_solution( + winner: T::AccountId +) -> Result<(Vec, CompactAssignments, ElectionScore, ElectionSize), &'static str> { + let snapshot_validators = >::snapshot_validators().unwrap(); + let snapshot_nominators = >::snapshot_nominators().unwrap(); + + let val_index = snapshot_validators.iter().position(|x| *x == winner).ok_or("not a validator")?; + let nom_index = snapshot_nominators.iter().position(|x| *x == winner).ok_or("not a nominator")?; + + let stake = >::slashable_balance_of(&winner); + let stake = , VoteWeight>>::convert(stake) + as ExtendedBalance; + + let val_index = val_index as ValidatorIndex; + let nom_index = nom_index as NominatorIndex; + + let winners = vec![val_index]; + let compact = CompactAssignments { + votes1: vec![(nom_index, val_index)], + ..Default::default() + }; + let score = [stake, stake, stake * stake]; + let size = ElectionSize { + validators: snapshot_validators.len() as ValidatorIndex, + nominators: snapshot_nominators.len() as NominatorIndex, + }; + + Ok((winners, compact, score, size)) +} + +/// get the active era. +pub fn current_era() -> EraIndex { + >::current_era().unwrap_or(0) +} + +/// initialize the first era. +pub fn init_active_era() { + ActiveEra::put(ActiveEraInfo { + index: 1, + start: None, + }) +} + +/// Create random assignments for the given list of winners. Each assignment will have +/// MAX_NOMINATIONS edges. +pub fn create_assignments_for_offchain( + num_assignments: u32, + winners: Vec<::Source>, +) -> Result< + ( + Vec<(T::AccountId, ExtendedBalance)>, + Vec>, + ), + &'static str +> { + let ratio = OffchainAccuracy::from_rational_approximation(1, MAX_NOMINATIONS); + let assignments: Vec> = >::iter() + .take(num_assignments as usize) + .map(|(n, t)| Assignment { + who: n, + distribution: t.targets.iter().map(|v| (v.clone(), ratio)).collect(), + }) + .collect(); + + ensure!(assignments.len() == num_assignments as usize, "must bench for `a` assignments"); + + let winners = winners.into_iter().map(|v| { + (::lookup(v).unwrap(), 0) + }).collect(); + + Ok((winners, assignments)) } diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 17770817696c55c940534ffa8577a359e4cf5664..a3cfed9e2f260e105948a0245dadc9bed3e175a5 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for the module. @@ -24,27 +25,29 @@ use sp_runtime::{ use sp_staking::offence::OffenceDetails; use frame_support::{ assert_ok, assert_noop, StorageMap, - traits::{Currency, ReservableCurrency, OnInitialize}, + traits::{Currency, ReservableCurrency, OnInitialize, OnFinalize}, }; use pallet_balances::Error as BalancesError; use substrate_test_utils::assert_eq_uvec; -use crate::Store; #[test] fn force_unstake_works() { - // Verifies initial conditions of mock - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Account 11 is stashed and locked, and account 10 is the controller assert_eq!(Staking::bonded(&11), Some(10)); + // Adds 2 slashing spans + add_slash(&11); // Cant transfer assert_noop!( Balances::transfer(Origin::signed(11), 1, 10), BalancesError::::LiquidityRestrictions ); // Force unstake requires root. - assert_noop!(Staking::force_unstake(Origin::signed(11), 11), BadOrigin); + assert_noop!(Staking::force_unstake(Origin::signed(11), 11, 2), BadOrigin); + // Force unstake needs correct number of slashing spans (for weight calculation) + assert_noop!(Staking::force_unstake(Origin::signed(11), 11, 0), BadOrigin); // We now force them to unstake - assert_ok!(Staking::force_unstake(Origin::ROOT, 11)); + assert_ok!(Staking::force_unstake(Origin::root(), 11, 2)); // No longer bonded. assert_eq!(Staking::bonded(&11), None); // Transfer works. @@ -52,10 +55,28 @@ fn force_unstake_works() { }); } +#[test] +fn kill_stash_works() { + ExtBuilder::default().build_and_execute(|| { + // Account 11 is stashed and locked, and account 10 is the controller + assert_eq!(Staking::bonded(&11), Some(10)); + // Adds 2 slashing spans + add_slash(&11); + // Only can kill a stash account + assert_noop!(Staking::kill_stash(&12, 0), Error::::NotStash); + // Respects slashing span count + assert_noop!(Staking::kill_stash(&11, 0), Error::::IncorrectSlashingSpans); + // Correct inputs, everything works + assert_ok!(Staking::kill_stash(&11, 2)); + // No longer bonded. + assert_eq!(Staking::bonded(&11), None); + }); +} + #[test] fn basic_setup_works() { // Verifies initial conditions of mock - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // 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 @@ -77,7 +98,7 @@ fn basic_setup_works() { assert_eq!(Staking::ledger(&1), None); // ValidatorPrefs are default - assert_eq!(>::iter().collect::>(), vec![ + assert_eq_uvec!(>::iter().collect::>(), vec![ (31, ValidatorPrefs::default()), (21, ValidatorPrefs::default()), (11, ValidatorPrefs::default()) @@ -105,7 +126,8 @@ fn basic_setup_works() { others: vec![ IndividualExposure { who: 101, value: 375 }] }, ); - // initial slot_stake + + // initial total stake = 1125 + 1375 assert_eq!(Staking::eras_total_stake(Staking::active_era().unwrap().index), 2500); @@ -121,27 +143,24 @@ fn basic_setup_works() { // New era is not being forced assert_eq!(Staking::force_era(), Forcing::NotForcing); - - // All exposures must be correct. - check_exposure_all(Staking::active_era().unwrap().index); - check_nominator_all(Staking::active_era().unwrap().index); }); } #[test] fn change_controller_works() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { + // 10 and 11 are bonded as stash controller. assert_eq!(Staking::bonded(&11), Some(10)); - assert!(Session::validators().contains(&11)); // 10 can control 11 who is initially a validator. assert_ok!(Staking::chill(Origin::signed(10))); - assert!(Session::validators().contains(&11)); + // change controller assert_ok!(Staking::set_controller(Origin::signed(11), 5)); - + assert_eq!(Staking::bonded(&11), Some(5)); mock::start_era(1); + // 10 is no longer in control. assert_noop!( Staking::validate(Origin::signed(10), ValidatorPrefs::default()), Error::::NotController, @@ -155,8 +174,9 @@ fn rewards_should_work() { // should check that: // * rewards get recorded per session // * rewards get paid per Era + // * `RewardRemainder::on_unbalanced` is called // * Check that nominators are also rewarded - ExtBuilder::default().nominate(true).build().execute_with(|| { + ExtBuilder::default().nominate(true).build_and_execute(|| { let init_balance_10 = Balances::total_balance(&10); let init_balance_11 = Balances::total_balance(&11); let init_balance_20 = Balances::total_balance(&20); @@ -200,6 +220,8 @@ fn rewards_should_work() { start_session(3); assert_eq!(Staking::active_era().unwrap().index, 1); + assert_eq!(mock::REWARD_REMAINDER_UNBALANCED.with(|v| *v.borrow()), 7050); + assert_eq!(*mock::staking_events().last().unwrap(), RawEvent::EraPayout(0, 2350, 7050)); mock::make_all_reward_payment(0); assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + part_for_10 * total_payout_0*2/3, 2); @@ -223,6 +245,8 @@ fn rewards_should_work() { assert!(total_payout_1 > 10); // Test is meaningful if reward something mock::start_era(2); + assert_eq!(mock::REWARD_REMAINDER_UNBALANCED.with(|v| *v.borrow()), 7050*2); + assert_eq!(*mock::staking_events().last().unwrap(), RawEvent::EraPayout(1, 2350, 7050)); mock::make_all_reward_payment(1); assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + part_for_10 * (total_payout_0 * 2/3 + total_payout_1), 2); @@ -313,7 +337,7 @@ fn staking_should_work() { claimed_rewards: vec![0], }) ); - // e.g. it cannot spend more than 500 that it has free from the total 2000 + // e.g. it cannot reserve more than 500 that it has free from the total 2000 assert_noop!( Balances::reserve(&3, 501), BalancesError::::LiquidityRestrictions @@ -343,11 +367,9 @@ fn less_than_needed_candidates_works() { // But the exposure is updated in a simple way. No external votes exists. // This is purely self-vote. assert!( - ErasStakers::::iter_prefix(Staking::active_era().unwrap().index) + ErasStakers::::iter_prefix_values(Staking::active_era().unwrap().index) .all(|exposure| exposure.others.is_empty()) ); - check_exposure_all(Staking::active_era().unwrap().index); - check_nominator_all(Staking::active_era().unwrap().index); }); } @@ -384,41 +406,6 @@ fn no_candidate_emergency_condition() { #[test] fn nominating_and_rewards_should_work() { - // PHRAGMEN OUTPUT: running this test with the reference impl gives: - // - // 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 - - // 10 has load 0.0003333333333333333 and supported - // 10 with stake 1000.0 - // 20 has load 0.0005555555555555556 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.0005555555555555556 and supported - // 10 with stake 600.0 20 with stake 400.0 30 with stake 0.0 - // 4 has load 0.0005555555555555556 and supported - // 10 with stake 600.0 20 with stake 400.0 40 with stake 0.0 - - // Sequential Phragmén with post processing gives - // 10 is elected with stake 2000.0 and score 0.0003333333333333333 - // 20 is elected with stake 2000.0 and score 0.0005555555555555556 - - // 10 has load 0.0003333333333333333 and supported - // 10 with stake 1000.0 - // 20 has load 0.0005555555555555556 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.0005555555555555556 and supported - // 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 ExtBuilder::default() .nominate(false) .validator_pool(true) @@ -455,7 +442,7 @@ fn nominating_and_rewards_should_work() { mock::start_era(1); - // 10 and 20 have more votes, they will be chosen by phragmen. + // 10 and 20 have more votes, they will be chosen. assert_eq_uvec!(validator_controllers(), vec![20, 10]); // OLD validators must have already received some rewards. @@ -466,7 +453,7 @@ fn nominating_and_rewards_should_work() { // ------ check the staked value of all parties. // 30 and 40 are not chosen anymore - assert_eq!(ErasStakers::::iter_prefix(Staking::active_era().unwrap().index).count(), 2); + assert_eq!(ErasStakers::::iter_prefix_values(Staking::active_era().unwrap().index).count(), 2); assert_eq!( Staking::eras_stakers(Staking::active_era().unwrap().index, 11), Exposure { @@ -529,68 +516,75 @@ fn nominating_and_rewards_should_work() { initial_balance + 5 * payout_for_20 / 11, 1, ); - - check_exposure_all(Staking::active_era().unwrap().index); - check_nominator_all(Staking::active_era().unwrap().index); }); } #[test] -fn nominators_also_get_slashed() { - // A nominator should be slashed if the validator they nominated is slashed - // 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); - - // Set payee to controller - assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); - - // give the man some money. - let initial_balance = 1000; - for i in [1, 2, 3, 10].iter() { - let _ = Balances::make_free_balance_be(i, initial_balance); - } - - // 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(3000); - assert!(total_payout > 100); // Test is meaningful if reward something - >::reward_by_ids(vec![(11, 1)]); - - // new era, pay rewards, +fn nominators_also_get_slashed_pro_rata() { + ExtBuilder::default().build_and_execute(|| { mock::start_era(1); + let slash_percent = Perbill::from_percent(5); + let initial_exposure = Staking::eras_stakers(active_era(), 11); + // 101 is a nominator for 11 + assert_eq!( + initial_exposure.others.first().unwrap().who, + 101, + ); - // Nominator stash didn't collect any. - assert_eq!(Balances::total_balance(&2), initial_balance); + // staked values; + let nominator_stake = Staking::ledger(100).unwrap().active; + let nominator_balance = balances(&101).0; + let validator_stake = Staking::ledger(10).unwrap().active; + let validator_balance = balances(&11).0; + let exposed_stake = initial_exposure.total; + let exposed_validator = initial_exposure.own; + let exposed_nominator = initial_exposure.others.first().unwrap().value; - // 10 goes offline + // 11 goes offline on_offence_now( &[OffenceDetails { offender: ( 11, - Staking::eras_stakers(Staking::active_era().unwrap().index, 11), + initial_exposure.clone(), ), reporters: vec![], }], - &[Perbill::from_percent(5)], + &[slash_percent], + ); + + // both stakes must have been decreased. + assert!(Staking::ledger(100).unwrap().active < nominator_stake); + assert!(Staking::ledger(10).unwrap().active < validator_stake); + + let slash_amount = slash_percent * exposed_stake; + let validator_share = + Perbill::from_rational_approximation(exposed_validator, exposed_stake) * slash_amount; + let nominator_share = Perbill::from_rational_approximation( + exposed_nominator, + exposed_stake, + ) * slash_amount; + + // both slash amounts need to be positive for the test to make sense. + assert!(validator_share > 0); + assert!(nominator_share > 0); + + // both stakes must have been decreased pro-rata. + assert_eq!( + Staking::ledger(100).unwrap().active, + nominator_stake - nominator_share, + ); + assert_eq!( + Staking::ledger(10).unwrap().active, + validator_stake - validator_share, + ); + assert_eq!( + balances(&101).0, // free balance + nominator_balance - nominator_share, + ); + assert_eq!( + balances(&11).0, // free balance + validator_balance - validator_share, ); - let expo = Staking::eras_stakers(Staking::active_era().unwrap().index, 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(&11), initial_balance - validator_slash); - assert_eq!(Balances::total_balance(&2), initial_balance - nominator_slash); - check_exposure_all(Staking::active_era().unwrap().index); - check_nominator_all(Staking::active_era().unwrap().index); // Because slashing happened. assert!(is_disabled(10)); }); @@ -602,7 +596,7 @@ 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. - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { let arbitrary_value = 5; // 2 = controller, 1 stashed => ok assert_ok!( @@ -625,7 +619,7 @@ fn double_staking_should_fail() { 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. - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { let arbitrary_value = 5; // 2 = controller, 1 stashed => ok assert_ok!(Staking::bond( @@ -644,7 +638,7 @@ fn double_controlling_should_fail() { #[test] fn session_and_eras_work() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { assert_eq!(Staking::active_era().unwrap().index, 0); assert_eq!(Session::current_index(), 0); @@ -682,7 +676,7 @@ fn session_and_eras_work() { #[test] fn forcing_new_era_works() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // normal flow of session. assert_eq!(Staking::active_era().unwrap().index, 0); start_session(0); @@ -738,7 +732,7 @@ fn forcing_new_era_works() { #[test] fn cannot_transfer_staked_balance() { // Tests that a stash account cannot transfer funds - ExtBuilder::default().nominate(false).build().execute_with(|| { + ExtBuilder::default().nominate(false).build_and_execute(|| { // Confirm account 11 is stashed assert_eq!(Staking::bonded(&11), Some(10)); // Confirm account 11 has some free balance @@ -763,7 +757,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 - ExtBuilder::default().nominate(false).fair(true).build().execute_with(|| { + ExtBuilder::default().nominate(false).fair(true).build_and_execute(|| { // Confirm account 21 is stashed assert_eq!(Staking::bonded(&21), Some(20)); // Confirm account 21 has some free balance @@ -782,17 +776,17 @@ fn cannot_transfer_staked_balance_2() { #[test] fn cannot_reserve_staked_balance() { // Checks that a bonded account cannot reserve balance from free balance - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Confirm account 11 is stashed assert_eq!(Staking::bonded(&11), Some(10)); // Confirm account 11 has some free balance assert_eq!(Balances::free_balance(11), 1000); // Confirm account 11 (via controller 10) is totally staked assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 11).own, 1000); - // Confirm account 11 cannot transfer as a result + // Confirm account 11 cannot reserve as a result assert_noop!( Balances::reserve(&11, 1), - BalancesError::::LiquidityRestrictions + BalancesError::::LiquidityRestrictions, ); // Give account 11 extra free balance @@ -805,7 +799,7 @@ fn cannot_reserve_staked_balance() { #[test] fn reward_destination_works() { // Rewards go to the correct destination as determined in Payee - ExtBuilder::default().nominate(false).build().execute_with(|| { + ExtBuilder::default().nominate(false).build_and_execute(|| { // Check that account 11 is a validator assert!(Session::validators().contains(&11)); // Check the balance of the validator account @@ -904,7 +898,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. - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { let commission = Perbill::from_percent(40); >::insert(&11, ValidatorPrefs { commission: commission.clone(), @@ -935,9 +929,6 @@ fn validator_payment_prefs_work() { let reward_of_100 = shared_cut * exposure_1.others[0].value / exposure_1.total; assert_eq_error_rate!(Balances::total_balance(&10), balance_era_1_10 + reward_of_10, 2); assert_eq_error_rate!(Balances::total_balance(&100), balance_era_1_100 + reward_of_100, 2); - - check_exposure_all(Staking::active_era().unwrap().index); - check_nominator_all(Staking::active_era().unwrap().index); }); } @@ -947,7 +938,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`. - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Check that account 10 is a validator assert!(>::contains_key(11)); // Check that account 10 is bonded to account 11 @@ -976,7 +967,7 @@ fn bond_extra_works() { })); // Call the bond_extra function with a large number, should handle it - assert_ok!(Staking::bond_extra(Origin::signed(11), u64::max_value())); + assert_ok!(Staking::bond_extra(Origin::signed(11), Balance::max_value())); // The full amount of the funds should now be in the total and active assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, @@ -995,7 +986,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. - ExtBuilder::default().nominate(false).build().execute_with(|| { + ExtBuilder::default().nominate(false).build_and_execute(|| { // Set payee to controller. avoids confusion assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); @@ -1020,7 +1011,10 @@ fn bond_extra_and_withdraw_unbonded_works() { unlocking: vec![], claimed_rewards: vec![], })); - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 11), Exposure { total: 1000, own: 1000, others: vec![] }); + assert_eq!( + Staking::eras_stakers(Staking::active_era().unwrap().index, 11), + Exposure { total: 1000, own: 1000, others: vec![] } + ); // deposit the extra 100 units Staking::bond_extra(Origin::signed(11), 100).unwrap(); @@ -1033,7 +1027,10 @@ fn bond_extra_and_withdraw_unbonded_works() { claimed_rewards: vec![], })); // Exposure is a snapshot! only updated after the next era update. - assert_ne!(Staking::eras_stakers(Staking::active_era().unwrap().index, 11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); + assert_ne!( + Staking::eras_stakers(Staking::active_era().unwrap().index, 11), + Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] } + ); // trigger next era. mock::start_era(2); @@ -1048,40 +1045,74 @@ fn bond_extra_and_withdraw_unbonded_works() { claimed_rewards: vec![], })); // Exposure is now updated. - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); + assert_eq!( + Staking::eras_stakers(Staking::active_era().unwrap().index, 11), + Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] } + ); // Unbond almost all of the funds in stash. Staking::unbond(Origin::signed(10), 1000).unwrap(); - assert_eq!(Staking::ledger(&10), Some(StakingLedger { - stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}], claimed_rewards: vec![] }) + assert_eq!( + Staking::ledger(&10), + Some(StakingLedger { + stash: 11, + total: 1000 + 100, + active: 100, + unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}], + claimed_rewards: vec![] + }), ); // Attempting to free the balances now will fail. 2 eras need to pass. - Staking::withdraw_unbonded(Origin::signed(10)).unwrap(); - assert_eq!(Staking::ledger(&10), Some(StakingLedger { - stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}], claimed_rewards: vec![] })); + assert_ok!(Staking::withdraw_unbonded(Origin::signed(10), 0)); + assert_eq!( + Staking::ledger(&10), + Some(StakingLedger { + stash: 11, + total: 1000 + 100, + active: 100, + unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}], + claimed_rewards: vec![] + }), + ); // trigger next era. mock::start_era(3); // nothing yet - Staking::withdraw_unbonded(Origin::signed(10)).unwrap(); - assert_eq!(Staking::ledger(&10), Some(StakingLedger { - stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}], claimed_rewards: vec![] })); + assert_ok!(Staking::withdraw_unbonded(Origin::signed(10), 0)); + assert_eq!( + Staking::ledger(&10), + Some(StakingLedger { + stash: 11, + total: 1000 + 100, + active: 100, + unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}], + claimed_rewards: vec![] + }), + ); // trigger next era. mock::start_era(5); - Staking::withdraw_unbonded(Origin::signed(10)).unwrap(); + assert_ok!(Staking::withdraw_unbonded(Origin::signed(10), 0)); // Now the value is free and the staking ledger is updated. - assert_eq!(Staking::ledger(&10), Some(StakingLedger { - stash: 11, total: 100, active: 100, unlocking: vec![], claimed_rewards: vec![] })); + assert_eq!( + Staking::ledger(&10), + Some(StakingLedger { + stash: 11, + total: 100, + active: 100, + unlocking: vec![], + claimed_rewards: vec![] + }), + ); }) } #[test] fn too_many_unbond_calls_should_not_work() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // locked at era 0 until 3 for _ in 0..MAX_UNLOCKING_CHUNKS-1 { assert_ok!(Staking::unbond(Origin::signed(10), 1)); @@ -1098,7 +1129,7 @@ fn too_many_unbond_calls_should_not_work() { assert_noop!(Staking::unbond(Origin::signed(10), 1), Error::::NoMoreChunks); // free up. - assert_ok!(Staking::withdraw_unbonded(Origin::signed(10))); + assert_ok!(Staking::withdraw_unbonded(Origin::signed(10), 0)); // Can add again. assert_ok!(Staking::unbond(Origin::signed(10), 1)); @@ -1359,7 +1390,7 @@ fn rebond_is_fifo() { #[test] fn reward_to_stake_works() { - ExtBuilder::default().nominate(false).fair(false).build().execute_with(|| { + ExtBuilder::default().nominate(false).fair(false).build_and_execute(|| { // Confirm validator count is 2 assert_eq!(Staking::validator_count(), 2); // Confirm account 10 and 20 are validators @@ -1401,9 +1432,6 @@ fn reward_to_stake_works() { // -- new infos assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 11).total, 1000 + total_payout_0 / 2); assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 21).total, 69 + total_payout_0 / 2); - - check_exposure_all(Staking::active_era().unwrap().index); - check_nominator_all(Staking::active_era().unwrap().index); }); } @@ -1411,7 +1439,7 @@ fn reward_to_stake_works() { 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 - ExtBuilder::default().existential_deposit(10).build().execute_with(|| { + ExtBuilder::default().existential_deposit(10).build_and_execute(|| { // Check the balance of the validator account assert_eq!(Balances::free_balance(10), 256); // Check the balance of the stash account @@ -1430,7 +1458,7 @@ fn on_free_balance_zero_stash_removes_validator() { assert!(>::contains_key(&11)); // Reduce free_balance of controller to 0 - let _ = Balances::slash(&10, u64::max_value()); + let _ = Balances::slash(&10, Balance::max_value()); // Check the balance of the stash account has not been touched assert_eq!(Balances::free_balance(11), 256000); @@ -1444,12 +1472,12 @@ fn on_free_balance_zero_stash_removes_validator() { assert!(>::contains_key(&11)); // Reduce free_balance of stash to 0 - let _ = Balances::slash(&11, u64::max_value()); + let _ = Balances::slash(&11, Balance::max_value()); // Check total balance of stash assert_eq!(Balances::total_balance(&11), 0); // Reap the stash - assert_ok!(Staking::reap_stash(Origin::NONE, 11)); + assert_ok!(Staking::reap_stash(Origin::none(), 11, 0)); // Check storage items do not exist assert!(!>::contains_key(&10)); @@ -1464,7 +1492,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 - ExtBuilder::default().existential_deposit(10).build().execute_with(|| { + ExtBuilder::default().existential_deposit(10).build_and_execute(|| { // Make 10 a nominator assert_ok!(Staking::nominate(Origin::signed(10), vec![20])); // Check that account 10 is a nominator @@ -1484,7 +1512,7 @@ fn on_free_balance_zero_stash_removes_nominator() { assert!(>::contains_key(&11)); // Reduce free_balance of controller to 0 - let _ = Balances::slash(&10, u64::max_value()); + let _ = Balances::slash(&10, Balance::max_value()); // Check total balance of account 10 assert_eq!(Balances::total_balance(&10), 0); @@ -1500,12 +1528,12 @@ fn on_free_balance_zero_stash_removes_nominator() { assert!(>::contains_key(&11)); // Reduce free_balance of stash to 0 - let _ = Balances::slash(&11, u64::max_value()); + let _ = Balances::slash(&11, Balance::max_value()); // Check total balance of stash assert_eq!(Balances::total_balance(&11), 0); // Reap the stash - assert_ok!(Staking::reap_stash(Origin::NONE, 11)); + assert_ok!(Staking::reap_stash(Origin::none(), 11, 0)); // Check storage items do not exist assert!(!>::contains_key(&10)); @@ -1520,7 +1548,7 @@ fn on_free_balance_zero_stash_removes_nominator() { #[test] fn switching_roles() { // Test that it should be possible to switch between roles (nominator, validator, idle) with minimal overhead. - ExtBuilder::default().nominate(false).build().execute_with(|| { + ExtBuilder::default().nominate(false).build_and_execute(|| { // Reset reward destination for i in &[10, 20] { assert_ok!(Staking::set_payee(Origin::signed(*i), RewardDestination::Controller)); } @@ -1557,15 +1585,12 @@ fn switching_roles() { mock::start_era(2); assert_eq_uvec!(validator_controllers(), vec![2, 20]); - - check_exposure_all(Staking::active_era().unwrap().index); - check_nominator_all(Staking::active_era().unwrap().index); }); } #[test] fn wrong_vote_is_null() { - ExtBuilder::default().nominate(false).validator_pool(true).build().execute_with(|| { + ExtBuilder::default().nominate(false).validator_pool(true).build_and_execute(|| { assert_eq_uvec!(validator_controllers(), vec![40, 30]); // put some money in account that we'll use. @@ -1622,14 +1647,14 @@ fn bond_with_no_staked_value() { mock::start_era(2); // not yet removed. - assert_ok!(Staking::withdraw_unbonded(Origin::signed(2))); + assert_ok!(Staking::withdraw_unbonded(Origin::signed(2), 0)); assert!(Staking::ledger(2).is_some()); assert_eq!(Balances::locks(&1)[0].amount, 5); mock::start_era(3); // poof. Account 1 is removed from the staking system. - assert_ok!(Staking::withdraw_unbonded(Origin::signed(2))); + assert_ok!(Staking::withdraw_unbonded(Origin::signed(2), 0)); assert!(Staking::ledger(2).is_none()); assert_eq!(Balances::locks(&1).len(), 0); }); @@ -1687,8 +1712,6 @@ fn bond_with_little_staked_value_bounded() { Balances::free_balance(&10), init_balance_10 + total_payout_0 / 3 + total_payout_1 / 3, ); - check_exposure_all(Staking::active_era().unwrap().index); - check_nominator_all(Staking::active_era().unwrap().index); }); } @@ -1707,80 +1730,39 @@ fn new_era_elects_correct_number_of_validators() { Session::on_initialize(System::block_number()); assert_eq!(validator_controllers().len(), 1); - check_exposure_all(Staking::active_era().unwrap().index); - check_nominator_all(Staking::active_era().unwrap().index); }) } #[test] -fn phragmen_should_not_overflow_validators() { - ExtBuilder::default().nominate(false).build().execute_with(|| { - let _ = Staking::chill(Origin::signed(10)); - let _ = Staking::chill(Origin::signed(20)); - - bond_validator(3, 2, u64::max_value()); - bond_validator(5, 4, u64::max_value()); - - bond_nominator(7, 6, u64::max_value() / 2, vec![3, 5]); - bond_nominator(9, 8, u64::max_value() / 2, vec![3, 5]); +fn phragmen_should_not_overflow() { + ExtBuilder::default().nominate(false).build_and_execute(|| { + // This is the maximum value that we can have as the outcome of CurrencyToVote. + type Votes = u64; - mock::start_era(1); - - assert_eq_uvec!(validator_controllers(), vec![4, 2]); - - // This test will fail this. Will saturate. - // check_exposure_all(); - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 3).total, u64::max_value()); - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 5).total, u64::max_value()); - }) -} - -#[test] -fn phragmen_should_not_overflow_nominators() { - ExtBuilder::default().nominate(false).build().execute_with(|| { let _ = Staking::chill(Origin::signed(10)); let _ = Staking::chill(Origin::signed(20)); - bond_validator(3, 2, u64::max_value() / 2); - bond_validator(5, 4, u64::max_value() / 2); + bond_validator(3, 2, Votes::max_value() as Balance); + bond_validator(5, 4, Votes::max_value() as Balance); - bond_nominator(7, 6, u64::max_value(), vec![3, 5]); - bond_nominator(9, 8, u64::max_value(), vec![3, 5]); + bond_nominator(7, 6, Votes::max_value() as Balance, vec![3, 5]); + bond_nominator(9, 8, Votes::max_value() as Balance, vec![3, 5]); mock::start_era(1); assert_eq_uvec!(validator_controllers(), vec![4, 2]); - // Saturate. - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 3).total, u64::max_value()); - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 5).total, u64::max_value()); + // We can safely convert back to values within [u64, u128]. + assert!(Staking::eras_stakers(active_era(), 3).total > Votes::max_value() as Balance); + assert!(Staking::eras_stakers(active_era(), 5).total > Votes::max_value() as Balance); }) } #[test] -fn phragmen_should_not_overflow_ultimate() { - ExtBuilder::default().nominate(false).build().execute_with(|| { - bond_validator(3, 2, u64::max_value()); - bond_validator(5, 4, u64::max_value()); - - bond_nominator(7, 6, u64::max_value(), vec![3, 5]); - bond_nominator(9, 8, u64::max_value(), vec![3, 5]); - - mock::start_era(1); - - assert_eq_uvec!(validator_controllers(), vec![4, 2]); - - // Saturate. - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 3).total, u64::max_value()); - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 5).total, u64::max_value()); - }) -} - -#[test] -fn reward_validator_slashing_validator_doesnt_overflow() { - ExtBuilder::default().build().execute_with(|| { - let stake = u32::max_value() as u64 * 2; - let reward_slash = u32::max_value() as u64 * 2; +fn reward_validator_slashing_validator_does_not_overflow() { + ExtBuilder::default().build_and_execute(|| { + let stake = u64::max_value() as Balance * 2; + let reward_slash = u64::max_value() as Balance * 2; // Assert multiplication overflows in balance arithmetic. assert!(stake.checked_mul(reward_slash).is_none()); @@ -1834,7 +1816,7 @@ fn reward_validator_slashing_validator_doesnt_overflow() { #[test] fn reward_from_authorship_event_handler_works() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { use pallet_authorship::EventHandler; assert_eq!(>::author(), 11); @@ -1861,7 +1843,7 @@ fn reward_from_authorship_event_handler_works() { #[test] fn add_reward_points_fns_works() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Not mandatory but must be coherent with rewards assert_eq!(Session::validators(), vec![21, 11]); @@ -1889,7 +1871,7 @@ fn add_reward_points_fns_works() { #[test] fn unbonded_balance_is_not_slashable() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // total amount staked is slashable. assert_eq!(Staking::slashable_balance_of(&11), 1000); @@ -1904,30 +1886,30 @@ fn unbonded_balance_is_not_slashable() { 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(|| { + ExtBuilder::default().build_and_execute(|| { let session_per_era = >::get(); mock::start_era(1); - assert_eq!(Staking::eras_start_session_index(active_era()).unwrap(), session_per_era); + assert_eq!(Staking::eras_start_session_index(current_era()).unwrap(), session_per_era); mock::start_era(2); - assert_eq!(Staking::eras_start_session_index(active_era()).unwrap(), session_per_era * 2u32); + assert_eq!(Staking::eras_start_session_index(current_era()).unwrap(), session_per_era * 2u32); let session = Session::current_index(); ForceEra::put(Forcing::ForceNew); advance_session(); advance_session(); - assert_eq!(Staking::active_era().unwrap().index, 3); - assert_eq!(Staking::eras_start_session_index(active_era()).unwrap(), session + 2); + assert_eq!(current_era(), 3); + assert_eq!(Staking::eras_start_session_index(current_era()).unwrap(), session + 2); mock::start_era(4); - assert_eq!(Staking::eras_start_session_index(active_era()).unwrap(), session + 2u32 + session_per_era); + assert_eq!(Staking::eras_start_session_index(current_era()).unwrap(), session + 2u32 + session_per_era); }); } #[test] fn offence_forces_new_era() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { on_offence_now( &[OffenceDetails { offender: ( @@ -1945,8 +1927,8 @@ fn offence_forces_new_era() { #[test] fn offence_ensures_new_era_without_clobbering() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Staking::force_new_era_always(Origin::ROOT)); + ExtBuilder::default().build_and_execute(|| { + assert_ok!(Staking::force_new_era_always(Origin::root())); assert_eq!(Staking::force_era(), Forcing::ForceAlways); on_offence_now( @@ -1966,7 +1948,7 @@ fn offence_ensures_new_era_without_clobbering() { #[test] fn offence_deselects_validator_even_when_slash_is_zero() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { assert!(Session::validators().contains(&11)); assert!(>::contains_key(11)); @@ -1995,7 +1977,7 @@ fn offence_deselects_validator_even_when_slash_is_zero() { 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(|| { + ExtBuilder::default().build_and_execute(|| { assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 11).own, 1000); // Handle an offence with a historical exposure. @@ -2021,7 +2003,7 @@ fn slashing_performed_according_exposure() { #[test] fn slash_in_old_span_does_not_deselect() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { mock::start_era(1); assert!(>::contains_key(11)); @@ -2087,7 +2069,6 @@ fn slash_in_old_span_does_not_deselect() { assert_eq!(Staking::force_era(), Forcing::NotForcing); assert!(>::contains_key(11)); assert!(Session::validators().contains(&11)); - assert_ledger_consistent(11); }); } @@ -2095,7 +2076,7 @@ fn slash_in_old_span_does_not_deselect() { 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(|| { + ExtBuilder::default().build_and_execute(|| { // The reporters' reward is calculated from the total exposure. let initial_balance = 1125; @@ -2118,7 +2099,6 @@ fn reporters_receive_their_slice() { let reward_each = reward / 2; // split into two pieces. assert_eq!(Balances::free_balance(1), 10 + reward_each); assert_eq!(Balances::free_balance(2), 20 + reward_each); - assert_ledger_consistent(11); }); } @@ -2126,7 +2106,7 @@ fn reporters_receive_their_slice() { fn subsequent_reports_in_same_span_pay_out_less() { // This test verifies that the reporters of the offence receive their slice from the slashed // amount, but less and less if they submit multiple reports in one span. - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // The reporters' reward is calculated from the total exposure. let initial_balance = 1125; @@ -2165,14 +2145,13 @@ fn subsequent_reports_in_same_span_pay_out_less() { // 50% * (10% * (initial_balance / 2) - prior_payout) let reward = ((initial_balance / 20) - prior_payout) / 2; assert_eq!(Balances::free_balance(1), 10 + prior_payout + reward); - assert_ledger_consistent(11); }); } #[test] fn invulnerables_are_not_slashed() { // For invulnerable validators no slashing is performed. - ExtBuilder::default().invulnerables(vec![11]).build().execute_with(|| { + ExtBuilder::default().invulnerables(vec![11]).build_and_execute(|| { assert_eq!(Balances::free_balance(11), 1000); assert_eq!(Balances::free_balance(21), 2000); @@ -2208,15 +2187,13 @@ fn invulnerables_are_not_slashed() { initial_balance - (2 * other.value / 10), ); } - assert_ledger_consistent(11); - assert_ledger_consistent(21); }); } #[test] fn dont_slash_if_fraction_is_zero() { // Don't slash if the fraction is zero. - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { assert_eq!(Balances::free_balance(11), 1000); on_offence_now( @@ -2233,8 +2210,6 @@ fn dont_slash_if_fraction_is_zero() { // The validator hasn't been slashed. The new era is not forced. assert_eq!(Balances::free_balance(11), 1000); assert_eq!(Staking::force_era(), Forcing::ForceNew); - - assert_ledger_consistent(11); }); } @@ -2242,7 +2217,7 @@ fn dont_slash_if_fraction_is_zero() { fn only_slash_for_max_in_era() { // multiple slashes within one era are only applied if it is more than any previous slash in the // same era. - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { assert_eq!(Balances::free_balance(11), 1000); on_offence_now( @@ -2284,14 +2259,13 @@ fn only_slash_for_max_in_era() { // The validator got slashed 10% more. assert_eq!(Balances::free_balance(11), 400); - assert_ledger_consistent(11); }) } #[test] fn garbage_collection_after_slashing() { // ensures that `SlashingSpans` and `SpanSlash` of an account is removed after reaping. - ExtBuilder::default().existential_deposit(2).build().execute_with(|| { + ExtBuilder::default().existential_deposit(2).build_and_execute(|| { assert_eq!(Balances::free_balance(11), 256_000); on_offence_now( @@ -2324,7 +2298,12 @@ fn garbage_collection_after_slashing() { assert_eq!(Balances::free_balance(11), 0); assert_eq!(Balances::total_balance(&11), 0); - assert_ok!(Staking::reap_stash(Origin::NONE, 11)); + let slashing_spans = ::SlashingSpans::get(&11).unwrap(); + assert_eq!(slashing_spans.iter().count(), 2); + + // reap_stash respects num_slashing_spans so that weight is accurate + assert_noop!(Staking::reap_stash(Origin::none(), 11, 0), Error::::IncorrectSlashingSpans); + assert_ok!(Staking::reap_stash(Origin::none(), 11, 2)); assert!(::SlashingSpans::get(&11).is_none()); assert_eq!(::SpanSlash::get(&(11, 0)).amount_slashed(), &0); @@ -2335,7 +2314,7 @@ fn garbage_collection_after_slashing() { fn garbage_collection_on_window_pruning() { // ensures that `ValidatorSlashInEra` and `NominatorSlashInEra` are cleared after // `BondingDuration`. - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { mock::start_era(1); assert_eq!(Balances::free_balance(11), 1000); @@ -2376,7 +2355,7 @@ fn garbage_collection_on_window_pruning() { #[test] fn slashing_nominators_by_span_max() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { mock::start_era(1); mock::start_era(2); mock::start_era(3); @@ -2474,7 +2453,7 @@ fn slashing_nominators_by_span_max() { #[test] fn slashes_are_summed_across_spans() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { mock::start_era(1); mock::start_era(2); mock::start_era(3); @@ -2532,7 +2511,7 @@ fn slashes_are_summed_across_spans() { #[test] fn deferred_slashes_are_deferred() { - ExtBuilder::default().slash_defer_duration(2).build().execute_with(|| { + ExtBuilder::default().slash_defer_duration(2).build_and_execute(|| { mock::start_era(1); assert_eq!(Balances::free_balance(11), 1000); @@ -2575,7 +2554,7 @@ fn deferred_slashes_are_deferred() { #[test] fn remove_deferred() { - ExtBuilder::default().slash_defer_duration(2).build().execute_with(|| { + ExtBuilder::default().slash_defer_duration(2).build_and_execute(|| { mock::start_era(1); assert_eq!(Balances::free_balance(11), 1000); @@ -2612,11 +2591,11 @@ fn remove_deferred() { // fails if empty assert_noop!( - Staking::cancel_deferred_slash(Origin::ROOT, 1, vec![]), + Staking::cancel_deferred_slash(Origin::root(), 1, vec![]), Error::::EmptyTargets ); - assert_ok!(Staking::cancel_deferred_slash(Origin::ROOT, 1, vec![0])); + assert_ok!(Staking::cancel_deferred_slash(Origin::root(), 1, vec![0])); assert_eq!(Balances::free_balance(11), 1000); assert_eq!(Balances::free_balance(101), 2000); @@ -2651,7 +2630,7 @@ fn remove_deferred() { #[test] fn remove_multi_deferred() { - ExtBuilder::default().slash_defer_duration(2).build().execute_with(|| { + ExtBuilder::default().slash_defer_duration(2).build_and_execute(|| { mock::start_era(1); assert_eq!(Balances::free_balance(11), 1000); @@ -2713,21 +2692,21 @@ fn remove_multi_deferred() { // fails if list is not sorted assert_noop!( - Staking::cancel_deferred_slash(Origin::ROOT, 1, vec![2, 0, 4]), + Staking::cancel_deferred_slash(Origin::root(), 1, vec![2, 0, 4]), Error::::NotSortedAndUnique ); // fails if list is not unique assert_noop!( - Staking::cancel_deferred_slash(Origin::ROOT, 1, vec![0, 2, 2]), + Staking::cancel_deferred_slash(Origin::root(), 1, vec![0, 2, 2]), Error::::NotSortedAndUnique ); // fails if bad index assert_noop!( - Staking::cancel_deferred_slash(Origin::ROOT, 1, vec![1, 2, 3, 4, 5]), + Staking::cancel_deferred_slash(Origin::root(), 1, vec![1, 2, 3, 4, 5]), Error::::InvalidSlashIndex ); - assert_ok!(Staking::cancel_deferred_slash(Origin::ROOT, 1, vec![0, 2, 4])); + assert_ok!(Staking::cancel_deferred_slash(Origin::root(), 1, vec![0, 2, 4])); let slashes = ::UnappliedSlashes::get(&1); assert_eq!(slashes.len(), 2); @@ -2738,7 +2717,11 @@ fn remove_multi_deferred() { mod offchain_phragmen { use crate::*; - use frame_support::{assert_noop, assert_ok}; + use codec::Encode; + use frame_support::{ + assert_noop, assert_ok, assert_err_with_weight, + dispatch::DispatchResultWithPostInfo, + }; use sp_runtime::transaction_validity::TransactionSource; use mock::*; use parking_lot::RwLock; @@ -2747,7 +2730,7 @@ mod offchain_phragmen { OffchainExt, TransactionPoolExt, }; use sp_io::TestExternalities; - use sp_phragmen::StakedAssignment; + use sp_npos_elections::StakedAssignment; use frame_support::traits::OffchainWorker; use std::sync::Arc; use substrate_test_utils::assert_eq_uvec; @@ -2758,7 +2741,7 @@ mod offchain_phragmen { /// setup a new set of validators and nominator storage items independent of the parent mock /// file. This produces a edge graph that can be reduced. - fn build_offchain_phragmen_test_ext() { + pub fn build_offchain_phragmen_test_ext() { for i in (10..=40).step_by(10) { // Note: we respect the convention of the mock (10, 11 pairs etc.) since these accounts // have corresponding keys in session which makes everything more ergonomic and @@ -2778,14 +2761,42 @@ mod offchain_phragmen { bond_nominator(voter, 1000 + voter, 100, vec![21, 31, 41]); } - fn offchainify(ext: &mut TestExternalities) -> Arc> { - let (offchain, _state) = TestOffchainExt::new(); - let (pool, state) = TestTransactionPoolExt::new(); + /// convert an externalities to one that can handle offchain worker tests. + fn offchainify(ext: &mut TestExternalities, iterations: u32) -> Arc> { + let (offchain, offchain_state) = TestOffchainExt::new(); + let (pool, pool_state) = TestTransactionPoolExt::new(); + + let mut seed = [0_u8; 32]; + seed[0..4].copy_from_slice(&iterations.to_le_bytes()); + offchain_state.write().seed = seed; ext.register_extension(OffchainExt::new(offchain)); ext.register_extension(TransactionPoolExt::new(pool)); - state + pool_state + } + + fn election_size() -> ElectionSize { + ElectionSize { + validators: Staking::snapshot_validators().unwrap().len() as ValidatorIndex, + nominators: Staking::snapshot_nominators().unwrap().len() as NominatorIndex, + } + } + + fn submit_solution( + origin: Origin, + winners: Vec, + compact: CompactAssignments, + score: ElectionScore, + ) -> DispatchResultWithPostInfo { + Staking::submit_election_solution( + origin, + winners, + compact, + score, + current_era(), + election_size(), + ) } #[test] @@ -2813,7 +2824,7 @@ mod offchain_phragmen { } #[test] - fn offchain_election_flag_is_triggered() { + fn offchain_window_is_triggered() { ExtBuilder::default() .session_per_era(5) .session_length(10) @@ -2873,8 +2884,105 @@ mod offchain_phragmen { } #[test] - fn election_on_chain_fallback_works() { - ExtBuilder::default().build().execute_with(|| { + fn offchain_window_is_triggered_when_forcing() { + ExtBuilder::default() + .session_per_era(5) + .session_length(10) + .election_lookahead(3) + .build() + .execute_with(|| { + run_to_block(12); + ForceEra::put(Forcing::ForceNew); + run_to_block(13); + assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); + + run_to_block(17); // instead of 47 + assert_eq!(Staking::era_election_status(), ElectionStatus::Open(17)); + + run_to_block(20); + assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); + }) + } + + #[test] + fn offchain_window_is_triggered_when_force_always() { + ExtBuilder::default() + .session_per_era(5) + .session_length(10) + .election_lookahead(3) + .build() + .execute_with(|| { + + ForceEra::put(Forcing::ForceAlways); + run_to_block(16); + assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); + + run_to_block(17); // instead of 37 + assert_eq!(Staking::era_election_status(), ElectionStatus::Open(17)); + + run_to_block(20); + assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); + + run_to_block(26); + assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); + + run_to_block(27); // next one again + assert_eq!(Staking::era_election_status(), ElectionStatus::Open(27)); + }) + } + + #[test] + fn offchain_window_closes_when_forcenone() { + ExtBuilder::default() + .session_per_era(5) + .session_length(10) + .election_lookahead(3) + .build() + .execute_with(|| { + ForceEra::put(Forcing::ForceNone); + + run_to_block(36); + assert_session_era!(3, 0); + assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); + + // opens + run_to_block(37); + assert_eq!(Staking::era_election_status(), ElectionStatus::Open(37)); + assert!(Staking::is_current_session_final()); + assert!(Staking::snapshot_validators().is_some()); + + // closes normally + run_to_block(40); + assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); + assert!(!Staking::is_current_session_final()); + assert!(Staking::snapshot_validators().is_none()); + assert_session_era!(4, 0); + + run_to_block(47); + assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); + assert_session_era!(4, 0); + + run_to_block(57); + assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); + assert_session_era!(5, 0); + + run_to_block(67); + assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); + + // Will not open again as scheduled + run_to_block(87); + assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); + assert_session_era!(8, 0); + + run_to_block(90); + assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); + assert_session_era!(9, 0); + }) + } + + #[test] + fn offchain_window_on_chain_fallback_works() { + ExtBuilder::default().build_and_execute(|| { start_session(1); start_session(2); assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); @@ -2902,7 +3010,6 @@ mod offchain_phragmen { fn offchain_wont_work_if_snapshot_fails() { ExtBuilder::default() .offchain_phragmen_ext() - .election_lookahead(3) .build() .execute_with(|| { run_to_block(12); @@ -2932,23 +3039,21 @@ mod offchain_phragmen { .execute_with(|| { run_to_block(12); assert!(Staking::snapshot_validators().is_some()); + // given assert_eq!(Staking::era_election_status(), ElectionStatus::Open(12)); - let call = crate::Call::bond(999, 998, Default::default()); - let outer: mock::Call = call.into(); - - let lock_staking: LockStakingStatus = Default::default(); - assert_eq!( - lock_staking.validate(&10, &outer, Default::default(), Default::default(),), - TransactionValidity::Err(InvalidTransaction::Stale.into()), - ) + // chill et. al. are now not allowed. + assert_noop!( + Staking::chill(Origin::signed(10)), + Error::::CallNotAllowed, + ); }) } #[test] fn signed_result_can_be_submitted() { - // should check that we have a new validator set normally, - // event says that it comes from offchain. + // should check that we have a new validator set normally, event says that it comes from + // offchain. ExtBuilder::default() .offchain_phragmen_ext() .build() @@ -2957,17 +3062,31 @@ mod offchain_phragmen { assert_eq!(Staking::era_election_status(), ElectionStatus::Open(12)); assert!(Staking::snapshot_validators().is_some()); - let (compact, winners, score) = prepare_submission_with(true, |_| {}); - assert_ok!(Staking::submit_election_solution( + let (compact, winners, score) = prepare_submission_with(true, 2, |_| {}); + assert_ok!(submit_solution( Origin::signed(10), winners, compact, score, - active_era(), )); let queued_result = Staking::queued_elected().unwrap(); assert_eq!(queued_result.compute, ElectionCompute::Signed); + assert_eq!( + System::events() + .into_iter() + .map(|r| r.event) + .filter_map(|e| { + if let MetaEvent::staking(inner) = e { + Some(inner) + } else { + None + } + }) + .last() + .unwrap(), + RawEvent::SolutionStored(ElectionCompute::Signed), + ); run_to_block(15); assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); @@ -3000,14 +3119,8 @@ mod offchain_phragmen { run_to_block(14); assert_eq!(Staking::era_election_status(), ElectionStatus::Open(12)); - let (compact, winners, score) = prepare_submission_with(true, |_| {}); - assert_ok!(Staking::submit_election_solution( - Origin::signed(10), - winners, - compact, - score, - active_era(), - )); + let (compact, winners, score) = prepare_submission_with(true, 2, |_| {}); + assert_ok!(submit_solution(Origin::signed(10), winners, compact, score)); let queued_result = Staking::queued_elected().unwrap(); assert_eq!(queued_result.compute, ElectionCompute::Signed); @@ -3035,8 +3148,8 @@ mod offchain_phragmen { #[test] fn early_solution_submission_is_rejected() { - // should check that we have a new validator set normally, - // event says that it comes from offchain. + // should check that we have a new validator set normally, event says that it comes from + // offchain. ExtBuilder::default() .offchain_phragmen_ext() .build() @@ -3047,18 +3160,20 @@ mod offchain_phragmen { // create all the indices just to build the solution. Staking::create_stakers_snapshot(); - let (compact, winners, score) = prepare_submission_with(true, |_| {}); + let (compact, winners, score) = prepare_submission_with(true, 2, |_| {}); Staking::kill_stakers_snapshot(); - assert_noop!( + assert_err_with_weight!( Staking::submit_election_solution( Origin::signed(10), - winners, - compact, + winners.clone(), + compact.clone(), score, - active_era(), + current_era(), + ElectionSize::default(), ), Error::::PhragmenEarlySubmission, + Some(::DbWeight::get().reads(1)), ); }) } @@ -3076,26 +3191,25 @@ mod offchain_phragmen { run_to_block(12); // a good solution - let (compact, winners, score) = prepare_submission_with(true, |_| {}); - assert_ok!(Staking::submit_election_solution( + let (compact, winners, score) = prepare_submission_with(true, 2, |_| {}); + assert_ok!(submit_solution( Origin::signed(10), winners, compact, score, - active_era(), )); // a bad solution let (compact, winners, score) = horrible_phragmen_with_post_processing(false); - assert_noop!( - Staking::submit_election_solution( + assert_err_with_weight!( + submit_solution( Origin::signed(10), - winners, - compact, + winners.clone(), + compact.clone(), score, - active_era(), ), Error::::PhragmenWeakSubmission, + Some(::DbWeight::get().reads(3)) ); }) } @@ -3114,22 +3228,20 @@ mod offchain_phragmen { // a meeeeh solution let (compact, winners, score) = horrible_phragmen_with_post_processing(false); - assert_ok!(Staking::submit_election_solution( + assert_ok!(submit_solution( Origin::signed(10), winners, compact, score, - active_era(), )); // a better solution - let (compact, winners, score) = prepare_submission_with(true, |_| {}); - assert_ok!(Staking::submit_election_solution( + let (compact, winners, score) = prepare_submission_with(true, 2, |_| {}); + assert_ok!(submit_solution( Origin::signed(10), winners, compact, score, - active_era(), )); }) } @@ -3141,7 +3253,50 @@ mod offchain_phragmen { .offchain_phragmen_ext() .validator_count(2) .build(); - let state = offchainify(&mut ext); + let state = offchainify(&mut ext, 0); + ext.execute_with(|| { + run_to_block(12); + + // local key 11 is in the elected set. + assert_eq_uvec!(Session::validators(), vec![11, 21]); + assert_eq!(state.read().transactions.len(), 0); + Staking::offchain_worker(12); + assert_eq!(state.read().transactions.len(), 1); + + let encoded = state.read().transactions[0].clone(); + let extrinsic: Extrinsic = Decode::decode(&mut &*encoded).unwrap(); + + let call = extrinsic.call; + let inner = match call { + mock::Call::Staking(inner) => inner, + }; + + assert_eq!( + ::validate_unsigned( + TransactionSource::Local, + &inner, + ), + TransactionValidity::Ok(ValidTransaction { + priority: UnsignedPriority::get() + 1125, // the proposed slot stake. + requires: vec![], + provides: vec![("StakingOffchain", current_era()).encode()], + longevity: 3, + propagate: false, + }) + ) + }) + } + + #[test] + fn offchain_worker_runs_with_equalise() { + // Offchain worker equalises based on the number provided by randomness. See the difference + // in the priority, which comes from the computed score. + let mut ext = ExtBuilder::default() + .offchain_phragmen_ext() + .validator_count(2) + .max_offchain_iterations(2) + .build(); + let state = offchainify(&mut ext, 2); ext.execute_with(|| { run_to_block(12); @@ -3165,7 +3320,8 @@ mod offchain_phragmen { &inner, ), TransactionValidity::Ok(ValidTransaction { - priority: 1125, // the proposed slot stake. + // the proposed slot stake, with balance_solution. + priority: UnsignedPriority::get() + 1250, requires: vec![], provides: vec![("StakingOffchain", active_era()).encode()], longevity: 3, @@ -3181,17 +3337,16 @@ mod offchain_phragmen { .offchain_phragmen_ext() .validator_count(4) .build(); - let state = offchainify(&mut ext); + let state = offchainify(&mut ext, 0); ext.execute_with(|| { run_to_block(12); // put a good solution on-chain - let (compact, winners, score) = prepare_submission_with(true, |_| {}); - assert_ok!(Staking::submit_election_solution( + let (compact, winners, score) = prepare_submission_with(true, 2, |_| {}); + assert_ok!(submit_solution( Origin::signed(10), winners, compact, score, - active_era(), ),); // now run the offchain worker in the same chain state. @@ -3231,24 +3386,47 @@ mod offchain_phragmen { run_to_block(12); ValidatorCount::put(3); - let (compact, winners, score) = prepare_submission_with(true, |_| {}); + let (compact, winners, score) = prepare_submission_with(true, 2, |_| {}); ValidatorCount::put(4); assert_eq!(winners.len(), 3); assert_noop!( - Staking::submit_election_solution( + submit_solution( Origin::signed(10), winners, compact, score, - active_era(), ), Error::::PhragmenBogusWinnerCount, ); }) } + #[test] + fn invalid_phragmen_result_solution_size() { + ExtBuilder::default() + .offchain_phragmen_ext() + .build() + .execute_with(|| { + run_to_block(12); + + let (compact, winners, score) = prepare_submission_with(true, 2, |_| {}); + + assert_noop!( + Staking::submit_election_solution( + Origin::signed(10), + winners, + compact, + score, + current_era(), + ElectionSize::default(), + ), + Error::::PhragmenBogusElectionSize, + ); + }) + } + #[test] fn invalid_phragmen_result_correct_number_of_winners_1() { // if we have too little validators, then the number of candidates is the bound. @@ -3262,18 +3440,17 @@ mod offchain_phragmen { run_to_block(12); ValidatorCount::put(3); - let (compact, winners, score) = prepare_submission_with(true, |_| {}); + let (compact, winners, score) = prepare_submission_with(true, 2, |_| {}); ValidatorCount::put(4); assert_eq!(winners.len(), 3); assert_noop!( - Staking::submit_election_solution( + submit_solution( Origin::signed(10), winners, compact, score, - active_era(), ), Error::::PhragmenBogusWinnerCount, ); @@ -3292,17 +3469,16 @@ mod offchain_phragmen { build_offchain_phragmen_test_ext(); run_to_block(12); - let (compact, winners, score) = prepare_submission_with(true, |_| {}); + let (compact, winners, score) = prepare_submission_with(true, 2, |_| {}); assert_eq!(winners.len(), 4); // all good. We chose 4 and it works. - assert_ok!(Staking::submit_election_solution( + assert_ok!(submit_solution( Origin::signed(10), winners, compact, score, - active_era(), ),); }) } @@ -3321,19 +3497,18 @@ mod offchain_phragmen { assert_eq!(Staking::snapshot_nominators().unwrap().len(), 5 + 4); assert_eq!(Staking::snapshot_validators().unwrap().len(), 4); - let (mut compact, winners, score) = prepare_submission_with(true, |_| {}); + let (mut compact, winners, score) = prepare_submission_with(true, 2, |_| {}); // index 9 doesn't exist. compact.votes1.push((9, 2)); // The error type sadly cannot be more specific now. assert_noop!( - Staking::submit_election_solution( + submit_solution( Origin::signed(10), winners, compact, score, - active_era(), ), Error::::PhragmenBogusCompact, ); @@ -3354,19 +3529,18 @@ mod offchain_phragmen { assert_eq!(Staking::snapshot_nominators().unwrap().len(), 5 + 4); assert_eq!(Staking::snapshot_validators().unwrap().len(), 4); - let (mut compact, winners, score) = prepare_submission_with(true, |_| {}); + let (mut compact, winners, score) = prepare_submission_with(true, 2, |_| {}); // index 4 doesn't exist. compact.votes1.push((3, 4)); // The error type sadly cannot be more specific now. assert_noop!( - Staking::submit_election_solution( + submit_solution( Origin::signed(10), winners, compact, score, - active_era(), ), Error::::PhragmenBogusCompact, ); @@ -3387,18 +3561,17 @@ mod offchain_phragmen { assert_eq!(Staking::snapshot_nominators().unwrap().len(), 5 + 4); assert_eq!(Staking::snapshot_validators().unwrap().len(), 4); - let (compact, _, score) = prepare_submission_with(true, |_| {}); + let (compact, _, score) = prepare_submission_with(true, 2, |_| {}); // index 4 doesn't exist. let winners = vec![0, 1, 2, 4]; assert_noop!( - Staking::submit_election_solution( + submit_solution( Origin::signed(10), winners, compact, score, - active_era(), ), Error::::PhragmenBogusWinner, ); @@ -3420,7 +3593,7 @@ mod offchain_phragmen { assert_eq!(Staking::snapshot_nominators().unwrap().len(), 5 + 4); assert_eq!(Staking::snapshot_validators().unwrap().len(), 4); - let (compact, winners, score) = prepare_submission_with(true, |a| { + let (compact, winners, score) = prepare_submission_with(true, 2, |a| { a.iter_mut() .find(|x| x.who == 5) // all 3 cannot be among the winners. Although, all of them are validator @@ -3429,12 +3602,11 @@ mod offchain_phragmen { }); assert_noop!( - Staking::submit_election_solution( + submit_solution( Origin::signed(10), winners, compact, score, - active_era(), ), Error::::PhragmenBogusEdge, ); @@ -3453,7 +3625,7 @@ mod offchain_phragmen { build_offchain_phragmen_test_ext(); run_to_block(12); - let (compact, winners, score) = prepare_submission_with(true, |a| { + let (compact, winners, score) = prepare_submission_with(true, 2, |a| { // mutate a self vote to target someone else. That someone else is still among the // winners a.iter_mut().find(|x| x.who == 11).map(|x| { @@ -3465,12 +3637,11 @@ mod offchain_phragmen { }); assert_noop!( - Staking::submit_election_solution( + submit_solution( Origin::signed(10), winners, compact, score, - active_era(), ), Error::::PhragmenBogusSelfVote, ); @@ -3489,7 +3660,7 @@ mod offchain_phragmen { build_offchain_phragmen_test_ext(); run_to_block(12); - let (compact, winners, score) = prepare_submission_with(true, |a| { + let (compact, winners, score) = prepare_submission_with(true, 2, |a| { // Remove the self vote. a.retain(|x| x.who != 11); // add is as a new double vote @@ -3501,12 +3672,11 @@ mod offchain_phragmen { // This raises score issue. assert_noop!( - Staking::submit_election_solution( + submit_solution( Origin::signed(10), winners, compact, score, - active_era(), ), Error::::PhragmenBogusSelfVote, ); @@ -3527,7 +3697,7 @@ mod offchain_phragmen { // Note: we don't reduce here to be able to tweak votes3. votes3 will vanish if you // reduce. - let (mut compact, winners, score) = prepare_submission_with(false, |_| {}); + let (mut compact, winners, score) = prepare_submission_with(false, 0, |_| {}); if let Some(c) = compact.votes3.iter_mut().find(|x| x.0 == 0) { // by default it should have been (0, [(2, 33%), (1, 33%)], 0) @@ -3536,12 +3706,11 @@ mod offchain_phragmen { } assert_noop!( - Staking::submit_election_solution( + submit_solution( Origin::signed(10), winners, compact, score, - active_era(), ), Error::::PhragmenBogusCompact, ); @@ -3569,7 +3738,7 @@ mod offchain_phragmen { build_offchain_phragmen_test_ext(); run_to_block(12); - let (compact, winners, score) = prepare_submission_with(false, |a| { + let (compact, winners, score) = prepare_submission_with(false, 0, |a| { // 3 only voted for 20 and 40. We add a fake vote to 30. The stake sum is still // correctly 100. a.iter_mut() @@ -3578,12 +3747,11 @@ mod offchain_phragmen { }); assert_noop!( - Staking::submit_election_solution( + submit_solution( Origin::signed(10), winners, compact, score, - active_era(), ), Error::::PhragmenBogusNomination, ); @@ -3611,7 +3779,7 @@ mod offchain_phragmen { run_to_block(20); // slash 10. This must happen outside of the election window. - let offender_expo = Staking::eras_stakers(active_era(), 11); + let offender_expo = Staking::eras_stakers(Staking::active_era().unwrap().index, 11); on_offence_now( &[OffenceDetails { offender: (11, offender_expo.clone()), @@ -3631,7 +3799,7 @@ mod offchain_phragmen { run_to_block(32); // a solution that has been prepared after the slash. - let (compact, winners, score) = prepare_submission_with(false, |a| { + let (compact, winners, score) = prepare_submission_with(false, 0, |a| { // no one is allowed to vote for 10, except for itself. a.into_iter() .filter(|s| s.who != 11) @@ -3641,16 +3809,15 @@ mod offchain_phragmen { }); // can be submitted. - assert_ok!(Staking::submit_election_solution( + assert_ok!(submit_solution( Origin::signed(10), winners, compact, score, - active_era(), )); // a wrong solution. - let (compact, winners, score) = prepare_submission_with(false, |a| { + let (compact, winners, score) = prepare_submission_with(false, 0, |a| { // add back the vote that has been filtered out. a.push(StakedAssignment { who: 1, @@ -3660,12 +3827,11 @@ mod offchain_phragmen { // is rejected. assert_noop!( - Staking::submit_election_solution( + submit_solution( Origin::signed(10), winners, compact, score, - active_era(), ), Error::::PhragmenSlashedNomination, ); @@ -3684,16 +3850,15 @@ mod offchain_phragmen { build_offchain_phragmen_test_ext(); run_to_block(12); - let (compact, winners, mut score) = prepare_submission_with(true, |_| {}); + let (compact, winners, mut score) = prepare_submission_with(true, 2, |_| {}); score[0] += 1; assert_noop!( - Staking::submit_election_solution( + submit_solution( Origin::signed(10), winners, compact, score, - active_era(), ), Error::::PhragmenBogusScore, ); @@ -3706,7 +3871,7 @@ mod offchain_phragmen { .offchain_phragmen_ext() .validator_count(4) .build(); - let state = offchainify(&mut ext); + let state = offchainify(&mut ext, 0); ext.execute_with(|| { use offchain_election::OFFCHAIN_HEAD_DB; @@ -3730,7 +3895,7 @@ mod offchain_phragmen { .offchain_phragmen_ext() .validator_count(4) .build(); - let _ = offchainify(&mut ext); + let _ = offchainify(&mut ext, 0); ext.execute_with(|| { use offchain_election::OFFCHAIN_HEAD_DB; @@ -3780,7 +3945,7 @@ mod offchain_phragmen { run_to_block(12); assert_eq!(Staking::era_election_status(), ElectionStatus::Open(12)); - let offender_expo = Staking::eras_stakers(active_era(), 10); + let offender_expo = Staking::eras_stakers(Staking::active_era().unwrap().index, 10); // panic from the impl in mock on_offence_now( @@ -3796,7 +3961,7 @@ mod offchain_phragmen { #[test] fn slash_kicks_validators_not_nominators_and_disables_nominator_for_kicked_validator() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { mock::start_era(1); assert_eq_uvec!(Session::validators(), vec![11, 21]); @@ -3805,8 +3970,8 @@ fn slash_kicks_validators_not_nominators_and_disables_nominator_for_kicked_valid assert_eq!(Balances::free_balance(101), 2000); // 11 and 21 both have the support of 100 - let exposure_11 = Staking::eras_stakers(active_era(), &11); - let exposure_21 = Staking::eras_stakers(active_era(), &21); + let exposure_11 = Staking::eras_stakers(Staking::active_era().unwrap().index, &11); + let exposure_21 = Staking::eras_stakers(Staking::active_era().unwrap().index, &21); assert_eq!(exposure_11.total, 1000 + 125); assert_eq!(exposure_21.total, 1000 + 375); @@ -3846,8 +4011,8 @@ fn slash_kicks_validators_not_nominators_and_disables_nominator_for_kicked_valid assert_ok!(Staking::validate(Origin::signed(10), Default::default())); mock::start_era(2); - let exposure_11 = Staking::eras_stakers(active_era(), &11); - let exposure_21 = Staking::eras_stakers(active_era(), &21); + let exposure_11 = Staking::eras_stakers(Staking::active_era().unwrap().index, &11); + let exposure_21 = Staking::eras_stakers(Staking::active_era().unwrap().index, &21); // 10 is re-elected, but without the support of 100 assert_eq!(exposure_11.total, 900); @@ -3863,7 +4028,7 @@ fn claim_reward_at_the_last_era_and_no_double_claim_and_invalid_claim() { // * rewards get paid until history_depth for both validators and nominators // * an invalid era to claim doesn't update last_reward // * double claim of one era fails - ExtBuilder::default().nominate(true).build().execute_with(|| { + ExtBuilder::default().nominate(true).build_and_execute(|| { let init_balance_10 = Balances::total_balance(&10); let init_balance_100 = Balances::total_balance(&100); @@ -3943,12 +4108,12 @@ fn claim_reward_at_the_last_era_and_no_double_claim_and_invalid_claim() { #[test] fn zero_slash_keeps_nominators() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { mock::start_era(1); assert_eq!(Balances::free_balance(11), 1000); - let exposure = Staking::eras_stakers(active_era(), 11); + let exposure = Staking::eras_stakers(Staking::active_era().unwrap().index, 11); assert_eq!(Balances::free_balance(101), 2000); on_offence_now( @@ -3981,7 +4146,7 @@ fn zero_slash_keeps_nominators() { #[test] fn six_session_delay() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { use pallet_session::SessionManager; let val_set = Session::validators(); @@ -4035,11 +4200,11 @@ fn test_max_nominator_rewarded_per_validator_and_cant_steal_someone_else_reward( // * If nominator nomination is below the $MaxNominatorRewardedPerValidator other nominator // then the nominator can't claim its reward // * A nominator can't claim another nominator reward - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { for i in 0..=::MaxNominatorRewardedPerValidator::get() { - let stash = 10_000 + i as u64; - let controller = 20_000 + i as u64; - let balance = 10_000 + i as u64; + let stash = 10_000 + i as AccountId; + let controller = 20_000 + i as AccountId; + let balance = 10_000 + i as Balance; Balances::make_free_balance_be(&stash, balance); assert_ok!( Staking::bond( @@ -4063,8 +4228,8 @@ fn test_max_nominator_rewarded_per_validator_and_cant_steal_someone_else_reward( // Assert only nominators from 1 to Max are rewarded for i in 0..=::MaxNominatorRewardedPerValidator::get() { - let stash = 10_000 + i as u64; - let balance = 10_000 + i as u64; + let stash = 10_000 + i as AccountId; + let balance = 10_000 + i as Balance; if stash == 10_000 { assert!(Balances::free_balance(&stash) == balance); } else { @@ -4076,18 +4241,18 @@ fn test_max_nominator_rewarded_per_validator_and_cant_steal_someone_else_reward( #[test] fn set_history_depth_works() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { mock::start_era(10); - Staking::set_history_depth(Origin::ROOT, 20).unwrap(); + Staking::set_history_depth(Origin::root(), 20, 0).unwrap(); assert!(::ErasTotalStake::contains_key(10 - 4)); assert!(::ErasTotalStake::contains_key(10 - 5)); - Staking::set_history_depth(Origin::ROOT, 4).unwrap(); + Staking::set_history_depth(Origin::root(), 4, 0).unwrap(); assert!(::ErasTotalStake::contains_key(10 - 4)); assert!(!::ErasTotalStake::contains_key(10 - 5)); - Staking::set_history_depth(Origin::ROOT, 3).unwrap(); + Staking::set_history_depth(Origin::root(), 3, 0).unwrap(); assert!(!::ErasTotalStake::contains_key(10 - 4)); assert!(!::ErasTotalStake::contains_key(10 - 5)); - Staking::set_history_depth(Origin::ROOT, 8).unwrap(); + Staking::set_history_depth(Origin::root(), 8, 0).unwrap(); assert!(!::ErasTotalStake::contains_key(10 - 4)); assert!(!::ErasTotalStake::contains_key(10 - 5)); }); @@ -4097,14 +4262,14 @@ fn set_history_depth_works() { fn test_payout_stakers() { // Here we will test validator can set `max_nominators_payout` and it works. // We also test that `payout_extra_nominators` works. - ExtBuilder::default().has_stakers(false).build().execute_with(|| { + ExtBuilder::default().has_stakers(false).build_and_execute(|| { let balance = 1000; // Create three validators: bond_validator(11, 10, balance); // Default(64) // Create nominators, targeting stash of validators for i in 0..100 { - bond_nominator(1000 + i, 100 + i, balance + i, vec![11]); + bond_nominator(1000 + i, 100 + i, balance + i as Balance, vec![11]); } mock::start_era(1); @@ -4119,11 +4284,11 @@ fn test_payout_stakers() { // Validator payout goes to controller. assert!(Balances::free_balance(&10) > balance); for i in 36..100 { - assert!(Balances::free_balance(&(100 + i)) > balance + i); + assert!(Balances::free_balance(&(100 + i)) > balance + i as Balance); } // The bottom 36 do not for i in 0..36 { - assert_eq!(Balances::free_balance(&(100 + i)), balance + i); + assert_eq!(Balances::free_balance(&(100 + i)), balance + i as Balance); } // We track rewards in `claimed_rewards` vec @@ -4177,14 +4342,14 @@ fn test_payout_stakers() { #[test] fn payout_stakers_handles_basic_errors() { // Here we will test payouts handle all errors. - ExtBuilder::default().has_stakers(false).build().execute_with(|| { + ExtBuilder::default().has_stakers(false).build_and_execute(|| { // Same setup as the test above let balance = 1000; bond_validator(11, 10, balance); // Default(64) // Create nominators, targeting stash for i in 0..100 { - bond_nominator(1000 + i, 100 + i, balance + i, vec![11]); + bond_nominator(1000 + i, 100 + i, balance + i as Balance, vec![11]); } mock::start_era(1); @@ -4221,7 +4386,7 @@ fn payout_stakers_handles_basic_errors() { #[test] fn bond_during_era_correctly_populates_claimed_rewards() { - ExtBuilder::default().has_stakers(false).build().execute_with(|| { + ExtBuilder::default().has_stakers(false).build_and_execute(|| { // Era = None bond_validator(9, 8, 1000); assert_eq!( @@ -4261,461 +4426,108 @@ fn bond_during_era_correctly_populates_claimed_rewards() { }); } -/* These migration tests below can be removed once migration code is removed */ - -#[test] -fn assert_migration_is_noop() { - let kusama_active_era = "4a0200000190e2721171010000"; - let era = ActiveEraInfo::decode(&mut &hex::decode(kusama_active_era).unwrap()[..]).unwrap(); - assert_eq!(era.index, 586); - assert_eq!(era.start, Some(1585135674000)); -} - #[test] -fn test_last_reward_migration() { - use sp_storage::Storage; - - let mut s = Storage::default(); - - #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] - struct OldStakingLedger { - pub stash: AccountId, - #[codec(compact)] - pub total: Balance, - #[codec(compact)] - pub active: Balance, - pub unlocking: Vec>, - pub last_reward: Option, - } - - let old_staking10 = OldStakingLedger:: { - stash: 0, - total: 10, - active: 10, - unlocking: vec![UnlockChunk{ value: 1234, era: 56}], - last_reward: Some(8), - }; - - let old_staking11 = OldStakingLedger:: { - stash: 1, - total: 0, - active: 0, - unlocking: vec![], - last_reward: None, - }; - - let old_staking12 = OldStakingLedger:: { - stash: 2, - total: 100, - active: 100, - unlocking: vec![UnlockChunk{ value: 9876, era: 54}, UnlockChunk{ value: 98, era: 76}], - last_reward: Some(23), - }; +fn offences_weight_calculated_correctly() { + ExtBuilder::default().nominate(true).build_and_execute(|| { + // On offence with zero offenders: 4 Reads, 1 Write + let zero_offence_weight = ::DbWeight::get().reads_writes(4, 1); + assert_eq!(Staking::on_offence(&[], &[Perbill::from_percent(50)], 0), Ok(zero_offence_weight)); + + // On Offence with N offenders, Unapplied: 4 Reads, 1 Write + 4 Reads, 5 Writes + let n_offence_unapplied_weight = ::DbWeight::get().reads_writes(4, 1) + + ::DbWeight::get().reads_writes(4, 5); + + let offenders: Vec::AccountId, pallet_session::historical::IdentificationTuple>> + = (1..10).map(|i| + OffenceDetails { + offender: (i, Staking::eras_stakers(Staking::active_era().unwrap().index, i)), + reporters: vec![], + } + ).collect(); + assert_eq!(Staking::on_offence(&offenders, &[Perbill::from_percent(50)], 0), Ok(n_offence_unapplied_weight)); - let old_staking13 = OldStakingLedger:: { - stash: 3, - total: 100, - active: 100, - unlocking: vec![], - last_reward: Some(23), - }; + // On Offence with one offenders, Applied + let one_offender = [ + OffenceDetails { + offender: (11, Staking::eras_stakers(Staking::active_era().unwrap().index, 11)), + reporters: vec![1], + }, + ]; - let data = vec![ - ( - Ledger::::hashed_key_for(10), - old_staking10.encode().to_vec() - ), - ( - Ledger::::hashed_key_for(11), - old_staking11.encode().to_vec() - ), - ( - Ledger::::hashed_key_for(12), - old_staking12.encode().to_vec() - ), - ( - Ledger::::hashed_key_for(13), - old_staking13.encode().to_vec() - ), - ]; - - s.top = data.into_iter().collect(); - sp_io::TestExternalities::new(s).execute_with(|| { - HistoryDepth::put(84); - CurrentEra::put(99); - let nominations = Nominations:: { - targets: vec![], - submitted_in: 0, - suppressed: false - }; - Nominators::::insert(3, nominations); - Bonded::::insert(3, 13); - Staking::migrate_last_reward_to_claimed_rewards(); - // Test staker out of range - assert_eq!( - Ledger::::get(10), - Some(StakingLedger { - stash: 0, - total: 10, - active: 10, - unlocking: vec![UnlockChunk{ value: 1234, era: 56}], - claimed_rewards: vec![], - }) - ); - // Test staker none - assert_eq!( - Ledger::::get(11), - Some(StakingLedger { - stash: 1, - total: 0, - active: 0, - unlocking: vec![], - claimed_rewards: vec![], - }) - ); - // Test staker migration - assert_eq!( - Ledger::::get(12), - Some(StakingLedger { - stash: 2, - total: 100, - active: 100, - unlocking: vec![UnlockChunk{ value: 9876, era: 54}, UnlockChunk{ value: 98, era: 76}], - claimed_rewards: vec![15,16,17,18,19,20,21,22,23], - }) - ); - // Test nominator migration - assert_eq!( - Ledger::::get(13), - Some(StakingLedger { - stash: 3, - total: 100, - active: 100, - unlocking: vec![], - claimed_rewards: vec![15,16,17,18,19,20,21,22,23], - }) - ); + let n = 1; // Number of offenders + let rw = 3 + 3 * n; // rw reads and writes + let one_offence_unapplied_weight = ::DbWeight::get().reads_writes(4, 1) + + ::DbWeight::get().reads_writes(rw, rw) + // One `slash_cost` + + ::DbWeight::get().reads_writes(6, 5) + // `slash_cost` * nominators (1) + + ::DbWeight::get().reads_writes(6, 5) + // `reward_cost` * reporters (1) + + ::DbWeight::get().reads_writes(2, 2); + + assert_eq!(Staking::on_offence(&one_offender, &[Perbill::from_percent(50)], 0), Ok(one_offence_unapplied_weight)); }); } #[test] -fn rewards_should_work_before_migration() { - // should check that before migration: - // * rewards get recorded per session - // * rewards get paid per Era - // * Check that nominators are also rewarded - ExtBuilder::default().nominate(true).build().execute_with(|| { - MigrateEra::put(10); - let init_balance_10 = Balances::total_balance(&10); - let init_balance_11 = Balances::total_balance(&11); - let init_balance_20 = Balances::total_balance(&20); - let init_balance_21 = Balances::total_balance(&21); - let init_balance_100 = Balances::total_balance(&100); - let init_balance_101 = Balances::total_balance(&101); - - // Check state - Payee::::insert(11, RewardDestination::Controller); - Payee::::insert(21, RewardDestination::Controller); - Payee::::insert(101, RewardDestination::Controller); - - >::reward_by_ids(vec![(11, 50)]); - >::reward_by_ids(vec![(11, 50)]); - // This is the second validator of the current elected set. - >::reward_by_ids(vec![(21, 50)]); - - // Compute total payout now for whole duration as other parameter won't change - let total_payout_0 = current_total_payout_for_duration(3 * 1000); - assert!(total_payout_0 > 10); // Test is meaningful if reward something - - start_session(1); - - assert_eq!(Balances::total_balance(&10), init_balance_10); - assert_eq!(Balances::total_balance(&11), init_balance_11); - assert_eq!(Balances::total_balance(&20), init_balance_20); - assert_eq!(Balances::total_balance(&21), init_balance_21); - assert_eq!(Balances::total_balance(&100), init_balance_100); - assert_eq!(Balances::total_balance(&101), init_balance_101); - assert_eq_uvec!(Session::validators(), vec![11, 21]); - assert_eq!(Staking::eras_reward_points(Staking::active_era().unwrap().index), EraRewardPoints { - total: 50*3, - individual: vec![(11, 100), (21, 50)].into_iter().collect(), - }); - let part_for_10 = Perbill::from_rational_approximation::(1000, 1125); - let part_for_20 = Perbill::from_rational_approximation::(1000, 1375); - let part_for_100_from_10 = Perbill::from_rational_approximation::(125, 1125); - let part_for_100_from_20 = Perbill::from_rational_approximation::(375, 1375); - - start_session(2); - start_session(3); - - assert_eq!(Staking::active_era().unwrap().index, 1); - mock::make_all_reward_payment_before_migration(0); - - assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + part_for_10 * total_payout_0*2/3, 2); - assert_eq_error_rate!(Balances::total_balance(&11), init_balance_11, 2); - assert_eq_error_rate!(Balances::total_balance(&20), init_balance_20 + part_for_20 * total_payout_0*1/3, 2); - assert_eq_error_rate!(Balances::total_balance(&21), init_balance_21, 2); - assert_eq_error_rate!( - Balances::total_balance(&100), - init_balance_100 - + part_for_100_from_10 * total_payout_0 * 2/3 - + part_for_100_from_20 * total_payout_0 * 1/3, - 2 - ); - assert_eq_error_rate!(Balances::total_balance(&101), init_balance_101, 2); - - assert_eq_uvec!(Session::validators(), vec![11, 21]); - >::reward_by_ids(vec![(11, 1)]); - - // Compute total payout now for whole duration as other parameter won't change - let total_payout_1 = current_total_payout_for_duration(3 * 1000); - assert!(total_payout_1 > 10); // Test is meaningful if reward something - - mock::start_era(2); - mock::make_all_reward_payment_before_migration(1); - - assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + part_for_10 * (total_payout_0 * 2/3 + total_payout_1), 2); - assert_eq_error_rate!(Balances::total_balance(&11), init_balance_11, 2); - assert_eq_error_rate!(Balances::total_balance(&20), init_balance_20 + part_for_20 * total_payout_0 * 1/3, 2); - assert_eq_error_rate!(Balances::total_balance(&21), init_balance_21, 2); - assert_eq_error_rate!( - Balances::total_balance(&100), - init_balance_100 - + part_for_100_from_10 * (total_payout_0 * 2/3 + total_payout_1) - + part_for_100_from_20 * total_payout_0 * 1/3, - 2 - ); - assert_eq_error_rate!(Balances::total_balance(&101), init_balance_101, 2); +fn on_initialize_weight_is_correct() { + ExtBuilder::default().has_stakers(false).build_and_execute(|| { + assert_eq!(Validators::::iter().count(), 0); + assert_eq!(Nominators::::iter().count(), 0); + // When this pallet has nothing, we do 4 reads each block + let base_weight = ::DbWeight::get().reads(4); + assert_eq!(base_weight, Staking::on_initialize(0)); }); -} - -#[test] -fn migrate_era_should_work() { - // should check that before and after migration: - // * rewards get recorded per session - // * rewards get paid per Era - // * Check that nominators are also rewarded - ExtBuilder::default().nominate(true).build().execute_with(|| { - MigrateEra::put(1); - let init_balance_10 = Balances::total_balance(&10); - let init_balance_11 = Balances::total_balance(&11); - let init_balance_20 = Balances::total_balance(&20); - let init_balance_21 = Balances::total_balance(&21); - let init_balance_100 = Balances::total_balance(&100); - let init_balance_101 = Balances::total_balance(&101); - - // Check state - Payee::::insert(11, RewardDestination::Controller); - Payee::::insert(21, RewardDestination::Controller); - Payee::::insert(101, RewardDestination::Controller); - - >::reward_by_ids(vec![(11, 50)]); - >::reward_by_ids(vec![(11, 50)]); - // This is the second validator of the current elected set. - >::reward_by_ids(vec![(21, 50)]); - - // Compute total payout now for whole duration as other parameter won't change - let total_payout_0 = current_total_payout_for_duration(3 * 1000); - assert!(total_payout_0 > 10); // Test is meaningful if reward something - - start_session(1); - - assert_eq!(Balances::total_balance(&10), init_balance_10); - assert_eq!(Balances::total_balance(&11), init_balance_11); - assert_eq!(Balances::total_balance(&20), init_balance_20); - assert_eq!(Balances::total_balance(&21), init_balance_21); - assert_eq!(Balances::total_balance(&100), init_balance_100); - assert_eq!(Balances::total_balance(&101), init_balance_101); - assert_eq_uvec!(Session::validators(), vec![11, 21]); - assert_eq!(Staking::eras_reward_points(Staking::active_era().unwrap().index), EraRewardPoints { - total: 50*3, - individual: vec![(11, 100), (21, 50)].into_iter().collect(), - }); - let part_for_10 = Perbill::from_rational_approximation::(1000, 1125); - let part_for_20 = Perbill::from_rational_approximation::(1000, 1375); - let part_for_100_from_10 = Perbill::from_rational_approximation::(125, 1125); - let part_for_100_from_20 = Perbill::from_rational_approximation::(375, 1375); - - start_session(2); - start_session(3); - - assert_eq!(Staking::active_era().unwrap().index, 1); - mock::make_all_reward_payment_before_migration(0); - - assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + part_for_10 * total_payout_0*2/3, 2); - assert_eq_error_rate!(Balances::total_balance(&11), init_balance_11, 2); - assert_eq_error_rate!(Balances::total_balance(&20), init_balance_20 + part_for_20 * total_payout_0*1/3, 2); - assert_eq_error_rate!(Balances::total_balance(&21), init_balance_21, 2); - assert_eq_error_rate!( - Balances::total_balance(&100), - init_balance_100 - + part_for_100_from_10 * total_payout_0 * 2/3 - + part_for_100_from_20 * total_payout_0 * 1/3, - 2 - ); - assert_eq_error_rate!(Balances::total_balance(&101), init_balance_101, 2); - assert_eq_uvec!(Session::validators(), vec![11, 21]); - >::reward_by_ids(vec![(11, 1)]); - - // Compute total payout now for whole duration as other parameter won't change - let total_payout_1 = current_total_payout_for_duration(3 * 1000); - assert!(total_payout_1 > 10); // Test is meaningful if reward something - - mock::start_era(2); - mock::make_all_reward_payment(1); - - assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + part_for_10 * (total_payout_0 * 2/3 + total_payout_1), 2); - assert_eq_error_rate!(Balances::total_balance(&11), init_balance_11, 2); - assert_eq_error_rate!(Balances::total_balance(&20), init_balance_20 + part_for_20 * total_payout_0 * 1/3, 2); - assert_eq_error_rate!(Balances::total_balance(&21), init_balance_21, 2); - assert_eq_error_rate!( - Balances::total_balance(&100), - init_balance_100 - + part_for_100_from_10 * (total_payout_0 * 2/3 + total_payout_1) - + part_for_100_from_20 * total_payout_0 * 1/3, - 2 - ); - assert_eq_error_rate!(Balances::total_balance(&101), init_balance_101, 2); + ExtBuilder::default() + .offchain_phragmen_ext() + .validator_count(4) + .has_stakers(false) + .build() + .execute_with(|| { + crate::tests::offchain_phragmen::build_offchain_phragmen_test_ext(); + run_to_block(11); + Staking::on_finalize(System::block_number()); + System::set_block_number((System::block_number() + 1).into()); + Timestamp::set_timestamp(System::block_number() * 1000 + INIT_TIMESTAMP); + Session::on_initialize(System::block_number()); + + assert_eq!(Validators::::iter().count(), 4); + assert_eq!(Nominators::::iter().count(), 5); + // With 4 validators and 5 nominator, we should increase weight by: + // - (4 + 5) reads + // - 3 Writes + let final_weight = ::DbWeight::get().reads_writes(4 + 9, 3); + assert_eq!(final_weight, Staking::on_initialize(System::block_number())); }); } -#[test] -#[should_panic] -fn migrate_era_should_handle_error() { - ExtBuilder::default().nominate(true).build().execute_with(|| { - MigrateEra::put(1); - let init_balance_10 = Balances::total_balance(&10); - let init_balance_11 = Balances::total_balance(&11); - let init_balance_20 = Balances::total_balance(&20); - let init_balance_21 = Balances::total_balance(&21); - let init_balance_100 = Balances::total_balance(&100); - let init_balance_101 = Balances::total_balance(&101); - - // Check state - Payee::::insert(11, RewardDestination::Controller); - Payee::::insert(21, RewardDestination::Controller); - Payee::::insert(101, RewardDestination::Controller); - - >::reward_by_ids(vec![(11, 50)]); - >::reward_by_ids(vec![(11, 50)]); - // This is the second validator of the current elected set. - >::reward_by_ids(vec![(21, 50)]); - - // Compute total payout now for whole duration as other parameter won't change - let total_payout_0 = current_total_payout_for_duration(3 * 1000); - assert!(total_payout_0 > 10); // Test is meaningful if reward something - - start_session(1); - - assert_eq!(Balances::total_balance(&10), init_balance_10); - assert_eq!(Balances::total_balance(&11), init_balance_11); - assert_eq!(Balances::total_balance(&20), init_balance_20); - assert_eq!(Balances::total_balance(&21), init_balance_21); - assert_eq!(Balances::total_balance(&100), init_balance_100); - assert_eq!(Balances::total_balance(&101), init_balance_101); - assert_eq_uvec!(Session::validators(), vec![11, 21]); - assert_eq!(Staking::eras_reward_points(Staking::active_era().unwrap().index), EraRewardPoints { - total: 50*3, - individual: vec![(11, 100), (21, 50)].into_iter().collect(), - }); - - start_session(2); - start_session(3); - - assert_eq!(Staking::active_era().unwrap().index, 1); - mock::make_all_reward_payment(0); - }); -} #[test] -#[should_panic] -fn migrate_era_should_handle_errors_2() { - // should check that before and after migration: - // * rewards get recorded per session - // * rewards get paid per Era - // * Check that nominators are also rewarded - ExtBuilder::default().nominate(true).build().execute_with(|| { - MigrateEra::put(1); - let init_balance_10 = Balances::total_balance(&10); - let init_balance_11 = Balances::total_balance(&11); - let init_balance_20 = Balances::total_balance(&20); - let init_balance_21 = Balances::total_balance(&21); - let init_balance_100 = Balances::total_balance(&100); - let init_balance_101 = Balances::total_balance(&101); +fn payout_creates_controller() { + // Here we will test validator can set `max_nominators_payout` and it works. + // We also test that `payout_extra_nominators` works. + ExtBuilder::default().has_stakers(false).build_and_execute(|| { + let balance = 1000; + // Create three validators: + bond_validator(11, 10, balance); // Default(64) - // Check state - Payee::::insert(11, RewardDestination::Controller); - Payee::::insert(21, RewardDestination::Controller); - Payee::::insert(101, RewardDestination::Controller); + // Create a stash/controller pair + bond_nominator(1234, 1337, 100, vec![11]); - >::reward_by_ids(vec![(11, 50)]); - >::reward_by_ids(vec![(11, 50)]); - // This is the second validator of the current elected set. - >::reward_by_ids(vec![(21, 50)]); + // kill controller + assert_ok!(Balances::transfer(Origin::signed(1337), 1234, 100)); + assert_eq!(Balances::free_balance(1337), 0); + mock::start_era(1); + Staking::reward_by_ids(vec![(11, 1)]); // Compute total payout now for whole duration as other parameter won't change let total_payout_0 = current_total_payout_for_duration(3 * 1000); - assert!(total_payout_0 > 10); // Test is meaningful if reward something - - start_session(1); - - assert_eq!(Balances::total_balance(&10), init_balance_10); - assert_eq!(Balances::total_balance(&11), init_balance_11); - assert_eq!(Balances::total_balance(&20), init_balance_20); - assert_eq!(Balances::total_balance(&21), init_balance_21); - assert_eq!(Balances::total_balance(&100), init_balance_100); - assert_eq!(Balances::total_balance(&101), init_balance_101); - assert_eq_uvec!(Session::validators(), vec![11, 21]); - assert_eq!(Staking::eras_reward_points(Staking::active_era().unwrap().index), EraRewardPoints { - total: 50*3, - individual: vec![(11, 100), (21, 50)].into_iter().collect(), - }); - let part_for_10 = Perbill::from_rational_approximation::(1000, 1125); - let part_for_20 = Perbill::from_rational_approximation::(1000, 1375); - let part_for_100_from_10 = Perbill::from_rational_approximation::(125, 1125); - let part_for_100_from_20 = Perbill::from_rational_approximation::(375, 1375); - - start_session(2); - start_session(3); - - assert_eq!(Staking::active_era().unwrap().index, 1); - mock::make_all_reward_payment_before_migration(0); - - assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + part_for_10 * total_payout_0*2/3, 2); - assert_eq_error_rate!(Balances::total_balance(&11), init_balance_11, 2); - assert_eq_error_rate!(Balances::total_balance(&20), init_balance_20 + part_for_20 * total_payout_0*1/3, 2); - assert_eq_error_rate!(Balances::total_balance(&21), init_balance_21, 2); - assert_eq_error_rate!( - Balances::total_balance(&100), - init_balance_100 - + part_for_100_from_10 * total_payout_0 * 2/3 - + part_for_100_from_20 * total_payout_0 * 1/3, - 2 - ); - assert_eq_error_rate!(Balances::total_balance(&101), init_balance_101, 2); - - assert_eq_uvec!(Session::validators(), vec![11, 21]); - >::reward_by_ids(vec![(11, 1)]); - - // Compute total payout now for whole duration as other parameter won't change - let total_payout_1 = current_total_payout_for_duration(3 * 1000); - assert!(total_payout_1 > 10); // Test is meaningful if reward something - + assert!(total_payout_0 > 100); // Test is meaningful if reward something mock::start_era(2); - mock::make_all_reward_payment_before_migration(1); + assert_ok!(Staking::payout_stakers(Origin::signed(1337), 11, 1)); - assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + part_for_10 * (total_payout_0 * 2/3 + total_payout_1), 2); - assert_eq_error_rate!(Balances::total_balance(&11), init_balance_11, 2); - assert_eq_error_rate!(Balances::total_balance(&20), init_balance_20 + part_for_20 * total_payout_0 * 1/3, 2); - assert_eq_error_rate!(Balances::total_balance(&21), init_balance_21, 2); - assert_eq_error_rate!( - Balances::total_balance(&100), - init_balance_100 - + part_for_100_from_10 * (total_payout_0 * 2/3 + total_payout_1) - + part_for_100_from_20 * total_payout_0 * 1/3, - 2 - ); - assert_eq_error_rate!(Balances::total_balance(&101), init_balance_101, 2); - }); + // Controller is created + assert!(Balances::free_balance(1337) > 0); + }) } diff --git a/frame/sudo/Cargo.toml b/frame/sudo/Cargo.toml index 4216b94ec12f12ccf8514698a78a25e3e9752ac6..8bb549977069fe7bc25ae6925bf150ab8add749a 100644 --- a/frame/sudo/Cargo.toml +++ b/frame/sudo/Cargo.toml @@ -1,24 +1,27 @@ [package] name = "pallet-sudo" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for sudo" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } [features] default = ["std"] @@ -31,6 +34,3 @@ std = [ "frame-support/std", "frame-system/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/sudo/src/lib.rs b/frame/sudo/src/lib.rs index 3f2eacdbf8139a83530fcf7536b6ad981e6af58f..cf55d9e67f31bbb1c149753e119577309fb0b49b 100644 --- a/frame/sudo/src/lib.rs +++ b/frame/sudo/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Sudo Module //! @@ -52,13 +53,13 @@ //! //! ``` //! use frame_support::{decl_module, dispatch}; -//! use frame_system::{self as system, ensure_root}; +//! use frame_system::ensure_root; //! //! pub trait Trait: frame_system::Trait {} //! //! decl_module! { //! pub struct Module for enum Call where origin: T::Origin { -//! #[weight = frame_support::weights::SimpleDispatchInfo::default()] +//! #[weight = 0] //! pub fn privileged_function(origin) -> dispatch::DispatchResult { //! ensure_root(origin)?; //! @@ -87,24 +88,29 @@ #![cfg_attr(not(feature = "std"), no_std)] use sp_std::prelude::*; -use sp_runtime::traits::{StaticLookup, Dispatchable}; +use sp_runtime::{DispatchResult, traits::StaticLookup}; use frame_support::{ Parameter, decl_module, decl_event, decl_storage, decl_error, ensure, }; -use frame_support::weights::{GetDispatchInfo, FunctionOf}; -use frame_system::{self as system, ensure_signed}; +use frame_support::{weights::{Weight, GetDispatchInfo}, traits::UnfilteredDispatchable}; +use frame_system::ensure_signed; + +#[cfg(test)] +mod mock; +#[cfg(test)] +mod tests; pub trait Trait: frame_system::Trait { /// The overarching event type. type Event: From> + Into<::Event>; /// A sudo-able call. - type Call: Parameter + Dispatchable + GetDispatchInfo; + type Call: Parameter + UnfilteredDispatchable + GetDispatchInfo; } decl_module! { - // Simple declaration of the `Module` type. Lets the macro know what it's working on. + /// Sudo module declaration. pub struct Module for enum Call where origin: T::Origin { type Error = Error; @@ -120,25 +126,34 @@ decl_module! { /// - One DB write (event). /// - Weight of derivative `call` execution + 10,000. /// # - #[weight = FunctionOf( - |args: (&Box<::Call>,)| args.0.get_dispatch_info().weight + 10_000, - |args: (&Box<::Call>,)| args.0.get_dispatch_info().class, - true - )] + #[weight = (call.get_dispatch_info().weight + 10_000, call.get_dispatch_info().class)] fn sudo(origin, call: Box<::Call>) { // This is a public call, so we ensure that the origin is some signed account. let sender = ensure_signed(origin)?; ensure!(sender == Self::key(), Error::::RequireSudo); - let res = match call.dispatch(frame_system::RawOrigin::Root.into()) { - Ok(_) => true, - Err(e) => { - sp_runtime::print(e); - false - } - }; + let res = call.dispatch_bypass_filter(frame_system::RawOrigin::Root.into()); + Self::deposit_event(RawEvent::Sudid(res.map(|_| ()).map_err(|e| e.error))); + } + + /// Authenticates the sudo key and dispatches a function call with `Root` origin. + /// This function does not check the weight of the call, and instead allows the + /// Sudo user to specify the weight of the call. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// # + /// - O(1). + /// - The weight of this call is defined by the caller. + /// # + #[weight = (*_weight, call.get_dispatch_info().class)] + fn sudo_unchecked_weight(origin, call: Box<::Call>, _weight: Weight) { + // This is a public call, so we ensure that the origin is some signed account. + let sender = ensure_signed(origin)?; + ensure!(sender == Self::key(), Error::::RequireSudo); - Self::deposit_event(RawEvent::Sudid(res)); + let res = call.dispatch_bypass_filter(frame_system::RawOrigin::Root.into()); + Self::deposit_event(RawEvent::Sudid(res.map(|_| ()).map_err(|e| e.error))); } /// Authenticates the current sudo key and sets the given AccountId (`new`) as the new sudo key. @@ -150,7 +165,7 @@ decl_module! { /// - Limited storage reads. /// - One DB change. /// # - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] fn set_key(origin, new: ::Source) { // This is a public call, so we ensure that the origin is some signed account. let sender = ensure_signed(origin)?; @@ -172,15 +187,7 @@ decl_module! { /// - One DB write (event). /// - Weight of derivative `call` execution + 10,000. /// # - #[weight = FunctionOf( - |args: (&::Source, &Box<::Call>,)| { - args.1.get_dispatch_info().weight + 10_000 - }, - |args: (&::Source, &Box<::Call>,)| { - args.1.get_dispatch_info().class - }, - true - )] + #[weight = (call.get_dispatch_info().weight + 10_000, call.get_dispatch_info().class)] fn sudo_as(origin, who: ::Source, call: Box<::Call>) { // This is a public call, so we ensure that the origin is some signed account. let sender = ensure_signed(origin)?; @@ -188,7 +195,7 @@ decl_module! { let who = T::Lookup::lookup(who)?; - let res = match call.dispatch(frame_system::RawOrigin::Signed(who).into()) { + let res = match call.dispatch_bypass_filter(frame_system::RawOrigin::Signed(who).into()) { Ok(_) => true, Err(e) => { sp_runtime::print(e); @@ -204,7 +211,7 @@ decl_module! { decl_event!( pub enum Event where AccountId = ::AccountId { /// A sudo just took place. - Sudid(bool), + Sudid(DispatchResult), /// The sudoer just switched identity; the old key is supplied. KeyChanged(AccountId), /// A sudo just took place. diff --git a/frame/sudo/src/mock.rs b/frame/sudo/src/mock.rs new file mode 100644 index 0000000000000000000000000000000000000000..5052d9c52d1b4245911fac94d212bf5e54ba9f54 --- /dev/null +++ b/frame/sudo/src/mock.rs @@ -0,0 +1,176 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Test utilities + +use super::*; +use frame_support::{ + impl_outer_origin, impl_outer_dispatch, impl_outer_event, parameter_types, + weights::Weight, +}; +use sp_core::H256; +use sp_runtime::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; +use sp_io; +use crate as sudo; +use frame_support::traits::Filter; + +// Logger module to track execution. +pub mod logger { + use super::*; + use frame_system::ensure_root; + + pub trait Trait: frame_system::Trait { + type Event: From> + Into<::Event>; + } + + decl_storage! { + trait Store for Module as Logger { + AccountLog get(fn account_log): Vec; + I32Log get(fn i32_log): Vec; + } + } + + decl_event! { + pub enum Event where AccountId = ::AccountId { + AppendI32(i32, Weight), + AppendI32AndAccount(AccountId, i32, Weight), + } + } + + decl_module! { + pub struct Module for enum Call where origin: ::Origin { + fn deposit_event() = default; + + #[weight = *weight] + fn privileged_i32_log(origin, i: i32, weight: Weight){ + // Ensure that the `origin` is `Root`. + ensure_root(origin)?; + ::append(i); + Self::deposit_event(RawEvent::AppendI32(i, weight)); + } + + #[weight = *weight] + fn non_privileged_log(origin, i: i32, weight: Weight){ + // Ensure that the `origin` is some signed account. + let sender = ensure_signed(origin)?; + ::append(i); + >::append(sender.clone()); + Self::deposit_event(RawEvent::AppendI32AndAccount(sender, i, weight)); + } + } + } +} + +impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} +} + +mod test_events { + pub use crate::Event; +} + +impl_outer_event! { + pub enum TestEvent for Test { + frame_system, + sudo, + logger, + } +} + +impl_outer_dispatch! { + pub enum Call for Test where origin: Origin { + sudo::Sudo, + logger::Logger, + } +} + +// For testing the pallet, we construct most of a mock runtime. This means +// first constructing a configuration type (`Test`) which `impl`s each of the +// configuration traits of pallets we want to use. +#[derive(Clone, Eq, PartialEq)] +pub struct Test; + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} + +pub struct BlockEverything; +impl Filter for BlockEverything { + fn filter(_: &Call) -> bool { + false + } +} + +impl frame_system::Trait for Test { + type BaseCallFilter = BlockEverything; + type Origin = Origin; + type Call = Call; + type Index = u64; + type BlockNumber = u64; + 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 DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); +} + +// Implement the logger module's `Trait` on the Test runtime. +impl logger::Trait for Test { + type Event = TestEvent; +} + +// Implement the sudo module's `Trait` on the Test runtime. +impl Trait for Test { + type Event = TestEvent; + type Call = Call; +} + +// Assign back to type variables in order to make dispatched calls of these modules later. +pub type Sudo = Module; +pub type Logger = logger::Module; +pub type System = frame_system::Module; + +// New types for dispatchable functions. +pub type SudoCall = sudo::Call; +pub type LoggerCall = logger::Call; + +// Build test environment by setting the root `key` for the Genesis. +pub fn new_test_ext(root_key: u64) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + GenesisConfig::{ + key: root_key, + }.assimilate_storage(&mut t).unwrap(); + t.into() +} diff --git a/frame/sudo/src/tests.rs b/frame/sudo/src/tests.rs new file mode 100644 index 0000000000000000000000000000000000000000..79424d2824f9026d43d3ec04332896f545ba7eb2 --- /dev/null +++ b/frame/sudo/src/tests.rs @@ -0,0 +1,169 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Tests for the module. + +use super::*; +use mock::{ + Sudo, SudoCall, Origin, Call, Test, new_test_ext, LoggerCall, Logger, System, TestEvent, +}; +use frame_support::{assert_ok, assert_noop}; + +#[test] +fn test_setup_works() { + // Environment setup, logger storage, and sudo `key` retrieval should work as expected. + new_test_ext(1).execute_with(|| { + assert_eq!(Sudo::key(), 1u64); + assert_eq!(Logger::i32_log(), vec![]); + assert_eq!(Logger::account_log(), vec![]); + }); +} + +#[test] +fn sudo_basics() { + // Configure a default test environment and set the root `key` to 1. + new_test_ext(1).execute_with(|| { + // A privileged function should work when `sudo` is passed the root `key` as `origin`. + let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log(42, 1_000))); + assert_ok!(Sudo::sudo(Origin::signed(1), call)); + assert_eq!(Logger::i32_log(), vec![42i32]); + + // A privileged function should not work when `sudo` is passed a non-root `key` as `origin`. + let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log(42, 1_000))); + assert_noop!(Sudo::sudo(Origin::signed(2), call), Error::::RequireSudo); + }); +} + +#[test] +fn sudo_emits_events_correctly() { + new_test_ext(1).execute_with(|| { + // Set block number to 1 because events are not emitted on block 0. + System::set_block_number(1); + + // Should emit event to indicate success when called with the root `key` and `call` is `Ok`. + let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log(42, 1))); + assert_ok!(Sudo::sudo(Origin::signed(1), call)); + let expected_event = TestEvent::sudo(RawEvent::Sudid(Ok(()))); + assert!(System::events().iter().any(|a| a.event == expected_event)); + }) +} + +#[test] +fn sudo_unchecked_weight_basics() { + new_test_ext(1).execute_with(|| { + // A privileged function should work when `sudo` is passed the root `key` as origin. + let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log(42, 1_000))); + assert_ok!(Sudo::sudo_unchecked_weight(Origin::signed(1), call, 1_000)); + assert_eq!(Logger::i32_log(), vec![42i32]); + + // A privileged function should not work when called with a non-root `key`. + let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log(42, 1_000))); + assert_noop!( + Sudo::sudo_unchecked_weight(Origin::signed(2), call, 1_000), + Error::::RequireSudo, + ); + // `I32Log` is unchanged after unsuccessful call. + assert_eq!(Logger::i32_log(), vec![42i32]); + + // Controls the dispatched weight. + let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log(42, 1))); + let sudo_unchecked_weight_call = SudoCall::sudo_unchecked_weight(call, 1_000); + let info = sudo_unchecked_weight_call.get_dispatch_info(); + assert_eq!(info.weight, 1_000); + }); +} + +#[test] +fn sudo_unchecked_weight_emits_events_correctly() { + new_test_ext(1).execute_with(|| { + // Set block number to 1 because events are not emitted on block 0. + System::set_block_number(1); + + // Should emit event to indicate success when called with the root `key` and `call` is `Ok`. + let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log(42, 1))); + assert_ok!(Sudo::sudo_unchecked_weight(Origin::signed(1), call, 1_000)); + let expected_event = TestEvent::sudo(RawEvent::Sudid(Ok(()))); + assert!(System::events().iter().any(|a| a.event == expected_event)); + }) +} + +#[test] +fn set_key_basics() { + new_test_ext(1).execute_with(|| { + // A root `key` can change the root `key` + assert_ok!(Sudo::set_key(Origin::signed(1), 2)); + assert_eq!(Sudo::key(), 2u64); + }); + + new_test_ext(1).execute_with(|| { + // A non-root `key` will trigger a `RequireSudo` error and a non-root `key` cannot change the root `key`. + assert_noop!(Sudo::set_key(Origin::signed(2), 3), Error::::RequireSudo); + }); +} + +#[test] +fn set_key_emits_events_correctly() { + new_test_ext(1).execute_with(|| { + // Set block number to 1 because events are not emitted on block 0. + System::set_block_number(1); + + // A root `key` can change the root `key`. + assert_ok!(Sudo::set_key(Origin::signed(1), 2)); + let expected_event = TestEvent::sudo(RawEvent::KeyChanged(1)); + assert!(System::events().iter().any(|a| a.event == expected_event)); + // Double check. + assert_ok!(Sudo::set_key(Origin::signed(2), 4)); + let expected_event = TestEvent::sudo(RawEvent::KeyChanged(2)); + assert!(System::events().iter().any(|a| a.event == expected_event)); + }); +} + +#[test] +fn sudo_as_basics() { + new_test_ext(1).execute_with(|| { + // A privileged function will not work when passed to `sudo_as`. + let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log(42, 1_000))); + assert_ok!(Sudo::sudo_as(Origin::signed(1), 2, call)); + assert_eq!(Logger::i32_log(), vec![]); + assert_eq!(Logger::account_log(), vec![]); + + // A non-privileged function should not work when called with a non-root `key`. + let call = Box::new(Call::Logger(LoggerCall::non_privileged_log(42, 1))); + assert_noop!(Sudo::sudo_as(Origin::signed(3), 2, call), Error::::RequireSudo); + + // A non-privileged function will work when passed to `sudo_as` with the root `key`. + let call = Box::new(Call::Logger(LoggerCall::non_privileged_log(42, 1))); + assert_ok!(Sudo::sudo_as(Origin::signed(1), 2, call)); + assert_eq!(Logger::i32_log(), vec![42i32]); + // The correct user makes the call within `sudo_as`. + assert_eq!(Logger::account_log(), vec![2]); + }); +} + +#[test] +fn sudo_as_emits_events_correctly() { + new_test_ext(1).execute_with(|| { + // Set block number to 1 because events are not emitted on block 0. + System::set_block_number(1); + + // A non-privileged function will work when passed to `sudo_as` with the root `key`. + let call = Box::new(Call::Logger(LoggerCall::non_privileged_log(42, 1))); + assert_ok!(Sudo::sudo_as(Origin::signed(1), 2, call)); + let expected_event = TestEvent::sudo(RawEvent::SudoAsDone(true)); + assert!(System::events().iter().any(|a| a.event == expected_event)); + }); +} diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index 3bad72a115716b6f5c1f6297bf62ef40d24674a2..eaeaf96a3edd906cac542465bb74c90142b689d6 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -1,40 +1,44 @@ [package] name = "frame-support" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Support code for the runtime." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] log = "0.4" serde = { version = "1.0.101", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -frame-metadata = { version = "11.0.0-alpha.5", default-features = false, path = "../metadata" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/core" } -sp-arithmetic = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/arithmetic" } -sp-inherents = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/inherents" } -frame-support-procedural = { version = "2.0.0-alpha.5", path = "./procedural" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +frame-metadata = { version = "11.0.0-rc4", default-features = false, path = "../metadata" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +sp-tracing = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/tracing" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/core" } +sp-arithmetic = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/arithmetic" } +sp-inherents = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/inherents" } +frame-support-procedural = { version = "2.0.0-rc4", path = "./procedural" } paste = "0.1.6" once_cell = { version = "1", default-features = false, optional = true } -sp-state-machine = { version = "0.8.0-alpha.5", optional = true, path = "../../primitives/state-machine" } +sp-state-machine = { version = "0.8.0-rc4", optional = true, path = "../../primitives/state-machine" } bitmask = { version = "0.5.0", default-features = false } impl-trait-for-tuples = "0.1.3" -tracing = { version = "0.1.10", optional = true } +smallvec = "1.4.1" [dev-dependencies] pretty_assertions = "0.6.1" -frame-system = { version = "2.0.0-alpha.5", path = "../system" } +frame-system = { version = "2.0.0-rc4", path = "../system" } +parity-util-mem = { version = "0.7.0", features = ["primitive-types"] } [features] default = ["std"] std = [ - "tracing", "once_cell", "bitmask/std", "serde", @@ -42,6 +46,7 @@ std = [ "codec/std", "sp-std/std", "sp-runtime/std", + "sp-tracing/std", "sp-arithmetic/std", "frame-metadata/std", "sp-inherents/std", @@ -50,6 +55,3 @@ std = [ nightly = [] strict = [] runtime-benchmarks = [] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/support/procedural/Cargo.toml b/frame/support/procedural/Cargo.toml index 2f7450e4b86d3ea960a9b9b2e1e3b2c32b1af306..593b2a16351b6e18ea5c89821eb45c761d6ed573 100644 --- a/frame/support/procedural/Cargo.toml +++ b/frame/support/procedural/Cargo.toml @@ -1,21 +1,21 @@ [package] name = "frame-support-procedural" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Proc macro of Support code for the runtime." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [lib] proc-macro = true [dependencies] -frame-support-procedural-tools = { version = "2.0.0-alpha.5", path = "./tools" } +frame-support-procedural-tools = { version = "2.0.0-rc4", path = "./tools" } proc-macro2 = "1.0.6" quote = "1.0.3" syn = { version = "1.0.7", features = ["full"] } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/support/procedural/src/construct_runtime/mod.rs b/frame/support/procedural/src/construct_runtime/mod.rs index b74a27e7ba936c982512438fc47d5ab7dd5dc379..57827b0673916da0b0002e6546f3ce46f8f90b80 100644 --- a/frame/support/procedural/src/construct_runtime/mod.rs +++ b/frame/support/procedural/src/construct_runtime/mod.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. mod parse; @@ -58,7 +59,7 @@ fn construct_runtime_parsed(definition: RuntimeDefinition) -> Result},`", + Please add this line: `System: frame_system::{Module, Call, Storage, Config, Event},`", )) } }; @@ -86,14 +87,19 @@ fn construct_runtime_parsed(definition: RuntimeDefinition) -> Result Result( ) -> TokenStream2 { let modules_tokens = module_declarations.filter_map(|module_declaration| { let maybe_config_part = module_declaration.find_part("Inherent"); - maybe_config_part.map(|config_part| { - let arg = config_part - .args - .as_ref() - .and_then(|parens| parens.content.inner.iter().next()) - .unwrap_or(&module_declaration.name); + maybe_config_part.map(|_| { let name = &module_declaration.name; - quote!(#name : #arg,) + quote!(#name,) }) }); quote!( #scrate::impl_outer_inherent!( - impl Inherents where Block = #block, UncheckedExtrinsic = #unchecked_extrinsic { + impl Inherents where + Block = #block, + UncheckedExtrinsic = #unchecked_extrinsic + { #(#modules_tokens)* } ); @@ -405,3 +411,17 @@ fn find_system_module<'a>( .find(|decl| decl.name == SYSTEM_MODULE_NAME) .map(|decl| &decl.module) } + +fn decl_integrity_test(scrate: &TokenStream2) -> TokenStream2 { + quote!( + #[cfg(test)] + mod __construct_runtime_integrity_test { + use super::*; + + #[test] + pub fn runtime_integrity_tests() { + ::integrity_test(); + } + } + ) +} diff --git a/frame/support/procedural/src/construct_runtime/parse.rs b/frame/support/procedural/src/construct_runtime/parse.rs index 4a81a7efd6b77ad09cad319a88eb16e8a4589e97..c8481480baac5e452b8294fec85bc367c59244ab 100644 --- a/frame/support/procedural/src/construct_runtime/parse.rs +++ b/frame/support/procedural/src/construct_runtime/parse.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use frame_support_procedural_tools::syn_ext as ext; use proc_macro2::Span; @@ -278,18 +279,6 @@ impl ModulePartKeyword { Ident::new(self.name(), self.span()) } - /// Returns `true` if this module part allows to have an argument. - /// - /// For example `Inherent(Timestamp)`. - fn allows_arg(&self) -> bool { - Self::all_allow_arg().iter().any(|n| *n == self.name()) - } - - /// Returns the names of all module parts that allow to have an argument. - fn all_allow_arg() -> &'static [&'static str] { - &["Inherent"] - } - /// Returns `true` if this module part is allowed to have generic arguments. fn allows_generic(&self) -> bool { Self::all_generic_arg().iter().any(|n| *n == self.name()) @@ -320,7 +309,6 @@ impl Spanned for ModulePartKeyword { pub struct ModulePart { pub keyword: ModulePartKeyword, pub generics: syn::Generics, - pub args: Option>>, } impl Parse for ModulePart { @@ -338,27 +326,10 @@ impl Parse for ModulePart { ); return Err(syn::Error::new(keyword.span(), msg)); } - let args = if input.peek(token::Paren) { - if !keyword.allows_arg() { - let syn::group::Parens { token: parens, .. } = syn::group::parse_parens(input)?; - let valid_names = ModulePart::format_names(ModulePartKeyword::all_allow_arg()); - let msg = format!( - "`{}` is not allowed to have arguments in parens. \ - Only the following modules are allowed to have arguments in parens: {}.", - keyword.name(), - valid_names, - ); - return Err(syn::Error::new(parens.span, msg)); - } - Some(input.parse()?) - } else { - None - }; Ok(Self { keyword, generics, - args, }) } } diff --git a/frame/support/procedural/src/lib.rs b/frame/support/procedural/src/lib.rs index a9662f530a5983438807ea47ef8827e80ef6032a..57c6080a90f0ad071376ca222b6af071f78ff4ef 100644 --- a/frame/support/procedural/src/lib.rs +++ b/frame/support/procedural/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. // tag::description[] //! Proc macro of Support code for the runtime. @@ -144,12 +145,12 @@ use proc_macro::TokenStream; /// /// * `#vis`: Set the visibility of the structure. `pub` or nothing. /// * `#name`: Name of the storage item, used as a prefix in storage. -/// * [optional] `get(fn #getter)`: Implements the function #getter to `Module`. -/// * [optional] `config(#field_name)`: `field_name` is optional if get is set. +/// * \[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. +/// * \[optional\] `build(#closure)`: Closure called with storage overlays. /// * `#type`: Storage type. -/// * [optional] `#default`: Value returned when none. +/// * \[optional\] `#default`: Value returned when none. /// /// Storage items are accessible in multiple ways: /// @@ -276,10 +277,8 @@ pub fn decl_storage(input: TokenStream) -> TokenStream { /// - `Event` or `Event` (if the event is generic) /// - `Origin` or `Origin` (if the origin is generic) /// - `Config` or `Config` (if the config is generic) -/// - `Inherent ( $(CALL),* )` - If the module provides/can check inherents. The optional parameter -/// is for modules that use a `Call` from a different module as -/// inherent. -/// - `ValidateUnsigned` - If the module validates unsigned extrinsics. +/// - `Inherent` - If the module provides/can check inherents. +/// - `ValidateUnsigned` - If the module validates unsigned extrinsics. /// /// # Note /// diff --git a/frame/support/procedural/src/storage/genesis_config/builder_def.rs b/frame/support/procedural/src/storage/genesis_config/builder_def.rs index 87255ee481b37b8debf9d2ff25b55775e8fe46c2..a045794529c958d908dfbb34ff6b847c9af52235 100644 --- a/frame/support/procedural/src/storage/genesis_config/builder_def.rs +++ b/frame/support/procedural/src/storage/genesis_config/builder_def.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Builder logic definition used to build genesis storage. @@ -54,10 +55,16 @@ impl BuilderDef { data = Some(match &line.storage_type { StorageLineTypeDef::Simple(_) if line.is_option => quote_spanned!(builder.span() => - let data = (#builder)(self); + // NOTE: the type of `data` is specified when used later in the code + let builder: fn(&Self) -> _ = #builder; + let data = builder(self); let data = Option::as_ref(&data); ), - _ => quote_spanned!(builder.span() => let data = &(#builder)(self); ), + _ => quote_spanned!(builder.span() => + // NOTE: the type of `data` is specified when used later in the code + let builder: fn(&Self) -> _ = #builder; + let data = &builder(self); + ), }); } else if let Some(config) = &line.config { is_generic |= line.is_generic; diff --git a/frame/support/procedural/src/storage/genesis_config/genesis_config_def.rs b/frame/support/procedural/src/storage/genesis_config/genesis_config_def.rs index 9b6ddc92178bd6f981fde39c47933412c565c31e..6339134ea0d22681ac413b60613b66080dec10bd 100644 --- a/frame/support/procedural/src/storage/genesis_config/genesis_config_def.rs +++ b/frame/support/procedural/src/storage/genesis_config/genesis_config_def.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Genesis config definition. diff --git a/frame/support/procedural/src/storage/genesis_config/mod.rs b/frame/support/procedural/src/storage/genesis_config/mod.rs index eeeca150d9b9b8419922f73f1ef51ed3ce46e095..7cc0f7c3befd4bc9ac331b5c690b3ffb69f30508 100644 --- a/frame/support/procedural/src/storage/genesis_config/mod.rs +++ b/frame/support/procedural/src/storage/genesis_config/mod.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Declaration of genesis config structure and implementation of build storage trait and //! functions. diff --git a/frame/support/procedural/src/storage/getters.rs b/frame/support/procedural/src/storage/getters.rs index ae0e646fcd73aaf0d398d82755372dbfe9736da6..5507db4630596f32addac764289d3dd71efa643b 100644 --- a/frame/support/procedural/src/storage/getters.rs +++ b/frame/support/procedural/src/storage/getters.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Implementation of getters on module structure. diff --git a/frame/support/procedural/src/storage/instance_trait.rs b/frame/support/procedural/src/storage/instance_trait.rs index b2f0ad9c06c037d075a1781b0ceda194ce0d9133..1e5e198a8c527a95f6a876db4fe639aa33be839a 100644 --- a/frame/support/procedural/src/storage/instance_trait.rs +++ b/frame/support/procedural/src/storage/instance_trait.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Implementation of the trait instance and the instance structures implementing it. //! (For not instantiable traits there is still the inherent instance implemented). diff --git a/frame/support/procedural/src/storage/metadata.rs b/frame/support/procedural/src/storage/metadata.rs index bb23c99d9df5160bc3f09d780c7960bcf9c0dfa2..065320cd018aef1061c05e8140777eec50efdbb8 100644 --- a/frame/support/procedural/src/storage/metadata.rs +++ b/frame/support/procedural/src/storage/metadata.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Implementation of `storage_metadata` on module structure, used by construct_runtime. diff --git a/frame/support/procedural/src/storage/mod.rs b/frame/support/procedural/src/storage/mod.rs index e8599c52a907173f5c19f1359bc43205667a749e..766141f5aaf8f677a2177fdc3c0afaf154e10966 100644 --- a/frame/support/procedural/src/storage/mod.rs +++ b/frame/support/procedural/src/storage/mod.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! `decl_storage` input definition and expansion. diff --git a/frame/support/procedural/src/storage/parse.rs b/frame/support/procedural/src/storage/parse.rs index af568c78cc6b72f3f71a9827ef4c260a11851425..5a3bb3f40cd4be0b9c3c5811f918f128b771a88f 100644 --- a/frame/support/procedural/src/storage/parse.rs +++ b/frame/support/procedural/src/storage/parse.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Parsing of decl_storage input. @@ -166,7 +167,7 @@ struct DeclStorageLine { #[derive(Parse, ToTokens, Debug)] struct DeclStorageGetterBody { - fn_keyword: Option, + fn_keyword: Token![fn], ident: Ident, } diff --git a/frame/support/procedural/src/storage/storage_struct.rs b/frame/support/procedural/src/storage/storage_struct.rs index cbd477354e820946a9f3f1692d70c3a7f2a52ca5..4cacb35c49d9abc0324a5009ee3ead917851e9a6 100644 --- a/frame/support/procedural/src/storage/storage_struct.rs +++ b/frame/support/procedural/src/storage/storage_struct.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Implementation of storage structures and implementation of storage traits on them. @@ -85,7 +86,10 @@ pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStre Ident::new(INHERENT_INSTANCE_NAME, Span::call_site()) }; - let storage_name_str = syn::LitStr::new(&line.name.to_string(), line.name.span()); + let storage_name_bstr = syn::LitByteStr::new( + line.name.to_string().as_ref(), + line.name.span() + ); let storage_generator_trait = &line.storage_generator_trait; let storage_struct = &line.storage_struct; @@ -106,7 +110,7 @@ pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStre } fn storage_prefix() -> &'static [u8] { - #storage_name_str.as_bytes() + #storage_name_bstr } fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query { @@ -130,7 +134,7 @@ pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStre } fn storage_prefix() -> &'static [u8] { - #storage_name_str.as_bytes() + #storage_name_bstr } } @@ -145,7 +149,7 @@ pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStre } fn storage_prefix() -> &'static [u8] { - #storage_name_str.as_bytes() + #storage_name_bstr } fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query { @@ -170,7 +174,7 @@ pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStre } fn storage_prefix() -> &'static [u8] { - #storage_name_str.as_bytes() + #storage_name_bstr } } @@ -188,7 +192,7 @@ pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStre } fn storage_prefix() -> &'static [u8] { - #storage_name_str.as_bytes() + #storage_name_bstr } fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query { diff --git a/frame/support/procedural/src/storage/store_trait.rs b/frame/support/procedural/src/storage/store_trait.rs index 96281e408e958342777aa53c4f973d6cfa9178a7..7efe65b5f31783596841e0c45a6083229ade15c5 100644 --- a/frame/support/procedural/src/storage/store_trait.rs +++ b/frame/support/procedural/src/storage/store_trait.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Declaration of store trait and implementation on module structure. diff --git a/frame/support/procedural/tools/Cargo.toml b/frame/support/procedural/tools/Cargo.toml index f199f1245db0499aa90425ac6da3966fa2132201..a00dd97a66a0bb3de7c3c08d305b99e291181c90 100644 --- a/frame/support/procedural/tools/Cargo.toml +++ b/frame/support/procedural/tools/Cargo.toml @@ -1,19 +1,19 @@ [package] name = "frame-support-procedural-tools" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Proc macro helpers for procedural macros" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -frame-support-procedural-tools-derive = { version = "2.0.0-alpha.5", path = "./derive" } +frame-support-procedural-tools-derive = { version = "2.0.0-rc4", path = "./derive" } proc-macro2 = "1.0.6" quote = "1.0.3" syn = { version = "1.0.7", features = ["full", "visit"] } proc-macro-crate = "0.1.4" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/support/procedural/tools/derive/Cargo.toml b/frame/support/procedural/tools/derive/Cargo.toml index bf6346ab1b67a63c57fb021550dec9a8fda0420a..3da66cf6928fa71b4cffd8bb1104e47ddce44127 100644 --- a/frame/support/procedural/tools/derive/Cargo.toml +++ b/frame/support/procedural/tools/derive/Cargo.toml @@ -1,13 +1,16 @@ [package] name = "frame-support-procedural-tools-derive" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Use to derive parsing for parsing struct." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [lib] proc-macro = true @@ -15,6 +18,3 @@ proc-macro = true proc-macro2 = "1.0.6" quote = { version = "1.0.3", features = ["proc-macro"] } syn = { version = "1.0.7", features = ["proc-macro" ,"full", "extra-traits", "parsing"] } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/support/procedural/tools/derive/src/lib.rs b/frame/support/procedural/tools/derive/src/lib.rs index 0c5930892b1b5321857d05993170acebf7cd2515..ec5af13b6753f2862bbe8ff874866f4d88b14cb3 100644 --- a/frame/support/procedural/tools/derive/src/lib.rs +++ b/frame/support/procedural/tools/derive/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // tag::description[] //! Use to derive parsing for parsing struct. diff --git a/frame/support/procedural/tools/src/lib.rs b/frame/support/procedural/tools/src/lib.rs index 102fee0e18ed0e2bd713967e99048f742273f21b..0033787a7c0450629c693037f73fd43e37d76504 100644 --- a/frame/support/procedural/tools/src/lib.rs +++ b/frame/support/procedural/tools/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. // tag::description[] //! Proc macro helpers for procedural macros diff --git a/frame/support/procedural/tools/src/syn_ext.rs b/frame/support/procedural/tools/src/syn_ext.rs index 45774372325aeebc6b6a89a4aef3efdb480a658d..2ba4cf3f28a11f1935ec50d76f025e543ae3cb06 100644 --- a/frame/support/procedural/tools/src/syn_ext.rs +++ b/frame/support/procedural/tools/src/syn_ext.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // tag::description[] //! Extension to syn types, mainly for parsing diff --git a/frame/support/src/debug.rs b/frame/support/src/debug.rs index 4b7ff6cc393366791d1225a4dbd048379a63b4d5..e4a48068460c6cc038577d7d8eae9304617094fa 100644 --- a/frame/support/src/debug.rs +++ b/frame/support/src/debug.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Runtime debugging and logging utilities. //! diff --git a/frame/support/src/dispatch.rs b/frame/support/src/dispatch.rs index 026b30d0f43d0cb358173819019e4de9def0e2e0..810c67e039b052c0c5b336bf882d71d6ed0ea718 100644 --- a/frame/support/src/dispatch.rs +++ b/frame/support/src/dispatch.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Dispatch system. Contains a macro for defining runtime modules and //! generating values representing lazy module function calls. @@ -24,11 +25,11 @@ pub use frame_metadata::{ ModuleConstantMetadata, DefaultByte, DefaultByteGetter, ModuleErrorMetadata, ErrorMetadata }; pub use crate::weights::{ - SimpleDispatchInfo, GetDispatchInfo, DispatchInfo, WeighData, ClassifyDispatch, - TransactionPriority, Weight, PaysFee, PostDispatchInfo, WithPostDispatchInfo, + GetDispatchInfo, DispatchInfo, WeighData, ClassifyDispatch, TransactionPriority, Weight, + PaysFee, PostDispatchInfo, WithPostDispatchInfo, }; pub use sp_runtime::{traits::Dispatchable, DispatchError}; -pub use crate::traits::{CallMetadata, GetCallMetadata, GetCallName}; +pub use crate::traits::{CallMetadata, GetCallMetadata, GetCallName, UnfilteredDispatchable}; /// The return typ of a `Dispatchable` in frame. When returned explicitly from /// a dispatchable function it allows overriding the default `PostDispatchInfo` @@ -46,19 +47,14 @@ pub type DispatchResult = Result<(), sp_runtime::DispatchError>; pub type DispatchErrorWithPostInfo = sp_runtime::DispatchErrorWithPostInfo; - -/// A type that cannot be instantiated. -pub enum Never {} - -/// Serializable version of Dispatchable. -/// This value can be used as a "function" in an extrinsic. +/// Serializable version of pallet dispatchable. pub trait Callable { - type Call: Dispatchable + Codec + Clone + PartialEq + Eq; + type Call: UnfilteredDispatchable + Codec + Clone + PartialEq + Eq; } // dirty hack to work around serde_derive issue // https://github.com/rust-lang/rust/issues/51331 -pub type CallableCallFor = >::Call; +pub type CallableCallFor = >::Call; /// A type that can be used as a parameter in a dispatchable function. /// @@ -74,14 +70,13 @@ impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {} /// # #[macro_use] /// # extern crate frame_support; /// # use frame_support::dispatch; -/// # use frame_support::weights::SimpleDispatchInfo; -/// # use frame_system::{self as system, Trait, ensure_signed}; +/// # use frame_system::{Trait, ensure_signed}; /// decl_module! { /// pub struct Module for enum Call where origin: T::Origin { /// /// // Private functions are dispatchable, but not available to other /// // FRAME pallets. -/// #[weight = SimpleDispatchInfo::default()] +/// #[weight = 0] /// fn my_function(origin, var: u64) -> dispatch::DispatchResult { /// // Your implementation /// Ok(()) @@ -89,7 +84,7 @@ impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {} /// /// // Public functions are both dispatchable and available to other /// // FRAME pallets. -/// #[weight = SimpleDispatchInfo::default()] +/// #[weight = 0] /// pub fn my_public_function(origin) -> dispatch::DispatchResult { /// // Your implementation /// Ok(()) @@ -111,23 +106,22 @@ impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {} /// ### Shorthand Example /// /// The macro automatically expands a shorthand function declaration to return the -/// [`DispatchResult`] type. These functions are the same: +/// [`DispatchResult`](dispatch::DispatchResult) type. These functions are the same: /// /// ``` /// # #[macro_use] /// # extern crate frame_support; /// # use frame_support::dispatch; -/// # use frame_support::weights::SimpleDispatchInfo; -/// # use frame_system::{self as system, Trait, ensure_signed}; +/// # use frame_system::{Trait, ensure_signed}; /// decl_module! { /// pub struct Module for enum Call where origin: T::Origin { -/// #[weight = SimpleDispatchInfo::default()] +/// #[weight = 0] /// fn my_long_function(origin) -> dispatch::DispatchResult { /// // Your implementation /// Ok(()) /// } /// -/// #[weight = SimpleDispatchInfo::default()] +/// #[weight = 0] /// fn my_short_function(origin) { /// // Your implementation /// } @@ -139,7 +133,7 @@ impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {} /// ### Consuming only portions of the annotated static weight /// /// Per default a callable function consumes all of its static weight as declared via -/// the #[weight] attribute. However, there are use cases where only a portion of this +/// the #\[weight\] attribute. However, there are use cases where only a portion of this /// weight should be consumed. In that case the static weight is charged pre dispatch and /// the difference is refunded post dispatch. /// @@ -153,11 +147,10 @@ impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {} /// # #[macro_use] /// # extern crate frame_support; /// # use frame_support::dispatch::{DispatchResultWithPostInfo, WithPostDispatchInfo}; -/// # use frame_support::weights::SimpleDispatchInfo; -/// # use frame_system::{self as system, Trait, ensure_signed}; +/// # use frame_system::{Trait, ensure_signed}; /// decl_module! { /// pub struct Module for enum Call where origin: T::Origin { -/// #[weight = SimpleDispatchInfo::FixedNormal(1_000_000)] +/// #[weight = 1_000_000] /// fn my_long_function(origin, do_expensive_calc: bool) -> DispatchResultWithPostInfo { /// ensure_signed(origin).map_err(|e| e.with_weight(100_000))?; /// if do_expensive_calc { @@ -182,11 +175,10 @@ impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {} /// # #[macro_use] /// # extern crate frame_support; /// # use frame_support::dispatch; -/// # use frame_support::weights::SimpleDispatchInfo; -/// # use frame_system::{self as system, Trait, ensure_signed, ensure_root}; +/// # use frame_system::{Trait, ensure_signed, ensure_root}; /// decl_module! { /// pub struct Module for enum Call where origin: T::Origin { -/// #[weight = SimpleDispatchInfo::default()] +/// #[weight = 0] /// fn my_privileged_function(origin) -> dispatch::DispatchResult { /// ensure_root(origin)?; /// // Your implementation @@ -277,8 +269,11 @@ impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {} /// * `fn on_finalize() -> frame_support::weights::Weight` /// /// * `offchain_worker`: Executes at the beginning of a block and produces extrinsics for a future block -/// upon completion. Using this function will implement the -/// [`OffchainWorker`](./traits/trait.OffchainWorker.html) trait. +/// upon completion. Using this function will implement the +/// [`OffchainWorker`](./traits/trait.OffchainWorker.html) trait. +/// * `integrity_test`: Executes in a test generated by `construct_runtime`, note it doesn't +/// execute in an externalities-provided environment. Implement +/// [`IntegrityTest`](./trait.IntegrityTest.html) trait. #[macro_export] macro_rules! decl_module { // Entry point #1. @@ -288,7 +283,7 @@ macro_rules! decl_module { $trait_instance:ident: $trait_name:ident $( , I: $instantiable:path $( = $module_default_instance:path )? )? > - for enum $call_type:ident where origin: $origin_type:ty $(, $where_ty:ty: $where_bound:path )* { + for enum $call_type:ident where origin: $origin_type:ty $(, $where_ty:ty: $where_bound:path )* $(,)? { $( $t:tt )* } ) => { @@ -297,7 +292,7 @@ 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 + for enum $call_type where origin: $origin_type, system = frame_system { $( $where_ty: $where_bound ),* } {} {} @@ -306,6 +301,7 @@ macro_rules! decl_module { {} {} {} + {} [] $($t)* ); @@ -321,6 +317,7 @@ macro_rules! decl_module { origin: $origin_type:ty, system = $system:ident $(, $where_ty:ty: $where_bound:path )* + $(,)? { $($t:tt)* } @@ -339,6 +336,7 @@ macro_rules! decl_module { {} {} {} + {} [] $($t)* ); @@ -357,6 +355,7 @@ macro_rules! decl_module { { $( $offchain:tt )* } { $( $constants:tt )* } { $( $error_type:tt )* } + { $( $integrity_test:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* $vis:vis fn deposit_event() = default; @@ -374,6 +373,7 @@ macro_rules! decl_module { { $( $offchain )* } { $( $constants )* } { $( $error_type )* } + { $( $integrity_test)* } [ $( $dispatchables )* ] $($rest)* ); @@ -390,6 +390,7 @@ macro_rules! decl_module { { $( $offchain:tt )* } { $( $constants:tt )* } { $( $error_type:tt )* } + { $( $integrity_test:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* $vis:vis fn deposit_event @@ -399,6 +400,29 @@ macro_rules! decl_module { "`deposit_event` function is reserved and must follow the syntax: `$vis:vis fn deposit_event() = default;`" ); }; + // Compile error on `deposit_event` being added a second time. + (@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 )* } + { $( $on_runtime_upgrade:tt )* } + { $( $on_finalize:tt )* } + { $( $offchain:tt )* } + { $( $constants:tt )* } + { $( $error_type:tt )* } + { $( $integrity_test:tt )* } + [ $( $dispatchables:tt )* ] + $(#[doc = $doc_attr:tt])* + $vis:vis fn deposit_event() = default; + $($rest:tt)* + ) => { + compile_error!("`deposit_event` can only be passed once as input."); + }; // Add on_finalize (@normalize $(#[$attr:meta])* @@ -412,6 +436,7 @@ macro_rules! decl_module { { $( $offchain:tt )* } { $( $constants:tt )* } { $( $error_type:tt )* } + { $( $integrity_test:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* fn on_finalize( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* } @@ -431,6 +456,7 @@ macro_rules! decl_module { { $( $offchain )* } { $( $constants )* } { $( $error_type )* } + { $( $integrity_test)* } [ $( $dispatchables )* ] $($rest)* ); @@ -448,6 +474,7 @@ macro_rules! decl_module { { $( $offchain:tt )* } { $( $constants:tt )* } { $( $error_type:tt )* } + { $( $integrity_test:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* #[weight = $weight:expr] @@ -459,6 +486,30 @@ macro_rules! decl_module { `on_initialize` or `on_runtime_upgrade` instead" ); }; + // Compile error on `on_finalize` being added a second time. + (@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 )* } + { $( $on_runtime_upgrade:tt )* } + { $( $on_finalize:tt )+ } + { $( $offchain:tt )* } + { $( $constants:tt )* } + { $( $error_type:tt )* } + { $( $integrity_test:tt )* } + [ $( $dispatchables:tt )* ] + $(#[doc = $doc_attr:tt])* + #[weight = $weight:expr] + fn on_finalize( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* } + $($rest:tt)* + ) => { + compile_error!("`on_finalize` can only be passed once as input."); + }; // compile_error on_runtime_upgrade, without a given weight removed syntax. (@normalize $(#[$attr:meta])* @@ -474,6 +525,7 @@ macro_rules! decl_module { { $( $offchain:tt )* } { $( $constants:tt )* } { $( $error_type:tt )* } + { $( $integrity_test:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* fn on_runtime_upgrade( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* } @@ -498,6 +550,7 @@ macro_rules! decl_module { { $( $offchain:tt )* } { $( $constants:tt )* } { $( $error_type:tt )* } + { $( $integrity_test:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* #[weight = $weight:expr] @@ -524,6 +577,7 @@ macro_rules! decl_module { { $( $offchain:tt )* } { $( $constants:tt )* } { $( $error_type:tt )* } + { $( $integrity_test:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* fn on_runtime_upgrade( $( $param_name:ident : $param:ty ),* $(,)? ) -> $return:ty { $( $impl:tt )* } @@ -543,10 +597,98 @@ macro_rules! decl_module { { $( $offchain )* } { $( $constants )* } { $( $error_type )* } + { $( $integrity_test)* } [ $( $dispatchables )* ] $($rest)* ); }; + // Compile error on `on_runtime_upgrade` being added a second time. + (@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 )* } + { $( $on_runtime_upgrade:tt )+ } + { $( $on_finalize:tt )* } + { $( $offchain:tt )* } + { $( $constants:tt )* } + { $( $error_type:tt )* } + { $( $integrity_test:tt )* } + [ $( $dispatchables:tt )* ] + $(#[doc = $doc_attr:tt])* + fn on_runtime_upgrade( $( $param_name:ident : $param:ty ),* $(,)? ) -> $return:ty { $( $impl:tt )* } + $($rest:tt)* + ) => { + compile_error!("`on_runtime_upgrade` can only be passed once as input."); + }; + // Add integrity_test + (@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 )* } + { $( $on_runtime_upgrade:tt )* } + { $( $on_finalize:tt )* } + { $( $offchain:tt )* } + { $( $constants:tt )* } + { $( $error_type:tt )* } + {} + [ $( $dispatchables:tt )* ] + $(#[doc = $doc_attr:tt])* + fn integrity_test() { $( $impl:tt )* } + $($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 )* } + { $( $deposit_event )* } + { $( $on_initialize )* } + { $( $on_runtime_upgrade )* } + { $( $on_finalize )* } + { $( $offchain )* } + { $( $constants )* } + { $( $error_type )* } + { + $(#[doc = $doc_attr])* + fn integrity_test() { $( $impl)* } + } + [ $( $dispatchables )* ] + $($rest)* + ); + }; + // Compile error on `integrity_test` being added a second time. + (@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 )* } + { $( $on_runtime_upgrade:tt )* } + { $( $on_finalize:tt )* } + { $( $offchain:tt )* } + { $( $constants:tt )* } + { $( $error_type:tt )* } + { $( $integrity_test:tt )+ } + [ $( $dispatchables:tt )* ] + $(#[doc = $doc_attr:tt])* + fn integrity_test() { $( $impl:tt )* } + $($rest:tt)* + ) => { + compile_error!("`integrity_test` can only be passed once as input."); + }; // compile_error on_initialize, without a given weight removed syntax. (@normalize $(#[$attr:meta])* @@ -562,6 +704,7 @@ macro_rules! decl_module { { $( $offchain:tt )* } { $( $constants:tt )* } { $( $error_type:tt )* } + { $( $integrity_test:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* fn on_initialize( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* } @@ -586,6 +729,7 @@ macro_rules! decl_module { { $( $offchain:tt )* } { $( $constants:tt )* } { $( $error_type:tt )* } + { $( $integrity_test:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* #[weight = $weight:expr] @@ -612,6 +756,7 @@ macro_rules! decl_module { { $( $offchain:tt )* } { $( $constants:tt )* } { $( $error_type:tt )* } + { $( $integrity_test:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* fn on_initialize( $( $param_name:ident : $param:ty ),* $(,)? ) -> $return:ty { $( $impl:tt )* } @@ -631,10 +776,34 @@ macro_rules! decl_module { { $( $offchain )* } { $( $constants )* } { $( $error_type )* } + { $( $integrity_test)* } [ $( $dispatchables )* ] $($rest)* ); }; + // Compile error on trying to add a second `on_initialize`. + (@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 )+ } + { $( $on_runtime_upgrade:tt )* } + { $( $on_finalize:tt )* } + { $( $offchain:tt )* } + { $( $constants:tt )* } + { $( $error_type:tt )* } + { $( $integrity_test:tt )* } + [ $( $dispatchables:tt )* ] + $(#[doc = $doc_attr:tt])* + fn on_initialize( $( $param_name:ident : $param:ty ),* $(,)? ) -> $return:ty { $( $impl:tt )* } + $($rest:tt)* + ) => { + compile_error!("`on_initialize` can only be passed once as input."); + }; (@normalize $(#[$attr:meta])* pub struct $mod_type:ident< @@ -650,6 +819,7 @@ macro_rules! decl_module { { } { $( $constants:tt )* } { $( $error_type:tt )* } + { $( $integrity_test:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* fn offchain_worker( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* } @@ -669,11 +839,34 @@ macro_rules! decl_module { { fn offchain_worker( $( $param_name : $param ),* ) { $( $impl )* } } { $( $constants )* } { $( $error_type )* } + { $( $integrity_test)* } [ $( $dispatchables )* ] $($rest)* ); }; - + // Compile error on trying to add a second `offchain_worker`. + (@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 )* } + { $( $on_runtime_upgrade:tt )* } + { $( $on_finalize:tt )* } + { $( $offchain:tt )+ } + { $( $constants:tt )* } + { $( $error_type:tt )* } + { $( $integrity_test:tt )* } + [ $( $dispatchables:tt )* ] + $(#[doc = $doc_attr:tt])* + fn offchain_worker( $( $param_name:ident : $param:ty ),* $(,)? ) -> $return:ty { $( $impl:tt )* } + $($rest:tt)* + ) => { + compile_error!("`offchain_worker` can only be passed once as input."); + }; // This puts a constant in the parsed constants list. (@normalize $(#[$attr:meta])* @@ -690,6 +883,7 @@ macro_rules! decl_module { { $( $offchain:tt )* } { $( $constants:tt )* } { $( $error_type:tt )* } + { $( $integrity_test:tt )* } [ $( $dispatchables:tt )* ] $( #[doc = $doc_attr:tt] )* const $name:ident: $ty:ty = $value:expr; @@ -714,6 +908,7 @@ macro_rules! decl_module { $name: $ty = $value; } { $( $error_type )* } + { $( $integrity_test)* } [ $( $dispatchables )* ] $($rest)* ); @@ -735,6 +930,7 @@ macro_rules! decl_module { { $( $offchain:tt )* } { $( $constants:tt )* } { } + { $( $integrity_test:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* type Error = $error_type:ty; @@ -754,6 +950,7 @@ macro_rules! decl_module { { $( $offchain )* } { $( $constants )* } { $error_type } + { $( $integrity_test)* } [ $( $dispatchables )* ] $($rest)* ); @@ -774,6 +971,7 @@ macro_rules! decl_module { { $( $offchain:tt )* } { $( $constants:tt )* } { } + { $( $integrity_test:tt )* } [ $($t:tt)* ] $($rest:tt)* ) => { @@ -791,6 +989,7 @@ macro_rules! decl_module { { $( $offchain )* } { $( $constants )* } { &'static str } + { $( $integrity_test)* } [ $($t)* ] $($rest)* ); @@ -812,6 +1011,7 @@ macro_rules! decl_module { { $( $offchain:tt )* } { $( $constants:tt )* } { $error_type:ty } + { $( $integrity_test:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* #[weight = $weight:expr] @@ -834,6 +1034,7 @@ macro_rules! decl_module { { $( $offchain )* } { $( $constants )* } { $error_type } + { $( $integrity_test)* } [ $( $dispatchables )* $(#[doc = $doc_attr])* @@ -862,6 +1063,7 @@ macro_rules! decl_module { { $( $offchain:tt )* } { $( $constants:tt )* } { $( $error_type:tt )* } + { $( $integrity_test:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* $fn_vis:vis fn $fn_name:ident( @@ -888,6 +1090,7 @@ macro_rules! decl_module { { $( $offchain:tt )* } { $( $constants:tt )* } { $( $error_type:tt )* } + { $( $integrity_test:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* $(#[weight = $weight:expr])? @@ -914,6 +1117,7 @@ macro_rules! decl_module { { $( $offchain:tt )* } { $( $constants:tt )* } { $( $error_type:tt )* } + { $( $integrity_test:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* $(#[weight = $weight:expr])? @@ -940,6 +1144,7 @@ macro_rules! decl_module { { $( $offchain:tt )* } { $( $constants:tt )* } { $( $error_type:tt )* } + { $( $integrity_test:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* $(#[weight = $weight:expr])? @@ -967,6 +1172,7 @@ macro_rules! decl_module { { $( $offchain:tt )* } { $( $constants:tt )* } { $( $error_type:tt )* } + { $( $integrity_test:tt )* } [ $( $dispatchables:tt )* ] ) => { $crate::decl_module!(@imp @@ -983,6 +1189,7 @@ macro_rules! decl_module { { $( $offchain )* } { $( $constants )* } { $( $error_type )* } + { $( $integrity_test)* } ); }; @@ -1012,6 +1219,7 @@ macro_rules! decl_module { impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> $module<$trait_instance $(, $instance)?> where $( $other_where_bounds )* { + /// Deposits an event using `frame_system::Module::deposit_event`. $vis fn deposit_event( event: impl Into<< $trait_instance as $trait_name $(<$instance>)? >::Event> ) { @@ -1030,12 +1238,7 @@ macro_rules! decl_module { for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )* { fn on_initialize(_block_number_not_used: $trait_instance::BlockNumber) -> $return { - use $crate::sp_std::if_std; - if_std! { - use $crate::tracing; - let span = tracing::span!(tracing::Level::DEBUG, "on_initialize"); - let _enter = span.enter(); - } + $crate::sp_tracing::enter_span!("on_initialize"); { $( $impl )* } } } @@ -1051,12 +1254,7 @@ macro_rules! decl_module { for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )* { fn on_initialize($param: $param_ty) -> $return { - use $crate::sp_std::if_std; - if_std! { - use $crate::tracing; - let span = tracing::span!(tracing::Level::DEBUG, "on_initialize"); - let _enter = span.enter(); - } + $crate::sp_tracing::enter_span!("on_initialize"); { $( $impl )* } } } @@ -1082,12 +1280,7 @@ macro_rules! decl_module { for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )* { fn on_runtime_upgrade() -> $return { - use $crate::sp_std::if_std; - if_std! { - use $crate::tracing; - let span = tracing::span!(tracing::Level::DEBUG, "on_runtime_upgrade"); - let _enter = span.enter(); - } + $crate::sp_tracing::enter_span!("on_runtime_upgrade"); { $( $impl )* } } } @@ -1103,6 +1296,32 @@ macro_rules! decl_module { {} }; + (@impl_integrity_test + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; + { $( $other_where_bounds:tt )* } + $(#[doc = $doc_attr:tt])* + fn integrity_test() { $( $impl:tt )* } + ) => { + impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> + $crate::traits::IntegrityTest + for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )* + { + $(#[doc = $doc_attr])* + fn integrity_test() { + $( $impl )* + } + } + }; + + (@impl_integrity_test + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; + { $( $other_where_bounds:tt )* } + ) => { + impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> + $crate::traits::IntegrityTest + for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )* + {} + }; (@impl_on_finalize $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; @@ -1114,12 +1333,7 @@ macro_rules! decl_module { for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )* { fn on_finalize(_block_number_not_used: $trait_instance::BlockNumber) { - use $crate::sp_std::if_std; - if_std! { - use $crate::tracing; - let span = tracing::span!(tracing::Level::DEBUG, "on_finalize"); - let _enter = span.enter(); - } + $crate::sp_tracing::enter_span!("on_finalize"); { $( $impl )* } } } @@ -1135,12 +1349,7 @@ macro_rules! decl_module { for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )* { fn on_finalize($param: $param_ty) { - use $crate::sp_std::if_std; - if_std! { - use $crate::tracing; - let span = tracing::span!(tracing::Level::DEBUG, "on_finalize"); - let _enter = span.enter(); - } + $crate::sp_tracing::enter_span!("on_finalize"); { $( $impl )* } } } @@ -1209,15 +1418,9 @@ macro_rules! decl_module { $vis fn $name( $origin: $origin_ty $(, $param: $param_ty )* ) -> $crate::dispatch::DispatchResult { - $crate::sp_std::if_std! { - use $crate::tracing; - let span = tracing::span!(tracing::Level::DEBUG, stringify!($name)); - let _enter = span.enter(); - } - { - { $( $impl )* } - Ok(()) - } + $crate::sp_tracing::enter_span!(stringify!($name)); + { $( $impl )* } + Ok(()) } }; @@ -1234,13 +1437,8 @@ macro_rules! decl_module { ) => { $(#[doc = $doc_attr])* $vis fn $name($origin: $origin_ty $(, $param: $param_ty )* ) -> $result { - use $crate::sp_std::if_std; - if_std! { - use $crate::tracing; - let span = tracing::span!(tracing::Level::DEBUG, stringify!($name)); - let _enter = span.enter(); - } - { $( $impl )* } + $crate::sp_tracing::enter_span!(stringify!($name)); + $( $impl )* } }; @@ -1352,7 +1550,7 @@ macro_rules! decl_module { { #[doc(hidden)] #[codec(skip)] - __PhantomItem($crate::sp_std::marker::PhantomData<($trait_instance, $($instance)?)>, $crate::dispatch::Never), + __PhantomItem($crate::sp_std::marker::PhantomData<($trait_instance, $($instance)?)>, $crate::Never), $( $generated_variants )* } }; @@ -1383,6 +1581,7 @@ macro_rules! decl_module { { $( $offchain:tt )* } { $( $constants:tt )* } { $error_type:ty } + { $( $integrity_test:tt )* } ) => { $crate::__check_reserved_fn_name! { $( $fn_name )* } @@ -1409,7 +1608,6 @@ macro_rules! decl_module { $( $on_runtime_upgrade )* } - $crate::decl_module! { @impl_on_finalize $mod_type<$trait_instance: $trait_name $(, $instance: $instantiable)?>; @@ -1431,6 +1629,13 @@ macro_rules! decl_module { $( $deposit_event )* } + $crate::decl_module! { + @impl_integrity_test + $mod_type<$trait_instance: $trait_name $(, $instance: $instantiable)?>; + { $( $other_where_bounds )* } + $( $integrity_test )* + } + /// Can also be called using [`Call`]. /// /// [`Call`]: enum.Call.html @@ -1445,6 +1650,8 @@ macro_rules! decl_module { $error_type; $from; $(#[doc = $doc_attr])* + /// + /// NOTE: Calling this function will bypass origin filters. $fn_vis fn $fn_name ( $from $(, $param_name : $param )* ) $( -> $result )* { $( $impl )* } @@ -1477,16 +1684,17 @@ macro_rules! decl_module { match *self { $( $call_type::$fn_name( $( ref $param_name ),* ) => { + let base_weight = $weight; let weight = >::weigh_data( - &$weight, + &base_weight, ($( $param_name, )*) ); let class = >::classify_dispatch( - &$weight, + &base_weight, ($( $param_name, )*) ); let pays_fee = >::pays_fee( - &$weight, + &base_weight, ($( $param_name, )*) ); $crate::dispatch::DispatchInfo { @@ -1588,13 +1796,11 @@ macro_rules! decl_module { } } - impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::Dispatchable + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::traits::UnfilteredDispatchable for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )* { - type Trait = $trait_instance; type Origin = $origin_type; - type PostInfo = $crate::weights::PostDispatchInfo; - fn dispatch(self, _origin: Self::Origin) -> $crate::dispatch::DispatchResultWithPostInfo { + fn dispatch_bypass_filter(self, _origin: Self::Origin) -> $crate::dispatch::DispatchResultWithPostInfo { match self { $( $call_type::$fn_name( $( $param_name ),* ) => { @@ -1615,17 +1821,6 @@ macro_rules! decl_module { type Call = $call_type<$trait_instance $(, $instance)?>; } - impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $mod_type<$trait_instance $(, $instance)?> - where $( $other_where_bounds )* - { - #[doc(hidden)] - pub fn dispatch>( - d: D, - origin: D::Origin - ) -> $crate::dispatch::DispatchResultWithPostInfo { - d.dispatch(origin) - } - } $crate::__dispatch_impl_metadata! { $mod_type<$trait_instance: $trait_name $(, $instance: $instantiable)?> { $( $other_where_bounds )* } @@ -1653,8 +1848,8 @@ macro_rules! decl_module { } } -pub trait IsSubType, R> { - fn is_sub_type(&self) -> Option<&CallableCallFor>; +pub trait IsSubType { + fn is_sub_type(&self) -> Option<&T>; } /// Implement a meta-dispatch module to dispatch to other dispatchers. @@ -1720,10 +1915,25 @@ macro_rules! impl_outer_dispatch { impl $crate::dispatch::Dispatchable for $call_type { type Origin = $origin; type Trait = $call_type; + type Info = $crate::weights::DispatchInfo; type PostInfo = $crate::weights::PostDispatchInfo; fn dispatch( self, origin: $origin, + ) -> $crate::dispatch::DispatchResultWithPostInfo { + if !::filter_call(&origin, &self) { + return $crate::sp_std::result::Result::Err($crate::dispatch::DispatchError::BadOrigin.into()) + } + + $crate::traits::UnfilteredDispatchable::dispatch_bypass_filter(self, origin) + } + } + + impl $crate::traits::UnfilteredDispatchable for $call_type { + type Origin = $origin; + fn dispatch_bypass_filter( + self, + origin: $origin, ) -> $crate::dispatch::DispatchResultWithPostInfo { $crate::impl_outer_dispatch! { @DISPATCH_MATCH @@ -1736,8 +1946,9 @@ macro_rules! impl_outer_dispatch { } } } + $( - impl $crate::dispatch::IsSubType<$camelcase, $runtime> for $call_type { + impl $crate::dispatch::IsSubType<$crate::dispatch::CallableCallFor<$camelcase, $runtime>> for $call_type { #[allow(unreachable_patterns)] fn is_sub_type(&self) -> Option<&$crate::dispatch::CallableCallFor<$camelcase, $runtime>> { match *self { @@ -1771,7 +1982,8 @@ macro_rules! impl_outer_dispatch { $origin { $( $generated )* - $call_type::$name(call) => call.dispatch($origin), + $call_type::$name(call) => + $crate::traits::UnfilteredDispatchable::dispatch_bypass_filter(call, $origin), } $index + 1; $( $rest ),* @@ -2051,6 +2263,9 @@ macro_rules! __check_reserved_fn_name { (offchain_worker $( $rest:ident )*) => { $crate::__check_reserved_fn_name!(@compile_error offchain_worker); }; + (integrity_test $( $rest:ident )*) => { + $crate::__check_reserved_fn_name!(@compile_error integrity_test); + }; ($t:ident $( $rest:ident )*) => { $crate::__check_reserved_fn_name!($( $rest )*); }; @@ -2084,146 +2299,169 @@ macro_rules! __check_reserved_fn_name { #[allow(dead_code)] mod tests { use super::*; - use crate::weights::{DispatchInfo, DispatchClass}; + use crate::weights::{DispatchInfo, DispatchClass, Pays}; use crate::traits::{ - CallMetadata, GetCallMetadata, GetCallName, OnInitialize, OnFinalize, OnRuntimeUpgrade + CallMetadata, GetCallMetadata, GetCallName, OnInitialize, OnFinalize, OnRuntimeUpgrade, + IntegrityTest, }; pub trait Trait: system::Trait + Sized where Self::AccountId: From { - type Origin; type BlockNumber: Into; - type Call: From>; } pub mod system { - use super::*; + use codec::{Encode, Decode}; pub trait Trait { type AccountId; + type Call; + type BaseCallFilter; + type Origin: crate::traits::OriginTrait; } - pub fn ensure_root(_: R) -> DispatchResult { - Ok(()) + #[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)] + pub enum RawOrigin { + Root, + Signed(AccountId), + None, + } + + impl From> for RawOrigin { + fn from(s: Option) -> RawOrigin { + match s { + Some(who) => RawOrigin::Signed(who), + None => RawOrigin::None, + } + } } + + pub type Origin = RawOrigin<::AccountId>; } decl_module! { - pub struct Module for enum Call where origin: T::Origin, T::AccountId: From { + pub struct Module for enum Call where origin: T::Origin, system = system, T::AccountId: From { /// Hi, this is a comment. - #[weight = SimpleDispatchInfo::default()] + #[weight = 0] fn aux_0(_origin) -> DispatchResult { unreachable!() } - #[weight = SimpleDispatchInfo::default()] + #[weight = 0] fn aux_1(_origin, #[compact] _data: u32,) -> DispatchResult { unreachable!() } - #[weight = SimpleDispatchInfo::default()] + #[weight = 0] fn aux_2(_origin, _data: i32, _data2: String) -> DispatchResult { unreachable!() } - #[weight = SimpleDispatchInfo::FixedNormal(3)] + #[weight = 3] fn aux_3(_origin) -> DispatchResult { unreachable!() } - #[weight = SimpleDispatchInfo::default()] + #[weight = 0] fn aux_4(_origin, _data: i32) -> DispatchResult { unreachable!() } - #[weight = SimpleDispatchInfo::default()] + #[weight = 0] fn aux_5(_origin, _data: i32, #[compact] _data2: u32,) -> DispatchResult { unreachable!() } - #[weight = SimpleDispatchInfo::FixedOperational(5)] + #[weight = (5, DispatchClass::Operational)] fn operational(_origin) { unreachable!() } fn on_initialize(n: T::BlockNumber,) -> Weight { if n.into() == 42 { panic!("on_initialize") } 7 } fn on_finalize(n: T::BlockNumber,) { if n.into() == 42 { panic!("on_finalize") } } fn on_runtime_upgrade() -> Weight { 10 } fn offchain_worker() {} + /// Some doc + fn integrity_test() { panic!("integrity_test") } } } const EXPECTED_METADATA: &'static [FunctionMetadata] = &[ - FunctionMetadata { - name: DecodeDifferent::Encode("aux_0"), - arguments: DecodeDifferent::Encode(&[]), - documentation: DecodeDifferent::Encode(&[ - " Hi, this is a comment." - ]) - }, - FunctionMetadata { - name: DecodeDifferent::Encode("aux_1"), - arguments: DecodeDifferent::Encode(&[ - FunctionArgumentMetadata { - name: DecodeDifferent::Encode("_data"), - ty: DecodeDifferent::Encode("Compact") - } - ]), - documentation: DecodeDifferent::Encode(&[]), - }, - FunctionMetadata { - name: DecodeDifferent::Encode("aux_2"), - arguments: DecodeDifferent::Encode(&[ - FunctionArgumentMetadata { - name: DecodeDifferent::Encode("_data"), - ty: DecodeDifferent::Encode("i32"), - }, - FunctionArgumentMetadata { - name: DecodeDifferent::Encode("_data2"), - ty: DecodeDifferent::Encode("String"), - } - ]), - documentation: DecodeDifferent::Encode(&[]), - }, - FunctionMetadata { - name: DecodeDifferent::Encode("aux_3"), - arguments: DecodeDifferent::Encode(&[]), - documentation: DecodeDifferent::Encode(&[]), - }, - FunctionMetadata { - name: DecodeDifferent::Encode("aux_4"), - arguments: DecodeDifferent::Encode(&[ - FunctionArgumentMetadata { - name: DecodeDifferent::Encode("_data"), - ty: DecodeDifferent::Encode("i32"), - } - ]), - documentation: DecodeDifferent::Encode(&[]), - }, - FunctionMetadata { - name: DecodeDifferent::Encode("aux_5"), - arguments: DecodeDifferent::Encode(&[ - FunctionArgumentMetadata { - name: DecodeDifferent::Encode("_data"), - ty: DecodeDifferent::Encode("i32"), - }, - FunctionArgumentMetadata { - name: DecodeDifferent::Encode("_data2"), - ty: DecodeDifferent::Encode("Compact") - } - ]), - documentation: DecodeDifferent::Encode(&[]), + FunctionMetadata { + name: DecodeDifferent::Encode("aux_0"), + arguments: DecodeDifferent::Encode(&[]), + documentation: DecodeDifferent::Encode(&[ + " Hi, this is a comment." + ]) + }, + FunctionMetadata { + name: DecodeDifferent::Encode("aux_1"), + arguments: DecodeDifferent::Encode(&[ + FunctionArgumentMetadata { + name: DecodeDifferent::Encode("_data"), + ty: DecodeDifferent::Encode("Compact") + } + ]), + documentation: DecodeDifferent::Encode(&[]), + }, + FunctionMetadata { + name: DecodeDifferent::Encode("aux_2"), + arguments: DecodeDifferent::Encode(&[ + FunctionArgumentMetadata { + name: DecodeDifferent::Encode("_data"), + ty: DecodeDifferent::Encode("i32"), }, - FunctionMetadata { - name: DecodeDifferent::Encode("operational"), - arguments: DecodeDifferent::Encode(&[]), - documentation: DecodeDifferent::Encode(&[]), + FunctionArgumentMetadata { + name: DecodeDifferent::Encode("_data2"), + ty: DecodeDifferent::Encode("String"), + } + ]), + documentation: DecodeDifferent::Encode(&[]), + }, + FunctionMetadata { + name: DecodeDifferent::Encode("aux_3"), + arguments: DecodeDifferent::Encode(&[]), + documentation: DecodeDifferent::Encode(&[]), + }, + FunctionMetadata { + name: DecodeDifferent::Encode("aux_4"), + arguments: DecodeDifferent::Encode(&[ + FunctionArgumentMetadata { + name: DecodeDifferent::Encode("_data"), + ty: DecodeDifferent::Encode("i32"), + } + ]), + documentation: DecodeDifferent::Encode(&[]), + }, + FunctionMetadata { + name: DecodeDifferent::Encode("aux_5"), + arguments: DecodeDifferent::Encode(&[ + FunctionArgumentMetadata { + name: DecodeDifferent::Encode("_data"), + ty: DecodeDifferent::Encode("i32"), }, - ]; + FunctionArgumentMetadata { + name: DecodeDifferent::Encode("_data2"), + ty: DecodeDifferent::Encode("Compact") + } + ]), + documentation: DecodeDifferent::Encode(&[]), + }, + FunctionMetadata { + name: DecodeDifferent::Encode("operational"), + arguments: DecodeDifferent::Encode(&[]), + documentation: DecodeDifferent::Encode(&[]), + }, + ]; pub struct TraitImpl {} impl Trait for TraitImpl { - type Origin = u32; type BlockNumber = u32; - type Call = OuterCall; } type Test = Module; + impl_outer_origin!{ + pub enum OuterOrigin for TraitImpl where system = system {} + } + impl_outer_dispatch! { - pub enum OuterCall for TraitImpl where origin: u32 { + pub enum OuterCall for TraitImpl where origin: OuterOrigin { self::Test, } } impl system::Trait for TraitImpl { + type Origin = OuterOrigin; type AccountId = u32; + type Call = OuterCall; + type BaseCallFilter = (); } #[test] @@ -2287,17 +2525,12 @@ mod tests { // operational. assert_eq!( Call::::operational().get_dispatch_info(), - DispatchInfo { weight: 5, class: DispatchClass::Operational, pays_fee: true }, - ); - // default weight. - assert_eq!( - Call::::aux_0().get_dispatch_info(), - DispatchInfo { weight: 10_000, class: DispatchClass::Normal, pays_fee: true }, + DispatchInfo { weight: 5, class: DispatchClass::Operational, pays_fee: Pays::Yes }, ); // custom basic assert_eq!( Call::::aux_3().get_dispatch_info(), - DispatchInfo { weight: 3, class: DispatchClass::Normal, pays_fee: true }, + DispatchInfo { weight: 3, class: DispatchClass::Normal, pays_fee: Pays::Yes }, ); } @@ -2326,4 +2559,10 @@ mod tests { let module_names = OuterCall::get_module_names(); assert_eq!(["Test"], module_names); } + + #[test] + #[should_panic(expected = "integrity_test")] + fn integrity_test_should_work() { + as IntegrityTest>::integrity_test(); + } } diff --git a/frame/support/src/error.rs b/frame/support/src/error.rs index f619250726deda5caea1f76894d1a75793458f01..d758ad52e72b3ba7fe10ceee4d978c7bd722887c 100644 --- a/frame/support/src/error.rs +++ b/frame/support/src/error.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Macro for declaring a module error. @@ -35,7 +36,7 @@ pub use frame_metadata::{ModuleErrorMetadata, ErrorMetadata, DecodeDifferent}; /// /// ``` /// # use frame_support::{decl_error, decl_module}; -/// # use frame_support::weights::SimpleDispatchInfo; +/// # /// decl_error! { /// /// Errors that can occur in my module. /// pub enum MyError for Module { @@ -46,7 +47,7 @@ pub use frame_metadata::{ModuleErrorMetadata, ErrorMetadata, DecodeDifferent}; /// } /// } /// -/// # use frame_system::{self as system, Trait}; +/// # use frame_system::Trait; /// /// // You need to register the error type in `decl_module!` as well to make the error /// // exported in the metadata. @@ -55,7 +56,7 @@ pub use frame_metadata::{ModuleErrorMetadata, ErrorMetadata, DecodeDifferent}; /// pub struct Module for enum Call where origin: T::Origin { /// type Error = MyError; /// -/// #[weight = SimpleDispatchInfo::default()] +/// #[weight = 0] /// fn do_something(origin) -> frame_support::dispatch::DispatchResult { /// Err(MyError::::YouAreNotCoolEnough.into()) /// } @@ -89,7 +90,7 @@ macro_rules! decl_error { #[doc(hidden)] __Ignore( $crate::sp_std::marker::PhantomData<($generic, $( $inst_generic)?)>, - $crate::dispatch::Never, + $crate::Never, ), $( $( #[doc = $doc_attr] )* diff --git a/frame/support/src/hash.rs b/frame/support/src/hash.rs index 693e929a309e366b0605805d1721429904d04806..a5de205863d5ca8584e32b4b557e5b13eedbeeec 100644 --- a/frame/support/src/hash.rs +++ b/frame/support/src/hash.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Hash utilities. @@ -60,7 +61,12 @@ pub trait StorageHasher: 'static { } /// Hasher to use to hash keys to insert to storage. +/// +/// Reversible hasher store the encoded key after the hash part. pub trait ReversibleStorageHasher: StorageHasher { + /// Split the hash part out of the input. + /// + /// I.e. for input `&[hash ++ key ++ some]` returns `&[key ++ some]` fn reverse(x: &[u8]) -> &[u8]; } diff --git a/frame/support/src/inherent.rs b/frame/support/src/inherent.rs index a21bd361b618dc515755a1cb444b4ccb22193283..e9b0c22692e9da09dd423a760962036d54b8e0d7 100644 --- a/frame/support/src/inherent.rs +++ b/frame/support/src/inherent.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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. +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. #[doc(hidden)] pub use crate::sp_std::vec::Vec; @@ -30,19 +31,20 @@ pub use sp_inherents::{InherentData, ProvideInherent, CheckInherentsResult, IsFa /// ```nocompile /// impl_outer_inherent! { /// impl Inherents where Block = Block, UncheckedExtrinsic = UncheckedExtrinsic { -/// timestamp: Timestamp, -/// consensus: Consensus, -/// /// Aura module using the `Timestamp` call. -/// aura: Timestamp, +/// timestamp, +/// consensus, +/// aura, /// } /// } /// ``` #[macro_export] macro_rules! impl_outer_inherent { ( - impl Inherents where Block = $block:ident, UncheckedExtrinsic = $uncheckedextrinsic:ident + impl Inherents where + Block = $block:ident, + UncheckedExtrinsic = $uncheckedextrinsic:ident { - $( $module:ident: $call:ident, )* + $( $module:ident, )* } ) => { trait InherentDataExt { @@ -54,15 +56,14 @@ macro_rules! impl_outer_inherent { impl InherentDataExt for $crate::inherent::InherentData { fn create_extrinsics(&self) -> $crate::inherent::Vec<<$block as $crate::inherent::BlockT>::Extrinsic> { - use $crate::inherent::ProvideInherent; - use $crate::inherent::Extrinsic; + use $crate::inherent::{ProvideInherent, Extrinsic}; let mut inherents = Vec::new(); $( if let Some(inherent) = $module::create_inherent(self) { inherents.push($uncheckedextrinsic::new( - Call::$call(inherent), + inherent.into(), None, ).expect("Runtime UncheckedExtrinsic is not Opaque, so it has to return `Some`; qed")); } @@ -73,32 +74,201 @@ macro_rules! impl_outer_inherent { fn check_extrinsics(&self, block: &$block) -> $crate::inherent::CheckInherentsResult { use $crate::inherent::{ProvideInherent, IsFatalError}; + use $crate::dispatch::IsSubType; let mut result = $crate::inherent::CheckInherentsResult::new(); for xt in block.extrinsics() { if $crate::inherent::Extrinsic::is_signed(xt).unwrap_or(false) { - break; + break } - $( - match xt.function { - Call::$call(ref call) => { - if let Err(e) = $module::check_inherent(call, self) { - result.put_error( - $module::INHERENT_IDENTIFIER, &e - ).expect("There is only one fatal error; qed"); - if e.is_fatal_error() { - return result; - } + $({ + if let Some(call) = IsSubType::<_>::is_sub_type(&xt.function) { + if let Err(e) = $module::check_inherent(call, self) { + result.put_error( + $module::INHERENT_IDENTIFIER, &e + ).expect("There is only one fatal error; qed"); + if e.is_fatal_error() { + return result } } - _ => {}, } - )* + })* } + $( + match $module::is_inherent_required(self) { + Ok(Some(e)) => { + let found = block.extrinsics().iter().any(|xt| { + if $crate::inherent::Extrinsic::is_signed(xt).unwrap_or(false) { + return false + } + + let call: Option<&<$module as ProvideInherent>::Call> = + xt.function.is_sub_type(); + + call.is_some() + }); + + if !found { + result.put_error( + $module::INHERENT_IDENTIFIER, &e + ).expect("There is only one fatal error; qed"); + if e.is_fatal_error() { + return result + } + } + }, + Ok(None) => (), + Err(e) => { + result.put_error( + $module::INHERENT_IDENTIFIER, &e + ).expect("There is only one fatal error; qed"); + if e.is_fatal_error() { + return result + } + }, + } + )* + result } } }; } + +#[cfg(test)] +mod tests { + use super::*; + use sp_runtime::{traits, testing::{Header, self}}; + use crate::dispatch::IsSubType; + + #[derive(codec::Encode, codec::Decode, Clone, PartialEq, Eq, Debug, serde::Serialize)] + enum Call { + Test(CallTest), + Test2(CallTest2), + } + + impl From for Call { + fn from(call: CallTest) -> Self { + Self::Test(call) + } + } + + impl From for Call { + fn from(call: CallTest2) -> Self { + Self::Test2(call) + } + } + + impl IsSubType for Call { + fn is_sub_type(&self) -> Option<&CallTest> { + match self { + Self::Test(test) => Some(test), + _ => None, + } + } + } + + impl IsSubType for Call { + fn is_sub_type(&self) -> Option<&CallTest2> { + match self { + Self::Test2(test) => Some(test), + _ => None, + } + } + } + + #[derive(codec::Encode, codec::Decode, Clone, PartialEq, Eq, Debug, serde::Serialize)] + enum CallTest { + Something, + SomethingElse, + } + + #[derive(codec::Encode, codec::Decode, Clone, PartialEq, Eq, Debug, serde::Serialize)] + enum CallTest2 { + Something, + } + + struct ModuleTest; + impl ProvideInherent for ModuleTest { + type Call = CallTest; + type Error = sp_inherents::MakeFatalError<()>; + const INHERENT_IDENTIFIER: sp_inherents::InherentIdentifier = *b"test1235"; + + fn create_inherent(_: &InherentData) -> Option { + Some(CallTest::Something) + } + + fn check_inherent(call: &Self::Call, _: &InherentData) -> Result<(), Self::Error> { + match call { + CallTest::Something => Ok(()), + CallTest::SomethingElse => Err(().into()), + } + } + } + + struct ModuleTest2; + impl ProvideInherent for ModuleTest2 { + type Call = CallTest2; + type Error = sp_inherents::MakeFatalError<()>; + const INHERENT_IDENTIFIER: sp_inherents::InherentIdentifier = *b"test1234"; + + fn create_inherent(_: &InherentData) -> Option { + Some(CallTest2::Something) + } + } + + type Block = testing::Block; + + #[derive(codec::Encode, codec::Decode, Clone, PartialEq, Eq, Debug, serde::Serialize)] + struct Extrinsic { + function: Call, + } + + impl traits::Extrinsic for Extrinsic { + type Call = Call; + type SignaturePayload = (); + + fn new(function: Call, _: Option<()>) -> Option { + Some(Self { function }) + } + } + + parity_util_mem::malloc_size_of_is_0!(Extrinsic); + + impl_outer_inherent! { + impl Inherents where Block = Block, UncheckedExtrinsic = Extrinsic { + ModuleTest, + ModuleTest2, + } + } + + #[test] + fn create_inherents_works() { + let inherents = InherentData::new().create_extrinsics(); + + let expected = vec![ + Extrinsic { function: Call::Test(CallTest::Something) }, + Extrinsic { function: Call::Test2(CallTest2::Something) }, + ]; + assert_eq!(expected, inherents); + } + + #[test] + fn check_inherents_works() { + let block = Block::new( + Header::new_from_number(1), + vec![Extrinsic { function: Call::Test(CallTest::Something) }], + ); + + assert!(InherentData::new().check_extrinsics(&block).ok()); + + let block = Block::new( + Header::new_from_number(1), + vec![Extrinsic { function: Call::Test(CallTest::SomethingElse) }], + ); + + assert!(InherentData::new().check_extrinsics(&block).fatal_error()); + } +} diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index 81438ea1bdeb5d0d733bd15a18f45db6d3c1cc75..06a8ce856dd6431a70b447d67a056fa818a26cd0 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Support code for the runtime. @@ -23,11 +24,13 @@ extern crate self as frame_support; #[macro_use] extern crate bitmask; -#[cfg(feature = "std")] -pub extern crate tracing; + +#[doc(hidden)] +pub use sp_tracing; #[cfg(feature = "std")] pub use serde; +pub use sp_core::Void; #[doc(hidden)] pub use sp_std; #[doc(hidden)] @@ -41,21 +44,21 @@ pub use paste; #[doc(hidden)] pub use sp_state_machine::BasicExternalities; #[doc(hidden)] -pub use sp_io::storage::root as storage_root; +pub use sp_io::{storage::root as storage_root, self}; #[doc(hidden)] pub use sp_runtime::RuntimeDebug; #[macro_use] pub mod debug; #[macro_use] +mod origin; +#[macro_use] pub mod dispatch; pub mod storage; mod hash; #[macro_use] pub mod event; #[macro_use] -mod origin; -#[macro_use] pub mod metadata; #[macro_use] pub mod inherent; @@ -68,7 +71,7 @@ pub mod weights; pub use self::hash::{ Twox256, Twox128, Blake2_256, Blake2_128, Identity, Twox64Concat, Blake2_128Concat, Hashable, - StorageHasher + StorageHasher, ReversibleStorageHasher }; pub use self::storage::{ StorageValue, StorageMap, StorageDoubleMap, StoragePrefixedMap, IterableStorageMap, @@ -77,21 +80,70 @@ pub use self::storage::{ pub use self::dispatch::{Parameter, Callable, IsSubType}; pub use sp_runtime::{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`: +/// A type that cannot be instantiated. +#[derive(Debug)] +pub enum Never {} + +/// Create new implementations of the [`Get`](crate::traits::Get) trait. +/// +/// The so-called parameter type can be created in three different ways: +/// +/// - Using `const` to create a parameter type that provides a `const` getter. +/// It is required that the `value` is const. +/// +/// - Declare the parameter type without `const` to have more freedom when creating the value. /// -/// ```no_compile +/// - Using `storage` to create a storage parameter type. This type is special as it tries to +/// load the value from the storage under a fixed key. If the value could not be found in the +/// storage, the given default value will be returned. It is required that the value implements +/// [`Encode`](codec::Encode) and [`Decode`](codec::Decode). The key for looking up the value +/// in the storage is built using the following formular: +/// +/// `twox_128(":" ++ NAME ++ ":")` where `NAME` is the name that is passed as type name. +/// +/// # Examples +/// +/// ``` +/// # use frame_support::traits::Get; +/// # use frame_support::parameter_types; +/// // This function cannot be used in a const context. +/// fn non_const_expression() -> u64 { 99 } +/// +/// const FIXED_VALUE: u64 = 10; /// parameter_types! { -/// pub const Argument: u64 = 42; +/// pub const Argument: u64 = 42 + FIXED_VALUE; +/// /// Visibility of the type is optional +/// OtherArgument: u64 = non_const_expression(); +/// pub storage StorageArgument: u64 = 5; /// } +/// /// trait Config { -/// type Parameter: Get; +/// type Parameter: Get; +/// type OtherParameter: Get; +/// type StorageParameter: Get; /// } +/// /// struct Runtime; /// impl Config for Runtime { -/// type Parameter = Argument; +/// type Parameter = Argument; +/// type OtherParameter = OtherArgument; +/// type StorageParameter = StorageArgument; +/// } +/// ``` +/// +/// # Invalid example: +/// +/// ```compile_fail +/// # use frame_support::traits::Get; +/// # use frame_support::parameter_types; +/// // This function cannot be used in a const context. +/// fn non_const_expression() -> u64 { 99 } +/// +/// parameter_types! { +/// pub const Argument: u64 = non_const_expression(); /// } /// ``` + #[macro_export] macro_rules! parameter_types { ( @@ -101,21 +153,89 @@ macro_rules! parameter_types { ) => ( $( #[ $attr ] )* $vis struct $name; - $crate::parameter_types!{IMPL $name , $type , $value} - $crate::parameter_types!{ $( $rest )* } + $crate::parameter_types!(IMPL_CONST $name , $type , $value); + $crate::parameter_types!( $( $rest )* ); + ); + ( + $( #[ $attr:meta ] )* + $vis:vis $name:ident: $type:ty = $value:expr; + $( $rest:tt )* + ) => ( + $( #[ $attr ] )* + $vis struct $name; + $crate::parameter_types!(IMPL $name, $type, $value); + $crate::parameter_types!( $( $rest )* ); + ); + ( + $( #[ $attr:meta ] )* + $vis:vis storage $name:ident: $type:ty = $value:expr; + $( $rest:tt )* + ) => ( + $( #[ $attr ] )* + $vis struct $name; + $crate::parameter_types!(IMPL_STORAGE $name, $type, $value); + $crate::parameter_types!( $( $rest )* ); ); () => (); - (IMPL $name:ident , $type:ty , $value:expr) => { + (IMPL_CONST $name:ident, $type:ty, $value:expr) => { + impl $name { + /// Returns the value of this parameter type. + pub const fn get() -> $type { + $value + } + } + + impl> $crate::traits::Get for $name { + fn get() -> I { + I::from($value) + } + } + }; + (IMPL $name:ident, $type:ty, $value:expr) => { impl $name { + /// Returns the value of this parameter type. pub fn get() -> $type { $value } } + impl> $crate::traits::Get for $name { fn get() -> I { I::from($value) } } + }; + (IMPL_STORAGE $name:ident, $type:ty, $value:expr) => { + impl $name { + /// Returns the key for this parameter type. + pub fn key() -> [u8; 16] { + $crate::sp_io::hashing::twox_128( + concat!(":", stringify!($name), ":").as_bytes() + ) + } + + /// Set the value of this parameter type in the storage. + /// + /// This needs to be executed in an externalities provided + /// environment. + pub fn set(value: &$type) { + $crate::storage::unhashed::put(&Self::key(), value); + } + + /// Returns the value of this parameter type. + /// + /// This needs to be executed in an externalities provided + /// environment. + pub fn get() -> $type { + $crate::storage::unhashed::get(&Self::key()).unwrap_or_else(|| $value) + } + } + + impl> $crate::traits::Get for $name { + fn get() -> I { + I::from(Self::get()) + } + } } } @@ -140,6 +260,8 @@ macro_rules! ord_parameter_types { fn contains(t: &$type) -> bool { &$value == t } fn sorted_members() -> $crate::sp_std::prelude::Vec<$type> { vec![$value] } fn count() -> usize { 1 } + #[cfg(feature = "runtime-benchmarks")] + fn add(_: &$type) {} } } } @@ -186,10 +308,6 @@ macro_rules! assert_noop { } } -/// Panic if an expression doesn't evaluate to an `Err`. -/// -/// Used as `assert_err!(expression_to_assert, expected_err_expression)`. - /// Assert an expression returns an error specified. /// /// Used as `assert_err!(expression_to_assert, expected_error_expression)` @@ -201,6 +319,32 @@ macro_rules! assert_err { } } +/// Assert an expression returns an error specified. +/// +/// This can be used on`DispatchResultWithPostInfo` when the post info should +/// be ignored. +#[macro_export] +#[cfg(feature = "std")] +macro_rules! assert_err_ignore_postinfo { + ( $x:expr , $y:expr $(,)? ) => { + $crate::assert_err!($x.map(|_| ()).map_err(|e| e.error), $y); + } +} + +/// Assert an expression returns error with the given weight. +#[macro_export] +#[cfg(feature = "std")] +macro_rules! assert_err_with_weight { + ($call:expr, $err:expr, $weight:expr $(,)? ) => { + if let Err(dispatch_err_with_post) = $call { + $crate::assert_err!($call.map(|_| ()).map_err(|e| e.error), $err); + assert_eq!(dispatch_err_with_post.post_info.actual_weight, $weight.into()); + } else { + panic!("expected Err(_), got Ok(_).") + } + } +} + /// Panic if an expression doesn't evaluate to `Ok`. /// /// Used as `assert_ok!(expression_to_assert, expected_ok_expression)`, @@ -220,11 +364,6 @@ macro_rules! assert_ok { } } -/// The void type - it cannot exist. -// Oh rust, you crack me up... -#[derive(Clone, Eq, PartialEq, RuntimeDebug)] -pub enum Void {} - #[cfg(feature = "std")] #[doc(hidden)] pub use serde::{Serialize, Deserialize}; @@ -238,6 +377,7 @@ mod tests { StorageEntryModifier, DefaultByteGetter, StorageHasher, }; use sp_std::marker::PhantomData; + use sp_io::TestExternalities; pub trait Trait { type BlockNumber: Codec + EncodeLike + Default; @@ -264,8 +404,6 @@ mod tests { map hasher(identity) T::BlockNumber => T::BlockNumber; pub GenericData2 get(fn generic_data2): map hasher(blake2_128_concat) 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, hasher(blake2_128_concat) u32 => u64; pub GenericDataDM: @@ -285,7 +423,7 @@ mod tests { type Origin = u32; } - fn new_test_ext() -> sp_io::TestExternalities { + fn new_test_ext() -> TestExternalities { GenesisConfig::default().build_storage().unwrap().into() } @@ -486,8 +624,8 @@ mod tests { let key2 = 18u32; DoubleMap::insert(&key1, &key2, &vec![1]); - DoubleMap::append(&key1, &key2, &[2, 3]).unwrap(); - assert_eq!(DoubleMap::get(&key1, &key2), &[1, 2, 3]); + DoubleMap::append(&key1, &key2, 2); + assert_eq!(DoubleMap::get(&key1, &key2), &[1, 2]); }); } @@ -551,15 +689,6 @@ 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, @@ -629,4 +758,20 @@ mod tests { let metadata = Module::::storage_metadata(); pretty_assertions::assert_eq!(EXPECTED_METADATA, metadata); } + + parameter_types! { + storage StorageParameter: u64 = 10; + } + + #[test] + fn check_storage_parameter_type_works() { + TestExternalities::default().execute_with(|| { + assert_eq!(sp_io::hashing::twox_128(b":StorageParameter:"), StorageParameter::key()); + + assert_eq!(10, StorageParameter::get()); + + StorageParameter::set(&300); + assert_eq!(300, StorageParameter::get()); + }) + } } diff --git a/frame/support/src/metadata.rs b/frame/support/src/metadata.rs index d9c8136d3c442a99a57e74fe6851193818ac0bb5..dca365ff8c9d12916563573026ffcc196e3a7cb9 100644 --- a/frame/support/src/metadata.rs +++ b/frame/support/src/metadata.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. pub use frame_metadata::{ DecodeDifferent, FnEncode, RuntimeMetadata, ModuleMetadata, RuntimeMetadataLastVersion, @@ -256,9 +257,8 @@ mod tests { struct TestExtension; impl sp_runtime::traits::SignedExtension for TestExtension { type AccountId = u32; - type Call = u32; + type Call = (); type AdditionalSigned = u32; - type DispatchInfo = (); type Pre = (); const IDENTIFIER: &'static str = "testextension"; fn additional_signed(&self) -> Result { @@ -270,9 +270,8 @@ mod tests { struct TestExtension2; impl sp_runtime::traits::SignedExtension for TestExtension2 { type AccountId = u32; - type Call = u32; + type Call = (); type AdditionalSigned = u32; - type DispatchInfo = (); type Pre = (); const IDENTIFIER: &'static str = "testextension2"; fn additional_signed(&self) -> Result { @@ -291,6 +290,7 @@ mod tests { use super::*; pub trait Trait: 'static { + type BaseCallFilter; const ASSOCIATED_CONST: u64 = 500; type Origin: Into, Self::Origin>> + From>; @@ -298,6 +298,7 @@ mod tests { type BlockNumber: From + Encode; type SomeValue: Get; type ModuleToIndex: crate::traits::ModuleToIndex; + type Call; } decl_module! { @@ -315,7 +316,7 @@ mod tests { } ); - #[derive(Clone, PartialEq, Eq, Debug)] + #[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)] pub enum RawOrigin { Root, Signed(AccountId), @@ -336,7 +337,6 @@ mod tests { mod event_module { use crate::dispatch::DispatchResult; - use crate::weights::SimpleDispatchInfo; pub trait Trait: super::system::Trait { type Balance; @@ -354,7 +354,7 @@ mod tests { pub struct Module for enum Call where origin: T::Origin { type Error = Error; - #[weight = SimpleDispatchInfo::default()] + #[weight = 0] fn aux_0(_origin) -> DispatchResult { unreachable!() } } } @@ -438,11 +438,13 @@ mod tests { } impl system::Trait for TestRuntime { + type BaseCallFilter = (); type Origin = Origin; type AccountId = u32; type BlockNumber = u32; type SomeValue = SystemValue; type ModuleToIndex = (); + type Call = Call; } impl_runtime_metadata!( diff --git a/frame/support/src/origin.rs b/frame/support/src/origin.rs index 43d2e70953af90b401c8b041d1cf76e35b9ba55c..ba9af6c98243abd22d75c7f165481d9ee3126640 100644 --- a/frame/support/src/origin.rs +++ b/frame/support/src/origin.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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. +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Macros that define an Origin type. Every function call to your runtime has an origin which //! specifies where the extrinsic was generated from. @@ -44,19 +45,23 @@ macro_rules! impl_outer_origin { $( $rest_with_system:tt )* } ) => { - $crate::impl_outer_origin!( - $( #[$attr] )*; - $name; - $runtime; - $system; - Modules { $( $rest_with_system )* }; - ); + $crate::paste::item! { + $crate::impl_outer_origin!( + $( #[$attr] )*; + $name; + [< $name Caller >]; + $runtime; + $system; + Modules { $( $rest_with_system )* }; + ); + } }; // Generic + Instance ( $(#[$attr:meta])*; $name:ident; + $caller_name:ident; $runtime:ident; $system:ident; Modules { @@ -68,6 +73,7 @@ macro_rules! impl_outer_origin { $crate::impl_outer_origin!( $( #[$attr] )*; $name; + $caller_name; $runtime; $system; Modules { $( $( $rest_module )* )? }; @@ -79,6 +85,7 @@ macro_rules! impl_outer_origin { ( $(#[$attr:meta])*; $name:ident; + $caller_name:ident; $runtime:ident; $system:ident; Modules { @@ -90,6 +97,7 @@ macro_rules! impl_outer_origin { $crate::impl_outer_origin!( $( #[$attr] )*; $name; + $caller_name; $runtime; $system; Modules { $( $rest_module )* }; @@ -101,6 +109,7 @@ macro_rules! impl_outer_origin { ( $(#[$attr:meta])*; $name:ident; + $caller_name:ident; $runtime:ident; $system:ident; Modules { @@ -112,6 +121,7 @@ macro_rules! impl_outer_origin { $crate::impl_outer_origin!( $( #[$attr] )*; $name; + $caller_name; $runtime; $system; Modules { $( $( $rest_module )* )? }; @@ -123,6 +133,7 @@ macro_rules! impl_outer_origin { ( $(#[$attr:meta])*; $name:ident; + $caller_name:ident; $runtime:ident; $system:ident; Modules { @@ -134,6 +145,7 @@ macro_rules! impl_outer_origin { $crate::impl_outer_origin!( $( #[$attr] )*; $name; + $caller_name; $runtime; $system; Modules { $( $( $rest_module )* )? }; @@ -145,16 +157,82 @@ macro_rules! impl_outer_origin { ( $(#[$attr:meta])*; $name:ident; + $caller_name:ident; $runtime:ident; $system:ident; Modules { }; $( $module:ident $( < $generic:ident > )? $( { $generic_instance:ident } )? ,)* ) => { + // WARNING: All instance must hold the filter `frame_system::Trait::BaseCallFilter`, except + // when caller is system Root. One can use `OriginTrait::reset_filter` to do so. + #[derive(Clone)] + pub struct $name { + caller: $caller_name, + filter: $crate::sp_std::rc::Rc::Call) -> bool>>, + } + + #[cfg(not(feature = "std"))] + impl $crate::sp_std::fmt::Debug for $name { + fn fmt( + &self, + fmt: &mut $crate::sp_std::fmt::Formatter + ) -> $crate::sp_std::result::Result<(), $crate::sp_std::fmt::Error> { + fmt.write_str("") + } + } + + #[cfg(feature = "std")] + impl $crate::sp_std::fmt::Debug for $name { + fn fmt( + &self, + fmt: &mut $crate::sp_std::fmt::Formatter + ) -> $crate::sp_std::result::Result<(), $crate::sp_std::fmt::Error> { + fmt.debug_struct(stringify!($name)) + .field("caller", &self.caller) + .field("filter", &"[function ptr]") + .finish() + } + } + + impl $crate::traits::OriginTrait for $name { + type Call = <$runtime as $system::Trait>::Call; + type PalletsOrigin = $caller_name; + + fn add_filter(&mut self, filter: impl Fn(&Self::Call) -> bool + 'static) { + let f = self.filter.clone(); + + self.filter = $crate::sp_std::rc::Rc::new(Box::new(move |call| { + f(call) && filter(call) + })); + } + + fn reset_filter(&mut self) { + let filter = < + <$runtime as $system::Trait>::BaseCallFilter + as $crate::traits::Filter<<$runtime as $system::Trait>::Call> + >::filter; + + self.filter = $crate::sp_std::rc::Rc::new(Box::new(filter)); + } + + fn set_caller_from(&mut self, other: impl Into) { + self.caller = other.into().caller + } + + fn filter_call(&self, call: &Self::Call) -> bool { + (self.filter)(call) + } + + fn caller(&self) -> &Self::PalletsOrigin { + &self.caller + } + } + $crate::paste::item! { - #[derive(Clone, PartialEq, Eq, $crate::RuntimeDebug)] + #[derive(Clone, PartialEq, Eq, $crate::RuntimeDebug, $crate::codec::Encode, $crate::codec::Decode)] $(#[$attr])* #[allow(non_camel_case_types)] - pub enum $name { + pub enum $caller_name { system($system::Origin<$runtime>), $( [< $module $( _ $generic_instance )? >] @@ -167,20 +245,55 @@ macro_rules! impl_outer_origin { #[allow(dead_code)] impl $name { - pub const NONE: Self = $name::system($system::RawOrigin::None); - pub const ROOT: Self = $name::system($system::RawOrigin::Root); + /// Create with system none origin and `frame-system::Trait::BaseCallFilter`. + pub fn none() -> Self { + $system::RawOrigin::None.into() + } + /// Create with system root origin and no filter. + pub fn root() -> Self { + $system::RawOrigin::Root.into() + } + /// Create with system signed origin and `frame-system::Trait::BaseCallFilter`. pub fn signed(by: <$runtime as $system::Trait>::AccountId) -> Self { - $name::system($system::RawOrigin::Signed(by)) + $system::RawOrigin::Signed(by).into() + } + } + + impl From<$system::Origin<$runtime>> for $caller_name { + fn from(x: $system::Origin<$runtime>) -> Self { + $caller_name::system(x) } } impl From<$system::Origin<$runtime>> for $name { + /// Convert to runtime origin: + /// * root origin is built with no filter + /// * others use `frame-system::Trait::BaseCallFilter` fn from(x: $system::Origin<$runtime>) -> Self { - $name::system(x) + let o: $caller_name = x.into(); + o.into() } } + + impl From<$caller_name> for $name { + fn from(x: $caller_name) -> Self { + let mut o = $name { + caller: x, + filter: $crate::sp_std::rc::Rc::new(Box::new(|_| true)), + }; + + // Root has no filter + if !matches!(o.caller, $caller_name::system($system::Origin::<$runtime>::Root)) { + $crate::traits::OriginTrait::reset_filter(&mut o); + } + + o + } + } + impl Into<$crate::sp_std::result::Result<$system::Origin<$runtime>, $name>> for $name { + /// NOTE: converting to pallet origin loses the origin filter information. fn into(self) -> $crate::sp_std::result::Result<$system::Origin<$runtime>, Self> { - if let $name::system(l) = self { + if let $caller_name::system(l) = self.caller { Ok(l) } else { Err(self) @@ -188,15 +301,26 @@ macro_rules! impl_outer_origin { } } impl From::AccountId>> for $name { + /// Convert to runtime origin with caller being system signed or none and use filter + /// `frame-system::Trait::BaseCallFilter`. fn from(x: Option<<$runtime as $system::Trait>::AccountId>) -> Self { <$system::Origin<$runtime>>::from(x).into() } } + $( $crate::paste::item! { + impl From<$module::Origin < $( $generic )? $(, $module::$generic_instance )? > > for $caller_name { + fn from(x: $module::Origin < $( $generic )? $(, $module::$generic_instance )? >) -> Self { + $caller_name::[< $module $( _ $generic_instance )? >](x) + } + } + impl From<$module::Origin < $( $generic )? $(, $module::$generic_instance )? > > for $name { + /// Convert to runtime origin using `frame-system::Trait::BaseCallFilter`. fn from(x: $module::Origin < $( $generic )? $(, $module::$generic_instance )? >) -> Self { - $name::[< $module $( _ $generic_instance )? >](x) + let x: $caller_name = x.into(); + x.into() } } impl Into< @@ -205,11 +329,12 @@ macro_rules! impl_outer_origin { $name, >> for $name { + /// NOTE: converting to pallet origin loses the origin filter information. fn into(self) -> $crate::sp_std::result::Result< $module::Origin < $( $generic )? $(, $module::$generic_instance )? >, Self, > { - if let $name::[< $module $( _ $generic_instance )? >](l) = self { + if let $caller_name::[< $module $( _ $generic_instance )? >](l) = self.caller { Ok(l) } else { Err(self) @@ -223,12 +348,18 @@ macro_rules! impl_outer_origin { #[cfg(test)] mod tests { + use codec::{Encode, Decode}; + use crate::traits::{Filter, OriginTrait}; mod system { + use super::*; + pub trait Trait { type AccountId; + type Call; + type BaseCallFilter; } - #[derive(Clone, PartialEq, Eq, Debug)] + #[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)] pub enum RawOrigin { Root, Signed(AccountId), @@ -248,22 +379,35 @@ mod tests { } mod origin_without_generic { - #[derive(Clone, PartialEq, Eq, Debug)] + use super::*; + + #[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)] pub struct Origin; } mod origin_with_generic { - #[derive(Clone, PartialEq, Eq, Debug)] + use super::*; + + #[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)] pub struct Origin { t: T } } - #[derive(Clone, PartialEq, Eq, Debug)] + #[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)] pub struct TestRuntime; + pub struct BaseCallFilter; + impl Filter for BaseCallFilter { + fn filter(c: &u32) -> bool { + *c % 2 == 0 + } + } + impl system::Trait for TestRuntime { type AccountId = u32; + type Call = u32; + type BaseCallFilter = BaseCallFilter; } impl_outer_origin!( @@ -297,4 +441,35 @@ mod tests { impl_outer_origin!( pub enum OriginEmpty for TestRuntime where system = system {} ); + + #[test] + fn test_default_filter() { + assert_eq!(OriginWithSystem::root().filter_call(&0), true); + assert_eq!(OriginWithSystem::root().filter_call(&1), true); + assert_eq!(OriginWithSystem::none().filter_call(&0), true); + assert_eq!(OriginWithSystem::none().filter_call(&1), false); + assert_eq!(OriginWithSystem::signed(0).filter_call(&0), true); + assert_eq!(OriginWithSystem::signed(0).filter_call(&1), false); + assert_eq!(OriginWithSystem::from(Some(0)).filter_call(&0), true); + assert_eq!(OriginWithSystem::from(Some(0)).filter_call(&1), false); + assert_eq!(OriginWithSystem::from(None).filter_call(&0), true); + assert_eq!(OriginWithSystem::from(None).filter_call(&1), false); + assert_eq!(OriginWithSystem::from(origin_without_generic::Origin).filter_call(&0), true); + assert_eq!(OriginWithSystem::from(origin_without_generic::Origin).filter_call(&1), false); + + let mut origin = OriginWithSystem::from(Some(0)); + + origin.add_filter(|c| *c % 2 == 1); + assert_eq!(origin.filter_call(&0), false); + assert_eq!(origin.filter_call(&1), false); + + origin.set_caller_from(OriginWithSystem::root()); + assert!(matches!(origin.caller, OriginWithSystemCaller::system(system::RawOrigin::Root))); + assert_eq!(origin.filter_call(&0), false); + assert_eq!(origin.filter_call(&1), false); + + origin.reset_filter(); + assert_eq!(origin.filter_call(&0), true); + assert_eq!(origin.filter_call(&1), false); + } } diff --git a/frame/support/src/storage/child.rs b/frame/support/src/storage/child.rs index d4d046a9d4245837702917e4cb5214d5af858d26..431b5e09303844db6bf212e325e251b22708c642 100644 --- a/frame/support/src/storage/child.rs +++ b/frame/support/src/storage/child.rs @@ -1,115 +1,106 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! 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)). -//! -//! A **key collision free** unique id is required as parameter to avoid key collision -//! between child tries. -//! This unique id management and generation responsibility is delegated to pallet module. -// 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 `child_info`. +// NOTE: could replace unhashed by having only one kind of storage (top trie being the child info +// of null length parent storage key). use crate::sp_std::prelude::*; use codec::{Codec, Encode, Decode}; -pub use sp_core::storage::ChildInfo; +pub use sp_core::storage::{ChildInfo, ChildType}; /// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. pub fn get( - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) -> Option { - let (data, child_type) = child_info.info(); - sp_io::storage::child_get( - storage_key, - data, - child_type, - key, - ).and_then(|v| { - Decode::decode(&mut &v[..]).map(Some).unwrap_or_else(|_| { - // TODO #3700: error should be handleable. - runtime_print!("ERROR: Corrupted state in child trie at {:?}/{:?}", storage_key, key); - None - }) - }) + match child_info.child_type() { + ChildType::ParentKeyId => { + let storage_key = child_info.storage_key(); + sp_io::default_child_storage::get( + storage_key, + key, + ).and_then(|v| { + Decode::decode(&mut &v[..]).map(Some).unwrap_or_else(|_| { + // TODO #3700: error should be handleable. + runtime_print!("ERROR: Corrupted state in child trie at {:?}/{:?}", storage_key, key); + None + }) + }) + }, + } } /// 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], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) -> T { - get(storage_key, child_info, key).unwrap_or_else(Default::default) + get(child_info, 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], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], default_value: T, ) -> T { - get(storage_key, child_info, key).unwrap_or(default_value) + get(child_info, 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], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], default_value: F, ) -> T { - get(storage_key, child_info, key).unwrap_or_else(default_value) + get(child_info, key).unwrap_or_else(default_value) } /// Put `value` in storage under `key`. pub fn put( - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], value: &T, ) { - let (data, child_type) = child_info.info(); - value.using_encoded(|slice| - sp_io::storage::child_set( - storage_key, - data, - child_type, - key, - slice, - ) - ); + match child_info.child_type() { + ChildType::ParentKeyId => value.using_encoded(|slice| + sp_io::default_child_storage::set( + child_info.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], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) -> Option { - let r = get(storage_key, child_info, key); + let r = get(child_info, key); if r.is_some() { - kill(storage_key, child_info, key); + kill(child_info, key); } r } @@ -117,113 +108,106 @@ pub fn take( /// 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], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) -> T { - take(storage_key, child_info, key).unwrap_or_else(Default::default) + take(child_info, 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], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], default_value: T, ) -> T { - take(storage_key, child_info, key).unwrap_or(default_value) + take(child_info, 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], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], default_value: F, ) -> T { - take(storage_key, child_info, key).unwrap_or_else(default_value) + take(child_info, key).unwrap_or_else(default_value) } /// Check to see if `key` has an explicit entry in storage. pub fn exists( - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) -> bool { - let (data, child_type) = child_info.info(); - sp_io::storage::child_read( - storage_key, data, child_type, - key, &mut [0;0][..], 0, - ).is_some() + match child_info.child_type() { + ChildType::ParentKeyId => sp_io::default_child_storage::read( + child_info.storage_key(), + key, &mut [0;0][..], 0, + ).is_some(), + } } /// Remove all `storage_key` key/values pub fn kill_storage( - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, ) { - let (data, child_type) = child_info.info(); - sp_io::storage::child_storage_kill( - storage_key, - data, - child_type, - ) + match child_info.child_type() { + ChildType::ParentKeyId => sp_io::default_child_storage::storage_kill( + child_info.storage_key(), + ), + } } /// Ensure `key` has no explicit entry in storage. pub fn kill( - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) { - let (data, child_type) = child_info.info(); - sp_io::storage::child_clear( - storage_key, - data, - child_type, - key, - ); + match child_info.child_type() { + ChildType::ParentKeyId => { + sp_io::default_child_storage::clear( + child_info.storage_key(), + key, + ); + }, + } } /// Get a Vec of bytes from storage. pub fn get_raw( - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) -> Option> { - let (data, child_type) = child_info.info(); - sp_io::storage::child_get( - storage_key, - data, - child_type, - key, - ) + match child_info.child_type() { + ChildType::ParentKeyId => sp_io::default_child_storage::get( + child_info.storage_key(), + key, + ), + } } /// Put a raw byte slice into storage. pub fn put_raw( - storage_key: &[u8], - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], value: &[u8], ) { - let (data, child_type) = child_info.info(); - sp_io::storage::child_set( - storage_key, - data, - child_type, - key, - value, - ) + match child_info.child_type() { + ChildType::ParentKeyId => sp_io::default_child_storage::set( + child_info.storage_key(), + key, + value, + ), + } } /// Calculate current child root value. -pub fn child_root( - storage_key: &[u8], +pub fn root( + child_info: &ChildInfo, ) -> Vec { - sp_io::storage::child_root( - storage_key, - ) + match child_info.child_type() { + ChildType::ParentKeyId => sp_io::default_child_storage::root( + child_info.storage_key(), + ), + } } diff --git a/frame/support/src/storage/generator/double_map.rs b/frame/support/src/storage/generator/double_map.rs index 9d05ff0b2d6d94ac1db87a730fc39015720b9938..ff83aaf8ec8297f6dc77af8bfb1b4cc2870996c4 100644 --- a/frame/support/src/storage/generator/double_map.rs +++ b/frame/support/src/storage/generator/double_map.rs @@ -1,23 +1,24 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use sp_std::prelude::*; use sp_std::borrow::Borrow; -use codec::{Ref, FullCodec, FullEncode, Decode, Encode, EncodeLike, EncodeAppend}; -use crate::{storage::{self, unhashed}, traits::Len}; +use codec::{FullCodec, FullEncode, Decode, Encode, EncodeLike}; +use crate::{storage::{self, unhashed, StorageAppend}, Never}; use crate::hash::{StorageHasher, Twox128, ReversibleStorageHasher}; /// Generator for `StorageDoubleMap` used by `decl_storage`. @@ -208,7 +209,7 @@ impl storage::StorageDoubleMap for G where unhashed::kill_prefix(Self::storage_double_map_final_key1(k1).as_ref()) } - fn iter_prefix(k1: KArg1) -> storage::PrefixIterator where + fn iter_prefix_values(k1: KArg1) -> storage::PrefixIterator where KArg1: ?Sized + EncodeLike { let prefix = Self::storage_double_map_final_key1(k1); @@ -224,81 +225,40 @@ impl storage::StorageDoubleMap for G where 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 + Self::try_mutate(k1, k2, |v| Ok::(f(v))).expect("`Never` can not be constructed; qed") } - fn append( - k1: KArg1, - k2: KArg2, - items: Items, - ) -> Result<(), &'static str> where + fn try_mutate(k1: KArg1, k2: KArg2, f: F) -> Result where KArg1: EncodeLike, KArg2: EncodeLike, - Item: Encode, - EncodeLikeItem: EncodeLike, - V: EncodeAppend, - Items: IntoIterator, - Items::IntoIter: ExactSizeIterator + F: FnOnce(&mut Self::Query) -> Result, { 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 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::new(), - } - }); - - 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(()) + let ret = f(&mut val); + if ret.is_ok() { + 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_or_insert( + fn append( k1: KArg1, k2: KArg2, - items: Items, + item: EncodeLikeItem, ) where KArg1: EncodeLike, KArg2: EncodeLike, Item: Encode, EncodeLikeItem: EncodeLike, - V: EncodeAppend, - Items: IntoIterator + Clone + EncodeLike, - Items::IntoIter: ExactSizeIterator + V: StorageAppend, { - Self::append(Ref::from(&k1), Ref::from(&k2), items.clone()) - .unwrap_or_else(|_| Self::insert(k1, k2, items)); - } - - fn decode_len(key1: KArg1, key2: KArg2) -> Result where - KArg1: EncodeLike, - KArg2: EncodeLike, - V: codec::DecodeLength + Len, - { - let final_key = Self::storage_double_map_final_key(key1, key2); - if let Some(v) = unhashed::get_raw(&final_key) { - ::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) - } + let final_key = Self::storage_double_map_final_key(k1, k2); + sp_io::storage::append(&final_key, item.encode()); } fn migrate_keys< @@ -334,41 +294,47 @@ impl storage::StorageDoubleMap for G where } } -/// Utility to iterate through items in a storage map. -pub struct MapIterator { +/// Iterate over a prefix and decode raw_key and raw_value into `T`. +pub struct MapIterator { prefix: Vec, previous_key: Vec, + /// If true then value are removed while iterating drain: bool, - _phantom: ::sp_std::marker::PhantomData<(K, V, Hasher)>, + /// Function that take `(raw_key_without_prefix, raw_value)` and decode `T`. + /// `raw_key_without_prefix` is the raw storage key without the prefix iterated on. + closure: fn(&[u8], &[u8]) -> Result, } -impl< - K: Decode + Sized, - V: Decode + Sized, - Hasher: ReversibleStorageHasher -> Iterator for MapIterator { - type Item = (K, V); +impl Iterator for MapIterator { + type Item = T; - fn next(&mut self) -> Option<(K, V)> { + fn next(&mut self) -> Option { loop { let maybe_next = sp_io::storage::next_key(&self.previous_key) .filter(|n| n.starts_with(&self.prefix)); break match maybe_next { Some(next) => { self.previous_key = next; - match unhashed::get::(&self.previous_key) { - Some(value) => { - if self.drain { - unhashed::kill(&self.previous_key) - } - let mut key_material = Hasher::reverse(&self.previous_key[self.prefix.len()..]); - match K::decode(&mut key_material) { - Ok(key) => Some((key, value)), - Err(_) => continue, - } + let raw_value = match unhashed::get_raw(&self.previous_key) { + Some(raw_value) => raw_value, + None => { + frame_support::print("ERROR: next_key returned a key with no value in MapIterator"); + continue } - None => continue, + }; + if self.drain { + unhashed::kill(&self.previous_key) } + let raw_key_without_prefix = &self.previous_key[self.prefix.len()..]; + let item = match (self.closure)(raw_key_without_prefix, &raw_value[..]) { + Ok(item) => item, + Err(_e) => { + frame_support::print("ERROR: (key, value) failed to decode in MapIterator"); + continue + } + }; + + Some(item) } None => None, } @@ -385,30 +351,50 @@ impl< G::Hasher1: ReversibleStorageHasher, G::Hasher2: ReversibleStorageHasher { - type Iterator = MapIterator; + type PrefixIterator = MapIterator<(K2, V)>; + type Iterator = MapIterator<(K1, K2, V)>; - /// Enumerate all elements in the map. - fn iter(k1: impl EncodeLike) -> Self::Iterator { + fn iter_prefix(k1: impl EncodeLike) -> Self::PrefixIterator { let prefix = G::storage_double_map_final_key1(k1); - Self::Iterator { + Self::PrefixIterator { prefix: prefix.clone(), previous_key: prefix, drain: false, - _phantom: Default::default(), + closure: |raw_key_without_prefix, mut raw_value| { + let mut key_material = G::Hasher2::reverse(raw_key_without_prefix); + Ok((K2::decode(&mut key_material)?, V::decode(&mut raw_value)?)) + }, } } - /// Enumerate all elements in the map. - fn drain(k1: impl EncodeLike) -> Self::Iterator { - let prefix = G::storage_double_map_final_key1(k1); + fn drain_prefix(k1: impl EncodeLike) -> Self::PrefixIterator { + let mut iterator = Self::iter_prefix(k1); + iterator.drain = true; + iterator + } + + fn iter() -> Self::Iterator { + let prefix = G::prefix_hash(); Self::Iterator { prefix: prefix.clone(), previous_key: prefix, - drain: true, - _phantom: Default::default(), + drain: false, + closure: |raw_key_without_prefix, mut raw_value| { + let mut k1_k2_material = G::Hasher1::reverse(raw_key_without_prefix); + let k1 = K1::decode(&mut k1_k2_material)?; + let mut k2_material = G::Hasher2::reverse(k1_k2_material); + let k2 = K2::decode(&mut k2_material)?; + Ok((k1, k2, V::decode(&mut raw_value)?)) + }, } } + fn drain() -> Self::Iterator { + let mut iterator = Self::iter(); + iterator.drain = true; + iterator + } + fn translate Option>(f: F) { let prefix = G::prefix_hash(); let mut previous_key = prefix.clone(); @@ -431,33 +417,111 @@ impl< } } +/// Test iterators for StorageDoubleMap #[cfg(test)] -mod test { - use sp_io::TestExternalities; - use crate::storage::{self, StorageDoubleMap}; - use crate::hash::Twox128; +#[allow(dead_code)] +mod test_iterators { + use codec::{Encode, Decode}; + use crate::storage::{generator::StorageDoubleMap, IterableStorageDoubleMap, unhashed}; + + pub trait Trait { + type Origin; + type BlockNumber; + } + + crate::decl_module! { + pub struct Module for enum Call where origin: T::Origin {} + } + + #[derive(PartialEq, Eq, Clone, Encode, Decode)] + struct NoDef(u32); + + crate::decl_storage! { + trait Store for Module as Test { + DoubleMap: double_map hasher(blake2_128_concat) u16, hasher(blake2_128_concat) u32 => u64; + } + } + + fn key_before_prefix(mut prefix: Vec) -> Vec { + let last = prefix.iter_mut().last().unwrap(); + assert!(*last != 0, "mock function not implemented for this prefix"); + *last -= 1; + prefix + } + + fn key_after_prefix(mut prefix: Vec) -> Vec { + let last = prefix.iter_mut().last().unwrap(); + assert!(*last != 255, "mock function not implemented for this prefix"); + *last += 1; + prefix + } + + fn key_in_prefix(mut prefix: Vec) -> Vec { + prefix.push(0); + prefix + } #[test] - fn iter_prefix_works() { - TestExternalities::default().execute_with(|| { - struct MyStorage; - impl storage::generator::StorageDoubleMap for MyStorage { - type Query = Option; - fn module_prefix() -> &'static [u8] { b"MyModule" } - fn storage_prefix() -> &'static [u8] { b"MyStorage" } - type Hasher1 = Twox128; - type Hasher2 = Twox128; - fn from_optional_value_to_query(v: Option) -> Self::Query { v } - fn from_query_to_optional_value(v: Self::Query) -> Option { v } + fn double_map_reversible_reversible_iteration() { + sp_io::TestExternalities::default().execute_with(|| { + // All map iterator + let prefix = DoubleMap::prefix_hash(); + + unhashed::put(&key_before_prefix(prefix.clone()), &1u64); + unhashed::put(&key_after_prefix(prefix.clone()), &1u64); + + for i in 0..4 { + DoubleMap::insert(i as u16, i as u32, i as u64); + } + + assert_eq!( + DoubleMap::iter().collect::>(), + vec![(3, 3, 3), (0, 0, 0), (2, 2, 2), (1, 1, 1)], + ); + + assert_eq!( + DoubleMap::iter_values().collect::>(), + vec![3, 0, 2, 1], + ); + + assert_eq!( + DoubleMap::drain().collect::>(), + vec![(3, 3, 3), (0, 0, 0), (2, 2, 2), (1, 1, 1)], + ); + + assert_eq!(DoubleMap::iter().collect::>(), vec![]); + assert_eq!(unhashed::get(&key_before_prefix(prefix.clone())), Some(1u64)); + assert_eq!(unhashed::get(&key_after_prefix(prefix.clone())), Some(1u64)); + + // Prefix iterator + let k1 = 3 << 8; + let prefix = DoubleMap::storage_double_map_final_key1(k1); + + unhashed::put(&key_before_prefix(prefix.clone()), &1u64); + unhashed::put(&key_after_prefix(prefix.clone()), &1u64); + + for i in 0..4 { + DoubleMap::insert(k1, i as u32, i as u64); } - MyStorage::insert(1, 3, 7); - MyStorage::insert(1, 4, 8); - MyStorage::insert(2, 5, 9); - MyStorage::insert(2, 6, 10); + assert_eq!( + DoubleMap::iter_prefix(k1).collect::>(), + vec![(0, 0), (2, 2), (1, 1), (3, 3)], + ); - assert_eq!(MyStorage::iter_prefix(1).collect::>(), vec![7, 8]); - assert_eq!(MyStorage::iter_prefix(2).collect::>(), vec![10, 9]); - }); + assert_eq!( + DoubleMap::iter_prefix_values(k1).collect::>(), + vec![0, 2, 1, 3], + ); + + assert_eq!( + DoubleMap::drain_prefix(k1).collect::>(), + vec![(0, 0), (2, 2), (1, 1), (3, 3)], + ); + + assert_eq!(DoubleMap::iter_prefix(k1).collect::>(), vec![]); + assert_eq!(unhashed::get(&key_before_prefix(prefix.clone())), Some(1u64)); + assert_eq!(unhashed::get(&key_after_prefix(prefix.clone())), Some(1u64)); + }) } } diff --git a/frame/support/src/storage/generator/map.rs b/frame/support/src/storage/generator/map.rs index c29a9a223aacf578d162864ef9a119aa015e78bc..fe932b797940b8ac8e8d08b74d1f96d984a7e0a6 100644 --- a/frame/support/src/storage/generator/map.rs +++ b/frame/support/src/storage/generator/map.rs @@ -1,25 +1,28 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #[cfg(not(feature = "std"))] use sp_std::prelude::*; use sp_std::borrow::Borrow; -use codec::{FullCodec, FullEncode, Decode, Encode, EncodeLike, Ref, EncodeAppend}; -use crate::{storage::{self, unhashed}, traits::Len}; -use crate::hash::{StorageHasher, Twox128, ReversibleStorageHasher}; +use codec::{FullCodec, FullEncode, Decode, Encode, EncodeLike}; +use crate::{ + storage::{self, unhashed, StorageAppend}, + Never, hash::{StorageHasher, Twox128, ReversibleStorageHasher}, +}; /// Generator for `StorageMap` used by `decl_storage`. /// @@ -229,27 +232,11 @@ impl> storage::StorageMap } 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), - None => unhashed::kill(final_key.as_ref()), - } - ret + Self::try_mutate(key, |v| Ok::(f(v))).expect("`Never` can not be constructed; qed") } fn mutate_exists, R, F: FnOnce(&mut Option) -> R>(key: KeyArg, f: F) -> R { - let final_key = Self::storage_map_final_key(key); - let mut val = unhashed::get(final_key.as_ref()); - - let ret = f(&mut val); - match val { - Some(ref val) => unhashed::put(final_key.as_ref(), &val), - None => unhashed::kill(final_key.as_ref()), - } - ret + Self::try_mutate_exists(key, |v| Ok::(f(v))).expect("`Never` can not be constructed; qed") } fn try_mutate, R, E, F: FnOnce(&mut Self::Query) -> Result>( @@ -292,58 +279,15 @@ impl> storage::StorageMap 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::new(), - } - }); - - 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) + fn append(key: EncodeLikeKey, item: EncodeLikeItem) where - KeyArg: EncodeLike, + EncodeLikeKey: 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 + V: StorageAppend, { 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) - } + sp_io::storage::append(&key, item.encode()); } fn migrate_key>(key: KeyArg) -> Option { diff --git a/frame/support/src/storage/generator/mod.rs b/frame/support/src/storage/generator/mod.rs index 687d8a3c9361ba1ca217ee22947a349ae9095955..7df7dfd31739918562367edcfe97d8572414df7c 100644 --- a/frame/support/src/storage/generator/mod.rs +++ b/frame/support/src/storage/generator/mod.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Generators are a set of trait on which storage traits are implemented. //! @@ -37,6 +38,7 @@ mod tests { use sp_io::TestExternalities; use codec::Encode; use crate::storage::{unhashed, generator::StorageValue, IterableStorageMap}; + use crate::{assert_noop, assert_ok}; struct Runtime {} pub trait Trait { @@ -57,6 +59,7 @@ mod tests { trait Store for Module as Runtime { Value get(fn value) config(): (u64, u64); NumberMap: map hasher(identity) u32 => u64; + DoubleMap: double_map hasher(identity) u32, hasher(identity) u32 => u64; } } @@ -102,4 +105,54 @@ mod tests { ); }) } + + #[test] + fn try_mutate_works() { + let t = GenesisConfig::default().build_storage().unwrap(); + TestExternalities::new(t).execute_with(|| { + assert_eq!(Value::get(), (0, 0)); + assert_eq!(NumberMap::get(0), 0); + assert_eq!(DoubleMap::get(0, 0), 0); + + // `assert_noop` ensures that the state does not change + assert_noop!(Value::try_mutate(|value| -> Result<(), &'static str> { + *value = (2, 2); + Err("don't change value") + }), "don't change value"); + + assert_noop!(NumberMap::try_mutate(0, |value| -> Result<(), &'static str> { + *value = 4; + Err("don't change value") + }), "don't change value"); + + assert_noop!(DoubleMap::try_mutate(0, 0, |value| -> Result<(), &'static str> { + *value = 6; + Err("don't change value") + }), "don't change value"); + + // Showing this explicitly for clarity + assert_eq!(Value::get(), (0, 0)); + assert_eq!(NumberMap::get(0), 0); + assert_eq!(DoubleMap::get(0, 0), 0); + + assert_ok!(Value::try_mutate(|value| -> Result<(), &'static str> { + *value = (2, 2); + Ok(()) + })); + + assert_ok!(NumberMap::try_mutate(0, |value| -> Result<(), &'static str> { + *value = 4; + Ok(()) + })); + + assert_ok!(DoubleMap::try_mutate(0, 0, |value| -> Result<(), &'static str> { + *value = 6; + Ok(()) + })); + + assert_eq!(Value::get(), (2, 2)); + assert_eq!(NumberMap::get(0), 4); + assert_eq!(DoubleMap::get(0, 0), 6); + }); + } } diff --git a/frame/support/src/storage/generator/value.rs b/frame/support/src/storage/generator/value.rs index 9e26131f48949637be4a8779169e97bddc9396a0..2da3d91718438ffd6cfbf038f1f051992accf3ff 100644 --- a/frame/support/src/storage/generator/value.rs +++ b/frame/support/src/storage/generator/value.rs @@ -1,23 +1,26 @@ -// Copyright 2019-2020 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 sp_std::prelude::*; -use codec::{FullCodec, Encode, EncodeAppend, EncodeLike, Decode}; -use crate::{storage::{self, unhashed}, hash::{Twox128, StorageHasher}, traits::Len}; +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use codec::{FullCodec, Encode, EncodeLike, Decode}; +use crate::{ + Never, + storage::{self, unhashed, StorageAppend}, + hash::{Twox128, StorageHasher}, +}; /// Generator for `StorageValue` used by `decl_storage`. /// @@ -104,12 +107,18 @@ impl> storage::StorageValue for G { } fn mutate R>(f: F) -> R { + Self::try_mutate(|v| Ok::(f(v))).expect("`Never` can not be constructed; qed") + } + + fn try_mutate Result>(f: F) -> Result { 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(), + if ret.is_ok() { + match G::from_query_to_optional_value(val) { + Some(ref val) => G::put(val), + None => G::kill(), + } } ret } @@ -123,67 +132,13 @@ impl> storage::StorageValue for G { 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> + fn append(item: EncodeLikeItem) 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::new(), - } - }); - - 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 + T: StorageAppend, { - 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) - } + sp_io::storage::append(&key, item.encode()); } } diff --git a/frame/support/src/storage/hashed.rs b/frame/support/src/storage/hashed.rs index a3ffddcb841053e341cb19d90044b596341eb492..96a487111a2af171f108d1627bdc9821498fcbe0 100644 --- a/frame/support/src/storage/hashed.rs +++ b/frame/support/src/storage/hashed.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Operation on runtime storage using hashed keys. diff --git a/frame/support/src/storage/migration.rs b/frame/support/src/storage/migration.rs index 8e6beefa8886e702fbd0536bfaa75d86d5f505b9..75f90ba7b06cc2d9a36e7f48e3a9453aeed9923c 100644 --- a/frame/support/src/storage/migration.rs +++ b/frame/support/src/storage/migration.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Some utilities for helping access storage with arbitrary key types. @@ -159,7 +160,7 @@ pub fn get_storage_value(module: &[u8], item: &[u8], hash: &[ frame_support::storage::unhashed::get::(&key) } -/// Get a particular value in storage by the `module`, the map's `item` name and the key `hash`. +/// Take a particular value in storage by the `module`, the map's `item` name and the key `hash`. pub fn take_storage_value(module: &[u8], item: &[u8], hash: &[u8]) -> Option { let mut key = vec![0u8; 32 + hash.len()]; key[0..16].copy_from_slice(&Twox128::hash(module)); diff --git a/frame/support/src/storage/mod.rs b/frame/support/src/storage/mod.rs index efec36b540abcc4ec8ab695e233919eeaf2de5b2..b8b08c5dc028c8436468f1e883441c26ece9dc70 100644 --- a/frame/support/src/storage/mod.rs +++ b/frame/support/src/storage/mod.rs @@ -1,24 +1,27 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Stuff to do with the runtime's storage. use sp_std::{prelude::*, marker::PhantomData}; -use codec::{FullCodec, FullEncode, Encode, EncodeAppend, EncodeLike, Decode}; -use crate::{traits::Len, hash::{Twox128, StorageHasher}}; +use codec::{FullCodec, FullEncode, Encode, EncodeLike, Decode}; +use crate::hash::{Twox128, StorageHasher}; +use sp_runtime::generic::{Digest, DigestItem}; +pub use sp_runtime::TransactionOutcome; pub mod unhashed; pub mod hashed; @@ -27,6 +30,25 @@ pub mod child; pub mod generator; pub mod migration; +/// Execute the supplied function in a new storage transaction. +/// +/// All changes to storage performed by the supplied function are discarded if the returned +/// outcome is `TransactionOutcome::Rollback`. +/// +/// Transactions can be nested to any depth. Commits happen to the parent transaction. +pub fn with_transaction(f: impl FnOnce() -> TransactionOutcome) -> R { + use sp_io::storage::{ + start_transaction, commit_transaction, rollback_transaction, + }; + use TransactionOutcome::*; + + start_transaction(); + match f() { + Commit(res) => { commit_transaction(); res }, + Rollback(res) => { rollback_transaction(); res }, + } +} + /// A trait for working with macro-generated storage values under the substrate storage API. /// /// Details on implementation can be found at @@ -80,6 +102,9 @@ pub trait StorageValue { /// Mutate the value fn mutate R>(f: F) -> R; + /// Mutate the value if closure returns `Ok` + fn try_mutate Result>(f: F) -> Result; + /// Clear the storage value. fn kill(); @@ -88,39 +113,33 @@ pub trait StorageValue { /// Append the given item to the value in the storage. /// - /// `T` is required to implement `codec::EncodeAppend`. - fn append(items: Items) -> Result<(), &'static str> + /// `T` is required to implement [`StorageAppend`]. + /// + /// # Warning + /// + /// If the storage item is not encoded properly, the storage item will be overwritten + /// and set to `[item]`. Any default value set for the storage item will be ignored + /// on overwrite. + fn append(item: EncodeLikeItem) where Item: Encode, EncodeLikeItem: EncodeLike, - T: EncodeAppend, - Items: IntoIterator, - Items::IntoIter: ExactSizeIterator; + T: StorageAppend; - /// Append the given items to the value in the storage. + /// Read the length of the storage value without decoding the entire value. /// - /// `T` is required to implement `Codec::EncodeAppend`. + /// `T` is required to implement [`StorageDecodeLength`]. /// - /// Upon any failure, it replaces `items` as the new value (assuming that the previous stored - /// data is simply corrupt and no longer usable). + /// If the value does not exists or it fails to decode the length, `None` is returned. + /// Otherwise `Some(len)` is returned. /// - /// ### 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; - - - /// Read the length of the value in a fast way, without decoding the entire value. + /// # Warning /// - /// `T` is required to implement `Codec::DecodeLength`. - fn decode_len() -> Result - where T: codec::DecodeLength + Len; + /// `None` does not mean that `get()` does not return a value. The default value is completly + /// ignored by this function. + fn decode_len() -> Option where T: StorageDecodeLength { + T::decode_len(&Self::hashed_key()) + } } /// A strongly-typed map in storage. @@ -173,35 +192,36 @@ pub trait StorageMap { /// 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, + /// # Warning + /// + /// If the storage item is not encoded properly, the storage will be overwritten + /// and set to `[item]`. Any default value set for the storage item will be ignored + /// on overwrite. + fn append(key: EncodeLikeKey, item: EncodeLikeItem) + where + EncodeLikeKey: EncodeLike, Item: Encode, EncodeLikeItem: EncodeLike, - V: EncodeAppend, - Items: IntoIterator + Clone + EncodeLike, - Items::IntoIter: ExactSizeIterator; + V: StorageAppend; - /// Read the length of the value in a fast way, without decoding the entire value. + /// Read the length of the storage value without decoding the entire value under the + /// given `key`. + /// + /// `V` is required to implement [`StorageDecodeLength`]. /// - /// `T` is required to implement `Codec::DecodeLength`. + /// If the value does not exists or it fails to decode the length, `None` is returned. + /// Otherwise `Some(len)` is returned. /// - /// 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 `::contains_key()` - /// function for this purpose. - fn decode_len>(key: KeyArg) -> Result - where V: codec::DecodeLength + Len; + /// # Warning + /// + /// `None` does not mean that `get()` does not return a value. The default value is completly + /// ignored by this function. + fn decode_len>(key: KeyArg) -> Option + where V: StorageDecodeLength, + { + V::decode_len(&Self::hashed_key_for(key)) + } /// Migrate an item with the given `key` from a defunct `OldHasher` to the current hasher. /// @@ -240,18 +260,29 @@ pub trait IterableStorageDoubleMap< K2: FullCodec, V: FullCodec >: StorageDoubleMap { - /// The type that iterates over all `(key, value)`. - type Iterator: Iterator; + /// The type that iterates over all `(key2, value)`. + type PrefixIterator: Iterator; + + /// The type that iterates over all `(key1, key2, value)`. + type Iterator: Iterator; /// Enumerate all elements in the map with first key `k1` in no particular order. If you add or /// remove values whose first key is `k1` to the map while doing this, you'll get undefined /// results. - fn iter(k1: impl EncodeLike) -> Self::Iterator; + fn iter_prefix(k1: impl EncodeLike) -> Self::PrefixIterator; /// Remove all elements from the map with first key `k1` and iterate through them in no /// particular order. If you add elements with first key `k1` to the map while doing this, /// you'll get undefined results. - fn drain(k1: impl EncodeLike) -> Self::Iterator; + fn drain_prefix(k1: impl EncodeLike) -> Self::PrefixIterator; + + /// Enumerate all elements in the map in no particular order. If you add or remove values to + /// the map while doing this, you'll get undefined results. + fn iter() -> Self::Iterator; + + /// Remove all elements from the map and iterate through them in no particular order. If you + /// add elements to the map while doing this, you'll get undefined results. + fn drain() -> Self::Iterator; /// Translate the values of all elements by a function `f`, in the map in no particular order. /// By returning `None` from `f` for an element, you'll remove it from the map. @@ -269,21 +300,25 @@ pub trait StorageDoubleMap { /// The type that get/take returns. type Query; + /// Get the storage key used to fetch a value corresponding to a specific key. fn hashed_key_for(k1: KArg1, k2: KArg2) -> Vec where KArg1: EncodeLike, KArg2: EncodeLike; + /// Does the value (explicitly) exist in storage? fn contains_key(k1: KArg1, k2: KArg2) -> bool where KArg1: EncodeLike, KArg2: EncodeLike; + /// Load the value associated with the given key from the double map. fn get(k1: KArg1, k2: KArg2) -> Self::Query where KArg1: EncodeLike, KArg2: EncodeLike; + /// Take a value from storage, removing it afterwards. fn take(k1: KArg1, k2: KArg2) -> Self::Query where KArg1: EncodeLike, @@ -297,68 +332,80 @@ pub trait StorageDoubleMap { YKArg1: EncodeLike, YKArg2: EncodeLike; + /// Store a value to be associated with the given keys from the double map. fn insert(k1: KArg1, k2: KArg2, val: VArg) where KArg1: EncodeLike, KArg2: EncodeLike, VArg: EncodeLike; + /// Remove the value under the given keys. fn remove(k1: KArg1, k2: KArg2) where KArg1: EncodeLike, KArg2: EncodeLike; + /// Remove all values under the first key. fn remove_prefix(k1: KArg1) where KArg1: ?Sized + EncodeLike; - fn iter_prefix(k1: KArg1) -> PrefixIterator + /// Iterate over values that share the first key. + fn iter_prefix_values(k1: KArg1) -> PrefixIterator where KArg1: ?Sized + EncodeLike; + /// Mutate the value under the given keys. fn mutate(k1: KArg1, k2: KArg2, f: F) -> R where KArg1: EncodeLike, KArg2: EncodeLike, F: FnOnce(&mut Self::Query) -> R; - fn append( - k1: KArg1, - k2: KArg2, - items: Items, - ) -> Result<(), &'static str> + /// Mutate the value under the given keys when the closure returns `Ok`. + fn try_mutate(k1: KArg1, k2: KArg2, f: F) -> Result where KArg1: EncodeLike, KArg2: EncodeLike, - Item: Encode, - EncodeLikeItem: EncodeLike, - V: EncodeAppend, - Items: IntoIterator, - Items::IntoIter: ExactSizeIterator; + F: FnOnce(&mut Self::Query) -> Result; - fn append_or_insert( + /// Append the given item to the value in the storage. + /// + /// `V` is required to implement [`StorageAppend`]. + /// + /// # Warning + /// + /// If the storage item is not encoded properly, the storage will be overwritten + /// and set to `[item]`. Any default value set for the storage item will be ignored + /// on overwrite. + fn append( k1: KArg1, k2: KArg2, - items: Items, - ) - where + item: EncodeLikeItem, + ) where KArg1: EncodeLike, KArg2: EncodeLike, Item: Encode, EncodeLikeItem: EncodeLike, - V: EncodeAppend, - Items: IntoIterator + Clone + EncodeLike, - Items::IntoIter: ExactSizeIterator; + V: StorageAppend; - /// Read the length of the value in a fast way, without decoding the entire value. + /// Read the length of the storage value without decoding the entire value under the + /// given `key1` and `key2`. + /// + /// `V` is required to implement [`StorageDecodeLength`]. /// - /// `V` is required to implement `Codec::DecodeLength`. + /// If the value does not exists or it fails to decode the length, `None` is returned. + /// Otherwise `Some(len)` is returned. /// - /// 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 `::contains_key()` - /// function for this purpose. - fn decode_len(key1: KArg1, key2: KArg2) -> Result + /// # Warning + /// + /// `None` does not mean that `get()` does not return a value. The default value is completly + /// ignored by this function. + fn decode_len(key1: KArg1, key2: KArg2) -> Option where KArg1: EncodeLike, KArg2: EncodeLike, - V: codec::DecodeLength + Len; + V: StorageDecodeLength, + { + V::decode_len(&Self::hashed_key_for(key1, key2)) + } /// Migrate an item with the given `key1` and `key2` from defunct `OldHasher1` and /// `OldHasher2` to the current hashers. @@ -412,7 +459,6 @@ impl Iterator for PrefixIterator { /// Twox128(module_prefix) ++ Twox128(storage_prefix) /// ``` pub trait StoragePrefixedMap { - /// Module prefix. Used for generating final key. fn module_prefix() -> &'static [u8]; @@ -488,11 +534,57 @@ pub trait StoragePrefixedMap { } } +/// Marker trait that will be implemented for types that support the `storage::append` api. +/// +/// This trait is sealed. +pub trait StorageAppend: private::Sealed {} + +/// Marker trait that will be implemented for types that support to decode their length in an +/// effificent way. It is expected that the length is at the beginning of the encoded object +/// and that the length is a `Compact`. +/// +/// This trait is sealed. +pub trait StorageDecodeLength: private::Sealed + codec::DecodeLength { + /// Decode the length of the storage value at `key`. + /// + /// This function assumes that the length is at the beginning of the encoded object + /// and is a `Compact`. + /// + /// Returns `None` if the storage value does not exist or the decoding failed. + fn decode_len(key: &[u8]) -> Option { + // `Compact` is 5 bytes in maximum. + let mut data = [0u8; 5]; + let len = sp_io::storage::read(key, &mut data, 0)?; + let len = data.len().min(len as usize); + ::len(&data[..len]).ok() + } +} + +/// Provides `Sealed` trait to prevent implementing trait `StorageAppend` & `StorageDecodeLength` +/// outside of this crate. +mod private { + use super::*; + + pub trait Sealed {} + + impl Sealed for Vec {} + impl Sealed for Digest {} +} + +impl StorageAppend for Vec {} +impl StorageDecodeLength for Vec {} + +/// We abuse the fact that SCALE does not put any marker into the encoding, i.e. +/// we only encode the internal vec and we can append to this vec. We have a test that ensures +/// that if the `Digest` format ever changes, we need to remove this here. +impl StorageAppend> for Digest {} + #[cfg(test)] mod test { + use super::*; use sp_core::hashing::twox_128; use sp_io::TestExternalities; - use crate::storage::{unhashed, StoragePrefixedMap}; + use generator::StorageValue as _; #[test] fn prefixed_map_works() { @@ -567,4 +659,41 @@ mod test { assert_eq!(unhashed::get(&key_after[..]), Some(33u64)); }); } + + // This test ensures that the Digest encoding does not change without being noticied. + #[test] + fn digest_storage_append_works_as_expected() { + TestExternalities::default().execute_with(|| { + struct Storage; + impl generator::StorageValue> for Storage { + type Query = Digest; + + fn module_prefix() -> &'static [u8] { + b"MyModule" + } + + fn storage_prefix() -> &'static [u8] { + b"Storage" + } + + fn from_optional_value_to_query(v: Option>) -> Self::Query { + v.unwrap() + } + + fn from_query_to_optional_value(v: Self::Query) -> Option> { + Some(v) + } + } + + Storage::append(DigestItem::ChangesTrieRoot(1)); + Storage::append(DigestItem::Other(Vec::new())); + + let value = unhashed::get_raw(&Storage::storage_value_final_key()).unwrap(); + + let expected = Digest { + logs: vec![DigestItem::ChangesTrieRoot(1), DigestItem::Other(Vec::new())], + }; + assert_eq!(Digest::decode(&mut &value[..]).unwrap(), expected); + }); + } } diff --git a/frame/support/src/storage/unhashed.rs b/frame/support/src/storage/unhashed.rs index 1ecf46ef1864708b53e7e19073768196314be5b4..34b146b86f6ba0ecdf75e0bf3467ac76400f085d 100644 --- a/frame/support/src/storage/unhashed.rs +++ b/frame/support/src/storage/unhashed.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Operation on unhashed runtime storage. diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index 7e2040ee234a75fbcd2b488b7ebb40c64bfbefd7..e0b2f256f0c78d62b7ddc3f5ae09b19f1003a5fc 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Traits for FRAME. //! @@ -24,13 +25,276 @@ use sp_core::u32_trait::Value as U32; use sp_runtime::{ RuntimeDebug, ConsensusEngineId, DispatchResult, DispatchError, traits::{ MaybeSerializeDeserialize, AtLeast32Bit, Saturating, TrailingZeroInput, Bounded, Zero, - BadOrigin + BadOrigin, AtLeast32BitUnsigned }, }; use crate::dispatch::Parameter; use crate::storage::StorageMap; +use crate::weights::Weight; use impl_trait_for_tuples::impl_for_tuples; +/// Re-expected for the macro. +#[doc(hidden)] +pub use sp_std::{mem::{swap, take}, cell::RefCell, vec::Vec, boxed::Box}; + +/// Simple trait for providing a filter over a reference to some type. +pub trait Filter { + /// Determine if a given value should be allowed through the filter (returns `true`) or not. + fn filter(_: &T) -> bool; +} + +impl Filter for () { + fn filter(_: &T) -> bool { true } +} + +/// Trait to add a constraint onto the filter. +pub trait FilterStack: Filter { + /// The type used to archive the stack. + type Stack; + + /// Add a new `constraint` onto the filter. + fn push(constraint: impl Fn(&T) -> bool + 'static); + + /// Removes the most recently pushed, and not-yet-popped, constraint from the filter. + fn pop(); + + /// Clear the filter, returning a value that may be used later to `restore` it. + fn take() -> Self::Stack; + + /// Restore the filter from a previous `take` operation. + fn restore(taken: Self::Stack); +} + +/// Guard type for pushing a constraint to a `FilterStack` and popping when dropped. +pub struct FilterStackGuard, T>(PhantomData<(F, T)>); + +/// Guard type for clearing all pushed constraints from a `FilterStack` and reinstating them when +/// dropped. +pub struct ClearFilterGuard, T>(Option, PhantomData); + +impl, T> FilterStackGuard { + /// Create a new instance, adding a new `constraint` onto the filter `T`, and popping it when + /// this instance is dropped. + pub fn new(constraint: impl Fn(&T) -> bool + 'static) -> Self { + F::push(constraint); + Self(PhantomData) + } +} + +impl, T> Drop for FilterStackGuard { + fn drop(&mut self) { + F::pop(); + } +} + +impl, T> ClearFilterGuard { + /// Create a new instance, adding a new `constraint` onto the filter `T`, and popping it when + /// this instance is dropped. + pub fn new() -> Self { + Self(Some(F::take()), PhantomData) + } +} + +impl, T> Drop for ClearFilterGuard { + fn drop(&mut self) { + if let Some(taken) = self.0.take() { + F::restore(taken); + } + } +} + +/// Simple trait for providing a filter over a reference to some type, given an instance of itself. +pub trait InstanceFilter: Sized + Send + Sync { + /// Determine if a given value should be allowed through the filter (returns `true`) or not. + fn filter(&self, _: &T) -> bool; + + /// Determines whether `self` matches at least everything that `_o` does. + fn is_superset(&self, _o: &Self) -> bool { false } +} + +impl InstanceFilter for () { + fn filter(&self, _: &T) -> bool { true } + fn is_superset(&self, _o: &Self) -> bool { true } +} + +#[macro_export] +macro_rules! impl_filter_stack { + ($target:ty, $base:ty, $call:ty, $module:ident) => { + #[cfg(feature = "std")] + mod $module { + #[allow(unused_imports)] + use super::*; + use $crate::traits::{swap, take, RefCell, Vec, Box, Filter, FilterStack}; + + thread_local! { + static FILTER: RefCell bool + 'static>>> = RefCell::new(Vec::new()); + } + + impl Filter<$call> for $target { + fn filter(call: &$call) -> bool { + <$base>::filter(call) && + FILTER.with(|filter| filter.borrow().iter().all(|f| f(call))) + } + } + + impl FilterStack<$call> for $target { + type Stack = Vec bool + 'static>>; + fn push(f: impl Fn(&$call) -> bool + 'static) { + FILTER.with(|filter| filter.borrow_mut().push(Box::new(f))); + } + fn pop() { + FILTER.with(|filter| filter.borrow_mut().pop()); + } + fn take() -> Self::Stack { + FILTER.with(|filter| take(filter.borrow_mut().as_mut())) + } + fn restore(mut s: Self::Stack) { + FILTER.with(|filter| swap(filter.borrow_mut().as_mut(), &mut s)); + } + } + } + + #[cfg(not(feature = "std"))] + mod $module { + #[allow(unused_imports)] + use super::*; + use $crate::traits::{swap, take, RefCell, Vec, Box, Filter, FilterStack}; + + struct ThisFilter(RefCell bool + 'static>>>); + // NOTE: Safe only in wasm (guarded above) because there's only one thread. + unsafe impl Send for ThisFilter {} + unsafe impl Sync for ThisFilter {} + + static FILTER: ThisFilter = ThisFilter(RefCell::new(Vec::new())); + + impl Filter<$call> for $target { + fn filter(call: &$call) -> bool { + <$base>::filter(call) && FILTER.0.borrow().iter().all(|f| f(call)) + } + } + + impl FilterStack<$call> for $target { + type Stack = Vec bool + 'static>>; + fn push(f: impl Fn(&$call) -> bool + 'static) { + FILTER.0.borrow_mut().push(Box::new(f)); + } + fn pop() { + FILTER.0.borrow_mut().pop(); + } + fn take() -> Self::Stack { + take(FILTER.0.borrow_mut().as_mut()) + } + fn restore(mut s: Self::Stack) { + swap(FILTER.0.borrow_mut().as_mut(), &mut s); + } + } + } + } +} + +/// Type that provide some integrity tests. +/// +/// This implemented for modules by `decl_module`. +#[impl_for_tuples(30)] +pub trait IntegrityTest { + /// Run integrity test. + /// + /// The test is not executed in a externalities provided environment. + fn integrity_test() {} +} + +#[cfg(test)] +mod test_impl_filter_stack { + use super::*; + + pub struct IsCallable; + pub struct BaseFilter; + impl Filter for BaseFilter { + fn filter(x: &u32) -> bool { x % 2 == 0 } + } + impl_filter_stack!( + crate::traits::test_impl_filter_stack::IsCallable, + crate::traits::test_impl_filter_stack::BaseFilter, + u32, + is_callable + ); + + #[test] + fn impl_filter_stack_should_work() { + assert!(IsCallable::filter(&36)); + assert!(IsCallable::filter(&40)); + assert!(IsCallable::filter(&42)); + assert!(!IsCallable::filter(&43)); + + IsCallable::push(|x| *x < 42); + assert!(IsCallable::filter(&36)); + assert!(IsCallable::filter(&40)); + assert!(!IsCallable::filter(&42)); + + IsCallable::push(|x| *x % 3 == 0); + assert!(IsCallable::filter(&36)); + assert!(!IsCallable::filter(&40)); + + IsCallable::pop(); + assert!(IsCallable::filter(&36)); + assert!(IsCallable::filter(&40)); + assert!(!IsCallable::filter(&42)); + + let saved = IsCallable::take(); + assert!(IsCallable::filter(&36)); + assert!(IsCallable::filter(&40)); + assert!(IsCallable::filter(&42)); + assert!(!IsCallable::filter(&43)); + + IsCallable::restore(saved); + assert!(IsCallable::filter(&36)); + assert!(IsCallable::filter(&40)); + assert!(!IsCallable::filter(&42)); + + IsCallable::pop(); + assert!(IsCallable::filter(&36)); + assert!(IsCallable::filter(&40)); + assert!(IsCallable::filter(&42)); + assert!(!IsCallable::filter(&43)); + } + + #[test] + fn guards_should_work() { + assert!(IsCallable::filter(&36)); + assert!(IsCallable::filter(&40)); + assert!(IsCallable::filter(&42)); + assert!(!IsCallable::filter(&43)); + { + let _guard_1 = FilterStackGuard::::new(|x| *x < 42); + assert!(IsCallable::filter(&36)); + assert!(IsCallable::filter(&40)); + assert!(!IsCallable::filter(&42)); + { + let _guard_2 = FilterStackGuard::::new(|x| *x % 3 == 0); + assert!(IsCallable::filter(&36)); + assert!(!IsCallable::filter(&40)); + } + assert!(IsCallable::filter(&36)); + assert!(IsCallable::filter(&40)); + assert!(!IsCallable::filter(&42)); + { + let _guard_2 = ClearFilterGuard::::new(); + assert!(IsCallable::filter(&36)); + assert!(IsCallable::filter(&40)); + assert!(IsCallable::filter(&42)); + assert!(!IsCallable::filter(&43)); + } + assert!(IsCallable::filter(&36)); + assert!(IsCallable::filter(&40)); + assert!(!IsCallable::filter(&42)); + } + assert!(IsCallable::filter(&36)); + assert!(IsCallable::filter(&40)); + assert!(IsCallable::filter(&42)); + assert!(!IsCallable::filter(&43)); + } +} + /// An abstraction of a value stored within storage, but possibly as part of a larger composite /// item. pub trait StoredMap { @@ -65,6 +329,10 @@ pub trait Happened { fn happened(t: &T); } +impl Happened for () { + fn happened(_: &T) {} +} + /// A shim for placing around a storage item in order to use it as a `StoredValue`. Ideally this /// wouldn't be needed as `StorageValue`s should blanket implement `StoredValue`s, however this /// would break the ability to have custom impls of `StoredValue`. The other workaround is to @@ -93,20 +361,23 @@ impl< fn get(k: &K) -> T { S::get(k) } fn is_explicit(k: &K) -> bool { S::contains_key(k) } fn insert(k: &K, t: T) { + let existed = S::contains_key(&k); S::insert(k, t); - if !S::contains_key(&k) { + if !existed { Created::happened(k); } } fn remove(k: &K) { - if S::contains_key(&k) { + let existed = S::contains_key(&k); + S::remove(k); + if existed { Removed::happened(&k); } - S::remove(k); } fn mutate(k: &K, f: impl FnOnce(&mut T) -> R) -> R { + let existed = S::contains_key(&k); let r = S::mutate(k, f); - if !S::contains_key(&k) { + if !existed { Created::happened(k); } r @@ -147,12 +418,19 @@ pub trait EstimateNextSessionRotation { /// /// None should be returned if the estimation fails to come to an answer fn estimate_next_session_rotation(now: BlockNumber) -> Option; + + /// Return the weight of calling `estimate_next_session_rotation` + fn weight(now: BlockNumber) -> Weight; } impl EstimateNextSessionRotation for () { fn estimate_next_session_rotation(_: BlockNumber) -> Option { Default::default() } + + fn weight(_: BlockNumber) -> Weight { + 0 + } } /// Something that can estimate at which block the next `new_session` will be triggered. This must @@ -160,12 +438,19 @@ impl EstimateNextSessionRotation for () { pub trait EstimateNextNewSession { /// Return the block number at which the next new session is estimated to happen. fn estimate_next_new_session(now: BlockNumber) -> Option; + + /// Return the weight of calling `estimate_next_new_session` + fn weight(now: BlockNumber) -> Weight; } impl EstimateNextNewSession for () { fn estimate_next_new_session(_: BlockNumber) -> Option { Default::default() } + + fn weight(_: BlockNumber) -> Weight { + 0 + } } /// Anything that can have a `::len()` method. @@ -180,9 +465,11 @@ impl Len for T where ::IntoIter: Ex } } -/// A trait for querying a single fixed value from a type. +/// A trait for querying a single value from a type. +/// +/// It is not required that the value is constant. pub trait Get { - /// Return a constant value. + /// Return the current value. fn get() -> T; } @@ -190,9 +477,7 @@ 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. +/// A trait for querying whether a type can be said to "contain" a value. pub trait Contains { /// Return `true` if this "contains" the given value `t`. fn contains(t: &T) -> bool { Self::sorted_members().binary_search(t).is_ok() } @@ -208,7 +493,15 @@ pub trait Contains { /// /// **Should be used for benchmarking only!!!** #[cfg(feature = "runtime-benchmarks")] - fn add(t: &T); + fn add(_t: &T) { unimplemented!() } +} + +/// A trait for querying bound for the length of an implementation of `Contains` +pub trait ContainsLengthBound { + /// Minimum number of elements contained + fn min_len() -> usize; + /// Maximum number of elements contained + fn max_len() -> usize; } /// Determiner to say whether a given account is unused. @@ -282,6 +575,21 @@ pub trait KeyOwnerProofSystem { fn check_proof(key: Key, proof: Self::Proof) -> Option; } +impl KeyOwnerProofSystem for () { + // The proof and identification tuples is any bottom type to guarantee that the methods of this + // implementation can never be called or return anything other than `None`. + type Proof = crate::Void; + type IdentificationTuple = crate::Void; + + fn prove(_key: Key) -> Option { + None + } + + fn check_proof(_key: Key, _proof: Self::Proof) -> Option { + None + } +} + /// Handler for when some currency "account" decreased in balance for /// some reason. /// @@ -484,7 +792,7 @@ pub enum SignedImbalance>{ impl< P: Imbalance, N: Imbalance, - B: AtLeast32Bit + FullCodec + Copy + MaybeSerializeDeserialize + Debug + Default, + B: AtLeast32BitUnsigned + FullCodec + Copy + MaybeSerializeDeserialize + Debug + Default, > SignedImbalance { pub fn zero() -> Self { SignedImbalance::Positive(P::zero()) @@ -547,7 +855,8 @@ impl< /// Abstraction over a fungible assets system. pub trait Currency { /// The balance of an account. - type Balance: AtLeast32Bit + FullCodec + Copy + MaybeSerializeDeserialize + Debug + Default; + type Balance: AtLeast32BitUnsigned + 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. @@ -715,6 +1024,7 @@ pub trait Currency { } /// Status of funds. +#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, RuntimeDebug)] pub enum BalanceStatus { /// Funds are free, as corresponding to `free` item in Balances. Free, @@ -1121,11 +1431,19 @@ impl OnInitialize for Tuple { } } -/// The runtime upgrade trait. Implementing this lets you express what should happen -/// when the runtime upgrades, and changes may need to occur to your module. +/// The runtime upgrade trait. +/// +/// Implementing this lets you express what should happen when the runtime upgrades, +/// and changes may need to occur to your module. pub trait OnRuntimeUpgrade { /// Perform a module upgrade. /// + /// # Warning + /// + /// This function will be called before we initialized any runtime state, aka `on_initialize` + /// wasn't called yet. So, information like the block number and any other + /// block local data are not accessible. + /// /// Return the non-negotiable weight consumed for runtime upgrade. fn on_runtime_upgrade() -> crate::weights::Weight { 0 } } @@ -1174,15 +1492,15 @@ pub mod schedule { /// The highest priority. We invert the value so that normal sorting will place the highest /// priority at the beginning of the list. - pub const HIGHEST_PRORITY: Priority = 0; + pub const HIGHEST_PRIORITY: Priority = 0; /// Anything of this value or lower will definitely be scheduled on the block that they ask for, even /// if it breaches the `MaximumWeight` limitation. pub const HARD_DEADLINE: Priority = 63; /// The lowest priority. Most stuff should be around here. - pub const LOWEST_PRORITY: Priority = 255; + pub const LOWEST_PRIORITY: Priority = 255; /// A type that can be used as a scheduler. - pub trait Anon { + pub trait Anon { /// An address which can be used for removing a scheduled task. type Address: Codec + Clone + Eq + EncodeLike + Debug; @@ -1195,8 +1513,9 @@ pub mod schedule { when: BlockNumber, maybe_periodic: Option>, priority: Priority, + origin: Origin, call: Call - ) -> Self::Address; + ) -> Result; /// Cancel a scheduled task. If periodic, then it will cancel all further instances of that, /// also. @@ -1212,7 +1531,7 @@ pub mod schedule { } /// A type that can be used as a scheduler. - pub trait Named { + pub trait Named { /// An address which can be used for removing a scheduled task. type Address: Codec + Clone + Eq + EncodeLike + sp_std::fmt::Debug; @@ -1220,10 +1539,11 @@ pub mod schedule { /// /// - `id`: The identity of the task. This must be unique and will return an error if not. fn schedule_named( - id: impl Encode, + id: Vec, when: BlockNumber, maybe_periodic: Option>, priority: Priority, + origin: Origin, call: Call ) -> Result; @@ -1234,7 +1554,7 @@ pub mod schedule { /// /// NOTE: This guaranteed to work only *before* the point that it is due to be executed. /// If it ends up being delayed beyond the point of execution, then it cannot be cancelled. - fn cancel_named(id: impl Encode) -> Result<(), ()>; + fn cancel_named(id: Vec) -> Result<(), ()>; } } @@ -1256,6 +1576,66 @@ pub trait EnsureOrigin { fn successful_origin() -> OuterOrigin; } +/// Type that can be dispatched with an origin but without checking the origin filter. +/// +/// Implemented for pallet dispatchable type by `decl_module` and for runtime dispatchable by +/// `construct_runtime` and `impl_outer_dispatch`. +pub trait UnfilteredDispatchable { + /// The origin type of the runtime, (i.e. `frame_system::Trait::Origin`). + type Origin; + + /// Dispatch this call but do not check the filter in origin. + fn dispatch_bypass_filter(self, origin: Self::Origin) -> crate::dispatch::DispatchResultWithPostInfo; +} + +/// Methods available on `frame_system::Trait::Origin`. +pub trait OriginTrait: Sized { + /// Runtime call type, as in `frame_system::Trait::Call` + type Call; + + /// The caller origin, overarching type of all pallets origins. + type PalletsOrigin; + + /// Add a filter to the origin. + fn add_filter(&mut self, filter: impl Fn(&Self::Call) -> bool + 'static); + + /// Reset origin filters to default one, i.e `frame_system::Trait::BaseCallFilter`. + fn reset_filter(&mut self); + + /// Replace the caller with caller from the other origin + fn set_caller_from(&mut self, other: impl Into); + + /// Filter the call, if false then call is filtered out. + fn filter_call(&self, call: &Self::Call) -> bool; + + /// Get the caller. + fn caller(&self) -> &Self::PalletsOrigin; +} + +/// Trait to be used when types are exactly same. +/// +/// This allow to convert back and forth from type, a reference and a mutable reference. +pub trait IsType: Into + From { + /// Cast reference. + fn from_ref(t: &T) -> &Self; + + /// Cast reference. + fn into_ref(&self) -> &T; + + /// Cast mutable reference. + fn from_mut(t: &mut T) -> &mut Self; + + /// Cast mutable reference. + fn into_mut(&mut self) -> &mut T; +} + +impl IsType for T { + fn from_ref(t: &T) -> &Self { t } + fn into_ref(&self) -> &T { self } + fn from_mut(t: &mut T) -> &mut Self { t } + fn into_mut(&mut self) -> &mut T { self } +} + #[cfg(test)] mod tests { use super::*; diff --git a/frame/support/src/unsigned.rs b/frame/support/src/unsigned.rs index 3bc6f692affc20426f196792666fe1c0413c146f..16c434fe638bca64c9f1dd6a266af052852d9207 100644 --- a/frame/support/src/unsigned.rs +++ b/frame/support/src/unsigned.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #[doc(hidden)] pub use crate::sp_runtime::traits::ValidateUnsigned; diff --git a/frame/support/src/weights.rs b/frame/support/src/weights.rs index 4d501305f0ddbf2df25e319eee8037dbe29d5041..595e84333bda7503df5a850f7b9cc2362ac40cdb 100644 --- a/frame/support/src/weights.rs +++ b/frame/support/src/weights.rs @@ -1,56 +1,180 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Primitives for transaction weighting. //! -//! 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 `#[weight = $x]` attribute. In this +//! snipped, `$x` can be any user provided struct that implements the following traits: //! -//! 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. +//! - [`WeighData`]: the weight amount. +//! - [`ClassifyDispatch`]: class of the dispatch. +//! - [`PaysFee`]: weather this weight should be translated to fee and deducted upon dispatch. //! //! 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. +//! and provides it by implementing the [`GetDispatchInfo`] for all `Call` both inner and outer call +//! types. +//! +//! Substrate provides two pre-defined ways to annotate weight: +//! +//! ### 1. Fixed values +//! +//! This can only be used when all 3 traits can be resolved statically. You have 3 degrees of +//! configuration: +//! +//! 1. Define only weight, **in which case `ClassifyDispatch` will be `Normal` and `PaysFee` will be +//! `Yes`**. +//! +//! ``` +//! # use frame_system::Trait; +//! frame_support::decl_module! { +//! pub struct Module for enum Call where origin: T::Origin { +//! #[weight = 1000] +//! fn dispatching(origin) { unimplemented!() } +//! } +//! } +//! # fn main() {} +//! ``` +//! +//! 2.1 Define weight and class, **in which case `PaysFee` would be `Yes`**. +//! +//! ``` +//! # use frame_system::Trait; +//! # use frame_support::weights::DispatchClass; +//! frame_support::decl_module! { +//! pub struct Module for enum Call where origin: T::Origin { +//! #[weight = (1000, DispatchClass::Operational)] +//! fn dispatching(origin) { unimplemented!() } +//! } +//! } +//! # fn main() {} +//! ``` +//! +//! 2.2 Define weight and `PaysFee`, **in which case `ClassifyDispatch` would be `Normal`**. //! -//! If no `#[weight]` is defined, the macro automatically injects the `Default` implementation of -//! the [`SimpleDispatchInfo`]. +//! ``` +//! # use frame_system::Trait; +//! # use frame_support::weights::Pays; +//! frame_support::decl_module! { +//! pub struct Module for enum Call where origin: T::Origin { +//! #[weight = (1000, Pays::No)] +//! fn dispatching(origin) { unimplemented!() } +//! } +//! } +//! # fn main() {} +//! ``` //! -//! 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. +//! 3. Define all 3 parameters. +//! +//! ``` +//! # use frame_system::Trait; +//! # use frame_support::weights::{DispatchClass, Pays}; +//! frame_support::decl_module! { +//! pub struct Module for enum Call where origin: T::Origin { +//! #[weight = (1000, DispatchClass::Operational, Pays::No)] +//! fn dispatching(origin) { unimplemented!() } +//! } +//! } +//! # fn main() {} +//! ``` +//! +//! ### 2. Define weights as a function of input arguments using `FunctionOf` tuple struct. This struct works +//! in a similar manner as above. 3 items must be provided and each can be either a fixed value or a +//! function/closure with the same parameters list as the dispatchable function itself, wrapper in a +//! tuple. +//! +//! Using this only makes sense if you want to use a function for at least one of the elements. If +//! all 3 are static values, providing a raw tuple is easier. +//! +//! ``` +//! # use frame_system::Trait; +//! # use frame_support::weights::{DispatchClass, FunctionOf, Pays}; +//! frame_support::decl_module! { +//! pub struct Module for enum Call where origin: T::Origin { +//! #[weight = FunctionOf( +//! // weight, function. +//! |args: (&u32, &u64)| *args.0 as u64 + args.1, +//! // class, fixed. +//! DispatchClass::Operational, +//! // pays fee, function. +//! |args: (&u32, &u64)| if *args.0 > 1000 { Pays::Yes } else { Pays::No }, +//! )] +//! fn dispatching(origin, a: u32, b: u64) { unimplemented!() } +//! } +//! } +//! # fn main() {} +//! ``` +//! FRAME assumes a weight of `1_000_000_000_000` equals 1 second of compute on a standard machine. +//! +//! Latest machine specification used to benchmark are: +//! - Digital Ocean: ubuntu-s-2vcpu-4gb-ams3-01 +//! - 2x Intel(R) Xeon(R) CPU E5-2650 v4 @ 2.20GHz +//! - 4GB RAM +//! - Ubuntu 19.10 (GNU/Linux 5.3.0-18-generic x86_64) +//! - rustc 1.42.0 (b8cedc004 2020-03-09) #[cfg(feature = "std")] use serde::{Serialize, Deserialize}; use codec::{Encode, Decode}; -use sp_arithmetic::traits::Bounded; use sp_runtime::{ RuntimeDebug, traits::SignedExtension, generic::{CheckedExtrinsic, UncheckedExtrinsic}, }; -use crate::dispatch::{DispatchErrorWithPostInfo, DispatchError}; +use crate::dispatch::{DispatchErrorWithPostInfo, DispatchResultWithPostInfo, DispatchError}; +use sp_runtime::traits::SaturatedConversion; +use sp_arithmetic::{Perbill, traits::{BaseArithmetic, Saturating, Unsigned}}; +use smallvec::{smallvec, SmallVec}; /// Re-export priority as type pub use sp_runtime::transaction_validity::TransactionPriority; /// Numeric range of a transaction weight. -pub type Weight = u32; +pub type Weight = u64; + +/// These constants are specific to FRAME, and the current implementation of its various components. +/// For example: FRAME System, FRAME Executive, our FRAME support libraries, etc... +pub mod constants { + use super::{RuntimeDbWeight, Weight}; + use crate::parameter_types; + + pub const WEIGHT_PER_SECOND: Weight = 1_000_000_000_000; + pub const WEIGHT_PER_MILLIS: Weight = WEIGHT_PER_SECOND / 1000; // 1_000_000_000 + pub const WEIGHT_PER_MICROS: Weight = WEIGHT_PER_MILLIS / 1000; // 1_000_000 + pub const WEIGHT_PER_NANOS: Weight = WEIGHT_PER_MICROS / 1000; // 1_000 + + parameter_types! { + /// Importing a block with 0 txs takes ~5 ms + pub const BlockExecutionWeight: Weight = 5 * WEIGHT_PER_MILLIS; + /// Executing 10,000 System remarks (no-op) txs takes ~1.26 seconds -> ~125 µs per tx + pub const ExtrinsicBaseWeight: Weight = 125 * WEIGHT_PER_MICROS; + /// By default, Substrate uses RocksDB, so this will be the weight used throughout + /// the runtime. + pub const RocksDbWeight: RuntimeDbWeight = RuntimeDbWeight { + read: 25 * WEIGHT_PER_MICROS, // ~25 µs @ 200,000 items + write: 100 * WEIGHT_PER_MICROS, // ~100 µs @ 200,000 items + }; + /// ParityDB can be enabled with a feature flag, but is still experimental. These weights + /// are available for brave runtime engineers who may want to try this out as default. + pub const ParityDbWeight: RuntimeDbWeight = RuntimeDbWeight { + read: 8 * WEIGHT_PER_MICROS, // ~8 µs @ 200,000 items + write: 50 * WEIGHT_PER_MICROS, // ~50 µs @ 200,000 items + }; + } +} /// Means of weighing some particular kind of data (`T`). pub trait WeighData { @@ -68,15 +192,27 @@ pub trait ClassifyDispatch { } /// Indicates if dispatch function should pay fees or not. -/// If set to false, the block resource limits are applied, yet no fee is deducted. +/// If set to `Pays::No`, the block resource limits are applied, yet no fee is deducted. pub trait PaysFee { - fn pays_fee(&self, _target: T) -> bool { - true + fn pays_fee(&self, _target: T) -> Pays; +} + +/// Explicit enum to denote if a transaction pays fee or not. +#[derive(Clone, Copy, Eq, PartialEq, RuntimeDebug, Encode, Decode)] +pub enum Pays { + /// Transactor will pay related fees. + Yes, + /// Transactor will NOT pay related fees. + No, +} + +impl Default for Pays { + fn default() -> Self { + Self::Yes } } -/// 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`). +/// A generalized group of dispatch types. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] #[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, RuntimeDebug)] @@ -85,24 +221,24 @@ pub enum DispatchClass { Normal, /// An operational dispatch. Operational, + /// A mandatory dispatch. These kinds of dispatch are always included regardless of their + /// weight, therefore it is critical that they are separately validated to ensure that a + /// malicious validator cannot craft a valid but impossibly heavy block. Usually this just means + /// ensuring that the extrinsic can only be included once and that it is always very light. + /// + /// Do *NOT* use it for extrinsics that can be heavy. + /// + /// The only real use case for this is inherent extrinsics that are required to execute in a + /// block for the block to be valid, and it solves the issue in the case that the block + /// initialization is sufficiently heavy to mean that those inherents do not fit into the + /// block. Essentially, we assume that in these exceptional circumstances, it is better to + /// allow an overweight block to be created than to not allow any block at all to be created. + Mandatory, } impl Default for DispatchClass { fn default() -> Self { - DispatchClass::Normal - } -} - -impl From for DispatchClass { - fn from(tx: SimpleDispatchInfo) -> Self { - match tx { - SimpleDispatchInfo::FixedOperational(_) => DispatchClass::Operational, - SimpleDispatchInfo::MaxOperational => DispatchClass::Operational, - - SimpleDispatchInfo::FixedNormal(_) => DispatchClass::Normal, - SimpleDispatchInfo::MaxNormal => DispatchClass::Normal, - SimpleDispatchInfo::InsecureFreeNormal => DispatchClass::Normal, - } + Self::Normal } } @@ -114,7 +250,16 @@ pub struct DispatchInfo { /// Class of this transaction. pub class: DispatchClass, /// Does this transaction pay fees. - pub pays_fee: bool, + pub pays_fee: Pays, +} + +/// 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. + /// + /// This is done independently of its encoded size. + fn get_dispatch_info(&self) -> DispatchInfo; } /// Weight information that is only available post dispatch. @@ -124,6 +269,30 @@ pub struct PostDispatchInfo { pub actual_weight: Option, } +impl PostDispatchInfo { + /// Calculate how much (if any) weight was not used by the `Dispatchable`. + pub fn calc_unspent(&self, info: &DispatchInfo) -> Weight { + info.weight - self.calc_actual_weight(info) + } + + /// Calculate how much weight was actually spent by the `Dispatchable`. + pub fn calc_actual_weight(&self, info: &DispatchInfo) -> Weight { + if let Some(actual_weight) = self.actual_weight { + actual_weight.min(info.weight) + } else { + info.weight + } + } +} + +/// Extract the actual weight from a dispatch result if any or fall back to the default weight. +pub fn extract_actual_weight(result: &DispatchResultWithPostInfo, info: &DispatchInfo) -> Weight { + match result { + Ok(post_info) => &post_info, + Err(err) => &err.post_info, + }.calc_actual_weight(info) +} + impl From> for PostDispatchInfo { fn from(actual_weight: Option) -> Self { Self { @@ -151,7 +320,7 @@ impl sp_runtime::traits::Printable for PostDispatchInfo { } /// Allows easy conversion from `DispatchError` to `DispatchErrorWithPostInfo` for dispatchables -/// that want to return a custom a posteriori weight on error. +/// that want to return a custom a posterior weight on error. pub trait WithPostDispatchInfo { /// Call this on your modules custom errors type in order to return a custom weight on error. /// @@ -175,88 +344,75 @@ impl WithPostDispatchInfo for T where } } -/// 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. - /// - /// This is done independently of its encoded size. - fn get_dispatch_info(&self) -> DispatchInfo; +impl WeighData for Weight { + fn weigh_data(&self, _: T) -> Weight { + return *self + } } -/// 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` -/// implementation of [`SimpleDispatchInfo`] is used. -/// -/// For each generalized group (`Normal` and `Operation`): -/// - A `Fixed` variant means weight fee is charged normally and the weight is the number -/// specified in the inner value of the variant. -/// - 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())`. -/// -/// As for the generalized groups themselves: -/// - `Normal` variants will be assigned a priority proportional to their weight. They can only -/// 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)] -pub enum SimpleDispatchInfo { - /// A normal dispatch with fixed weight. - FixedNormal(Weight), - /// A normal dispatch with the maximum weight. - MaxNormal, - /// A normal dispatch with no weight. Base and bytes fees still need to be paid. - InsecureFreeNormal, - /// An operational dispatch with fixed weight. - FixedOperational(Weight), - /// An operational dispatch with the maximum weight. - MaxOperational, -} - -impl WeighData for SimpleDispatchInfo { +impl ClassifyDispatch for Weight { + fn classify_dispatch(&self, _: T) -> DispatchClass { + DispatchClass::Normal + } +} + +impl PaysFee for Weight { + fn pays_fee(&self, _: T) -> Pays { + Pays::Yes + } +} + +impl WeighData for (Weight, DispatchClass, Pays) { fn weigh_data(&self, _: T) -> Weight { - match self { - SimpleDispatchInfo::FixedNormal(w) => *w, - SimpleDispatchInfo::MaxNormal => Bounded::max_value(), - SimpleDispatchInfo::InsecureFreeNormal => Bounded::min_value(), + return self.0 + } +} - SimpleDispatchInfo::FixedOperational(w) => *w, - SimpleDispatchInfo::MaxOperational => Bounded::max_value(), - } +impl ClassifyDispatch for (Weight, DispatchClass, Pays) { + fn classify_dispatch(&self, _: T) -> DispatchClass { + self.1 + } +} + +impl PaysFee for (Weight, DispatchClass, Pays) { + fn pays_fee(&self, _: T) -> Pays { + self.2 + } +} + +impl WeighData for (Weight, DispatchClass) { + fn weigh_data(&self, _: T) -> Weight { + return self.0 } } -impl ClassifyDispatch for SimpleDispatchInfo { +impl ClassifyDispatch for (Weight, DispatchClass) { fn classify_dispatch(&self, _: T) -> DispatchClass { - DispatchClass::from(*self) + self.1 } } -impl PaysFee for SimpleDispatchInfo { - fn pays_fee(&self, _: T) -> bool { - match self { - SimpleDispatchInfo::FixedNormal(_) => true, - SimpleDispatchInfo::MaxNormal => true, - SimpleDispatchInfo::InsecureFreeNormal => true, +impl PaysFee for (Weight, DispatchClass) { + fn pays_fee(&self, _: T) -> Pays { + Pays::Yes + } +} - SimpleDispatchInfo::FixedOperational(_) => true, - SimpleDispatchInfo::MaxOperational => true, - } +impl WeighData for (Weight, Pays) { + fn weigh_data(&self, _: T) -> Weight { + return self.0 } } -impl Default for SimpleDispatchInfo { - fn default() -> Self { - // Default weight of all transactions. - SimpleDispatchInfo::FixedNormal(10_000) +impl ClassifyDispatch for (Weight, Pays) { + fn classify_dispatch(&self, _: T) -> DispatchClass { + DispatchClass::Normal } } -impl SimpleDispatchInfo { - /// An _additive zero_ variant of SimpleDispatchInfo. - pub fn zero() -> Self { - Self::FixedNormal(0) +impl PaysFee for (Weight, Pays) { + fn pays_fee(&self, _: T) -> Pays { + self.1 } } @@ -267,11 +423,13 @@ impl SimpleDispatchInfo { /// argument list as the dispatched, wrapped in a tuple. /// - `CD`: a raw `DispatchClass` value or a closure that returns a `DispatchClass` /// with the same argument list as the dispatched, wrapped in a tuple. -/// - `PF`: a `bool` for whether this dispatch pays fee or not or a closure that -/// returns a bool with the same argument list as the dispatched, wrapped in a tuple. +/// - `PF`: a `Pays` variant for whether this dispatch pays fee or not or a closure that +/// returns a `Pays` variant with the same argument list as the dispatched, wrapped in a tuple. +#[deprecated = "Function arguments are available directly inside the annotation now."] pub struct FunctionOf(pub WD, pub CD, pub PF); // `WeighData` as a raw value +#[allow(deprecated)] impl WeighData for FunctionOf { fn weigh_data(&self, _: Args) -> Weight { self.0 @@ -279,6 +437,7 @@ impl WeighData for FunctionOf { } // `WeighData` as a closure +#[allow(deprecated)] impl WeighData for FunctionOf where WD : Fn(Args) -> Weight { @@ -288,6 +447,7 @@ impl WeighData for FunctionOf where } // `ClassifyDispatch` as a raw value +#[allow(deprecated)] impl ClassifyDispatch for FunctionOf { fn classify_dispatch(&self, _: Args) -> DispatchClass { self.1 @@ -295,6 +455,7 @@ impl ClassifyDispatch for FunctionOf } // `ClassifyDispatch` as a raw value +#[allow(deprecated)] impl ClassifyDispatch for FunctionOf where CD : Fn(Args) -> DispatchClass { @@ -304,17 +465,19 @@ impl ClassifyDispatch for FunctionOf where } // `PaysFee` as a raw value -impl PaysFee for FunctionOf { - fn pays_fee(&self, _: Args) -> bool { +#[allow(deprecated)] +impl PaysFee for FunctionOf { + fn pays_fee(&self, _: Args) -> Pays { self.2 } } // `PaysFee` as a closure +#[allow(deprecated)] impl PaysFee for FunctionOf where - PF : Fn(Args) -> bool + PF : Fn(Args) -> Pays { - fn pays_fee(&self, args: Args) -> bool { + fn pays_fee(&self, args: Args) -> Pays { (self.2)(args) } } @@ -349,51 +512,298 @@ impl GetDispatchInfo for sp_runtime::testing::TestX // for testing: weight == size. DispatchInfo { weight: self.encode().len() as _, - pays_fee: true, + pays_fee: Pays::Yes, ..Default::default() } } } +/// The weight of database operations that the runtime can invoke. +#[derive(Clone, Copy, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode)] +pub struct RuntimeDbWeight { + pub read: Weight, + pub write: Weight, +} + +impl RuntimeDbWeight { + pub fn reads(self, r: Weight) -> Weight { + self.read.saturating_mul(r) + } + + pub fn writes(self, w: Weight) -> Weight { + self.write.saturating_mul(w) + } + + pub fn reads_writes(self, r: Weight, w: Weight) -> Weight { + let read_weight = self.read.saturating_mul(r); + let write_weight = self.write.saturating_mul(w); + read_weight.saturating_add(write_weight) + } +} + +/// One coefficient and its position in the `WeightToFeePolynomial`. +/// +/// One term of polynomial is calculated as: +/// +/// ```ignore +/// coeff_integer * x^(degree) + coeff_frac * x^(degree) +/// ``` +/// +/// The `negative` value encodes whether the term is added or substracted from the +/// overall polynomial result. +#[derive(Clone, Encode, Decode)] +pub struct WeightToFeeCoefficient { + /// The integral part of the coefficient. + pub coeff_integer: Balance, + /// The fractional part of the coefficient. + pub coeff_frac: Perbill, + /// True iff the coefficient should be interpreted as negative. + pub negative: bool, + /// Degree/exponent of the term. + pub degree: u8, +} + +/// A list of coefficients that represent one polynomial. +pub type WeightToFeeCoefficients = SmallVec<[WeightToFeeCoefficient; 4]>; + +/// A trait that describes the weight to fee calculation as polynomial. +/// +/// An implementor should only implement the `polynomial` function. +pub trait WeightToFeePolynomial { + /// The type that is returned as result from polynomial evaluation. + type Balance: BaseArithmetic + From + Copy + Unsigned; + + /// Returns a polynomial that describes the weight to fee conversion. + /// + /// This is the only function that should be manually implemented. Please note + /// that all calculation is done in the probably unsigned `Balance` type. This means + /// that the order of coefficients is important as putting the negative coefficients + /// first will most likely saturate the result to zero mid evaluation. + fn polynomial() -> WeightToFeeCoefficients; + + /// Calculates the fee from the passed `weight` according to the `polynomial`. + /// + /// This should not be overriden in most circumstances. Calculation is done in the + /// `Balance` type and never overflows. All evaluation is saturating. + fn calc(weight: &Weight) -> Self::Balance { + Self::polynomial().iter().fold(Self::Balance::saturated_from(0u32), |mut acc, args| { + let w = Self::Balance::saturated_from(*weight).saturating_pow(args.degree.into()); + + // The sum could get negative. Therefore we only sum with the accumulator. + // The Perbill Mul implementation is non overflowing. + let frac = args.coeff_frac * w; + let integer = args.coeff_integer.saturating_mul(w); + + if args.negative { + acc = acc.saturating_sub(frac); + acc = acc.saturating_sub(integer); + } else { + acc = acc.saturating_add(frac); + acc = acc.saturating_add(integer); + } + + acc + }) + } +} + +/// Implementor of `WeightToFeePolynomial` that maps one unit of weight to one unit of fee. +pub struct IdentityFee(sp_std::marker::PhantomData); + +impl WeightToFeePolynomial for IdentityFee where + T: BaseArithmetic + From + Copy + Unsigned +{ + type Balance = T; + + fn polynomial() -> WeightToFeeCoefficients { + smallvec!(WeightToFeeCoefficient { + coeff_integer: 1u32.into(), + coeff_frac: Perbill::zero(), + negative: false, + degree: 1, + }) + } +} + #[cfg(test)] #[allow(dead_code)] mod tests { - use crate::decl_module; + use crate::{decl_module, parameter_types, traits::Get}; use super::*; pub trait Trait { type Origin; type Balance; type BlockNumber; + type DbWeight: Get; } pub struct TraitImpl {} + parameter_types! { + pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { + read: 100, + write: 1000, + }; + } + impl Trait for TraitImpl { type Origin = u32; type BlockNumber = u32; type Balance = u32; + type DbWeight = DbWeight; } decl_module! { pub struct Module for enum Call where origin: T::Origin { // no arguments, fixed weight - #[weight = SimpleDispatchInfo::FixedNormal(1000)] - fn f0(_origin) { unimplemented!(); } + #[weight = 1000] + fn f00(_origin) { unimplemented!(); } + + #[weight = (1000, DispatchClass::Mandatory)] + fn f01(_origin) { unimplemented!(); } + + #[weight = (1000, Pays::No)] + fn f02(_origin) { unimplemented!(); } + + #[weight = (1000, DispatchClass::Operational, Pays::No)] + fn f03(_origin) { unimplemented!(); } // weight = a x 10 + b - #[weight = FunctionOf(|args: (&u32, &u32)| args.0 * 10 + args.1, DispatchClass::Normal, true)] + #[weight = ((_a * 10 + _eb * 1) as Weight, DispatchClass::Normal, Pays::Yes)] fn f11(_origin, _a: u32, _eb: u32) { unimplemented!(); } - #[weight = FunctionOf(|_: (&u32, &u32)| 0, DispatchClass::Operational, true)] + #[weight = (0, DispatchClass::Operational, Pays::Yes)] fn f12(_origin, _a: u32, _eb: u32) { unimplemented!(); } + + #[weight = T::DbWeight::get().reads(3) + T::DbWeight::get().writes(2) + 10_000] + fn f2(_origin) { unimplemented!(); } + + #[weight = T::DbWeight::get().reads_writes(6, 5) + 40_000] + fn f21(_origin) { unimplemented!(); } + } } #[test] fn weights_are_correct() { + // #[weight = 1000] + let info = Call::::f00().get_dispatch_info(); + assert_eq!(info.weight, 1000); + assert_eq!(info.class, DispatchClass::Normal); + assert_eq!(info.pays_fee, Pays::Yes); + + // #[weight = (1000, DispatchClass::Mandatory)] + let info = Call::::f01().get_dispatch_info(); + assert_eq!(info.weight, 1000); + assert_eq!(info.class, DispatchClass::Mandatory); + assert_eq!(info.pays_fee, Pays::Yes); + + // #[weight = (1000, Pays::No)] + let info = Call::::f02().get_dispatch_info(); + assert_eq!(info.weight, 1000); + assert_eq!(info.class, DispatchClass::Normal); + assert_eq!(info.pays_fee, Pays::No); + + // #[weight = (1000, DispatchClass::Operational, Pays::No)] + let info = Call::::f03().get_dispatch_info(); + assert_eq!(info.weight, 1000); + assert_eq!(info.class, DispatchClass::Operational); + assert_eq!(info.pays_fee, Pays::No); + assert_eq!(Call::::f11(10, 20).get_dispatch_info().weight, 120); assert_eq!(Call::::f11(10, 20).get_dispatch_info().class, DispatchClass::Normal); - assert_eq!(Call::::f0().get_dispatch_info().weight, 1000); + assert_eq!(Call::::f12(10, 20).get_dispatch_info().weight, 0); + assert_eq!(Call::::f12(10, 20).get_dispatch_info().class, DispatchClass::Operational); + assert_eq!(Call::::f2().get_dispatch_info().weight, 12300); + assert_eq!(Call::::f21().get_dispatch_info().weight, 45600); + assert_eq!(Call::::f2().get_dispatch_info().class, DispatchClass::Normal); + } + + #[test] + fn extract_actual_weight_works() { + let pre = DispatchInfo { + weight: 1000, + .. Default::default() + }; + assert_eq!(extract_actual_weight(&Ok(Some(7).into()), &pre), 7); + assert_eq!(extract_actual_weight(&Ok(Some(1000).into()), &pre), 1000); + assert_eq!( + extract_actual_weight(&Err(DispatchError::BadOrigin.with_weight(9)), &pre), + 9 + ); + } + + #[test] + fn extract_actual_weight_caps_at_pre_weight() { + let pre = DispatchInfo { + weight: 1000, + .. Default::default() + }; + assert_eq!(extract_actual_weight(&Ok(Some(1250).into()), &pre), 1000); + assert_eq!( + extract_actual_weight(&Err(DispatchError::BadOrigin.with_weight(1300)), &pre), + 1000 + ); + } + + type Balance = u64; + + // 0.5x^3 + 2.333x2 + 7x - 10_000 + struct Poly; + impl WeightToFeePolynomial for Poly { + type Balance = Balance; + + fn polynomial() -> WeightToFeeCoefficients { + smallvec![ + WeightToFeeCoefficient { + coeff_integer: 0, + coeff_frac: Perbill::from_fraction(0.5), + negative: false, + degree: 3 + }, + WeightToFeeCoefficient { + coeff_integer: 2, + coeff_frac: Perbill::from_rational_approximation(1u32, 3u32), + negative: false, + degree: 2 + }, + WeightToFeeCoefficient { + coeff_integer: 7, + coeff_frac: Perbill::zero(), + negative: false, + degree: 1 + }, + WeightToFeeCoefficient { + coeff_integer: 10_000, + coeff_frac: Perbill::zero(), + negative: true, + degree: 0 + }, + ] + } + } + + #[test] + fn polynomial_works() { + assert_eq!(Poly::calc(&100), 514033); + assert_eq!(Poly::calc(&10_123), 518917034928); + } + + #[test] + fn polynomial_does_not_underflow() { + assert_eq!(Poly::calc(&0), 0); + } + + #[test] + fn polynomial_does_not_overflow() { + assert_eq!(Poly::calc(&Weight::max_value()), Balance::max_value() - 10_000); + } + + #[test] + fn identity_fee_works() { + assert_eq!(IdentityFee::::calc(&0), 0); + assert_eq!(IdentityFee::::calc(&50), 50); + assert_eq!(IdentityFee::::calc(&Weight::max_value()), Balance::max_value()); } } diff --git a/frame/support/test/Cargo.toml b/frame/support/test/Cargo.toml index 773523579b0b4ce8d580e5e80aad796591947fdf..682001564bda22987412e6e2768ac15f383be105 100644 --- a/frame/support/test/Cargo.toml +++ b/frame/support/test/Cargo.toml @@ -1,24 +1,29 @@ [package] name = "frame-support-test" -version = "2.0.0-dev" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" publish = false homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", default-features = false, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-io ={ path = "../../../primitives/io", default-features = false , version = "2.0.0-alpha.5"} -sp-state-machine = { version = "0.8.0-alpha.5", optional = true, path = "../../../primitives/state-machine" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../" } -sp-inherents = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/inherents" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/runtime" } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/core" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-io ={ version = "2.0.0-rc4", path = "../../../primitives/io", default-features = false } +sp-state-machine = { version = "0.8.0-rc4", optional = true, path = "../../../primitives/state-machine" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../" } +sp-inherents = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/inherents" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/runtime" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/core" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/std" } trybuild = "1.0.17" pretty_assertions = "0.6.1" +rustversion = "1.0.0" [features] default = ["std"] @@ -29,9 +34,7 @@ std = [ "frame-support/std", "sp-inherents/std", "sp-core/std", + "sp-std/std", "sp-runtime/std", "sp-state-machine", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/support/test/src/lib.rs b/frame/support/test/src/lib.rs index f62f5522680ebd724ed991f4ec2074a308df6c1b..c0baf448eed850511b2cdc33e307d6758739da8f 100644 --- a/frame/support/test/src/lib.rs +++ b/frame/support/test/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test crate for frame_support. Allow to make use of `frame_support::decl_storage`. //! See tests directory. diff --git a/frame/support/test/tests/decl_error.rs b/frame/support/test/tests/construct_runtime.rs similarity index 70% rename from frame/support/test/tests/decl_error.rs rename to frame/support/test/tests/construct_runtime.rs index 4191e79f2417ca59d118e0265094fa4e9a5b8782..10fc3319fb080fb34d70fd0dcddc3b991c4290ff 100644 --- a/frame/support/test/tests/decl_error.rs +++ b/frame/support/test/tests/construct_runtime.rs @@ -1,28 +1,38 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! General tests for construct_runtime macro, test for: +//! * error declareed with decl_error works +//! * integrity test is generated #![recursion_limit="128"] use sp_runtime::{generic, traits::{BlakeTwo256, Block as _, Verify}, DispatchError}; use sp_core::{H256, sr25519}; +use sp_std::cell::RefCell; mod system; pub trait Currency {} +thread_local! { + pub static INTEGRITY_TEST_EXEC: RefCell = RefCell::new(0); +} + mod module1 { use super::*; @@ -32,7 +42,7 @@ mod module1 { pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: ::Origin { - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] pub fn fail(_origin) -> frame_support::dispatch::DispatchResult { Err(Error::::Something.into()) } @@ -59,10 +69,14 @@ mod module2 { pub struct Module for enum Call where origin: ::Origin { - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] pub fn fail(_origin) -> frame_support::dispatch::DispatchResult { Err(Error::::Something.into()) } + + fn integrity_test() { + INTEGRITY_TEST_EXEC.with(|i| *i.borrow_mut() += 1); + } } } @@ -87,12 +101,14 @@ pub type BlockNumber = u64; pub type Index = u64; impl system::Trait for Runtime { + type BaseCallFilter = (); type Hash = H256; type Origin = Origin; type BlockNumber = BlockNumber; type AccountId = AccountId; type Event = Event; type ModuleToIndex = ModuleToIndex; + type Call = Call; } frame_support::construct_runtime!( @@ -135,3 +151,9 @@ fn check_module2_error_type() { Err(DispatchError::Module { index: 2, error: 0, message: Some("Something") }), ); } + +#[test] +fn integrity_test_works() { + __construct_runtime_integrity_test::runtime_integrity_tests(); + assert_eq!(INTEGRITY_TEST_EXEC.with(|i| *i.borrow()), 1); +} diff --git a/frame/support/test/tests/construct_runtime_ui.rs b/frame/support/test/tests/construct_runtime_ui.rs index acddf01f037a665fd1c03a4e1643ebf1298168ac..e1624c76830ae21849cd8dd6329476c779569bd6 100644 --- a/frame/support/test/tests/construct_runtime_ui.rs +++ b/frame/support/test/tests/construct_runtime_ui.rs @@ -1,5 +1,23 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use 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/frame/support/test/tests/construct_runtime_ui/missing_system_module.stderr b/frame/support/test/tests/construct_runtime_ui/missing_system_module.stderr index 442af9c01fa3469901f097055d01a120b0f630c7..2ebe0721eb381b54514a3f96445b10b335c350f9 100644 --- a/frame/support/test/tests/construct_runtime_ui/missing_system_module.stderr +++ b/frame/support/test/tests/construct_runtime_ui/missing_system_module.stderr @@ -1,4 +1,4 @@ -error: `System` module declaration is missing. Please add this line: `System: system::{Module, Call, Storage, Config, Event},` +error: `System` module declaration is missing. Please add this line: `System: frame_system::{Module, Call, Storage, Config, Event},` --> $DIR/missing_system_module.rs:8:2 | 8 | { diff --git a/frame/support/test/tests/construct_runtime_ui/params_in_invalid_module.rs b/frame/support/test/tests/construct_runtime_ui/params_in_invalid_module.rs deleted file mode 100644 index 9c752a2f39e2ad70f3acb2cd976abfcedf6455b8..0000000000000000000000000000000000000000 --- a/frame/support/test/tests/construct_runtime_ui/params_in_invalid_module.rs +++ /dev/null @@ -1,14 +0,0 @@ -use frame_support::construct_runtime; - -construct_runtime! { - pub enum Runtime where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic - { - System: system::{Module}, - Balance: balances::::{Call(toto), Origin}, - } -} - -fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/params_in_invalid_module.stderr b/frame/support/test/tests/construct_runtime_ui/params_in_invalid_module.stderr deleted file mode 100644 index 58f35720e31f739fb23eb3a50d7a09d970d7df05..0000000000000000000000000000000000000000 --- a/frame/support/test/tests/construct_runtime_ui/params_in_invalid_module.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: `Call` is not allowed to have arguments in parens. Only the following modules are allowed to have arguments in parens: `Inherent`. - --> $DIR/params_in_invalid_module.rs:10:40 - | -10 | Balance: balances::::{Call(toto), Origin}, - | ^^^^^^ diff --git a/frame/support/test/tests/decl_module_ui.rs b/frame/support/test/tests/decl_module_ui.rs new file mode 100644 index 0000000000000000000000000000000000000000..90d105e7cfae31a795125484bc4ce1012556e401 --- /dev/null +++ b/frame/support/test/tests/decl_module_ui.rs @@ -0,0 +1,26 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//#[rustversion::attr(not(stable), ignore)] +#[test] +fn decl_module_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_module_ui/*.rs"); +} diff --git a/frame/support/test/tests/decl_module_ui/reserved_keyword_two_times_integrity_test.rs b/frame/support/test/tests/decl_module_ui/reserved_keyword_two_times_integrity_test.rs new file mode 100644 index 0000000000000000000000000000000000000000..4dbae05f07ff77869d3f7c6367079138d7cbf73f --- /dev/null +++ b/frame/support/test/tests/decl_module_ui/reserved_keyword_two_times_integrity_test.rs @@ -0,0 +1,7 @@ +frame_support::decl_module! { + pub struct Module for enum Call where origin: T::Origin { + fn integrity_test() {} + + fn integrity_test() {} + } +} diff --git a/frame/support/test/tests/decl_module_ui/reserved_keyword_two_times_integrity_test.stderr b/frame/support/test/tests/decl_module_ui/reserved_keyword_two_times_integrity_test.stderr new file mode 100644 index 0000000000000000000000000000000000000000..d6498961d31c8006ec5f37218f9ff16b19fc80e4 --- /dev/null +++ b/frame/support/test/tests/decl_module_ui/reserved_keyword_two_times_integrity_test.stderr @@ -0,0 +1,25 @@ +error: `integrity_test` can only be passed once as input. + --> $DIR/reserved_keyword_two_times_integrity_test.rs:1:1 + | +1 | / frame_support::decl_module! { +2 | | pub struct Module for enum Call where origin: T::Origin { +3 | | fn integrity_test() {} +4 | | +5 | | fn integrity_test() {} +6 | | } +7 | | } + | |_^ + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0601]: `main` function not found in crate `$CRATE` + --> $DIR/reserved_keyword_two_times_integrity_test.rs:1:1 + | +1 | / frame_support::decl_module! { +2 | | pub struct Module for enum Call where origin: T::Origin { +3 | | fn integrity_test() {} +4 | | +5 | | fn integrity_test() {} +6 | | } +7 | | } + | |_^ consider adding a `main` function to `$DIR/tests/decl_module_ui/reserved_keyword_two_times_integrity_test.rs` diff --git a/frame/support/test/tests/decl_module_ui/reserved_keyword_two_times_on_initialize.rs b/frame/support/test/tests/decl_module_ui/reserved_keyword_two_times_on_initialize.rs new file mode 100644 index 0000000000000000000000000000000000000000..4f05134997e81e380010ff74a462c81f8833ac4d --- /dev/null +++ b/frame/support/test/tests/decl_module_ui/reserved_keyword_two_times_on_initialize.rs @@ -0,0 +1,11 @@ +frame_support::decl_module! { + pub struct Module for enum Call where origin: T::Origin { + fn on_initialize() -> Weight { + 0 + } + + fn on_initialize() -> Weight { + 0 + } + } +} diff --git a/frame/support/test/tests/decl_module_ui/reserved_keyword_two_times_on_initialize.stderr b/frame/support/test/tests/decl_module_ui/reserved_keyword_two_times_on_initialize.stderr new file mode 100644 index 0000000000000000000000000000000000000000..8a9f025046b7ee57323afd3c6faa0b2c6d5cda43 --- /dev/null +++ b/frame/support/test/tests/decl_module_ui/reserved_keyword_two_times_on_initialize.stderr @@ -0,0 +1,25 @@ +error: `on_initialize` can only be passed once as input. + --> $DIR/reserved_keyword_two_times_on_initialize.rs:1:1 + | +1 | / frame_support::decl_module! { +2 | | pub struct Module for enum Call where origin: T::Origin { +3 | | fn on_initialize() -> Weight { +4 | | 0 +... | +10 | | } +11 | | } + | |_^ + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0601]: `main` function not found in crate `$CRATE` + --> $DIR/reserved_keyword_two_times_on_initialize.rs:1:1 + | +1 | / frame_support::decl_module! { +2 | | pub struct Module for enum Call where origin: T::Origin { +3 | | fn on_initialize() -> Weight { +4 | | 0 +... | +10 | | } +11 | | } + | |_^ consider adding a `main` function to `$DIR/tests/decl_module_ui/reserved_keyword_two_times_on_initialize.rs` diff --git a/frame/support/test/tests/decl_storage.rs b/frame/support/test/tests/decl_storage.rs index ea9b09f9d7bc2c9001b70232facbb69d43270cc0..cda1d810d225ca55cfed587cc9322cf47566c999 100644 --- a/frame/support/test/tests/decl_storage.rs +++ b/frame/support/test/tests/decl_storage.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #[cfg(test)] // Do not complain about unused `dispatch` and `dispatch_aux`. @@ -526,47 +527,55 @@ mod test_append_and_len { #[test] fn append_works() { TestExternalities::default().execute_with(|| { - let _ = MapVec::append(1, [1, 2, 3].iter()); - let _ = MapVec::append(1, [4, 5].iter()); + for val in &[1, 2, 3, 4, 5] { + MapVec::append(1, val); + } assert_eq!(MapVec::get(1), vec![1, 2, 3, 4, 5]); - let _ = JustVec::append([1, 2, 3].iter()); - let _ = JustVec::append([4, 5].iter()); + MapVec::remove(1); + MapVec::append(1, 1); + assert_eq!(MapVec::get(1), vec![1]); + + for val in &[1, 2, 3, 4, 5] { + JustVec::append(val); + } assert_eq!(JustVec::get(), vec![1, 2, 3, 4, 5]); + + JustVec::kill(); + JustVec::append(1); + assert_eq!(JustVec::get(), vec![1]); }); } #[test] - fn append_works_for_default() { + fn append_overwrites_invalid_data() { 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])); + let key = JustVec::hashed_key(); + // Set it to some invalid value. + frame_support::storage::unhashed::put_raw(&key, &*b"1"); + assert_eq!(JustVec::get(), Vec::new()); + assert_eq!(frame_support::storage::unhashed::get_raw(&key), Some(b"1".to_vec())); + + JustVec::append(1); + JustVec::append(2); + assert_eq!(JustVec::get(), vec![1, 2]); }); } #[test] - fn append_or_put_works() { + fn append_overwrites_default() { 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]); + assert_eq!(JustVecWithDefault::get(), vec![6, 9]); + JustVecWithDefault::append(1); + assert_eq!(JustVecWithDefault::get(), vec![1]); - 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]); + assert_eq!(MapVecWithDefault::get(0), vec![6, 9]); + MapVecWithDefault::append(0, 1); + assert_eq!(MapVecWithDefault::get(0), vec![1]); - 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])); + assert_eq!(OptionVec::get(), None); + OptionVec::append(1); + assert_eq!(OptionVec::get(), Some(vec![1])); }); } @@ -585,38 +594,40 @@ mod test_append_and_len { }); } + // `decode_len` should always return `None` for default assigments + // in `decl_storage!`. #[test] - fn len_works_for_default() { + fn len_works_ignores_default_assignment() { TestExternalities::default().execute_with(|| { // vec assert_eq!(JustVec::get(), vec![]); - assert_eq!(JustVec::decode_len(), Ok(0)); + assert_eq!(JustVec::decode_len(), None); assert_eq!(JustVecWithDefault::get(), vec![6, 9]); - assert_eq!(JustVecWithDefault::decode_len(), Ok(2)); + assert_eq!(JustVecWithDefault::decode_len(), None); assert_eq!(OptionVec::get(), None); - assert_eq!(OptionVec::decode_len(), Ok(0)); + assert_eq!(OptionVec::decode_len(), None); // map assert_eq!(MapVec::get(0), vec![]); - assert_eq!(MapVec::decode_len(0), Ok(0)); + assert_eq!(MapVec::decode_len(0), None); assert_eq!(MapVecWithDefault::get(0), vec![6, 9]); - assert_eq!(MapVecWithDefault::decode_len(0), Ok(2)); + assert_eq!(MapVecWithDefault::decode_len(0), None); assert_eq!(OptionMapVec::get(0), None); - assert_eq!(OptionMapVec::decode_len(0), Ok(0)); + assert_eq!(OptionMapVec::decode_len(0), None); // Double map assert_eq!(DoubleMapVec::get(0, 0), vec![]); - assert_eq!(DoubleMapVec::decode_len(0, 1), Ok(0)); + assert_eq!(DoubleMapVec::decode_len(0, 1), None); assert_eq!(DoubleMapVecWithDefault::get(0, 0), vec![6, 9]); - assert_eq!(DoubleMapVecWithDefault::decode_len(0, 1), Ok(2)); + assert_eq!(DoubleMapVecWithDefault::decode_len(0, 1), None); assert_eq!(OptionDoubleMapVec::get(0, 0), None); - assert_eq!(OptionDoubleMapVec::decode_len(0, 1), Ok(0)); + assert_eq!(OptionDoubleMapVec::decode_len(0, 1), None); }); } } diff --git a/frame/support/test/tests/decl_storage_ui.rs b/frame/support/test/tests/decl_storage_ui.rs index 3aee5e98664131ee4d7f257016c601e10fe0f00d..d771b6e0eef83cd048a3decdd0d953a2f415f78d 100644 --- a/frame/support/test/tests/decl_storage_ui.rs +++ b/frame/support/test/tests/decl_storage_ui.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #[test] fn decl_storage_ui() { diff --git a/frame/support/test/tests/decl_storage_ui/config_duplicate.rs b/frame/support/test/tests/decl_storage_ui/config_duplicate.rs index 0f2759e740d7ddb81fc2edf244dab3b7422dd8c1..4d510da9f893652be1381babff9fe09980baf753 100644 --- a/frame/support/test/tests/decl_storage_ui/config_duplicate.rs +++ b/frame/support/test/tests/decl_storage_ui/config_duplicate.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. pub trait Trait { type Origin; diff --git a/frame/support/test/tests/decl_storage_ui/config_duplicate.stderr b/frame/support/test/tests/decl_storage_ui/config_duplicate.stderr index 761e3f3b7982492444854ec669094eb948f0c409..61f7c0bbe64a5ae48c4353a069953a34b675b633 100644 --- a/frame/support/test/tests/decl_storage_ui/config_duplicate.stderr +++ b/frame/support/test/tests/decl_storage_ui/config_duplicate.stderr @@ -1,5 +1,5 @@ error: `config()`/`get()` with the same name already defined. - --> $DIR/config_duplicate.rs:29:21 + --> $DIR/config_duplicate.rs:30:21 | -29 | pub Value2 config(value): u32; +30 | pub Value2 config(value): u32; | ^^^^^ diff --git a/frame/support/test/tests/decl_storage_ui/config_get_duplicate.rs b/frame/support/test/tests/decl_storage_ui/config_get_duplicate.rs index a4e0158d5c5c50733905c8c8795f72416512c878..49897e625186855c41b1848036116df058a9d146 100644 --- a/frame/support/test/tests/decl_storage_ui/config_get_duplicate.rs +++ b/frame/support/test/tests/decl_storage_ui/config_get_duplicate.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. pub trait Trait { type Origin; diff --git a/frame/support/test/tests/decl_storage_ui/config_get_duplicate.stderr b/frame/support/test/tests/decl_storage_ui/config_get_duplicate.stderr index 34d040f4e14f19a8fbfc1e904675ec6dacc5e963..02e7d41080339069a9a20224d7bf4baad2ff86e5 100644 --- a/frame/support/test/tests/decl_storage_ui/config_get_duplicate.stderr +++ b/frame/support/test/tests/decl_storage_ui/config_get_duplicate.stderr @@ -1,5 +1,5 @@ error: `config()`/`get()` with the same name already defined. - --> $DIR/config_get_duplicate.rs:29:21 + --> $DIR/config_get_duplicate.rs:30:21 | -29 | pub Value2 config(value): u32; +30 | pub Value2 config(value): u32; | ^^^^^ diff --git a/frame/support/test/tests/decl_storage_ui/get_duplicate.rs b/frame/support/test/tests/decl_storage_ui/get_duplicate.rs index 9edbc25bf9d8327ae36339cb1d595b8713fdb572..2fa78f4d17c562d6aa3817fb3fd58cb4a1d9d6d2 100644 --- a/frame/support/test/tests/decl_storage_ui/get_duplicate.rs +++ b/frame/support/test/tests/decl_storage_ui/get_duplicate.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. pub trait Trait { type Origin; diff --git a/frame/support/test/tests/decl_storage_ui/get_duplicate.stderr b/frame/support/test/tests/decl_storage_ui/get_duplicate.stderr index 130244196f67e03bb40de703fbb127d7bdecbfc8..d9ce420a6f2143ac015c5a9aa33b5153954e1d94 100644 --- a/frame/support/test/tests/decl_storage_ui/get_duplicate.stderr +++ b/frame/support/test/tests/decl_storage_ui/get_duplicate.stderr @@ -1,5 +1,5 @@ error: `config()`/`get()` with the same name already defined. - --> $DIR/get_duplicate.rs:29:21 + --> $DIR/get_duplicate.rs:30:21 | -29 | pub Value2 get(fn value) config(): u32; +30 | pub Value2 get(fn value) config(): u32; | ^^^^^ diff --git a/frame/support/test/tests/final_keys.rs b/frame/support/test/tests/final_keys.rs index ae23c5a64c200af647f0cd4387495742026ccc6c..e88389ade772bf0c5189f47ff6521fbbb508dfa6 100644 --- a/frame/support/test/tests/final_keys.rs +++ b/frame/support/test/tests/final_keys.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use frame_support::storage::unhashed; use codec::Encode; diff --git a/frame/support/test/tests/genesisconfig.rs b/frame/support/test/tests/genesisconfig.rs index bccffb737476b47fa9b8ebdccfce88139fb9370d..78b841d29501728e8e2eac048e6f2b465f19034b 100644 --- a/frame/support/test/tests/genesisconfig.rs +++ b/frame/support/test/tests/genesisconfig.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. pub trait Trait { type BlockNumber: codec::Codec + codec::EncodeLike + Default; diff --git a/frame/support/test/tests/instance.rs b/frame/support/test/tests/instance.rs index ea5d32fea3b222b754331aff047d65782b671911..08389eed3aa838e8cd8f155fd200044e7edd041c 100644 --- a/frame/support/test/tests/instance.rs +++ b/frame/support/test/tests/instance.rs @@ -1,21 +1,23 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #![recursion_limit="128"] +use codec::{Codec, EncodeLike, Encode, Decode}; use sp_runtime::{generic, BuildStorage, traits::{BlakeTwo256, Block as _, Verify}}; use frame_support::{ Parameter, traits::Get, parameter_types, @@ -43,19 +45,20 @@ mod module1 { type Event: From> + Into<::Event>; type Origin: From>; type SomeParameter: Get; - type GenericType: Default + Clone + codec::Codec + codec::EncodeLike; + type GenericType: Default + Clone + Codec + EncodeLike; } frame_support::decl_module! { pub struct Module, I: InstantiableThing> for enum Call where origin: ::Origin, + system = system, T::BlockNumber: From { fn offchain_worker() {} fn deposit_event() = default; - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] fn one(origin) { system::ensure_root(origin)?; Self::deposit_event(RawEvent::AnotherVariant(3)); @@ -86,7 +89,7 @@ mod module1 { } } - #[derive(PartialEq, Eq, Clone, sp_runtime::RuntimeDebug)] + #[derive(PartialEq, Eq, Clone, sp_runtime::RuntimeDebug, Encode, Decode)] pub enum Origin, I> where T::BlockNumber: From { Members(u32), _Phantom(std::marker::PhantomData<(T, I)>), @@ -127,7 +130,8 @@ mod module2 { frame_support::decl_module! { pub struct Module, I: Instance=DefaultInstance> for enum Call where - origin: ::Origin + origin: ::Origin, + system = system { fn deposit_event() = default; } @@ -147,7 +151,7 @@ mod module2 { } } - #[derive(PartialEq, Eq, Clone, sp_runtime::RuntimeDebug)] + #[derive(PartialEq, Eq, Clone, sp_runtime::RuntimeDebug, Encode, Decode)] pub enum Origin, I=DefaultInstance> { Members(u32), _Phantom(std::marker::PhantomData<(T, I)>), @@ -232,12 +236,14 @@ pub type BlockNumber = u64; pub type Index = u64; impl system::Trait for Runtime { + type BaseCallFilter= (); type Hash = H256; type Origin = Origin; type BlockNumber = BlockNumber; type AccountId = AccountId; type Event = Event; type ModuleToIndex = (); + type Call = Call; } frame_support::construct_runtime!( @@ -300,7 +306,7 @@ fn new_test_ext() -> sp_io::TestExternalities { fn storage_instance_independence() { let mut storage = sp_core::storage::Storage { top: std::collections::BTreeMap::new(), - children: std::collections::HashMap::new() + children_default: std::collections::HashMap::new() }; sp_state_machine::BasicExternalities::execute_with_storage(&mut storage, || { module2::Value::::put(0); diff --git a/frame/support/test/tests/issue2219.rs b/frame/support/test/tests/issue2219.rs index 8d8152a5ad0f35b7b2485acb13d49c56b2075392..7166f202c7325d2aed5a4a27ce1daaf08ad24398 100644 --- a/frame/support/test/tests/issue2219.rs +++ b/frame/support/test/tests/issue2219.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use frame_support::sp_runtime::generic; use frame_support::sp_runtime::traits::{BlakeTwo256, Block as _, Verify}; @@ -157,12 +158,14 @@ pub type Block = generic::Block; pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; impl system::Trait for Runtime { + type BaseCallFilter = (); type Hash = H256; type Origin = Origin; type BlockNumber = BlockNumber; type AccountId = AccountId; type Event = Event; type ModuleToIndex = (); + type Call = Call; } impl module::Trait for Runtime {} diff --git a/frame/support/test/tests/reserved_keyword.rs b/frame/support/test/tests/reserved_keyword.rs index d6cc4bba3b0b02e50d3a1c81e9c12a4c605043d0..382b2e498741fd6740dc7b1c94537706ce13ffac 100644 --- a/frame/support/test/tests/reserved_keyword.rs +++ b/frame/support/test/tests/reserved_keyword.rs @@ -1,19 +1,21 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#[rustversion::attr(not(stable), ignore)] #[test] fn reserved_keyword() { // As trybuild is using `cargo check`, we don't need the real WASM binaries. diff --git a/frame/support/test/tests/reserved_keyword/on_initialize.rs b/frame/support/test/tests/reserved_keyword/on_initialize.rs index 8eacc836c48685c1516ce129780c71f0ee636ea1..0751c600cccb2f67ceead54353818a8dd6aba514 100644 --- a/frame/support/test/tests/reserved_keyword/on_initialize.rs +++ b/frame/support/test/tests/reserved_keyword/on_initialize.rs @@ -19,7 +19,7 @@ macro_rules! reserved { frame_support::decl_module! { pub struct Module for enum Call where origin: T::Origin { - #[weight = frame_support::weights::SimpleDispatchInfo::default()] + #[weight = 0] fn $reserved(_origin) -> dispatch::DispatchResult { unreachable!() } } } diff --git a/frame/support/test/tests/reserved_keyword/on_initialize.stderr b/frame/support/test/tests/reserved_keyword/on_initialize.stderr index e899ef5d789426c620a9c92f7190a2ac5fdabd4f..dbe07195e89ddff6fbe0390a583cda4d553d13cb 100644 --- a/frame/support/test/tests/reserved_keyword/on_initialize.stderr +++ b/frame/support/test/tests/reserved_keyword/on_initialize.stderr @@ -2,38 +2,38 @@ error: Invalid call fn name: `on_finalize`, name is reserved and doesn't match e --> $DIR/on_initialize.rs:31:1 | 31 | reserved!(on_finalize on_initialize on_runtime_upgrade offchain_worker deposit_event); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: Invalid call fn name: `on_initialize`, 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. --> $DIR/on_initialize.rs:31:1 | 31 | reserved!(on_finalize on_initialize on_runtime_upgrade offchain_worker deposit_event); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: Invalid call fn name: `on_runtime_upgrade`, 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. --> $DIR/on_initialize.rs:31:1 | 31 | reserved!(on_finalize on_initialize on_runtime_upgrade offchain_worker deposit_event); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: Invalid call fn name: `offchain_worker`, 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. --> $DIR/on_initialize.rs:31:1 | 31 | reserved!(on_finalize on_initialize on_runtime_upgrade offchain_worker deposit_event); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro (in Nightly builds, run with -Z 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. --> $DIR/on_initialize.rs:31:1 | 31 | reserved!(on_finalize on_initialize on_runtime_upgrade offchain_worker deposit_event); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/frame/support/test/tests/storage_transaction.rs b/frame/support/test/tests/storage_transaction.rs new file mode 100644 index 0000000000000000000000000000000000000000..bf6c70966b469ebc0d0e64ab2a231a8d6c319d32 --- /dev/null +++ b/frame/support/test/tests/storage_transaction.rs @@ -0,0 +1,159 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use codec::{Encode, Decode, EncodeLike}; +use frame_support::{ + StorageMap, StorageValue, storage::{with_transaction, TransactionOutcome::*}, +}; +use sp_io::TestExternalities; + +pub trait Trait { + type Origin; + type BlockNumber: Encode + Decode + EncodeLike + Default + Clone; +} + +frame_support::decl_module! { + pub struct Module for enum Call where origin: T::Origin {} +} + +frame_support::decl_storage!{ + trait Store for Module as StorageTransactions { + pub Value: u32; + pub Map: map hasher(twox_64_concat) String => u32; + } +} + + +#[test] +fn storage_transaction_basic_commit() { + TestExternalities::default().execute_with(|| { + + assert_eq!(Value::get(), 0); + assert!(!Map::contains_key("val0")); + + with_transaction(|| { + Value::set(99); + Map::insert("val0", 99); + assert_eq!(Value::get(), 99); + assert_eq!(Map::get("val0"), 99); + Commit(()) + }); + + assert_eq!(Value::get(), 99); + assert_eq!(Map::get("val0"), 99); + }); +} + +#[test] +fn storage_transaction_basic_rollback() { + TestExternalities::default().execute_with(|| { + + assert_eq!(Value::get(), 0); + assert_eq!(Map::get("val0"), 0); + + with_transaction(|| { + Value::set(99); + Map::insert("val0", 99); + assert_eq!(Value::get(), 99); + assert_eq!(Map::get("val0"), 99); + Rollback(()) + }); + + assert_eq!(Value::get(), 0); + assert_eq!(Map::get("val0"), 0); + }); +} + +#[test] +fn storage_transaction_rollback_then_commit() { + TestExternalities::default().execute_with(|| { + Value::set(1); + Map::insert("val1", 1); + + with_transaction(|| { + Value::set(2); + Map::insert("val1", 2); + Map::insert("val2", 2); + + with_transaction(|| { + Value::set(3); + Map::insert("val1", 3); + Map::insert("val2", 3); + Map::insert("val3", 3); + + assert_eq!(Value::get(), 3); + assert_eq!(Map::get("val1"), 3); + assert_eq!(Map::get("val2"), 3); + assert_eq!(Map::get("val3"), 3); + + Rollback(()) + }); + + assert_eq!(Value::get(), 2); + assert_eq!(Map::get("val1"), 2); + assert_eq!(Map::get("val2"), 2); + assert_eq!(Map::get("val3"), 0); + + Commit(()) + }); + + assert_eq!(Value::get(), 2); + assert_eq!(Map::get("val1"), 2); + assert_eq!(Map::get("val2"), 2); + assert_eq!(Map::get("val3"), 0); + }); +} + +#[test] +fn storage_transaction_commit_then_rollback() { + TestExternalities::default().execute_with(|| { + Value::set(1); + Map::insert("val1", 1); + + with_transaction(|| { + Value::set(2); + Map::insert("val1", 2); + Map::insert("val2", 2); + + with_transaction(|| { + Value::set(3); + Map::insert("val1", 3); + Map::insert("val2", 3); + Map::insert("val3", 3); + + assert_eq!(Value::get(), 3); + assert_eq!(Map::get("val1"), 3); + assert_eq!(Map::get("val2"), 3); + assert_eq!(Map::get("val3"), 3); + + Commit(()) + }); + + assert_eq!(Value::get(), 3); + assert_eq!(Map::get("val1"), 3); + assert_eq!(Map::get("val2"), 3); + assert_eq!(Map::get("val3"), 3); + + Rollback(()) + }); + + assert_eq!(Value::get(), 1); + assert_eq!(Map::get("val1"), 1); + assert_eq!(Map::get("val2"), 0); + assert_eq!(Map::get("val3"), 0); + }); +} diff --git a/frame/support/test/tests/system.rs b/frame/support/test/tests/system.rs index c7f60117bc526ec4e96745c9f74379e913b43316..8ca2e97789d549c85f6ce013f1550f8d121eef41 100644 --- a/frame/support/test/tests/system.rs +++ b/frame/support/test/tests/system.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use frame_support::codec::{Encode, Decode, EncodeLike}; @@ -20,15 +21,17 @@ pub trait Trait: 'static + Eq + Clone { type Origin: Into, Self::Origin>> + From>; + type BaseCallFilter: frame_support::traits::Filter; type BlockNumber: Decode + Encode + EncodeLike + Clone + Default; type Hash; type AccountId: Encode + EncodeLike + Decode; + type Call; type Event: From>; type ModuleToIndex: frame_support::traits::ModuleToIndex; } frame_support::decl_module! { - pub struct Module for enum Call where origin: T::Origin {} + pub struct Module for enum Call where origin: T::Origin, {} } impl Module { @@ -54,7 +57,7 @@ frame_support::decl_error! { } /// Origin for the system module. -#[derive(PartialEq, Eq, Clone, sp_runtime::RuntimeDebug)] +#[derive(PartialEq, Eq, Clone, sp_runtime::RuntimeDebug, Encode, Decode)] pub enum RawOrigin { Root, Signed(AccountId), diff --git a/frame/system/Cargo.toml b/frame/system/Cargo.toml index 78288cff917e233306fe0bee01f5a04d96263f16..2173ea8cee445719d9f53cb1f2c33b34c41e01bf 100644 --- a/frame/system/Cargo.toml +++ b/frame/system/Cargo.toml @@ -1,28 +1,31 @@ [package] name = "frame-system" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME system module" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/core" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-io = { path = "../../primitives/io", default-features = false, version = "2.0.0-alpha.5"} -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -sp-version = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/version" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/core" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc4", path = "../../primitives/io", default-features = false } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +sp-version = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/version" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } impl-trait-for-tuples = "0.1.3" [dev-dependencies] criterion = "0.2.11" -sp-externalities = { version = "0.8.0-alpha.5", path = "../../primitives/externalities" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../test-utils/runtime/client" } +sp-externalities = { version = "0.8.0-rc4", path = "../../primitives/externalities" } +substrate-test-runtime-client = { version = "2.0.0-rc4", path = "../../test-utils/runtime/client" } [features] default = ["std"] @@ -36,11 +39,11 @@ std = [ "sp-runtime/std", "sp-version/std", ] -runtime-benchmarks = ["sp-runtime/runtime-benchmarks"] +runtime-benchmarks = [ + "sp-runtime/runtime-benchmarks", + "frame-support/runtime-benchmarks", +] [[bench]] name = "bench" harness = false - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/system/benches/bench.rs b/frame/system/benches/bench.rs index 90a4ad1d34de80c7991a7a87fb3fb480e1945cd1..1b64b813e59101f8b187697f7c25082be764f585 100644 --- a/frame/system/benches/bench.rs +++ b/frame/system/benches/bench.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use criterion::{Criterion, criterion_group, criterion_main, black_box}; use frame_system as system; @@ -60,6 +61,7 @@ frame_support::parameter_types! { #[derive(Clone, Eq, PartialEq)] pub struct Runtime; impl system::Trait for Runtime { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -72,6 +74,10 @@ impl system::Trait for Runtime { type Event = Event; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -79,6 +85,7 @@ impl system::Trait for Runtime { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } impl module::Trait for Runtime { diff --git a/frame/system/benchmarking/Cargo.toml b/frame/system/benchmarking/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..c278bad150eae6a9c5a3c5c1aa3c8ce57285a798 --- /dev/null +++ b/frame/system/benchmarking/Cargo.toml @@ -0,0 +1,37 @@ +[package] +name = "frame-system-benchmarking" +version = "2.0.0-rc4" +authors = ["Parity Technologies "] +edition = "2018" +license = "Apache-2.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +description = "FRAME System benchmarking" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/std" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/runtime" } +frame-benchmarking = { version = "2.0.0-rc4", default-features = false, path = "../../benchmarking" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../../system" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../../support" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/core" } + +[dev-dependencies] +serde = { version = "1.0.101" } +sp-io ={ version = "2.0.0-rc4", path = "../../../primitives/io" } + +[features] +default = ["std"] +std = [ + "codec/std", + "sp-runtime/std", + "sp-std/std", + "frame-benchmarking/std", + "frame-system/std", + "frame-support/std", + "sp-core/std", +] diff --git a/frame/system/benchmarking/src/lib.rs b/frame/system/benchmarking/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..049fa5298c677076702256735e6017b994279d0d --- /dev/null +++ b/frame/system/benchmarking/src/lib.rs @@ -0,0 +1,180 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Benchmarks for Utility Pallet + +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::Encode; +use sp_std::vec; +use sp_std::prelude::*; +use sp_core::{ChangesTrieConfiguration, storage::well_known_keys}; +use sp_runtime::traits::Hash; +use frame_benchmarking::{benchmarks, account}; +use frame_support::storage::{self, StorageMap}; +use frame_system::{Module as System, Call, RawOrigin, DigestItemOf, AccountInfo}; + +mod mock; + +const SEED: u32 = 0; + +pub struct Module(System); +pub trait Trait: frame_system::Trait {} + +benchmarks! { + _ { } + + remark { + // # of Bytes + let b in 0 .. 16_384; + let remark_message = vec![1; b as usize]; + let caller = account("caller", 0, SEED); + }: _(RawOrigin::Signed(caller), remark_message) + + set_heap_pages { + // Heap page size + let i in 0 .. u32::max_value(); + }: _(RawOrigin::Root, i.into()) + + // `set_code` was not benchmarked because it is pretty hard to come up with a real + // Wasm runtime to test the upgrade with. But this is okay because we will make + // `set_code` take a full block anyway. + + set_code_without_checks { + // Version number + let b in 0 .. 16_384; + let code = vec![1; b as usize]; + }: _(RawOrigin::Root, code) + verify { + let current_code = storage::unhashed::get_raw(well_known_keys::CODE).ok_or("Code not stored.")?; + assert_eq!(current_code.len(), b as usize); + } + + set_changes_trie_config { + let d in 0 .. 1000; + + let digest_item = DigestItemOf::::Other(vec![]); + + for i in 0 .. d { + System::::deposit_log(digest_item.clone()); + } + let changes_trie_config = ChangesTrieConfiguration { + digest_interval: d, + digest_levels: d, + }; + }: _(RawOrigin::Root, Some(changes_trie_config)) + verify { + assert_eq!(System::::digest().logs.len(), (d + 1) as usize) + } + + set_storage { + let i in 1 .. 1000; + + // Set up i items to add + let mut items = Vec::new(); + for j in 0 .. i { + let hash = (i, j).using_encoded(T::Hashing::hash).as_ref().to_vec(); + items.push((hash.clone(), hash.clone())); + } + }: _(RawOrigin::Root, items) + verify { + let last_hash = (i, i - 1).using_encoded(T::Hashing::hash); + let value = storage::unhashed::get_raw(last_hash.as_ref()).ok_or("No value stored")?; + assert_eq!(value, last_hash.as_ref().to_vec()); + } + + kill_storage { + let i in 1 .. 1000; + + // Add i items to storage + let mut items = Vec::new(); + for j in 0 .. i { + let hash = (i, j).using_encoded(T::Hashing::hash).as_ref().to_vec(); + storage::unhashed::put_raw(&hash, &hash); + items.push(hash); + } + + // We will verify this value is removed + let last_hash = (i, i - 1).using_encoded(T::Hashing::hash); + let value = storage::unhashed::get_raw(last_hash.as_ref()).ok_or("No value stored")?; + assert_eq!(value, last_hash.as_ref().to_vec()); + + }: _(RawOrigin::Root, items) + verify { + assert_eq!(storage::unhashed::get_raw(last_hash.as_ref()), None); + } + + kill_prefix { + let p in 1 .. 1000; + + let prefix = p.using_encoded(T::Hashing::hash).as_ref().to_vec(); + // add p items that share a prefix + for i in 0 .. p { + let hash = (p, i).using_encoded(T::Hashing::hash).as_ref().to_vec(); + let key = [&prefix[..], &hash[..]].concat(); + storage::unhashed::put_raw(&key, &key); + } + + // We will verify this value is removed + let last_hash = (p, p - 1).using_encoded(T::Hashing::hash).as_ref().to_vec(); + let last_key = [&prefix[..], &last_hash[..]].concat(); + let value = storage::unhashed::get_raw(&last_key).ok_or("No value stored")?; + assert_eq!(value, last_key); + + }: _(RawOrigin::Root, prefix, p) + verify { + assert_eq!(storage::unhashed::get_raw(&last_key), None); + } + + suicide { + let n in 1 .. 1000; + let caller: T::AccountId = account("caller", 0, SEED); + let account_info = AccountInfo:: { + nonce: n.into(), + refcount: 0, + data: T::AccountData::default() + }; + frame_system::Account::::insert(&caller, account_info); + let new_account_info = System::::account(caller.clone()); + assert_eq!(new_account_info.nonce, n.into()); + }: _(RawOrigin::Signed(caller.clone())) + verify { + let account_info = System::::account(&caller); + assert_eq!(account_info.nonce, 0.into()); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::{new_test_ext, Test}; + use frame_support::assert_ok; + + #[test] + fn test_benchmarks() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_remark::()); + assert_ok!(test_benchmark_set_heap_pages::()); + assert_ok!(test_benchmark_set_code_without_checks::()); + assert_ok!(test_benchmark_set_changes_trie_config::()); + assert_ok!(test_benchmark_set_storage::()); + assert_ok!(test_benchmark_kill_storage::()); + assert_ok!(test_benchmark_kill_prefix::()); + assert_ok!(test_benchmark_suicide::()); + }); + } +} diff --git a/frame/system/benchmarking/src/mock.rs b/frame/system/benchmarking/src/mock.rs new file mode 100644 index 0000000000000000000000000000000000000000..c2c953fb9738d077595f4e4c5d87bc70a8b6e32a --- /dev/null +++ b/frame/system/benchmarking/src/mock.rs @@ -0,0 +1,86 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Mock file for system benchmarking. + +#![cfg(test)] + +use sp_runtime::traits::IdentityLookup; +use frame_support::{ + impl_outer_origin, + dispatch::{Dispatchable, DispatchInfo, PostDispatchInfo}, +}; + +type AccountId = u64; +type AccountIndex = u32; +type BlockNumber = u64; + +impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} +} + +#[derive(Debug, codec::Encode, codec::Decode)] +pub struct Call; + +impl Dispatchable for Call { + type Origin = (); + type Trait = (); + type Info = DispatchInfo; + type PostInfo = PostDispatchInfo; + fn dispatch(self, _origin: Self::Origin) + -> sp_runtime::DispatchResultWithInfo { + panic!("Do not use dummy implementation for dispatch."); + } +} + +#[derive(Clone, Eq, PartialEq, Debug)] +pub struct Test; + +impl frame_system::Trait for Test { + type BaseCallFilter = (); + type Origin = Origin; + type Index = AccountIndex; + type BlockNumber = BlockNumber; + type Call = Call; + type Hash = sp_core::H256; + type Hashing = ::sp_runtime::traits::BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = sp_runtime::testing::Header; + type Event = (); + type BlockHashCount = (); + type MaximumBlockWeight = (); + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = (); + type AvailableBlockRatio = (); + type MaximumBlockLength = (); + type Version = (); + type ModuleToIndex = (); + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); +} + +impl crate::Trait for Test {} + +pub fn new_test_ext() -> sp_io::TestExternalities { + let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + sp_io::TestExternalities::new(t) +} diff --git a/frame/system/rpc/runtime-api/Cargo.toml b/frame/system/rpc/runtime-api/Cargo.toml index 9519427297425504a8fd1b9c769c5c2a6edd899e..8d340ad7defb81d23f3309b4872b915be65bf31b 100644 --- a/frame/system/rpc/runtime-api/Cargo.toml +++ b/frame/system/rpc/runtime-api/Cargo.toml @@ -1,16 +1,19 @@ [package] name = "frame-system-rpc-runtime-api" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Runtime API definition required by System RPC extensions." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-api = { version = "2.0.0-alpha.5", default-features = false, path = "../../../../primitives/api" } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } +sp-api = { version = "2.0.0-rc4", default-features = false, path = "../../../../primitives/api" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } [features] default = ["std"] @@ -18,6 +21,3 @@ std = [ "sp-api/std", "codec/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/system/rpc/runtime-api/src/lib.rs b/frame/system/rpc/runtime-api/src/lib.rs index 3b05bd162468e10e9a1d59712c2685332a5675bf..0ead94aabe016b739c4c8812618b1248d3116723 100644 --- a/frame/system/rpc/runtime-api/src/lib.rs +++ b/frame/system/rpc/runtime-api/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Runtime API definition required by System RPC extensions. //! diff --git a/frame/system/src/accounts.scale b/frame/system/src/accounts.scale deleted file mode 100644 index bfd7e6277f20c53ceb1d664235bb6af18ec538ed..0000000000000000000000000000000000000000 Binary files a/frame/system/src/accounts.scale and /dev/null differ diff --git a/frame/system/src/extensions/check_genesis.rs b/frame/system/src/extensions/check_genesis.rs new file mode 100644 index 0000000000000000000000000000000000000000..d0a346519ca23b8661cd92285ec2d72e5753b7a9 --- /dev/null +++ b/frame/system/src/extensions/check_genesis.rs @@ -0,0 +1,58 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use codec::{Encode, Decode}; +use crate::{Trait, Module}; +use sp_runtime::{ + traits::{SignedExtension, Zero}, + transaction_validity::TransactionValidityError, +}; + +/// Genesis hash check to provide replay protection between different networks. +#[derive(Encode, Decode, Clone, Eq, PartialEq)] +pub struct CheckGenesis(sp_std::marker::PhantomData); + +impl sp_std::fmt::Debug for CheckGenesis { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "CheckGenesis") + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } +} + +impl CheckGenesis { + /// Creates new `SignedExtension` to check genesis hash. + pub fn new() -> Self { + Self(sp_std::marker::PhantomData) + } +} + +impl SignedExtension for CheckGenesis { + type AccountId = T::AccountId; + type Call = ::Call; + type AdditionalSigned = T::Hash; + type Pre = (); + const IDENTIFIER: &'static str = "CheckGenesis"; + + fn additional_signed(&self) -> Result { + Ok(>::block_hash(T::BlockNumber::zero())) + } +} diff --git a/frame/system/src/extensions/check_mortality.rs b/frame/system/src/extensions/check_mortality.rs new file mode 100644 index 0000000000000000000000000000000000000000..7e3f65d0324d705fd5f6b1ce460b249917907ff4 --- /dev/null +++ b/frame/system/src/extensions/check_mortality.rs @@ -0,0 +1,123 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use codec::{Encode, Decode}; +use crate::{Trait, Module, BlockHash}; +use frame_support::StorageMap; +use sp_runtime::{ + generic::Era, + traits::{SignedExtension, DispatchInfoOf, SaturatedConversion}, + transaction_validity::{ + ValidTransaction, TransactionValidityError, InvalidTransaction, TransactionValidity, + }, +}; + +/// Check for transaction mortality. +#[derive(Encode, Decode, Clone, Eq, PartialEq)] +pub struct CheckMortality(Era, sp_std::marker::PhantomData); + +impl CheckMortality { + /// utility constructor. Used only in client/factory code. + pub fn from(era: Era) -> Self { + Self(era, sp_std::marker::PhantomData) + } +} + +impl sp_std::fmt::Debug for CheckMortality { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "CheckMortality({:?})", self.0) + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } +} + +impl SignedExtension for CheckMortality { + type AccountId = T::AccountId; + type Call = T::Call; + type AdditionalSigned = T::Hash; + type Pre = (); + const IDENTIFIER: &'static str = "CheckMortality"; + + fn validate( + &self, + _who: &Self::AccountId, + _call: &Self::Call, + _info: &DispatchInfoOf, + _len: usize, + ) -> TransactionValidity { + let current_u64 = >::block_number().saturated_into::(); + let valid_till = self.0.death(current_u64); + Ok(ValidTransaction { + longevity: valid_till.saturating_sub(current_u64), + ..Default::default() + }) + } + + fn additional_signed(&self) -> Result { + let current_u64 = >::block_number().saturated_into::(); + let n = self.0.birth(current_u64).saturated_into::(); + if !>::contains_key(n) { + Err(InvalidTransaction::AncientBirthBlock.into()) + } else { + Ok(>::block_hash(n)) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::{Test, new_test_ext, System, CALL}; + use frame_support::weights::{DispatchClass, DispatchInfo, Pays}; + use sp_core::H256; + + #[test] + fn signed_ext_check_era_should_work() { + new_test_ext().execute_with(|| { + // future + assert_eq!( + CheckMortality::::from(Era::mortal(4, 2)).additional_signed().err().unwrap(), + InvalidTransaction::AncientBirthBlock.into(), + ); + + // correct + System::set_block_number(13); + >::insert(12, H256::repeat_byte(1)); + assert!(CheckMortality::::from(Era::mortal(4, 12)).additional_signed().is_ok()); + }) + } + + #[test] + fn signed_ext_check_era_should_change_longevity() { + new_test_ext().execute_with(|| { + let normal = DispatchInfo { weight: 100, class: DispatchClass::Normal, pays_fee: Pays::Yes }; + let len = 0_usize; + let ext = ( + crate::CheckWeight::::default(), + CheckMortality::::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/frame/system/src/extensions/check_nonce.rs b/frame/system/src/extensions/check_nonce.rs new file mode 100644 index 0000000000000000000000000000000000000000..1af3a1210aaf417c96019f03b43944184d435e22 --- /dev/null +++ b/frame/system/src/extensions/check_nonce.rs @@ -0,0 +1,145 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use codec::{Encode, Decode}; +use crate::Trait; +use frame_support::{ + weights::DispatchInfo, + StorageMap, +}; +use sp_runtime::{ + traits::{SignedExtension, DispatchInfoOf, Dispatchable, One}, + transaction_validity::{ + ValidTransaction, TransactionValidityError, InvalidTransaction, TransactionValidity, + TransactionLongevity, TransactionPriority, + }, +}; +use sp_std::vec; + +/// Nonce check and increment to give replay protection for transactions. +#[derive(Encode, Decode, Clone, Eq, PartialEq)] +pub struct CheckNonce(#[codec(compact)] T::Index); + +impl CheckNonce { + /// utility constructor. Used only in client/factory code. + pub fn from(nonce: T::Index) -> Self { + Self(nonce) + } +} + +impl sp_std::fmt::Debug for CheckNonce { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "CheckNonce({})", self.0) + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } +} + +impl SignedExtension for CheckNonce where + T::Call: Dispatchable +{ + type AccountId = T::AccountId; + type Call = T::Call; + type AdditionalSigned = (); + type Pre = (); + const IDENTIFIER: &'static str = "CheckNonce"; + + fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) } + + fn pre_dispatch( + self, + who: &Self::AccountId, + _call: &Self::Call, + _info: &DispatchInfoOf, + _len: usize, + ) -> Result<(), TransactionValidityError> { + let mut account = crate::Account::::get(who); + if self.0 != account.nonce { + return Err( + if self.0 < account.nonce { + InvalidTransaction::Stale + } else { + InvalidTransaction::Future + }.into() + ) + } + account.nonce += T::Index::one(); + crate::Account::::insert(who, account); + Ok(()) + } + + fn validate( + &self, + who: &Self::AccountId, + _call: &Self::Call, + info: &DispatchInfoOf, + _len: usize, + ) -> TransactionValidity { + // check index + let account = crate::Account::::get(who); + if self.0 < account.nonce { + return InvalidTransaction::Stale.into() + } + + let provides = vec![Encode::encode(&(who, self.0))]; + let requires = if account.nonce < self.0 { + vec![Encode::encode(&(who, self.0 - One::one()))] + } else { + vec![] + }; + + Ok(ValidTransaction { + priority: info.weight as TransactionPriority, + requires, + provides, + longevity: TransactionLongevity::max_value(), + propagate: true, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::{Test, new_test_ext, CALL}; + + #[test] + fn signed_ext_check_nonce_works() { + new_test_ext().execute_with(|| { + crate::Account::::insert(1, crate::AccountInfo { + nonce: 1, + refcount: 0, + data: 0, + }); + let info = DispatchInfo::default(); + let len = 0_usize; + // stale + assert!(CheckNonce::(0).validate(&1, CALL, &info, len).is_err()); + assert!(CheckNonce::(0).pre_dispatch(&1, CALL, &info, len).is_err()); + // correct + assert!(CheckNonce::(1).validate(&1, CALL, &info, len).is_ok()); + assert!(CheckNonce::(1).pre_dispatch(&1, CALL, &info, len).is_ok()); + // future + assert!(CheckNonce::(5).validate(&1, CALL, &info, len).is_ok()); + assert!(CheckNonce::(5).pre_dispatch(&1, CALL, &info, len).is_err()); + }) + } +} diff --git a/frame/system/src/extensions/check_spec_version.rs b/frame/system/src/extensions/check_spec_version.rs new file mode 100644 index 0000000000000000000000000000000000000000..8dc4d8d9ceddc52893795cda924366bdec44975f --- /dev/null +++ b/frame/system/src/extensions/check_spec_version.rs @@ -0,0 +1,58 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::{Trait, Module}; +use codec::{Encode, Decode}; +use sp_runtime::{ + traits::SignedExtension, + transaction_validity::TransactionValidityError, +}; + +/// Ensure the runtime version registered in the transaction is the same as at present. +#[derive(Encode, Decode, Clone, Eq, PartialEq)] +pub struct CheckSpecVersion(sp_std::marker::PhantomData); + +impl sp_std::fmt::Debug for CheckSpecVersion { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "CheckSpecVersion") + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } +} + +impl CheckSpecVersion { + /// Create new `SignedExtension` to check runtime version. + pub fn new() -> Self { + Self(sp_std::marker::PhantomData) + } +} + +impl SignedExtension for CheckSpecVersion { + type AccountId = T::AccountId; + type Call = ::Call; + type AdditionalSigned = u32; + type Pre = (); + const IDENTIFIER: &'static str = "CheckSpecVersion"; + + fn additional_signed(&self) -> Result { + Ok(>::runtime_version().spec_version) + } +} diff --git a/frame/system/src/extensions/check_tx_version.rs b/frame/system/src/extensions/check_tx_version.rs new file mode 100644 index 0000000000000000000000000000000000000000..ee6f3349365b9b9b21801eabd91ef32863a45007 --- /dev/null +++ b/frame/system/src/extensions/check_tx_version.rs @@ -0,0 +1,58 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::{Trait, Module}; +use codec::{Encode, Decode}; +use sp_runtime::{ + traits::SignedExtension, + transaction_validity::TransactionValidityError, +}; + +/// Ensure the transaction version registered in the transaction is the same as at present. +#[derive(Encode, Decode, Clone, Eq, PartialEq)] +pub struct CheckTxVersion(sp_std::marker::PhantomData); + +impl sp_std::fmt::Debug for CheckTxVersion { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "CheckTxVersion") + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } +} + +impl CheckTxVersion { + /// Create new `SignedExtension` to check transaction version. + pub fn new() -> Self { + Self(sp_std::marker::PhantomData) + } +} + +impl SignedExtension for CheckTxVersion { + type AccountId = T::AccountId; + type Call = ::Call; + type AdditionalSigned = u32; + type Pre = (); + const IDENTIFIER: &'static str = "CheckTxVersion"; + + fn additional_signed(&self) -> Result { + Ok(>::runtime_version().transaction_version) + } +} diff --git a/frame/system/src/extensions/check_weight.rs b/frame/system/src/extensions/check_weight.rs new file mode 100644 index 0000000000000000000000000000000000000000..d52138b1e3bbe20cc7bef9b6d1b70a04bfa70efd --- /dev/null +++ b/frame/system/src/extensions/check_weight.rs @@ -0,0 +1,644 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::{Trait, Module}; +use codec::{Encode, Decode}; +use sp_runtime::{ + traits::{SignedExtension, DispatchInfoOf, Dispatchable, PostDispatchInfoOf, Printable}, + transaction_validity::{ + ValidTransaction, TransactionValidityError, InvalidTransaction, TransactionValidity, + TransactionPriority, + }, + Perbill, DispatchResult, +}; +use frame_support::{ + traits::{Get}, + weights::{PostDispatchInfo, DispatchInfo, DispatchClass}, + StorageValue, +}; + +/// Block resource (weight) limit check. +#[derive(Encode, Decode, Clone, Eq, PartialEq, Default)] +pub struct CheckWeight(sp_std::marker::PhantomData); + +impl CheckWeight where + T::Call: Dispatchable +{ + /// Get the quota ratio of each dispatch class type. This indicates that all operational and mandatory + /// 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 | DispatchClass::Mandatory + => ::one(), + DispatchClass::Normal => T::AvailableBlockRatio::get(), + } + } + + /// Checks if the current extrinsic does not exceed `MaximumExtrinsicWeight` limit. + fn check_extrinsic_weight( + info: &DispatchInfoOf, + ) -> Result<(), TransactionValidityError> { + match info.class { + // Mandatory transactions are included in a block unconditionally, so + // we don't verify weight. + DispatchClass::Mandatory => Ok(()), + // Normal transactions must not exceed `MaximumExtrinsicWeight`. + DispatchClass::Normal => { + let maximum_weight = T::MaximumExtrinsicWeight::get(); + let extrinsic_weight = info.weight.saturating_add(T::ExtrinsicBaseWeight::get()); + if extrinsic_weight > maximum_weight { + Err(InvalidTransaction::ExhaustsResources.into()) + } else { + Ok(()) + } + }, + // For operational transactions we make sure it doesn't exceed + // the space alloted for `Operational` class. + DispatchClass::Operational => { + let maximum_weight = T::MaximumBlockWeight::get(); + let operational_limit = + Self::get_dispatch_limit_ratio(DispatchClass::Operational) * maximum_weight; + let operational_limit = + operational_limit.saturating_sub(T::BlockExecutionWeight::get()); + let extrinsic_weight = info.weight.saturating_add(T::ExtrinsicBaseWeight::get()); + if extrinsic_weight > operational_limit { + Err(InvalidTransaction::ExhaustsResources.into()) + } else { + Ok(()) + } + }, + } + } + + /// 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_block_weight( + info: &DispatchInfoOf, + ) -> Result { + let maximum_weight = T::MaximumBlockWeight::get(); + let mut all_weight = Module::::block_weight(); + match info.class { + // If we have a dispatch that must be included in the block, it ignores all the limits. + DispatchClass::Mandatory => { + let extrinsic_weight = info.weight.saturating_add(T::ExtrinsicBaseWeight::get()); + all_weight.add(extrinsic_weight, DispatchClass::Mandatory); + Ok(all_weight) + }, + // If we have a normal dispatch, we follow all the normal rules and limits. + DispatchClass::Normal => { + let normal_limit = Self::get_dispatch_limit_ratio(DispatchClass::Normal) * maximum_weight; + let extrinsic_weight = info.weight.checked_add(T::ExtrinsicBaseWeight::get()) + .ok_or(InvalidTransaction::ExhaustsResources)?; + all_weight.checked_add(extrinsic_weight, DispatchClass::Normal) + .map_err(|_| InvalidTransaction::ExhaustsResources)?; + if all_weight.get(DispatchClass::Normal) > normal_limit { + Err(InvalidTransaction::ExhaustsResources.into()) + } else { + Ok(all_weight) + } + }, + // If we have an operational dispatch, allow it if we have not used our full + // "operational space" (independent of existing fullness). + DispatchClass::Operational => { + let operational_limit = Self::get_dispatch_limit_ratio(DispatchClass::Operational) * maximum_weight; + let normal_limit = Self::get_dispatch_limit_ratio(DispatchClass::Normal) * maximum_weight; + let operational_space = operational_limit.saturating_sub(normal_limit); + + let extrinsic_weight = info.weight.checked_add(T::ExtrinsicBaseWeight::get()) + .ok_or(InvalidTransaction::ExhaustsResources)?; + all_weight.checked_add(extrinsic_weight, DispatchClass::Operational) + .map_err(|_| InvalidTransaction::ExhaustsResources)?; + + // If it would fit in normally, its okay + if all_weight.total() <= maximum_weight || + // If we have not used our operational space + all_weight.get(DispatchClass::Operational) <= operational_space { + Ok(all_weight) + } else { + Err(InvalidTransaction::ExhaustsResources.into()) + } + } + } + } + + /// 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: &DispatchInfoOf, + 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 { + Err(InvalidTransaction::ExhaustsResources.into()) + } else { + Ok(next_len) + } + } + + /// get the priority of an extrinsic denoted by `info`. + fn get_priority(info: &DispatchInfoOf) -> TransactionPriority { + match info.class { + DispatchClass::Normal => info.weight.into(), + // Don't use up the whole priority space, to allow things like `tip` + // to be taken into account as well. + DispatchClass::Operational => TransactionPriority::max_value() / 2, + // Mandatory extrinsics are only for inherents; never transactions. + DispatchClass::Mandatory => TransactionPriority::min_value(), + } + } + + /// Creates new `SignedExtension` to check weight of the extrinsic. + pub fn new() -> Self { + Self(Default::default()) + } + + /// Do the pre-dispatch checks. This can be applied to both signed and unsigned. + /// + /// It checks and notes the new weight and length. + fn do_pre_dispatch( + info: &DispatchInfoOf, + len: usize, + ) -> Result<(), TransactionValidityError> { + let next_len = Self::check_block_length(info, len)?; + let next_weight = Self::check_block_weight(info)?; + Self::check_extrinsic_weight(info)?; + + crate::AllExtrinsicsLen::put(next_len); + crate::BlockWeight::put(next_weight); + Ok(()) + } + + /// Do the validate checks. This can be applied to both signed and unsigned. + /// + /// It only checks that the block weight and length limit will not exceed. + fn do_validate( + info: &DispatchInfoOf, + len: usize, + ) -> TransactionValidity { + // ignore the next length. If they return `Ok`, then it is below the limit. + let _ = Self::check_block_length(info, len)?; + // during validation we skip block limit check. Since the `validate_transaction` + // call runs on an empty block anyway, by this we prevent `on_initialize` weight + // consumption from causing false negatives. + Self::check_extrinsic_weight(info)?; + + Ok(ValidTransaction { priority: Self::get_priority(info), ..Default::default() }) + } +} + +impl SignedExtension for CheckWeight where + T::Call: Dispatchable +{ + type AccountId = T::AccountId; + type Call = T::Call; + type AdditionalSigned = (); + type Pre = (); + const IDENTIFIER: &'static str = "CheckWeight"; + + fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) } + + fn pre_dispatch( + self, + _who: &Self::AccountId, + _call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result<(), TransactionValidityError> { + if info.class == DispatchClass::Mandatory { + Err(InvalidTransaction::MandatoryDispatch)? + } + Self::do_pre_dispatch(info, len) + } + + fn validate( + &self, + _who: &Self::AccountId, + _call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> TransactionValidity { + if info.class == DispatchClass::Mandatory { + Err(InvalidTransaction::MandatoryDispatch)? + } + Self::do_validate(info, len) + } + + fn pre_dispatch_unsigned( + _call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result<(), TransactionValidityError> { + Self::do_pre_dispatch(info, len) + } + + fn validate_unsigned( + _call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> TransactionValidity { + Self::do_validate(info, len) + } + + fn post_dispatch( + _pre: Self::Pre, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, + _len: usize, + result: &DispatchResult, + ) -> Result<(), TransactionValidityError> { + // Since mandatory dispatched do not get validated for being overweight, we are sensitive + // to them actually being useful. Block producers are thus not allowed to include mandatory + // extrinsics that result in error. + if let (DispatchClass::Mandatory, Err(e)) = (info.class, result) { + "Bad mandantory".print(); + e.print(); + + Err(InvalidTransaction::BadMandatory)? + } + + let unspent = post_info.calc_unspent(info); + if unspent > 0 { + crate::BlockWeight::mutate(|current_weight| { + current_weight.sub(unspent, info.class); + }) + } + + Ok(()) + } +} + +impl sp_std::fmt::Debug for CheckWeight { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "CheckWeight") + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{BlockWeight, AllExtrinsicsLen}; + use crate::mock::{Test, CALL, new_test_ext, System}; + use sp_std::marker::PhantomData; + use frame_support::{assert_ok, assert_noop}; + use frame_support::weights::{Weight, Pays}; + + fn normal_weight_limit() -> Weight { + ::AvailableBlockRatio::get() * ::MaximumBlockWeight::get() + } + + fn normal_length_limit() -> u32 { + ::AvailableBlockRatio::get() * ::MaximumBlockLength::get() + } + + #[test] + fn mandatory_extrinsic_doesnt_care_about_limits() { + fn check(call: impl FnOnce(&DispatchInfo, usize)) { + new_test_ext().execute_with(|| { + let max = DispatchInfo { + weight: Weight::max_value(), + class: DispatchClass::Mandatory, + ..Default::default() + }; + let len = 0_usize; + + call(&max, len); + }); + } + + check(|max, len| { + assert_ok!(CheckWeight::::do_pre_dispatch(max, len)); + assert_eq!(System::block_weight().total(), Weight::max_value()); + assert!(System::block_weight().total() > ::MaximumBlockWeight::get()); + }); + check(|max, len| { + assert_ok!(CheckWeight::::do_validate(max, len)); + }); + } + + #[test] + fn normal_extrinsic_limited_by_maximum_extrinsic_weight() { + new_test_ext().execute_with(|| { + let max = DispatchInfo { + weight: ::MaximumExtrinsicWeight::get() + 1, + class: DispatchClass::Normal, + ..Default::default() + }; + let len = 0_usize; + + assert_noop!( + CheckWeight::::do_validate(&max, len), + InvalidTransaction::ExhaustsResources + ); + }); + } + + #[test] + fn operational_extrinsic_limited_by_operational_space_limit() { + new_test_ext().execute_with(|| { + let operational_limit = CheckWeight::::get_dispatch_limit_ratio( + DispatchClass::Operational + ) * ::MaximumBlockWeight::get(); + let base_weight = ::ExtrinsicBaseWeight::get(); + let block_base = ::BlockExecutionWeight::get(); + + let weight = operational_limit - base_weight - block_base; + let okay = DispatchInfo { + weight, + class: DispatchClass::Operational, + ..Default::default() + }; + let max = DispatchInfo { + weight: weight + 1, + class: DispatchClass::Operational, + ..Default::default() + }; + let len = 0_usize; + + assert_eq!( + CheckWeight::::do_validate(&okay, len), + Ok(ValidTransaction { + priority: CheckWeight::::get_priority(&okay), + ..Default::default() + }) + ); + assert_noop!( + CheckWeight::::do_validate(&max, len), + InvalidTransaction::ExhaustsResources + ); + }); + } + + #[test] + fn register_extra_weight_unchecked_doesnt_care_about_limits() { + new_test_ext().execute_with(|| { + System::register_extra_weight_unchecked(Weight::max_value(), DispatchClass::Normal); + assert_eq!(System::block_weight().total(), Weight::max_value()); + assert!(System::block_weight().total() > ::MaximumBlockWeight::get()); + }); + } + + #[test] + fn full_block_with_normal_and_operational() { + new_test_ext().execute_with(|| { + // Max block is 1024 + // Max normal is 768 (75%) + // 10 is taken for block execution weight + // So normal extrinsic can be 758 weight (-5 for base extrinsic weight) + // And Operational can be 256 to produce a full block (-5 for base) + let max_normal = DispatchInfo { weight: 753, ..Default::default() }; + let rest_operational = DispatchInfo { weight: 251, class: DispatchClass::Operational, ..Default::default() }; + + let len = 0_usize; + + assert_ok!(CheckWeight::::do_pre_dispatch(&max_normal, len)); + assert_eq!(System::block_weight().total(), 768); + assert_ok!(CheckWeight::::do_pre_dispatch(&rest_operational, len)); + assert_eq!(::MaximumBlockWeight::get(), 1024); + assert_eq!(System::block_weight().total(), ::MaximumBlockWeight::get()); + // Checking single extrinsic should not take current block weight into account. + assert_eq!(CheckWeight::::check_extrinsic_weight(&rest_operational), Ok(())); + }); + } + + #[test] + fn dispatch_order_does_not_effect_weight_logic() { + new_test_ext().execute_with(|| { + // We switch the order of `full_block_with_normal_and_operational` + let max_normal = DispatchInfo { weight: 753, ..Default::default() }; + let rest_operational = DispatchInfo { weight: 251, class: DispatchClass::Operational, ..Default::default() }; + + let len = 0_usize; + + assert_ok!(CheckWeight::::do_pre_dispatch(&rest_operational, len)); + // Extra 15 here from block execution + base extrinsic weight + assert_eq!(System::block_weight().total(), 266); + assert_ok!(CheckWeight::::do_pre_dispatch(&max_normal, len)); + assert_eq!(::MaximumBlockWeight::get(), 1024); + assert_eq!(System::block_weight().total(), ::MaximumBlockWeight::get()); + }); + } + + #[test] + fn operational_works_on_full_block() { + new_test_ext().execute_with(|| { + // An on_initialize takes up the whole block! (Every time!) + System::register_extra_weight_unchecked(Weight::max_value(), DispatchClass::Mandatory); + let dispatch_normal = DispatchInfo { weight: 251, class: DispatchClass::Normal, ..Default::default() }; + let dispatch_operational = DispatchInfo { weight: 251, class: DispatchClass::Operational, ..Default::default() }; + let len = 0_usize; + + assert_noop!( + CheckWeight::::do_pre_dispatch(&dispatch_normal, len), + InvalidTransaction::ExhaustsResources + ); + // Thank goodness we can still do an operational transaction to possibly save the blockchain. + assert_ok!(CheckWeight::::do_pre_dispatch(&dispatch_operational, len)); + // Not too much though + assert_noop!( + CheckWeight::::do_pre_dispatch(&dispatch_operational, len), + InvalidTransaction::ExhaustsResources + ); + // Even with full block, validity of single transaction should be correct. + assert_eq!(CheckWeight::::check_extrinsic_weight(&dispatch_operational), Ok(())); + }); + } + + #[test] + fn signed_ext_check_weight_works_operational_tx() { + new_test_ext().execute_with(|| { + let normal = DispatchInfo { weight: 100, ..Default::default() }; + let op = DispatchInfo { weight: 100, class: DispatchClass::Operational, pays_fee: Pays::Yes }; + let len = 0_usize; + let normal_limit = normal_weight_limit(); + + // given almost full block + BlockWeight::mutate(|current_weight| { + current_weight.put(normal_limit, DispatchClass::Normal) + }); + // will not fit. + assert!(CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &normal, len).is_err()); + // will fit. + assert!(CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &op, len).is_ok()); + + // likewise for length limit. + let len = 100_usize; + AllExtrinsicsLen::put(normal_length_limit()); + assert!(CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &normal, len).is_err()); + assert!(CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &op, len).is_ok()); + }) + } + + #[test] + fn signed_ext() { + new_test_ext().execute_with(|| { + let normal = DispatchInfo { weight: 100, class: DispatchClass::Normal, pays_fee: Pays::Yes }; + let op = DispatchInfo { weight: 100, class: DispatchClass::Operational, pays_fee: Pays::Yes }; + let len = 0_usize; + + 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, u64::max_value() / 2); + }) + } + + #[test] + fn signed_ext_check_weight_block_size_works() { + new_test_ext().execute_with(|| { + let normal = DispatchInfo::default(); + let normal_limit = normal_weight_limit() as usize; + let reset_check_weight = |tx, s, f| { + AllExtrinsicsLen::put(0); + let r = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, tx, s); + if f { assert!(r.is_err()) } else { assert!(r.is_ok()) } + }; + + reset_check_weight(&normal, normal_limit - 1, false); + reset_check_weight(&normal, normal_limit, false); + reset_check_weight(&normal, normal_limit + 1, true); + + // Operational ones don't have this limit. + let op = DispatchInfo { weight: 0, class: DispatchClass::Operational, pays_fee: Pays::Yes }; + reset_check_weight(&op, normal_limit, false); + reset_check_weight(&op, normal_limit + 100, false); + reset_check_weight(&op, 1024, false); + reset_check_weight(&op, 1025, true); + }) + } + + + #[test] + fn signed_ext_check_weight_works_normal_tx() { + new_test_ext().execute_with(|| { + let normal_limit = normal_weight_limit(); + let small = DispatchInfo { weight: 100, ..Default::default() }; + let medium = DispatchInfo { + weight: normal_limit - ::ExtrinsicBaseWeight::get(), + ..Default::default() + }; + let big = DispatchInfo { + weight: normal_limit - ::ExtrinsicBaseWeight::get() + 1, + ..Default::default() + }; + let len = 0_usize; + + let reset_check_weight = |i, f, s| { + BlockWeight::mutate(|current_weight| { + current_weight.put(s, DispatchClass::Normal) + }); + let r = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, i, len); + if f { assert!(r.is_err()) } else { assert!(r.is_ok()) } + }; + + reset_check_weight(&small, false, 0); + reset_check_weight(&medium, false, 0); + reset_check_weight(&big, true, 1); + }) + } + + #[test] + fn signed_ext_check_weight_refund_works() { + new_test_ext().execute_with(|| { + // This is half of the max block weight + let info = DispatchInfo { weight: 512, ..Default::default() }; + let post_info = PostDispatchInfo { actual_weight: Some(128), }; + let len = 0_usize; + + // We allow 75% for normal transaction, so we put 25% - extrinsic base weight + BlockWeight::mutate(|current_weight| { + current_weight.put(256 - ::ExtrinsicBaseWeight::get(), DispatchClass::Normal) + }); + + let pre = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &info, len).unwrap(); + assert_eq!(BlockWeight::get().total(), info.weight + 256); + + assert!( + CheckWeight::::post_dispatch(pre, &info, &post_info, len, &Ok(())) + .is_ok() + ); + assert_eq!( + BlockWeight::get().total(), + post_info.actual_weight.unwrap() + 256, + ); + }) + } + + #[test] + fn signed_ext_check_weight_actual_weight_higher_than_max_is_capped() { + new_test_ext().execute_with(|| { + let info = DispatchInfo { weight: 512, ..Default::default() }; + let post_info = PostDispatchInfo { actual_weight: Some(700), }; + let len = 0_usize; + + BlockWeight::mutate(|current_weight| { + current_weight.put(128, DispatchClass::Normal) + }); + + let pre = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &info, len).unwrap(); + assert_eq!( + BlockWeight::get().total(), + info.weight + 128 + ::ExtrinsicBaseWeight::get(), + ); + + assert!( + CheckWeight::::post_dispatch(pre, &info, &post_info, len, &Ok(())) + .is_ok() + ); + assert_eq!( + BlockWeight::get().total(), + info.weight + 128 + ::ExtrinsicBaseWeight::get(), + ); + }) + } + + #[test] + fn zero_weight_extrinsic_still_has_base_weight() { + new_test_ext().execute_with(|| { + let free = DispatchInfo { weight: 0, ..Default::default() }; + let len = 0_usize; + + // Initial weight from `BlockExecutionWeight` + assert_eq!(System::block_weight().total(), ::BlockExecutionWeight::get()); + let r = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &free, len); + assert!(r.is_ok()); + assert_eq!( + System::block_weight().total(), + ::ExtrinsicBaseWeight::get() + ::BlockExecutionWeight::get() + ); + }) + } +} diff --git a/frame/system/src/extensions/mod.rs b/frame/system/src/extensions/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..ff61353e2d176fbc1660e2a6787e370c6f15328c --- /dev/null +++ b/frame/system/src/extensions/mod.rs @@ -0,0 +1,24 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +pub mod check_genesis; +pub mod check_mortality; +pub mod check_nonce; +pub mod check_spec_version; +pub mod check_tx_version; +pub mod check_weight; + diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index 78239163476e1a27678fbe40aeea9f8199c32532..ad68e97d462ad566d3c148bfc109555d951e58f1 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # System Module //! @@ -53,7 +54,9 @@ //! - [`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 +//! - [`CheckSpecVersion`]: Checks that the runtime version is the same as the one used to sign the +//! transaction. +//! - [`CheckTxVersion`]: Checks that the transaction version is the same as the one used to sign the //! transaction. //! //! Lookup the runtime aggregator file (e.g. `node/runtime`) to see the full list of signed @@ -68,14 +71,14 @@ //! ### Example - Get extrinsic count and parent hash for the current block //! //! ``` -//! use frame_support::{decl_module, dispatch, weights::SimpleDispatchInfo}; +//! use frame_support::{decl_module, dispatch}; //! use frame_system::{self as system, ensure_signed}; //! //! pub trait Trait: system::Trait {} //! //! decl_module! { //! pub struct Module for enum Call where origin: T::Origin { -//! #[weight = SimpleDispatchInfo::default()] +//! #[weight = 0] //! pub fn system_module_example(origin) -> dispatch::DispatchResult { //! let _sender = ensure_signed(origin)?; //! let _extrinsic_count = >::extrinsic_count(); @@ -99,27 +102,29 @@ use sp_std::marker::PhantomData; use sp_std::fmt::Debug; use sp_version::RuntimeVersion; use sp_runtime::{ - RuntimeDebug, Perbill, DispatchOutcome, DispatchError, - generic::{self, Era}, - transaction_validity::{ - ValidTransaction, TransactionPriority, TransactionLongevity, TransactionValidityError, - InvalidTransaction, TransactionValidity, - }, + RuntimeDebug, Perbill, DispatchError, Either, generic, traits::{ - self, CheckEqual, AtLeast32Bit, Zero, SignedExtension, Lookup, LookupError, - SimpleBitOps, Hash, Member, MaybeDisplay, BadOrigin, SaturatedConversion, + self, CheckEqual, AtLeast32Bit, Zero, Lookup, LookupError, + SimpleBitOps, Hash, Member, MaybeDisplay, BadOrigin, MaybeSerialize, MaybeSerializeDeserialize, MaybeMallocSizeOf, StaticLookup, One, Bounded, + Dispatchable, AtLeast32BitUnsigned }, + offchain::storage_lock::BlockNumberProvider, }; use sp_core::{ChangesTrieConfiguration, storage::well_known_keys}; use frame_support::{ - decl_module, decl_event, decl_storage, decl_error, storage, Parameter, ensure, debug, + decl_module, decl_event, decl_storage, decl_error, Parameter, ensure, debug, + storage, traits::{ Contains, Get, ModuleToIndex, OnNewAccount, OnKilledAccount, IsDeadAccount, Happened, - StoredMap, EnsureOrigin, + StoredMap, EnsureOrigin, OriginTrait, Filter, + }, + weights::{ + Weight, RuntimeDbWeight, DispatchInfo, DispatchClass, + extract_actual_weight, }, - weights::{Weight, DispatchInfo, DispatchClass, SimpleDispatchInfo, FunctionOf}, + dispatch::DispatchResultWithPostInfo, }; use codec::{Encode, Decode, FullCodec, EncodeLike}; @@ -127,6 +132,21 @@ use codec::{Encode, Decode, FullCodec, EncodeLike}; use sp_io::TestExternalities; pub mod offchain; +#[cfg(test)] +pub(crate) mod mock; + +mod extensions; +mod weights; +#[cfg(test)] +mod tests; + +pub use extensions::{ + check_mortality::CheckMortality, check_genesis::CheckGenesis, check_nonce::CheckNonce, + check_spec_version::CheckSpecVersion, check_tx_version::CheckTxVersion, + check_weight::CheckWeight, +}; +// Backward compatible re-export. +pub use extensions::check_mortality::CheckMortality as CheckEra; /// Compute the trie root of a list of extrinsics. pub fn extrinsics_root(extrinsics: &[E]) -> H::Output { @@ -138,15 +158,42 @@ pub fn extrinsics_data_root(xts: Vec>) -> H::Output { H::ordered_trie_root(xts) } +pub trait WeightInfo { + fn remark(b: u32, ) -> Weight; + fn set_heap_pages(i: u32, ) -> Weight; + fn set_code_without_checks(b: u32, ) -> Weight; + fn set_changes_trie_config(d: u32, ) -> Weight; + fn set_storage(i: u32, ) -> Weight; + fn kill_storage(i: u32, ) -> Weight; + fn kill_prefix(p: u32, ) -> Weight; + fn suicide(n: u32, ) -> Weight; +} + +impl WeightInfo for () { + fn remark(_b: u32, ) -> Weight { 1_000_000_000 } + fn set_heap_pages(_i: u32, ) -> Weight { 1_000_000_000 } + fn set_code_without_checks(_b: u32, ) -> Weight { 1_000_000_000 } + fn set_changes_trie_config(_d: u32, ) -> Weight { 1_000_000_000 } + fn set_storage(_i: u32, ) -> Weight { 1_000_000_000 } + fn kill_storage(_i: u32, ) -> Weight { 1_000_000_000 } + fn kill_prefix(_p: u32, ) -> Weight { 1_000_000_000 } + fn suicide(_n: u32, ) -> Weight { 1_000_000_000 } +} + pub trait Trait: 'static + Eq + Clone { - /// The aggregated `Origin` type used by dispatchable calls. + /// The basic call filter to use in Origin. All origins are built with this filter as base, + /// except Root. + type BaseCallFilter: Filter; + + /// The `Origin` type used by dispatchable calls. type Origin: Into, Self::Origin>> + From> - + Clone; + + Clone + + OriginTrait; /// The aggregated `Call` type. - type Call: Debug; + type Call: Dispatchable + Debug; /// Account index (aka nonce) type. This stores the number of previous transactions associated /// with a sender account. @@ -156,8 +203,9 @@ pub trait Trait: 'static + Eq + Clone { /// The block number type used by the runtime. type BlockNumber: - Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + AtLeast32Bit - + Default + Bounded + Copy + sp_std::hash::Hash + sp_std::str::FromStr + MaybeMallocSizeOf; + Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + + AtLeast32BitUnsigned + Default + Bounded + Copy + sp_std::hash::Hash + + sp_std::str::FromStr + MaybeMallocSizeOf; /// The output of the `Hashing` function. type Hash: @@ -194,6 +242,20 @@ pub trait Trait: 'static + Eq + Clone { /// The maximum weight of a block. type MaximumBlockWeight: Get; + /// The weight of runtime database operations the runtime can invoke. + type DbWeight: Get; + + /// The base weight of executing a block, independent of the transactions in the block. + type BlockExecutionWeight: Get; + + /// The base weight of an Extrinsic in the block, independent of the of extrinsic being executed. + type ExtrinsicBaseWeight: Get; + + /// The maximal weight of a single Extrinsic. This should be set to at most + /// `MaximumBlockWeight - AverageOnInitializeWeight`. The limit only applies to extrinsics + /// containing `Normal` dispatch class calls. + type MaximumExtrinsicWeight: Get; + /// The maximum length of a block (in bytes). type MaximumBlockLength: Get; @@ -222,6 +284,8 @@ pub trait Trait: 'static + Eq + Clone { /// /// All resources should be cleaned up associated with the given account. type OnKilledAccount: OnKilledAccount; + + type SystemWeightInfo: WeightInfo; } pub type DigestOf = generic::Digest<::Hash>; @@ -261,7 +325,7 @@ pub struct EventRecord { } /// Origin for the System module. -#[derive(PartialEq, Eq, Clone, RuntimeDebug)] +#[derive(PartialEq, Eq, Clone, RuntimeDebug, Encode, Decode)] pub enum RawOrigin { /// The system itself ordained this dispatch to happen: this is the highest privilege level. Root, @@ -352,8 +416,8 @@ decl_storage! { /// Total extrinsics count for the current block. ExtrinsicCount: Option; - /// Total weight for all extrinsics put together, for the current block. - AllExtrinsicsWeight: Option; + /// The current weight for the block. + BlockWeight get(fn block_weight): weights::ExtrinsicsWeight; /// Total length (in bytes) for all extrinsics put together, for the current block. AllExtrinsicsLen: Option; @@ -456,7 +520,6 @@ decl_error! { /// /// Either calling `Core_version` or decoding `RuntimeVersion` failed. FailedToExtractRuntimeVersion, - /// Suicide called when the account has non-default composite data. NonDefaultComposite, /// There is a non-zero reference count preventing the account from being purged. @@ -468,33 +531,69 @@ decl_module! { pub struct Module for enum Call where origin: T::Origin { type Error = Error; + /// The maximum number of blocks to allow in mortal eras. + const BlockHashCount: T::BlockNumber = T::BlockHashCount::get(); + + /// The maximum weight of a block. + const MaximumBlockWeight: Weight = T::MaximumBlockWeight::get(); + + /// The weight of runtime database operations the runtime can invoke. + const DbWeight: RuntimeDbWeight = T::DbWeight::get(); + + /// The base weight of executing a block, independent of the transactions in the block. + const BlockExecutionWeight: Weight = T::BlockExecutionWeight::get(); + + /// The base weight of an Extrinsic in the block, independent of the of extrinsic being executed. + const ExtrinsicBaseWeight: Weight = T::ExtrinsicBaseWeight::get(); + + /// The maximum length of a block (in bytes). + const MaximumBlockLength: u32 = T::MaximumBlockLength::get(); + /// A dispatch that will fill the block weight up to the given ratio. // TODO: This should only be available for testing, rather than in general usage, but // that's not possible at present (since it's within the decl_module macro). - #[weight = FunctionOf( - |(ratio,): (&Perbill,)| *ratio * T::MaximumBlockWeight::get(), - DispatchClass::Operational, - true, - )] + #[weight = *_ratio * T::MaximumBlockWeight::get()] fn fill_block(origin, _ratio: Perbill) { ensure_root(origin)?; } /// Make some on-chain remark. - #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + /// + /// # + /// - `O(1)` + /// - Base Weight: 0.665 µs, independent of remark length. + /// - No DB operations. + /// # + #[weight = 700_000] fn remark(origin, _remark: Vec) { ensure_signed(origin)?; } /// Set the number of pages in the WebAssembly environment's heap. - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + /// + /// # + /// - `O(1)` + /// - 1 storage write. + /// - Base Weight: 1.405 µs + /// - 1 write to HEAP_PAGES + /// # + #[weight = (T::DbWeight::get().writes(1) + 1_500_000, DispatchClass::Operational)] fn set_heap_pages(origin, pages: u64) { ensure_root(origin)?; storage::unhashed::put_raw(well_known_keys::HEAP_PAGES, &pages.encode()); } /// Set the new runtime code. - #[weight = SimpleDispatchInfo::FixedOperational(200_000)] + /// + /// # + /// - `O(C + S)` where `C` length of `code` and `S` complexity of `can_set_code` + /// - 1 storage write (codec `O(C)`). + /// - 1 call to `can_set_code`: `O(S)` (calls `sp_io::misc::runtime_version` which is expensive). + /// - 1 event. + /// The weight of this function is dependent on the runtime, but generally this is very expensive. + /// We will treat this as a full block. + /// # + #[weight = (T::MaximumBlockWeight::get(), DispatchClass::Operational)] pub fn set_code(origin, code: Vec) { Self::can_set_code(origin, &code)?; @@ -503,7 +602,14 @@ decl_module! { } /// Set the new runtime code without doing any checks of the given `code`. - #[weight = SimpleDispatchInfo::FixedOperational(200_000)] + /// + /// # + /// - `O(C)` where `C` length of `code` + /// - 1 storage write (codec `O(C)`). + /// - 1 event. + /// The weight of this function is dependent on the runtime. We will treat this as a full block. + /// # + #[weight = (T::MaximumBlockWeight::get(), DispatchClass::Operational)] pub fn set_code_without_checks(origin, code: Vec) { ensure_root(origin)?; storage::unhashed::put_raw(well_known_keys::CODE, &code); @@ -511,7 +617,16 @@ decl_module! { } /// Set the new changes trie configuration. - #[weight = SimpleDispatchInfo::FixedOperational(20_000)] + /// + /// # + /// - `O(1)` + /// - 1 storage write or delete (codec `O(1)`). + /// - 1 call to `deposit_log`: Uses `append` API, so O(1) + /// - Base Weight: 7.218 µs + /// - DB Weight: + /// - Writes: Changes Trie, System Digest + /// # + #[weight = (T::DbWeight::get().writes(2) + 10_000_000, DispatchClass::Operational)] pub fn set_changes_trie_config(origin, changes_trie_config: Option) { ensure_root(origin)?; match changes_trie_config.clone() { @@ -529,7 +644,18 @@ decl_module! { } /// Set some items of storage. - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + /// + /// # + /// - `O(I)` where `I` length of `items` + /// - `I` storage writes (`O(1)`). + /// - Base Weight: 0.568 * i µs + /// - Writes: Number of items + /// # + #[weight = ( + T::DbWeight::get().writes(items.len() as Weight) + .saturating_add((items.len() as Weight).saturating_mul(600_000)), + DispatchClass::Operational, + )] fn set_storage(origin, items: Vec) { ensure_root(origin)?; for i in &items { @@ -538,7 +664,18 @@ decl_module! { } /// Kill some items from storage. - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + /// + /// # + /// - `O(IK)` where `I` length of `keys` and `K` length of one key + /// - `I` storage deletions. + /// - Base Weight: .378 * i µs + /// - Writes: Number of items + /// # + #[weight = ( + T::DbWeight::get().writes(keys.len() as Weight) + .saturating_add((keys.len() as Weight).saturating_mul(400_000)), + DispatchClass::Operational, + )] fn kill_storage(origin, keys: Vec) { ensure_root(origin)?; for key in &keys { @@ -547,21 +684,43 @@ decl_module! { } /// Kill all storage items with a key that starts with the given prefix. - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] - fn kill_prefix(origin, prefix: Key) { + /// + /// **NOTE:** We rely on the Root origin to provide us the number of subkeys under + /// the prefix we are removing to accurately calculate the weight of this function. + /// + /// # + /// - `O(P)` where `P` amount of keys with prefix `prefix` + /// - `P` storage deletions. + /// - Base Weight: 0.834 * P µs + /// - Writes: Number of subkeys + 1 + /// # + #[weight = ( + T::DbWeight::get().writes(Weight::from(*_subkeys) + 1) + .saturating_add((Weight::from(*_subkeys) + 1).saturating_mul(850_000)), + DispatchClass::Operational, + )] + fn kill_prefix(origin, prefix: Key, _subkeys: u32) { ensure_root(origin)?; storage::unhashed::kill_prefix(&prefix); } /// Kill the sending account, assuming there are no references outstanding and the composite /// data is equal to its default value. - #[weight = SimpleDispatchInfo::FixedOperational(25_000)] - fn suicide(origin) { + /// + /// # + /// - `O(1)` + /// - 1 storage read and deletion. + /// -------------------- + /// Base Weight: 8.626 µs + /// No DB Read or Write operations because caller is already in overlay + /// # + #[weight = (10_000_000, DispatchClass::Operational)] + pub fn suicide(origin) { let who = ensure_signed(origin)?; let account = Account::::get(&who); ensure!(account.refcount == 0, Error::::NonZeroRefCount); ensure!(account.data == T::AccountData::default(), Error::::NonDefaultComposite); - Account::::remove(who); + Self::kill_account(&who); } } } @@ -620,9 +779,12 @@ impl< #[cfg(feature = "runtime-benchmarks")] fn successful_origin() -> O { - let caller: AccountId = Default::default(); - // Who::add(&caller); - O::from(RawOrigin::Signed(caller)) + let members = Who::sorted_members(); + let first_member = match members.get(0) { + Some(account) => account.clone(), + None => Default::default(), + }; + O::from(RawOrigin::Signed(first_member.clone())) } } @@ -658,6 +820,30 @@ impl EnsureOrigin for EnsureNever { } } +/// The "OR gate" implementation of `EnsureOrigin`. +/// +/// Origin check will pass if `L` or `R` origin check passes. `L` is tested first. +pub struct EnsureOneOf(sp_std::marker::PhantomData<(AccountId, L, R)>); +impl< + AccountId, + O: Into, O>> + From>, + L: EnsureOrigin, + R: EnsureOrigin, +> EnsureOrigin for EnsureOneOf { + type Success = Either; + fn try_origin(o: O) -> Result { + L::try_origin(o).map_or_else( + |o| R::try_origin(o).map(|o| Either::Right(o)), + |o| Ok(Either::Left(o)), + ) + } + + #[cfg(feature = "runtime-benchmarks")] + fn successful_origin() -> O { + L::successful_origin() + } +} + /// 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 @@ -773,23 +959,10 @@ impl Module { old_event_count }; - // Appending can only fail if `Events` can not be decoded or - // when we try to insert more than `u32::max_value()` events. - // - // 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].iter()).is_err() { - // The most sensible thing to do here is to just ignore this event and wait until the - // new block. - return; - } + Events::::append(&event); for topic in topics { - // The same applies here. - if >::append(topic, &[(block_number, event_idx)]).is_err() { - return; - } + >::append(topic, &(block_number, event_idx)); } } @@ -803,11 +976,6 @@ impl Module { ExtrinsicCount::get().unwrap_or_default() } - /// Gets a total weight of all executed extrinsics. - pub fn all_extrinsics_weight() -> Weight { - AllExtrinsicsWeight::get().unwrap_or_default() - } - pub fn all_extrinsics_len() -> u32 { AllExtrinsicsLen::get().unwrap_or_default() } @@ -827,12 +995,10 @@ impl Module { /// of block weight is more than the block weight limit. This is what the _unchecked_. /// /// Another potential use-case could be for the `on_initialize` and `on_finalize` hooks. - /// - /// If no previous weight exists, the function initializes the weight to zero. - pub fn register_extra_weight_unchecked(weight: Weight) { - let current_weight = AllExtrinsicsWeight::get().unwrap_or_default(); - let next_weight = current_weight.saturating_add(weight).min(T::MaximumBlockWeight::get()); - AllExtrinsicsWeight::put(next_weight); + pub fn register_extra_weight_unchecked(weight: Weight, class: DispatchClass) { + BlockWeight::mutate(|current_weight| { + current_weight.add(weight, class); + }); } /// Start the execution of a particular block. @@ -852,6 +1018,10 @@ impl Module { >::insert(*number - One::one(), parent_hash); >::put(txs_root); + // Remove previous block data from storage + BlockWeight::kill(); + + // Kill inspectable storage entries in state when `InitKind::Full`. if let InitKind::Full = kind { >::kill(); EventCount::kill(); @@ -863,7 +1033,6 @@ impl Module { pub fn finalize() -> T::Header { ExecutionPhase::kill(); ExtrinsicCount::kill(); - AllExtrinsicsWeight::kill(); AllExtrinsicsLen::kill(); let number = >::take(); @@ -908,10 +1077,13 @@ impl Module { } /// Deposits a log and ensures it matches the block's log data. + /// + /// # + /// - `O(1)` + /// - 1 storage write (codec `O(1)`) + /// # pub fn deposit_log(item: DigestItemOf) { - let mut l = >::get(); - l.push(item); - >::put(l); + >::append(item); } /// Get the basic externalities for this module, useful for tests. @@ -923,7 +1095,7 @@ impl Module { >::hashed_key().to_vec() => T::BlockNumber::one().encode(), >::hashed_key().to_vec() => [69u8; 32].encode() ], - children: map![], + children_default: map![], }) } @@ -950,10 +1122,21 @@ impl Module { /// 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); + BlockWeight::mutate(|current_weight| { + current_weight.put(weight, DispatchClass::Normal) + }); AllExtrinsicsLen::put(len as u32); } + /// Reset events. Can be used as an alternative to + /// `initialize` for tests that don't need to bother with the other environment entries. + #[cfg(any(feature = "std", feature = "runtime-benchmarks", test))] + pub fn reset_events() { + >::kill(); + EventCount::kill(); + >::remove_all(); + } + /// Return the chain's current runtime version. pub fn runtime_version() -> RuntimeVersion { T::Version::get() } @@ -978,13 +1161,14 @@ impl Module { } /// To be called immediately after an extrinsic has been applied. - pub fn note_applied_extrinsic(r: &DispatchOutcome, _encoded_len: u32, info: DispatchInfo) { + pub fn note_applied_extrinsic(r: &DispatchResultWithPostInfo, mut info: DispatchInfo) { + info.weight = extract_actual_weight(r, &info); Self::deposit_event( match r { - Ok(()) => RawEvent::ExtrinsicSuccess(info), + Ok(_) => RawEvent::ExtrinsicSuccess(info), Err(err) => { sp_runtime::print(err); - RawEvent::ExtrinsicFailed(err.clone(), info) + RawEvent::ExtrinsicFailed(err.error, info) }, } ); @@ -1044,8 +1228,8 @@ impl Module { "WARNING: Referenced account deleted. This is probably a bug." ); } - Module::::on_killed_account(who.clone()); } + Module::::on_killed_account(who.clone()); } /// Determine whether or not it is possible to update the code. @@ -1091,6 +1275,15 @@ impl Happened for CallKillAccount { } } +impl BlockNumberProvider for Module +{ + type BlockNumber = ::BlockNumber; + + fn current_block_number() -> Self::BlockNumber { + Module::::block_number() + } +} + // Implement StoredMap for a simple single-item, kill-account-on-remove system. This works fine for // storing a single item which is required to not be empty/default for the account to exist. // Anything more complex will need more sophisticated logic. @@ -1160,243 +1353,6 @@ pub fn split_inner(option: Option, splitter: impl FnOnce(T) -> (R, S } } -/// resource limit check. -#[derive(Encode, Decode, Clone, Eq, PartialEq)] -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 => ::one(), - DispatchClass::Normal => T::AvailableBlockRatio::get(), - } - } - - /// 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 { - 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 { - Err(InvalidTransaction::ExhaustsResources.into()) - } else { - 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 { - 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 { - Err(InvalidTransaction::ExhaustsResources.into()) - } else { - Ok(next_len) - } - } - - /// get the priority of an extrinsic denoted by `info`. - fn get_priority(info: ::DispatchInfo) -> TransactionPriority { - match info.class { - DispatchClass::Normal => info.weight.into(), - DispatchClass::Operational => Bounded::max_value() - } - } - - /// Creates new `SignedExtension` to check weight of the extrinsic. - pub fn new() -> Self { - Self(PhantomData) - } - - /// Do the pre-dispatch checks. This can be applied to both signed and unsigned. - /// - /// It checks and notes the new weight and length. - fn do_pre_dispatch( - info: ::DispatchInfo, - len: usize, - ) -> Result<(), TransactionValidityError> { - let next_len = Self::check_block_length(info, len)?; - let next_weight = Self::check_weight(info)?; - AllExtrinsicsLen::put(next_len); - AllExtrinsicsWeight::put(next_weight); - Ok(()) - } - - /// Do the validate checks. This can be applied to both signed and unsigned. - /// - /// It only checks that the block weight and length limit will not exceed. - fn do_validate( - info: ::DispatchInfo, - len: usize, - ) -> TransactionValidity { - // ignore the next weight and length. If they return `Ok`, then it is below the limit. - let _ = Self::check_block_length(info, len)?; - let _ = Self::check_weight(info)?; - - Ok(ValidTransaction { priority: Self::get_priority(info), ..Default::default() }) - } -} - -impl SignedExtension for CheckWeight { - type AccountId = T::AccountId; - type Call = T::Call; - type AdditionalSigned = (); - type DispatchInfo = DispatchInfo; - type Pre = (); - const IDENTIFIER: &'static str = "CheckWeight"; - - fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) } - - fn pre_dispatch( - self, - _who: &Self::AccountId, - _call: &Self::Call, - info: Self::DispatchInfo, - len: usize, - ) -> Result<(), TransactionValidityError> { - Self::do_pre_dispatch(info, len) - } - - fn validate( - &self, - _who: &Self::AccountId, - _call: &Self::Call, - info: Self::DispatchInfo, - len: usize, - ) -> TransactionValidity { - Self::do_validate(info, len) - } - - fn pre_dispatch_unsigned( - _call: &Self::Call, - info: Self::DispatchInfo, - len: usize, - ) -> Result<(), TransactionValidityError> { - Self::do_pre_dispatch(info, len) - } - - fn validate_unsigned( - _call: &Self::Call, - info: Self::DispatchInfo, - len: usize, - ) -> TransactionValidity { - Self::do_validate(info, len) - } -} - -impl Debug for CheckWeight { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - write!(f, "CheckWeight") - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - Ok(()) - } -} - -/// Nonce check and increment to give replay protection for transactions. -#[derive(Encode, Decode, Clone, Eq, PartialEq)] -pub struct CheckNonce(#[codec(compact)] T::Index); - -impl CheckNonce { - /// utility constructor. Used only in client/factory code. - pub fn from(nonce: T::Index) -> Self { - Self(nonce) - } -} - -impl Debug for CheckNonce { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - write!(f, "CheckNonce({})", self.0) - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - Ok(()) - } -} - -impl SignedExtension for CheckNonce { - type AccountId = T::AccountId; - type Call = T::Call; - type AdditionalSigned = (); - type DispatchInfo = DispatchInfo; - type Pre = (); - const IDENTIFIER: &'static str = "CheckNonce"; - - fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) } - - fn pre_dispatch( - self, - who: &Self::AccountId, - _call: &Self::Call, - _info: Self::DispatchInfo, - _len: usize, - ) -> Result<(), TransactionValidityError> { - let mut account = Account::::get(who); - if self.0 != account.nonce { - return Err( - if self.0 < account.nonce { - InvalidTransaction::Stale - } else { - InvalidTransaction::Future - }.into() - ) - } - account.nonce += T::Index::one(); - Account::::insert(who, account); - Ok(()) - } - - fn validate( - &self, - who: &Self::AccountId, - _call: &Self::Call, - info: Self::DispatchInfo, - _len: usize, - ) -> TransactionValidity { - // check index - let account = Account::::get(who); - if self.0 < account.nonce { - return InvalidTransaction::Stale.into() - } - - let provides = vec![Encode::encode(&(who, self.0))]; - let requires = if account.nonce < self.0 { - vec![Encode::encode(&(who, self.0 - One::one()))] - } else { - vec![] - }; - - Ok(ValidTransaction { - priority: info.weight as TransactionPriority, - requires, - provides, - longevity: TransactionLongevity::max_value(), - propagate: true, - }) - } -} impl IsDeadAccount for Module { fn is_dead_account(who: &T::AccountId) -> bool { @@ -1404,135 +1360,6 @@ impl IsDeadAccount for Module { } } -/// Check for transaction mortality. -#[derive(Encode, Decode, Clone, Eq, PartialEq)] -pub struct CheckEra(Era, sp_std::marker::PhantomData); - -impl CheckEra { - /// utility constructor. Used only in client/factory code. - pub fn from(era: Era) -> Self { - Self(era, sp_std::marker::PhantomData) - } -} - -impl Debug for CheckEra { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - write!(f, "CheckEra({:?})", self.0) - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - Ok(()) - } -} - -impl SignedExtension for CheckEra { - type AccountId = T::AccountId; - type Call = T::Call; - type AdditionalSigned = T::Hash; - type DispatchInfo = DispatchInfo; - type Pre = (); - const IDENTIFIER: &'static str = "CheckEra"; - - fn validate( - &self, - _who: &Self::AccountId, - _call: &Self::Call, - _info: Self::DispatchInfo, - _len: usize, - ) -> TransactionValidity { - let current_u64 = >::block_number().saturated_into::(); - let valid_till = self.0.death(current_u64); - Ok(ValidTransaction { - longevity: valid_till.saturating_sub(current_u64), - ..Default::default() - }) - } - - fn additional_signed(&self) -> Result { - let current_u64 = >::block_number().saturated_into::(); - let n = self.0.birth(current_u64).saturated_into::(); - if !>::contains_key(n) { - Err(InvalidTransaction::AncientBirthBlock.into()) - } else { - Ok(>::block_hash(n)) - } - } -} - -/// Nonce check and increment to give replay protection for transactions. -#[derive(Encode, Decode, Clone, Eq, PartialEq)] -pub struct CheckGenesis(sp_std::marker::PhantomData); - -impl Debug for CheckGenesis { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - write!(f, "CheckGenesis") - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - Ok(()) - } -} - -impl CheckGenesis { - /// Creates new `SignedExtension` to check genesis hash. - pub fn new() -> Self { - Self(sp_std::marker::PhantomData) - } -} - -impl SignedExtension for CheckGenesis { - type AccountId = T::AccountId; - type Call = ::Call; - type AdditionalSigned = T::Hash; - type DispatchInfo = DispatchInfo; - type Pre = (); - const IDENTIFIER: &'static str = "CheckGenesis"; - - fn additional_signed(&self) -> Result { - Ok(>::block_hash(T::BlockNumber::zero())) - } -} - -/// Ensure the runtime version registered in the transaction is the same as at present. -#[derive(Encode, Decode, Clone, Eq, PartialEq)] -pub struct CheckVersion(sp_std::marker::PhantomData); - -impl Debug for CheckVersion { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - write!(f, "CheckVersion") - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - Ok(()) - } -} - -impl CheckVersion { - /// Create new `SignedExtension` to check runtime version. - pub fn new() -> Self { - Self(sp_std::marker::PhantomData) - } -} - -impl SignedExtension for CheckVersion { - type AccountId = T::AccountId; - type Call = ::Call; - type AdditionalSigned = u32; - type DispatchInfo = DispatchInfo; - type Pre = (); - const IDENTIFIER: &'static str = "CheckVersion"; - - fn additional_signed(&self) -> Result { - Ok(>::runtime_version().spec_version) - } -} - pub struct ChainContext(sp_std::marker::PhantomData); impl Default for ChainContext { fn default() -> Self { @@ -1548,542 +1375,3 @@ impl Lookup for ChainContext { ::lookup(s) } } - -#[cfg(test)] -mod tests { - use super::*; - use sp_std::cell::RefCell; - use sp_core::H256; - use sp_runtime::{traits::{BlakeTwo256, IdentityLookup}, testing::Header, DispatchError}; - use frame_support::{impl_outer_origin, parameter_types}; - - impl_outer_origin! { - pub enum Origin for Test where system = super {} - } - - #[derive(Clone, Eq, PartialEq)] - pub struct Test; - - parameter_types! { - pub const BlockHashCount: u64 = 10; - pub const MaximumBlockWeight: Weight = 1024; - pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); - pub const MaximumBlockLength: u32 = 1024; - pub const Version: RuntimeVersion = RuntimeVersion { - spec_name: sp_version::create_runtime_str!("test"), - impl_name: sp_version::create_runtime_str!("system-test"), - authoring_version: 1, - spec_version: 1, - impl_version: 1, - apis: sp_version::create_apis_vec!([]), - }; - } - - thread_local!{ - pub static KILLED: RefCell> = RefCell::new(vec![]); - } - - pub struct RecordKilled; - impl OnKilledAccount for RecordKilled { - fn on_killed_account(who: &u64) { KILLED.with(|r| r.borrow_mut().push(*who)) } - } - - impl Trait for Test { - type Origin = Origin; - type Call = (); - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = u16; - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type AvailableBlockRatio = AvailableBlockRatio; - type MaximumBlockLength = MaximumBlockLength; - type Version = Version; - type ModuleToIndex = (); - type AccountData = u32; - type OnNewAccount = (); - type OnKilledAccount = RecordKilled; - } - - impl From> for u16 { - fn from(e: Event) -> u16 { - match e { - Event::::ExtrinsicSuccess(..) => 100, - Event::::ExtrinsicFailed(..) => 101, - Event::::CodeUpdated => 102, - _ => 103, - } - } - } - - type System = Module; - - const CALL: &::Call = &(); - - fn new_test_ext() -> sp_io::TestExternalities { - GenesisConfig::default().build_storage::().unwrap().into() - } - - fn normal_weight_limit() -> Weight { - ::AvailableBlockRatio::get() * ::MaximumBlockWeight::get() - } - - fn normal_length_limit() -> u32 { - ::AvailableBlockRatio::get() * ::MaximumBlockLength::get() - } - - #[test] - fn origin_works() { - let o = Origin::from(RawOrigin::::Signed(1u64)); - let x: Result, Origin> = o.into(); - assert_eq!(x, Ok(RawOrigin::::Signed(1u64))); - } - - #[test] - fn stored_map_works() { - new_test_ext().execute_with(|| { - System::insert(&0, 42); - assert!(System::allow_death(&0)); - - System::inc_ref(&0); - assert!(!System::allow_death(&0)); - - System::insert(&0, 69); - assert!(!System::allow_death(&0)); - - System::dec_ref(&0); - assert!(System::allow_death(&0)); - - assert!(KILLED.with(|r| r.borrow().is_empty())); - System::kill_account(&0); - assert_eq!(KILLED.with(|r| r.borrow().clone()), vec![0u64]); - }); - } - - #[test] - fn deposit_event_should_work() { - new_test_ext().execute_with(|| { - System::initialize( - &1, - &[0u8; 32].into(), - &[0u8; 32].into(), - &Default::default(), - InitKind::Full, - ); - System::note_finished_extrinsics(); - System::deposit_event(1u16); - System::finalize(); - assert_eq!( - System::events(), - vec![ - EventRecord { - phase: Phase::Finalization, - event: 1u16, - topics: vec![], - } - ] - ); - - System::initialize( - &2, - &[0u8; 32].into(), - &[0u8; 32].into(), - &Default::default(), - InitKind::Full, - ); - System::deposit_event(32u16); - System::note_finished_initialize(); - System::deposit_event(42u16); - System::note_applied_extrinsic(&Ok(()), 0, Default::default()); - System::note_applied_extrinsic(&Err(DispatchError::BadOrigin), 0, Default::default()); - System::note_finished_extrinsics(); - System::deposit_event(3u16); - System::finalize(); - assert_eq!( - System::events(), - vec![ - EventRecord { phase: Phase::Initialization, event: 32u16, topics: 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() { - new_test_ext().execute_with(|| { - const BLOCK_NUMBER: u64 = 1; - - System::initialize( - &BLOCK_NUMBER, - &[0u8; 32].into(), - &[0u8; 32].into(), - &Default::default(), - InitKind::Full, - ); - System::note_finished_extrinsics(); - - let topics = vec![ - H256::repeat_byte(1), - H256::repeat_byte(2), - H256::repeat_byte(3), - ]; - - // We deposit a few events with different sets of topics. - System::deposit_event_indexed(&topics[0..3], 1u16); - System::deposit_event_indexed(&topics[0..1], 2u16); - System::deposit_event_indexed(&topics[1..2], 3u16); - - System::finalize(); - - // Check that topics are reflected in the event record. - assert_eq!( - System::events(), - vec![ - EventRecord { - phase: Phase::Finalization, - event: 1u16, - topics: topics[0..3].to_vec(), - }, - EventRecord { - phase: Phase::Finalization, - event: 2u16, - topics: topics[0..1].to_vec(), - }, - EventRecord { - phase: Phase::Finalization, - event: 3u16, - topics: topics[1..2].to_vec(), - } - ] - ); - - // Check that the topic-events mapping reflects the deposited topics. - // Note that these are indexes of the events. - assert_eq!( - System::event_topics(&topics[0]), - vec![(BLOCK_NUMBER, 0), (BLOCK_NUMBER, 1)], - ); - assert_eq!( - System::event_topics(&topics[1]), - vec![(BLOCK_NUMBER, 0), (BLOCK_NUMBER, 2)], - ); - assert_eq!( - System::event_topics(&topics[2]), - vec![(BLOCK_NUMBER, 0)], - ); - }); - } - - #[test] - fn prunes_block_hash_mappings() { - new_test_ext().execute_with(|| { - // simulate import of 15 blocks - for n in 1..=15 { - System::initialize( - &n, - &[n as u8 - 1; 32].into(), - &[0u8; 32].into(), - &Default::default(), - InitKind::Full, - ); - - System::finalize(); - } - - // first 5 block hashes are pruned - for n in 0..5 { - assert_eq!( - System::block_hash(n), - H256::zero(), - ); - } - - // the remaining 10 are kept - for n in 5..15 { - assert_eq!( - System::block_hash(n), - [n as u8; 32].into(), - ); - } - }) - } - - #[test] - fn signed_ext_check_nonce_works() { - new_test_ext().execute_with(|| { - Account::::insert(1, AccountInfo { nonce: 1, refcount: 0, data: 0 }); - let info = DispatchInfo::default(); - let len = 0_usize; - // stale - assert!(CheckNonce::(0).validate(&1, CALL, info, len).is_err()); - assert!(CheckNonce::(0).pre_dispatch(&1, CALL, info, len).is_err()); - // correct - assert!(CheckNonce::(1).validate(&1, CALL, info, len).is_ok()); - assert!(CheckNonce::(1).pre_dispatch(&1, CALL, info, len).is_ok()); - // future - assert!(CheckNonce::(5).validate(&1, CALL, info, len).is_ok()); - assert!(CheckNonce::(5).pre_dispatch(&1, CALL, info, len).is_err()); - }) - } - - #[test] - fn signed_ext_check_weight_works_normal_tx() { - new_test_ext().execute_with(|| { - let normal_limit = normal_weight_limit(); - let small = DispatchInfo { weight: 100, ..Default::default() }; - let medium = DispatchInfo { - weight: normal_limit - 1, - ..Default::default() - }; - let big = DispatchInfo { - weight: normal_limit + 1, - ..Default::default() - }; - let len = 0_usize; - - let reset_check_weight = |i, f, s| { - AllExtrinsicsWeight::put(s); - let r = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, i, len); - if f { assert!(r.is_err()) } else { assert!(r.is_ok()) } - }; - - reset_check_weight(small, false, 0); - reset_check_weight(medium, false, 0); - reset_check_weight(big, true, 1); - }) - } - - #[test] - fn signed_ext_check_weight_fee_works() { - new_test_ext().execute_with(|| { - let free = DispatchInfo { weight: 0, ..Default::default() }; - let len = 0_usize; - - assert_eq!(System::all_extrinsics_weight(), 0); - let r = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, free, len); - assert!(r.is_ok()); - assert_eq!(System::all_extrinsics_weight(), 0); - }) - } - - #[test] - fn signed_ext_check_weight_max_works() { - new_test_ext().execute_with(|| { - let max = DispatchInfo { weight: Weight::max_value(), ..Default::default() }; - let len = 0_usize; - let normal_limit = normal_weight_limit(); - - assert_eq!(System::all_extrinsics_weight(), 0); - let r = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, max, len); - assert!(r.is_ok()); - assert_eq!(System::all_extrinsics_weight(), normal_limit); - }) - } - - #[test] - fn signed_ext_check_weight_works_operational_tx() { - new_test_ext().execute_with(|| { - let normal = DispatchInfo { weight: 100, ..Default::default() }; - let op = DispatchInfo { weight: 100, class: DispatchClass::Operational, pays_fee: true }; - let len = 0_usize; - let normal_limit = normal_weight_limit(); - - // given almost full block - AllExtrinsicsWeight::put(normal_limit); - // will not fit. - assert!(CheckWeight::(PhantomData).pre_dispatch(&1, CALL, normal, len).is_err()); - // will fit. - assert!(CheckWeight::(PhantomData).pre_dispatch(&1, CALL, op, len).is_ok()); - - // likewise for length limit. - let len = 100_usize; - AllExtrinsicsLen::put(normal_length_limit()); - assert!(CheckWeight::(PhantomData).pre_dispatch(&1, CALL, normal, len).is_err()); - assert!(CheckWeight::(PhantomData).pre_dispatch(&1, CALL, op, len).is_ok()); - }) - } - - #[test] - fn signed_ext_check_weight_priority_works() { - new_test_ext().execute_with(|| { - let normal = DispatchInfo { weight: 100, class: DispatchClass::Normal, pays_fee: true }; - let op = DispatchInfo { weight: 100, class: DispatchClass::Operational, pays_fee: true }; - let len = 0_usize; - - 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, u64::max_value()); - }) - } - - #[test] - fn signed_ext_check_weight_block_size_works() { - new_test_ext().execute_with(|| { - let normal = DispatchInfo::default(); - let normal_limit = normal_weight_limit() as usize; - let reset_check_weight = |tx, s, f| { - AllExtrinsicsLen::put(0); - let r = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, tx, s); - if f { assert!(r.is_err()) } else { assert!(r.is_ok()) } - }; - - reset_check_weight(normal, normal_limit - 1, false); - reset_check_weight(normal, normal_limit, false); - reset_check_weight(normal, normal_limit + 1, true); - - // Operational ones don't have this limit. - let op = DispatchInfo { weight: 0, class: DispatchClass::Operational, pays_fee: true }; - reset_check_weight(op, normal_limit, false); - reset_check_weight(op, normal_limit + 100, false); - reset_check_weight(op, 1024, false); - reset_check_weight(op, 1025, true); - }) - } - - #[test] - fn signed_ext_check_era_should_work() { - new_test_ext().execute_with(|| { - // future - assert_eq!( - CheckEra::::from(Era::mortal(4, 2)).additional_signed().err().unwrap(), - InvalidTransaction::AncientBirthBlock.into(), - ); - - // correct - System::set_block_number(13); - >::insert(12, H256::repeat_byte(1)); - assert!(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, pays_fee: true }; - 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); - }) - } - - - #[test] - fn set_code_checks_works() { - struct CallInWasm(Vec); - - impl sp_core::traits::CallInWasm for CallInWasm { - fn call_in_wasm( - &self, - _: &[u8], - _: Option>, - _: &str, - _: &[u8], - _: &mut dyn sp_externalities::Externalities, - ) -> Result, String> { - Ok(self.0.clone()) - } - } - - let test_data = vec![ - ("test", 1, 2, Err(Error::::SpecVersionNeedsToIncrease)), - ("test", 1, 1, Err(Error::::SpecVersionNeedsToIncrease)), - ("test2", 1, 1, Err(Error::::InvalidSpecName)), - ("test", 2, 1, Ok(())), - ("test", 0, 1, Err(Error::::SpecVersionNeedsToIncrease)), - ("test", 1, 0, Err(Error::::SpecVersionNeedsToIncrease)), - ]; - - for (spec_name, spec_version, impl_version, expected) in test_data.into_iter() { - let version = RuntimeVersion { - spec_name: spec_name.into(), - spec_version, - impl_version, - ..Default::default() - }; - let call_in_wasm = CallInWasm(version.encode()); - - let mut ext = new_test_ext(); - ext.register_extension(sp_core::traits::CallInWasmExt::new(call_in_wasm)); - ext.execute_with(|| { - let res = System::set_code( - RawOrigin::Root.into(), - vec![1, 2, 3, 4], - ); - - assert_eq!(expected.map_err(DispatchError::from), res); - }); - } - } - - #[test] - fn set_code_with_real_wasm_blob() { - let executor = substrate_test_runtime_client::new_native_executor(); - let mut ext = new_test_ext(); - ext.register_extension(sp_core::traits::CallInWasmExt::new(executor)); - ext.execute_with(|| { - System::set_block_number(1); - System::set_code( - RawOrigin::Root.into(), - substrate_test_runtime_client::runtime::WASM_BINARY.to_vec(), - ).unwrap(); - - assert_eq!( - System::events(), - vec![EventRecord { phase: Phase::Initialization, event: 102u16, topics: vec![] }], - ); - }); - } - - #[test] - fn runtime_upgraded_with_set_storage() { - let executor = substrate_test_runtime_client::new_native_executor(); - let mut ext = new_test_ext(); - ext.register_extension(sp_core::traits::CallInWasmExt::new(executor)); - ext.execute_with(|| { - System::set_storage( - RawOrigin::Root.into(), - vec![( - well_known_keys::CODE.to_vec(), - substrate_test_runtime_client::runtime::WASM_BINARY.to_vec() - )], - ).unwrap(); - }); - } - - #[test] - fn events_not_emitted_during_genesis() { - new_test_ext().execute_with(|| { - // Block Number is zero at genesis - assert!(System::block_number().is_zero()); - System::on_created_account(Default::default()); - assert!(System::events().is_empty()); - // Events will be emitted starting on block 1 - System::set_block_number(1); - System::on_created_account(Default::default()); - assert!(System::events().len() == 1); - }); - } -} diff --git a/frame/system/src/mock.rs b/frame/system/src/mock.rs new file mode 100644 index 0000000000000000000000000000000000000000..d7c4d1c9e7b20d6717e1e940c1ef1d391c01a460 --- /dev/null +++ b/frame/system/src/mock.rs @@ -0,0 +1,125 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::*; +use sp_std::cell::RefCell; +use sp_core::H256; +use sp_runtime::{ + traits::{BlakeTwo256, IdentityLookup}, + testing::Header, +}; +use frame_support::{ + impl_outer_origin, parameter_types, + weights::PostDispatchInfo, +}; + +impl_outer_origin! { + pub enum Origin for Test where system = super {} +} + +#[derive(Clone, Eq, PartialEq, Debug, Default)] +pub struct Test; + +parameter_types! { + pub const BlockHashCount: u64 = 10; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumExtrinsicWeight: Weight = 768; + pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); + pub const MaximumBlockLength: u32 = 1024; + pub Version: RuntimeVersion = RuntimeVersion { + spec_name: sp_version::create_runtime_str!("test"), + impl_name: sp_version::create_runtime_str!("system-test"), + authoring_version: 1, + spec_version: 1, + impl_version: 1, + apis: sp_version::create_apis_vec!([]), + transaction_version: 1, + }; + pub const BlockExecutionWeight: Weight = 10; + pub const ExtrinsicBaseWeight: Weight = 5; + pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { + read: 10, + write: 100, + }; +} + +thread_local!{ + pub static KILLED: RefCell> = RefCell::new(vec![]); +} + +pub struct RecordKilled; +impl OnKilledAccount for RecordKilled { + fn on_killed_account(who: &u64) { KILLED.with(|r| r.borrow_mut().push(*who)) } +} + +#[derive(Debug, codec::Encode, codec::Decode)] +pub struct Call; + +impl Dispatchable for Call { + type Origin = Origin; + type Trait = (); + type Info = DispatchInfo; + type PostInfo = PostDispatchInfo; + fn dispatch(self, _origin: Self::Origin) + -> sp_runtime::DispatchResultWithInfo { + panic!("Do not use dummy implementation for dispatch."); + } +} + +impl Trait for Test { + type BaseCallFilter = (); + type Origin = Origin; + type Call = Call; + type Index = u64; + type BlockNumber = u64; + 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 DbWeight = DbWeight; + type BlockExecutionWeight = BlockExecutionWeight; + type ExtrinsicBaseWeight = ExtrinsicBaseWeight; + type MaximumExtrinsicWeight = MaximumExtrinsicWeight; + type AvailableBlockRatio = AvailableBlockRatio; + type MaximumBlockLength = MaximumBlockLength; + type Version = Version; + type ModuleToIndex = (); + type AccountData = u32; + type OnNewAccount = (); + type OnKilledAccount = RecordKilled; + type SystemWeightInfo = (); +} + +pub type System = Module; +pub type SysEvent = ::Event; + +pub const CALL: &::Call = &Call; + +/// Create new externalities for `System` module tests. +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut ext: sp_io::TestExternalities = GenesisConfig::default().build_storage::().unwrap().into(); + // Add to each test the initial weight of a block + ext.execute_with(|| System::register_extra_weight_unchecked( + ::BlockExecutionWeight::get(), + DispatchClass::Mandatory + )); + ext +} diff --git a/frame/system/src/offchain.rs b/frame/system/src/offchain.rs index a3fe3e00ca4be879ed6074cc6b13f75e0fbae83f..1290ca6378eb88aa87c41eddd423fb8c02d78700 100644 --- a/frame/system/src/offchain.rs +++ b/frame/system/src/offchain.rs @@ -1,367 +1,848 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Module helpers for off-chain calls. +//! +//! ## Overview +//! +//! This module provides transaction related helpers to: +//! - Submit a raw unsigned transaction +//! - Submit an unsigned transaction with a signed payload +//! - Submit a signed transction. +//! +//! ## Usage +//! +//! Please refer to [`example-offchain-worker`](../../pallet_example_offchain_worker/index.html) for +//! a concrete example usage of this crate. +//! +//! ### Submit a raw unsigned transaction +//! +//! To submit a raw unsigned transaction, [`SubmitTransaction`](./struct.SubmitTransaction.html) +//! can be used. +//! +//! ### Signing transactions +//! +//! To be able to use signing, the following trait should be implemented: +//! +//! - [`AppCrypto`](./trait.AppCrypto.html): where an application-specific key +//! is defined and can be used by this module's helpers for signing. +//! - [`CreateSignedTransaction`](./trait.CreateSignedTransaction.html): where +//! the manner in which the transaction is constructed is defined. +//! +//! #### Submit an unsigned transaction with a signed payload +//! +//! Initially, a payload instance that implements the `SignedPayload` trait should be defined. +//! See [`PricePayload`](../../pallet_example_offchain_worker/struct.PricePayload.html) +//! +//! The payload type that is defined defined can then be signed and submitted onchain. +//! +//! #### Submit a signed transaction +//! +//! [`Signer`](./struct.Signer.html) can be used to sign/verify payloads +//! + +#![warn(missing_docs)] use codec::Encode; -use sp_std::convert::TryInto; -use sp_std::prelude::Vec; -use sp_runtime::app_crypto::{RuntimeAppPublic, AppPublic, AppSignature}; +use sp_std::collections::btree_set::BTreeSet; +use sp_std::convert::{TryInto, TryFrom}; +use sp_std::prelude::{Box, Vec}; +use sp_runtime::app_crypto::RuntimeAppPublic; use sp_runtime::traits::{Extrinsic as ExtrinsicT, IdentifyAccount, One}; -use frame_support::{debug, storage::StorageMap}; +use frame_support::{debug, storage::StorageMap, RuntimeDebug}; + +/// Marker struct used to flag using all supported keys to sign a payload. +pub struct ForAll {} +/// Marker struct used to flag using any of the supported keys to sign a payload. +pub struct ForAny {} -/// Creates runtime-specific signed transaction. +/// Provides the ability to directly submit signed and unsigned +/// transaction onchain. /// -/// This trait should be implemented by your `Runtime` to be able -/// to submit `SignedTransaction`s` to the pool from off-chain code. -pub trait CreateTransaction { - /// A `Public` key representing a particular `AccountId`. - type Public: IdentifyAccount + Clone; - /// A `Signature` generated by the `Signer`. - type Signature; +/// For submitting unsigned transactions, `submit_unsigned_transaction` +/// utility function can be used. However, this struct is used by `Signer` +/// to submit a signed transactions providing the signature along with the call. +pub struct SubmitTransaction, OverarchingCall> { + _phantom: sp_std::marker::PhantomData<(T, OverarchingCall)> +} - /// 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)>; +impl SubmitTransaction +where + T: SendTransactionTypes, +{ + /// Submit transaction onchain by providing the call and an optional signature + pub fn submit_transaction( + call: >::OverarchingCall, + signature: Option<::SignaturePayload>, + ) -> Result<(), ()> { + let xt = T::Extrinsic::new(call.into(), signature).ok_or(())?; + sp_io::offchain::submit_transaction(xt.encode()) + } + + /// A convenience method to submit an unsigned transaction onchain. + pub fn submit_unsigned_transaction( + call: >::OverarchingCall, + ) -> Result<(), ()> { + SubmitTransaction::::submit_transaction(call, None) + } } -/// A trait responsible for signing a payload using given account. +/// Provides an implementation for signing transaction payloads. /// -/// This trait is usually going to represent a local public key -/// that has ability to sign arbitrary `Payloads`. +/// Keys used for signing are defined when instantiating the signer object. +/// Signing can be done using: /// -/// NOTE: Most likely you don't need to implement this trait manually. -/// It has a blanket implementation for all `RuntimeAppPublic` types, -/// so it's enough to pass an application-specific crypto type. +/// - All supported keys in the keystore +/// - Any of the supported keys in the keystore +/// - An intersection of in-keystore keys and the list of provided keys /// -/// To easily create `SignedTransaction`s have a look at the -/// [`TransactionSubmitter`] type. -pub trait Signer { - /// Sign any encodable payload with given account and produce a signature. +/// The signer is then able to: +/// - Submit a unsigned transaction with a signed payload +/// - Submit a signed transaction +#[derive(RuntimeDebug)] +pub struct Signer, X = ForAny> { + accounts: Option>, + _phantom: sp_std::marker::PhantomData<(X, C)>, +} + +impl, X> Default for Signer { + fn default() -> Self { + Self { + accounts: Default::default(), + _phantom: Default::default(), + } + } +} + +impl, X> Signer { + /// Use all available keys for signing. + pub fn all_accounts() -> Signer { + Default::default() + } + + /// Use any of the available keys for signing. + pub fn any_account() -> Signer { + Default::default() + } + + /// Use provided `accounts` for signing. /// - /// Returns `Some` if signing succeeded and `None` in case the `account` couldn't - /// be used (for instance we couldn't convert it to required application specific crypto). - fn sign(public: Public, payload: &Payload) -> Option; + /// Note that not all keys will be necessarily used. The provided + /// vector of accounts will be intersected with the supported keys + /// in the keystore and the resulting list will be used for signing. + pub fn with_filter(mut self, accounts: Vec) -> Self { + self.accounts = Some(accounts); + self + } + + /// Check if there are any keys that could be used for signing. + pub fn can_sign(&self) -> bool { + self.accounts_from_keys().count() > 0 + } + + /// Return a vector of the intersection between + /// all available accounts and the provided accounts + /// in `with_filter`. If no accounts are provided, + /// use all accounts by default. + fn accounts_from_keys<'a>(&'a self) -> Box> + 'a> { + let keystore_accounts = self.keystore_accounts(); + match self.accounts { + None => Box::new(keystore_accounts), + Some(ref keys) => { + let keystore_lookup: BTreeSet<::Public> = keystore_accounts + .map(|account| account.public).collect(); + + Box::new(keys.into_iter() + .enumerate() + .map(|(index, key)| { + let account_id = key.clone().into_account(); + Account::new(index, account_id, key.clone()) + }) + .filter(move |account| keystore_lookup.contains(&account.public))) + } + } + } + + fn keystore_accounts(&self) -> impl Iterator> { + C::RuntimeAppPublic::all() + .into_iter() + .enumerate() + .map(|(index, key)| { + let generic_public = C::GenericPublic::from(key); + let public = generic_public.into(); + let account_id = public.clone().into_account(); + Account::new(index, account_id, public.clone()) + }) + } } -/// A `Signer` implementation for any `AppPublic` type. -/// -/// This implementation additionally 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 TAnyAppPublic where - TAnyAppPublic: RuntimeAppPublic - + AppPublic - + From<::Generic>, - ::Signature: AppSignature, - Signature: From< - <::Signature as AppSignature>::Generic - >, - Public: TryInto<::Generic> -{ - fn sign(public: Public, raw_payload: &Payload) -> Option { - raw_payload.using_encoded(|payload| { - let public = public.try_into().ok()?; - TAnyAppPublic::from(public).sign(&payload) - .map( - <::Signature as AppSignature> - ::Generic::from - ) - .map(Signature::from) + +impl> Signer { + fn for_all(&self, f: F) -> Vec<(Account, R)> where + F: Fn(&Account) -> Option, + { + let accounts = self.accounts_from_keys(); + accounts + .into_iter() + .filter_map(|account| { + f(&account).map(|res| (account, res)) + }) + .collect() + } +} + +impl> Signer { + fn for_any(&self, f: F) -> Option<(Account, R)> where + F: Fn(&Account) -> Option, + { + let accounts = self.accounts_from_keys(); + for account in accounts.into_iter() { + let res = f(&account); + if let Some(res) = res { + return Some((account, res)); + } + } + None + } +} + +impl> SignMessage for Signer { + type SignatureData = Vec<(Account, T::Signature)>; + + fn sign_message(&self, message: &[u8]) -> Self::SignatureData { + self.for_all(|account| C::sign(message, account.public.clone())) + } + + fn sign(&self, f: F) -> Self::SignatureData where + F: Fn(&Account) -> TPayload, + TPayload: SignedPayload, + { + self.for_all(|account| f(account).sign::()) + } +} + +impl> SignMessage for Signer { + type SignatureData = Option<(Account, T::Signature)>; + + fn sign_message(&self, message: &[u8]) -> Self::SignatureData { + self.for_any(|account| C::sign(message, account.public.clone())) + } + + fn sign(&self, f: F) -> Self::SignatureData where + F: Fn(&Account) -> TPayload, + TPayload: SignedPayload, + { + self.for_any(|account| f(account).sign::()) + } +} + +impl< + T: CreateSignedTransaction + SigningTypes, + C: AppCrypto, + LocalCall, +> SendSignedTransaction for Signer { + type Result = Option<(Account, Result<(), ()>)>; + + fn send_signed_transaction( + &self, + f: impl Fn(&Account) -> LocalCall, + ) -> Self::Result { + self.for_any(|account| { + let call = f(account); + self.send_single_signed_transaction(account, call) }) } } -/// Retrieves a public key type for given `SignAndSubmitTransaction`. -pub type PublicOf = -< - >::CreateTransaction - as - CreateTransaction>::Extrinsic> ->::Public; +impl< + T: SigningTypes + CreateSignedTransaction, + C: AppCrypto, + LocalCall, +> SendSignedTransaction for Signer { + type Result = Vec<(Account, Result<(), ()>)>; + + fn send_signed_transaction( + &self, + f: impl Fn(&Account) -> LocalCall, + ) -> Self::Result { + self.for_all(|account| { + let call = f(account); + self.send_single_signed_transaction(account, call) + }) + } +} + +impl< + T: SigningTypes + SendTransactionTypes, + C: AppCrypto, + LocalCall, +> SendUnsignedTransaction for Signer { + type Result = Option<(Account, Result<(), ()>)>; + + fn send_unsigned_transaction( + &self, + f: F, + f2: impl Fn(TPayload, T::Signature) -> LocalCall, + ) -> Self::Result + where + F: Fn(&Account) -> TPayload, + TPayload: SignedPayload, + { + self.for_any(|account| { + let payload = f(account); + let signature= payload.sign::()?; + let call = f2(payload, signature); + self.submit_unsigned_transaction(call) + }) + } +} + +impl< + T: SigningTypes + SendTransactionTypes, + C: AppCrypto, + LocalCall, +> SendUnsignedTransaction for Signer { + type Result = Vec<(Account, Result<(), ()>)>; + + fn send_unsigned_transaction( + &self, + f: F, + f2: impl Fn(TPayload, T::Signature) -> LocalCall, + ) -> Self::Result + where + F: Fn(&Account) -> TPayload, + TPayload: SignedPayload { + self.for_all(|account| { + let payload = f(account); + let signature = payload.sign::()?; + let call = f2(payload, signature); + self.submit_unsigned_transaction(call) + }) + } +} + +/// Details of an account for which a private key is contained in the keystore. +#[derive(RuntimeDebug, PartialEq)] +pub struct Account { + /// Index on the provided list of accounts or list of all accounts. + pub index: usize, + /// Runtime-specific `AccountId`. + pub id: T::AccountId, + /// A runtime-specific `Public` key for that key pair. + pub public: T::Public, +} + +impl Account { + /// Create a new Account instance + pub fn new(index: usize, id: T::AccountId, public: T::Public) -> Self { + Self { index, id, public } + } +} -/// A trait to sign and submit transactions in off-chain calls. +impl Clone for Account where + T::AccountId: Clone, + T::Public: Clone, +{ + fn clone(&self) -> Self { + Self { + index: self.index, + id: self.id.clone(), + public: self.public.clone(), + } + } +} + +/// A type binding runtime-level `Public/Signature` pair with crypto wrapped by `RuntimeAppPublic`. /// -/// NOTE: Most likely you should not implement this trait yourself. -/// There is an implementation for -/// [`TransactionSubmitter`] type, which -/// you should use. -pub trait SignAndSubmitTransaction { - /// Unchecked extrinsic type. - type Extrinsic: ExtrinsicT + 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 mut account = super::Account::::get(&id); - debug::native::debug!( - target: "offchain", - "Creating signed transaction from account: {:?} (nonce: {:?})", - id, - account.nonce, - ); - let (call, signature_data) = Self::CreateTransaction - ::create_transaction::(call, public, id.clone(), account.nonce) - .ok_or(())?; - // increment the nonce. This is fine, since the code should always - // be running in off-chain context, so we NEVER persists data. - account.nonce += One::one(); - super::Account::::insert(&id, account); - - let xt = Self::Extrinsic::new(call, Some(signature_data)).ok_or(())?; - sp_io::offchain::submit_transaction(xt.encode()) +/// Implementations of this trait should specify the app-specific public/signature types. +/// This is merely a wrapper around an existing `RuntimeAppPublic` type, but with +/// extra non-application-specific crypto type that is being wrapped (e.g. `sr25519`, `ed25519`). +/// This is needed to later on convert into runtime-specific `Public` key, which might support +/// multiple different crypto. +/// The point of this trait is to be able to easily convert between `RuntimeAppPublic`, the wrapped +/// (generic = non application-specific) crypto types and the `Public` type required by the runtime. +/// +/// TODO [#5662] Potentially use `IsWrappedBy` types, or find some other way to make it easy to +/// obtain unwrapped crypto (and wrap it back). +/// +/// Example (pseudo-)implementation: +/// ```ignore +/// // im-online specific crypto +/// type RuntimeAppPublic = ImOnline(sr25519::Public); +/// +/// // wrapped "raw" crypto +/// type GenericPublic = sr25519::Public; +/// type GenericSignature = sr25519::Signature; +/// +/// // runtime-specific public key +/// type Public = MultiSigner: From; +/// type Signature = MulitSignature: From; +/// ``` +pub trait AppCrypto { + /// A application-specific crypto. + type RuntimeAppPublic: RuntimeAppPublic; + + /// A raw crypto public key wrapped by `RuntimeAppPublic`. + type GenericPublic: + From + + Into + + TryFrom + + Into; + + /// A matching raw crypto `Signature` type. + type GenericSignature: + From<::Signature> + + Into<::Signature> + + TryFrom + + Into; + + /// Sign payload with the private key to maps to the provided public key. + fn sign(payload: &[u8], public: Public) -> Option { + let p: Self::GenericPublic = public.try_into().ok()?; + let x = Into::::into(p); + x.sign(&payload) + .map(|x| { + let sig: Self::GenericSignature = x.into(); + sig + }) + .map(Into::into) + } + + /// Verify signature against the provided public key. + fn verify(payload: &[u8], public: Public, signature: Signature) -> bool { + let p: Self::GenericPublic = match public.try_into() { + Ok(a) => a, + _ => return false + }; + let x = Into::::into(p); + let signature: Self::GenericSignature = match signature.try_into() { + Ok(a) => a, + _ => return false + }; + let signature = Into::<< + Self::RuntimeAppPublic as RuntimeAppPublic + >::Signature>::into(signature); + + x.verify(&payload, &signature) } } -/// A trait to submit unsigned transactions in off-chain calls. +/// A wrapper around the types which are used for signing. /// -/// NOTE: Most likely you should not implement this trait yourself. -/// There is an implementation for -/// [`TransactionSubmitter`] type, which -/// you should use. -pub trait SubmitUnsignedTransaction { - /// Unchecked extrinsic type. - type Extrinsic: ExtrinsicT + Encode; - - /// Submit given call to the transaction pool as unsigned transaction. +/// This trait adds extra bounds to `Public` and `Signature` types of the runtime +/// that are necessary to use these types for signing. +/// +/// TODO [#5663] Could this be just `T::Signature as traits::Verify>::Signer`? +/// Seems that this may cause issues with bounds resolution. +pub trait SigningTypes: crate::Trait { + /// A public key that is capable of identifing `AccountId`s. /// - /// 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(())?; - let encoded_xt = xt.encode(); - sp_io::offchain::submit_transaction(encoded_xt) - } + /// Usually that's either a raw crypto public key (e.g. `sr25519::Public`) or + /// an aggregate type for multiple crypto public keys, like `MulitSigner`. + type Public: Clone + + PartialEq + + IdentifyAccount + + core::fmt::Debug + + codec::Codec + + Ord; + + /// A matching `Signature` type. + type Signature: Clone + + PartialEq + + core::fmt::Debug + + codec::Codec; +} + +/// A definition of types required to submit transactions from within the runtime. +pub trait SendTransactionTypes { + /// The extrinsic type expected by the runtime. + type Extrinsic: ExtrinsicT + codec::Encode; + /// The runtime's call type. + /// + /// This has additional bound to be able to be created from pallet-local `Call` types. + type OverarchingCall: From; } -/// A utility trait to easily create signed transactions -/// from accounts in node's local keystore. +/// Create signed transaction. /// -/// NOTE: Most likely you should not implement this trait yourself. -/// There is an implementation for -/// [`TransactionSubmitter`] type, which -/// you should use. -pub trait SubmitSignedTransaction { - /// A `SignAndSubmitTransaction` implementation. - type SignAndSubmit: SignAndSubmitTransaction; - - /// Find local keys that match given list of accounts. +/// This trait is meant to be implemented by the runtime and is responsible for constructing +/// a payload to be signed and contained within the extrinsic. +/// This will most likely include creation of `SignedExtra` (a set of `SignedExtensions`). +/// Note that the result can be altered by inspecting the `Call` (for instance adjusting +/// fees, or mortality depending on the `pallet` being called). +pub trait CreateSignedTransaction: SendTransactionTypes + SigningTypes { + /// Attempt to create signed extrinsic data that encodes call from given account. /// - /// Technically it finds an intersection between given list of `AccountId`s - /// and accounts that are represented by public keys in local keystore. - /// If `None` is passed it returns all accounts in the keystore. + /// 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: Self::OverarchingCall, + public: Self::Public, + account: Self::AccountId, + nonce: Self::Index, + ) -> Option<(Self::OverarchingCall, ::SignaturePayload)>; +} + +/// A message signer. +pub trait SignMessage { + /// A signature data. /// - /// Returns both public keys and `AccountId`s of accounts that are available. - /// Such accounts can later be used to sign a payload or send signed transactions. - fn find_local_keys(accounts: Option>) -> Vec<( - T::AccountId, - PublicOf, - )>; - - /// Find all available local keys. + /// May contain account used for signing and the `Signature` itself. + type SignatureData; + + /// Sign a message. /// - /// This is equivalent of calling `find_local_keys(None)`. - fn find_all_local_keys() -> Vec<(T::AccountId, PublicOf)> { - Self::find_local_keys(None as Option>) - } + /// Implementation of this method should return + /// a result containing the signature. + fn sign_message(&self, message: &[u8]) -> Self::SignatureData; - /// Check if there are keys for any of given accounts that could be used to send a transaction. + /// Construct and sign given payload. /// - /// This check can be used as an early-exit condition to avoid doing too - /// much work, before we actually realise that there are no accounts that you - /// we could use for signing. - fn can_sign_with(accounts: Option>) -> bool { - !Self::find_local_keys(accounts).is_empty() - } + /// This method expects `f` to return a `SignedPayload` + /// object which is then used for signing. + fn sign(&self, f: F) -> Self::SignatureData where + F: Fn(&Account) -> TPayload, + TPayload: SignedPayload, + ; +} - /// Check if there are any keys that could be used for signing. +/// Submit a signed transaction to the transaction pool. +pub trait SendSignedTransaction< + T: SigningTypes + CreateSignedTransaction, + C: AppCrypto, + LocalCall +> { + /// A submission result. + /// + /// This should contain an indication of success and the account that was used for signing. + type Result; + + /// Submit a signed transaction to the local pool. /// - /// This is equivalent of calling `can_sign_with(None)`. - fn can_sign() -> bool { - Self::can_sign_with(None as Option>) + /// Given `f` closure will be called for every requested account and expects a `Call` object + /// to be returned. + /// The call is then wrapped into a transaction (see `#CreateSignedTransaction`), signed and + /// submitted to the pool. + fn send_signed_transaction( + &self, + f: impl Fn(&Account) -> LocalCall, + ) -> Self::Result; + + /// Wraps the call into transaction, signs using given account and submits to the pool. + fn send_single_signed_transaction( + &self, + account: &Account, + call: LocalCall, + ) -> Option> { + let mut account_data = crate::Account::::get(&account.id); + debug::native::debug!( + target: "offchain", + "Creating signed transaction from account: {:?} (nonce: {:?})", + account.id, + account_data.nonce, + ); + let (call, signature) = T::create_transaction::( + call.into(), + account.public.clone(), + account.id.clone(), + account_data.nonce + )?; + let res = SubmitTransaction:: + ::submit_transaction(call, Some(signature)); + + if res.is_ok() { + // increment the nonce. This is fine, since the code should always + // be running in off-chain context, so we NEVER persists data. + account_data.nonce += One::one(); + crate::Account::::insert(&account.id, account_data); + } + + Some(res) } +} - /// Create and submit signed transactions from supported accounts. +/// Submit an unsigned transaction onchain with a signed payload +pub trait SendUnsignedTransaction< + T: SigningTypes + SendTransactionTypes, + LocalCall, +> { + /// A submission result. /// - /// This method should intersect given list of accounts with the ones - /// supported locally and submit signed transaction containing given `Call` - /// with every of them. + /// Should contain the submission result and the account(s) that signed the payload. + type Result; + + /// Send an unsigned transaction with a signed payload. /// - /// Returns a vector of results and account ids that were supported. - #[must_use] - fn submit_signed_from( - call: impl Into + Clone, - accounts: impl IntoIterator, - ) -> Vec<(T::AccountId, Result<(), ()>)> { - let keys = Self::find_local_keys(Some(accounts)); - keys.into_iter().map(|(account, pub_key)| { - let call = call.clone().into(); - ( - account, - Self::SignAndSubmit::sign_and_submit(call, pub_key) - ) - }).collect() - } - - /// Create and submit signed transactions from all local accounts. + /// This method takes `f` and `f2` where: + /// - `f` is called for every account and is expected to return a `SignedPayload` object. + /// - `f2` is then called with the `SignedPayload` returned by `f` and the signature and is + /// expected to return a `Call` object to be embedded into transaction. + fn send_unsigned_transaction( + &self, + f: F, + f2: impl Fn(TPayload, T::Signature) -> LocalCall, + ) -> Self::Result + where + F: Fn(&Account) -> TPayload, + TPayload: SignedPayload; + + /// Submits an unsigned call to the transaction pool. + fn submit_unsigned_transaction( + &self, + call: LocalCall + ) -> Option> { + Some(SubmitTransaction:: + ::submit_unsigned_transaction(call.into())) + } +} + +/// Utility trait to be implemented on payloads that can be signed. +pub trait SignedPayload: Encode { + /// Return a public key that is expected to have a matching key in the keystore, + /// which should be used to sign the payload. + fn public(&self) -> T::Public; + + /// Sign the payload using the implementor's provided public key. /// - /// This method submits a signed transaction from all local accounts - /// for given application crypto. + /// Returns `Some(signature)` if public key is supported. + fn sign>(&self) -> Option { + self.using_encoded(|payload| C::sign(payload, self.public())) + } + + /// Verify signature against payload. /// - /// Returns a vector of results and account ids that were supported. - #[must_use] - fn submit_signed( - call: impl Into + Clone, - ) -> Vec<(T::AccountId, Result<(), ()>)> { - let keys = Self::find_all_local_keys(); - keys.into_iter().map(|(account, pub_key)| { - let call = call.clone().into(); - ( - account, - Self::SignAndSubmit::sign_and_submit(call, pub_key) - ) - }).collect() + /// Returns a bool indicating whether the signature is valid or not. + fn verify>(&self, signature: T::Signature) -> bool { + self.using_encoded(|payload| C::verify(payload, self.public(), signature)) } } -/// A default type used to submit transactions to the pool. -/// -/// This is passed into each runtime as an opaque associated type that can have either of: -/// - [`SignAndSubmitTransaction`] -/// - [`SubmitUnsignedTransaction`] -/// - [`SubmitSignedTransaction`] -/// and used accordingly. -/// -/// This struct should be constructed by providing the following generic parameters: -/// * `Signer` - Usually the application specific key type (see `app_crypto`). -/// * `CreateTransaction` - A type that is able to produce signed transactions, -/// usually it's going to be the entire `Runtime` object. -/// * `Extrinsic` - A runtime-specific type for in-block extrinsics. -/// -/// If you only need the ability to submit unsigned transactions, -/// you may substitute both `Signer` and `CreateTransaction` with any type. -pub struct TransactionSubmitter { - _signer: sp_std::marker::PhantomData<(Signer, CreateTransaction, Extrinsic)>, -} -impl Default for TransactionSubmitter { - fn default() -> Self { - Self { - _signer: Default::default(), - } +#[cfg(test)] +mod tests { + use super::*; + use codec::Decode; + use crate::mock::{Test as TestRuntime, Call}; + use sp_core::offchain::{testing, TransactionPoolExt}; + use sp_runtime::testing::{UintAuthorityId, TestSignature, TestXt}; + + impl SigningTypes for TestRuntime { + type Public = UintAuthorityId; + type Signature = TestSignature; } -} -/// A blanket implementation to simplify creation of transaction signer & submitter in the runtime. -impl SignAndSubmitTransaction for TransactionSubmitter where - T: crate::Trait, - C: CreateTransaction, - S: Signer<>::Public, >::Signature>, - E: ExtrinsicT + Encode, -{ - type Extrinsic = E; - type CreateTransaction = C; - type Signer = S; -} + type Extrinsic = TestXt; -/// A blanket implementation to use the same submitter for unsigned transactions as well. -impl SubmitUnsignedTransaction for TransactionSubmitter where - T: crate::Trait, - E: ExtrinsicT + Encode, -{ - type Extrinsic = E; -} + impl SendTransactionTypes for TestRuntime { + type Extrinsic = Extrinsic; + type OverarchingCall = Call; + } -/// A blanket implementation to support local keystore of application-crypto types. -impl SubmitSignedTransaction for TransactionSubmitter where - T: crate::Trait, - C: CreateTransaction, - E: ExtrinsicT + Encode, - S: Signer<>::Public, >::Signature>, - // Make sure we can unwrap the app crypto key. - S: RuntimeAppPublic + AppPublic + Into<::Generic>, - // Make sure we can convert from wrapped crypto to public key (e.g. `MultiSigner`) - S::Generic: Into>, - // For simplicity we require the same trait to implement `SignAndSubmitTransaction` too. - Self: SignAndSubmitTransaction, -{ - type SignAndSubmit = Self; - - fn find_local_keys(accounts: Option>) -> Vec<( - T::AccountId, - PublicOf, - )> { - // Convert app-specific keys into generic ones. - let local_accounts_and_keys = S::all() - .into_iter() - .map(|app_key| { - // unwrap app-crypto - let generic_pub_key: ::Generic = app_key.into(); - // convert to expected public key type (might be MultiSigner) - let signer_pub_key: PublicOf = generic_pub_key.into(); - // lookup accountid for that pubkey - let account = signer_pub_key.clone().into_account(); - (account, signer_pub_key) - }).collect::>(); - - if let Some(accounts) = accounts { - let mut local_accounts_and_keys = local_accounts_and_keys; - // sort by accountId to allow bin-search. - local_accounts_and_keys.sort_by(|a, b| a.0.cmp(&b.0)); - - // get all the matching accounts - accounts.into_iter().filter_map(|acc| { - let idx = local_accounts_and_keys.binary_search_by(|a| a.0.cmp(&acc)).ok()?; - local_accounts_and_keys.get(idx).cloned() - }).collect() - } else { - // just return all account ids and keys - local_accounts_and_keys - } + #[derive(codec::Encode, codec::Decode)] + struct SimplePayload { + pub public: UintAuthorityId, + pub data: Vec, } - fn can_sign_with(accounts: Option>) -> bool { - // early exit if we care about any account. - if accounts.is_none() { - !S::all().is_empty() - } else { - !Self::find_local_keys(accounts).is_empty() + impl SignedPayload for SimplePayload { + fn public(&self) -> UintAuthorityId { + self.public.clone() } } + + struct DummyAppCrypto; + // Bind together the `SigningTypes` with app-crypto and the wrapper types. + // here the implementation is pretty dummy, because we use the same type for + // both application-specific crypto and the runtime crypto, but in real-life + // runtimes it's going to use different types everywhere. + impl AppCrypto for DummyAppCrypto { + type RuntimeAppPublic = UintAuthorityId; + type GenericPublic = UintAuthorityId; + type GenericSignature = TestSignature; + } + + fn assert_account( + next: Option<(Account, Result<(), ()>)>, + index: usize, + id: u64, + ) { + assert_eq!(next, Some((Account { + index, + id, + public: id.into(), + }, Ok(())))); + } + + #[test] + fn should_send_unsigned_with_signed_payload_with_all_accounts() { + let (pool, pool_state) = testing::TestTransactionPoolExt::new(); + + let mut t = sp_io::TestExternalities::default(); + t.register_extension(TransactionPoolExt::new(pool)); + + // given + UintAuthorityId::set_all_keys(vec![0xf0, 0xf1, 0xf2]); + + t.execute_with(|| { + // when + let result = Signer:: + ::all_accounts() + .send_unsigned_transaction( + |account| SimplePayload { + data: vec![1, 2, 3], + public: account.public.clone() + }, + |_payload, _signature| { + Call + } + ); + + // then + let mut res = result.into_iter(); + assert_account(res.next(), 0, 0xf0); + assert_account(res.next(), 1, 0xf1); + assert_account(res.next(), 2, 0xf2); + assert_eq!(res.next(), None); + + // check the transaction pool content: + let tx1 = pool_state.write().transactions.pop().unwrap(); + let _tx2 = pool_state.write().transactions.pop().unwrap(); + let _tx3 = pool_state.write().transactions.pop().unwrap(); + assert!(pool_state.read().transactions.is_empty()); + let tx1 = Extrinsic::decode(&mut &*tx1).unwrap(); + assert_eq!(tx1.signature, None); + }); + } + + #[test] + fn should_send_unsigned_with_signed_payload_with_any_account() { + let (pool, pool_state) = testing::TestTransactionPoolExt::new(); + + let mut t = sp_io::TestExternalities::default(); + t.register_extension(TransactionPoolExt::new(pool)); + + // given + UintAuthorityId::set_all_keys(vec![0xf0, 0xf1, 0xf2]); + + t.execute_with(|| { + // when + let result = Signer:: + ::any_account() + .send_unsigned_transaction( + |account| SimplePayload { + data: vec![1, 2, 3], + public: account.public.clone() + }, + |_payload, _signature| { + Call + } + ); + + // then + let mut res = result.into_iter(); + assert_account(res.next(), 0, 0xf0); + assert_eq!(res.next(), None); + + // check the transaction pool content: + let tx1 = pool_state.write().transactions.pop().unwrap(); + assert!(pool_state.read().transactions.is_empty()); + let tx1 = Extrinsic::decode(&mut &*tx1).unwrap(); + assert_eq!(tx1.signature, None); + }); + } + + #[test] + fn should_send_unsigned_with_signed_payload_with_all_account_and_filter() { + let (pool, pool_state) = testing::TestTransactionPoolExt::new(); + + let mut t = sp_io::TestExternalities::default(); + t.register_extension(TransactionPoolExt::new(pool)); + + // given + UintAuthorityId::set_all_keys(vec![0xf0, 0xf1, 0xf2]); + + t.execute_with(|| { + // when + let result = Signer:: + ::all_accounts() + .with_filter(vec![0xf2.into(), 0xf1.into()]) + .send_unsigned_transaction( + |account| SimplePayload { + data: vec![1, 2, 3], + public: account.public.clone() + }, + |_payload, _signature| { + Call + } + ); + + // then + let mut res = result.into_iter(); + assert_account(res.next(), 0, 0xf2); + assert_account(res.next(), 1, 0xf1); + assert_eq!(res.next(), None); + + // check the transaction pool content: + let tx1 = pool_state.write().transactions.pop().unwrap(); + let _tx2 = pool_state.write().transactions.pop().unwrap(); + assert!(pool_state.read().transactions.is_empty()); + let tx1 = Extrinsic::decode(&mut &*tx1).unwrap(); + assert_eq!(tx1.signature, None); + }); + } + + #[test] + fn should_send_unsigned_with_signed_payload_with_any_account_and_filter() { + let (pool, pool_state) = testing::TestTransactionPoolExt::new(); + + let mut t = sp_io::TestExternalities::default(); + t.register_extension(TransactionPoolExt::new(pool)); + + // given + UintAuthorityId::set_all_keys(vec![0xf0, 0xf1, 0xf2]); + + t.execute_with(|| { + // when + let result = Signer:: + ::any_account() + .with_filter(vec![0xf2.into(), 0xf1.into()]) + .send_unsigned_transaction( + |account| SimplePayload { + data: vec![1, 2, 3], + public: account.public.clone() + }, + |_payload, _signature| { + Call + } + ); + + // then + let mut res = result.into_iter(); + assert_account(res.next(), 0, 0xf2); + assert_eq!(res.next(), None); + + // check the transaction pool content: + let tx1 = pool_state.write().transactions.pop().unwrap(); + assert!(pool_state.read().transactions.is_empty()); + let tx1 = Extrinsic::decode(&mut &*tx1).unwrap(); + assert_eq!(tx1.signature, None); + }); + } + } diff --git a/frame/system/src/tests.rs b/frame/system/src/tests.rs new file mode 100644 index 0000000000000000000000000000000000000000..2f93dc858f10bb72b1d4265a6f9bd1233ccd78f2 --- /dev/null +++ b/frame/system/src/tests.rs @@ -0,0 +1,424 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::*; +use mock::{*, Origin}; +use sp_core::H256; +use sp_runtime::DispatchError; +use frame_support::weights::WithPostDispatchInfo; + +#[test] +fn origin_works() { + let o = Origin::from(RawOrigin::::Signed(1u64)); + let x: Result, Origin> = o.into(); + assert_eq!(x.unwrap(), RawOrigin::::Signed(1u64)); +} + +#[test] +fn stored_map_works() { + new_test_ext().execute_with(|| { + System::insert(&0, 42); + assert!(System::allow_death(&0)); + + System::inc_ref(&0); + assert!(!System::allow_death(&0)); + + System::insert(&0, 69); + assert!(!System::allow_death(&0)); + + System::dec_ref(&0); + assert!(System::allow_death(&0)); + + assert!(KILLED.with(|r| r.borrow().is_empty())); + System::kill_account(&0); + assert_eq!(KILLED.with(|r| r.borrow().clone()), vec![0u64]); + }); +} + +#[test] +fn deposit_event_should_work() { + new_test_ext().execute_with(|| { + System::initialize( + &1, + &[0u8; 32].into(), + &[0u8; 32].into(), + &Default::default(), + InitKind::Full, + ); + System::note_finished_extrinsics(); + System::deposit_event(SysEvent::CodeUpdated); + System::finalize(); + assert_eq!( + System::events(), + vec![ + EventRecord { + phase: Phase::Finalization, + event: SysEvent::CodeUpdated, + topics: vec![], + } + ] + ); + + System::initialize( + &2, + &[0u8; 32].into(), + &[0u8; 32].into(), + &Default::default(), + InitKind::Full, + ); + System::deposit_event(SysEvent::NewAccount(32)); + System::note_finished_initialize(); + System::deposit_event(SysEvent::KilledAccount(42)); + System::note_applied_extrinsic(&Ok(().into()), Default::default()); + System::note_applied_extrinsic( + &Err(DispatchError::BadOrigin.into()), + Default::default() + ); + System::note_finished_extrinsics(); + System::deposit_event(SysEvent::NewAccount(3)); + System::finalize(); + assert_eq!( + System::events(), + vec![ + EventRecord { + phase: Phase::Initialization, + event: SysEvent::NewAccount(32), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: SysEvent::KilledAccount(42), + topics: vec![] + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: SysEvent::ExtrinsicSuccess(Default::default()), + topics: vec![] + }, + EventRecord { + phase: Phase::ApplyExtrinsic(1), + event: SysEvent::ExtrinsicFailed( + DispatchError::BadOrigin.into(), + Default::default() + ), + topics: vec![] + }, + EventRecord { + phase: Phase::Finalization, + event: SysEvent::NewAccount(3), + topics: vec![] + }, + ] + ); + }); +} + +#[test] +fn deposit_event_uses_actual_weight() { + new_test_ext().execute_with(|| { + System::initialize( + &1, + &[0u8; 32].into(), + &[0u8; 32].into(), + &Default::default(), + InitKind::Full, + ); + System::note_finished_initialize(); + + let pre_info = DispatchInfo { + weight: 1000, + .. Default::default() + }; + System::note_applied_extrinsic( + &Ok(Some(300).into()), + pre_info, + ); + System::note_applied_extrinsic( + &Ok(Some(1000).into()), + pre_info, + ); + System::note_applied_extrinsic( + // values over the pre info should be capped at pre dispatch value + &Ok(Some(1200).into()), + pre_info, + ); + System::note_applied_extrinsic( + &Err(DispatchError::BadOrigin.with_weight(999)), + pre_info, + ); + + assert_eq!( + System::events(), + vec![ + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: SysEvent::ExtrinsicSuccess( + DispatchInfo { + weight: 300, + .. Default::default() + }, + ), + topics: vec![] + }, + EventRecord { + phase: Phase::ApplyExtrinsic(1), + event: SysEvent::ExtrinsicSuccess( + DispatchInfo { + weight: 1000, + .. Default::default() + }, + ), + topics: vec![] + }, + EventRecord { + phase: Phase::ApplyExtrinsic(2), + event: SysEvent::ExtrinsicSuccess( + DispatchInfo { + weight: 1000, + .. Default::default() + }, + ), + topics: vec![] + }, + EventRecord { + phase: Phase::ApplyExtrinsic(3), + event: SysEvent::ExtrinsicFailed( + DispatchError::BadOrigin.into(), + DispatchInfo { + weight: 999, + .. Default::default() + }, + ), + topics: vec![] + }, + ] + ); + }); +} + +#[test] +fn deposit_event_topics() { + new_test_ext().execute_with(|| { + const BLOCK_NUMBER: u64 = 1; + + System::initialize( + &BLOCK_NUMBER, + &[0u8; 32].into(), + &[0u8; 32].into(), + &Default::default(), + InitKind::Full, + ); + System::note_finished_extrinsics(); + + let topics = vec![ + H256::repeat_byte(1), + H256::repeat_byte(2), + H256::repeat_byte(3), + ]; + + // We deposit a few events with different sets of topics. + System::deposit_event_indexed(&topics[0..3], SysEvent::NewAccount(1)); + System::deposit_event_indexed(&topics[0..1], SysEvent::NewAccount(2)); + System::deposit_event_indexed(&topics[1..2], SysEvent::NewAccount(3)); + + System::finalize(); + + // Check that topics are reflected in the event record. + assert_eq!( + System::events(), + vec![ + EventRecord { + phase: Phase::Finalization, + event: SysEvent::NewAccount(1), + topics: topics[0..3].to_vec(), + }, + EventRecord { + phase: Phase::Finalization, + event: SysEvent::NewAccount(2), + topics: topics[0..1].to_vec(), + }, + EventRecord { + phase: Phase::Finalization, + event: SysEvent::NewAccount(3), + topics: topics[1..2].to_vec(), + } + ] + ); + + // Check that the topic-events mapping reflects the deposited topics. + // Note that these are indexes of the events. + assert_eq!( + System::event_topics(&topics[0]), + vec![(BLOCK_NUMBER, 0), (BLOCK_NUMBER, 1)], + ); + assert_eq!( + System::event_topics(&topics[1]), + vec![(BLOCK_NUMBER, 0), (BLOCK_NUMBER, 2)], + ); + assert_eq!( + System::event_topics(&topics[2]), + vec![(BLOCK_NUMBER, 0)], + ); + }); +} + +#[test] +fn prunes_block_hash_mappings() { + new_test_ext().execute_with(|| { + // simulate import of 15 blocks + for n in 1..=15 { + System::initialize( + &n, + &[n as u8 - 1; 32].into(), + &[0u8; 32].into(), + &Default::default(), + InitKind::Full, + ); + + System::finalize(); + } + + // first 5 block hashes are pruned + for n in 0..5 { + assert_eq!( + System::block_hash(n), + H256::zero(), + ); + } + + // the remaining 10 are kept + for n in 5..15 { + assert_eq!( + System::block_hash(n), + [n as u8; 32].into(), + ); + } + }) +} + +#[test] +fn set_code_checks_works() { + struct CallInWasm(Vec); + + impl sp_core::traits::CallInWasm for CallInWasm { + fn call_in_wasm( + &self, + _: &[u8], + _: Option>, + _: &str, + _: &[u8], + _: &mut dyn sp_externalities::Externalities, + _: sp_core::traits::MissingHostFunctions, + ) -> Result, String> { + Ok(self.0.clone()) + } + } + + let test_data = vec![ + ("test", 1, 2, Err(Error::::SpecVersionNeedsToIncrease)), + ("test", 1, 1, Err(Error::::SpecVersionNeedsToIncrease)), + ("test2", 1, 1, Err(Error::::InvalidSpecName)), + ("test", 2, 1, Ok(())), + ("test", 0, 1, Err(Error::::SpecVersionNeedsToIncrease)), + ("test", 1, 0, Err(Error::::SpecVersionNeedsToIncrease)), + ]; + + for (spec_name, spec_version, impl_version, expected) in test_data.into_iter() { + let version = RuntimeVersion { + spec_name: spec_name.into(), + spec_version, + impl_version, + ..Default::default() + }; + let call_in_wasm = CallInWasm(version.encode()); + + let mut ext = new_test_ext(); + ext.register_extension(sp_core::traits::CallInWasmExt::new(call_in_wasm)); + ext.execute_with(|| { + let res = System::set_code( + RawOrigin::Root.into(), + vec![1, 2, 3, 4], + ); + + assert_eq!(expected.map_err(DispatchError::from), res); + }); + } +} + +#[test] +fn set_code_with_real_wasm_blob() { + let executor = substrate_test_runtime_client::new_native_executor(); + let mut ext = new_test_ext(); + ext.register_extension(sp_core::traits::CallInWasmExt::new(executor)); + ext.execute_with(|| { + System::set_block_number(1); + System::set_code( + RawOrigin::Root.into(), + substrate_test_runtime_client::runtime::WASM_BINARY.to_vec(), + ).unwrap(); + + assert_eq!( + System::events(), + vec![EventRecord { + phase: Phase::Initialization, + event: SysEvent::CodeUpdated, + topics: vec![], + }], + ); + }); +} + +#[test] +fn runtime_upgraded_with_set_storage() { + let executor = substrate_test_runtime_client::new_native_executor(); + let mut ext = new_test_ext(); + ext.register_extension(sp_core::traits::CallInWasmExt::new(executor)); + ext.execute_with(|| { + System::set_storage( + RawOrigin::Root.into(), + vec![( + well_known_keys::CODE.to_vec(), + substrate_test_runtime_client::runtime::WASM_BINARY.to_vec() + )], + ).unwrap(); + }); +} + +#[test] +fn events_not_emitted_during_genesis() { + new_test_ext().execute_with(|| { + // Block Number is zero at genesis + assert!(System::block_number().is_zero()); + System::on_created_account(Default::default()); + assert!(System::events().is_empty()); + // Events will be emitted starting on block 1 + System::set_block_number(1); + System::on_created_account(Default::default()); + assert!(System::events().len() == 1); + }); +} + +#[test] +fn ensure_one_of_works() { + fn ensure_root_or_signed(o: RawOrigin) -> Result, Origin> { + EnsureOneOf::, EnsureSigned>::try_origin(o.into()) + } + + assert_eq!(ensure_root_or_signed(RawOrigin::Root).unwrap(), Either::Left(())); + assert_eq!(ensure_root_or_signed(RawOrigin::Signed(0)).unwrap(), Either::Right(0)); + assert!(ensure_root_or_signed(RawOrigin::None).is_err()) +} diff --git a/frame/system/src/weights.rs b/frame/system/src/weights.rs new file mode 100644 index 0000000000000000000000000000000000000000..93295093c4fb88aaff70c259d889a6ce1e352a04 --- /dev/null +++ b/frame/system/src/weights.rs @@ -0,0 +1,76 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use codec::{Encode, Decode}; +use frame_support::weights::{Weight, DispatchClass}; +use sp_runtime::RuntimeDebug; + +/// An object to track the currently used extrinsic weight in a block. +#[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode)] +pub struct ExtrinsicsWeight { + normal: Weight, + operational: Weight, +} + +impl ExtrinsicsWeight { + /// Returns the total weight consumed by all extrinsics in the block. + pub fn total(&self) -> Weight { + self.normal.saturating_add(self.operational) + } + + /// Add some weight of a specific dispatch class, saturating at the numeric bounds of `Weight`. + pub fn add(&mut self, weight: Weight, class: DispatchClass) { + let value = self.get_mut(class); + *value = value.saturating_add(weight); + } + + /// Try to add some weight of a specific dispatch class, returning Err(()) if overflow would + /// occur. + pub fn checked_add(&mut self, weight: Weight, class: DispatchClass) -> Result<(), ()> { + let value = self.get_mut(class); + *value = value.checked_add(weight).ok_or(())?; + Ok(()) + } + + /// Subtract some weight of a specific dispatch class, saturating at the numeric bounds of + /// `Weight`. + pub fn sub(&mut self, weight: Weight, class: DispatchClass) { + let value = self.get_mut(class); + *value = value.saturating_sub(weight); + } + + /// Get the current weight of a specific dispatch class. + pub fn get(&self, class: DispatchClass) -> Weight { + match class { + DispatchClass::Operational => self.operational, + DispatchClass::Normal | DispatchClass::Mandatory => self.normal, + } + } + + /// Get a mutable reference to the current weight of a specific dispatch class. + fn get_mut(&mut self, class: DispatchClass) -> &mut Weight { + match class { + DispatchClass::Operational => &mut self.operational, + DispatchClass::Normal | DispatchClass::Mandatory => &mut self.normal, + } + } + + /// Set the weight of a specific dispatch class. + pub fn put(&mut self, new: Weight, class: DispatchClass) { + *self.get_mut(class) = new; + } +} diff --git a/frame/timestamp/Cargo.toml b/frame/timestamp/Cargo.toml index eb7358e197a189dd33b55e985c1b9a65b86a72d8..2c2ad68b96bfd16df299dd28e6eef4f8c01548d0 100644 --- a/frame/timestamp/Cargo.toml +++ b/frame/timestamp/Cargo.toml @@ -1,31 +1,34 @@ [package] name = "pallet-timestamp" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME Timestamp Module" documentation = "https://docs.rs/pallet-timestamp" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/io", optional = true } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -sp-inherents = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/inherents" } -frame-benchmarking = { version = "2.0.0-alpha.5", default-features = false, path = "../benchmarking", optional = true } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } -sp-timestamp = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/timestamp" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io", optional = true } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +sp-inherents = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/inherents" } +frame-benchmarking = { version = "2.0.0-rc4", default-features = false, path = "../benchmarking", optional = true } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } +sp-timestamp = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/timestamp" } impl-trait-for-tuples = "0.1.3" [dev-dependencies] -sp-io ={ version = "2.0.0-alpha.5", path = "../../primitives/io" } -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } +sp-io ={ version = "2.0.0-rc4", path = "../../primitives/io" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } [features] default = ["std"] @@ -41,6 +44,3 @@ std = [ "sp-timestamp/std" ] runtime-benchmarks = ["frame-benchmarking", "sp-io"] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/timestamp/src/benchmarking.rs b/frame/timestamp/src/benchmarking.rs index 65b4dbf2b079ea23d4b2622b61847b99e41ce518..9b1c976229e665e330e62788d5a338589b4427c6 100644 --- a/frame/timestamp/src/benchmarking.rs +++ b/frame/timestamp/src/benchmarking.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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. +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Timestamp pallet benchmarking. @@ -21,16 +22,46 @@ use super::*; use sp_std::prelude::*; use frame_system::RawOrigin; +use frame_support::{ensure, traits::OnFinalize}; use frame_benchmarking::benchmarks; +use crate::Module as Timestamp; + const MAX_TIME: u32 = 100; benchmarks! { - _ { - let n in 1 .. MAX_TIME => (); - } + _ { } set { - let n in ...; - }: _(RawOrigin::None, n.into()) + let t in 1 .. MAX_TIME; + }: _(RawOrigin::None, t.into()) + + verify { + ensure!(Timestamp::::now() == t.into(), "Time was not set."); + } + + on_finalize { + let t in 1 .. MAX_TIME; + Timestamp::::set(RawOrigin::None.into(), t.into())?; + ensure!(DidUpdate::exists(), "Time was not set."); + }: { Timestamp::::on_finalize(t.into()); } + + verify { + ensure!(!DidUpdate::exists(), "Time was not removed."); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::tests::{new_test_ext, Test}; + use frame_support::assert_ok; + + #[test] + fn test_benchmarks() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_set::()); + assert_ok!(test_benchmark_on_finalize::()); + }); + } } diff --git a/frame/timestamp/src/lib.rs b/frame/timestamp/src/lib.rs index 54b4eeca6b36e6cbc01b5773463c8aba99d5b985..efcd440f9092ec4ea2571c531c3eefbecf6c7e41 100644 --- a/frame/timestamp/src/lib.rs +++ b/frame/timestamp/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Timestamp Module //! @@ -63,13 +64,13 @@ //! ``` //! use frame_support::{decl_module, dispatch}; //! # use pallet_timestamp as timestamp; -//! use frame_system::{self as system, ensure_signed}; +//! use frame_system::ensure_signed; //! //! pub trait Trait: timestamp::Trait {} //! //! decl_module! { //! pub struct Module for enum Call where origin: T::Origin { -//! #[weight = frame_support::weights::SimpleDispatchInfo::default()] +//! #[weight = 0] //! pub fn get_time(origin) -> dispatch::DispatchResult { //! let _sender = ensure_signed(origin)?; //! let _now = >::get(); @@ -100,7 +101,7 @@ use frame_support::debug; use frame_support::{ Parameter, decl_storage, decl_module, traits::{Time, UnixTime, Get}, - weights::SimpleDispatchInfo, + weights::{DispatchClass, Weight}, }; use sp_runtime::{ RuntimeString, @@ -114,6 +115,16 @@ use sp_timestamp::{ OnTimestampSet, }; +pub trait WeightInfo { + fn set(t: u32, ) -> Weight; + fn on_finalize(t: u32, ) -> Weight; +} + +impl WeightInfo for () { + fn set(_t: u32, ) -> Weight { 1_000_000_000 } + fn on_finalize(_t: u32, ) -> Weight { 1_000_000_000 } +} + /// The module configuration trait pub trait Trait: frame_system::Trait { /// Type used for expressing timestamp. @@ -128,6 +139,9 @@ pub trait Trait: frame_system::Trait { /// work with this to determine a sensible block time. e.g. For Aura, it will be double this /// period on default settings. type MinimumPeriod: Get; + + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; } decl_module! { @@ -147,12 +161,25 @@ decl_module! { /// `MinimumPeriod`. /// /// The dispatch origin for this call must be `Inherent`. - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + /// + /// # + /// - `O(T)` where `T` complexity of `on_timestamp_set` + /// - 1 storage read and 1 storage mutation (codec `O(1)`). (because of `DidUpdate::take` in `on_finalize`) + /// - 1 event handler `on_timestamp_set` `O(T)`. + /// - Benchmark: 7.678 (min squares analysis) + /// - NOTE: This benchmark was done for a runtime with insignificant `on_timestamp_set` handlers. + /// New benchmarking is needed when adding new handlers. + /// # + #[weight = ( + T::DbWeight::get().reads_writes(2, 1) + 8_000_000, + DispatchClass::Mandatory + )] fn set(origin, #[compact] now: T::Moment) { ensure_none(origin)?; assert!(!::DidUpdate::exists(), "Timestamp must be updated only once in the block"); + let prev = Self::now(); assert!( - Self::now().is_zero() || now >= Self::now() + T::MinimumPeriod::get(), + prev.is_zero() || now >= prev + T::MinimumPeriod::get(), "Timestamp must increment by at least between sequential blocks" ); ::Now::put(now); @@ -161,6 +188,17 @@ decl_module! { >::on_timestamp_set(now); } + /// dummy `on_initialize` to return the weight used in `on_finalize`. + fn on_initialize() -> Weight { + // weight of `on_finalize` + 5_000_000 + } + + /// # + /// - `O(1)` + /// - 1 storage deletion (codec `O(1)`). + /// - Benchmark: 4.928 µs (min squares analysis) + /// # fn on_finalize() { assert!(::DidUpdate::take(), "Timestamp must be updated once in the block"); } @@ -271,6 +309,11 @@ mod tests { use sp_core::H256; use sp_runtime::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; + pub fn new_test_ext() -> TestExternalities { + let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + TestExternalities::new(t) + } + impl_outer_origin! { pub enum Origin for Test where system = frame_system {} } @@ -284,6 +327,7 @@ mod tests { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -296,6 +340,10 @@ mod tests { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); @@ -303,6 +351,7 @@ mod tests { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } parameter_types! { pub const MinimumPeriod: u64 = 5; @@ -311,15 +360,15 @@ mod tests { type Moment = u64; type OnTimestampSet = (); type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); } type Timestamp = Module; #[test] fn timestamp_works() { - let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - TestExternalities::new(t).execute_with(|| { + new_test_ext().execute_with(|| { Timestamp::set_timestamp(42); - assert_ok!(Timestamp::dispatch(Call::set(69), Origin::NONE)); + assert_ok!(Timestamp::set(Origin::none(), 69)); assert_eq!(Timestamp::now(), 69); }); } @@ -327,21 +376,19 @@ mod tests { #[test] #[should_panic(expected = "Timestamp must be updated only once in the block")] fn double_timestamp_should_fail() { - let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - TestExternalities::new(t).execute_with(|| { + new_test_ext().execute_with(|| { Timestamp::set_timestamp(42); - assert_ok!(Timestamp::dispatch(Call::set(69), Origin::NONE)); - let _ = Timestamp::dispatch(Call::set(70), Origin::NONE); + assert_ok!(Timestamp::set(Origin::none(), 69)); + let _ = Timestamp::set(Origin::none(), 70); }); } #[test] #[should_panic(expected = "Timestamp must increment by at least between sequential blocks")] fn block_period_minimum_enforced() { - let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - TestExternalities::new(t).execute_with(|| { + new_test_ext().execute_with(|| { Timestamp::set_timestamp(42); - let _ = Timestamp::dispatch(Call::set(46), Origin::NONE); + let _ = Timestamp::set(Origin::none(), 46); }); } } diff --git a/frame/transaction-payment/Cargo.toml b/frame/transaction-payment/Cargo.toml index 811c2885b1bdaa674247c7e9510531efa8fe0e95..cc26af45d7948659b2e7da83bd5c8c6a967be556 100644 --- a/frame/transaction-payment/Cargo.toml +++ b/frame/transaction-payment/Cargo.toml @@ -1,29 +1,36 @@ [package] name = "pallet-transaction-payment" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet to manage transaction payments" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } -pallet-transaction-payment-rpc-runtime-api = { version = "2.0.0-alpha.5", default-features = false, path = "./rpc/runtime-api" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +serde = { version = "1.0.101", optional = true } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } +pallet-transaction-payment-rpc-runtime-api = { version = "2.0.0-rc4", default-features = false, path = "./rpc/runtime-api" } +smallvec = "1.4.1" [dev-dependencies] -sp-io = { version = "2.0.0-alpha.5", path = "../../primitives/io" } -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -pallet-balances = { version = "2.0.0-alpha.5", path = "../balances" } +sp-io = { version = "2.0.0-rc4", path = "../../primitives/io" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0-rc4", path = "../balances" } +sp-storage = { version = "2.0.0-rc4", path = "../../primitives/storage" } [features] default = ["std"] std = [ + "serde", "codec/std", "sp-std/std", "sp-runtime/std", @@ -31,6 +38,3 @@ std = [ "frame-system/std", "pallet-transaction-payment-rpc-runtime-api/std" ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/transaction-payment/rpc/Cargo.toml b/frame/transaction-payment/rpc/Cargo.toml index cd74829b29b049fb18b29a661b00bd8763c3c725..f26f6044714effc0eedb854612b4dbe22dccb686 100644 --- a/frame/transaction-payment/rpc/Cargo.toml +++ b/frame/transaction-payment/rpc/Cargo.toml @@ -1,25 +1,25 @@ [package] name = "pallet-transaction-payment-rpc" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "RPC interface for the transaction payment module." -[dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0" } -jsonrpc-core = "14.0.3" -jsonrpc-core-client = "14.0.5" -jsonrpc-derive = "14.0.3" -sp-core = { version = "2.0.0-alpha.5", path = "../../../primitives/core" } -sp-rpc = { version = "2.0.0-alpha.5", path = "../../../primitives/rpc" } -serde = { version = "1.0.101", features = ["derive"] } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime" } -sp-api = { version = "2.0.0-alpha.5", path = "../../../primitives/api" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../../primitives/blockchain" } -pallet-transaction-payment-rpc-runtime-api = { version = "2.0.0-alpha.5", path = "./runtime-api" } - [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.3.1" } +jsonrpc-core = "14.2.0" +jsonrpc-core-client = "14.2.0" +jsonrpc-derive = "14.2.1" +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } +sp-rpc = { version = "2.0.0-rc4", path = "../../../primitives/rpc" } +serde = { version = "1.0.101", features = ["derive"] } +sp-runtime = { version = "2.0.0-rc4", path = "../../../primitives/runtime" } +sp-api = { version = "2.0.0-rc4", path = "../../../primitives/api" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../../primitives/blockchain" } +pallet-transaction-payment-rpc-runtime-api = { version = "2.0.0-rc4", path = "./runtime-api" } diff --git a/frame/transaction-payment/rpc/runtime-api/Cargo.toml b/frame/transaction-payment/rpc/runtime-api/Cargo.toml index 447590111c7ee65ee098a2a508647c5fe7cefc57..2cd9977704cf5bae7e4becb7e2e74a7366029a35 100644 --- a/frame/transaction-payment/rpc/runtime-api/Cargo.toml +++ b/frame/transaction-payment/rpc/runtime-api/Cargo.toml @@ -1,20 +1,23 @@ [package] name = "pallet-transaction-payment-rpc-runtime-api" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "RPC runtime API for transaction payment FRAME pallet" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true, features = ["derive"] } -sp-api = { version = "2.0.0-alpha.5", default-features = false, path = "../../../../primitives/api" } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../../../primitives/std" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../../../primitives/runtime" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../../../support" } +sp-api = { version = "2.0.0-rc4", default-features = false, path = "../../../../primitives/api" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../../../primitives/std" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../../../primitives/runtime" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../../../support" } [dev-dependencies] serde_json = "1.0.41" @@ -29,6 +32,3 @@ std = [ "sp-runtime/std", "frame-support/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/transaction-payment/rpc/runtime-api/src/lib.rs b/frame/transaction-payment/rpc/runtime-api/src/lib.rs index 77b6e3b45464e5bc7837ce619a43f7d283cc4bb7..17a8bcdf44e87a695e703515801a56f03ffc4d8e 100644 --- a/frame/transaction-payment/rpc/runtime-api/src/lib.rs +++ b/frame/transaction-payment/rpc/runtime-api/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Runtime API definition for transaction payment module. @@ -25,7 +26,7 @@ use codec::{Encode, Codec, Decode}; use serde::{Serialize, Deserialize, Serializer, Deserializer}; use sp_runtime::traits::{MaybeDisplay, MaybeFromStr}; -/// Some information related to a dispatchable that can be queried from the runtime. +/// Information related to a dispatchable's class, weight, and fee that can be queried from the runtime. #[derive(Eq, PartialEq, Encode, Decode, Default)] #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] @@ -34,8 +35,8 @@ pub struct RuntimeDispatchInfo { 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`). + /// The inclusion fee of this dispatch. This does not include a tip or anything else that + /// depends on the signature (i.e. depends on a `SignedExtension`). #[cfg_attr(feature = "std", serde(bound(serialize = "Balance: std::fmt::Display")))] #[cfg_attr(feature = "std", serde(serialize_with = "serialize_as_string"))] #[cfg_attr(feature = "std", serde(bound(deserialize = "Balance: std::str::FromStr")))] diff --git a/frame/transaction-payment/rpc/src/lib.rs b/frame/transaction-payment/rpc/src/lib.rs index 945b0119d7236dd4108d84978fb017b736f318cf..d99907a6ac3f4e112a91682affca029a84ee179c 100644 --- a/frame/transaction-payment/rpc/src/lib.rs +++ b/frame/transaction-payment/rpc/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! RPC interface for the transaction payment module. diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs index 1078927747b228cd7b7787aa2d911ab41818ef7d..96fbd1068d57d0aa7f6558459afb410137697ceb 100644 --- a/frame/transaction-payment/src/lib.rs +++ b/frame/transaction-payment/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Transaction Payment Module //! @@ -24,10 +25,10 @@ //! 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`]. +//! - The mapping between one unit of weight to one unit of fee via [`Trait::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`] +//! [`Trait::FeeMultiplierUpdate`] #![cfg_attr(not(feature = "std"), no_std)] @@ -36,24 +37,145 @@ use codec::{Encode, Decode}; use frame_support::{ decl_storage, decl_module, traits::{Currency, Get, OnUnbalanced, ExistenceRequirement, WithdrawReason, Imbalance}, - weights::{Weight, DispatchInfo, GetDispatchInfo}, + weights::{ + Weight, DispatchInfo, PostDispatchInfo, GetDispatchInfo, Pays, WeightToFeePolynomial, + WeightToFeeCoefficient, + }, + dispatch::DispatchResult, }; use sp_runtime::{ - Fixed64, + FixedU128, FixedPointNumber, FixedPointOperand, Perquintill, RuntimeDebug, transaction_validity::{ TransactionPriority, ValidTransaction, InvalidTransaction, TransactionValidityError, TransactionValidity, }, - traits::{Zero, Saturating, SignedExtension, SaturatedConversion, Convert}, + traits::{ + Zero, Saturating, SignedExtension, SaturatedConversion, Convert, Dispatchable, + DispatchInfoOf, PostDispatchInfoOf, + }, }; use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo; -type Multiplier = Fixed64; +/// Fee multiplier. +pub type Multiplier = FixedU128; + type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; +/// A struct to update the weight multiplier per block. It implements `Convert`, meaning that it can convert the previous multiplier to the next one. This should +/// be called on `on_finalize` of a block, prior to potentially cleaning the weight data from the +/// system module. +/// +/// given: +/// s = previous block weight +/// s'= ideal block weight +/// m = maximum block weight +/// diff = (s - s')/m +/// v = 0.00001 +/// t1 = (v * diff) +/// t2 = (v * diff)^2 / 2 +/// then: +/// next_multiplier = prev_multiplier * (1 + t1 + t2) +/// +/// Where `(s', v)` must be given as the `Get` implementation of the `T` generic type. Moreover, `M` +/// must provide the minimum allowed value for the multiplier. Note that a runtime should ensure +/// with tests that the combination of this `M` and `V` is not such that the multiplier can drop to +/// zero and never recover. +/// +/// note that `s'` is interpreted as a portion in the _normal transaction_ capacity of the block. +/// For example, given `s' == 0.25` and `AvailableBlockRatio = 0.75`, then the target fullness is +/// _0.25 of the normal capacity_ and _0.1875 of the entire block_. +/// +/// This implementation implies the bound: +/// - `v ≤ p / k * (s − s')` +/// - or, solving for `p`: `p >= v * k * (s - s')` +/// +/// where `p` is the amount of change over `k` blocks. +/// +/// Hence: +/// - in a fully congested chain: `p >= v * k * (1 - s')`. +/// - in an empty chain: `p >= v * k * (-s')`. +/// +/// For example, when all blocks are full and there are 28800 blocks per day (default in `substrate-node`) +/// and v == 0.00001, s' == 0.1875, we'd have: +/// +/// p >= 0.00001 * 28800 * 0.8125 +/// p >= 0.234 +/// +/// Meaning that fees can change by around ~23% per day, given extreme congestion. +/// +/// More info can be found at: +/// https://w3f-research.readthedocs.io/en/latest/polkadot/Token%20Economics.html +pub struct TargetedFeeAdjustment(sp_std::marker::PhantomData<(T, S, V, M)>); + +impl Convert for TargetedFeeAdjustment + where T: frame_system::Trait, S: Get, V: Get, M: Get, +{ + fn convert(previous: Multiplier) -> Multiplier { + // Defensive only. The multiplier in storage should always be at most positive. Nonetheless + // we recover here in case of errors, because any value below this would be stale and can + // never change. + let min_multiplier = M::get(); + let previous = previous.max(min_multiplier); + + // the computed ratio is only among the normal class. + let normal_max_weight = + ::AvailableBlockRatio::get() * + ::MaximumBlockWeight::get(); + let normal_block_weight = + >::block_weight() + .get(frame_support::weights::DispatchClass::Normal) + .min(normal_max_weight); + + let s = S::get(); + let v = V::get(); + + let target_weight = (s * normal_max_weight) as u128; + let block_weight = normal_block_weight as u128; + + // determines if the first_term is positive + let positive = block_weight >= target_weight; + let diff_abs = block_weight.max(target_weight) - block_weight.min(target_weight); + + // defensive only, a test case assures that the maximum weight diff can fit in Multiplier + // without any saturation. + let diff = Multiplier::saturating_from_rational(diff_abs, normal_max_weight.max(1)); + let diff_squared = diff.saturating_mul(diff); + + let v_squared_2 = v.saturating_mul(v) / Multiplier::saturating_from_integer(2); + + let first_term = v.saturating_mul(diff); + let second_term = v_squared_2.saturating_mul(diff_squared); + + if positive { + let excess = first_term.saturating_add(second_term).saturating_mul(previous); + previous.saturating_add(excess).max(min_multiplier) + } else { + // Defensive-only: first_term > second_term. Safe subtraction. + let negative = first_term.saturating_sub(second_term).saturating_mul(previous); + previous.saturating_sub(negative).max(min_multiplier) + } + } +} + +/// Storage releases of the module. +#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug)] +enum Releases { + /// Original version of the module. + V1Ancient, + /// One that bumps the usage to FixedU128 from FixedI128. + V2, +} + +impl Default for Releases { + fn default() -> Self { + Releases::V1Ancient + } +} + pub trait Trait: frame_system::Trait { /// The currency type in which fees will be paid. type Currency: Currency + Send + Sync; @@ -63,14 +185,11 @@ pub trait Trait: frame_system::Trait { /// if any. 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>; + type WeightToFee: WeightToFeePolynomial>; /// Update the multiplier of the next block, based on the previous block's weight. type FeeMultiplierUpdate: Convert; @@ -78,31 +197,50 @@ pub trait Trait: frame_system::Trait { decl_storage! { trait Store for Module as TransactionPayment { - pub NextFeeMultiplier get(fn next_fee_multiplier): Multiplier = Multiplier::from_parts(0); + pub NextFeeMultiplier get(fn next_fee_multiplier): Multiplier = Multiplier::saturating_from_integer(1); + + StorageVersion build(|_: &GenesisConfig| Releases::V2): Releases; } } 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(); + /// The polynomial that is applied in order to derive fee from weight. + const WeightToFee: Vec>> = + T::WeightToFee::polynomial().to_vec(); + fn on_finalize() { NextFeeMultiplier::mutate(|fm| { - *fm = T::FeeMultiplierUpdate::convert(*fm) + *fm = T::FeeMultiplierUpdate::convert(*fm); }); } + + fn integrity_test() { + // given weight == u64, we build multipliers from `diff` of two weight values, which can + // at most be MaximumBlockWeight. Make sure that this can fit in a multiplier without + // loss. + use sp_std::convert::TryInto; + assert!( + ::max_value() >= + Multiplier::checked_from_integer( + ::MaximumBlockWeight::get().try_into().unwrap() + ).unwrap(), + ); + } } } -impl Module { +impl Module where + BalanceOf: FixedPointOperand +{ /// 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. + /// This module is not and cannot be aware of the internals of a signed extension, for example + /// a tip. It only interprets the extrinsic as some encoded value and accounts for its weight + /// and length, the runtime's extrinsic base weight, and the current fee multiplier. /// /// All dispatchables must be annotated with weight and will have some fee info. This function /// always returns. @@ -113,6 +251,7 @@ impl Module { where T: Send + Sync, BalanceOf: Send + Sync, + T::Call: Dispatchable, { // 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 @@ -121,72 +260,151 @@ impl Module { // a very very little potential gain in the future. let dispatch_info = ::get_dispatch_info(&unchecked_extrinsic); - let partial_fee = - >::compute_fee(len, dispatch_info, 0u32.into()); + let partial_fee = Self::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: - /// - _base_fee_: This is the minimum amount a user pays for a transaction. - /// - _len_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. - /// - _targeted_fee_adjustment_: This is a multiplier that can tune the final fee based on + /// - `base_fee`: This is the minimum amount a user pays for a transaction. It is declared + /// as a base _weight_ in the runtime and converted to a fee using `WeightToFee`. + /// - `len_fee`: The length fee, the amount paid for the encoded length (in bytes) of the + /// transaction. + /// - `weight_fee`: This amount is computed based on the weight of the transaction. Weight + /// accounts for the execution time of a transaction. + /// - `targeted_fee_adjustment`: This is a multiplier that can tune the final fee based on /// the congestion of the network. - /// - (optional) _tip_: if included in the transaction, it will be added on top. Only signed - /// transactions can have a tip. + /// - (Optional) `tip`: If included in the transaction, the tip will be added on top. Only + /// signed transactions can have a tip. + /// + /// The base fee and adjusted weight and length fees constitute the _inclusion fee,_ which is + /// the minimum fee for a transaction to be included in a block. /// - /// final_fee = base_fee + targeted_fee_adjustment(len_fee + weight_fee) + tip; + /// ```ignore + /// inclusion_fee = base_fee + len_fee + [targeted_fee_adjustment * weight_fee]; + /// final_fee = inclusion_fee + tip; + /// ``` pub fn compute_fee( len: u32, - info: ::DispatchInfo, + info: &DispatchInfoOf, tip: BalanceOf, - ) -> BalanceOf - where - BalanceOf: Sync + Send, + ) -> BalanceOf where + T::Call: Dispatchable, + { + Self::compute_fee_raw(len, info.weight, tip, info.pays_fee) + } + + /// Compute the actual post dispatch fee for a particular transaction. + /// + /// Identical to `compute_fee` with the only difference that the post dispatch corrected + /// weight is used for the weight fee calculation. + pub fn compute_actual_fee( + len: u32, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, + tip: BalanceOf, + ) -> BalanceOf where + T::Call: Dispatchable, { - if info.pays_fee { + Self::compute_fee_raw(len, post_info.calc_actual_weight(info), tip, info.pays_fee) + } + + fn compute_fee_raw( + len: u32, + weight: Weight, + tip: BalanceOf, + pays_fee: Pays, + ) -> BalanceOf { + if pays_fee == Pays::Yes { let len = >::from(len); let per_byte = T::TransactionByteFee::get(); - let len_fee = per_byte.saturating_mul(len); - - 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) - }; - // the adjustable part of the fee - let adjustable_fee = len_fee.saturating_add(weight_fee); - let targeted_fee_adjustment = NextFeeMultiplier::get(); - // adjusted_fee = adjustable_fee + (adjustable_fee * targeted_fee_adjustment) - let adjusted_fee = targeted_fee_adjustment.saturated_multiply_accumulate(adjustable_fee); + // length fee. this is not adjusted. + let fixed_len_fee = per_byte.saturating_mul(len); - let base_fee = T::TransactionBaseFee::get(); - base_fee.saturating_add(adjusted_fee).saturating_add(tip) + // the adjustable part of the fee. + let unadjusted_weight_fee = Self::weight_to_fee(weight); + let multiplier = Self::next_fee_multiplier(); + // final adjusted weight fee. + let adjusted_weight_fee = multiplier.saturating_mul_int(unadjusted_weight_fee); + + let base_fee = Self::weight_to_fee(T::ExtrinsicBaseWeight::get()); + base_fee + .saturating_add(fixed_len_fee) + .saturating_add(adjusted_weight_fee) + .saturating_add(tip) } else { tip } } + + fn weight_to_fee(weight: Weight) -> BalanceOf { + // 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 = weight.min(::MaximumBlockWeight::get()); + T::WeightToFee::calc(&capped_weight) + } +} + +impl Convert> for Module where + T: Trait, + BalanceOf: FixedPointOperand, +{ + /// Compute the fee for the specified weight. + /// + /// This fee is already adjusted by the per block fee adjustment factor and is therefore the + /// share that the weight contributes to the overall fee of a transaction. It is mainly + /// for informational purposes and not used in the actual fee calculation. + fn convert(weight: Weight) -> BalanceOf { + NextFeeMultiplier::get().saturating_mul_int(Self::weight_to_fee(weight)) + } +} + +/// 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 where + T::Call: Dispatchable, + BalanceOf: Send + Sync + FixedPointOperand, +{ + /// utility constructor. Used only in client/factory code. + pub fn from(fee: BalanceOf) -> Self { + Self(fee) + } + + fn withdraw_fee( + &self, + who: &T::AccountId, + info: &DispatchInfoOf, + len: usize, + ) -> Result<(BalanceOf, Option>), TransactionValidityError> { + let tip = self.0; + let fee = Module::::compute_fee(len as u32, info, tip); + + // Only mess with balances if fee is not zero. + if fee.is_zero() { + return Ok((fee, None)); + } + + match T::Currency::withdraw( + who, + fee, + if tip.is_zero() { + WithdrawReason::TransactionPayment.into() + } else { + WithdrawReason::TransactionPayment | WithdrawReason::Tip + }, + ExistenceRequirement::KeepAlive, + ) { + Ok(imbalance) => Ok((fee, Some(imbalance))), + Err(_) => Err(InvalidTransaction::Payment.into()), + } + } } impl sp_std::fmt::Debug for ChargeTransactionPayment { @@ -200,46 +418,25 @@ impl sp_std::fmt::Debug for ChargeTransactionPayment } } -impl SignedExtension for ChargeTransactionPayment - where BalanceOf: Send + Sync +impl SignedExtension for ChargeTransactionPayment where + BalanceOf: Send + Sync + From + FixedPointOperand, + T::Call: Dispatchable, { const IDENTIFIER: &'static str = "ChargeTransactionPayment"; type AccountId = T::AccountId; type Call = T::Call; type AdditionalSigned = (); - type DispatchInfo = DispatchInfo; - type Pre = (); + type Pre = (BalanceOf, Self::AccountId, Option>, BalanceOf); fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) } fn validate( &self, who: &Self::AccountId, _call: &Self::Call, - info: Self::DispatchInfo, + info: &DispatchInfoOf, len: usize, ) -> TransactionValidity { - // pay any fees. - let tip = self.0; - let fee = Self::compute_fee(len as u32, info, tip); - // Only mess with balances if fee is not zero. - if !fee.is_zero() { - 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(), - }; - let imbalances = imbalance.split(tip); - T::OnTransactionPayment::on_unbalanceds(Some(imbalances.0).into_iter() - .chain(Some(imbalances.1))); - } + let (fee, _) = self.withdraw_fee(who, info, len)?; let mut r = ValidTransaction::default(); // NOTE: we probably want to maximize the _fee (of any type) per weight unit_ here, which @@ -247,6 +444,53 @@ impl SignedExtension for ChargeTransactionPayment r.priority = fee.saturated_into::(); Ok(r) } + + fn pre_dispatch( + self, + who: &Self::AccountId, + _call: &Self::Call, + info: &DispatchInfoOf, + len: usize + ) -> Result { + let (fee, imbalance) = self.withdraw_fee(who, info, len)?; + Ok((self.0, who.clone(), imbalance, fee)) + } + + fn post_dispatch( + pre: Self::Pre, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, + len: usize, + _result: &DispatchResult, + ) -> Result<(), TransactionValidityError> { + let (tip, who, imbalance, fee) = pre; + if let Some(payed) = imbalance { + let actual_fee = Module::::compute_actual_fee( + len as u32, + info, + post_info, + tip, + ); + let refund = fee.saturating_sub(actual_fee); + let actual_payment = match T::Currency::deposit_into_existing(&who, refund) { + Ok(refund_imbalance) => { + // The refund cannot be larger than the up front payed max weight. + // `PostDispatchInfo::calc_unspent` guards against such a case. + match payed.offset(refund_imbalance) { + Ok(actual_payment) => actual_payment, + Err(_) => return Err(InvalidTransaction::Payment.into()), + } + } + // We do not recreate the account using the refund. The up front payment + // is gone in that case. + Err(_) => payed, + }; + let imbalances = actual_payment.split(tip); + T::OnTransactionPayment::on_unbalanceds(Some(imbalances.0).into_iter() + .chain(Some(imbalances.1))); + } + Ok(()) + } } #[cfg(test)] @@ -254,8 +498,11 @@ mod tests { use super::*; use codec::Encode; use frame_support::{ - impl_outer_dispatch, impl_outer_origin, parameter_types, - weights::{DispatchClass, DispatchInfo, GetDispatchInfo, Weight}, + impl_outer_dispatch, impl_outer_origin, impl_outer_event, parameter_types, + weights::{ + DispatchClass, DispatchInfo, PostDispatchInfo, GetDispatchInfo, Weight, + WeightToFeePolynomial, WeightToFeeCoefficients, WeightToFeeCoefficient, + }, }; use pallet_balances::Call as BalancesCall; use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo; @@ -266,6 +513,7 @@ mod tests { Perbill, }; use std::cell::RefCell; + use smallvec::smallvec; const CALL: &::Call = &Call::Balances(BalancesCall::transfer(2, 69)); @@ -277,6 +525,13 @@ mod tests { } } + impl_outer_event! { + pub enum Event for Runtime { + system, + pallet_balances, + } + } + #[derive(Clone, PartialEq, Eq, Debug)] pub struct Runtime; @@ -285,6 +540,15 @@ mod tests { pub enum Origin for Runtime {} } + thread_local! { + static EXTRINSIC_BASE_WEIGHT: RefCell = RefCell::new(0); + } + + pub struct ExtrinsicBaseWeight; + impl Get for ExtrinsicBaseWeight { + fn get() -> u64 { EXTRINSIC_BASE_WEIGHT.with(|v| *v.borrow()) } + } + parameter_types! { pub const BlockHashCount: u64 = 250; pub const MaximumBlockWeight: Weight = 1024; @@ -293,6 +557,7 @@ mod tests { } impl frame_system::Trait for Runtime { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -302,9 +567,13 @@ mod tests { type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; - type Event = (); + type Event = Event; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = ExtrinsicBaseWeight; + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -312,6 +581,7 @@ mod tests { type AccountData = pallet_balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } parameter_types! { @@ -320,38 +590,39 @@ mod tests { impl pallet_balances::Trait for Runtime { type Balance = u64; - type Event = (); + type Event = Event; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; + type WeightInfo = (); } 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)) + pub struct WeightToFee; + impl WeightToFeePolynomial for WeightToFee { + type Balance = u64; + + fn polynomial() -> WeightToFeeCoefficients { + smallvec![WeightToFeeCoefficient { + degree: 1, + coeff_frac: Perbill::zero(), + coeff_integer: WEIGHT_TO_FEE.with(|v| *v.borrow()), + negative: false, + }] } } impl Trait for Runtime { type Currency = pallet_balances::Module; type OnTransactionPayment = (); - type TransactionBaseFee = TransactionBaseFee; type TransactionByteFee = TransactionByteFee; type WeightToFee = WeightToFee; type FeeMultiplierUpdate = (); @@ -363,7 +634,7 @@ mod tests { pub struct ExtBuilder { balance_factor: u64, - base_fee: u64, + base_weight: u64, byte_fee: u64, weight_to_fee: u64 } @@ -372,7 +643,7 @@ mod tests { fn default() -> Self { Self { balance_factor: 1, - base_fee: 0, + base_weight: 0, byte_fee: 1, weight_to_fee: 1, } @@ -380,8 +651,8 @@ mod tests { } impl ExtBuilder { - pub fn base_fee(mut self, base_fee: u64) -> Self { - self.base_fee = base_fee; + pub fn base_weight(mut self, base_weight: u64) -> Self { + self.base_weight = base_weight; self } pub fn byte_fee(mut self, byte_fee: u64) -> Self { @@ -397,7 +668,7 @@ mod tests { self } fn set_constants(&self) { - TRANSACTION_BASE_FEE.with(|v| *v.borrow_mut() = self.base_fee); + EXTRINSIC_BASE_WEIGHT.with(|v| *v.borrow_mut() = self.base_weight); TRANSACTION_BYTE_FEE.with(|v| *v.borrow_mut() = self.byte_fee); WEIGHT_TO_FEE.with(|v| *v.borrow_mut() = self.weight_to_fee); } @@ -424,31 +695,77 @@ mod tests { /// 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, pays_fee: true, ..Default::default() } + // pays_fee: Pays::Yes -- class: DispatchClass::Normal + DispatchInfo { weight: w, ..Default::default() } + } + + fn post_info_from_weight(w: Weight) -> PostDispatchInfo { + PostDispatchInfo { actual_weight: Some(w), } + } + + fn default_post_info() -> PostDispatchInfo { + PostDispatchInfo { actual_weight: None, } } #[test] fn signed_extension_transaction_payment_work() { ExtBuilder::default() .balance_factor(10) - .base_fee(5) + .base_weight(5) .build() .execute_with(|| { let len = 10; + let pre = ChargeTransactionPayment::::from(0) + .pre_dispatch(&1, CALL, &info_from_weight(5), len) + .unwrap(); + assert_eq!(Balances::free_balance(1), 100 - 5 - 5 - 10); + assert!( - ChargeTransactionPayment::::from(0) - .pre_dispatch(&1, CALL, info_from_weight(5), len) + ChargeTransactionPayment:: + ::post_dispatch(pre, &info_from_weight(5), &default_post_info(), len, &Ok(())) .is_ok() ); assert_eq!(Balances::free_balance(1), 100 - 5 - 5 - 10); + let pre = ChargeTransactionPayment::::from(5 /* tipped */) + .pre_dispatch(&2, CALL, &info_from_weight(100), len) + .unwrap(); + assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5); + + assert!( + ChargeTransactionPayment:: + ::post_dispatch(pre, &info_from_weight(100), &post_info_from_weight(50), len, &Ok(())) + .is_ok() + ); + assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 50 - 5); + }); + } + + #[test] + fn signed_extension_transaction_payment_multiplied_refund_works() { + ExtBuilder::default() + .balance_factor(10) + .base_weight(5) + .build() + .execute_with(|| + { + let len = 10; + NextFeeMultiplier::put(Multiplier::saturating_from_rational(3, 2)); + + let pre = ChargeTransactionPayment::::from(5 /* tipped */) + .pre_dispatch(&2, CALL, &info_from_weight(100), len) + .unwrap(); + // 5 base fee, 10 byte fee, 3/2 * 100 weight fee, 5 tip + assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 150 - 5); + assert!( - ChargeTransactionPayment::::from(5 /* tipped */) - .pre_dispatch(&2, CALL, info_from_weight(3), len) + ChargeTransactionPayment:: + ::post_dispatch(pre, &info_from_weight(100), &post_info_from_weight(50), len, &Ok(())) .is_ok() ); - assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 3 - 5); + // 75 (3/2 of the returned 50 units of weight) is refunded + assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 75 - 5); }); } @@ -463,7 +780,7 @@ mod tests { // maximum weight possible assert!( ChargeTransactionPayment::::from(0) - .pre_dispatch(&1, CALL, info_from_weight(Weight::max_value()), 10) + .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. @@ -477,7 +794,7 @@ mod tests { #[test] fn signed_extension_allows_free_transactions() { ExtBuilder::default() - .base_fee(100) + .base_weight(100) .balance_factor(0) .build() .execute_with(|| @@ -491,11 +808,11 @@ mod tests { let operational_transaction = DispatchInfo { weight: 0, class: DispatchClass::Operational, - pays_fee: false, + pays_fee: Pays::No, }; assert!( ChargeTransactionPayment::::from(0) - .validate(&1, CALL, operational_transaction , len) + .validate(&1, CALL, &operational_transaction , len) .is_ok() ); @@ -503,11 +820,11 @@ mod tests { let free_transaction = DispatchInfo { weight: 0, class: DispatchClass::Normal, - pays_fee: true, + pays_fee: Pays::Yes, }; assert!( ChargeTransactionPayment::::from(0) - .validate(&1, CALL, free_transaction , len) + .validate(&1, CALL, &free_transaction , len) .is_err() ); }); @@ -516,21 +833,28 @@ mod tests { #[test] fn signed_ext_length_fee_is_also_updated_per_congestion() { ExtBuilder::default() - .base_fee(5) + .base_weight(5) .balance_factor(10) .build() .execute_with(|| { // all fees should be x1.5 - NextFeeMultiplier::put(Fixed64::from_rational(1, 2)); + NextFeeMultiplier::put(Multiplier::saturating_from_rational(3, 2)); let len = 10; assert!( ChargeTransactionPayment::::from(10) // tipped - .pre_dispatch(&1, CALL, info_from_weight(3), len) + .pre_dispatch(&1, CALL, &info_from_weight(3), len) .is_ok() ); - assert_eq!(Balances::free_balance(1), 100 - 10 - 5 - (10 + 3) * 3 / 2); + assert_eq!( + Balances::free_balance(1), + 100 // original + - 10 // tip + - 5 // base + - 10 // len + - (3 * 3 / 2) // adjusted weight + ); }) } @@ -544,13 +868,13 @@ mod tests { let ext = xt.encode(); let len = ext.len() as u32; ExtBuilder::default() - .base_fee(5) + .base_weight(5) .weight_fee(2) .build() .execute_with(|| { // all fees should be x1.5 - NextFeeMultiplier::put(Fixed64::from_rational(1, 2)); + NextFeeMultiplier::put(Multiplier::saturating_from_rational(3, 2)); assert_eq!( TransactionPayment::query_info(xt, len), @@ -558,11 +882,9 @@ mod tests { 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 + 5 * 2 /* base * weight_fee */ + + len as u64 /* len * 1 */ + + info.weight.min(MaximumBlockWeight::get()) as u64 * 2 * 3 / 2 /* weight */ }, ); @@ -572,80 +894,114 @@ mod tests { #[test] fn compute_fee_works_without_multiplier() { ExtBuilder::default() - .base_fee(100) + .base_weight(100) .byte_fee(10) .balance_factor(0) .build() .execute_with(|| { // Next fee multiplier is zero - assert_eq!(NextFeeMultiplier::get(), Fixed64::from_natural(0)); + assert_eq!(NextFeeMultiplier::get(), Multiplier::one()); // Tip only, no fees works let dispatch_info = DispatchInfo { weight: 0, class: DispatchClass::Operational, - pays_fee: false, + pays_fee: Pays::No, }; - assert_eq!(ChargeTransactionPayment::::compute_fee(0, dispatch_info, 10), 10); + assert_eq!(Module::::compute_fee(0, &dispatch_info, 10), 10); // No tip, only base fee works let dispatch_info = DispatchInfo { weight: 0, class: DispatchClass::Operational, - pays_fee: true, + pays_fee: Pays::Yes, }; - assert_eq!(ChargeTransactionPayment::::compute_fee(0, dispatch_info, 0), 100); + assert_eq!(Module::::compute_fee(0, &dispatch_info, 0), 100); // Tip + base fee works - assert_eq!(ChargeTransactionPayment::::compute_fee(0, dispatch_info, 69), 169); + assert_eq!(Module::::compute_fee(0, &dispatch_info, 69), 169); // Len (byte fee) + base fee works - assert_eq!(ChargeTransactionPayment::::compute_fee(42, dispatch_info, 0), 520); + assert_eq!(Module::::compute_fee(42, &dispatch_info, 0), 520); // Weight fee + base fee works let dispatch_info = DispatchInfo { weight: 1000, class: DispatchClass::Operational, - pays_fee: true, + pays_fee: Pays::Yes, }; - assert_eq!(ChargeTransactionPayment::::compute_fee(0, dispatch_info, 0), 1100); + assert_eq!(Module::::compute_fee(0, &dispatch_info, 0), 1100); }); } #[test] fn compute_fee_works_with_multiplier() { ExtBuilder::default() - .base_fee(100) + .base_weight(100) .byte_fee(10) .balance_factor(0) .build() .execute_with(|| { - // Add a next fee multiplier - NextFeeMultiplier::put(Fixed64::from_rational(1, 2)); // = 1/2 = .5 + // Add a next fee multiplier. Fees will be x3/2. + NextFeeMultiplier::put(Multiplier::saturating_from_rational(3, 2)); // Base fee is unaffected by multiplier let dispatch_info = DispatchInfo { weight: 0, class: DispatchClass::Operational, - pays_fee: true, + pays_fee: Pays::Yes, }; - assert_eq!(ChargeTransactionPayment::::compute_fee(0, dispatch_info, 0), 100); + assert_eq!(Module::::compute_fee(0, &dispatch_info, 0), 100); // Everything works together :) let dispatch_info = DispatchInfo { weight: 123, class: DispatchClass::Operational, - pays_fee: true, + pays_fee: Pays::Yes, + }; + // 123 weight, 456 length, 100 base + assert_eq!( + Module::::compute_fee(456, &dispatch_info, 789), + 100 + (3 * 123 / 2) + 4560 + 789, + ); + }); + } + + #[test] + fn compute_fee_works_with_negative_multiplier() { + ExtBuilder::default() + .base_weight(100) + .byte_fee(10) + .balance_factor(0) + .build() + .execute_with(|| + { + // Add a next fee multiplier. All fees will be x1/2. + NextFeeMultiplier::put(Multiplier::saturating_from_rational(1, 2)); + + // Base fee is unaffected by multiplier. + let dispatch_info = DispatchInfo { + weight: 0, + class: DispatchClass::Operational, + pays_fee: Pays::Yes, + }; + assert_eq!(Module::::compute_fee(0, &dispatch_info, 0), 100); + + // Everything works together. + let dispatch_info = DispatchInfo { + weight: 123, + class: DispatchClass::Operational, + pays_fee: Pays::Yes, }; // 123 weight, 456 length, 100 base - // adjustable fee = (123 * 1) + (456 * 10) = 4683 - // adjusted fee = (4683 * .5) + 4683 = 7024.5 -> 7024 - // final fee = 100 + 7024 + 789 tip = 7913 - assert_eq!(ChargeTransactionPayment::::compute_fee(456, dispatch_info, 789), 7913); + assert_eq!( + Module::::compute_fee(456, &dispatch_info, 789), + 100 + (123 / 2) + 4560 + 789, + ); }); } #[test] fn compute_fee_does_not_overflow() { ExtBuilder::default() - .base_fee(100) + .base_weight(100) .byte_fee(10) .balance_factor(0) .build() @@ -653,18 +1009,144 @@ mod tests { { // Overflow is handled let dispatch_info = DispatchInfo { - weight: ::max_value(), + weight: Weight::max_value(), class: DispatchClass::Operational, - pays_fee: true, + pays_fee: Pays::Yes, }; assert_eq!( - ChargeTransactionPayment::::compute_fee( + Module::::compute_fee( ::max_value(), - dispatch_info, + &dispatch_info, ::max_value() ), ::max_value() ); }); } + + #[test] + fn refund_does_not_recreate_account() { + ExtBuilder::default() + .balance_factor(10) + .base_weight(5) + .build() + .execute_with(|| + { + // So events are emitted + System::set_block_number(10); + let len = 10; + let pre = ChargeTransactionPayment::::from(5 /* tipped */) + .pre_dispatch(&2, CALL, &info_from_weight(100), len) + .unwrap(); + assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5); + + // kill the account between pre and post dispatch + assert!(Balances::transfer(Some(2).into(), 3, Balances::free_balance(2)).is_ok()); + assert_eq!(Balances::free_balance(2), 0); + + assert!( + ChargeTransactionPayment:: + ::post_dispatch(pre, &info_from_weight(100), &post_info_from_weight(50), len, &Ok(())) + .is_ok() + ); + assert_eq!(Balances::free_balance(2), 0); + // Transfer Event + assert!(System::events().iter().any(|event| { + event.event == Event::pallet_balances(pallet_balances::RawEvent::Transfer(2, 3, 80)) + })); + // Killed Event + assert!(System::events().iter().any(|event| { + event.event == Event::system(system::RawEvent::KilledAccount(2)) + })); + }); + } + + #[test] + fn actual_weight_higher_than_max_refunds_nothing() { + ExtBuilder::default() + .balance_factor(10) + .base_weight(5) + .build() + .execute_with(|| + { + let len = 10; + let pre = ChargeTransactionPayment::::from(5 /* tipped */) + .pre_dispatch(&2, CALL, &info_from_weight(100), len) + .unwrap(); + assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5); + + assert!( + ChargeTransactionPayment:: + ::post_dispatch(pre, &info_from_weight(100), &post_info_from_weight(101), len, &Ok(())) + .is_ok() + ); + assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5); + }); + } + + #[test] + fn zero_transfer_on_free_transaction() { + ExtBuilder::default() + .balance_factor(10) + .base_weight(5) + .build() + .execute_with(|| + { + // So events are emitted + System::set_block_number(10); + let len = 10; + let dispatch_info = DispatchInfo { + weight: 100, + pays_fee: Pays::No, + class: DispatchClass::Normal, + }; + let user = 69; + let pre = ChargeTransactionPayment::::from(0) + .pre_dispatch(&user, CALL, &dispatch_info, len) + .unwrap(); + assert_eq!(Balances::total_balance(&user), 0); + assert!( + ChargeTransactionPayment:: + ::post_dispatch(pre, &dispatch_info, &default_post_info(), len, &Ok(())) + .is_ok() + ); + assert_eq!(Balances::total_balance(&user), 0); + // No events for such a scenario + assert_eq!(System::events().len(), 0); + }); + } + + #[test] + fn refund_consistent_with_actual_weight() { + ExtBuilder::default() + .balance_factor(10) + .base_weight(7) + .build() + .execute_with(|| + { + let info = info_from_weight(100); + let post_info = post_info_from_weight(33); + let prev_balance = Balances::free_balance(2); + let len = 10; + let tip = 5; + + NextFeeMultiplier::put(Multiplier::saturating_from_rational(5, 4)); + + let pre = ChargeTransactionPayment::::from(tip) + .pre_dispatch(&2, CALL, &info, len) + .unwrap(); + + ChargeTransactionPayment:: + ::post_dispatch(pre, &info, &post_info, len, &Ok(())) + .unwrap(); + + let refund_based_fee = prev_balance - Balances::free_balance(2); + let actual_fee = Module:: + ::compute_actual_fee(len as u32, &info, &post_info, tip); + + // 33 weight, 10 length, 7 base, 5 tip + assert_eq!(actual_fee, 7 + 10 + (33 * 5 / 4) + 5); + assert_eq!(refund_based_fee, actual_fee); + }); + } } diff --git a/frame/treasury/Cargo.toml b/frame/treasury/Cargo.toml index 6951c0eba9ae7bd566681e385ab8bf7ca9400718..dfab1aca43b2831ecdf70e9c49c76084030d1be9 100644 --- a/frame/treasury/Cargo.toml +++ b/frame/treasury/Cargo.toml @@ -1,27 +1,31 @@ [package] name = "pallet-treasury" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet to manage treasury" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } -pallet-balances = { version = "2.0.0-alpha.5", default-features = false, path = "../balances" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } +pallet-balances = { version = "2.0.0-rc4", default-features = false, path = "../balances" } -frame-benchmarking = { version = "2.0.0-alpha.5", default-features = false, path = "../benchmarking", optional = true } +frame-benchmarking = { version = "2.0.0-rc4", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-io ={ version = "2.0.0-alpha.5", path = "../../primitives/io" } -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } +sp-io ={ version = "2.0.0-rc4", path = "../../primitives/io" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +sp-storage = { version = "2.0.0-rc4", path = "../../primitives/storage" } [features] default = ["std"] @@ -38,6 +42,3 @@ runtime-benchmarks = [ "frame-benchmarking", "frame-support/runtime-benchmarks", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/treasury/src/benchmarking.rs b/frame/treasury/src/benchmarking.rs index 925832e04cb1d8fa8b6fb8740454cf2ebdfee694..8dddf3581aef2f1cd459c615465af1988778ed24 100644 --- a/frame/treasury/src/benchmarking.rs +++ b/frame/treasury/src/benchmarking.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Treasury pallet benchmarking. @@ -58,12 +59,15 @@ fn setup_awesome(length: u32) -> (T::AccountId, Vec, T::AccountId) fn setup_tip(r: u32, t: u32) -> Result<(T::AccountId, Vec, T::AccountId, BalanceOf), &'static str> { + let tippers_count = T::Tippers::count(); + for i in 0 .. t { let member = account("member", i, SEED); T::Tippers::add(&member); + ensure!(T::Tippers::contains(&member), "failed to add tipper"); } - ensure!(T::Tippers::count() == t as usize, "problem creating tippers"); + ensure!(T::Tippers::count() == tippers_count + t as usize, "problem creating tippers"); let caller = account("member", t - 1, SEED); let reason = vec![0; r as usize]; let beneficiary = account("beneficiary", t, SEED); @@ -71,16 +75,19 @@ fn setup_tip(r: u32, t: u32) -> Ok((caller, reason, beneficiary, value)) } -// Create `t` new types for the tip proposal with `hash`. -// This function automatically moves forward the block number to a time which -// would resolve the tipping process. +// Create `t` new tips for the tip proposal with `hash`. +// This function automatically makes the tip able to close. fn create_tips(t: u32, hash: T::Hash, value: BalanceOf) -> Result<(), &'static str> { for i in 0 .. t { let caller = account("member", i, SEED); ensure!(T::Tippers::contains(&caller), "caller is not a tipper"); Treasury::::tip(RawOrigin::Signed(caller).into(), hash, value)?; } - frame_system::Module::::set_block_number(T::TipCountdown::get() * 10.into()); + Tips::::mutate(hash, |maybe_tip| { + if let Some(open_tip) = maybe_tip { + open_tip.closes = Some(T::BlockNumber::zero()); + } + }); Ok(()) } @@ -211,3 +218,25 @@ benchmarks! { Treasury::::on_initialize(T::BlockNumber::zero()); } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::tests::{new_test_ext, Test}; + use frame_support::assert_ok; + + #[test] + fn test_benchmarks() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_propose_spend::()); + assert_ok!(test_benchmark_reject_proposal::()); + assert_ok!(test_benchmark_approve_proposal::()); + assert_ok!(test_benchmark_report_awesome::()); + assert_ok!(test_benchmark_retract_tip::()); + assert_ok!(test_benchmark_tip_new::()); + assert_ok!(test_benchmark_tip::()); + assert_ok!(test_benchmark_close_tip::()); + assert_ok!(test_benchmark_on_initialize::()); + }); + } +} diff --git a/frame/treasury/src/lib.rs b/frame/treasury/src/lib.rs index f07b9b511e1682edfd3c450239ed95eef2f546a2..0b6f9cb7fc2a5b9262f1e2c214b580f37a8b6206 100644 --- a/frame/treasury/src/lib.rs +++ b/frame/treasury/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Treasury Module //! @@ -98,10 +99,10 @@ use frame_support::traits::{ use sp_runtime::{Permill, ModuleId, Percent, RuntimeDebug, traits::{ Zero, StaticLookup, AccountIdConversion, Saturating, Hash, BadOrigin }}; -use frame_support::weights::{Weight, WeighData, SimpleDispatchInfo}; -use frame_support::traits::{Contains, EnsureOrigin}; +use frame_support::weights::{Weight, DispatchClass}; +use frame_support::traits::{Contains, ContainsLengthBound, EnsureOrigin}; use codec::{Encode, Decode}; -use frame_system::{self as system, ensure_signed, ensure_root}; +use frame_system::{self as system, ensure_signed}; mod tests; mod benchmarking; @@ -110,10 +111,34 @@ type BalanceOf = <::Currency as Currency< = <::Currency as Currency<::AccountId>>::PositiveImbalance; type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; -/// The treasury's module id, used for deriving its sovereign account ID. -const MODULE_ID: ModuleId = ModuleId(*b"py/trsry"); +pub trait WeightInfo { + fn propose_spend(u: u32, ) -> Weight; + fn reject_proposal(u: u32, ) -> Weight; + fn approve_proposal(u: u32, ) -> Weight; + fn report_awesome(r: u32, ) -> Weight; + fn retract_tip(r: u32, ) -> Weight; + fn tip_new(r: u32, t: u32, ) -> Weight; + fn tip(t: u32, ) -> Weight; + fn close_tip(t: u32, ) -> Weight; + fn on_initialize(p: u32, ) -> Weight; +} + +impl WeightInfo for () { + fn propose_spend(_u: u32, ) -> Weight { 1_000_000_000 } + fn reject_proposal(_u: u32, ) -> Weight { 1_000_000_000 } + fn approve_proposal(_u: u32, ) -> Weight { 1_000_000_000 } + fn report_awesome(_r: u32, ) -> Weight { 1_000_000_000 } + fn retract_tip(_r: u32, ) -> Weight { 1_000_000_000 } + fn tip_new(_r: u32, _t: u32, ) -> Weight { 1_000_000_000 } + fn tip(_t: u32, ) -> Weight { 1_000_000_000 } + fn close_tip(_t: u32, ) -> Weight { 1_000_000_000 } + fn on_initialize(_p: u32, ) -> Weight { 1_000_000_000 } +} pub trait Trait: frame_system::Trait { + /// The treasury's module id, used for deriving its sovereign account ID. + type ModuleId: Get; + /// The staking balance. type Currency: Currency + ReservableCurrency; @@ -124,7 +149,9 @@ pub trait Trait: frame_system::Trait { type RejectOrigin: EnsureOrigin; /// Origin from which tippers must come. - type Tippers: Contains; + /// + /// `ContainsLengthBound::max_len` must be cost free (i.e. no storage read or heavy operation). + type Tippers: Contains + ContainsLengthBound; /// The period for which a tip remains open after is has achieved threshold tippers. type TipCountdown: Get; @@ -156,6 +183,9 @@ pub trait Trait: frame_system::Trait { /// Percentage of spare funds (if any) that are burnt per spend period. type Burn: Get; + + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; } /// An index of a proposal. Just a `u32`. @@ -189,13 +219,17 @@ pub struct OpenTip< reason: Hash, /// The account to be tipped. who: AccountId, - /// The account who began this tip and the amount held on deposit. - finder: Option<(AccountId, Balance)>, + /// The account who began this tip. + finder: AccountId, + /// The amount held on deposit for this tip. + deposit: Balance, /// The block number at which this tip will close if `Some`. If `None`, then no closing is /// scheduled. closes: Option, /// The members who have voted for this tip. Sorted by AccountId. tips: Vec<(AccountId, Balance)>, + /// Whether this tip should result in the finder taking a fee. + finders_fee: bool, } decl_storage! { @@ -314,6 +348,9 @@ decl_module! { /// The amount held on deposit per byte within the tip report reason. const TipReportDepositPerByte: BalanceOf = T::TipReportDepositPerByte::get(); + /// The treasury's module id, used for deriving its sovereign account ID. + const ModuleId: ModuleId = T::ModuleId::get(); + type Error = Error; fn deposit_event() = default; @@ -323,11 +360,11 @@ decl_module! { /// proposal is awarded. /// /// # - /// - O(1). - /// - Limited storage reads. - /// - One DB change, one extra DB entry. + /// - Complexity: O(1) + /// - DbReads: `ProposalCount`, `origin account` + /// - DbWrites: `ProposalCount`, `Proposals`, `origin account` /// # - #[weight = SimpleDispatchInfo::FixedNormal(500_000)] + #[weight = 120_000_000 + T::DbWeight::get().reads_writes(1, 2)] fn propose_spend( origin, #[compact] value: BalanceOf, @@ -349,16 +386,16 @@ decl_module! { /// Reject a proposed spend. The original deposit will be slashed. /// + /// May only be called from `T::RejectOrigin`. + /// /// # - /// - O(1). - /// - Limited storage reads. - /// - One DB clear. + /// - Complexity: O(1) + /// - DbReads: `Proposals`, `rejected proposer account` + /// - DbWrites: `Proposals`, `rejected proposer account` /// # - #[weight = SimpleDispatchInfo::FixedOperational(100_000)] + #[weight = (130_000_000 + T::DbWeight::get().reads_writes(2, 2), DispatchClass::Operational)] fn reject_proposal(origin, #[compact] proposal_id: ProposalIndex) { - T::RejectOrigin::try_origin(origin) - .map(|_| ()) - .or_else(ensure_root)?; + T::RejectOrigin::ensure_origin(origin)?; let proposal = >::take(&proposal_id).ok_or(Error::::InvalidProposalIndex)?; let value = proposal.bond; @@ -371,16 +408,16 @@ decl_module! { /// Approve a proposal. At a later time, the proposal will be allocated to the beneficiary /// and the original deposit will be returned. /// + /// May only be called from `T::ApproveOrigin`. + /// /// # - /// - O(1). - /// - Limited storage reads. - /// - One DB change. + /// - Complexity: O(1). + /// - DbReads: `Proposals`, `Approvals` + /// - DbWrite: `Approvals` /// # - #[weight = SimpleDispatchInfo::FixedOperational(100_000)] + #[weight = (34_000_000 + T::DbWeight::get().reads_writes(2, 1), DispatchClass::Operational)] fn approve_proposal(origin, #[compact] proposal_id: ProposalIndex) { - T::ApproveOrigin::try_origin(origin) - .map(|_| ()) - .or_else(ensure_root)?; + T::ApproveOrigin::ensure_origin(origin)?; ensure!(>::contains_key(proposal_id), Error::::InvalidProposalIndex); Approvals::mutate(|v| v.push(proposal_id)); @@ -400,12 +437,12 @@ decl_module! { /// Emits `NewTip` if successful. /// /// # - /// - `O(R)` where `R` length of `reason`. - /// - One balance operation. - /// - One storage mutation (codec `O(R)`). - /// - One event. + /// - Complexity: `O(R)` where `R` length of `reason`. + /// - encoding and hashing of 'reason' + /// - DbReads: `Reasons`, `Tips`, `who account data` + /// - DbWrites: `Tips`, `who account data` /// # - #[weight = SimpleDispatchInfo::FixedNormal(100_000)] + #[weight = 140_000_000 + 4_000 * reason.len() as Weight + T::DbWeight::get().reads_writes(3, 2)] fn report_awesome(origin, reason: Vec, who: T::AccountId) { let finder = ensure_signed(origin)?; @@ -422,8 +459,15 @@ decl_module! { T::Currency::reserve(&finder, deposit)?; Reasons::::insert(&reason_hash, &reason); - let finder = Some((finder, deposit)); - let tip = OpenTip { reason: reason_hash, who, finder, closes: None, tips: vec![] }; + let tip = OpenTip { + reason: reason_hash, + who, + finder, + deposit, + closes: None, + tips: vec![], + finders_fee: true + }; Tips::::insert(&hash, tip); Self::deposit_event(RawEvent::NewTip(hash)); } @@ -442,21 +486,22 @@ decl_module! { /// Emits `TipRetracted` if successful. /// /// # - /// - `O(T)` - /// - One balance operation. - /// - Two storage removals (one read, codec `O(T)`). - /// - One event. + /// - Complexity: `O(1)` + /// - Depends on the length of `T::Hash` which is fixed. + /// - DbReads: `Tips`, `origin account` + /// - DbWrites: `Reasons`, `Tips`, `origin account` /// # - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + #[weight = 120_000_000 + T::DbWeight::get().reads_writes(1, 2)] fn retract_tip(origin, hash: T::Hash) { let who = ensure_signed(origin)?; let tip = Tips::::get(&hash).ok_or(Error::::UnknownTip)?; - let (finder, deposit) = tip.finder.ok_or(Error::::NotFinder)?; - ensure!(finder == who, Error::::NotFinder); + ensure!(tip.finder == who, Error::::NotFinder); Reasons::::remove(&tip.reason); Tips::::remove(&hash); - let _ = T::Currency::unreserve(&who, deposit); + if !tip.deposit.is_zero() { + let _ = T::Currency::unreserve(&who, tip.deposit); + } Self::deposit_event(RawEvent::TipRetracted(hash)); } @@ -474,12 +519,18 @@ decl_module! { /// Emits `NewTip` if successful. /// /// # - /// - `O(R + T)` where `R` length of `reason`, `T` is the number of tippers. `T` is - /// naturally capped as a membership set, `R` is limited through transaction-size. - /// - Two storage insertions (codecs `O(R)`, `O(T)`), one read `O(1)`. - /// - One event. + /// - Complexity: `O(R + T)` where `R` length of `reason`, `T` is the number of tippers. + /// - `O(T)`: decoding `Tipper` vec of length `T` + /// `T` is charged as upper bound given by `ContainsLengthBound`. + /// The actual cost depends on the implementation of `T::Tippers`. + /// - `O(R)`: hashing and encoding of reason of length `R` + /// - DbReads: `Tippers`, `Reasons` + /// - DbWrites: `Reasons`, `Tips` /// # - #[weight = SimpleDispatchInfo::FixedNormal(150_000)] + #[weight = 110_000_000 + + 4_000 * reason.len() as Weight + + 480_000 * T::Tippers::max_len() as Weight + + T::DbWeight::get().reads_writes(2, 2)] fn tip_new(origin, reason: Vec, who: T::AccountId, tip_value: BalanceOf) { let tipper = ensure_signed(origin)?; ensure!(T::Tippers::contains(&tipper), BadOrigin); @@ -489,8 +540,16 @@ decl_module! { Reasons::::insert(&reason_hash, &reason); Self::deposit_event(RawEvent::NewTip(hash.clone())); - let tips = vec![(tipper, tip_value)]; - let tip = OpenTip { reason: reason_hash, who, finder: None, closes: None, tips }; + let tips = vec![(tipper.clone(), tip_value)]; + let tip = OpenTip { + reason: reason_hash, + who, + finder: tipper, + deposit: Zero::zero(), + closes: None, + tips, + finders_fee: false, + }; Tips::::insert(&hash, tip); } @@ -509,11 +568,18 @@ decl_module! { /// has started. /// /// # - /// - `O(T)` - /// - One storage mutation (codec `O(T)`), one storage read `O(1)`. - /// - Up to one event. + /// - Complexity: `O(T)` where `T` is the number of tippers. + /// decoding `Tipper` vec of length `T`, insert tip and check closing, + /// `T` is charged as upper bound given by `ContainsLengthBound`. + /// The actual cost depends on the implementation of `T::Tippers`. + /// + /// Actually weight could be lower as it depends on how many tips are in `OpenTip` but it + /// is weighted as if almost full i.e of length `T-1`. + /// - DbReads: `Tippers`, `Tips` + /// - DbWrites: `Tips` /// # - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + #[weight = 68_000_000 + 2_000_000 * T::Tippers::max_len() as Weight + + T::DbWeight::get().reads_writes(2, 1)] fn tip(origin, hash: T::Hash, tip_value: BalanceOf) { let tipper = ensure_signed(origin)?; ensure!(T::Tippers::contains(&tipper), BadOrigin); @@ -535,11 +601,15 @@ decl_module! { /// as the hash of the tuple of the original tip `reason` and the beneficiary account ID. /// /// # - /// - `O(T)` - /// - One storage retrieval (codec `O(T)`) and two removals. - /// - Up to three balance operations. + /// - Complexity: `O(T)` where `T` is the number of tippers. + /// decoding `Tipper` vec of length `T`. + /// `T` is charged as upper bound given by `ContainsLengthBound`. + /// The actual cost depends on the implementation of `T::Tippers`. + /// - DbReads: `Tips`, `Tippers`, `tip finder` + /// - DbWrites: `Reasons`, `Tips`, `Tippers`, `tip finder` /// # - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + #[weight = 220_000_000 + 1_100_000 * T::Tippers::max_len() as Weight + + T::DbWeight::get().reads_writes(3, 3)] fn close_tip(origin, hash: T::Hash) { ensure_signed(origin)?; @@ -549,16 +619,26 @@ decl_module! { // closed. Reasons::::remove(&tip.reason); Tips::::remove(hash); - Self::payout_tip(tip); + Self::payout_tip(hash, tip); } + /// # + /// - Complexity: `O(A)` where `A` is the number of approvals + /// - Db reads and writes: `Approvals`, `pot account data` + /// - Db reads and writes per approval: + /// `Proposals`, `proposer account data`, `beneficiary account data` + /// - The weight is overestimated if some approvals got missed. + /// # fn on_initialize(n: T::BlockNumber) -> Weight { // Check to see if we should spend some funds! if (n % T::SpendPeriod::get()).is_zero() { - Self::spend_funds(); - } + let approvals_len = Self::spend_funds(); - SimpleDispatchInfo::default().weigh_data(()) + 270_000_000 * approvals_len + + T::DbWeight::get().reads_writes(2 + approvals_len * 3, 2 + approvals_len * 3) + } else { + 0 + } } } } @@ -571,7 +651,7 @@ impl Module { /// This actually does computation. If you need to keep using it, then make sure you cache the /// value and only call this once. pub fn account_id() -> T::AccountId { - MODULE_ID.into_account() + T::ModuleId::get().into_account() } /// The needed bond for a proposal whose spend is `value`. @@ -627,36 +707,40 @@ impl Module { /// /// Up to three balance operations. /// Plus `O(T)` (`T` is Tippers length). - fn payout_tip(tip: OpenTip, T::BlockNumber, T::Hash>) { + fn payout_tip(hash: T::Hash, tip: OpenTip, T::BlockNumber, T::Hash>) { let mut tips = tip.tips; Self::retain_active_tips(&mut tips); tips.sort_by_key(|i| i.1); let treasury = Self::account_id(); let max_payout = Self::pot(); let mut payout = tips[tips.len() / 2].1.min(max_payout); - if let Some((finder, deposit)) = tip.finder { - let _ = T::Currency::unreserve(&finder, deposit); - if finder != tip.who { + if !tip.deposit.is_zero() { + let _ = T::Currency::unreserve(&tip.finder, tip.deposit); + } + if tip.finders_fee { + if tip.finder != tip.who { // pay out the finder's fee. let finders_fee = T::TipFindersFee::get() * payout; payout -= finders_fee; // this should go through given we checked it's at most the free balance, but still // we only make a best-effort. - let _ = T::Currency::transfer(&treasury, &finder, finders_fee, KeepAlive); + let _ = T::Currency::transfer(&treasury, &tip.finder, finders_fee, KeepAlive); } } // same as above: best-effort only. let _ = T::Currency::transfer(&treasury, &tip.who, payout, KeepAlive); + Self::deposit_event(RawEvent::TipClosed(hash, tip.who, payout)); } - // Spend some money! - fn spend_funds() { + /// Spend some money! returns number of approvals before spend. + fn spend_funds() -> u64 { let mut budget_remaining = Self::pot(); Self::deposit_event(RawEvent::Spending(budget_remaining)); let mut missed_any = false; let mut imbalance = >::zero(); - Approvals::mutate(|v| { + let prior_approvals_len = Approvals::mutate(|v| { + let prior_approvals_len = v.len() as u64; v.retain(|&index| { // Should always be true, but shouldn't panic if false or we're screwed. if let Some(p) = Self::proposals(index) { @@ -680,6 +764,7 @@ impl Module { false } }); + prior_approvals_len }); if !missed_any { @@ -706,6 +791,8 @@ impl Module { } Self::deposit_event(RawEvent::Rollover(budget_remaining)); + + prior_approvals_len } /// Return the amount of money in the pot. @@ -715,6 +802,55 @@ impl Module { // Must never be less than 0 but better be safe. .saturating_sub(T::Currency::minimum_balance()) } + + pub fn migrate_retract_tip_for_tip_new() { + /// An open tipping "motion". Retains all details of a tip including information on the finder + /// and the members who have voted. + #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug)] + pub struct OldOpenTip< + AccountId: Parameter, + Balance: Parameter, + BlockNumber: Parameter, + Hash: Parameter, + > { + /// The hash of the reason for the tip. The reason should be a human-readable UTF-8 encoded string. A URL would be + /// sensible. + reason: Hash, + /// The account to be tipped. + who: AccountId, + /// The account who began this tip and the amount held on deposit. + finder: Option<(AccountId, Balance)>, + /// The block number at which this tip will close if `Some`. If `None`, then no closing is + /// scheduled. + closes: Option, + /// The members who have voted for this tip. Sorted by AccountId. + tips: Vec<(AccountId, Balance)>, + } + + use frame_support::{Twox64Concat, migration::StorageKeyIterator}; + + for (hash, old_tip) in StorageKeyIterator::< + T::Hash, + OldOpenTip, T::BlockNumber, T::Hash>, + Twox64Concat, + >::new(b"Treasury", b"Tips").drain() + { + let (finder, deposit, finders_fee) = match old_tip.finder { + Some((finder, deposit)) => (finder, deposit, true), + None => (T::AccountId::default(), Zero::zero(), false), + }; + let new_tip = OpenTip { + reason: old_tip.reason, + who: old_tip.who, + finder, + deposit, + closes: old_tip.closes, + tips: old_tip.tips, + finders_fee + }; + Tips::::insert(hash, new_tip) + } + } } impl OnUnbalanced> for Module { diff --git a/frame/treasury/src/tests.rs b/frame/treasury/src/tests.rs index 1f6dbecef516e6fd9c9d62729a0245026017db35..2fa960f1c7cc50af7021f46c039d7613f0c29c63 100644 --- a/frame/treasury/src/tests.rs +++ b/frame/treasury/src/tests.rs @@ -1,32 +1,33 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Treasury pallet tests. #![cfg(test)] use super::*; - +use std::cell::RefCell; use frame_support::{ - assert_noop, assert_ok, impl_outer_origin, parameter_types, weights::Weight, + assert_noop, assert_ok, impl_outer_origin, impl_outer_event, parameter_types, weights::Weight, traits::{Contains, OnInitialize} }; use sp_core::H256; use sp_runtime::{ - Perbill, + Perbill, ModuleId, testing::Header, traits::{BlakeTwo256, IdentityLookup, BadOrigin}, }; @@ -35,6 +36,21 @@ impl_outer_origin! { pub enum Origin for Test where system = frame_system {} } + +mod treasury { + // Re-export needed for `impl_outer_event!`. + pub use super::super::*; +} + +impl_outer_event! { + pub enum Event for Test { + system, + pallet_balances, + treasury, + } +} + + #[derive(Clone, Eq, PartialEq)] pub struct Test; parameter_types! { @@ -44,6 +60,7 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -53,9 +70,13 @@ impl frame_system::Trait for Test { type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; - type Event = (); + type Event = Event; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); @@ -63,27 +84,43 @@ impl frame_system::Trait for Test { type AccountData = pallet_balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } parameter_types! { pub const ExistentialDeposit: u64 = 1; } impl pallet_balances::Trait for Test { type Balance = u64; - type Event = (); + type Event = Event; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; + type WeightInfo = (); +} +thread_local! { + static TEN_TO_FOURTEEN: RefCell> = RefCell::new(vec![10,11,12,13,14]); } pub struct TenToFourteen; impl Contains for TenToFourteen { - fn contains(n: &u64) -> bool { - *n >= 10 && *n <= 14 - } fn sorted_members() -> Vec { - vec![10, 11, 12, 13, 14] + TEN_TO_FOURTEEN.with(|v| { + v.borrow().clone() + }) } #[cfg(feature = "runtime-benchmarks")] - fn add(_: &u64) { unimplemented!() } + fn add(new: &u64) { + TEN_TO_FOURTEEN.with(|v| { + let mut members = v.borrow_mut(); + members.push(*new); + members.sort(); + }) + } +} +impl ContainsLengthBound for TenToFourteen { + fn max_len() -> usize { + TEN_TO_FOURTEEN.with(|v| v.borrow().len()) + } + fn min_len() -> usize { 0 } } parameter_types! { pub const ProposalBond: Permill = Permill::from_percent(5); @@ -94,8 +131,10 @@ parameter_types! { pub const TipFindersFee: Percent = Percent::from_percent(20); pub const TipReportDepositBase: u64 = 1; pub const TipReportDepositPerByte: u64 = 1; + pub const TreasuryModuleId: ModuleId = ModuleId(*b"py/trsry"); } impl Trait for Test { + type ModuleId = TreasuryModuleId; type Currency = pallet_balances::Module; type ApproveOrigin = frame_system::EnsureRoot; type RejectOrigin = frame_system::EnsureRoot; @@ -104,18 +143,19 @@ impl Trait for Test { type TipFindersFee = TipFindersFee; type TipReportDepositBase = TipReportDepositBase; type TipReportDepositPerByte = TipReportDepositPerByte; - type Event = (); + type Event = Event; type ProposalRejection = (); type ProposalBond = ProposalBond; type ProposalBondMinimum = ProposalBondMinimum; type SpendPeriod = SpendPeriod; type Burn = Burn; + type WeightInfo = (); } type System = frame_system::Module; type Balances = pallet_balances::Module; type Treasury = Module; -fn new_test_ext() -> sp_io::TestExternalities { +pub fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); pallet_balances::GenesisConfig::{ // Total issuance will be 200 with treasury account initialized at ED. @@ -197,22 +237,58 @@ fn report_awesome_from_beneficiary_and_tip_works() { #[test] fn close_tip_works() { new_test_ext().execute_with(|| { + System::set_block_number(1); + Balances::make_free_balance_be(&Treasury::account_id(), 101); assert_eq!(Treasury::pot(), 100); assert_ok!(Treasury::tip_new(Origin::signed(10), b"awesome.dot".to_vec(), 3, 10)); + let h = tip_hash(); + + assert_eq!( + System::events().into_iter().map(|r| r.event) + .filter_map(|e| { + if let Event::treasury(inner) = e { Some(inner) } else { None } + }) + .last() + .unwrap(), + RawEvent::NewTip(h), + ); + assert_ok!(Treasury::tip(Origin::signed(11), h.clone(), 10)); + assert_noop!(Treasury::close_tip(Origin::signed(0), h.into()), Error::::StillOpen); assert_ok!(Treasury::tip(Origin::signed(12), h.clone(), 10)); + + assert_eq!( + System::events().into_iter().map(|r| r.event) + .filter_map(|e| { + if let Event::treasury(inner) = e { Some(inner) } else { None } + }) + .last() + .unwrap(), + RawEvent::TipClosing(h), + ); + assert_noop!(Treasury::close_tip(Origin::signed(0), h.into()), Error::::Premature); System::set_block_number(2); - assert_noop!(Treasury::close_tip(Origin::NONE, h.into()), BadOrigin); + assert_noop!(Treasury::close_tip(Origin::none(), h.into()), BadOrigin); assert_ok!(Treasury::close_tip(Origin::signed(0), h.into())); assert_eq!(Balances::free_balance(3), 10); + assert_eq!( + System::events().into_iter().map(|r| r.event) + .filter_map(|e| { + if let Event::treasury(inner) = e { Some(inner) } else { None } + }) + .last() + .unwrap(), + RawEvent::TipClosed(h, 3, 10), + ); + assert_noop!(Treasury::close_tip(Origin::signed(100), h.into()), Error::::UnknownTip); }); } @@ -220,6 +296,7 @@ fn close_tip_works() { #[test] fn retract_tip_works() { new_test_ext().execute_with(|| { + // with report awesome Balances::make_free_balance_be(&Treasury::account_id(), 101); assert_ok!(Treasury::report_awesome(Origin::signed(0), b"awesome.dot".to_vec(), 3)); let h = tip_hash(); @@ -230,6 +307,17 @@ fn retract_tip_works() { assert_ok!(Treasury::retract_tip(Origin::signed(0), h.clone())); System::set_block_number(2); assert_noop!(Treasury::close_tip(Origin::signed(0), h.into()), Error::::UnknownTip); + + // with tip new + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_ok!(Treasury::tip_new(Origin::signed(10), b"awesome.dot".to_vec(), 3, 10)); + let h = tip_hash(); + assert_ok!(Treasury::tip(Origin::signed(11), h.clone(), 10)); + assert_ok!(Treasury::tip(Origin::signed(12), h.clone(), 10)); + assert_noop!(Treasury::retract_tip(Origin::signed(0), h.clone()), Error::::NotFinder); + assert_ok!(Treasury::retract_tip(Origin::signed(10), h.clone())); + System::set_block_number(2); + assert_noop!(Treasury::close_tip(Origin::signed(10), h.into()), Error::::UnknownTip); }); } @@ -309,7 +397,7 @@ fn accepted_spend_proposal_ignored_outside_spend_period() { 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)); + assert_ok!(Treasury::approve_proposal(Origin::root(), 0)); >::on_initialize(1); assert_eq!(Balances::free_balance(3), 0); @@ -336,7 +424,7 @@ fn rejected_spend_proposal_ignored_on_spend_period() { 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)); + assert_ok!(Treasury::reject_proposal(Origin::root(), 0)); >::on_initialize(2); assert_eq!(Balances::free_balance(3), 0); @@ -350,22 +438,22 @@ fn reject_already_rejected_spend_proposal_fails() { 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)); - assert_noop!(Treasury::reject_proposal(Origin::ROOT, 0), Error::::InvalidProposalIndex); + assert_ok!(Treasury::reject_proposal(Origin::root(), 0)); + assert_noop!(Treasury::reject_proposal(Origin::root(), 0), Error::::InvalidProposalIndex); }); } #[test] fn reject_non_existent_spend_proposal_fails() { new_test_ext().execute_with(|| { - assert_noop!(Treasury::reject_proposal(Origin::ROOT, 0), Error::::InvalidProposalIndex); + assert_noop!(Treasury::reject_proposal(Origin::root(), 0), Error::::InvalidProposalIndex); }); } #[test] fn accept_non_existent_spend_proposal_fails() { new_test_ext().execute_with(|| { - assert_noop!(Treasury::approve_proposal(Origin::ROOT, 0), Error::::InvalidProposalIndex); + assert_noop!(Treasury::approve_proposal(Origin::root(), 0), Error::::InvalidProposalIndex); }); } @@ -375,8 +463,8 @@ fn accept_already_rejected_spend_proposal_fails() { 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)); - assert_noop!(Treasury::approve_proposal(Origin::ROOT, 0), Error::::InvalidProposalIndex); + assert_ok!(Treasury::reject_proposal(Origin::root(), 0)); + assert_noop!(Treasury::approve_proposal(Origin::root(), 0), Error::::InvalidProposalIndex); }); } @@ -387,7 +475,7 @@ fn accepted_spend_proposal_enacted_on_spend_period() { assert_eq!(Treasury::pot(), 100); assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); - assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); + assert_ok!(Treasury::approve_proposal(Origin::root(), 0)); >::on_initialize(2); assert_eq!(Balances::free_balance(3), 100); @@ -402,7 +490,7 @@ fn pot_underflow_should_not_diminish() { assert_eq!(Treasury::pot(), 100); assert_ok!(Treasury::propose_spend(Origin::signed(0), 150, 3)); - assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); + assert_ok!(Treasury::approve_proposal(Origin::root(), 0)); >::on_initialize(2); assert_eq!(Treasury::pot(), 100); // Pot hasn't changed @@ -424,13 +512,13 @@ fn treasury_account_doesnt_get_deleted() { let treasury_balance = Balances::free_balance(&Treasury::account_id()); assert_ok!(Treasury::propose_spend(Origin::signed(0), treasury_balance, 3)); - assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); + assert_ok!(Treasury::approve_proposal(Origin::root(), 0)); >::on_initialize(2); 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)); + assert_ok!(Treasury::approve_proposal(Origin::root(), 1)); >::on_initialize(4); assert_eq!(Treasury::pot(), 0); // Pot is emptied @@ -454,9 +542,9 @@ fn inexistent_account_works() { 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::approve_proposal(Origin::root(), 0)); assert_ok!(Treasury::propose_spend(Origin::signed(0), 1, 3)); - assert_ok!(Treasury::approve_proposal(Origin::ROOT, 1)); + assert_ok!(Treasury::approve_proposal(Origin::root(), 1)); >::on_initialize(2); assert_eq!(Treasury::pot(), 0); // Pot hasn't changed assert_eq!(Balances::free_balance(3), 0); // Balance of `3` hasn't changed @@ -471,3 +559,97 @@ fn inexistent_account_works() { assert_eq!(Balances::free_balance(3), 99); // Balance of `3` has changed }); } + +#[test] +fn test_last_reward_migration() { + use sp_storage::Storage; + + let mut s = Storage::default(); + + #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug)] + pub struct OldOpenTip< + AccountId: Parameter, + Balance: Parameter, + BlockNumber: Parameter, + Hash: Parameter, + > { + /// The hash of the reason for the tip. The reason should be a human-readable UTF-8 encoded string. A URL would be + /// sensible. + reason: Hash, + /// The account to be tipped. + who: AccountId, + /// The account who began this tip and the amount held on deposit. + finder: Option<(AccountId, Balance)>, + /// The block number at which this tip will close if `Some`. If `None`, then no closing is + /// scheduled. + closes: Option, + /// The members who have voted for this tip. Sorted by AccountId. + tips: Vec<(AccountId, Balance)>, + } + + let reason1 = BlakeTwo256::hash(b"reason1"); + let hash1 = BlakeTwo256::hash_of(&(reason1, 10u64)); + + let old_tip_finder = OldOpenTip:: { + reason: reason1, + who: 10, + finder: Some((20, 30)), + closes: Some(13), + tips: vec![(40, 50), (60, 70)] + }; + + let reason2 = BlakeTwo256::hash(b"reason2"); + let hash2 = BlakeTwo256::hash_of(&(reason2, 20u64)); + + let old_tip_no_finder = OldOpenTip:: { + reason: reason2, + who: 20, + finder: None, + closes: Some(13), + tips: vec![(40, 50), (60, 70)] + }; + + let data = vec![ + ( + Tips::::hashed_key_for(hash1), + old_tip_finder.encode().to_vec() + ), + ( + Tips::::hashed_key_for(hash2), + old_tip_no_finder.encode().to_vec() + ), + ]; + + s.top = data.into_iter().collect(); + sp_io::TestExternalities::new(s).execute_with(|| { + Treasury::migrate_retract_tip_for_tip_new(); + + // Test w/ finder + assert_eq!( + Tips::::get(hash1), + Some(OpenTip { + reason: reason1, + who: 10, + finder: 20, + deposit: 30, + closes: Some(13), + tips: vec![(40, 50), (60, 70)], + finders_fee: true, + }) + ); + + // Test w/o finder + assert_eq!( + Tips::::get(hash2), + Some(OpenTip { + reason: reason2, + who: 20, + finder: Default::default(), + deposit: 0, + closes: Some(13), + tips: vec![(40, 50), (60, 70)], + finders_fee: false, + }) + ); + }); +} diff --git a/frame/utility/Cargo.toml b/frame/utility/Cargo.toml index cf1042d8521da3e0c8c538eaef51c48de03b5439..e4dbfdfff73ec728ee1acd3e71a46371347b7a90 100644 --- a/frame/utility/Cargo.toml +++ b/frame/utility/Cargo.toml @@ -1,28 +1,31 @@ [package] name = "pallet-utility" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME utilities pallet" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/core" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/io" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/core" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } -frame-benchmarking = { version = "2.0.0-alpha.5", default-features = false, path = "../benchmarking", optional = true } +frame-benchmarking = { version = "2.0.0-rc4", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -pallet-balances = { version = "2.0.0-alpha.5", path = "../balances" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0-rc4", path = "../balances" } [features] default = ["std"] @@ -39,6 +42,3 @@ runtime-benchmarks = [ "frame-benchmarking", "frame-support/runtime-benchmarks", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/utility/src/benchmarking.rs b/frame/utility/src/benchmarking.rs index f16754fad591e09c8e7e06abfb394a4ddc4c3c28..155a279807afc2bc185f94cba6aae6639be5b448 100644 --- a/frame/utility/src/benchmarking.rs +++ b/frame/utility/src/benchmarking.rs @@ -1,45 +1,36 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // Benchmarks for Utility Pallet #![cfg(feature = "runtime-benchmarks")] use super::*; -use frame_system::RawOrigin; +use frame_system::{RawOrigin, EventRecord}; use frame_benchmarking::{benchmarks, account}; -use sp_runtime::traits::Saturating; - -use crate::Module as Utility; const SEED: u32 = 0; -fn setup_multi(s: u32, z: u32) -> Result<(Vec, Box<::Call>), &'static str>{ - let mut signatories: Vec = Vec::new(); - for i in 0 .. s { - let signatory = account("signatory", i, SEED); - // Give them some balance for a possible deposit - let deposit = T::MultisigDepositBase::get() + T::MultisigDepositFactor::get() * s.into(); - let balance = T::Currency::minimum_balance().saturating_mul(100.into()) + deposit; - T::Currency::make_free_balance_be(&signatory, balance); - signatories.push(signatory); - } - signatories.sort(); - let call: Box<::Call> = Box::new(frame_system::Call::remark(vec![0; z as usize]).into()); - return Ok((signatories, call)) +fn assert_last_event(generic_event: ::Event) { + let events = frame_system::Module::::events(); + let system_event: ::Event = generic_event.into(); + // compare to the last event record + let EventRecord { event, .. } = &events[events.len() - 1]; + assert_eq!(event, &system_event); } benchmarks! { @@ -54,95 +45,28 @@ benchmarks! { } let caller = account("caller", 0, SEED); }: _(RawOrigin::Signed(caller), calls) + verify { + assert_last_event::(Event::BatchCompleted.into()) + } - as_sub { + as_derivative { let u in 0 .. 1000; let caller = account("caller", u, SEED); let call = Box::new(frame_system::Call::remark(vec![]).into()); }: _(RawOrigin::Signed(caller), u as u16, call) +} - as_multi_create { - // Signatories, need at least 2 total people - let s in 2 .. T::MaxSignatories::get() as u32; - // Transaction Length - let z in 0 .. 10_000; - let (mut signatories, call) = setup_multi::(s, z)?; - let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; - }: as_multi(RawOrigin::Signed(caller), s as u16, signatories, None, call) - - as_multi_approve { - // Signatories, need at least 2 people - let s in 2 .. T::MaxSignatories::get() as u32; - // Transaction Length - let z in 0 .. 10_000; - let (mut signatories, call) = setup_multi::(s, z)?; - let mut signatories2 = signatories.clone(); - let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; - // before the call, get the timepoint - let timepoint = Utility::::timepoint(); - // Create the multi - Utility::::as_multi(RawOrigin::Signed(caller).into(), s as u16, signatories, None, call.clone())?; - let caller2 = signatories2.remove(0); - }: as_multi(RawOrigin::Signed(caller2), s as u16, signatories2, Some(timepoint), call) - - as_multi_complete { - // Signatories, need at least 2 people - let s in 2 .. T::MaxSignatories::get() as u32; - // Transaction Length - let z in 0 .. 10_000; - let (mut signatories, call) = setup_multi::(s, z)?; - let mut signatories2 = signatories.clone(); - let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; - // before the call, get the timepoint - let timepoint = Utility::::timepoint(); - // Create the multi - Utility::::as_multi(RawOrigin::Signed(caller).into(), s as u16, signatories, None, call.clone())?; - // Everyone except the first person approves - for i in 1 .. s - 1 { - let mut signatories_loop = signatories2.clone(); - let caller_loop = signatories_loop.remove(i as usize); - Utility::::as_multi(RawOrigin::Signed(caller_loop).into(), s as u16, signatories_loop, Some(timepoint), call.clone())?; - } - let caller2 = signatories2.remove(0); - }: as_multi(RawOrigin::Signed(caller2), s as u16, signatories2, Some(timepoint), call) - - approve_as_multi_create { - // Signatories, need at least 2 people - let s in 2 .. T::MaxSignatories::get() as u32; - // Transaction Length - let z in 0 .. 10_000; - let (mut signatories, call) = setup_multi::(s, z)?; - let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; - let call_hash = call.using_encoded(blake2_256); - // Create the multi - }: approve_as_multi(RawOrigin::Signed(caller), s as u16, signatories, None, call_hash) - - approve_as_multi_approve { - // Signatories, need at least 2 people - let s in 2 .. T::MaxSignatories::get() as u32; - // Transaction Length - let z in 0 .. 10_000; - let (mut signatories, call) = setup_multi::(s, z)?; - let mut signatories2 = signatories.clone(); - let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; - let call_hash = call.using_encoded(blake2_256); - // before the call, get the timepoint - let timepoint = Utility::::timepoint(); - // Create the multi - Utility::::as_multi(RawOrigin::Signed(caller).into(), s as u16, signatories, None, call.clone())?; - let caller2 = signatories2.remove(0); - }: approve_as_multi(RawOrigin::Signed(caller2), s as u16, signatories2, Some(timepoint), call_hash) - - cancel_as_multi { - // Signatories, need at least 2 people - let s in 2 .. T::MaxSignatories::get() as u32; - // Transaction Length - let z in 0 .. 10_000; - let (mut signatories, call) = setup_multi::(s, z)?; - let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; - let call_hash = call.using_encoded(blake2_256); - let timepoint = Utility::::timepoint(); - // Create the multi - Utility::::as_multi(RawOrigin::Signed(caller.clone()).into(), s as u16, signatories.clone(), None, call.clone())?; - }: _(RawOrigin::Signed(caller), s as u16, signatories, timepoint, call_hash) +#[cfg(test)] +mod tests { + use super::*; + use crate::tests::{new_test_ext, Test}; + use frame_support::assert_ok; + + #[test] + fn test_benchmarks() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_batch::()); + assert_ok!(test_benchmark_as_derivative::()); + }); + } } diff --git a/frame/utility/src/lib.rs b/frame/utility/src/lib.rs index 49aea15a0f595a7633c2f7ce6fc8d6dfafe953f0..0b2697f4e4ef0e3b3a413a5ce29f69dd743ca5c5 100644 --- a/frame/utility/src/lib.rs +++ b/frame/utility/src/lib.rs @@ -1,43 +1,43 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Utility Module -//! A module with helpers for dispatch management. +//! A stateless module with helpers for dispatch management which does no re-authentication. //! //! - [`utility::Trait`](./trait.Trait.html) //! - [`Call`](./enum.Call.html) //! //! ## Overview //! -//! This module contains three basic pieces of functionality, two of which are stateless: +//! This module contains two basic pieces of functionality: //! - Batch dispatch: A stateless operation, allowing any origin to execute multiple calls in a //! single dispatch. This can be useful to amalgamate proposals, combining `set_code` with //! corresponding `set_storage`s, for efficient multiple payouts with just a single signature //! verify, or in combination with one of the other two dispatch functionality. //! - Pseudonymal dispatch: A stateless operation, allowing a signed origin to execute a call from -//! an alternative signed origin. Each account has 2**16 possible "pseudonyms" (alternative +//! an alternative signed origin. Each account has 2 * 2**16 possible "pseudonyms" (alternative //! account IDs) and these can be stacked. This can be useful as a key management tool, where you //! need multiple distinct accounts (e.g. as controllers for many staking accounts), but where //! it's perfectly fine to have each of them controlled by the same underlying keypair. -//! - Multisig dispatch (stateful): A potentially stateful operation, allowing multiple signed -//! origins (accounts) to coordinate and dispatch a call from a well-known origin, derivable -//! deterministically from the set of account IDs and the threshold number of accounts from the -//! set that must approve it. In the case that the threshold is just one then this is a stateless -//! operation. This is useful for multisig wallets where cryptographic threshold signatures are -//! not available or desired. +//! Derivative accounts are, for the purposes of proxy filtering considered exactly the same as +//! the oigin and are thus hampered with the origin's filters. +//! +//! Since proxy filters are respected in all dispatches of this module, it should never need to be +//! filtered by any proxy. //! //! ## Interface //! @@ -47,13 +47,7 @@ //! * `batch` - Dispatch multiple calls from the sender's origin. //! //! #### For pseudonymal dispatch -//! * `as_sub` - Dispatch a call from a secondary ("sub") signed origin. -//! -//! #### For multisig dispatch -//! * `as_multi` - Approve and if possible dispatch a call from a composite origin formed from a -//! number of signed origins. -//! * `approve_as_multi` - Approve a call from a composite origin. -//! * `cancel_as_multi` - Cancel a call from a composite origin. +//! * `as_derivative` - Dispatch a call from a derivative signed origin. //! //! [`Call`]: ./enum.Call.html //! [`Trait`]: ./trait.Trait.html @@ -65,130 +59,53 @@ use sp_std::prelude::*; use codec::{Encode, Decode}; use sp_core::TypeId; use sp_io::hashing::blake2_256; -use frame_support::{decl_module, decl_event, decl_error, decl_storage, Parameter, ensure, RuntimeDebug}; -use frame_support::{traits::{Get, ReservableCurrency, Currency}, - weights::{GetDispatchInfo, DispatchClass,FunctionOf}, - dispatch::PostDispatchInfo, +use frame_support::{decl_module, decl_event, decl_storage, Parameter}; +use frame_support::{ + traits::{OriginTrait, UnfilteredDispatchable}, + weights::{Weight, GetDispatchInfo, DispatchClass}, dispatch::PostDispatchInfo, }; -use frame_system::{self as system, ensure_signed}; +use frame_system::{ensure_signed, ensure_root}; use sp_runtime::{DispatchError, DispatchResult, traits::Dispatchable}; mod tests; mod benchmarking; -type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; +pub trait WeightInfo { + fn batch(c: u32, ) -> Weight; + fn as_derivative(u: u32, ) -> Weight; +} + +impl WeightInfo for () { + fn batch(_c: u32, ) -> Weight { 1_000_000_000 } + fn as_derivative(_u: u32, ) -> Weight { 1_000_000_000 } +} /// Configuration trait. pub trait Trait: frame_system::Trait { /// The overarching event type. - type Event: From> + Into<::Event>; + type Event: From + Into<::Event>; /// The overarching call type. - type Call: Parameter + Dispatchable + GetDispatchInfo + From>; - - /// The currency mechanism. - type Currency: ReservableCurrency; - - /// The base amount of currency needed to reserve for creating a multisig execution. - /// - /// This is held for an additional storage item whose value size is - /// `4 + sizeof((BlockNumber, Balance, AccountId))` bytes. - type MultisigDepositBase: Get>; - - /// The amount of currency needed per unit threshold when creating a multisig execution. - /// - /// This is held for adding 32 bytes more into a pre-existing storage value. - type MultisigDepositFactor: Get>; - - /// The maximum amount of signatories allowed in the multisig. - type MaxSignatories: Get; -} - -/// A global extrinsic index, formed as the extrinsic index within a block, together with that -/// block's height. This allows a transaction in which a multisig operation of a particular -/// composite was created to be uniquely identified. -#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, Default, RuntimeDebug)] -pub struct Timepoint { - /// The height of the chain at the point in time. - height: BlockNumber, - /// The index of the extrinsic at the point in time. - index: u32, -} + type Call: Parameter + Dispatchable + + GetDispatchInfo + From> + + UnfilteredDispatchable; -/// An open multisig operation. -#[derive(Clone, Eq, PartialEq, Encode, Decode, Default, RuntimeDebug)] -pub struct Multisig { - /// The extrinsic when the multisig operation was opened. - when: Timepoint, - /// The amount held in reserve of the `depositor`, to be returned once the operation ends. - deposit: Balance, - /// The account who opened it (i.e. the first to approve it). - depositor: AccountId, - /// The approvals achieved so far, including the depositor. Always sorted. - approvals: Vec, + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; } decl_storage! { - trait Store for Module as Utility { - /// The set of open multisig operations. - pub Multisigs: double_map - hasher(twox_64_concat) T::AccountId, hasher(blake2_128_concat) [u8; 32] - => Option, T::AccountId>>; - } -} - -decl_error! { - pub enum Error for Module { - /// Threshold is too low (zero). - ZeroThreshold, - /// Call is already approved by this signatory. - AlreadyApproved, - /// Call doesn't need any (more) approvals. - NoApprovalsNeeded, - /// There are too few signatories in the list. - TooFewSignatories, - /// There are too many signatories in the list. - TooManySignatories, - /// The signatories were provided out of order; they should be ordered. - SignatoriesOutOfOrder, - /// The sender was contained in the other signatories; it shouldn't be. - SenderInSignatories, - /// Multisig operation not found when attempting to cancel. - NotFound, - /// Only the account that originally created the multisig is able to cancel it. - NotOwner, - /// No timepoint was given, yet the multisig operation is already underway. - NoTimepoint, - /// A different timepoint was given to the multisig operation that is underway. - WrongTimepoint, - /// A timepoint was given, yet no multisig operation is underway. - UnexpectedTimepoint, - } + trait Store for Module as Utility {} } decl_event! { /// Events type. - pub enum Event where - AccountId = ::AccountId, - BlockNumber = ::BlockNumber - { + pub enum Event { /// Batch of dispatches did not complete fully. Index of first failing dispatch given, as /// well as the error. BatchInterrupted(u32, DispatchError), /// Batch of dispatches completed fully with no error. BatchCompleted, - /// A new multisig operation has begun. First param is the account that is approving, - /// second is the multisig account. - NewMultisig(AccountId, AccountId), - /// A multisig operation has been approved by someone. First param is the account that is - /// approving, third is the multisig account. - MultisigApproval(AccountId, Timepoint, AccountId), - /// A multisig operation has been executed. First param is the account that is - /// approving, third is the multisig account. - MultisigExecuted(AccountId, Timepoint, AccountId, DispatchResult), - /// A multisig operation has been cancelled. First param is the account that is - /// cancelling, third is the multisig account. - MultisigCancelled(AccountId, Timepoint, AccountId), } } @@ -202,22 +119,22 @@ impl TypeId for IndexedUtilityModuleId { decl_module! { pub struct Module for enum Call where origin: T::Origin { - type Error = Error; - /// Deposit one of this module's events by using the default implementation. fn deposit_event() = default; /// Send a batch of dispatch calls. /// - /// This will execute until the first one fails and then stop. - /// /// May be called from any origin. /// /// - `calls`: The calls to be dispatched from the same origin. /// + /// If origin is root then call are dispatch without checking origin filter. (This includes + /// bypassing `frame_system::Trait::BaseCallFilter`). + /// /// # - /// - The sum of the weights of the `calls`. - /// - One event. + /// - Base weight: 14.39 + .987 * c µs + /// - Plus the sum of the weights of the `calls`. + /// - Plus one additional event. (repeat read/write) /// # /// /// This will return `Ok` in all circumstances. To determine the success of the batch, an @@ -225,14 +142,12 @@ decl_module! { /// `BatchInterrupted` event is deposited, along with the number of successful calls made /// and the error of the failed call. If all were successful, then the `BatchCompleted` /// event is deposited. - #[weight = FunctionOf( - |args: (&Vec<::Call>,)| { - args.0.iter() - .map(|call| call.get_dispatch_info().weight) - .fold(10_000, |a, n| a + n) - }, - |args: (&Vec<::Call>,)| { - let all_operational = args.0.iter() + #[weight = ( + calls.iter() + .map(|call| call.get_dispatch_info().weight) + .fold(15_000_000, |a: Weight, n| a.saturating_add(n).saturating_add(1_000_000)), + { + let all_operational = calls.iter() .map(|call| call.get_dispatch_info().class) .all(|class| class == DispatchClass::Operational); if all_operational { @@ -241,333 +156,59 @@ decl_module! { DispatchClass::Normal } }, - true )] fn batch(origin, calls: Vec<::Call>) { + let is_root = ensure_root(origin.clone()).is_ok(); for (index, call) in calls.into_iter().enumerate() { - let result = call.dispatch(origin.clone()); + let result = if is_root { + call.dispatch_bypass_filter(origin.clone()) + } else { + call.dispatch(origin.clone()) + }; if let Err(e) = result { - Self::deposit_event(Event::::BatchInterrupted(index as u32, e.error)); + Self::deposit_event(Event::BatchInterrupted(index as u32, e.error)); return Ok(()); } } - Self::deposit_event(Event::::BatchCompleted); + Self::deposit_event(Event::BatchCompleted); } /// Send a call through an indexed pseudonym of the sender. /// - /// The dispatch origin for this call must be _Signed_. + /// Filter from origin are passed along. The call will be dispatched with an origin which + /// use the same filter as the origin of this call. /// - /// # - /// - The weight of the `call` + 10,000. - /// # - #[weight = FunctionOf( - |args: (&u16, &Box<::Call>)| args.1.get_dispatch_info().weight + 10_000, - |args: (&u16, &Box<::Call>)| args.1.get_dispatch_info().class, - true - )] - fn as_sub(origin, index: u16, call: Box<::Call>) -> DispatchResult { - let who = ensure_signed(origin)?; - let pseudonym = Self::sub_account_id(who, index); - call.dispatch(frame_system::RawOrigin::Signed(pseudonym).into()) - .map(|_| ()).map_err(|e| e.error) - } - - /// Register approval for a dispatch to be made from a deterministic composite account if - /// approved by a total of `threshold - 1` of `other_signatories`. - /// - /// If there are enough, then dispatch the call. + /// NOTE: If you need to ensure that any account-based filtering is not honored (i.e. + /// because you expect `proxy` to have been used prior in the call stack and you do not want + /// the call restrictions to apply to any sub-accounts), then use `as_multi_threshold_1` + /// in the Multisig pallet instead. /// - /// Payment: `MultisigDepositBase` will be reserved if this is the first approval, plus - /// `threshold` times `MultisigDepositFactor`. It is returned once this dispatch happens or - /// is cancelled. + /// NOTE: Prior to version *12, this was called `as_limited_sub`. /// /// The dispatch origin for this call must be _Signed_. /// - /// - `threshold`: The total number of approvals for this dispatch before it is executed. - /// - `other_signatories`: The accounts (other than the sender) who can approve this - /// dispatch. May not be empty. - /// - `maybe_timepoint`: If this is the first approval, then this must be `None`. If it is - /// not the first approval, then it must be `Some`, with the timepoint (block number and - /// transaction index) of the first approval transaction. - /// - `call`: The call to be executed. - /// - /// NOTE: Unless this is the final approval, you will generally want to use - /// `approve_as_multi` instead, since it only requires a hash of the call. - /// - /// Result is equivalent to the dispatched result if `threshold` is exactly `1`. Otherwise - /// on success, result is `Ok` and the result from the interior call, if it was executed, - /// may be found in the deposited `MultisigExecuted` event. - /// /// # - /// - `O(S + Z + Call)`. - /// - Up to one balance-reserve or unreserve operation. - /// - One passthrough operation, one insert, both `O(S)` where `S` is the number of - /// signatories. `S` is capped by `MaxSignatories`, with weight being proportional. - /// - One call encode & hash, both of complexity `O(Z)` where `Z` is tx-len. - /// - One encode & hash, both of complexity `O(S)`. - /// - Up to one binary search and insert (`O(logS + S)`). - /// - I/O: 1 read `O(S)`, up to 1 mutate `O(S)`. Up to one remove. - /// - One event. - /// - The weight of the `call`. - /// - Storage: inserts one item, value size bounded by `MaxSignatories`, with a - /// deposit taken for its lifetime of - /// `MultisigDepositBase + threshold * MultisigDepositFactor`. + /// - Base weight: 2.861 µs + /// - Plus the weight of the `call` /// # - #[weight = FunctionOf( - |args: (&u16, &Vec, &Option>, &Box<::Call>)| { - args.3.get_dispatch_info().weight + 10_000 * (args.1.len() as u32 + 1) - }, - |args: (&u16, &Vec, &Option>, &Box<::Call>)| { - args.3.get_dispatch_info().class - }, - true + #[weight = ( + call.get_dispatch_info().weight.saturating_add(3_000_000), + call.get_dispatch_info().class, )] - fn as_multi(origin, - threshold: u16, - other_signatories: Vec, - maybe_timepoint: Option>, - call: Box<::Call>, - ) -> DispatchResult { - let who = ensure_signed(origin)?; - ensure!(threshold >= 1, Error::::ZeroThreshold); - let max_sigs = T::MaxSignatories::get() as usize; - ensure!(!other_signatories.is_empty(), Error::::TooFewSignatories); - ensure!(other_signatories.len() < max_sigs, Error::::TooManySignatories); - let signatories = Self::ensure_sorted_and_insert(other_signatories, who.clone())?; - - let id = Self::multi_account_id(&signatories, threshold); - let call_hash = call.using_encoded(blake2_256); - - if let Some(mut m) = >::get(&id, call_hash) { - let timepoint = maybe_timepoint.ok_or(Error::::NoTimepoint)?; - ensure!(m.when == timepoint, Error::::WrongTimepoint); - if let Err(pos) = m.approvals.binary_search(&who) { - // we know threshold is greater than zero from the above ensure. - if (m.approvals.len() as u16) < threshold - 1 { - m.approvals.insert(pos, who.clone()); - >::insert(&id, call_hash, m); - Self::deposit_event(RawEvent::MultisigApproval(who, timepoint, id)); - return Ok(()) - } - } else { - if (m.approvals.len() as u16) < threshold { - Err(Error::::AlreadyApproved)? - } - } - - let result = call.dispatch(frame_system::RawOrigin::Signed(id.clone()).into()); - let _ = T::Currency::unreserve(&m.depositor, m.deposit); - >::remove(&id, call_hash); - Self::deposit_event(RawEvent::MultisigExecuted( - who, timepoint, id, result.map(|_| ()).map_err(|e| e.error) - )); - } else { - ensure!(maybe_timepoint.is_none(), Error::::UnexpectedTimepoint); - if threshold > 1 { - let deposit = T::MultisigDepositBase::get() - + T::MultisigDepositFactor::get() * threshold.into(); - T::Currency::reserve(&who, deposit)?; - >::insert(&id, call_hash, Multisig { - when: Self::timepoint(), - deposit, - depositor: who.clone(), - approvals: vec![who.clone()], - }); - Self::deposit_event(RawEvent::NewMultisig(who, id)); - } else { - return call.dispatch(frame_system::RawOrigin::Signed(id).into()) - .map(|_| ()).map_err(|e| e.error) - } - } - Ok(()) - } - - /// Register approval for a dispatch to be made from a deterministic composite account if - /// approved by a total of `threshold - 1` of `other_signatories`. - /// - /// Payment: `MultisigDepositBase` will be reserved if this is the first approval, plus - /// `threshold` times `MultisigDepositFactor`. It is returned once this dispatch happens or - /// is cancelled. - /// - /// The dispatch origin for this call must be _Signed_. - /// - /// - `threshold`: The total number of approvals for this dispatch before it is executed. - /// - `other_signatories`: The accounts (other than the sender) who can approve this - /// dispatch. May not be empty. - /// - `maybe_timepoint`: If this is the first approval, then this must be `None`. If it is - /// not the first approval, then it must be `Some`, with the timepoint (block number and - /// transaction index) of the first approval transaction. - /// - `call_hash`: The hash of the call to be executed. - /// - /// NOTE: If this is the final approval, you will want to use `as_multi` instead. - /// - /// # - /// - `O(S)`. - /// - Up to one balance-reserve or unreserve operation. - /// - One passthrough operation, one insert, both `O(S)` where `S` is the number of - /// signatories. `S` is capped by `MaxSignatories`, with weight being proportional. - /// - One encode & hash, both of complexity `O(S)`. - /// - Up to one binary search and insert (`O(logS + S)`). - /// - I/O: 1 read `O(S)`, up to 1 mutate `O(S)`. Up to one remove. - /// - One event. - /// - Storage: inserts one item, value size bounded by `MaxSignatories`, with a - /// deposit taken for its lifetime of - /// `MultisigDepositBase + threshold * MultisigDepositFactor`. - /// # - #[weight = FunctionOf( - |args: (&u16, &Vec, &Option>, &[u8; 32])| { - 10_000 * (args.1.len() as u32 + 1) - }, - DispatchClass::Normal, - true - )] - fn approve_as_multi(origin, - threshold: u16, - other_signatories: Vec, - maybe_timepoint: Option>, - call_hash: [u8; 32], - ) -> DispatchResult { - let who = ensure_signed(origin)?; - ensure!(threshold >= 1, Error::::ZeroThreshold); - let max_sigs = T::MaxSignatories::get() as usize; - ensure!(!other_signatories.is_empty(), Error::::TooFewSignatories); - ensure!(other_signatories.len() < max_sigs, Error::::TooManySignatories); - let signatories = Self::ensure_sorted_and_insert(other_signatories, who.clone())?; - - let id = Self::multi_account_id(&signatories, threshold); - - if let Some(mut m) = >::get(&id, call_hash) { - let timepoint = maybe_timepoint.ok_or(Error::::NoTimepoint)?; - ensure!(m.when == timepoint, Error::::WrongTimepoint); - ensure!(m.approvals.len() < threshold as usize, Error::::NoApprovalsNeeded); - if let Err(pos) = m.approvals.binary_search(&who) { - m.approvals.insert(pos, who.clone()); - >::insert(&id, call_hash, m); - Self::deposit_event(RawEvent::MultisigApproval(who, timepoint, id)); - } else { - Err(Error::::AlreadyApproved)? - } - } else { - if threshold > 1 { - ensure!(maybe_timepoint.is_none(), Error::::UnexpectedTimepoint); - let deposit = T::MultisigDepositBase::get() - + T::MultisigDepositFactor::get() * threshold.into(); - T::Currency::reserve(&who, deposit)?; - >::insert(&id, call_hash, Multisig { - when: Self::timepoint(), - deposit, - depositor: who.clone(), - approvals: vec![who.clone()], - }); - Self::deposit_event(RawEvent::NewMultisig(who, id)); - } else { - Err(Error::::NoApprovalsNeeded)? - } - } - Ok(()) - } - - /// Cancel a pre-existing, on-going multisig transaction. Any deposit reserved previously - /// for this operation will be unreserved on success. - /// - /// The dispatch origin for this call must be _Signed_. - /// - /// - `threshold`: The total number of approvals for this dispatch before it is executed. - /// - `other_signatories`: The accounts (other than the sender) who can approve this - /// dispatch. May not be empty. - /// - `timepoint`: The timepoint (block number and transaction index) of the first approval - /// transaction for this dispatch. - /// - `call_hash`: The hash of the call to be executed. - /// - /// # - /// - `O(S)`. - /// - Up to one balance-reserve or unreserve operation. - /// - One passthrough operation, one insert, both `O(S)` where `S` is the number of - /// signatories. `S` is capped by `MaxSignatories`, with weight being proportional. - /// - One encode & hash, both of complexity `O(S)`. - /// - One event. - /// - I/O: 1 read `O(S)`, one remove. - /// - Storage: removes one item. - /// # - #[weight = FunctionOf( - |args: (&u16, &Vec, &Timepoint, &[u8; 32])| { - 10_000 * (args.1.len() as u32 + 1) - }, - DispatchClass::Normal, - true - )] - fn cancel_as_multi(origin, - threshold: u16, - other_signatories: Vec, - timepoint: Timepoint, - call_hash: [u8; 32], - ) -> DispatchResult { - let who = ensure_signed(origin)?; - ensure!(threshold >= 1, Error::::ZeroThreshold); - let max_sigs = T::MaxSignatories::get() as usize; - ensure!(!other_signatories.is_empty(), Error::::TooFewSignatories); - ensure!(other_signatories.len() < max_sigs, Error::::TooManySignatories); - let signatories = Self::ensure_sorted_and_insert(other_signatories, who.clone())?; - - let id = Self::multi_account_id(&signatories, threshold); - - let m = >::get(&id, call_hash) - .ok_or(Error::::NotFound)?; - ensure!(m.when == timepoint, Error::::WrongTimepoint); - ensure!(m.depositor == who, Error::::NotOwner); - - let _ = T::Currency::unreserve(&m.depositor, m.deposit); - >::remove(&id, call_hash); - - Self::deposit_event(RawEvent::MultisigCancelled(who, timepoint, id)); - Ok(()) + fn as_derivative(origin, index: u16, call: Box<::Call>) -> DispatchResult { + let mut origin = origin; + let who = ensure_signed(origin.clone())?; + let pseudonym = Self::derivative_account_id(who, index); + origin.set_caller_from(frame_system::RawOrigin::Signed(pseudonym)); + call.dispatch(origin).map(|_| ()).map_err(|e| e.error) } } } impl Module { - /// Derive a sub-account ID from the owner account and the sub-account index. - pub fn sub_account_id(who: T::AccountId, index: u16) -> T::AccountId { + /// Derive a derivative account ID from the owner account and the sub-account index. + pub fn derivative_account_id(who: T::AccountId, index: u16) -> T::AccountId { let entropy = (b"modlpy/utilisuba", who, index).using_encoded(blake2_256); T::AccountId::decode(&mut &entropy[..]).unwrap_or_default() } - - /// Derive a multi-account ID from the sorted list of accounts and the threshold that are - /// required. - /// - /// NOTE: `who` must be sorted. If it is not, then you'll get the wrong answer. - pub fn multi_account_id(who: &[T::AccountId], threshold: u16) -> T::AccountId { - let entropy = (b"modlpy/utilisuba", who, threshold).using_encoded(blake2_256); - T::AccountId::decode(&mut &entropy[..]).unwrap_or_default() - } - - /// The current `Timepoint`. - pub fn timepoint() -> Timepoint { - Timepoint { - height: >::block_number(), - index: >::extrinsic_index().unwrap_or_default(), - } - } - - /// Check that signatories is sorted and doesn't contain sender, then insert sender. - fn ensure_sorted_and_insert(other_signatories: Vec, who: T::AccountId) - -> Result, DispatchError> - { - let mut signatories = other_signatories; - let mut maybe_last = None; - let mut index = 0; - for item in signatories.iter() { - if let Some(last) = maybe_last { - ensure!(last < item, Error::::SignatoriesOutOfOrder); - } - if item <= &who { - ensure!(item != &who, Error::::SenderInSignatories); - index += 1; - } - maybe_last = Some(item); - } - signatories.insert(index, who); - Ok(signatories) - } } diff --git a/frame/utility/src/tests.rs b/frame/utility/src/tests.rs index 9fcd525020a8096df1e6692678b9474b9bb89225..6de70506e452cb15f0c77501d20dcf18788cd070 100644 --- a/frame/utility/src/tests.rs +++ b/frame/utility/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // Tests for Utility Pallet @@ -22,7 +23,7 @@ use super::*; use frame_support::{ assert_ok, assert_noop, impl_outer_origin, parameter_types, impl_outer_dispatch, - weights::Weight, impl_outer_event + weights::Weight, impl_outer_event, dispatch::DispatchError, traits::Filter, storage, }; use sp_core::H256; use sp_runtime::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; @@ -31,12 +32,11 @@ use crate as utility; impl_outer_origin! { pub enum Origin for Test where system = frame_system {} } - impl_outer_event! { pub enum TestEvent for Test { - system, + frame_system, pallet_balances, - utility, + utility, } } impl_outer_dispatch! { @@ -59,6 +59,7 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = TestBaseCallFilter; type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -71,6 +72,10 @@ impl frame_system::Trait for Test { type Event = TestEvent; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -78,29 +83,39 @@ impl frame_system::Trait for Test { type AccountData = pallet_balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } parameter_types! { pub const ExistentialDeposit: u64 = 1; } impl pallet_balances::Trait for Test { type Balance = u64; - type Event = TestEvent; type DustRemoval = (); + type Event = TestEvent; type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; + type WeightInfo = (); } parameter_types! { pub const MultisigDepositBase: u64 = 1; pub const MultisigDepositFactor: u64 = 1; pub const MaxSignatories: u16 = 3; } +pub struct TestBaseCallFilter; +impl Filter for TestBaseCallFilter { + fn filter(c: &Call) -> bool { + match *c { + Call::Balances(_) => true, + // For benchmarking, this acts as a noop call + Call::System(frame_system::Call::remark(..)) => true, + _ => false, + } + } +} impl Trait for Test { type Event = TestEvent; type Call = Call; - type Currency = Balances; - type MultisigDepositBase = MultisigDepositBase; - type MultisigDepositFactor = MultisigDepositFactor; - type MaxSignatories = MaxSignatories; + type WeightInfo = (); } type System = frame_system::Module; type Balances = pallet_balances::Module; @@ -109,10 +124,10 @@ type Utility = Module; use pallet_balances::Call as BalancesCall; use pallet_balances::Error as BalancesError; -fn new_test_ext() -> sp_io::TestExternalities { +pub fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); pallet_balances::GenesisConfig:: { - balances: vec![(1, 10), (2, 10), (3, 10), (4, 10), (5, 10)], + balances: vec![(1, 10), (2, 10), (3, 10), (4, 10), (5, 2)], }.assimilate_storage(&mut t).unwrap(); let mut ext = sp_io::TestExternalities::new(t); ext.execute_with(|| System::set_block_number(1)); @@ -120,271 +135,24 @@ fn new_test_ext() -> sp_io::TestExternalities { } fn last_event() -> TestEvent { - system::Module::::events().pop().map(|e| e.event).expect("Event expected") + frame_system::Module::::events().pop().map(|e| e.event).expect("Event expected") } fn expect_event>(e: E) { assert_eq!(last_event(), e.into()); } -fn now() -> Timepoint { - Utility::timepoint() -} - -#[test] -fn multisig_deposit_is_taken_and_returned() { - new_test_ext().execute_with(|| { - let multi = Utility::multi_account_id(&[1, 2, 3][..], 2); - assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); - assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); - assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); - - let call = Box::new(Call::Balances(BalancesCall::transfer(6, 15))); - assert_ok!(Utility::as_multi(Origin::signed(1), 2, vec![2, 3], None, call.clone())); - assert_eq!(Balances::free_balance(1), 2); - assert_eq!(Balances::reserved_balance(1), 3); - - assert_ok!(Utility::as_multi(Origin::signed(2), 2, vec![1, 3], Some(now()), call)); - assert_eq!(Balances::free_balance(1), 5); - assert_eq!(Balances::reserved_balance(1), 0); - }); -} - -#[test] -fn cancel_multisig_returns_deposit() { - new_test_ext().execute_with(|| { - let call = Box::new(Call::Balances(BalancesCall::transfer(6, 15))); - let hash = call.using_encoded(blake2_256); - assert_ok!(Utility::approve_as_multi(Origin::signed(1), 3, vec![2, 3], None, hash.clone())); - assert_ok!(Utility::approve_as_multi(Origin::signed(2), 3, vec![1, 3], Some(now()), hash.clone())); - assert_eq!(Balances::free_balance(1), 6); - assert_eq!(Balances::reserved_balance(1), 4); - assert_ok!( - Utility::cancel_as_multi(Origin::signed(1), 3, vec![2, 3], now(), hash.clone()), - ); - assert_eq!(Balances::free_balance(1), 10); - assert_eq!(Balances::reserved_balance(1), 0); - }); -} - -#[test] -fn timepoint_checking_works() { - new_test_ext().execute_with(|| { - let multi = Utility::multi_account_id(&[1, 2, 3][..], 2); - assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); - assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); - assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); - - let call = Box::new(Call::Balances(BalancesCall::transfer(6, 15))); - let hash = call.using_encoded(blake2_256); - - assert_noop!( - Utility::approve_as_multi(Origin::signed(2), 2, vec![1, 3], Some(now()), hash.clone()), - Error::::UnexpectedTimepoint, - ); - - assert_ok!(Utility::approve_as_multi(Origin::signed(1), 2, vec![2, 3], None, hash)); - - assert_noop!( - Utility::as_multi(Origin::signed(2), 2, vec![1, 3], None, call.clone()), - Error::::NoTimepoint, - ); - let later = Timepoint { index: 1, .. now() }; - assert_noop!( - Utility::as_multi(Origin::signed(2), 2, vec![1, 3], Some(later), call.clone()), - Error::::WrongTimepoint, - ); - }); -} - -#[test] -fn multisig_2_of_3_works() { - new_test_ext().execute_with(|| { - let multi = Utility::multi_account_id(&[1, 2, 3][..], 2); - assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); - assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); - assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); - - let call = Box::new(Call::Balances(BalancesCall::transfer(6, 15))); - let hash = call.using_encoded(blake2_256); - assert_ok!(Utility::approve_as_multi(Origin::signed(1), 2, vec![2, 3], None, hash)); - assert_eq!(Balances::free_balance(6), 0); - - assert_ok!(Utility::as_multi(Origin::signed(2), 2, vec![1, 3], Some(now()), call)); - assert_eq!(Balances::free_balance(6), 15); - }); -} - -#[test] -fn multisig_3_of_3_works() { - new_test_ext().execute_with(|| { - let multi = Utility::multi_account_id(&[1, 2, 3][..], 3); - assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); - assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); - assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); - - let call = Box::new(Call::Balances(BalancesCall::transfer(6, 15))); - let hash = call.using_encoded(blake2_256); - assert_ok!(Utility::approve_as_multi(Origin::signed(1), 3, vec![2, 3], None, hash.clone())); - assert_ok!(Utility::approve_as_multi(Origin::signed(2), 3, vec![1, 3], Some(now()), hash.clone())); - assert_eq!(Balances::free_balance(6), 0); - - assert_ok!(Utility::as_multi(Origin::signed(3), 3, vec![1, 2], Some(now()), call)); - assert_eq!(Balances::free_balance(6), 15); - }); -} - -#[test] -fn cancel_multisig_works() { - new_test_ext().execute_with(|| { - let call = Box::new(Call::Balances(BalancesCall::transfer(6, 15))); - let hash = call.using_encoded(blake2_256); - assert_ok!(Utility::approve_as_multi(Origin::signed(1), 3, vec![2, 3], None, hash.clone())); - assert_ok!(Utility::approve_as_multi(Origin::signed(2), 3, vec![1, 3], Some(now()), hash.clone())); - assert_noop!( - Utility::cancel_as_multi(Origin::signed(2), 3, vec![1, 3], now(), hash.clone()), - Error::::NotOwner, - ); - assert_ok!( - Utility::cancel_as_multi(Origin::signed(1), 3, vec![2, 3], now(), hash.clone()), - ); - }); -} - #[test] -fn multisig_2_of_3_as_multi_works() { +fn as_derivative_works() { new_test_ext().execute_with(|| { - let multi = Utility::multi_account_id(&[1, 2, 3][..], 2); - assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); - assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); - assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); - - let call = Box::new(Call::Balances(BalancesCall::transfer(6, 15))); - assert_ok!(Utility::as_multi(Origin::signed(1), 2, vec![2, 3], None, call.clone())); - assert_eq!(Balances::free_balance(6), 0); - - assert_ok!(Utility::as_multi(Origin::signed(2), 2, vec![1, 3], Some(now()), call)); - assert_eq!(Balances::free_balance(6), 15); - }); -} - -#[test] -fn multisig_2_of_3_as_multi_with_many_calls_works() { - new_test_ext().execute_with(|| { - let multi = Utility::multi_account_id(&[1, 2, 3][..], 2); - assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); - assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); - assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); - - let call1 = Box::new(Call::Balances(BalancesCall::transfer(6, 10))); - let call2 = Box::new(Call::Balances(BalancesCall::transfer(7, 5))); - - assert_ok!(Utility::as_multi(Origin::signed(1), 2, vec![2, 3], None, call1.clone())); - assert_ok!(Utility::as_multi(Origin::signed(2), 2, vec![1, 3], None, call2.clone())); - assert_ok!(Utility::as_multi(Origin::signed(3), 2, vec![1, 2], Some(now()), call2)); - assert_ok!(Utility::as_multi(Origin::signed(3), 2, vec![1, 2], Some(now()), call1)); - - assert_eq!(Balances::free_balance(6), 10); - assert_eq!(Balances::free_balance(7), 5); - }); -} - -#[test] -fn multisig_2_of_3_cannot_reissue_same_call() { - new_test_ext().execute_with(|| { - let multi = Utility::multi_account_id(&[1, 2, 3][..], 2); - assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); - assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); - assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); - - let call = Box::new(Call::Balances(BalancesCall::transfer(6, 10))); - assert_ok!(Utility::as_multi(Origin::signed(1), 2, vec![2, 3], None, call.clone())); - assert_ok!(Utility::as_multi(Origin::signed(2), 2, vec![1, 3], Some(now()), call.clone())); - assert_eq!(Balances::free_balance(multi), 5); - - assert_ok!(Utility::as_multi(Origin::signed(1), 2, vec![2, 3], None, call.clone())); - assert_ok!(Utility::as_multi(Origin::signed(3), 2, vec![1, 2], Some(now()), call)); - - let err = DispatchError::from(BalancesError::::InsufficientBalance).stripped(); - expect_event(RawEvent::MultisigExecuted(3, now(), multi, Err(err))); - }); -} - -#[test] -fn zero_threshold_fails() { - new_test_ext().execute_with(|| { - let call = Box::new(Call::Balances(BalancesCall::transfer(6, 15))); - assert_noop!( - Utility::as_multi(Origin::signed(1), 0, vec![2], None, call), - Error::::ZeroThreshold, - ); - }); -} - -#[test] -fn too_many_signatories_fails() { - new_test_ext().execute_with(|| { - let call = Box::new(Call::Balances(BalancesCall::transfer(6, 15))); - assert_noop!( - Utility::as_multi(Origin::signed(1), 2, vec![2, 3, 4], None, call.clone()), - Error::::TooManySignatories, - ); - }); -} - -#[test] -fn duplicate_approvals_are_ignored() { - new_test_ext().execute_with(|| { - let call = Box::new(Call::Balances(BalancesCall::transfer(6, 15))); - let hash = call.using_encoded(blake2_256); - assert_ok!(Utility::approve_as_multi(Origin::signed(1), 2, vec![2, 3], None, hash.clone())); - assert_noop!( - Utility::approve_as_multi(Origin::signed(1), 2, vec![2, 3], Some(now()), hash.clone()), - Error::::AlreadyApproved, - ); - assert_ok!(Utility::approve_as_multi(Origin::signed(2), 2, vec![1, 3], Some(now()), hash.clone())); - assert_noop!( - Utility::approve_as_multi(Origin::signed(3), 2, vec![1, 2], Some(now()), hash.clone()), - Error::::NoApprovalsNeeded, - ); - }); -} - -#[test] -fn multisig_1_of_3_works() { - new_test_ext().execute_with(|| { - let multi = Utility::multi_account_id(&[1, 2, 3][..], 1); - assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); - assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); - assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); - - let call = Box::new(Call::Balances(BalancesCall::transfer(6, 15))); - let hash = call.using_encoded(blake2_256); - assert_noop!( - Utility::approve_as_multi(Origin::signed(1), 1, vec![2, 3], None, hash.clone()), - Error::::NoApprovalsNeeded, - ); - assert_noop!( - Utility::as_multi(Origin::signed(4), 1, vec![2, 3], None, call.clone()), - BalancesError::::InsufficientBalance, - ); - assert_ok!(Utility::as_multi(Origin::signed(1), 1, vec![2, 3], None, call)); - - assert_eq!(Balances::free_balance(6), 15); - }); -} - -#[test] -fn as_sub_works() { - new_test_ext().execute_with(|| { - let sub_1_0 = Utility::sub_account_id(1, 0); + let sub_1_0 = Utility::derivative_account_id(1, 0); assert_ok!(Balances::transfer(Origin::signed(1), sub_1_0, 5)); - assert_noop!(Utility::as_sub( + assert_noop!(Utility::as_derivative( Origin::signed(1), 1, Box::new(Call::Balances(BalancesCall::transfer(6, 3))), ), BalancesError::::InsufficientBalance); - assert_ok!(Utility::as_sub( + assert_ok!(Utility::as_derivative( Origin::signed(1), 0, Box::new(Call::Balances(BalancesCall::transfer(2, 3))), @@ -394,17 +162,33 @@ fn as_sub_works() { }); } +#[test] +fn as_derivative_filters() { + new_test_ext().execute_with(|| { + assert_noop!(Utility::as_derivative( + Origin::signed(1), + 1, + Box::new(Call::System(frame_system::Call::suicide())), + ), DispatchError::BadOrigin); + }); +} + #[test] fn batch_with_root_works() { new_test_ext().execute_with(|| { + let k = b"a".to_vec(); + let call = Call::System(frame_system::Call::set_storage(vec![(k.clone(), k.clone())])); + assert!(!TestBaseCallFilter::filter(&call)); assert_eq!(Balances::free_balance(1), 10); assert_eq!(Balances::free_balance(2), 10); - assert_ok!(Utility::batch(Origin::ROOT, vec![ + assert_ok!(Utility::batch(Origin::root(), vec![ + Call::Balances(BalancesCall::force_transfer(1, 2, 5)), Call::Balances(BalancesCall::force_transfer(1, 2, 5)), - Call::Balances(BalancesCall::force_transfer(1, 2, 5)) + call, // Check filters are correctly bypassed ])); assert_eq!(Balances::free_balance(1), 0); assert_eq!(Balances::free_balance(2), 20); + assert_eq!(storage::unhashed::get_raw(&k), Some(k)); }); } @@ -424,6 +208,18 @@ fn batch_with_signed_works() { }); } +#[test] +fn batch_with_signed_filters() { + new_test_ext().execute_with(|| { + assert_ok!( + Utility::batch(Origin::signed(1), vec![ + Call::System(frame_system::Call::suicide()) + ]), + ); + expect_event(Event::BatchInterrupted(0, DispatchError::BadOrigin)); + }); +} + #[test] fn batch_early_exit_works() { new_test_ext().execute_with(|| { diff --git a/frame/vesting/Cargo.toml b/frame/vesting/Cargo.toml index e40062706ff8559101e0390300b2a8af58a4174c..aa5f0731f21575c4004280996a62f604fcf5a075 100644 --- a/frame/vesting/Cargo.toml +++ b/frame/vesting/Cargo.toml @@ -1,28 +1,31 @@ [package] name = "pallet-vesting" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for manage vesting" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } enumflags2 = { version = "0.6.2" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../system" } -frame-benchmarking = { version = "2.0.0-alpha.5", default-features = false, path = "../benchmarking", optional = true } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" } +frame-benchmarking = { version = "2.0.0-rc4", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -pallet-balances = { version = "2.0.0-alpha.5", path = "../balances" } -sp-storage = { version = "2.0.0-alpha.5", path = "../../primitives/storage" } +sp-io = { version = "2.0.0-rc4", path = "../../primitives/io" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0-rc4", path = "../balances" } +sp-storage = { version = "2.0.0-rc4", path = "../../primitives/storage" } hex-literal = "0.2.1" [features] @@ -31,12 +34,8 @@ std = [ "serde", "codec/std", "sp-std/std", - "sp-io/std", "sp-runtime/std", "frame-support/std", "frame-system/std", ] runtime-benchmarks = ["frame-benchmarking"] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/frame/vesting/src/benchmarking.rs b/frame/vesting/src/benchmarking.rs index 2ef8ed9ef8dbb867136b37ceb43b85cdb3b21fc7..24cdc28c97f20f1e45531ec5fa61d024985562d4 100644 --- a/frame/vesting/src/benchmarking.rs +++ b/frame/vesting/src/benchmarking.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Vesting pallet benchmarking. @@ -21,106 +22,193 @@ use super::*; use frame_system::{RawOrigin, Module as System}; -use sp_io::hashing::blake2_256; use frame_benchmarking::{benchmarks, account}; +use sp_runtime::traits::Bounded; use crate::Module as Vesting; const SEED: u32 = 0; const MAX_LOCKS: u32 = 20; -fn add_locks(l: u32) { - for id in 0..l { - let lock_id = <[u8; 8]>::decode(&mut &id.using_encoded(blake2_256)[..]) - .unwrap_or_default(); - let locker = account("locker", 0, SEED); - let locked = 1; +type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; + +fn add_locks(who: &T::AccountId, n: u8) { + for id in 0..n { + let lock_id = [id; 8]; + let locked = 100; let reasons = WithdrawReason::Transfer | WithdrawReason::Reserve; - T::Currency::set_lock(lock_id, &locker, locked.into(), reasons); + T::Currency::set_lock(lock_id, who, locked.into(), reasons); } } -fn setup(b: u32) -> T::AccountId { - let locked = 1; - let per_block = 1; - let starting_block = 0; - - let caller = account("caller", 0, SEED); - System::::set_block_number(0.into()); - - // Add schedule to avoid `NotVesting` error. - let _ = Vesting::::add_vesting_schedule( - &caller, - locked.into(), - per_block.into(), - starting_block.into(), - ); - - // Set lock and block number to take different code paths. - let reasons = WithdrawReason::Transfer | WithdrawReason::Reserve; - T::Currency::set_lock(VESTING_ID, &caller, locked.into(), reasons); - System::::set_block_number(b.into()); - - caller +fn add_vesting_schedule(who: &T::AccountId) -> Result<(), &'static str> { + let locked = 100; + let per_block = 10; + let starting_block = 1; + + System::::set_block_number(0.into()); + + // Add schedule to avoid `NotVesting` error. + Vesting::::add_vesting_schedule( + &who, + locked.into(), + per_block.into(), + starting_block.into(), + )?; + Ok(()) } benchmarks! { - _ { - // Number of previous locks. - // It doesn't seems to influence the timings for lower values. - let l in 0 .. MAX_LOCKS => add_locks::(l); - } + _ { } vest_locked { - let l in ...; - - let caller = setup::(0u32); - - }: vest(RawOrigin::Signed(caller)) + let l in 0 .. MAX_LOCKS; - vest_not_locked { - let l in ...; + let caller = account("caller", 0, SEED); + T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + add_locks::(&caller, l as u8); + add_vesting_schedule::(&caller)?; + // At block zero, everything is vested. + System::::set_block_number(T::BlockNumber::zero()); + assert_eq!( + Vesting::::vesting_balance(&caller), + Some(100.into()), + "Vesting schedule not added", + ); + }: vest(RawOrigin::Signed(caller.clone())) + verify { + // Nothing happened since everything is still vested. + assert_eq!( + Vesting::::vesting_balance(&caller), + Some(100.into()), + "Vesting schedule was removed", + ); + } - let caller = setup::(1u32); + vest_unlocked { + let l in 0 .. MAX_LOCKS; - }: vest(RawOrigin::Signed(caller)) + let caller = account("caller", 0, SEED); + T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + add_locks::(&caller, l as u8); + add_vesting_schedule::(&caller)?; + // At block 20, everything is unvested. + System::::set_block_number(20.into()); + assert_eq!( + Vesting::::vesting_balance(&caller), + Some(BalanceOf::::zero()), + "Vesting schedule still active", + ); + }: vest(RawOrigin::Signed(caller.clone())) + verify { + // Vesting schedule is removed! + assert_eq!( + Vesting::::vesting_balance(&caller), + None, + "Vesting schedule was not removed", + ); + } vest_other_locked { - let l in ...; + let l in 0 .. MAX_LOCKS; - let other: T::AccountId = setup::(0u32); + let other: T::AccountId = account("other", 0, SEED); let other_lookup: ::Source = T::Lookup::unlookup(other.clone()); + T::Currency::make_free_balance_be(&other, BalanceOf::::max_value()); + add_locks::(&other, l as u8); + add_vesting_schedule::(&other)?; + // At block zero, everything is vested. + System::::set_block_number(T::BlockNumber::zero()); + assert_eq!( + Vesting::::vesting_balance(&other), + Some(100.into()), + "Vesting schedule not added", + ); - let caller = account("caller", 0, SEED); - - }: vest_other(RawOrigin::Signed(caller), other_lookup) + let caller: T::AccountId = account("caller", 0, SEED); + }: vest_other(RawOrigin::Signed(caller.clone()), other_lookup) + verify { + // Nothing happened since everything is still vested. + assert_eq!( + Vesting::::vesting_balance(&other), + Some(100.into()), + "Vesting schedule was removed", + ); + } - vest_other_not_locked { - let l in ...; + vest_other_unlocked { + let l in 0 .. MAX_LOCKS; - let other: T::AccountId = setup::(1u32); + let other: T::AccountId = account("other", 0, SEED); let other_lookup: ::Source = T::Lookup::unlookup(other.clone()); + T::Currency::make_free_balance_be(&other, BalanceOf::::max_value()); + add_locks::(&other, l as u8); + add_vesting_schedule::(&other)?; + // At block 20, everything is unvested. + System::::set_block_number(20.into()); + assert_eq!( + Vesting::::vesting_balance(&other), + Some(BalanceOf::::zero()), + "Vesting schedule still active", + ); - let caller = account("caller", 0, SEED); - - }: vest_other(RawOrigin::Signed(caller), other_lookup) + let caller: T::AccountId = account("caller", 0, SEED); + }: vest_other(RawOrigin::Signed(caller.clone()), other_lookup) + verify { + // Vesting schedule is removed! + assert_eq!( + Vesting::::vesting_balance(&other), + None, + "Vesting schedule was not removed", + ); + } vested_transfer { - let u in 0 .. 1000; + let l in 0 .. MAX_LOCKS; - let from = account("from", u, SEED); - let to = account("to", u, SEED); - let to_lookup: ::Source = T::Lookup::unlookup(to); + let caller: T::AccountId = account("caller", 0, SEED); + T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + let target: T::AccountId = account("target", 0, SEED); + let target_lookup: ::Source = T::Lookup::unlookup(target.clone()); + // Give target existing locks + add_locks::(&target, l as u8); let transfer_amount = T::MinVestedTransfer::get(); let vesting_schedule = VestingInfo { locked: transfer_amount, - per_block: 1.into(), - starting_block: 0.into(), + per_block: 10.into(), + starting_block: 1.into(), }; + }: _(RawOrigin::Signed(caller), target_lookup, vesting_schedule) + verify { + assert_eq!( + T::MinVestedTransfer::get(), + T::Currency::free_balance(&target), + "Transfer didn't happen", + ); + assert_eq!( + Vesting::::vesting_balance(&target), + Some(T::MinVestedTransfer::get()), + "Lock not created", + ); + } +} - let _ = T::Currency::make_free_balance_be(&from, transfer_amount * 10.into()); - - }: _(RawOrigin::Signed(from), to_lookup, vesting_schedule) +#[cfg(test)] +mod tests { + use super::*; + use crate::tests::{ExtBuilder, Test}; + use frame_support::assert_ok; + + #[test] + fn test_benchmarks() { + ExtBuilder::default().existential_deposit(256).build().execute_with(|| { + assert_ok!(test_benchmark_vest_locked::()); + assert_ok!(test_benchmark_vest_unlocked::()); + assert_ok!(test_benchmark_vest_other_locked::()); + assert_ok!(test_benchmark_vest_other_unlocked::()); + assert_ok!(test_benchmark_vested_transfer::()); + }); + } } diff --git a/frame/vesting/src/lib.rs b/frame/vesting/src/lib.rs index b0c98e78bd6f7243e4c017f133726fccf16407a9..7625cf741785d47d41cf49b29684fd51cd9ebb3b 100644 --- a/frame/vesting/src/lib.rs +++ b/frame/vesting/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Vesting Module //! @@ -50,20 +51,35 @@ use sp_std::prelude::*; use sp_std::fmt::Debug; use codec::{Encode, Decode}; use sp_runtime::{DispatchResult, RuntimeDebug, traits::{ - StaticLookup, Zero, AtLeast32Bit, MaybeSerializeDeserialize, Convert + StaticLookup, Zero, AtLeast32BitUnsigned, MaybeSerializeDeserialize, Convert }}; -use frame_support::{decl_module, decl_event, decl_storage, decl_error, ensure}; +use frame_support::{decl_module, decl_event, decl_storage, decl_error, ensure, weights::Weight}; use frame_support::traits::{ Currency, LockableCurrency, VestingSchedule, WithdrawReason, LockIdentifier, - ExistenceRequirement, Get + ExistenceRequirement, Get, }; -use frame_support::weights::SimpleDispatchInfo; -use frame_system::{self as system, ensure_signed}; +use frame_system::{ensure_signed, ensure_root}; mod benchmarking; type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; +pub trait WeightInfo { + fn vest_locked(l: u32, ) -> Weight; + fn vest_unlocked(l: u32, ) -> Weight; + fn vest_other_locked(l: u32, ) -> Weight; + fn vest_other_unlocked(l: u32, ) -> Weight; + fn vested_transfer(l: u32, ) -> Weight; +} + +impl WeightInfo for () { + fn vest_locked(_l: u32, ) -> Weight { 1_000_000_000 } + fn vest_unlocked(_l: u32, ) -> Weight { 1_000_000_000 } + fn vest_other_locked(_l: u32, ) -> Weight { 1_000_000_000 } + fn vest_other_unlocked(_l: u32, ) -> Weight { 1_000_000_000 } + fn vested_transfer(_l: u32, ) -> Weight { 1_000_000_000 } +} + pub trait Trait: frame_system::Trait { /// The overarching event type. type Event: From> + Into<::Event>; @@ -76,6 +92,9 @@ pub trait Trait: frame_system::Trait { /// The minimum amount transferred to call `vested_transfer`. type MinVestedTransfer: Get>; + + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; } const VESTING_ID: LockIdentifier = *b"vesting "; @@ -92,8 +111,8 @@ pub struct VestingInfo { } impl< - Balance: AtLeast32Bit + Copy, - BlockNumber: AtLeast32Bit + Copy, + Balance: AtLeast32BitUnsigned + Copy, + BlockNumber: AtLeast32BitUnsigned + Copy, > VestingInfo { /// Amount locked at block `n`. pub fn locked_at< @@ -172,7 +191,7 @@ decl_error! { } decl_module! { - // Simple declaration of the `Module` type. Lets the macro know what it's working on. + /// Vesting module declaration. pub struct Module for enum Call where origin: T::Origin { type Error = Error; @@ -190,11 +209,15 @@ decl_module! { /// /// # /// - `O(1)`. - /// - One balance-lock operation. - /// - One storage read (codec `O(1)`) and up to one removal. - /// - One event. + /// - DbWeight: 2 Reads, 2 Writes + /// - Reads: Vesting Storage, Balances Locks, [Sender Account] + /// - Writes: Vesting Storage, Balances Locks, [Sender Account] + /// - Benchmark: + /// - Unlocked: 48.76 + .048 * l µs (min square analysis) + /// - Locked: 44.43 + .284 * l µs (min square analysis) + /// - Using 50 µs fixed. Assuming less than 50 locks on any user, else we may want factor in number of locks. /// # - #[weight = SimpleDispatchInfo::default()] + #[weight = 50_000_000 + T::DbWeight::get().reads_writes(2, 2)] fn vest(origin) -> DispatchResult { let who = ensure_signed(origin)?; Self::update_lock(who) @@ -211,12 +234,15 @@ decl_module! { /// /// # /// - `O(1)`. - /// - Up to one account lookup. - /// - One balance-lock operation. - /// - One storage read (codec `O(1)`) and up to one removal. - /// - One event. + /// - DbWeight: 3 Reads, 3 Writes + /// - Reads: Vesting Storage, Balances Locks, Target Account + /// - Writes: Vesting Storage, Balances Locks, Target Account + /// - Benchmark: + /// - Unlocked: 44.3 + .294 * l µs (min square analysis) + /// - Locked: 48.16 + .103 * l µs (min square analysis) + /// - Using 50 µs fixed. Assuming less than 50 locks on any user, else we may want factor in number of locks. /// # - #[weight = SimpleDispatchInfo::default()] + #[weight = 50_000_000 + T::DbWeight::get().reads_writes(3, 3)] fn vest_other(origin, target: ::Source) -> DispatchResult { ensure_signed(origin)?; Self::update_lock(T::Lookup::lookup(target)?) @@ -233,10 +259,14 @@ decl_module! { /// Emits `VestingCreated`. /// /// # - /// - Creates a new storage entry, but is protected by a minimum transfer - /// amount needed to succeed. + /// - `O(1)`. + /// - DbWeight: 3 Reads, 3 Writes + /// - Reads: Vesting Storage, Balances Locks, Target Account, [Sender Account] + /// - Writes: Vesting Storage, Balances Locks, Target Account, [Sender Account] + /// - Benchmark: 100.3 + .365 * l µs (min square analysis) + /// - Using 100 µs fixed. Assuming less than 50 locks on any user, else we may want factor in number of locks. /// # - #[weight = SimpleDispatchInfo::FixedNormal(1_000_000)] + #[weight = 100_000_000 + T::DbWeight::get().reads_writes(3, 3)] pub fn vested_transfer( origin, target: ::Source, @@ -255,6 +285,47 @@ decl_module! { Ok(()) } + + /// Force a vested transfer. + /// + /// The dispatch origin for this call must be _Root_. + /// + /// - `source`: The account whose funds should be transferred. + /// - `target`: The account that should be transferred the vested funds. + /// - `amount`: The amount of funds to transfer and will be vested. + /// - `schedule`: The vesting schedule attached to the transfer. + /// + /// Emits `VestingCreated`. + /// + /// # + /// - `O(1)`. + /// - DbWeight: 4 Reads, 4 Writes + /// - Reads: Vesting Storage, Balances Locks, Target Account, Source Account + /// - Writes: Vesting Storage, Balances Locks, Target Account, Source Account + /// - Benchmark: 100.3 + .365 * l µs (min square analysis) + /// - Using 100 µs fixed. Assuming less than 50 locks on any user, else we may want factor in number of locks. + /// # + #[weight = 100_000_000 + T::DbWeight::get().reads_writes(4, 4)] + pub fn force_vested_transfer( + origin, + source: ::Source, + target: ::Source, + schedule: VestingInfo, T::BlockNumber>, + ) -> DispatchResult { + ensure_root(origin)?; + ensure!(schedule.locked >= T::MinVestedTransfer::get(), Error::::AmountLow); + + let target = T::Lookup::lookup(target)?; + let source = T::Lookup::lookup(source)?; + ensure!(!Vesting::::contains_key(&target), Error::::ExistingVestingSchedule); + + T::Currency::transfer(&source, &target, schedule.locked, ExistenceRequirement::AllowDeath)?; + + Self::add_vesting_schedule(&target, schedule.locked, schedule.per_block, schedule.starting_block) + .expect("user does not have an existing vesting schedule; q.e.d."); + + Ok(()) + } } } @@ -345,21 +416,17 @@ mod tests { traits::Get }; use sp_core::H256; - // The testing primitives are very useful for avoiding having to work with signatures - // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. use sp_runtime::{ Perbill, testing::Header, - traits::{BlakeTwo256, IdentityLookup, Identity}, + traits::{BlakeTwo256, IdentityLookup, Identity, BadOrigin}, }; + use frame_system::RawOrigin; impl_outer_origin! { pub enum Origin for Test where system = frame_system {} } - // For testing the pallet, we construct most of a mock runtime. This means - // first constructing a configuration type (`Test`) which `impl`s each of the - // configuration traits of pallets we want to use. #[derive(Clone, Eq, PartialEq)] pub struct Test; parameter_types! { @@ -369,6 +436,7 @@ mod tests { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -381,6 +449,10 @@ mod tests { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -388,6 +460,7 @@ mod tests { type AccountData = pallet_balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } impl pallet_balances::Trait for Test { type Balance = u64; @@ -395,6 +468,7 @@ mod tests { type Event = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; + type WeightInfo = (); } parameter_types! { pub const MinVestedTransfer: u64 = 256 * 2; @@ -404,6 +478,7 @@ mod tests { type Currency = Balances; type BlockNumberToBalance = Identity; type MinVestedTransfer = MinVestedTransfer; + type WeightInfo = (); } type System = frame_system::Module; type Balances = pallet_balances::Module; @@ -702,4 +777,94 @@ mod tests { assert_eq!(user4_free_balance, 256 * 40); }); } + + #[test] + fn force_vested_transfer_works() { + ExtBuilder::default() + .existential_deposit(256) + .build() + .execute_with(|| { + let user3_free_balance = Balances::free_balance(&3); + let user4_free_balance = Balances::free_balance(&4); + assert_eq!(user3_free_balance, 256 * 30); + assert_eq!(user4_free_balance, 256 * 40); + // Account 4 should not have any vesting yet. + assert_eq!(Vesting::vesting(&4), None); + // Make the schedule for the new transfer. + let new_vesting_schedule = VestingInfo { + locked: 256 * 5, + per_block: 64, // Vesting over 20 blocks + starting_block: 10, + }; + assert_noop!(Vesting::force_vested_transfer(Some(4).into(), 3, 4, new_vesting_schedule), BadOrigin); + assert_ok!(Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 4, new_vesting_schedule)); + // Now account 4 should have vesting. + assert_eq!(Vesting::vesting(&4), Some(new_vesting_schedule)); + // Ensure the transfer happened correctly. + let user3_free_balance_updated = Balances::free_balance(&3); + assert_eq!(user3_free_balance_updated, 256 * 25); + let user4_free_balance_updated = Balances::free_balance(&4); + assert_eq!(user4_free_balance_updated, 256 * 45); + // Account 4 has 5 * 256 locked. + assert_eq!(Vesting::vesting_balance(&4), Some(256 * 5)); + + System::set_block_number(20); + assert_eq!(System::block_number(), 20); + + // Account 4 has 5 * 64 units vested by block 20. + assert_eq!(Vesting::vesting_balance(&4), Some(10 * 64)); + + System::set_block_number(30); + assert_eq!(System::block_number(), 30); + + // Account 4 has fully vested. + assert_eq!(Vesting::vesting_balance(&4), Some(0)); + }); + } + + #[test] + fn force_vested_transfer_correctly_fails() { + ExtBuilder::default() + .existential_deposit(256) + .build() + .execute_with(|| { + let user2_free_balance = Balances::free_balance(&2); + let user4_free_balance = Balances::free_balance(&4); + assert_eq!(user2_free_balance, 256 * 20); + assert_eq!(user4_free_balance, 256 * 40); + // Account 2 should already have a vesting schedule. + let user2_vesting_schedule = VestingInfo { + locked: 256 * 20, + per_block: 256, // Vesting over 20 blocks + starting_block: 10, + }; + assert_eq!(Vesting::vesting(&2), Some(user2_vesting_schedule)); + + // The vesting schedule we will try to create, fails due to pre-existence of schedule. + let new_vesting_schedule = VestingInfo { + locked: 256 * 5, + per_block: 64, // Vesting over 20 blocks + starting_block: 10, + }; + assert_noop!( + Vesting::force_vested_transfer(RawOrigin::Root.into(), 4, 2, new_vesting_schedule), + Error::::ExistingVestingSchedule, + ); + + // Fails due to too low transfer amount. + let new_vesting_schedule_too_low = VestingInfo { + locked: 256 * 1, + per_block: 64, + starting_block: 10, + }; + assert_noop!( + Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 4, new_vesting_schedule_too_low), + Error::::AmountLow, + ); + + // Verify no currency transfer happened. + assert_eq!(user2_free_balance, 256 * 20); + assert_eq!(user4_free_balance, 256 * 40); + }); + } } diff --git a/primitives/allocator/Cargo.toml b/primitives/allocator/Cargo.toml index 635a3c9128febcd6fd46690ea3e91043d935e70f..ba0aed938723336accd84adce227105dce34b140 100644 --- a/primitives/allocator/Cargo.toml +++ b/primitives/allocator/Cargo.toml @@ -1,18 +1,21 @@ [package] name = "sp-allocator" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Collection of allocator implementations." documentation = "https://docs.rs/sp-allocator" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-std = { version = "2.0.0-alpha.5", path = "../std", default-features = false } -sp-core = { version = "2.0.0-alpha.5", path = "../core", default-features = false } -sp-wasm-interface = { version = "2.0.0-alpha.5", path = "../wasm-interface", default-features = false } +sp-std = { version = "2.0.0-rc4", path = "../std", default-features = false } +sp-core = { version = "2.0.0-rc4", path = "../core", default-features = false } +sp-wasm-interface = { version = "2.0.0-rc4", path = "../wasm-interface", default-features = false } log = { version = "0.4.8", optional = true } derive_more = { version = "0.99.2", optional = true } @@ -25,6 +28,3 @@ std = [ "log", "derive_more", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/allocator/src/error.rs b/primitives/allocator/src/error.rs index 9357bc456003bd440f6067c41e567d1c8ad302b8..7b634af4d5b295e4fd0cc3691778186319bcde75 100644 --- a/primitives/allocator/src/error.rs +++ b/primitives/allocator/src/error.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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. +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. /// The error type used by the allocators. #[derive(sp_core::RuntimeDebug)] diff --git a/primitives/allocator/src/freeing_bump.rs b/primitives/allocator/src/freeing_bump.rs index 0d15ed11f74e0ba6fb22d1d3dde0b35e3e04f2ad..a9cb89c55b5712e805155b0ddf07fcce043b5696 100644 --- a/primitives/allocator/src/freeing_bump.rs +++ b/primitives/allocator/src/freeing_bump.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! This module implements a freeing-bump allocator. //! diff --git a/primitives/allocator/src/lib.rs b/primitives/allocator/src/lib.rs index 0efadbc7f6d60299ee5104600884b3f34692d8e5..b7cfce8048354d8f005af6e9c5d88d480bfa2e92 100644 --- a/primitives/allocator/src/lib.rs +++ b/primitives/allocator/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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. +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Collection of allocator implementations. //! diff --git a/primitives/api/Cargo.toml b/primitives/api/Cargo.toml index fedeeceb3faadfb8e3ec6ff19b7204aa97e6904b..8fe0a6d910bd92973e189a2fe81f6259554f8c81 100644 --- a/primitives/api/Cargo.toml +++ b/primitives/api/Cargo.toml @@ -1,25 +1,28 @@ [package] name = "sp-api" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate runtime api primitives" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -sp-api-proc-macro = { version = "2.0.0-alpha.5", path = "proc-macro" } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../core" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../std" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../runtime" } -sp-version = { version = "2.0.0-alpha.5", default-features = false, path = "../version" } -sp-state-machine = { version = "0.8.0-alpha.5", optional = true, path = "../../primitives/state-machine" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +sp-api-proc-macro = { version = "2.0.0-rc4", path = "proc-macro" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../core" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../std" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../runtime" } +sp-version = { version = "2.0.0-rc4", default-features = false, path = "../version" } +sp-state-machine = { version = "0.8.0-rc4", optional = true, path = "../../primitives/state-machine" } hash-db = { version = "0.15.2", optional = true } [dev-dependencies] -sp-test-primitives = { version = "2.0.0-dev", path = "../test-primitives" } +sp-test-primitives = { version = "2.0.0-rc4", path = "../test-primitives" } [features] default = [ "std" ] @@ -32,6 +35,3 @@ std = [ "sp-version/std", "hash-db", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/api/proc-macro/Cargo.toml b/primitives/api/proc-macro/Cargo.toml index 25c5ae13435a5a107cee146acc2a0661afea8c9f..fb426fde885e27a75657f36d1e84328d1f55fc27 100644 --- a/primitives/api/proc-macro/Cargo.toml +++ b/primitives/api/proc-macro/Cargo.toml @@ -1,14 +1,17 @@ [package] name = "sp-api-proc-macro" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Macros for declaring and implementing runtime apis." documentation = "https://docs.rs/sp-api-proc-macro" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [lib] proc-macro = true @@ -24,6 +27,3 @@ proc-macro-crate = "0.1.4" [features] default = [ "std" ] std = [] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/api/proc-macro/src/decl_runtime_apis.rs b/primitives/api/proc-macro/src/decl_runtime_apis.rs index e9f3087912e26f322214fa22cdbca397a4a2c332..93ec09d0e615b8fa778ee3e786b414f08b2fe04f 100644 --- a/primitives/api/proc-macro/src/decl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/decl_runtime_apis.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::utils::{ generate_crate_access, generate_hidden_includes, generate_runtime_mod_name_for_trait, @@ -190,7 +191,8 @@ fn generate_native_call_generators(decl: &ItemTrait) -> Result { input: &I, error_desc: &'static str, ) -> std::result::Result { - ::decode( + ::decode_with_depth_limit( + #crate_::MAX_EXTRINSIC_DEPTH, &mut &#crate_::Encode::encode(input)[..], ).map_err(|e| format!("{} {}", error_desc, e.what())) } @@ -407,6 +409,7 @@ fn generate_call_api_at_calls(decl: &ItemTrait) -> Result { at: &#crate_::BlockId, args: Vec, changes: &std::cell::RefCell<#crate_::OverlayedChanges>, + offchain_changes: &std::cell::RefCell<#crate_::OffchainOverlayedChanges>, storage_transaction_cache: &std::cell::RefCell< #crate_::StorageTransactionCache >, @@ -436,6 +439,7 @@ fn generate_call_api_at_calls(decl: &ItemTrait) -> Result { native_call: None, arguments: args, overlayed_changes: changes, + offchain_changes, storage_transaction_cache, initialize_block, context, @@ -456,6 +460,7 @@ fn generate_call_api_at_calls(decl: &ItemTrait) -> Result { native_call, arguments: args, overlayed_changes: changes, + offchain_changes, storage_transaction_cache, initialize_block, context, @@ -876,6 +881,53 @@ struct CheckTraitDecl { errors: Vec, } +impl CheckTraitDecl { + /// Check the given trait. + /// + /// All errors will be collected in `self.errors`. + fn check(&mut self, trait_: &ItemTrait) { + self.check_method_declarations(trait_.items.iter().filter_map(|i| match i { + TraitItem::Method(method) => Some(method), + _ => None, + })); + + visit::visit_item_trait(self, trait_); + } + + /// Check that the given method declarations are correct. + /// + /// Any error is stored in `self.errors`. + fn check_method_declarations<'a>(&mut self, methods: impl Iterator) { + let mut method_to_signature_changed = HashMap::>>::new(); + + methods.into_iter().for_each(|method| { + let attributes = remove_supported_attributes(&mut method.attrs.clone()); + + let changed_in = match get_changed_in(&attributes) { + Ok(r) => r, + Err(e) => { self.errors.push(e); return; }, + }; + + method_to_signature_changed + .entry(method.sig.ident.clone()) + .or_default() + .push(changed_in); + }); + + method_to_signature_changed.into_iter().for_each(|(f, changed)| { + // If `changed_in` is `None`, it means it is the current "default" method that calls + // into the latest implementation. + if changed.iter().filter(|c| c.is_none()).count() == 0 { + self.errors.push(Error::new( + f.span(), + "There is no 'default' method with this name (without `changed_in` attribute).\n\ + The 'default' method is used to call into the latest implementation.", + )); + } + }); + } +} + impl<'ast> Visit<'ast> for CheckTraitDecl { fn visit_fn_arg(&mut self, input: &'ast FnArg) { if let FnArg::Receiver(_) = input { @@ -923,7 +975,7 @@ impl<'ast> Visit<'ast> for CheckTraitDecl { /// Check that the trait declarations are in the format we expect. fn check_trait_decls(decls: &[ItemTrait]) -> Result<()> { let mut checker = CheckTraitDecl { errors: Vec::new() }; - decls.iter().for_each(|decl| visit::visit_item_trait(&mut checker, &decl)); + decls.iter().for_each(|decl| checker.check(decl)); if let Some(err) = checker.errors.pop() { Err(checker.errors.into_iter().fold(err, |mut err, other| { diff --git a/primitives/api/proc-macro/src/impl_runtime_apis.rs b/primitives/api/proc-macro/src/impl_runtime_apis.rs index 7def6aa0fb73af3cca94b33ab1bb9ed7d6a8f70e..97b159e6f0791dfef6686355919c1f86bef207f6 100644 --- a/primitives/api/proc-macro/src/impl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/impl_runtime_apis.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::utils::{ generate_crate_access, generate_hidden_includes, @@ -33,7 +34,7 @@ use syn::{ fold::{self, Fold}, parse_quote, }; -use std::{collections::HashSet, iter}; +use std::collections::HashSet; /// Unique identifier used to make the hidden includes unique for this macro. const HIDDEN_INCLUDES_ID: &str = "IMPL_RUNTIME_APIS"; @@ -70,10 +71,8 @@ fn generate_impl_call( let params = extract_parameter_names_types_and_borrows(signature, AllowSelfRefInParameters::No)?; let c = generate_crate_access(HIDDEN_INCLUDES_ID); - let c_iter = iter::repeat(&c); let fn_name = &signature.ident; - let fn_name_str = iter::repeat(fn_name.to_string()); - let input = iter::repeat(input); + let fn_name_str = fn_name.to_string(); let pnames = params.iter().map(|v| &v.0); let pnames2 = params.iter().map(|v| &v.0); let ptypes = params.iter().map(|v| &v.1); @@ -81,12 +80,14 @@ fn generate_impl_call( Ok( quote!( - #( - let #pnames : #ptypes = match #c_iter::Decode::decode(&mut #input) { - Ok(input) => input, + let (#( #pnames ),*) : ( #( #ptypes ),* ) = + match #c::DecodeLimit::decode_all_with_depth_limit( + #c::MAX_EXTRINSIC_DEPTH, + &#input, + ) { + Ok(res) => res, Err(e) => panic!("Bad input data provided to {}: {}", #fn_name_str, e.what()), }; - )* #[allow(deprecated)] <#runtime as #impl_trait>::#fn_name(#( #pborrow #pnames2 ),*) @@ -134,7 +135,7 @@ 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 data = Ident::new("__sp_api__input_data", Span::call_site()); let c = generate_crate_access(HIDDEN_INCLUDES_ID); let impl_calls = generate_impl_calls(impls, &data)? .into_iter() @@ -173,7 +174,7 @@ fn generate_wasm_interface(impls: &[ItemImpl]) -> Result { #( #attrs )* #[cfg(not(feature = "std"))] #[no_mangle] - pub fn #fn_name(input_data: *mut u8, input_len: usize) -> u64 { + pub unsafe fn #fn_name(input_data: *mut u8, input_len: usize) -> u64 { let mut #input = if input_len == 0 { &[0u8; 0] } else { @@ -207,6 +208,7 @@ fn generate_runtime_api_base_structures() -> Result { commit_on_success: std::cell::RefCell, initialized_block: std::cell::RefCell>>, changes: std::cell::RefCell<#crate_::OverlayedChanges>, + offchain_changes: std::cell::RefCell<#crate_::OffchainOverlayedChanges>, storage_transaction_cache: std::cell::RefCell< #crate_::StorageTransactionCache >, @@ -251,17 +253,18 @@ fn generate_runtime_api_base_structures() -> Result { { type StateBackend = C::StateBackend; - fn map_api_result std::result::Result, R, E>( + fn execute_in_transaction #crate_::TransactionOutcome, R>( &self, - map_call: F, - ) -> std::result::Result where Self: Sized { + call: F, + ) -> R where Self: Sized { + self.changes.borrow_mut().start_transaction(); *self.commit_on_success.borrow_mut() = false; - let res = map_call(self); + let res = call(self); *self.commit_on_success.borrow_mut() = true; - self.commit_on_ok(&res); + self.commit_or_rollback(matches!(res, #crate_::TransactionOutcome::Commit(_))); - res + res.into_inner() } fn has_api( @@ -335,6 +338,7 @@ fn generate_runtime_api_base_structures() -> Result { commit_on_success: true.into(), initialized_block: None.into(), changes: Default::default(), + offchain_changes: Default::default(), recorder: Default::default(), storage_transaction_cache: Default::default(), }.into() @@ -353,6 +357,7 @@ fn generate_runtime_api_base_structures() -> Result { &C, &Self, &std::cell::RefCell<#crate_::OverlayedChanges>, + &std::cell::RefCell<#crate_::OffchainOverlayedChanges>, &std::cell::RefCell<#crate_::StorageTransactionCache>, &std::cell::RefCell>>, &Option<#crate_::ProofRecorder>, @@ -362,25 +367,34 @@ fn generate_runtime_api_base_structures() -> Result { &self, call_api_at: F, ) -> std::result::Result<#crate_::NativeOrEncoded, E> { + if *self.commit_on_success.borrow() { + self.changes.borrow_mut().start_transaction(); + } let res = call_api_at( &self.call, self, &self.changes, + &self.offchain_changes, &self.storage_transaction_cache, &self.initialized_block, &self.recorder, ); - self.commit_on_ok(&res); + self.commit_or_rollback(res.is_ok()); res } - fn commit_on_ok(&self, res: &std::result::Result) { + fn commit_or_rollback(&self, commit: bool) { + let proof = "\ + We only close a transaction when we opened one ourself. + Other parts of the runtime that make use of transactions (state-machine) + also balance their transactions. The runtime cannot close client initiated + transactions. qed"; if *self.commit_on_success.borrow() { - if res.is_err() { - self.changes.borrow_mut().discard_prospective(); + if commit { + self.changes.borrow_mut().commit_transaction().expect(proof); } else { - self.changes.borrow_mut().commit_prospective(); + self.changes.borrow_mut().rollback_transaction().expect(proof); } } } @@ -517,6 +531,7 @@ impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> { call_runtime_at, core_api, changes, + offchain_changes, storage_transaction_cache, initialized_block, recorder @@ -527,6 +542,7 @@ impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> { at, params_encoded, changes, + offchain_changes, storage_transaction_cache, initialized_block, params.map(|p| { diff --git a/primitives/api/proc-macro/src/lib.rs b/primitives/api/proc-macro/src/lib.rs index 12f435bd166dff2a579346ff8a710faec6bf89ba..4dd48094683d9fd02dc46f9155260e8e79e43ff8 100644 --- a/primitives/api/proc-macro/src/lib.rs +++ b/primitives/api/proc-macro/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Macros for declaring and implementing runtime apis. diff --git a/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs b/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs index 0767c804a637e2983c52affc97c69f4aea47ce62..0e8f18e3e6f14a403d5a650d10d08d28ab6143a7 100644 --- a/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::utils::{ generate_crate_access, generate_hidden_includes, @@ -72,11 +73,11 @@ fn implement_common_api_traits( impl #crate_::ApiExt<#block_type> for #self_ty { type StateBackend = #crate_::InMemoryBackend<#crate_::HashFor<#block_type>>; - fn map_api_result std::result::Result, R, E>( + fn execute_in_transaction #crate_::TransactionOutcome, R>( &self, - map_call: F, - ) -> std::result::Result where Self: Sized { - map_call(self) + call: F, + ) -> R where Self: Sized { + call(self).into_inner() } fn has_api( diff --git a/primitives/api/proc-macro/src/utils.rs b/primitives/api/proc-macro/src/utils.rs index 1a79cf6c1ef5b5f046ac98229b3f4203f46ce45b..534ddcfddd96e131a6d827c92386fd3aeb5945fe 100644 --- a/primitives/api/proc-macro/src/utils.rs +++ b/primitives/api/proc-macro/src/utils.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use proc_macro2::{TokenStream, Span}; diff --git a/primitives/api/src/lib.rs b/primitives/api/src/lib.rs index 74bcf19a9949e43316001d34b7ccfe3bda2b73cb..bad6c03058322f7f45475c32ccc2260fcef573f6 100644 --- a/primitives/api/src/lib.rs +++ b/primitives/api/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Substrate runtime api //! @@ -27,6 +28,8 @@ //! //! Besides the macros and the [`Core`] runtime api, this crates provides the [`Metadata`] runtime //! api, the [`ApiExt`] trait, the [`CallApiAt`] trait and the [`ConstructRuntimeApi`] trait. +//! +//! On a meta level this implies, the client calls the generated API from the client perspective. #![cfg_attr(not(feature = "std"), no_std)] @@ -44,6 +47,8 @@ pub use sp_core::NativeOrEncoded; #[doc(hidden)] #[cfg(feature = "std")] pub use hash_db::Hasher; +#[cfg(feature = "std")] +pub use sp_core::offchain::storage::OffchainOverlayedChanges; #[doc(hidden)] #[cfg(not(feature = "std"))] pub use sp_core::to_substrate_wasm_fn_return_value; @@ -53,7 +58,7 @@ pub use sp_runtime::{ Block as BlockT, GetNodeBlockType, GetRuntimeBlockType, HashFor, NumberFor, Header as HeaderT, Hash as HashT, }, - generic::BlockId, transaction_validity::TransactionValidity, + generic::BlockId, transaction_validity::TransactionValidity, RuntimeString, TransactionOutcome, }; #[doc(hidden)] pub use sp_core::{offchain, ExecutionContext}; @@ -64,11 +69,14 @@ pub use sp_std::{slice, mem}; #[cfg(feature = "std")] use sp_std::result; #[doc(hidden)] -pub use codec::{Encode, Decode}; +pub use codec::{Encode, Decode, DecodeLimit}; use sp_core::OpaqueMetadata; #[cfg(feature = "std")] use std::{panic::UnwindSafe, cell::RefCell}; +/// Maximum nesting level for extrinsics. +pub const MAX_EXTRINSIC_DEPTH: u32 = 256; + /// Declares given traits as runtime apis. /// /// The macro will create two declarations, one for using on the client side and one for using @@ -113,7 +121,9 @@ use std::{panic::UnwindSafe, cell::RefCell}; /// change is highlighted with the `#[changed_in(2)]` attribute above a method. A method that is /// tagged with this attribute is callable by the name `METHOD_before_version_VERSION`. This /// method will only support calling into wasm, trying to call into native will fail (change the -/// spec version!). Such a method also does not need to be implemented in the runtime. +/// spec version!). Such a method also does not need to be implemented in the runtime. It is +/// required that there exist the "default" of the method without the `#[changed_in(_)]` attribute, +/// this method will be used to call the current default implementation. /// /// ```rust /// sp_api::decl_runtime_apis! { @@ -222,6 +232,7 @@ pub use sp_api_proc_macro::decl_runtime_apis; /// impl_version: 0, /// // Here we are exposing the runtime api versions. /// apis: RUNTIME_API_VERSIONS, +/// transaction_version: 1, /// }; /// /// # fn main() {} @@ -345,15 +356,15 @@ pub trait ApiExt: ApiErrorExt { /// The state backend that is used to store the block states. type StateBackend: StateBackend>; - /// The given closure will be called with api instance. Inside the closure any api call is - /// allowed. After doing the api call, the closure is allowed to map the `Result` to a - /// different `Result` type. This can be important, as the internal data structure that keeps - /// track of modifications to the storage, discards changes when the `Result` is an `Err`. - /// On `Ok`, the structure commits the changes to an internal buffer. - fn map_api_result result::Result, R, E>( + /// Execute the given closure inside a new transaction. + /// + /// Depending on the outcome of the closure, the transaction is committed or rolled-back. + /// + /// The internal result of the closure is returned afterwards. + fn execute_in_transaction TransactionOutcome, R>( &self, - map_call: F, - ) -> result::Result where Self: Sized; + call: F, + ) -> R where Self: Sized; /// Checks if the given api is implemented and versions match. fn has_api( @@ -428,6 +439,8 @@ pub struct CallApiAtParams<'a, Block: BlockT, C, NC, Backend: StateBackend, /// The overlayed changes that are on top of the state. pub overlayed_changes: &'a RefCell, + /// The overlayed changes to be applied to the offchain worker database. + pub offchain_changes: &'a RefCell, /// The cache for storage transactions. pub storage_transaction_cache: &'a RefCell>, /// Determines if the function requires that `initialize_block` should be called before calling @@ -518,13 +531,53 @@ pub trait RuntimeApiInfo { #[cfg(feature = "std")] pub type ApiErrorFor = <>::Api as ApiErrorExt>::Error; +#[derive(codec::Encode, codec::Decode)] +pub struct OldRuntimeVersion { + pub spec_name: RuntimeString, + pub impl_name: RuntimeString, + pub authoring_version: u32, + pub spec_version: u32, + pub impl_version: u32, + pub apis: ApisVec, +} + +impl From for RuntimeVersion { + fn from(x: OldRuntimeVersion) -> Self { + Self { + spec_name: x.spec_name, + impl_name: x.impl_name, + authoring_version: x.authoring_version, + spec_version: x.spec_version, + impl_version: x.impl_version, + apis: x.apis, + transaction_version: 1, + } + } +} + +impl From for OldRuntimeVersion { + fn from(x: RuntimeVersion) -> Self { + Self { + spec_name: x.spec_name, + impl_name: x.impl_name, + authoring_version: x.authoring_version, + spec_version: x.spec_version, + impl_version: x.impl_version, + apis: x.apis, + } + } +} + decl_runtime_apis! { /// The `Core` runtime api that every Substrate runtime needs to implement. #[core_trait] - #[api_version(2)] + #[api_version(3)] pub trait Core { /// Returns the version of the runtime. fn version() -> RuntimeVersion; + /// Returns the version of the runtime. + #[changed_in(3)] + fn version() -> OldRuntimeVersion; /// Execute the given block. #[skip_initialize_block] fn execute_block(block: Block); diff --git a/primitives/api/test/Cargo.toml b/primitives/api/test/Cargo.toml index f2e66afc24abbac9f4c5604701d6b6f558bf3b4d..cf8f0ce47e17de4a5a32e316312d1c5fde1a0e4c 100644 --- a/primitives/api/test/Cargo.toml +++ b/primitives/api/test/Cargo.toml @@ -1,30 +1,33 @@ [package] name = "sp-api-test" -version = "2.0.0-dev" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" publish = false homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-api = { version = "2.0.0-alpha.5", path = "../" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../../test-utils/runtime/client" } -sp-version = { version = "2.0.0-alpha.5", path = "../../version" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../runtime" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../blockchain" } -sp-consensus = { version = "0.8.0-alpha.5", path = "../../../primitives/consensus/common" } -sc-block-builder = { version = "0.8.0-alpha.5", path = "../../../client/block-builder" } -codec = { package = "parity-scale-codec", version = "1.3.0" } -sp-state-machine = { version = "0.8.0-alpha.5", path = "../../../primitives/state-machine" } +sp-api = { version = "2.0.0-rc4", path = "../" } +substrate-test-runtime-client = { version = "2.0.0-rc4", path = "../../../test-utils/runtime/client" } +sp-version = { version = "2.0.0-rc4", path = "../../version" } +sp-runtime = { version = "2.0.0-rc4", path = "../../runtime" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../blockchain" } +sp-consensus = { version = "0.8.0-rc4", path = "../../../primitives/consensus/common" } +sc-block-builder = { version = "0.8.0-rc4", path = "../../../client/block-builder" } +codec = { package = "parity-scale-codec", version = "1.3.1" } +sp-state-machine = { version = "0.8.0-rc4", path = "../../../primitives/state-machine" } trybuild = "1.0.17" rustversion = "1.0.0" [dev-dependencies] criterion = "0.3.0" -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../../test-utils/runtime/client" } -sp-core = { version = "2.0.0-alpha.5", path = "../../core" } +substrate-test-runtime-client = { version = "2.0.0-rc4", path = "../../../test-utils/runtime/client" } +sp-core = { version = "2.0.0-rc4", path = "../../core" } [[bench]] name = "bench" @@ -34,6 +37,3 @@ harness = false [features] default = [ "std" ] std = [] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/api/test/benches/bench.rs b/primitives/api/test/benches/bench.rs index 9a90ca6e38b8501c4e7286d7919f56613d539df1..280b7079028735c897d0e5db517f41da2de0c0ef 100644 --- a/primitives/api/test/benches/bench.rs +++ b/primitives/api/test/benches/bench.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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. +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use criterion::{Criterion, criterion_group, criterion_main}; use substrate_test_runtime_client::{ diff --git a/primitives/api/test/tests/decl_and_impl.rs b/primitives/api/test/tests/decl_and_impl.rs index a09bd0412c8afe9f15deb078a3f338dd0937ac59..f16f0bbe71c562640fb5b89203433a795f811b33 100644 --- a/primitives/api/test/tests/decl_and_impl.rs +++ b/primitives/api/test/tests/decl_and_impl.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use sp_api::{ RuntimeApiInfo, decl_runtime_apis, impl_runtime_apis, mock_impl_runtime_apis, @@ -112,7 +113,7 @@ mock_impl_runtime_apis! { } } -type TestClient = substrate_test_runtime_client::sc_client::Client< +type TestClient = substrate_test_runtime_client::client::Client< substrate_test_runtime_client::Backend, substrate_test_runtime_client::Executor, Block, diff --git a/primitives/api/test/tests/runtime_calls.rs b/primitives/api/test/tests/runtime_calls.rs index a907ac80957200d8135ee50e3782420c134a3411..6717ab7a3bb92756275cee2928e2799b9d00ee94 100644 --- a/primitives/api/test/tests/runtime_calls.rs +++ b/primitives/api/test/tests/runtime_calls.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use sp_api::ProvideRuntimeApi; use substrate_test_runtime_client::{ @@ -206,3 +207,14 @@ fn record_proof_works() { &runtime_code, ).expect("Executes block while using the proof backend"); } + +#[test] +fn call_runtime_api_with_multiple_arguments() { + let client = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::Both).build(); + + let data = vec![1, 2, 4, 5, 6, 7, 8, 8, 10, 12]; + let block_id = BlockId::Number(client.chain_info().best_number); + client.runtime_api() + .test_multiple_arguments(&block_id, data.clone(), data.clone(), data.len() as u32) + .unwrap(); +} diff --git a/primitives/api/test/tests/trybuild.rs b/primitives/api/test/tests/trybuild.rs index 910771f9389691d61b1c84069fdf6090e242f80b..2f7fd6d06bcd34c3724d6fa39422d4f7890392cc 100644 --- a/primitives/api/test/tests/trybuild.rs +++ b/primitives/api/test/tests/trybuild.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use std::env; diff --git a/primitives/api/test/tests/ui/changed_in_no_default_method.rs b/primitives/api/test/tests/ui/changed_in_no_default_method.rs new file mode 100644 index 0000000000000000000000000000000000000000..6af183a4cde910248575e93ca57e437a24950fbf --- /dev/null +++ b/primitives/api/test/tests/ui/changed_in_no_default_method.rs @@ -0,0 +1,19 @@ +use sp_runtime::traits::GetNodeBlockType; +use substrate_test_runtime_client::runtime::Block; + +/// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType` +/// trait are done by the `construct_runtime!` macro in a real runtime. +struct Runtime {} +impl GetNodeBlockType for Runtime { + type NodeBlock = Block; +} + +sp_api::decl_runtime_apis! { + #[api_version(2)] + pub trait Api { + #[changed_in(2)] + fn test(data: u64); + } +} + +fn main() {} diff --git a/primitives/api/test/tests/ui/changed_in_no_default_method.stderr b/primitives/api/test/tests/ui/changed_in_no_default_method.stderr new file mode 100644 index 0000000000000000000000000000000000000000..ed4c0f9088573e78211f6e9560fc781e24936c02 --- /dev/null +++ b/primitives/api/test/tests/ui/changed_in_no_default_method.stderr @@ -0,0 +1,6 @@ +error: There is no 'default' method with this name (without `changed_in` attribute). +The 'default' method is used to call into the latest implementation. + --> $DIR/changed_in_no_default_method.rs:15:6 + | +15 | fn test(data: u64); + | ^^^^ diff --git a/primitives/api/test/tests/ui/declaring_old_block.rs b/primitives/api/test/tests/ui/declaring_old_block.rs index ba98bf9bf688317b4a8d6dd940b61112fba82485..fb741590282249c692af3b9233f59a95fa3b0b5b 100644 --- a/primitives/api/test/tests/ui/declaring_old_block.rs +++ b/primitives/api/test/tests/ui/declaring_old_block.rs @@ -1,5 +1,3 @@ -use sp_runtime::traits::Block as BlockT; - sp_api::decl_runtime_apis! { pub trait Api { fn test(); diff --git a/primitives/api/test/tests/ui/declaring_old_block.stderr b/primitives/api/test/tests/ui/declaring_old_block.stderr index 448dc38594321e5b7f11c0ccfeb4f4d6e6414862..50dd37582c603d5d355472e2003b1813d18ecb67 100644 --- a/primitives/api/test/tests/ui/declaring_old_block.stderr +++ b/primitives/api/test/tests/ui/declaring_old_block.stderr @@ -1,19 +1,11 @@ error: `Block: BlockT` generic parameter will be added automatically by the `decl_runtime_apis!` macro! If you try to use a different trait than the substrate `Block` trait, please rename it locally. - --> $DIR/declaring_old_block.rs:4:23 + --> $DIR/declaring_old_block.rs:2:23 | -4 | pub trait Api { +2 | pub trait Api { | ^^^^^^ error: `Block: BlockT` generic parameter will be added automatically by the `decl_runtime_apis!` macro! - --> $DIR/declaring_old_block.rs:4:16 + --> $DIR/declaring_old_block.rs:2:16 | -4 | pub trait Api { +2 | pub trait Api { | ^^^^^ - -warning: unused import: `sp_runtime::traits::Block as BlockT` - --> $DIR/declaring_old_block.rs:1:5 - | -1 | use sp_runtime::traits::Block as BlockT; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default diff --git a/primitives/api/test/tests/ui/declaring_own_block_with_different_name.rs b/primitives/api/test/tests/ui/declaring_own_block_with_different_name.rs index 67bb9cab10502cc7ef33fe9106d95221547a9a99..e3c7ae8a39ab748557c5d160f35e24dfcd0a353d 100644 --- a/primitives/api/test/tests/ui/declaring_own_block_with_different_name.rs +++ b/primitives/api/test/tests/ui/declaring_own_block_with_different_name.rs @@ -1,5 +1,3 @@ -use sp_runtime::traits::Block as BlockT; - sp_api::decl_runtime_apis! { pub trait Api { fn test(); diff --git a/primitives/api/test/tests/ui/declaring_own_block_with_different_name.stderr b/primitives/api/test/tests/ui/declaring_own_block_with_different_name.stderr index fe445b822dd88a25e340beb75fc834a5ff85febf..778de3c9d15f7ff9caf94b858182af78ff260bd1 100644 --- a/primitives/api/test/tests/ui/declaring_own_block_with_different_name.stderr +++ b/primitives/api/test/tests/ui/declaring_own_block_with_different_name.stderr @@ -1,13 +1,5 @@ error: `Block: BlockT` generic parameter will be added automatically by the `decl_runtime_apis!` macro! If you try to use a different trait than the substrate `Block` trait, please rename it locally. - --> $DIR/declaring_own_block_with_different_name.rs:4:19 + --> $DIR/declaring_own_block_with_different_name.rs:2:19 | -4 | pub trait Api { +2 | pub trait Api { | ^^^^^^ - -warning: unused import: `sp_runtime::traits::Block as BlockT` - --> $DIR/declaring_own_block_with_different_name.rs:1:5 - | -1 | use sp_runtime::traits::Block as BlockT; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default diff --git a/primitives/api/test/tests/ui/empty_impl_runtime_apis_call.stderr b/primitives/api/test/tests/ui/empty_impl_runtime_apis_call.stderr index f927912879ad037b448c24d3193679432a43d9f0..b08f056b57d1cde69d57a5cf9e2337c46a70cbe5 100644 --- a/primitives/api/test/tests/ui/empty_impl_runtime_apis_call.stderr +++ b/primitives/api/test/tests/ui/empty_impl_runtime_apis_call.stderr @@ -2,4 +2,6 @@ error: No api implementation given! --> $DIR/empty_impl_runtime_apis_call.rs:17:1 | 17 | sp_api::impl_runtime_apis! {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/primitives/api/test/tests/ui/impl_incorrect_method_signature.stderr b/primitives/api/test/tests/ui/impl_incorrect_method_signature.stderr index 4f112e91bb7a9c45eec3692e7c4dc3c9f8fc2790..46f138fccd5ecdd1c57c7e24d6ccacd1bf7472dc 100644 --- a/primitives/api/test/tests/ui/impl_incorrect_method_signature.stderr +++ b/primitives/api/test/tests/ui/impl_incorrect_method_signature.stderr @@ -21,20 +21,11 @@ error[E0053]: method `Api_test_runtime_api_impl` has an incompatible type for tr | |_- type in trait 16 | 17 | sp_api::impl_runtime_apis! { - | -^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | _expected `u64`, found struct `std::string::String` - | | -18 | | impl self::Api for Runtime { -19 | | fn test(data: String) {} -20 | | } -... | -32 | | } -33 | | } - | |_- in this macro invocation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found struct `std::string::String` | = note: expected fn pointer `fn(&RuntimeApiImpl<__SR_API_BLOCK__, RuntimeApiImplCall>, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId<__SR_API_BLOCK__>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option, std::vec::Vec<_>) -> std::result::Result<_, _>` found fn pointer `fn(&RuntimeApiImpl<__SR_API_BLOCK__, RuntimeApiImplCall>, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId<__SR_API_BLOCK__>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option, std::vec::Vec<_>) -> std::result::Result<_, _>` + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types --> $DIR/impl_incorrect_method_signature.rs:17:1 @@ -46,10 +37,9 @@ error[E0308]: mismatched types ... | 32 | | } 33 | | } - | | ^ - | | | - | |_expected `u64`, found struct `std::string::String` - | in this macro invocation + | |_^ expected `u64`, found struct `std::string::String` + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types --> $DIR/impl_incorrect_method_signature.rs:19:11 diff --git a/primitives/api/test/tests/ui/impl_two_traits_with_same_name.rs b/primitives/api/test/tests/ui/impl_two_traits_with_same_name.rs index 2122a6991ae5a9c6f38a0a9de9abdcc05b0641ca..76555a825dc8415c591455398ad931d43d6d7d5f 100644 --- a/primitives/api/test/tests/ui/impl_two_traits_with_same_name.rs +++ b/primitives/api/test/tests/ui/impl_two_traits_with_same_name.rs @@ -15,8 +15,6 @@ sp_api::decl_runtime_apis! { } mod second { - use super::*; - sp_api::decl_runtime_apis! { pub trait Api { fn test2(data: u64); diff --git a/primitives/api/test/tests/ui/impl_two_traits_with_same_name.stderr b/primitives/api/test/tests/ui/impl_two_traits_with_same_name.stderr index 24ee66f84b314d345dd7b5d86638293b140eedb1..17ee56d409a66e34fcaec32af8644385fe5ef520 100644 --- a/primitives/api/test/tests/ui/impl_two_traits_with_same_name.stderr +++ b/primitives/api/test/tests/ui/impl_two_traits_with_same_name.stderr @@ -1,13 +1,5 @@ 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:32:15 + --> $DIR/impl_two_traits_with_same_name.rs:30:15 | -32 | impl second::Api for Runtime { +30 | impl second::Api for Runtime { | ^^^ - -warning: unused import: `super::*` - --> $DIR/impl_two_traits_with_same_name.rs:18:6 - | -18 | use super::*; - | ^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default diff --git a/primitives/api/test/tests/ui/mock_only_one_block_type.rs b/primitives/api/test/tests/ui/mock_only_one_block_type.rs index 969b21d7378d75b6b2bb28c1ca118aa041015784..f49cafd23a00122bd53976c0656e0779f3d3fb5d 100644 --- a/primitives/api/test/tests/ui/mock_only_one_block_type.rs +++ b/primitives/api/test/tests/ui/mock_only_one_block_type.rs @@ -1,5 +1,3 @@ -use substrate_test_runtime_client::runtime::Block; - struct Block2; sp_api::decl_runtime_apis! { diff --git a/primitives/api/test/tests/ui/mock_only_one_block_type.stderr b/primitives/api/test/tests/ui/mock_only_one_block_type.stderr index 1abc8db726a160e151cb47abf6b745d5630b1851..1831d0485b473a3d33ca1bafce6c2fa67f6b78a2 100644 --- a/primitives/api/test/tests/ui/mock_only_one_block_type.stderr +++ b/primitives/api/test/tests/ui/mock_only_one_block_type.stderr @@ -1,19 +1,11 @@ error: Block type should be the same between all runtime apis. - --> $DIR/mock_only_one_block_type.rs:22:12 + --> $DIR/mock_only_one_block_type.rs:20:12 | -22 | impl Api2 for MockApi { +20 | impl Api2 for MockApi { | ^^^^^^ error: First block type found here - --> $DIR/mock_only_one_block_type.rs:18:11 + --> $DIR/mock_only_one_block_type.rs:16:11 | -18 | impl Api for MockApi { +16 | impl Api for MockApi { | ^^^^^ - -warning: unused import: `substrate_test_runtime_client::runtime::Block` - --> $DIR/mock_only_one_block_type.rs:1:5 - | -1 | use substrate_test_runtime_client::runtime::Block; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default diff --git a/primitives/api/test/tests/ui/mock_only_one_error_type.stderr b/primitives/api/test/tests/ui/mock_only_one_error_type.stderr index 8f026838c96b8db0e503179c745b3a76f4a2c181..65d05e83a7f69149947a4628b98224976a9e2659 100644 --- a/primitives/api/test/tests/ui/mock_only_one_error_type.stderr +++ b/primitives/api/test/tests/ui/mock_only_one_error_type.stderr @@ -5,23 +5,26 @@ error: Error type can not change between runtime apis | ^^^^ error[E0277]: the trait bound `u32: std::convert::From` is not satisfied - --> $DIR/mock_only_one_error_type.rs:15:1 - | -15 | / sp_api::mock_impl_runtime_apis! { -16 | | impl Api for MockApi { -17 | | type Error = u32; -18 | | -... | -26 | | } -27 | | } - | | ^ - | | | - | |_the trait `std::convert::From` is not implemented for `u32` - | in this macro invocation - | - = help: the following implementations were found: - > - > - > - > - and 16 others + --> $DIR/mock_only_one_error_type.rs:15:1 + | +15 | / sp_api::mock_impl_runtime_apis! { +16 | | impl Api for MockApi { +17 | | type Error = u32; +18 | | +... | +26 | | } +27 | | } + | |_^ the trait `std::convert::From` is not implemented for `u32` + | + ::: $WORKSPACE/primitives/api/src/lib.rs:350:35 + | +350 | type Error: std::fmt::Debug + From; + | ------------ required by this bound in `sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ApiErrorExt` + | + = help: the following implementations were found: + > + > + > + > + and 18 others + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/primitives/api/test/tests/ui/mock_only_one_self_type.rs b/primitives/api/test/tests/ui/mock_only_one_self_type.rs index 4b29ec2a6ab07e7a08689549423e03687501543d..617031b4d5f1a1f37c974ed8d826f43e49003233 100644 --- a/primitives/api/test/tests/ui/mock_only_one_self_type.rs +++ b/primitives/api/test/tests/ui/mock_only_one_self_type.rs @@ -1,5 +1,3 @@ -use substrate_test_runtime_client::runtime::Block; - sp_api::decl_runtime_apis! { pub trait Api { fn test(data: u64); diff --git a/primitives/api/test/tests/ui/mock_only_one_self_type.stderr b/primitives/api/test/tests/ui/mock_only_one_self_type.stderr index 996d1d44c044c151bc5e57e93e83d3749e86a80c..5f1e29b281c8504d39a355028882099b40298810 100644 --- a/primitives/api/test/tests/ui/mock_only_one_self_type.stderr +++ b/primitives/api/test/tests/ui/mock_only_one_self_type.stderr @@ -1,19 +1,11 @@ error: Self type should not change between runtime apis - --> $DIR/mock_only_one_self_type.rs:21:23 + --> $DIR/mock_only_one_self_type.rs:19:23 | -21 | impl Api2 for MockApi2 { +19 | impl Api2 for MockApi2 { | ^^^^^^^^ error: First self type found here - --> $DIR/mock_only_one_self_type.rs:17:22 + --> $DIR/mock_only_one_self_type.rs:15:22 | -17 | impl Api for MockApi { +15 | impl Api for MockApi { | ^^^^^^^ - -warning: unused import: `substrate_test_runtime_client::runtime::Block` - --> $DIR/mock_only_one_self_type.rs:1:5 - | -1 | use substrate_test_runtime_client::runtime::Block; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default diff --git a/primitives/api/test/tests/ui/mock_only_self_reference.stderr b/primitives/api/test/tests/ui/mock_only_self_reference.stderr index 9c1658b0a6cea1260b082eee7afea6d2521c66ac..6d1ac0e9a25636bb2645037c5925b092422ad3d1 100644 --- a/primitives/api/test/tests/ui/mock_only_self_reference.stderr +++ b/primitives/api/test/tests/ui/mock_only_self_reference.stderr @@ -22,20 +22,11 @@ error[E0053]: method `Api_test_runtime_api_impl` has an incompatible type for tr | |_- type in trait ... 12 | sp_api::mock_impl_runtime_apis! { - | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | _expected `u64`, found `()` - | | -13 | | impl Api for MockApi { -14 | | fn test(self, data: u64) {} -15 | | -16 | | fn test2(&mut self, data: u64) {} -17 | | } -18 | | } - | |_- in this macro invocation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found `()` | = note: expected fn pointer `fn(&MockApi, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId, substrate_test_runtime::Extrinsic>>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option, std::vec::Vec<_>) -> std::result::Result<_, _>` found fn pointer `fn(&MockApi, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId, substrate_test_runtime::Extrinsic>>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option<()>, std::vec::Vec<_>) -> std::result::Result<_, _>` + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0053]: method `Api_test2_runtime_api_impl` has an incompatible type for trait --> $DIR/mock_only_self_reference.rs:12:1 @@ -49,17 +40,8 @@ error[E0053]: method `Api_test2_runtime_api_impl` has an incompatible type for t | |_- type in trait ... 12 | sp_api::mock_impl_runtime_apis! { - | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | _expected `u64`, found `()` - | | -13 | | impl Api for MockApi { -14 | | fn test(self, data: u64) {} -15 | | -16 | | fn test2(&mut self, data: u64) {} -17 | | } -18 | | } - | |_- in this macro invocation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found `()` | = note: expected fn pointer `fn(&MockApi, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId, substrate_test_runtime::Extrinsic>>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option, std::vec::Vec<_>) -> std::result::Result<_, _>` found fn pointer `fn(&MockApi, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId, substrate_test_runtime::Extrinsic>>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option<()>, std::vec::Vec<_>) -> std::result::Result<_, _>` + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr b/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr index 1d7d0a78a86df87ac01b1d30a757a5a0695e265e..cc2a5f05cd5ffea8251c8b280eae656ddf550d4f 100644 --- a/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr +++ b/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr @@ -21,20 +21,11 @@ error[E0053]: method `Api_test_runtime_api_impl` has an incompatible type for tr | |_- type in trait 16 | 17 | sp_api::impl_runtime_apis! { - | -^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | _expected `u64`, found `&u64` - | | -18 | | impl self::Api for Runtime { -19 | | fn test(data: &u64) { -20 | | unimplemented!() -... | -34 | | } -35 | | } - | |_- in this macro invocation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found `&u64` | = note: expected fn pointer `fn(&RuntimeApiImpl<__SR_API_BLOCK__, RuntimeApiImplCall>, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId<__SR_API_BLOCK__>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option, std::vec::Vec<_>) -> std::result::Result<_, _>` found fn pointer `fn(&RuntimeApiImpl<__SR_API_BLOCK__, RuntimeApiImplCall>, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId<__SR_API_BLOCK__>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option<&u64>, std::vec::Vec<_>) -> std::result::Result<_, _>` + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types --> $DIR/type_reference_in_impl_runtime_apis_call.rs:17:1 @@ -46,10 +37,9 @@ error[E0308]: mismatched types ... | 34 | | } 35 | | } - | | ^ - | | | - | |_expected `u64`, found `&u64` - | in this macro invocation + | |_^ expected `u64`, found `&u64` + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types --> $DIR/type_reference_in_impl_runtime_apis_call.rs:19:11 diff --git a/primitives/application-crypto/Cargo.toml b/primitives/application-crypto/Cargo.toml index 7c3fb5357997ffa2e7470c5aaf94cca168594fc8..8e9c9225091dda4cad054f4b241b5bc167149efc 100644 --- a/primitives/application-crypto/Cargo.toml +++ b/primitives/application-crypto/Cargo.toml @@ -1,21 +1,24 @@ [package] name = "sp-application-crypto" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" description = "Provides facilities for generating application specific crypto wrapper types." -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" documentation = "https://docs.rs/sp-application-crypto" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../core" } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../core" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } serde = { version = "1.0.101", optional = true, features = ["derive"] } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../std" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/io" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../std" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } [features] default = [ "std" ] @@ -31,6 +34,3 @@ full_crypto = [ "sp-io/disable_panic_handler", "sp-io/disable_oom", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/application-crypto/src/ecdsa.rs b/primitives/application-crypto/src/ecdsa.rs new file mode 100644 index 0000000000000000000000000000000000000000..287ac8f3afcff000b5de63223e8c1157b8794d4d --- /dev/null +++ b/primitives/application-crypto/src/ecdsa.rs @@ -0,0 +1,61 @@ +// Copyright 2019-2020 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 . + +//! Ecdsa crypto types. + +use crate::{RuntimePublic, KeyTypeId}; + +use sp_std::vec::Vec; + +pub use sp_core::ecdsa::*; + +mod app { + use sp_core::testing::ECDSA; + + crate::app_crypto!(super, ECDSA); + + impl crate::traits::BoundToRuntimeAppPublic for Public { + type Public = Self; + } +} + +pub use app::{Public as AppPublic, Signature as AppSignature}; +#[cfg(feature = "full_crypto")] +pub use app::Pair as AppPair; + +impl RuntimePublic for Public { + type Signature = Signature; + + fn all(key_type: KeyTypeId) -> crate::Vec { + sp_io::crypto::ecdsa_public_keys(key_type) + } + + fn generate_pair(key_type: KeyTypeId, seed: Option>) -> Self { + sp_io::crypto::ecdsa_generate(key_type, seed) + } + + fn sign>(&self, key_type: KeyTypeId, msg: &M) -> Option { + sp_io::crypto::ecdsa_sign(key_type, self, msg.as_ref()) + } + + fn verify>(&self, msg: &M, signature: &Self::Signature) -> bool { + sp_io::crypto::ecdsa_verify(&signature, msg.as_ref(), self) + } + + fn to_raw_vec(&self) -> Vec { + sp_core::crypto::Public::to_raw_vec(self) + } +} diff --git a/primitives/application-crypto/src/ed25519.rs b/primitives/application-crypto/src/ed25519.rs index 5be79ff4f7985a54e9eb0c34fb3552f3cf062bb1..e761745cf5425a9a51d1499b5c10e5b849aabae1 100644 --- a/primitives/application-crypto/src/ed25519.rs +++ b/primitives/application-crypto/src/ed25519.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Ed25519 crypto types. @@ -23,27 +24,13 @@ use sp_std::vec::Vec; pub use sp_core::ed25519::*; mod app { - use sp_core::crypto::{CryptoTypePublicPair, Public as TraitPublic}; use sp_core::testing::ED25519; - use sp_core::ed25519::CRYPTO_ID; crate::app_crypto!(super, ED25519); impl crate::traits::BoundToRuntimeAppPublic for Public { type Public = Self; } - - impl From for CryptoTypePublicPair { - fn from(key: Public) -> Self { - (&key).into() - } - } - - impl From<&Public> for CryptoTypePublicPair { - fn from(key: &Public) -> Self { - CryptoTypePublicPair(CRYPTO_ID, key.to_raw_vec()) - } - } } pub use app::{Public as AppPublic, Signature as AppSignature}; diff --git a/primitives/application-crypto/src/lib.rs b/primitives/application-crypto/src/lib.rs index 07e2b45106ee9690c841a5d842eebdc4325afd59..6b5cf8857fb5b754dd27613089e275c4f03ed50f 100644 --- a/primitives/application-crypto/src/lib.rs +++ b/primitives/application-crypto/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Traits and macros for constructing application specific strongly typed crypto wrappers. @@ -25,7 +26,7 @@ pub use sp_core::{self, crypto::{CryptoType, CryptoTypePublicPair, Public, Deriv #[doc(hidden)] #[cfg(feature = "full_crypto")] pub use sp_core::crypto::{SecretStringError, DeriveJunction, Ss58Codec, Pair}; -pub use sp_core::crypto::{CryptoTypeId, KeyTypeId, key_types}; +pub use sp_core::crypto::{KeyTypeId, CryptoTypeId, key_types}; #[doc(hidden)] pub use codec; @@ -33,10 +34,15 @@ pub use codec; #[cfg(feature = "std")] pub use serde; #[doc(hidden)] -pub use sp_std::{ops::Deref, vec::Vec}; +pub use sp_std::{ + convert::TryFrom, + ops::Deref, + vec::Vec, +}; pub mod ed25519; pub mod sr25519; +pub mod ecdsa; mod traits; pub use traits::*; @@ -54,11 +60,11 @@ pub use traits::*; #[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_public_full_crypto!($module::Public, $key_type, $module::CRYPTO_ID); + $crate::app_crypto_public_common!($module::Public, $module::Signature, $key_type, $module::CRYPTO_ID); + $crate::app_crypto_signature_full_crypto!($module::Signature, $key_type, $module::CRYPTO_ID); $crate::app_crypto_signature_common!($module::Signature, $key_type); - $crate::app_crypto_pair!($module::Pair, $key_type); + $crate::app_crypto_pair!($module::Pair, $key_type, $module::CRYPTO_ID); }; } @@ -75,9 +81,9 @@ macro_rules! app_crypto { #[macro_export] macro_rules! app_crypto { ($module:ident, $key_type:expr) => { - $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_public_not_full_crypto!($module::Public, $key_type, $module::CRYPTO_ID); + $crate::app_crypto_public_common!($module::Public, $module::Signature, $key_type, $module::CRYPTO_ID); + $crate::app_crypto_signature_not_full_crypto!($module::Signature, $key_type, $module::CRYPTO_ID); $crate::app_crypto_signature_common!($module::Signature, $key_type); }; } @@ -86,7 +92,7 @@ macro_rules! app_crypto { /// Application-specific type whose identifier is `$key_type`. #[macro_export] macro_rules! app_crypto_pair { - ($pair:ty, $key_type:expr) => { + ($pair:ty, $key_type:expr, $crypto_type:expr) => { $crate::wrap!{ /// A generic `AppPublic` wrapper type over $pair crypto; this has no specific App. #[derive(Clone)] @@ -103,17 +109,8 @@ macro_rules! app_crypto_pair { 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> - { - <$pair>::from_phrase(phrase, password).map(|r| (Self(r.0), r.1)) - } + $crate::app_crypto_pair_functions_if_std!($pair); + fn derive< Iter: Iterator >(&self, path: Iter, seed: Option) -> Result<(Self, Option), Self::DeriveError> { @@ -150,6 +147,7 @@ macro_rules! app_crypto_pair { type Pair = Pair; type Signature = Signature; const ID: $crate::KeyTypeId = $key_type; + const CRYPTO_ID: $crate::CryptoTypeId = $crypto_type; } impl $crate::AppPair for Pair { @@ -158,13 +156,41 @@ macro_rules! app_crypto_pair { }; } +/// Implements functions for the `Pair` trait when `feature = "std"` is enabled. +#[doc(hidden)] +#[cfg(feature = "std")] +#[macro_export] +macro_rules! app_crypto_pair_functions_if_std { + ($pair:ty) => { + 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) + } + + fn from_phrase(phrase: &str, password: Option<&str>) + -> Result<(Self, Self::Seed), $crate::SecretStringError> + { + <$pair>::from_phrase(phrase, password).map(|r| (Self(r.0), r.1)) + } + } +} + +#[doc(hidden)] +#[cfg(not(feature = "std"))] +#[macro_export] +macro_rules! app_crypto_pair_functions_if_std { + ($pair:ty) => {} +} + + /// 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. +#[doc(hidden)] #[macro_export] macro_rules! app_crypto_public_full_crypto { - ($public:ty, $key_type:expr) => { + ($public:ty, $key_type:expr, $crypto_type:expr) => { $crate::wrap!{ /// A generic `AppPublic` wrapper type over $public crypto; this has no specific App. #[derive( @@ -187,6 +213,7 @@ macro_rules! app_crypto_public_full_crypto { type Pair = Pair; type Signature = Signature; const ID: $crate::KeyTypeId = $key_type; + const CRYPTO_ID: $crate::CryptoTypeId = $crypto_type; } } } @@ -195,9 +222,10 @@ macro_rules! app_crypto_public_full_crypto { /// 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. +#[doc(hidden)] #[macro_export] macro_rules! app_crypto_public_not_full_crypto { - ($public:ty, $key_type:expr) => { + ($public:ty, $key_type:expr, $crypto_type:expr) => { $crate::wrap!{ /// A generic `AppPublic` wrapper type over $public crypto; this has no specific App. #[derive( @@ -216,6 +244,7 @@ macro_rules! app_crypto_public_not_full_crypto { type Public = Public; type Signature = Signature; const ID: $crate::KeyTypeId = $key_type; + const CRYPTO_ID: $crate::CryptoTypeId = $crypto_type; } } } @@ -223,44 +252,11 @@ macro_rules! app_crypto_public_not_full_crypto { /// 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. +#[doc(hidden)] #[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, - path: Iter - ) -> Option { - self.0.derive(path).map(Self) - } - } - - #[cfg(feature = "std")] - impl std::fmt::Display for Public { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - use $crate::Ss58Codec; - write!(f, "{}", self.0.to_ss58check()) - } - } - #[cfg(feature = "std")] - impl $crate::serde::Serialize for Public { - fn serialize(&self, serializer: S) -> std::result::Result where - S: $crate::serde::Serializer - { - use $crate::Ss58Codec; - serializer.serialize_str(&self.to_ss58check()) - } - } - #[cfg(feature = "std")] - impl<'de> $crate::serde::Deserialize<'de> for Public { - fn deserialize(deserializer: D) -> std::result::Result where - D: $crate::serde::Deserializer<'de> - { - use $crate::Ss58Codec; - Public::from_ss58check(&String::deserialize(deserializer)?) - .map_err(|e| $crate::serde::de::Error::custom(format!("{:?}", e))) - } - } + ($public:ty, $sig:ty, $key_type:expr, $crypto_type:expr) => { + $crate::app_crypto_public_common_if_std!(); impl AsRef<[u8]> for Public { fn as_ref(&self) -> &[u8] { self.0.as_ref() } @@ -272,6 +268,10 @@ macro_rules! app_crypto_public_common { impl $crate::Public for Public { fn from_slice(x: &[u8]) -> Self { Self(<$public>::from_slice(x)) } + + fn to_public_crypto_pair(&self) -> $crate::CryptoTypePublicPair { + $crate::CryptoTypePublicPair($crypto_type, self.to_raw_vec()) + } } impl $crate::AppPublic for Public { @@ -280,6 +280,8 @@ macro_rules! app_crypto_public_common { impl $crate::RuntimeAppPublic for Public where $public: $crate::RuntimePublic { const ID: $crate::KeyTypeId = $key_type; + const CRYPTO_ID: $crate::CryptoTypeId = $crypto_type; + type Signature = Signature; fn all() -> $crate::Vec { @@ -306,16 +308,84 @@ macro_rules! app_crypto_public_common { <$public as $crate::RuntimePublic>::to_raw_vec(&self.0) } } + + impl From for $crate::CryptoTypePublicPair { + fn from(key: Public) -> Self { + (&key).into() + } + } + + impl From<&Public> for $crate::CryptoTypePublicPair { + fn from(key: &Public) -> Self { + $crate::CryptoTypePublicPair( + $crypto_type, + $crate::Public::to_raw_vec(key), + ) + } + } + } +} + +/// Implements traits for the public key type if `feature = "std"` is enabled. +#[cfg(feature = "std")] +#[doc(hidden)] +#[macro_export] +macro_rules! app_crypto_public_common_if_std { + () => { + impl $crate::Derive for Public { + fn derive>(&self, + path: Iter + ) -> Option { + self.0.derive(path).map(Self) + } + } + + impl std::fmt::Display for Public { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + use $crate::Ss58Codec; + write!(f, "{}", self.0.to_ss58check()) + } + } + + impl $crate::serde::Serialize for Public { + fn serialize(&self, serializer: S) -> std::result::Result where + S: $crate::serde::Serializer + { + use $crate::Ss58Codec; + serializer.serialize_str(&self.to_ss58check()) + } + } + + impl<'de> $crate::serde::Deserialize<'de> for Public { + fn deserialize(deserializer: D) -> std::result::Result where + D: $crate::serde::Deserializer<'de> + { + use $crate::Ss58Codec; + Public::from_ss58check(&String::deserialize(deserializer)?) + .map_err(|e| $crate::serde::de::Error::custom(format!("{:?}", e))) + } + } } } +#[cfg(not(feature = "std"))] +#[doc(hidden)] +#[macro_export] +macro_rules! app_crypto_public_common_if_std { + () => { + impl $crate::Derive for Public {} + } +} + + /// 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. +#[doc(hidden)] #[macro_export] macro_rules! app_crypto_signature_full_crypto { - ($sig:ty, $key_type:expr) => { + ($sig:ty, $key_type:expr, $crypto_type:expr) => { $crate::wrap! { /// A generic `AppPublic` wrapper type over $public crypto; this has no specific App. #[derive(Clone, Default, Eq, PartialEq, @@ -337,6 +407,7 @@ macro_rules! app_crypto_signature_full_crypto { type Pair = Pair; type Signature = Signature; const ID: $crate::KeyTypeId = $key_type; + const CRYPTO_ID: $crate::CryptoTypeId = $crypto_type; } } } @@ -345,9 +416,10 @@ macro_rules! app_crypto_signature_full_crypto { /// 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. +#[doc(hidden)] #[macro_export] macro_rules! app_crypto_signature_not_full_crypto { - ($sig:ty, $key_type:expr) => { + ($sig:ty, $key_type:expr, $crypto_type:expr) => { $crate::wrap! { /// A generic `AppPublic` wrapper type over $public crypto; this has no specific App. #[derive(Clone, Default, Eq, PartialEq, @@ -365,6 +437,7 @@ macro_rules! app_crypto_signature_not_full_crypto { type Public = Public; type Signature = Signature; const ID: $crate::KeyTypeId = $key_type; + const CRYPTO_ID: $crate::CryptoTypeId = $crypto_type; } } } @@ -372,6 +445,7 @@ macro_rules! app_crypto_signature_not_full_crypto { /// 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. +#[doc(hidden)] #[macro_export] macro_rules! app_crypto_signature_common { ($sig:ty, $key_type:expr) => { @@ -388,6 +462,14 @@ macro_rules! app_crypto_signature_common { impl $crate::AppSignature for Signature { type Generic = $sig; } + + impl $crate::TryFrom<$crate::Vec> for Signature { + type Error = (); + + fn try_from(data: $crate::Vec) -> Result { + Ok(<$sig>::try_from(data.as_slice())?.into()) + } + } } } diff --git a/primitives/application-crypto/src/sr25519.rs b/primitives/application-crypto/src/sr25519.rs index a0f2cef1c4e45b6150be335ac271e3dd592febbe..4700e0f756717345ca68e1c320bdf185f4a6fa47 100644 --- a/primitives/application-crypto/src/sr25519.rs +++ b/primitives/application-crypto/src/sr25519.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Sr25519 crypto types. @@ -23,27 +24,13 @@ use sp_std::vec::Vec; pub use sp_core::sr25519::*; mod app { - use sp_core::crypto::{CryptoTypePublicPair, Public as TraitPublic}; use sp_core::testing::SR25519; - use sp_core::sr25519::CRYPTO_ID; crate::app_crypto!(super, SR25519); impl crate::traits::BoundToRuntimeAppPublic for Public { type Public = Self; } - - impl From for CryptoTypePublicPair { - fn from(key: Public) -> Self { - (&key).into() - } - } - - impl From<&Public> for CryptoTypePublicPair { - fn from(key: &Public) -> Self { - CryptoTypePublicPair(CRYPTO_ID, key.to_raw_vec()) - } - } } pub use app::{Public as AppPublic, Signature as AppSignature}; diff --git a/primitives/application-crypto/src/traits.rs b/primitives/application-crypto/src/traits.rs index 2af039a88df4c3734fbce447072ebcd051ebcc41..f06e194aefddf07a5ee377508b21f55ccd785156 100644 --- a/primitives/application-crypto/src/traits.rs +++ b/primitives/application-crypto/src/traits.rs @@ -1,24 +1,25 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #[cfg(feature = "full_crypto")] use sp_core::crypto::Pair; use codec::Codec; -use sp_core::crypto::{KeyTypeId, CryptoType, IsWrappedBy, Public}; +use sp_core::crypto::{KeyTypeId, CryptoType, CryptoTypeId, IsWrappedBy, Public}; use sp_std::{fmt::Debug, vec::Vec}; /// An application-specific key. @@ -38,6 +39,8 @@ pub trait AppKey: 'static + Send + Sync + Sized + CryptoType + Clone { /// An identifier for this application-specific key type. const ID: KeyTypeId; + /// The identifier of the crypto type of this application-specific key type. + const CRYPTO_ID: CryptoTypeId; } /// Type which implements Hash in std, not when no-std (std variant). @@ -115,6 +118,8 @@ pub trait RuntimePublic: Sized { pub trait RuntimeAppPublic: Sized { /// An identifier for this application-specific key type. const ID: KeyTypeId; + /// The identifier of the crypto type of this application-specific key type. + const CRYPTO_ID: CryptoTypeId; /// The signature that will be generated when signing with the corresponding private key. type Signature: Codec + Debug + MaybeHash + Eq + PartialEq + Clone; diff --git a/primitives/application-crypto/test/Cargo.toml b/primitives/application-crypto/test/Cargo.toml index d34840b4eb5206429fbf829f60c2e11187b838f4..d3b336d92a6a7947ea87031b89cd63ac884824ce 100644 --- a/primitives/application-crypto/test/Cargo.toml +++ b/primitives/application-crypto/test/Cargo.toml @@ -1,20 +1,20 @@ [package] name = "sp-application-crypto-test" -version = "2.0.0-dev" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" description = "Integration tests for application-crypto" -license = "GPL-3.0" +license = "Apache-2.0" publish = false homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" -[dependencies] -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../core" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../../test-utils/runtime/client" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../runtime" } -sp-api = { version = "2.0.0-alpha.5", path = "../../api" } -sp-application-crypto = { version = "2.0.0-alpha.5", path = "../" } - [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../core" } +substrate-test-runtime-client = { version = "2.0.0-rc4", path = "../../../test-utils/runtime/client" } +sp-runtime = { version = "2.0.0-rc4", path = "../../runtime" } +sp-api = { version = "2.0.0-rc4", path = "../../api" } +sp-application-crypto = { version = "2.0.0-rc4", path = "../" } diff --git a/primitives/application-crypto/test/src/ecdsa.rs b/primitives/application-crypto/test/src/ecdsa.rs new file mode 100644 index 0000000000000000000000000000000000000000..9b5619b7c123e28ebc41559c69e52588f1e5ce76 --- /dev/null +++ b/primitives/application-crypto/test/src/ecdsa.rs @@ -0,0 +1,42 @@ +// Copyright 2019-2020 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 . + +//! Integration tests for ecdsa + +use sp_runtime::generic::BlockId; +use sp_core::{ + crypto::Pair, + testing::{KeyStore, ECDSA}, +}; +use substrate_test_runtime_client::{ + TestClientBuilder, DefaultTestClientBuilderExt, TestClientBuilderExt, + runtime::TestAPI, +}; +use sp_api::ProvideRuntimeApi; +use sp_application_crypto::ecdsa::{AppPair, AppPublic}; + +#[test] +fn ecdsa_works_in_runtime() { + let keystore = KeyStore::new(); + let test_client = TestClientBuilder::new().set_keystore(keystore.clone()).build(); + let (signature, public) = test_client.runtime_api() + .test_ecdsa_crypto(&BlockId::Number(0)) + .expect("Tests `ecdsa` crypto."); + + let supported_keys = keystore.read().keys(ECDSA).unwrap(); + assert!(supported_keys.contains(&public.clone().into())); + assert!(AppPair::verify(&signature, "ecdsa", &AppPublic::from(public))); +} diff --git a/primitives/application-crypto/test/src/ed25519.rs b/primitives/application-crypto/test/src/ed25519.rs index 1d72962829a53309ed4146a5f8657820ba15b697..ecdaabc30f10c06be086d3896080ee66a18cfc57 100644 --- a/primitives/application-crypto/test/src/ed25519.rs +++ b/primitives/application-crypto/test/src/ed25519.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Integration tests for ed25519 diff --git a/primitives/application-crypto/test/src/lib.rs b/primitives/application-crypto/test/src/lib.rs index cb045e81a7871c5b72003266656f17a346cc17bd..b78539239691adb9baa606c780d903eecec47265 100644 --- a/primitives/application-crypto/test/src/lib.rs +++ b/primitives/application-crypto/test/src/lib.rs @@ -1,22 +1,25 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Integration tests for application crypto #[cfg(test)] mod ed25519; #[cfg(test)] -mod sr25519; \ No newline at end of file +mod sr25519; +#[cfg(test)] +mod ecdsa; diff --git a/primitives/application-crypto/test/src/sr25519.rs b/primitives/application-crypto/test/src/sr25519.rs index f2c7c48b2bc91c0329ecaad7541be5f13f3f754c..55aaf1eac43b25aa8215b9bf7fc6dad4c45ba8d7 100644 --- a/primitives/application-crypto/test/src/sr25519.rs +++ b/primitives/application-crypto/test/src/sr25519.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Integration tests for sr25519 diff --git a/primitives/arithmetic/Cargo.toml b/primitives/arithmetic/Cargo.toml index 208525f6c193bdca2b9b5f9ba4a566999d523544..c3bef60d1a13541ffc25f028f9be29b5ca8ac668 100644 --- a/primitives/arithmetic/Cargo.toml +++ b/primitives/arithmetic/Cargo.toml @@ -1,27 +1,31 @@ [package] name = "sp-arithmetic" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Minimal fixed point arithmetic primitives and types for runtime." documentation = "https://docs.rs/sp-arithmetic" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } integer-sqrt = "0.1.2" num-traits = { version = "0.2.8", default-features = false } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../std" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../std" } serde = { version = "1.0.101", optional = true, features = ["derive"] } -sp-debug-derive = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/debug-derive" } +sp-debug-derive = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/debug-derive" } [dev-dependencies] -primitive-types = "0.7.0" rand = "0.7.2" criterion = "0.3" +serde_json = "1.0" +primitive-types = "0.7.0" [features] default = ["std"] @@ -36,6 +40,3 @@ std = [ [[bench]] name = "bench" harness = false - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/arithmetic/benches/bench.rs b/primitives/arithmetic/benches/bench.rs index 1dbcf260affc33cd6962ebd64dd58d8636e581ad..7a576c8af144bdd3e18b0c71236cbbeb13e9960e 100644 --- a/primitives/arithmetic/benches/bench.rs +++ b/primitives/arithmetic/benches/bench.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use criterion::{Criterion, Throughput, BenchmarkId, criterion_group, criterion_main}; use sp_arithmetic::biguint::{BigUint, Single}; diff --git a/primitives/arithmetic/fuzzer/Cargo.lock b/primitives/arithmetic/fuzzer/Cargo.lock deleted file mode 100644 index 3a4187437ae7312ec7016cb9e41638a018cfcbbf..0000000000000000000000000000000000000000 --- a/primitives/arithmetic/fuzzer/Cargo.lock +++ /dev/null @@ -1,401 +0,0 @@ -# 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" -checksum = "64cf76cb6e2222ed0ea86b2b0ee2f71c96ec6edd5af42e84d59160e91b836ec4" - -[[package]] -name = "arrayvec" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" - -[[package]] -name = "autocfg" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" - -[[package]] -name = "bitvec" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993f74b4c99c1908d156b8d2e0fb6277736b0ecbd833982fd1241d39b2766a6" - -[[package]] -name = "byte-slice-cast" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0a5e3906bcbf133e33c1d4d95afc664ad37fbdb9f6568d8043e7ea8c27d93d3" - -[[package]] -name = "byteorder" -version = "1.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" - -[[package]] -name = "c2-chacha" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" -dependencies = [ - "ppv-lite86", -] - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "fixed-hash" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3367952ceb191f4ab95dd5685dc163ac539e36202f9fcfd0cb22f9f9c542fefc" -dependencies = [ - "byteorder", - "rand", - "rustc-hex", - "static_assertions", -] - -[[package]] -name = "getrandom" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "honggfuzz" -version = "0.5.45" -dependencies = [ - "arbitrary", - "lazy_static", - "memmap", -] - -[[package]] -name = "impl-codec" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1be51a921b067b0eaca2fad532d9400041561aa922221cc65f95a85641c6bf53" -dependencies = [ - "parity-scale-codec", -] - -[[package]] -name = "integer-sqrt" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f65877bf7d44897a473350b1046277941cee20b263397e90869c50b6e766088b" - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.67" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018" - -[[package]] -name = "memmap" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "num-bigint" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-integer" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" -dependencies = [ - "autocfg", -] - -[[package]] -name = "parity-scale-codec" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f509c5e67ca0605ee17dcd3f91ef41cadd685c75a298fb6261b781a5acb3f910" -dependencies = [ - "arrayvec", - "bitvec", - "byte-slice-cast", - "parity-scale-codec-derive", - "serde", -] - -[[package]] -name = "parity-scale-codec-derive" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a0ec292e92e8ec7c58e576adacc1e3f399c597c8f263c42f18420abe58e7245" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" - -[[package]] -name = "primitive-types" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4336f4f5d5524fa60bcbd6fe626f9223d8142a50e7053e979acdf0da41ab975" -dependencies = [ - "fixed-hash", - "impl-codec", - "uint", -] - -[[package]] -name = "proc-macro-crate" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10d4b51f154c8a7fb96fd6dad097cb74b863943ec010ac94b9fd1be8861fe1e" -dependencies = [ - "toml", -] - -[[package]] -name = "proc-macro2" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quote" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom", - "libc", - "rand_chacha", - "rand_core", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" -dependencies = [ - "c2-chacha", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rustc-hex" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" - -[[package]] -name = "serde" -version = "1.0.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "sp-arithmetic" -version = "2.0.0-alpha.3" -dependencies = [ - "integer-sqrt", - "num-traits", - "parity-scale-codec", - "serde", - "sp-debug-derive", - "sp-std", -] - -[[package]] -name = "sp-arithmetic-fuzzer" -version = "2.0.0" -dependencies = [ - "honggfuzz", - "num-bigint", - "num-traits", - "primitive-types", - "sp-arithmetic", -] - -[[package]] -name = "sp-debug-derive" -version = "2.0.0-alpha.3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "sp-std" -version = "2.0.0-alpha.3" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "syn" -version = "1.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "toml" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" -dependencies = [ - "serde", -] - -[[package]] -name = "uint" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e75a4cdd7b87b28840dba13c483b9a88ee6bbf16ba5c951ee1ecfcf723078e0d" -dependencies = [ - "byteorder", - "crunchy", - "rustc-hex", - "static_assertions", -] - -[[package]] -name = "unicode-xid" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "winapi" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/primitives/arithmetic/fuzzer/Cargo.toml b/primitives/arithmetic/fuzzer/Cargo.toml index 26b5f8c27b5085fd615dce5af70939e994c76767..c7e5485a19fb5eeb3dab9d7a21ea2ff5fb20e6c4 100644 --- a/primitives/arithmetic/fuzzer/Cargo.toml +++ b/primitives/arithmetic/fuzzer/Cargo.toml @@ -1,17 +1,21 @@ [package] name = "sp-arithmetic-fuzzer" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Fuzzer for fixed point arithmetic primitives." documentation = "https://docs.rs/sp-arithmetic-fuzzer" +publish = false + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-arithmetic = { version = "2.0.0-alpha.5", path = ".." } -honggfuzz = "0.5" +sp-arithmetic = { version = "2.0.0-rc4", path = ".." } +honggfuzz = "0.5.49" primitive-types = "0.7.0" num-bigint = "0.2" num-traits = "0.2" @@ -20,6 +24,10 @@ num-traits = "0.2" name = "biguint" path = "src/biguint.rs" +[[bin]] +name = "normalize" +path = "src/normalize.rs" + [[bin]] name = "per_thing_rational" path = "src/per_thing_rational.rs" @@ -28,5 +36,6 @@ path = "src/per_thing_rational.rs" name = "rational128" path = "src/rational128.rs" -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +[[bin]] +name = "fixed_point" +path = "src/fixed_point.rs" diff --git a/primitives/arithmetic/fuzzer/src/biguint.rs b/primitives/arithmetic/fuzzer/src/biguint.rs index f217b080d25fa80c5c2199efb1440add203e9f06..0966c128954a7e4984ad2f168a46cc295b6077ef 100644 --- a/primitives/arithmetic/fuzzer/src/biguint.rs +++ b/primitives/arithmetic/fuzzer/src/biguint.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Running //! Running this fuzzer can be done with `cargo hfuzz run biguint`. `honggfuzz` CLI options can diff --git a/primitives/arithmetic/fuzzer/src/fixed_point.rs b/primitives/arithmetic/fuzzer/src/fixed_point.rs new file mode 100644 index 0000000000000000000000000000000000000000..9a88197ac32adfbd1ada4ecc1a85805dc291cd91 --- /dev/null +++ b/primitives/arithmetic/fuzzer/src/fixed_point.rs @@ -0,0 +1,82 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! # Running +//! Running this fuzzer can be done with `cargo hfuzz run fixed_point`. `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 fixed_point hfuzz_workspace/fixed_point/*.fuzz`. +//! +//! # More information +//! More information about `honggfuzz` can be found +//! [here](https://docs.rs/honggfuzz/). + +use honggfuzz::fuzz; +use sp_arithmetic::{FixedPointNumber, FixedI64, traits::Saturating}; + +fn main() { + loop { + fuzz!(|data: (i32, i32)| { + let x: i128 = data.0.into(); + let y: i128 = data.1.into(); + + // Check `from_rational` and division are consistent. + if y != 0 { + let f1 = FixedI64::saturating_from_integer(x) / FixedI64::saturating_from_integer(y); + let f2 = FixedI64::saturating_from_rational(x, y); + assert_eq!(f1.into_inner(), f2.into_inner()); + } + + // Check `saturating_mul`. + let a = FixedI64::saturating_from_rational(2, 5); + let b = a.saturating_mul(FixedI64::saturating_from_integer(x)); + let n = b.into_inner() as i128; + let m = 2i128 * x * FixedI64::accuracy() as i128 / 5i128; + assert_eq!(n, m); + + // Check `saturating_mul` and division are inverse. + if x != 0 { + assert_eq!(a, b / FixedI64::saturating_from_integer(x)); + } + + // Check `reciprocal`. + let r = a.reciprocal().unwrap().reciprocal().unwrap(); + assert_eq!(a, r); + + // Check addition. + let a = FixedI64::saturating_from_integer(x); + let b = FixedI64::saturating_from_integer(y); + let c = FixedI64::saturating_from_integer(x.saturating_add(y)); + assert_eq!(a.saturating_add(b), c); + + // Check substraction. + let a = FixedI64::saturating_from_integer(x); + let b = FixedI64::saturating_from_integer(y); + let c = FixedI64::saturating_from_integer(x.saturating_sub(y)); + assert_eq!(a.saturating_sub(b), c); + + // Check `saturating_mul_acc_int`. + let a = FixedI64::saturating_from_rational(2, 5); + let b = a.saturating_mul_acc_int(x); + let xx = FixedI64::saturating_from_integer(x); + let d = a.saturating_mul(xx).saturating_add(xx).into_inner() as i128 / FixedI64::accuracy() as i128; + assert_eq!(b, d); + }); + } +} diff --git a/primitives/arithmetic/fuzzer/src/normalize.rs b/primitives/arithmetic/fuzzer/src/normalize.rs new file mode 100644 index 0000000000000000000000000000000000000000..34c4ef9cb0ab51e125c4a9a2a2535d8770a8b342 --- /dev/null +++ b/primitives/arithmetic/fuzzer/src/normalize.rs @@ -0,0 +1,62 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +//! # Running +//! Running this fuzzer can be done with `cargo hfuzz run normalize`. `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 normalize hfuzz_workspace/normalize/*.fuzz`. + +use honggfuzz::fuzz; +use sp_arithmetic::Normalizable; +use std::convert::TryInto; + +fn main() { + let sum_limit = u32::max_value() as u128; + let len_limit: usize = u32::max_value().try_into().unwrap(); + + loop { + fuzz!(|data: (Vec, u32)| { + let (data, norm) = data; + if data.len() == 0 { return; } + let pre_sum: u128 = data.iter().map(|x| *x as u128).sum(); + + let normalized = data.normalize(norm); + // error cases. + if pre_sum > sum_limit || data.len() > len_limit { + assert!(normalized.is_err()) + } else { + if let Ok(normalized) = normalized { + // if sum goes beyond u128, panic. + let sum: u128 = normalized.iter().map(|x| *x as u128).sum(); + + // if this function returns Ok(), then it will ALWAYS be accurate. + assert_eq!( + sum, + norm as u128, + "sums don't match {:?}, {}", + normalized, + norm, + ); + } + } + }) + } +} diff --git a/primitives/arithmetic/fuzzer/src/per_thing_rational.rs b/primitives/arithmetic/fuzzer/src/per_thing_rational.rs index c2dda3de2299cb713114a856c6eafbedf2d91be2..fc22eacc9e499fc6a75489e6830f42d63f09f163 100644 --- a/primitives/arithmetic/fuzzer/src/per_thing_rational.rs +++ b/primitives/arithmetic/fuzzer/src/per_thing_rational.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Running //! Running this fuzzer can be done with `cargo hfuzz run per_thing_rational`. `honggfuzz` CLI options can @@ -113,7 +114,7 @@ fn main() { } } -fn assert_per_thing_equal_error(a: T, b: T, err: u128) { +fn assert_per_thing_equal_error(a: P, b: P, err: u128) { let a_abs = a.deconstruct().saturated_into::(); let b_abs = b.deconstruct().saturated_into::(); let diff = a_abs.max(b_abs) - a_abs.min(b_abs); diff --git a/primitives/arithmetic/fuzzer/src/rational128.rs b/primitives/arithmetic/fuzzer/src/rational128.rs index 586a165272244bc0ab8ee7a7ec5c5813de9b0a0e..7a33e46991aa1ed38ba581d2b594b9bf1f161be4 100644 --- a/primitives/arithmetic/fuzzer/src/rational128.rs +++ b/primitives/arithmetic/fuzzer/src/rational128.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! # Running //! Running this fuzzer can be done with `cargo hfuzz run rational128`. `honggfuzz` CLI options can diff --git a/primitives/arithmetic/src/biguint.rs b/primitives/arithmetic/src/biguint.rs index 6c3ca58a52d1f72c21fa548adcb5728e03be0ddf..41e2c759a59679a25eda9d42655eee83559cd4b4 100644 --- a/primitives/arithmetic/src/biguint.rs +++ b/primitives/arithmetic/src/biguint.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Infinite precision unsigned integer for substrate runtime. @@ -150,7 +151,7 @@ impl BigUint { // 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); + let index = self.digits.iter().position(|&elem| elem != 0).unwrap_or(self.len() - 1); if index > 0 { self.digits = self.digits[index..].to_vec() @@ -580,19 +581,19 @@ pub mod tests { fn strip_works() { let mut a = BigUint::from_limbs(&[0, 1, 0]); a.lstrip(); - assert_eq!(a, BigUint { digits: vec![1, 0] }); + assert_eq!(a.digits, vec![1, 0]); let mut a = BigUint::from_limbs(&[0, 0, 1]); a.lstrip(); - assert_eq!(a, BigUint { digits: vec![1] }); + assert_eq!(a.digits, vec![1]); let mut a = BigUint::from_limbs(&[0, 0]); a.lstrip(); - assert_eq!(a, BigUint { digits: vec![0] }); + assert_eq!(a.digits, vec![0]); let mut a = BigUint::from_limbs(&[0, 0, 0]); a.lstrip(); - assert_eq!(a, BigUint { digits: vec![0] }); + assert_eq!(a.digits, vec![0]); } #[test] diff --git a/primitives/arithmetic/src/fixed64.rs b/primitives/arithmetic/src/fixed64.rs deleted file mode 100644 index 6b399b6aa5106d3889c1152c8cb1e7fc38a14585..0000000000000000000000000000000000000000 --- a/primitives/arithmetic/src/fixed64.rs +++ /dev/null @@ -1,332 +0,0 @@ -// Copyright 2019-2020 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 sp_std::{ - ops, prelude::*, - convert::{TryFrom, TryInto}, -}; -use codec::{Encode, Decode}; -use crate::{ - Perbill, - traits::{ - SaturatedConversion, CheckedSub, CheckedAdd, CheckedDiv, 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)) - } - - fn saturating_pow(self, exp: usize) -> Self { - Self(self.0.saturating_pow(exp as u32)) - } -} - -/// 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) - } -} - -/// Note that this is a standard, _potentially-panicking_, implementation. Use `CheckedDiv` trait -/// for safe division. -impl ops::Div for Fixed64 { - type Output = Self; - - fn div(self, rhs: Self) -> Self::Output { - if rhs.0 == 0 { - let zero = 0; - return Fixed64::from_parts( self.0 / zero); - } - let (n, d) = if rhs.0 < 0 { - (-self.0, rhs.0.abs() as u64) - } else { - (self.0, rhs.0 as u64) - }; - Fixed64::from_rational(n, d) - } -} - -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 CheckedDiv for Fixed64 { - fn checked_div(&self, rhs: &Self) -> Option { - if rhs.0 == 0 { - None - } else { - Some(*self / *rhs) - } - } -} - -impl sp_std::fmt::Debug for Fixed64 { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - write!(f, "Fixed64({},{})", self.0 / DIV, (self.0 % DIV) / 1000) - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::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); - } - - #[test] - fn div_works() { - let a = Fixed64::from_rational(12, 10); - let b = Fixed64::from_rational(10, 1); - assert_eq!(a / b, Fixed64::from_rational(12, 100)); - - let a = Fixed64::from_rational(12, 10); - let b = Fixed64::from_rational(1, 100); - assert_eq!(a / b, Fixed64::from_rational(120, 1)); - - let a = Fixed64::from_rational(12, 100); - let b = Fixed64::from_rational(10, 1); - assert_eq!(a / b, Fixed64::from_rational(12, 1000)); - - let a = Fixed64::from_rational(12, 100); - let b = Fixed64::from_rational(1, 100); - assert_eq!(a / b, Fixed64::from_rational(12, 1)); - - let a = Fixed64::from_rational(-12, 10); - let b = Fixed64::from_rational(10, 1); - assert_eq!(a / b, Fixed64::from_rational(-12, 100)); - - let a = Fixed64::from_rational(12, 10); - let b = Fixed64::from_rational(-10, 1); - assert_eq!(a / b, Fixed64::from_rational(-12, 100)); - - let a = Fixed64::from_rational(-12, 10); - let b = Fixed64::from_rational(-10, 1); - assert_eq!(a / b, Fixed64::from_rational(12, 100)); - } - - #[test] - #[should_panic(expected = "attempt to divide by zero")] - fn div_zero() { - let a = Fixed64::from_rational(12, 10); - let b = Fixed64::from_natural(0); - let _ = a / b; - } - - #[test] - fn checked_div_zero() { - let a = Fixed64::from_rational(12, 10); - let b = Fixed64::from_natural(0); - assert_eq!(a.checked_div(&b), None); - } - - #[test] - fn checked_div_non_zero() { - let a = Fixed64::from_rational(12, 10); - let b = Fixed64::from_rational(1, 100); - assert_eq!(a.checked_div(&b), Some(Fixed64::from_rational(120, 1))); - } -} diff --git a/primitives/arithmetic/src/fixed_point.rs b/primitives/arithmetic/src/fixed_point.rs new file mode 100644 index 0000000000000000000000000000000000000000..8653ee2c8f7c8cb743dae10082c547fde14873db --- /dev/null +++ b/primitives/arithmetic/src/fixed_point.rs @@ -0,0 +1,1622 @@ +// Copyright 2020 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 . + +//! Decimal Fixed Point implementations for Substrate runtime. + +use sp_std::{ops::{self, Add, Sub, Mul, Div}, fmt::Debug, prelude::*, convert::{TryInto, TryFrom}}; +use codec::{Encode, Decode}; +use crate::{ + helpers_128bit::multiply_by_rational, PerThing, + traits::{ + SaturatedConversion, CheckedSub, CheckedAdd, CheckedMul, CheckedDiv, CheckedNeg, + Bounded, Saturating, UniqueSaturatedInto, Zero, One + }, +}; + +#[cfg(feature = "std")] +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + +/// Integer types that can be used to interact with `FixedPointNumber` implementations. +pub trait FixedPointOperand: Copy + Clone + Bounded + Zero + Saturating + + PartialOrd + UniqueSaturatedInto + TryFrom + CheckedNeg {} + +impl FixedPointOperand for i128 {} +impl FixedPointOperand for u128 {} +impl FixedPointOperand for i64 {} +impl FixedPointOperand for u64 {} +impl FixedPointOperand for i32 {} +impl FixedPointOperand for u32 {} +impl FixedPointOperand for i16 {} +impl FixedPointOperand for u16 {} +impl FixedPointOperand for i8 {} +impl FixedPointOperand for u8 {} + +/// Something that implements a decimal fixed point number. +/// +/// The precision is given by `Self::DIV`, i.e. `1 / DIV` can be represented. +/// +/// Each type can store numbers from `Self::Inner::min_value() / Self::DIV` +/// to `Self::Inner::max_value() / Self::DIV`. +/// This is also referred to as the _accuracy_ of the type in the documentation. +pub trait FixedPointNumber: + Sized + Copy + Default + Debug + + Saturating + Bounded + + Eq + PartialEq + Ord + PartialOrd + + CheckedSub + CheckedAdd + CheckedMul + CheckedDiv + + Add + Sub + Div + Mul +{ + /// The underlying data type used for this fixed point number. + type Inner: Debug + One + CheckedMul + CheckedDiv + FixedPointOperand; + + /// Precision of this fixed point implementation. It should be a power of `10`. + const DIV: Self::Inner; + + /// Indicates if this fixed point implementation is signed or not. + const SIGNED: bool; + + /// Precision of this fixed point implementation. + fn accuracy() -> Self::Inner { + Self::DIV + } + + /// Builds this type from an integer number. + fn from_inner(int: Self::Inner) -> Self; + + /// Consumes `self` and returns the inner raw value. + fn into_inner(self) -> Self::Inner; + + /// Creates self from an integer number `int`. + /// + /// Returns `Self::max` or `Self::min` if `int` exceeds accuracy. + fn saturating_from_integer(int: N) -> Self { + let mut n: I129 = int.into(); + n.value = n.value.saturating_mul(Self::DIV.saturated_into()); + Self::from_inner(from_i129(n).unwrap_or(to_bound(int, 0))) + } + + /// Creates `self` from an integer number `int`. + /// + /// Returns `None` if `int` exceeds accuracy. + fn checked_from_integer(int: Self::Inner) -> Option { + int.checked_mul(&Self::DIV).map(|inner| Self::from_inner(inner)) + } + + /// Creates `self` from a rational number. Equal to `n / d`. + /// + /// Panics if `d = 0`. Returns `Self::max` or `Self::min` if `n / d` exceeds accuracy. + fn saturating_from_rational(n: N, d: D) -> Self { + if d == D::zero() { + panic!("attempt to divide by zero") + } + Self::checked_from_rational(n, d).unwrap_or(to_bound(n, d)) + } + + /// Creates `self` from a rational number. Equal to `n / d`. + /// + /// Returns `None` if `d == 0` or `n / d` exceeds accuracy. + fn checked_from_rational(n: N, d: D) -> Option { + if d == D::zero() { + return None + } + + let n: I129 = n.into(); + let d: I129 = d.into(); + let negative = n.negative != d.negative; + + multiply_by_rational(n.value, Self::DIV.unique_saturated_into(), d.value).ok() + .and_then(|value| from_i129(I129 { value, negative })) + .map(|inner| Self::from_inner(inner)) + } + + /// Checked multiplication for integer type `N`. Equal to `self * n`. + /// + /// Returns `None` if the result does not fit in `N`. + fn checked_mul_int(self, n: N) -> Option { + let lhs: I129 = self.into_inner().into(); + let rhs: I129 = n.into(); + let negative = lhs.negative != rhs.negative; + + multiply_by_rational(lhs.value, rhs.value, Self::DIV.unique_saturated_into()).ok() + .and_then(|value| from_i129(I129 { value, negative })) + } + + /// Saturating multiplication for integer type `N`. Equal to `self * n`. + /// + /// Returns `N::min` or `N::max` if the result does not fit in `N`. + fn saturating_mul_int(self, n: N) -> N { + self.checked_mul_int(n).unwrap_or(to_bound(self.into_inner(), n)) + } + + /// Checked division for integer type `N`. Equal to `self / d`. + /// + /// Returns `None` if the result does not fit in `N` or `d == 0`. + fn checked_div_int(self, d: N) -> Option { + let lhs: I129 = self.into_inner().into(); + let rhs: I129 = d.into(); + let negative = lhs.negative != rhs.negative; + + lhs.value.checked_div(rhs.value) + .and_then(|n| n.checked_div(Self::DIV.unique_saturated_into())) + .and_then(|value| from_i129(I129 { value, negative })) + } + + /// Saturating division for integer type `N`. Equal to `self / d`. + /// + /// Panics if `d == 0`. Returns `N::min` or `N::max` if the result does not fit in `N`. + fn saturating_div_int(self, d: N) -> N { + if d == N::zero() { + panic!("attempt to divide by zero") + } + self.checked_div_int(d).unwrap_or(to_bound(self.into_inner(), d)) + } + + /// Saturating multiplication for integer type `N`, adding the result back. + /// Equal to `self * n + n`. + /// + /// Returns `N::min` or `N::max` if the multiplication or final result does not fit in `N`. + fn saturating_mul_acc_int(self, n: N) -> N { + if self.is_negative() && n > N::zero() { + n.saturating_sub(Self::zero().saturating_sub(self).saturating_mul_int(n)) + } else { + self.saturating_mul_int(n).saturating_add(n) + } + } + + /// Saturating absolute value. + /// + /// Returns `Self::max` if `self == Self::min`. + fn saturating_abs(self) -> Self { + let inner = self.into_inner(); + if inner >= Self::Inner::zero() { + self + } else { + Self::from_inner(inner.checked_neg().unwrap_or(Self::Inner::max_value())) + } + } + + /// Takes the reciprocal (inverse). Equal to `1 / self`. + /// + /// Returns `None` if `self = 0`. + fn reciprocal(self) -> Option { + Self::one().checked_div(&self) + } + + /// Returns zero. + fn zero() -> Self { + Self::from_inner(Self::Inner::zero()) + } + + /// Checks if the number is zero. + fn is_zero(&self) -> bool { + self.into_inner() == Self::Inner::zero() + } + + /// Returns one. + fn one() -> Self { + Self::from_inner(Self::DIV) + } + + /// Checks if the number is one. + fn is_one(&self) -> bool { + self.into_inner() == Self::Inner::one() + } + + /// Returns `true` if `self` is positive and `false` if the number is zero or negative. + fn is_positive(self) -> bool { + self.into_inner() > Self::Inner::zero() + } + + /// Returns `true` if `self` is negative and `false` if the number is zero or positive. + fn is_negative(self) -> bool { + self.into_inner() < Self::Inner::zero() + } + + /// Returns the integer part. + fn trunc(self) -> Self { + self.into_inner().checked_div(&Self::DIV) + .expect("panics only if DIV is zero, DIV is not zero; qed") + .checked_mul(&Self::DIV) + .map(|inner| Self::from_inner(inner)) + .expect("can not overflow since fixed number is >= integer part") + } + + /// Returns the fractional part. + /// + /// Note: the returned fraction will be non-negative for negative numbers, + /// except in the case where the integer part is zero. + fn frac(self) -> Self { + let integer = self.trunc(); + let fractional = self.saturating_sub(integer); + if integer == Self::zero() { + fractional + } else { + fractional.saturating_abs() + } + } + + /// Returns the smallest integer greater than or equal to a number. + /// + /// Saturates to `Self::max` (truncated) if the result does not fit. + fn ceil(self) -> Self { + if self.is_negative() { + self.trunc() + } else { + if self.frac() == Self::zero() { + self + } else { + self.saturating_add(Self::one()).trunc() + } + } + } + + /// Returns the largest integer less than or equal to a number. + /// + /// Saturates to `Self::min` (truncated) if the result does not fit. + fn floor(self) -> Self { + if self.is_negative() { + self.saturating_sub(Self::one()).trunc() + } else { + self.trunc() + } + } + + /// Returns the number rounded to the nearest integer. Rounds half-way cases away from 0.0. + /// + /// Saturates to `Self::min` or `Self::max` (truncated) if the result does not fit. + fn round(self) -> Self { + let n = self.frac().saturating_mul(Self::saturating_from_integer(10)); + if n < Self::saturating_from_integer(5) { + self.trunc() + } else { + if self.is_positive() { + self.saturating_add(Self::one()).trunc() + } else { + self.saturating_sub(Self::one()).trunc() + } + } + } +} + +/// Data type used as intermediate storage in some computations to avoid overflow. +struct I129 { + value: u128, + negative: bool, +} + +impl From for I129 { + fn from(n: N) -> I129 { + if n < N::zero() { + let value: u128 = n.checked_neg() + .map(|n| n.unique_saturated_into()) + .unwrap_or(N::max_value().unique_saturated_into().saturating_add(1)); + I129 { value, negative: true } + } else { + I129 { value: n.unique_saturated_into(), negative: false } + } + } +} + +/// Transforms an `I129` to `N` if it is possible. +fn from_i129(n: I129) -> Option { + let max_plus_one: u128 = N::max_value().unique_saturated_into().saturating_add(1); + if n.negative && N::min_value() < N::zero() && n.value == max_plus_one { + Some(N::min_value()) + } else { + let unsigned_inner: N = n.value.try_into().ok()?; + let inner = if n.negative { unsigned_inner.checked_neg()? } else { unsigned_inner }; + Some(inner) + } +} + +/// Returns `R::max` if the sign of `n * m` is positive, `R::min` otherwise. +fn to_bound(n: N, m: D) -> R { + if (n < N::zero()) != (m < D::zero()) { + R::min_value() + } else { + R::max_value() + } +} + +macro_rules! implement_fixed { + ( + $name:ident, + $test_mod:ident, + $inner_type:ty, + $signed:tt, + $div:tt, + $title:expr $(,)? + ) => { + /// A fixed point number representation in the range. + /// + #[doc = $title] + #[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] + pub struct $name($inner_type); + + impl From<$inner_type> for $name { + fn from(int: $inner_type) -> Self { + $name::saturating_from_integer(int) + } + } + + impl From<(N, D)> for $name { + fn from(r: (N, D)) -> Self { + $name::saturating_from_rational(r.0, r.1) + } + } + + impl FixedPointNumber for $name { + type Inner = $inner_type; + + const DIV: Self::Inner = $div; + const SIGNED: bool = $signed; + + fn from_inner(inner: Self::Inner) -> Self { + Self(inner) + } + + fn into_inner(self) -> Self::Inner { + self.0 + } + } + + impl $name { + /// const version of `FixedPointNumber::from_inner`. + pub const fn from_inner(inner: $inner_type) -> Self { + Self(inner) + } + + #[cfg(any(feature = "std", test))] + pub fn from_fraction(x: f64) -> Self { + Self((x * (::DIV as f64)) as $inner_type) + } + + #[cfg(any(feature = "std", test))] + pub fn to_fraction(self) -> f64 { + self.0 as f64 / ::DIV as f64 + } + } + + impl Saturating for $name { + fn saturating_add(self, rhs: Self) -> Self { + Self(self.0.saturating_add(rhs.0)) + } + + fn saturating_sub(self, rhs: Self) -> Self { + Self(self.0.saturating_sub(rhs.0)) + } + + fn saturating_mul(self, rhs: Self) -> Self { + self.checked_mul(&rhs).unwrap_or(to_bound(self.0, rhs.0)) + } + + fn saturating_pow(self, exp: usize) -> Self { + if exp == 0 { + return Self::saturating_from_integer(1); + } + + let exp = exp as u32; + let msb_pos = 32 - exp.leading_zeros(); + + let mut result = Self::saturating_from_integer(1); + let mut pow_val = self; + for i in 0..msb_pos { + if ((1 << i) & exp) > 0 { + result = result.saturating_mul(pow_val); + } + pow_val = pow_val.saturating_mul(pow_val); + } + result + } + } + + impl ops::Neg for $name { + type Output = Self; + + fn neg(self) -> Self::Output { + Self(::Inner::zero() - self.0) + } + } + + impl ops::Add for $name { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + Self(self.0 + rhs.0) + } + } + + impl ops::Sub for $name { + type Output = Self; + + fn sub(self, rhs: Self) -> Self::Output { + Self(self.0 - rhs.0) + } + } + + impl ops::Mul for $name { + type Output = Self; + + fn mul(self, rhs: Self) -> Self::Output { + self.checked_mul(&rhs) + .unwrap_or_else(|| panic!("attempt to multiply with overflow")) + } + } + + impl ops::Div for $name { + type Output = Self; + + fn div(self, rhs: Self) -> Self::Output { + if rhs.0 == 0 { + panic!("attempt to divide by zero") + } + self.checked_div(&rhs) + .unwrap_or_else(|| panic!("attempt to divide with overflow")) + } + } + + impl CheckedSub for $name { + fn checked_sub(&self, rhs: &Self) -> Option { + self.0.checked_sub(rhs.0).map(Self) + } + } + + impl CheckedAdd for $name { + fn checked_add(&self, rhs: &Self) -> Option { + self.0.checked_add(rhs.0).map(Self) + } + } + + impl CheckedDiv for $name { + fn checked_div(&self, other: &Self) -> Option { + if other.0 == 0 { + return None + } + + let lhs: I129 = self.0.into(); + let rhs: I129 = other.0.into(); + let negative = lhs.negative != rhs.negative; + + multiply_by_rational(lhs.value, Self::DIV as u128, rhs.value).ok() + .and_then(|value| from_i129(I129 { value, negative })) + .map(Self) + } + } + + impl CheckedMul for $name { + fn checked_mul(&self, other: &Self) -> Option { + let lhs: I129 = self.0.into(); + let rhs: I129 = other.0.into(); + let negative = lhs.negative != rhs.negative; + + multiply_by_rational(lhs.value, rhs.value, Self::DIV as u128).ok() + .and_then(|value| from_i129(I129 { value, negative })) + .map(Self) + } + } + + impl Bounded for $name { + fn min_value() -> Self { + Self(::Inner::min_value()) + } + + fn max_value() -> Self { + Self(::Inner::max_value()) + } + } + + impl sp_std::fmt::Debug for $name { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + let integral = { + let int = self.0 / Self::accuracy(); + let signum_for_zero = if int == 0 && self.is_negative() { "-" } else { "" }; + format!("{}{}", signum_for_zero, int) + }; + let precision = (Self::accuracy() as f64).log10() as usize; + let fractional = format!("{:0>weight$}", ((self.0 % Self::accuracy()) as i128).abs(), weight=precision); + write!(f, "{}({}.{})", stringify!($name), integral, fractional) + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } + } + + impl From

for $name { + fn from(p: P) -> Self { + let accuracy = P::ACCURACY.saturated_into(); + let value = p.deconstruct().saturated_into(); + $name::saturating_from_rational(value, accuracy) + } + } + + #[cfg(feature = "std")] + impl sp_std::fmt::Display for $name { + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "{}", self.0) + } + } + + #[cfg(feature = "std")] + impl sp_std::str::FromStr for $name { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + let inner: ::Inner = s.parse() + .map_err(|_| "invalid string input for fixed point number")?; + Ok(Self::from_inner(inner)) + } + } + + // Manual impl `Serialize` as serde_json does not support i128. + // TODO: remove impl if issue https://github.com/serde-rs/json/issues/548 fixed. + #[cfg(feature = "std")] + impl Serialize for $name { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&self.to_string()) + } + } + + // Manual impl `Deserialize` as serde_json does not support i128. + // TODO: remove impl if issue https://github.com/serde-rs/json/issues/548 fixed. + #[cfg(feature = "std")] + impl<'de> Deserialize<'de> for $name { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + use sp_std::str::FromStr; + let s = String::deserialize(deserializer)?; + $name::from_str(&s).map_err(|err_str| de::Error::custom(err_str)) + } + } + + #[cfg(test)] + mod $test_mod { + use super::*; + use crate::{Perbill, Percent, Permill, Perquintill}; + + fn max() -> $name { + $name::max_value() + } + + fn min() -> $name { + $name::min_value() + } + + fn precision() -> usize { + ($name::accuracy() as f64).log10() as usize + } + + #[test] + fn macro_preconditions() { + assert!($name::DIV > 0); + } + + #[test] + fn from_i129_works() { + let a = I129 { + value: 1, + negative: true, + }; + + // Can't convert negative number to unsigned. + assert_eq!(from_i129::(a), None); + + let a = I129 { + value: u128::max_value() - 1, + negative: false, + }; + + // Max - 1 value fits. + assert_eq!(from_i129::(a), Some(u128::max_value() - 1)); + + let a = I129 { + value: u128::max_value(), + negative: false, + }; + + // Max value fits. + assert_eq!(from_i129::(a), Some(u128::max_value())); + + let a = I129 { + value: i128::max_value() as u128 + 1, + negative: true, + }; + + // Min value fits. + assert_eq!(from_i129::(a), Some(i128::min_value())); + + let a = I129 { + value: i128::max_value() as u128 + 1, + negative: false, + }; + + // Max + 1 does not fit. + assert_eq!(from_i129::(a), None); + + let a = I129 { + value: i128::max_value() as u128, + negative: false, + }; + + // Max value fits. + assert_eq!(from_i129::(a), Some(i128::max_value())); + } + + #[test] + fn to_bound_works() { + let a = 1i32; + let b = 1i32; + + // Pos + Pos => Max. + assert_eq!(to_bound::<_, _, i32>(a, b), i32::max_value()); + + let a = -1i32; + let b = -1i32; + + // Neg + Neg => Max. + assert_eq!(to_bound::<_, _, i32>(a, b), i32::max_value()); + + let a = 1i32; + let b = -1i32; + + // Pos + Neg => Min. + assert_eq!(to_bound::<_, _, i32>(a, b), i32::min_value()); + + let a = -1i32; + let b = 1i32; + + // Neg + Pos => Min. + assert_eq!(to_bound::<_, _, i32>(a, b), i32::min_value()); + + let a = 1i32; + let b = -1i32; + + // Pos + Neg => Min (unsigned). + assert_eq!(to_bound::<_, _, u32>(a, b), 0); + } + + #[test] + fn op_neg_works() { + let a = $name::zero(); + let b = -a; + + // Zero. + assert_eq!(a, b); + + if $name::SIGNED { + let a = $name::saturating_from_integer(5); + let b = -a; + + // Positive. + assert_eq!($name::saturating_from_integer(-5), b); + + let a = $name::saturating_from_integer(-5); + let b = -a; + + // Negative + assert_eq!($name::saturating_from_integer(5), b); + + let a = $name::max_value(); + let b = -a; + + // Max. + assert_eq!($name::min_value() + $name::from_inner(1), b); + + let a = $name::min_value() + $name::from_inner(1); + let b = -a; + + // Min. + assert_eq!($name::max_value(), b); + + } + } + + #[test] + fn op_checked_add_overflow_works() { + let a = $name::max_value(); + let b = 1.into(); + assert!(a.checked_add(&b).is_none()); + } + + #[test] + fn op_add_works() { + let a = $name::saturating_from_rational(5, 2); + let b = $name::saturating_from_rational(1, 2); + + // Positive case: 6/2 = 3. + assert_eq!($name::saturating_from_integer(3), a + b); + + if $name::SIGNED { + // Negative case: 4/2 = 2. + let b = $name::saturating_from_rational(1, -2); + assert_eq!($name::saturating_from_integer(2), a + b); + } + } + + #[test] + fn op_checked_sub_underflow_works() { + let a = $name::min_value(); + let b = 1.into(); + assert!(a.checked_sub(&b).is_none()); + } + + #[test] + fn op_sub_works() { + let a = $name::saturating_from_rational(5, 2); + let b = $name::saturating_from_rational(1, 2); + + assert_eq!($name::saturating_from_integer(2), a - b); + assert_eq!($name::saturating_from_integer(-2), b.saturating_sub(a)); + } + + #[test] + fn op_checked_mul_overflow_works() { + let a = $name::max_value(); + let b = 2.into(); + assert!(a.checked_mul(&b).is_none()); + } + + #[test] + fn op_mul_works() { + let a = $name::saturating_from_integer(42); + let b = $name::saturating_from_integer(2); + assert_eq!($name::saturating_from_integer(84), a * b); + + let a = $name::saturating_from_integer(42); + let b = $name::saturating_from_integer(-2); + assert_eq!($name::saturating_from_integer(-84), a * b); + } + + #[test] + #[should_panic(expected = "attempt to divide by zero")] + fn op_div_panics_on_zero_divisor() { + let a = $name::saturating_from_integer(1); + let b = 0.into(); + let _c = a / b; + } + + #[test] + fn op_checked_div_overflow_works() { + if $name::SIGNED { + let a = $name::min_value(); + let b = $name::zero().saturating_sub($name::one()); + assert!(a.checked_div(&b).is_none()); + } + } + + #[test] + fn op_div_works() { + let a = $name::saturating_from_integer(42); + let b = $name::saturating_from_integer(2); + assert_eq!($name::saturating_from_integer(21), a / b); + + if $name::SIGNED { + let a = $name::saturating_from_integer(42); + let b = $name::saturating_from_integer(-2); + assert_eq!($name::saturating_from_integer(-21), a / b); + } + } + + #[test] + fn saturating_from_integer_works() { + let inner_max = <$name as FixedPointNumber>::Inner::max_value(); + let inner_min = <$name as FixedPointNumber>::Inner::min_value(); + let accuracy = $name::accuracy(); + + // Cases where integer fits. + let a = $name::saturating_from_integer(42); + assert_eq!(a.into_inner(), 42 * accuracy); + + let a = $name::saturating_from_integer(-42); + assert_eq!(a.into_inner(), 0.saturating_sub(42 * accuracy)); + + // Max/min integers that fit. + let a = $name::saturating_from_integer(inner_max / accuracy); + assert_eq!(a.into_inner(), (inner_max / accuracy) * accuracy); + + let a = $name::saturating_from_integer(inner_min / accuracy); + assert_eq!(a.into_inner(), (inner_min / accuracy) * accuracy); + + // Cases where integer doesn't fit, so it saturates. + let a = $name::saturating_from_integer(inner_max / accuracy + 1); + assert_eq!(a.into_inner(), inner_max); + + let a = $name::saturating_from_integer((inner_min / accuracy).saturating_sub(1)); + assert_eq!(a.into_inner(), inner_min); + } + + #[test] + fn checked_from_integer_works() { + let inner_max = <$name as FixedPointNumber>::Inner::max_value(); + let inner_min = <$name as FixedPointNumber>::Inner::min_value(); + let accuracy = $name::accuracy(); + + // Case where integer fits. + let a = $name::checked_from_integer(42) + .expect("42 * accuracy <= inner_max; qed"); + assert_eq!(a.into_inner(), 42 * accuracy); + + // Max integer that fit. + let a = $name::checked_from_integer(inner_max / accuracy) + .expect("(inner_max / accuracy) * accuracy <= inner_max; qed"); + assert_eq!(a.into_inner(), (inner_max / accuracy) * accuracy); + + // Case where integer doesn't fit, so it returns `None`. + let a = $name::checked_from_integer(inner_max / accuracy + 1); + assert_eq!(a, None); + + if $name::SIGNED { + // Case where integer fits. + let a = $name::checked_from_integer(0.saturating_sub(42)) + .expect("-42 * accuracy >= inner_min; qed"); + assert_eq!(a.into_inner(), 0 - 42 * accuracy); + + // Min integer that fit. + let a = $name::checked_from_integer(inner_min / accuracy) + .expect("(inner_min / accuracy) * accuracy <= inner_min; qed"); + assert_eq!(a.into_inner(), (inner_min / accuracy) * accuracy); + + // Case where integer doesn't fit, so it returns `None`. + let a = $name::checked_from_integer(inner_min / accuracy - 1); + assert_eq!(a, None); + } + } + + #[test] + fn from_inner_works() { + let inner_max = <$name as FixedPointNumber>::Inner::max_value(); + let inner_min = <$name as FixedPointNumber>::Inner::min_value(); + + assert_eq!(max(), $name::from_inner(inner_max)); + assert_eq!(min(), $name::from_inner(inner_min)); + } + + #[test] + #[should_panic(expected = "attempt to divide by zero")] + fn saturating_from_rational_panics_on_zero_divisor() { + let _ = $name::saturating_from_rational(1, 0); + } + + #[test] + fn saturating_from_rational_works() { + let inner_max = <$name as FixedPointNumber>::Inner::max_value(); + let inner_min = <$name as FixedPointNumber>::Inner::min_value(); + let accuracy = $name::accuracy(); + + let a = $name::saturating_from_rational(5, 2); + + // Positive case: 2.5 + assert_eq!(a.into_inner(), 25 * accuracy / 10); + + // Max - 1. + let a = $name::saturating_from_rational(inner_max - 1, accuracy); + assert_eq!(a.into_inner(), inner_max - 1); + + // Min + 1. + let a = $name::saturating_from_rational(inner_min + 1, accuracy); + assert_eq!(a.into_inner(), inner_min + 1); + + // Max. + let a = $name::saturating_from_rational(inner_max, accuracy); + assert_eq!(a.into_inner(), inner_max); + + // Min. + let a = $name::saturating_from_rational(inner_min, accuracy); + assert_eq!(a.into_inner(), inner_min); + + // Zero. + let a = $name::saturating_from_rational(0, 1); + assert_eq!(a.into_inner(), 0); + + if $name::SIGNED { + // Negative case: -2.5 + let a = $name::saturating_from_rational(-5, 2); + assert_eq!(a.into_inner(), 0 - 25 * accuracy / 10); + + // Other negative case: -2.5 + let a = $name::saturating_from_rational(5, -2); + assert_eq!(a.into_inner(), 0 - 25 * accuracy / 10); + + // Other positive case: 2.5 + let a = $name::saturating_from_rational(-5, -2); + assert_eq!(a.into_inner(), 25 * accuracy / 10); + + // Max + 1, saturates. + let a = $name::saturating_from_rational(inner_max as u128 + 1, accuracy); + assert_eq!(a.into_inner(), inner_max); + + // Min - 1, saturates. + let a = $name::saturating_from_rational(inner_max as u128 + 2, 0 - accuracy); + assert_eq!(a.into_inner(), inner_min); + + let a = $name::saturating_from_rational(inner_max, 0 - accuracy); + assert_eq!(a.into_inner(), 0 - inner_max); + + let a = $name::saturating_from_rational(inner_min, 0 - accuracy); + assert_eq!(a.into_inner(), inner_max); + + let a = $name::saturating_from_rational(inner_min + 1, 0 - accuracy); + assert_eq!(a.into_inner(), inner_max); + + let a = $name::saturating_from_rational(inner_min, 0 - 1); + assert_eq!(a.into_inner(), inner_max); + + let a = $name::saturating_from_rational(inner_max, 0 - 1); + assert_eq!(a.into_inner(), inner_min); + + let a = $name::saturating_from_rational(inner_max, 0 - inner_max); + assert_eq!(a.into_inner(), 0 - accuracy); + + let a = $name::saturating_from_rational(0 - inner_max, inner_max); + assert_eq!(a.into_inner(), 0 - accuracy); + + let a = $name::saturating_from_rational(inner_max, 0 - 3 * accuracy); + assert_eq!(a.into_inner(), 0 - inner_max / 3); + + let a = $name::saturating_from_rational(inner_min, 0 - accuracy / 3); + assert_eq!(a.into_inner(), inner_max); + + let a = $name::saturating_from_rational(1, 0 - accuracy); + assert_eq!(a.into_inner(), 0.saturating_sub(1)); + + let a = $name::saturating_from_rational(inner_min, inner_min); + assert_eq!(a.into_inner(), accuracy); + + // Out of accuracy. + let a = $name::saturating_from_rational(1, 0 - accuracy - 1); + assert_eq!(a.into_inner(), 0); + } + + let a = $name::saturating_from_rational(inner_max - 1, accuracy); + assert_eq!(a.into_inner(), inner_max - 1); + + let a = $name::saturating_from_rational(inner_min + 1, accuracy); + assert_eq!(a.into_inner(), inner_min + 1); + + let a = $name::saturating_from_rational(inner_max, 1); + assert_eq!(a.into_inner(), inner_max); + + let a = $name::saturating_from_rational(inner_min, 1); + assert_eq!(a.into_inner(), inner_min); + + let a = $name::saturating_from_rational(inner_max, inner_max); + assert_eq!(a.into_inner(), accuracy); + + let a = $name::saturating_from_rational(inner_max, 3 * accuracy); + assert_eq!(a.into_inner(), inner_max / 3); + + let a = $name::saturating_from_rational(inner_min, 2 * accuracy); + assert_eq!(a.into_inner(), inner_min / 2); + + let a = $name::saturating_from_rational(inner_min, accuracy / 3); + assert_eq!(a.into_inner(), inner_min); + + let a = $name::saturating_from_rational(1, accuracy); + assert_eq!(a.into_inner(), 1); + + // Out of accuracy. + let a = $name::saturating_from_rational(1, accuracy + 1); + assert_eq!(a.into_inner(), 0); + } + + #[test] + fn checked_from_rational_works() { + let inner_max = <$name as FixedPointNumber>::Inner::max_value(); + let inner_min = <$name as FixedPointNumber>::Inner::min_value(); + let accuracy = $name::accuracy(); + + // Divide by zero => None. + let a = $name::checked_from_rational(1, 0); + assert_eq!(a, None); + + // Max - 1. + let a = $name::checked_from_rational(inner_max - 1, accuracy).unwrap(); + assert_eq!(a.into_inner(), inner_max - 1); + + // Min + 1. + let a = $name::checked_from_rational(inner_min + 1, accuracy).unwrap(); + assert_eq!(a.into_inner(), inner_min + 1); + + // Max. + let a = $name::checked_from_rational(inner_max, accuracy).unwrap(); + assert_eq!(a.into_inner(), inner_max); + + // Min. + let a = $name::checked_from_rational(inner_min, accuracy).unwrap(); + assert_eq!(a.into_inner(), inner_min); + + // Max + 1 => Overflow => None. + let a = $name::checked_from_rational(inner_min, 0.saturating_sub(accuracy)); + assert_eq!(a, None); + + if $name::SIGNED { + // Min - 1 => Underflow => None. + let a = $name::checked_from_rational(inner_max as u128 + 2, 0.saturating_sub(accuracy)); + assert_eq!(a, None); + + let a = $name::checked_from_rational(inner_max, 0 - 3 * accuracy).unwrap(); + assert_eq!(a.into_inner(), 0 - inner_max / 3); + + let a = $name::checked_from_rational(inner_min, 0 - accuracy / 3); + assert_eq!(a, None); + + let a = $name::checked_from_rational(1, 0 - accuracy).unwrap(); + assert_eq!(a.into_inner(), 0.saturating_sub(1)); + + let a = $name::checked_from_rational(1, 0 - accuracy - 1).unwrap(); + assert_eq!(a.into_inner(), 0); + + let a = $name::checked_from_rational(inner_min, accuracy / 3); + assert_eq!(a, None); + } + + let a = $name::checked_from_rational(inner_max, 3 * accuracy).unwrap(); + assert_eq!(a.into_inner(), inner_max / 3); + + let a = $name::checked_from_rational(inner_min, 2 * accuracy).unwrap(); + assert_eq!(a.into_inner(), inner_min / 2); + + let a = $name::checked_from_rational(1, accuracy).unwrap(); + assert_eq!(a.into_inner(), 1); + + let a = $name::checked_from_rational(1, accuracy + 1).unwrap(); + assert_eq!(a.into_inner(), 0); + } + + #[test] + fn checked_mul_int_works() { + let a = $name::saturating_from_integer(2); + // Max - 1. + assert_eq!(a.checked_mul_int((i128::max_value() - 1) / 2), Some(i128::max_value() - 1)); + // Max. + assert_eq!(a.checked_mul_int(i128::max_value() / 2), Some(i128::max_value() - 1)); + // Max + 1 => None. + assert_eq!(a.checked_mul_int(i128::max_value() / 2 + 1), None); + + if $name::SIGNED { + // Min - 1. + assert_eq!(a.checked_mul_int((i128::min_value() + 1) / 2), Some(i128::min_value() + 2)); + // Min. + assert_eq!(a.checked_mul_int(i128::min_value() / 2), Some(i128::min_value())); + // Min + 1 => None. + assert_eq!(a.checked_mul_int(i128::min_value() / 2 - 1), None); + + let b = $name::saturating_from_rational(1, -2); + assert_eq!(b.checked_mul_int(42i128), Some(-21)); + assert_eq!(b.checked_mul_int(u128::max_value()), None); + assert_eq!(b.checked_mul_int(i128::max_value()), Some(i128::max_value() / -2)); + assert_eq!(b.checked_mul_int(i128::min_value()), Some(i128::min_value() / -2)); + } + + let a = $name::saturating_from_rational(1, 2); + assert_eq!(a.checked_mul_int(42i128), Some(21)); + assert_eq!(a.checked_mul_int(i128::max_value()), Some(i128::max_value() / 2)); + assert_eq!(a.checked_mul_int(i128::min_value()), Some(i128::min_value() / 2)); + + let c = $name::saturating_from_integer(255); + assert_eq!(c.checked_mul_int(2i8), None); + assert_eq!(c.checked_mul_int(2i128), Some(510)); + assert_eq!(c.checked_mul_int(i128::max_value()), None); + assert_eq!(c.checked_mul_int(i128::min_value()), None); + } + + #[test] + fn saturating_mul_int_works() { + let a = $name::saturating_from_integer(2); + // Max - 1. + assert_eq!(a.saturating_mul_int((i128::max_value() - 1) / 2), i128::max_value() - 1); + // Max. + assert_eq!(a.saturating_mul_int(i128::max_value() / 2), i128::max_value() - 1); + // Max + 1 => saturates to max. + assert_eq!(a.saturating_mul_int(i128::max_value() / 2 + 1), i128::max_value()); + + // Min - 1. + assert_eq!(a.saturating_mul_int((i128::min_value() + 1) / 2), i128::min_value() + 2); + // Min. + assert_eq!(a.saturating_mul_int(i128::min_value() / 2), i128::min_value()); + // Min + 1 => saturates to min. + assert_eq!(a.saturating_mul_int(i128::min_value() / 2 - 1), i128::min_value()); + + if $name::SIGNED { + let b = $name::saturating_from_rational(1, -2); + assert_eq!(b.saturating_mul_int(42i32), -21); + assert_eq!(b.saturating_mul_int(i128::max_value()), i128::max_value() / -2); + assert_eq!(b.saturating_mul_int(i128::min_value()), i128::min_value() / -2); + assert_eq!(b.saturating_mul_int(u128::max_value()), u128::min_value()); + } + + let a = $name::saturating_from_rational(1, 2); + assert_eq!(a.saturating_mul_int(42i32), 21); + assert_eq!(a.saturating_mul_int(i128::max_value()), i128::max_value() / 2); + assert_eq!(a.saturating_mul_int(i128::min_value()), i128::min_value() / 2); + + let c = $name::saturating_from_integer(255); + assert_eq!(c.saturating_mul_int(2i8), i8::max_value()); + assert_eq!(c.saturating_mul_int(-2i8), i8::min_value()); + assert_eq!(c.saturating_mul_int(i128::max_value()), i128::max_value()); + assert_eq!(c.saturating_mul_int(i128::min_value()), i128::min_value()); + } + + #[test] + fn checked_mul_works() { + let inner_max = <$name as FixedPointNumber>::Inner::max_value(); + let inner_min = <$name as FixedPointNumber>::Inner::min_value(); + + let a = $name::saturating_from_integer(2); + + // Max - 1. + let b = $name::from_inner(inner_max - 1); + assert_eq!(a.checked_mul(&(b/2.into())), Some(b)); + + // Max. + let c = $name::from_inner(inner_max); + assert_eq!(a.checked_mul(&(c/2.into())), Some(b)); + + // Max + 1 => None. + let e = $name::from_inner(1); + assert_eq!(a.checked_mul(&(c/2.into()+e)), None); + + if $name::SIGNED { + // Min + 1. + let b = $name::from_inner(inner_min + 1) / 2.into(); + let c = $name::from_inner(inner_min + 2); + assert_eq!(a.checked_mul(&b), Some(c)); + + // Min. + let b = $name::from_inner(inner_min) / 2.into(); + let c = $name::from_inner(inner_min); + assert_eq!(a.checked_mul(&b), Some(c)); + + // Min - 1 => None. + let b = $name::from_inner(inner_min) / 2.into() - $name::from_inner(1); + assert_eq!(a.checked_mul(&b), None); + + let c = $name::saturating_from_integer(255); + let b = $name::saturating_from_rational(1, -2); + + assert_eq!(b.checked_mul(&42.into()), Some(0.saturating_sub(21).into())); + assert_eq!(b.checked_mul(&$name::max_value()), $name::max_value().checked_div(&0.saturating_sub(2).into())); + assert_eq!(b.checked_mul(&$name::min_value()), $name::min_value().checked_div(&0.saturating_sub(2).into())); + assert_eq!(c.checked_mul(&$name::min_value()), None); + } + + let a = $name::saturating_from_rational(1, 2); + let c = $name::saturating_from_integer(255); + + assert_eq!(a.checked_mul(&42.into()), Some(21.into())); + assert_eq!(c.checked_mul(&2.into()), Some(510.into())); + assert_eq!(c.checked_mul(&$name::max_value()), None); + assert_eq!(a.checked_mul(&$name::max_value()), $name::max_value().checked_div(&2.into())); + assert_eq!(a.checked_mul(&$name::min_value()), $name::min_value().checked_div(&2.into())); + } + + #[test] + fn checked_div_int_works() { + let inner_max = <$name as FixedPointNumber>::Inner::max_value(); + let inner_min = <$name as FixedPointNumber>::Inner::min_value(); + let accuracy = $name::accuracy(); + + let a = $name::from_inner(inner_max); + let b = $name::from_inner(inner_min); + let c = $name::zero(); + let d = $name::one(); + let e = $name::saturating_from_integer(6); + let f = $name::saturating_from_integer(5); + + assert_eq!(e.checked_div_int(2.into()), Some(3)); + assert_eq!(f.checked_div_int(2.into()), Some(2)); + + assert_eq!(a.checked_div_int(i128::max_value()), Some(0)); + assert_eq!(a.checked_div_int(2), Some(inner_max / (2 * accuracy))); + assert_eq!(a.checked_div_int(inner_max / accuracy), Some(1)); + assert_eq!(a.checked_div_int(1i8), None); + + if b < c { + // Not executed by unsigned inners. + assert_eq!(a.checked_div_int(0.saturating_sub(2)), Some(0.saturating_sub(inner_max / (2 * accuracy)))); + assert_eq!(a.checked_div_int(0.saturating_sub(inner_max / accuracy)), Some(0.saturating_sub(1))); + assert_eq!(b.checked_div_int(i128::min_value()), Some(0)); + assert_eq!(b.checked_div_int(inner_min / accuracy), Some(1)); + assert_eq!(b.checked_div_int(1i8), None); + assert_eq!(b.checked_div_int(0.saturating_sub(2)), Some(0.saturating_sub(inner_min / (2 * accuracy)))); + assert_eq!(b.checked_div_int(0.saturating_sub(inner_min / accuracy)), Some(0.saturating_sub(1))); + assert_eq!(c.checked_div_int(i128::min_value()), Some(0)); + assert_eq!(d.checked_div_int(i32::min_value()), Some(0)); + } + + assert_eq!(b.checked_div_int(2), Some(inner_min / (2 * accuracy))); + + assert_eq!(c.checked_div_int(1), Some(0)); + assert_eq!(c.checked_div_int(i128::max_value()), Some(0)); + assert_eq!(c.checked_div_int(1i8), Some(0)); + + assert_eq!(d.checked_div_int(1), Some(1)); + assert_eq!(d.checked_div_int(i32::max_value()), Some(0)); + assert_eq!(d.checked_div_int(1i8), Some(1)); + + assert_eq!(a.checked_div_int(0), None); + assert_eq!(b.checked_div_int(0), None); + assert_eq!(c.checked_div_int(0), None); + assert_eq!(d.checked_div_int(0), None); + } + + #[test] + #[should_panic(expected = "attempt to divide by zero")] + fn saturating_div_int_panics_when_divisor_is_zero() { + let _ = $name::one().saturating_div_int(0); + } + + #[test] + fn saturating_div_int_works() { + let inner_max = <$name as FixedPointNumber>::Inner::max_value(); + let inner_min = <$name as FixedPointNumber>::Inner::min_value(); + let accuracy = $name::accuracy(); + + let a = $name::saturating_from_integer(5); + assert_eq!(a.saturating_div_int(2), 2); + + let a = $name::min_value(); + assert_eq!(a.saturating_div_int(1i128), (inner_min / accuracy) as i128); + + if $name::SIGNED { + let a = $name::saturating_from_integer(5); + assert_eq!(a.saturating_div_int(-2), -2); + + let a = $name::min_value(); + assert_eq!(a.saturating_div_int(-1i128), (inner_max / accuracy) as i128); + } + } + + #[test] + fn saturating_abs_works() { + let inner_max = <$name as FixedPointNumber>::Inner::max_value(); + let inner_min = <$name as FixedPointNumber>::Inner::min_value(); + + assert_eq!($name::from_inner(inner_max).saturating_abs(), $name::max_value()); + assert_eq!($name::zero().saturating_abs(), 0.into()); + + if $name::SIGNED { + assert_eq!($name::from_inner(inner_min).saturating_abs(), $name::max_value()); + assert_eq!($name::saturating_from_rational(-1, 2).saturating_abs(), (1, 2).into()); + } + } + + #[test] + fn saturating_mul_acc_int_works() { + assert_eq!($name::zero().saturating_mul_acc_int(42i8), 42i8); + assert_eq!($name::one().saturating_mul_acc_int(42i8), 2 * 42i8); + + assert_eq!($name::one().saturating_mul_acc_int(i128::max_value()), i128::max_value()); + assert_eq!($name::one().saturating_mul_acc_int(i128::min_value()), i128::min_value()); + + assert_eq!($name::one().saturating_mul_acc_int(u128::max_value() / 2), u128::max_value() - 1); + assert_eq!($name::one().saturating_mul_acc_int(u128::min_value()), u128::min_value()); + + if $name::SIGNED { + let a = $name::saturating_from_rational(-1, 2); + assert_eq!(a.saturating_mul_acc_int(42i8), 21i8); + assert_eq!(a.saturating_mul_acc_int(42u8), 21u8); + assert_eq!(a.saturating_mul_acc_int(u128::max_value() - 1), u128::max_value() / 2); + } + } + + #[test] + fn saturating_pow_should_work() { + assert_eq!($name::saturating_from_integer(2).saturating_pow(0), $name::saturating_from_integer(1)); + assert_eq!($name::saturating_from_integer(2).saturating_pow(1), $name::saturating_from_integer(2)); + assert_eq!($name::saturating_from_integer(2).saturating_pow(2), $name::saturating_from_integer(4)); + assert_eq!($name::saturating_from_integer(2).saturating_pow(3), $name::saturating_from_integer(8)); + assert_eq!($name::saturating_from_integer(2).saturating_pow(50), + $name::saturating_from_integer(1125899906842624i64)); + + assert_eq!($name::saturating_from_integer(1).saturating_pow(1000), (1).into()); + assert_eq!($name::saturating_from_integer(1).saturating_pow(usize::max_value()), (1).into()); + + if $name::SIGNED { + // Saturating. + assert_eq!($name::saturating_from_integer(2).saturating_pow(68), $name::max_value()); + + assert_eq!($name::saturating_from_integer(-1).saturating_pow(1000), (1).into()); + assert_eq!($name::saturating_from_integer(-1).saturating_pow(1001), 0.saturating_sub(1).into()); + assert_eq!($name::saturating_from_integer(-1).saturating_pow(usize::max_value()), 0.saturating_sub(1).into()); + assert_eq!($name::saturating_from_integer(-1).saturating_pow(usize::max_value() - 1), (1).into()); + } + + assert_eq!($name::saturating_from_integer(114209).saturating_pow(5), $name::max_value()); + + assert_eq!($name::saturating_from_integer(1).saturating_pow(usize::max_value()), (1).into()); + assert_eq!($name::saturating_from_integer(0).saturating_pow(usize::max_value()), (0).into()); + assert_eq!($name::saturating_from_integer(2).saturating_pow(usize::max_value()), $name::max_value()); + } + + #[test] + fn checked_div_works() { + let inner_max = <$name as FixedPointNumber>::Inner::max_value(); + let inner_min = <$name as FixedPointNumber>::Inner::min_value(); + + let a = $name::from_inner(inner_max); + let b = $name::from_inner(inner_min); + let c = $name::zero(); + let d = $name::one(); + let e = $name::saturating_from_integer(6); + let f = $name::saturating_from_integer(5); + + assert_eq!(e.checked_div(&2.into()), Some(3.into())); + assert_eq!(f.checked_div(&2.into()), Some((5, 2).into())); + + assert_eq!(a.checked_div(&inner_max.into()), Some(1.into())); + assert_eq!(a.checked_div(&2.into()), Some($name::from_inner(inner_max / 2))); + assert_eq!(a.checked_div(&$name::max_value()), Some(1.into())); + assert_eq!(a.checked_div(&d), Some(a)); + + if b < c { + // Not executed by unsigned inners. + assert_eq!(a.checked_div(&0.saturating_sub(2).into()), Some($name::from_inner(0.saturating_sub(inner_max / 2)))); + assert_eq!(a.checked_div(&-$name::max_value()), Some(0.saturating_sub(1).into())); + assert_eq!(b.checked_div(&0.saturating_sub(2).into()), Some($name::from_inner(0.saturating_sub(inner_min / 2)))); + assert_eq!(c.checked_div(&$name::max_value()), Some(0.into())); + assert_eq!(b.checked_div(&b), Some($name::one())); + } + + assert_eq!(b.checked_div(&2.into()), Some($name::from_inner(inner_min / 2))); + assert_eq!(b.checked_div(&a), Some(0.saturating_sub(1).into())); + assert_eq!(c.checked_div(&1.into()), Some(0.into())); + assert_eq!(d.checked_div(&1.into()), Some(1.into())); + + assert_eq!(a.checked_div(&$name::one()), Some(a)); + assert_eq!(b.checked_div(&$name::one()), Some(b)); + assert_eq!(c.checked_div(&$name::one()), Some(c)); + assert_eq!(d.checked_div(&$name::one()), Some(d)); + + assert_eq!(a.checked_div(&$name::zero()), None); + assert_eq!(b.checked_div(&$name::zero()), None); + assert_eq!(c.checked_div(&$name::zero()), None); + assert_eq!(d.checked_div(&$name::zero()), None); + } + + #[test] + fn is_positive_negative_works() { + let one = $name::one(); + assert!(one.is_positive()); + assert!(!one.is_negative()); + + let zero = $name::zero(); + assert!(!zero.is_positive()); + assert!(!zero.is_negative()); + + if $signed { + let minus_one = $name::saturating_from_integer(-1); + assert!(minus_one.is_negative()); + assert!(!minus_one.is_positive()); + } + } + + #[test] + fn trunc_works() { + let n = $name::saturating_from_rational(5, 2).trunc(); + assert_eq!(n, $name::saturating_from_integer(2)); + + if $name::SIGNED { + let n = $name::saturating_from_rational(-5, 2).trunc(); + assert_eq!(n, $name::saturating_from_integer(-2)); + } + } + + #[test] + fn frac_works() { + let n = $name::saturating_from_rational(5, 2); + let i = n.trunc(); + let f = n.frac(); + + assert_eq!(n, i + f); + + let n = $name::saturating_from_rational(5, 2) + .frac() + .saturating_mul(10.into()); + assert_eq!(n, 5.into()); + + let n = $name::saturating_from_rational(1, 2) + .frac() + .saturating_mul(10.into()); + assert_eq!(n, 5.into()); + + if $name::SIGNED { + let n = $name::saturating_from_rational(-5, 2); + let i = n.trunc(); + let f = n.frac(); + assert_eq!(n, i - f); + + // The sign is attached to the integer part unless it is zero. + let n = $name::saturating_from_rational(-5, 2) + .frac() + .saturating_mul(10.into()); + assert_eq!(n, 5.into()); + + let n = $name::saturating_from_rational(-1, 2) + .frac() + .saturating_mul(10.into()); + assert_eq!(n, 0.saturating_sub(5).into()); + } + } + + #[test] + fn ceil_works() { + let n = $name::saturating_from_rational(5, 2); + assert_eq!(n.ceil(), 3.into()); + + let n = $name::saturating_from_rational(-5, 2); + assert_eq!(n.ceil(), 0.saturating_sub(2).into()); + + // On the limits: + let n = $name::max_value(); + assert_eq!(n.ceil(), n.trunc()); + + let n = $name::min_value(); + assert_eq!(n.ceil(), n.trunc()); + } + + #[test] + fn floor_works() { + let n = $name::saturating_from_rational(5, 2); + assert_eq!(n.floor(), 2.into()); + + let n = $name::saturating_from_rational(-5, 2); + assert_eq!(n.floor(), 0.saturating_sub(3).into()); + + // On the limits: + let n = $name::max_value(); + assert_eq!(n.floor(), n.trunc()); + + let n = $name::min_value(); + assert_eq!(n.floor(), n.trunc()); + } + + #[test] + fn round_works() { + let n = $name::zero(); + assert_eq!(n.round(), n); + + let n = $name::one(); + assert_eq!(n.round(), n); + + let n = $name::saturating_from_rational(5, 2); + assert_eq!(n.round(), 3.into()); + + let n = $name::saturating_from_rational(-5, 2); + assert_eq!(n.round(), 0.saturating_sub(3).into()); + + // Saturating: + let n = $name::max_value(); + assert_eq!(n.round(), n.trunc()); + + let n = $name::min_value(); + assert_eq!(n.round(), n.trunc()); + + // On the limit: + + // floor(max - 1) + 0.33.. + let n = $name::max_value() + .saturating_sub(1.into()) + .trunc() + .saturating_add((1, 3).into()); + + assert_eq!(n.round(), ($name::max_value() - 1.into()).trunc()); + + // floor(max - 1) + 0.5 + let n = $name::max_value() + .saturating_sub(1.into()) + .trunc() + .saturating_add((1, 2).into()); + + assert_eq!(n.round(), $name::max_value().trunc()); + + if $name::SIGNED { + // floor(min + 1) - 0.33.. + let n = $name::min_value() + .saturating_add(1.into()) + .trunc() + .saturating_sub((1, 3).into()); + + assert_eq!(n.round(), ($name::min_value() + 1.into()).trunc()); + + // floor(min + 1) - 0.5 + let n = $name::min_value() + .saturating_add(1.into()) + .trunc() + .saturating_sub((1, 2).into()); + + assert_eq!(n.round(), $name::min_value().trunc()); + } + } + + #[test] + fn perthing_into_works() { + let ten_percent_percent: $name = Percent::from_percent(10).into(); + assert_eq!(ten_percent_percent.into_inner(), $name::accuracy() / 10); + + let ten_percent_permill: $name = Permill::from_percent(10).into(); + assert_eq!(ten_percent_permill.into_inner(), $name::accuracy() / 10); + + let ten_percent_perbill: $name = Perbill::from_percent(10).into(); + assert_eq!(ten_percent_perbill.into_inner(), $name::accuracy() / 10); + + let ten_percent_perquintill: $name = Perquintill::from_percent(10).into(); + assert_eq!(ten_percent_perquintill.into_inner(), $name::accuracy() / 10); + } + + #[test] + fn fmt_should_work() { + let zero = $name::zero(); + assert_eq!(format!("{:?}", zero), format!("{}(0.{:0>weight$})", stringify!($name), 0, weight=precision())); + + let one = $name::one(); + assert_eq!(format!("{:?}", one), format!("{}(1.{:0>weight$})", stringify!($name), 0, weight=precision())); + + let frac = $name::saturating_from_rational(1, 2); + assert_eq!(format!("{:?}", frac), format!("{}(0.{:0weight$})", stringify!($name), 0, weight=precision())); + + let frac = $name::saturating_from_rational(-314, 100); + assert_eq!(format!("{:?}", frac), format!("{}(-3.{:0. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! 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 diff --git a/primitives/arithmetic/src/lib.rs b/primitives/arithmetic/src/lib.rs index f6d8b53e3499b340b27285964e8c366be39ca158..5c0d2baa51db62183e7599142904ff5fe8cafad5 100644 --- a/primitives/arithmetic/src/lib.rs +++ b/primitives/arithmetic/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Minimal fixed point arithmetic primitives and types for runtime. @@ -36,21 +37,472 @@ pub mod biguint; pub mod helpers_128bit; pub mod traits; mod per_things; -mod fixed64; +mod fixed_point; mod rational128; -pub use fixed64::Fixed64; -pub use per_things::{PerThing, Percent, PerU16, Permill, Perbill, Perquintill}; +pub use fixed_point::{FixedPointNumber, FixedPointOperand, FixedI64, FixedI128, FixedU128}; +pub use per_things::{PerThing, InnerOf, UpperOf, Percent, PerU16, Permill, Perbill, Perquintill}; pub use rational128::Rational128; +use sp_std::{prelude::*, cmp::Ordering, fmt::Debug, convert::TryInto}; +use traits::{BaseArithmetic, One, Zero, SaturatedConversion, Unsigned}; + +/// Trait for comparing two numbers with an threshold. +/// +/// Returns: +/// - `Ordering::Greater` if `self` is greater than `other + threshold`. +/// - `Ordering::Less` if `self` is less than `other - threshold`. +/// - `Ordering::Equal` otherwise. +pub trait ThresholdOrd { + /// Compare if `self` is `threshold` greater or less than `other`. + fn tcmp(&self, other: &T, epsilon: T) -> Ordering; +} + +impl ThresholdOrd for T +where + T: Ord + PartialOrd + Copy + Clone + traits::Zero + traits::Saturating, +{ + fn tcmp(&self, other: &T, threshold: T) -> Ordering { + // early exit. + if threshold.is_zero() { + return self.cmp(&other) + } + + let upper_bound = other.saturating_add(threshold); + let lower_bound = other.saturating_sub(threshold); + + if upper_bound <= lower_bound { + // defensive only. Can never happen. + self.cmp(&other) + } else { + // upper_bound is guaranteed now to be bigger than lower. + match (self.cmp(&lower_bound), self.cmp(&upper_bound)) { + (Ordering::Greater, Ordering::Greater) => Ordering::Greater, + (Ordering::Less, Ordering::Less) => Ordering::Less, + _ => Ordering::Equal, + } + } + + } +} + +/// A collection-like object that is made of values of type `T` and can normalize its individual +/// values around a centric point. +/// +/// Note that the order of items in the collection may affect the result. +pub trait Normalizable { + /// Normalize self around `targeted_sum`. + /// + /// Only returns `Ok` if the new sum of results is guaranteed to be equal to `targeted_sum`. + /// Else, returns an error explaining why it failed to do so. + fn normalize(&self, targeted_sum: T) -> Result, &'static str>; +} + +macro_rules! impl_normalize_for_numeric { + ($($numeric:ty),*) => { + $( + impl Normalizable<$numeric> for Vec<$numeric> { + fn normalize(&self, targeted_sum: $numeric) -> Result, &'static str> { + normalize(self.as_ref(), targeted_sum) + } + } + )* + }; +} + +impl_normalize_for_numeric!(u8, u16, u32, u64, u128); + +impl Normalizable

for Vec

{ + fn normalize(&self, targeted_sum: P) -> Result, &'static str> { + let inners = self.iter().map(|p| p.clone().deconstruct().into()).collect::>(); + let normalized = normalize(inners.as_ref(), targeted_sum.deconstruct().into())?; + Ok(normalized.into_iter().map(|i: UpperOf

| P::from_parts(i.saturated_into())).collect()) + } +} + + +/// Normalize `input` so that the sum of all elements reaches `targeted_sum`. +/// +/// This implementation is currently in a balanced position between being performant and accurate. +/// +/// 1. We prefer storing original indices, and sorting the `input` only once. This will save the +/// cost of sorting per round at the cost of a little bit of memory. +/// 2. The granularity of increment/decrements is determined by the number of elements in `input` +/// and their sum difference with `targeted_sum`, namely `diff = diff(sum(input), target_sum)`. +/// This value is then distributed into `per_round = diff / input.len()` and `leftover = diff % +/// round`. First, per_round is applied to all elements of input, and then we move to leftover, +/// in which case we add/subtract 1 by 1 until `leftover` is depleted. +/// +/// When the sum is less than the target, the above approach always holds. In this case, then each +/// individual element is also less than target. Thus, by adding `per_round` to each item, neither +/// of them can overflow the numeric bound of `T`. In fact, neither of the can go beyond +/// `target_sum`*. +/// +/// If sum is more than target, there is small twist. The subtraction of `per_round` +/// form each element might go below zero. In this case, we saturate and add the error to the +/// `leftover` value. This ensures that the result will always stay accurate, yet it might cause the +/// execution to become increasingly slow, since leftovers are applied one by one. +/// +/// All in all, the complicated case above is rare to happen in all substrate use cases, hence we +/// opt for it due to its simplicity. +/// +/// This function will return an error is if length of `input` cannot fit in `T`, or if `sum(input)` +/// cannot fit inside `T`. +/// +/// * This proof is used in the implementation as well. +pub fn normalize(input: &[T], targeted_sum: T) -> Result, &'static str> + where T: Clone + Copy + Ord + BaseArithmetic + Unsigned + Debug, +{ + // compute sum and return error if failed. + let mut sum = T::zero(); + for t in input.iter() { + sum = sum.checked_add(t).ok_or("sum of input cannot fit in `T`")?; + } + + // convert count and return error if failed. + let count = input.len(); + let count_t: T = count.try_into().map_err(|_| "length of `inputs` cannot fit in `T`")?; + + // Nothing to do here. + if count.is_zero() { + return Ok(Vec::::new()); + } + + let diff = targeted_sum.max(sum) - targeted_sum.min(sum); + if diff.is_zero() { + return Ok(input.to_vec()); + } + + let needs_bump = targeted_sum > sum; + let per_round = diff / count_t; + let mut leftover = diff % count_t; + + // sort output once based on diff. This will require more data transfer and saving original + // index, but we sort only twice instead: once now and once at the very end. + let mut output_with_idx = input.iter().cloned().enumerate().collect::>(); + output_with_idx.sort_unstable_by_key(|x| x.1); + + if needs_bump { + // must increase the values a bit. Bump from the min element. Index of minimum is now zero + // because we did a sort. If at any point the min goes greater or equal the `max_threshold`, + // we move to the next minimum. + let mut min_index = 0; + // at this threshold we move to next index. + let threshold = targeted_sum / count_t; + + if !per_round.is_zero() { + for _ in 0..count { + output_with_idx[min_index].1 = output_with_idx[min_index].1 + .checked_add(&per_round) + .expect("Proof provided in the module doc; qed."); + if output_with_idx[min_index].1 >= threshold { + min_index += 1; + min_index = min_index % count; + } + } + } + + // continue with the previous min_index + while !leftover.is_zero() { + output_with_idx[min_index].1 = output_with_idx[min_index].1 + .checked_add(&T::one()) + .expect("Proof provided in the module doc; qed."); + if output_with_idx[min_index].1 >= threshold { + min_index += 1; + min_index = min_index % count; + } + leftover -= One::one() + } + } else { + // must decrease the stakes a bit. decrement from the max element. index of maximum is now + // last. if at any point the max goes less or equal the `min_threshold`, we move to the next + // maximum. + let mut max_index = count - 1; + // at this threshold we move to next index. + let threshold = output_with_idx + .first() + .expect("length of input is greater than zero; it must have a first; qed") + .1; + + if !per_round.is_zero() { + for _ in 0..count { + output_with_idx[max_index].1 = output_with_idx[max_index].1 + .checked_sub(&per_round) + .unwrap_or_else(|| { + let remainder = per_round - output_with_idx[max_index].1; + leftover += remainder; + output_with_idx[max_index].1.saturating_sub(per_round) + }); + if output_with_idx[max_index].1 <= threshold { + max_index = max_index.checked_sub(1).unwrap_or(count - 1); + } + } + } + + // continue with the previous max_index + while !leftover.is_zero() { + if let Some(next) = output_with_idx[max_index].1.checked_sub(&One::one()) { + output_with_idx[max_index].1 = next; + if output_with_idx[max_index].1 <= threshold { + max_index = max_index.checked_sub(1).unwrap_or(count - 1); + } + leftover -= One::one() + } else { + max_index = max_index.checked_sub(1).unwrap_or(count - 1); + } + } + } + + debug_assert_eq!( + output_with_idx.iter().fold(T::zero(), |acc, (_, x)| acc + *x), + targeted_sum, + "sum({:?}) != {:?}", + output_with_idx, + targeted_sum, + ); + + // sort again based on the original index. + output_with_idx.sort_unstable_by_key(|x| x.0); + Ok(output_with_idx.into_iter().map(|(_, t)| t).collect()) +} + #[cfg(test)] -mod tests { +mod normalize_tests { use super::*; + #[test] + fn work_for_all_types() { + macro_rules! test_for { + ($type:ty) => { + assert_eq!( + normalize(vec![8 as $type, 9, 7, 10].as_ref(), 40).unwrap(), + vec![10, 10, 10, 10], + ); + } + } + // it should work for all types as long as the length of vector can be converted to T. + test_for!(u128); + test_for!(u64); + test_for!(u32); + test_for!(u16); + test_for!(u8); + } + + #[test] + fn fails_on_if_input_sum_large() { + assert!(normalize(vec![1u8; 255].as_ref(), 10).is_ok()); + assert_eq!( + normalize(vec![1u8; 256].as_ref(), 10), + Err("sum of input cannot fit in `T`"), + ); + } + + #[test] + fn does_not_fail_on_subtraction_overflow() { + assert_eq!( + normalize(vec![1u8, 100, 100].as_ref(), 10).unwrap(), + vec![1, 9, 0], + ); + assert_eq!( + normalize(vec![1u8, 8, 9].as_ref(), 1).unwrap(), + vec![0, 1, 0], + ); + } + + #[test] + fn works_for_vec() { + assert_eq!(vec![8u32, 9, 7, 10].normalize(40).unwrap(), vec![10u32, 10, 10, 10]); + } + + #[test] + fn works_for_per_thing() { + assert_eq!( + vec![ + Perbill::from_percent(33), + Perbill::from_percent(33), + Perbill::from_percent(33) + ].normalize(Perbill::one()).unwrap(), + vec![ + Perbill::from_parts(333333334), + Perbill::from_parts(333333333), + Perbill::from_parts(333333333), + ] + ); + + assert_eq!( + vec![ + Perbill::from_percent(20), + Perbill::from_percent(15), + Perbill::from_percent(30) + ].normalize(Perbill::one()).unwrap(), + vec![ + Perbill::from_parts(316666668), + Perbill::from_parts(383333332), + Perbill::from_parts(300000000), + ] + ); + } + + #[test] + fn can_work_for_peru16() { + // Peru16 is a rather special case; since inner type is exactly the same as capacity, we + // could have a situation where the sum cannot be calculated in the inner type. Calculating + // using the upper type of the per_thing should assure this to be okay. + assert_eq!( + vec![ + PerU16::from_percent(40), + PerU16::from_percent(40), + PerU16::from_percent(40), + ].normalize(PerU16::one()).unwrap(), + vec![ + PerU16::from_parts(21845), // 33% + PerU16::from_parts(21845), // 33% + PerU16::from_parts(21845), // 33% + ] + ); + } + + #[test] + fn normalize_works_all_le() { + assert_eq!( + normalize(vec![8u32, 9, 7, 10].as_ref(), 40).unwrap(), + vec![10, 10, 10, 10], + ); + + assert_eq!( + normalize(vec![7u32, 7, 7, 7].as_ref(), 40).unwrap(), + vec![10, 10, 10, 10], + ); + + assert_eq!( + normalize(vec![7u32, 7, 7, 10].as_ref(), 40).unwrap(), + vec![11, 11, 8, 10], + ); + + assert_eq!( + normalize(vec![7u32, 8, 7, 10].as_ref(), 40).unwrap(), + vec![11, 8, 11, 10], + ); + + assert_eq!( + normalize(vec![7u32, 7, 8, 10].as_ref(), 40).unwrap(), + vec![11, 11, 8, 10], + ); + } + + #[test] + fn normalize_works_some_ge() { + assert_eq!( + normalize(vec![8u32, 11, 9, 10].as_ref(), 40).unwrap(), + vec![10, 11, 9, 10], + ); + } + + #[test] + fn always_inc_min() { + assert_eq!( + normalize(vec![10u32, 7, 10, 10].as_ref(), 40).unwrap(), + vec![10, 10, 10, 10], + ); + assert_eq!( + normalize(vec![10u32, 10, 7, 10].as_ref(), 40).unwrap(), + vec![10, 10, 10, 10], + ); + assert_eq!( + normalize(vec![10u32, 10, 10, 7].as_ref(), 40).unwrap(), + vec![10, 10, 10, 10], + ); + } + + #[test] + fn normalize_works_all_ge() { + assert_eq!( + normalize(vec![12u32, 11, 13, 10].as_ref(), 40).unwrap(), + vec![10, 10, 10, 10], + ); + + assert_eq!( + normalize(vec![13u32, 13, 13, 13].as_ref(), 40).unwrap(), + vec![10, 10, 10, 10], + ); + + assert_eq!( + normalize(vec![13u32, 13, 13, 10].as_ref(), 40).unwrap(), + vec![12, 9, 9, 10], + ); + + assert_eq!( + normalize(vec![13u32, 12, 13, 10].as_ref(), 40).unwrap(), + vec![9, 12, 9, 10], + ); + + assert_eq!( + normalize(vec![13u32, 13, 12, 10].as_ref(), 40).unwrap(), + vec![9, 9, 12, 10], + ); + } +} + +#[cfg(test)] +mod threshold_compare_tests { + use super::*; + use crate::traits::Saturating; + use sp_std::cmp::Ordering; + + #[test] + fn epsilon_ord_works() { + let b = 115u32; + let e = Perbill::from_percent(10).mul_ceil(b); + + // [115 - 11,5 (103,5), 115 + 11,5 (126,5)] is all equal + assert_eq!(103u32.tcmp(&b, e), Ordering::Equal); + assert_eq!(104u32.tcmp(&b, e), Ordering::Equal); + assert_eq!(115u32.tcmp(&b, e), Ordering::Equal); + assert_eq!(120u32.tcmp(&b, e), Ordering::Equal); + assert_eq!(126u32.tcmp(&b, e), Ordering::Equal); + assert_eq!(127u32.tcmp(&b, e), Ordering::Equal); + + assert_eq!(128u32.tcmp(&b, e), Ordering::Greater); + assert_eq!(102u32.tcmp(&b, e), Ordering::Less); + } + + #[test] + fn epsilon_ord_works_with_small_epc() { + let b = 115u32; + // way less than 1 percent. threshold will be zero. Result should be same as normal ord. + let e = Perbill::from_parts(100) * b; + + // [115 - 11,5 (103,5), 115 + 11,5 (126,5)] is all equal + assert_eq!(103u32.tcmp(&b, e), 103u32.cmp(&b)); + assert_eq!(104u32.tcmp(&b, e), 104u32.cmp(&b)); + assert_eq!(115u32.tcmp(&b, e), 115u32.cmp(&b)); + assert_eq!(120u32.tcmp(&b, e), 120u32.cmp(&b)); + assert_eq!(126u32.tcmp(&b, e), 126u32.cmp(&b)); + assert_eq!(127u32.tcmp(&b, e), 127u32.cmp(&b)); + + assert_eq!(128u32.tcmp(&b, e), 128u32.cmp(&b)); + assert_eq!(102u32.tcmp(&b, e), 102u32.cmp(&b)); + } + #[test] fn peru16_rational_does_not_overflow() { // A historical example that will panic only for per_thing type that are created with // maximum capacity of their type, e.g. PerU16. let _ = PerU16::from_rational_approximation(17424870u32, 17424870); } + + #[test] + fn saturating_mul_works() { + assert_eq!(Saturating::saturating_mul(2, i32::min_value()), i32::min_value()); + assert_eq!(Saturating::saturating_mul(2, i32::max_value()), i32::max_value()); + } + + #[test] + fn saturating_pow_works() { + assert_eq!(Saturating::saturating_pow(i32::min_value(), 0), 1); + assert_eq!(Saturating::saturating_pow(i32::max_value(), 0), 1); + assert_eq!(Saturating::saturating_pow(i32::min_value(), 3), i32::min_value()); + assert_eq!(Saturating::saturating_pow(i32::min_value(), 2), i32::max_value()); + assert_eq!(Saturating::saturating_pow(i32::max_value(), 2), i32::max_value()); + } } diff --git a/primitives/arithmetic/src/per_things.rs b/primitives/arithmetic/src/per_things.rs index ad529fbf32e249ef1fb0e5838c30fce52aab4b25..f809358446017a0ce8747f3ebe2d9bf36053d97c 100644 --- a/primitives/arithmetic/src/per_things.rs +++ b/primitives/arithmetic/src/per_things.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #[cfg(feature = "std")] use serde::{Serialize, Deserialize}; @@ -20,21 +21,29 @@ use serde::{Serialize, Deserialize}; use sp_std::{ops, fmt, prelude::*, convert::TryInto}; use codec::{Encode, CompactAs}; use crate::traits::{ - SaturatedConversion, UniqueSaturatedInto, Saturating, BaseArithmetic, Bounded, Zero, + SaturatedConversion, UniqueSaturatedInto, Saturating, BaseArithmetic, Bounded, Zero, Unsigned, }; use sp_debug_derive::RuntimeDebug; +/// Get the inner type of a `PerThing`. +pub type InnerOf

=

::Inner; + +/// Get the upper type of a `PerThing`. +pub type UpperOf

=

= <

::Block as BlockT>::Hash; pub type TransactionFor

= <

::Block as BlockT>::Extrinsic; /// Type of transactions event stream for a pool. pub type TransactionStatusStreamFor

= TransactionStatusStream, BlockHash

>; +/// Transaction type for a local pool. +pub type LocalTransactionFor

= <

::Block as BlockT>::Extrinsic; /// Typical future type used in transaction pool api. pub type PoolFuture = std::pin::Pin> + Send>>; @@ -161,7 +164,7 @@ pub trait InPoolTransaction { /// Get priority of the transaction. fn priority(&self) -> &TransactionPriority; /// Get longevity of the transaction. - fn longevity(&self) ->&TransactionLongevity; + fn longevity(&self) -> &TransactionLongevity; /// Get transaction dependencies. fn requires(&self) -> &[TransactionTag]; /// Get tags that transaction provides. @@ -250,12 +253,14 @@ pub enum ChainEvent { NewBlock { /// Is this the new best block. is_new_best: bool, - /// Id of the just imported block. - id: BlockId, + /// Hash of the block. + hash: B::Hash, /// Header of the just imported block header: B::Header, - /// List of retracted blocks ordered by block number. - retracted: Vec, + /// Tree route from old best to new best parent that was calculated on import. + /// + /// If `None`, no re-org happened on import. + tree_route: Option>>, }, /// An existing block has been finalized. Finalized { @@ -270,6 +275,28 @@ pub trait MaintainedTransactionPool: TransactionPool { fn maintain(&self, event: ChainEvent) -> Pin + Send>>; } +/// Transaction pool interface for submitting local transactions that exposes a +/// blocking interface for submission. +pub trait LocalTransactionPool: Send + Sync { + /// Block type. + type Block: BlockT; + /// Transaction hash type. + type Hash: Hash + Eq + Member + Serialize; + /// Error type. + type Error: From + crate::error::IntoPoolError; + + /// Submits the given local unverified transaction to the pool blocking the + /// current thread for any necessary pre-verification. + /// NOTE: It MUST NOT be used for transactions that originate from the + /// network or RPC, since the validation is performed with + /// `TransactionSource::Local`. + fn submit_local( + &self, + at: &BlockId, + xt: LocalTransactionFor, + ) -> Result; +} + /// An abstraction for transaction pool. /// /// This trait is used by offchain calls to be able to submit transactions. @@ -288,7 +315,7 @@ pub trait OffchainSubmitTransaction: Send + Sync { ) -> Result<(), ()>; } -impl OffchainSubmitTransaction for TPool { +impl OffchainSubmitTransaction for TPool { fn submit_at( &self, at: &BlockId, @@ -300,15 +327,14 @@ impl OffchainSubmitTransaction for TPool { extrinsic ); - let result = futures::executor::block_on(self.submit_one( - &at, TransactionSource::Local, extrinsic, - )); + let result = self.submit_local(&at, extrinsic); - result.map(|_| ()) - .map_err(|e| log::warn!( + result.map(|_| ()).map_err(|e| { + log::warn!( target: "txpool", "(offchain call) Error submitting a transaction to the pool: {:?}", e - )) + ) + }) } } diff --git a/primitives/transaction-pool/src/runtime_api.rs b/primitives/transaction-pool/src/runtime_api.rs index fa2e51653b284fcde5ca6362017c4ec813c48a0a..9080c023f58909cf739f87ce60fe917074fc9776 100644 --- a/primitives/transaction-pool/src/runtime_api.rs +++ b/primitives/transaction-pool/src/runtime_api.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Tagged Transaction Queue Runtime API. diff --git a/primitives/trie/Cargo.toml b/primitives/trie/Cargo.toml index 3876f4652624be83193661e83ea74f85c108920a..4807c5ae0a284036c4cd277fe9fb624d1d68e36b 100644 --- a/primitives/trie/Cargo.toml +++ b/primitives/trie/Cargo.toml @@ -1,33 +1,36 @@ [package] name = "sp-trie" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] description = "Patricia trie stuff using a parity-scale-codec node format" repository = "https://github.com/paritytech/substrate/" -license = "GPL-3.0" +license = "Apache-2.0" edition = "2018" homepage = "https://substrate.dev" documentation = "https://docs.rs/sp-trie" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [[bench]] name = "bench" harness = false [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../std" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../std" } hash-db = { version = "0.15.2", default-features = false } -trie-db = { version = "0.20.0", default-features = false } +trie-db = { version = "0.22.0", default-features = false } trie-root = { version = "0.16.0", default-features = false } -memory-db = { version = "0.20.0", default-features = false } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../core" } +memory-db = { version = "0.24.0", default-features = false } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../core" } [dev-dependencies] -trie-bench = "0.21.0" +trie-bench = "0.24.0" trie-standardmap = "0.15.2" criterion = "0.2.11" hex-literal = "0.2.1" -sp-runtime = { version = "2.0.0-alpha.5", path = "../runtime" } +sp-runtime = { version = "2.0.0-rc4", path = "../runtime" } [features] default = ["std"] @@ -40,6 +43,3 @@ std = [ "trie-root/std", "sp-core/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/trie/src/lib.rs b/primitives/trie/src/lib.rs index 80570a9792b107bfdfa14cd4fe6988c5088fbebd..7d1879a4f9f749a4bd3521cb72cc36641c7082ff 100644 --- a/primitives/trie/src/lib.rs +++ b/primitives/trie/src/lib.rs @@ -24,9 +24,7 @@ mod node_codec; mod storage_proof; mod trie_stream; -use sp_std::boxed::Box; -use sp_std::marker::PhantomData; -use sp_std::vec::Vec; +use sp_std::{boxed::Box, marker::PhantomData, vec::Vec, borrow::Borrow}; use hash_db::{Hasher, Prefix}; use trie_db::proof::{generate_proof, verify_proof}; pub use trie_db::proof::VerifyError; @@ -53,6 +51,7 @@ pub struct Layout(sp_std::marker::PhantomData); impl TrieLayout for Layout { const USE_EXTENSION: bool = false; + const ALLOW_EMPTY: bool = true; type Hash = H; type Codec = NodeCodec; } @@ -86,8 +85,6 @@ pub trait AsHashDB: hash_db::AsHashDB {} impl> AsHashDB for T {} /// Reexport from `hash_db`, with genericity set for `Hasher` trait. pub type HashDB<'a, H> = dyn hash_db::HashDB + 'a; -/// Reexport from `hash_db`, with genericity set for key only. -pub type PlainDB<'a, K> = dyn hash_db::PlainDB + 'a; /// Reexport from `hash_db`, with genericity set for `Hasher` trait. /// This uses a `KeyFunction` for prefixing keys internally (avoiding /// key conflict for non random keys). @@ -164,23 +161,24 @@ pub fn verify_trie_proof<'a, L: TrieConfiguration, I, K, V>( } /// Determine a trie root given a hash DB and delta values. -pub fn delta_trie_root( +pub fn delta_trie_root( db: &mut DB, mut root: TrieHash, delta: I ) -> Result, Box>> where - I: IntoIterator)>, - A: AsRef<[u8]> + Ord, - B: AsRef<[u8]>, + I: IntoIterator, + A: Borrow<[u8]>, + B: Borrow>, + V: Borrow<[u8]>, DB: hash_db::HashDB, { { let mut trie = TrieDBMut::::from_existing(&mut *db, &mut root)?; for (key, change) in delta { - match change { - Some(val) => trie.insert(key.as_ref(), val.as_ref())?, - None => trie.remove(key.as_ref())?, + match change.borrow() { + Some(val) => trie.insert(key.borrow(), val.borrow())?, + None => trie.remove(key.borrow())?, }; } } @@ -211,9 +209,8 @@ pub fn read_trie_value_with< Ok(TrieDB::::new(&*db, root)?.get_with(key, query).map(|x| x.map(|val| val.to_vec()))?) } -/// Determine the default child trie root. -pub fn default_child_trie_root( - _storage_key: &[u8], +/// Determine the empty child trie root. +pub fn empty_child_trie_root( ) -> ::Out { L::trie_root::<_, Vec, Vec>(core::iter::empty()) } @@ -221,7 +218,6 @@ pub fn default_child_trie_root( /// Determine a child trie root given its ordered contents, closed form. H is the default hasher, /// but a generic implementation may ignore this type parameter and use other hashers. pub fn child_trie_root( - _storage_key: &[u8], input: I, ) -> ::Out where @@ -234,20 +230,19 @@ pub fn child_trie_root( /// Determine a child trie root given a hash DB and delta values. H is the default hasher, /// but a generic implementation may ignore this type parameter and use other hashers. -pub fn child_delta_trie_root( - _storage_key: &[u8], +pub fn child_delta_trie_root( keyspace: &[u8], db: &mut DB, root_data: RD, delta: I, ) -> Result<::Out, Box>> where - I: IntoIterator)>, - A: AsRef<[u8]> + Ord, - B: AsRef<[u8]>, + I: IntoIterator, + A: Borrow<[u8]>, + B: Borrow>, + V: Borrow<[u8]>, RD: AsRef<[u8]>, DB: hash_db::HashDB - + hash_db::PlainDB, trie_db::DBValue>, { let mut root = TrieHash::::default(); // root is fetched from DB, not writable by runtime, so it's always valid. @@ -258,9 +253,9 @@ pub fn child_delta_trie_root( let mut trie = TrieDBMut::::from_existing(&mut db, &mut root)?; for (key, change) in delta { - match change { - Some(val) => trie.insert(key.as_ref(), val.as_ref())?, - None => trie.remove(key.as_ref())?, + match change.borrow() { + Some(val) => trie.insert(key.borrow(), val.borrow())?, + None => trie.remove(key.borrow())?, }; } } @@ -270,7 +265,6 @@ pub fn child_delta_trie_root( /// Call `f` for all keys in a child trie. pub fn for_keys_in_child_trie( - _storage_key: &[u8], keyspace: &[u8], db: &DB, root_slice: &[u8], @@ -278,7 +272,6 @@ pub fn for_keys_in_child_trie( ) -> Result<(), Box>> where DB: hash_db::HashDBRef - + hash_db::PlainDBRef, trie_db::DBValue>, { let mut root = TrieHash::::default(); // root is fetched from DB, not writable by runtime, so it's always valid. @@ -321,7 +314,6 @@ pub fn record_all_keys( /// Read a value from the child trie. pub fn read_child_trie_value( - _storage_key: &[u8], keyspace: &[u8], db: &DB, root_slice: &[u8], @@ -329,7 +321,6 @@ pub fn read_child_trie_value( ) -> Result>, Box>> where DB: hash_db::HashDBRef - + hash_db::PlainDBRef, trie_db::DBValue>, { let mut root = TrieHash::::default(); // root is fetched from DB, not writable by runtime, so it's always valid. @@ -341,7 +332,6 @@ pub fn read_child_trie_value( /// Read a value from the child trie with given query. pub fn read_child_trie_value_with, DB>( - _storage_key: &[u8], keyspace: &[u8], db: &DB, root_slice: &[u8], @@ -350,7 +340,6 @@ pub fn read_child_trie_value_with Result>, Box>> where DB: hash_db::HashDBRef - + hash_db::PlainDBRef, trie_db::DBValue>, { let mut root = TrieHash::::default(); // root is fetched from DB, not writable by runtime, so it's always valid. diff --git a/primitives/utils/Cargo.toml b/primitives/utils/Cargo.toml index 97e5ce1d9b618c2aa250ffd7054f4dbbc6165f14..96c7825515ec54374705711503fcfcc075cd8645 100644 --- a/primitives/utils/Cargo.toml +++ b/primitives/utils/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-utils" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "I/O for Substrate runtimes" @@ -13,6 +13,7 @@ futures = "0.3.4" futures-core = "0.3.4" lazy_static = "1.4.0" prometheus = "0.8.0" +futures-timer = "3.0.2" [features] default = ["metered"] diff --git a/primitives/utils/src/lib.rs b/primitives/utils/src/lib.rs index 385a9b6689896102d5e43fc0eda53bb170f0443c..77bcd096561b45befcee7f80a0611108ce756830 100644 --- a/primitives/utils/src/lib.rs +++ b/primitives/utils/src/lib.rs @@ -1,20 +1,22 @@ -// Copyright 2020 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. +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Utilities Primitives for Substrate pub mod metrics; -pub mod mpsc; \ No newline at end of file +pub mod mpsc; +pub mod status_sinks; diff --git a/primitives/utils/src/metrics.rs b/primitives/utils/src/metrics.rs index 160714fdca1cd8a6bc2864a38fead5bf7fa4cf56..a66589b5927fe2fa6386f5f2024e0e342f665825 100644 --- a/primitives/utils/src/metrics.rs +++ b/primitives/utils/src/metrics.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Metering primitives and globals @@ -22,8 +23,8 @@ use prometheus::{ core::{ AtomicU64, GenericGauge, GenericCounter }, }; -#[cfg(features = "metered")] -use prometheus::{core::GenericGaugeVec, Opts}; +#[cfg(feature = "metered")] +use prometheus::{core::GenericCounterVec, Opts}; lazy_static! { @@ -36,9 +37,9 @@ lazy_static! { ).expect("Creating of statics doesn't fail. qed"); } -#[cfg(features = "metered")] +#[cfg(feature = "metered")] lazy_static! { - pub static ref UNBOUNDED_CHANNELS_COUNTER : GenericGaugeVec = GenericGaugeVec::new( + pub static ref UNBOUNDED_CHANNELS_COUNTER : GenericCounterVec = GenericCounterVec::new( Opts::new("unbounded_channel_len", "Items in each mpsc::unbounded instance"), &["entity", "action"] // 'name of channel, send|received|dropped ).expect("Creating of statics doesn't fail. qed"); @@ -51,7 +52,7 @@ pub fn register_globals(registry: &Registry) -> Result<(), PrometheusError> { registry.register(Box::new(TOKIO_THREADS_ALIVE.clone()))?; registry.register(Box::new(TOKIO_THREADS_TOTAL.clone()))?; - #[cfg(features = "metered")] + #[cfg(feature = "metered")] registry.register(Box::new(UNBOUNDED_CHANNELS_COUNTER.clone()))?; Ok(()) diff --git a/primitives/utils/src/mpsc.rs b/primitives/utils/src/mpsc.rs index 42fb287c18d892ea204b60131dbea20c9f7ee43c..70baa006bdcdc0d86b99aec71859361806f9044c 100644 --- a/primitives/utils/src/mpsc.rs +++ b/primitives/utils/src/mpsc.rs @@ -1,22 +1,23 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Features to meter unbounded channels -#[cfg(not(features = "metered"))] +#[cfg(not(feature = "metered"))] mod inner { // just aliased, non performance implications use futures::channel::mpsc::{self, UnboundedReceiver, UnboundedSender}; @@ -30,22 +31,29 @@ mod inner { } -#[cfg(features = "metered")] +#[cfg(feature = "metered")] mod inner { //tracing implementation use futures::channel::mpsc::{self, UnboundedReceiver, UnboundedSender, TryRecvError, TrySendError, SendError }; - use futures::{sink::Sink, task::{Poll, Context}, stream::Stream}; + use futures::{sink::Sink, task::{Poll, Context}, stream::{Stream, FusedStream}}; use std::pin::Pin; use crate::metrics::UNBOUNDED_CHANNELS_COUNTER; /// Wrapper Type around `UnboundedSender` that increases the global /// measure when a message is added - #[derive(Debug, Clone)] + #[derive(Debug)] pub struct TracingUnboundedSender(&'static str, UnboundedSender); + // Strangely, deriving `Clone` requires that `T` is also `Clone`. + impl Clone for TracingUnboundedSender { + fn clone(&self) -> Self { + Self(self.0, self.1.clone()) + } + } + /// Wrapper Type around `UnboundedReceiver` that decreases the global /// measure when a message is polled #[derive(Debug)] @@ -87,7 +95,7 @@ mod inner { /// Proxy function to mpsc::UnboundedSender pub fn unbounded_send(&self, msg: T) -> Result<(), TrySendError> { self.1.unbounded_send(msg).map(|s|{ - UNBOUNDED_CHANNELS_COUNTER.with_label_values(&[self.0, &"send"]).incr(); + UNBOUNDED_CHANNELS_COUNTER.with_label_values(&[self.0, &"send"]).inc(); s }) } @@ -103,13 +111,19 @@ mod inner { fn consume(&mut self) { // consume all items, make sure to reflect the updated count let mut count = 0; - while let Ok(Some(..)) = self.try_next() { - count += 1; - } + loop { + if self.1.is_terminated() { + break; + } + match self.try_next() { + Ok(Some(..)) => count += 1, + _ => break + } + } // and discount the messages if count > 0 { - UNBOUNDED_CHANNELS_COUNTER.with_label_values(&[self.0, &"dropped"]).incr_by(count); + UNBOUNDED_CHANNELS_COUNTER.with_label_values(&[self.0, &"dropped"]).inc_by(count); } } @@ -126,7 +140,7 @@ mod inner { pub fn try_next(&mut self) -> Result, TryRecvError> { self.1.try_next().map(|s| { if s.is_some() { - UNBOUNDED_CHANNELS_COUNTER.with_label_values(&[self.0, &"received"]).incr(); + UNBOUNDED_CHANNELS_COUNTER.with_label_values(&[self.0, &"received"]).inc(); } s }) @@ -152,7 +166,7 @@ mod inner { match Pin::new(&mut s.1).poll_next(cx) { Poll::Ready(msg) => { if msg.is_some() { - UNBOUNDED_CHANNELS_COUNTER.with_label_values(&[self.0, "received"]).incr(); + UNBOUNDED_CHANNELS_COUNTER.with_label_values(&[s.0, "received"]).inc(); } Poll::Ready(msg) } @@ -163,6 +177,11 @@ mod inner { } } + impl FusedStream for TracingUnboundedReceiver { + fn is_terminated(&self) -> bool { + self.1.is_terminated() + } + } impl Sink for TracingUnboundedSender { type Error = SendError; diff --git a/primitives/utils/src/status_sinks.rs b/primitives/utils/src/status_sinks.rs new file mode 100644 index 0000000000000000000000000000000000000000..65a560af4eaa52a8eb3fa49cd0d5e6bc38527be7 --- /dev/null +++ b/primitives/utils/src/status_sinks.rs @@ -0,0 +1,207 @@ +// Copyright 2019-2020 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::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; +use futures::{prelude::*, lock::Mutex}; +use futures_timer::Delay; +use std::{pin::Pin, task::{Poll, Context}, time::Duration}; + +/// 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 { + /// Should only be locked by `next`. + inner: Mutex>, + /// Sending side of `Inner::entries_rx`. + entries_tx: TracingUnboundedSender>, +} + +struct Inner { + /// The actual entries of the list. + entries: stream::FuturesUnordered>, + /// Receives new entries and puts them in `entries`. + entries_rx: TracingUnboundedReceiver>, +} + +struct YieldAfter { + delay: Delay, + interval: Duration, + sender: Option>, +} + +impl StatusSinks { + /// Builds a new empty collection. + pub fn new() -> StatusSinks { + let (entries_tx, entries_rx) = tracing_unbounded("status-sinks-entries"); + + StatusSinks { + inner: Mutex::new(Inner { + entries: stream::FuturesUnordered::new(), + entries_rx, + }), + entries_tx, + } + } + + /// Adds a sender to the collection. + /// + /// The `interval` is the time period between two pushes on the sender. + pub fn push(&self, interval: Duration, sender: TracingUnboundedSender) { + let _ = self.entries_tx.unbounded_send(YieldAfter { + delay: Delay::new(interval), + interval, + sender: Some(sender), + }); + } + + /// Waits until one of the sinks is ready, then returns an object that can be used to send + /// an element on said sink. + /// + /// If the object isn't used to send an element, the slot is skipped. + pub async fn next(&self) -> ReadySinkEvent<'_, T> { + // This is only ever locked by `next`, which means that one `next` at a time can run. + let mut inner = self.inner.lock().await; + let inner = &mut *inner; + + loop { + // Future that produces the next ready entry in `entries`, or doesn't produce anything if + // the list is empty. + let next_ready_entry = { + let entries = &mut inner.entries; + async move { + if let Some(v) = entries.next().await { + v + } else { + loop { + futures::pending!() + } + } + } + }; + + futures::select!{ + new_entry = inner.entries_rx.next() => { + if let Some(new_entry) = new_entry { + inner.entries.push(new_entry); + } + }, + (sender, interval) = next_ready_entry.fuse() => { + return ReadySinkEvent { + sinks: self, + sender: Some(sender), + interval, + } + } + } + } + } +} + +/// One of the sinks is ready. +#[must_use] +pub struct ReadySinkEvent<'a, T> { + sinks: &'a StatusSinks, + sender: Option>, + interval: Duration, +} + +impl<'a, T> ReadySinkEvent<'a, T> { + /// Sends an element on the sender. + pub fn send(mut self, element: T) { + if let Some(sender) = self.sender.take() { + if sender.unbounded_send(element).is_ok() { + let _ = self.sinks.entries_tx.unbounded_send(YieldAfter { + // Note that since there's a small delay between the moment a task is + // woken up and the moment it is polled, the period is actually not + // `interval` but `interval + `. We ignore this problem in + // practice. + delay: Delay::new(self.interval), + interval: self.interval, + sender: Some(sender), + }); + } + } + } +} + +impl<'a, T> Drop for ReadySinkEvent<'a, T> { + fn drop(&mut self) { + if let Some(sender) = self.sender.take() { + if sender.is_closed() { + return; + } + + let _ = self.sinks.entries_tx.unbounded_send(YieldAfter { + delay: Delay::new(self.interval), + interval: self.interval, + sender: Some(sender), + }); + } + } +} + +impl futures::Future for YieldAfter { + type Output = (TracingUnboundedSender, Duration); + + fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { + let this = Pin::into_inner(self); + + match Pin::new(&mut this.delay).poll(cx) { + Poll::Pending => Poll::Pending, + Poll::Ready(()) => { + let sender = this.sender.take() + .expect("sender is always Some unless the future is finished; qed"); + Poll::Ready((sender, this.interval)) + } + } + } +} + +#[cfg(test)] +mod tests { + use crate::mpsc::tracing_unbounded; + use super::StatusSinks; + use futures::prelude::*; + use std::time::Duration; + + #[test] + fn works() { + // We're not testing that the `StatusSink` properly enforces an order in the intervals, as + // this easily causes test failures on busy CPUs. + + let status_sinks = StatusSinks::new(); + + let (tx, rx) = tracing_unbounded("test"); + status_sinks.push(Duration::from_millis(100), tx); + + let mut val_order = 5; + + futures::executor::block_on(futures::future::select( + Box::pin(async move { + loop { + let ev = status_sinks.next().await; + val_order += 1; + ev.send(val_order); + } + }), + Box::pin(async { + let items: Vec = rx.take(3).collect().await; + assert_eq!(items, [6, 7, 8]); + }) + )); + } +} diff --git a/primitives/version/Cargo.toml b/primitives/version/Cargo.toml index 726d064642fb355a9d037ac840c44a5708db2850..181b793bd57afeb8f9279fc6652302c7b6bb9e65 100644 --- a/primitives/version/Cargo.toml +++ b/primitives/version/Cargo.toml @@ -1,21 +1,24 @@ [package] name = "sp-version" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Version module for the Substrate runtime; Provides a function that returns the runtime version." documentation = "https://docs.rs/sp-version" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] impl-serde = { version = "0.2.3", optional = true } serde = { version = "1.0.101", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../std" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../runtime" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../std" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../runtime" } [features] default = ["std"] @@ -26,6 +29,3 @@ std = [ "sp-std/std", "sp-runtime/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/version/src/lib.rs b/primitives/version/src/lib.rs index 0534f87490868469294dbab078afeb2790155a1f..133d0497a2584ff936f19d48d2dac31d9405f534 100644 --- a/primitives/version/src/lib.rs +++ b/primitives/version/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Version module for the Substrate runtime; Provides a function that returns the runtime version. @@ -93,17 +94,29 @@ pub struct RuntimeVersion { ) )] pub apis: ApisVec, + + /// All existing dispatches are fully compatible when this number doesn't change. If this + /// number changes, then `spec_version` must change, also. + /// + /// This number must change when an existing dispatchable (module ID, dispatch ID) is changed, + /// either through an alteration in its user-level semantics, a parameter added/removed/changed, + /// a dispatchable being removed, a module being removed, or a dispatchable/module changing its + /// index. + /// + /// It need *not* change when a new module is added or when a dispatchable is added. + pub transaction_version: u32, } #[cfg(feature = "std")] impl fmt::Display for RuntimeVersion { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}-{}:{}({}-{})", + write!(f, "{}-{} ({}-{}.tx{}.au{})", self.spec_name, self.spec_version, - self.authoring_version, self.impl_name, - self.impl_version + self.impl_version, + self.transaction_version, + self.authoring_version, ) } } diff --git a/primitives/wasm-interface/Cargo.toml b/primitives/wasm-interface/Cargo.toml index 4a35d5b5180ff07529762e003370e7d2f21eef2b..8b32cde969c67e0932ce88e0b0fc96d865967550 100644 --- a/primitives/wasm-interface/Cargo.toml +++ b/primitives/wasm-interface/Cargo.toml @@ -1,23 +1,23 @@ [package] name = "sp-wasm-interface" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Types and traits for interfacing between the host and the wasm runtime." documentation = "https://docs.rs/sp-wasm-interface" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] wasmi = { version = "0.6.2", optional = true } impl-trait-for-tuples = "0.1.2" -sp-std = { version = "2.0.0-alpha.5", path = "../std", default-features = false } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0-rc4", path = "../std", default-features = false } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } [features] default = [ "std" ] std = [ "wasmi", "sp-std/std", "codec/std" ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/wasm-interface/src/lib.rs b/primitives/wasm-interface/src/lib.rs index eda2ebb1b527ae876d3275608e20aec04ba5223c..d3ca4ecb5e937c934ed5d9afb1c3de3c96b85c41 100644 --- a/primitives/wasm-interface/src/lib.rs +++ b/primitives/wasm-interface/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Types and traits for interfacing between the host and the wasm runtime. @@ -119,7 +120,7 @@ mod private { /// Something that can be wrapped in a wasm `Pointer`. /// /// This trait is sealed. -pub trait PointerType: Sized { +pub trait PointerType: Sized + private::Sealed { /// The size of the type in wasm. const SIZE: u32 = mem::size_of::() as u32; } diff --git a/primitives/wasm-interface/src/wasmi_impl.rs b/primitives/wasm-interface/src/wasmi_impl.rs index dea8519b711a7ef88a863bec5457a15116381546..5931671c97ed49afba78dc88624aa9ef4f570f25 100644 --- a/primitives/wasm-interface/src/wasmi_impl.rs +++ b/primitives/wasm-interface/src/wasmi_impl.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Implementation of conversions between Substrate and wasmi types. diff --git a/test-utils/Cargo.toml b/test-utils/Cargo.toml index b8c9f9bd606059b73adb080f68c78dda3e8026a5..f67f1560c1578a646828f12fdd2bf3c20f976fe9 100644 --- a/test-utils/Cargo.toml +++ b/test-utils/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "substrate-test-utils" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" diff --git a/test-utils/client/Cargo.toml b/test-utils/client/Cargo.toml index ec87e7cd168f05585f9f70a25793fc4840af5017..04fd898a70fd3badadefee10872a1a59fd9c1536 100644 --- a/test-utils/client/Cargo.toml +++ b/test-utils/client/Cargo.toml @@ -1,27 +1,33 @@ [package] name = "substrate-test-client" -version = "2.0.0-dev" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" publish = false +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sc-client-api = { version = "2.0.0-alpha.5", path = "../../client/api" } -sc-client = { version = "0.8.0-alpha.5", path = "../../client/" } -sc-client-db = { version = "0.8.0-alpha.5", features = ["test-helpers"], path = "../../client/db" } -sp-consensus = { version = "0.8.0-alpha.5", path = "../../primitives/consensus/common" } -sc-executor = { version = "0.8.0-alpha.5", path = "../../client/executor" } +codec = { package = "parity-scale-codec", version = "1.3.1" } futures = "0.3.4" +futures01 = { package = "futures", version = "0.1.29" } hash-db = "0.15.2" -sp-keyring = { version = "2.0.0-alpha.5", path = "../../primitives/keyring" } -codec = { package = "parity-scale-codec", version = "1.3.0" } -sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../primitives/runtime" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../primitives/blockchain" } -sp-state-machine = { version = "0.8.0-alpha.5", path = "../../primitives/state-machine" } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +hex = "0.4" +serde = "1.0.55" +serde_json = "1.0.55" +sc-client-api = { version = "2.0.0-rc4", path = "../../client/api" } +sc-client-db = { version = "0.8.0-rc4", features = ["test-helpers"], path = "../../client/db" } +sc-consensus = { version = "0.8.0-rc4", path = "../../client/consensus/common" } +sc-executor = { version = "0.8.0-rc4", path = "../../client/executor" } +sc-light = { version = "2.0.0-rc4", path = "../../client/light" } +sc-service = { version = "0.8.0-rc4", default-features = false, features = ["test-helpers"], path = "../../client/service" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../primitives/blockchain" } +sp-consensus = { version = "0.8.0-rc4", path = "../../primitives/consensus/common" } +sp-core = { version = "2.0.0-rc4", path = "../../primitives/core" } +sp-keyring = { version = "2.0.0-rc4", path = "../../primitives/keyring" } +sp-runtime = { version = "2.0.0-rc4", path = "../../primitives/runtime" } +sp-state-machine = { version = "0.8.0-rc4", path = "../../primitives/state-machine" } diff --git a/test-utils/client/src/client_ext.rs b/test-utils/client/src/client_ext.rs index 6d6b539483e3999ae79a9f78f3b7fdc6381230b1..a74bd3258ef0f97782fbba780e8c01d26124f480 100644 --- a/test-utils/client/src/client_ext.rs +++ b/test-utils/client/src/client_ext.rs @@ -1,23 +1,25 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Client extension for tests. -use sc_client::{self, Client}; +use sc_service::client::Client; use sc_client_api::backend::Finalizer; +use sc_client_api::client::BlockBackend; use sp_consensus::{ BlockImportParams, BlockImport, BlockOrigin, Error as ConsensusError, ForkChoiceStrategy, @@ -64,7 +66,7 @@ pub trait ClientBlockImportExt: Sized { impl ClientExt for Client where B: sc_client_api::backend::Backend, - E: sc_client::CallExecutor + 'static, + E: sc_client_api::CallExecutor + 'static, Self: BlockImport, Block: BlockT, { diff --git a/test-utils/client/src/lib.rs b/test-utils/client/src/lib.rs index d04e85fd10c2330161dc3636deb66cc4ba26b710..fd5b0e29192ae16a917a1a9762040cbba8ad8c47 100644 --- a/test-utils/client/src/lib.rs +++ b/test-utils/client/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Client testing utilities. @@ -20,7 +21,6 @@ pub mod client_ext; -pub use sc_client::{blockchain, self}; pub use sc_client_api::{ execution_extensions::{ExecutionStrategies, ExecutionExtensions}, ForkBlocks, BadBlocks, CloneableSpawn, @@ -36,16 +36,21 @@ pub use sp_keyring::{ pub use sp_core::{traits::BareCryptoStorePtr, tasks::executor as tasks_executor}; pub use sp_runtime::{Storage, StorageChild}; pub use sp_state_machine::ExecutionStrategy; +pub use sc_service::{RpcHandlers, RpcSession, client}; pub use self::client_ext::{ClientExt, ClientBlockImportExt}; +use std::pin::Pin; use std::sync::Arc; -use std::collections::HashMap; -use sp_core::storage::{well_known_keys, ChildInfo}; -use sp_runtime::traits::{Block as BlockT, BlakeTwo256}; -use sc_client::LocalCallExecutor; +use std::collections::{HashSet, HashMap}; +use futures::{future::{Future, FutureExt}, stream::StreamExt}; +use serde::Deserialize; +use sp_core::storage::ChildInfo; +use sp_runtime::{OpaqueExtrinsic, codec::Encode, traits::{Block as BlockT, BlakeTwo256}}; +use sc_service::client::{LocalCallExecutor, ClientConfig}; +use sc_client_api::BlockchainEvents; /// Test client light database backend. -pub type LightBackend = sc_client::light::backend::Backend< +pub type LightBackend = sc_light::Backend< sc_client_db::light::LightStorage, BlakeTwo256, >; @@ -66,6 +71,8 @@ impl GenesisInit for () { pub struct TestClientBuilder { execution_strategies: ExecutionStrategies, genesis_init: G, + /// The key is an unprefixed storage key, this only contains + /// default child trie content. child_storage_extension: HashMap, StorageChild>, backend: Arc, _executor: std::marker::PhantomData, @@ -129,17 +136,17 @@ impl TestClientBuilder, - child_key: impl AsRef<[u8]>, - child_info: ChildInfo, value: impl AsRef<[u8]>, ) -> Self { - let entry = self.child_storage_extension.entry(key.as_ref().to_vec()) + let storage_key = child_info.storage_key(); + let entry = self.child_storage_extension.entry(storage_key.to_vec()) .or_insert_with(|| StorageChild { data: Default::default(), - child_info: child_info.to_owned(), + child_info: child_info.clone(), }); - entry.data.insert(child_key.as_ref().to_vec(), value.as_ref().to_vec()); + entry.data.insert(key.as_ref().to_vec(), value.as_ref().to_vec()); self } @@ -173,15 +180,15 @@ impl TestClientBuilder ( - sc_client::Client< + client::Client< Backend, Executor, Block, RuntimeApi, >, - sc_client::LongestChain, + sc_consensus::LongestChain, ) where - Executor: sc_client::CallExecutor + 'static, + Executor: sc_client_api::CallExecutor + 'static, Backend: sc_client_api::backend::Backend, { let storage = { @@ -189,8 +196,8 @@ impl TestClientBuilder TestClientBuilder TestClientBuilder TestClientBuilder TestClientBuilder< Block, - sc_client::LocalCallExecutor>, + client::LocalCallExecutor>, Backend, G, > { @@ -231,13 +239,13 @@ impl TestClientBuilder< self, executor: I, ) -> ( - sc_client::Client< + client::Client< Backend, - sc_client::LocalCallExecutor>, + client::LocalCallExecutor>, Block, RuntimeApi >, - sc_client::LongestChain, + sc_consensus::LongestChain, ) where I: Into>>, E: sc_executor::NativeExecutionDispatch + 'static, @@ -246,8 +254,193 @@ impl TestClientBuilder< let executor = executor.into().unwrap_or_else(|| NativeExecutor::new(WasmExecutionMethod::Interpreted, None, 8) ); - let executor = LocalCallExecutor::new(self.backend.clone(), executor, tasks_executor()); + let executor = LocalCallExecutor::new(self.backend.clone(), executor, tasks_executor(), Default::default()); self.build_with_executor(executor) } } + +/// The output of an RPC transaction. +pub struct RpcTransactionOutput { + /// The output string of the transaction if any. + pub result: Option, + /// The session object. + pub session: RpcSession, + /// An async receiver if data will be returned via a callback. + pub receiver: futures01::sync::mpsc::Receiver, +} + +impl std::fmt::Debug for RpcTransactionOutput { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "RpcTransactionOutput {{ result: {:?}, session, receiver }}", self.result) + } +} + +/// An error for when the RPC call fails. +#[derive(Deserialize, Debug)] +pub struct RpcTransactionError { + /// A Number that indicates the error type that occurred. + pub code: i64, + /// A String providing a short description of the error. + pub message: String, + /// A Primitive or Structured value that contains additional information about the error. + pub data: Option, +} + +impl std::fmt::Display for RpcTransactionError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + std::fmt::Debug::fmt(self, f) + } +} + +/// An extension trait for `RpcHandlers`. +pub trait RpcHandlersExt { + /// Send a transaction through the RpcHandlers. + fn send_transaction( + &self, + extrinsic: OpaqueExtrinsic, + ) -> Pin> + Send>>; +} + +impl RpcHandlersExt for RpcHandlers { + fn send_transaction( + &self, + extrinsic: OpaqueExtrinsic, + ) -> Pin> + Send>> { + let (tx, rx) = futures01::sync::mpsc::channel(0); + let mem = RpcSession::new(tx.into()); + Box::pin(self + .rpc_query( + &mem, + &format!( + r#"{{ + "jsonrpc": "2.0", + "method": "author_submitExtrinsic", + "params": ["0x{}"], + "id": 0 + }}"#, + hex::encode(extrinsic.encode()) + ), + ) + .map(move |result| parse_rpc_result(result, mem, rx)) + ) + } +} + +pub(crate) fn parse_rpc_result( + result: Option, + session: RpcSession, + receiver: futures01::sync::mpsc::Receiver, +) -> Result { + if let Some(ref result) = result { + let json: serde_json::Value = serde_json::from_str(result) + .expect("the result can only be a JSONRPC string; qed"); + let error = json + .as_object() + .expect("JSON result is always an object; qed") + .get("error"); + + if let Some(error) = error { + return Err( + serde_json::from_value(error.clone()) + .expect("the JSONRPC result's error is always valid; qed") + ) + } + } + + Ok(RpcTransactionOutput { + result, + session, + receiver, + }) +} + +/// An extension trait for `BlockchainEvents`. +pub trait BlockchainEventsExt +where + C: BlockchainEvents, + B: BlockT, +{ + /// Wait for `count` blocks to be imported in the node and then exit. This function will not return if no blocks + /// are ever created, thus you should restrict the maximum amount of time of the test execution. + fn wait_for_blocks(&self, count: usize) -> Pin + Send>>; +} + +impl BlockchainEventsExt for C +where + C: BlockchainEvents, + B: BlockT, +{ + fn wait_for_blocks(&self, count: usize) -> Pin + Send>> { + assert!(count > 0, "'count' argument must be greater than 0"); + + let mut import_notification_stream = self.import_notification_stream(); + let mut blocks = HashSet::new(); + + Box::pin(async move { + while let Some(notification) = import_notification_stream.next().await { + blocks.insert(notification.hash); + if blocks.len() == count { + break; + } + } + }) + } +} + +#[cfg(test)] +mod tests { + use sc_service::RpcSession; + + fn create_session_and_receiver() -> (RpcSession, futures01::sync::mpsc::Receiver) { + let (tx, rx) = futures01::sync::mpsc::channel(0); + let mem = RpcSession::new(tx.into()); + + (mem, rx) + } + + #[test] + fn parses_error_properly() { + let (mem, rx) = create_session_and_receiver(); + assert!(super::parse_rpc_result(None, mem, rx).is_ok()); + + let (mem, rx) = create_session_and_receiver(); + assert!( + super::parse_rpc_result(Some(r#"{ + "jsonrpc": "2.0", + "result": 19, + "id": 1 + }"#.to_string()), mem, rx) + .is_ok(), + ); + + let (mem, rx) = create_session_and_receiver(); + let error = super::parse_rpc_result(Some(r#"{ + "jsonrpc": "2.0", + "error": { + "code": -32601, + "message": "Method not found" + }, + "id": 1 + }"#.to_string()), mem, rx) + .unwrap_err(); + assert_eq!(error.code, -32601); + assert_eq!(error.message, "Method not found"); + assert!(error.data.is_none()); + + let (mem, rx) = create_session_and_receiver(); + let error = super::parse_rpc_result(Some(r#"{ + "jsonrpc": "2.0", + "error": { + "code": -32601, + "message": "Method not found", + "data": 42 + }, + "id": 1 + }"#.to_string()), mem, rx) + .unwrap_err(); + assert_eq!(error.code, -32601); + assert_eq!(error.message, "Method not found"); + assert!(error.data.is_some()); + } +} diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml index be22747ea69166d91f83102e79171c18c8e5441a..f29451dd1130a2e7f4824b4b4a9825dcf19cce77 100644 --- a/test-utils/runtime/Cargo.toml +++ b/test-utils/runtime/Cargo.toml @@ -1,52 +1,58 @@ [package] name = "substrate-test-runtime" -version = "2.0.0-dev" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" build = "build.rs" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" publish = false +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-application-crypto = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/application-crypto" } -sp-consensus-aura = { version = "0.8.0-alpha.5", default-features = false, path = "../../primitives/consensus/aura" } -sp-consensus-babe = { version = "0.8.0-alpha.5", default-features = false, path = "../../primitives/consensus/babe" } -sp-block-builder = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/block-builder" } +sp-application-crypto = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/application-crypto" } +sp-consensus-aura = { version = "0.8.0-rc4", default-features = false, path = "../../primitives/consensus/aura" } +sp-consensus-babe = { version = "0.8.0-rc4", default-features = false, path = "../../primitives/consensus/babe" } +sp-block-builder = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/block-builder" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +frame-executive = { version = "2.0.0-rc4", default-features = false, path = "../../frame/executive" } +sp-inherents = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/inherents" } +sp-keyring = { version = "2.0.0-rc4", optional = true, path = "../../primitives/keyring" } +memory-db = { version = "0.24.0", default-features = false } +sp-offchain = { path = "../../primitives/offchain", default-features = false, version = "2.0.0-rc4"} +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/core" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } +sp-runtime-interface = { path = "../../primitives/runtime-interface", default-features = false, version = "2.0.0-rc4"} +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/io" } +frame-support = { version = "2.0.0-rc4", default-features = false, path = "../../frame/support" } +sp-version = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/version" } +sp-session = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/session" } +sp-api = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/api" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/runtime" } +pallet-babe = { version = "2.0.0-rc4", default-features = false, path = "../../frame/babe" } +frame-system = { version = "2.0.0-rc4", default-features = false, path = "../../frame/system" } +frame-system-rpc-runtime-api = { version = "2.0.0-rc4", default-features = false, path = "../../frame/system/rpc/runtime-api" } +pallet-timestamp = { version = "2.0.0-rc4", default-features = false, path = "../../frame/timestamp" } +sp-finality-grandpa = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/finality-grandpa" } +sp-trie = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/trie" } +sp-transaction-pool = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/transaction-pool" } +trie-db = { version = "0.22.0", default-features = false } +parity-util-mem = { version = "0.7.0", default-features = false, features = ["primitive-types"] } +sc-service = { version = "0.8.0-rc4", default-features = false, optional = true, features = ["test-helpers"], path = "../../client/service" } + +# 3rd party cfg-if = "0.1.10" -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -frame-executive = { version = "2.0.0-alpha.5", default-features = false, path = "../../frame/executive" } -sp-inherents = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/inherents" } -sp-keyring = { version = "2.0.0-alpha.5", optional = true, path = "../../primitives/keyring" } log = { version = "0.4.8", optional = true } -memory-db = { version = "0.20.0", default-features = false } -sp-offchain = { path = "../../primitives/offchain", default-features = false, version = "2.0.0-alpha.5"} -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/core" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } -sp-runtime-interface = { path = "../../primitives/runtime-interface", default-features = false, version = "2.0.0-alpha.5"} -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/io" } -frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../../frame/support" } -sp-version = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/version" } serde = { version = "1.0.101", optional = true, features = ["derive"] } -sp-session = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/session" } -sp-api = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/api" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -pallet-babe = { version = "2.0.0-alpha.5", default-features = false, path = "../../frame/babe" } -frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../../frame/system" } -frame-system-rpc-runtime-api = { version = "2.0.0-alpha.5", default-features = false, path = "../../frame/system/rpc/runtime-api" } -pallet-timestamp = { version = "2.0.0-alpha.5", default-features = false, path = "../../frame/timestamp" } -sc-client = { version = "0.8.0-alpha.5", optional = true, path = "../../client" } -sp-trie = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/trie" } -sp-transaction-pool = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/transaction-pool" } -trie-db = { version = "0.20.0", default-features = false } -parity-util-mem = { version = "0.6.0", default-features = false, features = ["primitive-types"] } [dev-dependencies] -sc-block-builder = { version = "0.8.0-alpha.5", path = "../../client/block-builder" } -sc-executor = { version = "0.8.0-alpha.5", path = "../../client/executor" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "./client" } -sp-state-machine = { version = "0.8.0-alpha.5", path = "../../primitives/state-machine" } +sc-block-builder = { version = "0.8.0-rc4", path = "../../client/block-builder" } +sc-executor = { version = "0.8.0-rc4", path = "../../client/executor" } +substrate-test-runtime-client = { version = "2.0.0-rc4", path = "./client" } +sp-state-machine = { version = "0.8.0-rc4", path = "../../primitives/state-machine" } [build-dependencies] wasm-builder-runner = { version = "1.0.5", package = "substrate-wasm-builder-runner", path = "../../utils/wasm-builder-runner" } @@ -82,11 +88,9 @@ std = [ "frame-system-rpc-runtime-api/std", "frame-system/std", "pallet-timestamp/std", - "sc-client", + "sc-service", + "sp-finality-grandpa/std", "sp-trie/std", "sp-transaction-pool/std", "trie-db/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/test-utils/runtime/build.rs b/test-utils/runtime/build.rs index 1fd3d52b2f860b0d3e73676b5fc1a707964e101d..69ff73a3ffc849168e51092a6391815ea0aa856f 100644 --- a/test-utils/runtime/build.rs +++ b/test-utils/runtime/build.rs @@ -1,25 +1,26 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use wasm_builder_runner::WasmBuilder; fn main() { WasmBuilder::new() .with_current_project() - .with_wasm_builder_from_crates_or_path("1.0.9", "../../utils/wasm-builder") + .with_wasm_builder_from_crates_or_path("1.0.11", "../../utils/wasm-builder") .export_heap_base() // 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/test-utils/runtime/client/Cargo.toml b/test-utils/runtime/client/Cargo.toml index 4be45fe46659a2583df6c02b2c67a32f8bf64a18..09f2c3f152abb98b606f334e8444ff3f8c21f084 100644 --- a/test-utils/runtime/client/Cargo.toml +++ b/test-utils/runtime/client/Cargo.toml @@ -1,25 +1,28 @@ [package] name = "substrate-test-runtime-client" -version = "2.0.0-dev" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" publish = false -[dependencies] -sc-block-builder = { version = "0.8.0-alpha.5", path = "../../../client/block-builder" } -substrate-test-client = { version = "2.0.0-dev", path = "../../client" } -sp-core = { version = "2.0.0-alpha.5", path = "../../../primitives/core" } -substrate-test-runtime = { version = "2.0.0-dev", path = "../../runtime" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime" } -sp-api = { version = "2.0.0-alpha.5", path = "../../../primitives/api" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../../primitives/blockchain" } -codec = { package = "parity-scale-codec", version = "1.3.0" } -sc-client-api = { version = "2.0.0-alpha.5", path = "../../../client/api" } -sc-client = { version = "0.8.0-alpha.5", path = "../../../client/" } -futures = "0.3.4" - [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +sc-light = { version = "2.0.0-rc4", path = "../../../client/light" } +sp-consensus = { version = "0.8.0-rc4", path = "../../../primitives/consensus/common" } +sc-block-builder = { version = "0.8.0-rc4", path = "../../../client/block-builder" } +substrate-test-client = { version = "2.0.0-rc4", path = "../../client" } +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } +substrate-test-runtime = { version = "2.0.0-rc4", path = "../../runtime" } +sp-runtime = { version = "2.0.0-rc4", path = "../../../primitives/runtime" } +sp-api = { version = "2.0.0-rc4", path = "../../../primitives/api" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../../primitives/blockchain" } +codec = { package = "parity-scale-codec", version = "1.3.1" } +sc-client-api = { version = "2.0.0-rc4", path = "../../../client/api" } +sc-consensus = { version = "0.8.0-rc4", path = "../../../client/consensus/common" } +sc-service = { version = "0.8.0-rc4", default-features = false, path = "../../../client/service" } +futures = "0.3.4" diff --git a/test-utils/runtime/client/src/block_builder_ext.rs b/test-utils/runtime/client/src/block_builder_ext.rs index 3a9f54d06cb2b4bdcb22d2029abb08343bce5ec6..cc0bbc69e8fc1063f5aa700d732399c17900e2bb 100644 --- a/test-utils/runtime/client/src/block_builder_ext.rs +++ b/test-utils/runtime/client/src/block_builder_ext.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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. +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Block Builder extensions for tests. diff --git a/test-utils/runtime/client/src/lib.rs b/test-utils/runtime/client/src/lib.rs index f0a405e67e469012f031bb0e3ab676a39e7c5c5b..4e9034fb4d493935c3ca47321681e6a94b1bf4c8 100644 --- a/test-utils/runtime/client/src/lib.rs +++ b/test-utils/runtime/client/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Client testing utilities. @@ -26,7 +27,7 @@ use std::sync::Arc; use std::collections::HashMap; pub use substrate_test_client::*; pub use substrate_test_runtime as runtime; -pub use sc_client::LongestChain; +pub use sc_consensus::LongestChain; pub use self::block_builder_ext::BlockBuilderExt; @@ -34,12 +35,9 @@ use sp_core::{sr25519, ChangesTrieConfiguration}; use sp_core::storage::{ChildInfo, Storage, StorageChild}; use substrate_test_runtime::genesismap::{GenesisConfig, additional_storage_with_genesis}; use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Hash as HashT, NumberFor, HashFor}; -use sc_client::{ - light::fetcher::{ - Fetcher, - RemoteHeaderRequest, RemoteReadRequest, RemoteReadChildRequest, - RemoteCallRequest, RemoteChangesRequest, RemoteBodyRequest, - }, +use sc_client_api::light::{ + RemoteCallRequest, RemoteChangesRequest, RemoteBodyRequest, + Fetcher, RemoteHeaderRequest, RemoteReadRequest, RemoteReadChildRequest, }; /// A prelude to import in tests. @@ -68,7 +66,7 @@ sc_executor::native_executor_instance! { pub type Backend = substrate_test_client::Backend; /// Test client executor. -pub type Executor = sc_client::LocalCallExecutor< +pub type Executor = client::LocalCallExecutor< Backend, NativeExecutor, >; @@ -77,10 +75,10 @@ pub type Executor = sc_client::LocalCallExecutor< pub type LightBackend = substrate_test_client::LightBackend; /// Test client light executor. -pub type LightExecutor = sc_client::light::call_executor::GenesisCallExecutor< +pub type LightExecutor = sc_light::GenesisCallExecutor< LightBackend, - sc_client::LocalCallExecutor< - sc_client::light::backend::Backend< + client::LocalCallExecutor< + sc_light::Backend< sc_client_db::light::LightStorage, HashFor >, @@ -123,16 +121,17 @@ impl substrate_test_client::GenesisInit for GenesisParameters { let mut storage = self.genesis_config().genesis_map(); - let child_roots = storage.children.iter().map(|(sk, child_content)| { + let child_roots = storage.children_default.iter().map(|(_sk, child_content)| { let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( child_content.data.clone().into_iter().collect() ); - (sk.clone(), state_root.encode()) + let prefixed_storage_key = child_content.child_info.prefixed_storage_key(); + (prefixed_storage_key.into_inner(), state_root.encode()) }); let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( storage.top.clone().into_iter().chain(child_roots).collect() ); - let block: runtime::Block = sc_client::genesis::construct_genesis_block(state_root); + let block: runtime::Block = client::genesis::construct_genesis_block(state_root); storage.top.extend(additional_storage_with_genesis(&block)); storage @@ -148,9 +147,9 @@ pub type TestClientBuilder = substrate_test_client::TestClientBuilder< >; /// Test client type with `LocalExecutor` and generic Backend. -pub type Client = sc_client::Client< +pub type Client = client::Client< B, - sc_client::LocalCallExecutor>, + client::LocalCallExecutor>, substrate_test_runtime::Block, substrate_test_runtime::RuntimeApi, >; @@ -192,22 +191,21 @@ pub trait TestClientBuilderExt: Sized { /// # Panics /// /// Panics if the key is empty. - fn add_extra_child_storage>, K: Into>, V: Into>>( + fn add_extra_child_storage>, V: Into>>( mut self, - storage_key: SK, - child_info: ChildInfo, + child_info: &ChildInfo, key: K, value: V, ) -> Self { - let storage_key = storage_key.into(); + let storage_key = child_info.storage_key().to_vec(); let key = key.into(); assert!(!storage_key.is_empty()); assert!(!key.is_empty()); - self.genesis_init_mut().extra_storage.children + self.genesis_init_mut().extra_storage.children_default .entry(storage_key) .or_insert_with(|| StorageChild { data: Default::default(), - child_info: child_info.to_owned(), + child_info: child_info.clone(), }).data.insert(key, value.into()); self } @@ -230,14 +228,14 @@ pub trait TestClientBuilderExt: Sized { } /// Build the test client and longest chain selector. - fn build_with_longest_chain(self) -> (Client, sc_client::LongestChain); + fn build_with_longest_chain(self) -> (Client, sc_consensus::LongestChain); /// Build the test client and the backend. fn build_with_backend(self) -> (Client, Arc); } impl TestClientBuilderExt for TestClientBuilder< - sc_client::LocalCallExecutor>, + client::LocalCallExecutor>, B > where B: sc_client_api::backend::Backend + 'static, @@ -249,7 +247,7 @@ impl TestClientBuilderExt for TestClientBuilder< Self::genesis_init_mut(self) } - fn build_with_longest_chain(self) -> (Client, sc_client::LongestChain) { + fn build_with_longest_chain(self) -> (Client, sc_consensus::LongestChain) { self.build_with_native_executor(None) } @@ -311,7 +309,10 @@ impl Fetcher for LightFetcher { unimplemented!() } - fn remote_read_child(&self, _: RemoteReadChildRequest) -> Self::RemoteReadResult { + fn remote_read_child( + &self, + _: RemoteReadChildRequest, + ) -> Self::RemoteReadResult { unimplemented!() } @@ -341,15 +342,15 @@ pub fn new() -> Client { /// Creates new light client instance used for tests. pub fn new_light() -> ( - sc_client::Client, + client::Client, Arc, ) { let storage = sc_client_db::light::LightStorage::new_test(); - let blockchain = Arc::new(sc_client::light::blockchain::Blockchain::new(storage)); + let blockchain = Arc::new(sc_light::Blockchain::new(storage)); let backend = Arc::new(LightBackend::new(blockchain.clone())); let executor = new_native_executor(); - let local_call_executor = sc_client::LocalCallExecutor::new(backend.clone(), executor, sp_core::tasks::executor()); + let local_call_executor = client::LocalCallExecutor::new(backend.clone(), executor, sp_core::tasks::executor(), Default::default()); let call_executor = LightExecutor::new( backend.clone(), local_call_executor, diff --git a/test-utils/runtime/client/src/trait_tests.rs b/test-utils/runtime/client/src/trait_tests.rs index 4af8aa37b640a27cd41f7859837a3808525b0327..537ff1197e7efaabe6afda32c9010dc4a18f4814 100644 --- a/test-utils/runtime/client/src/trait_tests.rs +++ b/test-utils/runtime/client/src/trait_tests.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! tests that should hold for all implementations of certain traits. //! to test implementations without duplication. @@ -26,7 +27,7 @@ use crate::{ }; use sc_client_api::backend; use sc_client_api::blockchain::{Backend as BlockChainBackendT, HeaderBackend}; -use substrate_test_client::sp_consensus::BlockOrigin; +use sp_consensus::BlockOrigin; use substrate_test_runtime::{self, Transfer}; use sp_runtime::generic::BlockId; use sp_runtime::traits::{Block as BlockT, HashFor}; diff --git a/test-utils/runtime/src/genesismap.rs b/test-utils/runtime/src/genesismap.rs index 25d9a807ccee15982c02f040001cdfd6c059983f..0b717fc5a99a20824d047847e9996ff511492cc1 100644 --- a/test-utils/runtime/src/genesismap.rs +++ b/test-utils/runtime/src/genesismap.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Tool for creating the genesis block. @@ -23,6 +24,7 @@ use codec::{Encode, KeyedVec, Joiner}; use sp_core::{ChangesTrieConfiguration, map}; use sp_core::storage::{well_known_keys, Storage}; use sp_runtime::traits::{Block as BlockT, Hash as HashT, Header as HeaderT}; +use sc_service::client::genesis; /// Configuration of a general Substrate test genesis block. pub struct GenesisConfig { @@ -73,7 +75,7 @@ impl GenesisConfig { map.extend(self.extra_storage.top.clone().into_iter()); // Assimilate the system genesis config. - let mut storage = Storage { top: map, children: self.extra_storage.children.clone()}; + let mut storage = Storage { top: map, children_default: self.extra_storage.children_default.clone()}; let mut config = system::GenesisConfig::default(); config.authorities = self.authorities.clone(); config.assimilate_storage(&mut storage).expect("Adding `system::GensisConfig` to the genesis"); @@ -85,7 +87,7 @@ impl GenesisConfig { pub fn insert_genesis_block( storage: &mut Storage, ) -> sp_core::hash::H256 { - let child_roots = storage.children.iter().map(|(sk, child_content)| { + let child_roots = storage.children_default.iter().map(|(sk, child_content)| { let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( child_content.data.clone().into_iter().collect(), ); @@ -96,7 +98,7 @@ pub fn insert_genesis_block( let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( storage.top.clone().into_iter().collect() ); - let block: crate::Block = sc_client::genesis::construct_genesis_block(state_root); + let block: crate::Block = genesis::construct_genesis_block(state_root); let genesis_hash = block.header.hash(); storage.top.extend(additional_storage_with_genesis(&block)); genesis_hash diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index f3efb4bea7c763f89aa9e8e79a1770d2c73c3c97..002658fe977847ebd411832c4f6544caec6d80f0 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The Substrate runtime. This can be compiled with #[no_std], ready for Wasm. @@ -25,35 +26,39 @@ pub mod system; use sp_std::{prelude::*, marker::PhantomData}; use codec::{Encode, Decode, Input, Error}; -use sp_core::{OpaqueMetadata, RuntimeDebug, ChangesTrieConfiguration}; -use sp_application_crypto::{ed25519, sr25519, RuntimeAppPublic}; +use sp_core::{offchain::KeyTypeId, ChangesTrieConfiguration, OpaqueMetadata, RuntimeDebug}; +use sp_application_crypto::{ed25519, sr25519, ecdsa, RuntimeAppPublic}; use trie_db::{TrieMut, Trie}; use sp_trie::PrefixedMemoryDB; use sp_trie::trie_types::{TrieDB, TrieDBMut}; use sp_api::{decl_runtime_apis, impl_runtime_apis}; use sp_runtime::{ - ApplyExtrinsicResult, create_runtime_str, Perbill, impl_opaque_keys, + create_runtime_str, impl_opaque_keys, + ApplyExtrinsicResult, Perbill, transaction_validity::{ TransactionValidity, ValidTransaction, TransactionValidityError, InvalidTransaction, TransactionSource, }, traits::{ BlindCheckable, BlakeTwo256, Block as BlockT, Extrinsic as ExtrinsicT, - GetNodeBlockType, GetRuntimeBlockType, Verify, IdentityLookup, + GetNodeBlockType, GetRuntimeBlockType, NumberFor, Verify, IdentityLookup, }, }; use sp_version::RuntimeVersion; pub use sp_core::hash::H256; #[cfg(any(feature = "std", test))] use sp_version::NativeVersion; -use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; +use frame_support::{ + impl_outer_origin, parameter_types, + traits::KeyOwnerProofSystem, + weights::{RuntimeDbWeight, Weight}, +}; use sp_inherents::{CheckInherentsResult, InherentData}; use cfg_if::cfg_if; -use sp_core::storage::ChildType; // Ensure Babe and Aura use the same crypto to simplify things a bit. -pub use sp_consensus_babe::{AuthorityId, SlotNumber}; +pub use sp_consensus_babe::{AuthorityId, SlotNumber, AllowedSlots}; pub type AuraId = sp_consensus_aura::sr25519::AuthorityId; // Include the WASM binary @@ -68,6 +73,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_version: 2, impl_version: 2, apis: RUNTIME_API_VERSIONS, + transaction_version: 1, }; fn version() -> RuntimeVersion { @@ -181,11 +187,31 @@ impl ExtrinsicT for Extrinsic { } } +impl sp_runtime::traits::Dispatchable for Extrinsic { + type Origin = Origin; + type Trait = (); + type Info = (); + type PostInfo = (); + fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo { + panic!("This implemention should not be used for actual dispatch."); + } +} + impl Extrinsic { + /// Convert `&self` into `&Transfer`. + /// + /// Panics if this is no `Transfer` extrinsic. pub fn transfer(&self) -> &Transfer { + self.try_transfer().expect("cannot convert to transfer ref") + } + + /// Try to convert `&self` into `&Transfer`. + /// + /// Returns `None` if this is no `Transfer` extrinsic. + pub fn try_transfer(&self) -> Option<&Transfer> { match self { - Extrinsic::Transfer { ref transfer, .. } => transfer, - _ => panic!("cannot convert to transfer ref"), + Extrinsic::Transfer { ref transfer, .. } => Some(transfer), + _ => None, } } } @@ -196,6 +222,8 @@ pub type AccountSignature = sr25519::Signature; pub type AccountId = ::Signer; /// A simple hash type for all our hashing. pub type Hash = H256; +/// The hashing algorithm used. +pub type Hashing = BlakeTwo256; /// The block number type used in this runtime. pub type BlockNumber = u64; /// Index of a transaction. @@ -207,7 +235,7 @@ pub type Digest = sp_runtime::generic::Digest; /// A test block. pub type Block = sp_runtime::generic::Block; /// A test block's header. -pub type Header = sp_runtime::generic::Header; +pub type Header = sp_runtime::generic::Header; /// Run whatever tests we have. pub fn run_tests(mut input: &[u8]) -> Vec { @@ -293,8 +321,15 @@ cfg_if! { /// /// Returns the signature generated for the message `sr25519`. fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic); + /// Test that `ecdsa` crypto works in the runtime. + /// + /// Returns the signature generated for the message `ecdsa`. + fn test_ecdsa_crypto() -> (ecdsa::AppSignature, ecdsa::AppPublic); /// Run various tests against storage. fn test_storage(); + /// Test that ensures that we can call a function that takes multiple + /// arguments. + fn test_multiple_arguments(data: Vec, other: Vec, num: u32); } } } else { @@ -335,8 +370,15 @@ cfg_if! { /// /// Returns the signature generated for the message `sr25519`. fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic); + /// Test that `ecdsa` crypto works in the runtime. + /// + /// Returns the signature generated for the message `ecdsa`. + fn test_ecdsa_crypto() -> (ecdsa::AppSignature, ecdsa::AppPublic); /// Run various tests against storage. fn test_storage(); + /// Test that ensures that we can call a function that takes multiple + /// arguments. + fn test_multiple_arguments(data: Vec, other: Vec, num: u32); } } } @@ -367,26 +409,35 @@ impl From> for Event { } parameter_types! { - pub const BlockHashCount: BlockNumber = 250; + pub const BlockHashCount: BlockNumber = 2400; pub const MinimumPeriod: u64 = 5; pub const MaximumBlockWeight: Weight = 4 * 1024 * 1024; + pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { + read: 100, + write: 1000, + }; pub const MaximumBlockLength: u32 = 4 * 1024 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); } impl frame_system::Trait for Runtime { + type BaseCallFilter = (); type Origin = Origin; type Call = Extrinsic; type Index = u64; type BlockNumber = u64; type Hash = H256; - type Hashing = BlakeTwo256; + type Hashing = Hashing; type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; type Event = Event; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -394,6 +445,7 @@ impl frame_system::Trait for Runtime { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); + type SystemWeightInfo = (); } impl pallet_timestamp::Trait for Runtime { @@ -401,6 +453,7 @@ impl pallet_timestamp::Trait for Runtime { type Moment = u64; type OnTimestampSet = (); type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); } parameter_types! { @@ -415,6 +468,18 @@ impl pallet_babe::Trait for Runtime { // are manually adding the digests. normally in this situation you'd use // pallet_babe::SameAuthoritiesForever. type EpochChangeTrigger = pallet_babe::ExternalTrigger; + + type KeyOwnerProofSystem = (); + + type KeyOwnerProof = + >::Proof; + + type KeyOwnerIdentification = >::IdentificationTuple; + + type HandleEquivocation = (); } /// Adds one to the given input and returns the final result. @@ -438,7 +503,7 @@ fn code_using_trie() -> u64 { let mut root = sp_std::default::Default::default(); let _ = { let v = &pairs; - let mut t = TrieDBMut::::new(&mut mdb, &mut root); + let mut t = TrieDBMut::::new(&mut mdb, &mut root); for i in 0..v.len() { let key: &[u8]= &v[i].0; let val: &[u8] = &v[i].1; @@ -449,7 +514,7 @@ fn code_using_trie() -> u64 { t }; - if let Ok(trie) = TrieDB::::new(&mdb, &root) { + if let Ok(trie) = TrieDB::::new(&mdb, &root) { if let Ok(iter) = trie.iter() { let mut iter_pairs = Vec::new(); for pair in iter { @@ -466,6 +531,7 @@ impl_opaque_keys! { pub struct SessionKeys { pub ed25519: ed25519::AppPublic, pub sr25519: sr25519::AppPublic, + pub ecdsa: ecdsa::AppPublic, } } @@ -601,10 +667,19 @@ cfg_if! { test_sr25519_crypto() } + fn test_ecdsa_crypto() -> (ecdsa::AppSignature, ecdsa::AppPublic) { + test_ecdsa_crypto() + } + fn test_storage() { test_read_storage(); test_read_child_storage(); } + + fn test_multiple_arguments(data: Vec, other: Vec, num: u32) { + assert_eq!(&data[..], &other[..]); + assert_eq!(data.len(), num as usize); + } } impl sp_consensus_aura::AuraApi for Runtime { @@ -618,21 +693,37 @@ cfg_if! { } impl sp_consensus_babe::BabeApi for Runtime { - fn configuration() -> sp_consensus_babe::BabeConfiguration { - sp_consensus_babe::BabeConfiguration { + fn configuration() -> sp_consensus_babe::BabeGenesisConfiguration { + sp_consensus_babe::BabeGenesisConfiguration { slot_duration: 1000, epoch_length: EpochDuration::get(), c: (3, 10), genesis_authorities: system::authorities() .into_iter().map(|x|(x, 1)).collect(), randomness: >::randomness(), - secondary_slots: true, + allowed_slots: AllowedSlots::PrimaryAndSecondaryPlainSlots, } } fn current_epoch_start() -> SlotNumber { >::current_epoch_start() } + + fn submit_report_equivocation_unsigned_extrinsic( + _equivocation_proof: sp_consensus_babe::EquivocationProof< + ::Header, + >, + _key_owner_proof: sp_consensus_babe::OpaqueKeyOwnershipProof, + ) -> Option<()> { + None + } + + fn generate_key_ownership_proof( + _slot_number: sp_consensus_babe::SlotNumber, + _authority_id: sp_consensus_babe::AuthorityId, + ) -> Option { + None + } } impl sp_offchain::OffchainWorkerApi for Runtime { @@ -654,6 +745,29 @@ cfg_if! { } } + impl sp_finality_grandpa::GrandpaApi for Runtime { + fn grandpa_authorities() -> sp_finality_grandpa::AuthorityList { + Vec::new() + } + + fn submit_report_equivocation_extrinsic( + _equivocation_proof: sp_finality_grandpa::EquivocationProof< + ::Hash, + NumberFor, + >, + _key_owner_proof: sp_finality_grandpa::OpaqueKeyOwnershipProof, + ) -> Option<()> { + None + } + + fn generate_key_ownership_proof( + _set_id: sp_finality_grandpa::SetId, + _authority_id: sp_finality_grandpa::AuthorityId, + ) -> Option { + None + } + } + impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { fn account_nonce(_account: AccountId) -> Index { 0 @@ -795,10 +909,19 @@ cfg_if! { test_sr25519_crypto() } + fn test_ecdsa_crypto() -> (ecdsa::AppSignature, ecdsa::AppPublic) { + test_ecdsa_crypto() + } + fn test_storage() { test_read_storage(); test_read_child_storage(); } + + fn test_multiple_arguments(data: Vec, other: Vec, num: u32) { + assert_eq!(&data[..], &other[..]); + assert_eq!(data.len(), num as usize); + } } impl sp_consensus_aura::AuraApi for Runtime { @@ -812,21 +935,37 @@ cfg_if! { } impl sp_consensus_babe::BabeApi for Runtime { - fn configuration() -> sp_consensus_babe::BabeConfiguration { - sp_consensus_babe::BabeConfiguration { + fn configuration() -> sp_consensus_babe::BabeGenesisConfiguration { + sp_consensus_babe::BabeGenesisConfiguration { slot_duration: 1000, epoch_length: EpochDuration::get(), c: (3, 10), genesis_authorities: system::authorities() .into_iter().map(|x|(x, 1)).collect(), randomness: >::randomness(), - secondary_slots: true, + allowed_slots: AllowedSlots::PrimaryAndSecondaryPlainSlots, } } fn current_epoch_start() -> SlotNumber { >::current_epoch_start() } + + fn submit_report_equivocation_unsigned_extrinsic( + _equivocation_proof: sp_consensus_babe::EquivocationProof< + ::Header, + >, + _key_owner_proof: sp_consensus_babe::OpaqueKeyOwnershipProof, + ) -> Option<()> { + None + } + + fn generate_key_ownership_proof( + _slot_number: sp_consensus_babe::SlotNumber, + _authority_id: sp_consensus_babe::AuthorityId, + ) -> Option { + None + } } impl sp_offchain::OffchainWorkerApi for Runtime { @@ -887,6 +1026,22 @@ fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic) { (signature, public0) } +fn test_ecdsa_crypto() -> (ecdsa::AppSignature, ecdsa::AppPublic) { + let public0 = ecdsa::AppPublic::generate_pair(None); + let public1 = ecdsa::AppPublic::generate_pair(None); + let public2 = ecdsa::AppPublic::generate_pair(None); + + let all = ecdsa::AppPublic::all(); + assert!(all.contains(&public0)); + assert!(all.contains(&public1)); + assert!(all.contains(&public2)); + + let signature = public0.sign(&"ecdsa").expect("Generates a valid `ecdsa` signature."); + + assert!(public0.verify(&"ecdsa", &signature)); + (signature, public0) +} + fn test_read_storage() { const KEY: &[u8] = b":read_storage"; sp_io::storage::set(KEY, b"test"); @@ -907,22 +1062,17 @@ fn test_read_storage() { } fn test_read_child_storage() { - const CHILD_KEY: &[u8] = b":child_storage:default:read_child_storage"; - const UNIQUE_ID: &[u8] = b":unique_id"; + const STORAGE_KEY: &[u8] = b"unique_id_1"; const KEY: &[u8] = b":read_child_storage"; - sp_io::storage::child_set( - CHILD_KEY, - UNIQUE_ID, - ChildType::CryptoUniqueId as u32, + sp_io::default_child_storage::set( + STORAGE_KEY, KEY, b"test", ); let mut v = [0u8; 4]; - let r = sp_io::storage::child_read( - CHILD_KEY, - UNIQUE_ID, - ChildType::CryptoUniqueId as u32, + let r = sp_io::default_child_storage::read( + STORAGE_KEY, KEY, &mut v, 0, @@ -931,10 +1081,8 @@ fn test_read_child_storage() { assert_eq!(&v, b"test"); let mut v = [0u8; 4]; - let r = sp_io::storage::child_read( - CHILD_KEY, - UNIQUE_ID, - ChildType::CryptoUniqueId as u32, + let r = sp_io::default_child_storage::read( + STORAGE_KEY, KEY, &mut v, 8, diff --git a/test-utils/runtime/src/system.rs b/test-utils/runtime/src/system.rs index c35850ae950e928ae46bb882457f1bf3ef3baa83..3cbc416a40eea02c8a866b3243739d607a368845 100644 --- a/test-utils/runtime/src/system.rs +++ b/test-utils/runtime/src/system.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! System manager: Handles all of the top-level stuff; executing block/transaction, setting code //! and depositing logs. @@ -373,7 +374,7 @@ mod tests { vec![111u8, 0, 0, 0, 0, 0, 0, 0] } ], - children: map![], + children_default: map![], }, ) } diff --git a/test-utils/runtime/transaction-pool/Cargo.toml b/test-utils/runtime/transaction-pool/Cargo.toml index 52e2020dc8dd18dfc82de735e66b98b469bfefb9..f29ae2b7bf46753606dbd6e7945307f13732fd7f 100644 --- a/test-utils/runtime/transaction-pool/Cargo.toml +++ b/test-utils/runtime/transaction-pool/Cargo.toml @@ -1,23 +1,23 @@ [package] name = "substrate-test-runtime-transaction-pool" -version = "2.0.0-dev" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" publish = false +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../client" } +substrate-test-runtime-client = { version = "2.0.0-rc4", path = "../client" } parking_lot = "0.10.0" -codec = { package = "parity-scale-codec", version = "1.3.0" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../../primitives/blockchain" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime" } -sp-transaction-pool = { version = "2.0.0-alpha.5", path = "../../../primitives/transaction-pool" } -sc-transaction-graph = { version = "2.0.0-alpha.5", path = "../../../client/transaction-pool/graph" } +codec = { package = "parity-scale-codec", version = "1.3.1" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../../primitives/blockchain" } +sp-runtime = { version = "2.0.0-rc4", path = "../../../primitives/runtime" } +sp-transaction-pool = { version = "2.0.0-rc4", path = "../../../primitives/transaction-pool" } +sc-transaction-graph = { version = "2.0.0-rc4", path = "../../../client/transaction-pool/graph" } futures = { version = "0.3.1", features = ["compat"] } derive_more = "0.99.2" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/test-utils/runtime/transaction-pool/src/lib.rs b/test-utils/runtime/transaction-pool/src/lib.rs index 432c9e520d1b178c0dc2567a35be82873d9ee687..17cecd394ab916eaf16a2d5e5cfb0fffb745189a 100644 --- a/test-utils/runtime/transaction-pool/src/lib.rs +++ b/test-utils/runtime/transaction-pool/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utils for the transaction pool together with the test runtime. //! @@ -22,17 +23,18 @@ use codec::Encode; use parking_lot::RwLock; use sp_runtime::{ generic::{self, BlockId}, - traits::{BlakeTwo256, Hash as HashT}, + traits::{BlakeTwo256, Hash as HashT, Block as _, Header as _}, transaction_validity::{ TransactionValidity, ValidTransaction, TransactionValidityError, InvalidTransaction, TransactionSource, }, }; -use std::collections::{HashSet, HashMap}; +use std::collections::{HashSet, HashMap, BTreeMap}; use substrate_test_runtime_client::{ runtime::{Index, AccountId, Block, BlockNumber, Extrinsic, Hash, Header, Transfer}, AccountKeyring::{self, *}, }; +use sp_blockchain::CachedHeaderMetadata; /// Error type used by [`TestApi`]. #[derive(Debug, derive_more::From, derive_more::Display)] @@ -52,9 +54,8 @@ impl std::error::Error for Error { #[derive(Default)] pub struct ChainState { - pub block_by_number: HashMap>, - pub block_by_hash: HashMap>, - pub header_by_number: HashMap, + pub block_by_number: BTreeMap>, + pub block_by_hash: HashMap, pub nonces: HashMap, pub invalid_hashes: HashSet, } @@ -69,11 +70,7 @@ pub struct TestApi { impl TestApi { /// Test Api with Alice nonce set initially. pub fn with_alice_nonce(nonce: u64) -> Self { - let api = TestApi { - valid_modifier: RwLock::new(Box::new(|_| {})), - chain: Default::default(), - validation_requests: RwLock::new(Default::default()), - }; + let api = Self::empty(); api.chain.write().nonces.insert(Alice.into(), nonce); @@ -88,6 +85,9 @@ impl TestApi { validation_requests: RwLock::new(Default::default()), }; + // Push genesis block + api.push_block(0, Vec::new()); + api } @@ -96,46 +96,61 @@ impl TestApi { *self.valid_modifier.write() = modifier; } - /// Push block as a part of canonical chain under given number. + /// Push block under given number. + /// + /// If multiple blocks exists with the same block number, the first inserted block will be + /// interpreted as part of the canonical chain. pub fn push_block(&self, block_number: BlockNumber, xts: Vec) -> Header { - let mut chain = self.chain.write(); - chain.block_by_number.insert(block_number, xts.clone()); - let header = Header { - number: block_number, - digest: Default::default(), - extrinsics_root: Default::default(), - parent_hash: block_number + let parent_hash = { + let chain = self.chain.read(); + block_number .checked_sub(1) .and_then(|num| { - chain.header_by_number.get(&num) - .cloned().map(|h| h.hash()) - }).unwrap_or_default(), - state_root: Default::default(), + chain.block_by_number + .get(&num) + .map(|blocks| { + blocks[0].header.hash() + }) + }).unwrap_or_default() }; - chain.block_by_hash.insert(header.hash(), xts); - chain.header_by_number.insert(block_number, header.clone()); - header + + self.push_block_with_parent(parent_hash, xts) } - /// Push a block without a number. + /// Push a block using the given `parent`. /// - /// As a part of non-canonical chain. - pub fn push_fork_block(&self, block_hash: Hash, xts: Vec) { + /// Panics if `parent` does not exists. + pub fn push_block_with_parent( + &self, + parent: Hash, + xts: Vec, + ) -> Header { let mut chain = self.chain.write(); - chain.block_by_hash.insert(block_hash, xts); - } - pub fn push_fork_block_with_parent(&self, parent: Hash, xts: Vec) -> Header { - let mut chain = self.chain.write(); - let blocknum = chain.block_by_number.keys().max().expect("block_by_number shouldn't be empty"); + // `Hash::default()` is the genesis parent hash + let block_number = if parent == Hash::default() { + 0 + } else { + *chain.block_by_hash + .get(&parent) + .expect("`parent` exists") + .header() + .number() + 1 + }; + let header = Header { - number: *blocknum, + number: block_number, digest: Default::default(), - extrinsics_root: Default::default(), + extrinsics_root: Hash::random(), parent_hash: parent, state_root: Default::default(), }; - chain.block_by_hash.insert(header.hash(), xts); + + let hash = header.hash(); + let block = Block::new(header.clone(), xts); + chain.block_by_hash.insert(hash, block.clone()); + chain.block_by_number.entry(block_number).or_default().push(block); + header } @@ -169,11 +184,19 @@ impl TestApi { let mut chain = self.chain.write(); chain.nonces.entry(account).and_modify(|n| *n += 1).or_insert(1); } + + /// Calculate a tree route between the two given blocks. + pub fn tree_route( + &self, + from: Hash, + to: Hash, + ) -> Result, Error> { + sp_blockchain::tree_route(self, from, to) + } } impl sc_transaction_graph::ChainApi for TestApi { type Block = Block; - type Hash = Hash; type Error = Error; type ValidationFuture = futures::future::Ready>; type BodyFuture = futures::future::Ready>, Error>>; @@ -186,13 +209,19 @@ impl sc_transaction_graph::ChainApi for TestApi { ) -> Self::ValidationFuture { self.validation_requests.write().push(uxt.clone()); - let chain_nonce = self.chain.read().nonces.get(&uxt.transfer().from).cloned().unwrap_or(0); - let requires = if chain_nonce == uxt.transfer().nonce { - vec![] + let (requires, provides) = if let Some(transfer) = uxt.try_transfer() { + let chain_nonce = self.chain.read().nonces.get(&transfer.from).cloned().unwrap_or(0); + let requires = if chain_nonce == transfer.nonce { + vec![] + } else { + vec![vec![chain_nonce as u8]] + }; + let provides = vec![vec![transfer.nonce as u8]]; + + (requires, provides) } else { - vec![vec![chain_nonce as u8]] + (Vec::new(), vec![uxt.encode()]) }; - let provides = vec![vec![uxt.transfer().nonce as u8]]; if self.chain.read().invalid_hashes.contains(&self.hash_and_length(&uxt).0) { return futures::future::ready(Ok( @@ -217,7 +246,14 @@ impl sc_transaction_graph::ChainApi for TestApi { &self, at: &BlockId, ) -> Result>, Error> { - Ok(Some(number_of(at))) + Ok(match at { + generic::BlockId::Hash(x) => self.chain + .read() + .block_by_hash + .get(x) + .map(|b| *b.header.number()), + generic::BlockId::Number(num) => Some(*num), + }) } fn block_id_to_hash( @@ -226,34 +262,60 @@ impl sc_transaction_graph::ChainApi for TestApi { ) -> Result>, Error> { Ok(match at { generic::BlockId::Hash(x) => Some(x.clone()), - generic::BlockId::Number(num) => { - self.chain.read() - .header_by_number.get(num) - .map(|h| h.hash()) - .or_else(|| Some(Default::default())) - }, + generic::BlockId::Number(num) => self.chain + .read() + .block_by_number + .get(num) + .map(|blocks| blocks[0].header().hash()), }) } fn hash_and_length( &self, ex: &sc_transaction_graph::ExtrinsicFor, - ) -> (Self::Hash, usize) { + ) -> (Hash, usize) { Self::hash_and_length_inner(ex) } fn block_body(&self, id: &BlockId) -> Self::BodyFuture { futures::future::ready(Ok(match id { - BlockId::Number(num) => self.chain.read().block_by_number.get(num).cloned(), - BlockId::Hash(hash) => self.chain.read().block_by_hash.get(hash).cloned(), + BlockId::Number(num) => self.chain + .read() + .block_by_number + .get(num) + .map(|b| b[0].extrinsics().to_vec()), + BlockId::Hash(hash) => self.chain + .read() + .block_by_hash + .get(hash) + .map(|b| b.extrinsics().to_vec()), })) } } -fn number_of(at: &BlockId) -> u64 { - match at { - generic::BlockId::Number(n) => *n as u64, - _ => 0, +impl sp_blockchain::HeaderMetadata for TestApi { + type Error = Error; + + fn header_metadata( + &self, + hash: Hash, + ) -> Result, Self::Error> { + let chain = self.chain.read(); + let block = chain.block_by_hash.get(&hash).expect("Hash exists"); + + Ok(block.header().into()) + } + + fn insert_header_metadata( + &self, + _: Hash, + _: CachedHeaderMetadata, + ) { + unimplemented!("Not implemented for tests") + } + + fn remove_header_metadata(&self, _: Hash) { + unimplemented!("Not implemented for tests") } } diff --git a/test-utils/src/lib.rs b/test-utils/src/lib.rs index c1a18a1fa7a3bce7a8ede30b7d3750323a736183..8163460df7427fb3bb7b7de3e187b487eee21378 100644 --- a/test-utils/src/lib.rs +++ b/test-utils/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utils @@ -37,7 +38,7 @@ /// ``` #[macro_export] macro_rules! assert_eq_uvec { - ( $x:expr, $y:expr ) => { + ( $x:expr, $y:expr $(,)? ) => { $crate::__assert_eq_uvec!($x, $y); $crate::__assert_eq_uvec!($y, $x); } diff --git a/utils/browser/Cargo.toml b/utils/browser/Cargo.toml index 188f46bf197b831aaad001528befd4cc4b60f47c..faa1bcfcef7e20fc932a8b2d2bc40b095a2bb9b6 100644 --- a/utils/browser/Cargo.toml +++ b/utils/browser/Cargo.toml @@ -1,28 +1,32 @@ [package] name = "substrate-browser-utils" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] description = "Utilities for creating a browser light-client." edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -futures = "0.3" +futures = { version = "0.3", features = ["compat"] } futures01 = { package = "futures", version = "0.1.29" } log = "0.4.8" -libp2p-wasm-ext = { version = "0.16.2", features = ["websocket"] } +libp2p-wasm-ext = { version = "0.20", features = ["websocket"] } console_error_panic_hook = "0.1.6" console_log = "0.1.2" js-sys = "0.3.34" wasm-bindgen = "0.2.57" wasm-bindgen-futures = "0.4.7" -kvdb-web = "0.5" -sc-informant = { version = "0.8.0-alpha.5", path = "../../client/informant" } -sc-service = { version = "0.8.0-alpha.5", path = "../../client/service", default-features = false } -sc-network = { path = "../../client/network", version = "0.8.0-alpha.5"} -sc-chain-spec = { path = "../../client/chain-spec", version = "2.0.0-alpha.5"} +kvdb-web = "0.7" +sp-database = { version = "2.0.0-rc4", path = "../../primitives/database" } +sc-informant = { version = "0.8.0-rc4", path = "../../client/informant" } +sc-service = { version = "0.8.0-rc4", path = "../../client/service", default-features = false } +sc-network = { path = "../../client/network", version = "0.8.0-rc4"} +sc-chain-spec = { path = "../../client/chain-spec", version = "2.0.0-rc4"} # Imported just for the `no_cc` feature clear_on_drop = { version = "0.2.3", features = ["no_cc"] } @@ -31,6 +35,3 @@ rand6 = { package = "rand", version = "0.6", features = ["wasm-bindgen"] } rand = { version = "0.7", features = ["wasm-bindgen"] } futures-timer = { version = "3.0.1", features = ["wasm-bindgen"]} chrono = { version = "0.4", features = ["wasmbind"] } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs index 80dfa5e2d2470828d5d883a0f0e2532a4478995d..9313d41bf572626934214a4896fce0e24e6b0664 100644 --- a/utils/browser/src/lib.rs +++ b/utils/browser/src/lib.rs @@ -1,30 +1,33 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use futures01::sync::mpsc as mpsc01; use log::{debug, info}; -use std::sync::Arc; +use sc_network::config::TransportConfig; use sc_service::{ - AbstractService, RpcSession, Role, Configuration, config::{DatabaseConfig, KeystoreConfig}, + RpcSession, Role, Configuration, TaskManager, RpcHandlers, + config::{DatabaseConfig, KeystoreConfig, NetworkConfiguration}, GenericChainSpec, RuntimeGenesis }; use wasm_bindgen::prelude::*; -use futures::{prelude::*, channel::{oneshot, mpsc}, future::{poll_fn, ok}, compat::*}; -use std::task::Poll; -use std::pin::Pin; +use futures::{ + prelude::*, channel::{oneshot, mpsc}, compat::*, future::{ready, ok, select} +}; +use std::{sync::Arc, pin::Pin}; use sc_chain_spec::Extension; use libp2p_wasm_ext::{ExtTransport, ffi}; @@ -43,29 +46,64 @@ where let name = chain_spec.name().to_string(); let transport = ExtTransport::new(ffi::websocket_transport()); - let mut config = Configuration::default(); - config.network.boot_nodes = chain_spec.boot_nodes().to_vec(); - config.telemetry_endpoints = chain_spec.telemetry_endpoints().clone(); - config.chain_spec = Some(Box::new(chain_spec)); - config.network.transport = sc_network::config::TransportConfig::Normal { + let mut network = NetworkConfiguration::new( + format!("{} (Browser)", name), + "unknown", + Default::default(), + None, + ); + network.boot_nodes = chain_spec.boot_nodes().to_vec(); + network.transport = TransportConfig::Normal { wasm_external_transport: Some(transport.clone()), allow_private_ipv4: true, enable_mdns: false, use_yamux_flow_control: true, }; - config.task_executor = Some(Arc::new(move |fut| { - wasm_bindgen_futures::spawn_local(fut) - })); - config.telemetry_external_transport = Some(transport); - config.role = Role::Light; - config.name = format!("{} (Browser)", name); - config.database = Some({ - info!("Opening Indexed DB database '{}'...", name); - let db = kvdb_web::Database::open(name, 10) - .await?; - DatabaseConfig::Custom(Arc::new(db)) - }); - config.keystore = KeystoreConfig::InMemory; + + let config = Configuration { + network, + telemetry_endpoints: chain_spec.telemetry_endpoints().clone(), + chain_spec: Box::new(chain_spec), + task_executor: (|fut, _| wasm_bindgen_futures::spawn_local(fut)).into(), + telemetry_external_transport: Some(transport), + role: Role::Light, + database: { + info!("Opening Indexed DB database '{}'...", name); + let db = kvdb_web::Database::open(name, 10).await?; + + DatabaseConfig::Custom(sp_database::as_database(db)) + }, + keystore: KeystoreConfig::InMemory, + default_heap_pages: Default::default(), + dev_key_seed: Default::default(), + disable_grandpa: Default::default(), + execution_strategies: Default::default(), + force_authoring: Default::default(), + impl_name: String::from("parity-substrate"), + impl_version: String::from("0.0.0"), + offchain_worker: Default::default(), + prometheus_config: Default::default(), + pruning: Default::default(), + rpc_cors: Default::default(), + rpc_http: Default::default(), + rpc_ipc: Default::default(), + rpc_ws: Default::default(), + rpc_ws_max_connections: Default::default(), + rpc_methods: Default::default(), + state_cache_child_ratio: Default::default(), + state_cache_size: Default::default(), + tracing_receiver: Default::default(), + tracing_targets: Default::default(), + transaction_pool: Default::default(), + wasm_method: Default::default(), + max_runtime_instances: 8, + announce_block: true, + base_path: None, + informant_output_format: sc_informant::OutputFormat { + enable_color: false, + prefix: String::new(), + }, + }; Ok(config) } @@ -83,36 +121,25 @@ struct RpcMessage { } /// Create a Client object that connects to a service. -pub fn start_client(mut service: impl AbstractService) -> Client { - // Spawn informant - wasm_bindgen_futures::spawn_local( - sc_informant::build(&service, sc_informant::OutputFormat::Plain).map(drop) - ); - +pub fn start_client(mut task_manager: TaskManager, rpc_handlers: Arc) -> Client { // We 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(poll_fn(move |cx| { - loop { - match Pin::new(&mut rpc_send_rx).poll_next(cx) { - Poll::Ready(Some(message)) => { - let fut = service - .rpc_query(&message.session, &message.rpc_json) - .boxed(); - let _ = message.send_back.send(fut); - }, - Poll::Pending => break, - Poll::Ready(None) => return Poll::Ready(()), - } - } - - Pin::new(&mut service) - .poll(cx) - .map(drop) - })); + let (rpc_send_tx, rpc_send_rx) = mpsc::unbounded::(); + wasm_bindgen_futures::spawn_local( + select( + rpc_send_rx.for_each(move |message| { + let fut = rpc_handlers.rpc_query(&message.session, &message.rpc_json); + let _ = message.send_back.send(fut); + ready(()) + }), + Box::pin(async move { + let _ = task_manager.future().await; + }), + ).map(drop) + ); Client { rpc_send_tx, diff --git a/utils/build-script-utils/Cargo.toml b/utils/build-script-utils/Cargo.toml index 3fe10f6a825a82585396eccdd3d3c447edf9a9d4..9eada7bf820a03fc413a6b5ac6b5af4ee4c687dc 100644 --- a/utils/build-script-utils/Cargo.toml +++ b/utils/build-script-utils/Cargo.toml @@ -1,14 +1,15 @@ [package] name = "substrate-build-script-utils" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Crate with utility functions for `build.rs` scripts." -[dependencies] - [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +platforms = "0.2.1" diff --git a/utils/build-script-utils/src/git.rs b/utils/build-script-utils/src/git.rs new file mode 100644 index 0000000000000000000000000000000000000000..29c6a325fe7e929b757c365511af598ae1ac1713 --- /dev/null +++ b/utils/build-script-utils/src/git.rs @@ -0,0 +1,125 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::{env, fs, fs::File, io, io::Read, path::PathBuf}; + +/// Make sure the calling `build.rs` script is rerun when `.git/HEAD` or the ref of `.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() { + match get_git_paths(&manifest_dir) { + Err(err) => { + eprintln!("cargo:warning=Unable to read the Git repository: {}", err); + + return; + } + Ok(None) => {} + Ok(Some(paths)) => { + for p in paths { + println!("cargo:rerun-if-changed={}", p.display()); + } + + return; + } + } + + manifest_dir.pop(); + } + + println!( + "cargo:warning=Could not find `.git/HEAD` searching from `{}` upwards!", + manifest_dir_copy.display(), + ); +} + +// Code taken from https://github.com/rustyhorde/vergen/blob/8d522db8c8e16e26c0fc9ea8e6b0247cbf5cca84/src/output/envvar.rs +fn get_git_paths(path: &PathBuf) -> Result>, io::Error> { + let git_dir_or_file = path.join(".git"); + + if let Ok(metadata) = fs::metadata(&git_dir_or_file) { + if metadata.is_dir() { + // Echo the HEAD path + let git_head_path = git_dir_or_file.join("HEAD"); + + // Determine where HEAD points and echo that path also. + let mut f = File::open(&git_head_path)?; + let mut git_head_contents = String::new(); + let _ = f.read_to_string(&mut git_head_contents)?; + let ref_vec: Vec<&str> = git_head_contents.split(": ").collect(); + + if ref_vec.len() == 2 { + let current_head_file = ref_vec[1]; + let git_refs_path = git_dir_or_file.join(current_head_file); + + Ok(Some(vec![git_head_path, git_refs_path])) + } else { + Err(io::Error::new( + io::ErrorKind::Other, + "You are most likely in a detached HEAD state", + )) + } + } else if metadata.is_file() { + // We are in a worktree, so find out where the actual worktrees//HEAD file is. + let mut git_file = File::open(&git_dir_or_file)?; + let mut git_contents = String::new(); + let _ = git_file.read_to_string(&mut git_contents)?; + let dir_vec: Vec<&str> = git_contents.split(": ").collect(); + let git_path = dir_vec[1].trim(); + + // Echo the HEAD psth + let git_head_path = PathBuf::from(git_path).join("HEAD"); + + // Find out what the full path to the .git dir is. + let mut actual_git_dir = PathBuf::from(git_path); + actual_git_dir.pop(); + actual_git_dir.pop(); + + // Determine where HEAD points and echo that path also. + let mut f = File::open(&git_head_path)?; + let mut git_head_contents = String::new(); + let _ = f.read_to_string(&mut git_head_contents)?; + let ref_vec: Vec<&str> = git_head_contents.split(": ").collect(); + + if ref_vec.len() == 2 { + let current_head_file = ref_vec[1]; + let git_refs_path = actual_git_dir.join(current_head_file); + + Ok(Some(vec![git_head_path, git_refs_path])) + } else { + Err(io::Error::new( + io::ErrorKind::Other, + "You are most likely in a detached HEAD state", + )) + } + } else { + Err(io::Error::new( + io::ErrorKind::Other, + "Invalid .git format (Not a directory or a file)", + )) + } + } else { + Ok(None) + } +} diff --git a/utils/build-script-utils/src/lib.rs b/utils/build-script-utils/src/lib.rs index 1b915bdcafacb1e5ecc0b81c60d062d0537ed496..512e6dcaefda71686d53825a7446fc0c1568be28 100644 --- a/utils/build-script-utils/src/lib.rs +++ b/utils/build-script-utils/src/lib.rs @@ -1,44 +1,24 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! 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(); - } +mod version; +mod git; - println!( - "cargo:warning=Could not find `.git/HEAD` searching from `{}` upwards!", - manifest_dir_copy.display(), - ); -} +pub use git::*; +pub use version::*; diff --git a/utils/build-script-utils/src/version.rs b/utils/build-script-utils/src/version.rs new file mode 100644 index 0000000000000000000000000000000000000000..eefd3315921a692e0b1ee7dcc9b3d750be89a411 --- /dev/null +++ b/utils/build-script-utils/src/version.rs @@ -0,0 +1,67 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use platforms::*; +use std::{borrow::Cow, process::Command}; + +/// Generate the `cargo:` key output +pub fn generate_cargo_keys() { + let output = Command::new("git") + .args(&["rev-parse", "--short", "HEAD"]) + .output(); + + let commit = match output { + Ok(o) if o.status.success() => { + let sha = String::from_utf8_lossy(&o.stdout).trim().to_owned(); + Cow::from(sha) + } + Ok(o) => { + println!("cargo:warning=Git command failed with status: {}", o.status); + Cow::from("unknown-commit") + }, + Err(err) => { + println!("cargo:warning=Failed to execute git command: {}", err); + Cow::from("unknown-commit") + }, + }; + + println!("cargo:rustc-env=SUBSTRATE_CLI_IMPL_VERSION={}", get_version(&commit)) +} + +fn get_platform() -> String { + let env_dash = if TARGET_ENV.is_some() { "-" } else { "" }; + + format!( + "{}-{}{}{}", + TARGET_ARCH.as_str(), + TARGET_OS.as_str(), + env_dash, + TARGET_ENV.map(|x| x.as_str()).unwrap_or(""), + ) +} + +fn get_version(impl_commit: &str) -> String { + let commit_dash = if impl_commit.is_empty() { "" } else { "-" }; + + format!( + "{}{}{}-{}", + std::env::var("CARGO_PKG_VERSION").unwrap_or_default(), + commit_dash, + impl_commit, + get_platform(), + ) +} diff --git a/utils/fork-tree/Cargo.toml b/utils/fork-tree/Cargo.toml index e46618feb8e5a9d8dc4aed8f100c5f6bfcea1323..a1aaea70b1f54aa3aa9ff882e99a97c5c1ae989b 100644 --- a/utils/fork-tree/Cargo.toml +++ b/utils/fork-tree/Cargo.toml @@ -1,16 +1,16 @@ [package] name = "fork-tree" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Utility library for managing tree-like ordered data with logic for pruning the tree while finalizing nodes." documentation = "https://docs.rs/fork-tree" -[dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive"] } - [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.3.1", features = ["derive"] } diff --git a/utils/fork-tree/src/lib.rs b/utils/fork-tree/src/lib.rs index 1e7b48fed07076a29a184579dc79f622c2e028ac..e11c1138f49db4ef07c466e01281dbc6df085c95 100644 --- a/utils/fork-tree/src/lib.rs +++ b/utils/fork-tree/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Utility library for managing tree-like ordered data with logic for pruning //! the tree while finalizing nodes. @@ -114,7 +115,7 @@ impl ForkTree where )?; let removed = if let Some(mut root_index) = new_root_index { - let mut old_roots = std::mem::replace(&mut self.roots, Vec::new()); + let mut old_roots = std::mem::take(&mut self.roots); let mut root = None; let mut cur_children = Some(&mut old_roots); @@ -137,7 +138,7 @@ impl ForkTree where // we found the deepest ancestor of the finalized block, so we prune // out any children that don't include the finalized block. - let root_children = std::mem::replace(&mut root.children, Vec::new()); + let root_children = std::mem::take(&mut root.children); let mut is_first = true; for child in root_children { @@ -306,7 +307,7 @@ impl ForkTree where } } - /// Same as [`find_node_where`](Self::find_node_where), but returns mutable reference. + /// Same as [`find_node_where`](ForkTree::find_node_where), but returns mutable reference. pub fn find_node_where_mut( &mut self, hash: &H, @@ -331,7 +332,7 @@ impl ForkTree where Ok(None) } - /// Same as [`find_node_where`](Self::find_node_where), but returns indexes. + /// Same as [`find_node_where`](ForkTree::find_node_where), but returns indexes. pub fn find_node_index_where( &self, hash: &H, diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml index f4b72187478d47c63575c01ad27d86500c160816..db620c86ca98e3522dab0591872424e2d3136bd6 100644 --- a/utils/frame/benchmarking-cli/Cargo.toml +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -1,30 +1,30 @@ [package] name = "frame-benchmarking-cli" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "CLI for benchmarking FRAME" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -frame-benchmarking = { version = "2.0.0-alpha.5", path = "../../../frame/benchmarking" } -sp-core = { version = "2.0.0-alpha.5", path = "../../../primitives/core" } -sc-service = { version = "0.8.0-alpha.5", default-features = false, path = "../../../client/service" } -sc-cli = { version = "0.8.0-alpha.5", path = "../../../client/cli" } -sc-client = { version = "0.8.0-alpha.5", path = "../../../client" } -sc-client-db = { version = "0.8.0-alpha.5", path = "../../../client/db" } -sc-executor = { version = "0.8.0-alpha.5", path = "../../../client/executor" } -sp-externalities = { version = "0.8.0-alpha.5", path = "../../../primitives/externalities" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime" } -sp-state-machine = { version = "0.8.0-alpha.5", path = "../../../primitives/state-machine" } +Inflector = "0.11.4" +frame-benchmarking = { version = "2.0.0-rc4", path = "../../../frame/benchmarking" } +sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" } +sc-service = { version = "0.8.0-rc4", default-features = false, path = "../../../client/service" } +sc-cli = { version = "0.8.0-rc4", path = "../../../client/cli" } +sc-client-db = { version = "0.8.0-rc4", path = "../../../client/db" } +sc-executor = { version = "0.8.0-rc4", path = "../../../client/executor" } +sp-externalities = { version = "0.8.0-rc4", path = "../../../primitives/externalities" } +sp-runtime = { version = "2.0.0-rc4", path = "../../../primitives/runtime" } +sp-state-machine = { version = "0.8.0-rc4", path = "../../../primitives/state-machine" } structopt = "0.3.8" -codec = { version = "1.3.0", package = "parity-scale-codec" } +codec = { version = "1.3.1", package = "parity-scale-codec" } [features] -default = ["rocksdb"] -rocksdb = ["sc-client-db/kvdb-rocksdb"] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +default = ["db"] +db = ["sc-client-db/with-kvdb-rocksdb", "sc-client-db/with-parity-db"] diff --git a/utils/frame/benchmarking-cli/src/command.rs b/utils/frame/benchmarking-cli/src/command.rs new file mode 100644 index 0000000000000000000000000000000000000000..09b246e4766a3bf77a3ebeea4dc45d80c93c6ec2 --- /dev/null +++ b/utils/frame/benchmarking-cli/src/command.rs @@ -0,0 +1,185 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::BenchmarkCmd; +use codec::{Decode, Encode}; +use frame_benchmarking::{Analysis, BenchmarkBatch, BenchmarkSelector}; +use sc_cli::{SharedParams, CliConfiguration, ExecutionStrategy, Result}; +use sc_client_db::BenchmarkingState; +use sc_executor::NativeExecutor; +use sp_state_machine::StateMachine; +use sp_externalities::Extensions; +use sc_service::{Configuration, NativeExecutionDispatch}; +use sp_runtime::{ + traits::{Block as BlockT, Header as HeaderT, NumberFor}, +}; +use sp_core::{ + tasks, + testing::KeyStore, + traits::KeystoreExt, + offchain::{OffchainExt, testing::TestOffchainExt}, +}; +use std::fmt::Debug; + +impl BenchmarkCmd { + /// Runs the command and benchmarks the chain. + pub fn run(&self, config: Configuration) -> Result<()> + where + BB: BlockT + Debug, + <<::Header as HeaderT>::Number as std::str::FromStr>::Err: std::fmt::Debug, + ::Hash: std::str::FromStr, + ExecDispatch: NativeExecutionDispatch + 'static, + { + let spec = config.chain_spec; + let wasm_method = self.wasm_method.into(); + let strategy = self.execution.unwrap_or(ExecutionStrategy::Native); + + let genesis_storage = spec.build_storage()?; + let mut changes = Default::default(); + let mut offchain_changes = Default::default(); + let cache_size = Some(self.database_cache_size as usize); + let state = BenchmarkingState::::new(genesis_storage, cache_size)?; + let executor = NativeExecutor::::new( + wasm_method, + self.heap_pages, + 2, // The runtime instances cache size. + ); + + let mut extensions = Extensions::default(); + extensions.register(KeystoreExt(KeyStore::new())); + let (offchain, _) = TestOffchainExt::new(); + extensions.register(OffchainExt::new(offchain)); + + let result = StateMachine::<_, _, NumberFor, _>::new( + &state, + None, + &mut changes, + &mut offchain_changes, + &executor, + "Benchmark_dispatch_benchmark", + &( + &self.pallet, + &self.extrinsic, + self.lowest_range_values.clone(), + self.highest_range_values.clone(), + self.steps.clone(), + self.repeat, + ).encode(), + extensions, + &sp_state_machine::backend::BackendRuntimeCode::new(&state).runtime_code()?, + tasks::executor(), + ) + .execute(strategy.into()) + .map_err(|e| format!("Error executing runtime benchmark: {:?}", e))?; + + let results = , String> as Decode>::decode(&mut &result[..]) + .map_err(|e| format!("Failed to decode benchmark results: {:?}", e))?; + + if self.output { + if self.weight_trait { + let mut file = crate::writer::open_file("traits.rs")?; + crate::writer::write_trait(&mut file, results.clone())?; + } else { + let mut file = crate::writer::open_file("benchmarks.rs")?; + crate::writer::write_results(&mut file, results.clone())?; + } + } + + match results { + Ok(batches) => for batch in batches.into_iter() { + // Print benchmark metadata + println!( + "Pallet: {:?}, Extrinsic: {:?}, Lowest values: {:?}, Highest values: {:?}, Steps: {:?}, Repeat: {:?}", + String::from_utf8(batch.pallet).expect("Encoded from String; qed"), + String::from_utf8(batch.benchmark).expect("Encoded from String; qed"), + self.lowest_range_values, + self.highest_range_values, + self.steps, + self.repeat, + ); + + // Skip raw data + analysis if there are no results + if batch.results.len() == 0 { continue } + + if self.raw_data { + // Print the table header + batch.results[0].components.iter().for_each(|param| print!("{:?},", param.0)); + + print!("extrinsic_time,storage_root_time,reads,repeat_reads,writes,repeat_writes\n"); + // Print the values + batch.results.iter().for_each(|result| { + let parameters = &result.components; + parameters.iter().for_each(|param| print!("{:?},", param.1)); + // Print extrinsic time and storage root time + print!("{:?},{:?},{:?},{:?},{:?},{:?}\n", + result.extrinsic_time, + result.storage_root_time, + result.reads, + result.repeat_reads, + result.writes, + result.repeat_writes, + ); + }); + + println!(); + } + + // Conduct analysis. + if !self.no_median_slopes { + println!("Median Slopes Analysis\n========"); + if let Some(analysis) = Analysis::median_slopes(&batch.results, BenchmarkSelector::ExtrinsicTime) { + println!("-- Extrinsic Time --\n{}", analysis); + } + if let Some(analysis) = Analysis::median_slopes(&batch.results, BenchmarkSelector::Reads) { + println!("Reads = {:?}", analysis); + } + if let Some(analysis) = Analysis::median_slopes(&batch.results, BenchmarkSelector::Writes) { + println!("Writes = {:?}", analysis); + } + } + if !self.no_min_squares { + println!("Min Squares Analysis\n========"); + if let Some(analysis) = Analysis::min_squares_iqr(&batch.results, BenchmarkSelector::ExtrinsicTime) { + println!("-- Extrinsic Time --\n{}", analysis); + } + if let Some(analysis) = Analysis::min_squares_iqr(&batch.results, BenchmarkSelector::Reads) { + println!("Reads = {:?}", analysis); + } + if let Some(analysis) = Analysis::min_squares_iqr(&batch.results, BenchmarkSelector::Writes) { + println!("Writes = {:?}", analysis); + } + } + }, + Err(error) => eprintln!("Error: {:?}", error), + } + + Ok(()) + } +} + +impl CliConfiguration for BenchmarkCmd { + fn shared_params(&self) -> &SharedParams { + &self.shared_params + } + + fn chain_id(&self, _is_dev: bool) -> Result { + Ok(match self.shared_params.chain { + Some(ref chain) => chain.clone(), + None => "dev".into(), + }) + } +} diff --git a/utils/frame/benchmarking-cli/src/lib.rs b/utils/frame/benchmarking-cli/src/lib.rs index 926d140e024098cc0a30787d4a458e27c05ae8db..8a53c9fd8b16bc1518157805eddaddd1087fd009 100644 --- a/utils/frame/benchmarking-cli/src/lib.rs +++ b/utils/frame/benchmarking-cli/src/lib.rs @@ -1,37 +1,28 @@ -// Copyright 2020 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 . - +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +mod command; +mod writer; + +use sc_cli::{ExecutionStrategy, WasmExecutionMethod}; use std::fmt::Debug; -use sp_runtime::{traits::{Block as BlockT, Header as HeaderT, NumberFor}}; -use sc_client::StateMachine; -use sc_cli::{ExecutionStrategy, WasmExecutionMethod, VersionInfo}; -use sc_client_db::BenchmarkingState; -use sc_service::{Configuration, ChainSpec}; -use sc_executor::{NativeExecutor, NativeExecutionDispatch}; -use codec::{Encode, Decode}; -use frame_benchmarking::{BenchmarkBatch, Analysis}; -use sp_core::{ - tasks, - traits::KeystoreExt, - testing::KeyStore, -}; -use sp_externalities::Extensions; /// The `benchmark` command used to benchmark FRAME Pallets. -#[derive(Debug, structopt::StructOpt, Clone)] +#[derive(Debug, structopt::StructOpt)] pub struct BenchmarkCmd { /// Select a FRAME Pallet to benchmark, or `*` for all (in which case `extrinsic` must be `*`). #[structopt(short, long)] @@ -69,6 +60,18 @@ pub struct BenchmarkCmd { #[structopt(long)] pub no_min_squares: bool, + /// Output the benchmarks to a Rust file. + #[structopt(long)] + pub output: bool, + + /// Output the trait definition to a Rust file. + #[structopt(long)] + pub weight_trait: bool, + + /// Set the heap pages while running benchmarks. + #[structopt(long)] + pub heap_pages: Option, + #[allow(missing_docs)] #[structopt(flatten)] pub shared_params: sc_cli::SharedParams, @@ -96,128 +99,3 @@ pub struct BenchmarkCmd { #[structopt(long = "db-cache", value_name = "MiB", default_value = "128")] pub database_cache_size: u32, } - -impl BenchmarkCmd { - /// Initialize - pub fn init(&self, version: &sc_cli::VersionInfo) -> sc_cli::Result<()> { - self.shared_params.init(version) - } - - /// Runs the command and benchmarks the chain. - pub fn run( - self, - config: Configuration, - ) -> sc_cli::Result<()> - where - BB: BlockT + Debug, - <<::Header as HeaderT>::Number as std::str::FromStr>::Err: std::fmt::Debug, - ::Hash: std::str::FromStr, - ExecDispatch: NativeExecutionDispatch + 'static, - { - let spec = config.chain_spec.expect("chain_spec is always Some"); - let wasm_method = self.wasm_method.into(); - let strategy = self.execution.unwrap_or(ExecutionStrategy::Native); - - let genesis_storage = spec.build_storage()?; - let mut changes = Default::default(); - let cache_size = Some(self.database_cache_size as usize); - let state = BenchmarkingState::::new(genesis_storage, cache_size)?; - let executor = NativeExecutor::::new( - wasm_method, - None, // heap pages - 2, // The runtime instances cache size. - ); - - let mut extensions = Extensions::default(); - extensions.register(KeystoreExt(KeyStore::new())); - - let result = StateMachine::<_, _, NumberFor, _>::new( - &state, - None, - &mut changes, - &executor, - "Benchmark_dispatch_benchmark", - &( - &self.pallet, - &self.extrinsic, - self.lowest_range_values.clone(), - self.highest_range_values.clone(), - self.steps.clone(), - self.repeat, - ).encode(), - extensions, - &sp_state_machine::backend::BackendRuntimeCode::new(&state).runtime_code()?, - tasks::executor(), - ) - .execute(strategy.into()) - .map_err(|e| format!("Error executing runtime benchmark: {:?}", e))?; - - let results = , String> as Decode>::decode(&mut &result[..]) - .map_err(|e| format!("Failed to decode benchmark results: {:?}", e))?; - - match results { - Ok(batches) => for batch in batches.into_iter() { - // Print benchmark metadata - println!( - "Pallet: {:?}, Extrinsic: {:?}, Lowest values: {:?}, Highest values: {:?}, Steps: {:?}, Repeat: {:?}", - String::from_utf8(batch.pallet).expect("Encoded from String; qed"), - String::from_utf8(batch.benchmark).expect("Encoded from String; qed"), - self.lowest_range_values, - self.highest_range_values, - self.steps, - self.repeat, - ); - - if self.raw_data { - // Print the table header - batch.results[0].0.iter().for_each(|param| print!("{:?},", param.0)); - - print!("extrinsic_time,storage_root_time\n"); - // Print the values - batch.results.iter().for_each(|result| { - let parameters = &result.0; - parameters.iter().for_each(|param| print!("{:?},", param.1)); - // Print extrinsic time and storage root time - print!("{:?},{:?}\n", result.1, result.2); - }); - - print!("\n"); - } - - // Conduct analysis. - if !self.no_median_slopes { - if let Some(analysis) = Analysis::median_slopes(&batch.results) { - println!("Median Slopes Analysis\n========\n{}", analysis); - } - } - if !self.no_min_squares { - if let Some(analysis) = Analysis::min_squares_iqr(&batch.results) { - println!("Min Squares Analysis\n========\n{}", analysis); - } - } - }, - Err(error) => eprintln!("Error: {:?}", error), - } - - Ok(()) - } - - /// Update and prepare a `Configuration` with command line parameters - pub fn update_config( - &self, - mut config: &mut Configuration, - spec_factory: impl FnOnce(&str) -> Result, String>, - _version: &VersionInfo, - ) -> sc_cli::Result<()> - { - // Configure chain spec. - let chain_key = self.shared_params.chain.clone().unwrap_or("dev".into()); - let spec = spec_factory(&chain_key)?; - config.chain_spec = Some(spec); - - // Make sure to configure keystore. - config.use_in_memory_keystore()?; - - Ok(()) - } -} diff --git a/utils/frame/benchmarking-cli/src/writer.rs b/utils/frame/benchmarking-cli/src/writer.rs new file mode 100644 index 0000000000000000000000000000000000000000..bd411b536a826377190f3311c938861bfa1d5701 --- /dev/null +++ b/utils/frame/benchmarking-cli/src/writer.rs @@ -0,0 +1,191 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Outputs benchmark results to Rust files that can be ingested by the runtime. + +use std::fs::{File, OpenOptions}; +use std::io::prelude::*; +use frame_benchmarking::{BenchmarkBatch, BenchmarkSelector, Analysis}; +use inflector::Inflector; + +pub fn open_file(path: &str) -> Result { + OpenOptions::new() + .create(true) + .write(true) + .append(true) + .open(path) +} + +pub fn write_trait(file: &mut File, batches: Result, String>) -> Result<(), std::io::Error> { + let batches = batches.unwrap(); + + let mut current_pallet = Vec::::new(); + + batches.iter().for_each(|batch| { + + let pallet_string = String::from_utf8(batch.pallet.clone()).unwrap(); + let benchmark_string = String::from_utf8(batch.benchmark.clone()).unwrap(); + + // only create new trait definitions when we go to a new pallet + if batch.pallet != current_pallet { + if !current_pallet.is_empty() { + // close trait + write!(file, "}}\n").unwrap(); + } + + // trait wrapper + write!(file, "// {}\n", pallet_string).unwrap(); + write!(file, "pub trait WeightInfo {{\n").unwrap(); + + current_pallet = batch.pallet.clone() + } + + // function name + write!(file, " fn {}(", benchmark_string).unwrap(); + + // params + let components = &batch.results[0].components; + for component in components { + write!(file, "{:?}: u32, ", component.0).unwrap(); + } + // return value + write!(file, ") -> Weight;\n").unwrap(); + }); + + // final close trait + write!(file, "}}\n").unwrap(); + + // Reset + current_pallet = Vec::::new(); + + batches.iter().for_each(|batch| { + + let benchmark_string = String::from_utf8(batch.benchmark.clone()).unwrap(); + + // only create new trait definitions when we go to a new pallet + if batch.pallet != current_pallet { + if !current_pallet.is_empty() { + // close trait + write!(file, "}}\n").unwrap(); + } + + // impl trait + write!(file, "\n").unwrap(); + write!(file, "impl WeightInfo for () {{\n").unwrap(); + + current_pallet = batch.pallet.clone() + } + + // function name + write!(file, " fn {}(", benchmark_string).unwrap(); + + // params + let components = &batch.results[0].components; + for component in components { + write!(file, "_{:?}: u32, ", component.0).unwrap(); + } + // return value + write!(file, ") -> Weight {{ 1_000_000_000 }}\n").unwrap(); + }); + + // final close trait + write!(file, "}}\n").unwrap(); + + Ok(()) +} + +pub fn write_results(file: &mut File, batches: Result, String>) -> Result<(), std::io::Error> { + let batches = batches.unwrap(); + + let mut current_pallet = Vec::::new(); + + // general imports + write!(file, "use frame_support::weights::{{Weight, constants::RocksDbWeight as DbWeight}};\n").unwrap(); + + batches.iter().for_each(|batch| { + + let pallet_string = String::from_utf8(batch.pallet.clone()).unwrap(); + let benchmark_string = String::from_utf8(batch.benchmark.clone()).unwrap(); + + // only create new trait definitions when we go to a new pallet + if batch.pallet != current_pallet { + if !current_pallet.is_empty() { + // close trait + write!(file, "}}\n").unwrap(); + } + + // struct for weights + write!(file, "pub struct WeightFor{};\n", + pallet_string.to_pascal_case(), + ).unwrap(); + + // trait wrapper + write!(file, "impl {}::WeightInfo for WeightFor{} {{\n", + pallet_string, + pallet_string.to_pascal_case(), + ).unwrap(); + + current_pallet = batch.pallet.clone() + } + + // function name + write!(file, " fn {}(", benchmark_string).unwrap(); + + // params + let components = &batch.results[0].components; + for component in components { + write!(file, "{:?}: u32, ", component.0).unwrap(); + } + // return value + write!(file, ") -> Weight {{\n").unwrap(); + + let extrinsic_time = Analysis::min_squares_iqr(&batch.results, BenchmarkSelector::ExtrinsicTime).unwrap(); + write!(file, " ({} as Weight)\n", extrinsic_time.base.saturating_mul(1000)).unwrap(); + extrinsic_time.slopes.iter().zip(extrinsic_time.names.iter()).for_each(|(slope, name)| { + write!(file, " .saturating_add(({} as Weight).saturating_mul({} as Weight))\n", + slope.saturating_mul(1000), + name, + ).unwrap(); + }); + + let reads = Analysis::min_squares_iqr(&batch.results, BenchmarkSelector::Reads).unwrap(); + write!(file, " .saturating_add(DbWeight::get().reads({} as Weight))\n", reads.base).unwrap(); + reads.slopes.iter().zip(reads.names.iter()).for_each(|(slope, name)| { + write!(file, " .saturating_add(DbWeight::get().reads(({} as Weight).saturating_mul({} as Weight)))\n", + slope, + name, + ).unwrap(); + }); + + let writes = Analysis::min_squares_iqr(&batch.results, BenchmarkSelector::Writes).unwrap(); + write!(file, " .saturating_add(DbWeight::get().writes({} as Weight))\n", writes.base).unwrap(); + writes.slopes.iter().zip(writes.names.iter()).for_each(|(slope, name)| { + write!(file, " .saturating_add(DbWeight::get().writes(({} as Weight).saturating_mul({} as Weight)))\n", + slope, + name, + ).unwrap(); + }); + + // close function + write!(file, " }}\n").unwrap(); + }); + + // final close trait + write!(file, "}}\n").unwrap(); + + Ok(()) +} diff --git a/utils/frame/rpc/support/Cargo.toml b/utils/frame/rpc/support/Cargo.toml index 72884330d2e8224cc9959beb5c23bcd67166dea1..ec4d06c93c9cca1d1cb8f3a55268fbd2ea9480b8 100644 --- a/utils/frame/rpc/support/Cargo.toml +++ b/utils/frame/rpc/support/Cargo.toml @@ -1,26 +1,26 @@ [package] name = "substrate-frame-rpc-support" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies ", "Andrew Dirksen "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate RPC for FRAME's support" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] futures = { version = "0.3.0", features = ["compat"] } -jsonrpc-client-transports = { version = "14.0.5", default-features = false, features = ["http"] } -jsonrpc-core = "14" -codec = { package = "parity-scale-codec", version = "1" } +jsonrpc-client-transports = { version = "14.2.0", default-features = false, features = ["http"] } +jsonrpc-core = "14.2.0" +codec = { package = "parity-scale-codec", version = "1.3.1" } serde = "1" -frame-support = { version = "2.0.0-alpha.5", path = "../../../../frame/support" } -sp-storage = { version = "2.0.0-alpha.5", path = "../../../../primitives/storage" } -sc-rpc-api = { version = "0.8.0-alpha.5", path = "../../../../client/rpc-api" } +frame-support = { version = "2.0.0-rc4", path = "../../../../frame/support" } +sp-storage = { version = "2.0.0-rc4", path = "../../../../primitives/storage" } +sc-rpc-api = { version = "0.8.0-rc4", path = "../../../../client/rpc-api" } [dev-dependencies] -frame-system = { version = "2.0.0-alpha.5", path = "../../../../frame/system" } +frame-system = { version = "2.0.0-rc4", path = "../../../../frame/system" } tokio = "0.2" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/utils/frame/rpc/support/src/lib.rs b/utils/frame/rpc/support/src/lib.rs index 118f5709a6b7044712002d851fc49dbbd2b5eb6a..dc87d6185209deba1c02a4f0f8abb3973f361199 100644 --- a/utils/frame/rpc/support/src/lib.rs +++ b/utils/frame/rpc/support/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Combines [sc_rpc_api::state::StateClient] with [frame_support::storage::generator] traits //! to provide strongly typed chain state queries over rpc. diff --git a/utils/frame/rpc/system/Cargo.toml b/utils/frame/rpc/system/Cargo.toml index a9e775393dfb17702933d17399a80824872ba5ee..1d655bcca3470bdfe2af43135bf51e1ba03a8bfe 100644 --- a/utils/frame/rpc/system/Cargo.toml +++ b/utils/frame/rpc/system/Cargo.toml @@ -1,33 +1,35 @@ [package] name = "substrate-frame-rpc-system" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME's system exposed over Substrate RPC" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sc-client = { version = "0.8.0-alpha.5", path = "../../../../client/" } -codec = { package = "parity-scale-codec", version = "1.3.0" } -futures = "0.3.4" -jsonrpc-core = "14.0.3" -jsonrpc-core-client = "14.0.5" -jsonrpc-derive = "14.0.3" +sc-client-api = { version = "2.0.0-rc4", path = "../../../../client/api" } +codec = { package = "parity-scale-codec", version = "1.3.1" } +futures = { version = "0.3.4", features = ["compat"] } +jsonrpc-core = "14.2.0" +jsonrpc-core-client = "14.2.0" +jsonrpc-derive = "14.2.1" log = "0.4.8" serde = { version = "1.0.101", features = ["derive"] } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../../../primitives/runtime" } -sp-api = { version = "2.0.0-alpha.5", path = "../../../../primitives/api" } -frame-system-rpc-runtime-api = { version = "2.0.0-alpha.5", path = "../../../../frame/system/rpc/runtime-api" } -sp-core = { version = "2.0.0-alpha.5", path = "../../../../primitives/core" } -sp-blockchain = { version = "2.0.0-alpha.5", path = "../../../../primitives/blockchain" } -sp-transaction-pool = { version = "2.0.0-alpha.5", path = "../../../../primitives/transaction-pool" } +sp-runtime = { version = "2.0.0-rc4", path = "../../../../primitives/runtime" } +sp-api = { version = "2.0.0-rc4", path = "../../../../primitives/api" } +frame-system-rpc-runtime-api = { version = "2.0.0-rc4", path = "../../../../frame/system/rpc/runtime-api" } +sp-core = { version = "2.0.0-rc4", path = "../../../../primitives/core" } +sp-blockchain = { version = "2.0.0-rc4", path = "../../../../primitives/blockchain" } +sp-transaction-pool = { version = "2.0.0-rc4", path = "../../../../primitives/transaction-pool" } +sp-block-builder = { version = "2.0.0-rc4", path = "../../../../primitives/block-builder" } +sc-rpc-api = { version = "0.8.0-rc4", path = "../../../../client/rpc-api" } [dev-dependencies] -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../../../test-utils/runtime/client" } +substrate-test-runtime-client = { version = "2.0.0-rc4", path = "../../../../test-utils/runtime/client" } env_logger = "0.7.0" -sc-transaction-pool = { version = "2.0.0-alpha.5", path = "../../../../client/transaction-pool" } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +sc-transaction-pool = { version = "2.0.0-rc4", path = "../../../../client/transaction-pool" } diff --git a/utils/frame/rpc/system/src/lib.rs b/utils/frame/rpc/system/src/lib.rs index c73ddfe93efa067d8188f9abb66c554c9865baad..dc87f622fdc08d47fde608ec7fe71f4e04990bec 100644 --- a/utils/frame/rpc/system/src/lib.rs +++ b/utils/frame/rpc/system/src/lib.rs @@ -1,31 +1,29 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! System FRAME specific RPC methods. use std::sync::Arc; use codec::{self, Codec, Decode, Encode}; -use sc_client::{ - light::blockchain::{future_header, RemoteBlockchain}, - light::fetcher::{Fetcher, RemoteCallRequest}, -}; +use sc_client_api::light::{future_header, RemoteBlockchain, Fetcher, RemoteCallRequest}; use jsonrpc_core::{ - Error, ErrorCode, - futures::future::{result, Future}, + Error as RpcError, ErrorCode, + futures::future::{self as rpc_future,result, Future}, }; use jsonrpc_derive::rpc; use futures::future::{ready, TryFutureExt}; @@ -37,18 +35,20 @@ use sp_runtime::{ generic::BlockId, traits, }; -use sp_core::hexdisplay::HexDisplay; +use sp_core::{hexdisplay::HexDisplay, Bytes}; use sp_transaction_pool::{TransactionPool, InPoolTransaction}; +use sp_block_builder::BlockBuilder; +use sc_rpc_api::DenyUnsafe; pub use frame_system_rpc_runtime_api::AccountNonceApi; pub use self::gen_client::Client as SystemClient; /// Future that resolves to account nonce. -pub type FutureResult = Box + Send>; +pub type FutureResult = Box + Send>; /// System RPC methods. #[rpc] -pub trait SystemApi { +pub trait SystemApi { /// Returns the next valid index (aka nonce) for given account. /// /// This method takes into consideration all pending transactions @@ -56,34 +56,57 @@ pub trait SystemApi { /// it fallbacks to query the index from the runtime (aka. state nonce). #[rpc(name = "system_accountNextIndex", alias("account_nextIndex"))] fn nonce(&self, account: AccountId) -> FutureResult; + + /// Dry run an extrinsic at a given block. Return SCALE encoded ApplyExtrinsicResult. + #[rpc(name = "system_dryRun", alias("system_dryRunAt"))] + fn dry_run(&self, extrinsic: Bytes, at: Option) -> FutureResult; } -const RUNTIME_ERROR: i64 = 1; +/// 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, + } + } +} /// An implementation of System-specific RPC methods on full client. pub struct FullSystem { client: Arc, pool: Arc

, + deny_unsafe: DenyUnsafe, _marker: std::marker::PhantomData, } impl FullSystem { /// Create new `FullSystem` given client and transaction pool. - pub fn new(client: Arc, pool: Arc

) -> Self { + pub fn new(client: Arc, pool: Arc

, deny_unsafe: DenyUnsafe,) -> Self { FullSystem { client, pool, + deny_unsafe, _marker: Default::default(), } } } -impl SystemApi for FullSystem +impl SystemApi<::Hash, AccountId, Index> + for FullSystem where C: sp_api::ProvideRuntimeApi, C: HeaderBackend, C: Send + Sync + 'static, C::Api: AccountNonceApi, + C::Api: BlockBuilder, P: TransactionPool + 'static, Block: traits::Block, AccountId: Clone + std::fmt::Display + Codec, @@ -95,8 +118,8 @@ where 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), + let nonce = api.account_nonce(&at, account.clone()).map_err(|e| RpcError { + code: ErrorCode::ServerError(Error::RuntimeError.into()), message: "Unable to query nonce.".into(), data: Some(format!("{:?}", e).into()), })?; @@ -106,6 +129,38 @@ where Box::new(result(get_nonce())) } + + fn dry_run(&self, extrinsic: Bytes, at: Option<::Hash>) -> FutureResult { + if let Err(err) = self.deny_unsafe.check_if_safe() { + return Box::new(rpc_future::err(err.into())); + } + + let dry_run = || { + 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 uxt: ::Extrinsic = Decode::decode(&mut &*extrinsic).map_err(|e| RpcError { + code: ErrorCode::ServerError(Error::DecodeError.into()), + message: "Unable to dry run extrinsic.".into(), + data: Some(format!("{:?}", e).into()), + })?; + + let result = api.apply_extrinsic(&at, uxt) + .map_err(|e| RpcError { + code: ErrorCode::ServerError(Error::RuntimeError.into()), + message: "Unable to dry run extrinsic.".into(), + data: Some(format!("{:?}", e).into()), + })?; + + Ok(Encode::encode(&result).into()) + }; + + + Box::new(result(dry_run())) + } } /// An implementation of System-specific RPC methods on light client. @@ -133,7 +188,8 @@ impl LightSystem { } } -impl SystemApi for LightSystem +impl SystemApi<::Hash, AccountId, Index> + for LightSystem where P: TransactionPool + 'static, C: HeaderBackend, @@ -167,8 +223,8 @@ where ).compat(); let future_nonce = future_nonce.and_then(|nonce| Decode::decode(&mut &nonce[..]) .map_err(|e| ClientError::CallResultDecode("Cannot decode account nonce", e))); - let future_nonce = future_nonce.map_err(|e| Error { - code: ErrorCode::ServerError(RUNTIME_ERROR), + let future_nonce = future_nonce.map_err(|e| RpcError { + code: ErrorCode::ServerError(Error::RuntimeError.into()), message: "Unable to query nonce.".into(), data: Some(format!("{:?}", e).into()), }); @@ -178,6 +234,14 @@ where Box::new(future_nonce) } + + fn dry_run(&self, _extrinsic: Bytes, _at: Option<::Hash>) -> FutureResult { + Box::new(result(Err(RpcError { + code: ErrorCode::MethodNotFound, + message: "Unable to dry run extrinsic.".into(), + data: None, + }))) + } } /// Adjust account nonce from state, so that tx with the nonce will be @@ -224,19 +288,23 @@ mod tests { use super::*; use futures::executor::block_on; - use substrate_test_runtime_client::{ - runtime::Transfer, - AccountKeyring, - }; + use substrate_test_runtime_client::{runtime::Transfer, AccountKeyring}; use sc_transaction_pool::{BasicPool, FullChainApi}; + use sp_runtime::{ApplyExtrinsicResult, transaction_validity::{TransactionValidityError, InvalidTransaction}}; #[test] fn should_return_next_nonce_for_some_account() { - // given let _ = env_logger::try_init(); + + // given let client = Arc::new(substrate_test_runtime_client::new()); - let pool = Arc::new( - BasicPool::new(Default::default(), Arc::new(FullChainApi::new(client.clone()))).0 + let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let pool = BasicPool::new_full( + Default::default(), + Arc::new(FullChainApi::new(client.clone(), None)), + None, + spawner, + client.clone(), ); let source = sp_runtime::transaction_validity::TransactionSource::External; @@ -255,7 +323,7 @@ mod tests { let ext1 = new_transaction(1); block_on(pool.submit_one(&BlockId::number(0), source, ext1)).unwrap(); - let accounts = FullSystem::new(client, pool); + let accounts = FullSystem::new(client, pool, DenyUnsafe::Yes); // when let nonce = accounts.nonce(AccountKeyring::Alice.into()); @@ -263,4 +331,94 @@ mod tests { // then assert_eq!(nonce.wait().unwrap(), 2); } + + #[test] + fn dry_run_should_deny_unsafe() { + let _ = env_logger::try_init(); + + // given + let client = Arc::new(substrate_test_runtime_client::new()); + let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let pool = BasicPool::new_full( + Default::default(), + Arc::new(FullChainApi::new(client.clone(), None)), + None, + spawner, + client.clone(), + ); + + let accounts = FullSystem::new(client, pool, DenyUnsafe::Yes); + + // when + let res = accounts.dry_run(vec![].into(), None); + + // then + assert_eq!(res.wait(), Err(RpcError::method_not_found())); + } + + #[test] + fn dry_run_should_work() { + let _ = env_logger::try_init(); + + // given + let client = Arc::new(substrate_test_runtime_client::new()); + let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let pool = BasicPool::new_full( + Default::default(), + Arc::new(FullChainApi::new(client.clone(), None)), + None, + spawner, + client.clone(), + ); + + let accounts = FullSystem::new(client, pool, DenyUnsafe::No); + + let tx = Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Bob.into(), + amount: 5, + nonce: 0, + }.into_signed_tx(); + + // when + let res = accounts.dry_run(tx.encode().into(), None); + + // then + let bytes = res.wait().unwrap().0; + let apply_res: ApplyExtrinsicResult = Decode::decode(&mut bytes.as_slice()).unwrap(); + assert_eq!(apply_res, Ok(Ok(()))); + } + + #[test] + fn dry_run_should_indicate_error() { + let _ = env_logger::try_init(); + + // given + let client = Arc::new(substrate_test_runtime_client::new()); + let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let pool = BasicPool::new_full( + Default::default(), + Arc::new(FullChainApi::new(client.clone(), None)), + None, + spawner, + client.clone(), + ); + + let accounts = FullSystem::new(client, pool, DenyUnsafe::No); + + let tx = Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Bob.into(), + amount: 5, + nonce: 100, + }.into_signed_tx(); + + // when + let res = accounts.dry_run(tx.encode().into(), None); + + // then + let bytes = res.wait().unwrap().0; + let apply_res: ApplyExtrinsicResult = Decode::decode(&mut bytes.as_slice()).unwrap(); + assert_eq!(apply_res, Err(TransactionValidityError::Invalid(InvalidTransaction::Stale))); + } } diff --git a/utils/prometheus/Cargo.toml b/utils/prometheus/Cargo.toml index add4b0da5ff9565b76e0efb25c5c7ceb888e709a..6a76f6109c2c0d5453f319725288823c770be827 100644 --- a/utils/prometheus/Cargo.toml +++ b/utils/prometheus/Cargo.toml @@ -1,13 +1,16 @@ [package] description = "Endpoint to expose Prometheus metrics" name = "substrate-prometheus-endpoint" -version = "0.8.0-alpha.5" -license = "GPL-3.0" +version = "0.8.0-rc4" +license = "Apache-2.0" authors = ["Parity Technologies "] edition = "2018" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] log = "0.4.8" prometheus = "0.8" @@ -15,9 +18,6 @@ futures-util = { version = "0.3.1", default-features = false, features = ["io"] derive_more = "0.99" [target.'cfg(not(target_os = "unknown"))'.dependencies] -async-std = { version = "1.0.1", features = ["unstable"] } +async-std = { version = "1.6.2", features = ["unstable"] } hyper = { version = "0.13.1", default-features = false, features = ["stream"] } tokio = "0.2" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/utils/prometheus/src/lib.rs b/utils/prometheus/src/lib.rs index 00f0fb4f972e476122ac70007c1fe52c443f0625..9030704cb746ffbb4fa9ebfe5f468751a67a28d2 100644 --- a/utils/prometheus/src/lib.rs +++ b/utils/prometheus/src/lib.rs @@ -19,6 +19,7 @@ pub use prometheus::{ self, Registry, Error as PrometheusError, Opts, Histogram, HistogramOpts, HistogramVec, + exponential_buckets, core::{ GenericGauge as Gauge, GenericCounter as Counter, GenericGaugeVec as GaugeVec, GenericCounterVec as CounterVec, diff --git a/utils/prometheus/src/networking.rs b/utils/prometheus/src/networking.rs index 5c8c036d4459761bde9055fc2b593d91a9e3a0af..92b9fedf6c79a9174b74362b7aa2e542722cb51c 100644 --- a/utils/prometheus/src/networking.rs +++ b/utils/prometheus/src/networking.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use async_std::pin::Pin; use std::task::{Poll, Context}; diff --git a/utils/wasm-builder-runner/Cargo.toml b/utils/wasm-builder-runner/Cargo.toml index 77796ea8d9a8b15c21d7531fb772afc43c47ee6a..346807d2e97f41397279f25b2e4bb861bcf1cec0 100644 --- a/utils/wasm-builder-runner/Cargo.toml +++ b/utils/wasm-builder-runner/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "substrate-wasm-builder-runner" -version = "1.0.5" +version = "1.0.6" authors = ["Parity Technologies "] description = "Runner for substrate-wasm-builder" edition = "2018" readme = "README.md" repository = "https://github.com/paritytech/substrate/" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" -[dependencies] - [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] diff --git a/utils/wasm-builder-runner/src/lib.rs b/utils/wasm-builder-runner/src/lib.rs index 0e4b1421f880438283b2e2bc7fea997ceff7befe..ae1a6e4968f93e86e12aeb091b079e324f46c7bd 100644 --- a/utils/wasm-builder-runner/src/lib.rs +++ b/utils/wasm-builder-runner/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # WASM builder runner //! @@ -169,7 +170,7 @@ impl WasmBuilderSelectSource { /// 3. Select the source of the `wasm-builder` crate using the methods of /// [`WasmBuilderSelectSource`]. /// 4. Set additional `RUST_FLAGS` or a different name for the file containing the WASM code -/// using methods of [`Self`]. +/// using methods of [`WasmBuilder`]. /// 5. Build the WASM binary using [`Self::build`]. pub struct WasmBuilder { /// Where should we pull the `wasm-builder` crate from. diff --git a/utils/wasm-builder/Cargo.toml b/utils/wasm-builder/Cargo.toml index ed953cca577ddf1deaec0f8600b7d473293ab24c..e46db432689e06938e81ffa7ce20b264c6d44fc1 100644 --- a/utils/wasm-builder/Cargo.toml +++ b/utils/wasm-builder/Cargo.toml @@ -1,24 +1,24 @@ [package] name = "substrate-wasm-builder" -version = "1.0.9" +version = "1.0.11" authors = ["Parity Technologies "] description = "Utility for building WASM binaries" edition = "2018" readme = "README.md" repository = "https://github.com/paritytech/substrate/" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] build-helper = "0.1.1" -cargo_metadata = "0.9.0" +cargo_metadata = "0.10.0" tempfile = "3.1.0" toml = "0.5.4" -walkdir = "2.2.9" +walkdir = "2.3.1" fs2 = "0.4.3" wasm-gc-api = "0.1.11" atty = "0.2.13" itertools = "0.8.2" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/utils/wasm-builder/README.md b/utils/wasm-builder/README.md index 5f4ca615d5065dca62e1d9c7d0463975c52acb2c..b72e7e16d4ff4110597e4f44119d571842b79e3e 100644 --- a/utils/wasm-builder/README.md +++ b/utils/wasm-builder/README.md @@ -1,11 +1,11 @@ -# 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 +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 -A project that should be compiled as a WASM binary needs to: +A project that should be compiled as a Wasm binary needs to: 1. Add a `build.rs` file. 2. Add `substrate-wasm-builder` as dependency into `build-dependencies`. @@ -31,12 +31,20 @@ As the final step, you need to add the following to your project: 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. +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. + +### Feature + +Wasm builder supports to enable cargo features while building the Wasm binary. By default it will +enable all features in the wasm build that are enabled for the native build except the +`default` and `std` features. Besides that, wasm builder supports the special `runtime-wasm` +feature. This `runtime-wasm` feature will be enabled by the wasm builder when it compiles the +Wasm binary. If this feature is not present, it will not be enabled. ## Environment variables -By using environment variables, you can configure which WASM binaries are built and how: +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 @@ -44,7 +52,7 @@ By using environment variables, you can configure which WASM binaries are built - `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 - needs to change. As WASM builder instructs `cargo` to watch for file changes + 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_NO_COLOR` - Disable color output of the wasm build. @@ -59,7 +67,7 @@ be `NODE_RUNTIME`. ## Prerequisites: -WASM builder requires the following prerequisites for building the WASM binary: +Wasm builder requires the following prerequisites for building the Wasm binary: - rust nightly + `wasm32-unknown-unknown` toolchain @@ -67,4 +75,4 @@ If a specific rust nightly is installed with `rustup`, it is important that the as well. For example if installing the rust nightly from 20.02.2020 using `rustup install nightly-2020-02-20`, the wasm target needs to be installed as well `rustup target add wasm32-unknown-unknown --toolchain nightly-2020-02-20`. -License: GPL-3.0 +License: Apache-2.0 diff --git a/utils/wasm-builder/src/lib.rs b/utils/wasm-builder/src/lib.rs index 195527a122725129e0a23058fe675dcc72e4320a..95b75c5867f6097d4d8eb51703713228650000c9 100644 --- a/utils/wasm-builder/src/lib.rs +++ b/utils/wasm-builder/src/lib.rs @@ -1,27 +1,28 @@ -// Copyright 2019-2020 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 . - -//! # WASM builder is a utility for building a project as a WASM binary +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! # 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 +//! 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 //! -//! A project that should be compiled as a WASM binary needs to: +//! A project that should be compiled as a Wasm binary needs to: //! //! 1. Add a `build.rs` file. //! 2. Add `substrate-wasm-builder` as dependency into `build-dependencies`. @@ -47,12 +48,20 @@ //! 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. +//! 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. +//! +//! ### Feature +//! +//! Wasm builder supports to enable cargo features while building the Wasm binary. By default it will +//! enable all features in the wasm build that are enabled for the native build except the +//! `default` and `std` features. Besides that, wasm builder supports the special `runtime-wasm` +//! feature. This `runtime-wasm` feature will be enabled by the wasm builder when it compiles the +//! Wasm binary. If this feature is not present, it will not be enabled. //! //! ## Environment variables //! -//! By using environment variables, you can configure which WASM binaries are built and how: +//! 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 @@ -60,7 +69,7 @@ //! - `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 -//! needs to change. As WASM builder instructs `cargo` to watch for file changes +//! 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_NO_COLOR` - Disable color output of the wasm build. @@ -75,7 +84,7 @@ //! //! ## Prerequisites: //! -//! WASM builder requires the following prerequisites for building the WASM binary: +//! Wasm builder requires the following prerequisites for building the Wasm binary: //! //! - rust nightly + `wasm32-unknown-unknown` toolchain //! @@ -166,8 +175,8 @@ pub fn build_project_with_default_rustflags( pub const WASM_BINARY: &[u8] = include_bytes!("{wasm_binary}"); pub const WASM_BINARY_BLOATY: &[u8] = include_bytes!("{wasm_binary_bloaty}"); "#, - wasm_binary = wasm_binary.wasm_binary_path(), - wasm_binary_bloaty = bloaty.wasm_binary_bloaty_path(), + wasm_binary = wasm_binary.wasm_binary_path_escaped(), + wasm_binary_bloaty = bloaty.wasm_binary_bloaty_path_escaped(), ), ); } @@ -184,6 +193,17 @@ fn write_file_if_changed(file: PathBuf, content: String) { } } +/// Copy `src` to `dst` if the `dst` does not exist or is different. +fn copy_file_if_changed(src: PathBuf, dst: PathBuf) { + let src_file = fs::read_to_string(&src).ok(); + let dst_file = fs::read_to_string(&dst).ok(); + + if src_file != dst_file { + fs::copy(&src, &dst) + .expect(&format!("Copying `{}` to `{}` can not fail; qed", src.display(), dst.display())); + } +} + /// Get a cargo command that compiles with nightly fn get_nightly_cargo() -> CargoCommand { let env_cargo = CargoCommand::new( diff --git a/utils/wasm-builder/src/prerequisites.rs b/utils/wasm-builder/src/prerequisites.rs index da118a71f98dae9da4243a2b3eaaff8e1aed8b69..d7c15095762e8a17ec8effab1e6da2e7ecc2572d 100644 --- a/utils/wasm-builder/src/prerequisites.rs +++ b/utils/wasm-builder/src/prerequisites.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use std::fs; diff --git a/utils/wasm-builder/src/wasm_project.rs b/utils/wasm-builder/src/wasm_project.rs index 6248f81935242ab4d43d5ded8e8cb52e34ee6059..7df3524e8aaf8a9da430ba5962ec70fb4e3d4da5 100644 --- a/utils/wasm-builder/src/wasm_project.rs +++ b/utils/wasm-builder/src/wasm_project.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::write_file_if_changed; @@ -25,7 +26,7 @@ use toml::value::Table; use build_helper::rerun_if_changed; -use cargo_metadata::MetadataCommand; +use cargo_metadata::{MetadataCommand, Metadata}; use walkdir::WalkDir; @@ -37,9 +38,9 @@ use itertools::Itertools; pub struct WasmBinaryBloaty(PathBuf); impl WasmBinaryBloaty { - /// Returns the path to the bloaty wasm binary. - pub fn wasm_binary_bloaty_path(&self) -> String { - self.0.display().to_string().replace('\\', "/") + /// Returns the escaped path to the bloaty wasm binary. + pub fn wasm_binary_bloaty_path_escaped(&self) -> String { + self.0.display().to_string().escape_default().to_string() } } @@ -48,8 +49,13 @@ pub struct WasmBinary(PathBuf); impl WasmBinary { /// Returns the path to the wasm binary. - pub fn wasm_binary_path(&self) -> String { - self.0.display().to_string().replace('\\', "/") + pub fn wasm_binary_path(&self) -> &Path { + &self.0 + } + + /// Returns the escaped path to the wasm binary. + pub fn wasm_binary_path_escaped(&self) -> String { + self.0.display().to_string().escape_default().to_string() } } @@ -296,10 +302,23 @@ fn create_wasm_workspace_project(wasm_workspace: &Path, workspace_root_path: &Pa wasm_workspace_toml.insert("patch".into(), patch.into()); } - fs::write( + write_file_if_changed( wasm_workspace.join("Cargo.toml"), toml::to_string_pretty(&wasm_workspace_toml).expect("Wasm workspace toml is valid; qed"), - ).expect("WASM workspace `Cargo.toml` writing can not fail; qed"); + ); +} + +/// Find a package by the given `manifest_path` in the metadata. +/// +/// Panics if the package could not be found. +fn find_package_by_manifest_path<'a>( + manifest_path: &Path, + crate_metadata: &'a cargo_metadata::Metadata, +) -> &'a cargo_metadata::Package { + crate_metadata.packages + .iter() + .find(|p| p.manifest_path == manifest_path) + .expect("Wasm project exists in its own metadata; qed") } /// Get a list of enabled features for the project. @@ -307,10 +326,7 @@ fn project_enabled_features( cargo_manifest: &Path, crate_metadata: &cargo_metadata::Metadata, ) -> Vec { - let package = crate_metadata.packages - .iter() - .find(|p| p.manifest_path == cargo_manifest) - .expect("Wasm project exists in its own metadata; qed"); + let package = find_package_by_manifest_path(cargo_manifest, crate_metadata); let mut enabled_features = package.features.keys() .filter(|f| { @@ -332,23 +348,34 @@ fn project_enabled_features( enabled_features } +/// Returns if the project has the `runtime-wasm` feature +fn has_runtime_wasm_feature_declared( + cargo_manifest: &Path, + crate_metadata: &cargo_metadata::Metadata, +) -> bool { + let package = find_package_by_manifest_path(cargo_manifest, crate_metadata); + + package.features.keys().any(|k| k == "runtime-wasm") +} + /// Create the project used to build the wasm binary. /// /// # Returns /// The path to the created project. -fn create_project( - cargo_manifest: &Path, - wasm_workspace: &Path, - crate_metadata: &cargo_metadata::Metadata, -) -> PathBuf { +fn create_project(cargo_manifest: &Path, wasm_workspace: &Path, crate_metadata: &Metadata) -> PathBuf { let crate_name = get_crate_name(cargo_manifest); let crate_path = cargo_manifest.parent().expect("Parent path exists; qed"); let wasm_binary = get_wasm_binary_name(cargo_manifest); let project_folder = wasm_workspace.join(&crate_name); - fs::create_dir_all(project_folder.join("src")).expect("Wasm project dir create can not fail; qed"); + fs::create_dir_all(project_folder.join("src")) + .expect("Wasm project dir create can not fail; qed"); - let enabled_features = project_enabled_features(&cargo_manifest, &crate_metadata); + let mut enabled_features = project_enabled_features(&cargo_manifest, &crate_metadata); + + if has_runtime_wasm_feature_declared(cargo_manifest, crate_metadata) { + enabled_features.push("runtime-wasm".into()); + } write_file_if_changed( project_folder.join("Cargo.toml"), @@ -380,8 +407,7 @@ fn create_project( if let Some(crate_lock_file) = find_cargo_lock(cargo_manifest) { // Use the `Cargo.lock` of the main project. - fs::copy(crate_lock_file, wasm_workspace.join("Cargo.lock")) - .expect("Copying the `Cargo.lock` can not fail; qed"); + crate::copy_file_if_changed(crate_lock_file, wasm_workspace.join("Cargo.lock")); } project_folder @@ -513,22 +539,33 @@ fn generate_rerun_if_changed_instructions( .exec() .expect("`cargo metadata` can not fail!"); - // Start with the dependencies of the crate we want to compile for wasm. - let mut dependencies = metadata.packages + let package = metadata.packages .iter() .find(|p| p.manifest_path == cargo_manifest) - .expect("The crate package is contained in its own metadata; qed") - .dependencies - .iter() - .collect::>(); + .expect("The crate package is contained in its own metadata; qed"); + + // Start with the dependencies of the crate we want to compile for wasm. + let mut dependencies = package.dependencies.iter().collect::>(); // Collect all packages by follow the dependencies of all packages we find. let mut packages = HashSet::new(); + packages.insert(DeduplicatePackage::from(package)); + while let Some(dependency) = dependencies.pop() { + let path_or_git_dep = dependency.source + .as_ref() + .map(|s| s.starts_with("git+")) + .unwrap_or(true); + let package = metadata.packages .iter() .filter(|p| !p.manifest_path.starts_with(wasm_workspace)) - .find(|p| dependency.req.matches(&p.version) && dependency.name == p.name); + .find(|p| { + // Check that the name matches and that the version matches or this is + // a git or path dep. A git or path dependency can only occur once, so we don't + // need to check the version. + (path_or_git_dep || dependency.req.matches(&p.version)) && dependency.name == p.name + }); if let Some(package) = package { if packages.insert(DeduplicatePackage::from(package)) { @@ -538,21 +575,7 @@ fn generate_rerun_if_changed_instructions( } // Make sure that if any file/folder of a dependency change, we need to rerun the `build.rs` - packages.into_iter() - .filter(|p| !p.manifest_path.starts_with(wasm_workspace)) - .for_each(|package| { - let mut manifest_path = package.manifest_path.clone(); - if manifest_path.ends_with("Cargo.toml") { - manifest_path.pop(); - } - - rerun_if_changed(&manifest_path); - - WalkDir::new(manifest_path) - .into_iter() - .filter_map(|p| p.ok()) - .for_each(|p| rerun_if_changed(p.path())); - }); + packages.iter().for_each(package_rerun_if_changed); // Register our env variables println!("cargo:rerun-if-env-changed={}", crate::SKIP_BUILD_ENV); @@ -562,8 +585,32 @@ fn generate_rerun_if_changed_instructions( println!("cargo:rerun-if-env-changed={}", crate::WASM_BUILD_TOOLCHAIN); } -/// 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. +/// Track files and paths related to the given package to rerun `build.rs` on any relevant change. +fn package_rerun_if_changed(package: &DeduplicatePackage) { + let mut manifest_path = package.manifest_path.clone(); + if manifest_path.ends_with("Cargo.toml") { + manifest_path.pop(); + } + + WalkDir::new(&manifest_path) + .into_iter() + .filter_entry(|p| { + // Ignore this entry if it is a directory that contains a `Cargo.toml` that is not the + // `Cargo.toml` related to the current package. This is done to ignore sub-crates of a crate. + // If such a sub-crate is a dependency, it will be processed independently anyway. + p.path() == manifest_path + || !p.path().is_dir() + || !p.path().join("Cargo.toml").exists() + }) + .filter_map(|p| p.ok().map(|p| p.into_path())) + .filter(|p| { + p.is_dir() || p.extension().map(|e| e == "rs" || e == "toml").unwrap_or_default() + }) + .for_each(|p| rerun_if_changed(p)); +} + +/// 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),

::Upper; + /// Something that implements a fixed point ration with an arbitrary granularity `X`, as _parts per /// `X`_. pub trait PerThing: Sized + Saturating + Copy + Default + Eq + PartialEq + Ord + PartialOrd + Bounded + fmt::Debug { /// The data type used to build this per-thingy. - type Inner: BaseArithmetic + Copy + fmt::Debug; + type Inner: BaseArithmetic + Unsigned + Copy + fmt::Debug; /// A data type larger than `Self::Inner`, used to avoid overflow in some computations. /// It must be able to compute `ACCURACY^2`. - type Upper: BaseArithmetic + Copy + From + TryInto + fmt::Debug; + type Upper: + BaseArithmetic + Copy + From + TryInto + + UniqueSaturatedInto + Unsigned + fmt::Debug; /// The accuracy of this type. const ACCURACY: Self::Inner; @@ -85,7 +94,7 @@ pub trait PerThing: /// ``` fn mul_floor(self, b: N) -> N where N: Clone + From + UniqueSaturatedInto + ops::Rem + - ops::Div + ops::Mul + ops::Add + ops::Div + ops::Mul + ops::Add + Unsigned { overflow_prune_mul::(b, self.deconstruct(), Rounding::Down) } @@ -107,7 +116,7 @@ pub trait PerThing: /// ``` fn mul_ceil(self, b: N) -> N where N: Clone + From + UniqueSaturatedInto + ops::Rem + - ops::Div + ops::Mul + ops::Add + ops::Div + ops::Mul + ops::Add + Unsigned { overflow_prune_mul::(b, self.deconstruct(), Rounding::Up) } @@ -123,7 +132,8 @@ pub trait PerThing: /// ``` fn saturating_reciprocal_mul(self, b: N) -> N where N: Clone + From + UniqueSaturatedInto + ops::Rem + - ops::Div + ops::Mul + ops::Add + Saturating + ops::Div + ops::Mul + ops::Add + Saturating + + Unsigned { saturating_reciprocal_mul::(b, self.deconstruct(), Rounding::Nearest) } @@ -142,7 +152,8 @@ pub trait PerThing: /// ``` fn saturating_reciprocal_mul_floor(self, b: N) -> N where N: Clone + From + UniqueSaturatedInto + ops::Rem + - ops::Div + ops::Mul + ops::Add + Saturating + ops::Div + ops::Mul + ops::Add + Saturating + + Unsigned { saturating_reciprocal_mul::(b, self.deconstruct(), Rounding::Down) } @@ -161,7 +172,8 @@ pub trait PerThing: /// ``` fn saturating_reciprocal_mul_ceil(self, b: N) -> N where N: Clone + From + UniqueSaturatedInto + ops::Rem + - ops::Div + ops::Mul + ops::Add + Saturating + ops::Div + ops::Mul + ops::Add + Saturating + + Unsigned { saturating_reciprocal_mul::(b, self.deconstruct(), Rounding::Up) } @@ -189,14 +201,14 @@ pub trait PerThing: /// # fn main () { /// // 989/100 is technically closer to 99%. /// assert_eq!( - /// Percent::from_rational_approximation(989, 1000), + /// Percent::from_rational_approximation(989u64, 1000), /// Percent::from_parts(98), /// ); /// # } /// ``` fn from_rational_approximation(p: N, q: N) -> Self where N: Clone + Ord + From + TryInto + TryInto + - ops::Div + ops::Rem + ops::Add; + ops::Div + ops::Rem + ops::Add + Unsigned; } /// The rounding method to use. @@ -218,7 +230,7 @@ fn saturating_reciprocal_mul( ) -> N where N: Clone + From + UniqueSaturatedInto + ops::Div + ops::Mul + ops::Add + ops::Rem + Saturating, + Output=N> + ops::Add + ops::Rem + Saturating + Unsigned, P: PerThing, { let maximum: N = P::ACCURACY.into(); @@ -239,7 +251,7 @@ fn overflow_prune_mul( ) -> N where N: Clone + From + UniqueSaturatedInto + ops::Div + ops::Mul + ops::Add + ops::Rem, + Output=N> + ops::Add + ops::Rem + Unsigned, P: PerThing, { let maximum: N = P::ACCURACY.into(); @@ -265,7 +277,7 @@ fn rational_mul_correction( ) -> N where N: From + UniqueSaturatedInto + ops::Div + ops::Mul + ops::Add + ops::Rem, + Output=N> + ops::Add + ops::Rem + Unsigned, P: PerThing, { let numer_upper = P::Upper::from(numer); @@ -311,8 +323,7 @@ macro_rules! implement_per_thing { /// #[doc = $title] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] - #[derive(Encode, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, - RuntimeDebug, CompactAs)] + #[derive(Encode, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, CompactAs)] pub struct $name($type); impl PerThing for $name { @@ -327,14 +338,15 @@ macro_rules! implement_per_thing { /// Build this type from a number of parts per thing. fn from_parts(parts: Self::Inner) -> Self { Self(parts.min($max)) } + /// NOTE: saturate to 0 or 1 if x is beyond `[0, 1]` #[cfg(feature = "std")] fn from_fraction(x: f64) -> Self { - Self::from_parts((x * $max as f64) as Self::Inner) + Self::from_parts((x.max(0.).min(1.) * $max as f64) as Self::Inner) } fn from_rational_approximation(p: N, q: N) -> Self where N: Clone + Ord + From + TryInto + TryInto - + ops::Div + ops::Rem + ops::Add + + ops::Div + ops::Rem + ops::Add + Unsigned { let div_ceil = |x: N, f: N| -> N { let mut o = x.clone() / f.clone(); @@ -382,7 +394,6 @@ macro_rules! implement_per_thing { impl $name { /// From an explicitly defined number of parts per maximum of the type. /// - /// This can be called at compile time. // needed only for peru16. Since peru16 is the only type in which $max == // $type::max_value(), rustc is being a smart-a** here by warning that the comparison // is not needed. @@ -398,9 +409,9 @@ macro_rules! implement_per_thing { Self(([x, 100][(x > 100) as usize] as $upper_type * $max as $upper_type / 100) as $type) } - /// See [`PerThing::one`]. - pub fn one() -> Self { - ::one() + /// See [`PerThing::one`] + pub const fn one() -> Self { + Self::from_parts($max) } /// See [`PerThing::is_one`]. @@ -409,8 +420,8 @@ macro_rules! implement_per_thing { } /// See [`PerThing::zero`]. - pub fn zero() -> Self { - ::zero() + pub const fn zero() -> Self { + Self::from_parts(0) } /// See [`PerThing::is_zero`]. @@ -419,8 +430,8 @@ macro_rules! implement_per_thing { } /// See [`PerThing::deconstruct`]. - pub fn deconstruct(self) -> $type { - PerThing::deconstruct(self) + pub const fn deconstruct(self) -> $type { + self.0 } /// See [`PerThing::square`]. @@ -438,7 +449,8 @@ macro_rules! implement_per_thing { pub fn from_rational_approximation(p: N, q: N) -> Self where N: Clone + Ord + From<$type> + TryInto<$type> + TryInto<$upper_type> + ops::Div + ops::Rem + - ops::Add { + ops::Add + Unsigned + { ::from_rational_approximation(p, q) } @@ -446,7 +458,8 @@ macro_rules! implement_per_thing { pub fn mul_floor(self, b: N) -> N where N: Clone + From<$type> + UniqueSaturatedInto<$type> + ops::Rem + ops::Div + ops::Mul + - ops::Add { + ops::Add + Unsigned + { PerThing::mul_floor(self, b) } @@ -454,7 +467,8 @@ macro_rules! implement_per_thing { pub fn mul_ceil(self, b: N) -> N where N: Clone + From<$type> + UniqueSaturatedInto<$type> + ops::Rem + ops::Div + ops::Mul + - ops::Add { + ops::Add + Unsigned + { PerThing::mul_ceil(self, b) } @@ -462,7 +476,8 @@ macro_rules! implement_per_thing { pub fn saturating_reciprocal_mul(self, b: N) -> N where N: Clone + From<$type> + UniqueSaturatedInto<$type> + ops::Rem + ops::Div + ops::Mul + ops::Add + - Saturating { + Saturating + Unsigned + { PerThing::saturating_reciprocal_mul(self, b) } @@ -470,7 +485,8 @@ macro_rules! implement_per_thing { pub fn saturating_reciprocal_mul_floor(self, b: N) -> N where N: Clone + From<$type> + UniqueSaturatedInto<$type> + ops::Rem + ops::Div + ops::Mul + ops::Add + - Saturating { + Saturating + Unsigned + { PerThing::saturating_reciprocal_mul_floor(self, b) } @@ -478,7 +494,8 @@ macro_rules! implement_per_thing { pub fn saturating_reciprocal_mul_ceil(self, b: N) -> N where N: Clone + From<$type> + UniqueSaturatedInto<$type> + ops::Rem + ops::Div + ops::Mul + ops::Add + - Saturating { + Saturating + Unsigned + { PerThing::saturating_reciprocal_mul_ceil(self, b) } } @@ -566,13 +583,19 @@ macro_rules! implement_per_thing { } } + impl Default for $name { + fn default() -> Self { + ::zero() + } + } + /// Non-overflow multiplication. /// /// This is 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, + + ops::Div + ops::Mul + ops::Add + Unsigned, { type Output = N; fn mul(self, b: N) -> Self::Output { @@ -671,6 +694,8 @@ macro_rules! implement_per_thing { assert_eq!($name::from_fraction(0.0), $name::from_parts(Zero::zero())); assert_eq!($name::from_fraction(0.1), $name::from_parts($max / 10)); assert_eq!($name::from_fraction(1.0), $name::from_parts($max)); + assert_eq!($name::from_fraction(2.0), $name::from_parts($max)); + assert_eq!($name::from_fraction(-1.0), $name::from_parts(Zero::zero())); } macro_rules! u256ify { @@ -1096,7 +1121,7 @@ macro_rules! implement_per_thing { <$type>::max_value(), super::Rounding::Nearest, ), - (<$type>::max_value() - 1).into(), + <$upper_type>::from((<$type>::max_value() - 1)), ); // (max % 2) * max / 2 == max / 2 assert_eq!( @@ -1129,6 +1154,18 @@ macro_rules! implement_per_thing { 1, ); } + + #[test] + #[allow(unused)] + fn const_fns_work() { + const C1: $name = $name::from_percent(50); + const C2: $name = $name::one(); + const C3: $name = $name::zero(); + const C4: $name = $name::from_parts(1); + + // deconstruct is also const, hence it can be called in const rhs. + const C5: bool = C1.deconstruct() == 0; + } } }; } diff --git a/primitives/arithmetic/src/rational128.rs b/primitives/arithmetic/src/rational128.rs index 248df70794c635efc726255e5130ed8dc70ac037..947c7bc537d19fc1906a4e2e29d0b3f9947338e5 100644 --- a/primitives/arithmetic/src/rational128.rs +++ b/primitives/arithmetic/src/rational128.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use sp_std::{cmp::Ordering, prelude::*}; use crate::helpers_128bit; @@ -214,7 +215,7 @@ mod tests { 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. + // large to perbill. This is very well needed for npos-elections. assert_eq!( r(MAX128 / 2, MAX128).to_den(1000_000_000), Ok(r(500_000_000, 1000_000_000)) @@ -359,6 +360,15 @@ mod tests { multiply_by_rational(1_000_000_000, MAX128 / 8, MAX128 / 2).unwrap(), 250000000, ); + + assert_eq!( + multiply_by_rational( + 29459999999999999988000u128, + 1000000000000000000u128, + 10000000000000000000u128 + ).unwrap(), + 2945999999999999998800u128 + ); } #[test] diff --git a/primitives/arithmetic/src/traits.rs b/primitives/arithmetic/src/traits.rs index 23f8f23f0bd77b783dfc1908b0efc6354f9fc4a8..ce645cfe65d94326c26fd5e4996324187e7913c7 100644 --- a/primitives/arithmetic/src/traits.rs +++ b/primitives/arithmetic/src/traits.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Primitive traits for the runtime arithmetic. @@ -20,8 +21,8 @@ use sp_std::{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, checked_pow + Zero, One, Bounded, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, CheckedNeg, + CheckedShl, CheckedShr, checked_pow, Signed, Unsigned, }; use sp_std::ops::{ Add, Sub, Mul, Div, Rem, AddAssign, SubAssign, MulAssign, DivAssign, @@ -78,6 +79,11 @@ pub trait AtLeast32Bit: BaseArithmetic + From + From {} impl + From> AtLeast32Bit for T {} +/// A meta trait for arithmetic. Same as [`AtLeast32Bit `], but also bounded to be unsigned. +pub trait AtLeast32BitUnsigned: AtLeast32Bit + Unsigned {} + +impl AtLeast32BitUnsigned 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 { @@ -117,13 +123,13 @@ pub trait Saturating { /// Saturating multiply. Compute `self * rhs`, saturating at the numeric bounds instead of /// overflowing. fn saturating_mul(self, rhs: Self) -> Self; - + /// Saturating exponentiation. Compute `self.pow(exp)`, saturating at the numeric bounds /// instead of overflowing. fn saturating_pow(self, exp: usize) -> Self; } -impl Saturating for T { +impl Saturating for T { fn saturating_add(self, o: Self) -> Self { ::saturating_add(self, o) } @@ -133,11 +139,26 @@ impl Saturating } fn saturating_mul(self, o: Self) -> Self { - self.checked_mul(&o).unwrap_or_else(Bounded::max_value) + self.checked_mul(&o) + .unwrap_or_else(|| + if (self < T::zero()) != (o < T::zero()) { + Bounded::min_value() + } else { + Bounded::max_value() + } + ) } fn saturating_pow(self, exp: usize) -> Self { - checked_pow(self, exp).unwrap_or_else(Bounded::max_value) + let neg = self < T::zero() && exp % 2 != 0; + checked_pow(self, exp) + .unwrap_or_else(|| + if neg { + Bounded::min_value() + } else { + Bounded::max_value() + } + ) } } diff --git a/primitives/authority-discovery/Cargo.toml b/primitives/authority-discovery/Cargo.toml index f37b67fab1ce8d476fef66656b3c5013701edbf9..79b8a832fbe13ac0f184ceb4530d0735590caf37 100644 --- a/primitives/authority-discovery/Cargo.toml +++ b/primitives/authority-discovery/Cargo.toml @@ -1,19 +1,22 @@ [package] name = "sp-authority-discovery" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] description = "Authority discovery primitives" edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-application-crypto = { version = "2.0.0-alpha.5", default-features = false, path = "../application-crypto" } -codec = { package = "parity-scale-codec", default-features = false, version = "1.3.0" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../std" } -sp-api = { version = "2.0.0-alpha.5", default-features = false, path = "../api" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../runtime" } +sp-application-crypto = { version = "2.0.0-rc4", default-features = false, path = "../application-crypto" } +codec = { package = "parity-scale-codec", default-features = false, version = "1.3.1" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../std" } +sp-api = { version = "2.0.0-rc4", default-features = false, path = "../api" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../runtime" } [features] default = ["std"] @@ -24,6 +27,3 @@ std = [ "sp-api/std", "sp-runtime/std" ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/authority-discovery/src/lib.rs b/primitives/authority-discovery/src/lib.rs index 68680ad75946545f93d8d0c5ef5c3004a3623efc..8903a7f3837553806912770243bf6b18e3a3aadf 100644 --- a/primitives/authority-discovery/src/lib.rs +++ b/primitives/authority-discovery/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Runtime Api to help discover authorities. @@ -22,24 +23,11 @@ use sp_std::vec::Vec; mod app { use sp_application_crypto::{ - CryptoTypePublicPair, key_types::AUTHORITY_DISCOVERY, - Public as _, app_crypto, - sr25519}; + sr25519, + }; app_crypto!(sr25519, AUTHORITY_DISCOVERY); - - impl From for CryptoTypePublicPair { - fn from(key: Public) -> Self { - (&key).into() - } - } - - impl From<&Public> for CryptoTypePublicPair { - fn from(key: &Public) -> Self { - CryptoTypePublicPair(sr25519::CRYPTO_ID, key.to_raw_vec()) - } - } } sp_application_crypto::with_pair! { diff --git a/primitives/authorship/Cargo.toml b/primitives/authorship/Cargo.toml index a4d5aa03c2382c3c93f278bca825c7ca08688951..1c44b9aad7ab2ed740c8d142f5641096e6642687 100644 --- a/primitives/authorship/Cargo.toml +++ b/primitives/authorship/Cargo.toml @@ -1,18 +1,21 @@ [package] name = "sp-authorship" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] description = "Authorship primitives" edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-inherents = { version = "2.0.0-alpha.5", default-features = false, path = "../inherents" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../runtime" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../std" } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } +sp-inherents = { version = "2.0.0-rc4", default-features = false, path = "../inherents" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../runtime" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../std" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } [features] default = [ "std" ] @@ -22,6 +25,3 @@ std = [ "sp-inherents/std", "sp-runtime/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/authorship/src/lib.rs b/primitives/authorship/src/lib.rs index 53dac56dc473c20d3f18e717a396ac13b80eb7b3..a760c546a25d7f2947b374b25965fc5192e53a2e 100644 --- a/primitives/authorship/src/lib.rs +++ b/primitives/authorship/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Authorship Primitives diff --git a/primitives/block-builder/Cargo.toml b/primitives/block-builder/Cargo.toml index df33b2c955ff096b1bd861769d1dd5c56497a867..2b594640fd10fa97f0cb708c0d97dccc95cab9ea 100644 --- a/primitives/block-builder/Cargo.toml +++ b/primitives/block-builder/Cargo.toml @@ -1,19 +1,22 @@ [package] name = "sp-block-builder" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "The block builder runtime api." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../runtime" } -sp-api = { version = "2.0.0-alpha.5", default-features = false, path = "../api" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../std" } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -sp-inherents = { version = "2.0.0-alpha.5", default-features = false, path = "../inherents" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../runtime" } +sp-api = { version = "2.0.0-rc4", default-features = false, path = "../api" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../std" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +sp-inherents = { version = "2.0.0-rc4", default-features = false, path = "../inherents" } [features] default = [ "std" ] @@ -24,6 +27,3 @@ std = [ "sp-api/std", "sp-std/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/block-builder/src/lib.rs b/primitives/block-builder/src/lib.rs index 732c937c1a0858514c3841d3dad5419b5749b519..6367a18afa6151aea69c80c7c65b455d33c1933e 100644 --- a/primitives/block-builder/src/lib.rs +++ b/primitives/block-builder/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The block builder runtime api. diff --git a/primitives/blockchain/Cargo.toml b/primitives/blockchain/Cargo.toml index 49e6baead1fb82a919b3d7ca40fe0a6045ee0524..0ce19cba3369481fb5835dc3dd6a88cf24b33ac1 100644 --- a/primitives/blockchain/Cargo.toml +++ b/primitives/blockchain/Cargo.toml @@ -1,25 +1,25 @@ [package] name = "sp-blockchain" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate blockchain traits and primitives." documentation = "https://docs.rs/sp-blockchain" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = "0.4.8" lru = "0.4.0" parking_lot = "0.10.0" derive_more = "0.99.2" -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-consensus = { version = "0.8.0-alpha.5", path = "../consensus/common" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../runtime" } -sp-block-builder = { version = "2.0.0-alpha.5", path = "../block-builder" } -sp-state-machine = { version = "0.8.0-alpha.5", path = "../state-machine" } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-consensus = { version = "0.8.0-rc4", path = "../consensus/common" } +sp-runtime = { version = "2.0.0-rc4", path = "../runtime" } +sp-block-builder = { version = "2.0.0-rc4", path = "../block-builder" } +sp-state-machine = { version = "0.8.0-rc4", path = "../state-machine" } +sp-database = { version = "2.0.0-rc4", path = "../database" } diff --git a/primitives/blockchain/src/backend.rs b/primitives/blockchain/src/backend.rs index e92dfd8c98e89397ee2e3d10e6f85e71b0c5ac00..1328dfb5752fc0544e33c6b9934965dd3158dded 100644 --- a/primitives/blockchain/src/backend.rs +++ b/primitives/blockchain/src/backend.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Substrate blockchain trait @@ -242,7 +243,7 @@ pub trait Cache: Send + Sync { } /// Blockchain info -#[derive(Debug)] +#[derive(Debug, Eq, PartialEq)] pub struct Info { /// Best block hash. pub best_hash: Block::Hash, diff --git a/primitives/blockchain/src/error.rs b/primitives/blockchain/src/error.rs index e479b8abe918ee881dbb4fa79cdf824cfe6fb14e..bc412e8358c8d93de893a49ee81b86559b4dfaab 100644 --- a/primitives/blockchain/src/error.rs +++ b/primitives/blockchain/src/error.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Substrate client possible errors. @@ -129,6 +130,8 @@ pub enum Error { IncompletePipeline, #[display(fmt = "Transaction pool not ready for block production.")] TransactionPoolNotReady, + #[display(fmt = "Database: {}", _0)] + DatabaseError(sp_database::error::DatabaseError), /// A convenience variant for String #[display(fmt = "{}", _0)] Msg(String), diff --git a/primitives/blockchain/src/header_metadata.rs b/primitives/blockchain/src/header_metadata.rs index 85a94624c9243ca24e9f7b7b7fa0eef7b46c3b89..b8d9c5c9345812c36e9271e859a81b61ae21f2fc 100644 --- a/primitives/blockchain/src/header_metadata.rs +++ b/primitives/blockchain/src/header_metadata.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Implements tree backend, cached header metadata and algorithms //! to compute routes efficiently over the tree of headers. @@ -136,7 +137,8 @@ pub fn tree_route>( from = backend.header_metadata(from.parent)?; } - // add the pivot block. and append the reversed to-branch (note that it's reverse order originals) + // 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, @@ -181,18 +183,24 @@ pub struct HashAndNumber { /// Tree route from C to E2. Retracted empty. Common is C, enacted [E1, E2] /// C -> E1 -> E2 /// ``` -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct TreeRoute { route: Vec>, pivot: usize, } impl TreeRoute { - /// Get a slice of all retracted blocks in reverse order (towards common ancestor) + /// Get a slice of all retracted blocks in reverse order (towards common ancestor). pub fn retracted(&self) -> &[HashAndNumber] { &self.route[..self.pivot] } + /// Convert into all retracted blocks in reverse order (towards common ancestor). + pub fn into_retracted(mut self) -> Vec> { + self.route.truncate(self.pivot); + self.route + } + /// Get the common ancestor block. This might be one of the two blocks of the /// route. pub fn common_block(&self) -> &HashAndNumber { @@ -212,8 +220,15 @@ 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 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); } @@ -239,19 +254,16 @@ impl Default for HeaderMetadataCache { } } -impl HeaderMetadata for HeaderMetadataCache { - type Error = String; - - fn header_metadata(&self, hash: Block::Hash) -> Result, Self::Error> { +impl HeaderMetadataCache { + pub fn header_metadata(&self, hash: Block::Hash) -> Option> { self.cache.write().get(&hash).cloned() - .ok_or("header metadata not found in cache".to_owned()) } - fn insert_header_metadata(&self, hash: Block::Hash, metadata: CachedHeaderMetadata) { + pub fn insert_header_metadata(&self, hash: Block::Hash, metadata: CachedHeaderMetadata) { self.cache.write().put(hash, metadata); } - fn remove_header_metadata(&self, hash: Block::Hash) { + pub fn remove_header_metadata(&self, hash: Block::Hash) { self.cache.write().pop(&hash); } } @@ -265,6 +277,8 @@ pub struct CachedHeaderMetadata { pub number: NumberFor, /// Hash of parent header. pub parent: Block::Hash, + /// Block state root. + pub state_root: Block::Hash, /// Hash of an ancestor header. Used to jump through the tree. ancestor: Block::Hash, } @@ -275,6 +289,7 @@ impl From<&Block::Header> for CachedHeaderMetadata { hash: header.hash().clone(), number: header.number().clone(), parent: header.parent_hash().clone(), + state_root: header.state_root().clone(), ancestor: header.parent_hash().clone(), } } diff --git a/primitives/blockchain/src/lib.rs b/primitives/blockchain/src/lib.rs index 8f83c7aec5d9d13cc18e929a48bd224c43a2ce46..27b9c3585e9caa673460f000ae3c8adb88fb94c0 100644 --- a/primitives/blockchain/src/lib.rs +++ b/primitives/blockchain/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Substrate blockchain traits and primitives. diff --git a/primitives/chain-spec/Cargo.toml b/primitives/chain-spec/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..e091a59245541db3876a4274c29da49de5c4faac --- /dev/null +++ b/primitives/chain-spec/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "sp-chain-spec" +version = "2.0.0-rc4" +authors = ["Parity Technologies "] +edition = "2018" +license = "Apache-2.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +description = "Substrate chain configurations types." + +[dependencies] +serde = { version = "1.0.101", features = ["derive"] } +serde_json = "1.0.41" diff --git a/primitives/chain-spec/src/lib.rs b/primitives/chain-spec/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..869fae8236b7674ba0eb8d02b86cb382686dd840 --- /dev/null +++ b/primitives/chain-spec/src/lib.rs @@ -0,0 +1,43 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Types and traits related to chain specifications. + +/// The type of a chain. +/// +/// This can be used by tools to determine the type of a chain for displaying +/// additional information or enabling additional features. +#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)] +pub enum ChainType { + /// A development chain that runs mainly on one node. + Development, + /// A local chain that runs locally on multiple nodes for testing purposes. + Local, + /// A live chain. + Live, + /// Some custom chain type. + Custom(String), +} + +impl Default for ChainType { + fn default() -> Self { + Self::Live + } +} + +/// Arbitrary properties defined in chain spec as a JSON object +pub type Properties = serde_json::map::Map; diff --git a/primitives/consensus/aura/Cargo.toml b/primitives/consensus/aura/Cargo.toml index 99ce51a229c72e045e97b92f9e8c8f8d3aff2513..10c7f5a2de0b570da7f99ded7848ef0af8c1694d 100644 --- a/primitives/consensus/aura/Cargo.toml +++ b/primitives/consensus/aura/Cargo.toml @@ -1,21 +1,24 @@ [package] name = "sp-consensus-aura" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] description = "Primitives for Aura consensus" edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-application-crypto = { version = "2.0.0-alpha.5", default-features = false, path = "../../application-crypto" } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../std" } -sp-api = { version = "2.0.0-alpha.5", default-features = false, path = "../../api" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../runtime" } -sp-inherents = { version = "2.0.0-alpha.5", default-features = false, path = "../../inherents" } -sp-timestamp = { version = "2.0.0-alpha.5", default-features = false, path = "../../timestamp" } +sp-application-crypto = { version = "2.0.0-rc4", default-features = false, path = "../../application-crypto" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../std" } +sp-api = { version = "2.0.0-rc4", default-features = false, path = "../../api" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../runtime" } +sp-inherents = { version = "2.0.0-rc4", default-features = false, path = "../../inherents" } +sp-timestamp = { version = "2.0.0-rc4", default-features = false, path = "../../timestamp" } [features] default = ["std"] @@ -28,6 +31,3 @@ std = [ "sp-inherents/std", "sp-timestamp/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/consensus/aura/src/inherents.rs b/primitives/consensus/aura/src/inherents.rs index 77ec03c6f43425bbaa1c4983c95f9585590b75b1..a18bd3370306196ddafc15e339457e4c5d1918ec 100644 --- a/primitives/consensus/aura/src/inherents.rs +++ b/primitives/consensus/aura/src/inherents.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. /// Contains the inherents for the AURA module diff --git a/primitives/consensus/aura/src/lib.rs b/primitives/consensus/aura/src/lib.rs index 2dda5b28bf825e7716578298ac9340013f1dd087..cf0bcf2218a06440ec815b84a16650a8f9eef0a1 100644 --- a/primitives/consensus/aura/src/lib.rs +++ b/primitives/consensus/aura/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Primitives for Aura. diff --git a/primitives/consensus/babe/Cargo.toml b/primitives/consensus/babe/Cargo.toml index 195a54a5910c419957f053a6f928aa369b467110..8199bad6be5d18043d2206ec82b0e786404a6afb 100644 --- a/primitives/consensus/babe/Cargo.toml +++ b/primitives/consensus/babe/Cargo.toml @@ -1,37 +1,43 @@ [package] name = "sp-consensus-babe" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] description = "Primitives for BABE consensus" edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-application-crypto = { version = "2.0.0-alpha.5", default-features = false, path = "../../application-crypto" } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../std" } -sp-api = { version = "2.0.0-alpha.5", default-features = false, path = "../../api" } -sp-consensus = { version = "0.8.0-alpha.5", optional = true, path = "../common" } -sp-consensus-vrf = { version = "0.8.0-alpha.5", path = "../vrf", default-features = false } -sp-inherents = { version = "2.0.0-alpha.5", default-features = false, path = "../../inherents" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../runtime" } -sp-timestamp = { version = "2.0.0-alpha.5", default-features = false, path = "../../timestamp" } +sp-application-crypto = { version = "2.0.0-rc4", default-features = false, path = "../../application-crypto" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +merlin = { version = "2.0", default-features = false } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../std" } +sp-api = { version = "2.0.0-rc4", default-features = false, path = "../../api" } +sp-consensus = { version = "0.8.0-rc4", optional = true, path = "../common" } +sp-consensus-slots = { version = "0.8.0-rc4", default-features = false, path = "../slots" } +sp-consensus-vrf = { version = "0.8.0-rc4", path = "../vrf", default-features = false } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../core" } +sp-inherents = { version = "2.0.0-rc4", default-features = false, path = "../../inherents" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../runtime" } +sp-timestamp = { version = "2.0.0-rc4", default-features = false, path = "../../timestamp" } [features] default = ["std"] std = [ "sp-application-crypto/std", "codec/std", + "merlin/std", "sp-std/std", "sp-api/std", "sp-consensus", + "sp-consensus-slots/std", "sp-consensus-vrf/std", + "sp-core/std", "sp-inherents/std", "sp-runtime/std", "sp-timestamp/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/consensus/babe/src/digests.rs b/primitives/consensus/babe/src/digests.rs index 6079aa88c87492538fbf3caefdd3775d4cdd9292..a680ca0656c3a5ffe1f2a11f7aee8b40abcf97af 100644 --- a/primitives/consensus/babe/src/digests.rs +++ b/primitives/consensus/babe/src/digests.rs @@ -1,40 +1,35 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Private implementation details of BABE digests. -#[cfg(feature = "std")] -use super::{BABE_ENGINE_ID, AuthoritySignature}; -use super::{AuthorityId, AuthorityIndex, SlotNumber, BabeAuthorityWeight}; -#[cfg(feature = "std")] -use sp_runtime::{DigestItem, generic::OpaqueDigestItemId}; -#[cfg(feature = "std")] -use std::{fmt::Debug, convert::{TryFrom, TryInto}}; -use codec::{Decode, Encode}; -#[cfg(feature = "std")] -use codec::Codec; +use super::{ + AllowedSlots, AuthorityId, AuthorityIndex, AuthoritySignature, BabeAuthorityWeight, + BabeEpochConfiguration, SlotNumber, BABE_ENGINE_ID, +}; +use codec::{Codec, Decode, Encode}; use sp_std::vec::Vec; -use sp_runtime::RuntimeDebug; -use sp_consensus_vrf::schnorrkel::{self, Randomness}; -#[cfg(feature = "std")] -use sp_consensus_vrf::schnorrkel::SignatureError; +use sp_runtime::{generic::OpaqueDigestItemId, DigestItem, RuntimeDebug}; + +use sp_consensus_vrf::schnorrkel::{Randomness, VRFOutput, VRFProof}; /// Raw BABE primary slot assignment pre-digest. #[derive(Clone, RuntimeDebug, Encode, Decode)] -pub struct RawPrimaryPreDigest { +pub struct PrimaryPreDigest { /// Authority index pub authority_index: super::AuthorityIndex, /// Slot number @@ -45,27 +40,9 @@ pub struct RawPrimaryPreDigest; - -#[cfg(feature = "std")] -impl TryFrom for PrimaryPreDigest { - type Error = SignatureError; - - fn try_from(raw: RawPrimaryPreDigest) -> Result { - Ok(PrimaryPreDigest { - authority_index: raw.authority_index, - slot_number: raw.slot_number, - vrf_output: raw.vrf_output.try_into()?, - vrf_proof: raw.vrf_proof.try_into()?, - }) - } -} - /// BABE secondary slot assignment pre-digest. #[derive(Clone, RuntimeDebug, Encode, Decode)] -pub struct SecondaryPreDigest { +pub struct SecondaryPlainPreDigest { /// Authority index /// /// This is not strictly-speaking necessary, since the secondary slots @@ -77,37 +54,51 @@ pub struct SecondaryPreDigest { pub slot_number: SlotNumber, } +/// BABE secondary deterministic slot assignment with VRF outputs. +#[derive(Clone, RuntimeDebug, Encode, Decode)] +pub struct SecondaryVRFPreDigest { + /// Authority index + pub authority_index: super::AuthorityIndex, + /// Slot number + pub slot_number: SlotNumber, + /// VRF output + pub vrf_output: VRFOutput, + /// VRF proof + pub vrf_proof: VRFProof, +} + /// 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). #[derive(Clone, RuntimeDebug, Encode, Decode)] -pub enum RawPreDigest { +pub enum PreDigest { /// A primary VRF-based slot assignment. #[codec(index = "1")] - Primary(RawPrimaryPreDigest), + Primary(PrimaryPreDigest), /// A secondary deterministic slot assignment. #[codec(index = "2")] - Secondary(SecondaryPreDigest), + SecondaryPlain(SecondaryPlainPreDigest), + /// A secondary deterministic slot assignment with VRF outputs. + #[codec(index = "3")] + SecondaryVRF(SecondaryVRFPreDigest), } -#[cfg(feature = "std")] -/// A BABE pre-runtime digest for std. -pub type PreDigest = RawPreDigest; - -impl RawPreDigest { +impl PreDigest { /// Returns the slot number of the pre digest. pub fn authority_index(&self) -> AuthorityIndex { match self { - RawPreDigest::Primary(primary) => primary.authority_index, - RawPreDigest::Secondary(secondary) => secondary.authority_index, + PreDigest::Primary(primary) => primary.authority_index, + PreDigest::SecondaryPlain(secondary) => secondary.authority_index, + PreDigest::SecondaryVRF(secondary) => secondary.authority_index, } } /// Returns the slot number of the pre digest. pub fn slot_number(&self) -> SlotNumber { match self { - RawPreDigest::Primary(primary) => primary.slot_number, - RawPreDigest::Secondary(secondary) => secondary.slot_number, + PreDigest::Primary(primary) => primary.slot_number, + PreDigest::SecondaryPlain(secondary) => secondary.slot_number, + PreDigest::SecondaryVRF(secondary) => secondary.slot_number, } } @@ -115,27 +106,15 @@ impl RawPreDigest { /// of the chain. pub fn added_weight(&self) -> crate::BabeBlockWeight { match self { - RawPreDigest::Primary(_) => 1, - RawPreDigest::Secondary(_) => 0, + PreDigest::Primary(_) => 1, + PreDigest::SecondaryPlain(_) | PreDigest::SecondaryVRF(_) => 0, } } } -#[cfg(feature = "std")] -impl TryFrom for PreDigest { - type Error = SignatureError; - - fn try_from(raw: RawPreDigest) -> Result { - Ok(match raw { - RawPreDigest::Primary(primary) => PreDigest::Primary(primary.try_into()?), - RawPreDigest::Secondary(secondary) => PreDigest::Secondary(secondary), - }) - } -} - /// Information about the next epoch. This is broadcast in the first block /// of the epoch. -#[derive(Decode, Encode, Default, PartialEq, Eq, Clone, RuntimeDebug)] +#[derive(Decode, Encode, PartialEq, Eq, Clone, RuntimeDebug)] pub struct NextEpochDescriptor { /// The authorities. pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, @@ -144,8 +123,30 @@ pub struct NextEpochDescriptor { pub randomness: Randomness, } +/// Information about the next epoch config, if changed. This is broadcast in the first +/// block of the epoch, and applies using the same rules as `NextEpochDescriptor`. +#[derive(Decode, Encode, PartialEq, Eq, Clone, RuntimeDebug)] +pub enum NextConfigDescriptor { + /// Version 1. + #[codec(index = "1")] + V1 { + /// Value of `c` in `BabeEpochConfiguration`. + c: (u64, u64), + /// Value of `allowed_slots` in `BabeEpochConfiguration`. + allowed_slots: AllowedSlots, + } +} + +impl From for BabeEpochConfiguration { + fn from(desc: NextConfigDescriptor) -> Self { + match desc { + NextConfigDescriptor::V1 { c, allowed_slots } => + Self { c, allowed_slots }, + } + } +} + /// A digest item which is usable with BABE consensus. -#[cfg(feature = "std")] pub trait CompatibleDigestItem: Sized { /// Construct a digest item which contains a BABE pre-digest. fn babe_pre_digest(seal: PreDigest) -> Self; @@ -159,13 +160,15 @@ pub trait CompatibleDigestItem: Sized { /// If this item is a BABE signature, return the signature. fn as_babe_seal(&self) -> Option; - /// If this item is a BABE epoch, return it. + /// If this item is a BABE epoch descriptor, return it. fn as_next_epoch_descriptor(&self) -> Option; + + /// If this item is a BABE config descriptor, return it. + fn as_next_config_descriptor(&self) -> Option; } -#[cfg(feature = "std")] impl CompatibleDigestItem for DigestItem where - Hash: Debug + Send + Sync + Eq + Clone + Codec + 'static + Hash: Send + Sync + Eq + Clone + Codec + 'static { fn babe_pre_digest(digest: PreDigest) -> Self { DigestItem::PreRuntime(BABE_ENGINE_ID, digest.encode()) @@ -190,4 +193,12 @@ impl CompatibleDigestItem for DigestItem where _ => None, }) } + + fn as_next_config_descriptor(&self) -> Option { + self.try_to(OpaqueDigestItemId::Consensus(&BABE_ENGINE_ID)) + .and_then(|x: super::ConsensusLog| match x { + super::ConsensusLog::NextConfigData(n) => Some(n), + _ => None, + }) + } } diff --git a/primitives/consensus/babe/src/inherents.rs b/primitives/consensus/babe/src/inherents.rs index 7c0744ac6e13ac21f4fc1fc01afd071d93e745ec..5384183f9e67835902387a2f92e401a2bf9546b4 100644 --- a/primitives/consensus/babe/src/inherents.rs +++ b/primitives/consensus/babe/src/inherents.rs @@ -1,18 +1,20 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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. +// 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. -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . //! Inherents for BABE use sp_inherents::{Error, InherentData, InherentIdentifier}; diff --git a/primitives/consensus/babe/src/lib.rs b/primitives/consensus/babe/src/lib.rs index 33701860d1f10234a823c4d625acfc02094f89f5..54f05d7bc51da5cf47706349132ea4e9981b419f 100644 --- a/primitives/consensus/babe/src/lib.rs +++ b/primitives/consensus/babe/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Primitives for BABE. #![deny(warnings)] @@ -22,14 +23,21 @@ pub mod digests; pub mod inherents; +pub use merlin::Transcript; pub use sp_consensus_vrf::schnorrkel::{ - Randomness, VRF_PROOF_LENGTH, VRF_OUTPUT_LENGTH, RANDOMNESS_LENGTH + Randomness, RANDOMNESS_LENGTH, VRF_OUTPUT_LENGTH, VRF_PROOF_LENGTH, }; -use codec::{Encode, Decode}; +use codec::{Decode, Encode}; +#[cfg(feature = "std")] +use sp_core::vrf::{VRFTranscriptData, VRFTranscriptValue}; +use sp_runtime::{traits::Header, ConsensusEngineId, RuntimeDebug}; use sp_std::vec::Vec; -use sp_runtime::{ConsensusEngineId, RuntimeDebug}; -use crate::digests::NextEpochDescriptor; + +use crate::digests::{NextConfigDescriptor, NextEpochDescriptor}; + +/// Key type for BABE module. +pub const KEY_TYPE: sp_core::crypto::KeyTypeId = sp_application_crypto::key_types::BABE; mod app { use sp_application_crypto::{app_crypto, key_types::BABE, sr25519}; @@ -39,6 +47,9 @@ mod app { /// The prefix used by BABE for its VRF keys. pub const BABE_VRF_PREFIX: &[u8] = b"substrate-babe-vrf"; +/// BABE VRFInOut context. +pub static BABE_VRF_INOUT_CONTEXT: &[u8] = b"BabeVRFInOutContext"; + /// 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")] @@ -66,7 +77,10 @@ pub const MEDIAN_ALGORITHM_CARDINALITY: usize = 1200; // arbitrary suggestion by pub type AuthorityIndex = u32; /// A slot number. -pub type SlotNumber = u64; +pub use sp_consensus_slots::SlotNumber; + +/// An equivocation proof for multiple block authorships on the same slot (i.e. double vote). +pub type EquivocationProof = sp_consensus_slots::EquivocationProof; /// The weight of an authority. // NOTE: we use a unique name for the weight to avoid conflicts with other @@ -76,6 +90,36 @@ pub type BabeAuthorityWeight = u64; /// The weight of a BABE block. pub type BabeBlockWeight = u32; +/// Make a VRF transcript from given randomness, slot number and epoch. +pub fn make_transcript( + randomness: &Randomness, + slot_number: u64, + epoch: u64, +) -> Transcript { + let mut transcript = Transcript::new(&BABE_ENGINE_ID); + transcript.append_u64(b"slot number", slot_number); + transcript.append_u64(b"current epoch", epoch); + transcript.append_message(b"chain randomness", &randomness[..]); + transcript +} + +/// Make a VRF transcript data container +#[cfg(feature = "std")] +pub fn make_transcript_data( + randomness: &Randomness, + slot_number: u64, + epoch: u64, +) -> VRFTranscriptData { + VRFTranscriptData { + label: &BABE_ENGINE_ID, + items: vec![ + ("slot number", VRFTranscriptValue::U64(slot_number)), + ("current epoch", VRFTranscriptValue::U64(epoch)), + ("chain randomness", VRFTranscriptValue::Bytes(&randomness[..])), + ] + } +} + /// An consensus log item for BABE. #[derive(Decode, Encode, Clone, PartialEq, Eq)] pub enum ConsensusLog { @@ -87,11 +131,15 @@ pub enum ConsensusLog { /// Disable the authority with given index. #[codec(index = "2")] OnDisabled(AuthorityIndex), + /// The epoch has changed, and the epoch after the current one will + /// enact different epoch configurations. + #[codec(index = "3")] + NextConfigData(NextConfigDescriptor), } /// Configuration data used by the BABE consensus engine. #[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)] -pub struct BabeConfiguration { +pub struct BabeGenesisConfigurationV1 { /// The slot duration in milliseconds for BABE. Currently, only /// the value provided by this type at genesis will be used. /// @@ -120,8 +168,78 @@ pub struct BabeConfiguration { pub secondary_slots: bool, } +impl From for BabeGenesisConfiguration { + fn from(v1: BabeGenesisConfigurationV1) -> Self { + Self { + slot_duration: v1.slot_duration, + epoch_length: v1.epoch_length, + c: v1.c, + genesis_authorities: v1.genesis_authorities, + randomness: v1.randomness, + allowed_slots: if v1.secondary_slots { + AllowedSlots::PrimaryAndSecondaryPlainSlots + } else { + AllowedSlots::PrimarySlots + }, + } + } +} + +/// Configuration data used by the BABE consensus engine. +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)] +pub struct BabeGenesisConfiguration { + /// 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. + 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 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 authorities for the genesis epoch. + pub genesis_authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, + + /// The randomness for the genesis epoch. + pub randomness: Randomness, + + /// Type of allowed slots. + pub allowed_slots: AllowedSlots, +} + +/// Types of allowed slots. +#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, RuntimeDebug)] +pub enum AllowedSlots { + /// Only allow primary slots. + PrimarySlots, + /// Allow primary and secondary plain slots. + PrimaryAndSecondaryPlainSlots, + /// Allow primary and secondary VRF slots. + PrimaryAndSecondaryVRFSlots, +} + +impl AllowedSlots { + /// Whether plain secondary slots are allowed. + pub fn is_secondary_plain_slots_allowed(&self) -> bool { + *self == Self::PrimaryAndSecondaryPlainSlots + } + + /// Whether VRF secondary slots are allowed. + pub fn is_secondary_vrf_slots_allowed(&self) -> bool { + *self == Self::PrimaryAndSecondaryVRFSlots + } +} + #[cfg(feature = "std")] -impl sp_consensus::SlotData for BabeConfiguration { +impl sp_consensus::SlotData for BabeGenesisConfiguration { fn slot_duration(&self) -> u64 { self.slot_duration } @@ -129,16 +247,150 @@ impl sp_consensus::SlotData for BabeConfiguration { const SLOT_KEY: &'static [u8] = b"babe_configuration"; } +/// Configuration data used by the BABE consensus engine. +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)] +pub struct BabeEpochConfiguration { + /// A constant value that is used in the threshold calculation formula. + /// 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), + + /// Whether this chain should run with secondary slots, which are assigned + /// in round-robin manner. + pub allowed_slots: AllowedSlots, +} + +/// Verifies the equivocation proof by making sure that: both headers have +/// different hashes, are targetting the same slot, and have valid signatures by +/// the same authority. +pub fn check_equivocation_proof(proof: EquivocationProof) -> bool +where + H: Header, +{ + use digests::*; + use sp_application_crypto::RuntimeAppPublic; + + let find_pre_digest = |header: &H| { + header + .digest() + .logs() + .iter() + .find_map(|log| log.as_babe_pre_digest()) + }; + + let verify_seal_signature = |mut header: H, offender: &AuthorityId| { + let seal = header.digest_mut().pop()?.as_babe_seal()?; + let pre_hash = header.hash(); + + if !offender.verify(&pre_hash.as_ref(), &seal) { + return None; + } + + Some(()) + }; + + let verify_proof = || { + // we must have different headers for the equivocation to be valid + if proof.first_header.hash() == proof.second_header.hash() { + return None; + } + + let first_pre_digest = find_pre_digest(&proof.first_header)?; + let second_pre_digest = find_pre_digest(&proof.second_header)?; + + // both headers must be targetting the same slot and it must + // be the same as the one in the proof. + if proof.slot_number != first_pre_digest.slot_number() || + first_pre_digest.slot_number() != second_pre_digest.slot_number() + { + return None; + } + + // both headers must have been authored by the same authority + if first_pre_digest.authority_index() != second_pre_digest.authority_index() { + return None; + } + + // we finally verify that the expected authority has signed both headers and + // that the signature is valid. + verify_seal_signature(proof.first_header, &proof.offender)?; + verify_seal_signature(proof.second_header, &proof.offender)?; + + Some(()) + }; + + // NOTE: we isolate the verification code into an helper function that + // returns `Option<()>` so that we can use `?` to deal with any intermediate + // errors and discard the proof as invalid. + verify_proof().is_some() +} + +/// An opaque type used to represent the key ownership proof at the runtime API +/// boundary. The inner value is an encoded representation of the actual key +/// ownership proof which will be parameterized when defining the runtime. At +/// the runtime API boundary this type is unknown and as such we keep this +/// opaque representation, implementors of the runtime API will have to make +/// sure that all usages of `OpaqueKeyOwnershipProof` refer to the same type. +#[derive(Decode, Encode, PartialEq)] +pub struct OpaqueKeyOwnershipProof(Vec); +impl OpaqueKeyOwnershipProof { + /// Create a new `OpaqueKeyOwnershipProof` using the given encoded + /// representation. + pub fn new(inner: Vec) -> OpaqueKeyOwnershipProof { + OpaqueKeyOwnershipProof(inner) + } + + /// Try to decode this `OpaqueKeyOwnershipProof` into the given concrete key + /// ownership proof type. + pub fn decode(self) -> Option { + Decode::decode(&mut &self.0[..]).ok() + } +} + sp_api::decl_runtime_apis! { /// API necessary for block authorship with BABE. + #[api_version(2)] pub trait BabeApi { - /// Return the configuration for BABE. Currently, - /// only the value provided by this type at genesis will be used. - /// - /// Dynamic configuration may be supported in the future. - fn configuration() -> BabeConfiguration; + /// Return the genesis configuration for BABE. The configuration is only read on genesis. + fn configuration() -> BabeGenesisConfiguration; + + /// Return the configuration for BABE. Version 1. + #[changed_in(2)] + fn configuration() -> BabeGenesisConfigurationV1; /// Returns the slot number that started the current epoch. fn current_epoch_start() -> SlotNumber; + + /// Generates a proof of key ownership for the given authority in the + /// current epoch. An example usage of this module is coupled with the + /// session historical module to prove that a given authority key is + /// tied to a given staking identity during a specific session. Proofs + /// of key ownership are necessary for submitting equivocation reports. + /// NOTE: even though the API takes a `slot_number` as parameter the current + /// implementations ignores this parameter and instead relies on this + /// method being called at the correct block height, i.e. any point at + /// which the epoch for the given slot is live on-chain. Future + /// implementations will instead use indexed data through an offchain + /// worker, not requiring older states to be available. + fn generate_key_ownership_proof( + slot_number: SlotNumber, + authority_id: AuthorityId, + ) -> Option; + + /// Submits an unsigned extrinsic to report an equivocation. The caller + /// must provide the equivocation proof and a key ownership proof + /// (should be obtained using `generate_key_ownership_proof`). The + /// extrinsic will be unsigned and should only be accepted for local + /// authorship (not to be broadcast to the network). This method returns + /// `None` when creation of the extrinsic fails, e.g. if equivocation + /// reporting is disabled for the given runtime (i.e. this method is + /// hardcoded to return `None`). Only useful in an offchain context. + fn submit_report_equivocation_unsigned_extrinsic( + equivocation_proof: EquivocationProof, + key_owner_proof: OpaqueKeyOwnershipProof, + ) -> Option<()>; } } diff --git a/primitives/consensus/common/Cargo.toml b/primitives/consensus/common/Cargo.toml index 112b9499a7485a289893965c644918b1451165a1..c03f1f150200210271292e69267455759a00c0a4 100644 --- a/primitives/consensus/common/Cargo.toml +++ b/primitives/consensus/common/Cargo.toml @@ -1,38 +1,40 @@ [package] name = "sp-consensus" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Common utilities for building and using consensus engines in substrate." documentation = "https://docs.rs/sp-consensus/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] derive_more = "0.99.2" -libp2p = { version = "0.16.2", default-features = false } +libp2p = { version = "0.21.1", default-features = false } log = "0.4.8" -sp-core = { path= "../../core" , version = "2.0.0-alpha.5"} -sp-inherents = { version = "2.0.0-alpha.5", path = "../../inherents" } -sp-state-machine = { version = "0.8.0-alpha.5", path = "../../../primitives/state-machine" } +sp-core = { path= "../../core", version = "2.0.0-rc4"} +sp-inherents = { version = "2.0.0-rc4", path = "../../inherents" } +sp-state-machine = { version = "0.8.0-rc4", path = "../../../primitives/state-machine" } futures = { version = "0.3.1", features = ["thread-pool"] } futures-timer = "3.0.1" -futures-diagnose = "1.0" -sp-std = { version = "2.0.0-alpha.5", path = "../../std" } -sp-version = { version = "2.0.0-alpha.5", path = "../../version" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../runtime" } -sp-utils = { version = "2.0.0-alpha.5", path = "../../utils" } -codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive"] } +sp-std = { version = "2.0.0-rc4", path = "../../std" } +sp-version = { version = "2.0.0-rc4", path = "../../version" } +sp-runtime = { version = "2.0.0-rc4", path = "../../runtime" } +sp-utils = { version = "2.0.0-rc4", path = "../../utils" } +sp-trie = { version = "2.0.0-rc4", path = "../../trie" } +codec = { package = "parity-scale-codec", version = "1.3.1", features = ["derive"] } parking_lot = "0.10.0" serde = { version = "1.0", features = ["derive"] } +prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.8.0-rc4"} +wasm-timer = "0.2.4" [dev-dependencies] -sp-test-primitives = { version = "2.0.0-dev", path = "../../test-primitives" } +sp-test-primitives = { version = "2.0.0-rc4", path = "../../test-primitives" } [features] default = [] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/consensus/common/src/block_import.rs b/primitives/consensus/common/src/block_import.rs index eb90ac9f1d4df6ceb0ecba42bca4b7911cce7de5..5e593da1163d77a65be2ca7bfaa9cd9f4114d71b 100644 --- a/primitives/consensus/common/src/block_import.rs +++ b/primitives/consensus/common/src/block_import.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Block import helpers. diff --git a/primitives/consensus/common/src/block_validation.rs b/primitives/consensus/common/src/block_validation.rs index e8054f3ae40d7291b62604876ab9a639267f2632..66f960f16fff396fe40a6f3e38ff5a0d84ffc17e 100644 --- a/primitives/consensus/common/src/block_validation.rs +++ b/primitives/consensus/common/src/block_validation.rs @@ -36,7 +36,10 @@ impl, B: Block> Chain for Arc { #[derive(Debug, PartialEq, Eq)] pub enum Validation { /// Valid block announcement. - Success, + Success { + /// Is this the new best block of the node? + is_new_best: bool, + }, /// Invalid block announcement. Failure, } @@ -49,18 +52,10 @@ pub trait BlockAnnounceValidator { /// Default implementation of `BlockAnnounceValidator`. #[derive(Debug)] -pub struct DefaultBlockAnnounceValidator { - chain: C -} - -impl DefaultBlockAnnounceValidator { - pub fn new(chain: C) -> Self { - Self { chain } - } -} +pub struct DefaultBlockAnnounceValidator; -impl> BlockAnnounceValidator for DefaultBlockAnnounceValidator { +impl BlockAnnounceValidator for DefaultBlockAnnounceValidator { fn validate(&mut self, _h: &B::Header, _d: &[u8]) -> Result> { - Ok(Validation::Success) + Ok(Validation::Success { is_new_best: false }) } } diff --git a/primitives/consensus/common/src/error.rs b/primitives/consensus/common/src/error.rs index d7e396223a2c53611856642631f363025107f486..0da749589013d8ce2a8328ac6c1f647b83ba2005 100644 --- a/primitives/consensus/common/src/error.rs +++ b/primitives/consensus/common/src/error.rs @@ -1,22 +1,23 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Error types in Consensus use sp_version::RuntimeVersion; -use sp_core::ed25519::{Public, Signature}; +use sp_core::ed25519::Public; use std::error; /// Result type alias. @@ -48,7 +49,7 @@ pub enum Error { CannotPropose, /// Error checking signature #[display(fmt="Message signature {:?} by {:?} is invalid.", _0, _1)] - InvalidSignature(Signature, Public), + InvalidSignature(Vec, Vec), /// Invalid authorities set received from the runtime. #[display(fmt="Current state of blockchain has invalid authorities set")] InvalidAuthoritiesSet, @@ -79,6 +80,9 @@ pub enum Error { #[display(fmt="Chain lookup failed: {}", _0)] #[from(ignore)] ChainLookup(String), + /// Signing failed + #[display(fmt="Failed to sign using key: {:?}. Reason: {}", _0, _1)] + CannotSign(Vec, String) } impl error::Error for Error { diff --git a/primitives/consensus/common/src/evaluation.rs b/primitives/consensus/common/src/evaluation.rs index 5542042fedb1c186dae948b7da1b91e7c57fd9e2..76fcd5310b06af6daf0704b964059a3d0e95ad36 100644 --- a/primitives/consensus/common/src/evaluation.rs +++ b/primitives/consensus/common/src/evaluation.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Block evaluation and evaluation errors. diff --git a/primitives/consensus/common/src/import_queue.rs b/primitives/consensus/common/src/import_queue.rs index 2da0bcac0c17b8b6661bd5fcedf0f7ef7e1a691c..94228a266385f6bc5469f0dda14ba1e2c89262e0 100644 --- a/primitives/consensus/common/src/import_queue.rs +++ b/primitives/consensus/common/src/import_queue.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Import Queue primitive: something which can verify and import blocks. //! @@ -26,13 +27,17 @@ //! queues to be instantiated simply. use std::collections::HashMap; + use sp_runtime::{Justification, traits::{Block as BlockT, Header as _, NumberFor}}; -use crate::error::Error as ConsensusError; -use crate::block_import::{ - BlockImport, BlockOrigin, BlockImportParams, ImportedAux, JustificationImport, ImportResult, - BlockCheckParams, FinalityProofImport, -}; +use crate::{ + error::Error as ConsensusError, + block_import::{ + BlockImport, BlockOrigin, BlockImportParams, ImportedAux, JustificationImport, ImportResult, + BlockCheckParams, FinalityProofImport, + }, + metrics::Metrics, +}; pub use basic_queue::BasicQueue; mod basic_queue; @@ -185,6 +190,17 @@ pub fn import_single_block, Transaction>( block_origin: BlockOrigin, block: IncomingBlock, verifier: &mut V, +) -> Result>, BlockImportError> { + import_single_block_metered(import_handle, block_origin, block, verifier, None) +} + +/// Single block import function with metering. +pub(crate) fn import_single_block_metered, Transaction>( + import_handle: &mut dyn BlockImport, + block_origin: BlockOrigin, + block: IncomingBlock, + verifier: &mut V, + metrics: Option, ) -> Result>, BlockImportError> { let peer = block.origin; @@ -206,8 +222,8 @@ pub fn import_single_block, Transaction>( let hash = header.hash(); let parent_hash = header.parent_hash().clone(); - let import_error = |e| { - match e { + let import_handler = |import| { + match import { Ok(ImportResult::AlreadyInChain) => { trace!(target: "sync", "Block already in chain {}: {:?}", number, hash); Ok(BlockImportResult::ImportedKnown(number)) @@ -231,7 +247,8 @@ pub fn import_single_block, Transaction>( } } }; - match import_error(import_handle.check_block(BlockCheckParams { + + match import_handler(import_handle.check_block(BlockCheckParams { hash, number, parent_hash, @@ -242,6 +259,7 @@ pub fn import_single_block, Transaction>( r => return Ok(r), // Any other successful result means that the block is already imported. } + let started = wasm_timer::Instant::now(); let (mut import_block, maybe_keys) = verifier.verify(block_origin, header, justification, block.body) .map_err(|msg| { if let Some(ref peer) = peer { @@ -249,14 +267,21 @@ pub fn import_single_block, Transaction>( } else { trace!(target: "sync", "Verifying {}({}) failed: {}", number, hash, msg); } + if let Some(metrics) = metrics.as_ref() { + metrics.report_verification(false, started.elapsed()); + } BlockImportError::VerificationFailed(peer.clone(), msg) })?; + if let Some(metrics) = metrics.as_ref() { + metrics.report_verification(true, started.elapsed()); + } + let mut cache = HashMap::new(); if let Some(keys) = maybe_keys { cache.extend(keys.into_iter()); } import_block.allow_missing_state = block.allow_missing_state; - import_error(import_handle.import_block(import_block.convert_transaction(), cache)) + import_handler(import_handle.import_block(import_block.convert_transaction(), cache)) } diff --git a/primitives/consensus/common/src/import_queue/basic_queue.rs b/primitives/consensus/common/src/import_queue/basic_queue.rs index 024e473849349f416ce0d84a87222f2fb57bd88b..8eb194841f196f4e1fa6b073ee84307743d7de98 100644 --- a/primitives/consensus/common/src/import_queue/basic_queue.rs +++ b/primitives/consensus/common/src/import_queue/basic_queue.rs @@ -1,32 +1,36 @@ -// Copyright 2017-2020 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::{mem, pin::Pin, time::Duration, marker::PhantomData, sync::Arc}; +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::{mem, pin::Pin, time::Duration, marker::PhantomData}; use futures::{prelude::*, task::Context, task::Poll}; use futures_timer::Delay; -use parking_lot::{Mutex, Condvar}; use sp_runtime::{Justification, traits::{Block as BlockT, Header as HeaderT, NumberFor}}; use sp_utils::mpsc::{TracingUnboundedSender, tracing_unbounded}; - -use crate::block_import::BlockOrigin; -use crate::import_queue::{ - BlockImportResult, BlockImportError, Verifier, BoxBlockImport, BoxFinalityProofImport, - BoxJustificationImport, ImportQueue, Link, Origin, - IncomingBlock, import_single_block, - buffered_link::{self, BufferedLinkSender, BufferedLinkReceiver} +use prometheus_endpoint::Registry; + +use crate::{ + block_import::BlockOrigin, + import_queue::{ + BlockImportResult, BlockImportError, Verifier, BoxBlockImport, BoxFinalityProofImport, + BoxJustificationImport, ImportQueue, Link, Origin, + IncomingBlock, import_single_block_metered, + buffered_link::{self, BufferedLinkSender, BufferedLinkReceiver}, + }, + metrics::Metrics, }; /// Interface to a basic block import queue that is importing blocks sequentially in a separate @@ -36,31 +40,14 @@ pub struct BasicQueue { sender: TracingUnboundedSender>, /// Results coming from the worker task. result_port: BufferedLinkReceiver, - /// If it isn't possible to spawn the future in `future_to_spawn` (which is notably the case in - /// "no std" environment), we instead put it in `manual_poll`. It is then polled manually from - /// `poll_actions`. - manual_poll: Option + Send>>>, - /// A thread pool where the background worker is being run. - pool: Option, - pool_guard: Arc<(Mutex, Condvar)>, _phantom: PhantomData, } impl Drop for BasicQueue { fn drop(&mut self) { - self.pool = None; // Flush the queue and close the receiver to terminate the future. self.sender.close_channel(); self.result_port.close(); - - // Make sure all pool threads terminate. - // https://github.com/rust-lang/futures-rs/issues/1470 - // https://github.com/rust-lang/futures-rs/issues/1349 - let (ref mutex, ref condvar) = *self.pool_guard; - let mut lock = mutex.lock(); - while *lock != 0 { - condvar.wait(&mut lock); - } } } @@ -74,49 +61,29 @@ impl BasicQueue { block_import: BoxBlockImport, justification_import: Option>, finality_proof_import: Option>, + spawner: &impl sp_core::traits::SpawnNamed, + prometheus_registry: Option<&Registry>, ) -> Self { let (result_sender, result_port) = buffered_link::buffered_link(); + let metrics = prometheus_registry.and_then(|r| + Metrics::register(r) + .map_err(|err| { log::warn!("Failed to register Prometheus metrics: {}", err); }) + .ok() + ); let (future, worker_sender) = BlockImportWorker::new( result_sender, verifier, block_import, justification_import, finality_proof_import, + metrics, ); - let guard = Arc::new((Mutex::new(0usize), Condvar::new())); - let guard_start = guard.clone(); - let guard_end = guard.clone(); - - let mut pool = futures::executor::ThreadPool::builder() - .name_prefix("import-queue-worker-") - .pool_size(1) - .after_start(move |_| *guard_start.0.lock() += 1) - .before_stop(move |_| { - let (ref mutex, ref condvar) = *guard_end; - let mut lock = mutex.lock(); - *lock -= 1; - if *lock == 0 { - condvar.notify_one(); - } - }) - .create() - .ok(); - - let manual_poll; - if let Some(pool) = &mut pool { - pool.spawn_ok(futures_diagnose::diagnose("import-queue", future)); - manual_poll = None; - } else { - manual_poll = Some(Box::pin(future) as Pin>); - } + spawner.spawn_blocking("basic-block-import-worker", future.boxed()); Self { sender: worker_sender, result_port, - manual_poll, - pool, - pool_guard: guard, _phantom: PhantomData, } } @@ -160,15 +127,6 @@ impl ImportQueue for BasicQueue } fn poll_actions(&mut self, cx: &mut Context, link: &mut dyn Link) { - // As a backup mechanism, if we failed to spawn the `future_to_spawn`, we instead poll - // manually here. - if let Some(manual_poll) = self.manual_poll.as_mut() { - match Future::poll(Pin::new(manual_poll), cx) { - Poll::Pending => {} - _ => self.manual_poll = None, - } - } - self.result_port.poll_actions(cx, link); } } @@ -186,6 +144,7 @@ struct BlockImportWorker { justification_import: Option>, finality_proof_import: Option>, delay_between_blocks: Duration, + metrics: Option, _phantom: PhantomData, } @@ -196,6 +155,7 @@ impl BlockImportWorker { block_import: BoxBlockImport, justification_import: Option>, finality_proof_import: Option>, + metrics: Option, ) -> (impl Future + Send, TracingUnboundedSender>) { let (sender, mut port) = tracing_unbounded("mpsc_block_import_worker"); @@ -204,6 +164,7 @@ impl BlockImportWorker { justification_import, finality_proof_import, delay_between_blocks: Duration::new(0, 0), + metrics, _phantom: PhantomData, }; @@ -264,7 +225,7 @@ impl BlockImportWorker { // a `Future` into `importing`. let (bi, verif) = block_import_verifier.take() .expect("block_import_verifier is always Some; qed"); - importing = Some(worker.import_a_batch_of_blocks(bi, verif, origin, blocks)); + importing = Some(worker.import_batch(bi, verif, origin, blocks)); }, ToWorkerMsg::ImportFinalityProof(who, hash, number, proof) => { let (_, verif) = block_import_verifier.as_mut() @@ -286,16 +247,17 @@ impl BlockImportWorker { /// /// For lifetime reasons, the `BlockImport` implementation must be passed by value, and is /// yielded back in the output once the import is finished. - fn import_a_batch_of_blocks>( + fn import_batch>( &mut self, block_import: BoxBlockImport, verifier: V, origin: BlockOrigin, - blocks: Vec> + blocks: Vec>, ) -> impl Future, V)> { let mut result_sender = self.result_sender.clone(); + let metrics = self.metrics.clone(); - import_many_blocks(block_import, origin, blocks, verifier, self.delay_between_blocks) + import_many_blocks(block_import, origin, blocks, verifier, self.delay_between_blocks, metrics) .then(move |(imported, count, results, block_import, verifier)| { result_sender.blocks_processed(imported, count, results); future::ready((block_import, verifier)) @@ -366,6 +328,7 @@ fn import_many_blocks, Transaction>( blocks: Vec>, verifier: V, delay_between_blocks: Duration, + metrics: Option, ) -> impl Future< Output = ( usize, @@ -415,9 +378,9 @@ fn import_many_blocks, Transaction>( None => { // No block left to import, success! let import_handle = import_handle.take() - .expect("Future polled again after it has finished"); + .expect("Future polled again after it has finished (import handle is None)"); let verifier = verifier.take() - .expect("Future polled again after it has finished"); + .expect("Future polled again after it has finished (verifier handle is None)"); let results = mem::replace(&mut results, Vec::new()); return Poll::Ready((imported, count, results, import_handle, verifier)); }, @@ -427,9 +390,9 @@ fn import_many_blocks, Transaction>( // therefore `import_handle` and `verifier` are always `Some` here. It is illegal to poll // a `Future` again after it has ended. let import_handle = import_handle.as_mut() - .expect("Future polled again after it has finished"); + .expect("Future polled again after it has finished (import handle is None)"); let verifier = verifier.as_mut() - .expect("Future polled again after it has finished"); + .expect("Future polled again after it has finished (verifier handle is None)"); let block_number = block.header.as_ref().map(|h| h.number().clone()); let block_hash = block.hash; @@ -437,14 +400,19 @@ fn import_many_blocks, Transaction>( Err(BlockImportError::Cancelled) } else { // The actual import. - import_single_block( + import_single_block_metered( &mut **import_handle, blocks_origin.clone(), block, verifier, + metrics.clone(), ) }; + if let Some(metrics) = metrics.as_ref() { + metrics.report_import::(&import_result); + } + if import_result.is_ok() { trace!(target: "sync", "Block imported successfully {:?} ({})", block_number, block_hash); imported += 1; diff --git a/primitives/consensus/common/src/import_queue/buffered_link.rs b/primitives/consensus/common/src/import_queue/buffered_link.rs index ea77fc97f0e8a28e889ea8c13c1644a2f968a734..d85121a710ecbee67716fa1462c2b5dfc96035d1 100644 --- a/primitives/consensus/common/src/import_queue/buffered_link.rs +++ b/primitives/consensus/common/src/import_queue/buffered_link.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Provides the `buffered_link` utility. //! diff --git a/primitives/consensus/common/src/lib.rs b/primitives/consensus/common/src/lib.rs index 09dc031dc9ba08863ac4f53136792bea2aef7668..da23172783cdcba7d973a5c6f4c1dd96b6b86963 100644 --- a/primitives/consensus/common/src/lib.rs +++ b/primitives/consensus/common/src/lib.rs @@ -44,6 +44,7 @@ pub mod block_import; mod select_chain; pub mod import_queue; pub mod evaluation; +mod metrics; // block size limit. const MAX_BLOCK_SIZE: usize = 4 * 1024 * 1024 + 512; @@ -71,7 +72,9 @@ pub enum BlockStatus { Unknown, } -/// Environment producer for a Consensus instance. Creates proposer instance and communication streams. +/// Environment for a Consensus instance. +/// +/// Creates proposer instance. pub trait Environment { /// The proposer type this creates. type Proposer: Proposer + Send + 'static; @@ -152,9 +155,9 @@ pub trait Proposer { /// /// # Return /// - /// Returns a future that resolves to a [`Proposal`] or to [`Self::Error`]. + /// Returns a future that resolves to a [`Proposal`] or to [`Error`]. fn propose( - &mut self, + self, inherent_data: InherentData, inherent_digests: DigestFor, max_duration: Duration, diff --git a/primitives/consensus/common/src/metrics.rs b/primitives/consensus/common/src/metrics.rs new file mode 100644 index 0000000000000000000000000000000000000000..90df85a2948ef39cfb391a9f09a168b0e8effbcd --- /dev/null +++ b/primitives/consensus/common/src/metrics.rs @@ -0,0 +1,80 @@ +// Copyright 2020 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 . + +//! Metering tools for consensus + +use prometheus_endpoint::{register, U64, Registry, PrometheusError, Opts, CounterVec, HistogramVec, HistogramOpts}; + +use sp_runtime::traits::{Block as BlockT, NumberFor}; + +use crate::import_queue::{BlockImportResult, BlockImportError}; + +/// Generic Prometheus metrics for common consensus functionality. +#[derive(Clone)] +pub(crate) struct Metrics { + pub import_queue_processed: CounterVec, + pub block_verification_time: HistogramVec, +} + +impl Metrics { + pub(crate) fn register(registry: &Registry) -> Result { + Ok(Self { + import_queue_processed: register( + CounterVec::new( + Opts::new("import_queue_processed_total", "Blocks processed by import queue"), + &["result"] // 'success or failure + )?, + registry, + )?, + block_verification_time: register( + HistogramVec::new( + HistogramOpts::new( + "block_verification_time", + "Histogram of time taken to import blocks", + ), + &["result"], + )?, + registry, + )?, + }) + } + + pub fn report_import( + &self, + result: &Result>, BlockImportError>, + ) { + let label = match result { + Ok(_) => "success", + Err(BlockImportError::IncompleteHeader(_)) => "incomplete_header", + Err(BlockImportError::VerificationFailed(_,_)) => "verification_failed", + Err(BlockImportError::BadBlock(_)) => "bad_block", + Err(BlockImportError::MissingState) => "missing_state", + Err(BlockImportError::UnknownParent) => "unknown_parent", + Err(BlockImportError::Cancelled) => "cancelled", + Err(BlockImportError::Other(_)) => "failed", + }; + + self.import_queue_processed.with_label_values( + &[label] + ).inc(); + } + + pub fn report_verification(&self, success: bool, time: std::time::Duration) { + self.block_verification_time.with_label_values( + &[if success { "success" } else { "verification_failed" }] + ).observe(time.as_secs_f64()); + } +} diff --git a/primitives/consensus/common/src/offline_tracker.rs b/primitives/consensus/common/src/offline_tracker.rs index b4959503b1d394403de4434865dd10d3f43c61ea..b96498041f25d39fc55e12d9d5fd99cb3e974ce9 100644 --- a/primitives/consensus/common/src/offline_tracker.rs +++ b/primitives/consensus/common/src/offline_tracker.rs @@ -1,23 +1,25 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tracks offline validators. use std::collections::HashMap; -use std::time::{Instant, Duration}; +use std::time::Duration; +use wasm_timer::Instant; // time before we report a validator. const REPORT_TIME: Duration = Duration::from_secs(60 * 5); diff --git a/primitives/consensus/pow/Cargo.toml b/primitives/consensus/pow/Cargo.toml index 5ca60bb2155590fa34e1368ee1758ce7639871aa..5e031235dc10a1cd1abd7eed8f9b747fef4b4218 100644 --- a/primitives/consensus/pow/Cargo.toml +++ b/primitives/consensus/pow/Cargo.toml @@ -1,19 +1,22 @@ [package] name = "sp-consensus-pow" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] description = "Primitives for Aura consensus" edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-api = { version = "2.0.0-alpha.5", default-features = false, path = "../../api" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../std" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../runtime" } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../core" } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } +sp-api = { version = "2.0.0-rc4", default-features = false, path = "../../api" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../std" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../runtime" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../core" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } [features] default = ["std"] @@ -24,6 +27,3 @@ std = [ "sp-core/std", "codec/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/consensus/pow/src/lib.rs b/primitives/consensus/pow/src/lib.rs index fa8f75d1be64c3e014cfa43f5cb15801dd84a851..79c9b6f16c3bd9e3cb91dec5a9e2fa40f9d3c43c 100644 --- a/primitives/consensus/pow/src/lib.rs +++ b/primitives/consensus/pow/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Primitives for Substrate Proof-of-Work (PoW) consensus. diff --git a/primitives/consensus/slots/Cargo.toml b/primitives/consensus/slots/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..f8435495d96db3564bc70d17b71812ea8512111e --- /dev/null +++ b/primitives/consensus/slots/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "sp-consensus-slots" +version = "0.8.0-rc4" +authors = ["Parity Technologies "] +description = "Primitives for slots-based consensus" +edition = "2018" +license = "Apache-2.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../runtime" } + +[features] +default = ["std"] +std = [ + "codec/std", + "sp-runtime/std", +] diff --git a/primitives/consensus/slots/src/lib.rs b/primitives/consensus/slots/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..f898cf9da6e2a0e19e0bd89b0c6868fea4a7aff1 --- /dev/null +++ b/primitives/consensus/slots/src/lib.rs @@ -0,0 +1,41 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Primitives for slots-based consensus engines. + +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::{Decode, Encode}; + +/// A slot number. +pub type SlotNumber = u64; + +/// Represents an equivocation proof. An equivocation happens when a validator +/// produces more than one block on the same slot. The proof of equivocation +/// are the given distinct headers that were signed by the validator and which +/// include the slot number. +#[derive(Clone, Debug, Decode, Encode, PartialEq)] +pub struct EquivocationProof { + /// Returns the authority id of the equivocator. + pub offender: Id, + /// The slot number at which the equivocation happened. + pub slot_number: SlotNumber, + /// The first header involved in the equivocation. + pub first_header: Header, + /// The second header involved in the equivocation. + pub second_header: Header, +} diff --git a/primitives/consensus/vrf/Cargo.toml b/primitives/consensus/vrf/Cargo.toml index cf194ec38b50ac75b638044936ceca73172309c8..3c89c05bb1aebde21b1777eb30bbaaf299d1c318 100644 --- a/primitives/consensus/vrf/Cargo.toml +++ b/primitives/consensus/vrf/Cargo.toml @@ -1,29 +1,29 @@ [package] name = "sp-consensus-vrf" -version = "0.8.0-alpha.5" +version = "0.8.0-rc4" authors = ["Parity Technologies "] description = "Primitives for VRF based consensus" edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" repository = "https://github.com/paritytech/substrate/" homepage = "https://substrate.dev" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] codec = { version = "1.0.0", package = "parity-scale-codec", default-features = false } -schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated"], optional = true } -sp-std = { version = "2.0.0-alpha.5", path = "../../std", default-features = false } -sp-core = { version = "2.0.0-alpha.5", path = "../../core", default-features = false } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../runtime" } +schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated", "u64_backend"], default-features = false } +sp-std = { version = "2.0.0-rc4", path = "../../std", default-features = false } +sp-core = { version = "2.0.0-rc4", path = "../../core", default-features = false } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../runtime" } [features] default = ["std"] std = [ "codec/std", - "schnorrkel", + "schnorrkel/std", "sp-std/std", "sp-core/std", "sp-runtime/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/consensus/vrf/src/lib.rs b/primitives/consensus/vrf/src/lib.rs index 4ec6e376d6829f15937e38d569c9edf1779b0927..430e11974bcd44cc6a3919ef1d8ad84af1357ddb 100644 --- a/primitives/consensus/vrf/src/lib.rs +++ b/primitives/consensus/vrf/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Primitives for VRF-based consensus engines. #![cfg_attr(not(feature = "std"), no_std)] diff --git a/primitives/consensus/vrf/src/schnorrkel.rs b/primitives/consensus/vrf/src/schnorrkel.rs index 265572dbdaee78dc4848f075bf22a690ea743a4e..65e68375865d05bb6e19929985abad3908218c4c 100644 --- a/primitives/consensus/vrf/src/schnorrkel.rs +++ b/primitives/consensus/vrf/src/schnorrkel.rs @@ -1,87 +1,54 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Schnorrkel-based VRF. -use codec::{Encode, Decode}; -use sp_runtime::RuntimeDebug; +use codec::{Encode, Decode, EncodeLike}; +use sp_std::{convert::TryFrom, prelude::*}; +use sp_core::U512; use sp_std::ops::{Deref, DerefMut}; -#[cfg(feature = "std")] -use std::convert::TryFrom; -#[cfg(feature = "std")] -use codec::EncodeLike; -#[cfg(feature = "std")] use schnorrkel::errors::MultiSignatureStage; -#[cfg(feature = "std")] -use sp_core::U512; - -#[cfg(feature = "std")] -pub use schnorrkel::{SignatureError, vrf::{VRF_PROOF_LENGTH, VRF_OUTPUT_LENGTH}}; - -/// The length of the VRF proof. -#[cfg(not(feature = "std"))] -pub const VRF_PROOF_LENGTH: usize = 64; -/// The length of the VRF output. -#[cfg(not(feature = "std"))] -pub const VRF_OUTPUT_LENGTH: usize = 32; +pub use schnorrkel::{SignatureError, PublicKey, vrf::{VRF_PROOF_LENGTH, VRF_OUTPUT_LENGTH}}; /// The length of the Randomness. pub const RANDOMNESS_LENGTH: usize = VRF_OUTPUT_LENGTH; -/// Raw VRF output. -#[derive(Clone, Copy, Eq, PartialEq, RuntimeDebug, Encode, Decode)] -pub struct RawVRFOutput(pub [u8; VRF_OUTPUT_LENGTH]); - -impl Deref for RawVRFOutput { - type Target = [u8; VRF_OUTPUT_LENGTH]; - fn deref(&self) -> &Self::Target { &self.0 } -} - -impl DerefMut for RawVRFOutput { - fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } -} - /// VRF output type available for `std` environment, suitable for schnorrkel operations. -#[cfg(feature = "std")] #[derive(Clone, Debug, PartialEq, Eq)] pub struct VRFOutput(pub schnorrkel::vrf::VRFOutput); -#[cfg(feature = "std")] impl Deref for VRFOutput { type Target = schnorrkel::vrf::VRFOutput; fn deref(&self) -> &Self::Target { &self.0 } } -#[cfg(feature = "std")] impl DerefMut for VRFOutput { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } -#[cfg(feature = "std")] impl Encode for VRFOutput { fn encode(&self) -> Vec { self.0.as_bytes().encode() } } -#[cfg(feature = "std")] impl EncodeLike for VRFOutput { } -#[cfg(feature = "std")] impl Decode for VRFOutput { fn decode(i: &mut R) -> Result { let decoded = <[u8; VRF_OUTPUT_LENGTH]>::decode(i)?; @@ -89,7 +56,6 @@ impl Decode for VRFOutput { } } -#[cfg(feature = "std")] impl TryFrom<[u8; VRF_OUTPUT_LENGTH]> for VRFOutput { type Error = SignatureError; @@ -98,91 +64,39 @@ impl TryFrom<[u8; VRF_OUTPUT_LENGTH]> for VRFOutput { } } -#[cfg(feature = "std")] -impl TryFrom for VRFOutput { - type Error = SignatureError; - - fn try_from(raw: RawVRFOutput) -> Result { - schnorrkel::vrf::VRFOutput::from_bytes(&raw.0).map(VRFOutput) - } -} - -#[cfg(feature = "std")] -impl From for RawVRFOutput { - fn from(output: VRFOutput) -> RawVRFOutput { - RawVRFOutput(output.to_bytes()) - } -} - -/// Raw VRF proof. -#[derive(Clone, Copy, Encode, Decode)] -pub struct RawVRFProof(pub [u8; VRF_PROOF_LENGTH]); - -impl Deref for RawVRFProof { - type Target = [u8; VRF_PROOF_LENGTH]; - fn deref(&self) -> &Self::Target { &self.0 } -} - -impl DerefMut for RawVRFProof { - fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } -} - -#[cfg(feature = "std")] -impl std::fmt::Debug for RawVRFProof { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", &self) - } -} - -impl core::cmp::PartialEq for RawVRFProof { - fn eq(&self, other: &Self) -> bool { - self == other - } -} - -impl core::cmp::Eq for RawVRFProof { } - /// VRF proof type available for `std` environment, suitable for schnorrkel operations. -#[cfg(feature = "std")] #[derive(Clone, Debug, PartialEq, Eq)] pub struct VRFProof(pub schnorrkel::vrf::VRFProof); -#[cfg(feature = "std")] impl PartialOrd for VRFProof { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -#[cfg(feature = "std")] impl Ord for VRFProof { fn cmp(&self, other: &Self) -> core::cmp::Ordering { U512::from(self.0.to_bytes()).cmp(&U512::from(other.0.to_bytes())) } } -#[cfg(feature = "std")] impl Deref for VRFProof { type Target = schnorrkel::vrf::VRFProof; fn deref(&self) -> &Self::Target { &self.0 } } -#[cfg(feature = "std")] impl DerefMut for VRFProof { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } -#[cfg(feature = "std")] impl Encode for VRFProof { fn encode(&self) -> Vec { self.0.to_bytes().encode() } } -#[cfg(feature = "std")] impl EncodeLike for VRFProof { } -#[cfg(feature = "std")] impl Decode for VRFProof { fn decode(i: &mut R) -> Result { let decoded = <[u8; VRF_PROOF_LENGTH]>::decode(i)?; @@ -190,7 +104,6 @@ impl Decode for VRFProof { } } -#[cfg(feature = "std")] impl TryFrom<[u8; VRF_PROOF_LENGTH]> for VRFProof { type Error = SignatureError; @@ -199,23 +112,6 @@ impl TryFrom<[u8; VRF_PROOF_LENGTH]> for VRFProof { } } -#[cfg(feature = "std")] -impl TryFrom for VRFProof { - type Error = SignatureError; - - fn try_from(raw: RawVRFProof) -> Result { - schnorrkel::vrf::VRFProof::from_bytes(&raw.0).map(VRFProof) - } -} - -#[cfg(feature = "std")] -impl From for RawVRFProof { - fn from(output: VRFProof) -> RawVRFProof { - RawVRFProof(output.to_bytes()) - } -} - -#[cfg(feature = "std")] fn convert_error(e: SignatureError) -> codec::Error { use SignatureError::*; use MultiSignatureStage::*; diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 7708188ea4bf230e40a06814e5ac0773773da173..9b9a8b270e0b2033bd97cfd2744e6956881f44da 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -1,17 +1,21 @@ [package] name = "sp-core" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Shareable Substrate types." documentation = "https://docs.rs/sp-core" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../std" } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } +derive_more = "0.99.2" +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../std" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } log = { version = "0.4.8", default-features = false } serde = { version = "1.0.101", optional = true, features = ["derive"] } byteorder = { version = "1.3.2", default-features = false } @@ -21,18 +25,19 @@ wasmi = { version = "0.6.2", optional = true } hash-db = { version = "0.15.2", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } base58 = { version = "0.1.0", optional = true } -rand = { version = "0.7.2", optional = true } +rand = { version = "0.7.3", optional = true, features = ["small_rng"] } substrate-bip39 = { version = "0.4.1", optional = true } tiny-bip39 = { version = "0.7", optional = true } regex = { version = "1.3.1", optional = true } num-traits = { version = "0.2.8", default-features = false } zeroize = { version = "1.0.0", default-features = false } +secrecy = { version = "0.6.0", default-features = false } lazy_static = { version = "1.4.0", default-features = false, optional = true } parking_lot = { version = "0.10.0", optional = true } -sp-debug-derive = { version = "2.0.0-alpha.5", path = "../debug-derive" } -sp-externalities = { version = "0.8.0-alpha.5", optional = true, path = "../externalities" } -sp-storage = { version = "2.0.0-alpha.5", default-features = false, path = "../storage" } -parity-util-mem = { version = "0.6.0", default-features = false, features = ["primitive-types"] } +sp-debug-derive = { version = "2.0.0-rc4", path = "../debug-derive" } +sp-externalities = { version = "0.8.0-rc4", optional = true, path = "../externalities" } +sp-storage = { version = "2.0.0-rc4", default-features = false, path = "../storage" } +parity-util-mem = { version = "0.7.0", default-features = false, features = ["primitive-types"] } futures = { version = "0.3.1", optional = true } # full crypto @@ -44,16 +49,18 @@ sha2 = { version = "0.8.0", default-features = false, optional = true } hex = { version = "0.4", default-features = false, optional = true } twox-hash = { version = "1.5.0", default-features = false, optional = true } libsecp256k1 = { version = "0.3.2", default-features = false, features = ["hmac"], optional = true } +merlin = { version = "2.0", default-features = false, optional = true } -sp-runtime-interface = { version = "2.0.0-alpha.5", default-features = false, path = "../runtime-interface" } +sp-runtime-interface = { version = "2.0.0-rc4", default-features = false, path = "../runtime-interface" } [dev-dependencies] -sp-serializer = { version = "2.0.0-alpha.5", path = "../serializer" } +sp-serializer = { version = "2.0.0-rc4", path = "../serializer" } pretty_assertions = "0.6.1" hex-literal = "0.2.1" rand = "0.7.2" criterion = "0.2.11" serde_json = "1.0" +rand_chacha = "0.2.2" [[bench]] name = "bench" @@ -94,15 +101,16 @@ std = [ "schnorrkel/std", "regex", "num-traits/std", - "libsecp256k1/std", "tiny-keccak", "sp-debug-derive/std", "sp-externalities", "sp-storage/std", "sp-runtime-interface/std", "zeroize/alloc", + "secrecy/alloc", "futures", "futures/thread-pool", + "libsecp256k1/std", ] # This feature enables all crypto primitives for `no_std` builds like microcontrollers @@ -118,7 +126,5 @@ full_crypto = [ "twox-hash", "libsecp256k1", "sp-runtime-interface/disable_target_static_assertions", + "merlin", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/core/benches/bench.rs b/primitives/core/benches/bench.rs index 7db9d72e6b5b0d6afa04c28f07c91c6491a4c541..335920c4d204c52b2f4ca1d9ddd946bdcbfde11e 100644 --- a/primitives/core/benches/bench.rs +++ b/primitives/core/benches/bench.rs @@ -13,6 +13,7 @@ // limitations under the License. + #[macro_use] extern crate criterion; diff --git a/primitives/core/src/changes_trie.rs b/primitives/core/src/changes_trie.rs index cb21ffe13df969141cb056056694914e4006ca9e..1d88242e43d69729d2c3e37697f63fc81d75f364 100644 --- a/primitives/core/src/changes_trie.rs +++ b/primitives/core/src/changes_trie.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Substrate changes trie configuration. diff --git a/primitives/core/src/crypto.rs b/primitives/core/src/crypto.rs index da78e8e47f98f22cc46953b6981f809d03c84c84..74e448687490a44b0daea4ca196fa28fdda1e280 100644 --- a/primitives/core/src/crypto.rs +++ b/primitives/core/src/crypto.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // tag::description[] //! Cryptographic utilities. @@ -36,10 +37,16 @@ use regex::Regex; use base58::{FromBase58, ToBase58}; #[cfg(feature = "std")] use crate::hexdisplay::HexDisplay; -use zeroize::Zeroize; #[doc(hidden)] pub use sp_std::ops::Deref; use sp_runtime_interface::pass_by::PassByInner; +/// Trait to zeroize a memory buffer. +pub use zeroize::Zeroize; +/// Trait for accessing reference to `SecretString`. +pub use secrecy::ExposeSecret; +/// A store for sensitive data. +#[cfg(feature = "std")] +pub use secrecy::SecretString; /// The root phrase for our publicly known keys. pub const DEV_PHRASE: &str = "bottom drive obey lake curtain smoke basket hold race lonely fit walk"; @@ -78,51 +85,6 @@ impl> UncheckedInto for S { } } -/// A store for sensitive data. -/// -/// Calls `Zeroize::zeroize` upon `Drop`. -#[derive(Clone)] -pub struct Protected(T); - -impl AsRef for Protected { - fn as_ref(&self) -> &T { - &self.0 - } -} - -impl sp_std::ops::Deref for Protected { - type Target = T; - - fn deref(&self) -> &T { - &self.0 - } -} - -#[cfg(feature = "std")] -impl std::fmt::Debug for Protected { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(fmt, "") - } -} - -impl From for Protected { - fn from(t: T) -> Self { - Protected(t) - } -} - -impl Zeroize for Protected { - fn zeroize(&mut self) { - self.0.zeroize() - } -} - -impl Drop for Protected { - fn drop(&mut self) { - self.zeroize() - } -} - /// An error with the interpretation of a secret. #[derive(Debug, Clone, PartialEq, Eq)] #[cfg(feature = "full_crypto")] @@ -359,12 +321,20 @@ macro_rules! ss58_address_format { ( $( $identifier:tt => ($number:expr, $name:expr, $desc:tt) )* ) => ( /// A known address (sub)format/network ID for SS58. #[derive(Copy, Clone, PartialEq, Eq)] + #[cfg_attr(feature = "std", derive(Debug))] pub enum Ss58AddressFormat { $(#[doc = $desc] $identifier),*, /// Use a manually provided numeric value. Custom(u8), } + #[cfg(feature = "std")] + impl std::fmt::Display for Ss58AddressFormat { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{:?}", self) + } + } + static ALL_SS58_ADDRESS_FORMATS: [Ss58AddressFormat; 0 $(+ { let _ = $number; 1})*] = [ $(Ss58AddressFormat::$identifier),*, ]; @@ -458,20 +428,28 @@ ss58_address_format!( (10, "acala", "Acala mainnet, standard account (*25519).") LaminarAccount => (11, "laminar", "Laminar mainnet, standard account (*25519).") + PolymathAccount => + (12, "polymath", "Polymath network, standard account (*25519).") + SubstraTeeAccount => + (13, "substratee", "Any SubstraTEE off-chain network private account (*25519).") KulupuAccount => (16, "kulupu", "Kulupu mainnet, standard account (*25519).") DarwiniaAccount => (18, "darwinia", "Darwinia Chain mainnet, standard account (*25519).") + StafiAccount => + (20, "stafi", "Stafi mainnet, standard account (*25519).") RobonomicsAccount => (32, "robonomics", "Any Robonomics network standard account (*25519).") + DataHighwayAccount => + (33, "datahighway", "DataHighway mainnet, standard account (*25519).") CentrifugeAccount => (36, "centrifuge", "Centrifuge Chain mainnet, standard account (*25519).") SubstrateAccount => (42, "substrate", "Any Substrate network, standard account (*25519).") Reserved43 => (43, "reserved43", "Reserved for future use (43).") - SubstraTeeAccount => - (44, "substratee", "Any SubstraTEE off-chain network private account (*25519).") + ChainXAccount => + (44, "chainx", "ChainX mainnet, standard account (*25519).") Reserved46 => (46, "reserved46", "Reserved for future use (46).") Reserved47 => @@ -560,6 +538,8 @@ pub trait Public: /// Return a slice filled with raw data. fn as_slice(&self) -> &[u8] { self.as_ref() } + /// Return `CryptoTypePublicPair` from public key. + fn to_public_crypto_pair(&self) -> CryptoTypePublicPair; } /// An opaque 32-byte cryptographic identifier. @@ -672,6 +652,23 @@ impl<'de> serde::Deserialize<'de> for AccountId32 { } } +#[cfg(feature = "std")] +impl sp_std::str::FromStr for AccountId32 { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + let hex_or_ss58_without_prefix = s.trim_start_matches("0x"); + if hex_or_ss58_without_prefix.len() == 64 { + let mut bytes = [0u8; 32]; + hex::decode_to_slice(hex_or_ss58_without_prefix, &mut bytes) + .map_err(|_| "invalid hex address.") + .map(|_| Self::from(bytes)) + } else { + Self::from_ss58check(s).map_err(|_| "invalid ss58 address.") + } + } +} + #[cfg(feature = "std")] pub use self::dummy::*; @@ -707,6 +704,11 @@ mod dummy { #[cfg(feature = "std")] fn to_raw_vec(&self) -> Vec { vec![] } fn as_slice(&self) -> &[u8] { b"" } + fn to_public_crypto_pair(&self) -> CryptoTypePublicPair { + CryptoTypePublicPair( + CryptoTypeId(*b"dumm"), Public::to_raw_vec(self) + ) + } } impl Pair for Dummy { @@ -874,7 +876,7 @@ pub trait Pair: CryptoType + Sized + Clone + Send + Sync + 'static { /// 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. + /// See [`from_string_with_seed`](Pair::from_string_with_seed) for more extensive documentation. #[cfg(feature = "std")] fn from_string(s: &str, password_override: Option<&str>) -> Result { Self::from_string_with_seed(s, password_override).map(|x| x.0) @@ -993,20 +995,22 @@ impl sp_std::fmt::Display for CryptoTypePublicPair { pub mod key_types { use super::KeyTypeId; - /// Key type for Babe module, build-in. + /// Key type for Babe module, built-in. Identified as `babe`. pub const BABE: KeyTypeId = KeyTypeId(*b"babe"); - /// Key type for Grandpa module, build-in. + /// Key type for Grandpa module, built-in. Identified as `gran`. pub const GRANDPA: KeyTypeId = KeyTypeId(*b"gran"); - /// Key type for controlling an account in a Substrate runtime, built-in. + /// Key type for controlling an account in a Substrate runtime, built-in. Identified as `acco`. pub const ACCOUNT: KeyTypeId = KeyTypeId(*b"acco"); - /// Key type for Aura module, built-in. + /// Key type for Aura module, built-in. Identified as `aura`. pub const AURA: KeyTypeId = KeyTypeId(*b"aura"); - /// Key type for ImOnline module, built-in. + /// Key type for ImOnline module, built-in. Identified as `imon`. pub const IM_ONLINE: KeyTypeId = KeyTypeId(*b"imon"); - /// Key type for AuthorityDiscovery module, built-in. + /// Key type for AuthorityDiscovery module, built-in. Identified as `audi`. pub const AUTHORITY_DISCOVERY: KeyTypeId = KeyTypeId(*b"audi"); - /// Key type for staking, built-in. + /// Key type for staking, built-in. Identified as `stak`. pub const STAKING: KeyTypeId = KeyTypeId(*b"stak"); + /// Key type for equivocation reporting, built-in. Identified as `fish`. + pub const REPORTING: KeyTypeId = KeyTypeId(*b"fish"); /// A key type ID useful for tests. pub const DUMMY: KeyTypeId = KeyTypeId(*b"dumy"); } @@ -1060,6 +1064,11 @@ mod tests { fn to_raw_vec(&self) -> Vec { vec![] } + fn to_public_crypto_pair(&self) -> CryptoTypePublicPair { + CryptoTypePublicPair( + CryptoTypeId(*b"dumm"), self.to_raw_vec(), + ) + } } impl Pair for TestPair { type Public = TestPublic; @@ -1172,4 +1181,31 @@ mod tests { Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: Some("password".to_owned()), path: vec![DeriveJunction::soft(1), DeriveJunction::hard("DOT")]}) ); } + + #[test] + fn accountid_32_from_str_works() { + use std::str::FromStr; + assert!(AccountId32::from_str("5G9VdMwXvzza9pS8qE8ZHJk3CheHW9uucBn9ngW4C1gmmzpv").is_ok()); + assert!(AccountId32::from_str("5c55177d67b064bb5d189a3e1ddad9bc6646e02e64d6e308f5acbb1533ac430d").is_ok()); + assert!(AccountId32::from_str("0x5c55177d67b064bb5d189a3e1ddad9bc6646e02e64d6e308f5acbb1533ac430d").is_ok()); + + assert_eq!( + AccountId32::from_str("99G9VdMwXvzza9pS8qE8ZHJk3CheHW9uucBn9ngW4C1gmmzpv").unwrap_err(), + "invalid ss58 address.", + ); + assert_eq!( + AccountId32::from_str("gc55177d67b064bb5d189a3e1ddad9bc6646e02e64d6e308f5acbb1533ac430d").unwrap_err(), + "invalid hex address.", + ); + assert_eq!( + AccountId32::from_str("0xgc55177d67b064bb5d189a3e1ddad9bc6646e02e64d6e308f5acbb1533ac430d").unwrap_err(), + "invalid hex address.", + ); + + // valid hex but invalid length will be treated as ss58. + assert_eq!( + AccountId32::from_str("55c55177d67b064bb5d189a3e1ddad9bc6646e02e64d6e308f5acbb1533ac430d").unwrap_err(), + "invalid ss58 address.", + ); + } } diff --git a/primitives/core/src/ecdsa.rs b/primitives/core/src/ecdsa.rs index 2364272161df6bfd3560740c7bd1af5c5f15396f..10ded01ab44021e6a698553d0fc2e384e0ae67d8 100644 --- a/primitives/core/src/ecdsa.rs +++ b/primitives/core/src/ecdsa.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // tag::description[] //! Simple ECDSA API. @@ -36,7 +37,8 @@ use crate::{hashing::blake2_256, crypto::{Pair as TraitPair, DeriveJunction, Sec use crate::crypto::Ss58Codec; #[cfg(feature = "std")] use serde::{de, Serializer, Serialize, Deserializer, Deserialize}; -use crate::crypto::{Public as TraitPublic, UncheckedFrom, CryptoType, Derive, CryptoTypeId}; +use crate::crypto::{Public as TraitPublic, CryptoTypePublicPair, UncheckedFrom, CryptoType, Derive, CryptoTypeId}; +use sp_runtime_interface::pass_by::PassByInner; #[cfg(feature = "full_crypto")] use secp256k1::{PublicKey, SecretKey}; @@ -50,7 +52,7 @@ pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"ecds"); type Seed = [u8; 32]; /// The ECDSA compressed public key. -#[derive(Clone, Encode, Decode)] +#[derive(Clone, Encode, Decode, PassByInner)] pub struct Public([u8; 33]); impl PartialOrd for Public { @@ -118,6 +120,22 @@ impl TraitPublic for Public { r.copy_from_slice(data); Self(r) } + + fn to_public_crypto_pair(&self) -> CryptoTypePublicPair { + CryptoTypePublicPair(CRYPTO_ID, self.to_raw_vec()) + } +} + +impl From for CryptoTypePublicPair { + fn from(key: Public) -> Self { + (&key).into() + } +} + +impl From<&Public> for CryptoTypePublicPair { + fn from(key: &Public) -> Self { + CryptoTypePublicPair(CRYPTO_ID, key.to_raw_vec()) + } } impl Derive for Public {} @@ -173,12 +191,17 @@ impl std::fmt::Display for Public { } } -#[cfg(feature = "std")] -impl std::fmt::Debug for Public { +impl sp_std::fmt::Debug for Public { + #[cfg(feature = "std")] fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { let s = self.to_ss58check(); write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.as_ref()), &s[0..8]) } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } } #[cfg(feature = "std")] @@ -204,7 +227,7 @@ impl sp_std::hash::Hash for Public { } /// A signature (a 512-bit value, plus 8 bits for recovery ID). -#[derive(Encode, Decode)] +#[derive(Encode, Decode, PassByInner)] pub struct Signature([u8; 65]); impl sp_std::convert::TryFrom<&[u8]> for Signature { @@ -284,11 +307,16 @@ 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 sp_std::fmt::Debug for Signature { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0)) } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } } #[cfg(feature = "full_crypto")] diff --git a/primitives/core/src/ed25519.rs b/primitives/core/src/ed25519.rs index abeac05388d2773e7ba80f60d6b4e9193ebe2fcd..f6e7227013728c86dd9ad5ce9d6febd6ab79b006 100644 --- a/primitives/core/src/ed25519.rs +++ b/primitives/core/src/ed25519.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // tag::description[] //! Simple Ed25519 API. @@ -377,20 +378,24 @@ impl TraitPublic for Public { r.copy_from_slice(data); Public(r) } + + fn to_public_crypto_pair(&self) -> CryptoTypePublicPair { + CryptoTypePublicPair(CRYPTO_ID, self.to_raw_vec()) + } } impl Derive for Public {} impl From for CryptoTypePublicPair { - fn from(key: Public) -> Self { - (&key).into() - } + fn from(key: Public) -> Self { + (&key).into() + } } impl From<&Public> for CryptoTypePublicPair { - fn from(key: &Public) -> Self { - CryptoTypePublicPair(CRYPTO_ID, key.to_raw_vec()) - } + fn from(key: &Public) -> Self { + CryptoTypePublicPair(CRYPTO_ID, key.to_raw_vec()) + } } /// Derive a single hard junction. diff --git a/primitives/core/src/hash.rs b/primitives/core/src/hash.rs index 424fefbe6a47028f773699a0f27a1a78a7f66ae4..20a6788c3207029eacba04c0e8faae79ee1ef3fd 100644 --- a/primitives/core/src/hash.rs +++ b/primitives/core/src/hash.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! A fixed hash type. diff --git a/primitives/core/src/hasher.rs b/primitives/core/src/hasher.rs index 28da432da7142b1a8ada83946088a03eb90d54ee..8ccaa4d90a78d7e697750f18f0b35fbcb8351396 100644 --- a/primitives/core/src/hasher.rs +++ b/primitives/core/src/hasher.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Substrate Blake2b Hasher implementation @@ -35,3 +36,23 @@ pub mod blake2 { } } } + +pub mod keccak { + use hash_db::Hasher; + use hash256_std_hasher::Hash256StdHasher; + use crate::hash::H256; + + /// Concrete implementation of Hasher using Keccak 256-bit hashes + #[derive(Debug)] + pub struct KeccakHasher; + + impl Hasher for KeccakHasher { + type Out = H256; + type StdHasher = Hash256StdHasher; + const LENGTH: usize = 32; + + fn hash(x: &[u8]) -> Self::Out { + crate::hashing::keccak_256(x).into() + } + } +} diff --git a/primitives/core/src/hashing.rs b/primitives/core/src/hashing.rs index 87f6469b573e1a54f4eaa6f700183fa3457ea245..f61700a5a43cdcff29946cfffaa39131187236a9 100644 --- a/primitives/core/src/hashing.rs +++ b/primitives/core/src/hashing.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Hashing functions. @@ -57,6 +58,18 @@ pub fn blake2_128(data: &[u8]) -> [u8; 16] { r } +/// Do a Blake2 64-bit hash and place result in `dest`. +pub fn blake2_64_into(data: &[u8], dest: &mut [u8; 8]) { + dest.copy_from_slice(blake2_rfc::blake2b::blake2b(8, &[], data).as_bytes()); +} + +/// Do a Blake2 64-bit hash and return result. +pub fn blake2_64(data: &[u8]) -> [u8; 8] { + let mut r = [0; 8]; + blake2_64_into(data, &mut r); + r +} + /// Do a XX 64-bit hash and place result in `dest`. pub fn twox_64_into(data: &[u8], dest: &mut [u8; 8]) { use ::core::hash::Hasher; diff --git a/primitives/core/src/hexdisplay.rs b/primitives/core/src/hexdisplay.rs index 14fedc205c49ebd87b2af807975f3c6d7ddf0c72..f4c8fea8f22230fa36b276898205cd9813f3bdeb 100644 --- a/primitives/core/src/hexdisplay.rs +++ b/primitives/core/src/hexdisplay.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Wrapper type for byte collections that outputs hex. diff --git a/primitives/core/src/lib.rs b/primitives/core/src/lib.rs index 8d5ad7daaec83965e26ac78b68219f6e41da80e1..27f59f4fba7f3a2fcf31c006a98b2668b7f9e4d2 100644 --- a/primitives/core/src/lib.rs +++ b/primitives/core/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Shareable Substrate types. @@ -72,6 +73,8 @@ pub mod traits; pub mod testing; #[cfg(feature = "std")] pub mod tasks; +#[cfg(feature = "std")] +pub mod vrf; pub use self::hash::{H160, H256, H512, convert_hash}; pub use self::uint::{U256, U512}; @@ -82,6 +85,8 @@ pub use crypto::{DeriveJunction, Pair, Public}; pub use hash_db::Hasher; #[cfg(feature = "std")] pub use self::hasher::blake2::Blake2Hasher; +#[cfg(feature = "std")] +pub use self::hasher::keccak::KeccakHasher; pub use sp_storage as storage; @@ -90,9 +95,16 @@ pub use sp_std; /// Context for executing a call into the runtime. pub enum ExecutionContext { - /// Context for general importing (including own blocks). + /// Context used for general block import (including locally authored blocks). Importing, - /// Context used when syncing the blockchain. + /// Context used for importing blocks as part of an initial sync of the blockchain. + /// + /// We distinguish between major sync and import so that validators who are running + /// their initial sync (or catching up after some time offline) can use the faster + /// native runtime (since we can reasonably assume the network as a whole has already + /// come to a broad conensus on the block and it probably hasn't been crafted + /// specifically to attack this node), but when importing blocks at the head of the + /// chain in normal operation they can use the safer Wasm version. Syncing, /// Context used for block construction. BlockConstruction, @@ -110,8 +122,11 @@ impl ExecutionContext { match self { Importing | Syncing | BlockConstruction => offchain::Capabilities::none(), - // Enable keystore by default for offchain calls. CC @bkchr - OffchainCall(None) => [offchain::Capability::Keystore][..].into(), + // Enable keystore and transaction pool by default for offchain calls. + OffchainCall(None) => [ + offchain::Capability::Keystore, + offchain::Capability::TransactionPool, + ][..].into(), OffchainCall(Some((_, capabilities))) => *capabilities, } } @@ -318,6 +333,11 @@ pub fn to_substrate_wasm_fn_return_value(value: &impl Encode) -> u64 { res } +/// The void type - it cannot exist. +// Oh rust, you crack me up... +#[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebug)] +pub enum Void {} + /// Macro for creating `Maybe*` marker traits. /// /// Such a maybe-marker trait requires the given bound when `feature = std` and doesn't require diff --git a/primitives/core/src/offchain/mod.rs b/primitives/core/src/offchain/mod.rs index c393b0f9f88821e8c9f58c9e93b3d6544ba4c7e3..b2ff3552135ce935a2e8d3a79c7533baa5afa117 100644 --- a/primitives/core/src/offchain/mod.rs +++ b/primitives/core/src/offchain/mod.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Offchain workers types @@ -28,11 +29,17 @@ pub mod storage; #[cfg(feature = "std")] pub mod testing; +/// Local storage prefix used by the Offchain Worker API to +pub const STORAGE_PREFIX : &'static [u8] = b"storage"; + /// Offchain workers local storage. pub trait OffchainStorage: Clone + Send + Sync { /// Persist a value in storage under given key and prefix. fn set(&mut self, prefix: &[u8], key: &[u8], value: &[u8]); + /// Clear a storage entry under given key and prefix. + fn remove(&mut self, prefix: &[u8], key: &[u8]); + /// Retrieve a value from storage under given key and prefix. fn get(&self, prefix: &[u8], key: &[u8]) -> Option>; @@ -215,7 +222,7 @@ pub struct Duration(u64); impl Duration { /// Create new duration representing given number of milliseconds. - pub fn from_millis(millis: u64) -> Self { + pub const fn from_millis(millis: u64) -> Self { Duration(millis) } @@ -342,9 +349,15 @@ pub trait Externalities: Send { /// Sets a value in the local storage. /// /// Note this storage is not part of the consensus, it's only accessible by - /// offchain worker tasks running on the same machine. It IS persisted between runs. + /// offchain worker tasks running on the same machine. It _is_ persisted between runs. fn local_storage_set(&mut self, kind: StorageKind, key: &[u8], value: &[u8]); + /// Removes a value in the local storage. + /// + /// Note this storage is not part of the consensus, it's only accessible by + /// offchain worker tasks running on the same machine. It _is_ persisted between runs. + fn local_storage_clear(&mut self, kind: StorageKind, key: &[u8]); + /// Sets a value in the local storage if it matches current value. /// /// Since multiple offchain workers may be running concurrently, to prevent @@ -353,7 +366,7 @@ pub trait Externalities: Send { /// Returns `true` if the value has been set, `false` otherwise. /// /// Note this storage is not part of the consensus, it's only accessible by - /// offchain worker tasks running on the same machine. It IS persisted between runs. + /// offchain worker tasks running on the same machine. It _is_ persisted between runs. fn local_storage_compare_and_set( &mut self, kind: StorageKind, @@ -366,7 +379,7 @@ pub trait Externalities: Send { /// /// If the value does not exist in the storage `None` will be returned. /// Note this storage is not part of the consensus, it's only accessible by - /// offchain worker tasks running on the same machine. It IS persisted between runs. + /// offchain worker tasks running on the same machine. It _is_ persisted between runs. fn local_storage_get(&mut self, kind: StorageKind, key: &[u8]) -> Option>; /// Initiates a http request given HTTP verb and the URL. @@ -482,8 +495,8 @@ pub trait Externalities: Send { buffer: &mut [u8], deadline: Option ) -> Result; - } + impl Externalities for Box { fn is_validator(&self) -> bool { (& **self).is_validator() @@ -509,6 +522,10 @@ impl Externalities for Box { (&mut **self).local_storage_set(kind, key, value) } + fn local_storage_clear(&mut self, kind: StorageKind, key: &[u8]) { + (&mut **self).local_storage_clear(kind, key) + } + fn local_storage_compare_and_set( &mut self, kind: StorageKind, @@ -557,6 +574,7 @@ 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, @@ -613,6 +631,11 @@ impl Externalities for LimitedExternalities { self.externalities.local_storage_set(kind, key, value) } + fn local_storage_clear(&mut self, kind: StorageKind, key: &[u8]) { + self.check(Capability::OffchainWorkerDbWrite, "local_storage_clear"); + self.externalities.local_storage_clear(kind, key) + } + fn local_storage_compare_and_set( &mut self, kind: StorageKind, diff --git a/primitives/core/src/offchain/storage.rs b/primitives/core/src/offchain/storage.rs index 31b6423e5d81ce5d7257b3e1505bcb113e87117f..7d7c711ed95f046ccf33e1e3d2e8262c9d2bb06a 100644 --- a/primitives/core/src/offchain/storage.rs +++ b/primitives/core/src/offchain/storage.rs @@ -1,23 +1,25 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! In-memory implementation of offchain workers database. use std::collections::hash_map::{HashMap, Entry}; use crate::offchain::OffchainStorage; +use std::iter::Iterator; /// In-memory storage for offchain workers. #[derive(Debug, Clone, Default)] @@ -25,12 +27,35 @@ pub struct InMemOffchainStorage { storage: HashMap, Vec>, } +impl InMemOffchainStorage { + /// Consume the offchain storage and iterate over all key value pairs. + pub fn into_iter(self) -> impl Iterator,Vec)> { + self.storage.into_iter() + } + + /// Iterate over all key value pairs by reference. + pub fn iter<'a>(&'a self) -> impl Iterator,&'a Vec)> { + self.storage.iter() + } + + /// Remove a key and its associated value from the offchain database. + pub fn remove(&mut self, prefix: &[u8], key: &[u8]) { + let key: Vec = prefix.iter().chain(key).cloned().collect(); + let _ = self.storage.remove(&key); + } +} + impl OffchainStorage for InMemOffchainStorage { fn set(&mut self, prefix: &[u8], key: &[u8], value: &[u8]) { let key = prefix.iter().chain(key).cloned().collect(); self.storage.insert(key, value.to_vec()); } + fn remove(&mut self, prefix: &[u8], key: &[u8]) { + let key: Vec = prefix.iter().chain(key).cloned().collect(); + self.storage.remove(&key); + } + fn get(&self, prefix: &[u8], key: &[u8]) -> Option> { let key: Vec = prefix.iter().chain(key).cloned().collect(); self.storage.get(&key).cloned() @@ -58,3 +83,215 @@ impl OffchainStorage for InMemOffchainStorage { } } } + + + + +/// Change to be applied to the offchain worker db in regards to a key. +#[derive(Debug,Clone,Hash,Eq,PartialEq)] +pub enum OffchainOverlayedChange { + /// Remove the data associated with the key + Remove, + /// Overwrite the value of an associated key + SetValue(Vec), +} + +/// In-memory storage for offchain workers recoding changes for the actual offchain storage implementation. +#[derive(Debug, Clone)] +pub enum OffchainOverlayedChanges { + /// Writing overlay changes to the offchain worker database is disabled by configuration. + Disabled, + /// Overlay changes can be recorded using the inner collection of this variant, + /// where the identifier is the tuple of `(prefix, key)`. + Enabled(HashMap<(Vec, Vec), OffchainOverlayedChange>), +} + +impl Default for OffchainOverlayedChanges { + fn default() -> Self { + Self::Disabled + } +} + +impl OffchainOverlayedChanges { + /// Create the disabled variant. + pub fn disabled() -> Self { + Self::Disabled + } + + /// Create the enabled variant. + pub fn enabled() -> Self { + Self::Enabled(HashMap::new()) + } + + /// Consume the offchain storage and iterate over all key value pairs. + pub fn into_iter(self) -> OffchainOverlayedChangesIntoIter { + OffchainOverlayedChangesIntoIter::new(self) + } + + /// Iterate over all key value pairs by reference. + pub fn iter<'a>(&'a self) -> OffchainOverlayedChangesIter { + OffchainOverlayedChangesIter::new(&self) + } + + /// Drain all elements of changeset. + pub fn drain<'a, 'd>(&'a mut self) -> OffchainOverlayedChangesDrain<'d> where 'a: 'd { + OffchainOverlayedChangesDrain::new(self) + } + + /// Remove a key and its associated value from the offchain database. + pub fn remove(&mut self, prefix: &[u8], key: &[u8]) { + if let Self::Enabled(ref mut storage) = self { + let _ = storage.insert((prefix.to_vec(), key.to_vec()), OffchainOverlayedChange::Remove); + } + } + + /// Set the value associated with a key under a prefix to the value provided. + pub fn set(&mut self, prefix: &[u8], key: &[u8], value: &[u8]) { + if let Self::Enabled(ref mut storage) = self { + let _ = storage.insert((prefix.to_vec(), key.to_vec()), OffchainOverlayedChange::SetValue(value.to_vec())); + } + } + + /// Obtain a associated value to the given key in storage with prefix. + pub fn get(&self, prefix: &[u8], key: &[u8]) -> Option { + if let Self::Enabled(ref storage) = self { + let key = (prefix.to_vec(), key.to_vec()); + storage.get(&key).cloned() + } else { + None + } + } +} + +use std::collections::hash_map; + +/// Iterate by reference over the prepared offchain worker storage changes. +pub struct OffchainOverlayedChangesIter<'i> { + inner: Option, Vec), OffchainOverlayedChange>>, +} + +impl<'i> Iterator for OffchainOverlayedChangesIter<'i> { + type Item = (&'i (Vec, Vec), &'i OffchainOverlayedChange); + fn next(&mut self) -> Option { + if let Some(ref mut iter) = self.inner { + iter.next() + } else { + None + } + } +} + +impl<'i> OffchainOverlayedChangesIter<'i> { + /// Create a new iterator based on a refernce to the parent container. + pub fn new(container: &'i OffchainOverlayedChanges) -> Self { + match container { + OffchainOverlayedChanges::Enabled(inner) => Self { + inner: Some(inner.iter()) + }, + OffchainOverlayedChanges::Disabled => Self { inner: None, }, + } + } +} + + +/// Iterate by value over the prepared offchain worker storage changes. +pub struct OffchainOverlayedChangesIntoIter { + inner: Option,Vec),OffchainOverlayedChange>>, +} + +impl Iterator for OffchainOverlayedChangesIntoIter { + type Item = ((Vec, Vec), OffchainOverlayedChange); + fn next(&mut self) -> Option { + if let Some(ref mut iter) = self.inner { + iter.next() + } else { + None + } + } +} + +impl OffchainOverlayedChangesIntoIter { + /// Create a new iterator by consuming the collection. + pub fn new(container: OffchainOverlayedChanges) -> Self { + match container { + OffchainOverlayedChanges::Enabled(inner) => Self { + inner: Some(inner.into_iter()) + }, + OffchainOverlayedChanges::Disabled => Self { inner: None, }, + } + } +} + +/// Iterate over all items while draining them from the collection. +pub struct OffchainOverlayedChangesDrain<'d> { + inner: Option, Vec), OffchainOverlayedChange>>, +} + +impl<'d> Iterator for OffchainOverlayedChangesDrain<'d> { + type Item = ((Vec, Vec), OffchainOverlayedChange); + fn next(&mut self) -> Option { + if let Some(ref mut iter) = self.inner { + iter.next() + } else { + None + } + } +} + +impl<'d> OffchainOverlayedChangesDrain<'d> { + /// Create a new iterator by taking a mut reference to the collection, + /// for the lifetime of the created drain iterator. + pub fn new(container: &'d mut OffchainOverlayedChanges) -> Self { + match container { + OffchainOverlayedChanges::Enabled(ref mut inner) => Self { + inner: Some(inner.drain()) + }, + OffchainOverlayedChanges::Disabled => Self { inner: None, }, + } + } +} + + +#[cfg(test)] +mod test { + use super::*; + use super::super::STORAGE_PREFIX; + + #[test] + fn test_drain() { + let mut ooc = OffchainOverlayedChanges::enabled(); + ooc.set(STORAGE_PREFIX,b"kkk", b"vvv"); + let drained = ooc.drain().count(); + assert_eq!(drained, 1); + let leftover = ooc.iter().count(); + assert_eq!(leftover, 0); + + ooc.set(STORAGE_PREFIX, b"a", b"v"); + ooc.set(STORAGE_PREFIX, b"b", b"v"); + ooc.set(STORAGE_PREFIX, b"c", b"v"); + ooc.set(STORAGE_PREFIX, b"d", b"v"); + ooc.set(STORAGE_PREFIX, b"e", b"v"); + assert_eq!(ooc.iter().count(), 5); + } + + #[test] + fn test_accumulated_set_remove_set() { + let mut ooc = OffchainOverlayedChanges::enabled(); + ooc.set(STORAGE_PREFIX, b"ppp", b"qqq"); + ooc.remove(STORAGE_PREFIX, b"ppp"); + // keys are equiv, so it will overwrite the value and the overlay will contain + // one item + assert_eq!(ooc.iter().count(), 1); + + ooc.set(STORAGE_PREFIX, b"ppp", b"rrr"); + let mut iter = ooc.into_iter(); + assert_eq!( + iter.next(), + Some( + ((STORAGE_PREFIX.to_vec(), b"ppp".to_vec()), + OffchainOverlayedChange::SetValue(b"rrr".to_vec())) + ) + ); + assert_eq!(iter.next(), None); + } +} diff --git a/primitives/core/src/offchain/testing.rs b/primitives/core/src/offchain/testing.rs index f4faee6b026eb70f069149993b9b197246230da5..9145477722d78b1ffe86c5f55e076ba290b88712 100644 --- a/primitives/core/src/offchain/testing.rs +++ b/primitives/core/src/offchain/testing.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Utilities for offchain calls testing. //! @@ -20,12 +21,12 @@ //! the extra APIs. use std::{ - collections::BTreeMap, + collections::{BTreeMap, VecDeque}, sync::Arc, }; use crate::offchain::{ self, - storage::InMemOffchainStorage, + storage::{InMemOffchainStorage, OffchainOverlayedChange, OffchainOverlayedChanges}, HttpError, HttpRequestId as RequestId, HttpRequestStatus as RequestStatus, @@ -35,6 +36,7 @@ use crate::offchain::{ TransactionPool, OffchainStorage, }; + use parking_lot::RwLock; /// Pending request. @@ -60,6 +62,57 @@ pub struct PendingRequest { pub response_headers: Vec<(String, String)>, } +/// Sharable "persistent" offchain storage for test. +#[derive(Debug, Clone, Default)] +pub struct TestPersistentOffchainDB { + persistent: Arc>, +} + +impl TestPersistentOffchainDB { + /// Create a new and empty offchain storage db for persistent items + pub fn new() -> Self { + Self { + persistent: Arc::new(RwLock::new(InMemOffchainStorage::default())) + } + } + + /// Apply a set of off-chain changes directly to the test backend + pub fn apply_offchain_changes(&mut self, changes: &mut OffchainOverlayedChanges) { + let mut me = self.persistent.write(); + for ((_prefix, key), value_operation) in changes.drain() { + match value_operation { + OffchainOverlayedChange::SetValue(val) => me.set(b"", key.as_slice(), val.as_slice()), + OffchainOverlayedChange::Remove => me.remove(b"", key.as_slice()), + } + } + } +} + +impl OffchainStorage for TestPersistentOffchainDB { + fn set(&mut self, prefix: &[u8], key: &[u8], value: &[u8]) { + self.persistent.write().set(prefix, key, value); + } + + fn remove(&mut self, prefix: &[u8], key: &[u8]) { + self.persistent.write().remove(prefix, key); + } + + fn get(&self, prefix: &[u8], key: &[u8]) -> Option> { + self.persistent.read().get(prefix, key) + } + + fn compare_and_set( + &mut self, + prefix: &[u8], + key: &[u8], + old_value: Option<&[u8]>, + new_value: &[u8], + ) -> bool { + self.persistent.write().compare_and_set(prefix, key, old_value, new_value) + } +} + + /// Internal state of the externalities. /// /// This can be used in tests to respond or assert stuff about interactions. @@ -67,13 +120,16 @@ pub struct PendingRequest { pub struct OffchainState { /// A list of pending requests. pub requests: BTreeMap, - expected_requests: BTreeMap, + // Queue of requests that the test is expected to perform (in order). + expected_requests: VecDeque, /// Persistent local storage - pub persistent_storage: InMemOffchainStorage, + pub persistent_storage: TestPersistentOffchainDB, /// Local storage pub local_storage: InMemOffchainStorage, - /// Current timestamp (unix millis) - pub timestamp: u64, + /// A supposedly random seed. + pub seed: [u8; 32], + /// A timestamp simulating the current time. + pub timestamp: Timestamp, } impl OffchainState { @@ -101,9 +157,9 @@ impl OffchainState { } fn fulfill_expected(&mut self, id: u16) { - if let Some(mut req) = self.expected_requests.remove(&RequestId(id)) { - let response = req.response.take().expect("Response checked while added."); - let headers = std::mem::replace(&mut req.response_headers, vec![]); + if let Some(mut req) = self.expected_requests.pop_back() { + let response = req.response.take().expect("Response checked when added."); + let headers = std::mem::take(&mut req.response_headers); self.fulfill_pending_request(id, req, response, headers); } } @@ -114,11 +170,12 @@ impl OffchainState { /// before running the actual code that utilizes them (for instance before calling into runtime). /// 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) { + /// Requests are expected to be performed in the insertion order. + pub fn expect_request(&mut self, expected: PendingRequest) { if expected.response.is_none() { panic!("Expected request needs to have a response."); } - self.expected_requests.insert(RequestId(id), expected); + self.expected_requests.push_front(expected); } } @@ -142,6 +199,13 @@ impl TestOffchainExt { let state = ext.0.clone(); (ext, state) } + + /// Create new `TestOffchainExt` and a reference to the internal state. + pub fn with_offchain_db(offchain_db: TestPersistentOffchainDB) -> (Self, Arc>) { + let (ext, state) = Self::new(); + ext.0.write().persistent_storage = offchain_db; + (ext, state) + } } impl offchain::Externalities for TestOffchainExt { @@ -157,23 +221,31 @@ impl offchain::Externalities for TestOffchainExt { } fn timestamp(&mut self) -> Timestamp { - Timestamp::from_unix_millis(self.0.read().timestamp) + self.0.read().timestamp } - fn sleep_until(&mut self, _deadline: Timestamp) { - unimplemented!("not needed in tests so far") + fn sleep_until(&mut self, deadline: Timestamp) { + self.0.write().timestamp = deadline; } fn random_seed(&mut self) -> [u8; 32] { - unimplemented!("not needed in tests so far") + self.0.read().seed } fn local_storage_set(&mut self, kind: StorageKind, key: &[u8], value: &[u8]) { let mut state = self.0.write(); match kind { - StorageKind::LOCAL => &mut state.local_storage, - StorageKind::PERSISTENT => &mut state.persistent_storage, - }.set(b"", key, value); + StorageKind::LOCAL => state.local_storage.set(b"", key, value), + StorageKind::PERSISTENT => state.persistent_storage.set(b"", key, value), + }; + } + + fn local_storage_clear(&mut self, kind: StorageKind, key: &[u8]) { + let mut state = self.0.write(); + match kind { + StorageKind::LOCAL => state.local_storage.remove(b"", key), + StorageKind::PERSISTENT => state.persistent_storage.remove(b"", key), + }; } fn local_storage_compare_and_set( @@ -185,17 +257,17 @@ impl offchain::Externalities for TestOffchainExt { ) -> bool { let mut state = self.0.write(); match kind { - StorageKind::LOCAL => &mut state.local_storage, - StorageKind::PERSISTENT => &mut state.persistent_storage, - }.compare_and_set(b"", key, old_value, new_value) + StorageKind::LOCAL => state.local_storage.compare_and_set(b"", key, old_value, new_value), + StorageKind::PERSISTENT => state.persistent_storage.compare_and_set(b"", key, old_value, new_value), + } } fn local_storage_get(&mut self, kind: StorageKind, key: &[u8]) -> Option> { let state = self.0.read(); match kind { - StorageKind::LOCAL => &state.local_storage, - StorageKind::PERSISTENT => &state.persistent_storage, - }.get(b"", key) + StorageKind::LOCAL => state.local_storage.get(b"", key), + StorageKind::PERSISTENT => state.persistent_storage.get(b"", key), + } } fn http_request_start(&mut self, method: &str, uri: &str, meta: &[u8]) -> Result { diff --git a/primitives/core/src/sandbox.rs b/primitives/core/src/sandbox.rs index 73fbcfb572ee355f645dc716f197ef8f29a7292d..4cb5bd41d5826bd3f7d8a581f424d368a11cf070 100644 --- a/primitives/core/src/sandbox.rs +++ b/primitives/core/src/sandbox.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Definition of a sandbox environment. diff --git a/primitives/core/src/sr25519.rs b/primitives/core/src/sr25519.rs index 717952eb01c71b7cb398c5c57efc040704e07d24..9e9aaf53bbf1fda34f81450af3a5617184f78d82 100644 --- a/primitives/core/src/sr25519.rs +++ b/primitives/core/src/sr25519.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // tag::description[] //! Simple sr25519 (Schnorr-Ristretto) API. @@ -391,6 +392,10 @@ impl TraitPublic for Public { r.copy_from_slice(data); Public(r) } + + fn to_public_crypto_pair(&self) -> CryptoTypePublicPair { + CryptoTypePublicPair(CRYPTO_ID, self.to_raw_vec()) + } } impl From for CryptoTypePublicPair { @@ -611,6 +616,45 @@ impl CryptoType for Pair { type Pair = Pair; } +/// Batch verification. +/// +/// `messages`, `signatures` and `pub_keys` should all have equal length. +/// +/// Returns `true` if all signatures are correct, `false` otherwise. +#[cfg(feature = "std")] +pub fn verify_batch( + messages: Vec<&[u8]>, + signatures: Vec<&Signature>, + pub_keys: Vec<&Public>, +) -> bool { + let mut sr_pub_keys = Vec::with_capacity(pub_keys.len()); + for pub_key in pub_keys { + match schnorrkel::PublicKey::from_bytes(pub_key.as_ref()) { + Ok(pk) => sr_pub_keys.push(pk), + Err(_) => return false, + }; + } + + let mut sr_signatures = Vec::with_capacity(signatures.len()); + for signature in signatures { + match schnorrkel::Signature::from_bytes(signature.as_ref()) { + Ok(s) => sr_signatures.push(s), + Err(_) => return false + }; + } + + let mut messages: Vec = messages.into_iter().map( + |msg| signing_context(SIGNING_CTX).bytes(msg) + ).collect(); + + schnorrkel::verify_batch( + &mut messages, + &sr_signatures, + &sr_pub_keys, + true, + ).is_ok() +} + #[cfg(test)] mod compatibility_test { use super::*; diff --git a/primitives/core/src/tasks.rs b/primitives/core/src/tasks.rs index 199a185e5371a0efdd272e824d934d07f994d1e3..731e51d2470c0e10a6470e3b7cc470c7acb3e5b0 100644 --- a/primitives/core/src/tasks.rs +++ b/primitives/core/src/tasks.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Module for low-level asynchronous processing. @@ -53,4 +54,4 @@ impl CloneableSpawn for Executor { /// Create tasks executor. pub fn executor() -> Box { Box::new(Executor::new()) -} \ No newline at end of file +} diff --git a/primitives/core/src/testing.rs b/primitives/core/src/testing.rs index b5e6f4c7aff37427573de40587b9bfe6bf311281..1d88e1fad5513d0cd417892d9ba3dc44d2e3a5b6 100644 --- a/primitives/core/src/testing.rs +++ b/primitives/core/src/testing.rs @@ -1,35 +1,39 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Types that should only be used for testing! -use crate::crypto::{KeyTypeId, CryptoTypePublicPair}; +use crate::crypto::KeyTypeId; #[cfg(feature = "std")] use crate::{ - crypto::{Pair, Public}, - ed25519, sr25519, - traits::BareCryptoStoreError + crypto::{Pair, Public, CryptoTypePublicPair}, + ed25519, sr25519, ecdsa, + traits::Error, + vrf::{VRFTranscriptData, VRFSignature, make_transcript}, }; #[cfg(feature = "std")] use std::collections::HashSet; -use codec::Encode; + /// 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"); +/// Key type for generic Sr 25519 key. +pub const ECDSA: KeyTypeId = KeyTypeId(*b"ecds"); /// A keystore implementation usable in tests. #[cfg(feature = "std")] @@ -62,11 +66,19 @@ impl KeyStore { ) } + fn ecdsa_key_pair(&self, id: KeyTypeId, pub_key: &ecdsa::Public) -> Option { + self.keys.get(&id) + .and_then(|inner| + inner.get(pub_key.as_slice()) + .map(|s| ecdsa::Pair::from_string(s, None).expect("`ecdsa` seed slice is valid")) + ) + } + } #[cfg(feature = "std")] impl crate::traits::BareCryptoStore for KeyStore { - fn keys(&self, id: KeyTypeId) -> Result, BareCryptoStoreError> { + fn keys(&self, id: KeyTypeId) -> Result, Error> { self.keys .get(&id) .map(|map| { @@ -74,6 +86,7 @@ impl crate::traits::BareCryptoStore for KeyStore { .fold(Vec::new(), |mut v, k| { v.push(CryptoTypePublicPair(sr25519::CRYPTO_ID, k.clone())); v.push(CryptoTypePublicPair(ed25519::CRYPTO_ID, k.clone())); + v.push(CryptoTypePublicPair(ecdsa::CRYPTO_ID, k.clone())); v })) }) @@ -95,11 +108,11 @@ impl crate::traits::BareCryptoStore for KeyStore { &mut self, id: KeyTypeId, seed: Option<&str>, - ) -> Result { + ) -> Result { match seed { Some(seed) => { let pair = sr25519::Pair::from_string(seed, None) - .map_err(|_| BareCryptoStoreError::ValidationError("Generates an `sr25519` pair.".to_owned()))?; + .map_err(|_| Error::ValidationError("Generates an `sr25519` pair.".to_owned()))?; self.keys.entry(id).or_default().insert(pair.public().to_raw_vec(), seed.into()); Ok(pair.public()) }, @@ -126,11 +139,11 @@ impl crate::traits::BareCryptoStore for KeyStore { &mut self, id: KeyTypeId, seed: Option<&str>, - ) -> Result { + ) -> Result { match seed { Some(seed) => { let pair = ed25519::Pair::from_string(seed, None) - .map_err(|_| BareCryptoStoreError::ValidationError("Generates an `ed25519` pair.".to_owned()))?; + .map_err(|_| Error::ValidationError("Generates an `ed25519` pair.".to_owned()))?; self.keys.entry(id).or_default().insert(pair.public().to_raw_vec(), seed.into()); Ok(pair.public()) }, @@ -142,6 +155,37 @@ impl crate::traits::BareCryptoStore for KeyStore { } } + fn ecdsa_public_keys(&self, id: KeyTypeId) -> Vec { + self.keys.get(&id) + .map(|keys| + keys.values() + .map(|s| ecdsa::Pair::from_string(s, None).expect("`ecdsa` seed slice is valid")) + .map(|p| p.public()) + .collect() + ) + .unwrap_or_default() + } + + fn ecdsa_generate_new( + &mut self, + id: KeyTypeId, + seed: Option<&str>, + ) -> Result { + match seed { + Some(seed) => { + let pair = ecdsa::Pair::from_string(seed, None) + .map_err(|_| Error::ValidationError("Generates an `ecdsa` pair.".to_owned()))?; + self.keys.entry(id).or_default().insert(pair.public().to_raw_vec(), seed.into()); + Ok(pair.public()) + }, + None => { + let (pair, phrase, _) = ecdsa::Pair::generate_with_phrase(None); + self.keys.entry(id).or_default().insert(pair.public().to_raw_vec(), phrase); + Ok(pair.public()) + } + } + } + fn insert_unknown(&mut self, id: KeyTypeId, suri: &str, public: &[u8]) -> Result<(), ()> { self.keys.entry(id).or_default().insert(public.to_owned(), suri.to_string()); Ok(()) @@ -159,7 +203,7 @@ impl crate::traits::BareCryptoStore for KeyStore { &self, id: KeyTypeId, keys: Vec, - ) -> std::result::Result, BareCryptoStoreError> { + ) -> std::result::Result, Error> { let provided_keys = keys.into_iter().collect::>(); let all_keys = self.keys(id)?.into_iter().collect::>(); @@ -171,23 +215,48 @@ impl crate::traits::BareCryptoStore for KeyStore { id: KeyTypeId, key: &CryptoTypePublicPair, msg: &[u8], - ) -> Result, BareCryptoStoreError> { + ) -> Result, Error> { + use codec::Encode; + match key.0 { ed25519::CRYPTO_ID => { let key_pair: ed25519::Pair = self .ed25519_key_pair(id, &ed25519::Public::from_slice(key.1.as_slice())) - .ok_or(BareCryptoStoreError::PairNotFound("ed25519".to_owned()))?; + .ok_or(Error::PairNotFound("ed25519".to_owned()))?; return Ok(key_pair.sign(msg).encode()); } sr25519::CRYPTO_ID => { let key_pair: sr25519::Pair = self .sr25519_key_pair(id, &sr25519::Public::from_slice(key.1.as_slice())) - .ok_or(BareCryptoStoreError::PairNotFound("sr25519".to_owned()))?; + .ok_or(Error::PairNotFound("sr25519".to_owned()))?; return Ok(key_pair.sign(msg).encode()); } - _ => Err(BareCryptoStoreError::KeyNotSupported(id)) + ecdsa::CRYPTO_ID => { + let key_pair: ecdsa::Pair = self + .ecdsa_key_pair(id, &ecdsa::Public::from_slice(key.1.as_slice())) + .ok_or(Error::PairNotFound("ecdsa".to_owned()))?; + return Ok(key_pair.sign(msg).encode()); + } + _ => Err(Error::KeyNotSupported(id)) } } + + fn sr25519_vrf_sign( + &self, + key_type: KeyTypeId, + public: &sr25519::Public, + transcript_data: VRFTranscriptData, + ) -> Result { + let transcript = make_transcript(transcript_data); + let pair = self.sr25519_key_pair(key_type, public) + .ok_or(Error::PairNotFound("Not found".to_owned()))?; + + let (inout, proof, _) = pair.as_ref().vrf_sign(transcript); + Ok(VRFSignature { + output: inout.to_output(), + proof, + }) + } } /// Macro for exporting functions from wasm in with the expected signature for using it with the @@ -290,11 +359,39 @@ macro_rules! wasm_export_functions { }; } +/// An executor that supports spawning blocking futures in tests. +/// +/// Internally this just wraps a `ThreadPool` with a pool size of `8`. This +/// should ensure that we have enough threads in tests for spawning blocking futures. +#[cfg(feature = "std")] +#[derive(Clone)] +pub struct SpawnBlockingExecutor(futures::executor::ThreadPool); + +#[cfg(feature = "std")] +impl SpawnBlockingExecutor { + /// Create a new instance of `Self`. + pub fn new() -> Self { + let mut builder = futures::executor::ThreadPoolBuilder::new(); + Self(builder.pool_size(8).create().expect("Failed to create thread pool")) + } +} + +#[cfg(feature = "std")] +impl crate::traits::SpawnNamed for SpawnBlockingExecutor { + fn spawn_blocking(&self, _: &'static str, future: futures::future::BoxFuture<'static, ()>) { + self.0.spawn_ok(future); + } + fn spawn(&self, _: &'static str, future: futures::future::BoxFuture<'static, ()>) { + self.0.spawn_ok(future); + } +} + #[cfg(test)] mod tests { use super::*; use crate::sr25519; use crate::testing::{ED25519, SR25519}; + use crate::vrf::VRFTranscriptValue; #[test] fn store_key_and_extract() { @@ -326,4 +423,42 @@ mod tests { assert!(public_keys.contains(&key_pair.public().into())); } + + #[test] + fn vrf_sign() { + let store = KeyStore::new(); + + let secret_uri = "//Alice"; + let key_pair = sr25519::Pair::from_string(secret_uri, None).expect("Generates key pair"); + + let transcript_data = VRFTranscriptData { + label: b"Test", + items: vec![ + ("one", VRFTranscriptValue::U64(1)), + ("two", VRFTranscriptValue::U64(2)), + ("three", VRFTranscriptValue::Bytes("test".as_bytes())), + ] + }; + + let result = store.read().sr25519_vrf_sign( + SR25519, + &key_pair.public(), + transcript_data.clone(), + ); + assert!(result.is_err()); + + store.write().insert_unknown( + SR25519, + secret_uri, + key_pair.public().as_ref(), + ).expect("Inserts unknown key"); + + let result = store.read().sr25519_vrf_sign( + SR25519, + &key_pair.public(), + transcript_data, + ); + + assert!(result.is_ok()); + } } diff --git a/primitives/core/src/traits.rs b/primitives/core/src/traits.rs index 14839fb58562a3ec1bcff7219e6dbfb7e1b47b4d..4481145818f2689ceac2836658fce24f7d9f99d9 100644 --- a/primitives/core/src/traits.rs +++ b/primitives/core/src/traits.rs @@ -1,26 +1,27 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Shareable Substrate traits. use crate::{ crypto::{KeyTypeId, CryptoTypePublicPair}, - ed25519, sr25519, + vrf::{VRFTranscriptData, VRFSignature}, + ed25519, sr25519, ecdsa, }; - use std::{ borrow::Cow, fmt::{Debug, Display}, @@ -31,17 +32,22 @@ use std::{ pub use sp_externalities::{Externalities, ExternalitiesExt}; /// BareCryptoStore error -#[derive(Debug)] -pub enum BareCryptoStoreError { +#[derive(Debug, derive_more::Display)] +pub enum Error { /// Public key type is not supported + #[display(fmt="Key not supported: {:?}", _0)] KeyNotSupported(KeyTypeId), /// Pair not found for public key and KeyTypeId + #[display(fmt="Pair was not found: {}", _0)] PairNotFound(String), /// Validation error + #[display(fmt="Validation error: {}", _0)] ValidationError(String), /// Keystore unavailable + #[display(fmt="Keystore unavailable")] Unavailable, /// Programming errors + #[display(fmt="An unknown keystore error occurred: {}", _0)] Other(String) } @@ -58,7 +64,7 @@ pub trait BareCryptoStore: Send + Sync { &mut self, id: KeyTypeId, seed: Option<&str>, - ) -> Result; + ) -> Result; /// Returns all ed25519 public keys for the given key type. fn ed25519_public_keys(&self, id: KeyTypeId) -> Vec; /// Generate a new ed25519 key pair for the given key type and an optional seed. @@ -70,7 +76,19 @@ pub trait BareCryptoStore: Send + Sync { &mut self, id: KeyTypeId, seed: Option<&str>, - ) -> Result; + ) -> Result; + /// Returns all ecdsa public keys for the given key type. + fn ecdsa_public_keys(&self, id: KeyTypeId) -> Vec; + /// Generate a new ecdsa key pair for the given key type and an optional seed. + /// + /// If the given seed is `Some(_)`, the key pair will only be stored in memory. + /// + /// Returns the public key of the generated key pair. + fn ecdsa_generate_new( + &mut self, + id: KeyTypeId, + seed: Option<&str>, + ) -> Result; /// Insert a new key. This doesn't require any known of the crypto; but a public key must be /// manually provided. @@ -90,11 +108,11 @@ pub trait BareCryptoStore: Send + Sync { &self, id: KeyTypeId, keys: Vec - ) -> Result, BareCryptoStoreError>; + ) -> Result, Error>; /// List all supported keys /// /// Returns a set of public keys the signer supports. - fn keys(&self, id: KeyTypeId) -> Result, BareCryptoStoreError>; + fn keys(&self, id: KeyTypeId) -> Result, Error>; /// Checks if the private keys for the given public key and key type combinations exist. /// @@ -113,20 +131,20 @@ pub trait BareCryptoStore: Send + Sync { id: KeyTypeId, key: &CryptoTypePublicPair, msg: &[u8], - ) -> Result, BareCryptoStoreError>; + ) -> Result, Error>; /// Sign with any key /// /// Given a list of public keys, find the first supported key and /// sign the provided message with that key. /// - /// Returns a tuple of the used key and the signature + /// Returns a tuple of the used key and the SCALE encoded signature. fn sign_with_any( &self, id: KeyTypeId, keys: Vec, msg: &[u8] - ) -> Result<(CryptoTypePublicPair, Vec), BareCryptoStoreError> { + ) -> Result<(CryptoTypePublicPair, Vec), Error> { if keys.len() == 1 { return self.sign_with(id, &keys[0], msg).map(|s| (keys[0].clone(), s)); } else { @@ -136,7 +154,7 @@ pub trait BareCryptoStore: Send + Sync { } } } - Err(BareCryptoStoreError::KeyNotSupported(id)) + Err(Error::KeyNotSupported(id)) } /// Sign with all keys @@ -144,16 +162,37 @@ pub trait BareCryptoStore: Send + Sync { /// Provided a list of public keys, sign a message with /// each key given that the key is supported. /// - /// Returns a list of `Result`s each representing the signature of each key or - /// a BareCryptoStoreError for non-supported keys. + /// Returns a list of `Result`s each representing the SCALE encoded + /// signature of each key or a Error for non-supported keys. fn sign_with_all( &self, id: KeyTypeId, keys: Vec, msg: &[u8], - ) -> Result, BareCryptoStoreError>>, ()>{ + ) -> Result, Error>>, ()>{ Ok(keys.iter().map(|k| self.sign_with(id, k, msg)).collect()) } + + /// Generate VRF signature for given transcript data. + /// + /// Receives KeyTypeId and Public key to be able to map + /// them to a private key that exists in the keystore which + /// is, in turn, used for signing the provided transcript. + /// + /// Returns a result containing the signature data. + /// Namely, VRFOutput and VRFProof which are returned + /// inside the `VRFSignature` container struct. + /// + /// This function will return an error in the cases where + /// the public key and key type provided do not match a private + /// key in the keystore. Or, in the context of remote signing + /// an error could be a network one. + fn sr25519_vrf_sign( + &self, + key_type: KeyTypeId, + public: &sr25519::Public, + transcript_data: VRFTranscriptData, + ) -> Result; } /// A pointer to the key store. @@ -262,6 +301,23 @@ impl std::fmt::Display for CodeNotFound { } } +/// `Allow` or `Disallow` missing host functions when instantiating a WASM blob. +#[derive(Clone, Copy, Debug)] +pub enum MissingHostFunctions { + /// Any missing host function will be replaced by a stub that returns an error when + /// being called. + Allow, + /// Any missing host function will result in an error while instantiating the WASM blob, + Disallow, +} + +impl MissingHostFunctions { + /// Are missing host functions allowed? + pub fn allowed(self) -> bool { + matches!(self, Self::Allow) + } +} + /// Something that can call a method in a WASM blob. pub trait CallInWasm: Send + Sync { /// Call the given `method` in the given `wasm_blob` using `call_data` (SCALE encoded arguments) @@ -280,6 +336,7 @@ pub trait CallInWasm: Send + Sync { method: &str, call_data: &[u8], ext: &mut dyn Externalities, + missing_host_functions: MissingHostFunctions, ) -> Result, String>; } @@ -312,3 +369,15 @@ impl TaskExecutorExt { Self(spawn_handle) } } + +/// Something that can spawn futures (blocking and non-blocking) with am assigned name. +pub trait SpawnNamed { + /// Spawn the given blocking future. + /// + /// The given `name` is used to identify the future in tracing. + fn spawn_blocking(&self, name: &'static str, future: futures::future::BoxFuture<'static, ()>); + /// Spawn the given non-blocking future. + /// + /// The given `name` is used to identify the future in tracing. + fn spawn(&self, name: &'static str, future: futures::future::BoxFuture<'static, ()>); +} diff --git a/primitives/core/src/u32_trait.rs b/primitives/core/src/u32_trait.rs index 975b4aa90990e7ea4c80cd31e5b4a438fdd2d628..6f73e1f6ba7190e9274dfb6958002917faab92d3 100644 --- a/primitives/core/src/u32_trait.rs +++ b/primitives/core/src/u32_trait.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! An u32 trait with "values" as impl'd types. diff --git a/primitives/core/src/uint.rs b/primitives/core/src/uint.rs index e666137c08161d897707def5fadde55a9d2f1abe..ef1adc4a0e0ee7fa2ac30d0f3f5a3bc70ece1c82 100644 --- a/primitives/core/src/uint.rs +++ b/primitives/core/src/uint.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! An unsigned fixed-size integer. diff --git a/primitives/core/src/vrf.rs b/primitives/core/src/vrf.rs new file mode 100644 index 0000000000000000000000000000000000000000..d392587cb72e7acaec7139e81a6ca531bc2b3b67 --- /dev/null +++ b/primitives/core/src/vrf.rs @@ -0,0 +1,99 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! VRF-specifc data types and helpers + +use codec::Encode; +use merlin::Transcript; +use schnorrkel::vrf::{VRFOutput, VRFProof}; +/// An enum whose variants represent possible +/// accepted values to construct the VRF transcript +#[derive(Clone, Encode)] +pub enum VRFTranscriptValue<'a> { + /// Value is an array of bytes + Bytes(&'a [u8]), + /// Value is a u64 integer + U64(u64), +} +/// VRF Transcript data +#[derive(Clone, Encode)] +pub struct VRFTranscriptData<'a> { + /// The transcript's label + pub label: &'static [u8], + /// Additional data to be registered into the transcript + pub items: Vec<(&'static str, VRFTranscriptValue<'a>)>, +} +/// VRF signature data +pub struct VRFSignature { + /// The VRFOutput serialized + pub output: VRFOutput, + /// The calculated VRFProof + pub proof: VRFProof, +} + +/// Construct a `Transcript` object from data. +/// +/// Returns `merlin::Transcript` +pub fn make_transcript(data: VRFTranscriptData) -> Transcript { + let mut transcript = Transcript::new(data.label); + for (label, value) in data.items.into_iter() { + match value { + VRFTranscriptValue::Bytes(bytes) => { + transcript.append_message(label.as_bytes(), &bytes); + }, + VRFTranscriptValue::U64(val) => { + transcript.append_u64(label.as_bytes(), val); + } + } + } + transcript +} + + +#[cfg(test)] +mod tests { + use super::*; + use crate::vrf::VRFTranscriptValue; + use rand::RngCore; + use rand_chacha::{ + rand_core::SeedableRng, + ChaChaRng, + }; + + #[test] + fn transcript_creation_matches() { + let mut orig_transcript = Transcript::new(b"My label"); + orig_transcript.append_u64(b"one", 1); + orig_transcript.append_message(b"two", "test".as_bytes()); + + let new_transcript = make_transcript(VRFTranscriptData { + label: b"My label", + items: vec![ + ("one", VRFTranscriptValue::U64(1)), + ("two", VRFTranscriptValue::Bytes("test".as_bytes())), + ], + }); + let test = |t: Transcript| -> [u8; 16] { + let mut b = [0u8; 16]; + t.build_rng() + .finalize(&mut ChaChaRng::from_seed([0u8;32])) + .fill_bytes(&mut b); + b + }; + debug_assert!(test(orig_transcript) == test(new_transcript)); + } +} diff --git a/primitives/database/Cargo.toml b/primitives/database/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..6d35e69125f8e6cea4f818794e66312288bd721f --- /dev/null +++ b/primitives/database/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "sp-database" +version = "2.0.0-rc4" +authors = ["Parity Technologies "] +edition = "2018" +license = "Apache-2.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +description = "Substrate database trait." +documentation = "https://docs.rs/sp-database" + +[dependencies] +parking_lot = "0.10.0" +kvdb = "0.7.0" diff --git a/primitives/database/src/error.rs b/primitives/database/src/error.rs new file mode 100644 index 0000000000000000000000000000000000000000..2e5d4557a9791bd71512d7f8ef3e0203011c6705 --- /dev/null +++ b/primitives/database/src/error.rs @@ -0,0 +1,35 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/// The error type for database operations. +#[derive(Debug)] +pub struct DatabaseError(pub Box); + +impl std::fmt::Display for DatabaseError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +impl std::error::Error for DatabaseError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + None + } +} + +/// A specialized `Result` type for database operations. +pub type Result = std::result::Result; diff --git a/primitives/database/src/kvdb.rs b/primitives/database/src/kvdb.rs new file mode 100644 index 0000000000000000000000000000000000000000..f436979aaf4c14cf093fcf6a854ec06172331b8b --- /dev/null +++ b/primitives/database/src/kvdb.rs @@ -0,0 +1,60 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/// A wrapper around `kvdb::Database` that implements `sp_database::Database` trait + +use ::kvdb::{DBTransaction, KeyValueDB}; + +use crate::{Database, Change, ColumnId, Transaction, error}; + +struct DbAdapter(D); + +fn handle_err(result: std::io::Result) -> T { + match result { + Ok(r) => r, + Err(e) => { + panic!("Critical database eror: {:?}", e); + } + } +} + +/// Wrap RocksDb database into a trait object that implements `sp_database::Database` +pub fn as_database(db: D) -> std::sync::Arc> { + std::sync::Arc::new(DbAdapter(db)) +} + +impl Database for DbAdapter { + fn commit(&self, transaction: Transaction) -> error::Result<()> { + let mut tx = DBTransaction::new(); + for change in transaction.0.into_iter() { + match change { + Change::Set(col, key, value) => tx.put_vec(col, &key, value), + Change::Remove(col, key) => tx.delete(col, &key), + _ => unimplemented!(), + } + } + self.0.write(tx).map_err(|e| error::DatabaseError(Box::new(e))) + } + + fn get(&self, col: ColumnId, key: &[u8]) -> Option> { + handle_err(self.0.get(col, key)) + } + + fn lookup(&self, _hash: &H) -> Option> { + unimplemented!(); + } +} diff --git a/primitives/database/src/lib.rs b/primitives/database/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..1908eb49bb6c68cdbff1f39adc274d51452e2a0a --- /dev/null +++ b/primitives/database/src/lib.rs @@ -0,0 +1,197 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! The main database trait, allowing Substrate to store data persistently. + +pub mod error; +mod mem; +mod kvdb; + +pub use mem::MemDb; +pub use crate::kvdb::as_database; + +/// An identifier for a column. +pub type ColumnId = u32; + +/// An alteration to the database. +#[derive(Clone)] +pub enum Change { + Set(ColumnId, Vec, Vec), + Remove(ColumnId, Vec), + Store(H, Vec), + Release(H), +} + +/// An alteration to the database that references the data. +pub enum ChangeRef<'a, H> { + Set(ColumnId, &'a [u8], &'a [u8]), + Remove(ColumnId, &'a [u8]), + Store(H, &'a [u8]), + Release(H), +} + +/// A series of changes to the database that can be committed atomically. They do not take effect +/// until passed into `Database::commit`. +#[derive(Default, Clone)] +pub struct Transaction(pub Vec>); + +impl Transaction { + /// Create a new transaction to be prepared and committed atomically. + pub fn new() -> Self { + Transaction(Vec::new()) + } + /// Set the value of `key` in `col` to `value`, replacing anything that is there currently. + pub fn set(&mut self, col: ColumnId, key: &[u8], value: &[u8]) { + self.0.push(Change::Set(col, key.to_vec(), value.to_vec())) + } + /// Set the value of `key` in `col` to `value`, replacing anything that is there currently. + pub fn set_from_vec(&mut self, col: ColumnId, key: &[u8], value: Vec) { + self.0.push(Change::Set(col, key.to_vec(), value)) + } + /// Remove the value of `key` in `col`. + pub fn remove(&mut self, col: ColumnId, key: &[u8]) { + self.0.push(Change::Remove(col, key.to_vec())) + } + /// Store the `preimage` of `hash` into the database, so that it may be looked up later with + /// `Database::lookup`. This may be called multiple times, but `Database::lookup` but subsequent + /// calls will ignore `preimage` and simply increase the number of references on `hash`. + pub fn store(&mut self, hash: H, preimage: &[u8]) { + self.0.push(Change::Store(hash, preimage.to_vec())) + } + /// Release the preimage of `hash` from the database. An equal number of these to the number of + /// corresponding `store`s must have been given before it is legal for `Database::lookup` to + /// be unable to provide the preimage. + pub fn release(&mut self, hash: H) { + self.0.push(Change::Release(hash)) + } +} + +pub trait Database: Send + Sync { + /// Commit the `transaction` to the database atomically. Any further calls to `get` or `lookup` + /// will reflect the new state. + fn commit(&self, transaction: Transaction) -> error::Result<()> { + for change in transaction.0.into_iter() { + match change { + Change::Set(col, key, value) => self.set(col, &key, &value), + Change::Remove(col, key) => self.remove(col, &key), + Change::Store(hash, preimage) => self.store(&hash, &preimage), + Change::Release(hash) => self.release(&hash), + }?; + } + + Ok(()) + } + + /// Commit the `transaction` to the database atomically. Any further calls to `get` or `lookup` + /// will reflect the new state. + fn commit_ref<'a>(&self, transaction: &mut dyn Iterator>) -> error::Result<()> { + let mut tx = Transaction::new(); + for change in transaction { + match change { + ChangeRef::Set(col, key, value) => tx.set(col, key, value), + ChangeRef::Remove(col, key) => tx.remove(col, key), + ChangeRef::Store(hash, preimage) => tx.store(hash, preimage), + ChangeRef::Release(hash) => tx.release(hash), + } + } + self.commit(tx) + } + + /// Retrieve the value previously stored against `key` or `None` if + /// `key` is not currently in the database. + fn get(&self, col: ColumnId, key: &[u8]) -> Option>; + + /// Call `f` with the value previously stored against `key`. + /// + /// This may be faster than `get` since it doesn't allocate. + /// Use `with_get` helper function if you need `f` to return a value from `f` + fn with_get(&self, col: ColumnId, key: &[u8], f: &mut dyn FnMut(&[u8])) { + self.get(col, key).map(|v| f(&v)); + } + + /// Set the value of `key` in `col` to `value`, replacing anything that is there currently. + fn set(&self, col: ColumnId, key: &[u8], value: &[u8]) -> error::Result<()> { + let mut t = Transaction::new(); + t.set(col, key, value); + self.commit(t) + } + /// Remove the value of `key` in `col`. + fn remove(&self, col: ColumnId, key: &[u8]) -> error::Result<()> { + let mut t = Transaction::new(); + t.remove(col, key); + self.commit(t) + } + + /// Retrieve the first preimage previously `store`d for `hash` or `None` if no preimage is + /// currently stored. + fn lookup(&self, hash: &H) -> Option>; + + /// Call `f` with the preimage stored for `hash` and return the result, or `None` if no preimage + /// is currently stored. + /// + /// This may be faster than `lookup` since it doesn't allocate. + /// Use `with_lookup` helper function if you need `f` to return a value from `f` + fn with_lookup(&self, hash: &H, f: &mut dyn FnMut(&[u8])) { + self.lookup(hash).map(|v| f(&v)); + } + + /// Store the `preimage` of `hash` into the database, so that it may be looked up later with + /// `Database::lookup`. This may be called multiple times, but `Database::lookup` but subsequent + /// calls will ignore `preimage` and simply increase the number of references on `hash`. + fn store(&self, hash: &H, preimage: &[u8]) -> error::Result<()> { + let mut t = Transaction::new(); + t.store(hash.clone(), preimage); + self.commit(t) + } + + /// Release the preimage of `hash` from the database. An equal number of these to the number of + /// corresponding `store`s must have been given before it is legal for `Database::lookup` to + /// be unable to provide the preimage. + fn release(&self, hash: &H) -> error::Result<()> { + let mut t = Transaction::new(); + t.release(hash.clone()); + self.commit(t) + } +} + +impl std::fmt::Debug for dyn Database { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "Database") + } +} + +/// Call `f` with the value previously stored against `key` and return the result, or `None` if +/// `key` is not currently in the database. +/// +/// This may be faster than `get` since it doesn't allocate. +pub fn with_get(db: &dyn Database, col: ColumnId, key: &[u8], mut f: impl FnMut(&[u8]) -> R) -> Option { + let mut result: Option = None; + let mut adapter = |k: &_| { result = Some(f(k)); }; + db.with_get(col, key, &mut adapter); + result +} + +/// Call `f` with the preimage stored for `hash` and return the result, or `None` if no preimage +/// is currently stored. +/// +/// This may be faster than `lookup` since it doesn't allocate. +pub fn with_lookup(db: &dyn Database, hash: &H, mut f: impl FnMut(&[u8]) -> R) -> Option { + let mut result: Option = None; + let mut adapter = |k: &_| { result = Some(f(k)); }; + db.with_lookup(hash, &mut adapter); + result +} diff --git a/primitives/database/src/mem.rs b/primitives/database/src/mem.rs new file mode 100644 index 0000000000000000000000000000000000000000..51cb854334d50ab9449bc96e6c96a188df044218 --- /dev/null +++ b/primitives/database/src/mem.rs @@ -0,0 +1,71 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! In-memory implementation of `Database` + +use std::collections::HashMap; +use crate::{Database, Change, ColumnId, Transaction, error}; +use parking_lot::RwLock; + +#[derive(Default)] +/// This implements `Database` as an in-memory hash map. `commit` is not atomic. +pub struct MemDb + (RwLock<(HashMap, Vec>>, HashMap>)>); + +impl Database for MemDb + where H: Clone + Send + Sync + Eq + PartialEq + Default + std::hash::Hash +{ + fn commit(&self, transaction: Transaction) -> error::Result<()> { + let mut s = self.0.write(); + for change in transaction.0.into_iter() { + match change { + Change::Set(col, key, value) => { s.0.entry(col).or_default().insert(key, value); }, + Change::Remove(col, key) => { s.0.entry(col).or_default().remove(&key); }, + Change::Store(hash, preimage) => { s.1.insert(hash, preimage); }, + Change::Release(hash) => { s.1.remove(&hash); }, + } + } + + Ok(()) + } + + fn get(&self, col: ColumnId, key: &[u8]) -> Option> { + let s = self.0.read(); + s.0.get(&col).and_then(|c| c.get(key).cloned()) + } + + fn lookup(&self, hash: &H) -> Option> { + let s = self.0.read(); + s.1.get(hash).cloned() + } +} + +impl MemDb + where H: Clone + Send + Sync + Eq + PartialEq + Default + std::hash::Hash +{ + /// Create a new instance + pub fn new() -> Self { + MemDb::default() + } + + /// Count number of values in a column + pub fn count(&self, col: ColumnId) -> usize { + let s = self.0.read(); + s.0.get(&col).map(|c| c.len()).unwrap_or(0) + } +} + diff --git a/primitives/debug-derive/Cargo.toml b/primitives/debug-derive/Cargo.toml index 0079b6219f5b618c709c322cf5639b9f6eec85f9..fd63abcfa7a6cf7dda9bab20ddaa4adc780b7841 100644 --- a/primitives/debug-derive/Cargo.toml +++ b/primitives/debug-derive/Cargo.toml @@ -1,14 +1,18 @@ [package] name = "sp-debug-derive" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Macros to derive runtime debug implementation." documentation = "https://docs.rs/sp-debug-derive" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [lib] proc-macro = true @@ -21,7 +25,3 @@ proc-macro2 = "1.0" std = [] [dev-dependencies] - - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/debug-derive/src/impls.rs b/primitives/debug-derive/src/impls.rs index b0e6dfa3eec4b9790901eef8b6dce5696250b622..1757b294d9d490191b968e4d5d0a5440d198f04f 100644 --- a/primitives/debug-derive/src/impls.rs +++ b/primitives/debug-derive/src/impls.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use quote::quote; use proc_macro2::TokenStream; diff --git a/primitives/debug-derive/src/lib.rs b/primitives/debug-derive/src/lib.rs index 68bbb94e1b006bba81ccead4a7fefb72f9b2354e..db370f890810dedcc78a9bbba19f7b23fb59412f 100644 --- a/primitives/debug-derive/src/lib.rs +++ b/primitives/debug-derive/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Macros to derive runtime debug implementation. //! diff --git a/primitives/debug-derive/tests/tests.rs b/primitives/debug-derive/tests/tests.rs index 77b3d53a2d4ad0189d58e22afbaa8455d07458ec..6a03762b1c65535462d96fc58e793886f1949369 100644 --- a/primitives/debug-derive/tests/tests.rs +++ b/primitives/debug-derive/tests/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use sp_debug_derive::RuntimeDebug; diff --git a/primitives/externalities/Cargo.toml b/primitives/externalities/Cargo.toml index af6e516fbfcd32eec31dd9d446785a5028a70ddd..65c59e41e4ab0a8683a376776dc1ea5a5a018e53 100644 --- a/primitives/externalities/Cargo.toml +++ b/primitives/externalities/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "sp-externalities" -version = "0.8.0-alpha.5" -license = "GPL-3.0" +version = "0.8.0-rc4" +license = "Apache-2.0" authors = ["Parity Technologies "] edition = "2018" homepage = "https://substrate.dev" @@ -9,10 +9,11 @@ repository = "https://github.com/paritytech/substrate/" description = "Substrate externalities abstraction" documentation = "https://docs.rs/sp-externalities" -[dependencies] -sp-storage = { version = "2.0.0-alpha.5", path = "../storage" } -sp-std = { version = "2.0.0-alpha.5", path = "../std" } -environmental = { version = "1.1.1" } - [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +sp-storage = { version = "2.0.0-rc4", path = "../storage" } +sp-std = { version = "2.0.0-rc4", path = "../std" } +environmental = { version = "1.1.1" } +codec = { package = "parity-scale-codec", version = "1.3.1" } diff --git a/primitives/externalities/src/extensions.rs b/primitives/externalities/src/extensions.rs index a61c03534fb0dbaeaad4e91bfcf2affa9555c10d..c75877e67db96c9bd553033e1cf7c463a3f2f663 100644 --- a/primitives/externalities/src/extensions.rs +++ b/primitives/externalities/src/extensions.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Externalities extensions storage. //! @@ -21,7 +22,8 @@ //! //! It is required that each extension implements the [`Extension`] trait. -use std::{collections::HashMap, any::{Any, TypeId}, ops::DerefMut}; +use std::{collections::HashMap, collections::hash_map::Entry, any::{Any, TypeId}, ops::DerefMut}; +use crate::Error; /// Marker trait for types that should be registered as [`Externalities`](crate::Externalities) extension. /// @@ -87,6 +89,16 @@ pub trait ExtensionStore { /// 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>; + + /// Register extension `extension` with speciifed `type_id`. + /// + /// It should return error if extension is already registered. + fn register_extension_with_type_id(&mut self, type_id: TypeId, extension: Box) -> Result<(), Error>; + + /// Deregister extension with speicifed 'type_id' and drop it. + /// + /// It should return error if extension is not registered. + fn deregister_extension_by_type_id(&mut self, type_id: TypeId) -> Result<(), Error>; } /// Stores extensions that should be made available through the externalities. @@ -95,6 +107,12 @@ pub struct Extensions { extensions: HashMap>, } +impl std::fmt::Debug for Extensions { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Extensions: ({})", self.extensions.len()) + } +} + impl Extensions { /// Create new instance of `Self`. pub fn new() -> Self { @@ -106,10 +124,23 @@ impl Extensions { self.extensions.insert(ext.type_id(), Box::new(ext)); } + /// Register extension `ext`. + pub fn register_with_type_id(&mut self, type_id: TypeId, extension: Box) -> Result<(), Error> { + match self.extensions.entry(type_id) { + Entry::Vacant(vacant) => { vacant.insert(extension); Ok(()) }, + Entry::Occupied(_) => Err(Error::ExtensionAlreadyRegistered), + } + } + /// 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) } + + /// Deregister extension of type `E`. + pub fn deregister(&mut self, type_id: TypeId) -> Option> { + self.extensions.remove(&type_id) + } } #[cfg(test)] diff --git a/primitives/externalities/src/lib.rs b/primitives/externalities/src/lib.rs index 6fbd239b89cef8995d2ab05d7192e710fcc87c34..8e141867195b743d99817fa464f930769af7fbf2 100644 --- a/primitives/externalities/src/lib.rs +++ b/primitives/externalities/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Substrate externalities abstraction //! @@ -24,7 +25,7 @@ use std::any::{Any, TypeId}; -use sp_storage::{ChildStorageKey, ChildInfo}; +use sp_storage::ChildInfo; pub use scope_limited::{set_and_run_with_externalities, with_externalities}; pub use extensions::{Extension, Extensions, ExtensionStore}; @@ -32,23 +33,42 @@ pub use extensions::{Extension, Extensions, ExtensionStore}; mod extensions; mod scope_limited; +/// Externalities error. +#[derive(Debug)] +pub enum Error { + /// Same extension cannot be registered twice. + ExtensionAlreadyRegistered, + /// Extensions are not supported. + ExtensionsAreNotSupported, + /// Extension `TypeId` is not registered. + ExtensionIsNotRegistered(TypeId), + /// Failed to update storage, + StorageUpdateFailed(&'static str), +} + /// The Substrate externalities. /// /// Provides access to the storage and to other registered extensions. pub trait Externalities: ExtensionStore { + /// Write a key value pair to the offchain storage database. + fn set_offchain_storage(&mut self, key: &[u8], value: Option<&[u8]>); + /// Read runtime storage. fn storage(&self, key: &[u8]) -> Option>; - /// Get storage value hash. This may be optimized for large values. + /// 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. + /// Get child storage value hash. + /// + /// This may be optimized for large values. /// /// Returns an `Option` that holds the SCALE encoded hash. fn child_storage_hash( &self, - storage_key: ChildStorageKey, - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) -> Option>; @@ -57,8 +77,7 @@ pub trait Externalities: ExtensionStore { /// Returns an `Option` that holds the SCALE encoded hash. fn child_storage( &self, - storage_key: ChildStorageKey, - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) -> Option>; @@ -70,12 +89,11 @@ pub trait Externalities: ExtensionStore { /// Set child storage entry `key` of current contract being called (effective immediately). fn set_child_storage( &mut self, - storage_key: ChildStorageKey, - child_info: ChildInfo, + child_info: &ChildInfo, key: Vec, value: Vec, ) { - self.place_child_storage(storage_key, child_info, key, Some(value)) + self.place_child_storage(child_info, key, Some(value)) } /// Clear a storage entry (`key`) of current contract being called (effective immediately). @@ -86,11 +104,10 @@ pub trait Externalities: ExtensionStore { /// Clear a child storage entry (`key`) of current contract being called (effective immediately). fn clear_child_storage( &mut self, - storage_key: ChildStorageKey, - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) { - self.place_child_storage(storage_key, child_info, key.to_vec(), None) + self.place_child_storage(child_info, key.to_vec(), None) } /// Whether a storage entry exists. @@ -101,11 +118,10 @@ pub trait Externalities: ExtensionStore { /// Whether a child storage entry exists. fn exists_child_storage( &self, - storage_key: ChildStorageKey, - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) -> bool { - self.child_storage(storage_key, child_info, key).is_some() + self.child_storage(child_info, key).is_some() } /// Returns the key immediately following the given key, if it exists. @@ -114,13 +130,12 @@ pub trait Externalities: ExtensionStore { /// Returns the key immediately following the given key, if it exists, in child storage. fn next_child_storage_key( &self, - storage_key: ChildStorageKey, - child_info: ChildInfo, + child_info: &ChildInfo, key: &[u8], ) -> Option>; /// Clear an entire child storage. - fn kill_child_storage(&mut self, storage_key: ChildStorageKey, child_info: ChildInfo); + fn kill_child_storage(&mut self, child_info: &ChildInfo); /// Clear storage entries which keys are start with the given prefix. fn clear_prefix(&mut self, prefix: &[u8]); @@ -128,19 +143,17 @@ pub trait Externalities: ExtensionStore { /// Clear child storage entries which keys are start with the given prefix. fn clear_child_prefix( &mut self, - storage_key: ChildStorageKey, - child_info: ChildInfo, + child_info: &ChildInfo, 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. + /// Set or clear a child storage entry. fn place_child_storage( &mut self, - storage_key: ChildStorageKey, - child_info: ChildInfo, + child_info: &ChildInfo, key: Vec, value: Option>, ); @@ -148,31 +161,63 @@ pub trait Externalities: ExtensionStore { /// 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. + /// Get the trie root of the current storage map. /// - /// The hash is defined by the `Block`. + /// This will also update all child storage keys in the top-level storage map. /// - /// Returns the SCALE encoded hash. + /// The returned hash is defined by the `Block` and is SCALE encoded. fn storage_root(&mut self) -> Vec; - /// 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. + /// 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, + child_info: &ChildInfo, ) -> Vec; - /// Get the change trie root of the current storage overlay at a block with given parent. - /// `parent` is expects a SCALE encoded hash. + /// Append storage item. /// - /// The hash is defined by the `Block`. + /// This assumes specific format of the storage item. Also there is no way to undo this operation. + fn storage_append( + &mut self, + key: Vec, + value: Vec, + ); + + /// Get the changes trie root of the current storage overlay at a block with given `parent`. + /// + /// `parent` expects a SCALE encoded hash. /// - /// Returns the SCALE encoded hash. + /// The returned hash is defined by the `Block` and is SCALE encoded. fn storage_changes_root(&mut self, parent: &[u8]) -> Result>, ()>; + /// Start a new nested transaction. + /// + /// This allows to either commit or roll back all changes made after this call to the + /// top changes or the default child changes. For every transaction there cam be a + /// matching call to either `storage_rollback_transaction` or `storage_commit_transaction`. + /// Any transactions that are still open after returning from runtime are committed + /// automatically. + /// + /// Changes made without any open transaction are committed immediately. + fn storage_start_transaction(&mut self); + + /// Rollback the last transaction started by `storage_start_transaction`. + /// + /// Any changes made during that storage transaction are discarded. Returns an error when + /// no transaction is open that can be closed. + fn storage_rollback_transaction(&mut self) -> Result<(), ()>; + + /// Commit the last transaction started by `storage_start_transaction`. + /// + /// Any changes made during that storage transaction are committed. Returns an error when + /// no transaction is open that can be closed. + fn storage_commit_transaction(&mut self) -> Result<(), ()>; + /// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! /// Benchmarking related functionality and shouldn't be used anywhere else! /// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -188,16 +233,56 @@ pub trait Externalities: ExtensionStore { /// /// Commits all changes to the database and clears all caches. fn commit(&mut self); + + /// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + /// Benchmarking related functionality and shouldn't be used anywhere else! + /// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + /// + /// Gets the current read/write count for the benchmarking process. + fn read_write_count(&self) -> (u32, u32, u32, u32); + + /// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + /// Benchmarking related functionality and shouldn't be used anywhere else! + /// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + /// + /// Resets read/write count for the benchmarking process. + fn reset_read_write_count(&mut self); + + /// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + /// Benchmarking related functionality and shouldn't be used anywhere else! + /// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + /// + /// Adds new storage keys to the DB tracking whitelist. + fn set_whitelist(&mut self, new: Vec>); } /// 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>; + + /// Register extension `ext`. + /// + /// Should return error if extension is already registered or extensions are not supported. + fn register_extension(&mut self, ext: T) -> Result<(), Error>; + + /// Deregister and drop extension of `T` type. + /// + /// Should return error if extension of type `T` is not registered or + /// extensions are not supported. + fn deregister_extension(&mut self) -> Result<(), Error>; } impl ExternalitiesExt for &mut dyn Externalities { fn extension(&mut self) -> Option<&mut T> { self.extension_by_type_id(TypeId::of::()).and_then(Any::downcast_mut) } + + fn register_extension(&mut self, ext: T) -> Result<(), Error> { + self.register_extension_with_type_id(TypeId::of::(), Box::new(ext)) + } + + fn deregister_extension(&mut self) -> Result<(), Error> { + self.deregister_extension_by_type_id(TypeId::of::()) + } } diff --git a/primitives/externalities/src/scope_limited.rs b/primitives/externalities/src/scope_limited.rs index 263858aa5f5ced3b3c16dfbadf3a701737823d26..1f70276f02d36658edf58a4bf873c045f7891b4a 100644 --- a/primitives/externalities/src/scope_limited.rs +++ b/primitives/externalities/src/scope_limited.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Stores the externalities in an `environmental` value to make it scope limited available. diff --git a/primitives/finality-grandpa/Cargo.toml b/primitives/finality-grandpa/Cargo.toml index 0595fa7ba700649fa2c4df5ae1ad3178648fdc1f..7e77e1253cbb2749d1e410ee90ecdef538c20178 100644 --- a/primitives/finality-grandpa/Cargo.toml +++ b/primitives/finality-grandpa/Cargo.toml @@ -1,33 +1,39 @@ [package] name = "sp-finality-grandpa" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Primitives for GRANDPA integration, suitable for WASM compilation." documentation = "https://docs.rs/sp-finality-grandpa" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-application-crypto = { version = "2.0.0-alpha.5", default-features = false, path = "../application-crypto" } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../std" } +sp-application-crypto = { version = "2.0.0-rc4", default-features = false, path = "../application-crypto" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +grandpa = { package = "finality-grandpa", version = "0.12.3", default-features = false, features = ["derive-codec"] } +log = { version = "0.4.8", optional = true } serde = { version = "1.0.101", optional = true, features = ["derive"] } -sp-api = { version = "2.0.0-alpha.5", default-features = false, path = "../api" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../runtime" } +sp-api = { version = "2.0.0-rc4", default-features = false, path = "../api" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../core" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../runtime" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../std" } [features] default = ["std"] std = [ "sp-application-crypto/std", "codec/std", - "sp-std/std", + "grandpa/std", + "log", "serde", "sp-api/std", + "sp-core/std", "sp-runtime/std", + "sp-std/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/finality-grandpa/src/lib.rs b/primitives/finality-grandpa/src/lib.rs index 9dcb1c2363c1551c5968320ca3c9493c0e23e98b..f99880041c0c04d0b20df639ea5121b317571aec 100644 --- a/primitives/finality-grandpa/src/lib.rs +++ b/primitives/finality-grandpa/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Primitives for GRANDPA integration, suitable for WASM compilation. @@ -23,10 +24,20 @@ extern crate alloc; #[cfg(feature = "std")] use serde::Serialize; + use codec::{Encode, Decode, Input, Codec}; -use sp_runtime::{ConsensusEngineId, RuntimeDebug}; +use sp_runtime::{ConsensusEngineId, RuntimeDebug, traits::NumberFor}; use sp_std::borrow::Cow; use sp_std::vec::Vec; +#[cfg(feature = "std")] +use sp_core::traits::BareCryptoStorePtr; +use sp_std::convert::TryInto; + +#[cfg(feature = "std")] +use log::debug; + +/// Key type for GRANDPA module. +pub const KEY_TYPE: sp_core::crypto::KeyTypeId = sp_application_crypto::key_types::GRANDPA; mod app { use sp_application_crypto::{app_crypto, key_types::GRANDPA, ed25519}; @@ -157,6 +168,238 @@ impl ConsensusLog { } } +/// Proof of voter misbehavior on a given set id. Misbehavior/equivocation in +/// GRANDPA happens when a voter votes on the same round (either at prevote or +/// precommit stage) for different blocks. Proving is achieved by collecting the +/// signed messages of conflicting votes. +#[derive(Clone, Debug, Decode, Encode, PartialEq)] +pub struct EquivocationProof { + set_id: SetId, + equivocation: Equivocation, +} + +impl EquivocationProof { + /// Create a new `EquivocationProof` for the given set id and using the + /// given equivocation as proof. + pub fn new(set_id: SetId, equivocation: Equivocation) -> Self { + EquivocationProof { + set_id, + equivocation, + } + } + + /// Returns the set id at which the equivocation occurred. + pub fn set_id(&self) -> SetId { + self.set_id + } + + /// Returns the round number at which the equivocation occurred. + pub fn round(&self) -> RoundNumber { + match self.equivocation { + Equivocation::Prevote(ref equivocation) => equivocation.round_number, + Equivocation::Precommit(ref equivocation) => equivocation.round_number, + } + } + + /// Returns the authority id of the equivocator. + pub fn offender(&self) -> &AuthorityId { + self.equivocation.offender() + } +} + +/// Wrapper object for GRANDPA equivocation proofs, useful for unifying prevote +/// and precommit equivocations under a common type. +#[derive(Clone, Debug, Decode, Encode, PartialEq)] +pub enum Equivocation { + /// Proof of equivocation at prevote stage. + Prevote(grandpa::Equivocation, AuthoritySignature>), + /// Proof of equivocation at precommit stage. + Precommit(grandpa::Equivocation, AuthoritySignature>), +} + +impl From, AuthoritySignature>> + for Equivocation +{ + fn from( + equivocation: grandpa::Equivocation< + AuthorityId, + grandpa::Prevote, + AuthoritySignature, + >, + ) -> Self { + Equivocation::Prevote(equivocation) + } +} + +impl From, AuthoritySignature>> + for Equivocation +{ + fn from( + equivocation: grandpa::Equivocation< + AuthorityId, + grandpa::Precommit, + AuthoritySignature, + >, + ) -> Self { + Equivocation::Precommit(equivocation) + } +} + +impl Equivocation { + /// Returns the authority id of the equivocator. + pub fn offender(&self) -> &AuthorityId { + match self { + Equivocation::Prevote(ref equivocation) => &equivocation.identity, + Equivocation::Precommit(ref equivocation) => &equivocation.identity, + } + } +} + +/// Verifies the equivocation proof by making sure that both votes target +/// different blocks and that its signatures are valid. +pub fn check_equivocation_proof(report: EquivocationProof) -> bool +where + H: Clone + Encode + PartialEq, + N: Clone + Encode + PartialEq, +{ + // NOTE: the bare `Prevote` and `Precommit` types don't share any trait, + // this is implemented as a macro to avoid duplication. + macro_rules! check { + ( $equivocation:expr, $message:expr ) => { + // if both votes have the same target the equivocation is invalid. + if $equivocation.first.0.target_hash == $equivocation.second.0.target_hash && + $equivocation.first.0.target_number == $equivocation.second.0.target_number + { + return false; + } + + // check signatures on both votes are valid + let valid_first = check_message_signature( + &$message($equivocation.first.0), + &$equivocation.identity, + &$equivocation.first.1, + $equivocation.round_number, + report.set_id, + ); + + let valid_second = check_message_signature( + &$message($equivocation.second.0), + &$equivocation.identity, + &$equivocation.second.1, + $equivocation.round_number, + report.set_id, + ); + + return valid_first && valid_second; + }; + } + + match report.equivocation { + Equivocation::Prevote(equivocation) => { + check!(equivocation, grandpa::Message::Prevote); + } + Equivocation::Precommit(equivocation) => { + check!(equivocation, grandpa::Message::Precommit); + } + } +} + +/// Encode round message localized to a given round and set id. +pub fn localized_payload(round: RoundNumber, set_id: SetId, message: &E) -> Vec { + let mut buf = Vec::new(); + localized_payload_with_buffer(round, set_id, message, &mut buf); + buf +} + +/// Encode round message localized to a given round and set id using the given +/// buffer. The given buffer will be cleared and the resulting encoded payload +/// will always be written to the start of the buffer. +pub fn localized_payload_with_buffer( + round: RoundNumber, + set_id: SetId, + message: &E, + buf: &mut Vec, +) { + buf.clear(); + (message, round, set_id).encode_to(buf) +} + +/// Check a message signature by encoding the message as a localized payload and +/// verifying the provided signature using the expected authority id. +pub fn check_message_signature( + message: &grandpa::Message, + id: &AuthorityId, + signature: &AuthoritySignature, + round: RoundNumber, + set_id: SetId, +) -> bool +where + H: Encode, + N: Encode, +{ + check_message_signature_with_buffer(message, id, signature, round, set_id, &mut Vec::new()) +} + +/// Check a message signature by encoding the message as a localized payload and +/// verifying the provided signature using the expected authority id. +/// The encoding necessary to verify the signature will be done using the given +/// buffer, the original content of the buffer will be cleared. +pub fn check_message_signature_with_buffer( + message: &grandpa::Message, + id: &AuthorityId, + signature: &AuthoritySignature, + round: RoundNumber, + set_id: SetId, + buf: &mut Vec, +) -> bool +where + H: Encode, + N: Encode, +{ + use sp_application_crypto::RuntimeAppPublic; + + localized_payload_with_buffer(round, set_id, message, buf); + + let valid = id.verify(&buf, signature); + + if !valid { + #[cfg(feature = "std")] + debug!(target: "afg", "Bad signature on message from {:?}", id); + } + + valid +} + +/// Localizes the message to the given set and round and signs the payload. +#[cfg(feature = "std")] +pub fn sign_message( + keystore: &BareCryptoStorePtr, + message: grandpa::Message, + public: AuthorityId, + round: RoundNumber, + set_id: SetId, +) -> Option> +where + H: Encode, + N: Encode, +{ + use sp_core::crypto::Public; + use sp_application_crypto::AppKey; + + let encoded = localized_payload(round, set_id, &message); + let signature = keystore.read() + .sign_with(AuthorityId::ID, &public.to_public_crypto_pair(), &encoded[..]) + .ok()? + .try_into() + .ok()?; + + Some(grandpa::SignedMessage { + message, + signature, + id: public, + }) +} + /// WASM function call to check for pending changes. pub const PENDING_CHANGE_CALL: &str = "grandpa_pending_change"; /// WASM function call to get current GRANDPA authorities. @@ -211,6 +454,29 @@ impl<'a> Decode for VersionedAuthorityList<'a> { } } +/// An opaque type used to represent the key ownership proof at the runtime API +/// boundary. The inner value is an encoded representation of the actual key +/// ownership proof which will be parameterized when defining the runtime. At +/// the runtime API boundary this type is unknown and as such we keep this +/// opaque representation, implementors of the runtime API will have to make +/// sure that all usages of `OpaqueKeyOwnershipProof` refer to the same type. +#[derive(Decode, Encode, PartialEq)] +pub struct OpaqueKeyOwnershipProof(Vec); + +impl OpaqueKeyOwnershipProof { + /// Create a new `OpaqueKeyOwnershipProof` using the given encoded + /// representation. + pub fn new(inner: Vec) -> OpaqueKeyOwnershipProof { + OpaqueKeyOwnershipProof(inner) + } + + /// Try to decode this `OpaqueKeyOwnershipProof` into the given concrete key + /// ownership proof type. + pub fn decode(self) -> Option { + codec::Decode::decode(&mut &self.0[..]).ok() + } +} + sp_api::decl_runtime_apis! { /// APIs for integrating the GRANDPA finality gadget into runtimes. /// This should be implemented on the runtime side. @@ -230,5 +496,35 @@ sp_api::decl_runtime_apis! { /// used to finalize descendants of this block (B+1, B+2, ...). The block B itself /// is finalized by the authorities from block B-1. fn grandpa_authorities() -> AuthorityList; + + /// Submits an extrinsic to report an equivocation. The caller must + /// provide the equivocation proof and a key ownership proof (should be + /// obtained using `generate_key_ownership_proof`). This method will + /// sign the extrinsic with any reporting keys available in the keystore + /// and will push the transaction to the pool. This method returns `None` + /// when creation of the extrinsic fails, either due to unavailability + /// of keys to sign, or because equivocation reporting is disabled for + /// the given runtime (i.e. this method is hardcoded to return `None`). + /// Only useful in an offchain context. + fn submit_report_equivocation_extrinsic( + equivocation_proof: EquivocationProof>, + key_owner_proof: OpaqueKeyOwnershipProof, + ) -> Option<()>; + + /// Generates a proof of key ownership for the given authority in the + /// given set. An example usage of this module is coupled with the + /// session historical module to prove that a given authority key is + /// tied to a given staking identity during a specific session. Proofs + /// of key ownership are necessary for submitting equivocation reports. + /// NOTE: even though the API takes a `set_id` as parameter the current + /// implementations ignore this parameter and instead rely on this + /// method being called at the correct block height, i.e. any point at + /// which the given set id is live on-chain. Future implementations will + /// instead use indexed data through an offchain worker, not requiring + /// older states to be available. + fn generate_key_ownership_proof( + set_id: SetId, + authority_id: AuthorityId, + ) -> Option; } } diff --git a/primitives/finality-tracker/Cargo.toml b/primitives/finality-tracker/Cargo.toml index 4e6cf6c92d324c36278c18ef0b5b5703b21b56e3..5cbd497becc865f9d176e34623eb591b1107e0f4 100644 --- a/primitives/finality-tracker/Cargo.toml +++ b/primitives/finality-tracker/Cargo.toml @@ -1,17 +1,20 @@ [package] name = "sp-finality-tracker" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME module that tracks the last finalized block, as perceived by block authors." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -sp-inherents = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/inherents" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/std" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +sp-inherents = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/inherents" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../primitives/std" } [features] default = ["std"] @@ -20,6 +23,3 @@ std = [ "sp-std/std", "sp-inherents/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/finality-tracker/src/lib.rs b/primitives/finality-tracker/src/lib.rs index a7157139dc1050699682824ae2763a76b01dec7b..fea40039056068a04f2f40054b7255763be8b7a5 100644 --- a/primitives/finality-tracker/src/lib.rs +++ b/primitives/finality-tracker/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! FRAME module that tracks the last finalized block, as perceived by block authors. diff --git a/primitives/inherents/Cargo.toml b/primitives/inherents/Cargo.toml index dd640f00ec1a272d87511bd2f22f88916abeebbb..3532e08da1d6a177d241e6a731a2384e93e9278d 100644 --- a/primitives/inherents/Cargo.toml +++ b/primitives/inherents/Cargo.toml @@ -1,20 +1,23 @@ [package] name = "sp-inherents" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Provides types and traits for creating and checking inherents." documentation = "https://docs.rs/sp-inherents" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] parking_lot = { version = "0.10.0", optional = true } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../std" } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../core" } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../std" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../core" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } derive_more = { version = "0.99.2", optional = true } [features] @@ -26,6 +29,3 @@ std = [ "sp-core/std", "derive_more", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/inherents/src/lib.rs b/primitives/inherents/src/lib.rs index e8df2c49e51931659859b16912664ab3fcd4c208..98942969535285081b7bb42774867c566dbfd830 100644 --- a/primitives/inherents/src/lib.rs +++ b/primitives/inherents/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Provides types and traits for creating and checking inherents. //! @@ -408,6 +409,11 @@ pub trait ProvideInherent { /// Create an inherent out of the given `InherentData`. fn create_inherent(data: &InherentData) -> Option; + /// If `Some`, indicates that an inherent is required. Check will return the inner error if no + /// inherent is found. If `Err`, indicates that the check failed and further operations should + /// be aborted. + fn is_inherent_required(_: &InherentData) -> Result, Self::Error> { Ok(None) } + /// Check the given inherent if it is valid. /// Checking the inherent is optional and can be omitted. fn check_inherent(_: &Self::Call, _: &InherentData) -> Result<(), Self::Error> { diff --git a/primitives/io/Cargo.toml b/primitives/io/Cargo.toml index 9cda2120cc2b45290da425f14f758ba483445b43..06df2cc5ed6c441980b8bb1eacff635d5220dad0 100644 --- a/primitives/io/Cargo.toml +++ b/primitives/io/Cargo.toml @@ -1,27 +1,33 @@ [package] name = "sp-io" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "I/O for Substrate runtimes" documentation = "https://docs.rs/sp-io" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } hash-db = { version = "0.15.2", default-features = false } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../core" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../std" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../core" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../std" } libsecp256k1 = { version = "0.3.4", optional = true } -sp-state-machine = { version = "0.8.0-alpha.5", optional = true, path = "../../primitives/state-machine" } -sp-wasm-interface = { version = "2.0.0-alpha.5", path = "../../primitives/wasm-interface", default-features = false } -sp-runtime-interface = { version = "2.0.0-alpha.5", default-features = false, path = "../runtime-interface" } -sp-trie = { version = "2.0.0-alpha.5", optional = true, path = "../../primitives/trie" } -sp-externalities = { version = "0.8.0-alpha.5", optional = true, path = "../externalities" } +sp-state-machine = { version = "0.8.0-rc4", optional = true, path = "../../primitives/state-machine" } +sp-wasm-interface = { version = "2.0.0-rc4", path = "../../primitives/wasm-interface", default-features = false } +sp-runtime-interface = { version = "2.0.0-rc4", default-features = false, path = "../runtime-interface" } +sp-trie = { version = "2.0.0-rc4", optional = true, path = "../../primitives/trie" } +sp-externalities = { version = "0.8.0-rc4", optional = true, path = "../externalities" } +sp-tracing = { version = "2.0.0-rc4", default-features = false, path = "../tracing" } log = { version = "0.4.8", optional = true } +futures = { version = "0.3.1", features = ["thread-pool"], optional = true } +parking_lot = { version = "0.10.0", optional = true } [features] default = ["std"] @@ -37,6 +43,8 @@ std = [ "sp-externalities", "sp-wasm-interface/std", "log", + "futures", + "parking_lot", ] # These two features are used for `no_std` builds for the environments which already provides @@ -46,6 +54,3 @@ std = [ disable_panic_handler = [] disable_oom = [] disable_allocator = [] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/io/src/batch_verifier.rs b/primitives/io/src/batch_verifier.rs new file mode 100644 index 0000000000000000000000000000000000000000..642e77504d00f034d76811f1e618efebbc589263 --- /dev/null +++ b/primitives/io/src/batch_verifier.rs @@ -0,0 +1,191 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Batch/parallel verification. + +use sp_core::{ed25519, sr25519, ecdsa, crypto::Pair, traits::CloneableSpawn}; +use std::sync::{Arc, atomic::{AtomicBool, Ordering as AtomicOrdering}}; +use futures::{future::FutureExt, task::FutureObj, channel::oneshot}; + +#[derive(Debug, Clone)] +struct Sr25519BatchItem { + signature: sr25519::Signature, + pub_key: sr25519::Public, + message: Vec, +} + +/// Batch verifier. +/// +/// Used to parallel-verify signatures for runtime host. Provide task executor and +/// just push (`push_ed25519`, `push_sr25519`) as many signature as you need. At the end, +/// call `verify_and_clear to get a result. After that, batch verifier is ready for the +/// next batching job. +pub struct BatchVerifier { + scheduler: Box, + sr25519_items: Vec, + invalid: Arc, + pending_tasks: Vec>, +} + +impl BatchVerifier { + pub fn new(scheduler: Box) -> Self { + BatchVerifier { + scheduler, + sr25519_items: Default::default(), + invalid: Arc::new(false.into()), + pending_tasks: vec![], + } + } + + /// Spawn a verification task. + /// + /// Returns `false` if there was already an invalid verification or if + /// the verification could not be spawned. + fn spawn_verification_task( + &mut self, f: impl FnOnce() -> bool + Send + 'static, + ) -> bool { + // there is already invalid transaction encountered + if self.invalid.load(AtomicOrdering::Relaxed) { return false; } + + let invalid_clone = self.invalid.clone(); + let (sender, receiver) = oneshot::channel(); + self.pending_tasks.push(receiver); + + self.scheduler.spawn_obj(FutureObj::new( + async move { + if !f() { + invalid_clone.store(true, AtomicOrdering::Relaxed); + } + if sender.send(()).is_err() { + // sanity + log::warn!("Verification halted while result was pending"); + invalid_clone.store(true, AtomicOrdering::Relaxed); + } + }.boxed() + )) + .map_err(|_| { + log::debug!( + target: "runtime", + "Batch-verification returns false because failed to spawn background task.", + ) + }) + .is_ok() + } + + /// Push ed25519 signature to verify. + /// + /// Returns false if some of the pushed signatures before already failed the check + /// (in this case it won't verify anything else) + pub fn push_ed25519( + &mut self, + signature: ed25519::Signature, + pub_key: ed25519::Public, + message: Vec, + ) -> bool { + self.spawn_verification_task(move || ed25519::Pair::verify(&signature, &message, &pub_key)) + } + + /// Push sr25519 signature to verify. + /// + /// Returns false if some of the pushed signatures before already failed the check. + /// (in this case it won't verify anything else) + pub fn push_sr25519( + &mut self, + signature: sr25519::Signature, + pub_key: sr25519::Public, + message: Vec, + ) -> bool { + if self.invalid.load(AtomicOrdering::Relaxed) { return false; } + self.sr25519_items.push(Sr25519BatchItem { signature, pub_key, message }); + + if self.sr25519_items.len() >= 128 { + let items = std::mem::take(&mut self.sr25519_items); + self.spawn_verification_task(move || Self::verify_sr25519_batch(items)) + } else { + true + } + } + + /// Push ecdsa signature to verify. + /// + /// Returns false if some of the pushed signatures before already failed the check + /// (in this case it won't verify anything else) + pub fn push_ecdsa( + &mut self, + signature: ecdsa::Signature, + pub_key: ecdsa::Public, + message: Vec, + ) -> bool { + self.spawn_verification_task(move || ecdsa::Pair::verify(&signature, &message, &pub_key)) + } + + fn verify_sr25519_batch(items: Vec) -> bool { + let messages = items.iter().map(|item| &item.message[..]).collect(); + let signatures = items.iter().map(|item| &item.signature).collect(); + let pub_keys = items.iter().map(|item| &item.pub_key).collect(); + + sr25519::verify_batch(messages, signatures, pub_keys) + } + + /// Verify all previously pushed signatures since last call and return + /// aggregated result. + #[must_use] + pub fn verify_and_clear(&mut self) -> bool { + let pending = std::mem::take(&mut self.pending_tasks); + let started = std::time::Instant::now(); + + log::trace!( + target: "runtime", + "Batch-verification: {} pending tasks, {} sr25519 signatures", + pending.len(), + self.sr25519_items.len(), + ); + + if !Self::verify_sr25519_batch(std::mem::take(&mut self.sr25519_items)) { + return false; + } + + if pending.len() > 0 { + let (sender, receiver) = std::sync::mpsc::channel(); + if self.scheduler.spawn_obj(FutureObj::new(async move { + futures::future::join_all(pending).await; + sender.send(()) + .expect("Channel never panics if receiver is live. \ + Receiver is always live until received this data; qed. "); + }.boxed())).is_err() { + log::debug!( + target: "runtime", + "Batch-verification returns false because failed to spawn background task.", + ); + + return false; + } + if receiver.recv().is_err() { + log::warn!(target: "runtime", "Haven't received async result from verification task. Returning false."); + return false; + } + } + + log::trace!( + target: "runtime", + "Finalization of batch verification took {} ms", + started.elapsed().as_millis(), + ); + + !self.invalid.swap(false, AtomicOrdering::Relaxed) + } +} diff --git a/primitives/io/src/lib.rs b/primitives/io/src/lib.rs index bc49df159eb6f873d5a9ac7e011a529cc2422cc0..6c99a5c75195b4c07a5eaad80a80a9bd86954865 100644 --- a/primitives/io/src/lib.rs +++ b/primitives/io/src/lib.rs @@ -1,20 +1,21 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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. +// 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. -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! This is part of the Substrate runtime. +//! I/O host interface for substrate runtime. #![warn(missing_docs)] @@ -34,14 +35,14 @@ use sp_std::ops::Deref; #[cfg(feature = "std")] use sp_core::{ crypto::Pair, - traits::{KeystoreExt, CallInWasmExt}, + traits::{KeystoreExt, CallInWasmExt, TaskExecutorExt}, offchain::{OffchainExt, TransactionPoolExt}, hexdisplay::HexDisplay, - storage::{ChildStorageKey, ChildInfo}, + storage::ChildInfo, }; use sp_core::{ - crypto::KeyTypeId, ed25519, sr25519, H256, LogLevel, + crypto::KeyTypeId, ed25519, sr25519, ecdsa, H256, LogLevel, offchain::{ Timestamp, HttpRequestId, HttpRequestStatus, HttpError, StorageKind, OpaqueNetworkState, }, @@ -57,6 +58,12 @@ use codec::{Encode, Decode}; #[cfg(feature = "std")] use sp_externalities::{ExternalitiesExt, Externalities}; +#[cfg(feature = "std")] +mod batch_verifier; + +#[cfg(feature = "std")] +use batch_verifier::BatchVerifier; + /// Error verifying ECDSA signature #[derive(Encode, Decode)] pub enum EcdsaVerifyError { @@ -68,19 +75,6 @@ pub enum EcdsaVerifyError { BadSignature, } -/// Returns a `ChildStorageKey` if the given `storage_key` slice is a valid storage -/// key or panics otherwise. -/// -/// Panicking here is aligned with what the `without_std` environment would do -/// in the case of an invalid child storage key. -#[cfg(feature = "std")] -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"), - } -} - /// Interface for accessing the storage from within the runtime. #[runtime_interface] pub trait Storage { @@ -89,30 +83,6 @@ pub trait Storage { self.storage(key).map(|s| s.to_vec()) } - /// All Child api uses : - /// - A `child_storage_key` to define the anchor point for the child proof - /// (commonly the location where the child root is stored in its parent trie). - /// - A `child_storage_types` to identify the kind of the child type and how its - /// `child definition` parameter is encoded. - /// - A `child_definition_parameter` which is the additional information required - /// to use the child trie. For instance defaults child tries requires this to - /// contain a collision free unique id. - /// - /// This function specifically returns the data for `key` in the child storage or `None` - /// if the key can not be found. - fn child_get( - &self, - child_storage_key: &[u8], - child_definition: &[u8], - child_type: u32, - key: &[u8], - ) -> Option> { - let storage_key = child_storage_key_or_panic(child_storage_key); - let child_info = ChildInfo::resolve_child_info(child_type, child_definition) - .expect("Invalid child definition"); - self.child_storage(storage_key, child_info, key).map(|s| s.to_vec()) - } - /// Get `key` from storage, placing the value into `value_out` and return the number of /// bytes that the entry in storage has beyond the offset or `None` if the storage entry /// doesn't exist at all. @@ -128,26 +98,138 @@ pub trait Storage { }) } + /// Set `key` to `value` in the storage. + fn set(&mut self, key: &[u8], value: &[u8]) { + self.set_storage(key.to_vec(), value.to_vec()); + } + + /// Clear the storage of the given `key` and its value. + fn clear(&mut self, key: &[u8]) { + self.clear_storage(key) + } + + /// Check whether the given `key` exists in storage. + fn exists(&self, key: &[u8]) -> bool { + self.exists_storage(key) + } + + /// Clear the storage of each key-value pair where the key starts with the given `prefix`. + fn clear_prefix(&mut self, prefix: &[u8]) { + Externalities::clear_prefix(*self, prefix) + } + + /// Append the encoded `value` to the storage item at `key`. + /// + /// The storage item needs to implement [`EncodeAppend`](codec::EncodeAppend). + /// + /// # Warning + /// + /// If the storage item does not support [`EncodeAppend`](codec::EncodeAppend) or + /// something else fails at appending, the storage item will be set to `[value]`. + fn append(&mut self, key: &[u8], value: Vec) { + self.storage_append(key.to_vec(), value); + } + + /// "Commit" all existing operations and compute the resulting storage root. + /// + /// The hashing algorithm is defined by the `Block`. + /// + /// Returns a `Vec` that holds the SCALE encoded hash. + fn root(&mut self) -> Vec { + self.storage_root() + } + + /// "Commit" all existing operations and get the resulting storage change root. + /// `parent_hash` is a SCALE encoded hash. + /// + /// The hashing algorithm is defined by the `Block`. + /// + /// Returns `Some(Vec)` which holds the SCALE encoded hash or `None` when + /// changes trie is disabled. + fn changes_root(&mut self, parent_hash: &[u8]) -> Option> { + self.storage_changes_root(parent_hash) + .expect("Invalid `parent_hash` given to `changes_root`.") + } + + /// Get the next key in storage after the given one in lexicographic order. + fn next_key(&mut self, key: &[u8]) -> Option> { + self.next_storage_key(&key) + } + + /// Start a new nested transaction. + /// + /// This allows to either commit or roll back all changes that are made after this call. + /// For every transaction there must be a matching call to either `rollback_transaction` + /// or `commit_transaction`. This is also effective for all values manipulated using the + /// `DefaultChildStorage` API. + /// + /// # Warning + /// + /// This is a low level API that is potentially dangerous as it can easily result + /// in unbalanced transactions. For example, FRAME users should use high level storage + /// abstractions. + fn start_transaction(&mut self) { + self.storage_start_transaction(); + } + + /// Rollback the last transaction started by `start_transaction`. + /// + /// Any changes made during that transaction are discarded. + /// + /// # Panics + /// + /// Will panic if there is no open transaction. + fn rollback_transaction(&mut self) { + self.storage_rollback_transaction() + .expect("No open transaction that can be rolled back."); + } + + /// Commit the last transaction started by `start_transaction`. + /// + /// Any changes made during that transaction are committed. + /// + /// # Panics + /// + /// Will panic if there is no open transaction. + fn commit_transaction(&mut self) { + self.storage_commit_transaction() + .expect("No open transaction that can be committed."); + } +} + +/// Interface for accessing the child storage for default child trie, +/// from within the runtime. +#[runtime_interface] +pub trait DefaultChildStorage { + /// Get a default child storage value for a given key. + /// + /// Parameter `storage_key` is the unprefixed location of the root of the child trie in the parent trie. + /// Result is `None` if the value for `key` in the child storage can not be found. + fn get( + &self, + storage_key: &[u8], + key: &[u8], + ) -> Option> { + let child_info = ChildInfo::new_default(storage_key); + self.child_storage(&child_info, key).map(|s| s.to_vec()) + } + + /// Allocation efficient variant of `get`. + /// /// Get `key` from child storage, placing the value into `value_out` and return the number /// of bytes that the entry in storage has beyond the offset or `None` if the storage entry /// doesn't exist at all. /// If `value_out` length is smaller than the returned length, only `value_out` length bytes /// are copied into `value_out`. - /// - /// See `child_get` for common child api parameters. - fn child_read( + fn read( &self, - child_storage_key: &[u8], - child_definition: &[u8], - child_type: u32, + storage_key: &[u8], key: &[u8], value_out: &mut [u8], value_offset: u32, ) -> Option { - let storage_key = child_storage_key_or_panic(child_storage_key); - let child_info = ChildInfo::resolve_child_info(child_type, child_definition) - .expect("Invalid child definition"); - self.child_storage(storage_key, child_info, key) + let child_info = ChildInfo::new_default(storage_key); + self.child_storage(&child_info, key) .map(|value| { let value_offset = value_offset as usize; let data = &value[value_offset.min(value.len())..]; @@ -157,159 +239,91 @@ pub trait Storage { }) } - /// Set `key` to `value` in the storage. - fn set(&mut self, key: &[u8], value: &[u8]) { - self.set_storage(key.to_vec(), value.to_vec()); - } - - /// Set `key` to `value` in the child storage denoted by `child_storage_key`. + /// Set a child storage value. /// - /// See `child_get` for common child api parameters. - fn child_set( + /// Set `key` to `value` in the child storage denoted by `storage_key`. + fn set( &mut self, - child_storage_key: &[u8], - child_definition: &[u8], - child_type: u32, + storage_key: &[u8], key: &[u8], value: &[u8], ) { - let storage_key = child_storage_key_or_panic(child_storage_key); - let child_info = ChildInfo::resolve_child_info(child_type, child_definition) - .expect("Invalid child definition"); - self.set_child_storage(storage_key, child_info, key.to_vec(), value.to_vec()); + let child_info = ChildInfo::new_default(storage_key); + self.set_child_storage(&child_info, key.to_vec(), value.to_vec()); } - /// Clear the storage of the given `key` and its value. - fn clear(&mut self, key: &[u8]) { - self.clear_storage(key) - } - - /// Clear the given child storage of the given `key` and its value. + /// Clear a child storage key. /// - /// See `child_get` for common child api parameters. - fn child_clear( + /// For the default child storage at `storage_key`, clear value at `key`. + fn clear( &mut self, - child_storage_key: &[u8], - child_definition: &[u8], - child_type: u32, + storage_key: &[u8], key: &[u8], ) { - let storage_key = child_storage_key_or_panic(child_storage_key); - let child_info = ChildInfo::resolve_child_info(child_type, child_definition) - .expect("Invalid child definition"); - self.clear_child_storage(storage_key, child_info, key); + let child_info = ChildInfo::new_default(storage_key); + self.clear_child_storage(&child_info, key); } /// Clear an entire child storage. /// - /// See `child_get` for common child api parameters. - fn child_storage_kill( + /// If it exists, the child storage for `storage_key` + /// is removed. + fn storage_kill( &mut self, - child_storage_key: &[u8], - child_definition: &[u8], - child_type: u32, + storage_key: &[u8], ) { - let storage_key = child_storage_key_or_panic(child_storage_key); - let child_info = ChildInfo::resolve_child_info(child_type, child_definition) - .expect("Invalid child definition"); - self.kill_child_storage(storage_key, child_info); - } - - /// Check whether the given `key` exists in storage. - fn exists(&self, key: &[u8]) -> bool { - self.exists_storage(key) + let child_info = ChildInfo::new_default(storage_key); + self.kill_child_storage(&child_info); } - /// Check whether the given `key` exists in storage. + /// Check a child storage key. /// - /// See `child_get` for common child api parameters. - fn child_exists( + /// Check whether the given `key` exists in default child defined at `storage_key`. + fn exists( &self, - child_storage_key: &[u8], - child_definition: &[u8], - child_type: u32, + storage_key: &[u8], key: &[u8], ) -> bool { - let storage_key = child_storage_key_or_panic(child_storage_key); - let child_info = ChildInfo::resolve_child_info(child_type, child_definition) - .expect("Invalid child definition"); - self.exists_child_storage(storage_key, child_info, key) - } - - /// Clear the storage of each key-value pair where the key starts with the given `prefix`. - fn clear_prefix(&mut self, prefix: &[u8]) { - Externalities::clear_prefix(*self, prefix) + let child_info = ChildInfo::new_default(storage_key); + self.exists_child_storage(&child_info, key) } - /// Clear the child storage of each key-value pair where the key starts with the given `prefix`. + /// Clear child default key by prefix. /// - /// See `child_get` for common child api parameters. - fn child_clear_prefix( + /// Clear the child storage of each key-value pair where the key starts with the given `prefix`. + fn clear_prefix( &mut self, - child_storage_key: &[u8], - child_definition: &[u8], - child_type: u32, + storage_key: &[u8], prefix: &[u8], ) { - let storage_key = child_storage_key_or_panic(child_storage_key); - let child_info = ChildInfo::resolve_child_info(child_type, child_definition) - .expect("Invalid child definition"); - self.clear_child_prefix(storage_key, child_info, prefix); + let child_info = ChildInfo::new_default(storage_key); + self.clear_child_prefix(&child_info, prefix); } - /// "Commit" all existing operations and compute the resulting storage root. - /// - /// The hashing algorithm is defined by the `Block`. + /// Default child root calculation. /// - /// Returns the SCALE encoded hash. - fn root(&mut self) -> Vec { - self.storage_root() - } - /// "Commit" all existing operations and compute the resulting child storage root. - /// /// The hashing algorithm is defined by the `Block`. /// - /// Returns the SCALE encoded hash. - /// - /// See `child_get` for common child api parameters. - fn child_root( + /// Returns a `Vec` that holds the SCALE encoded hash. + fn root( &mut self, - child_storage_key: &[u8], + storage_key: &[u8], ) -> Vec { - let storage_key = child_storage_key_or_panic(child_storage_key); - self.child_storage_root(storage_key) + let child_info = ChildInfo::new_default(storage_key); + self.child_storage_root(&child_info) } - /// "Commit" all existing operations and get the resulting storage change root. - /// `parent_hash` is a SCALE encoded hash. - /// - /// The hashing algorithm is defined by the `Block`. + /// Child storage key iteration. /// - /// Returns an `Some(_)` which holds the SCALE encoded hash or `None` when - /// changes trie is disabled. - fn changes_root(&mut self, parent_hash: &[u8]) -> Option> { - self.storage_changes_root(parent_hash) - .expect("Invalid `parent_hash` given to `changes_root`.") - } - - /// Get the next key in storage after the given one in lexicographic order. - fn next_key(&mut self, key: &[u8]) -> Option> { - self.next_storage_key(&key) - } - /// Get the next key in storage after the given one in lexicographic order in child storage. - fn child_next_key( + fn next_key( &mut self, - child_storage_key: &[u8], - child_definition: &[u8], - child_type: u32, + storage_key: &[u8], key: &[u8], ) -> Option> { - let storage_key = child_storage_key_or_panic(child_storage_key); - let child_info = ChildInfo::resolve_child_info(child_type, child_definition) - .expect("Invalid child definition"); - self.next_child_storage_key(storage_key, child_info, key) + let child_info = ChildInfo::new_default(storage_key); + self.next_child_storage_key(&child_info, key) } } @@ -325,6 +339,16 @@ pub trait Trie { fn blake2_256_ordered_root(input: Vec>) -> H256 { Layout::::ordered_trie_root(input) } + + /// A trie root formed from the iterated items. + fn keccak_256_root(input: Vec<(Vec, Vec)>) -> H256 { + Layout::::trie_root(input) + } + + /// A trie root formed from the enumerated items. + fn keccak_256_ordered_root(input: Vec>) -> H256 { + Layout::::ordered_trie_root(input) + } } /// Interface that provides miscellaneous functions for communicating between the runtime and the node. @@ -354,7 +378,8 @@ pub trait Misc { /// Extract the runtime version of the given wasm blob by calling `Core_version`. /// - /// Returns the SCALE encoded runtime version and `None` if the call failed. + /// Returns `None` if calling the function failed for any reason or `Some(Vec)` where + /// the `Vec` holds the SCALE encoded runtime version. /// /// # Performance /// @@ -367,7 +392,18 @@ pub trait Misc { self.extension::() .expect("No `CallInWasmExt` associated for the current context!") - .call_in_wasm(wasm, None, "Core_version", &[], &mut ext) + .call_in_wasm( + wasm, + None, + "Core_version", + &[], + &mut ext, + // If a runtime upgrade introduces new host functions that are not provided by + // the node, we should not fail at instantiation. Otherwise nodes that are + // updated could run this successfully and it could lead to a storage root + // mismatch when importing this block. + sp_core::traits::MissingHostFunctions::Allow, + ) .ok() } } @@ -416,11 +452,10 @@ pub trait Crypto { .ok() } - /// Verify an `ed25519` signature. + /// Verify `ed25519` signature. /// - /// Returns `true` when the verification in successful. + /// Returns `true` when the verification was successful. fn ed25519_verify( - &self, sig: &ed25519::Signature, msg: &[u8], pub_key: &ed25519::Public, @@ -428,6 +463,84 @@ pub trait Crypto { ed25519::Pair::verify(sig, msg, pub_key) } + /// Register a `ed25519` signature for batch verification. + /// + /// Batch verification must be enabled by calling [`start_batch_verify`]. + /// If batch verification is not enabled, the signature will be verified immediatley. + /// To get the result of the batch verification, [`finish_batch_verify`] + /// needs to be called. + /// + /// Returns `true` when the verification is either successful or batched. + fn ed25519_batch_verify( + &mut self, + sig: &ed25519::Signature, + msg: &[u8], + pub_key: &ed25519::Public, + ) -> bool { + self.extension::().map( + |extension| extension.push_ed25519(sig.clone(), pub_key.clone(), msg.to_vec()) + ).unwrap_or_else(|| ed25519_verify(sig, msg, pub_key)) + } + + /// Verify `sr25519` signature. + /// + /// Returns `true` when the verification was successful. + #[version(2)] + fn sr25519_verify( + sig: &sr25519::Signature, + msg: &[u8], + pub_key: &sr25519::Public, + ) -> bool { + sr25519::Pair::verify(sig, msg, pub_key) + } + + /// Register a `sr25519` signature for batch verification. + /// + /// Batch verification must be enabled by calling [`start_batch_verify`]. + /// If batch verification is not enabled, the signature will be verified immediatley. + /// To get the result of the batch verification, [`finish_batch_verify`] + /// needs to be called. + /// + /// Returns `true` when the verification is either successful or batched. + fn sr25519_batch_verify( + &mut self, + sig: &sr25519::Signature, + msg: &[u8], + pub_key: &sr25519::Public, + ) -> bool { + self.extension::().map( + |extension| extension.push_sr25519(sig.clone(), pub_key.clone(), msg.to_vec()) + ).unwrap_or_else(|| sr25519_verify(sig, msg, pub_key)) + } + + /// Start verification extension. + fn start_batch_verify(&mut self) { + let scheduler = self.extension::() + .expect("No task executor associated with the current context!") + .0 + .clone(); + + self.register_extension(VerificationExt(BatchVerifier::new(scheduler))) + .expect("Failed to register required extension: `VerificationExt`"); + } + + /// Finish batch-verification of signatures. + /// + /// Verify or wait for verification to finish for all signatures which were previously + /// deferred by `sr25519_verify`/`ed25519_verify`. + /// + /// Will panic if no `VerificationExt` is registered (`start_batch_verify` was not called). + fn finish_batch_verify(&mut self) -> bool { + let result = self.extension::() + .expect("`finish_batch_verify` should only be called after `start_batch_verify`") + .verify_and_clear(); + + self.deregister_extension::() + .expect("No verification extension in current context!"); + + result + } + /// Returns all `sr25519` public keys for the given key id from the keystore. fn sr25519_public_keys(&mut self, id: KeyTypeId) -> Vec { self.extension::() @@ -477,12 +590,75 @@ pub trait Crypto { sr25519::Pair::verify_deprecated(sig, msg, pubkey) } - /// Verify an `sr25519` signature. + /// Returns all `ecdsa` public keys for the given key id from the keystore. + fn ecdsa_public_keys(&mut self, id: KeyTypeId) -> Vec { + self.extension::() + .expect("No `keystore` associated for the current context!") + .read() + .ecdsa_public_keys(id) + } + + /// Generate an `ecdsa` key for the given key type using an optional `seed` and + /// store it in the keystore. /// - /// Returns `true` when the verification in successful. - #[version(2)] - fn sr25519_verify(sig: &sr25519::Signature, msg: &[u8], pubkey: &sr25519::Public) -> bool { - sr25519::Pair::verify(sig, msg, pubkey) + /// The `seed` needs to be a valid utf8. + /// + /// Returns the public key. + fn ecdsa_generate(&mut self, id: KeyTypeId, seed: Option>) -> ecdsa::Public { + let seed = seed.as_ref().map(|s| std::str::from_utf8(&s).expect("Seed is valid utf8!")); + self.extension::() + .expect("No `keystore` associated for the current context!") + .write() + .ecdsa_generate_new(id, seed) + .expect("`ecdsa_generate` failed") + } + + /// Sign the given `msg` with the `ecdsa` key that corresponds to the given public key and + /// key type in the keystore. + /// + /// Returns the signature. + fn ecdsa_sign( + &mut self, + id: KeyTypeId, + pub_key: &ecdsa::Public, + msg: &[u8], + ) -> Option { + self.extension::() + .expect("No `keystore` associated for the current context!") + .read() + .sign_with(id, &pub_key.into(), msg) + .map(|sig| ecdsa::Signature::from_slice(sig.as_slice())) + .ok() + } + + /// Verify `ecdsa` signature. + /// + /// Returns `true` when the verification was successful. + fn ecdsa_verify( + sig: &ecdsa::Signature, + msg: &[u8], + pub_key: &ecdsa::Public, + ) -> bool { + ecdsa::Pair::verify(sig, msg, pub_key) + } + + /// Register a `ecdsa` signature for batch verification. + /// + /// Batch verification must be enabled by calling [`start_batch_verify`]. + /// If batch verification is not enabled, the signature will be verified immediatley. + /// To get the result of the batch verification, [`finish_batch_verify`] + /// needs to be called. + /// + /// Returns `true` when the verification is either successful or batched. + fn ecdsa_batch_verify( + &mut self, + sig: &ecdsa::Signature, + msg: &[u8], + pub_key: &ecdsa::Public, + ) -> bool { + self.extension::().map( + |extension| extension.push_ecdsa(sig.clone(), pub_key.clone(), msg.to_vec()) + ).unwrap_or_else(|| ecdsa_verify(sig, msg, pub_key)) } /// Verify and recover a SECP256k1 ECDSA signature. @@ -566,7 +742,29 @@ pub trait Hashing { } } +/// Interface that provides functions to access the Offchain DB. +#[runtime_interface] +pub trait OffchainIndex { + /// Write a key value pair to the Offchain DB database in a buffered fashion. + fn set(&mut self, key: &[u8], value: &[u8]) { + self.set_offchain_storage(key, Some(value)); + } + + /// Remove a key and its associated value from the Offchain DB. + fn clear(&mut self, key: &[u8]) { + self.set_offchain_storage(key, None); + } +} + +#[cfg(feature = "std")] +sp_externalities::decl_extension! { + /// The keystore extension to register/retrieve from the externalities. + pub struct VerificationExt(BatchVerifier); +} + /// Interface that provides functions to access the offchain functionality. +/// +/// These functions are being made available to the runtime and are called by the runtime. #[runtime_interface] pub trait Offchain { /// Returns if the local node is a potential validator. @@ -630,6 +828,16 @@ pub trait Offchain { .local_storage_set(kind, key, value) } + /// Remove a value from the local storage. + /// + /// Note this storage is not part of the consensus, it's only accessible by + /// offchain worker tasks running on the same machine. It IS persisted between runs. + fn local_storage_clear(&mut self, kind: StorageKind, key: &[u8]) { + self.extension::() + .expect("local_storage_clear can be called only in the offchain worker context") + .local_storage_clear(kind, key) + } + /// Sets a value in the local storage if it matches current value. /// /// Since multiple offchain workers may be running concurrently, to prevent @@ -789,6 +997,55 @@ pub trait Logging { } } +#[cfg(feature = "std")] +sp_externalities::decl_extension! { + /// Extension to allow running traces in wasm via Proxy + pub struct TracingProxyExt(sp_tracing::proxy::TracingProxy); +} + +/// Interface that provides functions for profiling the runtime. +#[runtime_interface] +pub trait WasmTracing { + /// To create and enter a `tracing` span, using `sp_tracing::proxy` + /// Returns 0 value to indicate that no further traces should be attempted + fn enter_span(&mut self, target: &str, name: &str) -> u64 { + if sp_tracing::wasm_tracing_enabled() { + match self.extension::() { + Some(proxy) => return proxy.enter_span(target, name), + None => { + if self.register_extension(TracingProxyExt(sp_tracing::proxy::TracingProxy::new())).is_ok() { + if let Some(proxy) = self.extension::() { + return proxy.enter_span(target, name); + } + } else { + log::warn!( + target: "tracing", + "Unable to register extension: TracingProxyExt" + ); + } + } + } + } + log::debug!( + target: "tracing", + "Notify to runtime that tracing is disabled." + ); + 0 + } + + /// Exit a `tracing` span, using `sp_tracing::proxy` + fn exit_span(&mut self, id: u64) { + if let Some(proxy) = self.extension::() { + proxy.exit_span(id) + } else { + log::warn!( + target: "tracing", + "Unable to load extension: TracingProxyExt" + ); + } + } +} + /// Wasm-only interface that provides functions for interacting with the sandbox. #[runtime_interface(wasm_only)] pub trait Sandbox { @@ -933,7 +1190,9 @@ pub type TestExternalities = sp_state_machine::TestExternalities b"bar".to_vec()], - children: map![], + children_default: map![], }); t.execute_with(|| { @@ -976,7 +1237,7 @@ mod tests { fn read_storage_works() { let mut t = BasicExternalities::new(Storage { top: map![b":test".to_vec() => b"\x0b\0\0\0Hello world".to_vec()], - children: map![], + children_default: map![], }); t.execute_with(|| { @@ -998,7 +1259,7 @@ mod tests { b":abc".to_vec() => b"\x0b\0\0\0Hello world".to_vec(), b":abdd".to_vec() => b"\x0b\0\0\0Hello world".to_vec() ], - children: map![], + children_default: map![], }); t.execute_with(|| { @@ -1010,4 +1271,132 @@ mod tests { assert!(storage::get(b":abc").is_none()); }); } + + #[test] + fn batch_verify_start_finish_works() { + let mut ext = BasicExternalities::with_tasks_executor(); + ext.execute_with(|| { + crypto::start_batch_verify(); + }); + + assert!(ext.extensions().get_mut(TypeId::of::()).is_some()); + + ext.execute_with(|| { + assert!(crypto::finish_batch_verify()); + }); + + assert!(ext.extensions().get_mut(TypeId::of::()).is_none()); + } + + #[test] + fn long_sr25519_batching() { + let mut ext = BasicExternalities::with_tasks_executor(); + ext.execute_with(|| { + let pair = sr25519::Pair::generate_with_phrase(None).0; + crypto::start_batch_verify(); + for it in 0..70 { + let msg = format!("Schnorrkel {}!", it); + let signature = pair.sign(msg.as_bytes()); + crypto::sr25519_batch_verify(&signature, msg.as_bytes(), &pair.public()); + } + + // push invlaid + crypto::sr25519_batch_verify( + &Default::default(), + &Vec::new(), + &Default::default(), + ); + assert!(!crypto::finish_batch_verify()); + + crypto::start_batch_verify(); + for it in 0..70 { + let msg = format!("Schnorrkel {}!", it); + let signature = pair.sign(msg.as_bytes()); + crypto::sr25519_batch_verify(&signature, msg.as_bytes(), &pair.public()); + } + assert!(crypto::finish_batch_verify()); + }); + } + + #[test] + fn batching_works() { + let mut ext = BasicExternalities::with_tasks_executor(); + ext.execute_with(|| { + // invalid ed25519 signature + crypto::start_batch_verify(); + crypto::ed25519_batch_verify( + &Default::default(), + &Vec::new(), + &Default::default(), + ); + assert!(!crypto::finish_batch_verify()); + + // 2 valid ed25519 signatures + crypto::start_batch_verify(); + + let pair = ed25519::Pair::generate_with_phrase(None).0; + let msg = b"Important message"; + let signature = pair.sign(msg); + crypto::ed25519_batch_verify(&signature, msg, &pair.public()); + + let pair = ed25519::Pair::generate_with_phrase(None).0; + let msg = b"Even more important message"; + let signature = pair.sign(msg); + crypto::ed25519_batch_verify(&signature, msg, &pair.public()); + + assert!(crypto::finish_batch_verify()); + + // 1 valid, 1 invalid ed25519 signature + crypto::start_batch_verify(); + + let pair = ed25519::Pair::generate_with_phrase(None).0; + let msg = b"Important message"; + let signature = pair.sign(msg); + crypto::ed25519_batch_verify(&signature, msg, &pair.public()); + + crypto::ed25519_batch_verify( + &Default::default(), + &Vec::new(), + &Default::default(), + ); + + assert!(!crypto::finish_batch_verify()); + + // 1 valid ed25519, 2 valid sr25519 + crypto::start_batch_verify(); + + let pair = ed25519::Pair::generate_with_phrase(None).0; + let msg = b"Ed25519 batching"; + let signature = pair.sign(msg); + crypto::ed25519_batch_verify(&signature, msg, &pair.public()); + + let pair = sr25519::Pair::generate_with_phrase(None).0; + let msg = b"Schnorrkel rules"; + let signature = pair.sign(msg); + crypto::sr25519_batch_verify(&signature, msg, &pair.public()); + + let pair = sr25519::Pair::generate_with_phrase(None).0; + let msg = b"Schnorrkel batches!"; + let signature = pair.sign(msg); + crypto::sr25519_batch_verify(&signature, msg, &pair.public()); + + assert!(crypto::finish_batch_verify()); + + // 1 valid sr25519, 1 invalid sr25519 + crypto::start_batch_verify(); + + let pair = sr25519::Pair::generate_with_phrase(None).0; + let msg = b"Schnorrkcel!"; + let signature = pair.sign(msg); + crypto::sr25519_batch_verify(&signature, msg, &pair.public()); + + crypto::sr25519_batch_verify( + &Default::default(), + &Vec::new(), + &Default::default(), + ); + + assert!(!crypto::finish_batch_verify()); + }); + } } diff --git a/primitives/keyring/Cargo.toml b/primitives/keyring/Cargo.toml index 0764146250446c367c0c0bfbd53147e0a9dd4134..abd7f3d3d548574ed7c998ac932303f0c4aecf0d 100644 --- a/primitives/keyring/Cargo.toml +++ b/primitives/keyring/Cargo.toml @@ -1,20 +1,20 @@ [package] name = "sp-keyring" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Keyring support code for the runtime. A set of test accounts." documentation = "https://docs.rs/sp-keyring" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-core = { version = "2.0.0-alpha.5", path = "../core" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../runtime" } +sp-core = { version = "2.0.0-rc4", path = "../core" } +sp-runtime = { version = "2.0.0-rc4", path = "../runtime" } lazy_static = "1.4.0" strum = { version = "0.16.0", features = ["derive"] } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/keyring/src/ed25519.rs b/primitives/keyring/src/ed25519.rs index 197b9ded8794b2cc93418af09572c2d0dae9e24f..17882027387c538e4ab4b9a96312ba32488984d5 100644 --- a/primitives/keyring/src/ed25519.rs +++ b/primitives/keyring/src/ed25519.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Support code for the runtime. A set of test accounts. diff --git a/primitives/keyring/src/lib.rs b/primitives/keyring/src/lib.rs index 18f8cdf2c4ab9c8ce8e97e9f1dfe6a315460a7dc..55ed14d294f1dc7cb82d8e516d14bbca4c08f03b 100644 --- a/primitives/keyring/src/lib.rs +++ b/primitives/keyring/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Support code for the runtime. A set of test accounts. diff --git a/primitives/keyring/src/sr25519.rs b/primitives/keyring/src/sr25519.rs index 476997f2db79b00b79b3214bd8f20f6d49898ffb..80397f0de9fc12d42eae2776b484651954270a90 100644 --- a/primitives/keyring/src/sr25519.rs +++ b/primitives/keyring/src/sr25519.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Support code for the runtime. A set of test accounts. diff --git a/primitives/phragmen/Cargo.toml b/primitives/npos-elections/Cargo.toml similarity index 51% rename from primitives/phragmen/Cargo.toml rename to primitives/npos-elections/Cargo.toml index f5d26e8a40b80427360bfd56915a540d84d584bc..0a55a3e8954eef3b604aa9033f6b9f48cc8ba333 100644 --- a/primitives/phragmen/Cargo.toml +++ b/primitives/npos-elections/Cargo.toml @@ -1,24 +1,27 @@ [package] -name = "sp-phragmen" -version = "2.0.0-alpha.5" +name = "sp-npos-elections" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" -description = "Phragmen primitives" +description = "NPoS election algorithm primitives" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } serde = { version = "1.0.101", optional = true, features = ["derive"] } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../std" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../primitives/runtime" } -sp-phragmen-compact = { version = "2.0.0-alpha.4", path = "./compact" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../std" } +sp-npos-elections-compact = { version = "2.0.0-rc4", path = "./compact" } +sp-arithmetic = { version = "2.0.0-rc4", default-features = false, path = "../arithmetic" } [dev-dependencies] -substrate-test-utils = { version = "2.0.0-alpha.5", path = "../../test-utils" } +substrate-test-utils = { version = "2.0.0-rc4", path = "../../test-utils" } rand = "0.7.3" -sp-phragmen = { path = "." } +sp-runtime = { version = "2.0.0-rc4", path = "../../primitives/runtime" } [features] default = ["std"] @@ -27,8 +30,5 @@ std = [ "codec/std", "serde", "sp-std/std", - "sp-runtime/std", + "sp-arithmetic/std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/npos-elections/benches/phragmen.rs b/primitives/npos-elections/benches/phragmen.rs new file mode 100644 index 0000000000000000000000000000000000000000..e2385665bf0655ef422db11aa96baf05ffa4ed4c --- /dev/null +++ b/primitives/npos-elections/benches/phragmen.rs @@ -0,0 +1,218 @@ +// Copyright 2019-2020 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}; +use sp_npos_elections::{ElectionResult, VoteWeight}; + +use std::collections::BTreeMap; +use sp_runtime::{Perbill, PerThing, traits::Zero}; +use sp_npos_elections::{ + balance_solution, assignment_ratio_to_staked, build_support_map, to_without_backing, VoteWeight, + ExtendedBalance, Assignment, StakedAssignment, IdentifierT, assignment_ratio_to_staked, + seq_phragmen, +}; + +// default params. Each will be scaled by the benchmarks individually. +const VALIDATORS: u64 = 100; +const NOMINATORS: u64 = 1_000; +const EDGES: u64 = 2; +const TO_ELECT: usize = 10; +const STAKE: VoteWeight = 1000; + +const PREFIX: AccountId = 1000_000; + +type AccountId = u64; + +mod bench_closure_and_slice { + use super::*; + + fn random_assignment() -> Assignment { + let mut rng = rand::thread_rng(); + let who = rng.next_u32(); + let distribution = (0..5) + .map(|x| (x + rng.next_u32(), Perbill::from_percent(rng.next_u32() % 100))) + .collect::>(); + Assignment { who, distribution } + } + + /// Converts a vector of ratio assignments into ones with absolute budget value. + pub fn assignment_ratio_to_staked_slice( + ratio: Vec>, + stakes: &[VoteWeight], + ) -> Vec> + where + T: sp_std::ops::Mul, + ExtendedBalance: From<::Inner>, + { + ratio + .into_iter() + .zip(stakes.into_iter().map(|x| *x as ExtendedBalance)) + .map(|(a, stake)| { + a.into_staked(stake.into(), true) + }) + .collect() + } + + #[bench] + fn closure(b: &mut Bencher) { + let assignments = (0..1000).map(|_| random_assignment()).collect::>>(); + let stake_of = |x: &u32| -> VoteWeight { (x * 2 + 100).into() }; + + // each have one clone of assignments + b.iter(|| assignment_ratio_to_staked(assignments.clone(), stake_of)); + } + + #[bench] + fn slice(b: &mut Bencher) { + let assignments = (0..1000).map(|_| random_assignment()).collect::>>(); + let stake_of = |x: &u32| -> VoteWeight { (x * 2 + 100).into() }; + + b.iter(|| { + let local = assignments.clone(); + let stakes = local.iter().map(|x| stake_of(&x.who)).collect::>(); + assignment_ratio_to_staked_slice(local, stakes.as_ref()); + }); + } +} + +fn do_phragmen( + b: &mut Bencher, + num_validators: u64, + num_nominators: u64, + to_elect: usize, + edge_per_voter: u64, + eq_iters: usize, + eq_tolerance: u128, +) { + assert!(num_validators > edge_per_voter); + let rr = |a, b| rand::thread_rng().gen_range(a as usize, b as usize) as VoteWeight; + + let mut candidates = Vec::with_capacity(num_validators as usize); + let mut stake_of_tree: BTreeMap = BTreeMap::new(); + + (1 ..= num_validators).for_each(|acc| { + candidates.push(acc); + stake_of_tree.insert(acc, STAKE + rr(10, 1000)); + }); + + let mut voters = Vec::with_capacity(num_nominators as usize); + (PREFIX ..= (PREFIX + num_nominators)).for_each(|acc| { + // all possible targets + let mut all_targets = candidates.clone(); + // we remove and pop into `targets` `edge_per_voter` times. + let targets = (0 .. edge_per_voter).map(|_| { + all_targets.remove(rr(0, all_targets.len()) as usize) + }) + .collect::>(); + + let stake = STAKE + rr(10, 1000); + stake_of_tree.insert(acc, stake); + voters.push((acc, stake, targets)); + }); + + b.iter(|| { + let ElectionResult { winners, assignments } = seq_phragmen::( + to_elect, + Zero::zero(), + candidates.clone(), + voters.clone(), + ).unwrap(); + + let stake_of = |who: &AccountId| -> VoteWeight { + *stake_of_tree.get(who).unwrap() + }; + + // Do the benchmarking with balancing. + if eq_iters > 0 { + let staked = assignment_ratio_to_staked(assignments, &stake_of); + let winners = to_without_backing(winners); + let mut support = build_support_map(winners.as_ref(), staked.as_ref()).0; + + balance_solution( + staked.into_iter().map(|a| (a.clone(), stake_of(&a.who))).collect(), + &mut support, + 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!( + "++ 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/primitives/phragmen/compact/Cargo.toml b/primitives/npos-elections/compact/Cargo.toml similarity index 76% rename from primitives/phragmen/compact/Cargo.toml rename to primitives/npos-elections/compact/Cargo.toml index 56b4520c54277825b7dc340b8fef7a9f132ca43a..61d1990a3a5bcdc0d33b6fd99d60088b5f3b1a85 100644 --- a/primitives/phragmen/compact/Cargo.toml +++ b/primitives/npos-elections/compact/Cargo.toml @@ -1,12 +1,15 @@ [package] -name = "sp-phragmen-compact" -version = "2.0.0-dev" +name = "sp-npos-elections-compact" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" -description = "Phragmen Compact Solution" +description = "NPoS Compact Solution Type" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] [lib] proc-macro = true @@ -16,6 +19,3 @@ syn = { version = "1.0.7", features = ["full", "visit"] } quote = "1.0" proc-macro2 = "1.0.6" proc-macro-crate = "0.1.4" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/phragmen/compact/src/assignment.rs b/primitives/npos-elections/compact/src/assignment.rs similarity index 80% rename from primitives/phragmen/compact/src/assignment.rs rename to primitives/npos-elections/compact/src/assignment.rs index 587e482ccb22096182404dd04823c05749d4575b..96c68ece92a19acb028d238962dd029f6067d0c4 100644 --- a/primitives/phragmen/compact/src/assignment.rs +++ b/primitives/npos-elections/compact/src/assignment.rs @@ -1,24 +1,25 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Code generation for the ratio assignment type. use crate::field_name_for; -use proc_macro2::{TokenStream as TokenStream2}; -use syn::{GenericArgument}; +use proc_macro2::TokenStream as TokenStream2; +use syn::GenericArgument; use quote::quote; fn from_impl(count: usize) -> TokenStream2 { @@ -56,7 +57,13 @@ fn from_impl(count: usize) -> TokenStream2 { let last = quote!(index_of_target(&distribution[#last_index].0).ok_or(_phragmen::Error::CompactInvalidIndex)?); quote!( - #c => compact.#field_name.push((index_of_voter(&who).ok_or(_phragmen::Error::CompactInvalidIndex)?, [#inner], #last)), + #c => compact.#field_name.push( + ( + index_of_voter(&who).ok_or(_phragmen::Error::CompactInvalidIndex)?, + [#inner], + #last, + ) + ), ) }).collect::(); @@ -91,7 +98,7 @@ fn into_impl(count: usize) -> TokenStream2 { } // defensive only. Since Percent doesn't have `Sub`. - let p2 = _phragmen::sp_runtime::traits::Saturating::saturating_sub( + let p2 = _phragmen::sp_arithmetic::traits::Saturating::saturating_sub( Accuracy::one(), p1, ); @@ -115,7 +122,7 @@ fn into_impl(count: usize) -> TokenStream2 { let mut inners_parsed = inners .iter() .map(|(ref t_idx, p)| { - sum = _phragmen::sp_runtime::traits::Saturating::saturating_add(sum, *p); + sum = _phragmen::sp_arithmetic::traits::Saturating::saturating_add(sum, *p); let target = target_at(*t_idx).ok_or(_phragmen::Error::CompactInvalidIndex)?; Ok((target, *p)) }) @@ -126,7 +133,7 @@ fn into_impl(count: usize) -> TokenStream2 { } // defensive only. Since Percent doesn't have `Sub`. - let p_last = _phragmen::sp_runtime::traits::Saturating::saturating_sub( + let p_last = _phragmen::sp_arithmetic::traits::Saturating::saturating_sub( Accuracy::one(), sum, ); @@ -163,7 +170,7 @@ pub(crate) fn assignment( #voter_type: _phragmen::codec::Codec + Default + Copy, #target_type: _phragmen::codec::Codec + Default + Copy, Accuracy: - _phragmen::codec::Codec + Default + Clone + _phragmen::sp_runtime::PerThing + + _phragmen::codec::Codec + Default + Clone + _phragmen::sp_arithmetic::PerThing + PartialOrd, > #ident<#voter_type, #target_type, Accuracy> diff --git a/primitives/phragmen/compact/src/lib.rs b/primitives/npos-elections/compact/src/lib.rs similarity index 68% rename from primitives/phragmen/compact/src/lib.rs rename to primitives/npos-elections/compact/src/lib.rs index 114aeaeb32ed92ae4badbb59d38dc77cbcf309e7..1b88ff653108157f5845a3773dffe77922efabdd 100644 --- a/primitives/phragmen/compact/src/lib.rs +++ b/primitives/npos-elections/compact/src/lib.rs @@ -1,20 +1,21 @@ -// Copyright 2020 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. +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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. +// 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. -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Proc macro for phragmen compact assignment. +//! Proc macro for a npos compact assignment. use proc_macro::TokenStream; use proc_macro2::{TokenStream as TokenStream2, Span, Ident}; @@ -28,7 +29,7 @@ mod staked; // prefix used for struct fields in compact. const PREFIX: &'static str = "votes"; -/// Generates a struct to store the phragmen assignments in a compact way. The struct can only store +/// Generates a struct to store the election assignments in a compact way. The struct can only store /// distributions up to the given input count. The given count must be greater than 2. /// /// ```ignore @@ -157,14 +158,31 @@ fn struct_def( ) }).collect::(); + + let len_impl = (1..=count).map(|c| { + let field_name = field_name_for(c); + quote!( + all_len = all_len.saturating_add(self.#field_name.len()); + ) + }).collect::(); + + let edge_count_impl = (1..count).map(|c| { + let field_name = field_name_for(c); + quote!( + all_edges = all_edges.saturating_add( + self.#field_name.len().saturating_mul(#c as usize) + ); + ) + }).collect::(); + Ok(quote! ( - /// A struct to encode a Phragmen assignment in a compact way. + /// A struct to encode a election assignment in a compact way. #[derive( Default, PartialEq, Eq, Clone, - _phragmen::sp_runtime::RuntimeDebug, + Debug, _phragmen::codec::Encode, _phragmen::codec::Decode, )] @@ -180,21 +198,45 @@ fn struct_def( { const LIMIT: usize = #count; } + + impl<#voter_type, #target_type, #weight_type> #ident<#voter_type, #target_type, #weight_type> { + /// Get the length of all the assignments that this type is encoding. This is basically + /// the same as the number of assignments, or the number of voters in total. + pub fn len(&self) -> usize { + let mut all_len = 0usize; + #len_impl + all_len + } + + /// Get the total count of edges. + pub fn edge_count(&self) -> usize { + let mut all_edges = 0usize; + #edge_count_impl + all_edges + } + + /// Get the average edge count. + pub fn average_edge_count(&self) -> usize { + self.edge_count().checked_div(self.len()).unwrap_or(0) + } + } )) } fn imports() -> Result { - let sp_phragmen_imports = match crate_name("sp-phragmen") { - Ok(sp_phragmen) => { - let ident = syn::Ident::new(&sp_phragmen, Span::call_site()); - quote!( extern crate #ident as _phragmen; ) + if std::env::var("CARGO_PKG_NAME").unwrap() == "sp-npos-elections" { + Ok(quote! { + use crate as _phragmen; + }) + } else { + match crate_name("sp-npos-elections") { + Ok(sp_npos_elections) => { + let ident = syn::Ident::new(&sp_npos_elections, Span::call_site()); + Ok(quote!( extern crate #ident as _phragmen; )) + }, + Err(e) => Err(syn::Error::new(Span::call_site(), &e)), } - Err(e) => return Err(syn::Error::new(Span::call_site(), &e)), - }; - - Ok(quote!( - #sp_phragmen_imports - )) + } } struct CompactSolutionDef { diff --git a/primitives/phragmen/compact/src/staked.rs b/primitives/npos-elections/compact/src/staked.rs similarity index 84% rename from primitives/phragmen/compact/src/staked.rs rename to primitives/npos-elections/compact/src/staked.rs index a7cf853f17086651ef4be37dcf2538cdce936dc6..e2680e18b6326964531737ce8235dae0bde65570 100644 --- a/primitives/phragmen/compact/src/staked.rs +++ b/primitives/npos-elections/compact/src/staked.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Code generation for the staked assignment type. @@ -56,7 +57,9 @@ fn from_impl(count: usize) -> TokenStream2 { let last = quote!(index_of_target(&distribution[#last_index].0).ok_or(_phragmen::Error::CompactInvalidIndex)?); quote!( - #c => compact.#field_name.push((index_of_voter(&who).ok_or(_phragmen::Error::CompactInvalidIndex)?, [#inner], #last)), + #c => compact.#field_name.push( + (index_of_voter(&who).ok_or(_phragmen::Error::CompactInvalidIndex)?, [#inner], #last) + ), ) }).collect::(); @@ -73,7 +76,7 @@ fn into_impl(count: usize) -> TokenStream2 { quote!( for (voter_index, target_index) in self.#name { let who = voter_at(voter_index).ok_or(_phragmen::Error::CompactInvalidIndex)?; - let all_stake = max_of(&who); + let all_stake: u128 = max_of(&who).into(); assignments.push(_phragmen::StakedAssignment { who, distribution: vec![(target_at(target_index).ok_or(_phragmen::Error::CompactInvalidIndex)?, all_stake)], @@ -87,7 +90,7 @@ fn into_impl(count: usize) -> TokenStream2 { quote!( for (voter_index, (t1_idx, w1), t2_idx) in self.#name { let who = voter_at(voter_index).ok_or(_phragmen::Error::CompactInvalidIndex)?; - let all_stake = max_of(&who); + let all_stake: u128 = max_of(&who).into(); if w1 >= all_stake { return Err(_phragmen::Error::CompactStakeOverflow); @@ -112,7 +115,7 @@ fn into_impl(count: usize) -> TokenStream2 { for (voter_index, inners, t_last_idx) in self.#name { let who = voter_at(voter_index).ok_or(_phragmen::Error::CompactInvalidIndex)?; let mut sum = u128::min_value(); - let all_stake = max_of(&who); + let all_stake: u128 = max_of(&who).into(); let mut inners_parsed = inners .iter() @@ -154,6 +157,7 @@ pub(crate) fn staked( let from_impl = from_impl(count); let into_impl = into_impl(count); + quote!( impl< #voter_type: _phragmen::codec::Codec + Default + Copy, @@ -196,7 +200,7 @@ pub(crate) fn staked( ) -> Result>, _phragmen::Error> where - for<'r> FM: Fn(&'r A) -> u128, + for<'r> FM: Fn(&'r A) -> u64, A: _phragmen::IdentifierT, { let mut assignments: Vec<_phragmen::StakedAssignment> = Default::default(); diff --git a/primitives/npos-elections/fuzzer/.gitignore b/primitives/npos-elections/fuzzer/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..3ebcb104d4a50a19959dc7ff2bc06ee6bb48b31f --- /dev/null +++ b/primitives/npos-elections/fuzzer/.gitignore @@ -0,0 +1,2 @@ +hfuzz_target +hfuzz_workspace diff --git a/primitives/phragmen/fuzzer/Cargo.lock b/primitives/npos-elections/fuzzer/Cargo.lock similarity index 99% rename from primitives/phragmen/fuzzer/Cargo.lock rename to primitives/npos-elections/fuzzer/Cargo.lock index 3ef2a2732424a3ddd412192dc01ac0647c36ffe1..cd172421aeb28f8cddde2902801dfd322aaddd2c 100644 --- a/primitives/phragmen/fuzzer/Cargo.lock +++ b/primitives/npos-elections/fuzzer/Cargo.lock @@ -540,7 +540,7 @@ dependencies = [ [[package]] name = "memory-db" -version = "0.19.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "198831fe8722331a395bc199a5d08efbc197497ef354cb4c77b969c02ffc0fc4" dependencies = [ @@ -1234,20 +1234,20 @@ dependencies = [ ] [[package]] -name = "sp-phragmen" +name = "sp-npos-elections" version = "2.0.0-alpha.3" dependencies = [ "parity-scale-codec", "serde", "sp-core", - "sp-phragmen-compact", + "sp-npos-elections-compact", "sp-runtime", "sp-std", ] [[package]] -name = "sp-phragmen-compact" -version = "2.0.0-dev" +name = "sp-npos-elections-compact" +version = "2.0.0-rc3" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1256,12 +1256,12 @@ dependencies = [ ] [[package]] -name = "sp-phragmen-fuzzer" +name = "sp-npos-elections-fuzzer" version = "2.0.0" dependencies = [ "honggfuzz", "rand 0.7.3", - "sp-phragmen", + "sp-npos-elections", ] [[package]] diff --git a/primitives/npos-elections/fuzzer/Cargo.toml b/primitives/npos-elections/fuzzer/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..b7c7dcab65427b8f4b84754022a3a15f348bf350 --- /dev/null +++ b/primitives/npos-elections/fuzzer/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "sp-npos-elections-fuzzer" +version = "2.0.0-alpha.5" +authors = ["Parity Technologies "] +edition = "2018" +license = "Apache-2.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +description = "Fuzzer for phragmén implementation." +documentation = "https://docs.rs/sp-npos-elections-fuzzer" +publish = false + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +sp-npos-elections = { version = "2.0.0-rc4", path = ".." } +sp-std = { version = "2.0.0-rc4", path = "../../std" } +sp-runtime = { version = "2.0.0-rc4", path = "../../runtime" } +honggfuzz = "0.5" +rand = { version = "0.7.3", features = ["std", "small_rng"] } + +[[bin]] +name = "reduce" +path = "src/reduce.rs" + +[[bin]] +name = "balance_solution" +path = "src/balance_solution.rs" diff --git a/primitives/npos-elections/fuzzer/src/balance_solution.rs b/primitives/npos-elections/fuzzer/src/balance_solution.rs new file mode 100644 index 0000000000000000000000000000000000000000..e1bd3bd0a07dd8d3b149309246737be13d8749e6 --- /dev/null +++ b/primitives/npos-elections/fuzzer/src/balance_solution.rs @@ -0,0 +1,155 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Fuzzing fro the balance_solution algorithm +//! +//! It ensures that any solution which gets equalized will lead into a better or equally scored +//! one. + +mod common; +use common::to_range; +use honggfuzz::fuzz; +use sp_npos_elections::{ + balance_solution, assignment_ratio_to_staked, build_support_map, to_without_backing, seq_phragmen, + ElectionResult, VoteWeight, evaluate_support, is_score_better, +}; +use sp_std::collections::btree_map::BTreeMap; +use sp_runtime::Perbill; +use rand::{self, Rng, SeedableRng, RngCore}; + +type AccountId = u64; + +fn generate_random_phragmen_result( + voter_count: u64, + target_count: u64, + to_elect: usize, + edge_per_voter: u64, + mut rng: impl RngCore, +) -> (ElectionResult, BTreeMap) { + let prefix = 100_000; + // Note, it is important that stakes are always bigger than ed and + let base_stake: u64 = 1_000_000_000; + let ed: u64 = base_stake; + + let mut candidates = Vec::with_capacity(target_count as usize); + let mut stake_of_tree: BTreeMap = BTreeMap::new(); + + (1..=target_count).for_each(|acc| { + candidates.push(acc); + let stake_var = rng.gen_range(ed, 100 * ed); + stake_of_tree.insert(acc, base_stake + stake_var); + }); + + let mut voters = Vec::with_capacity(voter_count as usize); + (prefix ..= (prefix + voter_count)).for_each(|acc| { + // all possible targets + let mut all_targets = candidates.clone(); + // we remove and pop into `targets` `edge_per_voter` times. + let targets = (0..edge_per_voter).map(|_| { + let upper = all_targets.len() - 1; + let idx = rng.gen_range(0, upper); + all_targets.remove(idx) + }) + .collect::>(); + + let stake_var = rng.gen_range(ed, 100 * ed) ; + let stake = base_stake + stake_var; + stake_of_tree.insert(acc, stake); + voters.push((acc, stake, targets)); + }); + + ( + seq_phragmen::( + to_elect, + 0, + candidates, + voters, + ).unwrap(), + stake_of_tree, + ) +} + +fn main() { + loop { + fuzz!(|data: (usize, usize, usize, usize, usize, u64)| { + let ( + mut target_count, + mut voter_count, + mut iterations, + mut edge_per_voter, + mut to_elect, + seed, + ) = data; + let rng = rand::rngs::SmallRng::seed_from_u64(seed); + target_count = to_range(target_count, 50, 2000); + voter_count = to_range(voter_count, 50, 1000); + iterations = to_range(iterations, 1, 20); + to_elect = to_range(to_elect, 25, target_count); + edge_per_voter = to_range(edge_per_voter, 1, target_count); + + println!("++ [{} / {} / {} / {}]", voter_count, target_count, to_elect, iterations); + let (ElectionResult { winners, assignments }, stake_of_tree) = generate_random_phragmen_result( + voter_count as u64, + target_count as u64, + to_elect, + edge_per_voter as u64, + rng, + ); + + let stake_of = |who: &AccountId| -> VoteWeight { + *stake_of_tree.get(who).unwrap() + }; + + let mut staked = assignment_ratio_to_staked(assignments.clone(), &stake_of); + let winners = to_without_backing(winners); + let mut support = build_support_map(winners.as_ref(), staked.as_ref()).0; + + let initial_score = evaluate_support(&support); + if initial_score[0] == 0 { + // such cases cannot be improved by reduce. + return; + } + + let i = balance_solution( + &mut staked, + &mut support, + 10, + iterations, + ); + + let final_score = evaluate_support(&support); + if final_score[0] == initial_score[0] { + // such solutions can only be improved by such a tiny fiction that it is most often + // wrong due to rounding errors. + return; + } + + let enhance = is_score_better(final_score, initial_score, Perbill::zero()); + + println!( + "iter = {} // {:?} -> {:?} [{}]", + i, + initial_score, + final_score, + enhance, + ); + + // if more than one iteration has been done, or they must be equal. + assert!(enhance || initial_score == final_score || i == 0) + }); + } +} diff --git a/primitives/npos-elections/fuzzer/src/common.rs b/primitives/npos-elections/fuzzer/src/common.rs new file mode 100644 index 0000000000000000000000000000000000000000..89fed14cfaeabb55a9658245170105e2304511e8 --- /dev/null +++ b/primitives/npos-elections/fuzzer/src/common.rs @@ -0,0 +1,30 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Common fuzzing utils. + +/// converts x into the range [a, b] in a pseudo-fair way. +pub fn to_range(x: usize, a: usize, b: usize) -> usize { + // does not work correctly if b < 2 * a + assert!(b >= 2 * a); + let collapsed = x % b; + if collapsed >= a { + collapsed + } else { + collapsed + a + } +} diff --git a/primitives/phragmen/fuzzer/src/reduce.rs b/primitives/npos-elections/fuzzer/src/reduce.rs similarity index 61% rename from primitives/phragmen/fuzzer/src/reduce.rs rename to primitives/npos-elections/fuzzer/src/reduce.rs index 4bf08590a149feafae1fc9ab33372c24440377de..d08a440a6291ff18190090d16f0c43f5ffa24707 100644 --- a/primitives/phragmen/fuzzer/src/reduce.rs +++ b/primitives/npos-elections/fuzzer/src/reduce.rs @@ -1,19 +1,26 @@ -// Copyright 2020 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 . - +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Fuzzing for the reduce algorithm. +//! +//! It that reduce always return a new set og edges in which the bound is kept (`edges_after <= m + +//! n,`) and the result must effectively be the same, meaning that the same support map should be +//! computable from both. +//! //! # Running //! //! Run with `cargo hfuzz run reduce`. `honggfuzz`. @@ -24,8 +31,11 @@ //! `cargo hfuzz run-debug reduce hfuzz_workspace/reduce/*.fuzz`. use honggfuzz::fuzz; -use sp_phragmen::{StakedAssignment, ExtendedBalance, build_support_map, reduce}; -use rand::{self, Rng}; + +mod common; +use common::to_range; +use sp_npos_elections::{StakedAssignment, ExtendedBalance, build_support_map, reduce}; +use rand::{self, Rng, SeedableRng, RngCore}; type Balance = u128; type AccountId = u64; @@ -35,15 +45,20 @@ const KSM: Balance = 1_000_000_000_000; fn main() { loop { - fuzz!(|_data: _| { - let (assignments, winners) = generate_random_phragmen_assignment( - rr(100, 1000), - rr(100, 2000), - 8, - 8, - ); + fuzz!(|data: (usize, usize, u64)| { + let (mut voter_count, mut target_count, seed) = data; + let rng = rand::rngs::SmallRng::seed_from_u64(seed); + target_count = to_range(target_count, 100, 1000); + voter_count = to_range(voter_count, 100, 2000); + let (assignments, winners) = generate_random_phragmen_assignment( + voter_count, + target_count, + 8, + 8, + rng + ); reduce_and_compare(&assignments, &winners); - }); + }); } } @@ -52,13 +67,10 @@ fn generate_random_phragmen_assignment( target_count: usize, avg_edge_per_voter: usize, edge_per_voter_var: usize, + mut rng: impl RngCore, ) -> (Vec>, Vec) { - // random in range of (a, b) - let rr_128 = |a: u128, b: u128| -> u128 { rand::thread_rng().gen_range(a, b) }; - // prefix to distinguish the voter and target account ranges. let target_prefix = 1_000_000; - // let target_prefix = 1000; assert!(voter_count < target_prefix); let mut assignments = Vec::with_capacity(voter_count as usize); @@ -70,17 +82,17 @@ fn generate_random_phragmen_assignment( (1..=voter_count).for_each(|acc| { let mut targets_to_chose_from = all_targets.clone(); - let targets_to_chose = if edge_per_voter_var > 0 { rr( + let targets_to_chose = if edge_per_voter_var > 0 { rng.gen_range( avg_edge_per_voter - edge_per_voter_var, avg_edge_per_voter + edge_per_voter_var, ) } else { avg_edge_per_voter }; let distribution = (0..targets_to_chose).map(|_| { - let target = targets_to_chose_from.remove(rr(0, targets_to_chose_from.len())); + let target = targets_to_chose_from.remove(rng.gen_range(0, targets_to_chose_from.len())); if winners.iter().find(|w| **w == target).is_none() { winners.push(target.clone()); } - (target, rr_128(1 * KSM, 100 * KSM)) + (target, rng.gen_range(1 * KSM, 100 * KSM)) }).collect::>(); assignments.push(StakedAssignment { @@ -139,7 +151,3 @@ fn assignment_len(assignments: &[StakedAssignment]) -> u32 { assignments.iter().for_each(|x| x.distribution.iter().for_each(|_| counter += 1)); counter } - -fn rr(a: usize, b: usize) -> usize { - rand::thread_rng().gen_range(a, b) -} diff --git a/primitives/npos-elections/src/helpers.rs b/primitives/npos-elections/src/helpers.rs new file mode 100644 index 0000000000000000000000000000000000000000..063eac70c57fd77325da73c99581532977f315ee --- /dev/null +++ b/primitives/npos-elections/src/helpers.rs @@ -0,0 +1,134 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Helper methods for npos-elections. + +use crate::{Assignment, ExtendedBalance, VoteWeight, IdentifierT, StakedAssignment, WithApprovalOf, Error}; +use sp_arithmetic::{PerThing, InnerOf}; +use sp_std::prelude::*; + +/// Converts a vector of ratio assignments into ones with absolute budget value. +/// +/// Note that this will NOT attempt at normalizing the result. +pub fn assignment_ratio_to_staked( + ratio: Vec>, + stake_of: FS, +) -> Vec> +where + for<'r> FS: Fn(&'r A) -> VoteWeight, + P: sp_std::ops::Mul, + ExtendedBalance: From>, +{ + ratio + .into_iter() + .map(|a| { + let stake = stake_of(&a.who); + a.into_staked(stake.into()) + }) + .collect() +} + +/// Same as [`assignment_ratio_to_staked`] and try and do normalization. +pub fn assignment_ratio_to_staked_normalized( + ratio: Vec>, + stake_of: FS, +) -> Result>, Error> +where + for<'r> FS: Fn(&'r A) -> VoteWeight, + P: sp_std::ops::Mul, + ExtendedBalance: From>, +{ + let mut staked = assignment_ratio_to_staked(ratio, &stake_of); + staked.iter_mut().map(|a| + a.try_normalize(stake_of(&a.who).into()).map_err(|err| Error::ArithmeticError(err)) + ).collect::>()?; + Ok(staked) +} + +/// Converts a vector of staked assignments into ones with ratio values. +/// +/// Note that this will NOT attempt at normalizing the result. +pub fn assignment_staked_to_ratio( + staked: Vec>, +) -> Vec> +where + ExtendedBalance: From>, +{ + staked.into_iter().map(|a| a.into_assignment()).collect() +} + +/// Same as [`assignment_staked_to_ratio`] and try and do normalization. +pub fn assignment_staked_to_ratio_normalized( + staked: Vec>, +) -> Result>, Error> +where + ExtendedBalance: From>, +{ + let mut ratio = staked.into_iter().map(|a| a.into_assignment()).collect::>(); + ratio.iter_mut().map(|a| + a.try_normalize().map_err(|err| Error::ArithmeticError(err)) + ).collect::>()?; + Ok(ratio) +} + +/// consumes a vector of winners with backing stake to just winners. +pub fn to_without_backing(winners: Vec>) -> Vec { + winners.into_iter().map(|(who, _)| who).collect::>() +} + +#[cfg(test)] +mod tests { + use super::*; + use sp_arithmetic::Perbill; + + #[test] + fn into_staked_works() { + let assignments = vec![ + Assignment { + who: 1u32, + distribution: vec![ + (10u32, Perbill::from_fraction(0.5)), + (20, Perbill::from_fraction(0.5)), + ], + }, + Assignment { + who: 2u32, + distribution: vec![ + (10, Perbill::from_fraction(0.33)), + (20, Perbill::from_fraction(0.67)), + ], + }, + ]; + + let stake_of = |_: &u32| -> VoteWeight { 100 }; + let staked = assignment_ratio_to_staked(assignments, stake_of); + + assert_eq!( + staked, + vec![ + StakedAssignment { + who: 1u32, + distribution: vec![(10u32, 50), (20, 50),] + }, + StakedAssignment { + who: 2u32, + distribution: vec![(10u32, 33), (20, 67),] + } + ] + ); + } +} diff --git a/primitives/phragmen/src/lib.rs b/primitives/npos-elections/src/lib.rs similarity index 71% rename from primitives/phragmen/src/lib.rs rename to primitives/npos-elections/src/lib.rs index c0d94a71e1fc209f4db7085bd8fcba0262d66ecd..592ed3b7173504ff8da810dd1c32289912f73c9f 100644 --- a/primitives/phragmen/src/lib.rs +++ b/primitives/npos-elections/src/lib.rs @@ -1,41 +1,39 @@ -// Copyright 2019-2020 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 pallets 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! A set of election algorithms to be used with a substrate runtime, typically within the staking +//! sub-system. Notable implementation include //! -//! 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. +//! - [`seq_phragmen`]: Implements the Phragmén Sequential Method. An un-ranked, relatively fast +//! election method that ensures PJR, but does not provide a constant factor approximation of the +//! maximin problem. +//! - [`balance_solution`]: Implements the star balancing algorithm. This iterative process can +//! increase a solutions score, as described in [`evaluate_support`]. //! -//! 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/ +//! More information can be found at: https://arxiv.org/abs/2004.12990 #![cfg_attr(not(feature = "std"), no_std)] use sp_std::{prelude::*, collections::btree_map::BTreeMap, fmt::Debug, cmp::Ordering, convert::TryFrom}; -use sp_runtime::{helpers_128bit::multiply_by_rational, PerThing, Rational128, RuntimeDebug, SaturatedConversion}; -use sp_runtime::traits::{Zero, Convert, Member, AtLeast32Bit, Saturating, Bounded}; +use sp_arithmetic::{ + PerThing, Rational128, ThresholdOrd, InnerOf, Normalizable, + helpers_128bit::multiply_by_rational, + traits::{Zero, Saturating, Bounded, SaturatedConversion}, +}; #[cfg(test)] mod mock; @@ -60,10 +58,10 @@ pub use helpers::*; #[doc(hidden)] pub use codec; #[doc(hidden)] -pub use sp_runtime; +pub use sp_arithmetic; // re-export the compact solution type. -pub use sp_phragmen_compact::generate_compact_solution_type; +pub use sp_npos_elections_compact::generate_compact_solution_type; /// A trait to limit the number of votes per voter. The generated compact type will implement this. pub trait VotingLimit { @@ -86,26 +84,30 @@ pub enum Error { CompactTargetOverflow, /// One of the index functions returned none. CompactInvalidIndex, + /// An error occurred in some arithmetic operation. + ArithmeticError(&'static str), } -/// 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`. +/// A type which is used in the API of this crate as a numeric weight of a vote, most often the +/// stake of the voter. It is always converted to [`ExtendedBalance`] for computation. +pub type VoteWeight = u64; + +/// A type in which performing operations on vote weights are safe. pub type ExtendedBalance = u128; /// The score of an assignment. This can be computed from the support map via [`evaluate_support`]. -pub type PhragmenScore = [ExtendedBalance; 3]; +pub type ElectionScore = [ExtendedBalance; 3]; + +/// A winner, with their respective approval stake. +pub type WithApprovalOf = (A, ExtendedBalance); /// 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)] +/// A candidate entity for the election. +#[derive(Clone, Default, Debug)] struct Candidate { /// Identifier. who: AccountId, @@ -118,7 +120,7 @@ struct Candidate { } /// A voter entity. -#[derive(Clone, Default, RuntimeDebug)] +#[derive(Clone, Default, Debug)] struct Voter { /// Identifier. who: AccountId, @@ -131,7 +133,7 @@ struct Voter { } /// A candidate being backed by a voter. -#[derive(Clone, Default, RuntimeDebug)] +#[derive(Clone, Default, Debug)] struct Edge { /// Identifier. who: AccountId, @@ -141,30 +143,30 @@ struct Edge { candidate_index: usize, } -/// Final result of the phragmen election. -#[derive(RuntimeDebug)] -pub struct PhragmenResult { +/// Final result of the election. +#[derive(Debug)] +pub struct ElectionResult { /// 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)>, + pub winners: Vec>, /// 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>, } /// A voter's stake assignment among a set of targets, represented as ratios. -#[derive(RuntimeDebug, Clone, Default)] +#[derive(Debug, Clone, Default)] #[cfg_attr(feature = "std", derive(PartialEq, Eq, Encode, Decode))] -pub struct Assignment { - /// Voter's identifier +pub struct Assignment { + /// Voter's identifier. pub who: AccountId, /// The distribution of the voter's stake. - pub distribution: Vec<(AccountId, T)>, + pub distribution: Vec<(AccountId, P)>, } -impl Assignment +impl Assignment where - ExtendedBalance: From<::Inner>, + ExtendedBalance: From>, { /// Convert from a ratio assignment into one with absolute values aka. [`StakedAssignment`]. /// @@ -173,55 +175,54 @@ where /// distribution's sum is exactly equal to the total budget, by adding or subtracting the /// remainder from the last distribution. /// - /// If an edge ratio is [`Bounded::max_value()`], it is dropped. This edge can never mean + /// If an edge ratio is [`Bounded::min_value()`], it is dropped. This edge can never mean /// anything useful. - pub fn into_staked(self, stake: ExtendedBalance, fill: bool) -> StakedAssignment + pub fn into_staked(self, stake: ExtendedBalance) -> StakedAssignment where - T: sp_std::ops::Mul, + P: sp_std::ops::Mul, { - let mut sum: ExtendedBalance = Bounded::min_value(); - let mut distribution = self - .distribution + let distribution = self.distribution .into_iter() .filter_map(|(target, p)| { // if this ratio is zero, then skip it. - if p == Bounded::min_value() { + if p.is_zero() { None } else { // NOTE: this mul impl will always round to the nearest number, so we might both // overflow and underflow. let distribution_stake = p * stake; - // defensive only. We assume that balance cannot exceed extended balance. - sum = sum.saturating_add(distribution_stake); Some((target, distribution_stake)) } }) .collect::>(); - if fill { - // NOTE: we can do this better. - // https://revs.runtime-revolution.com/getting-100-with-rounded-percentages-273ffa70252b - if let Some(leftover) = stake.checked_sub(sum) { - if let Some(last) = distribution.last_mut() { - last.1 = last.1.saturating_add(leftover); - } - } else if let Some(excess) = sum.checked_sub(stake) { - if let Some(last) = distribution.last_mut() { - last.1 = last.1.saturating_sub(excess); - } - } - } - StakedAssignment { who: self.who, distribution, } } + + /// Try and normalize this assignment. + /// + /// If `Ok(())` is returned, then the assignment MUST have been successfully normalized to 100%. + pub fn try_normalize(&mut self) -> Result<(), &'static str> { + self.distribution + .iter() + .map(|(_, p)| *p) + .collect::>() + .normalize(P::one()) + .map(|normalized_ratios| + self.distribution + .iter_mut() + .zip(normalized_ratios) + .for_each(|((_, old), corrected)| { *old = corrected; }) + ) + } } /// A voter's stake assignment among a set of targets, represented as absolute values in the scale /// of [`ExtendedBalance`]. -#[derive(RuntimeDebug, Clone, Default)] +#[derive(Debug, Clone, Default)] #[cfg_attr(feature = "std", derive(PartialEq, Eq, Encode, Decode))] pub struct StakedAssignment { /// Voter's identifier @@ -243,58 +244,68 @@ impl StakedAssignment { /// /// If an edge stake is so small that it cannot be represented in `T`, it is ignored. This edge /// can never be re-created and does not mean anything useful anymore. - pub fn into_assignment(self, fill: bool) -> Assignment + pub fn into_assignment(self) -> Assignment where - ExtendedBalance: From<::Inner>, + ExtendedBalance: From>, + AccountId: IdentifierT, { - let accuracy: u128 = T::ACCURACY.saturated_into(); - let mut sum: u128 = Zero::zero(); - let stake = self.distribution.iter().map(|x| x.1).sum(); - let mut distribution = self - .distribution + let stake = self.total(); + let distribution = self.distribution .into_iter() .filter_map(|(target, w)| { - let per_thing = T::from_rational_approximation(w, stake); + let per_thing = P::from_rational_approximation(w, stake); if per_thing == Bounded::min_value() { None } else { - sum += per_thing.clone().deconstruct().saturated_into(); Some((target, per_thing)) } }) - .collect::>(); - - if fill { - if let Some(leftover) = accuracy.checked_sub(sum) { - if let Some(last) = distribution.last_mut() { - last.1 = last.1.saturating_add( - T::from_parts(leftover.saturated_into()) - ); - } - } else if let Some(excess) = sum.checked_sub(accuracy) { - if let Some(last) = distribution.last_mut() { - last.1 = last.1.saturating_sub( - T::from_parts(excess.saturated_into()) - ); - } - } - } + .collect::>(); Assignment { who: self.who, distribution, } } + + /// Try and normalize this assignment. + /// + /// If `Ok(())` is returned, then the assignment MUST have been successfully normalized to + /// `stake`. + /// + /// NOTE: current implementation of `.normalize` is almost safe to `expect()` upon. The only + /// error case is when the input cannot fit in `T`, or the sum of input cannot fit in `T`. + /// Sadly, both of these are dependent upon the implementation of `VoteLimit`, i.e. the limit + /// of edges per voter which is enforced from upstream. Hence, at this crate, we prefer + /// returning a result and a use the name prefix `try_`. + pub fn try_normalize(&mut self, stake: ExtendedBalance) -> Result<(), &'static str> { + self.distribution + .iter() + .map(|(_, ref weight)| *weight) + .collect::>() + .normalize(stake) + .map(|normalized_weights| + self.distribution + .iter_mut() + .zip(normalized_weights.into_iter()) + .for_each(|((_, weight), corrected)| { *weight = corrected; }) + ) + } + + /// Get the total stake of this assignment (aka voter budget). + pub fn total(&self) -> ExtendedBalance { + self.distribution.iter().fold(Zero::zero(), |a, b| a.saturating_add(b.1)) + } } -/// A structure to demonstrate the phragmen result from the perspective of the candidate, i.e. how +/// A structure to demonstrate the election 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 complements the [`ElectionResult`] and is needed to run the balancing post-processing. /// /// This, at the current version, resembles the `Exposure` defined in the Staking pallet, yet /// they do not necessarily have to be the same. -#[derive(Default, RuntimeDebug)] +#[derive(Default, Debug)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Eq, PartialEq))] pub struct Support { /// Total support. @@ -316,25 +327,20 @@ pub type SupportMap = BTreeMap>; /// `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. /// /// This function does not strip out candidates who do not have any backing stake. It is the /// responsibility of the caller to make sure only those candidates who have a sensible economic /// value are passed in. From the perspective of this function, a candidate can easily be among the /// winner with no backing stake. -pub fn elect( +pub fn seq_phragmen( candidate_count: usize, minimum_candidate_count: usize, initial_candidates: Vec, - initial_voters: Vec<(AccountId, Balance, Vec)>, -) -> Option> where - AccountId: Default + Ord + Member, - Balance: Default + Copy + AtLeast32Bit, - C: Convert + Convert, + initial_voters: Vec<(AccountId, VoteWeight, Vec)>, +) -> Option> where + AccountId: Default + Ord + Clone, R: PerThing, { - let to_votes = |b: Balance| >::convert(b) as ExtendedBalance; - // return structures let mut elected_candidates: Vec<(AccountId, ExtendedBalance)>; let mut assigned: Vec>; @@ -368,21 +374,20 @@ pub fn elect( 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)); + .saturating_add(voter_stake.into()); 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), + budget: voter_stake.into(), 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); @@ -518,13 +523,13 @@ pub fn elect( } } - Some(PhragmenResult { + Some(ElectionResult { winners: elected_candidates, assignments: assigned, }) } -/// Build the support map from the given phragmen result. It maps a flat structure like +/// Build the support map from the given election result. It maps a flat structure like /// /// ```nocompile /// assignments: vec![ @@ -559,7 +564,7 @@ pub fn build_support_map( winners: &[AccountId], assignments: &[StakedAssignment], ) -> (SupportMap, u32) where - AccountId: Default + Ord + Member, + AccountId: Default + Ord + Clone, { let mut errors = 0; // Initialize the support of each candidate. @@ -582,7 +587,7 @@ pub fn build_support_map( (supports, errors) } -/// Evaluate a phragmen result, given the support map. The returned tuple contains: +/// Evaluate a support map. The returned tuple contains: /// /// - Minimum support. This value must be **maximized**. /// - Sum of all supports. This value must be **maximized**. @@ -591,14 +596,14 @@ pub fn build_support_map( /// `O(E)` where `E` is the total number of edges. pub fn evaluate_support( support: &SupportMap, -) -> PhragmenScore { +) -> ElectionScore { let mut min_support = ExtendedBalance::max_value(); let mut sum: ExtendedBalance = Zero::zero(); - // NOTE: this will probably saturate but using big num makes it even slower. We'll have to see. - // This must run on chain.. + // NOTE: The third element might saturate but fine for now since this will run on-chain and need + // to be fast. let mut sum_squared: ExtendedBalance = Zero::zero(); for (_, support) in support.iter() { - sum += support.total; + sum = sum.saturating_add(support.total); let squared = support.total.saturating_mul(support.total); sum_squared = sum_squared.saturating_add(squared); if support.total < min_support { @@ -608,57 +613,65 @@ pub fn evaluate_support( [min_support, sum, sum_squared] } -/// Compares two sets of phragmen scores based on desirability and returns true if `that` is -/// better than `this`. +/// Compares two sets of election scores based on desirability and returns true if `this` is +/// better than `that`. /// -/// Evaluation is done in a lexicographic manner. +/// Evaluation is done in a lexicographic manner, and if each element of `this` is `that * epsilon` +/// greater or less than `that`. /// /// Note that the third component should be minimized. -pub fn is_score_better(this: PhragmenScore, that: PhragmenScore) -> bool { - match that +pub fn is_score_better(this: ElectionScore, that: ElectionScore, epsilon: P) -> bool + where ExtendedBalance: From> +{ + match this .iter() .enumerate() - .map(|(i, e)| e.cmp(&this[i])) - .collect::>() + .map(|(i, e)| ( + e.ge(&that[i]), + e.tcmp(&that[i], epsilon.mul_ceil(that[i])), + )) + .collect::>() .as_slice() { - [Ordering::Greater, _, _] => true, - [Ordering::Equal, Ordering::Greater, _] => true, - [Ordering::Equal, Ordering::Equal, Ordering::Less] => true, + // epsilon better in the score[0], accept. + [(_, Ordering::Greater), _, _] => true, + + // less than epsilon better in score[0], but more than epsilon better in the second. + [(true, Ordering::Equal), (_, Ordering::Greater), _] => true, + + // less than epsilon better in score[0, 1], but more than epsilon better in the third + [(true, Ordering::Equal), (true, Ordering::Equal), (_, Ordering::Less)] => true, + + // anything else is not a good score. _ => false, } } -/// Performs equalize post-processing to the output of the election algorithm. This happens in +/// Performs balancing 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. +/// Returns the number of iterations that were preformed. /// -/// - `assignments`: exactly the same is the output of phragmen. +/// - `assignments`: exactly the same as the output of [`seq_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>, +pub fn balance_solution( + assignments: &mut 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; +) -> usize where AccountId: Ord + Clone { + if iterations == 0 { return 0; } - for StakedAssignment { who, distribution } in assignments.iter_mut() { - let voter_budget = stake_of(&who); - - let diff = do_equalize::<_, _, C>( + let mut i = 0 ; + loop { + let mut max_diff = 0; + for assignment in assignments.iter_mut() { + let voter_budget = assignment.total(); + let StakedAssignment { who, distribution } = assignment; + let diff = do_balancing( who, voter_budget, distribution, @@ -668,28 +681,22 @@ pub fn equalize( if diff > max_diff { max_diff = diff; } } - if max_diff < tolerance { - break; + i += 1; + if max_diff <= tolerance || i >= iterations { + break i; } } } -/// actually perform equalize. same interface is `equalize`. Just called in loops with a check for +/// actually perform balancing. same interface is `balance_solution`. Just called in loops with a check for /// maximum difference. -fn do_equalize( +fn do_balancing( voter: &AccountId, - budget_balance: Balance, + budget: ExtendedBalance, elected_edges: &mut Vec<(AccountId, ExtendedBalance)>, 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); - +) -> ExtendedBalance where AccountId: Ord + Clone { // Nothing to do. This voter had nothing useful. // Defensive only. Assignment list should always be populated. 1 might happen for self vote. if elected_edges.is_empty() || elected_edges.len() == 1 { return 0; } diff --git a/primitives/phragmen/src/mock.rs b/primitives/npos-elections/src/mock.rs similarity index 83% rename from primitives/phragmen/src/mock.rs rename to primitives/npos-elections/src/mock.rs index 31ce3d38c3500ef930d3676a141beabb8694b275..b9c2396b08bb00e39d1851d1d03b2ac83f7fb357 100644 --- a/primitives/phragmen/src/mock.rs +++ b/primitives/npos-elections/src/mock.rs @@ -1,37 +1,28 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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. +// 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. -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Mock file for phragmen. +//! Mock file for npos-elections. #![cfg(test)] -use crate::{elect, PhragmenResult, Assignment}; -use sp_runtime::{ - assert_eq_error_rate, PerThing, - traits::{Convert, Member, SaturatedConversion, Zero, One} -}; +use crate::{seq_phragmen, ElectionResult, Assignment, VoteWeight, ExtendedBalance}; +use sp_arithmetic::{PerThing, traits::{SaturatedConversion, Zero, One}}; use sp_std::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 } -} +use sp_runtime::assert_eq_error_rate; #[derive(Default, Debug)] pub(crate) struct _Candidate { @@ -66,12 +57,11 @@ pub(crate) struct _Support { 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 winners: Vec<(A, ExtendedBalance)>, pub assignments: Vec<(A, Vec<_PhragmenAssignment>)> } @@ -86,10 +76,10 @@ pub(crate) fn elect_float( initial_voters: Vec<(A, Vec)>, stake_of: FS, ) -> Option<_PhragmenResult> where - A: Default + Ord + Member + Copy, - for<'r> FS: Fn(&'r A) -> Balance, + A: Default + Ord + Copy, + for<'r> FS: Fn(&'r A) -> VoteWeight, { - let mut elected_candidates: Vec<(A, Balance)>; + let mut elected_candidates: Vec<(A, ExtendedBalance)>; let mut assigned: Vec<(A, Vec<_PhragmenAssignment>)>; let mut c_idx_cache = BTreeMap::::new(); let num_voters = initial_candidates.len() + initial_voters.len(); @@ -161,7 +151,7 @@ pub(crate) fn elect_float( } } - elected_candidates.push((winner.who.clone(), winner.approval_stake as Balance)); + elected_candidates.push((winner.who.clone(), winner.approval_stake as ExtendedBalance)); } else { break } @@ -195,7 +185,7 @@ pub(crate) fn equalize_float( iterations: usize, stake_of: FS, ) where - for<'r> FS: Fn(&'r A) -> Balance, + for<'r> FS: Fn(&'r A) -> VoteWeight, A: Ord + Clone + std::fmt::Debug, { for _i in 0..iterations { @@ -220,7 +210,7 @@ pub(crate) fn equalize_float( pub(crate) fn do_equalize_float( voter: &A, - budget_balance: Balance, + budget_balance: VoteWeight, elected_edges: &mut Vec<_PhragmenAssignment>, support_map: &mut _SupportMap, tolerance: f64 @@ -310,12 +300,12 @@ pub(crate) fn do_equalize_float( } -pub(crate) fn create_stake_of(stakes: &[(AccountId, Balance)]) - -> Box Balance> +pub(crate) fn create_stake_of(stakes: &[(AccountId, VoteWeight)]) + -> Box VoteWeight> { - let mut storage = BTreeMap::::new(); + 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() }; + let stake_of = move |who: &AccountId| -> VoteWeight { storage.get(who).unwrap().to_owned() }; Box::new(stake_of) } @@ -331,12 +321,12 @@ pub fn check_assignments_sum(assignments: Vec( candidates: Vec, voters: Vec<(AccountId, Vec)>, - stake_of: &Box Balance>, + stake_of: &Box VoteWeight>, to_elect: usize, min_to_elect: usize, ) { // run fixed point code. - let PhragmenResult { winners, assignments } = elect::<_, _, TestCurrencyToVote, Output>( + let ElectionResult { winners, assignments } = seq_phragmen::<_, Output>( to_elect, min_to_elect, candidates.clone(), @@ -352,7 +342,7 @@ pub(crate) fn run_and_compare( &stake_of, ).unwrap(); - assert_eq!(winners, truth_value.winners); + assert_eq!(winners.iter().map(|(x, _)| x).collect::>(), truth_value.winners.iter().map(|(x, _)| x).collect::>()); for Assignment { who, distribution } in assignments.clone() { if let Some(float_assignments) = truth_value.assignments.iter().find(|x| x.0 == who) { @@ -379,7 +369,7 @@ pub(crate) fn build_support_map_float( result: &mut _PhragmenResult, stake_of: FS, ) -> _SupportMap - where for<'r> FS: Fn(&'r AccountId) -> Balance + where for<'r> FS: Fn(&'r AccountId) -> VoteWeight { let mut supports = <_SupportMap>::new(); result.winners diff --git a/primitives/phragmen/src/node.rs b/primitives/npos-elections/src/node.rs similarity index 89% rename from primitives/phragmen/src/node.rs rename to primitives/npos-elections/src/node.rs index 92ef325a348724762f3c92f29849963c1cfe4edb..d18c0e9016b64450606a2c2320d317770c5586f9 100644 --- a/primitives/phragmen/src/node.rs +++ b/primitives/npos-elections/src/node.rs @@ -1,26 +1,26 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! (very) Basic implementation of a graph node used in the reduce algorithm. -use sp_runtime::RuntimeDebug; use sp_std::{cell::RefCell, fmt, prelude::*, rc::Rc}; /// The role that a node can accept. -#[derive(PartialEq, Eq, Ord, PartialOrd, Clone, RuntimeDebug)] +#[derive(PartialEq, Eq, Ord, PartialOrd, Clone, Debug)] pub(crate) enum NodeRole { /// A voter. This is synonym to a nominator in a staking context. Voter, diff --git a/primitives/phragmen/src/reduce.rs b/primitives/npos-elections/src/reduce.rs similarity index 96% rename from primitives/phragmen/src/reduce.rs rename to primitives/npos-elections/src/reduce.rs index 54a71a7ff29aabdf80b35565f4f09c34fec5b808..d0b4afe73dff9e1483dd803cec7a969a078e52d4 100644 --- a/primitives/phragmen/src/reduce.rs +++ b/primitives/npos-elections/src/reduce.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Rust implementation of the Phragmén reduce algorithm. This can be used by any off chain //! application to reduce cycles from the edge assignment, which will result in smaller size. @@ -48,7 +49,7 @@ use crate::node::{Node, NodeId, NodeRef, NodeRole}; use crate::{ExtendedBalance, IdentifierT, StakedAssignment}; -use sp_runtime::traits::{Bounded, Zero}; +use sp_arithmetic::traits::{Bounded, Zero}; use sp_std::{ collections::btree_map::{BTreeMap, Entry::*}, prelude::*, @@ -305,7 +306,7 @@ fn reduce_4(assignments: &mut Vec>) -> u32 { } (false, false) => { // Neither of the edges was removed? impossible. - debug_assert!(false, "Duplicate voter (or other corrupt input)."); + panic!("Duplicate voter (or other corrupt input)."); } } } @@ -639,8 +640,8 @@ fn reduce_all(assignments: &mut Vec>) -> u32 num_changed } -/// Reduce the given [`PhragmenResult`]. This removes redundant edges from without changing the -/// overall backing of any of the elected candidates. +/// Reduce the given [`Vec>`]. This removes redundant edges from +/// without changing the overall backing of any of the elected candidates. /// /// Returns the number of edges removed. /// diff --git a/primitives/phragmen/src/tests.rs b/primitives/npos-elections/src/tests.rs similarity index 65% rename from primitives/phragmen/src/tests.rs rename to primitives/npos-elections/src/tests.rs index e9861ede723cf9f31baf5f6c5d91b79e361b75d9..80c742117d979168cfc825e22ffcccaaa31259de 100644 --- a/primitives/phragmen/src/tests.rs +++ b/primitives/npos-elections/src/tests.rs @@ -1,30 +1,29 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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. +// 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. -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Tests for phragmen. - -#![cfg(test)] +//! Tests for npos-elections. use crate::mock::*; use crate::{ - elect, equalize, build_support_map, is_score_better, - Support, StakedAssignment, Assignment, PhragmenResult, ExtendedBalance, + seq_phragmen, balance_solution, build_support_map, is_score_better, helpers::*, + Support, StakedAssignment, Assignment, ElectionResult, ExtendedBalance, }; use substrate_test_utils::assert_eq_uvec; -use sp_runtime::{Perbill, Permill, Percent, PerU16, traits::Convert}; +use sp_arithmetic::{Perbill, Permill, Percent, PerU16}; #[test] fn float_phragmen_poc_works() { @@ -82,7 +81,7 @@ fn phragmen_poc_works() { ]; let stake_of = create_stake_of(&[(10, 10), (20, 20), (30, 30)]); - let PhragmenResult { winners, assignments } = elect::<_, _, TestCurrencyToVote, Perbill>( + let ElectionResult { winners, assignments } = seq_phragmen::<_, Perbill>( 2, 2, candidates, @@ -110,6 +109,77 @@ fn phragmen_poc_works() { }, ] ); + + let mut staked = assignment_ratio_to_staked(assignments, &stake_of); + let winners = to_without_backing(winners); + let mut support_map = build_support_map::(&winners, &staked).0; + + assert_eq_uvec!( + staked, + vec![ + StakedAssignment { + who: 10u64, + distribution: vec![(2, 10)], + }, + StakedAssignment { + who: 20, + distribution: vec![(3, 20)], + }, + StakedAssignment { + who: 30, + distribution: vec![ + (2, 15), + (3, 15), + ], + }, + ] + ); + + assert_eq!( + *support_map.get(&2).unwrap(), + Support:: { total: 25, voters: vec![(10, 10), (30, 15)] }, + ); + assert_eq!( + *support_map.get(&3).unwrap(), + Support:: { total: 35, voters: vec![(20, 20), (30, 15)] }, + ); + + balance_solution( + &mut staked, + &mut support_map, + 0, + 2, + ); + + assert_eq_uvec!( + staked, + vec![ + StakedAssignment { + who: 10u64, + distribution: vec![(2, 10)], + }, + StakedAssignment { + who: 20, + distribution: vec![(3, 20)], + }, + StakedAssignment { + who: 30, + distribution: vec![ + (2, 20), + (3, 10), + ], + }, + ] + ); + + assert_eq!( + *support_map.get(&2).unwrap(), + Support:: { total: 30, voters: vec![(10, 10), (30, 20)] }, + ); + assert_eq!( + *support_map.get(&3).unwrap(), + Support:: { total: 30, voters: vec![(20, 20), (30, 10)] }, + ); } #[test] @@ -168,11 +238,14 @@ fn phragmen_accuracy_on_large_scale_only_validators() { (5, (u64::max_value() - 2).into()), ]); - let PhragmenResult { winners, assignments } = elect::<_, _, TestCurrencyToVote, Perbill>( + let ElectionResult { winners, assignments } = seq_phragmen::<_, Perbill>( 2, 2, candidates.clone(), - auto_generate_self_voters(&candidates).iter().map(|(ref v, ref vs)| (v.clone(), stake_of(v), vs.clone())).collect::>(), + auto_generate_self_voters(&candidates) + .iter() + .map(|(ref v, ref vs)| (v.clone(), stake_of(v), vs.clone())) + .collect::>(), ).unwrap(); assert_eq_uvec!(winners, vec![(1, 18446744073709551614u128), (5, 18446744073709551613u128)]); @@ -198,7 +271,7 @@ fn phragmen_accuracy_on_large_scale_validators_and_nominators() { (14, u64::max_value().into()), ]); - let PhragmenResult { winners, assignments } = elect::<_, _, TestCurrencyToVote, Perbill>( + let ElectionResult { winners, assignments } = seq_phragmen::<_, Perbill>( 2, 2, candidates, @@ -241,7 +314,7 @@ fn phragmen_accuracy_on_small_scale_self_vote() { (30, 1), ]); - let PhragmenResult { winners, assignments: _ } = elect::<_, _, TestCurrencyToVote, Perbill>( + let ElectionResult { winners, assignments: _ } = seq_phragmen::<_, Perbill>( 3, 3, candidates, @@ -271,7 +344,7 @@ fn phragmen_accuracy_on_small_scale_no_self_vote() { (3, 1), ]); - let PhragmenResult { winners, assignments: _ } = elect::<_, _, TestCurrencyToVote, Perbill>( + let ElectionResult { winners, assignments: _ } = seq_phragmen::<_, Perbill>( 3, 3, candidates, @@ -304,7 +377,7 @@ fn phragmen_large_scale_test() { (50, 990000000000000000), ]); - let PhragmenResult { winners, assignments } = elect::<_, _, TestCurrencyToVote, Perbill>( + let ElectionResult { winners, assignments } = seq_phragmen::<_, Perbill>( 2, 2, candidates, @@ -330,7 +403,7 @@ fn phragmen_large_scale_test_2() { (50, nom_budget.into()), ]); - let PhragmenResult { winners, assignments } = elect::<_, _, TestCurrencyToVote, Perbill>( + let ElectionResult { winners, assignments } = seq_phragmen::<_, Perbill>( 2, 2, candidates, @@ -406,7 +479,7 @@ fn elect_has_no_entry_barrier() { (2, 10), ]); - let PhragmenResult { winners, assignments: _ } = elect::<_, _, TestCurrencyToVote, Perbill>( + let ElectionResult { winners, assignments: _ } = seq_phragmen::<_, Perbill>( 3, 3, candidates, @@ -433,7 +506,7 @@ fn minimum_to_elect_is_respected() { (2, 10), ]); - let maybe_result = elect::<_, _, TestCurrencyToVote, Perbill>( + let maybe_result = seq_phragmen::<_, Perbill>( 10, 10, candidates, @@ -459,7 +532,7 @@ fn self_votes_should_be_kept() { (1, 8), ]); - let result = elect::<_, _, TestCurrencyToVote, Perbill>( + let result = seq_phragmen::<_, Perbill>( 2, 2, candidates, @@ -480,16 +553,11 @@ fn self_votes_should_be_kept() { ], ); - let staked_assignments: Vec> = result.assignments - .into_iter() - .map(|a| { - let stake = >::convert(stake_of(&a.who)) as ExtendedBalance; - a.into_staked(stake, true) - }).collect(); + let mut staked_assignments = assignment_ratio_to_staked(result.assignments, &stake_of); + let winners = to_without_backing(result.winners); - let winners = result.winners.into_iter().map(|(who, _)| who).collect::>(); let (mut supports, _) = build_support_map::( - winners.as_slice(), + &winners, &staked_assignments, ); @@ -503,12 +571,11 @@ fn self_votes_should_be_kept() { &Support { total: 24u128, voters: vec![(20u64, 20u128), (1u64, 4u128)] }, ); - equalize::( - staked_assignments, + balance_solution( + &mut staked_assignments, &mut supports, 0, 2usize, - &stake_of, ); assert_eq!( @@ -521,69 +588,288 @@ fn self_votes_should_be_kept() { ); } -#[test] -fn assignment_convert_works() { - let staked = StakedAssignment { - who: 1 as AccountId, - distribution: vec![ - (20, 100 as Balance), - (30, 25), - ], - }; +mod assignment_convert_normalize { + use super::*; + #[test] + fn assignment_convert_works() { + let staked = StakedAssignment { + who: 1 as AccountId, + distribution: vec![ + (20, 100 as ExtendedBalance), + (30, 25), + ], + }; - let assignment = staked.clone().into_assignment(true); - assert_eq!( - assignment, - Assignment { + let assignment = staked.clone().into_assignment(); + assert_eq!( + assignment, + Assignment { + who: 1, + distribution: vec![ + (20, Perbill::from_percent(80)), + (30, Perbill::from_percent(20)), + ] + } + ); + + assert_eq!( + assignment.into_staked(125), + staked, + ); + } + + #[test] + fn assignment_convert_will_not_normalize() { + assert_eq!( + Assignment { + who: 1, + distribution: vec![ + (2, Perbill::from_percent(33)), + (3, Perbill::from_percent(66)), + ] + }.into_staked(100), + StakedAssignment { + who: 1, + distribution: vec![ + (2, 33), + (3, 66), + // sum is not 100! + ], + }, + ); + + assert_eq!( + StakedAssignment { + who: 1, + distribution: vec![ + (2, 333_333_333_333_333), + (3, 333_333_333_333_333), + (4, 666_666_666_666_333), + ], + }.into_assignment(), + Assignment { + who: 1, + distribution: vec![ + (2, Perbill::from_parts(250000000)), + (3, Perbill::from_parts(250000000)), + (4, Perbill::from_parts(499999999)), + // sum is not 100%! + ] + }, + ) + } + + #[test] + fn assignment_can_normalize() { + let mut a = Assignment { who: 1, distribution: vec![ - (20, Perbill::from_percent(80)), - (30, Perbill::from_percent(20)), + (2, Perbill::from_parts(330000000)), + (3, Perbill::from_parts(660000000)), + // sum is not 100%! ] - } - ); + }; + a.try_normalize().unwrap(); + assert_eq!( + a, + Assignment { + who: 1, + distribution: vec![ + (2, Perbill::from_parts(340000000)), + (3, Perbill::from_parts(660000000)), + ] + }, + ); + } - assert_eq!( - assignment.into_staked(125, true), - staked, - ); + #[test] + fn staked_assignment_can_normalize() { + let mut a = StakedAssignment { + who: 1, + distribution: vec![ + (2, 33), + (3, 66), + ] + }; + a.try_normalize(100).unwrap(); + assert_eq!( + a, + StakedAssignment { + who: 1, + distribution: vec![ + (2, 34), + (3, 66), + ] + }, + ); + } } -#[test] -fn score_comparison_is_lexicographical() { - // only better in the fist parameter, worse in the other two ✅ - assert_eq!( - is_score_better([10, 20, 30], [12, 10, 35]), - true, - ); +mod score { + use super::*; + #[test] + fn score_comparison_is_lexicographical_no_epsilon() { + let epsilon = Perbill::zero(); + // only better in the fist parameter, worse in the other two ✅ + assert_eq!( + is_score_better([12, 10, 35], [10, 20, 30], epsilon), + true, + ); - // worse in the first, better in the other two ❌ - assert_eq!( - is_score_better([10, 20, 30], [9, 30, 10]), - false, - ); + // worse in the first, better in the other two ❌ + assert_eq!( + is_score_better([9, 30, 10], [10, 20, 30], epsilon), + false, + ); - // equal in the first, the second one dictates. - assert_eq!( - is_score_better([10, 20, 30], [10, 25, 40]), - true, - ); + // equal in the first, the second one dictates. + assert_eq!( + is_score_better([10, 25, 40], [10, 20, 30], epsilon), + true, + ); - // equal in the first two, the last one dictates. - assert_eq!( - is_score_better([10, 20, 30], [10, 20, 40]), - false, - ); + // equal in the first two, the last one dictates. + assert_eq!( + is_score_better([10, 20, 40], [10, 20, 30], epsilon), + false, + ); + } + + #[test] + fn score_comparison_with_epsilon() { + let epsilon = Perbill::from_percent(1); + + { + // no more than 1 percent (10) better in the first param. + assert_eq!( + is_score_better([1009, 5000, 100000], [1000, 5000, 100000], epsilon), + false, + ); + + // now equal, still not better. + assert_eq!( + is_score_better([1010, 5000, 100000], [1000, 5000, 100000], epsilon), + false, + ); + + // now it is. + assert_eq!( + is_score_better([1011, 5000, 100000], [1000, 5000, 100000], epsilon), + true, + ); + } + + { + // First score score is epsilon better, but first score is no longer `ge`. Then this is + // still not a good solution. + assert_eq!( + is_score_better([999, 6000, 100000], [1000, 5000, 100000], epsilon), + false, + ); + } + + { + // first score is equal or better, but not epsilon. Then second one is the determinant. + assert_eq!( + is_score_better([1005, 5000, 100000], [1000, 5000, 100000], epsilon), + false, + ); + + assert_eq!( + is_score_better([1005, 5050, 100000], [1000, 5000, 100000], epsilon), + false, + ); + + assert_eq!( + is_score_better([1005, 5051, 100000], [1000, 5000, 100000], epsilon), + true, + ); + } + + { + // first score and second are equal or less than epsilon more, third is determinant. + assert_eq!( + is_score_better([1005, 5025, 100000], [1000, 5000, 100000], epsilon), + false, + ); + + assert_eq!( + is_score_better([1005, 5025, 99_000], [1000, 5000, 100000], epsilon), + false, + ); + + assert_eq!( + is_score_better([1005, 5025, 98_999], [1000, 5000, 100000], epsilon), + true, + ); + } + } + + #[test] + fn score_comparison_large_value() { + // some random value taken from eras in kusama. + let initial = [12488167277027543u128, 5559266368032409496, 118749283262079244270992278287436446]; + // this claim is 0.04090% better in the third component. It should be accepted as better if + // epsilon is smaller than 5/10_0000 + let claim = [12488167277027543u128, 5559266368032409496, 118700736389524721358337889258988054]; + + assert_eq!( + is_score_better( + claim.clone(), + initial.clone(), + Perbill::from_rational_approximation(1u32, 10_000), + ), + true, + ); + + assert_eq!( + is_score_better( + claim.clone(), + initial.clone(), + Perbill::from_rational_approximation(2u32, 10_000), + ), + true, + ); + + assert_eq!( + is_score_better( + claim.clone(), + initial.clone(), + Perbill::from_rational_approximation(3u32, 10_000), + ), + true, + ); + + assert_eq!( + is_score_better( + claim.clone(), + initial.clone(), + Perbill::from_rational_approximation(4u32, 10_000), + ), + true, + ); + + assert_eq!( + is_score_better( + claim.clone(), + initial.clone(), + Perbill::from_rational_approximation(5u32, 10_000), + ), + false, + ); + } } mod compact { use codec::{Decode, Encode}; - use crate::generate_compact_solution_type; - use super::{AccountId, Balance}; - // these need to come from the same dev-dependency `sp-phragmen`, not from the crate. - use sp_phragmen::{Assignment, StakedAssignment, Error as PhragmenError}; + use super::AccountId; + // these need to come from the same dev-dependency `sp-npos-elections`, not from the crate. + use crate::{ + generate_compact_solution_type, VoteWeight, Assignment, StakedAssignment, + Error as PhragmenError, ExtendedBalance, + }; use sp_std::{convert::{TryInto, TryFrom}, fmt::Debug}; - use sp_runtime::Percent; + use sp_arithmetic::Percent; type Accuracy = Percent; @@ -606,6 +892,8 @@ mod compact { compact, Decode::decode(&mut &encoded[..]).unwrap(), ); + assert_eq!(compact.len(), 4); + assert_eq!(compact.edge_count(), 2 + 4); } fn basic_ratio_test_with() where @@ -681,6 +969,13 @@ mod compact { target_index, ).unwrap(); + // basically number of assignments that it is encoding. + assert_eq!(compacted.len(), assignments.len()); + assert_eq!( + compacted.edge_count(), + assignments.iter().fold(0, |a, b| a + b.distribution.len()), + ); + assert_eq!( compacted, TestCompact { @@ -736,7 +1031,7 @@ mod compact { let assignments = vec![ StakedAssignment { who: 2 as AccountId, - distribution: vec![(20, 100 as Balance)] + distribution: vec![(20, 100 as ExtendedBalance)] }, StakedAssignment { who: 4, @@ -773,11 +1068,16 @@ mod compact { targets.iter().position(|x| x == a).map(TryInto::try_into).unwrap().ok() }; - let compacted = >::from_staked( + let compacted = >::from_staked( assignments.clone(), voter_index, target_index, ).unwrap(); + assert_eq!(compacted.len(), assignments.len()); + assert_eq!( + compacted.edge_count(), + assignments.iter().fold(0, |a, b| a + b.distribution.len()), + ); assert_eq!( compacted, @@ -794,7 +1094,7 @@ mod compact { } ); - let max_of_fn = |_: &AccountId| -> Balance { 100u128 }; + let max_of_fn = |_: &AccountId| -> VoteWeight { 100 }; let voter_at = |a: u16| -> Option { voters.get(a as usize).cloned() }; let target_at = |a: u16| -> Option { targets.get(a as usize).cloned() }; @@ -812,14 +1112,14 @@ mod compact { fn compact_into_stake_must_report_overflow() { // The last edge which is computed from the rest should ALWAYS be positive. // in votes2 - let compact = TestCompact:: { + let compact = TestCompact:: { votes1: Default::default(), votes2: vec![(0, (1, 10), 2)], ..Default::default() }; let entity_at = |a: u16| -> Option { Some(a as AccountId) }; - let max_of = |_: &AccountId| -> Balance { 5 }; + let max_of = |_: &AccountId| -> VoteWeight { 5 }; assert_eq!( compact.into_staked(&max_of, &entity_at, &entity_at).unwrap_err(), @@ -827,7 +1127,7 @@ mod compact { ); // in votes3 onwards - let compact = TestCompact:: { + let compact = TestCompact:: { votes1: Default::default(), votes2: Default::default(), votes3: vec![(0, [(1, 7), (2, 8)], 3)], @@ -840,7 +1140,7 @@ mod compact { ); // Also if equal - let compact = TestCompact:: { + let compact = TestCompact:: { votes1: Default::default(), votes2: Default::default(), // 5 is total, we cannot leave none for 30 here. @@ -889,13 +1189,13 @@ mod compact { let assignments = vec![ StakedAssignment { who: 1 as AccountId, - distribution: (10..26).map(|i| (i as AccountId, i as Balance)).collect::>(), + distribution: (10..26).map(|i| (i as AccountId, i as ExtendedBalance)).collect::>(), }, ]; let entity_index = |a: &AccountId| -> Option { Some(*a as u16) }; - let compacted = >::from_staked( + let compacted = >::from_staked( assignments.clone(), entity_index, entity_index, @@ -906,11 +1206,11 @@ mod compact { let assignments = vec![ StakedAssignment { who: 1 as AccountId, - distribution: (10..27).map(|i| (i as AccountId, i as Balance)).collect::>(), + distribution: (10..27).map(|i| (i as AccountId, i as ExtendedBalance)).collect::>(), }, ]; - let compacted = >::from_staked( + let compacted = >::from_staked( assignments.clone(), entity_index, entity_index, @@ -948,7 +1248,7 @@ mod compact { let assignments = vec![ StakedAssignment { who: 1 as AccountId, - distribution: vec![(10, 100 as Balance), (11, 100)] + distribution: vec![(10, 100 as ExtendedBalance), (11, 100)] }, StakedAssignment { who: 2, @@ -963,7 +1263,7 @@ mod compact { targets.iter().position(|x| x == a).map(TryInto::try_into).unwrap().ok() }; - let compacted = >::from_staked( + let compacted = >::from_staked( assignments.clone(), voter_index, target_index, diff --git a/primitives/offchain/Cargo.toml b/primitives/offchain/Cargo.toml index 66febccd59b9b6ac5a9111cfbd4fcb8027e8113a..44eb1bc0e10ce42206f9520fe82bc6bd6343a854 100644 --- a/primitives/offchain/Cargo.toml +++ b/primitives/offchain/Cargo.toml @@ -1,23 +1,28 @@ [package] description = "Substrate offchain workers primitives" name = "sp-offchain" -version = "2.0.0-alpha.5" -license = "GPL-3.0" +version = "2.0.0-rc4" +license = "Apache-2.0" authors = ["Parity Technologies "] edition = "2018" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-api = { version = "2.0.0-alpha.5", default-features = false, path = "../api" } -sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../runtime" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../core" } +sp-api = { version = "2.0.0-rc4", default-features = false, path = "../api" } +sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../runtime" } + +[dev-dependencies] +sp-state-machine = { version = "0.8.0-rc4", default-features = false, path = "../state-machine" } [features] default = ["std"] std = [ + "sp-core/std", "sp-api/std", "sp-runtime/std" ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/offchain/src/lib.rs b/primitives/offchain/src/lib.rs index ae02fed4967685e7cb419d49064a63634497a749..fa5ab808df8a107f7033ccb73aa0a92b832e15fb 100644 --- a/primitives/offchain/src/lib.rs +++ b/primitives/offchain/src/lib.rs @@ -1,26 +1,27 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The Offchain Worker runtime api primitives. #![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs)] -/// Local Storage Prefix used by the Offchain Worker API to -pub const STORAGE_PREFIX: &[u8] = b"storage"; +/// Re-export of parent module scope storage prefix. +pub use sp_core::offchain::STORAGE_PREFIX as STORAGE_PREFIX; sp_api::decl_runtime_apis! { /// The offchain worker api. diff --git a/primitives/panic-handler/Cargo.toml b/primitives/panic-handler/Cargo.toml index 169443f6c42cee9f40de81baeb04fe5d49a8ba76..f350d317a031331aceb940a57c77a6ce661e7d5d 100644 --- a/primitives/panic-handler/Cargo.toml +++ b/primitives/panic-handler/Cargo.toml @@ -1,17 +1,17 @@ [package] name = "sp-panic-handler" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Custom panic hook with bug report link" documentation = "https://docs.rs/sp-panic-handler" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] backtrace = "0.3.38" log = "0.4.8" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/panic-handler/src/lib.rs b/primitives/panic-handler/src/lib.rs index c0f70d9d145c893dc38700e362c224a132cff808..2ac30dd636914464b8c6a3d6d1e2da06e8f7347a 100644 --- a/primitives/panic-handler/src/lib.rs +++ b/primitives/panic-handler/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Custom panic hook with bug report link //! @@ -51,11 +52,12 @@ enum OnPanic { /// /// 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, version: &str) { +pub fn set(bug_url: &str, version: &str) { panic::set_hook(Box::new({ let version = version.to_string(); + let bug_url = bug_url.to_string(); move |c| { - panic_hook(c, bug_url, &version) + panic_hook(c, &bug_url, &version) } })); } @@ -129,7 +131,7 @@ impl Drop for AbortGuard { } /// Function being called when a panic happens. -fn panic_hook(info: &PanicInfo, report_url: &'static str, version: &str) { +fn panic_hook(info: &PanicInfo, report_url: &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); diff --git a/primitives/phragmen/benches/phragmen.rs b/primitives/phragmen/benches/phragmen.rs deleted file mode 100644 index 33da0b19563a8d3f7ef226077862558b5e0fd285..0000000000000000000000000000000000000000 --- a/primitives/phragmen/benches/phragmen.rs +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright 2019-2020 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 sp_phragmen as phragmen; -use phragmen::{Support, SupportMap, PhragmenStakedAssignment}; - -use std::collections::BTreeMap; -use sp_runtime::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/primitives/phragmen/fuzzer/Cargo.toml b/primitives/phragmen/fuzzer/Cargo.toml deleted file mode 100644 index 90af69a707f75a84b417e2729abf6a245061bb41..0000000000000000000000000000000000000000 --- a/primitives/phragmen/fuzzer/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "sp-phragmen-fuzzer" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -sp-phragmen = { version = "2.0.0-alpha.3", path = ".." } -honggfuzz = "0.5" -rand = "0.7.3" - -[workspace] - -[[bin]] -name = "reduce" -path = "src/reduce.rs" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/phragmen/src/helpers.rs b/primitives/phragmen/src/helpers.rs deleted file mode 100644 index 27f51b4a05fe2c2c22a02f8442efdd9d9f86124d..0000000000000000000000000000000000000000 --- a/primitives/phragmen/src/helpers.rs +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2020 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 for phragmen. - -use crate::{Assignment, ExtendedBalance, IdentifierT, StakedAssignment}; -use sp_runtime::PerThing; -use sp_std::prelude::*; - -/// Converts a vector of ratio assignments into ones with absolute budget value. -pub fn assignment_ratio_to_staked( - ratio: Vec>, - stake_of: FS, -) -> Vec> -where - for<'r> FS: Fn(&'r A) -> ExtendedBalance, - T: sp_std::ops::Mul, - ExtendedBalance: From<::Inner>, -{ - ratio - .into_iter() - .map(|a| { - let stake = stake_of(&a.who); - a.into_staked(stake, true) - }) - .collect() -} - -/// Converts a vector of staked assignments into ones with ratio values. -pub fn assignment_staked_to_ratio( - ratio: Vec>, -) -> Vec> -where - ExtendedBalance: From<::Inner>, -{ - ratio.into_iter().map(|a| a.into_assignment(true)).collect() -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::ExtendedBalance; - use sp_runtime::Perbill; - - #[test] - fn into_staked_works() { - let ratio = vec![ - Assignment { - who: 1u32, - distribution: vec![ - (10u32, Perbill::from_fraction(0.5)), - (20, Perbill::from_fraction(0.5)), - ], - }, - Assignment { - who: 2u32, - distribution: vec![ - (10, Perbill::from_fraction(0.33)), - (20, Perbill::from_fraction(0.67)), - ], - }, - ]; - - let stake_of = |_: &u32| -> ExtendedBalance { 100u128 }; - let staked = assignment_ratio_to_staked(ratio, stake_of); - - assert_eq!( - staked, - vec![ - StakedAssignment { - who: 1u32, - distribution: vec![(10u32, 50), (20, 50),] - }, - StakedAssignment { - who: 2u32, - distribution: vec![(10u32, 33), (20, 67),] - } - ] - ); - } -} diff --git a/primitives/rpc/Cargo.toml b/primitives/rpc/Cargo.toml index a7975fb4754b9ee049b7f76f45ca0876a4b91006..86809803b4730195ae754775f5a0eed45ec091dd 100644 --- a/primitives/rpc/Cargo.toml +++ b/primitives/rpc/Cargo.toml @@ -1,19 +1,19 @@ [package] name = "sp-rpc" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate RPC primitives and utilities." +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", features = ["derive"] } -sp-core = { version = "2.0.0-alpha.5", path = "../core" } +sp-core = { version = "2.0.0-rc4", path = "../core" } [dev-dependencies] serde_json = "1.0.41" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/rpc/src/lib.rs b/primitives/rpc/src/lib.rs index 7c22daf5cd94fce09ba1d967de8b99469299d2cf..c479f0df8b60e9acb8755526d6e7a01737920eff 100644 --- a/primitives/rpc/src/lib.rs +++ b/primitives/rpc/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Substrate RPC primitives and utilities. diff --git a/primitives/rpc/src/list.rs b/primitives/rpc/src/list.rs index 469eae3d1479aab9412addd006badf70eee44907..a80d5a22272c84e4b220a1110138a7405295bc7a 100644 --- a/primitives/rpc/src/list.rs +++ b/primitives/rpc/src/list.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! RPC a lenient list or value type. diff --git a/primitives/rpc/src/number.rs b/primitives/rpc/src/number.rs index 1d41dd234f7043c80ae2c257e563c41586c0df51..3d7e74753526c9a756cdd1a9b9f4d9f0d78a1b6d 100644 --- a/primitives/rpc/src/number.rs +++ b/primitives/rpc/src/number.rs @@ -1,78 +1,93 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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. +// 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. -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . +//! A number type that can be serialized both as a number or a string that encodes a number in a +//! string. -//! Chain RPC Block number type. - -use serde::{Serialize, Deserialize}; use std::{convert::TryFrom, fmt::Debug}; +use serde::{Serialize, Deserialize}; use sp_core::U256; -/// RPC Block number type +/// A number type that can be serialized both as a number or a string that encodes a number in a +/// string. +/// +/// We allow two representations of the block number as input. Either we deserialize to the type +/// that is specified in the block type or we attempt to parse given hex value. /// -/// We allow two representations of the block number as input. -/// Either we deserialize to the type that is specified in the block type -/// or we attempt to parse given hex value. -/// We do that for consistency with the returned type, default generic header -/// serializes block number as hex to avoid overflows in JavaScript. -#[derive(Serialize, Deserialize, Debug, PartialEq)] +/// The primary motivation for having this type is to avoid overflows when using big integers in +/// JavaScript (which we consider as an important RPC API consumer). +#[derive(Copy, Clone, Serialize, Deserialize, Debug, PartialEq)] #[serde(untagged)] -pub enum NumberOrHex { - /// The original header number type of block. - Number(Number), - /// Hex representation of the block number. +pub enum NumberOrHex { + /// The number represented directly. + Number(u64), + /// Hex representation of the number. Hex(U256), } -impl + From + Debug + PartialOrd> NumberOrHex { - /// Attempts to convert into concrete block number. - /// - /// Fails in case hex number is too big. - pub fn to_number(self) -> Result { - let num = match self { - NumberOrHex::Number(n) => n, - NumberOrHex::Hex(h) => { - let l = h.low_u64(); - if U256::from(l) != h { - return Err(format!("`{}` does not fit into u64 type; unsupported for now.", h)) - } else { - Number::try_from(l) - .map_err(|_| format!("`{}` does not fit into block number type.", h))? - } - }, - }; - // FIXME <2329>: Database seems to limit the block number to u32 for no reason - if num > Number::from(u32::max_value()) { - return Err(format!("`{:?}` > u32::max_value(), the max block number is u32.", num)) +impl NumberOrHex { + /// Converts this number into an U256. + pub fn into_u256(self) -> U256 { + match self { + NumberOrHex::Number(n) => n.into(), + NumberOrHex::Hex(h) => h, } - Ok(num) } } -impl From for NumberOrHex { +impl From for NumberOrHex { fn from(n: u64) -> Self { NumberOrHex::Number(n) } } -impl From for NumberOrHex { +impl From for NumberOrHex { fn from(n: U256) -> Self { NumberOrHex::Hex(n) } } +/// An error type that signals an out-of-range conversion attempt. +pub struct TryFromIntError(pub(crate) ()); + +impl TryFrom for u32 { + type Error = TryFromIntError; + fn try_from(num_or_hex: NumberOrHex) -> Result { + let num_or_hex = num_or_hex.into_u256(); + if num_or_hex > U256::from(u32::max_value()) { + return Err(TryFromIntError(())); + } else { + Ok(num_or_hex.as_u32()) + } + } +} + +impl TryFrom for u64 { + type Error = TryFromIntError; + fn try_from(num_or_hex: NumberOrHex) -> Result { + let num_or_hex = num_or_hex.into_u256(); + if num_or_hex > U256::from(u64::max_value()) { + return Err(TryFromIntError(())); + } else { + Ok(num_or_hex.as_u64()) + } + } +} + #[cfg(test)] mod tests { use super::*; @@ -80,10 +95,11 @@ mod tests { #[test] fn should_serialize_and_deserialize() { - assert_deser(r#""0x1234""#, NumberOrHex::::Hex(0x1234.into())); - assert_deser(r#""0x0""#, NumberOrHex::::Hex(0.into())); - assert_deser(r#"5"#, NumberOrHex::Number(5_u64)); - assert_deser(r#"10000"#, NumberOrHex::Number(10000_u32)); - assert_deser(r#"0"#, NumberOrHex::Number(0_u16)); + assert_deser(r#""0x1234""#, NumberOrHex::Hex(0x1234.into())); + assert_deser(r#""0x0""#, NumberOrHex::Hex(0.into())); + assert_deser(r#"5"#, NumberOrHex::Number(5)); + assert_deser(r#"10000"#, NumberOrHex::Number(10000)); + assert_deser(r#"0"#, NumberOrHex::Number(0)); + assert_deser(r#"1000000000000"#, NumberOrHex::Number(1000000000000)); } } diff --git a/primitives/runtime-interface/Cargo.toml b/primitives/runtime-interface/Cargo.toml index 01f7f2f19c98169dbebd86e841fd37473ea6d011..dc37c186293d5319e4abd01bf65c80fbd5927ecf 100644 --- a/primitives/runtime-interface/Cargo.toml +++ b/primitives/runtime-interface/Cargo.toml @@ -1,28 +1,32 @@ [package] name = "sp-runtime-interface" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate runtime interface" documentation = "https://docs.rs/sp-runtime-interface/" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-wasm-interface = { version = "2.0.0-alpha.5", path = "../wasm-interface", default-features = false } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../std" } -sp-runtime-interface-proc-macro = { version = "2.0.0-alpha.5", path = "proc-macro" } -sp-externalities = { version = "0.8.0-alpha.5", optional = true, path = "../externalities" } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } +sp-wasm-interface = { version = "2.0.0-rc4", path = "../wasm-interface", default-features = false } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../std" } +sp-tracing = { version = "2.0.0-rc4", default-features = false, path = "../tracing" } +sp-runtime-interface-proc-macro = { version = "2.0.0-rc4", path = "proc-macro" } +sp-externalities = { version = "0.8.0-rc4", optional = true, path = "../externalities" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } static_assertions = "1.0.0" primitive-types = { version = "0.7.0", default-features = false } [dev-dependencies] -sp-runtime-interface-test-wasm = { version = "2.0.0-dev", path = "test-wasm" } -sp-state-machine = { version = "0.8.0-alpha.5", path = "../../primitives/state-machine" } -sp-core = { version = "2.0.0-alpha.5", path = "../core" } -sp-io = { version = "2.0.0-alpha.5", path = "../io" } +sp-runtime-interface-test-wasm = { version = "2.0.0-rc4", path = "test-wasm" } +sp-state-machine = { version = "0.8.0-rc4", path = "../../primitives/state-machine" } +sp-core = { version = "2.0.0-rc4", path = "../core" } +sp-io = { version = "2.0.0-rc4", path = "../io" } rustversion = "1.0.0" trybuild = "1.0.23" @@ -31,6 +35,7 @@ default = [ "std" ] std = [ "sp-wasm-interface/std", "sp-std/std", + "sp-tracing/std", "codec/std", "sp-externalities", "primitive-types/std", @@ -43,6 +48,3 @@ std = [ # Disables static assertions in `impls.rs` that checks the word size. To prevent any footgun, the # check is changed into a runtime check. disable_target_static_assertions = [] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/runtime-interface/proc-macro/Cargo.toml b/primitives/runtime-interface/proc-macro/Cargo.toml index 6d0b7ee5fb7262c4a55922c0b1cef6549424c935..dfb3840a08e87d4b1041ef388ffce2ca0693c74d 100644 --- a/primitives/runtime-interface/proc-macro/Cargo.toml +++ b/primitives/runtime-interface/proc-macro/Cargo.toml @@ -1,14 +1,17 @@ [package] name = "sp-runtime-interface-proc-macro" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "This crate provides procedural macros for usage within the context of the Substrate runtime interface." documentation = "https://docs.rs/sp-runtime-interface-proc-macro" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [lib] proc-macro = true @@ -18,6 +21,3 @@ quote = "1.0.3" proc-macro2 = "1.0.3" Inflector = "0.11.4" proc-macro-crate = "0.1.4" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/runtime-interface/proc-macro/src/lib.rs b/primitives/runtime-interface/proc-macro/src/lib.rs index 2ed8b1a2281b727ca7e9333272111d81dfb8591f..2f5b9de1c14e7da9dd07113cfe71facb6d97f776 100644 --- a/primitives/runtime-interface/proc-macro/src/lib.rs +++ b/primitives/runtime-interface/proc-macro/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! This crate provides procedural macros for usage within the context of the Substrate runtime //! interface. diff --git a/primitives/runtime-interface/proc-macro/src/pass_by/codec.rs b/primitives/runtime-interface/proc-macro/src/pass_by/codec.rs index 5e30870a82d2e7831a43a454451fbe68e5926dc4..5e51440938456b41628ca89a6736970e6e51b65d 100644 --- a/primitives/runtime-interface/proc-macro/src/pass_by/codec.rs +++ b/primitives/runtime-interface/proc-macro/src/pass_by/codec.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Derive macro implementation of `PassBy` with the associated type set to `Codec`. //! diff --git a/primitives/runtime-interface/proc-macro/src/pass_by/enum_.rs b/primitives/runtime-interface/proc-macro/src/pass_by/enum_.rs index 5d5b3ae43bdf5f0014c4355914b544c7d3529727..35ed9c0cb802f6ce105c8f18caf23957c4e9d3cb 100644 --- a/primitives/runtime-interface/proc-macro/src/pass_by/enum_.rs +++ b/primitives/runtime-interface/proc-macro/src/pass_by/enum_.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Derive macro implementation of `PassBy` with the associated type set to `Enum`. //! diff --git a/primitives/runtime-interface/proc-macro/src/pass_by/inner.rs b/primitives/runtime-interface/proc-macro/src/pass_by/inner.rs index 2e1caaa96c61fa4c2f501a7c8efcc9fe924e877e..cf3bb965d0743b04be7367416b43773fc0c2beee 100644 --- a/primitives/runtime-interface/proc-macro/src/pass_by/inner.rs +++ b/primitives/runtime-interface/proc-macro/src/pass_by/inner.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Derive macro implementation of `PassBy` with the associated type set to `Inner` and of the //! helper trait `PassByInner`. diff --git a/primitives/runtime-interface/proc-macro/src/pass_by/mod.rs b/primitives/runtime-interface/proc-macro/src/pass_by/mod.rs index 1466af598ea7cafac655f0efd0034b1d9e7b017a..ff5ea4849af77cb650d5f2ec0535441a7ead395a 100644 --- a/primitives/runtime-interface/proc-macro/src/pass_by/mod.rs +++ b/primitives/runtime-interface/proc-macro/src/pass_by/mod.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! All the `PassBy*` derive implementations. diff --git a/primitives/runtime-interface/proc-macro/src/runtime_interface/bare_function_interface.rs b/primitives/runtime-interface/proc-macro/src/runtime_interface/bare_function_interface.rs index e7c34fbf9934211df7ea874e08d2d4382b1c7fe2..6760e9656113a9e8b3cfd0e7246a514ce915a477 100644 --- a/primitives/runtime-interface/proc-macro/src/runtime_interface/bare_function_interface.rs +++ b/primitives/runtime-interface/proc-macro/src/runtime_interface/bare_function_interface.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Generates the bare function interface for a given trait definition. //! @@ -146,6 +147,7 @@ fn function_std_impl( is_wasm_only: bool, ) -> Result { let function_name = create_function_ident_with_version(&method.sig.ident, version); + let function_name_str = function_name.to_string(); let crate_ = generate_crate_access(); let args = get_function_arguments(&method.sig).map(FnArg::Typed).chain( @@ -172,6 +174,7 @@ fn function_std_impl( #[cfg(feature = "std")] #( #attrs )* fn #function_name( #( #args, )* ) #return_value { + #crate_::sp_tracing::enter_span!(#function_name_str); #call_to_trait } } diff --git a/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs b/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs index 205ee87105c41c9a1d5166f2a6b182ae28dd308b..721eed649c25d5d0244615194f185b672c2bd1e3 100644 --- a/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs +++ b/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Generates the extern host functions and the implementation for these host functions. //! @@ -226,6 +227,7 @@ fn generate_host_function_implementation( __function_context__: &mut dyn #crate_::sp_wasm_interface::FunctionContext, args: &mut dyn Iterator, ) -> std::result::Result, String> { + #crate_::sp_tracing::enter_span!(#name); #( #wasm_to_ffi_values )* #( #ffi_to_host_values )* #host_function_call diff --git a/primitives/runtime-interface/proc-macro/src/runtime_interface/mod.rs b/primitives/runtime-interface/proc-macro/src/runtime_interface/mod.rs index 1c88198d6ea44fa04a5bc11878f8fa8d0b075833..c9b6edf68fd5a48ec9f56200b3b2154c267baebe 100644 --- a/primitives/runtime-interface/proc-macro/src/runtime_interface/mod.rs +++ b/primitives/runtime-interface/proc-macro/src/runtime_interface/mod.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::utils::generate_runtime_interface_include; diff --git a/primitives/runtime-interface/proc-macro/src/runtime_interface/trait_decl_impl.rs b/primitives/runtime-interface/proc-macro/src/runtime_interface/trait_decl_impl.rs index 542c4ca4b8c37b3519a4bb103897c80d83145b4d..70015d02426d4de85be697f303873ed756dbb246 100644 --- a/primitives/runtime-interface/proc-macro/src/runtime_interface/trait_decl_impl.rs +++ b/primitives/runtime-interface/proc-macro/src/runtime_interface/trait_decl_impl.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Checks the trait declaration, makes the trait declaration module local, removes all method //! default implementations and implements the trait for `&mut dyn Externalities`. diff --git a/primitives/runtime-interface/src/host.rs b/primitives/runtime-interface/src/host.rs index cf03e6623af591ac39966e0808913223c42dd7bd..4a01291e68455dc74a16040c31992dd818d64764 100644 --- a/primitives/runtime-interface/src/host.rs +++ b/primitives/runtime-interface/src/host.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Traits required by the runtime interface from the host side. diff --git a/primitives/runtime-interface/src/impls.rs b/primitives/runtime-interface/src/impls.rs index 084b5e11eb3b128c61aae7eefe7bc9baabe71413..259d3517f001dcd415b452c09273baa2d2346589 100644 --- a/primitives/runtime-interface/src/impls.rs +++ b/primitives/runtime-interface/src/impls.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Provides implementations for the runtime interface traits. @@ -364,6 +365,10 @@ impl PassBy for Option { type PassBy = Codec; } +impl PassBy for (u32, u32, u32, u32) { + type PassBy = Codec; +} + /// Implement `PassBy` with `Inner` for the given fixed sized hash types. macro_rules! for_primitive_types { { $( $hash:ident $n:expr ),* $(,)? } => { diff --git a/primitives/runtime-interface/src/lib.rs b/primitives/runtime-interface/src/lib.rs index fd158d4b8aa9609df1206b2ce5a640e95b5e3092..562f94b278efcc60fd21b754dfcf4e1e65f88ab3 100644 --- a/primitives/runtime-interface/src/lib.rs +++ b/primitives/runtime-interface/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! Substrate runtime interface //! @@ -109,6 +110,9 @@ extern crate self as sp_runtime_interface; #[cfg(feature = "std")] pub use sp_wasm_interface; +#[doc(hidden)] +pub use sp_tracing; + #[doc(hidden)] pub use sp_std; diff --git a/primitives/runtime-interface/src/pass_by.rs b/primitives/runtime-interface/src/pass_by.rs index d6767b5ebbe93dfb131c13564b4f900d6bdca0bd..5ccb3a5e96ee1168ea2cdb73a2d92b6bc3bb376a 100644 --- a/primitives/runtime-interface/src/pass_by.rs +++ b/primitives/runtime-interface/src/pass_by.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Provides the [`PassBy`](PassBy) trait to simplify the implementation of the //! runtime interface traits for custom types. diff --git a/primitives/runtime-interface/src/util.rs b/primitives/runtime-interface/src/util.rs index fa7016a2b01a6632632e7b11ea618763e04b0381..604e37e8be3976c369bae2f82173f3fb484f914c 100644 --- a/primitives/runtime-interface/src/util.rs +++ b/primitives/runtime-interface/src/util.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Various utilities that help interfacing with wasm runtime code. diff --git a/primitives/runtime-interface/src/wasm.rs b/primitives/runtime-interface/src/wasm.rs index a0801c2bfb5a9aca7c937ef276306428f44630e0..5511f60e30d214e9473088ce58c4573dc83264f9 100644 --- a/primitives/runtime-interface/src/wasm.rs +++ b/primitives/runtime-interface/src/wasm.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Traits required by the runtime interface from the wasm side. diff --git a/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml b/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml index 6f2d66bd77c4b2d672c54d3dc6f760830ccc570b..9ad22599ad08eef5aa962b51bf0cd2dad2596dbd 100644 --- a/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml +++ b/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml @@ -1,19 +1,22 @@ [package] name = "sp-runtime-interface-test-wasm-deprecated" -version = "2.0.0-dev" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" build = "build.rs" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" publish = false +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-runtime-interface = { version = "2.0.0-alpha.5", default-features = false, path = "../" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../std" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../io" } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../core" } +sp-runtime-interface = { version = "2.0.0-rc4", default-features = false, path = "../" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../std" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../io" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../core" } [build-dependencies] wasm-builder-runner = { version = "1.0.5", package = "substrate-wasm-builder-runner", path = "../../../utils/wasm-builder-runner" } @@ -21,6 +24,3 @@ wasm-builder-runner = { version = "1.0.5", package = "substrate-wasm-builder-run [features] default = [ "std" ] std = [ "sp-runtime-interface/std", "sp-std/std", "sp-core/std", "sp-io/std" ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/runtime-interface/test-wasm-deprecated/build.rs b/primitives/runtime-interface/test-wasm-deprecated/build.rs index 647b4768141d2203155bf5325f9ff87f7d9c2446..a4f323566006cf7c003cec2e413e1d23ecffead1 100644 --- a/primitives/runtime-interface/test-wasm-deprecated/build.rs +++ b/primitives/runtime-interface/test-wasm-deprecated/build.rs @@ -1,25 +1,26 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use wasm_builder_runner::WasmBuilder; fn main() { WasmBuilder::new() .with_current_project() - .with_wasm_builder_from_crates_or_path("1.0.9", "../../../utils/wasm-builder") + .with_wasm_builder_from_crates_or_path("1.0.11", "../../../utils/wasm-builder") .export_heap_base() .import_memory() .build() diff --git a/primitives/runtime-interface/test-wasm-deprecated/src/lib.rs b/primitives/runtime-interface/test-wasm-deprecated/src/lib.rs index 29d28c75faafb9b4864479568c819e9bc3178477..ad005bfb5f8b980425e7b07d45d900c5241ad93d 100644 --- a/primitives/runtime-interface/test-wasm-deprecated/src/lib.rs +++ b/primitives/runtime-interface/test-wasm-deprecated/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for the runtime interface traits and proc macros. diff --git a/primitives/runtime-interface/test-wasm/Cargo.toml b/primitives/runtime-interface/test-wasm/Cargo.toml index 4eb4f01c9f0c810ab42f9016e1f7db66147e1f65..7973f152bcb0c8c48b14362f9b90dec2676cc5ed 100644 --- a/primitives/runtime-interface/test-wasm/Cargo.toml +++ b/primitives/runtime-interface/test-wasm/Cargo.toml @@ -1,19 +1,22 @@ [package] name = "sp-runtime-interface-test-wasm" -version = "2.0.0-dev" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" build = "build.rs" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" publish = false +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] -sp-runtime-interface = { version = "2.0.0-alpha.5", default-features = false, path = "../" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../std" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../io" } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../core" } +sp-runtime-interface = { version = "2.0.0-rc4", default-features = false, path = "../" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../std" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../../io" } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../../core" } [build-dependencies] wasm-builder-runner = { version = "1.0.5", package = "substrate-wasm-builder-runner", path = "../../../utils/wasm-builder-runner" } @@ -21,6 +24,3 @@ wasm-builder-runner = { version = "1.0.5", package = "substrate-wasm-builder-run [features] default = [ "std" ] std = [ "sp-runtime-interface/std", "sp-std/std", "sp-core/std", "sp-io/std" ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/runtime-interface/test-wasm/build.rs b/primitives/runtime-interface/test-wasm/build.rs index 647b4768141d2203155bf5325f9ff87f7d9c2446..a4f323566006cf7c003cec2e413e1d23ecffead1 100644 --- a/primitives/runtime-interface/test-wasm/build.rs +++ b/primitives/runtime-interface/test-wasm/build.rs @@ -1,25 +1,26 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use wasm_builder_runner::WasmBuilder; fn main() { WasmBuilder::new() .with_current_project() - .with_wasm_builder_from_crates_or_path("1.0.9", "../../../utils/wasm-builder") + .with_wasm_builder_from_crates_or_path("1.0.11", "../../../utils/wasm-builder") .export_heap_base() .import_memory() .build() diff --git a/primitives/runtime-interface/test-wasm/src/lib.rs b/primitives/runtime-interface/test-wasm/src/lib.rs index 700c77854a8b3e003c56c1b25d2c0ba904550fd1..90112046fcda4c11e2109c9715ae23469824d129 100644 --- a/primitives/runtime-interface/test-wasm/src/lib.rs +++ b/primitives/runtime-interface/test-wasm/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for the runtime interface traits and proc macros. diff --git a/primitives/runtime-interface/test/Cargo.toml b/primitives/runtime-interface/test/Cargo.toml index f3bee038c8204c612444c8c3d6e34a4e7f3e2126..bdbe7ff902ee9760b1d04ebc3bbce0c232ed4d46 100644 --- a/primitives/runtime-interface/test/Cargo.toml +++ b/primitives/runtime-interface/test/Cargo.toml @@ -1,21 +1,23 @@ [package] name = "sp-runtime-interface-test" -version = "2.0.0-dev" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" publish = false homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" -[dependencies] -sp-runtime-interface = { version = "2.0.0-alpha.5", path = "../" } -sc-executor = { version = "0.8.0-alpha.5", path = "../../../client/executor" } -sp-runtime-interface-test-wasm = { version = "2.0.0-dev", path = "../test-wasm" } -sp-runtime-interface-test-wasm-deprecated = { version = "2.0.0-dev", path = "../test-wasm-deprecated" } -sp-state-machine = { version = "0.8.0-alpha.5", path = "../../../primitives/state-machine" } -sp-runtime = { version = "2.0.0-alpha.5", path = "../../runtime" } -sp-io = { version = "2.0.0-alpha.5", path = "../../io" } - [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +sp-runtime-interface = { version = "2.0.0-rc4", path = "../" } +sc-executor = { version = "0.8.0-rc4", path = "../../../client/executor" } +sp-runtime-interface-test-wasm = { version = "2.0.0-rc4", path = "../test-wasm" } +sp-runtime-interface-test-wasm-deprecated = { version = "2.0.0-rc4", path = "../test-wasm-deprecated" } +sp-state-machine = { version = "0.8.0-rc4", path = "../../../primitives/state-machine" } +sp-runtime = { version = "2.0.0-rc4", path = "../../runtime" } +sp-core = { version = "2.0.0-rc4", path = "../../core" } +sp-io = { version = "2.0.0-rc4", path = "../../io" } +tracing = "0.1.13" diff --git a/primitives/runtime-interface/test/src/lib.rs b/primitives/runtime-interface/test/src/lib.rs index 110eda980fd6947166768150e55c464c31c9ac80..109caab6062f8e7a6b5d49069366528b236c8c36 100644 --- a/primitives/runtime-interface/test/src/lib.rs +++ b/primitives/runtime-interface/test/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Integration tests for runtime interface primitives #![cfg(test)] @@ -27,9 +28,14 @@ use sp_runtime_interface_test_wasm_deprecated::WASM_BINARY as WASM_BINARY_DEPREC use sp_wasm_interface::HostFunctions as HostFunctionsT; use sc_executor::CallInWasm; +use std::{collections::HashSet, sync::{Arc, Mutex}}; + type TestExternalities = sp_state_machine::TestExternalities; -fn call_wasm_method(binary: &[u8], method: &str) -> TestExternalities { +fn call_wasm_method_with_result( + binary: &[u8], + method: &str, +) -> Result { let mut ext = TestExternalities::default(); let mut ext_ext = ext.ext(); let mut host_functions = HF::host_functions(); @@ -39,7 +45,6 @@ fn call_wasm_method(binary: &[u8], method: &str) -> TestExte sc_executor::WasmExecutionMethod::Interpreted, Some(8), host_functions, - false, 8, ); executor.call_in_wasm( @@ -48,9 +53,13 @@ fn call_wasm_method(binary: &[u8], method: &str) -> TestExte method, &[], &mut ext_ext, - ).expect(&format!("Executes `{}`", method)); + sp_core::traits::MissingHostFunctions::Disallow, + ).map_err(|e| format!("Failed to execute `{}`: {}", method, e))?; + Ok(ext) +} - ext +fn call_wasm_method(binary: &[u8], method: &str) -> TestExternalities { + call_wasm_method_with_result::(binary, method).unwrap() } #[test] @@ -92,20 +101,15 @@ fn test_return_input_public_key() { } #[test] -#[should_panic( - expected = "Instantiation: Export ext_test_api_return_input_version_1 not found" -)] fn host_function_not_found() { - call_wasm_method::<()>(&WASM_BINARY[..], "test_return_data"); + let err = call_wasm_method_with_result::<()>(&WASM_BINARY[..], "test_return_data").unwrap_err(); + + assert!(err.contains("Instantiation: Export ")); + assert!(err.contains(" not found")); } #[test] -#[should_panic( - expected = - "Executes `test_invalid_utf8_data_should_return_an_error`: \ - \"Trap: Trap { kind: Host(FunctionExecution(\\\"ext_test_api_invalid_utf8_data_version_1\\\", \ - \\\"Invalid utf8 data provided\\\")) }\"" -)] +#[should_panic(expected = "Invalid utf8 data provided")] fn test_invalid_utf8_data_should_return_an_error() { call_wasm_method::(&WASM_BINARY[..], "test_invalid_utf8_data_should_return_an_error"); } @@ -150,3 +154,47 @@ fn test_versionining_with_new_host_works() { "test_versionning_works", ); } + +#[test] +fn test_tracing() { + use tracing::span::Id as SpanId; + + #[derive(Clone)] + struct TracingSubscriber(Arc>); + + #[derive(Default)] + struct Inner { + spans: HashSet<&'static str>, + } + + impl tracing::subscriber::Subscriber for TracingSubscriber { + fn enabled(&self, _: &tracing::Metadata) -> bool { true } + + fn new_span(&self, span: &tracing::span::Attributes) -> tracing::Id { + let mut inner = self.0.lock().unwrap(); + let id = SpanId::from_u64((inner.spans.len() + 1) as _); + inner.spans.insert(span.metadata().name()); + id + } + + fn record(&self, _: &SpanId, _: &tracing::span::Record) {} + + fn record_follows_from(&self, _: &SpanId, _: &SpanId) {} + + fn event(&self, _: &tracing::Event) {} + + fn enter(&self, _: &SpanId) {} + + fn exit(&self, _: &SpanId) {} + } + + let subscriber = TracingSubscriber(Default::default()); + let _guard = tracing::subscriber::set_default(subscriber.clone()); + + // Call some method to generate a trace + call_wasm_method::(&WASM_BINARY[..], "test_return_data"); + + let inner = subscriber.0.lock().unwrap(); + assert!(inner.spans.contains("return_input_version_1")); + assert!(inner.spans.contains("ext_test_api_return_input_version_1")); +} diff --git a/primitives/runtime-interface/tests/ui.rs b/primitives/runtime-interface/tests/ui.rs index 910771f9389691d61b1c84069fdf6090e242f80b..2f7fd6d06bcd34c3724d6fa39422d4f7890392cc 100644 --- a/primitives/runtime-interface/tests/ui.rs +++ b/primitives/runtime-interface/tests/ui.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use std::env; diff --git a/primitives/runtime-interface/tests/ui/pass_by_enum_with_struct.stderr b/primitives/runtime-interface/tests/ui/pass_by_enum_with_struct.stderr index 6502a36fc18b7f387b1112b559c455e515411db9..c7ed1af3b1a037bfc657692b60bc166be8452850 100644 --- a/primitives/runtime-interface/tests/ui/pass_by_enum_with_struct.stderr +++ b/primitives/runtime-interface/tests/ui/pass_by_enum_with_struct.stderr @@ -3,3 +3,5 @@ error: `PassByEnum` only supports enums as input type. | 3 | #[derive(PassByEnum)] | ^^^^^^^^^^ + | + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/primitives/runtime-interface/tests/ui/pass_by_enum_with_value_variant.stderr b/primitives/runtime-interface/tests/ui/pass_by_enum_with_value_variant.stderr index 1f03436d4e007fc9fe6cc85a4d2f2b6dd37de4fa..f6c85ed2bba3e24b44cf93ac30c1e7b8d54ba8bd 100644 --- a/primitives/runtime-interface/tests/ui/pass_by_enum_with_value_variant.stderr +++ b/primitives/runtime-interface/tests/ui/pass_by_enum_with_value_variant.stderr @@ -3,3 +3,5 @@ error: `PassByEnum` only supports unit variants. | 3 | #[derive(PassByEnum)] | ^^^^^^^^^^ + | + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/primitives/runtime-interface/tests/ui/pass_by_inner_with_two_fields.stderr b/primitives/runtime-interface/tests/ui/pass_by_inner_with_two_fields.stderr index 7f576a69f0e5039a0e058aa385fe5da2879d7710..9afbce76f0c233c3156f0024a8485b32a29aa50c 100644 --- a/primitives/runtime-interface/tests/ui/pass_by_inner_with_two_fields.stderr +++ b/primitives/runtime-interface/tests/ui/pass_by_inner_with_two_fields.stderr @@ -3,3 +3,5 @@ error: Only newtype/one field structs are supported by `PassByInner`! | 3 | #[derive(PassByInner)] | ^^^^^^^^^^^ + | + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 0e71e8becd61e4ea18a77e9ae4b5afcc031d731d..ecbaa7ba58703292f310e69bb7bc240f9e5c9167 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -1,34 +1,39 @@ [package] name = "sp-runtime" -version = "2.0.0-alpha.5" +version = "2.0.0-rc4" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Runtime Modules shared primitive types." documentation = "https://docs.rs/sp-runtime" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] serde = { version = "1.0.101", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../core" } -sp-application-crypto = { version = "2.0.0-alpha.5", default-features = false, path = "../application-crypto" } -sp-arithmetic = { version = "2.0.0-alpha.5", default-features = false, path = "../arithmetic" } -sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../std" } -sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../io" } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +sp-core = { version = "2.0.0-rc4", default-features = false, path = "../core" } +sp-application-crypto = { version = "2.0.0-rc4", default-features = false, path = "../application-crypto" } +sp-arithmetic = { version = "2.0.0-rc4", default-features = false, path = "../arithmetic" } +sp-std = { version = "2.0.0-rc4", default-features = false, path = "../std" } +sp-io = { version = "2.0.0-rc4", default-features = false, path = "../io" } 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" -sp-inherents = { version = "2.0.0-alpha.5", default-features = false, path = "../inherents" } -parity-util-mem = { version = "0.6.0", default-features = false, features = ["primitive-types"] } +sp-inherents = { version = "2.0.0-rc4", default-features = false, path = "../inherents" } +parity-util-mem = { version = "0.7.0", default-features = false, features = ["primitive-types"] } hash256-std-hasher = { version = "0.15.2", default-features = false } +either = { version = "1.5", default-features = false } [dev-dependencies] serde_json = "1.0.41" rand = "0.7.2" +sp-state-machine = { version = "0.8.0-rc4", path = "../../primitives/state-machine" } [features] bench = [] @@ -47,7 +52,5 @@ std = [ "sp-inherents/std", "parity-util-mem/std", "hash256-std-hasher/std", + "either/use_std", ] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/primitives/runtime/src/curve.rs b/primitives/runtime/src/curve.rs index b00cbed6525a16cf6f1db35eed8f5b6e225437f3..27eb89a76947e039b396870ae3a3e2dc772f6b57 100644 --- a/primitives/runtime/src/curve.rs +++ b/primitives/runtime/src/curve.rs @@ -1,22 +1,23 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Provides some utilities to define a piecewise linear function. -use crate::{Perbill, traits::{AtLeast32Bit, SaturatedConversion}}; +use crate::{Perbill, traits::{AtLeast32BitUnsigned, SaturatedConversion}}; use core::ops::Sub; /// Piecewise Linear function in [0, 1] -> [0, 1]. @@ -35,7 +36,7 @@ fn abs_sub + Clone>(a: N, b: N) -> N where { 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: AtLeast32Bit + Clone + N: AtLeast32BitUnsigned + Clone { let n = n.min(d.clone()); @@ -79,7 +80,7 @@ impl<'a> PiecewiseLinear<'a> { // 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: AtLeast32Bit + Clone + where N: AtLeast32BitUnsigned + Clone { let q = q.max(1); diff --git a/primitives/runtime/src/generic/block.rs b/primitives/runtime/src/generic/block.rs index fb07d6c215d81f3a241926da6252c12686fc2f28..4a758b7416dec568876a769ff4dbcf1f69b00385 100644 --- a/primitives/runtime/src/generic/block.rs +++ b/primitives/runtime/src/generic/block.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Generic implementation of a block and associated items. diff --git a/primitives/runtime/src/generic/checked_extrinsic.rs b/primitives/runtime/src/generic/checked_extrinsic.rs index 7a71ef5218ffb66efc36941779e0156036cd868d..f355308a59f9704d7f7343dcd904d8458ad63184 100644 --- a/primitives/runtime/src/generic/checked_extrinsic.rs +++ b/primitives/runtime/src/generic/checked_extrinsic.rs @@ -1,26 +1,27 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Generic implementation of an extrinsic that has passed the verification //! stage. use crate::traits::{ - self, Member, MaybeDisplay, SignedExtension, Dispatchable, + self, Member, MaybeDisplay, SignedExtension, Dispatchable, DispatchInfoOf, PostDispatchInfoOf, + ValidateUnsigned, }; -use crate::traits::ValidateUnsigned; use crate::transaction_validity::{TransactionValidity, TransactionSource}; /// Definition of something that the external world might want to say; its @@ -36,28 +37,26 @@ pub struct CheckedExtrinsic { pub function: Call, } -impl traits::Applyable for +impl traits::Applyable for CheckedExtrinsic where AccountId: Member + MaybeDisplay, Call: Member + Dispatchable, - Extra: SignedExtension, + Extra: SignedExtension, Origin: From>, - Info: Clone, { type Call = Call; - type DispatchInfo = Info; fn validate>( &self, // TODO [#5006;ToDr] should source be passed to `SignedExtension`s? // Perhaps a change for 2.0 to avoid breaking too much APIs? source: TransactionSource, - info: Self::DispatchInfo, + info: &DispatchInfoOf, len: usize, ) -> TransactionValidity { if let Some((ref id, ref extra)) = self.signed { - Extra::validate(extra, id, &self.function, info.clone(), len) + Extra::validate(extra, id, &self.function, info, len) } else { let valid = Extra::validate_unsigned(&self.function, info, len)?; let unsigned_validation = U::validate_unsigned(source, &self.function)?; @@ -67,19 +66,23 @@ where fn apply>( self, - info: Self::DispatchInfo, + info: &DispatchInfoOf, len: usize, - ) -> crate::ApplyExtrinsicResult { + ) -> crate::ApplyExtrinsicResultWithInfo> { let (maybe_who, pre) = if let Some((id, extra)) = self.signed { - let pre = Extra::pre_dispatch(extra, &id, &self.function, info.clone(), len)?; + let pre = Extra::pre_dispatch(extra, &id, &self.function, info, len)?; (Some(id), pre) } else { - let pre = Extra::pre_dispatch_unsigned(&self.function, info.clone(), len)?; + 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.map(|_| ()).map_err(|e| e.error)) + let post_info = match res { + Ok(info) => info, + Err(err) => err.post_info, + }; + Extra::post_dispatch(pre, info, &post_info, len, &res.map(|_| ()).map_err(|e| e.error))?; + Ok(res) } } diff --git a/primitives/runtime/src/generic/digest.rs b/primitives/runtime/src/generic/digest.rs index dad3e1fc26b7caedacd99d454bb486588eab3428..ec0963e5ba002c15490ef63034d7c8aa43a3d596 100644 --- a/primitives/runtime/src/generic/digest.rs +++ b/primitives/runtime/src/generic/digest.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Generic implementation of a digest. @@ -28,18 +29,22 @@ use sp_core::{ChangesTrieConfiguration, RuntimeDebug}; /// Generic header digest. #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, parity_util_mem::MallocSizeOf))] -pub struct Digest { +pub struct Digest { /// A list of logs in the digest. + #[cfg_attr( + feature = "std", + serde(bound(serialize = "Hash: codec::Codec", deserialize = "Hash: codec::Codec")) + )] pub logs: Vec>, } -impl Default for Digest { +impl Default for Digest { fn default() -> Self { Digest { logs: Vec::new(), } } } -impl Digest { +impl Digest { /// Get reference to all digest items. pub fn logs(&self) -> &[DigestItem] { &self.logs diff --git a/primitives/runtime/src/generic/era.rs b/primitives/runtime/src/generic/era.rs index 37b4b495fef540eb3b942098e3f54f11dfd41d1e..9bfab517a92caab182dba4d6a652757eb47158d4 100644 --- a/primitives/runtime/src/generic/era.rs +++ b/primitives/runtime/src/generic/era.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Generic implementation of an unchecked (pre-verification) extrinsic. diff --git a/primitives/runtime/src/generic/header.rs b/primitives/runtime/src/generic/header.rs index 5efb36603d572fd7be350f7b046e8b5969408cc6..e6c800e5787ff2e7e0f7efb77efffacbc2be9c7e 100644 --- a/primitives/runtime/src/generic/header.rs +++ b/primitives/runtime/src/generic/header.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Generic implementation of a block header. @@ -20,7 +21,7 @@ use serde::{Deserialize, Serialize}; use crate::codec::{Decode, Encode, Codec, Input, Output, HasCompact, EncodeAsRef, Error}; use crate::traits::{ - self, Member, AtLeast32Bit, SimpleBitOps, Hash as HashT, + self, Member, AtLeast32BitUnsigned, SimpleBitOps, Hash as HashT, MaybeSerializeDeserialize, MaybeSerialize, MaybeDisplay, MaybeMallocSizeOf, }; @@ -122,7 +123,7 @@ impl codec::EncodeLike for Header where impl traits::Header for Header where Number: Member + MaybeSerializeDeserialize + Debug + sp_std::hash::Hash + MaybeDisplay + - AtLeast32Bit + Codec + Copy + Into + TryFrom + sp_std::str::FromStr + + AtLeast32BitUnsigned + Codec + Copy + Into + TryFrom + sp_std::str::FromStr + MaybeMallocSizeOf, Hash: HashT, Hash::Output: Default + sp_std::hash::Hash + Copy + Member + Ord + @@ -170,7 +171,8 @@ impl traits::Header for Header where } impl Header where - Number: Member + sp_std::hash::Hash + Copy + MaybeDisplay + AtLeast32Bit + Codec + Into + TryFrom, + Number: Member + sp_std::hash::Hash + Copy + MaybeDisplay + AtLeast32BitUnsigned + Codec + + Into + TryFrom, Hash: HashT, Hash::Output: Default + sp_std::hash::Hash + Copy + Member + MaybeDisplay + SimpleBitOps + Codec, { diff --git a/primitives/runtime/src/generic/mod.rs b/primitives/runtime/src/generic/mod.rs index 5e9928ba1909ab2aa114babaadcc1cc774131e60..2a25c063ead7345c9428a920de39780ab5eedb35 100644 --- a/primitives/runtime/src/generic/mod.rs +++ b/primitives/runtime/src/generic/mod.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // tag::description[] //! Generic implementations of Extrinsic/Header/Block. diff --git a/primitives/runtime/src/generic/tests.rs b/primitives/runtime/src/generic/tests.rs index de2f4a19d99cf7b366af00ef24ea322a6fc0ce68..56138094fa0246e5f25b173a7cf11a596e2e96be 100644 --- a/primitives/runtime/src/generic/tests.rs +++ b/primitives/runtime/src/generic/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for the generic implementations of Extrinsic/Header/Block. diff --git a/primitives/runtime/src/generic/unchecked_extrinsic.rs b/primitives/runtime/src/generic/unchecked_extrinsic.rs index a516bc1f7fa999f1087718f93f072ff8eff45099..d16d404ddfd0e9207771b606d224d54df7288998 100644 --- a/primitives/runtime/src/generic/unchecked_extrinsic.rs +++ b/primitives/runtime/src/generic/unchecked_extrinsic.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Generic implementation of an unchecked (pre-verification) extrinsic. @@ -24,7 +25,9 @@ use crate::{ self, Member, MaybeDisplay, SignedExtension, Checkable, Extrinsic, ExtrinsicMetadata, IdentifyAccount, }, - generic::CheckedExtrinsic, transaction_validity::{TransactionValidityError, InvalidTransaction}, + generic::CheckedExtrinsic, + transaction_validity::{TransactionValidityError, InvalidTransaction}, + OpaqueExtrinsic, }; const TRANSACTION_VERSION: u8 = 4; @@ -125,9 +128,7 @@ where Some((signed, signature, extra)) => { let signed = lookup.lookup(signed)?; let raw_payload = SignedPayload::new(self.function, extra)?; - if !raw_payload.using_encoded(|payload| { - signature.verify(payload, &signed) - }) { + if !raw_payload.using_encoded(|payload| signature.verify(payload, &signed)) { return Err(InvalidTransaction::BadProof.into()) } @@ -316,34 +317,32 @@ where } } +impl From> + for OpaqueExtrinsic +where + Address: Encode, + Signature: Encode, + Call: Encode, + Extra: SignedExtension, +{ + fn from(extrinsic: UncheckedExtrinsic) -> Self { + OpaqueExtrinsic::from_bytes(extrinsic.encode().as_slice()) + .expect( + "both OpaqueExtrinsic and UncheckedExtrinsic have encoding that is compatible with \ + raw Vec encoding; qed" + ) + } +} + #[cfg(test)] mod tests { use super::*; use sp_io::hashing::blake2_256; use crate::codec::{Encode, Decode}; - use crate::traits::{SignedExtension, IdentifyAccount, IdentityLookup}; - use serde::{Serialize, Deserialize}; + use crate::traits::{SignedExtension, IdentityLookup}; + use crate::testing::TestSignature as TestSig; 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 = TestSigner; - fn verify>(&self, mut msg: L, signer: &u64) -> bool { - signer == &self.0 && msg.get() == &self.1[..] - } - } - type TestAccountId = u64; type TestCall = Vec; @@ -357,7 +356,6 @@ mod tests { type AccountId = u64; type Call = (); type AdditionalSigned = (); - type DispatchInfo = (); type Pre = (); fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) } @@ -444,4 +442,13 @@ mod tests { let as_vec: Vec = Decode::decode(&mut encoded.as_slice()).unwrap(); assert_eq!(as_vec.encode(), encoded); } + + #[test] + fn conversion_to_opaque() { + let ux = Ex::new_unsigned(vec![0u8; 0]); + let encoded = ux.encode(); + let opaque: OpaqueExtrinsic = ux.into(); + let opaque_encoded = opaque.encode(); + assert_eq!(opaque_encoded, encoded); + } } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index c80971b576df2d9c6312bb3df0966ebc942cc680..02031a2df9a55c7c083facb1b9351e16b33e17f3 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Runtime Modules shared primitive types. @@ -42,7 +43,8 @@ pub use sp_core::storage::{Storage, StorageChild}; use sp_std::prelude::*; use sp_std::convert::TryFrom; -use sp_core::{crypto, ed25519, sr25519, ecdsa, hash::{H256, H512}}; +use sp_core::{crypto::{self, Public}, ed25519, sr25519, ecdsa, hash::{H256, H512}}; + use codec::{Encode, Decode}; pub mod curve; @@ -61,7 +63,7 @@ pub use crate::runtime_string::*; pub use generic::{DigestItem, Digest}; /// Re-export this since it's part of the API of this crate. -pub use sp_core::{TypeId, crypto::{key_types, KeyTypeId, CryptoType, AccountId32}}; +pub use sp_core::{TypeId, crypto::{key_types, KeyTypeId, CryptoType, CryptoTypeId, AccountId32}}; pub use sp_application_crypto::{RuntimeAppPublic, BoundToRuntimeAppPublic}; /// Re-export `RuntimeDebug`, to avoid dependency clutter. @@ -69,8 +71,8 @@ pub use sp_core::RuntimeDebug; /// Re-export top-level arithmetic stuff. pub use sp_arithmetic::{ - Perquintill, Perbill, Permill, Percent, PerU16, Rational128, Fixed64, PerThing, - traits::SaturatedConversion, + PerThing, traits::SaturatedConversion, Perquintill, Perbill, Permill, Percent, PerU16, InnerOf, + Rational128, FixedI64, FixedI128, FixedU128, FixedPointNumber, FixedPointOperand, }; /// Re-export 128 bit helpers. pub use sp_arithmetic::helpers_128bit; @@ -79,6 +81,8 @@ pub use sp_arithmetic::biguint; pub use random_number_generator::RandomNumberGenerator; +pub use either::Either; + /// An abstraction over justification for a block's validity under a consensus algorithm. /// /// Essentially a finality proof. The exact formulation will vary between consensus @@ -135,15 +139,15 @@ impl BuildStorage for sp_core::storage::Storage { storage: &mut sp_core::storage::Storage, )-> Result<(), String> { storage.top.extend(self.top.iter().map(|(k, v)| (k.clone(), v.clone()))); - for (k, other_map) in self.children.iter() { + for (k, other_map) in self.children_default.iter() { let k = k.clone(); - if let Some(map) = storage.children.get_mut(&k) { + if let Some(map) = storage.children_default.get_mut(&k) { map.data.extend(other_map.data.iter().map(|(k, v)| (k.clone(), v.clone()))); - if !map.child_info.try_update(other_map.child_info.as_ref()) { + if !map.child_info.try_update(&other_map.child_info) { return Err("Incompatible child info update".to_string()); } } else { - storage.children.insert(k, other_map.clone()); + storage.children_default.insert(k, other_map.clone()); } } Ok(()) @@ -181,18 +185,39 @@ impl From for MultiSignature { } } +impl TryFrom for ed25519::Signature { + type Error = (); + fn try_from(m: MultiSignature) -> Result { + if let MultiSignature::Ed25519(x) = m { Ok(x) } else { Err(()) } + } +} + impl From for MultiSignature { fn from(x: sr25519::Signature) -> Self { MultiSignature::Sr25519(x) } } +impl TryFrom for sr25519::Signature { + type Error = (); + fn try_from(m: MultiSignature) -> Result { + if let MultiSignature::Sr25519(x) = m { Ok(x) } else { Err(()) } + } +} + impl From for MultiSignature { fn from(x: ecdsa::Signature) -> Self { MultiSignature::Ecdsa(x) } } +impl TryFrom for ecdsa::Signature { + type Error = (); + fn try_from(m: MultiSignature) -> Result { + if let MultiSignature::Ecdsa(x) = m { Ok(x) } else { Err(()) } + } +} + impl Default for MultiSignature { fn default() -> Self { MultiSignature::Ed25519(Default::default()) @@ -299,7 +324,6 @@ impl std::fmt::Display for MultiSigner { impl Verify for MultiSignature { type Signer = MultiSigner; fn verify>(&self, mut msg: L, signer: &AccountId32) -> bool { - use sp_core::crypto::Public; match (self, signer) { (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())), @@ -324,7 +348,6 @@ pub struct AnySignature(H512); impl Verify for AnySignature { type Signer = sr25519::Public; fn verify>(&self, mut msg: L, signer: &sr25519::Public) -> bool { - use sp_core::crypto::Public; let msg = msg.get(); sr25519::Signature::try_from(self.0.as_fixed_bytes().as_ref()) .map(|s| s.verify(msg, signer)) @@ -353,16 +376,16 @@ impl From for DispatchOutcome { } } -/// This is the legacy return type of `Dispatchable`. It is still exposed for compatibilty -/// reasons. The new return type is `DispatchResultWithInfo`. -/// FRAME runtimes should use frame_support::dispatch::DispatchResult +/// This is the legacy return type of `Dispatchable`. It is still exposed for compatibility reasons. +/// The new return type is `DispatchResultWithInfo`. FRAME runtimes should use +/// `frame_support::dispatch::DispatchResult`. pub type DispatchResult = sp_std::result::Result<(), DispatchError>; /// Return type of a `Dispatchable` which contains the `DispatchResult` and additional information /// about the `Dispatchable` that is only known post dispatch. pub type DispatchResultWithInfo = sp_std::result::Result>; -/// Reason why a dispatch call failed +/// Reason why a dispatch call failed. #[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, RuntimeDebug)] #[cfg_attr(feature = "std", derive(Serialize))] pub enum DispatchError { @@ -372,11 +395,11 @@ pub enum DispatchError { CannotLookup, /// A bad origin. BadOrigin, - /// A custom error in a module + /// A custom error in a module. Module { - /// Module index, matching the metadata module index + /// Module index, matching the metadata module index. index: u8, - /// Module specific error value + /// Module specific error value. error: u8, /// Optional error message. #[codec(skip)] @@ -384,15 +407,15 @@ pub enum DispatchError { }, } -/// Result of a `Dispatchable` which contains the `DispatchResult` and additional information -/// about the `Dispatchable` that is only known post dispatch. +/// Result of a `Dispatchable` which contains the `DispatchResult` and additional information about +/// the `Dispatchable` that is only known post dispatch. #[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, RuntimeDebug)] pub struct DispatchErrorWithPostInfo where Info: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable { - /// Addditional information about the `Dispatchable` which is only known post dispatch. + /// Additional information about the `Dispatchable` which is only known post dispatch. pub post_info: Info, - /// The actual `DispatchResult` indicating whether the dispatch was succesfull. + /// The actual `DispatchResult` indicating whether the dispatch was successful. pub error: DispatchError, } @@ -515,6 +538,10 @@ pub type DispatchOutcome = Result<(), DispatchError>; /// - The extrinsic supplied a bad signature. This transaction won't become valid ever. pub type ApplyExtrinsicResult = Result; +/// Same as `ApplyExtrinsicResult` but augmented with `PostDispatchInfo` on success. +pub type ApplyExtrinsicResultWithInfo = + Result, transaction_validity::TransactionValidityError>; + /// 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( @@ -687,7 +714,14 @@ macro_rules! assert_eq_error_rate { /// 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); +pub struct OpaqueExtrinsic(Vec); + +impl OpaqueExtrinsic { + /// Convert an encoded extrinsic to an `OpaqueExtrinsic`. + pub fn from_bytes(mut bytes: &[u8]) -> Result { + OpaqueExtrinsic::decode(&mut bytes) + } +} #[cfg(feature = "std")] impl parity_util_mem::MallocSizeOf for OpaqueExtrinsic { @@ -735,6 +769,56 @@ pub fn print(print: impl traits::Printable) { print.print(); } + +/// Batching session. +/// +/// To be used in runtime only. Outside of runtime, just construct +/// `BatchVerifier` directly. +#[must_use = "`verify()` needs to be called to finish batch signature verification!"] +pub struct SignatureBatching(bool); + +impl SignatureBatching { + /// Start new batching session. + pub fn start() -> Self { + sp_io::crypto::start_batch_verify(); + SignatureBatching(false) + } + + /// Verify all signatures submitted during the batching session. + #[must_use] + pub fn verify(mut self) -> bool { + self.0 = true; + sp_io::crypto::finish_batch_verify() + } +} + +impl Drop for SignatureBatching { + fn drop(&mut self) { + // Sanity check. If user forgets to actually call `verify()`. + if !self.0 { + panic!("Signature verification has not been called before `SignatureBatching::drop`") + } + } +} + +/// Describes on what should happen with a storage transaction. +pub enum TransactionOutcome { + /// Commit the transaction. + Commit(R), + /// Rollback the transaction. + Rollback(R), +} + +impl TransactionOutcome { + /// Convert into the inner type. + pub fn into_inner(self) -> R { + match self { + Self::Commit(r) => r, + Self::Rollback(r) => r, + } + } +} + #[cfg(test)] mod tests { use super::*; @@ -782,4 +866,19 @@ mod tests { let multi_signer = MultiSigner::from(pair.public()); assert!(multi_sig.verify(msg, &multi_signer.into_account())); } + + + #[test] + #[should_panic(expected = "Signature verification has not been called")] + fn batching_still_finishes_when_not_called_directly() { + let mut ext = sp_state_machine::BasicExternalities::with_tasks_executor(); + ext.execute_with(|| { + let _batching = SignatureBatching::start(); + sp_io::crypto::sr25519_verify( + &Default::default(), + &Vec::new(), + &Default::default(), + ); + }); + } } diff --git a/primitives/runtime/src/offchain/http.rs b/primitives/runtime/src/offchain/http.rs index bbc929526b75998c181346a87eeaa3e532dc441c..12a0fcf1e5b45cb5c7cb258950ef561c11a6797a 100644 --- a/primitives/runtime/src/offchain/http.rs +++ b/primitives/runtime/src/offchain/http.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! A high-level helpers for making HTTP requests from Offchain Workers. //! diff --git a/primitives/runtime/src/offchain/mod.rs b/primitives/runtime/src/offchain/mod.rs index 9f0f949eaeb8df483df75b680fc1b872ae91ea4f..fe5844ce3004b62286968cf829e4b71793515446 100644 --- a/primitives/runtime/src/offchain/mod.rs +++ b/primitives/runtime/src/offchain/mod.rs @@ -1,22 +1,24 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// 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. //! A collection of higher lever helpers for offchain calls. pub mod http; pub mod storage; +pub mod storage_lock; pub use sp_core::offchain::*; diff --git a/primitives/runtime/src/offchain/storage.rs b/primitives/runtime/src/offchain/storage.rs index 681bc14451e116e52c71f1f239d7ff539ded9c8e..2f62d400c0b950b326f70edae145de259eb16e7d 100644 --- a/primitives/runtime/src/offchain/storage.rs +++ b/primitives/runtime/src/offchain/storage.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! A set of storage helpers for offchain workers. @@ -49,6 +50,11 @@ impl<'a> StorageValueRef<'a> { }) } + /// Remove the associated value from the storage. + pub fn clear(&mut self) { + sp_io::offchain::local_storage_clear(self.kind, self.key) + } + /// Retrieve & decode the value from storage. /// /// Note that if you want to do some checks based on the value @@ -66,7 +72,8 @@ impl<'a> StorageValueRef<'a> { /// Function `f` should return a new value that we should attempt to write to storage. /// This function returns: /// 1. `Ok(Ok(T))` in case the value has been successfully set. - /// 2. `Ok(Err(T))` in case the value was returned, but it couldn't have been set. + /// 2. `Ok(Err(T))` in case the value was calculated by the passed closure `f`, + /// but it could not be stored. /// 3. `Err(_)` in case `f` returns an error. pub fn mutate(&self, f: F) -> Result, E> where T: codec::Codec, diff --git a/primitives/runtime/src/offchain/storage_lock.rs b/primitives/runtime/src/offchain/storage_lock.rs new file mode 100644 index 0000000000000000000000000000000000000000..9d4e671db6ea18ac90a1c8f90194ccf8c4d611dd --- /dev/null +++ b/primitives/runtime/src/offchain/storage_lock.rs @@ -0,0 +1,593 @@ +// Copyright 2019-2020 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 . + +//! # Off-chain Storage Lock +//! +//! A storage-based lock with a defined expiry time. +//! +//! The lock is using Local Storage and allows synchronizing access to critical +//! section of your code for concurrently running Off-chain Workers. Usage of +//! `PERSISTENT` variant of the storage persists the lock value across a full node +//! restart or re-orgs. +//! +//! A use case for the lock is to make sure that a particular section of the +//! code is only run by one Off-chain Worker at a time. This may include +//! performing a side-effect (i.e. an HTTP call) or alteration of single or +//! multiple Local Storage entries. +//! +//! One use case would be collective updates of multiple data items or append / +//! remove of i.e. sets, vectors which are stored in the off-chain storage DB. +//! +//! ## Example: +//! +//! ```rust +//! # use codec::{Decode, Encode, Codec}; +//! // in your off-chain worker code +//! use sp_runtime::offchain::{ +//! storage::StorageValueRef, +//! storage_lock::{StorageLock, Time}, +//! }; +//! +//! fn append_to_in_storage_vec<'a, T>(key: &'a [u8], _: T) where T: Codec { +//! // `access::lock` defines the storage entry which is used for +//! // persisting the lock in the underlying database. +//! // The entry name _must_ be unique and can be interpreted as a +//! // unique mutex instance reference tag. +//! let mut lock = StorageLock::